|
|
@@ -1,310 +1,170 @@
|
|
|
<template>
|
|
|
<view class="cwg-sidebar">
|
|
|
- <view class="menu" v-for="(item, index) in menu" :key="item.path">
|
|
|
- <view class="menu-item" @click="handleClick(index)">
|
|
|
- <cwg-icon :name="item.icon" :size="20" color="#6c8595" />
|
|
|
- <view class="menu-label" v-t="item.label" />
|
|
|
- <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" />
|
|
|
+ <view class="menu-list">
|
|
|
+ <view class="menu" v-for="(item, index) in menus" :key="item.path + index">
|
|
|
+ <view class="menu-item" @click="handleClick(index)">
|
|
|
+ <cwg-icon :name="item.icon" :size="20" color="#6c8595" />
|
|
|
+ <view class="menu-label" v-t="item.label" />
|
|
|
+ <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" />
|
|
|
+ </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 }">
|
|
|
+ <cwg-submenu v-if="item.children && item.children.length" :submenu-items="item.children"
|
|
|
+ @submenu-click="handleSubmenuClick" />
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ <view class="menu fixed">
|
|
|
+ <view class="menu-item ib-box" @click="setMode('ib')" v-if="mode !== 'ib'">
|
|
|
+ <cwg-icon name="crm-ib" :size="20" color="#6c8595" />
|
|
|
+ <view class="menu-label" v-t="'Home.msg.Ib'" />
|
|
|
+ </view>
|
|
|
+ <view class="menu-item ib-box" @click="setMode('customer')" v-if="mode !== 'customer'">
|
|
|
+ <cwg-icon name="crm-trade" :size="20" color="#6c8595" />
|
|
|
+ <view class="menu-label" v-t="'Home.msg.Custom'" />
|
|
|
</view>
|
|
|
- <view ref="submenuRefs" class="submenu-box" :style="{
|
|
|
- height: 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" :submenu-items="item.children" @submenu-click="handleSubmenuClick" />
|
|
|
+ <view class="menu-item zy-box" @click="handleFixedMenuClick">
|
|
|
+ <cwg-icon name="crm-zy" :size="20" color="#6c8595" />
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
- import { ref, onMounted, nextTick, watch, onBeforeUnmount } from 'vue'
|
|
|
- import useRouter from '@/hooks/useRouter'
|
|
|
+import { useMenuSplit } from '@/composables/useMenuSplit'
|
|
|
+const { menus, setSubmenuRef, setMode, handleClick, handleSubmenuClick, mode } = useMenuSplit()
|
|
|
+// 固定菜单项点击事件
|
|
|
+function handleFixedMenuClick() {
|
|
|
+ // 这里可以添加固定菜单的点击处理逻辑
|
|
|
+ console.log('Fixed menu clicked')
|
|
|
+}
|
|
|
|
|
|
- const router = useRouter()
|
|
|
- import useRoute from '@/hooks/useRoute'
|
|
|
-
|
|
|
- const route = useRoute()
|
|
|
- import Config from '@/config/index'
|
|
|
- import { useI18n } from 'vue-i18n'
|
|
|
-
|
|
|
- const { t, locale } = useI18n()
|
|
|
+</script>
|
|
|
|
|
|
- interface MenuItem {
|
|
|
- key: string;
|
|
|
- label: string;
|
|
|
- icon?: string;
|
|
|
- children?: MenuItem[];
|
|
|
+<style scoped lang="scss">
|
|
|
+@import "@/uni.scss";
|
|
|
+
|
|
|
+.cwg-sidebar {
|
|
|
+ width: 100%;
|
|
|
+ color: #6c8595;
|
|
|
+ height: calc(100vh - 56px);
|
|
|
+ overflow: hidden;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ padding: px2rpx(8);
|
|
|
+ padding-top: px2rpx(20);
|
|
|
+ padding-bottom: px2rpx(8);
|
|
|
+ box-sizing: border-box;
|
|
|
+ gap: px2rpx(8);
|
|
|
+ border-right: 1px solid rgba(108, 133, 149, 0.12);
|
|
|
+
|
|
|
+ .logo {
|
|
|
+ width: px2rpx(54);
|
|
|
}
|
|
|
|
|
|
- const emit = defineEmits(['menu-click'])
|
|
|
- // 菜单数据
|
|
|
- const menu = ref<MenuItem[]>(
|
|
|
- [
|
|
|
- {
|
|
|
- isOpenMenu: false, submenuHeight: 0,
|
|
|
- path: '/pages/customer/index', label: 'Shop.Index.Transaction', icon: 'crm-trade',
|
|
|
- children: [
|
|
|
- { path: '/pages/customer/index', label: 'Custom.Index.AccountList', icon: 'icon-client' },
|
|
|
- { path: '/pages/customer/trade-history', label: 'Ib.Report.Tit1', icon: 'icon-transfer' },
|
|
|
- { path: '/pages/customer/trade-position', label: 'Ib.Report.Tit4', icon: 'icon-transfer' },
|
|
|
- { path: '/pages/customer/recording-history', label: 'Home.page_customer.item7', icon: 'icon-application' },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- isOpenMenu: false, submenuHeight: 0,
|
|
|
- path: '/pages/customer/index', label: 'Latest.PaymentWallet', icon: 'crm-payment',
|
|
|
- children: [
|
|
|
- { path: '/pages/customer/deposit', label: 'Home.page_customer.item2', icon: 'icon-deposit' },
|
|
|
- { path: '/pages/customer/withdrawal', label: 'Home.page_customer.item3', icon: 'icon-withdrawal' },
|
|
|
- { path: '/pages/customer/payment-history', label: 'Home.page_customer.item4', icon: 'icon-payment' },
|
|
|
- { path: '/pages/customer/transfer', label: 'Custom.Index.Transfer', icon: 'icon-transfer' },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- isOpenMenu: false,
|
|
|
- path: '/pages/ib/index', label: 'Home.msg.Ib', icon: 'crm-ib',
|
|
|
- children: [
|
|
|
- { path: '/pages/ib/index', label: 'Home.page_ib.item1', icon: 'icon-client' },
|
|
|
- // 客户管理
|
|
|
- { path: '/pages/ib/customer', label: 'Home.page_ib.item2', icon: 'icon-deposit' },
|
|
|
- //代理管理
|
|
|
- { path: '/pages/ib/subsList', label: 'Home.page_ib.item12', icon: 'icon-deposit' },
|
|
|
- // 信号源列表
|
|
|
- { path: '/pages/ib/agentList', label: 'Home.page_ib.item11', icon: 'icon-deposit' },
|
|
|
- // 账户管理
|
|
|
- { path: '/pages/ib/accountList', label: 'Home.page_ib.item10', icon: 'icon-deposit' },
|
|
|
- { path: '/pages/ib/report', label: 'Home.page_ib.item3', icon: 'icon-withdrawal' },
|
|
|
- { path: '/pages/ib/transfer', label: 'Home.page_ib.item4', icon: 'icon-payment' },
|
|
|
- { path: '/pages/ib/withdraw', label: 'Home.page_ib.item5', icon: 'icon-transfer' },
|
|
|
- { path: '/pages/ib/agent-transfer', label: 'Home.page_ib.item9', icon: 'icon-transfer' },
|
|
|
- { path: '/pages/ib/recording', label: 'Home.page_ib.item7', icon: 'icon-application' },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- path: '/pages/analytics/analystViews', isOpenMenu: false, label: 'News.News', icon: 'crm-chart-area',
|
|
|
- children: [
|
|
|
- { path: '/pages/analytics/analystViews', label: 'News.Announcement', icon: 'icon-application' },
|
|
|
- { path: '/pages/analytics/news', label: 'News.NewsInformation', icon: 'icon-application' },
|
|
|
- {
|
|
|
- path: `https://www.${Config.host}.com/${locale.value}/economic-calendar`,
|
|
|
- label: 'News.FinancialCalendar',
|
|
|
- icon: 'icon-application',
|
|
|
- isExternal: true,
|
|
|
- },
|
|
|
- ],
|
|
|
- },
|
|
|
- {
|
|
|
- path: '/pages/customer/withdrawal', isOpenMenu: false, label: 'Downloadpage.item1', icon: 'crm-download',
|
|
|
- children: [],
|
|
|
- },
|
|
|
- {
|
|
|
- path: '/pages/common/chat', isOpenMenu: false, label: 'Downloadpage.item16', icon: 'crm-headset',
|
|
|
- children: [],
|
|
|
- type: 'chat',
|
|
|
- },
|
|
|
- {
|
|
|
- path: '/pages/customer/support', isOpenMenu: false, label: 'Custom.Index.Settings', icon: 'crm-sz',
|
|
|
- children: [
|
|
|
- {
|
|
|
- path: '/pages/mine/info?type=1',
|
|
|
- isOpenMenu: false,
|
|
|
- label: 'PersonalManagement.Title.PersonalInformation',
|
|
|
- icon: 'crm-headset',
|
|
|
- },
|
|
|
- {
|
|
|
- path: '/pages/mine/info?type=2',
|
|
|
- isOpenMenu: false,
|
|
|
- label: 'PersonalManagement.Title.BankInformation',
|
|
|
- icon: 'crm-headset',
|
|
|
- },
|
|
|
- {
|
|
|
- path: '/pages/mine/info?type=3',
|
|
|
- isOpenMenu: false,
|
|
|
- label: 'PersonalManagement.Title.FileManagement',
|
|
|
- icon: 'crm-headset',
|
|
|
- },
|
|
|
- {
|
|
|
- path: '/pages/mine/info?type=4',
|
|
|
- isOpenMenu: false,
|
|
|
- label: 'PersonalManagement.Title.SecurityCenter',
|
|
|
- icon: 'crm-headset',
|
|
|
- },
|
|
|
- { path: '/pages/common/notice', isOpenMenu: false, label: 'News.Notice', icon: 'crm-headset' },
|
|
|
- ],
|
|
|
- },
|
|
|
- ])
|
|
|
- const submenuRefs = ref<any[]>([])
|
|
|
- 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
|
|
|
- if (refs && refs[index]) {
|
|
|
- const el = refs[index].$el || refs[index]
|
|
|
- const height = measureHeight(el)
|
|
|
- if (height > 0) {
|
|
|
- menu.value[index].submenuHeight = height
|
|
|
- }
|
|
|
- }
|
|
|
+ .menu-list {
|
|
|
+ flex: 1;
|
|
|
+ width: 100%;
|
|
|
+ overflow-y: auto;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: px2rpx(8);
|
|
|
}
|
|
|
|
|
|
- function handleClick(index: number) {
|
|
|
- if (!menu.value[index].children || menu.value[index].children.length == 0) {
|
|
|
- // #ifdef H5
|
|
|
- if (menu.value[index].type === 'chat') {
|
|
|
- if (window.LiveChatWidget) {
|
|
|
- window.LiveChatWidget.call('maximize')
|
|
|
- }
|
|
|
- } else {
|
|
|
- router.push(menu.value[index].path)
|
|
|
- }
|
|
|
- // #endif
|
|
|
-
|
|
|
- // #ifdef APP-VUE
|
|
|
- router.push(menu.value[index].path)
|
|
|
- // #endif
|
|
|
- return
|
|
|
- }
|
|
|
- menu.value[index].isOpenMenu = !menu.value[index].isOpenMenu
|
|
|
+ .submenu-box {
|
|
|
+ width: 100%;
|
|
|
+ height: 0;
|
|
|
+ overflow: hidden;
|
|
|
}
|
|
|
|
|
|
- watch(route, () => {
|
|
|
- const currentPath = route.path
|
|
|
- menu.value.forEach((item, index) => {
|
|
|
- if (item.children) {
|
|
|
- const isActive = item.children.some(child => child.path.includes(currentPath))
|
|
|
- menu.value[index].isOpenMenu = isActive
|
|
|
- if (isActive) {
|
|
|
- nextTick(() => {
|
|
|
- updateSubmenuHeight(index)
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- }, { immediate: true })
|
|
|
+ .menu {
|
|
|
+ width: 100%;
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
|
- // 添加窗口大小变化监听
|
|
|
- const handleResize = () => {
|
|
|
- menu.value.forEach((item, index) => {
|
|
|
- if (item.children) {
|
|
|
- updateSubmenuHeight(index)
|
|
|
- }
|
|
|
- })
|
|
|
}
|
|
|
|
|
|
- onMounted(() => {
|
|
|
- nextTick(() => {
|
|
|
- menu.value.forEach((item, index) => {
|
|
|
- if (item.children) {
|
|
|
- updateSubmenuHeight(index)
|
|
|
- }
|
|
|
- })
|
|
|
- })
|
|
|
-
|
|
|
- // 添加窗口resize监听
|
|
|
- window.addEventListener('resize', handleResize)
|
|
|
- })
|
|
|
-
|
|
|
- // 组件卸载时移除监听
|
|
|
- onBeforeUnmount(() => {
|
|
|
- window.removeEventListener('resize', handleResize)
|
|
|
- })
|
|
|
-</script>
|
|
|
-
|
|
|
-<style scoped lang="scss">
|
|
|
- @import "@/uni.scss";
|
|
|
-
|
|
|
- .cwg-sidebar {
|
|
|
+ .menu-item {
|
|
|
width: 100%;
|
|
|
- color: #6c8595;
|
|
|
- height: calc(100vh - 56px);
|
|
|
- overflow: auto;
|
|
|
+ height: px2rpx(40);
|
|
|
+ cursor: pointer;
|
|
|
display: flex;
|
|
|
- flex-direction: column;
|
|
|
align-items: center;
|
|
|
- padding: px2rpx(8);
|
|
|
- padding-top: px2rpx(20);
|
|
|
- box-sizing: border-box;
|
|
|
+ justify-content: space-between;
|
|
|
gap: px2rpx(8);
|
|
|
- border-right: 1px solid rgba(108, 133, 149, 0.12);
|
|
|
+ padding: px2rpx(10);
|
|
|
+ box-sizing: border-box;
|
|
|
+ font-size: 14px;
|
|
|
|
|
|
- .logo {
|
|
|
- width: px2rpx(54);
|
|
|
+ .menu-label {
|
|
|
+ flex: 1;
|
|
|
}
|
|
|
|
|
|
- .submenu-box {
|
|
|
- width: 100%;
|
|
|
- height: 0;
|
|
|
- overflow: hidden;
|
|
|
+ &:hover {
|
|
|
+ background: rgba(108, 133, 149, 0.12) !important;
|
|
|
+ border: 1px solid rgb(145, 163, 176) !important;
|
|
|
+ border-radius: px2rpx(4);
|
|
|
}
|
|
|
|
|
|
- .menu {
|
|
|
- width: 100%;
|
|
|
- position: relative;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- box-sizing: border-box;
|
|
|
-
|
|
|
+ .expanded .icon {
|
|
|
+ transform: rotate(180deg);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- .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;
|
|
|
+ .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;
|
|
|
|
|
|
- .menu-label {
|
|
|
- flex: 1;
|
|
|
- }
|
|
|
+ &:hover {
|
|
|
+ background: rgba(140, 69, 246, 0.08) !important;
|
|
|
+ border: 1px solid rgba(140, 69, 246, 0.2) !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- &:hover {
|
|
|
- background: rgba(108, 133, 149, 0.12) !important;
|
|
|
- border: 1px solid rgb(145, 163, 176) !important;
|
|
|
- border-radius: px2rpx(4);
|
|
|
- }
|
|
|
+ .zy-box {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
|
|
|
- .expanded .icon {
|
|
|
- transform: rotate(180deg);
|
|
|
- }
|
|
|
- }
|
|
|
+ .fixed {
|
|
|
+ position: relative;
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ gap: px2rpx(8);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- @media screen and (max-width: 1100px) {
|
|
|
+@media screen and (max-width: 1100px) {
|
|
|
|
|
|
- .cwg-sidebar:not(:hover) .menu-label,
|
|
|
- .cwg-sidebar:not(:hover) .submenu-box,
|
|
|
- .cwg-sidebar:not(:hover) .chevron-icon {
|
|
|
- display: none;
|
|
|
- }
|
|
|
+ .cwg-sidebar:not(:hover) .menu-label,
|
|
|
+ .cwg-sidebar:not(:hover) .submenu-box,
|
|
|
+ .cwg-sidebar:not(:hover) .chevron-icon {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
|
|
|
- .cwg-sidebar:hover .menu-label,
|
|
|
- .cwg-sidebar:hover .submenu-box,
|
|
|
- .cwg-sidebar:hover .chevron-icon {
|
|
|
- display: block;
|
|
|
- }
|
|
|
+ .cwg-sidebar:hover .menu-label,
|
|
|
+ .cwg-sidebar:hover .submenu-box,
|
|
|
+ .cwg-sidebar:hover .chevron-icon {
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+
|
|
|
+ .cwg-sidebar .fixed {
|
|
|
+ display: flex;
|
|
|
}
|
|
|
+}
|
|
|
</style>
|