From 67050944064953c069a46089a04ba1e9aadc0ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E7=90=A6?= Date: Mon, 10 Aug 2026 12:38:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=A7=84=E5=88=99=E5=92=8Cui?= =?UTF-8?q?pro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cursor/rules/Code-Standards.mdc | 179 +++ .cursor/skills/ui-ux-pro-max/SKILL.md | 288 +++++ .cursor/skills/ui-ux-pro-max/data/charts.csv | 26 + .cursor/skills/ui-ux-pro-max/data/colors.csv | 97 ++ .cursor/skills/ui-ux-pro-max/data/icons.csv | 101 ++ .cursor/skills/ui-ux-pro-max/data/landing.csv | 31 + .../skills/ui-ux-pro-max/data/products.csv | 97 ++ .../ui-ux-pro-max/data/react-performance.csv | 45 + .../ui-ux-pro-max/data/stacks/astro.csv | 54 + .../ui-ux-pro-max/data/stacks/flutter.csv | 53 + .../data/stacks/html-tailwind.csv | 56 + .../data/stacks/jetpack-compose.csv | 53 + .../ui-ux-pro-max/data/stacks/nextjs.csv | 53 + .../ui-ux-pro-max/data/stacks/nuxt-ui.csv | 51 + .../ui-ux-pro-max/data/stacks/nuxtjs.csv | 59 + .../data/stacks/react-native.csv | 52 + .../ui-ux-pro-max/data/stacks/react.csv | 54 + .../ui-ux-pro-max/data/stacks/shadcn.csv | 61 + .../ui-ux-pro-max/data/stacks/svelte.csv | 54 + .../ui-ux-pro-max/data/stacks/swiftui.csv | 51 + .../skills/ui-ux-pro-max/data/stacks/vue.csv | 50 + .cursor/skills/ui-ux-pro-max/data/styles.csv | 68 ++ .../skills/ui-ux-pro-max/data/typography.csv | 58 + .../ui-ux-pro-max/data/ui-reasoning.csv | 101 ++ .../ui-ux-pro-max/data/ux-guidelines.csv | 100 ++ .../ui-ux-pro-max/data/web-interface.csv | 31 + .cursor/skills/ui-ux-pro-max/scripts/core.py | 253 ++++ .../ui-ux-pro-max/scripts/design_system.py | 1067 +++++++++++++++++ .../skills/ui-ux-pro-max/scripts/search.py | 114 ++ 29 files changed, 3357 insertions(+) create mode 100644 .cursor/rules/Code-Standards.mdc create mode 100644 .cursor/skills/ui-ux-pro-max/SKILL.md create mode 100644 .cursor/skills/ui-ux-pro-max/data/charts.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/colors.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/icons.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/landing.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/products.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/react-performance.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/stacks/astro.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/stacks/flutter.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/stacks/nextjs.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/stacks/react-native.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/stacks/react.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/stacks/shadcn.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/stacks/svelte.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/stacks/swiftui.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/stacks/vue.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/styles.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/typography.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/ui-reasoning.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/ux-guidelines.csv create mode 100644 .cursor/skills/ui-ux-pro-max/data/web-interface.csv create mode 100644 .cursor/skills/ui-ux-pro-max/scripts/core.py create mode 100644 .cursor/skills/ui-ux-pro-max/scripts/design_system.py create mode 100644 .cursor/skills/ui-ux-pro-max/scripts/search.py diff --git a/.cursor/rules/Code-Standards.mdc b/.cursor/rules/Code-Standards.mdc new file mode 100644 index 00000000..b4e5423f --- /dev/null +++ b/.cursor/rules/Code-Standards.mdc @@ -0,0 +1,179 @@ +--- +description: nl-admin 管理后台(Vben Admin v5 + Vue 3 + TS + Ant Design Vue)代码规范 +alwaysApply: true +--- + +# 基础规范(所有项目通用) + +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: 1 }, + { label: '禁用', value: 0 }, + ]; + ``` + +## 路由规范 + +- 业务路由通过后端动态菜单驱动(库表 `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`) + +## 中文注释 + +- 每个 `",High,https://nuxt.com/docs/guide/concepts/nuxt-lifecycle +18,Lifecycle,Use onMounted for DOM access,Access DOM only after component is mounted,onMounted for DOM manipulation,Direct DOM access in setup,"onMounted(() => { document.getElementById('el') })","",High,https://nuxt.com/docs/api/composables/on-mounted +19,Lifecycle,Use nextTick for post-render access,Wait for DOM updates before accessing elements,await nextTick() after state changes,Immediate DOM access after state change,"count.value++; await nextTick(); el.value.focus()","count.value++; el.value.focus()",Medium,https://nuxt.com/docs/api/utils/next-tick +20,Lifecycle,Use onPrehydrate for pre-hydration logic,Run code before Nuxt hydrates the page,onPrehydrate for client setup,onMounted for hydration-critical code,"onPrehydrate(() => { console.log(window) })",onMounted for pre-hydration needs,Low,https://nuxt.com/docs/api/composables/on-prehydrate +21,Server,Use server/api for API routes,Create API endpoints in server/api directory,server/api/users.ts for /api/users,Manual Express setup,server/api/hello.ts -> /api/hello,app.get('/api/hello'),High,https://nuxt.com/docs/guide/directory-structure/server +22,Server,Use defineEventHandler for handlers,Define server route handlers,defineEventHandler for all handlers,export default function,"export default defineEventHandler((event) => { return { hello: 'world' } })","export default function(req, res) {}",High,https://nuxt.com/docs/guide/directory-structure/server +23,Server,Use server/routes for non-api routes,Routes without /api prefix,server/routes for custom paths,server/api for non-api routes,server/routes/sitemap.xml.ts,server/api/sitemap.xml.ts,Medium,https://nuxt.com/docs/guide/directory-structure/server +24,Server,Use getQuery and readBody for input,Access query params and request body,getQuery(event) readBody(event),Direct event access,"const { id } = getQuery(event)",event.node.req.query,Medium,https://nuxt.com/docs/guide/directory-structure/server +25,Server,Validate server input,Always validate input in server handlers,Zod or similar for validation,Trust client input,"const body = await readBody(event); schema.parse(body)",const body = await readBody(event),High,https://nuxt.com/docs/guide/directory-structure/server +26,State,Use useState for shared reactive state,SSR-friendly shared state across components,useState for cross-component state,ref for shared state,"const count = useState('count', () => 0)",const count = ref(0) in composable,High,https://nuxt.com/docs/api/composables/use-state +27,State,Use unique keys for useState,Prevent state conflicts with unique keys,Descriptive unique keys for each state,Generic or duplicate keys,"useState('user-preferences', () => ({}))",useState('data') in multiple places,Medium,https://nuxt.com/docs/api/composables/use-state +28,State,Use Pinia for complex state,Pinia for advanced state management,@pinia/nuxt for complex apps,Custom state management,useMainStore() with Pinia,Custom reactive store implementation,Medium,https://nuxt.com/docs/getting-started/state-management +29,State,Use callOnce for one-time async operations,Ensure async operations run only once,callOnce for store initialization,Direct await in component,"await callOnce(store.fetch)",await store.fetch() on every render,Medium,https://nuxt.com/docs/api/utils/call-once +30,SEO,Use useSeoMeta for SEO tags,Type-safe SEO meta tag management,useSeoMeta for meta tags,useHead for simple meta,"useSeoMeta({ title: 'Home', ogTitle: 'Home', description: '...' })","useHead({ meta: [{ name: 'description', content: '...' }] })",High,https://nuxt.com/docs/api/composables/use-seo-meta +31,SEO,Use reactive values in useSeoMeta,Dynamic SEO tags with refs or getters,Computed getters for dynamic values,Static values for dynamic content,"useSeoMeta({ title: () => post.value.title })","useSeoMeta({ title: post.value.title })",Medium,https://nuxt.com/docs/api/composables/use-seo-meta +32,SEO,Use useHead for non-meta head elements,Scripts styles links in head,useHead for scripts and links,useSeoMeta for scripts,"useHead({ script: [{ src: '/analytics.js' }] })","useSeoMeta({ script: '...' })",Medium,https://nuxt.com/docs/api/composables/use-head +33,SEO,Include OpenGraph tags,Add OG tags for social sharing,ogTitle ogDescription ogImage,Missing social preview,"useSeoMeta({ ogImage: '/og.png', twitterCard: 'summary_large_image' })",No OG configuration,Medium,https://nuxt.com/docs/api/composables/use-seo-meta +34,Middleware,Use defineNuxtRouteMiddleware,Define route middleware properly,defineNuxtRouteMiddleware wrapper,export default function,"export default defineNuxtRouteMiddleware((to, from) => {})","export default function(to, from) {}",High,https://nuxt.com/docs/guide/directory-structure/middleware +35,Middleware,Use navigateTo for redirects,Redirect in middleware with navigateTo,return navigateTo('/login'),router.push in middleware,"if (!auth) return navigateTo('/login')","if (!auth) router.push('/login')",High,https://nuxt.com/docs/api/utils/navigate-to +36,Middleware,Reference middleware in definePageMeta,Apply middleware to specific pages,middleware array in definePageMeta,Global middleware for page-specific,definePageMeta({ middleware: ['auth'] }),Global auth check for one page,Medium,https://nuxt.com/docs/guide/directory-structure/middleware +37,Middleware,Use .global suffix for global middleware,Apply middleware to all routes,auth.global.ts for app-wide auth,Manual middleware on every page,middleware/auth.global.ts,middleware: ['auth'] on every page,Medium,https://nuxt.com/docs/guide/directory-structure/middleware +38,ErrorHandling,Use createError for errors,Create errors with proper status codes,createError with statusCode,throw new Error,"throw createError({ statusCode: 404, statusMessage: 'Not Found' })",throw new Error('Not Found'),High,https://nuxt.com/docs/api/utils/create-error +39,ErrorHandling,Use NuxtErrorBoundary for local errors,Handle errors within component subtree,NuxtErrorBoundary for component errors,Global error page for local errors,"