Files
Neo-ZQYY/docs/audit/changes/2026-05-04__wave1_t1_board_sandbox_clock.md
Neo 9eb495686f 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
2026-05-04 07:42:51 +08:00

5.7 KiB

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

改动 1:import + isCurrentMonthFilter 改造

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

data: {
  ...
  isCurrentMonth: true,
  businessDate: '',  // YYYY-MM-DD,沙箱模式下回放虚拟日期
}

改动 3:onShow 拉业务时钟 + 修正 isCurrentMonth

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

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)