From f1a63ee4731bd13fe2b9f8262ffe6f60ab76034b Mon Sep 17 00:00:00 2001 From: hezhaohui Date: Wed, 15 Jul 2026 14:38:58 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat(frontend):=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=B7=B1=E8=89=B2/=E6=B5=85=E8=89=B2=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E5=88=87=E6=8D=A2=EF=BC=8C=E7=BB=9F=E4=B8=80=E4=B8=BB=E9=A2=98?= =?UTF-8?q?=E5=8F=98=E9=87=8F=E4=BD=93=E7=B3=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 useTheme composable,支持 light/dark 双主题,默认浅色模式 - 主题偏好持久化到 localStorage,支持跟随系统主题 - AppHeader 顶栏添加 Moon/Sunny 切换图标,带旋转过渡动效 - variables.css 重构为 :root(浅色)/:root.dark(深色)双套变量 - 新增标签色系(蓝/紫/琥珀/绿)、节点色系、阴影、发光效果等语义化变量 - 全组件硬编码颜色替换为 CSS 变量,消除跨主题不一致 - global.css 添加主题切换过渡动画(background/border/box-shadow) - 涉及组件:AppHeader、AppSidebar、SubsystemCard、AuditLogTable - 涉及页面:Dashboard、Resource、Cluster、Config、Task、Service、Login --- frontend/components.d.ts | 2 - frontend/src/components/AuditLogTable.vue | 4 +- frontend/src/components/Layout/AppHeader.vue | 54 ++++++- frontend/src/components/Layout/AppSidebar.vue | 12 +- frontend/src/components/SubsystemCard.vue | 30 ++-- frontend/src/composables/useTheme.ts | 68 ++++++++ frontend/src/styles/global.css | 38 ++++- frontend/src/styles/variables.css | 150 ++++++++++++++++++ frontend/src/views/auth/Login.vue | 8 +- frontend/src/views/cluster/ClusterList.vue | 26 +-- frontend/src/views/config/ConfigCenter.vue | 20 +-- frontend/src/views/dashboard/Index.vue | 32 ++-- frontend/src/views/resource/Management.vue | 22 +-- frontend/src/views/resource/StatusBoard.vue | 2 +- frontend/src/views/service/Catalog.vue | 12 +- frontend/src/views/service/Management.vue | 22 +-- frontend/src/views/task/TaskCenter.vue | 6 +- 17 files changed, 402 insertions(+), 106 deletions(-) create mode 100644 frontend/src/composables/useTheme.ts diff --git a/frontend/components.d.ts b/frontend/components.d.ts index 9fc6636..7821290 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -12,14 +12,12 @@ declare module 'vue' { AppSidebar: typeof import('./src/components/Layout/AppSidebar.vue')['default'] AuditLogTable: typeof import('./src/components/AuditLogTable.vue')['default'] ElButton: typeof import('element-plus/es')['ElButton'] - ElDivider: typeof import('element-plus/es')['ElDivider'] ElForm: typeof import('element-plus/es')['ElForm'] ElFormItem: typeof import('element-plus/es')['ElFormItem'] ElIcon: typeof import('element-plus/es')['ElIcon'] ElInput: typeof import('element-plus/es')['ElInput'] ElOption: typeof import('element-plus/es')['ElOption'] ElSelect: typeof import('element-plus/es')['ElSelect'] - ElSpace: typeof import('element-plus/es')['ElSpace'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] SubsystemCard: typeof import('./src/components/SubsystemCard.vue')['default'] diff --git a/frontend/src/components/AuditLogTable.vue b/frontend/src/components/AuditLogTable.vue index e568768..0813817 100644 --- a/frontend/src/components/AuditLogTable.vue +++ b/frontend/src/components/AuditLogTable.vue @@ -187,11 +187,11 @@ tr.tr-hover:hover td { .pg-btn.active { background: var(--accent-dim); border-color: var(--accent-dim); - color: #CFFCE9; + color: var(--active-text); } .pg-btn:hover { - border-color: #3A4356; + border-color: var(--hover-border); color: var(--text-hi); } diff --git a/frontend/src/components/Layout/AppHeader.vue b/frontend/src/components/Layout/AppHeader.vue index 0b9b8df..324d6ed 100644 --- a/frontend/src/components/Layout/AppHeader.vue +++ b/frontend/src/components/Layout/AppHeader.vue @@ -11,6 +11,14 @@ 搜索集群 / 节点 / 服务实例 ⌘K +
+ + + + + + +
{{ userInitial }}
@@ -24,12 +32,16 @@ diff --git a/frontend/src/components/Layout/AppSidebar.vue b/frontend/src/components/Layout/AppSidebar.vue index 298e2fd..09f4fea 100644 --- a/frontend/src/components/Layout/AppSidebar.vue +++ b/frontend/src/components/Layout/AppSidebar.vue @@ -118,24 +118,26 @@ } .nav-item.active { - background: #13261F; + background: var(--accent-dim); color: var(--accent); - border-color: var(--accent-dim); + border-color: var(--accent); } .nav-item .badge { margin-left: auto; font-family: var(--mono); font-size: 10px; - background: #262C38; + background: var(--bg-panel-2); color: var(--text-dim); padding: 1px 6px; border-radius: 10px; + border: 1px solid var(--line); } .nav-item.active .badge { - background: var(--accent-dim); - color: #CFFCE9; + background: var(--accent); + color: #FFFFFF; + border-color: var(--accent); } .sidebar-foot { diff --git a/frontend/src/components/SubsystemCard.vue b/frontend/src/components/SubsystemCard.vue index bd31574..1815db0 100644 --- a/frontend/src/components/SubsystemCard.vue +++ b/frontend/src/components/SubsystemCard.vue @@ -27,26 +27,26 @@ const props = defineProps<{ const bgColor = computed(() => { const colors: Record = { - W: '#1C2A3A', - DM: '#1C3A2E', - CC: '#3A1C28', - AP: '#1C2A3A', - QP: '#241B0A', - GF: '#1B202B', + W: 'var(--logo-w-bg)', + DM: 'var(--logo-dm-bg)', + CC: 'var(--logo-cc-bg)', + AP: 'var(--logo-ap-bg)', + QP: 'var(--logo-qp-bg)', + GF: 'var(--logo-gf-bg)', } - return colors[props.system.icon] || '#262C38' + return colors[props.system.icon] || 'var(--bg-panel-2)' }) const iconColor = computed(() => { const colors: Record = { - W: '#7FB8FF', - DM: '#7FFFC2', - CC: '#FF8E9C', - AP: '#8EC8FF', - QP: '#FFC97A', - GF: '#F2B544', + W: 'var(--tag-blue-text)', + DM: 'var(--tag-green-text)', + CC: 'var(--err)', + AP: 'var(--tag-blue-text)', + QP: 'var(--tag-amber-text)', + GF: 'var(--warn)', } - return colors[props.system.icon] || '#9AA3B5' + return colors[props.system.icon] || 'var(--text-mid)' }) const description = computed(() => { @@ -85,7 +85,7 @@ const handleClick = async () => { } .ext-card:hover { - border-color: #3A4356; + border-color: var(--hover-border); } .ext-top { diff --git a/frontend/src/composables/useTheme.ts b/frontend/src/composables/useTheme.ts new file mode 100644 index 0000000..b74e5a9 --- /dev/null +++ b/frontend/src/composables/useTheme.ts @@ -0,0 +1,68 @@ +import { ref, watch, onMounted } from 'vue' + +export type Theme = 'light' | 'dark' + +const THEME_KEY = 'xinfra-theme' + +// 默认浅色模式 +const theme = ref('light') + +export function useTheme() { + // 初始化主题 + const initTheme = () => { + const savedTheme = localStorage.getItem(THEME_KEY) as Theme | null + if (savedTheme && ['light', 'dark'].includes(savedTheme)) { + theme.value = savedTheme + } else { + // 默认浅色模式 + theme.value = 'light' + } + applyTheme(theme.value) + } + + // 应用主题 + const applyTheme = (newTheme: Theme) => { + document.documentElement.setAttribute('data-theme', newTheme) + document.documentElement.classList.toggle('dark', newTheme === 'dark') + } + + // 切换主题 + const toggleTheme = () => { + theme.value = theme.value === 'light' ? 'dark' : 'light' + localStorage.setItem(THEME_KEY, theme.value) + applyTheme(theme.value) + } + + // 设置主题 + const setTheme = (newTheme: Theme) => { + theme.value = newTheme + localStorage.setItem(THEME_KEY, theme.value) + applyTheme(theme.value) + } + + // 监听系统主题变化(可选) + const watchSystemTheme = () => { + if (window.matchMedia) { + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)') + mediaQuery.addEventListener('change', (e) => { + // 只有在用户没有手动设置过主题时才跟随系统 + if (!localStorage.getItem(THEME_KEY)) { + theme.value = e.matches ? 'dark' : 'light' + applyTheme(theme.value) + } + }) + } + } + + onMounted(() => { + initTheme() + watchSystemTheme() + }) + + return { + theme, + toggleTheme, + setTheme, + initTheme + } +} \ No newline at end of file diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index 324f9d7..e8586df 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -11,6 +11,22 @@ html, body { color: var(--text-hi); font-family: var(--sans); font-size: 14px; + transition: background-color 0.3s ease, color 0.3s ease; +} + +/* 主题切换过渡效果 */ +*, *::before, *::after { + transition: background-color 0.2s ease, + border-color 0.2s ease, + box-shadow 0.2s ease; +} + +/* 排除不需要过渡的元素 */ +.no-transition, +.no-transition *, +.no-transition *::before, +.no-transition *::after { + transition: none !important; } /* 滚动条样式 */ @@ -20,10 +36,14 @@ html, body { } ::-webkit-scrollbar-thumb { - background: #2A3140; + background: var(--bar-bg); border-radius: 4px; } +::-webkit-scrollbar-thumb:hover { + background: var(--text-dim); +} + ::-webkit-scrollbar-track { background: transparent; } @@ -54,7 +74,7 @@ button { .dot.ok { background: var(--accent); - box-shadow: 0 0 6px #3FE0A599; + box-shadow: 0 0 6px var(--accent-glow); } .dot.warn { @@ -109,7 +129,7 @@ button { .bar-wrap { width: 90px; height: 5px; - background: #262C38; + background: var(--bar-bg); border-radius: 3px; overflow: hidden; display: inline-block; @@ -130,3 +150,15 @@ button { .bar-fill.err { background: var(--err); } + +/* 卡片样式 */ +.card { + background: var(--bg-panel); + border: 1px solid var(--line); + border-radius: var(--radius); + box-shadow: var(--shadow-sm); +} + +.card:hover { + box-shadow: var(--shadow-md); +} diff --git a/frontend/src/styles/variables.css b/frontend/src/styles/variables.css index 30748e4..fe4e32e 100644 --- a/frontend/src/styles/variables.css +++ b/frontend/src/styles/variables.css @@ -1,4 +1,96 @@ +/* 浅色模式(默认) */ :root { + /* 背景色 */ + --bg-deep: #F5F7FA; + --bg-panel: #FFFFFF; + --bg-panel-2: #F0F2F5; + + /* 边框色 */ + --line: #E4E7ED; + --line-soft: #EBEEF5; + + /* 文字色 */ + --text-hi: #1D2129; + --text-mid: #4E5969; + --text-dim: #86909C; + + /* 强调色 */ + --accent: #00B42A; + --accent-dim: #E8FFEA; + + /* 状态色 */ + --warn: #FF7D00; + --err: #F53F3F; + --info: #165DFF; + + /* 圆角 */ + --radius: 6px; + + /* 字体 */ + --mono: 'IBM Plex Mono', monospace; + --sans: 'IBM Plex Sans', sans-serif; + + /* 阴影 */ + --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); + + /* 标签/徽章颜色 - 蓝色系 */ + --tag-blue-text: #165DFF; + --tag-blue-bg: #E8F3FF; + --tag-blue-border: #BEDAFF; + + /* 标签/徽章颜色 - 紫色系 */ + --tag-purple-text: #722ED1; + --tag-purple-bg: #F5E8FF; + --tag-purple-border: #D3ADF7; + + /* 标签/徽章颜色 - 琥珀色系 */ + --tag-amber-text: #D46B08; + --tag-amber-bg: #FFF7E6; + --tag-amber-border: #FFD591; + + /* 标签/徽章颜色 - 绿色系 */ + --tag-green-text: #00B42A; + --tag-green-bg: #E8FFEA; + --tag-green-border: #9FD9A8; + + /* 节点单元格颜色 */ + --node-empty-bg: #F0F2F5; + --node-a-bg: #E8FFEA; + --node-a-border: #9FD9A8; + --node-b-bg: #F5E8FF; + --node-b-border: #D3ADF7; + --node-c-bg: #FFF7E6; + --node-c-border: #FFD591; + + /* 进度条背景 */ + --bar-bg: #E4E7ED; + + /* 悬停边框 */ + --hover-border: #C9CDD4; + + /* 激活状态文字 */ + --active-text: #00873E; + + /* 主题切换按钮 */ + --theme-btn-bg: #F0F2F5; + --theme-btn-hover: #E4E7ED; + + /* 子系统卡片logo背景 */ + --logo-w-bg: #E8F3FF; + --logo-dm-bg: #E8FFEA; + --logo-cc-bg: #FFF0F0; + --logo-ap-bg: #E8F3FF; + --logo-qp-bg: #FFF7E6; + --logo-gf-bg: #F5F7FA; + + /* 发光/阴影效果 */ + --accent-glow: rgba(0, 180, 42, 0.3); +} + +/* 深色模式 */ +:root.dark { /* 背景色 */ --bg-deep: #0E1117; --bg-panel: #151922; @@ -28,4 +120,62 @@ /* 字体 */ --mono: 'IBM Plex Mono', monospace; --sans: 'IBM Plex Sans', sans-serif; + + /* 阴影 */ + --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3); + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3); + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.3); + + /* 标签/徽章颜色 - 蓝色系 */ + --tag-blue-text: #8EC8FF; + --tag-blue-bg: #0E1C2C; + --tag-blue-border: #1C3A5C; + + /* 标签/徽章颜色 - 紫色系 */ + --tag-purple-text: #C9A6FF; + --tag-purple-bg: #1A1430; + --tag-purple-border: #3A2C5C; + + /* 标签/徽章颜色 - 琥珀色系 */ + --tag-amber-text: #FFC97A; + --tag-amber-bg: #241B0A; + --tag-amber-border: #5C4A1C; + + /* 标签/徽章颜色 - 绿色系 */ + --tag-green-text: #7FFFC2; + --tag-green-bg: #0F261D; + --tag-green-border: var(--accent-dim); + + /* 节点单元格颜色 */ + --node-empty-bg: #1E2532; + --node-a-bg: #13261F; + --node-a-border: var(--accent-dim); + --node-b-bg: #1A1430; + --node-b-border: #3A2C5C; + --node-c-bg: #241B0A; + --node-c-border: #5C4A1C; + + /* 进度条背景 */ + --bar-bg: #262C38; + + /* 悬停边框 */ + --hover-border: #3A4356; + + /* 激活状态文字 */ + --active-text: #CFFCE9; + + /* 主题切换按钮 */ + --theme-btn-bg: #1B202B; + --theme-btn-hover: #262C38; + + /* 子系统卡片logo背景 */ + --logo-w-bg: #1C2A3A; + --logo-dm-bg: #1C3A2E; + --logo-cc-bg: #3A1C28; + --logo-ap-bg: #1C2A3A; + --logo-qp-bg: #241B0A; + --logo-gf-bg: #1B202B; + + /* 发光/阴影效果 */ + --accent-glow: rgba(63, 224, 165, 0.3); } diff --git a/frontend/src/views/auth/Login.vue b/frontend/src/views/auth/Login.vue index db9f04a..610aaa0 100644 --- a/frontend/src/views/auth/Login.vue +++ b/frontend/src/views/auth/Login.vue @@ -135,7 +135,7 @@ const handleLogin = async () => { font-family: var(--mono); font-size: 16px; font-weight: 600; - color: #08140F; + color: var(--bg-deep); } .login-header h2 { @@ -174,7 +174,7 @@ const handleLogin = async () => { } :deep(.el-input__wrapper:hover) { - border-color: #3A4356; + border-color: var(--hover-border); } :deep(.el-input__wrapper.is-focus) { @@ -188,11 +188,11 @@ const handleLogin = async () => { :deep(.el-button--primary) { background: var(--accent); border-color: var(--accent); - color: #06150F; + color: var(--bg-deep); font-weight: 600; } :deep(.el-button--primary:hover) { - background: #55E8B3; + opacity: 0.9; } diff --git a/frontend/src/views/cluster/ClusterList.vue b/frontend/src/views/cluster/ClusterList.vue index 8234378..c317218 100644 --- a/frontend/src/views/cluster/ClusterList.vue +++ b/frontend/src/views/cluster/ClusterList.vue @@ -86,9 +86,9 @@ const clusters = ref([ ]) const nodes = ref([ - { name: 'bj-node-014', ip: '10.21.4.14', label: 'business-line=kodo', labelColor: '#8EC8FF', labelBorder: '#1C3A5C', taint: 'kodo:NoSchedule', spec: '64C/256G', cpu: 58, cpuClass: '', status: 'Ready', statusClass: 'ok' }, - { name: 'bj-node-015', ip: '10.21.4.15', label: 'business-line=kodo', labelColor: '#8EC8FF', labelBorder: '#1C3A5C', taint: 'kodo:NoSchedule', spec: '64C/256G', cpu: 62, cpuClass: '', status: 'Ready', statusClass: 'ok' }, - { name: 'bj-node-031', ip: '10.21.4.31', label: 'business-line=las', labelColor: '#C9A6FF', labelBorder: '#3A2C5C', taint: 'las:NoSchedule', spec: '32C/128G', cpu: 88, cpuClass: 'warn', status: '资源告警', statusClass: 'warn' }, + { name: 'bj-node-014', ip: '10.21.4.14', label: 'business-line=kodo', labelColor: 'var(--tag-blue-text)', labelBorder: 'var(--tag-blue-border)', taint: 'kodo:NoSchedule', spec: '64C/256G', cpu: 58, cpuClass: '', status: 'Ready', statusClass: 'ok' }, + { name: 'bj-node-015', ip: '10.21.4.15', label: 'business-line=kodo', labelColor: 'var(--tag-blue-text)', labelBorder: 'var(--tag-blue-border)', taint: 'kodo:NoSchedule', spec: '64C/256G', cpu: 62, cpuClass: '', status: 'Ready', statusClass: 'ok' }, + { name: 'bj-node-031', ip: '10.21.4.31', label: 'business-line=las', labelColor: 'var(--tag-purple-text)', labelBorder: 'var(--tag-purple-border)', taint: 'las:NoSchedule', spec: '32C/128G', cpu: 88, cpuClass: 'warn', status: '资源告警', statusClass: 'warn' }, { name: 'bj-node-048', ip: '10.21.4.48', label: '未分配', labelColor: 'var(--text-dim)', labelBorder: 'var(--line)', taint: '—', spec: '32C/128G', cpu: 4, cpuClass: '', status: 'Ready · 空闲', statusClass: 'ok' }, ]) @@ -197,21 +197,21 @@ tr.tr-hover:hover td { } .tag.zone-a { - color: #8EC8FF; - border-color: #1C3A5C; - background: #0E1C2C; + color: var(--tag-blue-text); + border-color: var(--tag-blue-border); + background: var(--tag-blue-bg); } .tag.zone-b { - color: #C9A6FF; - border-color: #3A2C5C; - background: #1A1430; + color: var(--tag-purple-text); + border-color: var(--tag-purple-border); + background: var(--tag-purple-bg); } .tag.zone-c { - color: #FFC97A; - border-color: #5C4A1C; - background: #241B0A; + color: var(--tag-amber-text); + border-color: var(--tag-amber-border); + background: var(--tag-amber-bg); } .tag.biz { @@ -221,7 +221,7 @@ tr.tr-hover:hover td { .bar-wrap { width: 90px; height: 5px; - background: #262C38; + background: var(--bar-bg); border-radius: 3px; overflow: hidden; display: inline-block; diff --git a/frontend/src/views/config/ConfigCenter.vue b/frontend/src/views/config/ConfigCenter.vue index c28aa19..582bde4 100644 --- a/frontend/src/views/config/ConfigCenter.vue +++ b/frontend/src/views/config/ConfigCenter.vue @@ -133,7 +133,7 @@ const clusters = ref([ font-size: 11px; color: var(--accent); border: 1px solid var(--accent-dim); - background: #0F261D; + background: var(--accent-dim); padding: 3px 9px; border-radius: 20px; letter-spacing: 0.4px; @@ -312,21 +312,21 @@ tr.tr-hover:hover td { } .tag.zone-a { - color: #8EC8FF; - border-color: #1C3A5C; - background: #0E1C2C; + color: var(--tag-blue-text); + border-color: var(--tag-blue-border); + background: var(--tag-blue-bg); } .tag.zone-b { - color: #C9A6FF; - border-color: #3A2C5C; - background: #1A1430; + color: var(--tag-purple-text); + border-color: var(--tag-purple-border); + background: var(--tag-purple-bg); } .tag.zone-c { - color: #FFC97A; - border-color: #5C4A1C; - background: #241B0A; + color: var(--tag-amber-text); + border-color: var(--tag-amber-border); + background: var(--tag-amber-bg); } .status-text { diff --git a/frontend/src/views/dashboard/Index.vue b/frontend/src/views/dashboard/Index.vue index efa84f2..8e9c3b8 100644 --- a/frontend/src/views/dashboard/Index.vue +++ b/frontend/src/views/dashboard/Index.vue @@ -260,23 +260,23 @@ const refresh = () => { .node-cell { aspect-ratio: 1; border-radius: 3px; - background: #1E2532; + background: var(--node-empty-bg); border: 1px solid var(--line-soft); } .node-cell.a { - background: #13261F; - border-color: var(--accent-dim); + background: var(--node-a-bg); + border-color: var(--node-a-border); } .node-cell.b { - background: #1A1430; - border-color: #3A2C5C; + background: var(--node-b-bg); + border-color: var(--node-b-border); } .node-cell.c { - background: #241B0A; - border-color: #5C4A1C; + background: var(--node-c-bg); + border-color: var(--node-c-border); } .node-cell.empty { @@ -352,21 +352,21 @@ td.strong { } .tag.zone-a { - color: #8EC8FF; - border-color: #1C3A5C; - background: #0E1C2C; + color: var(--tag-blue-text); + border-color: var(--tag-blue-border); + background: var(--tag-blue-bg); } .tag.zone-b { - color: #C9A6FF; - border-color: #3A2C5C; - background: #1A1430; + color: var(--tag-purple-text); + border-color: var(--tag-purple-border); + background: var(--tag-purple-bg); } .tag.zone-c { - color: #FFC97A; - border-color: #5C4A1C; - background: #241B0A; + color: var(--tag-amber-text); + border-color: var(--tag-amber-border); + background: var(--tag-amber-bg); } .status-text { diff --git a/frontend/src/views/resource/Management.vue b/frontend/src/views/resource/Management.vue index 91af0bb..275d5fb 100644 --- a/frontend/src/views/resource/Management.vue +++ b/frontend/src/views/resource/Management.vue @@ -278,21 +278,21 @@ tr.tr-hover:hover td { } .tag.vm { - color: #8EC8FF; - border-color: #1C3A5C; - background: #0E1C2C; + color: var(--tag-blue-text); + border-color: var(--tag-blue-border); + background: var(--tag-blue-bg); } .tag.zone-a { - color: #8EC8FF; - border-color: #1C3A5C; - background: #0E1C2C; + color: var(--tag-blue-text); + border-color: var(--tag-blue-border); + background: var(--tag-blue-bg); } .tag.src-cmdb { - color: #7FFFC2; - border-color: var(--accent-dim); - background: #0F261D; + color: var(--tag-green-text); + border-color: var(--tag-green-border); + background: var(--tag-green-bg); } .status-text { @@ -340,11 +340,11 @@ tr.tr-hover:hover td { .pg-btn.active { background: var(--accent-dim); border-color: var(--accent-dim); - color: #CFFCE9; + color: var(--active-text); } .pg-btn:hover { - border-color: #3A4356; + border-color: var(--hover-border); color: var(--text-hi); } diff --git a/frontend/src/views/resource/StatusBoard.vue b/frontend/src/views/resource/StatusBoard.vue index 324b683..04c1be2 100644 --- a/frontend/src/views/resource/StatusBoard.vue +++ b/frontend/src/views/resource/StatusBoard.vue @@ -272,7 +272,7 @@ tr.tr-hover:hover td { .bar-wrap { width: 90px; height: 5px; - background: #262C38; + background: var(--bar-bg); border-radius: 3px; overflow: hidden; display: inline-block; diff --git a/frontend/src/views/service/Catalog.vue b/frontend/src/views/service/Catalog.vue index de32d0f..53d0b7b 100644 --- a/frontend/src/views/service/Catalog.vue +++ b/frontend/src/views/service/Catalog.vue @@ -30,11 +30,11 @@ import { ref } from 'vue' import { ElMessage } from 'element-plus' const services = ref([ - { name: 'MySQL', icon: 'My', bgColor: '#1C2E4A', iconColor: '#7FB8FF', description: '一主多从,自动注册进 open-cdm 数据源,支持 LDAP 账号统一审核 SQL 上线。', playbook: 'roles/mysql-deploy', version: 'v8.0.36' }, - { name: 'Redis', icon: 'Rd', bgColor: '#3A1C28', iconColor: '#FF8E9C', description: '支持 Standalone / Sentinel / Cluster,部署完成后自动注册进 CacheCloud。', playbook: 'roles/redis-deploy', version: 'v7.2' }, - { name: 'openresty', icon: 'Or', bgColor: '#1C3A2E', iconColor: '#7FFFC2', description: '容器化部署在 K8s 内,作为业务边缘网关,支持灰度路由配置。', playbook: 'roles/openresty-deploy', version: 'v1.25' }, - { name: 'dpvs', icon: 'Dp', bgColor: '#3A2E1C', iconColor: '#FFC97A', description: '四层负载均衡,直接管理宿主机网络命名空间,不纳入容器编排。', playbook: 'roles/dpvs-deploy', version: 'v1.9' }, - { name: 'PgSQL', icon: 'Pg', bgColor: '#2E1C3A', iconColor: '#C9A6FF', description: '流复制主从架构,规划中 · 第二期接入 open-cdm 统一审核体系。', playbook: 'roles/pgsql-deploy', version: '规划中' }, + { name: 'MySQL', icon: 'My', bgColor: 'var(--tag-blue-bg)', iconColor: 'var(--tag-blue-text)', description: '一主多从,自动注册进 open-cdm 数据源,支持 LDAP 账号统一审核 SQL 上线。', playbook: 'roles/mysql-deploy', version: 'v8.0.36' }, + { name: 'Redis', icon: 'Rd', bgColor: 'var(--logo-cc-bg)', iconColor: 'var(--err)', description: '支持 Standalone / Sentinel / Cluster,部署完成后自动注册进 CacheCloud。', playbook: 'roles/redis-deploy', version: 'v7.2' }, + { name: 'openresty', icon: 'Or', bgColor: 'var(--logo-dm-bg)', iconColor: 'var(--tag-green-text)', description: '容器化部署在 K8s 内,作为业务边缘网关,支持灰度路由配置。', playbook: 'roles/openresty-deploy', version: 'v1.25' }, + { name: 'dpvs', icon: 'Dp', bgColor: 'var(--logo-qp-bg)', iconColor: 'var(--tag-amber-text)', description: '四层负载均衡,直接管理宿主机网络命名空间,不纳入容器编排。', playbook: 'roles/dpvs-deploy', version: 'v1.9' }, + { name: 'PgSQL', icon: 'Pg', bgColor: 'var(--tag-purple-bg)', iconColor: 'var(--tag-purple-text)', description: '流复制主从架构,规划中 · 第二期接入 open-cdm 统一审核体系。', playbook: 'roles/pgsql-deploy', version: '规划中' }, ]) const handleDeploy = (service: any) => { @@ -78,7 +78,7 @@ const handleDeploy = (service: any) => { } .svc-card:hover { - border-color: #3A4356; + border-color: var(--hover-border); } .svc-top { diff --git a/frontend/src/views/service/Management.vue b/frontend/src/views/service/Management.vue index 32354e8..271e247 100644 --- a/frontend/src/views/service/Management.vue +++ b/frontend/src/views/service/Management.vue @@ -273,21 +273,21 @@ tr.tr-hover:hover td { } .tag.zone-a { - color: #8EC8FF; - border-color: #1C3A5C; - background: #0E1C2C; + color: var(--tag-blue-text); + border-color: var(--tag-blue-border); + background: var(--tag-blue-bg); } .tag.zone-b { - color: #C9A6FF; - border-color: #3A2C5C; - background: #1A1430; + color: var(--tag-purple-text); + border-color: var(--tag-purple-border); + background: var(--tag-purple-bg); } .tag.zone-c { - color: #FFC97A; - border-color: #5C4A1C; - background: #241B0A; + color: var(--tag-amber-text); + border-color: var(--tag-amber-border); + background: var(--tag-amber-bg); } .status-text { @@ -339,11 +339,11 @@ tr.tr-hover:hover td { .pg-btn.active { background: var(--accent-dim); border-color: var(--accent-dim); - color: #CFFCE9; + color: var(--active-text); } .pg-btn:hover { - border-color: #3A4356; + border-color: var(--hover-border); color: var(--text-hi); } diff --git a/frontend/src/views/task/TaskCenter.vue b/frontend/src/views/task/TaskCenter.vue index 53bf7e6..44b20d1 100644 --- a/frontend/src/views/task/TaskCenter.vue +++ b/frontend/src/views/task/TaskCenter.vue @@ -212,7 +212,7 @@ tr.tr-hover.active td { } .task-log-line.tag-ok { - color: #7FB8FF; + color: var(--tag-blue-text); } .blink { @@ -259,11 +259,11 @@ tr.tr-hover.active td { .pg-btn.active { background: var(--accent-dim); border-color: var(--accent-dim); - color: #CFFCE9; + color: var(--active-text); } .pg-btn:hover { - border-color: #3A4356; + border-color: var(--hover-border); color: var(--text-hi); } From 3144a50ef5bb4ad79b09c276111f51d14b25ae63 Mon Sep 17 00:00:00 2001 From: hezhaohui Date: Wed, 15 Jul 2026 15:11:55 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix(frontend):=20=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E9=87=8D=E6=9E=84=E5=89=8D=E7=AB=AF=E6=A0=B7=E5=BC=8F=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=EF=BC=8C=E6=B6=88=E9=99=A4=E9=87=8D=E5=A4=8D=E3=80=81?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=93=8D=E5=BA=94=E5=BC=8F=E3=80=81=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E7=A1=AC=E7=BC=96=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #61 ## 变更内容 ### CSS 变量扩展 - 新增 --radius-sm / --radius-lg / --radius-xl 圆角变量 - 新增 --accent-end 渐变终点色(浅色/深色模式) ### 公共样式提取到 global.css - 提取 15+ 组重复样式:.page-head / .panel / .stat-row / table / .tag / .status-text / .bar-wrap / .cols-2 / .pagination / .log-stream 等 - 所有 border-radius 硬编码值改用 CSS 变量 - 新增工具类:.text-xs / .text-dim / .cols-2-equal / .panel-body.padded / .search-input / .accent-pill ### 响应式设计 - @media (max-width: 1024px):stat-row 3 列,双栏布局单列化 - @media (max-width: 768px):page-head 纵向排列,stat-row 2 列, 表格横向滚动,卡片网格单列化 ### 内联 style 清理 - 非动态绑定的 style="color: ..." / style="font-size: ..." / style="flex: 1" / style="padding: ..." 改为 CSS 类 ### 硬编码颜色修复 - ConfigCenter.vue: #1C2A3A/#8EC8FF 改用 CSS 变量 - Login.vue: #1C8F69 改用 --accent-end 变量 ### 页面组件 scoped 样式精简 - 13 个页面组件删除已提取的重复样式,净减少 1070 行 --- frontend/src/styles/global.css | 483 ++++++++++++++++++++ frontend/src/styles/variables.css | 12 + frontend/src/views/audit/LoginAudit.vue | 20 +- frontend/src/views/audit/OpsAudit.vue | 20 +- frontend/src/views/auth/Login.vue | 12 +- frontend/src/views/cluster/ClusterList.vue | 157 +------ frontend/src/views/config/ConfigCenter.vue | 234 +--------- frontend/src/views/dashboard/Index.vue | 200 +------- frontend/src/views/monitor/Monitor.vue | 122 +---- frontend/src/views/resource/Management.vue | 227 +-------- frontend/src/views/resource/StatusBoard.vue | 189 +------- frontend/src/views/service/Catalog.vue | 27 +- frontend/src/views/service/Management.vue | 237 +--------- frontend/src/views/subsystem/Navigation.vue | 26 +- frontend/src/views/task/TaskCenter.vue | 184 +------- 15 files changed, 540 insertions(+), 1610 deletions(-) diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index e8586df..a5d0ae1 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -162,3 +162,486 @@ button { .card:hover { box-shadow: var(--shadow-md); } + +/* ========== 页面标题区 ========== */ +.page-head { + display: flex; + align-items: flex-end; + justify-content: space-between; + margin-bottom: 18px; +} + +.page-head h1 { + font-size: 19px; + margin: 0 0 4px; + font-weight: 700; + letter-spacing: 0.2px; +} + +.page-head p { + margin: 0; + color: var(--text-dim); + font-size: 12.5px; +} + +/* ========== 面板 ========== */ +.panel { + background: var(--bg-panel); + border: 1px solid var(--line); + border-radius: var(--radius-lg); + margin-bottom: 18px; +} + +.panel-head { + display: flex; + align-items: center; + justify-content: space-between; + padding: 13px 16px; + border-bottom: 1px solid var(--line-soft); +} + +.panel-head h3 { + margin: 0; + font-size: 13.5px; + font-weight: 600; +} + +.panel-head .meta { + font-size: 11.5px; + color: var(--text-dim); + font-family: var(--mono); + text-decoration: none; +} + +.panel-body { + padding: 4px 0; +} + +.panel-body.padded { + padding: 16px; +} + +/* ========== 统计卡片行 ========== */ +.stat-row { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 12px; + margin-bottom: 20px; +} + +.stat-card { + background: var(--bg-panel); + border: 1px solid var(--line); + border-radius: var(--radius-lg); + padding: 14px 16px; + position: relative; + overflow: hidden; +} + +.stat-card .label { + font-size: 11px; + color: var(--text-dim); + margin-bottom: 8px; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.stat-card .value { + font-family: var(--mono); + font-size: 24px; + font-weight: 600; +} + +.stat-card .value.accent-pill { + color: var(--accent); + font-size: 16px; +} + +.stat-card .value.warn { + color: var(--warn); +} + +.stat-card .value.err { + color: var(--err); +} + +.stat-card .value.accent { + color: var(--accent); +} + +.stat-card .delta { + font-size: 11px; + color: var(--text-dim); + margin-top: 4px; +} + +.stat-card .delta.up { + color: var(--accent); +} + +.stat-card .delta.warn { + color: var(--warn); +} + +.stat-card .delta.err { + color: var(--err); +} + +/* ========== 双栏布局 ========== */ +.cols-2 { + display: grid; + grid-template-columns: 1.4fr 1fr; + gap: 18px; +} + +.cols-2-equal { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 18px; +} + +/* ========== 表格 ========== */ +table { + width: 100%; + border-collapse: collapse; + font-size: 12.5px; +} + +th { + text-align: left; + color: var(--text-dim); + font-weight: 500; + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.4px; + padding: 9px 16px; + border-bottom: 1px solid var(--line-soft); +} + +td { + padding: 11px 16px; + border-bottom: 1px solid var(--line-soft); + color: var(--text-mid); +} + +tr:last-child td { + border-bottom: none; +} + +tr.tr-hover:hover td { + background: var(--bg-panel-2); +} + +tr.tr-hover.active td { + background: var(--bg-panel-2); +} + +.strong { + color: var(--text-hi); + font-weight: 500; +} + +.text-xs { + font-size: 11px; +} + +.text-dim { + color: var(--text-dim); +} + +.search-input { + flex: 1; +} + +/* ========== 标签 ========== */ +.tag { + display: inline-flex; + align-items: center; + gap: 5px; + font-family: var(--mono); + font-size: 10.5px; + padding: 2px 8px; + border-radius: var(--radius-sm); + border: 1px solid var(--line); + color: var(--text-mid); +} + +.tag.zone-a { + color: var(--tag-blue-text); + border-color: var(--tag-blue-border); + background: var(--tag-blue-bg); +} + +.tag.zone-b { + color: var(--tag-purple-text); + border-color: var(--tag-purple-border); + background: var(--tag-purple-bg); +} + +.tag.zone-c { + color: var(--tag-amber-text); + border-color: var(--tag-amber-border); + background: var(--tag-amber-bg); +} + +/* ========== 状态文本 ========== */ +.status-text { + font-size: 12px; + display: flex; + align-items: center; +} + +.status-text.ok { + color: var(--accent); +} + +.status-text.warn { + color: var(--warn); +} + +.status-text.err { + color: var(--err); +} + +.status-text.idle { + color: var(--text-dim); +} + +/* ========== 进度条 ========== */ +.bar-wrap { + width: 90px; + height: 5px; + background: var(--bar-bg); + border-radius: 3px; + overflow: hidden; + display: inline-block; + vertical-align: middle; + margin-right: 8px; +} + +.bar-fill { + height: 100%; + border-radius: 3px; + background: var(--accent); +} + +.bar-fill.warn { + background: var(--warn); +} + +.bar-fill.err { + background: var(--err); +} + +/* ========== 分页 ========== */ +.pagination { + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 16px; + border-top: 1px solid var(--line-soft); + font-size: 11.5px; + color: var(--text-dim); +} + +.pg-btns { + display: flex; + gap: 4px; + align-items: center; +} + +.pg-btn { + min-width: 26px; + height: 26px; + padding: 0 6px; + display: inline-flex; + align-items: center; + justify-content: center; + border: 1px solid var(--line); + border-radius: var(--radius-sm); + color: var(--text-mid); + font-family: var(--mono); + font-size: 11px; + background: var(--bg-panel-2); + cursor: pointer; +} + +.pg-btn.active { + background: var(--accent-dim); + border-color: var(--accent-dim); + color: var(--active-text); +} + +.pg-btn:hover { + border-color: var(--hover-border); + color: var(--text-hi); +} + +.pg-btn.disabled { + opacity: 0.35; + cursor: not-allowed; +} + +.pg-sep { + color: var(--text-dim); + padding: 0 2px; +} + +/* ========== 日志流 ========== */ +.log-stream { + padding: 14px 16px; +} + +.task-log-line { + font-family: var(--mono); + font-size: 11.5px; + padding: 2px 0; + color: var(--text-mid); +} + +.task-log-line .t { + color: var(--text-dim); + margin-right: 10px; +} + +.task-log-line.ok { + color: var(--accent); +} + +.task-log-line.tag-ok { + color: var(--tag-blue-text); +} + +/* ========== 工具栏 ========== */ +.las-toolbar { + display: flex; + gap: 10px; + margin-bottom: 14px; + align-items: center; +} + +/* ========== 子系统/扩展卡片网格 ========== */ +.ext-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 14px; +} + +.svc-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 14px; +} + +/* ========== Apollo / 外部服务卡片 ========== */ +.ext-card { + background: var(--bg-panel); + border: 1px solid var(--line); + border-radius: var(--radius-lg); + padding: 18px; + max-width: 560px; +} + +.ext-top { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 10px; +} + +.ext-logo { + width: 38px; + height: 38px; + border-radius: var(--radius-lg); + display: flex; + align-items: center; + justify-content: center; + font-family: var(--mono); + font-weight: 700; + font-size: 13px; +} + +.ext-logo.ap-logo { + background: var(--logo-ap-bg); + color: var(--tag-blue-text); +} + +.ext-sub { + font-size: 11px; + color: var(--text-dim); + font-family: var(--mono); +} + +/* ========== 环境状态标签 ========== */ +.env-pill { + font-family: var(--mono); + font-size: 11px; + color: var(--accent); + border: 1px solid var(--accent-dim); + background: var(--accent-dim); + padding: 3px 9px; + border-radius: 20px; + letter-spacing: 0.4px; +} + +/* ========== SSO 行 ========== */ +.sso-row { + display: flex; + align-items: center; + gap: 6px; + font-size: 11px; + color: var(--text-dim); +} + +.sso-dot { + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--accent); +} + +/* ========== 响应式断点 ========== */ + +/* 平板 */ +@media (max-width: 1024px) { + .stat-row { + grid-template-columns: repeat(3, 1fr); + } + + .cols-2, + .cols-2-equal { + grid-template-columns: 1fr; + } +} + +/* 移动端 */ +@media (max-width: 768px) { + .page-head { + flex-direction: column; + align-items: flex-start; + gap: 12px; + } + + .stat-row { + grid-template-columns: repeat(2, 1fr); + } + + .cols-2, + .cols-2-equal { + grid-template-columns: 1fr; + } + + .las-toolbar { + flex-wrap: wrap; + } + + .ext-grid, + .svc-grid { + grid-template-columns: 1fr; + } + + .panel-body table { + display: block; + overflow-x: auto; + } +} diff --git a/frontend/src/styles/variables.css b/frontend/src/styles/variables.css index fe4e32e..4eb814e 100644 --- a/frontend/src/styles/variables.css +++ b/frontend/src/styles/variables.css @@ -25,6 +25,9 @@ /* 圆角 */ --radius: 6px; + --radius-sm: 4px; + --radius-lg: 8px; + --radius-xl: 12px; /* 字体 */ --mono: 'IBM Plex Mono', monospace; @@ -35,6 +38,9 @@ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); + /* 渐变终点色 */ + --accent-end: #1C8F69; + /* 标签/徽章颜色 - 蓝色系 */ --tag-blue-text: #165DFF; --tag-blue-bg: #E8F3FF; @@ -116,6 +122,9 @@ /* 圆角 */ --radius: 6px; + --radius-sm: 4px; + --radius-lg: 8px; + --radius-xl: 12px; /* 字体 */ --mono: 'IBM Plex Mono', monospace; @@ -126,6 +135,9 @@ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3); --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -2px rgba(0, 0, 0, 0.3); + /* 渐变终点色 */ + --accent-end: #1F6B52; + /* 标签/徽章颜色 - 蓝色系 */ --tag-blue-text: #8EC8FF; --tag-blue-bg: #0E1C2C; diff --git a/frontend/src/views/audit/LoginAudit.vue b/frontend/src/views/audit/LoginAudit.vue index 46465bf..6065184 100644 --- a/frontend/src/views/audit/LoginAudit.vue +++ b/frontend/src/views/audit/LoginAudit.vue @@ -52,23 +52,5 @@ onMounted(() => { diff --git a/frontend/src/views/audit/OpsAudit.vue b/frontend/src/views/audit/OpsAudit.vue index e79875b..cf0adf7 100644 --- a/frontend/src/views/audit/OpsAudit.vue +++ b/frontend/src/views/audit/OpsAudit.vue @@ -53,23 +53,5 @@ onMounted(() => { diff --git a/frontend/src/views/auth/Login.vue b/frontend/src/views/auth/Login.vue index 610aaa0..930a5be 100644 --- a/frontend/src/views/auth/Login.vue +++ b/frontend/src/views/auth/Login.vue @@ -40,7 +40,7 @@ size="large" :loading="loading" @click="handleLogin" - style="width: 100%" + class="login-btn" > 登录 @@ -105,10 +105,14 @@ const handleLogin = async () => { width: 400px; background: var(--bg-panel); border: 1px solid var(--line); - border-radius: 12px; + border-radius: var(--radius-xl); padding: 40px; } +.login-btn { + width: 100%; +} + .login-header { text-align: center; margin-bottom: 32px; @@ -127,8 +131,8 @@ const handleLogin = async () => { .login-header .brand .mark { width: 36px; height: 36px; - border-radius: 8px; - background: linear-gradient(135deg, var(--accent), #1C8F69); + border-radius: var(--radius-lg); + background: linear-gradient(135deg, var(--accent), var(--accent-end)); display: flex; align-items: center; justify-content: center; diff --git a/frontend/src/views/cluster/ClusterList.vue b/frontend/src/views/cluster/ClusterList.vue index c317218..0ddd7fe 100644 --- a/frontend/src/views/cluster/ClusterList.vue +++ b/frontend/src/views/cluster/ClusterList.vue @@ -64,7 +64,7 @@ {{ node.name }} {{ node.ip }} {{ node.label }} - {{ node.taint }} + {{ node.taint }} {{ node.spec }} {{ node.cpu }}% ● {{ node.status }} @@ -94,162 +94,9 @@ const nodes = ref([ diff --git a/frontend/src/views/config/ConfigCenter.vue b/frontend/src/views/config/ConfigCenter.vue index 582bde4..1492e83 100644 --- a/frontend/src/views/config/ConfigCenter.vue +++ b/frontend/src/views/config/ConfigCenter.vue @@ -31,7 +31,7 @@
同步状态
-
● 正常
+
● 正常
最近发布 09:12:30
@@ -41,10 +41,10 @@

统一入口

Apollo Portal · LDAP 单点登录 -
+
- +

Apollo Portal

apollo.xinfra.internal
@@ -81,7 +81,7 @@ {{ cluster.name }} cluster={{ cluster.cluster }} - {{ cluster.address }} + {{ cluster.address }} {{ cluster.type }} {{ cluster.biz }} {{ cluster.items }} @@ -109,241 +109,17 @@ const clusters = ref([ diff --git a/frontend/src/views/dashboard/Index.vue b/frontend/src/views/dashboard/Index.vue index 8e9c3b8..fb1764d 100644 --- a/frontend/src/views/dashboard/Index.vue +++ b/frontend/src/views/dashboard/Index.vue @@ -31,7 +31,7 @@
进行中任务
-
2
+
2
1 个待关注
@@ -46,7 +46,7 @@
IDC-华北机房 - 46节点 + 46节点
@@ -55,7 +55,7 @@
IDC-华东机房 - 52节点 + 52节点
@@ -64,7 +64,7 @@
阿里云-华南 - 30节点 + 30节点
@@ -127,107 +127,7 @@ const refresh = () => { diff --git a/frontend/src/views/monitor/Monitor.vue b/frontend/src/views/monitor/Monitor.vue index d63a4f8..5fe24ab 100644 --- a/frontend/src/views/monitor/Monitor.vue +++ b/frontend/src/views/monitor/Monitor.vue @@ -7,7 +7,7 @@
-
+

VictoriaMetrics · 指标概览

@@ -94,123 +94,5 @@ const logs = ref([ diff --git a/frontend/src/views/resource/Management.vue b/frontend/src/views/resource/Management.vue index 275d5fb..9d9ad77 100644 --- a/frontend/src/views/resource/Management.vue +++ b/frontend/src/views/resource/Management.vue @@ -31,7 +31,7 @@
最近一次同步
-
● 正常
+
● 正常
07:39:10 · 新增 3 条
@@ -58,7 +58,7 @@ - +
@@ -84,11 +84,11 @@ {{ item.hostname }} - {{ item.asset_number }} + {{ item.asset_number }} {{ item.type }} {{ item.location }} {{ item.ip }} - {{ item.spec }} + {{ item.spec }} {{ item.business_line }} {{ item.source }} ● {{ item.status }} @@ -127,155 +127,7 @@ const resources = ref([ diff --git a/frontend/src/views/resource/StatusBoard.vue b/frontend/src/views/resource/StatusBoard.vue index 04c1be2..f8e1d17 100644 --- a/frontend/src/views/resource/StatusBoard.vue +++ b/frontend/src/views/resource/StatusBoard.vue @@ -26,17 +26,17 @@
P0 / Disaster 告警
-
1
-
来自 VictoriaMetrics
+
1
+
来自 VictoriaMetrics
P1 / High 告警
-
5
+
5
来自 Zabbix · 4 条 / VM · 1 条
-
+

物理机状态 · 按机房

@@ -131,184 +131,5 @@ const refresh = () => { diff --git a/frontend/src/views/service/Catalog.vue b/frontend/src/views/service/Catalog.vue index 53d0b7b..1be61fb 100644 --- a/frontend/src/views/service/Catalog.vue +++ b/frontend/src/views/service/Catalog.vue @@ -43,35 +43,12 @@ const handleDeploy = (service: any) => { diff --git a/frontend/src/views/subsystem/Navigation.vue b/frontend/src/views/subsystem/Navigation.vue index 44a50f7..7c2a6ba 100644 --- a/frontend/src/views/subsystem/Navigation.vue +++ b/frontend/src/views/subsystem/Navigation.vue @@ -34,29 +34,5 @@ onMounted(async () => { diff --git a/frontend/src/views/task/TaskCenter.vue b/frontend/src/views/task/TaskCenter.vue index 44b20d1..dcd1882 100644 --- a/frontend/src/views/task/TaskCenter.vue +++ b/frontend/src/views/task/TaskCenter.vue @@ -7,7 +7,7 @@
-
+

任务列表

@@ -18,7 +18,7 @@ ● {{ task.status }} {{ task.name }} - {{ task.playbook }} + {{ task.playbook }} @@ -83,138 +83,13 @@ const logs = ref([ From f3ca4a4217e7b70cbc8bb74e27b8c5b913198857 Mon Sep 17 00:00:00 2001 From: hezhaohui Date: Wed, 15 Jul 2026 15:25:11 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix(frontend):=20=E6=9B=BF=E6=8D=A2Logo?= =?UTF-8?q?=E3=80=81=E5=A2=9E=E5=A4=A7=E9=A1=B6=E6=A0=8F=E4=BE=A7=E6=A0=8F?= =?UTF-8?q?=E5=B0=BA=E5=AF=B8=E5=8F=8A=E5=85=A8=E5=B1=80=E5=AD=97=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 替换顶栏Logo为七牛logo图片(logo-qiniu.png) - 顶栏高度 56→70px,侧栏宽度 226→282px - 顶栏各元素字号增大约25%,头像26→32px,搜索框240→280px - 侧栏导航项字号13→16px,分组标题10.5→13px,徽标10→12px - 全局基础字号 14→16px --- frontend/public/logo-qiniu.png | Bin 0 -> 4830 bytes frontend/src/components/Layout/AppHeader.vue | 41 ++++++++---------- frontend/src/components/Layout/AppSidebar.vue | 12 ++--- frontend/src/layouts/DefaultLayout.vue | 4 +- frontend/src/styles/global.css | 2 +- 5 files changed, 26 insertions(+), 33 deletions(-) create mode 100644 frontend/public/logo-qiniu.png diff --git a/frontend/public/logo-qiniu.png b/frontend/public/logo-qiniu.png new file mode 100644 index 0000000000000000000000000000000000000000..f871591a465ea9501c7116e6ed691d0a8487f49c GIT binary patch literal 4830 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
-
xi
+ logo xinfra 统一基础设施平台
● 生产环境 @@ -61,27 +61,20 @@ const { theme, toggleTheme } = useTheme() gap: 9px; font-weight: 600; letter-spacing: 0.3px; - font-size: 15px; + font-size: 18px; } -.brand .mark { - width: 22px; - height: 22px; - border-radius: 5px; - background: linear-gradient(135deg, var(--accent), #1C8F69); - display: flex; - align-items: center; - justify-content: center; - font-family: var(--mono); - font-size: 11px; - font-weight: 600; - color: var(--bg-deep); +.brand .mark-img { + width: 36px; + height: 36px; + border-radius: 6px; + object-fit: contain; } .brand .sub { color: var(--text-dim); font-weight: 400; - font-size: 12px; + font-size: 15px; margin-left: 4px; } @@ -91,7 +84,7 @@ const { theme, toggleTheme } = useTheme() .env-pill { font-family: var(--mono); - font-size: 11px; + font-size: 14px; color: var(--accent); border: 1px solid var(--accent-dim); background: var(--accent-dim); @@ -109,14 +102,14 @@ const { theme, toggleTheme } = useTheme() border-radius: 6px; padding: 6px 10px; color: var(--text-dim); - font-size: 12.5px; - width: 240px; + font-size: 15px; + width: 280px; } .search-box kbd { margin-left: auto; font-family: var(--mono); - font-size: 10px; + font-size: 12px; background: var(--bg-panel); padding: 1px 5px; border-radius: 3px; @@ -128,27 +121,27 @@ const { theme, toggleTheme } = useTheme() display: flex; align-items: center; gap: 8px; - font-size: 12.5px; + font-size: 15px; color: var(--text-mid); } .identity .avatar { - width: 26px; - height: 26px; + width: 32px; + height: 32px; border-radius: 50%; background: var(--bg-panel-2); display: flex; align-items: center; justify-content: center; font-family: var(--mono); - font-size: 11px; + font-size: 14px; color: var(--text-hi); border: 1px solid var(--line); } .identity .ldap-tag { font-family: var(--mono); - font-size: 10px; + font-size: 12px; color: var(--text-dim); } diff --git a/frontend/src/components/Layout/AppSidebar.vue b/frontend/src/components/Layout/AppSidebar.vue index 09f4fea..117f640 100644 --- a/frontend/src/components/Layout/AppSidebar.vue +++ b/frontend/src/components/Layout/AppSidebar.vue @@ -81,7 +81,7 @@ } .nav-label { - font-size: 10.5px; + font-size: 13px; color: var(--text-dim); text-transform: uppercase; letter-spacing: 1px; @@ -94,10 +94,10 @@ display: flex; align-items: center; gap: 10px; - padding: 8px 10px; + padding: 10px 10px; border-radius: 6px; color: var(--text-mid); - font-size: 13px; + font-size: 16px; font-weight: 500; cursor: pointer; margin-bottom: 2px; @@ -108,7 +108,7 @@ .nav-item .ic { width: 16px; text-align: center; - font-size: 13px; + font-size: 16px; opacity: 0.85; } @@ -126,7 +126,7 @@ .nav-item .badge { margin-left: auto; font-family: var(--mono); - font-size: 10px; + font-size: 12px; background: var(--bg-panel-2); color: var(--text-dim); padding: 1px 6px; @@ -144,7 +144,7 @@ margin-top: auto; padding: 10px; border-top: 1px solid var(--line-soft); - font-size: 11px; + font-size: 14px; color: var(--text-dim); line-height: 1.6; } diff --git a/frontend/src/layouts/DefaultLayout.vue b/frontend/src/layouts/DefaultLayout.vue index aba2fbf..ee88ed7 100644 --- a/frontend/src/layouts/DefaultLayout.vue +++ b/frontend/src/layouts/DefaultLayout.vue @@ -15,8 +15,8 @@ import AppMain from '@/components/Layout/AppMain.vue' diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index a5d0ae1..32dc6ed 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -10,7 +10,7 @@ html, body { background: var(--bg-deep); color: var(--text-hi); font-family: var(--sans); - font-size: 14px; + font-size: 16px; transition: background-color 0.3s ease, color 0.3s ease; } From 4538452c438c88e730d8e69d817fa474546b1918 Mon Sep 17 00:00:00 2001 From: hezhaohui Date: Wed, 15 Jul 2026 17:36:44 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix(frontend):=20=E7=A7=BB=E9=99=A4=20useTh?= =?UTF-8?q?eme=20=E4=B8=AD=E6=9C=AA=E4=BD=BF=E7=94=A8=E7=9A=84=20watch=20?= =?UTF-8?q?=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 useTheme.ts 中未使用的 'watch' 导入 - 修复 TypeScript 编译错误 --- frontend/src/composables/useTheme.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/composables/useTheme.ts b/frontend/src/composables/useTheme.ts index b74e5a9..6d0ce46 100644 --- a/frontend/src/composables/useTheme.ts +++ b/frontend/src/composables/useTheme.ts @@ -1,4 +1,4 @@ -import { ref, watch, onMounted } from 'vue' +import { ref, onMounted } from 'vue' export type Theme = 'light' | 'dark'