架构与实现
卓安Claw 预约排期 v1.0
日期:2026-11-13
状态:接诊/会见/电话/回访排期、冲突校验、状态流转已落地;企微提醒待接
关联:卓安Claw-分诊承办分配-v1.0.md、卓安Claw-任务链-v1.0.md
0. 一句话
预约不是日历展示,而是把“接诊、会见、电话、回访”变成可排期、可确认、可追责的时间承诺;同一负责人的时间段不允许重叠。
1. 数据模型
新增 zhuoan_appointment:
| 字段 | 说明 |
|---|---|
id |
UUID |
case_id |
关联案件;V1 必填 |
intake_id |
预留:线索/建档阶段预约,尚不启用 |
title |
预约标题 |
type |
接诊 / 会见 / 电话 / 回访 / 会议 / 其他 |
starts_at / ends_at |
YYYY-MM-DD HH:MM,结束时间默认开始 + 1 小时 |
location |
地点或“电话” |
owner_user_id / owner_name |
负责人(承办/谈案/客服) |
status |
待确认 / 已确认 / 已完成 / 已取消 |
notes |
会见提纲、需带材料、注意事项 |
created_by / created_at / updated_at |
操作人与时间 |
索引:
(starts_at, status):按时间查排期。(owner_user_id, starts_at):按负责人查冲突。
预约不复制案卷内容,只存时间、参与人和必要说明。
2. 状态机与冲突规则
待确认 ──确认──> 已确认 ──完成──> 已完成
│ │
└──────取消───────┴──────> 已取消
- 只有“待确认”可以确认。
- “待确认/已确认”可以完成。
- “已完成”不能取消;“已取消”不再参与冲突判断。
- 冲突规则:同一
owner_user_id,existing.starts_at < new.ends_at且existing.ends_at > new.starts_at即冲突。 - 首尾相接不算冲突(例如 14:00–15:00 与 15:00–16:00)。
- V1 只校验负责人时间,不校验会议室、车辆等资源。
3. API
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/zhuoan/appointments?from=&to=&case_id= |
当前数据范围内的预约,按开始时间升序;返回 items 与 summary |
| POST | /api/zhuoan/appointments |
创建预约;case_id、title、starts_at 必填;冲突返回 400 |
| PATCH | /api/zhuoan/appointments/<id> |
action=confirm|complete|cancel|patch;patch 支持改标题/类型/时间/地点/备注 |
summary 字段:total / today / week / by_status。week 指今天起未来 7 天,不含已取消。
权限:
- 读取:
case:view或customer:view。 - 创建/操作:
case:edit或customer:view,并校验案件数据范围。 - 客服可看客户/预约但没有案卷权限;案件正文仍由
case:file控制。 - 所有创建/确认/完成/取消/改期写审计(
zhuoan_appointment_*)。
4. UI
侧栏「客户与线索 → 预约」:
- 指标:今日预约、未来 7 天、待确认、已完成。
- 筛选:全部 / 今天 / 本周 / 待确认。
- 按日期分组;每条显示时间段、类型、标题、案件、地点、负责人、备注、状态。
- 操作:确认 / 改期 / 完成 / 取消 / 跳转案件。
- 新建/改期弹窗:案件、标题、类型、负责人、开始/结束、地点、备注。
- 负责人下拉来自账号库(
/api/zhuoan/tasks/members);改期不允许换案件/负责人,避免绕过冲突校验。
页面头部从“模块名 + 模块名”改成“导航组 + 页面名”,例如「客户与线索 / 预约」。
5. Agent 与案件上下文
build_case_context注入“近期预约”(最多 4 条):时间、类型、标题、负责人、状态。zhuoan_case(method=context)返回appointments(最多 5 条,已取消不返回)。- Agent 只读展示,不直接改预约;改期/确认仍由律师在页面操作并写审计。
6. 演示数据
首次启动种子 6 条:
- 昨天 16:00 已完成:王某故意伤害案庭前辅导(陈默)。
- 今天 14:00 待确认:刘某危险驾驶案首次接诊(周婷)。
- 明天 09:30 已确认:张某合同诈骗案会见(李然)。
- 明天 14:00 待确认:建设工程案服务方案沟通(周婷)。
- +2 天 10:00 已确认:复购客户回访(赵敏)。
- +3 天 15:00 待确认:归档后回访(赵敏)。
种子只在表为空时写入,不覆盖真实数据。
7. 验证
- API:6 条种子;今日 1、未来 7 天 5、待确认 3、已完成 1。
- 冲突:同负责人 14:30–15:30 撞 14:00–15:00 → 400「时间冲突」。
- 创建:非重叠时段 → 201,状态待确认。
- 状态:确认 200 → 完成 200 → 对已完成取消 400。
- Playwright 1920×1080:6 条预约、4 个筛选、新建弹窗、确认后待确认数下降,0 console error。
- 截图(临时):
C:\tmp\appointments-final.png。
8. 边界与未做
- 预约必须关联案件;线索阶段预约尚未开放(
intake_id已预留)。 - 企微/站内提醒未接;V1 只做排期与状态,不自动发消息。
- 没有周/日日历视图、拖拽改期、重复预约。
- 没有 resource(会议室/车辆)冲突、跨分所时区处理。
- 客户经理/客服的数据范围若为“本人”,只能看到自己负责案件的预约;跨角色预约可见性后续按组织架构细化。
9. 下一步
- 接提醒 worker:开始前 30/15 分钟推送企微/站内,失败可重试。
- 开放线索阶段预约:
intake_id+ 客户手机号,转案后自动带出。 - 预约与任务联动:会见预约自动生成“会见准备”任务,完成后回写。
- 日历视图与拖拽改期(拖拽仍走同一冲突校验)。
- 爽约/改期统计,进入律师评定与客户体验指标。