docs(spec): 二次审计修订8项(微信群表列真机结构/统计明细分tab列型/phone_call userId转换坑/类型归一化回填任务/通讯录批量操作/msgid定位/chat_group补列/左栏折叠)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
浅念
2026-08-25 12:10:16 +08:00
parent 2d93f31be7
commit 00180ef479
@@ -19,6 +19,7 @@
| 删除聊天记录按钮 | **不复刻**(镜像数据删了只有重扫能找回) |
| 敏感词统计 | tab 占位空态(待 C1 敏感词功能接入,见 2026-08-24 数据分析方案) |
| 实现方案 | 方案 A:独立新页 `StaffChat.vue`,组件拆分,旧页不动 |
| 二次审计修订(同日) | 8 项全部修订:微信群表列改真机结构、统计明细按 tab 分型、语音通话复用 CallList 列、phone_call userId 转换写明、消息类型归一化+回填任务、通讯录批量操作、红包转账 msgid 定位、chat_group 补列(raw_json 提取)、左栏折叠 |
## 2. 云客真机事实(对齐依据)
@@ -50,7 +51,7 @@
| 朋友圈 | `POST /wechatweb/wechatFriendster/getFriendsterInfo` form | `startTime/endTime(空), pageNum, pageSize=10, wechatId`;行:`id/snsId/friendsterName/friendsterWXIdImg/content/createTime(秒)/type(1图文/28纯文字)/praise[]{name,praiseImg}/comment[]/imgUrlsList[](OSS URL)/praiseNum`;头部 `saleNickName/headImageUrl/saleAlias/bgImg`;`hashNext` 翻页 |
| 通讯录 | `POST /wechatweb/wxFriends/friend_list/es` | 即逐员工客户列表(已抓过);表格列:客户微信(昵称+微信号)/数据来源/客户备注名/最近沟通时间/发送条数/接收条数/操作(查看聊天记录+导出HTML聊天记录) |
| 统计计数 | `POST /wechatweb/wechatcount/getSaleWechatIdInfoCount` | `{addFriend, addGroup, redAndTrans, sensitiveCount, delFriend, blackFriend, weChatVoiceCount}` |
| 统计明细 | `POST /wechatweb/wxFriends/getAddFriendOrGroup` form | `pageNum, pageSize, friendTypeYunke=1, wechatId, startdate, enddate`;行:客户微信(可点→聊天)/客户备注/员工微信/时间 |
| 统计明细 | `POST /wechatweb/wxFriends/getAddFriendOrGroup` form | `pageNum, pageSize, friendTypeYunke=1, wechatId, startdate, enddate`;**各 tab 明细列不同(真机逐 tab 验证)**:新客户=客户微信(可点)/客户备注/员工微信/时间;红包转账=操作类型/客户微信/员工微信/金额/发生时间/操作(查看聊天记录**带 msgid 定位消息**);新的群=微信群信息/员工微信/时间;删除客户=客户微信/员工微信/发生时间;语音通话=复选框/通话人/通话类型/来源/呼入呼出/接通状态/通话录音/通话时间/操作(9 列,与 CallList 同构) |
其他 UI 事实:
- 右列默认日期窗**近 14 天**(`今日00:00-14天 ~ 今日23:59:59`),统计视图默认**近 7 天**
@@ -59,15 +60,20 @@
- 置顶区含文件传输助手,可「折叠置顶聊天」
- 已删除好友 tab 存在(实测 3 条老好友,最近联系时间可显示到 2025 年)
- 资料卡 cursor=pointer 但点击无可见行为(不复刻点击)
- **通讯录·微信群 tab 列(真机验证)**:复选框/群信息/数据来源/群主信息(昵称+微信号)/群成员数量/群成员好友数量/消息数量/操作(查看聊天记录→群聊消息+导出HTML聊天记录);搜索框仅「请输入群名称」
- **通讯录批量操作**:客户表/群表都有全选复选框 + 顶部「查询/导出/导出聊天记录(勾选后可批量)」
- 左栏有「收起菜单」「收起侧边栏」折叠按钮
- 云客全站昵称脱敏(A**2),我们不脱敏(镜像惯例,有意差异)
## 3. 架构(方案 A)
```
路由: /staff-chat/:ownerId/:tab(single|group|moments|contacts|stats)/:talkerId?
默认 tab=single;talkerId 可空(账号级入口)
tab=group 时 talkerId 语义为 roomId;红包转账明细跳转带 ?msgid= 定位消息
StaffChat.vue (页面骨架)
├── StaffChatSide.vue 左栏: 员工资料卡 + 5 导航按钮
├── StaffChatSide.vue 左栏: 员工资料卡 + 5 导航按钮 + 收起/展开(对齐云客「收起侧边栏」)
├── tab=single|group → SessionPane.vue (中列) + ChatMain.vue (右列)
├── tab=moments → MomentsPane.vue
├── tab=contacts → ContactsPane.vue
@@ -101,6 +107,18 @@ StaffChat.vue (页面骨架)
- 接入 `scrape_via_page.py` 实体注册、`full_sync_all.sh` 加一步、调度 4h 增量(水位=本地 max(create_time),仅扫有新朋友圈的员工——云客接口无 per-员工增量标记,简化为全量浅扫第一页有新才继续)
- 图片接入现有 media 本地化批处理(OSS URL 型)
### 4.2b `chat_group` 补列(通讯录·微信群 tab 数据,从 raw_json 提取)
真机验证云客群表需要:群主信息/群成员好友数量/消息数量。`raw_json` 已有这些键(ownerName/ownerWchatId/ownerAlias/ownerImage/friendCount/createTime),加实体列避免每行解析 JSON:
| 新列 | 来源 raw_json 键 | 说明 |
|---|---|---|
| owner_name / owner_wxid / owner_alias / owner_avatar | ownerName/ownerWchatId/ownerAlias/ownerImage | 群主信息(上游脱敏,如实存) |
| friend_count | friendCount | 群成员中该员工好友数 |
| create_time | createTime | 建群时间(ms,统计·新的群 tab 用) |
一次性迁移脚本回填存量(幂等,复用 migrate 惯例),scraper upsert 持续写入。
### 4.3 API 改动
| API | 改动 |
@@ -109,18 +127,24 @@ StaffChat.vue (页面骨架)
| `GET /api/sessions` | + `is_del` 参数(join `customer.delete_flag`,NULL 视为 0);行 + `pinned`(`talker_id='filehelper'`) |
| `GET /api/moments` 新 | `?wechat_id=&page=&page_size=` 帖子 desc + 头部 `{nickname, avatar, alias}`(头部取自 `wechat_account` 表/nick_name + `raw_json.headImageUrl`,不在 moments_post 存) |
| `GET /api/staff-stats` 新 | `?wechat_id=&start=&end=` 计数;`&kind=` 明细行(**除敏感词外全部 tab 都出明细行**,本地表聚合) |
| `GET /api/messages` | + `msg_type` 过滤 + `q` 全文关键词(聊天记录模式用)。**msg_type→本地 type_raw 映射在 plan 第一阶段从 message 表实数据推导并记录**(如 语音消息/语音通话/视频通话 需不同 raw 签名,47/50/类型分布待实测) |
| `GET /api/messages` | + `msg_type` 过滤 + `q` 全文关键词(聊天记录模式用)。**msg_type→本地 type_raw 映射需先补全归一化**(见 4.5) |
### 4.4 统计口径(现有表本地聚合)
### 4.4 消息类型归一化补全 + 存量回填(10 类过滤的数据前提)
本地实测 wechat 渠道 `type` 仅 4 种(text/image/image_legacy/unknown),**unknown 约 13 万行**:type_raw 21=31859(链接)、15=18393、9=9023、10/4/18/8/6/22/13/14/5/11/20 各数千数百、49=202(红包转账);语音消息(34)未出现。10 类下拉中 语音/视频/文件/小程序名片 4 类现状过滤必为 0。
任务:扩展 `scripts/_normalize_msg_type` 映射(21→link、49 拆红包/转账按 paymsgid/appmsg type、15/18→视频/语音通话候选——**具体语义在 plan 第一阶段用 raw_json 样本逐一判别**),跑存量回填(2026-08-20 type=2 回填先例,幂等可重跑)。回填后 10 类过滤才有真实数据。
### 4.5 统计口径(现有表本地聚合)
| tab | 口径 |
|---|---|
| 新的客户 | `customer.add_time` 窗内(实测 62% 有值);缺失兜底=该对话首条消息时间 |
| 新的群 | `chat_group` 建群时间(无则跳过该 tab 计数,显示现存量) |
| 红包转账 | `message.type_raw=49 AND (raw_json.paymsgid 非空 OR text 含 appmsg type 2001/2000)`,合并一类;明细金额从 XML `<feedesc>` 提取,失败显 `—` |
| 新的群 | `chat_group.create_time` 窗内(新列,从 raw_json.createTime 回填;无值行不计入) |
| 红包转账 | `message.type_raw=49 AND (raw_json.paymsgid 非空 OR text 含 appmsg type 2001/2000)`,合并一类;明细金额从 XML `<feedesc>` 提取,失败显 `—`(云客本条金额也显 `-`) |
| 删除客户 | `customer.delete_flag=1`(实测 53 行;无时间字段→计数=现存量,时间列显最近 updated) |
| 拉黑客户 | `customer.is_block=1`(实测 8 行,同上) |
| 语音通话 | `phone_call.user_id=员工 AND start_call_time 窗内` |
| 语音通话 | **`phone_call.user_id` 存的是员工 userId(32位HEX) 非 wxId(实测确认)**——必须先 `wechat_account.user_id` join 转换再查,直接用 wxId 查会 0 行;`channel='voice_call' AND start_call_time 窗内` |
| 敏感词 | 占位空态「词库未配置,待 C1 敏感词功能接入」 |
## 5. 各视图细节(对齐云客)
@@ -139,14 +163,20 @@ StaffChat.vue (页面骨架)
- 滚动翻页;空态提示先跑 moments 抓取;缺图占位框
### 通讯录
- `微信客户|微信群` tab + 搜索(昵称/微信号/备注/手机号)
- 客户表 7 列:客户微信(头像+昵称+微信号)/数据来源/客户备注名/最近沟通时间/发送条数/接收条数/操作(查看聊天记录+导出HTML聊天记录)
- 微信群 tab:群名/群主/成员数/最近群消息时间/查看群聊
- 复用 `/api/customers`、`/api/groups`(owner 过滤已支持)
- `微信客户|微信群` tab + 搜索框(客户 tab:昵称/微信号/备注/手机号;群 tab:仅群名称)
- 客户表 7 列:复选框/客户微信(头像+昵称+微信号)/数据来源/客户备注名/最近沟通时间/发送条数/接收条数/操作(查看聊天记录+导出HTML聊天记录)
- **微信群表 8 列(真机)**:复选框/群信息(群名)/数据来源/群主信息(昵称+微信号,raw_json 提取)/群成员数量/群成员好友数量(friend_count)/消息数量/操作(查看聊天记录→群聊消息+导出HTML聊天记录)
- **批量操作**:全选复选框 + 顶部「查询/导出(CSV)/导出聊天记录(勾选后批量导出 HTML,串行调 /export/chat-html)」
- 复用 `/api/customers`、`/api/groups`(owner 过滤已支持;groups 补 owner 精确+新列输出)
### 统计分析
- 7 tab 带计数徽标,默认近 7 天窗
- 明细 4 列:客户微信(可点→聊天)/客户备注/员工微信/时间
- **明细列按 tab 分型(配置驱动 cols,真机验证)**:
- 新的客户:客户微信(可点→聊天)/客户备注/员工微信/时间
- 红包转账:操作类型(红包/转账)/客户微信(可点)/员工微信/金额/发生时间/操作(查看聊天记录**带 msgid 定位滚动到该消息**)
- 新的群:微信群信息(可点→群聊)/员工微信/时间
- 删除/拉黑客户:客户微信/员工微信/发生时间
- 语音通话:**复用 CallList 列定义**(通话人/通话类型/来源/呼入呼出/接通状态/通话录音/通话时间/操作)
- 敏感词空态占位
## 6. 错误处理
@@ -164,8 +194,8 @@ StaffChat.vue (页面骨架)
## 8. 实施顺序
1. 后端:表+scraper → API(accounts/sessions/messages 改动,moments/staff-stats 新增)
2. 前端骨架:路由+左栏+单聊视图
3. 群聊/通讯录/统计分析视图
1. 后端:moments 表+scraper → chat_group 补列+回填 → 消息类型归一化映射判别+存量回填 → API(accounts/sessions/messages/groups 改动,moments/staff-stats 新增)
2. 前端骨架:路由+左栏+单聊视图(含 msgid 定位消息能力)
3. 群聊/通讯录(客户表+群表+批量操作)/统计分析(分型明细)视图
4. 朋友圈视图
5. 入口改造 + 走查 + 提交
5. 入口改造 + Playwright 走查 5 视图对照云客 + 提交