Explorar el Código

Merge branch 'admin_dev' of http://112.213.107.185:3000/cwg-crm/gypsy-crm-frontend-vu into admin_dev

zhb hace 1 mes
padre
commit
02695c6a86

+ 3 - 4
components/PrefectInfo.vue

@@ -27,6 +27,7 @@
 <script setup lang="ts">
   import { computed, ref,onMounted } from 'vue'
   import { useI18n } from 'vue-i18n'
+  import useGlobalStore from '@/stores/use-global-store'
   import useUserStore from '@/stores/use-user-store'
   import useRouter from '@/hooks/useRouter'
   import useRoute from '@/hooks/useRoute'
@@ -35,15 +36,14 @@
   const router = useRouter()
   const route = useRoute()
   const { userInfo } = useUserStore()
+  const { setApplyStatus } = useGlobalStore()
   const { t } = useI18n()
   // 认证弹窗,
   const dialogCheck = ref(null)
-  const customInfo = computed(() => {
-    return userInfo.customInfo
-  })
 
   const isPerfectInfo = computed(() => {
     const {status,applyRealStatus} = userInfo.customInfo
+    setApplyStatus(!(status == 2 || applyRealStatus == 1|| applyRealStatus ==2))
     return !(status == 2 || applyRealStatus == 1|| applyRealStatus ==2) && route.path != '/pages/mine/improveImmediately'
   })
   const info = computed(() => {
@@ -51,7 +51,6 @@
   })
 
   function immediately() {
-    console.log(customInfo.value)
     router.push({
       path:'/pages/mine/improveImmediately'
     })

+ 81 - 24
components/QrCode.vue

@@ -175,26 +175,77 @@ function drawLogo(ctx) {
 }
 /** 下载二维码 */
 function download() {
-    uni.canvasToTempFilePath({
-        canvasId,
-        success(res) {
-            console.log('canvas转图片成功:', res.tempFilePath)
-            uni.saveImageToPhotosAlbum({
-                filePath: res.tempFilePath,
-                success() {
-                    uni.showToast({ title: '已保存', icon: 'success' })
-                },
-                fail(err) {
-                    console.error('保存图片失败:', err)
-                    uni.showToast({ title: '保存失败', icon: 'error' })
-                }
-            })
-        },
-        fail(err) {
-            console.error('canvas转图片失败:', err)
-            uni.showToast({ title: '生成图片失败', icon: 'error' })
-        }
-    })
+    // 延迟一点时间确保画布渲染完成
+    setTimeout(() => {
+        uni.canvasToTempFilePath({
+            canvasId: canvasId,
+            success(res) {
+                console.log('canvas转图片成功:', res.tempFilePath)
+                // #ifdef H5
+                // H5端下载处理
+                const a = document.createElement('a')
+                a.href = res.tempFilePath
+                a.download = 'qrcode.png'
+                document.body.appendChild(a)
+                a.click()
+                document.body.removeChild(a)
+                uni.showToast({ title: '已保存', icon: 'success' })
+                // #endif
+
+                // #ifndef H5
+                // 移动端下载处理
+                uni.saveImageToPhotosAlbum({
+                    filePath: res.tempFilePath,
+                    success() {
+                        uni.showToast({ title: '已保存', icon: 'success' })
+                    },
+                    fail(err) {
+                        console.error('保存图片失败:', err)
+                        // 如果是没有权限,提示用户授权
+                        if (err.errMsg === 'saveImageToPhotosAlbum:fail auth deny' || err.errMsg === 'saveImageToPhotosAlbum:fail:auth denied') {
+                            uni.showModal({
+                                title: '提示',
+                                content: '需要您授权保存相册',
+                                success: (modalRes) => {
+                                    if (modalRes.confirm) {
+                                        uni.openSetting({
+                                            success(settingdata) {
+                                                if (settingdata.authSetting['scope.writePhotosAlbum']) {
+                                                    uni.showToast({ title: '获取权限成功,再次点击图片即可保存', icon: 'none' })
+                                                } else {
+                                                    uni.showToast({ title: '获取权限失败', icon: 'none' })
+                                                }
+                                            }
+                                        })
+                                    }
+                                }
+                            })
+                        } else {
+                            uni.showToast({ title: '保存失败', icon: 'error' })
+                        }
+                    }
+                })
+                // #endif
+            },
+            fail(err) {
+                console.error('canvas转图片失败:', err)
+                uni.showToast({ title: '生成图片失败', icon: 'error' })
+            }
+        })
+    }, 200)
+}
+
+/** 清空二维码 */
+function clear() {
+    const ctx = uni.createCanvasContext(canvasId)
+    if (!ctx) return
+    // 清除画布区域
+    ctx.clearRect(0, 0, props.width, props.height)
+    // 绘制透明/白色背景
+    ctx.setFillStyle(props.colorLight)
+    ctx.fillRect(0, 0, props.width, props.height)
+    ctx.draw()
+    console.log('二维码已清空')
 }
 
 onMounted(() => {
@@ -202,13 +253,19 @@ onMounted(() => {
     drawQr()
 })
 
-watch(() => props.text, () => {
-    console.log('二维码文本变化,重新绘制:', props.text)
-    drawQr()
+watch(() => props.text, (newVal) => {
+    console.log('二维码文本变化:', newVal)
+    if (!newVal) {
+        clear()
+    } else {
+        drawQr()
+    }
 })
 
 defineExpose({
-    download
+    download,
+    clear,
+    drawQr
 })
 </script>
 

+ 10 - 1
components/cwg-sidebar.vue

@@ -21,7 +21,7 @@
             </view>
         </view>
         <view class="menu fixed">
-            <view class="menu-item ib-box" @click="setMode('ib')" v-if="mode !== 'ib'">
+            <view class="menu-item ib-box" @click="setMode('ib')" v-if="mode !== 'ib' && ibStatus">
                 <cwg-icon name="crm-ib" :size="20" color="#6c8595" />
                 <view class="menu-label" v-t="'Home.msg.Ib'" />
             </view>
@@ -34,8 +34,17 @@
 </template>
 
 <script lang="ts" setup>
+  import useUserStore from '@/stores/use-user-store'
 import { useMenuSplit } from '@/composables/useMenuSplit'
+import { computed } from 'vue'
+
 const { menus, setSubmenuRef, setMode, handleClick, handleSubmenuClick, mode } = useMenuSplit()
+  const { userInfo } = useUserStore()
+  // ib按钮展示
+  const ibStatus = computed(() => {
+    console.log(userInfo)
+    return userInfo.customInfo.ibInvalid == 0 && !!userInfo.ibInfo
+  })
 </script>
 
 <style scoped lang="scss">

+ 5 - 0
components/cwg-tabel.vue

@@ -634,6 +634,11 @@ watch(() => props.queryParams, () => {
         // refreshTable()
     })
 }, { deep: true })
+watch(() => props.api, () => {
+    nextTick(() => {
+        refreshTable()
+    })
+}, { deep: true })
 // ========== 生命周期 ==========
 onMounted(() => {
     checkIsMobile()

+ 1 - 0
hooks/useEmailCountdown.ts

@@ -52,6 +52,7 @@ export function useEmailCountdown(options: UseEmailCountdownOptions) {
     if (timer) {
       clearInterval(timer)
       timer = null
+      time.value = duration
     }
     ls.set(storageKey, '')
   }

+ 13 - 6
pages/ib/components/applyIbDialog.vue

@@ -101,7 +101,7 @@
   const props = defineProps({
     paramsType: {
       type: String,
-      default: 'vietnam'
+      default: '',
     },
     title: {
       type: String,
@@ -149,13 +149,14 @@
       loadCustomerList()
 
       // initCommissionTemplateData(29634)
+      console.log(props.detail)
       if (props.detail.id) {
         let params = {
           customerId: props.detail.id,
         }
         if (props.paramsType == 'vietnam') {
           params = {
-            agentId: 91886//props.params.id,
+            agentId: props.params.id,
           }
         }
         initCommissionTemplateData(params)
@@ -488,19 +489,25 @@
       }
 
       // 越南分配和新增代理
-      const res = props.paramsType === 'vietnam' ?await ibApi.saveVietnamPoints(params):await ibApi.agentApplyAddPoint(params)
+      const res = props.paramsType === 'vietnam' ? await ibApi.saveVietnamPoints(params) : await ibApi.agentApplyAddPoint(params)
 
       if (res.code == Code.StatusOK) {
-        uni.showToast({ title: res.msg || props.paramsType?t("Ib.Custom.SaveSuccess"):t('Ib.Custom.SubmitSuccess'), icon: 'success' })
+        uni.showToast({
+          title: res.msg || props.paramsType ? t('Ib.Custom.SaveSuccess') : t('Ib.Custom.SubmitSuccess'),
+          icon: 'success',
+        })
         closeDia()
         emit('confirm')
 
       } else {
-        uni.showToast({ title: res.msg || props.paramsType?t("Ib.Custom.SaveFailed"):t('Ib.Custom.SubmitFailed'), icon: 'none' })
+        uni.showToast({
+          title: res.msg || props.paramsType ? t('Ib.Custom.SaveFailed') : t('Ib.Custom.SubmitFailed'),
+          icon: 'none',
+        })
       }
     } catch (error) {
       console.error('新增代理失败或保存越南分配数据失败:', error)
-      uni.showToast({ title: props.paramsType?t("Ib.Custom.SaveFailed"):t('Ib.Custom.SubmitFailed'), icon: 'none' })
+      uni.showToast({ title: props.paramsType ? t('Ib.Custom.SaveFailed') : t('Ib.Custom.SubmitFailed'), icon: 'none' })
     }
   }
 </script>

+ 3 - 3
pages/ib/components/documentaryDialog.vue

@@ -24,8 +24,8 @@
               <checkbox value="1" />
               <view style="display: inline">
                 <text class="crm-cursor">{{ t('Documentary.AgentBackground.item3') }}</text>
-                <cwg-link type="pdf" title="Documentary.AgentBackground.item4" v-if="['cn', 'zhHant'].indexOf(lang) != -1"
-                  style="color: #4497ff" url="pdf/CopyTradeUserAgreementcn.paf"
+                <cwg-link type="pdf" title="Documentary.AgentBackground.item4" v-if="['cn', 'zhHant'].indexOf(local) != -1"
+                  style="color: #4497ff" url="pdf/CopyTradeUserAgreementcn.pdf"
                   target="_blank" />
                 <cwg-link style="color: #4497ff" title="Documentary.AgentBackground.item4" url="pdf/CopyTradeUserAgreement.pdf" target="_blank" v-else />
               </view>
@@ -64,7 +64,7 @@
     detail: { type: Object, default: () => ({}) },
   })
   const { Code, Host80 } = Config
-  const { t } = useI18n()
+  const { t ,local} = useI18n()
   const formData = ref({
     cId: '',
     permissionDisplay: '',

+ 1 - 1
pages/ib/components/linkDetailDialog.vue

@@ -1,6 +1,6 @@
 <template>
   <cwg-popup :title="t('Btn.Detail')" :visible="visible" @singleClick="closeDia" :footerType="'single'"
-             :singleBtnText="t('Btn.Close')" @close="closeDia">
+             :singleBtnText="t('Btn.Confirm')" @close="closeDia">
     <view class="dialog-content">
       <cwg-label-line-value
         v-for="(item, index) in items"

+ 1 - 1
pages/ib/components/pointDialog.vue

@@ -8,7 +8,7 @@
       <uni-forms :model="dialogForm" ref="formRef" label-width="0" class="dialogCheck_form dialog-account-adjust-form">
         <view class="form-section form-section-commission">
           <view class="section-title">
-            <cwg-icon name="crm-option" :size="24"></cwg-icon>
+            <cwg-icon name="crm-option" :size="24" color="#000"></cwg-icon>
             {{ t('Ib.Index.Spread5') }}
           </view>
           <view class="account-type-grid">

+ 436 - 429
pages/ib/const/recording.ts

@@ -1,440 +1,447 @@
-import { t } from '@/utils/i18n'
+import { useI18n } from 'vue-i18n'
 import { useFilters } from '../../../composables/useFilters'
-const { numberFormat } = useFilters()
+import { computed } from 'vue'
 
-export const columnList  = {
-  1: [
-    { prop: 'platform', label: t('Ib.Recording.Platform') },
-    {
-      prop: 'accountType', label: t('Ib.Recording.AccountType'),
-      type: 'tag',
-      tagMap: {
-        1: t('AccountType.ClassicAccount'),
-        2: t('AccountType.SeniorAccount'),
-        7: t('AccountType.StandardAccount'),
-        8: t('AccountType.CentAccount'),
-      },
-    },
-    { prop: 'currency', label: t('Ib.Recording.CurrencyType') },
-    {
-      prop: 'leverage', label: t('Ib.Recording.Lever'),
-      formatter: ({ row }) => row.leverage ? `1:${row.leverage}` : '--',
-    },
-    { prop: 'commission', label: t('Ib.Recording.Commission') },
-    { prop: 'addTime', label: t('Ib.Recording.ApplicationDate') },
-    {
-      prop: 'status', label: t('Ib.Recording.Status'),
-      type: 'tag',
-      tagMap: {
-        1: t('State.ToBeProcessed'),
-        2: t('State.Completed'),
-        3: t('State.Refused'),
-      },
-    },
-    {
-      prop: 'approveDesc', label: t('Ib.Recording.Note'),
-      slot: 'approveDesc',
-    },
-  ],
-  2: [
-    { prop: 'login', label: t('Ib.Recording.TradingAccount') },
-    {
-      prop: 'oldLeverage', label: t('Ib.Recording.OldLever'),
-      formatter: ({ row }) => row.oldLeverage ? `1:${row.oldLeverage}` : '--',
-    },
-    {
-      prop: 'newLeverage', label: t('Ib.Recording.NewLever'),
-      formatter: ({ row }) => row.newLeverage ? `1:${row.newLeverage}` : '--',
-    },
-    { prop: 'addTime', label: t('Ib.Recording.ApplicationDate') },
-    {
-      prop: 'status', label: t('Ib.Recording.Status'),
-      type: 'tag',
-      tagMap: {
-        1: t('State.ToBeProcessed'),
-        2: t('State.Completed'),
-        3: t('State.Refused'),
-      },
-    },
-    {
-      prop: 'approveDesc', label: t('Ib.Recording.Note'),
-      slot: 'approveDesc',
-    },
-  ],
-  3: [
-    { prop: 'ibNo', label: t('Ib.Recording.TransferAccounts') },
-    { prop: 'to', label: t('Ib.Recording.IntoAccount') },
-    { prop: 'currency', label: t('Ib.Recording.CurrencyType') },
-    {
-      prop: 'amount', label: t('Ib.Recording.Amount'),
-      formatter: ({ row }) => numberFormat(row.amount ?? 0),
-    },
-    { prop: 'addTime', label: t('Ib.Recording.ApplicationDate') },
-    {
-      prop: 'status', label: t('Ib.Recording.Status'),
-      type: 'tag',
-      tagMap: {
-        1: t('State.ToBeProcessed'),
-        2: t('State.Completed'),
-        3: t('State.Refused'),
-      },
-    },
-    {
-      prop: 'approveDesc', label: t('Ib.Recording.Note'),
-      slot: 'approveDesc',
-    },
-  ],
-  4: [
-    { prop: 'login', label: t('Ib.Recording.TradingAccount') },
-    {
-      prop: 'loginType', label: t('Ib.Recording.AccountType'),
-      type: 'tag',
-      tagMap: {
-        1: t('AccountType.ClassicAccount'),
-        2: t('AccountType.SeniorAccount'),
-        7: t('AccountType.StandardAccount'),
-        8: t('AccountType.CentAccount'),
-      },
-    },
-    { prop: 'title', label: t('Label.Describe') },
-    { prop: 'addTime', label: t('Ib.Recording.ApplicationDate') },
-    {
-      prop: 'status', label: t('Ib.Recording.Status'),
-      type: 'tag',
-      tagMap: {
-        1: t('State.ToBeProcessed'),
-        2: t('State.Completed'),
-        3: t('State.Refused'),
-      },
-    },
-    {
-      prop: 'approveDesc', label: t('Ib.Recording.Note'),
-      slot: 'approveDesc',
-    },
-  ],
-  5: [
-    { prop: 'login', label: t('Ib.Recording.TradingAccount') },
-    {
-      prop: 'oldPoint', label: t('Ib.Recording.OldPoint'),
-      formatter: ({ row }) => row.oldPoint || '0',
-    },
-    {
-      prop: 'newPoint', label: t('Ib.Recording.NewPoint'),
-      formatter: ({ row }) => row.newPoint || '0',
-    },
-    {
-      prop: 'oldHide', label: t('Drawer.Label.OldHide'),
-      formatter: ({ row }) => row.oldHide || '0',
-    },
-    {
-      prop: 'newHide', label: t('Drawer.Label.NewHide'),
-      formatter: ({ row }) => row.newHide || '0',
-    },
-    { prop: 'addTime', label: t('Ib.Recording.ApplicationDate') },
-    {
-      prop: 'status', label: t('Ib.Recording.Status'),
-      type: 'tag',
-      tagMap: {
-        1: t('State.ToBeProcessed'),
-        2: t('State.Completed'),
-        3: t('State.Refused'),
-      },
-    },
-    {
-      prop: 'approveDesc', label: t('Ib.Recording.Note'),
-      slot: 'approveDesc',
-    },
-  ],
-  6: [
-    { prop: 'login', label: t('Ib.Recording.TradingAccount') },
-    { prop: 'oldAgentIbNo', label: t('Ib.Recording.OldBelong') },
-    { prop: 'newAgentIbNo', label: t('Ib.Recording.NewBelong') },
-    { prop: 'addTime', label: t('Ib.Recording.ApplicationDate') },
-    {
-      prop: 'status', label: t('Ib.Recording.Status'),
-      type: 'tag',
-      tagMap: {
-        1: t('State.ToBeProcessed'),
-        2: t('State.Completed'),
-        3: t('State.Refused'),
-      },
-    },
-    { prop: 'approveDesc', label: t('Ib.Recording.Note') },
-  ],
-  7: [
-    { prop: 'typeName', label: t('Label.Type') },
-    { prop: 'newPercent', label: t('Label.NewPercentage') },
-    { prop: 'newClassicFx', label: t('Label.NewClassicForex') },
-    { prop: 'newVipFx', label: t('Label.NewAdvancedForex') },
-    { prop: 'newClassicCfd', label: t('Label.NewClassicCFD') },
-    { prop: 'newVipCfd', label: t('Label.NewAdvancedCFD') },
-    { prop: 'newComPointOne', label: t('Label.NewCommission10') },
-    { prop: 'newComPointTwo', label: t('Label.NewCommission20') },
-    { prop: 'newComPointThree', label: t('Label.NewCommission30') },
-    { prop: 'newInstantFx', label: t('Label.NewSpeedForex') },
-    { prop: 'newInstantMetal', label: t('Label.NewSpeedMetal') },
-  ],
-  8: [
-    { prop: 'cId', label: t('Label.CidAccount') },
-    { prop: 'ibNo', label: t('Label.IBAccount') },
-    {
-      prop: 'amount', label: t('Label.AmountMoney'),
-      formatter: ({ row }) => numberFormat(row.amount ?? '--'),
-    },
-    { prop: 'currency', label: t('Label.Currency') },
-    { prop: 'serial', label: t('Label.SerialNumber') },
-    {
-      prop: 'remitChannelName', label: t('Label.WithdrawalWay'),
-      slot: 'remitChannelName',
-    },
-    { prop: 'addTime', label: t('Label.ApplyTime') },
-    {
-      prop: 'status', label: t('Label.State'),
-      slot: 'status',
-    },
-    {
-      prop: 'approveDesc', label: t('Label.Note'),
-      slot: 'approveDesc',
-    },
-  ],
-  9: [
-    { prop: 'cId', label: t('Label.CidAccount') },
-    { prop: 'mam', label: 'MAM' },
-    { prop: 'platform', label: t('Label.Platform') },
-    { prop: 'sub', label: t('Ib.Settings.HangUndo') },
-    {
-      prop: 'type', label: t('Label.Type'),
-      type: 'tag',
-      tagMap: {
-        1: t('Ib.Settings.Hang'),
-        2: t('Ib.Settings.Undo'),
-      },
-    },
-    { prop: 'addTime', label: t('Label.ApplyTime') },
-    {
-      prop: 'status', label: t('Label.State'),
-      type: 'tag',
-      tagMap: {
-        1: t('State.ToBeProcessed'),
-        2: t('State.Completed'),
-        3: t('State.Refused'),
-      },
-    },
-    { prop: 'approveDesc', label: t('Label.Note'), slot: 'approveDesc' },
-  ],
-  10: [
-    { prop: 'withdrawLogin', label: t('Custom.Recording.TransferAccounts') },
-    { prop: 'depositLogin', label: t('Custom.Recording.IntoAccount') },
-    { prop: 'withdrawCurrency', label: t('Custom.Recording.CurrencyType') },
-    {
-      prop: 'withdrawAmount', label: t('Custom.Recording.Amount'),
-      formatter: ({ row }) => numberFormat(row.withdrawAmount ?? '--'),
-    },
-    { prop: 'addTime', label: t('Custom.Recording.ApplicationDate') },
-    {
-      prop: 'status', label: t('Custom.Recording.Status'),
-      formatter: ({ row }) => {
-        if (row.status == 1) {
-          return t('State.ToBeProcessed')
-        }
-        if (row.status == 2 && row.withdrawStatus == 2 &&
-          row.depositStatus == 2) {
-          return t('State.Completed')
-        }
-        if (row.status == 2 && (row.withdrawStatus == 1 ||
-          row.depositStatus == 1)) {
-          return t('State.InTheProcessing')
-        }
-        if (row.status == 3 || row.withdrawStatus == 3 || row.depositStatus == 3) {
-          return t('State.Refused')
-        }
-      },
-    },
-    { prop: 'approveDesc', label: t('Custom.Recording.Note'), slot: 'approveDesc' },
-  ],
-  11: [
-    { prop: 'cId', label: t('Label.CidAccount') },
-    { prop: 'pIbNo', label: t('Label.AttributionNumber') },
-    { prop: 'email', label: t('Label.Email') },
-    { prop: 'addTime', label: t('Label.ApplyTime') },
-    { prop: 'ownerId', label: t('Ib.PammManager.ownerId') },
-    { prop: 'accountId', label: t('Ib.PammManager.accountId') },
-    { prop: 'percent', label: t('Ib.PammManager.percent') },
-    {
-      prop: 'status', label: t('Label.State'),
-      type: 'tag',
-      tagMap: {
-        1: t('State.ToBeProcessed'),
-        2: t('State.Completed'),
-        3: t('State.Refused'),
-      },
-    },
-    { prop: 'approveDesc', label: t('Label.Descr'), slot: 'approveDesc' },
-  ],
-  12: [
-    { prop: 'cId', label: t('Label.CidAccount') },
-    { prop: 'pIbNo', label: t('Label.AttributionNumber') },
-    { prop: 'ownerId', label: t('Ib.PammManager.ownerId') },
-    { prop: 'accountId', label: t('Ib.PammManager.accountId') },
-    { prop: 'percent', label: t('Ib.PammManager.percent') },
-    { prop: 'platform', label: t('Label.Platform') },
-    { prop: 'addTime', label: t('Label.ApplyTime') },
-    { prop: 'sub', label: t('Label.ApplicationAccount') },
-    {
-      prop: 'type', label: t('Label.Type'),
-      type: 'tag',
-      tagMap: {
-        1: t('Ib.Settings.Hang'),
-        2: t('Ib.Settings.Undo'),
-      },
-    },
-    {
-      prop: 'status', label: t('Label.State'),
-      type: 'tag',
-      tagMap: {
-        1: t('State.ToBeProcessed'),
-        2: t('State.Completed'),
-        3: t('State.Refused'),
-      },
-    },
-    { prop: 'approveDesc', label: t('Label.Descr'), slot: 'approveDesc' },
-    { prop: 'approveTime', label: t('Label.ProcessingDate') },
-  ],
-  13: [
-    { prop: 'withdrawIbNo', label: t('AmountLabel.item4') },
-    { prop: 'depositIbNo', label: t('AmountLabel.item5') },
-    {
-      prop: 'amount', label: t('Ib.Recording.Amount'),
-      formatter: ({ row }) => numberFormat(row.amount ?? '--'),
-    },
-    { prop: 'currency', label: t('Ib.Recording.CurrencyType') },
-    { prop: 'addTime', label: t('Ib.Recording.ApplicationDate') },
-    { prop: 'approveDesc', label: t('Ib.Recording.Note'), slot: 'approveDesc' },
-  ],
-}
+export const useRecordingConst = () => {
+  const { t } = useI18n()
+  const { numberFormat } = useFilters()
 
-export const mobileList  = {
-  1: [
-    { prop: 'platform', label: t('Ib.Recording.Platform') },
-    {
-      prop: 'accountType', label: t('Ib.Recording.AccountType'),
-      type: 'tag',
-      tagMap: {
-        1: t('AccountType.ClassicAccount'),
-        2: t('AccountType.SeniorAccount'),
-        7: t('AccountType.StandardAccount'),
-        8: t('AccountType.CentAccount'),
-      },
-    },
-    { prop: 'currency', label: t('Ib.Recording.CurrencyType') },
+  const columnList = computed(() => ({
+    1: [
+      { prop: 'platform', label: t('Ib.Recording.Platform') },
+      {
+        prop: 'accountType', label: t('Ib.Recording.AccountType'),
+        type: 'tag',
+        tagMap: {
+          1: t('AccountType.ClassicAccount'),
+          2: t('AccountType.SeniorAccount'),
+          7: t('AccountType.StandardAccount'),
+          8: t('AccountType.CentAccount'),
+        },
+      },
+      { prop: 'currency', label: t('Ib.Recording.CurrencyType') },
+      {
+        prop: 'leverage', label: t('Ib.Recording.Lever'),
+        formatter: ({ row }) => row.leverage ? `1:${row.leverage}` : '--',
+      },
+      { prop: 'commission', label: t('Ib.Recording.Commission') },
+      { prop: 'addTime', label: t('Ib.Recording.ApplicationDate') },
+      {
+        prop: 'status', label: t('Ib.Recording.Status'),
+        type: 'tag',
+        tagMap: {
+          1: t('State.ToBeProcessed'),
+          2: t('State.Completed'),
+          3: t('State.Refused'),
+        },
+      },
+      {
+        prop: 'approveDesc', label: t('Ib.Recording.Note'),
+        type: 'note'
+      },
+    ],
+    2: [
+      { prop: 'login', label: t('Ib.Recording.TradingAccount') },
+      {
+        prop: 'oldLeverage', label: t('Ib.Recording.OldLever'),
+        formatter: ({ row }) => row.oldLeverage ? `1:${row.oldLeverage}` : '--',
+      },
+      {
+        prop: 'newLeverage', label: t('Ib.Recording.NewLever'),
+        formatter: ({ row }) => row.newLeverage ? `1:${row.newLeverage}` : '--',
+      },
+      { prop: 'addTime', label: t('Ib.Recording.ApplicationDate') },
+      {
+        prop: 'status', label: t('Ib.Recording.Status'),
+        type: 'tag',
+        tagMap: {
+          1: t('State.ToBeProcessed'),
+          2: t('State.Completed'),
+          3: t('State.Refused'),
+        },
+      },
+      {
+        prop: 'approveDesc', label: t('Ib.Recording.Note'),
+        type: 'note'
+      },
+    ],
+    3: [
+      { prop: 'ibNo', label: t('Ib.Recording.TransferAccounts') },
+      { prop: 'to', label: t('Ib.Recording.IntoAccount') },
+      { prop: 'currency', label: t('Ib.Recording.CurrencyType') },
+      {
+        prop: 'amount', label: t('Ib.Recording.Amount'),
+        formatter: ({ row }) => numberFormat(row.amount ?? 0),
+      },
+      { prop: 'addTime', label: t('Ib.Recording.ApplicationDate') },
+      {
+        prop: 'status', label: t('Ib.Recording.Status'),
+        type: 'tag',
+        tagMap: {
+          1: t('State.ToBeProcessed'),
+          2: t('State.Completed'),
+          3: t('State.Refused'),
+        },
+      },
+      {
+        prop: 'approveDesc', label: t('Ib.Recording.Note'),
+        type: 'note'
+      },
+    ],
+    4: [
+      { prop: 'login', label: t('Ib.Recording.TradingAccount') },
+      {
+        prop: 'loginType', label: t('Ib.Recording.AccountType'),
+        type: 'tag',
+        tagMap: {
+          1: t('AccountType.ClassicAccount'),
+          2: t('AccountType.SeniorAccount'),
+          7: t('AccountType.StandardAccount'),
+          8: t('AccountType.CentAccount'),
+        },
+      },
+      { prop: 'title', label: t('Label.Describe') },
+      { prop: 'addTime', label: t('Ib.Recording.ApplicationDate') },
+      {
+        prop: 'status', label: t('Ib.Recording.Status'),
+        type: 'tag',
+        tagMap: {
+          1: t('State.ToBeProcessed'),
+          2: t('State.Completed'),
+          3: t('State.Refused'),
+        },
+      },
+      {
+        prop: 'approveDesc', label: t('Ib.Recording.Note'),
+        type: 'note'
+      },
+    ],
+    5: [
+      { prop: 'login', label: t('Ib.Recording.TradingAccount') },
+      {
+        prop: 'oldPoint', label: t('Ib.Recording.OldPoint'),
+        formatter: ({ row }) => row.oldPoint || '0',
+      },
+      {
+        prop: 'newPoint', label: t('Ib.Recording.NewPoint'),
+        formatter: ({ row }) => row.newPoint || '0',
+      },
+      {
+        prop: 'oldHide', label: t('Drawer.Label.OldHide'),
+        formatter: ({ row }) => row.oldHide || '0',
+      },
+      {
+        prop: 'newHide', label: t('Drawer.Label.NewHide'),
+        formatter: ({ row }) => row.newHide || '0',
+      },
+      { prop: 'addTime', label: t('Ib.Recording.ApplicationDate') },
+      {
+        prop: 'status', label: t('Ib.Recording.Status'),
+        type: 'tag',
+        tagMap: {
+          1: t('State.ToBeProcessed'),
+          2: t('State.Completed'),
+          3: t('State.Refused'),
+        },
+      },
+      {
+        prop: 'approveDesc', label: t('Ib.Recording.Note'),
+        type: 'note'
+      },
+    ],
+    6: [
+      { prop: 'login', label: t('Ib.Recording.TradingAccount') },
+      { prop: 'oldAgentIbNo', label: t('Ib.Recording.OldBelong') },
+      { prop: 'newAgentIbNo', label: t('Ib.Recording.NewBelong') },
+      { prop: 'addTime', label: t('Ib.Recording.ApplicationDate') },
+      {
+        prop: 'status', label: t('Ib.Recording.Status'),
+        type: 'tag',
+        tagMap: {
+          1: t('State.ToBeProcessed'),
+          2: t('State.Completed'),
+          3: t('State.Refused'),
+        },
+      },
+      { prop: 'approveDesc', label: t('Ib.Recording.Note') },
+    ],
+    7: [
+      { prop: 'typeName', label: t('Label.Type') },
+      { prop: 'newPercent', label: t('Label.NewPercentage') },
+      { prop: 'newClassicFx', label: t('Label.NewClassicForex') },
+      { prop: 'newVipFx', label: t('Label.NewAdvancedForex') },
+      { prop: 'newClassicCfd', label: t('Label.NewClassicCFD') },
+      { prop: 'newVipCfd', label: t('Label.NewAdvancedCFD') },
+      { prop: 'newComPointOne', label: t('Label.NewCommission10') },
+      { prop: 'newComPointTwo', label: t('Label.NewCommission20') },
+      { prop: 'newComPointThree', label: t('Label.NewCommission30') },
+      { prop: 'newInstantFx', label: t('Label.NewSpeedForex') },
+      { prop: 'newInstantMetal', label: t('Label.NewSpeedMetal') },
+    ],
+    8: [
+      { prop: 'cId', label: t('Label.CidAccount') },
+      { prop: 'ibNo', label: t('Label.IBAccount') },
+      {
+        prop: 'amount', label: t('Label.AmountMoney'),
+        formatter: ({ row }) => numberFormat(row.amount ?? '--'),
+      },
+      { prop: 'currency', label: t('Label.Currency') },
+      { prop: 'serial', label: t('Label.SerialNumber') },
+      {
+        prop: 'remitChannelName', label: t('Label.WithdrawalWay'),
+        slot: 'remitChannelName',
+      },
+      { prop: 'addTime', label: t('Label.ApplyTime') },
+      {
+        prop: 'status', label: t('Label.State'),
+        slot: 'status',
+      },
+      {
+        prop: 'approveDesc', label: t('Label.Note'),
+        type: 'note'
+      },
+    ],
+    9: [
+      { prop: 'cId', label: t('Label.CidAccount') },
+      { prop: 'mam', label: 'MAM' },
+      { prop: 'platform', label: t('Label.Platform') },
+      { prop: 'sub', label: t('Ib.Settings.HangUndo') },
+      {
+        prop: 'type', label: t('Label.Type'),
+        type: 'tag',
+        tagMap: {
+          1: t('Ib.Settings.Hang'),
+          2: t('Ib.Settings.Undo'),
+        },
+      },
+      { prop: 'addTime', label: t('Label.ApplyTime') },
+      {
+        prop: 'status', label: t('Label.State'),
+        type: 'tag',
+        tagMap: {
+          1: t('State.ToBeProcessed'),
+          2: t('State.Completed'),
+          3: t('State.Refused'),
+        },
+      },
+      { prop: 'approveDesc', label: t('Label.Note'), slot: 'approveDesc' },
+    ],
+    10: [
+      { prop: 'withdrawLogin', label: t('Custom.Recording.TransferAccounts') },
+      { prop: 'depositLogin', label: t('Custom.Recording.IntoAccount') },
+      { prop: 'withdrawCurrency', label: t('Custom.Recording.CurrencyType') },
+      {
+        prop: 'withdrawAmount', label: t('Custom.Recording.Amount'),
+        formatter: ({ row }) => numberFormat(row.withdrawAmount ?? '--'),
+      },
+      { prop: 'addTime', label: t('Custom.Recording.ApplicationDate') },
+      {
+        prop: 'status', label: t('Custom.Recording.Status'),
+        formatter: ({ row }) => {
+          if (row.status == 1) {
+            return t('State.ToBeProcessed')
+          }
+          if (row.status == 2 && row.withdrawStatus == 2 &&
+            row.depositStatus == 2) {
+            return t('State.Completed')
+          }
+          if (row.status == 2 && (row.withdrawStatus == 1 ||
+            row.depositStatus == 1)) {
+            return t('State.InTheProcessing')
+          }
+          if (row.status == 3 || row.withdrawStatus == 3 || row.depositStatus == 3) {
+            return t('State.Refused')
+          }
+        },
+      },
+      { prop: 'approveDesc', label: t('Custom.Recording.Note'),  type: 'note' },
+    ],
+    11: [
+      { prop: 'cId', label: t('Label.CidAccount') },
+      { prop: 'pIbNo', label: t('Label.AttributionNumber') },
+      { prop: 'email', label: t('Label.Email') },
+      { prop: 'addTime', label: t('Label.ApplyTime') },
+      { prop: 'ownerId', label: t('Ib.PammManager.ownerId') },
+      { prop: 'accountId', label: t('Ib.PammManager.accountId') },
+      { prop: 'percent', label: t('Ib.PammManager.percent') },
+      {
+        prop: 'status', label: t('Label.State'),
+        type: 'tag',
+        tagMap: {
+          1: t('State.ToBeProcessed'),
+          2: t('State.Completed'),
+          3: t('State.Refused'),
+        },
+      },
+      { prop: 'approveDesc', label: t('Label.Descr'),  type: 'note' },
+    ],
+    12: [
+      { prop: 'cId', label: t('Label.CidAccount') },
+      { prop: 'pIbNo', label: t('Label.AttributionNumber') },
+      { prop: 'ownerId', label: t('Ib.PammManager.ownerId') },
+      { prop: 'accountId', label: t('Ib.PammManager.accountId') },
+      { prop: 'percent', label: t('Ib.PammManager.percent') },
+      { prop: 'platform', label: t('Label.Platform') },
+      { prop: 'addTime', label: t('Label.ApplyTime') },
+      { prop: 'sub', label: t('Label.ApplicationAccount') },
+      {
+        prop: 'type', label: t('Label.Type'),
+        type: 'tag',
+        tagMap: {
+          1: t('Ib.Settings.Hang'),
+          2: t('Ib.Settings.Undo'),
+        },
+      },
+      {
+        prop: 'status', label: t('Label.State'),
+        type: 'tag',
+        tagMap: {
+          1: t('State.ToBeProcessed'),
+          2: t('State.Completed'),
+          3: t('State.Refused'),
+        },
+      },
+      { prop: 'approveDesc', label: t('Label.Descr'), type: 'note' },
+      { prop: 'approveTime', label: t('Label.ProcessingDate') },
+    ],
+    13: [
+      { prop: 'withdrawIbNo', label: t('AmountLabel.item4') },
+      { prop: 'depositIbNo', label: t('AmountLabel.item5') },
+      {
+        prop: 'amount', label: t('Ib.Recording.Amount'),
+        formatter: ({ row }) => numberFormat(row.amount ?? '--'),
+      },
+      { prop: 'currency', label: t('Ib.Recording.CurrencyType') },
+      { prop: 'addTime', label: t('Ib.Recording.ApplicationDate') },
+      { prop: 'approveDesc', label: t('Ib.Recording.Note'),  type: 'note' },
+    ],
+  }))
 
-  ],
-  2: [
-    { prop: 'login', label: t('Ib.Recording.TradingAccount') },
-    {
-      prop: 'oldLeverage', label: t('Ib.Recording.OldLever'),
-      formatter: ({ row }) => row.oldLeverage ? `1:${row.oldLeverage}` : '--',
-    },
-    {
-      prop: 'newLeverage', label: t('Ib.Recording.NewLever'),
-      formatter: ({ row }) => row.newLeverage ? `1:${row.newLeverage}` : '--',
-    },
-  ],
-  3: [
-    { prop: 'ibNo', label: t('Ib.Recording.TransferAccounts') },
-    { prop: 'to', label: t('Ib.Recording.IntoAccount') },
-    { prop: 'currency', label: t('Ib.Recording.CurrencyType') },
+  const mobileList = computed(() => ({
+    1: [
+      { prop: 'platform', label: t('Ib.Recording.Platform') },
+      {
+        prop: 'accountType', label: t('Ib.Recording.AccountType'),
+        type: 'tag',
+        tagMap: {
+          1: t('AccountType.ClassicAccount'),
+          2: t('AccountType.SeniorAccount'),
+          7: t('AccountType.StandardAccount'),
+          8: t('AccountType.CentAccount'),
+        },
+      },
+      { prop: 'currency', label: t('Ib.Recording.CurrencyType') },
 
-  ],
-  4: [
-    { prop: 'login', label: t('Ib.Recording.TradingAccount') },
-    {
-      prop: 'loginType', label: t('Ib.Recording.AccountType'),
-      type: 'tag',
-      tagMap: {
-        1: t('AccountType.ClassicAccount'),
-        2: t('AccountType.SeniorAccount'),
-        7: t('AccountType.StandardAccount'),
-        8: t('AccountType.CentAccount'),
-      },
-    },
-    { prop: 'title', label: t('Label.Describe') },
-  ],
-  5: [
-    { prop: 'login', label: t('Ib.Recording.TradingAccount') },
-    {
-      prop: 'oldPoint', label: t('Ib.Recording.OldPoint'),
-      formatter: ({ row }) => row.oldPoint || '0',
-    },
-    {
-      prop: 'newPoint', label: t('Ib.Recording.NewPoint'),
-      formatter: ({ row }) => row.newPoint || '0',
-    },
-  ],
-  6: [
-    { prop: 'login', label: t('Ib.Recording.TradingAccount') },
-    { prop: 'oldAgentIbNo', label: t('Ib.Recording.OldBelong') },
-    { prop: 'newAgentIbNo', label: t('Ib.Recording.NewBelong') },
-  ],
-  7: [
-    { prop: 'typeName', label: t('Label.Type') },
-    { prop: 'newPercent', label: t('Label.NewPercentage') },
-    { prop: 'newClassicFx', label: t('Label.NewClassicForex') },
-  ],
-  8: [
-    { prop: 'cId', label: t('Label.CidAccount') },
-    { prop: 'ibNo', label: t('Label.IBAccount') },
-    {
-      prop: 'amount', label: t('Label.AmountMoney'),
-      formatter: ({ row }) => numberFormat(row.amount ?? '--'),
-    },
+    ],
+    2: [
+      { prop: 'login', label: t('Ib.Recording.TradingAccount') },
+      {
+        prop: 'oldLeverage', label: t('Ib.Recording.OldLever'),
+        formatter: ({ row }) => row.oldLeverage ? `1:${row.oldLeverage}` : '--',
+      },
+      {
+        prop: 'newLeverage', label: t('Ib.Recording.NewLever'),
+        formatter: ({ row }) => row.newLeverage ? `1:${row.newLeverage}` : '--',
+      },
+    ],
+    3: [
+      { prop: 'ibNo', label: t('Ib.Recording.TransferAccounts') },
+      { prop: 'to', label: t('Ib.Recording.IntoAccount') },
+      { prop: 'currency', label: t('Ib.Recording.CurrencyType') },
+
+    ],
+    4: [
+      { prop: 'login', label: t('Ib.Recording.TradingAccount') },
+      {
+        prop: 'loginType', label: t('Ib.Recording.AccountType'),
+        type: 'tag',
+        tagMap: {
+          1: t('AccountType.ClassicAccount'),
+          2: t('AccountType.SeniorAccount'),
+          7: t('AccountType.StandardAccount'),
+          8: t('AccountType.CentAccount'),
+        },
+      },
+      { prop: 'title', label: t('Label.Describe') },
+    ],
+    5: [
+      { prop: 'login', label: t('Ib.Recording.TradingAccount') },
+      {
+        prop: 'oldPoint', label: t('Ib.Recording.OldPoint'),
+        formatter: ({ row }) => row.oldPoint || '0',
+      },
+      {
+        prop: 'newPoint', label: t('Ib.Recording.NewPoint'),
+        formatter: ({ row }) => row.newPoint || '0',
+      },
+    ],
+    6: [
+      { prop: 'login', label: t('Ib.Recording.TradingAccount') },
+      { prop: 'oldAgentIbNo', label: t('Ib.Recording.OldBelong') },
+      { prop: 'newAgentIbNo', label: t('Ib.Recording.NewBelong') },
+    ],
+    7: [
+      { prop: 'typeName', label: t('Label.Type') },
+      { prop: 'newPercent', label: t('Label.NewPercentage') },
+      { prop: 'newClassicFx', label: t('Label.NewClassicForex') },
+    ],
+    8: [
+      { prop: 'cId', label: t('Label.CidAccount') },
+      { prop: 'ibNo', label: t('Label.IBAccount') },
+      {
+        prop: 'amount', label: t('Label.AmountMoney'),
+        formatter: ({ row }) => numberFormat(row.amount ?? '--'),
+      },
 
-  ],
-  9: [
-    { prop: 'cId', label: t('Label.CidAccount') },
-    { prop: 'mam', label: 'MAM' },
-    { prop: 'platform', label: t('Label.Platform') },
-  ],
-  10: [
-    { prop: 'withdrawLogin', label: t('Custom.Recording.TransferAccounts') },
-    { prop: 'depositLogin', label: t('Custom.Recording.IntoAccount') },
-    { prop: 'withdrawCurrency', label: t('Custom.Recording.CurrencyType') },
-  ],
-  11: [
-    { prop: 'cId', label: t('Label.CidAccount') },
-    { prop: 'pIbNo', label: t('Label.AttributionNumber') },
-    { prop: 'email', label: t('Label.Email') },
-  ],
-  12: [
-    { prop: 'cId', label: t('Label.CidAccount') },
-    { prop: 'pIbNo', label: t('Label.AttributionNumber') },
-    { prop: 'ownerId', label: t('Ib.PammManager.ownerId') },
+    ],
+    9: [
+      { prop: 'cId', label: t('Label.CidAccount') },
+      { prop: 'mam', label: 'MAM' },
+      { prop: 'platform', label: t('Label.Platform') },
+    ],
+    10: [
+      { prop: 'withdrawLogin', label: t('Custom.Recording.TransferAccounts') },
+      { prop: 'depositLogin', label: t('Custom.Recording.IntoAccount') },
+      { prop: 'withdrawCurrency', label: t('Custom.Recording.CurrencyType') },
+    ],
+    11: [
+      { prop: 'cId', label: t('Label.CidAccount') },
+      { prop: 'pIbNo', label: t('Label.AttributionNumber') },
+      { prop: 'email', label: t('Label.Email') },
+    ],
+    12: [
+      { prop: 'cId', label: t('Label.CidAccount') },
+      { prop: 'pIbNo', label: t('Label.AttributionNumber') },
+      { prop: 'ownerId', label: t('Ib.PammManager.ownerId') },
 
-  ],
-  13: [
-    { prop: 'withdrawIbNo', label: t('AmountLabel.item4') },
-    { prop: 'depositIbNo', label: t('AmountLabel.item5') },
-    {
-      prop: 'amount', label: t('Ib.Recording.Amount'),
-      formatter: ({ row }) => numberFormat(row.amount ?? '--'),
-    },
-  ],
-}
+    ],
+    13: [
+      { prop: 'withdrawIbNo', label: t('AmountLabel.item4') },
+      { prop: 'depositIbNo', label: t('AmountLabel.item5') },
+      {
+        prop: 'amount', label: t('Ib.Recording.Amount'),
+        formatter: ({ row }) => numberFormat(row.amount ?? '--'),
+      },
+    ],
+  }))
 
 
 // api 列表
-export const apiList = {
-  1: 'mamApplyList',
-  2: 'mamLeverageApplyList',
-  3: 'agentBalanceTransferList',
-  4: 'CustomRecordAccount',
-  5: 'customCommissionApplyList',
-  6: 'agentBelongChangeList',
-  7: 'agentPointChangeList',
-  8: 'agentWithdrawList',
-  9: 'mamSubsApplyRecording',
-  10: 'agentTransferList',
-  11: 'mamApplyList',
-  12: 'mamSubsApplyRecording',
-  13: 'agentBalanceCommissionSearchList',
+  const apiList = computed(() => ({
+    1: 'mamApplyList',
+    2: 'mamLeverageApplyList',
+    3: 'agentBalanceTransferList',
+    4: 'CustomRecordAccount',
+    5: 'customCommissionApplyList',
+    6: 'agentBelongChangeList',
+    7: 'agentPointChangeList',
+    8: 'agentWithdrawList',
+    9: 'mamSubsApplyRecording',
+    10: 'agentTransferList',
+    11: 'mamApplyList',
+    12: 'mamSubsApplyRecording',
+    13: 'agentBalanceCommissionSearchList',
+  }))
+
+  return { columnList, mobileList, apiList }
 }

+ 42 - 36
pages/ib/const/report.ts

@@ -1,22 +1,45 @@
-import { t } from '@/utils/i18n'
+import { useI18n } from 'vue-i18n'
 import { isAfterJuly28 } from '@/utils/dateUtils'
 import { useFilters } from '../../../composables/useFilters'
+import { computed } from 'vue'
 
-const { numberFormat } = useFilters()
+export const useReportConst = () => {
+  const { t } = useI18n()
+  const { numberFormat } = useFilters()
 
-export const platformOptions = [
-  { text: 'MT4', value: 'MT4' },
-  { text: 'MT5', value: 'MT5' },
-]
-export const customTypeList = [
-  { text: t('AccountType.ClassicAccount'), value: 1 },
-  { text: t('AccountType.ClassicAccount'), value: 2 },
-  !isAfterJuly28 ? { text: t('AccountType.ClassicAccount'), value: 3 } : '',
-  { text: t('AccountType.ClassicAccount'), value: 7 },
-  { text: t('AccountType.ClassicAccount'), value: 8 },
-].filter((v) => !!v)
+  const groupCurrency1 = (type: string) => {
+    if (type == 'GBP') return '£'
+    if (type == 'USD') return '$'
+    if (type == 'EUR') return '€'
+    if (type == 'USC') return '¢'
+    return '$'
+  }
 
-export const columnList = {
+  const groupTypeName = (type: string | number) => {
+    if (type == '1') return t('AccountType.ClassicAccount')
+    if (type == '2') return t('AccountType.SeniorAccount')
+    if (type == '3') return isAfterJuly28() ? '--' : t('AccountType.AgencyAccount')
+    if (type == '5') return t('AccountType.SpeedAccount')
+    if (type == '6') return t('AccountType.SpeedAccount')
+    if (type == '7') return t('AccountType.StandardAccount')
+    if (type == '8') return t('AccountType.CentAccount')
+    return '--'
+  }
+
+  const platformOptions = [
+    { text: 'MT4', value: 'MT4' },
+    { text: 'MT5', value: 'MT5' },
+  ]
+
+  const customTypeList = computed(() => [
+    { text: t('AccountType.ClassicAccount'), value: 1 },
+    { text: t('AccountType.ClassicAccount'), value: 2 },
+    !isAfterJuly28() ? { text: t('AccountType.ClassicAccount'), value: 3 } : '',
+    { text: t('AccountType.ClassicAccount'), value: 7 },
+    { text: t('AccountType.ClassicAccount'), value: 8 },
+  ].filter((v) => !!v))
+
+  const columnList = computed(() => ({
   '1': [
     { prop: 'ibNo', label: t('Label.AttributionNumber') },
     { prop: 'login', label: t('Label.TradingAccount') },
@@ -392,29 +415,9 @@ export const columnList = {
     { prop: 'ibNo', label: t('Label.AgentNumber') },
     { prop: 'platform', label: t('Label.Platform') },
   ],
-}
-
-const groupCurrency1 = (type: string) => {
-  if (type == 'GBP') return '£'
-  if (type == 'USD') return '$'
-  if (type == 'EUR') return '€'
-  if (type == 'USC') return '¢'
-  return '$'
-}
-
-const groupTypeName = (type: string | number) => {
-  if (type == '1') return t('AccountType.ClassicAccount')
-  if (type == '2') return t('AccountType.SeniorAccount')
-  if (type == '3') return isAfterJuly28() ? '--' : t('AccountType.AgencyAccount')
-  if (type == '5') return t('AccountType.SpeedAccount')
-  if (type == '6') return t('AccountType.SpeedAccount')
-  if (type == '7') return t('AccountType.StandardAccount')
-  if (type == '8') return t('AccountType.CentAccount')
-  return '--'
-}
+}))
 
-
-export const mobileList = {
+const mobileList = computed(() => ({
   '1': [
     { prop: 'ibNo', label: t('Label.AttributionNumber') },
     { prop: 'login', label: t('Label.TradingAccount') },
@@ -485,4 +488,7 @@ export const mobileList = {
     { prop: 'ticket', label: t('Label.OrderNumber') },
     { prop: 'login', label: t('Label.TradingAccount') },
   ],
+}))
+
+  return { columnList, mobileList, platformOptions, customTypeList, groupCurrency1, groupTypeName }
 }

+ 62 - 39
pages/ib/customer.vue

@@ -6,21 +6,27 @@
       <cwg-match-media :max-width="991">
         <view class="search-content mobile-search-content">
           <view class="search-tabs">
-            <view class="crm-cursor tab-item" :class="{ active: search.belongsType == 1 }" @click="chooseBelongsType(1)">
+            <view class="crm-cursor tab-item" :class="{ active: search.belongsType == 1 }"
+                  @click="chooseBelongsType(1)">
               {{ t('Ib.Custom.Unverified') }}
-              <view v-if="statistics.unverifiedNum !== undefined" class="count-badge">({{ statistics.unverifiedNum }})</view>
+              <view v-if="statistics.unverifiedNum !== undefined" class="count-badge">({{ statistics.unverifiedNum }})
+              </view>
             </view>
-            <view class="crm-cursor tab-item" :class="{ active: search.belongsType == 2 }" @click="chooseBelongsType(2)">
+            <view class="crm-cursor tab-item" :class="{ active: search.belongsType == 2 }"
+                  @click="chooseBelongsType(2)">
               {{ t('Ib.Custom.UnDeposit') }}
-              <view v-if="statistics.unDepositNum !== undefined" class="count-badge">({{ statistics.unDepositNum }})</view>
+              <view v-if="statistics.unDepositNum !== undefined" class="count-badge">({{ statistics.unDepositNum }})
+              </view>
             </view>
-            <view class="crm-cursor tab-item" :class="{ active: search.belongsType == 3 }" @click="chooseBelongsType(3)">
+            <view class="crm-cursor tab-item" :class="{ active: search.belongsType == 3 }"
+                  @click="chooseBelongsType(3)">
               {{ t('Ib.Custom.Deposited') }}
               <view v-if="statistics.depositNum !== undefined" class="count-badge">({{ statistics.depositNum }})</view>
             </view>
           </view>
           <view class="search-bar">
-            <cwg-complex-search :fields="filterFields" v-model="searchParams" @search="handleSearch" @reset="handleReset" />
+            <cwg-complex-search :fields="filterFields" v-model="search" @search="handleSearch"
+                                @reset="handleReset" />
           </view>
         </view>
       </cwg-match-media>
@@ -29,18 +35,24 @@
       <cwg-match-media :min-width="992">
         <view class="search-content pc-search-content">
           <view class="search-bar">
-            <cwg-complex-search :fields="filterFields" v-model="searchParams" @search="handleSearch" @reset="handleReset" />
+            <cwg-complex-search :fields="filterFields" v-model="search" @search="handleSearch"
+                                @reset="handleReset" />
           </view>
           <view class="search-tabs">
-            <view class="crm-cursor tab-item" :class="{ active: search.belongsType == 1 }" @click="chooseBelongsType(1)">
+            <view class="crm-cursor tab-item" :class="{ active: search.belongsType == 1 }"
+                  @click="chooseBelongsType(1)">
               {{ t('Ib.Custom.Unverified') }}
-              <view v-if="statistics.unverifiedNum !== undefined" class="count-badge">({{ statistics.unverifiedNum }})</view>
+              <view v-if="statistics.unverifiedNum !== undefined" class="count-badge">({{ statistics.unverifiedNum }})
+              </view>
             </view>
-            <view class="crm-cursor tab-item" :class="{ active: search.belongsType == 2 }" @click="chooseBelongsType(2)">
+            <view class="crm-cursor tab-item" :class="{ active: search.belongsType == 2 }"
+                  @click="chooseBelongsType(2)">
               {{ t('Ib.Custom.UnDeposit') }}
-              <view v-if="statistics.unDepositNum !== undefined" class="count-badge">({{ statistics.unDepositNum }})</view>
+              <view v-if="statistics.unDepositNum !== undefined" class="count-badge">({{ statistics.unDepositNum }})
+              </view>
             </view>
-            <view class="crm-cursor tab-item" :class="{ active: search.belongsType == 3 }" @click="chooseBelongsType(3)">
+            <view class="crm-cursor tab-item" :class="{ active: search.belongsType == 3 }"
+                  @click="chooseBelongsType(3)">
               {{ t('Ib.Custom.Deposited') }}
               <view v-if="statistics.depositNum !== undefined" class="count-badge">({{ statistics.depositNum }})</view>
             </view>
@@ -58,35 +70,35 @@
         :showPagination="true"
       >
         <template #action="{ row }">
-          <cwg-dropdown :menu-list="menuList(row)" @menuClick="handleMenuClick">
-            <view class="pc-header-btn">
-              <cwg-icon name="crm-ellipsis" :size="24" />
-            </view>
-          </cwg-dropdown>
+          <view class="action-btn">
+            <cwg-dropdown :menu-list="menuList(row)" @menuClick="handleMenuClick">
+              <view class="pc-header-btn">
+                <cwg-icon name="crm-ellipsis" :size="24" color="#000"/>
+              </view>
+            </cwg-dropdown>
+          </view>
         </template>
       </cwg-tabel>
       <!-- 跟单全局设置     -->
       <DocumentaryDialog :visible="docVisible" :detail="formInfoRow" @close="closeDoc" @confirm="confirmDoc" />
       <!-- 开户调整     -->
       <PointDialog :visible="pointVisible" :detail="pointForm" @close="closePoint" @confirm="confirmPoint" />
-      <ApplyIbDialog :visible="applyVisible" :tableData="applyForm" @close="closeApply" @confirm="confirmApply" />
+      <ApplyIbDialog :visible="applyVisible" :detail="applyForm" @close="closeApply" @confirm="confirmApply" />
     </view>
   </cwg-page-wrapper>
 </template>
 
 <script setup lang="ts">
-  import { computed, ref, onMounted } from 'vue'
+  import { computed, ref, onMounted, nextTick } from 'vue'
   import { useI18n } from 'vue-i18n'
   import Config from '@/config/index'
 
   const { t, locale } = useI18n()
   import { customApi } from '@/service/custom'
-  import { lang } from '@/composables/config'
   import { ibApi } from '@/service/ib'
   import DocumentaryDialog from '@/pages/ib/components/documentaryDialog.vue'
   import PointDialog from '@/pages/ib/components/pointDialog.vue'
   import ApplyIbDialog from '@/pages/ib/components/applyIbDialog.vue'
-  import { nextTick } from 'vue'
 
   const { Code } = Config
   const statistics = ref({
@@ -95,7 +107,6 @@
     depositNum: 0,
   })
 
-  const searchParams = ref({})
   const search = ref({
     'name': '',
     'email': '',
@@ -103,11 +114,17 @@
     // 1:未实名 2:未入金 3:已入金
     belongsType: null,
   })
-  
+
   const filterFields = [
     { key: 'cId', type: 'input', label: 'CID', placeholder: 'CID', defaultValue: '' },
-    { key: 'name', type: 'input', label: t('Ib.Custom.NameLabel'), placeholder: t('Ib.Custom.NameLabel'), defaultValue: '' },
-    { key: 'email', type: 'input', label: t('Label.Email'), placeholder: t('Label.Email'), defaultValue: '' }
+    {
+      key: 'name',
+      type: 'input',
+      label: t('Ib.Custom.NameLabel'),
+      placeholder: t('Ib.Custom.NameLabel'),
+      defaultValue: '',
+    },
+    { key: 'email', type: 'input', label: t('Label.Email'), placeholder: t('Label.Email'), defaultValue: '' },
   ]
 
   const formInfoRow = ref({})
@@ -141,13 +158,13 @@
       prop: 'countryEnName',
       label: t('Label.Nationality'),
       align: 'center',
-      width: lang ? 110 : 0,
+      width: locale.value == 'en' ? 110 : 0,
     },
     {
       prop: 'addTime',
       label: t('Label.RegistrationTime'),
       align: 'center',
-      width: lang ? 110 : 0,
+      width: locale.value == 'en' ? 110 : 0,
     },
     {
       prop: 'belongsType',
@@ -200,10 +217,11 @@
   listApi.value = ibApi.customerSubs
 
   const handleSearch = (params: any) => {
+    console.log(params)
     // 合并表单的过滤参数,同时保留当前的 belongsType 标签选中状态
     search.value = {
       ...params,
-      belongsType: search.value.belongsType
+      belongsType: search.value.belongsType,
     }
     nextTick(() => {
       tableRef.value.refreshTable()
@@ -215,7 +233,7 @@
       name: '',
       email: '',
       cId: '',
-      belongsType: search.value.belongsType // 保持当前的分类标签选中
+      belongsType: search.value.belongsType, // 保持当前的分类标签选中
     }
     nextTick(() => {
       tableRef.value.refreshTable()
@@ -258,17 +276,18 @@
     ].filter((item) => item.show)
   }
   const handleMenuClick = (item) => {
-    if (item.type == 'documentary') {
-      const { cId, id, permissionDisplay } = item.row
+    const { value } = item
+    if (value.type == 'documentary') {
+      const { cId, id, permissionDisplay } = value.row
       formInfoRow.value = {
         cId, id, permissionDisplay,
       }
       docVisible.value = true
-    } else if (item.type == 'applyIb') {
-      applyForm.value = row
+    } else if (value.type == 'applyIb') {
+      applyForm.value = value.row
       applyVisible.value = true
-    } else if (item.type == 'Point') {
-      const { cId, id, comPoint1, hide1 } = item.row
+    } else if (value.type == 'Point') {
+      const { cId, id, comPoint1, hide1 } = value.row
       pointForm.value = {
         cId, id, comPoint1, hide1,
       }
@@ -292,9 +311,6 @@
   }
   onMounted(() => {
     getStatistics()
-    // docVisible.value =true
-    // pointVisible.value =true
-    // applyVisible.value =true
   })
 
   const closeDoc = () => {
@@ -336,7 +352,8 @@
     flex-direction: column;
     align-items: flex-start;
     gap: px2rpx(10);
-    .search-tabs{
+
+    .search-tabs {
       padding: 0;
       margin: 0;
     }
@@ -387,4 +404,10 @@
       }
     }
   }
+
+  .action-btn {
+    display: flex;
+    //align-items: center;
+    justify-content: center;
+  }
 </style>

+ 49 - 27
pages/ib/index.vue

@@ -8,13 +8,13 @@
           <view class="card balance-card">
             <view class="card-header">
               <view class="header-left">
-                <cwg-icon name="qbye" :size="24" />
+                <cwg-icon name="qbye" :size="24" color="#000" />
                 <text class="header-title">{{ t('news_add_field.Label.Balance') }}</text>
               </view>
               <view class="header-right">
                 <cwg-dropdown :menu-list="menuList" @menuClick="handleMenuClick">
                   <view class="pc-header-btn">
-                    <cwg-icon name="crm-ellipsis" :size="24" />
+                    <cwg-icon name="crm-ellipsis" :size="24" color="#000" />
                   </view>
                 </cwg-dropdown>
               </view>
@@ -27,7 +27,7 @@
               </view>
               <view class="total-earnings">
                 <text class="total-label">{{ t('Ib.Index.TotalRevenue') }}</text>
-                <text class="total-value">{{ ibData.all }}</text>
+                <text class="total-value">${{ numberFormat(ibData.all || '0') }}</text>
               </view>
             </view>
           </view>
@@ -36,7 +36,7 @@
           <view class="card partner-card">
             <view class="card-header">
               <view class="header-left">
-                <cwg-icon name="crm-share-nodes" :size="24" />
+                <cwg-icon name="crm-share-nodes" :size="24" color="#000" />
                 <text class="header-title">{{ t('Ib.Index.Link') }}</text>
               </view>
             </view>
@@ -57,14 +57,14 @@
           <view class="card custom-card">
             <view class="card-header">
               <view class="header-left">
-                <cwg-icon name="crm-custom" :size="24" />
+                <cwg-icon name="crm-custom" :size="24" color="#000" />
                 <text class="header-title">{{ t('Ib.Index.NameCustom') }}</text>
               </view>
             </view>
             <view class="custom-content">
               <view class="con" @click="toCustomManagement">
                 <view class="num">
-                  {{ ibData.customAmount }}
+                  {{ ibData.customAmount || '0' }}
                 </view>
                 <view class="des">
                   {{ t('Ib.Index.Custom') }}
@@ -72,7 +72,7 @@
               </view>
               <view class="con" @click="toIbManagement">
                 <view class="num">
-                  {{ ibData.ibAmount }}
+                  {{ ibData.ibAmount || '0' }}
                 </view>
                 <view class="des">
                   {{ t('Ib.Index.Agent') }}
@@ -364,27 +364,27 @@
       </view>
     </cwg-popup>
     <!-- 调整收益分成弹窗 -->
-    <cwg-popup 
-      :visible="dialogPercent" 
-      :title="t('Ib.PammManager.percent')" 
-      @close="closeDialogPercent" 
+    <cwg-popup
+      :visible="dialogPercent"
+      :title="t('Ib.PammManager.percent')"
+      @close="closeDialogPercent"
       @confirm="applyPercent"
     >
       <view class="dia-content custom-dialog-content">
         <uni-forms :model="dialogPercentData" label-width="150" label-position="left">
           <uni-forms-item :label="t('Ib.PammManager.ownerId') + ':'">
-            <text class="info-text">{{ dialogPercentData.oldOwnerId || "--" }}</text>
+            <text class="info-text">{{ dialogPercentData.oldOwnerId || '--' }}</text>
           </uni-forms-item>
           <uni-forms-item :label="t('Ib.PammManager.accountId') + ':'">
-            <text class="info-text">{{ dialogPercentData.oldAccountId || "--" }}</text>
+            <text class="info-text">{{ dialogPercentData.oldAccountId || '--' }}</text>
           </uni-forms-item>
           <uni-forms-item :label="t('Ib.PammManager.percent') + ':'">
             <text class="info-text">{{ dialogPercentData.oldPercent }}%</text>
           </uni-forms-item>
           <uni-forms-item :label="t('Ib.PammManager.percentNew') + ':'" name="percent" required>
-            <uni-easyinput 
-              v-model="dialogPercentData.percent" 
-              :placeholder="t('placeholder.input')" 
+            <uni-easyinput
+              v-model="dialogPercentData.percent"
+              :placeholder="t('placeholder.input')"
             />
           </uni-forms-item>
         </uni-forms>
@@ -432,12 +432,13 @@
     mamListId: '',
     oldOwnerId: '',
     oldAccountId: '',
-    percent: ''
+    percent: '',
   })
   const isActionLoading = ref(false)
-  const menuList = ref([
+  const menuList = computed(() => [
     { label: t('Custom.Index.Withdrawals'), type: 1 },
-    { label: t('Custom.Index.Transfer'), type: 2 },
+    { label: t('Home.page_ib.item4'), type: 2 },
+    { label: t('Ib.Transfer.CommissionIssue'), type: 3 },
   ])
   const excludeList = ref([])
   const excludeLists = ref([
@@ -479,7 +480,7 @@
     return numberFormat(ibData.value?.balance || 0, true)[0]
   })
   const balanceDecimal = computed(() => {
-    return numberFormat(ibData.value?.balance || 0, true)[1]
+    return numberFormat(ibData.value?.balance || 0, true)[1] || '00'
   })
 
   // 国家
@@ -737,8 +738,10 @@
     console.log(value.type)
     if (value.type === 1) {
       toWithdraw()
-    } else {
+    } else if (value.type === 2) {
       toTransfer()
+    } else {
+      toTransfer(2)
     }
   }
 
@@ -748,9 +751,10 @@
       },
     )
   }
-  const toTransfer = () => {
+  const toTransfer = (tab = 1) => {
     router.push({
         path: '/pages/ib/transfer',
+        query: { tab },
       },
     )
   }
@@ -778,6 +782,10 @@
     }
   }
   const getPammManagerValid = async () => {
+    // 没有ib状态不调用
+    if (!userInfo.ibInfo) {
+      return
+    }
     const res = await ibApi.mamApplyPammManagerValid()
     if (res.code === Code.StatusOK) {
       if (res.data != null)
@@ -789,7 +797,18 @@
 
   const mamTableRef = ref(null)
   const mamSearch = ref({})
-  const mamListApi = (params) => ibApi.MamList(params)
+  const mamListApi = computed(() => {
+    // 模拟,没有ib不调用接口
+    if (!userInfo.ibInfo) {
+      return (params) => new Promise(resolve => {
+        resolve({
+          code: 200,
+          data: [],
+        })
+      })
+    }
+    return (params) => ibApi.MamList(params)
+  })
 
   const showAddMamAccount = computed(() => {
     return !!(
@@ -889,12 +908,12 @@
 
   const applyPercent = async () => {
     if (isActionLoading.value) return
-    
+
     if (!dialogPercentData.value.percent) {
       uni.showToast({ title: t('placeholder.input'), icon: 'none' })
       return
     }
-    
+
     isActionLoading.value = true
     try {
       const res = await ibApi.applyPercent({
@@ -958,13 +977,14 @@
 
   .custom-dialog-content {
     padding: px2rpx(20);
-    
+
     .info-text {
       color: #333;
       font-size: px2rpx(14);
       line-height: px2rpx(36);
     }
   }
+
   .card-header {
     display: flex;
     justify-content: space-between;
@@ -1038,12 +1058,14 @@
 
   .total-earnings {
     display: flex;
-    gap: 12px;
+    align-items: center;
+    gap: 5px;
     color: rgba(20, 29, 34, 0.6);
     font-size: px2rpx(12);
   }
 
   .total-value {
+    align-self: flex-end;
   }
 
   /* 合作伙伴卡片 */

+ 61 - 41
pages/ib/linkList.vue

@@ -34,13 +34,15 @@
           </view>
         </template>
       </cwg-tabel>
-<!--详情-->
-      <link-detail-dialog :visible="datailVisible" @close="closeDetail" :detail="detail" @showQrCode="showQrCodeDialog"/>
+      <!--详情-->
+      <link-detail-dialog :visible="datailVisible" @close="closeDetail" :detail="detail"
+                          @showQrCode="showQrCodeDialog" />
 
-      <cwg-popup ref="linkPopup" :visible="dialogLink" type="center" :title="t('Ib.Index.CreateLink')" showFooterLine @close="dialogLink = false" @confirm="saveLink">
+      <cwg-popup ref="linkPopup" :visible="dialogLink" type="center" :title="t('Ib.Index.CreateLink')" showFooterLine
+                 @close="dialogLink = false" @confirm="saveLink">
         <view class="dia-content">
           <view class="content" style="font-size: 14px; text-align: left">
-            <view class="label">{{ t('Ib.Custom.NameLabelColon') }} </view>
+            <view class="label">{{ t('Ib.Custom.NameLabelColon') }}</view>
             <uni-easyinput
               v-model="linkName"
               :placeholder="t('Ib.Custom.NameLabel')"
@@ -106,7 +108,9 @@
           </view>
         </view>
       </cwg-popup>
-      <cwg-popup :visible="qrCodeDialogVisible" type="center" :title="t('Ib.Index.QrCode')" showFooterLine @singleClick="qrCodeDialogVisible = false" :singleBtnText="t('Btn.Cancel')" :footerType="'single'">
+      <cwg-popup :visible="qrCodeDialogVisible" type="center" :title="t('Ib.Index.QrCode')" showFooterLine
+                 @singleClick="qrCodeDialogVisible = false" :singleBtnText="t('Btn.Cancel')" :footerType="'single'"
+                 @close="qrCodeDialogVisible = false">
         <view class="qr-code-dialog-content">
           <QrCode
             ref="dialogQrCode"
@@ -127,7 +131,7 @@
 </template>
 
 <script setup lang="ts">
-  import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
+  import { ref, reactive, computed, onMounted, onUnmounted, watch } from 'vue'
   import { onLoad } from '@dcloudio/uni-app'
   import { useI18n } from 'vue-i18n' // uni-app 中已集成,但需配置
   import { customApi } from '@/service/custom'
@@ -209,13 +213,14 @@
       label: t('Ib.Index.Link'),
       align: 'center',
       slot: 'link',
-      width: 450,
+      width: 480,
     },
     {
       prop: 'linkValue',
       label: t('Ib.Index.LinkValue'),
       align: 'center',
       slot: 'linkValue',
+      width: 200,
     },
     {
       prop: 'customNum',
@@ -388,12 +393,12 @@
     }
     dialogLink.value = true
   }
-  const onNameChange = (e)=>{
+  const onNameChange = (e) => {
     console.log(e)
   }
   // 账户类型选择变化处理
-  const handleAccountTypeChange = (type, loginType,val) => {
-    console.log(type, loginType,val,'221')
+  const handleAccountTypeChange = (type, loginType, val) => {
+    console.log(type, loginType, val, '221')
     const setting = accountTypeSettings.value[type]
     const availableSpreads = getAvailableSpreads(loginType)
     if (setting.selectedIndex !== null && setting.selectedIndex !== undefined) {
@@ -406,11 +411,15 @@
   const getAvailableSpreads = (loginType) => {
     // 根据 loginType 返回对应的数据
     if (loginType === '2') {
-      return accountTypeData.value.ecn?.map((item,index) => ({ ...item,value:index, text: item.groupName })) || []
+      return accountTypeData.value.ecn?.map((item, index) => ({ ...item, value: index, text: item.groupName })) || []
     } else if (loginType === '7') {
-      return accountTypeData.value.standard?.map((item,index) => ({ ...item,value:index, text: item.groupName })) || []
+      return accountTypeData.value.standard?.map((item, index) => ({
+        ...item,
+        value: index,
+        text: item.groupName,
+      })) || []
     } else if (loginType === '8') {
-      return accountTypeData.value.cent?.map((item,index) => ({ ...item,value:index, text: item.groupName })) || []
+      return accountTypeData.value.cent?.map((item, index) => ({ ...item, value: index, text: item.groupName })) || []
     }
     return []
   }
@@ -464,36 +473,36 @@
   const saveLink = async () => {
     if (!linkName.value) {
       uni.showToast({
-        title: t("Ib.Custom.NameLabel"),
+        title: t('Ib.Custom.NameLabel'),
         icon: 'none',
       })
-      return;
+      return
     }
     if (!link.value) {
       uni.showToast({
-        title: t("Ib.Index.CreateLink"),
+        title: t('Ib.Index.CreateLink'),
         icon: 'none',
       })
-      return;
+      return
     }
 
     // 收集所有选中的账户类型配置
-    const loginConfig = [];
+    const loginConfig = []
 
     Object.keys(accountTypeSettings.value).forEach((key) => {
-      const setting = accountTypeSettings.value[key];
+      const setting = accountTypeSettings.value[key]
       if (setting.selectedItem) {
         // 将选中的整个对象添加到 loginConfig 数组
-        loginConfig.push(setting.selectedItem);
+        loginConfig.push(setting.selectedItem)
       }
-    });
+    })
 
     if (loginConfig.length === 0) {
       uni.showToast({
-        title: t("Ib.Index.Spread5"),
+        title: t('Ib.Index.Spread5'),
         icon: 'none',
       })
-      return;
+      return
     }
 
     // 调用保存接口
@@ -502,25 +511,25 @@
       link: link.value,
       linkValue: linkValue.value,
       loginConfig: loginConfig,
-    });
+    })
 
     if (res.code === Code.StatusOK) {
       uni.showToast({
         title: res.msg,
         icon: 'none',
       })
-      dialogLink.value = false;
+      dialogLink.value = false
       // 重置表单
-      linkName.value = "";
-      link.value = "";
-      linkValue.value = "";
-      excludeShowLoginTypes.value = [];
-      selectedSpreadId.value = "";
+      linkName.value = ''
+      link.value = ''
+      linkValue.value = ''
+      excludeShowLoginTypes.value = []
+      selectedSpreadId.value = ''
       accountTypeSettings.value = {
-        ecn: { selectedIndex: null, selectedItem: null, loginType: "2" },
-        standard: { selectedIndex: null, selectedItem: null, loginType: "7" },
-        cent: { selectedIndex: null, selectedItem: null, loginType: "8" },
-      };
+        ecn: { selectedIndex: null, selectedItem: null, loginType: '2' },
+        standard: { selectedIndex: null, selectedItem: null, loginType: '7' },
+        cent: { selectedIndex: null, selectedItem: null, loginType: '8' },
+      }
       tableRef.value.refreshTable()
     } else {
       uni.showToast({
@@ -529,6 +538,12 @@
       })
     }
   }
+  watch(() => dialogLink.value, (val) => {
+    // 关闭弹窗清空
+    if (!val) {
+      link.value = ''
+    }
+  })
   // 生成链接(不保存)
   const CreateLink = async () => {
     console.log(linkName.value)
@@ -546,11 +561,11 @@
   }
 
   const downloadQrCode = (type = 0) => {
-      qrCode.value.download()
+    qrCode.value.download()
   }
   // 下载弹窗中的二维码
   const downloadDialogQrCode = (type = 0) => {
-      dialogQrCode.value.download()
+    dialogQrCode.value.download()
   }
   // 打开详情弹窗
   const openDetail = (row) => {
@@ -591,12 +606,12 @@
     width: 100%;
     display: inline-flex;
     align-items: center;
-    justify-content: center;
-    gap: 10px;
+    justify-content: flex-start;
+    gap: 5px;
     white-space: nowrap;
 
     .read-input {
-      max-width: px2rpx(400);
+      max-width: px2rpx(360);
       white-space: nowrap;
       overflow: hidden;
       text-overflow: ellipsis;
@@ -623,6 +638,7 @@
       opacity: 0.7;
     }
   }
+
   .dia-content {
     padding: 20rpx;
   }
@@ -632,7 +648,8 @@
     flex-direction: column;
     gap: 20rpx;
   }
-  .label-tit{
+
+  .label-tit {
     font-weight: 500;
     margin-bottom: 8rpx;
   }
@@ -646,6 +663,7 @@
     margin-top: px2rpx(16);
     text-align: center;
   }
+
   .link {
     display: flex;
     margin-top: px2rpx(20);
@@ -665,13 +683,15 @@
     align-items: center;
     gap: px2rpx(16);
   }
+
   .qr-code-dialog-content {
     display: flex;
     flex-direction: column;
     justify-content: center;
     align-items: center;
     padding: px2rpx(20) 0;
-    .qr-code-btn{
+
+    .qr-code-btn {
       margin-top: px2rpx(16);
     }
   }

+ 2 - 3
pages/ib/openAccount.vue

@@ -140,9 +140,8 @@ import { useI18n } from 'vue-i18n'
 import { ibApi } from '@/service/ib'
 import { isAfterJuly28 } from '@/utils/dateUtils'
 import Config from '@/config/index'
-import { lang } from '@/composables/config'
 
-const { t } = useI18n()
+const { t, local } = useI18n()
 const { Code } = Config
 
 const pictLoading = ref(false)
@@ -286,7 +285,7 @@ const backIndex = () => {
 }
 
 const openLeverageMargin = () => {
-  const url = ['cn', 'zhHant'].includes(lang.value) 
+  const url = ['cn', 'zhHant'].includes(local.value)
     ? 'https://www.cwgvu.com/cn/leveragemargin' 
     : 'https://www.cwgvu.com/en/leveragemargin'
   // #ifdef H5

+ 11 - 11
pages/ib/recording.vue

@@ -6,7 +6,7 @@
       <view class="search-content">
         <view class="search-bar">
           <cwg-combox v-model:value="search.types" :options="typeList"
-                      :placeholder="t('placeholder.choose')" :clearable="false"/>
+                      :placeholder="t('placeholder.choose')" :clearable="false" />
           <uni-datetime-picker type="daterange" v-model="search.date"
                                :placeholder="t('placeholder.Start') + ' - ' + t('placeholder.End')"
                                @change="handleDateChange" />
@@ -78,17 +78,17 @@
   import { financialApi } from '@/service/financial'
   import Config from '@/config/index'
   import { ibApi } from '@/service/ib'
-  import { apiList, columnList, mobileList } from '@/pages/ib/const/recording'
+  import { useRecordingConst } from '@/pages/ib/const/recording'
   import { useFilters } from '@/composables/useFilters'
   import { useConfirm } from '@/hooks/useConfirm'
 
   const confirm = useConfirm()
   const { numberFormat, numberDecimal } = useFilters()
   const { t, locale } = useI18n()
-  const lang = locale.value
+  const { columnList, mobileList, apiList } = useRecordingConst()
   const reasons = ref({})
   let { Code } = Config
-  const typeList = ref([
+  const typeList = computed(() => [
     { text: t('Ib.Recording.NewAccount'), value: 1 },
     { text: t('Ib.Recording.LeverageApply'), value: 2 },
     { text: t('Ib.Recording.InternalTransfer'), value: 3 },
@@ -111,34 +111,34 @@
     endDate: '',
   })
   const isZh = computed(() => {
-    ['cn', 'zhHant'].indexOf(lang) != -1
+    return ['cn', 'zhHant'].indexOf(locale.value) != -1
   })
   // 表格列配置 根据types 切换
   const columns = computed(() => {
-    return columnList[search.value.types]
+    return columnList.value[search.value.types]
   })
 
   const mobilePrimaryFields = computed(() => {
     return [
-      ...mobileList[search.value.types],
+      ...mobileList.value[search.value.types],
       {
         prop: 'more',
         type: 'more',
         width: 20,
         align: 'right',
-      }
+      },
     ]
   })
 
   // 接口 根据types 切换
   const listApi = computed(() => {
-    return ibApi[apiList[search.value.types]]
+    return search.value.types == 4? (params)=> ibApi[apiList.value[search.value.types]]({ ...params ,type: 4}): (params)=> ibApi[apiList.value[search.value.types]]({ ...params })
   })
   //获取原因列表
   const searchReasons = async () => {
-    let res = await customApi.reasonsRefusalList({ type: nviewl })
+    let res = await customApi.reasonsRefusalList({ type: null })
     if (res.code == Code.StatusOK) {
-      if (res.data == nviewl) {
+      if (res.data == null) {
         reasons.value = {}
       } else {
         reasons.value = res.data

+ 82 - 97
pages/ib/report.vue

@@ -31,18 +31,19 @@
   import { useI18n } from 'vue-i18n'
   import Config from '@/config/index'
   import { ibApi } from '@/service/ib'
-  import { columnList, mobileList, platformOptions, customTypeList } from '@/pages/ib/const/report'
+  import { useReportConst } from '@/pages/ib/const/report'
   import { useFilters } from '@/composables/useFilters'
   import { isAfterJuly28 } from '@/utils/dateUtils'
   import useUserStore from '@/stores/use-user-store'
 
   const { numberFormat } = useFilters()
   const { t } = useI18n()
+  const { columnList, mobileList, platformOptions, customTypeList, groupCurrency1, groupTypeName } = useReportConst()
   let { Code } = Config
   const { userInfo } = useUserStore()
   const tableRef = ref(null)
 
-  const typeList = ref([
+  const typeList = computed(() => [
     { text: t('Ib.Report.Title1'), value: 1 },
     { text: t('Ib.Report.Title2'), value: 2 },
     { text: t('Ib.Report.Title3'), value: 3 },
@@ -53,14 +54,14 @@
     { text: t('Ib.Report.Title8'), value: 24 },
   ])
 
-  const detailTypeList = ref([
+  const detailTypeList = computed(() => [
     { text: t('Ib.Report.Tit1'), value: 1 },
     { text: t('Ib.Report.Tit2'), value: 2 },
     { text: t('Ib.Report.Tit3'), value: 3 },
     { text: t('Ib.Report.Tit4'), value: 4 },
   ])
 
-  const isShortList = ref([
+  const isShortList = computed(() => [
     { text: t('State.All'), value: 0 },
     { text: t('Ib.Report.item1'), value: 1 },
     { text: t('Ib.Report.item2'), value: 2 },
@@ -101,16 +102,57 @@
     return userInfo.customInfo.country
   })
 
-  const agentIdOpts = ref<any[]>([
-    { value: 0, label: t('news_add_field.IbReport.ALL'), children: [] },
+  const agentLevels = ref<Array<{ key: string, options: any[] }>>([
     {
-      value: -1,
-      label: t('news_add_field.IbReport.DirectlyUnder'),
-      children: [],
-    },
+      key: 'agentId_0',
+      options: [
+        { value: 0, text: t('news_add_field.IbReport.ALL') },
+        { value: -1, text: t('news_add_field.IbReport.DirectlyUnder') },
+      ]
+    }
   ])
 
-  const handleItemChange = (e: any) => {}
+  const handleAgentChange = async (val: any, levelIndex: number) => {
+    // 截断当前层级之后的所有层级
+    agentLevels.value.splice(levelIndex + 1)
+    
+    // 清理 searchParams 中被移除层级的值
+    for (let key in searchParams.value) {
+      if (key.startsWith('agentId_')) {
+        const idx = parseInt(key.split('_')[1])
+        if (idx > levelIndex) {
+          delete searchParams.value[key]
+        }
+      }
+    }
+
+    if (val === 0 || val === -1 || val === '') {
+      return
+    }
+
+    try {
+      const res = await ibApi.ibTree({ pid: val })
+      if (res.code === Code.StatusOK && res.data && res.data.length > 0) {
+        const nextOptions = []
+        res.data.forEach((item: any) => {
+          if (item.ibNo) {
+            nextOptions.push({
+              value: item.id,
+              text: item.name ? `${item.ibNo} - ${item.name}` : item.ibNo
+            })
+          }
+        })
+        if (nextOptions.length > 1) {
+          agentLevels.value.push({
+            key: `agentId_${levelIndex + 1}`,
+            options: nextOptions
+          })
+        }
+      }
+    } catch (error) {
+      uni.showToast({ title: 'Error', icon: 'none' })
+    }
+  }
 
   const getSummaries = (param: any) => {
     const { columns, summaryData } = param
@@ -193,15 +235,18 @@
     return sums
   }
 
-  const normalizePickerValue = (val: any) => {
-    if (Array.isArray(val)) return val[val.length - 1]
-    return val
-  }
-
   const handleSearch = (params: any) => {
     const payload: any = { ...params }
 
-    payload.agentId = normalizePickerValue(payload.agentId)
+    let finalAgentId = payload.agentId_0
+    for (let i = agentLevels.value.length - 1; i >= 0; i--) {
+      const val = payload[`agentId_${i}`]
+      if (val !== undefined && val !== '') {
+        finalAgentId = val
+        break
+      }
+    }
+    payload.agentId = finalAgentId
 
     const type = Number(payload.reportType)
     if (![1, 3, 4, 7, 24].includes(type)) payload.platform = ''
@@ -228,6 +273,8 @@
   }
 
   const handleReset = (emptyParams: any) => {
+    // 重置时清理级联菜单到只有第一层
+    agentLevels.value.splice(1)
     handleSearch(emptyParams)
   }
 
@@ -240,11 +287,9 @@
           if (item.ibNo) {
             let option = {
               value: item.id,
-              label: item.name ? `${item.ibNo} - ${item.name}` : item.ibNo,
-              name: item.name,
-              children: [],
+              text: item.name ? `${item.ibNo} - ${item.name}` : item.ibNo,
             }
-            agentIdOpts.value.push(option)
+            agentLevels.value[0].options.push(option)
           }
         })
       } else {
@@ -256,61 +301,20 @@
     }
   }
 
-  const onnodeclick = async (node: any) => {
-    const val = node.value
-
-    if (node.children && node.children.length > 0) {
-      return
-    }
-
-    try {
-      // uni.showLoading({ title: t('Msg.Loading') || 'Loading...', mask: true })
-      const res = await ibApi.ibTree({ pid: val })
-
-      if (res.code === Code.StatusOK) {
-        if (res.data && res.data.length > 0) {
-          const newChildren: any[] = []
-          res.data.forEach((item: any) => {
-            if (item.ibNo) {
-              newChildren.push({
-                value: item.id,
-                label: item.name ? `${item.ibNo} - ${item.name}` : item.ibNo,
-                name: item.name,
-                children: [],
-              })
-            }
-          })
-          node.children = newChildren
-        } else {
-          delete node.children
-        }
-      } else {
-        uni.showToast({
-          title: res.msg || 'Error',
-          icon: 'none',
-        })
-      }
-    } catch (error) {
-      uni.showToast({ title: 'Error', icon: 'none' })
-    } finally {
-      // uni.hideLoading()
-    }
-  }
-
   // 表格列配置 根据types 切换
   const columns = computed(() => {
     if (search.value.reportType === 3) {
-      return columnList[`3_${search.value.detail_type}` as keyof typeof columnList] || []
+      return columnList.value[`3_${search.value.detail_type}`] || []
     }
-    return columnList[search.value.reportType as keyof typeof columnList] || []
+    return columnList.value[search.value.reportType] || []
   })
 
   const mobilePrimaryFields = computed(() => {
     let list: any[] = []
     if (search.value.reportType === 3) {
-      list = mobileList[`3_${search.value.detail_type}` as keyof typeof mobileList] || []
+      list = mobileList.value[`3_${search.value.detail_type}`] || []
     } else {
-      list = mobileList[search.value.reportType as keyof typeof mobileList] || []
+      list = mobileList.value[search.value.reportType] || []
     }
     return [
       ...list,
@@ -354,25 +358,6 @@
     }
   })
 
-  const groupCurrency1 = (type: string) => {
-    if (type == 'GBP') return '£'
-    if (type == 'USD') return '$'
-    if (type == 'EUR') return '€'
-    if (type == 'USC') return '¢'
-    return '$'
-  }
-
-  const groupTypeName = (type: string | number) => {
-    if (type == '1') return t('AccountType.ClassicAccount')
-    if (type == '2') return t('AccountType.SeniorAccount')
-    if (type == '3') return isAfterJuly28() ? '--' : t('AccountType.AgencyAccount')
-    if (type == '5') return t('AccountType.SpeedAccount')
-    if (type == '6') return t('AccountType.SpeedAccount')
-    if (type == '7') return t('AccountType.StandardAccount')
-    if (type == '8') return t('AccountType.CentAccount')
-    return '--'
-  }
-
   watch(() => searchParams.value.reportType, (val) => {
     const type = Number(val)
     search.value.reportType = type
@@ -427,20 +412,20 @@
     }
 
     if (type === 24) {
-      fields.push({ key: 'customType', type: 'select', label: t('placeholder.choose'), placeholder: t('placeholder.choose'), options: customTypeList, defaultValue: 0, isSelect: true })
+      fields.push({ key: 'customType', type: 'select', label: t('placeholder.choose'), placeholder: t('placeholder.choose'), options: customTypeList.value, defaultValue: 0, isSelect: true })
     }
 
-    fields.push({
-      key: 'agentId',
-      type: 'picker',
-      label: t('State.All'),
-      options: agentIdOpts.value,
-      popupTitle: t('State.All'),
-      map: { value: 'value', text: 'label' },
-      onChange: handleItemChange,
-      onNodeClick: onnodeclick,
-      defaultValue: '',
-    })
+    // agentLevels.value.forEach((level, index) => {
+    //   fields.push({
+    //     key: level.key,
+    //     type: 'select',
+    //     label: t('State.All'),
+    //     options: level.options,
+    //     placeholder: t('State.All'),
+    //     onChange: (val: any) => handleAgentChange(val, index),
+    //     defaultValue: index === 0 ? 0 : '',
+    //   })
+    // })
 
     if ([1, 2, 3, 4, 7].includes(type)) {
       fields.push({ key: 'login', type: 'input', label: t('Label.TradingAccount'), placeholder: t('Label.TradingAccount'), defaultValue: '' })

+ 2 - 1
pages/ib/subsList.vue

@@ -83,7 +83,6 @@
   import { customApi } from '@/service/custom'
   import { financialApi } from '@/service/financial'
   import Config from '@/config/index'
-  import { lang } from '@/composables/config'
   import { ibApi } from '@/service/ib'
   import { useFilters } from '@/composables/useFilters'
   import ApplyIbDialog from '@/pages/ib/components/applyIbDialog.vue'
@@ -330,6 +329,7 @@
       margin-bottom: px2rpx(10);
 
       .search-button {
+        background-color: var(--color-error);
         margin: 0 0 0 auto; /* 强制按钮靠右且消除其它 margin */
       }
     }
@@ -338,6 +338,7 @@
   .search-button{
     display: flex;
     align-items: center;
+    background-color: var(--color-error);
     line-height: px2rpx(36);
     min-width: px2rpx(120);
   }

+ 3 - 0
pages/ib/transfer.vue

@@ -605,6 +605,9 @@ onLoad((options) => {
         step2.value = true
         form.withdrawLogin = options.login
     }
+    if (options?.tab) {
+      activeTab.value = options?.tab
+    }
 })
 </script>
 

+ 3 - 2
pages/login/index.vue

@@ -306,7 +306,7 @@
         display: flex;
         flex-direction: column;
         justify-content: center;
-        align-items: center;
+        align-items: flex-start;
         width: 60%;
         margin-top: px2rpx(20);
 
@@ -316,6 +316,7 @@
           margin-bottom: px2rpx(20);
 
           .section-title {
+            margin-top: px2rpx(30);
             margin-bottom: px2rpx(10);
           }
 
@@ -409,7 +410,7 @@
           }
 
           .doc-link {
-            color: #ffde02;
+            color: var(--color-error);
             text-decoration: underline;
             margin: 0 px2rpx(4);
           }

+ 126 - 29
pages/login/regist.vue

@@ -2,20 +2,42 @@
   <view class="regist-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">
-          <view class="company logo u-flex-y u-flex-y-center">
-            <image src="/static/images/logo4.png" class="company-icon" mode="widthFix"></image>
-          </view>
-          <view class="left-box">
-            <view class="left-content">
-              <view class="h1">
-                <text>{{ t('newLoop.item12') }}</text>
-                <br />
-                <text class="color-white">{{ t('newLoop.item13') }}</text>
+        <uni-col :xs="24" :sm="24" :md="12" :lg="14" :xl="16">
+          <view class="left-bg">
+            <view class="left-box">
+              <view class="inner">
+                <view class="section-title">
+                  <text class="bg-secondary-opacity subtitle w-40" v-t="'newLoop.item11'"></text>
+                </view>
+                <view class="title w-700">
+                  <text v-t="'newLoop.item12'"></text>
+                  <text>&nbsp;</text>
+                  <text class="color-white" v-t="'newLoop.item13'"></text>
+                </view>
+                <view class="text-white" v-t="'newLoop.item14'"></view>
               </view>
-              <view class="h6 text-white">{{ t('newLoop.item14') }}</view>
-              <view class="company u-flex-y u-flex-y-center">
-                <image src="/static/images/trust-pilot.png" class="company-icon" mode="widthFix"></image>
+              <image src="/static/images/trust-pilot.png" class="img-fluid mt--10" mode="widthFix"></image>
+              <view class="left-content">
+                <view class="des text-white">
+                  <text v-html="t('newSignin.item12')"></text>
+                  <br />
+                  <text v-html="t('newSignin.item12_1')"></text>
+                  <br />
+                  <text v-html="t('newSignin.item10')"></text>
+                  <br />
+                  <text v-html="t('newSignin.item11')"></text>
+                  <br />
+                  <text v-t="'newSignin.item13'"></text>
+                  <a
+                    :href="`https://www.${ho}.com/doc/Risk-Disclosures-and-Acknowledgements-2020-08.pdf`"
+                    target="_blank"
+                    v-t="'newSignin.item13_1'"
+                    class="doc-link"
+                  ></a>
+                  <text v-t="'newSignin.item13_2'"></text>
+                  <!-- <view v-t="'newSignin.item13_3'"></view>
+                  <text v-t="'newSignin.item13_4'"></text> -->
+                </view>
               </view>
             </view>
           </view>
@@ -190,7 +212,7 @@
 
   const isRouteHasId = ref(false)
   const formData = ref({
-    country: '',
+    country: 'CN',
     phone: '',
     birthDate: '',
     email: '',
@@ -578,19 +600,85 @@
     margin: 0 !important;
 
     .left-bg {
-      height: calc(100vh - 60px);
+      height: 100%;
+      min-height: 100vh;
       background-image: url(/static/images/login-bg.gif);
       background-repeat: no-repeat;
       background-size: cover;
       background-position: center center;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
 
       .left-box {
         display: flex;
         flex-direction: column;
         justify-content: center;
-        align-items: center;
+        align-items: flex-start;
+        width: 60%;
+        margin-top: px2rpx(20);
+
+        .inner {
+          width: 100%;
+          text-align: start;
+          margin-bottom: px2rpx(20);
+
+          .section-title {
+            margin-top: px2rpx(30);
+            margin-bottom: px2rpx(10);
+          }
+
+
+          .title {
+            font-size: px2rpx(60);
+            line-height: 1.3;
+            color: #fff;
+            font-weight: 700;
+          }
+
+          .w-700 {
+            font-weight: 700;
+          }
+
+          .subtitle {
+            width: 45%;
+            font-size: px2rpx(18);
+            letter-spacing: px2rpx(1);
+            display: block;
+            margin-bottom: px2rpx(24);
+            color: #ffffff;
+            line-height: px2rpx(15);
+            font-weight: 500;
+            padding: px2rpx(10) px2rpx(20);
+            border-radius: px2rpx(100);
+            text-transform: uppercase;
+            background-color: #e61f1e;
+            text-align: center;
+          }
+
+          .w-40 {
+            max-width: 40%;
+          }
+
+          .text-white {
+            margin-top: px2rpx(10);
+            font-size: px2rpx(14);
+            line-height: 1.6;
+            color: #fff;
+          }
+        }
+
+        .img-fluid {
+          width: 100%;
+          max-width: px2rpx(240);
+        }
+
+        .mt--10 {
+          margin-top: px2rpx(10);
+        }
 
         .h1 {
+          // text-align: center;
           color: #fff;
           font-size: 30px;
           margin-top: 30px;
@@ -606,26 +694,35 @@
         }
 
         .company {
-          padding: px2rpx(40) 0 px2rpx(50) 0;
+          padding: px2rpx(10) 0 px2rpx(10) 0;
           position: relative;
           align-items: flex-start !important;
+          width: 100%;
         }
       }
 
       .left-content {
-        .h1 {
-          // text-align: center;
-          color: #fff;
-          font-size: 30px;
-          margin-top: 30px;
-          line-height: 1.5;
-        }
+        width: 100%;
 
-        .h6 {
-          line-height: 20px;
+        .des {
+          text-align: start;
+          line-height: 24px;
           color: #fff;
           font-size: 14px;
-          margin-top: 10px;
+          margin-top: px2rpx(20);
+          padding: 0;
+
+          :nth-child(n) {
+            display: inline;
+            word-break: break-all;
+            word-wrap: break-word;
+          }
+
+          .doc-link {
+            color: var(--color-error);
+            text-decoration: underline;
+            margin: 0 px2rpx(4);
+          }
         }
       }
     }
@@ -878,8 +975,8 @@
     width: 100%;
     height: px2rpx(40);
     border-radius: px2rpx(4);
-    background-color: #ffde02;
-    color: #333;
+    background-color: var(--color-error);
+    color: #fff;
     font-weight: bold;
   }
 

+ 9 - 2
pages/mine/components/SecurityCenterTab.vue

@@ -89,7 +89,8 @@ const {
     text: getCodeString,
     canSend,
     start,
-    restore
+    restore,
+    clear,
 } = useEmailCountdown()
 const { t, locale } = useI18n();
 interface BankListType {
@@ -120,6 +121,7 @@ const rule3 = computed(() => {
     );
 });
 const rule4 = computed(() => {
+    console.log( /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[~!@&%$^*./\\(\\)\\+\\=#_-])[A-Za-z0-9~!@&%$^*./\\(\\)\\+\\=#_-]{8,16}$/.test(passwordInfo.value.newPassword))
     return /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[~!@&%$^*./\\(\\)\\+\\=#_-])[A-Za-z0-9~!@&%$^*./\\(\\)\\+\\=#_-]{8,16}$/.test(
         passwordInfo.value.newPassword
     );
@@ -170,7 +172,8 @@ async function emailUpdate() {
             ...emailInfo.value
         });
         if (res.code === 200) {
-            start()
+            clear()
+            emailInfo.value = {}
             showToast(t("Msg.Success"));
         } else {
             showToast(res.msg);
@@ -194,6 +197,10 @@ async function passwordUpdate() {
             showToast(t("signup.form.rules.4rd"));
             return;
         }
+        if (passwordInfo.value.newPassword !== passwordInfo.value.checkPass) {
+            showToast(t("vaildate.password.same"));
+            return;
+        }
         const res = await personalApi.customUpdatePassword({
             ...passwordInfo.value
         });

+ 16 - 16
pages/mine/improveImmediately.vue

@@ -38,7 +38,7 @@
               </uni-forms-item>
             </uni-col>
             <!-- 法人中间名 -->
-            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="lang == 'en'">
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="local == 'en'">
               <uni-forms-item name="middle" :label="t('placeholder.middle')">
                 <uni-easyinput :clearable="false" v-model="formData.middle" :placeholder="t('placeholder.input')" />
               </uni-forms-item>
@@ -65,7 +65,7 @@
               </uni-forms-item>
             </uni-col>
             <!-- 拼音 -->
-            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="['cn', 'zhHant'].includes(lang)">
+            <uni-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-if="['cn', 'zhHant'].includes(local)">
               <uni-forms-item name="nameEn" :label="t('ImproveImmediately.Label.NamePinYin')">
                 <uni-easyinput :clearable="false" v-model="formData.nameEn" :placeholder="t('placeholder.input')" />
               </uni-forms-item>
@@ -380,7 +380,7 @@
               <span class="dian">-</span>
               <span>{{ t('ImproveImmediately.Content.ProofIdentity5') }}</span>
             </p>
-            <p class="des" v-if="['cn', 'zhHant'].indexOf(lang) == -1">
+            <p class="des" v-if="['cn', 'zhHant'].indexOf(local) == -1">
               <span class="dian">-</span>
               <span>{{ t('ImproveImmediately.Content.ProofIdentity6') }}</span>
             </p>
@@ -396,11 +396,11 @@
               <span class="dian">·</span>
               <span>{{ t('ImproveImmediately.Content.ProofIdentity3') }}</span>
             </p>
-            <p class="des" v-if="['cn', 'zhHant'].indexOf(lang) == -1">
+            <p class="des" v-if="['cn', 'zhHant'].indexOf(local) == -1">
               <span class="dian">·</span>
               <span>{{ t('ImproveImmediately.Content.ProofIdentity7') }}</span>
             </p>
-            <p class="des" v-if="['cn', 'zhHant'].indexOf(lang) == -1">
+            <p class="des" v-if="['cn', 'zhHant'].indexOf(local) == -1">
               <span class="dian">·</span>
               <span>{{ t('ImproveImmediately.Content.ProofIdentity8') }}</span>
             </p>
@@ -607,19 +607,19 @@
               <span>{{ t('ImproveImmediately.Content.ProofAddress3') }}</span>
             </p>
             <p class="des">
-              <span class="dian" v-if="['cn', 'zhHant'].indexOf(lang) != -1">·</span>
-              <span class="dian" v-if="lang == 'en'">-</span>
+              <span class="dian" v-if="['cn', 'zhHant'].indexOf(local) != -1">·</span>
+              <span class="dian" v-if="local == 'en'">-</span>
               <span>{{ t('ImproveImmediately.Content.ProofAddress4') }}</span>
             </p>
             <p class="des">
               <span class="dian">·</span>
               <span>{{ t('ImproveImmediately.Content.ProofAddress6') }}</span>
             </p>
-            <p class="des" v-if="lang == 'en'">
+            <p class="des" v-if="local == 'en'">
               <span class="dian">·</span>
               <span>{{ t('ImproveImmediately.Content.ProofAddress7') }}</span>
             </p>
-            <p class="des" v-if="lang == 'en'">
+            <p class="des" v-if="local == 'en'">
               <span class="dian">·</span>
               <span>{{ t('ImproveImmediately.Content.ProofAddress8') }}</span>
             </p>
@@ -732,10 +732,9 @@
   import icon_refresh from '@/static/icons/crm-refresh.svg'
   import icon_mobile from '@/static/icons/icon_mobile.svg'
   import icon_arrowR from '@/static/icons/icon_arrowR.svg'
-  import { lang } from '@/composables/config'
 
   const router = useRouter()
-  const { t } = useI18n()
+  const { t,local } = useI18n()
   const currentStep = ref<number>(3)
   const formRef = ref()
   const dialogCheck = ref(null)
@@ -1021,7 +1020,7 @@
     firstName: undefined,
     middle: undefined,
     nationality: undefined,
-    IdentityType: 1,
+    IdentityType: 2,
     identity: undefined,
     nameEn: undefined,
     gender: undefined,
@@ -1319,8 +1318,8 @@
       let res = await personalApi.Country({ pid })
       if (res.code == Config.Code.StatusOK) {
         stateOptions.value = res.data.map((item: any) => ({
-          text: lang.value === 'en' ? item.enName : item.name,
-          value: lang.value === 'en' ? item.enName : item.name,
+          text: local.value === 'en' ? item.enName : item.name,
+          value: local.value === 'en' ? item.enName : item.name,
         }))
         states.value = res.data
         const state = formData.value.state
@@ -1344,8 +1343,8 @@
       let res = await personalApi.Country({ pid })
       if (res.code == Config.Code.StatusOK) {
         cityOptions.value = res.data.map((item: any) => ({
-          text: lang.value === 'en' ? item.enName : item.name,
-          value: lang.value === 'en' ? item.enName : item.name,
+          text: local.value === 'en' ? item.enName : item.name,
+          value: local.value === 'en' ? item.enName : item.name,
         }))
         cities.value = res.data
       }
@@ -1363,6 +1362,7 @@
           formData.value.addressLines2 = formData.value.addressLines[1]
         }
         formData.value.customType = formData.value.customType ? formData.value.customType : 1
+        formData.value.IdentityType = 2
         await getCountryList()
       } else {
         uni.showToast({ title: t('Msg.SystemError'), icon: 'none' })

+ 1 - 0
stores/pinia.types.ts

@@ -11,4 +11,5 @@ export interface GlobalState {
     theme: string
     statusBarHeight: number
     mode: 'customer' | 'ib'
+    applyStatus: boolean
 }

+ 7 - 1
stores/use-global-store.ts

@@ -11,7 +11,9 @@ const useStore = defineStore("globalStore", () => {
     isPageSwitching: false,
     statusBarHeight: 0,
     mode: 'customer',
-    theme: "light"
+    theme: "light",
+    // 认证状态
+    applyStatus: false
   });
 
   const setGlobalTheme = (payload: string) => {
@@ -40,6 +42,9 @@ const useStore = defineStore("globalStore", () => {
   const setFullScreenLoading = (payload: boolean) => {
     state.fullScreenLoading = payload;
   };
+  const setApplyStatus = (payload: boolean) => {
+    state.applyStatus = payload;
+  };
   initMode()
   return {
     ...toRefs(state),
@@ -50,6 +55,7 @@ const useStore = defineStore("globalStore", () => {
     setRouterLoading,
     setRequestLoading,
     setFullScreenLoading,
+    setApplyStatus,
   };
 });
 

+ 16 - 15
utils/request.js

@@ -43,12 +43,13 @@ const requestInterceptor = (config) => {
   const userStore = useUserStore();
   const cId = userStore.userInfo?.cId;
 
-  const method = String(config.method || "GET").toUpperCase();
-  if (method === "GET") {
-    config.data = { ...(config.data || {}), cId };
-  } else {
-    config.data = { ...(config.data || {}), cId };
-  }
+  const method = String(config.method || "GET").toUpperCase();
+  if (method === "GET") {
+    config.data = { ...(config.data || {}) };
+  } else {
+    console.log(config.data,'ccc')
+    config.data = { ...(config.data || {}) };
+  }
   if (!config.header["Content-Type"]) {
     config.header["Content-Type"] = "application/json";
   }
@@ -60,9 +61,9 @@ const responseInterceptor = (response, options = {}) => {
   const { data, statusCode } = response;
   // 处理业务错误
   if (statusCode === 200) {
-    if (options.responseType === "arraybuffer" || data instanceof ArrayBuffer) {
-      return data;
-    }
+    if (options.responseType === "arraybuffer" || data instanceof ArrayBuffer) {
+      return data;
+    }
     // 1. 捕获 401 未授权错误
     if (data.code === 401 || data.code === 600) {
       // 关键:判断当前页面是否为登录页,避免循环跳转
@@ -312,16 +313,16 @@ export const uploadFile = (url, file, data = {}, header = {}, checkCode = true)
 };
 
 // 快捷方法
-export const get = (url, data = {}, typeOrOptions = {}, options = {}) => {
-  const mergedOptions =
-    typeof typeOrOptions === "string"
-      ? { type: typeOrOptions, ...(options || {}) }
-      : (typeOrOptions || {});
+export const get = (url, data = {}, typeOrOptions = {}, options = {}) => {
+  const mergedOptions =
+    typeof typeOrOptions === "string"
+      ? { type: typeOrOptions, ...(options || {}) }
+      : (typeOrOptions || {});
   return request({
     url,
     method: "GET",
     data,
-    ...mergedOptions,
+    ...mergedOptions,
   });
 };
 

+ 10 - 2
windows/left-window.vue

@@ -20,7 +20,7 @@
       </view>
     </view>
     <view class="menu fixed">
-      <view class="menu-item ib-box" @click="setMode('ib')" v-if="mode !== 'ib'">
+      <view class="menu-item ib-box" @click="setMode('ib')" v-if="mode !== 'ib' && ibStatus">
         <cwg-icon name="crm-ib" :size="20" color="#6c8595" />
         <view class="menu-label" v-t="'Home.msg.Ib'" />
       </view>
@@ -36,13 +36,21 @@
 </template>
 
 <script lang="ts" setup>
-import { ref } from 'vue'
+import { ref,computed } from 'vue'
+import useUserStore from '@/stores/use-user-store'
 import { useMenuSplit } from '@/composables/useMenuSplit'
 const { menus, setSubmenuRef, setMode, handleClick, handleSubmenuClick, mode } = useMenuSplit()
+const { userInfo } = useUserStore()
 
 // 控制侧边栏折叠状态
 const isCollapsed = ref(false)
 
+// ib按钮展示
+const ibStatus = computed(() => {
+  console.log(userInfo)
+  return userInfo.customInfo.ibInvalid == 0 && !!userInfo.ibInfo
+})
+
 // 固定菜单项点击事件
 function handleFixedMenuClick() {
   // 切换侧边栏折叠状态