279 lines
30 KiB
Markdown
279 lines
30 KiB
Markdown
# 需求文档:小程序核心业务模块(miniapp-core-business)
|
||
|
||
## 简介
|
||
|
||
本 SPEC 实现小程序的核心业务逻辑,涵盖助教任务系统(生成、分配、状态流转、完成检测)、备注系统(CRUD、星星评分、类型区分)、以及后台触发器/轮询调度框架。系统基于 P1(miniapp-db-foundation)的数据库基础设施、P2(etl-dws-miniapp-extensions)的 DWS 指数数据、P3(miniapp-auth-system)的用户认证体系,在 `test_zqyy_app.biz` Schema 中创建任务、备注、触发器等业务表,并在 FastAPI 后端实现对应的 API 端点和后台调度逻辑。
|
||
|
||
## 术语表
|
||
|
||
- **Task_Generator**:任务生成器,每日 4:00 后运行,基于 WBI/NCI/RS 指数为每个助教分配 4 种类型任务的后台服务
|
||
- **Task_Manager**:任务管理服务,负责任务 CRUD、置顶、放弃、状态流转的后端模块
|
||
- **Task_Expiry_Checker**:任务有效期轮询器,每小时检查 `expires_at` 并将过期任务标记为无效
|
||
- **Recall_Completion_Detector**:召回完成检测器,ETL 数据更新后检查助教是否为匹配客户提供了服务
|
||
- **Note_Reclassifier**:备注回溯重分类器,召回完成时回溯检查是否有普通备注需重分类为回访备注
|
||
- **Note_Service**:备注服务模块,负责备注 CRUD、星星评分存储与读取
|
||
- **Trigger_Scheduler**:触发器调度框架,支持 cron/interval/event 三种触发方式的统一调度引擎
|
||
- **coach_tasks**:助教任务表,位于 `biz` Schema,存储任务分配、状态、有效期等信息
|
||
- **coach_task_history**:任务变更历史表,记录任务关闭/新建的追溯链
|
||
- **notes**:统一备注表,位于 `biz` Schema,通过 `type` 字段区分普通备注/回访备注/放弃原因
|
||
- **trigger_jobs**:触发器配置表,位于 `biz` Schema,存储轮询/事件触发器的配置与执行状态
|
||
- **task_type**:任务类型枚举,取值为 `high_priority_recall`(高优先召回)/ `priority_recall`(优先召回)/ `follow_up_visit`(客户回访)/ `relationship_building`(关系构建)
|
||
- **task_status**:任务状态枚举,取值为 `active`(有效)/ `inactive`(无效)/ `completed`(已完成)/ `abandoned`(已放弃)
|
||
- **note_type**:备注类型枚举,取值为 `normal`(普通备注)/ `follow_up`(回访备注)/ `abandon_reason`(放弃原因)
|
||
- **priority_score**:优先级分数,取 `max(WBI, NCI)` 的快照值,用于任务排序
|
||
- **expires_at**:有效期时间戳,默认 NULL(无限期),填充后表示任务将在该时间点过期
|
||
- **FDW**:`postgres_fdw` 外部数据包装器,通过 `fdw_etl` Schema 读取 ETL 库指数数据
|
||
- **Migration_Script**:存放在 `db/zqyy_app/migrations/` 中的纯 SQL 迁移脚本,以日期前缀命名
|
||
- **site_id**:门店标识符,类型为 `BIGINT`,用于多门店数据隔离
|
||
- **member_retention_clue**:维客线索表,位于 `public` Schema,存储助教为客户记录的维护线索(大类 + 摘要 + 详情),独立于 ETL 数据。当前已有基础表结构和 CRUD API(`/api/retention-clue`),若不足以支撑本 SPEC 的任务系统需求,可对其 DDL、Pydantic 模型及路由进行扩展或修改
|
||
|
||
## 需求
|
||
|
||
### 需求 1:业务数据表创建
|
||
|
||
**用户故事:** 作为后端开发者,我需要在 `biz` Schema 中创建任务、备注、触发器等业务表,以便支撑核心业务功能。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN Migration_Script 执行完成, THE Task_Manager SHALL 在 `biz` Schema 中创建 `coach_tasks` 表,包含 `id`(BIGSERIAL PK)、`site_id`(BIGINT NOT NULL)、`assistant_id`(BIGINT NOT NULL)、`member_id`(BIGINT NOT NULL)、`task_type`(VARCHAR NOT NULL)、`status`(VARCHAR NOT NULL DEFAULT 'active')、`priority_score`(NUMERIC(5,2))、`expires_at`(TIMESTAMPTZ,可空)、`is_pinned`(BOOLEAN DEFAULT FALSE)、`abandon_reason`(TEXT,可空)、`completed_at`(TIMESTAMPTZ,可空)、`completed_task_type`(VARCHAR,可空)、`parent_task_id`(BIGINT,可空,FK → coach_tasks)、`created_at`(TIMESTAMPTZ DEFAULT NOW())、`updated_at`(TIMESTAMPTZ DEFAULT NOW())字段
|
||
2. WHEN Migration_Script 执行完成, THE Task_Manager SHALL 在 `biz` Schema 中创建 `coach_task_history` 表,包含 `id`(BIGSERIAL PK)、`task_id`(BIGINT FK → coach_tasks)、`action`(VARCHAR NOT NULL)、`old_status`(VARCHAR)、`new_status`(VARCHAR)、`old_task_type`(VARCHAR)、`new_task_type`(VARCHAR)、`detail`(JSONB)、`created_at`(TIMESTAMPTZ DEFAULT NOW())字段
|
||
3. WHEN Migration_Script 执行完成, THE Note_Service SHALL 在 `biz` Schema 中创建 `notes` 表,包含 `id`(BIGSERIAL PK)、`site_id`(BIGINT NOT NULL)、`user_id`(INTEGER NOT NULL)、`target_type`(VARCHAR NOT NULL)、`target_id`(BIGINT NOT NULL)、`type`(VARCHAR NOT NULL DEFAULT 'normal')、`content`(TEXT NOT NULL)、`rating_service_willingness`(SMALLINT,可空,CHECK 1-5)、`rating_revisit_likelihood`(SMALLINT,可空,CHECK 1-5)、`task_id`(BIGINT,可空,FK → coach_tasks)、`ai_score`(SMALLINT,可空)、`ai_analysis`(TEXT,可空)、`created_at`(TIMESTAMPTZ DEFAULT NOW())、`updated_at`(TIMESTAMPTZ DEFAULT NOW())字段
|
||
4. WHEN Migration_Script 执行完成, THE Trigger_Scheduler SHALL 在 `biz` Schema 中创建 `trigger_jobs` 表,包含 `id`(SERIAL PK)、`job_type`(VARCHAR NOT NULL)、`job_name`(VARCHAR NOT NULL UNIQUE)、`trigger_condition`(VARCHAR NOT NULL)、`trigger_config`(JSONB NOT NULL)、`last_run_at`(TIMESTAMPTZ,可空)、`next_run_at`(TIMESTAMPTZ,可空)、`status`(VARCHAR NOT NULL DEFAULT 'enabled')、`created_at`(TIMESTAMPTZ DEFAULT NOW())字段
|
||
5. THE Migration_Script SHALL 对 `coach_tasks` 表创建唯一索引 `idx_coach_tasks_site_assistant_member_type` 在 `(site_id, assistant_id, member_id, task_type)` 上,仅对 `status = 'active'` 的记录生效(部分唯一索引)
|
||
6. THE Migration_Script SHALL 对 `coach_tasks` 表创建索引 `idx_coach_tasks_assistant_status` 在 `(site_id, assistant_id, status)` 上,用于助教任务列表查询
|
||
7. THE Migration_Script SHALL 对 `notes` 表创建索引 `idx_notes_target` 在 `(site_id, target_type, target_id)` 上,用于按目标查询备注
|
||
8. THE Migration_Script SHALL 使用 `IF NOT EXISTS` 幂等语法,确保重复执行不会报错
|
||
9. THE Migration_Script SHALL 在脚本中包含回滚语句(以注释形式)
|
||
|
||
### 需求 2:触发器种子数据预置
|
||
|
||
**用户故事:** 作为系统管理员,我需要系统预置核心触发器配置,以便后台调度任务自动运行。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN 种子数据脚本执行完成, THE Trigger_Scheduler SHALL 在 `biz.trigger_jobs` 表中插入 `task_generator` 记录(trigger_condition='cron',trigger_config 包含 cron 表达式 '0 4 * * *')
|
||
2. WHEN 种子数据脚本执行完成, THE Trigger_Scheduler SHALL 在 `biz.trigger_jobs` 表中插入 `task_expiry_check` 记录(trigger_condition='interval',trigger_config 包含间隔秒数 3600)
|
||
3. WHEN 种子数据脚本执行完成, THE Trigger_Scheduler SHALL 在 `biz.trigger_jobs` 表中插入 `recall_completion_check` 记录(trigger_condition='event',trigger_config 包含事件名 'etl_data_updated')
|
||
4. WHEN 种子数据脚本执行完成, THE Trigger_Scheduler SHALL 在 `biz.trigger_jobs` 表中插入 `note_reclassify_backfill` 记录(trigger_condition='event',trigger_config 包含事件名 'recall_completed')
|
||
5. THE 种子数据脚本 SHALL 使用 `ON CONFLICT (job_name) DO NOTHING` 语法,确保重复执行不会产生重复数据
|
||
|
||
### 需求 3:任务生成器
|
||
|
||
**用户故事:** 作为助教,我每天打开小程序能看到系统为我分配的任务列表,按优先级排序。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN Task_Generator 运行时, THE Task_Generator SHALL 通过 FDW 读取 `fdw_etl` 中的 `dws_member_winback_index`(WBI)和 `dws_member_newconv_index`(NCI)指数数据,计算 `priority_score = max(WBI, NCI)`
|
||
2. WHEN `priority_score > 7`, THE Task_Generator SHALL 为该客户-助教对生成 `high_priority_recall`(高优先召回)类型任务
|
||
3. WHEN `priority_score > 5` 且 `priority_score <= 7`, THE Task_Generator SHALL 为该客户-助教对生成 `priority_recall`(优先召回)类型任务
|
||
4. WHEN 助教完成某客户的召回任务后该客户无回访备注, THE Task_Generator SHALL 为该客户-助教对生成 `follow_up_visit`(客户回访)类型任务
|
||
5. WHEN 客户-助教对的 RS 指数 < 6(通过 FDW 读取 `dws_member_assistant_relation_index`), THE Task_Generator SHALL 为该客户-助教对生成 `relationship_building`(关系构建)类型任务
|
||
6. WHEN Task_Generator 生成任务时发现已存在相同 `(site_id, assistant_id, member_id, task_type)` 且 `status = 'active'` 的任务, THE Task_Generator SHALL 跳过该任务不做任何操作
|
||
7. WHEN Task_Generator 生成任务时发现已存在相同 `(site_id, assistant_id, member_id)` 但 `task_type` 不同且 `status = 'active'` 的任务, THE Task_Generator SHALL 将旧任务状态设为 `inactive`,创建新任务,并在 `coach_task_history` 中记录变更
|
||
8. THE Task_Generator SHALL 按优先级从高到低的顺序处理任务类型:`high_priority_recall`(0)> `priority_recall`(0)> `follow_up_visit`(1)> `relationship_building`(2),高优先级任务覆盖低优先级任务
|
||
9. THE Task_Generator SHALL 通过 `auth.user_assistant_binding` 确定助教与小程序用户的映射关系,仅为已绑定的助教生成任务
|
||
10. THE Task_Generator SHALL 在 `trigger_jobs` 中更新 `last_run_at` 和 `next_run_at` 时间戳
|
||
|
||
### 需求 4:48 小时回访滞留机制
|
||
|
||
**用户故事:** 作为系统,回访任务至少保留 48 小时,到期后自动失效。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN Task_Generator 生成 `follow_up_visit` 类型任务时, THE Task_Generator SHALL 将 `expires_at` 设为 NULL(无限期有效),`status` 设为 `active`
|
||
2. WHEN Task_Generator 检测到某 `follow_up_visit` 任务的触发条件不再满足(指数变化), THE Task_Generator SHALL 将该任务的 `expires_at` 填充为 `created_at + 48 小时`,`status` 保持 `active`
|
||
3. WHEN Task_Expiry_Checker 轮询检查时发现某任务的 `expires_at` 不为 NULL 且当前时间超过 `expires_at`, THE Task_Expiry_Checker SHALL 将该任务 `status` 设为 `inactive`
|
||
4. WHEN 新的 `follow_up_visit` 任务生成时发现同一 `(site_id, assistant_id, member_id)` 已存在一个有 `expires_at` 的 `follow_up_visit` 任务, THE Task_Generator SHALL 将旧任务标记为 `inactive`,创建新的 `active` 任务(`expires_at` 为 NULL)
|
||
5. THE Task_Expiry_Checker SHALL 每小时运行一次,由 `trigger_jobs` 中的 `task_expiry_check` 配置驱动
|
||
|
||
### 需求 5:任务类型变更与状态流转
|
||
|
||
**用户故事:** 作为系统,当客户指数变化导致任务类型变更时,系统正确关闭旧任务并创建新任务。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN 任务类型从 `priority_recall` 变更为 `high_priority_recall`, THE Task_Generator SHALL 将旧 `priority_recall` 任务标记为 `inactive`(`expires_at` 保持 NULL),创建新的 `high_priority_recall` 任务
|
||
2. WHEN 任务类型从 `follow_up_visit` 变更为 `high_priority_recall` 或 `priority_recall`, THE Task_Generator SHALL 将旧 `follow_up_visit` 任务标记为 `active` 并填充 `expires_at = created_at + 48 小时`,创建新的召回任务
|
||
3. WHEN 任务类型从召回类型变回 `follow_up_visit`, THE Task_Generator SHALL 检查是否存在有 `expires_at` 的旧 `follow_up_visit` 任务,若存在则将旧任务标记为 `inactive`,创建新的 `follow_up_visit` 任务
|
||
4. THE Task_Manager SHALL 在每次状态变更时在 `coach_task_history` 中记录 `action`、`old_status`、`new_status`、`old_task_type`、`new_task_type`
|
||
|
||
### 需求 6:召回完成检测
|
||
|
||
**用户故事:** 作为助教,我完成召回任务后(客户到店被服务),系统自动标记任务完成。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN ETL 数据更新后, THE Recall_Completion_Detector SHALL 通过 FDW 读取 `fdw_etl.dwd_assistant_service_log` 中的新增服务记录
|
||
2. WHEN 发现某助教为某客户提供了服务, THE Recall_Completion_Detector SHALL 查找该 `(site_id, assistant_id, member_id)` 下所有 `status = 'active'` 的任务
|
||
3. WHEN 匹配到活跃任务, THE Recall_Completion_Detector SHALL 将任务 `status` 设为 `completed`,记录 `completed_at` 为服务时间,记录 `completed_task_type` 为完成时的任务类型
|
||
4. WHEN 召回完成后, THE Recall_Completion_Detector SHALL 触发 `note_reclassify_backfill` 事件,通知 Note_Reclassifier 执行备注回溯
|
||
5. THE Recall_Completion_Detector SHALL 由 `trigger_jobs` 中的 `recall_completion_check` 配置驱动,在 ETL 数据更新事件后触发
|
||
|
||
### 需求 7:备注回溯重分类
|
||
|
||
**用户故事:** 作为系统,当 ETL 数据延迟导致召回完成晚于备注提交时,需要回溯重分类备注。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN 召回完成事件触发后, THE Note_Reclassifier SHALL 查找该 `(site_id, assistant_id, member_id)` 在召回服务结束时间之后提交的第一条 `type = 'normal'` 的备注
|
||
2. WHEN 找到符合条件的普通备注, THE Note_Reclassifier SHALL 将该备注的 `type` 从 `normal` 更新为 `follow_up`
|
||
3. WHEN 备注重分类完成后, THE Note_Reclassifier SHALL 触发 AI 应用 6 对该备注进行含金量评分(评分逻辑由 P5 AI 集成层实现,本 SPEC 仅定义触发接口)
|
||
4. WHEN AI 应用 6 返回评分 >= 6, THE Note_Reclassifier SHALL 生成一条 `follow_up_visit` 任务并标记为 `completed`(回溯完成)
|
||
5. WHEN AI 应用 6 返回评分 < 6, THE Note_Reclassifier SHALL 生成一条 `follow_up_visit` 任务,`status` 为 `active`(回访未完成,需助教重新备注)
|
||
|
||
### 需求 8:任务 CRUD API
|
||
|
||
**用户故事:** 作为助教,我可以查看任务列表、置顶/放弃任务、取消置顶/取消放弃。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN 助教请求任务列表, THE Task_Manager SHALL 返回该助教在当前 `site_id` 下所有 `status = 'active'` 的任务,按 `is_pinned DESC, priority_score DESC, created_at ASC` 排序
|
||
2. WHEN 助教请求任务列表, THE Task_Manager SHALL 在每条任务中包含客户基本信息(通过 FDW 读取 `dim_member`)、RS 指数(通过 FDW 读取 `dws_member_assistant_relation_index`)、爱心 icon 档位(💖>8.5 / 🧡>7 / 💛>5 / 💙<5)
|
||
3. WHEN 助教置顶某任务, THE Task_Manager SHALL 将该任务的 `is_pinned` 设为 TRUE,并在 `coach_task_history` 中记录
|
||
4. WHEN 助教放弃某任务, THE Task_Manager SHALL 将该任务 `status` 设为 `abandoned`,记录 `abandon_reason`(必填),并在 `coach_task_history` 中记录
|
||
5. WHEN 助教取消置顶某任务, THE Task_Manager SHALL 将该任务的 `is_pinned` 设为 FALSE
|
||
6. WHEN 助教取消放弃某任务, THE Task_Manager SHALL 将该任务 `status` 恢复为 `active`,清空 `abandon_reason`
|
||
7. IF 助教放弃任务时未提供 `abandon_reason`, THEN THE Task_Manager SHALL 返回 HTTP 422 错误
|
||
8. THE Task_Manager SHALL 通过 Permission_Middleware 验证用户身份,仅允许操作自己的任务
|
||
|
||
### 需求 9:备注 CRUD API
|
||
|
||
**用户故事:** 作为助教,我给客户添加备注后,系统正确存储备注内容和星星评分。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN 助教创建备注时, THE Note_Service SHALL 在 `biz.notes` 表中创建记录,包含 `site_id`、`user_id`、`target_type`('member')、`target_id`(member_id)、`type`、`content`、可选的 `rating_service_willingness`(1-5)、可选的 `rating_revisit_likelihood`(1-5)、可选的 `task_id`
|
||
2. WHEN 备注关联的任务类型为 `follow_up_visit`, THE Note_Service SHALL 将备注 `type` 自动设为 `follow_up`
|
||
3. WHEN 备注关联的任务类型不是 `follow_up_visit`, THE Note_Service SHALL 将备注 `type` 设为 `normal`
|
||
4. WHEN 备注创建成功且 `type = 'follow_up'`, THE Note_Service SHALL 触发 AI 应用 6 备注分析接口(由 P5 实现),传入备注内容和客户信息
|
||
5. WHEN AI 应用 6 返回评分 >= 6 且备注关联的 `follow_up_visit` 任务 `status = 'active'`, THE Note_Service SHALL 将该任务标记为 `completed`
|
||
6. WHEN 助教查询某客户的备注列表, THE Note_Service SHALL 返回该客户在当前 `site_id` 下的所有备注,按 `created_at DESC` 排序,包含星星评分和 AI 评分
|
||
7. WHEN 助教删除备注, THE Note_Service SHALL 执行软删除或硬删除(根据业务需要),删除前需二次确认(前端实现)
|
||
8. IF 星星评分值不在 1-5 范围内, THEN THE Note_Service SHALL 返回 HTTP 422 错误
|
||
9. THE Note_Service 的星星评分 SHALL 不参与回访完成判定(完成判定仅看 AI 应用 6 评分 >= 6),不参与 AI 应用 6 分析,仅作辅助数据存储
|
||
|
||
### 需求 10:触发器调度框架
|
||
|
||
**用户故事:** 作为系统,我需要一个统一的触发器调度框架,支持定时、间隔、事件驱动三种触发方式。
|
||
|
||
#### 验收标准
|
||
|
||
1. THE Trigger_Scheduler SHALL 支持 `cron` 类型触发器,按 cron 表达式计算下次运行时间
|
||
2. THE Trigger_Scheduler SHALL 支持 `interval` 类型触发器,按固定间隔秒数计算下次运行时间
|
||
3. THE Trigger_Scheduler SHALL 支持 `event` 类型触发器,在指定事件发生时立即执行
|
||
4. WHEN 触发器执行完成, THE Trigger_Scheduler SHALL 更新 `trigger_jobs` 表中的 `last_run_at` 和 `next_run_at`
|
||
5. WHEN 触发器 `status = 'disabled'`, THE Trigger_Scheduler SHALL 跳过该触发器不执行
|
||
6. THE Trigger_Scheduler SHALL 提供 `fire_event(event_name, payload)` 方法,用于触发事件驱动型任务
|
||
7. IF 触发器执行过程中发生错误, THEN THE Trigger_Scheduler SHALL 记录错误日志但不中断其他触发器的执行
|
||
|
||
### 需求 11:迁移脚本管理
|
||
|
||
**用户故事:** 作为后端开发者,我需要所有数据库变更都有对应的迁移脚本,以便变更可追溯、可重放。
|
||
|
||
#### 验收标准
|
||
|
||
1. THE Migration_Script SHALL 将所有业务表的 DDL 存放在 `db/zqyy_app/migrations/` 目录中
|
||
2. THE Migration_Script SHALL 使用日期前缀命名(格式:`YYYY-MM-DD__<描述>.sql`)
|
||
3. THE Migration_Script SHALL 使用 UTF-8 编码,纯 SQL(非 ORM)
|
||
4. THE Migration_Script SHALL 在每个脚本中包含回滚语句(以注释形式)
|
||
5. THE Migration_Script SHALL 使用幂等语法(`IF NOT EXISTS`、`ON CONFLICT DO NOTHING`),确保重复执行不会报错
|
||
|
||
### 需求 12:DDL 测试库落库与文档同步
|
||
|
||
**用户故事:** 作为后端开发者,我需要所有 DDL 变更在测试库中实际执行验证,并同步更新数据库手册和 DDL 基线。
|
||
|
||
#### 验收标准
|
||
|
||
1. WHEN 迁移脚本编写完成, THE Task_Manager SHALL 在 `test_zqyy_app` 测试库中执行迁移脚本,验证无错误
|
||
2. WHEN 迁移脚本执行成功, THE Task_Manager SHALL 创建或更新 `docs/database/BD_Manual_biz_tables.md` 数据库手册,包含变更说明、兼容性影响、回滚策略、验证 SQL(至少 3 条)
|
||
3. WHEN 迁移脚本执行成功, THE Task_Manager SHALL 运行 `python scripts/ops/gen_consolidated_ddl.py` 重新生成 DDL 基线文件
|
||
4. WHEN 种子数据脚本执行成功, THE Task_Manager SHALL 在数据库手册中记录种子数据内容(触发器配置)
|
||
|
||
### 需求 13:小程序前端页面原型还原(强制)
|
||
|
||
**用户故事:** 作为产品经理,我需要小程序前端页面严格忠于 `docs/h5_ui/pages/` 中的 H5 原型图结构和视觉细节,确保最终实现与设计稿高度一致。
|
||
|
||
#### 原型图索引
|
||
|
||
| 原型文件 | 对应小程序页面 | 说明 |
|
||
|---------|--------------|------|
|
||
| `docs/h5_ui/pages/task-list.html` | `pages/task-list/task-list` | 任务列表页(首页),含业绩进度卡片、置顶/一般/已放弃三区域 |
|
||
| `docs/h5_ui/pages/task-detail.html` | `pages/task-detail/task-detail` | 任务详情页 - 高优先召回(theme-red Banner) |
|
||
| `docs/h5_ui/pages/task-detail-priority.html` | `pages/task-detail/task-detail` | 任务详情页 - 优先召回(theme-orange Banner) |
|
||
| `docs/h5_ui/pages/task-detail-relationship.html` | `pages/task-detail/task-detail` | 任务详情页 - 关系构建(theme-pink Banner) |
|
||
| `docs/h5_ui/pages/task-detail-callback.html` | `pages/task-detail/task-detail` | 任务详情页 - 客户回访(theme-teal Banner) |
|
||
| `docs/h5_ui/pages/notes.html` | `pages/notes/notes` | 备注记录页 |
|
||
| `docs/h5_ui/pages/customer-detail.html` | `pages/customer-detail/customer-detail` | 客户详情页 |
|
||
|
||
#### 验收标准
|
||
|
||
##### 13.A 结构还原(强制)
|
||
|
||
1. WHEN 实现任务列表页时, THE 小程序页面 SHALL 严格还原原型图中的以下结构层次:顶部用户信息区(头像 + 姓名 + 角色标签 + 门店名)→ 业绩进度卡片(5 段档位进度条 + 课时数据含红戳 + 奖金激励 + 预计收入)→ 任务列表区(📌 置顶区 / 一般任务区 / 已放弃区三个分区,每个分区有标签 + 计数)
|
||
2. WHEN 实现任务卡片时, THE 每张任务卡片 SHALL 包含原型图中的全部元素:左侧 4px 彩色边框(高优先=红、优先=橙、关系构建=粉、客户回访=青)、任务类型标签(渐变色圆角矩形)、客户姓名、爱心 icon(💖/🧡/💛/💙)、备注指示器(📝)、描述行(最近到店 + 余额)、AI 建议行(含 AI 机器人 icon)、右侧箭头
|
||
3. WHEN 实现任务详情页时, THE 页面 SHALL 严格还原原型图中的以下模块顺序:通栏 Banner(导航栏 + 客户信息 + 放弃按钮)→ 维客线索卡片(客户基础/消费习惯/玩法偏好/重要反馈,每条含大类标签 + 摘要 + 详情 + 来源标注)→ 与我的关系卡片(爱心档位标签 + 进度条 + RS 分数 + 描述 + 近期服务记录列表)→ 任务建议卡片(建议执行 + 话术参考含复制按钮)→ 我给 TA 的备注卡片(备注列表含星星评分 + 删除按钮)→ 底部操作栏(问问助手 + 备注两个按钮)
|
||
4. WHEN 实现备注弹窗时, THE 弹窗 SHALL 包含原型图中的全部元素:标题行(添加备注 + 展开评价按钮)、可折叠的星星评分区(再次服务意愿 1-5 星 + 再来店可能性 1-5 星,各含文字提示)、文本输入区、保存按钮
|
||
5. WHEN 实现长按上下文菜单时, THE 菜单 SHALL 还原原型图中的交互:遮罩层 + 圆角菜单面板(置顶/取消置顶、备注、放弃/取消放弃等选项)
|
||
6. WHEN 实现备注记录页时, THE 页面 SHALL 还原原型图中的列表结构:每条备注含内容文本 + 底部标签(助教/客户类型标签 + 时间戳)
|
||
|
||
##### 13.B 视觉还原(强制)
|
||
|
||
1. THE 小程序页面 SHALL 使用与原型图一致的 TDesign 色彩体系:primary=#0052d9、success=#00a870、warning=#ed7b2f、error=#e34d59,灰阶色板 gray-1(#f3f3f3) 至 gray-13(#242424)
|
||
2. THE 任务详情页 Banner SHALL 根据任务类型使用不同主题色:高优先召回=theme-red、优先召回=theme-orange、关系构建=theme-pink、客户回访=theme-teal,与原型图中的渐变背景一致
|
||
3. THE 维客线索大类标签 SHALL 使用原型图中的配色方案:客户基础=primary/10 底色 + primary 文字、消费习惯=success/10 底色 + success 文字、玩法偏好=purple-500/10 底色 + purple-600 文字、重要反馈=error/10 底色 + error 文字
|
||
4. THE 星星评分组件 SHALL 还原原型图中的视觉效果:填充星/空心星 SVG、支持半星显示(用于展示 AI 评分映射)
|
||
5. THE 业绩进度卡片 SHALL 还原原型图中的 5 段档位进度条(按比例宽度:0-100 占 45.45%、100-130/130-160/160-190/190-220 各占 13.64%)、红戳动画(盖戳效果)、奖金金额突出样式
|
||
|
||
##### 13.C WXML/WXSS 技术规范(强制)
|
||
|
||
1. THE 小程序页面 SHALL 使用 WXML 语法而非 HTML 语法:`<view>` 替代 `<div>`、`<text>` 替代 `<span>`/`<p>`、`<image>` 替代 `<img>`、`<navigator>` 替代 `<a>`,禁止使用 HTML 标签
|
||
2. THE 小程序样式 SHALL 使用 WXSS 语法:使用 `rpx` 单位替代 `px`(750rpx = 屏幕宽度)、使用 `@import` 导入公共样式、禁止使用 `rem`/`em`/`vw`/`vh` 等 CSS 单位
|
||
3. THE 小程序页面 SHALL 使用 `wx:for` 替代 JavaScript 循环渲染、`wx:if`/`wx:elif`/`wx:else` 替代条件渲染、`bind:tap` 替代 `onclick`、`data-*` + `e.currentTarget.dataset` 替代 DOM 操作
|
||
4. THE 小程序页面 SHALL 禁止使用以下 Web 特性:`document.*`、`window.*`、`localStorage`(用 `wx.setStorageSync`)、`fetch`/`XMLHttpRequest`(用 `wx.request`)、CSS `position: fixed` 的 `bottom: 0` 底部栏(用小程序安全区域适配)
|
||
5. THE 小程序样式 SHALL 仅使用小程序支持的 CSS 选择器:`.class`、`#id`、`element`、`element, element`、`::after`、`::before`,禁止使用 `>`(子选择器)、`+`(相邻兄弟)、`~`(通用兄弟)、`[attr]`(属性选择器)等不支持的选择器
|
||
6. THE 小程序页面 SHALL 使用 `<block>` 标签作为无渲染包裹容器(替代 HTML 的 `<template>` 或 React 的 `<Fragment>`),`<block>` 不会生成真实 DOM 节点
|
||
|
||
##### 13.D TDesign 组件使用规范(强制)
|
||
|
||
1. THE 小程序页面 SHALL 优先使用 TDesign 组件库中的组件,组件引入路径格式为 `tdesign-miniprogram/{组件名}/{组件名}`,在页面 `.json` 的 `usingComponents` 中注册
|
||
2. THE 以下 UI 元素 SHALL 使用对应的 TDesign 组件:导航栏→`t-navbar`、底部标签栏→`t-tab-bar`、对话框→`t-dialog`、轻提示→`t-toast`、弹出层→`t-popup`、空状态→`t-empty`、加载→`t-loading`、骨架屏→`t-skeleton`、标签→`t-tag`、搜索框→`t-search`
|
||
3. THE TDesign 组件样式覆盖 SHALL 使用以下 4 种方式之一:`style`/`custom-style` 属性、解除样式隔离(`addGlobalClass`)、外部样式类(`t-class`)、CSS 变量(`--td-*`),禁止直接修改 `node_modules` 中的组件源码
|
||
4. THE 小程序 `app.json` SHALL 移除 `"style": "v2"` 配置项,避免 TDesign 组件样式错乱
|
||
5. WHEN 原型图中的 UI 元素无法用 TDesign 组件直接实现时(如自定义进度条、红戳动画、话术气泡等), THE 开发者 SHALL 使用原生 WXML + WXSS 自定义实现,但视觉效果必须与原型图一致
|
||
|
||
##### 13.E 原型图参考流程(强制)
|
||
|
||
1. WHEN 开始实现任何小程序页面前, THE 开发者 SHALL 首先阅读对应的 `docs/h5_ui/pages/*.html` 原型文件,提取页面结构、组件层次、样式细节、交互行为
|
||
2. WHEN 原型图中使用 Tailwind CSS 类名时, THE 开发者 SHALL 将其转换为等效的 WXSS 样式(如 `px-4` → `padding: 0 32rpx`、`rounded-xl` → `border-radius: 24rpx`、`text-sm` → `font-size: 28rpx`)
|
||
3. WHEN 原型图中使用 `<iframe>` 嵌套页面时, THE 开发者 SHALL 理解这是原型展示方式,实际小程序中使用 `wx.navigateTo` 页面跳转
|
||
4. WHEN 原型图中使用 `onclick`/`history.back()` 等 Web API 时, THE 开发者 SHALL 转换为小程序等效 API:`bind:tap` + `wx.navigateBack()`
|
||
5. THE 开发者 SHALL 在实现前加载 `wechat-miniprogram` Power 的相关 steering 文件(`view-layer.md`、`tdesign.md`、`builtin-components.md`),确保使用正确的小程序语法和 TDesign 组件规范
|
||
6. THE 开发者 SHALL 在实现前阅读项目内的 H5 转小程序避坑指南 `apps/miniprogram/doc/h5-to-miniprogram-pitfalls.md`,该文档基于本项目已转换页面的实际踩坑经验整理,涵盖标签映射、rpx 换算、事件系统、TDesign 覆盖方式、高频踩坑清单及新页面开发 Checklist,所有条目具有强制参考效力
|
||
|
||
### 需求 14:任务系统属性测试
|
||
|
||
**用户故事:** 作为后端开发者,我需要通过属性测试验证任务系统核心逻辑的正确性。
|
||
|
||
#### 验收标准
|
||
|
||
1. THE 属性测试 SHALL 验证:对于任意 `(site_id, assistant_id, member_id, task_type)` 组合,`status = 'active'` 的任务最多只有一条(唯一性不变量)
|
||
2. THE 属性测试 SHALL 验证:对于任意任务类型变更操作,旧任务被标记为 `inactive` 且新任务被创建为 `active`(状态机正确性)
|
||
3. THE 属性测试 SHALL 验证:对于任意 `follow_up_visit` 任务,当 `expires_at` 不为 NULL 且当前时间超过 `expires_at` 时,轮询后 `status` 变为 `inactive`(有效期机制)
|
||
4. THE 属性测试 SHALL 验证:对于任意任务放弃操作,`abandon_reason` 不为空字符串(放弃原因必填)
|
||
5. THE 属性测试 SHALL 验证:对于任意备注创建操作,`rating_service_willingness` 和 `rating_revisit_likelihood` 的值在 NULL 或 1-5 范围内(评分范围约束)
|
||
6. THE 属性测试 SHALL 验证:对于任意召回完成事件,`completed_task_type` 记录了完成时的任务类型快照(完成类型快照不变量)
|
||
7. THE 属性测试 SHALL 验证:对于任意备注回溯操作,重分类后的备注 `type` 从 `normal` 变为 `follow_up`(回溯分类正确性)
|
||
|
||
---
|
||
|
||
## 附录:原型还原强制规则摘要
|
||
|
||
> 以下规则适用于本 SPEC 及所有后续小程序页面开发 SPEC,具有全局约束力。
|
||
|
||
1. **原型图是唯一视觉真相**:`docs/h5_ui/pages/*.html` 中的结构、层次、元素、配色、间距、交互行为是小程序页面实现的唯一参考标准。任何偏离原型图的实现都需要明确的产品确认。
|
||
2. **WXML ≠ HTML**:严禁在小程序中使用 HTML 标签(div/span/p/a/img 等),必须使用小程序原生标签(view/text/image/navigator 等)。
|
||
3. **WXSS ≠ CSS**:使用 rpx 单位、仅支持有限选择器、无 DOM/BOM API、样式隔离机制不同。Tailwind CSS 类名必须手动转换为 WXSS。
|
||
4. **TDesign 优先**:凡 TDesign 组件库能覆盖的 UI 元素,必须使用 TDesign 组件;自定义实现仅限 TDesign 无法覆盖的场景。
|
||
5. **Power 文档优先**:实现前必须加载 `wechat-miniprogram` Power 的相关 steering 文件,确保语法和组件用法正确。
|
||
6. **项目踩坑指南必读**:实现前必须阅读 `apps/miniprogram/doc/h5-to-miniprogram-pitfalls.md`,该文档是基于本项目实际转换经验的避坑手册,涵盖 WXML/WXSS 差异、事件系统、TDesign 用法、rpx 换算规则及新页面开发 Checklist。
|