tydata-admin/.cursor/rules/vben.mdc

330 lines
7.8 KiB
Plaintext
Raw Normal View History

2025-06-08 20:16:51 +08:00
---
description:
globs:
alwaysApply: true
---
# Vue Vben Admin 开发规范与模板
## 1. 目录结构规范
```
views/
├── [module]/ # 模块目录
│ ├── data.ts # 表单schema、表格列配置等
│ ├── list.vue # 主列表页面
│ └── modules/ # 子模块组件
│ └── form.vue # 表单抽屉组件
```
## 2. 代码模板
### 2.1 列表页面模板 (list.vue)
```vue
<script lang="ts" setup>
import type { Recordable } from '@vben/types';
import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/vxe-table';
import type { [Module]Api } from '#/api';
import { Page, useVbenDrawer } from '@vben/common-ui';
import { Plus } from '@vben/icons';
import { Button, message, Modal } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { delete[Module], get[Module]List, update[Module] } from '#/api';
import { $t } from '#/locales';
import { useColumns, useGridFormSchema } from './data';
import Form from './modules/form.vue';
// 表单抽屉
const [FormDrawer, formDrawerApi] = useVbenDrawer({
connectedComponent: Form,
destroyOnClose: true,
});
// 表格配置
const [Grid, gridApi] = useVbenVxeGrid({
formOptions: {
fieldMappingTime: [['create_time', ['startTime', 'endTime']]],
schema: useGridFormSchema(),
submitOnChange: true,
},
gridOptions: {
columns: useColumns(onActionClick, onStatusChange),
height: 'auto',
keepSource: true,
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
return await get[Module]List({
page: page.currentPage,
pageSize: page.pageSize,
...formValues,
});
},
},
},
rowConfig: {
keyField: 'id',
},
toolbarConfig: {
custom: true,
export: false,
refresh: { code: 'query' },
search: true,
zoom: true,
},
} as VxeTableGridOptions<[Module]Api.[Module]Item>,
});
// 操作处理函数
function onActionClick(e: OnActionClickParams<[Module]Api.[Module]Item>) {
switch (e.code) {
case 'delete': onDelete(e.row); break;
case 'edit': onEdit(e.row); break;
}
}
// 状态变更处理
async function onStatusChange(newStatus: number, row: [Module]Api.[Module]Item) {
const status: Recordable<string> = {
0: '禁用',
1: '启用',
};
try {
await confirm(
`你要将${row.name}的状态切换为 【${status[newStatus.toString()]}】 吗?`,
`切换状态`,
);
await update[Module](mdc:row.id, { status: newStatus });
return true;
} catch {
return false;
}
}
// 编辑处理
function onEdit(row: [Module]Api.[Module]Item) {
formDrawerApi.setData(row).open();
}
// 删除处理
function onDelete(row: [Module]Api.[Module]Item) {
const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting', [row.name]),
duration: 0,
key: 'action_process_msg',
});
delete[Module](mdc:row.id)
.then(() => {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.name]),
key: 'action_process_msg',
});
onRefresh();
})
.catch(() => {
hideLoading();
});
}
// 刷新处理
function onRefresh() {
gridApi.query();
}
// 创建处理
function onCreate() {
formDrawerApi.setData({}).open();
}
</script>
<template>
<Page auto-content-height>
<FormDrawer @success="onRefresh" />
<Grid :table-title="$t('module.list')">
<template #toolbar-tools>
<Button type="primary" @click="onCreate">
<Plus class="size-5" />
{{ $t('ui.actionTitle.create', [$t('module.name')]) }}
</Button>
</template>
</Grid>
</Page>
</template>
```
### 2.2 数据配置模板 (data.ts)
```typescript
import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
import type { [Module]Api } from '#/api';
import { $t } from '#/locales';
// 表单配置
export function useFormSchema(): VbenFormSchema[] {
return [
{
component: 'Input',
fieldName: 'field_name',
label: $t('module.field.label'),
rules: 'required',
},
// ... 其他表单项
];
}
// 搜索表单配置
export function useGridFormSchema(): VbenFormSchema[] {
return [
{
component: 'Input',
fieldName: 'search_field',
label: $t('module.search.label'),
},
// ... 其他搜索项
];
}
// 表格列配置
export function useColumns<T = [Module]Api.[Module]Item>(
onActionClick: OnActionClickFn<T>,
onStatusChange?: (newStatus: any, row: T) => PromiseLike<boolean | undefined>,
): VxeTableGridOptions['columns'] {
return [
{
field: 'field_name',
title: $t('module.field.label'),
width: 200,
},
// ... 其他列
{
align: 'center',
cellRender: {
attrs: {
nameField: 'name_field',
nameTitle: $t('module.name.label'),
onClick: onActionClick,
},
name: 'CellOperation',
},
field: 'operation',
fixed: 'right',
title: $t('module.operation'),
width: 130,
},
];
}
```
### 2.3 表单组件模板 (form.vue)
```vue
<script lang="ts" setup>
import type { [Module]Api } from '#/api';
import { useVbenForm } from '#/adapter/form';
import { create[Module], update[Module] } from '#/api';
import { $t } from '#/locales';
import { useFormSchema } from '../data';
const emit = defineEmits<{
(e: 'success'): void;
}>();
const [Form, formApi] = useVbenForm({
schema: useFormSchema(),
submitButtonText: $t('ui.actionTitle.submit'),
submit: async (values) => {
if (values.id) {
await update[Module](mdc:values.id, values);
} else {
await create[Module](mdc:values);
}
emit('success');
},
});
</script>
<template>
<Form />
</template>
```
### 2.4 API 接口定义模板
```typescript
import type { BaseApi } from '#/api';
export namespace [Module]Api {
export interface [Module]Item {
id: number;
// ... 其他字段
}
export interface [Module]ListParams extends BaseApi.ListParams {
// ... 其他查询参数
}
export interface [Module]ListResult extends BaseApi.ListResult<[Module]Item> {}
}
export function get[Module]List(params: [Module]Api.[Module]ListParams) {
return request.get<[Module]Api.[Module]ListResult>('/api/[module]/list', { params });
}
export function create[Module](mdc:data: Omit<[Module]Api.[Module]Item, 'id'>) {
return request.post<[Module]Api.[Module]Item>('/api/[module]/create', data);
}
export function update[Module](mdc:id: number, data: Partial<[Module]Api.[Module]Item>) {
return request.put<[Module]Api.[Module]Item>(`/api/[module]/update/${id}`, data);
}
export function delete[Module](mdc:id: number) {
return request.delete(`/api/[module]/delete/${id}`);
}
```
### 2.5 国际化文案模板
```typescript
export default {
module: {
name: '[模块名称]',
list: '[模块名称]列表',
field: {
label: '[字段标签]',
},
search: {
label: '[搜索标签]',
},
operation: '操作',
},
};
```
## 3. 使用说明
1. 创建新模块时,按照目录结构规范创建相应的文件
2. 复制对应的模板代码到相应文件中
3. 替换所有 `[Module]` 为你的模块名称(如 `Product`
4. 根据实际需求修改:
- 表单字段配置
- 搜索表单配置
- 表格列配置
- API 接口定义
- 国际化文案
## 4. 注意事项
1. 确保 API 接口已定义并正确实现
2. 确保国际化文案已配置
3. 根据实际需求调整表单和表格配置
4. 注意处理特殊字段(如时间、状态等)
5. 保持代码风格统一
6. 遵循项目的命名规范
## 5. 参考示例
可以参考以下现有模块的实现:
- @system/role
- @system/user
- @order