# RNS1 拆分计划 — NS1 小程序后端 API 补全

> 创建时间：2026-03-18
> 来源：NS1 原始 spec + 两份 Storyboard 走查报告（助教视角 51 Gap + 管理层视角 31 Gap）
> 拆分原则：每个子 spec 控制在 5-8 个任务、可独立交付验证、依赖关系清晰

---

## 拆分总览

| 子 Spec | 名称 | 任务数 | 依赖 | 交付物 | 状态 |
|---------|------|:------:|------|--------|------|
| RNS1.0 | 基础设施与契约重写 | 6 | 无 | 全局中间件 + 重写后的 API 契约 + 前端跨页面参数修复 | ✅ 已完成 |
| RNS1.1 | 任务与绩效接口 | 6 | RNS1.0 | TASK-1 扩展 + TASK-2 + PERF-1 + PERF-2 + 前端适配 | ✅ 已完成 |
| RNS1.2 | 客户与助教接口 | 6 | RNS1.0 | CUST-1 + CUST-2 + COACH-1 + 前端适配 | ✅ 已完成 |
| RNS1.3 | 三看板接口 | 7 | RNS1.0 | BOARD-1 + BOARD-2 + BOARD-3 + CONFIG-1 + 前端筛选修复 | ✅ 已完成 |
| RNS1.4 | CHAT 对齐与联调收尾 | 5 | RNS1.1-1.3 | CHAT 迁移 + FDW 验证 + 前后端联调 | 🔧 实施中 |

总计：30 个任务，5 个子 spec。

---

## RNS1.0：基础设施与契约重写

> 阻塞所有后续子 spec，必须最先完成。
> 预估：2-3 天

### 目标
1. 后端全局响应包装 + camelCase 转换（R2 决策）
2. API 契约按走查报告发现完全重写（BOARD-1/2/3、CUST-1、COACH-1、PERF-1、TASK-1 performance）
3. 前端跨页面参数传递统一用唯一 ID

### 任务清单

| # | 任务 | 说明 | 产出 |
|---|------|------|------|
| T0-1 | 全局响应包装中间件 | `{ code: 0, data }` + 异常处理器 `{ code, message }` | `apps/backend/app/middleware/` |
| T0-2 | Pydantic schema 统一 camelCase | `alias_generator=to_camel`，所有现有 + 新增 schema | `apps/backend/app/schemas/` |
| T0-3 | 后端 TASK-4 路径 `/cancel-abandon` → `/restore` | 对齐契约（R1-3） | `xcx_tasks.py` |
| T0-4 | 前端 `request()` 加 `.data` 解包 | 适配全局包装 | `api.ts` |
| T0-5 | **API 契约完全重写** | 按走查报告重写全部接口响应定义（详见下方） | `API-contract.md` |
| T0-6 | **前端跨页面参数修复** | 统一用唯一 ID 传参（详见下方） | 多个页面 `.ts` |

#### T0-5 契约重写范围

需要完全重写响应定义的接口：

| 接口 | 问题 | 重写要点 |
|------|------|---------|
| BOARD-3 | 扁平 metrics → 6 板块嵌套 | overview/recharge/revenue/cashflow/expense/coachAnalysis 完整字段定义，赠送卡 3×4 矩阵，收入结构表 9 行含子行，助教分析按等级分行，现金流出 4 子分组，环比格式（xxxCompare + isDown/isFlat） |
| BOARD-1 | 10 通用字段 → 20 字段含 4 维度 | skills 改为 `Array<{text,cls}>`，补充 topCustomers，4 维度专属字段（perf/salary/sv/task），sort 参数改为枚举 |
| BOARD-2 | 8 通用字段 → 40+ 维度专属字段 | 8 维度各自字段集，补充 assistants 关联助教列表，weeklyVisits 柱状图，coachDetails 明细表，potentialTags |
| CUST-1 | 缺少 5 大模块 | 补充 balance/consumption60d/idealInterval/daysSinceVisit，aiInsight，coachTasks，favoriteCoaches，消费记录改为嵌套结构（含 coaches 子数组），备注列表 |
| COACH-1 | 缺少 6 大模块 | 补充 performance（6 指标），income（本月/上月各 4 项），tierNodes，historyMonths，topCustomers 扩展（heartEmoji/score/balance），备注列表 |
| PERF-1 | 扁平数组 → DateGroup | this_month_records 改为按日期分组结构，补充收入档位（currentTier/nextTier/upgradeHoursNeeded/upgradeBonus），lastMonthIncome，incomeItems.desc |
| TASK-1 perf | 4 字段 → 15+ 字段 | 补充 tierNodes/basicHours/bonusHours/currentTier/nextTierHours/tierCompleted/bonusMoney/incomeTrend/incomeTrendDir/prevMonth |
| CHAT-1/2 | 字段名不一致 + 缺失 | timestamp→created_at 统一，补充 title，referenceCard 结构，SSE 端点定义，customerId→chatId 映射 |

#### T0-6 前端跨页面参数修复范围

用户决策：统一用唯一 ID 传参。

| 来源页面 | 目标页面 | 当前问题 | 修复方案 |
|---------|---------|---------|---------|
| task-detail | chat | 传 `detail.id`（taskId）当 customerId | TASK-2 响应增加 `customer_id`，跳转改为 `?customerId={detail.customerId}` |
| task-detail | customer-service-records | 同上 | 同上 |
| customer-detail | customer-service-records | 未传 customerId | 跳转加 `?customerId={detail.id}` |
| customer-detail | chat | 未传 customerId | 跳转加 `?customerId={detail.id}` |
| coach-detail | customer-detail | 任务项用 name 跳转 | 改为 `?id={customerId}`（需 TaskItem 含 customerId） |
| performance | task-detail | 传 customerName | 改为 `?id={taskId}`（需记录含 taskId） |
| customer-detail | — | loadDetail() 用 `__route__` 解析 id | 改为从 `onLoad(options)` 获取 |
| chat | API | 传 customerId 但 API 需 chatId | 后端支持 `?customerId=` 查询参数自动查找/创建对话 |

---

## RNS1.1：任务与绩效接口

> 助教日常使用频率最高的 4 个接口。
> 依赖：RNS1.0（全局中间件 + 契约）
> 预估：3-4 天

### 目标
实现任务列表扩展、任务详情、绩效概览、绩效明细 4 个接口，覆盖助教视角的核心工作流。

### 任务清单

| # | 任务 | 说明 | 涉及 Gap |
|---|------|------|---------|
| T1-1 | 扩展 TASK-1（任务列表 + 绩效概览） | performance 从 4 字段扩展到 15+ 字段（tierNodes/basicHours/bonusHours/currentTier/nextTierHours/tierCompleted/bonusMoney/incomeTrend/incomeTrendDir/prevMonth）；enrichTask 补充 lastVisitDays/balance/aiSuggestion | GAP-02, GAP-03 |
| T1-2 | 实现 TASK-2（任务详情完整版） | 服务记录/备注各 20 条懒加载；响应含 `customer_id`；维客线索统一 tag 格式和 source 枚举；aiAnalysis 明确 cache_type 映射 | GAP-06~11 |
| T1-3 | 实现 PERF-1（绩效概览） | this_month_records 按 DateGroup 分组；收入档位数据（currentTier/nextTier/upgradeHoursNeeded/upgradeBonus）；lastMonthIncome；incomeItems 含 desc | GAP-12~16 |
| T1-4 | 实现 PERF-2（绩效明细） | 20 条懒加载；按日期分组；courseTypeClass 枚举统一（`basic`/`vip`/`tip`，不带 `tag-` 前缀） | GAP-19~20 |
| T1-5 | 实现 pin/unpin API 端点 | `POST /tasks/{id}/pin` + `POST /tasks/{id}/unpin`；前端 api.ts 补充对应函数 | GAP-04 |
| T1-6 | 前端适配（任务+绩效页面） | createNote 补充 score 参数；performance 页添加月份切换（F8）；performance-records 月份切换重置分页（F9）；avatarChar/avatarColor 前端自行计算（GAP-19 决策） | GAP-05, F8, F9 |

### 数据源
- `dws_assistant_salary_calc` via FDW → 绩效/档位/收入
- `dwd_assistant_service_log` via FDW → 服务记录
- `biz.coach_tasks` → 任务列表
- `biz.ai_cache` → AI 分析/话术
- `public.member_retention_clue` → 维客线索

### 验收标准
- 助教登录后可看到真实任务列表 + 绩效卡片
- 点击任务可查看完整详情（服务记录、维客线索、AI 分析、备注）
- 绩效概览展示真实档位进度和收入明细
- 绩效明细按日期分组展示，支持月份切换

---

## RNS1.2：客户与助教接口

> 详情页是 Gap 最集中的区域，数据结构最复杂。
> 依赖：RNS1.0（全局中间件 + 契约）
> 预估：3-4 天

### 目标
实现客户详情、客户服务记录、助教详情 3 个接口，覆盖两个角色视角的详情查看需求。

### 任务清单

| # | 任务 | 说明 | 涉及 Gap |
|---|------|------|---------|
| T2-1 | 实现 CUST-1（客户详情） | 含 balance/consumption60d/idealInterval/daysSinceVisit（Banner）；aiInsight（biz.ai_cache app4）；维客线索；消费记录嵌套结构（含 coaches 子数组、tableFee/foodAmount 分项）；备注列表 | GAP-23~30 |
| T2-2 | 实现 CUST-1 coachTasks 模块 | 关联助教任务列表：从 biz.coach_tasks + FDW 聚合，每位助教含任务类型/状态/最后服务时间/近60天服务次数/总时长/次均时长 | GAP-25 |
| T2-3 | 实现 CUST-1 favoriteCoaches 模块 | 最亲密助教：从 `v_dws_member_assistant_relation_index` 获取关系指数，聚合基础课时/激励课时/上课次数/充值金额 | GAP-26 |
| T2-4 | 实现 CUST-2（客户服务记录） | 按月查询（改掉前端全量加载本地过滤）；补充 recordType/isEstimate；月度统计汇总（monthCount/monthHours）；customerPhoneFull；totalServiceCount | GAP-32~35 |
| T2-5 | 实现 COACH-1（助教详情） | performance（6 指标）；income（本月/上月各 4 项）；tierNodes；topCustomers 扩展（heartEmoji/score/balance/consume）；近期服务明细含 perfHours；任务分组（active/inactive/abandoned 含 notes 子数组和 reason）；备注列表 | GAP-38~44 |
| T2-6 | 实现 COACH-1 historyMonths 模块 | 历史月份统计（最近 5+ 个月）：客户数/工时/工资/回访完成数/召回完成数/是否预估 | GAP-41 |

### 数据源
- `fdw_etl.v_dim_member` → 客户基本信息（DQ-6：member_phone 不可靠，用 dim_member.mobile）
- `fdw_etl.v_dws_member_consumption_summary` → 消费汇总/余额
- `fdw_etl.v_dws_member_assistant_relation_index` → 关系指数
- `fdw_etl.v_dwd_assistant_service_log` → 服务记录明细
- `fdw_etl.v_dwd_table_fee_log` → 台费明细
- `fdw_etl.v_dim_assistant` → 助教基本信息
- `fdw_etl.v_dws_assistant_salary_calc` → 助教绩效/收入
- `biz.coach_tasks` → 任务关联
- `biz.ai_cache` → AI 洞察
- `public.member_retention_clue` → 维客线索

### 关键约束
- 金额口径：统一使用 `items_sum`，禁用 `consume_money`（DWD-DOC 强制规则 1）
- 助教费用拆分：`assistant_pd_money`（陪打）+ `assistant_cx_money`（超休），禁用 `service_fee`（DWD-DOC 强制规则 2）
- 会员信息：通过 `member_id` JOIN `dim_member`，禁用 `settlement_head.member_phone`（DQ-6）

### 验收标准
- 客户详情页展示真实余额、消费、AI 洞察、关联助教、最亲密助教、消费记录（含助教明细）、备注
- 客户服务记录支持按月切换，展示真实数据
- 助教详情页展示真实绩效、收入明细、档位进度、TOP20 客户、历史月份统计、任务分组

---

## RNS1.3：三看板接口

> 看板是管理层视角的核心，BOARD-3 财务看板是全项目最复杂的单个接口。
> 依赖：RNS1.0（全局中间件 + 契约）
> 预估：4-5 天

### 目标
实现 3 个看板接口 + 技能配置接口，修复前端看板筛选 Bug。

### 任务清单

| # | 任务 | 说明 | 涉及 Gap |
|---|------|------|---------|
| T3-1 | 实现 BOARD-1（助教看板） | 4 维度专属字段（perf/salary/sv/task）；skills 为 `Array<{text,cls}>`；topCustomers；sort 枚举参数；time 参数日期范围计算 | G2, 八¾ B1 |
| T3-2 | 实现 BOARD-2（客户看板） | 8 维度各自字段集；assistants 关联助教列表；weeklyVisits 柱状图（freq60）；coachDetails 明细表（loyal）；potentialTags（potential）；20 条懒加载 | G3, 八¾ B2 |
| T3-3 | 实现 BOARD-3 经营一览 + 预收资产 | overview（8 指标 + 8 环比）；recharge（储值卡 5 指标 + 赠送卡 3×4 矩阵 = 24 字段 + 24 环比）；area≠all 时预收资产隐藏 | G1, G6, G10 |
| T3-4 | 实现 BOARD-3 应计收入 + 现金流 | revenue（收入结构表 9 行含子行 + 正价/优惠/渠道明细）；cashflow（消费收款 + 充值收款 + 合计） | G7 |
| T3-5 | 实现 BOARD-3 现金流出 + 助教分析 | expense（4 子分组：经营/固定/助教分成/平台服务费）；coachAnalysis（基础课 + 激励课各按 4 等级分行） | G8, G9 |
| T3-6 | 实现 CONFIG-1（技能类型列表） | 从 ETL cfg 表读取，前端 api.ts 硬编码作为 mock 回退 | R8-1 |
| T3-7 | 前端看板筛选修复 | F1-F6（筛选变更触发重新请求）；BOARD-2 补充分页参数；BOARD-3 fetchBoardFinance 签名扩展为 `{time,area,compare}` | F1~F6 |

### BOARD-3 环比计算说明
- 所有环比为月环比（与上一个相同时间周期对比）
- 后端根据 `time` 参数计算当期和上期日期范围，分别查询后计算百分比
- 返回格式：每个值旁有 `xxxCompare: string`（如 `"+12.5%"`）+ `isDown: boolean` + `isFlat: boolean`
- `compare=0` 时不计算环比，减少查询开销

### 数据源
- BOARD-1：`v_dws_assistant_salary_calc` + `v_dws_assistant_monthly_summary` + `v_dim_assistant`
- BOARD-2：8 个维度对应不同 FDW 表（详见八¾ B2 维度映射）
- BOARD-3：6 个 `v_dws_finance_*` 表 + `v_dws_assistant_salary_calc`（助教分析）
- CONFIG-1：ETL cfg 表

### 验收标准
- 助教看板 4 维度切换正常，筛选变更触发重新请求
- 客户看板 8 维度切换正常，懒加载 20 条
- 财务看板 6 板块数据正确，环比开关工作，区域筛选隐藏预收资产
- 技能类型从 cfg 表读取

---

## RNS1.4：CHAT 对齐与联调收尾

> 最后阶段，依赖前面所有子 spec 完成。
> 预估：2-3 天

### 目标
CHAT 模块路径迁移和功能补全，FDW 端到端验证，全量前后端联调。

### 任务清单

| # | 任务 | 说明 | 涉及 Gap |
|---|------|------|---------|
| T4-1 | CHAT 路径迁移 | `/api/ai/*` → `/api/xcx/chat/*`；保留 SSE 流式端点 | R3, GAP-51 |
| T4-2 | 新增 CHAT-1/2 同步端点 | 历史列表（含 title 字段）+ 消息查看（timestamp→created_at 统一）；支持 `?customerId=` 查询参数自动查找/创建对话 | GAP-45~50 |
| T4-3 | CHAT referenceCard 支持 | 消息中附带结构化引用卡片（type/title/summary/data）；多入口参数路由（customerId/historyId/coachId） | GAP-45, GAP-50 |
| T4-4 | FDW 端到端验证 | 验证所有 FDW 查询在 test_zqyy_app → test_etl_feiqiu 链路上正常工作；检查索引和查询性能 | — |
| T4-5 | 前后端联调 + 修复 | 全量联调 13 个页面；修复联调中发现的问题；notes 页补充触底加载（F11）；customer-service-records 改为按月请求 API（F10） | F10, F11 |

### 验收标准
- CHAT 模块 SSE 流式 + 同步端点均可用
- 从任意入口进入 chat 页面均能正确关联上下文
- 13 个页面全部连接真实后端运行，无 mock 数据残留

---

## 执行顺序与依赖关系

```
RNS1.0（基础设施+契约）
  ├── RNS1.1（任务+绩效）──┐
  ├── RNS1.2（客户+助教）──┼── RNS1.4（CHAT+联调）
  └── RNS1.3（三看板）─────┘
```

- RNS1.0 必须最先完成（阻塞所有后续）
- RNS1.1 / RNS1.2 / RNS1.3 可并行（无相互依赖）
- RNS1.4 依赖 RNS1.1-1.3 全部完成

---

## 与 NS1 原始 spec 的关系

NS1 原始 spec（`NS1-xcx-backend-api.md`）保留为历史参考文档，其中：
- 一~七章：技术架构和接口设计（被 RNS1.0 T0-5 契约重写替代）
- 八½：前置审查发现 R1-R8（决策仍有效，分散到各子 spec 执行）
- 八¾：看板筛选交叉矩阵（仍为权威参考，RNS1.3 直接引用）
- 九：原始任务清单（被本拆分计划替代）

两份走查报告保留在 `docs/reports/` 作为需求追溯依据：
- `storyboard-walkthrough-assistant-view.md`（助教视角，51 Gap）
- `miniprogram-storyboard-walkthrough-gaps.md`（管理层视角，31 Gap）

---

## Gap 追溯矩阵

### 助教视角报告 Gap → 子 Spec 映射

| Gap | 描述 | 子 Spec |
|-----|------|---------|
| GAP-01 | globalData.authUser 缺少 role/store_name/coach_level/avatar | RNS1.0 T0-6（前端修复，/me 已返回这些字段） |
| GAP-02 | TASK-1 performance 字段不足（4→15+） | RNS1.1 T1-1 |
| GAP-03 | enrichTask 需要 lastVisitDays/balance/aiSuggestion | RNS1.1 T1-1 |
| GAP-04 | pin/unpin API 端点未定义 | RNS1.1 T1-5 |
| GAP-05 | createNote 缺少 score 参数 | RNS1.1 T1-6 |
| GAP-06~08 | 维客线索 tag/source 格式 + aiAnalysis cache_type | RNS1.1 T1-2 |
| GAP-09~10 | taskId/customerId 混淆 | RNS1.0 T0-6 |
| GAP-11 | storageLevel/relationLevel 计算逻辑 | RNS1.1 T1-6（前端自行计算） |
| GAP-12~16 | PERF-1 DateGroup/档位/lastMonthIncome/incomeItems | RNS1.1 T1-3 |
| GAP-17 | performance→task-detail 传参不匹配 | RNS1.0 T0-6 |
| GAP-18 | performance 无月份切换 | RNS1.1 T1-6（F8） |
| GAP-19~22 | PERF-2 avatarChar/courseTypeClass/分页重置/Banner | RNS1.1 T1-4 + T1-6 |
| GAP-23~30 | CUST-1 五大缺失模块 | RNS1.2 T2-1~T2-3 |
| GAP-31 | customer-detail 跳转未传 customerId | RNS1.0 T0-6 |
| GAP-32~35 | CUST-2 扩展字段 + 按月查询 | RNS1.2 T2-4 |
| GAP-36~37 | notes 触底加载 + tagType 语义 | RNS1.4 T4-5 |
| GAP-38~44 | COACH-1 六大缺失模块 | RNS1.2 T2-5~T2-6 |
| GAP-45~51 | CHAT 模块全部 Gap | RNS1.4 T4-1~T4-3 |

### 管理层视角报告 Gap → 子 Spec 映射

| Gap | 描述 | 子 Spec |
|-----|------|---------|
| G1 | BOARD-3 响应结构完全不匹配 | RNS1.3 T3-3~T3-5 |
| G2 | BOARD-1 字段严重不足 | RNS1.3 T3-1 |
| G3 | BOARD-2 字段严重不足 | RNS1.3 T3-2 |
| G4 | COACH-1 缺少多个核心区域 | RNS1.2 T2-5~T2-6 |
| G5 | CUST-1 缺少管理层核心数据 | RNS1.2 T2-1~T2-3 |
| G6~G10 | BOARD-3 各子模块缺失 + 环比格式 | RNS1.3 T3-3~T3-5 |
| G11 | customer-detail→customer-service-records 未传 customerId | RNS1.0 T0-6 |
| G12 | coach-detail 任务项用 name 跳转 | RNS1.0 T0-6 |
| G13~G14 | api.ts 返回类型不匹配 | RNS1.0 T0-5（契约重写时同步更新类型） |
| G15~G26 | 各接口中等严重度缺陷 | 分散到对应子 Spec |
| G27~G31 | 低严重度设计决策 | 分散到对应子 Spec |

### 前端修复项 → 子 Spec 映射

| 修复项 | 描述 | 子 Spec |
|--------|------|---------|
| F1~F6 | 看板筛选变更不触发重新请求 | RNS1.3 T3-7 |
| F7 | task-list status 筛选 UI 未实现 | RNS1.1 T1-6（低优先级，可后续） |
| F8 | performance 无月份切换 | RNS1.1 T1-6 |
| F9 | performance-records 月份切换未重置分页 | RNS1.1 T1-6 |
| F10 | customer-service-records 本地筛选改 API 请求 | RNS1.4 T4-5 |
| F11 | notes 无触底加载 | RNS1.4 T4-5 |
