交付出件箱

← 返回出件箱

新版手机端首页(家长端 P2 + 门店端 S1)· 可行性 verify 报告

2026-09-23 · 效果图:zhaoyang-home-6styles-20260921-flat1.html(设计 gpt-6-astra,组装校验 Claude)
基线:本 worktree HEAD = c6884c23(main)· origin/test 领先 1362 commit
方法:5 路并行子代理物理 grep + 主会话复核,每条结论带命令与真实输出;0 命中处均带对照组


一句话结论

两端首页在现有代码里都不存在容器(家长端和门店端目前共用同一个 /h5/chat,3412 行)。效果图 24 个区块里,11 个可直接复用、6 个需改造、7 个是从零新建;其中「今日护眼四设备手动记录」是最大的一块新工程(家长端录入 + 门店端汇总两头连锁),「眼轴百分位」卡在外部数据、不该排期。

与「二维码与端口绑定断开」(= Phase 83 批次五 / 子席位登录 v2)有真实文件级冲突:家长端首页就是 chat/page.tsx,批次五要改的 :791 :861 在同一个文件里。


一、先纠正 4 个会改变方案形状的事实

事实 1 · 家长端和门店端现在是同一个页面

/h5/chat(web/app/h5/chat/page.tsx,3412 行)既是家长端首页,也是门店坐席登录后的落地页,靠一个布尔分流:

$ grep -n "getSeatType()" web/app/h5/chat/page.tsx
1179:    setIsParentSeat(getSeatType() === "parent");

门店的"视光档案"/h5/store-refractive 只是从这个页面胶囊按钮跳进去的二级列表页(chat/page.tsx:3086-3101),它自己带门禁,不满足就 router.replace("/h5/chat")(store-refractive/page.tsx:34-105)。

→ 效果图画的两个首页,现实里一个都不存在。要做就是新建两个路由容器,不是"改现有首页"。

事实 2 · 「今日护眼情况」不是"没接数据",是整条功能都不存在,而且现有 UI 是不可达死代码

$ grep -n "TodayBand\|TodayDetailSheet\|setTodayDetailOpen" web/app/h5/chat/page.tsx
42:import { TodayBand } from "./components/today-band";
43:import { TodayDetailSheet } from "./components/today-detail-sheet";
1380:  const [todayDetailOpen, setTodayDetailOpen] = useState(false);
2595:  {false && <TodayBand onOpenDetail={() => setTodayDetailOpen(true)} />}
3308:  <TodayDetailSheet open={todayDetailOpen} onOpenChange={setTodayDetailOpen} />

# 对照组(同文件正常渲染的组件,证明查法有效)
3299:  <HistorySheet

TodayBand 被 {false && ...} 短路永不渲染;而 setTodayDetailOpen(true) 全文件只在这个死代码块里被调用过一次 → TodayDetailSheet 物理上永远打不开。today-detail-sheet.tsx(310 行)全文件 fetch 零命中,纯静态 JSX。

后端侧:
- app/models/device.py 三张表 DeviceData / DeviceTypeConfig / UserPhoneVerification,DeviceData 的 comment 明写「设备使用数据(厂商推送)」,走 device_report.py:71 POST /report + API-Key
- 全仓 grep 离焦镜|红光仪|护眼灯|读写台 在 app/models app/api 里零命中记录功能(命中的全是 AI 话术治理规则和验光单品牌下拉选项)
- 对照组:grep -rn "护眼" --include="*.py" 能查到 DeviceTypeConfig(device_type="light", display_name="护眼台灯") → 查法有效

→ 没有表、没有字段、没有 API、没有可用前端。只有一份视觉骨架可以抄。

事实 3 · 「眼轴百分位」不是"还没做",是做过又主动拆掉了

$ grep -n "@router\." app/api/find_similar.py
43:@router.post("/search")   83:@router.get("/facets")
99:@router.get("/cases/{case_id}")   135:@router.get("/image/{image_id}")

→ 历史上存在的 /peer-axial-norms 端点在当前代码里已不存在;前端 find-similar-pane.tsx:1254 注释写明「flags / peerNorms + peer-axial-norms 请求随双 tab 一并移除」;机构开关 enable_peer_axial_compare 默认 false(app/models/database.py:133),迁移注释写着「无合格人群基线前不得开」。

拆除原因写在 flywheel-progress.md:42:b3_cases 是成功案例集、不是人群样本,拿它算同龄中位数会误伤正常孩子;合格基线(门诊 5411 条历史记录清洗入库)另立 Phase,至今数据文件仍未上服务器。

→ 效果图上家长端、门店端各画了一张百分位图,这两张图背后是一个需要外部数据的独立工程,不是首页改版的一部分。

事实 4 · 「该功能需门店开通」这个弹窗,跟现网门控逻辑是相反的

$ grep -rn "该功能需门店开通\|需门店开通" web/app app
(0 命中)
# 对照组
$ grep -n "谣言粉碎机" web/app/h5/chat/page.tsx
3157: {/* Phase 75 · 机构开关 gate 谣言粉碎机入口 · 关则不渲染 */}

现网口径是 「关则不渲染」 —— 用户根本看不见这个入口,不会点到、也就不会弹窗。效果图改成了「看得见 + 点了告诉你需要开通 + 联系门店」,这是产品行为变更,不是视觉改版,需要长官单独拍板。


二、效果图 24 区块 · 逐块 verify 结果

家长端 P2(11 块)

# 区块 判定 证据 / 缺口
1 品牌头卡 ✅ 复用 enable_hero_image(database.py:147)· 现网已上线样式
2 孩子视光档案头(更新至 X) ✅ 复用 parent_patients.py /api/parent/patients/* 12 端点
3 消息通知条(门店发来解读·未读·查看) ❌ 新建 无消息表/通知 API/角标。只有 RefractiveRecord.store_conclusion_read_at(:175),且长官 9-15/16 D9 拍板「只做已读/未读,不做通知」(parent_patients.py:829)。doctor_push_log 是医生端订阅消息,不能套用
4 孩子切换 / 添加 ✅ 复用 parent_patients.py:222 列表 · :330 新增 · 前端 family/page.tsx、family/new/page.tsx
5 今日护眼情况(四设备手动记录) ❌ 全新建 见事实 2。需新表 + 录入 API + 今日汇总 API + 前端
6 赵阳博士 AI 解读卡 ✅ 复用 four_l_report.py 8 端点 · four-l-detail-sheet.tsx · gate enable_4l_report + 年度配额
7 最近一次检查(OD/OS + 较上次) 🟡 改造 字段全在 detail.eyes(family/[id]/page.tsx:2893-2929);但 delta 是前端 useMemo 自算、且只算了眼轴(:719)。度数/裸眼视力的「较上次」要补
8 趋势对比(裸眼视力/等效球镜/眼轴) 🟡 改造 家长端 tab 只有两个:useState<"records"\|"axial">(:536)。门店端 trend-chart.tsx:89 三指标齐全可抄。图表库 recharts ^3.8.0,echarts 0 命中(合规)
9 眼轴百分位 ❌ 不排期 见事实 3
10 常用功能入口(5 项) ✅ 复用 逐项见下表
11 「需门店开通」弹窗 ⚠️ 产品变更 见事实 4,需拍板

门店端 S1(13 块)

# 区块 判定 证据 / 缺口
1 品牌头卡 ✅ 复用 同上
2 「我的 / 看别人怎么做」双 tab ❌ 新建 纯前端容器
3 待办清单 4 类 🟡+❌ 字段:草稿=status='draft'(refractive_record.py:59)· 待推送=store_conclusion_text 非空且 pushed_at 空(:166,172)· 家长未读=pushed_at 非空且 read_at 空(:175)→ 3 类字段齐;但 0 个聚合列表 API(grep list_todo\|待办 app/services/refractive_record_service.py 零命中)。第 4 类「复查提醒待发送」后端整条不存在 —— 无到期字段、无发送状态,h5_chat.py:45 followup 只是 AI 生成的自由文本
4 今日数据 4 项 🟡 新端点 底层字段全有(created_at/completed_at/status);admin_dashboard.py:57 是平台全局统计(User/Org/AuthAuditLog),门店坐席维度的聚合端点 0 个
5 待跟进复查 ❌ 新建 同上,无复查调度体系
6 我最近处理的孩子 / 最近检查 🟡 改造 GET /patients 已按 Patient.updated_at DESC 排序 + 带 bound_seat 绑定状态(refractive_record_service.py:223-265);缺「结论已读/未读」字段(记录级,需 JOIN 到患者级)
7 示范档案 · 给家长演示 ✅ 复用 张思源全套在 main:模型 is_sample、403 只读拦截(:682)、跨机构可见 contract 测试(test_phase63_patients_api.py:384)
8 眼轴百分位 ❌ 不排期 同家长端
9 同款案例 ✅ 复用 find_similar.py 4 端点 + /h5/find-similar 真实页(644 真 case,非 mock)
10 家长记录汇总(四设备聚合 + 提醒未记录) ❌ 连锁新建 完全依赖家长端区块 5。家长端不做,这块就没有数据源。「提醒未记录家长」还需要通知能力(见区块 3 的 D9 拍板冲突)
11 家长连接(已绑定/待绑定/本周新增) ❌ 新端点 store_subseat.py 只有 /provision /list /{id}/remark 三个端点,无 stats;平台侧 admin_parent_seats.py:133 /stats 守门是 require_role("admin"),门店坐席调不到
12 快捷操作 4 项 🟡 改造 新建档案 ✅(store-refractive/page.tsx:257)· 绑定家长 ✅(:241)· 新增检查 ⚠️ 现在必须先进患者详情页才能点([patientId]/page.tsx:496),首页级入口需要加"选患者"中间态 · 门店海报 ✅ 后端现成(h5_store_card.py:482)但入口在 settings 页要挪
13 常用工具 8 项 ✅ 复用 逐项见下表

工具入口逐项(两端共用)

入口 机构开关(app/models/database.py) 后端 状态
视光档案 enable_refractive_record:113(默认关) refractive_records.py 19 端点 ✅
报告秒读 enable_4l_report:83(默认关) four_l_report.py 8 端点 ✅
历史解读 无开关 chat_history.py ✅
抗近领航 enable_eye_nav:88(默认开) eye_nav.py 3 端点 ✅
谣言粉碎机 enable_rumor_buster:140(默认开) h5_rumor_buster.py ⚠️ 后端模块只在 test 分支,main 上不存在(main.py:249 用 try/except ImportError 兜底跳过)
近视的世界 enable_myopia_world:89(默认开) 无(静态页 /myopia-world.html) ✅ 但不是 Next 路由,统一框架要额外适配
量身定案 enable_anti_myopia_plan:87(默认开) 内嵌问诊流程,无独立文件 ✅
关于赵阳智脑 无开关 无(静态弹层) ✅
上传检查单 OCR 无开关 parent_ocr.py:63 ✅

门控机制:后端 OrgBrainConfig → /api/seat/org-features 下发 → 前端 parent-feature-gate.ts 做「机构开关 ∩ 家长可见名单(parent_visible_features)」交集 → 条件渲染。前端隐藏 + 后端 fail-closed 双门,没有裸露漏洞。


三、与「二维码与端口绑定断开」的冲突/依赖矩阵

先说清楚我对这个说法的理解(⚠️ 需长官确认)

代码里没有任何叫「设备/端口二维码解绑」的能力。我找到的最接近的在建工作是今天 23:22 落的《子席位账号与登录体系 v2》批次五(归口 Phase 83,长官已逐条拍板 13 条):品牌码(=二维码)扫进来的家长,账号被微信身份绑死,拿不到 unionid 就彻底进不去,批次五给他们一条不依赖微信的手机号+密码通道 —— 这在口语上就是"把二维码进来的账号跟微信端的绑定断开"。

如果长官指的是别的(比如平板/门店设备与二维码的绑定),那我查到的是:
- device_epoch 只有换绑(清绑定+重置密码+踢设备,原子操作),seat_service.py:341,382,502
- 刻意不做独立"解绑":phase50-seat-wechat-openid-binding-spec:32 D4 决策原文「单独"解绑"会留缺口(旧人抢绑/新人403) → 必须解绑+改密码合并一步」
- 唯一一份"设备绑定/解绑"设计(kid-clock-binding-spec-v0.1.md 的 device_bind_record 表 + DELETE /api/h5/devices/{sn})是纯 spec,0 行代码落地(对照组:同样查法能查到 brand_code_claim.py 与 refractive_records.py 的 bind/unbind,证明查法有效)

冲突矩阵(按我的理解 = 批次五)

# 冲突点 严重度 说明
C1 同一个文件 🔴 高 家长端首页 = web/app/h5/chat/page.tsx;批次五要改 :791(密码门红线)和 :861(品牌码重授权分支)。3412 行的文件两边同时大改 = 必冲突
C2 门店端落地页也是这个文件 🔴 高 门店新首页要改"登录后落到哪" → 又回到 chat/page.tsx + 登录跳转逻辑
C3 批次五决策 11:品牌码家长点任意功能弹初始化弹窗 🟠 中 新首页每个入口都会被这个 gate 拦一道。首页交互设计必须把这个弹窗算进去,否则做完发现点哪都弹框
C4 批次五决策 4:新席位登录框只显示手机号、不给账号入口 🟠 中 影响进首页之前的那一屏。首页改版如果连登录态一起画,口径要对齐
C5 批次五红线 4:手机端与平板端是两份复制代码 🟠 中 首页改版同样踩这条 —— /h5/chat(手机) 与 /h5/tablet(平板) 两套,漏一份两端行为不一致
C6 谣言粉碎机后端只在 test 🟡 低 首页改版分支必须从 origin/test 拉(本 worktree 是 main,落后 test 1362 commit),否则新首页点它 404

依赖(必须等)

# 依赖 说明
D1 🔴 批次五硬依赖 #730-#733 先上生产 生产迁移停在 phase48a_002,seat_seq_counter 表只在 test。首页改版如果和批次五同批发版,一起被卡
D2 🟡 门店端「家长记录汇总」依赖家长端「今日护眼记录」 家长端不先做,门店端这块没有数据源
D3 ⛔ 眼轴百分位依赖门诊 5411 条历史记录清洗入库 数据文件至今未上服务器,建议直接从首页范围里摘出去

结论:不是"等它做完才能用",而是 C1/C2 要求两件事必须同分支串行做,或者由同一个人排期。并行改同一个 3412 行文件,必炸。


四、建议的实施分批(供拍板)

批 内容 后端工作量 阻塞项
批一 两端首页容器 + 已有能力重排:品牌头卡、孩子切换、最近一次检查、AI 解读、示范档案、同款案例、工具入口、快捷操作 0(纯前端) 只需等批次五让出 chat/page.tsx
批二 三个只读聚合端点:门店待办(3 类)、今日数据(4 项)、家长连接统计 小(字段全有,纯查询) 无
批三 趋势图补两条(裸眼视力/SE)+ 度数/裸眼视力的「较上次」delta 小~中 无
批四 今日护眼四设备手动记录:新表 + 录入/汇总 API + 家长端填写 + 门店端汇总 + 「提醒未记录家长」 大(本次最大块) 「提醒」功能与 D9「只做已读未读不做通知」拍板冲突,需重新拍板
批五 复查提醒体系(到期规则 + 发送状态 + 待跟进列表) 中~大 需先定义业务规则(多久复查一次、谁触发)
摘出 眼轴百分位(两端各一张图) — 卡外部数据,不排期

五、待长官拍板

# 决策点 我的建议
H1 「二维码与端口绑定断开」是否就是指 Phase 83 批次五? 需您确认,我不猜
H2 首页改版与批次五谁先谁后(都要动 chat/page.tsx) 批次五先(它已拍板 13 条、且卡着生产迁移),首页改版基于它之后的 test
H3 新首页是新建独立路由(如 /h5/home、/h5/store-home)还是改造 /h5/chat? 新建独立路由,chat 退回纯对话页 —— 冲突面最小、可灰度
H4 「今日护眼四设备手动记录」这一大块是否本期做? 建议单独立 Phase,不塞进首页改版
H5 「该功能需门店开通」弹窗 = 把关闭的功能从隐藏改为可见+提示,是产品行为变更,做不做? 建议做,但要确认哪些功能适用(全部 or 部分)
H6 「提醒未记录家长」需要通知能力,与 9-15/16 D9「只做已读未读、不做通知」拍板冲突,是否推翻 D9? 需您重新拍板
H7 眼轴百分位是否确认摘出本期? 建议摘出

六、我没验的 / 说不准的

  1. 没在真机/test 上打开过新首页 —— 本报告全部是静态代码 grep 结论,没有渲染证据
  2. 示范档案「已上生产」只验到代码在 main,没查发布记录确认生产容器真的带了它
  3. 工作量估算是相对大小,不是人天 —— 没做过任务拆解,不敢给绝对数字
  4. 「二维码与端口绑定断开」的所指是我的推断,证据链指向批次五但不排除是别的事(见 H1)
  5. 效果图的交互细节(如门店端"看别人怎么做"tab 里到底放什么)效果图上是占位页,没有内容定义
  6. 平板端 /h5/tablet 本次没有深入 verify —— 它是第三个端,若首页改版要覆盖平板,需要再查一轮

证据全部来自 5 路并行子代理 grep + 主会话复核,0 命中处均带对照组。本机为云端隔离开发机,非验收环境。