index.vue 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  1. <template>
  2. <cwg-page-wrapper class="create-page" :isHeaderFixed="true">
  3. <!-- <cwg-header :title="t('Home.page_ib.item1')" :showBack="false" />-->
  4. <uni-loading v-if="loading" />
  5. <uni-row v-else class="demo-uni-row uni-row1" :gutter="20">
  6. <uni-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  7. <view class="border-0 card-header ">
  8. <view class="d-flex flex-wrap gap-3 align-items-center justify-content-between mb-3" style="width: 100%;">
  9. <view class="mb-0 h3" style="align-self: flex-start">{{ t('Home.msg.Ib') }}</view>
  10. <button hover-class="" type="button" class="btn btn-secondary btn-shadow waves-effect"
  11. @click="LinkActivity1">
  12. <cwg-icon name="crm-share-nodes" :size="16" color="#fff" />{{ t('Ib.Index.CreateLink') }}</button>
  13. </view>
  14. </view>
  15. </uni-col>
  16. <uni-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="uni-col-left">
  17. <uni-row class="dashboard-container">
  18. <!-- 余额卡片 操作代码隐藏了,-->
  19. <!-- <cwg-dropdown :menu-list="menuList" @menuClick="handleMenuClick">-->
  20. <!-- <view class="pc-header-btn">-->
  21. <!-- <cwg-icon name="crm-ellipsis" :size="24" color="#000" />-->
  22. <!-- </view>-->
  23. <!-- </cwg-dropdown>-->
  24. <uni-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
  25. <view class="card position-relative">
  26. <view class="card-body d-flex gap-3 align-items-center">
  27. <view class="clearfix pe-2 text-warning">
  28. <image src="/static/images/dollar.png" alt="dollar" mode="aspectFill" class="img-fluid" />
  29. </view>
  30. <view class="clearfix">
  31. <view class="mb-2">{{ t('news_add_field.Label.Balance') }}</view>
  32. <view class="mb-0 fw-bold ">${{ numberFormat(ibData.balance) }}<text
  33. class="badge bg-danger-subtle text-danger">{{ t('Ib.Index.TotalRevenue') }}:
  34. ${{ numberFormat(ibData.all) }}</text></view>
  35. </view>
  36. </view>
  37. </view>
  38. </uni-col>
  39. <!-- 开户链接 -->
  40. <!-- <view class="card partner-card">-->
  41. <!-- <view class="card-header">-->
  42. <!-- <view class="header-left">-->
  43. <!-- <cwg-icon name="crm-share-nodes" :size="24" color="#000" />-->
  44. <!-- <text class="header-title">{{ t('Ib.Index.Link') }}</text>-->
  45. <!-- </view>-->
  46. <!-- </view>-->
  47. <!-- <view class="partner-content">-->
  48. <!-- <view class="link-area">-->
  49. <!-- <button hover-class="" class="link-btn" @click="LinkActivity1">-->
  50. <!-- {{ t('Ib.Index.CreateLink') }}-->
  51. <!-- </button>-->
  52. <!-- &lt;!&ndash; <button hover-class="" class="link-btn" @click="LinkActivity">&ndash;&gt;-->
  53. <!-- &lt;!&ndash; {{ t('Ib.Index.CreateLinkActivity') }}&ndash;&gt;-->
  54. <!-- &lt;!&ndash; </button>&ndash;&gt;-->
  55. <!-- </view>-->
  56. <!-- </view>-->
  57. <!-- </view>-->
  58. <uni-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
  59. <view class="card position-relative stat-card-clickable cursor-pointer" @click="toCustomManagement"
  60. :data-tooltip="t('vu.tooltip.t4', { pageName: t('Home.page_ib.item2') })" data-placement="top">
  61. <view class="card-body d-flex gap-3 align-items-center">
  62. <view class="clearfix pe-2 text-warning">
  63. <cwg-icon name="crm-user" :size="50" color="#FDBB1F" />
  64. </view>
  65. <view class="clearfix">
  66. <view class="mb-2">{{ t('Ib.Index.NameCustom') }}-{{ t('Ib.Index.Custom') }}</view>
  67. <view class="mb-0 fw-bold">{{ ibData.customAmount || '0' }}</view>
  68. </view>
  69. </view>
  70. </view>
  71. </uni-col>
  72. <uni-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
  73. <view class="card position-relative stat-card-clickable cursor-pointer" @click="toIbManagement"
  74. :data-tooltip="t('vu.tooltip.t4', { pageName: t('Ib.Custom.Manage2') })" data-placement="top">
  75. <view class="card-body d-flex gap-3 align-items-center">
  76. <view class="clearfix pe-2 text-warning">
  77. <cwg-icon name="crm-ib" :size="50" color="#FDBB1F" />
  78. </view>
  79. <view class="clearfix">
  80. <view class="mb-2">{{ t('Ib.Index.NameCustom') }}-{{ t('Ib.Index.Agent') }}</view>
  81. <view class="mb-0 fw-bold">{{ ibData.ibAmount || '0' }}</view>
  82. </view>
  83. </view>
  84. </view>
  85. </uni-col>
  86. <!-- 名下客户 -->
  87. <!-- <view class="card custom-card">-->
  88. <!-- <view class="card-header">-->
  89. <!-- <view class="header-left">-->
  90. <!-- <cwg-icon name="crm-custom" :size="24" color="#333" />-->
  91. <!-- <text class="header-title">{{ t('Ib.Index.NameCustom') }}</text>-->
  92. <!-- </view>-->
  93. <!-- </view>-->
  94. <!-- <view class="custom-content">-->
  95. <!-- <view class="con" @click="toCustomManagement">-->
  96. <!-- <view class="num">-->
  97. <!-- {{ ibData.customAmount || '0' }}-->
  98. <!-- </view>-->
  99. <!-- <view class="des">-->
  100. <!-- {{ t('Ib.Index.Custom') }}-->
  101. <!-- </view>-->
  102. <!-- </view>-->
  103. <!-- <view class="con" @click="toIbManagement">-->
  104. <!-- <view class="num">-->
  105. <!-- {{ ibData.ibAmount || '0' }}-->
  106. <!-- </view>-->
  107. <!-- <view class="des">-->
  108. <!-- {{ t('Ib.Index.Agent') }}-->
  109. <!-- </view>-->
  110. <!-- </view>-->
  111. <!-- </view>-->
  112. <!-- </view>-->
  113. <!-- 归属推荐码 -->
  114. <!-- <view class="card code-card">
  115. <view class="card-header">
  116. <view class="header-left">
  117. <text class="header-title">{{ t('Tips.AttributionCode') }}</text>
  118. <uni-tooltip placement="top">
  119. <text class="icon-tip">?</text>
  120. <template v-slot:content>
  121. <view style="width: 100px;">
  122. {{ t('Tips.tips') }}
  123. </view>
  124. </template>
  125. </uni-tooltip>
  126. </view>
  127. </view>
  128. <view class="code-content">
  129. <uni-easyinput class="code-input" :disabled="true" v-model="getInfoId" :clearable="false"></uni-easyinput>
  130. <button hover-class="" class="link-btn">{{ t('Ib.Index.Copy') }}</button>
  131. </view>
  132. </view>-->
  133. </uni-row>
  134. </uni-col>
  135. <uni-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="uni-col-right">
  136. <view class="card">
  137. <view class="card-body">
  138. <view class="d-flex flex-wrap gap-3 align-items-center justify-content-between mb-3 ">
  139. <view class="header-left">
  140. <text class="header-title">{{ t('Ib.Index.MAMList') }}</text>
  141. </view>
  142. <view class="header-right" v-if="showAddMamAccount">
  143. <cwg-droplist :menu-list="addMamAccountMenus" @menuClick="handleAddMamAccountMenuClick">
  144. <button hover-class="" type="button" class="btn btn-danger btn-shadow waves-effect add-mam-btn">
  145. <cwg-icon name="icon_add" :size="16" color="#fff" />{{ t('Custom.Index.AddAccount') }}</button>
  146. </cwg-droplist>
  147. </view>
  148. </view>
  149. <cwg-tabel ref="mamTableRef" :columns="mamColumns" :mobilePrimaryFields="mamMobilePrimaryFields"
  150. :queryParams="mamSearch" :api="mamListApi" :show-operation="false" :showPagination="true">
  151. <template #mamAccount="{ row }">
  152. <view v-if="row.type == 1 || row.type == 2">
  153. <text>{{ row.login || '-' }}</text>
  154. </view>
  155. <view v-else-if="row.type == 3">
  156. <view class="mam-line">
  157. <text>{{ t('Ib.PammManager.ownerId') }}:</text>
  158. <text>{{ row.ownerId || '--' }}</text>
  159. </view>
  160. <view class="mam-line">
  161. <text>{{ t('Ib.PammManager.accountId') }}:</text>
  162. <text>{{ row.accountId || '--' }}</text>
  163. </view>
  164. <view class="mam-line">
  165. <text>{{ t('Ib.PammManager.percent') }}:</text>
  166. <text>{{ (row.percent ?? '--') + '%' }}</text>
  167. </view>
  168. </view>
  169. </template>
  170. <template #mamType="{ row }">
  171. <text>{{ formatMamType(row.type) }}</text>
  172. </template>
  173. <template #loginType="{ row }">
  174. <text>{{ formatAccountType(row.accountType) }}</text>
  175. </template>
  176. <template #leverage="{ row }">
  177. <text>{{ row.leverage ? '1:' + row.leverage : '-' }}</text>
  178. </template>
  179. <template #balance="{ row }">
  180. <text>{{ numberFormat(row.balance || 0) }}</text>
  181. </template>
  182. <template #equity="{ row }">
  183. <text>{{ numberFormat(row.equity || 0) }}</text>
  184. </template>
  185. <template #operation="{ row }">
  186. <view class="mam-ops">
  187. <view v-if="row.type == 1 || row.type == 2" class="mam-op" @click.stop="toSettings(row)">
  188. <text>{{ t('Ib.Index.Settings') }}</text>
  189. </view>
  190. <view v-if="row.type == 3" class="mam-op" @click.stop="toSettings(row)">
  191. <text>{{ t('Ib.PammManager.btn1') }}</text>
  192. </view>
  193. <view v-if="row.type == 3" class="mam-op" @click.stop="toDialogPercent(row)">
  194. <text>{{ t('Ib.PammManager.percent') }}</text>
  195. </view>
  196. <view class="mam-op" @click.stop="toDialogSubs(row)">
  197. <text>{{ t('blockchain.item1') }}</text>
  198. </view>
  199. </view>
  200. </template>
  201. </cwg-tabel>
  202. </view>
  203. </view>
  204. </uni-col>
  205. </uni-row>
  206. <!-- 调整收益分成弹窗 -->
  207. <cwg-popup :visible="dialogPercent" :title="t('Ib.PammManager.percent')" @close="closeDialogPercent"
  208. @confirm="applyPercent">
  209. <view class="dia-content custom-dialog-content">
  210. <uni-forms :model="dialogPercentData" label-width="150" label-position="left">
  211. <uni-forms-item :label="t('Ib.PammManager.ownerId') + ':'">
  212. <text class="info-text">{{ dialogPercentData.oldOwnerId || '--' }}</text>
  213. </uni-forms-item>
  214. <uni-forms-item :label="t('Ib.PammManager.accountId') + ':'">
  215. <text class="info-text">{{ dialogPercentData.oldAccountId || '--' }}</text>
  216. </uni-forms-item>
  217. <uni-forms-item :label="t('Ib.PammManager.percent') + ':'">
  218. <text class="info-text">{{ dialogPercentData.oldPercent }}%</text>
  219. </uni-forms-item>
  220. <uni-forms-item :label="t('Ib.PammManager.percentNew') + ':'" name="percent" required>
  221. <uni-easyinput v-model="dialogPercentData.percent" :placeholder="t('placeholder.input')" />
  222. </uni-forms-item>
  223. </uni-forms>
  224. </view>
  225. </cwg-popup>
  226. <!-- 子账户数量弹窗 -->
  227. <cwg-popup v-model:visible="isSubsDialogVisible" type="center" :title="t('blockchain.item1')" :showFooters="true"
  228. @close="isSubsDialogVisible = false" @confirm="isSubsDialogVisible = false">
  229. <view class="dia-content custom-dialog-content" style="padding: 10px 0; max-height: 50vh; overflow-y: auto;">
  230. <cwg-tabel :data="agentId_level" :columns="[
  231. { label: t('Ib.Index.TradingAccount'), prop: 'login', align: 'center' },
  232. { label: t('Ib.Index.Balance'), prop: 'balance', align: 'center' }
  233. ]" :showPagination="false" :showOperation="false" style="margin-bottom: 20px" />
  234. </view>
  235. </cwg-popup>
  236. </cwg-page-wrapper>
  237. </template>
  238. <script setup>
  239. import { ref, computed, watch, onMounted, nextTick } from 'vue'
  240. import { useI18n } from 'vue-i18n'
  241. import useRouter from '@/hooks/useRouter'
  242. import { ibApi } from '@/service/ib'
  243. import config from '@/config/index'
  244. import useUserStore from '@/stores/use-user-store'
  245. import { useStorage } from '@/hooks/useStorage'
  246. import QrCode from '@/components/QrCode.vue'
  247. import { useFilters } from '@/composables/useFilters'
  248. import { isAfterJuly28 } from '@/utils/dateUtils'
  249. import useGlobalStore from '@/stores/use-global-store'
  250. const { t } = useI18n()
  251. const loading = ref(false)
  252. const router = useRouter()
  253. const { Code } = config
  254. const { userInfo } = useUserStore()
  255. const { numberFormat } = useFilters()
  256. const globalStore = useGlobalStore()
  257. // 数据
  258. const isDark = computed(() => globalStore.theme === 'dark')
  259. const ibData = ref({
  260. customAmount: 0,
  261. ibAmount: 0,
  262. },
  263. )
  264. const selectedSpreadId = ref('')
  265. const spreadList = ref([])
  266. const excludeShowLoginTypes = ref([])
  267. const pammManagerValid = ref()
  268. const dialogPercent = ref(false)
  269. const dialogPercentData = ref({
  270. oldPercent: '',
  271. mamListId: '',
  272. oldOwnerId: '',
  273. oldAccountId: '',
  274. percent: '',
  275. })
  276. const isActionLoading = ref(false)
  277. const menuList = computed(() => [
  278. { label: t('Custom.Index.Withdrawals'), type: 1 },
  279. { label: t('Home.page_ib.item4'), type: 2 },
  280. { label: t('Ib.Transfer.CommissionIssue'), type: 3 },
  281. ])
  282. const excludeList = ref([])
  283. const excludeLists = ref([
  284. { text: t('AccountType.SeniorAccount'), value: '2' },
  285. // {text: t('AccountType.SeniorAccount'),value: '3'},
  286. { text: t('AccountType.StandardAccount'), value: '7' },
  287. { text: t('AccountType.CentAccount'), value: '8' },
  288. ])
  289. const link = ref('')
  290. const loginTypes = ref('')
  291. const ibInvalid = ref('B0')
  292. const qrCode = ref(null)
  293. const qrCode1 = ref(null)
  294. // 语言
  295. const lang = useStorage('lang')
  296. const flag = ref(false)
  297. const agentLinkList = ref([])
  298. const activityLing = ref('')
  299. const linkActivity = ref('')
  300. const commission = ref('')
  301. const linkActivityPopup = ref(null)
  302. // 开户链接
  303. const linkPopup = ref(null)
  304. const qrSize = ref(200)
  305. const levelNum = computed(() => {
  306. return userInfo.ibInfo.levelNum
  307. })
  308. const fixedHide = computed(() => {
  309. return userInfo.ibInfo.fixedHide
  310. })
  311. const getInfoId = computed(() => {
  312. return userInfo.ibInfo.id
  313. })
  314. const balanceInt = computed(() => {
  315. return numberFormat(ibData.value?.balance || 0, true)[0]
  316. })
  317. const balanceDecimal = computed(() => {
  318. return numberFormat(ibData.value?.balance || 0, true)[1] || '00'
  319. })
  320. // 国家
  321. const country = computed(() => {
  322. console.log(userInfo.customInfo.country, '2')
  323. return userInfo.customInfo.country
  324. })
  325. // 修改多选
  326. const handleChange = (val) => {
  327. excludeShowLoginTypes.value = val
  328. }
  329. const isAfterJuly7 = () => {
  330. const currentDate = new Date()
  331. const july7 = new Date(currentDate.getFullYear(), 6, 7) // 月份从0开始,6表示7月
  332. return currentDate >= july7
  333. }
  334. const getValidAccountTypes = (selectedExcludeValues, selectedSpreadId) => {
  335. const spread = spreadList.value.find(
  336. (item) => item.id === selectedSpreadId,
  337. )
  338. let data = {
  339. hide: '',
  340. commission: '',
  341. excludeShowLoginTypes: [],
  342. }
  343. if (!spread) return data
  344. const validValues = selectedExcludeValues.filter((value) =>
  345. spread.loginTypes.includes(value),
  346. )
  347. const invalidValues = selectedExcludeValues.filter(
  348. (value) => !spread.loginTypes.includes(value),
  349. )
  350. const invalidLabels = excludeList.value
  351. .filter((item) => invalidValues.includes(item.value))
  352. .map((item) => item.label)
  353. const excludeTypes = excludeLists.value
  354. .filter((item) => !validValues.includes(item.value))
  355. .map((item) => item.value)
  356. loginTypes.value = invalidLabels.join('、')
  357. return {
  358. hide: spread.hide,
  359. commission: spread.comPoint,
  360. excludeShowLoginTypes: excludeTypes,
  361. invalidLabels,
  362. invalidValues,
  363. }
  364. }
  365. const downloadQrCode = (type = 0) => {
  366. if (type === 1) {
  367. qrCode1.value.download()
  368. } else {
  369. qrCode.value.download()
  370. }
  371. }
  372. // 复制
  373. const CopyShareLink = (value) => {
  374. uni.setClipboardData({ data: value })
  375. }
  376. const getLink1 = async () => {
  377. console.log(excludeShowLoginTypes.value, 2)
  378. if (excludeShowLoginTypes.value.length == 0) {
  379. uni.showToast({
  380. title: t('Ib.Index.Spread5'), icon: 'none',
  381. })
  382. link.value = ''
  383. return
  384. }
  385. if (!selectedSpreadId.value.length) {
  386. uni.showToast({
  387. title: t('Ib.Index.Spread4'), icon: 'none',
  388. })
  389. link.value = ''
  390. return
  391. }
  392. const validList = getValidAccountTypes(
  393. excludeShowLoginTypes.value,
  394. selectedSpreadId.value,
  395. )
  396. if (validList.invalidLabels.length > 0) {
  397. return new Promise((resolve) => {
  398. uni.showModal({
  399. title: t('Msg.SystemPrompt'),
  400. content: `${t('Ib.Index.Spread1')}${loginTypes.value
  401. }${t('')}`,
  402. confirmText: t('Btn.Confirm'),
  403. cancelText: t('Btn.Cancel'),
  404. success: async (res) => {
  405. if (res.confirm) {
  406. const res = await ibApi.customLink(validList)
  407. if (res.code === Code.StatusOK) {
  408. uni.showToast({
  409. title: res.msg,
  410. icon: 'none',
  411. })
  412. resolve(res.data)
  413. } else {
  414. uni.showToast({
  415. title: res.msg,
  416. icon: 'none',
  417. })
  418. resolve('')
  419. }
  420. }
  421. },
  422. fail: () => resolve(''),
  423. })
  424. })
  425. } else {
  426. const res = await ibApi.customLink(validList)
  427. if (res.code === Code.StatusOK) {
  428. uni.showToast({
  429. title: res.msg,
  430. icon: 'none',
  431. })
  432. return res.data
  433. } else {
  434. uni.showToast({
  435. title: res.msg,
  436. icon: 'none',
  437. })
  438. return ''
  439. }
  440. }
  441. }
  442. const CreateLink = async () => {
  443. const linkValue = await getLink1()
  444. if (!linkValue) return
  445. link.value = `${Host80}/#/signup/${getInfoId.value}/${linkValue}/${ibInvalid.value}`
  446. }
  447. const loginTypeList = async () => {
  448. const res = await ibApi.loginTypeList(
  449. {
  450. page: {
  451. current: 1,
  452. row: 100,
  453. },
  454. },
  455. )
  456. if (res.code === Code.StatusOK) {
  457. spreadList.value = res.data
  458. } else {
  459. uni.showToast({ title: res.msg, icon: 'none' })
  460. }
  461. }
  462. const getAgentAccountSetting = async () => {
  463. const { agentAccountSetting = '' } = userInfo.ibInfo ?? {}
  464. if (agentAccountSetting === 0) {
  465. const excludeValues = userInfo.customInfo.excludeShowLoginTypes
  466. try {
  467. excludeList.value = excludeLists.value.filter(
  468. (item) => !excludeValues.includes(item.value),
  469. )
  470. excludeShowLoginTypes.value = []
  471. } catch (e) {
  472. excludeShowLoginTypes.value = []
  473. excludeList.value = excludeLists.value
  474. }
  475. } else {
  476. excludeShowLoginTypes.value = []
  477. excludeList.value = excludeLists.value
  478. }
  479. }
  480. // 生成开户链接
  481. const LinkActivity1 = async () => {
  482. // 跳转到开户链接页面
  483. uni.navigateTo({
  484. url: '/pages/ib/linkList',
  485. })
  486. }
  487. const handleMenuClick = ({ value }) => {
  488. console.log(value.type)
  489. if (value.type === 1) {
  490. toWithdraw()
  491. } else if (value.type === 2) {
  492. toTransfer()
  493. } else {
  494. toTransfer(2)
  495. }
  496. }
  497. const toWithdraw = () => {
  498. router.push({
  499. path: '/pages/ib/withdraw-select',
  500. },
  501. )
  502. }
  503. const toTransfer = (tab = 1) => {
  504. router.push({
  505. path: '/pages/ib/transfer',
  506. query: { tab },
  507. },
  508. )
  509. }
  510. const toCustomManagement = () => {
  511. router.push({
  512. path: '/pages/ib/customer',
  513. query: { type: 3 },
  514. },
  515. )
  516. }
  517. const toIbManagement = () => {
  518. router.push({
  519. path: '/pages/ib/subsList',
  520. query: { type: 2 },
  521. },
  522. )
  523. }
  524. const getIbData = async () => {
  525. const res = await ibApi.IbData()
  526. if (res.code === Code.StatusOK) {
  527. if (res.data != null)
  528. ibData.value = res.data
  529. } else {
  530. uni.showToast({ title: res.msg, icon: 'none' })
  531. }
  532. }
  533. const getPammManagerValid = async () => {
  534. // 没有ib状态不调用
  535. if (!userInfo.ibInfo) {
  536. return
  537. }
  538. const res = await ibApi.mamApplyPammManagerValid()
  539. if (res.code === Code.StatusOK) {
  540. if (res.data != null)
  541. pammManagerValid.value = res.data
  542. } else {
  543. uni.showToast({ title: res.msg, icon: 'none' })
  544. }
  545. }
  546. const mamTableRef = ref(null)
  547. const mamSearch = ref({})
  548. const mamListApi = computed(() => {
  549. // 模拟,没有ib不调用接口
  550. if (!userInfo.ibInfo) {
  551. return (params) => new Promise(resolve => {
  552. resolve({
  553. code: 200,
  554. data: [],
  555. })
  556. })
  557. }
  558. return (params) => ibApi.MamList(params)
  559. })
  560. const showAddMamAccount = computed(() => {
  561. return !!(
  562. pammManagerValid.value?.mamValid ||
  563. pammManagerValid.value?.pammValid ||
  564. pammManagerValid.value?.pammManagerValid
  565. )
  566. })
  567. const addMamAccountMenus = computed(() => {
  568. const list = []
  569. if (pammManagerValid.value?.mamValid) list.push({ label: 'MAM', type: 1 })
  570. if (pammManagerValid.value?.pammValid) list.push({ label: 'Money Manager', type: 2 })
  571. if (pammManagerValid.value?.pammManagerValid) list.push({ label: t('Ib.PammManager.title'), type: 3 })
  572. return list
  573. })
  574. const handleAddMamAccountMenuClick = ({ value }) => {
  575. toNewAccount(value.type)
  576. }
  577. const formatMamType = (type) => {
  578. if (type == 1) return 'MAM'
  579. if (type == 2) return 'Money Manager'
  580. if (type == 3) return t('Ib.PammManager.title1')
  581. return '--'
  582. }
  583. const formatAccountType = (accountType) => {
  584. if (accountType == 1) return t('AccountType.ClassicAccount')
  585. if (accountType == 2) return t('AccountType.SeniorAccount')
  586. if (accountType == 3 && !isAfterJuly28()) return t('AccountType.AgencyAccount')
  587. if (accountType == 5) return t('AccountType.SpeedAccount')
  588. if (accountType == 6) return t('AccountType.SpeedAccount')
  589. if (accountType == 7) return t('AccountType.StandardAccount')
  590. if (accountType == 8) return t('AccountType.CentAccount')
  591. return '--'
  592. }
  593. const mamColumns = computed(() => [
  594. { prop: 'mamAccount', label: t('Ib.Index.MAMAccount'), align: 'center', slot: 'mamAccount' },
  595. { prop: 'type', label: t('Label.Type'), align: 'center', slot: 'mamType' },
  596. { prop: 'accountType', label: t('Ib.Index.LoginType'), align: 'center', slot: 'loginType' },
  597. { prop: 'platform', label: t('Ib.Index.Platform'), align: 'center' },
  598. { prop: 'currency', label: t('Ib.Index.Currency'), align: 'center' },
  599. { prop: 'leverage', label: t('Ib.Index.Leverage'), align: 'center', slot: 'leverage' },
  600. { prop: 'balance', label: t('Ib.Index.Balance'), align: 'center', slot: 'balance' },
  601. { prop: 'equity', label: t('Ib.Index.Equity'), align: 'center', slot: 'equity' },
  602. { prop: 'commission', label: t('Ib.Index.Commission'), align: 'center' },
  603. { prop: 'operation', label: t('Ib.Index.Operation'), align: 'center', slot: 'operation' },
  604. ])
  605. const mamMobilePrimaryFields = computed(() => [
  606. { prop: 'mamAccount', width: 120, label: t('Ib.Index.MAMAccount'), align: 'center', slot: 'mamAccount' },
  607. { prop: 'type', label: t('Label.Type'), align: 'center', slot: 'mamType' },
  608. { prop: 'platform', label: t('Ib.Index.Platform'), align: 'center' },
  609. { prop: 'more', type: 'more', width: 20, align: 'right' },
  610. ])
  611. const toNewAccount = (type) => {
  612. if (type == 3) {
  613. router.push({
  614. path: '/pages/ib/openPammManager',
  615. query: {
  616. type: type,
  617. },
  618. })
  619. } else {
  620. router.push({
  621. path: '/pages/ib/openAccount',
  622. query: {
  623. type: type,
  624. },
  625. })
  626. }
  627. }
  628. const toSettings = (row) => {
  629. router.push({
  630. path: '/pages/ib/settingPammManager',
  631. query: { login: row.accountId, id: row.id },
  632. })
  633. }
  634. const toDialogPercent = (row) => {
  635. dialogPercentData.value.oldPercent = row.percent
  636. dialogPercentData.value.mamListId = row.id
  637. dialogPercentData.value.oldOwnerId = row.ownerId
  638. dialogPercentData.value.oldAccountId = row.accountId
  639. dialogPercentData.value.percent = ''
  640. dialogPercent.value = true
  641. }
  642. const closeDialogPercent = () => {
  643. dialogPercent.value = false
  644. }
  645. const applyPercent = async () => {
  646. if (isActionLoading.value) return
  647. if (!dialogPercentData.value.percent) {
  648. uni.showToast({ title: t('placeholder.input'), icon: 'none' })
  649. return
  650. }
  651. isActionLoading.value = true
  652. try {
  653. const res = await ibApi.applyPercent({
  654. mamListId: dialogPercentData.value.mamListId,
  655. percent: dialogPercentData.value.percent,
  656. })
  657. if (res.code === Code.StatusOK) {
  658. uni.showToast({ title: res.msg, icon: 'success' })
  659. dialogPercent.value = false
  660. // Refresh MAM list
  661. mamTableRef.value?.refreshTable()
  662. } else {
  663. uni.showToast({ title: res.msg, icon: 'none' })
  664. }
  665. } catch (error) {
  666. uni.showToast({ title: t('Msg.Fail'), icon: 'none' })
  667. } finally {
  668. isActionLoading.value = false
  669. }
  670. }
  671. const isSubsDialogVisible = ref(false)
  672. const agentId_level = ref([])
  673. const toDialogSubs = async (row) => {
  674. agentId_level.value = []
  675. try {
  676. const res = await ibApi.pammListSubs({ id: row.id })
  677. if (res.code === Code.StatusOK) {
  678. agentId_level.value = res.data || []
  679. } else {
  680. uni.showToast({ title: res.msg, icon: 'none' })
  681. }
  682. } catch (e) {
  683. // uni.showToast({ title: t('Msg.Fail'), icon: 'none' })
  684. }
  685. nextTick(() => {
  686. isSubsDialogVisible.value = true
  687. })
  688. }
  689. onMounted(async () => {
  690. let a = numberFormat(80.7)
  691. console.log(a)
  692. loading.value = true
  693. // 初始化数据
  694. await getIbData()
  695. await getPammManagerValid()
  696. loading.value = false
  697. })
  698. </script>
  699. <style lang="scss" scoped>
  700. @import "@/uni.scss";
  701. .clearfix {
  702. .fw-bold {
  703. color: var(--bs-emphasis-color);
  704. }
  705. }
  706. .demo-uni-row {
  707. display: flex;
  708. flex-wrap: wrap;
  709. align-items: stretch;
  710. margin: 0 auto !important;
  711. }
  712. .uni-col-left {
  713. display: flex;
  714. flex-direction: column;
  715. }
  716. .uni-col-right {
  717. display: flex;
  718. flex-direction: column;
  719. }
  720. .dashboard-container {
  721. min-height: 10vh;
  722. box-sizing: border-box;
  723. height: 100%;
  724. }
  725. .mam-card {
  726. flex: 1;
  727. display: flex;
  728. flex-direction: column;
  729. }
  730. /* 卡片通用样式 */
  731. .card {
  732. border-radius: px2rpx(8);
  733. box-shadow: 0 px2rpx(2) px2rpx(8) rgba(0, 0, 0, 0.06);
  734. //background: var(--bs-body-bg);
  735. //color: var(--bs-emphasis-color);
  736. //padding: px2rpx(12) px2rpx(16);
  737. //border-radius: 4rpx;
  738. flex: 1;
  739. margin: 0 px2rpx(5) px2rpx(10);
  740. //box-shadow: 0 px2rpx(4) px2rpx(12) rgba(0, 0, 0, 0.2);
  741. display: flex;
  742. flex-direction: column;
  743. min-height: px2rpx(110);
  744. }
  745. .stat-card-clickable {
  746. cursor: pointer;
  747. &:hover {
  748. box-shadow: 0 px2rpx(4) px2rpx(12) rgba(0, 0, 0, 0.1);
  749. }
  750. }
  751. .dashboard-container .card-body {
  752. flex: 1;
  753. display: flex;
  754. align-items: center;
  755. padding: px2rpx(16);
  756. }
  757. .custom-dialog-content {
  758. padding: px2rpx(20);
  759. .info-text {
  760. color: var(--bs-heading-color);
  761. font-size: px2rpx(14);
  762. line-height: px2rpx(36);
  763. }
  764. }
  765. .card-header {
  766. display: flex;
  767. justify-content: space-between;
  768. align-items: center;
  769. margin-bottom: px2rpx(12);
  770. .btn {
  771. margin: 0;
  772. display: flex;
  773. align-items: center;
  774. }
  775. }
  776. .header-left {
  777. display: flex;
  778. align-items: center;
  779. gap: 12rpx;
  780. }
  781. .header-title {
  782. font-size: px2rpx(24.5);
  783. font-weight: 600;
  784. color: var(--bs-emphasis-color);
  785. }
  786. .header-right {
  787. display: flex;
  788. align-items: center;
  789. @media screen and (max-width: 991px) {
  790. :deep(.cwg-dropdown-menu-container) {
  791. right: px2rpx(-20) !important;
  792. //max-width: px2rpx(400);
  793. }
  794. }
  795. }
  796. .action-btn {
  797. background: #ffde02;
  798. border: none;
  799. border-radius: 50%;
  800. width: px2rpx(32);
  801. height: px2rpx(32);
  802. display: flex;
  803. align-items: center;
  804. justify-content: center;
  805. padding: 0;
  806. margin: 0;
  807. &:after {
  808. border: none;
  809. }
  810. }
  811. /* 余额区域 */
  812. .balance-content {
  813. display: flex;
  814. flex-direction: column;
  815. align-items: center;
  816. gap: 16rpx;
  817. }
  818. .balance-main {
  819. display: flex;
  820. align-items: baseline;
  821. flex-wrap: wrap;
  822. }
  823. .balance-amount {
  824. font-size: px2rpx(20);
  825. font-weight: 700;
  826. line-height: 1;
  827. }
  828. .balance-decimal {
  829. font-size: px2rpx(16);
  830. font-weight: 500;
  831. line-height: 1;
  832. }
  833. .balance-currency {
  834. font-size: px2rpx(16);
  835. font-weight: 500;
  836. }
  837. .total-earnings {
  838. display: flex;
  839. align-items: center;
  840. gap: 5px;
  841. color: var(--bs-emphasis-color);
  842. font-size: px2rpx(12);
  843. }
  844. .total-value {
  845. align-self: flex-end;
  846. }
  847. /* 合作伙伴卡片 */
  848. .partner-content {
  849. display: flex;
  850. flex-direction: column;
  851. gap: 12px;
  852. }
  853. .link-area {
  854. display: flex;
  855. flex-wrap: wrap;
  856. justify-content: space-around;
  857. align-items: center;
  858. gap: 12px;
  859. }
  860. .link-btn {
  861. height: px2rpx(32);
  862. background-color: rgb(108, 133, 149);
  863. line-height: px2rpx(32);
  864. color: var(--color-white);
  865. border-radius: px2rpx(16);
  866. font-size: px2rpx(14);
  867. margin: 0;
  868. }
  869. .code-content {
  870. display: flex;
  871. justify-content: center;
  872. }
  873. .code-input {
  874. width: 50%;
  875. max-width: px2rpx(178);
  876. margin-right: px2rpx(20);
  877. }
  878. .custom-content {
  879. display: flex;
  880. justify-content: space-around;
  881. flex-wrap: wrap;
  882. .con {
  883. cursor: pointer;
  884. text-align: center;
  885. font-size: px2rpx(16);
  886. margin: 5px;
  887. }
  888. .num {
  889. font-weight: bold;
  890. }
  891. .des {
  892. margin-top: px2rpx(5);
  893. }
  894. }
  895. .dia-content {
  896. padding: 20rpx;
  897. }
  898. .content {
  899. display: flex;
  900. flex-direction: column;
  901. gap: 20rpx;
  902. }
  903. .label {
  904. font-weight: 500;
  905. margin-bottom: 8rpx;
  906. }
  907. .btn {
  908. margin-top: 16rpx;
  909. text-align: center;
  910. }
  911. .crm-cursor {
  912. cursor: pointer;
  913. }
  914. .link {
  915. display: flex;
  916. margin-top: 20rpx;
  917. .btn {
  918. display: flex;
  919. align-items: center;
  920. justify-content: center;
  921. height: px2rpx(35);
  922. margin: 0 px2rpx(10);
  923. }
  924. }
  925. .qrCode {
  926. display: flex;
  927. flex-direction: column;
  928. align-items: center;
  929. gap: 16rpx;
  930. }
  931. .add-mam-btn {
  932. display: flex;
  933. justify-content: center;
  934. }
  935. .mam-line {
  936. display: flex;
  937. flex-direction: column;
  938. justify-content: center;
  939. gap: 6rpx;
  940. line-height: 1.5;
  941. }
  942. .mam-ops {
  943. display: flex;
  944. flex-wrap: wrap;
  945. justify-content: center;
  946. cursor: pointer;
  947. gap: 10rpx;
  948. }
  949. .mam-op {
  950. color: #2b5aed;
  951. font-size: px2rpx(12);
  952. line-height: 1.4;
  953. }
  954. .img-fluid {
  955. width: px2rpx(50);
  956. height: px2rpx(50);
  957. }
  958. </style>