From 19cb3326456f44fedceff19751b3bca586e2d583 Mon Sep 17 00:00:00 2001 From: ZF sun <34314687@qq.com> Date: Fri, 14 Aug 2026 09:36:04 +0800 Subject: [PATCH] =?UTF-8?q?refactor(ai-page):=20=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E8=B7=AF=E7=94=B1=E7=AE=A1=E7=90=86=E5=B9=B6?= =?UTF-8?q?=E4=BF=AE=E5=A4=8DAI=E6=99=BA=E8=83=BD=E4=BD=93=E8=B7=AF?= =?UTF-8?q?=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 将硬编码的页面路径替换为PAGE_KEY_MAP常量统一管理 2. 修正AI智能体页面路径为/pages_tool/ai-agent/index 3. 优化客服跳转逻辑,避免重复注入tabBar隐藏标记 4. 为AI聊天页面添加自定义组件占位配置 --- common/js/customer-service.js | 18 ++++++++- common/js/util.js | 2 +- components/hover-nav/hover-nav.vue | 46 +++++++++++++++++++++++ pages.json | 59 +++++++++++++++++++++++++++++- pages_goods/detail.vue | 2 +- 5 files changed, 122 insertions(+), 5 deletions(-) diff --git a/common/js/customer-service.js b/common/js/customer-service.js index 507eed2..737bcb1 100644 --- a/common/js/customer-service.js +++ b/common/js/customer-service.js @@ -4,6 +4,7 @@ */ import IMAGE_CONFIG from './image-config.js'; import Platform from './platform.js'; +import PAGE_KEY_MAP from './util.js'; export class CustomerService { constructor(vueInstance, externalConfig = null) { @@ -118,6 +119,16 @@ export class CustomerService { /** * 跳转到 AI智能客服页面(AiChat) + * + * 注意:不在此处注入 __dyu=FloatBtn。 + * 该标记原本是 diy-float-btn.vue 用来告诉 ai-chat "我是从浮动按钮来的,请隐藏底部 tabBar"。 + * 此方法是 customer-service.js 的**通用 AI 客服入口**,被多处复用: + * - hover-nav(悬浮客服按钮) + * - 商品详情页 / 会员中心 / 个人中心 等的"联系客服"按钮 + * - DIY 浮动按钮(diy-float-btn 内部已自行注入 __dyu=FloatBtn,这里再注入会重复) + * 若在此处统一注入,会让所有 AI 客服入口都隐藏底部 tabBar,语义错误且侵入性过强。 + * hover-nav 需要隐藏 tabBar 的场景,由 hover-nav.vue#handleUnifiedKefuClick + * 自行注入 __dyu=FloatBtn(与 diy-float-btn.vue#onFloatBtnClick 一致)。 */ openAiChatService() { try { @@ -127,7 +138,7 @@ export class CustomerService { } // ✅ 修正路径:必须与 pages.json 中注册的路径一致 - const aiChatUrl = '/pages_tool/ai-chat/index'; + const aiChatUrl = PAGE_KEY_MAP.AI_CHAT_PAGE_URL; // ✅ 使用 navigateTo 保留返回栈(体验更好) uni.navigateTo({ @@ -551,6 +562,9 @@ export class CustomerService { /** * 打开 AI 智能助手 + * + * 注意:不在此处注入 __dyu=FloatBtn,理由同 openAiChatService()。 + * 由调用方(hover-nav.vue 等)按需注入。 */ openAIChat() { try { @@ -558,7 +572,7 @@ export class CustomerService { this.vm.setAiUnreadCount(0); } - const aiChatUrl = '/pages_tool/ai-chat/index'; + const aiChatUrl = PAGE_KEY_MAP.AI_CHAT_PAGE_URL; uni.navigateTo({ url: aiChatUrl, diff --git a/common/js/util.js b/common/js/util.js index eef84bd..a714c70 100644 --- a/common/js/util.js +++ b/common/js/util.js @@ -139,7 +139,7 @@ export const CONTACT_PAGE_URL = '/pages_tool/contact/contact'; export const MEMBER_PAGE_URL = '/pages_tool/member/index'; export const LOGIN_PAGE_URL = '/pages_tool/login/login'; export const AI_CHAT_PAGE_URL = '/pages_tool/ai-chat/index'; -export const AI_AGENT_PAGE_URL = '/pages_tool/ai-chat/index'; // AI 智能体入口页(智能客服是首个 agent) +export const AI_AGENT_PAGE_URL = '/pages_tool/ai-agent/index'; // AI 智能体入口页(智能客服是首个 agent) // page_key 到实际路径的映射表(统一管理所有页面的语义常量 → 实际路径) // 前端组织页面(重命名路径、分包调整)时只需要修改此映射表 diff --git a/components/hover-nav/hover-nav.vue b/components/hover-nav/hover-nav.vue index 133166a..af357ed 100644 --- a/components/hover-nav/hover-nav.vue +++ b/components/hover-nav/hover-nav.vue @@ -743,7 +743,53 @@ export default { this.$langConfig.change(targetLang, url); }, + /** + * 客服按钮点击的统一入口。 + * + * 关键修复:智能客服(AI 客服)类型需要走 ai-chat 页面, + * 且必须在 URL 上注入 __dyu=FloatBtn 标记, + * 让 ai-chat/index.vue 的 onLoad(options) 识别"来自悬浮按钮/浮动按钮", + * commit setBottomNavHidden(true) 隐藏底部 tabBar。 + * + * 为什么不在 customer-service.js#openAiChatService 统一注入: + * 该方法是通用 AI 客服入口,被多处复用(hover-nav / 商品详情页 / 会员中心 / DIY 浮动按钮等), + * 其中 DIY 浮动按钮(diy-float-btn.vue)已自行注入 __dyu=FloatBtn;其他入口(商品详情页等) + * 是否要隐藏 tabBar 是另一个独立的产品决策,不能在此一刀切。 + * 因此由调用方按需注入:本方法(hover-nav)显式注入,diy-float-btn 显式注入, + * 其他入口保持原样。 + * + * 与 diy-float-btn.vue#onFloatBtnClick 的行为完全一致,只是触发位置不同。 + */ handleUnifiedKefuClick() { + // 仅智能客服(aikefu)类型需要走 ai-chat 页面并隐藏 tabBar; + // 其他类型(企业微信 / 第三方 / 小程序原生客服等)由 customerService 内部 + // 路由到对应渠道(navigateToMiniProgram / openCustomerServiceChat 等), + // 与底部 tabBar 无关,继续走原统一入口。 + if (this.customerService && this.customerService.isAIKefu && this.customerService.isAIKefu()) { + // 清除未读数(与 openAiChatService 行为保持一致) + if (typeof this.setAiUnreadCount === 'function') { + this.setAiUnreadCount(0); + } else if (this.$store && typeof this.$store.commit === 'function') { + try { this.$store.commit('setAiUnreadCount', 0); } catch (e) { /* 兼容旧 store */ } + } + + // 注入 __dyu=FloatBtn 标记,与 diy-float-btn.vue#onFloatBtnClick 语义一致 + const aiChatUrl = `${this.$util.PAGE_KEY_MAP.PAGE_AI_CHAT}?__dyu=FloatBtn`; + uni.navigateTo({ + url: aiChatUrl, + fail: (err) => { + console.error('[hover-nav] 跳转 AI智能客服失败:', err); + // H5 兜底 + // #ifdef H5 + window.location.href = aiChatUrl; + // #endif + uni.showToast({ title: this.$lang('customerService.openFailed'), icon: 'none' }); + } + }); + return; + } + + // 非智能客服类型:走原统一入口(企业微信 / 第三方 / 微信原生客服 等) this.customerService.handleUnifiedKefuClick({ sendMessageTitle: '来自悬浮按钮的咨询', sendMessagePath: '/pages/index/index' diff --git a/pages.json b/pages.json index 649e15d..7eddf16 100644 --- a/pages.json +++ b/pages.json @@ -1086,7 +1086,64 @@ { "path": "ai-chat/index", "style": { - "navigationBarTitleText": "AI智能客服" + "navigationBarTitleText": "AI智能客服", + "componentPlaceholder": { + "diy-article": "view", + "diy-audio": "view", + "diy-bargain": "view", + "diy-bottom-nav": "view", + "diy-category": "view", + "diy-category-item": "view", + "diy-channel-list": "view", + "diy-channel-video": "view", + "diy-comp-extend": "view", + "diy-coupon": "view", + "diy-digit": "view", + "diy-fenxiao-goods-list": "view", + "diy-float-btn": "view", + "diy-follow-official-account": "view", + "diy-form": "view", + "diy-goods-brand": "view", + "diy-goods-list": "view", + "diy-goods-recommend": "view", + "diy-graphic-nav": "view", + "diy-group": "view", + "diy-groupbuy": "view", + "diy-horz-blank": "view", + "diy-horz-line": "view", + "diy-hot-area": "view", + "diy-icon": "view", + "diy-image-nav": "view", + "diy-img-ads": "view", + "diy-index-page": "view", + "diy-kefu": "view", + "diy-listmenu": "view", + "diy-live": "view", + "diy-many-goods-list": "view", + "diy-map": "view", + "diy-member-info": "view", + "diy-member-my-order": "view", + "diy-merch-list": "view", + "diy-notes": "view", + "diy-notice": "view", + "diy-payment-qrcode": "view", + "diy-picture": "view", + "diy-pinfan": "view", + "diy-pintuan": "view", + "diy-presale": "view", + "diy-quick-nav": "view", + "diy-recommend-code": "view", + "diy-rich-text": "view", + "diy-rubik-cube": "view", + "diy-search": "view", + "diy-seckill": "view", + "diy-store": "view", + "diy-store-label": "view", + "diy-tab": "view", + "diy-text": "view", + "diy-video": "view", + "diy-video-list": "view" + } } }, { diff --git a/pages_goods/detail.vue b/pages_goods/detail.vue index ed33592..23a231e 100644 --- a/pages_goods/detail.vue +++ b/pages_goods/detail.vue @@ -603,7 +603,7 @@ export default { uni.setStorageSync('selectedProduct', productInfo); uni.navigateTo({ - url: '/pages_tool/ai-chat/index' + url: this.$util.PAGE_KEY_MAP.PAGE_AI_CHAT }); },