Files
yunke/docs/superpowers/specs/2026-08-05-yunke-ui-alignment-design.md
T
浅念 1d815d84b9 docs: UI alignment spec + StaffList interaction plan
Spec: align all list/detail pages to 云客 (columns + interactions); covers interaction taxonomy, backend extensions (customer add_time/filters, /api/sessions), phase-0 capture. Plan 1: StaffList interaction closure + customer backend + YkStaffDetailModal.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-05 18:30:12 +08:00

11 KiB
Raw Blame History

yunkes 前端页面对齐云客后台 — 设计文档

  • 日期:2026-08-05
  • 分支:feat/yunke-data-mirror
  • 状态:待评审

背景

yunkes 是云客 CRM(crm2.yunkecn.com)数据镜像的查看后台(Vue3 + Element Plus)。当前各列表/详情页的表格列结构与交互均与云客后台(Ant Design Vue)不一致,用户在两套系统间切换认知成本高。

需将所有"有云客对应"的页面列结构 + 交互功能对齐云客。StaffList(员工列表)已于 2026-08-05 完成列结构对齐(待补交互),验证了采集与改造方法。

目标

所有有云客对应的列表/详情页:

  1. 列结构(列名、顺序、操作按钮、复合单元格字段组合)与云客一致
  2. 交互功能(可点元素 + 点击行为:跳转/modal/新 tab)与云客一致

视觉用 Element Plus 自然样式(不引入 antd,不做像素级复刻)。包含必要的后端筛选参数扩展。

范围

对齐(6 个页面 + StaffList 补交互)

页面 路由 云客对应 列对齐 交互
StaffList /staff 员工微信列表 + WhatsApp 员工列表 ✅ 已完成 本轮补
CustomerList /customers 客户列表 待做 待做
GroupList /groups 群列表/统计 待做 待做
CallList /calls 语音通话列表 待做 待做
SmsList /sms 短信记录 待做 待做
ChatTimeline /chat,/group 聊天记录(会话列表+消息流,只读查看器) 待做 待做
SearchView /search 全局搜索 待做 待做

删除

  • AccountList /accounts — 云客无此页面,且与 StaffList 内容重复。删除路由 + 文件 + 导航入口,/accounts → /staff 客户端重定向。

不动

  • SyncStatus /sync — 运维监控页,云客无对应。

列对齐设计

对齐:列名、列顺序、操作按钮(文字/位置)、复合单元格字段组合。 不对齐:antd vs el-table 像素级视觉(配色/行高/表头用 el-table 默认 + 少量 scoped 微调)。

方法(StaffList 已验证):Playwright browser_evaluate 采云客表头 + 复合单元格字段(td.innerText 按行拆分)+ 操作按钮文字 → dump smoke.db raw_json 核字段 → 改 .vue(el-table 列定义,字段经 readField 读)→ 浏览器对比 + vue-tsc。

交互对齐设计

云客列表的可点元素分三类,每类统一处理模式(已在 WhatsApp 员工表验证):

类型 1:跳转到列表页(route push)

  • 触发:操作按钮(如"好友列表""群聊")、部分可点数字
  • 行为:router.push 到目标列表页,带 query 预筛(?owner_account_id= 或 ?user_id=)
  • 目标页改动:读 route.query 的 owner/user 参数 → 传给 API 筛选 + 顶部显示"按员工 X 筛选"chip + 清除按钮
  • 云客实例:WhatsApp 员工表"好友列表"→ friendlist/0/{userId},"群聊"→ friendlist/1/{userId}
  • 后端:/api/customers、/api/groups 已支持 owner_account_id ✓;新增 user_id 筛选(云客按 userId)

类型 2:明细 modal(el-dialog)

  • 触发:统计数字(如"添加人数""沟通人数""消息数")
  • 行为:弹出 el-dialog,内嵌精简明细表格,数据按"该员工 + 该维度"筛
  • 实现:通用组件 YkStaffDetailModal(props:title / api 函数 / columns / 筛选参数),多页复用。复用 el-table + el-pagination
  • 云客实例:WhatsApp 员工表"添加人数"→ modal 列 序号/员工信息/员工WhatsApp/客户WhatsApp/添加时间/最后沟通时间
  • 后端(customer raw_json 已确认含 addTime/lastChatTime/messageCount):
    • 添加人数 → customer where owner=X AND add_time >= now-N天 → 加 add_time_since 参数(依赖新增 Customer.add_time 列,见"后端端点需求")
    • 沟通人数 → customer where owner=X AND lastChatTime >= now-N天 → 加 last_chat_since 参数
    • 其他维度(消息数/好友数等)执行时确认对应查询条件

类型 3:新 tab 聊天

  • 触发:昵称 / 账号
  • 行为:router.push(或新 tab)到 ChatTimeline /chat/:channel/:ownerId/:talkerId
  • 云客实例:WhatsApp 员工表 WA 昵称 → wschatroom/...(该账号聊天记录)
  • 后端:/api/messages 已支持 owner_account_id ✓;点昵称打开的是会话列表 + 消息流视图(已验证云客 wschatroom 即此结构,只读、无发消息),需新增 /api/sessions 聚合端点(见后端端点需求)

交互探测方法(每页执行时)

用 Playwright 探测脚本(已验证):对每行每个可点元素(button/a),点击后记录"URL 变化 / modal title / popup",每次点前回到列表页、关闭残留 modal/tab。产出该页"可点元素 → 行为类型 → 目标"映射表。

后端端点需求

端点 扩展 依据列 用途
GET /api/customers 加 user_id Customer.user_id(已有列) 按员工筛客户
GET /api/customers 加 last_chat_since Customer.last_chat_time(epoch 列) 沟通人数 modal
GET /api/customers 加 add_time_since 需新增 Customer.add_time 列(见下) 添加人数 modal
GET /api/groups 加 user_id ChatGroup.owner_user_id(参数名 user_id → 此列,注意映射) 按员工筛群
GET /api/accounts — 已支持 channel StaffList 用
GET /api/messages — 已支持 owner_account_id 昵称跳聊天 ✓
GET /api/sessions(新增) 按账号列会话:好友(customer)+群聊(group),含今日消息数 + 最近联系时间 聚合 customer/group + message(当日计数) ChatTimeline 会话列表、类型 3 昵称入口

user_id / last_chat_since:直接走现有 router 模式(Query() 参数 + conditions.append),单测覆盖。

add_time_since 需要数据模型扩展(本计划唯一 schema 变更):Customer 当前无 add_time 结构化列——addTime 仅在 raw_json 里且是字符串 "YYYY-MM-DD HH:mm:ss",无法用 col >= value 直接筛(JSON-path 查询方言相关且慢,不采用)。方案:新增 Customer.add_time 列(BigInteger ms-epoch,对齐 last_chat_time)+ Alembic 迁移 + 回填脚本(解析 raw_json.addTime 字符串 → epoch)。完成后即可走标准筛选,参照 last_chat_time 既有实现与回填方式(项目已有 surrogate 修复回填先例)。

同步层适配(关键,易漏):增量同步引擎(fetcher/ingest)抓取新 customer 时也必须解析 raw_json.addTime 填充 add_time,否则回填之后到达的增量数据该字段仍为 null。回填脚本只覆盖历史,同步层覆盖增量,两者都要做。

顺序

  1. 全量采集(plan 第 0 步,必做):对每个待做页面,用 Playwright 采云客的列结构 + 可点元素 + 交互行为,dump 对应 raw_json 核字段,产出每页"目标列 + 交互映射 + 字段覆盖"清单。把当前的外推假设变成事实,避免返工。当前仅 WhatsApp 员工表 + 聊天页结构是已采事实,其余为外推。
  2. StaffList 补交互(已采,先闭环):数字 modal + 操作跳转 + 昵称聊天 + 后端 customer 筛选参数
  3. CustomerList:列对齐 + 可点元素交互(预计含跳客户详情、消息数 modal 等)
  4. GroupList:列对齐 + 交互 + 后端 group user_id
  5. CallList + SmsList(并行):列对齐 + 交互
  6. ChatTimeline:对齐云客只读聊天查看器——左侧会话列表(好友/群聊 tab + 今日消息数 + 最近联系时间)+ 右侧消息流 + 查询/导出按钮;新增 /api/sessions 聚合端点(工作量较大,单独评估)
  7. SearchView:搜索结果布局对齐 + 交互
  8. AccountList 删除(收尾)

共性策略

  • 沿用统一模式:useChannelStore、rtl 全字段抽屉(build*Sections)、[20/50/100] 分页、row-click 开抽屉。
  • 字段读取复用各 utils/*Fields.ts 的 readField;新字段补进 *_FIELD_LABELS/*_FIELD_GROUPS。
  • 字符串时间修复:云客 addTime/lastUpdate 等是 "YYYY-MM-DD HH:mm:ss",旧代码按 number 解析显示 --;统一用 cellTimeText(字符串直显、number 才 formatTime)。StaffList 已修,其他页一并修。
  • 明细 modal 抽通用组件(YkStaffDetailModal)——多页多数字复用,值得抽(不违反 YAGNI)。
  • CallList 的 channel 是 phone_call/voice_call(通话类型),保留其 LOCAL callType 筛选。
  • 不引入云客有但后端不支持的功能(导出/查询等装饰按钮),除非单独要求。

AccountList 删除清单

  • router/index.ts:移除 /accounts 路由记录,新增 /accounts → /staff 重定向。
  • 删除 views/AccountList.vue。
  • 清理导航入口(layouts/MainLayout.vue 约 line 126 指向 /accounts 的菜单项)。
  • 更新 StaffList.vue 两处对 AccountList.vue 的注释引用(drawer 实际来自 accountFields.ts)。
  • 保留数据层:后端 GET /api/accounts(yunke-server)与前端 getAccounts()(api/index.ts,StaffList 依赖)是数据接口,不删。
  • 全仓 grep AccountList、/accounts 确认无 UI 残留引用。

验收标准

  • 每页列名/顺序/操作按钮与云客一致(截图留档)。
  • 每页可点元素的行为与云客一致(跳转目标 / modal 列 / 新 tab),探测对比留档。
  • 数据正确填充(raw_json 读字段,无整列 --)。
  • 字符串时间字段正确显示。
  • 后端新筛选参数有单测;Customer.add_time 迁移 + 回填 + 同步引擎填充完成;/api/sessions 聚合端点有单测;pytest 全绿(≥323 测试)。
  • vue-tsc -b exit 0,无 console 报错。
  • /accounts 客户端重定向到 /staff(URL 变 /staff、StaffList 渲染;非 HTTP 301)。

风险与降级

  • 字段缺口:某页云客 KPI 字段不在 raw_json → dump 确认;缺失显示 --/0,不阻塞,记入附录。
  • modal 维度查询不明:某些数字(如"消息数")对应的后端筛选条件云客未必直白 → 以云客 modal 实际返回数据为准,反推查询;无法精确复刻的,降级为跳转到对应列表页。
  • 会话列表视图(已验证需要):云客聊天页 = 会话列表 + 消息流(只读、无发消息),需新增 /api/sessions 聚合端点(好友/群聊 + 今日消息数 + 最近联系时间)。今日消息数需按 message 当日计数聚合,注意大数据量下的查询性能。
  • modal 统计窗口:员工列表统计已验证不依赖日期选择器(顶部 pickerCount=0,固定统计),但"添加人数 N"的窗口语义(最近几天/全部)仍未确认 → 执行时从 modal 明细的 addTime 范围反推;无法确认时默认取全部或最近 7 天并标注近似。
  • 采集时效:云客改版则列/交互会变 → 以采集时刻为准,spec 记录采集日期(2026-08-05)。
  • 工作量:列+交互+后端是大工程 → plan 按"页面 × 阶段"分解,每页可独立交付,不阻塞整体。