Files
danyang-match/admin-web/src/theme/index.css
T
WorkBuddy 3c2b967274
CI/CD Pipeline / UI Contracts (source-structure gates) (push) Canceled after 0s
CI/CD Pipeline / E2E (live stack) (push) Canceled after 0s
CI/CD Pipeline / Backend Build & Test (push) Canceled after 0s
CI/CD Pipeline / Admin Web Build (push) Canceled after 0s
CI/CD Pipeline / Mini Program Compile Check (push) Canceled after 0s
CI/CD Pipeline / Migration Validation (push) Canceled after 0s
CI/CD Pipeline / Test Shell Guard (Phase 23 Gate) (push) Canceled after 0s
release: freeze 2026-10-15 validated release baseline
2026-10-15 09:47:31 +08:00

423 lines
18 KiB
CSS
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.
/* ============================================================================
* 管理端设计系统 · v2
*
* 本文件是管理端唯一的设计 token 事实源。24 个 .vue 的 <style> 只允许通过
* var(--token) 取色 / 取字号 / 取间距,不应出现字面色值(由门控脚本
* scripts/lint-admin-tokens.mjs 拦截)。
*
* 立此版本的原因(2026-09-22 审计实测,不是主观判断):
* · 97 处硬编码颜色 / 67 种色值:6 种近似粉底(#FFF0F1 #FFF3F2 #FFF6F6
* #FFF7F7 #FFF8F7 #FFFAFA)、6 种近似浅灰边框、大量灰阶碎片。
* · 88 处硬编码字号 / 23 种档位,其中 20 处 ≤11px(9px 见于 .metric-copy em、
* .activity-status、.todo-copy small),低于可读下限。
* · --color-text-tertiary(#888888) 白底 3.54:1、--color-warning(#E59A32) 2.33:1、
* --admin-coral(#F45F68) 3.14:1 —— 在各自用法下均不达 WCAG AA 的 4.5:1。
* · Element Plus 的 --el-color-*-light-N / -dark-2 / -rgb 是**编译期静态生成**的,
* 项目只覆盖了 --el-color-primary,于是开关、滑块、焦点环、分页、标签等
* 组件仍是默认蓝 —— 品牌色与 EP 蓝混用。
*
* 三条硬规则:
* 1) 品牌色三级分化:基础色只做色块/渐变/图形(不承载文字);
* -strong 做白底文字;-solid 做实心底压白字;两者均实算 ≥4.5:1。
* 2) 字重只用 400 / 500 / 600 / 700 四档(跨平台缺字重会回退,导致渲染不一致)。
* 3) 字号有下限:正文最小 12px,角标/计数不得低于 11px。
*
* 所有对比度数值均由脚本按 WCAG 相对亮度公式实算(非估算),标注在各 token 后。
* ========================================================================== */
:root {
/* ---------------- 品牌色 ---------------- */
/* 基础色:仅用于色块 / 渐变 / 图标 / 边框氛围。白底作文字只有 3.14:1,禁止承载文字。 */
--admin-coral: #F45F68;
--admin-coral-hover: #E5535D;
--admin-coral-strong: #C0414A; /* 白底文字 5.13:1 */
--admin-coral-solid: #C84A53; /* 实心底压白字 4.60:1 */
--admin-coral-solid-hover: #B8434A; /* hover 反而更深更清晰 5.33:1 */
--admin-coral-on-dark: #FF969C; /* 侧栏深底文字 6.76:1 */
--admin-coral-soft: #FFF0F1; /* 品牌浅底(角标 / 选中态底) */
--admin-coral-lighter: #FFF8F7; /* 更浅一档,hover 底 */
--admin-coral-border: rgba(244, 95, 104, 0.22);
--admin-scene-bg-start: #FFEDEE;
--admin-scene-bg-mid: #FFF6F4;
--admin-scene-bg-end: #FBF5F4;
--admin-scene-glow: rgba(244, 95, 104, 0.28);
--admin-scene-glow-soft: rgba(255, 150, 170, 0.22);
--admin-scene-surface: rgba(255, 255, 255, 0.65);
--admin-scene-border: rgba(244, 95, 104, 0.18);
--admin-scene-divider: rgba(244, 95, 104, 0.30);
/* 承载白字的品牌渐变(两端均 ≥4.5:1)。基础色渐变见 --gradient-brand-vivid。 */
--gradient-brand-solid: linear-gradient(135deg, #C84A53 0%, #B8434A 100%);
/* 文字用渐变(background-clip:text):比 solid 更鲜亮,用于「善缘丹阳」等大字号品牌标题 */
--gradient-brand-text: linear-gradient(135deg, #FF7D6E 0%, #E8475D 60%, #B8434A 100%);
/* 鲜亮品牌渐变:只允许用在「无文字覆盖」的装饰,或预览态还原(如 Banner 预览)。 */
--gradient-brand-vivid: linear-gradient(135deg, #FF7D6E 0%, #FF5C82 100%);
--gradient-brand-soft: linear-gradient(135deg, #FFE9DF 0%, #FFF7F2 100%);
/* 水平进度条填充(对轨道 --color-primary-light):原 #F56B75→#EF5A65 仅 2.53:1,
条与轨道难以区分;改达标渐变后 4.01:1。 */
--gradient-brand-bar: linear-gradient(90deg, #C84A53 0%, #B8434A 100%);
/* 兼容既有引用名(全站仍在用) */
--admin-primary: var(--admin-coral);
--admin-primary-hover: var(--admin-coral-hover);
--admin-primary-strong: var(--admin-coral-strong);
--admin-primary-solid: var(--admin-coral-solid);
--color-primary: var(--admin-coral);
--color-primary-hover: var(--admin-coral-hover);
--color-primary-strong: var(--admin-coral-strong);
--color-primary-solid: var(--admin-coral-solid);
--color-primary-light: var(--admin-coral-soft);
--color-primary-lighter: var(--admin-coral-lighter);
/* ---------------- 语义色五组 ----------------
基色做图形/色块;-strong 做文字(实算 ≥4.5:1);-soft 为配套浅底。 */
--color-success: #2E9B68; /* 白底 3.50:1 —— 仅图形 */
--color-success-strong: #1F7A4F; /* 白底 5.31:1 */
--color-success-soft: #EDF8F1;
--color-warning: #E59A32; /* 白底 2.33:1 —— 仅图形 */
--color-warning-strong: #8F5D0F; /* 白底 5.61:1 */
--color-warning-soft: #FFF6E6;
--color-danger: #D94A4A; /* 白底 4.18:1 —— 图形 / ≥24px 大字 */
--color-danger-strong: #B8353A; /* 白底 5.82:1 */
--color-danger-soft: #FFF6F6;
--color-info: #4A7CD4; /* 白底 4.10:1 —— 图形 */
--color-info-strong: #3A63B0; /* 白底 5.85:1 */
--color-info-soft: #EEF5FF;
--color-purple: #8B63BC;
--color-purple-strong: #6B47A0; /* 白底 6.92:1 */
--color-purple-soft: #F4EFFF;
--color-neutral: #8A9099;
--color-neutral-strong: #656C79; /* 白底 5.28:1 */
--color-neutral-soft: #F4F5F7;
/* ---------------- 文字 ---------------- */
--color-text-primary: #1F2328; /* 白底 15.80:1 */
--color-text-secondary: #555555; /* 白底 7.46:1 */
--color-text-tertiary: #676E7B; /* 白底 5.13:1;浅底 #F5F6F8 上 4.74:1(原 #888 仅 3.54:1) */
--color-text-placeholder: #8A9099; /* 3.25:1:占位符按惯例弱于正文一档(EP 默认 2.5:1) */
--color-text-disabled: #B9BEC7;
--color-text-inverse: #FFFFFF;
--color-text-on-dark: #D9E1E6; /* 侧栏深底 10.62:1 */
--color-text-on-dark-muted: #8FA1AC; /* 侧栏深底 5.26:1 */
--color-icon-muted: #D7DCE0; /* 空态大图标等纯装饰 */
/* ---------------- 背景 ---------------- */
--color-bg-primary: #FFFFFF;
--color-bg-page: #F7F9FB;
--color-bg-secondary: #FAFAFB;
--color-bg-subtle: #F5F6F8;
--color-bg-input: #F6F7F8;
--color-bg-overlay: rgba(255, 255, 255, 0.86);
--color-bg-overlay-strong: rgba(255, 255, 255, 0.96);
/* ---------------- 边框 ---------------- */
--color-border: #E4E7EB;
--color-border-light: #EDF0F2;
--color-border-hairline: #F2F3F4;
--color-border-strong: #D7DCE0;
--color-border-danger: #F3CCCC;
/* ---------------- 侧栏(深底) ---------------- */
--admin-sidebar-bg: #202D38;
--admin-sidebar-bg-deep: #192733;
--admin-sidebar-gradient: linear-gradient(180deg, #202D38 0%, #192733 100%);
--admin-sidebar-surface: #2B3A46;
--admin-sidebar-text: #D9E1E6;
--admin-sidebar-muted: #8FA1AC;
--admin-sidebar-hairline: rgba(255, 255, 255, 0.08);
--admin-sidebar-hairline-soft: rgba(255, 255, 255, 0.06);
/* ---------------- 壳与栅格 ---------------- */
--admin-shell-bg: rgba(255, 255, 255, 0.96);
--admin-header-bg: #FFFFFF;
--admin-shell-radius: 22px;
--admin-card-radius: 14px;
--admin-shell-max-width: 1840px;
--admin-page-max-width: 1440px;
--admin-content-max-width: 1500px;
--sidebar-width: 220px;
--sidebar-width-collapsed: 76px;
--header-height: 64px;
/* ---------------- 圆角 ---------------- */
--border-radius-xs: 6px;
--border-radius-sm: 8px;
--border-radius-md: 14px;
--border-radius-lg: 16px;
--border-radius-xl: 18px;
--border-radius-pill: 999px;
/* ---------------- 阴影 ---------------- */
--shadow-panel: 0 8px 20px rgba(48, 58, 67, 0.035);
--shadow-card: 0 8px 24px rgba(75, 55, 46, 0.06);
--shadow-raise: 0 10px 24px rgba(68, 48, 55, 0.1);
--shadow-brand: 0 8px 18px rgba(200, 74, 83, 0.26);
--admin-shadow: 0 18px 48px rgba(57, 40, 45, 0.14);
/* ---------------- 排版刻度 ----------------
正文 14px 起;角标/计数下限 11px;元信息下限 12px。 */
--font-family-base: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
--font-family-brand: KaiTi, STKaiti, serif; /* 品牌书法体:仅装饰性标语 */
--font-size-micro: 11px;
--font-size-xs: 12px;
--font-size-sm: 13px;
--font-size-base: 14px;
--font-size-md: 15px;
--font-size-lg: 16px;
--font-size-xl: 18px;
--font-size-2xl: 20px;
--font-size-3xl: 24px;
--font-size-4xl: 28px;
--font-size-5xl: 32px;
--font-size-display: 38px;
--font-line-tight: 1.2;
--font-line-snug: 1.35;
--font-line-base: 1.6;
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
/* ---------------- 间距 ---------------- */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
/* ---------------- 动效 ---------------- */
--motion-fast: 140ms;
--motion-normal: 200ms;
--motion-slow: 320ms;
--ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--press-scale: 0.985;
--press-opacity: 0.88;
/* ---------------- 交互热区 ----------------
桌面端按下限为 WCAG 2.5.8(AA) 的 24×24px;本项目常规控件取 32px(舒适),
主导航行取 44px(兼顾触屏笔记本)。不套用移动端 44px 全量规则,
否则会把管理端的单屏信息密度牺牲掉。 */
--tap-min: 44px;
--tap-control: 32px;
--tap-icon: 36px;
/* ---------------- tone 色调组(工作台指标卡 / 待办图标) ----------------
每组三档:--tone-x 用于图标与图形;--tone-x-ink 用于文字(压 --tone-x-soft
实算均 ≥4.6:1);--tone-x-soft 为浅底。 */
--tone-rose: #F45F68; --tone-rose-ink: var(--admin-coral-strong); --tone-rose-soft: #FFF0F1;
--tone-amber: #E59A32; --tone-amber-ink: var(--color-warning-strong); --tone-amber-soft: #FFF6E6;
--tone-blue: #4A7CD4; --tone-blue-ink: var(--color-info-strong); --tone-blue-soft: #EEF5FF;
--tone-green: #2E9B68; --tone-green-ink: var(--color-success-strong); --tone-green-soft: #EDF8F1;
--tone-purple: #8B63BC; --tone-purple-ink: var(--color-purple-strong); --tone-purple-soft: #F4EFFF;
--tone-slate: #8A9099; --tone-slate-ink: var(--color-neutral-strong); --tone-slate-soft: #F4F5F7;
--tone-red: #D94A4A; --tone-red-ink: var(--color-danger-strong); --tone-red-soft: #FFF6F6;
/* 兼容既有引用名 */
--admin-soft-pink: var(--admin-coral-soft);
--admin-soft-blue: var(--color-info-soft);
--admin-soft-green: var(--color-success-soft);
--admin-soft-purple: var(--color-purple-soft);
/* ==========================================================================
Element Plus 联动
EP 的 --el-color-{t}-light-{i} / -dark-2 / -rgb 由 SCSS 在**编译期**按默认色
静态生成,运行时改 --el-color-primary 不会带动它们(开关、滑块、焦点环、
分页、标签因此仍是默认蓝)。这里按 EP 的派生公式补全:
light-{i} = mix(#FFFFFF, base, i*10%) i ∈ 1..9
dark-2 = mix(#000000, base, 20%)
基色取 -strong / -solid 档 —— 既能当文字色也能做实心底,使 EP 全组件与品牌一致。
info 保持中性灰:EP 的 info 语义是「中性/未知」,不应变成品牌红。
========================================================================== */
--el-color-primary: #C84A53;
--el-color-primary-rgb: 200, 74, 83;
--el-color-primary-light-3: #d98087;
--el-color-primary-light-5: #e4a5a9;
--el-color-primary-light-7: #efc9cb;
--el-color-primary-light-8: #f4dbdd;
--el-color-primary-light-9: #faedee;
--el-color-primary-dark-2: #a03b42;
--el-color-success: #1F7A4F;
--el-color-success-rgb: 31, 122, 79;
--el-color-success-light-3: #62a284;
--el-color-success-light-5: #8fbda7;
--el-color-success-light-7: #bcd7ca;
--el-color-success-light-8: #d2e4dc;
--el-color-success-light-9: #e9f2ed;
--el-color-success-dark-2: #19623f;
--el-color-warning: #8F5D0F;
--el-color-warning-rgb: 143, 93, 15;
--el-color-warning-light-3: #b18e57;
--el-color-warning-light-5: #c7ae87;
--el-color-warning-light-7: #ddceb7;
--el-color-warning-light-8: #e9dfcf;
--el-color-warning-light-9: #f4efe7;
--el-color-warning-dark-2: #724a0c;
--el-color-danger: #B8353A;
--el-color-danger-rgb: 184, 53, 58;
--el-color-danger-light-3: #cd7275;
--el-color-danger-light-5: #dc9a9d;
--el-color-danger-light-7: #eac2c4;
--el-color-danger-light-8: #f1d7d8;
--el-color-danger-light-9: #f8ebeb;
--el-color-danger-dark-2: #932a2e;
--el-color-info: #656C79;
--el-color-info-rgb: 101, 108, 121;
--el-color-info-light-3: #9398a1;
--el-color-info-light-5: #b2b6bc;
--el-color-info-light-7: #d1d3d7;
--el-color-info-light-8: #e0e2e4;
--el-color-info-light-9: #f0f0f2;
--el-color-info-dark-2: #515661;
/* EP 中性色(文字 / 边框 / 填充)接到同一套 token,避免表格、输入框另成一套灰 */
--el-text-color-primary: var(--color-text-primary);
--el-text-color-regular: var(--color-text-secondary);
--el-text-color-secondary: var(--color-text-tertiary);
--el-text-color-placeholder: var(--color-text-placeholder);
--el-text-color-disabled: var(--color-text-disabled);
--el-border-color: var(--color-border);
--el-border-color-light: var(--color-border-light);
--el-border-color-lighter: var(--color-border-light);
--el-border-color-extra-light: var(--color-border-hairline);
--el-fill-color: var(--color-bg-subtle);
--el-fill-color-light: var(--color-bg-secondary);
--el-fill-color-lighter: var(--color-bg-secondary);
--el-bg-color: var(--color-bg-primary);
--el-bg-color-page: var(--color-bg-page);
--el-border-radius-base: var(--border-radius-sm);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body, #app {
width: 100%;
height: 100%;
font-family: var(--font-family-base);
font-size: var(--font-size-base);
color: var(--color-text-primary);
background-color: var(--color-bg-page);
}
/* 管理端是桌面密度布局,1100px 以下由 MainLayout 的 .admin-scene 承担横向滚动。 */
body { min-width: 1100px; }
/* <small> 的浏览器默认样式是 font-size: smaller(0.833em),会按父级字号再缩一档:
父级 12px 时实际渲染 10px、11px 时渲染 9.17px —— 静默跌破 11px 下限,
且源码里看不到任何非法字号,静态检查抓不到(2026-09-22 由渲染态实测发现)。
这里统一改为继承父级字号,需要更小的场景必须显式声明 token 字号(守卫会校验)。 */
small { font-size: inherit; }
button:focus-visible,
a:focus-visible,
input:focus-visible,
[tabindex]:focus-visible {
outline: 3px solid var(--admin-coral-border);
outline-offset: 2px;
}
/* ---------------- Element Plus 组件级覆盖 ---------------- */
/* EP 默认 hover 是把主色「加白」(白字对比度随之掉到 2.2:1)。这里改成更深一档,
既保住白字可读性(5.33:1),hover 反馈也更明确。 */
.el-button--primary {
--el-button-bg-color: var(--admin-coral-solid);
--el-button-border-color: var(--admin-coral-solid);
--el-button-hover-bg-color: var(--admin-coral-solid-hover);
--el-button-hover-border-color: var(--admin-coral-solid-hover);
--el-button-active-bg-color: var(--el-color-primary-dark-2);
--el-button-active-border-color: var(--el-color-primary-dark-2);
}
.el-radio-group .el-radio-button__inner:checked {
background-color: var(--admin-coral-solid);
border-color: var(--admin-coral-solid);
}
.el-card {
--el-card-border-radius: var(--border-radius-md);
--el-card-border-color: var(--color-border-light);
}
.el-table {
--el-table-header-bg-color: var(--color-bg-secondary);
--el-table-border-color: var(--color-border-light);
}
.el-tag { border-radius: var(--border-radius-pill); }
/* ---------------- 通用版式 ---------------- */
.page-container { padding: var(--space-6); }
.page-shell { max-width: var(--admin-page-max-width); margin: 0 auto; }
.page-heading {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: var(--space-4);
margin-bottom: var(--space-5);
}
.page-heading h1 {
font-size: var(--font-size-3xl);
line-height: var(--font-line-snug);
font-weight: var(--font-weight-semibold);
}
.page-heading p { margin-top: 6px; color: var(--color-text-tertiary); }
.surface-card {
background: var(--color-bg-primary);
border: 1px solid var(--color-border-light);
border-radius: var(--border-radius-md);
box-shadow: var(--shadow-card);
}
/* 语义文字色工具类(比在页面里各写一遍 color: #xxx 更不容易漂移) */
.text-primary { color: var(--color-text-primary); }
.text-secondary { color: var(--color-text-secondary); }
.text-tertiary { color: var(--color-text-tertiary); }
.text-muted { color: var(--color-text-tertiary); }
.text-brand { color: var(--admin-coral-strong); }
.text-success { color: var(--color-success-strong); }
.text-warning { color: var(--color-warning-strong); }
.text-danger { color: var(--color-danger-strong); }
/* 语义底色工具类 */
.bg-card { background: var(--color-bg-primary); }
.bg-subtle { background: var(--color-bg-subtle); }
.bg-brand-soft { background: var(--admin-coral-soft); }
/* 间距工具类 */
.mt-sm { margin-top: var(--space-2); }
.mt-md { margin-top: var(--space-4); }
.mt-lg { margin-top: var(--space-6); }
.mb-sm { margin-bottom: var(--space-2); }
.mb-md { margin-bottom: var(--space-4); }
.mb-lg { margin-bottom: var(--space-6); }
.flex-center { display: flex; align-items: center; justify-content: center; }
/* ---------------- 交互反馈 ---------------- */
/* 桌面端控件热区下限:32px(WCAG 2.5.8 AA 为 24px,留出舒适余量) */
.tap-control { min-height: var(--tap-control); min-width: var(--tap-control); }
/* 按压反馈:统一走 token,避免各页面各写一套 scale/opacity */
.pressable { transition: transform var(--motion-fast) var(--ease-standard), opacity var(--motion-fast) var(--ease-standard); }
.pressable:active { transform: scale(var(--press-scale)); opacity: var(--press-opacity); }
@media (max-width: 1200px) {
body { min-width: 0; }
}
@media (max-width: 900px) {
.page-container { padding: var(--space-4); }
.page-heading { align-items: flex-start; flex-direction: column; }
}