- 现场型(一线师傅、班组长,户外 / 车间,可能 50 岁以上):用「现场端」字号组,触控 ≥56,对比 ≥7:1。灵构的小程序与工单类 App 属于这类。
- 办公型(管理者、普通员工,坐着看):可以降到 iOS / Android 的常规尺寸——正文 16、按钮 50、触控 44 / 48——但不能再小。智算 App 属于这类。
不确定是哪类,按现场型做。
现场约束 → 硬指标
| 现场是什么样 | 硬指标 | 常规做法为什么不行 |
|---|---|---|
| 户外强光、屏幕反光 | 正文对比 ≥7:1,辅助文字 ≥4.5:1 | AA 的 4.5:1 在阳光下读不清 |
| 戴手套操作 | 触控 ≥56×56,列表行高 ≥64 | 44 是裸手标准,戴手套点不中 |
| 用户年纪偏大 | 正文 f-body 17,一键放大到 f-body-large 20 |
14 是办公标准 |
| 单手扶梯 / 拿工具 | 主操作固定在底部、通宽、高 56、留安全区 | 右上角「保存」单手够不到 |
| 风场 / 地下室弱网 | 不加载 web font;提交先落本地队列 | 字体失败整页无字;提交失败丢数据 |
| 手脏、不方便打字 | 语音和拍照常驻可见,是一等公民 | 藏进「更多」等于没有 |
四个必须这么做的场景组件:① 麦克风常驻在每个长文本字段右侧;② 状态芯片带文字和图标,整行可点;③ 离线条常驻吸顶,显示「N 条待上传」;④ 拍照 capture="environment" 直接开后置相机,不弹三选一。
iOS(SwiftUI)
token 逐一映射,界面里不许出现散落的数值:
| 本系统 | SwiftUI |
|---|---|
background / card / muted / secondary |
Color.dynamic(light:dark:) 静态常量,一个 token 一个,放在 Theme.Color 里 |
foreground / muted-foreground / subtle |
textPrimary / textSecondary / textTertiary——三级到头 |
primary / primary-foreground |
primaryAction / onPrimaryAction。主按钮是实心梧桐蓝(默认主题),与 Web 端同色 |
| 状态五色 + soft | success / warning / danger / info / pending 各配 …Soft |
radius-chip/sm/md/lg |
RoundedRectangle(cornerRadius: 4/6/8/12, style: .continuous)。不用 999 胶囊 |
space-* |
Theme.Spacing 基数 4,只用这些值 |
| 字体 | Font.system(size:weight:)——SF Pro 自动回落 PingFang SC;数字一律 .monospacedDigit() |
| 图标 | SF Symbols,.regular 字重、.monochrome 渲染,不用 .multicolor |
| 焦点 / 按压 | 按压 scaleEffect(0.99) 100ms;不做 hover |
| 动效 | .spring(response: 0.35, dampingFraction: 1.0)——默认不回弹;仅拖拽释放用 0.8 |
平台惯例照 HIG,但以下几条以本系统为准:主操作固定在底部通宽(不是导航栏右上角);表单用 .sheet + presentationDetents([.medium, .large])(底部抽屉),不用居中 alert 放表单;破坏性确认用 .confirmationDialog 或 .alert,按钮 role: .destructive 且文案带动词与数量;iOS 没有 toast,自己做一个底部居中偏上的轻提示。Dynamic Type 要支持,f-body 对应 .body 基准,用户放大时随之放大而不是截断。深色模式跟随系统,底色用 background 暗色值而不是 .black。
Android(Jetpack Compose)
Material 3 的默认值与本系统冲突最多(大圆角、胶囊按钮、tonal 色阶),必须整体覆盖,不能只改颜色:
| 本系统 | Compose |
|---|---|
| 色板 | lightColorScheme(background=, surface=card, surfaceVariant=muted, primary=, onPrimary=, error=destructive, errorContainer=destructive-soft, outline=border);success / warning / info / pending M3 没有,做成 CompositionLocal 扩展色 |
| 圆角 | Shapes(extraSmall=4.dp, small=6.dp, medium=8.dp, large=12.dp, extraLarge=12.dp)——M3 默认 4/8/12/16/28 全部改掉;Button 显式传 shape = MaterialTheme.shapes.medium,否则默认胶囊 |
| 字体 | FontFamily.Default(Roboto / 厂商中文字体),不打包字体文件;Typography 用本系统字号重建,数字 FontFeatureSettings("tnum") |
| 图标 | Material Symbols Outlined、weight 400、tint = LocalContentColor.current |
| 触控 | 现场型 Modifier.sizeIn(minHeight = 56.dp);办公型 48 |
| 动效 | tween(180, easing = CubicBezierEasing(0.16f, 1f, 0.3f, 1f));不用 spring 回弹 |
| 表单 | ModalBottomSheet;确认 AlertDialog 的 confirm 按钮用 error 色与动词文案 |
| 轻提示 | Snackbar 放底部,现场型上移避开底部主按钮 |
edge-to-edge 开启,用 WindowInsets.safeDrawing 留安全区;底部主按钮 navigationBarsPadding()。暗色 background 用本系统暗色值,不用 Color.Black。不改 ripple 颜色。
微信小程序
设计稿按 750 宽,1px = 2rpx。系统字体(-apple-system, PingFang SC, Microsoft YaHei),不 @font-face。触控与字号按现场型。语音走 wx.getRecorderManager、拍照 wx.chooseMedia({ sourceType: ['camera'] }),离线队列落 wx.setStorage。page 的 backgroundColor 设成 background 的值,否则下拉回弹时露出白底。
四端一致性的验收点
- 同一个状态(超期)在四端的颜色、文字、图标一致
- 底色
background四端一致——早先手机端自己定了一套偏绿米色,比桌面深一档,并排放着一眼看出是两个 App - 圆角四端一致(4/6/8/12),不因平台默认而放大
- 主操作在移动端固定底部,不在导航栏右上角