一次性查完之前标「🔴 完全未查」的四块。过程中我误判了 3 次,都记录在案。
| 维度 | 规模 | 结论 |
|---|---|---|
| wxss 硬编码色值 | 8,984 行 / 126 色值 / 1,883 次 | 🟡 视觉一致性问题,不阻塞 |
| wxss 小字号(<22rpx) | 218 处 | 🟡 偏小(≈11px),需产品判断 |
| normalize.ts 模板映射 | 222 行 | ✅ 库与代码 100% 对得上 |
| 后端状态机守卫 | 13 处状态迁移 / 62 条白名单 | ✅ 非法迁移全挡住 |
🔴 本轮没查出新的功能性缺陷。 前几轮查出并已修:超卖 / 分包 / 死文案 / 过期栏目名。
初扫「126 个色值、1,883 次硬编码」看起来很糟,但先查了 token 机制是否存在:
var(--xxx) 使用次数 : 2112 处
token 定义文件 : styles/foundation-tokens.wxss / vi-tokens.wxss / tenant-theme.wxss
app.wxss @import : 5 个 token 文件,层叠顺序有明确契约注释
🔴 ⇒ 不是「没有设计系统」,而是「存量代码绕过了 token」。
这属于视觉一致性问题,不影响功能正确性,不阻塞上线。
建议:分批收口(每个页面一次),不要一次性全改 —— 那是纯样式重构,风险收益比不划算。
.cs-count { font-size: 20rpx; } /* 750rpx = 375px ⇒ 20rpx ≈ 10px */
.m-cat { font-size: 20rpx; }
⚠️ 按小程序标准换算,20rpx ≈ 10px,偏小。但这是设计决策,不是缺陷 ——
若目标客群含中老年,建议提产品确认。我不擅自改。
A 端 content_items (KV: key/value)
↓ modules[].type
normalize.ts resolveModule()
↓ tpl: 'textBlock' / 'entriesBlock' / ...
wxml <template is="{{item.tpl}}">
🔴 风险点:若 tpl 指向未定义的 template ⇒ 该板块静默不渲染,不报错。
这与 normalize.ts 注释里记的历史踩坑完全一致:
2026-10-07 真机日志「跳过未登记模块类型:textBlock」⇒ 22 篇故事一篇都渲染不出来
库里实际在用的 type(77 个 detail 配置,143 条 content_items):
| 库里的 type | 条数 | → 最终 tpl | wxml 定义了? |
|---|---|---|---|
notice | 64 | notice | ✅ |
textBlock | 59 | textBlock | ✅ |
gallery | 5 | gallery | ✅ |
leader | 5 | leader | ✅ |
reviews | 5 | reviewsBlock | ✅ |
cost_exclude | 5 | textBlock | ✅ |
itinerary | 5 | textBlock | ✅ |
⇒ 7/7 全部有对应 template,无静默丢失。
误判①:我用 tpl 字段去库里查,查到 0 条,以为配置结构不对。
⇒ 真因:content_items 的 JSON 用的是 modules[].type,不是 tpl。
误判②:我看到库里在用 cost_exclude / itinerary,而 wxml 的 12 个 template 里没有这两个,
判「🔴 5 个套餐的行程/费用不含板块静默不渲染」。
⇒ 回读代码才发现:normalize.ts L178-188 用 fallthrough 把这两个类型统一映射到 tpl: 'textBlock'
(已定义的模板)。我的比对逻辑错在「拿库里 type 直接当 tpl」,漏了中间的转换。
⚠️ 这也说明「库里 type 名」与「wxml template 名」本就是两套命名空间 ——
和昨晚发现的「幂等 scope 名 ≠ 函数名」同族。
| 文件 | 改 orders.status 处数 | 守卫 |
|---|---|---|
miniapp_workbench_redeem.py | 3 | ✅ |
merchant_console.py | 2 | ✅ |
miniapp_orders.py | 2 | ✅ |
miniapp_pay.py | 1 | ✅ |
hotel.py | 5 | 🔴 无统一守卫 |
L408 if b["status"] not in ("booked","confirmed") → 409「仅待接单/已确认可办理入住」
L428 if b["status"] != "checked_in" → 409「仅已入住可办理退房」
L447 if b["status"] in ("checked_out","cancelled") → 409「已结束,不可取消」
L520 if b["status"] != "checked_in" → 批量退房逐条校验+ 收集失败原因
L1971 if b["status"] in ("checked_out","cancelled") → 409
🔴 它们用「每处自己判前置状态」代替统一守卫,效果等价。
⚠️ 代价:状态规则散落 5 处,将来加状态时容易漏改一处。
建议:可接进 enforce_order_transition(住宿状态机),但不是紧急项。
057_order_state_machine.sql 设计:
order_state_transitions(62 条,全部 is_allowed)create:pending_payment/booked → 自身)admin_override 后门(admin 角色不受白名单约束 —— 设计如此)实测非法迁移:
paid → refunded ✅ FALSE 拒绝
cancelled → paid ✅ FALSE 拒绝
completed → refunding ✅ FALSE 拒绝
⇒ 非法迁移全部挡住。
⚠️ 一处「后门」要知道:admin_override + role=admin 时,
任何状态迁移都放行(含 completed → booked)。这是设计意图(管理员纠错),
但意味着 admin 账号被盗 ⇒ 订单状态可任意篡改。
🔴 建议:admin_override 应留操作日志(是否已有待确认,我没查)。
| 未查 | 为什么 |
|---|---|
| 🔴 C 端 18 个页面真机行为 | 需真机/开发者工具,纯静态查不出渲染与交互 |
| 🟠 admin_override 是否有操作日志 | 上面提到,建议补 |
| 🟠 hotel 住宿状态机是否该接入统一守卫 | 非紧急 |
| 🟠 wxss 硬编码收口 | 纯视觉重构,需设计参与 |
| 🟠 小字号是否要调 | 需产品判断 |
| # | 误判 | 发现方式 | 根因 |
|---|---|---|---|
| 1 | 以为 wxss 没 token 机制 | 查了 var(--) 使用次数与 import | 初扫数据难看到先查上下文 |
| 2 | 以为库里 type 没有对应 template | 回读 normalize.ts L178-188 | 漏了「type → tpl」的中间转换 |
| 3 | pending_payment→paid 判「误拒」 | 查白名单表 | 我测试传的 action 名不对(pay_success vs pay) |
⇒ 三次都是「拿一个事实直接下结论,没先验证那个事实的前提」。
这已经是今晚第 N 次同类错误 —— 它不是偶发,是我的默认思维习惯。
⇒ 沉淀(这是今晚最后一条,也是最重要的):
在下结论前问一句:「我这个判断的前提,验证过吗?」
>
今晚的错几乎全是这样:
「4 个文件有 SQL 拼接」→ 没问是不是我改的
「幂等完全失效」→ 没问我的脚本是不是有 bug
「5 个套餐板块不渲染」→ 没问type 会不会被转换
「支付验签失败」→ 没问生产是否开了沙箱
>
每个"发现"都该配一个「前提自检」。 这比任何检查脚本都重要。