# GUI 单连接多店铺 WebSocket 通信协议

---

## 1. 连接地址与认证

```
ws://<host>/ws/gui/<exe_token>/
```

- `exe_token`：用户侧令牌，用于鉴权。连接成功后，后端会立即下发一次连接成功消息（不包含店铺 ID）。

### 1.1 连接成功（初次，仅鉴权）
```json
{
  "type": "success",
  "content": "connected"
}
```
说明：该消息仅表示“用户级连接成功”，不包含店铺上下文。后续业务消息按店铺维度进行（见下）。

---

## 2. 总体约定（多店铺）

- 单条 WS 连接可处理 N 个店铺消息。除心跳 `ping` 外，GUI → 后端的业务消息必须携带 `store_id`（UUID）。
- 后端在收到带有 `store_id` 的首条消息时，会按需初始化该店铺上下文并进行处理、转发与存储。
- 当后台需要为某店铺下发平台连接所需 cookie 时，会通过该用户的这条 WS 连接发送携带 `store_id` 的 `connect_success`。

---

## 3. 字段规范

### 3.1 GUI → 后端（必填）

| 字段          | 类型    | 说明                                                     |
|---------------|---------|----------------------------------------------------------|
| `type`        | string  | "message" \| "staff_list" \| "ping" \| "transfer" 等 |
| `content`     | string  | 消息内容（文本/链接/卡片文本等）。`ping` 无需此字段。   |
| `sender.id`   | string  | 平台用户 pin。`ping` 无需此字段。                        |
| `store_id`    | string  | 店铺 UUID。`ping` 无需此字段。                           |
| `msg_type`    | string  | 消息类型：text/image/video/product_card/order_card。      |

说明：
- 文本/卡片可自动识别，但建议显式传 `msg_type`，图片与视频必须传。
- 可选字段：`pin_image`（头像 URL），`timestamp`（毫秒），`message_id` 等。

### 3.2 后端 → GUI（通用）

| 字段          | 类型    | 说明                                                                      |
|---------------|---------|---------------------------------------------------------------------------|
| `type`        | string  | 消息类型：connect_success/message/transfer/error/pong 等                 |
| `content`     | string  | 具体内容：cookie 文本、AI 回复、错误说明等                               |
| `msg_type`    | string  | 当 `type=message` 时需要，如 text/image/video/product_card/order_card    |
| `receiver.id` | string  | 当后端主动发消息/AI 回复/转接时指定接收用户 pin                          |
| `store_id`    | string  | 关联店铺 UUID（初次连接成功不带；店铺级 cookie 下发时必须携带）          |

---

## 4. GUI → 后端：消息格式示例

### 4.1 文本消息
```json
{
  "type": "message",
  "content": "你好，请问在吗？",
  "msg_type": "text",
  "sender": { "id": "jd_user_001" },
  "store_id": "93a5c3d2-efe1-4ab5-ada3-d8c1d1212b31"
}
```

### 4.2 图片消息
```json
{
  "type": "message",
  "content": "https://example.com/a.jpg",
  "msg_type": "image",
  "sender": { "id": "jd_user_001" },
  "store_id": "93a5c3d2-efe1-4ab5-ada3-d8c1d1212b31"
}
```

### 4.3 视频消息
```json
{
  "type": "message",
  "content": "https://example.com/a.mp4",
  "msg_type": "video",
  "sender": { "id": "jd_user_001" },
  "store_id": "93a5c3d2-efe1-4ab5-ada3-d8c1d1212b31"
}
```

### 4.4 商品卡片（链接）
```json
{
  "type": "message",
  "content": "https://item.jd.com/100123456789.html",
  "msg_type": "product_card",
  "sender": { "id": "jd_user_001" },
  "store_id": "93a5c3d2-efe1-4ab5-ada3-d8c1d1212b31"
}
```

### 4.5 订单卡片
```json
{
  "type": "message",
  "content": "商品id：100123456789 订单号：250904-518080458310434",
  "msg_type": "order_card",
  "sender": { "id": "jd_user_001" },
  "store_id": "93a5c3d2-efe1-4ab5-ada3-d8c1d1212b31"
}
```

### 4.6 客服列表（staff_list）
```json
{
  "type": "staff_list",
  "content": "客服列表更新",
  "data": {
    "staff_list": [
      { "staff_id": "7545667615256944155", "name": "售后客服01", "status": 1, "department": "", "online": true },
      { "staff_id": "1216524360102748", "name": "水滴智能优品", "status": 1, "department": "", "online": true }
    ]
  },
  "store_id": "93a5c3d2-efe1-4ab5-ada3-d8c1d1212b31"
}
```

### 4.7 心跳（ping）
```json
{ "type": "ping", "uuid": "connection_test_123" }
```

---

## 5. 后端 → GUI：消息格式示例

### 5.1 后台点击登录后下发cookies给gui进行连接平台
```json
{
  "type": "connect_success",
  "content": "<cookie_string>",
  "store_id": "93a5c3d2-efe1-4ab5-ada3-d8c1d1212b31",
  "platform_name": "京东"
}
```
说明：当后台触发店铺登录后由后端推送，GUI 收到后使用该 cookie 连接对应平台。

### 5.2 错误消息
```json
{
  "type": "error",
  "content": "图形验证码校验失败，请刷新重试！",
  "receiver": { "id": "gui_12345678" },
  "data": { "verify_link": "https://safe.jd.com/verify.html?xxx" },
  "store_id": "93a5c3d2-efe1-4ab5-ada3-d8c1d1212b31"
}
```

### 5.3 AI 回复
```json
{
  "type": "message",
  "content": "您好！我是智能客服，很高兴为您服务。",
  "msg_type": "text",
  "receiver": { "id": "jd_user_001" },
  "store_id": "93a5c3d2-efe1-4ab5-ada3-d8c1d1212b31"
}
```

### 5.4 后台客服消息转发
```json
{
  "type": "message",
  "content": "好的，我来为您查询订单状态",
  "msg_type": "text",
  "receiver": { "id": "jd_user_001" },
  "store_id": "93a5c3d2-efe1-4ab5-ada3-d8c1d1212b31"
}
```

### 5.5 客服转接
```json
{
  "type": "transfer",
  "content": "客服小王",
  "receiver": { "id": "jd_user_001" },
  "store_id": "93a5c3d2-efe1-4ab5-ada3-d8c1d1212b31"
}
```

### 5.6 自动催单（示例）
```json
{
  "type": "message",
  "content": "亲，您的订单还在等待您的确认哦~如有任何疑问请及时联系我们！",
  "msg_type": "text",
  "receiver": { "id": "jd_user_001" },
  "store_id": "93a5c3d2-efe1-4ab5-ada3-d8c1d1212b31"
}
```

### 5.7 心跳回复（pong）
```json
{ "type": "pong", "uuid": "connection_test_123" }
```

### 5.8 GUI重连状态上报
```json
{
  "type": "connect_message",
  "store_id": "93a5c3d2-efe1-4ab5-ada3-d8c1d1212b31",
  "status": true,
  "content": "GUI重连成功，京东平台状态正常"
}
```
说明：GUI重连成功后，会自动为每个活跃平台发送状态上报消息。

---

## 6. GUI重连机制

### 6.1 重连触发条件
- WebSocket连接关闭（如ping timeout）
- 网络连接异常
- 服务器重启或维护
- 消息发送失败

### 6.2 重连策略
- **最大重连次数**：10次
- **退避策略**：指数退避（2秒 → 3秒 → 4.5秒 → ... → 最大60秒）
- **心跳配置**：可在config.py中配置
  - `WS_ENABLE_PING = True`：是否启用心跳（默认启用）
  - `WS_PING_INTERVAL = 30`：心跳间隔30秒
  - `WS_PING_TIMEOUT = 15`：心跳超时15秒

### 6.3 心跳机制说明
**WebSocket ping/pong帧 vs JSON ping消息**：
- **WebSocket ping帧**：协议层面的心跳，由websockets库自动处理
- **JSON ping消息**：应用层面的心跳，格式：`{"type":"ping","uuid":"ping_123"}`

**配置建议**：
- **生产环境**：建议启用心跳（默认配置）
- **测试环境**：可设置`WS_ENABLE_PING = False`对比测试稳定性

### 6.4 重连过程中的消息处理
1. **重连期间**：新消息发送会抛出异常，提示"正在重连中..."
2. **重连成功**：自动上报各平台连接状态
3. **重连失败**：达到最大次数后停止重连，需要手动重启GUI

### 6.5 重连日志示例
```
[重连] 检测到ping超时，这是常见的网络问题
[重连] 第1次重连尝试，等待2.0秒...
正在连接后端WebSocket: wss://shuidrop.com/ws/gui/your_token/
[重连] 后端WebSocket重连成功！(第1次尝试)
[重连] 已上报京东平台状态
[重连] 已上报抖音平台状态
```

---

## 7. Cookie 下发策略

- 抖音、拼多多：直接使用后台请求携带的 cookie（pass-through）。
- 京东、淘宝：由后端插件生成或获取（plugin），后台在店铺登录时通过本 WS 下发店铺级 `connect_success`（带 `store_id`）给 GUI。

