Files
qiji/docs/superpowers/specs/2026-07-30-visit-dedup-design.md
2026-07-30 09:55:08 +08:00

5.8 KiB
Raw Permalink Blame History

协同拜访记录去重 — 设计方案

背景

当前机制:客户经理 A 创建拜访记录并选择协同人员 B 时,后端为 B 生成一条空内容的草稿副本。B 填写后,同一客户、同一天出现两条独立拜访记录,导致周报重复展示、亮灯表重复计数。

设计目标

  1. 周报中同一客户同一次拜访合并展示为一张卡片
  2. 亮灯表不重复计数
  3. 每个参与人的填报进度不受影响(各自计入)
  4. 每个参与人能独立编辑自己的副本
  5. 历史数据兼容,不做强制迁移

方案概要

1. 数据库:新增 visit_group_id

ALTER TABLE visits ADD COLUMN visit_group_id UUID;
CREATE INDEX ix_visits_visit_group_id ON visits(visit_group_id);
  • 单人拜访:visit_group_id = NULL
  • 多人协同拜访:同一次拜访的所有记录共享同一个 visit_group_id

2. 后端:POST /visits/ 改造

原逻辑: 为每个协同人生成一条空内容草稿(communication_content="", photos=[], companions=[]

新逻辑: 为每个协同人生成一条完整副本:

副本字段 说明
customer_id 同主记录
visit_date 同主记录
visit_method 同主记录
time_range 同主记录
visitor_name 同主记录 实际拜访人不变
visitor_phone 同主记录
communication_content 原内容 + (协同XXX 如:了解项目进度...(协同韦佶秀)
customer_demand 同主记录
companions [主记录创建人] 互换:协同人看到主访人
companion_names 同主记录
photos 同主记录
manager_id 协同人的 UUID 归属到协同人名下
visit_group_id 同主记录 同一 UUID,关联所有副本

前端表现(创建人韦佶秀视角):

相关人员选择了 [韦伦]
  → 保存后韦伦收到一条完整拜访记录
  → 韦伦记录内容末尾自动追加"(协同韦佶秀)"

3. 后端:PUT /visits/{id} 不变

协同人编辑自己的副本时不影响主记录,各自独立。

4. 仪表盘统计:按 visit_group_id 去重

get_dashboard_stats 中的 week_visits 改为:

# 原:count 所有 visit 行
select count(distinct coalesce(visit_group_id, id))
from visits
where visit_date between monday and sunday

每个 visit_group_id 只算一次,跳过 NULL(单人拜访用 id 做 fallback key)。

5. 填报进度:不变

get_reporting_progressmanager_id 分组计数,每个参与人各算一次,不受去重影响。

6. 亮灯表:按 (customer_id, visit_date, visit_group_id) 去重

同一客户同一天同一次拜访只亮一盏灯。

7. 周报展示:按 visit_group_id 合并

get_weekly_report 查询时,同一个 visit_group_id 的记录合并成一条输出:

{
  "customer_name": "污水处理厂",
  "visit_date": "2026-07-30",
  "visit_method": "上门",
  "time_range": "09:00-10:30",
  "visit_group_id": "abc-123",
  "participants": [
    {
      "manager_name": "韦佶秀",
      "manager_id": "uuid-1",
      "role": "primary",
      "communication_content": "了解污水处理新项目...",
      "customer_demand": "专线扩容至100M...",
      "photos": ["photo_001", "photo_002"]
    },
    {
      "manager_name": "韦伦",
      "manager_id": "uuid-2",
      "role": "companion",
      "communication_content": "了解污水处理新项目...(协同韦佶秀)",
      "customer_demand": "专线扩容至100M...",
      "photos": ["photo_001", "photo_002"]
    }
  ]
}

前端周报卡片展示:

┌─────────────────────────────────────────────┐
│ 污水处理厂             2026-07-30  上门       │
│ 09:00-10:30                                │
│                                             │
│ ▸ 韦佶秀(主访)                              │
│   了解污水处理新项目建设进度,客户计划新增...    │
│   客户需求:专线扩容至100M,新增视频监控...     │
│   📷 2张                                    │
│                                             │
│ ▸ 韦伦(协同)                                │
│   了解污水处理新项目建设进度...(协同韦佶秀)    │
│   客户需求:专线扩容至100M...                 │
│   📷 2张                                    │
└─────────────────────────────────────────────┘

8. 前端:协同记录编辑提示

协同人打开自己的副本编辑时,沟通内容区域上方显示一行提示:

💡 此记录为协同韦佶秀拜访「污水处理厂」的副本。你可以补充或修改内容,不会影响主记录。

改动清单

文件 改动
DB migration ALTER TABLE visits ADD visit_group_id UUID
后端 models/visit.py 新增 visit_group_id 字段
后端 schemas/visit.py VisitOut 新增 visit_group_id
后端 api/visits.py POST 副本改为完整复制 + (协同XXX) 后缀 + 互换 companions + 设置 visit_group_id
后端 services/dashboard.py get_dashboard_stats 的 week_visits 改为 distinct 去重
后端 services/dashboard.py get_weekly_report 合并同 visit_group_id 记录
后端 services/light_board.py 亮灯计数去重
前端 周报 WeeklyReport.vue 拜访卡片支持 participants 展开/折叠
前端 移动端 VisitForm.vue 协同记录编辑时显示提示条

兼容性

  • 历史数据 visit_group_id = NULL,行为与现在完全一致
  • 前端 participants 字段回退:单 participant 时展示与现在无差异