# 企业微信联系客服组件

## 功能说明

这个组件实现了在小程序中点击"联系客服"后，自动跳转到企业微信添加对应销售的功能。

## 关键前提条件

### ⚠️ 重要提醒
微信小程序与企业微信互通有严格的平台限制和权限要求，使用前请确保满足以下所有条件：

### 1. 微信小程序环境要求
- **平台限制**：功能仅在微信小程序环境中可用
- **基础库版本**：需要微信小程序基础库 2.3.0 及以上版本
- **用户环境**：用户需要在微信中打开小程序

### 2. 企业微信配置要求
- **企业认证**：企业微信账号必须完成企业认证
- **客户联系功能**：需要开通企业微信"客户联系"功能
- **应用权限**：企业微信应用需要有客户联系相关权限

### 3. 互通配置要求
- **关联配置**：小程序必须与企业微信进行关联配置
- **权限申请**：需要在微信开放平台和企业微信后台分别申请相应权限
- **域名白名单**：相关域名需要在小程序和企业微信后台都配置白名单

### 4. 跳转权限要求
- **小程序AppID**：需要在企业微信中配置允许跳转的小程序AppID
- **企业微信AppID**：需要在微信开放平台配置关联的企业微信AppID
- **业务域授权**：需要配置业务域授权，允许跨平台跳转

### 5. 开发调试要求
- **测试环境**：需要在测试环境中验证跳转功能
- **权限验证**：确保所有必要的API权限已申请并生效
- **兼容性测试**：在不同微信版本中进行兼容性测试

### 6. 具体配置要求

| 条件 | 说明 |
|------|------|
| **小程序与企业微信绑定** | 在企业微信管理后台 → 「应用管理」→「小程序」中关联你的微信小程序AppID |
| **配置可信域名** | 如果涉及网页跳转或回调，需在企业微信后台配置业务域名 |
| **使用企业微信服务商 or 自建应用** | 若需高级功能（如获取客户详情），需有企业微信管理员权限或通过服务商代开发 |

## 使用方法

### 1. 基础用法

```vue
<wxwork-contact 
    :corp-id="corpId"
    :agent-id="agentId"
    :timestamp="timestamp"
    :nonce-str="nonceStr"
    :signature="signature"
    :contact-id="contactId"
    :contact-url="contactUrl"
    btn-text="添加企业微信客服">
</wxwork-contact>
```

### 组件架构

### 分层设计
```
调用方 (页面组件)
    ↓ 传递配置参数
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
<wxwork-contact 
    v-if="wxworkConfig && wxworkConfig.enabled"
    :corp-id="wxworkConfig.corpId"
    :agent-id="wxworkConfig.agentId"
    :timestamp="wxworkConfig.timestamp"
    :nonce-str="wxworkConfig.nonceStr"
    :signature="wxworkConfig.signature"
    :contact-id="wxworkConfig.contactId"
    :contact-url="wxworkConfig.contactUrl"
    btn-text="企业微信客服"
    :show-confirm="false">
</wxwork-contact>
```

## 配置说明

### 后端接口需求

企业微信配置已集成到 `/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 |