docs(spec): 4c 设计修订——补 user_real_name API 参数 + 员工姓名筛选语义/播放/scaper 文件定稿

spec review 反馈:API↔modal 员工姓名筛选对齐 + 打开语义澄清 +
channel 移出 body + scraper 文件/播放方式 pin。

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
浅念
2026-08-07 14:36:50 +08:00
parent fd33e82d62
commit 334adcb712
@@ -76,7 +76,7 @@
## 4. 抓取 + sync
- `scrape_voice_clips(client, department_id?)`:遍历本地员工表所有员工 `user_id`(微信 + WA 员工),逐员工 `POST /wechatweb/call/list` body=`{pageNum, pageSize, userId, channel-tag}`,**不传时间窗**(全量),分页至 `total`,按 `id` upsert `voice_clip`,`channel` 按该员工所属通道(wechat/whatsapp)标记。
- `scrape_voice_clips(client, department_id?)`:遍历本地员工表所有员工 `user_id`(微信 + WA 员工),逐员工 `POST /wechatweb/call/list` body=`{pageNum, pageSize, userId}`(**不传时间窗** = 该员工全量片段),分页至 `total`,按 `id` upsert `voice_clip`。`channel` 是**本地按该员工所属通道(wechat/whatsapp)打的标记,写在行上,不发给云客**。
- 复用 4a 的 `_build_voice_body` / 分页 / coerce 模式;client 走现有 `YunkeClient`。
- 员工→通道映射:复用 staff 表(`user_id` + channel 信息)。
- `sync_voice_clips(engine, ...)`:照 4a `sync_wa_voice_calls` 模式(建表/ensure + 调 scraper + `SyncRun` 记录)。
@@ -86,17 +86,19 @@
## 5. API
`GET /api/voice-clips`(新 router,镜像 `/api/calls`)
- query:`user_id?`(员工过滤,对应云客 modal 按员工开)、`start?`/`end?`(ms-epoch,录音结束时间窗)、`company_code?`(企业串码)、`page?`/`page_size?`。
- query(全可选):`user_id?`(员工精确过滤,modal 从 CallList 行打开时传,对应云客按员工开)、`user_real_name?`(员工姓名**模糊**,对应云客 modal 的「员工姓名」筛选)、`start?`/`end?`(ms-epoch,录音结束时间窗)、`company_code?`(企业串码)、`page?`/`page_size?`。
- **优先级**:`user_id` 与 `user_real_name` 同时给时,以 `user_id` 为准(更精确);只给名字则按名字模糊。
- 返回 `Page<VoiceClipOut>`(`items/total/page/page_size`)。
- 前端 `getVoiceClips({user_id, start, end, company_code, page, page_size})`。
- 前端 `getVoiceClips({user_id?, user_real_name?, start?, end?, company_code?, page, page_size})`。
## 6. 前端
**`VoiceClipModal.vue`**(新组件,只读):
- props:`userId`(打开时限定员工)、`visible` v-model。
- 顶部筛选:录音结束时间范围(el-date-picker) / 员工姓名(user_real_name 模糊) / 企业串码(company_code)。
- props:`userId`(从 CallList 行传入,精确限定员工)、`staffName?`(该员工姓名,用于筛选框预填)、`visible` v-model。
- 顶部筛选(对齐云客 modal 三筛):录音结束时间范围(el-date-picker → `start/end`) / 员工姓名(`user_real_name` 模糊,**打开时预填 `staffName`,可编辑**) / 企业串码(`company_code`)。
- 查询规则:员工姓名未改 → 传 `user_id`(精确);用户改了员工姓名 → 改传 `user_real_name`(模糊,可跨员工搜,镜像云客)。
- 表格列(对齐云客 modal):员工姓名 / 企业串码 / 文件地址(截断 + tooltip 全 URL)/ 录音开始时间 / 录音结束时间 / 录音时长(duration_format)/ 操作(播放)。
- 播放:复用 CallList 的录音播放 dialog 思路(audio + `oss_file_name`);或 modal 内联 audio。
- 播放:**modal 内内联 `<audio controls src=oss_file_name>`**(只读最简,不另开 dialog;src 用 OSS URL,见 §7.3)。
- 底部:关闭(**无「确定」/「匹配」**)。
- 数据:`getVoiceClips({user_id: userId, start, end, company_code, page, page_size})`。
@@ -126,7 +128,7 @@
- 新 `app/db/models.py`:`VoiceClip` 模型
- 新 `app/api/schemas.py`:`VoiceClipOut`
- 新 `app/api/routers/voice_clips.py`:`/api/voice-clips`
- 新 `app/scraper/voice_clip.py`(或并入 `call.py`):`scrape_voice_clips`
- 新 `app/scraper/voice_clip.py`(独立文件,照 `whatsapp.py`/`call.py` 模式):`scrape_voice_clips`
- 新 `app/sync/...`:`sync_voice_clips` + scheduler ENTITY_FUNC
- 新 Alembic 迁移
- 新测试 + cassette fixture