15 KiB
15 KiB
贴票台 · 界面优化方案
依据当前代码(
reimburse/下 26 个 Swift 视图文件)整理,只提优化建议,不改动代码。 应用结构:顶层 TabView(项目管理 AdminView+本地贴票 ContentView),本地贴票内含材料扫描 ScanPage、人工配对 PairPage、已核对 MatchedPage三个页面,以及报销单模板、收款信息、报销单预览等弹窗。
一、现状盘点
信息架构
| 层级 | 内容 | 现状评价 |
|---|---|---|
| 顶层 Tab | 项目管理 / 本地贴票 | 应用名为"贴票台"且主功能是本地贴票,但项目管理排在第一个 Tab,与产品定位略有错位 |
| 本地贴票 | 侧栏 3 页 + 顶栏统计 + 工具栏 3 按钮 | 结构清晰,导航合理 |
| 弹窗 | 报销模板(1000×700)、收款信息(宽 580)、个人报销单(870×620)、预览(动态)、材料预览(1000×700) | 尺寸规格不统一,部分固定尺寸在小屏上有溢出风险 |
已做好的地方(应保留)
MaterialCard卡片 + Canvas 贝塞尔连线的配对交互,直观且具辨识度;MatchExplanationPopover的 100 分制证据评分明细,透明度高;- 拖拽导入的 dropDestination 高亮反馈、
.help()悬停提示、accessibilityLabel覆盖较全; - Table + 分组 Picker + 跨分组保留勾选的选择模型,业务逻辑扎实。
二、设计系统层面(全局问题)
2.1 颜色语义不统一 ⭐ 高优先级
- 现状:teal 同时承担「品牌色、强调色、成功色、进行中状态」四种语义(侧栏图标、付款金额、匹配满分、通知横幅全是 teal);警告用 orange、错误用 red、AdminView 里成功又用 green。同一语义在两个 Tab 中颜色不同。
- 建议:
- 建立语义色枚举(如
AppTheme.success / warning / danger / accent),收敛到一处定义; - teal 保留为品牌/强调色;成功态用系统 green、警告 orange、危险 red,与项目管理端对齐;
- 「自动匹配 ≥90 分」与「人工确认」目前用 teal / blue 区分,建议改为统一的徽章组件(形状+图标+色),而非仅靠文字前缀。
- 建立语义色枚举(如
- 金额显示可遵循国内财务习惯:发票与付款两列总额(topbar)目前一灰一 teal,对比弱,建议付款列加图标或用同色不同字重,避免用户误读为涨跌。
2.2 深色模式适配缺失 ⭐ 高优先级
- 现状:
MaterialThumbnail用Color.white背景、SpreadsheetPreview / ExpenseTemplateManager大量.background(.white)、预览区.black.opacity(0.04)。深色模式下会出现大面积刺眼的白色块与文字对比不足。 - 建议:表格/缩略图区保留白底是合理的(还原纸张观感),但外层容器、边框、占位图标应改用
Color(nsColor: .textBackgroundColor)或材质色;至少验证Window在深色外观下所有页面无纯白大色块、无低对比 caption。
2.3 排版与间距 token 化
- 现状:
padding(28) / (26) / (22) / (20)、cornerRadius 16 / 13 / 12 / 10 / 9 / 8、字号.title2 / .title3 / .system(size: 34 / 44 / 42)混用,页面间无对应关系。 - 建议:定义间距(4 的倍数:8/12/16/24/28)与圆角(8 卡片内、12 卡片、16 面板)两档规格;页面主标题统一为
.title2.bold()(当前 PairPage 是 title3、MatchedPage 是 title2)。
2.4 组件重复实现
AdminView内自建了statusBadge / sectionCard / searchField / emptyState,ContentView一侧有Panel / EmptyPanel,两套体系风格接近但参数不同。- 建议:抽出共享组件库(Badge、Card、SearchField、EmptyState、StatNumber),两个 Tab 复用,减少后续维护分叉。
三、页面级优化
3.1 材料扫描 ScanPage
| 问题 | 建议 | 优先级 |
|---|---|---|
| 空工作区时仍显示全部统计面板(全是 0),首屏信息密度高但价值低 | 无材料时展示「导入引导」大空状态:仅保留拖拽卡片 + 模板卡片,统计面板在导入后再出现 | P1 |
| 单列滚动太长:导入卡、模板卡、警告、3 个统计卡、2 个金额面板、分类汇总、底部计数,关键动作「前往人工配对」沉底 | ① 统计卡片改为一行 4 列紧凑指标条;②「前往人工配对」在有待配对材料时上浮为醒目入口(如导入完成后的成功横幅内嵌跳转按钮);③ 分类汇总与金额概览合并为一个「金额」面板 | P1 |
拖拽高亮 opacity 0→1 突变 |
加 withAnimation(.easeInOut(duration: 0.15)),并让图标/文字随 targeted 状态做位移或缩放微动效 |
P2 |
| warnings 面板无法关闭、数量多时占据大量空间 | 逐条可关闭 + 超过 3 条折叠为「N 条提醒」;每条加对应的跳转动作(如跳转到识别失败的材料) | P2 |
三个统计卡数字 size: 34 硬编码,视觉与「金额概览」面板重复 |
数字统一走 StatNumber 组件(.rounded 数字字体 + tabular),金额面板可考虑用小图表(分类占比条)替代纯文本 |
P3 |
3.2 人工配对 PairPage
| 问题 | 建议 | 优先级 |
|---|---|---|
| 材料多时无法定位:无搜索、无排序切换、无金额/日期过滤 | 每栏顶部加搜索框(文件名/商户/金额)+ 排序菜单(日期/金额/文件名),复用 AdminView 的 searchField 样式 |
P0 |
| 已选 N 张发票 × N 张付款为全连接,选 5×5 时 25 条虚线交叉难以阅读 | 连线改为:hover/聚焦某卡片时只高亮与它相关的连线;或选中的卡片显示序号,连线带序号标签 | P1 |
| 只有 Return 键可操作选中,无方向键导航 | 利用现有 .focusable() 补充 ↑↓ 移动焦点、Space 选中,形成完整键盘流;说明文字中标注快捷键 |
P1 |
| 缩略图固定 180pt 网格,看不清细节需逐个开预览 | 增加缩放滑杆(紧凑/标准/大图三档),或双击卡片直接放大预览后可从预览中「选中此材料」 | P2 |
| 确认配对按钮位于右上角,与底部的选中信息分离 | 选中数 >0 时在两栏之间显示居中的「确认配对(N×M)」悬浮按钮,动线更短 | P2 |
| 空状态文案两栏雷同 | 左栏空时提示「所有发票已处理或已核对」,右栏提示对应付款文案,并可放「撤销上一组」入口 | P3 |
3.3 已核对 MatchedPage
| 问题 | 建议 | 优先级 |
|---|---|---|
| 无搜索/过滤:几十组材料时找特定金额/商户困难 | 表格上方加搜索框(金额、商户、日期),支持过滤后再勾选 | P0 |
MaterialCell 只列前 2 个文件名链接,「还有 N 份」不可展开 |
点击单元格弹出 popover 缩略图网格,与 PairPage 的卡片视觉统一;>2 份时显示「+N」叠图效果 | P1 |
| 底部三行 caption 说明文字(勾选规则、PPT 版式)常驻 | 收敛为一个「导出说明」帮助按钮(questionmark.circle)弹出;常用信息已在按钮禁用态与选中计数中体现 |
P2 |
| 分组多时 segmented Picker 挤压变形 | 分类 ≥5 个时改用 Menu + 下拉,或横向滚动 chips | P2 |
| 「操作」列撤销仅图标按钮,与分类 Picker 挤在一列 | 撤销改为 hover 行时出现的 trailing 按钮或右键菜单;分类修改也可考虑双击单元格弹出,减少列宽 | P2 |
| 表格无小计:分组切换后看不到当前分组金额合计 | 表格底部(或分组标题旁)显示「本分组合计:发票 X · 付款 Y」 | P2 |
| 评分 <90 分为橙色但没有聚合入口(「哪些组需要人工复核」) | 增加「需关注」过滤(评分 <90 或识别失败),配合 P0 搜索框;侧栏「已核对」徽标可显示低分组数量 | P1 |
3.4 个人报销单 ExpenseSheet 与预览
| 问题 | 建议 | 优先级 |
|---|---|---|
固定 frame(width: 870, height: 620),小屏(MacBook Air 13" 缩放)可能顶出屏幕 |
改为 min 上限策略(参照 ExpensePreviewSheet 的 min(1200, visibleFrame - 80) 写法) |
P1 |
| 费用行用途 TextField 无校验反馈(空值、重复用途不易发现) | 空用途时行内灰字提示;重复用途合并提示 | P3 |
| 签字岗位 minus.circle 无确认,误触即删 | 删除加轻量确认或支持撤销 toast;输入框加默认岗位快选 Menu | P3 |
expenseSelectionValid 失效只显示一行红字,动作指引弱 |
失效时禁用预览按钮并把红字放进醒目横幅,附「返回重新选择」按钮 | P2 |
| 预览弹窗已较好;「返回修改」与「确认并保存」并排但视觉主次不明 | 确认按钮保持 prominent 即可;建议保存成功后用横幅告知保存路径并提供「在访达中显示」 | P2 |
3.5 报销模板管理 ExpenseTemplateManager / ExpenseTemplateFields
| 问题 | 建议 | 优先级 |
|---|---|---|
| 模板字段调整(列字母/单元格地址)要求用户手工填 "C" "C23",认知门槛高 | ① 输入框支持点选:在左侧表格预览上点击单元格即回填地址(SwiftUI 可用 onTapGesture + 布局信息);② 输入时实时校验字母/地址格式并给出示例反馈 | P1 |
| 「查看单元格地址与原文」DisclosureGroup 是纯文本行,对照困难 | 与左侧预览联动:hover 某行时高亮预览中对应行;保留行号列 | P3 |
| 未识别完整时只有一行橙色警告,确认按钮置灰原因不直观 | 每个缺失必填项(用途/金额列)在对应输入框旁标橙点,按钮旁注明「还差 N 项」 | P2 |
| 模板卡片(ExpenseTemplateSummary)与导入卡片视觉相似,都是 teal 虚线框 | 模板卡片改为普通卡片 + 右上「模板」徽标,虚线拖拽样式只留给导入场景,减少误拖 | P3 |
3.6 收款信息 PayeeProfileSheet
- 现状已经较好(SecureField + 显隐切换 + 删除确认)。可补充:保存成功后 toast 确认;
PayeeProfileSummary中「尾号 XXXX」处加复制按钮。 - 优先级 P3。
3.7 项目管理 AdminView
| 问题 | 建议 | 优先级 |
|---|---|---|
单文件 1364 行、50+ 个 @State,六个页签全部内联 |
拆分为独立 View 文件(AdminExpensesTab 等);这不是纯界面问题,但直接影响后续所有 UI 迭代效率 |
P1(技术债) |
| 自绘 tab 条(navigationItem)与 macOS 惯例不符,窗口宽度不足时六个标签挤压 | 采用 macOS 15 可用的 TabView 新样式或保留但允许横向滚动 + 更多收纳进 Menu |
P2 |
| 登录页固定 400 宽输入区 + ScrollView,视觉重心偏上 | 居中卡片式布局;服务地址输入记忆历史地址下拉;微信扫码过期自动刷新提示 | P2 |
| 报销审批表无分页指示、无列排序 | Table 补充排序(金额/日期);行数多时显示计数 | P2 |
| 错误横幅红色整条较突兀 | 收敛为顶部统一通知组件(同本地贴票端的 notice 样式),成功/警告/错误三态 | P2 |
四、全局交互与反馈
- 统一通知体系(P1):目前成功提示是自定义 teal 横幅、错误是
alert、Admin 是红横幅。建议统一为三态通知条(成功/警告/错误),支持多条堆叠与自动消失(错误不自动消失),并复用 macOS 15 的SymbolEffect。 - 菜单栏与快捷键(P2):已有 ⌘O 导入。建议补充:⌘Z 撤销最近核对组(复用 store.undo)、⌘F 聚焦搜索(配合 P0 搜索项)、⌘1/2/3 切换三个页面、⌘, 打开设置类弹窗(模板/收款信息)。
- 空状态体系(P1):EmptyPanel 目前只有图标+标题+说明,可按页面补一个行动按钮(如「选择文件夹」「前往人工配对」),形成闭环。
- 进度反馈(P2):busy 时是整页
disabled+ 顶部进度条;扫描大目录时建议在 Dock 图标显示进度(NSApp.dockTile.progress),并保留页面滚动可读。 - 危险操作确认(P2):「清空重置」的 confirmationDialog 文案已很详细,但「恢复内置模板」「删除收款信息」等破坏性操作可统一加「需要输入确认/二次点击」模式中的轻量档:按钮文字改为具体后果(如「移除本机模板副本」)。
五、性能相关(影响体感的界面项)
| 问题 | 建议 | 优先级 |
|---|---|---|
MaterialPreview 用 NSImage(contentsOf:) 在主线程同步解码整图,大图/PDF 首页可能卡顿 |
改为 task 异步加载 + 占位 ProgressView;预览窗口打开先显示缩略图再换全图 |
P1 |
Workspace.sortedMatches、matches(for:)、groups、表格行的 index(of:) 都是每次重算的 computed 属性,匹配组多时 Table 滚动会重复计算 |
在 Store 层缓存排序结果(matches 变更时失效);index(of:) 用 Dictionary(id→index) 替代 |
P2 |
| ScanPage 分类汇总对每个 category 全量 filter(7 × N) | 一次遍历 reduce 成字典再渲染 | P3 |
MaterialThumbnail 700px 缩略图生成已异步(好);但 task(id: previewURL) 取消旧任务的行为依赖 detached task,建议显式检查 Task.isCancelled |
补充取消检查,避免快速滚动时旧图覆盖新图 | P2 |
六、无障碍与本地化细节
- caption / caption2 +
.tertiary的组合在浅色模式下对比度偏低(如「支持图片和 PDF · PDF 处理首页」),建议 tertiary 只用于辅助信息,主说明用 secondary。 MatchConfidenceCell的颜色(teal/orange)承载了语义,建议在 accessibilityLabel 中补充「评分高/需关注」文字(目前已有百分比,可再补状态词)。- PairPage 连线是 Canvas 绘制,VoiceOver 完全不可见;建议在读出的标签中描述配对关系(已有 accessibilityLabel 基础,补充「已与 N 张付款连线」)。
七、实施路线图
| 阶段 | 内容 | 预期收益 |
|---|---|---|
| P0(先做) | PairPage / MatchedPage 搜索与排序;低分组「需关注」过滤 | 解决材料量大时的核心查找痛点 |
| P1 | 颜色语义统一 + 深色模式适配;语义色/间距 token 化;空状态行动按钮;ScanPage 信息层级重组;MaterialPreview 异步加载;AdminView 拆分 | 视觉一致性与小屏/深色体验 |
| P2 | 统一通知组件;键盘快捷键;表格 MaterialCell 缩略图 popover;分组小计;模板字段可视化点选;拖拽动效;进度 Dock 反馈 | 效率与细节打磨 |
| P3 | 统计卡组件化、金额小图表、模板卡片徽标、签字岗位快选 | 锦上添花 |
约束提醒:以上均为界面层建议,实施时须保持 README 中列明的业务口径不变(PPT 版式、金额计算口径、勾选保留规则等),尤其 P1 中 ScanPage 重组不要改变「再次导入替换工作区」的确认流程。