添加AGENTS.md,重写README.md
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
# AGENTS.md — 唱作网 (ichangzuo)
|
||||
|
||||
> This file tells AI agents what they would likely get wrong without help.
|
||||
> Every line answers: "Would an agent miss this on first contact?" If the answer is no, it doesn't belong here.
|
||||
|
||||
## Project Identity
|
||||
|
||||
- **Name**: `ichangzuo` (唱作网) — a fork of vue3-element-admin, heavily customized
|
||||
- **Type**: Vue 3 admin panel / SPA (single-page app, no SSR/SSG)
|
||||
- **Package manager**: **pnpm only** — `preinstall` script enforces this (`npx only-allow pnpm`); npm/yarn will fail
|
||||
|
||||
## Tech Stack (versions from package.json, not README badges)
|
||||
|
||||
| Layer | Package | Version |
|
||||
|---|---|---|
|
||||
| Framework | vue | ^3.5.13 |
|
||||
| Build | vite | ^6.0.2 |
|
||||
| Language | typescript | ^5.7.2 |
|
||||
| UI | element-plus | ^2.9.0 |
|
||||
| State | pinia | ^2.2.8 |
|
||||
| Routing | vue-router | ^4.5.0 |
|
||||
| i18n | vue-i18n | 10.0.5 |
|
||||
| CSS | UnoCSS + SCSS | ^0.65.0 / sass ^1.82.0 |
|
||||
| HTTP | axios | ^1.7.8 |
|
||||
| Node | >=18 (20.6.0 broken) | — |
|
||||
|
||||
## Commands
|
||||
|
||||
| Purpose | Command | Notes |
|
||||
|---|---|---|
|
||||
| Dev server | `pnpm dev` | Reads `VITE_APP_PORT` from `.env.development` (default 3000) |
|
||||
| Type check | `pnpm type-check` | `vue-tsc --noEmit` — **use this before committing** |
|
||||
| Build (prod) | `pnpm build` | Runs `vue-tsc --noEmit & vite build` in parallel (Windows `&` = background) |
|
||||
| Build only | `pnpm build-only` | `vite build` without type check |
|
||||
| Lint JS/TS/Vue | `pnpm lint:eslint` | `eslint --fix` |
|
||||
| Format | `pnpm lint:prettier` | `prettier --write` |
|
||||
| Lint CSS/Vue | `pnpm lint:stylelint` | `stylelint --fix` |
|
||||
| Commit | `pnpm commit` | Interactive cz-git; do NOT `git commit` directly |
|
||||
|
||||
**No test runner is configured.** There is no `test` script, no test framework, and no test files in this repo.
|
||||
|
||||
## Path Alias
|
||||
|
||||
- **`@` → `src/`** — configured in both `vite.config.ts` (`resolve.alias`) and `tsconfig.json` (`paths`).
|
||||
- Import as `@/api/auth`, `@/store/modules/user`, etc.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Defined in `src/types/env.d.ts` and `.env.*` files:
|
||||
|
||||
| Variable | Dev Default | Prod | Purpose |
|
||||
|---|---|---|---|
|
||||
| `VITE_APP_PORT` | `3000` | — | Dev server port |
|
||||
| `VITE_APP_BASE_API` | `/dev-api` | `/prod-api` | Proxy prefix — Vite rewrites requests under this prefix to `VITE_APP_API_URL` |
|
||||
| `VITE_APP_API_URL` | `http://localhost:8989` | — | Backend API target |
|
||||
| `VITE_MOCK_DEV_SERVER` | `false` | — | Enable mock server (currently disabled in code) |
|
||||
|
||||
**Agent trap**: The proxy prefix is NOT a real URL path on the backend. The Vite dev server strips it before forwarding. So a request to `/dev-api/api/v1/auth/login` is proxied to `http://localhost:8989/api/v1/auth/login`.
|
||||
|
||||
## Architecture & Wiring
|
||||
|
||||
### App Bootstrap Order (src/plugins/index.ts)
|
||||
|
||||
```
|
||||
main.ts → createApp(App) → app.use(setupPlugins) → mount("#app")
|
||||
setupPlugins.install(app):
|
||||
1. setupDirective(app) — custom directives (e.g., v-permission)
|
||||
2. setupRouter(app) — vue-router
|
||||
3. setupStore(app) — Pinia
|
||||
4. setupI18n(app) — vue-i18n
|
||||
5. setupElIcons(app) — Element Plus icons
|
||||
6. setupPermission() — route guards (NProgress + auth check)
|
||||
```
|
||||
|
||||
### Route System
|
||||
|
||||
- **Static routes** defined in `src/router/index.ts` (`constantRoutes`) — includes `/software`, `/helper`, `/dashboard`, `/autoLogin`, `/resetPassword`, error pages (401, 404)
|
||||
- **Dynamic routes** injected at runtime by `permissionStore.generateRoutes()` after login — fetched from backend API
|
||||
- **Default redirect**: `/` → `/software`
|
||||
- **History mode**: `createWebHistory()` (HTML5 history, NOT hash mode)
|
||||
|
||||
### Permission / Auth Flow
|
||||
|
||||
1. Route guard (`src/plugins/permission.ts`) runs `beforeEach`
|
||||
2. Checks `localStorage.getItem("accessToken")` for token
|
||||
3. **White-listed paths** (no auth required): `/software`, `/helper`, `/autoLogin`, `/resetPassword`
|
||||
4. If token exists but no roles loaded → calls `userStore.getUserInfo()` → `permissionStore.generateRoutes()` → `router.addRoute()`
|
||||
5. Token invalid → `A0230` code from backend → `resetToken()` + redirect to `/software`
|
||||
6. **Button-level auth** via `hasAuth()` — checks `perms` array; `ROOT` role bypasses all button checks
|
||||
7. **Directives**: `v-permission` in `src/directive/` for template-level auth
|
||||
|
||||
### API Layer Pattern
|
||||
|
||||
- All API modules live in `src/api/` — one file per domain (auth, user, role, menu, dict, etc.)
|
||||
- Each exports a **static class** with methods that call `request()` from `src/utils/request.ts`
|
||||
- The `request.ts` axios instance:
|
||||
- `baseURL` = `import.meta.env.VITE_APP_BASE_API` (the proxy prefix)
|
||||
- Request interceptor: attaches `Authorization` header from `localStorage.accessToken`
|
||||
- Response interceptor: unwraps `{ code, data, msg }` — returns `data` on success (`00000`), rejects otherwise
|
||||
- Token invalid (`A0230`): auto-redirect to login
|
||||
- **Request/response types exported alongside the class** in the same file (e.g., `AuthAPI`, `LoginData`, `LoginResult` in `src/api/auth.ts`)
|
||||
|
||||
### State Management (Pinia)
|
||||
|
||||
- Store modules in `src/store/modules/`: `app`, `permission`, `settings`, `tagsView`, `user`
|
||||
- **Composition API style** — uses `defineStore("name", () => { ... })`
|
||||
- **Outside-component usage**: `useUserStoreHook()`, `useAppStoreHook()` etc. — these wrap `useXxxStore(piniaInstance)` for use in non-component code (interceptors, guards)
|
||||
- **Token stored in localStorage** under key `"accessToken"` (from `CacheEnum.TOKEN_KEY`), NOT in Pinia state directly
|
||||
|
||||
### Global Types (src/types/global.d.ts)
|
||||
|
||||
These are **ambient global** types (no import needed):
|
||||
- `ResponseData<T>` — `{ code, data, msg }`
|
||||
- `PageQuery` — `{ pageNum, pageSize }`
|
||||
- `PageResult<T>` — `{ list, total }`
|
||||
- `TagView` — tab/nav view metadata
|
||||
- `AppSettings` — app configuration interface
|
||||
- `OptionType` — select/dropdown datasource (`{ value, label, children? }`)
|
||||
|
||||
### Components
|
||||
|
||||
- Auto-registered: `unplugin-vue-components` scans `src/components/` and `src/**/components/`
|
||||
- **DTS generation is OFF** (`dts: false` in vite.config.ts) — types for auto-imported components are in `src/types/components.d.ts` (checked in, not auto-generated)
|
||||
- **Element Plus components**: auto-imported via `ElementPlusResolver` — no manual imports needed
|
||||
- **Icons**: use `<i-ep-xxx />` (e.g., `<i-ep-edit />`) via unplugin-icons with `@iconify-json/ep`
|
||||
- **SVG icons**: place SVGs in `src/assets/icons/`, use `<SvgIcon icon-class="name" />`
|
||||
|
||||
## Auto-Import: Critical Trap
|
||||
|
||||
`unplugin-auto-import` is configured in `vite.config.ts`:
|
||||
|
||||
```js
|
||||
AutoImport({
|
||||
imports: ["vue", "@vueuse/core", "pinia", "vue-router", "vue-i18n"],
|
||||
resolvers: [ElementPlusResolver(), IconsResolver({})],
|
||||
eslintrc: { enabled: false }, // NOT generating eslint rules
|
||||
dts: false, // NOT generating .d.ts
|
||||
})
|
||||
```
|
||||
|
||||
**This means**:
|
||||
- `ref`, `reactive`, `computed`, `watch`, `onMounted`, `defineStore`, `useRouter`, `useRoute`, `createI18n`, etc. are **auto-imported** — do NOT add explicit `import { ref } from "vue"` in new files
|
||||
- The existing `src/types/auto-imports.d.ts` and `.eslintrc-auto-import.json` are **checked-in snapshots** — they are NOT auto-updated
|
||||
- **When adding new auto-imported APIs** (e.g., from @vueuse/core): enable `dts` and `eslintrc.enabled` temporarily, run dev server once, then disable both again and commit the updated files
|
||||
- **ElMessage, ElNotification, ElMessageBox** etc. are auto-imported — no need to import them manually
|
||||
|
||||
## UnoCSS Shortcuts
|
||||
|
||||
Defined in `uno.config.ts` — use these instead of writing full utility classes:
|
||||
|
||||
| Shortcut | Expands To |
|
||||
|---|---|
|
||||
| `flex-center` | `flex justify-center items-center` |
|
||||
| `flex-x-center` | `flex justify-center` |
|
||||
| `flex-y-center` | `flex items-center` |
|
||||
| `wh-full` | `w-full h-full` |
|
||||
| `flex-x-between` | `flex items-center justify-between` |
|
||||
| `flex-x-end` | `flex items-center justify-end` |
|
||||
| `absolute-lt` | `absolute left-0 top-0` |
|
||||
| `absolute-rt` | `absolute right-0 top-0` |
|
||||
| `fixed-lt` | `fixed left-0 top-0` |
|
||||
|
||||
**Theme colors**: `primary` → `var(--el-color-primary)`, `primary_dark` → `var(--el-color-primary-light-5)` — these reference Element Plus CSS variables, not hardcoded values.
|
||||
|
||||
## SCSS
|
||||
|
||||
- Global SCSS variables injected via `vite.config.ts` `css.preprocessorOptions.scss.additionalData`:
|
||||
```scss
|
||||
@use "@/styles/variables.scss" as *;
|
||||
```
|
||||
This means every `.vue` and `.scss` file can use variables from `src/styles/variables.scss` without explicit `@use`.
|
||||
|
||||
## Build Details
|
||||
|
||||
- **Minifier**: `terser` (not esbuild) — configured with `drop_console: true` and `drop_debugger: true` for production
|
||||
- **Manual chunks**: `vue` (vue+router+pinia), `vue-i18n`, `element-plus` — split into separate bundles
|
||||
- **Asset naming**: `js/[name].[hash].js`, `img/[name].[hash].[ext]`, `fonts/[name].[hash].[ext]`, `media/[name].[hash].[ext]`
|
||||
- **`__APP_INFO__`**: build-time global constant (name, version, engines, dependencies, buildTimestamp) — do NOT try to modify at runtime
|
||||
|
||||
## Git Commit Convention
|
||||
|
||||
Enforced by `husky` + `commitlint` + `lint-staged`:
|
||||
|
||||
- **Always use `pnpm commit`** — launches cz-git interactive prompt
|
||||
- **Allowed types**: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `revert`, `chore`, `wip`
|
||||
- **Subject case**: not enforced (rule level 0)
|
||||
- **Pre-commit**: `lint-staged` runs ESLint + Prettier + Stylelint on staged files automatically
|
||||
|
||||
## ESLint Specifics
|
||||
|
||||
- **Config**: `.eslintrc.cjs` (legacy format, NOT flat config)
|
||||
- **Parser**: `vue-eslint-parser` → `@typescript-eslint/parser` for `<script>` blocks
|
||||
- **Relaxed rules** (common gotcha for agents that try to "fix" these):
|
||||
- `@typescript-eslint/no-explicit-any`: **OFF** — `any` is allowed
|
||||
- `@typescript-eslint/no-unused-vars`: **OFF** — unused vars allowed
|
||||
- `vue/multi-word-component-names`: **OFF** — single-word component names OK
|
||||
- `vue/html-self-closing`: enforced (void: always, normal: never, component: always)
|
||||
- **Global**: `OptionType` is declared as readonly global
|
||||
|
||||
## Directory Map
|
||||
|
||||
```
|
||||
src/
|
||||
├── api/ # API modules (one class per file + request/response types)
|
||||
├── assets/icons/ # SVG icons (loaded by vite-plugin-svg-icons)
|
||||
├── components/ # Shared components (CURD, SvgIcon, Pagination, Upload, WangEditor, etc.)
|
||||
├── directive/ # Custom directives (v-permission)
|
||||
├── enums/ # Const enums (ResultEnum, CacheEnum, LayoutEnum, ThemeEnum, etc.)
|
||||
├── lang/ # i18n (vue-i18n, zh-CN + en)
|
||||
├── layout/ # App shell layout (sidebar, header, tags-view)
|
||||
├── plugins/ # App plugin registration (icons, permission guard)
|
||||
├── router/ # Vue Router (static + dynamic routes)
|
||||
├── store/modules/ # Pinia stores (app, permission, settings, tagsView, user)
|
||||
├── styles/ # Global SCSS (variables, reset, login styles)
|
||||
├── types/ # Global .d.ts (env, auto-imports, components, router types)
|
||||
├── utils/ # Utilities (request.ts = axios wrapper, i18n, format, nprogress)
|
||||
└── views/ # Page components
|
||||
├── software/ # Main product page (default landing page)
|
||||
├── helper/ # Help/assistant page
|
||||
├── dashboard/ # Account info
|
||||
├── system/ # Admin: users, roles, menus, dicts, etc.
|
||||
├── account/ # User account management
|
||||
└── ...
|
||||
```
|
||||
|
||||
## Things Agents Get Wrong
|
||||
|
||||
1. **Adding explicit imports for auto-imported APIs** — `ref`, `reactive`, `computed`, `watch`, `defineStore`, `useRouter`, `useRoute`, `ElMessage`, `ElNotification`, etc. are injected at compile time. Do not write `import { ref } from "vue"`.
|
||||
|
||||
2. **Importing Element Plus components manually** — `unplugin-vue-components` handles this. `<el-button>` just works; no `import { ElButton } from 'element-plus'`.
|
||||
|
||||
3. **Using `import.meta.env.VITE_APP_API_URL` as the axios baseURL** — the baseURL is `VITE_APP_BASE_API` (the proxy prefix `/dev-api`), NOT the actual backend URL. The proxy rewrite happens in the Vite dev server.
|
||||
|
||||
4. **Writing unit tests** — there is no test framework installed. Do not create `*.test.ts` or `*.spec.ts` files or install testing dependencies unless explicitly asked.
|
||||
|
||||
5. **Hardcoding Element Plus color values** — use `var(--el-color-primary)` or UnoCSS `primary` shortcut, not hex values like `#409EFF`.
|
||||
|
||||
6. **Modifying `src/types/auto-imports.d.ts` or `components.d.ts` by hand** — these are generated files. If the auto-import plugin is re-enabled, they will be overwritten.
|
||||
|
||||
7. **Using `git commit` instead of `pnpm commit`** — commitlint will reject non-conventional messages. Always use `pnpm commit`.
|
||||
|
||||
8. **Forgetting the `@` alias** — use `@/` for all internal imports, never relative `../../` paths for cross-module references.
|
||||
|
||||
9. **Changing the `tsconfig.json` module resolution** — it uses `node16` module resolution with `type: "module"` in package.json. This is intentional; don't change to `bundler` or `node` without understanding the impact.
|
||||
|
||||
10. **Token in Pinia vs localStorage** — the source of truth for auth is `localStorage.getItem("accessToken")`. The Pinia `sessionToken` is just a reactive mirror; the route guard reads localStorage directly.
|
||||
@@ -1,191 +1,259 @@
|
||||
# 唱作网 (ichangzuo)
|
||||
|
||||
<div align="center">
|
||||
<img alt="vue3-element-admin" width="80" height="80" src="./src/assets/logo.png">
|
||||
<h1>vue3-element-admin</h1>
|
||||
基于 Vue3 + Vite6 + TypeScript5 + Element-Plus + Pinia 等主流技术栈构建的中后台管理前端应用。
|
||||
|
||||
<img src="https://img.shields.io/badge/Vue-3.4.35-brightgreen.svg"/>
|
||||
<img src="https://img.shields.io/badge/Vite-5.3.5-green.svg"/>
|
||||
<img src="https://img.shields.io/badge/Element Plus-2.7.8-blue.svg"/>
|
||||
<img src="https://img.shields.io/badge/license-MIT-green.svg"/>
|
||||
<a href="https://gitee.com/youlaiorg" target="_blank">
|
||||
<img src="https://img.shields.io/badge/Author-有来开源组织-orange.svg"/>
|
||||
</a>
|
||||
</div>
|
||||
## 技术栈
|
||||
|
||||

|
||||
|
||||
|
||||
<div align="center">
|
||||
<a target="_blank" href="http://vue3.youlai.tech">🔍 在线预览</a> | <a target="_blank" href="https://juejin.cn/post/7228990409909108793">📖 阅读文档</a> | <a href="./README.en-US.md">🌐English
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
## 项目简介
|
||||
|
||||
[vue3-element-admin](https://gitee.com/youlaiorg/vue3-element-admin) 是基于 Vue3 + Vite5+ TypeScript5 + Element-Plus + Pinia 等主流技术栈构建的免费开源的中后台管理的前端模板(配套[Java 后端源码](https://gitee.com/youlaiorg/youlai-boot))。
|
||||
|
||||
|
||||
## 项目特色
|
||||
|
||||
- **简洁易用**:基于 [vue-element-admin](https://gitee.com/panjiachen/vue-element-admin) 升级的 Vue3 版本,无过渡封装 ,易上手。
|
||||
|
||||
- **数据交互**:同时支持本地 `Mock` 和线上接口,配套 [Java 后端源码](https://gitee.com/youlaiorg/youlai-boot)和[在线接口文档](https://www.apifox.cn/apidoc/shared-195e783f-4d85-4235-a038-eec696de4ea5)。
|
||||
|
||||
- **权限管理**:用户、角色、菜单、字典、部门等完善的权限系统功能。
|
||||
|
||||
- **基础设施**:动态路由、按钮权限、国际化、代码规范、Git 提交规范、常用组件封装。
|
||||
|
||||
- **持续更新**:项目持续开源更新,实时更新工具和依赖。
|
||||
|
||||
|
||||
|
||||
## 项目预览
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## 项目地址
|
||||
|
||||
| 项目 | Gitee | Github |
|
||||
| ---- | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||
| 前端 | [vue3-element-admin](https://gitee.com/youlaiorg/vue3-element-admin) | [vue3-element-admin](https://github.com/youlaitech/vue3-element-admin) | [vue3-element-admin](https://gitcode.net/youlai/vue3-element-admin) |
|
||||
| 精简版 | [vue3-element-admin-thin](https://gitee.com/cshaptx4869/vue3-element-admin-thin) | [vue3-element-admin-thin](https://github.com/youlaitech/vue3-element-admin-thin) |
|
||||
| 后端 | [youlai-boot](https://gitee.com/youlaiorg/youlai-boot) | [youlai-boot](https://github.com/haoxianrui/youlai-boot.git) |
|
||||
| 层级 | 技术 | 版本 |
|
||||
|---|---|---|
|
||||
| 框架 | Vue | ^3.5.13 |
|
||||
| 构建 | Vite | ^6.0.2 |
|
||||
| 语言 | TypeScript | ^5.7.2 |
|
||||
| UI | Element Plus | ^2.9.0 |
|
||||
| 状态管理 | Pinia | ^2.2.8 |
|
||||
| 路由 | Vue Router | ^4.5.0 |
|
||||
| 国际化 | Vue I18n | 10.0.5 |
|
||||
| CSS | UnoCSS + SCSS | ^0.65.0 / sass ^1.82.0 |
|
||||
| HTTP | Axios | ^1.7.8 |
|
||||
| 富文本 | WangEditor | ^5.1.23 |
|
||||
|
||||
## 环境准备
|
||||
|
||||
| 环境 | 名称版本 | 下载地址 |
|
||||
| -------------------- | :----------------------------------------------------------- | ------------------------------------------------------------ |
|
||||
| **开发工具** | VSCode | [下载](https://code.visualstudio.com/Download) |
|
||||
| **运行环境** | Node ≥18 (其中 20.6.0 版本不可用) | [下载](http://nodejs.cn/download) |
|
||||
| 环境 | 要求 |
|
||||
|---|---|
|
||||
| 运行环境 | Node.js ≥18(注意:20.6.0 版本不可用) |
|
||||
| 包管理器 | pnpm(项目强制,npm/yarn 无法安装) |
|
||||
| 开发工具 | VSCode(推荐) |
|
||||
|
||||
## 开发指南
|
||||
|
||||
## 项目启动
|
||||
### 安装与启动
|
||||
|
||||
```bash
|
||||
# 克隆代码
|
||||
git clone https://gitee.com/youlaiorg/vue3-element-admin.git
|
||||
|
||||
# 切换目录
|
||||
cd vue3-element-admin
|
||||
|
||||
# 安装 pnpm
|
||||
npm install pnpm -g
|
||||
|
||||
# 设置镜像源(可忽略)
|
||||
pnpm config set registry https://registry.npmmirror.com
|
||||
|
||||
# 安装依赖
|
||||
pnpm install
|
||||
|
||||
# 启动运行
|
||||
pnpm run dev
|
||||
# 启动开发服务器(默认端口 3000)
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
### 常用命令
|
||||
|
||||
| 命令 | 说明 |
|
||||
|---|---|
|
||||
| `pnpm dev` | 启动开发服务器 |
|
||||
| `pnpm build` | 类型检查 + 生产构建 |
|
||||
| `pnpm build-only` | 仅生产构建(不做类型检查) |
|
||||
| `pnpm type-check` | TypeScript 类型检查 |
|
||||
| `pnpm lint:eslint` | ESLint 检查并自动修复 |
|
||||
| `pnpm lint:prettier` | Prettier 格式化 |
|
||||
| `pnpm lint:stylelint` | Stylelint 检查并自动修复 |
|
||||
| `pnpm commit` | 交互式 Git 提交(必须使用,不要直接 `git commit`) |
|
||||
|
||||
## 项目部署
|
||||
### 环境变量
|
||||
|
||||
环境变量定义在 `.env.development` 和 `.env.production` 中:
|
||||
|
||||
| 变量 | 开发环境 | 生产环境 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `VITE_APP_PORT` | 3000 | — | 开发服务器端口 |
|
||||
| `VITE_APP_BASE_API` | `/dev-api` | `/prod-api` | API 代理前缀 |
|
||||
| `VITE_APP_API_URL` | `http://localhost:8989` | — | 后端接口地址 |
|
||||
| `VITE_MOCK_DEV_SERVER` | false | — | 是否启用 Mock 服务 |
|
||||
|
||||
> 注意:`VITE_APP_BASE_API` 是代理前缀,不是后端的真实路径。Vite 开发服务器会自动将 `/dev-api` 前缀剥离后再转发请求到 `VITE_APP_API_URL`。例如请求 `/dev-api/api/v1/auth/login`,实际转发到 `http://localhost:8989/api/v1/auth/login`。
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
src/
|
||||
├── api/ # API 模块(每个文件对应一个业务域,导出静态类和类型)
|
||||
├── assets/icons/ # SVG 图标(通过 vite-plugin-svg-icons 加载)
|
||||
├── components/ # 通用组件(自动注册,无需手动导入)
|
||||
├── directive/ # 自定义指令(v-permission 按钮权限)
|
||||
├── enums/ # 常量枚举(ResultEnum, CacheEnum, LayoutEnum, ThemeEnum 等)
|
||||
├── lang/ # 国际化资源(zh-CN + en)
|
||||
├── layout/ # 应用布局框架(侧边栏、顶栏、标签导航)
|
||||
├── plugins/ # 应用插件注册(图标、路由守卫)
|
||||
├── router/ # Vue Router 配置(静态路由 + 动态路由)
|
||||
├── store/modules/ # Pinia 状态模块(app, permission, settings, tagsView, user)
|
||||
├── styles/ # 全局样式(SCSS 变量、重置、登录样式)
|
||||
├── types/ # 全局类型声明(env, auto-imports, components, router)
|
||||
├── utils/ # 工具函数(request.ts = axios 封装, i18n, format, nprogress)
|
||||
└── views/ # 页面组件
|
||||
├── software/ # 软件产品页(默认首页)
|
||||
├── helper/ # 帮助/助手页
|
||||
├── dashboard/ # 账号信息
|
||||
├── account/ # 用户账户(笔记、消息、VIP、安全、修改密码)
|
||||
├── system/ # 系统管理(用户、角色、菜单、字典、配置、日志)
|
||||
├── website/ # 网站管理
|
||||
├── autoLogin/ # 自动登录
|
||||
├── resetPassword/ # 重置密码
|
||||
└── error-page/ # 错误页面(401、404)
|
||||
```
|
||||
|
||||
## 核心功能
|
||||
|
||||
### 权限系统
|
||||
|
||||
- **路由权限**:基于角色的动态路由,登录后从后端获取菜单并动态注入路由
|
||||
- **按钮权限**:通过 `v-permission` 指令和 `hasAuth()` 函数控制按钮级权限
|
||||
- **白名单路由**:`/software`、`/helper`、`/autoLogin`、`/resetPassword` 无需登录即可访问
|
||||
- **ROOT 角色**:超级管理员拥有所有按钮权限,自动放行
|
||||
|
||||
### 认证流程
|
||||
|
||||
1. 用户登录 → 后端返回 Token → 存储到 `localStorage`(key: `accessToken`)
|
||||
2. 路由守卫检测 Token → 获取用户信息(角色、权限) → 生成动态路由
|
||||
3. Token 过期(后端返回 `A0230`) → 自动清除 Token → 重定向到登录页
|
||||
|
||||
### API 层
|
||||
|
||||
API 模块位于 `src/api/`,每个文件导出一个静态类和对应的请求/响应类型:
|
||||
|
||||
- `auth.ts` — 登录、注册、验证码
|
||||
- `user.ts` — 用户信息、账户信息
|
||||
- `role.ts` — 角色管理
|
||||
- `menu.ts` — 菜单管理
|
||||
- `dict.ts` — 字典管理
|
||||
- `software.ts` — 软件产品
|
||||
- `helper.ts` — 帮助内容
|
||||
- `order.ts` — 订单管理
|
||||
- `integral.ts` — 积分系统
|
||||
- `message.ts` — 消息通知
|
||||
- `notice.ts` — 公告管理
|
||||
- `bank.ts` — 银行信息
|
||||
- `file.ts` — 文件上传
|
||||
- `config.ts` — 系统配置
|
||||
- `log.ts` — 日志管理
|
||||
- `statistics.ts` — 数据统计
|
||||
- `style.ts` — 样式管理
|
||||
- `codegen.ts` — 代码生成
|
||||
|
||||
### 状态管理
|
||||
|
||||
Pinia Store 采用 Composition API 风格(`defineStore("name", () => { ... })`):
|
||||
|
||||
| 模块 | 文件 | 职责 |
|
||||
|---|---|---|
|
||||
| app | `store/modules/app.ts` | 应用全局状态(侧边栏、设备类型等) |
|
||||
| permission | `store/modules/permission.ts` | 动态路由生成 |
|
||||
| settings | `store/modules/settings.ts` | 应用设置(主题、布局、语言等) |
|
||||
| tagsView | `store/modules/tagsView.ts` | 标签导航管理 |
|
||||
| user | `store/modules/user.ts` | 用户认证与信息 |
|
||||
|
||||
> 在组件外(如路由守卫、拦截器)使用 Store 时,用 `useUserStoreHook()`、`useAppStoreHook()` 等包装函数。
|
||||
|
||||
## 开发约定
|
||||
|
||||
### 路径别名
|
||||
|
||||
`@` 映射到 `src/`,跨模块引用统一使用 `@/` 前缀:
|
||||
|
||||
```typescript
|
||||
// 正确
|
||||
import { useUserStore } from "@/store/modules/user";
|
||||
import AuthAPI from "@/api/auth";
|
||||
|
||||
// 错误
|
||||
import { useUserStore } from "../../store/modules/user";
|
||||
```
|
||||
|
||||
### 自动导入
|
||||
|
||||
项目配置了 `unplugin-auto-import` 和 `unplugin-vue-components`,以下无需手动导入:
|
||||
|
||||
- **Vue API**:`ref`、`reactive`、`computed`、`watch`、`onMounted` 等
|
||||
- **Pinia**:`defineStore`
|
||||
- **Vue Router**:`useRouter`、`useRoute`
|
||||
- **Vue I18n**:`createI18n`
|
||||
- **@vueuse/core**:所有导出
|
||||
- **Element Plus**:`ElMessage`、`ElNotification`、`ElMessageBox` 及所有组件
|
||||
|
||||
```typescript
|
||||
// 错误 — 不要添加这些导入
|
||||
import { ref } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
|
||||
// 正确 — 直接使用,编译时自动注入
|
||||
const count = ref(0);
|
||||
ElMessage.success("操作成功");
|
||||
```
|
||||
|
||||
### 图标使用
|
||||
|
||||
- **Element Plus 图标**:`<i-ep-xxx />`(如 `<i-ep-edit />`、`<i-ep-delete />`)
|
||||
- **自定义 SVG 图标**:将 SVG 文件放入 `src/assets/icons/`,使用 `<SvgIcon icon-class="name" />`
|
||||
|
||||
### UnoCSS 快捷类
|
||||
|
||||
| 快捷类 | 等效 |
|
||||
|---|---|
|
||||
| `flex-center` | `flex justify-center items-center` |
|
||||
| `flex-x-center` | `flex justify-center` |
|
||||
| `flex-y-center` | `flex items-center` |
|
||||
| `wh-full` | `w-full h-full` |
|
||||
| `flex-x-between` | `flex items-center justify-between` |
|
||||
| `flex-x-end` | `flex items-center justify-end` |
|
||||
|
||||
主题色使用 UnoCSS 的 `primary`(等价于 `var(--el-color-primary)`),不要硬编码色值。
|
||||
|
||||
### SCSS 全局变量
|
||||
|
||||
`src/styles/variables.scss` 中的变量通过 Vite 全局注入,所有 `.vue` 和 `.scss` 文件可直接使用,无需 `@use`。
|
||||
|
||||
### Git 提交规范
|
||||
|
||||
使用 `pnpm commit` 交互式提交,支持以下类型:
|
||||
|
||||
| 类型 | 说明 |
|
||||
|---|---|
|
||||
| `feat` | 新增功能 |
|
||||
| `fix` | 修复缺陷 |
|
||||
| `docs` | 文档变更 |
|
||||
| `style` | 代码格式(不影响功能) |
|
||||
| `refactor` | 代码重构 |
|
||||
| `perf` | 性能优化 |
|
||||
| `test` | 测试相关 |
|
||||
| `build` | 构建流程、外部依赖变更 |
|
||||
| `ci` | CI 配置变更 |
|
||||
| `revert` | 回滚提交 |
|
||||
| `chore` | 构建过程或辅助工具变更 |
|
||||
| `wip` | 开发阶段临时提交 |
|
||||
|
||||
Pre-commit 钩子会自动对暂存文件执行 ESLint + Prettier + Stylelint 检查。
|
||||
|
||||
## 部署
|
||||
|
||||
```bash
|
||||
# 项目打包
|
||||
pnpm run build
|
||||
# 生产构建
|
||||
pnpm build
|
||||
|
||||
# 上传文件至远程服务器
|
||||
将本地打包生成的 dist 目录下的所有文件拷贝至服务器的 /usr/share/nginx/html 目录。
|
||||
# 构建产物在 dist/ 目录,部署到服务器即可
|
||||
```
|
||||
|
||||
# nginx.cofig 配置
|
||||
Nginx 配置参考:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
# 反向代理配置
|
||||
# 后端 API 反向代理
|
||||
location /prod-api/ {
|
||||
# vapi.youlai.tech 替换后端API地址,注意保留后面的斜杠 /
|
||||
proxy_pass http://vapi.youlai.tech/;
|
||||
proxy_pass http://localhost:8989/;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 本地Mock
|
||||
|
||||
项目同时支持在线和本地 Mock 接口,默认使用线上接口,如需替换为 Mock 接口,修改文件 `.env.development` 的 `VITE_MOCK_DEV_SERVER` 为 `true` **即可**。
|
||||
|
||||
## 后端接口
|
||||
|
||||
> 如果您具备Java开发基础,按照以下步骤将在线接口转为本地后端接口,创建企业级前后端分离开发环境,助您走向全栈之路。
|
||||
|
||||
1. 获取基于 `Java` 和 `SpringBoot` 开发的后端 [youlai-boot](https://gitee.com/youlaiorg/youlai-boot.git) 源码。
|
||||
2. 根据后端工程的说明文档 [README.md](https://gitee.com/youlaiorg/youlai-boot#%E9%A1%B9%E7%9B%AE%E8%BF%90%E8%A1%8C) 完成本地启动。
|
||||
3. 修改 `.env.development` 文件中的 `VITE_APP_API_URL` 的值,将其从 http://vapi.youlai.tech 更改为 http://localhost:8989。
|
||||
|
||||
> 注意:`try_files` 配置确保 Vue Router 的 HTML5 History 模式正常工作,刷新页面不会 404。
|
||||
|
||||
## 注意事项
|
||||
|
||||
- **自动导入插件自动生成默认关闭**
|
||||
|
||||
模板项目的组件类型声明已自动生成。如果添加和使用新的组件,请按照图示方法开启自动生成。在自动生成完成后,记得将其设置为 `false`,避免重复执行引发冲突。
|
||||
|
||||

|
||||
|
||||
- **项目启动浏览器访问空白**
|
||||
|
||||
请升级浏览器尝试,低版本浏览器内核可能不支持某些新的 JavaScript 语法,比如可选链操作符 `?.`。
|
||||
|
||||
- **项目同步仓库更新升级**
|
||||
|
||||
项目同步仓库更新升级之后,建议 `pnpm install` 安装更新依赖之后启动 。
|
||||
|
||||
- **项目组件、函数和引用爆红**
|
||||
|
||||
重启 VSCode 尝试
|
||||
|
||||
- **其他问题**
|
||||
|
||||
如果有其他问题或者建议,建议 [ISSUE](https://gitee.com/youlaiorg/vue3-element-admin/issues/new)
|
||||
|
||||
|
||||
|
||||
## 项目文档
|
||||
|
||||
- [基于 Vue3 + Vite + TypeScript + Element-Plus 从0到1搭建后台管理系统](https://blog.csdn.net/u013737132/article/details/130191394)
|
||||
|
||||
- [ESLint+Prettier+Stylelint+EditorConfig 约束和统一前端代码规范](https://blog.csdn.net/u013737132/article/details/130190788)
|
||||
- [Husky + Lint-staged + Commitlint + Commitizen + cz-git 配置 Git 提交规范](https://blog.csdn.net/u013737132/article/details/130191363)
|
||||
|
||||
|
||||
## 提交规范
|
||||
|
||||
执行 `pnpm run commit` 唤起 git commit 交互,根据提示完成信息的输入和选择。
|
||||
|
||||

|
||||
|
||||
|
||||
## 项目统计
|
||||
|
||||

|
||||
|
||||
|
||||
Thanks to all the contributors!
|
||||
|
||||
[](https://github.com/youlaitech/vue3-element-admin/graphs/contributors)
|
||||
|
||||
|
||||
## 交流群🚀
|
||||
|
||||
> **关注「有来技术」公众号,获取交流群二维码。**
|
||||
>
|
||||
> 如果交流群的二维码过期,请加微信(haoxianrui)并备注「前端」、「后端」或「全栈」以获取最新二维码。
|
||||
>
|
||||
> 为确保交流群质量,防止营销广告人群混入,我们采取了此措施。望各位理解!
|
||||
|
||||
| 公众号 | 交流群 |
|
||||
|:----:|:----:|
|
||||
|  |  |
|
||||
|
||||
- **自动导入插件 DTS 生成已关闭**:组件类型声明已预生成。如需添加新组件,临时开启 `vite.config.ts` 中 AutoImport/Components 的 `dts` 选项,运行一次开发服务器后重新关闭。
|
||||
- **Node 20.6.0 不可用**:该版本存在已知问题,请使用其他 18+ 版本。
|
||||
- **IDE 爆红**:如遇组件、函数或引用标红,尝试重启 VSCode 或重新执行 `pnpm install`。
|
||||
|
||||
Reference in New Issue
Block a user