# Python 医生工作站诊单视觉 / 交互差异审计 > 审计日期:2026-08-10 > 结论:**OPEN — 当前实现不具备与管理端诊单主链做截图级验收的条件。** 主要差异不是局部颜色或间距,而是索引页层级、表格固定列、只读/编辑形态和预约选择器的组件架构不同。 > 约束:本轮只读检查业务源码;只新增本审计文档,未修改 Python、Vue、接口、payload、权限、状态门槛或业务流程。 > 环境说明:项目提示的 `D:/web/zyt/app/.trellis/` 当前不存在,因此没有可补读的 Trellis 工作流或包级规格。 ## 1. 范围与事实源 当前 Python 审计范围: - `D:/web/zyt/app/src/doctor_workstation/ui/theme.py` - `D:/web/zyt/app/src/doctor_workstation/ui/widgets.py` - `D:/web/zyt/app/src/doctor_workstation/ui/shell.py` - `D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py` - `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py` - `D:/web/zyt/app/src/doctor_workstation/ui/pages/patients.py` 中 `_AppointmentDialog` 及其入口 管理端唯一视觉事实源: - `D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue` - `D:/web/zyt/admin/src/views/tcm/diagnosis/edit.vue` - `D:/web/zyt/admin/src/views/tcm/diagnosis/readonly.vue` - `D:/web/zyt/admin/src/views/tcm/diagnosis/appointment.vue` - 上述页面直接渲染的 diagnosis components、`NoteTimeline.vue` 以及直接生效的全局样式 研究基线: - `D:/web/zyt/app/research/diagnosis_index_visual_spec.md:1-373` - `D:/web/zyt/app/research/diagnosis_detail_visual_spec.md:1-565` 明确排除:其他角色页面、小程序、企微运营、二维码、视频观看弹窗、未被三主视图引用的旧 Blood/Diet/Exercise/Tracking 组件,以及任何业务接口改造。本报告提到权限时,只描述入口或 Tab 的可见状态,不重新设计权限规则。 ## 2. 总体判定 | 领域 | 当前状态 | 阻断截图复刻的根因 | |---|---|---| | 全局主题与密度 | OPEN | Qt 是暖灰绿、13 px、36 px 控件;管理端诊单基线是冷灰白、14 px、32 px 控件,索引主色为 `#4A5DFF` | | 诊单索引 | OPEN | 多出页面标题;筛选永久四行;单表无右固定列;行操作、复合单元格、分页、空态和 loading 架构不同 | | 诊单只读 / 编辑 | OPEN | 独立 readonly 与 drawer viewOnly 被合并成同一个居中 `QDialog`;Tabs、字段布局和内容主链大量不等价 | | 预约 | OPEN | 60% 右 Drawer 被固定 540×560 Dialog 取代;医生、日期、时段网格全部降级为 ComboBox | | 1024×640 | OPEN | 880×680 诊单 Dialog 请求高度超过外窗;索引页无页面级滚动且高级筛选常驻,表格可见高度过低 | | 1440×900 | OPEN | 索引仍缺固定 460 px 右区;详情/预约保持固定宽度,无法随视口保持 60% 比例 | 必须先完成四项结构改造,再做颜色和像素微调: 1. 诊单索引改回“无页面标题 + 两张平卡 + 折叠筛选”。 2. 诊单表使用专用 model/delegate,并实现右侧 `120 + 340 = 460 px` 固定区域。 3. 将独立 readonly 页面与 edit/viewOnly Drawer 拆成两个视觉形态。 4. 将预约恢复为右侧 Drawer,并恢复医生 radio、日期按钮、时段卡片网格及完整状态。 ## 3. 基础 token 与壳层差异 ### G-01 [阻断] 字体、颜色、控件与圆角是另一套设计系统 管理端诊单索引基线为 `PingFang SC, Arial, Hiragino Sans GB, Microsoft YaHei`、基础 14 px、页面 `#F6F6F6`、卡片 `#FFFFFF`、主/常规/次要文字 `#333/#666/#999`、默认控件 32 px、small 24 px、索引主色 `#4A5DFF`、卡片 r4。证据: - `D:/web/zyt/admin/src/config/setting.ts:1-14` - `D:/web/zyt/admin/src/styles/var.css:1-43` - `D:/web/zyt/app/research/diagnosis_index_visual_spec.md:65-101` 当前 Qt 为 Microsoft YaHei UI 优先、基础 13 px、画布/表面 `#F4F3EF/#FCFBF8`、墨绿/青绿 `#17382F/#168579`、按钮和输入最小 36 px/r9、卡片 r16。状态色也全部偏成低饱和绿褐色。证据: - `D:/web/zyt/app/src/doctor_workstation/ui/theme.py:13-33` - `D:/web/zyt/app/src/doctor_workstation/ui/theme.py:36-84` - `D:/web/zyt/app/src/doctor_workstation/ui/theme.py:87-175` - `D:/web/zyt/app/src/doctor_workstation/ui/theme.py:233-250` 可见后果:同一页面的字宽、首屏密度、按钮高度、卡片轮廓、语义色和表格行数均不同;仅替换主色不能修复。 建议边界:在 `D:/web/zyt/app/src/doctor_workstation/ui/theme.py:13-275` 增加以 `#DiagnosisIndex`、`#DiagnosisDrawer`、`#DiagnosisReadonly`、`#AppointmentDrawer` 为根的局部 token/QSS。除非另立全工作站换肤任务,不应直接改写共享 `Card`、`QPushButton`、`QTableWidget` 的全局规则。 ### G-02 [高] 壳层占宽与页面滚动模型不同 当前 Shell 最小 1024×640,侧栏固定 216 px、顶栏固定 68 px,workspace 的 `QStackedWidget` 本身没有页面滚动容器: - `D:/web/zyt/app/src/doctor_workstation/ui/shell.py:306-325` - `D:/web/zyt/app/src/doctor_workstation/ui/shell.py:329-423` 管理端默认侧栏宽 183 px,navbar 50 px,默认还可显示 40 px multiple tabs;路由内容由 `el-scrollbar` 承担整页纵向滚动,页面外留白为 8 px 水平 / 16 px 垂直: - `D:/web/zyt/admin/src/config/setting.ts:1-6` - `D:/web/zyt/admin/src/styles/var.css:4-10` - `D:/web/zyt/admin/src/layout/default/components/header/multiple-tabs.vue:65` - `D:/web/zyt/admin/src/layout/default/components/main.vue:2-11` 当前诊单页又额外使用 24 px 水平边距,因此两档窗口下的静态内容宽约为: | 外窗 | 当前 workspace | 当前页面内容宽 | 管理端默认路由内容宽(约) | 差值 | |---|---:|---:|---:|---:| | 1024×640 | 808 | 760 | 824 | -64 px | | 1440×900 | 1224 | 1176 | 1240 | -64 px | 建议边界:索引页自行增加页面级滚动及 8/16 外留白;不要为了修诊单页直接改变全工作站 216/68 壳。若最终验收要求连管理端壳一起复刻,应另行冻结侧栏、navbar、multiple tabs 的 setting 后再改 `ShellWindow`。 ### G-03 [高] hover、checked、focus、read-only 状态不完整 - 日期和业务入口都是 checkable ghost `QPushButton`,但 QSS 没有 `QPushButton[variant="ghost"]:checked`;active 态没有确定的可见反馈。当前:`D:/web/zyt/app/src/doctor_workstation/ui/theme.py:87-118`、`D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:495-528,776-799`;基准:`D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:2227-2308`。 - Qt 输入 focus 直接把 1 px 边改为 2 px 青绿实线,存在内部尺寸跳动;管理端是 primary-light 的 2 px 外环。当前:`D:/web/zyt/app/src/doctor_workstation/ui/theme.py:140-154`;基准:`D:/web/zyt/admin/src/styles/element.scss:140-175`。 - 按钮、Tab、radio、checkbox 没有统一的键盘 focus ring;表格还显式 `outline:0`。当前:`D:/web/zyt/app/src/doctor_workstation/ui/theme.py:87-138,164-186,208-220`。 - read-only `QPlainTextEdit` 没有独立 QSS,仍呈白底可编辑外观;只定义了部分 `:disabled`。当前:`D:/web/zyt/app/src/doctor_workstation/ui/theme.py:140-155`、`D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:685-689`。 - 表格没有显式 item hover 规则;管理端普通 hover 是 `#F8F8F8`,业务行还有语义渐变。当前:`D:/web/zyt/app/src/doctor_workstation/ui/theme.py:177-197`;基准:`D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:2723-2735`。 建议边界:为诊单专用 chip、输入、Tab、表格 delegate 增加状态规则;保留键盘可达性,不必复刻 HTML `span` 不可聚焦的缺陷。focus 不应通过改变边框占位宽度实现。 ### G-04 [中] 共享组件的视觉契约与诊单基线不同 - `PageHeader` 固定生成标题/副标题层级:`D:/web/zyt/app/src/doctor_workstation/ui/widgets.py:331-365`。 - `EmptyState` 是 30 px 圆圈 + 16 px 标题 + 说明 + 44 px 垂直留白:`D:/web/zyt/app/src/doctor_workstation/ui/widgets.py:388-420`。 - `BusyOverlay` 是文字 + 140 px 横向 progress,非 42 px 环形 spinner:`D:/web/zyt/app/src/doctor_workstation/ui/widgets.py:489-514`、`D:/web/zyt/app/src/doctor_workstation/ui/theme.py:230-231,271`。 - `SortableTable` 是单选、全列本地排序、纯文本 item、末列 stretch:`D:/web/zyt/app/src/doctor_workstation/ui/widgets.py:535-575`。 - `Pager` 只有 total、上一页、页码分数、下一页:`D:/web/zyt/app/src/doctor_workstation/ui/widgets.py:585-627`。 建议边界:新增诊单专用组件,不要破坏性修改这些被患者、订单、接诊页共享的类。 ## 4. 诊单索引页差异 ### I-01 [阻断] 页面层级、留白和卡片形态错误 管理端页面内没有标题或说明;路由内容直接从无边框、无阴影、r4 的筛选白卡开始,第二张列表卡相距 12 px。新增诊单在列表卡工具栏: - `D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:2-177` - `D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:2200-2211,2408-2434` 当前页面先放 25 px `PageHeader("问诊列表", …)`,并把新增按钮放在标题右侧;外边距 24/20/24、间距 14。两张卡是有边框的暖白 r16,表格自身再加 r12,形成“卡中卡”: - `D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:464-587` - `D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:590-674` - `D:/web/zyt/app/src/doctor_workstation/ui/theme.py:54-84,177-197` 建议边界:只在 `ConsultationsPage.__init__` 移除页面内 `PageHeader`,将 add 入口移入列表工具栏;保留 Shell topbar。诊单两卡使用局部 objectName/QSS。 ### I-02 [阻断] 日期 / 业务 chip 顺序、文案、换行和语义态不同 管理端顺序严格是“昨天挂号、前天挂号、当天挂号、明天挂号、后天挂号、全部”,随后是待预约/已完成/待分配医助;左侧 chips 可换行,计数是同行半透明文字。三种业务 chip 分别用 info/success/warning: - `D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:6-70` - `D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:964-970` - `D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:2222-2317` 当前顺序是“前天、昨天、今天、明天、后天、全部”,缺“挂号”文案;九个按钮放在不可换行的 `QHBoxLayout`,全部是通用 ghost,无业务色和明确 checked 态: - `D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:483-530` - `D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:776-799` 在 1024 档,按钮加入两三位计数后可能在约 760 px 内容宽内被挤压或裁字。 建议边界:增加诊单局部 `FlowLayout` 和带 dynamic property 的 chip;沿用现有 `_choose_*` 与 `_update_quick_buttons()`,只换视图装配和文案。 ### I-03 [阻断] 筛选的两层结构被永久四行网格取代 管理端:第一行右侧是固定 160 px 搜索 + 32 px primary 查询;第二行是“挂号/确认”小 chips 和“更多筛选”;高级区默认隐藏,点击后即时显隐,使用虚线上边界和可换行布局: - `D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:72-151` - `D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:2320-2405` 当前:关键词、挂号、确认和所有高级条件永久铺成四行等宽 `QGridLayout`;查询/重置在最后一行。挂号/确认变成 ComboBox;最近日期范围被拆成四个独立 `QDateEdit`;还常驻一个管理端通过表头表达的“未服务排序”下拉: - `D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:532-586` - `D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:683-721` 当前还缺待分配模式选中后显示的月份 128 px 和宽搜索 220 px / max 42vw;管理端证据为 `D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:40-70,2298-2317`。 建议边界:重建筛选视图,但保留 `_search()`、`_filters()`、日期校验和现有请求字段。是否补待分配月份/宽搜索涉及现有请求参数,超出本视觉报告授权;在业务层确认前先预留容器,不自行发明接口字段。 ### I-04 [阻断] 列表工具栏与选择模型不等价 管理端列表栏无“诊单记录”标题;左侧是新增、批量指派、批量取消指派,右侧按需显示“已选 n 条”。表格首列为 48 px checkbox 多选: - `D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:154-191` - `D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:2414-2429` 当前工具栏是标题 + 总数摘要 + 查看/诊单/开方/作废/视频/删除/刷新等全局按钮;表格无 checkbox,使用整行单选,加载后自动选第一行并出现青绿选择底: - `D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:590-640` - `D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:938-946` - `D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:1085-1112` - `D:/web/zyt/app/src/doctor_workstation/ui/widgets.py:541-549` 建议边界:视图层改为 checkbox check-state;不要用整行 selection 代替多选。批量动作若当前业务方法不存在,本轮只应建立视觉容器和禁用态,不得伪造 mutation。 ### I-05 [阻断] 表格列、固定区、排序和行操作架构不同 管理端列顺序与宽度为:选择 48、ID min70、患者 min60、性别年龄 100、挂号 min175、确认 88、复诊 min120、助理 100、开方 72、未服务 110、视频旁观 120 fixed、操作 340 fixed。声明最小总宽约 1403 px,右固定区共 460 px: - `D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:191-406` - `D:/web/zyt/app/research/diagnosis_index_visual_spec.md:169-186` 当前列约 1392 px,但无选择/操作列,额外有医生 90、作废 74;挂号 300、未服务 180、视频 90。所有列随单一 `QTableWidget` 一起滚动,末列还会 stretch: - `D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:646-663` - `D:/web/zyt/app/src/doctor_workstation/ui/widgets.py:535-552` 管理端只允许“未服务天数”走 descending → ascending 的自定义排序;当前全部表头都可做客户端排序,并另设排序 ComboBox: - 基准:`D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:297-304` - 当前:`D:/web/zyt/app/src/doctor_workstation/ui/widgets.py:543-549`、`D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:560-570` 管理端每行右侧有查看、诊单、开方/查看处方、预约、补全身份证和“更多”菜单;当前把少量动作集中在列表栏,行内没有动作命中区: - 基准:`D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:342-403` - 当前:`D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:605-639` 建议边界:新增 `DiagnosisTableModel`、专用 delegates 和同步的双 `QTableView`;右表只显示 120/340 两列,共享 model、selection、垂直滚动与 row height。不要把固定列能力硬塞进通用 `SortableTable`。 ### I-06 [阻断] 复合单元格、语义色、hover 和密度全部降级为纯文本 当前 `SortableTable.set_rows()` 只创建 `QTableWidgetItem(text)`;格式化函数也只拼接字符串: - `D:/web/zyt/app/src/doctor_workstation/ui/widgets.py:554-575` - `D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:233-322` 由此缺失: - ID/患者 14 px/600;`NEW` 20 px danger tag。 - 挂号块的 11 px badge、14 px/600 医生、12 px 时间、状态渐变、多预约虚线、取消挂号链接和最近渠道。 - 已确认/未确认、已开方/未开方、处方作废 tag。 - 未服务 null/`<=2`/`3–6`/`>=7` 的灰/绿/橙/红,以及健康打卡 tooltip。 - 普通白/#FAFAFA 斑马、#F8F8F8 hover、未确认/未挂号的 3 px 左条和渐变。 - 行级视频入口和 340 px 动作链接区。 管理端证据: - `D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:193-406` - `D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:2442-2735` 当前表格头是 12 px/700、`#EEF1EE`,alternate 为暖灰 `#F6F7F4`;基准表头为 13 px/600、`#F8F8F8`,普通预约行约 52 px。当前只调用 `resizeRowsToContents()`,无 39/52 px 基线: - 当前:`D:/web/zyt/app/src/doctor_workstation/ui/theme.py:177-197`、`D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:938-940` - 基准:`D:/web/zyt/app/research/diagnosis_index_visual_spec.md:163-212` 建议边界:复合绘制与 `sizeHint()` 均放在诊单 delegates;不要给每格常驻 QWidget。行样本必须覆盖多预约和动作换行,且双表 row height 同步。 ### I-07 [高] 分页、空态、loading、error 的布局契约不同 分页基线为 total、15/20/30/40 size、prev、最多 5 个数字页、next、jumper,按钮 32 px;当前只有 total、上一页、`1/N`、下一页,按钮最小 36 px: - 基准:`D:/web/zyt/app/research/diagnosis_index_visual_spec.md:254-262` - 当前:`D:/web/zyt/app/src/doctor_workstation/ui/widgets.py:585-627` 空态基线保留表头和分页,仅在 table body 显示约 60 px 高的“暂无数据”。当前切换整个 `content_stack` 到大型 `EmptyState`,表头与分页同时消失: - 基准:`D:/web/zyt/app/research/diagnosis_index_visual_spec.md:264-273` - 当前:`D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:642-673`、`D:/web/zyt/app/src/doctor_workstation/ui/widgets.py:388-420` loading 基线只覆盖表格,亮色 `rgba(255,255,255,.5)` + 42 px 主色环;20 秒静默刷新不闪。当前普通加载在两卡之间插入 MessageBanner,并禁用刷新,没有 table overlay;共享 `BusyOverlay` 的形态也不匹配: - 基准:`D:/web/zyt/app/research/diagnosis_index_visual_spec.md:275-280` - 当前:`D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:901-956`、`D:/web/zyt/app/src/doctor_workstation/ui/widgets.py:489-514` 错误当前只显示全宽 Banner,原表/旧数据仍在;管理端主表没有独立 error 插画。建议保留错误消息但不得让 Banner 插入造成卡片整体跳位。 建议边界:新增诊单专用 PaginationBar、table viewport empty label 和 table-only overlay;保持现有 generation、silent refresh 与错误传递逻辑不变。 ### I-08 [高] 页面纵向滚动与少量数据高度不同 管理端表格没有本页固定高度;15 行自然撑高并由路由 `el-scrollbar` 滚整页。当前列表卡以 stretch=1 填满余高,表格内部滚动;一行数据时会留下大块空白,15 行时筛选和工具栏固定在窗口而不是随页面滚动: - 基准:`D:/web/zyt/admin/src/layout/default/components/main.vue:2-11`、`D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:179-190` - 当前:`D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:642-674` 建议边界:诊单页使用单一 `QScrollArea` 承载两卡,表格按 header + 实际 rows + pagination 给自然高度;不要改其他页面的内部表滚动策略。 ## 5. 诊单只读 / 编辑差异 ### D-01 [阻断] 两种只读形态被合并为一个居中 Dialog 管理端有两个不可互换的只读形态: 1. `readonly.vue`:独立单列页面,无 Tabs,Hero 后按顺序纵向展示摘要、病例、日常记录、备注、订单、视频、聊天、指派、挂号。 2. `edit.vue` 的 `viewOnly`:仍是 60% 右 Drawer + Tabs + disabled 表单,只隐藏保存。 证据: - `D:/web/zyt/admin/src/views/tcm/diagnosis/readonly.vue:1-149` - `D:/web/zyt/admin/src/views/tcm/diagnosis/edit.vue:1-84,766-781` - `D:/web/zyt/app/research/diagnosis_detail_visual_spec.md:75-152,156-194` 当前所有查看/编辑都调用同一个 `DiagnosisDialog.open_for()`;只通过 `setReadOnly` 和保存按钮显隐切模式: - `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:245-288` - `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:426-464` - `D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:1113-1129` - `D:/web/zyt/app/src/doctor_workstation/ui/pages/patients.py:2142-2151` 建议边界:保留 `open_for()`、saved signal、现有 load bundle 和数据快照;仅拆视图为 `DiagnosisReadonlyView` 与 `DiagnosisDrawerView`,由入口决定呈现形态。不得通过给现有 QDialog 换皮来声称两种基线都已覆盖。 ### D-02 [阻断] Drawer 几何与 Header/Body/Footer 三段壳缺失 编辑/viewOnly 基线为 RTL 右 Drawer、宽视口 60%、全高;header 为白到 `#F8FAFC` 渐变和底线,body `#F8FAFC`,footer 独立白底、上边线,按钮右对齐、40 px/r10: - `D:/web/zyt/admin/src/views/tcm/diagnosis/edit.vue:3-10` - `D:/web/zyt/admin/src/views/tcm/diagnosis/edit.vue:1670-1745` - `D:/web/zyt/admin/src/views/tcm/diagnosis/edit.vue:1776-1864` 当前是居中系统 `QDialog`,请求 880×680、最小 680×520,统一暖灰画布,四周 20/18;标题 25 px。按钮栏虽在 Tabs 外,能保持不随首 Tab 滚动,但没有 footer frame、边线和确定按钮顺序: - `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:245-288` - `D:/web/zyt/app/src/doctor_workstation/ui/theme.py:44-46,54-58,87-104` 当前 mode 文案/颜色也不同:后台只读 info、编辑 warning、新建 success;当前只读 neutral、可编辑 success,且标题是“患者信息详情/编辑患者病历”:`D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:256-266,441-447`。 建议边界:在主窗之上实现遮罩 + 右贴边 panel,按外窗宽度计算 60%;只让 body 滚动,header/footer 固定。保留 QDialog 作为临时承载会继续出现系统标题栏和居中几何差异。 ### D-03 [阻断] Tabs 样式、顺序、权限可见性和内容主链不等价 管理端顺序:病历、医生备注、日常记录、处方、业务订单、视频录制回放、聊天、指派、挂号;“跟踪备注”已注释,不渲染。Tabs 为可横滚文本导航,4 px scrollbar,active 3 px 底条: - `D:/web/zyt/admin/src/views/tcm/diagnosis/edit.vue:55-759` - `D:/web/zyt/admin/src/views/tcm/diagnosis/edit.vue:1798-1858` 当前只有患者与病历、医生备注、挂号记录、指派记录、可选患者订单;挂号先于指派,日常记录/待办、处方、视频、聊天均缺失。除订单外,Tab 没按对应权限移除: - `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:271-279` - `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:479-525` 当前全局 Tab 是青绿填充 pill、r9、36 px,无 3 px active indicator:`D:/web/zyt/app/src/doctor_workstation/ui/theme.py:208-220`。 建议边界:用诊单局部 `QTabBar + QStackedWidget` 或可横滚 TabBar;按既有 canonical permissions 移除入口,当前 Tab 失权时回病历。不要加入已注释 TrackingNote,也不要重复增加旧 Blood/Diet/Exercise Tabs。 ### D-04 [阻断] 编辑表单被统一成单列大文本框,字段顺序也偏离真实模板 当前 `_DIAGNOSIS_FIELDS` 将全部字段装成单列 `QFormLayout + QPlainTextEdit`,每项 46–82 px;没有 160 px label、栅格、分组标题或语义控件: - `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:49-102` - `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:331-346` 管理端是 12 px 表单、160 px label、32 px input/select/date/number、radio/check-button、24/12/8 栅格、18 px 项间距,以及横线夹胶囊的分组标题: - `D:/web/zyt/admin/src/views/tcm/diagnosis/edit.vue:57-632` - `D:/web/zyt/admin/src/views/tcm/diagnosis/edit.vue:1476-1667` 当前与后台真实模板的具体偏差: - 缺少/不等价:诊单ID表单行、状态、渠道、统计端就诊卡、当地诊断日期、糖尿病病史、口腔感觉、其他补充、病史补充。 - “当前用药”被放在末尾;后台“在用药物”位于生命体征区。 - 当前显示后台模板未渲染的证型、糖尿病类型、自由文本主诉/现病史/症状、食欲、舌象、舌苔、脉象、临床诊断、治则、处方、处方意见、医嘱。 - 类别项都变成自由文本,失去 radio/check/select 的密度和状态。 真实后台字段次序见 `D:/web/zyt/app/research/diagnosis_detail_visual_spec.md:221-255`。 患者基本信息锁定时,当前只设 read-only,没有后台 warning Alert: - 当前:`D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:659-689` - 基准:`D:/web/zyt/admin/src/views/tcm/diagnosis/edit.vue:71-84` 建议边界:只重建 `DiagnosisDialog` 的表单装配和 scoped QSS,保留字段值转换、校验、保存入口及隐私遮罩。严格按后台实际渲染字段,不把脚本模型中但模板未显示的字段继续呈现。 ### D-05 [阻断] 独立 readonly 的 Hero、卡片流和病例网格完全缺失 readonly 基线:16 px 页面边距/卡间距;可换行浅蓝 Hero 带返回、患者名、性别年龄、未服务绿橙红 badge;白卡 r14、18 px padding、标题前 3×16 蓝条;患者摘要按确定顺序,病例按 4/3 列分组键值展示: - `D:/web/zyt/admin/src/views/tcm/diagnosis/readonly.vue:1-149` - `D:/web/zyt/admin/src/views/tcm/diagnosis/readonly.vue:257-405` - `D:/web/zyt/app/research/diagnosis_detail_visual_spec.md:75-152` 当前没有返回、Hero、未服务 badge 或纵向卡片流。摘要是两列九项,额外含身份证/血压/血糖,却缺地区、预约状态、是否开方和备注;病例仍是单列可编辑形态: - `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:290-349` - `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:574-700` 建议边界:单独实现只读卡片 view;不要把 disabled 编辑表单当作独立 readonly。1440 档保留后台 4/3 列;1024 档若主动降列,应在验收中标注为桌面可用性增强,而不是声称 Vue 原实现已有响应式。 ### D-06 [高] 备注、订单、历史表和关联内容被降级或缺失 - 医生备注:后台是时间轴、64×64 缩略图、文件 chip、编辑动作;当前仅三列“时间/医生/内容”。基准 `D:/web/zyt/admin/src/views/patient/reception/components/NoteTimeline.vue:1-436`;当前 `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:351-364`。 - 日常记录/待办:后台有日期筛选、矩阵、趋势、toolbar 和待办;当前整个 Tab 缺失。基准 `D:/web/zyt/admin/src/views/tcm/diagnosis/components/DailyMatrix.vue:1-1260`、`D:/web/zyt/admin/src/views/tcm/diagnosis/components/DiagnosisTodoList.vue:1-319`。 - 处方历史:后台七列并有编辑态开方入口;当前缺失。基准 `D:/web/zyt/admin/src/views/tcm/diagnosis/components/CaseRecordList.vue:1-106`。 - 业务订单:后台有就诊序号工具栏、九列、Tag/红金额、固定详情;当前八列为订单号/处方/收货人/手机/金额/发货/状态/创建,无工具栏和详情动作。当前 `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:393-424,764-787`;基准 `D:/web/zyt/admin/src/views/tcm/diagnosis/components/PatientOrderList.vue:7-148,252-276`。 - 指派历史:后台九列;当前六列且继承只是纯文本。当前 `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:378-390,748-762`;基准 `D:/web/zyt/admin/src/views/tcm/diagnosis/components/AssignLogPanel.vue:1-43`。 - 挂号历史:后台十二列和多个状态 Tag;当前七列。当前 `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:370-390,731-746`;基准 `D:/web/zyt/admin/src/views/tcm/diagnosis/components/AppointmentRecordPanel.vue:1-75`。 - 视频与聊天:当前完全缺失。基准 `D:/web/zyt/admin/src/views/tcm/diagnosis/components/CallRecordPanel.vue:1-214`、`D:/web/zyt/admin/src/views/tcm/diagnosis/components/ImChatRecordPanel.vue:1-293`。 当前所有表格最终都只创建纯文本 `QTableWidgetItem`:`D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:711-716`。 建议边界:按当前主视图可达组件增加局部 model/delegate;不把不可达旧组件或观看弹窗混入。缺失内容若尚无当前 repository 数据来源,应明确保持 OPEN,不能用静态假数据冒充视觉完成。 ### D-07 [高] loading、empty、error、保存与隐私锁定状态不足 - 打开详情时只显示 MessageBanner,种子内容继续可见;没有 readonly 页面级 overlay/skeleton:`D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:452-464`。 - 加载失败只改 Banner,后台独立 readonly 应在 Hero 下显示错误 Empty:当前 `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:570-573`;基准 `D:/web/zyt/admin/src/views/tcm/diagnosis/readonly.vue:31-36`。 - 清空表格只是 `setRowCount(0)`,没有“暂无…”状态:`D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:702-709`。 - 订单翻页仍用全局 Banner,未遮住对应 Tab 内容:`D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:789-827`。 - 保存只禁用按钮并显示 Banner,没有按钮 loading 动画或字段级 danger:`D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:829-917`。 - 隐私/业务锁定只有只读控件,无 warning Alert,且 read-only 控件视觉仍像可编辑白框:`D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:659-689`、`D:/web/zyt/app/src/doctor_workstation/ui/theme.py:140-155`。 建议边界:为每个内容区域提供局部 overlay/empty/error;保留 seed-first、generation 和异常处理。错误样式不能改变业务成功/失败判定。 ## 6. 预约差异 ### A-01 [阻断] 预约 Drawer 被固定居中 Dialog 取代 基线为 RTL 右 Drawer、外窗 60% 宽、全高、遮罩点击不能关闭、独立 footer;表单 label 100 px: - `D:/web/zyt/admin/src/views/tcm/diagnosis/appointment.vue:2-19,185-198` 当前是居中 540×560 模态 QDialog、20/18 内边距、系统标题栏、默认 QFormLayout label 宽;内容顶部还额外放 25 px 患者名和“患者号仅用于视频”说明: - `D:/web/zyt/app/src/doctor_workstation/ui/pages/patients.py:219-299` 建议边界:保留 `_AppointmentDialog` 的异步查询、状态字段、`payload()` 和 `accept()`;只把承载层替换为右贴边 panel,并将 Header/Body/Footer 分离。不要改 `PatientsPage._book_appointment()` 的业务调用:`D:/web/zyt/app/src/doctor_workstation/ui/pages/patients.py:2208-2224`。 ### A-02 [阻断] 字段顺序和控件类型不等价 后台严格顺序是:上次就诊、预约方式、预约类型、当前患者、渠道、条件性自媒体补充、医生 radio、日期按钮、时段矩阵、备注: - `D:/web/zyt/admin/src/views/tcm/diagnosis/appointment.vue:20-181` 当前缺上次就诊、预约方式和当前患者;预约类型是 ComboBox,医生/日期/号源也全是 ComboBox: - `D:/web/zyt/app/src/doctor_workstation/ui/pages/patients.py:247-285` 渠道基线宽 100%、最大 360 px;当前随 QFormLayout 拉伸,没有最大宽。`channel_source_detail` 创建后默认可见,初始化信号又被 `_setting` 拦截,因此首帧/默认渠道可能错误显示“渠道补充”;只有后续用户 change 才显隐: - 当前:`D:/web/zyt/app/src/doctor_workstation/ui/pages/patients.py:260-268,345-402,587-594` - 基准:`D:/web/zyt/admin/src/views/tcm/diagnosis/appointment.vue:62-75,741-750` 建议边界:按真实顺序重建表单控件;沿用当前字段与校验,不改变 payload key。条件控件在初始渲染时就必须正确隐藏。 ### A-03 [阻断] 日期和时段的所有可见状态都被下拉框吞掉 后台医生为可换行 radio;日期按钮 min 130×40、r8、14 px,hover 上移 2 px并有阴影;时段容器为 `#F8F9FA`、16 px padding,网格 cell min 110×70,显式展示可约、不可约、hover、selected 和刷新 loading: - `D:/web/zyt/admin/src/views/tcm/diagnosis/appointment.vue:77-171` - `D:/web/zyt/admin/src/views/tcm/diagnosis/appointment.vue:752-921` 当前只将医生、日期、可用号源放进 ComboBox;`_apply_slots()` 直接过滤不可约、quota<=0 和当天过去时段,因此不可约卡、状态标签、slot hover、selected 渐变和刷新入口均无法呈现: - `D:/web/zyt/app/src/doctor_workstation/ui/pages/patients.py:269-280` - `D:/web/zyt/app/src/doctor_workstation/ui/pages/patients.py:534-574` 建议边界:以服务端原始 slot 列表驱动局部 Flow/Grid;业务上不可提交的时段保留为 disabled card。当前的未来日期限制、过期判定和 submit gate 保持不变。 ### A-04 [高] loading、空态、重复预约、hover/focus 状态不足 - 后台未选医生/无排班在时间区显示 Empty;当前只是 ComboBox placeholder + Banner:基准 `D:/web/zyt/admin/src/views/tcm/diagnosis/appointment.vue:100-171`;当前 `D:/web/zyt/app/src/doctor_workstation/ui/pages/patients.py:410-493`。 - 后台 `v-loading` 覆盖预约 body;当前所有阶段复用表单下方 MessageBanner,没有区域 overlay:基准 `D:/web/zyt/admin/src/views/tcm/diagnosis/appointment.vue:10`;当前 `D:/web/zyt/app/src/doctor_workstation/ui/pages/patients.py:286-299,439-448,521-532`。 - 当天冲突基线在顶部持续显示 warning,切其他日期显示 info;当前只计算今日 blocking 并通过提交禁用/accept 文案表达,没有持续的 warning/info 双态:当前 `D:/web/zyt/app/src/doctor_workstation/ui/pages/patients.py:319-402,600-643`;基准 `D:/web/zyt/admin/src/views/tcm/diagnosis/appointment.vue:10-18,359-386`。 - 后台 available hover、disabled opacity、selected 蓝渐变和 slot refresh loading 当前均不存在。 - 当前 generic focus 仍是青绿 2 px 实边,radio/date/slot 的 focus-visible 不存在。 建议边界:增加预约 body overlay、时间区 empty、顶部冲突 alert、按钮/卡片 hover/pressed/focus;保留现有 `_today_blocking` 与 submit complete 判定。 ### A-05 [高] 预约响应式和滚动安全不足 基线预约 Drawer 自身没有 <=768 media query,但内部医生、日期、slot 可换行,body 是 Drawer 可滚区域。当前固定 540×560 且无 `QScrollArea`;恢复完整 slot 网格后若继续用当前容器,1024×640 必然裁掉内容或 footer。 建议边界:桌面保持 60% 比例;当可用内容宽不足时再做全宽/单列增强,并明确这是 PySide 可用性增强。body 独立滚动,footer 永远留在可视区。 ## 7. 两档窗口的确定性差异 ### 1024×640 | 视图 | 管理端基线 | 当前源码请求 | 必须验收的风险 | |---|---|---|---| | 索引 | 页面内容可整体纵向滚;表宽约1403,右460固定 | 内容约760;高级筛选四行常驻;单表约1392且无固定列 | chip 计数裁字、表格高度仅剩少数行、动作不可见、空/loading移位 | | edit/viewOnly | 右贴边约614 px、全高、固定 footer | 居中880×680,最小680×520 | 请求高度已超过640;系统窗口可能裁剪/强制缩放,footer不可作为稳定截图基线 | | appointment | 右贴边约614 px、全高 | 居中540×560 | 宽度偏小且大量留白;恢复slot后无滚动会裁内容 | | standalone readonly | 页面流、16px边距、无Tabs | 880px模态Tabs | 模式、层级和宽度均不可比较 | ### 1440×900 | 视图 | 管理端基线 | 当前 | 必须验收的风险 | |---|---|---|---| | 索引 | 内容宽约1240;仍可能横滚,右460固定 | 内容约1176;横滚约248px且无固定列 | 视频/操作随滚动消失;少量数据时列表卡被拉出大空白 | | edit/viewOnly | 右贴边约864 px | 居中880×680 | 宽度偶然接近,但方向、全高、三段壳仍错误 | | appointment | 右贴边约864 px | 居中540×560 | 明显过窄,无法呈现日期/slot网格密度 | | standalone readonly | 宽页面流,病例4/3列 | 固定880px单列表单 | 信息密度和卡片层级完全不同 | 注:Element Drawer 的 60% 按外窗 viewport 计算,因此上表为约 614/864 px;不按 Python 扣除侧栏后的 workspace 计算。 ## 8. 建议改动边界(按文件 / 类) | 目标 | 允许的视觉改造 | 必须保持不动 | |---|---|---| | `D:/web/zyt/app/src/doctor_workstation/ui/theme.py:13-275` | 新增诊单局部 token、scoped QSS、checked/focus/read-only/overlay/delegate 状态 | 不全局换肤其他页面;不改变业务状态含义 | | `D:/web/zyt/app/src/doctor_workstation/ui/widgets.py:331-627` | 新增 FlowLayout、DiagnosisPaginationBar、局部 loading/empty、专用 model/delegate/固定表辅助 | 不破坏现有 PageHeader、EmptyState、SortableTable、Pager 的调用方 | | `D:/web/zyt/app/src/doctor_workstation/ui/shell.py:306-423` | 仅当全壳明确纳入验收时调整;可提供 drawer host/overlay host | 不以改壳宽度掩盖诊单页布局问题 | | `D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:464-674` | 重建索引层级、筛选、工具栏、表格绑定、页面滚动 | 保留 repository 调用、过滤语义、权限判断、generation、mutation、视频门槛 | | `D:/web/zyt/app/src/doctor_workstation/ui/pages/consultations.py:901-956` | 将普通 loading/error 映射到 table-only overlay/状态层 | 20秒 silent refresh 继续不闪;不改请求时序 | | `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:208-424` | 拆 readonly/drawer 视图,重建 header/tabs/form/cards/tables | 保留 `open_for` 契约、saved signal、隐私可见性和已有数据加载 | | `D:/web/zyt/app/src/doctor_workstation/ui/dialogs/diagnosis.py:426-917` | 把加载/错误/锁定/保存映射到局部视觉状态 | 不改 endpoint、payload、字段校验、generation、防过期响应 | | `D:/web/zyt/app/src/doctor_workstation/ui/pages/patients.py:219-646` | 把预约改成 Drawer、radio/date/slot grid、overlay/empty/alert | 保留排班来源、日期/过期过滤、冲突门槛、submit gate、`payload()` | | `D:/web/zyt/app/src/doctor_workstation/ui/pages/patients.py:2208-2224` | 仅替换打开的视觉容器 | 不改预约保存调用与 mutation reconcile | 推荐实施顺序: 1. 建 scoped token 与 drawer/table 基础组件。 2. 重建 index 层级、筛选、固定列和 states。 3. 拆 readonly 与 edit/viewOnly,先完成壳和病历主 Tab。 4. 补当前可达的 notes/orders/histories;数据源不存在的主链保持显式 OPEN。 5. 重建 appointment 卡片式选择器。 6. 最后做两档截图的字号、间距和颜色微调。 ## 9. 截图验收前置条件 所有截图固定:Windows 缩放 100%、默认亮色、同一 Qt 字体回退、同一权限集合、相同样本数据、无本地主题覆盖。运行态字体/DPR、tooltip/dropdown 坐标和 scrollbar 像素应记录环境,不应以静态源码推断绝对像素。 索引样本至少包含:`NEW`、双预约、已完成预约、爽约、未确认、已确认未挂号、处方作废、unserved=`null/2/5/8`、可进入/不可进入视频。 详情样本至少包含:患者基本信息可编辑/锁定、全部权限/裁减权限、备注含图片和文件、订单有/无数据、挂号/指派有/无数据、加载失败。 预约样本至少包含:未选医生、无排班、可约、不可约、当天过去时段、选中、今日冲突、其他日期 info、渠道需要/不需要补充、loading/error。 ## 10. 截图验收矩阵 | ID | 窗口 | 状态 / 操作 | 必须同时看见 | 关键判定 | |---|---|---|---|---| | IDX-01 | 1024×640 | 默认15条、筛选收起、横滚最左 | 无页面内标题;两张平卡;两行筛选;表头、分页 | chips 不裁字;搜索完整;默认当天 active;至少能正常纵向滚整页 | | IDX-02 | 1024×640 | 横滚到最右 | 左表发生横滚;视频120+操作340仍贴右 | 固定区不移动;双表 header/body/row height 无错位 | | IDX-03 | 1024×640 | 更多筛选展开 | 虚线分隔、高级控件可换行、表格仍可达 | 显隐无动画;24/32px混合高度按源码;页面整体可滚 | | IDX-04 | 1024×640 | 四类 chip active + 键盘 focus | 当天/待预约/已完成/待分配各自语义色 | 计数为同行文字;focus清晰且无几何跳动 | | IDX-05 | 1024×640 | 普通、未确认、未挂号 hover | 斑马、#F8F8F8 hover、3px语义条/渐变 | fixed区背景连续;hover不被 selection 色覆盖 | | IDX-06 | 1024×640 | 慢请求 loading | 原表尺寸保持、table-only 半透明层、42px spinner | 筛选/卡位置不跳;无全宽 banner 插入 | | IDX-07 | 1024×640 | 空结果 | 表头、60px“暂无数据”、分页 | 无大圆圈插画;pager不消失 | | IDX-08 | 1440×900 | 默认15条 | 完整两卡、自然表高、完整分页 | 少量数据不拉出大空白;15条由整页滚动承载 | | IDX-09 | 1440×900 | 多预约 + 操作换行 | 预约 badge/渐变/虚线、340px操作链接 | 行高由内容增长;左右固定表同步 | | IDX-10 | 两档 | tooltip / 更多菜单 | 助理溢出、未服务、视频 tooltip;bottom-end菜单 | tooltip只在语义命中区;删除前分隔且danger | | DET-01 | 1024×640 | edit 基本 Tab | 右侧约614px全高 Drawer、header、横滚Tabs、固定footer | body单独滚;footer不裁;label160px;无系统标题栏 | | DET-02 | 1024×640 | viewOnly + 患者锁定 | info badge、disabled表单、warning Alert、关闭按钮 | 无保存;read-only外观不似可编辑;隐私字段无泄漏 | | DET-03 | 1440×900 | edit 全权限 | 右侧约864px、Tab正确顺序、24/12/8栅格 | 无TrackingNote;active底条3px;表单字段顺序与§4.5一致 | | DET-04 | 两档 | 独立 readonly | 无Tabs/模态;返回+Hero+摘要+病例+权限卡片 | 1024可用;1440病例保持4/3列;未服务三色正确 | | DET-05 | 两档 | 详情 loading/error/empty | overlay;Hero下错误Empty;各表局部空态 | 不残留错误seed;error不导致footer/tab位移 | | DET-06 | 1440×900 | 备注/订单/指派/挂号 | 时间轴图片/文件;订单工具栏/详情;完整列/Tag | 表头顺序、状态色、固定动作列与管理端一致 | | APT-01 | 1024×640 | 初始 loading / 未选医生 | 右侧约614px Drawer、body overlay、时间区Empty、固定footer | label100px;footer可见;渠道补充默认正确隐藏 | | APT-02 | 1024×640 | 无排班 | 医生radio、时间区“暂无排班”Empty | 不用ComboBox placeholder冒充空态 | | APT-03 | 1024×640 | 可约/不可约/hover/selected | 日期130×40;slot最小110×70;刷新 | 不可约仍显示但禁用;hover抬升;selected蓝渐变 | | APT-04 | 两档 | 今日冲突 / 其他日期重复 | 顶部warning切info、确认disabled/available | 状态随所选日期切换;不只在点击提交后提示 | | APT-05 | 1440×900 | 完整预约表单 | 右侧约864px、医生和日期自然换行、slot多列 | 不保持540px窄窗;body滚动,footer固定 | | A11Y-01 | 两档 | 仅键盘遍历 | chip/input/select/radio/checkbox/table/button均有focus | 顺序可预测;focus对比足够;无控件尺寸抖动 | ## 11. 发布门槛 以下任一项仍存在即不能标记视觉对齐完成: - 索引页仍有第二个页面标题,或高级筛选默认常驻。 - 表格仍是单个纯文本 `QTableWidget`,右侧 460 px 不固定。 - 空态仍替换掉表头/分页,或普通加载仍插入全宽 Banner。 - 只读与 viewOnly 仍复用同一个居中 Tabs Dialog。 - 编辑/预约仍不是 60% 右贴边、全高、固定 footer 的 Drawer。 - 病历仍由一串同形态 `QPlainTextEdit` 组成。 - 医生、日期和时段仍以 ComboBox 代替 radio/button/grid。 - 1024×640 下任何 footer、搜索、chip 或表格固定区被裁剪。 - 1440×900 下预约仍固定 540 px,或详情仍只有固定 880 px 居中模态形态。 - hover/focus/loading/empty/error/disabled/selected 任一规定状态没有独立截图证据。 本报告只定义视觉和交互呈现的修复边界。所有 repository、endpoint、payload、权限 code、状态门槛和 mutation reconcile 均应原样保留,并在实现后另走现有业务回归测试。