zhb 1 месяц назад
Родитель
Сommit
e899749723

+ 1 - 4
components/cwg-custom-footer.vue

@@ -7,10 +7,7 @@
                 <view class="desc-text" v-t="'newSignin.item11'" />
                 <view class="desc-text" v-t="'newSignin.item11'" />
                 <view class="desc-text">
                 <view class="desc-text">
                     <text v-t="'newSignin.item13'" />
                     <text v-t="'newSignin.item13'" />
-                    <cwg-link type="pdf1" :title="'newSignin.item13_1'" :url="'https://www.' +
-                        ho +
-                        '.com/doc/Risk-Disclosures-and-Acknowledgements-2020-08.pdf'
-                        " target="_blank" class="desc-link" />
+                    <cwg-link type="pdf" :title="'newSignin.item13_1'" :url="'pdf/Risk-Disclosures-and-Acknowledgements-2020-08.pdf'" target="_blank" class="desc-link" />
                     <text class="desc-text" v-t="'newSignin.item13_2'" />
                     <text class="desc-text" v-t="'newSignin.item13_2'" />
                 </view>
                 </view>
                 <text class="desc-text" v-t="'newSignin.item13_3'" />
                 <text class="desc-text" v-t="'newSignin.item13_3'" />

+ 5 - 6
components/cwg-page-wrapper.vue

@@ -149,17 +149,16 @@ const sidebarVisible = ref(false)
 const maskVisible = ref(false)
 const maskVisible = ref(false)
 
 
 function openLeftDrawer() {
 function openLeftDrawer() {
-  if (sidebarVisible.value) {
-    // 关闭时先隐藏遮罩层
+  // 真正显示时 → 关闭
+  if (maskVisible.value) {
     maskVisible.value = false
     maskVisible.value = false
-    // 等待遮罩层动画结束后再隐藏侧边栏
     setTimeout(() => {
     setTimeout(() => {
       sidebarVisible.value = false
       sidebarVisible.value = false
     }, 200)
     }, 200)
-  } else {
-    // 打开时先显示侧边栏
+  }
+  // 隐藏时 → 打开
+  else {
     sidebarVisible.value = true
     sidebarVisible.value = true
-    // 等待侧边栏动画结束后再显示遮罩层
     setTimeout(() => {
     setTimeout(() => {
       maskVisible.value = true
       maskVisible.value = true
     }, 200)
     }, 200)

+ 74 - 50
components/cwg-right-drawer.vue

@@ -9,23 +9,21 @@
                     <view class="drawer-header">
                     <view class="drawer-header">
                         <image class="avatar" src="/static/images/avatars.png" mode="aspectFill" />
                         <image class="avatar" src="/static/images/avatars.png" mode="aspectFill" />
                         <view class="user-info">
                         <view class="user-info">
-                            <text class="name">{{ displayName }}</text>
-                            <text class="cid">CID: {{ displayCid }}</text>
+                            <text class="name">{{ _displayName }}</text>
+                            <text class="cid">CID: {{ _displayCid }}</text>
                         </view>
                         </view>
                     </view>
                     </view>
-
                     <view class="menu-list">
                     <view class="menu-list">
-                        <view v-for="item in menuList" :key="item.key" class="menu-item"
-                            :class="{ active: activePath === item.path }" @click="handleNavigate(item.path)">
-                            <cwg-icon :name="item.icon" :size="16"
-                                :color="activePath === item.path ? '#0f172b' : '#0f172b'" />
-                            <text>{{ item.name }}</text>
+                        <view v-for="item in menuList" :key="item.id" class="menu-item"
+                            :class="{ active: _activePath === item.path }" @click="handleNavigate(item.path)">
+                            <cwg-icon :name="item.icon" :size="16" color="#0f172b" />
+                            <text v-t="item.name"></text>
                         </view>
                         </view>
                     </view>
                     </view>
                     <view class="logout-wrap">
                     <view class="logout-wrap">
                         <view class="logout-btn" @click="handleLogout">
                         <view class="logout-btn" @click="handleLogout">
                             <cwg-icon name="logout" :size="16" color="#ff9800" />
                             <cwg-icon name="logout" :size="16" color="#ff9800" />
-                            <text>Logout</text>
+                            <text v-t="'language.i6'"></text>
                         </view>
                         </view>
                     </view>
                     </view>
                 </view>
                 </view>
@@ -35,72 +33,98 @@
 </template>
 </template>
 
 
 <script setup lang="ts">
 <script setup lang="ts">
-import { computed, ref } from 'vue'
+import { ref, watch, onMounted } from 'vue'
+import { onLoad, onShow, onLaunch } from '@dcloudio/uni-app'
 import useRoute from '@/hooks/useRoute'
 import useRoute from '@/hooks/useRoute'
 import useUserStore from '@/stores/use-user-store'
 import useUserStore from '@/stores/use-user-store'
 import { userApi } from '@/api/user'
 import { userApi } from '@/api/user'
-import { useI18n } from "vue-i18n";
-const { t } = useI18n();
-import useRouter from "@/hooks/useRouter";
-const router = useRouter();
+import { useI18n } from "vue-i18n"
+import useRouter from "@/hooks/useRouter"
+
+const { t } = useI18n()
+const router = useRouter()
 const dropdownRef = ref(null)
 const dropdownRef = ref(null)
 const userStore = useUserStore()
 const userStore = useUserStore()
-const userInfo = computed<any>(() => userStore.userInfo?.customInfo || {})
+const route = useRoute()
+
+// 强制用 ref 让插槽能渲染
+const menuList = ref([])
+const _displayName = ref('--')
+const _displayCid = ref('--')
+const _activePath = ref('')
+
+// 初始化菜单
+function initMenu() {
+    menuList.value = [
+        { id: 1, path: '/pages/mine/info?type=1', name: 'PersonalManagement.Title.PersonalInformation', icon: 'crm-circle-user' },
+        { id: 2, path: '/pages/mine/info?type=2', name: 'PersonalManagement.Title.BankInformation', icon: 'crm-building-columns' },
+        { id: 3, path: '/pages/mine/info?type=3', name: 'PersonalManagement.Title.FileManagement', icon: 'crm-file' },
+        { id: 4, path: '/pages/mine/info?type=4', name: 'PersonalManagement.Title.SecurityCenter', icon: 'crm-lock' },
+    ]
+}
 
 
+// 强制同步用户信息
+function syncUserInfo() {
+    const info = userStore.userInfo?.customInfo || {}
+    const firstName = info.firstName || ''
+    const lastName = info.lastName || ''
+    _displayName.value = (firstName + ' ' + lastName).trim() || info.name || info.email || '--'
+    _displayCid.value = info.cId || info.id || '--'
+}
 
 
-const route = useRoute()
-const menuList = computed(() => [
-    {
-        id: 1, path: '/pages/mine/info?type=1', name: t('PersonalManagement.Title.PersonalInformation'), icon: 'crm-circle-user'
-    },
-    {
-        id: 2, path: '/pages/mine/info?type=2', name: t('PersonalManagement.Title.BankInformation'), icon: 'crm-building-columns'
-    },
-    {
-        id: 3, path: '/pages/mine/info?type=3', name: t('PersonalManagement.Title.FileManagement'), icon: 'crm-file'
-    },
-    {
-        id: 4, path: '/pages/mine/info?type=4', name: t('PersonalManagement.Title.SecurityCenter'), icon: 'crm-lock'
-    }
-]);
+// 强制同步路径
+function syncPath() {
+    _activePath.value = route.path + (route.query?.type ? `?type=${route.query.type}` : '')
+}
+
+onMounted(() => {
+    initMenu()
+    syncUserInfo()
+    syncPath()
+})
 
 
-const displayName = computed(() => {
-    const fullName = `${userInfo.value?.firstName || ''} ${userInfo.value?.lastName || ''}`.trim()
-    return fullName || userInfo.value?.name || userInfo.value?.email || '--'
+onShow(() => {
+    initMenu()
+    syncUserInfo()
+    syncPath()
 })
 })
 
 
-const displayCid = computed(() => userInfo.value?.cId || userInfo.value?.id || '--')
-const activePath = computed(() => route.path + (route.query?.type ? `?type=${route.query.type}` : '') || '')
+// 监听变化自动更新
+watch(() => userStore.userInfo, () => {
+    syncUserInfo()
+}, { deep: true })
+
+watch(() => route, () => {
+    syncPath()
+}, { deep: true })
 
 
+// 打开抽屉
+function openNotice() {
+    dropdownRef.value?.open()
+}
 
 
+// 关闭
 function close() {
 function close() {
     dropdownRef.value?.close()
     dropdownRef.value?.close()
-    console.log(userInfo, 1212);
 }
 }
 
 
-function handleNavigate(path: string) {
+// 跳转
+function handleNavigate(path) {
     router.push({ path })
     router.push({ path })
     close()
     close()
 }
 }
 
 
+// 登出
 async function handleLogout() {
 async function handleLogout() {
     try {
     try {
-        const res = await userApi.logout()
-        if (res.code === 200) {
-            userStore.clearUserInfo()
-            router.push('/pages/login/index')
-        }
-    } catch (error) {
-        userStore.clearUserInfo()
-        router.push('/pages/login/index')
-    }
+        await userApi.logout()
+    } catch (e) { }
+    userStore.clearUserInfo()
+    router.push('/pages/login/index')
     close()
     close()
 }
 }
 
 
-defineExpose({
-    open,
-    close
-})
+defineExpose({ openNotice, close })
 </script>
 </script>
 
 
 <style scoped lang="scss">
 <style scoped lang="scss">

+ 336 - 338
components/cwg-sidebar.vue

@@ -1,9 +1,8 @@
 <template>
 <template>
   <view class="cwg-sidebar">
   <view class="cwg-sidebar">
     <view class="wallet-widget">
     <view class="wallet-widget">
-      <view class="wallet-header" :class="{ 'header-bottom': isWalletOpen }"
-            @click="isWalletOpen = !isWalletOpen">
-        <view v-if="mode=='follow'" class="wallet-header-left">
+      <view class="wallet-header" :class="{ 'header-bottom': isWalletOpen }" @click="isWalletOpen = !isWalletOpen">
+        <view v-if="mode == 'follow'" class="wallet-header-left">
           <cwg-icon name="crm-payment" :size="16" color="#141d22" />
           <cwg-icon name="crm-payment" :size="16" color="#141d22" />
           <text>{{ t('Documentary.console.item14') }}</text>
           <text>{{ t('Documentary.console.item14') }}</text>
           <text class="wallet-header-text">{{ followBalance }} USD</text>
           <text class="wallet-header-text">{{ followBalance }} USD</text>
@@ -21,11 +20,11 @@
         <view class="wallet-body-header">
         <view class="wallet-body-header">
           <text class="drawer-title">隐藏余额</text>
           <text class="drawer-title">隐藏余额</text>
           <switch :checked="!isShow" @change="toggleShow" color="#6c8595"
           <switch :checked="!isShow" @change="toggleShow" color="#6c8595"
-                  style="transform:scale(0.7); margin-right: -10px;" />
+            style="transform:scale(0.7); margin-right: -10px;" />
         </view>
         </view>
 
 
         <view class="wallet-body-content">
         <view class="wallet-body-content">
-          <template v-if="mode==='follow'">
+          <template v-if="mode === 'follow'">
             <view class="balance-amount">{{ followBalance }} USD</view>
             <view class="balance-amount">{{ followBalance }} USD</view>
           </template>
           </template>
           <template v-else>
           <template v-else>
@@ -61,17 +60,16 @@
           <cwg-icon :name="item.icon" :size="20" color="#6c8595" />
           <cwg-icon :name="item.icon" :size="20" color="#6c8595" />
           <view class="menu-label" v-t="item.label" />
           <view class="menu-label" v-t="item.label" />
           <view class="chevron-icon" :class="{ 'expanded': item.isOpenMenu }">
           <view class="chevron-icon" :class="{ 'expanded': item.isOpenMenu }">
-            <cwg-icon v-if="item.children && item.children.length" name="crm-chevron-down" :size="20"
-                      color="#6c8595" />
+            <cwg-icon v-if="item.children && item.children.length" name="crm-chevron-down" :size="20" color="#6c8595" />
           </view>
           </view>
         </view>
         </view>
-        <view :ref="(el) => setSubmenuRef(index, el)" class="submenu-box" :a="index" :key1="item.path + index"
-              :b="item" :style="{
-                        height: !(item.children && item.children.length) ? '0px' : item.isOpenMenu ? item.submenuHeight + 'px' : '0px',
-                        transition: 'height 281ms cubic-bezier(0.4, 0, 0.2, 1)'
-                    }" :class="{ 'active': item.isOpenMenu }">
+        <view :ref="(el) => setSubmenuRef(index, el)" class="submenu-box" :a="index" :key1="item.path + index" :b="item"
+          :style="{
+            height: !(item.children && item.children.length) ? '0px' : item.isOpenMenu ? item.submenuHeight + 'px' : '0px',
+            transition: 'height 281ms cubic-bezier(0.4, 0, 0.2, 1)'
+          }" :class="{ 'active': item.isOpenMenu }">
           <cwg-submenu v-if="item.children && item.children.length" :submenu-items="item.children"
           <cwg-submenu v-if="item.children && item.children.length" :submenu-items="item.children"
-                       @submenu-click="handleClick1" />
+            @submenu-click="handleClick1" />
         </view>
         </view>
       </view>
       </view>
     </view>
     </view>
@@ -93,391 +91,391 @@
 </template>
 </template>
 
 
 <script lang="ts" setup>
 <script lang="ts" setup>
-  import { ref, computed, watch, onMounted } from 'vue'
-  import useUserStore from '@/stores/use-user-store'
-  import { useMenuSplit } from '@/composables/useMenuSplit'
-  import { storeToRefs } from 'pinia'
-  import { drawApi } from '@/service/draw'
-  import { ibApi } from '@/service/ib'
-  import { userToken } from '@/composables/config'
-  import useRouter from '@/hooks/useRouter'
-  import { useI18n } from 'vue-i18n'
-  import { documentaryApi } from '@/service/documentary'
-
-  const { t } = useI18n()
-  const router = useRouter()
-  const handleClick1 = (item: MenuItem) => {
-    emit('handle-click', item)
+import { ref, computed, watch, onMounted } from 'vue'
+import useUserStore from '@/stores/use-user-store'
+import { useMenuSplit } from '@/composables/useMenuSplit'
+import { storeToRefs } from 'pinia'
+import { drawApi } from '@/service/draw'
+import { ibApi } from '@/service/ib'
+import { userToken } from '@/composables/config'
+import useRouter from '@/hooks/useRouter'
+import { useI18n } from 'vue-i18n'
+import { documentaryApi } from '@/service/documentary'
+
+const { t } = useI18n()
+const router = useRouter()
+const handleClick1 = (item: MenuItem) => {
+  emit('handle-click', item)
+}
+const { menus, setSubmenuRef, setMode, handleClick, handleSubmenuClick, mode } = useMenuSplit(handleClick1)
+const userStore = useUserStore()
+const { userInfo } = storeToRefs(userStore)
+
+const emit = defineEmits(['handle-click'])
+
+// ib按钮展示
+const ibStatus = computed(() => {
+  const info: any = userInfo.value
+  return !!info && !!info.customInfo && info.customInfo.ibInvalid == 0 && !!info.ibInfo
+})
+
+const isWalletOpen = ref(true)
+const isShow = ref(true)
+const walletbalance = ref(0)
+const pendingWithdrawAmount = ref(0)
+const ibData = ref({} as any)
+const walletData = ref({} as any)
+
+const NumberDecimal = (value: any) => {
+  let realVal = ''
+  if (!isNaN(value) && value !== '') {
+    realVal = parseFloat(value).toFixed(2)
+  } else {
+    realVal = '0.00'
   }
   }
-  const { menus, setSubmenuRef, setMode, handleClick, handleSubmenuClick, mode } = useMenuSplit(handleClick1)
-  const userStore = useUserStore()
-  const { userInfo } = storeToRefs(userStore)
-
-  const emit = defineEmits(['handle-click'])
-
-  // ib按钮展示
-  const ibStatus = computed(() => {
-    const info: any = userInfo.value
-    return !!info && !!info.customInfo && info.customInfo.ibInvalid == 0 && !!info.ibInfo
-  })
-
-  const isWalletOpen = ref(true)
-  const isShow = ref(true)
-  const walletbalance = ref(0)
-  const pendingWithdrawAmount = ref(0)
-  const ibData = ref({} as any)
-  const walletData = ref({} as any)
-
-  const NumberDecimal = (value: any) => {
-    let realVal = ''
-    if (!isNaN(value) && value !== '') {
-      realVal = parseFloat(value).toFixed(2)
-    } else {
-      realVal = '0.00'
-    }
-    return realVal
+  return realVal
+}
+const NumberDesensitization = (value: any) => {
+  let realVal = ''
+  if (!isNaN(value) && value !== '') {
+    value = value.toString()
+    realVal = value.substr(0, 2) + '****' + value.substr(-2)
+  } else {
+    realVal = '--'
   }
   }
-  const NumberDesensitization = (value: any) => {
-    let realVal = ''
-    if (!isNaN(value) && value !== '') {
-      value = value.toString()
-      realVal = value.substr(0, 2) + '****' + value.substr(-2)
-    } else {
-      realVal = '--'
+  return realVal
+}
+
+const formattedBalance = computed(() => {
+  const value = walletbalance.value || '0'
+  const decimalValue = NumberDecimal(value)
+  return isShow.value ? decimalValue : NumberDesensitization(decimalValue)
+})
+
+const ibBalance = computed(() => {
+  const value = NumberDecimal(ibData.value?.balance || 0)
+  return isShow.value ? value : NumberDesensitization(value)
+})
+
+const formattedPendingWithdrawAmount = computed(() => {
+  const value = pendingWithdrawAmount.value || '0'
+  const decimalValue = NumberDecimal(value)
+  return isShow.value ? decimalValue : NumberDesensitization(decimalValue)
+})
+
+const ibTotalBalance = computed(() => {
+  const value = NumberDecimal(ibData.value?.all || 0)
+  return isShow.value ? value : NumberDesensitization(value)
+})
+// 跟单分润
+const followBalance = computed(() => {
+  const value = NumberDecimal(walletData.value?.walletAmount || 0)
+  return isShow.value ? value : NumberDesensitization(value)
+})
+const getWalletList = async () => {
+  let res = await drawApi.walletbalance({})
+  if (res.code == 200) {
+    if (res.data != null) {
+      walletbalance.value = res.data
     }
     }
-    return realVal
+  } else {
+    uni.showToast({ title: res.msg, icon: 'none' })
   }
   }
-
-  const formattedBalance = computed(() => {
-    const value = walletbalance.value || '0'
-    const decimalValue = NumberDecimal(value)
-    return isShow.value ? decimalValue : NumberDesensitization(decimalValue)
-  })
-
-  const ibBalance = computed(() => {
-    const value = NumberDecimal(ibData.value?.balance || 0)
-    return isShow.value ? value : NumberDesensitization(value)
-  })
-
-  const formattedPendingWithdrawAmount = computed(() => {
-    const value = pendingWithdrawAmount.value || '0'
-    const decimalValue = NumberDecimal(value)
-    return isShow.value ? decimalValue : NumberDesensitization(decimalValue)
-  })
-
-  const ibTotalBalance = computed(() => {
-    const value = NumberDecimal(ibData.value?.all || 0)
-    return isShow.value ? value : NumberDesensitization(value)
-  })
-  // 跟单分润
-  const followBalance = computed(() => {
-    const value = NumberDecimal(walletData.value?.walletAmount || 0)
-    return isShow.value ? value : NumberDesensitization(value)
-  })
-  const getWalletList = async () => {
-    let res = await drawApi.walletbalance({})
-    if (res.code == 200) {
-      if (res.data != null) {
-        walletbalance.value = res.data
-      }
-    } else {
-      uni.showToast({ title: res.msg, icon: 'none' })
+}
+
+//获取处理中出金金额
+const getPendingWithdrawAmount = async () => {
+  let res = await drawApi.pendingWithdrawAmount({})
+  if (res.code == 200) {
+    if (res.data != null) {
+      pendingWithdrawAmount.value = res.data
     }
     }
+  } else {
+    uni.showToast({
+      title: res.msg,
+      icon: 'none',
+    })
   }
   }
-
-  //获取处理中出金金额
-  const getPendingWithdrawAmount = async () => {
-    let res = await drawApi.pendingWithdrawAmount({})
-    if (res.code == 200) {
-      if (res.data != null) {
-        pendingWithdrawAmount.value = res.data
-      }
-    } else {
-      uni.showToast({
-        title: res.msg,
-        icon: 'none',
-      })
-    }
+}
+
+const getIbData = async () => {
+  const res = await ibApi.IbData()
+  if (res.code === 200) {
+    if (res.data != null) ibData.value = res.data
+  } else {
+    uni.showToast({ title: res.msg, icon: 'none' })
   }
   }
-
-  const getIbData = async () => {
-    const res = await ibApi.IbData()
-    if (res.code === 200) {
-      if (res.data != null) ibData.value = res.data
-    } else {
-      uni.showToast({ title: res.msg, icon: 'none' })
+}
+//跟单金额
+const getMoneyList = async () => {
+  let res = await documentaryApi.followWalletSingle({})
+  if (res.code == 200) {
+    if (res.data != null) {
+      walletData.value = res.data
     }
     }
+  } else {
+    uni.showToast({
+      title: res.msg,
+      icon: 'none',
+    })
   }
   }
-  //跟单金额
-  const getMoneyList = async () => {
-    let res = await documentaryApi.followWalletSingle({})
-    if (res.code == 200) {
-      if (res.data != null) {
-        walletData.value = res.data
-      }
-    } else {
-      uni.showToast({
-        title: res.msg,
-        icon: 'none',
-      })
-    }
+}
+
+watch(() => mode.value, (newMode) => {
+  if (!userToken.value) return
+  if (newMode == 'customer') {
+    getWalletList()
+    getPendingWithdrawAmount()
+  } else if (newMode == 'ib') {
+    getIbData()
+  } else if (newMode == 'follow') {
+    getMoneyList()
   }
   }
-
-  watch(() => mode.value, (newMode) => {
-    if (!userToken.value) return
-    if (newMode == 'customer') {
-      getWalletList()
-      getPendingWithdrawAmount()
-    } else if (newMode == 'ib') {
-      getIbData()
-    }else if (newMode == 'follow') {
-      getMoneyList()
-    }
-  }, { immediate: true })
-
-  const toggleShow = (e: any) => {
-    isShow.value = !e.detail.value
-  }
-
-  const goPages = (type: number) => {
-    let path = ''
-    if (type == 1) {
-      path = '/pages/customer/wallet-transfer'
-    } else if (type == 2) {
-      path = '/pages/customer/wallet-history'
-    }
-    if (path) router.push(path)
+}, { immediate: true })
+
+const toggleShow = (e: any) => {
+  isShow.value = !e.detail.value
+}
+
+const goPages = (type: number) => {
+  let path = ''
+  if (type == 1) {
+    path = '/pages/customer/wallet-transfer'
+  } else if (type == 2) {
+    path = '/pages/customer/wallet-history'
   }
   }
-  const goFollow = (type: number) => {
-    router.push('/pages/follow/transfer')
-  }
-
-  const goIbPages = (type: number) => {
-    let path = ''
-    let query = {}
-    if (type == 1) {
-      path = '/pages/ib/withdraw-select'
-    } else if (type == 2) {
-      path = '/pages/ib/transfer'
-    } else if (type == 3) {
-      path = '/pages/ib/transfer'
-      query = { tab: 2 }
-    }
-    if (path) router.push({ path, query })
+  if (path) router.push(path)
+}
+const goFollow = (type: number) => {
+  router.push('/pages/follow/transfer')
+}
+
+const goIbPages = (type: number) => {
+  let path = ''
+  let query = {}
+  if (type == 1) {
+    path = '/pages/ib/withdraw-select'
+  } else if (type == 2) {
+    path = '/pages/ib/transfer'
+  } else if (type == 3) {
+    path = '/pages/ib/transfer'
+    query = { tab: 2 }
   }
   }
+  if (path) router.push({ path, query })
+}
 </script>
 </script>
 
 
 <style scoped lang="scss">
 <style scoped lang="scss">
-  @import "@/uni.scss";
-
-  .cwg-sidebar {
-    width: px2rpx(280);
-    color: #6c8595;
-    height: calc(100vh - 56px);
-    overflow: auto;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    padding: px2rpx(8);
-    padding-top: px2rpx(20);
-    box-sizing: border-box;
-    gap: px2rpx(8);
-    border-right: 1px solid rgba(108, 133, 149, 0.12);
-
-    .wallet-widget {
-      width: 100%;
-      //border-radius: px2rpx(4);
-      border-top: 1px solid rgba(108, 133, 149, 0.12);
+@import "@/uni.scss";
+
+.cwg-sidebar {
+  width: px2rpx(280);
+  color: #6c8595;
+  height: calc(100vh - (56px + var(--status-bar-height)));
+  overflow: auto;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: px2rpx(8);
+  padding-top: px2rpx(20);
+  box-sizing: border-box;
+  gap: px2rpx(8);
+  border-right: 1px solid rgba(108, 133, 149, 0.12);
+
+  .wallet-widget {
+    width: 100%;
+    //border-radius: px2rpx(4);
+    border-top: 1px solid rgba(108, 133, 149, 0.12);
+    border-bottom: 1px solid rgba(108, 133, 149, 0.12);
+    overflow: hidden;
+    margin-bottom: px2rpx(4);
+
+    .header-bottom {
       border-bottom: 1px solid rgba(108, 133, 149, 0.12);
       border-bottom: 1px solid rgba(108, 133, 149, 0.12);
-      overflow: hidden;
-      margin-bottom: px2rpx(4);
+    }
 
 
-      .header-bottom {
-        border-bottom: 1px solid rgba(108, 133, 149, 0.12);
-      }
+    .wallet-header {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      padding: px2rpx(10) px2rpx(12);
+      //background: #f4f6f8;
+
+      cursor: pointer;
 
 
-      .wallet-header {
+      .wallet-header-left {
         display: flex;
         display: flex;
         align-items: center;
         align-items: center;
-        justify-content: space-between;
-        padding: px2rpx(10) px2rpx(12);
-        //background: #f4f6f8;
+        gap: px2rpx(8);
+      }
 
 
-        cursor: pointer;
+      .wallet-header-text {
+        font-size: 14px;
+        color: #141d22;
+        font-weight: 500;
+      }
 
 
-        .wallet-header-left {
-          display: flex;
-          align-items: center;
-          gap: px2rpx(8);
-        }
+      .wallet-header-right {
+        transition: transform 0.3s;
 
 
-        .wallet-header-text {
-          font-size: 14px;
-          color: #141d22;
-          font-weight: 500;
+        &.expanded {
+          transform: rotate(180deg);
         }
         }
+      }
+    }
 
 
-        .wallet-header-right {
-          transition: transform 0.3s;
+    .wallet-body {
+      padding: px2rpx(12);
+      background: #ffffff;
 
 
-          &.expanded {
-            transform: rotate(180deg);
-          }
+      .wallet-body-header {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        margin-bottom: px2rpx(12);
+
+        .drawer-title {
+          font-size: 13px;
+          color: #6c8595;
         }
         }
       }
       }
 
 
-      .wallet-body {
-        padding: px2rpx(12);
-        background: #ffffff;
+      .wallet-body-content {
+        margin-bottom: px2rpx(16);
 
 
-        .wallet-body-header {
-          display: flex;
-          align-items: center;
-          justify-content: space-between;
-          margin-bottom: px2rpx(12);
-
-          .drawer-title {
-            font-size: 13px;
-            color: #6c8595;
-          }
+        .balance-amount {
+          font-size: 16px;
+          font-weight: 600;
+          color: #141d22;
+          margin-bottom: px2rpx(4);
         }
         }
 
 
-        .wallet-body-content {
-          margin-bottom: px2rpx(16);
+        .wallet-type {
+          font-size: 12px;
+          color: #999;
+          margin-bottom: px2rpx(4);
+        }
 
 
-          .balance-amount {
-            font-size: 16px;
-            font-weight: 600;
-            color: #141d22;
-            margin-bottom: px2rpx(4);
-          }
+        .wallet-id-box {
+          display: flex;
+          align-items: center;
+          gap: px2rpx(4);
 
 
-          .wallet-type {
+          .wallet-id {
             font-size: 12px;
             font-size: 12px;
             color: #999;
             color: #999;
-            margin-bottom: px2rpx(4);
           }
           }
+        }
+      }
 
 
-          .wallet-id-box {
-            display: flex;
-            align-items: center;
-            gap: px2rpx(4);
+      .wallet-actions {
+        display: flex;
+        gap: px2rpx(8);
+
+        .action-btn {
+          flex: 1;
+          height: px2rpx(32);
+          line-height: px2rpx(32);
+          background-color: #f5f7fa;
+          color: #141d22;
+          font-size: 13px;
+          border-radius: px2rpx(4);
+          margin: 0;
 
 
-            .wallet-id {
-              font-size: 12px;
-              color: #999;
-            }
+          &::after {
+            border: none;
           }
           }
-        }
 
 
-        .wallet-actions {
-          display: flex;
-          gap: px2rpx(8);
-
-          .action-btn {
-            flex: 1;
-            height: px2rpx(32);
-            line-height: px2rpx(32);
-            background-color: #f5f7fa;
-            color: #141d22;
-            font-size: 13px;
-            border-radius: px2rpx(4);
-            margin: 0;
-
-            &::after {
-              border: none;
-            }
-
-            &:active {
-              background-color: #e4e7ed;
-            }
+          &:active {
+            background-color: #e4e7ed;
           }
           }
         }
         }
       }
       }
     }
     }
+  }
 
 
-    .logo {
-      width: px2rpx(54);
-    }
+  .logo {
+    width: px2rpx(54);
+  }
 
 
-    .menu-list {
-      flex: 1;
-      width: 100%;
-      overflow-y: auto;
-      display: flex;
-      flex-direction: column;
-      gap: px2rpx(8);
-    }
+  .menu-list {
+    flex: 1;
+    width: 100%;
+    overflow-y: auto;
+    display: flex;
+    flex-direction: column;
+    gap: px2rpx(8);
+  }
 
 
-    .submenu-box {
-      width: 100%;
-      height: 0;
-      overflow: hidden;
-    }
+  .submenu-box {
+    width: 100%;
+    height: 0;
+    overflow: hidden;
+  }
 
 
-    .menu {
-      width: 100%;
-      position: relative;
-      display: flex;
-      flex-direction: column;
-      align-items: center;
-      box-sizing: border-box;
+  .menu {
+    width: 100%;
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    box-sizing: border-box;
 
 
-    }
+  }
 
 
-    .menu-item {
-      width: 100%;
-      height: px2rpx(40);
-      cursor: pointer;
-      display: flex;
-      align-items: center;
-      justify-content: space-between;
-      gap: px2rpx(8);
-      padding: px2rpx(10);
-      box-sizing: border-box;
-      font-size: 14px;
+  .menu-item {
+    width: 100%;
+    height: px2rpx(40);
+    cursor: pointer;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    gap: px2rpx(8);
+    padding: px2rpx(10);
+    box-sizing: border-box;
+    font-size: 14px;
 
 
-      .menu-label {
-        flex: 1;
-      }
+    .menu-label {
+      flex: 1;
+    }
 
 
-      &:hover {
-        background: rgba(108, 133, 149, 0.12) !important;
-        border: 1px solid rgb(145, 163, 176) !important;
-        border-radius: px2rpx(4);
-      }
+    &:hover {
+      background: rgba(108, 133, 149, 0.12) !important;
+      border: 1px solid rgb(145, 163, 176) !important;
+      border-radius: px2rpx(4);
+    }
 
 
-      .expanded .icon {
-        transform: rotate(180deg);
-      }
+    .expanded .icon {
+      transform: rotate(180deg);
     }
     }
+  }
+
+  .ib-box {
+    background: rgba(140, 69, 246, 0.08) !important;
+    border: 1px solid rgba(140, 69, 246, 0.2) !important;
+    font-size: px2rpx(18);
+    font-weight: 600;
+    color: #141d22;
 
 
-    .ib-box {
+    &:hover {
       background: rgba(140, 69, 246, 0.08) !important;
       background: rgba(140, 69, 246, 0.08) !important;
       border: 1px solid rgba(140, 69, 246, 0.2) !important;
       border: 1px solid rgba(140, 69, 246, 0.2) !important;
-      font-size: px2rpx(18);
-      font-weight: 600;
-      color: #141d22;
-
-      &:hover {
-        background: rgba(140, 69, 246, 0.08) !important;
-        border: 1px solid rgba(140, 69, 246, 0.2) !important;
-      }
     }
     }
+  }
 
 
-    .zy-box {
-      display: flex;
-      align-items: center;
-      justify-content: center;
-    }
+  .zy-box {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
 
 
-    .fixed {
-      position: relative;
-      width: 100%;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      gap: px2rpx(8);
-    }
+  .fixed {
+    position: relative;
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    gap: px2rpx(8);
   }
   }
+}
 </style>
 </style>

+ 54 - 126
composables/useMenuSplit.ts

@@ -25,6 +25,8 @@ function cloneMenu(menus: MenuItem[]): MenuItem[] {
         ...item,
         ...item,
         children: item.children ? cloneMenu(item.children) : [],
         children: item.children ? cloneMenu(item.children) : [],
         isOpenMenu: item.isOpenMenu ?? false,
         isOpenMenu: item.isOpenMenu ?? false,
+        // 🔥 直接按数量 × 40px
+        submenuHeight: (item.children?.length || 0) * ((40 + 8)) + 8,
     }))
     }))
 }
 }
 
 
@@ -37,13 +39,10 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
     const { host } = Config
     const { host } = Config
     const router = useRouter()
     const router = useRouter()
     const route = useRoute()
     const route = useRoute()
-    // 子菜单 DOM 引用
+
     const submenuRefs = ref<any[]>([])
     const submenuRefs = ref<any[]>([])
-    function setSubmenuRef(index: number, el: HTMElement | null) {
-        if (el) {
-            submenuRefs.value[index] = el
-        }
-    }
+    function setSubmenuRef(index: number, el: HTMLElement | null) { }
+
     // 设置全局模式
     // 设置全局模式
     function setMode(code: string) {
     function setMode(code: string) {
         globalStore.setMode(code);
         globalStore.setMode(code);
@@ -63,54 +62,19 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
         if (code === 'ib') {
         if (code === 'ib') {
             uni.$emit('open-ib')
             uni.$emit('open-ib')
         }
         }
-        nextTick(() => {
-            submenuRefs.value = [] // 重置,等待重新绑定
-            menus.value.forEach((item, index) => {
-                if (item.isOpenMenu && item.children && item.children.length) {
-                    updateSubmenuHeight(index)
-                }
-            })
-        })
-    }
-    // 测量元素实际高度(用于过渡动画)
-    const measureHeight = (element: HTMLElement): number => {
-        const originalDisplay = element.style.display
-        const originalPosition = element.style.position
-        const originalVisibility = element.style.visibility
-        const originalWidth = element.style.width
-        element.style.display = 'block'
-        element.style.position = 'absolute'
-        element.style.visibility = 'hidden'
-        element.style.width = '100%'
-        const height = element.scrollHeight || element.offsetHeight
-        element.style.display = originalDisplay
-        element.style.position = originalPosition
-        element.style.visibility = originalVisibility
-        element.style.width = originalWidth
-        return height
-    }
-    // 更新指定索引的子菜单高度
-    const updateSubmenuHeight = (index: number) => {
-        const refs = submenuRefs.value
-        nextTick(() => {
-            if (refs && refs[index]) {
-                const el = refs[index].$el || refs[index]
-                const height = measureHeight(el)
-                if (height > 0) {
-                    menus.value[index].submenuHeight = height
-                }
-            }
-        })
     }
     }
+
+    // 🔥 已删除:measureHeight
+    // 🔥 已删除:updateSubmenuHeight
+
     let clickTimer: ReturnType<typeof setTimeout> | null = null
     let clickTimer: ReturnType<typeof setTimeout> | null = null
-    // 点击菜单项(切换展开/折叠或跳转)
     function handleClick(index: number) {
     function handleClick(index: number) {
         if (clickTimer) return
         if (clickTimer) return
         clickTimer = setTimeout(() => {
         clickTimer = setTimeout(() => {
             clickTimer = null
             clickTimer = null
         }, 300)
         }, 300)
         const item = menus.value[index]
         const item = menus.value[index]
-        // 无子菜单:执行跳转或特殊操作
+
         if (!item.children || item.children.length === 0) {
         if (!item.children || item.children.length === 0) {
             // #ifdef H5
             // #ifdef H5
             if (item.type === 'chat' && !shouldShowLanguageMenu.value) {
             if (item.type === 'chat' && !shouldShowLanguageMenu.value) {
@@ -128,20 +92,15 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
             router.push(item.path)
             router.push(item.path)
             return
             return
         }
         }
-        // 有子菜单:切换展开/折叠状态
+
         item.isOpenMenu = !item.isOpenMenu
         item.isOpenMenu = !item.isOpenMenu
-        if (item.isOpenMenu) {
-            nextTick(() => updateSubmenuHeight(index))
-        }
     }
     }
-    // 子菜单项点击事件(由 cwg-submenu 组件发出)
+
     function handleSubmenuClick(subItem: any) {
     function handleSubmenuClick(subItem: any) {
-        // 处理语言切换
         if (subItem.type === 'lang') {
         if (subItem.type === 'lang') {
             locale.value = subItem.lang
             locale.value = subItem.lang
             return
             return
         }
         }
-        // 处理外部链接
         if (subItem.isExternal) {
         if (subItem.isExternal) {
             // #ifdef H5
             // #ifdef H5
             window.open(subItem.path, '_blank')
             window.open(subItem.path, '_blank')
@@ -151,20 +110,12 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
             // #endif
             // #endif
             return
             return
         }
         }
-        // 内部页面跳转
         shouldShowLanguageMenu.value && handleClick1(subItem)
         shouldShowLanguageMenu.value && handleClick1(subItem)
         router.push(subItem.path)
         router.push(subItem.path)
-
     }
     }
 
 
-    // 窗口大小变化时重新计算所有已展开子菜单的高度
-    const handleResize = () => {
-        menus.value.forEach((item, index) => {
-            if (item.isOpenMenu && item.children && item.children.length) {
-                updateSubmenuHeight(index)
-            }
-        })
-    }
+    const handleResize = () => { }
+
     const customMenuList = computed(() =>
     const customMenuList = computed(() =>
         localesList.map((code) => ({
         localesList.map((code) => ({
             label: `language.${code}`,
             label: `language.${code}`,
@@ -180,12 +131,13 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
         label: 'language.index',
         label: 'language.index',
         icon: 'cwg-lang',
         icon: 'cwg-lang',
         children: customMenuList.value,
         children: customMenuList.value,
-        submenuHeight: 0,
+        submenuHeight: customMenuList.value.length * ((40 + 8)) + 8,
     }))
     }))
+
     const customerBaseMenus = computed<MenuItem[]>(() => [
     const customerBaseMenus = computed<MenuItem[]>(() => [
         {
         {
             isOpenMenu: false,
             isOpenMenu: false,
-            submenuHeight: 0,
+            submenuHeight: 4 * ((40 + 8)) + 8,
             path: '/',
             path: '/',
             label: 'Shop.Index.Transaction',
             label: 'Shop.Index.Transaction',
             icon: 'crm-trade',
             icon: 'crm-trade',
@@ -198,7 +150,7 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
         },
         },
         {
         {
             isOpenMenu: false,
             isOpenMenu: false,
-            submenuHeight: 0,
+            submenuHeight: 6 * ((40 + 8)) + 8,
             path: '/',
             path: '/',
             label: 'vu.item6',
             label: 'vu.item6',
             icon: 'crm-payment',
             icon: 'crm-payment',
@@ -217,21 +169,17 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
             label: 'Home.page_customer.item6',
             label: 'Home.page_customer.item6',
             icon: 'crm-hd',
             icon: 'crm-hd',
             children: [],
             children: [],
+            submenuHeight: 0,
         },
         },
         {
         {
             path: '/',
             path: '/',
             isOpenMenu: false,
             isOpenMenu: false,
+            submenuHeight: 2 * ((40 + 8)) + 8,
             label: 'vu.item5',
             label: 'vu.item5',
             icon: 'crm-chart-area',
             icon: 'crm-chart-area',
             children: [
             children: [
                 { path: '/pages/analytics/analystViews', label: 'News.Announcement', icon: 'icon-application' },
                 { path: '/pages/analytics/analystViews', label: 'News.Announcement', icon: 'icon-application' },
                 { path: '/pages/analytics/news', label: 'News.NewsInformation', icon: 'icon-application' },
                 { path: '/pages/analytics/news', label: 'News.NewsInformation', icon: 'icon-application' },
-                // {
-                //     path: `https://www.${host}.com/${locale.value}/economic-calendar`,
-                //     label: 'News.FinancialCalendar',
-                //     icon: 'icon-application',
-                //     isExternal: true,
-                // },
             ],
             ],
         },
         },
         {
         {
@@ -240,6 +188,7 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
             label: 'Downloadpage.item1',
             label: 'Downloadpage.item1',
             icon: 'crm-download',
             icon: 'crm-download',
             children: [],
             children: [],
+            submenuHeight: 0,
         },
         },
         {
         {
             path: '/pages/common/chat',
             path: '/pages/common/chat',
@@ -248,10 +197,12 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
             icon: 'crm-headset',
             icon: 'crm-headset',
             children: [],
             children: [],
             type: 'chat',
             type: 'chat',
+            submenuHeight: 0,
         },
         },
         {
         {
             path: '/',
             path: '/',
             isOpenMenu: false,
             isOpenMenu: false,
+            submenuHeight: 5 * ((40 + 8)) + 8,
             label: 'Custom.Index.Settings',
             label: 'Custom.Index.Settings',
             icon: 'crm-sz',
             icon: 'crm-sz',
             children: [
             children: [
@@ -263,17 +214,20 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
             ],
             ],
         },
         },
     ])
     ])
+
     const ibBaseMenus = computed<MenuItem[]>(() => [
     const ibBaseMenus = computed<MenuItem[]>(() => [
         {
         {
             isOpenMenu: false,
             isOpenMenu: false,
             path: '/pages/ib/index',
             path: '/pages/ib/index',
             label: 'Documentary.console.item1',
             label: 'Documentary.console.item1',
             icon: 'crm-mb',
             icon: 'crm-mb',
+            submenuHeight: 0,
         },
         },
         {
         {
             path: '/',
             path: '/',
             label: 'Ib.Custom.Manage3',
             label: 'Ib.Custom.Manage3',
             icon: 'crm-bg',
             icon: 'crm-bg',
+            submenuHeight: 4 * ((40 + 8)) + 8,
             children: [
             children: [
                 { path: '/pages/ib/customer', label: 'Ib.Custom.Manage3', icon: 'icon-deposit' },
                 { path: '/pages/ib/customer', label: 'Ib.Custom.Manage3', icon: 'icon-deposit' },
                 { path: '/pages/ib/subsList', label: 'Ib.Custom.Manage2', icon: 'icon-deposit' },
                 { path: '/pages/ib/subsList', label: 'Ib.Custom.Manage2', icon: 'icon-deposit' },
@@ -283,7 +237,7 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
         },
         },
         {
         {
             isOpenMenu: false,
             isOpenMenu: false,
-            submenuHeight: 0,
+            submenuHeight: 4 * ((40 + 8)) + 8,
             path: '/',
             path: '/',
             label: 'vu.item6',
             label: 'vu.item6',
             icon: 'crm-payment',
             icon: 'crm-payment',
@@ -296,6 +250,7 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
         },
         },
         {
         {
             isOpenMenu: false,
             isOpenMenu: false,
+            submenuHeight: 2 * ((40 + 8)) + 8,
             path: '/',
             path: '/',
             label: 'Home.page_ib.item3',
             label: 'Home.page_ib.item3',
             icon: 'crm-newspaper',
             icon: 'crm-newspaper',
@@ -305,22 +260,25 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
             ],
             ],
         },
         },
     ])
     ])
+
     const followBaseMenus = computed<MenuItem[]>(() => [
     const followBaseMenus = computed<MenuItem[]>(() => [
         {
         {
             isOpenMenu: false,
             isOpenMenu: false,
             path: '/pages/follow/index',
             path: '/pages/follow/index',
             label: 'Documentary.console.item1',
             label: 'Documentary.console.item1',
             icon: 'crm-mb',
             icon: 'crm-mb',
+            submenuHeight: 0,
         },
         },
         {
         {
             isOpenMenu: false,
             isOpenMenu: false,
             path: '/pages/follow/trading-center',
             path: '/pages/follow/trading-center',
             label: 'Documentary.page_doc.item2',
             label: 'Documentary.page_doc.item2',
             icon: 'crm-gd',
             icon: 'crm-gd',
+            submenuHeight: 0,
         },
         },
         {
         {
             isOpenMenu: false,
             isOpenMenu: false,
-            submenuHeight: 0,
+            submenuHeight: 1 * ((40 + 8)) + 8,
             path: '/',
             path: '/',
             label: 'Documentary.page_doc.item3',
             label: 'Documentary.page_doc.item3',
             icon: 'crm-newspaper',
             icon: 'crm-newspaper',
@@ -330,7 +288,7 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
         },
         },
         {
         {
             isOpenMenu: false,
             isOpenMenu: false,
-            submenuHeight: 0,
+            submenuHeight: 2 * ((40 + 8)) + 8,
             path: '/',
             path: '/',
             label: 'Documentary.page_doc.item4',
             label: 'Documentary.page_doc.item4',
             icon: 'crm-payment',
             icon: 'crm-payment',
@@ -341,7 +299,7 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
         },
         },
         {
         {
             isOpenMenu: false,
             isOpenMenu: false,
-            submenuHeight: 0,
+            submenuHeight: 5 * ((40 + 8)) + 8,
             path: '/',
             path: '/',
             label: 'Documentary.page_doc.item5',
             label: 'Documentary.page_doc.item5',
             icon: 'crm-trade',
             icon: 'crm-trade',
@@ -354,76 +312,46 @@ export function useMenuSplit(handleClick1: (item: MenuItem) => void) {
             ],
             ],
         },
         },
     ])
     ])
+
     const menus = ref<MenuItem[]>([])
     const menus = ref<MenuItem[]>([])
 
 
-    // 监听 mode 变化,自动导航到对应首页
     watch(mode, (newMode, oldMode) => {
     watch(mode, (newMode, oldMode) => {
         if (newMode !== oldMode) {
         if (newMode !== oldMode) {
             let base: MenuItem[] = []
             let base: MenuItem[] = []
             switch (newMode) {
             switch (newMode) {
-                case 'follow':
-                    base = [...followBaseMenus.value]
-                    break
-                case 'ib':
-                    base = [...ibBaseMenus.value]
-                    break
-                case 'customer':
-                    base = [...customerBaseMenus.value]
-                    break
-                default:
-                    break
-            }
-            if (shouldShowLanguageMenu.value) {
-                base.push(languageMenuItem.value)
+                case 'follow': base = [...followBaseMenus.value]; break
+                case 'ib': base = [...ibBaseMenus.value]; break
+                case 'customer': base = [...customerBaseMenus.value]; break
+                default: break
             }
             }
+            if (shouldShowLanguageMenu.value) base.push(languageMenuItem.value)
             menus.value = cloneMenu(base)
             menus.value = cloneMenu(base)
         }
         }
     }, { immediate: true })
     }, { immediate: true })
-    // 监听路由变化:自动展开包含当前路径的父菜单,不自动关闭其他菜单
+
     watch(route, () => {
     watch(route, () => {
         const currentPath = route.path
         const currentPath = route.path
-        const shouldOpenIndices: number[] = []
         menus.value.forEach((item, idx) => {
         menus.value.forEach((item, idx) => {
-            if (item.children && item.children.length) {
+            if (item.children?.length) {
                 const isActive = item.children.some(child => {
                 const isActive = item.children.some(child => {
                     if (child.isExternal || child.type === 'lang') return false
                     if (child.isExternal || child.type === 'lang') return false
-                    return currentPath === child.path || currentPath.startsWith(child.path + '?') || currentPath.startsWith(child.path + '/')
+                    return currentPath === child.path || currentPath.startsWith(child.path + '?')
                 })
                 })
-                if (isActive && !item.isOpenMenu) {
-                    shouldOpenIndices.push(idx)
-                }
+                if (isActive) item.isOpenMenu = true
             }
             }
         })
         })
-        if (shouldOpenIndices.length) {
-            shouldOpenIndices.forEach(idx => {
-                menus.value[idx].isOpenMenu = true
-            })
-            nextTick(() => {
-                shouldOpenIndices.forEach(idx => updateSubmenuHeight(idx))
-            })
-        }
     }, { immediate: true })
     }, { immediate: true })
-    watch(windowWidth, handleResize)
 
 
-    onMounted(() => {
-        nextTick(() => {
-            menus.value.forEach((item, index) => {
-                if (item.isOpenMenu && item.children && item.children.length) {
-                    updateSubmenuHeight(index)
-                }
-            })
-        })
-    })
-    return {
-        menus,          // 最终菜单(已克隆,可直接修改 isOpenMenu 等)
-        mode,           // 只读或按需使用
-        shouldShowLanguageMenu, // 可选,供外部获取状态
-        windowWidth,          // 可选,供外部获取宽度(300)
-        setMode,              // 可选,供外部设置模式
-        setSubmenuRef,        // 可选,供外部设置子菜单引用
-        updateSubmenuHeight,  // 可选,供外部更新子菜单高度
-        handleClick,          // 可选,供外部处理点击事件
-        handleSubmenuClick,   // 可选,供外部处理子菜单点击事件
+    onMounted(() => { })
 
 
+    return {
+        menus,
+        mode,
+        shouldShowLanguageMenu,
+        windowWidth,
+        setMode,
+        setSubmenuRef,
+        handleClick,
+        handleSubmenuClick,
     }
     }
 }
 }

+ 14 - 1
pages/customer/components/AccountCardDesktop.vue

@@ -427,12 +427,21 @@ onBeforeUnmount(() => {
             margin-bottom: px2rpx(16);
             margin-bottom: px2rpx(16);
             flex-wrap: wrap;
             flex-wrap: wrap;
 
 
+            :deep(.cwg-dropdown-menu-container) {
+                left: px2rpx(-90) !important;
+
+                @media screen and (max-width: 768px) {
+                    left: px2rpx(-90) !important;
+                    width: px2rpx(140);
+                }
+            }
+
             .circle-btn {
             .circle-btn {
                 display: flex;
                 display: flex;
                 flex-direction: column;
                 flex-direction: column;
                 align-items: center;
                 align-items: center;
                 cursor: pointer;
                 cursor: pointer;
-                width: px2rpx(64);
+                width: px2rpx(54);
 
 
                 .circle-icon {
                 .circle-icon {
                     width: px2rpx(48);
                     width: px2rpx(48);
@@ -473,6 +482,10 @@ onBeforeUnmount(() => {
         .desktop-buttons {
         .desktop-buttons {
             display: none;
             display: none;
 
 
+            :deep(.cwg-dropdown-menu-container) {
+                left: px2rpx(-110) !important;
+            }
+
             .action-btn {
             .action-btn {
                 background: transparent;
                 background: transparent;
                 border: 1px solid rgba(108, 133, 149, 0);
                 border: 1px solid rgba(108, 133, 149, 0);

+ 4 - 0
pages/customer/components/AccountCardMobile.vue

@@ -473,6 +473,10 @@ onBeforeUnmount(() => {
 
 
     :deep(.cwg-dropdown-menu-container) {
     :deep(.cwg-dropdown-menu-container) {
         left: px2rpx(-190) !important;
         left: px2rpx(-190) !important;
+        @media screen and (max-width: 768px) {
+            left: px2rpx(-200) !important;
+            width: px2rpx(240);
+        }
     }
     }
 
 
     .more-btn {
     .more-btn {

+ 444 - 446
pages/login/index.vue

@@ -1,166 +1,166 @@
 <script setup>
 <script setup>
-  import { ref, onMounted, computed } from 'vue'
-  import QrCode from '@/components/QrCode.vue'
-  import { post } from '@/utils/request'
-  import { userToken } from '@/composables/config'
-  import { userApi } from '@/api/user'
-  import { ucardApi } from '@/api/ucard'
-  import { customApi } from '@/service/custom'
-  import useGlobalStore from '@/stores/use-global-store'
-  import useUserStore from '@/stores/use-user-store'
-  import useRouter from '@/hooks/useRouter'
-  import { useI18n } from 'vue-i18n'
-  import companyLogo from '@/static/images/logo4.png'
-  import LoginHeaderGroup from './components/LoginHeaderGroup.vue'
-
-  const router = useRouter()
-  const { t } = useI18n()
-  const userStore = useUserStore()
-  const globalStore = useGlobalStore()
-  const modeStore = computed(() => globalStore.mode)
-  // 响应式表单数据
-  const form = ref({
-    loginName: '',
-    password: '',
-  })
-
-  function submit() {
-    if (!form.value.loginName) {
-      uni.$u.toast(t('signin.form.email'))
-      return
-    }
-    if (!form.value.password) {
-      uni.$u.toast(t('signin.form.password'))
-      return
-    }
-
-    handleLogin()
+import { ref, onMounted, computed } from 'vue'
+import QrCode from '@/components/QrCode.vue'
+import { post } from '@/utils/request'
+import { userToken } from '@/composables/config'
+import { userApi } from '@/api/user'
+import { ucardApi } from '@/api/ucard'
+import { customApi } from '@/service/custom'
+import useGlobalStore from '@/stores/use-global-store'
+import useUserStore from '@/stores/use-user-store'
+import useRouter from '@/hooks/useRouter'
+import { useI18n } from 'vue-i18n'
+import companyLogo from '@/static/images/logo4.png'
+import LoginHeaderGroup from './components/LoginHeaderGroup.vue'
+
+const router = useRouter()
+const { t } = useI18n()
+const userStore = useUserStore()
+const globalStore = useGlobalStore()
+const modeStore = computed(() => globalStore.mode)
+// 响应式表单数据
+const form = ref({
+  loginName: '',
+  password: '',
+})
+
+function submit() {
+  if (!form.value.loginName) {
+    uni.$u.toast(t('signin.form.email'))
+    return
   }
   }
-
-  const customStyle = {
-    height: '44px',
-    'border-radius': '8px',
-    background: '#f7f8fa',
-    padding: '0 20px !important',
-    position: 'relative',
-  }
-  const remenber = ref([])
-  const checkboxChange = (e) => {
-    remenber.value = e
-  }
-  const fetchUserList = (params) => post('/Login/AcctLogin', params)
-
-  async function handleLogin() {
-    try {
-      const res = await userApi.login({
-        loginName: form.value.loginName,
-        password: form.value.password,
-      })
-      if (res.code === 200) {
-        userToken.value = res.data
-        uni.$u.toast(t('login.msg0_1'))
-        getCustomLoginInfo()
-        // getCardUserInfo();
-        reasonsRefusalList()
-        if (remenber.value.length) {
-          userStore.saveAccountInfo({
-            loginName: form.value.loginName,
-            password: form.value.password,
-            rememberPassword: true,
-          })
-        } else {
-          userStore.saveAccountInfo({
-            loginName: '',
-            password: '',
-            rememberPassword: false,
-          })
-        }
-        //  console.log(1111);
-      } else {
-        uni.showToast({ title: res.msg })
-        //  console.log(12112);
-      }
-    } catch (error) {
-      // console.log(error)
-      uni.showToast({ title: error.msg, icon: 'none' })
-      //  console.log(error, 19089);
-    }
+  if (!form.value.password) {
+    uni.$u.toast(t('signin.form.password'))
+    return
   }
   }
 
 
-  async function getCustomLoginInfo() {
-    try {
-      const res = await userApi.getUserInfo()
-      userStore.saveUserInfo(res.data)
-      if (res.code === 200) {
-        router.reLaunch(modeStore.value === 'customer' ? '/pages/customer/index' : '/pages/ib/index')
+  handleLogin()
+}
+
+const customStyle = {
+  height: '44px',
+  'border-radius': '8px',
+  background: '#f7f8fa',
+  padding: '0 20px !important',
+  position: 'relative',
+}
+const remenber = ref([])
+const checkboxChange = (e) => {
+  remenber.value = e
+}
+const fetchUserList = (params) => post('/Login/AcctLogin', params)
+
+async function handleLogin() {
+  try {
+    const res = await userApi.login({
+      loginName: form.value.loginName,
+      password: form.value.password,
+    })
+    if (res.code === 200) {
+      userToken.value = res.data
+      uni.$u.toast(t('login.msg0_1'))
+      getCustomLoginInfo()
+      // getCardUserInfo();
+      reasonsRefusalList()
+      if (remenber.value.length) {
+        userStore.saveAccountInfo({
+          loginName: form.value.loginName,
+          password: form.value.password,
+          rememberPassword: true,
+        })
       } else {
       } else {
-        uni.$u.toast(res.msg || t('login.msg0'))
+        userStore.saveAccountInfo({
+          loginName: '',
+          password: '',
+          rememberPassword: false,
+        })
       }
       }
-    } catch (error) {
-      //  console.log(error, 111);
+      //  console.log(1111);
+    } else {
+      uni.showToast({ title: res.msg })
+      //  console.log(12112);
     }
     }
+  } catch (error) {
+    // console.log(error)
+    uni.showToast({ title: error.msg, icon: 'none' })
+    //  console.log(error, 19089);
   }
   }
-
-  async function getCardUserInfo() {
-    try {
-      const res = await ucardApi.getSingle()
-      userStore.saveUserInfo(res.data)
-      if (res.code === 200) {
-        if (!res.data || res.data.approveStatus != 2) {
-          router.push('/pages/mine/improve')
-        } else {
-          router.push('/pages/card/index')
-        }
-      } else {
-        uni.$u.toast(res.msg || t('login.msg0'))
-      }
-    } catch (error) {
-      //  console.log(error, 111);
+}
+
+async function getCustomLoginInfo() {
+  try {
+    const res = await userApi.getUserInfo()
+    userStore.saveUserInfo(res.data)
+    if (res.code === 200) {
+      router.reLaunch(modeStore.value === 'customer' ? '/pages/customer/index' : '/pages/ib/index')
+    } else {
+      uni.$u.toast(res.msg || t('login.msg0'))
     }
     }
+  } catch (error) {
+    //  console.log(error, 111);
   }
   }
-
-  async function reasonsRefusalList() {
-    try {
-      const res = await customApi.reasonsRefusalList()
-      if (res.code === 200) {
-        pickFields(res.data)
+}
+
+async function getCardUserInfo() {
+  try {
+    const res = await ucardApi.getSingle()
+    userStore.saveUserInfo(res.data)
+    if (res.code === 200) {
+      if (!res.data || res.data.approveStatus != 2) {
+        router.push('/pages/mine/improve')
       } else {
       } else {
-        uni.$u.toast(res.msg || t('login.msg0'))
+        router.push('/pages/card/index')
       }
       }
-    } catch (error) {
-      //  console.log(error, 111);
+    } else {
+      uni.$u.toast(res.msg || t('login.msg0'))
     }
     }
+  } catch (error) {
+    //  console.log(error, 111);
   }
   }
+}
 
 
-  function pickFields(source, fields = ['content', 'enContent']) {
-    const result = {}
-
-    Object.entries(source).forEach(([key, value]) => {
-      result[key] = fields.reduce((acc, f) => {
-        acc[f] = value[f] ?? null
-        return acc
-      }, {})
-    })
-    userStore.saveReasonsOptions(result)
+async function reasonsRefusalList() {
+  try {
+    const res = await customApi.reasonsRefusalList()
+    if (res.code === 200) {
+      pickFields(res.data)
+    } else {
+      uni.$u.toast(res.msg || t('login.msg0'))
+    }
+  } catch (error) {
+    //  console.log(error, 111);
   }
   }
+}
 
 
-  onMounted(() => {
-    const hostParts = window.location.host.split('.')
-    ho.value = hostParts.length > 1 ? hostParts[1] : ''
+function pickFields(source, fields = ['content', 'enContent']) {
+  const result = {}
 
 
-    const accountInfo = userStore.accountInfo
-    if (accountInfo?.rememberPassword) {
-      form.value.loginName = accountInfo?.loginName || ''
-      form.value.password = accountInfo?.password || ''
-      remenber.value = ['记住我']
-    } else {
-      form.value.loginName = ''
-      form.value.password = ''
-      remenber.value = []
-    }
+  Object.entries(source).forEach(([key, value]) => {
+    result[key] = fields.reduce((acc, f) => {
+      acc[f] = value[f] ?? null
+      return acc
+    }, {})
   })
   })
-  const inputType = ref('password')
-  const ho = ref('')
+  userStore.saveReasonsOptions(result)
+}
+
+onMounted(() => {
+  const hostParts = window.location.host.split('.')
+  ho.value = hostParts.length > 1 ? hostParts[1] : ''
+
+  const accountInfo = userStore.accountInfo
+  if (accountInfo?.rememberPassword) {
+    form.value.loginName = accountInfo?.loginName || ''
+    form.value.password = accountInfo?.password || ''
+    remenber.value = ['记住我']
+  } else {
+    form.value.loginName = ''
+    form.value.password = ''
+    remenber.value = []
+  }
+})
+const inputType = ref('password')
+const ho = ref('')
 </script>
 </script>
 
 
 <template>
 <template>
@@ -211,12 +211,9 @@
                     <text v-html="t('newSignin.item11')"></text>
                     <text v-html="t('newSignin.item11')"></text>
                     <br />
                     <br />
                     <text v-t="'newSignin.item13'"></text>
                     <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>
+                    <cwg-link type="pdf" :title="'newSignin.item13_1'"
+                      :url="`pdf/Risk-Disclosures-and-Acknowledgements-2020-08.pdf`" target="_blank"
+                      v-t="'newSignin.item13_1'" class="doc-link" />
                     <text v-t="'newSignin.item13_2'"></text>
                     <text v-t="'newSignin.item13_2'"></text>
                     <!-- <view v-t="'newSignin.item13_3'"></view>
                     <!-- <view v-t="'newSignin.item13_3'"></view>
                     <text v-t="'newSignin.item13_4'"></text> -->
                     <text v-t="'newSignin.item13_4'"></text> -->
@@ -241,7 +238,7 @@
               <up-form :model="form" ref="uFormRef">
               <up-form :model="form" ref="uFormRef">
                 <up-form-item label="" prop="loginName">
                 <up-form-item label="" prop="loginName">
                   <up-input :customStyle="customStyle" v-model="form.loginName" border="none"
                   <up-input :customStyle="customStyle" v-model="form.loginName" border="none"
-                            :placeholder="t('signin.form.email')">
+                    :placeholder="t('signin.form.email')">
                     <template #prefix>
                     <template #prefix>
                       <cwg-icon name="email-outline" :size="20" color="#000" />
                       <cwg-icon name="email-outline" :size="20" color="#000" />
                     </template>
                     </template>
@@ -250,7 +247,7 @@
 
 
                 <up-form-item label="" prop="password">
                 <up-form-item label="" prop="password">
                   <up-input :customStyle="customStyle" v-model="form.password" :type="inputType" border="none"
                   <up-input :customStyle="customStyle" v-model="form.password" :type="inputType" border="none"
-                            :placeholder="t('signin.form.password')">
+                    :placeholder="t('signin.form.password')">
                     <template #prefix>
                     <template #prefix>
                       <cwg-icon name="lock-outline" :size="20" color="#000" />
                       <cwg-icon name="lock-outline" :size="20" color="#000" />
                     </template>
                     </template>
@@ -262,7 +259,7 @@
               <view class="check-box">
               <view class="check-box">
                 <up-checkbox-group v-model="remenber" @change="checkboxChange">
                 <up-checkbox-group v-model="remenber" @change="checkboxChange">
                   <up-checkbox size="14" labelSize="14" labelColor="#666666" activeColor="#ea002a"
                   <up-checkbox size="14" labelSize="14" labelColor="#666666" activeColor="#ea002a"
-                               :label="t('newSignin.item5')" name="记住我" class="wcg-checkbox"></up-checkbox>
+                    :label="t('newSignin.item5')" name="记住我" class="wcg-checkbox"></up-checkbox>
                 </up-checkbox-group>
                 </up-checkbox-group>
               </view>
               </view>
               <navigator url="/pages/login/reset" class="account-tip">
               <navigator url="/pages/login/reset" class="account-tip">
@@ -298,368 +295,369 @@
 </template>
 </template>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-  @import "@/uni.scss";
-
-  :deep(uni-content) {
-    padding-left: 0 !important;
-  }
-
-  .login-page {
-    height: 100vh;
-    border: none;
-    padding: 0;
-    position: relative;
-    display: flex;
-    flex-direction: column;
+@import "@/uni.scss";
+
+:deep(uni-content) {
+  padding-left: 0 !important;
+}
+
+.login-page {
+  height: 100vh;
+  border: none;
+  padding: 0;
+  position: relative;
+  display: flex;
+  flex-direction: column;
+}
+
+.global-header-bar {
+  width: 100%;
+  height: px2rpx(60);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-shrink: 0;
+  z-index: 100;
+
+  &.pc-header {
+    background-color: transparent;
   }
   }
 
 
-  .global-header-bar {
+  .header-inner {
     width: 100%;
     width: 100%;
-    height: px2rpx(60);
+    padding: 0 5%;
     display: flex;
     display: flex;
+    justify-content: space-between;
+    /* 两端对齐,可放logo和组件 */
     align-items: center;
     align-items: center;
-    justify-content: center;
-    flex-shrink: 0;
-    z-index: 100;
-
-    &.pc-header {
-      background-color: transparent;
-    }
-
-    .header-inner {
-      width: 100%;
-      padding: 0 5%;
-      display: flex;
-      justify-content: space-between; /* 两端对齐,可放logo和组件 */
-      align-items: center;
-    }
-  }
-
-  .mobile-header-bar {
-    position: absolute;
-    top: px2rpx(20);
-    right: px2rpx(20);
-    z-index: 10;
   }
   }
-
-  .main-content {
-    flex: 1;
-    overflow: hidden;
-    background-image: url(/static/images/login-bg.gif);
-    background-repeat: no-repeat;
-    background-size: cover;
-    background-position: center center;
-  }
-
-  .demo-uni-row {
+}
+
+.mobile-header-bar {
+  position: absolute;
+  top: px2rpx(20);
+  right: px2rpx(20);
+  z-index: 10;
+}
+
+.main-content {
+  flex: 1;
+  overflow: hidden;
+  background-image: url(/static/images/login-bg.gif);
+  background-repeat: no-repeat;
+  background-size: cover;
+  background-position: center center;
+}
+
+.demo-uni-row {
+  height: 100%;
+  margin: 0 !important;
+
+  .left-bg {
     height: 100%;
     height: 100%;
-    margin: 0 !important;
+    min-height: calc(100vh - 120px);
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
 
 
-    .left-bg {
-      height: 100%;
-      min-height: calc(100vh - 120px);
+    .left-box {
       display: flex;
       display: flex;
       flex-direction: column;
       flex-direction: column;
-      align-items: center;
       justify-content: center;
       justify-content: center;
+      align-items: flex-start;
+      width: 60%;
+      //margin-top: px2rpx(20);
+
+      .inner {
+        width: 100%;
+        text-align: start;
+        margin-bottom: px2rpx(20);
 
 
-      .left-box {
-        display: flex;
-        flex-direction: column;
-        justify-content: 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(10);
-            margin-bottom: px2rpx(10);
-          }
-
-
-          .title {
-            font-size: px2rpx(50);
-            line-height: 1;
-            color: #fff;
-            font-weight: 700;
-            text-align: left;
-          }
-
-          .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;
-          }
+        .section-title {
+          margin-top: px2rpx(10);
+          margin-bottom: px2rpx(10);
         }
         }
 
 
-        .img-fluid {
-          width: 100%;
-          max-width: px2rpx(240);
+
+        .title {
+          font-size: px2rpx(50);
+          line-height: 1;
+          color: #fff;
+          font-weight: 700;
+          text-align: left;
         }
         }
 
 
-        .mt--10 {
-          margin-top: px2rpx(10);
+        .w-700 {
+          font-weight: 700;
         }
         }
 
 
-        .h1 {
-          // text-align: center;
-          color: #fff;
-          font-size: 30px;
-          margin-top: 30px;
-          line-height: 1.5;
+        .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;
         }
         }
 
 
-        .h6 {
-          text-align: start;
-          line-height: 20px;
-          color: #fff;
-          font-size: 14px;
-          margin-top: 10px;
+        .w-40 {
+          max-width: 40%;
         }
         }
 
 
-        .company {
-          padding: px2rpx(10) 0 px2rpx(10) 0;
-          position: relative;
-          align-items: flex-start !important;
-          width: 100%;
+        .text-white {
+          margin-top: px2rpx(10);
+          font-size: px2rpx(14);
+          line-height: 1.6;
+          color: #fff;
         }
         }
       }
       }
 
 
-      .left-content {
+      .img-fluid {
         width: 100%;
         width: 100%;
+        max-width: px2rpx(240);
+      }
 
 
-        .des {
-          text-align: start;
-          line-height: 24px;
-          color: #fff;
-          font-size: 14px;
-          margin-top: px2rpx(20);
-
-          :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);
-          }
-        }
+      .mt--10 {
+        margin-top: px2rpx(10);
       }
       }
-    }
 
 
-    .right-f {
-      background-color: var(--color-white);
-      padding: 0 px2rpx(24);
-      height: 100%;
-      box-sizing: border-box;
+      .h1 {
+        // text-align: center;
+        color: #fff;
+        font-size: 30px;
+        margin-top: 30px;
+        line-height: 1.5;
+      }
+
+      .h6 {
+        text-align: start;
+        line-height: 20px;
+        color: #fff;
+        font-size: 14px;
+        margin-top: 10px;
+      }
 
 
-      .account {
-        background-color: var(--color-white);
+      .company {
+        padding: px2rpx(10) 0 px2rpx(10) 0;
         position: relative;
         position: relative;
-        height: calc(100vh - 120px);
-        display: flex;
-        flex-direction: column;
-        justify-content: center;
-        padding: 0 10%;
-
-        .company {
-          padding: px2rpx(50) 0 px2rpx(20) 0;
-          position: relative;
-          align-items: center !important;
+        align-items: flex-start !important;
+        width: 100%;
+      }
+    }
+
+    .left-content {
+      width: 100%;
+
+      .des {
+        text-align: start;
+        line-height: 24px;
+        color: #fff;
+        font-size: 14px;
+        margin-top: px2rpx(20);
+
+        :nth-child(n) {
+          display: inline;
+          word-break: break-all;
+          word-wrap: break-word;
         }
         }
 
 
-        .company-icon {
-          width: px2rpx(234);
+        .doc-link {
+          color: var(--color-error);
+          text-decoration: underline;
+          margin: 0 px2rpx(4);
         }
         }
       }
       }
     }
     }
   }
   }
 
 
-  .bottom-box {
-    width: 100%;
-    height: 60px;
+  .right-f {
     background-color: var(--color-white);
     background-color: var(--color-white);
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    color: #000;
-
-    .bottom-title {
-
-      text-align: center;
-      font-size: px2rpx(14);
-      font-weight: 500;
-      line-height: 1.5;
-      color: #666666;
+    padding: 0 px2rpx(24);
+    height: 100%;
+    box-sizing: border-box;
 
 
-    }
+    .account {
+      background-color: var(--color-white);
+      position: relative;
+      height: calc(100vh - 120px);
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      padding: 0 10%;
 
 
-    .ellipsis {
-      width: px2rpx(200);
-      white-space: nowrap;
-      overflow: hidden;
-      text-overflow: ellipsis;
-    }
+      .company {
+        padding: px2rpx(50) 0 px2rpx(20) 0;
+        position: relative;
+        align-items: center !important;
+      }
 
 
-    .cwg-button {
-      width: 120px !important;
-      padding: px2rpx(4) 0 !important;
+      .company-icon {
+        width: px2rpx(234);
+      }
     }
     }
   }
   }
+}
 
 
+.bottom-box {
+  width: 100%;
+  height: 60px;
+  background-color: var(--color-white);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  color: #000;
 
 
-  button {
-    background-color: #ea002a;
+  .bottom-title {
+
+    text-align: center;
     font-size: px2rpx(14);
     font-size: px2rpx(14);
-    font-weight: normal;
-    height: px2rpx(44);
-    line-height: px2rpx(44);
-  }
+    font-weight: 500;
+    line-height: 1.5;
+    color: #666666;
 
 
-  .right-f .account .company {
-    padding: px2rpx(50) 0 px2rpx(200) 0;
-    position: relative;
-    align-items: flex-start !important;
   }
   }
 
 
-  .logo {
-    margin-left: px2rpx(48);
+  .ellipsis {
+    width: px2rpx(200);
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
   }
   }
 
 
-  .left-bg .company-icon {
-    width: px2rpx(234);
+  .cwg-button {
+    width: 120px !important;
+    padding: px2rpx(4) 0 !important;
   }
   }
-
-  .left-bg .left-content {
-    position: relative;
-    z-index: 1;
+}
+
+
+button {
+  background-color: #ea002a;
+  font-size: px2rpx(14);
+  font-weight: normal;
+  height: px2rpx(44);
+  line-height: px2rpx(44);
+}
+
+.right-f .account .company {
+  padding: px2rpx(50) 0 px2rpx(200) 0;
+  position: relative;
+  align-items: flex-start !important;
+}
+
+.logo {
+  margin-left: px2rpx(48);
+}
+
+.left-bg .company-icon {
+  width: px2rpx(234);
+}
+
+.left-bg .left-content {
+  position: relative;
+  z-index: 1;
+}
+
+.title {
+  margin: px2rpx(32) 0;
+  font-size: px2rpx(24);
+  font-weight: bolder;
+  color: #e4e4e4;
+  text-align: center;
+
+  i {
+    margin-right: px2rpx(10);
   }
   }
 
 
-  .title {
-    margin: px2rpx(32) 0;
-    font-size: px2rpx(24);
-    font-weight: bolder;
-    color: #e4e4e4;
-    text-align: center;
-
-    i {
-      margin-right: px2rpx(10);
-    }
-
-    .tit1 {
-      font-size: px2rpx(34);
-      line-height: 1.5;
-      font-weight: bold;
-      color: #000000;
-    }
-
-    .tit2 {
-      font-size: px2rpx(16);
-      line-height: 1.5;
-      color: #cecece;
-      font-weight: 500;
-    }
+  .tit1 {
+    font-size: px2rpx(34);
+    line-height: 1.5;
+    font-weight: bold;
+    color: #000000;
   }
   }
 
 
-  .qr-title {
+  .tit2 {
     font-size: px2rpx(16);
     font-size: px2rpx(16);
     line-height: 1.5;
     line-height: 1.5;
     color: #cecece;
     color: #cecece;
     font-weight: 500;
     font-weight: 500;
-    text-align: center;
-    margin: px2rpx(40) 0;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-
-    .line {
-      flex: 1;
-      height: 1px;
-      background-color: #e4e4e4;
-    }
-
-    .qr-tit2 {
-      margin: 0 px2rpx(12);
-
-    }
-
-  }
-
-  .input {
-    height: px2rpx(44);
-    border-radius: px2rpx(8);
-    background: #f7f8fa;
-    padding: 0 px2rpx(20) !important;
-    position: relative;
   }
   }
-
-  .account-icon {
-    width: px2rpx(12);
-    height: px2rpx(14) !important;
-    margin-right: px2rpx(5);
+}
+
+.qr-title {
+  font-size: px2rpx(16);
+  line-height: 1.5;
+  color: #cecece;
+  font-weight: 500;
+  text-align: center;
+  margin: px2rpx(40) 0;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+
+  .line {
+    flex: 1;
+    height: 1px;
+    background-color: #e4e4e4;
   }
   }
 
 
-  :deep(.u-input__content__prefix-icon) {
-    height: px2rpx(20);
-  }
+  .qr-tit2 {
+    margin: 0 px2rpx(12);
 
 
-  .regiset-btn {
-    margin: px2rpx(20) 0;
   }
   }
 
 
-  .account-tip {
-    color: #666666;
-    font-size: px2rpx(14);
-    text-align: center;
-
-    text {
-      color: #ea002a;
-    }
+}
+
+.input {
+  height: px2rpx(44);
+  border-radius: px2rpx(8);
+  background: #f7f8fa;
+  padding: 0 px2rpx(20) !important;
+  position: relative;
+}
+
+.account-icon {
+  width: px2rpx(12);
+  height: px2rpx(14) !important;
+  margin-right: px2rpx(5);
+}
+
+:deep(.u-input__content__prefix-icon) {
+  height: px2rpx(20);
+}
+
+.regiset-btn {
+  margin: px2rpx(20) 0;
+}
+
+.account-tip {
+  color: #666666;
+  font-size: px2rpx(14);
+  text-align: center;
+
+  text {
+    color: #ea002a;
   }
   }
+}
 
 
-  :deep(.u-form-item__body) {
-    padding: 0 !important;
-    padding-bottom: px2rpx(24) !important;
-  }
+:deep(.u-form-item__body) {
+  padding: 0 !important;
+  padding-bottom: px2rpx(24) !important;
+}
 
 
-  :deep(.wcg-checkbox) {
-    padding: 0 !important;
-  }
+:deep(.wcg-checkbox) {
+  padding: 0 !important;
+}
 
 
-  .cwg-button {
-    padding: px2rpx(34) 0 !important;
-  }
+.cwg-button {
+  padding: px2rpx(34) 0 !important;
+}
 </style>
 </style>

+ 3 - 3
pages/login/regist.vue

@@ -46,12 +46,12 @@
                   <text v-html="t('newSignin.item11')"></text>
                   <text v-html="t('newSignin.item11')"></text>
                   <br />
                   <br />
                   <text v-t="'newSignin.item13'"></text>
                   <text v-t="'newSignin.item13'"></text>
-                  <a
-                    :href="`https://www.${ho}.com/doc/Risk-Disclosures-and-Acknowledgements-2020-08.pdf`"
+                  <cwg-link type="pdf" :title="'newSignin.item13_1'"
+                    :url="`pdf/Risk-Disclosures-and-Acknowledgements-2020-08.pdf`"
                     target="_blank"
                     target="_blank"
                     v-t="'newSignin.item13_1'"
                     v-t="'newSignin.item13_1'"
                     class="doc-link"
                     class="doc-link"
-                  ></a>
+                  />
                   <text v-t="'newSignin.item13_2'"></text>
                   <text v-t="'newSignin.item13_2'"></text>
                   <!-- <view v-t="'newSignin.item13_3'"></view>
                   <!-- <view v-t="'newSignin.item13_3'"></view>
                   <text v-t="'newSignin.item13_4'"></text> -->
                   <text v-t="'newSignin.item13_4'"></text> -->

BIN
pdf/Risk-Disclosures-and-Acknowledgements-2020-08.pdf