Files
danyang-match/miniapp/app.wxss
T
WorkBuddy 269adf1fed 小程序端:设计系统收敛与排版层级修复
问题:88 个 wxss 里散落大量硬编码颜色/字号/字重,无法统一调整;
部分正文对比度不达 WCAG AA(4.5:1);组件触摸目标偏小。

改动:
- 硬编码颜色收敛到语义 token(颜色统一走 design token,不再散落字面值)
- 修正全站字号阶梯:正文 ≥12px、角标 ≥11px;字重只用 400/500/600/700
- 组件触摸目标提升到 ≥44px,并补交互反馈
- 首页补氛围层次、强化排版层级

验证(本轮实测):
- UI 契约门禁 18/18 PASS(含 wxml 结构、wxss 组件选择器、token 显式值断言)
- 声明级体检 88/88 通过(全部 wxss 声明合法)

交付物:artifacts/miniapp-design-v2-preview.html
2026-09-23 01:06:46 +08:00

376 lines
16 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 丹阳公益婚恋服务平台 - 全局 Design Token
*
* v2(2026-09-22 设计系统夯实)
* ---------------------------------------------------------------
* 本次修订针对审计发现的系统性问题,逐条给出依据:
*
* 1) 品牌色不能承载文字 → 引入「基础色 / -strong」分级
* #E96B6B on 白 = 3.10:1,白字 on #E96B6B = 3.10:1,on #FFF3F2 = 2.85:1,
* 三条路径都不满足正文 4.5:1。故:
* --color-primary 仅用于大色块、渐变、光晕、装饰(非文字)
* --color-primary-strong 用于文字、小图标、纯文字链接(5.33:1 ✓)
* --color-primary-solid 实心按钮底(白字 ≥4.5:1 ✓)
* 功能色(success/warning/danger/info)同此分级。
*
* 2) 次要文字对比度过低
* 旧 --color-text-tertiary(#777) = 4.48(on 白,勉强)/ #999 实测 2.85 却被用了 71 次。
* 现将三级文字压到 #646C85 = 5.22:1,占位符保留浅色(占位符非正文)。
*
* 3) 颜色碎片化
* 审计前全站 182 种 hex、770 次硬编码(54 种灰、60 种蓝紫、40 种红橙)。
* 本文件是唯一的颜色事实源;页面层禁止再写 hex,一律 var(--token)。
*
* 4) 触摸目标
* 组件库默认按钮只有 40px、小号 28px、"喜欢"按钮 31px。
* 统一以 --tap-min(88rpx=44px) 为下限,--tap-gap 为最小间距。
*
* 5) 动效几乎未落地(--motion-* 全站仅 5 次引用)
* 补充 --ease-spring 与 --press-scale,让点击有即时反馈。
*
* 6) 夜间氛围层缺失(参考图有明显的光晕/星点,代码只有纯渐变)
* 新增 --mini-glow-* / --mini-star / --mini-glass / --mini-hairline。
*
* 单位说明:rpx(750rpx = 屏幕宽度,1rpx ≈ 0.5px @375pt)
* 旧 token 名全部保留(88 个 wxss 共 909 处引用),只更新取值,避免大范围失效。
*/
page {
/* ============ 品牌主色(分级:色块 / 文字 / 实心按钮) ============ */
--color-primary: #E96B6B; /* 基础色:渐变、光晕、装饰、非文字图形 */
--color-primary-strong: #B8434A; /* 文字与小图标(5.33:1 on 白,4.91:1 on 浅粉底) */
--color-primary-solid: #C24C50; /* 实心按钮底(白字 4.62:1) */
--color-primary-active: #D95F5F; /* 按压态(配合 --color-primary 使用) */
--color-primary-light: #FFF3F2;
--color-primary-lighter: #FFF8F7;
/* ============ 小程序参考图品牌主题(夜间紫蓝) ============ */
--mini-night-start: #172A72;
--mini-night-end: #25104F;
--mini-night-soft: #3445A1;
--mini-accent-pink: #FF4F91; /* 点缀色:仅用于色块/装饰,不作正文 */
--mini-accent-coral: #FF6A78;
--mini-card-bg: rgba(255, 255, 255, 0.98);
--mini-text: #1F2744;
--mini-muted: #7D839B;
--mini-card-radius: 24rpx;
--mini-text-on-night: #FFFFFF; /* on 深底 13.04:1 ✓ */
--mini-text-on-night-muted: rgba(255, 255, 255, 0.72); /* on 深底 ≈8:1 ✓ */
--mini-shadow: 0 16rpx 40rpx rgba(28, 30, 88, 0.14);
/* ---- 渐变(集中定义:此前 4 个页面各写了一份「橙红渐变」按钮) ---- */
/* --gradient-brand 明亮活泼,但白字仅 2.77:1 —— 只能用于无文字的装饰填充。 */
--gradient-brand: linear-gradient(135deg, #FF6A78 0%, #E96B6B 100%);
/* 承载白字的 CTA 渐变:两端 #C24C50(4.73:1) / #B8434A(5.33:1) 均达标。 */
--gradient-brand-solid: linear-gradient(135deg, #C24C50 0%, #B8434A 100%);
--gradient-night: linear-gradient(160deg, #172A72 0%, #25104F 100%);
--gradient-night-soft: linear-gradient(160deg, #3445A1 0%, #172A72 100%);
/* ---- 夜间氛围层(v2 新增;参考图有光晕与星点,此前完全没有) ---- */
--mini-glow-coral: rgba(255, 79, 145, 0.40);
--mini-glow-indigo: rgba(94, 124, 255, 0.32);
--mini-glow-soft: rgba(255, 255, 255, 0.10);
--mini-star: rgba(255, 255, 255, 0.70);
--mini-glass: rgba(255, 255, 255, 0.10); /* 深底玻璃面 */
--mini-glass-strong: rgba(255, 255, 255, 0.16);
--mini-hairline: rgba(255, 255, 255, 0.16); /* 深底分隔线 */
--mini-glass-success: rgba(90, 226, 184, 0.16); /* 深底上的成功态玻璃面 */
/* 星点层:多个小径向渐变叠在夜空渐变之上。用 radial-gradient 而非图片,
避免额外请求,也便于随主题换色(index 页脚注:装饰层不承载信息)。 */
--mini-starfield:
radial-gradient(circle at 12% 18%, var(--mini-star) 0, transparent 2.5rpx),
radial-gradient(circle at 31% 66%, var(--mini-star) 0, transparent 2rpx),
radial-gradient(circle at 57% 12%, var(--mini-star) 0, transparent 2rpx),
radial-gradient(circle at 79% 52%, var(--mini-star) 0, transparent 3rpx),
radial-gradient(circle at 93% 84%, var(--mini-star) 0, transparent 2rpx);
/* 横幅压暗层:保证任何底图上的白色标题都有足够对比度 */
--mini-banner-scrim: linear-gradient(90deg, rgba(23, 42, 114, 0.84) 0%, rgba(37, 16, 79, 0.40) 56%, rgba(255, 79, 145, 0.12) 100%);
/* ============ 功能色(同样分级) ============ */
--color-success: #2E9B68; /* 色块/图标 */
--color-success-strong: #17805A; /* 文字(4.92:1 ✓) */
--color-success-light: #ECF8F2;
--color-warning: #E59A32; /* 色块/图标(作文字仅 2.33:1) */
--color-warning-strong: #9C5F14; /* 文字(5.17:1 ✓) */
--color-warning-light: #FFF7E9;
--color-danger: #D94A4A; /* 色块/图标 */
--color-danger-strong: #C62828; /* 文字(5.62:1 ✓) */
--color-danger-light: #FFF0F0;
--color-info: #4A7CD4; /* 色块/图标 */
--color-info-strong: #2A5DB0; /* 文字(6.38:1 ✓) */
--color-info-light: #EEF4FF;
/* ============ 强调紫(参考图的标签语言;此前散落成 6 种写法) ============ */
--color-accent-purple: #8B63BC; /* 色块/装饰 */
--color-accent-purple-strong: #7C60BC; /* 文字(5.03:1 ✓) */
--color-accent-purple-light: #F3EEFF;
/* 深色夜空底上的强调色(不可用于浅色底) */
--color-success-on-night: #A6F5D7; /* on #172A72 = 10.35:1 ✓ */
/* ============ 文字色(实测对比度 on 白 / on 页面底) ============ */
--color-text-strong: #1A1F36; /* 标题 16.24 / 14.90 ✓ */
--color-text-primary: #2A3050; /* 正文 12.83 / 11.77 ✓ */
--color-text-secondary: #4A5169; /* 次要正文 7.86 / 7.21 ✓ */
--color-text-tertiary: #646C85; /* 说明文字 5.22 / 4.79 ✓(旧 #777 为 4.48) */
--color-text-placeholder: #9AA1B4; /* 占位符(非正文,可浅) */
--color-text-disabled: #B8BDC9;
--color-text-inverse: #FFFFFF; /* 深色背景上的文字 */
/* ============ 边框与分割线 ============ */
--color-border: #E6E8EF;
--color-border-strong: #D8DBE5;
--color-divider: #EFF0F5;
--color-border-focus: #B8434A; /* 焦点环用 strong,保证 3:1 可见度 */
--color-border-error: #C62828;
/* ============ 背景(避免纯白/纯灰平铺,页面底为暖白) ============ */
--color-bg-page: #F6F5F3;
--color-bg-card: #FFFFFF;
--color-bg-subtle: #F5F6FA; /* 次级区块、内嵌列表 */
--color-bg-muted: #EEF0F6; /* 更弱的填充 */
--color-bg-input: #F7F8FB; /* 表单输入框底(此前被引用但从未定义,导致背景失效) */
--color-bg-disabled: #F3F4F7;
--color-bg-overlay: rgba(0, 0, 0, 0.45);
/* ============ 字体 ============ */
/* 小程序无法可靠加载 Web Font(wx.loadFontFace 依赖 HTTPS 白名单且有闪动风险),
故使用中文系统字栈:iOS 走苹方、Android 走思源/系统黑体。
排版辨识度靠字号阶梯与字重建立,而非依赖字体本身。 */
--font-family-cn: -apple-system, "PingFang SC", "Noto Sans SC", "Hiragino Sans GB", "Microsoft YaHei", system-ui, sans-serif;
--font-family-number: "SF Pro Display", -apple-system, "DIN Alternate", "PingFang SC", sans-serif;
/* 字号阶梯 —— 正文 32rpx(16px) 起,元信息下限 24rpx(12px) */
--font-size-micro: 22rpx; /* 11px 仅角标/装饰,禁用于正文 */
--font-size-xs: 24rpx; /* 12px 元信息下限 */
--font-size-sm: 26rpx; /* 13px 次要说明 */
--font-size-md: 28rpx; /* 14px 次要正文 */
--font-size-base: 32rpx; /* 16px 正文 */
--font-size-lg: 36rpx; /* 18px 小标题 */
--font-size-xl: 40rpx; /* 20px 区块标题 */
--font-size-2xl: 48rpx; /* 24px 页面标题 */
--font-size-3xl: 56rpx; /* 28px 大标题 */
--font-size-display: 64rpx; /* 32px Hero */
/* 字重:只用 4 档。禁止 550/650/750 等非百位值 —— Android 无对应字重会回退,
导致同一设计在不同机型上粗细不一致(审计发现 30 处)。 */
--font-weight-regular: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
--line-height-tight: 1.25;
--line-height-normal: 1.5;
--line-height-relaxed: 1.65;
--letter-spacing-tight: 0;
--letter-spacing-wide: 1rpx;
--letter-spacing-wider: 2rpx;
/* ============ 间距(4px 栅格) ============ */
--spacing-1: 8rpx;
--spacing-2: 16rpx;
--spacing-3: 24rpx;
--spacing-4: 32rpx;
--spacing-5: 40rpx;
--spacing-6: 48rpx;
--spacing-8: 64rpx;
--spacing-10: 80rpx;
--spacing-12: 96rpx;
--spacing-page-x: 32rpx;
--spacing-section: 48rpx;
--spacing-card-inner: 32rpx;
--spacing-tight: 16rpx;
/* ============ 圆角 ============ */
--radius-sm: 16rpx;
--radius-md: 24rpx;
--radius-lg: 32rpx;
--radius-xl: 40rpx;
--radius-2xl: 48rpx;
--radius-full: 9999rpx;
/* ============ 阴影(统一为一套,此前 30+ 种近似值) ============ */
--shadow-card: 0 8rpx 28rpx rgba(35, 35, 95, 0.07);
--shadow-raised: 0 12rpx 36rpx rgba(35, 35, 95, 0.10);
--shadow-popup: 0 16rpx 64rpx rgba(0, 0, 0, 0.10);
--shadow-night: 0 16rpx 40rpx rgba(28, 30, 88, 0.18);
/* ============ 边框宽度 ============ */
--border-width: 1rpx;
--border-width-strong: 2rpx;
/* ============ 触摸目标(无障碍下限 44×44px) ============ */
--tap-min: 88rpx; /* 44px 最小可点区域 */
--tap-comfortable: 96rpx; /* 48px 舒适尺寸:主操作 */
--tap-gap: 16rpx; /* 8px 相邻目标最小间距 */
/* ============ 动效 ============ */
--motion-fast: 120ms;
--motion-normal: 200ms;
--motion-slow: 300ms;
--ease-standard: cubic-bezier(0.32, 0.72, 0, 1);
--ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
--press-scale: 0.97;
--press-opacity: 0.88;
/* ============ 层级 z-index ============ */
--z-base: 1;
--z-sticky: 100;
--z-tabbar: 200;
--z-dropdown: 500;
--z-modal: 1000;
--z-toast: 2000;
--z-ambient: 0;
/* ============ 页面基础样式 ============ */
background-color: var(--color-bg-page);
font-family: var(--font-family-cn);
font-size: var(--font-size-base);
color: var(--color-text-primary);
line-height: var(--line-height-normal);
}
/* ==========================================================================
通用工具类
========================================================================== */
.container {
padding: var(--spacing-page-x);
}
.flex { display: flex; }
.flex-column { display: flex; flex-direction: column; }
.flex-center { display: flex; align-items: center; justify-content: center; }
.flex-between { display: flex; align-items: center; justify-content: space-between; }
.flex-start { display: flex; align-items: center; justify-content: flex-start; }
.flex-1 { flex: 1; min-width: 0; }
.flex-shrink-0 { flex-shrink: 0; }
.wrap { flex-wrap: wrap; }
/* 4 列宫格:用 flex + 百分比宽度实现。
注:display:grid 在 WebView 渲染下可用,但 Skyline 不支持,故统一改为 flex 以免疫渲染引擎迁移。*/
.grid-4 {
display: flex;
flex-wrap: wrap;
}
.grid-4 > .grid-item {
width: 25%;
box-sizing: border-box;
}
.text-strong { color: var(--color-text-strong); }
.text-primary { color: var(--color-text-primary); }
.text-secondary { color: var(--color-text-secondary); }
.text-tertiary { color: var(--color-text-tertiary); }
.text-placeholder { color: var(--color-text-placeholder); }
.text-white { color: var(--color-text-inverse); }
.text-brand { color: var(--color-primary-strong); }
/* 品牌色作文字只能用 -strong 变体:基础色 #E96B6B 在白底仅 3.10:1。
保留 .text-brand-soft 这个类名是为了不破坏既有引用,取值已统一到 -strong,
如需「更亮的品牌色」请用于背景/图形而非文字。 */
.text-brand-soft { color: var(--color-primary-strong); }
.text-success { color: var(--color-success-strong); }
.text-warning { color: var(--color-warning-strong); }
.text-danger { color: var(--color-danger-strong); }
.text-info { color: var(--color-info-strong); }
.font-micro { font-size: var(--font-size-micro); }
.font-xs { font-size: var(--font-size-xs); }
.font-sm { font-size: var(--font-size-sm); }
.font-md { font-size: var(--font-size-md); }
.font-base { font-size: var(--font-size-base); }
.font-lg { font-size: var(--font-size-lg); }
.font-xl { font-size: var(--font-size-xl); }
.font-2xl { font-size: var(--font-size-2xl); }
.font-3xl { font-size: var(--font-size-3xl); }
.font-display { font-size: var(--font-size-display); }
.font-regular { font-weight: var(--font-weight-regular); }
.font-medium { font-weight: var(--font-weight-medium); }
.font-semibold { font-weight: var(--font-weight-semibold); }
.font-bold { font-weight: var(--font-weight-bold); }
.mt-1 { margin-top: var(--spacing-1); }
.mt-2 { margin-top: var(--spacing-2); }
.mt-3 { margin-top: var(--spacing-3); }
.mt-4 { margin-top: var(--spacing-4); }
.mt-5 { margin-top: var(--spacing-5); }
.mt-6 { margin-top: var(--spacing-6); }
.mb-1 { margin-bottom: var(--spacing-1); }
.mb-2 { margin-bottom: var(--spacing-2); }
.mb-3 { margin-bottom: var(--spacing-3); }
.mb-4 { margin-bottom: var(--spacing-4); }
.mb-5 { margin-bottom: var(--spacing-5); }
.mb-6 { margin-bottom: var(--spacing-6); }
/* 文本省略 */
.ellipsis {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.ellipsis-2 {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
/* 安全区底部留白(避开 Home Indicator) */
.safe-area-bottom {
padding-bottom: env(safe-area-inset-bottom);
}
/* 页面卡片基础样式 */
.card-base {
background: var(--color-bg-card);
border-radius: var(--radius-lg);
padding: var(--spacing-card-inner);
box-shadow: var(--shadow-card);
}
/* 分割线 */
.divider {
height: var(--border-width);
background: var(--color-divider);
}
/* ==========================================================================
可访问性工具类(v2 新增)
========================================================================== */
/* 保证任意可点元素达到 44×44px 热区,且视觉尺寸可独立控制 */
.tap-min {
min-width: var(--tap-min);
min-height: var(--tap-min);
display: flex;
align-items: center;
justify-content: center;
}
/* 相邻可点元素之间的最小间距 */
.tap-gap > * + * {
margin-left: var(--tap-gap);
}
/* 焦点可见(小程序支持键盘/无障碍焦点) */
.focusable:focus,
.focusable:focus-visible {
outline: 4rpx solid var(--color-border-focus);
outline-offset: 2rpx;
}
/* 按压反馈:所有可点元素统一使用,替代"点了没反应" */
.pressable {
transition: transform var(--motion-fast) var(--ease-spring),
opacity var(--motion-fast) var(--ease-standard);
}
.pressable:active {
transform: scale(var(--press-scale));
opacity: var(--press-opacity);
}