diff --git a/.mimocode/plans/1783060688305-neon-meadow.md b/.mimocode/plans/1783060688305-neon-meadow.md new file mode 100644 index 0000000..198609a --- /dev/null +++ b/.mimocode/plans/1783060688305-neon-meadow.md @@ -0,0 +1,125 @@ +# 后台样式统一优化计划 + +## 问题总结 + +经过全面审查,发现以下风格不一致和突兀的地方: + +| # | 问题 | 严重度 | 涉及文件 | +|---|------|--------|----------| +| 1 | CSS 中大量使用硬编码十六进制颜色,未引用 Tailwind 语义 token | 高 | `index.css` | +| 2 | `stat-card` 悬浮效果(上移+大阴影)与 `section-card`(仅阴影)风格差异大 | 中 | `index.css` | +| 3 | 主按钮悬浮时 `translateY(-1px)` 在管理后台中显得突兀 | 中 | `index.css` | +| 4 | `blue-600` 应为 `brand` 的渐变色在布局和头像中混用 | 中 | `layout/index.tsx`, `ProfileSummary.tsx` | +| 5 | 登录页使用 `#f7f8fa` 而非 `canvas` token | 低 | `Login/index.tsx`, `LoginPanel.tsx` | +| 6 | Role/Personnel 页面缺少 `page-stack` 包裹 | 中 | `Role/index.tsx`, `Personnel/index.tsx` | +| 7 | Modal 宽度不一致(640/720/默认520) | 中 | `Channel`, `DramaList`, `DramaDetail`, `Role`, `Personnel` | +| 8 | 分页配置不一致(部分有 sizeCanChange/showTotal,部分没有) | 中 | 多个页面 | +| 9 | 状态标签颜色不一致(禁用:红色 vs 灰色) | 低 | `User`, `Personnel` vs `Channel`, `Drama` | +| 10 | DramaList 的"新增短剧"按钮用绿色,其他页面用蓝色 | 低 | `DramaList.tsx` | +| 11 | InputNumber 宽度不一致(固定180px vs 100%) | 低 | `Channel` vs `Drama` | + +## 实施方案 + +### 步骤 1:统一 CSS 中的颜色引用 (`index.css`) + +将所有硬编码颜色替换为 Tailwind 语义化写法: + +```css +/* 之前 */ +background-color: #f2f3f5 !important; /* canvas */ +color: #165dff !important; /* brand */ +background-color: #e8f3ff !important; /* brand-light */ +color: #4e5969 !important; /* 无对应token,新增 secondary */ +background-color: #fafbfc !important; /* 无对应token,新增 header-bg */ +color: #1d2129 !important; /* ink */ +color: #86909c !important; /* muted */ +border-color: #c9cdd4 !important; /* 无对应token,新增 border-hover */ +background-color: #f7f8fa !important; /* 无对应token,新增 row-hover */ +color: #fff !important; /* white */ +``` + +新增 tailwind.config.js token: +- `secondary: '#4e5969'` — 表头、表单标签等次级文字 +- `header-bg: '#fafbfc'` — 表头、描述标签背景 +- `row-hover: '#f7f8fa'` — 表格行悬浮背景 +- `border-hover: '#c9cdd4'` — 输入框悬浮边框 + +CSS 改用 `theme()` 函数引用: +```css +background-color: theme('colors.canvas') !important; +color: theme('colors.brand') !important; +``` + +### 步骤 2:统一悬浮效果 (`index.css`) + +- 移除 `stat-card` 的 `hover:-translate-y-0.5`,改为与 `section-card` 一致的仅阴影变化 +- 移除 `.arco-btn-primary:hover` 的 `transform: translateY(-1px)` +- 统一所有悬浮阴影为同一级别 + +### 步骤 3:修复渐变色 (`layout/index.tsx`, `ProfileSummary.tsx`) + +将 `to-blue-600` 改为 `to-brand`: +- `layout/index.tsx` 行 61:Logo 渐变 +- `layout/index.tsx` 行 103:Avatar 渐变 +- `ProfileSummary.tsx` 行 7:Avatar 渐变 + +### 步骤 4:修复登录页背景色 (`Login/index.tsx`, `LoginPanel.tsx`) + +将 `bg-[#f7f8fa]` 改为 `bg-canvas` + +### 步骤 5:统一页面结构 (`Role/index.tsx`, `Personnel/index.tsx`) + +为 Role 和 Personnel 页面添加 `page-stack` 包裹: +```tsx +return ( +
+ +``` + +### 步骤 6:统一 Modal 宽度 + +所有包含表单的 Modal 统一使用 `style={{ width: 640 }}`: +- `Role/index.tsx`:新增角色 Modal 添加宽度 +- `Personnel/index.tsx`:新增人员 Modal、分配角色 Modal 添加宽度 + +### 步骤 7:统一分页配置 + +所有 Table 的 pagination 统一添加 `sizeCanChange: true` 和 `showTotal: true`: +- `User/index.tsx` +- `Role/index.tsx` +- `Personnel/index.tsx` +- `Data/index.tsx`(3个表格) + +### 步骤 8:统一状态标签颜色 + +禁用/停用状态统一使用 `gray` 而非 `red`: +- `User/index.tsx`:将 `'red'` 改为 `'gray'` +- `Personnel/index.tsx`:将 `'red'` 改为 `'gray'` + +### 步骤 9:统一"新增"按钮颜色 + +`DramaList.tsx` 的"新增短剧"按钮移除 `status="success"`,使用默认蓝色主按钮。 + +### 步骤 10:统一 InputNumber 宽度 + +`Channel/index.tsx` 的 InputNumber 从 `style={{ width: 180 }}` 改为 `style={{ width: 200 }}`,与 Select 保持一致。 + +## 涉及文件清单 + +1. `tailwind.config.js` — 新增 secondary/header-bg/row-hover/border-hover token +2. `src/index.css` — 统一颜色引用、统一悬浮效果 +3. `src/layout/index.tsx` — 修复渐变色 blue-600 → brand +4. `src/Profile/components/ProfileSummary.tsx` — 修复渐变色 +5. `src/Login/index.tsx` — 背景色 canvas +6. `src/Login/components/LoginPanel.tsx` — 背景色 canvas +7. `src/Role/index.tsx` — 添加 page-stack、Modal 宽度、分页配置 +8. `src/Personnel/index.tsx` — 添加 page-stack、Modal 宽度、分页配置、状态标签颜色 +9. `src/User/index.tsx` — 分页配置、状态标签颜色 +10. `src/Data/index.tsx` — 分页配置(3个表格) +11. `src/Drama/components/DramaList.tsx` — 按钮颜色 + +## 验证方式 + +1. `pnpm lint` — TypeScript 类型检查通过 +2. `pnpm build` — 构建成功 +3. 视觉检查:各页面悬浮效果、颜色、间距保持一致 diff --git a/src/Channel/index.tsx b/src/Channel/index.tsx index 0e7a08d..53b7c18 100644 --- a/src/Channel/index.tsx +++ b/src/Channel/index.tsx @@ -84,10 +84,10 @@ export default function ChannelPage() { - + - 启用 停用 diff --git a/src/Data/index.tsx b/src/Data/index.tsx index ba6b7cc..47e89d4 100644 --- a/src/Data/index.tsx +++ b/src/Data/index.tsx @@ -55,7 +55,7 @@ function DataPage() { - -
-
- } onClick={() => setVisible(true)}>新增短剧}> + } onClick={() => setVisible(true)}>新增短剧}>
短剧标题
diff --git a/src/Login/components/LoginPanel.tsx b/src/Login/components/LoginPanel.tsx index 477ac88..43fc5b0 100644 --- a/src/Login/components/LoginPanel.tsx +++ b/src/Login/components/LoginPanel.tsx @@ -4,7 +4,7 @@ import type { LoginPanelProps } from "../interface"; export const LoginPanel = ({ loading, onSubmit }: LoginPanelProps) => { return ( -
+

后台登录

diff --git a/src/Login/index.tsx b/src/Login/index.tsx index 3bfeed2..0d51ae3 100644 --- a/src/Login/index.tsx +++ b/src/Login/index.tsx @@ -23,7 +23,7 @@ function LoginPage() { }; return ( -
+
diff --git a/src/Personnel/index.tsx b/src/Personnel/index.tsx index b2921f3..9394870 100644 --- a/src/Personnel/index.tsx +++ b/src/Personnel/index.tsx @@ -66,14 +66,15 @@ function PersonnelPage() { )); return ( +
} onClick={openCreate}>新增人员} noPadding> -
{record.isSuperAdmin ? 超级管理员 : record.roles.map((role) => {role.name})} }, - { title: '状态', dataIndex: 'status', width: 120, render: (status) => {status === 'active' ? '启用' : '禁用'} }, + { title: '状态', dataIndex: 'status', width: 120, render: (status) => {status === 'active' ? '启用' : '禁用'} }, { title: '创建时间', dataIndex: 'createdAt', width: 190 }, { title: '操作', @@ -88,7 +89,7 @@ function PersonnelPage() { ), }, ]} /> - setCreateVisible(false)} footer={null}> + setCreateVisible(false)} footer={null} style={{ width: 640 }}>
@@ -119,6 +120,7 @@ function PersonnelPage() { confirmLoading={assigning} onOk={saveAssignedRoles} onCancel={() => setAssignVisible(false)} + style={{ width: 640 }} > @@ -135,10 +138,12 @@ function RolesPage() { confirmLoading={savingPermissions} onOk={saveRolePermissions} onCancel={() => setAssignmentVisible(false)} + style={{ width: 640 }} >
+ ); } diff --git a/src/User/index.tsx b/src/User/index.tsx index 9e2d053..3641798 100644 --- a/src/User/index.tsx +++ b/src/User/index.tsx @@ -15,11 +15,11 @@ function UsersPage() { return (
-
{status === 'active' ? '启用' : '禁用'} }, + { title: '状态', dataIndex: 'status', width: 120, render: (status) => {status === 'active' ? '启用' : '禁用'} }, { title: '操作', width: 160, render: (_, record: AppUser) => }, ]} /> diff --git a/src/index.css b/src/index.css index e69fdae..c630804 100644 --- a/src/index.css +++ b/src/index.css @@ -26,7 +26,7 @@ } .section-card:hover { - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + box-shadow: theme('boxShadow.card-hover'); } .page-stack { @@ -38,7 +38,7 @@ } .form-label { - @apply mb-2 text-sm font-medium text-ink; + @apply mb-2 text-sm font-medium; } .form-help { @@ -46,7 +46,7 @@ } .stat-card { - @apply rounded-xl border border-line/60 bg-white p-5 shadow-sm transition-all duration-300 hover:shadow-lg hover:-translate-y-0.5 cursor-default; + @apply rounded-xl border border-line/60 bg-white p-5 shadow-sm transition-shadow duration-300 hover:shadow-card-hover cursor-default; } } @@ -66,12 +66,12 @@ } .arco-menu-item:hover { - background-color: #f2f3f5 !important; + background-color: theme('colors.canvas') !important; } .arco-menu-item.arco-menu-selected { - background-color: #e8f3ff !important; - color: #165dff !important; + background-color: theme('colors.brand-light') !important; + color: theme('colors.brand') !important; font-weight: 600 !important; } @@ -80,29 +80,29 @@ } .arco-menu-inline-header:hover { - background-color: #f2f3f5 !important; + background-color: theme('colors.canvas') !important; } /* ── Card ───────────────────────────────────────────── */ .arco-card { - border: 1px solid rgba(229, 230, 235, 0.6) !important; - box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.04) !important; + border: 1px solid theme('colors.line / 60%') !important; + box-shadow: theme('boxShadow.card') !important; transition: box-shadow 0.3s ease !important; } .arco-card:hover { - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06) !important; + box-shadow: theme('boxShadow.card-hover') !important; } .arco-card-header { - border-bottom: 1px solid rgba(229, 230, 235, 0.5) !important; + border-bottom: 1px solid theme('colors.line / 50%') !important; padding: 14px 20px !important; } .arco-card-header-title { font-weight: 600 !important; font-size: 15px !important; - color: #1d2129 !important; + color: theme('colors.ink') !important; } /* ── Table ──────────────────────────────────────────── */ @@ -111,12 +111,12 @@ } .arco-table-th { - background-color: #fafbfc !important; + background-color: theme('colors.header-bg') !important; font-weight: 600 !important; - color: #4e5969 !important; + color: theme('colors.secondary') !important; font-size: 13px !important; letter-spacing: 0.01em; - border-bottom: 1px solid rgba(229, 230, 235, 0.8) !important; + border-bottom: 1px solid theme('colors.line / 80%') !important; } .arco-table-td { @@ -124,7 +124,7 @@ } .arco-table-tr:hover .arco-table-td { - background-color: #f7f8fa !important; + background-color: theme('colors.row-hover') !important; } .arco-table-sticky-header .arco-table-container { @@ -142,16 +142,16 @@ } .arco-pagination-item:hover { - background-color: #e8f3ff !important; - color: #165dff !important; - border-color: #bedaff !important; + background-color: theme('colors.brand-light') !important; + color: theme('colors.brand') !important; + border-color: theme('colors.brand / 40%') !important; } .arco-pagination-item-active { - background-color: #165dff !important; - border-color: #165dff !important; + background-color: theme('colors.brand') !important; + border-color: theme('colors.brand') !important; color: #fff !important; - box-shadow: 0 2px 6px rgba(22, 93, 251, 0.3) !important; + box-shadow: 0 2px 6px theme('colors.brand / 30%') !important; } /* ── Button ─────────────────────────────────────────── */ @@ -161,25 +161,24 @@ } .arco-btn-primary { - box-shadow: 0 2px 6px rgba(22, 93, 251, 0.3) !important; + box-shadow: 0 2px 6px theme('colors.brand / 30%') !important; } .arco-btn-primary:hover { - box-shadow: 0 4px 12px rgba(22, 93, 251, 0.4) !important; - transform: translateY(-1px); + box-shadow: 0 4px 12px theme('colors.brand / 40%') !important; } .arco-btn-secondary:not(.arco-btn-disabled):hover { - background-color: #f2f3f5 !important; - border-color: #c9cdd4 !important; + background-color: theme('colors.canvas') !important; + border-color: theme('colors.line-hover') !important; } .arco-btn-text:not(.arco-btn-disabled):hover { - background-color: #f2f3f5 !important; + background-color: theme('colors.canvas') !important; } .arco-btn-text-danger:not(.arco-btn-disabled):hover { - background-color: #fff1f0 !important; + background-color: theme('colors.danger-light') !important; } /* ── Modal ──────────────────────────────────────────── */ @@ -188,7 +187,7 @@ } .arco-modal-header { - border-bottom: 1px solid rgba(229, 230, 235, 0.6) !important; + border-bottom: 1px solid theme('colors.line / 60%') !important; padding: 16px 24px !important; } @@ -202,7 +201,7 @@ } .arco-modal-footer { - border-top: 1px solid rgba(229, 230, 235, 0.6) !important; + border-top: 1px solid theme('colors.line / 60%') !important; padding: 12px 24px !important; } @@ -212,12 +211,12 @@ } .arco-input-wrapper:hover { - border-color: #c9cdd4 !important; + border-color: theme('colors.line-hover') !important; } .arco-input-wrapper.arco-input-focus { - border-color: #165dff !important; - box-shadow: 0 0 0 2px rgba(22, 93, 251, 0.1) !important; + border-color: theme('colors.brand') !important; + box-shadow: 0 0 0 2px theme('colors.brand / 10%') !important; } .arco-select-view { @@ -225,12 +224,12 @@ } .arco-select-view:hover { - border-color: #c9cdd4 !important; + border-color: theme('colors.line-hover') !important; } .arco-select-view.arco-select-view-focus { - border-color: #165dff !important; - box-shadow: 0 0 0 2px rgba(22, 93, 251, 0.1) !important; + border-color: theme('colors.brand') !important; + box-shadow: 0 0 0 2px theme('colors.brand / 10%') !important; } .arco-textarea-wrapper { @@ -238,18 +237,18 @@ } .arco-textarea-wrapper:hover { - border-color: #c9cdd4 !important; + border-color: theme('colors.line-hover') !important; } .arco-textarea-focus { - border-color: #165dff !important; - box-shadow: 0 0 0 2px rgba(22, 93, 251, 0.1) !important; + border-color: theme('colors.brand') !important; + box-shadow: 0 0 0 2px theme('colors.brand / 10%') !important; } /* ── Form ───────────────────────────────────────────── */ .arco-form-item-label { font-weight: 500 !important; - color: #4e5969 !important; + color: theme('colors.secondary') !important; font-size: 13px !important; } @@ -262,12 +261,12 @@ /* ── Descriptions ───────────────────────────────────── */ .arco-descriptions-item-label { font-weight: 500 !important; - color: #86909c !important; - background-color: #fafbfc !important; + color: theme('colors.muted') !important; + background-color: theme('colors.header-bg') !important; } .arco-descriptions-item-value { - color: #1d2129 !important; + color: theme('colors.ink') !important; } /* ── Dropdown ───────────────────────────────────────── */ @@ -280,7 +279,7 @@ } .arco-dropdown-menu-item:hover { - background-color: #f2f3f5 !important; + background-color: theme('colors.canvas') !important; } /* ── Switch ─────────────────────────────────────────── */ @@ -289,5 +288,5 @@ } .arco-switch-checked { - box-shadow: 0 2px 4px rgba(22, 93, 251, 0.3) !important; + box-shadow: 0 2px 4px theme('colors.brand / 30%') !important; } diff --git a/src/layout/index.tsx b/src/layout/index.tsx index a7a19b0..428c47f 100644 --- a/src/layout/index.tsx +++ b/src/layout/index.tsx @@ -58,7 +58,7 @@ export function AdminLayout() { trigger={null} >
- TK + TK {!collapsed && TK短剧管理后台}
@@ -99,8 +99,8 @@ export function AdminLayout() { } > - diff --git a/tailwind.config.js b/tailwind.config.js index 31a13ce..d9fe521 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -9,9 +9,13 @@ export default { extend: { colors: { ink: '#1d2129', + secondary: '#4e5969', muted: '#86909c', line: '#e5e6eb', + 'line-hover': '#c9cdd4', canvas: '#f2f3f5', + 'row-hover': '#f7f8fa', + 'header-bg': '#fafbfc', panel: '#fbfcfd', brand: '#165dff', 'brand-light': '#e8f3ff',