AccountCard.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. <template>
  2. <view class="col-lg-4 col-md-6">
  3. <view class="card">
  4. <view class="card-header d-flex align-items-center justify-content-between border-0 pb-2 p-3">
  5. <text v-if="!isDel" class="badge bg-success-subtle text-success">正常</text>
  6. <text v-if="isDel" class="badge bg-danger-subtle text-danger">已删除</text>
  7. <view class="clearfix">
  8. <view class="btn-group">
  9. <cwg-dropdown ref="dropdownRef" @open="onOpen" @close="onClose" :menu-list="customMenuList"
  10. @menuClick="handleCustomClick">
  11. <button class="btn btn-white btn-sm btn-shadow btn-icon waves-effect dropdown-toggle"
  12. type="button">
  13. <cwg-icon name="crm-ellipsis-vertical" :size="18"
  14. :color="!isDark ? '#6c8595' : '#fff'" />
  15. </button>
  16. </cwg-dropdown>
  17. </view>
  18. </view>
  19. </view>
  20. <view class="card-body p-3 pt-0">
  21. <view class="text-left mb-3">
  22. <h5 class="fw-bold mb-3 cursor-pointer" @click="copy(account.accountNumber)"># {{
  23. account.accountNumber }}</h5>
  24. <h4 class="mb-2 cursor-pointer" @click="copy(account.fwq)">{{ account.fwq }}</h4>
  25. <template v-for="(label, index) in account.labels" :key="index">
  26. <text v-if="label" class="badge text-danger1 bg-danger-subtle mx-1">{{ label }}</text>
  27. </template>
  28. <h1 class="mt-2">${{ balanceInteger }}{{ balanceDecimal }}</h1>
  29. <!-- <button type="submit" value="Submit" class="btn btn-secondary btn-sm w-75 waves-effect waves-light"
  30. @click="handleAction('trade')">
  31. <view class="d-flex align-items-center justify-content-center gap-1"><cwg-icon name="crm-trade"
  32. :size="16" color="#fff" />
  33. 开始交易</view>
  34. </button> -->
  35. <hr>
  36. </view>
  37. <view class="text-left">
  38. <view class="border-0 card-header p-2">
  39. <view class="row">
  40. <view class="col-6">
  41. <view class="mb-3">
  42. <view class="mb-1">{{ t('Label.Leverage') }}</view>
  43. <view class="d-flex fw-semibold mb-0 text-dark">{{ account.actualLeverage }}</view>
  44. </view>
  45. <view class="mb-3">
  46. <view class="mb-1">{{ t('Label.FloatingPL') }}</view>
  47. <view class="d-flex fw-semibold mb-0 text-dark">{{ account.floatingPL }}</view>
  48. </view>
  49. <view class="mb-3">
  50. <view class="mb-1">{{ t('Label.Balance') }}</view>
  51. <view class="text-dark fw-semibold mb-0">{{ account.balanceWithSymbol }}</view>
  52. </view>
  53. </view>
  54. <view class="col-6">
  55. <view class="mb-3">
  56. <view class="mb-1">{{ t('Label.Equity') }}</view>
  57. <view class="text-dark fw-semibold mb-0">{{ account.equityWithSymbol }}</view>
  58. </view>
  59. <view class="mb-3">
  60. <view class="mb-1">{{ t('Label.Credit') }}</view>
  61. <view class="text-dark fw-semibold mb-0">{{ account.creditWithSymbol }}</view>
  62. </view>
  63. <view class="mb-3">
  64. <view class="mb-1">{{ t('Documentary.console.item3') }}</view>
  65. <view class="text-dark fw-semibold mb-0">{{ account.platform }}</view>
  66. </view>
  67. </view>
  68. </view>
  69. <view class="d-flex flex-wrap gap-2" v-if="isReal">
  70. <button v-for="btn in actionButtons" :key="btn.key" type="submit" value="Submit"
  71. class="btn btn-dark btn-sm waves-effect waves-light"
  72. :class="{ 'disabled': btn.disabled, 'btn-outline-dark1': btn.key !== 'deposit'}" @click="handleAction(btn.action)">
  73. <view class="d-flex align-items-center justify-content-center gap-1">
  74. <cwg-icon :name="btn.icon" :size="14" :color="btn.key === 'deposit' ? '#fff' : ''" />
  75. {{ t(btn.label) }}
  76. </view>
  77. </button>
  78. </view>
  79. </view>
  80. </view>
  81. </view>
  82. </view>
  83. </view>
  84. <TerminalDialog v-model:visible="terminalDialogVisible" />
  85. <TerminalChangePasswordDialog v-model:visible="terminalChangePasswordDialogVisible" :pwdType="pwdType"
  86. :account="account" :accountLabel="t('Documentary.tradingCenter.item29') + ' # '" />
  87. <TerminalInfoDialog v-model:visible="terminalInfoDialogVisible" :accountNumber="accountInfo.login"
  88. :form="accountInfo" :fieldList="fieldList" :title="t('Documentary.TundManagement.item29')"
  89. :accountLabel="t('Documentary.tradingCenter.item29') + ' # '" />
  90. </template>
  91. <script setup lang="ts">
  92. import { ref, computed, onMounted, nextTick, onBeforeUnmount } from 'vue';
  93. import useRouter from "@/hooks/useRouter";
  94. const router = useRouter();
  95. import { useI18n } from 'vue-i18n';
  96. const { t } = useI18n();
  97. import TerminalDialog from './TerminalDialog.vue'
  98. import TerminalChangePasswordDialog from './TerminalChangePasswordDialog.vue'
  99. import TerminalInfoDialog from './TerminalInfoDialog.vue'
  100. import useGlobalStore from '@/stores/use-global-store'
  101. const globalStore = useGlobalStore()
  102. const isDark = computed(() => globalStore.theme === 'dark')
  103. const props = defineProps<{
  104. account: Account;
  105. }>();
  106. const accountInfo = ref(props.account)
  107. export interface Account {
  108. labels: string[]; // 标签数组,如 ['真实', 'MT4', 'Standard']
  109. accountNumber: string; // 账号,如 '85319215'
  110. nickName: string; // 昵称,如 '标准账户'
  111. balance: number; // 余额数字
  112. currency: string; // 货币,如 'USD'
  113. actualLeverage: string; // 实际杠杆,如 '1:2000'
  114. maxLeverage: string; // 调整杠杆,如 '1:2000'
  115. floatingPL: string; // 浮动盈亏,如 '0.00 USD'
  116. creditWithSymbol: string; // 可用保证金,如 '0.00 USD'
  117. equityWithSymbol: string; // 净值,如 '0.00 USD'
  118. platform: string; // 平台,如 'MT4'
  119. server: string; // 服务器,如 'Exness-Real28'
  120. login: string; // 登录名,如 '85319215'
  121. balanceWithSymbol: string; // 余额,如 '85319215'
  122. fwq: string; // 服务器名称
  123. listType: string; // 账户类型,如 'real' 或 'demo'
  124. closeFunctions?: string; // 关闭的功能
  125. }
  126. const isDemo = computed(() => accountInfo.value.listType == 'demo')
  127. const isDel = computed(() => accountInfo.value.listType == 'del')
  128. const isReal = computed(() => accountInfo.value.listType == 'real')
  129. const closeFunctionOpen = (code) => {
  130. const closeFunctions = accountInfo.value.closeFunctions || ""
  131. if (closeFunctions == null || closeFunctions === "") {
  132. return true;
  133. }
  134. return String(closeFunctions).indexOf(String(code)) === -1;
  135. }
  136. const circleButtons = ref([
  137. { key: 'deposit', label: 'Home.page_customer.item2', icon: 'crm-deposit', action: 'deposit', needDemo: isDemo.value, disabled: !closeFunctionOpen('1'), color: '#6c8595' },
  138. { key: 'withdraw', label: 'Home.page_customer.item3', icon: 'crm-withdraw', action: 'withdraw', needDemo: isDemo.value, disabled: !closeFunctionOpen('2'), color: '#6c8595' },
  139. { key: 'transfer', label: 'Custom.Index.Transfer', icon: 'crm-transfer', action: 'transfer', needDemo: isDemo.value, disabled: !(closeFunctionOpen('5') && closeFunctionOpen('6') && closeFunctionOpen('3')), color: '#6c8595' }
  140. ])
  141. const fieldList = ref([
  142. { label: t('Custom.PaymentHistory.AccountType'), key: 'nickname', copyable: false },
  143. { label: t('Label.Leverage'), key: 'actualLeverage', copyable: false },
  144. { label: t('Label.FloatingPL'), key: 'floatingPL', copyable: false },
  145. { label: t('Label.Balance'), key: 'balanceWithSymbol', copyable: false },
  146. { label: t('Label.Equity'), key: 'equityWithSymbol', copyable: false },
  147. { label: t('Label.Credit'), key: 'creditWithSymbol', copyable: false },
  148. { label: t('Documentary.console.item3'), key: 'platform', copyable: false },
  149. { label: t('Documentary.console.item4'), key: 'login', copyable: true }
  150. ])
  151. const nickName = ref(accountInfo.value.nickName);
  152. const actionButtons = ref([
  153. { key: 'deposit', label: 'Home.page_customer.item2', icon: 'crm-deposit', action: 'deposit', disabled: computed(() => !closeFunctionOpen('1')) },
  154. { key: 'withdraw', label: 'Home.page_customer.item3', icon: 'crm-withdraw', action: 'withdraw', disabled: computed(() => !closeFunctionOpen('2')) },
  155. { key: 'transfer', label: 'Custom.Index.Transfer', icon: 'crm-transfer', action: 'transfer', disabled: computed(() => !(closeFunctionOpen('5') && closeFunctionOpen('6') && closeFunctionOpen('3'))) }
  156. ])
  157. const terminalDialogVisible = ref(false)
  158. const terminalChangePasswordDialogVisible = ref(false)
  159. const terminalInfoDialogVisible = ref(false)
  160. const pwdType = ref(1)
  161. const dropdownRef = ref(null)
  162. const handleAction = (type: string) => {
  163. if (dropdownRef.value) {
  164. dropdownRef.value.close()
  165. }
  166. switch (type) {
  167. case 'trade':
  168. terminalDialogVisible.value = true
  169. break;
  170. case 'changePassword1':
  171. pwdType.value = 1
  172. terminalChangePasswordDialogVisible.value = true
  173. break;
  174. case 'changePassword2':
  175. pwdType.value = 2
  176. terminalChangePasswordDialogVisible.value = true
  177. break;
  178. case 'changePassword3':
  179. pwdType.value = 3
  180. terminalChangePasswordDialogVisible.value = true
  181. break;
  182. case 'info':
  183. terminalInfoDialogVisible.value = true
  184. break;
  185. case 'deposit':
  186. toDeposit()
  187. break;
  188. case 'withdraw':
  189. toWithdraw()
  190. break;
  191. case 'transfer':
  192. toTransfer()
  193. break;
  194. case 'position':
  195. toPosition()
  196. break;
  197. case 'history':
  198. toHistory()
  199. break;
  200. case 'payment-history':
  201. toPaymentHistory()
  202. break;
  203. default:
  204. break;
  205. }
  206. };
  207. const customMenuList = computed(() => {
  208. switch (accountInfo.value.listType) {
  209. case 'real':
  210. return [
  211. { label: '开始交易', type: 'trade' },
  212. { label: t('Ib.Report.Tit1'), type: 'history' },
  213. { label: t('Ib.Report.Tit4'), type: 'position' },
  214. { label: t('Home.page_customer.item4'), type: 'payment-history' },
  215. { label: t('Documentary.TundManagement.item29'), type: 'info' },
  216. { label: t('vu.item3'), type: 'changePassword1' },
  217. { label: t('vu.item4'), type: 'changePassword2' },
  218. { label: t('Custom.Settings.TitReset'), type: 'changePassword3' }
  219. ]
  220. case 'demo':
  221. return [
  222. { label: '开始交易', type: 'trade' },
  223. { label: t('Documentary.TundManagement.item29'), type: 'info' }
  224. ]
  225. case 'del':
  226. return [
  227. { label: t('Documentary.TundManagement.item29'), type: 'info' }
  228. ]
  229. }
  230. })
  231. const handleCustomClick = (item, index) => {
  232. handleAction(item.value.type)
  233. }
  234. const copy = (text: string) => {
  235. uni.setClipboardData({
  236. data: text,
  237. success: function () {
  238. uni.showToast({
  239. title: t('Btn.item8'),
  240. icon: 'none',
  241. duration: 2000
  242. });
  243. }
  244. });
  245. };
  246. const toHistory = () => {
  247. router.push(`/pages/customer/trade-history?login=${accountInfo.value.login}`)
  248. }
  249. const toPosition = () => {
  250. router.push(`/pages/customer/trade-position?login=${accountInfo.value.login}`)
  251. }
  252. const toPaymentHistory = () => {
  253. router.push(`/pages/customer/payment-history?login=${accountInfo.value.login}`)
  254. }
  255. const toDeposit = () => {
  256. router.push(`/pages/customer/deposit-select?login=${accountInfo.value.login}&type=${accountInfo.value.type}&balance=${accountInfo.value.balance}&currency=${accountInfo.value.currency}`)
  257. }
  258. const toWithdraw = () => {
  259. router.push(`/pages/customer/withdrawal-select?login=${accountInfo.value.login}&type=${accountInfo.value.type}&balance=${accountInfo.value.balance}&currency=${accountInfo.value.currency}`)
  260. }
  261. const toTransfer = () => {
  262. router.push(`/pages/customer/transfer?login=${accountInfo.value.login}&type=${accountInfo.value.type}&balance=${accountInfo.value.balance}&currency=${accountInfo.value.currency}`)
  263. }
  264. const balanceInteger = computed(() => {
  265. return accountInfo.value.balance ? Math.floor(accountInfo.value.balance).toString() : '0';
  266. });
  267. const balanceDecimal = computed(() => {
  268. const parts = accountInfo.value?.balance?.toFixed(2)?.split || [];
  269. console.log(accountInfo.value?.balance, 1212);
  270. if (!accountInfo.value?.balance) return '.00'
  271. return parts[1] ? '.' + parts[1] : '.00';
  272. });
  273. onMounted(() => {
  274. });
  275. onBeforeUnmount(() => {
  276. });
  277. </script>
  278. <style scoped lang="scss">
  279. @import '@/uni.scss';
  280. .btn.disabled {
  281. opacity: 0.5;
  282. cursor: not-allowed;
  283. }
  284. .btn {
  285. margin-left: 0;
  286. margin-right: 0;
  287. }
  288. .text-danger1 {
  289. color: var(--bs-emphasis-color) !important;
  290. }
  291. .btn-outline-dark1 {
  292. background-color: var(--btn-color) !important;
  293. color: var(--bs-emphasis-color) !important;
  294. border-color: var(--btn-color) !important;
  295. }
  296. </style>