Files
nl-admin-view/.cursor/rules/Vben-Components.mdc
李琦 089fa2f3eb
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CI / CI OK (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
更新规则和uipro
2026-08-10 14:42:27 +08:00

236 lines
9.8 KiB
Plaintext
Raw Permalink 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: nl-admin-view Vben 5.7 官方组件用法规范Page/Form/Modal/Drawer/VxeTable 等)
globs: apps/web-antd/**/*.{vue,ts}
alwaysApply: false
---
# Vben 组件规则(对齐 5.7.0 官方文档 + 本仓库约定)
当前版本:**Vben Admin 5.7.0**。文档来源https://doc.vben.pro/components/
业务页统一在 `apps/web-antd`;表单/表格必须走本仓库适配器,不要直接依赖底层实现细节。
`lock` / `unlock`、Promise 版 `onBeforeClose`、`animationType`、`center-footer` 等在 5.7 已是基线能力,规则里不再标注「>5.5.x」版本门槛。
## 选型速查
| 场景 | 用什么 | 不要用 |
|---|---|---|
| 页面外壳 | `Page``@vben/common-ui` | 自写页面头/底容器 |
| 列表+搜索 | `useVbenVxeGrid``#/adapter/vxe-table` | 直接 `new VxeGrid` / antd `Table` |
| 表单 | `useVbenForm``#/adapter/form` | antd `Form` / 手写校验 |
| 复杂弹窗(表单/多步) | `useVbenModal` | antd `Modal` |
| 侧滑面板 | `useVbenDrawer` | antd `Drawer` |
| 轻量确认/提示/单输入 | `alert` / `confirm` / `prompt` | 为简单确认再开 Modal |
| 表格行/工具栏按钮 | `#/components/table-action` 的 `TableAction` | 散落一排 `Button` |
| 远程下拉/树选 | 适配器里的 `ApiSelect` / `ApiTreeSelect`(底层 `ApiComponent` | 页面里手写 options 拉取逻辑 |
| 超长文本 | `EllipsisText` | CSS 省略后无 Tooltip |
| 只读详情字段组 | `VbenDescriptions` | 手写 label-value 网格 |
| 头像/固定比例裁剪 | `VCropper` | 无裁剪直接上传原图(需要裁剪时) |
| 富文本 | `VbenTiptap``@vben/plugins/tiptap` | 再引一套编辑器 |
---
## Page
- 业务页根节点用 `<Page>`;列表页常见:`<Page auto-content-height title="xxx">`
- `title` / `description` / `#extra` 都没有内容时,头部不渲染
- `autoContentHeight`:内容区按可视高度自动扣减头/底;额外偏移用 `heightOffset`px
- `appendToMain` 的 Modal/Drawer 挂到内容区时,**Page 必须开 `auto-content-height`**,否则高度计算不对
- 插槽:`default` / `title` / `description` / `extra` / `footer`
---
## Modal`useVbenModal`
```ts
const [Modal, modalApi] = useVbenModal({
connectedComponent: ExtraModal, // 复杂内容抽离子组件
draggable: true,
// overflow: true, // 需要拖出可视区时再开
});
```
强制约定:
- 复杂弹窗用 `connectedComponent`;内外共享 `modalApi`
- **严禁覆盖 `#footer`**(会丢掉默认取消/确定与 loading
- 扩展底部只用:`prepend-footer` / `center-footer` / `append-footer`
- 提交防重复:优先 `modalApi.lock()` / `unlock()``unlock` = `lock(false)`;锁定时确认按钮 loading、禁关弹窗或 `setState({ confirmLoading: true })`
- 回填:`modalApi.setData(data).open()`;内部 `onOpenChange` 里 `modalApi.getData()`
- 参数优先级:`slot` > `props` > `state``connectedComponent` 时同名事件**以内侧为准**`onOpenChange` 内外都会触发)
- 默认属性可在 `apps/web-antd/src/bootstrap.ts` 的 `setDefaultModalProps` 统一改
- 动画:`animationType: 'slide' | 'scale'`(默认 slide
- `destroyOnClose`:关闭后销毁内部 Modal 及子组件(配合 `connectedComponent` 时同样生效)
常用 API`open` / `close` / `setState` / `setData` / `getData` / `lock` / `unlock` / `useStore`
---
## Drawer`useVbenDrawer`
- API 形态与 Modal 基本一致:`connectedComponent`、`setData/getData`、`lock/unlock`、footer 三插槽
- **同样严禁覆盖 `#footer`**
- `placement`: `left | right | top | bottom`(默认 `right`
- 关闭前校验用 `onBeforeClose`(支持 Promise / 返回 `false`);需要重置内部状态可开 `destroyOnClose`
- 挂内容区同样要配合 Page 的 `auto-content-height`
- 默认属性:`setDefaultDrawerProps`
---
## Alert轻量提示
来自 `@vben/common-ui``alert` / `confirm` / `prompt` / `useAlertContext`
- **简单确认、提示、单字段输入**用这套;复杂表单/多控件仍用 Modal
- `confirm().then/catch`;异步关闭用 `beforeClose`,返回 `false` 可阻止关闭
- `prompt` 可传 `component` + `componentProps`antd Select 需 `popupClassName: 'pointer-events-auto'`
- 自定义内容里需要主动确认/取消:`useAlertContext().doConfirm/doCancel`(仅 setup/函数组件)
- 动态创建的 Alert **不支持 HMR**,改代码后需关掉重开
---
## Form`useVbenForm` from `#/adapter/form`
```ts
const [Form, formApi] = useVbenForm({
schema: [
{
fieldName: 'nick_name', // 与后端 snake_case 对齐
label: '昵称',
component: 'Input',
rules: 'required', // 选择类用 selectRequired
componentProps: { placeholder: '请输入' },
},
],
});
```
强制约定:
- 只从 `#/adapter/form` 引入,不直接玩 TanStack Form 实例
- 动态改字段:`formApi.updateSchema([...])`**没有** `setComponentProps`
- 重置:`formApi.resetForm()`**禁止** `resetFields()`antd API会报错
- 取值/赋值:`getValues()` / `setValues()`;需要提交编解码时用 `codec` / `getRawValues()`
- 校验:`formApi.validate().then(e => { if (e.valid) ... })` 或 `validateAndSubmitForm()`
- 字段自定义 slot控件绑定用 `v-bind="slotProps.componentProps"`(不要再 `v-bind="slotProps"`
- 联动优先 `dependencies.resolve(context)` 一次返回 `show/disabled/rules/componentProps...`
- 远程 options打开时拉取后 `updateSchema` 注入;或用 `ApiSelect`/`ApiTreeSelect`
- 密码字段用 `InputPassword`(适配器组件名),不要 `Input` + `type="password"`
---
## Vxe Table`useVbenVxeGrid` from `#/adapter/vxe-table`
```ts
const [Grid, gridApi] = useVbenVxeGrid({
formOptions, // 搜索表单Vben Form
gridOptions: {
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
// 返回适配器约定结构
return { items: [], total: 0 };
},
},
},
toolbarConfig: { search: true },
},
gridEvents,
});
```
强制约定:
- 远程列表走 `proxyConfig.ajax.query`,禁止自己 fetch 再赋 `data`
- 响应结构对齐适配器:`{ items, total }`(见 `apps/web-antd/src/adapter/vxe-table.ts`
- 分页从 `{ page }` 取 `currentPage` / `pageSize`
- 刷新:`gridApi.query()` 保留页;`gridApi.reload()` 回第一页
- loading`gridApi.setLoading(bool)`
- 工具栏插槽:`toolbar-actions`(左)/ `toolbar-tools`(右)
- 操作列:列上 `slots: { default: 'action' }`,页面 `<template #action="{ row }">`**禁止**列 render 写 JSX
- 需要原生能力时用 `gridApi.grid`(如树展开 `setAllTreeExpand`
---
## ApiComponent / ApiSelect
- 一般不直接用 `ApiComponent`;优先用适配器包装好的 `ApiSelect` / `ApiTreeSelect`
- 关键映射:`api` / `params` / `resultField` / `labelField` / `valueField` / `childrenField`
- `immediate: false` + `visibleEvent`:展开时再请求
- 同页多实例同数据源:用 TanStack Query/`useQuery` 包一层再传 `api`,避免 N 次请求
- `autoSelect`: `'first' | 'last' | 'one' | fn | false`(不要用在多选)
---
## TableAction本仓库
本仓库列表页已统一用本地封装:
```ts
import { TableAction } from '#/components/table-action';
```
- 字段习惯:`label`(不是官方 demo 的 `text`)、`drop-down-actions`、`popConfirm`、`auth`、`ifShow`
- 放在 `#toolbar-actions` 与 `#action` 插槽中
- 若改用官方 `VbenTableAction``@vben/common-ui` / `#/adapter/vxe-table`),注意其字段为 `text` / `dropdownActions`,并优先走适配器以自动注入权限
---
## EllipsisText
```vue
<EllipsisText :max-width="240" :line="2" :tooltip-when-ellipsis="true">
{{ text }}
</EllipsisText>
```
- 表格/卡片超长文案优先用它;需要展开收起开 `expand`
- `tooltipWhenEllipsis`:仅截断时显示提示,避免短文本也弹层
---
## VbenDescriptions
- 详情/预览优先 `:items="[{ label, content, span }]"` 数据驱动
- `span: 'filled'` 占满当前行剩余;`column` 可传断点对象
- `bordered` + `title` + `#extra` 做带操作的信息块
- `layout="vertical"` 标签在上;也可用 `VbenDescriptionsItem` 子组件(`items` 优先)
---
## VCropper
```ts
const blob = await cropperRef.value?.getCropImage('image/jpeg', 0.9, 'blob');
```
- Props`img`(必填)、`width`/`height`、`aspectRatio`(如 `'1:1'` `'16:9'`
- blob URL 用完/`onBeforeUnmount` 要 `URL.revokeObjectURL`,防泄漏
- 网络图导出需 CORS头像场景常用固定比例 + 指定 `targetWidth/targetHeight`
---
## VbenTiptap`@vben/plugins/tiptap`
```vue
<VbenTiptap v-model="html" :image-upload="imageUpload" />
<VbenTiptapPreview :content="html" />
```
- 内容为 HTML 字符串;只读展示用 `VbenTiptapPreview`
- 上传必须配 `imageUpload.upload(file, onProgress) => Promise<url>`,走本项目上传接口
- 上传中不要拿 `getHTML()` 去保存(可能是临时 blob URL
- 自定义 `extensions` 会覆盖默认扩展,且图片上传能力不可用——非必要不要自定义
---
## 与本仓库踩坑清单(必守)
1. Form 无 `setComponentProps` / 无 `resetFields`
2. Modal/Drawer 禁止覆盖 `#footer`;提交用 `lock/unlock`5.7 基线,无需再判断版本)
3. 表格返回必须是 `{ items, total }`;刷新分清 `query` vs `reload`
4. 字段名 `fieldName` 用后端 snake_case如 `created_at`、`nick_name`
5. 状态枚举与后端一致:**0 正常 / 1 禁用**
6. 暗色主题:业务样式用 CSS 变量,禁止写死亮色色值(见 `Code-Standards.mdc`
7. Tailwind 已是 v4业务样式优先主题 CSS 变量 / 现有 utility不要新建 v3 的 `tailwind.config.*`
8. 业务 CRUD 只改 `apps/web-antd`;不要往 `web-ele` / `web-naive` / `web-antdv-next` 等演示端塞业务代码