Files
xuetang/app/research/diagnosis_index_visual_spec.md
T
2026-09-08 11:40:15 +08:00

35 KiB
Raw Blame History

管理端“诊单列表”视觉规格(源码基准)

审计日期:2026-08-10
唯一业务页面基准:D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue
方法:只读检查 Vue 模板、同文件 scoped SCSS、直接挂载组件、全局样式、主题生成逻辑和当前锁定的 Element Plus 源码;未启动浏览器、未改业务源码。

1. 结论摘要

  1. 该页面没有页面内标题、说明文案或独立标题栏。路由内容从一张无边框、无阴影的筛选卡直接开始;“新增诊单”等主操作位于第二张列表卡顶部,而不是页面标题旁。证据:index.vue:2-154
  2. 页面是“浅灰页面底 + 两张白卡”的高密度后台列表。外层路由容器提供左右 8px、上下 16px 的留白;筛选卡和列表卡之间为 12px。证据:D:/web/zyt/admin/src/layout/default/components/main.vue:2-10index.vue:154D:/web/zyt/admin/tailwind.config.js:103-113
  3. 顶部不是常规 tabs,而是可换行的圆角文字 chip:6 个日期入口,再接“待预约 / 已完成 / 待分配医助”,计数是文字后面的普通半透明数字,不是独立 badge。当天默认选中。证据:index.vue:6-70,964-976,2174-2182,2222-2317
  4. 表格声明列的最小总宽约为 1403px;右侧固定“视频旁观” 120px 与“操作” 340px,合计 460px。窄于该宽度时由 Element Table 横向滚动,右侧两列保持 fixed。证据:index.vue:191-342
  5. 表格使用斑马纹;普通偶数行是 #FAFAFA,普通悬停是 #F8F8F8。未确认、未挂号行还声明了左侧语义色和横向渐变,但静态渐变写在 tr,斑马纹及 fixed cell 的 td 背景可能遮住它;两类行的 hover 渐变直接写在 td,表现更稳定。证据:index.vue:2723-2735、Element Plus table.scss:560-588,665-668
  6. 空态不是 el-empty 插画,而是表格默认的 60px 高“暂无数据”文本区;加载态是覆盖表格的半透明蒙层和 42px 主色环。证据:Element Plus table.scss:52-70loading.scss:19-73、中文 locale zh-cn.mjs:137

2. 源码证据层级

层级 文件 本规格使用内容
页面模板与局部样式 D:/web/zyt/admin/src/views/tcm/diagnosis/index.vue:1-2766 DOM 次序、列宽、状态类、局部尺寸和颜色
路由内容容器 D:/web/zyt/admin/src/layout/default/components/main.vue:1-12 页面底色、外层滚动、px-2 py-4
共享组件 D:/web/zyt/admin/src/components/pagination/index.vue:1-50D:/web/zyt/admin/src/components/daterange-picker/index.vue:1-49 分页布局、页容量、日期范围控件行为
项目全局样式 D:/web/zyt/admin/src/styles/index.scss:1-5var.css:1-49element.scss:58-68,106-115,140-151,177-201public.scss:1-3 全局字体、颜色、表格、输入焦点、移动分页
项目主题 D:/web/zyt/admin/src/config/setting.ts:1-15src/utils/theme.ts:3-75src/App.vue:25-34 默认主色、明暗主题色派生、运行时覆盖
Tailwind token D:/web/zyt/admin/tailwind.config.js:5-155 字体族、颜色映射、间距值
UI 框架 D:/web/zyt/admin/pnpm-lock.yaml:47-49,2412-2415node_modules/element-plus/theme-chalk/src/** 当前锁定 Element Plus 2.13.7 的默认组件尺寸

package.json:27 写的是兼容范围 ^2.9.4,当前 lock 与已安装源码均为 2.13.7;本规格的框架默认尺寸以锁文件和当前安装源码为准。

3. 页面骨架与 ASCII wireframe

3.1 宽屏主态

主内容滚动区,#F6F6F6;左右 8,上下 16
┌────────────────────────────────────────────────────────────────────────────────────────────┐
│  筛选卡 #FFF / r4 / 无边框无阴影;内边距 12V × 16H                                      │
│  [昨天挂号 n] [前天挂号 n] [当天挂号 n] [明天挂号 n] [后天挂号 n] [全部 n]                │
│  [待预约 n] [已完成 n] [待分配医助 n]                 [患者姓名 / 手机号 160] [查询 32h] │
│  ────────────────────────────────────────────────────────────────────────────────────────  │
│  挂号:[全部] [已挂号] [未挂号] │ 确认:[全部] [已确认] [未确认]   更多筛选⌄             │
│  · · · 展开时:诊断类型 / 证型 / 医助 / 最近挂号日期 / 最近指派日期 / 渠道 / 重置 · · ·  │
└────────────────────────────────────────────────────────────────────────────────────────────┘
                                      12px
┌────────────────────────────────────────────────────────────────────────────────────────────┐
│  [新增诊单]  [批量指派医助]  [批量取消指派]                         已选 n 条(按需显示) │
├────┬──────┬──────┬───────────┬──────────────┬──────┬────────┬──────┬──────┬──────────┬──────┬────────────────────┤
│ □  │ ID   │ 患者 │ 性别/年龄 │ 挂号         │ 确认 │ 复诊   │ 助理 │ 开方 │未服务天数│旁观* │ 操作*              │
├────┼──────┼──────┼───────────┼──────────────┼──────┼────────┼──────┼──────┼──────────┼──────┼────────────────────┤
│ □  │123 NEW│张三 │ 男 · 42岁 │[待问诊] 医生 │未确认│日期/医生│医助  │已开方│    8     │进入  │查看 诊单 开方 … 更多│
│    │      │      │           │时间 / 渠道   │      │        │      │      │          │      │                    │
├────┴──────┴──────┴───────────┴──────────────┴──────┴────────┴──────┴──────┴──────────┴──────┴────────────────────┤
│                                               共 n 条  [15条/页] [<] 1 2 … [>]  前往 [ ] 页 │
└────────────────────────────────────────────────────────────────────────────────────────────┘
                                                            * 右侧固定列,共 460px

3.2 结构说明

  • 外层 main 是整页垂直滚动容器;诊单表没有本页固定高度或纵向虚拟滚动,15 条数据会把页面自然撑高。证据:layout/default/components/main.vue:2-11index.vue:179-190
  • 两张卡都使用 shadow="never"!border-none;保留 Element Card 的白底、裁切和 4px 圆角。框架默认:Element Plus card.scss:9-17common/var.scss:1226-1235
  • 页面根节点只设 min-height:100%、页面底色和水平居中;不设自身宽度、最大宽度或 padding。证据:index.vue:2200-2206
  • 顶部全局 header、面包屑和多页签属于应用壳,不在 index.vue 中;它们是否出现受全局 setting 控制,不能当作本页标题复刻。

4. 可复刻的基础 token

4.1 字体与基础尺寸

源码确定值 证据
字体族 PingFang SC, Arial, Hiragino Sans GB, Microsoft YaHei, sans-serif tailwind.config.js:79-81var.css:2
body / Element base 14px public.scss:1-3var.css:16
small / extra-small 13px / 12px var.css:17-18
默认控件高度 32px Element Plus common/var.scss:233-241
small 控件高度 24px 同上
默认圆角 4px Element Plus base.css:1
卡片圆角 4px Element Plus common/var.scss:1227-1234

字体栅格的真实像素高度仍受 Windows 缩放、浏览器 DPR 与首个可用字体影响;页面 chip 没有固定 height/line-height,只能精确复刻 padding,不能仅凭源码承诺最终外框高度。

4.2 亮色主题

项目在 App.vue mount 时用 setting 重写 Element 语义色。默认主色不是 Element 原生蓝,而是 #4A5DFF。主题派生算法见 src/utils/theme.ts:3-18,29-37,55-74

token 默认运行值 使用处
--el-color-primary #4A5DFF active chip、主按钮、链接、loading
primary light-3 / 5 / 7 / 8 / 9 #808EFF / #A5AEFF / #C9CEFF / #DBDFFF / #EDEFFF hover、focus、轻底色
primary dark-2 #3B4ACC active 状态;页面另有硬编码近似值 #3A4ACC
success #67C23A 已完成 chip、已确认、成功按钮
warning #E6A23C 待分配、未确认、警示行
danger #F56C6C NEW、删除/取消
info #909399 待预约、完成预约、次要态
page / card #F6F6F6 / #FFFFFF 页面底 / 卡片与普通行
primary / regular / secondary text #333333 / #666666 / #999999 标题信息 / 常规 / 辅助
placeholder / disabled #A8ABB2 / #C0C4CC 空值、禁用
border / light / lighter #DCDFE6 / #E4E7ED / #EBEEF5 控件、卡线、行分隔
fill / light / lighter #F0F2F5 / #F8F8F8 / #FAFAFA hover、表头、斑马纹
loading mask rgba(255,255,255,.5) 表格加载蒙层

证据:src/config/setting.ts:9-14src/styles/var.css:9-43。主色的派生结果使用项目同一 css-color-function 算法计算;不是页面硬编码。warning/info 的页面渐变使用 --el-color-*-rgb,其当前框架默认分别为 230,162,60144,147,153Element Plus base.css:1)。

4.3 暗色与运行时主题边界

  • .dark 下页面底为 #0A0A0A、普通背景 #1D2124、overlay #1D1E1F,主/常规/次要文字为 #E5EAF3 / #CFD3DC / #A3A6ADlighter border 为 #363637。证据:src/styles/dark.css:1-31
  • App.vue 根据 useDark() 调用主题生成器,主色仍可保持 #4A5DFF,但 light-* 在暗色下改用 shade 算法。证据:src/App.vue:29-34src/utils/theme.ts:12-18,55-77
  • setting 会从本地缓存覆盖默认颜色,因此某个真实账号的主色/语义色可能不同。证据:src/stores/modules/setting.ts:12-50,65-77。上表是无用户自定义时的确定基线。
  • 页面内硬编码的 #4A5DFF#3A4ACCrgba(74,93,255,...) 不会随自定义主题变化,因而自定义主题下会出现两套蓝色。证据:index.vue:2522-2529,2556-2559,2596-2599

5. 顶部筛选卡

5.1 卡与第一行

筛选卡 body padding 为 12px 16px。第一行 .filter-main 是单行 flex:垂直居中、两端对齐、组间 16px、下边距 8px自身没有 flex-wrap。左侧 .date-chips 才可换行,chip 间距 6px。证据:index.vue:3-76,2208-2225

元素 几何/排版 默认/交互颜色 证据
普通日期 chip padding 6px 12px14px/500r6transition .2s 常规 #666 + #F8F8F8hover #F0F2F5active 白字 + 主色 index.vue:2227-2250
chip 计数 与标题相隔 4pxnormal styleopacity .8 跟随父 chip index.vue:23-24,2237-2241
待预约 普通 chip 外再有左 margin 8px info / info-light-9active info 实色 index.vue:26-32,2253-2265
已完成 左 margin 8px success / success-light-9active success 实色 index.vue:33-39,2268-2280
待分配医助 权限控制;外容器可换行、gap 8px、左 margin 8px warning / warning-light-9active warning 实色 index.vue:40-70,2283-2308
待分配月份 default 月选择器;宽 128px Element 默认输入态 index.vue:51-60,2310-2312
待分配宽搜索 default 输入;宽 220px,最大 42vw Element 默认输入态 index.vue:61-69,2314-2317
主搜索 default 输入宽 160px placeholder“患者姓名 / 手机号” index.vue:72-75,2320-2326
查询 primary default button;高 32px14pxr4 白字/主色底 index.vue:74、Element Plus button.scss:22-43,76-82

日期 chip 的实际顺序是:昨天、前天、当天、明天、后天、全部,不是按自然日期升序;随后才是 3 个业务 chip。证据:index.vue:964-976。页面挂载时直接选中当天并请求列表;各 chip 计数延后到 idle(不支持时延后约 120ms)获取,所以首帧可能只有标签、稍后才出现数字。证据:index.vue:1046-1095,2174-2182

5.2 第二行快捷筛选

  • 第二行上方有 1px solid #EBEEF5;自身 padding-top:8pxmargin-top:8px、水平 gap 6px、垂直居中。证据:index.vue:78-102,2329-2335
  • “挂号:”“确认:”为 13px #999label 后额外 2px。每组都是“全部 / 已… / 未…”。证据:index.vue:79-97,2337-2341
  • 小 chip 最终 padding 是 .chip-sm4px 10px13px、r4、透明底;hover/active 用主色文字与 primary-light-9active 权重 500。证据:index.vue:2343-2366
  • 两组之间为 1×14px 的 lighter 分隔线,左右 margin 4px。证据:index.vue:2368-2373
  • “更多筛选”是 primary/link/small 按钮,左 margin 8px;展开时 ArrowDown 旋转 180°,文字变“收起”。源码没有为该旋转指定独立 transition。证据:index.vue:98-101,2375-2380

5.3 展开筛选区

展开区使用 v-show,所以是即时显隐而非折叠动画。它为可换行 flex,gap 10px,上 margin/padding 各 8px,顶部是 1px dashed #EBEEF5。证据:index.vue:104-151,2384-2391

控件从左到右:

  1. 诊断类型 selectsmall24px 高);
  2. 证型 selectsmall);
  3. 医助 selectsmall,可搜索);
  4. 最近挂号日期范围(共享 DaterangePicker260px 宽、最大 100%,未传 size,故 default 32px 高);
  5. 最近指派日期范围(同上);
  6. 最近挂号渠道(small,可搜索,宽 170px);
  7. 重置(small button24px 高)。

证据:index.vue:104-150,2393-2405;共享日期组件只是透传一个 el-date-picker,见 components/daterange-picker/index.vue:1-11,15-31。因此展开区客观上混有 24px32px 两种控件高度。前三个 select 没有本页固定宽度;Element Select 自身是 width:100% 的可收缩 flex item,最终每行宽度依赖可用空间与浏览器 flex 计算,源码不能给出一个稳定像素值。

6. 列表卡操作栏

  • 列表卡距筛选卡 12pxbody padding 清零。证据:index.vue:154,2408-2412、Tailwind spacing tailwind.config.js:103-113
  • 操作栏为左右两端布局,padding 10px 16px,底边 1px #EBEEF5;未固定高度。default button 高 32px,故无换行时栏高至少约 52px。证据:index.vue:155-177,2414-2429
  • 左侧依权限显示:primary“新增诊单”、success“批量指派医助”、warning/plain“批量取消指派”。后两者按选中状态禁用。右侧仅在选中数量大于 0 时显示 13px #999 的“已选 n 条”。证据:index.vue:157-176
  • .list-actions 声明 gap:8px,但 Element 默认还有 .el-button + .el-button { margin-left:12px },此处没有清零。因此相邻按钮的实际起点间空白通常是 20px8+12,而不是设计者表面写下的 8px。证据:index.vue:2421-2424、Element Plus button.scss:72-74

7. 表格规格

7.1 外框与表头

  • 表格外围 padding 10px 16px 0;表格宽度 100%,默认 fixed layout、无竖边框;行之间由 1px #EBEEF5 底边分隔。证据:index.vue:178-190,2432-2434、Element Plus table.scss:11-20,188-195,217-235
  • 表头底 #F8F8F8、13px/600、文字 #666。默认 cell 水平 padding 12px,行高 23px,纵向 padding 8px,所以单行表头的理论最小高度约 39px(23+16,不含亚像素/边线差异)。证据:index.vue:2710-2716、Element Plus table.scss:156-195common/var.scss:1014-1031
  • 表头“未服务天数”有双态排序箭头,顺序只允许 descending → ascending;激活箭头使用主色。证据:index.vue:297-304、Element Plus table.scss:548-552

7.2 列宽与内容

次序 声明宽度 对齐/固定 主要视觉内容
1 选择 48px center header 全选 + 行 checkbox
2 ID min 70px left ID 为 14px/600;未读指派时附 small/dark/danger NEW
3 患者 min 60px left 患者名 14px/600;头像模板已注释,不显示
4 性别 / 年龄 100px left 男 · 42岁,继承表格 14px
5 挂号 min 175px left 预约状态 badge、医生、时间、可取消链接、最近渠道;无则“未挂号”
6 确认 88px center 13px 已确认/未确认文字
7 复诊 min 120px left 时间、医生、可选“处方已作废” tag;无则“无”
8 助理 100px left 13px 次要文字,溢出 tooltip
9 开方 72px center 13px 已开方/未开方
10 未服务天数 110px center 13px/600 tabular number,按天数绿/橙/红;可有健康打卡 tooltip
11 视频旁观 120px center / right fixed small link 或 12px 次要状态
12 操作 340px left / right fixed 5 个 small/link 主动作 + click dropdown

证据:index.vue:191-406。声明宽度/最小宽度合计约 1403pxmin-width 列在更宽窗口可继续分配余量。右固定区域为 120+340=460pxElement 会在滚动边缘加 fixed-column 阴影;阴影值来自框架 common/var.scss:981-1000

7.3 行高与密度

  • 本页再次把 body cell 设为 padding:8px 0cell 内层保留 Element 的水平 12px23px line-height。纯单行内容的最小行高约 39px。证据:index.vue:2720-2722、Element Plus table.scss:188-195
  • 挂号 cell 有 min-height:36px、内 padding 4px 8px、r6,所以含该列的常规数据行通常至少约 52pxcell 36 + table 上下 16);实际由内容较高者决定。证据:index.vue:2485-2489
  • 同一诊单多条预约时,每一后续预约额外带 8px top margin、8px top padding 和 1px dashed #EBEEF5,行高会显著增加,不是固定行高。证据:index.vue:227-247,2490-2494
  • 操作区允许换行;链接数量受权限与记录状态影响,所以操作列也可能增高整行。证据:index.vue:344-403,2683-2688

7.4 斑马、hover 与业务高亮

状态 静态 hover 判定优先级
普通奇数行 #FFF #F8F8F8 无业务类
普通偶数行 #FAFAFA #F8F8F8 stripe
未确认 预期左侧 3px #E6A23C;从左到右 warning RGB .06 → transparent warning RGB .10 → transparent,直接覆盖 td 第一优先
已确认但未挂号 预期左侧 3px #909399info RGB .04 → transparent info RGB .08 → transparent,直接覆盖 td 第二优先

判定函数先检查“是否确认”,只有已确认才检查“是否挂号”,所以一行不会同时得到两个业务类。证据:index.vue:1313-1337。页面声明见 index.vue:2723-2735;斑马和 hover 框架规则见 Element Plus table.scss:560-588,665-668

实现时必须区分“源码意图”和“浏览器可见结果”:

  • 静态业务渐变在 tr,而偶数斑马行和 fixed cell 的背景落在 td;不透明 td 会遮住下面的 tr 渐变。
  • 业务 hover 选择器直接命中 td 且带 !important,因此 hover 更可靠。
  • border-left 施加在 tr,在 border-collapse:separate 的 table 中具体像素绘制还受浏览器表格格式化上下文影响。

PySide 复刻应按“意图”直接给每个可见 cell/row delegate 绘背景和 3px 左条,避免复现 CSS 遮挡缺陷;若目标是截图逐像素一致,则需先用指定 Chromium、固定数据测一张运行态截图。

7.5 单元格内部视觉

患者与 ID

  • .patient-name 为 14px/600、#333、line-height 1.3。ID 与患者列都复用该样式。证据:index.vue:194-212,2461-2470
  • 32×32、r8、主色渐变的头像 CSS 存在,但患者模板已注释,不参与实际页面。证据:index.vue:207,2447-2459
  • NEW 是 small (20px 高)、danger、dark tag:白字、danger 实色底;字体 12px、r4。证据:index.vue:198、Element Plus tag.scss:66-87,142-165common/var.scss:1110-1138

挂号块

  • 每个预约 badge11px/600、padding 2px 6px、r4、下 margin 2px;医生 14px/600 #333;时间 12px、上 margin 2px。证据:index.vue:2496-2519
  • 活跃预约 badge 为 #3A4ACC / rgba(74,93,255,.15),时间硬编码 #4A5DFF;整块为 135° 蓝色渐变 .12 → .06,边 rgba(74,93,255,.3)。证据:index.vue:2522-2531,2556-2559
  • 已完成预约用 info-dark-2 / info-light-7;爽约用 warning-dark-2 / warning-light-7。整块也分别换成 info 或 warning 透明渐变。证据:index.vue:2533-2569
  • 最近渠道为上 margin 6px、12px、line-height 1.35#999;未挂号为 13px #A8ABB2。证据:index.vue:2571-2581

语义文字与 tag

  • 已确认:13px/500 success;未确认:13px/600 warning。证据:index.vue:2584-2594
  • 已开方:13px/500、硬编码 #4A5DFF;未开方:13px #A8ABB2。证据:index.vue:2596-2605
  • 复诊时间 13px/500 #333,医生 12px #999,纵向 gap 4px、line-height 1.35;“处方已作废”是 small/plain/info tag。证据:index.vue:268-285,2651-2676
  • 未服务天数:最小 28px、13px/600、等宽数字;空值灰 #A8ABB2/400<=2 绿 #16A34A3-6#EA580C>=7#DC2626。证据:index.vue:305-316,1319-1329,2607-2632
  • 视频旁观为 12px、line-height 1.4,左右 padding 2px;不可进入时是 #999。证据:index.vue:318-341,2690-2704

8. 按钮、dropdown、tooltip

8.1 操作列链接

直接动作依次为:查看(primary)、诊单(primary)、开方/查看处方(primary)、预约(success)、补全身份证(warning),最后是 info“更多”。权限会移除部分按钮。证据:index.vue:345-403

  • 均为 size="small"link12px,透明边/底,padding 2px,高度 autohover 使用各语义色的 light-3。证据:Element Plus button.scss:223-248element.scss:113-127
  • .action-cell 设 flex-wrap + gap:4px;但相邻 .el-button + .el-button 仍有 12px 左 margin,因此连续按钮间通常是 16px4+12。dropdown 外壳与前一按钮之间只有 flex gap 4px。证据:index.vue:2683-2688、Element Plus button.scss:72-74
  • 340px 操作列不足时允许链接换行;没有强制单行或省略号。

8.2 “更多”菜单

  • click 触发、bottom-end 对齐。菜单项按权限/状态可包含:指派、取消指派、视频二维码、二维码、取消挂号、挂号日志、创建订单、删除。证据:index.vue:379-403
  • Element 默认 dropdown item 为 14px、line-height 22px、padding 5px 16px,故普通项约 32px 高;菜单上下净 padding 约 5pxr4、overlay 白底,popper 有 light border 与 shadow。hover 为 fill-light + primary。证据:Element Plus dropdown.scss:7-24,42-70,137-176
  • 删除项有 divided 顶线,文字由 .text-danger 强制为 danger。证据:index.vue:400,2706-2708
  • tooltip 使用 Element 默认 popper12px、line-height 20px、padding 5px 11px;实际位置由视口碰撞计算,不能从源码固定。

9. 分页、空态与加载态

9.1 分页

  • 列表默认 page=1, size=15;共享组件页容量选项为 [15,20,30,40]。证据:src/hooks/usePaging.ts:14-34components/pagination/index.vue:18-28
  • 布局固定为 total, sizes, prev, pager, next, jumper,最多显示 5 个 pager,单页也不隐藏。证据:components/pagination/index.vue:3-14,24-28
  • 容器右对齐,padding 10px 16px 16px。默认分页按钮 32×32px(最小宽),14pxr2,项组间 gap token 16pxactive 仅主色文字 + bold,并未启用 background 模式。证据:index.vue:408-410,2436-2440、Element Plus common/var.scss:1034-1057pagination.scss:5-67
  • page-size select 框架宽 128pxjumper 输入 56px。证据:Element Plus pagination.scss:73-75,118-150
  • 视口 <=768px 时,全局 CSS 隐藏 size selector 与 jumper,仍保留 total、prev、pager、next。证据:src/styles/element.scss:177-184

9.2 空态

页面没有提供 table #empty slot,也没有在主列表使用 el-empty。因此空列表为:

  • sticky empty blockmin-height 60px
  • 居中纯文本“暂无数据”;
  • 文字 #999line-height 60px,宽 50%
  • 表头、底线和分页仍存在。

证据:index.vue:179-190、Element Plus table.scss:52-70src/App.vue:5,25-28、Element 中文 locale zh-cn.mjs:137

9.3 加载

  • v-loading="pager.loading" 直接挂表格;普通请求开始时 loading=true,完成后 false。证据:index.vue:179-184src/hooks/usePaging.ts:35-72
  • 蒙层绝对覆盖 tablez-index 2000,亮色为 rgba(255,255,255,.5);中央环 42px,主色描边 2px,2 秒旋转、1.5 秒 dash 动画。证据:src/styles/var.css:41-43、Element Plus loading.scss:19-73,85-103common/var.scss:1340-1349
  • 页面每 20 秒静默刷新列表和计数;标签页不可见时跳过,静默刷新不打开 loading,因此不会周期性白闪。证据:index.vue:1098-1105,2182-2195src/hooks/usePaging.ts:36-42,64-71
  • 首次 pager.loading 初值是 false,但 mount 后立即调用 getLists(),正常网络下会很快进入蒙层;能否肉眼看到取决于响应时长。

10. 响应式与滚动行为

  1. index.vue 的 scoped 样式没有 media query。页面级响应式主要来自 flex-wrap、宽度上限、Element Table 横向滚动及全局分页规则。
  2. body 被全局设为 min-width:375pxoverflow:hidden;应用主内容通过 el-scrollbar 承担页面滚动。证据:src/styles/public.scss:1-3layout/default/components/main.vue:2-11
  3. 第一筛选行本身不换行。左侧日期 chip 可换行,但右侧 160px 搜索 + 32px 查询按钮仍与左侧同一 flex 行;在极窄内容宽度下可能压缩、增高左侧或溢出,源码没有把搜索行堆到下一行的断点。
  4. 待分配容器可换行,宽搜索最多 42vw;展开筛选区可换行,两个日期范围各为 260pxmax-width:100%。证据:index.vue:2298-2317,2384-2405
  5. 表格 min 总宽约 1403px。Element Table 内部提供横向 scrollbar;右侧 460px fixed 区保持可见,导致很窄时可见的左侧业务列空间进一步减少。
  6. 外层应用在窄屏会折叠侧栏,但那是壳层行为,不改变本页筛选/表格 DOM。证据:src/App.vue:36-53
  7. dark mode 有完整全局变量,但页面的硬编码蓝/绿/橙/红不会自适应;其亮度对比应另做暗色运行态验收。

11. 直接挂载的覆盖层(不占主页面静态布局)

主列表下方常驻挂载多个异步组件或 dialog/drawer;关闭时不占主页面空间,操作后覆盖在页面之上:

入口 覆盖层 关键尺寸 证据
新增/诊单 edit.vue 诊单 drawer 60% index.vue:414edit.vue:1-10
详情组件 detail.vue popup 800px index.vue:415detail.vue:1-10
开方/处方 tcm-prescription drawer 1200px index.vue:416components/tcm-prescription/index.vue:1-8
预约 appointment.vue drawer 60% index.vue:417appointment.vue:1-10
视频旁观 AssistantWatchCall dialog 760px;视频 grid min 220px index.vue:418-422AssistantWatchCallDialog.vue:1-19,242-284
挂号日志 drawer 460px index.vue:424-447
小程序二维码 dialog 400px;二维码 256×256 index.vue:449-481
指派医助 dialog 500px index.vue:483-531
创建订单 dialog 600px index.vue:533-587
补全身份证 dialog 400px index.vue:589-615
企微记录 drawer 600px index.vue:617-722

这些覆盖层说明“操作按钮点击后”的页面层级,但其完整内部视觉不应混入诊单 index 主页面的静态复刻范围。

12. PySide 映射建议

12.1 页面与筛选

Vue/CSS 意图 PySide 建议 复刻要点
外层 el-scrollbar + 两张 card QScrollArea → 单一 QWidget/QVBoxLayout;卡用 QFrame viewport #F6F6F6;外 margin 16V/8H;卡 r4、白底、无 border/shadow;卡间 12
date chips 自定义 FlowLayout + checkable QToolButton padding 6×12、r6、gap6;计数拼接为同一 label,保持源码顺序
业务色 chip 同一 button class 加 dynamic property pending_booking/infocompleted/successpending/warningactive 白字实底
第一行搜索 QHBoxLayout 右侧固定 QLineEdit(160) + QPushButton 高 32、gap8;若追求源码一致,不自行添加窄屏 stack
第二行筛选 QHBoxLayout/FlowLayout + QToolButton top line、上下 813pxactive primary-light-9
更多筛选 可显隐 QWidget + FlowLayout 无动画;top dashed bordergap10small 控件 24,日期范围 32

Qt 没有内建通用 FlowLayout,建议采用 Qt 示例式 FlowLayout,并把 chip 的 sizeHint() 包含字体宽度、左右 12/10px padding;不要用固定总宽,否则计数从一位变三位时会截断。

12.2 表格

  • 使用 QTableView + QAbstractTableModel,不要堆 15 行 QWidget。列的 initial/min widths 按本规格表设置;表头高建议从 39px 起,常规 row 从 52px 起,并由 delegate sizeHint() 为多预约/操作换行增高。
  • 选择列用 check-state delegateID/患者、确认、复诊、开方、未服务天数分别用专用 delegate 绘文字和 tag,避免嵌套控件带来的滚动性能问题。
  • 挂号列用一个复合 delegater6 的状态背景、11px badge、14px/600 医生、12px 时间、多预约虚线分隔。可点击“取消挂号”若必须嵌入,可在命中区域处理 mouse event,而不是每格常驻 QPushButton。
  • 两个右固定列可用同步滚动的双 QTableView:主表隐藏最后两列,右表只显示 120/340 两列,共宽 460;共享 model、selection model、vertical scrollbar 与 row height。单一 QTableView 无 Element 的 sticky fixed-column 等价物。
  • 行背景应在 delegate 对每个 cell 绘制:普通白/#FAFAFAhover #F8F8F8;业务行覆盖渐变并在第一可见 cell 绘 3px 语义条。不要把渐变只画在 viewport 底层,否则会重现 HTML td 遮挡问题。
  • 操作列优先使用 delegate + 命中区域或常驻 QWidget 行容器;若用按钮,链接样式为 12px、2px padding、无背景/边框,并预留源码实际的较大按钮间距。
  • 横向滚动时保持右表固定;表头与 body 必须共用列宽。多预约行要同步两张表的 row height。

12.3 dropdown、分页、空态、加载

  • “更多”使用 QMenuitem 高约 32、左右 padding16、14px;按权限/状态动态构建,删除项前 addSeparator() 且 danger 文本。
  • 分页建议自定义 PaginationBartotal、15/20/30/40 combo、prev、最多 5 页、next、jump;高度32,容器右对齐并保留 10T/16H/16B。窗口内容宽度 <=768 时隐藏 combo 与 jump。
  • 空态在 QTableView.viewport() 中央放一个透明 QLabel("暂无数据"),有效高度 60;不要用大插画。仍显示 header 和分页。
  • 加载态用覆盖 table rect 的半透明 widget:亮色 rgba(255,255,255,.5),中央约 42px 主色 spinner。新请求显示;20 秒静默刷新不显示。
  • 用 generation/request id 丢弃过期异步响应,并只在当前请求结束时关闭 overlay;这不是 Vue 当前 latestOnly:false 的视觉保证,但能避免 PySide 快速筛选时旧响应造成闪回。

12.4 主题与字体

  • 定义集中 token,而不是把 #4A5DFF 散落在 QSS;但为了忠实,挂号块与“已开方”目前应保留硬编码蓝,或在设计确认后统一为 theme primary。
  • Windows 上首选“Microsoft YaHei UI”还是源码的“Microsoft YaHei”会改变字宽;逐像素复刻应显式用 Microsoft YaHei14px CSS 大致映射为 Qt pixelSize 14,而不是 pointSize 14。
  • Qt 的 devicePixelRatio 与 CSS px 不同。截图验收需固定 Windows 缩放(建议 100%)、字体、窗口内容宽度和主题。

13. 能从源码确定 / 不能从源码确定

可以确定

  • DOM 顺序、无页面内标题、两张卡、每个筛选和操作入口;
  • 页面局部 padding/gap/宽度、列声明宽度、固定列、颜色、字体大小/字重;
  • 日期 chip 的顺序与当天默认态;
  • 表格 stripe、业务类判定优先级、语义文本与预约块状态;
  • 共享分页的页容量、布局、空态文案、loading 结构;
  • 默认亮/暗 token 及运行时主题派生方式;
  • 权限或数据条件控制哪些按钮/tag 出现。

仅运行态可最终确定

  1. 最终换行和行高:取决于 viewport、数据长度、按钮权限、预约条数、字体回退、DPR;chip 和多数 row 都没有固定 height。
  2. 实际主题色:setting 存在本地缓存,账号可改主色及语义色;dark 状态也来自浏览器存储/系统偏好。
  3. 业务行静态渐变是否完整可见:受 tr 背景、striped/fixed td 背景与 Chromium table paint 顺序影响;源码只能确定规则叠加关系。
  4. fixed-column 阴影和 scrollbar 尺寸:由 Chromium/Element 的滚动状态、平台 scrollbar 策略决定。
  5. tooltip/dropdown 的最终坐标popper 会做视口碰撞与翻转。
  6. 加载态停留时间和计数出现时间:由 API 延迟、idle callback 调度决定;静默轮询通常无蒙层。
  7. 应用壳标题/面包屑/多页签:由路由菜单、setting 和权限生成,不是 index.vue 的页面内视觉。

若后续要求“像素级截图一致”,应在固定 Element Plus 2.13.7 + Chromium 版本 + 100% Windows 缩放 + 默认亮色主题 + 固定权限/样本数据 下补一轮运行态测量;本文件已经给出源码能够保证的全部静态约束与明确边界。