Files
Neo-ZQYY/docs/specs/miniapp-data-perf-optimization/requirements.md
Neo 70324d8542 chore: 文档与 IDE 配置整理
- .kiro/specs/ → docs/specs/(41 个历史需求 spec 迁移,移除 .config.kiro)
- CLAUDE.md 三层拆分:根文件精简 + apps/backend/CLAUDE.md + .claude/commands/
- 新增 /spec-close、/pre-change 两个工作流命令
- DDL 基线刷新(从测试库重新导出 11 个文件,dws 35→38 表,biz 18→21 表)
- BD_Manual → BD_manual 命名统一(48 个文件)
- 修复 3 处文档与数据库不一致(auth.users.status 默认值、scheduled_tasks 字段、RLS 视图数)
- 新增 BD_manual_public_rbac_tables.md(public schema 8 张 RBAC/工作流表)
- 合并 biz.trigger_jobs 文档(10→12 字段,归档独立文档)
- docs/database/README.md 索引更新

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 00:02:37 +08:00

141 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 需求文档:小程序数据获取与展示效率优化
## 简介
对小程序三个核心页面Performance 绩效页、Task-List 任务列表页、Task-Detail 任务详情页)进行数据获取和展示效率优化。优化覆盖两个维度:页面加载速度(减少 SQL 查询次数和连接开销和页面间跳转体验减少重复请求。通过后端批量查询、SQL 层过滤、前端内存缓存 + 版本校验等手段,提升整体用户体验。
## 术语表
- **小程序Miniprogram**:微信小程序客户端,面向门店助教使用
- **Performance_页**绩效概览页面展示助教当月绩效、收入、TOP 客户、服务记录等
- **Task_List_页**:任务列表页面,展示助教待办任务卡片列表及绩效进度条
- **Task_Detail_页**任务详情页面展示单个任务的客户信息、维客线索、服务记录、AI 分析等
- **ETL_库**:数据仓库(`test_etl_feiqiu`),通过 `_fdw_context` 设置 RLS 参数后访问 `app.v_*` 视图
- **业务库**:应用数据库(`test_zqyy_app`),存储 `biz.coach_tasks``biz.notes``biz.ai_cache` 等业务表
- **N_Plus_1_问题**:循环中逐条执行 SQL 查询的反模式,导致查询次数随数据量线性增长
- **Batch_Query**`fdw_queries.batch_query_for_task_list()`,单连接内批量执行多条 ETL 查询的封装函数
- **RS_指数**:关系指数(`rs_display`),来自 `v_dws_member_assistant_relation_index`,衡量助教与客户的关系紧密度
- **updated_at**:数据版本时间戳,用于前端缓存校验后端数据是否已变更
- **Cache_Store**:前端内存缓存模块,存储跨页面共享的 ETL 数据会员信息、余额、RS 指数等)
- **salary_calc**`v_dws_assistant_salary_calc` 视图,按 `assistant_id + salary_month` 唯一,包含工资计算参数
- **relation_index**`v_dws_member_assistant_relation_index` 视图,按 `assistant_id + member_id` 唯一
## 需求
### 需求 1Performance 页 N+1 查询消除
**用户故事:** 作为助教,我希望绩效页加载更快,以便在繁忙时段快速查看当月绩效数据。
#### 验收标准
1. WHEN `get_coach_detail` 被调用, THE Coach_Service SHALL 通过单条批量 SQL 查询获取所有 TOP 客户的 RS 指数,替代当前按 `member_id` 逐条循环调用 `get_relation_index` 的模式
2. THE FDW_Queries 模块 SHALL 提供 `get_relation_index_batch(conn, site_id, assistant_id, member_ids)` 函数,接受 `member_ids` 列表参数,返回 `dict[int, float]`member_id → rs_display 映射)
3. WHEN `member_ids` 列表为空, THE `get_relation_index_batch` 函数 SHALL 返回空字典,不执行任何 SQL 查询
4. WHEN 批量查询执行后, THE 返回结果 SHALL 与逐条查询 `get_relation_index` 对相同 `member_ids` 的结果在 RS 指数值上完全一致
5. THE `_build_top_customers` 函数 SHALL 调用 `get_relation_index_batch` 一次性获取所有客户的 RS 指数,替代当前的 `for mid in member_ids` 循环
### 需求 2Task-List 页服务端过滤优化
**用户故事:** 作为助教,我希望任务列表加载更快且数据准确,以便高效管理待办任务。
#### 验收标准
1. WHEN `get_task_list_v2` 查询 `biz.coach_tasks` 时, THE Task_Manager SHALL 在 SQL WHERE 子句中直接排除不满足展示条件的任务,替代拉取全量 200 条后在内存中过滤的模式
2. THE SQL 查询 SHALL 在 WHERE 子句中包含 `relationship_building` 任务的 RS 范围过滤条件(排除 RS 指数不在 `[rs_min, rs_max]` 范围内的 `member_id`
3. WHEN RS 排除列表查询失败时, THE Task_Manager SHALL 降级为不排除任何任务(当前已有的容错行为保持不变)
4. THE 分页 `total` 计数 SHALL 与实际返回的过滤后结果集一致,跨页翻页时 `total` 值保持准确
5. WHILE 前端请求 `pageSize=200` 一次性加载时, THE 后端 SHALL 仅返回满足展示条件的任务,减少无效数据传输量
### 需求 3前端内存缓存与版本校验
**用户故事:** 作为助教,我希望在页面间跳转时不重复等待相同数据加载,以获得流畅的操作体验。
#### 验收标准
1. THE Cache_Store SHALL 缓存以下跨页面共享的 ETL 数据:会员信息(`member_info`)、会员余额(`balance`、RS 指数(`relation_index`
2. THE 后端接口 SHALL 在每条返回数据中包含 `updated_at` 时间戳字段,表示该数据在后端的最后更新时间
3. WHEN 前端请求数据时, THE Cache_Store SHALL 先检查本地缓存是否存在且 `updated_at` 未过期;若缓存有效则直接使用,若缓存过期或不存在则发起网络请求
4. WHEN 后端数据发生变更(`updated_at` 更新)时, THE Cache_Store SHALL 在下次请求时检测到版本变化并重新获取最新数据
5. IF 缓存校验逻辑发生异常, THEN THE Cache_Store SHALL 降级为直接发起网络请求,确保功能可用性不受影响
6. THE Cache_Store SHALL 在小程序 `onHide`(切后台)或用户主动下拉刷新时清空全部缓存,确保回到前台时获取最新数据
### 需求 4跳转传参优化
**用户故事:** 作为助教,我希望从任务列表点击进入任务详情时,已加载的客户信息能直接展示,减少等待时间。
#### 验收标准
1. WHEN 用户从 Task_List_页 点击任务卡片跳转到 Task_Detail_页 时, THE Task_List_页 SHALL 将已加载的任务数据(`customer_name``heart_score``balance``task_type``task_type_label`)通过全局 Cache_Store 传递给 Task_Detail_页
2. WHEN Task_Detail_页 加载时, THE Task_Detail_页 SHALL 优先从 Cache_Store 读取已有数据立即渲染骨架内容,同时异步请求完整详情数据
3. WHEN 完整详情数据返回后, THE Task_Detail_页 SHALL 用完整数据覆盖骨架内容,实现无缝过渡
4. IF Cache_Store 中无对应任务的预加载数据, THEN THE Task_Detail_页 SHALL 回退为当前的全量加载模式(显示 loading → 请求 → 渲染)
5. WHEN 用户从 Performance_页 点击客户卡片跳转到 Task_Detail_页 时, THE Performance_页 SHALL 同样将已有的客户数据(`customer_name``heart_score`)通过 Cache_Store 传递
### 需求 5Task-Detail 页 ETL 查询合并
**用户故事:** 作为助教,我希望任务详情页加载更快,以便快速查看客户信息并采取行动。
#### 验收标准
1. WHEN `get_task_detail` 查询 ETL 数据时, THE Task_Manager SHALL 将 `member_info``balance``relation_index` 三个独立 ETL 连接合并为单连接批量查询
2. THE 合并后的查询 SHALL 复用 `_fdw_context` 单次连接在同一个事务中依次执行会员信息、余额、RS 指数查询
3. WHEN 批量 ETL 查询失败时, THE Task_Manager SHALL 对每个子查询独立降级(返回默认值),不影响其他子查询的结果
4. THE 合并后的查询结果 SHALL 与当前三个独立查询的结果在数据内容上完全一致
### 需求 6后端 updated_at 版本字段支持
**用户故事:** 作为开发者,我希望后端接口返回数据版本时间戳,以便前端缓存能准确判断数据是否过期。
#### 验收标准
1. THE 后端 SHALL 在 `get_task_list_v2` 返回的每个任务项中包含 `updated_at` 字段(来自 `biz.coach_tasks.updated_at`
2. THE 后端 SHALL 在 `get_coach_detail` 返回的 `top_customers` 列表中,为每个客户附加 `data_updated_at` 字段(取 ETL 查询时的服务器时间戳)
3. THE 后端 SHALL 在 `get_task_detail` 返回中包含 `updated_at` 字段
4. IF `biz.coach_tasks` 表当前缺少 `updated_at` 列, THEN THE 数据库迁移 SHALL 添加该列,默认值为 `now()`,并在任务状态变更时自动更新
5. THE DDL 变更 SHALL 合并到主 DDL 迁移文件中,并通过审计流程记录
### 需求 7Task-Detail 页折前/折后小时数条件显示
**用户故事:** 作为助教,我希望只在折前和折后小时数有差异时才看到折前小时数,以减少信息干扰。
#### 验收标准
1. WHEN 服务记录的折前小时数(`service_hours_raw`)与折后小时数(`service_hours`)不相等时, THE Task_Detail_页 SHALL 在折后小时数旁显示"折前 XX.Xh"标注
2. WHEN 折前小时数与折后小时数相等时, THE Task_Detail_页 SHALL 仅显示折后小时数,不显示折前标注
3. IF 折前小时数(`duration_raw`)为 `null` 或未返回, THEN THE Task_Detail_页 SHALL 视为与折后小时数相等,不显示折前标注
4. THE 折前小时数 SHALL 格式化为一位小数(如"折前 2.5h"),与折后小时数的格式保持一致
### 需求 8LEFT JOIN LATERAL 酒水聚合优化(低优先级)
**用户故事:** 作为开发者,我希望服务记录的酒水明细聚合查询在数据量增长时仍保持高效。
#### 验收标准
1. WHILE 单次查询涉及的服务记录超过 50 条时, THE FDW_Queries 模块 SHALL 使用 CTE 预聚合方式替代当前的 `LEFT JOIN LATERAL` 子查询聚合酒水商品明细
2. WHEN 使用 CTE 预聚合后, THE 查询结果 SHALL 与 `LEFT JOIN LATERAL` 方式返回的 `drinks` 字段内容完全一致
3. WHILE 单次查询涉及的服务记录不超过 50 条时, THE FDW_Queries 模块 SHALL 保持当前的 `LEFT JOIN LATERAL` 方式(小数据量下性能已足够)
### 需求 9数据基线快照与回归验证
**用户故事:** 作为开发者,我希望每次效率优化后能自动验证数据正确性,确保优化不引入数据偏差。
#### 验收标准
1. BEFORE 任何优化任务开始实施前, THE 验证脚本 SHALL 使用小燕assistant_id: `2964673443302213`、site_id: `2790685415443269`)的真实数据,对三个核心接口(`get_coach_detail``get_task_list_v2``get_task_detail`)各执行一次,将完整返回值序列化为 JSON 基线快照
2. AFTER 每个优化任务完成后, THE 验证脚本 SHALL 使用相同参数再次调用接口,逐字段 diff 对比优化前后的返回值
3. THE diff 对比 SHALL 覆盖以下关键校验点到手金额hours × net_rate、RS 指数、会员余额、服务记录条数和排序、酒水商品明细、TOP 客户列表
4. IF diff 发现任何数据值不一致(排除 `updated_at``data_updated_at` 等时间戳字段), THEN THE 验证脚本 SHALL 报告失败并输出差异详情
5. THE 验证脚本 SHALL 以 pytest 形式编写,放置在 `tests/` 目录下,可通过 `pytest tests/test_perf_optimization_baseline.py -v` 执行
6. THE 基线快照 JSON 文件 SHALL 存储在 `tests/fixtures/perf_optimization/` 目录下,纳入版本控制
### 需求 10AI 分析数据校对预留(后期)
**用户故事:** 作为开发者,我希望 AI 分析相关的数据字段在优化过程中保持接口兼容,以便后期校对和调整。
#### 验收标准
1. THE 优化过程 SHALL 不改变 `aiAnalysis``app4_analysis`)和 `talkingPoints``app5_talking_points`)字段的数据来源、查询逻辑和返回结构
2. THE `biz.ai_cache` 表的查询方式(按 `target_id + site_id + cache_type` 查询,`ORDER BY created_at DESC`SHALL 在优化后保持不变
3. IF 后续需要对 AI 分析数据进行校对或调整, THEN THE 接口返回结构 SHALL 保持向后兼容(新增字段可以,删除或改名已有字段不可以)
4. THE 数据基线快照(需求 9SHALL 包含 `aiAnalysis``talkingPoints` 字段的完整内容,作为后期 AI 校对的参考基准