23 KiB
23 KiB
前端优化方案与设计规范文档
基于: 前端项目分析报告.md
日期: 2026-05-13
原则: 简洁、高可读性、高可操作性、统一白色体系
第一部分:色彩规范优化方案(白色体系)
1.1 设计理念
采用白色及白色不同色调作为唯一设计色彩体系,遵循以下原则:
- 以白色为基础,通过不同的灰度层级区分信息重要程度和视觉层次
- 去除所有彩色渐变背景,回归简洁干净的商业软件风格
- 仅保留少量必要的功能色用于状态标识(成功/警告/错误)
- 确保所有文字与背景对比度满足 WCAG 2.1 AA 级标准(至少 4.5:1)
1.2 完整色值定义
基础色板(白 → 黑灰度层级)
:root {
/* ===== 白色体系 - 背景色 ===== */
--bg-page: #FFFFFF; /* 页面背景 - 纯白 */
--bg-container: #F8F9FA; /* 容器背景 - 极浅灰 */
--bg-card: #FFFFFF; /* 卡片背景 - 纯白 */
--bg-hover: #F1F3F5; /* 悬停背景 - 浅灰 */
--bg-active: #E9ECEF; /* 激活背景 - 中浅灰 */
--bg-disabled: #F8F9FA; /* 禁用背景 */
--bg-header: #FFFFFF; /* 头部背景 - 纯白 */
--bg-sidebar: #F8F9FA; /* 侧边栏背景 */
/* ===== 白色体系 - 边框色 ===== */
--border-light: #E9ECEF; /* 浅边框 */
--border-default: #DEE2E6; /* 默认边框 */
--border-medium: #CED4DA; /* 中等边框 */
--border-dark: #ADB5BD; /* 深边框 */
/* ===== 白色体系 - 文字色 ===== */
--text-primary: #212529; /* 主要文字 (AA级: 16.9:1) */
--text-secondary: #495057; /* 次要文字 (AA级: 8.6:1) */
--text-tertiary: #6C757D; /* 辅助文字 (AA级: 5.2:1) */
--text-disabled: #ADB5BD; /* 禁用文字 */
--text-inverse: #FFFFFF; /* 反色文字(深色底上) */
/* ===== 功能色(仅状态标识)===== */
--color-success: #2B8A3E; /* 成功状态 (AA级: 5.0:1) */
--color-warning: #E67700; /* 警告状态 */
--color-error: #C92A2A; /* 错误状态 (AA级: 6.3:1) */
--color-info: #1C7ED6; /* 信息状态 */
/* ===== 功能色 - 浅色背景 ===== */
--bg-success: #EBFBEE; /* 成功浅底 */
--bg-warning: #FFF9DB; /* 警告浅底 */
--bg-error: #FFF5F5; /* 错误浅底 */
--bg-info: #E7F5FF; /* 信息浅底 */
/* ===== 主色调(品牌色 - 克制使用)===== */
--color-primary: #212529; /* 主操作色 - 深灰黑 */
--color-primary-hover: #495057; /* 悬停 */
--color-primary-active: #000000; /* 按下 */
--color-link: #1C7ED6; /* 链接色 - 仅用于超链接 */
/* ===== 阴影层级(替代彩色阴影)===== */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
--shadow-md: 0 2px 8px rgba(0, 0, 0, 0.06);
--shadow-lg: 0 4px 16px rgba(0, 0, 0, 0.08);
--shadow-xl: 0 8px 32px rgba(0, 0, 0, 0.10);
}
1.3 组件色彩映射表
| 组件/区域 | 旧色值 | 新色值 | 说明 |
|---|---|---|---|
| Header | linear-gradient(#1890ff, #096dd9) |
#FFFFFF + border-bottom: 1px solid --border-light |
纯白头部 |
| 主按钮 | linear-gradient(#1890ff, #096dd9) |
#212529 (深灰黑) → 悬停 #000 |
简洁深色按钮 |
| 次按钮 | transparent |
#FFFFFF + 边框 |
白色边框按钮 |
| 菜单选中 | linear-gradient(#1890ff, #40a9ff) |
#F1F3F5 背景 + #212529 文字 |
灰底黑字 |
| 卡片 | 渐变彩色背景 | #FFFFFF + shadow-sm 边框 |
纯白卡片 |
| 统计卡片 | 彩色图标背景 | #F8F9FA 图标底 + 深色文字 |
灰底卡片 |
| 标签 | 6色渐变 | 白底 + 深色边框 + 深色文字 | 统一标签样式 |
| 进度条 | 4色渐变 | 灰色系(#212529 → #495057 → #ADB5BD) |
灰度进度 |
| 模态弹窗 | 彩色渐变更改 | #FFFFFF + shadow-xl |
纯白模态 |
| 表格头部 | linear-gradient(#fafafa, #f5f5f5) |
#F8F9FA 纯色 |
统一表头 |
1.4 设计前后对比
【修改前】 【修改后】
┌──────────────────────────┐ ┌──────────────────────────┐
│ 🔵 蓝色渐变Header │ │ ⬜ 纯白Header + 底部灰色边线 │
├──────────────────────────┤ ├──────────────────────────┤
│ 🔵 蓝色菜单 │ │ ⬜ 灰色激活态 + 黑色文字 │
├──────────────────────────┤ ├──────────────────────────┤
│ 🟣 紫色渐变标题 │ │ ⬜ 灰色标题 │
├──────────────────────────┤ ├──────────────────────────┤
│ 🔴🟢🔵🟡 彩色统计卡片 │ │ ⬜ 统一灰色统计卡片 │
├──────────────────────────┤ ├──────────────────────────┤
│ 🔵 蓝色主按钮 │ │ ⬛ 深灰色主按钮 │
├──────────────────────────┤ ├──────────────────────────┤
│ 🟢🔵🟠🔴 彩色标签 │ │ ⬜ 统一白色标签 │
└──────────────────────────┘ └──────────────────────────┘
碎片化、多彩 统一、简洁、专业
第二部分:页面大小与信息密度优化
2.1 组件尺寸标准
| 尺寸级别 | 值 | 用途 | 示例 |
|---|---|---|---|
| XS | 4px | 极小间距 | 图标与文字间距 |
| SM | 8px | 小间距 | 按钮内边距、标签间距 |
| MD | 12px | 中间距 | 卡片内边距、列表项间距 |
| LG | 16px | 大间距 | 区块间距 |
| XL | 20px | 特大间距 | 页面边距 |
| 2XL | 24px | 区块分隔 | 主要内容区边距 |
2.2 关键组件尺寸优化
| 组件 | 当前尺寸 | 优化后 | 节省空间 |
|---|---|---|---|
| Header | 64px | 48px | -25% |
main-tabs-bar 按钮 |
padding: 14px 20px | padding: 8px 16px | -35% |
exam-header |
~80px | 56px | -30% |
stat-card |
~100px | 72px | -28% |
exam-card 内边距 |
24px | 16px | -33% |
| 表格行高 | ~57px | 44px | -23% |
| 表单垂直间距 | 24px | 16px | -33% |
文件卡片 file-card |
~200×160 | 160×128 | -36% |
统计行 stats-row 间距 |
16px | 12px | -25% |
2.3 信息密度提升策略
/* 全局紧凑模式 */
:root {
--density-compact: 1; /* 紧凑系数:0.75 = 紧凑,1 = 标准 */
}
/* 应用示例 */
.ant-table {
font-size: 13px; /* 原14px */
}
.ant-table-thead > tr > th {
padding: 8px 12px; /* 原16px 16px */
}
.ant-table-tbody > tr > td {
padding: 8px 12px; /* 原16px 16px */
}
.ant-card-body {
padding: 16px; /* 原24px */
}
.ant-form-item {
margin-bottom: 16px; /* 原24px */
}
.ant-tabs-tab {
padding: 8px 16px; /* 原14px 20px */
}
2.4 信息布局优化
优化前(低密度)
┌────────────────────────────────────────┐
│ exam-header (~80px 含大量留白) │
├────────────────────────────────────────┤
│ stats-row (~120px 含彩色图标) │
├────────────────────────────────────────┤
│ exam-card 标题 (~50px) │
│ ┌──────────────────────────────────┐ │
│ │ 表单 (24px 间距,大输入框) │ │
│ │ 字段1 │ │
│ │ ──24px── │ │
│ │ 字段2 │ │
│ │ ──24px── │ │
│ │ 字段3 │ │
│ └──────────────────────────────────┘ │
│ ──24px── │
│ 底部操作区 │
└────────────────────────────────────────┘
总高度: ~450px, 有效信息区域: ~35%
优化后(高密度)
┌────────────────────────────────────────┐
│ 标题 + 操作 (56px,紧凑单行) │
├────────────────────────────────────────┤
│ stats-row (80px,精简统计卡片) │
├────────────────────────────────────────┤
│ card: 表单 (12px 间距) │
│ 字段1 字段2 │
│ 字段3 字段4 (两列布局) │
│ ──12px── │
│ 底部操作区 │
└────────────────────────────────────────┘
总高度: ~260px, 有效信息区域: ~55%
第三部分:页面组件统一性优化
3.1 组件体系设计
通用布局组件(消除碎片化)
BasePage.vue ← 统一页面容器(替换各模块重复的 exam-page)
├─ PageHeader.vue ← 统一页面标题栏(替换 exam-header)
├─ TabsBar.vue ← 统一标签栏(替换 main-tabs-bar)
├─ StatsRow.vue ← 统一统计卡片行(替换 stats-row + stat-card)
├─ ContentCard.vue ← 统一内容卡片(替换 exam-card)
└─ DataTable.vue ← 统一数据表格(包装 antd Table)
3.2 组件规范定义
3.2.1 PageHeader 组件规范
<!-- 统一页面标题栏 -->
<template>
<div class="page-header">
<div class="header-left">
<h1 class="page-title">{{ title }}</h1>
<p v-if="description" class="page-desc">{{ description }}</p>
</div>
<div class="header-right">
<slot name="actions" />
</div>
</div>
</template>
<style scoped>
.page-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 20px; /* 原 大padding → 紧凑 */
background: #FFFFFF;
border-bottom: 1px solid #E9ECEF;
min-height: 56px; /* 原 ~80px → 56px */
}
.page-title {
font-size: 16px; /* 原 20px+ → 16px */
font-weight: 600;
color: #212529;
margin: 0;
}
.page-desc {
font-size: 12px;
color: #6C757D;
margin: 4px 0 0 0;
}
</style>
3.2.2 TabsBar 组件规范
<template>
<div class="tabs-bar">
<button
v-for="tab in tabs"
:key="tab.key"
:class="['tab-btn', { active: modelValue === tab.key }]"
@click="$emit('update:modelValue', tab.key)"
>
<span v-if="tab.icon" class="tab-icon">{{ tab.icon }}</span>
<span class="tab-text">{{ tab.label }}</span>
</button>
</div>
</template>
<style scoped>
.tabs-bar {
display: flex;
gap: 4px;
padding: 8px 16px;
background: #FFFFFF;
border-bottom: 1px solid #E9ECEF;
}
.tab-btn {
display: flex;
align-items: center;
gap: 6px;
padding: 6px 14px; /* 原 14px 20px → 紧凑 */
border: none;
border-radius: 6px;
background: transparent;
color: #495057;
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.15s ease;
}
.tab-btn:hover {
background: #F1F3F5;
color: #212529;
}
.tab-btn.active {
background: #F1F3F5;
color: #212529;
font-weight: 600;
}
</style>
3.2.3 ContentCard 组件规范
<template>
<div class="content-card" :class="{ 'has-header': $slots.header }">
<div v-if="$slots.header" class="card-header">
<slot name="header" />
</div>
<div class="card-body" :style="{ padding: padding }">
<slot />
</div>
</div>
</template>
<script setup>
defineProps({
padding: { type: String, default: '16px' }
})
</script>
<style scoped>
.content-card {
background: #FFFFFF;
border: 1px solid #E9ECEF;
border-radius: 8px; /* 原 12px → 8px */
box-shadow: 0 1px 2px rgba(0,0,0,0.04); /* 原大阴影 → 轻阴影 */
}
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
border-bottom: 1px solid #E9ECEF;
}
</style>
3.2.4 StatsRow 组件规范
<template>
<div class="stats-row">
<div v-for="stat in stats" :key="stat.label" class="stat-card">
<span class="stat-value">{{ stat.value }}</span>
<span class="stat-label">{{ stat.label }}</span>
</div>
</div>
</template>
<style scoped>
.stats-row {
display: flex;
gap: 12px;
padding: 12px 20px;
background: #FFFFFF;
border-bottom: 1px solid #E9ECEF;
}
.stat-card {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
padding: 10px 12px;
background: #F8F9FA;
border-radius: 6px;
border: 1px solid #E9ECEF;
min-height: 72px; /* 原 ~100px → 72px */
}
.stat-value {
font-size: 22px; /* 原 28px+ → 22px */
font-weight: 700;
color: #212529;
}
.stat-label {
font-size: 12px;
color: #6C757D;
font-weight: 500;
}
</style>
3.2.5 DataTable 组件规范
基于 Ant Design Vue Table 的封装,统一表头样式、行高、分页、空状态:
<!-- 统一表格组件 -->
<template>
<a-table
:dataSource="dataSource"
:columns="columns"
:loading="loading"
:pagination="paginationConfig"
:rowKey="rowKey"
size="small" /* 统一小尺寸 */
:locale="emptyLocale"
class="data-table"
@change="handleTableChange"
>
<template v-for="slot in Object.keys($slots)" #[slot]="scope">
<slot :name="slot" v-bind="scope" />
</template>
</a-table>
</template>
3.3 消除碎片化的实施路径
| 阶段 | 内容 | 涉及文件 |
|---|---|---|
| 1 | 创建通用组件库 BasePage, PageHeader, TabsBar, ContentCard, StatsRow, DataTable |
新建6个组件 |
| 2 | 重构 ReadModule.vue 使用通用组件 |
修改1个文件 |
| 3 | 重构 ManageModule.vue 使用通用组件 |
修改1个文件 |
| 4 | 重构 ExamModule.vue 使用通用组件 |
修改1个文件 |
| 5 | 重构 QAModule.vue 使用通用组件 |
修改1个文件 |
| 6 | 重构 MindModule.vue, DashboardModule.vue, PermissionModule.vue |
修改3个文件 |
| 7 | 移除各模块中的重复样式,统一到全局CSS变量 | 全局样式修改 |
第四部分:功能流程与操作流程优化
4.1 导航体验优化
当前问题:使用 <a-select> 下拉框选择功能模块,不符合主流习惯。
优化方案:改为顶部固定标签栏导航
<!-- 优化前:下拉选择 -->
<a-select v-model:value="currentModule" style="width: 220px;">
<a-select-option value="read">📄 制度文件查看和学习</a-select-option>
...
</a-select>
<!-- 优化后:顶部标签栏 -->
<div class="top-nav">
<button
v-for="mod in visibleModules"
:class="['nav-item', { active: currentModule === mod.key }]"
@click="currentModule = mod.key"
>
{{ mod.icon }} {{ mod.label }}
</button>
</div>
4.2 文件选择器流程简化
当前流程(3步):
选择知识库 → 搜索/浏览文件 → 选择版本 → 确认
优化流程(2步):
搜索/浏览文件(自动关联知识库)→ 点击选择(默认最新版本)→ 确认
4.3 出题流程优化
当前流程(6步):
选择知识库 → 选择文件 → 配置题型数量 → 设置难度 → 提交 → 等待轮询 → 查看结果
优化流程(4步):
选择文件 → 配置题型(带智能推荐)→ 提交 → 实时进度 → 查看结果
第五部分:设计规范文档(开发维护参考)
5.1 通用设计原则
- 白色优先:所有背景使用白色体系,彩色仅用于状态标识
- 减法设计:去除不必要的装饰元素(渐变、阴影、动画)
- 信息优先:内容区域最大化,装饰和留白最小化
- 一致性:所有页面使用统一的布局组件和间距体系
- 可访问性:所有文字对比度 ≥ 4.5:1(WCAG AA级)
5.2 CSS变量完整清单
:root {
/* 间距系统 */
--space-xs: 4px;
--space-sm: 8px;
--space-md: 12px;
--space-lg: 16px;
--space-xl: 20px;
--space-2xl: 24px;
--space-3xl: 32px;
/* 圆角系统 */
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 8px;
--radius-xl: 12px;
/* 字体系统 */
--font-xs: 11px;
--font-sm: 12px;
--font-md: 13px;
--font-lg: 14px;
--font-xl: 16px;
--font-2xl: 18px;
--font-3xl: 22px;
/* 字体粗细 */
--weight-normal: 400;
--weight-medium: 500;
--weight-semibold: 600;
--weight-bold: 700;
/* 阴影系统 */
--shadow-sm: 0 1px 2px rgba(0,0,0,0.04);
--shadow-md: 0 2px 8px rgba(0,0,0,0.06);
--shadow-lg: 0 4px 16px rgba(0,0,0,0.08);
/* 过渡 */
--transition-fast: 0.15s ease;
--transition-normal: 0.2s ease;
/* 层级 */
--z-dropdown: 1000;
--z-modal: 1050;
--z-tooltip: 1100;
}
5.3 按钮规范
| 类型 | 背景 | 边框 | 文字色 | 悬停 | 使用场景 |
|---|---|---|---|---|---|
| 主按钮 | #212529 |
无 | #FFFFFF |
#000 |
主要操作(提交、确认) |
| 次按钮 | #FFFFFF |
#DEE2E6 |
#212529 |
#F1F3F5 |
次要操作(取消、返回) |
| 文字按钮 | 透明 | 无 | #495057 |
#F1F3F5 |
低优先级操作 |
| 危险按钮 | #C92A2A |
无 | #FFFFFF |
#B02525 |
删除、清空 |
| 成功按钮 | #2B8A3E |
无 | #FFFFFF |
#246E33 |
审核通过 |
.btn { /* 通用按钮基础 */
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 14px;
border: none;
border-radius: 6px;
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.15s ease;
line-height: 1.5;
}
.btn-primary { background: #212529; color: #fff; }
.btn-secondary { background: #fff; color: #212529; border: 1px solid #DEE2E6; }
.btn-text { background: transparent; color: #495057; }
.btn-danger { background: #C92A2A; color: #fff; }
.btn-success { background: #2B8A3E; color: #fff; }
.btn-sm { padding: 4px 10px; font-size: 12px; }
.btn-lg { padding: 8px 18px; font-size: 14px; }
5.4 表单规范
.form-item {
margin-bottom: 16px; /* 原24px */
}
.form-label {
font-size: 13px;
font-weight: 500;
color: #212529;
margin-bottom: 6px;
}
.form-input {
height: 36px; /* 原40px */
padding: 6px 12px;
border: 1px solid #DEE2E6;
border-radius: 6px;
font-size: 13px;
color: #212529;
transition: border-color 0.15s ease;
}
.form-input:focus {
border-color: #212529;
outline: none;
box-shadow: 0 0 0 3px rgba(0,0,0,0.05);
}
5.5 标签规范
/* 统一标签替代6种彩色标签 */
.tag {
display: inline-flex;
align-items: center;
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
}
.tag-default { background: #F1F3F5; color: #495057; border: 1px solid #DEE2E6; }
.tag-success { background: #EBFBEE; color: #2B8A3E; border: 1px solid #B2F2BB; }
.tag-warning { background: #FFF9DB; color: #E67700; border: 1px solid #FFE066; }
.tag-error { background: #FFF5F5; color: #C92A2A; border: 1px solid #FFC9C9; }
.tag-info { background: #E7F5FF; color: #1C7ED6; border: 1px solid #A5D8FF; }
5.6 表格规范
| 属性 | 当前 | 优化后 | 说明 |
|---|---|---|---|
| 表头背景 | linear-gradient(#fafafa, #f5f5f5) |
#F8F9FA |
纯色统一 |
| 表头字体 | 14px / 600 | 13px / 600 | - |
| 表头内边距 | 16px 16px | 8px 12px | 紧凑 |
| 行高 | ~57px | 44px | -22% |
| 单元格内边距 | 16px 16px | 8px 12px | 紧凑 |
| 悬停背景 | #f0f7ff (蓝色) |
#F1F3F5 (灰色) |
统一灰色系 |
| 圆角 | 12px | 6px | 弱化圆角 |
| 阴影 | 0 2px 8px rgba(...) |
0 1px 2px rgba(0,0,0,0.04) |
轻阴影 |
第六部分:实施建议
6.1 优先级排序
| 优先级 | 优化项 | 预计工时 | 影响范围 |
|---|---|---|---|
| P0 | CSS变量体系建立 + 全局样式替换 | 2天 | 全局 |
| P0 | 色彩体系迁移到白色方案 | 3天 | 全局 |
| P1 | 通用组件库创建 (BasePage, PageHeader, TabsBar, ContentCard) |
2天 | 新建 |
| P1 | 组件尺寸和信息密度调整 | 2天 | 全局 |
| P2 | 各模块使用通用组件重构 | 5天 | 8个组件 |
| P2 | 导航优化(下拉→标签栏) | 1天 | Home.vue |
| P3 | 文件选择器流程简化 | 2天 | FileSelector.vue |
| P3 | 出题流程优化 | 1天 | ExamModule.vue |
6.2 回滚策略
- 所有样式修改通过CSS变量进行,方便快速回滚
- 通用组件与原有组件并行开发,逐模块切换
- 每个模块切换后进行功能回归测试
- 保留原有组件的备份分支
6.3 验收标准
- 全站使用统一的白色色板,无彩色渐变背景
- 所有文字对比度 ≥ 4.5:1
- 组件尺寸减少 ≥ 20%
- 同等屏幕尺寸下信息展示量提升 ≥ 30%
- 所有模块使用统一的通用布局组件
- 用户操作步骤减少(导航1步,文件选择减少1步)
- 1920×1080 和 1366×768 分辨率下均无横向滚动条
附录
A. 需要删除的CSS类清单
以下全局CSS类将在白色体系下移除或重写:
| 文件 | 类名 | 操作 |
|---|---|---|
style.css |
.btn-gradient-primary ~ .btn-gradient-purple |
删除(6个渐变按钮类) |
style.css |
.card-gradient-blue ~ .card-gradient-purple |
删除(6个渐变卡片类) |
style.css |
.tag-blue ~ .tag-cyan |
删除(6个彩色标签类) |
style.css |
.progress-blue ~ .progress-cyan |
删除(6个彩色进度条类) |
style.css |
.animate-float, .animate-pulse-glow, .animate-shimmer |
删除或简化 |
index.css |
.header 蓝色背景 |
改为白色 |
| 各组件 | 内联 style="background: linear-gradient(...)" |
替换为CSS变量 |
B. 参考标准
- WCAG 2.1 AA 对比度标准: https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html
- Ant Design 5.0 设计语言: https://ant.design/
- Tailwind CSS 间距/色彩系统: https://tailwindcss.com/