diff --git a/App.vue b/App.vue index 061c99f..ddc469e 100644 --- a/App.vue +++ b/App.vue @@ -98,6 +98,11 @@ if (uni.getStorageSync('servicerConfig')) { this.$store.commit('setServicerConfig', uni.getStorageSync('servicerConfig')); } + + // 企业微信配置 + if (uni.getStorageSync('wxworkConfig')) { + this.$store.commit('setWxworkConfig', uni.getStorageSync('wxworkConfig')); + } // 版权信息 if (uni.getStorageSync('copyright')) { diff --git a/common/js/customer-service.js b/common/js/customer-service.js new file mode 100644 index 0000000..a24af90 --- /dev/null +++ b/common/js/customer-service.js @@ -0,0 +1,345 @@ +/** + * 客服统一处理服务 + * 整合各种客服方式,提供统一的调用接口 + */ + +export class CustomerService { + constructor(vueInstance) { + this.vm = vueInstance; + } + + /** + * 获取平台配置 + * @returns {Object} 平台对应的客服配置 + */ + getPlatformConfig() { + const servicerConfig = this.vm.$store.state.servicerConfig; + if (!servicerConfig) return null; + + // #ifdef H5 + return servicerConfig.h5; + // #endif + + // #ifdef MP-WEIXIN + return servicerConfig.weapp; + // #endif + + // #ifdef MP-ALIPAY + return servicerConfig.aliapp; + // #endif + + return null; + } + + /** + * 获取企业微信配置 + * @returns {Object} 企业微信配置 + */ + getWxworkConfig() { + return this.vm.$store.state.wxworkConfig; + } + + /** + * 检查客服配置是否可用 + * @returns {boolean} 是否有可用配置 + */ + isConfigAvailable() { + const config = this.getPlatformConfig(); + return config && typeof config === 'object' && config.type; + } + + /** + * 验证客服配置完整性 + * @returns {Object} 验证结果 + */ + validateConfig() { + const config = this.getPlatformConfig(); + const wxworkConfig = this.getWxworkConfig(); + + const result = { + isValid: true, + errors: [], + warnings: [] + }; + + if (!config) { + result.isValid = false; + result.errors.push('客服配置不存在'); + return result; + } + + if (!config.type) { + result.isValid = false; + result.errors.push('客服类型未配置'); + } + + // 验证企业微信配置 + 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('企业微信活码链接未配置,将使用原有客服方式'); + } + } + } + + return result; + } + + /** + * 获取客服类型 + * @returns {string} 客服类型 + */ + getServiceType() { + const config = this.getPlatformConfig(); + return config?.type || 'none'; + } + + /** + * 处理客服点击事件 + * @param {Object} options 选项参数 + * @param {Object} options.niushop 牛商客服参数 + * @param {string} options.sendMessageTitle 消息标题 + * @param {string} options.sendMessagePath 消息路径 + * @param {string} options.sendMessageImg 消息图片 + */ + handleCustomerClick(options = {}) { + // 验证配置 + const validation = this.validateConfig(); + if (!validation.isValid) { + console.error('客服配置验证失败:', validation.errors); + this.showConfigErrorPopup(validation.errors); + return; + } + + // 显示警告(如果有) + if (validation.warnings.length > 0) { + console.warn('客服配置警告:', validation.warnings); + } + + const config = this.getPlatformConfig(); + const { + niushop = {}, + sendMessageTitle = '', + sendMessagePath = '', + sendMessageImg = '' + } = options; + + // 检查是否为无客服类型 + if (config.type === 'none') { + this.showNoServicePopup(); + return; + } + + // 根据类型处理客服 + switch (config.type) { + case 'wxwork': + this.openWxworkService(false, config, options); + break; + case 'third': + this.openThirdService(config); + break; + case 'niushop': + this.openNiushopService(niushop); + break; + case 'weapp': + this.openWeappService(config); + break; + case 'aliapp': + this.openAliappService(config); + break; + default: + this.makePhoneCall(); + } + } + + /** + * 打开企业微信客服 + * @param {boolean} useOriginalService 是否使用原有客服方式 + * @param {Object} servicerConfig 客服配置 + */ + openWxworkService(useOriginalService = false, servicerConfig = null, options = {}) { + const config = servicerConfig || this.getPlatformConfig(); + const wxworkConfig = this.getWxworkConfig(); + + const { + sendMessageTitle = '', + sendMessagePath = '', + sendMessageImg = '' + } = options; + + // #ifdef MP-WEIXIN + if (wxworkConfig?.enable && wxworkConfig?.contact_url && !useOriginalService) { + // 使用活码链接跳转到企业微信 + wx.navigateToMiniProgram({ + appId: 'wxeb490c6f9b154ef9', // 企业微信官方小程序AppID + path: `pages/contacts/externalContactDetail?url=${encodeURIComponent(wxworkConfig.contact_url)}`, + success: () => { + console.log('跳转企业微信成功'); + }, + fail: (err) => { + console.error('跳转企业微信失败:', err); + this.fallbackToOriginalService(); + } + }); + } else { + // 使用原有的客服会话方式 + wx.openCustomerServiceChat({ + extInfo: { url: config.wxwork_url }, + corpId: config.corpid, + showMessageCard: true, + sendMessageTitle, + sendMessagePath, + sendMessageImg + }); + } + // #endif + + // #ifdef H5 + if (wxworkConfig?.enable && wxworkConfig?.contact_url) { + window.location.href = wxworkConfig.contact_url; + } else { + location.href = config.wxwork_url; + } + // #endif + } + + /** + * 打开第三方客服 + * @param {Object} config 客服配置 + */ + openThirdService(config) { + if (config.third_url) { + location.href = config.third_url; + } + } + + /** + * 打开牛商客服 + * @param {Object} niushop 牛商参数 + */ + openNiushopService(niushop) { + if (Object.keys(niushop).length > 0) { + this.vm.$util.redirectTo('/pages_tool/chat/room', niushop); + } else { + this.makePhoneCall(); + } + } + + /** + * 打开微信小程序客服 + * @param {Object} config 客服配置 + */ + openWeappService(config) { + // 微信小程序客服会由 open-type="contact" 自动处理 + console.log('微信小程序客服'); + } + + /** + * 打开支付宝小程序客服 + * @param {Object} config 客服配置 + */ + openAliappService(config) { + // 支付宝小程序客服会由 contact-button 组件自动处理 + console.log('支付宝小程序客服'); + } + + /** + * 拨打电话 + */ + makePhoneCall() { + this.vm.$api.sendRequest({ + url: '/api/site/shopcontact', + success: res => { + if (res.code === 0 && res.data?.mobile) { + uni.makePhoneCall({ + phoneNumber: res.data.mobile + }); + } + } + }); + } + + /** + * 显示无客服弹窗 + */ + showNoServicePopup() { + const siteInfo = this.vm.$store.state.siteInfo; + const message = siteInfo?.site_tel + ? `请联系客服,客服电话是${siteInfo.site_tel}` + : '抱歉,商家暂无客服,请线下联系'; + + uni.showModal({ + title: '联系客服', + content: message, + showCancel: false + }); + } + + /** + * 显示配置错误弹窗 + * @param {Array} errors 错误列表 + */ + showConfigErrorPopup(errors) { + const message = errors.join('\n'); + uni.showModal({ + title: '配置错误', + content: `客服配置有误:\n${message}`, + showCancel: false + }); + } + + /** + * 降级处理:使用原有客服方式 + */ + fallbackToOriginalService() { + uni.showModal({ + title: '提示', + content: '无法直接添加企业微信客服,是否使用其他方式联系客服?', + success: (res) => { + if (res.confirm) { + console.log('降级处理:使用原有客服方式'); + this.openWxworkService(true); + } + } + }); + } + + /** + * 获取客服按钮配置 + * @returns {Object} 按钮配置 + */ + getButtonConfig() { + const config = this.getPlatformConfig(); + if (!config) return { openType: '' }; + + let openType = ''; + + // #ifdef MP-WEIXIN + if (config.type === 'weapp') openType = 'contact'; + // #endif + + // #ifdef MP-ALIPAY + if (config.type === 'aliapp') openType = 'contact'; + // #endif + + return { + ...config, + openType + }; + } +} + +/** + * 创建客服服务实例 + * @param {Object} vueInstance Vue实例 + * @returns {CustomerService} 客服服务实例 + */ +export function createCustomerService(vueInstance) { + return new CustomerService(vueInstance); +} \ No newline at end of file diff --git a/components/hover-nav/hover-nav.vue b/components/hover-nav/hover-nav.vue index c4f38c3..d5a46bf 100644 --- a/components/hover-nav/hover-nav.vue +++ b/components/hover-nav/hover-nav.vue @@ -3,17 +3,20 @@ - - + + - - - + - + @@ -24,7 +18,8 @@ 联系客服 - {{ siteInfo.site_tel ? '请联系客服,客服电话是' + siteInfo.site_tel : '抱歉,商家暂无客服,请线下联系' }} + {{ siteInfo.site_tel ? '请联系客服,客服电话是' + siteInfo.site_tel : '抱歉,商家暂无客服,请线下联系' }} + @@ -32,186 +27,98 @@ \ No newline at end of file diff --git a/components/wxwork-contact/CHANGELOG.md b/components/wxwork-contact/CHANGELOG.md new file mode 100644 index 0000000..bbd49e1 --- /dev/null +++ b/components/wxwork-contact/CHANGELOG.md @@ -0,0 +1,66 @@ +# 企业微信联系客服组件更新日志 + +## v2.0.0 - 集成全局Store配置 + +### 新增功能 +- ✅ 企业微信配置集成到全局Store +- ✅ 从 `/api/config/init` 统一获取配置 +- ✅ 支持props覆盖全局配置 +- ✅ 优化配置获取逻辑 + +### 变更内容 +1. **Store集成**: + - 在 `store/index.js` 中添加 `wxworkConfig` 状态 + - 添加 `setWxworkConfig` mutation + - 在 `init` action 中从 `/api/config/init` 获取企业微信配置 + +2. **组件优化**: + - `wxwork-contact.vue` 组件现在优先从全局Store获取配置 + - 支持通过props覆盖全局配置 + - 移除单独的API调用,使用统一配置 + +3. **页面集成**: + - `pages/contact/contact.vue` 页面简化配置获取逻辑 + - 直接使用全局Store中的企业微信配置 + +### 配置格式 +后端 `/api/config/init` 需要返回以下格式的企业微信配置: + +```json +{ + "code": 0, + "data": { + // ... 其他配置 ... + "wxwork": { + "corp_id": "企业ID", + "agent_id": "应用ID", + "contact_id": "客服ID", + "contact_url": "活码链接", + "timestamp": "时间戳", + "nonceStr": "随机字符串", + "signature": "签名", + "enabled": true + } + } +} +``` + +### 使用方式 +```vue + + + + + +``` + +## v1.0.0 - 初始版本 + +### 功能 +- 企业微信JS-SDK封装 +- 基础联系客服组件 +- 支持小程序和H5环境 +- 活码跳转和SDK两种方式 \ No newline at end of file diff --git a/components/wxwork-contact/README.md b/components/wxwork-contact/README.md new file mode 100644 index 0000000..ce09d20 --- /dev/null +++ b/components/wxwork-contact/README.md @@ -0,0 +1,484 @@ +# 企业微信联系客服组件 + +## 功能说明 + +这个组件实现了在小程序中点击"联系客服"后,自动跳转到企业微信添加对应销售的功能。 + +## 关键前提条件 + +### ⚠️ 重要提醒 +微信小程序与企业微信互通有严格的平台限制和权限要求,使用前请确保满足以下所有条件: + +### 1. 微信小程序环境要求 +- **平台限制**:功能仅在微信小程序环境中可用 +- **基础库版本**:需要微信小程序基础库 2.3.0 及以上版本 +- **用户环境**:用户需要在微信中打开小程序 + +### 2. 企业微信配置要求 +- **企业认证**:企业微信账号必须完成企业认证 +- **客户联系功能**:需要开通企业微信"客户联系"功能 +- **应用权限**:企业微信应用需要有客户联系相关权限 + +### 3. 互通配置要求 +- **关联配置**:小程序必须与企业微信进行关联配置 +- **权限申请**:需要在微信开放平台和企业微信后台分别申请相应权限 +- **域名白名单**:相关域名需要在小程序和企业微信后台都配置白名单 + +### 4. 跳转权限要求 +- **小程序AppID**:需要在企业微信中配置允许跳转的小程序AppID +- **企业微信AppID**:需要在微信开放平台配置关联的企业微信AppID +- **业务域授权**:需要配置业务域授权,允许跨平台跳转 + +### 5. 开发调试要求 +- **测试环境**:需要在测试环境中验证跳转功能 +- **权限验证**:确保所有必要的API权限已申请并生效 +- **兼容性测试**:在不同微信版本中进行兼容性测试 + +### 6. 具体配置要求 + +| 条件 | 说明 | +|------|------| +| **小程序与企业微信绑定** | 在企业微信管理后台 → 「应用管理」→「小程序」中关联你的微信小程序AppID | +| **配置可信域名** | 如果涉及网页跳转或回调,需在企业微信后台配置业务域名 | +| **使用企业微信服务商 or 自建应用** | 若需高级功能(如获取客户详情),需有企业微信管理员权限或通过服务商代开发 | + +## 使用方法 + +### 1. 基础用法 + +```vue + + +``` + +### 组件架构 + +### 分层设计 +``` +调用方 (页面组件) + ↓ 传递配置参数 +wxwork-contact 组件 + ↓ 调用SDK +wxwork-jssdk.js + ↓ 调用企业微信API +企业微信服务 +``` + +### 组件设计原则 + +- **独立性**:组件不直接依赖全局Store,所有配置通过props传递 +- **职责分离**:组件只负责UI展示和企业微信SDK调用,配置管理由调用方负责 +- **灵活配置**:支持调用者覆盖任何配置参数 + +## 版本信息 + +### v3.0.0 - 统一客服服务重构版本 +- 创建 `CustomerService` 统一客服处理服务 +- 重构 `ns-contact.vue` 和 `hover-nav.vue` 消除重复代码 +- 提供统一的客服处理接口和平台适配 +- 完善错误处理和降级机制 +- 支持所有客服类型的统一调用 + +### v2.0.0 - Store集成版本 +- 企业微信配置集成到全局Store +- 从 `/api/config/init` 统一获取配置 +- 组件完全独立,通过props接收配置 +- 支持全局配置和局部覆盖 + +### v1.0.0 - 初始版本 +- 基础企业微信联系功能 +- 支持活码跳转和JS-SDK两种方式 + +### 2. 属性说明 + +| 属性 | 类型 | 默认值 | 说明 | +|------|------|--------|------| +| btnText | String | '添加企业微信客服' | 按钮文字 | +| corpId | String | - | 企业ID(必需) | +| agentId | String | '' | 应用ID | +| timestamp | String | '' | 时间戳 | +| nonceStr | String | '' | 随机字符串 | +| signature | String | '' | 签名 | +| contactId | String | '' | 客服ID或活码配置ID | +| contactUrl | String | '' | 活码链接 | +| showConfirm | Boolean | true | 是否显示确认弹窗 | + +### 3. 在联系页面中使用 + +在 `pages/contact/contact.vue` 中已集成使用示例: + +```vue + + +``` + +## 配置说明 + +### 后端接口需求 + +企业微信配置已集成到 `/api/config/init` 接口中,返回以下格式的数据: + +```json +{ + "code": 0, + "data": { + // ... 其他配置 ... + "wxwork": { + "corp_id": "企业ID", + "agent_id": "应用ID", + "contact_id": "客服ID", + "contact_url": "活码链接", + "timestamp": "时间戳", + "nonceStr": "随机字符串", + "signature": "签名", + "enabled": true + } + } +} +``` + +### 全局Store集成 + +企业微信配置通过以下方式集成到全局状态管理: + +1. **Store状态**:在 `store/index.js` 中添加 `wxworkConfig` 状态 +2. **配置获取**:在 `init` action 中从 `/api/config/init` 获取企业微信配置 +3. **状态更新**:使用 `setWxworkConfig` mutation 更新配置 +4. **持久化**:配置自动保存到本地存储 + +### 企业微信配置步骤 + +1. **获取企业微信活码**: + - 登录企业微信管理后台 + - 进入"客户联系" -> "配置" -> "联系我" + - 创建活码,获取配置ID或直接获取活码链接 + +2. **配置参数**: + - `corp_id`: 企业ID(在企业微信后台获取) + - `agent_id`: 企业微信应用ID + - `contact_id`: 客服的用户ID + - `contact_url`: 企业微信活码链接(推荐使用活码链接) + - `timestamp`: 生成签名的时间戳 + - `nonceStr`: 生成签名的随机字符串 + - `signature`: JS-SDK签名 + +## 典型业务流程示例 + +### 目标 +用户在小程序中点击"联系客服",自动添加对应的企业微信销售。 + +### 步骤 +1. **后端调用企业微信 API** 创建「联系我」二维码(可带场景值,如 user_id=123)。 +2. **前端在小程序中展示该二维码(或生成跳转链接)**。 +3. **用户长按识别 → 打开企业微信 → 添加客服**。 +4. **企业微信收到添加事件 → 通过 API 获取 external_userid → 关联到原小程序用户**。 + +## 实现原理 + +### 方案1:企业微信活码跳转(推荐) +- 使用企业微信活码链接 +- 通过 `uni.navigateToMiniProgram` 跳转到企业微信小程序 +- 直接添加对应的销售为联系人 + +### 方案2:JS-SDK方式 +- 使用企业微信JS-SDK +- 调用 `openUserProfile` 接口打开用户资料 +- 用户手动添加联系人 + +## 注意事项 + +### 功能限制 +1. **小程序环境**:需要在微信小程序环境中使用 +2. **权限配置**:确保小程序有跳转企业微信的权限 +3. **降级处理**:当企业微信不可用时,会降级到原有客服方式 +4. **用户体验**:建议添加确认弹窗,避免误操作 + +### 前提条件验证 +5. **权限检查**:使用前需要验证所有必需权限是否生效 +6. **配置完整性**:确保所有配置参数都已正确设置 +7. **网络环境**:确保用户网络环境允许访问企业微信服务 +8. **版本兼容**:检查微信版本和企业微信版本兼容性 + +### 调试建议 +9. **错误监控**:添加适当的错误日志和用户反馈机制 +10. **性能优化**:避免频繁的SDK初始化和配置获取 +11. **安全考虑**:敏感配置信息应在服务端处理,前端不暴露 + +## 兼容性 + +- 微信小程序:✅ 支持 +- H5环境:✅ 支持跳转活码链接 +- 其他平台:降级处理 + +## 文件结构 + +``` +components/wxwork-contact/ +├── wxwork-contact.vue # 主组件 +└── README.md # 说明文档 + +components/ns-contact/ +└── ns-contact.vue # 统一客服组件(重构后) + +components/hover-nav/ +└── hover-nav.vue # 悬浮导航组件(重构后) + +common/js/ +├── wxwork-jssdk.js # 企业微信JS-SDK封装 +└── customer-service.js # 客服统一处理服务(新增) + +store/ +└── index.js # 全局Store,包含wxworkConfig状态管理 + +pages/contact/ +└── contact.vue # 联系页面,集成企业微信功能 +``` + +## 系统梳理与优化 (v3.1.0) + +### 🔧 已修复的问题 + +#### 1. **App.vue 配置恢复** +- ✅ 修复了企业微信配置 (`wxworkConfig`) 在应用启动时的恢复 +- ✅ 确保所有配置都能正确从本地存储恢复到Store + +#### 2. **客服服务参数传递** +- ✅ 修复了 `openCustomerServiceChat` 参数传递错误 +- ✅ 正确传递 `sendMessageTitle`、`sendMessagePath`、`sendMessageImg` + +#### 3. **组件配置访问** +- ✅ 在 `ns-contact.vue` 和 `hover-nav.vue` 中添加 computed 属性 +- ✅ 确保能够正确访问 `servicerConfig` + +#### 4. **企业微信服务优化** +- ✅ 改进参数传递,支持自定义消息参数 +- ✅ 统一处理函数调用方式 + +### 🛡️ 新增功能 + +#### 1. **配置验证机制** +```javascript +const validation = this.customerService.validateConfig(); +if (!validation.isValid) { + // 处理配置错误 +} +``` + +#### 2. **错误处理增强** +- ✅ 添加配置错误弹窗 +- ✅ 改进错误日志记录 +- ✅ 警告信息提示 + +#### 3. **类型安全** +- ✅ 完善参数类型检查 +- ✅ 空值和异常情况处理 + +### 📋 当前系统状态 + +| 组件 | 状态 | 功能完整性 | +|------|------|-----------| +| **customer-service.js** | ✅ 完成 | 统一客服处理服务 | +| **ns-contact.vue** | ✅ 修复 | 支持所有客服类型 | +| **hover-nav.vue** | ✅ 修复 | 集成统一客服服务 | +| **App.vue** | ✅ 修复 | 配置完整恢复 | +| **contact.vue** | ⚠️ 待优化 | 仍使用原始方式 | + +### 🔄 待优化项 + +#### 1. **contact.vue 页面重构** +- 建议集成统一客服服务 +- 添加企业微信客服按钮 +- 统一UI交互体验 + +#### 2. **加载状态反馈** +- 客服功能调用时的loading状态 +- 网络请求的进度指示 + +#### 3. **用户体验优化** +- 客服按钮的点击反馈 +- 错误状态的友好提示 + +### 🧪 测试建议 + +1. **配置验证测试**: + - 测试各种配置缺失情况 + - 验证错误提示准确性 + +2. **平台兼容测试**: + - 微信小程序客服功能 + - H5环境跳转 + - 支付宝小程序客服 + +3. **企业微信功能测试**: + - 活码链接跳转 + - 降级处理机制 + - 参数传递正确性 + +### 📖 使用最佳实践 + +```javascript +// 推荐使用方式 +const customerService = createCustomerService(this); + +// 带配置验证的调用 +if (customerService.isConfigAvailable()) { + customerService.handleCustomerClick({ + sendMessageTitle: '商品咨询', + sendMessagePath: '/pages/goods/detail', + sendMessageImg: 'product-image.jpg' + }); +} +``` + +## 重构说明 (v3.0.0) + +### 统一客服处理服务 + +为了解决代码重复问题,我们创建了 `CustomerService` 类来统一处理所有客服逻辑: + +#### 主要改进 +1. **代码复用**:消除 `ns-contact.vue` 和 `hover-nav.vue` 中的重复代码 +2. **统一接口**:提供一致的客服处理API +3. **平台适配**:自动处理不同平台的客服配置 +4. **类型安全**:完善的错误处理和降级机制 + +#### 使用方式 + +**1. 在组件中导入** +```javascript +import { createCustomerService } from '@/common/js/customer-service.js'; +``` + +**2. 初始化服务** +```javascript +created() { + this.customerService = createCustomerService(this); + this.buttonConfig = this.customerService.getButtonConfig(); +} +``` + +**3. 处理客服点击** +```javascript +methods: { + contactServicer() { + this.customerService.handleCustomerClick({ + niushop: this.niushop, + sendMessageTitle: this.sendMessageTitle, + sendMessagePath: this.sendMessagePath, + sendMessageImg: this.sendMessageImg + }); + } +} +``` + +#### 核心方法 + +| 方法名 | 用途 | 参数 | +|--------|------|------| +| `handleCustomerClick(options)` | 统一处理客服点击 | 客服配置选项 | +| `getButtonConfig()` | 获取按钮配置 | - | +| `getServiceType()` | 获取客服类型 | - | +| `openWxworkService()` | 打开企业微信客服 | 是否使用原方式 | + +#### 支持的客服类型 + +- `wxwork` - 企业微信客服 +- `third` - 第三方客服 +- `niushop` - 牛商客服 +- `weapp` - 微信小程序客服 +- `aliapp` - 支付宝小程序客服 +- `none` - 无客服(显示提示) + +## 常见问题 (FAQ) + +### Q: contact_id 是小程序ID吗? +A: 不是的。`contact_id` 是**企业微信中客服人员的用户ID**,具体说明如下: + +- **定义**:企业微信系统内部分配给客服人员的唯一标识符 +- **获取方式**:通过企业微信管理后台的"客户联系" → "配置" → "联系我"功能创建活码时获得 +- **用途**:用于指定具体客服人员,当用户点击"联系客服"时,系统通过这个ID知道应该添加哪个企业微信客服人员 + +### Q: contact_id 和小程序ID的区别? +A: 两者的作用完全不同: + +| 字段 | 用途 | 获取方式 | +|------|------|----------| +| **contact_id** | 指定具体的企业微信客服人员 | 企业微信管理后台获取 | +| **小程序AppID** | 识别整个微信小程序应用 | 微信开放平台获取 | + +在业务流程中: +1. 用户在小程序中点击"联系客服" +2. 系统使用 `contact_id` 打开对应的企业微信客服人员资料 +3. 用户添加该企业微信客服为联系人 + +所以 `contact_id` 是企业微信客服的ID,不是小程序的ID。 + +### Q: wxwork_contact_url 从哪里来? +A: `wxwork_contact_url` 应该来自全局Store中的 `wxworkConfig`,而不是 `servicerConfig`: + +**正确的配置来源**: +- ✅ `this.$store.state.wxworkConfig.contact_url` - 企业微信配置 +- ❌ `this.config.wxwork_contact_url` - 错误的配置路径 + +**配置获取流程**: +1. **后端接口**:`/api/config/init` 返回 `wxwork_config` 数据 +2. **Store存储**:`setWxworkConfig` 将配置保存到 `wxworkConfig` 状态 +3. **组件使用**:通过 `this.$store.state.wxworkConfig.contact_url` 访问 + +**代码修正示例**: +```javascript +// 错误 ❌ +if (this.config.wxwork_contact_url) { ... } + +// 正确 ✅ +const wxworkConfig = this.$store.state?.wxworkConfig; +if (wxworkConfig?.contact_url) { ... } +``` + +**字段对应关系**: +| 后端字段 | Store字段 | 组件使用 | +|---------|----------|----------| +| `contact_url` | `contact_url` | `wxworkConfig.contact_url` | + +### Q: navigateToMiniProgram 中的企业微信小程序AppID 是指我的业务小程序ID吗? +A: 不是的!`appId: 'wxeb490c6f9b154ef9'` 是**企业微信官方小程序的AppID**,不是你的业务小程序ID。 + +**两者的区别**: + +| 小程序类型 | AppID示例 | 用途 | 所有者 | +|-----------|----------|------|--------| +| **企业微信官方小程序** | `wxeb490c6f9b154ef9` | 展示企业联系人详情页面 | 腾讯企业微信团队 | +| **你的业务小程序** | 你的AppID | 你的业务功能(电商、服务等) | 你的企业/组织 | + +**业务流程**: +``` +用户小程序 (你的业务) + ↓ 点击"联系客服" +navigateToMiniProgram 跳转到 +企业微信官方小程序 (wxeb490c6f9b154ef9) + ↓ 展示联系人详情 +用户添加客服人员到企业微信 +``` + +**关键点**: +- 这个AppID是企业微信官方小程序,通常是固定值 +- 用于跳转到企业微信环境展示联系人详情 +- 不需要替换成你自己的小程序AppID | \ No newline at end of file