# Wave 1 W1-T1 — 看板沙箱接入(P0-3) | 字段 | 值 | |---|---| | 日期 | 2026-05-04 | | Wave | 1 / Day 2 | | 范围 | P0-3 看板沙箱接入(实际改动量 < 原估算 5-7h,因调研发现后端已接入) | | 文件改动 | 1 个小程序文件(board-finance.ts) | | 编译验证 | tsc 对 board-finance.ts 零错误 ✅ | ## 一、调研修正前期 P0-3 报告 **P0-3 原结论(Wave 0)**: > Grep 实证:小程序三大看板 + xcx_board.py **零处引用** runtime-clock / runtime_context **Day 2 实地走查发现**: - ✅ **xcx_board.py 是 router 层薄封装**,不直接引用 runtime_context 是正常设计 - ✅ **board_service.py(服务层)已接入 runtime_context**: - L264 `runtime_ctx = get_runtime_context(site_id)` + `_calc_date_range(time, ref_date=runtime_ctx.business_date)` - L482-490 60 天消费窗口已用 `as_runtime_today_param` - L712 同样接入业务日 - ✅ **board-customer.ts / board-coach.ts 0 处使用 `new Date()`**,完全没问题 - ❌ **board-finance.ts 唯一遗漏**:`isCurrentMonthFilter` 函数用 `new Date().getDate() <= 5` 判断"本月前 5 天",沙箱模式回放历史日期时会判错 **P20 SPEC §13 已知冲突表的标记是准确的**:`board-finance.ts isCurrentMonthFilter` 设计文档要求改但未在 grep 结果中确认 → 现已确认未改,本轮修复。 ## 二、修复内容 文件:[apps/miniprogram/miniprogram/pages/board-finance/board-finance.ts](../../../apps/miniprogram/miniprogram/pages/board-finance/board-finance.ts) ### 改动 1:import + isCurrentMonthFilter 改造 ```typescript import { getBusinessClock } from '../../utils/runtime-clock' function isCurrentMonthFilter(selectedTime: string, businessDate?: string): boolean { if (selectedTime !== 'month') return false if (businessDate) { const day = parseInt(businessDate.slice(8, 10), 10) return !Number.isNaN(day) && day <= 5 } return new Date().getDate() <= 5 // 降级:业务时钟未就绪时用本地 } ``` ### 改动 2:data 加 businessDate ```typescript data: { ... isCurrentMonth: true, businessDate: '', // YYYY-MM-DD,沙箱模式下回放虚拟日期 } ``` ### 改动 3:onShow 拉业务时钟 + 修正 isCurrentMonth ```typescript onShow() { checkPageAccess(...).then((allowed) => { if (!allowed) return ... // Wave 1 W1-T1:刷新业务时钟,沙箱模式下回放虚拟日期 getBusinessClock().then((clock) => { const businessDate = clock.business_date || '' this.setData({ businessDate, isCurrentMonth: isCurrentMonthFilter(this.data.selectedTime, businessDate), }) }).catch(() => { // 降级:保留默认 isCurrentMonth(本地时钟) }) this._loadData() }) } ``` ### 改动 4:onTimeChange 用 businessDate ```typescript onTimeChange(...) { this.setData({ selectedTime: value, selectedTimeText: option?.text || '本月', isCurrentMonth: isCurrentMonthFilter(value, this.data.businessDate), // 加 businessDate }) this._loadData() } ``` ## 三、未改动项(已是设计共识) - `board-finance.ts L243 `Date.now()`** — onPageScroll 节流计时,纯 UI 行为(100ms 节流),与业务时间无关,**保留**(对齐 P20 SPEC §11.1 "操作时间戳保留 new Date()" 设计共识) - `board-customer.ts` — 0 处 `new Date()`,**无需改** - `board-coach.ts` — 0 处 `new Date()`,**无需改** - 后端 `xcx_board.py` + `board_service.py` — 服务层已接入 runtime_context,**无需改** ## 四、行为对照(沙箱模式下) | 场景 | 修改前 | 修改后 | |---|---|---| | live 模式,真实今天 = 2026-05-04(月初 4 日) | `isCurrentMonth = true`(预估提示)| 同 | | live 模式,真实今天 = 2026-05-15(月中) | `isCurrentMonth = false`(无预估) | 同 | | sandbox 切换到 2026-03-01 | `isCurrentMonth = false`(因为真实今天 = 2026-05-04 第 4 日)❌ | `isCurrentMonth = true`(基于 sandbox_date day=1 ≤ 5)✅ | | sandbox 切换到 2026-03-15 | `isCurrentMonth = false`(同上 4 日)❌ | `isCurrentMonth = false`(基于 sandbox_date day=15 > 5)✅ | | 业务时钟拉取失败 | 用 `new Date()`(降级一致)| 用 `new Date()`(降级一致)| ## 五、验证 ### 工程层 - ✅ tsc `board-finance.ts` 零编译错误(其他遗留 component / app 类型错误与本次改动无关) - ✅ getBusinessClock 已存在 `runtime-clock.ts`,接口稳定 - ✅ 降级路径(getBusinessClock 失败)保留 fallback `new Date()`,不会破坏 live 行为 ### 成果层(留 W1-T8) 按 P20 SPEC §14.3.6 走查清单,W1-T8 时: - 切 sandbox → 2026-03-01 → 进 board-finance → 经营一览 标题应显示"(预估)" - 切 sandbox → 2026-03-15 → 进 board-finance → 经营一览 标题不应显示"(预估)" - 切回 live → 行为应恢复 ## 六、commit 建议消息 ``` feat(miniprogram): board-finance isCurrentMonthFilter 接入业务时钟 (W1-T1 / P0-3) Wave 1 Day 2 看板沙箱接入。 调研修正: - xcx_board.py + board_service.py 服务层已接入 runtime_context (L264/L712) - board-customer.ts / board-coach.ts 0 处使用 new Date(),无需改 - 唯一遗漏:board-finance.ts `isCurrentMonthFilter` 用 new Date().getDate() 沙箱回放历史日期会判错"本月前 5 天预估"提示 修复: - import getBusinessClock from utils/runtime-clock - isCurrentMonthFilter 接收可选 businessDate 参数;空值降级 new Date() - data 加 businessDate: '' - onShow 拉业务时钟 + 修正 isCurrentMonth - onTimeChange 用 this.data.businessDate 参考: docs/audit/changes/2026-05-04__wave1_t1_board_sandbox_clock.md ``` ## 七、未覆盖 / 后续 - W1-T8 §14.3.6/7/8 走查时实地验证沙箱模式下三大看板行为 - 多角色身份走查(W1-T8 触发,主线提醒 Neo 切身份) - 单测覆盖留 Wave 2(`tests/board-finance/test_isCurrentMonthFilter.ts`)