# 开发文档 ## 项目简介 本项目是基于 Vue3 + TypeScript + Vite + Element Plus 的前端管理系统,采用前后端分离架构,提供完整的权限管理、CRUD操作等功能。 ## 技术栈 - **框架**: Vue 3.4+ (Composition API) - **语言**: TypeScript 4.9+ - **构建工具**: Vite 5.4+ - **UI框架**: Element Plus 2.8+ - **状态管理**: Pinia 2.0+ - **路由**: Vue Router 4.4+ - **CRUD框架**: Fast-Crud 1.21+ - **HTTP客户端**: Axios 1.7+ - **样式**: Tailwind CSS 3.2+ / SCSS ## 环境要求 - **Node.js**: >= 16.0.0 (推荐使用最新 LTS 版本) - **npm**: >= 7.0.0 (或使用 yarn) - **操作系统**: Windows / macOS / Linux ## 快速开始 ### 1. 克隆项目 ```bash git clone cd zheda ``` ### 2. 安装依赖 使用 npm: ```bash npm install ``` 或使用 yarn: ```bash yarn install ``` 或使用国内镜像加速: ```bash npm install --registry=https://registry.npm.taobao.org ``` ### 3. 配置环境变量 在项目根目录创建环境变量文件(根据实际需要选择): **开发环境** (`.env.development`): ```env # 开发服务器端口 VITE_PORT=8080 # API 基础路径 VITE_API_URL=http://localhost:8000/api/ # 公共路径(开发环境通常为 ./) VITE_PUBLIC_PATH=./ # 构建输出目录 VITE_DIST_PATH=dist ``` **生产环境** (`.env.production`): ```env # API 基础路径(生产环境) VITE_API_URL=https://your-api-domain.com/api/ # 公共路径(根据部署路径配置,如:/ 或 /admin/) VITE_PUBLIC_PATH=/ # 构建输出目录 VITE_DIST_PATH=dist ``` **本地生产环境** (`.env.local_prod`): ```env # 本地生产环境配置 VITE_API_URL=http://localhost:8000/api/ VITE_PUBLIC_PATH=/ VITE_DIST_PATH=dist ``` ### 4. 启动开发服务器 ```bash npm run dev ``` 或 ```bash yarn dev ``` 开发服务器启动后,访问: `http://localhost:8080` (端口可在环境变量中配置) ## 项目结构 ``` zheda/ ├── public/ # 静态资源目录(不会被 Vite 处理,直接复制到 dist) │ ├── favicon.ico # 网站图标 │ ├── favicon1.ico # 备用图标 │ ├── favicon2.ico # 备用图标 │ └── version-build # 版本构建文件(自动生成) ├── src/ # 源代码目录 │ ├── api/ # API 接口定义 │ │ ├── login/ # 登录相关接口 │ │ │ └── index.ts # 登录 API │ │ ├── menu/ # 菜单相关接口 │ │ └── system/ # 系统相关接口 │ │ ├── loginBackground.ts │ │ └── ... │ ├── assets/ # 静态资源(图片、样式等) │ │ ├── style/ # 全局样式文件 │ │ ├── iconfont/ # 图标字体文件 │ │ └── *.png|jpg|svg # 图片资源 │ ├── components/ # 公共组件(可复用的 Vue 组件) │ ├── directive/ # 自定义指令(Vue 指令) │ ├── i18n/ # 国际化配置(多语言支持) │ ├── layout/ # 布局组件(页面布局结构) │ ├── plugin/ # 插件配置(第三方插件初始化) │ │ └── permission/ # 权限插件 │ ├── router/ # 路由配置 │ │ ├── index.ts # 路由入口(路由实例和守卫) │ │ ├── backEnd.ts # 后端控制路由逻辑 │ │ ├── frontEnd.ts # 前端控制路由逻辑 │ │ └── route.ts # 路由定义(静态路由) │ ├── stores/ # Pinia 状态管理 │ │ ├── index.ts # Store 入口 │ │ ├── userInfo.ts # 用户信息 Store │ │ ├── routesList.ts # 路由列表 Store │ │ ├── btnPermission.ts # 按钮权限 Store │ │ ├── columnPermission.ts # 列权限 Store │ │ ├── themeConfig.ts # 主题配置 Store │ │ └── ... # 其他 Store │ ├── theme/ # 主题样式(颜色、布局等) │ ├── types/ # TypeScript 类型定义 │ │ └── global.d.ts # 全局类型声明 │ ├── utils/ # 工具函数 │ │ ├── baseUrl.ts # 基础URL处理(API地址管理) │ │ ├── service.ts # HTTP请求封装(Axios封装) │ │ ├── storage.ts # 本地存储封装(LocalStorage/SessionStorage) │ │ ├── authFunction.ts # 权限验证函数 │ │ ├── message.ts # 消息提示封装 │ │ ├── dictionary.ts # 字典数据管理 │ │ ├── upgrade.ts # 版本升级检查 │ │ └── ... # 其他工具函数 │ ├── views/ # 页面组件(业务页面) │ │ └── system/ # 系统管理模块 │ │ └── company/ # 公司管理 │ │ ├── crud.tsx # CRUD 配置 │ │ ├── api.ts # API 接口 │ │ └── index.vue # 页面组件 │ ├── App.vue # 根组件(应用入口组件) │ ├── main.ts # 入口文件(应用初始化) │ └── settings.ts # Fast-Crud 配置(CRUD框架配置) ├── dist/ # 构建输出目录(生产环境,gitignore) ├── node_modules/ # 依赖包目录(gitignore) ├── index.html # HTML 模板 ├── package.json # 项目依赖配置 ├── package-lock.json # 依赖锁定文件 ├── yarn.lock # Yarn 依赖锁定文件(如果使用 Yarn) ├── tsconfig.json # TypeScript 配置 ├── vite.config.ts # Vite 构建配置 ├── tailwind.config.js # Tailwind CSS 配置 ├── postcss.config.js # PostCSS 配置 ├── .env.development # 开发环境变量(需要创建) ├── .env.production # 生产环境变量(需要创建) ├── .env.local_prod # 本地生产环境变量(需要创建) ├── .gitignore # Git 忽略文件配置 ├── README.md # 项目说明文档 ├── DEVELOPMENT.md # 开发文档(本文档) └── DEPLOYMENT.md # 部署文档 ``` ### 目录详细说明 #### `/src/api/` - API 接口层 - **作用**: 统一管理所有后端 API 接口 - **规范**: - 按业务模块划分目录 - 每个模块创建独立的 `api.ts` 文件 - 使用统一的 `request` 方法进行请求 - **示例**: 参考 `src/views/system/company/api.ts` #### `/src/stores/` - 状态管理 - **作用**: 使用 Pinia 进行全局状态管理 - **主要 Store**: - `userInfo.ts`: 用户信息(登录状态、用户数据) - `routesList.ts`: 路由列表(动态路由) - `btnPermission.ts`: 按钮权限列表 - `themeConfig.ts`: 主题配置(布局、颜色等) - **使用方式**: ```typescript import { useUserInfo } from '/@/stores/userInfo'; const { userInfos } = storeToRefs(useUserInfo()); ``` #### `/src/utils/` - 工具函数 - **核心工具**: - `service.ts`: HTTP 请求封装,包含请求/响应拦截器 - `storage.ts`: 本地存储封装(LocalStorage/SessionStorage) - `authFunction.ts`: 权限验证函数(auth、auths、authAll) - `baseUrl.ts`: API 基础地址管理 - `message.ts`: 消息提示封装 - `dictionary.ts`: 字典数据管理 #### `/src/router/` - 路由系统 - **路由模式**: Hash 模式(`createWebHashHistory`) - **路由控制**: 支持前端控制和后端控制两种模式 - 前端控制: 路由定义在前端,通过角色权限过滤 - 后端控制: 路由由后端返回,动态注册 - **路由守卫**: - 登录验证 - 权限验证 - 版本检查 - 路由缓存(keep-alive) #### `/src/views/` - 页面组件 - **组织方式**: 按业务模块划分 - **命名规范**: 使用 kebab-case(短横线命名) - **CRUD 页面**: 使用 Fast-Crud 框架,参考 `system/company/crud.tsx` ## 开发指南 ### 代码规范 项目使用 ESLint 进行代码检查,建议在提交代码前运行: ```bash npm run lint-fix ``` ### 添加新页面 1. 在 `src/views/` 目录下创建页面组件 2. 在 `src/router/` 中添加路由配置 3. 如需 CRUD 功能,参考 `src/views/system/company/crud.tsx` 的实现方式 ### API 接口调用 #### 1. 创建 API 文件 在 `src/api/` 或对应业务模块目录下创建 API 文件,例如 `src/views/system/company/api.ts`: ```typescript import { request } from '/@/utils/service'; import { UserPageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud'; // API 前缀(统一管理) export const apiPrefix = '/api/platform-admin/tenants/'; // 获取列表(分页查询) export function GetList(query: UserPageQuery) { return request({ url: apiPrefix, method: 'get', params: query, }); } // 获取详情 export function GetObj(id: InfoReq) { return request({ url: apiPrefix + id, method: 'get', }); } // 新增 export function AddObj(obj: AddReq) { return request({ url: apiPrefix, method: 'post', data: obj, }); } // 更新 export function UpdateObj(obj: EditReq) { return request({ url: apiPrefix + obj.id + '/', method: 'put', data: obj, }); } // 删除 export function DelObj(id: DelReq) { return request({ url: apiPrefix + id + '/', method: 'delete', data: { id }, }); } // 自定义接口示例 export function updateTenantStatus(id: string, status: number) { return request({ url: `${apiPrefix}${id}/activate/`, method: 'post', data: { status }, }); } ``` #### 2. 在组件中使用 API ```typescript import { GetList, AddObj, UpdateObj, DelObj } from './api'; // 在 setup 函数中使用 const loadData = async () => { try { const res = await GetList({ page: 1, limit: 10 }); console.log(res.data); } catch (error) { console.error('加载数据失败', error); } }; ``` #### 3. API 请求配置说明 **请求拦截器** (`src/utils/service.ts`): - 自动添加 `Authorization` 头(从 SessionStorage 获取 token) - 统一设置 `baseURL`(从环境变量获取) - 参数序列化(处理布尔值、空值等) **响应拦截器**: - 统一处理错误码(400、401、403、500 等) - 401 自动跳转登录页 - 统一错误提示 **请求配置选项**: ```typescript request({ url: '/api/xxx', method: 'get' | 'post' | 'put' | 'delete', params: {}, // GET 请求参数 data: {}, // POST/PUT 请求体 headers: {}, // 自定义请求头 timeout: 20000, // 超时时间(毫秒) responseType: 'blob', // 响应类型(用于文件下载) unpack: false, // 是否解包响应数据 }) ``` #### 4. 文件下载 项目提供了文件下载工具函数: ```typescript import { downloadFile, downloadFilePost } from '/@/utils/service'; // GET 方式下载 downloadFile({ url: '/api/export/', params: { id: 1 }, method: 'get', filename: '导出文件' }); // POST 方式下载 downloadFilePost({ url: '/api/export/', data: { ids: [1, 2, 3] }, method: 'post', filename: '导出文件' }); ``` ### 使用 Fast-Crud 项目集成了 Fast-Crud 框架,可以快速生成 CRUD 页面。参考 `src/views/system/company/crud.tsx` 的实现。 #### 1. 基本结构 ```typescript import * as api from './api'; import { UserPageQuery, AddReq, DelReq, EditReq, CreateCrudOptionsProps, CreateCrudOptionsRet } from '@fast-crud/fast-crud'; export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOptionsRet { // 分页查询 const pageRequest = async (query: UserPageQuery) => { return await api.GetList(query); }; // 编辑请求 const editRequest = async ({ form, row }: EditReq) => { form.id = row.id; return await api.UpdateObj(form); }; // 删除请求 const delRequest = async ({ row }: DelReq) => { return await api.DelObj(row.id); }; // 新增请求 const addRequest = async ({ form }: AddReq) => { return await api.AddObj(form); }; return { crudOptions: { // CRUD 配置 } }; }; ``` #### 2. 主要配置项 **请求配置**: ```typescript request: { pageRequest, // 分页查询 addRequest, // 新增 editRequest, // 编辑 delRequest, // 删除 } ``` **工具栏配置**: ```typescript toolbar: { buttons: { search: { show: true }, // 搜索按钮 refresh: { show: true }, // 刷新按钮 export: { show: true }, // 导出按钮 columns: { show: true }, // 列设置按钮 } } ``` **搜索配置**: ```typescript search: { col: { span: 3 }, // 每列占用的栅格数 show: true, // 显示搜索区域 autoSearch: true, // 自动搜索 buttons: { search: { size: 'small' }, // 查询按钮大小 reset: { size: 'small' }, // 重置按钮大小 } } ``` **操作栏配置**: ```typescript actionbar: { buttons: { add: { size: 'small', show: true, // 或使用权限: auth('company:Create') }, }, } ``` **行操作配置**: ```typescript rowHandle: { fixed: 'right', // 固定在右侧 width: 260, // 操作栏宽度 buttons: { view: { // 查看按钮 size: 'small', text: '查看', show: true, }, edit: { // 编辑按钮 size: 'small', show: true, }, remove: { // 删除按钮 show: false, }, // 自定义按钮 customAction: { size: 'small', text: '自定义操作', click: async ({ row }) => { // 自定义操作逻辑 }, }, }, } ``` **列配置**: ```typescript columns: { name: { title: '名称', type: 'input', // 字段类型 search: { show: true }, // 是否显示在搜索区域 form: { // 表单配置 rules: [{ required: true, message: '名称必填' }], component: { placeholder: '请输入名称' }, }, column: { minWidth: 120 }, // 列配置 }, status: { title: '状态', type: 'dict-select', // 字典选择器 search: { show: true }, dict: dict({ data: [ { value: 1, label: '启用' }, { value: 0, label: '禁用' }, ] }), }, } ``` #### 3. 字段类型 Fast-Crud 支持多种字段类型: - `input`: 文本输入框 - `textarea`: 多行文本 - `number`: 数字输入框 - `password`: 密码输入框 - `select`: 下拉选择 - `dict-select`: 字典选择器 - `date`: 日期选择器 - `datetime`: 日期时间选择器 - `switch`: 开关 - `radio`: 单选框 - `checkbox`: 复选框 - `upload`: 文件上传 - `editor`: 富文本编辑器 #### 4. 完整示例 参考 `src/views/system/company/crud.tsx` 查看完整的 CRUD 配置示例。 ### 状态管理 使用 Pinia 进行状态管理,store 文件位于 `src/stores/` 目录。 #### 1. Store 结构 ```typescript // src/stores/userInfo.ts 示例 import { defineStore } from 'pinia'; import { Session } from '/@/utils/storage'; export const useUserInfo = defineStore('userInfo', { state: (): UserInfosState => ({ userInfos: { username: '', avatar: '', roles: [], // ...其他用户信息 }, }), actions: { // 设置用户信息 setUserInfos(data: any) { this.userInfos = data; }, // 清除用户信息 clearUserInfos() { this.userInfos = { username: '', avatar: '', roles: [], }; }, }, persist: { key: 'userInfo', storage: Session, // 使用 SessionStorage }, }); ``` #### 2. 使用 Store ```typescript import { useUserInfo } from '/@/stores/userInfo'; import { storeToRefs } from 'pinia'; // 在 setup 中使用 const userInfoStore = useUserInfo(); const { userInfos } = storeToRefs(userInfoStore); // 调用 actions userInfoStore.setUserInfos(newData); // 直接访问 state console.log(userInfoStore.userInfos); ``` #### 3. 主要 Store 说明 **userInfo.ts** - 用户信息 - 存储当前登录用户的信息 - 包含用户名、头像、角色等 **routesList.ts** - 路由列表 - 存储动态路由列表 - 用于路由权限控制 **btnPermission.ts** - 按钮权限 - 存储当前用户的按钮权限列表 - 配合 `auth()` 函数使用 **themeConfig.ts** - 主题配置 - 存储主题相关配置(布局、颜色等) - 支持持久化存储 #### 4. Store 持久化 项目使用 `pinia-plugin-persist` 实现 Store 持久化: ```typescript persist: { key: 'storeKey', // 存储的 key storage: Session, // 存储方式:Session 或 Local paths: ['userInfos'], // 需要持久化的字段 } ``` ### 样式开发 - 支持 Tailwind CSS 工具类 - 支持 SCSS 预处理器 - 全局样式位于 `src/assets/style/` 和 `src/theme/` ### 权限系统 项目实现了完整的权限控制系统,包括路由权限、按钮权限和字段权限。 #### 1. 按钮权限 使用 `auth()` 函数进行按钮权限验证: ```typescript import { auth } from '/@/utils/authFunction'; // 单个权限验证 if (auth('company:Create')) { // 有权限,显示按钮 } // 多个权限验证(满足一个即可) import { auths } from '/@/utils/authFunction'; if (auths(['company:Create', 'company:Edit'])) { // 有任一权限即可 } // 多个权限验证(全部满足) import { authAll } from '/@/utils/authFunction'; if (authAll(['company:Create', 'company:Edit'])) { // 必须全部有权限 } ``` 在模板中使用: ```vue ``` #### 2. 路由权限 路由权限在路由守卫中自动处理(`src/router/index.ts`): - 未登录用户自动跳转到登录页 - 根据用户角色动态加载路由 - 支持前端控制和后端控制两种模式 #### 3. 字段权限 字段权限通过 `columnPermission` Store 管理,可以控制表格列的显示。 ### 国际化 项目支持多语言,配置文件位于 `src/i18n/` 目录。 #### 使用方式 ```typescript import { useI18n } from 'vue-i18n'; const { t } = useI18n(); const message = t('common.save'); // 获取翻译文本 ``` #### 添加新语言 1. 在 `src/i18n/` 目录下创建语言文件 2. 在 `src/i18n/index.ts` 中注册新语言 3. 使用 `useI18n().locale.value = 'en'` 切换语言 ## 常用命令 ```bash # 启动开发服务器 npm run dev # 构建生产版本 npm run build # 构建本地生产版本(使用 local_prod 环境变量) npm run build:local # 代码检查和自动修复 npm run lint-fix ``` ## 开发注意事项 1. **路径别名**: - `/@/` 指向 `src/` 目录 - `@views` 指向 `src/views` 目录 2. **环境变量**: - 所有环境变量必须以 `VITE_` 开头才能在代码中访问 - 使用 `import.meta.env.VITE_XXX` 访问环境变量 3. **API 请求**: - 所有 API 请求会自动添加认证 token(从 Cookie 中获取) - 请求拦截器配置在 `src/utils/service.ts` 4. **版本管理**: - 构建时会自动生成版本文件到 `public/version-build` - 生产环境会自动检查版本更新 5. **浏览器兼容性**: - 支持 Edge ≥ 79, Firefox ≥ 78, Chrome ≥ 64, Safari ≥ 12 - 不支持 IE11 及以下版本 ## 组件开发规范 ### 1. 组件命名 - **文件命名**: 使用 PascalCase(大驼峰),如 `UserProfile.vue` - **组件注册**: 使用 kebab-case(短横线),如 `` - **目录命名**: 使用 kebab-case,如 `user-profile/` ### 2. 组件结构 ```vue ``` ### 3. 代码规范 - 使用 TypeScript 进行类型定义 - 使用 Composition API(`