diff --git a/docs/superpowers/plans/2026-07-25-migu-outpost-ui-lock.md b/docs/superpowers/plans/2026-07-25-migu-outpost-ui-lock.md new file mode 100644 index 0000000..7fd69a9 --- /dev/null +++ b/docs/superpowers/plans/2026-07-25-migu-outpost-ui-lock.md @@ -0,0 +1,23 @@ +# 迷毂 Outpost UI 实现计划(P0–P1) + +> **面向 AI 代理的工作者:** 按任务顺序实现;规格见 `docs/superpowers/specs/2026-07-25-migu-outpost-ui-lock-design.md`。 + +## 文件 + +| 文件 | 职责 | +|---|---| +| `src/styles/themes.ts` | PRIMARY 三色 + LEGACY;默认 `outpost-light`;`data-shell` | +| `src/styles/theme.css` | 浅色壳选择器改 `data-shell="outpost"`;默认 token 贴近浅色 | +| `src/stores/ui.ts` | `availableThemes` / `legacyThemes`;未知 id 迁移 | +| `src/components/ThemeSwitcher.vue` | 仅精选 3 | +| `src/layouts/AppShell.vue` | 高级 → 兼容主题 | +| `src/views/LoginView.vue` | 弱化霓虹(P1) | +| 若干 Vue 内 `fame-lavender` 选择器 | 改为 `data-shell="outpost"` | + +## 任务 + +1. 重写 `themes.ts`(精选 + legacy + applyThemeVars 写 `data-shell`) +2. `theme.css` / 组件选择器:`fame-lavender` → `data-shell="outpost"` +3. `ui` store + ThemeSwitcher + AppShell 高级入口 +4. Login 弱化星空主导(能快则做) +5. `pnpm`/`npm` typecheck 或 build 验证 diff --git a/docs/superpowers/specs/2026-07-25-migu-outpost-ui-lock-design.md b/docs/superpowers/specs/2026-07-25-migu-outpost-ui-lock-design.md new file mode 100644 index 0000000..671ed75 --- /dev/null +++ b/docs/superpowers/specs/2026-07-25-migu-outpost-ui-lock-design.md @@ -0,0 +1,273 @@ +# 迷毂平台 UI · 锁定 Outpost 浅色设计规格 + +> 状态:待用户审查(主题策略已按反馈修订) +> 日期:2026-07-25 +> 参考站:[Outpost · Fairyland Technology](https://fairylandtech.amerc.ai) +> 决策:方案 1 壳层气质(Outpost)+ **主路径精选 3 套配色(浅色 / 紫色 / 蓝色)**;旧深色霓虹主题**保留并藏入高级** +> 范围前端:`Migu2.0/frontends/apps/simple-platform-vue` +> 不改:SimpleLite ImGui / CycleGUI 桌面壳、后端 API 契约 + +--- + +## 1. 目标与非目标 + +### 1.1 目标 + +- 迷毂 Web(登录 → AppShell → 业务页 → 地图编辑器 chrome)在视觉与壳层气质上对齐 Outpost。 +- **壳层统一为 Outpost 结构**:浅主区 + 深色纹理侧栏 + 纸白卡片 + 柔阴影;无默认霓虹 orb。 +- **主路径提供 3 套精选配色**(可一键切换):浅色(默认)、紫色、蓝色——同结构、不同主色/侧栏色相。 +- 旧深色霓虹主题(星云紫等)**代码保留**,放入「高级 / 兼容主题」,不进主切换列表。 +- 保留调度业务信息架构;**不**把 Outpost 会话列表硬套进调度导航。 +- 状态色(绿/琥珀/红/蓝/灰)与品牌色解耦,语义不变。 + +### 1.2 非目标 + +- 不重写业务逻辑、路由权限、Projection/SSE 协议。 +- 不第一阶段替换 Element Plus(以 CSS 变量 + 皮肤覆盖为主)。 +- 不强制 3D 画布(webVRender)改浅色底。 +- 不把 Outpost 的 Agent 对话 IA 迁移为迷毂主导航。 +- 主路径不堆砌过多主题(精选 3 + 高级兼容即可)。 + +--- + +## 2. 产品决策(已确认) + +| 项 | 决策 | +|---|---| +| 壳层气质 | Outpost:浅主区 + 深侧栏 + 纸白卡 + 柔阴影 | +| 主路径配色 | **3 套精选**:浅色(默认)/ 紫色 / 蓝色 | +| 旧深色主题 | **保留**,藏入用户菜单「高级 → 兼容主题」 | +| ThemeSwitcher | **保留在顶栏**,只列出精选 3 套;兼容主题在高级入口 | +| 登录页 | 跟当前精选主题(默认浅色 Outpost);去掉星空霓虹主导 | +| 地图编辑器 | Chrome 跟精选浅色壳;**3D 画布保持深色** | +| AI 助手抽屉 | 视觉跟 Outpost 对话区,不改后端权限 | + +--- + +## 3. 参考站提炼(Outpost) + +### 3.1 信息架构(借壳不借业务) + +``` +┌────────────┬──────────────────────────────────────┐ +│ Sidebar │ Top context (optional, light) │ +│ ~256px ├──────────────────────────────────────┤ +│ dark plum │ Main workspace │ +│ textured │ paper cards / lists / forms │ +│ brand+nav │ │ +└────────────┴──────────────────────────────────────┘ +``` + +迷毂映射: + +| Outpost | 迷毂 | +|---|---| +| Sidebar brand + list | `AppShell` 侧栏 logo + `el-menu` | +| Workspace | `el-main` + 各业务 View | +| Artifact / card | KPI 卡、列表卡、属性面板、抽屉 | +| Conversation chrome | AI 助手抽屉(仅视觉) | + +### 3.2 设计 Token(锁定值) + +来源:Outpost 线上 CSS(`color-scheme: light`)。 + +| Token | 值 | 用途 | +|---|---|---| +| `--op-page` | `#f6f3fb` | 应用主区底 | +| `--op-paper` | `#fffefd` | 卡片/面板底 | +| `--op-paper-soft` | `#fbf9fd` | 次级表面 | +| `--op-ink` | `#28213a` | 主文字 | +| `--op-muted` | `#756d85` | 次级文字 | +| `--op-faint` | `#9a93a7` | 弱化/占位 | +| `--op-line` | `#e8e2ef` | 分割线 | +| `--op-line-strong` | `#ddd4e8` | 强调边框 | +| `--op-violet` | `#7543e8` | 品牌主色 | +| `--op-violet-strong` | `#5d2ecb` | 主色按下/深 | +| `--op-violet-soft` | `#eee8ff` | 主色浅底 | +| `--op-mint` / `--op-amber` / `--op-danger` / `--op-blue` | 见参考站 | 仅作辅助;**业务状态仍用既有 `--mg-status-*`** | +| `--op-shadow` | `0 12px 35px rgba(54,35,78,.08)` | 默认浮起 | +| `--op-shadow-strong` | `0 22px 65px rgba(46,24,72,.18)` | 弹层/强调卡 | +| `--op-radius` | `16px` | 默认圆角 | +| Sidebar | `linear-gradient(160deg,#3f2454,#2c193c 45%,#241530)` + 细纹理 | 侧栏底 | +| Font | Inter + 系统无衬线;数据位保留 JetBrains Mono | 与现 `--mg-font-*` 对齐 | + +### 3.3 明确禁止(相对当前「星云紫」) + +- 主路径禁用:大面积霓虹 glow、多层 orb 背景、深色玻璃卡片作默认表面。 +- 主路径禁用:把品牌紫当 success/warning。 +- 避免再引入第三套互不兼容的色板命名;Outpost token **映射进**既有 `--mg-*`,业务组件继续只读 `--mg-*`。 + +--- + +## 4. 精选三套主题 + Token 映射 + +三套均遵守同一 Outpost 壳层规则(浅主区 / 纸白卡 / 柔阴影 / orb=0 / radius≈16),仅 **主色 + 侧栏色相 + 主区底轻微染色** 不同。 + +### 4.1 主路径精选(`PRIMARY_THEMES`) + +| id | 显示名 | 定位 | 主色 | 侧栏 | 主区底 | +|---|---|---|---|---|---| +| `outpost-light` | **浅色**(默认) | 最贴近参考站 | `#7543e8` | `#3f2454 → #241530`(plum) | `#f6f3fb` | +| `outpost-purple` | **紫色** | 同结构、更饱和紫品牌 | `#7c3aed` | `#2d1b69 → #1a1040` | `#f3eefc`(略偏紫) | +| `outpost-blue` | **蓝色** | 同结构、蓝科技感 | `#3c78d2` | `#0f2744 → #0a1a30` | `#f3f6fb`(略偏蓝) | + +共用表面: + +| `--mg-*` | 值 | +|---|---| +| `--mg-bg-card-rgb` | paper `255,254,253` | +| `--mg-text` 系 | ink `#28213a` / muted `#756d85`(浅底深字) | +| `--mg-glass-*` | 白卡片 + 细边 + 柔阴影(无强 blur glow) | +| `--mg-radius*` | 基准 16px | +| `--mg-orb-*-opacity` | **0** | +| 状态色 | 继续 `--mg-status-*`,不随主题主色改语义 | + +### 4.2 高级兼容主题(`LEGACY_THEMES`,保留) + +现有深色霓虹预设移入此列表(至少含): + +- `industrial-purple` 星云紫 +- `deep-azure` 深邃蓝 +- `emerald-forge` / `crimson-iron` / `graphite-steel` / `amber-forge`(若仍在代码中) +- 旧 `fame-lavender`:合并进 `outpost-purple` 或标 deprecated 后从主列表移除 + +入口:用户头像菜单 → **高级 → 兼容主题**(折叠)。主顶栏 `ThemeSwitcher` **只显示 3 个精选**。 + +### 4.3 默认与迁移 + +- `DEFAULT_THEME_ID = 'outpost-light'` +- `:root` 默认 CSS 与 `outpost-light` 一致,避免闪屏 +- localStorage 若为未知 / 已 deprecated id → 迁移到 `outpost-light` +- 若为 `LEGACY_THEMES` 中的 id → **尊重用户选择**(不强制踢回浅色) +- 登录页品牌区跟当前主题侧栏色;`--lg-*` 随精选主题切换或登录页固定跟 `outpost-light`(实现时二选一,推荐:**登录固定 outpost-light,进壳后再跟用户主题**) + +--- + +## 5. 壳层与页面改造要点 + +### 5.1 AppShell + +- 侧栏:纹理渐变(随主题色相)、品牌区分隔线、菜单选中用 soft 底或左侧高光条。 +- 主区装饰 orb:`opacity=0`。 +- 顶栏:浅底、细边、弱阴影;breadcrumb + **精选 ThemeSwitcher(3 项)** + 用户区。 +- 用户菜单增加「高级 → 兼容主题」子菜单(列出 `LEGACY_THEMES`)。 +- 底栏:弱化字色或并入顶栏次级信息(可选后续)。 +- `aside-footer`:版本号;可选极简当前主题名。 + +### 5.2 登录 / 配置向导 + +- 布局可保留左右分栏,但: + - 背景:浅底 + 可选极轻纹理,不用星空粒子主导。 + - 左:深色品牌板(默认跟 `outpost-light` 侧栏)。 + - 右:paper 表单卡 + 主色按钮。 +- 配置向导与登录同肤。 + +### 5.3 Element Plus 皮肤 + +统一覆盖(全局): + +- Button primary / default +- Card / Dialog / Drawer / MessageBox +- Table / Pagination +- Menu(侧栏已透明底,补选中态) +- Input / Select / Tabs / Tag + +原则:纸白表面、ink 文字、violet 主按钮、radius≈14–16、阴影用 `--op-shadow`。 + +### 5.4 业务页(渐进,同一皮肤) + +优先级: + +1. Dashboard / 地图监控 / 调度工作台 +2. 任务 / 告警 / 车辆中心 +3. OTA / 配置中心 / 服务状态 +4. AI 助手抽屉 + +统一模式:`page-header` + paper 卡片栅格 + 紫 CTA;清理页面内 `industrial-purple` 专用覆盖或改为仅在「兼容主题」下生效。 + +### 5.5 地图编辑器 + +| 层 | 皮肤 | +|---|---| +| EditTopBar / ToolRail / PropertyPanel / StatusBar / AI 侧栏 | Outpost 浅色 | +| Workspace3D / webVRender 画布 | **保持深色视口** | +| 与壳层交界 | 1px `--op-line`,避免深浅硬切刺眼 | + +### 5.6 主题列表处理 + +| 分组 | 主题 | 处理 | +|---|---|---| +| 精选 | `outpost-light` / `outpost-purple` / `outpost-blue` | 新建或由现有浅色主题改版;顶栏可切换 | +| 合并 | `fame-lavender` | 并入 `outpost-purple` 或启动时 remap | +| 高级兼容 | `industrial-purple`、`deep-azure`、绿/赤/钢/琥珀等 | 保留完整 vars,仅高级菜单可选 | +| 持久化 | 精选或 legacy id | 精选正常读写;未知 id → `outpost-light`;legacy id **不强制迁移** | + +--- + +## 6. 文件影响面(实现时) + +| 文件/目录 | 职责 | +|---|---| +| `src/styles/theme.css` | 默认 token、Element 覆盖、禁 orb | +| `src/styles/themes.ts` | `PRIMARY_THEMES`(3)+ `LEGACY_THEMES`;默认 `outpost-light` | +| `src/stores/ui.ts`(或等价) | 默认主题、未知 id 迁移、legacy 可选 | +| `src/components/ThemeSwitcher.vue` | 只渲染精选 3;样式 Outpost 化 | +| `src/layouts/AppShell.vue` | 侧栏/顶栏;用户菜单挂「兼容主题」 | +| `src/views/LoginView.vue` | 登录换肤 | +| `design-system/MASTER.md` | 产品风格改为 Outpost 浅色工作台 | +| `design-system/outpost.md` | Token 与组件规范(新建) | +| 各 View 内 `:root[data-theme="industrial-purple"]` 块 | 降级为 legacy 或删除 | +| 地图编辑器 chrome 组件 | 浅色适配 | + +--- + +## 7. 分阶段交付 + +| Phase | 内容 | 验收 | +|---|---|---| +| **P0** | 三套精选 token + 默认 `outpost-light` + legacy 分组 + 文档 | 冷启动浅色 Outpost;可切紫/蓝 | +| **P1** | AppShell + 登录 + Element 皮肤 + ThemeSwitcher(3) + 高级兼容入口 | 壳层/登录 Outpost 化;高级仍能开星云紫等 | +| **P2** | Dashboard / 监控 / 调度 / 列表页 | 主业务无霓虹玻璃默认态 | +| **P3** | 地图编辑器 chrome + AI 抽屉 | 外围浅、画布深;助手区纸白气泡 | +| **P4** | 清理 legacy 覆盖、MASTER 更新、回归清单 | 无残留 `industrial-purple` 主路径样式 | + +每阶段可独立合并;**不在本规格内自动改 SimpleLite 原生菜单皮肤**。 + +--- + +## 8. 风险与缓解 + +| 风险 | 缓解 | +|---|---| +| 深色主题下写死的白字/半透明在浅底不可读 | P0 强制迁移 + P2 逐页扫对比度 | +| 地图页信息密度高,浅色易显脏 | 卡片分区 + 表格紧凑密度,状态色保留 | +| Element 覆盖不全 | 先覆盖高频控件,缺口记入回归清单 | +| 用户 localStorage 旧主题 | 启动迁移 + 一次性提示(可选) | + +--- + +## 9. 验收清单(整站) + +- [ ] 未登录:登录页为 Outpost 浅色气质 +- [ ] 登录后:侧栏深紫纹理 + 主区 `#f6f3fb` + 纸白卡片 +- [ ] 顶栏可切换 **浅色 / 紫色 / 蓝色** 三套精选 +- [ ] 用户菜单「高级 → 兼容主题」仍能选星云紫等旧深色 +- [ ] 监控/调度/OTA/配置:纸白卡、ink 字、无默认霓虹 orb +- [ ] 地图编辑器:工具/属性浅色,3D 画布仍深色可读 +- [ ] 告警/成功/故障色不被品牌色替换 +- [ ] 刷新后主题保持;未知 id 回落 `outpost-light` + +--- + +## 10. 开放项(审查时确认) + +1. ~~旧深色主题~~ → **已确认:保留并藏入高级** +2. **底栏 footer**:保留弱化版,还是删除并入顶栏?(建议:P1 先弱化保留) +3. 实现计划:`Migu2.0/docs/superpowers/plans/2026-07-25-migu-outpost-ui-lock.md`(本规格通过后编写) + +--- + +## 11. 审查结论(请用户勾选) + +- [ ] 同意本规格(含精选三色 + 高级保留旧主题),可编写实现计划并开工 +- [ ] 需要修改:________ diff --git a/frontends/apps/simple-platform-vue/design-system/outpost.md b/frontends/apps/simple-platform-vue/design-system/outpost.md new file mode 100644 index 0000000..8be7959 --- /dev/null +++ b/frontends/apps/simple-platform-vue/design-system/outpost.md @@ -0,0 +1,22 @@ +# Outpost 视觉规范(迷毂壳层) + +> 权威决策见:`Migu2.0/docs/superpowers/specs/2026-07-25-migu-outpost-ui-lock-design.md` +> 参考:https://fairylandtech.amerc.ai + +## 一句话 + +Outpost 壳层:浅主区 + 深色纹理侧栏 + 纸白卡片 + 柔阴影。 +主路径精选三色:**浅色(默认)/ 紫色 / 蓝色**;旧深色霓虹主题保留在「高级 → 兼容主题」。 + +## 精选主题 id + +| id | 名称 | +|---|---| +| `outpost-light` | 浅色(默认) | +| `outpost-purple` | 紫色 | +| `outpost-blue` | 蓝色 | + +## 例外 + +- webVRender / 地图 3D 画布:保持深色视口。 +- 状态色:继续用 `--mg-status-*`。 diff --git a/frontends/apps/simple-platform-vue/index.html b/frontends/apps/simple-platform-vue/index.html index e4e1248..a632fdb 100644 --- a/frontends/apps/simple-platform-vue/index.html +++ b/frontends/apps/simple-platform-vue/index.html @@ -1,11 +1,14 @@ - + 迷毂 · 智能调度平台 - + + + +
diff --git a/frontends/apps/simple-platform-vue/src/components/Workspace3D.vue b/frontends/apps/simple-platform-vue/src/components/Workspace3D.vue index 9ffcb20..f9f5dae 100644 --- a/frontends/apps/simple-platform-vue/src/components/Workspace3D.vue +++ b/frontends/apps/simple-platform-vue/src/components/Workspace3D.vue @@ -291,14 +291,23 @@ defineExpose({ reload, enterFullscreen }) .workspace-3d-mask { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; + /* 画布加载光晕固定深紫(不跟浅色壳白底 token,避免被冲成灰白) */ background: - radial-gradient(ellipse at center, rgba(var(--mg-primary-rgb), 0.35) 0%, rgba(var(--mg-bg-app-deep-rgb), 0.92) 80%), - rgba(var(--mg-bg-app-deep-rgb), 0.85); + radial-gradient( + ellipse at 50% 42%, + rgba(155, 124, 255, 0.42) 0%, + rgba(88, 48, 168, 0.72) 38%, + rgba(45, 27, 105, 0.92) 68%, + rgba(15, 4, 32, 0.98) 100% + ); color: rgba(232, 220, 255, 0.92); font-size: 13px; backdrop-filter: blur(10px); pointer-events: none; } -.workspace-3d-mask .muted { color: rgba(var(--mg-accent-rgb), 0.7); font-size: 12px; } -.workspace-3d-mask .el-icon { color: var(--mg-accent); filter: drop-shadow(0 0 10px rgba(var(--mg-accent-rgb), 0.6)); } +.workspace-3d-mask .muted { color: rgba(196, 181, 253, 0.78); font-size: 12px; } +.workspace-3d-mask .el-icon { + color: #c4b5fd; + filter: drop-shadow(0 0 12px rgba(155, 124, 255, 0.65)); +} diff --git a/frontends/apps/simple-platform-vue/src/components/map-editor/BetterAddFieldDialog.vue b/frontends/apps/simple-platform-vue/src/components/map-editor/BetterAddFieldDialog.vue new file mode 100644 index 0000000..98adbb9 --- /dev/null +++ b/frontends/apps/simple-platform-vue/src/components/map-editor/BetterAddFieldDialog.vue @@ -0,0 +1,168 @@ + + + + + diff --git a/frontends/apps/simple-platform-vue/src/components/map-editor/EditPropertyPanel.vue b/frontends/apps/simple-platform-vue/src/components/map-editor/EditPropertyPanel.vue index bd5fd5b..c2dca9c 100644 --- a/frontends/apps/simple-platform-vue/src/components/map-editor/EditPropertyPanel.vue +++ b/frontends/apps/simple-platform-vue/src/components/map-editor/EditPropertyPanel.vue @@ -16,11 +16,8 @@
-
-
- {{ selectionCount > 1 ? `多选 ${selectionCount}` : `#${primary?.id ?? '-'}` }} - {{ primary?.typeName ?? '-' }} -
+
+ 基础属性
- {{ deleting ? '⟳' : '🗑' }} + {{ deleting ? '⟳' : '×' }} 删除
+
+ +
+
+ {{ selectionCount > 1 ? `多选 ${selectionCount}` : `#${primary?.id ?? '-'}` }} + {{ primary?.typeName ?? '-' }} +
@@ -863,17 +867,17 @@ function onDelete() { diff --git a/frontends/apps/simple-platform-vue/src/components/map-editor/EditStatusBar.vue b/frontends/apps/simple-platform-vue/src/components/map-editor/EditStatusBar.vue index c99eab0..d28c1da 100644 --- a/frontends/apps/simple-platform-vue/src/components/map-editor/EditStatusBar.vue +++ b/frontends/apps/simple-platform-vue/src/components/map-editor/EditStatusBar.vue @@ -43,15 +43,15 @@ function formatXY(v: number) { align-items: center; gap: 16px; padding: 4px 14px; - background: rgba(20, 8, 40, 0.85); - border-top: 1px solid rgba(255,255,255,0.08); - color: rgba(232,215,245,0.85); + background: var(--me-chrome-2); + border-top: 1px solid var(--me-border); + color: var(--me-text-muted); font-size: 12px; - font-family: ui-monospace, Menlo, Consolas, monospace; + font-family: var(--mg-font-mono, ui-monospace, Menlo, Consolas, monospace); height: 28px; } .spacer { flex: 1; } -.seg b { color: var(--mg-accent, #c4a4ff); } +.seg b { color: var(--mg-accent); } .seg .on { color: #67c23a; } .seg .off { color: #a0a0a0; } .seg.ok { color: #67c23a; } diff --git a/frontends/apps/simple-platform-vue/src/components/map-editor/EditToolRail.vue b/frontends/apps/simple-platform-vue/src/components/map-editor/EditToolRail.vue index be3a143..9ab17fb 100644 --- a/frontends/apps/simple-platform-vue/src/components/map-editor/EditToolRail.vue +++ b/frontends/apps/simple-platform-vue/src/components/map-editor/EditToolRail.vue @@ -99,7 +99,6 @@ const groups: ToolGroup[] = [ { id: 'transform.move', label: '移动', glyph: '✥' }, { id: 'transform.rotate', label: '旋转', glyph: '⟳' }, { id: 'transform.scale', label: '缩放', glyph: '⤡' }, - { id: 'transform.duplicate', label: '复制副本', glyph: '⎘', tip: 'Ctrl+D' }, { id: 'transform.copy', label: '复制', glyph: '📋', tip: 'Ctrl+C' }, { id: 'transform.paste', label: '粘贴', glyph: '📥', tip: 'Ctrl+V' }, { id: 'transform.delete', label: '删除', glyph: '🗑', tip: 'Delete' }, @@ -152,12 +151,12 @@ function onClick(id: EditToolId) { emit('select-tool', id) } .edit-tool-rail { height: 100%; width: 170px; - background: linear-gradient(180deg, rgba(28, 12, 56, 0.85) 0%, rgba(18, 6, 36, 0.95) 100%); - border-right: 1px solid rgba(255,255,255,0.10); + background: linear-gradient(180deg, var(--me-chrome-1) 0%, var(--me-chrome-2) 100%); + border-right: 1px solid var(--me-border); padding: 4px 0 12px; backdrop-filter: blur(10px); display: flex; flex-direction: column; - box-shadow: inset -1px 0 0 rgba(255,255,255,0.04); + box-shadow: inset -1px 0 0 var(--me-card-border, transparent); } .rail-scroll { height: 100%; } .rail-group { @@ -168,12 +167,12 @@ function onClick(id: EditToolId) { emit('select-tool', id) } display: flex; align-items: center; gap: 6px; font-size: 10px; letter-spacing: 2px; - color: rgba(190, 160, 230, 0.7); + color: var(--me-text-muted); text-transform: uppercase; margin: 4px 0 6px; font-weight: 600; } -.rail-group-bar { flex: 1; height: 1px; background: rgba(190, 160, 230, 0.2); } +.rail-group-bar { flex: 1; height: 1px; background: rgba(var(--mg-primary-rgb), 0.18); } .rail-group-list { display: flex; flex-direction: column; gap: 2px; @@ -181,7 +180,7 @@ function onClick(id: EditToolId) { emit('select-tool', id) } .rail-divider { width: 100%; height: 1px; - background: linear-gradient(90deg, rgba(255,255,255,0.0) 0%, rgba(255,255,255,0.08) 50%, rgba(255,255,255,0.0) 100%); + background: linear-gradient(90deg, transparent 0%, var(--me-border) 50%, transparent 100%); margin: 6px 0 2px; } .rail-btn { @@ -192,8 +191,8 @@ function onClick(id: EditToolId) { emit('select-tool', id) } min-height: 32px; padding: 0 8px; border-radius: 6px; - background: rgba(255,255,255,0.04); - color: rgba(232,215,245,0.92); + background: var(--me-surface); + color: var(--me-text); display: flex; align-items: center; gap: 8px; font-size: 12.5px; @@ -202,16 +201,16 @@ function onClick(id: EditToolId) { emit('select-tool', id) } transition: background .14s ease, color .14s ease, box-shadow .14s ease, transform .12s ease; } .rail-btn:hover { - background: rgba(150, 90, 230, 0.20); - color: #fff; + background: var(--me-hover); + color: var(--mg-primary); } .rail-btn:active { transform: scale(0.985); } .rail-btn.rail-btn--active { - background: linear-gradient(120deg, rgba(170, 110, 250, 0.92) 0%, rgba(120, 70, 220, 0.92) 100%); + background: var(--mg-primary); color: #fff; - box-shadow: 0 3px 10px rgba(140, 80, 230, 0.45), inset 0 0 0 1px rgba(255,255,255,0.18); + box-shadow: 0 3px 10px var(--me-active-glow), inset 0 0 0 1px rgba(255,255,255,0.18); } .rail-btn-glyph { width: 20px; @@ -236,21 +235,21 @@ function onClick(id: EditToolId) { emit('select-tool', id) } position: absolute; left: 8px; right: 8px; top: 0; height: 1px; - background: linear-gradient(90deg, rgba(255,255,255,0.0) 0%, rgba(220, 140, 230, 0.35) 50%, rgba(255,255,255,0.0) 100%); + background: linear-gradient(90deg, transparent 0%, rgba(var(--mg-accent-rgb), 0.4) 50%, transparent 100%); } .rail-btn--ai { - background: linear-gradient(135deg, rgba(120, 70, 220, 0.55) 0%, rgba(255, 90, 200, 0.55) 100%); + background: var(--mg-primary); color: #fff; font-weight: 600; - box-shadow: 0 2px 10px rgba(220, 90, 220, 0.30), inset 0 0 0 1px rgba(255,255,255,0.20); + box-shadow: 0 2px 10px var(--me-active-glow), inset 0 0 0 1px rgba(255,255,255,0.20); } .rail-btn--ai:hover { - background: linear-gradient(135deg, rgba(150, 90, 240, 0.85) 0%, rgba(255, 110, 220, 0.85) 100%); + background: var(--mg-primary-hover); color: #fff; - box-shadow: 0 4px 14px rgba(230, 110, 230, 0.55), inset 0 0 0 1px rgba(255,255,255,0.30); + box-shadow: 0 4px 14px var(--me-active-glow), inset 0 0 0 1px rgba(255,255,255,0.30); } .rail-btn--ai .rail-btn-glyph { font-size: 16px; - text-shadow: 0 0 8px rgba(255, 200, 250, 0.6); + text-shadow: 0 0 8px rgba(var(--mg-accent-rgb), 0.55); } diff --git a/frontends/apps/simple-platform-vue/src/components/map-editor/EditTopBar.vue b/frontends/apps/simple-platform-vue/src/components/map-editor/EditTopBar.vue index 49d780d..81b91cb 100644 --- a/frontends/apps/simple-platform-vue/src/components/map-editor/EditTopBar.vue +++ b/frontends/apps/simple-platform-vue/src/components/map-editor/EditTopBar.vue @@ -148,16 +148,16 @@ function mark(on: boolean): string { align-items: center; gap: 4px; padding: 8px 14px; - background: linear-gradient(180deg, rgba(50, 22, 88, 0.95) 0%, rgba(34, 14, 64, 0.95) 100%); - border-bottom: 1px solid rgba(255,255,255,0.12); + background: linear-gradient(180deg, var(--me-chrome-1) 0%, var(--me-chrome-2) 100%); + border-bottom: 1px solid var(--me-border); backdrop-filter: blur(10px); - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25); + box-shadow: 0 2px 8px rgba(var(--mg-shadow-rgb, 22, 58, 74), 0.08); } .spacer { flex: 1; } -.el-divider--vertical { margin: 0 6px; background: rgba(255,255,255,0.15); } +.el-divider--vertical { margin: 0 6px; background: var(--me-border); } .topbar-btn { - color: #fdf6ff !important; + color: var(--me-text) !important; font-weight: 600; font-size: 13.5px; padding: 6px 12px; @@ -166,22 +166,23 @@ function mark(on: boolean): string { transition: background .15s ease, color .15s ease; } .topbar-btn:hover { - color: #fff !important; - background: rgba(170, 110, 250, 0.28) !important; + color: var(--mg-primary) !important; + background: var(--me-hover) !important; } .topbar-btn:focus { - background: rgba(170, 110, 250, 0.30) !important; + background: var(--me-hover) !important; } .topbar-icon-btn { - color: rgba(253, 246, 255, 0.92) !important; - background: rgba(255,255,255,0.05) !important; - border: 1px solid rgba(255,255,255,0.15) !important; + color: var(--me-text) !important; + background: var(--me-surface) !important; + border: 1px solid var(--me-border) !important; font-size: 15px; } .topbar-icon-btn:hover:not(.is-disabled) { - background: rgba(170, 110, 250, 0.30) !important; - border-color: rgba(170, 110, 250, 0.55) !important; + background: var(--me-hover) !important; + border-color: rgba(var(--mg-primary-rgb), 0.55) !important; + color: var(--mg-primary) !important; } .topbar-icon-btn.is-disabled { opacity: 0.4; @@ -194,11 +195,19 @@ function mark(on: boolean): string { height: auto; border-radius: 6px; margin-right: 4px; + --el-button-bg-color: var(--mg-primary) !important; + --el-button-border-color: var(--mg-primary) !important; + --el-button-hover-bg-color: var(--mg-primary-hover) !important; + --el-button-hover-border-color: var(--mg-primary-hover) !important; + --el-button-active-bg-color: var(--mg-primary-active) !important; + --el-button-active-border-color: var(--mg-primary-active) !important; + --el-button-text-color: #fff !important; + --el-button-hover-text-color: #fff !important; } .topbar-filter-menu :deep(.topbar-filter-header) { font-size: 11px; - color: rgba(232, 215, 245, 0.55); + color: var(--me-text-muted); cursor: default; pointer-events: none; padding-top: 6px; diff --git a/frontends/apps/simple-platform-vue/src/layouts/AppShell.vue b/frontends/apps/simple-platform-vue/src/layouts/AppShell.vue index 26ba643..24525c2 100644 --- a/frontends/apps/simple-platform-vue/src/layouts/AppShell.vue +++ b/frontends/apps/simple-platform-vue/src/layouts/AppShell.vue @@ -53,7 +53,7 @@ @@ -82,6 +82,15 @@ 配置向导 服务状态 + 高级 · 兼容主题 + + + {{ t.name }} + 退出登录 @@ -97,10 +106,13 @@ - {{ scopeLabel }} · webVRender :{{ vrPort }} · API {{ apiBase }} + {{ scopeLabel }} · Projection :{{ slPort }} · API {{ apiBase }} + + +
@@ -113,13 +125,14 @@ import { useAuthStore } from '@/stores/auth' import { useUiStore } from '@/stores/ui' import ScopeSwitcher from '@/components/ScopeSwitcher.vue' import ThemeSwitcher from '@/components/ThemeSwitcher.vue' +import AiAssistantDrawer from '@/components/assistant/AiAssistantDrawer.vue' const route = useRoute() const router = useRouter() const auth = useAuthStore() const ui = useUiStore() -const vrPort = computed(() => (import.meta.env.VITE_VRENDER_HOST as string | undefined)?.split(':')[1] ?? '8223') +const slPort = computed(() => (import.meta.env.VITE_SL_PORT as string | undefined) ?? '8222') const apiBase = computed(() => (import.meta.env.VITE_API_BASE as string | undefined) ?? '/api') const initial = computed(() => (auth.user?.displayName ?? auth.user?.username ?? '?').slice(0, 1).toUpperCase()) @@ -171,6 +184,10 @@ const activePath = computed(() => { const currentTitle = computed(() => (route.meta.title as string | undefined) ?? '') function onUserCommand(cmd: string) { + if (cmd.startsWith('theme:')) { + ui.setThemeId(cmd.slice('theme:'.length)) + return + } if (cmd === 'logout') { auth.logout() router.push('/login') @@ -187,6 +204,7 @@ function onUserCommand(cmd: string) { .app-shell { position: relative; height: 100vh; + height: 100dvh; overflow: hidden; } @@ -236,6 +254,7 @@ function onUserCommand(cmd: string) { position: relative; z-index: 1; height: 100vh; + height: 100dvh; } /* ─────────────── Sidebar ─────────────── */ @@ -549,3 +568,25 @@ function onUserCommand(cmd: string) { flex-direction: column; } + + diff --git a/frontends/apps/simple-platform-vue/src/stores/ui.ts b/frontends/apps/simple-platform-vue/src/stores/ui.ts index 489e33d..189d55b 100644 --- a/frontends/apps/simple-platform-vue/src/stores/ui.ts +++ b/frontends/apps/simple-platform-vue/src/stores/ui.ts @@ -2,8 +2,11 @@ import { defineStore } from 'pinia' import { DEFAULT_THEME_ID, + LEGACY_THEMES, + PRIMARY_THEMES, applyThemeVars, findTheme, + resolveThemeId, THEMES, type ThemePreset } from '@/styles/themes' @@ -28,6 +31,9 @@ interface UiState { } const STORAGE_KEY = 'simple.ui.state' +/** Outpost 壳层上线:旧本地主题只换了 id、观感几乎不变 → 升 schema 强制一次默认浅色 */ +const THEME_SCHEMA_KEY = 'simple.ui.themeSchema' +const THEME_SCHEMA_VERSION = 2 const DEFAULT_STATE: UiState = { sidebarCollapsed: false, @@ -39,14 +45,33 @@ const DEFAULT_STATE: UiState = { function loadInitial(): UiState { try { const raw = localStorage.getItem(STORAGE_KEY) - if (!raw) return { ...DEFAULT_STATE } + if (!raw) { + localStorage.setItem(THEME_SCHEMA_KEY, String(THEME_SCHEMA_VERSION)) + return { ...DEFAULT_STATE } + } const parsed = JSON.parse(raw) as Partial - return { + let themeId = resolveThemeId(parsed.themeId ?? DEFAULT_STATE.themeId) + const schema = Number(localStorage.getItem(THEME_SCHEMA_KEY) || '0') + const migrated = schema < THEME_SCHEMA_VERSION + if (migrated) { + // ponytail: 一次强制 outpost-light,兼容主题仍可从高级菜单切回 + themeId = DEFAULT_THEME_ID + localStorage.setItem(THEME_SCHEMA_KEY, String(THEME_SCHEMA_VERSION)) + } + const state: UiState = { sidebarCollapsed: parsed.sidebarCollapsed ?? DEFAULT_STATE.sidebarCollapsed, theme: parsed.theme === 'dark' ? 'dark' : 'light', - themeId: parsed.themeId ?? DEFAULT_STATE.themeId, + themeId, themeOverrides: parsed.themeOverrides ?? {} } + if (migrated) { + try { + localStorage.setItem(STORAGE_KEY, JSON.stringify(state)) + } catch { + /* ignore */ + } + } + return state } catch (err) { console.warn('[ui.store] localStorage 中的 UI 状态解析失败,已回退默认:', err) return { ...DEFAULT_STATE } @@ -60,8 +85,16 @@ export const useUiStore = defineStore('ui', { activeTheme(state): ThemePreset { return mergeThemePreset(findTheme(state.themeId), state.themeOverrides[state.themeId]) }, - /** 所有可选主题列表 */ + /** 顶栏精选主题(浅色 / 紫色 / 蓝色) */ availableThemes(): ThemePreset[] { + return PRIMARY_THEMES + }, + /** 高级 → 兼容主题(旧深色霓虹) */ + legacyThemes(): ThemePreset[] { + return LEGACY_THEMES + }, + /** 全量(自定义配色等内部用) */ + allThemes(): ThemePreset[] { return THEMES } }, @@ -107,7 +140,7 @@ export const useUiStore = defineStore('ui', { this.persist() }, - /** 切换品牌主题色板 */ + /** 切换品牌主题色板(精选或兼容均可) */ setThemeId(id: string) { const preset = findTheme(id) this.themeId = preset.id diff --git a/frontends/apps/simple-platform-vue/src/styles/theme.css b/frontends/apps/simple-platform-vue/src/styles/theme.css index 99e8ad5..51529b9 100644 --- a/frontends/apps/simple-platform-vue/src/styles/theme.css +++ b/frontends/apps/simple-platform-vue/src/styles/theme.css @@ -1,15 +1,13 @@ -/* 迷毂 平台主题:可切换色板 (v1.9) - * 默认主题:industrial-purple (星云紫 · 紫主色 + 蓝紫辅助 · 霓虹磨砂玻璃) - * 所有品牌相关颜色全部走 --mg-* CSS 变量,可由 src/styles/themes.ts 在运行时切换 - * - * 设计系统规范见 design-system/MASTER.md (由 ui-ux-pro-max skill 推导) +/* ?? ?????????? (v2.0) + * ?????outpost-light?Harbor??????+ ?????????? themes.ts ?? + * ?????design-system/outpost.md / MASTER.md */ -/* JetBrains Mono · 用于 KPI / 坐标 / ID 等数据数字(tabular-nums)*/ +/* JetBrains Mono ? KPI / coords / IDs (tabular-nums) */ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap'); :root { - /* ── 状态色(与品牌色解耦,跨主题保持语义) ── */ + /* ?? ??????????????????? ?? */ --mg-status-success: #22c55e; --mg-status-success-rgb: 34, 197, 94; --mg-status-warning: #f59e0b; @@ -21,7 +19,7 @@ --mg-status-idle: #94a3b8; --mg-status-idle-rgb: 148, 163, 184; - /* ── 数据可视化色板(ECharts / Progress 等) ── */ + /* ?? ????????ECharts / Progress ?? ?? */ --mg-data-c1: #3b82f6; --mg-data-c2: #22c55e; --mg-data-c3: #a855f7; @@ -31,19 +29,19 @@ --mg-data-c7: #ec4899; --mg-data-c8: #84cc16; - /* ── 字体栈 ── */ - --mg-font-sans: 'PingFang SC', 'Microsoft YaHei', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + /* ?? ????Outpost?Inter ?????? */ + --mg-font-sans: 'Inter', 'PingFang SC', 'Microsoft YaHei', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; --mg-font-mono: 'JetBrains Mono', 'Cascadia Mono', 'SF Mono', Menlo, Consolas, monospace; - /* ── 登录页 / 配置向导 固定品牌色(紫蓝混合,永不随主题切换变化) ── - * 登录窗与「平台配置向导」共用同一套定值,保证两处观感统一、且不受用户切换主题影响。 - * 色相:靛紫 #7c5cff ↔ 蓝紫(periwinkle) #5e7cff 的「紫蓝」渐变,刻意避开纯蓝 / 青色。 */ + /* ?? ????/ ???? ???????????????????????? + * ?????????????????????????????????????????? + * ??????#7c5cff ????(periwinkle) #5e7cff ?????????????? / ????*/ --lg-primary: #7d4dff; --lg-primary-rgb: 125, 77, 255; --lg-primary-hover: #9c79ff; --lg-primary-hover-rgb: 156, 121, 255; --lg-primary-deep: #5a2fc4; - /* accent 与登录按钮同款紫(同色系、略亮),让强调色/光晕/激活态都呈现按钮那种紫 */ + /* accent ????????????????????????/????????????*/ --lg-accent: #8b5cff; --lg-accent-rgb: 139, 92, 255; --lg-deep-rgb: 14, 9, 28; @@ -53,31 +51,30 @@ --lg-text-soft: rgba(220, 220, 250, 0.82); --lg-text-dim: rgba(196, 198, 235, 0.58); - /* ── 品牌主色(默认 = 星云紫,可被 themes.ts 注入覆盖) ── */ + /* default = outpost-light pure white (themes.ts overrides at runtime) */ --mg-primary: #7c3aed; --mg-primary-rgb: 124, 58, 237; --mg-primary-hover: #8b5cf6; --mg-primary-hover-rgb: 139, 92, 246; --mg-primary-active: #5b21b6; - --mg-accent: #c4b5fd; - --mg-accent-rgb: 196, 181, 253; + --mg-accent: #a855f7; + --mg-accent-rgb: 168, 85, 247; - --mg-primary-light-3: #9d6cf2; - --mg-primary-light-5: #b594f7; - --mg-primary-light-7: #6f4eab; - --mg-primary-light-8: #4c357a; - --mg-primary-light-9: #2d1f55; - --mg-primary-dark-2: #4c1d95; + --mg-primary-light-3: #a78bfa; + --mg-primary-light-5: #c4b5fd; + --mg-primary-light-7: #ddd6fe; + --mg-primary-light-8: #ede9fe; + --mg-primary-light-9: #f5f3ff; + --mg-primary-dark-2: #6d28d9; - /* ── 背景:深紫黑底 ── */ - --mg-bg-app-1: #0e0a24; - --mg-bg-app-2: #1f1147; - --mg-bg-app-3: #06031a; - --mg-bg-app-deep-rgb: 6, 3, 26; + --mg-bg-app-1: #ffffff; + --mg-bg-app-2: #ffffff; + --mg-bg-app-3: #ffffff; + --mg-bg-app-deep-rgb: 255, 255, 255; - --mg-bg-aside-1: #0c0820; - --mg-bg-aside-2: #03020e; - --mg-bg-aside-rgb: 10, 6, 30; + --mg-bg-aside-1: #ffffff; + --mg-bg-aside-2: #fafafa; + --mg-bg-aside-rgb: 255, 255, 255; --mg-bg-card-rgb: 38, 24, 78; --mg-bg-card-hi-rgb: 58, 38, 110; @@ -91,7 +88,7 @@ --mg-orb-b-opacity: 0.50; --mg-orb-c-opacity: 0.40; - /* ── 玻璃设计令牌(霓虹磨砂玻璃体系,主色感知更明显) ── */ + /* ?? ???????????????????????? ?? */ --mg-glass-bg: rgba(255, 255, 255, 0.06); --mg-glass-bg-hover: rgba(255, 255, 255, 0.10); --mg-glass-bg-active: rgba(255, 255, 255, 0.14); @@ -115,14 +112,14 @@ --mg-radius-lg: 20px; --mg-radius-xl: 24px; - /* ── 文字 ── */ + /* ?? ?? ?? */ --mg-text-light: #ffffff; --mg-text-muted: rgba(255, 255, 255, 0.7); --mg-text-dim: rgba(255, 255, 255, 0.5); --mg-text-faint: rgba(255, 255, 255, 0.35); --mg-divider: rgba(255, 255, 255, 0.08); - /* ── Element Plus 主色覆盖 ── */ + /* ?? Element Plus ???? ?? */ --el-color-primary: var(--mg-primary); --el-color-primary-rgb: var(--mg-primary-rgb); --el-color-primary-light-3: var(--mg-primary-light-3); @@ -134,19 +131,34 @@ --mg-transition: all .25s cubic-bezier(.25, .8, .25, 1); - /* ── 通用「内嵌表面」veil 令牌 ── - * 面板里的嵌套行 / 子卡 / 统计项常用 rgba(255,255,255,.0x) 当作浅色微透表面, - * 在深色主题里是「白色微透」效果;但 fame-lavender 浅紫主题切到白底后这些白veil - * 直接消失(白叠白)。把它们抽成令牌:深色主题保持白微透,fame-lavender 翻成紫微透, - * 这样所有引用处自动双主题可见,且不影响 6 套深色主题观感。 */ + /* ?? ????????veil ?? ?? + * ????????/ ?? / ??????rgba(255,255,255,.0x) ????????? + * ??????????????????fame-lavender ????????????veil + * ????????????????????????????fame-lavender ?????? + * ??????????????????? 6 ?????????*/ --mg-veil-1: rgba(255, 255, 255, 0.05); --mg-veil-2: rgba(255, 255, 255, 0.08); --mg-veil-3: rgba(255, 255, 255, 0.12); --mg-veil-border: rgba(255, 255, 255, 0.12); --mg-veil-border-hi: rgba(255, 255, 255, 0.20); - /* ── 面板「动作按钮」令牌 ── - * 深色主题:半透明紫玻璃底 + 白字;fame-lavender:实色紫底 + 白字(对比足够)。 */ + /* ?? ???? chrome????Harbor ????/???? themes.ts ???? ?? + * ???? themes.ts applyThemeVars ???????????*/ + --me-chrome-1: #ffffff; + --me-chrome-2: #ffffff; + --me-chrome-rgb: 255, 255, 255; + --me-border: rgba(15, 23, 42, 0.10); + --me-text: rgba(15, 23, 42, 0.92); + --me-text-muted: rgba(15, 23, 42, 0.52); + --me-surface: rgba(15, 23, 42, 0.03); + --me-hover: rgba(30, 58, 95, 0.06); + --me-active-glow: rgba(30, 58, 95, 0.14); + --me-card-bg: #ffffff; + --me-card-border: #e5e7eb; + --me-inset: #f8fafc; + + /* ?? ????????????? + * ???????????? + ???fame-lavender??????+ ??????????*/ --mg-action-bg: rgba(76, 29, 149, 0.45); --mg-action-bg-hover: rgba(109, 40, 217, 0.75); --mg-action-border: rgba(167, 139, 250, 0.55); @@ -179,7 +191,7 @@ body { #app { min-height: 100vh; position: relative; } -/* ── 全局科幻网格层 (默认开启,主题可单独关闭) ── */ +/* ?? ????????(????????????? ?? */ #app::before { content: ''; position: fixed; @@ -194,7 +206,7 @@ body { -webkit-mask-image: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.85) 0%, transparent 75%); opacity: 0.55; } -/* ── 极淡扫描线(增加科技感) ── */ +/* ?? ???????????? ?? */ #app::after { content: ''; position: fixed; @@ -211,10 +223,10 @@ body { mix-blend-mode: overlay; } -/* 让所有 router 内容在背景层之上 */ +/* ????router ???????? */ .app-shell, .login-page { position: relative; z-index: 1; } -/* ── 玻璃卡片复用类 ── */ +/* ?? ?????????? */ .mg-glass { background: var(--mg-glass-bg); border: 1px solid var(--mg-glass-border); @@ -242,7 +254,7 @@ body { 0 1px 0 rgba(255, 255, 255, 0.4) inset; } -/* ── 主按钮统一 ── */ +/* ?? ????? ?? */ .el-button--primary { --el-button-bg-color: var(--mg-primary); --el-button-border-color: var(--mg-primary); @@ -252,7 +264,7 @@ body { --el-button-active-border-color: var(--mg-primary-active); } -/* ── 滚动条 ── */ +/* ?? ?????? */ ::-webkit-scrollbar { width: 6px; height: 6px; } ::-webkit-scrollbar-thumb { background: rgba(var(--mg-accent-rgb), 0.4); @@ -266,19 +278,19 @@ body { a { color: var(--mg-accent); } a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } -/* ── 玻璃语境下 Element Plus 全局填充/背景变量暗化(会话 N+2 UI 修复)── - * 问题:默认 industrial-purple (星云紫) 主题下,`.mg-content` 把 `--el-text-color-primary` - * 改成白色 (line ~290) 让卡片/Table 等深底组件的字可读,但 element-plus 内部仍然有 - * `var(--el-fill-color-light)` (#f5f7fa)、`var(--el-bg-color)` (#fff) 等浅色填充值。 - * 任何组件(如 FieldMemberEditor `.fme-desc`、ProjectPropertiesView .pp-desc)用 - * `background: var(--el-fill-color-light)` + `color: var(--el-text-color-primary)` 就撞出 - * 「浅灰底 + 白字」不可读。 +/* ?? ??????Element Plus ????/??????????N+2 UI ????? + * ??????industrial-purple (???? ????`.mg-content` ??`--el-text-color-primary` + * ???? (line ~290) ????Table ????????????element-plus ?????? + * `var(--el-fill-color-light)` (#f5f7fa)?`var(--el-bg-color)` (#fff) ???????? + * ?????? FieldMemberEditor `.fme-desc`?ProjectPropertiesView .pp-desc?? + * `background: var(--el-fill-color-light)` + `color: var(--el-text-color-primary)` ???? + * ???? + ???????? * - * 解法:把 element-plus 填充/背景变量改成基于 `--mg-bg-card-rgb` 的半透明: - * - industrial-purple 时 --mg-bg-card-rgb = "38, 24, 78" → 暗紫 35-55% 透明,深底+白字 OK; - * - fame-lavender 时 --mg-bg-card-rgb = "255, 255, 255" → 白色 35-55% 透明,配 fame-lavender - * 的 #2d1b69 深字(line ~1069 已配)也清楚。 - * 边框、占位符同步走「主色感知」的灰阶。 */ + * ???? element-plus ??/???????? `--mg-bg-card-rgb` ?????? + * - industrial-purple ??--mg-bg-card-rgb = "38, 24, 78" ???? 35-55% ???????? OK?? + * - fame-lavender ??--mg-bg-card-rgb = "255, 255, 255" ???? 35-55% ???? fame-lavender + * ??#2d1b69 ???line ~1069 ???????? + * ????????????????????*/ .mg-content { --el-fill-color-blank: transparent; --el-fill-color-light: rgba(var(--mg-bg-card-rgb), 0.45); @@ -289,6 +301,9 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } --el-bg-color: rgba(var(--mg-bg-card-rgb), 0.55); --el-bg-color-page: transparent; --el-bg-color-overlay: rgba(var(--mg-bg-card-rgb), 0.92); + /* ??/???????? alpha ????????????? */ + --el-dialog-bg-color: rgb(var(--mg-bg-card-rgb)); + --el-drawer-bg-color: rgb(var(--mg-bg-card-rgb)); --el-border-color: rgba(255, 255, 255, 0.14); --el-border-color-light: rgba(255, 255, 255, 0.10); --el-border-color-lighter: rgba(255, 255, 255, 0.08); @@ -298,10 +313,37 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } --el-text-color-disabled: rgba(255, 255, 255, 0.30); } -/* FieldMemberEditor / ProjectPropertiesView 的「描述长条」专项修复 ─ - * 组件 scoped css 写 `background: var(--el-fill-color-light)` + `color: var(--el-text-color-primary)`, - * 即便上面 `.mg-content` 已经把变量改基于 --mg-bg-card-rgb,组件本身仍可能因 Vue scoped 选择器 - * 优先级把变量「冻结」住。这里直接给 `.fme-desc` 在 .mg-content 上下文里写绝对色,杜绝歧义。 */ +/* el-drawer????????????????? ? + * EP ????background-color: var(--el-drawer-bg-color)?? .el-drawer ?????? + * ????????var(--el-dialog-bg-color, var(--el-bg-color))??????0.55 ????? + * ?????? modal-class="tm-detail-drawer-modal"?? el-drawer ??class ???? + * ??????inheritAttrs=false + Teleport ????????? theme ?????? + * ?? alpha ??rgb() ?????????*/ +.mg-content .el-drawer, +.tm-detail-drawer-modal .el-drawer { + --el-drawer-bg-color: rgb(var(--mg-bg-card-rgb)) !important; + --el-dialog-bg-color: rgb(var(--mg-bg-card-rgb)) !important; + background: rgb(var(--mg-bg-card-rgb)) !important; + background-color: rgb(var(--mg-bg-card-rgb)) !important; + opacity: 1 !important; +} +.tm-detail-drawer-modal .el-drawer::before { + content: ''; + position: absolute; + inset: 0; + background: rgb(var(--mg-bg-card-rgb)) !important; + z-index: 0; + pointer-events: none; +} +.tm-detail-drawer-modal .el-drawer > * { + position: relative; + z-index: 1; +} + +/* FieldMemberEditor / ProjectPropertiesView ????????????? + * ?? scoped css ??`background: var(--el-fill-color-light)` + `color: var(--el-text-color-primary)`?? + * ???? `.mg-content` ???????? --mg-bg-card-rgb??????????Vue scoped ???? + * ????????????????? `.fme-desc` ??.mg-content ???????????????*/ .mg-content .fme-desc { background: rgba(var(--mg-bg-card-rgb), 0.55) !important; color: var(--mg-text-light) !important; @@ -310,15 +352,15 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } .mg-content .fme-path { color: var(--mg-text-light) !important; } .mg-content .fme-path-empty { color: var(--mg-text-muted) !important; } -/* ─── 「admin 风格 tabs」共享样式(会话 N+2 用户反馈) ──────────────────────────── - * 把「场景管理」(SceneManagerView) 里的 type="border-card" + 紫色高亮 tabs 抽成 - * 全局 .admin-tabs 类,让项目属性 / 车辆管理 / 后续配置中心等多 tab 页面统一外观。 +/* ??? ?admin ?? tabs???????? N+2 ?????????????????????????????????? + * ????????SceneManagerView) ?? type="border-card" + ???? tabs ?? + * ?? .admin-tabs ????????/ ???? / ???????? tab ???????? * - * 用法: ... - * - 容器:透明背景 + 紫色微辉边框; - * - tab 头:透明 + 浅紫边线; - * - tab 项:未激活淡紫白;hover 加亮;激活时紫色高亮底 + 紫色底边。 - * 仅在 .mg-content 内生效,避免污染登录页等非主区组件。 */ + * ????el-tabs class="admin-tabs" type="border-card"> ... + * - ??????? + ???????? + * - tab ???? + ?????? + * - tab ?????????hover ????????????+ ?????? + * ?? .mg-content ???????????????????*/ .mg-content .admin-tabs.el-tabs--border-card { height: 100%; background: rgba(var(--mg-bg-card-rgb), 0.45) !important; @@ -370,29 +412,92 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } height: 100%; } -/* fame-lavender 主题下 admin-tabs 反白:浅紫底 + 深紫字 + 紫色高亮 */ -:root[data-theme="fame-lavender"] .mg-content .admin-tabs.el-tabs--border-card { +/* fame-lavender ????admin-tabs ?????? + ????+ ???? */ +:root[data-shell="outpost"] .mg-content .admin-tabs.el-tabs--border-card { background: #ffffff !important; border: 1px solid rgba(124, 58, 237, 0.18) !important; box-shadow: 0 8px 24px rgba(124, 58, 237, 0.06) !important; } -:root[data-theme="fame-lavender"] .mg-content .admin-tabs.el-tabs--border-card > .el-tabs__header { +:root[data-shell="outpost"] .mg-content .admin-tabs.el-tabs--border-card > .el-tabs__header { background: rgba(124, 58, 237, 0.04) !important; border-bottom: 1px solid rgba(124, 58, 237, 0.14) !important; } -:root[data-theme="fame-lavender"] .mg-content .admin-tabs.el-tabs--border-card > .el-tabs__header .el-tabs__item { +:root[data-shell="outpost"] .mg-content .admin-tabs.el-tabs--border-card > .el-tabs__header .el-tabs__item { color: #4a3d6e !important; } -:root[data-theme="fame-lavender"] .mg-content .admin-tabs.el-tabs--border-card > .el-tabs__header .el-tabs__item:hover { +:root[data-shell="outpost"] .mg-content .admin-tabs.el-tabs--border-card > .el-tabs__header .el-tabs__item:hover { background: rgba(124, 58, 237, 0.08) !important; color: #7c3aed !important; } -:root[data-theme="fame-lavender"] .mg-content .admin-tabs.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active { +:root[data-shell="outpost"] .mg-content .admin-tabs.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active { background: rgba(124, 58, 237, 0.14) !important; color: #7c3aed !important; } -/* ── 玻璃语境下 Element Plus 的常见组件调整 ── */ +/* Style A ? Ops Console?underline tabs?????????? border-card ??*/ +.mg-content .admin-tabs.admin-tabs--ops { + height: 100%; + background: transparent !important; + border: 0 !important; + box-shadow: none !important; + border-radius: 0; + display: flex; + flex-direction: column; + overflow: hidden; +} +.mg-content .admin-tabs.admin-tabs--ops > .el-tabs__header { + background: transparent !important; + border-bottom: 1px solid var(--mg-veil-border, rgba(124, 58, 237, 0.14)) !important; + margin: 0 0 8px; + flex: none; +} +.mg-content .admin-tabs.admin-tabs--ops > .el-tabs__header .el-tabs__nav { + border: 0 !important; +} +.mg-content .admin-tabs.admin-tabs--ops > .el-tabs__header .el-tabs__item { + background: transparent !important; + border: 0 !important; + height: 36px; + line-height: 36px; + font-size: 13.5px; + letter-spacing: 0.2px; + padding: 0 16px !important; + color: var(--mg-text-muted, #756d85) !important; + font-weight: 500; + box-shadow: none !important; +} +.mg-content .admin-tabs.admin-tabs--ops > .el-tabs__header .el-tabs__item:hover { + color: var(--mg-primary, #7c3aed) !important; + background: transparent !important; +} +.mg-content .admin-tabs.admin-tabs--ops > .el-tabs__header .el-tabs__item.is-active { + color: var(--mg-primary, #7c3aed) !important; + font-weight: 700; + background: transparent !important; +} +.mg-content .admin-tabs.admin-tabs--ops > .el-tabs__header .el-tabs__active-bar { + background: var(--mg-primary, #7c3aed); + height: 2px; +} +.mg-content .admin-tabs.admin-tabs--ops > .el-tabs__content { + flex: 1; + padding: 0; + overflow: hidden; + background: transparent !important; + min-height: 0; +} +.mg-content .admin-tabs.admin-tabs--ops .el-tab-pane { + height: 100%; +} +:root[data-shell="outpost"] .mg-content .admin-tabs.admin-tabs--ops > .el-tabs__header .el-tabs__item { + color: #4a3d6e !important; +} +:root[data-shell="outpost"] .mg-content .admin-tabs.admin-tabs--ops > .el-tabs__header .el-tabs__item:hover, +:root[data-shell="outpost"] .mg-content .admin-tabs.admin-tabs--ops > .el-tabs__header .el-tabs__item.is-active { + color: #7c3aed !important; +} + +/* ?? ??????Element Plus ?????????? */ .mg-content .el-card { background: linear-gradient(135deg, rgba(var(--mg-bg-card-rgb), 0.55) 0%, rgba(var(--mg-bg-app-deep-rgb), 0.6) 100%) !important; border: 1px solid rgba(255, 255, 255, 0.14); @@ -425,7 +530,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } color: var(--mg-text-light); } -/* 嵌套的 card(如 ConfigPageBase 内层)使用更浅的透明度 */ +/* ????card?? ConfigPageBase ????????????*/ .mg-content .el-card .el-card { background: rgba(255, 255, 255, 0.04) !important; border-color: rgba(255, 255, 255, 0.1); @@ -442,12 +547,12 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } .mg-content h3 { color: var(--mg-text-light); margin-top: 0; } .mg-content p { color: var(--mg-text-muted); } -/* el-statistic 在玻璃语境下 */ +/* el-statistic ?????? */ .mg-content .el-statistic__head { color: var(--mg-text-muted); } .mg-content .el-statistic__number { color: var(--mg-text-light); } .mg-content .el-statistic__content { color: var(--mg-text-light); } -/* el-tabs 玻璃语境(SimpleLite 监控台:地图/进程/场景等) */ +/* el-tabs ?????SimpleLite ??????/??/???? */ .mg-content .el-tabs { --el-text-color-primary: #fff; } @@ -468,7 +573,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } background-color: rgba(255, 255, 255, 0.14) !important; } -/* el-table 在玻璃语境下 */ +/* el-table ?????? */ .mg-content .el-table, .mg-content .el-table tr, .mg-content .el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell { @@ -507,7 +612,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } .mg-content .el-table__inner-wrapper::before, .mg-content .el-table::before { background: rgba(255, 255, 255, 0.1) !important; } -/* el-input 在玻璃语境下 (admin 区表单) */ +/* el-input ?????? (admin ???? */ .mg-content .el-input__wrapper, .mg-content .el-textarea__inner { background: rgba(255, 255, 255, 0.06) !important; @@ -526,7 +631,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } .mg-content .el-divider__text { background: transparent !important; color: var(--mg-text-muted); } .mg-content .el-divider { background: var(--mg-divider); } -/* el-tag 在玻璃语境下保持主题色 */ +/* el-tag ????????????*/ .mg-content .el-tag { background: rgba(var(--mg-accent-rgb), 0.18); color: rgba(var(--mg-text-tint-rgb), 1); @@ -553,7 +658,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } border-color: rgba(122, 107, 135, 0.5); } -/* el-descriptions 在玻璃语境 */ +/* el-descriptions ??????*/ .mg-content .el-descriptions { --el-text-color-primary: #fff; --el-text-color-regular: var(--mg-text-muted); @@ -579,7 +684,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } } .mg-content .el-descriptions__title { color: #fff; } -/* el-progress 主题色 */ +/* el-progress ????*/ .mg-content .el-progress-bar__outer { background: rgba(255, 255, 255, 0.1); } @@ -587,7 +692,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } background: linear-gradient(90deg, var(--mg-primary-hover) 0%, var(--mg-accent) 100%); } -/* el-alert 玻璃化 */ +/* el-alert ????*/ .mg-content .el-alert { background: rgba(255, 255, 255, 0.06) !important; border: 1px solid rgba(255, 255, 255, 0.14); @@ -596,7 +701,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } .mg-content .el-alert__title, .mg-content .el-alert__description { color: var(--mg-text-light) !important; } -/* el-collapse 玻璃化 */ +/* el-collapse ????*/ .mg-content .el-collapse { border-color: rgba(255, 255, 255, 0.1); --el-collapse-header-bg-color: transparent; @@ -611,7 +716,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } color: var(--mg-text-light) !important; } -/* el-radio / el-checkbox 在玻璃语境下 */ +/* el-radio / el-checkbox ?????? */ .mg-content .el-radio__label, .mg-content .el-checkbox__label { color: var(--mg-text-light) !important; } .mg-content .el-radio__inner, @@ -632,13 +737,13 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } color: #fff !important; } -/* el-select 玻璃化 */ +/* el-select ????*/ .mg-content .el-select .el-input__wrapper { background: rgba(255, 255, 255, 0.06) !important; box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.18) inset !important; } -/* el-input-number 玻璃化 */ +/* el-input-number ????*/ .mg-content .el-input-number .el-input-number__decrease, .mg-content .el-input-number .el-input-number__increase { background: rgba(255, 255, 255, 0.06) !important; @@ -646,13 +751,13 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } border-color: rgba(255, 255, 255, 0.15) !important; } -/* el-switch 主题色 */ +/* el-switch ????*/ .mg-content .el-switch.is-checked .el-switch__core { background: var(--mg-primary); border-color: var(--mg-primary); } -/* el-statistic 颜色重置 */ +/* el-statistic ???? */ .mg-content .el-statistic .el-statistic__head { color: var(--mg-text-muted); font-size: 13px; @@ -664,7 +769,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } text-shadow: 0 2px 8px rgba(var(--mg-primary-hover-rgb), 0.4); } -/* KPI 玻璃卡片: 内的 el-statistic 自动玻璃化 */ +/* KPI ??????el-row class="kpi-row"> ?? el-statistic ??????*/ .mg-content .kpi-row .el-statistic, .mg-content .kpi-card { background: linear-gradient(135deg, rgba(var(--mg-bg-card-rgb), 0.55) 0%, rgba(var(--mg-bg-app-deep-rgb), 0.6) 100%); @@ -684,7 +789,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } border-color: rgba(255, 255, 255, 0.22); } -/* el-pagination 玻璃化 */ +/* el-pagination ????*/ .mg-content .el-pagination { --el-pagination-bg-color: transparent; --el-pagination-button-bg-color: rgba(255, 255, 255, 0.06); @@ -693,7 +798,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } color: var(--mg-text-muted); } -/* el-dropdown-menu 暗化 */ +/* el-dropdown-menu ?? */ .el-dropdown-menu { background: rgba(var(--mg-bg-aside-rgb), 0.92) !important; backdrop-filter: blur(20px); @@ -707,9 +812,9 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } color: #fff !important; } -/* el-message / 全局消息提示沿用 Element Plus 默认浅色(在暗背景上更易读) */ +/* el-message / ???????? Element Plus ?????????????? */ -/* el-button default 按钮在玻璃语境下 */ +/* el-button default ???????? */ .mg-content .el-button:not(.el-button--primary):not(.el-button--success):not(.el-button--warning):not(.el-button--danger):not(.el-button--text) { background: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.2); @@ -721,11 +826,11 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } color: #fff; } -/* h2 在浅色页面(如对话框)保留主题深色 */ +/* h2 ??????????????????*/ .el-dialog h2 { color: var(--mg-primary-active); } .el-dialog { border-radius: var(--mg-radius); } -/* ─────────────── 星云紫专项:深紫底 + 蓝紫辉光 + 霓虹高光 ─────────────── */ +/* ??????????????? ??????????+ ???? + ???? ??????????????? */ :root[data-theme="industrial-purple"] { --mg-orb-a-opacity: 0.55; --mg-orb-b-opacity: 0.50; @@ -757,7 +862,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } linear-gradient(135deg, var(--mg-bg-app-1) 0%, var(--mg-bg-app-2) 48%, var(--mg-bg-app-3) 100%); } -/* 星云紫主题下:网格更紫,扫描线更明显 */ +/* ??????:????,?????? */ :root[data-theme="industrial-purple"] #app::before { background-image: linear-gradient(rgba(var(--mg-accent-rgb), 0.07) 1px, transparent 1px), @@ -774,7 +879,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } ); } -/* 卡片:紫色玻璃质感 */ +/* ??????????*/ :root[data-theme="industrial-purple"] .mg-content .el-card, :root[data-theme="industrial-purple"] .mg-content .kpi-row .el-statistic, :root[data-theme="industrial-purple"] .mg-content .kpi-card { @@ -793,7 +898,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } -webkit-backdrop-filter: blur(18px) saturate(160%); overflow: hidden; } -/* 顶部 1px 高光线 → 玻璃质感的灵魂 */ +/* ?? 1px ??????????????*/ :root[data-theme="industrial-purple"] .mg-content .el-card::before, :root[data-theme="industrial-purple"] .mg-content .kpi-card::before { content: ''; @@ -853,7 +958,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } box-shadow: 0 0 0 1px rgba(var(--mg-accent-rgb), 0.18) inset !important; } -/* 主按钮:紫色霓虹脉冲 */ +/* ?????????? */ :root[data-theme="industrial-purple"] .el-button--primary { background: linear-gradient(135deg, var(--mg-primary) 0%, @@ -887,14 +992,14 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } transform: translateY(-1px); } -/* el-tag 增强紫色感 */ +/* el-tag ??????*/ :root[data-theme="industrial-purple"] .mg-content .el-tag { background: linear-gradient(135deg, rgba(var(--mg-primary-rgb), 0.25), rgba(var(--mg-accent-rgb), 0.18)); color: #fff; border-color: rgba(var(--mg-accent-rgb), 0.45); } -/* 工具类:霓虹文字(卡片标题、KPI数值可用) */ +/* ??????????????KPI????? */ .mg-neon-text { background: linear-gradient(135deg, #ffffff 0%, var(--mg-accent) 100%); -webkit-background-clip: text; @@ -903,7 +1008,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } text-shadow: 0 0 18px rgba(var(--mg-primary-hover-rgb), 0.45); } -/* 工具类:浮动 orb 节奏可视化(其他组件可用) */ +/* ?????? orb ??????????????*/ @keyframes mg-pulse-glow { 0%, 100% { box-shadow: @@ -917,13 +1022,13 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } } } -/* ════════════════════════════════════════════════════════════════════ - * 迷毂浅紫 (fame-lavender) ─ 参考 FAME 系统的浅色变体 - * 设计目标:长时间使用不刺眼;右侧主区采用浅紫白底,深紫字色; - * 侧栏保留深紫渐变以维持品牌一致性; - * 关闭所有 orb / 网格 / 扫描线 / 霓虹光效。 - * ════════════════════════════════════════════════════════════════════ */ -:root[data-theme="fame-lavender"] { +/* ???????????????????????????????????????????????????????????????????? + * ???? (fame-lavender) ? ???FAME ???????? + * ?????????????????????????????? + * ????????????????? + * ?????orb / ?? / ????/ ?????? + * ???????????????????????????????????????????????????????????????????? */ +:root[data-shell="outpost"] { --mg-glass-bg: rgba(255, 255, 255, 0.95); --mg-glass-bg-hover: rgba(249, 246, 255, 1); --mg-glass-bg-active: rgba(245, 240, 251, 1); @@ -938,14 +1043,14 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } --mg-glass-blur: none; --mg-glass-blur-hi: none; - /* 文字层级(v2 升级:对比度从 4.5:1 提至 7-15:1,关键提升正文清晰度) */ - --mg-text-light: #1a0f3d; /* 主标题 / KPI 数字 · 对比 ~15:1 */ - --mg-text-muted: #4a3d6e; /* 正文 / 说明文字 · 对比 ~9:1 (旧 #606266 在浅紫底上仅 5:1) */ - --mg-text-dim: #7a6b9a; /* 次要信息 / 时间戳 / 占位 · 对比 ~5:1 */ - --mg-text-faint: #a8a0c0; /* 禁用 / 装饰文字 · 对比 ~3:1 */ - --mg-divider: #e8e1f0; /* 分割线 / 卡片描边(比 #ebe5f4 略冷略深,更清晰) */ + /* ?????v2 ????????4.5:1 ?? 7-15:1????????????*/ + --mg-text-light: #1a0f3d; /* ????/ KPI ?? ? ?? ~15:1 */ + --mg-text-muted: #4a3d6e; /* ?? / ???? ? ?? ~9:1 (??#606266 ?????? 5:1) */ + --mg-text-dim: #7a6b9a; /* ???? / ????/ ?? ? ?? ~5:1 */ + --mg-text-faint: #a8a0c0; /* ?? / ???? ? ?? ~3:1 */ + --mg-divider: #e8e1f0; /* ????/ ?????? #ebe5f4 ??????????*/ - /* 浅色主题状态色 (WCAG AA 兼容) */ + /* ??????? (WCAG AA ??) */ --mg-status-success: #15803d; --mg-status-success-rgb: 21, 128, 61; --mg-status-warning: #b45309; @@ -957,56 +1062,207 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } --mg-status-idle: #64748b; --mg-status-idle-rgb: 100, 116, 139; - /* 卡片 / 列表行:浅底白卡(与 industrial-purple 深紫卡区分) */ + /* ?? / ?????????? industrial-purple ?????? */ --mg-bg-card-rgb: 255, 255, 255; --mg-bg-card-hi-rgb: 249, 246, 255; --mg-bg-card-darker-rgb: 245, 240, 251; --mg-accent-rgb: 124, 58, 237; - /* 内嵌表面 veil:浅紫主题翻成紫色微透,保证白底卡片内的嵌套行 / 子卡可见 */ + /* ???? veil????????????????????????/ ???? */ --mg-veil-1: rgba(124, 58, 237, 0.05); --mg-veil-2: rgba(124, 58, 237, 0.10); --mg-veil-3: rgba(124, 58, 237, 0.16); --mg-veil-border: rgba(124, 58, 237, 0.16); --mg-veil-border-hi: rgba(124, 58, 237, 0.32); - /* 动作按钮:实色紫底 + 白字(对比 ~6.9:1,WCAG AA 通过) */ + /* ??????????+ ??????~6.9:1?WCAG AA ????*/ --mg-action-bg: #7c3aed; --mg-action-bg-hover: #6d28d9; --mg-action-border: #7c3aed; --mg-action-border-hi: #6d28d9; } -/* body:纯净紫白渐变(更柔和、长时间阅读不刺眼) */ -:root[data-theme="fame-lavender"] body { - background: - linear-gradient(160deg, #edeaf5 0%, #e7e4f1 55%, #f1eef8 100%) !important; - color: #1a0f3d; +/* outpost-light: pure white shell + indigo accents */ +:root[data-theme="outpost-light"] { + --mg-glass-bg: #ffffff; + --mg-glass-bg-hover: #ffffff; + --mg-glass-bg-active: #f8fafc; + --mg-glass-border: rgba(15, 23, 42, 0.10); + --mg-glass-border-hi: rgba(30, 58, 95, 0.22); + --mg-glass-shadow: + 0 1px 2px rgba(15, 23, 42, 0.04), + 0 0 0 1px rgba(15, 23, 42, 0.06); + --mg-glass-shadow-hi: + 0 4px 16px rgba(15, 23, 42, 0.06), + 0 0 0 1px rgba(30, 58, 95, 0.12); + --mg-text-light: #0f172a; + --mg-text-muted: #64748b; + --mg-text-dim: #94a3b8; + --mg-text-faint: #cbd5e1; + --mg-divider: #e5e7eb; + --mg-veil-1: rgba(15, 23, 42, 0.03); + --mg-veil-2: rgba(15, 23, 42, 0.05); + --mg-veil-3: rgba(15, 23, 42, 0.08); + --mg-veil-border: rgba(15, 23, 42, 0.10); + --mg-veil-border-hi: rgba(30, 58, 95, 0.22); + --mg-action-bg: #7c3aed; + --mg-action-bg-hover: #8b5cf6; + --mg-action-border: #7c3aed; + --mg-action-border-hi: #8b5cf6; +} +:root[data-theme="outpost-light"] body { + background: #ffffff !important; +} +:root[data-theme="outpost-light"] .aside { + background: #ffffff !important; + border-right: 1px solid #e5e7eb !important; + box-shadow: 1px 0 0 rgba(15, 23, 42, 0.04) !important; +} +:root[data-theme="outpost-light"] .aside .logo { + border-bottom-color: #e5e7eb !important; + background: #ffffff !important; +} +:root[data-theme="outpost-light"] .aside .logo-img-full, +:root[data-theme="outpost-light"] .aside .logo-img-small { + filter: brightness(0) saturate(100%) invert(27%) sepia(86%) saturate(2400%) hue-rotate(248deg) brightness(0.95); +} +:root[data-theme="outpost-light"] .aside .logo-title-zh { + background: none !important; + -webkit-text-fill-color: #7c3aed !important; + color: #7c3aed !important; + text-shadow: none !important; +} +:root[data-theme="outpost-light"] .aside .logo-title-en { + color: #94a3b8 !important; +} +:root[data-theme="outpost-light"] .aside .logo-title-en b { + color: #7c3aed !important; +} +:root[data-theme="outpost-light"] .aside .logo-abbr { + color: #7c3aed !important; +} +:root[data-theme="outpost-light"] .aside .el-menu-item, +:root[data-theme="outpost-light"] .aside .el-sub-menu__title { + color: #475569 !important; +} +:root[data-theme="outpost-light"] .aside .el-menu-item:hover, +:root[data-theme="outpost-light"] .aside .el-sub-menu__title:hover { + background: #f8fafc !important; + color: #0f172a !important; +} +:root[data-theme="outpost-light"] .aside .el-menu-item.is-active, +:root[data-theme="outpost-light"] .aside .el-sub-menu.is-active > .el-sub-menu__title { + background: #f5f3ff !important; + color: #7c3aed !important; + box-shadow: inset 3px 0 0 #7c3aed !important; + font-weight: 700 !important; +} +:root[data-theme="outpost-light"] .aside .el-menu .el-menu-item.is-active { + background: #f5f3ff !important; + box-shadow: inset 2px 0 0 #7c3aed !important; + color: #7c3aed !important; +} +:root[data-theme="outpost-light"] .aside .el-sub-menu .el-menu { + background: #f8fafc !important; +} +:root[data-theme="outpost-light"] .aside-footer { + border-top-color: #e5e7eb !important; + color: #94a3b8 !important; +} +:root[data-theme="outpost-light"] .aside-footer-badge { + background: #f5f3ff !important; + border-color: #ddd6fe !important; + color: #7c3aed !important; + box-shadow: none !important; +} +:root[data-theme="outpost-light"] .header { + background: #ffffff !important; + border-bottom-color: #e5e7eb !important; + box-shadow: none !important; +} +:root[data-theme="outpost-light"] .header .el-breadcrumb__inner { color: #64748b !important; } +:root[data-theme="outpost-light"] .header .el-breadcrumb__item:last-child .el-breadcrumb__inner { + color: #0f172a !important; +} +:root[data-theme="outpost-light"] .header .el-breadcrumb__separator { color: #cbd5e1 !important; } +:root[data-theme="outpost-light"] .header .el-breadcrumb__inner:hover { color: #7c3aed !important; } +:root[data-theme="outpost-light"] .header .user-name { color: #0f172a !important; } +:root[data-theme="outpost-light"] .header .icon-btn:hover { color: #7c3aed !important; } +:root[data-theme="outpost-light"] .header .el-radio-button.is-active .el-radio-button__inner { + background: #7c3aed !important; + border-color: #7c3aed !important; + color: #fff !important; +} +:root[data-theme="outpost-light"] .mg-content h1, +:root[data-theme="outpost-light"] .mg-content h2, +:root[data-theme="outpost-light"] .mg-content h3 { + color: #0f172a !important; +} +:root[data-theme="outpost-light"] .mg-content p { color: #64748b !important; } +:root[data-theme="outpost-light"] .mg-content .el-tabs__item, +:root[data-theme="outpost-light"] .el-tabs__item { color: #64748b !important; } +:root[data-theme="outpost-light"] .mg-content .el-tabs__item:hover, +:root[data-theme="outpost-light"] .el-tabs__item:hover { color: #7c3aed !important; } +:root[data-theme="outpost-light"] .mg-content .el-tabs__item.is-active, +:root[data-theme="outpost-light"] .el-tabs__item.is-active { + color: #7c3aed !important; + font-weight: 700; +} +:root[data-theme="outpost-light"] .el-tabs__active-bar { + background-color: #7c3aed !important; +} +:root[data-theme="outpost-light"] .mg-content .el-form-item__label { color: #64748b !important; } +:root[data-theme="outpost-light"] .mg-content .method-btn, +:root[data-theme="outpost-light"] .mg-content .header-action-btn { + background: #7c3aed !important; + border-color: #7c3aed !important; +} +:root[data-theme="outpost-light"] .mg-content .method-btn:hover:not(:disabled), +:root[data-theme="outpost-light"] .mg-content .header-action-btn:hover { + background: #8b5cf6 !important; + border-color: #8b5cf6 !important; +} +:root[data-theme="outpost-light"] .mg-content .add-field-btn { + background: #ffffff !important; + border: 1px dashed #cbd5e1 !important; + color: #7c3aed !important; +} +:root[data-theme="outpost-light"] .mg-content .add-field-btn:hover { + background: #f8fafc !important; + border-color: #7c3aed !important; + color: #0f172a !important; } -/* 关闭全局背景网格与扫描线 */ -:root[data-theme="fame-lavender"] #app::before, -:root[data-theme="fame-lavender"] #app::after { +/* body???????????--mg-bg-app-*??*/ +:root[data-shell="outpost"] body { + background: + linear-gradient(160deg, var(--mg-bg-app-1) 0%, var(--mg-bg-app-2) 55%, var(--mg-bg-app-3) 100%) !important; + color: var(--mg-text-light); +} + +/* ???????????? */ +:root[data-shell="outpost"] #app::before, +:root[data-shell="outpost"] #app::after { display: none !important; } -/* 关闭 AppShell 中的浮动 orb */ -:root[data-theme="fame-lavender"] .bg-orbs { display: none !important; } +/* ?? AppShell ???? orb */ +:root[data-shell="outpost"] .bg-orbs { display: none !important; } -/* 侧栏:宝石紫渐变 + 高可读性 menu 状态(v2 优化对比度与层级) */ -:root[data-theme="fame-lavender"] .aside { - background: linear-gradient(180deg, #2e1065 0%, #1c0a4d 100%) !important; +/* ?????? aside ???? plum / ??/ ?? */ +:root[data-shell="outpost"] .aside { + background: linear-gradient(180deg, var(--mg-bg-aside-1) 0%, var(--mg-bg-aside-2) 100%) !important; border-right: 1px solid rgba(0, 0, 0, 0.08) !important; backdrop-filter: none !important; -webkit-backdrop-filter: none !important; box-shadow: 4px 0 24px rgba(45, 27, 105, 0.18) !important; } -:root[data-theme="fame-lavender"] .aside::before { display: none !important; } -:root[data-theme="fame-lavender"] .aside .logo { +:root[data-shell="outpost"] .aside::before { display: none !important; } +:root[data-shell="outpost"] .aside .logo { background: transparent !important; border-bottom: 1px solid rgba(196, 181, 253, 0.12) !important; } -:root[data-theme="fame-lavender"] .aside .logo-title-zh { +:root[data-shell="outpost"] .aside .logo-title-zh { background: linear-gradient(135deg, #ffffff 0%, #c4b5fd 100%) !important; -webkit-background-clip: text !important; background-clip: text !important; @@ -1016,26 +1272,26 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } font-weight: 700; } -/* inactive menu item:浅紫白文字(提高可读性,比纯白稍柔和) - * 会话 14:原规则同样误用了 Vue scoped 专属的 :deep(),在全局 css 中无效。 - * 去掉 :deep() 后规则才能落到 element-plus 渲染出的 .el-menu-item / .el-sub-menu__title 上。 */ -:root[data-theme="fame-lavender"] .aside .el-menu { +/* inactive menu item????????????????????? + * ?? 14??????????Vue scoped ????:deep()???? css ????? + * ?? :deep() ????????element-plus ???? .el-menu-item / .el-sub-menu__title ???*/ +:root[data-shell="outpost"] .aside .el-menu { background: transparent !important; border-right: none !important; } -:root[data-theme="fame-lavender"] .aside .el-menu-item, -:root[data-theme="fame-lavender"] .aside .el-sub-menu__title { +:root[data-shell="outpost"] .aside .el-menu-item, +:root[data-shell="outpost"] .aside .el-sub-menu__title { color: #d4cae8 !important; font-weight: 500 !important; background: transparent !important; } -:root[data-theme="fame-lavender"] .aside .el-menu-item:hover, -:root[data-theme="fame-lavender"] .aside .el-sub-menu__title:hover { +:root[data-shell="outpost"] .aside .el-menu-item:hover, +:root[data-shell="outpost"] .aside .el-sub-menu__title:hover { background: rgba(196, 181, 253, 0.10) !important; color: #ffffff !important; } -:root[data-theme="fame-lavender"] .aside .el-menu-item.is-active, -:root[data-theme="fame-lavender"] .aside .el-sub-menu.is-active > .el-sub-menu__title { +:root[data-shell="outpost"] .aside .el-menu-item.is-active, +:root[data-shell="outpost"] .aside .el-sub-menu.is-active > .el-sub-menu__title { background: linear-gradient(90deg, rgba(168, 85, 247, 0.30) 0%, rgba(124, 58, 237, 0.16) 100%) !important; color: #ffffff !important; font-weight: 700 !important; @@ -1043,110 +1299,161 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } text-shadow: none !important; } -/* 子菜单 active 区分(左条更细更柔和) */ -:root[data-theme="fame-lavender"] .aside .el-menu .el-menu-item.is-active { +/* ????active ????????????*/ +:root[data-shell="outpost"] .aside .el-menu .el-menu-item.is-active { background: linear-gradient(90deg, rgba(168, 85, 247, 0.22) 0%, transparent 100%) !important; box-shadow: inset 2px 0 0 #a855f7 !important; } -/* 顶部 header:白色卡片质感 */ -:root[data-theme="fame-lavender"] .header { +/* outpost-light white sidebar wins over purple shell nav colors */ +:root[data-shell="outpost"][data-theme="outpost-light"] .aside { + background: #ffffff !important; + border-right: 1px solid #e5e7eb !important; + box-shadow: 1px 0 0 rgba(15, 23, 42, 0.04) !important; +} +:root[data-shell="outpost"][data-theme="outpost-light"] .aside .logo { + border-bottom-color: #e5e7eb !important; + background: #ffffff !important; +} +:root[data-shell="outpost"][data-theme="outpost-light"] .aside .logo-img-full, +:root[data-shell="outpost"][data-theme="outpost-light"] .aside .logo-img-small { + filter: brightness(0) saturate(100%) invert(27%) sepia(86%) saturate(2400%) hue-rotate(248deg) brightness(0.95); +} +:root[data-shell="outpost"][data-theme="outpost-light"] .aside .logo-title-zh { + background: none !important; + -webkit-background-clip: initial !important; + background-clip: initial !important; + -webkit-text-fill-color: #7c3aed !important; + color: #7c3aed !important; +} +:root[data-shell="outpost"][data-theme="outpost-light"] .aside .el-menu-item, +:root[data-shell="outpost"][data-theme="outpost-light"] .aside .el-sub-menu__title { + color: #475569 !important; + background: transparent !important; +} +:root[data-shell="outpost"][data-theme="outpost-light"] .aside .el-menu-item:hover, +:root[data-shell="outpost"][data-theme="outpost-light"] .aside .el-sub-menu__title:hover { + background: #f8fafc !important; + color: #0f172a !important; +} +:root[data-shell="outpost"][data-theme="outpost-light"] .aside .el-menu-item.is-active, +:root[data-shell="outpost"][data-theme="outpost-light"] .aside .el-sub-menu.is-active > .el-sub-menu__title { + background: #f5f3ff !important; + color: #7c3aed !important; + box-shadow: inset 3px 0 0 #7c3aed !important; + text-shadow: none !important; +} +:root[data-shell="outpost"][data-theme="outpost-light"] .aside .el-menu .el-menu-item.is-active { + background: #f5f3ff !important; + box-shadow: inset 2px 0 0 #7c3aed !important; + color: #7c3aed !important; +} +:root[data-shell="outpost"][data-theme="outpost-light"] .aside .el-sub-menu .el-menu { + background: #f8fafc !important; +} +:root[data-shell="outpost"][data-theme="outpost-light"] .header { + border-bottom-color: #e5e7eb !important; + box-shadow: none !important; +} + +/* ?? header????????*/ +:root[data-shell="outpost"] .header { background: #fff !important; border-bottom: 1px solid #ebe5f4 !important; backdrop-filter: none !important; -webkit-backdrop-filter: none !important; box-shadow: 0 1px 6px rgba(45, 27, 105, 0.05) !important; } -:root[data-theme="fame-lavender"] .header::after { display: none !important; } -/* 会话 14:原规则误用 Vue scoped 专属的 :deep() 伪类写在全局 css 里,浏览器不识别 → 整条规则 - * 被丢弃,AppShell.vue scoped 中的白色面包屑文字在 fame-lavender 白底 header 上完全看不见。 - * 这里去掉 :deep(),直接用普通后代选择器;特异性 (0,4,0) + !important 足以覆盖 scoped 的 (0,2,0)。 - * 同时补上面包屑分隔符 "/" 的色,原默认是 rgba(255,255,255,.35),在白底上也不可见。 */ -:root[data-theme="fame-lavender"] .header .el-breadcrumb__inner { color: #4a3d6e !important; font-weight: 500; } -:root[data-theme="fame-lavender"] .header .el-breadcrumb__item:last-child .el-breadcrumb__inner { +:root[data-shell="outpost"] .header::after { display: none !important; } +/* ?? 14?????? Vue scoped ????:deep() ?????? css ???????? ?????? + * ????AppShell.vue scoped ?????????? fame-lavender ?? header ???????? + * ???? :deep()????????????????(0,4,0) + !important ???? scoped ??(0,2,0)?? + * ?????????? "/" ????????rgba(255,255,255,.35)???????????*/ +:root[data-shell="outpost"] .header .el-breadcrumb__inner { color: #4a3d6e !important; font-weight: 500; } +:root[data-shell="outpost"] .header .el-breadcrumb__item:last-child .el-breadcrumb__inner { color: #7c3aed !important; font-weight: 700; } -:root[data-theme="fame-lavender"] .header .el-breadcrumb__separator { color: #a8a0c0 !important; } -:root[data-theme="fame-lavender"] .header .el-breadcrumb__inner:hover { color: #7c3aed !important; } -:root[data-theme="fame-lavender"] .header .icon-btn { +:root[data-shell="outpost"] .header .el-breadcrumb__separator { color: #a8a0c0 !important; } +:root[data-shell="outpost"] .header .el-breadcrumb__inner:hover { color: #7c3aed !important; } +:root[data-shell="outpost"] .header .icon-btn { border-color: #ebe5f4 !important; color: #7c3aed !important; background: #f8f4fc !important; } -:root[data-theme="fame-lavender"] .header .icon-btn:hover { +:root[data-shell="outpost"] .header .icon-btn:hover { background: #ede9fe !important; border-color: #c4b5fd !important; color: #5b21b6 !important; } -:root[data-theme="fame-lavender"] .header .runmode-tag { +:root[data-shell="outpost"] .header .runmode-tag { background: #f5f3ff !important; border-color: #ddd6fe !important; color: #5b21b6 !important; } -:root[data-theme="fame-lavender"] .header .runmode-tag.WebEnabled { +:root[data-shell="outpost"] .header .runmode-tag.WebEnabled { background: #ecfdf5 !important; border-color: #bbf7d0 !important; color: #047857 !important; } -/* 会话 N+2:补 WebOnly 适配。原默认深主题 .runmode-tag.WebOnly 用 var(--mg-accent) 浅紫白字, - 在 fame-lavender 白色 header 上跟背景同色 → 完全看不见。这里强制为「紫色描边 + 深紫字」。 */ -:root[data-theme="fame-lavender"] .header .runmode-tag.WebOnly { +/* ?? N+2?? WebOnly ??????????.runmode-tag.WebOnly ??var(--mg-accent) ?????? + ??fame-lavender ?? header ?????? ???????????????????+ ??????*/ +:root[data-shell="outpost"] .header .runmode-tag.WebOnly { background: #ede9fe !important; border-color: #c4b5fd !important; color: #6d28d9 !important; } -/* 会话 N+2:header 内 ScopeSwitcher (el-radio-button) 在 fame-lavender 白底下的适配。 - * 默认深主题下 .mg-content .el-radio-button 已配深底白字,但 header 不在 .mg-content 里, - * 所以 fame-lavender 切到白底 header 时 element-plus 默认样式 (#fff 底 + #606266 字) 接管, - * 看起来"灰色椭圆 + 几乎不可读" —— 这里强制改成紫色描边 + 深紫字,激活态紫底白字。 */ -:root[data-theme="fame-lavender"] .header .el-radio-button__inner { +/* ?? N+2?header ??ScopeSwitcher (el-radio-button) ??fame-lavender ???????? + * ?????? .mg-content .el-radio-button ???????? header ?? .mg-content ?? + * ???fame-lavender ???? header ??element-plus ???? (#fff ??+ #606266 ?? ???? + * ???????? + ?????? ????????????? + ?????????????*/ +:root[data-shell="outpost"] .header .el-radio-button__inner { background: #fff !important; border-color: #ddd6fe !important; color: #5b21b6 !important; font-weight: 500; } -:root[data-theme="fame-lavender"] .header .el-radio-button__inner:hover { +:root[data-shell="outpost"] .header .el-radio-button__inner:hover { color: #6d28d9 !important; border-color: #c4b5fd !important; background: #f5f3ff !important; } -:root[data-theme="fame-lavender"] .header .el-radio-button.is-active .el-radio-button__inner { +:root[data-shell="outpost"] .header .el-radio-button.is-active .el-radio-button__inner { background: #7c3aed !important; border-color: #7c3aed !important; color: #ffffff !important; box-shadow: 0 2px 6px rgba(124, 58, 237, 0.25); } -:root[data-theme="fame-lavender"] .header .user-link { +:root[data-shell="outpost"] .header .user-link { background: #f8f4fc !important; border-color: #ebe5f4 !important; color: #2d1b69 !important; } -:root[data-theme="fame-lavender"] .header .user-link:hover { +:root[data-shell="outpost"] .header .user-link:hover { background: #ede9fe !important; border-color: #c4b5fd !important; } -:root[data-theme="fame-lavender"] .header .user-name { color: #2d1b69 !important; } +:root[data-shell="outpost"] .header .user-name { color: #2d1b69 !important; } -/* 主内容区:纯净紫白底 + 高对比深字(v2 文字层级清晰化) */ -:root[data-theme="fame-lavender"] .main, -:root[data-theme="fame-lavender"] .mg-content { +/* ???????????+ ??????v2 ???????? */ +:root[data-shell="outpost"] .main, +:root[data-shell="outpost"] .mg-content { background: transparent !important; color: #1a0f3d !important; } -:root[data-theme="fame-lavender"] .mg-content h1, -:root[data-theme="fame-lavender"] .mg-content h2, -:root[data-theme="fame-lavender"] .mg-content h3 { +:root[data-shell="outpost"] .mg-content h1, +:root[data-shell="outpost"] .mg-content h2, +:root[data-shell="outpost"] .mg-content h3 { color: #1a0f3d !important; font-weight: 700; } -:root[data-theme="fame-lavender"] .mg-content p { color: #4a3d6e !important; } -:root[data-theme="fame-lavender"] .mg-content small, -:root[data-theme="fame-lavender"] .mg-content .text-secondary { color: #7a6b9a !important; } +:root[data-shell="outpost"] .mg-content p { color: #4a3d6e !important; } +:root[data-shell="outpost"] .mg-content small, +:root[data-shell="outpost"] .mg-content .text-secondary { color: #7a6b9a !important; } /* footer */ -:root[data-theme="fame-lavender"] .footer { +:root[data-shell="outpost"] .footer { background: rgba(255, 255, 255, 0.7) !important; border-top: 1px solid #ebe5f4 !important; backdrop-filter: none !important; @@ -1154,8 +1461,8 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } color: #909399 !important; } -/* el-card:白底紫描边 + 双层阴影(紫色阴影更显品牌) */ -:root[data-theme="fame-lavender"] .mg-content .el-card { +/* el-card?????? + ?????????????? */ +:root[data-shell="outpost"] .mg-content .el-card { background: #ffffff !important; border: 1px solid #e2dbf0 !important; border-radius: 14px !important; @@ -1167,8 +1474,8 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } color: #1a0f3d !important; overflow: hidden; } -:root[data-theme="fame-lavender"] .mg-content .el-card::before { display: none !important; } -:root[data-theme="fame-lavender"] .mg-content .el-card:hover { +:root[data-shell="outpost"] .mg-content .el-card::before { display: none !important; } +:root[data-shell="outpost"] .mg-content .el-card:hover { background: #ffffff !important; border-color: #c4b5fd !important; box-shadow: @@ -1176,25 +1483,25 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } 0 18px 40px rgba(108, 71, 200, 0.16) !important; transform: translateY(-2px) !important; } -:root[data-theme="fame-lavender"] .mg-content .el-card .el-card { +:root[data-shell="outpost"] .mg-content .el-card .el-card { background: #faf7fd !important; border-color: #f0eaf6 !important; box-shadow: none !important; } -:root[data-theme="fame-lavender"] .mg-content .el-card__header { +:root[data-shell="outpost"] .mg-content .el-card__header { background: #faf7fd !important; border-bottom: 1px solid #e8e1f0 !important; color: #1a0f3d !important; font-weight: 600; } -:root[data-theme="fame-lavender"] .mg-content .el-card__body { +:root[data-shell="outpost"] .mg-content .el-card__body { background: transparent !important; color: #1a0f3d !important; } -/* KPI 玻璃卡片:浅底化 */ -:root[data-theme="fame-lavender"] .mg-content .kpi-row .el-statistic, -:root[data-theme="fame-lavender"] .mg-content .kpi-card { +/* KPI ???????? */ +:root[data-shell="outpost"] .mg-content .kpi-row .el-statistic, +:root[data-shell="outpost"] .mg-content .kpi-card { background: #fff !important; border: 1px solid #e2dbf0 !important; border-radius: 12px !important; @@ -1205,8 +1512,8 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } -webkit-backdrop-filter: none !important; padding: 16px 18px !important; } -:root[data-theme="fame-lavender"] .mg-content .kpi-row .el-statistic:hover, -:root[data-theme="fame-lavender"] .mg-content .kpi-card:hover { +:root[data-shell="outpost"] .mg-content .kpi-row .el-statistic:hover, +:root[data-shell="outpost"] .mg-content .kpi-card:hover { background: #fff !important; border-color: #c4b5fd !important; box-shadow: @@ -1214,9 +1521,9 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } 0 14px 32px rgba(108, 71, 200, 0.15) !important; transform: translateY(-2px) !important; } -:root[data-theme="fame-lavender"] .mg-content .el-statistic__head { color: #4a3d6e !important; font-weight: 500; } -:root[data-theme="fame-lavender"] .mg-content .el-statistic__number, -:root[data-theme="fame-lavender"] .mg-content .el-statistic__content { +:root[data-shell="outpost"] .mg-content .el-statistic__head { color: #4a3d6e !important; font-weight: 500; } +:root[data-shell="outpost"] .mg-content .el-statistic__number, +:root[data-shell="outpost"] .mg-content .el-statistic__content { background: none !important; -webkit-background-clip: initial !important; background-clip: initial !important; @@ -1227,8 +1534,8 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } font-weight: 700; } -/* el-table:浅底高对比 + 紫色 hover */ -:root[data-theme="fame-lavender"] .mg-content .el-table { +/* el-table?????? + ?? hover */ +:root[data-shell="outpost"] .mg-content .el-table { --el-table-bg-color: #ffffff; --el-table-tr-bg-color: #ffffff; --el-table-header-bg-color: #faf7fd; @@ -1240,207 +1547,249 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } --el-fill-color-light: #faf7fd; color: #1a0f3d !important; } -:root[data-theme="fame-lavender"] .mg-content .el-table, -:root[data-theme="fame-lavender"] .mg-content .el-table tr { +:root[data-shell="outpost"] .mg-content .el-table, +:root[data-shell="outpost"] .mg-content .el-table tr { background: #ffffff !important; } -:root[data-theme="fame-lavender"] .mg-content .el-table th.el-table__cell { +:root[data-shell="outpost"] .mg-content .el-table th.el-table__cell { background: #faf7fd !important; color: #1a0f3d !important; border-bottom-color: #e8e1f0 !important; font-weight: 600; } -:root[data-theme="fame-lavender"] .mg-content .el-table td.el-table__cell { +:root[data-shell="outpost"] .mg-content .el-table td.el-table__cell { background: #ffffff !important; color: #1a0f3d !important; border-bottom-color: #f0eaf6 !important; } -:root[data-theme="fame-lavender"] .mg-content .el-table--striped .el-table__body tr:nth-child(2n) td.el-table__cell { +:root[data-shell="outpost"] .mg-content .el-table--striped .el-table__body tr:nth-child(2n) td.el-table__cell { background: #faf7fd !important; } -:root[data-theme="fame-lavender"] .mg-content .el-table tr:hover > td.el-table__cell { +:root[data-shell="outpost"] .mg-content .el-table tr:hover > td.el-table__cell { background: #f5f3ff !important; } -/* el-input / el-textarea / el-select:浅底 + 深字 + 焦点紫光晕 */ -:root[data-theme="fame-lavender"] .mg-content .el-input__wrapper, -:root[data-theme="fame-lavender"] .mg-content .el-textarea__inner, -:root[data-theme="fame-lavender"] .mg-content .el-select .el-input__wrapper { +/* el-input / el-textarea / el-select????+ ?? + ??????*/ +:root[data-shell="outpost"] .mg-content .el-input__wrapper, +:root[data-shell="outpost"] .mg-content .el-textarea__inner, +:root[data-shell="outpost"] .mg-content .el-select .el-input__wrapper { background: #ffffff !important; box-shadow: 0 0 0 1px #e0d4f5 inset !important; } -:root[data-theme="fame-lavender"] .mg-content .el-input__wrapper:hover { +:root[data-shell="outpost"] .mg-content .el-input__wrapper:hover { box-shadow: 0 0 0 1px #c4b5fd inset !important; } -:root[data-theme="fame-lavender"] .mg-content .el-input__wrapper.is-focus { +:root[data-shell="outpost"] .mg-content .el-input__wrapper.is-focus { box-shadow: 0 0 0 1px #7c3aed inset, 0 0 0 3px rgba(124, 58, 237, 0.15) !important; } -:root[data-theme="fame-lavender"] .mg-content .el-input__inner, -:root[data-theme="fame-lavender"] .mg-content .el-textarea__inner { color: #1a0f3d !important; font-weight: 500; } -:root[data-theme="fame-lavender"] .mg-content .el-input__inner::placeholder, -:root[data-theme="fame-lavender"] .mg-content .el-textarea__inner::placeholder { color: #a8a0c0 !important; } -:root[data-theme="fame-lavender"] .mg-content .el-form-item__label { color: #4a3d6e !important; font-weight: 500; } +:root[data-shell="outpost"] .mg-content .el-input__inner, +:root[data-shell="outpost"] .mg-content .el-textarea__inner { color: #1a0f3d !important; font-weight: 500; } +:root[data-shell="outpost"] .mg-content .el-input__inner::placeholder, +:root[data-shell="outpost"] .mg-content .el-textarea__inner::placeholder { color: #a8a0c0 !important; } +:root[data-shell="outpost"] .mg-content .el-form-item__label { color: #4a3d6e !important; font-weight: 500; } -/* el-tabs:紫色活跃 + 高对比 */ -/* 浅色主题下 el-tabs 容器内不再继承玻璃主题强制白字,恢复深色 primary, - 避免 .mg-content .el-tabs { --el-text-color-primary: #fff } 把内部 h2 / label - 一并染白后出现"白底白字"(车辆管理标题、其他 tabs 内 .ref-mgr-title 同理)。 */ -:root[data-theme="fame-lavender"] .mg-content .el-tabs { +/* el-tabs??????+ ????*/ +/* ??????el-tabs ???????????????????? primary?? + ?? .mg-content .el-tabs { --el-text-color-primary: #fff } ????h2 / label + ???????"????"???????????tabs ??.ref-mgr-title ?????*/ +:root[data-shell="outpost"] .mg-content .el-tabs { --el-text-color-primary: #2d1b69 !important; --el-text-color-regular: #303133 !important; } -:root[data-theme="fame-lavender"] .mg-content .el-tabs__item { color: #4a3d6e !important; font-weight: 500; } -:root[data-theme="fame-lavender"] .mg-content .el-tabs__item:hover { color: #7c3aed !important; } -:root[data-theme="fame-lavender"] .mg-content .el-tabs__item.is-active { +:root[data-shell="outpost"] .mg-content .el-tabs__item { color: #4a3d6e !important; font-weight: 500; } +:root[data-shell="outpost"] .mg-content .el-tabs__item:hover { color: #7c3aed !important; } +:root[data-shell="outpost"] .mg-content .el-tabs__item.is-active { color: #7c3aed !important; font-weight: 700; } -/* 兜底:element-plus 内部 css 改版后曾出现「.el-tabs__item 不在 .mg-content 路径下」的场景, - 再加一组不带 .mg-content 限定的规则,避免在 dialog / drawer 中弹出的 tabs 仍然白字。 */ -:root[data-theme="fame-lavender"] .el-tabs__item { color: #4a3d6e !important; } -:root[data-theme="fame-lavender"] .el-tabs__item:hover { color: #7c3aed !important; } -:root[data-theme="fame-lavender"] .el-tabs__item.is-active { color: #7c3aed !important; font-weight: 700; } -:root[data-theme="fame-lavender"] .mg-content .el-tabs__active-bar { +/* ???element-plus ?? css ????????el-tabs__item ?? .mg-content ????????? + ???????.mg-content ??????????dialog / drawer ???? tabs ??????*/ +:root[data-shell="outpost"] .el-tabs__item { color: #4a3d6e !important; } +:root[data-shell="outpost"] .el-tabs__item:hover { color: #7c3aed !important; } +:root[data-shell="outpost"] .el-tabs__item.is-active { color: #7c3aed !important; font-weight: 700; } +:root[data-shell="outpost"] .mg-content .el-tabs__active-bar { background-color: #7c3aed !important; height: 3px !important; border-radius: 2px; } -:root[data-theme="fame-lavender"] .mg-content .el-tabs__nav-wrap::after { background-color: #e8e1f0 !important; } +:root[data-shell="outpost"] .mg-content .el-tabs__nav-wrap::after { background-color: #e8e1f0 !important; } -/* ───────────────────────────────────────────────────────────────────────── - * ReflectionManagerPanel / CarPanelView 等 tabs 内长标题(会话 N+2 UI 修复) - * 问题:组件 scoped CSS 写 `color: var(--el-text-color-primary, #fff)`, - * 但在 el-tab-pane 嵌套层级里变量没下传,回退到 #fff → 浅紫背景白字看不清。 - * 解法:在 fame-lavender 主题下直接给关键文字类「深紫色 #2d1b69」+ !important, - * 优先级压过 scoped css。同时把面板卡片底色从深紫透明改成白色,对比足够。 - * ───────────────────────────────────────────────────────────────────────── */ -:root[data-theme="fame-lavender"] .mg-content .ref-mgr-page, -:root[data-theme="fame-lavender"] .mg-content .ref-mgr-title, -:root[data-theme="fame-lavender"] .mg-content .field-section-title, -:root[data-theme="fame-lavender"] .mg-content .detail-name { +/* ????????????????????????????????????????????????????????????????????????? + * ReflectionManagerPanel / CarPanelView ??tabs ????????N+2 UI ???? + * ??????scoped CSS ??`color: var(--el-text-color-primary, #fff)`?? + * ?? el-tab-pane ???????????????#fff ????????????? + * ???? fame-lavender ??????????????? #2d1b69?? !important?? + * ??????scoped css?????????????????????????? + * ????????????????????????????????????????????????????????????????????????? */ +:root[data-shell="outpost"] .mg-content .ref-mgr-page, +:root[data-shell="outpost"] .mg-content .ref-mgr-title, +:root[data-shell="outpost"] .mg-content .field-section-title, +:root[data-shell="outpost"] .mg-content .detail-name { color: #2d1b69 !important; } -:root[data-theme="fame-lavender"] .mg-content .ref-mgr-title { font-weight: 700; } -:root[data-theme="fame-lavender"] .mg-content .detail-id, -:root[data-theme="fame-lavender"] .mg-content .ref-type-asm, -:root[data-theme="fame-lavender"] .mg-content .field-empty { +:root[data-shell="outpost"] .mg-content .ref-mgr-title { font-weight: 700; } +:root[data-shell="outpost"] .mg-content .detail-id, +:root[data-shell="outpost"] .mg-content .ref-type-asm, +:root[data-shell="outpost"] .mg-content .field-empty { color: #7a6b9a !important; } -:root[data-theme="fame-lavender"] .mg-content .ref-mgr-list-card, -:root[data-theme="fame-lavender"] .mg-content .ref-mgr-detail-card { - background: #ffffff !important; - border: 1px solid rgba(124, 58, 237, 0.16) !important; - box-shadow: 0 8px 24px rgba(124, 58, 237, 0.06) !important; +:root[data-shell="outpost"] .mg-content .ref-mgr-list-card, +:root[data-shell="outpost"] .mg-content .ref-mgr-detail-card { + background: #fffefd !important; + border: 1px solid rgba(40, 33, 58, 0.10) !important; + box-shadow: none !important; + border-radius: 8px !important; } -:root[data-theme="fame-lavender"] .mg-content .ref-mgr-header, -:root[data-theme="fame-lavender"] .mg-content .detail-header { +:root[data-shell="outpost"] .mg-content .ref-mgr-count, +:root[data-shell="outpost"] .mg-content .col-mono, +:root[data-shell="outpost"] .mg-content .col-type { + color: #756d85 !important; +} +:root[data-shell="outpost"] .mg-content .ref-chip { + background: #fffefd !important; + border-color: rgba(40, 33, 58, 0.12) !important; + color: #756d85 !important; +} +:root[data-shell="outpost"] .mg-content .ref-chip b { color: #28213a !important; } +:root[data-shell="outpost"] .mg-content .ref-chip.is-active { + color: #7c3aed !important; + border-color: rgba(124, 58, 237, 0.4) !important; + background: rgba(124, 58, 237, 0.08) !important; +} +:root[data-shell="outpost"] .mg-content .plugin-list-card { + background: #fffefd !important; + border: 1px solid rgba(40, 33, 58, 0.10) !important; + box-shadow: none !important; +} +:root[data-shell="outpost"] .mg-content .ref-mgr-header, +:root[data-shell="outpost"] .mg-content .detail-header { border-color: rgba(124, 58, 237, 0.18) !important; } -:root[data-theme="fame-lavender"] .mg-content .field-section { +:root[data-shell="outpost"] .mg-content .field-section { color: #303133; } -:root[data-theme="fame-lavender"] .mg-content .status-value { +:root[data-shell="outpost"] .mg-content .status-value { color: #303133 !important; } -/* el-tag:浅紫 */ -:root[data-theme="fame-lavender"] .mg-content .el-tag { +/* el-tag????*/ +:root[data-shell="outpost"] .mg-content .el-tag { background: #ede9fe !important; color: #5b21b6 !important; border-color: #ddd6fe !important; } -:root[data-theme="fame-lavender"] .mg-content .el-tag--primary { +:root[data-shell="outpost"] .mg-content .el-tag--primary { background: #ede9fe !important; color: #5b21b6 !important; border-color: #c4b5fd !important; } -:root[data-theme="fame-lavender"] .mg-content .el-tag--success { +:root[data-shell="outpost"] .mg-content .el-tag--success { background: #ecfdf5 !important; color: #047857 !important; border-color: #bbf7d0 !important; } -:root[data-theme="fame-lavender"] .mg-content .el-tag--warning { +:root[data-shell="outpost"] .mg-content .el-tag--warning { background: #fffbeb !important; color: #b45309 !important; border-color: #fde68a !important; } -:root[data-theme="fame-lavender"] .mg-content .el-tag--danger { +:root[data-shell="outpost"] .mg-content .el-tag--danger { background: #fef2f2 !important; color: #b91c1c !important; border-color: #fecaca !important; } -:root[data-theme="fame-lavender"] .mg-content .el-tag--info { +:root[data-shell="outpost"] .mg-content .el-tag--info { background: #f3f4f6 !important; color: #4b5563 !important; border-color: #e5e7eb !important; } /* el-descriptions */ -:root[data-theme="fame-lavender"] .mg-content .el-descriptions { +:root[data-shell="outpost"] .mg-content .el-descriptions { --el-text-color-primary: #2d1b69; --el-text-color-regular: #606266; --el-border-color-lighter: #ebe5f4; --el-fill-color-blank: #fff; color: #303133 !important; } -:root[data-theme="fame-lavender"] .mg-content .el-descriptions__label, -:root[data-theme="fame-lavender"] .mg-content .el-descriptions__cell.is-bordered-label { +:root[data-shell="outpost"] .mg-content .el-descriptions__label, +:root[data-shell="outpost"] .mg-content .el-descriptions__cell.is-bordered-label { background: #faf7fd !important; color: #606266 !important; border-color: #ebe5f4 !important; } -:root[data-theme="fame-lavender"] .mg-content .el-descriptions__content, -:root[data-theme="fame-lavender"] .mg-content .el-descriptions__cell.is-bordered-content { +:root[data-shell="outpost"] .mg-content .el-descriptions__content, +:root[data-shell="outpost"] .mg-content .el-descriptions__cell.is-bordered-content { background: #fff !important; color: #303133 !important; border-color: #ebe5f4 !important; } -:root[data-theme="fame-lavender"] .mg-content .el-descriptions__title { color: #2d1b69 !important; } +:root[data-shell="outpost"] .mg-content .el-descriptions__title { color: #2d1b69 !important; } -/* el-alert / collapse / radio / checkbox 浅化 */ -:root[data-theme="fame-lavender"] .mg-content .el-alert { +/* el-alert / collapse / radio / checkbox ?? */ +:root[data-shell="outpost"] .mg-content .el-alert { background: #faf7fd !important; border: 1px solid #ebe5f4 !important; color: #303133 !important; } -:root[data-theme="fame-lavender"] .mg-content .el-alert__title, -:root[data-theme="fame-lavender"] .mg-content .el-alert__description { color: #303133 !important; } +:root[data-shell="outpost"] .mg-content .el-alert__title, +:root[data-shell="outpost"] .mg-content .el-alert__description { color: #303133 !important; } -:root[data-theme="fame-lavender"] .mg-content .el-collapse { +:root[data-shell="outpost"] .mg-content .el-collapse { border-color: #ebe5f4 !important; --el-collapse-header-text-color: #2d1b69; --el-collapse-content-text-color: #303133; } -:root[data-theme="fame-lavender"] .mg-content .el-collapse-item__header, -:root[data-theme="fame-lavender"] .mg-content .el-collapse-item__wrap { +:root[data-shell="outpost"] .mg-content .el-collapse-item__header, +:root[data-shell="outpost"] .mg-content .el-collapse-item__wrap { background: #fff !important; border-color: #ebe5f4 !important; color: #303133 !important; } -:root[data-theme="fame-lavender"] .mg-content .el-radio__label, -:root[data-theme="fame-lavender"] .mg-content .el-checkbox__label { color: #303133 !important; } -:root[data-theme="fame-lavender"] .mg-content .el-radio__inner, -:root[data-theme="fame-lavender"] .mg-content .el-checkbox__inner { +:root[data-shell="outpost"] .mg-content .el-radio__label, +:root[data-shell="outpost"] .mg-content .el-checkbox__label { color: #303133 !important; } +:root[data-shell="outpost"] .mg-content .el-radio__inner, +:root[data-shell="outpost"] .mg-content .el-checkbox__inner { + background: #fff !important; + border-color: #7c3aed !important; + border-width: 1.5px !important; +} +/* ???????????? !important???????????????????????*/ +:root[data-shell="outpost"] .mg-content .el-checkbox__input.is-checked .el-checkbox__inner, +:root[data-shell="outpost"] .mg-content .el-checkbox__input.is-indeterminate .el-checkbox__inner { + background: #7c3aed !important; + border-color: #7c3aed !important; +} +:root[data-shell="outpost"] .mg-content .el-checkbox__input.is-checked .el-checkbox__inner::after { + border-color: #fff !important; +} +:root[data-shell="outpost"] .mg-content .el-checkbox__input.is-indeterminate .el-checkbox__inner::before { + background-color: #fff !important; +} +:root[data-shell="outpost"] .mg-content .el-radio__input.is-checked .el-radio__inner { + background: #7c3aed !important; + border-color: #7c3aed !important; +} +:root[data-shell="outpost"] .mg-content .el-radio__input.is-checked .el-radio__inner::after { background: #fff !important; - border-color: #c4b5fd !important; } -:root[data-theme="fame-lavender"] .mg-content .el-radio-button__inner { +:root[data-shell="outpost"] .mg-content .el-radio-button__inner { background: #fff !important; border-color: #ddd6fe !important; color: #5b21b6 !important; } -:root[data-theme="fame-lavender"] .mg-content .el-radio-button.is-active .el-radio-button__inner { +:root[data-shell="outpost"] .mg-content .el-radio-button.is-active .el-radio-button__inner { background: #7c3aed !important; border-color: #7c3aed !important; color: #fff !important; } -/* el-button--primary:紫色稳重 + 高对比白字(去霓虹动画) */ -:root[data-theme="fame-lavender"] .el-button--primary { +/* el-button--primary??????+ ???????????? */ +:root[data-shell="outpost"] .el-button--primary { background: #7c3aed !important; border: 1px solid #7c3aed !important; color: #ffffff !important; @@ -1449,8 +1798,8 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } 0 1px 2px rgba(45, 27, 105, 0.08), 0 2px 6px rgba(124, 58, 237, 0.22) !important; } -:root[data-theme="fame-lavender"] .el-button--primary::after { display: none !important; } -:root[data-theme="fame-lavender"] .el-button--primary:hover { +:root[data-shell="outpost"] .el-button--primary::after { display: none !important; } +:root[data-shell="outpost"] .el-button--primary:hover { background: #6d28d9 !important; border-color: #6d28d9 !important; box-shadow: @@ -1458,20 +1807,20 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } 0 4px 14px rgba(124, 58, 237, 0.32) !important; transform: translateY(-1px) !important; } -:root[data-theme="fame-lavender"] .el-button--primary:active { +:root[data-shell="outpost"] .el-button--primary:active { background: #5b21b6 !important; border-color: #5b21b6 !important; transform: translateY(0) !important; } -/* default 按钮:白底紫描边 + hover 浅紫底 */ -:root[data-theme="fame-lavender"] .mg-content .el-button:not(.el-button--primary):not(.el-button--success):not(.el-button--warning):not(.el-button--danger):not(.el-button--text) { +/* default ???????? + hover ????*/ +:root[data-shell="outpost"] .mg-content .el-button:not(.el-button--primary):not(.el-button--success):not(.el-button--warning):not(.el-button--danger):not(.el-button--text) { background: #ffffff !important; border-color: #ddd6fe !important; color: #5b21b6 !important; font-weight: 500; } -:root[data-theme="fame-lavender"] .mg-content .el-button:not(.el-button--primary):not(.el-button--success):not(.el-button--warning):not(.el-button--danger):not(.el-button--text):hover { +:root[data-shell="outpost"] .mg-content .el-button:not(.el-button--primary):not(.el-button--success):not(.el-button--warning):not(.el-button--danger):not(.el-button--text):hover { background: #f5f3ff !important; border-color: #a78bfa !important; color: #5b21b6 !important; @@ -1479,13 +1828,13 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } } /* el-progress */ -:root[data-theme="fame-lavender"] .mg-content .el-progress-bar__outer { background: #ede9fe !important; } -:root[data-theme="fame-lavender"] .mg-content .el-progress-bar__inner { +:root[data-shell="outpost"] .mg-content .el-progress-bar__outer { background: #ede9fe !important; } +:root[data-shell="outpost"] .mg-content .el-progress-bar__inner { background: linear-gradient(90deg, #7c3aed 0%, #a855f7 100%) !important; } -/* el-pagination 浅化 */ -:root[data-theme="fame-lavender"] .mg-content .el-pagination { +/* el-pagination ?? */ +:root[data-shell="outpost"] .mg-content .el-pagination { --el-pagination-bg-color: #fff; --el-pagination-button-bg-color: #faf7fd; --el-pagination-button-color: #2d1b69; @@ -1493,46 +1842,46 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } color: #606266 !important; } -/* el-dropdown 菜单 浅化(影响 header 用户菜单) */ -:root[data-theme="fame-lavender"] .el-dropdown-menu { +/* el-dropdown ?? ??????header ??????*/ +:root[data-shell="outpost"] .el-dropdown-menu { background: #fff !important; backdrop-filter: none !important; border: 1px solid #ebe5f4 !important; box-shadow: 0 6px 16px rgba(45, 27, 105, 0.10) !important; } -:root[data-theme="fame-lavender"] .el-dropdown-menu__item { +:root[data-shell="outpost"] .el-dropdown-menu__item { color: #303133 !important; } -:root[data-theme="fame-lavender"] .el-dropdown-menu__item:hover { +:root[data-shell="outpost"] .el-dropdown-menu__item:hover { background: #f5f3ff !important; color: #7c3aed !important; } /* el-switch */ -:root[data-theme="fame-lavender"] .mg-content .el-switch.is-checked .el-switch__core { +:root[data-shell="outpost"] .mg-content .el-switch.is-checked .el-switch__core { background: #7c3aed !important; border-color: #7c3aed !important; } -/* el-dialog 上的 h2 */ -:root[data-theme="fame-lavender"] .el-dialog h2 { color: #2d1b69 !important; } -:root[data-theme="fame-lavender"] .el-dialog { background: #fff !important; } -:root[data-theme="fame-lavender"] .el-dialog__title { color: #2d1b69 !important; } -:root[data-theme="fame-lavender"] .el-dialog__body { color: #303133 !important; } +/* el-dialog ?? h2 */ +:root[data-shell="outpost"] .el-dialog h2 { color: #2d1b69 !important; } +:root[data-shell="outpost"] .el-dialog { background: #fff !important; } +:root[data-shell="outpost"] .el-dialog__title { color: #2d1b69 !important; } +:root[data-shell="outpost"] .el-dialog__body { color: #303133 !important; } -/* 滚动条:紫色半透明(与 FAME 一致) */ -:root[data-theme="fame-lavender"] ::-webkit-scrollbar-thumb { +/* ??????????? FAME ??? */ +:root[data-shell="outpost"] ::-webkit-scrollbar-thumb { background: rgba(124, 58, 237, 0.25); } -:root[data-theme="fame-lavender"] ::-webkit-scrollbar-thumb:hover { +:root[data-shell="outpost"] ::-webkit-scrollbar-thumb:hover { background: rgba(124, 58, 237, 0.45); } -/* ════════════════════════════════════════════════════════════════════ - * 通用工具类(基于 design-system tokens · 见 design-system/MASTER.md) - * ════════════════════════════════════════════════════════════════════ */ +/* ???????????????????????????????????????????????????????????????????? + * ???????? design-system tokens ? ??design-system/MASTER.md?? + * ???????????????????????????????????????????????????????????????????? */ -/* 等宽数字:KPI 数值 / 坐标 / ID / 时间戳 */ +/* ?????KPI ???/ ?? / ID / ????*/ .mg-mono, .mg-num { font-family: var(--mg-font-mono); @@ -1540,7 +1889,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } letter-spacing: 0; } -/* 状态徽章(pill 样式,胶囊状) */ +/* ?????pill ????????*/ .mg-pill { display: inline-flex; align-items: center; @@ -1579,7 +1928,7 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } border-color: rgba(var(--mg-status-idle-rgb), 0.40); } -/* 实时脉动指示点: */ +/* ???????? */ .mg-live-dot { display: inline-block; width: 8px; @@ -1610,33 +1959,36 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } 100% { transform: scale(1.8); opacity: 0; } } -/* 尊重用户的减少动画偏好 */ +/* ????????????*/ @media (prefers-reduced-motion: reduce) { .mg-live-dot::after { animation: none; } .bg-orb, .hero-orb, .hero-scene .agv-1, .hero-scene .agv-2, - .hero-scene .float-data { animation: none !important; } + .hero-scene .float-data, + .tag-dot, + .quick-item, + .quick-item.primary .quick-icon { animation: none !important; } } -/* ───────────────────────────────────────────────────────────────────────── - * fame-lavender 下 ReflectionManagerPanel 自定义按钮反差修复 +/* ????????????????????????????????????????????????????????????????????????? + * fame-lavender ??ReflectionManagerPanel ?????????? * - * 问题:组件 scoped css 把 .method-btn / .header-action-btn / .add-field-btn 写成 - * 「半透明紫底 + 白字」(rgba(170,110,250,0.30) 衬 #fff),本来是给星云紫深底主题设计的。 - * fame-lavender 切到白色卡片底后,半透明紫直接糊在白底 → 浅紫;白字糊在浅紫 - * → 对比度 ~1.5:1,"动作 / 方法" 区按钮文字几乎不可见(见会话 N+3 用户反馈截图)。 + * ??????scoped css ??.method-btn / .header-action-btn / .add-field-btn ?? + * ?????? + ????rgba(170,110,250,0.30) ??#fff)????????????????? + * fame-lavender ???????????????????????????????? + * ??????~1.5:1???? / ??" ?????????????? N+3 ????????? * - * 策略:与 fame-lavender 下 .el-button--primary 保持一致 —— - * 实色 #7c3aed 紫底 + #ffffff 白字 + 紫色双层阴影,对比度 ~6.9:1(WCAG AA 通过)。 - * 「+ 添加字段」(.add-field-btn) 偏次要等级,改为白底紫描边紫字(与 default 按钮一致)。 + * ???? fame-lavender ??.el-button--primary ???????? + * ?? #7c3aed ?? + #ffffff ?? + ?????????? ~6.9:1?WCAG AA ????? + * ?? ??????.add-field-btn) ??????????????????default ??????? * - * 特异性::root[data-theme] .mg-content .x = (0,3,0),加 !important 足以压过 Vue - * scoped css 的 .x[data-v-xxx] = (0,2,0)。 - * ───────────────────────────────────────────────────────────────────────── */ -:root[data-theme="fame-lavender"] .mg-content .method-btn, -:root[data-theme="fame-lavender"] .mg-content .header-action-btn { + * ????:root[data-theme] .mg-content .x = (0,3,0)?? !important ???? Vue + * scoped css ??.x[data-v-xxx] = (0,2,0)?? + * ????????????????????????????????????????????????????????????????????????? */ +:root[data-shell="outpost"] .mg-content .method-btn, +:root[data-shell="outpost"] .mg-content .header-action-btn { background: #7c3aed !important; border: 1px solid #7c3aed !important; color: #ffffff !important; @@ -1645,8 +1997,8 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } 0 1px 2px rgba(45, 27, 105, 0.08), 0 2px 6px rgba(124, 58, 237, 0.22) !important; } -:root[data-theme="fame-lavender"] .mg-content .method-btn:hover:not(:disabled), -:root[data-theme="fame-lavender"] .mg-content .header-action-btn:hover { +:root[data-shell="outpost"] .mg-content .method-btn:hover:not(:disabled), +:root[data-shell="outpost"] .mg-content .header-action-btn:hover { background: #6d28d9 !important; border-color: #6d28d9 !important; color: #ffffff !important; @@ -1654,166 +2006,320 @@ a:hover { color: rgba(var(--mg-accent-rgb), 0.85); } 0 2px 6px rgba(45, 27, 105, 0.12), 0 4px 14px rgba(124, 58, 237, 0.32) !important; } -:root[data-theme="fame-lavender"] .mg-content .method-btn:active:not(:disabled) { +:root[data-shell="outpost"] .mg-content .method-btn:active:not(:disabled) { background: #5b21b6 !important; border-color: #5b21b6 !important; } -:root[data-theme="fame-lavender"] .mg-content .method-btn:disabled { +:root[data-shell="outpost"] .mg-content .method-btn:disabled { background: #c4b5fd !important; border-color: #c4b5fd !important; color: #ffffff !important; box-shadow: none !important; opacity: 0.85 !important; } -:root[data-theme="fame-lavender"] .mg-content .method-btn .method-btn-icon, -:root[data-theme="fame-lavender"] .mg-content .method-btn .method-btn-spin { +:root[data-shell="outpost"] .mg-content .method-btn .method-btn-icon, +:root[data-shell="outpost"] .mg-content .method-btn .method-btn-spin { color: rgba(255, 255, 255, 0.92) !important; } -:root[data-theme="fame-lavender"] .mg-content .method-btn .method-btn-tag { +:root[data-shell="outpost"] .mg-content .method-btn .method-btn-tag { background: rgba(255, 255, 255, 0.24) !important; color: #ffffff !important; } -/* 「+ 添加字段」次级按钮:与 default 按钮同视觉等级(白底紫描边紫字),避免与 primary 等高。 */ -:root[data-theme="fame-lavender"] .mg-content .add-field-btn { +/* ?? ????????????default ???????????????????? primary ????*/ +:root[data-shell="outpost"] .mg-content .add-field-btn { background: #ffffff !important; border: 1px dashed #a78bfa !important; color: #5b21b6 !important; font-weight: 500 !important; } -:root[data-theme="fame-lavender"] .mg-content .add-field-btn:hover { +:root[data-shell="outpost"] .mg-content .add-field-btn:hover { background: #f5f3ff !important; border-color: #7c3aed !important; color: #5b21b6 !important; } +/* ????????????????????????? */ +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .prop-add-field-btn, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .add-field-btn { + background: transparent !important; + border: 1px dashed rgba(var(--mg-primary-rgb), 0.5) !important; + color: rgba(255, 255, 255, 0.88) !important; + font-weight: 600 !important; +} +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .prop-add-field-btn:hover, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .add-field-btn:hover { + background: rgba(var(--mg-primary-rgb), 0.18) !important; + border-color: var(--mg-primary) !important; + color: #fff !important; +} -/* ───────────────────────────────────────────────────────────────────────── - * fame-lavender × 地图编辑器深紫沉浸 UI(MapEditorView) - * 侧栏 / 属性面板 / 工具轨保持深紫底 + 浅字。全局浅紫规则会把 .mg-content 内 - * el-form 标签、el-tabs 等改成深紫字 (#4a3d6e),在深底上出现「深底深字」看不清。 - * ───────────────────────────────────────────────────────────────────────── */ -:root[data-theme="fame-lavender"] .mg-content .map-editor-page { +/* ????????????????????????????????????????????????????????????????????????? + * fame-lavender ? ??????????UI?MapEditorView?? + * ?? / ?????/ ???????? + ??????????? .mg-content ?? + * el-form ???el-tabs ?????? (#4a3d6e)?????????????????? + * ????????????????????????????????????????????????????????????????????????? */ +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page { --el-text-color-primary: rgba(232, 215, 245, 0.95); --el-text-color-regular: rgba(220, 200, 230, 0.88); --el-text-color-secondary: rgba(200, 180, 220, 0.72); color: rgba(232, 215, 245, 0.92); } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .el-form-item__label { +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .el-form-item__label { color: rgba(220, 200, 230, 0.9) !important; font-weight: 500; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .el-tabs { +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .el-tabs { --el-text-color-primary: rgba(232, 215, 245, 0.95) !important; --el-text-color-regular: rgba(220, 200, 240, 0.75) !important; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .el-tabs__item, -:root[data-theme="fame-lavender"] .map-editor-page .el-tabs__item { +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .el-tabs__item, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .map-editor-page .el-tabs__item { color: rgba(220, 200, 240, 0.72) !important; font-weight: 500; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .el-tabs__item:hover, -:root[data-theme="fame-lavender"] .map-editor-page .el-tabs__item:hover { +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .el-tabs__item:hover, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .map-editor-page .el-tabs__item:hover { color: rgba(240, 225, 255, 0.95) !important; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .el-tabs__item.is-active, -:root[data-theme="fame-lavender"] .map-editor-page .el-tabs__item.is-active { +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .el-tabs__item.is-active, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .map-editor-page .el-tabs__item.is-active { color: #ffffff !important; font-weight: 600; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .el-tabs__nav-wrap::after { +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .el-tabs__nav-wrap::after { background-color: rgba(255, 255, 255, 0.1) !important; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .el-tabs__active-bar { +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .el-tabs__active-bar { background: linear-gradient(90deg, rgba(170, 110, 250, 1) 0%, rgba(255, 110, 220, 1) 100%) !important; } -/* 图层 Tab:白底数据岛 + 深紫字(与属性面板输入框一致,避免白底叠浅字) */ -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .layer-table.el-table { - --el-table-bg-color: #ffffff; - --el-table-tr-bg-color: #ffffff; - --el-table-header-bg-color: #f5f3ff; - --el-table-text-color: #1a0f3d; - --el-table-header-text-color: #2d1b69; - --el-table-row-hover-bg-color: #ede9fe; - --el-table-border-color: #e0d4f5; - --el-fill-color-blank: #ffffff; - --el-fill-color-light: #faf7fd; - color: #1a0f3d !important; - background: #ffffff !important; - border-radius: 8px; +/* ?? Tab?????????????chrome ???????????*/ +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .layer-table.el-table { + --el-table-bg-color: rgba(0, 0, 0, 0.28); + --el-table-tr-bg-color: transparent; + --el-table-header-bg-color: rgba(var(--mg-primary-rgb), 0.16); + --el-table-text-color: var(--me-text); + --el-table-header-text-color: var(--me-text); + --el-table-row-hover-bg-color: rgba(var(--mg-primary-rgb), 0.14); + --el-table-border-color: var(--me-border); + --el-fill-color-blank: transparent; + --el-fill-color-light: rgba(255, 255, 255, 0.04); + color: var(--me-text) !important; + background: rgba(0, 0, 0, 0.22) !important; + border-radius: 10px; overflow: hidden; - box-shadow: 0 0 0 1px rgba(124, 58, 237, 0.14); + box-shadow: inset 0 0 0 1px var(--me-border); } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .layer-table.el-table, -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .layer-table.el-table tr, -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .layer-table .el-table__inner-wrapper { - background: #ffffff !important; +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .layer-table.el-table, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .layer-table.el-table tr, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .layer-table .el-table__inner-wrapper { + background: transparent !important; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .layer-table th.el-table__cell { - background: #f5f3ff !important; - color: #2d1b69 !important; +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .layer-table th.el-table__cell { + background: rgba(var(--mg-primary-rgb), 0.16) !important; + color: var(--me-text) !important; font-weight: 600 !important; - border-bottom-color: #e0d4f5 !important; + border-bottom-color: var(--me-border) !important; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .layer-table td.el-table__cell { - background: #ffffff !important; - color: #1a0f3d !important; +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .layer-table td.el-table__cell { + background: transparent !important; + color: var(--me-text) !important; font-weight: 500 !important; - border-bottom-color: #f0eaf6 !important; + border-bottom-color: rgba(255, 255, 255, 0.06) !important; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .layer-table .cell { - color: #1a0f3d !important; +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .layer-table .cell { + color: var(--me-text) !important; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .layer-table.el-table--striped .el-table__body tr:nth-child(2n) td.el-table__cell { - background: #faf7fd !important; +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .layer-table.el-table--striped .el-table__body tr:nth-child(2n) td.el-table__cell { + background: rgba(255, 255, 255, 0.03) !important; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .layer-table tr:hover > td.el-table__cell { - background: #ede9fe !important; +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .layer-table tr:hover > td.el-table__cell { + background: rgba(var(--mg-primary-rgb), 0.14) !important; } -/* 新建图层行:白底深字 + 占位符可读 */ -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .new-layer .el-input__inner { - color: #1a0f3d !important; +/* ?????????? */ +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .new-layer .el-input__inner { + color: var(--me-text) !important; font-weight: 500; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .new-layer .el-input__inner::placeholder { - color: #7a6b9a !important; +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .new-layer .el-input__inner::placeholder { + color: var(--me-text-muted) !important; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .new-layer .el-input-group__append .el-button { - background: #f5f3ff !important; - border-color: #ddd6fe !important; - color: #5b21b6 !important; +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .new-layer .el-input-group__append .el-button { + background: rgba(var(--mg-primary-rgb), 0.18) !important; + border-color: rgba(var(--mg-primary-rgb), 0.35) !important; + color: #fff !important; font-weight: 600 !important; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .new-layer .el-input-group__append .el-button:hover { - background: #ede9fe !important; - border-color: #a78bfa !important; - color: #5b21b6 !important; +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .new-layer .el-input-group__append .el-button:hover { + background: rgba(var(--mg-primary-rgb), 0.28) !important; + border-color: var(--mg-primary) !important; + color: #fff !important; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .el-checkbox__label { +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .el-checkbox__label { color: rgba(220, 200, 230, 0.88) !important; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .prop-card-flag, -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .prop-card-flag-text { +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .prop-card-flag, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .prop-card-flag-text { color: rgba(200, 220, 255, 0.88) !important; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .prop-card-flag.is-synced, -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .prop-card-flag.is-synced .prop-card-flag-text { +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .prop-card-flag.is-synced, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .prop-card-flag.is-synced .prop-card-flag-text { color: rgba(220, 255, 230, 0.98) !important; } -/* 属性面板内输入框仍用白底深字(与组件 scoped 设计一致),仅修正标签/Tab 等说明文字 */ -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .el-input__wrapper, -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .el-textarea__inner, -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .el-select .el-input__wrapper { +/* ?????????????Outpost ?????????? chrome ??? */ +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-input__wrapper, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-textarea__inner, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-select .el-input__wrapper, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-select__wrapper, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-input-number .el-input__wrapper { + background: rgba(0, 0, 0, 0.32) !important; + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12) !important; +} +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-input__wrapper:hover, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-select__wrapper:hover, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-select .el-input__wrapper:hover { + box-shadow: inset 0 0 0 1px rgba(var(--mg-primary-rgb), 0.5) !important; +} +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-input__wrapper.is-focus, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-select__wrapper.is-focused, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-select .el-input__wrapper.is-focus { + box-shadow: + inset 0 0 0 1px var(--mg-primary), + 0 0 0 3px rgba(var(--mg-primary-rgb), 0.18) !important; +} +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-input__inner, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-textarea__inner, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-select__placeholder, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-select__selected-item { + color: var(--me-text) !important; + font-weight: 500; +} +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-input__inner::placeholder, +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-textarea__inner::placeholder { + color: var(--me-text-muted) !important; +} +:root[data-shell="outpost"]:not([data-theme="outpost-light"]) .mg-content .map-editor-page .edit-property-panel .el-form-item__label { + color: var(--me-text-muted) !important; +} + +/* ????????????????????????????????????????????????????????????????????????? + * Harbor ?? ? ????????? + ?????????? + * ????????????????????????????????????????????????????????????????????????? */ +:root[data-theme="outpost-light"] .mg-content .map-editor-page { + --el-text-color-primary: #0b1220; + --el-text-color-regular: #64748b; + --el-text-color-secondary: #94a3b8; + color: var(--me-text); +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .el-tabs__item { + color: var(--me-text-muted) !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .el-tabs__item:hover { + color: var(--mg-primary) !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .el-tabs__item.is-active { + color: var(--mg-primary) !important; + font-weight: 700; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .el-tabs__active-bar { + background: linear-gradient(90deg, #7c3aed 0%, #64748b 100%) !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .el-tabs__nav-wrap::after { + background-color: var(--me-border) !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .el-input__wrapper, +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .el-textarea__inner, +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .el-select .el-input__wrapper, +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .el-select__wrapper, +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .el-input-number .el-input__wrapper { background: #ffffff !important; - box-shadow: 0 0 0 1px rgba(170, 110, 250, 0.28) inset !important; + box-shadow: inset 0 0 0 1px rgba(30, 58, 95, 0.14) !important; } -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .el-input__inner, -:root[data-theme="fame-lavender"] .mg-content .map-editor-page .edit-property-panel .el-textarea__inner { +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .el-input__wrapper:hover, +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .el-select__wrapper:hover { + box-shadow: inset 0 0 0 1px rgba(30, 58, 95, 0.32) !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .el-input__wrapper.is-focus, +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .el-select__wrapper.is-focused { + box-shadow: + inset 0 0 0 1px #7c3aed, + 0 0 0 3px rgba(30, 58, 95, 0.12) !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .el-input__inner, +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .el-textarea__inner, +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .el-select__selected-item { + color: #0b1220 !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .el-input__inner::placeholder, +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .el-textarea__inner::placeholder, +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .el-select__placeholder { + color: #94a3b8 !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .prop-add-field-btn { + background: #f5f3ff !important; + border: 1px dashed rgba(124, 58, 237, 0.42) !important; + color: #7c3aed !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .prop-add-field-btn:hover { + background: #ede9fe !important; + border-color: #7c3aed !important; + border-style: solid !important; + color: #5b21b6 !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .custom-field-item { + background: #f8fafc !important; + border: 1px solid #e5e7eb !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .custom-field-key { + color: rgba(45, 27, 105, 0.88) !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .custom-field-input .el-input__wrapper { + background: #ffffff !important; + box-shadow: inset 0 0 0 1px rgba(124, 58, 237, 0.16) !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .custom-field-input .el-input__inner { color: #1a0f3d !important; + font-weight: 550 !important; + -webkit-text-fill-color: #1a0f3d !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .prop-action-btn { + background: #7c3aed !important; + border: 1px solid #7c3aed !important; + color: #ffffff !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .prop-action-btn .prop-action-icon, +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .prop-action-btn .prop-action-label { + color: #ffffff !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .prop-action-btn:nth-child(2n) { + background: #ffffff !important; + border-color: rgba(124, 58, 237, 0.4) !important; + color: #7c3aed !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .prop-action-btn:nth-child(2n) .prop-action-icon, +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .prop-action-btn:nth-child(2n) .prop-action-label { + color: #7c3aed !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .prop-action-btn:hover:not(:disabled) { + background: #8b5cf6 !important; + border-color: #8b5cf6 !important; + color: #ffffff !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .prop-action-btn:nth-child(2n):hover:not(:disabled) { + background: #f5f3ff !important; + border-color: #7c3aed !important; + color: #5b21b6 !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .prop-action-btn:nth-child(2n):hover:not(:disabled) .prop-action-icon, +:root[data-theme="outpost-light"] .mg-content .map-editor-page .edit-property-panel .prop-action-btn:nth-child(2n):hover:not(:disabled) .prop-action-label { + color: #5b21b6 !important; +} +:root[data-theme="outpost-light"] .mg-content .map-editor-page .el-checkbox__label { + color: #64748b !important; } diff --git a/frontends/apps/simple-platform-vue/src/styles/themes.ts b/frontends/apps/simple-platform-vue/src/styles/themes.ts index cf5ebfc..3bb0b9d 100644 --- a/frontends/apps/simple-platform-vue/src/styles/themes.ts +++ b/frontends/apps/simple-platform-vue/src/styles/themes.ts @@ -1,10 +1,9 @@ /** * 主题色板预设 * - * 设计原则: - * - 每个主题提供一组 CSS 变量,运行时通过 document.documentElement.style.setProperty 注入 - * - 命名遵循 theme.css 中既有的 --mg-* 体系 - * - 工业紫色 (industrial-purple) 为默认主题:紫蓝渐变,深蓝底 + 天蓝高光 + * 主路径:Outpost 壳层三套精选(浅色 / 紫色 / 蓝色) + * 高级:旧深色霓虹主题(LEGACY_THEMES) + * 规范:docs/superpowers/specs/2026-07-25-migu-outpost-ui-lock-design.md */ export interface ThemePreset { @@ -15,116 +14,229 @@ export interface ThemePreset { preview: string /** 强调高光,用于 UI 预览的次代表色 */ previewAccent: string + /** Outpost 浅色壳(纸白主区);legacy 深色为 false */ + outpostShell?: boolean vars: Record } -export const DEFAULT_THEME_ID = 'fame-lavender' +/** Outpost 浅色壳共用表面(纸白卡、深字、关 orb);各主题可覆盖 card/tint */ +const OUTPOST_SHELL_VARS: Record = { + '--mg-bg-card-rgb': '255, 254, 253', + '--mg-bg-card-hi-rgb': '251, 249, 253', + '--mg-bg-card-darker-rgb': '245, 240, 251', + '--mg-text-tint-rgb': '40, 33, 58', + '--mg-text-hi-rgb': '117, 109, 133', + '--mg-orb-a-opacity': '0', + '--mg-orb-b-opacity': '0', + '--mg-orb-c-opacity': '0', + '--mg-radius-sm': '10px', + '--mg-radius': '16px', + '--mg-radius-lg': '20px', + '--mg-radius-xl': '24px' +} -export const THEMES: ThemePreset[] = [ - { - id: 'fame-lavender', - name: '迷毂浅紫', - description: '参考 FAME 系统:深紫侧栏 + 浅紫白主区,柔和耐看,长时间使用不刺眼', +/** + * 地图编辑 chrome(顶栏/工具轨/属性栏/底栏)跟主题色相走。 + * 默认真色壳(跟侧栏);浅色 Harbor 等可显式覆盖 --me-* 为浅壳。 + * 画布始终保持深色。 + */ +function withMapEditorChrome(vars: Record): Record { + const primaryRgb = vars['--mg-primary-rgb'] ?? '30, 58, 95' + const chrome1 = vars['--mg-bg-aside-1'] ?? '#1e3a5f' + const chrome2 = vars['--mg-bg-aside-2'] ?? '#0b1220' + const chromeRgb = vars['--mg-bg-aside-rgb'] ?? primaryRgb + const lightChrome = vars['--me-chrome-mode'] === 'light' + return { + ...vars, + '--me-chrome-1': vars['--me-chrome-1'] ?? chrome1, + '--me-chrome-2': vars['--me-chrome-2'] ?? chrome2, + '--me-chrome-rgb': vars['--me-chrome-rgb'] ?? chromeRgb, + '--me-border': vars['--me-border'] ?? (lightChrome ? 'rgba(30, 58, 95, 0.12)' : 'rgba(255, 255, 255, 0.12)'), + '--me-text': vars['--me-text'] ?? (lightChrome ? 'rgba(11, 18, 32, 0.92)' : 'rgba(245, 242, 255, 0.94)'), + '--me-text-muted': vars['--me-text-muted'] ?? (lightChrome ? 'rgba(11, 18, 32, 0.55)' : 'rgba(210, 200, 235, 0.68)'), + '--me-surface': vars['--me-surface'] ?? (lightChrome ? 'rgba(30, 58, 95, 0.04)' : 'rgba(255, 255, 255, 0.05)'), + '--me-hover': vars['--me-hover'] ?? (lightChrome ? `rgba(${primaryRgb}, 0.08)` : `rgba(${primaryRgb}, 0.28)`), + '--me-active-glow': vars['--me-active-glow'] ?? `rgba(${primaryRgb}, 0.28)`, + '--me-card-bg': vars['--me-card-bg'] ?? (lightChrome ? 'rgba(255, 255, 255, 0.96)' : 'rgba(0, 0, 0, 0.22)'), + '--me-card-border': vars['--me-card-border'] ?? (lightChrome ? '#e2e6ec' : 'rgba(255, 255, 255, 0.08)'), + '--me-inset': vars['--me-inset'] ?? (lightChrome ? '#f4f6f8' : 'rgba(0, 0, 0, 0.28)') + } +} + +function outpostPreset( + partial: Omit & { vars: Record } +): ThemePreset { + return { + ...partial, + outpostShell: true, + vars: withMapEditorChrome({ ...OUTPOST_SHELL_VARS, ...partial.vars }) + } +} + +/** 默认:Outpost 浅色(对齐 fairylandtech.amerc.ai) */ +export const DEFAULT_THEME_ID = 'outpost-light' + +/** 主路径精选三色(顶栏 ThemeSwitcher) */ +export const PRIMARY_THEMES: ThemePreset[] = [ + outpostPreset({ + id: 'outpost-light', + name: '浅色', + description: '纯白壳 + 紫色品牌点缀;地图壳白,画布深色', + preview: '#ffffff', + previewAccent: '#7c3aed', + vars: { + '--mg-primary': '#7c3aed', + '--mg-primary-rgb': '124, 58, 237', + '--mg-primary-hover': '#8b5cf6', + '--mg-primary-hover-rgb': '139, 92, 246', + '--mg-primary-active': '#5b21b6', + '--mg-accent': '#a855f7', + '--mg-accent-rgb': '168, 85, 247', + '--mg-primary-light-3': '#a78bfa', + '--mg-primary-light-5': '#c4b5fd', + '--mg-primary-light-7': '#ddd6fe', + '--mg-primary-light-8': '#ede9fe', + '--mg-primary-light-9': '#f5f3ff', + '--mg-primary-dark-2': '#6d28d9', + '--mg-bg-app-1': '#ffffff', + '--mg-bg-app-2': '#ffffff', + '--mg-bg-app-3': '#ffffff', + '--mg-bg-app-deep-rgb': '255, 255, 255', + '--mg-bg-aside-1': '#ffffff', + '--mg-bg-aside-2': '#fafafa', + '--mg-bg-aside-rgb': '255, 255, 255', + '--mg-shadow-rgb': '76, 29, 149', + '--mg-bg-card-rgb': '255, 255, 255', + '--mg-bg-card-hi-rgb': '255, 255, 255', + '--mg-bg-card-darker-rgb': '248, 250, 252', + '--mg-text-tint-rgb': '45, 27, 105', + '--mg-text-hi-rgb': '109, 40, 217', + /* 地图编辑:纯白壳 */ + '--me-chrome-mode': 'light', + '--me-chrome-1': '#ffffff', + '--me-chrome-2': '#ffffff', + '--me-chrome-rgb': '255, 255, 255', + '--me-border': 'rgba(124, 58, 237, 0.12)', + '--me-text': 'rgba(45, 27, 105, 0.92)', + '--me-text-muted': 'rgba(76, 29, 149, 0.55)', + '--me-surface': 'rgba(124, 58, 237, 0.04)', + '--me-hover': 'rgba(124, 58, 237, 0.08)', + '--me-active-glow': 'rgba(124, 58, 237, 0.18)', + '--me-card-bg': '#ffffff', + '--me-card-border': '#e5e7eb', + '--me-inset': '#f8fafc' + } + }), + outpostPreset({ + id: 'outpost-purple', + name: '紫色', + description: '同壳层、更饱和紫品牌;侧栏深蓝紫', preview: '#7c3aed', previewAccent: '#a855f7', vars: { - // 主色保留紫色(与 FAME 一致),但 hover/accent 使用更明亮的 violet/purple - '--mg-primary': '#7c3aed', - '--mg-primary-rgb': '124, 58, 237', - '--mg-primary-hover': '#8b5cf6', + '--mg-primary': '#7c3aed', + '--mg-primary-rgb': '124, 58, 237', + '--mg-primary-hover': '#8b5cf6', '--mg-primary-hover-rgb': '139, 92, 246', - '--mg-primary-active': '#5b21b6', - '--mg-accent': '#a855f7', - '--mg-accent-rgb': '168, 85, 247', - - '--mg-primary-light-3': '#a78bfa', - '--mg-primary-light-5': '#c4b5fd', - '--mg-primary-light-7': '#ddd6fe', - '--mg-primary-light-8': '#ede9fe', - '--mg-primary-light-9': '#f5f3ff', - '--mg-primary-dark-2': '#6d28d9', - - // 主区背景:浅薰衣草灰(v3:从近白下沉到 ~92% 明度,让白卡片靠阴影清晰浮起) - '--mg-bg-app-1': '#edeaf5', - '--mg-bg-app-2': '#e7e4f1', - '--mg-bg-app-3': '#f1eef8', - '--mg-bg-app-deep-rgb': '231, 228, 241', - - // 侧栏:FAME 深紫渐变 #2d1b69 -> #1a1040 - '--mg-bg-aside-1': '#2d1b69', - '--mg-bg-aside-2': '#1a1040', - '--mg-bg-aside-rgb': '45, 27, 105', - - // 卡片:白底(在 fame-lavender 专属规则中走纯 #fff) - '--mg-bg-card-rgb': '255, 255, 255', - '--mg-bg-card-hi-rgb': '249, 246, 255', - '--mg-bg-card-darker-rgb':'245, 240, 251', - '--mg-shadow-rgb': '124, 58, 237', - - // 文字:深紫标题 #2d1b69, 中灰正文 #606266 - '--mg-text-tint-rgb': '45, 27, 105', - '--mg-text-hi-rgb': '96, 98, 102', - - // 关闭装饰性 orb - '--mg-orb-a-opacity': '0', - '--mg-orb-b-opacity': '0', - '--mg-orb-c-opacity': '0' + '--mg-primary-active': '#5b21b6', + '--mg-accent': '#a855f7', + '--mg-accent-rgb': '168, 85, 247', + '--mg-primary-light-3': '#a78bfa', + '--mg-primary-light-5': '#c4b5fd', + '--mg-primary-light-7': '#ddd6fe', + '--mg-primary-light-8': '#ede9fe', + '--mg-primary-light-9': '#f5f3ff', + '--mg-primary-dark-2': '#6d28d9', + '--mg-bg-app-1': '#f3eefc', + '--mg-bg-app-2': '#edeaf5', + '--mg-bg-app-3': '#f8f5ff', + '--mg-bg-app-deep-rgb': '243, 238, 252', + '--mg-bg-aside-1': '#2d1b69', + '--mg-bg-aside-2': '#1a1040', + '--mg-bg-aside-rgb': '45, 27, 105', + '--mg-shadow-rgb': '124, 58, 237' } - }, + }), + outpostPreset({ + id: 'outpost-blue', + name: '蓝色', + description: '同壳层、蓝科技感;侧栏深蓝', + preview: '#3c78d2', + previewAccent: '#6ea8f0', + vars: { + '--mg-primary': '#3c78d2', + '--mg-primary-rgb': '60, 120, 210', + '--mg-primary-hover': '#4d8ae0', + '--mg-primary-hover-rgb': '77, 138, 224', + '--mg-primary-active': '#2a5fad', + '--mg-accent': '#6ea8f0', + '--mg-accent-rgb': '110, 168, 240', + '--mg-primary-light-3': '#6ea8f0', + '--mg-primary-light-5': '#9bc4f5', + '--mg-primary-light-7': '#c5ddf9', + '--mg-primary-light-8': '#e3effc', + '--mg-primary-light-9': '#f3f7fc', + '--mg-primary-dark-2': '#2a5fad', + '--mg-bg-app-1': '#f3f6fb', + '--mg-bg-app-2': '#eef2f8', + '--mg-bg-app-3': '#f8fafc', + '--mg-bg-app-deep-rgb': '243, 246, 251', + '--mg-bg-aside-1': '#0f2744', + '--mg-bg-aside-2': '#0a1a30', + '--mg-bg-aside-rgb': '15, 39, 68', + '--mg-shadow-rgb': '30, 58, 95' + } + }) +] + +/** 高级兼容:旧深色霓虹主题(用户菜单「兼容主题」) */ +export const LEGACY_THEMES: ThemePreset[] = [ { id: 'industrial-purple', name: '星云紫', - description: '科幻紫主色,辅以蓝紫渐变,磨砂玻璃 · 霓虹辉光', + description: '科幻紫主色 · 磨砂玻璃 · 霓虹辉光(兼容)', preview: '#7c3aed', previewAccent: '#c4b5fd', + outpostShell: false, vars: { - // ── 主色:明亮 violet(紫),主导整个画面 ── - '--mg-primary': '#7c3aed', - '--mg-primary-rgb': '124, 58, 237', - // hover/辉光:偏蓝紫 indigo,带来氛围流动感 - '--mg-primary-hover': '#8b5cf6', + '--mg-primary': '#7c3aed', + '--mg-primary-rgb': '124, 58, 237', + '--mg-primary-hover': '#8b5cf6', '--mg-primary-hover-rgb': '139, 92, 246', - '--mg-primary-active': '#5b21b6', - // accent:浅紫高光,边缘霓虹与点缀 - '--mg-accent': '#c4b5fd', - '--mg-accent-rgb': '196, 181, 253', - + '--mg-primary-active': '#5b21b6', + '--mg-accent': '#c4b5fd', + '--mg-accent-rgb': '196, 181, 253', '--mg-primary-light-3': '#9d6cf2', '--mg-primary-light-5': '#b594f7', '--mg-primary-light-7': '#6f4eab', '--mg-primary-light-8': '#4c357a', '--mg-primary-light-9': '#2d1f55', - '--mg-primary-dark-2': '#4c1d95', - - // ── 背景:深紫黑底,带 indigo 余晖 ── - '--mg-bg-app-1': '#0e0a24', - '--mg-bg-app-2': '#1f1147', - '--mg-bg-app-3': '#06031a', + '--mg-primary-dark-2': '#4c1d95', + '--mg-bg-app-1': '#0e0a24', + '--mg-bg-app-2': '#1f1147', + '--mg-bg-app-3': '#06031a', '--mg-bg-app-deep-rgb': '6, 3, 26', - - '--mg-bg-aside-1': '#0c0820', - '--mg-bg-aside-2': '#03020e', - '--mg-bg-aside-rgb': '10, 6, 30', - - '--mg-bg-card-rgb': '38, 24, 78', - '--mg-bg-card-hi-rgb': '58, 38, 110', + '--mg-bg-aside-1': '#0c0820', + '--mg-bg-aside-2': '#03020e', + '--mg-bg-aside-rgb': '10, 6, 30', + '--mg-bg-card-rgb': '38, 24, 78', + '--mg-bg-card-hi-rgb': '58, 38, 110', '--mg-bg-card-darker-rgb': '20, 12, 48', - '--mg-shadow-rgb': '8, 2, 24', - - '--mg-text-tint-rgb': '242, 232, 255', - '--mg-text-hi-rgb': '220, 200, 252', - - '--mg-orb-a-opacity': '0.55', - '--mg-orb-b-opacity': '0.50', - '--mg-orb-c-opacity': '0.40' + '--mg-shadow-rgb': '8, 2, 24', + '--mg-text-tint-rgb': '242, 232, 255', + '--mg-text-hi-rgb': '220, 200, 252', + '--mg-orb-a-opacity': '0.55', + '--mg-orb-b-opacity': '0.50', + '--mg-orb-c-opacity': '0.40' } }, { id: 'deep-azure', name: '深邃蓝', - description: '科技感深蓝,沉静稳重', + description: '科技感深蓝,沉静稳重(兼容)', preview: '#1565c0', previewAccent: '#82b1ff', + outpostShell: false, vars: { '--mg-primary': '#1565c0', '--mg-primary-rgb': '21, 101, 192', @@ -133,28 +245,23 @@ export const THEMES: ThemePreset[] = [ '--mg-primary-active': '#0d47a1', '--mg-accent': '#82b1ff', '--mg-accent-rgb': '130, 177, 255', - '--mg-primary-light-3': '#5a8fce', '--mg-primary-light-5': '#83aedb', '--mg-primary-light-7': '#adcde7', '--mg-primary-light-8': '#c4dbed', '--mg-primary-light-9': '#e3eef8', '--mg-primary-dark-2': '#0d47a1', - '--mg-bg-app-1': '#051a3a', '--mg-bg-app-2': '#0a2f6b', '--mg-bg-app-3': '#020a1f', '--mg-bg-app-deep-rgb': '2, 8, 26', - '--mg-bg-aside-1': '#06122a', '--mg-bg-aside-2': '#02060f', '--mg-bg-aside-rgb': '8, 18, 42', - '--mg-bg-card-rgb': '12, 36, 80', '--mg-bg-card-hi-rgb': '18, 50, 110', '--mg-bg-card-darker-rgb': '6, 18, 44', '--mg-shadow-rgb': '2, 4, 14', - '--mg-text-tint-rgb': '218, 234, 252', '--mg-text-hi-rgb': '170, 200, 240' } @@ -162,9 +269,10 @@ export const THEMES: ThemePreset[] = [ { id: 'emerald-forge', name: '翡翠绿', - description: '机械翡翠绿,沉稳活力', + description: '机械翡翠绿(兼容)', preview: '#00796b', previewAccent: '#80cbc4', + outpostShell: false, vars: { '--mg-primary': '#00796b', '--mg-primary-rgb': '0, 121, 107', @@ -173,28 +281,23 @@ export const THEMES: ThemePreset[] = [ '--mg-primary-active': '#004d40', '--mg-accent': '#80cbc4', '--mg-accent-rgb': '128, 203, 196', - '--mg-primary-light-3': '#4ca094', '--mg-primary-light-5': '#79b9b0', '--mg-primary-light-7': '#a6d2cc', '--mg-primary-light-8': '#bfdfdb', '--mg-primary-light-9': '#e1f0ee', '--mg-primary-dark-2': '#004d40', - '--mg-bg-app-1': '#06241f', '--mg-bg-app-2': '#0a4538', '--mg-bg-app-3': '#020f0c', '--mg-bg-app-deep-rgb': '2, 12, 10', - '--mg-bg-aside-1': '#061a16', '--mg-bg-aside-2': '#020a08', '--mg-bg-aside-rgb': '8, 26, 22', - '--mg-bg-card-rgb': '10, 50, 42', '--mg-bg-card-hi-rgb': '14, 66, 56', '--mg-bg-card-darker-rgb': '6, 28, 24', '--mg-shadow-rgb': '2, 10, 8', - '--mg-text-tint-rgb': '220, 244, 240', '--mg-text-hi-rgb': '170, 220, 210' } @@ -202,9 +305,10 @@ export const THEMES: ThemePreset[] = [ { id: 'crimson-iron', name: '熔铁赤', - description: '熔铁炉火般的暗红工业风', + description: '暗红工业风(兼容)', preview: '#b71c1c', previewAccent: '#ff8a80', + outpostShell: false, vars: { '--mg-primary': '#b71c1c', '--mg-primary-rgb': '183, 28, 28', @@ -213,28 +317,23 @@ export const THEMES: ThemePreset[] = [ '--mg-primary-active': '#8a0c0c', '--mg-accent': '#ff8a80', '--mg-accent-rgb': '255, 138, 128', - '--mg-primary-light-3': '#c95a5a', '--mg-primary-light-5': '#d68585', '--mg-primary-light-7': '#e4afaf', '--mg-primary-light-8': '#edc8c8', '--mg-primary-light-9': '#f7e6e6', '--mg-primary-dark-2': '#8a0c0c', - '--mg-bg-app-1': '#2a0606', '--mg-bg-app-2': '#4a0c0c', '--mg-bg-app-3': '#150303', '--mg-bg-app-deep-rgb': '20, 4, 4', - '--mg-bg-aside-1': '#200505', '--mg-bg-aside-2': '#0c0202', '--mg-bg-aside-rgb': '36, 6, 6', - '--mg-bg-card-rgb': '60, 10, 10', '--mg-bg-card-hi-rgb': '80, 14, 14', '--mg-bg-card-darker-rgb': '34, 5, 5', '--mg-shadow-rgb': '10, 1, 1', - '--mg-text-tint-rgb': '252, 220, 220', '--mg-text-hi-rgb': '240, 175, 175' } @@ -242,9 +341,10 @@ export const THEMES: ThemePreset[] = [ { id: 'graphite-steel', name: '石墨钢', - description: '中性冷灰,纯粹工业', + description: '中性冷灰(兼容)', preview: '#455a64', previewAccent: '#b0bec5', + outpostShell: false, vars: { '--mg-primary': '#455a64', '--mg-primary-rgb': '69, 90, 100', @@ -253,28 +353,23 @@ export const THEMES: ThemePreset[] = [ '--mg-primary-active': '#263238', '--mg-accent': '#b0bec5', '--mg-accent-rgb': '176, 190, 197', - '--mg-primary-light-3': '#7a8a92', '--mg-primary-light-5': '#9aa6ac', '--mg-primary-light-7': '#bac2c7', '--mg-primary-light-8': '#ccd2d6', '--mg-primary-light-9': '#e8ebed', '--mg-primary-dark-2': '#263238', - '--mg-bg-app-1': '#161e24', '--mg-bg-app-2': '#243038', '--mg-bg-app-3': '#0a0e12', '--mg-bg-app-deep-rgb': '10, 14, 18', - '--mg-bg-aside-1': '#11181d', '--mg-bg-aside-2': '#060a0d', '--mg-bg-aside-rgb': '18, 26, 32', - '--mg-bg-card-rgb': '30, 42, 50', '--mg-bg-card-hi-rgb': '42, 56, 66', '--mg-bg-card-darker-rgb': '16, 22, 28', '--mg-shadow-rgb': '4, 6, 10', - '--mg-text-tint-rgb': '226, 232, 238', '--mg-text-hi-rgb': '186, 198, 210' } @@ -282,9 +377,10 @@ export const THEMES: ThemePreset[] = [ { id: 'amber-forge', name: '琥珀金', - description: '高对比的橙金调,警示与活力并存', + description: '橙金调(兼容)', preview: '#e65100', previewAccent: '#ffb74d', + outpostShell: false, vars: { '--mg-primary': '#e65100', '--mg-primary-rgb': '230, 81, 0', @@ -293,44 +389,69 @@ export const THEMES: ThemePreset[] = [ '--mg-primary-active': '#bf360c', '--mg-accent': '#ffb74d', '--mg-accent-rgb': '255, 183, 77', - '--mg-primary-light-3': '#ec8344', '--mg-primary-light-5': '#f2a474', '--mg-primary-light-7': '#f7c4a3', '--mg-primary-light-8': '#fad6bc', '--mg-primary-light-9': '#fdeadd', '--mg-primary-dark-2': '#bf360c', - '--mg-bg-app-1': '#2a1404', '--mg-bg-app-2': '#4a2a0c', '--mg-bg-app-3': '#150a02', '--mg-bg-app-deep-rgb': '20, 10, 4', - '--mg-bg-aside-1': '#200f04', '--mg-bg-aside-2': '#0c0602', '--mg-bg-aside-rgb': '34, 16, 6', - '--mg-bg-card-rgb': '62, 32, 8', '--mg-bg-card-hi-rgb': '82, 44, 12', '--mg-bg-card-darker-rgb': '34, 16, 4', '--mg-shadow-rgb': '10, 4, 1', - '--mg-text-tint-rgb': '252, 232, 210', '--mg-text-hi-rgb': '240, 196, 140' } } ] -export function findTheme(id: string | undefined | null): ThemePreset { - if (!id) return THEMES[0] - return THEMES.find((t) => t.id === id) ?? THEMES[0] +/** 全量(查找用):精选 + 兼容 */ +export const THEMES: ThemePreset[] = [...PRIMARY_THEMES, ...LEGACY_THEMES] + +/** 旧 id → 新精选 id */ +const THEME_ALIASES: Record = { + 'fame-lavender': 'outpost-purple', + 'outpost-fairyland': 'outpost-light' } -/** 把主题变量写入 :root;多次调用幂等,会覆盖同名属性 */ +export function resolveThemeId(id: string | undefined | null): string { + if (!id) return DEFAULT_THEME_ID + const aliased = THEME_ALIASES[id] ?? id + if (THEMES.some((t) => t.id === aliased)) return aliased + return DEFAULT_THEME_ID +} + +export function findTheme(id: string | undefined | null): ThemePreset { + const resolved = resolveThemeId(id) + return THEMES.find((t) => t.id === resolved) ?? PRIMARY_THEMES[0] +} + +export function isLegacyThemeId(id: string | undefined | null): boolean { + if (!id) return false + const resolved = THEME_ALIASES[id] ?? id + return LEGACY_THEMES.some((t) => t.id === resolved) +} + +/** 把主题变量写入 :root;Outpost 壳写 data-shell="outpost" 供浅色 CSS 命中 */ export function applyThemeVars(preset: ThemePreset): void { const root = document.documentElement - for (const [key, value] of Object.entries(preset.vars)) { + // preset.vars 在 outpostPreset 里已跑过 withMapEditorChrome;再跑一次以补全缺省 --me-* + const vars = withMapEditorChrome({ ...preset.vars }) + for (const [key, value] of Object.entries(vars)) { + if (key === '--me-chrome-mode') continue root.style.setProperty(key, value) } root.setAttribute('data-theme', preset.id) + if (preset.outpostShell) { + root.setAttribute('data-shell', 'outpost') + } else { + root.removeAttribute('data-shell') + } } diff --git a/frontends/apps/simple-platform-vue/src/views/LoginView.vue b/frontends/apps/simple-platform-vue/src/views/LoginView.vue index f0fb998..1d7be0f 100644 --- a/frontends/apps/simple-platform-vue/src/views/LoginView.vue +++ b/frontends/apps/simple-platform-vue/src/views/LoginView.vue @@ -4,17 +4,10 @@
-
-