全新的前端ui

This commit is contained in:
eafonyang
2026-07-16 16:34:18 +08:00
parent 1a9003261d
commit e59d9c72ee
352 changed files with 39009 additions and 196 deletions
@@ -0,0 +1,103 @@
---
kind: build_system
name: Docker Compose 多阶段构建与脚本化部署
category: build_system
scope:
- '**'
source_files:
- docker-compose.yml
- backend/Dockerfile
- frontend/Dockerfile
- scripts/upload.sh
- frontend/vite.config.js
- frontend/nginx.conf
- DEPLOY.md
---
## 构建系统概览
项目采用 pnpm + Vite + Docker Compose 的现代化 Node.js/Vue 3 单体仓库构建方案,通过多阶段 Docker 镜像实现前后端分离部署。
### 核心构建工具链
- 包管理: pnpm@11.5.2(通过 packageManager 字段锁定版本)
- 前端构建: Vite 6.x + Vue 3,支持手动分包(manualChunks)优化
- 后端运行: Node.js 22 AlpineExpress + Sequelize
- 容器编排: Docker Compose,双服务架构(frontend: nginx, backend: node
### 构建流程
前端构建 (frontend/)
```bash
cd frontend && pnpm install && pnpm build
# 产物输出至 frontend/dist/
```
Vite 配置关键特性:
- 开发服务器端口 3000,自动代理 /api 到 localhost:8083
- 生产环境启用 Gzip、静态资源长期缓存(1年 immutable
- 手动分包策略:vendor-vue、vendor-element-plus、vendor-lucide
后端构建 (backend/)
```bash
cd backend && pnpm install --prod && node src/app.js
```
### Docker 多阶段镜像
后端镜像 (backend/Dockerfile)
- 基础镜像:node:22-alpine
- 仅安装生产依赖(--frozen-lockfile --prod
- 暴露端口 8000,启动命令 node src/app.js
前端镜像 (frontend/Dockerfile)
- 构建阶段:node:18-alpine + pnpm 全局安装
- 运行阶段:nginx:alpine,仅包含静态文件
- 通过 COPY --from=builder 复制构建产物
### 服务编排
docker-compose.yml 定义两个服务:
- backend: 端口映射 8083->8000,挂载 OTA 存储卷 /data/projects/source
- frontend: 端口映射 8082->80,挂载 dist 和 nginx.conf
- 自定义网络 audio-network 实现服务间通信
- 统一日志轮转配置(单文件 10MB,保留 5 个文件)
Nginx 反向代理将 /api 请求转发至 http://backend:8000,支持 Vue Router history 模式和 8MB 文件上传。
### 部署脚本
scripts/upload.sh 提供一键同步能力:
- 预设目标:frontend、backend、compose、all
- 基于 rsync + SSH 密钥认证
- 支持 dry-run 模式预览同步内容
- 默认上传路径:ubuntu@ec2:/data/project/dashboard/
### 环境变量管理
- 开发环境:根目录 .env,通过 dotenv 加载
- 生产环境:Compose env_file 指定 .env,覆盖容器内 PORT=8000
- 敏感信息(JWT_SECRET、数据库密码等)不提交 Git
### 本地开发工作流
```bash
# 后端开发
cd backend && pnpm dev # nodemon 热重载,端口 8083
# 前端开发
cd frontend && pnpm dev # Vite 开发服务器,端口 3000
```
### 版本策略
- 前后端均使用 1.0.0 版本号(语义化版本占位)
- 无自动化发布流水线,通过脚本手动触发部署
- 依赖锁定文件(pnpm-lock.yaml)确保构建可重现性
### 注意事项
- 前端 Dockerfile 使用 Node 18,但 packageManager 指定 pnpm@11.5.2,需确保兼容性
- 后端 Dockerfile 使用 Node 22,与 packageManager 版本一致
- OTA 升级包通过宿主机卷持久化,避免容器重启丢失
- 生产环境建议通过 EC2 IAM 角色访问 S3,无需硬编码 AWS 凭证
@@ -1 +0,0 @@
前端:Vue 3 + Vite + Element Plus + vue-router + axios;后端:Express + Sequelize(ORM) + MySQL2 + JSON Web Token + Multer(文件上传) + Axios(上游曲线服务) + Winston(日志) + ioredis + @aws-sdk/client-s3;构建产物由 Nginx 静态托管,开发期使用 nodemon 热重载。
@@ -1,5 +0,0 @@
仓库为前后端同仓部署结构:
- `backend/src` 采用经典 Express 分层:`app.js` 入口挂载 CORS、JSON/bodyLimit 中间件后按目录遍历加载 `routes/*``models/*` 通过 Sequelize 定义 ORM 实体并由 `config/database.js` 初始化连接;`services/*` 封装外部依赖(S3/OtaStorage/MeasurementStorage/CurveClient/Squiglink),`middleware/auth.js` 负责 JWT 校验,`validators/*` 使用 Zod 做入参校验。
- `frontend/src``layout/index.vue` 作为全局壳,内部用 `el-container` 组合侧栏(`sidebar-glass`)、顶栏(`lux-header`)、主内容区(`TabsView` 多标签页)和底栏;路由由 `router/index.js` 驱动,API 调用集中在 `api/*.js`,鉴权状态在 `utils/auth.js`
- 样式体系完全收敛到 `frontend/src/styles/lux-theme.css`,通过 `:root` CSS 变量统一色板、模糊半径、阴影层级,并以 `.lux-shell` 命名空间覆盖 Element Plus 组件默认样式,实现 Glassmorphism + Dimensional Layering + Dark Mode OLED 三层次视觉。
- 部署层由根级 `docker-compose.yml` 编排:后端容器暴露 8083,前端以 nginx:alpine 静态托管 `frontend/dist`,并通过 `nginx.conf` 反向代理 `/api` 到后端;`autoeq/` 下存放测量 CSV 数据供服务读取。
@@ -1 +0,0 @@
基于 Vue3 + Element Plus 与 Express/Sequelize 的耳机品牌型号 OTA 管理平台,提供玻璃拟态暗色主题的管理后台。
@@ -1 +0,0 @@
本地启动需先复制 `.env.example``.env` 并填写数据库/Redis/S3 等环境变量;运行 `docker compose up -d` 即可同时拉起后端与前端(端口 8082/8083)。前端单独开发:`cd frontend && pnpm dev`;后端单独开发:`cd backend && pnpm dev`
@@ -1,6 +0,0 @@
- CSS 主题通过 `:root` 下的 `--lux-*` 变量集中管理颜色、模糊、阴影、圆角,组件样式一律引用这些变量而非硬编码色值。
- 所有覆盖 Element Plus 的全局样式都包裹在 `.lux-shell` 命名空间下,避免污染登录页等非 shell 页面。
- 后端路由文件只导出 `{ path, handler }` 对象数组,由 `routes/index.js` 统一遍历注册,新增接口只需新建文件并在 index 中引入。
- 模型定义遵循 `src/models/<Name>.js` 单文件一个 Sequelize Model 的模式,并通过 `src/models/index.js` 统一关联与导出。
- 业务逻辑从路由中下沉到 `src/services/*`,路由仅做参数校验与响应包装,保持控制器薄而纯。
- 前端 API 模块按资源维度拆分为 `api/*.js`,每个模块暴露同名函数,组件通过 `import { listModels } from '@/api/model'` 直接调用。
@@ -1,6 +1,6 @@
schema_version: 1
module_path: ""
title: Luxsin CMS Dashboard(前后端单体仓库)
title: Luxsin 音频设备管理后台(前后端单体仓库)
scope: []
source_files: []
depends_on: []
@@ -0,0 +1 @@
后端:Express + Sequelize + JWT + Redis + Meilisearch + AWS S3X9 OTA 包存储)+ squiglink 曲线客户端;前端:Vue 3 + Vite + Element Plus + axios;构建与运行:pnpm v11、Node 22、Docker ComposeNginx 静态托管 + Node API)。
@@ -0,0 +1,7 @@
仓库采用前后端分离、Docker Compose 编排的单体部署形态:
- `backend/src` 为 Express 应用,入口 `app.js` 通过 `routes/index.js` 聚合各业务路由(auth、brands、models、ota、blacklist、users 等),按 MVC 分层组织:`models/` 使用 Sequelize 定义数据模型并统一由 `models/index.js` 初始化连接;`services/` 封装外部依赖(S3、Redis EQ 缓存、Meilisearch、squiglink 曲线服务、OTA 存储);`middleware/` 注入认证与请求体大小限制;`validators/` 用 zod 校验入参。
- `frontend/` 为 Vue 3 + Element Plus SPAVite 构建产物 `dist/` 由 Nginx 容器静态托管,并通过 `/api` 反向代理到后端 8000 端口;`src/api/` 按领域拆分 API 调用,`views/` 对应功能页面,`components/` 存放通用组件(TabsView、ChangePasswordDialog 等)。
- `frontend_v2/` 是基于 Soybean Admin 模板的重构分支,采用 pnpm workspace 多包结构(@soybeanjs/axios、hooks、scripts 等),尚未替换主前端。
- `autoeq/` 存放第三方测量 CSV/TXT 数据及日期归档,供 OTA 推送时读取频响曲线。
- 根级 `docker-compose.yml` 编排 backendNode 22 Alpine 镜像)与 frontendnginx:alpine)两个服务,共享 `audio-network` 网络,宿主机卷挂载 `/data/projects/source` 用于 X9 OTA 包本地存储。
- 部署脚本 `scripts/upload.sh` 负责将 dist、后端源码、compose 文件上传至服务器 `/data/project/dashboard/`,环境变量集中维护在根 `.env`
@@ -0,0 +1 @@
基于 Node.js + Vue 3 的 Luxsin 音频设备与 OTA 升级管理后台,提供品牌/型号/黑名单/OTA/用户等管理能力。
@@ -0,0 +1 @@
首次部署需在服务器创建 `/data/project/dashboard/.env`(参考 `.env.example`)并手动上传代码后执行 `docker compose build --no-cache backend && docker compose up -d`;本地开发推荐先 `cd frontend && pnpm build` 生成 dist,再分别启动后端与前端 dev server,或直接用 `./scripts/upload.sh all` 一键上传。
@@ -0,0 +1,5 @@
- 后端路由按领域拆分为独立文件(如 `routes/models.js``routes/ota.js`),并在 `routes/index.js` 中统一注册,控制器内直接操作 Sequelize model。
- 每个业务模块配套一个 `validators/<module>.js`,使用 zod schema 对入参进行结构化校验,路由层在执行业务前调用 validator。
- 对外部依赖(S3、Redis、Meilisearch、squiglink)统一收敛到 `services/` 目录下的单一 client 文件,路由层不直接调用 SDK。
- 前端 API 调用按领域拆分到 `src/api/*.js`,统一通过 `src/utils/request.js` 封装的 axios 实例发起,携带 JWT 与基础路径。
- 前端视图按功能域划分目录(`views/brand/``views/model/``views/ota/` 等),复杂页面内部再细分 `components/``composables/`
+3 -3
View File
@@ -3,11 +3,11 @@ schema_version: 1
locale: zh-CN
branch: main
nodes_managed: true
exported_at: "2026-07-15T01:54:51Z"
exported_at: "2026-07-16T07:23:16Z"
modules:
"":
dir_name: Luxsin CMS Dashboard(前后端单体仓库)
title: Luxsin CMS Dashboard(前后端单体仓库)
dir_name: Luxsin 音频设备管理后台(前后端单体仓库)
title: Luxsin 音频设备管理后台(前后端单体仓库)
scope: []
source_files: []
children: []
@@ -0,0 +1,41 @@
---
kind: dependency_management
name: pnpm 多包工作区与镜像源管理
category: dependency_management
scope:
- '**'
source_files:
- backend/package.json
- frontend/package.json
- frontend_v2/package.json
- frontend_v2/pnpm-workspace.yaml
- frontend_v2/.npmrc
---
## 1. 使用的系统/工具链
- **包管理器**:统一使用 pnpm(v11),通过 `packageManager` 字段锁定版本,确保团队一致。
- **锁文件策略**:后端 `backend/` 提交 `pnpm-lock.yaml`;前端 `frontend/` 同时存在 `pnpm-lock.yaml``package-lock.json`(后者为历史遗留);`frontend_v2/` 仅提交 `pnpm-lock.yaml`
- **私有仓库/镜像**`frontend_v2/.npmrc` 配置淘宝镜像 `https://registry.npmmirror.com/``frontend/` 未显式配置 `.npmrc`,默认走官方源。
- **无 vendor 目录**:三个子项目均未将 `node_modules` 或第三方源码纳入版本控制,依赖通过安装生成。
## 2. 关键文件与包
- `backend/package.json` — 后端 API 依赖声明(Express、Sequelize、MySQL2、JWT、Axios、Zod、AWS S3 SDK、Winston、ioredis 等)。
- `frontend/package.json` — 旧版前端(Vue 3 + Element Plus + Vite)依赖。
- `frontend_v2/package.json` — 新版前端模板(Soybean Admin,基于 Vue 3 + Naive UI + UnoCSS + TypeScript)。
- `frontend_v2/pnpm-workspace.yaml` — 定义 Monorepo 工作区,包含 `packages/*` 下的内部包(@sa/axios@sa/color@sa/hooks@sa/materials@sa/utils@sa/scripts@sa/uno-preset)。
- `frontend_v2/.npmrc` — 指定 npm 镜像源。
- 各子项目 `.gitignore` 均忽略 `node_modules/``dist/``.env*` 等。
## 3. 架构与约定
- **Monorepo 结构**`frontend_v2/` 采用 pnpm workspace,根 `package.json` 作为聚合入口,业务代码在 `src/`,可复用能力下沉到 `packages/` 下以 `workspace:*` 协议引用。
- **版本范围策略**`backend/``frontend/` 的依赖普遍使用 `^major.minor` 宽泛范围,便于自动升级;`frontend_v2/` 则对核心依赖使用精确版本号(如 `vue: 3.5.34``naive-ui: 2.44.1`),配合 `simple-git-hooks``update-pkg` 脚本统一管理更新。
- **Node 引擎约束**`frontend_v2/` 通过 `engines` 强制 Node ≥ 20.19.0、pnpm ≥ 10.5.0,避免环境差异导致的依赖解析问题。
- **构建期依赖隔离**`frontend_v2/pnpm-workspace.yaml``allowBuilds` 明确禁止 esbuild、@parcel/watcher 等构建工具在工作区内被提升,减少重复安装。
## 4. 开发者应遵循的规则
1. **统一使用 pnpm**:新增依赖一律通过 `pnpm add [-D] <pkg>` 操作,不要手动编辑 `package.json` 后自行安装。
2. **不提交 node_modules**:所有子项目的 `.gitignore` 已忽略 `node_modules/`,请勿将其纳入版本控制。
3. **镜像源一致性**:新成员应在本地 `.npmrc` 中配置 `registry=https://registry.npmmirror.com/`,与 `frontend_v2/` 保持一致,避免下载缓慢或失败。
4. **Monorepo 内共享包**:如需在 `frontend_v2/packages/` 间共享代码,使用 `workspace:*` 协议并在 `pnpm-workspace.yaml``packages` 列表中添加路径。
5. **依赖版本策略**:公共库建议固定主版本(`^x.y.z`),框架核心依赖参考 `frontend_v2/` 的精确版本写法以保持稳定性。
6. **更新流程**:优先使用 `pnpm update``pnpm sa update-pkg`(在 `frontend_v2/` 中)进行批量升级,并检查 `pnpm-lock.yaml` 变更后再提交。
@@ -0,0 +1,37 @@
---
kind: frontend_style
name: 前端样式体系:双前端并存(Element Plus 玻璃拟态 + NaiveUI/UnoCSS 主题系统)
category: frontend_style
scope:
- '**'
source_files:
- frontend/src/styles/lux-theme.css
- frontend/package.json
- frontend_v2/uno.config.ts
- frontend_v2/src/theme/settings.ts
- frontend_v2/src/theme/preset/dark.json
- frontend_v2/src/styles/css/global.css
---
仓库包含两套独立的前端实现,各自采用不同的 UI 与样式方案:
## frontend(当前生产版本)
- **框架与组件库**Vue 3 + Element Plus 2.xVite 构建。
- **样式方法论**:单文件 CSS 主题覆盖,核心位于 `src/styles/lux-theme.css`,通过 `.lux-shell` 根容器限定作用域,使用大量 `!important` 覆盖 Element Plus 默认样式。
- **设计语言**:自研「Luxsin CMS Design System」,风格为「Glassmorphism + Dimensional Layering + Dark Mode OLED」。以 `:root` 变量定义品牌色板(--lux-cyan、--lux-coral、--lux-indigo 等)、玻璃表面透明度、模糊层级(--lux-blur-*)、阴影层级(--lux-shadow-1~4)、圆角(--lux-radius-*),并通过 `backdrop-filter` 实现侧栏、卡片、对话框、下拉菜单的毛玻璃效果。
- **布局结构**`.lux-shell``.sidebar-glass`(可折叠 64px/220px+ `.lux-header` + `.lux-main` + `.lux-footer`,侧栏与顶栏均为浮动玻璃层。
- **响应式策略**:未引入响应式工具库,主要依赖 Flexbox 与固定宽度侧栏;无断点媒体查询。
- **图标**`@lucide/vue`
## frontend_v2(重构/预览版)
- **框架与组件库**Vue 3 + Naive UI + TypeScript,基于 SoybeanAdmin 模板。
- **原子化样式**Unocss`uno.config.ts`+ Tailwind 预设 `presetWind3`,并集成自定义 preset `@sa/uno-preset`;提供 `card-wrapper` 等 shortcuts。
- **主题系统**:集中式 JSON 预设(`src/theme/preset/*.json`default/dark/azir/compact+ `settings.ts` 运行时配置,支持 light/dark 切换、灰度/色弱模式、主色/辅助色、圆角、布局模式(vertical/horizontal/mix)、Tab 模式、水印等。主题 tokens 通过 `theme/vars.ts` 注入 Unocss theme。
- **全局样式分层**`src/styles/css/`reset、nprogress、transition、global+ `src/styles/scss/`global.scss、scrollbar.scss)。
- **国际化**`src/locales/` 下 zh-cn/en-us 文案,配合 `vue-i18n`
- **图标**`@iconify/vue` + `unplugin-icons` 按需加载。
## 开发者约定
-`frontend` 中新增样式应追加到 `lux-theme.css` 内对应区块,遵循 `--lux-*` 变量命名,避免直接写死颜色值。
-`frontend_v2` 中优先使用 UnoCSS 原子类;需要扩展时修改 `uno.config.ts``shortcuts``theme`,主题色调整走 `src/theme/preset/*.json``settings.ts`
- 两套前端互不引用,业务页面按目录 `views/<模块>/index.vue` 组织,组件复用集中在 `components/``composables/`
@@ -0,0 +1,47 @@
---
kind: configuration_system
name: 后端 .env + 前端 Vite 环境变量双轨配置体系
category: configuration_system
scope:
- '**'
source_files:
- backend/src/config/loadEnv.js
- backend/src/config/env.js
- backend/src/config/database.js
- backend/src/config/redis.js
- backend/src/config/logger.js
- backend/src/app.js
- .env.example
- frontend_v2/.env
- frontend_v2/vite.config.ts
---
## 系统概览
本仓库采用「后端 Node.js + 前端 Vue3/Vite」前后端分离的单体部署模式,配置系统分为两条独立轨道:
- **后端**:基于 `dotenv` 从根目录 `.env` 加载,通过 `process.env` 注入;启动时由 `src/config/loadEnv.js` 统一读取。
- **前端(v2**:基于 Vite 的 `loadEnv`,按 `VITE_` 前缀暴露给浏览器,支持多环境文件 `.env` / `.env.prod` / `.env.test`
## 关键文件与包
- `backend/src/config/loadEnv.js` — 项目入口最先执行,解析根目录 `.env`Docker 场景下由 compose env_file 覆盖)。
- `backend/src/config/env.js` — 提供 `APP_ENV``isDevelopment``isProduction` 三个布尔/字符串常量,供各模块判断运行环境。
- `backend/src/config/database.js` — Sequelize 连接串,所有 MySQL 参数均走 `DATABASE_*` 环境变量,开发默认 `localhost:3306/audio/root/root123`
- `backend/src/config/redis.js` — ioredis 客户端单例工厂 `getEqCacheRedis()`,通过 `REDIS_HOST/PORT/PASSWORD/EQ_DB` 控制,带错误日志与重连策略。
- `backend/src/config/logger.js` — winston 实例,固定输出到 `backend/logs/app.log` 与控制台,无运行时可配级别。
- `backend/src/app.js` — 应用入口,先 `require('./config/loadEnv')` 再挂载中间件、路由,最后以 `process.env.PORT` 监听。
- `backend/.env.example` — 完整的环境变量清单(数据库、JWT、Meilisearch、S3、OTA URL、Curve API、Redis 等),是部署时的权威参考。
- `frontend_v2/.env` / `.env.prod` / `.env.test` — Vite 构建期环境变量,全部以 `VITE_` 前缀命名,被 `vite.config.ts` 通过 `loadEnv` 读取并注入到 `define`/`server.proxy` 中。
- `frontend_v2/vite.config.ts` — 使用 `loadEnv(configEnv.mode, process.cwd())` 加载对应环境的 `.env*`,并将 `base``proxy``sourcemap` 等构建选项与之一一对应。
## 架构与约定
1. **加载顺序**`app.js``require('./config/loadEnv')``dotenv.config({ path: root/.env })` → 后续各 `config/*.js` 直接读 `process.env`。这保证了在 Docker 中以 `env_file` 注入的变量优先级高于本地 `.env`
2. **环境标识**:仅依赖单一变量 `APP_ENV`development | production),不提供 staging 等中间态;各模块用 `isDevelopment`/`isProduction` 做分支逻辑(如 Sequelize logging、OTA 上传目录回退到系统临时目录)。
3. **配置分层**:没有集中式配置对象,每个子系统(DB、Redis、Logger、JWT、S3、OTA URL)各自在自己的 config 文件中按需读取 `process.env`,形成“分散但自描述”的配置结构。
4. **前端隔离**Vite 只把 `VITE_` 前缀的变量注入到客户端代码,敏感信息不会进入产物;后端变量与前端变量完全解耦,避免泄露风险。
5. **默认值策略**:所有关键配置都提供合理的本地开发默认值(MySQL root/root123、Redis 空密码、端口 8083/9527),保证克隆后 `pnpm dev` 即可运行。
## 开发者应遵循的规则
- **新增环境变量**:先在根目录 `.env.example` 补充条目与注释,再在对应 `config/*.js``vite.config.ts` 中消费;不要硬编码路径或密钥。
- **区分环境**:通过 `APP_ENV` 切换行为,不要在业务代码里写死 `if (process.env.NODE_ENV)` 之类的判断。
- **安全边界**:任何包含密钥、密码、私钥的变量一律不进源码,仅出现在 `.env.example`(占位值)和 CI/CD 的 secrets 中;前端变量必须以 `VITE_` 开头。
- **Docker 优先**:容器内不依赖 `.env` 文件,所有变量应由 `docker-compose.yml``environment`/`env_file` 注入;本地开发才使用根目录 `.env`
- **前端构建期变量**:修改 `VITE_*` 需要重新 build,而非热重载生效;生产环境通过 `.env.prod` 控制打包产物。
@@ -0,0 +1,41 @@
---
kind: logging_system
name: 后端日志系统(Winston 文件+控制台输出)
category: logging_system
scope:
- '**'
source_files:
- backend/src/config/logger.js
- backend/src/app.js
- backend/logs/app.log
---
## 1. 使用的框架与工具
- 日志框架:winston v3,通过 backend/src/config/logger.js 统一创建并导出单例实例。
- 依赖声明在 backend/package.json 中:"winston": "^3.14"。
- 前端(frontend / frontend_v2)未发现独立的日志模块,主要使用浏览器 console,未纳入本仓库的日志体系。
## 2. 核心文件与位置
- backend/src/config/logger.js — winston 初始化、格式、传输层配置。
- backend/src/app.js — 应用入口,启动时记录数据库同步、服务监听等关键事件。
- backend/logs/app.log — 默认文件输出路径(由 logger 自动创建目录)。
## 3. 架构与约定
- 全局单例模式:所有模块通过 require('./config/logger') 获取同一 logger 实例,避免重复配置。
- 日志级别策略:默认 level 为 info,业务代码按语义选择 info/warn/error;未发现 debug 级别的使用。
- 结构化字段:通过 printf 将 timestamp、level、message 以及任意 meta 对象序列化为 JSON 字符串拼接在消息末尾,便于后续解析。
- 双通道输出:同时写入 Console 和 Filelogs/app.log),未做按级别分文件、轮转或远程收集的配置。
- 错误处理:路由与服务层捕获异常后统一 logger.error(...) 输出,未定义全局错误中间件集中记录 HTTP 请求日志。
- 数据库日志:Sequelize 仅在开发环境开启 SQL 日志到 console.log,生产环境关闭,不进入 winston。
- Redis 缓存:EQ 缓存读写失败通过 logger.error 记录,属于业务级告警而非基础设施错误。
## 4. 开发者应遵循的规则
- 统一导入:在需要日志的模块顶部 const logger = require('../config/logger');,禁止直接使用 console.log 输出业务信息。
- 级别选择:
- info:正常业务流程关键点(登录成功、数据创建/更新、服务启动)。
- warn:可恢复的异常情况(资源不存在、参数校验失败但返回 4xx)。
- error:不可恢复错误或外部调用失败(DB/Redis/HTTP 异常)。
- 结构化元数据:尽量以第三个参数传入对象,例如 logger.info('User logged in', { username }),以便后续提取字段。
- 敏感信息脱敏:不要在日志中记录密码、token、完整手机号等敏感字段。
- 性能考虑:当前无日志轮转,生产环境需配合外部 logrotate 或容器日志采集方案,避免 app.log 无限增长。
- 前端日志:前端未集成统一日志 SDK,如需埋点建议在后端 API 层记录请求上下文(IP、UA、耗时等),前端仅保留调试用 console。
@@ -1,52 +0,0 @@
---
kind: configuration_system
name: 后端环境变量与配置加载体系
category: configuration_system
scope:
- '**'
source_files:
- backend/src/config/loadEnv.js
- backend/src/config/env.js
- backend/src/config/database.js
- backend/src/config/redis.js
- backend/src/config/logger.js
- .env.example
- backend/src/app.js
---
## 系统概述
本项目的配置系统基于 Node.js 的 `dotenv` + 进程环境变量(`process.env`)实现,采用「根目录 `.env` 文件 + Docker compose env_file 注入」的双源模式,通过统一的入口在应用启动时完成加载。
## 核心机制
- **统一入口**`backend/src/app.js` 首行 `require('./config/loadEnv')` 触发配置加载,确保所有后续模块都能读到环境变量。
- **本地开发**`loadEnv.js` 解析项目根目录 `dashboard/.env`(相对 `__dirname` 向上四层),使用 `dotenv.config({ path })` 注入到 `process.env`;若文件不存在则静默跳过。
- **Docker 部署**:容器内无 `.env` 文件,由 `docker-compose.yml``env_file` 直接注入环境变量,`fs.existsSync` 判断避免覆盖已有值。
- **环境判断**`config/env.js` 暴露 `APP_ENV``isDevelopment``isProduction` 三个常量,供各模块按环境切换行为(如 Sequelize SQL 日志开关)。
## 配置项组织
所有可配置项集中在根级 `.env.example`,按功能域分组注释:
- 数据库:`DATABASE_HOST/PORT/NAME/USER/PASSWORD`
- 应用:`APP_NAME``APP_ENV``PORT`
- JWT 与初始管理员:`JWT_SECRET``DASHBOARD_ADMIN_USERNAME/PASSWORD`
- Meilisearch`MEILISEARCH_URL/API_KEY/INDEX`
- AWS S3`AWS_REGION/ACCESS_KEY_ID/SECRET_ACCESS_KEY/S3_OTA_BUCKET/S3_MEASUREMENT_BUCKET`
- OTA URL 与上传目录:`OTA_X8_PUBLIC_BASE``OTA_X9_URL_BASE``OTA_UPLOAD_DIR`
- Curve API`CURVE_API_BASE_URL`
- Redis EQ 缓存:`REDIS_HOST/PORT/PASSWORD/EQ_DB`
## 配置消费方式
各模块直接通过 `process.env.XXX || '默认值'` 读取,形成「分散式消费」模式:
- `config/database.js` → MySQL 连接参数
- `config/redis.js` → ioredis 客户端(含密码可选、错误监听)
- `config/logger.js` → winston 输出级别与文件路径
- `services/otaStorage.js` → OTA 包上传目录与 S3 配置
- `services/measurementStorage.js` → 频响测量文件 S3 存储
- `routes/models.js` → Meilisearch 搜索索引
- `services/curveClient.js` → 曲线查询外部 API 基地址
## 设计约定与约束
1. **禁止硬编码敏感信息**:所有密钥、密码、URL 必须来自环境变量,`.env` 已在 `.gitignore` 中排除。
2. **默认值兜底**:每个 `process.env` 读取都提供合理默认值,保证本地开箱即用。
3. **按域拆分配置文件**:数据库、Redis、日志等基础设施各自独立文件,便于扩展新依赖。
4. **Docker 优先**:生产环境推荐通过 compose `env_file` 注入而非挂载 `.env` 文件。
5. **新增配置项流程**:先在 `.env.example` 添加注释说明,再在各消费处补充 `process.env.XXX || default`
@@ -0,0 +1,42 @@
---
kind: error_handling
name: 后端统一响应与前端拦截器式错误处理
category: error_handling
scope:
- '**'
source_files:
- backend/src/utils/response.js
- backend/src/middleware/auth.js
- backend/src/app.js
- backend/src/config/redis.js
- frontend/src/utils/request.js
---
## 1. 采用的体系与模式
- 后端:Express + Sequelize**无全局错误中间件**。每个路由 handler 使用 `try/catch` 包裹业务逻辑,捕获异常后通过 `logger.error` 记录日志,再以统一的 `ApiResponse.error()` 返回 `{ code, msg, data }` 结构。
- 前端(frontend):基于 axios 的**请求/响应拦截器**集中处理 HTTP 状态码与业务码 `code === 0` 的错误,自动弹出 ElMessage、401 时清除本地 token 并跳转登录页。
- 前端(frontend_v2):采用 alova + Naive UI 的独立实现,错误处理策略与 frontend 类似但组件库不同。
- 未使用自定义 Error 类、未定义业务错误码枚举,也未使用 `throw new CustomError(...)` 这类结构化错误对象;错误信息以字符串形式在路由层直接构造。
## 2. 关键文件与位置
- 后端统一响应封装:`backend/src/utils/response.js`
- 认证中间件(401/403 错误入口):`backend/src/middleware/auth.js`
- 应用启动与数据库同步异常兜底:`backend/src/app.js`
- Redis 连接错误监听:`backend/src/config/redis.js`
- 前端请求封装与拦截器:`frontend/src/utils/request.js`
- 各业务路由(大量 try/catch + ApiResponse.error 示例):`backend/src/routes/*.js`auth.js、blacklist.js、brands.js 等)
## 3. 架构与约定
- **统一响应体**:所有成功/失败接口均返回 `{ code: 1|0|2, msg, data }``code=1` 成功,`code=0` 业务错误,`code=2` 无数据。调用方可据此判断是否继续。
- **HTTP 状态码约定**:认证失败返回 401,权限不足返回 403,其余业务错误默认 200 + `code=0`。未对 5xx 做全局兜底,依赖 Node 默认行为或路由内 catch。
- **错误传播路径**:路由层 → `ApiResponse.error(msg)` → 前端响应拦截器 → `ElMessage.error(res.msg)` 或直接 reject Promise,由业务组件自行处理。
- **鉴权错误**`authMiddleware` 区分 TokenExpiredError 与普通解析错误,分别返回“登录已过期”和“无效凭证”,前端据此提示并跳转。
- **可跳过全局提示**:前端支持在请求配置中设置 `skipErrorToast: true`,让上层组件自行控制错误提示(如推送进度弹窗场景)。
## 4. 开发者应遵循的规则
- 新增路由一律用 `try/catch` 包裹核心逻辑,catch 中先 `logger.error(e.message)`,再 `res.json(ApiResponse.error('中文错误描述'))`
- 不要直接 `throw` 自定义错误对象到上层;当前代码库没有全局错误处理器来消费它。
- 需要返回 HTTP 401/403 的场景(如鉴权、权限校验)优先使用 `authMiddleware``requireSuperAdmin`,避免在各路由重复实现。
- 前端发起请求时,如需自行展示错误(例如表单提交),可在 axios 配置中添加 `skipErrorToast: true`,并在 `.catch` 中手动 `ElMessage.warning/error`
- 对于网络超时、DNS 解析失败等底层错误,前端拦截器会统一提示“网络错误”,业务层无需重复处理。
- 若需引入更精细的错误分类(如参数校验失败 vs 数据库不可用),建议先在 `utils/response.js` 中扩展 `ApiResponse` 方法或在 `validators/` 中集中抛出带 code 的错误对象,再由路由层统一转换,以保持前后端一致。