--- 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. 写代码的时候要补充详细的中文注释(每个方法是干嘛的,为什么要这样写),如果是工作区,则所有项目都适用该规则 2. 注意不要生成太多的空行,上一部分代码和下一部分代码中间的空行不要大于 2 行 3. 有封装好的方法、组件需要复用,不要重复造轮子 4. 小程序端的抽屉全部需要用 page-container 来防止用户意外退出页面(记得使用 v-if 而不是 v-show;本仓库为 PC 管理端,此项约束 uniapp) 5. 数据库的(created_at、updated_at、deleted_at)统一使用时间戳,不要使用字符串,并且我在查询器中一级格式化成字符串了,无需再次格式化 # 全局架构规范 ## 目录结构规范 - 业务页面统一放在 `apps/web-antd/src/views/<端>/<模块>/` - 当前已有端/模块:`system`(admin / role / menu / database)、`dashboard`、`code-generation`、`_core` - 新增业务优先挂在已有端下;确需新端时再建目录,**不要**照搬其他项目的 `business` / `doctor` 等目录名 - 标准 CRUD 模块目录结构(以 `system/admin`、`system/role`、`system/menu` 为准): ``` views/<端>/<模块>/ ├── index.vue # 列表页(Page + Grid + Modal) ├── api/index.ts # 本模块 API(CRUD) ├── config/ │ ├── table.ts # vxe-grid 列定义 + proxyConfig │ ├── search.ts # 顶部搜索表单 schema │ └── form.ts # 新增/编辑弹窗 form schema ├── components/ │ └── modal.vue # 新增/编辑弹窗 └── utils/ # 模块工具(可选) ``` - 非标准 CRUD(如 `system/database`、`code-generation`)可按功能拆组件,但仍须把请求收敛到模块 `api/` - 全局复用组件放 `apps/web-antd/src/components/` - 表单内可用组件放 `apps/web-antd/src/components/form/components/`,文件名 kebab-case,自动注册为 schema 的 `component` 名(PascalCase 引用) ## 强制复用封装(禁止重复造轮子) - 表格统一用 `useVbenVxeGrid`(来自 `#/adapter/vxe-table`),**不要直接 new VxeGrid** - 表单统一用 `useVbenForm`(来自 `#/adapter/form`),**不要直接写 `
` + 手动校验** - 弹窗统一用 `useVbenModal`(来自 `@vben/common-ui`),**不要用原生 ``** - 页面外壳统一用 `` 组件(来自 `@vben/common-ui`) - HTTP 请求统一用 `requestClient`(来自 `#/api/request`),**禁止直接 axios / fetch** - 行操作和工具栏按钮统一用 `` 组件(来自 `#/components/table-action`) - 表单选择器/上传等:优先复用 `#/components/form/components/` 已有组件(当前有 upload / upload-image / avatar);没有再新增,禁止业务页内再造一份 ## API 层规范 - API 文件统一放在 `<模块>/api/index.ts` - 函数命名约定:`get{Entity}List` / `get{Entity}Option` / `get{Entity}Info` / `create{Entity}` / `update{Entity}` / `delete{Entity}` - URL 使用 kebab-case,统一前缀变量 `const prefix = 'xxx/'`,**URL 末尾不补 `/`** - GET 用 `params`,POST 用 `data`,例如: ```ts import { requestClient } from '#/api/request'; const prefix = 'admin/'; export async function getAdminList(data: any) { return requestClient.get(`${prefix}list`, { params: data }); } ``` - 现有资源前缀参考:`admin/`、`role/`、`menu/`、`database/`、`code/`;登录后菜单接口为 `GET admin/menu` ## 字段命名对齐后端 - 数据库字段在前端 schema 的 `field` / `fieldName` 中保持 snake_case(如 `created_at`、`role_id`、`nick_name`),**不要转换为 camelCase** - 时间戳字段(`created_at` 等)后端查询器已格式化为字符串,前端**无需再次格式化** - TS 变量用 camelCase,常量用 UPPER_SNAKE_CASE,类型用 PascalCase - 物理表前缀为 `nl_`(如 `nl_admin`、`nl_menu`),前端只对齐字段名,不必在 API 路径里写表前缀 ## 表单校验 - 必填用字符串规则 `rules: 'required'`(选择项用 `'selectRequired'`),规则定义在 `#/adapter/form.ts` 的 `defineRules` - 校验调用统一用 `formApi.validate().then(e => { if (e.valid) {...} })` - 必填字段在 schema 中加 `rules: 'required'`,禁止散落 `validator` 写法 ## 字典/枚举管理 - 模块内建 `config/constants.ts`,导出 `{ label, value }[]` 数组,禁止在 schema 中散落字面量 - 例如: ```ts export const STATUS_OPTIONS = [ { label: '启用', value: 0 }, { label: '禁用', value: 1 }, ]; ``` ## 路由规范 - 业务路由通过后端动态菜单驱动(库表 `nl_menu`,接口 `admin/menu`,`accessMode: 'backend'`) - **不要**在前端 `router/routes/modules/` 静态注册业务路由(框架自带的 dashboard / core 除外) - `defineOptions({ name: 'PascalCaseName' })` 必须与 `nl_menu.name` 字段一致(如 `SystemUser`、`SystemRole`、`SystemMenu`) ## Tab 用法 - 统一用 antd 原生 `Tabs` + `Tabs.TabPane`,**不要找 Vben 自封装的 Tabs** - Tab 选中状态需要持久化时走 `localStorage`(模块内自定义 `TAB_STORAGE_KEY`) ## 中文注释 - 每个 `