# 前端开发文档
本文档定义了项目的开发规范、组件复用指南和代码风格要求,确保团队开发风格统一。
---
## 一、开发规范
### 1.1 组件开发规范
#### 组件命名
```typescript
// ✅ 正确:组件文件使用 PascalCase
UserList.vue;
DictTag.vue;
TableAction.vue;
// ❌ 错误:使用 kebab-case 或其他命名
user - list.vue;
dict_tag.vue;
```
#### 组件定义
```vue
```
#### TypeScript 规范
```typescript
// ✅ 正确:禁止使用 any,使用具体类型
interface UserInfo {
id: number;
name: string;
email?: string;
}
function getUser(id: number): Promise {
return request.get(`/user/${id}`);
}
// ❌ 错误:使用 any
function getUser(id: any): any {
return request.get(`/user/${id}`);
}
// ✅ 正确:使用 import type 导入类型
import type { UserInfo } from "#/api/system/user";
// ❌ 错误:普通导入类型
import { UserInfo } from "#/api/system/user";
```
### 1.2 目录结构规范
```
src/
├── api/ # API 接口定义,按模块划分
│ ├── system/ # 系统模块
│ │ ├── user/
│ │ │ └── index.ts
│ │ └── dept/
│ │ └── index.ts
│ └── ...
├── components/ # 公共组件(全局注册)
├── views/ # 页面组件,按业务模块划分
│ └── system/
│ └── user/
│ ├── index.vue # 列表页
│ ├── data.ts # 数据定义
│ └── modules/ # 子组件/弹窗
│ └── form.vue
├── locales/ # 国际化
├── router/ # 路由配置
├── stores/ # Pinia 状态管理
├── utils/ # 工具函数
└── adapter/ # 适配器配置
```
### 1.3 API 接口规范
```typescript
// src/api/system/user/index.ts
import { request } from "#/utils/request";
export namespace SystemUserApi {
/** 用户信息 */
export interface User {
id: number;
username: string;
nickname: string;
email?: string;
status: number;
deptId?: number;
createTime: string;
}
/** 用户分页查询参数 */
export interface PageParams {
pageNo: number;
pageSize: number;
username?: string;
status?: number;
deptId?: number;
}
/** 分页结果 */
export interface PageResult {
list: User[];
total: number;
}
}
/** 获取用户分页列表 */
export function getUserPage(params: SystemUserApi.PageParams) {
return request.get("/system/user/page", { params });
}
/** 获取用户详情 */
export function getUser(id: number) {
return request.get(`/system/user/get?id=${id}`);
}
/** 创建用户 */
export function createUser(data: SystemUserApi.User) {
return request.post("/system/user/create", data);
}
/** 更新用户 */
export function updateUser(data: SystemUserApi.User) {
return request.put("/system/user/update", data);
}
/** 删除用户 */
export function deleteUser(id: number) {
return request.delete(`/system/user/delete?id=${id}`);
}
```
### 1.4 样式规范
```vue
```
---
## 二、核心组件复用指南
### 2.1 表格组件 (useVbenVxeGrid)
项目使用 VxeTable 封装的 `useVbenVxeGrid` 作为核心表格组件。
#### 基础用法
```vue
```
#### 表格列渲染器
| 渲染器 | 用途 | 示例 |
| --------------- | -------- | -------------------------------------------------------------------- |
| `CellImage` | 单图展示 | `cellRender: { name: 'CellImage' }` |
| `CellImages` | 多图展示 | `cellRender: { name: 'CellImages' }` |
| `CellLink` | 链接按钮 | `cellRender: { name: 'CellLink', props: { text: '查看' } }` |
| `CellTag` | 标签展示 | `cellRender: { name: 'CellTag', props: { color: 'blue' } }` |
| `CellDict` | 字典标签 | `cellRender: { name: 'CellDict', props: { type: 'common_status' } }` |
| `CellSwitch` | 开关切换 | `cellRender: { name: 'CellSwitch', attrs: { beforeChange } }` |
| `CellOperation` | 操作按钮 | `cellRender: { name: 'CellOperation', options: ['edit', 'delete'] }` |
### 2.2 表单弹窗 (useVbenModal)
```vue
```
表单组件示例:
```vue
```
### 2.3 字典组件
#### DictTag - 字典标签
用于展示数据字典值的标签形式。
```vue
```
#### DictSelect - 字典选择器
用于表单中从字典选择值。
```vue
```
#### 字典工具函数
```typescript
import {
getDictOptions,
getDictLabel,
getDictObj,
} from "#/packages/effects/hooks/src";
// 获取字典选项列表(用于 Select/Radio 等组件)
const options = getDictOptions("common_status", "number");
// 获取字典标签文本
const label = getDictLabel("common_status", 1); // "开启"
// 获取字典完整对象
const dictObj = getDictObj("common_status", 1);
// { label: '开启', value: 1, colorType: 'success', cssClass: '' }
```
### 2.4 表格操作组件 (TableAction)
用于表格中的操作按钮,支持权限控制和二次确认。
```vue
```
### 2.5 文件上传组件
#### ImageUpload - 图片上传
```vue
```
#### FileUpload - 文件上传
```vue
```
### 2.6 描述列表组件 (Description)
用于详情页展示数据。
```vue
```
---
## 三、状态管理
### 3.1 使用 Pinia Store
项目使用 Pinia 进行状态管理,Store 定义在 `src/packages/stores/src` 中。
#### 常用 Store
| Store | 用途 | 导入路径 |
| ---------------- | ---------- | ----------------------- |
| `useUserStore` | 用户信息 | `#/packages/stores/src` |
| `useAccessStore` | 权限/Token | `#/packages/stores/src` |
| `useDictStore` | 数据字典 | `#/packages/stores/src` |
#### 示例
```typescript
import { useUserStore, useAccessStore } from "#/packages/stores/src";
const userStore = useUserStore();
const accessStore = useAccessStore();
// 获取用户信息
const userInfo = userStore.userInfo;
// 检查权限
const { hasAccessByCodes } = useAccess();
const canEdit = hasAccessByCodes(["system:user:update"]);
```
---
## 四、权限控制
### 4.1 按钮权限
```vue
```
### 4.2 路由权限
在路由配置中通过 `meta.authorities` 设置权限:
```typescript
{
path: 'user',
name: 'SystemUser',
component: () => import('#/views/system/user/index.vue'),
meta: {
title: '用户管理',
authorities: ['system:user:visit'],
},
}
```
---
## 五、国际化
### 5.1 使用方式
```vue
{{ $t("ui.actionMessage.deleteSuccess", ["用户"]) }}
```
### 5.2 添加国际化文本
在 `src/locales` 目录下的语言文件中添加:
```json
// src/locales/zh-CN.json
{
"common": {
"save": "保存",
"cancel": "取消"
},
"ui": {
"actionMessage": {
"deleteSuccess": "删除【{0}】成功"
}
}
}
```
---
## 六、常用 Hooks
### 6.1 usePagination - 分页
```typescript
import { usePagination } from "#/packages/effects/hooks/src";
const { page, pageSize, total, setPage, setTotal } = usePagination();
```
### 6.2 useTabs - 标签页操作
```typescript
import { useTabs } from "#/packages/effects/hooks/src";
const { closeOtherTabs, closeTab, refreshTab } = useTabs();
// 关闭其他标签页
await closeOtherTabs();
// 刷新当前页
await refreshTab();
```
### 6.3 useWatermark - 水印
```typescript
import { useWatermark } from "#/packages/effects/hooks/src";
const { updateWatermark, destroyWatermark } = useWatermark();
// 设置水印
await updateWatermark({
content: "用户名",
});
// 销毁水印
destroyWatermark();
```
---
## 七、工具函数
### 7.1 常用工具
```typescript
import {
formatDateTime, // 日期格式化
formatDate, // 日期格式化(不含时间)
downloadFileFromBlobPart, // 文件下载
isEmpty, // 判空
isFunction, // 判断函数
isString, // 判断字符串
} from "#/packages/utils/src";
// 日期格式化
formatDateTime("2024-01-01T12:00:00"); // "2024-01-01 12:00:00"
// 文件下载
downloadFileFromBlobPart({
fileName: "用户列表.xlsx",
source: blobData,
});
// 判空
isEmpty([]); // true
isEmpty({}); // true
isEmpty(null); // true
```
### 7.2 数字格式化
```typescript
import {
erpNumberFormatter, // 数字格式化
fenToYuan, // 分转元
formatFileSize, // 文件大小格式化
} from "#/packages/utils/src";
// 保留两位小数
erpNumberFormatter(1234.567, 2); // "1,234.57"
// 分转元
fenToYuan(12345); // 123.45
// 文件大小
formatFileSize(1024 * 1024); // "1.00 MB"
```
---
## 八、代码示例:标准 CRUD 页面
```vue
```
---
## 九、注意事项
1. **路径别名**:`#/*` 指向 `./src/*`,导入时使用 `#/components/xxx` 而非相对路径
2. **表单验证**:使用 VeeValidate + Zod,在 schema 中通过 `rules` 属性定义
3. **HTML 安全**:用户输入的 HTML 使用 `v-dompurify-html` 处理
4. **敏感数据**:使用 `secure-ls` 加密存储
5. **代码注释**:只在 WHY 不明显时添加注释,避免无意义的注释
6. **组件命名**:必须使用 `defineOptions({ name: 'ComponentName' })` 定义组件名
---
## 十、相关资源
- [Vue 3 文档](https://vuejs.org/)
- [Ant Design Vue 文档](https://antdv.com/)
- [VxeTable 文档](https://vxetable.cn/)
- [Tailwind CSS 文档](https://tailwindcss.com/)
- [项目 CLAUDE.md](./CLAUDE.md)