签入版本
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
# 4.4 前端分层架构
|
||||
|
||||
:::tip 概述
|
||||
前端采用 Vue 3 + TypeScript 组件化架构,分为 View(视图)→ API(接口)→ Store(状态)→ HTTP(请求)四层。辅以 Router(路由)、Directives(指令)、Hooks(组合式函数)、Utils(工具)等支撑模块。
|
||||
前端采用 Vue 3 + TypeScript 组件化架构,分为 View(视图)→ API(接口)→ Store(状态)→ HTTP(请求)四层。辅以 Router(路由)、Directives(指令)、Hooks(组合式函数)、Utils(工具)等支撑模块。前端为本仓库 `ui/` 目录内的 EleVue 管理后台。
|
||||
:::
|
||||
|
||||
## 架构全景
|
||||
|
||||
```text
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ 支撑模块 │
|
||||
│ 支撑模块 │
|
||||
│ │
|
||||
│ Router(路由) Directives(指令) Hooks(组合式函数) │
|
||||
│ src/router/ src/directives/ src/hooks/ │
|
||||
@@ -19,7 +19,7 @@
|
||||
│ 被主干层引用
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ 主干链路 │
|
||||
│ 主干链路 │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ View(视图层) │ │
|
||||
@@ -40,10 +40,9 @@
|
||||
│ │ Axios 封装:拦截器、Token 携带、错误处理 │ │
|
||||
│ │ 文件:src/utils/http/axios/ │ │
|
||||
│ └──────────────────────────┬──────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
│ │ 后端 API(RESTful JSON) │ │
|
||||
│ │ 后端 API(RESTful JSON,{code, ok, msg, data}) │ │
|
||||
│ └─────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||||
@@ -72,7 +71,7 @@ src/views/
|
||||
├── content/ 内容管理
|
||||
│ ├── article/ 文章管理
|
||||
│ └── category/ 分类管理
|
||||
├── login.vue 登录页
|
||||
├── login/ 登录页
|
||||
├── dashboard/ 仪表盘
|
||||
└── ...
|
||||
```
|
||||
@@ -107,7 +106,7 @@ src/views/
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<!-- 分页(后端固定返回 records / total / current / size / pages) -->
|
||||
<el-pagination v-model:current-page="pageNo" v-model:page-size="pageSize"
|
||||
:total="total" @change="fetchData" />
|
||||
</template>
|
||||
@@ -145,44 +144,48 @@ onMounted(() => fetchData());
|
||||
| 新增 | `{module}Add` | POST | `data` |
|
||||
| 修改 | `{module}Update` | PUT | `data` |
|
||||
| 删除 | `{module}Delete` | DELETE | URL 参数 |
|
||||
| 批量删除 | `{module}BatchDelete` | DELETE | `data` |
|
||||
| 批量删除 | `{module}BatchDelete` | **DELETE**(带 body) | `data`(`{ids:[]}`) |
|
||||
| 导入 | `{module}Import` | POST | FormData |
|
||||
| 导出 | `{module}Export` | GET | `params` |
|
||||
|
||||
:::warning 批量删除方法为 DELETE
|
||||
本项目 `batchDelete` 路由为 **DELETE**(请求体仍传 `ids` 数组——DELETE 方法携带 body),见 [3.7 路由注册](/zh/guide/route.html)。
|
||||
:::
|
||||
|
||||
**完整示例:**
|
||||
|
||||
```typescript
|
||||
// src/api/system/user.ts
|
||||
// src/api/tool/example.ts
|
||||
import { http } from '@/utils/http/axios';
|
||||
|
||||
// 分页查询
|
||||
export function getUserPage(params?) {
|
||||
return http.request({ url: '/user/page', method: 'GET', params });
|
||||
export function getExamplePage(params?) {
|
||||
return http.request({ url: '/example/page', method: 'GET', params });
|
||||
}
|
||||
|
||||
// 详情
|
||||
export function getUserDetail(id) {
|
||||
return http.request({ url: '/user/detail/' + id, method: 'GET' });
|
||||
export function getExampleDetail(id) {
|
||||
return http.request({ url: '/example/detail/' + id, method: 'GET' });
|
||||
}
|
||||
|
||||
// 新增
|
||||
export function userAdd(data: any) {
|
||||
return http.request({ url: '/user/add', method: 'POST', data });
|
||||
export function exampleAdd(data: any) {
|
||||
return http.request({ url: '/example/add', method: 'POST', data });
|
||||
}
|
||||
|
||||
// 修改
|
||||
export function userUpdate(data: any) {
|
||||
return http.request({ url: '/user/update', method: 'PUT', data });
|
||||
export function exampleUpdate(data: any) {
|
||||
return http.request({ url: '/example/update', method: 'PUT', data });
|
||||
}
|
||||
|
||||
// 删除
|
||||
export function userDelete(id) {
|
||||
return http.request({ url: '/user/delete/' + id, method: 'DELETE' });
|
||||
export function exampleDelete(id) {
|
||||
return http.request({ url: '/example/delete/' + id, method: 'DELETE' });
|
||||
}
|
||||
|
||||
// 批量删除
|
||||
export function userBatchDelete(data: any) {
|
||||
return http.request({ url: '/user/batchDelete', method: 'DELETE', data });
|
||||
// 批量删除(DELETE + 请求体 ids 数组)
|
||||
export function exampleBatchDelete(data: any) {
|
||||
return http.request({ url: '/example/batchDelete', method: 'DELETE', data });
|
||||
}
|
||||
```
|
||||
|
||||
@@ -239,15 +242,18 @@ src/utils/http/axios/
|
||||
```text
|
||||
登录:
|
||||
userStore.login(userInfo)
|
||||
→ POST /login → 获取 access_token
|
||||
→ POST /login(含 key/code 验证码参数)
|
||||
→ 获取 access_token
|
||||
→ Storage.set(ACCESS_TOKEN, token)
|
||||
→ this.setToken(token)
|
||||
|
||||
获取用户信息:
|
||||
userStore.GetInfo()
|
||||
→ GET /index/getUserInfo
|
||||
→ this.setPermissions(res.permissions)
|
||||
→ this.setUserInfo(res)
|
||||
→ GET /index/getUser
|
||||
→ setPermissions(res.permissions)
|
||||
→ setUserInfo(res)
|
||||
|
||||
获取菜单(动态路由):
|
||||
→ GET /index/getMenus
|
||||
|
||||
登出:
|
||||
userStore.logout()
|
||||
@@ -280,7 +286,7 @@ src/utils/http/axios/
|
||||
```text
|
||||
1. 用户登录 → 获取 Token → 存入 Store
|
||||
2. 路由守卫(router.beforeEach)检测到 Token
|
||||
3. 调用 GET /index/getMenus 获取菜单树
|
||||
3. 调用 GET /index/getMenus 获取菜单树(后端按用户权限过滤)
|
||||
4. generator-routers.ts 将菜单树转换为路由表
|
||||
5. router.addRoute() 动态注入路由
|
||||
6. 渲染侧边栏菜单
|
||||
@@ -324,6 +330,10 @@ src/utils/http/axios/
|
||||
用户权限列表包含 `*:*:*` 时,表示超级管理员,拥有所有权限,`v-perm`/`v-perms` 指令始终放行。
|
||||
:::
|
||||
|
||||
:::warning 前端权限不是安全防线
|
||||
`v-perm` 只是体验层(隐藏按钮);真正的安全校验在后端 `#[Permission]` 注解 + `auth.jwt` 中间件(见 [3.8 权限节点配置](/zh/guide/permission.html))。
|
||||
:::
|
||||
|
||||
## 支撑模块
|
||||
|
||||
### Hooks(组合式函数)
|
||||
@@ -366,8 +376,8 @@ API: getExamplePage(params)
|
||||
HTTP: 请求拦截器添加 Token
|
||||
│ 发送 GET /example/page?pageNo=1&pageSize=20
|
||||
▼
|
||||
后端: Controller → Logic → Model → Database
|
||||
│
|
||||
后端: Controller → Service → Model → Database
|
||||
│(响应 {code, ok, msg, data},snake→camel 已在后端完成)
|
||||
▼
|
||||
HTTP: 响应拦截器判断 code
|
||||
│ code === 0 → 返回 data
|
||||
@@ -387,8 +397,8 @@ Vue 响应式 → 表格自动刷新
|
||||
登录成功
|
||||
│
|
||||
▼
|
||||
userStore.setToken(token) → 响应式更新
|
||||
userStore.setUserInfo(info) → 响应式更新
|
||||
userStore.setToken(token) → 响应式更新
|
||||
userStore.setUserInfo(info) → 响应式更新
|
||||
userStore.setPermissions(perm) → 响应式更新
|
||||
│
|
||||
▼
|
||||
@@ -402,14 +412,14 @@ v-perm 指令读取 permissions 列表 → 控制元素显隐
|
||||
|
||||
| 后端 | 前端 | 说明 |
|
||||
|------|------|------|
|
||||
| `app/controller/UserController.php` | `src/api/system/user.ts` | API 函数映射 |
|
||||
| `app/logic/UserLogic.php` | `src/views/system/user/` | 业务页面 |
|
||||
| `app/model/User.php` | — | 前端不直接操作模型 |
|
||||
| `app/validate/UserValidate.php` | — | 前端校验由表单组件处理 |
|
||||
| `app/validate/*Validate.php` 的场景 | 表单 `rules` | 前端表单校验规则 |
|
||||
| `route/app.php` | `src/api/**/*.ts` | 路由 ↔ API 函数 |
|
||||
| 后端字典 `DictService` | `src/enums/` + 字典 Store | 枚举常量 |
|
||||
| 后端 `#[Permission]` 注解 | `v-perm` 指令 | 权限码对应 |
|
||||
| `Http/Controllers/Api/UserController.php` | `src/api/system/user.ts` | API 函数映射 |
|
||||
| `Services/UserService.php` | `src/views/system/user/` | 业务页面 |
|
||||
| `Http/Requests/UserRequest.php` 的 rules | 表单 `rules` | 前端表单校验规则(体验层) |
|
||||
| `Models/User.php` | — | 前端不直接操作模型 |
|
||||
| `routes/api.php` | `src/api/**/*.ts` | 路由 ↔ API 函数 |
|
||||
| 字典数据(`dict` 表) | `src/enums/` + 字典 Store | 枚举常量 |
|
||||
| `#[Permission]` 注解 | `v-perm` 指令 | 权限码对应 |
|
||||
| 分页 `records/total/current/size/pages` | el-pagination 绑定 | 固定分页结构 |
|
||||
|
||||
## 层间通信规范
|
||||
|
||||
|
||||
Reference in New Issue
Block a user