feat: opsx-loki 全面升级 — 前端重构/用户与LDAP/部署向导/日志查询
基于 WEB-UI-Development-Guide 标准的整体升级,并更名 LokiDeploy → opsx-loki。 前端(Gin+React+shadcn/ui): - 按 02/07 章重构:页面域化拆分(无超 400 行文件)、PageContainer/ListQuery、 反馈分级(成功静默/失败 toast/危险确认)、401 单飞刷新+队列重放 - 暗色模式(next-themes)+ 语义 Token(--primary 品牌色/success/warning/info) - 部署向导(状态推导四步:环境→存储→Loki→采集,内嵌表单闭环) - 日志查询页:LogQL 标签构建器/拖拽直方图/日志上下文/Live Tail/查询历史 - 按用户+标签策略的查询授权(服务端强制合并策略) 后端(Go+Gin+JSON DB): - 简单用户管理(仅 admin,无 RBAC)+ TokenVersion 会话吊销 + 登录 IP 限流 - LDAP 接入:配置(AES 加密存储/hasPassword 脱敏)/测试连接/批量导入/登录 - 存储配置测试连接(SigV4 零依赖)+ 桶不存在自动创建 - Loki 三模式部署修复:SSH 密钥认证、3.x 配置模板、ruler 对象存储嵌套块、 凭证解密、孤儿 deploying 状态恢复、Grafana 部署(可选默认关)+面板导入 - DaemonSet 采集纯 YAML(去 helm 依赖)+ DNS 自愈回退 ClusterIP + 集群名标签 - 日志查询代理:cluster-svc 经 kube-apiserver proxy/url 直连 + cursor 翻页 - 统一 log 命名空间;部署就绪探活;Grafana 访问地址自动记录 修复:run.sh 增量编译检测、Sanitized 脱敏补全、LokiDeployment Update 白名单、 健康检查 CreatedAt 零值等 10+ 存量 bug。 数据兼容:DB 沿用旧 lokideploy.json(新名优先);localStorage 一次性迁移; HKDF 加密前缀保留(已加密凭证不受影响)。
This commit is contained in:
1 parent
327e282356
commit
f9c6c1d826
204 files changed
+14107
-9103
No files matched your search
@@ -0,0 +1,316 @@
|
||||
# 06 — 主题系统与视觉设计
|
||||
|
||||
> 参考:vue-vben-admin(HSL Token + Tailwind 桥接 + CSS layer + EP 适配器)、soybean-admin(单一 ThemeSetting 类型 + 三端同步)、vue-pure-admin(EP↔Tailwind v4 变量桥接)、ant-design-pro(antd token + data-theme);补充:gin-vue-admin(EP SCSS 定制三层法)
|
||||
|
||||
---
|
||||
|
||||
## 一、设计 Token:单一事实源
|
||||
|
||||
### 1.1 Token 分层模型
|
||||
|
||||
```
|
||||
语义层(唯一手写处)
|
||||
--background --foreground --primary --card --border --radius ...
|
||||
↓ 派生(工具类桥接)
|
||||
Tailwind 层 bg-background text-foreground(@theme 映射)
|
||||
↓ 派生(适配器)
|
||||
组件库层 --el-color-primary / antd token —— 从语义层变量计算得出
|
||||
↓ 派生(算法)
|
||||
色阶层 primary-50 … primary-950 / light-3 … light-9
|
||||
```
|
||||
|
||||
**铁律:语义 Token 是唯一手写源,其余全部派生。** 任何地方再出现硬编码色值(`#409eff`、`rgb(64,158,255)`)都是违规。
|
||||
|
||||
### 1.2 vben 的 Token 定义(shadcn 范式)
|
||||
|
||||
```css
|
||||
/* vben: packages/@core/base/design/src/design-tokens/default.css */
|
||||
:root {
|
||||
--background: 0 0% 100%; /* HSL 三元组,不带 hsl() 包装 */
|
||||
--primary: 211 91% 39%;
|
||||
--border: 214 32% 91%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
.dark { /* 整组覆盖,暗色即换一套值 */
|
||||
--background: 224 71% 4%;
|
||||
--primary: 210 98% 56%;
|
||||
}
|
||||
```
|
||||
|
||||
两个细节值千金:
|
||||
|
||||
1. **裸 HSL 值不带 `hsl()` 包装**——这样 `hsl(var(--primary) / 0.5)` 可直接拼透明度(soybean 同款:RGB 拆三段 `r g b` 供 `rgb(var(--x) / 0.5)`)
|
||||
2. **暗色 = `.dark` class 整组覆盖**,而非媒体查询——用户偏好优先于系统
|
||||
|
||||
### 1.3 Tailwind v4 桥接(vben)
|
||||
|
||||
```css
|
||||
/* internal/tailwind-config/src/theme.css */
|
||||
@custom-variant dark (&:is(.dark *)); /* class 策略暗色 */
|
||||
@theme inline {
|
||||
--color-background: hsl(var(--background)); /* 语义 Token → 工具类 */
|
||||
--color-primary: hsl(var(--primary));
|
||||
}
|
||||
@layer properties, theme, base, components, utilities; /* 级联层声明 */
|
||||
```
|
||||
|
||||
**CSS layer 声明是组件库共存的关键**:把组件库样式压在低层,工具类天然可覆盖,避免 `!important` 军备竞赛。
|
||||
|
||||
### 1.4 pure 的 EP↔Tailwind 桥接与 soybean 的三端同步(★★★★☆)
|
||||
|
||||
**EP 工程引入原子类的最短路径(pure):**
|
||||
|
||||
```css
|
||||
/* vue-pure-admin: src/style/tailwind.css —— Tailwind v4 CSS-first 写法 */
|
||||
@custom-variant dark (&:is(.dark *)); /* class 策略暗色 */
|
||||
@theme {
|
||||
--color-bg_color: var(--el-bg-color); /* EP 变量 → 原子色 token */
|
||||
--color-primary: var(--el-color-primary); /* 于是 bg-bg_color / text-primary 与组件库同色 */
|
||||
}
|
||||
```
|
||||
|
||||
soybean 则是「单一强类型配置对象」路线:`themeSettings`(`App.Theme.ThemeSetting` 一份 schema 即文档)驱动 **CSS 变量 + NaiveUI GlobalThemeOverrides + UnoCSS theme 三端同步**,且用 `BUILD_TIME` 作覆盖标志——**发版自动淘汰用户本地旧主题缓存**(防「新版本旧皮肤」)。两案共同点:换肤 = 改上游变量,组件库与原子类自动跟随。
|
||||
|
||||
---
|
||||
|
||||
## 二、暗色模式
|
||||
|
||||
### 2.1 实现要点(三标杆殊途同归)
|
||||
|
||||
| 环节 | 做法 | 反面 |
|
||||
|------|------|------|
|
||||
| 切换机制 | html 挂 class(vben/pure `.dark`)或 `data-theme="dark"`(adp) | `prefers-color-scheme` 媒体查询直连(用户无法覆盖系统) |
|
||||
| 跟随系统 | watch `prefers-color-scheme` 作为 **auto 模式初值**,用户手动选择后以用户为准 | — |
|
||||
| 持久化 | localStorage 单 key;**读取要在 app 挂载前**(防白闪,必要时内联脚本) | 挂载后再初始化(首屏闪白) |
|
||||
| 组件库 | EP:引 `dark/css-vars.css` 一行;antd:token 切换 | 自写暗色样式覆盖组件库 |
|
||||
|
||||
三态标准:`light | dark | auto`(auto 跟随系统)。附加无障碍模式(可选):灰度 / 色弱滤镜(`html-grey` / `html-weakness`,一行 filter + class 切换;值班大屏场景有真实需求)。
|
||||
|
||||
**暗色的分层策略与浅色不同**:阴影在深底上几乎不可见——暗色模式靠**边框 + 表面亮度差**分层(卡片 = 页面底色提亮一档),不要只调阴影。
|
||||
|
||||
### 2.2 双端 key 一致(迁移期,必须)
|
||||
|
||||
同产品双栈并存的工程,暗色 key **必须**两端同名(推荐 `<app>.theme.mode`),切换机制统一(class + data-theme 双挂成本最低)。key 不一致 = 同浏览器两端口偏好不互通 + 迁移时暗色选择器要全量改。
|
||||
|
||||
---
|
||||
|
||||
## 三、组件库主题定制(Element Plus)
|
||||
|
||||
标杆做法(vben):语义 Token **派生**组件库变量——`useElementPlusDesignTokens` 监听主题变化,把语义 Token 实时映射为 `--el-color-primary` 全系(暗色下自动反转色阶方向)。**换肤不碰组件库,只改上游 Token。**
|
||||
|
||||
补充范式(gva 的 EP 专属三层法):
|
||||
|
||||
```
|
||||
第 1 层 编译期:SCSS 定制色板
|
||||
@forward 'element-plus/theme-chalk/src/common/var.scss'
|
||||
with ($colors: ('primary': ('base': #409EFF), ...));
|
||||
|
||||
第 2 层 运行时:JS 生成 --el-color-primary 及 light-1..10 / dark-1..2 / -bg
|
||||
色阶写入 documentElement —— 换主色不重新编译
|
||||
(gva setBodyPrimaryColor:light/dark 两套明度算法)
|
||||
|
||||
第 3 层 暗色变量:element-plus/theme-chalk/dark/css-vars.css
|
||||
+ html.dark { --el-bg-color: ... } 局部覆盖
|
||||
```
|
||||
|
||||
pure 的 `setEpThemeColor()`(`useDataThemeChange.ts`)是第 2 层的更简实现:`documentElement.style.setProperty` + 循环生成 light-1~9/dark-1~2,且暗色下**色阶方向反转**。品牌主色运行时换肤(站点名/Logo/主色/favicon 联动)是底座「品牌可配」能力的核心——主色、圆角(`--el-border-radius-base`)、基础字号纳入同一变量体系。
|
||||
|
||||
---
|
||||
|
||||
## 四、视觉执行规范(写出好看代码的数值层)
|
||||
|
||||
> 本章前三节解决「主题怎么搭」,本节解决「页面怎么写才好看」。所有数值**必须**落为 CSS 变量后使用——AI/开发者写页面时只允许引用变量,不允许现场发明数值。
|
||||
|
||||
### 4.1 品牌可配项
|
||||
|
||||
| 配置项 | 生效点 | 存储 |
|
||||
|--------|--------|------|
|
||||
| 站点名称 | 侧栏 logo 文案 / document.title 后缀 | 后端配置 |
|
||||
| Logo | 侧栏 + favicon | 后端配置 |
|
||||
| 主色 | `--el-color-primary` 系列运行时混色 | 后端配置或用户偏好 |
|
||||
| 暗色 | 用户偏好 | localStorage(统一命名空间) |
|
||||
|
||||
pure 的补充范式:**运行时平台配置**(`public/platform-config.json`,Title/Layout/Theme/DarkMode 等 30+ 项,启动拉取注入)——改配置不发版(详见 08 章 env 分层)。
|
||||
|
||||
### 4.2 基础 Token 全表(新工程第一天就建)
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* —— 背景层次(浅色值示例;暗色整组覆盖,靠亮度差分层) —— */
|
||||
--bg-page: #f5f6f8; /* 页面底 */
|
||||
--bg-card: #ffffff; /* 卡片 / 弹层 */
|
||||
--bg-hover: rgba(0, 0, 0, 0.04); /* 行/项 hover */
|
||||
--bg-muted: #f5f7fa; /* 次级区块 / 代码块 */
|
||||
|
||||
/* —— 文字层次(四档灰,禁用两档灰打天下) —— */
|
||||
--text-primary: rgba(0, 0, 0, 0.88); /* 正文 */
|
||||
--text-secondary: rgba(0, 0, 0, 0.65); /* 次要说明、表头 */
|
||||
--text-placeholder: rgba(0, 0, 0, 0.38); /* 占位、禁用标签 */
|
||||
--text-disabled: rgba(0, 0, 0, 0.25);
|
||||
--text-inverse: #ffffff; /* 深底上的文字 */
|
||||
|
||||
/* —— 边框(三级) —— */
|
||||
--border-strong: rgba(0, 0, 0, 0.26); /* 输入框 */
|
||||
--border-base: rgba(0, 0, 0, 0.15); /* 卡片描边 */
|
||||
--border-light: rgba(0, 0, 0, 0.08); /* 分割线 */
|
||||
|
||||
/* —— 语义色(对齐组件库 success/warning/danger/info) —— */
|
||||
|
||||
/* —— 间距(4px 基数,全站只用这六档) —— */
|
||||
--space-1: 4px; --space-2: 8px; --space-3: 12px;
|
||||
--space-4: 16px; --space-6: 24px; --space-8: 32px;
|
||||
|
||||
/* —— 圆角(三档) —— */
|
||||
--radius-sm: 4px; /* 标签、小按钮 */
|
||||
--radius: 8px; /* 卡片、按钮、输入框(主值) */
|
||||
--radius-lg: 12px; /* 弹窗、大图 */
|
||||
|
||||
/* —— 阴影(卡片最多 2 级;弹层用组件库默认) —— */
|
||||
--shadow-1: 0 1px 2px rgba(0, 0, 0, 0.06);
|
||||
--shadow-2: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
|
||||
/* —— 层级(防 z-index 军备竞赛) —— */
|
||||
--z-dropdown: 100; --z-drawer: 200;
|
||||
--z-modal: 300; --z-message: 400;
|
||||
}
|
||||
```
|
||||
|
||||
项目可从组件库变量派生(EP:`--bg-card: var(--el-bg-color)`),重点是**层次齐全、命名统一**。卡片风格全站二选一:**描边(border-base)或阴影(shadow-1)**,不许混用。
|
||||
|
||||
### 4.3 字体与排版
|
||||
|
||||
| 用途 | 字号 / 行高 | 字重 |
|
||||
|------|------------|------|
|
||||
| 页面标题 | 18-20 / 28 | 600 |
|
||||
| 卡片标题 | 16 / 24 | 600 |
|
||||
| 正文 / 表格 | 14 / 22 | 400 |
|
||||
| 次要说明 | 13 / 20 | 400 |
|
||||
| 辅助 / 标签 | 12 / 20 | 400 |
|
||||
|
||||
规则:**正文最小 12px**(再小不可读);同一页面标题层级 ≤2 级;数字用 `font-variant-numeric: tabular-nums`;中英文与数字混排加空格(「共 12 条」);长文本省略必须带 title 提示;字体栈取系统栈 + 组件库默认,**禁止**引入额外 webfont 除非品牌需要。
|
||||
|
||||
### 4.4 图标规范
|
||||
|
||||
- **一套图标集**(线性或面性统一,**禁止**混搭两套风格;推荐 Iconify 单集或组件库图标)
|
||||
- 尺寸四档:12(辅助)/ 16(按钮、菜单、表格行内 **主值**)/ 20(页头)/ 24(空态插图位)
|
||||
- 图标与文字并排间距 6px;按钮内图标与文字同色同级
|
||||
- 纯图标按钮**必须**带 tooltip 与 aria-label
|
||||
|
||||
### 4.5 过渡与微交互
|
||||
|
||||
| 场景 | 时长 / 缓动 |
|
||||
|------|-------------|
|
||||
| 颜色 / hover 变化 | 150ms ease |
|
||||
| 展开 / 抽屉 / 弹层 | 200-300ms `cubic-bezier(0.4, 0, 0.2, 1)` |
|
||||
| 页面切换 | fade 150ms |
|
||||
|
||||
规则:同类交互全站**同时长同缓动**;**禁止**超过 400ms 的阻塞动画;按钮提交必须有 loading 态(防重复触发);自定义交互组件四态齐全——**hover / active / focus-visible / disabled** 缺一不可(focus 可见性是可访问性底线)。
|
||||
|
||||
### 4.6 对齐与栅格
|
||||
|
||||
- 表格:数字列右对齐 + tabular-nums,文本列左对齐,**居中对齐只用于状态标签/操作列**(全列居中是典型反模式)
|
||||
- 表单:标签右对齐或上对齐全站统一一档;输入宽度按内容语义定(手机号 11 位就别 100% 宽)
|
||||
- 卡片间距统一 `--space-4`(16px);页面内边距 `--space-6`(24px)
|
||||
|
||||
---
|
||||
|
||||
## 五、好看反模式清单(出现即改)
|
||||
|
||||
1. 硬编码色值(`#333`、`rgba(0,0,0,.5)` 散落模板)——不走 Token
|
||||
2. 一页混用多种圆角 / 多种阴影 / 非 4px 基数间距(8 和 10 混用)
|
||||
3. 全列居中对齐的表格(数字该右对齐、文本该左对齐)
|
||||
4. 图标混用两套风格(线性 + 面性、单色 + 彩色)
|
||||
5. 一页多个 primary 按钮(主操作**只能有一个**,其余 default/text)
|
||||
6. 只有两种灰的文字层次(该用四档文字 Token)
|
||||
7. 弹窗套弹窗再套抽屉(层级超过两层改抽屉分流)
|
||||
8. 满屏成功 toast(见 07 章反馈分级:成功静默)
|
||||
9. 骨架屏与真实内容尺寸不符(loading 结束页面跳动)
|
||||
10. 表格列被挤压换行(缺 min-width / 未开横向滚动)
|
||||
11. 危险操作无确认且无 danger 语义色
|
||||
12. 空页面白板(empty 必须带引导动作)
|
||||
13. 阴影当装饰乱叠(卡片最多 shadow-2,层级感来自留白而非阴影堆叠)
|
||||
14. 暗色模式直接套浅色阴影(暗色靠边框 + 亮度差分层)
|
||||
|
||||
---
|
||||
|
||||
## 六、死 CSS 治理
|
||||
|
||||
存量工程常见病灶:styles/ 下积累多代无入口引用的样式文件(曾有工程沉淀约 2000 行死 CSS,且「设计系统」存在 v1/v2 两代并存——换了两茬样式系统、旧的没删的考古层)。
|
||||
|
||||
### 6.1 治理方案(四步)
|
||||
|
||||
```
|
||||
第 1 步 验死:对每个文件跑全仓引用检查(import/@import/url()),
|
||||
确认零引用后直接删除(git 里有历史,不建备份目录)
|
||||
第 2 步 收敛:保留三件套 = variables(语义 Token)+ 栅格 + 基础元素;
|
||||
组件样式回归 scoped / 组件库
|
||||
第 3 步 立规:CI 检查 styles/ 下每个 .css 必须被入口链引用,
|
||||
新文件无引用直接 fail
|
||||
第 4 步 单源:设计规范类文档只留一份(docs),代码里不留第二套实现
|
||||
```
|
||||
|
||||
**规则**:CSS 文件必须有入口引用链,如同 JS 文件必须有 import——「无引用样式」=「无主代码」,删除是唯一正确处理。
|
||||
|
||||
---
|
||||
|
||||
## 七、样式写法优先级(adp 明文范式,直接抄用)
|
||||
|
||||
```
|
||||
1. 组件库自带能力(EP 的 type/size/token props) ← 优先
|
||||
2. 语义工具类 / Tailwind 原子类(布局、间距) ← 其次
|
||||
3. scoped 样式 + CSS 变量(主题相关) ← 业务组件
|
||||
4. 深度选择器 :deep()(覆盖组件库,须注释原因) ← 最后手段
|
||||
5. 全局覆盖(唯一收口文件,如 element 覆盖表) ← 禁散落
|
||||
```
|
||||
|
||||
gva 的补充范式:语义化页面类(`gva-search-box / gva-table-box / gva-btn-list`)。与「页面容器 + 列表组件」的组件路线二选一——**推荐组件路线**(类型提示与 props 约束更强),不要并行引入两套体系。
|
||||
|
||||
---
|
||||
|
||||
## 八、最佳实践清单
|
||||
|
||||
✅ **要做**
|
||||
|
||||
1. 新颜色/间距/圆角一律引用 Token 变量,组件里禁止现场发明数值
|
||||
2. 透明度拼接用 `hsl(var(--x) / 0.5)` 裸值模式
|
||||
3. 暗色切换在 app 挂载前完成(必要时 index.html 内联首帧脚本)
|
||||
4. 图表颜色从主题变量读取(初始化注入当前主题色板,暗色切换重建实例)
|
||||
5. 新全局覆盖样式集中一个文件并注释原因
|
||||
|
||||
❌ **不要**
|
||||
|
||||
1. 不要保留 v1/v2 并存的设计系统文件
|
||||
2. 不要用 `!important` 解决覆盖问题(用 CSS layer 或提高选择器语义)
|
||||
3. 不要在组件里写 `@media (prefers-color-scheme)` 直连暗色(绕过用户选择)
|
||||
4. 不要硬编码暗色背景色值(读组件库 bg 变量)
|
||||
5. 不要双端各存一套主题 key(迁移期统一命名)
|
||||
|
||||
---
|
||||
|
||||
## 九、AI 检查清单(对比目标工程逐项核对)
|
||||
|
||||
**P0(结构)**
|
||||
|
||||
1. styles/ 下是否有零入口引用的样式文件?列出并标记删除(统计行数)
|
||||
2. 是否存在硬编码色值 / 非 Token 间距圆角出现在模板与 scoped 样式?抽样列出
|
||||
3. 是否有多套并行样式系统 / 两代设计系统文件并存?
|
||||
|
||||
**P1(视觉执行)**
|
||||
|
||||
4. 基础 Token 全表(背景四档/文字四档/边框三级/间距六档/圆角三档)是否建立且被引用?
|
||||
5. 排版抽检:正文 <12px?数字列未右对齐/未 tabular-nums?长文本省略无 title?
|
||||
6. 图标抽检:是否混用两套风格?纯图标按钮是否缺 tooltip/aria-label?
|
||||
7. 过渡抽检:同类交互时长是否统一?提交按钮是否都有 loading?四态是否齐全?
|
||||
8. 对照「好看反模式清单」14 条逐条扫描,命中项列出
|
||||
9. 暗色抽检:分层是否靠边框/亮度差?图表色板是否随主题重建?
|
||||
|
||||
**P2(体验升级)**
|
||||
|
||||
10. 对比度达标:正文 ≥ 4.5:1、大字 ≥ 3:1(WCAG AA)——用工具抽查文字层次 Token
|
||||
11. Tailwind 是否与组件库变量打通(pure `@theme` 桥接)?
|
||||
12. 是否需要 BUILD_TIME 发版覆盖用户旧主题缓存(soybean 方案)?
|
||||
13. 灰度/色弱无障碍模式是否值得启用(值班场景)?
|
||||
|
||||
---
|
||||
|
||||
> 下一篇:[07-组件设计与交互反馈](07-组件设计与交互反馈.md) —— 组件是设计的词汇表。
|
||||
Reference in new issue
Block a user