diff --git a/.cursor/rules/Code-Standards.mdc b/.cursor/rules/Code-Standards.mdc index 296de99d..0a922108 100644 --- a/.cursor/rules/Code-Standards.mdc +++ b/.cursor/rules/Code-Standards.mdc @@ -1,8 +1,16 @@ --- -description: nl-admin 管理后台(Vben Admin v5 + Vue 3 + TS + Ant Design Vue)代码规范 +description: nl-admin 管理后台(Vben Admin 5.7 + Vue 3.5 + TS + Ant Design Vue 4)代码规范 alwaysApply: true --- +# 技术栈基线(升级后必守) + +- **Vben Admin 5.7.0**(monorepo 根 `package.json` / `@vben/web-antd` 版本) +- **Vue 3.5** + **TypeScript** + **Ant Design Vue 4.x**;业务只改 `apps/web-antd` +- **Tailwind CSS v4**(CSS-first,主题在 `@vben/tailwind-config`);不要再引入 `tailwind.config.*` / PostCSS Tailwind 插件那套 v3 写法 +- 格式化 / Lint 以仓库现有工具链为准:`oxfmt` + `oxlint`(配合 eslint / stylelint),**不要**再单独引入 Prettier 作为主格式化器 +- 组件细则见同目录 `Vben-Components.mdc`(与 https://doc.vben.pro/components/ 对齐) + # 基础规范(所有项目通用) 1. 写代码的时候要补充详细的中文注释(每个方法是干嘛的,为什么要这样写),如果是工作区,则所有项目都适用该规则 @@ -133,7 +141,9 @@ alwaysApply: true - 表格空态、分割线、次要文案:用 `--muted` / `--muted-foreground` / `--border` - 改完后切换暗色主题肉眼过一遍,不要只测亮色 -## Vben 组件使用规范 +## Vben 组件使用规范(5.7 基线) + +> 完整 API / 踩坑见 `Vben-Components.mdc`。下列为业务页强制约定;`lock` / `unlock` / Promise 版 `onBeforeClose` 在 5.7 已是默认能力,**不要再写「需 >5.5.x」这类过时版本门槛**。 ### VbenModal(来自 @vben/common-ui) @@ -141,18 +151,18 @@ alwaysApply: true - 抽离弹窗内容到子组件时,外层用 `connectedComponent` 参数连接,内外组件共享 `modalApi` - 底部按钮扩展 slot 优先级:`prepend-footer`(取消按钮左侧)> `center-footer`(取消/确定之间)> `append-footer`(确定右侧) - **严禁覆盖 `#footer` slot**,会丢失默认的取消/确定按钮和 loading 行为 -- 表单提交 loading 走 `modalApi.setState({ confirmLoading: true })`,禁止自己写 button loading -- 提交防抖/防重复用 `modalApi.lock()` / `unlock()`(>5.5.3),禁止手动 disabled +- 提交防抖/防重复优先 `modalApi.lock()` / `unlock()`(锁定时确认按钮 loading,并禁止关闭);也可用 `setState({ confirmLoading: true })`,禁止自己写 button loading / disabled - 拖拽开 `draggable: true`,需要拖出可视区时同时开 `overflow: true` - 数据回填走 `modalApi.setData()` + `onOpenChange(isOpen) { const data = modalApi.getData() }` +- `animationType: 'slide' | 'scale'`(默认 slide);挂内容区时开 `appendToMain`,且 Page 必须 `auto-content-height` ### VbenDrawer(来自 @vben/common-ui) - 创建抽屉必须用 `useVbenDrawer`,禁止直接用 antd `Drawer` - 底部按钮扩展 slot 与 Modal 一致:`prepend-footer` / `center-footer` / `append-footer` - **同样严禁覆盖 `#footer` slot** -- 关闭前校验用 `onBeforeClose`(>5.5.2 支持 Promise),禁止自己拦截 -- 提交防抖/防重复用 `drawerApi.lock()` / `unlock()`(>5.5.3) +- 关闭前校验用 `onBeforeClose`(支持 Promise / 返回 `false`),禁止自己拦截 +- 提交防抖/防重复用 `drawerApi.lock()` / `unlock()` ### VbenVxeTable(来自 #/adapter/vxe-table) @@ -175,5 +185,5 @@ alwaysApply: true - 校验用 `formApi.validate().then(e => { if (e.valid) {...} })` 或 `formApi.validateAndSubmitForm()` - 必填规则用字符串 `'required'` / `'selectRequired'`,规则在 `#/adapter/form.ts` 的 `defineRules` 注册 - schema 中字段名(`fieldName`)必须与后端字段 snake_case 对齐,禁止前端 camelCase -- 密码/敏感字段用 `VbenInputPassword` 组件,禁止用 `VbenInput` 配 `type="password"` +- 业务表单密码字段用适配器组件名 `InputPassword`;禁止 `Input` + `type="password"`(框架自带页可用 `VbenInputPassword`) - 单选/多选选项来自接口时,必须在弹窗/页面 `onMounted` 或 `onOpenChange` 里拉取后通过 `updateSchema` 注入,禁止写死常量 diff --git a/.cursor/rules/Vben-Components.mdc b/.cursor/rules/Vben-Components.mdc index 879d51f4..04e19458 100644 --- a/.cursor/rules/Vben-Components.mdc +++ b/.cursor/rules/Vben-Components.mdc @@ -1,13 +1,14 @@ --- -description: nl-admin-view Vben 官方组件用法规范(Page/Form/Modal/Drawer/VxeTable 等) +description: nl-admin-view Vben 5.7 官方组件用法规范(Page/Form/Modal/Drawer/VxeTable 等) globs: apps/web-antd/**/*.{vue,ts} alwaysApply: false --- -# Vben 组件规则(对齐官方文档 + 本仓库约定) +# Vben 组件规则(对齐 5.7.0 官方文档 + 本仓库约定) -文档来源:https://doc.vben.pro/components/ -业务页统一在 `apps/web-antd`;表单/表格必须走本仓库适配器,不要直接依赖底层实现细节。 +当前版本:**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」版本门槛。 ## 选型速查 @@ -53,13 +54,14 @@ const [Modal, modalApi] = useVbenModal({ - 复杂弹窗用 `connectedComponent`;内外共享 `modalApi` - **严禁覆盖 `#footer`**(会丢掉默认取消/确定与 loading) - 扩展底部只用:`prepend-footer` / `center-footer` / `append-footer` -- 提交防重复:`modalApi.lock()` / `unlock()`(或 `setState({ confirmLoading: true })`) +- 提交防重复:优先 `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` +常用 API:`open` / `close` / `setState` / `setData` / `getData` / `lock` / `unlock` / `useStore` --- @@ -68,7 +70,7 @@ const [Modal, modalApi] = useVbenModal({ - API 形态与 Modal 基本一致:`connectedComponent`、`setData/getData`、`lock/unlock`、footer 三插槽 - **同样严禁覆盖 `#footer`** - `placement`: `left | right | top | bottom`(默认 `right`) -- 关闭前校验用 `onBeforeClose`(支持 Promise);需要重置内部状态可开 `destroyOnClose` +- 关闭前校验用 `onBeforeClose`(支持 Promise / 返回 `false`);需要重置内部状态可开 `destroyOnClose` - 挂内容区同样要配合 Page 的 `auto-content-height` - 默认属性:`setDefaultDrawerProps` @@ -224,8 +226,10 @@ const blob = await cropperRef.value?.getCropImage('image/jpeg', 0.9, 'blob'); ## 与本仓库踩坑清单(必守) 1. Form 无 `setComponentProps` / 无 `resetFields` -2. Modal/Drawer 禁止覆盖 `#footer`;提交用 `lock/unlock` +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` 等演示端塞业务代码