zhb 2 hónapja
szülő
commit
4d4f98e405
100 módosított fájl, 5853 hozzáadás és 2677 törlés
  1. 209 0
      components/cwg-dropdown.vue
  2. 12 14
      components/cwg-header.vue
  3. 11 6
      components/cwg-label-line-value.vue
  4. 1 1
      components/cwg-page-wrapper.vue
  5. 9 6
      components/cwg-popup.vue
  6. 9 4
      config/index.ts
  7. 403 0
      global/constPY.js
  8. 128 0
      global/index.js
  9. 12 0
      global/isImageType.js
  10. 40 0
      global/py.js
  11. 11 0
      global/tool.js
  12. 28 0
      lib/crypt.js
  13. 159 0
      lib/service.js
  14. 56 0
      lib/session.js
  15. 138 0
      lib/upload.js
  16. 1 0
      package.json
  17. 33 10
      pages.json
  18. 480 0
      pages/customer/account-select.vue
  19. 119 45
      pages/customer/components/AccountCard.vue
  20. 21 17
      pages/customer/components/AccountList.vue
  21. 1 1
      pages/customer/components/DeleteAccountDialogs.vue
  22. 184 0
      pages/customer/components/PaymentMethodsList.vue
  23. 210 0
      pages/customer/components/TerminalChangePasswordDialog.vue
  24. 332 0
      pages/customer/components/TerminalDialog.vue
  25. 182 0
      pages/customer/components/TerminalInfoDialog.vue
  26. 184 0
      pages/customer/components/TerminalNickNameDialog.vue
  27. 1 1
      pages/customer/components/TransactionDialogs.vue
  28. 116 0
      pages/customer/composables/TerminalMap.ts
  29. 0 1379
      pages/customer/create-account copy.vue
  30. 169 181
      pages/customer/create-account.vue
  31. 824 577
      pages/customer/deposit.vue
  32. 350 0
      pages/customer/style.scss
  33. 1347 0
      pages/customer/withdrawal.vue
  34. 0 257
      pages/login/forget.vue
  35. 6 2
      pages/login/index.vue
  36. 60 174
      pages/login/regist.vue
  37. 1 2
      pages/mine/improve.vue
  38. 5 0
      service/custom.ts
  39. 1 0
      static/icons/crm-caret-right.svg
  40. BIN
      static/pdf/Client_Agreement.pdf
  41. BIN
      static/pdf/CopyTradeUserAgreement.pdf
  42. BIN
      static/pdf/CopyTradeUserAgreementcn.pdf
  43. BIN
      static/pdf/DigitalCurrency_Withdrawal_Cn.pdf
  44. BIN
      static/pdf/DigitalCurrency_Withdrawal_En.pdf
  45. BIN
      static/pdf/PrivacyPolicy2019_01.pdf
  46. BIN
      static/pdf/Privacy_Policy.pdf
  47. BIN
      static/pdf/Terms&Conditions.pdf
  48. BIN
      static/pdf/pdf1/ar.pdf
  49. BIN
      static/pdf/pdf1/cn.pdf
  50. BIN
      static/pdf/pdf1/en.pdf
  51. BIN
      static/pdf/pdf1/es.pdf
  52. BIN
      static/pdf/pdf1/ko.pdf
  53. BIN
      static/pdf/pdf1/pt.pdf
  54. BIN
      static/pdf/pdf1/th.pdf
  55. BIN
      static/pdf/pdf1/vn.pdf
  56. BIN
      static/pdf/pdf1/zhHant.pdf
  57. BIN
      static/pdf/pdf10/Account Type Allocation Table-cn.pdf
  58. BIN
      static/pdf/pdf10/Account Type Allocation Table-en.pdf
  59. BIN
      static/pdf/pdf10/Account Type Allocation Table-zhHant.pdf
  60. BIN
      static/pdf/pdf11/Account Type Allocation Table-cn.pdf
  61. BIN
      static/pdf/pdf11/Account Type Allocation Table-en.pdf
  62. BIN
      static/pdf/pdf11/Account Type Allocation Table-zhHant.pdf
  63. BIN
      static/pdf/pdf12/Account Type Allocation Table-cn.pdf
  64. BIN
      static/pdf/pdf12/CWG Markets Prime Bonus Application Process-cn.pdf
  65. BIN
      static/pdf/pdf12/CWG Markets Prime Bonus Application Process-en.pdf
  66. BIN
      static/pdf/pdf12/CWG Markets Prime Bonus Application Process-zhHant.pdf
  67. BIN
      static/pdf/pdf12/CWG Prime Bonus-ar.pdf
  68. BIN
      static/pdf/pdf12/CWG Prime Bonus-cn.pdf
  69. BIN
      static/pdf/pdf12/CWG Prime Bonus-de.pdf
  70. BIN
      static/pdf/pdf12/CWG Prime Bonus-en.pdf
  71. BIN
      static/pdf/pdf12/CWG Prime Bonus-es.pdf
  72. BIN
      static/pdf/pdf12/CWG Prime Bonus-fa.pdf
  73. BIN
      static/pdf/pdf12/CWG Prime Bonus-id.pdf
  74. BIN
      static/pdf/pdf12/CWG Prime Bonus-ko.pdf
  75. BIN
      static/pdf/pdf12/CWG Prime Bonus-ms.pdf
  76. BIN
      static/pdf/pdf12/CWG Prime Bonus-pt.pdf
  77. BIN
      static/pdf/pdf12/CWG Prime Bonus-th.pdf
  78. BIN
      static/pdf/pdf12/CWG Prime Bonus-tr.pdf
  79. BIN
      static/pdf/pdf12/CWG Prime Bonus-vn.pdf
  80. BIN
      static/pdf/pdf12/CWG Prime Bonus-zhHant.pdf
  81. BIN
      static/pdf/pdf13/CWG Markets Prime Bonus Application Process-cn.pdf
  82. BIN
      static/pdf/pdf13/CWG Prime Bonus-cn.pdf
  83. BIN
      static/pdf/pdf2/pdf-cn.pdf
  84. BIN
      static/pdf/pdf2/pdf-en.pdf
  85. BIN
      static/pdf/pdf2/pdf-es.pdf
  86. BIN
      static/pdf/pdf2/pdf-pt.pdf
  87. BIN
      static/pdf/pdf2/pdf-th.pdf
  88. BIN
      static/pdf/pdf2/pdf-vn.pdf
  89. BIN
      static/pdf/pdf2/pdf-zhHant.pdf
  90. BIN
      static/pdf/pdf3/pdf-cn.pdf
  91. BIN
      static/pdf/pdf3/pdf-en.pdf
  92. BIN
      static/pdf/pdf3/pdf-zhHant.pdf
  93. BIN
      static/pdf/pdf4/100Bonus-ar.pdf
  94. BIN
      static/pdf/pdf4/100Bonus-en.pdf
  95. BIN
      static/pdf/pdf4/100Bonus-es.pdf
  96. BIN
      static/pdf/pdf4/ar.pdf
  97. BIN
      static/pdf/pdf4/cn.pdf
  98. BIN
      static/pdf/pdf4/de.pdf
  99. BIN
      static/pdf/pdf4/en.pdf
  100. BIN
      static/pdf/pdf4/es.pdf

+ 209 - 0
components/cwg-dropdown.vue

@@ -0,0 +1,209 @@
+<template>
+    <view>
+        <view class="cwg-dropdown" :style="customStyle" @click="click">
+            <slot></slot>
+        </view>
+        <view class="cwg-dropdown-menu">
+            <view class="cwg-dropdown-menu-container" :style="[layout]" @click.stop>
+                <slot name="menu">
+                    <view class="menu">
+                        <view class="menu-item" v-for="(item, idx) in menuList" :key="idx"
+                            @click="menuClick(item, idx)">
+                            <view>{{ item.label || item }}</view>
+                        </view>
+                    </view>
+                </slot>
+            </view>
+        </view>
+        <view class="cwg-dropdown-mask" :class="{ 'cwg-dropdown-mask-show': maskShow }" @touchmove.prevent="() => { }"
+            @click="close" />
+    </view>
+</template>
+
+<script setup>
+import { ref, reactive, nextTick, onMounted } from 'vue'
+import { queryElementRect } from '@/uni_modules/x-tools/tools/sugar.js'
+import { str2px, commonProps } from '@/uni_modules/x-tools/tools/com.js'
+
+// 合并 props
+const props = defineProps({
+    ...commonProps,
+    menuList: {
+        type: Object,
+        default: () => ['菜单1', '菜单2', '菜单3']
+    },
+    menuStyle: {
+        type: Object,
+        default: () => ({})
+    },
+    interspace: {
+        type: [String, Number],
+        default: '10rpx'
+    }
+})
+
+const emit = defineEmits(['open', 'close', 'change', 'menuClick'])
+
+// 响应式数据
+const maskShow = ref(false)
+const windowInfo = reactive({
+    width: 0,
+    height: 0
+})
+const layout = reactive({})
+const innerInterspace = ref(0)
+
+// 获取系统信息
+const getSystemInfo = () => {
+    return new Promise((resolve) => {
+        if (windowInfo.width > 0) {
+            resolve(windowInfo)
+        } else {
+            uni.getSystemInfo({
+                success: (res) => {
+                    windowInfo.width = res.windowWidth
+                    windowInfo.height = res.windowHeight
+                    resolve(windowInfo)
+                },
+                fail: () => {
+                    setTimeout(() => getSystemInfo().then(resolve), 100)
+                }
+            })
+        }
+    })
+}
+
+// 点击触发器
+const click = async (e) => {
+    e.stopPropagation()
+    await getSystemInfo()
+    const triggerRect = await queryElementRect('.cwg-dropdown')
+    if (!triggerRect) return
+    const tempStyle = {
+        transform: 'scaleY(1)',
+        visibility: 'hidden',
+        top: '-9999px',
+        left: '-9999px',
+        transition: 'none'
+    }
+    Object.assign(layout, tempStyle)
+    await nextTick()
+    const menuRect = await queryElementRect('.cwg-dropdown-menu-container')
+    if (!menuRect) {
+        Object.keys(layout).forEach(key => delete layout[key])
+        layout.transform = 'scaleY(0)'
+        return
+    }
+    const { width: winWidth } = windowInfo
+    const { left, right, bottom } = triggerRect
+    const interspaceVal = innerInterspace.value
+    const finalLayout = {
+        transition: 'transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)',
+        transform: 'scaleY(1)',
+        top: `10px`
+    }
+    if (left + menuRect.width < winWidth) {
+        finalLayout.left = `-110px`
+    } else {
+        const val = winWidth - right
+        finalLayout.right = `${val > 0 ? val : 0}px`
+    }
+    Object.keys(layout).forEach(key => delete layout[key])
+    Object.assign(layout, finalLayout)
+    maskShow.value = true
+    emit('open')
+    emit('change', true)
+}
+const menuClick = (value, index) => {
+    emit('menuClick', { value, index })
+    close()
+}
+const close = () => {
+    maskShow.value = false
+    Object.keys(layout).forEach(key => delete layout[key])
+    layout.transform = 'scaleY(0)'
+    emit('close')
+    emit('change', false)
+}
+onMounted(() => {
+    getSystemInfo()
+    innerInterspace.value = str2px(props.interspace)
+})
+</script>
+
+<style lang="scss" scoped>
+@import '@/uni.scss';
+
+.cwg-dropdown {
+    width: fit-content;
+    position: relative;
+    overflow: hidden;
+}
+
+.cwg-dropdown-menu {
+    position: relative;
+    z-index: 1000;
+}
+
+.cwg-dropdown-mask {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100vw;
+    height: 100vh;
+    z-index: 999;
+    transition: all 0.3s;
+    opacity: 0;
+    pointer-events: none;
+    background-color: rgba(0, 0, 0, 0);
+}
+
+.cwg-dropdown-mask-show {
+    opacity: 1;
+    pointer-events: auto;
+}
+
+.cwg-dropdown-menu-container {
+    position: absolute;
+    transform-origin: top;
+    transform: scaleY(0);
+
+    .menu {
+        position: relative;
+        background: #FFFFFF;
+        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+        border-radius: px2rpx(4);
+        overflow: hidden;
+
+        .menu-item {
+            width: px2rpx(150);
+            display: flex;
+            align-items: center;
+            padding: px2rpx(10) px2rpx(16);
+            font-size: px2rpx(14);
+            line-height: px2rpx(30);
+            color: #333;
+            transition: background 0.2s;
+            border-bottom: 1px solid #f0f0f0;
+            box-sizing: border-box;
+
+            &:last-child {
+                border-bottom: none;
+            }
+
+            text {
+                flex: 1;
+                line-height: 1.4;
+            }
+
+            &:hover {
+                background-color: rgba(0, 0, 0, 0.05);
+            }
+
+            &:active {
+                background-color: rgba(0, 0, 0, 0.05);
+            }
+        }
+    }
+}
+</style>

+ 12 - 14
components/cwg-header.vue

@@ -1,18 +1,15 @@
 <template>
-  <uni-nav-bar :leftWidth="0" :rightWidth="0" :statusBar="true" :fixed="true" :height="60"
-    :backgroundColor="props.backgrounds || '#fff'" :border="false" :a="props.backgrounds">
-    <view class="pages-header">
-      <view class="header">
-        <view v-if="showBack" class="back">
-          <cwg-icon name="dropdown" class="back-icon" color="#000" @click="handleBack" />
-        </view>
-        <view>{{ headerTitleReady ? headerTitle : '' }}</view>
-      </view>
-      <view class="header-r">
-        <slot></slot>
+  <view class="pages-header" v-if="showBack">
+    <view class="header">
+      <view v-if="showBack" class="back">
+        <cwg-icon name="dropdown" class="back-icon" color="#000" @click="handleBack" />
       </view>
+      <view>{{ headerTitleReady ? headerTitle : '' }}</view>
+    </view>
+    <view class="header-r">
+      <slot></slot>
     </view>
-  </uni-nav-bar>
+  </view>
 </template>
 
 <script setup lang="ts">
@@ -83,13 +80,14 @@ function handleBack() {
   align-items: center;
   justify-content: space-between;
   box-sizing: border-box;
+  margin-bottom: px2rpx(24);
 }
 
 .header {
   position: relative;
   text-align: left;
-  font-size: var(--font-size-22);
-  color: var(--white);
+  font-size: px2rpx(32);
+  color: #141d22;
   font-weight: 700;
   margin: px2rpx(10) 0;
   height: px2rpx(40);

+ 11 - 6
components/cwg-label-line-value.vue

@@ -1,8 +1,11 @@
 <template>
     <view class="info-item">
-        <span class="label">{{ label }}</span>
-        <span class="line"></span>
-        <span class="value">{{ value }}</span>
+        <view class="label">{{ label }}</view>
+        <view class="line"></view>
+        <view class="value">
+            <view>{{ value }}</view>
+            <slot name="operation" />
+        </view>
     </view>
 </template>
 
@@ -24,24 +27,26 @@ const props = defineProps({
 @import "@/uni.scss";
 
 .info-item {
+    width: 100%;
     display: flex;
     justify-content: space-between;
     align-items: flex-end;
     font-size: px2rpx(14);
+    line-height: px2rpx(24);
 
     .label {
         color: #6c8595;
     }
-
     .line {
         flex: 1;
         height: 1px;
-        border-top: 1px dashed rgba(108, 133, 149, 0.5);
+        border-top: 1px dashed rgba(20, 29, 34, .122);
         margin-bottom: px2rpx(1);
 
     }
-
     .value {
+        display: flex;
+        align-items: flex-end;
         font-weight: 500;
         color: #2e3a47;
     }

+ 1 - 1
components/cwg-page-wrapper.vue

@@ -9,7 +9,6 @@
       <cwg-match-media :max-width="991" v-if="!isLoginPage">
         <view class="left-sidebar" :class="{ 'sidebar-visible': sidebarVisible }">
           <cwg-sidebar />
-
         </view>
         <view class="sidebar-mask" v-if="sidebarVisible" @click="openLeftDrawer" :style="{
           opacity: sidebarVisible ? 1 : 0,
@@ -17,6 +16,7 @@
         }"></view>
       </cwg-match-media>
       <view class="content-wrapper" :class="{ 'content-wrapper-padding': isContentPadding }">
+        <cwg-header />
         <slot />
       </view>
       <view :style="{ height: isTabBarPage ? '60px' : '0px' }" />

+ 9 - 6
components/cwg-popup.vue

@@ -1,6 +1,6 @@
 <template>
-    <uni-popup ref="popupRef" type="center" :mask-click="false" @change="handlePopupChange">
-        <view class="delete-account-dialog">
+    <uni-popup ref="popupRef" type="center" @change="handlePopupChange">
+        <view class="cwg-dialog">
             <!-- 弹窗头部 -->
             <view class="dialog-header">
                 <text class="dialog-title">{{ title || t('Tips.DeleteAccount') }}</text>
@@ -168,18 +168,21 @@ defineExpose({
 <style scoped lang="scss">
 @import "@/uni.scss";
 
-.delete-account-dialog {
+.cwg-dialog {
     background-color: var(--color-white);
     border-radius: px2rpx(8);
     overflow: hidden;
     width: px2rpx(600);
     max-width: 90vw;
+}
 
-    @media (min-width: 768px) {
-        width: px2rpx(800);
+@media (min-width: 768px) {
+    :deep(.cwg-dialog) {
+        width: px2rpx(600) !important;
     }
 }
 
+
 .dialog-header {
     display: flex;
     align-items: center;
@@ -195,7 +198,7 @@ defineExpose({
 }
 
 .dialog-content {
-    padding: px2rpx(20);
+    padding: px2rpx(20) px2rpx(30);
     max-height: 60vh;
     overflow-y: auto;
 

+ 9 - 4
config/index.ts

@@ -11,16 +11,21 @@ let ho = '44a5c8109e4'; // 默认主域名或可根据实际APP环境配置
 const config = {
 
   HostWs: "wss://ws." + ho + ".com",
-  Host80: ht + "//secure." + ho + ".com",
-  Host00: ht + "//ucard." + ho + ".com",
-  Host85: ht + "//ucard." + ho + ".com",
-  Host04: ht + "//pay." + ho + ".com",
+  // Host80: ht + "//secure." + ho + ".com",
+  // Host00: ht + "//ucard." + ho + ".com",
+  // Host85: ht + "//ucard." + ho + ".com",
+  // Host04: ht + "//pay." + ho + ".com",
+  Host80: 'http://192.168.0.21:8000',
+  Host00: 'http://192.168.0.21:8000',
+  Host85: 'http://192.168.0.21:8000',
+  Host04: 'http://192.168.0.21:8004',
   Host90: ht + "//data." + ho + ".com",
   HostShop: ht + "//shopcustom." + ho + ".com",
   HostShopImg: ht + "//shopmanager." + ho + ".com",
   Host87: ht + "//followup." + ho + ".com",
   Host05: ht + "//file." + ho + ".com",
   HostEnter: ht + "//ad." + ho + ".com",
+  ho,
   Code: {
     StatusOK: 200,
     StatusFail: 400,

+ 403 - 0
global/constPY.js

@@ -0,0 +1,403 @@
+export const pinyin = {
+  'a': '\u554a\u963f\u9515',
+  'ai': '\u57c3\u6328\u54ce\u5509\u54c0\u7691\u764c\u853c\u77ee\u827e\u788d\u7231\u9698\u8bf6\u6371\u55f3\u55cc\u5ad2\u7477\u66a7\u7839\u953f\u972d',
+  'an': '\u978d\u6c28\u5b89\u4ffa\u6309\u6697\u5cb8\u80fa\u6848\u8c19\u57ef\u63de\u72b4\u5eb5\u6849\u94f5\u9e4c\u9878\u9eef',
+  'ang': '\u80ae\u6602\u76ce',
+  'ao': '\u51f9\u6556\u71ac\u7ff1\u8884\u50b2\u5965\u61ca\u6fb3\u5773\u62d7\u55f7\u5662\u5c99\u5ed2\u9068\u5aaa\u9a9c\u8071\u87af\u93ca\u9ccc\u93d6',
+  'ba': '\u82ad\u634c\u6252\u53ed\u5427\u7b06\u516b\u75a4\u5df4\u62d4\u8dcb\u9776\u628a\u8019\u575d\u9738\u7f62\u7238\u8307\u83dd\u8406\u636d\u5c9c\u705e\u6777\u94af\u7c91\u9c85\u9b43',
+  'bai': '\u767d\u67cf\u767e\u6446\u4f70\u8d25\u62dc\u7a17\u859c\u63b0\u97b4',
+  'ban': '\u6591\u73ed\u642c\u6273\u822c\u9881\u677f\u7248\u626e\u62cc\u4f34\u74e3\u534a\u529e\u7eca\u962a\u5742\u8c73\u94a3\u7622\u764d\u8228',
+  'bang': '\u90a6\u5e2e\u6886\u699c\u8180\u7ed1\u68d2\u78c5\u868c\u9551\u508d\u8c24\u84a1\u8783',
+  'bao': '\u82de\u80de\u5305\u8912\u96f9\u4fdd\u5821\u9971\u5b9d\u62b1\u62a5\u66b4\u8c79\u9c8d\u7206\u52f9\u8446\u5b80\u5b62\u7172\u9e28\u8913\u8db5\u9f85',
+  'bo': '\u5265\u8584\u73bb\u83e0\u64ad\u62e8\u94b5\u6ce2\u535a\u52c3\u640f\u94c2\u7b94\u4f2f\u5e1b\u8236\u8116\u818a\u6e24\u6cca\u9a73\u4eb3\u8543\u5575\u997d\u6a97\u64d8\u7934\u94b9\u9e41\u7c38\u8ddb',
+  'bei': '\u676f\u7891\u60b2\u5351\u5317\u8f88\u80cc\u8d1d\u94a1\u500d\u72c8\u5907\u60eb\u7119\u88ab\u5b5b\u9642\u90b6\u57e4\u84d3\u5457\u602b\u6096\u789a\u9e4e\u8919\u943e',
+  'ben': '\u5954\u82ef\u672c\u7b28\u755a\u574c\u951b',
+  'beng': '\u5d29\u7ef7\u752d\u6cf5\u8e66\u8ff8\u552a\u5623\u750f',
+  'bi': '\u903c\u9f3b\u6bd4\u9119\u7b14\u5f7c\u78a7\u84d6\u853d\u6bd5\u6bd9\u6bd6\u5e01\u5e87\u75f9\u95ed\u655d\u5f0a\u5fc5\u8f9f\u58c1\u81c2\u907f\u965b\u5315\u4ef3\u4ffe\u8298\u835c\u8378\u5421\u54d4\u72f4\u5eb3\u610e\u6ed7\u6fde\u5f3c\u59a3\u5a62\u5b16\u74a7\u8d32\u7540\u94cb\u79d5\u88e8\u7b5a\u7b85\u7be6\u822d\u895e\u8df8\u9ac0',
+  'bian': '\u97ad\u8fb9\u7f16\u8d2c\u6241\u4fbf\u53d8\u535e\u8fa8\u8fa9\u8fab\u904d\u533e\u5f01\u82c4\u5fed\u6c74\u7f0f\u7178\u782d\u78a5\u7a39\u7a86\u8759\u7b3e\u9cca',
+  'biao': '\u6807\u5f6a\u8198\u8868\u5a4a\u9aa0\u98d1\u98d9\u98da\u706c\u9556\u9573\u762d\u88f1\u9cd4',
+  'bie': '\u9cd6\u618b\u522b\u762a\u8e69\u9cd8',
+  'bin': '\u5f6c\u658c\u6fd2\u6ee8\u5bbe\u6448\u50a7\u6d5c\u7f24\u73a2\u6ba1\u8191\u9554\u9acc\u9b13',
+  'bing': '\u5175\u51b0\u67c4\u4e19\u79c9\u997c\u70b3\u75c5\u5e76\u7980\u90b4\u6452\u7ee0\u678b\u69df\u71f9',
+  'bu': '\u6355\u535c\u54fa\u8865\u57e0\u4e0d\u5e03\u6b65\u7c3f\u90e8\u6016\u62ca\u535f\u900b\u74ff\u6661\u949a\u91ad',
+  'ca': '\u64e6\u5693\u7924',
+  'cai': '\u731c\u88c1\u6750\u624d\u8d22\u776c\u8e29\u91c7\u5f69\u83dc\u8521',
+  'can': '\u9910\u53c2\u8695\u6b8b\u60ed\u60e8\u707f\u9a96\u74a8\u7cb2\u9eea',
+  'cang': '\u82cd\u8231\u4ed3\u6ca7\u85cf\u4f27',
+  'cao': '\u64cd\u7cd9\u69fd\u66f9\u8349\u8279\u5608\u6f15\u87ac\u825a',
+  'ce': '\u5395\u7b56\u4fa7\u518c\u6d4b\u5202\u5e3b\u607b',
+  'ceng': '\u5c42\u8e6d\u564c',
+  'cha': '\u63d2\u53c9\u832c\u8336\u67e5\u78b4\u643d\u5bdf\u5c94\u5dee\u8be7\u7339\u9987\u6c4a\u59f9\u6748\u6942\u69ce\u6aab\u9497\u9538\u9572\u8869',
+  'chai': '\u62c6\u67f4\u8c7a\u4faa\u8308\u7625\u867f\u9f87',
+  'chan': '\u6400\u63ba\u8749\u998b\u8c17\u7f20\u94f2\u4ea7\u9610\u98a4\u5181\u8c04\u8c36\u8487\u5edb\u5fcf\u6f7a\u6fb6\u5b71\u7fbc\u5a75\u5b17\u9aa3\u89c7\u7985\u9561\u88e3\u87fe\u8e94',
+  'chang': '\u660c\u7316\u573a\u5c1d\u5e38\u957f\u507f\u80a0\u5382\u655e\u7545\u5531\u5021\u4f25\u9b2f\u82cc\u83d6\u5f9c\u6005\u60dd\u960a\u5a3c\u5ae6\u6636\u6c05\u9cb3',
+  'chao': '\u8d85\u6284\u949e\u671d\u5632\u6f6e\u5de2\u5435\u7092\u600a\u7ec9\u6641\u8016',
+  'che': '\u8f66\u626f\u64a4\u63a3\u5f7b\u6f88\u577c\u5c6e\u7817',
+  'chen': '\u90f4\u81e3\u8fb0\u5c18\u6668\u5ff1\u6c89\u9648\u8d81\u886c\u79f0\u8c0c\u62bb\u55d4\u5bb8\u741b\u6987\u809c\u80c2\u789c\u9f80',
+  'cheng': '\u6491\u57ce\u6a59\u6210\u5448\u4e58\u7a0b\u60e9\u6f84\u8bda\u627f\u901e\u9a8b\u79e4\u57d5\u5d4a\u5fb5\u6d48\u67a8\u67fd\u6a18\u665f\u584d\u77a0\u94d6\u88ce\u86cf\u9172',
+  'chi': '\u5403\u75f4\u6301\u5319\u6c60\u8fdf\u5f1b\u9a70\u803b\u9f7f\u4f88\u5c3a\u8d64\u7fc5\u65a5\u70bd\u50ba\u5880\u82aa\u830c\u640b\u53f1\u54e7\u557b\u55e4\u5f73\u996c\u6cb2\u5ab8\u6555\u80dd\u7719\u7735\u9e31\u761b\u892b\u86a9\u87ad\u7b1e\u7bea\u8c49\u8e05\u8e1f\u9b51',
+  'chong': '\u5145\u51b2\u866b\u5d07\u5ba0\u833a\u5fe1\u61a7\u94f3\u825f',
+  'chou': '\u62bd\u916c\u7574\u8e0c\u7a20\u6101\u7b79\u4ec7\u7ef8\u7785\u4e11\u4fe6\u5733\u5e31\u60c6\u6eb4\u59af\u7633\u96e0\u9c8b',
+  'chu': '\u81ed\u521d\u51fa\u6a71\u53a8\u8e87\u9504\u96cf\u6ec1\u9664\u695a\u7840\u50a8\u77d7\u6410\u89e6\u5904\u4e8d\u520d\u61b7\u7ecc\u6775\u696e\u6a17\u870d\u8e70\u9edc',
+  'chuan': '\u63e3\u5ddd\u7a7f\u693d\u4f20\u8239\u5598\u4e32\u63be\u821b\u60f4\u9044\u5ddb\u6c1a\u948f\u9569\u8221',
+  'chuang': '\u75ae\u7a97\u5e62\u5e8a\u95ef\u521b\u6006',
+  'chui': '\u5439\u708a\u6376\u9524\u5782\u9672\u68f0\u69cc',
+  'chun': '\u6625\u693f\u9187\u5507\u6df3\u7eaf\u8822\u4fc3\u83bc\u6c8c\u80ab\u6710\u9e51\u877d',
+  'chuo': '\u6233\u7ef0\u851f\u8fb6\u8f8d\u955e\u8e14\u9f8a',
+  'ci': '\u75b5\u8328\u78c1\u96cc\u8f9e\u6148\u74f7\u8bcd\u6b64\u523a\u8d50\u6b21\u8360\u5472\u5d6f\u9e5a\u8785\u7ccd\u8d91',
+  'cong': '\u806a\u8471\u56f1\u5306\u4ece\u4e1b\u506c\u82c1\u6dd9\u9aa2\u742e\u7481\u679e',
+  'cu': '\u51d1\u7c97\u918b\u7c07\u731d\u6b82\u8e59',
+  'cuan': '\u8e7f\u7be1\u7a9c\u6c46\u64ba\u6615\u7228',
+  'cui': '\u6467\u5d14\u50ac\u8106\u7601\u7cb9\u6dec\u7fe0\u8403\u60b4\u7480\u69b1\u96b9',
+  'cun': '\u6751\u5b58\u5bf8\u78cb\u5fd6\u76b4',
+  'cuo': '\u64ae\u6413\u63aa\u632b\u9519\u539d\u811e\u9509\u77ec\u75e4\u9e7e\u8e49\u8e9c',
+  'da': '\u642d\u8fbe\u7b54\u7629\u6253\u5927\u8037\u54d2\u55d2\u601b\u59b2\u75b8\u8921\u7b2a\u977c\u9791',
+  'dai': '\u5446\u6b79\u50a3\u6234\u5e26\u6b86\u4ee3\u8d37\u888b\u5f85\u902e\u6020\u57ed\u7519\u5454\u5cb1\u8fe8\u902f\u9a80\u7ed0\u73b3\u9edb',
+  'dan': '\u803d\u62c5\u4e39\u5355\u90f8\u63b8\u80c6\u65e6\u6c2e\u4f46\u60ee\u6de1\u8bde\u5f39\u86cb\u4ebb\u510b\u5369\u840f\u5556\u6fb9\u6a90\u6b9a\u8d55\u7708\u7605\u8043\u7baa',
+  'dang': '\u5f53\u6321\u515a\u8361\u6863\u8c20\u51fc\u83ea\u5b95\u7800\u94db\u88c6',
+  'dao': '\u5200\u6363\u8e48\u5012\u5c9b\u7977\u5bfc\u5230\u7a3b\u60bc\u9053\u76d7\u53e8\u5541\u5fc9\u6d2e\u6c18\u7118\u5fd1\u7e9b',
+  'de': '\u5fb7\u5f97\u7684\u951d',
+  'deng': '\u8e6c\u706f\u767b\u7b49\u77aa\u51f3\u9093\u5654\u5d9d\u6225\u78f4\u956b\u7c26',
+  'di': '\u5824\u4f4e\u6ef4\u8fea\u654c\u7b1b\u72c4\u6da4\u7fdf\u5ae1\u62b5\u5e95\u5730\u8482\u7b2c\u5e1d\u5f1f\u9012\u7f14\u6c10\u7c74\u8bcb\u8c1b\u90b8\u577b\u839c\u837b\u5600\u5a23\u67e2\u68e3\u89cc\u7825\u78b2\u7747\u955d\u7f9d\u9ab6',
+  'dian': '\u98a0\u6382\u6ec7\u7898\u70b9\u5178\u975b\u57ab\u7535\u4f43\u7538\u5e97\u60e6\u5960\u6dc0\u6bbf\u4e36\u963d\u576b\u57dd\u5dc5\u73b7\u765c\u766b\u7c1f\u8e2e',
+  'diao': '\u7889\u53fc\u96d5\u51cb\u5201\u6389\u540a\u9493\u8c03\u8f7a\u94de\u8729\u7c9c\u8c82',
+  'die': '\u8dcc\u7239\u789f\u8776\u8fed\u8c0d\u53e0\u4f5a\u57a4\u581e\u63f2\u558b\u6e2b\u8f76\u7252\u74de\u8936\u800b\u8e40\u9cbd\u9cce',
+  'ding': '\u4e01\u76ef\u53ee\u9489\u9876\u9f0e\u952d\u5b9a\u8ba2\u4e22\u4ec3\u5576\u738e\u815a\u7887\u753a\u94e4\u7594\u8035\u914a',
+  'dong': '\u4e1c\u51ac\u8463\u61c2\u52a8\u680b\u4f97\u606b\u51bb\u6d1e\u578c\u549a\u5cbd\u5cd2\u5902\u6c21\u80e8\u80f4\u7850\u9e2b',
+  'dou': '\u515c\u6296\u6597\u9661\u8c46\u9017\u75d8\u8538\u94ad\u7aa6\u7aac\u86aa\u7bfc\u9161',
+  'du': '\u90fd\u7763\u6bd2\u728a\u72ec\u8bfb\u5835\u7779\u8d4c\u675c\u9540\u809a\u5ea6\u6e21\u5992\u828f\u561f\u6e0e\u691f\u6a50\u724d\u8839\u7b03\u9ad1\u9ee9',
+  'duan': '\u7aef\u77ed\u953b\u6bb5\u65ad\u7f0e\u5f56\u6934\u7145\u7c16',
+  'dui': '\u5806\u5151\u961f\u5bf9\u603c\u619d\u7893',
+  'dun': '\u58a9\u5428\u8e72\u6566\u987f\u56e4\u949d\u76fe\u9041\u7096\u7818\u7905\u76f9\u9566\u8db8',
+  'duo': '\u6387\u54c6\u591a\u593a\u579b\u8eb2\u6735\u8dfa\u8235\u5241\u60f0\u5815\u5484\u54da\u7f0d\u67c1\u94ce\u88f0\u8e31',
+  'e': '\u86fe\u5ce8\u9e45\u4fc4\u989d\u8bb9\u5a25\u6076\u5384\u627c\u904f\u9102\u997f\u5669\u8c14\u57a9\u57ad\u82ca\u83aa\u843c\u5443\u6115\u5c59\u5a40\u8f6d\u66f7\u816d\u786a\u9507\u9537\u9e57\u989a\u9cc4',
+  'en': '\u6069\u84bd\u6441\u5514\u55ef',
+  'er': '\u800c\u513f\u8033\u5c14\u9975\u6d31\u4e8c\u8d30\u8fe9\u73e5\u94d2\u9e38\u9c95',
+  'fa': '\u53d1\u7f5a\u7b4f\u4f10\u4e4f\u9600\u6cd5\u73d0\u57a1\u781d',
+  'fan': '\u85e9\u5e06\u756a\u7ffb\u6a0a\u77fe\u9492\u7e41\u51e1\u70e6\u53cd\u8fd4\u8303\u8d29\u72af\u996d\u6cdb\u8629\u5e61\u72ad\u68b5\u6535\u71d4\u7548\u8e6f',
+  'fang': '\u574a\u82b3\u65b9\u80aa\u623f\u9632\u59a8\u4eff\u8bbf\u7eba\u653e\u531a\u90a1\u5f77\u94ab\u822b\u9c82',
+  'fei': '\u83f2\u975e\u5561\u98de\u80a5\u532a\u8bfd\u5420\u80ba\u5e9f\u6cb8\u8d39\u82be\u72d2\u60b1\u6ddd\u5983\u7ecb\u7eef\u69a7\u8153\u6590\u6249\u7953\u7829\u9544\u75f1\u871a\u7bda\u7fe1\u970f\u9cb1',
+  'fen': '\u82ac\u915a\u5429\u6c1b\u5206\u7eb7\u575f\u711a\u6c7e\u7c89\u594b\u4efd\u5fff\u6124\u7caa\u507e\u7035\u68fc\u610d\u9cbc\u9f22',
+  'feng': '\u4e30\u5c01\u67ab\u8702\u5cf0\u950b\u98ce\u75af\u70fd\u9022\u51af\u7f1d\u8bbd\u5949\u51e4\u4ff8\u9146\u8451\u6ca3\u781c',
+  'fu': '\u4f5b\u5426\u592b\u6577\u80a4\u5b75\u6276\u62c2\u8f90\u5e45\u6c1f\u7b26\u4f0f\u4fd8\u670d\u6d6e\u6daa\u798f\u88b1\u5f17\u752b\u629a\u8f85\u4fef\u91dc\u65a7\u812f\u8151\u5e9c\u8150\u8d74\u526f\u8986\u8d4b\u590d\u5085\u4ed8\u961c\u7236\u8179\u8d1f\u5bcc\u8ba3\u9644\u5987\u7f1a\u5490\u5310\u51eb\u90db\u8299\u82fb\u832f\u83a9\u83d4\u544b\u5e5e\u6ecf\u8274\u5b5a\u9a78\u7ec2\u6874\u8d59\u9efb\u9efc\u7f58\u7a03\u99a5\u864d\u86a8\u8709\u8760\u876e\u9eb8\u8dba\u8dd7\u9cc6',
+  'ga': '\u5676\u560e\u86e4\u5c2c\u5477\u5c15\u5c1c\u65ee\u9486',
+  'gai': '\u8be5\u6539\u6982\u9499\u76d6\u6e89\u4e10\u9654\u5793\u6224\u8d45\u80f2',
+  'gan': '\u5e72\u7518\u6746\u67d1\u7aff\u809d\u8d76\u611f\u79c6\u6562\u8d63\u5769\u82f7\u5c34\u64c0\u6cd4\u6de6\u6f89\u7ec0\u6a44\u65f0\u77f8\u75b3\u9150',
+  'gang': '\u5188\u521a\u94a2\u7f38\u809b\u7eb2\u5c97\u6e2f\u6206\u7f61\u9883\u7b7b',
+  'gong': '\u6760\u5de5\u653b\u529f\u606d\u9f9a\u4f9b\u8eac\u516c\u5bab\u5f13\u5de9\u6c5e\u62f1\u8d21\u5171\u857b\u5efe\u54a3\u73d9\u80b1\u86a3\u86e9\u89e5',
+  'gao': '\u7bd9\u768b\u9ad8\u818f\u7f94\u7cd5\u641e\u9550\u7a3f\u544a\u777e\u8bf0\u90dc\u84bf\u85c1\u7f1f\u69d4\u69c1\u6772\u9506',
+  'ge': '\u54e5\u6b4c\u6401\u6208\u9e3d\u80f3\u7599\u5272\u9769\u845b\u683c\u9601\u9694\u94ec\u4e2a\u5404\u9b32\u4ee1\u54ff\u5865\u55dd\u7ea5\u643f\u8188\u784c\u94ea\u9549\u88bc\u988c\u867c\u8238\u9abc\u9ac2',
+  'gei': '\u7ed9',
+  'gen': '\u6839\u8ddf\u4e98\u831b\u54cf\u826e',
+  'geng': '\u8015\u66f4\u5e9a\u7fb9\u57c2\u803f\u6897\u54fd\u8d53\u9ca0',
+  'gou': '\u94a9\u52fe\u6c9f\u82df\u72d7\u57a2\u6784\u8d2d\u591f\u4f5d\u8bdf\u5ca3\u9058\u5abe\u7f11\u89cf\u5f40\u9e32\u7b31\u7bdd\u97b2',
+  'gu': '\u8f9c\u83c7\u5495\u7b8d\u4f30\u6cbd\u5b64\u59d1\u9f13\u53e4\u86ca\u9aa8\u8c37\u80a1\u6545\u987e\u56fa\u96c7\u560f\u8bc2\u83f0\u54cc\u5d2e\u6c69\u688f\u8f71\u726f\u727f\u80cd\u81cc\u6bc2\u77bd\u7f5f\u94b4\u9522\u74e0\u9e2a\u9e44\u75fc\u86c4\u9164\u89da\u9cb4\u9ab0\u9e58',
+  'gua': '\u522e\u74dc\u5250\u5be1\u6302\u8902\u5366\u8bd6\u5471\u681d\u9e39',
+  'guai': '\u4e56\u62d0\u602a\u54d9',
+  'guan': '\u68fa\u5173\u5b98\u51a0\u89c2\u7ba1\u9986\u7f50\u60ef\u704c\u8d2f\u500c\u839e\u63bc\u6dab\u76e5\u9e73\u9ccf',
+  'guang': '\u5149\u5e7f\u901b\u72b7\u6844\u80f1\u7592',
+  'gui': '\u7470\u89c4\u572d\u7845\u5f52\u9f9f\u95fa\u8f68\u9b3c\u8be1\u7678\u6842\u67dc\u8dea\u8d35\u523d\u5326\u523f\u5e8b\u5b84\u59ab\u6867\u7085\u6677\u7688\u7c0b\u9c91\u9cdc',
+  'gun': '\u8f8a\u6eda\u68cd\u4e28\u886e\u7ef2\u78d9\u9ca7',
+  'guo': '\u9505\u90ed\u56fd\u679c\u88f9\u8fc7\u9998\u8803\u57da\u63b4\u5459\u56d7\u5e3c\u5d1e\u7313\u6901\u8662\u951e\u8052\u872e\u873e\u8748',
+  'ha': '\u54c8',
+  'hai': '\u9ab8\u5b69\u6d77\u6c26\u4ea5\u5bb3\u9a87\u54b4\u55e8\u988f\u91a2',
+  'han': '\u9163\u61a8\u90af\u97e9\u542b\u6db5\u5bd2\u51fd\u558a\u7f55\u7ff0\u64bc\u634d\u65f1\u61be\u608d\u710a\u6c57\u6c49\u9097\u83e1\u6496\u961a\u701a\u6657\u7113\u9894\u86b6\u9f3e',
+  'hen': '\u592f\u75d5\u5f88\u72e0\u6068',
+  'hang': '\u676d\u822a\u6c86\u7ed7\u73e9\u6841',
+  'hao': '\u58d5\u568e\u8c6a\u6beb\u90dd\u597d\u8017\u53f7\u6d69\u8585\u55e5\u5686\u6fe0\u704f\u660a\u7693\u98a2\u869d',
+  'he': '\u5475\u559d\u8377\u83cf\u6838\u79be\u548c\u4f55\u5408\u76d2\u8c89\u9602\u6cb3\u6db8\u8d6b\u8910\u9e64\u8d3a\u8bc3\u52be\u58d1\u85ff\u55d1\u55ec\u9616\u76cd\u86b5\u7fee',
+  'hei': '\u563f\u9ed1',
+  'heng': '\u54fc\u4ea8\u6a2a\u8861\u6052\u8a07\u8605',
+  'hong': '\u8f70\u54c4\u70d8\u8679\u9e3f\u6d2a\u5b8f\u5f18\u7ea2\u9ec9\u8ba7\u836d\u85a8\u95f3\u6cd3',
+  'hou': '\u5589\u4faf\u7334\u543c\u539a\u5019\u540e\u5820\u5f8c\u9005\u760a\u7bcc\u7cc7\u9c8e\u9aba',
+  'hu': '\u547c\u4e4e\u5ffd\u745a\u58f6\u846b\u80e1\u8774\u72d0\u7cca\u6e56\u5f27\u864e\u552c\u62a4\u4e92\u6caa\u6237\u51b1\u553f\u56eb\u5cb5\u7322\u6019\u60da\u6d52\u6ef9\u7425\u69f2\u8f77\u89f3\u70c0\u7173\u623d\u6248\u795c\u9e55\u9e71\u7b0f\u9190\u659b',
+  'hua': '\u82b1\u54d7\u534e\u733e\u6ed1\u753b\u5212\u5316\u8bdd\u5290\u6d4d\u9a85\u6866\u94e7\u7a1e',
+  'huai': '\u69d0\u5f8a\u6000\u6dee\u574f\u8fd8\u8e1d',
+  'huan': '\u6b22\u73af\u6853\u7f13\u6362\u60a3\u5524\u75ea\u8c62\u7115\u6da3\u5ba6\u5e7b\u90c7\u5942\u57b8\u64d0\u571c\u6d39\u6d63\u6f36\u5bf0\u902d\u7f33\u953e\u9ca9\u9b1f',
+  'huang': '\u8352\u614c\u9ec4\u78fa\u8757\u7c27\u7687\u51f0\u60f6\u714c\u6643\u5e4c\u604d\u8c0e\u968d\u5fa8\u6e5f\u6f62\u9051\u749c\u8093\u7640\u87e5\u7bc1\u9cc7',
+  'hui': '\u7070\u6325\u8f89\u5fbd\u6062\u86d4\u56de\u6bc1\u6094\u6167\u5349\u60e0\u6666\u8d3f\u79fd\u4f1a\u70e9\u6c47\u8bb3\u8bf2\u7ed8\u8bd9\u8334\u835f\u8559\u54d5\u5599\u96b3\u6d04\u5f57\u7f0b\u73f2\u6656\u605a\u867a\u87ea\u9ebe\u8886',
+  'hun': '\u8364\u660f\u5a5a\u9b42\u6d51\u6df7\u8be8\u9984\u960d\u6eb7\u7f17',
+  'huo': '\u8c41\u6d3b\u4f19\u706b\u83b7\u6216\u60d1\u970d\u8d27\u7978\u6509\u56af\u5925\u94ac\u952a\u956c\u8020\u8816',
+  'ji': '\u51fb\u573e\u57fa\u673a\u7578\u7a3d\u79ef\u7b95\u808c\u9965\u8ff9\u6fc0\u8ba5\u9e21\u59ec\u7ee9\u7f09\u5409\u6781\u68d8\u8f91\u7c4d\u96c6\u53ca\u6025\u75be\u6c72\u5373\u5ac9\u7ea7\u6324\u51e0\u810a\u5df1\u84df\u6280\u5180\u5b63\u4f0e\u796d\u5242\u60b8\u6d4e\u5bc4\u5bc2\u8ba1\u8bb0\u65e2\u5fcc\u9645\u5993\u7ee7\u7eaa\u5c45\u4e0c\u4e69\u525e\u4f76\u4f74\u8114\u58bc\u82a8\u82b0\u8401\u84ba\u857a\u638e\u53fd\u54ad\u54dc\u5527\u5c8c\u5d74\u6d0e\u5f50\u5c50\u9aa5\u757f\u7391\u696b\u6b9b\u621f\u6222\u8d4d\u89ca\u7284\u9f51\u77f6\u7f81\u5d47\u7a37\u7620\u7635\u866e\u7b08\u7b04\u66a8\u8dfb\u8dfd\u9701\u9c9a\u9cab\u9afb\u9e82',
+  'jia': '\u5609\u67b7\u5939\u4f73\u5bb6\u52a0\u835a\u988a\u8d3e\u7532\u94be\u5047\u7a3c\u4ef7\u67b6\u9a7e\u5ac1\u4f3d\u90cf\u62ee\u5cac\u6d43\u8fe6\u73c8\u621b\u80db\u605d\u94d7\u9553\u75c2\u86f1\u7b33\u8888\u8dcf',
+  'jian': '\u6b7c\u76d1\u575a\u5c16\u7b3a\u95f4\u714e\u517c\u80a9\u8270\u5978\u7f04\u8327\u68c0\u67ec\u78b1\u7877\u62e3\u6361\u7b80\u4fed\u526a\u51cf\u8350\u69db\u9274\u8df5\u8d31\u89c1\u952e\u7bad\u4ef6\u5065\u8230\u5251\u996f\u6e10\u6e85\u6da7\u5efa\u50ed\u8c0f\u8c2b\u83c5\u84b9\u641b\u56dd\u6e54\u8e47\u8b07\u7f23\u67a7\u67d9\u6957\u620b\u622c\u726e\u728d\u6bfd\u8171\u7751\u950f\u9e63\u88e5\u7b15\u7bb4\u7fe6\u8dbc\u8e3a\u9ca3\u97af',
+  'jiang': '\u50f5\u59dc\u5c06\u6d46\u6c5f\u7586\u848b\u6868\u5956\u8bb2\u5320\u9171\u964d\u8333\u6d1a\u7edb\u7f30\u729f\u7913\u8029\u7ce8\u8c47',
+  'jiao': '\u8549\u6912\u7901\u7126\u80f6\u4ea4\u90ca\u6d47\u9a84\u5a07\u56bc\u6405\u94f0\u77eb\u4fa5\u811a\u72e1\u89d2\u997a\u7f34\u7ede\u527f\u6559\u9175\u8f7f\u8f83\u53eb\u4f7c\u50ec\u832d\u6322\u564d\u5ce4\u5fbc\u59e3\u7e9f\u656b\u768e\u9e6a\u86df\u91ae\u8de4\u9c9b',
+  'jie': '\u7a96\u63ed\u63a5\u7686\u79f8\u8857\u9636\u622a\u52ab\u8282\u6854\u6770\u6377\u776b\u7aed\u6d01\u7ed3\u89e3\u59d0\u6212\u85c9\u82a5\u754c\u501f\u4ecb\u75a5\u8beb\u5c4a\u5048\u8ba6\u8bd8\u5588\u55df\u736c\u5a55\u5b51\u6840\u7352\u78a3\u9534\u7596\u88b7\u9889\u86a7\u7faf\u9c92\u9ab1\u9aeb',
+  'jin': '\u5dfe\u7b4b\u65a4\u91d1\u4eca\u6d25\u895f\u7d27\u9526\u4ec5\u8c28\u8fdb\u9773\u664b\u7981\u8fd1\u70ec\u6d78\u5c3d\u537a\u8369\u5807\u5664\u9991\u5ed1\u5997\u7f19\u747e\u69ff\u8d46\u89d0\u9485\u9513\u887f\u77dc',
+  'jing': '\u52b2\u8346\u5162\u830e\u775b\u6676\u9cb8\u4eac\u60ca\u7cbe\u7cb3\u7ecf\u4e95\u8b66\u666f\u9888\u9759\u5883\u656c\u955c\u5f84\u75c9\u9756\u7adf\u7ade\u51c0\u522d\u5106\u9631\u83c1\u734d\u61ac\u6cfe\u8ff3\u5f2a\u5a67\u80bc\u80eb\u8148\u65cc',
+  'jiong': '\u70af\u7a98\u5182\u8fe5\u6243',
+  'jiu': '\u63ea\u7a76\u7ea0\u7396\u97ed\u4e45\u7078\u4e5d\u9152\u53a9\u6551\u65e7\u81fc\u8205\u548e\u5c31\u759a\u50e6\u557e\u9604\u67e9\u6855\u9e6b\u8d73\u9b0f',
+  'ju': '\u97a0\u62d8\u72d9\u75bd\u9a79\u83ca\u5c40\u5480\u77e9\u4e3e\u6cae\u805a\u62d2\u636e\u5de8\u5177\u8ddd\u8e1e\u952f\u4ff1\u53e5\u60e7\u70ac\u5267\u5028\u8bb5\u82e3\u82f4\u8392\u63ac\u907d\u5c66\u741a\u67b8\u6910\u6998\u6989\u6a58\u728b\u98d3\u949c\u9514\u7aad\u88fe\u8d84\u91b5\u8e3d\u9f83\u96ce\u97ab',
+  'juan': '\u6350\u9e43\u5a1f\u5026\u7737\u5377\u7ee2\u9104\u72f7\u6d93\u684a\u8832\u9529\u954c\u96bd',
+  'jue': '\u6485\u652b\u6289\u6398\u5014\u7235\u89c9\u51b3\u8bc0\u7edd\u53a5\u5282\u8c32\u77cd\u8568\u5658\u5d1b\u7357\u5b53\u73cf\u6877\u6a5b\u721d\u9562\u8e76\u89d6',
+  'jun': '\u5747\u83cc\u94a7\u519b\u541b\u5cfb\u4fca\u7ae3\u6d5a\u90e1\u9a8f\u6343\u72fb\u76b2\u7b60\u9e87',
+  'ka': '\u5580\u5496\u5361\u4f67\u5494\u80e9',
+  'ke': '\u54af\u5777\u82db\u67ef\u68f5\u78d5\u9897\u79d1\u58f3\u54b3\u53ef\u6e34\u514b\u523b\u5ba2\u8bfe\u5ca2\u606a\u6e98\u9a92\u7f02\u73c2\u8f72\u6c2a\u778c\u94b6\u75b4\u7aa0\u874c\u9ac1',
+  'kai': '\u5f00\u63e9\u6977\u51ef\u6168\u5240\u57b2\u8488\u5ffe\u607a\u94e0\u950e',
+  'kan': '\u520a\u582a\u52d8\u574e\u780d\u770b\u4f83\u51f5\u83b0\u83b6\u6221\u9f9b\u77b0',
+  'kang': '\u5eb7\u6177\u7ce0\u625b\u6297\u4ea2\u7095\u5751\u4f09\u95f6\u94aa',
+  'kao': '\u8003\u62f7\u70e4\u9760\u5c3b\u6832\u7292\u94d0',
+  'ken': '\u80af\u5543\u57a6\u6073\u57a0\u88c9\u9880',
+  'keng': '\u542d\u5fd0\u94ff',
+  'kong': '\u7a7a\u6050\u5b54\u63a7\u5025\u5d06\u7b9c',
+  'kou': '\u62a0\u53e3\u6263\u5bc7\u82a4\u853b\u53e9\u770d\u7b58',
+  'ku': '\u67af\u54ed\u7a9f\u82e6\u9177\u5e93\u88e4\u5233\u5800\u55be\u7ed4\u9ab7',
+  'kua': '\u5938\u57ae\u630e\u8de8\u80ef\u4f89',
+  'kuai': '\u5757\u7b77\u4fa9\u5feb\u84af\u90d0\u8489\u72ef\u810d',
+  'kuan': '\u5bbd\u6b3e\u9acb',
+  'kuang': '\u5321\u7b50\u72c2\u6846\u77ff\u7736\u65f7\u51b5\u8bd3\u8bf3\u909d\u5739\u593c\u54d0\u7ea9\u8d36',
+  'kui': '\u4e8f\u76d4\u5cbf\u7aa5\u8475\u594e\u9b41\u5080\u9988\u6127\u6e83\u9997\u532e\u5914\u9697\u63c6\u55b9\u559f\u609d\u6126\u9615\u9035\u668c\u777d\u8069\u8770\u7bd1\u81fe\u8dec',
+  'kun': '\u5764\u6606\u6346\u56f0\u6083\u9603\u7428\u951f\u918c\u9cb2\u9ae1',
+  'kuo': '\u62ec\u6269\u5ed3\u9614\u86de',
+  'la': '\u5783\u62c9\u5587\u8721\u814a\u8fa3\u5566\u524c\u647a\u908b\u65ef\u782c\u760c',
+  'lai': '\u83b1\u6765\u8d56\u5d03\u5f95\u6d9e\u6fd1\u8d49\u7750\u94fc\u765e\u7c41',
+  'lan': '\u84dd\u5a6a\u680f\u62e6\u7bee\u9611\u5170\u6f9c\u8c30\u63fd\u89c8\u61d2\u7f06\u70c2\u6ee5\u5549\u5c9a\u61d4\u6f24\u6984\u6593\u7f71\u9567\u8934',
+  'lang': '\u7405\u6994\u72fc\u5eca\u90ce\u6717\u6d6a\u83a8\u8497\u5577\u9606\u9512\u7a02\u8782',
+  'lao': '\u635e\u52b3\u7262\u8001\u4f6c\u59e5\u916a\u70d9\u6d9d\u5520\u5d02\u6833\u94d1\u94f9\u75e8\u91aa',
+  'le': '\u52d2\u4e50\u808b\u4ec2\u53fb\u561e\u6cd0\u9cd3',
+  'lei': '\u96f7\u956d\u857e\u78ca\u7d2f\u5121\u5792\u64c2\u7c7b\u6cea\u7fb8\u8bd4\u837d\u54a7\u6f2f\u5ad8\u7f27\u6a91\u8012\u9179',
+  'ling': '\u68f1\u51b7\u62ce\u73b2\u83f1\u96f6\u9f84\u94c3\u4f36\u7f9a\u51cc\u7075\u9675\u5cad\u9886\u53e6\u4ee4\u9143\u5844\u82d3\u5464\u56f9\u6ce0\u7eeb\u67c3\u68c2\u74f4\u8046\u86c9\u7fce\u9cae',
+  'leng': '\u695e\u6123',
+  'li': '\u5398\u68a8\u7281\u9ece\u7bf1\u72f8\u79bb\u6f13\u7406\u674e\u91cc\u9ca4\u793c\u8389\u8354\u540f\u6817\u4e3d\u5389\u52b1\u783e\u5386\u5229\u5088\u4f8b\u4fd0\u75e2\u7acb\u7c92\u6ca5\u96b6\u529b\u7483\u54e9\u4fea\u4fda\u90e6\u575c\u82c8\u8385\u84e0\u85dc\u6369\u5456\u5533\u55b1\u7301\u6ea7\u6fa7\u9026\u5a0c\u5ae0\u9a8a\u7f21\u73de\u67a5\u680e\u8f79\u623e\u783a\u8a48\u7f79\u9502\u9e42\u75a0\u75ac\u86ce\u870a\u8821\u7b20\u7be5\u7c9d\u91b4\u8dde\u96f3\u9ca1\u9ce2\u9ee7',
+  'lian': '\u4fe9\u8054\u83b2\u8fde\u9570\u5ec9\u601c\u6d9f\u5e18\u655b\u8138\u94fe\u604b\u70bc\u7ec3\u631b\u8539\u5941\u6f4b\u6fc2\u5a08\u740f\u695d\u6b93\u81c1\u81a6\u88e2\u880a\u9ca2',
+  'liang': '\u7cae\u51c9\u6881\u7cb1\u826f\u4e24\u8f86\u91cf\u667e\u4eae\u8c05\u589a\u690b\u8e09\u9753\u9b49',
+  'liao': '\u64a9\u804a\u50da\u7597\u71ce\u5be5\u8fbd\u6f66\u4e86\u6482\u9563\u5ed6\u6599\u84fc\u5c25\u5639\u7360\u5bee\u7f2d\u948c\u9e69\u8022',
+  'lie': '\u5217\u88c2\u70c8\u52a3\u730e\u51bd\u57d2\u6d0c\u8d94\u8e90\u9b23',
+  'lin': '\u7433\u6797\u78f7\u9716\u4e34\u90bb\u9cde\u6dcb\u51db\u8d41\u541d\u853a\u5d99\u5eea\u9074\u6aa9\u8f9a\u77b5\u7cbc\u8e8f\u9e9f',
+  'liu': '\u6e9c\u7409\u69b4\u786b\u998f\u7559\u5218\u7624\u6d41\u67f3\u516d\u62a1\u507b\u848c\u6cd6\u6d4f\u905b\u9a9d\u7efa\u65d2\u7198\u950d\u954f\u9e68\u938f',
+  'long': '\u9f99\u804b\u5499\u7b3c\u7abf\u9686\u5784\u62e2\u9647\u5f04\u5785\u830f\u6cf7\u73d1\u680a\u80e7\u783b\u7643',
+  'lou': '\u697c\u5a04\u6402\u7bd3\u6f0f\u964b\u55bd\u5d5d\u9542\u7618\u8027\u877c\u9ac5',
+  'lu': '\u82a6\u5362\u9885\u5e90\u7089\u63b3\u5364\u864f\u9c81\u9e93\u788c\u9732\u8def\u8d42\u9e7f\u6f5e\u7984\u5f55\u9646\u622e\u5786\u6445\u64b8\u565c\u6cf8\u6e0c\u6f09\u7490\u680c\u6a79\u8f73\u8f82\u8f98\u6c07\u80ea\u9565\u9e2c\u9e6d\u7c0f\u823b\u9c88',
+  'lv': '\u9a74\u5415\u94dd\u4fa3\u65c5\u5c65\u5c61\u7f15\u8651\u6c2f\u5f8b\u7387\u6ee4\u7eff\u634b\u95fe\u6988\u8182\u7a06\u891b',
+  'luan': '\u5ce6\u5b6a\u6ee6\u5375\u4e71\u683e\u9e3e\u92ae',
+  'lue': '\u63a0\u7565\u950a',
+  'lun': '\u8f6e\u4f26\u4ed1\u6ca6\u7eb6\u8bba\u56f5',
+  'luo': '\u841d\u87ba\u7f57\u903b\u9523\u7ba9\u9aa1\u88f8\u843d\u6d1b\u9a86\u7edc\u502e\u8366\u645e\u7321\u6cfa\u6924\u8136\u9559\u7630\u96d2',
+  'ma': '\u5988\u9ebb\u739b\u7801\u8682\u9a6c\u9a82\u561b\u5417\u551b\u72b8\u5b37\u6769\u9ebd',
+  'mai': '\u57cb\u4e70\u9ea6\u5356\u8fc8\u8109\u52a2\u836c\u54aa\u973e',
+  'man': '\u7792\u9992\u86ee\u6ee1\u8513\u66fc\u6162\u6f2b\u8c29\u5881\u5e54\u7f26\u71b3\u9558\u989f\u87a8\u9cd7\u9794',
+  'mang': '\u8292\u832b\u76f2\u5fd9\u83bd\u9099\u6f2d\u6726\u786d\u87d2',
+  'meng': '\u6c13\u840c\u8499\u6aac\u76df\u9530\u731b\u68a6\u5b5f\u52d0\u750d\u77a2\u61f5\u791e\u867b\u8722\u8813\u824b\u8268\u9efe',
+  'miao': '\u732b\u82d7\u63cf\u7784\u85d0\u79d2\u6e3a\u5e99\u5999\u55b5\u9088\u7f08\u7f2a\u676a\u6dfc\u7707\u9e4b\u8731',
+  'mao': '\u8305\u951a\u6bdb\u77db\u94c6\u536f\u8302\u5192\u5e3d\u8c8c\u8d38\u4f94\u88a4\u52d6\u8306\u5cc1\u7441\u6634\u7266\u8004\u65c4\u61cb\u7780\u86d1\u8765\u87ca\u9ae6',
+  'me': '\u4e48',
+  'mei': '\u73ab\u679a\u6885\u9176\u9709\u7164\u6ca1\u7709\u5a92\u9541\u6bcf\u7f8e\u6627\u5bd0\u59b9\u5a9a\u5776\u8393\u5d4b\u7338\u6d7c\u6e44\u6963\u9545\u9e5b\u8882\u9b45',
+  'men': '\u95e8\u95f7\u4eec\u626a\u739f\u7116\u61d1\u9494',
+  'mi': '\u772f\u919a\u9761\u7cdc\u8ff7\u8c1c\u5f25\u7c73\u79d8\u89c5\u6ccc\u871c\u5bc6\u5e42\u8288\u5196\u8c27\u863c\u5627\u7315\u736f\u6c68\u5b93\u5f2d\u8112\u6549\u7cf8\u7e3b\u9e8b',
+  'mian': '\u68c9\u7720\u7ef5\u5195\u514d\u52c9\u5a29\u7f05\u9762\u6c94\u6e4e\u817c\u7704',
+  'mie': '\u8511\u706d\u54a9\u881b\u7bfe',
+  'min': '\u6c11\u62bf\u76bf\u654f\u60af\u95fd\u82e0\u5cb7\u95f5\u6cef\u73c9',
+  'ming': '\u660e\u879f\u9e23\u94ed\u540d\u547d\u51a5\u8317\u6e9f\u669d\u7791\u9169',
+  'miu': '\u8c2c',
+  'mo': '\u6478\u6479\u8611\u6a21\u819c\u78e8\u6469\u9b54\u62b9\u672b\u83ab\u58a8\u9ed8\u6cab\u6f20\u5bde\u964c\u8c1f\u8309\u84e6\u998d\u5aeb\u9546\u79e3\u763c\u8031\u87c6\u8c8a\u8c98',
+  'mou': '\u8c0b\u725f\u67d0\u53b6\u54de\u5a7a\u7738\u936a',
+  'mu': '\u62c7\u7261\u4ea9\u59c6\u6bcd\u5893\u66ae\u5e55\u52df\u6155\u6728\u76ee\u7766\u7267\u7a46\u4eeb\u82dc\u5452\u6c90\u6bea\u94bc',
+  'na': '\u62ff\u54ea\u5450\u94a0\u90a3\u5a1c\u7eb3\u5185\u637a\u80ad\u954e\u8872\u7bac',
+  'nai': '\u6c16\u4e43\u5976\u8010\u5948\u9f10\u827f\u8418\u67f0',
+  'nan': '\u5357\u7537\u96be\u56ca\u5583\u56e1\u6960\u8169\u877b\u8d67',
+  'nao': '\u6320\u8111\u607c\u95f9\u5b6c\u57b4\u7331\u7459\u7847\u94d9\u86f2',
+  'ne': '\u6dd6\u5462\u8bb7',
+  'nei': '\u9981',
+  'nen': '\u5ae9\u80fd\u6798\u6041',
+  'ni': '\u59ae\u9713\u502a\u6ce5\u5c3c\u62df\u4f60\u533f\u817b\u9006\u6eba\u4f32\u576d\u730a\u6029\u6ee0\u6635\u65ce\u7962\u615d\u7768\u94cc\u9cb5',
+  'nian': '\u852b\u62c8\u5e74\u78be\u64b5\u637b\u5ff5\u5eff\u8f87\u9ecf\u9c87\u9cb6',
+  'niang': '\u5a18\u917f',
+  'niao': '\u9e1f\u5c3f\u8311\u5b32\u8132\u8885',
+  'nie': '\u634f\u8042\u5b7d\u556e\u954a\u954d\u6d85\u4e5c\u9667\u8616\u55eb\u8080\u989e\u81ec\u8e51',
+  'nin': '\u60a8\u67e0',
+  'ning': '\u72de\u51dd\u5b81\u62e7\u6cde\u4f5e\u84e5\u549b\u752f\u804d',
+  'niu': '\u725b\u626d\u94ae\u7ebd\u72c3\u5ff8\u599e\u86b4',
+  'nong': '\u8113\u6d53\u519c\u4fac',
+  'nu': '\u5974\u52aa\u6012\u5476\u5e11\u5f29\u80ec\u5b65\u9a7d',
+  'nv': '\u5973\u6067\u9495\u8844',
+  'nuan': '\u6696',
+  'nuenue': '\u8650',
+  'nue': '\u759f\u8c11',
+  'nuo': '\u632a\u61e6\u7cef\u8bfa\u50a9\u6426\u558f\u9518',
+  'ou': '\u54e6\u6b27\u9e25\u6bb4\u85d5\u5455\u5076\u6ca4\u6004\u74ef\u8026',
+  'pa': '\u556a\u8db4\u722c\u5e15\u6015\u7436\u8469\u7b62',
+  'pai': '\u62cd\u6392\u724c\u5f98\u6e43\u6d3e\u4ff3\u848e',
+  'pan': '\u6500\u6f58\u76d8\u78d0\u76fc\u7554\u5224\u53db\u723f\u6cee\u88a2\u897b\u87e0\u8e52',
+  'pang': '\u4e53\u5e9e\u65c1\u802a\u80d6\u6ec2\u9004',
+  'pao': '\u629b\u5486\u5228\u70ae\u888d\u8dd1\u6ce1\u530f\u72cd\u5e96\u812c\u75b1',
+  'pei': '\u5478\u80da\u57f9\u88f4\u8d54\u966a\u914d\u4f69\u6c9b\u638a\u8f94\u5e14\u6de0\u65c6\u952b\u9185\u9708',
+  'pen': '\u55b7\u76c6\u6e53',
+  'peng': '\u7830\u62a8\u70f9\u6f8e\u5f6d\u84ec\u68da\u787c\u7bf7\u81a8\u670b\u9e4f\u6367\u78b0\u576f\u580b\u562d\u6026\u87db',
+  'pi': '\u7812\u9739\u6279\u62ab\u5288\u7435\u6bd7\u5564\u813e\u75b2\u76ae\u5339\u75de\u50fb\u5c41\u8b6c\u4e15\u9674\u90b3\u90eb\u572e\u9f19\u64d7\u567c\u5e80\u5ab2\u7eb0\u6787\u7513\u7765\u7f74\u94cd\u75e6\u7656\u758b\u868d\u8c94',
+  'pian': '\u7bc7\u504f\u7247\u9a97\u8c1d\u9a88\u728f\u80fc\u890a\u7fe9\u8e41',
+  'piao': '\u98d8\u6f02\u74e2\u7968\u527d\u560c\u5ad6\u7f25\u6b8d\u779f\u87b5',
+  'pie': '\u6487\u77a5\u4e3f\u82e4\u6c15',
+  'pin': '\u62fc\u9891\u8d2b\u54c1\u8058\u62da\u59d8\u5ad4\u6980\u725d\u98a6',
+  'ping': '\u4e52\u576a\u82f9\u840d\u5e73\u51ed\u74f6\u8bc4\u5c4f\u4fdc\u5a09\u67b0\u9c86',
+  'po': '\u5761\u6cfc\u9887\u5a46\u7834\u9b44\u8feb\u7c95\u53f5\u9131\u6ea5\u73c0\u948b\u94b7\u76a4\u7b38',
+  'pou': '\u5256\u88d2\u8e23',
+  'pu': '\u6251\u94fa\u4ec6\u8386\u8461\u83e9\u84b2\u57d4\u6734\u5703\u666e\u6d66\u8c31\u66dd\u7011\u530d\u5657\u6fee\u749e\u6c06\u9564\u9568\u8e7c',
+  'qi': '\u671f\u6b3a\u6816\u621a\u59bb\u4e03\u51c4\u6f06\u67d2\u6c8f\u5176\u68cb\u5947\u6b67\u7566\u5d0e\u8110\u9f50\u65d7\u7948\u7941\u9a91\u8d77\u5c82\u4e5e\u4f01\u542f\u5951\u780c\u5668\u6c14\u8fc4\u5f03\u6c7d\u6ce3\u8bab\u4e9f\u4e93\u573b\u8291\u840b\u847a\u5601\u5c7a\u5c90\u6c54\u6dc7\u9a90\u7eee\u742a\u7426\u675e\u6864\u69ed\u6b39\u797a\u61a9\u789b\u86f4\u871e\u7da6\u7dae\u8dbf\u8e4a\u9ccd\u9e92',
+  'qia': '\u6390\u6070\u6d3d\u845c',
+  'qian': '\u7275\u6266\u948e\u94c5\u5343\u8fc1\u7b7e\u4edf\u8c26\u4e7e\u9ed4\u94b1\u94b3\u524d\u6f5c\u9063\u6d45\u8c34\u5811\u5d4c\u6b20\u6b49\u4f65\u9621\u828a\u82a1\u8368\u63ae\u5c8d\u60ad\u614a\u9a9e\u6434\u8930\u7f31\u6920\u80b7\u6106\u94a4\u8654\u7b9d',
+  'qiang': '\u67aa\u545b\u8154\u7f8c\u5899\u8537\u5f3a\u62a2\u5af1\u6a2f\u6217\u709d\u9516\u9535\u956a\u8941\u8723\u7f9f\u8deb\u8dc4',
+  'qiao': '\u6a47\u9539\u6572\u6084\u6865\u77a7\u4e54\u4fa8\u5de7\u9798\u64ac\u7fd8\u5ced\u4fcf\u7a8d\u5281\u8bee\u8c2f\u835e\u6100\u6194\u7f32\u6a35\u6bf3\u7857\u8df7\u9792',
+  'qie': '\u5207\u8304\u4e14\u602f\u7a83\u90c4\u553c\u60ec\u59be\u6308\u9532\u7ba7',
+  'qin': '\u94a6\u4fb5\u4eb2\u79e6\u7434\u52e4\u82b9\u64d2\u79bd\u5bdd\u6c81\u82a9\u84c1\u8572\u63ff\u5423\u55ea\u5659\u6eb1\u6a8e\u8793\u887e',
+  'qing': '\u9752\u8f7b\u6c22\u503e\u537f\u6e05\u64ce\u6674\u6c30\u60c5\u9877\u8bf7\u5e86\u5029\u82d8\u570a\u6aa0\u78ec\u873b\u7f44\u7b90\u8b26\u9cad\u9ee5',
+  'qiong': '\u743c\u7a77\u909b\u8315\u7a79\u7b47\u928e',
+  'qiu': '\u79cb\u4e18\u90b1\u7403\u6c42\u56da\u914b\u6cc5\u4fc5\u6c3d\u5def\u827d\u72b0\u6e6b\u9011\u9052\u6978\u8d47\u9e20\u866c\u86af\u8764\u88d8\u7cd7\u9cc5\u9f3d',
+  'qu': '\u8d8b\u533a\u86c6\u66f2\u8eaf\u5c48\u9a71\u6e20\u53d6\u5a36\u9f8b\u8da3\u53bb\u8bce\u52ac\u8556\u8627\u5c96\u8862\u9612\u74a9\u89d1\u6c0d\u795b\u78f2\u766f\u86d0\u883c\u9eb4\u77bf\u9ee2',
+  'quan': '\u5708\u98a7\u6743\u919b\u6cc9\u5168\u75ca\u62f3\u72ac\u5238\u529d\u8be0\u8343\u737e\u609b\u7efb\u8f81\u754e\u94e8\u8737\u7b4c\u9b08',
+  'que': '\u7f3a\u7094\u7638\u5374\u9e4a\u69b7\u786e\u96c0\u9619\u60ab',
+  'qun': '\u88d9\u7fa4\u9021',
+  'ran': '\u7136\u71c3\u5189\u67d3\u82d2\u9aef',
+  'rang': '\u74e4\u58e4\u6518\u56b7\u8ba9\u79b3\u7a70',
+  'rao': '\u9976\u6270\u7ed5\u835b\u5a06\u6861',
+  'ruo': '\u60f9\u82e5\u5f31',
+  're': '\u70ed\u504c',
+  'ren': '\u58ec\u4ec1\u4eba\u5fcd\u97e7\u4efb\u8ba4\u5203\u598a\u7eab\u4ede\u834f\u845a\u996a\u8f6b\u7a14\u887d',
+  'reng': '\u6254\u4ecd',
+  'ri': '\u65e5',
+  'rong': '\u620e\u8338\u84c9\u8363\u878d\u7194\u6eb6\u5bb9\u7ed2\u5197\u5d58\u72e8\u7f1b\u6995\u877e',
+  'rou': '\u63c9\u67d4\u8089\u7cc5\u8e42\u97a3',
+  'ru': '\u8339\u8815\u5112\u5b7a\u5982\u8fb1\u4e73\u6c5d\u5165\u8925\u84d0\u85b7\u5685\u6d33\u6ebd\u6fe1\u94f7\u8966\u98a5',
+  'ruan': '\u8f6f\u962e\u670a',
+  'rui': '\u854a\u745e\u9510\u82ae\u8564\u777f\u868b',
+  'run': '\u95f0\u6da6',
+  'sa': '\u6492\u6d12\u8428\u5345\u4ee8\u6332\u98d2',
+  'sai': '\u816e\u9cc3\u585e\u8d5b\u567b',
+  'san': '\u4e09\u53c1\u4f1e\u6563\u5f61\u9993\u6c35\u6bf5\u7cc1\u9730',
+  'sang': '\u6851\u55d3\u4e27\u6421\u78c9\u98a1',
+  'sao': '\u6414\u9a9a\u626b\u5ac2\u57fd\u81ca\u7619\u9ccb',
+  'se': '\u745f\u8272\u6da9\u556c\u94e9\u94ef\u7a51',
+  'sen': '\u68ee',
+  'seng': '\u50e7',
+  'sha': '\u838e\u7802\u6740\u5239\u6c99\u7eb1\u50bb\u5565\u715e\u810e\u6b43\u75e7\u88df\u970e\u9ca8',
+  'shai': '\u7b5b\u6652\u917e',
+  'shan': '\u73ca\u82eb\u6749\u5c71\u5220\u717d\u886b\u95ea\u9655\u64c5\u8d61\u81b3\u5584\u6c55\u6247\u7f2e\u5261\u8baa\u912f\u57cf\u829f\u6f78\u59d7\u9a9f\u81bb\u9490\u759d\u87ee\u8222\u8dda\u9cdd',
+  'shang': '\u5892\u4f24\u5546\u8d4f\u664c\u4e0a\u5c1a\u88f3\u57a7\u7ef1\u6b87\u71b5\u89de',
+  'shao': '\u68a2\u634e\u7a0d\u70e7\u828d\u52fa\u97f6\u5c11\u54e8\u90b5\u7ecd\u52ad\u82d5\u6f72\u86f8\u7b24\u7b72\u8244',
+  'she': '\u5962\u8d4a\u86c7\u820c\u820d\u8d66\u6444\u5c04\u6151\u6d89\u793e\u8bbe\u538d\u4f58\u731e\u7572\u9e9d',
+  'shen': '\u7837\u7533\u547b\u4f38\u8eab\u6df1\u5a20\u7ec5\u795e\u6c88\u5ba1\u5a76\u751a\u80be\u614e\u6e17\u8bdc\u8c02\u5432\u54c2\u6e16\u6939\u77e7\u8703',
+  'sheng': '\u58f0\u751f\u7525\u7272\u5347\u7ef3\u7701\u76db\u5269\u80dc\u5723\u4e1e\u6e11\u5ab5\u771a\u7b19',
+  'shi': '\u5e08\u5931\u72ee\u65bd\u6e7f\u8bd7\u5c38\u8671\u5341\u77f3\u62fe\u65f6\u4ec0\u98df\u8680\u5b9e\u8bc6\u53f2\u77e2\u4f7f\u5c4e\u9a76\u59cb\u5f0f\u793a\u58eb\u4e16\u67ff\u4e8b\u62ed\u8a93\u901d\u52bf\u662f\u55dc\u566c\u9002\u4ed5\u4f8d\u91ca\u9970\u6c0f\u5e02\u6043\u5ba4\u89c6\u8bd5\u8c25\u57d8\u83b3\u84cd\u5f11\u5511\u9963\u8f7c\u8006\u8d33\u70bb\u793b\u94c8\u94ca\u87ab\u8210\u7b6e\u8c55\u9ca5\u9cba',
+  'shou': '\u6536\u624b\u9996\u5b88\u5bff\u6388\u552e\u53d7\u7626\u517d\u624c\u72e9\u7ef6\u824f',
+  'shu': '\u852c\u67a2\u68b3\u6b8a\u6292\u8f93\u53d4\u8212\u6dd1\u758f\u4e66\u8d4e\u5b70\u719f\u85af\u6691\u66d9\u7f72\u8700\u9ecd\u9f20\u5c5e\u672f\u8ff0\u6811\u675f\u620d\u7ad6\u5885\u5eb6\u6570\u6f31\u6055\u500f\u587e\u83fd\u5fc4\u6cad\u6d91\u6f8d\u59dd\u7ebe\u6bf9\u8167\u6bb3\u956f\u79eb\u9e6c',
+  'shua': '\u5237\u800d\u5530\u6dae',
+  'shuai': '\u6454\u8870\u7529\u5e05\u87c0',
+  'shuan': '\u6813\u62f4\u95e9',
+  'shuang': '\u971c\u53cc\u723d\u5b40',
+  'shui': '\u8c01\u6c34\u7761\u7a0e',
+  'shun': '\u542e\u77ac\u987a\u821c\u6042',
+  'shuo': '\u8bf4\u7855\u6714\u70c1\u84b4\u6420\u55cd\u6fef\u5981\u69ca\u94c4',
+  'si': '\u65af\u6495\u5636\u601d\u79c1\u53f8\u4e1d\u6b7b\u8086\u5bfa\u55e3\u56db\u4f3a\u4f3c\u9972\u5df3\u53ae\u4fdf\u5155\u83e5\u549d\u6c5c\u6cd7\u6f8c\u59d2\u9a77\u7f0c\u7940\u7960\u9536\u9e36\u801c\u86f3\u7b25',
+  'song': '\u677e\u8038\u6002\u9882\u9001\u5b8b\u8bbc\u8bf5\u51c7\u83d8\u5d27\u5d69\u5fea\u609a\u6dde\u7ae6',
+  'sou': '\u641c\u8258\u64de\u55fd\u53df\u55d6\u55fe\u998a\u6eb2\u98d5\u778d\u953c\u878b',
+  'su': '\u82cf\u9165\u4fd7\u7d20\u901f\u7c9f\u50f3\u5851\u6eaf\u5bbf\u8bc9\u8083\u5919\u8c21\u850c\u55c9\u612b\u7c0c\u89eb\u7a23',
+  'suan': '\u9178\u849c\u7b97',
+  'sui': '\u867d\u968b\u968f\u7ee5\u9ad3\u788e\u5c81\u7a57\u9042\u96a7\u795f\u84d1\u51ab\u8c07\u6fc9\u9083\u71e7\u772d\u7762',
+  'sun': '\u5b59\u635f\u7b0b\u836a\u72f2\u98e7\u69ab\u8de3\u96bc',
+  'suo': '\u68ad\u5506\u7f29\u7410\u7d22\u9501\u6240\u5522\u55e6\u5a11\u686b\u7743\u7fa7',
+  'ta': '\u584c\u4ed6\u5b83\u5979\u5854\u736d\u631e\u8e4b\u8e0f\u95fc\u6ebb\u9062\u69bb\u6c93',
+  'tai': '\u80ce\u82d4\u62ac\u53f0\u6cf0\u915e\u592a\u6001\u6c70\u90b0\u85b9\u80bd\u70b1\u949b\u8dc6\u9c90',
+  'tan': '\u574d\u644a\u8d2a\u762b\u6ee9\u575b\u6a80\u75f0\u6f6d\u8c2d\u8c08\u5766\u6bef\u8892\u78b3\u63a2\u53f9\u70ad\u90ef\u8548\u6619\u94bd\u952c\u8983',
+  'tang': '\u6c64\u5858\u642a\u5802\u68e0\u819b\u5510\u7cd6\u50a5\u9967\u6e8f\u746d\u94f4\u9557\u8025\u8797\u87b3\u7fb0\u91a3',
+  'thang': '\u5018\u8eba\u6dcc',
+  'theng': '\u8d9f\u70eb',
+  'tao': '\u638f\u6d9b\u6ed4\u7ee6\u8404\u6843\u9003\u6dd8\u9676\u8ba8\u5957\u6311\u9f17\u5555\u97ec\u9955',
+  'te': '\u7279',
+  'teng': '\u85e4\u817e\u75bc\u8a8a\u6ed5',
+  'ti': '\u68af\u5254\u8e22\u9511\u63d0\u9898\u8e44\u557c\u4f53\u66ff\u568f\u60d5\u6d95\u5243\u5c49\u8351\u608c\u9016\u7ee8\u7f07\u9e48\u88fc\u918d',
+  'tian': '\u5929\u6dfb\u586b\u7530\u751c\u606c\u8214\u8146\u63ad\u5fdd\u9617\u6b84\u754b\u94bf\u86ba',
+  'tiao': '\u6761\u8fe2\u773a\u8df3\u4f7b\u7967\u94eb\u7a95\u9f86\u9ca6',
+  'tie': '\u8d34\u94c1\u5e16\u841c\u992e',
+  'ting': '\u5385\u542c\u70c3\u6c40\u5ef7\u505c\u4ead\u5ead\u633a\u8247\u839b\u8476\u5a77\u6883\u8713\u9706',
+  'tong': '\u901a\u6850\u916e\u77b3\u540c\u94dc\u5f64\u7ae5\u6876\u6345\u7b52\u7edf\u75db\u4f5f\u50ee\u4edd\u833c\u55f5\u6078\u6f7c\u783c',
+  'tou': '\u5077\u6295\u5934\u900f\u4ea0',
+  'tu': '\u51f8\u79c3\u7a81\u56fe\u5f92\u9014\u6d82\u5c60\u571f\u5410\u5154\u580d\u837c\u83df\u948d\u9174',
+  'tuan': '\u6e4d\u56e2\u7583',
+  'tui': '\u63a8\u9893\u817f\u8715\u892a\u9000\u5fd2\u717a',
+  'tun': '\u541e\u5c6f\u81c0\u9968\u66be\u8c5a\u7a80',
+  'tuo': '\u62d6\u6258\u8131\u9e35\u9640\u9a6e\u9a7c\u692d\u59a5\u62d3\u553e\u4e47\u4f57\u5768\u5eb9\u6cb1\u67dd\u7823\u7ba8\u8204\u8dce\u9f0d',
+  'wa': '\u6316\u54c7\u86d9\u6d3c\u5a03\u74e6\u889c\u4f64\u5a32\u817d',
+  'wai': '\u6b6a\u5916',
+  'wan': '\u8c4c\u5f2f\u6e7e\u73a9\u987d\u4e38\u70f7\u5b8c\u7897\u633d\u665a\u7696\u60cb\u5b9b\u5a49\u4e07\u8155\u525c\u8284\u82cb\u83c0\u7ea8\u7efe\u742c\u8118\u7579\u873f\u7ba2',
+  'wang': '\u6c6a\u738b\u4ea1\u6789\u7f51\u5f80\u65fa\u671b\u5fd8\u5984\u7f54\u5c22\u60d8\u8f8b\u9b4d',
+  'wei': '\u5a01\u5dcd\u5fae\u5371\u97e6\u8fdd\u6845\u56f4\u552f\u60df\u4e3a\u6f4d\u7ef4\u82c7\u840e\u59d4\u4f1f\u4f2a\u5c3e\u7eac\u672a\u851a\u5473\u754f\u80c3\u5582\u9b4f\u4f4d\u6e2d\u8c13\u5c09\u6170\u536b\u502d\u504e\u8bff\u9688\u8473\u8587\u5e0f\u5e37\u5d34\u5d6c\u7325\u732c\u95f1\u6ca9\u6d27\u6da0\u9036\u5a13\u73ae\u97ea\u8ece\u709c\u7168\u71a8\u75ff\u8249\u9c94',
+  'wen': '\u761f\u6e29\u868a\u6587\u95fb\u7eb9\u543b\u7a33\u7d0a\u95ee\u520e\u6120\u960c\u6c76\u74ba\u97eb\u6b81\u96ef',
+  'weng': '\u55e1\u7fc1\u74ee\u84ca\u8579',
+  'wo': '\u631d\u8717\u6da1\u7a9d\u6211\u65a1\u5367\u63e1\u6c83\u83b4\u5e44\u6e25\u674c\u809f\u9f8c',
+  'wu': '\u5deb\u545c\u94a8\u4e4c\u6c61\u8bec\u5c4b\u65e0\u829c\u68a7\u543e\u5434\u6bcb\u6b66\u4e94\u6342\u5348\u821e\u4f0d\u4fae\u575e\u620a\u96fe\u6664\u7269\u52ff\u52a1\u609f\u8bef\u5140\u4ef5\u9622\u90ac\u572c\u82b4\u5e91\u6003\u5fe4\u6d6f\u5be4\u8fd5\u59a9\u9a9b\u727e\u7110\u9e49\u9e5c\u8708\u92c8\u9f2f',
+  'xi': '\u6614\u7199\u6790\u897f\u7852\u77fd\u6670\u563b\u5438\u9521\u727a\u7a00\u606f\u5e0c\u6089\u819d\u5915\u60dc\u7184\u70ef\u6eaa\u6c50\u7280\u6a84\u88ad\u5e2d\u4e60\u5ab3\u559c\u94e3\u6d17\u7cfb\u9699\u620f\u7ec6\u50d6\u516e\u96b0\u90d7\u831c\u8478\u84f0\u595a\u550f\u5f99\u9969\u960b\u6d60\u6dc5\u5c63\u5b09\u73ba\u6a28\u66e6\u89cb\u6b37\u71b9\u798a\u79a7\u94b8\u7699\u7a78\u8725\u87cb\u823e\u7fb2\u7c9e\u7fd5\u91af\u9f37',
+  'xia': '\u778e\u867e\u5323\u971e\u8f96\u6687\u5ce1\u4fa0\u72ed\u4e0b\u53a6\u590f\u5413\u6380\u846d\u55c4\u72ce\u9050\u7455\u7856\u7615\u7f45\u9ee0',
+  'xian': '\u9528\u5148\u4ed9\u9c9c\u7ea4\u54b8\u8d24\u8854\u8237\u95f2\u6d8e\u5f26\u5acc\u663e\u9669\u73b0\u732e\u53bf\u817a\u9985\u7fa1\u5baa\u9677\u9650\u7ebf\u51bc\u85d3\u5c98\u7303\u66b9\u5a34\u6c19\u7946\u9e47\u75eb\u86ac\u7b45\u7c7c\u9170\u8df9',
+  'xiang': '\u76f8\u53a2\u9576\u9999\u7bb1\u8944\u6e58\u4e61\u7fd4\u7965\u8be6\u60f3\u54cd\u4eab\u9879\u5df7\u6a61\u50cf\u5411\u8c61\u8297\u8459\u9977\u5ea0\u9aa7\u7f03\u87d3\u9c9e\u98e8',
+  'xiao': '\u8427\u785d\u9704\u524a\u54ee\u56a3\u9500\u6d88\u5bb5\u6dc6\u6653\u5c0f\u5b5d\u6821\u8096\u5578\u7b11\u6548\u54d3\u54bb\u5d24\u6f47\u900d\u9a81\u7ee1\u67ad\u67b5\u7b71\u7bab\u9b48',
+  'xie': '\u6954\u4e9b\u6b47\u874e\u978b\u534f\u631f\u643a\u90aa\u659c\u80c1\u8c10\u5199\u68b0\u5378\u87f9\u61c8\u6cc4\u6cfb\u8c22\u5c51\u5055\u4eb5\u52f0\u71ee\u85a4\u64b7\u5ee8\u7023\u9082\u7ec1\u7f2c\u69ad\u698d\u6b59\u8e9e',
+  'xin': '\u85aa\u82af\u950c\u6b23\u8f9b\u65b0\u5ffb\u5fc3\u4fe1\u8845\u56df\u99a8\u8398\u6b46\u94fd\u946b',
+  'xing': '\u661f\u8165\u7329\u60fa\u5174\u5211\u578b\u5f62\u90a2\u884c\u9192\u5e78\u674f\u6027\u59d3\u9649\u8347\u8365\u64e4\u60bb\u784e',
+  'xiong': '\u5144\u51f6\u80f8\u5308\u6c79\u96c4\u718a\u828e',
+  'xiu': '\u4f11\u4fee\u7f9e\u673d\u55c5\u9508\u79c0\u8896\u7ee3\u83a0\u5cab\u9990\u5ea5\u9e3a\u8c85\u9af9',
+  'xu': '\u589f\u620c\u9700\u865a\u5618\u987b\u5f90\u8bb8\u84c4\u9157\u53d9\u65ed\u5e8f\u755c\u6064\u7d6e\u5a7f\u7eea\u7eed\u8bb4\u8be9\u5729\u84ff\u6035\u6d2b\u6e86\u987c\u6829\u7166\u7809\u76f1\u80e5\u7cc8\u9191',
+  'xuan': '\u8f69\u55a7\u5ba3\u60ac\u65cb\u7384\u9009\u7663\u7729\u7eda\u5107\u8c16\u8431\u63ce\u9994\u6ceb\u6d35\u6e32\u6f29\u7487\u6966\u6684\u70ab\u714a\u78b9\u94c9\u955f\u75c3',
+  'xue': '\u9774\u859b\u5b66\u7a74\u96ea\u8840\u5671\u6cf6\u9cd5',
+  'xun': '\u52cb\u718f\u5faa\u65ec\u8be2\u5bfb\u9a6f\u5de1\u6b89\u6c5b\u8bad\u8baf\u900a\u8fc5\u5dfd\u57d9\u8340\u85b0\u5ccb\u5f87\u6d54\u66db\u7aa8\u91ba\u9c9f',
+  'ya': '\u538b\u62bc\u9e26\u9e2d\u5440\u4e2b\u82bd\u7259\u869c\u5d16\u8859\u6daf\u96c5\u54d1\u4e9a\u8bb6\u4f22\u63e0\u5416\u5c88\u8fd3\u5a05\u740a\u6860\u6c29\u7811\u775a\u75d6',
+  'yan': '\u7109\u54bd\u9609\u70df\u6df9\u76d0\u4e25\u7814\u8712\u5ca9\u5ef6\u8a00\u989c\u960e\u708e\u6cbf\u5944\u63a9\u773c\u884d\u6f14\u8273\u5830\u71d5\u538c\u781a\u96c1\u5501\u5f66\u7130\u5bb4\u8c1a\u9a8c\u53a3\u9765\u8d5d\u4fe8\u5043\u5156\u8ba0\u8c33\u90fe\u9122\u82ab\u83f8\u5d26\u6079\u95eb\u960f\u6d07\u6e6e\u6edf\u598d\u5ae3\u7430\u664f\u80ed\u814c\u7131\u7f68\u7b75\u917d\u9b47\u990d\u9f39',
+  'yang': '\u6b83\u592e\u9e2f\u79e7\u6768\u626c\u4f6f\u75a1\u7f8a\u6d0b\u9633\u6c27\u4ef0\u75d2\u517b\u6837\u6f3e\u5f89\u600f\u6cf1\u7080\u70ca\u6059\u86d8\u9785',
+  'yao': '\u9080\u8170\u5996\u7476\u6447\u5c27\u9065\u7a91\u8c23\u59da\u54ac\u8200\u836f\u8981\u8000\u592d\u723b\u5406\u5d3e\u5fad\u7039\u5e7a\u73e7\u6773\u66dc\u80b4\u9e5e\u7a88\u7e47\u9cd0',
+  'ye': '\u6930\u564e\u8036\u7237\u91ce\u51b6\u4e5f\u9875\u6396\u4e1a\u53f6\u66f3\u814b\u591c\u6db2\u8c12\u90ba\u63f6\u9980\u6654\u70e8\u94d8',
+  'yi': '\u4e00\u58f9\u533b\u63d6\u94f1\u4f9d\u4f0a\u8863\u9890\u5937\u9057\u79fb\u4eea\u80f0\u7591\u6c82\u5b9c\u59e8\u5f5d\u6905\u8681\u501a\u5df2\u4e59\u77e3\u4ee5\u827a\u6291\u6613\u9091\u5c79\u4ebf\u5f79\u81c6\u9038\u8084\u75ab\u4ea6\u88d4\u610f\u6bc5\u5fc6\u4e49\u76ca\u6ea2\u8be3\u8bae\u8c0a\u8bd1\u5f02\u7ffc\u7fcc\u7ece\u5208\u5293\u4f7e\u8bd2\u572a\u572f\u57f8\u61ff\u82e1\u858f\u5f08\u5955\u6339\u5f0b\u5453\u54a6\u54bf\u566b\u5cc4\u5db7\u7317\u9974\u603f\u6021\u6092\u6f2a\u8fe4\u9a7f\u7f22\u6baa\u8d3b\u65d6\u71a0\u9487\u9552\u9571\u75cd\u7617\u7654\u7fca\u8864\u8734\u8223\u7fbf\u7ff3\u914f\u9edf',
+  'yin': '\u8335\u836b\u56e0\u6bb7\u97f3\u9634\u59fb\u541f\u94f6\u6deb\u5bc5\u996e\u5c39\u5f15\u9690\u5370\u80e4\u911e\u5819\u831a\u5591\u72fa\u5924\u6c24\u94df\u763e\u8693\u972a\u9f88',
+  'ying': '\u82f1\u6a31\u5a74\u9e70\u5e94\u7f28\u83b9\u8424\u8425\u8367\u8747\u8fce\u8d62\u76c8\u5f71\u9896\u786c\u6620\u5b34\u90e2\u8314\u83ba\u8426\u6484\u5624\u81ba\u6ee2\u6f46\u701b\u745b\u748e\u6979\u9e66\u763f\u988d\u7f42',
+  'yo': '\u54df\u5537',
+  'yong': '\u62e5\u4f63\u81c3\u75c8\u5eb8\u96cd\u8e0a\u86f9\u548f\u6cf3\u6d8c\u6c38\u607f\u52c7\u7528\u4fd1\u58c5\u5889\u6175\u9095\u955b\u752c\u9cd9\u9954',
+  'you': '\u5e7d\u4f18\u60a0\u5fe7\u5c24\u7531\u90ae\u94c0\u72b9\u6cb9\u6e38\u9149\u6709\u53cb\u53f3\u4f51\u91c9\u8bf1\u53c8\u5e7c\u5363\u6538\u4f91\u83b8\u5466\u56ff\u5ba5\u67da\u7337\u7256\u94d5\u75a3\u8763\u9c7f\u9edd\u9f2c',
+  'yu': '\u8fc2\u6de4\u4e8e\u76c2\u6986\u865e\u611a\u8206\u4f59\u4fde\u903e\u9c7c\u6109\u6e1d\u6e14\u9685\u4e88\u5a31\u96e8\u4e0e\u5c7f\u79b9\u5b87\u8bed\u7fbd\u7389\u57df\u828b\u90c1\u5401\u9047\u55bb\u5cea\u5fa1\u6108\u6b32\u72f1\u80b2\u8a89\u6d74\u5bd3\u88d5\u9884\u8c6b\u9a6d\u79ba\u6bd3\u4f1b\u4fe3\u8c00\u8c15\u8438\u84e3\u63c4\u5581\u5704\u5709\u5d5b\u72f3\u996b\u5ebe\u9608\u59aa\u59a4\u7ea1\u745c\u6631\u89ce\u8174\u6b24\u65bc\u715c\u71e0\u807f\u94b0\u9e46\u7610\u7600\u7ab3\u8753\u7afd\u8201\u96e9\u9f89',
+  'yuan': '\u9e33\u6e0a\u51a4\u5143\u57a3\u8881\u539f\u63f4\u8f95\u56ed\u5458\u5706\u733f\u6e90\u7f18\u8fdc\u82d1\u613f\u6028\u9662\u586c\u6c85\u5a9b\u7457\u6a7c\u7230\u7722\u9e22\u8788\u9f0b',
+  'yue': '\u66f0\u7ea6\u8d8a\u8dc3\u94a5\u5cb3\u7ca4\u6708\u60a6\u9605\u9fa0\u6a3e\u5216\u94ba',
+  'yun': '\u8018\u4e91\u90e7\u5300\u9668\u5141\u8fd0\u8574\u915d\u6655\u97f5\u5b55\u90d3\u82b8\u72c1\u607d\u7ead\u6b92\u6600\u6c32',
+  'za': '\u531d\u7838\u6742\u62f6\u5482',
+  'zai': '\u683d\u54c9\u707e\u5bb0\u8f7d\u518d\u5728\u54b1\u5d3d\u753e',
+  'zan': '\u6512\u6682\u8d5e\u74d2\u661d\u7c2a\u7ccc\u8db1\u933e',
+  'zang': '\u8d43\u810f\u846c\u5958\u6215\u81e7',
+  'zao': '\u906d\u7cdf\u51ff\u85fb\u67a3\u65e9\u6fa1\u86a4\u8e81\u566a\u9020\u7682\u7076\u71e5\u5523\u7f2b',
+  'ze': '\u8d23\u62e9\u5219\u6cfd\u4ec4\u8d5c\u5567\u8fee\u6603\u7b2e\u7ba6\u8234',
+  'zei': '\u8d3c',
+  'zen': '\u600e\u8c2e',
+  'zeng': '\u589e\u618e\u66fe\u8d60\u7f2f\u7511\u7f7e\u9503',
+  'zha': '\u624e\u55b3\u6e23\u672d\u8f67\u94e1\u95f8\u7728\u6805\u69a8\u548b\u4e4d\u70b8\u8bc8\u63f8\u5412\u54a4\u54f3\u600d\u781f\u75c4\u86b1\u9f44',
+  'zhai': '\u6458\u658b\u5b85\u7a84\u503a\u5be8\u7826',
+  'zhan': '\u77bb\u6be1\u8a79\u7c98\u6cbe\u76cf\u65a9\u8f97\u5d2d\u5c55\u8638\u6808\u5360\u6218\u7ad9\u6e5b\u7efd\u8c35\u640c\u65c3',
+  'zhang': '\u6a1f\u7ae0\u5f70\u6f33\u5f20\u638c\u6da8\u6756\u4e08\u5e10\u8d26\u4ed7\u80c0\u7634\u969c\u4ec9\u9123\u5e5b\u5d82\u7350\u5adc\u748b\u87d1',
+  'zhao': '\u62db\u662d\u627e\u6cbc\u8d75\u7167\u7f69\u5146\u8087\u53ec\u722a\u8bcf\u68f9\u948a\u7b0a',
+  'zhe': '\u906e\u6298\u54f2\u86f0\u8f99\u8005\u9517\u8517\u8fd9\u6d59\u8c2a\u966c\u67d8\u8f84\u78d4\u9e67\u891a\u8707\u8d6d',
+  'zhen': '\u73cd\u659f\u771f\u7504\u7827\u81fb\u8d1e\u9488\u4fa6\u6795\u75b9\u8bca\u9707\u632f\u9547\u9635\u7f1c\u6862\u699b\u8f78\u8d48\u80d7\u6715\u796f\u755b\u9e29',
+  'zheng': '\u84b8\u6323\u7741\u5f81\u72f0\u4e89\u6014\u6574\u62ef\u6b63\u653f\u5e27\u75c7\u90d1\u8bc1\u8be4\u5ce5\u94b2\u94ee\u7b5d',
+  'zhi': '\u829d\u679d\u652f\u5431\u8718\u77e5\u80a2\u8102\u6c41\u4e4b\u7ec7\u804c\u76f4\u690d\u6b96\u6267\u503c\u4f84\u5740\u6307\u6b62\u8dbe\u53ea\u65e8\u7eb8\u5fd7\u631a\u63b7\u81f3\u81f4\u7f6e\u5e1c\u5cd9\u5236\u667a\u79e9\u7a1a\u8d28\u7099\u75d4\u6ede\u6cbb\u7a92\u536e\u965f\u90c5\u57f4\u82b7\u646d\u5e19\u5fee\u5f58\u54ab\u9a98\u6809\u67b3\u6800\u684e\u8f75\u8f7e\u6534\u8d3d\u81a3\u7949\u7957\u9ef9\u96c9\u9e37\u75e3\u86ed\u7d77\u916f\u8dd6\u8e2c\u8e2f\u8c78\u89ef',
+  'zhong': '\u4e2d\u76c5\u5fe0\u949f\u8877\u7ec8\u79cd\u80bf\u91cd\u4ef2\u4f17\u51a2\u953a\u87bd\u8202\u822f\u8e35',
+  'zhou': '\u821f\u5468\u5dde\u6d32\u8bcc\u7ca5\u8f74\u8098\u5e1a\u5492\u76b1\u5b99\u663c\u9aa4\u5544\u7740\u501c\u8bf9\u836e\u9b3b\u7ea3\u80c4\u78a1\u7c40\u8233\u914e\u9cb7',
+  'zhu': '\u73e0\u682a\u86db\u6731\u732a\u8bf8\u8bdb\u9010\u7af9\u70db\u716e\u62c4\u77a9\u5631\u4e3b\u8457\u67f1\u52a9\u86c0\u8d2e\u94f8\u7b51\u4f4f\u6ce8\u795d\u9a7b\u4f2b\u4f8f\u90be\u82ce\u8331\u6d19\u6e1a\u6f74\u9a7a\u677c\u69e0\u6a65\u70b7\u94e2\u75b0\u7603\u86b0\u7afa\u7bb8\u7fe5\u8e85\u9e88',
+  'zhua': '\u6293',
+  'zhuai': '\u62fd',
+  'zhuan': '\u4e13\u7816\u8f6c\u64b0\u8d5a\u7bc6\u629f\u556d\u989b',
+  'zhuang': '\u6869\u5e84\u88c5\u5986\u649e\u58ee\u72b6\u4e2c',
+  'zhui': '\u690e\u9525\u8ffd\u8d58\u5760\u7f00\u8411\u9a93\u7f12',
+  'zhun': '\u8c06\u51c6',
+  'zhuo': '\u6349\u62d9\u5353\u684c\u7422\u8301\u914c\u707c\u6d4a\u502c\u8bfc\u5ef4\u855e\u64e2\u555c\u6d5e\u6dbf\u6753\u712f\u799a\u65ab',
+  'zi': '\u5179\u54a8\u8d44\u59ff\u6ecb\u6dc4\u5b5c\u7d2b\u4ed4\u7c7d\u6ed3\u5b50\u81ea\u6e0d\u5b57\u8c18\u5d6b\u59ca\u5b73\u7f01\u6893\u8f8e\u8d40\u6063\u7726\u9531\u79ed\u8014\u7b2b\u7ca2\u89dc\u8a3e\u9cbb\u9aed',
+  'zong': '\u9b03\u68d5\u8e2a\u5b97\u7efc\u603b\u7eb5\u8159\u7cbd',
+  'zou': '\u90b9\u8d70\u594f\u63cd\u9139\u9cb0',
+  'zu': '\u79df\u8db3\u5352\u65cf\u7956\u8bc5\u963b\u7ec4\u4fce\u83f9\u5550\u5f82\u9a75\u8e74',
+  'zuan': '\u94bb\u7e82\u6525\u7f35',
+  'zui': '\u5634\u9189\u6700\u7f6a',
+  'zun': '\u5c0a\u9075\u6499\u6a3d\u9cdf',
+  'zuo': '\u6628\u5de6\u4f50\u67de\u505a\u4f5c\u5750\u5ea7\u961d\u963c\u80d9\u795a\u9162',
+  'cou': '\u85ae\u6971\u8f8f\u8160',
+  'nang': '\u652e\u54dd\u56d4\u9995\u66e9',
+  'o': '\u5594',
+  'dia': '\u55f2',
+  'chuai': '\u562c\u81aa\u8e39',
+  'cen': '\u5c91\u6d94',
+  'diu': '\u94e5',
+  'nou': '\u8028',
+  'fou': '\u7f36',
+  'bia': '\u9adf'
+}

+ 128 - 0
global/index.js

@@ -0,0 +1,128 @@
+import Vue from 'vue'
+
+Vue.filter('PercentFormat',function (value) {
+  if (value == null || value == undefined) {
+    return '+0%';
+  } else if (value < 0) {
+    return value + '%';
+  } else if (value == '+∞') {
+    return value ;
+  } else if (value == '-∞') {
+    return value ;
+  } else {
+    return '+' + value + '%';
+  }
+});
+
+Vue.filter('NumberFormat',function (value) {
+  
+  if (value == '***') {
+    return '***';
+  }
+  if (isNaN(value)) {
+    return 0;
+  }
+  let value1 = value.toString();
+  if (value1.indexOf('-')>-1) {
+    value1 = value1.split('-')[1];
+    let num = value1.split('.');
+    let interCount = num[0].length;
+    if (interCount < 3) {
+      return value;
+    }
+    let index = 0;
+    let inter = '';
+    for (let i = interCount - 3; i >= 0; i -= 3) {
+      inter = num[0].substr(i, 3) + (inter == '' ? '' : ',') + inter;
+      index = i;
+    }
+    if (index > 0) {
+      inter = num[0].substr(0, index) + (inter == '' ? '' : ',') + inter;
+    }
+    return '-' + inter + (num.length == 1 ? '' : '.' + num[1]);
+  } else {
+    let num = value1.split('.');
+    let interCount = num[0].length;
+    if (interCount < 3) {
+      return value;
+    }
+    let index = 0;
+    let inter = '';
+    for (let i = interCount - 3; i >= 0; i -= 3) {
+      inter = num[0].substr(i, 3) + (inter == '' ? '' : ',') + inter;
+      index = i;
+    }
+    if (index > 0) {
+      inter = num[0].substr(0, index) + (inter == '' ? '' : ',') + inter;
+    }
+    return inter + (num.length == 1 ? '' : '.' + num[1]);
+  }
+  
+});
+
+Vue.filter('NumberFormat1',function (value) {
+  if (value == '--') {
+    return '--';
+  }
+  if (isNaN(value)) {
+    return 0;
+  }
+  let num = value.toString().split('.');
+  let interCount = num[0].length;
+  if (interCount < 3) {
+    return value;
+  }
+  let index = 0;
+  let inter = '';
+  for (let i = interCount - 3; i >= 0; i -= 3) {
+    inter = num[0].substr(i, 3) + (inter == '' ? '' : ',') + inter;
+    index = i;
+  }
+  if (index > 0) {
+    inter = num[0].substr(0, index) + (inter == '' ? '' : ',') + inter;
+  }
+  return inter + (num.length == 1 ? '' : '.' + num[1]);
+});
+
+Vue.filter('PwdFormat',function (value) {
+  if (value == null || value == undefined) {
+    return 'Null';
+  } else {
+    let len = value.toString().length;
+    let val = '';
+    for (let i = 0; i < len; i++) {
+      val = val + '*';
+    }
+    return val;
+  }
+});
+
+
+Vue.filter('NumberDecimal',function (value) {
+  let realVal = ''
+  if (!isNaN(value) && value!== '') {
+    // 截取当前数据到小数点后两位
+    realVal = parseFloat(value).toFixed(2)
+  } else {
+    realVal = '0'
+  }
+  return realVal
+});
+
+Vue.filter('NumberDesensitization',function (value) {
+  let realVal = ''
+  if (!isNaN(value) && value!== '') {
+    value = value.toString();
+    realVal = value.substr(0,2) + '****' + value.substr(-2);
+  } else {
+    realVal = '--'
+  }
+  return realVal
+});
+
+Vue.filter('NumberDesensitization1',function (value) {
+  let realVal = ''
+  value = value.toString();
+  realVal = value.substr(0,1) + '***' + value.substr(-2);
+  return realVal
+});

+ 12 - 0
global/isImageType.js

@@ -0,0 +1,12 @@
+
+export default {
+  checkFile: function (val) {
+    const imageType = ['image/jpeg', 'image/png', 'image/jpg', 'application/pdf']
+    const isImage = imageType.indexOf(val.toLocaleLowerCase()) == -1 ? false : true;
+    return isImage
+  },
+  checkSize: function (val) {
+    const isSize = val / 1024 / 1024 < 20;
+    return isSize
+  },
+}

+ 40 - 0
global/py.js

@@ -0,0 +1,40 @@
+import { pinyin } from '../global/constPY'
+export default {
+  chineseToPinYin: function (l1) {
+    if (!l1) {
+      return ''
+    }
+    var l2 = l1.length
+    var I1 = ''
+    var reg = new RegExp('[a-zA-Z0-9]')
+    for (var i = 0; i < l2; i++) {
+      var val = l1.substr(i, 1)
+      var name = this.arraySearch(val, pinyin)
+      if (reg.test(val)) {
+        I1 += val
+      } else if (name !== false) {
+        I1 += name
+      }
+    }
+    I1 = I1.replace(/ /g, '-')
+    while (I1.indexOf('--') > 0) {
+      I1 = I1.replace('--', '-')
+    }
+    return I1
+  },
+  arraySearch: function (l1) {
+    for (var name in pinyin) {
+      if (pinyin[name].indexOf(l1) !== -1) {
+        return this.ucfirst(name)
+      }
+    }
+    return false
+  },
+  ucfirst: function (l1) {
+    if (l1.length > 0) {
+      var first = l1.substr(0, 1).toUpperCase()
+      var spare = l1.substr(1, l1.length)
+      return first + spare
+    }
+  }
+}

+ 11 - 0
global/tool.js

@@ -0,0 +1,11 @@
+
+export default {
+  tokenReplace: function (val) {
+    if (!val) {
+      return val
+    }
+    let token = '';
+    token = val.replace(/%/g,'%25').replace(/\+/g,'%2B').replace(/ /g,'%20').replace(/\//g,'%2F').replace(/\?/g,'%3F');
+    return token
+  },
+}

+ 28 - 0
lib/crypt.js

@@ -0,0 +1,28 @@
+/*
+ * @Description: 本地数据加密解密
+ * @Author: sql
+ * @Date: 2018-11-23 20:38:06
+ * @LastEditTime: 2018-11-29 16:14:16
+ */
+import CryptoJs from 'crypto-js'
+
+class CryptToJS {
+    constructor() {
+        this.crypt = CryptoJs
+        this.secret = 'Believe in yourself.'
+    }
+    // 加密内容, 原文
+    Encrypt(text) {
+        return this.crypt.AES.encrypt(text, this.secret).toString()
+    }
+    // 解密,加密内容
+    Decrypt(text) {
+        if (text == null || text.lenth == 0) {
+            return ""
+        }
+        return this.crypt.AES.decrypt(text, this.secret).toString(CryptoJs.enc.Utf8)
+    }
+
+}
+
+export default new CryptToJS

+ 159 - 0
lib/service.js

@@ -0,0 +1,159 @@
+/*
+ * @Description: service类,其他业务层继承此类
+ * @Author: sql
+ * @Date: 2018-11-22 16:57:16
+ * @LastEditTime: 2018-11-30 10:39:09
+ */
+import Vue from "vue"
+import axios from 'axios'
+import Config from '../config'
+import store from '../store'
+import session from "./session";
+Vue.prototype.$store = store;
+// axios.defaults.baseURL = Config.Host
+
+if (sessionStorage.getItem("access_token")) {
+  axios.defaults.headers.common['Access-Token'] = sessionStorage.getItem("access_token")
+}
+if (sessionStorage.getItem("lang")) {
+	axios.defaults.headers.common['Language'] = sessionStorage.getItem("lang")
+}
+if (sessionStorage.getItem("CLIENT")) {
+	axios.defaults.headers.common['CLIENT'] = sessionStorage.getItem("CLIENT")
+}
+axios.defaults.headers.common['X-System'] = 'A'
+const SystemError = {
+    "cn":"网络状态不佳,请稍后重试。",
+    "en":"The network is not in good condition. Please try again later.",
+    "vn":"Mạng không được tốt lắm. Vui lòng thử lại sau.",
+}
+
+class Service {
+	constructor() {
+		this.axio = axios;
+		this.vue = new Vue({store})
+	}
+
+	// session过期
+	SessionExpire() {
+		this.vue.$store.commit("InfoExpire", true)
+	}
+
+	// // 统一登陆
+	// Login(params) {
+	// 	//console.log(params)
+	// }
+
+	// 统一登出
+	Logout() {
+		let _vue = new Vue()
+		_vue.$routes.push({
+			name: 'login'
+		})
+		_vue = null
+	}
+
+
+	//多端口-多token
+	getAll(type,url,params){
+		switch (type) {
+			case 'Host80':
+				this.axio.defaults.baseURL = Config.Host80;
+				this.axio.defaults.headers.common['Access-Token'] = sessionStorage.getItem("access_token");
+			break;
+			case 'Host04':
+				this.axio.defaults.baseURL = Config.Host04;
+				this.axio.defaults.headers.common['Access-Token'] = sessionStorage.getItem("access_token");
+			break;
+			case 'Host90':
+				this.axio.defaults.baseURL = Config.Host90;
+				this.axio.defaults.headers.common['Access-Token'] = sessionStorage.getItem("access_token");
+			break;
+			case 'HostShop':
+				this.axio.defaults.baseURL = Config.HostShop;
+				this.axio.defaults.headers.common['Access-Token'] = sessionStorage.getItem("shop_token");
+			break;
+			case 'Host87':
+				this.axio.defaults.baseURL = Config.Host87;
+				this.axio.defaults.headers.common['Access-Token'] = sessionStorage.getItem("access_token");
+			break;
+		}
+		return this.get(url,params);
+	}
+	postAll(type,url,params,config = {}){
+		switch (type) {
+			case 'Host80':
+				this.axio.defaults.baseURL = Config.Host80;
+				this.axio.defaults.headers.common['Access-Token'] = sessionStorage.getItem("access_token");
+				
+			break;
+			case 'Host04':
+				this.axio.defaults.baseURL = Config.Host04;
+				this.axio.defaults.headers.common['Access-Token'] = sessionStorage.getItem("access_token");
+			break;
+			case 'Host90':
+				this.axio.defaults.baseURL = Config.Host90;
+				this.axio.defaults.headers.common['Access-Token'] = sessionStorage.getItem("access_token");
+			break;
+			case 'HostShop':
+				this.axio.defaults.baseURL = Config.HostShop;
+				this.axio.defaults.headers.common['Access-Token'] = sessionStorage.getItem("shop_token");
+			break;
+			case 'Host87':
+				this.axio.defaults.baseURL = Config.Host87;
+				this.axio.defaults.headers.common['Access-Token'] = sessionStorage.getItem("access_token");
+			break;
+		}
+		return this.post(url,params,config);
+	}
+
+	// method GET
+	get(url,params) {
+		return this.axio.get(url,params).then((response) => {
+			if (response.data.code == Config.Code.StatusSessionExpire) {
+				this.SessionExpire()
+			} else if (response.data.code == 500) {
+				return {
+					code: 500,
+					msg: SystemError[session.Get('lang')] || SystemError['en']
+				}
+			} else {
+				return response.data
+			}
+		}).catch(() => {
+			this.SessionExpire()
+			return {
+				code: Config.Code.StatusFail,
+				msg: SystemError[session.Get('lang')] || SystemError['en']
+			}
+		})
+	}
+
+	// method POST
+	post(url, params, config = {}) {
+        return this.axio.post(url, params, config).then((response) => {
+			if (response.data.code == Config.Code.StatusSessionExpire) {
+				this.SessionExpire()
+			} else if (response.data.code == Config.Code.StatusSNotFound) {
+				return {
+					code: Config.Code.StatusFail,
+					msg: SystemError[session.Get('lang')] || SystemError['en']
+				}
+			} else if (response.data.code == 500) {
+				return {
+					code: 500,
+					msg: SystemError[session.Get('lang')] || SystemError['en']
+				}
+			} else {
+				return response.data
+			}
+		}).catch(() => {
+			return {
+				code: Config.Code.StatusFail,
+				msg: SystemError[session.Get('lang')] || SystemError['en']
+			}
+		})
+	}
+}
+
+export default Service

+ 56 - 0
lib/session.js

@@ -0,0 +1,56 @@
+/*
+ * @Description: sessionStorage 封装
+ * @Author: sql
+ * @Date: 2018-11-23 21:02:16
+ * @LastEditTime: 2018-11-27 17:25:50
+ */
+import crypt from "@/lib/crypt"
+
+class SessionStorage {
+
+  constructor() {
+    this.Data = sessionStorage
+  }
+
+  // 获取 key中的数据
+  Get(key, flag = false) {
+    let res = null
+    if (flag) {
+      res = crypt.Decrypt(this.Data[key])
+    } else {
+      res = this.Data[key]
+
+    }
+    return this.IsExist(key) ? res : null
+  }
+
+  // 更新或创建新数据
+  Set(key, val, flag = false) {
+    let res = null
+    if (flag) {
+      res = crypt.Encrypt(String(val))
+    } else {
+      res = String(val)
+    }
+    this.Data[key] = sessionStorage[key] = res
+  }
+
+  // 输出 key 数据
+  Del(key) {
+    this.Data[key] = null
+    sessionStorage.removeItem(key)
+  }
+
+  // key数据是否存在
+  IsExist(key) {
+    return this.Data.getItem(key) ? true : false
+  }
+
+  // 清除所有session
+  Clear() {
+    this.Data = null
+    sessionStorage.clear()
+  }
+}
+
+export default new SessionStorage

+ 138 - 0
lib/upload.js

@@ -0,0 +1,138 @@
+/*
+ * @Description: 统一上传工具,先获取uploadToken,再上传到新接口
+ * @Author: Auto
+ * @Date: 2024-01-01
+ */
+import axios from 'axios'
+import Config from '../config'
+
+
+/**
+ * 统一上传方法
+ * @param {File} file - 要上传的文件
+ * @param {String} originalUrl - 原上传接口URL(用于获取uploadToken)
+ * @param {Object} headers - 请求头
+ * @param {Function} onProgress - 上传进度回调
+ * @returns {Promise} 上传结果
+ */
+export async function unifiedUpload(file, originalUrl, headers = {}, onProgress = null, id = null) {
+  try {
+    // 第一步:调用原接口获取 uploadToken
+    const formData = new FormData()
+    formData.append('file', file)
+    
+    // 设置请求头
+    const requestHeaders = {
+      'Access-Token': sessionStorage.getItem("access_token") || '',
+      'Language': sessionStorage.getItem("lang") || '',
+      'CLIENT': sessionStorage.getItem("CLIENT") || '',
+      ...headers
+    }
+    
+    // 获取基础URL
+    let baseURL = Config.Host80
+    if (originalUrl.includes(Config.Host80)) {
+      baseURL = Config.Host80
+    } else if (originalUrl.includes(Config.Host04)) {
+      baseURL = Config.Host04
+    } else if (originalUrl.includes(Config.Host90)) {
+      baseURL = Config.Host90
+    } else if (originalUrl.includes(Config.HostShop)) {
+      baseURL = Config.HostShop
+    } else if (originalUrl.includes(Config.Host87)) {
+      baseURL = Config.Host87
+    }
+    
+    // 提取原接口路径
+    let originalPath = originalUrl
+    if (originalUrl.startsWith('http://') || originalUrl.startsWith('https://')) {
+      // 完整URL,提取路径部分
+      const urlObj = new URL(originalUrl)
+      originalPath = urlObj.pathname
+    }
+    
+    // 调用原接口获取 uploadToken(先不传文件,只获取token)
+    // 如果原接口需要文件才能返回token,则传文件
+    const tokenFormData = new FormData()
+    tokenFormData.append('file', file)
+    
+    const tokenResponse = await axios.post(originalPath, tokenFormData, {
+      baseURL: baseURL,
+      headers: requestHeaders,
+      timeout: 30000
+    })
+    
+    // 从原接口响应中获取 uploadToken
+    // 假设原接口返回格式为 { code: 200, data: { uploadToken: 'xxx', ... } } 或 { code: 200, uploadToken: 'xxx' }
+    let uploadToken = null  
+    if (tokenResponse.data.code == 200) {
+      if(id === 1){
+        uploadToken = tokenResponse.data.data
+      }else {
+         // 如果直接返回 uploadToken
+         uploadToken = tokenResponse.data.data.path
+      }
+    }
+    
+    if (!uploadToken) {
+      throw new Error('Failed to get uploadToken from original upload interface')
+    }
+    
+    // 第二步:使用新接口上传文件
+    const uploadFormData = new FormData()
+    uploadFormData.append('file', file)
+    uploadFormData.append('uploadToken', uploadToken)
+    
+    const uploadResponse = await axios.post('/common/base/upload', uploadFormData, {
+      baseURL: Config.Host05,
+      headers: requestHeaders,
+      timeout: 60000,
+      onUploadProgress: (progressEvent) => {
+        if (onProgress && progressEvent.total) {
+          const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total)
+          onProgress({ percent })
+        }
+      }
+    })
+    
+    return uploadResponse.data
+    
+  } catch (error) {
+    console.error('Upload error:', error)
+    if (error.response) {
+      return {
+        code: error.response.status || 400,
+        msg: (error.response.data && error.response.data.msg) || error.message || 'Upload failed'
+      }
+    }
+    return {
+      code: 400,
+      msg: error.message || 'Upload failed'
+    }
+  }
+}
+
+/**
+ * 为 Element UI Upload 组件创建自定义上传方法
+ * @param {String} originalUrl - 原上传接口URL
+ * @param {Object} headers - 请求头
+ * @returns {Function} http-request 方法
+ */
+export function createUploadRequest(originalUrl, headers = {}, id = null) {
+  return async (options) => {
+    const { file, onProgress, onSuccess, onError } = options
+    
+    try {
+      const result = await unifiedUpload(file, originalUrl, headers, onProgress, id)
+      
+      if (result.code === 200) {
+        onSuccess(result)
+      } else {
+        onError(new Error(result.msg || 'Upload failed'))
+      }
+    } catch (error) {
+      onError(error)
+    }
+  }
+}
+

+ 1 - 0
package.json

@@ -18,6 +18,7 @@
     "clipboard": "^2.0.11",
     "crypto-js": "^4.2.0",
     "dayjs": "^1.11.13",
+    "decimal.js": "^10.6.0",
     "lodash": "^4.17.21",
     "pdfh5": "^3.0.0",
     "pinyin-pro": "^3.27.0",

+ 33 - 10
pages.json

@@ -95,28 +95,30 @@
       "path": "pages/login/index",
       "style": {
         "navigationBarTitleText": "",
-        "navigationStyle": "custom"
+        "navigationStyle": "custom",
+        "topWindow": false,
+        "leftWindow": false,
+        "rightWindow": false
       }
     },
     {
       "path": "pages/login/regist",
       "style": {
         "navigationBarTitleText": "",
-        "navigationStyle": "custom"
+        "navigationStyle": "custom",
+        "topWindow": false,
+        "leftWindow": false,
+        "rightWindow": false
       }
     },
     {
       "path": "pages/login/reset",
       "style": {
         "navigationBarTitleText": "",
-        "navigationStyle": "custom"
-      }
-    },
-    {
-      "path": "pages/login/forget",
-      "style": {
-        "navigationBarTitleText": "",
-        "navigationStyle": "custom"
+        "navigationStyle": "custom",
+        "topWindow": false,
+        "leftWindow": false,
+        "rightWindow": false
       }
     },
     {
@@ -161,6 +163,13 @@
         "navigationStyle": "custom"
       }
     },
+    {
+      "path": "pages/customer/account-select",
+      "style": {
+        "navigationBarTitleText": "",
+        "navigationStyle": "custom"
+      }
+    },
     {
       "path": "pages/customer/create-account",
       "style": {
@@ -168,6 +177,20 @@
         "navigationStyle": "custom"
       }
     },
+    {
+      "path": "pages/customer/deposit",
+      "style": {
+        "navigationBarTitleText": "",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/customer/withdrawal",
+      "style": {
+        "navigationBarTitleText": "",
+        "navigationStyle": "custom"
+      }
+    },
     {
       "path": "pages/mine/notice",
       "style": {

+ 480 - 0
pages/customer/account-select.vue

@@ -0,0 +1,480 @@
+<template>
+    <cwg-page-wrapper class="create-page" :isHeaderFixed="true">
+        <view class="account-selector">
+            <!-- PC 端表格视图 -->
+            <view class="account-table pc-view">
+                <!-- 表头:账户类型 -->
+                <view class="table-header">
+                    <view class="header-cell type-cell">标准型账户</view>
+                    <view class="header-cell">最低入金</view>
+                    <view class="header-cell">最小手数</view>
+                    <view class="header-cell">最大杠杆</view>
+                </view>
+                <!-- 标准账户行 -->
+                <template v-for="account in standardAccounts" :key="account.id">
+                    <view class="account-row" v-if="account.showCondition()" @click="onAccountSelect(account.id)"
+                        :class="{ 'active': account.id == selectedAccountId }">
+                        <view class="row-cell type-cell">
+                            <radio-group @change="(e) => onAccountSelect(account.id)" class="radio-group">
+                                <label class="radio-label">
+                                    <radio :value="account.id" :checked="selectedAccountId === account.id"
+                                        color="#1e2a3a" />
+                                    <image class="account-icon" :src="account.icon" mode="aspectFit" />
+                                    <view class="account-info">
+                                        <text class="account-name" v-t="account.name" />
+                                        <text class="account-desc" v-t="account.description" />
+                                    </view>
+                                </label>
+                            </radio-group>
+                        </view>
+                        <view class="row-cell">{{ account.minDeposit }}</view>
+                        <view class="row-cell">{{ account.minSpread }}</view>
+                        <view class="row-cell">{{ account.maxLeverage }}</view>
+                    </view>
+                </template>
+            </view>
+
+            <!-- 移动端轮播视图 -->
+            <view class="mobile-view">
+                <swiper class="account-swiper" :current="currentSwiperIndex" circular indicator-dots
+                    indicator-active-color="#1e2a3a" @change="onSwiperChange">
+                    <swiper-item v-for="account in filteredAccounts" :key="account.id">
+                        <view class="account-card" @click="onAccountSelect(account.id)"
+                            :class="{ 'active': account.id == selectedAccountId }">
+                            <image class="card-img" :src="account.icon" mode="aspectFit" />
+                            <view class="card-title" v-t="account.name"></view>
+                            <view class="card-tag">
+                                <text class="tag-label">{{ account.typeLabel }}</text>
+                            </view>
+                            <p class="card-desc" v-t="account.description"></p>
+                            <view class="card-info-stack">
+                                <cwg-label-line-value :label="'最低入金'" :value="account.minDeposit" />
+                                <cwg-label-line-value :label="'最小手数'" :value="account.minSpread" />
+                                <cwg-label-line-value :label="'最大杠杆'" :value="account.maxLeverage" />
+                            </view>
+                        </view>
+                    </swiper-item>
+                </swiper>
+            </view>
+        </view>
+        <!-- 继续按钮 -->
+        <view class="action-button">
+            <view class="btn" @click="handleContinue">
+                <text class="button-text">继续</text>
+            </view>
+        </view>
+        <!-- 条款说明 -->
+        <view class="terms-section">
+            <text v-t="'news_add_field.OpenAccount.Des1'"></text>
+            <text class="pdfLink">
+                <a href="/static/pdf/PrivacyPolicy2019_01.pdf" target="_blank"
+                    v-t="'news_add_field.OpenAccount.Des2'"></a>
+            </text>
+        </view>
+
+    </cwg-page-wrapper>
+</template>
+
+
+<script setup>
+import { ref, reactive, computed, onMounted, watch, nextTick } from 'vue';
+import { onLoad } from '@dcloudio/uni-app';
+import { userToken } from "@/composables/config";
+import { customApi } from "@/service/custom";
+import { ucardApi } from "@/api/ucard";
+import useUserStore from "@/stores/use-user-store";
+import useRouter from "@/hooks/useRouter";
+import { useI18n } from "vue-i18n";
+const router = useRouter();
+const { t, locale } = useI18n();
+const userStore = useUserStore();
+const server = ref('')
+const showLogin = ref([])
+const isTimeShow = ref(true)
+
+onLoad((e) => {
+    server.value = e.server
+})
+
+// 定义账户数据类型
+const standardAccounts = ref([
+    {
+        id: 7,
+        type: 'StandardAccount',
+        name: 'AccountType.StandardAccount',
+        showCondition: () => showLogin.value.indexOf('7') === -1,
+        description: 'Custom.NewAccount.DesLogin5',
+        minDeposit: '50 USD',
+        minSpread: '0.01',
+        maxLeverage: '1:1000',
+        icon: '/static/images/info/bank-information-1.webp',
+    },
+    {
+        id: 2,
+        type: 'SeniorAccount',
+        name: 'AccountType.SeniorAccount',
+        showCondition: () => showLogin.value.indexOf('2') === -1,
+        description: 'Custom.NewAccount.DesLogin3',
+        minDeposit: '200 USD',
+        minSpread: '0.01',
+        maxLeverage: '1:2000',
+        icon: '/static/images/info/bank-information-2.webp',
+    },
+    {
+        id: 8,
+        type: 'CentAccount',
+        name: 'AccountType.CentAccount',
+        showCondition: () => showLogin.value.indexOf('8') === -1 && isTimeShow.value,
+        description: 'Custom.NewAccount.DesLogin8',
+        minDeposit: '10 USD',
+        minSpread: '0.01',
+        maxLeverage: '1:1000',
+        icon: '/static/images/info/bank-information-3.webp',
+    }
+])
+
+// 过滤后的账户列表
+const filteredAccounts = computed(() => {
+    return standardAccounts.value.filter(account => account.showCondition())
+})
+
+// 当前选中的账户 ID
+const selectedAccountId = ref(7)
+
+// 轮播图当前索引
+const currentSwiperIndex = computed(() => {
+    const index = filteredAccounts.value.findIndex(a => a.id === selectedAccountId.value)
+    return index > -1 ? index : 0
+})
+
+// 账户选择事件
+const onAccountSelect = (id) => {
+    selectedAccountId.value = id
+}
+
+// 轮播图切换事件
+const onSwiperChange = (e) => {
+    const index = e.detail.current
+    const account = filteredAccounts.value[index]
+    if (account) {
+        selectedAccountId.value = account.id
+    }
+}
+
+// 继续按钮点击事件,向上传递选中的账户信息
+const handleContinue = () => {
+    router.push({
+        path: "/pages/customer/create-account",
+        query: { id: selectedAccountId.value, server: server.value },
+    });
+}
+</script>
+
+<style lang="scss" scoped>
+@import "@/uni.scss";
+
+.account-selector {
+    background-color: #fff;
+    overflow: hidden;
+}
+
+.table-wrapper {
+    width: 100%;
+    overflow-x: auto;
+
+    white-space: nowrap;
+}
+
+.account-table {
+    min-width: px2rpx(350);
+    margin-bottom: px2rpx(10);
+    /* 保证在小屏上可滚动 */
+    display: flex;
+    flex-direction: column;
+    font-size: px2rpx(14);
+    color: #333;
+}
+
+.table-header {
+    display: flex;
+    padding: px2rpx(10) 0;
+    font-weight: 500;
+    color: #666;
+
+    .header-cell {
+        flex: 1;
+        text-align: center;
+        padding: 0 px2rpx(8);
+        white-space: normal;
+        word-break: break-word;
+    }
+
+    .type-cell {
+        flex: 2;
+        text-align: left;
+        padding-left: px2rpx(12);
+    }
+}
+
+.professional-header {
+    margin-top: px2rpx(8);
+}
+
+.account-row {
+    display: flex;
+    align-items: center;
+    padding: px2rpx(12) 0;
+    margin: px2rpx(12) 0;
+    border: 1px solid rgba(108, 133, 149, 0.2);
+    border-radius: px2rpx(8);
+
+    &:hover {
+        box-shadow: 0 10px 15px -3px rgba(7, 10, 12, 0.08), 0 4px 6px -4px rgba(7, 10, 12, 0.08), 0 0 4px 0 rgba(7, 10, 12, 0.08);
+    }
+
+    &.active {
+        background-color: rgba(108, 133, 149, 0.07843);
+    }
+
+    .row-cell {
+        flex: 1;
+        text-align: center;
+        padding: 0 px2rpx(8);
+        font-size: px2rpx(12);
+        color: #1e2a3a;
+        white-space: normal;
+        word-break: break-word;
+    }
+
+    .type-cell {
+        flex: 2;
+        text-align: left;
+        padding-left: px2rpx(12);
+    }
+}
+
+.radio-group {
+    display: flex;
+    align-items: center;
+    width: 100%;
+}
+
+.radio-label {
+    display: flex;
+    align-items: center;
+    gap: px2rpx(6);
+    width: 100%;
+}
+
+radio {
+    transform: scale(0.8);
+    margin-right: px2rpx(4);
+}
+
+.account-icon {
+    width: px2rpx(48);
+    height: px2rpx(48);
+    margin-right: px2rpx(24);
+    flex-shrink: 0;
+}
+
+.account-info {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    text-align: left;
+
+    .account-name {
+        font-size: px2rpx(14);
+        font-weight: 500;
+        color: #1e2a3a;
+        margin-bottom: px2rpx(4);
+    }
+
+    .account-desc {
+        font-size: px2rpx(12);
+        color: #7f8c8d;
+        line-height: 1.4;
+    }
+}
+
+.mobile-view {
+    display: none;
+}
+
+@media screen and (max-width: 600px) {
+    .pc-view {
+        display: none;
+    }
+
+    .mobile-view {
+        display: block;
+        padding: px2rpx(20) 0;
+    }
+
+    .account-swiper {
+        height: px2rpx(520);
+        width: 100%;
+
+    }
+
+    .account-card {
+        background: #fff;
+        border-radius: px2rpx(8);
+        margin: px2rpx(2) px2rpx(20);
+        padding: px2rpx(30);
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        text-align: center;
+        border: 2px solid transparent;
+        transition: all 0.3s;
+        height: px2rpx(400);
+        color: rgb(20, 29, 34);
+        box-shadow:
+            rgba(54, 61, 66, 0.15) 0px 0px 1px 0px,
+            rgba(54, 61, 66, 0.04) 0px 2px 2px 0px,
+            rgba(54, 61, 66, 0.12) 0px 2px 8px 0px,
+            rgba(54, 61, 66, 0.08) 0px -2px 4px 0px;
+        transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1);
+        overflow: hidden;
+
+        &.active {
+            transform: translateY(px2rpx(-5));
+        }
+
+        .card-img {
+            width: px2rpx(120);
+            height: px2rpx(120);
+            margin-bottom: px2rpx(20);
+        }
+
+        .card-title {
+            font-size: px2rpx(24);
+            font-weight: 700;
+            color: #1e2a3a;
+            margin-bottom: px2rpx(8);
+        }
+
+        .card-tag {
+            background: #f0f2f5;
+            padding: px2rpx(4) px2rpx(12);
+            border-radius: px2rpx(20);
+            margin-bottom: px2rpx(16);
+
+            .tag-label {
+                font-size: px2rpx(12);
+                color: #666;
+            }
+        }
+
+        .card-desc {
+            font-size: px2rpx(14);
+            color: #7f8c8d;
+            line-height: 1.6;
+            margin-bottom: px2rpx(24);
+            height: px2rpx(44);
+            overflow: hidden;
+        }
+
+        .card-info-stack {
+            width: 100%;
+            display: flex;
+            flex-direction: column;
+            gap: px2rpx(12);
+
+            .info-row {
+                display: flex;
+                justify-content: space-between;
+                align-items: baseline;
+                position: relative;
+                font-size: px2rpx(14);
+
+                &::after {
+                    content: "";
+                    flex: 1;
+                    margin: 0 px2rpx(10);
+                    border-bottom: 1px dotted #ddd;
+                    height: 1px;
+                }
+
+                .label {
+                    color: #666;
+                    order: 1;
+                }
+
+                .value {
+                    color: #1e2a3a;
+                    font-weight: 500;
+                    order: 3;
+                }
+            }
+        }
+    }
+
+    .action-button {
+        justify-content: center !important;
+        // padding: 0 px2rpx(20);
+
+        .btn {
+            width: 100%;
+            min-width: unset !important;
+        }
+    }
+
+    .terms-section {
+        text-align: center;
+        padding: 0 px2rpx(20);
+    }
+}
+
+.action-button {
+    width: 100%;
+    display: flex;
+    justify-content: flex-end;
+    margin-top: px2rpx(40);
+
+    .btn {
+        width: px2rpx(320);
+        background-color: #1e2a3a;
+        padding: px2rpx(12) px2rpx(20);
+        border-radius: px2rpx(8);
+        text-align: center;
+        cursor: pointer;
+        box-sizing: border-box;
+        transition: all 0.2s;
+
+        &:active {
+            opacity: 0.9;
+            transform: scale(0.98);
+        }
+
+        .button-text {
+            color: #fff;
+            font-size: px2rpx(16);
+            font-weight: 600;
+        }
+    }
+}
+
+.terms-section {
+    margin: px2rpx(30) 0;
+    font-size: px2rpx(14);
+    line-height: 1.7;
+    color: #666;
+    text-align: center;
+
+    .pdfLink {
+        margin-left: px2rpx(4);
+
+        a {
+            color: var(--color-primary);
+            text-decoration: none;
+
+            &:hover {
+                text-decoration: underline;
+            }
+        }
+    }
+}
+</style>

+ 119 - 45
pages/customer/components/AccountCard.vue

@@ -12,12 +12,14 @@
         <!-- 标签区域 -->
         <view class="labels-container">
             <view class="labels">
-                <view v-for="(label, index) in account.labels" :key="index" class="label-badge">
-                    {{ label }}
-                </view>
+                <template v-for="(label, index) in account.labels" :key="index">
+                    <view v-if="label" class="label-badge">
+                        {{ label }}
+                    </view>
+                </template>
             </view>
             <view class="account-number"># {{ account.accountNumber }}</view>
-            <view class="account-nickname">{{ account.nickname }}</view>
+            <view class="account-nickname">{{ nickName }}</view>
         </view>
 
         <!-- 主要内容区域(余额和操作按钮) -->
@@ -42,9 +44,8 @@
                     </view>
                     <text class="circle-label">交易</text>
                 </view>
-
                 <!-- 入金(带限制包装,此处简化) -->
-                <view class="circle-btn" @click="toDeposit">
+                <view class="circle-btn" @click="toDeposit" v-if="!isDemo">
                     <view class="circle-icon">
                         <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
                             stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -58,7 +59,7 @@
                 </view>
 
                 <!-- 出金 -->
-                <view class="circle-btn" @click="toWithdraw">
+                <view class="circle-btn" @click="toWithdraw" v-if="!isDemo">
                     <view class="circle-icon">
                         <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
                             stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -71,7 +72,7 @@
                 </view>
 
                 <!-- 转账 -->
-                <view class="circle-btn" @click="toTransfer">
+                <view class="circle-btn" @click="toTransfer" v-if="!isDemo">
                     <view class="circle-icon">
                         <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
                             <path d="M21 17H3M21 17L17.5 20.5M21 17L17.5 13.5M6.5 10.5L3 7M3 7L6.5 3.5M3 7H21"
@@ -82,17 +83,22 @@
                 </view>
 
                 <!-- 更多(三点) -->
-                <view class="circle-btn" @click="handleAction('more')">
-                    <view class="circle-icon">
-                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
-                            stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
-                            <path d="M12 12m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
-                            <path d="M12 19m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
-                            <path d="M12 5m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
-                        </svg>
+                <cwg-dropdown @open="onOpen" @close="onClose" :menu-list="customMenuList"
+                    @menuClick="handleCustomClick">
+                    <view class="circle-btn">
+                        <view class="circle-icon">
+                            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
+                                fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
+                                stroke-linejoin="round">
+                                <path d="M12 12m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
+                                <path d="M12 19m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
+                                <path d="M12 5m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
+                            </svg>
+                        </view>
+                        <text class="circle-label">更多</text>
                     </view>
-                    <text class="circle-label">更多</text>
-                </view>
+                </cwg-dropdown>
+
             </view>
 
             <!-- 桌面端按钮组(>1100px显示) -->
@@ -108,7 +114,7 @@
                     </span>
                     交易
                 </view>
-                <view class="action-btn" @click="toDeposit">
+                <view class="action-btn" @click="toDeposit" v-if="!isDemo">
                     <span class="btn-icon">
                         <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
                             stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -120,7 +126,7 @@
                     </span>
                     入金
                 </view>
-                <view class="action-btn" @click="toWithdraw">
+                <view class="action-btn" @click="toWithdraw" v-if="!isDemo">
                     <span class="btn-icon">
                         <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
                             stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -131,7 +137,7 @@
                     </span>
                     出金
                 </view>
-                <view class="action-btn" @click="toTransfer">
+                <view class="action-btn" @click="toTransfer" v-if="!isDemo">
                     <span class="btn-icon">
                         <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
                             <path d="M21 17H3M21 17L17.5 20.5M21 17L17.5 13.5M6.5 10.5L3 7M3 7L6.5 3.5M3 7H21"
@@ -140,14 +146,18 @@
                     </span>
                     转账
                 </view>
-                <view class="action-btn icon-only" @click="handleAction('more')">
-                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
-                        stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
-                        <path d="M12 12m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
-                        <path d="M12 19m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
-                        <path d="M12 5m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
-                    </svg>
-                </view>
+                <cwg-dropdown @open="onOpen" @close="onClose" :menu-list="customMenuList"
+                    @menuClick="handleCustomClick">
+                    <view class="action-btn icon-only">
+                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
+                            stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                            <path d="M12 12m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
+                            <path d="M12 19m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
+                            <path d="M12 5m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0" />
+                        </svg>
+                    </view>
+                </cwg-dropdown>
+
             </view>
         </view>
         <view ref="infoBottomRef" class="info-bottom" :style="{
@@ -185,7 +195,7 @@
                 </view>
 
                 <!-- 更改交易密码按钮 -->
-                <view class="change-password-btn" @click="handleChangePassword">
+                <view class="change-password-btn" @click="handleAction('changePassword1')" v-if="!isDemo">
                     <span class="btn-icon">
                         <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
                             stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -200,22 +210,36 @@
 
         <!-- 通知区域(预留) -->
         <view class="notificators"></view>
+        <TerminalDialog v-model:visible="terminalDialogVisible" />
+        <!-- <TerminalNickNameDialog v-model:visible="terminalNickNameDialogVisible" :account="account"
+            @save="saveNickName" /> -->
+        <TerminalChangePasswordDialog v-model:visible="terminalChangePasswordDialogVisible" :pwdType="pwdType"
+            :account="account" />
+        <TerminalInfoDialog v-model:visible="terminalInfoDialogVisible" :accountNumber="accountInfo.login"
+            :form="accountInfo" :fieldList="fieldList" />
     </view>
 </template>
 
 <script setup lang="ts">
-import { ref, computed, onMounted, nextTick, onBeforeUnmount } from 'vue';
+import { ref, computed, onMounted, nextTick, onBeforeUnmount, watch } from 'vue';
 import useRouter from "@/hooks/useRouter";
 const router = useRouter();
 import { useI18n } from 'vue-i18n';
 const { t, locale } = useI18n();
+import TerminalDialog from './TerminalDialog.vue'
+import TerminalNickNameDialog from './TerminalNickNameDialog.vue'
+import TerminalChangePasswordDialog from './TerminalChangePasswordDialog.vue'
+import TerminalInfoDialog from './TerminalInfoDialog.vue'
 
-
+const props = defineProps<{
+    account: Account;
+}>();
+const accountInfo = ref(props.account)
 // 定义账户数据类型
 export interface Account {
     labels: string[];          // 标签数组,如 ['真实', 'MT4', 'Standard']
     accountNumber: string;      // 账号,如 '85319215'
-    nickname: string;           // 昵称,如 '标准账户'
+    nickName: string;           // 昵称,如 '标准账户'
     balance: number;            // 余额数字
     currency: string;           // 货币,如 'USD'
     actualLeverage: string;     // 实际杠杆,如 '1:2000'
@@ -228,6 +252,23 @@ export interface Account {
     login: string;              // 登录名,如 '85319215'
     balanceWithSymbol: string;              // 余额,如 '85319215'
 }
+const isDemo = computed(() => accountInfo.value.listType == 'demo')
+
+const fieldList = ref([
+    { label: '账户类型', key: 'nickname', copyable: false },
+    { label: t('Label.Leverage'), key: 'actualLeverage', copyable: false },
+    { label: '浮动盈/亏', key: 'floatingPL', copyable: false },
+    { label: t('Label.Balance'), key: 'balanceWithSymbol', copyable: false },
+    { label: t('Label.Equity'), key: 'equityWithSymbol', copyable: false },
+    { label: t('Label.Credit'), key: 'creditWithSymbol', copyable: false },
+    { label: '平台', key: 'platform', copyable: false },
+    { label: '账号', key: 'login', copyable: true }
+])
+const nickName = ref(accountInfo.value.nickName)
+const saveNickName = (newNickName) => {
+    nickName.value = newNickName
+    accountInfo.value.nickName = newNickName
+}
 
 const infoBottomRef = ref(null);
 const infoBottomHeight = ref(0);
@@ -256,47 +297,80 @@ const toggleExpand = () => {
     }
 };
 
-const props = defineProps<{
-    account: Account;
-}>();
 
+const terminalDialogVisible = ref(false)
+const terminalChangePasswordDialogVisible = ref(false)
+const terminalInfoDialogVisible = ref(false)
+const pwdType = ref(1)
 // 处理按钮操作
 const handleAction = (type: string) => {
+    console.log(type == 'info', type, 'info');
+    switch (type) {
+        case 'trade':
+            terminalDialogVisible.value = true
+            break;
+        case 'changePassword1':
+            pwdType.value = 1
+            terminalChangePasswordDialogVisible.value = true
+            break;
+        case 'changePassword2':
+            pwdType.value = 2
+            terminalChangePasswordDialogVisible.value = true
+            break;
+        case 'info':
+            console.log(type);
+            terminalInfoDialogVisible.value = true
+            break;
+        default:
+            break;
+    }
 };
 
+const customMenuList = computed(() => !isDemo.value ? [{ label: '修改交易密码', type: 'changePassword1' }, { label: '修改投资者密码', type: 'changePassword2' }, { label: '账户信息', type: 'info' }] : [{ label: '账户信息', type: 'info' }])
+
+
+const handleCustomClick = (item, index) => {
+
+
+    handleAction(item.value.type)
+}
+
+
 // 复制文本
 const copy = (text: string) => {
     uni.setClipboardData({ data: text });
 };
 
+
+
 // 按钮对应的操作方法
 const toDeposit = () => {
-    router.push(`/pages/customer/deposit?login=${props.accountlogin}&type=${props.accounttype}&balance=${props.accountbalance}&currency=${props.accountcurrency}`)
+    router.push(`/pages/customer/deposit?login=${accountInfo.value.login}&type=${accountInfo.value.type}&balance=${accountInfo.value.balance}&currency=${accountInfo.value.currency}`)
 }
 
 const toWithdraw = () => {
-    router.push(`/pages/customer/withdraw?login=${props.accountlogin}&type=${props.accounttype}&balance=${props.accountbalance}&currency=${props.accountcurrency}`)
+    router.push(`/pages/customer/withdraw?login=${accountInfo.value.login}&type=${accountInfo.value.type}&balance=${accountInfo.value.balance}&currency=${accountInfo.value.currency}`)
 }
 
 const toTransfer = () => {
-    router.push(`/pages/customer/transfer?login=${props.accountlogin}&type=${props.accounttype}&balance=${props.accountbalance}&currency=${props.accountcurrency}`)
+    router.push(`/pages/customer/transfer?login=${accountInfo.value.login}&type=${accountInfo.value.type}&balance=${accountInfo.value.balance}&currency=${accountInfo.value.currency}`)
 }
 
 // 更改交易密码
 const handleChangePassword = () => {
-    const close = props.accountcloseFunctions?.indexOf('4') !== -1 ? 1 : 0
-    router.push(`/pages/customer/settings?login=${props.accountlogin}&platform=${props.accountplatform}&type=${props.accounttype}&currency=${props.accountcurrency}&leverage=${props.accountleverage}&close=${close}`)
+    const close = accountInfo.value.closeFunctions?.indexOf('4') !== -1 ? 1 : 0
+    router.push(`/pages/customer/settings?login=${accountInfo.value.login}&platform=${accountInfo.value.platform}&type=${accountInfo.value.type}&currency=${accountInfo.value.currency}&leverage=${accountInfo.value.leverage}&close=${close}`)
 }
 
 const toStandardRebate = () => {
-    router.push(`/pages/customer/standard/rebate?login=${props.accountlogin}`)
+    router.push(`/pages/customer/standard/rebate?login=${accountInfo.value.login}`)
 }
 // 格式化余额,拆分为整数和小数部分
 const balanceInteger = computed(() => {
-    return Math.floor(props.account.balance).toString();
+    return Math.floor(accountInfo.value.balance).toString();
 });
 const balanceDecimal = computed(() => {
-    const parts = props.account.balance.toFixed(2).split('.');
+    const parts = accountInfo.value.balance.toFixed(2).split('.');
     return parts[1] ? '.' + parts[1] : '.00';
 });
 // 在组件挂载后初始化高度
@@ -305,7 +379,7 @@ onMounted(() => {
         updateSubmenuHeight();
     });
     window.addEventListener('resize', handleResize);
-    isExpanded.value = props.account.isExpanded;
+    isExpanded.value = accountInfo.value.isExpanded;
 });
 // 监听窗口 resize
 const handleResize = () => {

+ 21 - 17
pages/customer/components/AccountList.vue

@@ -7,16 +7,14 @@
                     <cwg-icon icon="crm-plus" :size="16" color="#fff" />
                     <text v-t="'Custom.Index.AddAccount'" />
                 </view>
-                <view class="btn-primary" @click="openDeleteAccountDialogs()">
-                    <cwg-icon icon="crm-trash-can" :size="16" color="#fff" />
-                    <text v-t="'Tips.DeleteAccount'" />
-                </view>
             </view>
         </view>
-        <cwg-tabs v-model:cativeIndex="cativeIndex" :tabs="tabs" class="tabs-class" />
-        <AccountCard v-for="acc in accounts" :key="acc.accountNumber" :account="acc" @action="handleAction"
-            @copy="handleCopy" @change-password="handleChangePassword" />
-
+        <view class="tabs-class"><cwg-tabs v-model:cativeIndex="cativeIndex" :tabs="tabs" /></view>
+        <view v-if="accounts.length">
+            <AccountCard v-for="acc in accounts" :zhtype="cativeIndex" :key="acc.accountNumber" :account="acc" @action="handleAction"
+                @copy="handleCopy" @change-password="handleChangePassword" />
+        </view>
+        <cwg-empty-state v-else />
         <DeleteAccountDialogs ref="deleteAccountDialogRef" v-model:visible="deleteAccountDialogVisible" />
     </view>
 </template>
@@ -58,8 +56,8 @@ const typeMap = computed(() => ({
 }));
 const cativeIndex = ref(0)
 const tabs = computed(() => ([
-    { id: 'MT4', name: 'MT4' },
-    { id: 'MT5', name: 'MT5' }
+    { id: 'real', name: '真实' },
+    { id: 'demo', name: '模拟' }
 ]))
 
 const tableRef = ref(null)
@@ -152,7 +150,7 @@ const createAccount = () => {
 const isZh = computed(() => ['cn', 'zh', 'zhHant'].includes(locale.value));
 
 watch(cativeIndex, (newVal) => {
-    search.value.platform = tabs.value[newVal].id
+    // search.value.platform = tabs.value[newVal].id
     getAccountList()
 })
 
@@ -166,7 +164,7 @@ async function getCustomLoginInfo() {
                 res.data.customInfo.status == 2 &&
                 res.data.customInfo.applyRealStatus == 2
             ) {
-                router.push('/pages/customer/create-account')
+                router.push(`/pages/customer/account-select?server=${cativeIndex.value == 1 ? 'demo' : 'real'}`)
             } else {
                 // this.dialogCheck = true;
             }
@@ -177,11 +175,14 @@ async function getCustomLoginInfo() {
 }
 const AccountList = ref([])
 const getAccountList = async () => {
-    const res = await customApi.AccountList({
+    AccountList.value = []
+
+    const api = cativeIndex.value == 1 ? customApi.demoList : customApi.AccountAllList
+    const res = await api({
         page: {
             current: 1,
             size: 100
-        }, ...search.value
+        }
     })
     if (res.code === 200) {
         AccountList.value = res.data
@@ -197,10 +198,11 @@ function formatMoney(value) {
 
 // 转换数组
 const accounts = computed(() =>
-    AccountList.value.map((acc, index) => {
+    AccountList.value && AccountList.value.length != 0 ? AccountList.value.map((acc, index) => {
         const currency = acc.currency || 'USD';
         const floating = acc.floating ?? 0;
         let labels = ['真实', 'MT4', 'Standard'];
+        labels[0] = cativeIndex.value == 1 ? '模拟' : '真实';
         labels[1] = acc.platform || 'MT4';
         labels[2] = typeMap.value[acc.type];
         let nickname = typeMap.value[acc.type];
@@ -220,9 +222,10 @@ const accounts = computed(() =>
             floatingPL: formatMoney(floating), // 盈亏
             platform: acc.platform || 'MT4',
             server: acc.groupCode || '',
-            login: acc.login.toString()
+            login: acc.login.toString(),
+            listType: cativeIndex.value == 1 ? 'demo' : 'real'
         };
-    })
+    }) : []
 )
 onMounted(async () => {
     await getAccountList()
@@ -240,6 +243,7 @@ onMounted(async () => {
 }
 
 .tabs-class {
+    width: px2rpx(200);
     margin: px2rpx(20) 0;
 }
 

+ 1 - 1
pages/customer/components/DeleteAccountDialogs.vue

@@ -1,5 +1,5 @@
 <template>
-    <cwg-popup :title="t('Tips.DeleteAccount')" v-model:visible="props.visible" :showFooter="false"
+    <cwg-popup :title="t('Tips.DeleteAccount')" :visible="props.visible" :showFooter="false"
         @update:visible="$emit('update:visible', $event)">
         <scroll-view scroll-y class="account-list" :style="{ maxHeight: '40vh' }">
             <!-- 加载状态 -->

+ 184 - 0
pages/customer/components/PaymentMethodsList.vue

@@ -0,0 +1,184 @@
+<template>
+  <view class="payment-list">
+    <view v-for="item in list" :key="item.id" class="payment-card" :class="{ disabled: item.disabled }"
+      @click="handleClick(item)">
+      <view class="icon-wrapper">
+        <image class="icon" :src="imgUrl + item.icon" mode="widthFix" />
+      </view>
+      <view class="content">
+        <view class="header">
+          <text class="title">{{ item.name }}</text>
+        </view>
+        <view class="info-list">
+          <view class="info-item">
+            <text class="info-label" v-t="'Label.ProcessingTime'" />
+            <text class="info-value">{{ item.fundingTime }}</text>
+          </view>
+          <view class="info-item">
+            <text class="info-label" v-t="'Label.Fee'" />
+            <text class="info-value">{{ item.free != null ? item.free + '%' : '-' }}</text>
+          </view>
+          <view class="info-item">
+            <text class="info-label">限制</text>
+            <text class="info-value">{{ item.minAmount }}-{{ item.maxAmount }} {{ item.currency }}</text>
+          </view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { defineProps, defineEmits } from 'vue'
+import Config from '@/config/index'
+const { Code, Host80 } = Config
+const imgUrl = Host80
+// 定义 props,接收支付方式列表
+const props = defineProps({
+  list: {
+    type: Array,
+    default: () => []
+  }
+})
+
+// 定义事件,点击卡片时触发
+const emit = defineEmits(['select'])
+
+const handleClick = (item) => {
+  if (!item.disabled) {
+    emit('select', item)
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+@import "@/uni.scss";
+
+.payment-list {
+  display: grid;
+  grid-row-gap: px2rpx(16);
+  grid-column-gap: px2rpx(24);
+  grid-template-columns: repeat(auto-fill, minmax(px2rpx(320), 1fr));
+}
+
+.payment-card {
+  background-color: #fff;
+  border-radius: px2rpx(12);
+  padding: px2rpx(16);
+  display: flex;
+  align-items: flex-start;
+  border: 1px solid rgba(14, 15, 12, 0.08);
+  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+  cursor: pointer;
+  box-sizing: border-box;
+  gap: px2rpx(16);
+
+  &:hover {
+    transform: translateY(px2rpx(-2));
+    background-color: #fff;
+    box-shadow: 0 px2rpx(8) px2rpx(20) rgba(0, 0, 0, 0.06);
+    border-color: var(--color-primary, #007aff);
+  }
+
+  &.disabled {
+    opacity: 0.5;
+    cursor: not-allowed;
+    filter: grayscale(100%);
+  }
+
+  .icon-wrapper {
+    width: px2rpx(120);
+    height: px2rpx(120);
+    flex-shrink: 0;
+    border-radius: px2rpx(8);
+    background-color: var(--color-zinc-50, #f9f9f9);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    overflow: hidden;
+
+    .icon {
+      width: 80%;
+    }
+  }
+
+  .content {
+    flex: 1;
+    min-width: 0; // 防止文本溢出
+
+    .header {
+      margin-bottom: px2rpx(12);
+
+      .title {
+        font-size: px2rpx(16);
+        font-weight: 700;
+        color: var(--color-navy-900, #1e2a3a);
+        word-break: break-all;
+      }
+    }
+
+    .info-list {
+      .info-item {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: px2rpx(8);
+        font-size: px2rpx(13);
+        line-height: 1.4;
+
+        .info-label {
+          color: var(--color-zinc-500, #7f8c8d);
+          margin-right: px2rpx(8);
+          white-space: nowrap;
+        }
+
+        .info-value {
+          color: var(--color-navy-900, #1e2a3a);
+          font-weight: 600;
+          text-align: right;
+          word-break: break-all;
+        }
+
+        &:last-child {
+          margin-bottom: 0;
+        }
+      }
+    }
+  }
+}
+
+/* 移动端适配 */
+@media screen and (max-width: 768px) {
+  .payment-list {
+    grid-template-columns: 1fr;
+    grid-row-gap: px2rpx(12);
+  }
+
+  .payment-card {
+    padding: px2rpx(12);
+    gap: px2rpx(12);
+
+    .icon-wrapper {
+      width: px2rpx(90);
+      height: px2rpx(90);
+    }
+
+    .content {
+      .header {
+        margin-bottom: px2rpx(8);
+
+        .title {
+          font-size: px2rpx(15);
+        }
+      }
+
+      .info-list {
+        .info-item {
+          margin-bottom: px2rpx(4);
+          font-size: px2rpx(12);
+        }
+      }
+    }
+  }
+}
+</style>

+ 210 - 0
pages/customer/components/TerminalChangePasswordDialog.vue

@@ -0,0 +1,210 @@
+<template>
+    <cwg-popup :title="props.pwdType == 1 ? t('Custom.Settings.LoginPwd') : t('Custom.Settings.InvestorPwd')"
+        :visible="props.visible" :showFooter="false" @update:visible="$emit('update:visible', $event)">
+        <view class="popup-content">
+            <text class="account-number">{{ accountLabel }} {{ account.login }}</text>
+
+            <uni-forms :model="passwordInfo" labelWidth="200" label-position="top" class="crm-form">
+                <uni-forms-item
+                    :label="props.pwdType == 1 ? t('Custom.Settings.LoginPwdOld') : t('Custom.Settings.InvestorPwdOld')">
+                    <uni-easyinput type="password" :clearable="false" v-model="passwordInfo.oldPassword"
+                        :placeholder="props.pwdType == 1 ? t('Custom.Settings.LoginPwdOld') : t('Custom.Settings.InvestorPwdOld')" />
+                </uni-forms-item>
+                <uni-forms-item :label="t('Custom.Settings.NewPwd')">
+                    <uni-easyinput type="password" :clearable="false" v-model="passwordInfo.newPassword"
+                        :placeholder="t('Custom.Settings.NewPwd')" />
+                </uni-forms-item>
+            </uni-forms>
+
+            <view class="notice-list">
+                <view v-for="(item, index) in noticeItems" :key="index"
+                    :class="['notice-item', item.valid ? 'isOK' : '']">
+                    {{ item.label }}
+                </view>
+            </view>
+
+            <view class="save-btn">
+                <view class="btn primary" @click="save" :disabled="!isFormValid" v-t="'Btn.Save'" />
+            </view>
+        </view>
+    </cwg-popup>
+</template>
+
+<script setup>
+import { ref, computed } from 'vue'
+import { customApi } from '@/service/custom';
+import { useI18n } from 'vue-i18n'
+import { showToast } from "@/utils/toast";
+
+const { t } = useI18n()
+
+const props = defineProps({
+    visible: { type: Boolean, default: false },
+    account: { type: Object, default: () => ({}) },
+    accountLabel: { type: String, default: '账户: #' },
+    // 1: 交易密码, 2: 投资者密码
+    pwdType: { type: [Number, String], default: 1 },
+})
+
+const emit = defineEmits(['update:visible', 'save'])
+
+const passwordInfo = ref({
+    oldPassword: '',
+    newPassword: ''
+});
+
+const rule1 = computed(() => {
+    if (!passwordInfo.value.newPassword) return false;
+    return /^.{8,16}$/.test(passwordInfo.value.newPassword);
+});
+
+const rule2 = computed(() => {
+    return /^(?=.*?[a-z])(?=.*?[A-Z]).*$/.test(passwordInfo.value.newPassword);
+});
+
+const rule3 = computed(() => {
+    return /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?!.*([~!@&%$^\\(\\)#_]).*\\1.*\\1)[A-Za-z0-9~!@&%$^\\(\\)#_]{8,16}$/.test(
+        passwordInfo.value.newPassword
+    );
+});
+
+const noticeItems = computed(() => [
+    { label: t('signup.form.rules.1st'), valid: rule1.value },
+    { label: t('signup.form.rules.2nd'), valid: rule2.value },
+    { label: t('signup.form.rules.3rd'), valid: rule3.value }
+]);
+
+const isFormValid = computed(() => {
+    return rule1.value && rule2.value && rule3.value && passwordInfo.value.oldPassword && passwordInfo.value.newPassword;
+});
+
+const flag = ref(false); // 防止重复提交
+
+const save = async () => {
+    if (!isFormValid.value) {
+        return;
+    }
+
+    if (flag.value) return;
+    flag.value = true;
+
+    try {
+        let res;
+        if (props.pwdType == 1) {
+            // 修改交易账户密码
+            res = await customApi.ChangeDealPassword({
+                login: props.account.login,
+                ...passwordInfo.value
+            });
+        } else {
+            // 修改投资者密码
+            res = await customApi.ChangeInvestorOassword({
+                login: props.account.login,
+                ...passwordInfo.value
+            });
+        }
+
+        if (res.code == 200) {
+            showToast(t('Msg.Success'));
+            emit('update:visible', false);
+            passwordInfo.value = {
+                oldPassword: '',
+                newPassword: ''
+            }
+            emit('save');
+
+        } else {
+            showToast(res.msg);
+        }
+    } catch (error) {
+        console.error(error);
+    } finally {
+        flag.value = false;
+    }
+}
+</script>
+
+<style scoped lang="scss">
+@import "@/uni.scss";
+@media (min-width: 768px) {
+    :deep(.cwg-dialog) {
+        background-color: var(--color-white);
+        border-radius: px2rpx(8);
+        width: px2rpx(480) !important;
+    }
+}
+
+.popup-content {
+    padding: px2rpx(16);
+}
+
+.account-number {
+    display: block;
+    font-size: px2rpx(14);
+    color: #141d22;
+    margin-bottom: px2rpx(24);
+}
+
+.crm-form {
+    :deep(.uni-forms-item) {
+        margin-bottom: px2rpx(16);
+    }
+
+    :deep(.uni-easyinput__content) {
+        border: none !important;
+        background-color: var(--color-zinc-100) !important;
+    }
+}
+
+.notice-list {
+    margin: px2rpx(10) 0;
+    padding: 0 px2rpx(12) px2rpx(12) 0;
+
+    .notice-item {
+        font-size: px2rpx(14);
+        color: var(--color-yellow-800);
+        line-height: px2rpx(24);
+    }
+
+    .isOK {
+        color: var(--color-success);
+    }
+}
+
+.save-btn {
+    width: 100%;
+    display: flex;
+    justify-content: flex-end;
+    margin-top: px2rpx(20);
+
+    .btn {
+        border: 1px solid rgba(108, 133, 149, 0);
+        border-radius: px2rpx(8);
+        padding: px2rpx(8) px2rpx(20);
+        font-size: px2rpx(14);
+        color: #2e3a47;
+        display: inline-flex;
+        align-items: center;
+        justify-content: center;
+        gap: px2rpx(8);
+        cursor: pointer;
+        transition: all 0.2s;
+        height: px2rpx(40);
+        box-sizing: border-box;
+        background-color: rgba(108, 133, 149, 0.08);
+
+        &.primary {
+            background-color: var(--color-navy-700);
+            color: #fff;
+
+            &:hover {
+                background-color: var(--color-navy-600);
+            }
+
+            &[disabled] {
+                cursor: not-allowed;
+            }
+        }
+    }
+}
+</style>

+ 332 - 0
pages/customer/components/TerminalDialog.vue

@@ -0,0 +1,332 @@
+<template>
+    <cwg-popup :title="t('Shop.Index.Transaction')" :visible="props.visible" :showFooter="false"
+        @update:visible="$emit('update:visible', $event)">
+        <view class="card-list">
+            <view class="card" @click="handleWebClick">
+                <view class="card-icon">
+                    <svg width="48" height="48" viewBox="0 0 48 48" class="muiltr-l39xog">
+                        <rect width="48" height="48" rx="8" fill="#141D22"></rect>
+                        <path
+                            d="M24.3183 13.6533C26.025 13.6533 27.4116 12.2667 27.4116 10.56C27.4116 8.85334 26.025 7.46667 24.3183 7.46667C22.6116 7.46667 21.225 8.85334 21.225 10.56C21.225 12.2667 22.6116 13.6533 24.3183 13.6533Z"
+                            fill="white"></path>
+                        <path
+                            d="M24.3174 31.5951C27.3254 31.5951 29.768 29.1524 29.768 26.1444C29.768 23.1364 27.3254 20.6937 24.3174 20.6937C21.3094 20.6937 18.8667 23.1364 18.8667 26.1444C18.8667 29.1524 21.3094 31.5951 24.3174 31.5951Z"
+                            fill="white"></path>
+                        <path
+                            d="M28.8627 12.4052C28.8627 12.4052 28.7774 12.3732 28.724 12.3625C28.0094 14.1012 26.3027 15.3279 24.308 15.3279C22.3134 15.3279 20.6067 14.1012 19.892 12.3625C19.8494 12.3732 19.8067 12.3945 19.7534 12.4052C18.26 12.9065 17.3 14.3572 17.3 15.9252V20.3092C17.4494 20.5012 17.588 20.7039 17.7587 20.8745L18.868 21.9839C19.4227 21.2479 20.1267 20.6292 20.9267 20.1705V18.9759C20.9267 18.2825 21.4814 17.7279 22.1747 17.7279H26.4094C27.1027 17.7279 27.6574 18.2825 27.6574 18.9759V20.1065C28.532 20.5865 29.2787 21.2585 29.8654 22.0479L30.8254 21.0879C30.996 20.9172 31.1454 20.7145 31.284 20.5225V15.9145C31.284 14.3465 30.324 12.8959 28.8307 12.3945L28.8627 12.4052Z"
+                            fill="white"></path>
+                        <path
+                            d="M13.245 32.4272C12.3916 30.9445 10.5036 30.4325 9.02095 31.2859C7.53828 32.1392 7.02628 34.0272 7.87962 35.5099C8.73295 36.9925 10.621 37.5045 12.1036 36.6512C13.5863 35.7979 14.0983 33.9099 13.245 32.4272Z"
+                            fill="white"></path>
+                        <path
+                            d="M9.92847 29.2056V29.2376C11.7951 28.9923 13.7151 29.8563 14.7071 31.5843C15.6991 33.3123 15.4858 35.403 14.3338 36.8856C14.3338 36.8856 14.3445 36.8963 14.3551 36.907C15.5605 38.0163 17.3845 38.1123 18.8031 37.3016L22.5151 35.1683C22.6111 34.9443 22.7071 34.7203 22.7711 34.4856L23.1765 32.971C22.2591 32.8536 21.3738 32.555 20.5738 32.0856L19.3258 32.8003C18.8458 33.0776 18.2378 32.907 17.9711 32.4376L15.6138 28.331C15.3365 27.851 15.5071 27.243 15.9765 26.9763L17.1818 26.283C17.1605 25.291 17.3738 24.299 17.7685 23.3923L16.4458 23.0403C16.2111 22.9763 15.9658 22.955 15.7311 22.923L11.8271 25.163C10.4085 25.9736 9.57647 27.6056 9.92847 29.2056Z"
+                            fill="white"></path>
+                        <path
+                            d="M35.3692 32.4272C36.2226 30.9445 38.1106 30.4325 39.5932 31.2859C41.0759 32.1392 41.5879 34.0272 40.7346 35.5099C39.8812 36.9925 37.9932 37.5045 36.5106 36.6512C35.0279 35.7979 34.5159 33.9099 35.3692 32.4272Z"
+                            fill="white"></path>
+                        <path
+                            d="M38.6959 29.2058V29.2378C36.8292 28.9925 34.9092 29.8565 33.9172 31.5845C32.9252 33.3125 33.1385 35.4031 34.2905 36.8858C34.2905 36.8858 34.2799 36.8965 34.2692 36.9071C33.0639 38.0165 31.2399 38.1125 29.8212 37.3018L26.1092 35.1685C26.0132 34.9445 25.9172 34.7205 25.8532 34.4858L25.4479 32.9711C26.3652 32.8538 27.2505 32.5551 28.0505 32.0858L28.9252 32.5871C29.6079 32.9818 30.4825 32.7471 30.8772 32.0645L32.8079 28.7045C33.2025 28.0218 32.9679 27.1471 32.2852 26.7525L31.4532 26.2725C31.4745 25.2805 31.2612 24.2885 30.8665 23.3818L32.1892 23.0298C32.4239 22.9658 32.6692 22.9445 32.9039 22.9125L36.8079 25.1525C38.2265 25.9631 39.0585 27.5951 38.7065 29.1951L38.6959 29.2058Z"
+                            fill="white"></path>
+                    </svg>
+                </view>
+                <view class="card-content">
+                    <text class="card-title">{{ webTitle }}</text>
+                    <text class="card-desc">{{ t('Downloadpage.item40') }}</text>
+                </view>
+                <view class="card-arrow">
+                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
+                        stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
+                        class="muiltr-isq1pf">
+                        <path d="M5 12l14 0"></path>
+                        <path d="M13 18l6 -6"></path>
+                        <path d="M13 6l6 6"></path>
+                    </svg>
+                </view>
+            </view>
+            <view class="card" @click="handleDownloadClick">
+                <view class="card-icon">
+                    <svg width="48" height="48" viewBox="0 0 48 48" class="muiltr-l39xog">
+                        <rect width="48" height="48" rx="8" fill="#141D22"></rect>
+                        <path
+                            d="M24.3183 13.6533C26.025 13.6533 27.4116 12.2667 27.4116 10.56C27.4116 8.85334 26.025 7.46667 24.3183 7.46667C22.6116 7.46667 21.225 8.85334 21.225 10.56C21.225 12.2667 22.6116 13.6533 24.3183 13.6533Z"
+                            fill="white"></path>
+                        <path
+                            d="M24.3174 31.5951C27.3254 31.5951 29.768 29.1524 29.768 26.1444C29.768 23.1364 27.3254 20.6937 24.3174 20.6937C21.3094 20.6937 18.8667 23.1364 18.8667 26.1444C18.8667 29.1524 21.3094 31.5951 24.3174 31.5951Z"
+                            fill="white"></path>
+                        <path
+                            d="M28.8627 12.4052C28.8627 12.4052 28.7774 12.3732 28.724 12.3625C28.0094 14.1012 26.3027 15.3279 24.308 15.3279C22.3134 15.3279 20.6067 14.1012 19.892 12.3625C19.8494 12.3732 19.8067 12.3945 19.7534 12.4052C18.26 12.9065 17.3 14.3572 17.3 15.9252V20.3092C17.4494 20.5012 17.588 20.7039 17.7587 20.8745L18.868 21.9839C19.4227 21.2479 20.1267 20.6292 20.9267 20.1705V18.9759C20.9267 18.2825 21.4814 17.7279 22.1747 17.7279H26.4094C27.1027 17.7279 27.6574 18.2825 27.6574 18.9759V20.1065C28.532 20.5865 29.2787 21.2585 29.8654 22.0479L30.8254 21.0879C30.996 20.9172 31.1454 20.7145 31.284 20.5225V15.9145C31.284 14.3465 30.324 12.8959 28.8307 12.3945L28.8627 12.4052Z"
+                            fill="white"></path>
+                        <path
+                            d="M13.245 32.4272C12.3916 30.9445 10.5036 30.4325 9.02095 31.2859C7.53828 32.1392 7.02628 34.0272 7.87962 35.5099C8.73295 36.9925 10.621 37.5045 12.1036 36.6512C13.5863 35.7979 14.0983 33.9099 13.245 32.4272Z"
+                            fill="white"></path>
+                        <path
+                            d="M9.92847 29.2056V29.2376C11.7951 28.9923 13.7151 29.8563 14.7071 31.5843C15.6991 33.3123 15.4858 35.403 14.3338 36.8856C14.3338 36.8856 14.3445 36.8963 14.3551 36.907C15.5605 38.0163 17.3845 38.1123 18.8031 37.3016L22.5151 35.1683C22.6111 34.9443 22.7071 34.7203 22.7711 34.4856L23.1765 32.971C22.2591 32.8536 21.3738 32.555 20.5738 32.0856L19.3258 32.8003C18.8458 33.0776 18.2378 32.907 17.9711 32.4376L15.6138 28.331C15.3365 27.851 15.5071 27.243 15.9765 26.9763L17.1818 26.283C17.1605 25.291 17.3738 24.299 17.7685 23.3923L16.4458 23.0403C16.2111 22.9763 15.9658 22.955 15.7311 22.923L11.8271 25.163C10.4085 25.9736 9.57647 27.6056 9.92847 29.2056Z"
+                            fill="white"></path>
+                        <path
+                            d="M35.3692 32.4272C36.2226 30.9445 38.1106 30.4325 39.5932 31.2859C41.0759 32.1392 41.5879 34.0272 40.7346 35.5099C39.8812 36.9925 37.9932 37.5045 36.5106 36.6512C35.0279 35.7979 34.5159 33.9099 35.3692 32.4272Z"
+                            fill="white"></path>
+                        <path
+                            d="M38.6959 29.2058V29.2378C36.8292 28.9925 34.9092 29.8565 33.9172 31.5845C32.9252 33.3125 33.1385 35.4031 34.2905 36.8858C34.2905 36.8858 34.2799 36.8965 34.2692 36.9071C33.0639 38.0165 31.2399 38.1125 29.8212 37.3018L26.1092 35.1685C26.0132 34.9445 25.9172 34.7205 25.8532 34.4858L25.4479 32.9711C26.3652 32.8538 27.2505 32.5551 28.0505 32.0858L28.9252 32.5871C29.6079 32.9818 30.4825 32.7471 30.8772 32.0645L32.8079 28.7045C33.2025 28.0218 32.9679 27.1471 32.2852 26.7525L31.4532 26.2725C31.4745 25.2805 31.2612 24.2885 30.8665 23.3818L32.1892 23.0298C32.4239 22.9658 32.6692 22.9445 32.9039 22.9125L36.8079 25.1525C38.2265 25.9631 39.0585 27.5951 38.7065 29.1951L38.6959 29.2058Z"
+                            fill="white"></path>
+                    </svg>
+                </view>
+                <view class="card-content">
+                    <text class="card-title">{{ downloadItem.name }}</text>
+                    <text class="card-desc">{{ downloadItem.description }}</text>
+                </view>
+                <view class="card-arrow">
+                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
+                        stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                        <path d="M5 12l14 0"></path>
+                        <path d="M13 18l6 -6"></path>
+                        <path d="M13 6l6 6"></path>
+                    </svg>
+                </view>
+            </view>
+        </view>
+    </cwg-popup>
+</template>
+
+<script setup>
+import { ref, computed, onMounted } from 'vue'
+import { useI18n } from 'vue-i18n'
+import { TerminalMap } from '../composables/TerminalMap'
+import config from '@/config';
+const { t, locale } = useI18n()
+const props = defineProps({
+    visible: { type: Boolean, default: false },
+    mtType: { type: String, default: 'MT4', validator: val => ['MT4', 'MT5'].includes(val) }
+})
+const emit = defineEmits(['update:visible'])
+
+// ---------- 平台相关 ----------
+const platform = ref('')
+const baseUrl = ref('')
+const domain = ref('')
+
+// 获取当前运行平台
+const getPlatform = () => {
+    // #ifdef APP-PLUS
+    const sys = uni.getSystemInfoSync()
+    return sys.platform === 'android' ? 'android' : 'ios'
+    // #endif
+    // #ifdef H5
+    const ua = navigator.userAgent.toLowerCase()
+    if (ua.includes('windows')) return 'windows'
+    if (ua.includes('mac')) return 'mac'
+    if (ua.includes('android')) return 'android'
+    if (ua.includes('iphone') || ua.includes('ipad')) return 'ios'
+    return 'windows'
+    // #endif
+}
+
+// 初始化环境变量(域名、基础URL)
+const initEnv = () => {
+    baseUrl.value = config.Host80
+    domain.value = config.ho
+}
+
+// 替换 URL 中的占位符
+const resolveUrl = (urlTemplate) => {
+    if (!urlTemplate) return ''
+    let url = urlTemplate
+    if (url.includes('{myLink}')) {
+        url = url.replace(/{myLink}/g, baseUrl.value)
+    }
+    if (url.includes('{domain}')) {
+        url = url.replace(/{domain}/g, domain.value)
+    }
+    return url
+}
+
+// 获取当前 MT 版本的数据
+const mtData = computed(() => TerminalMap[props.mtType] || {})
+
+// Web 端标题(根据版本显示不同标题)
+const webTitle = computed(() => {
+    return props.mtType === 'MT4' ? t('Downloadpage.item38') : t('Downloadpage.item39')
+})
+
+// 根据当前 MT 版本和平台,获取对应的下载端信息
+const downloadItem = computed(() => {
+    const data = mtData.value
+    if (!data) return null
+
+    let item = null
+    if (platform.value === 'windows' || platform.value === 'mac') {
+        const list = data.desktop?.[platform.value] || []
+        item = list[0]
+    } else if (platform.value === 'android' || platform.value === 'ios') {
+        const list = data.mobile?.[platform.value] || []
+        item = list[0]
+    }
+
+    if (!item) return null
+
+    // 构造显示名称和描述(国际化)
+    let name = ''
+    let description = ''
+    if (item.name) {
+        name = item.name
+        description = item.descriptionKey ? t(item.descriptionKey) : (item.description || '')
+    } else if (item.nameKey) {
+        name = t(item.nameKey)
+        description = item.descriptionKey ? t(item.descriptionKey) : ''
+    }
+
+    // 图标路径处理
+    let icon = item.icon || ''
+    if (platform.value === 'android' && !icon) icon = 'android-os-3-72.png'
+    if (platform.value === 'ios' && !icon) icon = 'apple-os-3-72.png'
+    if (platform.value === 'windows' && !icon) icon = 'windows-os-1-48.png'
+    if (platform.value === 'mac' && !icon) icon = 'apple-os-1-48.png'
+
+    return {
+        url: resolveUrl(item.url),
+        filename: item.filename,
+        name,
+        description,
+        icon
+    }
+})
+
+// 获取 Web 端链接(根据当前 MT 版本和语言)
+const webUrl = computed(() => {
+    const data = mtData.value
+    if (!data || !data.web) return ''
+    let url = data.web.url
+    // 替换动态变量
+    url = resolveUrl(url)
+    // 替换语言占位符({lang})
+    url = url.replace(/{lang}/g, locale.value)
+    return url
+})
+
+// 处理 Web 端点击
+const handleWebClick = () => {
+    if (!webUrl.value) {
+        uni.showToast({ title: t('Downloadpage.invalidLink') || '链接无效', icon: 'none' })
+        return
+    }
+    // #ifdef APP-PLUS
+    plus.runtime.openURL(webUrl.value, (err) => {
+        uni.showToast({ title: t('Downloadpage.openFailed') || '打开失败,请重试', icon: 'none' })
+    })
+    // #endif
+    // #ifdef H5
+    window.location.href = webUrl.value
+    // #endif
+}
+
+// 处理下载端点击
+const handleDownloadClick = () => {
+    if (!downloadItem.value || !downloadItem.value.url) {
+        uni.showToast({ title: t('Downloadpage.unsupported') || '暂不支持当前平台下载', icon: 'none' })
+        return
+    }
+
+    const url = downloadItem.value.url
+    // #ifdef APP-PLUS
+    plus.runtime.openURL(url, (err) => {
+        uni.showToast({ title: t('Downloadpage.openFailed') || '打开失败,请重试', icon: 'none' })
+    })
+    // #endif
+    // #ifdef H5
+    if (url.match(/\.(exe|dmg|pkg|apk|zip)$/i)) {
+        const a = document.createElement('a')
+        a.href = url
+        a.download = downloadItem.value.filename || ''
+        document.body.appendChild(a)
+        a.click()
+        document.body.removeChild(a)
+    } else {
+        window.open(url, '_blank')
+    }
+    // #endif
+}
+
+// 初始化
+onMounted(() => {
+    platform.value = getPlatform()
+    initEnv()
+})
+</script>
+
+<style scoped lang="scss">
+@import "@/uni.scss";
+
+@media (min-width: 768px) {
+    :deep(.cwg-dialog) {
+        background-color: var(--color-white);
+        border-radius: px2rpx(8);
+        width: px2rpx(600) !important;
+    }
+}
+
+.card-list {
+    display: flex;
+    flex-direction: column;
+    gap: px2rpx(12);
+}
+
+.card {
+    display: flex;
+    align-items: center;
+    background-color: rgba(108, 133, 149, 0.08);
+    border-radius: px2rpx(12);
+    padding: px2rpx(14) px2rpx(12);
+    border: 1px solid rgba(108, 133, 149, 0);
+    transition: background-color 0.2s;
+
+    &:hover {
+        border: 1px solid rgba(108, 133, 149, 0.2);
+    }
+}
+
+.card-icon {
+    width: px2rpx(54);
+    height: px2rpx(54);
+    background-color: #141D22;
+    border-radius: px2rpx(12);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: px2rpx(12);
+    flex-shrink: 0;
+
+    .icon-image {
+        width: px2rpx(32);
+        height: px2rpx(32);
+    }
+}
+
+.card-content {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+}
+
+.card-title {
+    font-size: px2rpx(14);
+    font-weight: 600;
+    line-height: 1.4;
+    color: #141d22;
+}
+
+.card-desc {
+    font-size: px2rpx(14);
+    color: #A0B0C0;
+    margin-top: 8rpx;
+}
+
+.card-arrow {
+    width: px2rpx(24);
+    height: px2rpx(24);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-left: 16rpx;
+    flex-shrink: 0;
+    color: #141d22;
+}
+</style>

+ 182 - 0
pages/customer/components/TerminalInfoDialog.vue

@@ -0,0 +1,182 @@
+<template>
+    <cwg-popup :title="title" v-model:visible="props.visible" :showFooter="false"
+        @update:visible="$emit('update:visible', $event)">
+        <view class="account-detail-content">
+            <!-- 账户编号独立显示(如果需要,也可以作为 fieldList 中的一项) -->
+            <view v-if="accountNumber" class="account-number-row">
+                <text class="label">{{ accountLabel }}</text>
+                <text class="value">{{ accountNumber }}</text>
+            </view>
+
+            <!-- 动态字段列表 -->
+            <view v-for="(field, index) in fieldList" :key="index" class="field-row">
+
+                <cwg-label-line-value :label="field.label" :value="getFieldValue(field.key)">
+                    <template #operation v-if="field.copyable">
+                        <view class="copy-btn" @click="copyValue(getFieldValue(field.key))">
+                            <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"
+                                fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
+                                stroke-linejoin="round">
+                                <path
+                                    d="M7 7m0 2.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667z" />
+                                <path
+                                    d="M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1" />
+                            </svg>
+                        </view>
+                    </template>
+                </cwg-label-line-value>
+                <!-- <text class="label">{{ field.label }}</text>
+                <view class="value-wrapper">
+                    <text class="value">{{ getFieldValue(field.key) || '--' }}</text>
+                    <view v-if="field.copyable" class="copy-btn" @click="copyValue(getFieldValue(field.key))">
+                        <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"
+                            stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+                            <path
+                                d="M7 7m0 2.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667z" />
+                            <path
+                                d="M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1" />
+                        </svg>
+                    </view>
+                </view> -->
+            </view>
+        </view>
+    </cwg-popup>
+</template>
+
+<script setup>
+import { computed } from 'vue'
+
+const props = defineProps({
+    // 是否显示弹窗
+    visible: {
+        type: Boolean,
+        default: false
+    },
+    // 弹窗标题
+    title: {
+        type: String,
+        default: '账户详情'
+    },
+    // 账户编号(若单独展示)
+    accountNumber: {
+        type: String,
+        default: ''
+    },
+    // 账户编号标签
+    accountLabel: {
+        type: String,
+        default: '账户:'
+    },
+    // 表单数据对象
+    form: {
+        type: Object,
+        default: () => ({})
+    },
+    // 字段配置列表,每项包含:
+    // - label: 字段显示名称
+    // - key: 在 form 中对应的键名
+    // - copyable: 是否显示复制按钮,默认 false
+    fieldList: {
+        type: Array,
+        default: () => []
+    }
+})
+
+const emit = defineEmits(['update:visible'])
+
+// 获取字段值
+const getFieldValue = (key) => {
+    return props.form?.[key] ?? ''
+}
+
+// 复制文本到剪贴板
+const copyValue = (text) => {
+    if (!text) {
+        uni.showToast({ title: '无内容可复制', icon: 'none' })
+        return
+    }
+    uni.setClipboardData({
+        data: String(text),
+        success: () => {
+            uni.showToast({ title: '复制成功', icon: 'success' })
+        },
+        fail: () => {
+            uni.showToast({ title: '复制失败', icon: 'none' })
+        }
+    })
+}
+</script>
+
+<style scoped lang="scss">
+@import "@/uni.scss";
+@media (min-width: 768px) {
+    :deep(.cwg-dialog) {
+        background-color: var(--color-white);
+        border-radius: px2rpx(8);
+        width: px2rpx(500) !important;
+    }
+}
+
+.account-number-row,
+.field-row {
+    display: flex;
+    align-items: center;
+    padding: px2rpx(10) 0;
+    width: 100%;
+    font-size: px2rpx(14);
+
+    &:last-child {
+        border-bottom: none;
+    }
+
+    .label {
+        min-width: px2rpx(30);
+        color: #666;
+        font-weight: normal;
+        flex-shrink: 0;
+    }
+
+    .value-wrapper {
+        flex: 1;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+    }
+
+    .value {
+        color: #333;
+        flex: 1;
+    }
+
+    .copy-btn {
+        width: px2rpx(20);
+        height: px2rpx(20);
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        margin-left: px2rpx(12);
+        cursor: pointer;
+        color: #999;
+        transition: color 0.2s;
+
+        &:active {
+            color: #007aff;
+        }
+
+        svg {
+            width: px2rpx(20);
+            height: px2rpx(20);
+        }
+    }
+}
+
+// 可复制行样式(仅用于视觉区分)
+.copyable-row {
+    .value-wrapper {
+        .value {
+            // 可复制字段的值留出右侧空间
+            margin-right: px2rpx(8);
+        }
+    }
+}
+</style>

+ 184 - 0
pages/customer/components/TerminalNickNameDialog.vue

@@ -0,0 +1,184 @@
+<template>
+    <cwg-popup :title="'账户昵称'" :visible="props.visible" :showFooter="false"
+        @update:visible="$emit('update:visible', $event)">
+        <view class="popup-content">
+            <text class="account-number">{{ accountLabel }} {{ account.login }}</text>
+            <text class="account-hint">{{ hint }}</text>
+
+            <view class="form-item">
+                <view class="input-label">账户昵称</view>
+                <input class="input-field" v-model="nickName" :maxlength="36" :placeholder="placeholder"
+                    @input="onInput" />
+                <text class="input-hint">{{ constraint }}</text>
+            </view>
+            <view class="save-btn">
+                <view class="btn primary" @click="save" :disabled="!isValid || !nickName.trim()" v-t="'Btn.Save'" />
+            </view>
+        </view>
+    </cwg-popup>
+</template>
+
+<script setup>
+import { ref, computed, onMounted } from 'vue'
+import { customApi } from '@/service/custom';
+import { useI18n } from 'vue-i18n'
+const { t, locale } = useI18n()
+const props = defineProps({
+    visible: { type: Boolean, default: false },
+    // 账户编号
+    account: { type: Object, default: {} },
+    // 标题
+    title: { type: String, default: '账户昵称' },
+    // 账户标签前缀
+    accountLabel: { type: String, default: '账户: #' },
+    // 提示文字
+    hint: { type: String, default: '为账户定制名称,以便快速查找。' },
+    // 输入框占位符
+    placeholder: { type: String, default: '为账户定制名称,以便快速查找。' },
+    // 特殊字符限制说明
+    constraint: { type: String, default: '昵称不可包含特殊字符:< > " \' & ? ^ * # @' }
+})
+const emit = defineEmits(['update:visible', 'save'])
+
+const nickName = ref(props.account.nickName)
+
+// 特殊字符正则
+const specialCharsRegex = /[<>"\'&?^*#@]/
+
+// 校验昵称是否合法
+const isValid = computed(() => {
+    if (!nickName.value) return false
+    return !specialCharsRegex.test(nickName.value)
+})
+
+// 输入时实时校验(可选,可去掉)
+const onInput = (e) => {
+    // 实时过滤非法字符(也可以只是校验)
+}
+// 保存昵称
+const save = async () => {
+    if (!isValid.value) {
+        uni.showToast({
+            title: '昵称包含非法字符,请重新输入',
+            icon: 'none'
+        })
+        return
+    }
+    const nickname = nickName.value.trim()
+    if (!nickname) {
+        uni.showToast({
+            title: '昵称不能为空',
+            icon: 'none'
+        })
+        return
+    }
+    const res = await customApi.updateNick({ nickName: nickname, login: props.account.login })
+    if (res.code == 200) {
+        emit('update:visible', false)
+        emit('save', nickname)
+    }
+}
+</script>
+
+<style scoped lang="scss">
+@import "@/uni.scss";
+
+@media (min-width: 768px) {
+    :deep(.cwg-dialog) {
+        background-color: var(--color-white);
+        border-radius: px2rpx(8);
+        width: px2rpx(480) !important;
+    }
+}
+
+.popup-content {
+    padding: px2rpx(16);
+}
+
+.account-number {
+    display: block;
+    font-size: px2rpx(14);
+    color: #141d22;
+    margin-bottom: px2rpx(40);
+}
+
+.account-hint {
+    display: block;
+    font-size: px2rpx(13);
+    color: #141d22;
+    margin-bottom: px2rpx(40);
+}
+
+.form-item {
+    margin-bottom: px2rpx(20);
+}
+
+.input-label {
+    font-size: px2rpx(12);
+    color: #141d22;
+    margin-bottom: px2rpx(4);
+}
+
+.input-field {
+    width: 100%;
+    height: px2rpx(40);
+    border: 1px solid #ddd;
+    border-radius: px2rpx(6);
+    padding: 0 px2rpx(12);
+    font-size: px2rpx(14);
+    box-sizing: border-box;
+}
+
+.input-hint {
+    display: block;
+    font-size: px2rpx(11);
+    color: #999;
+    margin-top: px2rpx(6);
+    line-height: 1.4;
+}
+
+.save-btn {
+    width: 100%;
+    height: px2rpx(40);
+    color: #fff;
+    border-radius: px2rpx(8);
+    font-size: px2rpx(16);
+    font-weight: 500;
+    display: flex;
+    justify-content: flex-end;
+
+    border: none;
+
+
+    .btn {
+        background: transparent;
+        border: 1px solid rgba(108, 133, 149, 0);
+        border-radius: px2rpx(8);
+        padding: px2rpx(8) px2rpx(20);
+        font-size: px2rpx(14);
+        color: #2e3a47;
+        display: inline-flex;
+        align-items: center;
+        justify-content: center;
+        gap: px2rpx(8);
+        cursor: pointer;
+        transition: all 0.2s;
+        height: px2rpx(40);
+        box-sizing: border-box;
+        background-color: rgba(108, 133, 149, 0.08);
+
+        &.primary {
+            background-color: var(--color-navy-700);
+            color: #fff;
+
+            svg {
+                stroke: #fff;
+            }
+
+            &:hover {
+                background-color: var(--color-navy-600);
+            }
+        }
+    }
+}
+</style>

+ 1 - 1
pages/customer/components/TransactionDialogs.vue

@@ -1,5 +1,5 @@
 <template>
-    <cwg-popup :title="t('Tips.TransactionRecord')" v-model:visible="props.visible" :showFooter="false"
+    <cwg-popup :title="t('Tips.TransactionRecord')" :visible="props.visible" :showFooter="false"
         @update:visible="$emit('update:visible', $event)">
         <scroll-view scroll-y class="account-list" :style="{ maxHeight: '40vh' }">
             <view v-if="loading" class="loading-state">

+ 116 - 0
pages/customer/composables/TerminalMap.ts

@@ -0,0 +1,116 @@
+export const TerminalMap = {
+    "MT4": {
+        "desktop": {
+            "windows": [
+                {
+                    "nameKey": "Downloadpage.item4",
+                    "descriptionKey": "Downloadpage.item5",
+                    "url": "{myLink}/mt/cwgmarketssvgltd4setup.exe",
+                    "filename": "cwgmarketssvgltd4setup.exe",
+                    "icon": "windows-os-1-48.png"
+                },
+                {
+                    "nameKey": "Downloadpage.item4-1",
+                    "descriptionKey": "Downloadpage.item5",
+                    "url": "{myLink}/mt/mt4.zip",
+                    "filename": "mt4.zip",
+                    "icon": "windows-os-1-48.png"
+                }
+            ],
+            "mac": [
+                {
+                    "nameKey": "Downloadpage.item6",
+                    "descriptionKey": "Downloadpage.item5",
+                    "url": "{myLink}/mt/MetaTrader4.pkg",
+                    "filename": "MetaTrader4.pkg",
+                    "icon": "apple-os-1-48.png"
+                }
+            ]
+        },
+        "web": {
+            "url": "https://www.{domain}.com/{lang}/mt4/web",
+            "descriptionKey": "Downloadpage.item40"
+        },
+        "mobile": {
+            "android": [
+                {
+                    "name": "Google Play",
+                    "descriptionKey": "Downloadpage.item9",
+                    "url": "https://www.metatrader4.com/en/download#download-block-android?server=CWGMarketsSVGLtd-Demo,CWGMarketsSVGLtd-Live",
+                    "qrText": "https://www.metatrader4.com/en/download#download-block-android?server=CWGMarketsSVGLtd-Demo,CWGMarketsSVGLtd-Live"
+                },
+                {
+                    "name": "MetaTrader .Apk",
+                    "descriptionKey": "Downloadpage.item9",
+                    "url": "https://secure.{domain}.com/metatrader/metatrader4.apk",
+                    "qrText": "https://secure.{domain}.com/metatrader/metatrader4.apk"
+                }
+            ],
+            "ios": [
+                {
+                    "name": "App Store",
+                    "descriptionKey": "Downloadpage.item10",
+                    "url": "https://apps.apple.com/us/app/metatrader-4/id496212596?server=CWGMarketsSVGLtd-Demo,CWGMarketsSVGLtd-Live",
+                    "qrText": "https://apps.apple.com/us/app/metatrader-4/id496212596?server=CWGMarketsSVGLtd-Demo,CWGMarketsSVGLtd-Live"
+                }
+            ]
+        }
+    },
+    "MT5": {
+        "desktop": {
+            "windows": [
+                {
+                    "nameKey": "Downloadpage.item4",
+                    "descriptionKey": "Downloadpage.item5",
+                    "url": "{myLink}/mt/cwgmarketssvg5setup.exe",
+                    "filename": "cwgmarketssvg5setup.exe",
+                    "icon": "windows-os-1-48.png"
+                },
+                {
+                    "nameKey": "Downloadpage.item4-1",
+                    "descriptionKey": "Downloadpage.item5",
+                    "url": "{myLink}/mt/mt5.zip",
+                    "filename": "mt5.zip",
+                    "icon": "windows-os-1-48.png"
+                }
+            ],
+            "mac": [
+                {
+                    "nameKey": "Downloadpage.item6",
+                    "descriptionKey": "Downloadpage.item5",
+                    "url": "{myLink}/mt/MetaTrader5.pkg",
+                    "filename": "MetaTrader5.dmg",
+                    "icon": "apple-os-1-48.png"
+                }
+            ]
+        },
+        "web": {
+            "url": "https://www.{domain}.com/{lang}/mt5/web",
+            "descriptionKey": "Downloadpage.item40"
+        },
+        "mobile": {
+            "android": [
+                {
+                    "name": "Google Play",
+                    "descriptionKey": "Downloadpage.item14",
+                    "url": "https://download.metatrader.com/cdn/mobile/mt5/android?server=CWGMarketsSVG-Demo,CWGMarketsSVG-Live",
+                    "qrText": "https://download.metatrader.com/cdn/mobile/mt5/android?server=CWGMarketsSVG-Demo,CWGMarketsSVG-Live"
+                },
+                {
+                    "name": "MetaTrader .Apk",
+                    "descriptionKey": "Downloadpage.item14",
+                    "url": "{myLink}/mt/metatrader5.apk",
+                    "qrText": "{myLink}/mt/metatrader5.apk"
+                }
+            ],
+            "ios": [
+                {
+                    "name": "App Store",
+                    "descriptionKey": "Downloadpage.item15",
+                    "url": "https://download.metatrader.com/cdn/mobile/mt5/ios?server=CWGMarketsSVG-Demo,CWGMarketsSVG-Live",
+                    "qrText": "https://download.metatrader.com/cdn/mobile/mt5/ios?server=CWGMarketsSVG-Demo,CWGMarketsSVG-Live"
+                }
+            ]
+        }
+    }
+}

+ 0 - 1379
pages/customer/create-account copy.vue

@@ -1,1379 +0,0 @@
-<template>
-    <cwg-page-wrapper class="create-page" :isHeaderFixed="true">
-        <uni-card class="create-content" :margin="0" :spacing="0">
-            <view class="content-title" v-t="'Custom.NewAccount.Title'"></view>
-            <view class="tit">
-                <text class="iconfont icon-caret-right"></text>
-                <text>{{ t('Custom.NewAccount.Title1') }}</text>
-            </view>
-            <view class="des">
-                <text>{{ t('Custom.NewAccount.Des1') }}</text>
-            </view>
-            <cwg-tabs :cativeIndex="cativeIndex" :tabs="tabs" class="tabs-class" />
-
-        </uni-card>
-        <view id="custom_newAccount" :class="{ 'u-loading': pictLoading }">
-            <view class="main-content" v-if="showPage">
-                <!-- 账户列表 -->
-                <view class="box" v-if="
-                    showLogin.indexOf('6') === -1 ||
-                    showLogin.indexOf('2') === -1 ||
-                    showLogin.indexOf('7') === -1 ||
-                    (showLogin.indexOf('8') === -1 && isTimeShow)
-                ">
-
-
-                    <!-- 极速账户 -->
-                    <!-- <view class="b-card" v-if="showLogin.indexOf('6') === -1">
-                        <view class="btn-tag-star" v-if="false">
-                            <text class="iconfont icon-star-on"></text>
-                        </view>
-                        <view class="card-top">
-                            <view class="header" style="width: 66.66667%;">
-                                <view class="tit">
-                                    <text>{{ t('AccountType.SpeedAccount') }}</text>
-                                </view>
-                                <view class="des">
-                                    <text>{{ t('Custom.NewAccount.DesLogin1') }}</text>
-                                </view>
-                                <view class="btn-bottom">
-                                    <text class="btn-open" @click="isOpenClose(6, null)">
-                                        <text>{{ t('Custom.NewAccount.Btn') }}</text>
-                                        <text class="iconfont icon-arrow-right"></text>
-                                    </text>
-                                    <text class="btn-try" @click="isOpenClose(6, 6)">
-                                        <text>{{ t('Custom.NewAccount.BtnDome') }}</text>
-                                        <text class="iconfont icon-arrow-right"></text>
-                                    </text>
-                                </view>
-                            </view>
-                            <view class="descending" style="width: 33.33333%;">
-                                <view><text>{{ t('Custom.NewAccount.DesLogin11') }}</text></view>
-                                <view><text>{{ t('Custom.NewAccount.DesLogin12') }}</text></view>
-                                <view><text>{{ t('Custom.NewAccount.DesLogin13') }}</text></view>
-                                <view><text>{{ t('Custom.NewAccount.DesLogin14') }}</text></view>
-                            </view>
-                        </view>
-                        <view class="card-bottom" v-if="isOpenAccount == 6">
-                            <uv-form :model="params" :rules="rules" ref="formRef" label-position="top">
-                                <uv-form-item prop="platform" :label="t('Custom.NewAccount.Platform')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.platform" :columns="platformColumns"
-                                        :placeholder="t('placeholder.choose')" @confirm="handlePlatformConfirm">
-                                        <view class="picker-value">{{ params.platform || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="currency" :label="t('Custom.NewAccount.Currency')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.currency" :columns="currencyColumns"
-                                        :placeholder="t('placeholder.choose')" @confirm="handleCurrencyConfirm">
-                                        <view class="picker-value">{{ params.currency || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="password" :label="t('Custom.NewAccount.Password')"
-                                    :borderBottom="false">
-                                    <uv-input v-model="params.password" :password="true"
-                                        :placeholder="t('Custom.NewAccount.Password')"></uv-input>
-                                </uv-form-item>
-
-                                <uv-form-item prop="leverage" :label="t('Custom.NewAccount.Lever')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.leverage" :columns="leverageColumns"
-                                        :placeholder="t('placeholder.choose')" :disabled="hidden"
-                                        @confirm="handleLeverageConfirm">
-                                        <view class="picker-value">{{ params.leverage || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="platform" :borderBottom="false">
-                                    <view class="pwd">
-                                        <view :class="{ fit: rule1 }">{{ t('signup.form.rules.1st') }}</view>
-                                        <view :class="{ fit: rule2 }">{{ t('signup.form.rules.2nd') }}</view>
-                                        <view :class="{ fit: rule4 }">{{ t('signup.form.rules.4rd') }}</view>
-                                    </view>
-                                </uv-form-item>
-
-                                <uv-form-item prop="balance" :label="t('Custom.NewAccount.Balance')" v-if="dome"
-                                    :borderBottom="false">
-                                    <uv-input v-model="params.balance" type="number"
-                                        :placeholder="t('Custom.NewAccount.BalancePlaceholder')"
-                                        @blur="handleBalanceChange"></uv-input>
-                                </uv-form-item>
-
-                                <uv-form-item prop="platform" v-if="dome" :borderBottom="false">
-                                    <view class="pwd">
-                                        <view :class="{ fit: rule1 }">0 - 100000</view>
-                                    </view>
-                                </uv-form-item>
-
-                                <uv-form-item :borderBottom="false">
-                                    <uv-button type="primary" class="s-btn" @click="newAccount(6, dome ? 1 : null)">
-                                        {{ t('Btn.OpenAccount') }}
-                                    </uv-button>
-                                </uv-form-item>
-
-                                <uv-form-item :borderBottom="false" v-if="!dome">
-                                    <view style="margin: 20px 0; font-size: 14px; line-height: 1.7;">
-                                        <text>{{ t('news_add_field.OpenAccount.Des4') }}</text>
-                                        <text class="pdfLink" @click="openLink('leveragemargin')">
-                                            {{ t('news_add_field.OpenAccount.Des5') }}
-                                        </text>
-                                    </view>
-                                </uv-form-item>
-                            </uv-form>
-                        </view>
-                    </view> -->
-
-                    <!-- 经典账户 -->
-                    <!-- <view class="b-card" v-if="showLogin.indexOf('1') === -1">
-                        <view class="btn-tag-star" v-if="false">
-                            <text class="iconfont icon-star-on"></text>
-                        </view>
-                        <view class="card-top">
-                            <view class="header" style="width: 66.66667%;">
-                                <view class="tit">
-                                    <text>{{ t('AccountType.ClassicAccount') }}</text>
-                                </view>
-                                <view class="des">
-                                    <text>{{ t('Custom.NewAccount.DesLogin2') }}</text>
-                                </view>
-                                <view class="btn-bottom">
-                                    <text class="btn-open" @click="isOpenClose(1, null)">
-                                        <text>{{ t('Custom.NewAccount.Btn') }}</text>
-                                        <text class="iconfont icon-arrow-right"></text>
-                                    </text>
-                                    <text class="btn-try" @click="isOpenClose(1, 1)">
-                                        <text>{{ t('Custom.NewAccount.BtnDome') }}</text>
-                                        <text class="iconfont icon-arrow-right"></text>
-                                    </text>
-                                </view>
-                            </view>
-                            <view class="descending" style="width: 33.33333%;">
-                                <view><text>{{ t('Custom.NewAccount.DesLogin21') }}</text></view>
-                                <view><text>{{ t('Custom.NewAccount.DesLogin22') }}</text></view>
-                                <view v-if="['cn', 'zhHant'].indexOf(language) === -1">
-                                    <text>{{ t('Custom.NewAccount.DesLogin23') }}</text>
-                                </view>
-                                <view><text>{{ t('Custom.NewAccount.DesLogin24') }}</text></view>
-                            </view>
-                        </view>
-                        <view class="card-bottom" v-if="isOpenAccount == 1">
-                            <uv-form :model="params" :rules="rules" ref="formRef" label-position="top">
-                                <uv-form-item prop="platform" :label="t('Custom.NewAccount.Platform')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.platform" :columns="platformColumns"
-                                        :placeholder="t('placeholder.choose')" @confirm="handlePlatformConfirm">
-                                        <view class="picker-value">{{ params.platform || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="currency" :label="t('Custom.NewAccount.Currency')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.currency" :columns="currencyColumns"
-                                        :placeholder="t('placeholder.choose')" @confirm="handleCurrencyConfirm">
-                                        <view class="picker-value">{{ params.currency || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="password" :label="t('Custom.NewAccount.Password')"
-                                    :borderBottom="false">
-                                    <uv-input v-model="params.password" :password="true"
-                                        :placeholder="t('Custom.NewAccount.Password')"></uv-input>
-                                </uv-form-item>
-
-                                <uv-form-item prop="leverage" :label="t('Custom.NewAccount.Lever')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.leverage" :columns="leverageColumns"
-                                        :placeholder="t('placeholder.choose')" :disabled="true"
-                                        @confirm="handleLeverageConfirm">
-                                        <view class="picker-value">{{ params.leverage || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="platform" :borderBottom="false">
-                                    <view class="pwd">
-                                        <view :class="{ fit: rule1 }">{{ t('signup.form.rules.1st') }}</view>
-                                        <view :class="{ fit: rule2 }">{{ t('signup.form.rules.2nd') }}</view>
-                                        <view :class="{ fit: rule4 }">{{ t('signup.form.rules.4rd') }}</view>
-                                    </view>
-                                </uv-form-item>
-
-                                <uv-form-item :borderBottom="false">
-                                    <uv-button type="primary" class="s-btn" @click="newAccount(1, dome ? 1 : null)">
-                                        {{ t('Btn.OpenAccount') }}
-                                    </uv-button>
-                                </uv-form-item>
-                            </uv-form>
-                        </view>
-                    </view> -->
-
-                    <!-- 标准账户 -->
-                    <view class="b-card" v-if="showLogin.indexOf('7') === -1">
-                        <view class="btn-tag-star">
-                            <text class="iconfont icon-star-on"></text>
-                        </view>
-                        <view class="card-top">
-                            <view class="header" style="width: 66.66667%;">
-                                <view class="tit">
-                                    <text>{{ t('AccountType.StandardAccount') }}</text>
-                                </view>
-                                <view class="des">
-                                    <text>{{ t('Custom.NewAccount.DesLogin5') }}</text>
-                                </view>
-                                <view class="btn-bottom">
-                                    <text class="btn-open" @click="isOpenClose(7, null)">
-                                        <text>{{ t('Custom.NewAccount.Btn') }}</text>
-                                        <text class="iconfont icon-arrow-right"></text>
-                                    </text>
-                                    <text class="btn-try" @click="isOpenClose(7, 7)">
-                                        <text>{{ t('Custom.NewAccount.BtnDome') }}</text>
-                                        <text class="iconfont icon-arrow-right"></text>
-                                    </text>
-                                </view>
-                            </view>
-                            <view class="descending" style="width: 33.33333%;">
-                                <view><text>{{ t('Custom.NewAccount.DesLogin51') }}</text></view>
-                                <view><text>{{ t('Custom.NewAccount.DesLogin52') }}</text></view>
-                                <view v-if="['cn', 'zhHant'].indexOf(language) === -1">
-                                    <text>{{ t('Custom.NewAccount.DesLogin53') }}</text>
-                                </view>
-                                <view><text>{{ t('Custom.NewAccount.DesLogin54') }}</text></view>
-                            </view>
-                        </view>
-
-                        <!-- 标准账户表单 -->
-                        <view class="card-bottom" v-if="isOpenAccount == 7">
-                            <uv-form :model="params" :rules="rules" ref="formRef" label-position="top">
-                                <uv-form-item prop="platform" :label="t('Custom.NewAccount.Platform')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.platform" :columns="platformColumns"
-                                        :placeholder="t('placeholder.choose')" @confirm="handlePlatformConfirm">
-                                        <view class="picker-value">{{ params.platform || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="currency" :label="t('Custom.NewAccount.Currency')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.currency" :columns="currencyColumns"
-                                        :placeholder="t('placeholder.choose')" @confirm="handleCurrencyConfirm">
-                                        <view class="picker-value">{{ params.currency || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="password" :label="t('Custom.NewAccount.Password')"
-                                    :borderBottom="false">
-                                    <uv-input v-model="params.password" :password="true"
-                                        :placeholder="t('Custom.NewAccount.Password')"></uv-input>
-                                </uv-form-item>
-
-                                <uv-form-item prop="leverage" :label="t('Custom.NewAccount.Lever')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.leverage" :columns="leverageColumns"
-                                        :placeholder="t('placeholder.choose')" :disabled="hidden"
-                                        @confirm="handleLeverageConfirm">
-                                        <view class="picker-value">{{ params.leverage || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="platform" :borderBottom="false">
-                                    <view class="pwd">
-                                        <view :class="{ fit: rule1 }">{{ t('signup.form.rules.1st') }}</view>
-                                        <view :class="{ fit: rule2 }">{{ t('signup.form.rules.2nd') }}</view>
-                                        <view :class="{ fit: rule4 }">{{ t('signup.form.rules.4rd') }}</view>
-                                    </view>
-                                </uv-form-item>
-
-                                <uv-form-item prop="balance" :label="t('Custom.NewAccount.Balance')" v-if="dome"
-                                    :borderBottom="false">
-                                    <uv-input v-model="params.balance" type="number"
-                                        :placeholder="t('Custom.NewAccount.BalancePlaceholder')"
-                                        @blur="handleBalanceChange"></uv-input>
-                                </uv-form-item>
-
-                                <uv-form-item prop="platform" v-if="dome" :borderBottom="false">
-                                    <view class="pwd">
-                                        <view :class="{ fit: rule1 }">0 - 100000</view>
-                                    </view>
-                                </uv-form-item>
-
-                                <uv-form-item :borderBottom="false">
-                                    <uv-button type="primary" class="s-btn" @click="newAccount(7, dome ? 1 : null)">
-                                        {{ t('Btn.OpenAccount') }}
-                                    </uv-button>
-                                </uv-form-item>
-                            </uv-form>
-                        </view>
-                    </view>
-
-                    <!-- 高级账户 -->
-                    <view class="b-card" v-if="showLogin.indexOf('2') === -1">
-                        <view class="btn-tag-star" v-if="false">
-                            <text class="iconfont icon-star-on"></text>
-                        </view>
-                        <view class="card-top">
-                            <view class="header" style="width: 66.66667%;">
-                                <view class="tit">
-                                    <text>{{ t('AccountType.SeniorAccount') }}</text>
-                                </view>
-                                <view class="des">
-                                    <text>{{ t('Custom.NewAccount.DesLogin3') }}</text>
-                                </view>
-                                <view class="btn-bottom">
-                                    <text class="btn-open" @click="isOpenClose(2, null)">
-                                        <text>{{ t('Custom.NewAccount.Btn') }}</text>
-                                        <text class="iconfont icon-arrow-right"></text>
-                                    </text>
-                                    <text class="btn-try" @click="isOpenClose(2, 2)">
-                                        <text>{{ t('Custom.NewAccount.BtnDome') }}</text>
-                                        <text class="iconfont icon-arrow-right"></text>
-                                    </text>
-                                </view>
-                            </view>
-                            <view class="descending" style="width: 33.33333%;">
-                                <view><text>{{ t('Custom.NewAccount.DesLogin31') }}</text></view>
-                                <view><text>{{ t('Custom.NewAccount.DesLogin32') }}</text></view>
-                                <view><text>{{ t('Custom.NewAccount.DesLogin33') }}</text></view>
-                                <view><text>{{ t('Custom.NewAccount.DesLogin34') }}</text></view>
-                            </view>
-                        </view>
-
-                        <!-- 高级账户表单 -->
-                        <view class="card-bottom" v-if="isOpenAccount == 2">
-                            <uv-form :model="params" :rules="rules" ref="formRef" label-position="top">
-                                <uv-form-item prop="platform" :label="t('Custom.NewAccount.Platform')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.platform" :columns="platformColumns"
-                                        :placeholder="t('placeholder.choose')" @confirm="handlePlatformConfirm">
-                                        <view class="picker-value">{{ params.platform || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="currency" :label="t('Custom.NewAccount.Currency')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.currency" :columns="currencyColumns"
-                                        :placeholder="t('placeholder.choose')" @confirm="handleCurrencyConfirm">
-                                        <view class="picker-value">{{ params.currency || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="password" :label="t('Custom.NewAccount.Password')"
-                                    :borderBottom="false">
-                                    <uv-input v-model="params.password" :password="true"
-                                        :placeholder="t('Custom.NewAccount.Password')"></uv-input>
-                                </uv-form-item>
-
-                                <uv-form-item prop="leverage" :label="t('Custom.NewAccount.Lever')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.leverage" :columns="leverageColumns"
-                                        :placeholder="t('placeholder.choose')" :disabled="hidden"
-                                        @confirm="handleLeverageConfirm">
-                                        <view class="picker-value">{{ params.leverage || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="platform" :borderBottom="false">
-                                    <view class="pwd">
-                                        <view :class="{ fit: rule1 }">{{ t('signup.form.rules.1st') }}</view>
-                                        <view :class="{ fit: rule2 }">{{ t('signup.form.rules.2nd') }}</view>
-                                        <view :class="{ fit: rule4 }">{{ t('signup.form.rules.4rd') }}</view>
-                                    </view>
-                                </uv-form-item>
-
-                                <uv-form-item prop="balance" :label="t('Custom.NewAccount.Balance')" v-if="dome"
-                                    :borderBottom="false">
-                                    <uv-input v-model="params.balance" type="number"
-                                        :placeholder="t('Custom.NewAccount.BalancePlaceholder')"
-                                        @blur="handleBalanceChange"></uv-input>
-                                </uv-form-item>
-
-                                <uv-form-item prop="platform" v-if="dome" :borderBottom="false">
-                                    <view class="pwd">
-                                        <view :class="{ fit: rule1 }">0 - 100000</view>
-                                    </view>
-                                </uv-form-item>
-
-                                <uv-form-item :borderBottom="false">
-                                    <uv-button type="primary" class="s-btn" @click="newAccount(2, dome ? 1 : null)">
-                                        {{ t('Btn.OpenAccount') }}
-                                    </uv-button>
-                                </uv-form-item>
-                            </uv-form>
-                        </view>
-                    </view>
-
-                    <!-- 美分账户 -->
-                    <view class="b-card" v-if="showLogin.indexOf('8') === -1 && isTimeShow">
-                        <view class="btn-tag-star" v-if="false">
-                            <text class="iconfont icon-star-on"></text>
-                        </view>
-                        <view class="card-top">
-                            <view class="header" style="width: 66.66667%;">
-                                <view class="tit">
-                                    <text>{{ t('AccountType.CentAccount') }}</text>
-                                </view>
-                                <view class="des">
-                                    <text>{{ t('Custom.NewAccount.DesLogin8') }}</text>
-                                </view>
-                                <view class="btn-bottom">
-                                    <text class="btn-open" @click="isOpenClose(8, null)">
-                                        <text>{{ t('Custom.NewAccount.Btn') }}</text>
-                                        <text class="iconfont icon-arrow-right"></text>
-                                    </text>
-                                    <text class="btn-try" @click="isOpenClose(8, 8)">
-                                        <text>{{ t('Custom.NewAccount.BtnDome') }}</text>
-                                        <text class="iconfont icon-arrow-right"></text>
-                                    </text>
-                                </view>
-                            </view>
-                            <view class="descending" style="width: 33.33333%;">
-                                <view><text>{{ t('Custom.NewAccount.DesLogin81') }}</text></view>
-                                <view><text>{{ t('Custom.NewAccount.DesLogin82') }}</text></view>
-                                <view><text>{{ t('Custom.NewAccount.DesLogin84') }}</text></view>
-                            </view>
-                        </view>
-
-                        <!-- 美分账户表单 -->
-                        <view class="card-bottom" v-if="isOpenAccount == 8">
-                            <uv-form :model="params" :rules="rules" ref="formRef" label-position="top">
-                                <uv-form-item prop="platform" :label="t('Custom.NewAccount.Platform')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.platform" :columns="platformColumns"
-                                        :placeholder="t('placeholder.choose')" @confirm="handlePlatformConfirm">
-                                        <view class="picker-value">{{ params.platform || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="currency" :label="t('Custom.NewAccount.Currency')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.currency" :columns="currencyColumns"
-                                        :placeholder="t('placeholder.choose')" @confirm="handleCurrencyConfirm">
-                                        <view class="picker-value">{{ params.currency || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="password" :label="t('Custom.NewAccount.Password')"
-                                    :borderBottom="false">
-                                    <uv-input v-model="params.password" :password="true"
-                                        :placeholder="t('Custom.NewAccount.Password')"></uv-input>
-                                </uv-form-item>
-
-                                <uv-form-item prop="leverage" :label="t('Custom.NewAccount.Lever')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.leverage" :columns="leverageColumns"
-                                        :placeholder="t('placeholder.choose')" :disabled="hidden"
-                                        @confirm="handleLeverageConfirm">
-                                        <view class="picker-value">{{ params.leverage || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="platform" :borderBottom="false">
-                                    <view class="pwd">
-                                        <view :class="{ fit: rule1 }">{{ t('signup.form.rules.1st') }}</view>
-                                        <view :class="{ fit: rule2 }">{{ t('signup.form.rules.2nd') }}</view>
-                                        <view :class="{ fit: rule4 }">{{ t('signup.form.rules.4rd') }}</view>
-                                    </view>
-                                </uv-form-item>
-
-                                <uv-form-item prop="balance" :label="t('Custom.NewAccount.Balance')" v-if="dome"
-                                    :borderBottom="false">
-                                    <uv-input v-model="params.balance" type="number"
-                                        :placeholder="t('Custom.NewAccount.BalancePlaceholder')"
-                                        @blur="handleBalanceChange"></uv-input>
-                                </uv-form-item>
-
-                                <uv-form-item prop="platform" v-if="dome" :borderBottom="false">
-                                    <view class="pwd">
-                                        <view :class="{ fit: rule1 }">0 - 100000</view>
-                                    </view>
-                                </uv-form-item>
-
-                                <uv-form-item :borderBottom="false">
-                                    <uv-button type="primary" class="s-btn" @click="newAccount(8, dome ? 1 : null)">
-                                        {{ t('Btn.OpenAccount') }}
-                                    </uv-button>
-                                </uv-form-item>
-
-                                <uv-form-item :borderBottom="false">
-                                    <view style="margin: 20px 0; font-size: 14px; line-height: 1.7;">
-                                        <text>{{ t('news_add_field.OpenAccount.Des4') }}</text>
-                                        <text class="pdfLink" @click="openLink('leveragemargin')">
-                                            {{ t('news_add_field.OpenAccount.Des5') }}
-                                        </text>
-                                    </view>
-                                </uv-form-item>
-                            </uv-form>
-                        </view>
-                    </view>
-                </view>
-
-                <!-- 代理账户 -->
-                <!-- <view class="box" v-if="showLogin.indexOf('3') === -1 && !isAfterJuly28()">
-                    <view class="tit">
-                        <text class="iconfont icon-caret-right"></text>
-                        <text>{{ t('Custom.NewAccount.Title2') }}</text>
-                    </view>
-                    <view class="des">
-                        <text>{{ t('Custom.NewAccount.Des2') }}</text>
-                    </view>
-
-                    <view class="b-card">
-                        <view class="btn-tag-star" v-if="false">
-                            <text class="iconfont icon-star-on"></text>
-                        </view>
-                        <view class="card-top">
-                            <view class="header" style="width: 66.66667%;">
-                                <view class="tit">
-                                    <text>{{ t('AccountType.AgencyAccount') }}</text>
-                                </view>
-                                <view class="des">
-                                    <text>{{ t('Custom.NewAccount.DesLogin4') }}</text>
-                                </view>
-                                <view class="btn-bottom">
-                                    <text class="btn-open" @click="isOpenClose(3, null)">
-                                        <text>{{ t('Custom.NewAccount.Btn') }}</text>
-                                        <text class="iconfont icon-arrow-right"></text>
-                                    </text>
-                                </view>
-                            </view>
-                            <view class="descending" style="width: 33.33333%;">
-                                <view><text>{{ t('Custom.NewAccount.DesLogin41') }}</text></view>
-                                <view><text>{{ t('Custom.NewAccount.DesLogin42') }}</text></view>
-                                <view><text>{{ t('Custom.NewAccount.DesLogin43') }}</text></view>
-                                <view><text>{{ t('Custom.NewAccount.DesLogin44') }}</text></view>
-                            </view>
-                        </view>
-                        <view class="card-bottom" v-if="isOpenAccount == 3">
-                            <uv-form :model="params" :rules="rules" ref="formRef" label-position="top">
-                                <uv-form-item prop="platform" :label="t('Custom.NewAccount.Platform')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.platform" :columns="platformColumns"
-                                        :placeholder="t('placeholder.choose')" @confirm="handlePlatformConfirm">
-                                        <view class="picker-value">{{ params.platform || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="currency" :label="t('Custom.NewAccount.Currency')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.currency" :columns="currencyColumns"
-                                        :placeholder="t('placeholder.choose')" @confirm="handleCurrencyConfirm">
-                                        <view class="picker-value">{{ params.currency || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="password" :label="t('Custom.NewAccount.Password')"
-                                    :borderBottom="false">
-                                    <uv-input v-model="params.password" :password="true"
-                                        :placeholder="t('Custom.NewAccount.Password')"></uv-input>
-                                </uv-form-item>
-
-                                <uv-form-item prop="leverage" :label="t('Custom.NewAccount.Lever')"
-                                    :borderBottom="false">
-                                    <uv-picker v-model="params.leverage" :columns="leverageColumns"
-                                        :placeholder="t('placeholder.choose')" :disabled="hidden"
-                                        @confirm="handleLeverageConfirm">
-                                        <view class="picker-value">{{ params.leverage || t('placeholder.choose') }}
-                                        </view>
-                                    </uv-picker>
-                                </uv-form-item>
-
-                                <uv-form-item prop="platform" :borderBottom="false">
-                                    <view class="pwd">
-                                        <view :class="{ fit: rule1 }">{{ t('signup.form.rules.1st') }}</view>
-                                        <view :class="{ fit: rule2 }">{{ t('signup.form.rules.2nd') }}</view>
-                                        <view :class="{ fit: rule4 }">{{ t('signup.form.rules.4rd') }}</view>
-                                    </view>
-                                </uv-form-item>
-
-                                <uv-form-item :borderBottom="false">
-                                    <uv-button type="primary" class="s-btn" @click="newAccount(3, null)">
-                                        {{ t('Btn.OpenAccount') }}
-                                    </uv-button>
-                                </uv-form-item>
-                            </uv-form>
-                        </view>
-                    </view>
-                </view> -->
-
-                <!-- 无可用账户提示 -->
-                <view class="box" v-if="
-                    showLogin.indexOf('6') !== -1 &&
-                    showLogin.indexOf('1') !== -1 &&
-                    showLogin.indexOf('2') !== -1 &&
-                    showLogin.indexOf('3') !== -1 &&
-                    showLogin.indexOf('7') !== -1 &&
-                    !(showLogin.indexOf('8') === -1 && isTimeShow)
-                ">
-                    <view style="margin: 20px 0; font-size: 14px; line-height: 1.7;">
-                        <text>{{ t('news_add_field.OpenAccount.Des3') }}</text>
-                    </view>
-                </view>
-
-                <!-- 底部说明 -->
-                <view class="box">
-                    <view style="margin: 20px 0; font-size: 14px; line-height: 1.7;">
-                        <text>{{ t('news_add_field.OpenAccount.Des1') }}</text>
-                        <text class="pdfLink" @click="openPdf('PrivacyPolicy2019_01.pdf')">
-                            {{ t('news_add_field.OpenAccount.Des2') }}
-                        </text>
-                    </view>
-                </view>
-            </view>
-
-            <!-- 提交后的弹出框 -->
-            <uv-popup :show="dialogCheck" mode="center" round="16" @close="closeDia">
-                <view class="dia-content" v-if="dialogVisible">
-                    <view class="icon">
-                        <text class="iconfont icon-success"></text>
-                    </view>
-                    <view class="des1">{{ t('ApplicationDialog.Des1') }}</view>
-                    <view class="des2">{{ t('ApplicationDialog.Des12') }}</view>
-                    <view class="dialog-footer">
-                        <uv-button type="primary" @click="closeDia">
-                            {{ t('Btn.Confirm') }}
-                        </uv-button>
-                        <uv-button @click="closeDia">
-                            {{ t('Btn.Cancel') }}
-                        </uv-button>
-                    </view>
-                </view>
-
-                <view class="dia-content" v-if="!dialogVisible">
-                    <view class="icon">
-                        <text class="iconfont icon-warning"></text>
-                    </view>
-                    <view class="des1">{{ RES }}</view>
-                    <view class="dialog-footer">
-                        <uv-button type="primary" @click="closeDia">
-                            {{ t('Btn.Confirm') }}
-                        </uv-button>
-                        <uv-button @click="closeDia">
-                            {{ t('Btn.Cancel') }}
-                        </uv-button>
-                    </view>
-                </view>
-            </uv-popup>
-
-            <!-- 账户开立上限提示弹框 -->
-            <uv-popup :show="dialogAccountLimit" mode="center" round="16" @close="closeAccountLimitDialog">
-                <view class="account-limit-content">
-                    <view class="icon">
-                        <text class="iconfont icon-warning"></text>
-                    </view>
-                    <view class="title">{{ t('accountLimit.title') }}</view>
-                    <view class="content">
-                        <view class="limit-text">
-                            <view>{{ t('accountLimit.mt4Message') }}</view>
-                            <view>
-                                <view>{{ t('accountLimit.mt4Condition1') }}</view>
-                            </view>
-                            <view>{{ t('accountLimit.mt4Action') }}</view>
-                        </view>
-                    </view>
-                    <view class="dialog-footer">
-                        <uv-button type="primary" class="confirm-btn" @click="closeAccountLimitDialog">
-                            {{ t('accountLimit.button') }}
-                        </uv-button>
-                    </view>
-                </view>
-            </uv-popup>
-        </view>
-
-    </cwg-page-wrapper>
-
-</template>
-
-<script setup>
-import { ref, reactive, computed, onMounted, watch, nextTick } from 'vue';
-import { onLoad } from '@dcloudio/uni-app';
-import QrCode from "@/components/QrCode.vue";
-import { post } from "@/utils/request";
-import { userToken } from "@/composables/config";
-import { customApi } from "@/service/custom";
-import { ucardApi } from "@/api/ucard";
-import useUserStore from "@/stores/use-user-store";
-import useRouter from "@/hooks/useRouter";
-import { useI18n } from "vue-i18n";
-const router = useRouter();
-const { t } = useI18n();
-const userStore = useUserStore();
-// 响应式表单数据
-const cativeIndex = ref(0);
-const tabs = computed(() => ([
-    { id: 1, name: 'Step 1: Select Account' },
-    { id: 2, name: 'Step 2: Add Information' },
-    { id: 3, name: 'Step 3: Success' },
-
-]))
-
-
-// 数据定义
-const pictLoading = ref(false);
-const flag = ref(false);
-const RES = ref('');
-const dialogCheck = ref(false);
-const dialogVisible = ref(false);
-const showData = ref(null);
-const isOpenAccount = ref(0);
-const checked = ref('');
-const optionsLev = ref([]);
-const optionsCur = ref([]);
-const dome = ref(null);
-const showLogin = ref([]);
-const showPage = ref(false);
-const isTimeShow = ref(false);
-const dialogAccountLimit = ref(false);
-const limitPlatform = ref('');
-const hidden = ref(true);
-const ho = ref('');
-const language = ref('');
-
-// 表单引用
-const formRef = ref(null);
-
-// 表单数据
-const params = reactive({
-    password: '',
-    currency: '',
-    leverage: '',
-    platform: '',
-    balance: null
-});
-
-// 计算属性
-const rule1 = computed(() => {
-    if (!params.password) return false;
-    return /^.{8,15}$/.test(params.password);
-});
-
-const rule2 = computed(() => {
-    return /^(?=.*?[a-z])(?=.*?[A-Z]).*$/.test(params.password);
-});
-
-const rule4 = computed(() => {
-    return /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[~!@&%$^*./\\(\\)\\+\\=#_-])[A-Za-z0-9~!@&%$^*./\\(\\)\\+\\=#_-]{8,16}$/.test(
-        params.password
-    );
-});
-
-// 验证规则
-const rules = {
-    password: [
-        {
-            validator: (rule, value, callback) => {
-                if (/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[~!@&%$^*./\\(\\)\\+\\=#_-])[A-Za-z0-9~!@&%$^*./\\(\\)\\+\\=#_-]{8,16}$/.test(value)) {
-                    callback();
-                } else {
-                    callback(new Error(t('vaildate.password.format')));
-                }
-            },
-            trigger: 'blur',
-            required: true
-        }
-    ],
-    platform: [
-        {
-            required: true,
-            message: t('vaildate.select.empty'),
-            trigger: 'change'
-        }
-    ],
-    currency: [
-        {
-            required: true,
-            message: t('vaildate.select.empty'),
-            trigger: 'change'
-        }
-    ],
-    leverage: [
-        {
-            required: true,
-            message: t('vaildate.select.empty'),
-            trigger: 'change'
-        }
-    ],
-    balance: [
-        {
-            validator: (rule, value, callback) => {
-                if (value === null || value === undefined || value === '') {
-                    callback();
-                    return;
-                }
-                const numValue = Number(value);
-                if (isNaN(numValue)) {
-                    callback(new Error(t('vaildate.amount.format')));
-                    return;
-                }
-                if (numValue < 0 || numValue > 100000) {
-                    callback(new Error(t('vaildate.amount.amount') + '0-100000'));
-                    return;
-                }
-                callback();
-            },
-            trigger: ['blur', 'change']
-        }
-    ]
-};
-
-// 平台选项
-const platformColumns = computed(() => {
-    const columns = [];
-    if (showData.value && showData.value['mt4s'] && showData.value['mt4s'].length) {
-        columns.push({ label: 'MT4', value: 'MT4' });
-    }
-    if (showData.value && showData.value['mt5s'] && showData.value['mt5s'].length) {
-        columns.push({ label: 'MT5', value: 'MT5' });
-    }
-    return [columns];
-});
-
-// 货币选项
-const currencyColumns = computed(() => {
-    if (optionsCur.value.length) {
-        return [optionsCur.value.map(item => ({ label: item, value: item }))];
-    }
-    return [[]];
-});
-
-// 杠杆选项
-const leverageColumns = computed(() => {
-    if (optionsLev.value.length) {
-        return [optionsLev.value.map(item => ({ label: String(item), value: item }))];
-    }
-    return [[]];
-});
-
-// 方法
-const closeDia = () => {
-    if (formRef.value) {
-        formRef.value.resetFields();
-    }
-    dialogCheck.value = false;
-    dialogVisible.value = false;
-};
-
-const closeAccountLimitDialog = () => {
-    dialogAccountLimit.value = false;
-    limitPlatform.value = '';
-};
-
-const showAccountLimitDialog = (platform) => {
-    limitPlatform.value = platform;
-    dialogAccountLimit.value = true;
-};
-
-// 获取必要数据
-const getMustData = async (type, isDome) => {
-    const api = isDome ? customApi.AccountApplyDataDome : customApi.AccountApplyData;
-    const res = await api({
-        type: type
-    });
-    if (res.code === 200) {
-        showData.value = res.data;
-    } else {
-        uni.showToast({
-            title: res.msg,
-            icon: 'none'
-        });
-    }
-};
-
-// 获取显示权限
-const getExcludeShowLogin = async () => {
-    pictLoading.value = true;
-    const res = await customApi.excludeShowLogin({});
-    if (res.code === 200) {
-        showLogin.value = res.data?.excludeShowLoginTypes || [];
-        showPage.value = true;
-        pictLoading.value = false;
-    } else {
-        uni.showToast({
-            title: res.msg,
-            icon: 'none'
-        });
-        pictLoading.value = false;
-    }
-};
-
-// 提交开户
-const newAccount = async (type, isDome) => {
-    if (!formRef.value) return;
-
-    try {
-        await formRef.value.validate();
-    } catch (error) {
-        return;
-    }
-
-    if (flag.value) return;
-    flag.value = true;
-
-    const api = isDome ? customApi.AccountApplyAddDome : customApi.AccountApplyAdd;
-    const res = await api({
-        type: type,
-        ...params
-    });
-
-    if (res.code === 200) {
-        if (isDome) {
-            uni.showToast({
-                title: t('Msg.Success'),
-                icon: 'success'
-            });
-        }
-        isOpenAccount.value = 0;
-        dialogCheck.value = true;
-        dialogVisible.value = true;
-        if (formRef.value) {
-            formRef.value.resetFields();
-        }
-        flag.value = false;
-    } else if (res.code === 407) {
-        showAccountLimitDialog(params.platform);
-        flag.value = false;
-    } else {
-        RES.value = res.msg;
-        dialogCheck.value = true;
-        dialogVisible.value = false;
-        flag.value = false;
-    }
-};
-
-// 展开/关闭账户表单
-const isOpenClose = (index, isDome) => {
-    hidden.value = true;
-    if (isOpenAccount.value === index) {
-        isOpenAccount.value = 0;
-        if (formRef.value) {
-            formRef.value.resetFields();
-        }
-        return;
-    } else {
-        isOpenAccount.value = index;
-    }
-    if (formRef.value) {
-        formRef.value.resetFields();
-    }
-    dome.value = isDome;
-    optionsLev.value = [];
-    optionsCur.value = [];
-    getMustData(index, isDome);
-};
-
-// 选择平台
-const checkPlatform = (pla) => {
-    if (pla === 'mt5s') {
-        hidden.value = false;
-    } else {
-        hidden.value = true;
-    }
-    params.currency = '';
-    params.leverage = '';
-    optionsLev.value = [];
-    optionsCur.value = [];
-    const Cur = [];
-    showData.value[pla].forEach((item) => {
-        Cur.push(item.currency);
-    });
-    Cur.forEach((item) => {
-        if (!optionsCur.value.includes(item)) {
-            optionsCur.value.push(item);
-        }
-    });
-};
-
-// 平台确认
-const handlePlatformConfirm = (value) => {
-    params.platform = value.value[0];
-    const pla = params.platform === 'MT4' ? 'mt4s' : 'mt5s';
-    checkPlatform(pla);
-};
-
-// 货币确认
-const handleCurrencyConfirm = (value) => {
-    params.currency = value.value[0];
-    const pla = params.platform === 'MT4' ? 'mt4s' : 'mt5s';
-    checkCurrency(pla, params.currency);
-};
-
-// 杠杆确认
-const handleLeverageConfirm = (value) => {
-    params.leverage = value.value[0];
-};
-
-// 选择货币
-const checkCurrency = (pla, cur) => {
-    params.leverage = '';
-    optionsLev.value = [];
-    const platform = pla === 'MT4' ? 'mt4s' : 'mt5s';
-    const list = [];
-    showData.value[platform].forEach((item) => {
-        if (item.currency === cur) {
-            list.push(item.leverage);
-        }
-    });
-    params.leverage = list.reduce((a, b) => Math.max(a, b));
-    optionsLev.value = list;
-};
-
-// 时间判断
-const isAfterJuly28 = () => {
-    // 实现日期判断逻辑
-    return false;
-};
-
-const isTimeShowType8 = () => {
-    const endTime1 = '2024/9/25 00:00:00';
-    const timezone = 2;
-    const offset_GMT = new Date().getTimezoneOffset();
-    const nowDate = new Date().getTime();
-    const now = new Date(nowDate + offset_GMT * 60 * 1000 + timezone * 60 * 60 * 1000).getTime();
-    const end = new Date(endTime1).getTime();
-    if (now > end) {
-        isTimeShow.value = true;
-    }
-};
-
-// 余额变化验证
-const handleBalanceChange = () => {
-    if (formRef.value) {
-        formRef.value.validateField('balance');
-    }
-};
-
-// 打开链接
-const openLink = (path) => {
-    uni.navigateTo({
-        url: `/pages/webview/index?url=https://www.${ho.value}.com/${path}`
-    });
-};
-
-// 打开PDF
-const openPdf = (path) => {
-    uni.navigateTo({
-        url: `/pages/webview/index?url=/pdf/${path}`
-    });
-};
-
-// 监听balance变化
-watch(() => params.balance, (newVal, oldVal) => {
-    if (newVal !== oldVal && newVal !== null && newVal !== undefined) {
-        nextTick(() => {
-            if (formRef.value) {
-                formRef.value.validateField('balance');
-            }
-        });
-    }
-});
-
-// 生命周期
-onLoad(() => {
-    const host = window?.location?.host || '';
-    ho.value = host.split('.')[1] || '';
-
-    // 获取语言
-    const locale = uni.getLocale();
-    language.value = locale;
-
-    getExcludeShowLogin();
-    isTimeShowType8();
-});
-
-onMounted(() => {
-    // 挂载后的操作
-});
-</script>
-
-<style lang="scss" scoped>
-.tit {
-    font-size: 16px;
-    font-weight: bold;
-    margin: 10px 0;
-
-    .iconfont {
-        margin-right: 6px;
-    }
-}
-
-.des {
-    font-size: 14px;
-    font-weight: bold;
-    line-height: 1.5;
-    margin-bottom: 20px;
-}
-
-#custom_newAccount {
-    width: 100%;
-    height: 100%;
-    overflow: hidden;
-    overflow-y: auto;
-
-    &.u-loading {
-        position: relative;
-
-        &::after {
-            content: '';
-            position: absolute;
-            top: 0;
-            left: 0;
-            right: 0;
-            bottom: 0;
-            background: rgba(255, 255, 255, 0.5);
-            z-index: 99;
-        }
-    }
-
-    .main-content {
-        text-align: left;
-        padding: 0 20px;
-
-        .box {
-            padding: 10px 0;
-            text-align: left;
-            background-color: #ffffff;
-            border-radius: 2px;
-            margin: 20px 0;
-
-            .pdfLink {
-                color: #42b983;
-                font-weight: bold;
-                text-decoration: underline;
-                margin-left: 4px;
-            }
-
-
-            .b-card {
-                border: 2px solid #e5e5e5;
-                margin-bottom: 20px;
-                border-radius: 2px;
-                position: relative;
-                overflow: hidden;
-
-                .btn-tag-star {
-                    position: absolute;
-                    top: 4px;
-                    left: -15px;
-                    background-color: #f56c6c;
-                    color: #ffffff;
-                    transform: rotate(-45deg);
-                    width: 60px;
-                    text-align: center;
-                    z-index: 9;
-                    padding: 1px 0;
-                }
-
-                .card-top {
-                    display: flex;
-                    border-bottom: 1px solid #e5e5e5;
-
-                    .tit {
-                        font-weight: bold;
-                    }
-
-                    .btn-bottom {
-                        font-size: 14px;
-
-                        .btn-open,
-                        .btn-try {
-                            display: inline-block;
-                            width: 150px;
-                            text-align: center;
-                            border: 1px solid #e5e5e5;
-                            padding: 8px 0;
-                            margin: 5px;
-                            color: #ffffff;
-
-                            .iconfont {
-                                margin-right: 3px;
-                                font-size: 12px;
-                            }
-                        }
-
-                        .btn-open {
-                            margin-right: 5px;
-                            background-color: #f56c6c;
-                            color: #ffffff;
-                        }
-
-                        .btn-try {
-                            background-color: #909399;
-                        }
-                    }
-
-                    .header {
-                        padding: 15px 25px;
-                    }
-
-                    .descending {
-                        padding: 10px;
-                        box-sizing: border-box;
-                        height: 100%;
-                        width: 100%;
-                        font-size: 14px;
-                        line-height: 1.2;
-                        background-color: #f5f5f5;
-                        display: flex;
-                        flex-wrap: wrap;
-                        align-items: center;
-
-                        view {
-                            width: 100%;
-                            box-sizing: border-box;
-                            text-align: center;
-                        }
-                    }
-                }
-
-                .card-bottom {
-                    padding: 20px;
-                    border-bottom: 1px solid #d5d5d5;
-
-                    .check {
-                        padding: 6px 8px;
-                        margin: 15px 15px 15px 0;
-                        border: 1px solid #d5d5d5;
-                    }
-
-                    .pwd {
-                        text-align: left;
-                        padding-left: 20px;
-                        margin-top: 15px;
-
-                        view {
-                            list-style-type: disc;
-                            line-height: 1.2;
-                            margin: 4px 0;
-                            color: #c0c4cc;
-
-                            &.fit {
-                                color: #67c23a;
-                            }
-                        }
-                    }
-
-                    .picker-value {
-                        padding: 10px 0;
-                        border-bottom: 1px solid #e5e5e5;
-                    }
-
-                    .s-btn {
-                        width: 100%;
-                        margin-top: 20px;
-                    }
-                }
-
-                &:hover {
-                    border-color: #f56c6c;
-                }
-            }
-        }
-    }
-
-    .dia-content {
-        text-align: center;
-        padding: 30px 20px;
-
-        .icon {
-            .iconfont {
-                font-size: 80px;
-
-                &.icon-warning {
-                    color: #f56c6c;
-                }
-
-                &.icon-success {
-                    color: #67c23a;
-                }
-            }
-        }
-
-        .des1 {
-            font-weight: bold;
-            font-size: 16px;
-            margin: 30px 0 15px;
-        }
-
-        .des2 {
-            font-size: 14px;
-            margin-bottom: 30px;
-        }
-
-        .dialog-footer {
-            display: flex;
-            justify-content: center;
-            gap: 20px;
-            margin-top: 20px;
-
-            .uv-button {
-                min-width: 100px;
-            }
-        }
-    }
-
-    .account-limit-content {
-        text-align: center;
-        padding: 30px 20px;
-
-        .icon {
-            margin-bottom: 20px;
-
-            .iconfont {
-                font-size: 60px;
-                color: #f56c6c;
-            }
-        }
-
-        .title {
-            font-size: 18px;
-            font-weight: bold;
-            color: #333;
-            margin-bottom: 20px;
-        }
-
-        .content {
-            text-align: center;
-            margin: 20px 0 30px;
-
-            .limit-text {
-                view {
-                    font-size: 14px;
-                    line-height: 1.6;
-                    color: #666;
-                    margin-bottom: 15px;
-                    text-align: center;
-                }
-            }
-        }
-
-        .dialog-footer {
-            text-align: center;
-            margin-top: 20px;
-
-            .confirm-btn {
-                min-width: 120px;
-                background-color: #f56c6c;
-                border: none;
-                color: #fff;
-            }
-        }
-    }
-}
-</style>

+ 169 - 181
pages/customer/create-account.vue

@@ -1,97 +1,24 @@
 <template>
-    <cwg-page-wrapper class="create-page" :isHeaderFixed="true">
-        <uni-card class="create-content" :margin="0" :spacing="0">
-            <view class="content-title" v-t="'Custom.NewAccount.Title'"></view>
-            <view class="tit">
-                <text class="iconfont icon-caret-right"></text>
-                <text>{{ t('Custom.NewAccount.Title1') }}</text>
-            </view>
-            <view class="des">
-                <text>{{ t('Custom.NewAccount.Des1') }}</text>
-            </view>
-            <cwg-tabs :cativeIndex="cativeIndex" @tabClick="handleTabClick" :tabs="tabs" class="tabs-class" />
-            <template v-if="cativeIndex === 0">
-                <view class="box" v-if="
-                    showLogin.indexOf('6') === -1 ||
-                    showLogin.indexOf('2') === -1 ||
-                    showLogin.indexOf('7') === -1 ||
-                    (showLogin.indexOf('8') === -1 && isTimeShow)">
-                    <uni-row class="form-row uni-row1">
-                        <uni-col :xs="24" :sm="24" :md="24" :lg="8" :xl="8" v-for="(item, index) in accountList"
-                            :key="index">
-                            <view class="b-card" v-if="item.showCondition() && !item.isHide">
-                                <view class="btn-tag-star">
-                                    <image :src="item.img" class="avatar" mode="widthFix" />
-                                </view>
-                                <view class="header">
-                                    <view class="tit">
-                                        <text v-t="item.typeKey"></text>
-                                    </view>
-                                    <view class="des">
-                                        <text v-t="item.desKey">{{ t('Custom.NewAccount.DesLogin5') }}</text>
-                                    </view>
+    <cwg-page-wrapper class="create-page " :isHeaderFixed="true">
+        <view class="create-card">
 
-                                </view>
-                                <view class="descending">
-                                    <view v-for="value in item.features" :key="value.key" class="feature">
-                                        <view class="icon-success"><cwg-icon name="crm-check" :size="16"
-                                                color="#10b981" />
-                                        </view>
-                                        <text v-t="value.key" />
-                                    </view>
-                                </view>
-                                <view class="btn-bottom">
-                                    <text class="btn-open" @click="isOpenClose(item.id, null)">
-                                        <text>{{ t('Custom.NewAccount.Btn') }}</text>
-                                        <text class="iconfont icon-arrow-right"></text>
-                                    </text>
-                                    <text class="btn-try" @click="isOpenClose(item.id, item.id)">
-                                        <text>{{ t('Custom.NewAccount.BtnDome') }}</text>
-                                        <text class="iconfont icon-arrow-right"></text>
-                                    </text>
-                                </view>
-                            </view>
-                        </uni-col>
-                    </uni-row>
-                </view>
-                <!-- 无可用账户提示 -->
-                <view class="box-text" v-if="
-                    showLogin.indexOf('6') !== -1 &&
-                    showLogin.indexOf('1') !== -1 &&
-                    showLogin.indexOf('2') !== -1 &&
-                    showLogin.indexOf('3') !== -1 &&
-                    showLogin.indexOf('7') !== -1 &&
-                    !(showLogin.indexOf('8') === -1 && isTimeShow)
-                ">
-                    <view class="text">
-                        <text>{{ t('news_add_field.OpenAccount.Des3') }}</text>
-                    </view>
-                </view>
+            <view class="card-bottom user-form crm-form">
+                <view class="tabs-class">
+                    <cwg-tabs v-model:cativeIndex="cativeIndex" :tabs="tabs" />
 
-                <!-- 底部说明 -->
-                <view class="box-text">
-                    <view class="text">
-                        <text>{{ t('news_add_field.OpenAccount.Des1') }}</text>
-                        <text class="pdfLink" @click="openPdf('PrivacyPolicy2019_01.pdf')">
-                            {{ t('news_add_field.OpenAccount.Des2') }}
-                        </text>
-                    </view>
                 </view>
-            </template>
-
-            <view class="card-bottom user-form crm-form " v-if="cativeIndex == 1">
                 <uni-forms ref="baseForm" :model="formData" labelWidth="200" label-position="top" :rules="rules"
                     class="base-info-form">
-                    <uni-row class="demo-uni-row uni-row1">
+                    <uni-row class="demo-uni-row uni-row1 uni-row2">
                         <!-- MT4/MT5 -->
-                        <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+                        <uni-col :xs="24">
                             <uni-forms-item :label="t('Custom.NewAccount.Platform')">
                                 <cwg-combox :clearable="false" v-model:value="formData.platform"
                                     :options="platformColumns" :placeholder="t('placeholder.choose')" />
                             </uni-forms-item>
                         </uni-col>
                         <!-- 货币类型 -->
-                        <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+                        <uni-col :xs="24">
                             <uni-forms-item :label="t('Custom.NewAccount.Currency')">
                                 <cwg-combox :clearable="false" v-model:value="formData.currency"
                                     :options="currencyColumns" :placeholder="t('placeholder.choose')" />
@@ -99,20 +26,28 @@
                         </uni-col>
 
                         <!-- 杠杆 -->
-                        <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+                        <uni-col :xs="24">
                             <uni-forms-item :label="t('Custom.NewAccount.Lever')">
                                 <cwg-combox :clearable="false" :disabled="hidden" v-model:value="formData.leverage"
                                     :options="leverageColumns" :placeholder="t('placeholder.choose')" />
                             </uni-forms-item>
                         </uni-col>
+
+                        <!-- 账户余额 -->
+                        <uni-col :xs="24" v-if="dome">
+                            <uni-forms-item :label="t('Custom.NewAccount.Balance')">
+                                <uni-easyinput type="digit" :clearable="false" v-model="formData.balance"
+                                    :placeholder="t('Custom.NewAccount.BalancePlaceholder')" />
+                            </uni-forms-item>
+                        </uni-col>
                         <!-- 交易密码 -->
-                        <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+                        <uni-col :xs="24">
                             <uni-forms-item :label="t('Custom.NewAccount.Password')">
                                 <uni-easyinput :clearable="false" v-model="formData.password"
                                     :placeholder="t('Custom.NewAccount.Password')" />
                             </uni-forms-item>
                         </uni-col>
-                        <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+                        <uni-col :xs="24">
                             <view class="notice-list">
                                 <view v-for="(item, index) in noticeItems" :key="index"
                                     :class="['notice-item', item.valid ? 'isOK' : '']">
@@ -120,21 +55,40 @@
                                 </view>
                             </view>
                         </uni-col>
-                        <!-- 账户余额 -->
-                        <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="dome">
-                            <uni-forms-item :label="t('Custom.NewAccount.Balance')">
-                                <uni-easyinput type="digit" :clearable="false" v-model="formData.balance"
-                                    :placeholder="t('Custom.NewAccount.BalancePlaceholder')" />
-                            </uni-forms-item>
-                        </uni-col>
 
-                        <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+
+                        <uni-col :xs="24">
                             <view class="btn btn-confirm" @click="newAccount">{{ t('Btn.Application') }}</view>
                         </uni-col>
                     </uni-row>
                 </uni-forms>
             </view>
-        </uni-card>
+
+            <view class="card-content">
+                <text class="account-name" v-t="currentAccount?.name"></text>
+
+                <!-- 点差信息 -->
+                <view class="info-row">
+                    <view class="info-label">最低入金</view>
+                    <view class="info-value">{{ currentAccount?.minDeposit || '--' }}</view>
+                </view>
+                <!-- 点差信息 -->
+                <view class="info-row">
+                    <view class="info-label">最小点差</view>
+                    <view class="info-value">{{ currentAccount?.minSpread || '--' }}</view>
+                </view>
+
+                <!-- 杠杆信息 -->
+                <view class="info-row">
+                    <view class="info-label">最大杠杆</view>
+                    <view class="info-value">{{ currentAccount?.maxLeverage || '--' }}</view>
+                </view>
+                <view class="info-row">
+                    <view class="info-value"><a href="/static/pdf/PrivacyPolicy2019_01.pdf" target="_blank"
+                            v-t="'news_add_field.OpenAccount.Des2'"></a></view>
+                </view>
+            </view>
+        </view>
         <!-- 提交后的弹出框 -->
         <uni-popup :show="dialogCheck" mode="center" round="16" @close="closeDia">
             <view class="dia-content" v-if="dialogVisible">
@@ -199,111 +153,72 @@
 <script setup>
 import { ref, reactive, computed, onMounted, watch, nextTick } from 'vue';
 import { onLoad } from '@dcloudio/uni-app';
-import { userToken } from "@/composables/config";
 import { customApi } from "@/service/custom";
-import { ucardApi } from "@/api/ucard";
 import useUserStore from "@/stores/use-user-store";
 import useRouter from "@/hooks/useRouter";
 import { useI18n } from "vue-i18n";
-import { image } from 'uview-plus/libs/function/test';
 const router = useRouter();
 const { t, locale } = useI18n();
 const userStore = useUserStore();
-// 响应式表单数据
-const cativeIndex = ref(0);
-const handleTabClick = (index) => {
-    if(index == 0){
-        cativeIndex.value = 0
-    }
-};
-const tabs = computed(() => ([
-    { id: 1, name: 'Step 1: Select Account' },
-    { id: 2, name: 'Step 2: Add Information' },
-    { id: 3, name: 'Step 3: Success' },
-]))
-
-const accountList = computed(() => ([
-    {
-        id: 6,
-        type: 'SpeedAccount',
-        typeKey: 'AccountType.SpeedAccount',
-        showCondition: () => showLogin.value.indexOf('6') === -1,
-        desKey: 'Custom.NewAccount.DesLogin1',
-        features: [
-            { key: 'Custom.NewAccount.DesLogin11', condition: true },
-            { key: 'Custom.NewAccount.DesLogin12', condition: true },
-            { key: 'Custom.NewAccount.DesLogin13', condition: true },
-            { key: 'Custom.NewAccount.DesLogin14', condition: true }
-        ],
-        hasStar: false,
-        isHide: true
-    },
-    {
-        id: 1,
-        type: 'ClassicAccount',
-        typeKey: 'AccountType.ClassicAccount',
-        showCondition: () => showLogin.value.indexOf('1') === -1,
-        desKey: 'Custom.NewAccount.DesLogin2',
-        features: [
-            { key: 'Custom.NewAccount.DesLogin21', condition: true },
-            { key: 'Custom.NewAccount.DesLogin22', condition: true },
-            {
-                key: 'Custom.NewAccount.DesLogin23',
-                condition: ['cn', 'zhHant'].indexOf(locale.value) === -1
-            },
-            { key: 'Custom.NewAccount.DesLogin24', condition: true }
-        ],
-        hasStar: false,
-        isHide: true
-    },
+// 定义账户数据类型
+const standardAccounts = ref([
     {
         id: 7,
         type: 'StandardAccount',
-        typeKey: 'AccountType.StandardAccount',
+        name: 'AccountType.StandardAccount',
         showCondition: () => showLogin.value.indexOf('7') === -1,
-        desKey: 'Custom.NewAccount.DesLogin5',
-        features: [
-            { key: 'Custom.NewAccount.DesLogin51', condition: true },
-            { key: 'Custom.NewAccount.DesLogin52', condition: true },
-            {
-                key: 'Custom.NewAccount.DesLogin53',
-                condition: ['cn', 'zhHant'].indexOf(locale.value) === -1
-            },
-            { key: 'Custom.NewAccount.DesLogin54', condition: true }
-        ],
-        hasStar: true,
-        img: '/static/images/info/bank-information-1.webp',
+        description: 'Custom.NewAccount.DesLogin5',
+        minDeposit: '50 USD',
+        minSpread: '0.01',
+        maxLeverage: '1:1000',
+        icon: '/static/images/info/bank-information-1.webp',
     },
     {
         id: 2,
         type: 'SeniorAccount',
-        typeKey: 'AccountType.SeniorAccount',
+        name: 'AccountType.SeniorAccount',
         showCondition: () => showLogin.value.indexOf('2') === -1,
-        desKey: 'Custom.NewAccount.DesLogin3',
+        description: 'Custom.NewAccount.DesLogin3',
         features: [
             { key: 'Custom.NewAccount.DesLogin31', condition: true },
             { key: 'Custom.NewAccount.DesLogin32', condition: true },
             { key: 'Custom.NewAccount.DesLogin33', condition: true },
             { key: 'Custom.NewAccount.DesLogin34', condition: true }
         ],
-        hasStar: false,
-        img: '/static/images/info/bank-information-2.webp',
+        minDeposit: '200 USD',
+        minSpread: '0.01',
+        maxLeverage: '1:2000',
+        icon: '/static/images/info/bank-information-2.webp',
     },
     {
         id: 8,
         type: 'CentAccount',
-        typeKey: 'AccountType.CentAccount',
+        name: 'AccountType.CentAccount',
         showCondition: () => showLogin.value.indexOf('8') === -1 && isTimeShow.value,
-        desKey: 'Custom.NewAccount.DesLogin8',
+        description: 'Custom.NewAccount.DesLogin8',
         features: [
             { key: 'Custom.NewAccount.DesLogin81', condition: true },
             { key: 'Custom.NewAccount.DesLogin82', condition: true },
             { key: 'Custom.NewAccount.DesLogin84', condition: true }
         ],
-        hasStar: false,
-        img: '/static/images/info/bank-information-3.webp',
+        minDeposit: '10 USD',
+        minSpread: '0.01',
+        maxLeverage: '1:1000',
+        icon: '/static/images/info/bank-information-3.webp',
     }
-]));
+])
+const cativeIndex = ref(0)
+const tabs = computed(() => ([
+    { id: 'real', name: '真实' },
+    { id: 'demo', name: '模拟' }
+]))
+
+const currentAccount = computed(() => {
+    // 从账户列表中查找匹配的账户
+    const matched = standardAccounts.value.find(account => account.id == isOpenAccount.value);
+    // 如果未找到,返回一个默认空对象或 null,模板中需做判空处理
+    return matched || null;
+});
 
 // 数据定义
 const pictLoading = ref(false);
@@ -334,7 +249,7 @@ const formData = reactive({
     currency: '',
     leverage: '',
     platform: '',
-    balance: null
+    balance: null,
 });
 
 
@@ -502,7 +417,6 @@ const newAccount = async () => {
 
     if (flag.value) return;
     flag.value = true;
-
     const api = dome.value ? customApi.AccountApplyAddDome : customApi.AccountApplyAdd;
     const res = await api({
         type: isOpenAccount.value,
@@ -516,6 +430,7 @@ const newAccount = async () => {
                 icon: 'success'
             });
         }
+        router.push('/pages/customer/index')
         isOpenAccount.value = 0;
         dialogCheck.value = true;
         dialogVisible.value = true;
@@ -534,15 +449,6 @@ const newAccount = async () => {
     }
 };
 
-// 展开/关闭账户表单
-const isOpenClose = (index, isDome) => {
-    cativeIndex.value = 1
-    isOpenAccount.value = index
-    dome.value = isDome;
-    optionsLev.value = [];
-    optionsCur.value = [];
-    getMustData(index, isDome);
-};
 
 // 选择平台
 const checkPlatform = (pla) => {
@@ -640,13 +546,20 @@ watch(() => formData.balance, (newVal, oldVal) => {
         });
     }
 });
+watch(() => cativeIndex.value, (newVal) => {
+    dome.value = newVal == 1
+});
 
 // 生命周期
-onLoad(() => {
+onLoad((e) => {
+    dome.value = e.server == 'demo'
+    cativeIndex.value = e.server == 'demo' ? 1 : 0
+    isOpenAccount.value = e.id
     const host = window?.location?.host || '';
     ho.value = host.split('.')[1] || '';
 
     getExcludeShowLogin();
+    getMustData(isOpenAccount.value, dome.value);
     isTimeShowType8();
 });
 
@@ -760,10 +673,6 @@ onMounted(() => {
         margin-bottom: px2rpx(10);
     }
 
-    .uni-easyinput__content {
-        border: none !important;
-        background-color: var(--color-zinc-100) !important;
-    }
 }
 
 .btn {
@@ -812,6 +721,85 @@ onMounted(() => {
 }
 
 .card-bottom {
+    max-width: px2rpx(566);
     margin-top: px2rpx(20);
+
+    .tabs-class {
+        margin: 0 px2rpx(10) px2rpx(20) px2rpx(10);
+    }
+}
+
+.create-card {
+    display: flex;
+    gap: px2rpx(30);
+    justify-content: space-between;
+}
+
+@media (max-width: 992px) {
+    .card-bottom {
+        width: 100%;
+        margin-top: px2rpx(20);
+    }
+
+    .create-card {
+        display: flex;
+        gap: px2rpx(30);
+        flex-wrap: wrap;
+    }
+}
+
+.card-content {
+    margin-top: px2rpx(30);
+    padding: px2rpx(16);
+    width: px2rpx(300);
+
+
+    .account-name {
+        display: block;
+        font-size: px2rpx(18);
+        font-weight: 600;
+        color: #1e2a3a;
+        padding-bottom: px2rpx(16);
+        padding-left: px2rpx(20);
+        border-left: 1px solid #f0f2f5;
+    }
+
+    .info-row {
+        padding-left: px2rpx(20);
+        padding-bottom: px2rpx(12);
+        border-left: 1px solid #f0f2f5;
+
+        .info-label {
+            font-size: px2rpx(15);
+            line-height: px2rpx(30);
+            color: #7f8c8d;
+        }
+
+        .info-value {
+            font-size: px2rpx(14);
+            font-weight: 500;
+            color: #1e2a3a;
+        }
+    }
+
+    .link-wrapper {
+        display: flex;
+        align-items: center;
+        justify-content: flex-end;
+        margin-top: px2rpx(8);
+        padding-top: px2rpx(8);
+        border-top: 1rpx solid #f0f2f5;
+
+        .link-text {
+            font-size: px2rpx(14);
+            color: #007aff;
+            margin-right: px2rpx(4);
+        }
+
+        .link-icon {
+            font-size: px2rpx(14);
+            color: #007aff;
+        }
+    }
 }
 </style>

+ 824 - 577
pages/customer/deposit.vue

@@ -1,431 +1,488 @@
 <template>
-    <view class="custom-deposit">
-        <!-- 标题 -->
-        <view class="crm-title-box">
-            <text class="tit">{{ t('Home.page_customer.item2') }}</text>
-        </view>
-
-        <!-- 步骤1:选择账户 -->
-        <view class="box box-step1">
-            <view class="b-card">
-                <view class="card-top">
-                    <text class="tit"><text class="iconfont icon-caret-right"></text>{{ t('Custom.Deposit.Title1')
-                        }}</text>
-                    <picker mode="selector" :range="loginOptions" :range-key="'label'" @change="onAccountChange"
-                        :value="selectedAccountIndex">
-                        <view class="picker-view">{{ selectedAccountLabel || t('placeholder.choose') }}</view>
-                    </picker>
-                </view>
-            </view>
-        </view>
-
-        <!-- 步骤2:支付通道列表(卡片布局) -->
-        <view class="box box-step2" v-if="step2">
-            <view class="b-card">
-                <view class="card-top">
-                    <text class="tit"><text class="iconfont icon-caret-right"></text>{{ t('Custom.Deposit.Title2')
-                        }}</text>
-                    <view v-for="(group, index) in sortedTableData" :key="index">
-                        <view class="channelType" v-if="group.length" v-t="groupTitleMap[group[0].type]" />
-                        <PaymentMethodsList :list="group" @select="isShowStep3" />
-                    </view>
-                    <view v-if="step3" class="reselect-btn">
-                        <button class="s-btn reselect" type="primary" @click="showTable">{{
-                            t('Custom.Deposit.Reselect') }}</button>
+    <cwg-page-wrapper class="create-page" :isHeaderFixed="true">
+        <view class="custom-deposit">
+            <!-- 标题 -->
+            <!-- <view class="crm-title-box">
+                <text class="tit">{{ t('Home.page_customer.item2') }}</text>
+            </view> -->
+
+            <!-- 步骤1:选择账户 -->
+            <view class="box box-step1">
+                <view class="b-card">
+                    <view class="card-top">
+                        <text class="tit"><text class="iconfont icon-caret-right"></text>{{ t('Custom.Deposit.Title1')
+                            }}</text>
+                        <cwg-combox :clearable="false" v-model:value="loginValue" :options="loginComboxOptions"
+                            :placeholder="t('placeholder.choose')" @change="onAccountChange" />
                     </view>
                 </view>
             </view>
-        </view>
-
-        <!-- 步骤3:填写入金信息 -->
-        <view class="box box-step3" v-if="step3">
-            <view class="b-card">
-                <view class="card-top">
-                    <!-- 注意事项(第一步确认) -->
-                    <view v-if="!isStep3">
-                        <view class="step3-attention">
-                            <rich-text class="attention"
-                                :nodes="(locale === 'cn' || locale === 'zhHant') ? introduce.introduce : introduce.enIntroduce"></rich-text>
-                            <view class="btn-bottom">
-                                <text class="btn crm-cursor" @click="isStep3Open()">{{ t('Btn.Confirm') }}</text>
-                            </view>
-                        </view>
-                    </view>
-
-                    <!-- 表单(确认后显示) -->
-                    <form v-if="isStep3">
-                        <!-- 信用卡选择 -->
-                        <view v-if="channelData.confirmCreditCard == 1">
-                            <view class="add-back">
-                                <text>{{ t('PersonalManagement.Label.addCreditCard') }}</text>
-                                <text class="add-btn crm-cursor" @click="openAddBankCard">{{
-                                    t('Custom.Withdraw.addBank1') }}</text>
-                            </view>
-                            <picker mode="selector" :range="ruleForm.bankCredit"
-                                :range-key="(item) => item.bankUname + '-' + item.bankCardNum"
-                                @change="onCreditCardChange" :value="selectedCreditIndex">
-                                <view class="picker-view">{{ selectedCreditLabel || t('placeholder.choose') }}</view>
-                            </picker>
-                        </view>
-
-                        <!-- 银行选择(如有) -->
-                        <view v-if="bankDate.length">
-                            <text class="tit"><text class="iconfont icon-caret-right"></text>{{
-                                t('news_add_field.Label.Title4') }}</text>
-                            <picker mode="selector" :range="bankDate"
-                                :range-key="(item) => (locale === 'cn' || locale === 'zhHant') ? item.name : item.enName"
-                                @change="onBankChange" :value="selectedBankIndex">
-                                <view class="picker-view">{{ selectedBankLabel || t('placeholder.choose') }}</view>
-                            </picker>
-                        </view>
 
-                        <!-- 特别提示(B2BINPAY) -->
-                        <view v-if="bankDate.length && channelData.code == 'B2BINPAY'">
-                            <text class="tit"><text class="iconfont iconi"></text>{{ t('Custom.Deposit.Des') }}</text>
+            <!-- 步骤2:支付通道列表(卡片布局) -->
+            <view class="box box-step2" v-if="step2">
+                <view class="b-card">
+                    <view class="card-top">
+                        <text class="tit"><text class="iconfont icon-caret-right"></text>{{ t('Custom.Deposit.Title2')
+                            }}</text>
+                        <view v-for="(group, index) in sortedTableData" :key="index">
+                            <view class="channelType" v-if="group.length" v-t="groupTitleMap[group[0].type]" />
+                            <PaymentMethodsList :list="group" @select="isShowStep3" />
                         </view>
-
-                        <!-- 电汇信息展示 -->
-                        <view
-                            v-if="['UNION_PAY_TELEGRAPHIC', 'UNION_PAY_TELEGRAPHIC_SPECIAL', 'UNION_PAY_TELEGRAPHIC_TWO'].includes(channelData.code)">
-                            <text class="tit"><text class="iconfont icon-caret-right"></text>{{
-                                t('Custom.Deposit.Title5') }}</text>
-                            <view class="wire-transfer-account">
-                                <view class="row"><text class="label SpecialColor">{{ t('Custom.Deposit.bankUname')
-                                        }}</text><text class="content SpecialColor">{{ WireTransferAccount.bankUname ||
-                                            '--' }}</text></view>
-                                <view class="row"><text class="label">{{ t('Custom.Deposit.bankName') }}</text><text
-                                        class="content">{{ WireTransferAccount.bankName || '--' }}</text></view>
-                                <view class="row"><text class="label SpecialColor">{{ t('Custom.Deposit.bankCardNum')
-                                        }}</text><text class="content SpecialColor">{{ WireTransferAccount.bankCardNum
-                                            || '--' }}</text></view>
-                                <view class="row"><text class="label">{{ t('Custom.Deposit.bankAddr') }}</text><text
-                                        class="content">{{ WireTransferAccount.bankAddr || '--' }}</text></view>
-                                <view class="row"><text class="label SpecialColor">{{ t('Custom.Deposit.swiftCode')
-                                        }}</text><text class="content SpecialColor">{{ WireTransferAccount.swiftCode ||
-                                            '--' }}</text></view>
-                                <view class="row"><text class="label">{{ t('Custom.Deposit.bankCode') }}</text><text
-                                        class="content">{{ WireTransferAccount.bankCode || '--' }}</text></view>
-                                <view class="row"><text class="label SpecialColor">{{ t('Custom.Recording.Note')
-                                        }}</text><text class="content SpecialColor">{{ WireTransferAccount.bankMsg ||
-                                            '--' }}</text></view>
-                            </view>
+                        <view v-if="step3" class="reselect-btn">
+                            <button class="s-btn reselect" type="primary" @click="showTable">{{
+                                t('Custom.Deposit.Reselect') }}</button>
                         </view>
+                    </view>
+                </view>
+            </view>
 
-                        <!-- 数字货币信息展示 -->
-                        <view v-if="channelData.code && channelData.code.indexOf('DIGITAL_PAY_TYPE_KEY') === 0">
-                            <text class="tit"><text class="iconfont icon-caret-right"></text>{{
-                                t('Custom.Deposit.DigitalAcc') }}</text>
-                            <view class="wire-transfer-account">
-                                <view class="row"><text class="label SpecialColor">{{ t('Custom.Deposit.DigitalName')
-                                        }}</text><text class="content SpecialColor">{{ WireTransferAccount.name + '-' +
-                                            WireTransferAccount.type }}</text></view>
-                                <view class="row"><text class="label">{{ t('Custom.Withdraw.Title6') }}</text><text
-                                        class="content">{{ WireTransferAccount.address || '--' }}</text></view>
-                                <view class="row"><text class="label">QR Code</text>
-                                    <image :src="Host85 + WireTransferAccount.url" mode="aspectFit"
-                                        style="width: 100rpx; height: 100rpx;" />
+            <!-- 步骤3:填写入金信息 -->
+            <view class="box box-step3" v-if="step3">
+                <view class="b-card">
+                    <view class="card-top">
+                        <!-- 注意事项(第一步确认) -->
+                        <view v-if="!isStep3">
+                            <view class="step3-attention">
+                                <rich-text class="attention"
+                                    :nodes="(locale === 'cn' || locale === 'zhHant') ? introduce.introduce : introduce.enIntroduce"></rich-text>
+                                <view class="btn-bottom">
+                                    <text class="btn crm-cursor" @click="isStep3Open()">{{ t('Btn.Confirm') }}</text>
                                 </view>
                             </view>
                         </view>
 
-                        <!-- 表单字段:金额、预估金额、上传凭证、优惠码 -->
-                        <text class="tit"><text class="iconfont icon-caret-right"></text>{{ t('Custom.Deposit.Title3')
-                            }}</text>
-                        <view class="form-row">
-                            <view class="form-item">
-                                <text class="label">{{ t('Custom.Deposit.Title3') + '(' + channelData.currency + ')'
-                                    }}</text>
-                                <input class="input" v-model="params.amount" type="number" @input="onAmountInput" />
-                                <text class="error" v-if="amountError">{{ amountError }}</text>
-                            </view>
-                            <view class="form-item" v-if="channelData.rate">
-                                <text class="label">{{ t('Custom.Deposit.EstimatedAmount') + '(' +
-                                    channelData.transformCurrency + ')' }}</text>
-                                <input class="input" v-model="params.amount1" disabled />
-                                <text class="help-icon" @click="showEstimateHelp">?</text>
-                            </view>
-                            <view class="form-item" v-if="needUploadVoucher">
-                                <text class="label">{{ t('Custom.Deposit.UploadRemittanceVoucher') }}</text>
-                                <button @click="chooseImage">{{ t('upload') }}</button>
-                                <image v-if="imageUrl" :src="imageUrl" mode="aspectFit"
-                                    style="width: 100rpx; height: 100rpx;" />
-                            </view>
-                            <view class="form-item">
-                                <text class="label">{{ t('Custom.Deposit.PromoCode') }}</text>
-                                <input class="input" v-model="params.promoCode" />
-                            </view>
-                        </view>
+                        <!-- 表单(确认后显示) -->
+                        <uni-forms v-if="isStep3" ref="baseForm" :model="params" labelWidth="200" label-position="top"
+                            class="base-info-form">
+                            <uni-row class="demo-uni-row uni-row1">
+                                <!-- 信用卡选择 -->
+                                <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8"
+                                    v-if="channelData.confirmCreditCard == 1">
+                                    <view class="add-back">
+                                        <text>{{ t('PersonalManagement.Label.addCreditCard') }}</text>
+                                        <text class="add-btn crm-cursor" @click="openAddBankCard">{{
+                                            t('Custom.Withdraw.addBank1') }}</text>
+                                    </view>
+                                    <uni-forms-item :label="t('PersonalManagement.Label.addCreditCard')">
+                                        <cwg-combox :clearable="false" v-model:value="myId" :options="creditCardOptions"
+                                            :placeholder="t('placeholder.choose')" @change="onCreditCardChange" />
+                                    </uni-forms-item>
+                                </uni-col>
+
+                                <!-- 银行选择(如有) -->
+                                <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="bankDate.length">
+                                    <uni-forms-item :label="t('news_add_field.Label.Title4')">
+                                        <cwg-combox :clearable="false" v-model:value="selectedBankIndex"
+                                            :options="bankOptions" :placeholder="t('placeholder.choose')"
+                                            @change="onBankChange" />
+                                    </uni-forms-item>
+                                </uni-col>
+
+                                <!-- 特别提示(B2BINPAY) -->
+                                <uni-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24"
+                                    v-if="bankDate.length && channelData.code == 'B2BINPAY'">
+                                    <text class="tit"><text class="iconfont iconi"></text>{{ t('Custom.Deposit.Des')
+                                        }}</text>
+                                </uni-col>
+
+                                <!-- 电汇信息展示 -->
+                                <uni-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24"
+                                    v-if="['UNION_PAY_TELEGRAPHIC', 'UNION_PAY_TELEGRAPHIC_SPECIAL', 'UNION_PAY_TELEGRAPHIC_TWO'].includes(channelData.code)">
+                                    <text class="tit"><text class="iconfont icon-caret-right"></text>{{
+                                        t('Custom.Deposit.Title5') }}</text>
+                                    <view class="wire-transfer-account">
+                                        <view class="row"><text class="label SpecialColor">{{
+                                            t('Custom.Deposit.bankUname')
+                                                }}</text><text class="content SpecialColor">{{
+                                                    WireTransferAccount.bankUname
+                                                    ||
+                                                    '--' }}</text></view>
+                                        <view class="row"><text class="label">{{ t('Custom.Deposit.bankName')
+                                                }}</text><text class="content">{{ WireTransferAccount.bankName || '--'
+                                                }}</text></view>
+                                        <view class="row"><text class="label SpecialColor">{{
+                                            t('Custom.Deposit.bankCardNum')
+                                                }}</text><text class="content SpecialColor">{{
+                                                    WireTransferAccount.bankCardNum
+                                                    || '--' }}</text></view>
+                                        <view class="row"><text class="label">{{ t('Custom.Deposit.bankAddr')
+                                                }}</text><text class="content">{{ WireTransferAccount.bankAddr || '--'
+                                                }}</text></view>
+                                        <view class="row"><text class="label SpecialColor">{{
+                                            t('Custom.Deposit.swiftCode')
+                                                }}</text><text class="content SpecialColor">{{
+                                                    WireTransferAccount.swiftCode
+                                                    ||
+                                                    '--' }}</text></view>
+                                        <view class="row"><text class="label">{{ t('Custom.Deposit.bankCode')
+                                                }}</text><text class="content">{{ WireTransferAccount.bankCode || '--'
+                                                }}</text></view>
+                                        <view class="row"><text class="label SpecialColor">{{ t('Custom.Recording.Note')
+                                                }}</text><text class="content SpecialColor">{{
+                                                    WireTransferAccount.bankMsg
+                                                    ||
+                                                    '--' }}</text></view>
+                                    </view>
+                                </uni-col>
+
+                                <!-- 数字货币信息展示 -->
+                                <uni-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24"
+                                    v-if="channelData.code && channelData.code.indexOf('DIGITAL_PAY_TYPE_KEY') === 0">
+                                    <text class="tit"><text class="iconfont icon-caret-right"></text>{{
+                                        t('Custom.Deposit.DigitalAcc') }}</text>
+                                    <view class="wire-transfer-account">
+                                        <view class="row"><text class="label SpecialColor">{{
+                                            t('Custom.Deposit.DigitalName')
+                                                }}</text><text class="content SpecialColor">{{ WireTransferAccount.name
+                                                    +
+                                                    '-' +
+                                                    WireTransferAccount.type }}</text></view>
+                                        <view class="row"><text class="label">{{ t('Custom.Withdraw.Title6')
+                                                }}</text><text class="content">{{ WireTransferAccount.address || '--'
+                                                }}</text></view>
+                                        <view class="row"><text class="label">QR Code</text>
+                                            <image :src="Host85 + WireTransferAccount.url" mode="aspectFit"
+                                                style="width: 100rpx; height: 100rpx;" />
+                                        </view>
+                                    </view>
+                                </uni-col>
+
+                                <!-- 表单字段:金额、预估金额、上传凭证、优惠码 -->
+                                <uni-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
+                                    <text class="tit"><text class="iconfont icon-caret-right"></text>{{
+                                        t('Custom.Deposit.Title3')
+                                        }}</text>
+                                </uni-col>
+                                <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+                                    <uni-forms-item
+                                        :label="t('Custom.Deposit.Title3') + '(' + channelData.currency + ')'">
+                                        <uni-easyinput type="number" v-model="params.amount" @input="onAmountInput"
+                                            :placeholder="t('placeholder.input')" />
+                                        <text class="error" v-if="amountError">{{ amountError }}</text>
+                                    </uni-forms-item>
+                                </uni-col>
+                                <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="channelData.rate">
+                                    <uni-forms-item>
+                                        <template #label>
+                                            <view class="label-with-icon">
+                                                <text>{{ t('Custom.Deposit.EstimatedAmount') + '(' +
+                                                    channelData.transformCurrency + ')' }}</text>
+                                                <text class="help-icon" @click="showEstimateHelp">?</text>
+                                            </view>
+                                        </template>
+                                        <uni-easyinput v-model="params.amount1" disabled
+                                            :placeholder="t('placeholder.input')" />
+                                    </uni-forms-item>
+                                </uni-col>
+                                <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="needUploadVoucher">
+                                    <uni-forms-item :label="t('Custom.Deposit.UploadRemittanceVoucher')">
+                                        <view class="upload-box">
+                                            <button class="btn-upload" @click="chooseImage">{{ t('upload') }}</button>
+                                            <image v-if="imageUrl" :src="imageUrl" mode="aspectFit"
+                                                class="img-preview" />
+                                        </view>
+                                    </uni-forms-item>
+                                </uni-col>
+                                <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+                                    <uni-forms-item>
+                                        <template #label>
+                                            <view class="label-with-icon">
+                                                <text v-t="'Custom.Deposit.PromoCode'" />
+                                                <uni-tooltip placement="top" class="tooltip-content">
+                                                    <view class="item">?</view>
+                                                    <template #content>
+                                                        <text v-t="'news_add_field.Des.item3'"></text>
+                                                    </template>
+                                                </uni-tooltip>
+                                            </view>
+                                        </template>
+                                        <uni-easyinput v-model="params.promoCode"
+                                            :placeholder="t('placeholder.input')" />
+                                    </uni-forms-item>
+                                </uni-col>
+                            </uni-row>
+
+                            <!-- 活动勾选区域(完整保留所有原逻辑) -->
+                            <view class="activities">
+                                <!-- 10%赠金/普通活动(原代码中第一个大块) -->
+                                <view
+                                    v-if="!tableData4Flag && !tableData4TwoFlag && !tableDataNewListFlag && (country != 'CN' || (country == 'CN' && (ACCType == 1 || ACCType == 2 || ACCType == 7 || ACCType == 5 || ACCType == 6 || ACCType == 8))) && ACCType != 3">
+                                    <template v-if="isSupportedCountry && (ACCType == 2 || ACCType == 7)">
+                                        <label class="checkbox">
+                                            <checkbox :checked="params.agree2"
+                                                @click="params.agree2 = !params.agree2" />
+                                            <text>{{ t('news_add_field1.deposit.item2_1') }}</text>
+                                        </label>
+                                        <view style="line-height: 1.5; font-size: 14px" v-if="country == 'CN'">
+                                            <p style="margin-bottom: 15px" v-if="isGuoQin">
+                                                <span>{{ t('Custom.Deposit.agree21') }}</span>
+                                                <span class="clause crm-cursor">
+                                                    <a :href="`pdf/pdf4/100Bonus-en.pdf`" style="color: black">{{
+                                                        t('Custom.Deposit.agree22_2') }}</a>
+                                                </span>
+                                                <span>{{ t('Custom.Deposit.agree23_2') }}</span>
+                                            </p>
+                                            <p style="margin-bottom: 15px" v-else>
+                                                <span>{{ t('Custom.Deposit.agree21') }}</span>
+                                                <span class="clause crm-cursor">
+                                                    <a :href="`pdf/pdf4/100Bonus-en.pdf`" style="color: black">{{
+                                                        t('Custom.Deposit.agree22_2') }}</a>
+                                                </span>
+                                                <span>{{ t('Custom.Deposit.agree23_2') }}</span>
+                                            </p>
+                                        </view>
+                                        <view style="line-height: 1.5; font-size: 14px" v-if="country != 'CN'">
+                                            <p style="margin-bottom: 15px">
+                                                <span>{{ t('Custom.Deposit.agree21') }}</span>
+                                                <span class="clause crm-cursor">
+                                                    <a :href="`pdf/pdf4/100Bonus-en.pdf`" style="color: black">{{
+                                                        t('Custom.Deposit.agree22_2') }}</a>
+                                                </span>
+                                                <span>{{ t('Custom.Deposit.agree23_2') }}</span>
+                                            </p>
+                                        </view>
+                                    </template>
+                                    <template v-if="!isSupportedCountry && ACCType != 8 && !isAfterSeptember30()">
+                                        <label class="checkbox">
+                                            <checkbox :checked="params.agree2"
+                                                @click="params.agree2 = !params.agree2" />
+                                            <text>{{ t('news_add_field1.deposit.item1') }}</text>
+                                        </label>
+                                        <view style="line-height: 1.5; font-size: 14px" v-if="country == 'CN'">
+                                            <p style="margin-bottom: 15px" v-if="isGuoQin">
+                                                <span>{{ t('Custom.Deposit.agree21') }}</span>
+                                                <span class="clause crm-cursor">
+                                                    <a :href="`pdf/pdf4/${locale}.pdf`" style="color: black">{{
+                                                        t('Custom.Deposit.agree22') }}</a>
+                                                </span>
+                                                <span>{{ t('Custom.Deposit.agree23_1') }}</span>
+                                            </p>
+                                            <p style="margin-bottom: 15px" v-else>
+                                                <span>{{ t('Custom.Deposit.agree21') }}</span>
+                                                <span class="clause crm-cursor">
+                                                    <a :href="`pdf/pdf4/${locale}.pdf`" style="color: black">{{
+                                                        t('Custom.Deposit.agree22') }}</a>
+                                                </span>
+                                                <span>{{ t('Custom.Deposit.agree23') }}</span>
+                                            </p>
+                                        </view>
+                                        <view style="line-height: 1.5; font-size: 14px" v-if="country != 'CN'">
+                                            <p style="margin-bottom: 15px">
+                                                <span>{{ t('Custom.Deposit.agree21') }}</span>
+                                                <span class="clause crm-cursor">
+                                                    <a :href="`pdf/pdf4/${locale}.pdf`" style="color: black">{{
+                                                        t('Custom.Deposit.agree22') }}</a>
+                                                </span>
+                                                <span>{{ t('Custom.Deposit.agree23_1') }}</span>
+                                            </p>
+                                        </view>
+                                    </template>
+                                </view>
 
-                        <!-- 活动勾选区域(完整保留所有原逻辑) -->
-                        <view class="activities">
-                            <!-- 10%赠金/普通活动(原代码中第一个大块) -->
-                            <view
-                                v-if="!tableData4Flag && !tableData4TwoFlag && !tableDataNewListFlag && (country != 'CN' || (country == 'CN' && (ACCType == 1 || ACCType == 2 || ACCType == 7 || ACCType == 5 || ACCType == 6 || ACCType == 8))) && ACCType != 3">
-                                <template v-if="isSupportedCountry && (ACCType == 2 || ACCType == 7)">
+                                <!-- 10%赠金-年中赠金 -->
+                                <view v-if="tableData4Flag">
                                     <label class="checkbox">
-                                        <checkbox :checked="params.agree2" @click="params.agree2 = !params.agree2" />
-                                        <text>{{ t('news_add_field1.deposit.item2_1') }}</text>
+                                        <checkbox :checked="params.agree4" @click="params.agree4 = !params.agree4" />
+                                        <text>{{ t('news_add_field1.activitiesNZ.itemDeposit1') }}</text>
                                     </label>
-                                    <view style="line-height: 1.5; font-size: 14px" v-if="country == 'CN'">
-                                        <p style="margin-bottom: 15px" v-if="isGuoQin">
-                                            <span>{{ t('Custom.Deposit.agree21') }}</span>
-                                            <span class="clause crm-cursor">
-                                                <a :href="`pdf/pdf4/100Bonus-en.pdf`" style="color: black">{{
-                                                    t('Custom.Deposit.agree22_2') }}</a>
-                                            </span>
-                                            <span>{{ t('Custom.Deposit.agree23_2') }}</span>
-                                        </p>
-                                        <p style="margin-bottom: 15px" v-else>
-                                            <span>{{ t('Custom.Deposit.agree21') }}</span>
-                                            <span class="clause crm-cursor">
-                                                <a :href="`pdf/pdf4/100Bonus-en.pdf`" style="color: black">{{
-                                                    t('Custom.Deposit.agree22_2') }}</a>
-                                            </span>
-                                            <span>{{ t('Custom.Deposit.agree23_2') }}</span>
-                                        </p>
-                                    </view>
-                                    <view style="line-height: 1.5; font-size: 14px" v-if="country != 'CN'">
+                                    <view style="line-height: 1.5; font-size: 14px">
                                         <p style="margin-bottom: 15px">
-                                            <span>{{ t('Custom.Deposit.agree21') }}</span>
-                                            <span class="clause crm-cursor">
-                                                <a :href="`pdf/pdf4/100Bonus-en.pdf`" style="color: black">{{
-                                                    t('Custom.Deposit.agree22_2') }}</a>
-                                            </span>
-                                            <span>{{ t('Custom.Deposit.agree23_2') }}</span>
+                                            <span>{{ t('news_add_field1.activitiesNZ.itemDeposit2') }}</span>
+                                            <span class="clause crm-cursor" @click="dialogClauseNZ = true">{{
+                                                t('news_add_field1.activitiesNZ.itemDeposit3') }}</span>
+                                            <span>{{ t('news_add_field1.activitiesNZ.itemDeposit4') }}</span>
                                         </p>
                                     </view>
-                                </template>
-                                <template v-if="!isSupportedCountry && ACCType != 8 && !isAfterSeptember30()">
+                                </view>
+
+                                <!-- 20%赠金-年中赠金 -->
+                                <view v-if="tableData4TwoFlag">
                                     <label class="checkbox">
-                                        <checkbox :checked="params.agree2" @click="params.agree2 = !params.agree2" />
-                                        <text>{{ t('news_add_field1.deposit.item1') }}</text>
+                                        <checkbox :checked="params.agree5" @click="params.agree5 = !params.agree5" />
+                                        <text>{{ t('news_add_field1.activitiesNZTwo.itemDeposit1') }}</text>
                                     </label>
-                                    <view style="line-height: 1.5; font-size: 14px" v-if="country == 'CN'">
-                                        <p style="margin-bottom: 15px" v-if="isGuoQin">
-                                            <span>{{ t('Custom.Deposit.agree21') }}</span>
-                                            <span class="clause crm-cursor">
-                                                <a :href="`pdf/pdf4/${locale}.pdf`" style="color: black">{{
-                                                    t('Custom.Deposit.agree22') }}</a>
-                                            </span>
-                                            <span>{{ t('Custom.Deposit.agree23_1') }}</span>
-                                        </p>
-                                        <p style="margin-bottom: 15px" v-else>
-                                            <span>{{ t('Custom.Deposit.agree21') }}</span>
-                                            <span class="clause crm-cursor">
-                                                <a :href="`pdf/pdf4/${locale}.pdf`" style="color: black">{{
-                                                    t('Custom.Deposit.agree22') }}</a>
-                                            </span>
-                                            <span>{{ t('Custom.Deposit.agree23') }}</span>
-                                        </p>
-                                    </view>
-                                    <view style="line-height: 1.5; font-size: 14px" v-if="country != 'CN'">
+                                    <view style="line-height: 1.5; font-size: 14px">
                                         <p style="margin-bottom: 15px">
-                                            <span>{{ t('Custom.Deposit.agree21') }}</span>
-                                            <span class="clause crm-cursor">
-                                                <a :href="`pdf/pdf4/${locale}.pdf`" style="color: black">{{
-                                                    t('Custom.Deposit.agree22') }}</a>
-                                            </span>
-                                            <span>{{ t('Custom.Deposit.agree23_1') }}</span>
+                                            <span>{{ t('news_add_field1.activitiesNZTwo.itemDeposit2') }}</span>
+                                            <span class="clause crm-cursor" @click="dialogClauseNZTwo = true">{{
+                                                t('news_add_field1.activitiesNZTwo.itemDeposit3') }}</span>
+                                            <span>{{ t('news_add_field1.activitiesNZTwo.itemDeposit4') }}</span>
                                         </p>
                                     </view>
-                                </template>
-                            </view>
-
-                            <!-- 10%赠金-年中赠金 -->
-                            <view v-if="tableData4Flag">
-                                <label class="checkbox">
-                                    <checkbox :checked="params.agree4" @click="params.agree4 = !params.agree4" />
-                                    <text>{{ t('news_add_field1.activitiesNZ.itemDeposit1') }}</text>
-                                </label>
-                                <view style="line-height: 1.5; font-size: 14px">
-                                    <p style="margin-bottom: 15px">
-                                        <span>{{ t('news_add_field1.activitiesNZ.itemDeposit2') }}</span>
-                                        <span class="clause crm-cursor" @click="dialogClauseNZ = true">{{
-                                            t('news_add_field1.activitiesNZ.itemDeposit3') }}</span>
-                                        <span>{{ t('news_add_field1.activitiesNZ.itemDeposit4') }}</span>
-                                    </p>
                                 </view>
-                            </view>
 
-                            <!-- 20%赠金-年中赠金 -->
-                            <view v-if="tableData4TwoFlag">
-                                <label class="checkbox">
-                                    <checkbox :checked="params.agree5" @click="params.agree5 = !params.agree5" />
-                                    <text>{{ t('news_add_field1.activitiesNZTwo.itemDeposit1') }}</text>
-                                </label>
-                                <view style="line-height: 1.5; font-size: 14px">
-                                    <p style="margin-bottom: 15px">
-                                        <span>{{ t('news_add_field1.activitiesNZTwo.itemDeposit2') }}</span>
-                                        <span class="clause crm-cursor" @click="dialogClauseNZTwo = true">{{
-                                            t('news_add_field1.activitiesNZTwo.itemDeposit3') }}</span>
-                                        <span>{{ t('news_add_field1.activitiesNZTwo.itemDeposit4') }}</span>
-                                    </p>
-                                </view>
-                            </view>
-
-                            <!-- 赠送活动 -->
-                            <view v-if="tableDataNewListFlag">
-                                <label class="checkbox">
-                                    <checkbox :checked="params.agree6" @click="params.agree6 = !params.agree6" />
-                                    <text>{{ tableDataNewList.title }}</text>
-                                </label>
-                                <view style="line-height: 1.5; font-size: 14px">
-                                    <p style="margin-bottom: 15px">
-                                        <span>{{ t('news_add_field1.activitiesNewList.item1') }}</span>
-                                        <span class="clause crm-cursor" @click="dialogClauseNewList = true">{{
-                                            tableDataNewList.title }}</span>
-                                        <span>{{ t('news_add_field1.activitiesNewList.item2') }}</span>
-                                    </p>
+                                <!-- 赠送活动 -->
+                                <view v-if="tableDataNewListFlag">
+                                    <label class="checkbox">
+                                        <checkbox :checked="params.agree6" @click="params.agree6 = !params.agree6" />
+                                        <text>{{ tableDataNewList.title }}</text>
+                                    </label>
+                                    <view style="line-height: 1.5; font-size: 14px">
+                                        <p style="margin-bottom: 15px">
+                                            <span>{{ t('news_add_field1.activitiesNewList.item1') }}</span>
+                                            <span class="clause crm-cursor" @click="dialogClauseNewList = true">{{
+                                                tableDataNewList.title }}</span>
+                                            <span>{{ t('news_add_field1.activitiesNewList.item2') }}</span>
+                                        </p>
+                                    </view>
                                 </view>
-                            </view>
 
-                            <!-- 20%赠金申请 -->
-                            <view
-                                v-if="(ACCType == 1 || ACCType == 2 || ACCType == 5 || ACCType == 6 || ACCType == 7) && anshiClose">
-                                <label class="checkbox">
-                                    <checkbox :checked="params.agree3" @click="params.agree3 = !params.agree3"
-                                        :disabled="CheckExistSuccess" />
-                                    <text>{{ t('news_add_field1.deposit.item3') }}</text>
-                                </label>
-                                <view style="line-height: 1.5; font-size: 14px">
-                                    <p style="margin-bottom: 15px">
-                                        <span>{{ t('news_add_field1.deposit.item4') }}</span>
-                                        <span class="clause crm-cursor" @click="dialogClause1 = true">{{
-                                            t('news_add_field1.deposit.item5')
-                                            }}</span>
-                                        <span>{{ t('news_add_field1.deposit.item6') }}</span>
-                                    </p>
+                                <!-- 20%赠金申请 -->
+                                <view
+                                    v-if="(ACCType == 1 || ACCType == 2 || ACCType == 5 || ACCType == 6 || ACCType == 7) && anshiClose">
+                                    <label class="checkbox">
+                                        <checkbox :checked="params.agree3" @click="params.agree3 = !params.agree3"
+                                            :disabled="CheckExistSuccess" />
+                                        <text>{{ t('news_add_field1.deposit.item3') }}</text>
+                                    </label>
+                                    <view style="line-height: 1.5; font-size: 14px">
+                                        <p style="margin-bottom: 15px">
+                                            <span>{{ t('news_add_field1.deposit.item4') }}</span>
+                                            <span class="clause crm-cursor" @click="dialogClause1 = true">{{
+                                                t('news_add_field1.deposit.item5')
+                                                }}</span>
+                                            <span>{{ t('news_add_field1.deposit.item6') }}</span>
+                                        </p>
+                                    </view>
                                 </view>
                             </view>
-                        </view>
 
-                        <button class="s-btn" type="primary" @click="submitConfirm">{{ t('Btn.Submit') }}</button>
-                    </form>
+                            <button class="s-btn" type="primary" @click="submitConfirm">{{ t('Btn.Submit') }}</button>
+                        </uni-forms>
+                    </view>
                 </view>
             </view>
-        </view>
 
-        <!-- 弹窗组件(使用 uni-popup) -->
-        <uni-popup ref="popup" type="center" :mask-click="false">
-            <view class="popup-content" v-if="popupType === 'confirm'">
-                <text class="popup-title">{{ t('Home.page_customer.item2') }}</text>
-                <view class="popup-form">
-                    <view class="popup-row"><text class="label">{{ t('Custom.Deposit.Title1') }}:</text><text>{{
-                        selectedAccountLabel }}</text></view>
-                    <view class="popup-row"><text class="label">{{ t('Custom.Deposit.Title2') }}:</text><text>{{
-                        locale ==
-                            'cn' ? channelData.name : channelData.enName }}</text></view>
-                    <view class="popup-row" v-if="code"><text class="label">{{ t('news_add_field.Label.Title4')
-                            }}:</text><text>{{ selectCodes }}</text></view>
-                    <view class="popup-row"><text class="label">{{ t('Custom.Deposit.Title3') }}:</text><text>{{
-                        params.amount
-                            }}({{ channelData.currency }})</text></view>
-                    <view class="popup-row" v-if="channelData.confirmName"><text class="label">{{ t('Label.Name')
-                            }}:</text><text>{{ userName }}</text></view>
-                    <view class="popup-row" v-if="channelData.confirmAreaCode">
-                        <text class="label">{{ t('placeholder.phone') }}:</text>
-                        <input class="small-input" v-model="dialogConfirmForm.confirmAreaCode" />
-                        <text>-</text>
-                        <input class="small-input" v-model="dialogConfirmForm.confirmPhone" />
+            <!-- 弹窗组件(使用 uni-popup) -->
+            <uni-popup ref="popupRef" type="center" :mask-click="false">
+                <view class="popup-content" v-if="popupType === 'confirm'">
+                    <text class="popup-title">{{ t('Home.page_customer.item2') }}</text>
+                    <view class="popup-form">
+                        <view class="popup-row"><text class="label">{{ t('Custom.Deposit.Title1') }}:</text><text>{{
+                            selectedAccountLabel }}</text></view>
+                        <view class="popup-row"><text class="label">{{ t('Custom.Deposit.Title2') }}:</text><text>{{
+                            locale ==
+                                'cn' ? channelData.name : channelData.enName }}</text></view>
+                        <view class="popup-row" v-if="code"><text class="label">{{ t('news_add_field.Label.Title4')
+                                }}:</text><text>{{ selectCodes }}</text></view>
+                        <view class="popup-row"><text class="label">{{ t('Custom.Deposit.Title3') }}:</text><text>{{
+                            params.amount
+                                }}({{ channelData.currency }})</text></view>
+                        <view class="popup-row" v-if="channelData.confirmName"><text class="label">{{ t('Label.Name')
+                                }}:</text><text>{{ userName }}</text></view>
+                        <view class="popup-row" v-if="channelData.confirmAreaCode">
+                            <text class="label">{{ t('placeholder.phone') }}:</text>
+                            <input class="small-input" v-model="dialogConfirmForm.confirmAreaCode" />
+                            <text>-</text>
+                            <input class="small-input" v-model="dialogConfirmForm.confirmPhone" />
+                        </view>
+                    </view>
+                    <view class="popup-buttons">
+                        <button @click="closePopup">{{ t('Btn.Cancel') }}</button>
+                        <button type="primary" @click="submitDeposit">{{ t('Btn.Confirm') }}</button>
                     </view>
                 </view>
-                <view class="popup-buttons">
-                    <button @click="closePopup">{{ t('Btn.Cancel') }}</button>
-                    <button type="primary" @click="submitDeposit">{{ t('Btn.Confirm') }}</button>
+                <view class="popup-content" v-else-if="popupType === 'result'">
+                    <view class="result-icon" v-if="dialogSuccess"><text class="iconfont iconchenggong"></text></view>
+                    <view class="result-icon" v-else><text class="iconfont iconjingshi"></text></view>
+                    <text class="popup-text">{{ dialogMessage }}</text>
+                    <view class="popup-buttons">
+                        <button type="primary" @click="closeResultPopup">{{ t('Btn.Confirm') }}</button>
+                        <button v-if="!dialogSuccess" @click="closeResultPopup">{{ t('Btn.Cancel') }}</button>
+                    </view>
                 </view>
-            </view>
-            <view class="popup-content" v-else-if="popupType === 'result'">
-                <view class="result-icon" v-if="dialogSuccess"><text class="iconfont iconchenggong"></text></view>
-                <view class="result-icon" v-else><text class="iconfont iconjingshi"></text></view>
-                <text class="popup-text">{{ dialogMessage }}</text>
-                <view class="popup-buttons">
-                    <button type="primary" @click="closeResultPopup">{{ t('Btn.Confirm') }}</button>
-                    <button v-if="!dialogSuccess" @click="closeResultPopup">{{ t('Btn.Cancel') }}</button>
+                <view class="popup-content" v-else-if="popupType === 'wait'">
+                    <text class="iconfont icondengdai"></text>
+                    <text class="popup-text">{{ t('ApplicationDialog.Des38') }}</text>
                 </view>
-            </view>
-            <view class="popup-content" v-else-if="popupType === 'wait'">
-                <text class="iconfont icondengdai"></text>
-                <text class="popup-text">{{ t('ApplicationDialog.Des38') }}</text>
-            </view>
-        </uni-popup>
-
-        <!-- 其他弹窗(越南提示、年中赠金协议等)用 uni-popup 或 uni.showModal 模拟,因原结构复杂,保留基础 -->
-        <!-- 越南用户提示弹窗 -->
-        <uni-popup ref="vietnamPopup" type="center">
-            <view class="popup-content" style="width: 600rpx;">
-                <text class="popup-title">{{ t('Home.page_customer.item2') }}</text>
-                <view class="popup-text" style="text-align: left; font-size: 24rpx; line-height: 1.6;">
-                    <p><strong>Quý khách hàng thân mến:</strong></p>
-                    <p>Trước khi giao dịch, chúng tôi xin nhắc nhở bạn rằng:</p>
-                    <p>1. Vì có những rủi ro nhất định trong giao dịch, bạn nên đầu tư thích hợp theo kinh nghiệm giao
-                        dịch và
-                        thu nhập liên quan của mình, thay vì sử dụng tiền vay từ người khác.</p>
-                    <p>2. Dựa trên sự điều chỉnh đối với hệ thống kiểm soát rủi ro của ngân hàng, kênh nạp tiền có thể
-                        không
-                        được hỗ trợ hoặc hạn mức giao dịch có thể không chính xác khi bạn sẵn sàng nạp tiền (đặc biệt là
-                        vào ban
-                        đêm tại địa phương của bạn), vì vậy bạn nên sắp xếp vị thế giao dịch của mình và khoảng thời
-                        gian nạp
-                        tiền sao cho hợp lý để tránh những tổn thất không đáng có do bất kỳ sự chậm trễ nào trong việc
-                        nhận tiền
-                        nạp.</p>
-                    <p>Không bao giờ tiết lộ thông tin cá nhân nhạy cảm cho người gọi đến. CWG sẽ không bao giờ yêu cầu
-                        bất kỳ
-                        thông tin cá nhân nhạy cảm nào từ bạn qua điện thoại hoặc email cũng như không cung cấp bất kỳ
-                        lời
-                        khuyên đầu tư nào.</p>
-                    <p>Trong trường hợp có bất kỳ vấn đề gì với khoản tiền nạp của bạn, vui lòng liên hệ với trung tâm
-                        dịch vụ
-                        khách hàng chính thức của chúng tôi bất kỳ lúc nào.</p>
-                    <p>Trân trọng,</p>
-                </view>
-                <view class="popup-buttons">
-                    <button type="primary" @click="closeVietnamPopup">{{ t('Btn.Confirm') }}</button>
+            </uni-popup>
+
+            <!-- 其他弹窗(越南提示、年中赠金协议等)用 uni-popup 或 uni.showModal 模拟,因原结构复杂,保留基础 -->
+            <!-- 越南用户提示弹窗 -->
+            <uni-popup ref="vietnamPopup" type="center">
+                <view class="popup-content" style="width: 600rpx;">
+                    <text class="popup-title">{{ t('Home.page_customer.item2') }}</text>
+                    <view class="popup-text" style="text-align: left; font-size: 24rpx; line-height: 1.6;">
+                        <p><strong>Quý khách hàng thân mến:</strong></p>
+                        <p>Trước khi giao dịch, chúng tôi xin nhắc nhở bạn rằng:</p>
+                        <p>1. Vì có những rủi ro nhất định trong giao dịch, bạn nên đầu tư thích hợp theo kinh nghiệm
+                            giao
+                            dịch và
+                            thu nhập liên quan của mình, thay vì sử dụng tiền vay từ người khác.</p>
+                        <p>2. Dựa trên sự điều chỉnh đối với hệ thống kiểm soát rủi ro của ngân hàng, kênh nạp tiền có
+                            thể
+                            không
+                            được hỗ trợ hoặc hạn mức giao dịch có thể không chính xác khi bạn sẵn sàng nạp tiền (đặc
+                            biệt là
+                            vào ban
+                            đêm tại địa phương của bạn), vì vậy bạn nên sắp xếp vị thế giao dịch của mình và khoảng thời
+                            gian nạp
+                            tiền sao cho hợp lý để tránh những tổn thất không đáng có do bất kỳ sự chậm trễ nào trong
+                            việc
+                            nhận tiền
+                            nạp.</p>
+                        <p>Không bao giờ tiết lộ thông tin cá nhân nhạy cảm cho người gọi đến. CWG sẽ không bao giờ yêu
+                            cầu
+                            bất kỳ
+                            thông tin cá nhân nhạy cảm nào từ bạn qua điện thoại hoặc email cũng như không cung cấp bất
+                            kỳ
+                            lời
+                            khuyên đầu tư nào.</p>
+                        <p>Trong trường hợp có bất kỳ vấn đề gì với khoản tiền nạp của bạn, vui lòng liên hệ với trung
+                            tâm
+                            dịch vụ
+                            khách hàng chính thức của chúng tôi bất kỳ lúc nào.</p>
+                        <p>Trân trọng,</p>
+                    </view>
+                    <view class="popup-buttons">
+                        <button type="primary" @click="closeVietnamPopup">{{ t('Btn.Confirm') }}</button>
+                    </view>
                 </view>
-            </view>
-        </uni-popup>
-
-        <!-- 中国网银提示弹窗 -->
-        <uni-popup ref="chinaUnionPayPopup" type="center">
-            <view class="popup-content">
-                <text class="popup-text">{{ t('news_add_field1.deposit.item64') }}</text>
-                <view class="popup-buttons">
-                    <button type="primary" @click="closeChinaUnionPayPopup">{{ t('Btn.Confirm') }}</button>
-                    <button @click="closeChinaUnionPayPopup">{{ t('Btn.Cancel') }}</button>
+            </uni-popup>
+
+            <!-- 中国网银提示弹窗 -->
+            <uni-popup ref="chinaUnionPayPopup" type="center">
+                <view class="popup-content">
+                    <text class="popup-text">{{ t('news_add_field1.deposit.item64') }}</text>
+                    <view class="popup-buttons">
+                        <button type="primary" @click="closeChinaUnionPayPopup">{{ t('Btn.Confirm') }}</button>
+                        <button @click="closeChinaUnionPayPopup">{{ t('Btn.Cancel') }}</button>
+                    </view>
                 </view>
-            </view>
-        </uni-popup>
-
-        <!-- 不参加活动弹窗 -->
-        <uni-popup ref="dontActivePopup" type="center">
-            <view class="popup-content">
-                <text class="popup-text">{{ t('Custom.Withdraw.item9') }}</text>
-                <view class="popup-buttons">
-                    <button type="primary" @click="confirmDontActive">{{ t('Btn.Confirm') }}</button>
-                    <button @click="closeDontActivePopup">{{ t('Btn.Cancel') }}</button>
+            </uni-popup>
+
+            <!-- 不参加活动弹窗 -->
+            <uni-popup ref="dontActivePopupRef" type="center">
+                <view class="popup-content">
+                    <text class="popup-text">{{ t('Custom.Withdraw.item9') }}</text>
+                    <view class="popup-buttons">
+                        <button type="primary" @click="confirmDontActive">{{ t('Btn.Confirm') }}</button>
+                        <button @click="closeDontActivePopup">{{ t('Btn.Cancel') }}</button>
+                    </view>
                 </view>
-            </view>
-        </uni-popup>
-
-        <!-- 20%赠金协议 -->
-        <uni-popup ref="clausePopup" type="center">
-            <view class="popup-content" style="width: 700rpx;">
-                <text class="popup-title">{{ locale === 'cn' ? 'CWG 20%赠金入会礼' : '20% CASH BACK BONUS' }}</text>
-                <scroll-view scroll-y style="height: 400rpx;">
-                    <rich-text :nodes="clauseContent" class="popup-text"></rich-text>
-                </scroll-view>
-                <view class="popup-buttons">
-                    <button @click="closeClausePopup">{{ t('Btn.Cancel') }}</button>
-                    <button type="primary" @click="closeClausePopup">{{ t('Btn.Confirm') }}</button>
+            </uni-popup>
+
+            <!-- 20%赠金协议 -->
+            <uni-popup ref="clausePopup" type="center">
+                <view class="popup-content" style="width: 700rpx;">
+                    <text class="popup-title">{{ locale === 'cn' ? 'CWG 20%赠金入会礼' : '20% CASH BACK BONUS' }}</text>
+                    <scroll-view scroll-y style="height: 400rpx;">
+                        <rich-text :nodes="clauseContent" class="popup-text"></rich-text>
+                    </scroll-view>
+                    <view class="popup-buttons">
+                        <button @click="closeClausePopup">{{ t('Btn.Cancel') }}</button>
+                        <button type="primary" @click="closeClausePopup">{{ t('Btn.Confirm') }}</button>
+                    </view>
                 </view>
-            </view>
-        </uni-popup>
+            </uni-popup>
+
+            <!-- 抽屉组件 -->
+            <drawer :dialogInfoTradingAdd="dialogInfoTradingAdd" :addType="openType" @closeAdd="closeAdd"
+                @confirmToReload="confirmToReload" />
+            <view class="crm_verified_info_mask" v-if="dialogInfoTradingAdd" @click="closeDiaAdd"></view>
+        </view>
+    </cwg-page-wrapper>
 
-        <!-- 抽屉组件 -->
-        <drawer :dialogInfoTradingAdd="dialogInfoTradingAdd" :addType="openType" @closeAdd="closeAdd"
-            @confirmToReload="confirmToReload" />
-        <view class="crm_verified_info_mask" v-if="dialogInfoTradingAdd" @click="closeDiaAdd"></view>
-    </view>
 </template>
 
 <script setup>
@@ -553,6 +610,27 @@ const amountError = ref('')
 const selectedCreditIndex = ref(-1)
 const selectedCreditLabel = ref('')
 
+const loginComboxOptions = computed(() => {
+    return loginOptions.value.map((item) => ({
+        text: item.label,
+        value: item.login
+    }))
+})
+
+const creditCardOptions = computed(() => {
+    return ruleForm.bankCredit.map((item, index) => ({
+        text: `${item.bankUname}-${item.bankCardNum}`,
+        value: item.id
+    }))
+})
+
+const bankOptions = computed(() => {
+    return bankDate.value.map((item, index) => ({
+        text: (locale.value === 'cn' || locale.value === 'zhHant') ? item.name : item.enName,
+        value: index
+    }))
+})
+
 // 计算属性
 const country = computed(() => userInfo.value?.customInfo?.country || '')
 const userName = computed(() => {
@@ -806,11 +884,10 @@ const is20Open = () => {
 }
 
 // 事件处理
-const onAccountChange = (e) => {
-    const idx = e.detail.value
-    const item = loginOptions.value[idx]
+const onAccountChange = (val) => {
+    const item = loginOptions.value.find(opt => opt.login === val)
     if (item) {
-        selectedAccountIndex.value = idx
+        selectedAccountIndex.value = loginOptions.value.indexOf(item)
         selectedAccountLabel.value = item.label
         loginValue.value = item.login
         step2.value = true
@@ -902,8 +979,7 @@ const isShowStep3 = (row) => {
         doShowStep3(row)
     }
 }
-const onBankChange = (e) => {
-    const idx = e.detail.value
+const onBankChange = (idx) => {
     const item = bankDate.value[idx]
     if (item) {
         selectedBankIndex.value = idx
@@ -916,17 +992,17 @@ const onBankChange = (e) => {
         channelData.value.transformCurrency = item.currency || channelData.value.transformCurrency
     }
 }
-const onCreditCardChange = (e) => {
-    const idx = e.detail.value
-    const item = ruleForm.bankCredit[idx]
+const onCreditCardChange = (val) => {
+    const item = ruleForm.bankCredit.find(i => i.id === val)
     if (item) {
-        selectedCreditIndex.value = idx
+        selectedCreditIndex.value = ruleForm.bankCredit.indexOf(item)
         selectedCreditLabel.value = `${item.bankUname}-${item.bankCardNum}`
         myId.value = item.id
         // 填充表单(原 chooseBank 逻辑)
     }
 }
 const onAmountInput = (e) => {
+    console.log(e, e.detail.value);
     const val = e.detail.value
     params.amount = val
     if (val && channelData.value.rate) {
@@ -1024,6 +1100,7 @@ const closeDiaAdd = () => { dialogInfoTradingAdd.value = false }
 
 // 提交确认逻辑
 const submitConfirm = () => {
+    console.log(params,121212);
     // 原 openDontActive 逻辑,先判断活动冲突,然后打开确认弹窗
     if (!tableData4Flag.value && !tableData4TwoFlag.value && !tableDataNewListFlag.value &&
         (country.value != 'CN' || (country.value == 'CN' && (ACCType.value == 1 || ACCType.value == 2 || ACCType.value == 7))) &&
@@ -1390,287 +1467,457 @@ onLoad(() => {
 </script>
 
 <style lang="scss" scoped>
-// 样式保持与之前转换一致,此处只列出关键类
+@import "@/uni.scss";
+
 .custom-deposit {
-    padding: 30rpx;
-    background: #f5f7fa;
+    min-height: 100vh;
 
     .crm-title-box {
-        margin-bottom: 30rpx;
+        margin-bottom: px2rpx(20);
 
         .tit {
-            font-size: 36rpx;
-            font-weight: bold;
+            font-size: px2rpx(20);
+            font-weight: 700;
+            color: var(--color-navy-900);
         }
     }
 
     .box {
-        margin-bottom: 30rpx;
+        margin-bottom: px2rpx(20);
 
         .b-card {
             background: #fff;
-            border-radius: 16rpx;
-            padding: 30rpx;
+            border-radius: px2rpx(12);
+            padding: px2rpx(20);
+            box-shadow: 0 px2rpx(4) px2rpx(12) rgba(0, 0, 0, 0.03);
 
             .card-top {
                 .tit {
-                    font-size: 32rpx;
-                    font-weight: 500;
-                    margin-bottom: 20rpx;
+                    font-size: px2rpx(16);
+                    font-weight: 600;
+                    margin-bottom: px2rpx(16);
                     display: flex;
                     align-items: center;
-
-                    .iconfont {
-                        margin-right: 10rpx;
+                    color: var(--color-navy-900);
+
+                    position: relative;
+                    padding-left: 20px;
+
+                    &:after {
+                        content: '';
+                        position: absolute;
+                        left: 0;
+                        top: 50%;
+                        transform: translateY(-50%);
+                        width: 0;
+                        height: 0;
+                        border-top: 6px solid transparent;
+                        border-bottom: 6px solid transparent;
+                        border-left: 8px solid currentColor;
                     }
                 }
             }
-        }
-    }
 
-    .picker-view {
-        background: #f5f7fa;
-        padding: 20rpx;
-        border-radius: 8rpx;
-        margin: 20rpx 0;
+            .channelType {
+                font-size: px2rpx(15);
+                font-weight: 600;
+                margin: px2rpx(24) 0 px2rpx(12);
+                color: var(--color-navy-700);
+                padding-left: px2rpx(8);
+                border-left: px2rpx(4) solid var(--color-primary);
+            }
+        }
     }
 
-    .payment-list {
+    .reselect-btn {
+        margin-top: px2rpx(20);
         display: flex;
-        flex-wrap: wrap;
-        gap: 2%;
+        justify-content: flex-end;
 
-        .payment-card {
-            width: 47%;
-            background: #fff;
-            border-radius: 12rpx;
-            margin-bottom: 24rpx;
-            padding: 24rpx;
-            box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
-
-            .icon-wrapper {
-                width: 96rpx;
-                height: 96rpx;
-                margin-right: 24rpx;
-                background: #f0f2f5;
-                border-radius: 48rpx;
-                display: flex;
-                align-items: center;
-                justify-content: center;
-
-                .icon {
-                    width: 64rpx;
-                    height: 64rpx;
-                }
+        .reselect {
+            background-color: var(--color-zinc-100);
+            color: var(--color-navy-700);
+            border: none;
+            font-size: px2rpx(14);
+            padding: px2rpx(8) px2rpx(20);
+            border-radius: px2rpx(8);
+
+            &:active {
+                background-color: var(--color-zinc-200);
             }
+        }
+    }
 
-            .content {
-                flex: 1;
-
-                .header {
-                    display: flex;
-                    justify-content: space-between;
-                    margin-bottom: 16rpx;
-
-                    .title {
-                        font-size: 32rpx;
-                        font-weight: 600;
-                    }
-                }
-
-                .info-list {
-                    .info-item {
-                        display: flex;
-                        justify-content: space-between;
-                        margin-bottom: 12rpx;
-                        font-size: 26rpx;
-                    }
-                }
-
-                .s-btn {
-                    background: #007aff;
-                    color: #fff;
-                    border: none;
-                    padding: 10rpx 20rpx;
-                    border-radius: 8rpx;
-                    margin-top: 16rpx;
+    .s-btn[type="primary"] {
+        width: 100%;
+        height: px2rpx(48);
+        background: var(--color-navy-900);
+        color: #fff;
+        border-radius: px2rpx(12);
+        font-size: px2rpx(16);
+        font-weight: 600;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        border: none;
+        margin-top: px2rpx(30);
+        transition: all 0.2s;
 
-                    &.active {
-                        background: #4caf50;
-                    }
-                }
-            }
+        &:active {
+            transform: scale(0.98);
+            background: var(--color-navy-800);
         }
     }
 
     .add-back {
         display: flex;
         justify-content: space-between;
-        margin: 20rpx 0;
+        align-items: center;
+        margin-bottom: px2rpx(12);
+        padding: px2rpx(12) px2rpx(16);
+        background: var(--color-zinc-100);
+        border-radius: px2rpx(8);
+
+        text {
+            font-size: px2rpx(14);
+            color: var(--color-navy-700);
+            font-weight: 500;
+        }
 
         .add-btn {
-            color: #007aff;
+            color: var(--color-primary);
+            font-weight: 600;
             text-decoration: underline;
-        }
-    }
 
-    .form-row {
-        display: flex;
-        flex-wrap: wrap;
-
-        .form-item {
-            flex: 1;
-            margin: 20rpx;
-
-            .label {
-                font-size: 28rpx;
-                color: #666;
-            }
-
-            .input {
-                background: #f5f7fa;
-                padding: 20rpx;
-                border-radius: 8rpx;
-                margin-top: 10rpx;
-            }
-
-            .error {
-                color: #f56c6c;
-                font-size: 24rpx;
+            &:active {
+                opacity: 0.7;
             }
         }
     }
 
     .wire-transfer-account {
-        background: #fafafa;
-        padding: 20rpx;
-        border-radius: 8rpx;
-        margin: 20rpx 0;
+        background: var(--color-zinc-50);
+        padding: px2rpx(16);
+        border-radius: px2rpx(12);
+        margin: px2rpx(16) 0;
 
         .row {
             display: flex;
-            margin-bottom: 15rpx;
+            margin-bottom: px2rpx(12);
+            font-size: px2rpx(14);
+
+            &:last-child {
+                margin-bottom: 0;
+            }
 
             .label {
-                width: 200rpx;
+                width: px2rpx(120);
+                color: var(--color-zinc-500);
             }
 
             .content {
                 flex: 1;
+                color: var(--color-navy-900);
+                font-weight: 500;
             }
 
             .SpecialColor {
-                color: #f56c6c;
+                color: var(--color-error);
             }
         }
     }
 
     .activities {
-        margin: 30rpx 0;
+        margin: px2rpx(24) 0;
 
         .checkbox {
             display: flex;
-            align-items: center;
-            margin-bottom: 20rpx;
+            align-items: flex-start;
+            gap: px2rpx(8);
+            margin-bottom: px2rpx(12);
+
+            :deep(uni-checkbox .uni-checkbox-input) {
+                border-radius: px2rpx(4);
+                width: px2rpx(18);
+                height: px2rpx(18);
+            }
 
-            checkbox {
-                margin-right: 20rpx;
+            text {
+                font-size: px2rpx(14);
+                color: var(--color-navy-700);
+                font-weight: 500;
+                line-height: 1.5;
             }
         }
-    }
 
-    .s-btn {
-        background: #007aff;
-        color: #fff;
-        border: none;
-        padding: 20rpx;
-        border-radius: 8rpx;
-        width: 100%;
-        font-size: 32rpx;
-        margin-top: 30rpx;
-    }
-
-    .reselect-btn {
-        margin-top: 30rpx;
+        .clause-text {
+            font-size: px2rpx(13);
+            color: var(--color-zinc-500);
+            line-height: 1.6;
+            padding-left: px2rpx(26);
 
-        .reselect {
-            background: #f0f0f0;
-            color: #333;
+            .clause {
+                color: var(--color-primary);
+                text-decoration: underline;
+            }
         }
     }
 
     .step3-attention {
+        background: var(--color-error-50, #fff1f0);
+        border-radius: px2rpx(12);
+        padding: px2rpx(16);
+        margin-bottom: px2rpx(20);
+
         .attention {
-            margin: 20rpx 0;
+            font-size: px2rpx(14);
+            color: var(--color-error-600, #cf1322);
             line-height: 1.6;
         }
 
         .btn-bottom {
-            text-align: center;
+            margin-top: px2rpx(20);
+            display: flex;
+            justify-content: center;
 
             .btn {
-                display: inline-block;
-                background: #007aff;
+                background: var(--color-error-600, #cf1322);
                 color: #fff;
-                padding: 20rpx 60rpx;
-                border-radius: 40rpx;
+                padding: px2rpx(10) px2rpx(48);
+                border-radius: px2rpx(24);
+                font-size: px2rpx(15);
+                font-weight: 700;
+                box-shadow: 0 px2rpx(4) px2rpx(10) rgba(207, 19, 34, 0.2);
+                transition: all 0.2s;
+
+                &:active {
+                    transform: scale(0.96);
+                    opacity: 0.8;
+                }
             }
         }
     }
-}
 
-.popup-content {
-    background: #fff;
-    border-radius: 16rpx;
-    padding: 40rpx;
-    width: 600rpx;
-    text-align: center;
-
-    .popup-title {
-        font-size: 36rpx;
-        font-weight: bold;
-        margin-bottom: 30rpx;
-        display: block;
-    }
+    .upload-box {
+        display: flex;
+        align-items: center;
+        gap: px2rpx(12);
+
+        .btn-upload {
+            background: var(--color-zinc-100);
+            border: px2rpx(1) dashed var(--color-zinc-300);
+            border-radius: px2rpx(8);
+            height: px2rpx(44);
+            font-size: px2rpx(14);
+            color: var(--color-zinc-600);
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            padding: 0 px2rpx(20);
+        }
 
-    .popup-text {
-        font-size: 28rpx;
-        line-height: 1.6;
-        margin: 20rpx 0;
+        .img-preview {
+            width: px2rpx(44);
+            height: px2rpx(44);
+            border-radius: px2rpx(4);
+            object-fit: cover;
+        }
     }
 
-    .popup-form {
+    .label-with-icon {
+        font-size: px2rpx(14);
+        color: #606266;
+        box-sizing: border-box;
+        display: flex;
+        align-items: center;
+        padding: 0 0 8px;
+        height: px2rpx(36);
+        line-height: 1.5715;
         text-align: left;
-        margin: 30rpx 0;
+        /* #ifndef APP-NVUE */
+        white-space: initial;
+        /* #endif */
+
+        .help-icon {
+            margin-left: px2rpx(8);
+            width: px2rpx(16);
+            height: px2rpx(16);
+            background: var(--color-zinc-200);
+            border-radius: 50%;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            font-size: px2rpx(12);
+            color: var(--color-zinc-600);
+            cursor: pointer;
+        }
+    }
+
+    .tooltip-content {
+        :deep(.uni-tooltip-popup) {
+            background-color: #fff !important;
+            box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1) !important;
+            width: px2rpx(300) !important;
+            color: var(--color-zinc-500);
+            line-height: 1.6;
+        }
+    }
 
-        .popup-row {
-            margin-bottom: 20rpx;
+    .error {
+        color: var(--color-error);
+        font-size: px2rpx(12);
+        margin-top: px2rpx(4);
+        display: block;
+    }
 
-            .label {
-                font-weight: bold;
+    :deep(.base-info-form) {
+        .uni-row1 {
+            .uni-col {
+                padding: 0 px2rpx(10) !important;
+            }
+
+            .uni-forms-item {
+                min-height: px2rpx(79);
+                margin-bottom: px2rpx(10);
+                position: relative;
+            }
+
+            .uni-select,
+            .uni-combox,
+            .uni-easyinput__content,
+            .uni-date-editor--x {
+                border: none !important;
+                background-color: var(--color-zinc-100) !important;
+                border-radius: px2rpx(8) !important;
             }
 
-            .small-input {
-                width: 120rpx;
-                display: inline-block;
+            .uni-easyinput__content-input {
+                height: px2rpx(44) !important;
             }
         }
     }
 
-    .popup-buttons {
-        display: flex;
-        justify-content: space-around;
-        margin-top: 30rpx;
+    .popup-content {
+        background: #fff;
+        border-radius: px2rpx(20);
+        padding: px2rpx(24);
+        width: px2rpx(320);
+        text-align: center;
+
+        .popup-title {
+            font-size: px2rpx(18);
+            font-weight: 700;
+            margin-bottom: px2rpx(20);
+            color: var(--color-navy-900);
+            display: block;
+        }
+
+        .popup-text {
+            font-size: px2rpx(14);
+            line-height: 1.6;
+            color: var(--color-zinc-600);
+            margin-bottom: px2rpx(20);
+            display: block;
+        }
 
-        button {
-            flex: 1;
-            margin: 0 20rpx;
+        .popup-form {
+            background: var(--color-zinc-50);
+            border-radius: px2rpx(12);
+            padding: px2rpx(16);
+            margin-bottom: px2rpx(24);
+            text-align: left;
+
+            .popup-row {
+                display: flex;
+                justify-content: space-between;
+                margin-bottom: px2rpx(12);
+                font-size: px2rpx(14);
+
+                &:last-child {
+                    margin-bottom: 0;
+                }
+
+                .label {
+                    color: var(--color-zinc-500);
+                    font-weight: 500;
+                }
+
+                text:not(.label) {
+                    color: var(--color-navy-900);
+                    font-weight: 500;
+                }
+
+                .small-input {
+                    width: px2rpx(60);
+                    background: #fff;
+                    border: px2rpx(1) solid var(--color-zinc-200);
+                    border-radius: px2rpx(4);
+                    padding: 0 px2rpx(4);
+                    height: px2rpx(24);
+                    font-size: px2rpx(12);
+                }
+            }
+        }
+
+        .popup-buttons {
+            display: flex;
+            gap: px2rpx(12);
+
+            button {
+                flex: 1;
+                height: px2rpx(44);
+                border-radius: px2rpx(10);
+                font-size: px2rpx(15);
+                font-weight: 600;
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                border: none;
+
+                &[type="primary"] {
+                    background: var(--color-navy-900);
+                    color: #fff;
+                }
+
+                &:not([type="primary"]) {
+                    background: var(--color-zinc-100);
+                    color: var(--color-zinc-600);
+                }
+            }
+        }
+
+        .result-icon {
+            display: flex;
+            justify-content: center;
+            margin-bottom: px2rpx(16);
+
+            .iconfont {
+                font-size: px2rpx(48);
+
+                &.iconchenggong {
+                    color: #52c41a;
+                }
+
+                &.iconjingshi {
+                    color: #faad14;
+                }
+
+                &.icondengdai {
+                    color: var(--color-primary);
+                    animation: rotate 2s linear infinite;
+                }
+            }
         }
     }
 
-    .result-icon {
-        font-size: 80rpx;
-        margin-bottom: 20rpx;
+    @keyframes rotate {
+        from {
+            transform: rotate(0deg);
+        }
+
+        to {
+            transform: rotate(360deg);
+        }
     }
 }
 </style>

+ 350 - 0
pages/customer/style.scss

@@ -0,0 +1,350 @@
+@import "@/uni.scss";
+
+.custom-withdraw {
+  background: var(--color-zinc-50);
+  min-height: 100vh;
+
+  .box {
+    margin-bottom: px2rpx(20);
+
+    .b-card {
+      background: #fff;
+      border-radius: px2rpx(12);
+      padding: px2rpx(20);
+      box-shadow: 0 px2rpx(4) px2rpx(12) rgba(0, 0, 0, 0.03);
+
+      .card-top {
+        .tit {
+          font-size: px2rpx(16);
+          font-weight: 600;
+          margin-bottom: px2rpx(16);
+          display: flex;
+          align-items: center;
+          color: var(--color-navy-900);
+
+          .iconfont {
+            margin-right: px2rpx(8);
+            color: var(--color-primary);
+            font-size: px2rpx(18);
+          }
+        }
+      }
+
+      .channelType {
+        font-size: px2rpx(15);
+        font-weight: 600;
+        margin: px2rpx(24) 0 px2rpx(12);
+        color: var(--color-navy-700);
+        padding-left: px2rpx(8);
+        border-left: px2rpx(4) solid var(--color-primary);
+      }
+    }
+  }
+
+  .reselect-btn {
+    margin-top: px2rpx(20);
+    display: flex;
+    justify-content: flex-end;
+  }
+
+  .s-btn {
+    &.reselect {
+      background-color: var(--color-zinc-100);
+      color: var(--color-navy-700);
+      border: none;
+      font-size: px2rpx(14);
+      padding: px2rpx(8) px2rpx(20);
+      border-radius: px2rpx(8);
+
+      &:active {
+        background-color: var(--color-zinc-200);
+      }
+    }
+
+    &[type="primary"] {
+      width: 100%;
+      height: px2rpx(48);
+      background: var(--color-navy-900);
+      color: #fff;
+      border-radius: px2rpx(12);
+      font-size: px2rpx(16);
+      font-weight: 600;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      border: none;
+      margin-top: px2rpx(30);
+      transition: all 0.2s;
+
+      &:active {
+        transform: scale(0.98);
+        background: var(--color-navy-800);
+      }
+    }
+  }
+
+  .add-back {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: px2rpx(12);
+    padding: px2rpx(12) px2rpx(16);
+    background: var(--color-zinc-100);
+    border-radius: px2rpx(8);
+
+    text {
+      font-size: px2rpx(14);
+      color: var(--color-navy-700);
+      font-weight: 500;
+    }
+
+    .add-btn {
+      color: var(--color-primary);
+      font-weight: 600;
+      text-decoration: underline;
+
+      &:active {
+        opacity: 0.7;
+      }
+    }
+  }
+
+  .proof {
+    margin-top: px2rpx(8);
+    border: px2rpx(1) dashed var(--color-zinc-300);
+    border-radius: px2rpx(8);
+    padding: px2rpx(8);
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    background: var(--color-zinc-50);
+
+    .state {
+      padding: px2rpx(4) px2rpx(12);
+      border-radius: px2rpx(4);
+      font-size: px2rpx(12);
+      font-weight: bold;
+    }
+  }
+
+  .agree {
+    margin: px2rpx(24) 0;
+    display: flex;
+    align-items: flex-start;
+
+    .checkbox {
+      display: flex;
+      align-items: flex-start;
+      gap: px2rpx(8);
+
+      :deep(uni-checkbox .uni-checkbox-input) {
+        border-radius: px2rpx(4);
+        width: px2rpx(18);
+        height: px2rpx(18);
+      }
+
+      text {
+        font-size: px2rpx(13);
+        color: var(--color-zinc-500);
+        line-height: 1.5;
+      }
+    }
+  }
+
+  .step3-attention {
+    background: var(--color-error-50, #fff1f0);
+    border-radius: px2rpx(12);
+    padding: px2rpx(16);
+    margin-bottom: px2rpx(20);
+
+    .attention {
+      font-size: px2rpx(14);
+      color: var(--color-error-600, #cf1322);
+      line-height: 1.6;
+    }
+
+    .btn-bottom {
+      margin-top: px2rpx(20);
+      display: flex;
+      justify-content: center;
+
+      .btn {
+        background: var(--color-error-600, #cf1322);
+        color: #fff;
+        padding: px2rpx(10) px2rpx(48);
+        border-radius: px2rpx(24);
+        font-size: px2rpx(15);
+        font-weight: 700;
+        box-shadow: 0 px2rpx(4) px2rpx(10) rgba(207, 19, 34, 0.2);
+        transition: all 0.2s;
+
+        &:active {
+          transform: scale(0.96);
+          opacity: 0.8;
+        }
+      }
+    }
+  }
+
+  :deep(.base-info-form) {
+    .uni-row1 {
+      .uni-col {
+        padding: 0 px2rpx(10) !important;
+      }
+
+      .uni-forms-item {
+        min-height: px2rpx(79);
+        margin-bottom: px2rpx(10);
+      }
+
+      .uni-select,
+      .uni-combox,
+      .uni-easyinput__content,
+      .uni-date-editor--x {
+        border: none !important;
+        background-color: var(--color-zinc-100) !important;
+        border-radius: px2rpx(8) !important;
+      }
+
+      .uni-date-x {
+        border: none !important;
+        background-color: rgba(195, 195, 195, 0) !important;
+      }
+
+      .uni-easyinput__content-input {
+        height: px2rpx(44) !important;
+      }
+    }
+  }
+
+  /* 弹窗样式美化 */
+  :deep(.uni-popup__wrapper) {
+    .popup-content {
+      background-color: #fff;
+      border-radius: px2rpx(20);
+      padding: px2rpx(24);
+      width: px2rpx(320);
+
+      .popup-title {
+        font-size: px2rpx(18);
+        font-weight: 700;
+        text-align: center;
+        margin-bottom: px2rpx(20);
+        color: var(--color-navy-900);
+        display: block;
+      }
+
+      .popup-text {
+        font-size: px2rpx(14);
+        line-height: 1.6;
+        color: var(--color-zinc-600);
+        margin-bottom: px2rpx(20);
+        display: block;
+      }
+
+      .popup-form {
+        background: var(--color-zinc-50);
+        border-radius: px2rpx(12);
+        padding: px2rpx(16);
+        margin-bottom: px2rpx(24);
+
+        .popup-row {
+          display: flex;
+          justify-content: space-between;
+          margin-bottom: px2rpx(12);
+          font-size: px2rpx(14);
+
+          &:last-child {
+            margin-bottom: 0;
+          }
+
+          .label {
+            color: var(--color-zinc-500);
+          }
+
+          text:not(.label) {
+            color: var(--color-navy-900);
+            font-weight: 500;
+          }
+        }
+      }
+
+      .popup-buttons {
+        display: flex;
+        gap: px2rpx(12);
+
+        button {
+          flex: 1;
+          height: px2rpx(44);
+          border-radius: px2rpx(10);
+          font-size: px2rpx(15);
+          font-weight: 600;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          border: none;
+
+          &[type="primary"] {
+            background: var(--color-navy-900);
+            color: #fff;
+          }
+
+          &:not([type="primary"]) {
+            background: var(--color-zinc-100);
+            color: var(--color-zinc-600);
+          }
+        }
+      }
+
+      .result-icon {
+        display: flex;
+        justify-content: center;
+        margin-bottom: px2rpx(16);
+
+        .iconfont {
+          font-size: px2rpx(48);
+
+          &.iconchenggong {
+            color: #52c41a;
+          }
+
+          &.iconjingshi {
+            color: #faad14;
+          }
+
+          &.icondengdai {
+            color: var(--color-primary);
+            animation: rotate 2s linear infinite;
+          }
+        }
+      }
+
+      .code-input {
+        background: var(--color-zinc-100);
+        border: none;
+        border-radius: px2rpx(8);
+        padding: px2rpx(12);
+        margin-bottom: px2rpx(12);
+        font-size: px2rpx(15);
+      }
+
+      .code-timer {
+        color: var(--color-primary);
+        font-size: px2rpx(13);
+        text-align: right;
+        margin-bottom: px2rpx(20);
+        font-weight: 500;
+      }
+    }
+  }
+
+  @keyframes rotate {
+    from {
+      transform: rotate(0deg);
+    }
+
+    to {
+      transform: rotate(360deg);
+    }
+  }
+}

+ 1347 - 0
pages/customer/withdrawal.vue

@@ -0,0 +1,1347 @@
+<template>
+  <cwg-page-wrapper class="create-page" :isHeaderFixed="true">
+    <view class="custom-withdraw">
+      <!-- 标题 -->
+      <!-- <view class="crm-title-box">
+        <text class="tit">{{ t('Custom.Withdraw.Title') }}</text>
+      </view> -->
+
+      <!-- 步骤1:选择账户 -->
+      <view class="box box-step1">
+        <view class="b-card">
+          <view class="card-top">
+            <text class="tit"><text class="iconfont icon-caret-right"></text>{{ t('Custom.Deposit.Title11') }}</text>
+            <view class="base-info-form">
+              <view class="uni-row2">
+                <cwg-combox :clearable="false" v-model:value="loginValue" :options="loginComboxOptions"
+                  :placeholder="t('placeholder.choose')" @change="onAccountChange" />
+              </view>
+            </view>
+          </view>
+        </view>
+      </view>
+
+      <!-- 步骤2:支付通道列表 -->
+      <view class="box box-step2" v-if="step2">
+        <view class="b-card">
+          <view class="card-top">
+            <text class="tit"><text class="iconfont icon-caret-right"></text>{{ t('Custom.Deposit.Title22') }}</text>
+            <view v-for="(group, groupKey) in tableData" :key="groupKey">
+              <!-- 通道分组标题 -->
+              <view class="channelType" v-if="group.length" v-t="groupTitleMap[groupKey]" />
+              <PaymentMethodsList :list="group" @select="isShowStep3" />
+            </view>
+            <view v-if="step3" class="reselect-btn">
+              <button class="s-btn reselect" type="primary" @click="showTable">{{ t('Custom.Deposit.Reselect')
+                }}</button>
+            </view>
+          </view>
+        </view>
+      </view>
+
+      <!-- 步骤3:填写出金信息 -->
+      <view class="box box-step3" v-if="step3">
+        <view class="b-card">
+          <view class="card-top">
+            <!-- 注意事项 -->
+            <view v-if="!isStep3" class="step3-attention">
+              <rich-text class="attention" :nodes="isZh ? introduce.introduce : introduce.enIntroduce"></rich-text>
+              <view class="btn-bottom">
+                <text class="btn crm-cursor" @click="isStep3 = true">{{ t('Btn.Confirm') }}</text>
+              </view>
+            </view>
+
+            <!-- 表单 -->
+            <uni-forms ref="baseForm" :model="form" labelWidth="200" label-position="top" v-if="isStep3"
+              class="base-info-form">
+              <uni-row class="demo-uni-row uni-row1">
+                <!-- 银行选择(针对有银行列表的通道) -->
+                <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="bankDate.length">
+                  <uni-forms-item :label="t('Custom.Withdraw.Title5')">
+                    <cwg-combox :clearable="false" v-model:value="selectedBankIndex" :options="bankOptions"
+                      :placeholder="t('placeholder.choose')" @change="onBankChange" />
+                  </uni-forms-item>
+                </uni-col>
+
+                <!-- 电子钱包地址输入 -->
+                <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8"
+                  v-if="['CHANNEL_TYPE_WALLET', 'UCARD_WALLET', 'CHANNEL_TYPE_ALI_WALLET'].includes(channelData.type)">
+                  <uni-forms-item :label="getWalletLabel">
+                    <uni-easyinput :clearable="false" v-model="form.address" :placeholder="t('placeholder.input')" />
+                  </uni-forms-item>
+                </uni-col>
+
+                <!-- 数字货币选择(从已保存地址中选择) -->
+                <uni-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="channelData.type === 'DIGITAL_CURRENCY'">
+                  <view class="add-back">
+                    <text>{{ t('blockchain.item10') }}</text>
+                    <text class="add-btn crm-cursor" @click="openAddBankCard('add_bankBlockchain')">{{
+                      t('Custom.Withdraw.addBank1') }}</text>
+                  </view>
+                  <uni-forms-item :label="t('blockchain.item10')">
+                    <cwg-combox :clearable="false" v-model:value="selectedDigitalIndex" :options="digitalOptions"
+                      :placeholder="t('placeholder.choose')" @change="onDigitalCurrencyChange"
+                      :disabled="!ruleForm.bankBlockchain.length" />
+                  </uni-forms-item>
+                  <uni-row>
+                    <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+                      <uni-forms-item :label="t('blockchain.item3')">
+                        <uni-easyinput disabled v-model="form.addressName" />
+                      </uni-forms-item>
+                    </uni-col>
+                    <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+                      <uni-forms-item :label="t('blockchain.item4')">
+                        <uni-easyinput disabled v-model="form.address" />
+                      </uni-forms-item>
+                    </uni-col>
+                    <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.addressProve">
+                      <uni-forms-item :label="t('blockchain.item5')">
+                        <view class="proof">
+                          <template v-if="form.addressProve && (form.addressProve.slice(-3).toLowerCase() === 'pdf')">
+                            <a :href="imgUrl + form.addressProve" target="_blank" class="state crm_state_blue">PDF</a>
+                          </template>
+                          <image v-else :src="imgUrl + form.addressProve" mode="aspectFit"
+                            style="width: 100rpx; height: 100rpx;" @click="previewImage(imgUrl + form.addressProve)" />
+                        </view>
+                      </uni-forms-item>
+                    </uni-col>
+                  </uni-row>
+                  <text class="tit"><text class="iconfont iconi"></text>{{ t('Custom.Deposit.Des') }}</text>
+                </uni-col>
+
+                <!-- 银行卡/信用卡选择 -->
+                <uni-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24"
+                  v-if="['BANK', 'BANK_TELEGRAPHIC', 'CHANNEL_TYPE_CARD'].includes(channelData.type)">
+                  <view class="add-back" v-if="channelData.type === 'BANK_TELEGRAPHIC'">
+                    <text>{{ t('Custom.Withdraw.addWire') }}</text>
+                    <text class="add-btn crm-cursor" @click="openAddBankCard('add_wireTransfer')">{{
+                      t('Custom.Withdraw.addBank1') }}</text>
+                  </view>
+                  <view class="add-back" v-else-if="channelData.type === 'BANK'">
+                    <text>{{ t('Custom.Withdraw.addBank') }}</text>
+                    <text class="add-btn crm-cursor" @click="openAddBankCard('add_bankCard')">{{
+                      t('Custom.Withdraw.addBank1')
+                    }}</text>
+                  </view>
+                  <view class="add-back" v-else-if="channelData.type === 'CHANNEL_TYPE_CARD'">
+                    <text>{{ t('PersonalManagement.Label.addCreditCard') }}</text>
+                    <text class="add-btn crm-cursor" @click="openAddBankCard('add_CreditCard')">{{
+                      t('Custom.Withdraw.addBank1') }}</text>
+                  </view>
+
+                  <uni-forms-item :label="t('placeholder.choose')">
+                    <cwg-combox :clearable="false" v-model:value="selectedBankCardIndex" :options="bankCardOptions"
+                      :placeholder="t('placeholder.choose')" @change="onBankCardChange" />
+                  </uni-forms-item>
+
+                  <!-- 通用银行信息展示 -->
+                  <uni-row>
+                    <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.bankUname">
+                      <uni-forms-item :label="t('Custom.Withdraw.UserName')">
+                        <uni-easyinput disabled v-model="form.bankUname" />
+                      </uni-forms-item>
+                    </uni-col>
+                    <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.bankCardNum">
+                      <uni-forms-item :label="t('Custom.Withdraw.BankCardNum')">
+                        <uni-easyinput disabled v-model="form.bankCardNum" />
+                      </uni-forms-item>
+                    </uni-col>
+                    <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.bankName">
+                      <uni-forms-item :label="t('Custom.Withdraw.BankName')">
+                        <uni-easyinput disabled v-model="form.bankName" />
+                      </uni-forms-item>
+                    </uni-col>
+                    <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.bankBranchName">
+                      <uni-forms-item :label="t('Custom.Withdraw.bankBranchName')">
+                        <uni-easyinput disabled v-model="form.bankBranchName" />
+                      </uni-forms-item>
+                    </uni-col>
+                    <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.swiftCode">
+                      <uni-forms-item :label="t('Custom.Withdraw.swiftCode')">
+                        <uni-easyinput disabled v-model="form.swiftCode" />
+                      </uni-forms-item>
+                    </uni-col>
+                    <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.customBankCode">
+                      <uni-forms-item :label="t('Custom.Withdraw.bankCode')">
+                        <uni-easyinput disabled v-model="form.customBankCode" />
+                      </uni-forms-item>
+                    </uni-col>
+                    <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="form.bankAddr">
+                      <uni-forms-item :label="t('Custom.Withdraw.bankAddr')">
+                        <uni-easyinput disabled v-model="form.bankAddr" />
+                      </uni-forms-item>
+                    </uni-col>
+                    <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8"
+                      v-if="channelData.type === 'BANK_TELEGRAPHIC' && form.agencyNo">
+                      <uni-forms-item label="Account Agency NO">
+                        <uni-easyinput v-model="form.agencyNo" />
+                      </uni-forms-item>
+                    </uni-col>
+                    <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8"
+                      v-if="channelData.type === 'BANK_TELEGRAPHIC' && form.cpf">
+                      <uni-forms-item label="CPF">
+                        <uni-easyinput v-model="form.cpf" />
+                      </uni-forms-item>
+                    </uni-col>
+                  </uni-row>
+                </uni-col>
+
+                <!-- 出金金额 -->
+                <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="channelData.type !== 'BANK_TELEGRAPHIC'">
+                  <uni-forms-item :label="t('Custom.Withdraw.Title3') + '(' + channelData.currency + ')'">
+                    <uni-easyinput v-model="form.amount" type="number" @input="onAmountInput" />
+                  </uni-forms-item>
+                </uni-col>
+                <template v-else>
+                  <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+                    <uni-forms-item :label="t('Custom.Withdraw.CurrencyType')">
+                      <cwg-combox :clearable="false" v-model:value="form.currency"
+                        :options="[{ text: 'USD', value: 'USD' }]" @change="(val) => form.currency = val" />
+                    </uni-forms-item>
+                  </uni-col>
+                  <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8">
+                    <uni-forms-item :label="t('Custom.Withdraw.amount')">
+                      <uni-easyinput v-model="form.amount" type="number" @input="onAmountInput" />
+                    </uni-forms-item>
+                  </uni-col>
+                </template>
+
+              </uni-row>
+
+              <!-- 协议同意 -->
+              <view class="agree">
+                <label class="checkbox">
+                  <checkbox :checked="form.agree2" @click="form.agree2 = !form.agree2" />
+                  <text class="crm-cursor" style="text-decoration: underline;" @click="dialogCheckTip = true">{{
+                    t('Custom.Withdraw.Des') }}</text>
+                </label>
+              </view>
+              <view class="agree" v-if="dialogTipsIsShow">
+                <label class="checkbox">
+                  <checkbox :checked="form.agree3" @click="form.agree3 = !form.agree3" />
+                  <text>* {{ t('Custom.Withdraw.item1') }}<br>{{ t('Custom.Withdraw.item1_1') }}<br>{{
+                    t('Custom.Withdraw.item1_2') }}</text>
+                </label>
+              </view>
+
+              <button class="s-btn" type="primary" @click="openTips">{{ t('Btn.Submit') }}</button>
+            </uni-forms>
+          </view>
+        </view>
+      </view>
+
+      <!-- 弹窗:确认信息 -->
+      <uni-popup ref="confirmPopup" type="center" :mask-click="false">
+        <view class="popup-content">
+          <text class="popup-title">{{ t('Home.page_customer.item3') }}</text>
+          <view class="popup-form">
+            <view class="popup-row"><text class="label">{{ t('Custom.Deposit.Title11') }}:</text><text>{{ loginValue
+                }}</text></view>
+            <view class="popup-row"><text class="label">{{ t('Custom.Deposit.Title22') }}:</text><text>{{ (t('lang') ===
+              'cn' || t('lang') === 'zhHant') ? channelData.name : channelData.enName }}</text></view>
+            <view class="popup-row"><text class="label">{{ t('Custom.Withdraw.Title3') }}:</text><text>{{ form.amount
+                }}({{
+                  channelData.currency }})</text></view>
+            <view class="popup-row"><text class="label">{{ t('Custom.Withdraw.item7') }}:</text><text
+                v-if="FreeNumber > 0 && dialogConfirmFee > 0"><text style="text-decoration:line-through">${{
+                  dialogConfirmFee
+                  }}</text> $0.00</text><text v-else>${{ dialogConfirmFee }}</text></view>
+          </view>
+          <view class="popup-buttons">
+            <button @click="closeConfirmPopup">{{ t('Btn.Cancel') }}</button>
+            <button type="primary" @click="submitConfirm">{{ t('Btn.Confirm') }}</button>
+          </view>
+        </view>
+      </uni-popup>
+
+      <!-- 弹窗:提交前警告 -->
+      <uni-popup ref="warningPopup" type="center">
+        <view class="popup-content">
+          <text class="popup-text">{{ t('Custom.Withdraw.item2') }}</text>
+          <view class="popup-buttons">
+            <button @click="closeWarningPopup">{{ t('Custom.Withdraw.item4') }}</button>
+            <button type="primary" @click="submitAfterWarning">{{ t('Custom.Withdraw.item3') }}</button>
+          </view>
+        </view>
+      </uni-popup>
+
+      <!-- 弹窗:结果 -->
+      <uni-popup ref="resultPopup" type="center" :mask-click="false">
+        <view class="popup-content">
+          <view class="result-icon" v-if="dialogSuccess"><text class="iconfont iconchenggong"></text></view>
+          <view class="result-icon" v-else><text class="iconfont iconjingshi"></text></view>
+          <text class="popup-text">{{ dialogMessage }}</text>
+          <view class="popup-buttons">
+            <button type="primary" @click="closeResultPopup">{{ t('Btn.Confirm') }}</button>
+            <button v-if="!dialogSuccess" @click="closeResultPopup">{{ t('Btn.Cancel') }}</button>
+          </view>
+        </view>
+      </uni-popup>
+
+      <!-- 弹窗:条款 -->
+      <uni-popup ref="tipPopup" type="center">
+        <view class="popup-content">
+          <rich-text class="popup-text"
+            :nodes="(t('lang') === 'cn' || t('lang') === 'zhHant') ? introduce.introduce : introduce.enIntroduce"></rich-text>
+          <view class="popup-buttons">
+            <button @click="closeTipPopup">{{ t('Btn.Cancel') }}</button>
+            <button type="primary" @click="closeTipPopup">{{ t('Btn.Confirm') }}</button>
+          </view>
+        </view>
+      </uni-popup>
+
+      <!-- 弹窗:等待 -->
+      <uni-popup ref="waitPopup" type="center" :mask-click="false">
+        <view class="popup-content">
+          <text class="iconfont icondengdai"></text>
+          <text class="popup-text">{{ t('ApplicationDialog.Des38') }}</text>
+        </view>
+      </uni-popup>
+
+      <!-- 弹窗:验证码 -->
+      <uni-popup ref="codePopup" type="center">
+        <view class="popup-content">
+          <text class="popup-title">{{ t('signup.form.code') }}</text>
+          <input class="code-input" v-model="emailCode" :placeholder="t('signup.form.code')" />
+          <view class="code-timer" @click="getCode">{{ getCodeString }}</view>
+          <view class="popup-buttons">
+            <button @click="closeCodePopup">{{ t('Btn.Cancel') }}</button>
+            <button type="primary" @click="submitCode">{{ t('Btn.Confirm') }}</button>
+          </view>
+        </view>
+      </uni-popup>
+
+      <!-- 抽屉:新增/修改银行信息 -->
+      <!-- <drawer :dialogInfoTradingAdd="dialogInfoTradingAdd" :addType="openType" @closeAdd="closeAdd"
+      @confirmToReload="confirmToReload" /> -->
+    </view>
+  </cwg-page-wrapper>
+
+</template>
+
+<script setup>
+import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
+import { onLoad } from '@dcloudio/uni-app'
+import { useI18n } from 'vue-i18n' // uni-app 中已集成,但需配置
+import { customApi } from '@/service/custom'
+import { financialApi } from '@/service/financial'
+// import {ServiceA} from '@/service/activity'
+import Config from '@/config/index'
+import Decimal from 'decimal.js'
+// import Drawer from '@/components/Drawer.vue' // 假设抽屉组件已存在
+import PaymentMethodsList from './components/PaymentMethodsList.vue'
+
+const { t, locale } = useI18n()
+
+const isZh = computed(() => ['cn', 'zhHant'].includes(locale.value))
+
+const loginComboxOptions = computed(() => {
+  return loginOptions.value.map((item, index) => ({
+    text: item.label,
+    value: item.login
+  }))
+})
+
+const bankOptions = computed(() => {
+  return bankDate.value.map((item, index) => ({
+    text: isZh.value ? item.name : item.enName,
+    value: index
+  }))
+})
+
+const digitalOptions = computed(() => {
+  return ruleForm.bankBlockchain.map((item, index) => ({
+    text: `${item.addressName}-${item.address}`,
+    value: index
+  }))
+})
+
+const bankCardOptions = computed(() => {
+  return bankList.value.map((item, index) => ({
+    text: getBankLabel(item),
+    value: index
+  }))
+})
+
+const getWalletLabel = computed(() => {
+  if (channelData.value.type === 'CHANNEL_TYPE_WALLET') return t('Custom.Withdraw.Title7')
+  if (channelData.value.type === 'UCARD_WALLET') return t('card.title')
+  if (channelData.value.type === 'CHANNEL_TYPE_ALI_WALLET') return t('Label.AliAccout')
+  return ''
+})
+
+const { Code, Host80 } = Config
+const imgUrl = Host80
+
+// 工具函数
+const Session = {
+  get: (key, parse = false) => {
+    const val = uni.getStorageSync(key)
+    return parse ? JSON.parse(val) : val
+  },
+  set: (key, val) => uni.setStorageSync(key, val)
+}
+
+// 分组标题映射
+const groupTitleMap = {
+  'Ucard_Wallet': 'card.title',
+  'Digital_Currency': 'Custom.Deposit.Channel3',
+  'China_UnionPay': 'Custom.Deposit.Channel2',
+  'Electronic_Wallet': 'Custom.Deposit.Channel4',
+  'International_Transfer': 'Custom.Deposit.Channel1',
+  'CHANNEL_TYPE_CARD': 'PersonalManagement.Label.CreditCard',
+  'CHANNEL_TYPE_ALI_WALLET': 'Label.Ali'
+}
+// 数据
+const loginOptions = ref([])
+const selectedAccountIndex = ref(-1)
+const selectedAccountLabel = ref('')
+const loginValue = ref(null)
+const step2 = ref(false)
+const step3 = ref(false)
+const isStep3 = ref(false)
+const tableData = ref({
+  Ucard_Wallet: [],
+  Digital_Currency: [],
+  China_UnionPay: [],
+  Electronic_Wallet: [],
+  International_Transfer: [],
+  CHANNEL_TYPE_CARD: [],
+  CHANNEL_TYPE_ALI_WALLET: []
+})
+const channelData = ref({})
+const introduce = ref({ introduce: '', enIntroduce: '' })
+const bankDate = ref([])
+const selectedBankIndex = ref(-1)
+const selectedBankLabel = ref('')
+const ruleForm = reactive({
+  bankInfo: [],
+  bankWrit: [],
+  xykInfo: [],
+  bankBlockchain: []
+})
+const form = reactive({
+  currency: 'USD',
+  amount: '',
+  amount1: '',
+  agree2: false,
+  agree3: false,
+  address: '',
+  addressName: '',
+  addressProve: '',
+  bankUname: '',
+  bankCardNum: '',
+  bankName: '',
+  bankBranchName: '',
+  swiftCode: '',
+  customBankCode: '',
+  bankAddr: '',
+  agencyNo: '',
+  cpf: ''
+})
+const myId = ref(null)
+const bankList = computed(() => {
+  if (channelData.value.type === 'BANK') return ruleForm.bankInfo
+  if (channelData.value.type === 'BANK_TELEGRAPHIC') return ruleForm.bankWrit
+  if (channelData.value.type === 'CHANNEL_TYPE_CARD') return ruleForm.xykInfo
+  return []
+})
+const selectedBankCardIndex = ref(-1)
+const selectedBankCardLabel = ref('')
+const selectedDigitalIndex = ref(-1)
+const selectedDigitalLabel = ref('')
+const mAmount = reactive({ minAmount: '', maxAmount: '' })
+const FreeNumber = ref(0)
+const isFree = ref(false)
+const dialogTipsIsShow = ref(true)
+const dialogConfirmFee = ref(0)
+
+// 弹窗引用
+const confirmPopup = ref(null)
+const warningPopup = ref(null)
+const resultPopup = ref(null)
+const tipPopup = ref(null)
+const waitPopup = ref(null)
+const codePopup = ref(null)
+
+// 结果状态
+const dialogSuccess = ref(false)
+const dialogMessage = ref('')
+
+// 验证码
+const emailCode = ref('')
+const getCodeString = ref('')
+let timer = null
+let countdown = 59
+
+// 抽屉
+const dialogInfoTradingAdd = ref(false)
+const openType = ref('')
+
+// 其他
+const pictLoading = ref(false)
+const isChannel = ref(true)
+const bankPayType = ref('')
+const requestUrl = ref('')
+const RES = ref('')
+const flag = ref(false)
+
+// 方法
+const getDateList = async () => {
+  const res = await customApi.CustomDropdown({ platform: '' })
+  if (res.code === Code.StatusOK) {
+    loginOptions.value = res.data.map(item => ({
+      ...item,
+      label: `${item.login} - ${groupTypeName(item.type)} - ${t('Custom.Deposit.AvailableBalance')}${groupCurrency(item.currency)}${item.balance}`
+    }))
+    const route = getCurrentPages().pop().$page.options
+    if (route.login) {
+      const found = loginOptions.value.find(opt => opt.login === Number(route.login))
+      if (found) {
+        selectedAccountIndex.value = loginOptions.value.indexOf(found)
+        selectedAccountLabel.value = found.label
+        loginValue.value = found.login
+        step2.value = true
+      }
+    }
+  } else {
+    uni.showToast({ title: res.msg, icon: 'none' })
+  }
+}
+
+const groupTypeName = (type) => {
+  const map = {
+    '1': 'AccountType.ClassicAccount',
+    '2': 'AccountType.SeniorAccount',
+    '5': 'AccountType.SpeedAccount',
+    '6': 'AccountType.SpeedAccount',
+    '7': 'AccountType.StandardAccount',
+    '8': 'AccountType.CentAccount'
+  }
+  return t(map[type] || '')
+}
+
+const groupCurrency = (type) => {
+  const symbol = { GBP: '£', USD: '$', EUR: '€', USC: '¢' }[type] || '$'
+  return `: ${symbol}`
+}
+
+const getDepositList = async () => {
+  pictLoading.value = true
+  const res = await financialApi.RemitChannelList({})
+  if (res.code === Code.StatusOK) {
+    const groups = {
+      Ucard_Wallet: [],
+      Digital_Currency: [],
+      China_UnionPay: [],
+      Electronic_Wallet: [],
+      International_Transfer: [],
+      CHANNEL_TYPE_CARD: [],
+      CHANNEL_TYPE_ALI_WALLET: []
+    }
+    res.data.forEach(item => {
+      if (item.type === 'UCARD_WALLET') groups.Ucard_Wallet.push(item)
+      if (item.type === 'DIGITAL_CURRENCY') groups.Digital_Currency.push(item)
+      if (item.type === 'BANK') groups.China_UnionPay.push(item)
+      if (item.type === 'CHANNEL_TYPE_WALLET') groups.Electronic_Wallet.push(item)
+      if (item.type === 'BANK_TELEGRAPHIC') groups.International_Transfer.push(item)
+      if (item.type === 'CHANNEL_TYPE_CARD') groups.CHANNEL_TYPE_CARD.push(item)
+      if (item.type === 'CHANNEL_TYPE_ALI_WALLET') groups.CHANNEL_TYPE_ALI_WALLET.push(item)
+    })
+    tableData.value = groups
+    pictLoading.value = false
+  } else {
+    uni.showToast({ title: res.msg, icon: 'none' })
+    pictLoading.value = false
+  }
+}
+
+const getBankList = async (row) => {
+  const res = await financialApi.BankList({ channelCode: row.code })
+  if (res.code === Code.StatusOK) {
+    const data = res.data.map(j => ({
+      ...j,
+      minAmount: j.minAmount ?? row.minAmount,
+      maxAmount: j.maxAmount ?? row.maxAmount,
+      payType: row.code
+    }))
+    bankDate.value = data
+  } else {
+    uni.showToast({ title: res.msg, icon: 'none' })
+  }
+}
+
+const getBankInfo = async () => {
+  const res = await financialApi.customBankList({})
+  if (res.code === Code.StatusOK) {
+    ruleForm.bankInfo = []
+    ruleForm.bankWrit = []
+    ruleForm.xykInfo = []
+    ruleForm.bankBlockchain = []
+    res.data.forEach(item => {
+      item.customBankCode = item.bankCode
+      item.bankCode = null
+      if (item.type === 1) ruleForm.bankInfo.push(item)
+      else if (item.type === 2) ruleForm.bankWrit.push(item)
+      else if (item.type === 3) {
+        item.expiryYearMonth = `${item.expiryYear}/${item.expiryMonth}`
+        ruleForm.xykInfo.push(item)
+      } else if (item.type === 4) ruleForm.bankBlockchain.push(item)
+    })
+    // 如果有默认选中
+    const findDefault = (list, type) => list.find(b => b.defaultBank && b.type === type)
+    const defaultBank = findDefault(ruleForm.bankInfo, 1)
+    const defaultWire = findDefault(ruleForm.bankWrit, 2)
+    const defaultCard = findDefault(ruleForm.xykInfo, 3)
+    const defaultDigital = findDefault(ruleForm.bankBlockchain, 4)
+    if (channelData.value.type === 'BANK' && defaultBank) selectBankCard(defaultBank)
+    if (channelData.value.type === 'BANK_TELEGRAPHIC' && defaultWire) selectBankCard(defaultWire)
+    if (channelData.value.type === 'CHANNEL_TYPE_CARD' && defaultCard) selectBankCard(defaultCard)
+    if (channelData.value.type === 'DIGITAL_CURRENCY' && defaultDigital && defaultDigital.authStatus === 1) selectDigital(defaultDigital)
+  } else {
+    uni.showToast({ title: res.msg, icon: 'none' })
+  }
+}
+
+const selectBankCard = (item) => {
+  const index = bankList.value.findIndex(b => b.id === item.id)
+  if (index !== -1) {
+    selectedBankCardIndex.value = index
+    selectedBankCardLabel.value = getBankLabel(item)
+    Object.assign(form, item)
+  }
+}
+
+const selectDigital = (item) => {
+  const index = ruleForm.bankBlockchain.findIndex(b => b.id === item.id)
+  if (index !== -1) {
+    selectedDigitalIndex.value = index
+    selectedDigitalLabel.value = `${item.addressName}-${item.address}`
+    form.addressName = item.addressName
+    form.address = item.address
+    form.addressProve = item.addressProve
+  }
+}
+
+const getBankLabel = (item) => {
+  if (channelData.value.type === 'BANK' || channelData.value.type === 'BANK_TELEGRAPHIC') {
+    return `${item.bankName}-${item.bankCardNum}`
+  } else if (channelData.value.type === 'CHANNEL_TYPE_CARD') {
+    return item.bankCardNum
+  }
+  return ''
+}
+
+const getFreeNumber = async () => {
+  if (!isFree.value) return
+  const res = await financialApi.remainingReductionNumber({})
+  if (res.code === Code.StatusOK) {
+    FreeNumber.value = res.data || 0
+  } else {
+    uni.showToast({ title: res.msg, icon: 'none' })
+  }
+}
+
+const isNewYear24Open = () => {
+  // 简化,原逻辑是判断活动时间
+  // 根据需求决定是否保留
+}
+
+// 事件处理
+const onAccountChange = (val) => {
+  const item = loginOptions.value.find(opt => opt.login === val)
+  if (item) {
+    selectedAccountIndex.value = loginOptions.value.indexOf(item)
+    selectedAccountLabel.value = item.label
+    loginValue.value = item.login
+    step2.value = true
+    showTable()
+  }
+}
+
+const showTable = () => {
+  myId.value = null
+  step3.value = false
+  isStep3.value = false
+  isChannel.value = true
+  getDepositList()
+  Object.assign(form, { currency: 'USD', amount: '', amount1: '', agree2: false, agree3: false, address: '', addressName: '', addressProve: '', bankUname: '', bankCardNum: '', bankName: '', bankBranchName: '', swiftCode: '', customBankCode: '', bankAddr: '', agencyNo: '', cpf: '' })
+  if (bankDate.value.length) bankDate.value = []
+  selectedBankIndex.value = -1
+  selectedBankLabel.value = ''
+  selectedBankCardIndex.value = -1
+  selectedBankCardLabel.value = ''
+  selectedDigitalIndex.value = -1
+  selectedDigitalLabel.value = ''
+}
+
+const isShowStep3 = (row) => {
+  if (row.bankValid && isChannel.value) {
+    getBankList(row)
+    isChannel.value = false
+    step3.value = true
+    channelData.value = row
+    mAmount.minAmount = row.minAmount
+    mAmount.maxAmount = row.maxAmount
+  } else {
+    step3.value = true
+    bankDate.value = []
+    channelData.value = row
+    mAmount.minAmount = row.minAmount
+    mAmount.maxAmount = row.maxAmount
+  }
+  if (row.code === 'UNION_PAY_TELEGRAPHIC') {
+    // WireTransferAccount = JSON.parse(row.property) 暂略
+  }
+  if (['BANK', 'BANK_TELEGRAPHIC', 'CHANNEL_TYPE_CARD', 'DIGITAL_CURRENCY'].includes(row.type)) {
+    getBankInfo()
+    form.login = loginValue.value
+    form.payType = row.code
+    bankPayType.value = row.code
+  }
+  // 重新组织 tableData 只显示当前选中项
+  const newGroups = {
+    Ucard_Wallet: [],
+    Digital_Currency: [],
+    China_UnionPay: [],
+    Electronic_Wallet: [],
+    International_Transfer: [],
+    CHANNEL_TYPE_CARD: [],
+    CHANNEL_TYPE_ALI_WALLET: []
+  }
+  if (row.type === 'UCARD_WALLET') newGroups.Ucard_Wallet = [row]
+  if (row.type === 'DIGITAL_CURRENCY') newGroups.Digital_Currency = [row]
+  if (row.type === 'BANK') newGroups.China_UnionPay = [row]
+  if (row.type === 'CHANNEL_TYPE_WALLET') newGroups.Electronic_Wallet = [row]
+  if (row.type === 'BANK_TELEGRAPHIC') newGroups.International_Transfer = [row]
+  if (row.type === 'CHANNEL_TYPE_CARD') newGroups.CHANNEL_TYPE_CARD = [row]
+  if (row.type === 'CHANNEL_TYPE_ALI_WALLET') newGroups.CHANNEL_TYPE_ALI_WALLET = [row]
+  tableData.value = newGroups
+  introduce.value = { introduce: row.introduce, enIntroduce: row.enIntroduce }
+}
+
+const onBankChange = (val) => {
+  const index = val
+  const item = bankDate.value[index]
+  if (item) {
+    selectedBankIndex.value = index
+    selectedBankLabel.value = (t('lang') === 'cn' || t('lang') === 'zhHant') ? item.name : item.enName
+    channelData.value.rate = item.rate
+    channelData.value.transformCurrency = item.currency
+    channelData.value.feeTypeBank = item.feeType
+    channelData.value.freeBank = item.free
+    channelData.value.feeAmountBank = item.feeAmount
+  }
+}
+
+const onBankCardChange = (val) => {
+  const index = val
+  const item = bankList.value[index]
+  if (item) {
+    selectedBankCardIndex.value = index
+    selectedBankCardLabel.value = getBankLabel(item)
+    Object.assign(form, item)
+  }
+}
+
+const onDigitalCurrencyChange = (val) => {
+  const index = val
+  const item = ruleForm.bankBlockchain[index]
+  if (item && item.authStatus === 1) {
+    selectedDigitalIndex.value = index
+    selectedDigitalLabel.value = `${item.addressName}-${item.address}`
+    form.addressName = item.addressName
+    form.address = item.address
+    form.addressProve = item.addressProve
+  } else if (item && item.authStatus === 0) {
+    uni.showToast({ title: t('Msg.item11'), icon: 'none' })
+    selectedDigitalIndex.value = -1
+    selectedDigitalLabel.value = ''
+  }
+}
+
+const onAmountInput = (val) => {
+  // val is the value from uni-easyinput
+  if (val && channelData.value.rate) {
+    if (isFree.value) {
+      let feeAmount = 0
+      if (channelData.value.feeTypeBank) {
+        if (channelData.value.feeTypeBank === 1) feeAmount = Number(val) * (Number(channelData.value.freeBank || 0) / 100)
+        else if (channelData.value.feeTypeBank === 2) feeAmount = Number(channelData.value.feeAmountBank || 0)
+      } else {
+        if (channelData.value.feeType === 1) feeAmount = Number(val) * (Number(channelData.value.free || 0) / 100)
+        else if (channelData.value.feeType === 2) feeAmount = Number(channelData.value.feeAmount || 0)
+      }
+      if (FreeNumber.value > 0) {
+        form.amount1 = new Decimal(Number(val)).mul(Number(channelData.value.rate || 0)).toNumber()
+      } else {
+        form.amount1 = new Decimal(Number(val)).sub(Number(feeAmount || 0)).mul(Number(channelData.value.rate || 0)).toNumber()
+      }
+    } else {
+      form.amount1 = (val * channelData.value.rate).toFixed(2)
+    }
+    if (['CNY', 'THB', 'VND'].includes(channelData.value.transformCurrency)) {
+      form.amount1 = parseInt(form.amount1)
+    }
+  }
+}
+
+const openTips = () => {
+  // 校验
+  if (channelData.value.type === 'DIGITAL_CURRENCY' && !myId.value) {
+    uni.showToast({ title: t('blockchain.item11'), icon: 'none' })
+    return
+  }
+  if (['BANK', 'BANK_TELEGRAPHIC', 'CHANNEL_TYPE_CARD'].includes(channelData.value.type) && !selectedBankCardIndex.value !== -1) {
+    uni.showToast({ title: t('vaildate.withdrawBank.empty'), icon: 'none' })
+    return
+  }
+  // 金额校验
+  if (!form.amount) {
+    uni.showToast({ title: t('vaildate.input.empty'), icon: 'none' })
+    return
+  }
+  if (Number(form.amount) < Number(mAmount.minAmount) || Number(form.amount) > Number(mAmount.maxAmount)) {
+    uni.showToast({ title: `${t('vaildate.amount.amount')}${mAmount.minAmount} - ${mAmount.maxAmount}`, icon: 'none' })
+    return
+  }
+  if (!/^[0-9]+([.]{1}[0-9]{1,2})?$/.test(form.amount)) {
+    uni.showToast({ title: t('vaildate.amount.format'), icon: 'none' })
+    return
+  }
+  if (!form.agree2) {
+    uni.showToast({ title: t('vaildate.agree.empty'), icon: 'none' })
+    return
+  }
+  if (dialogTipsIsShow.value && !form.agree3) {
+    uni.showToast({ title: t('vaildate.agree.empty'), icon: 'none' })
+    return
+  }
+
+  if (dialogTipsIsShow.value) {
+    warningPopup.value.open()
+  } else {
+    // 直接提交,先弹出确认框
+    prepareConfirm()
+  }
+}
+
+const prepareConfirm = () => {
+  // 计算手续费
+  let feeAmount = 0
+  if (channelData.value.feeTypeBank) {
+    if (channelData.value.feeTypeBank === 1) feeAmount = Number(form.amount) * (Number(channelData.value.freeBank || 0) / 100)
+    else if (channelData.value.feeTypeBank === 2) feeAmount = Number(channelData.value.feeAmountBank || 0)
+  } else {
+    if (channelData.value.feeType === 1) feeAmount = Number(form.amount) * (Number(channelData.value.free || 0) / 100)
+    else if (channelData.value.feeType === 2) feeAmount = Number(channelData.value.feeAmount || 0)
+  }
+  dialogConfirmFee.value = feeAmount
+  confirmPopup.value.open()
+}
+
+const submitConfirm = () => {
+  confirmPopup.value.close()
+  submit()
+}
+
+const submitAfterWarning = () => {
+  warningPopup.value.close()
+  prepareConfirm()
+}
+
+const submit = async () => {
+  if (flag.value) return
+  flag.value = true
+  waitPopup.value.open()
+
+  const params = {
+    login: loginValue.value,
+    payType: channelData.value.code,
+    ...form
+  }
+
+  // 根据不同通道类型调用不同接口
+  let res = null
+  if (channelData.value.type === 'DIGITAL_CURRENCY') {
+    if (!emailCode.value) {
+      waitPopup.value.close()
+      codePopup.value.open()
+      flag.value = false
+      return
+    }
+    params.emailCode = emailCode.value
+    res = await financialApi.WithdrawAapplyDigitalCurrency(channelData.value.requestUrl, params)
+  } else if (['CHANNEL_TYPE_WALLET', 'UCARD_WALLET', 'CHANNEL_TYPE_ALI_WALLET'].includes(channelData.value.type)) {
+    res = await financialApi.WithdrawAapplyDigitalCurrency(channelData.value.requestUrl, params)
+  } else if (['BANK', 'BANK_TELEGRAPHIC', 'CHANNEL_TYPE_CARD'].includes(channelData.value.type)) {
+    res = await financialApi.WithdrawApplyBank(channelData.value.requestUrl, params)
+  }
+
+  waitPopup.value.close()
+  if (res && res.code === Code.StatusOK) {
+    dialogSuccess.value = true
+    dialogMessage.value = t('ApplicationDialog.Des1')
+    resultPopup.value.open()
+  } else {
+    dialogSuccess.value = false
+    dialogMessage.value = res?.msg || t('ApplicationDialog.Des2')
+    resultPopup.value.open()
+  }
+  flag.value = false
+}
+
+const getCode = async () => {
+  if (getCodeString.value !== t('signup.form.getCode')) return
+  const res = await financialApi.withdrawCode({})
+  if (res.code === Code.StatusOK) {
+    uni.showToast({ title: t('Msg.CodeSuccess'), icon: 'none' })
+    startCountdown()
+  } else {
+    uni.showToast({ title: res.msg, icon: 'none' })
+  }
+}
+
+const startCountdown = () => {
+  getCodeString.value = `${t('signup.form.waitCode1')}${countdown}${t('signup.form.waitCode2')}`
+  timer = setInterval(() => {
+    countdown--
+    if (countdown <= 0) {
+      clearInterval(timer)
+      timer = null
+      countdown = 59
+      getCodeString.value = t('signup.form.getCode')
+    } else {
+      getCodeString.value = `${t('signup.form.waitCode1')}${countdown}${t('signup.form.waitCode2')}`
+    }
+  }, 1000)
+}
+
+const submitCode = () => {
+  if (!emailCode.value) {
+    uni.showToast({ title: t('vaildate.code.empty'), icon: 'none' })
+    return
+  }
+  codePopup.value.close()
+  submit()
+}
+
+const openAddBankCard = (type) => {
+  openType.value = type
+  dialogInfoTradingAdd.value = true
+}
+
+const closeAdd = (val) => {
+  dialogInfoTradingAdd.value = val
+}
+
+const confirmToReload = () => {
+  dialogInfoTradingAdd.value = false
+  getBankInfo()
+}
+
+const closeConfirmPopup = () => confirmPopup.value.close()
+const closeWarningPopup = () => warningPopup.value.close()
+const closeResultPopup = () => {
+  resultPopup.value.close()
+  if (dialogSuccess.value) {
+    // 重置状态
+    showTable()
+    step2.value = false
+    step3.value = false
+    isStep3.value = false
+    selectedAccountIndex.value = -1
+    selectedAccountLabel.value = ''
+    loginValue.value = null
+  }
+}
+const closeTipPopup = () => tipPopup.value.close()
+const closeCodePopup = () => codePopup.value.close()
+
+// 预览图片
+const previewImage = (url) => {
+  uni.previewImage({ urls: [url] })
+}
+
+// 生命周期
+onLoad(() => {
+  getDateList()
+  getFreeNumber()
+  isNewYear24Open()
+  // 计算 isFree 时间判断,原逻辑略
+  isFree.value = true // 根据实际需求
+  getDepositList()
+})
+
+onUnmounted(() => {
+  if (timer) clearInterval(timer)
+})
+</script>
+
+<style lang="scss" scoped>
+@import "@/uni.scss";
+
+.custom-withdraw {
+  background: var(--color-zinc-50);
+  min-height: 100vh;
+
+  .box {
+    margin-bottom: px2rpx(20);
+
+    .b-card {
+      background: #fff;
+      border-radius: px2rpx(12);
+      padding: px2rpx(20);
+      box-shadow: 0 px2rpx(4) px2rpx(12) rgba(0, 0, 0, 0.03);
+
+      .card-top {
+        .tit {
+          font-size: px2rpx(16);
+          font-weight: 600;
+          margin-bottom: px2rpx(16);
+          display: flex;
+          align-items: center;
+          color: var(--color-navy-900);
+          position: relative;
+          padding-left: 20px;
+
+          &:after {
+            content: '';
+            position: absolute;
+            left: 0;
+            top: 50%;
+            transform: translateY(-50%);
+            width: 0;
+            height: 0;
+            border-top: 6px solid transparent;
+            border-bottom: 6px solid transparent;
+            border-left: 8px solid currentColor;
+          }
+
+          .iconfont {
+            margin-right: px2rpx(8);
+            color: var(--color-primary);
+            font-size: px2rpx(18);
+          }
+        }
+      }
+
+      .channelType {
+        font-size: px2rpx(15);
+        font-weight: 600;
+        margin: px2rpx(24) 0 px2rpx(12);
+        color: var(--color-navy-700);
+        padding-left: px2rpx(8);
+        border-left: px2rpx(4) solid var(--color-primary);
+      }
+    }
+  }
+
+  .reselect-btn {
+    margin-top: px2rpx(20);
+    display: flex;
+    justify-content: flex-end;
+  }
+
+  .s-btn {
+    &.reselect {
+      background-color: var(--color-zinc-100);
+      color: var(--color-navy-700);
+      border: none;
+      font-size: px2rpx(14);
+      padding: px2rpx(8) px2rpx(20);
+      border-radius: px2rpx(8);
+
+      &:active {
+        background-color: var(--color-zinc-200);
+      }
+    }
+
+    &[type="primary"] {
+      width: 100%;
+      height: px2rpx(48);
+      background: var(--color-navy-900);
+      color: #fff;
+      border-radius: px2rpx(12);
+      font-size: px2rpx(16);
+      font-weight: 600;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      border: none;
+      margin-top: px2rpx(30);
+      transition: all 0.2s;
+
+      &:active {
+        transform: scale(0.98);
+        background: var(--color-navy-800);
+      }
+    }
+  }
+
+  .add-back {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: px2rpx(12);
+    padding: px2rpx(12) px2rpx(16);
+    background: var(--color-zinc-100);
+    border-radius: px2rpx(8);
+
+    text {
+      font-size: px2rpx(14);
+      color: var(--color-navy-700);
+      font-weight: 500;
+    }
+
+    .add-btn {
+      color: var(--color-primary);
+      font-weight: 600;
+      text-decoration: underline;
+
+      &:active {
+        opacity: 0.7;
+      }
+    }
+  }
+
+  .proof {
+    margin-top: px2rpx(8);
+    border: px2rpx(1) dashed var(--color-zinc-300);
+    border-radius: px2rpx(8);
+    padding: px2rpx(8);
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    background: var(--color-zinc-50);
+
+    .state {
+      padding: px2rpx(4) px2rpx(12);
+      border-radius: px2rpx(4);
+      font-size: px2rpx(12);
+      font-weight: bold;
+    }
+  }
+
+  .agree {
+    margin: px2rpx(24) 0;
+    display: flex;
+    align-items: flex-start;
+
+    .checkbox {
+      display: flex;
+      align-items: flex-start;
+      gap: px2rpx(8);
+
+      :deep(uni-checkbox .uni-checkbox-input) {
+        border-radius: px2rpx(4);
+        width: px2rpx(18);
+        height: px2rpx(18);
+      }
+
+      text {
+        font-size: px2rpx(13);
+        color: var(--color-zinc-500);
+        line-height: 1.5;
+      }
+    }
+  }
+
+  .step3-attention {
+    background: var(--color-error-50, #fff1f0);
+    border-radius: px2rpx(12);
+    padding: px2rpx(16);
+    margin-bottom: px2rpx(20);
+
+    .attention {
+      font-size: px2rpx(14);
+      color: var(--color-error-600, #cf1322);
+      line-height: 1.6;
+    }
+
+    .btn-bottom {
+      margin-top: px2rpx(20);
+      display: flex;
+      justify-content: center;
+
+      .btn {
+        background: var(--color-error-600, #cf1322);
+        color: #fff;
+        padding: px2rpx(10) px2rpx(48);
+        border-radius: px2rpx(24);
+        font-size: px2rpx(15);
+        font-weight: 700;
+        box-shadow: 0 px2rpx(4) px2rpx(10) rgba(207, 19, 34, 0.2);
+        transition: all 0.2s;
+
+        &:active {
+          transform: scale(0.96);
+          opacity: 0.8;
+        }
+      }
+    }
+  }
+
+  :deep(.base-info-form) {
+    .uni-row1 {
+      .uni-col {
+        padding: 0 px2rpx(10) !important;
+      }
+
+      .uni-forms-item {
+        min-height: px2rpx(79);
+        margin-bottom: px2rpx(10);
+      }
+
+      .uni-select,
+      .uni-combox,
+      .uni-easyinput__content,
+      .uni-date-editor--x {
+        border: none !important;
+        background-color: var(--color-zinc-100) !important;
+        border-radius: px2rpx(8) !important;
+      }
+
+      .uni-date-x {
+        border: none !important;
+        background-color: rgba(195, 195, 195, 0) !important;
+      }
+
+      .uni-easyinput__content-input {
+        height: px2rpx(44) !important;
+      }
+    }
+  }
+
+  /* 弹窗样式美化 */
+  :deep(.uni-popup__wrapper) {
+    .popup-content {
+      background-color: #fff;
+      border-radius: px2rpx(20);
+      padding: px2rpx(24);
+      width: px2rpx(320);
+
+      .popup-title {
+        font-size: px2rpx(18);
+        font-weight: 700;
+        text-align: center;
+        margin-bottom: px2rpx(20);
+        color: var(--color-navy-900);
+        display: block;
+      }
+
+      .popup-text {
+        font-size: px2rpx(14);
+        line-height: 1.6;
+        color: var(--color-zinc-600);
+        margin-bottom: px2rpx(20);
+        display: block;
+      }
+
+      .popup-form {
+        background: var(--color-zinc-50);
+        border-radius: px2rpx(12);
+        padding: px2rpx(16);
+        margin-bottom: px2rpx(24);
+
+        .popup-row {
+          display: flex;
+          justify-content: space-between;
+          margin-bottom: px2rpx(12);
+          font-size: px2rpx(14);
+
+          &:last-child {
+            margin-bottom: 0;
+          }
+
+          .label {
+            color: var(--color-zinc-500);
+          }
+
+          text:not(.label) {
+            color: var(--color-navy-900);
+            font-weight: 500;
+          }
+        }
+      }
+
+      .popup-buttons {
+        display: flex;
+        gap: px2rpx(12);
+
+        button {
+          flex: 1;
+          height: px2rpx(44);
+          border-radius: px2rpx(10);
+          font-size: px2rpx(15);
+          font-weight: 600;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          border: none;
+
+          &[type="primary"] {
+            background: var(--color-navy-900);
+            color: #fff;
+          }
+
+          &:not([type="primary"]) {
+            background: var(--color-zinc-100);
+            color: var(--color-zinc-600);
+          }
+        }
+      }
+
+      .result-icon {
+        display: flex;
+        justify-content: center;
+        margin-bottom: px2rpx(16);
+
+        .iconfont {
+          font-size: px2rpx(48);
+
+          &.iconchenggong {
+            color: #52c41a;
+          }
+
+          &.iconjingshi {
+            color: #faad14;
+          }
+
+          &.icondengdai {
+            color: var(--color-primary);
+            animation: rotate 2s linear infinite;
+          }
+        }
+      }
+
+      .code-input {
+        background: var(--color-zinc-100);
+        border: none;
+        border-radius: px2rpx(8);
+        padding: px2rpx(12);
+        margin-bottom: px2rpx(12);
+        font-size: px2rpx(15);
+      }
+
+      .code-timer {
+        color: var(--color-primary);
+        font-size: px2rpx(13);
+        text-align: right;
+        margin-bottom: px2rpx(20);
+        font-weight: 500;
+      }
+    }
+  }
+
+  @keyframes rotate {
+    from {
+      transform: rotate(0deg);
+    }
+
+    to {
+      transform: rotate(360deg);
+    }
+  }
+}
+</style>

+ 0 - 257
pages/login/forget.vue

@@ -1,257 +0,0 @@
-<script setup>
-import { ref, reactive, watch } from "vue";
-
-import { post, get } from "@/utils/request";
-import { useRequest } from "@/composables/useRequest";
-
-const SendCodeByPhone = (params) => post("/Common/SendCodeByPhone", params);
-const ResetPwd = (params) => post("/Login/ResetPwd", params);
-
-// 响应式表单数据
-const form = ref({
-  mobile: "",
-  code: "",
-  password: "",
-});
-// 校验规则
-const rules = {
-  mobile: [
-    {
-      required: true,
-      message: "请输入用户名或手机号",
-      trigger: ["change", "blur"],
-    },
-    {
-      // 自定义验证函数,见上说明
-      validator: (rule, value, callback) => {
-        // 上面有说,返回true表示校验通过,返回false表示不通过
-        // uni.$u.test.mobile()就是返回true或者false的
-        return uni.$u.test.mobile(value);
-      },
-      message: "手机号码不正确",
-      // 触发器可以同时用blur和change
-      trigger: ["change", "blur"],
-    },
-  ],
-  code: [
-    {
-      required: true,
-      message: "请输入验证码",
-      trigger: ["change", "blur"],
-    },
-  ],
-  password: [
-    {
-      required: true,
-      message: "请输入密码",
-      trigger: ["change", "blur"],
-    },
-  ],
-};
-
-const tips = ref("");
-const value = ref("");
-const seconds = ref(60);
-const uCodeRef = ref(null);
-
-watch(value, (newValue, oldValue) => {
-  // console.log('v-model', newValue);
-});
-
-const codeChange = (text) => {
-  tips.value = text;
-};
-
-const getCode = async () => {
-  // console.log('uCodeRef.canGetCode: ', uCodeRef.value);
-  if (uCodeRef.value.canGetCode) {
-    // 模拟向后端请求验证码
-    uni.showLoading({
-      title: "正在获取验证码",
-    });
-    const data = await SendCodeByPhone({ phone: form.value.mobile });
-    console.log("data: ", data);
-    if (data) {
-      setTimeout(() => {
-        uni.hideLoading();
-        // 这里此提示会被start()方法中的提示覆盖
-        uni.$u.toast("验证码已发送");
-        // 通知验证码组件内部开始倒计时
-        uCodeRef.value.start();
-      }, 2000);
-    } else {
-      uni.hideLoading();
-    }
-  } else {
-    uni.$u.toast("倒计时结束后再发送");
-  }
-};
-
-const uFormRef = ref(null);
-function submit() {
-  uFormRef.value
-    .validate()
-    .then((valid) => {
-      if (valid) {
-        // uni.$u.toast('校验通过');
-        refresh({
-          phone: form.value.mobile,
-          code: form.value.code,
-          newPassword: form.value.password,
-        });
-      } else {
-        // uni.$u.toast('校验失败');
-      }
-    })
-    .catch(() => {
-      // 处理验证错误
-      // uni.$u.toast('校验失败');
-    });
-}
-
-// 使用组合函数
-const { data, loading, error, refresh } = useRequest(ResetPwd, {
-  initialParams: {
-    phone: form.value.mobile,
-    code: form.value.code,
-    newPassword: form.value.password,
-  },
-  immediate: false, // 默认立即执行
-});
-const token = ref("");
-watch([loading, error], () => {
-  if (!loading.value) {
-    // 加载完成
-    if (error.value) {
-      console.log("请求失败: ", error.value); // 打印错误信息
-    } else {
-      console.log("请求成功: ", data.value); // 成功时获取数据
-      uni.$u.toast("修改成功");
-      setTimeout(() => {
-        uni.navigateBack();
-      }, 1500);
-    }
-  }
-});
-const customStyle = {
-  height: "84px",
-  "border-radius": "8px",
-  background: "#f7f8fa",
-  padding: "0 20px !important",
-  position: "relative",
-};
-</script>
-<template>
-  <view>
-    <view class="company u-flex u-flex-y-center">
-      <image src="/static/images/logo.png" class="company-icon" mode="widthFix"></image>
-      <view class="company-head">
-        <view class="name">华都渠道管家</view>
-        <view class="into">专业的房产销售管理平台</view>
-      </view>
-    </view>
-    <view class="account">
-      <view>
-        <up-form :model="form" :rules="rules" ref="uFormRef">
-          <up-form-item label="" prop="mobile">
-            <up-input :customStyle="customStyle" v-model="form.mobile" border="none" placeholder="请输入用户名或手机号" />
-          </up-form-item>
-          <up-form-item label="" prop="code">
-            <up-input :customStyle="customStyle" v-model="form.code" border="none" placeholder="请输入验证码">
-              <template #suffix>
-                <up-code ref="uCodeRef" @change="codeChange" :seconds="seconds"></up-code>
-                <up-text :text="tips" @click="getCode" class="code-text"></up-text>
-              </template>
-            </up-input>
-          </up-form-item>
-
-          <up-form-item label="" prop="password">
-            <up-input :customStyle="customStyle" v-model="form.password" type="password" border="none"
-              placeholder="新密码" />
-          </up-form-item>
-        </up-form>
-      </view>
-    </view>
-
-    <button type="primary" class="regiset-btn" @click="submit">重置密码</button>
-    <navigator url="/pages/login/regist" class="account-tip">
-      还没有账号?
-      <text>立即注册</text>
-    </navigator>
-  </view>
-</template>
-
-<style>
-page {
-  padding: px2rpx(10) px2rpx(52);
-  box-sizing: border-box;
-}
-</style>
-<style lang="scss" scoped>
-@import "@/uni.scss";
-
-button {
-  background-color: #ea002a;
-  font-size: px2rpx(14);
-  font-weight: normal;
-  height: px2rpx(84);
-  line-height: px2rpx(84);
-}
-
-.company {
-  padding: px2rpx(40) 0;
-}
-
-.company-icon {
-  width: px2rpx(104);
-  height: px2rpx(104);
-  margin-right: px2rpx(14);
-}
-
-.company-head {
-  .name {
-    font-size: px2rpx(20);
-    font-weight: 500;
-    color: #ea002a;
-    margin-bottom: px2rpx(2);
-  }
-
-  .into {
-    font-size: px2rpx(13);
-    font-weight: 350;
-    color: #222222;
-  }
-}
-
-.account {
-  .input {
-    height: px2rpx(84);
-    border-radius: px2rpx(8);
-    background: #f7f8fa;
-    padding: 0 px2rpx(20) !important;
-  }
-}
-
-.regiset-btn {
-  margin: px2rpx(20) 0;
-}
-
-.account-tip {
-  color: #666666;
-  font-size: px2rpx(13);
-  text-align: center;
-
-  text {
-    color: #ea002a;
-  }
-}
-
-.code-text {
-  padding-right: px2rpx(20);
-}
-
-:deep(.u-text__value) {
-  color: #ea002a !important;
-  font-size: px2rpx(14) !important;
-}
-</style>

+ 6 - 2
pages/login/index.vue

@@ -146,7 +146,7 @@ const inputType = ref("password");
 </script>
 
 <template>
-  <cwg-page-wrapper class="login-page" :isHeaderFixed="true" :isLoginPage="true">
+  <view class="login-page" :isHeaderFixed="true" :isLoginPage="true">
     <uni-row class="demo-uni-row">
       <cwg-match-media :min-width="991">
         <uni-col :xs="24" :sm="24" :md="12" :lg="14" :xl="16" class="left-bg">
@@ -248,12 +248,16 @@ const inputType = ref("password");
         </u-button>
       </view>
     </view>
-  </cwg-page-wrapper>
+  </view>
 </template>
 
 <style lang="scss" scoped>
 @import "@/uni.scss";
 
+:deep(uni-content) {
+  padding-left: 0 !important;
+}
+
 .login-page {
   height: 100vh;
   border: none;

+ 60 - 174
pages/login/regist.vue

@@ -1,14 +1,9 @@
 <script setup>
-import { ref, reactive, watch,onMounted } from 'vue'
-import { post, get } from '@/utils/request'
-import { useRequest } from '@/composables/useRequest'
+import { ref, watch, onMounted } from 'vue'
 import { useI18n } from 'vue-i18n'
 import { useEmailCountdown } from '@/hooks/useEmailCountdown'
 import { ucardApi } from '@/api/ucard'
 import { showToast } from '@/utils/toast'
-
-const SendCodeByPhone = (params) => post('/Common/SendCodeByPhone', params)
-const PhoneLoginReg = (params) => post('/Login/PhoneLoginReg', params)
 const { t } = useI18n()
 
 const {
@@ -22,120 +17,24 @@ const {
 // 响应式表单数据
 const formData = ref({
   country: '',
-  birthDate:'',
+  birthDate: '',
   code: '',
   password: '',
   agentId: null,
   agentValue: '',
-  userType: 4,
-  userTypeName: '全民营销',
   readName: '',
   agree: '',
 })
 const ho = ref('')
 // 账号类型
 const accountType = ref(1)
-const columnsAgent = ref([])
-const columnsType = ref([
-  {
-    text: '中介',
-    value: 3,
-  },
-  {
-    text: '全民营销',
-    value: 4,
-  },
-])
-// 校验规则
-const rules = {
-  mobile: [
-    {
-      required: true,
-      message: '请输入用户名或手机号',
-      trigger: ['change', 'blur'],
-    },
-    {
-      // 自定义验证函数,见上说明
-      validator: (rule, value, callback) => {
-        // 上面有说,返回true表示校验通过,返回false表示不通过
-        // uni.$u.test.mobile()就是返回true或者false的
-        return uni.$u.test.mobile(value)
-      },
-      message: '手机号码不正确',
-      // 触发器可以同时用blur和change
-      trigger: ['change', 'blur'],
-    },
-  ],
-  code: [
-    {
-      required: true,
-      message: '请输入验证码',
-      trigger: ['change', 'blur'],
-    },
-  ],
-  password: [
-    {
-      required: true,
-      message: '请输入密码',
-      trigger: ['change', 'blur'],
-    },
-  ],
-  readName: [
-    {
-      required: true,
-      message: '请输入真实姓名',
-      trigger: ['change', 'blur'],
-    },
-  ],
-  agentValue: [
-    {
-      required: true,
-      message: '请选择中介',
-      trigger: ['change', 'blur'],
-    },
-  ],
-}
 
-const tips = ref('')
 const value = ref('')
-const seconds = ref(60)
-const uCodeRef = ref(null)
-const timer = ref(59)
-const interval = ref(null)
 
 watch(value, (newValue, oldValue) => {
   //  console.log('v-model', newValue);
 })
 
-const codeChange = (text) => {
-  tips.value = text
-}
-
-const change = (e) => {
-  //  console.log("change", e);
-}
-const showAgent = ref(false)
-const confirmAgent = (e) => {
-  //  console.log("e: ", e);
-  form.value.agentValue = e.value[0].text
-  form.value.agentId = e.value[0].value
-  showAgent.value = false
-}
-
-const showType = ref(false)
-const confirmType = (e) => {
-  //  console.log("e: ", e);
-  form.value.userTypeName = e.value[0].text
-  form.value.userType = e.value[0].value
-  if (form.value.userType == 4) {
-    form.value.agentValue = ''
-    form.value.agentId = ''
-  }
-  showType.value = false
-}
-
-const uFormRef = ref(null)
-
 // 切换注册账号类型
 const changeAccountType = (type) => {
   if (accountType.value !== type) accountType.value = type
@@ -163,50 +62,25 @@ async function sendEmailCode() {
   }
 }
 
-const aloneChecked = ref(false)
-const getRichText = (url) => {
-  uni.navigateTo({
-    url,
-  })
-}
-const GetAgencys = (params) => get('/Buss/GetAgencys', params)
-const { data, loading, error, refresh } = useRequest(GetAgencys, {
-  initialParams: {},
-  immediate: true, // 默认立即执行
-})
-onMounted(()=>{
+
+onMounted(() => {
   const hostParts = window.location.host.split('.')
   ho.value = hostParts.length > 1 ? hostParts[1] : ''
 })
-watch([loading, error], () => {
-  if (!loading.value) {
-    // 加载完成
-    if (error.value) {
-      //  console.log("请求失败: ", error.value); // 打印错误信息
-    } else {
-      //  console.log("请求成功: ", data.value); // 成功时获取数据
-      columnsAgent.value = data.value.map((item) => {
-        return {
-          text: item.name,
-          value: item.id,
-        }
-      })
-    }
-  }
-})
+
 </script>
 <template>
-  <cwg-page-wrapper class="regist-page" :isHeaderFixed="true" :isLoginPage="true">
+  <view class="regist-page" :isHeaderFixed="true" :isLoginPage="true">
     <uni-row class="content">
-      <uni-col :span="20" :offset="2" :sm="{ span: 14 , offset:5}">
+      <uni-col :span="20" :offset="2" :sm="{ span: 14, offset: 5 }">
         <view class="logo">
           <image src="/static/images/logo.png" class="company-icon" mode="widthFix"></image>
         </view>
         <!--        账号类型-->
         <view class="account-type">
-          <view class="type-btn" @click="changeAccountType(1)" :class="{active:accountType === 1}">Open Live Account
+          <view class="type-btn" @click="changeAccountType(1)" :class="{ active: accountType === 1 }">Open Live Account
           </view>
-          <view class="type-btn" @click="changeAccountType(2)" :class="{active:accountType === 2}">Register Demo
+          <view class="type-btn" @click="changeAccountType(2)" :class="{ active: accountType === 2 }">Register Demo
             Account
           </view>
         </view>
@@ -225,26 +99,28 @@ watch([loading, error], () => {
               </uni-forms-item>
             </uni-col>
             <uni-col :xs="24" :md="12">
-              <uni-forms-item  name="phone" :label="t('newSignup.item5')">
+              <uni-forms-item name="phone" :label="t('newSignup.item5')">
                 <uni-easyinput class="formStyle" v-model="formData.phone"></uni-easyinput>
               </uni-forms-item>
             </uni-col>
             <uni-col :xs="24" :md="12">
-              <uni-forms-item  name="birthDate" :label="t('newSignup.item18')">
-                <uni-datetime-picker class="formStyle" type="date" v-model="formData.birthDate" :placeholder="t('newSignup.item19')"/>
+              <uni-forms-item name="birthDate" :label="t('newSignup.item18')">
+                <uni-datetime-picker class="formStyle" type="date" v-model="formData.birthDate"
+                  :placeholder="t('newSignup.item19')" />
               </uni-forms-item>
             </uni-col>
             <uni-col :xs="24" :md="12">
-              <uni-forms-item  name="email" :label="t('newSignup.item7')">
-                <uni-easyinput class="formStyle" v-model="formData.email" :placeholder="t('newSignup.item8')"></uni-easyinput>
+              <uni-forms-item name="email" :label="t('newSignup.item7')">
+                <uni-easyinput class="formStyle" v-model="formData.email"
+                  :placeholder="t('newSignup.item8')"></uni-easyinput>
               </uni-forms-item>
             </uni-col>
             <uni-col :xs="24" :md="12">
-              <uni-forms-item  name="code" :label="t('newSignup.item7')">
+              <uni-forms-item name="code" :label="t('newSignup.item7')">
                 <uni-easyinput class="formStyle" v-model="formData.code" :placeholder="t('newSignup.item8')">
-                    <template #right>
-                      <view class="btn-code" @click="handleGetCode">{{getCodeString}}</view>
-                    </template>
+                  <template #right>
+                    <view class="btn-code" @click="handleGetCode">{{ getCodeString }}</view>
+                  </template>
                 </uni-easyinput>
               </uni-forms-item>
             </uni-col>
@@ -254,17 +130,20 @@ watch([loading, error], () => {
         </uni-forms>
         <view class="check-box">
           <up-checkbox-group v-model="formData.agree">
-            <up-checkbox size="14" labelSize="14" labelColor="#666666" activeColor="#ea002a" v-model="formData.agree" :label="t('signup.agree')" name="" class="wcg-checkbox"></up-checkbox>
+            <up-checkbox size="14" labelSize="14" labelColor="#666666" activeColor="#ea002a" v-model="formData.agree"
+              :label="t('signup.agree')" name="" class="wcg-checkbox"></up-checkbox>
           </up-checkbox-group>
         </view>
         <view class="check-box">
           <up-checkbox-group v-model="formData.isSubscribeEmail">
-            <up-checkbox size="14" labelSize="14" labelColor="#666666" activeColor="#ea002a" v-model="formData.isSubscribeEmail" :label="t('signup.agree1')" name="" class="wcg-checkbox"></up-checkbox>
+            <up-checkbox size="14" labelSize="14" labelColor="#666666" activeColor="#ea002a"
+              v-model="formData.isSubscribeEmail" :label="t('signup.agree1')" name=""
+              class="wcg-checkbox"></up-checkbox>
           </up-checkbox-group>
         </view>
         <view>
           <u-button class="regiset-btn">
-            {{t('signup.button')}}
+            {{ t('signup.button') }}
           </u-button>
         </view>
         <view class="or-title">
@@ -275,12 +154,12 @@ watch([loading, error], () => {
         <uni-row :gutter="20">
           <uni-col :xs="24" :md="12">
             <u-button class="login-btn">
-              {{t('signup.button')}}
+              {{ t('signup.button') }}
             </u-button>
           </uni-col>
           <uni-col :xs="24" :md="12">
             <u-button class="login-btn">
-              {{t('signup.button')}}
+              {{ t('signup.button') }}
             </u-button>
           </uni-col>
         </uni-row>
@@ -289,30 +168,26 @@ watch([loading, error], () => {
     </uni-row>
     <view class="des">
       <view>
-        {{t('newSignin.item12')}}
+        {{ t('newSignin.item12') }}
       </view><br />
       <view>
-        {{t('newSignin.item10')}}
+        {{ t('newSignin.item10') }}
       </view><br />
       <view>
-        {{t('newSignin.item11')}}
+        {{ t('newSignin.item11') }}
       </view><br />
       <view>{{ t('newSignin.item13') }}</view>
-      <a
-        :href="`https://www.${ho}.com/doc/Risk-Disclosures-and-Acknowledgements-2020-08.pdf`"
-        target="_blank"
-      >
+      <a :href="`https://www.${ho}.com/doc/Risk-Disclosures-and-Acknowledgements-2020-08.pdf`" target="_blank">
         {{ t('newSignin.item13_1') }}
       </a>
       <view>{{ t('newSignin.item13_2') }}</view>
       <view>{{ t('newSignin.item13_3') }}</view>
       <view>{{ t('newSignin.item13_4') }}</view>
     </view>
-  </cwg-page-wrapper>
+  </view>
 </template>
 
-<style lang="scss">
-</style>
+<style lang="scss"></style>
 <style lang="scss" scoped>
 @import "@/uni.scss";
 
@@ -323,6 +198,7 @@ watch([loading, error], () => {
 }
 
 .content {
+
   //display: flex;
   .logo {
     width: 100%;
@@ -382,27 +258,33 @@ watch([loading, error], () => {
     color: var(--gray);
   }
 }
-.formContent{
+
+.formContent {
   padding: 0 10px;
 }
+
 // 修改表单组件高度。
-:deep(.uni-stat-box){
+:deep(.uni-stat-box) {
   height: 100%;
 }
-:deep(.uni-select){
+
+:deep(.uni-select) {
   height: 100%;
 }
-:deep(.uni-easyinput__content){
+
+:deep(.uni-easyinput__content) {
   height: 100%;
 }
-:deep(.uni-date-editor){
+
+:deep(.uni-date-editor) {
   height: 100%;
 }
-:deep(.uni-date-editor--x){
+
+:deep(.uni-date-editor--x) {
   height: 100%;
 }
 
-.btn-code{
+.btn-code {
   width: 30%;
   height: 100%;
   background-color: #102047;
@@ -413,15 +295,17 @@ watch([loading, error], () => {
   border-radius: 0 4px 4px 0;
 }
 
-.check-box{
-  padding: 0  px2rpx(10);
+.check-box {
+  padding: 0 px2rpx(10);
   margin-bottom: px2rpx(10);
-  :deep(.u-checkbox){
+
+  :deep(.u-checkbox) {
     display: flex;
     align-items: flex-start;
   }
 }
-.regiset-btn{
+
+.regiset-btn {
   width: 100%;
   height: px2rpx(40);
   border-radius: px2rpx(20);
@@ -452,7 +336,7 @@ watch([loading, error], () => {
   }
 }
 
-.login-btn{
+.login-btn {
   width: 100%;
   height: px2rpx(40);
   border-radius: px2rpx(20);
@@ -474,17 +358,19 @@ watch([loading, error], () => {
   color: #000;
   font-size: 12px;
   padding: px2rpx(20) px2rpx(30);
+
   //display: none;
-  :nth-child(n){
+  :nth-child(n) {
     display: inline;
-    word-break:break-all;
-    word-wrap:break-word;
+    word-break: break-all;
+    word-wrap: break-word;
   }
 
   a {
     color: #e61f1e;
   }
 }
+
 :deep(.u-text__value) {
   color: #ea002a !important;
   font-size: px2rpx(14) !important;

+ 1 - 2
pages/mine/improve.vue

@@ -187,8 +187,7 @@ import { Patterns, Validators } from "@/utils/validators";
 import CardWebsdkLink from "@/components/card-websdkLink.vue";
 import useRouter from "@/hooks/useRouter";
 const router = useRouter();
-const userStore = useUserStore();
-const userInfo = computed(() => userStore.userInfo);
+
 const { availableIdTypeOptions, loadIdTypesConfig } = useIdTypeOptions()
 console.log(availableIdTypeOptions, 1212121, 'storeIdTypeOptionsstoreIdTypeOptions');
 

+ 5 - 0
service/custom.ts

@@ -27,6 +27,7 @@ export const customApi = {
   ChangeDealPassword: (params = {}) => post('/account/settings/change/deal/password/add', params, 'Host80'),
   // 交易账户列表
   AccountList: (params = {}) => post('/account/list', params, 'Host80'),
+  AccountAllList: (params = {}) => post('/account/all/list', params, 'Host80'),
   // 申请账户
   AccountApplyAdd: (params = {}) => post('/account/apply/add', params, 'Host80'),
   // 申请账户-dome
@@ -97,4 +98,8 @@ export const customApi = {
   getSystemList: (params = {}) => post('/custom/system/config/all/list', params, 'Host80'),
   // 切换系统
   switchSystem: (params = {}) => post('/custom/system/config/choose', params, 'Host80'),
+  // 模拟账户
+  demoList: (params = {}) => post('/account/demo/all/list', params, 'Host80'),
+  // 修改昵称
+  updateNick: (params = {}) => post('/custom/login/update/nick/name', params, 'Host80'),
 };

+ 1 - 0
static/icons/crm-caret-right.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free 7.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M441.3 299.8C451.5 312.4 450.8 330.9 439.1 342.6L311.1 470.6C301.9 479.8 288.2 482.5 276.2 477.5C264.2 472.5 256.5 460.9 256.5 448L256.5 192C256.5 179.1 264.3 167.4 276.3 162.4C288.3 157.4 302 160.2 311.2 169.3L439.2 297.3L441.4 299.7z"/></svg>

BIN
static/pdf/Client_Agreement.pdf


BIN
static/pdf/CopyTradeUserAgreement.pdf


BIN
static/pdf/CopyTradeUserAgreementcn.pdf


BIN
static/pdf/DigitalCurrency_Withdrawal_Cn.pdf


BIN
static/pdf/DigitalCurrency_Withdrawal_En.pdf


BIN
static/pdf/PrivacyPolicy2019_01.pdf


BIN
static/pdf/Privacy_Policy.pdf


BIN
static/pdf/Terms&Conditions.pdf


BIN
static/pdf/pdf1/ar.pdf


BIN
static/pdf/pdf1/cn.pdf


BIN
static/pdf/pdf1/en.pdf


BIN
static/pdf/pdf1/es.pdf


BIN
static/pdf/pdf1/ko.pdf


BIN
static/pdf/pdf1/pt.pdf


BIN
static/pdf/pdf1/th.pdf


BIN
static/pdf/pdf1/vn.pdf


BIN
static/pdf/pdf1/zhHant.pdf


BIN
static/pdf/pdf10/Account Type Allocation Table-cn.pdf


BIN
static/pdf/pdf10/Account Type Allocation Table-en.pdf


BIN
static/pdf/pdf10/Account Type Allocation Table-zhHant.pdf


BIN
static/pdf/pdf11/Account Type Allocation Table-cn.pdf


BIN
static/pdf/pdf11/Account Type Allocation Table-en.pdf


BIN
static/pdf/pdf11/Account Type Allocation Table-zhHant.pdf


BIN
static/pdf/pdf12/Account Type Allocation Table-cn.pdf


BIN
static/pdf/pdf12/CWG Markets Prime Bonus Application Process-cn.pdf


BIN
static/pdf/pdf12/CWG Markets Prime Bonus Application Process-en.pdf


BIN
static/pdf/pdf12/CWG Markets Prime Bonus Application Process-zhHant.pdf


BIN
static/pdf/pdf12/CWG Prime Bonus-ar.pdf


BIN
static/pdf/pdf12/CWG Prime Bonus-cn.pdf


BIN
static/pdf/pdf12/CWG Prime Bonus-de.pdf


BIN
static/pdf/pdf12/CWG Prime Bonus-en.pdf


BIN
static/pdf/pdf12/CWG Prime Bonus-es.pdf


BIN
static/pdf/pdf12/CWG Prime Bonus-fa.pdf


BIN
static/pdf/pdf12/CWG Prime Bonus-id.pdf


BIN
static/pdf/pdf12/CWG Prime Bonus-ko.pdf


BIN
static/pdf/pdf12/CWG Prime Bonus-ms.pdf


BIN
static/pdf/pdf12/CWG Prime Bonus-pt.pdf


BIN
static/pdf/pdf12/CWG Prime Bonus-th.pdf


BIN
static/pdf/pdf12/CWG Prime Bonus-tr.pdf


BIN
static/pdf/pdf12/CWG Prime Bonus-vn.pdf


BIN
static/pdf/pdf12/CWG Prime Bonus-zhHant.pdf


BIN
static/pdf/pdf13/CWG Markets Prime Bonus Application Process-cn.pdf


BIN
static/pdf/pdf13/CWG Prime Bonus-cn.pdf


BIN
static/pdf/pdf2/pdf-cn.pdf


BIN
static/pdf/pdf2/pdf-en.pdf


BIN
static/pdf/pdf2/pdf-es.pdf


BIN
static/pdf/pdf2/pdf-pt.pdf


BIN
static/pdf/pdf2/pdf-th.pdf


BIN
static/pdf/pdf2/pdf-vn.pdf


BIN
static/pdf/pdf2/pdf-zhHant.pdf


BIN
static/pdf/pdf3/pdf-cn.pdf


BIN
static/pdf/pdf3/pdf-en.pdf


BIN
static/pdf/pdf3/pdf-zhHant.pdf


BIN
static/pdf/pdf4/100Bonus-ar.pdf


BIN
static/pdf/pdf4/100Bonus-en.pdf


BIN
static/pdf/pdf4/100Bonus-es.pdf


BIN
static/pdf/pdf4/ar.pdf


BIN
static/pdf/pdf4/cn.pdf


BIN
static/pdf/pdf4/de.pdf


BIN
static/pdf/pdf4/en.pdf


BIN
static/pdf/pdf4/es.pdf


Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott