6.2 KiB
name, version, description, requires
| name | version | description | requires | |
|---|---|---|---|---|
| vue-page | 5.1.0 | 生成 Vue 3 + Vue Router 页面脚手架,含布局和加载状态。当需要新建路由页面时使用。管理端用 Element Plus,用户端用 Headless UI。 |
|
⚠️ 核心执行流程已在
.cursor/rules/skill-vue-page.mdc中由 Cursor 自动注入。 本文件提供完整模板、代码示例和边缘场景处理,供 Agent 按需深入 Read。
Vue 3 + Vue Router Page Scaffold
触发条件
用户要求创建新的页面、路由页面、带有布局的页面。
执行流程
0. 加载规范
读取 .cursor/rules/010-typescript.mdc、.cursor/rules/011-vue.mdc、019-modular.mdc,提取类型注解要求(隐式 any 禁令、ref 泛型规范、Composable 类型规范)、script setup、组件分类、拆分阈值、SFC 结构。
0.5 ⚠️ 生成前强制拆分分析(禁止跳过)
在写任何代码之前,必须先输出拆分方案。 按以下顺序检查:
A. 多视图检测
页面是否包含多个"屏"(通过 v-if / v-else-if 切换不同视图)?
判断标准:同一区域内,通过状态变量控制显示/隐藏的不同内容块,每块有独立的表单字段、UI 结构或交互逻辑。
规则:页面内存在 ≥2 个相互排斥的内容视图(无论是登录态切换、Tab 内容、步骤表单还是其他形式)→ 每个视图必须是独立组件,页面文件只做编排和视图切换逻辑。
B. 行数预估
基于需求估算各部分代码量:
| 判断标准 | 必须操作 |
|---|---|
| 整页 template 预计 > 80 行 | 识别可拆子区域,每个区域 → 独立组件 |
| script 逻辑预计 > 60 行 | 提取为 use<PageName>.ts composable(必须遵循 010-typescript.mdc Composable 类型规范) |
| 整个 SFC 预计 > 150 行 | 停止,先完成拆分方案再生成 |
C. 重复 UI 模式检测
页面中是否存在相同结构的 UI 块(如多个表单输入项、多个卡片)?
规则:同一 UI 结构出现 ≥3 次 → 必须抽取为基础组件(例:
FormInput.vue、CaseCard.vue)
D. 输出拆分方案(必须在代码前输出)
格式:
src/views/<module>/<page>/
├── index.vue ← 编排层,仅做布局编排和视图切换,目标 ≤ 60 行
├── components/
│ ├── <ViewA>.vue ← 视图A(≤ 120 行)
│ ├── <ViewB>.vue ← 视图B(≤ 120 行)
│ └── <SharedWidget>.vue ← 共享 UI 组件(≤ 80 行)
└── composables/
└── use<PageName>.ts ← 所有表单状态和提交逻辑(≤ 80 行,参数必须有类型注解,ref 必须有泛型)
用户确认或 AI 自主判断方案合理后,才开始逐文件生成。
1. 确认页面规格
| 字段 | 必填 | 默认值 |
|---|---|---|
| 路由路径 | ✅ | — |
| 页面标题 | ✅ | — |
| 所属模块 | ✅ | — |
| 需要数据获取? | ❌ | true |
| 需要独立 Layout? | ❌ | false |
| 是动态路由? | ❌ | false |
| 需要权限? | ❌ | true |
| 页面类型 | ❌ | list |
类型:list | detail | form | dashboard | blank | multi-view(新增)。
2. 生成文件结构
按步骤 0.5 输出的拆分方案生成,所有文件逐一输出,不合并到一个文件。
入口:src/views/<module>/<page-name>/index.vue,路由:src/router/routes/<module>.ts。
3. 页面模板
index.vue 编排层职责(强制):
- 只负责:整体布局骨架 + 子组件引用 + 视图切换逻辑
- 禁止在 index.vue 内写具体表单字段、业务 UI 细节
管理端列表页:useTable、搜索栏、el-table、el-pagination。详情页:fetchDetail、el-skeleton、el-descriptions。 用户端列表页:useTable、搜索栏、自定义 Tailwind 卡片。详情页:fetchDetail、骨架屏、自定义描述区(禁止 Element Plus)。 完整模板见 Tier 3。
4. 路由配置
path、name、component 懒加载、meta(title、requiresAuth、permission、icon)。
4.5 Pinia Store 设计
ListItem(轻量)与 Detail(完整)分离。detailMap 缓存已加载详情。fetchDetail 有缓存则直接返回。完整 Store 结构见 Tier 3。
4.6 Provider 模式
页面内 ≥3 个子组件共享状态时:Provider + keys + 子组件 inject。简单页面直接模板即可。完整实现见 Tier 3。
5. 动态路由 (RBAC)
menuStore.fetchMenus() → router.addRoute。
验证
- 页面可正常渲染
- document.title 正确
- Loading 骨架屏
- 错误提示友好
- meta.requiresAuth、meta.permission
- 动态路由参数验证
- ESLint 无报错
- index.vue ≤ 60 行(编排层)
- 无子组件超过 150 行
- 多视图已拆分为独立组件(若适用)
- 重复 UI 结构已抽取为基础组件(≥3 次重复时)
- 提取的 composable(use.ts)参数有类型注解、
ref([])/ref(null)有泛型标注*(参见010-typescript.mdcComposable 类型规范)
Red Flags(触发则必须停止并重构)
- ❌ 未输出拆分方案直接写代码 → 停止,先输出步骤 0.5 的方案
- ❌ index.vue > 60 行(含 template + script) → 拆分子组件
- ❌ 任意 SFC > 150 行 → 拆分
- ❌ 多视图(≥2 个 v-if 屏)写在同一文件 → 每个视图独立组件
- ❌ 同一 UI 结构重复 ≥3 次 → 抽取为基础组件
- ❌ Options API → script setup
- ❌ 直接修改 props → emit
- ❌ watch deep:true 滥用
- ❌ ≥3 子组件 prop drilling → Provider
- ❌ 列表返回详情级重型字段 → 分离 ListItem/Detail
- ❌ 详情每次都请求 → detailMap 缓存
- ❌ composable 参数无类型 /
ref([])无泛型 → 补全类型注解(strict: true下必报错)
Tier 3 深度参考
| 文件 | 内容 |
|---|---|
references/page-templates.md |
列表/详情/路由/Pinia/Provider 完整模板 |
.cursor/skills/component-scaffold/references/naming-conventions.md |
页面命名规范 |
.cursor/skills/component-scaffold/references/vue-api-reference.md |
Vue 3 API 索引 |