Explorar el Código

liveChat、完善布局

zhb hace 2 meses
padre
commit
4b0fa6113e

+ 53 - 4
App.vue

@@ -1,7 +1,8 @@
 <script setup>
-import {
-	onMounted
-} from "vue";
+import { ref, onMounted, nextTick, watch, onBeforeUnmount, getCurrentInstance } from 'vue';
+import { useI18n } from "vue-i18n";
+const { locale } = useI18n();
+
 import {
 	onLoad,
 	onShow,
@@ -12,6 +13,7 @@ import {
 } from "@/hooks/useRoute";
 import useGlobalStore from "@/stores/use-global-store";
 import { useAppUpdate } from '@/hooks/useAppUpdate'
+import liveChat from '@/utils/liveChat';
 const { checkUpdate } = useAppUpdate()
 const globalStore = useGlobalStore()
 onLoad((options) => {
@@ -26,9 +28,56 @@ onLaunch((options) => {
 	updateRoute();
 	checkUpdate()
 })
+const adjustLiveChatPosition = () => {
+	// #ifdef H5
+	const footerBody = document.getElementById('footer-body');
+	if (footerBody) {
+		liveChat.adjustPosition(footerBody.offsetHeight);
+	}
+	// #endif
+}
+watch(locale, () => {
+	console.log(locale.value, 23123)
+	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 })
+onBeforeUnmount(() => {
+	// #ifdef H5
+	if (typeof window !== 'undefined') {
+		window.removeEventListener('resize', adjustLiveChatPosition)
+	}
+	// #endif
+})
 onMounted(() => {
 	const sysInfo = uni.getSystemInfoSync();
 	globalStore.setBarHeight(sysInfo.statusBarHeight);
+
+	// ---------- 新增 H5 端专属初始化 ----------
+	// 仅在 H5 端执行(通过环境判断)
+	// #ifdef H5
+	if (typeof window !== 'undefined') {
+		const instance = getCurrentInstance()
+		if (instance) {
+			window.vm = instance.proxy
+		}
+
+		// 调用一次调整位置
+		adjustLiveChatPosition()
+
+		// 监听窗口大小变化,动态调整
+		window.addEventListener('resize', adjustLiveChatPosition)
+	}
+	// #endif
 });
 </script>
 
@@ -63,4 +112,4 @@ html {
 uni-page-body {
 	height: 100%;
 }
-</style>
+</style>

+ 14 - 18
components/LanguageDropdown.vue

@@ -1,9 +1,7 @@
 <template>
   <cwg-dropdown :menu-list="customMenuList" @menuClick="handleMenuClick">
     <view class="lang-select">
-      <image class="img flag" :src="currentFlag" alt="lang" />
-      <text>{{ currentLabel }}</text>
-      <text class="arrow">▼</text>
+      <cwg-icon name="cwg-lang" color="#141d22" />
     </view>
   </cwg-dropdown>
 </template>
@@ -56,13 +54,22 @@ function getFlagSrc(code: string) {
 @import "@/uni.scss";
 
 .lang-select {
+  width: px2rpx(40);
+  height: px2rpx(40);
+  border-radius: px2rpx(4);
+  border: 1px solid rgba(108, 133, 149, 0);
   display: flex;
   align-items: center;
-  background: #f5f7fa;
-  border-radius: 18px;
-  padding: 4px 12px;
-  font-size: 14px;
+  font-size: px2rpx(14);
   cursor: pointer;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+
+  &:hover {
+    background: rgba(108, 133, 149, 0.12);
+    border-color: rgb(145, 163, 176);
+  }
 }
 
 .flag {
@@ -76,17 +83,6 @@ function getFlagSrc(code: string) {
   font-size: 12px;
 }
 
-:deep(.cwg-dropdown-menu-container) {
-  top: px2rpx(40) !important;
-  left: 0 !important;
-  right: auto !important;
-  z-index: 1000 !important;
-}
-
-:deep(.cwg-dropdown-menu-container .menu) {
-  min-width: px2rpx(180);
-}
-
 :deep(.cwg-dropdown-menu-container .menu .menu-item) {
   min-height: px2rpx(36);
 }

+ 22 - 11
components/cwg-page-wrapper.vue

@@ -1,8 +1,8 @@
 <template>
   <view :class="['page-wrapper', { dark: isDark }]">
     <cwg-match-media :max-width="991" v-if="!isLoginPage">
-      <cwg-pc-header @open-right-drawer="openRightDrawer" @open-left-drawer="openLeftDrawer" class="header-box" />
-<!--      占位-->
+      <cwg-pc-header @open-right-drawer="openRightDrawer" @open-left-drawer="openLeftDrawer" class="header-box" :sidebarVisible="sidebarVisible" />
+      <!--      占位-->
       <view class="fixed"></view>
     </cwg-match-media>
     <LanguageDropdown style="width: 0;display: none;" />
@@ -19,12 +19,14 @@
 
         </view>
       </cwg-match-media>
-<!--      完善信息提示,-->
-      <PrefectInfo/>
+      <view class="content-info">
+        <!--      完善信息提示,-->
+        <PrefectInfo />
 
-      <view class="content-wrapper" :class="{ 'content-wrapper-padding': isContentPadding }">
-        <!-- <cwg-header /> -->
-        <slot />
+        <view class="content-wrapper" :class="{ 'content-wrapper-padding': isContentPadding }">
+          <!-- <cwg-header /> -->
+          <slot />
+        </view>
       </view>
       <view :style="{ height: isTabBarPage ? '60px' : '0px' }" />
     </view>
@@ -123,10 +125,18 @@ onShow(() => {
 
 .page-content {
   width: 100%;
+  height: calc(100vh - 56px);
+  overflow: hidden;
   display: flex;
   flex-direction: column;
   position: relative;
   box-sizing: border-box;
+
+  .content-info {
+    height: calc(100vh - 56px);
+    overflow: auto;
+  }
+
 }
 
 .left-sidebar {
@@ -162,10 +172,11 @@ onShow(() => {
   box-sizing: border-box;
   // border: 1px solid rgba(108, 133, 149, 0.12);
 }
-.fixed{
-  position: fixed;
-  top: 0;
-  left: 0;
+
+.fixed {
+  // position: fixed;
+  // top: 0;
+  // left: 0;
   width: 100%;
   height: 56px;
   background-color: var(--color-white);

+ 5 - 12
components/cwg-pc-header.vue

@@ -1,19 +1,14 @@
 <template>
 	<header class="cwg-pc-header">
 		<div class="left">
-			<image class="left-img" src="/static/images/logo.png" mode="widthFix" alt="logo" @click="openLeftDrawer" />
+			<cwg-icon :name="!sidebarVisible ? 'crm-bars-staggered' : 'cwg-close'" color="#141d22"
+				@click="openLeftDrawer" />
+		</div>
+		<div class="left">
+			<image class="left-img" src="/static/images/logo.png" mode="widthFix" alt="logo" />
 		</div>
 		<div class="right">
-			<div class="lang-select">
-				<image class="img flag" src="/static/flag-en.png" alt="en" />
-				<text>English</text>
-				<text class="arrow">▼</text>
-			</div>
-			<text class="icon sun" @click="toggleTheme">🌞</text>
 			<text class="icon bell">🔔<text class="dot"></text></text>
-			<text class="icon avatar">
-				<image class="img" src="/static/avatar.png" alt="avatar" />
-			</text>
 			<text class="icon logo" @click="openRightDrawer">
 				<image class="img" src="/static/logo.png" alt="logo" />
 			</text>
@@ -22,8 +17,6 @@
 </template>
 
 <script setup lang="ts">
-// import useGlobalStore from '@/stores/use-global-store'
-// const globalStore = useGlobalStore()
 import useRouter from "@/hooks/useRouter";
 const router = useRouter();
 const props = defineProps({

+ 100 - 53
components/cwg-sidebar.vue

@@ -20,11 +20,16 @@
 </template>
 
 <script lang="ts" setup>
-import { ref, onMounted, nextTick, watch } from 'vue';
+import { ref, onMounted, nextTick, watch, computed } from 'vue';
+import Config from '@/config/index'
 import useRouter from "@/hooks/useRouter";
 const router = useRouter();
 import useRoute from '@/hooks/useRoute'
 const route = useRoute()
+import { useI18n } from "vue-i18n";
+const { t, locale } = useI18n();
+import { localesList, LANG_MAP } from '@/locale/index'
+import { lang } from '@/composables/config'
 interface MenuItem {
     key: string;
     label: string;
@@ -32,55 +37,83 @@ interface MenuItem {
     children?: MenuItem[];
 }
 const emit = defineEmits(['menu-click']);
-// 菜单数据
-const menu = ref<MenuItem[]>([
-    {
-        isOpenMenu: false, submenuHeight: 0,
-        path: '/pages/customer/index', label: 'Home.msg.Custom', icon: 'crm-house',
-        children: [
-            { path: '/pages/customer/index', label: 'Custom.Index.AccountList', icon: 'icon-client' },
-            { 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: 'Home.page_customer.item5', icon: 'icon-transfer' },
-            { path: '/pages/customer/recording-history', label: 'Home.page_customer.item7', icon: 'icon-application' }
-        ]
-    },
-    {
-        isOpenMenu: false,
-        path: '/pages/customer/promotion', label: 'Home.msg.Ib', icon: 'crm-users',
-        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/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/customer/deposit', isOpenMenu: false, label: 'Documentary.title', icon: 'crm-chart-area',
-        children: []
-    },
-    {
-        path: '/pages/customer/withdrawal', isOpenMenu: false, label: 'Downloadpage.item1', icon: 'crm-download',
-        children: []
-    },
-    {
-        path: '/pages/customer/support', isOpenMenu: false, label: 'Downloadpage.item16', icon: 'crm-headset',
-        children: []
-    },
-    {
-        path: '/pages/customer/support', isOpenMenu: false, label: '设置', icon: 'crm-headset',
-        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' },
-        ]
-    },
-]);
+const currentLang = computed(() => lang.value || locale.value)
+const currentLabel = computed(() => t(`language.${currentLang.value}`))
+
+const customMenuList = computed(() =>
+    localesList.map((code) => ({
+        label: t(`language.${code}`),
+        lang: code,
+        type: "lang",
+        path: '/'
+    })),
+)
+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/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/customer/support', isOpenMenu: false, label: currentLabel.value, icon: 'cwg-lang',
+            children: customMenuList.value
+        },
+    ]);
 const submenuRefs = ref<any[]>([]);
 const measureHeight = (element: HTMLElement): number => {
     const originalDisplay = element.style.display;
@@ -96,7 +129,6 @@ const measureHeight = (element: HTMLElement): number => {
     element.style.position = originalPosition;
     element.style.visibility = originalVisibility;
     element.style.width = originalWidth;
-
     return height;
 };
 const updateSubmenuHeight = (index: number) => {
@@ -104,20 +136,34 @@ const updateSubmenuHeight = (index: number) => {
     if (refs && refs[index]) {
         const el = refs[index].$el || refs[index];
         const height = measureHeight(el);
-
         if (height > 0) {
             menu.value[index].submenuHeight = height;
         }
     }
 };
 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;
 }
 watch(route, () => {
     const currentPath = route.path;
     menu.value.forEach((item, index) => {
         if (item.children) {
-            const isActive = item.children.some(child => child.path === currentPath);
+            const isActive = item.children.some(child => child.path.includes(currentPath));
             menu.value[index].isOpenMenu = isActive;
             if (isActive) {
                 nextTick(() => {
@@ -128,6 +174,7 @@ watch(route, () => {
     });
 }, { immediate: true })
 
+
 onMounted(() => {
     nextTick(() => {
         menu.value.forEach((item, index) => {

+ 25 - 5
components/cwg-submenu.vue

@@ -13,6 +13,10 @@
 <script lang="ts" setup>
 import { computed, watch, nextTick } from 'vue';
 import { openExternalUrl } from '@/utils/openExternalUrl'
+import { useI18n } from 'vue-i18n'
+import { lang } from '@/composables/config'
+import { LANG_MAP } from '@/locale/index'
+const { locale } = useI18n()
 import useRouter from "@/hooks/useRouter";
 const router = useRouter();
 import useRoute from '@/hooks/useRoute'
@@ -21,6 +25,10 @@ interface MenuItem {
     key: string;
     label: string;
     icon?: string;
+    type?: string;
+    lang?: string;
+    path?: string;
+    isExternal?: boolean;
     children?: MenuItem[];
 }
 const props = defineProps({
@@ -31,13 +39,25 @@ const props = defineProps({
 })
 const activePath = computed(() => route.path + (route.query?.type ? `?type=${route.query.type}` : '') || '')
 const emit = defineEmits(['submenu-click']);
-function handleClick(item) {
-    if (item.isExternal) {
-        openExternalUrl(item.path);
-    } else if (route.path !== item.path) {
-        router.push(item.path);
+function handleClick(item: MenuItem) {
+    if (item.type == 'lang') {
+        handleMenuClick(item.lang)
+    } else {
+        if (item.isExternal) {
+            openExternalUrl(item.path);
+        } else if (route.path !== item.path) {
+            router.push(item.path);
+        }
     }
 }
+
+function handleMenuClick(a: string) {
+    if (!a) return
+    locale.value = a
+    lang.value = a
+    const localeValue = LANG_MAP[a] || 'zh-Hans'
+    uni.setLocale(localeValue)
+}
 </script>
 
 <style scoped lang="scss">

+ 1 - 1
components/cwg-tabel.vue

@@ -35,7 +35,7 @@
                                 <cwg-file :path="row[column.prop]" />
                             </view>
                             <cwg-icon v-else-if="column.type === 'more'" name="crm-chevron-down"
-                                class="crm-chevron-down" :size="16" color="#007" @click="toggleRowExpand(rowIndex)" />
+                                class="crm-chevron-down" :size="16" color="#007" />
                             <template v-else>
                                 {{ formatCellValue(row[column.prop], column, row) }}
                             </template>

+ 3 - 2
pages.json

@@ -52,7 +52,8 @@
     {
       "path": "pages/mine/improveImmediately",
       "style": {
-        "navigationBarTitleText": ""
+        "navigationBarTitleText": "",
+        "navigationStyle": "custom"
       }
     },
     {
@@ -263,4 +264,4 @@
     "animationDuration": 300
   },
   "uniIdRouter": {}
-}
+}

+ 41 - 0
pages/common/chat.vue

@@ -0,0 +1,41 @@
+<template>
+  <cwg-page-wrapper class="create-page" :isHeaderFixed="true">
+    <cwg-header :title="title" />
+    <view class="chat-wrapper">
+      <web-view v-if="chatUrl" :src="chatUrl" :webview-styles="webviewStyles" />
+    </view>
+  </cwg-page-wrapper>
+</template>
+
+<script setup lang="ts">
+import { computed } from 'vue'
+import { useI18n } from 'vue-i18n'
+import { lang } from '@/composables/config'
+import useGlobalStore from '@/stores/use-global-store'
+
+const { t } = useI18n()
+const globalStore = useGlobalStore()
+
+const title = computed(() => t('Label.CustomerService') || '在线客服')
+const statusBarHeight = computed(() => globalStore.statusBarHeight || 0)
+
+const webviewStyles = computed(() => ({
+  progress: { color: '#ea002a' },
+}))
+
+const chatUrl = computed(() => {
+  const currentLang = lang.value || 'cn'
+  const base = 'https://secure.cwgmx.com/mobile/zopim.html'
+  const query = `lang=${encodeURIComponent(currentLang)}&statusBarHeight=${encodeURIComponent(String(statusBarHeight.value))}`
+  return `${base}?${query}`
+})
+</script>
+
+<style scoped lang="scss">
+@import "@/uni.scss";
+
+.chat-wrapper {
+  width: 100%;
+  min-height: calc(100vh - 56px);
+}
+</style>

+ 93 - 0
utils/liveChat.js

@@ -0,0 +1,93 @@
+export class LiveChatService {
+  static instance = null;
+  initialized = false;
+
+  constructor() {
+    this.initLiveChat();
+  }
+
+  static getInstance() {
+    if (!LiveChatService.instance) {
+      LiveChatService.instance = new LiveChatService();
+    }
+    return LiveChatService.instance;
+  }
+
+  initLiveChat() {
+    if (this.initialized) return;
+
+    // #ifdef H5
+    window.__lc = window.__lc || {};
+    window.__lc.license = 18945964;
+
+    (function (n, t, c) {
+      function i(n) {
+        return e._h ? e._h.apply(null, n) : e._q.push(n);
+      }
+      var e = {
+        _q: [],
+        _h: null,
+        _v: "2.0",
+        on: function () {
+          i(["on", c.call(arguments)]);
+        },
+        once: function () {
+          i(["once", c.call(arguments)]);
+        },
+        off: function () {
+          i(["off", c.call(arguments)]);
+        },
+        get: function () {
+          if (!e._h)
+            throw new Error("[LiveChatWidget] You can't use getters before load.");
+          return i(["get", c.call(arguments)]);
+        },
+        call: function () {
+          i(["call", c.call(arguments)]);
+        },
+        init: function () {
+          var n = t.createElement("script");
+          n.async = !0;
+          n.type = "text/javascript";
+          n.src = "https://cdn.livechatinc.com/tracking.js";
+          t.head.appendChild(n);
+        },
+      };
+      !n.__lc.asyncInit && e.init();
+      n.LiveChatWidget = n.LiveChatWidget || e;
+    })(window, document, [].slice);
+    // #endif
+
+    this.initialized = true;
+  }
+
+  setLanguage(lang) {
+    // #ifdef H5
+    if (window.LiveChatWidget) {
+      if (lang === 'cn') {
+        window.LiveChatWidget.call('set_language', 'zh_CN');
+      } else {
+        window.LiveChatWidget.call('set_language', 'en');
+      }
+    }
+    // #endif
+  }
+
+  adjustPosition(footerHeight) {
+    // #ifdef H5
+    if (window.innerWidth > 768) {
+      const launcher = document.getElementById('chat-widget-launcher');
+      const widget = document.getElementById('chat-widget-container');
+
+      if (launcher) {
+        launcher.style.bottom = `${footerHeight}px`;
+      }
+      if (widget) {
+        widget.style.bottom = `${footerHeight}px`;
+      }
+    }
+    // #endif
+  }
+}
+
+export default LiveChatService.getInstance(); 

+ 15 - 2
windows/left-window.vue

@@ -84,8 +84,9 @@ const menu = ref<MenuItem[]>(
             children: []
         },
         {
-            path: '/pages/customer/support', isOpenMenu: false, label: 'Downloadpage.item16', icon: 'crm-headset',
-            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',
@@ -127,7 +128,19 @@ const updateSubmenuHeight = (index: number) => {
 };
 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;

+ 0 - 4
windows/top-window.vue

@@ -5,11 +5,7 @@
 		</div>
 		<div class="right">
 			<LanguageDropdown />
-			<!-- <text class="icon sun" @click="toggleTheme">🌞</text> -->
 			<text class="icon bell">🔔<text class="dot"></text></text>
-			<text class="icon avatar">
-				<image class="img" src="/static/avatar.png" alt="avatar" />
-			</text>
 			<text class="icon logo" @click="openRightDrawer">
 				<image class="img" src="/static/logo.png" alt="logo" />
 			</text>