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,231 @@
|
||||
# 02 — 项目架构与目录结构
|
||||
|
||||
> 参考:vue-vben-admin(三层包划分)、soybean-admin(文件路由 + store 纯函数分离)、ant-design-pro(页面 co-location)、vue-pure-admin(页面内聚五件套);补充:gin-vue-admin(分域 api/view)
|
||||
|
||||
---
|
||||
|
||||
## 一、组织目录的三种流派
|
||||
|
||||
### 1.1 流派对照
|
||||
|
||||
| 流派 | 代表 | 结构 | 优点 | 代价 |
|
||||
|------|------|------|------|------|
|
||||
| **按层分**(layer-first) | 早期中台 | `components/ views/ api/ stores/` 每层内平铺全部业务 | 上手简单 | 业务散在 5 个目录,删模块要全局找 |
|
||||
| **按域分**(domain-first) | **本标准(Vue 单包)/ gva** | 层目录保留,但 `api/user/`、`views/user/`、`stores/` 域内聚合 | 删域=删目录,心智清晰 | 需要约定维持层内域目录一致 |
|
||||
| **按功能分包**(feature-first) | adp 页面级、vben 包级 | 页面目录自带 service/mock/类型/样式;框架能力独立成包 | 高内聚,可整体搬移 | 需要晋升机制防止复制泛滥 |
|
||||
|
||||
**结论:中小工程用「按域分 + 页面 co-location」混合式**——全局按域(api/views 域目录对齐),页面私有代码留在页面目录内。
|
||||
|
||||
### 1.2 四标杆的目录精髓
|
||||
|
||||
```
|
||||
vue-vben-admin(依赖方向三层,分层标杆)
|
||||
apps/* ──▶ packages/effects/* ──▶ packages/@core/*
|
||||
(app 是唯一允许直接依赖具体 UI 库的层;
|
||||
@core 零 UI 依赖零业务;effects 通过 adapter 适配 UI 生态)
|
||||
|
||||
ant-design-pro(页面五件套 co-location)
|
||||
src/pages/table-list/
|
||||
├── index.tsx # 页面(ProTable 声明式列配置)
|
||||
├── service.ts # 本页接口(手写层)
|
||||
├── data.d.ts # 本页类型
|
||||
├── _mock.ts # 本页 mock(config 显式 include)
|
||||
└── components/
|
||||
├── CreateForm.tsx # 新建弹窗(trigger 模式)
|
||||
└── UpdateForm.tsx # 编辑弹窗(StepsForm 进 Modal)
|
||||
|
||||
soybean-admin(生成物 + store 纯函数分离,★★★★☆)
|
||||
src/
|
||||
├── router/elegant/ # 文件路由生成物(routes/transform/imports + RouteKey 类型 d.ts)
|
||||
├── service/{api,request}/ # api=纯请求函数、request=实例拦截器,两层分离
|
||||
├── store/modules/<mod>/ # 每模块 index.ts(状态编排) + shared.ts(可单测纯函数)
|
||||
├── typings/{api,...} # 全局 namespace 类型(Api/App/Storage/Env)
|
||||
└── views/_builtin/ # 403/404/500/login 内置页统一收纳,业务页平级
|
||||
|
||||
vue-pure-admin(页面内聚五件套,★★★★☆)
|
||||
src/views/system/user/
|
||||
├── index.vue # 纯模板(零逻辑,只解构 hook)
|
||||
├── form/index.vue # 弹窗表单
|
||||
├── tree.vue # 左树
|
||||
└── utils/{hook.tsx,rule.ts,types.ts} # 逻辑/校验/类型全在本域
|
||||
|
||||
gin-vue-admin(补充:全局分域 + 指令/钩子独立)
|
||||
src/
|
||||
├── api/ # 一域一文件:user.js menu.js ...
|
||||
├── pinia/modules/ # 一域一 store
|
||||
├── view/superAdmin/ view/example/ # 按业务分组
|
||||
├── directive/auth.js # v-auth 指令独立目录
|
||||
├── hooks/responsive.js # 组合式函数独立目录
|
||||
└── plugin/<name>/ # 业务插件 = 自带 view/api/assets 的小应用
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、标准目录结构(Vue 工程)
|
||||
|
||||
### 2.1 目标结构
|
||||
|
||||
```
|
||||
src/
|
||||
├── main.js # 入口:仅装配(EP按需、pinia、router、指令、全局组件)
|
||||
├── App.vue
|
||||
├── api/ # ★ 按功能域分目录,与 views 域目录同名
|
||||
│ ├── auth/ # captcha.js mfa.js
|
||||
│ ├── user/ # users.js roles.js permissions.js
|
||||
│ ├── rbac/ # 域小可单文件,大了再拆
|
||||
│ ├── system/ # menu.js modules.js logs.js ...
|
||||
│ └── <domain>/ # 业务域
|
||||
├── views/ # ★ 域目录与 api/ 一一对应
|
||||
│ ├── user/ # Users.vue + components/XxxFormDialog.vue ...
|
||||
│ ├── <domain>/
|
||||
│ └── _builtin/ # 403/404/500/login 内置页统一收纳(soybean 范式)
|
||||
├── stores/ # Pinia:一域一文件(auth.js menu.js site.js ...)
|
||||
├── composables/ # useXxx(依赖业务上下文的钩子)
|
||||
├── components/ # ★ 全局组件(需晋升,见第四章)
|
||||
├── layout/ # 布局骨架(业务页只挂内容区,禁止重写布局)
|
||||
├── router/ # index.js(含守卫) modules/(路由分文件)
|
||||
├── config/ # theme.js modules.js(纯配置,无副作用导入)
|
||||
├── typings/ # 全局契约类型(TS 渐进路线,soybean 四区)
|
||||
├── utils/ # request.js permission.js(无状态工具)
|
||||
└── styles/ # 全部文件必须有入口引用链
|
||||
```
|
||||
|
||||
React 工程同构映射:`views→pages`、`composables→hooks`、`stores→store`(zustand slices)、`components→components`(含 barrel 出口)。
|
||||
|
||||
### 2.2 层内规则(必须)
|
||||
|
||||
1. **api 域目录与 views 域目录强制同名**(`api/cron/` ↔ `views/cron/`);**禁止**在 api 根级别放散文件
|
||||
2. **store 文件名 = 导出名**(`stores/auth.js` → `useAuthStore`);单 store ≤300 行;推荐 soybean 的「index + shared」目录式(状态编排与纯函数分离)
|
||||
3. **layout/ 是禁改区**:业务页通过页面容器组件的 header/slot 定制,不碰布局骨架(可裁剪底座的前提)
|
||||
4. **components/ 只放「晋升组件」**(见第四章晋升机制),新页面私有组件一律 `views/<域>/components/`
|
||||
|
||||
### 2.3 可裁剪分层与模块开关(底座/脚手架推荐)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ 壳层 shell 登录/MFA/403/500 —— 不挂主布局 │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ 系统层 system 用户/RBAC/审计/设置 —— 底座自带 │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ 示例层 examples 演示模块 —— fork 后可整层删除 │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- 路由 `meta.layer: 'shell' | 'system' | 'examples'` 声明归属
|
||||
- 运行时开关:**源真相在后端**(如 `GET/PUT /api/system/modules`),localStorage 仅作缓存——**禁止**把 localStorage 当源真相
|
||||
- 构建期裁剪:环境变量(如 `VITE_ENABLE_EXAMPLES=false`)+ 路由中字面量比较,保证打包器 tree-shake 掉示例 chunk
|
||||
- 示例层代码**不得 import 系统层**内聚单元,保证整层可摘除;示例域附删除指引文档(EXAMPLES.md 惯例)
|
||||
|
||||
**分层是目录结构之外的第二根轴**:每个新模块必须先回答「我在哪一层」。
|
||||
|
||||
### 2.4 命名规范与类型目录
|
||||
|
||||
| 对象 | 规范 | 示例 |
|
||||
|------|------|------|
|
||||
| 组件文件 | PascalCase | `UserFormDialog.vue` |
|
||||
| 工具 / composable | camelCase,composable 带 use 前缀 | `request.js`、`usePagedQuery.js` |
|
||||
| 目录 | kebab-case(views 域目录用业务域名) | `user-management/`、`cron/` |
|
||||
| store 文件 | 文件名与导出同名 | `stores/auth.js` → `useAuthStore` |
|
||||
| API 文件 | 资源名复数 | `api/user/users.js` |
|
||||
| 常量 | UPPER_SNAKE_CASE | `SYSTEM_ORDER` |
|
||||
|
||||
类型目录(TS 渐进路线,soybean 范式):全局契约类型集中 `typings/`(Api / App / Storage / Env 四区 namespace,storage 与 env 均键级类型);页面私有类型随页面(`data.d.ts` / `utils/types.ts`);**禁止**同一类型定义在多个组件内重复出现。
|
||||
|
||||
---
|
||||
|
||||
## 三、页面 co-location(adp 五件套)
|
||||
|
||||
### 3.1 什么时候页面自带 service
|
||||
|
||||
```
|
||||
全局 api/<域>/xxx.js # 多页面复用、域级语义(users.js 的 list/create/delete)
|
||||
页面内 service.ts # 只服务本页的接口(dashboard 聚合、报表导出)
|
||||
```
|
||||
|
||||
判定:**接口第二个消费者出现时**,从页面 `service.ts` 提升到 `api/<域>/`。反向不成立——不要预防性提升。
|
||||
|
||||
### 3.2 页面目录模板
|
||||
|
||||
```
|
||||
views/<domain>/<Page>.vue # 页面骨架:容器 + 列表组件 + 子组件编排(≤400 行)
|
||||
views/<domain>/components/ # 本页私有组件(表单弹窗、详情抽屉、单元格渲染器)
|
||||
views/<domain>/composables/ # 本页私有逻辑(可选,超过 2 个页面组件共享时建)
|
||||
views/<domain>/utils/ # 本页 hook/rule/types(pure 范式,可选)
|
||||
views/<domain>/EXAMPLES.md # 仅示例层:删除指引
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、公共组件晋升机制
|
||||
|
||||
```
|
||||
第 1 次使用:写在页面 components/ 里
|
||||
第 2 次使用:复制一份,页面内注明来源 ← 允许的重复
|
||||
第 3 次使用:晋升 src/components/,删除两份复制 ← 必须执行
|
||||
```
|
||||
|
||||
晋升时同步做三件事:
|
||||
|
||||
1. **去业务化**:props 收口(`fetcher`/`permissions` 进来,具体 API 调用出去)
|
||||
2. **注册出口**:Vue 端全局组件在 `main.js` 注册;React 端进 `components/index.ts` barrel(adp:按「布局组件 / 业务组件」分组导出)
|
||||
3. **写使用说明**:组件头部注释 3 行(用途/必需 props/已知限制)
|
||||
|
||||
必备的两个全局页面组件(详见 05/07 章):**PageContainer**(页面容器:页头/面包屑/slot)与 **ListPage**(分页列表:fetcher + 筛选 slot + 表格透传 + 分页)。
|
||||
|
||||
---
|
||||
|
||||
## 五、架构守护:让目录约定不被腐蚀
|
||||
|
||||
| 守护手段 | 出处 | 可落地做法 |
|
||||
|----------|------|------------|
|
||||
| 循环依赖扫描 | vben `check:circular` | `npx madge --circular src/` 进 CI |
|
||||
| 依赖方向检查 | vben `check:dep`(@core 禁依赖 UI 库) | 示例层禁 import 系统层:ESLint `no-restricted-imports` 按路径分组 |
|
||||
| 死代码检测 | adp coverage 排除生成物 | CI 跑 `knip`/`depcheck`,styles 无入口文件直接报错 |
|
||||
| 生成物隔离 | adp `services/ant-design-pro/`(OpenAPI 生成,禁手改) | 生成物独立目录 + lint ignore |
|
||||
| 路由自动收集 | pure `router/modules/` + `import.meta.glob` | 新增路由文件零注册代码 |
|
||||
|
||||
---
|
||||
|
||||
## 六、最佳实践清单
|
||||
|
||||
✅ **要做**
|
||||
|
||||
1. api 域目录与 views 域目录同名;新域从脚手架起步(自动生成五处对照:菜单/路由/页面/API/权限码)
|
||||
2. 页面私有组件不出页面目录;晋升走「三次法则」
|
||||
3. 每个新模块先声明 `meta.layer`,示例层保持可整层摘除
|
||||
4. store 按域拆分、文件名=导出名、单 store ≤300 行
|
||||
5. 目录结构变化(新增域/晋升组件/删示例)在同一 PR 内更新架构文档
|
||||
|
||||
❌ **不要**
|
||||
|
||||
1. 不要在 api 根级别放散文件
|
||||
2. 不要把页面私有组件直接丢进 `src/components/`
|
||||
3. 不要让业务页 import layout 内部组件(只准用 slot 协议)
|
||||
4. 不要建「future/」「temp/」「new/」这类无语义目录
|
||||
5. 不要保留无入口引用的样式文件和空目录
|
||||
|
||||
---
|
||||
|
||||
## 七、AI 检查清单(对比目标工程逐项核对)
|
||||
|
||||
**P0**
|
||||
|
||||
1. api 与 views 域目录是否同名对齐?有无 api 根级散文件?
|
||||
2. store 文件名与导出名是否一致?有无超 300 行的 store?
|
||||
3. 有无空目录、无引用样式、描述已不存在目录的文档残留?
|
||||
|
||||
**P1**
|
||||
|
||||
4. 页面骨架是否 ≤400 行?超 400 行的视图列出拆分建议(参照 07 章)
|
||||
5. 私有组件是否越界进全局 components/?全局组件是否都有注册出口与头注释?
|
||||
6. 若为可裁剪底座:meta.layer 是否全覆盖?模块开关源真相是否在后端?
|
||||
7. CI 是否有循环依赖与死代码检查?
|
||||
|
||||
**P2**
|
||||
|
||||
8. 是否值得引入路由文件自动收集(`router/modules/` + glob)或文件路由(soybean @elegant-router)?
|
||||
9. `typings/` 全局类型目录是否建立(Api/App/Storage/Env 四区)?
|
||||
|
||||
---
|
||||
|
||||
> 下一篇:[03-请求层与数据流](03-请求层与数据流.md) —— 前端工程的血管系统。
|
||||
Reference in new issue
Block a user