Files
LokiStack/docs/web-ui-guide/08-工程化与质量保障.md
T
logan f9c6c1d826 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 加密前缀保留(已加密凭证不受影响)。
2026-10-24 13:20:12 +08:00

11 KiB
Raw Blame History

08 — 工程化与质量保障

参考:vue-vben-admin(Vite 配置工厂 + lefthook 流水线)、soybean-admin(eslint-config 工厂 + sa CLI)、vue-pure-admin(build/ 拆分 + env 开关能力)、ant-design-pro(Biome + 测试范式 + CI 矩阵)


一、构建配置组织

1.1 配置组织范式

vben:配置即内部包
internal/vite-config/ 提供 defineConfig({ application | library }) 工厂,
app 的 vite.config.ts 只剩 15 行(proxy 声明)

pure:根目录 build/ 拆分
build/{plugins,cdn,compress,optimize,utils,info}.ts,vite.config.ts 只做组装
(env 用 wrapperEnv 类型化读取)

soybean:build/plugins/ 按域拆文件
{router,unplugin,html,unocss,devtools}.ts 一文件一插件域

单工程标准:必须把 vite 配置按职责拆文件(plugins/env/proxy/compress),主配置只做组装;双栈工程的两个 vite 配置结构镜像(插件列表、alias、产物命名、proxy 规则逐项对齐)。

1.2 env 分层(三层结构)

层 形态 语义 说明
构建期烧录 VITE_* 打进产物,改了要重新构建 API 前缀、功能开关
运行时可改 VITE_GLOB_*(vben) 构建时抽成 _app-config-{hash}.js 挂 window 改 API 地址无需重构建
运行时 JSON public/platform-config.json(pure) 构建产物旁的配置文件,启动拉取注入 免重构建、免 window 挂载
纯 dev proxy 端口等 只在 dev server 用 —

env 类型契约:每个 VITE_* 变量在 vite-env.d.ts 有类型与注释(soybean:联合类型直接收窄如 'static' | 'dynamic')。

1.3 dev server 要点(必须)

strictPort: true            # 端口被占直接报错,不悄悄漂移
proxy '/api' → 后端端口
  ws: true                  # 供 WebSocket(必须显式开)
  changeOrigin: true

1.4 产物与指纹

  • 构建注入版本:define: { __APP_VERSION__, __COMMIT_HASH__ }(adp 用 git rev-parse 兜底)——设置页「关于」直接展示,排障救命
  • 手工分包保留(radix/icons/charts/motion 等);新大依赖(图表/编辑器)必须评估独立 chunk + 懒加载
  • 可选:构建压缩 env 开关(pure VITE_COMPRESSION = none|gzip|brotli|both)、CDN 开关(VITE_CDN)、构建时间戳 banner

二、代码规范流水线

2.1 分层流水线(vben lefthook 范式)

pre-commit(仅 staged 文件):
  快修复:oxlint --fix → oxfmt → eslint --fix → stylelint --fix
          (stage_fixed 回填暂存区)
commit-msg:commitlint(conventional)
push/CI:慢检查全量 vue-tsc/tsc --noEmit + lint + madge 循环依赖

原则:快的在本地 pre-commit 自动修,慢的在 CI 卡。

soybean 的同构版本:@soybeanjs/eslint-config-vue 工厂(eslint.config.mjs 仅 14 行)+ vp lint(oxc 快扫)→ eslint(精修)双层;commit 由自研 sa CLI 交互生成并校验,scope 白名单单一数据源。pure 再补两块:stylelint(recess-order 属性排序)与 eslint-plugin-better-tailwindcss(校验 class 书写)。

2.2 必配清单(必须)

工具 要求
ESLint(flat)+ Prettier 双端同大版本、规则集可复制
Stylelint standard-scss + recommended-vue + 属性排序
commitlint + husky + lint-staged pre-commit 快修复、commit-msg 校验
preinstall: only-allow pnpm 锁包管理器

Conventional Commits 类型集(commitlint type-enum,统一):feat / fix / docs / style / refactor / perf / test / chore / revert;scope 用功能域(user、rbac、cron、react……)。

any 管控:TS strict 端禁止裸 any——as any 需同行注释原因与消除计划;JS 端以 JSDoc @param/@returns 过渡,不允许出现「既无类型注释也无类型定义」的接口函数。

2.3 项目级 lint 增强(把各章规则自动化)

// eslint 配置片段(示意)
'no-console': ['warn', { allow: ['warn', 'error'] }]   // 生产禁 console.log
'no-restricted-imports': // 示例层禁 import 系统层内聚单元
  { patterns: [{ group: ['@/views/system/*'], message: '示例层不得依赖系统层' }] }
vue/name: 'error'            // 页面组件必须 defineOptions name(keep-alive 前置)
import/no-cycle: 'error'     // 循环依赖

三、测试策略

3.1 管理端测试金字塔(务实版)

        ▲  E2E 冒烟(Playwright)
        │   登录→进列表→CRUD→登出 3-5 条主线,别贪多
        ├─ 组件/页面测试(Vitest + Testing Library)
        │   列表组件三态、表单弹窗校验与提交、菜单失败重试
        ├─ 组合函数测试(重点投入区,性价比最高)
        │   usePagedQuery(取消/错序/分页边界)
        │   permission 纯函数穷举
        │   请求层拦截器分支(401刷新/重放/静默)
        └─ 纯函数单测
            格式化、confirm、色阶算法

3.2 adp 测试范式(直接照抄)

// 重依赖 mock + 动态 import(vi.mock 提升到顶部,import 在 test 内)
vi.mock('@/services/user', () => ({ queryCurrentUser: vi.fn() }))

test('未登录访问受保护页重定向 login 并保留 redirect', async () => {
  queryCurrentUser.mockRejectedValueOnce({ /* 401 */ })
  const { getInitialState } = await import('@/app')
  const redirect = await getInitialState()
  expect(redirect).toContain('/user/login?redirect=')
})

关键点:纯函数穷举测试(permission/access 这类零成本高回报)、拦截器分支测试(请求层是事故高发区,mock adapter 驱动各分支)。

3.3 覆盖要求

  • coverage 阈值必须配置(如 lines 70 / statements 70 / functions 60 / branches 70),排除生成代码
  • E2E 至少覆盖:登录主线、一条 CRUD 主线、模块开关生效(若为底座)
  • vben 是组件测试深度的标杆:连 Modal 的 keep-alive 场景都有单测

四、性能优化清单

手段 做法 出处
路由懒加载 全部页面 () => import();示例层可构建期 tree-shake 通行
首屏占位 index.html 注入 loading HTML(#root 空时先渲染骨架) adp
路由预取 菜单 hover prefetch / vite server.warmup 预热核心目录 adp/vben/pure
图表懒加载 Suspense/条件 import 包裹 ECharts 区块 通行
chunk 失效恢复 ChunkLoadError → 提示/自动 reload 一次(发版后旧 hash 404) adp + 路由 onError
请求防抖取消 列表页「取消 + 版本号」(见 03 章) 本标准
大日期库治理 moment→dayjs / 按需 locale adp
WebSocket 卸载断开 + 重连指数退避 + 心跳 监控类页面
长列表 虚拟滚动(日志类页面 >1000 行时) 按需

度量先行:CI 加 rollup-plugin-visualizer 产物报告,chunk 超阈值(如 500KB)报警。


五、双端一致性规范(迁移期)

5.1 契约清单(迁移开始前统一,不等迁移完成)

项 统一值(推荐) 说明
token key <app>.auth.token 迁移期「读旧写新」一个版本
暗色 key <app>.theme.mode 同上
模块开关键 <app>.modules.<name>.enabled 常量两端同名,注释指向后端 API
会话存储结构 字段名一致 localStorage 布局对齐
响应契约 同一份 code/data/msg + 错误分级 见 03 章
权限语义 权限码清单同源(单一文档维护) 见 04 章
路由路径 两端一致 互通书签
ESLint / Prettier 同大版本、同规则 配置可复制

执行方式:契约清单进 docs/(一页表),双端各引用;改任何一项 = 双端 PR 同步。副端纪律:不抢先实现主端没有的功能;mock 显式开关、生产禁用;每对齐一个域删除对应 mock(向真实收敛)。


六、CI/CD

6.1 标准流水线(adp 范式裁剪)

PR 触发:
  job lint     eslint + prettier --check + vue-tsc/tsc
  job test     vitest --coverage(阈值卡点)
  job build    vite build
  job e2e      主分支 PR:playwright(webServer 自动拉起前后端)
main 合并:
  构建产物部署(嵌入后端二进制 / 静态托管)

CI 增强项:madge 循环依赖检查、styles 入口引用检查、产物体积报告。CI 与本地命令同源(CI 里跑 make 目标,不另写一套脚本)。


七、文档与可观测性

7.1 文档治理(制度)

文档 责任
新模块指南 新模块五列表(菜单/路由/页面/API/权限码)同步
信息架构文档 分组/菜单行为描述与实现同步
删除性重构 过期段落归档,不留「描述已删除组件」的漂移文档
CHANGELOG 只描述现存功能

规则:实现与文档不一致 = 文档 bug,同一 PR 修复。

7.2 版本可观测

  • 设置页「关于」展示 __APP_VERSION__ / commit hash / 构建时间(构建指纹注入)
  • 全局错误上报预留钩子(gva core/error-handel.js 式),先 console.error 收口,接 Sentry 留接口
  • 可选:页面版本更新提示(pure 的 version-rocket:新版本发布后提醒用户刷新)

八、最佳实践清单

✅ 要做

  1. pre-commit 快修复 + CI 慢检查的分层流水线
  2. 请求层与权限纯函数优先补测试
  3. 双端 vite 配置结构镜像;契约清单一页表维护
  4. CI 与本地同源(make 目标)
  5. 每次构建带版本指纹,关于页可见

❌ 不要

  1. 不要双份 e2e/eslint 配置文件并存(配置漂移源头)
  2. 不要 CI 跑本地跑不通的命令(或反之)
  3. 不要 console.log 进生产(尤其 token 片段)
  4. 不要在 mock 数据里放真实用户名/密钥样式的假数据
  5. 不要为「以后可能用到」保留死配置、死样式、空目录

九、AI 检查清单(对比目标工程逐项核对)

P0(安全与一致性)

  1. 生产路径上是否有 console.log(尤其 token 片段打印)?
  2. 双端(若有)token/主题 key 是否同名?配置文件是否双份并存?
  3. mock 是否显式开关(是否存在网络错误静默回退假数据)?

P1(质量基建)

  1. lint 流水线是否分层(pre-commit 快修 + CI 慢查)?stylelint/commitlint 是否齐配?
  2. 请求层与权限纯函数是否有测试?coverage 阈值是否配置?
  3. CI 是否有循环依赖检查、产物体积报告?
  4. 构建指纹是否注入并在关于页展示?

P2(体验与治理)

  1. 文档漂移清单(描述已不存在实现的文档段落)列出并归档
  2. 运行时配置(VITE_GLOB / platform-config.json)是否值得引入
  3. 错误上报钩子是否预留

至此八章完毕。回到 00-目录与概览 复查十大黄金法则,或按各章「AI 检查清单」逐项对比目标工程输出优化任务。