交付出件箱

← 返回出件箱

开关机制 Review + C 端(家长端)模块开关方案

dev2 · 2026-08-21 · 长官三问:①家长端能不能也做成"可配置显示哪些模块"、以后新增功能不用改代码
②review 现在系统的开关套逻辑 ③C 端也要有平板端和手机端,怎么显示好看
全部结论来自物理 grep。

一、结论先行

系统里现在有两套开关写法,一好一差。
- 🟢 平板端是「注册表 + 可见列表过滤」 —— 正是长官要的那种,新增功能零改渲染逻辑
- 🔴 手机端是「一个个硬编码 &&」 —— 每加一个功能就要动 JSX

⇒ 家长端照平板端那套做,而且顺手把手机端也收敛过去。


二、开关全链路 review(四层)

第 1 层 · 存:org_brain_config 表(机构级)

enable_4l_report / enable_find_similar / enable_anti_myopia_plan / enable_eye_nav /
enable_myopia_world / enable_refractive_record / enable_peer_axial_compare /
enable_tablet_home_branding / enable_user_registration / enable_password_login /
show_expiry_countdown …

特点:一功能一列(布尔)。新增功能 = 加一列 + 改 API + 改前端。

第 2 层 · 下发:api_v1.py

换 token 时把 cfg.enable_* 逐个塞进 TokenResponse(逐字段手写,新增要改这里)。

第 3 层 · 前端消费(两种写法)

🔴 手机端(h5/chat/page.tsx)—— 硬编码

{featureFlags.enable_eye_nav && ( …抗近领航药丸… )}
{featureFlags.enable_myopia_world && ( …近视的世界药丸… )}
{featureFlags.enable_anti_myopia_plan && ( …定抗近方案… )}

每个入口一段 &&,新增功能必须改 JSX。

🟢 平板端(h5/tablet/pane/)—— 注册表驱动

// menu-sidebar.tsx:41-50 · 模块注册表
TABLET_FEATURES = [
  { id:"chat",              label:"你问我答",    icon:MessageCircleHeart },
  { id:"find_similar",      label:"同款案例",    icon:Users },
  { id:"report",            label:"报告秒读",    icon:FileText },
  { id:"consult",           label:"量身定案",    icon:ClipboardCheck },
  { id:"eye_nav",           label:"抗近领航",    icon:Compass },
  { id:"myopia_world",      label:"近视的世界",  icon:Eye },
  { id:"refractive_record", label:"视力屈光记录",icon:ClipboardList },
  { id:"about",             label:"关于",        icon:Info },
]
const items = TABLET_FEATURES.filter(f => visibleFeatures.includes(f.id));  // :72

// pane/page.tsx:121-132 · 由 flag 算出可见列表
FEATURE_GATES.filter(isVisible).map(f => f.id)

新增一个模块 = 注册表加一行 + 后端加一个开关,渲染逻辑一行不用动。

第 4 层 · 关掉之后的表现

{flag && (...)} / filter ⇒ 入口直接不渲染,不留占位、不留灰按钮。
⚠️ 有一处特例:enable_refractive_record 是 opt-in fail-closed 双门
(flag===true 且 有 seat token 才显示),与其余 fail-open 相反 —— 家长端要沿用这条更严的门。


三、家长端模块开关方案(长官问的第①件)

照平板端做,建 PARENT_FEATURES 注册表:

PARENT_FEATURES = [
  { id:"chat",          label:"你问我答",   gate:"enable_chat" },
  { id:"report",        label:"报告秒读",   gate:"enable_4l_report",   badge:"quota" },
  { id:"myopia_world",  label:"近视的世界", gate:"enable_myopia_world" },
  { id:"child_profile", label:"孩子档案",   gate:"enable_child_profile" },   // 本期新增
  // 以后新增:往这里加一行即可
]

配套三点:
1. 后台加一块「家长端模块」开关组(与现有机构开关同一个编辑弹窗,不新建页面)
2. 下发改成"列表"而不是逐字段:{"visible_features":["chat","report","myopia_world","child_profile"]}
—— 以后新增功能后端 API 也不用改(现在 api_v1.py 是逐字段手写,这是第二个硬编码点)
3. 默认值:子席位默认开 问答/秒读/近视的世界/孩子档案,其余默认关

收益:新增功能只动"注册表 + 配置项"两处,不动渲染、不动下发结构。


四、C 端要不要平板端?(长官问的第③件)

要,而且几乎白得。 平板端整套壳(h5/tablet/pane/)是注册表驱动 + 左侧菜单 + 右侧面板,
家长端只要给出自己的 visibleFeatures,同一套壳直接跑:

形态 现状 家长端怎么做
手机端 h5/chat 药丸排 + 对话区(硬编码 &&) 沿用样式,入口改注册表渲染;加"我的孩子"卡片
平板端 h5/tablet/pane 左菜单 + 右面板(注册表驱动) 直接复用壳,菜单项换成家长四项,面板里塞档案模块

关掉之后好不好看:两端都是"入口直接消失"而不是留灰按钮 —— 家长端只剩 3~4 项时:
- 手机端:药丸本来就是流式排列,少几个只是这一行短一点,不会留空洞
- 平板端:左菜单条目变少,菜单本来就按内容高度排,同样不留空
⇒ 视觉上都安全,不需要额外做"少功能时的兜底版式"。


五、要长官拍的两件

  1. 下发结构要不要改成列表(visible_features: [])? 改了以后新增功能连后端 API 都不用动;
    不改就沿用逐字段,但每次新增要改三处。我建议改。
  2. 家长端平板形态一期做不做? 复用壳成本不高,但要多验一轮。
    我建议一期只做手机端,平板端二期开(注册表在,随时能开)。

云机环境 · 非验收证据。