From a464a8731f2938d9b817754af8df8b09ebd944a3 Mon Sep 17 00:00:00 2001 From: jinhhanhan <1683105490@qq.com> Date: Sat, 31 Jan 2026 08:59:30 +0800 Subject: [PATCH] =?UTF-8?q?chore=EF=BC=9A=E6=9B=BF=E6=8D=A2=E4=BA=86custom?= =?UTF-8?q?er-service.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/js/customer-service.js | 461 ++++++++++++++-------------------- 1 file changed, 191 insertions(+), 270 deletions(-) diff --git a/common/js/customer-service.js b/common/js/customer-service.js index bd1b508..df71d59 100644 --- a/common/js/customer-service.js +++ b/common/js/customer-service.js @@ -2,68 +2,13 @@ * 客服统一处理服务 * 整合各种客服方式,提供统一的调用接口 */ -class CustomerService { - constructor(vueInstance, externalConfig = {}) { - if (!vueInstance.$lang) { - throw new Error('CustomerService 必须在 Vue 实例中初始化'); - } - +export class CustomerService { + constructor(vueInstance, externalConfig = null) { this.vm = vueInstance; this.externalConfig = externalConfig; // 外部传入的最新配置(优先级最高) this.latestPlatformConfig = null; } - getSupoortKeFuList() { - if (!this.vm) return []; - - const vm = this.vm; - - return [ - { - id: 'weixin-official', - name: vm.$lang('customer.weChatKefu'), - isOfficial: true, - type: 'weapp' - }, - { - id: 'custom-kefu', - name: vm.$lang('customer.systemKefu'), - isOfficial: false - }, - { - id: 'qyweixin-kefu', - name: vm.$lang('customer.weChatWorkKefu'), - isOfficial: false - }, - ] - } - - /** - * 打开客服选择弹窗 - */ - openCustomerSelectPopupDialog() { - const kefu_list = this.getSupoortKeFuList(); - const kefuNames = kefu_list.map(item => item.name); - - uni.showActionSheet({ - itemList: kefuNames, - success: (res) => { - const kefu = kefu_list[res.tapIndex]; - this.externalConfig = kefu ?? this.externalConfig ?? {}; - if (kefu.isOfficial) { - uni.openCustomerServiceConversation({ - sessionFrom: 'weapp', - showMessageCard: true - }); - } else if (kefu.id === 'custom-kefu') { - this.handleCustomerClick(); - } else if (kefu.id === 'qyweixin-kefu') { - this.handleQyWeixinKefuClick(); - } - } - }); - } - /** * 强制刷新配置(支持传入外部配置) * @param {Object} externalConfig 外部最新配置 @@ -83,28 +28,29 @@ class CustomerService { return this.latestPlatformConfig; } - // 优先级:外部传入的最新配置 > vuex配置 > 空对象 + // 优先级:外部传入 > vuex store > 空对象 const servicerConfig = this.externalConfig || this.vm.$store.state.servicerConfig || {}; console.log(`【实时客服配置】`, servicerConfig); let platformConfig = null; + // #ifdef H5 - platformConfig = servicerConfig.h5 ? (typeof servicerConfig.h5 === 'object' ? servicerConfig.h5 : null) : null; + platformConfig = servicerConfig.h5 && typeof servicerConfig.h5 === 'object' ? servicerConfig.h5 : null; // #endif // #ifdef MP-WEIXIN - platformConfig = servicerConfig.weapp ? (typeof servicerConfig.weapp === 'object' ? servicerConfig.weapp : null) : null; + platformConfig = servicerConfig.weapp && typeof servicerConfig.weapp === 'object' ? servicerConfig.weapp : null; // #endif // #ifdef MP-ALIPAY - platformConfig = servicerConfig.aliapp ? (typeof servicerConfig.aliapp === 'object' ? servicerConfig.aliapp : null) : null; + platformConfig = servicerConfig.aliapp && typeof servicerConfig.aliapp === 'object' ? servicerConfig.aliapp : null; // #endif // #ifdef PC - platformConfig = servicerConfig.pc ? (typeof servicerConfig.pc === 'object' ? servicerConfig.pc : null) : null; + platformConfig = servicerConfig.pc && typeof servicerConfig.pc === 'object' ? servicerConfig.pc : null; // #endif - // 处理空数组情况(你的配置中pc/aliapp是空数组,转为null) + // 防止空数组被当作有效配置 if (Array.isArray(platformConfig)) { platformConfig = null; } @@ -144,32 +90,18 @@ class CustomerService { warnings: [] }; - if (!config) { - result.isValid = false; - result.errors.push('客服配置不存在'); - return result; - } - - if (config.type === 'aikefu') { - return result; - } - - if (!config.type) { + if (!config || !config.type) { result.isValid = false; result.errors.push('客服类型未配置'); + return result; } if (config.type === 'wxwork') { - if (!wxworkConfig) { - result.isValid = false; - result.errors.push('企业微信配置不存在'); - } else { - if (!wxworkConfig.enable) { - result.warnings.push('企业微信功能未启用'); - } - if (!wxworkConfig.contact_url) { - result.warnings.push('企业微信活码链接未配置,将使用原有客服方式'); - } + if (!wxworkConfig || !wxworkConfig.enable) { + result.warnings.push('企业微信未启用'); + } + if (!wxworkConfig.contact_url) { + result.warnings.push('企业微信活码链接未配置'); } } @@ -177,16 +109,39 @@ class CustomerService { } /** - * 跳转到AI客服页面 + * 跳转到 AI 客服页面(Dify) */ - openAIKeFuService() { - const vm = this.vm; - vm.$util.redirectTo(vm.$util.AI_CHAT_PAGE_URL); + openDifyService() { + try { + // 清除未读数(如果存在) + if (typeof this.vm.setAiUnreadCount === 'function') { + this.vm.setAiUnreadCount(0); + } + + // ✅ 修正路径:必须与 pages.json 中注册的路径一致 + const aiChatUrl = '/pages_tool/ai-chat/index'; + + // ✅ 使用 navigateTo 保留返回栈(体验更好) + uni.navigateTo({ + url: aiChatUrl, + fail: (err) => { + console.error('跳转 AI 客服失败:', err); + // H5 兜底 + // #ifdef H5 + window.location.href = aiChatUrl; + // #endif + uni.showToast({ title: '打开客服失败', icon: 'none' }); + } + }); + } catch (e) { + console.error('跳转 AI 客服异常:', e); + uni.showToast({ title: '打开客服失败', icon: 'none' }); + } } /** - * 处理客服点击事件 - * @param {Object} options 选项参数 + * 处理客服点击事件(统一入口) + * @param {Object} options 选项参数(用于消息卡片等) */ handleCustomerClick(options = {}) { const validation = this.validateConfig(); @@ -201,51 +156,61 @@ class CustomerService { } const config = this.getPlatformConfig(); - const { niushop = {}, sendMessageTitle = '', sendMessagePath = '', sendMessageImg = '' } = options || {}; + console.log('【当前客服配置】', config); + console.log('【客服类型】', config.type); + + const { niushop = {}, sendMessageTitle = '', sendMessagePath = '', sendMessageImg = '' } = options; if (config.type === 'none') { this.showNoServicePopup(); return; } - // 核心分支:根据最新的type处理 + // 核心路由:根据 type 决定行为 switch (config.type) { case 'aikefu': - this.openAIKeFuService(); + console.log('【跳转 AI 客服】目标路径: /pages_tool/ai-chat/index'); + this.openDifyService(); break; case 'wxwork': + console.log('【跳转企业微信客服】'); this.openWxworkService(false, config, options); break; case 'third': + console.log('【跳转第三方客服】'); + this.openThirdService(config); + break; + case 'miniprogram': + console.log('【跳转第三方小程序客服】'); this.openThirdService(config); break; case 'niushop': + console.log('【跳转牛商客服】'); this.openNiushopService(niushop); break; case 'weapp': + console.log('【跳转微信官方客服】'); this.openWeappService(config, options); break; case 'aliapp': + console.log('【跳转支付宝客服】'); this.openAliappService(config); break; default: + console.error('【未知客服类型】', config.type); this.makePhoneCall(); } } - /** - * 打开企业微信客服 - * @param {boolean} useOriginalService 是否使用原有客服方式 - * @param {Object} servicerConfig 客服配置 - * @param {Object} options 选项参数 - */ + // ================== 各类型客服实现 ================== + openWxworkService(useOriginalService = false, servicerConfig = null, options = {}) { const config = servicerConfig || this.getPlatformConfig(); const wxworkConfig = this.getWxworkConfig(); - const { sendMessageTitle = '', sendMessagePath = '', sendMessageImg = '' } = options || {}; + const { sendMessageTitle = '', sendMessagePath = '', sendMessageImg = '' } = options; // #ifdef MP-WEIXIN - if (wxworkConfig?.enable && wxworkConfig?.contact_url && !useOriginalService) { + if (!useOriginalService && wxworkConfig?.enable && wxworkConfig?.contact_url) { wx.navigateToMiniProgram({ appId: 'wxeb490c6f9b154ef9', path: `pages/contacts/externalContactDetail?url=${encodeURIComponent(wxworkConfig.contact_url)}`, @@ -256,9 +221,16 @@ class CustomerService { } }); } else { + // 检查是否有企业微信配置 + if (!config.wxwork_url && !config.corpid) { + console.error('企业微信配置不完整,缺少 wxwork_url 或 corpid'); + uni.showToast({ title: '企业微信配置不完整', icon: 'none' }); + this.fallbackToPhoneCall(); + return; + } wx.openCustomerServiceChat({ - extInfo: { url: config.wxwork_url }, - corpId: config.corpid, + extInfo: { url: config.wxwork_url || '' }, + corpId: config.corpid || '', showMessageCard: true, sendMessageTitle, sendMessagePath, @@ -268,227 +240,181 @@ class CustomerService { // #endif // #ifdef H5 - if (wxworkConfig?.enable && wxworkConfig?.contact_url) { + if (!useOriginalService && wxworkConfig?.enable && wxworkConfig?.contact_url) { window.location.href = wxworkConfig.contact_url; } else if (config.wxwork_url) { - location.href = config.wxwork_url; + window.location.href = config.wxwork_url; } else { this.fallbackToPhoneCall(); } // #endif } - /** - * 打开第三方客服 - * @param {Object} config 客服配置 - */ openThirdService(config) { + console.log('【第三方客服配置】', config); + console.log('【配置字段】', Object.keys(config)); + + // 支持多种可能的字段名 + const miniAppId = config.mini_app_id || config.miniAppId || config.appid || config.appId || config.app_id; + const miniAppPath = config.mini_app_path || config.miniAppPath || config.path || config.page_path || ''; + + console.log('【解析后的小程序配置】AppID:', miniAppId, 'Path:', miniAppPath); + + // 优先处理第三方微信小程序客服 + if (miniAppId) { + console.log('【跳转第三方小程序】AppID:', miniAppId, 'Path:', miniAppPath); + // #ifdef MP-WEIXIN + wx.navigateToMiniProgram({ + appId: miniAppId, + path: miniAppPath, + success: () => { + console.log('【跳转第三方小程序成功】'); + }, + fail: (err) => { + console.error('【跳转第三方小程序失败】', err); + uni.showToast({ title: '跳转失败,请稍后重试', icon: 'none' }); + } + }); + // #endif + // #ifdef H5 + uni.showToast({ title: '第三方小程序客服仅在微信小程序中可用', icon: 'none' }); + // #endif + return; + } + + // 处理第三方链接客服 if (config.third_url) { + console.log('【跳转第三方链接】', config.third_url); + // #ifdef H5 window.location.href = config.third_url; + // #endif + // #ifdef MP-WEIXIN + uni.setClipboardData({ + data: config.third_url, + success: () => { + uni.showToast({ title: '链接已复制,请在浏览器打开', icon: 'none' }); + } + }); + // #endif } else { + console.error('【第三方客服配置不完整】缺少 mini_app_id 或 third_url'); this.fallbackToPhoneCall(); } } - /** - * 打开牛商客服 - * @param {Object} niushop 牛商参数 - */ openNiushopService(niushop) { - if (Object.keys(niushop).length > 0) { + if (Object.keys(niushop).length > 0 && this.vm.$util?.redirectTo) { this.vm.$util.redirectTo('/pages_tool/chat/room', niushop); } else { this.makePhoneCall(); } } - /** - * 打开微信小程序客服 - * @param {Object} config 客服配置 - * @param {Object} options 选项参数 - */ openWeappService(config, options = {}) { - if (!this.shouldUseCustomService(config)) { - console.log('使用官方微信小程序客服'); + // 如果 useOfficial 为 true 或 undefined,则使用原生系统客服(由 button open-type="contact" 触发) + // 此方法仅用于自定义跳转(如 useOfficial: false) + if (config.useOfficial !== false) { + // 不做任何事,应由