Files
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

11 KiB
Raw Permalink Blame History

需求文档:小程序数据获取与展示效率优化

简介

对小程序三个核心页面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_tasksbiz.notesbiz.ai_cache 等业务表
  • N_Plus_1_问题:循环中逐条执行 SQL 查询的反模式,导致查询次数随数据量线性增长
  • Batch_Queryfdw_queries.batch_query_for_task_list(),单连接内批量执行多条 ETL 查询的封装函数
  • RS_指数:关系指数(rs_display),来自 v_dws_member_assistant_relation_index,衡量助教与客户的关系紧密度
  • updated_at:数据版本时间戳,用于前端缓存校验后端数据是否已变更
  • Cache_Store:前端内存缓存模块,存储跨页面共享的 ETL 数据会员信息、余额、RS 指数等)
  • salary_calcv_dws_assistant_salary_calc 视图,按 assistant_id + salary_month 唯一,包含工资计算参数
  • relation_indexv_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_nameheart_scorebalancetask_typetask_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_nameheart_score)通过 Cache_Store 传递

需求 5Task-Detail 页 ETL 查询合并

用户故事: 作为助教,我希望任务详情页加载更快,以便快速查看客户信息并采取行动。

验收标准

  1. WHEN get_task_detail 查询 ETL 数据时, THE Task_Manager SHALL 将 member_infobalancerelation_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_detailget_task_list_v2get_task_detail)各执行一次,将完整返回值序列化为 JSON 基线快照
  2. AFTER 每个优化任务完成后, THE 验证脚本 SHALL 使用相同参数再次调用接口,逐字段 diff 对比优化前后的返回值
  3. THE diff 对比 SHALL 覆盖以下关键校验点到手金额hours × net_rate、RS 指数、会员余额、服务记录条数和排序、酒水商品明细、TOP 客户列表
  4. IF diff 发现任何数据值不一致(排除 updated_atdata_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 不改变 aiAnalysisapp4_analysis)和 talkingPointsapp5_talking_points)字段的数据来源、查询逻辑和返回结构
  2. THE biz.ai_cache 表的查询方式(按 target_id + site_id + cache_type 查询,ORDER BY created_at DESCSHALL 在优化后保持不变
  3. IF 后续需要对 AI 分析数据进行校对或调整, THEN THE 接口返回结构 SHALL 保持向后兼容(新增字段可以,删除或改名已有字段不可以)
  4. THE 数据基线快照(需求 9SHALL 包含 aiAnalysistalkingPoints 字段的完整内容,作为后期 AI 校对的参考基准