From 99bc522b24f063642f0ee10acc0877bfd6d01e8b Mon Sep 17 00:00:00 2001 From: zou Date: Tue, 18 Aug 2026 14:47:39 +0800 Subject: [PATCH] =?UTF-8?q?feat(F006):=20=E5=90=8E=E5=8F=B0UI=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E8=A7=84=E8=8C=83=20-=20DataTable=E9=BB=98=E8=AE=A4bo?= =?UTF-8?q?rderless/=E5=85=A8=E5=B1=80=E8=A1=A8=E6=A0=BC=E8=A1=A8=E5=A4=B4?= =?UTF-8?q?=E5=BA=95=E8=89=B2=E5=9C=86=E8=A7=92=E7=BB=9F=E4=B8=80/?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=86=85=E8=BE=B9=E8=B7=9D=E7=BB=9F=E4=B8=80?= =?UTF-8?q?/=E7=8A=B6=E6=80=81=E8=89=B2token=E5=8C=96(=E6=9A=97=E8=89=B2?= =?UTF-8?q?=E9=80=82=E9=85=8D)/=E6=A0=87=E9=A2=98=E5=AD=97=E5=8F=B720px?= =?UTF-8?q?=E7=BB=9F=E4=B8=80/=E7=BB=9F=E8=AE=A1=E9=A1=B5echarts=E5=BC=82?= =?UTF-8?q?=E6=AD=A5=E7=BB=84=E4=BB=B6=E6=8B=86=E5=88=86(509KB->6.9KB)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DataTable/DataTable.vue | 3 +- src/main.ts | 1 + src/modules/dashboard/DashboardView.vue | 2 +- .../supplierBrand/SupplierBrandListView.vue | 4 +- src/modules/statistics/StatisticsView.vue | 88 ++--------------- .../statistics/charts/EchartsStatusPie.vue | 94 ++++++++++++++++++ .../statistics/charts/EchartsTrendChart.vue | 89 +++++++++++++++++ src/modules/sys/DeptListView.vue | 2 +- src/modules/sys/DictDataListView.vue | 2 +- src/modules/sys/DictTypeListView.vue | 2 +- src/modules/sys/FileListView.vue | 2 +- src/modules/sys/MenuListView.vue | 2 +- src/modules/sys/NoticeListView.vue | 2 +- src/modules/sys/PostListView.vue | 2 +- src/modules/sys/ProductListView.vue | 2 +- src/modules/sys/RoleGroupListView.vue | 2 +- src/modules/sys/ScheduleListView.vue | 2 +- src/modules/user/EnterpriseListView.vue | 17 ++-- src/styles/global-ui.scss | 99 +++++++++++++++++++ 19 files changed, 314 insertions(+), 103 deletions(-) create mode 100644 src/modules/statistics/charts/EchartsStatusPie.vue create mode 100644 src/modules/statistics/charts/EchartsTrendChart.vue create mode 100644 src/styles/global-ui.scss diff --git a/src/components/DataTable/DataTable.vue b/src/components/DataTable/DataTable.vue index 0c0b2b6..3c02a17 100644 --- a/src/components/DataTable/DataTable.vue +++ b/src/components/DataTable/DataTable.vue @@ -63,7 +63,8 @@ const props = withDefaults(defineProps(), { pageSizes: () => [10, 20, 50, 100], rowKey: 'id', stripe: false, - borderless: false, + // 2026-08-18 UI 统一: 默认无边框 (带 border 的老页面由全局样式消除, 见 styles/global-ui.scss) + borderless: true, emptyText: '暂无数据', errorText: '', error: null diff --git a/src/main.ts b/src/main.ts index bf8b4a9..d0413d2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -10,6 +10,7 @@ import 'element-plus/dist/index.css' import './theme/tokens.scss' import './theme/themes.scss' import './styles/global-popper.scss' +import './styles/global-ui.scss' // 2026-08-18 UI 统一规范 (表格/卡片/内边距/暗色状态色) import { loadTheme } from './theme/presets' // 启动时恢复用户主题 diff --git a/src/modules/dashboard/DashboardView.vue b/src/modules/dashboard/DashboardView.vue index fb76e83..bf8f197 100644 --- a/src/modules/dashboard/DashboardView.vue +++ b/src/modules/dashboard/DashboardView.vue @@ -414,7 +414,7 @@ window.addEventListener('resize', () => { trendChart?.resize(); statusChart?.res .rr-dashboard { max-width: 1400px; } .rr-page-header { margin-bottom: 20px; } .rr-page-title { - font-size: 22px; font-weight: 600; letter-spacing: -0.02em; + font-size: 20px; font-weight: 700; color: var(--ink); margin-bottom: 4px; } .rr-page-sub { color: var(--ink-3); font-size: 13px; } diff --git a/src/modules/other/supplierBrand/SupplierBrandListView.vue b/src/modules/other/supplierBrand/SupplierBrandListView.vue index d967674..f0b2565 100644 --- a/src/modules/other/supplierBrand/SupplierBrandListView.vue +++ b/src/modules/other/supplierBrand/SupplierBrandListView.vue @@ -241,7 +241,7 @@ onMounted(load) - + @@ -279,7 +279,7 @@ onMounted(load) \ No newline at end of file diff --git a/src/modules/statistics/charts/EchartsTrendChart.vue b/src/modules/statistics/charts/EchartsTrendChart.vue new file mode 100644 index 0000000..fcca6d0 --- /dev/null +++ b/src/modules/statistics/charts/EchartsTrendChart.vue @@ -0,0 +1,89 @@ + + + + + \ No newline at end of file diff --git a/src/modules/sys/DeptListView.vue b/src/modules/sys/DeptListView.vue index 536eb84..8255f95 100644 --- a/src/modules/sys/DeptListView.vue +++ b/src/modules/sys/DeptListView.vue @@ -226,7 +226,7 @@ onMounted(load) .rr-muted { color: var(--ink-3); font-size: 12px; } .rr-page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .rr-page-titles { display: flex; flex-direction: column; gap: 2px; } -.rr-page-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--el-text-color-primary); } +.rr-page-title { margin: 0; font-size: 20px; font-weight: 700; color: var(--el-text-color-primary); } .rr-page-sub { margin: 0; font-size: 12px; color: var(--el-text-color-secondary); } .rr-page-actions { display: flex; gap: 8px; } .rr-list-card { background: var(--el-bg-color); border-radius: 12px; padding: 4px; } diff --git a/src/modules/sys/DictDataListView.vue b/src/modules/sys/DictDataListView.vue index ff52f33..d6a72bc 100644 --- a/src/modules/sys/DictDataListView.vue +++ b/src/modules/sys/DictDataListView.vue @@ -229,7 +229,7 @@ onMounted(load) .rr-muted { color: var(--ink-3); font-size: 12px; } .rr-page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .rr-page-titles { display: flex; flex-direction: column; gap: 2px; } -.rr-page-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--el-text-color-primary); } +.rr-page-title { margin: 0; font-size: 20px; font-weight: 700; color: var(--el-text-color-primary); } .rr-page-sub { margin: 0; font-size: 12px; color: var(--el-text-color-secondary); } .rr-page-actions { display: flex; gap: 8px; } .rr-filters-row { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; padding: 12px 16px; background: var(--el-fill-color-light); border-radius: 8px; } diff --git a/src/modules/sys/DictTypeListView.vue b/src/modules/sys/DictTypeListView.vue index a7e413a..e8cede7 100644 --- a/src/modules/sys/DictTypeListView.vue +++ b/src/modules/sys/DictTypeListView.vue @@ -213,7 +213,7 @@ onMounted(load) .rr-muted { color: var(--ink-3); font-size: 12px; } .rr-page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .rr-page-titles { display: flex; flex-direction: column; gap: 2px; } -.rr-page-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--el-text-color-primary); } +.rr-page-title { margin: 0; font-size: 20px; font-weight: 700; color: var(--el-text-color-primary); } .rr-page-sub { margin: 0; font-size: 12px; color: var(--el-text-color-secondary); } .rr-page-actions { display: flex; gap: 8px; } .rr-filters-row { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; padding: 12px 16px; background: var(--el-fill-color-light); border-radius: 8px; } diff --git a/src/modules/sys/FileListView.vue b/src/modules/sys/FileListView.vue index 3b34aef..258f58e 100644 --- a/src/modules/sys/FileListView.vue +++ b/src/modules/sys/FileListView.vue @@ -137,7 +137,7 @@ onMounted(load) .rr-muted { color: var(--ink-3); font-size: 12px; } .rr-page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .rr-page-titles { display: flex; flex-direction: column; gap: 2px; } -.rr-page-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--el-text-color-primary); } +.rr-page-title { margin: 0; font-size: 20px; font-weight: 700; color: var(--el-text-color-primary); } .rr-page-sub { margin: 0; font-size: 12px; color: var(--el-text-color-secondary); } .rr-page-actions { display: flex; gap: 8px; } .rr-list-card { background: var(--el-bg-color); border-radius: 12px; padding: 4px; } diff --git a/src/modules/sys/MenuListView.vue b/src/modules/sys/MenuListView.vue index 1b2dd34..7aed1d3 100644 --- a/src/modules/sys/MenuListView.vue +++ b/src/modules/sys/MenuListView.vue @@ -275,7 +275,7 @@ onMounted(load) .rr-muted { color: var(--ink-3); font-size: 12px; } .rr-page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .rr-page-titles { display: flex; flex-direction: column; gap: 2px; } -.rr-page-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--el-text-color-primary); } +.rr-page-title { margin: 0; font-size: 20px; font-weight: 700; color: var(--el-text-color-primary); } .rr-page-sub { margin: 0; font-size: 12px; color: var(--el-text-color-secondary); } .rr-page-actions { display: flex; gap: 8px; } .rr-list-card { background: var(--el-bg-color); border-radius: 12px; padding: 4px; } diff --git a/src/modules/sys/NoticeListView.vue b/src/modules/sys/NoticeListView.vue index ce1a715..0cb134c 100644 --- a/src/modules/sys/NoticeListView.vue +++ b/src/modules/sys/NoticeListView.vue @@ -260,7 +260,7 @@ onMounted(load) .rr-muted { color: var(--ink-3); font-size: 12px; } .rr-page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .rr-page-titles { display: flex; flex-direction: column; gap: 2px; } -.rr-page-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--el-text-color-primary); } +.rr-page-title { margin: 0; font-size: 20px; font-weight: 700; color: var(--el-text-color-primary); } .rr-page-sub { margin: 0; font-size: 12px; color: var(--el-text-color-secondary); } .rr-page-actions { display: flex; gap: 8px; } .rr-filters-row { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; padding: 12px 16px; background: var(--el-fill-color-light); border-radius: 8px; } diff --git a/src/modules/sys/PostListView.vue b/src/modules/sys/PostListView.vue index e5865ce..667d0d4 100644 --- a/src/modules/sys/PostListView.vue +++ b/src/modules/sys/PostListView.vue @@ -221,7 +221,7 @@ onMounted(load) .rr-muted { color: var(--ink-3); font-size: 12px; } .rr-page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .rr-page-titles { display: flex; flex-direction: column; gap: 2px; } -.rr-page-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--el-text-color-primary); } +.rr-page-title { margin: 0; font-size: 20px; font-weight: 700; color: var(--el-text-color-primary); } .rr-page-sub { margin: 0; font-size: 12px; color: var(--el-text-color-secondary); } .rr-page-actions { display: flex; gap: 8px; } .rr-filters-row { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; padding: 12px 16px; background: var(--el-fill-color-light); border-radius: 8px; } diff --git a/src/modules/sys/ProductListView.vue b/src/modules/sys/ProductListView.vue index 5dcbe15..6f39cfb 100644 --- a/src/modules/sys/ProductListView.vue +++ b/src/modules/sys/ProductListView.vue @@ -254,7 +254,7 @@ onMounted(load) .rr-muted { color: var(--ink-3); font-size: 12px; } .rr-page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .rr-page-titles { display: flex; flex-direction: column; gap: 2px; } -.rr-page-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--el-text-color-primary); } +.rr-page-title { margin: 0; font-size: 20px; font-weight: 700; color: var(--el-text-color-primary); } .rr-page-sub { margin: 0; font-size: 12px; color: var(--el-text-color-secondary); } .rr-page-actions { display: flex; gap: 8px; } .rr-filters-row { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; padding: 12px 16px; background: var(--el-fill-color-light); border-radius: 8px; } diff --git a/src/modules/sys/RoleGroupListView.vue b/src/modules/sys/RoleGroupListView.vue index 86adcaf..3ac1bbf 100644 --- a/src/modules/sys/RoleGroupListView.vue +++ b/src/modules/sys/RoleGroupListView.vue @@ -189,7 +189,7 @@ onMounted(load) .rr-muted { color: var(--ink-3); font-size: 12px; } .rr-page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .rr-page-titles { display: flex; flex-direction: column; gap: 2px; } -.rr-page-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--el-text-color-primary); } +.rr-page-title { margin: 0; font-size: 20px; font-weight: 700; color: var(--el-text-color-primary); } .rr-page-sub { margin: 0; font-size: 12px; color: var(--el-text-color-secondary); } .rr-page-actions { display: flex; gap: 8px; } .rr-filters-row { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; padding: 12px 16px; background: var(--el-fill-color-light); border-radius: 8px; } diff --git a/src/modules/sys/ScheduleListView.vue b/src/modules/sys/ScheduleListView.vue index b2c89e8..284a019 100644 --- a/src/modules/sys/ScheduleListView.vue +++ b/src/modules/sys/ScheduleListView.vue @@ -193,7 +193,7 @@ onMounted(load) .rr-muted { color: var(--ink-3); font-size: 12px; } .rr-page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; } .rr-page-titles { display: flex; flex-direction: column; gap: 2px; } -.rr-page-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--el-text-color-primary); } +.rr-page-title { margin: 0; font-size: 20px; font-weight: 700; color: var(--el-text-color-primary); } .rr-page-sub { margin: 0; font-size: 12px; color: var(--el-text-color-secondary); } .rr-page-actions { display: flex; gap: 8px; } .rr-filters-row { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; padding: 12px 16px; background: var(--el-fill-color-light); border-radius: 8px; } diff --git a/src/modules/user/EnterpriseListView.vue b/src/modules/user/EnterpriseListView.vue index 58d0bb5..54f6ac2 100644 --- a/src/modules/user/EnterpriseListView.vue +++ b/src/modules/user/EnterpriseListView.vue @@ -86,19 +86,20 @@ const filters = reactive({ }) // status 映射 (老 vue: 1=待审核,2=已认证,3=已驳回) +// 状态/等级色引用全局 token (styles/global-ui.scss), 主题切换自动适配暗色 const STATUS_META: Record = { - '1': { label: '待审核', color: '#b45309', bg: '#fef3c7' }, - '2': { label: '已认证', color: '#15803d', bg: '#dcfce7' }, - '3': { label: '已驳回', color: '#b91c1c', bg: '#fee2e2' } + '1': { label: '待审核', color: 'var(--st-warn-fg)', bg: 'var(--st-warn-bg)' }, + '2': { label: '已认证', color: 'var(--st-ok-fg)', bg: 'var(--st-ok-bg)' }, + '3': { label: '已驳回', color: 'var(--st-err-fg)', bg: 'var(--st-err-bg)' } } // supplierLevel 映射 (老 vue: 1=优质,2=钻石,3=金牌,4=银牌,5=铜牌) const LEVEL_META: Record = { - 1: { label: '优质供应商', color: '#92400e', bg: '#fef3c7' }, - 2: { label: '钻石供应商', color: '#6d28d9', bg: '#ede9fe' }, - 3: { label: '金牌供应商', color: '#c2410c', bg: '#ffedd5' }, - 4: { label: '银牌供应商', color: '#475569', bg: '#f1f5f9' }, - 5: { label: '铜牌供应商', color: '#a16207', bg: '#fefce8' } + 1: { label: '优质供应商', color: 'var(--st-lv1-fg)', bg: 'var(--st-lv1-bg)' }, + 2: { label: '钻石供应商', color: 'var(--st-lv2-fg)', bg: 'var(--st-lv2-bg)' }, + 3: { label: '金牌供应商', color: 'var(--st-lv3-fg)', bg: 'var(--st-lv3-bg)' }, + 4: { label: '银牌供应商', color: 'var(--st-lv4-fg)', bg: 'var(--st-lv4-bg)' }, + 5: { label: '铜牌供应商', color: 'var(--st-lv5-fg)', bg: 'var(--st-lv5-bg)' } } // 头像品牌渐变色组 (企业无 logo 时交替使用) diff --git a/src/styles/global-ui.scss b/src/styles/global-ui.scss new file mode 100644 index 0000000..051034a --- /dev/null +++ b/src/styles/global-ui.scss @@ -0,0 +1,99 @@ +/* ============================================================ + * 后台全局 UI 统一规范 (2026-08-18 建立) + * 由 UI 审查驱动, 解决跨页视觉一致性缺口: + * 1. 页面骨架统一 (rr-page 默认内边距) + * 2. 表格视觉统一 (表头底色/圆角/消除老页面 border 竖线) + * 3. 卡片圆角统一 + * 4. 状态标签/el-tag 暗色主题适配 + * 设计原则: 只做"兜底默认", 页面 scoped 样式优先覆盖 + * ============================================================ */ + +/* ---------- 1. 页面骨架: 默认 16px 内边距 (页面未定义时生效) ---------- */ +.rr-page { padding: 16px; } + +/* ---------- 2. 表格视觉统一 ---------- */ +/* 表头底色/文字统一 (el-table 全局) */ +.el-table { + --el-table-header-bg-color: var(--surface-2, #f1f5f9); + --el-table-header-text-color: var(--ink-3, #64748b); +} +.el-table th.el-table__cell { + background: var(--surface-2, #f1f5f9) !important; /* !important 覆盖 EP .el-table--border 表头白底 */ + color: var(--ink-3, #64748b); + font-weight: 600; +} +/* 单元格内边距统一 (与 DataTable 规范一致) */ +.el-table td.el-table__cell { padding: 10px 12px; } + +/* 消除老页面裸 el-table border 属性产生的边框/竖线 → 统一 borderless 视觉 */ +.el-table--border, +.el-table--border .el-table__cell, +.el-table--border th.el-table__cell, +.el-table--border td.el-table__cell { + border: none !important; +} +.el-table--border .el-table__inner-wrapper::after, +.el-table--border .el-table__inner-wrapper::before, +.el-table::before, +.el-table::after { + display: none !important; +} + +/* ---------- 3. 卡片圆角统一 ---------- */ +.rr-list-card, +.rr-card, +.info-card { + border-radius: 12px; +} + +/* ---------- 4. 状态色暗色适配 ---------- */ +/* 状态语义色 token (亮色默认) — 各页面状态标签通过 var() 引用, 主题切换自动适配 */ +:root, +[data-theme="tech-blue"], +[data-theme="red"], +[data-theme="purple"] { + --st-warn-fg: #b45309; --st-warn-bg: #fef3c7; + --st-ok-fg: #15803d; --st-ok-bg: #dcfce7; + --st-err-fg: #b91c1c; --st-err-bg: #fee2e2; + --st-lv1-fg: #92400e; --st-lv1-bg: #fef3c7; + --st-lv2-fg: #6d28d9; --st-lv2-bg: #ede9fe; + --st-lv3-fg: #c2410c; --st-lv3-bg: #ffedd5; + --st-lv4-fg: #475569; --st-lv4-bg: #f1f5f9; + --st-lv5-fg: #a16207; --st-lv5-bg: #fefce8; +} +[data-theme="dark"] { + --st-warn-fg: #fcd34d; --st-warn-bg: rgba(245, 158, 11, 0.16); + --st-ok-fg: #6ee7b7; --st-ok-bg: rgba(16, 185, 129, 0.16); + --st-err-fg: #fca5a5; --st-err-bg: rgba(239, 68, 68, 0.16); + --st-lv1-fg: #fcd34d; --st-lv1-bg: rgba(245, 158, 11, 0.14); + --st-lv2-fg: #c4b5fd; --st-lv2-bg: rgba(109, 40, 217, 0.2); + --st-lv3-fg: #fdba74; --st-lv3-bg: rgba(194, 65, 12, 0.2); + --st-lv4-fg: #cbd5e1; --st-lv4-bg: rgba(100, 116, 139, 0.2); + --st-lv5-fg: #fde047; --st-lv5-bg: rgba(161, 98, 7, 0.2); + + /* el-tag 四态: 暗色下深底浅字 */ + .el-tag--success { + --el-tag-bg-color: rgba(16, 185, 129, 0.16); + --el-tag-text-color: #6ee7b7; + --el-tag-border-color: rgba(16, 185, 129, 0.4); + } + .el-tag--warning { + --el-tag-bg-color: rgba(245, 158, 11, 0.16); + --el-tag-text-color: #fcd34d; + --el-tag-border-color: rgba(245, 158, 11, 0.4); + } + .el-tag--danger { + --el-tag-bg-color: rgba(239, 68, 68, 0.16); + --el-tag-text-color: #fca5a5; + --el-tag-border-color: rgba(239, 68, 68, 0.4); + } + .el-tag--info { + --el-tag-bg-color: rgba(148, 163, 184, 0.16); + --el-tag-text-color: #cbd5e1; + --el-tag-border-color: rgba(148, 163, 184, 0.4); + } + /* 老式 rr-tag-* 状态类 (浅底深字 -> 深底浅字) */ + .rr-tag-warn { background: rgba(245, 158, 11, 0.16); color: #fcd34d; } + .rr-tag-ok { background: rgba(16, 185, 129, 0.16); color: #6ee7b7; } + .rr-tag-err { background: rgba(239, 68, 68, 0.16); color: #fca5a5; } +} \ No newline at end of file