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); }