feat: batch update - gift card breakdown spec, backend APIs, miniprogram pages, ETL finance recharge, docs & migrations
This commit is contained in:
997
docs/prd/Neo_Specs/NS1-xcx-backend-api.md
Normal file
997
docs/prd/Neo_Specs/NS1-xcx-backend-api.md
Normal file
@@ -0,0 +1,997 @@
|
||||
# NS1:小程序后端 API 补全 — xcx-backend-api
|
||||
|
||||
> 优先级:最高(上线关键路径)
|
||||
> 预估工作量:大
|
||||
> 前置条件:P1-P5 已完成(数据库、认证、任务、备注、AI 骨架均就绪)
|
||||
> 契约基准:`docs/miniprogram-dev/API-contract.md`
|
||||
|
||||
---
|
||||
|
||||
## 一、背景与目标
|
||||
|
||||
小程序前端 13 个业务页面已全部完成(P5.2 交付),`services/api.ts` 已统一封装 mock → real 切换机制(`USE_REAL_API` 开关)。但后端 23 个接口中仅 16 个已实现,剩余 12 个业务接口缺失,是前后端联调的最大阻塞。
|
||||
|
||||
本 SPEC 目标:补全全部缺失接口 + FDW 端到端验证 + 前后端联调修复,使小程序可以连接真实后端运行。
|
||||
|
||||
### 已实现的接口(16 个)
|
||||
|
||||
| 模块 | 接口 | 路由文件 |
|
||||
|------|------|---------|
|
||||
| Auth(5) | AUTH-1~5(登录/dev-login/me/refresh/apply) | `xcx_auth.py` |
|
||||
| Tasks(5) | GET tasks + pin/unpin/abandon/cancel-abandon | `xcx_tasks.py` |
|
||||
| Notes(3) | POST/GET/DELETE notes | `xcx_notes.py` |
|
||||
| AI Chat(3) | SSE stream + conversations + messages | `xcx_ai_chat.py` |
|
||||
|
||||
### 缺失的接口(12 个)
|
||||
|
||||
| 接口 ID | 端点 | 页面依赖 | 数据源 |
|
||||
|---------|------|---------|--------|
|
||||
| TASK-1 扩展 | GET /tasks(增加 performance 附带字段) | task-list | `dws_assistant_salary_calc` via FDW |
|
||||
| TASK-2 | GET /tasks/{id}(完整详情) | task-detail | biz.coach_tasks + FDW 多表 + ai_cache |
|
||||
| PERF-1 | GET /performance | performance | `dws_assistant_salary_calc` + `dws_assistant_daily_detail` via FDW |
|
||||
| PERF-2 | GET /performance/records | performance-records | `dwd_assistant_service_log` via FDW |
|
||||
| CUST-1 | GET /customers/{id} | customer-detail | `dim_member` + `dws_member_consumption_summary` via FDW |
|
||||
| CUST-2 | GET /customers/{id}/records | customer-service-records | `dwd_assistant_service_log` + `dwd_table_fee_log` via FDW |
|
||||
| COACH-1 | GET /coaches/{id} | coach-detail | `dim_assistant` + `dws_member_assistant_relation_index` via FDW |
|
||||
| BOARD-1 | GET /board/coaches | board-coach | `dws_assistant_salary_calc` + `dws_assistant_monthly_summary` via FDW |
|
||||
| BOARD-2 | GET /board/customers | board-customer | 多个 DWS 指数表 via FDW |
|
||||
| BOARD-3 | GET /board/finance | board-finance | 6 个 `dws_finance_*` 表 via FDW |
|
||||
| CONFIG-1 | GET /config/skill-types | board-coach | 静态配置或 cfg 表 |
|
||||
| CHAT 路径对齐 | 对齐 CHAT-1/2/3 路径与契约 | chat/chat-history | 现有 xcx_ai_chat.py 路径调整 |
|
||||
|
||||
---
|
||||
|
||||
## 二、技术架构
|
||||
|
||||
### 2.1 后端代码模式(沿用现有模式)
|
||||
|
||||
```
|
||||
apps/backend/app/
|
||||
├── routers/ # FastAPI 路由(xcx_*.py)
|
||||
│ ├── xcx_auth.py ✅ 已有
|
||||
│ ├── xcx_tasks.py ✅ 已有(需扩展 TASK-1/TASK-2)
|
||||
│ ├── xcx_notes.py ✅ 已有
|
||||
│ ├── xcx_ai_chat.py ✅ 已有(需路径对齐)
|
||||
│ ├── xcx_performance.py 🆕 新建
|
||||
│ ├── xcx_customers.py 🆕 新建
|
||||
│ ├── xcx_coaches.py 🆕 新建
|
||||
│ ├── xcx_board.py 🆕 新建
|
||||
│ └── xcx_config.py 🆕 新建
|
||||
├── services/ # 业务逻辑层
|
||||
│ ├── task_manager.py ✅ 已有(需扩展)
|
||||
│ ├── note_service.py ✅ 已有
|
||||
│ ├── perf_service.py 🆕 新建
|
||||
│ ├── customer_service.py 🆕 新建
|
||||
│ ├── coach_service.py 🆕 新建
|
||||
│ └── board_service.py 🆕 新建
|
||||
├── schemas/ # Pydantic 响应模型
|
||||
└── auth/ # 认证依赖注入 ✅ 已有
|
||||
```
|
||||
|
||||
### 2.2 数据库连接模式
|
||||
|
||||
- 业务库(zqyy_app):`get_connection()` → psycopg2 直连,读写
|
||||
- ETL 库(通过 FDW):`fdw_etl.*` schema 查询,需先 `SET LOCAL app.current_site_id`
|
||||
- ETL 库(直连只读):`get_etl_readonly_connection(site_id)` → 用于复杂聚合查询
|
||||
|
||||
### 2.3 权限控制
|
||||
|
||||
- 所有接口需 JWT(`require_approved()`)
|
||||
- 看板接口需额外权限检查(`require_permission("view_board_finance")` 等)
|
||||
- 权限种子数据已就绪(auth.role_permissions,14 条映射)
|
||||
|
||||
---
|
||||
|
||||
## 三、接口详细设计
|
||||
|
||||
### 3.1 TASK-1 扩展:任务列表增加绩效概览
|
||||
|
||||
现有 `GET /api/xcx/tasks` 返回 `list[TaskListItem]`,需扩展为:
|
||||
- 增加 `performance` 字段(当月工时/收入/客户数/月份标签)
|
||||
- 增加分页支持(`page`/`pageSize` 参数)
|
||||
- 增加 `status` 筛选参数
|
||||
|
||||
数据源:
|
||||
- 任务列表:`biz.coach_tasks` + `fdw_etl.v_dim_member`(客户信息)+ `fdw_etl.v_dws_member_winback_index`/`v_dws_member_newconv_index`(指数)
|
||||
- 绩效概览:`fdw_etl.v_dws_assistant_salary_calc`(当月薪资计算快照)
|
||||
|
||||
### 3.2 TASK-2:任务详情(完整版)
|
||||
|
||||
现有 `xcx_tasks.py` 无 `GET /tasks/{id}` 端点,需新增。
|
||||
|
||||
数据源(多表聚合):
|
||||
- 基础信息:`biz.coach_tasks`
|
||||
- 客户信息:`fdw_etl.v_dim_member` + `fdw_etl.v_dws_member_consumption_summary`
|
||||
- 亲密度:`fdw_etl.v_dws_member_assistant_intimacy`
|
||||
- 近期服务记录:`fdw_etl.v_dwd_assistant_service_log`(最近 N 条)
|
||||
- 备注:`biz.notes`(最近 N 条,含 ai_score)
|
||||
- 维客线索:`public.member_retention_clue`
|
||||
- AI 缓存:`biz.ai_cache`(app4/app5/app6/app7 缓存)
|
||||
- 喜好标签:`fdw_etl.v_dwd_table_fee_log`(按房间类型统计)
|
||||
|
||||
> ⚠️ 这是最复杂的接口,涉及 8+ 张表的聚合。建议拆分为多个 service 函数组合。
|
||||
|
||||
### 3.3 PERF-1/PERF-2:绩效模块
|
||||
|
||||
PERF-1(绩效概览)数据源:
|
||||
- `fdw_etl.v_dws_assistant_salary_calc`(收入/档位/工资)
|
||||
- `fdw_etl.v_dwd_assistant_service_log`(当月服务记录明细)
|
||||
- `fdw_etl.v_dws_assistant_customer_stats`(新客/常客统计)
|
||||
|
||||
PERF-2(绩效明细)数据源:
|
||||
- `fdw_etl.v_dwd_assistant_service_log`(按月筛选,按日分组)
|
||||
- `fdw_etl.v_dws_assistant_daily_detail`(定档折算惩罚字段)
|
||||
|
||||
### 3.4 CUST-1/CUST-2:客户模块
|
||||
|
||||
CUST-1(客户详情)数据源:
|
||||
- `fdw_etl.v_dim_member` + `fdw_etl.v_dim_member_card_account`(基本信息 + 会员卡)
|
||||
- `fdw_etl.v_dws_member_consumption_summary`(消费汇总)
|
||||
- `fdw_etl.v_dws_member_assistant_relation_index`(关系指数)
|
||||
- `public.member_retention_clue`(维客线索)
|
||||
- 消费记录:`fdw_etl.v_dwd_settlement_head` + `fdw_etl.v_dwd_table_fee_log` + `fdw_etl.v_dwd_store_goods_sale` + `fdw_etl.v_dwd_recharge_order`
|
||||
|
||||
> ⚠️ 会员字段断档规则(DQ-6/DQ-7):`member_phone`/`member_name`/`member_card_type_name` 不可靠,必须通过 `member_id` JOIN `dim_member`/`dim_member_card_account`
|
||||
|
||||
CUST-2(客户服务记录)数据源:
|
||||
- `fdw_etl.v_dwd_assistant_service_log`(按客户+助教筛选)
|
||||
- `fdw_etl.v_dwd_table_fee_log`(台桌信息)
|
||||
|
||||
### 3.5 COACH-1:助教详情
|
||||
|
||||
数据源:
|
||||
- `fdw_etl.v_dim_assistant`(基本信息)
|
||||
- `fdw_etl.v_dws_member_assistant_relation_index`(客户数统计,RS>2)
|
||||
- `biz.coach_tasks`(任务统计:可见/隐藏/已放弃)
|
||||
- `biz.notes`(备注列表)
|
||||
|
||||
### 3.6 BOARD-1/2/3:看板模块
|
||||
|
||||
BOARD-1(助教看板)数据源:
|
||||
- `fdw_etl.v_dws_assistant_salary_calc`(定档业绩/工资)
|
||||
- `fdw_etl.v_dws_assistant_monthly_summary`(月度汇总)
|
||||
- `biz.coach_tasks`(任务完成数统计)
|
||||
|
||||
BOARD-2(客户看板)数据源(8 个维度排序):
|
||||
- 最应召回:`fdw_etl.v_dws_member_winback_index`(WBI 降序)
|
||||
- 最大消费潜力:`fdw_etl.v_dws_member_spending_power_index`(SPI 降序)
|
||||
- 最高余额:`fdw_etl.v_dws_member_consumption_summary`
|
||||
- 最近充值:`fdw_etl.v_dwd_recharge_order`
|
||||
- 最高消费 60 天:`fdw_etl.v_dws_member_consumption_summary`(基于 `items_sum`)
|
||||
- 最频繁 60 天:`fdw_etl.v_dws_member_consumption_summary`
|
||||
- 最近到店:`fdw_etl.v_dws_member_visit_detail`
|
||||
- 最专一:`fdw_etl.v_dws_member_assistant_relation_index`(RS 最大值)
|
||||
|
||||
BOARD-3(财务看板)数据源:
|
||||
- `fdw_etl.v_dws_finance_daily_summary`
|
||||
- `fdw_etl.v_dws_finance_income_structure`
|
||||
- `fdw_etl.v_dws_finance_recharge_summary`
|
||||
- `fdw_etl.v_dws_finance_discount_detail`
|
||||
- `fdw_etl.v_dws_finance_expense_summary`
|
||||
- `fdw_etl.v_dws_platform_settlement`
|
||||
- `biz.ai_cache`(app2_finance 缓存,AI 洞察)
|
||||
|
||||
### 3.7 CONFIG-1:技能类型列表
|
||||
|
||||
静态配置接口,返回助教技能类型列表。数据来源待定(硬编码 or cfg 表)。
|
||||
|
||||
### 3.8 CHAT 路径对齐
|
||||
|
||||
现有 `xcx_ai_chat.py` 路径:
|
||||
- `POST /api/ai/chat/stream`
|
||||
- `GET /api/ai/conversations`
|
||||
- `GET /api/ai/conversations/{id}/messages`
|
||||
|
||||
契约定义路径:
|
||||
- `GET /api/xcx/chat/history`
|
||||
- `GET /api/xcx/chat/{chatId}/messages`
|
||||
- `POST /api/xcx/chat/{chatId}/messages`
|
||||
|
||||
需要对齐路径,或在前端 service 层适配。
|
||||
|
||||
---
|
||||
|
||||
## 四、数据库审查与新增表建议
|
||||
|
||||
### 4.1 现有表结构满足度
|
||||
|
||||
| 接口 | 现有表是否满足 | 缺口 |
|
||||
|------|--------------|------|
|
||||
| TASK-1/2 | ✅ 基本满足 | 需 FDW 多表 JOIN |
|
||||
| PERF-1/2 | ✅ 满足 | 无 |
|
||||
| CUST-1/2 | ✅ 满足 | 消费记录需 3 种类型 UNION |
|
||||
| COACH-1 | ✅ 满足 | 无 |
|
||||
| BOARD-1 | ⚠️ 部分 | 任务完成数需实时统计 |
|
||||
| BOARD-2 | ⚠️ 部分 | 8 维度排序需多表查询,性能风险 |
|
||||
| BOARD-3 | ✅ 满足 | 环比需后端计算 |
|
||||
|
||||
### 4.2 建议新增的中间表/物化视图
|
||||
|
||||
#### 表 1:`biz.board_coach_snapshot`(助教看板快照)
|
||||
|
||||
用途:预聚合助教看板数据,避免每次请求实时 JOIN 多张 FDW 表。
|
||||
|
||||
```sql
|
||||
CREATE TABLE biz.board_coach_snapshot (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
site_id BIGINT NOT NULL,
|
||||
assistant_id BIGINT NOT NULL,
|
||||
snapshot_date DATE NOT NULL,
|
||||
-- 定档业绩
|
||||
performance_tier VARCHAR(20),
|
||||
tier_revenue NUMERIC(12,2),
|
||||
-- 工资
|
||||
salary_total NUMERIC(12,2),
|
||||
-- 客户数
|
||||
customer_count INTEGER,
|
||||
-- 高客源储值额
|
||||
high_value_balance NUMERIC(12,2),
|
||||
-- 任务完成数
|
||||
task_completed_count INTEGER,
|
||||
-- 服务时长
|
||||
total_hours NUMERIC(8,2),
|
||||
total_income NUMERIC(12,2),
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE (site_id, assistant_id, snapshot_date)
|
||||
);
|
||||
```
|
||||
|
||||
刷新策略:ETL 数据更新后触发(`trigger_jobs` 事件驱动),或每日凌晨批量刷新。
|
||||
|
||||
#### 表 2:`biz.board_customer_snapshot`(客户看板快照)
|
||||
|
||||
用途:预聚合客户看板 8 个维度的排序数据,避免实时查询 8 张 FDW 表。
|
||||
|
||||
```sql
|
||||
CREATE TABLE biz.board_customer_snapshot (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
site_id BIGINT NOT NULL,
|
||||
member_id BIGINT NOT NULL,
|
||||
snapshot_date DATE NOT NULL,
|
||||
-- 8 个维度排序值
|
||||
wbi_score NUMERIC(8,4), -- 最应召回
|
||||
spi_score NUMERIC(8,4), -- 最大消费潜力
|
||||
balance_amount NUMERIC(12,2), -- 最高余额
|
||||
last_recharge_date DATE, -- 最近充值
|
||||
spend_60d NUMERIC(12,2), -- 最高消费 60 天(items_sum 口径)
|
||||
visit_count_60d INTEGER, -- 最频繁 60 天
|
||||
last_visit_date DATE, -- 最近到店
|
||||
max_rs_score NUMERIC(8,4), -- 最专一
|
||||
-- 展示字段
|
||||
member_name VARCHAR(100),
|
||||
member_avatar VARCHAR(500),
|
||||
member_tags TEXT[], -- 喜好标签
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE (site_id, member_id, snapshot_date)
|
||||
);
|
||||
```
|
||||
|
||||
#### 表 3:`biz.board_finance_snapshot`(财务看板快照)
|
||||
|
||||
用途:预聚合财务看板数据 + 环比计算结果。
|
||||
|
||||
```sql
|
||||
CREATE TABLE biz.board_finance_snapshot (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
site_id BIGINT NOT NULL,
|
||||
biz_date DATE NOT NULL,
|
||||
-- 核心指标(JSON 存储,灵活扩展)
|
||||
metrics JSONB NOT NULL,
|
||||
-- 环比数据
|
||||
prev_day_metrics JSONB,
|
||||
prev_week_metrics JSONB,
|
||||
prev_month_metrics JSONB,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE (site_id, biz_date)
|
||||
);
|
||||
```
|
||||
|
||||
#### 表 4:`biz.task_detail_cache`(任务详情缓存)
|
||||
|
||||
用途:TASK-2 接口涉及 8+ 张表聚合,首次查询后缓存结果,后续读缓存。
|
||||
|
||||
```sql
|
||||
CREATE TABLE biz.task_detail_cache (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
task_id BIGINT NOT NULL REFERENCES biz.coach_tasks(id),
|
||||
site_id BIGINT NOT NULL,
|
||||
detail_json JSONB NOT NULL,
|
||||
version INTEGER NOT NULL DEFAULT 1,
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
UNIQUE (task_id)
|
||||
);
|
||||
```
|
||||
|
||||
失效策略:备注新增/AI 缓存更新/任务状态变更时,DELETE 对应缓存行。
|
||||
|
||||
---
|
||||
|
||||
## 五、FDW 端到端验证
|
||||
|
||||
### 5.1 验证范围
|
||||
|
||||
需验证 `fdw_etl` schema 下所有外部表可正常 SELECT,重点关注:
|
||||
|
||||
| 外部表 | 用途 | 验证 SQL |
|
||||
|--------|------|---------|
|
||||
| `v_dim_member` | 客户信息 | `SELECT count(*) FROM fdw_etl.v_dim_member` |
|
||||
| `v_dim_assistant` | 助教信息 | `SELECT count(*) FROM fdw_etl.v_dim_assistant` |
|
||||
| `v_dws_assistant_salary_calc` | 薪资计算 | `SELECT * FROM fdw_etl.v_dws_assistant_salary_calc LIMIT 5` |
|
||||
| `v_dws_finance_daily_summary` | 财务日报 | `SELECT * FROM fdw_etl.v_dws_finance_daily_summary LIMIT 5` |
|
||||
| `v_dws_member_winback_index` | WBI 指数 | `SELECT * FROM fdw_etl.v_dws_member_winback_index LIMIT 5` |
|
||||
| `v_dws_member_spending_power_index` | SPI 指数 | `SELECT * FROM fdw_etl.v_dws_member_spending_power_index LIMIT 5` |
|
||||
|
||||
### 5.2 RLS 验证
|
||||
|
||||
```sql
|
||||
-- 设置门店隔离
|
||||
SET LOCAL app.current_site_id = '目标 site_id';
|
||||
-- 验证只返回该门店数据
|
||||
SELECT site_id, count(*) FROM fdw_etl.v_dim_member GROUP BY site_id;
|
||||
-- 预期:只有一个 site_id
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、前后端联调
|
||||
|
||||
### 6.1 联调步骤
|
||||
|
||||
1. 后端接口开发完成后,逐个验证响应格式与 `API-contract.md` 一致
|
||||
2. 小程序 `services/api.ts` 中 `USE_REAL_API = true`
|
||||
3. 逐页面联调:login → task-list → task-detail → performance → board → customer-detail → chat
|
||||
4. 修复 snake_case → camelCase 映射差异
|
||||
5. 处理 inline-mock 页面的数据替换(7 个页面有 TODO 标记)
|
||||
|
||||
### 6.2 已知需要对齐的差异
|
||||
|
||||
- TASK-1 响应格式:现有返回 `list[TaskListItem]`,契约要求 `{ items, total, page, pageSize, performance }`
|
||||
- CHAT 路径:现有 `/api/ai/*`,契约要求 `/api/xcx/chat/*`
|
||||
- 响应包装:现有直接返回数据,契约要求 `{ code: 0, data: ... }` 包装
|
||||
|
||||
---
|
||||
|
||||
## 七、参考文档
|
||||
|
||||
| 文档 | 路径 | 用途 |
|
||||
|------|------|------|
|
||||
| API 契约 | `docs/miniprogram-dev/API-contract.md` | 接口定义基准 |
|
||||
| 前端 Service 层 | `apps/miniprogram/miniprogram/services/api.ts` | 前端期望的响应格式 |
|
||||
| BD 手册-认证表 | `docs/database/BD_Manual_auth_tables.md` | auth schema 表结构 |
|
||||
| BD 手册-业务表 | `docs/database/BD_Manual_biz_tables.md` | biz schema 表结构 |
|
||||
| DWD-DOC 标杆 | `docs/reports/DWD-DOC/` | 金额口径、字段语义权威参考 |
|
||||
| 数据依赖矩阵 | `docs/prd/specs/00-数据依赖矩阵.md` | 页面→数据表映射 |
|
||||
| 现有 task_manager | `apps/backend/app/services/task_manager.py` | 任务服务层模式参考 |
|
||||
| 现有 note_service | `apps/backend/app/services/note_service.py` | 备注服务层模式参考 |
|
||||
| 权限中间件 | `apps/backend/app/middleware/permission.py` | 权限检查模式参考 |
|
||||
| 数据库连接 | `apps/backend/app/database.py` | 连接方式参考 |
|
||||
| FDW 配置 | `db/fdw/setup_fdw_test.sql` | FDW 外部表映射 |
|
||||
|
||||
---
|
||||
|
||||
## 八、预审查清单(SPEC 启动前确认)
|
||||
|
||||
以下问题需要在启动 SPEC 前与用户确认,确保需求无歧义:
|
||||
|
||||
### 8.1 接口设计
|
||||
|
||||
1. **响应包装格式**:现有后端直接返回数据对象,契约要求 `{ code: 0, data: ... }` 包装。是全局统一改造(中间件),还是仅新接口使用包装格式?
|
||||
2. **CHAT 路径对齐**:是修改后端路径从 `/api/ai/*` 改为 `/api/xcx/chat/*`,还是在前端 service 层适配现有路径?
|
||||
3. **分页策略**:TASK-1 契约要求分页,但现有实现返回全量列表。是否所有列表接口都需要分页?看板接口(前 100 名)是否需要分页?
|
||||
4. **CONFIG-1 技能类型**:数据来源是硬编码还是从 `cfg_*` 表读取?如果硬编码,具体的技能类型列表是什么?
|
||||
|
||||
### 8.2 数据库
|
||||
|
||||
5. **快照表刷新策略**:3 个看板快照表(coach/customer/finance)的刷新频率?是 ETL 数据更新后触发,还是每日定时刷新,还是请求时按需刷新?
|
||||
6. **任务详情缓存**:`task_detail_cache` 的过期时间设多久?缓存失效触发条件是否完整(备注新增、AI 缓存更新、任务状态变更)?
|
||||
7. **FDW 外部表命名**:现有代码中使用 `fdw_etl.v_dim_member`(带 `v_` 前缀),需确认所有 FDW 外部表的实际命名是否一致。
|
||||
|
||||
### 8.3 业务逻辑
|
||||
|
||||
8. **TASK-2 服务记录范围**:近期服务记录取最近多少条?最近 30 天还是最近 10 条?
|
||||
9. **BOARD-2 客户看板**:8 个维度排序是否都取前 100 名?是否需要支持类型筛选(如按会员等级筛选)?
|
||||
10. **BOARD-3 财务看板**:环比计算的基准是什么?日环比、周环比、月环比都需要吗?
|
||||
11. **CUST-1 消费记录**:3 种消费类型(台桌/商城/充值)是混合排序还是分类展示?分页策略?
|
||||
12. **COACH-1 任务统计**:可见/隐藏/已放弃的分类逻辑是什么?"隐藏"指什么状态?
|
||||
|
||||
### 8.4 性能与安全
|
||||
|
||||
13. **FDW 查询性能**:看板接口涉及多张 FDW 表的聚合查询,是否需要设置查询超时?超时后返回什么?
|
||||
14. **维客线索脱敏**:TASK-2 返回维客线索时,后端脱敏规则是否与 P6 spec 中定义的一致(移除 recorded_by_assistant_id/name)?
|
||||
15. **金额口径确认**:所有涉及消费金额的接口,确认使用 `items_sum` 口径(= table_charge_money + goods_money + assistant_pd_money + assistant_cx_money + electricity_money),不使用 `consume_money`。
|
||||
|
||||
---
|
||||
|
||||
## 八½、前置审查发现(2026-03-18 Kiro 审查)
|
||||
|
||||
> 审查方法:对照现有代码(`xcx_auth.py`、`xcx_tasks.py`、`xcx_ai_chat.py`、`task_manager.py`、`permission.py`、`database.py`)、API 契约(`API-contract.md`)、前端 Service 层(`api.ts`)、FDW 配置(`setup_fdw_test.sql`)、BD 手册、数据依赖矩阵、DWD-DOC 标杆文档,逐项交叉验证。
|
||||
|
||||
### R1:接口清单准确性
|
||||
|
||||
| # | 问题 | 严重度 | 说明 |
|
||||
|---|------|--------|------|
|
||||
| R1-1 | 接口总数算术错误 | 🟡 低 | spec 称"23 个接口中仅 16 个已实现,剩余 12 个缺失",16+12=28≠23。需修正总数或重新盘点 |
|
||||
| R1-2 | Auth 已实现接口数低估 | 🟡 低 | spec 列 Auth 5 个,实际 `xcx_auth.py` 生产端点 7 个(login/apply/me/me-sites/switch-site/refresh/dev-login),含 dev 端点共 11 个 |
|
||||
| R1-3 | TASK-4 路径不一致 | 🔴 高 | API 契约定义 `POST /tasks/{taskId}/restore`,前端 `api.ts` 调用 `/tasks/${taskId}/restore`,但后端实现的是 `/tasks/{taskId}/cancel-abandon`。联调必然失败 |
|
||||
|
||||
**R1-3 ✅ 已确认**:统一为 `/restore`(改后端路由路径,契约和前端不动)。后端 `xcx_tasks.py` 中 `/cancel-abandon` 端点已实现,需改路径为 `/restore`。
|
||||
|
||||
### R2:响应格式(全局架构决策,阻塞所有新接口开发)
|
||||
|
||||
| # | 问题 | 严重度 | 说明 |
|
||||
|---|------|--------|------|
|
||||
| R2-1 | 成功响应无包装 | 🔴 高 | 契约要求 `{ code: 0, data: ... }`,现有后端直接返回 Pydantic model。全局改造影响所有已实现接口 |
|
||||
| R2-2 | 错误响应格式不一致 | 🔴 高 | 契约要求 `{ code: number, message: string }`,现有 FastAPI 默认 `{ detail: "..." }`。需自定义异常处理器 |
|
||||
| R2-3 | snake_case vs camelCase | 🔴 高 | 后端返回 snake_case,前端期望 camelCase。api.ts 有 TODO 标记但未实现转换。需决定转换层位置 |
|
||||
|
||||
**R2 ✅ 已确认:采用方案 A**(后端全局包装 `{ code: 0, data: ... }` + Pydantic `alias_generator=to_camel`)
|
||||
|
||||
实施路径:
|
||||
1. 新增全局响应包装中间件(或 `response_model` 基类),成功响应统一 `{ code: 0, data: ... }`
|
||||
2. 新增全局异常处理器,`HTTPException` → `{ code: status_code, message: detail }`
|
||||
3. 所有 Pydantic schema 加 `model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)`
|
||||
4. 前端 `request()` 工具函数加 `.data` 解包(一处改动)
|
||||
5. 已有接口(Auth/Tasks/Notes/AI Chat)逐个验证兼容性
|
||||
|
||||
### R3:CHAT 模块路径与功能差异
|
||||
|
||||
| # | 问题 | 严重度 | 说明 |
|
||||
|---|------|--------|------|
|
||||
| R3-1 | 路径前缀不同 | 🟠 中 | 现有 `/api/ai/*`,契约 `/api/xcx/chat/*` |
|
||||
| R3-2 | 功能模式不同 | 🔴 高 | 现有是 SSE 流式(`POST /chat/stream`),契约是同步 JSON(`POST /chat/{chatId}/messages` 返回 `{ userMessage, aiReply }`)。两者不可互替 |
|
||||
| R3-3 | 历史列表字段不同 | 🟠 中 | 现有返回 `{ id, app_id, source_page, first_message_preview }`,契约要求 `{ id, customer_name, last_message, last_time, unread_count }` |
|
||||
|
||||
**R3 ✅ 已确认:采用选项 A**(保留 SSE 流式 + 新增同步端点)
|
||||
|
||||
实施方案:
|
||||
- 保留 `POST /api/xcx/chat/stream`(SSE 流式对话,路径从 `/api/ai/chat/stream` 迁移)
|
||||
- 新增 `GET /api/xcx/chat/history`(历史对话列表,替代 `/api/ai/conversations`)
|
||||
- 新增 `GET /api/xcx/chat/{chatId}/messages`(消息查看,替代 `/api/ai/conversations/{id}/messages`)
|
||||
- 契约补充 SSE 端点定义
|
||||
- `ai_conversations` 表无 `unread_count` 字段,CHAT-1 响应中此字段暂返回 0(或后续按需新增)
|
||||
|
||||
### R4:数据库新增表设计
|
||||
|
||||
| # | 问题 | 严重度 | 说明 |
|
||||
|---|------|--------|------|
|
||||
| R4-1 | 快照表刷新时机未定义 | 🟠 中 | 3 个 board_*_snapshot 表的刷新策略(ETL 后触发 / 每日定时 / 按需)直接影响数据新鲜度和实现复杂度 |
|
||||
| R4-2 | task_detail_cache 命中率存疑 | 🟡 低 | TASK-2 涉及 8+ 张表,备注/AI 缓存/服务记录变更频繁,缓存频繁失效。建议评估:优化 SQL + 并行查询是否足够,不一定需要缓存表 |
|
||||
| R4-3 | board_finance_snapshot.metrics 缺 schema | 🟡 低 | JSONB 灵活但无约束,建议在 spec 中定义 metrics 的 key 清单(如 `total_revenue`、`total_expense`、`net_income` 等) |
|
||||
| R4-4 | board_customer_snapshot.spend_60d 窗口定义 | 🟡 低 | "60 天"是 `snapshot_date - 60` 到 `snapshot_date`,还是自然月?需明确 |
|
||||
| R4-5 | 快照表是否真的需要 | 🟠 中 | 看板数据量不大(单店助教 < 50 人、活跃客户 < 5000 人),FDW 直查 + 合理索引可能已够用。快照表增加了维护复杂度(刷新逻辑、数据一致性)。建议先不建快照表,性能不足时再加 |
|
||||
|
||||
**R4 ✅ 已确认:采用选项 A**(先直查 FDW,做好索引和查询优化)
|
||||
- 不建 `board_coach_snapshot`、`board_customer_snapshot`、`board_finance_snapshot` 三张快照表
|
||||
- 不建 `task_detail_cache` 缓存表
|
||||
- 看板接口直接查 FDW 表,通过合理索引 + SQL 优化保证性能
|
||||
- 如后续出现性能瓶颈,再按需引入快照/缓存机制
|
||||
- spec 第四章中的 4 张新增表建议全部移除
|
||||
|
||||
### R5:权限模型
|
||||
|
||||
| # | 问题 | 严重度 | 说明 |
|
||||
|---|------|--------|------|
|
||||
| R5-1 | 看板接口权限映射未明确 | 🟠 中 | BOARD-1 → `view_board_coach`?BOARD-2 → `view_board_customer`?BOARD-3 → `view_board_finance`?需确认 |
|
||||
| R5-2 | PERF/CUST/COACH 权限未定义 | 🟠 中 | 绩效/客户/助教模块是否只需 `require_approved()`?助教只能看自己的绩效,管理员能看所有人的? |
|
||||
| R5-3 | 数据隔离粒度 | 🟠 中 | 助教只能看自己的任务/绩效/客户(通过 `assistant_id` 过滤),管理员能看全店。这个逻辑在 service 层实现还是中间件层? |
|
||||
|
||||
**R5 ✅ 已确认**:现有 5 个权限 code 够用,从上游入口控制即可。
|
||||
- `view_tasks`:任务模块(TASK-1/2、PERF-1/2、CUST-1/2、COACH-1 均通过此权限 + `require_approved()` 控制)
|
||||
- `view_board` + `view_board_finance` / `view_board_customer` / `view_board_coach`:看板模块
|
||||
- 数据隔离在 service 层实现:助教通过 `user_assistant_binding` 获取 `assistant_id`,只查自己的数据;管理员角色可查全店
|
||||
- 权限选项固定,角色-权限映射通过租户管理后台灵活配置
|
||||
- 不新增权限 code
|
||||
|
||||
### R6:数据源与口径
|
||||
|
||||
| # | 问题 | 严重度 | 说明 |
|
||||
|---|------|--------|------|
|
||||
| R6-1 | TASK-1 performance.total_customers 来源不明 | 🟡 低 | `dws_assistant_salary_calc` 是否有客户数字段?可能需要从 `dws_assistant_customer_stats` 单独查 |
|
||||
| R6-2 | CUST-1 消费记录混合 vs 分类 | 🟡 低 | 3 种消费类型(台桌/商城/充值)在 API 契约中是单一 `consumption_records` 数组,暗示混合排序。确认? |
|
||||
| R6-3 | BOARD-2 维度切换方式 | 🟡 低 | API 契约通过 `dimension` 参数切换 8 个维度,一次返回一个维度的排序结果。确认? |
|
||||
|
||||
### R7:spec 中引用但未定义的表
|
||||
|
||||
| # | 表名 | 引用位置 | 说明 |
|
||||
|---|------|---------|------|
|
||||
| R7-1 | `biz.ai_cache` | TASK-2(app4/5/6/7)、BOARD-3(app2) | 多处引用但 BD 手册无定义。需确认表结构或补充 BD 手册 |
|
||||
| R7-2 | `biz.ai_conversations` + `biz.ai_messages` | CHAT 模块 | 现有 `xcx_ai_chat.py` 通过 `ConversationService` 操作,但 spec 未引用其结构 |
|
||||
| R7-3 | `public.member_retention_clue` | TASK-2、CUST-1 | 维客线索表,spec 未描述字段结构和脱敏规则 |
|
||||
|
||||
**R7 ✅ 已确认(查库验证)**:4 张表全部已建,无需新增 DDL。
|
||||
|
||||
| 表名 | Schema | 字段数 | 关键字段 |
|
||||
|------|--------|--------|---------|
|
||||
| `ai_cache` | biz | 9 | `cache_type`(app2_finance/app3_clue/app4_analysis/app5_script/app6_note/app7_task)、`target_id`、`result_json`(JSONB)、`expires_at` |
|
||||
| `ai_conversations` | biz | 8 | `user_id`(varchar)、`app_id`、`site_id`、`source_page`、`source_context`(JSONB) |
|
||||
| `ai_messages` | biz | 6 | `conversation_id`(FK)、`role`、`content`、`tokens_used` |
|
||||
| `member_retention_clue` | public | 10 | `member_id`、`category`、`summary`、`detail`、`recorded_by_assistant_id`、`recorded_by_name`、`source`(默认 'manual') |
|
||||
|
||||
脱敏规则:TASK-2/CUST-1 返回维客线索时,后端应排除 `recorded_by_assistant_id` 和 `recorded_by_name` 字段(仅返回 `category`、`summary`、`detail`、`source`、`recorded_at`)。
|
||||
|
||||
### R8:其他待确认项
|
||||
|
||||
| # | 问题 | 来源 | 状态 |
|
||||
|---|------|------|------|
|
||||
| R8-1 | CONFIG-1 技能类型 | spec §3.7 + api.ts | ✅ 使用 cfg 表 |
|
||||
| R8-2 | TASK-2 近期服务记录分页 | spec §3.2 | ✅ 一批 20 条,懒加载 |
|
||||
| R8-3 | TASK-2 备注分页 | spec §3.2 | ✅ 一批 20 条,懒加载 |
|
||||
| R8-4 | BOARD-2 每维度取前多少名 | spec §3.6 | ✅ 一批 20 条,懒加载,无上限 |
|
||||
| R8-5 | BOARD-3 环比 | spec §3.6 | ✅ 全部月环比(详见下方) |
|
||||
| R8-6 | COACH-1 "隐藏任务" | spec §3.5 + API 契约 | ✅ `inactive` 状态(详见下方) |
|
||||
| R8-7 | FDW 查询超时 | 性能风险 | 待定(实施时按需设置) |
|
||||
| R8-8 | 金额口径 | DWD-DOC 标杆 | ✅ `items_sum`,禁用 `consume_money` |
|
||||
|
||||
**R8-1 ✅ 已确认**:使用 cfg 表。后端从 ETL 库的 cfg 表读取技能类型列表,前端 api.ts 中的硬编码仅作为 mock 回退。
|
||||
|
||||
**R8-2/3 ✅ 已确认**:一批 20 条,懒加载。
|
||||
- 前端修改需求:TASK-2 页面的服务记录区域和备注区域需从一次性渲染改为懒加载模式(`page` + `pageSize=20` 参数 + 滚动到底部触发"加载更多")
|
||||
|
||||
**R8-4 ✅ 已确认**:一批 20 条,懒加载,无上限。
|
||||
- 前端修改需求:BOARD-2 客户看板需从一次性渲染改为懒加载模式
|
||||
|
||||
**R8-5 ✅ 已确认(环比调研完成)**:
|
||||
- 所有环比均为**月环比**(与上月同期对比)
|
||||
- 共 60+ 个环比数据点,覆盖 6 个板块:经营一览(8 项)、预收资产(6 项 + 赠送卡矩阵 12 项)、应计收入确认(收入结构 9 项 + 正价 4 项 + 优惠 4 项 + 渠道 3 项)、现金流入(5 项)、现金流出(15 项)、助教分析(基础课 + 激励课各 6 项)
|
||||
- 前端已实现环比开关(`compareEnabled`),环比值格式为百分比字符串(如 `"+12.5%"`)
|
||||
- API 契约缺陷:BOARD-3 响应中 `trend` 字段仅支持 `up/down/flat`,**未定义环比百分比值**,需补充 `compareValue: string`(如 `"12.5%"`)字段
|
||||
- 后端需计算所有指标的月环比值(当前期 vs 上期),返回百分比和方向
|
||||
- 页面筛选支持:本月、上月、本周、上周、前3个月、本季度、上季度、最近6个月
|
||||
|
||||
**R8-6 ✅ 已确认**:"隐藏任务"= 回访任务被顶替后,仍有一段生效时间但前端不显示。
|
||||
- 映射关系:`hidden_tasks` 对应 `coach_tasks.status = 'inactive'`(被新任务顶替但未过期)
|
||||
- 后端在 COACH-1 接口中按 status 分组返回:`active` → `visible_tasks`,`inactive` → `hidden_tasks`,`abandoned` → `abandoned_tasks`
|
||||
- 前端不展示 `hidden_tasks`,但后端仍需返回(管理端可能需要查看)
|
||||
|
||||
---
|
||||
|
||||
## 八¾、看板筛选项交叉矩阵(2026-03-18 Kiro 调研)
|
||||
|
||||
> 调研方法:逐文件阅读 `board-coach.ts`、`board-customer.ts`、`board-finance.ts` 的完整源码,提取所有筛选项定义、可选值、默认值、交叉约束、前端传参方式,并与 API 契约和 `api.ts` service 层交叉验证。
|
||||
|
||||
### B1:BOARD-1 助教看板(board-coach)
|
||||
|
||||
#### 筛选项清单
|
||||
|
||||
| 参数名 | 类型 | 可选值 | 默认值 | 说明 |
|
||||
|--------|------|--------|--------|------|
|
||||
| `sort` | 排序维度 | `perf_desc`、`perf_asc`、`salary_desc`、`salary_asc`、`sv_desc`、`task_desc` | `perf_desc` | 6 种排序,决定卡片模板 |
|
||||
| `skill` | 技能筛选 | `all`、`chinese`、`snooker`、`mahjong`、`karaoke` | `all` | 不限、中式/追分、斯诺克、麻将/棋牌、团建/K歌 |
|
||||
| `time` | 时间范围 | `month`、`quarter`、`last_month`、`last_3m`、`last_quarter`、`last_6m` | `month` | 本月、本季度、上月、前3个月、上季度、最近6个月 |
|
||||
|
||||
#### 排序→卡片模板映射(`SORT_TO_DIM`)
|
||||
|
||||
| sort 值 | dimType | 卡片显示内容 |
|
||||
|---------|---------|------------|
|
||||
| `perf_desc` / `perf_asc` | `perf` | 定档业绩工时、上期工时、距升档差距、是否达标 |
|
||||
| `salary_desc` / `salary_asc` | `salary` | 工资总额、定档工时、上期工时 |
|
||||
| `sv_desc` | `sv` | 客源储值额、储值客户数、储值消耗 |
|
||||
| `task_desc` | `task` | 召回任务完成数、回访任务完成数 |
|
||||
|
||||
#### 各维度卡片所需字段(后端响应必须包含)
|
||||
|
||||
所有维度共享的基础字段(每个 item 都返回):
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `id` | string | 助教 ID |
|
||||
| `name` | string | 助教姓名 |
|
||||
| `initial` | string | 姓名首字(头像占位) |
|
||||
| `avatarGradient` | string | 头像渐变色(blue/green/pink/amber/violet/cyan) |
|
||||
| `level` | string | 等级 key:`star`/`senior`/`middle`/`junior` |
|
||||
| `levelClass` | string | 等级样式类(前端可自行映射,后端可不返回) |
|
||||
| `skills` | array | 技能列表 `[{ text: '🎱', cls: 'skill--chinese' }]` |
|
||||
| `topCustomers` | string[] | Top 客户列表(如 `['💖 王先生', '💛 李女士']`) |
|
||||
|
||||
各维度专属字段:
|
||||
|
||||
| dimType | 维度名 | 专属字段 | 类型 | 说明 |
|
||||
|---------|--------|---------|------|------|
|
||||
| `perf` | 定档业绩 | `perfHours` | number | 当期定档工时 |
|
||||
| | | `perfHoursBefore` | number? | 上期定档工时(可选,无上期数据时不返回) |
|
||||
| | | `perfGap` | string? | 距升档差距描述(如 `"距升档 13.8h"`,已达标时不返回) |
|
||||
| | | `perfReached` | boolean | 是否已达标 |
|
||||
| `salary` | 工资 | `salary` | number | 工资总额(元) |
|
||||
| | | `salaryPerfHours` | number | 定档工时 |
|
||||
| | | `salaryPerfBefore` | number? | 上期定档工时 |
|
||||
| `sv` | 客源储值 | `svAmount` | number | 客源储值总额(元) |
|
||||
| | | `svCustomerCount` | number | 储值客户数 |
|
||||
| | | `svConsume` | number | 储值消耗额(元) |
|
||||
| `task` | 任务完成 | `taskRecall` | number | 召回任务完成数 |
|
||||
| | | `taskCallback` | number | 回访任务完成数 |
|
||||
|
||||
> 后端设计建议:所有维度的字段统一返回在同一个 item 对象中(扁平结构),前端根据当前 `dimType` 选择性渲染。这样切换维度时无需重新请求(数据已在本地),仅切换卡片模板即可。如果数据量大或查询开销高,也可按 `sort` 参数只返回当前维度所需字段。
|
||||
|
||||
#### 交叉约束
|
||||
|
||||
| 约束 | 说明 |
|
||||
|------|------|
|
||||
| `time=last_6m` + `sort=sv_desc` | ⚠️ 不兼容。前端 TIME_OPTIONS 注释标注"不支持客源储值最高"。后端需返回 400 或忽略 |
|
||||
| 其他组合 | 无限制,3 参数自由组合 |
|
||||
|
||||
#### 交叉组合总数
|
||||
- sort(6) × skill(5) × time(6) = **180 种**(减去 1 个不兼容 = **175 种有效组合**)
|
||||
|
||||
#### 前端传参(`api.ts`)
|
||||
```typescript
|
||||
fetchBoardCoaches({ skill, sort, time })
|
||||
```
|
||||
|
||||
#### ⚠️ 前端 Bug:筛选变更不触发重新请求
|
||||
`onSortChange`/`onSkillChange`/`onTimeChange` 仅更新 `data` 状态(`selectedSort`/`selectedSkill`/`selectedTime`),**未调用 `loadData()`**。联调时前端需修复:筛选变更后重新调用 `loadData()`。
|
||||
|
||||
---
|
||||
|
||||
### B2:BOARD-2 客户看板(board-customer)
|
||||
|
||||
#### 筛选项清单
|
||||
|
||||
| 参数名 | 类型 | 可选值 | 默认值 | 说明 |
|
||||
|--------|------|--------|--------|------|
|
||||
| `dimension` | 维度切换 | `recall`、`potential`、`balance`、`recharge`、`recent`、`spend60`、`freq60`、`loyal` | `recall` | 8 个维度,决定卡片模板和排序逻辑 |
|
||||
| `project` | 项目筛选 | `all`、`chinese`、`snooker`、`mahjong`、`karaoke` | `all` | 全部、中式/追分、斯诺克、麻将/棋牌、团建/K歌 |
|
||||
| `page` | 分页页码 | 正整数 | `1` | 前端待补充(R8-4 决策:20 条懒加载) |
|
||||
| `pageSize` | 每页条数 | 正整数 | `20` | 前端待补充 |
|
||||
|
||||
#### 8 维度→卡片模板映射(`DIMENSION_TO_DIM`)
|
||||
|
||||
| dimension | 中文名 | 排序依据(后端) | 数据源(FDW 表) | 卡片关键字段 |
|
||||
|-----------|--------|----------------|-----------------|------------|
|
||||
| `recall` | 最应召回 | WBI 降序 | `v_dws_member_winback_index` | idealDays、elapsedDays、overdueDays、visits30d、balance、recallIndex |
|
||||
| `potential` | 最大消费潜力 | SPI 降序 | `v_dws_member_spending_power_index` | potentialTags、spend30d、avgVisits、avgSpend |
|
||||
| `balance` | 最高余额 | balance_amount 降序 | `v_dws_member_consumption_summary` | lastVisit、monthlyConsume、availableMonths |
|
||||
| `recharge` | 最近充值 | last_recharge_date 降序 | `v_dwd_recharge_order` | lastRecharge、rechargeAmount、recharges60d、currentBalance |
|
||||
| `recent` | 最近到店 | last_visit_date 降序 | `v_dws_member_visit_detail` | daysAgo、visitFreq、idealDays |
|
||||
| `spend60` | 最高消费 近60天 | items_sum_60d 降序 | `v_dws_member_consumption_summary` | spend60d、visits60d、highSpendTag |
|
||||
| `freq60` | 最频繁 近60天 | visit_count_60d 降序 | `v_dws_member_consumption_summary` | avgInterval、weeklyVisits(8 周柱状图) |
|
||||
| `loyal` | 最专一 近60天 | max_rs 降序 | `v_dws_member_assistant_relation_index` | intimacy、topCoachName、coachDetails(助教明细表) |
|
||||
|
||||
#### 各维度卡片所需字段(后端响应必须包含)
|
||||
|
||||
所有维度共享的基础字段(每个 item 都返回):
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `id` | string | 客户 member_id |
|
||||
| `name` | string | 客户姓名 |
|
||||
| `initial` | string | 姓名首字(头像占位) |
|
||||
| `avatarCls` | string | 头像样式类(avatar--amber/pink/blue 等) |
|
||||
| `assistants` | array | 关联助教列表 `[{ name, cls, heartScore, badge?, badgeCls? }]` |
|
||||
|
||||
各维度专属字段:
|
||||
|
||||
| dimType | 维度名 | 专属字段 | 类型 | 说明 |
|
||||
|---------|--------|---------|------|------|
|
||||
| `recall` | 最应召回 | `idealDays` | number | 理想到店间隔(天) |
|
||||
| | | `elapsedDays` | number | 已过天数 |
|
||||
| | | `overdueDays` | number | 超期天数(= elapsedDays - idealDays) |
|
||||
| | | `visits30d` | number | 近 30 天到店次数 |
|
||||
| | | `balance` | string | 余额(格式化,如 `"¥2,680"`) |
|
||||
| | | `recallIndex` | string | 召回指数(如 `"9.2"`) |
|
||||
| `potential` | 最大消费潜力 | `potentialTags` | array | 潜力标签 `[{ text: '高频', theme: 'primary' }]` |
|
||||
| | | `spend30d` | string | 近 30 天消费 |
|
||||
| | | `avgVisits` | string | 月均到店(如 `"6.2次"`) |
|
||||
| | | `avgSpend` | string | 次均消费 |
|
||||
| `balance` | 最高余额 | `balance` | string | 当前余额 |
|
||||
| | | `lastVisit` | string | 最近到店(如 `"3天前"`) |
|
||||
| | | `monthlyConsume` | string | 月均消耗 |
|
||||
| | | `availableMonths` | string | 可用月数(如 `"约0.8个月"`) |
|
||||
| `recharge` | 最近充值 | `lastRecharge` | string | 最后充值日期(如 `"2月15日"`) |
|
||||
| | | `rechargeAmount` | string | 充值金额 |
|
||||
| | | `recharges60d` | string | 近 60 天充值次数 |
|
||||
| | | `currentBalance` | string | 当前余额 |
|
||||
| `recent` | 最近到店 | `daysAgo` | number | 距今天数(右上角大字) |
|
||||
| | | `visitFreq` | string | 到店频率(如 `"6.2次/月"`) |
|
||||
| | | `idealDays` | number | 理想间隔 |
|
||||
| | | `visits30d` | number | 近 30 天到店 |
|
||||
| | | `avgSpend` | string | 次均消费 |
|
||||
| `spend60` | 最高消费 近60天 | `spend60d` | string | 近 60 天消费总额 |
|
||||
| | | `visits60d` | string | 近 60 天到店次数 |
|
||||
| | | `highSpendTag` | boolean | 是否高消费标签 |
|
||||
| | | `avgSpend` | string | 次均消费 |
|
||||
| `freq60` | 最频繁 近60天 | `visits60d` | string | 近 60 天到店次数(右上角大字) |
|
||||
| | | `avgInterval` | string | 平均到店间隔(如 `"5.0天"`) |
|
||||
| | | `weeklyVisits` | array | 8 周到店柱状图 `[{ val: number, pct: number }]` |
|
||||
| | | `spend60d` | string | 近 60 天消费 |
|
||||
| `loyal` | 最专一 近60天 | `intimacy` | string | 亲密度指数 |
|
||||
| | | `topCoachName` | string | 最亲密助教姓名 |
|
||||
| | | `topCoachHeart` | number | 最亲密助教爱心分 |
|
||||
| | | `topCoachScore` | string | 最亲密助教关系指数 |
|
||||
| | | `coachName` | string | 主助教姓名 |
|
||||
| | | `coachRatio` | string | 主助教占比(如 `"78%"`) |
|
||||
| | | `coachDetails` | array | 助教服务明细表 `[{ name, cls, heartScore, badge?, avgDuration, serviceCount, coachSpend, relationIdx }]` |
|
||||
|
||||
> 后端设计建议:与助教看板不同,客户看板 8 个维度的字段差异很大,且数据来源不同(8 张不同的 FDW 表)。建议后端按 `dimension` 参数只查询和返回当前维度所需字段,切换维度时前端重新请求。这样避免一次查询 8 张表的性能开销。
|
||||
|
||||
#### 交叉约束
|
||||
- **无交叉限制**:dimension 和 project 完全独立,可自由组合
|
||||
|
||||
#### 交叉组合总数
|
||||
- dimension(8) × project(5) = **40 种有效组合**
|
||||
|
||||
#### 前端传参(`api.ts`)
|
||||
```typescript
|
||||
fetchBoardCustomers({ dimension, project, sort })
|
||||
// 注意:sort 参数在 api.ts 签名中存在但前端未使用(无排序筛选 UI)
|
||||
// page/pageSize 参数缺失,需前端补充(R8-4 决策)
|
||||
```
|
||||
|
||||
#### ⚠️ 前端 Bug:筛选变更不触发重新请求
|
||||
`onDimensionChange`/`onProjectChange` 仅更新 `data` 状态,**未调用 `loadData()`**。联调时前端需修复。
|
||||
|
||||
#### ⚠️ 前端缺失:分页参数
|
||||
R8-4 已确认 20 条懒加载,但 `fetchBoardCustomers` 签名和 `board-customer.ts` 均无 `page`/`pageSize` 参数和"加载更多"逻辑。联调时前端需补充。
|
||||
|
||||
---
|
||||
|
||||
### B3:BOARD-3 财务看板(board-finance)
|
||||
|
||||
#### 筛选项清单
|
||||
|
||||
| 参数名 | 类型 | 可选值 | 默认值 | 说明 |
|
||||
|--------|------|--------|--------|------|
|
||||
| `time` | 时间范围 | `month`、`lastMonth`、`week`、`lastWeek`、`quarter3`、`quarter`、`lastQuarter`、`half6` | `month` | 8 种时间范围 |
|
||||
| `area` | 区域筛选 | `all`、`hall`、`hallA`、`hallB`、`hallC`、`mahjong`、`teamBuilding` | `all` | 7 种区域 |
|
||||
| `compareEnabled` | 环比开关 | `true` / `false` | `false` | 控制环比数据显示/隐藏 |
|
||||
|
||||
#### 6 个板块及筛选影响
|
||||
|
||||
| 板块 | sectionId | 受 time 影响 | 受 area 影响 | 受 compare 影响 | 特殊规则 |
|
||||
|------|-----------|:-----------:|:-----------:|:--------------:|---------|
|
||||
| 经营一览 | section-overview | ✅ | ✅ | ✅ | 无 |
|
||||
| 预收资产 | section-recharge | ✅ | ⚠️ | ✅ | **仅 `area=all` 时显示**,选中具体区域时整个板块隐藏 |
|
||||
| 应计收入确认 | section-revenue | ✅ | ✅ | ✅ | 含收入结构表(按区域分行)、正价明细、优惠明细、渠道明细 |
|
||||
| 现金流入 | section-cashflow | ✅ | ✅ | ✅ | 无 |
|
||||
| 现金流出 | section-expense | ✅ | ✅ | ✅ | 含经营支出、固定支出、助教分成、平台服务费 4 个子分组 |
|
||||
| 助教分析 | section-coach | ✅ | ✅ | ✅ | 含基础课、激励课两个子表(各按等级分行) |
|
||||
|
||||
#### 环比开关行为
|
||||
|
||||
| 状态 | 行为 |
|
||||
|------|------|
|
||||
| `compareEnabled=false`(默认) | 仅显示当期数值,隐藏所有环比箭头和百分比 |
|
||||
| `compareEnabled=true` | 每个数据单元格下方显示环比方向+百分比 |
|
||||
|
||||
环比样式规则:
|
||||
- 上升:绿色 ↑ + 百分比(如 `↑12.5%`)
|
||||
- 下降:红色 ↓ + 百分比(如 `↓3.2%`)
|
||||
- 持平:灰色文字 `持平`
|
||||
|
||||
环比计算基准:与上一个相同时间周期对比(本月 vs 上月、本周 vs 上周、本季度 vs 上季度等)
|
||||
|
||||
#### 交叉约束
|
||||
|
||||
| 约束 | 说明 |
|
||||
|------|------|
|
||||
| `area ≠ all` → 预收资产板块隐藏 | 储值卡数据不按区域拆分,选中具体区域时无意义 |
|
||||
| `compareEnabled` 独立 | 与 time/area 无交叉限制 |
|
||||
| time + area 自由组合 | 无其他限制 |
|
||||
|
||||
#### 交叉组合总数
|
||||
- time(8) × area(7) × compare(2) = **112 种组合**
|
||||
- 其中 area≠all 时预收资产板块隐藏(不影响请求参数,仅影响前端渲染)
|
||||
|
||||
#### ⚠️ 重大设计缺陷:筛选参数不传后端
|
||||
|
||||
当前 `fetchBoardFinance` 签名:
|
||||
```typescript
|
||||
fetchBoardFinance({ date?: string }) // 仅 date 参数
|
||||
```
|
||||
|
||||
前端 `onTimeChange`/`onAreaChange`/`toggleCompare` 仅更新本地 data 状态,**不重新调用 API**。mock 模式下不需要重新请求(数据内联),但联调后必须:
|
||||
|
||||
1. `fetchBoardFinance` 签名扩展为 `{ time, area, compareEnabled }` 三个参数
|
||||
2. 筛选变更后重新调用 `fetchBoardFinance`
|
||||
3. 后端根据 `time` 计算日期范围、根据 `area` 过滤区域、根据 `compareEnabled` 决定是否返回环比数据
|
||||
|
||||
#### 后端 API 参数设计建议
|
||||
|
||||
```
|
||||
GET /api/xcx/board/finance?time={time}&area={area}&compare={0|1}
|
||||
```
|
||||
|
||||
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
||||
|------|------|:----:|--------|------|
|
||||
| `time` | string | 否 | `month` | 时间范围枚举 |
|
||||
| `area` | string | 否 | `all` | 区域枚举 |
|
||||
| `compare` | 0/1 | 否 | `0` | 是否返回环比数据(减少不需要时的计算开销) |
|
||||
|
||||
---
|
||||
|
||||
### 前端修改需求汇总(联调前必须完成)
|
||||
|
||||
#### 看板页修复(F1-F6)
|
||||
|
||||
| # | 页面 | 问题 | 修改内容 |
|
||||
|---|------|------|---------|
|
||||
| F1 | board-coach | 筛选变更不触发重新请求 | `onSortChange`/`onSkillChange`/`onTimeChange` 末尾加 `this.loadData()` |
|
||||
| F2 | board-customer | 筛选变更不触发重新请求 | `onDimensionChange`/`onProjectChange` 末尾加 `this.loadData()` |
|
||||
| F3 | board-customer | 缺少分页参数 | `fetchBoardCustomers` 签名加 `page`/`pageSize`,页面加"加载更多"逻辑 |
|
||||
| F4 | board-finance | 筛选参数不传后端 | `fetchBoardFinance` 签名扩展为 `{ time, area, compare }`,筛选变更后重新调用 |
|
||||
| F5 | board-finance | 筛选变更不触发重新请求 | `onTimeChange`/`onAreaChange` 末尾加 `this.loadData()` |
|
||||
| F6 | board-coach | `time=last_6m` + `sort=sv_desc` 不兼容 | 前端在选择 `last_6m` 时禁用 `sv_desc` 选项,或选择 `sv_desc` 时禁用 `last_6m` |
|
||||
|
||||
#### 列表页修复(F7-F11)
|
||||
|
||||
| # | 页面 | 问题 | 修改内容 |
|
||||
|---|------|------|---------|
|
||||
| F7 | task-list | status 筛选 UI 未实现 | API 支持 `status` 参数但页面无筛选控件,需添加 Tab 或筛选栏 |
|
||||
| F8 | performance | 无月份切换功能 | API 支持 `year`/`month` 参数但页面固定当前月,需添加月份切换按钮 |
|
||||
| F9 | performance-records | 月份切换时未重置分页 | `switchMonth()` 中需将 `page` 重置为 1 |
|
||||
| F10 | customer-service-records | 月份切换采用本地筛选 | `updateMonthView()` 仅本地过滤,联调后需改为重新调用 API |
|
||||
| F11 | notes | 无触底加载逻辑 | API 支持分页但页面未实现 `onReachBottom()` |
|
||||
|
||||
---
|
||||
|
||||
### 非看板列表页筛选矩阵
|
||||
|
||||
#### L1:task-list(任务列表)
|
||||
|
||||
| 参数名 | 类型 | 可选值 | 默认值 | UI 实现 | 说明 |
|
||||
|--------|------|--------|--------|:-------:|------|
|
||||
| `status` | string | `pending`、`completed`、`abandoned` | 无(全部) | ❌ 缺失 | API 支持但页面无筛选控件 |
|
||||
| `page` | number | 1+ | `1` | ✅ 自动 | 触底加载 |
|
||||
| `pageSize` | number | 1+ | `20` | ✅ 硬编码 | — |
|
||||
|
||||
交互:下拉刷新重置 page=1;触底 page++。前端将任务分为 pinnedTasks / normalTasks / abandonedTasks 三组渲染。
|
||||
|
||||
#### L2:performance(绩效概览)
|
||||
|
||||
| 参数名 | 类型 | 可选值 | 默认值 | UI 实现 | 说明 |
|
||||
|--------|------|--------|--------|:-------:|------|
|
||||
| `year` | number | 当前年 ± N | 当前年 | ❌ 缺失 | 固定当前年 |
|
||||
| `month` | number | 1-12 | 当前月 | ❌ 缺失 | 固定当前月 |
|
||||
|
||||
交互:无筛选 UI,页面加载时固定请求当前年月。无分页。
|
||||
|
||||
#### L3:performance-records(绩效明细)
|
||||
|
||||
| 参数名 | 类型 | 可选值 | 默认值 | UI 实现 | 说明 |
|
||||
|--------|------|--------|--------|:-------:|------|
|
||||
| `year` | number | 当前年 ± N | 当前年 | ✅ 月份切换按钮 | 上月/下月箭头 |
|
||||
| `month` | number | 1-12 | 当前月 | ✅ 月份切换按钮 | 不可超过当前月 |
|
||||
| `page` | number | 1+ | `1` | ✅ 自动 | 触底加载 |
|
||||
| `pageSize` | number | 1+ | `20` | ✅ 硬编码 | — |
|
||||
|
||||
月份切换详细交互:
|
||||
1. 页面顶部显示 `{year}年{month}月` 标签,左右各有箭头按钮
|
||||
2. 点击左箭头 → `currentMonth--`(跨年自动 `currentYear--`,`currentMonth=12`)
|
||||
3. 点击右箭头 → `currentMonth++`(跨年自动 `currentYear++`,`currentMonth=1`)
|
||||
4. 边界:`canGoNext = false` 当 `currentYear == nowYear && currentMonth == nowMonth`(不可超过当前月);`canGoPrev = true`(无下限)
|
||||
5. 月份变更后 → 调用 `loadData()` → 重新请求 API `fetchPerformanceRecords({ year, month, page, pageSize })`
|
||||
6. ⚠️ Bug:`switchMonth()` 中未将 `page` 重置为 1,月份切换后可能请求第 N 页数据
|
||||
|
||||
后端响应结构(按月返回):
|
||||
- `summary`:当月汇总(总笔数、总工时、折算前总工时、总收入)
|
||||
- `date_groups`:按日期降序分组,每组含日期标签、当日总工时/总收入、记录列表
|
||||
- 每条记录字段:`id`、`customerName`、`timeRange`(如 `"20:00-22:00"`)、`hours`(折算后)、`hoursRaw`(折算前,可选)、`courseType`、`courseTypeClass`(`tag-basic`/`tag-vip`/`tag-tip`)、`location`(台号)、`income`
|
||||
|
||||
后端时间范围处理:
|
||||
- 接收 `year` + `month` → 转换为 `biz_date BETWEEN '{year}-{month}-01' AND '{year}-{month}-{lastDay}'`
|
||||
- 数据源:`fdw_etl.v_dwd_assistant_service_log`(按 `assistant_id` + `biz_date` 范围查询)
|
||||
|
||||
#### L4:customer-service-records(客户服务记录)
|
||||
|
||||
| 参数名 | 类型 | 可选值 | 默认值 | UI 实现 | 说明 |
|
||||
|--------|------|--------|--------|:-------:|------|
|
||||
| `customerId` | string | 客户 ID | 从 options 读取 | ✅ 自动 | 页面参数 |
|
||||
| `year` | number | 当前年 ± N | 当前年 | ✅ 月份切换按钮 | 上月/下月箭头 |
|
||||
| `month` | number | 1-12 | 当前月 | ✅ 月份切换按钮 | 不可超过当前月 |
|
||||
| `table` | string | 台号 | 无 | ❌ 缺失 | API 支持但页面未使用 |
|
||||
|
||||
月份切换详细交互:
|
||||
1. 页面顶部显示 `{year}年{month}月` 标签,左右各有箭头按钮
|
||||
2. 点击左箭头 → `currentMonth--`(跨年处理同 L3)
|
||||
3. 点击右箭头 → `currentMonth++`(跨年处理同 L3)
|
||||
4. 边界:`canPrev` = `yearMonth > minYearMonth`(最早 12 个月前);`canNext` = `yearMonth < maxYearMonth`(不超过当前月)
|
||||
5. 月份变更后 → 调用 `updateMonthView()` → **仅本地过滤**(从 `allRecords` 中按 `date.startsWith('{year}-{month}')` 筛选)
|
||||
6. ⚠️ 设计问题:首次 `loadData()` 一次性拉取全部记录,月份切换仅本地过滤。联调后如果数据量大(单客户数百条记录),需改为按月请求 API
|
||||
|
||||
本地筛选逻辑:
|
||||
- `allRecords`(首次加载时获取全部)→ 按 `date` 字段前缀 `{year}-{month}` 过滤 → 转换为 `ServiceRecord` 展示格式
|
||||
- 月度统计:`monthCount`(当月记录数)、`monthHours`(当月总时长)
|
||||
- 记录字段:`table`(台号)、`type`(课程类型标签)、`typeClass`(`basic`/`vip`/`tip`/`recharge`)、`recordType`(`course`/`recharge`)、`duration`(折算后小时)、`income`(到手金额)、`drinks`(饮品描述)、`date`(显示日期+时间段)
|
||||
|
||||
后端时间范围处理(联调后建议改为按月请求):
|
||||
- 当前方案:一次返回全部记录,前端本地按月过滤
|
||||
- 建议方案:`fetchCustomerRecords({ customerId, year, month })` → 后端按月查询 `fdw_etl.v_dwd_assistant_service_log`(按 `member_id` + `assistant_id` + `biz_date` 范围)
|
||||
|
||||
#### L5:notes(备注列表)
|
||||
|
||||
| 参数名 | 类型 | 可选值 | 默认值 | UI 实现 | 说明 |
|
||||
|--------|------|--------|--------|:-------:|------|
|
||||
| `page` | number | 1+ | `1` | ✅ 自动 | 下拉刷新重置 |
|
||||
| `pageSize` | number | 1+ | `20` | ✅ 硬编码 | — |
|
||||
|
||||
交互:下拉刷新重置 page=1。⚠️ 无触底加载(`onReachBottom()` 未实现)。
|
||||
|
||||
#### L6:customer-detail / coach-detail(详情页)
|
||||
|
||||
无筛选项,单次加载全部数据。
|
||||
|
||||
---
|
||||
|
||||
## 八⅞、Storyboard 走查 Gap 汇总(2026-03-18)
|
||||
|
||||
> 走查方法:两个子代理分别以助教视角和管理层视角,逐页面对照前端内联 mock 数据 vs API 契约 vs 八¾节字段定义,提取所有未记录的接口需求 Gap。
|
||||
> 完整报告:`docs/reports/storyboard-walkthrough-assistant-view.md`(助教视角,51 Gap)+ `docs/reports/miniprogram-storyboard-walkthrough-gaps.md`(管理层视角,31 Gap)
|
||||
|
||||
### 统计
|
||||
|
||||
| 严重度 | 助教视角 | 管理层视角 | 去重后合计 |
|
||||
|--------|:--------:|:----------:|:----------:|
|
||||
| 🔴 高(阻塞联调) | 17 | 14 | ~20 |
|
||||
| 🟠 中(影响完整性) | 19 | 12 | ~18 |
|
||||
| 🟡 低(可后续修复) | 15 | 5 | ~12 |
|
||||
|
||||
### 核心发现
|
||||
|
||||
1. **契约与前端严重脱节**:BOARD-1/2/3、CUST-1、COACH-1、PERF-1、TASK-1 performance 的契约响应定义与前端实际需求严重不匹配,需完全重写
|
||||
2. **BOARD-3 财务看板**:契约定义扁平 `metrics` 数组,前端需要 6 个独立板块(overview/recharge/revenue/cashflow/expense/coachAnalysis)的深度嵌套结构,含 200+ 字段
|
||||
3. **CUST-1 客户详情**:缺少 5 大模块(aiInsight/coachTasks/favoriteCoaches/消费记录嵌套结构/备注列表)
|
||||
4. **COACH-1 助教详情**:缺少 6 大模块(performance/income/tierNodes/historyMonths/topCustomers 扩展/备注列表)
|
||||
5. **跨页面参数传递**:多处 taskId/customerId 混淆、未传参数、用 name 代替 id 跳转(用户决策:统一用唯一 ID)
|
||||
6. **CHAT 模块**:referenceCard 未定义、customerId→chatId 映射缺失、SSE 端点未在契约中定义
|
||||
|
||||
### 处置方案
|
||||
|
||||
全部 Gap 已纳入 **[RNS1 拆分计划](./RNS1-split-plan.md)**,分 5 个子 Spec 逐步实施。Gap 追溯矩阵见拆分计划末尾。
|
||||
|
||||
---
|
||||
|
||||
## 九、任务清单
|
||||
|
||||
> ⚠️ **已拆分**:原始任务清单(T0-1 ~ T18)已被 Storyboard 走查发现的 80+ 个 Gap 大幅扩展,体量超出单个 SPEC 可控范围。
|
||||
>
|
||||
> 完整的拆分计划见 **[RNS1-split-plan.md](./RNS1-split-plan.md)**,将 NS1 拆为 5 个子 Spec:
|
||||
>
|
||||
> | 子 Spec | 名称 | 任务数 | 状态 |
|
||||
> |---------|------|:------:|:----:|
|
||||
> | RNS1.0 | 基础设施与契约重写 | 6 | 待启动 |
|
||||
> | RNS1.1 | 任务与绩效接口 | 6 | 待启动 |
|
||||
> | RNS1.2 | 客户与助教接口 | 6 | 待启动 |
|
||||
> | RNS1.3 | 三看板接口 | 7 | 待启动 |
|
||||
> | RNS1.4 | CHAT 对齐与联调收尾 | 5 | 待启动 |
|
||||
>
|
||||
> 执行顺序:RNS1.0 → (RNS1.1 ∥ RNS1.2 ∥ RNS1.3) → RNS1.4
|
||||
>
|
||||
> 需求追溯:两份走查报告(`docs/reports/storyboard-walkthrough-assistant-view.md` + `docs/reports/miniprogram-storyboard-walkthrough-gaps.md`)中的全部 Gap 已在拆分计划的追溯矩阵中映射到具体任务。
|
||||
|
||||
### 原始任务清单(归档参考)
|
||||
|
||||
<details>
|
||||
<summary>点击展开原始 Batch 0~C 任务清单(已被 RNS1 拆分计划替代)</summary>
|
||||
|
||||
#### Batch 0:基础设施改造(阻塞所有新接口)
|
||||
- [ ] T0-1:全局响应包装中间件(`{ code: 0, data: ... }` + 异常处理器 `{ code, message }`)
|
||||
- [ ] T0-2:Pydantic schema 统一 camelCase(`alias_generator=to_camel`,所有现有 + 新增 schema)
|
||||
- [ ] T0-3:后端 TASK-4 路径从 `/cancel-abandon` 改为 `/restore`(对齐契约)
|
||||
- [ ] T0-4:前端 `request()` 工具函数加 `.data` 解包适配
|
||||
|
||||
#### Batch A:核心业务接口
|
||||
- [ ] T1:扩展 TASK-1(任务列表 + 绩效概览 + 分页 + 懒加载)
|
||||
- [ ] T2:实现 TASK-2(任务详情完整版,服务记录/备注各 20 条懒加载)
|
||||
- [ ] T3:实现 PERF-1(绩效概览)
|
||||
- [ ] T4:实现 PERF-2(绩效明细,20 条懒加载)
|
||||
- [ ] T5:实现 CUST-1(客户详情,消费记录 3 类混合排序 + 懒加载)
|
||||
- [ ] T6:实现 CUST-2(客户服务记录,20 条懒加载)
|
||||
- [ ] T7:实现 COACH-1(助教详情,任务按 active/inactive/abandoned 分组)
|
||||
|
||||
#### Batch B:看板 + 配置接口
|
||||
- [ ] T8:实现 BOARD-1(助教看板,FDW 直查)
|
||||
- [ ] T9:实现 BOARD-2(客户看板,8 维度切换,20 条懒加载,FDW 直查)
|
||||
- [ ] T10:实现 BOARD-3(财务看板,60+ 指标月环比计算,FDW 直查)
|
||||
- [ ] T11:实现 CONFIG-1(技能类型列表,从 cfg 表读取)
|
||||
|
||||
#### Batch C:CHAT 对齐、前端修复与联调
|
||||
- [ ] T12:CHAT 路径迁移(`/api/ai/*` → `/api/xcx/chat/*`,保留 SSE 流式端点)
|
||||
- [ ] T13:新增 CHAT-1/2 同步端点(历史列表 + 消息查看)
|
||||
- [ ] T14:API 契约补充(SSE 端点定义 + BOARD-3 `compareValue` 字段 + BOARD-3 `time`/`area`/`compare` 参数)
|
||||
- [ ] T15:FDW 端到端验证
|
||||
- [ ] T16:前端懒加载改造(TASK-2 服务记录/备注、BOARD-2 客户列表)
|
||||
- [ ] T17:前端看板筛选修复(F1-F6,详见八¾节)
|
||||
- [ ] T18:前后端联调 + 修复
|
||||
|
||||
</details>
|
||||
Reference in New Issue
Block a user