Files
framework_project_web/.cursor/rules/admin-framework-usage.mdc
张成 b7208545e3 1
2026-04-29 13:46:24 +08:00

290 lines
12 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
description: Admin 前端 admin-framework 使用约定(详尽版,对照 admin_core 与 README
globs: admin/src/**/*.{vue,js},admin_core/src/**/*.{vue,js}
alwaysApply: false
---
# Admin Framework 使用约定(详尽)
适用于 **Vue 2 + Vue Router 3 + Vuex 3 + View Design** 的后台;约定与 **`admin_core` 源码**、根目录 **`README.md`**、分发 **`admin-framework.md`** 一致。默认构建产物为 **`dist/admin-framework.js`UMD**,浏览器全局为 **`window.AdminFramework`** / **`window.framework`**(单例)。
---
## 1. 依赖与引入
### 1.1 Peer 依赖(须由宿主安装)
`vue`、`vue-router`、`vuex`、`view-design`、`axios` 等须满足 **`package.json` 中 peerDependencies**;打包时将框架作 externals 或正常解析均可,须与 UMD externals 一致。
### 1.2 入口最小示例
```javascript
import AdminFramework from 'admin-framework' // 或 dist 路径
import componentMap from './router/component-map.js'
const app = AdminFramework.createApp({
title: '某某管理系统',
apiUrl: 'https://api.example.com/admin_api/',
componentMap,
HomePage: null, // 可选:自定义首页组件
onReady() {
// this 为根 Vue 实例
}
})
app.$mount('#app')
```
---
## 2. `createApp(config)` 配置项
| 字段 | 类型 | 说明 |
|------|------|------|
| `apiUrl` | string | **必填**`http` 的 `baseURL` |
| `uploadUrl` | string | 可选;不传则按 `apiUrl` 自动拼 `upload` 或 `/upload` |
| `title` | string | 默认 `document.title`、未登录或 `getSysTitle` 失败时的标题基线 |
| `componentMap` | object | 业务页组件路径 → 组件构造器;与菜单 `component` 字段对应 |
| `HomePage` | Component | 可选;覆盖默认欢迎首页 |
| `onReady` | function | 可选;根实例 `created` 末尾、`this` 指向根实例 |
**执行后**可用:`AdminFramework.store`、`AdminFramework.router`、`AdminFramework.config`、`AdminFramework.http`、`AdminFramework.uiTool`、`AdminFramework.tools` 等(与单例上字段一致)。
---
## 3. 框架单例 API 速查(`index.js` / README
| API | 用途 |
|-----|------|
| `createApp(config)` | 一键创建 store、router、根实例 |
| `addComponentMap(customMap)` | 运行时合并组件映射(内部 `setupComponentMap` |
| `initHttp(config, store)` | 非 `createApp` 场景手动绑定 http 与 store |
| `version` | 版本字符串 |
| `pages` | 内置登录、错误页、部分系统页导出 |
| `components` | **Main**、**ParentView**、**Tables**、**AsyncModal**、**editModal**、**FieldRenderer** 等 |
| `systemApi` | `src/api/system` 聚合(框架自带系统接口封装) |
| `storeModules` | 默认 `user`/`app` 模块引用,扩展 store 时可参考 |
| `createBaseRoutes` / `setupRouterGuards` / `createRouter` / `getRoutes` | 高级自定义路由时使用 |
| `registerComponents` / `registerGlobalComponents` | 高级注册组件 |
---
## 4. 全局注入(`createApp` 内)
- **`Vue.prototype.$config`**`createApp` 的 config。
- **`$http`**、`$tools`**、`$uiTool`**、`$framework`**:与单例一致。
组件内推荐 **`this.$http`** / **`this.$uiTool`**;单元测试或非组件模块可用 **`AdminFramework.http`**。
---
## 5. HTTP 模块(`src/utils/http.js`
### 5.1 成功约定
- 后端 JSON**`code === 0`** 为业务成功;否则拦截器 **`Message.error`** 并 **reject**。
- `get`/`post` 返回的 Promise **resolve 值为 `response.data`**(即整包 `{ code, message, data }`),业务通常再判断 **`res.code === 0`** 后使用 **`res.data`**。
### 5.2 方法一览
| 方法 | 说明 |
|------|------|
| `get(url, param, config)` | Query**`config.hideLoad`** 为 true 时不显示全局 loading |
| `post(url, param, config)` | JSON body**始终**显示 loading |
| `postFormData(url, data)` | `application/x-www-form-urlencoded` |
| `fileExport(url, param, filename, is_down)` | `blob` 下载;默认 **`is_down=true`** 时内部 **`uiTool.downloadFile`** |
| `baseUrl()` | 当前 `apiUrl` |
| `ImgSrc(src)` | `baseUrl() + src` |
### 5.3 401 行为
- 清空 **`user.token`**;依赖 **`window.framework.router`** 跳转 **`/login`**(布局代码应避免在非浏览器环境假设 router 已挂 window
---
## 6. uiTool 模块README §6 整段,`src/utils/uiTool.js`
通过 **`this.$uiTool`** 或 **`AdminFramework.uiTool`** 使用(**类静态方法**)。
| 方法 | 说明 |
|------|------|
| `setComponentMap(map)` | 合并组件映射表 |
| `getComponent(path)` | 按路径取组件,`path` 可带或不带 `.vue` |
| `downloadFile(res, fileName)` | Blob 下载 |
| `setRem()` | 根据屏宽设置根字体(自适应) |
| `getImgSrc(src)` | 图片地址(同 http 规则) |
| `getBtn(h, options)` | Render 函数里生成操作按钮组 |
| `getDropdown(h, items)` | 下拉更多菜单 |
| `delConfirm(callback)` | 删除确认框 |
| `showConfirm({ title, content }, callback)` | 通用确认框 |
| `transformTree(list, cb)` | 扁平列表转树 |
| `subTree` / `menuToRoute` / `getRoutes` | 菜单转路由(框架内部与权限菜单配合) |
**树表示例:**
```javascript
const tree = this.$uiTool.transformTree(flatListFromApi)
```
**与路由、菜单的衔接**`menuToRoute`、`getRoutes` 与动态权限、`componentMap` 的配合见 **`admin-framework-routing-store.mdc`**`downloadFile` 与 **`this.$http.fileExport`** 配合见本文 §5。
---
## 6.2 通用工具 `tools`README §6.2`src/utils/tools.js`
通过 **`this.$tools`** 使用(具体以源码为准)。
常用包括:
- **Cookie / Token**`getToken`、`setToken`、`TOKEN_KEY`
- **日期**`formatDate(val, fmt)`dayjs
- **数组**`forEach`、`hasOneOf`、`getUnion`、`getIntersection`
- **对象**`objEqual`、`removeEmptyObject`、`isNullorEmpty`
- **路由/菜单**`getBreadCrumbList`、`getHomeRoute`、`getMenuByRouter`、`filterMenu`
- **本地存储**`localSave`、`localRead`
- **其它**`generateUUID`、`getUrlParam`、`downStream`、`scrollTop` 等
**示例:**
```javascript
if (this.$tools.getToken()) { /* 已登录 */ }
```
---
## 6.3 表格组件 `Tables`README §12.2
基于 View Design **`Table`** 封装,支持分页条、导出、列配置、可编辑列等。
| Props | 说明 |
|-------|------|
| `value` | 表格数据数组 |
| `columns` | 列配置(同 iView Table `columns`,框架内会做对齐等默认处理) |
| `title` / `tip` | 表格标题与灰色提示 |
| `isDown` | 为 true 且 `value` 非空时显示「下载」链接触发导出 |
| `pageOption` | 分页:`{ page, pageSize, total }`,存在则显示 `Page` |
| `width` / `height` | 传给内部 Table |
| `maxHeightOffset` | 表格外层最大高度:`auto`(默认,按视口计算)或数字,用于 `calc(100vh - offset)` |
| 插槽 | 说明 |
|------|------|
| `header` | 标题行右侧区域 |
| 默认 | 透传给内部 Table如 `slot-scope` 列) |
| `footer` / `loading` | 透传 Table 同名插槽 |
| 事件 | 说明 |
|------|------|
| `changePage` | 分页变更(内部已更新 `pageOption.page` |
| `on-select` | 多选变化 |
| `downExecl` | 点击下载时,`{ value, columns }` |
```vue
<Tables
:value="tableData"
:columns="columns"
:page-option="{ page: 1, pageSize: 10, total: 100 }"
title="用户列表"
@changePage="loadData"
/>
```
---
## 7. 系统 API`systemApi`README §8 整段)
`AdminFramework.systemApi` 聚合导出 **`admin_core/src/api/system/index.js`** 中的服务(与源码 `export { default as ... }` 一致;以下为当前版本完整导出)。
| 导出名 | 模块文件 | 典型用途 |
|--------|----------|----------|
| `fileServe` | `fileServe.js` | 文件上传下载 |
| `plaAccountServer` | `pla_account_server.js` | 平台账号管理 |
| `rolePermissionServer` | `rolePermissionServer.js` | 角色权限 |
| `roleServer` | `roleServer.js` | 角色管理 |
| `sysAddressServer` | `sysAddressServer.js` | 地址字典 |
| `sysModuleServer` | `sysModuleServer.js` | 模块管理 |
| `sysLogServe` | `sys_log_serve.js` | 系统日志 |
| `systemTypeServer` | `systemType_server.js` | 系统类型配置 |
| `tableServer` | `tableServer.js` | 表结构相关 |
| `userServer` | `userServer.js` | 登录、用户 CRUD、权限菜单 |
| `formFieldServer` | `formFieldServer.js` | 表单字段 |
| `formServer` | `formServer.js` | 表单模型 |
| `menuServer` | `menuServer.js` | 菜单管理 |
| `modelFieldServer` | `modelFieldServer.js` | 数据模型字段 |
| `modelServer` | `modelServer.js` | 数据模型 |
| `paramSetupServer` | `paramSetupServer.js` | 系统参数标题、Logo |
| `sysTenantServer` | `sysTenantServer.js` | 租户管理 |
**调用示例:**
```javascript
const { userServer } = AdminFramework.systemApi
async function login() {
const res = await userServer.login({ username: 'admin', password: '***' })
if (res.code === 0) {
// 写入 token、拉菜单等由登录页与 store 配合完成
}
}
```
实际请求仍走全局配置的 **`http`**`apiUrl`、`admin-token` 头)。
> **说明**`src/api/system` 中若存在**未**在 **`index.js`** 聚合导出的文件(例如实验性模块),**不会**出现在 **`AdminFramework.systemApi`**;新增系统接口时须同时 **`export`** 才能在框架聚合对象上访问。
---
## 8. Vuex 内置模块
### 8.1 `user`namespaced
- **state**`token`、`userName`、`authorityMenus`、`menuList`、`currentTenant`、`avatorImgPath` 等。
- **常用 action****`handleLogin`**、**`handleLogOut`**、**`setAuthorityMenus`**。
- **租户****`currentTenant`** 与 **`localStorage.currentTenant`** 由 **`setCurrentTenant`** 同步。
### 8.2 `app`namespaced
- **state****`sysFormModel`**标题、Logo、**`breadCrumbList`**、**`homeRoute`**。
- **action****`getSysTitle`** — 必须使用 **`app/getSysTitle`** 形式 dispatch。
### 8.3 扩展 Store
```javascript
import { createStore } from 'admin-framework/src/store' // 按实际包路径调整
import createPersistedState from 'vuex-persistedstate'
// 第三个参数传工厂函数则启用持久化
const store = createStore(Vuex, { myModule }, createPersistedState)
```
默认 **`createApp`** 内为 **`createStore(Vuex, {}, null)`**,即**无** persistedstate 插件。
---
## 9. 路由
- **Hash 模式**`router/index.js`)。
- **动态菜单**:依赖 **`localStorage.authorityMenus`** + **`setAuthorityMenus`** 与 **`router.addRoute`**;详见 routing-store 文档。
- **守卫**:未登录跳转登录、已登录访问登录重定向 **`home`**、动态路由未命中延迟重试等,见 routing-store 文档。
---
## 10. 与后端协作约定
- **管理端 API** 路径通常带 **`/admin_api/`** 前缀(以项目 `apiUrl` 为准)。
- **请求体/查询**:与 Node 端 **`snake_case`** 字段对齐;前端展示层若用驼峰,应在边界单次映射,避免全页双写。
- **分页**:若后端使用框架 **`ctx.getPageSize`**,则与 **`pageOption`** JSON 约定一致(见 node-core 规范)。
---
## 11. 调试与排错
- **`window.framework`**单例、router、store、config。
- **`window.rootVue`**`createApp` 返回的根实例。
- 动态页空白:控制台搜 **「组件未找到」**;检查菜单 **`component`** 与 **`componentMap`**。
- 刷新后丢菜单:检查 **`token`** 与 **`localStorage.authorityMenus`** 是否仍存在、是否执行了 **`setAuthorityMenus`**。
---
## 12. 版本与构建
- 框架版本见 **`AdminFramework.version`** 与 **`README`**;发版时注意 **`admin-framework.js`** 与 **`admin-framework.md`** 同步分发。