You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

279 lines
12 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# FastAPI Admin · 前端工程web
基于 **Vue 3 + Vite + TypeScript + Element Plus** 的后台管理前端,与 FastAPI Admin 后端配套使用。状态管理为 **Pinia**,样式以 **Tailwind CSS 4****SCSS** 为主,接口请求使用 **Axios**
> **与仓库根文档的关系**项目总览、一键前后端启动、演示账号、Docker 部署等请以 [根目录 README.md](../../README.md) 为准;**本文档**侧重 `frontend/web/` 目录结构、环境变量与前端开发约定。
## 快速开始
### 环境准备
| 工具 | 版本要求 |
| ------- | ------------------------------------------------------ |
| Node.js | ≥ 20.19(见 `package.json``engines` |
| pnpm | ≥ 8.8,推荐 **pnpm 9**(与 `packageManager` 字段一致) |
未安装 pnpm 时可执行:`corepack enable && corepack prepare pnpm@9.15.3 --activate`(版本可按项目 `packageManager` 调整)。
### 安装依赖并启动
```bash
cd frontend/web
pnpm install
pnpm dev
```
默认开发端口由 **`.env`** 中的 **`VITE_PORT`** 决定(当前模板为 **5173**)。
### 与后端联调
1. 先启动 **FastAPI Admin 后端**,监听地址与 **`.env.development`** 里 **`VITE_API_BASE_URL`** 一致(模板默认为 **`http://127.0.0.1:8001`**)。
2. 前端开发时,浏览器请求发往当前页面同源路径,由 **Vite `server.proxy`****`VITE_APP_BASE_API`**(如 `/api/v1`)转发到上述后端。
3. 若页面提示「连接被拒绝」,检查后端是否启动、端口是否一致,或把 **`VITE_API_BASE_URL`** 改成你的实际后端地址。
## 架构概览
```
main.ts 启动
└─ initPlugins(app) ← 插件注册Pinia → Router → 指令 → i18n → Element Plus
└─ mount("#app")
└─ App.vue
├─ onBeforeMount: 主题初始化
└─ onMounted: bootstrap() → 存储检查/版本升级/站点配置
└─ 路由守卫 beforeEach
├─ 存储失效检测
├─ 登录态校验
├─ 动态路由注册(菜单 → addRoute
└─ 标签/标题同步
```
路由采用 **Hash 模式**静态路由Layout/登录/404首屏注册业务路由由守卫根据菜单权限延迟 `addRoute`。HTTP 拦截器支持 **Token 静默续期**401 时自动 refresh失败后跳转登录
## 技术栈
| 类别 | 选型 |
| ------ | ------------------------------------------------------ |
| 框架 | Vue 3Composition API / `<script setup>` |
| 构建 | Vite 7 |
| 语言 | TypeScript |
| UI | Element Plus |
| 路由 | Vue Router 4Hash静态路由 + 守卫内动态 `addRoute` |
| 状态 | Pinia + pinia-plugin-persistedstate |
| 样式 | Tailwind CSS 4、SCSS |
| HTTP | Axios |
| 国际化 | vue-i18n |
## 常用脚本
| 命令 | 说明 |
| --------------------------------------------- | ------------------------------------------------------------- |
| `pnpm dev` | 本地开发(读取 `.env` + `.env.development` |
| `pnpm dev:force` | 强制预打包依赖后启动(缓存异常时) |
| `pnpm build` | `vue-tsc` 类型检查 + 生产构建,产物在 **`dist/`** |
| `pnpm build:dev` / `build:test` / `build:pro` | 按 mode 构建(需对应 env 文件) |
| `pnpm preview` | 本地预览构建结果 |
| `pnpm type-check` | 仅 TypeScript 检查 |
| `pnpm lint` | ESLint + Prettier + Stylelint |
| `pnpm clean:dev` | 执行 `scripts/clean-dev.ts`(清理演示等,使用前阅读脚本说明) |
| `pnpm clean:cache` | 清理 Vite 等缓存 |
## 目录结构src
```
src/
├── api/ # 按业务模块划分的接口封装
├── assets/ # 图片、字体、全局样式等
├── components/ # 通用与业务组件
├── config/ # 应用配置fastEnter、headerBar 等)
├── enums/ # 枚举
├── hooks/ # 组合式函数
├── layouts/ # 布局壳art-* 顶栏、侧栏、Tab、设置抽屉等
├── locales/ # i18n如 langs/zh.json
├── plugins/ # Vue 插件注册入口plugins/index.ts → initPlugins
├── router/ # staticRoutes、动态路由、守卫、MenuProcessor
├── store/ # Pinia 模块
├── types/ # TypeScript 类型
├── utils/ # 工具(含 `@utils`
├── views/ # 页面module_* / dashboard 等)
├── App.vue
└── main.ts # 入口
```
## 路径别名
| 别名 | 指向 |
| ------------------ | ------------ |
| `@` | `src/` |
| `@views` | `src/views` |
| `@stores` | `src/store` |
| `@utils` | `src/utils` |
| `@styles` | `src/styles` |
| `@imgs` / `@icons` | 图片与 SVG |
**`vite.config.ts`**、`tsconfig.json` 中 `paths` 保持一致。
## 环境变量
只有以 **`VITE_`** 开头的变量会注入前端代码:
| 变量 | 作用 |
| ---------------------- | ------------------------------------------------ |
| `VITE_PORT` | 开发服务器端口 |
| `VITE_BASE_URL` | 部署基础路径(子目录部署时形如 `/admin/` |
| `VITE_APP_BASE_API` | 接口路径前缀,与 Vite 代理匹配 |
| `VITE_API_URL` | 浏览器侧发出的 API 根前缀(开发时常为 `/` |
| `VITE_API_BASE_URL` | **代理目标**:后端 HTTP 根地址 |
| `VITE_ACCESS_MODE` | `frontend` / `backend` / `mixed`,菜单与路由来源 |
| `VITE_APP_WS_ENDPOINT` | WebSocket如 AI 对话) |
| `VITE_APP_TITLE` | 页面标题(可被后端参数配置覆盖) |
完整列表以仓库内 **`.env`**、**`.env.development`** 为准;模板说明见 **`.env.example`**。修改任一 env 后需 **重启** `pnpm dev`
## 路由与菜单
| 文件 | 职责 |
| ----------------------------- | ------------------------------------------------- |
| `src/router/staticRoutes.ts` | 静态路由、`dashboardLayoutChildren`、壳层菜单合并 |
| `src/router/dynamicRoutes.ts` | 菜单驱动的动态路由 |
| `src/router/beforeEach.ts` | 权限与动态挂载 |
| `src/router/MenuProcessor.ts` | 后端菜单 → 前端路由记录 |
新增业务页:一般需要 **视图 +(可选)静态或动态路由 + 后端菜单/i18n**,三者路径与 **name** 保持一致。
## 常见问题
| 现象 | 建议 |
| ------------------------- | --------------------------------------------------------------------------------------- |
| `ECONNREFUSED` / 网络错误 | 后端未启动或 **`VITE_API_BASE_URL`** 端口错误 |
| 接口 401 / 频繁跳转登录 | Token 失效或未登录;清除站点本地存储后重新登录 |
| 修改 `.env` 不生效 | 必须 **重启** `pnpm dev` |
| 依赖异常、热更新怪异 | 尝试 **`pnpm clean:cache`** 后再 **`pnpm dev`**;仍不行可 **`pnpm dev:force`** |
| 类型报错 | 运行 **`pnpm type-check`**;自动生成类型见 `src/types/import/`(勿手改自动生成的 d.ts |
## 构建与部署
- 输出目录:**`dist/`**
- 部署在子路径时配置 **`VITE_BASE_URL`**,并配置网关/Nginx 将前端资源与 `/api` 等转发到后端
- 生产构建可能移除部分 `console`(见 **`vite.config.ts`** 中 `terserOptions`
## 代码规范与 Git
- **格式化与校验**`pnpm lint`
- **提交**husky、lint-staged、commitlint可使用 **`pnpm commit`**Commitizen / cz-git
/\*\*
- 浅蓝色系主题 — #1975FC
-
- 来源:花瓣网 B端淡蓝色配色参考
- 主色 #1975FC — 明快透亮、B端专业感
-
- 【启用方式】在本文件中取消注释对应主题模式的变量块,
- 并在 src/styles/index.scss 中 @use "./core/theme-blue";
- 同时在 src/config/setting.ts 中将 themeColor 改为 "#1975FC"。
-
- 【色阶 palette】
- #f8fcff 最浅底色(页面背景)
- #f0f5ff 浅蓝悬停态
- #e5f2ff 选中态 / tag 背景
- #c5ddff 浅蓝边框 / 分割线点缀
- #82b8ff 中浅蓝(图标辅助色)
- #1975FC ★ 主色
- #115ac8 深蓝hover 按下态)
-
- 【功能色】
- success: #16a34a
- warning: #d97706
- danger: #dc2626
- error: #fa896b
- info: #8b92a0
-
- ================================================================
\*/
// ================================================================
// 亮色主题 — 浅蓝色系
// ================================================================
// :root {
// /_ ---- 侧边栏 ---- _/
// --sidebar-bg-color: #ffffff;
// --sidebar-border-color: #edf0f2;
// --sidebar-text-color: #485260;
// --sidebar-text-hover-color: #1975fc;
// --sidebar-text-active-color: #1975fc;
// --sidebar-bg-hover-color: #f0f5ff;
// --sidebar-bg-active-color: #e5f2ff;
// --sidebar-logo-color: #121926;
// --sidebar-section-title-color: #8b92a0;
//
// /_ ---- 页面 ---- _/
// --main-bg-color: #f4f6f9;
// --header-bg-color: #ffffff;
// --header-border-color: #edf0f2;
//
// /_ ---- 卡片 ---- _/
// --card-bg-color: #ffffff;
// --card-border-color: #edf0f2;
//
// /_ ---- 表格 ---- _/
// --table-header-bg: #f8fafc;
// --table-header-color: #8b92a0;
// --table-row-hover-bg: #f8fafc;
// --table-border-color: #edf0f2;
//
// /_ ---- 文字 ---- _/
// --text-primary: #121926;
// --text-regular: #334155;
// --text-secondary: #8b92a0;
//
// /_ ---- 标签 ---- _/
// --tag-bg-color: #e5f2ff;
// --tag-text-color: #1975fc;
//
// /_ ---- 按钮 —— 由 Element Plus 通过 primary 色阶自动生成 ---- _/
// /_ ---- 进度条 ---- _/
// --nprogress-color: #1975fc;
//
// /_ ---- 边框模式 ---- _/
// --fa-card-border: #edf0f2;
// --default-box-color: #ffffff;
// --default-border: #edf0f2;
// --custom-radius: 0.75rem;
// }
// ================================================================
// 暗色主题 — 浅蓝色系(可选)
// ================================================================
// html.dark {
// --sidebar-bg-color: #0c1031;
// --sidebar-border-color: #1a1e3d;
// --sidebar-text-color: #a8adcc;
// --sidebar-text-hover-color: #5c9fff;
// --sidebar-text-active-color: #1975fc;
// --sidebar-bg-hover-color: rgba(25, 117, 252, 0.15);
// --sidebar-bg-active-color: rgba(25, 117, 252, 0.25);
// --sidebar-logo-color: #ffffff;
// --sidebar-section-title-color: #6b7094;
//
// --main-bg-color: #0f1420;
// --header-bg-color: #151a2d;
// --header-border-color: #1a1e3d;
//
// --card-bg-color: #151a2d;
// --card-border-color: #1a1e3d;
//
// --table-header-bg: #1a1e3d;
// --table-header-color: #6b7094;
// --table-row-hover-bg: #1a1e3d;
// --table-border-color: #1a1e3d;
//
// --text-primary: #e5e7eb;
// --text-regular: #a8adcc;
// --text-secondary: #6b7094;
//
// --tag-bg-color: rgba(25, 117, 252, 0.2);
// --tag-text-color: #5c9fff;
// }