GuDingZiChan/前端视觉重构台账.md

24 KiB
Raw Blame History

固定资产管理系统 - 前端视觉重构台账

重构日期: 2026-03-17
重构范围: 全站前端视觉统一
版本: v2.0


一、重构概述

本次重构将项目前端视觉全面统一,建立了严格的视觉规范体系,确保所有页面风格一致、排版协调。

核心目标

  1. 统一页面结构 - 所有页面遵循相同的布局层次
  2. 统一组件样式 - 按钮、输入框、卡片等组件完全一致
  3. 统一间距系统 - 严格执行 4px 基准的间距规范
  4. 统一响应式策略 - 移动端/桌面端切换时机一致

二、关键文件清单

核心样式系统(1个)

文件路径 说明 变更类型
frontend/src/style.css 全局样式系统 全面重写

布局框架(1个)

文件路径 说明 变更类型
frontend/src/layouts/MainLayout.vue 侧边栏+顶部导航布局 结构调整

页面组件(18个)

模块 文件路径 说明 变更类型
登录 frontend/src/views/Login.vue 登录页 样式统一
首页 frontend/src/views/dashboard/Dashboard.vue 仪表盘 结构重构
资产列表 frontend/src/views/equipment/EquipmentList.vue 资产管理主页面 结构重构
资产表单 frontend/src/views/equipment/EquipmentForm.vue 新增/编辑资产 结构重构
借用列表 frontend/src/views/borrow/BorrowList.vue 借用记录 结构重构
扫码借出 frontend/src/views/borrow/BorrowScan.vue 扫码出库页面 样式统一
扫码归还 frontend/src/views/borrow/ReturnScan.vue 扫码入库页面 样式统一
统计分析 frontend/src/views/statistics/Statistics.vue 数据统计 结构重构
站内消息 frontend/src/views/notifications/NotificationCenter.vue 消息中心 结构重构
设置主框架 frontend/src/views/settings/Settings.vue 系统设置框架 结构重构
站点设置 frontend/src/views/settings/components/SiteSettings.vue 站点配置 样式统一
用户管理 frontend/src/views/settings/components/UserManagement.vue 用户管理 结构重构
人员管理 frontend/src/views/settings/components/PersonManagement.vue 人员管理 结构重构
部门管理 frontend/src/views/settings/components/DepartmentManagement.vue 部门管理 结构重构
资产类型 frontend/src/views/settings/components/AssetTypeManagement.vue 类型管理 样式统一
地址管理 frontend/src/views/settings/components/StorageLocationManagement.vue 地址管理 样式统一
维修管理 frontend/src/views/settings/components/MaintenanceManagement.vue 维修管理 结构重构
报废管理 frontend/src/views/settings/components/DisposalManagement.vue 报废管理 结构重构
操作日志 frontend/src/views/settings/components/OperationLogList.vue 日志查询 结构重构
组织同步 frontend/src/views/settings/components/HrSyncManagement.vue HR同步 样式统一

总计: 20 个文件


三、视觉规范体系

3.1 颜色系统

/* 背景色 */
--bg-primary: #0d0d0d      /* 页面主背景 - 纯黑 */
--bg-secondary: #141414    /* 卡片背景 - 深灰 */
--bg-tertiary: #1a1a1a     /* 表头背景 */
--bg-elevated: #242424     /* 输入框背景 */
--bg-hover: #2a2a2a        /* 悬停状态 */

/* 文字色 */
--text-primary: #ffffff      /* 主文字 - 纯白 */
--text-secondary: #a1a1a1    /* 次要文字 - 灰白 */
--text-tertiary: #6e6e6e     /* 辅助文字 - 深灰 */

/* 边框 */
--border-color: #2a2a2a      /* 默认边框 */
--border-hover: #3a3a3a      /* 悬停边框 */

/* 强调色 */
--accent-primary: #10a37f      /* 主按钮、链接 - 青绿 */
--accent-primary-hover: #0d8c6d  /* 按钮悬停 */

/* 状态色 */
--status-success: #10a37f   /* 成功、可用 */
--status-warning: #f59e0b   /* 警告、借出 */
--status-error: #ef4444     /* 错误、删除 */
--status-neutral: #6b7280   /* 中性、禁用 */

3.2 间距系统(严格执行)

变量 值 使用场景
--space-1 4px 微调间距
--space-2 8px 小间距
--space-3 12px 按钮组间距、列表项间距
--space-4 16px 卡片内间距、表单字段间距
--space-5 20px 卡片 padding
--space-6 24px 页面级间距
--space-8 32px 大区块间距

强制规范:

  • 页面级间距统一使用 space-y-6 (24px)
  • 卡片内元素间距统一使用 gap-4 (16px)
  • 表单字段间距使用 field-stack (6px)

3.3 圆角系统

变量 值 使用场景
--radius-sm 6px 小按钮
--radius-md 8px 按钮、输入框
--radius-lg 12px 卡片、面板
--radius-xl 16px 弹窗
--radius-full 9999px 标签、圆形按钮

3.4 字体规范

级别 类名 大小 用途
页面标题 .page-title 24px 页面主标题
区块标题 .section-title 16px 卡片/列表标题
正文 .input 等 14px 普通文字
辅助文字 .mobile-card__label 11px 标签、时间戳

四、页面结构规范

4.1 标准列表页结构

<template>
  <div class="space-y-6">
    <!-- 1. 页面头部 -->
    <section class="page-header">
      <div>
        <p class="page-kicker">英文标签</p>
        <h2 class="page-title">页面标题</h2>
        <div class="mt-5 flex flex-wrap gap-3">
          <!-- 主要操作按钮 -->
          <button class="btn-primary text-sm">主要操作</button>
        </div>
      </div>
      <div class="page-meta-grid">
        <!-- 3个统计卡片 -->
        <div class="page-meta">...</div>
        <div class="page-meta">...</div>
        <div class="page-meta">...</div>
      </div>
    </section>

    <!-- 2. 筛选区域 -->
    <section class="card">
      <div class="filter-bar">
        <div class="filter-bar__inputs">
          <!-- 筛选输入框 -->
          <div class="field-stack">
            <label class="field-label">标签</label>
            <input class="input" />
          </div>
          <select class="select">...</select>
        </div>
        <div class="filter-bar__actions">
          <!-- 筛选按钮 -->
          <button class="btn-secondary text-sm">重置</button>
          <button class="btn-primary text-sm">查询</button>
        </div>
      </div>
    </section>

    <!-- 3. 数据列表 -->
    <section class="card">
      <div class="list-header">
        <h3 class="section-title">列表标题</h3>
        <span class="badge badge-neutral">共 XX 条</span>
      </div>

      <!-- 移动端:卡片列表 -->
      <div class="mobile-card-list md:hidden">
        <article class="mobile-card">
          <div class="mobile-card__row">...</div>
          <div class="mobile-card__meta">...</div>
        </article>
      </div>

      <!-- 桌面端:表格 -->
      <div class="hidden md:block">
        <div class="table-container">
          <table class="data-table min-w-[900px]">
            ...
          </table>
        </div>
      </div>

      <!-- 分页 -->
      <div class="pagination-bar">
        <p class="text-sm text-text-secondary">共 XX 条记录</p>
        <div class="flex items-center gap-2">
          <button class="btn-secondary text-sm">上一页</button>
          <span class="text-sm text-text-primary">1 / 10</span>
          <button class="btn-secondary text-sm">下一页</button>
        </div>
      </div>
    </section>
  </div>
</template>

4.2 标准表单页结构

<template>
  <div class="space-y-6 pb-24 md:pb-0">
    <!-- 页面头部 -->
    <section class="page-header">
      <div>
        <p class="page-kicker">Field Entry</p>
        <h2 class="page-title">表单标题</h2>
      </div>
      <div class="flex gap-3">
        <button class="btn-secondary text-sm">次要操作</button>
      </div>
    </section>

    <!-- 表单卡片 -->
    <section class="card">
      <h3 class="section-title mb-5">区块标题</h3>
      <form @submit.prevent="handleSubmit" class="space-y-5">
        <div class="field-grid">
          <div class="field-stack">
            <label class="field-label">字段名 *</label>
            <input class="input" required />
          </div>
          <div class="field-stack lg:col-span-2">
            <label class="field-label">长字段</label>
            <textarea class="input" rows="3"></textarea>
          </div>
        </div>

        <!-- 底部操作栏 -->
        <div class="mobile-sticky-actions md:static">
          <div class="flex flex-col gap-2 md:flex-row md:justify-end">
            <button type="submit" class="btn-primary w-full md:w-auto">保存</button>
            <button type="button" class="btn-secondary w-full md:w-auto">取消</button>
          </div>
        </div>
      </form>
    </section>
  </div>
</template>

4.3 标准设置页结构

<template>
  <div class="space-y-6">
    <!-- 页面头部 -->
    <section class="page-header">
      <div>
        <p class="page-kicker">英文标签</p>
        <h2 class="page-title">设置标题</h2>
      </div>
      <div class="page-meta-grid">...</div>
    </section>

    <!-- 筛选/新增卡片 -->
    <section class="card">
      <div class="filter-bar">...</div>
    </section>

    <!-- 列表卡片 -->
    <section class="card">
      <div class="list-header">...</div>
      <!-- 移动端卡片 / 桌面端表格 -->
      <div class="pagination-bar">...</div>
    </section>

    <!-- 编辑弹窗 -->
    <div v-if="editing" class="sheet-backdrop">
      <div class="sheet-panel max-w-2xl">
        <h3 class="text-xl font-semibold text-text-primary mb-4">编辑</h3>
        <div class="space-y-4">
          <div class="field-stack">...</div>
        </div>
        <div class="flex justify-end gap-3 mt-6">
          <button class="btn-secondary" @click="close">取消</button>
          <button class="btn-primary" @click="save">保存</button>
        </div>
      </div>
    </div>
  </div>
</template>

五、组件类名速查表

5.1 按钮

<!-- 主要按钮 -->
<button class="btn-primary">确认</button>

<!-- 次要按钮 -->
<button class="btn-secondary">取消</button>

<!-- 危险按钮 -->
<button class="btn-danger">删除</button>

<!-- 图标按钮 -->
<button class="btn-icon"><Icon /></button>

<!-- 小尺寸按钮 -->
<button class="btn-primary text-sm">小按钮</button>

5.2 表单

<!-- 字段组 -->
<div class="field-stack">
  <label class="field-label">字段名</label>
  <input class="input" />
</div>

<!-- 输入框 -->
<input class="input" type="text" placeholder="提示文字" />

<!-- 选择框 -->
<select class="select">
  <option>选项</option>
</select>

<!-- 多行输入 -->
<textarea class="input" rows="3"></textarea>

<!-- 表单网格(2列) -->
<div class="field-grid">
  <div class="field-stack">...</div>
  <div class="field-stack">...</div>
</div>

<!-- 表单网格(跨2列) -->
<div class="field-stack lg:col-span-2">
  <label class="field-label">长字段</label>
  <textarea class="input" rows="3"></textarea>
</div>

5.3 卡片与面板

<!-- 主卡片 -->
<section class="card">...</section>

<!-- 内层面板 -->
<div class="panel">...</div>

5.4 标签

<span class="badge badge-success">成功</span>
<span class="badge badge-warning">警告</span>
<span class="badge badge-error">错误</span>
<span class="badge badge-neutral">中性</span>

5.5 表格

<div class="table-container">
  <table class="data-table min-w-[900px]">
    <thead>
      <tr>
        <th>列标题</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>数据</td>
      </tr>
    </tbody>
  </table>
</div>

5.6 移动端卡片列表

<div class="mobile-card-list md:hidden">
  <article class="mobile-card">
    <div class="mobile-card__row">
      <p class="text-sm font-semibold text-text-primary">标题</p>
      <span class="badge badge-success">状态</span>
    </div>
    <div class="mobile-card__meta">
      <div>
        <p class="mobile-card__label">标签</p>
        <p class="mobile-card__value">值</p>
      </div>
    </div>
  </article>
</div>

5.7 弹窗

<div class="sheet-backdrop">
  <div class="sheet-panel max-w-2xl">
    <h3 class="text-xl font-semibold text-text-primary mb-4">标题</h3>
    <div class="space-y-4">...</div>
    <div class="flex justify-end gap-3 mt-6">
      <button class="btn-secondary">取消</button>
      <button class="btn-primary">确认</button>
    </div>
  </div>
</div>

5.8 空状态

<p class="empty-state">暂无数据</p>

六、响应式断点规范

6.1 断点定义

断点 范围 类名前缀
sm >= 640px sm:
md >= 768px md:
lg >= 1024px lg:
xl >= 1280px xl:

6.2 列表切换策略

统一使用 md 断点:

<!-- 移动端显示,桌面端隐藏 -->
<div class="mobile-card-list md:hidden">...</div>

<!-- 移动端隐藏,桌面端显示 -->
<div class="hidden md:block">...</div>

6.3 网格响应式

<!-- 1列 -> 2列 -->
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">...</div>

<!-- 1列 -> 2列 -> 3列 -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">...</div>

<!-- 1列 -> 2列 -> 4列 -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">...</div>

七、新增/修改的 CSS 类名

7.1 页面结构

.page-header          /* 页面头部容器 */
.page-kicker          /* 英文标签 */
.page-title           /* 页面标题 */
.page-meta-grid       /* 统计卡片网格 */
.page-meta            /* 统计卡片 */
.page-meta__label     /* 统计标签 */
.page-meta__value     /* 统计数值 */
.page-meta__subvalue  /* 统计副标题 */

.list-header          /* 列表头部 */
.section-title        /* 区块标题 */

7.2 筛选区域

.filter-bar           /* 筛选栏容器 */
.filter-bar__inputs   /* 输入区 */
.filter-bar__actions  /* 按钮区 */

7.3 表单系统

.field-grid           /* 表单网格(响应式2列) */
.field-grid--3        /* 表单网格(响应式3列) */
.field-stack          /* 字段组(标签+输入) */
.field-label          /* 字段标签 */

7.4 表格系统

.table-container      /* 表格容器(带边框和圆角) */
.data-table           /* 数据表格 */

7.5 移动端卡片

.mobile-card-list     /* 卡片列表容器 */
.mobile-card          /* 单个卡片 */
.mobile-card__row     /* 卡片行(标题+状态) */
.mobile-card__meta    /* 卡片元信息网格 */
.mobile-card__label   /* 标签 */
.mobile-card__value   /* 值 */

7.6 其他

.empty-state          /* 空状态 */
.pagination-bar       /* 分页栏 */
.mobile-sticky-actions /* 移动端底部固定操作栏 */
.sheet-backdrop       /* 弹窗遮罩 */
.sheet-panel          /* 弹窗面板 */

八、开发注意事项

8.1 必须遵守的规范

  1. 页面间距: 所有页面根容器必须使用 space-y-6
  2. 卡片内边距: 所有 card 内部使用 p-5(已由 card 类自带)
  3. 表单标签: 必须使用 field-label,禁止自定义样式
  4. 按钮顺序: 主要操作在左,次要操作在右(弹窗内相反)
  5. 列表头部: 必须包含 list-header + section-title

8.2 禁止使用的类名

已废弃的类名(虽然 style.css 保留了兼容,但新代码不应使用):

  • btn-apple-* 系列
  • input-apple
  • card-apple
  • text-apple-*
  • text-system-label-*
  • bg-system-gray-*
  • border-system-gray-*
  • surface-note
  • page-subtitle
  • section-subtitle

8.3 推荐的间距

  • 页面级: space-y-6 (24px)
  • 卡片内: gap-4 (16px)
  • 按钮组: gap-3 (12px)
  • 列表项: mobile-card-list 自带 12px gap

禁止使用的间距:

  • gap-5 (20px) - 非标准间距
  • mt-5 / mb-5 - 使用 mt-4 (16px) 或 mt-6 (24px)

8.4 断点使用

  • 列表切换统一使用 md 断点
  • 网格响应式使用 sm: 和 lg:
  • 不要混用 md 和 lg 进行列表切换

九、示例页面参考

最标准的列表页

frontend/src/views/equipment/EquipmentList.vue

最标准的表单页

frontend/src/views/equipment/EquipmentForm.vue

最标准的设置页

frontend/src/views/settings/components/UserManagement.vue


十、构建验证

cd frontend
npm run build

预期结果:

  • ✓ vue-tsc -b 无错误
  • ✓ vite build 成功
  • ✓ 所有 chunk 生成完成

附录:颜色使用速查

用途 类名
主文字 text-text-primary
次要文字 text-text-secondary
辅助文字 text-text-tertiary
强调色 text-accent
成功状态 text-status-success
警告状态 text-status-warning
错误状态 text-status-error
页面背景 bg-bg-primary
卡片背景 bg-bg-secondary
输入框背景 bg-bg-elevated


十一、移动端优化(新增)

优化日期: 2026-03-17
优化范围: 全站移动端体验增强

11.1 优化内容

样式系统增强 (style.css)

新增移动端全面优化样式(在文件末尾添加):

/* 移动端按钮尺寸优化 - 修复按钮过大问题 */
@media (max-width: 767px) {
  .btn-primary, .btn-secondary, .btn-danger {
    min-height: 40px;
    padding: 0.5rem 0.875rem;
    font-size: 13px;
  }
}

/* 移动端徽章防止压缩 - 修复胶囊变圆问题 */
@media (max-width: 767px) {
  .badge {
    flex-shrink: 0;
    white-space: nowrap;
    padding: 0.25rem 0.5rem;
    font-size: 10px;
  }
}

/* 移动端卡片紧凑模式 - 修复卡片过大问题 */
@media (max-width: 767px) {
  .card { padding: var(--space-3); border-radius: var(--radius-md); }
  .panel { padding: var(--space-3); }
  .mobile-card { padding: var(--space-3); }
}

/* 移动端页面头部优化 */
@media (max-width: 767px) {
  .page-header { padding: var(--space-3); gap: var(--space-3); }
  .page-title { font-size: 20px; }
  .page-kicker { font-size: 10px; }
  .page-meta { padding: var(--space-3); }
  .page-meta__value { font-size: 16px; }
}

/* iOS 防缩放 */
@media (max-width: 767px) {
  .input, .select, textarea.input {
    font-size: 16px;
    min-height: 48px;
  }
}

/* 安全区域适配 */
@supports (padding: max(0px)) {
  .mobile-sticky-actions {
    padding-bottom: max(var(--space-4), env(safe-area-inset-bottom));
  }
}

页面移动端适配

页面 优化内容
Dashboard.vue 最近借用记录添加 mobile-card-list;统计卡片使用 grid-cols-2 并缩小字体
Statistics.vue Top 10 高价值资产添加 mobile-card-list 移动端卡片列表
EquipmentList.vue 移动端卡片按钮使用 text-xs 并简化文字
NotificationCenter.vue 按钮使用 text-xs sm:text-sm,"全部标记已读"简化为"全标已读"
PersonManagement.vue 按钮添加 text-xs sm:text-sm,文字简化
UserManagement.vue 按钮添加 text-xs sm:text-sm
AssetTypeManagement.vue 按钮添加 text-xs sm:text-sm
StorageLocationManagement.vue 按钮添加 text-xs sm:text-sm
DepartmentManagement.vue 按钮添加 text-xs sm:text-sm,文字简化
MaintenanceManagement.vue 按钮添加 text-xs sm:text-sm,"完成维修/取消维修"简化为"完成/取消"
DisposalManagement.vue 按钮添加 text-xs sm:text-sm,"通过审批/驳回申请"简化为"通过/驳回"
OperationLogList.vue 按钮添加 text-xs sm:text-sm
HrSyncManagement.vue 按钮添加 text-xs sm:text-sm,"刷新预览/立即同步"简化为"刷新/同步"
SiteSettings.vue 按钮添加 text-xs sm:text-sm

移动端列表结构模板

<!-- 移动端卡片列表 (md:hidden) -->
<div class="mobile-card-list md:hidden">
  <article v-for="item in list" :key="item.id" class="mobile-card">
    <div class="mobile-card__row">
      <p class="text-sm font-semibold text-text-primary">{{ item.name }}</p>
      <span class="badge badge-success">状态</span>
    </div>
    <div class="mobile-card__meta mt-3">
      <div>
        <p class="mobile-card__label">标签</p>
        <p class="mobile-card__value">{{ item.value }}</p>
      </div>
    </div>
  </article>
  <div v-if="list.length === 0" class="empty-state">暂无数据</div>
</div>

<!-- 桌面端表格 (hidden md:block) -->
<div class="hidden md:block">
  <div class="table-container">
    <table class="data-table">...</table>
  </div>
</div>

11.2 移动端组件清单

组件类名 用途 移动端特性
.mobile-card-list 卡片列表容器 垂直布局,12px 间距
.mobile-card 单个卡片 触摸反馈、点击缩放效果
.mobile-card__row 卡片标题行 标题+状态 横向排列
.mobile-card__meta 卡片元信息 2列网格布局
.mobile-sticky-actions 底部固定操作栏 移动端 fixed,桌面端 static
.touch-option-list 触摸选项列表 大按钮,易于触摸
.touch-option 触摸选项 点击反馈效果

11.3 响应式断点策略

统一使用 md (768px) 作为列表切换断点:

<!-- 移动端显示,桌面端隐藏 -->
<div class="mobile-card-list md:hidden">...</div>

<!-- 移动端隐藏,桌面端显示 -->
<div class="hidden md:block">...</div>

11.4 移动端按钮规范

尺寸规范:

/* 移动端默认按钮 */
min-height: 40px;
padding: 0.5rem 0.875rem;
font-size: 13px;

/* 移动端小按钮 */
class="text-xs" /* 12px */

文字简化原则:

桌面端文字 移动端文字
全部标记已读 全标已读
刷新预览 刷新
立即同步 同步
通过审批 通过
驳回申请 驳回
完成维修 完成
取消维修 取消
完成处置 完成
新增使用者 新增
下载导入模板 下载模板
查看配件 N 配件(N)
收起配件 收起
打印标签 标签

Vue 模板示例:

<button class="btn-primary text-xs sm:text-sm">保存</button>
<button class="btn-secondary text-xs sm:text-sm">取消</button>

11.5 移动端表单优化

  1. 输入框字体大小: 统一使用 16px,防止 iOS 自动缩放
  2. 触摸目标: 按钮最小高度 40px (移动端)
  3. 底部固定操作栏: 长表单使用 mobile-sticky-actions
<template>
  <div class="space-y-6 pb-24 md:pb-0">
    <!-- 表单内容 -->
    
    <!-- 底部操作栏 -->
    <div class="mobile-sticky-actions md:static">
      <button type="submit" class="btn-primary w-full">保存</button>
    </div>
  </div>
</template>

11.6 移动端徽章(Badge)规范

防止压缩成圆:

@media (max-width: 767px) {
  .badge {
    flex-shrink: 0;      /* 防止被压缩 */
    white-space: nowrap; /* 防止文字换行 */
    padding: 0.25rem 0.5rem;
    font-size: 10px;
  }
}

使用建议:

  • 徽章文字尽量简短(2-4个字符)
  • 使用 flex-shrink-0 防止在 flex 容器中被压缩
  • 使用 white-space: nowrap 防止文字换行导致高度变化

11.7 移动端手势支持

/* 滑动容器 */
.swipe-container {
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.swipe-item {
  scroll-snap-align: start;
  flex-shrink: 0;
}

文档版本: v2.0
最后更新: 2026-03-17
维护者: Claude