pandax 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -0
- package/bin/pandax.js +592 -0
- package/package.json +33 -0
- package/skills/pandax-frontend-api-mock/SKILL.md +62 -0
- package/skills/pandax-frontend-architecture/SKILL.md +1239 -0
- package/skills/pandax-frontend-component-review/SKILL.md +114 -0
- package/skills/pandax-frontend-requirement/SKILL.md +142 -0
- package/skills/pandax-frontend-standards/SKILL.md +468 -0
- package/skills/pandax-frontend-use-modal/SKILL.md +621 -0
- package/templates/pandax-monorepo/.editorconfig +16 -0
- package/templates/pandax-monorepo/.husky/commit-msg +2 -0
- package/templates/pandax-monorepo/.husky/pre-commit +2 -0
- package/templates/pandax-monorepo/.prettierrc.json +28 -0
- package/templates/pandax-monorepo/apps/base/env.d.ts +1 -0
- package/templates/pandax-monorepo/apps/base/index.html +13 -0
- package/templates/pandax-monorepo/apps/base/package.json +30 -0
- package/templates/pandax-monorepo/apps/base/src/App.vue +15 -0
- package/templates/pandax-monorepo/apps/base/src/layouts/default-layout/index.vue +23 -0
- package/templates/pandax-monorepo/apps/base/src/main.ts +31 -0
- package/templates/pandax-monorepo/apps/base/src/router/index.ts +22 -0
- package/templates/pandax-monorepo/apps/base/src/stores/index.ts +15 -0
- package/templates/pandax-monorepo/apps/base/src/styles/global.scss +19 -0
- package/templates/pandax-monorepo/apps/base/src/styles/variables.scss +4 -0
- package/templates/pandax-monorepo/apps/base/src/types/wujie.d.ts +16 -0
- package/templates/pandax-monorepo/apps/base/src/views/home/index.vue +21 -0
- package/templates/pandax-monorepo/apps/base/tsconfig.json +25 -0
- package/templates/pandax-monorepo/apps/base/tsconfig.node.json +11 -0
- package/templates/pandax-monorepo/apps/base/vite.config.ts +26 -0
- package/templates/pandax-monorepo/apps/main/env.d.ts +1 -0
- package/templates/pandax-monorepo/apps/main/index.html +13 -0
- package/templates/pandax-monorepo/apps/main/package.json +32 -0
- package/templates/pandax-monorepo/apps/main/src/App.vue +15 -0
- package/templates/pandax-monorepo/apps/main/src/layouts/MicroApp.vue +29 -0
- package/templates/pandax-monorepo/apps/main/src/layouts/default-layout/index.vue +48 -0
- package/templates/pandax-monorepo/apps/main/src/main.ts +27 -0
- package/templates/pandax-monorepo/apps/main/src/router/index.ts +22 -0
- package/templates/pandax-monorepo/apps/main/src/stores/index.ts +23 -0
- package/templates/pandax-monorepo/apps/main/src/styles/global.scss +23 -0
- package/templates/pandax-monorepo/apps/main/src/styles/variables.scss +8 -0
- package/templates/pandax-monorepo/apps/main/src/views/home/index.vue +25 -0
- package/templates/pandax-monorepo/apps/main/tsconfig.json +25 -0
- package/templates/pandax-monorepo/apps/main/tsconfig.node.json +11 -0
- package/templates/pandax-monorepo/apps/main/vite.config.ts +24 -0
- package/templates/pandax-monorepo/commitlint.config.js +38 -0
- package/templates/pandax-monorepo/eslint.config.js +61 -0
- package/templates/pandax-monorepo/package.json +50 -0
- package/templates/pandax-monorepo/packages/components/package.json +20 -0
- package/templates/pandax-monorepo/packages/components/src/PandaButton.vue +15 -0
- package/templates/pandax-monorepo/packages/components/src/PandaCard.vue +16 -0
- package/templates/pandax-monorepo/packages/components/src/index.ts +2 -0
- package/templates/pandax-monorepo/packages/core/package.json +20 -0
- package/templates/pandax-monorepo/packages/core/src/index.ts +2 -0
- package/templates/pandax-monorepo/packages/core/src/request.ts +24 -0
- package/templates/pandax-monorepo/packages/core/src/utils.ts +7 -0
- package/templates/pandax-monorepo/packages/hooks/package.json +19 -0
- package/templates/pandax-monorepo/packages/hooks/src/index.ts +2 -0
- package/templates/pandax-monorepo/packages/hooks/src/useCounter.ts +27 -0
- package/templates/pandax-monorepo/packages/hooks/src/useToggle.ts +19 -0
- package/templates/pandax-monorepo/packages/styles/package.json +19 -0
- package/templates/pandax-monorepo/packages/styles/src/index.ts +1 -0
- package/templates/pandax-monorepo/packages/styles/src/uno.ts +19 -0
- package/templates/pandax-monorepo/packages/styles/src/variables.scss +14 -0
- package/templates/pandax-monorepo/pnpm-workspace.yaml +32 -0
- package/templates/pandax-monorepo/turbo.json +23 -0
- package/templates/vue3/.eslintrc.cjs +16 -0
- package/templates/vue3/.prettierrc +7 -0
- package/templates/vue3/env.d.ts +1 -0
- package/templates/vue3/index.html +13 -0
- package/templates/vue3/package.json +34 -0
- package/templates/vue3/src/App.vue +14 -0
- package/templates/vue3/src/api/index.ts +27 -0
- package/templates/vue3/src/assets/.gitkeep +1 -0
- package/templates/vue3/src/components/.gitkeep +1 -0
- package/templates/vue3/src/composables/.gitkeep +1 -0
- package/templates/vue3/src/constants/.gitkeep +1 -0
- package/templates/vue3/src/directives/.gitkeep +1 -0
- package/templates/vue3/src/layouts/default-layout/index.vue +33 -0
- package/templates/vue3/src/locales/.gitkeep +1 -0
- package/templates/vue3/src/main.ts +17 -0
- package/templates/vue3/src/router/index.ts +17 -0
- package/templates/vue3/src/services/.gitkeep +1 -0
- package/templates/vue3/src/stores/index.ts +12 -0
- package/templates/vue3/src/styles/global.scss +18 -0
- package/templates/vue3/src/styles/variables.scss +17 -0
- package/templates/vue3/src/types/global.d.ts +9 -0
- package/templates/vue3/src/utils/format.ts +11 -0
- package/templates/vue3/src/views/home/index.vue +19 -0
- package/templates/vue3/tsconfig.json +25 -0
- package/templates/vue3/tsconfig.node.json +10 -0
- package/templates/vue3/vite.config.ts +20 -0
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "pandax-frontend-standards"
|
|
3
|
+
category: "frontend"
|
|
4
|
+
description: "统一引用前端规范文档。Invoke when 前端开发涉及命名、目录结构、组件设计、API、Git、文案等规范问题,或需要先读取团队规范再执行任务。"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Pandax 前端规范总览
|
|
8
|
+
|
|
9
|
+
本 skill 是 Pandax 前端规范的统一入口。当前端任务涉及命名、目录、组件、API、Git、文案等规范问题时,先读取本 skill 明确的规范文档位置,再按规范执行。
|
|
10
|
+
|
|
11
|
+
## 触发条件
|
|
12
|
+
|
|
13
|
+
- 用户提到"按规范"、"符合规范"、"规范怎么定"
|
|
14
|
+
- 开发前需要确认命名规则、目录结构、组件设计方式
|
|
15
|
+
- 代码审查时发现风格不一致,需要引用规范
|
|
16
|
+
- 新成员加入,需要了解前端项目约定
|
|
17
|
+
- 其他 Pandax skill(如 component-review、api-mock)执行时需要引用规范
|
|
18
|
+
|
|
19
|
+
## 规范文档位置
|
|
20
|
+
|
|
21
|
+
项目内统一放在 `docs/standards/` 目录下:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
docs/standards/
|
|
25
|
+
├── README.md # 规范总览和索引
|
|
26
|
+
├── code-style.md # 代码风格与命名规范
|
|
27
|
+
├── component.md # 组件规范
|
|
28
|
+
├── api.md # API 对接规范
|
|
29
|
+
├── git-workflow.md # Git 工作流规范
|
|
30
|
+
└── copywriting.md # 中文文案排版规范
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
如果项目中不存在 `docs/standards/`,则先询问用户规范文档存放在哪里,或按本 skill 的默认约定创建。
|
|
34
|
+
|
|
35
|
+
## 规范条目速查
|
|
36
|
+
|
|
37
|
+
### 1. 目录结构
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
src/
|
|
41
|
+
├── apis/ # API 请求封装与接口定义
|
|
42
|
+
├── assets/ # 静态资源(图片、字体、图标)
|
|
43
|
+
├── components/ # 通用业务组件
|
|
44
|
+
│ └── button/
|
|
45
|
+
│ ├── index.ts
|
|
46
|
+
│ ├── index.vue
|
|
47
|
+
│ └── index.spec.ts
|
|
48
|
+
├── composables/ # Vue 组合式函数(推荐)
|
|
49
|
+
│ └── use-modal/
|
|
50
|
+
│ ├── index.ts
|
|
51
|
+
│ ├── Types.ts
|
|
52
|
+
│ └── Config.ts
|
|
53
|
+
├── hooks/ # React Hooks 或 Vue 组合式函数(项目统一即可)
|
|
54
|
+
├── directives/ # 自定义指令
|
|
55
|
+
├── layouts/ # 页面布局组件
|
|
56
|
+
├── router/ # 路由配置
|
|
57
|
+
├── stores/ # 状态管理
|
|
58
|
+
├── styles/ # 全局样式、变量、mixins
|
|
59
|
+
├── types/ # 全局类型定义
|
|
60
|
+
├── utils/ # 工具函数
|
|
61
|
+
└── views/ # 页面级组件
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 2. 文件与命名规范
|
|
65
|
+
|
|
66
|
+
**总原则:** `src/` 目录下,**所有目录名统一使用全小写**(多词用短横线连接);**入口文件 `index.*` 使用全小写**;**其他所有文件统一使用 PascalCase**。
|
|
67
|
+
|
|
68
|
+
| 类型 | 命名方式 | 示例 |
|
|
69
|
+
|------|---------|------|
|
|
70
|
+
| Vue 单文件组件 | 全小写 | `components/user-profile/index.vue` |
|
|
71
|
+
| 组件目录 | 全小写 + 短横线 | `components/user-profile/` |
|
|
72
|
+
| 组件入口文件 | `index.ts` | `components/user-profile/index.ts` |
|
|
73
|
+
| 工具函数文件 | PascalCase | `utils/DateUtil.ts` |
|
|
74
|
+
| 常量文件 | PascalCase | `constants/ApiTimeout.ts` |
|
|
75
|
+
| TypeScript 接口 | PascalCase | `types/UserInfo.ts` |
|
|
76
|
+
| TypeScript 类型别名 | PascalCase | `types/FetchStatus.ts` |
|
|
77
|
+
| 枚举 | PascalCase,成员 UPPER_SNAKE_CASE | `constants/StatusCode.ts` |
|
|
78
|
+
| 测试文件 | 与被测文件同名 + `.spec.ts` | `components/user-profile/index.spec.ts` |
|
|
79
|
+
|
|
80
|
+
#### 特殊目录后缀约定
|
|
81
|
+
|
|
82
|
+
以下目录中的文件(除 `index.*` 外)必须按职责追加统一后缀:
|
|
83
|
+
|
|
84
|
+
| 目录 | 文件命名后缀 | 示例 |
|
|
85
|
+
|------|-------------|------|
|
|
86
|
+
| `src/apis/` | `Api` | `UserApi.ts`、`OrderApi.ts` |
|
|
87
|
+
| `src/services/` | `Service` | `UserService.ts`、`OrderService.ts` |
|
|
88
|
+
| `src/utils/` | `Util` | `DateUtil.ts`、`StorageUtil.ts` |
|
|
89
|
+
|
|
90
|
+
**注意:** 这些目录内的 `index.ts` 仍保持小写,用于统一导出。导出时也不得省略统一后缀,如 `export { UserApi } from './UserApi'`。
|
|
91
|
+
|
|
92
|
+
### 3. 组件规范
|
|
93
|
+
|
|
94
|
+
#### 通用原则
|
|
95
|
+
|
|
96
|
+
- 单一组件文件行数不宜超过 300 行
|
|
97
|
+
- Props 必须声明类型;可选 Props 设置默认值,必填 Props 不设置默认值
|
|
98
|
+
- boolean 类型 props 命名应为形容词,如 `disabled`、`visible`
|
|
99
|
+
- 事件名使用 `onXxx` 或 `xxxChange`
|
|
100
|
+
- Vue 单文件组件使用 `scoped` 或 CSS Modules
|
|
101
|
+
- React 优先使用 CSS Modules / styled-components
|
|
102
|
+
|
|
103
|
+
#### Vue3 组件结构
|
|
104
|
+
|
|
105
|
+
Vue3 组件目录采用**全小写 + 短横线**命名,组件内部文件统一如下:
|
|
106
|
+
|
|
107
|
+
```text
|
|
108
|
+
app-register/ # 组件目录:全小写 + 短横线
|
|
109
|
+
├── index.vue # 组件默认入口
|
|
110
|
+
├── Prop.ts # Props 定义
|
|
111
|
+
├── Type.ts # 组件相关 TypeScript 类型定义
|
|
112
|
+
└── index.module.scss # 组件样式(CSS Modules)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
子组件同样遵循该结构,放在当前组件的 `components/` 目录下:
|
|
116
|
+
|
|
117
|
+
```text
|
|
118
|
+
app-register/
|
|
119
|
+
├── index.vue
|
|
120
|
+
├── Prop.ts
|
|
121
|
+
├── Type.ts
|
|
122
|
+
├── index.module.scss
|
|
123
|
+
└── components/ # 当前组件的私有子组件
|
|
124
|
+
├── sub-title/ # 子组件目录:全小写 + 短横线
|
|
125
|
+
│ ├── index.vue
|
|
126
|
+
│ ├── Prop.ts
|
|
127
|
+
│ ├── Type.ts
|
|
128
|
+
│ └── index.module.scss
|
|
129
|
+
└── info-card/
|
|
130
|
+
├── index.vue
|
|
131
|
+
├── Prop.ts
|
|
132
|
+
├── Type.ts
|
|
133
|
+
└── index.module.scss
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**原子化原则**:
|
|
137
|
+
|
|
138
|
+
- 组件应尽可能原子化,一个组件只做一件事
|
|
139
|
+
- 如果组件内部出现可复用的 UI 片段,应拆分为 `components/` 下的子组件
|
|
140
|
+
- 子组件的拆分深度不超过 3 层,避免过度嵌套
|
|
141
|
+
- 每个子组件同样遵循 `index.vue + Prop.ts + Type.ts + index.module.scss` 结构
|
|
142
|
+
|
|
143
|
+
#### Vue3 组件代码组织
|
|
144
|
+
|
|
145
|
+
必须使用 `<script setup lang="ts">` 语法。
|
|
146
|
+
|
|
147
|
+
`index.vue` 内部按以下顺序和 `// #region` 注释块组织代码。即使某个区域暂时没有逻辑,也必须保留该区域注释和一句话说明,方便后续维护。
|
|
148
|
+
|
|
149
|
+
```vue
|
|
150
|
+
<script setup lang="ts">
|
|
151
|
+
import { ref, computed, watch, onMounted } from 'vue';
|
|
152
|
+
import { props } from './Prop';
|
|
153
|
+
import type { FormState } from './Type';
|
|
154
|
+
|
|
155
|
+
// #region Props - 组件属性定义
|
|
156
|
+
// #endregion
|
|
157
|
+
|
|
158
|
+
// #region Types - 组件内部类型
|
|
159
|
+
// #endregion
|
|
160
|
+
|
|
161
|
+
// #region State - 响应式数据
|
|
162
|
+
const count = ref(0);
|
|
163
|
+
const form = reactive<FormState>({ name: '' });
|
|
164
|
+
// #endregion
|
|
165
|
+
|
|
166
|
+
// #region Computed - 计算属性
|
|
167
|
+
const doubleCount = computed(() => count.value * 2);
|
|
168
|
+
// #endregion
|
|
169
|
+
|
|
170
|
+
// #region Watch - 监听器
|
|
171
|
+
watch(count, (newVal) => {
|
|
172
|
+
console.log(newVal);
|
|
173
|
+
});
|
|
174
|
+
// #endregion
|
|
175
|
+
|
|
176
|
+
// #region Lifecycle - onBeforeMount
|
|
177
|
+
// 在挂载开始之前调用:适合获取初始数据前的准备工作
|
|
178
|
+
// 当前组件未使用
|
|
179
|
+
// #endregion
|
|
180
|
+
|
|
181
|
+
// #region Lifecycle - onMounted
|
|
182
|
+
// 组件挂载完成后调用:适合发起请求、操作 DOM、订阅事件
|
|
183
|
+
// onMounted(() => { fetchData() })
|
|
184
|
+
// #endregion
|
|
185
|
+
|
|
186
|
+
// #region Lifecycle - onBeforeUpdate
|
|
187
|
+
// 组件更新前调用:适合获取更新前的 DOM 状态
|
|
188
|
+
// 当前组件未使用
|
|
189
|
+
// #endregion
|
|
190
|
+
|
|
191
|
+
// #region Lifecycle - onUpdated
|
|
192
|
+
// 组件更新后调用:适合操作更新后的 DOM
|
|
193
|
+
// 当前组件未使用
|
|
194
|
+
// #endregion
|
|
195
|
+
|
|
196
|
+
// #region Lifecycle - onBeforeUnmount
|
|
197
|
+
// 组件卸载前调用:适合移除事件监听、清理定时器
|
|
198
|
+
// 当前组件未使用
|
|
199
|
+
// #endregion
|
|
200
|
+
|
|
201
|
+
// #region Lifecycle - onUnmounted
|
|
202
|
+
// 组件卸载后调用:适合彻底清理副作用
|
|
203
|
+
// 当前组件未使用
|
|
204
|
+
// #endregion
|
|
205
|
+
|
|
206
|
+
// #region Methods - 组件内部方法
|
|
207
|
+
const increment = () => {
|
|
208
|
+
count.value++;
|
|
209
|
+
};
|
|
210
|
+
// #endregion
|
|
211
|
+
|
|
212
|
+
// #region Expose - 对外暴露
|
|
213
|
+
// defineExpose({ increment });
|
|
214
|
+
// #endregion
|
|
215
|
+
</script>
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**代码组织约定**:
|
|
219
|
+
|
|
220
|
+
- `import` 语句统一放在 `<script setup>` 最顶部,不需要包 region
|
|
221
|
+
- 从 `Props` 开始,每个区域用 `// #region` / `// #endregion` 包裹
|
|
222
|
+
|
|
223
|
+
**Region 顺序**:
|
|
224
|
+
|
|
225
|
+
1. `Props` - 属性定义
|
|
226
|
+
2. `Types` - 内部类型
|
|
227
|
+
3. `State` - 响应式数据
|
|
228
|
+
4. `Computed` - 计算属性
|
|
229
|
+
5. `Watch` - 监听器
|
|
230
|
+
6. `Lifecycle` - 生命周期钩子(按执行顺序)
|
|
231
|
+
7. `Methods` - 组件方法
|
|
232
|
+
8. `Expose` - 对外暴露
|
|
233
|
+
|
|
234
|
+
**生命周期占位规则**:
|
|
235
|
+
|
|
236
|
+
- 即使当前组件没有对应逻辑,也必须保留生命周期 region
|
|
237
|
+
- 未使用的生命周期:写一句话用途说明 + `// 当前组件未使用` 占位
|
|
238
|
+
- 已使用的生命周期:写一句话用途说明 + 一行注释示例(可选)
|
|
239
|
+
- 禁止写空函数调用,如 `onBeforeMount(() => {})`
|
|
240
|
+
|
|
241
|
+
这有助于:
|
|
242
|
+
|
|
243
|
+
- 统一代码结构,降低阅读成本
|
|
244
|
+
- 提示开发者未来可以在哪个阶段添加逻辑
|
|
245
|
+
- 便于代码审查时快速定位生命周期使用
|
|
246
|
+
|
|
247
|
+
### 4. 页面规范(views)
|
|
248
|
+
|
|
249
|
+
#### 目录结构
|
|
250
|
+
|
|
251
|
+
`src/views/` 下按业务模块组织页面,页面目录采用**全小写 + 短横线**命名:
|
|
252
|
+
|
|
253
|
+
```text
|
|
254
|
+
src/views/
|
|
255
|
+
├── user-management/ # 用户管理模块
|
|
256
|
+
│ ├── index.vue # 列表页(默认入口)
|
|
257
|
+
│ ├── Prop.ts # 页面级 props(如有)
|
|
258
|
+
│ ├── Type.ts # 页面相关类型
|
|
259
|
+
│ ├── index.module.scss # 页面样式
|
|
260
|
+
│ ├── components/ # 本页面私有组件
|
|
261
|
+
│ │ ├── user-form/
|
|
262
|
+
│ │ │ ├── index.vue
|
|
263
|
+
│ │ │ ├── Prop.ts
|
|
264
|
+
│ │ │ ├── Type.ts
|
|
265
|
+
│ │ │ └── index.module.scss
|
|
266
|
+
│ │ └── user-filter/
|
|
267
|
+
│ │ ├── index.vue
|
|
268
|
+
│ │ ├── Prop.ts
|
|
269
|
+
│ │ ├── Type.ts
|
|
270
|
+
│ │ └── index.module.scss
|
|
271
|
+
│ └── pages/ # 用户管理下的子页面
|
|
272
|
+
│ ├── create/ # 新建用户页
|
|
273
|
+
│ │ └── index.vue
|
|
274
|
+
│ ├── detail/ # 用户详情页
|
|
275
|
+
│ │ └── index.vue
|
|
276
|
+
│ └── edit/ # 编辑用户页
|
|
277
|
+
│ └── index.vue
|
|
278
|
+
└── order-management/
|
|
279
|
+
├── index.vue
|
|
280
|
+
├── components/
|
|
281
|
+
└── pages/
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
#### 子页面命名规则
|
|
285
|
+
|
|
286
|
+
| 位置 | 推荐命名 | 说明 |
|
|
287
|
+
|------|---------|------|
|
|
288
|
+
| `views/{module}/pages/` 下 | 简短动词 | 如 `create/`、`edit/`、`detail/`,上下文已明确 |
|
|
289
|
+
| `views/` 顶层 | 完整语义 | 如 `user-create/`、`order-detail/`,避免歧义 |
|
|
290
|
+
|
|
291
|
+
#### 新增/编辑复用规则
|
|
292
|
+
|
|
293
|
+
新增和编辑页面 UI 相似时,**合并为同一个表单页**,目录名用 `form/`:
|
|
294
|
+
|
|
295
|
+
```text
|
|
296
|
+
user-management/
|
|
297
|
+
├── index.vue
|
|
298
|
+
└── pages/
|
|
299
|
+
└── form/ # 新增/编辑共用页
|
|
300
|
+
├── index.vue
|
|
301
|
+
├── Prop.ts
|
|
302
|
+
├── Type.ts
|
|
303
|
+
└── index.module.scss
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
路由配置:
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
{
|
|
310
|
+
path: '/user-management',
|
|
311
|
+
component: () => import('@/views/user-management/index.vue'),
|
|
312
|
+
children: [
|
|
313
|
+
{ path: 'create', component: () => import('@/views/user-management/pages/form/index.vue') },
|
|
314
|
+
{ path: 'edit/:id', component: () => import('@/views/user-management/pages/form/index.vue') },
|
|
315
|
+
],
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
页面内部通过路由参数判断模式:
|
|
320
|
+
|
|
321
|
+
```ts
|
|
322
|
+
// #region State - 响应式数据
|
|
323
|
+
const route = useRoute();
|
|
324
|
+
const id = computed(() => route.params.id as string | undefined);
|
|
325
|
+
const isEdit = computed(() => !!id.value);
|
|
326
|
+
// #endregion
|
|
327
|
+
|
|
328
|
+
// #region Lifecycle - onMounted
|
|
329
|
+
// 编辑模式时查询详情并回显
|
|
330
|
+
// onMounted(() => { if (isEdit.value) fetchDetail(id.value) })
|
|
331
|
+
// #endregion
|
|
332
|
+
|
|
333
|
+
// #region Methods - 组件内部方法
|
|
334
|
+
// const submit = async (values) => {
|
|
335
|
+
// if (isEdit.value) await updateUser({ ...values, id: id.value })
|
|
336
|
+
// else await createUser(values)
|
|
337
|
+
// }
|
|
338
|
+
// #endregion
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
#### 拆分原则
|
|
342
|
+
|
|
343
|
+
满足以下任一条件时,才将新增和编辑拆分为两个独立页面:
|
|
344
|
+
|
|
345
|
+
- 新增和编辑的 UI 差异超过 50%
|
|
346
|
+
- 编辑页需要额外的大量权限控制或状态管理
|
|
347
|
+
- 新增和编辑的表单字段差异很大
|
|
348
|
+
|
|
349
|
+
否则一律合并为 `pages/form/`。
|
|
350
|
+
|
|
351
|
+
#### 新增/编辑容器选择规则
|
|
352
|
+
|
|
353
|
+
列表页中的新增/编辑操作,按以下优先级选择容器:
|
|
354
|
+
|
|
355
|
+
1. **用户明确指定**:用户说用独立页面/弹窗/抽屉,就按用户要求
|
|
356
|
+
2. **默认使用抽屉(Drawer)**:用户未指定时,默认用抽屉
|
|
357
|
+
3. **独立页面**:需要独立路由、可被外部直接访问、或用户明确要求页面时
|
|
358
|
+
4. **弹窗(Modal)**:用户明确要求弹窗时
|
|
359
|
+
|
|
360
|
+
**目录结构对应关系**:
|
|
361
|
+
|
|
362
|
+
| 容器类型 | 组件位置 | 路由 |
|
|
363
|
+
|---------|---------|------|
|
|
364
|
+
| 独立页面 | `views/user-management/pages/form/` | 有独立路由 |
|
|
365
|
+
| 抽屉 | `views/user-management/components/user-form-drawer/` | 无独立路由 |
|
|
366
|
+
| 弹窗 | `views/user-management/components/user-form-modal/` | 无独立路由 |
|
|
367
|
+
|
|
368
|
+
**抽屉/弹窗组件拆分**:
|
|
369
|
+
|
|
370
|
+
如果新增/编辑共用同一个表单,建议拆成容器 + 表单两层:
|
|
371
|
+
|
|
372
|
+
```text
|
|
373
|
+
user-management/
|
|
374
|
+
├── components/
|
|
375
|
+
│ ├── user-form-drawer/ # 抽屉容器(负责显隐、标题、底部按钮)
|
|
376
|
+
│ │ ├── index.vue
|
|
377
|
+
│ │ ├── Prop.ts
|
|
378
|
+
│ │ ├── Type.ts
|
|
379
|
+
│ │ └── index.module.scss
|
|
380
|
+
│ └── user-form/ # 纯表单组件(业务字段、校验逻辑)
|
|
381
|
+
│ ├── index.vue
|
|
382
|
+
│ ├── Prop.ts
|
|
383
|
+
│ ├── Type.ts
|
|
384
|
+
│ └── index.module.scss
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
- `user-form-drawer`:负责 `visible`、标题、提交/取消按钮
|
|
388
|
+
- `user-form`:负责表单字段、校验、收集数据
|
|
389
|
+
|
|
390
|
+
如果不需要复用,也可以直接把表单写在抽屉组件内。
|
|
391
|
+
|
|
392
|
+
**调用示例**:
|
|
393
|
+
|
|
394
|
+
```ts
|
|
395
|
+
// #region State - 响应式数据
|
|
396
|
+
const drawerVisible = ref(false);
|
|
397
|
+
const editingId = ref<string | undefined>(undefined);
|
|
398
|
+
const isEdit = computed(() => !!editingId.value);
|
|
399
|
+
// #endregion
|
|
400
|
+
|
|
401
|
+
// #region Methods - 组件内部方法
|
|
402
|
+
const openCreateDrawer = () => {
|
|
403
|
+
editingId.value = undefined;
|
|
404
|
+
drawerVisible.value = true;
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
const openEditDrawer = (id: string) => {
|
|
408
|
+
editingId.value = id;
|
|
409
|
+
drawerVisible.value = true;
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
const handleSubmit = async (values: UserFormData) => {
|
|
413
|
+
if (isEdit.value) {
|
|
414
|
+
await updateUser({ ...values, id: editingId.value });
|
|
415
|
+
} else {
|
|
416
|
+
await createUser(values);
|
|
417
|
+
}
|
|
418
|
+
drawerVisible.value = false;
|
|
419
|
+
};
|
|
420
|
+
// #endregion
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### 5. API 规范
|
|
424
|
+
|
|
425
|
+
- 所有请求必须通过统一的请求客户端
|
|
426
|
+
- 按业务模块划分 API 文件,如 `apis/UserApi.ts`
|
|
427
|
+
- 函数名使用 `动词 + 名词`,如 `getUserList`
|
|
428
|
+
- 请求参数与响应数据必须定义 TypeScript 接口
|
|
429
|
+
- Mock 数据与真实响应结构保持一致
|
|
430
|
+
|
|
431
|
+
### 6. Git 规范
|
|
432
|
+
|
|
433
|
+
- 分支命名:
|
|
434
|
+
- 功能分支:`feature/xxx`
|
|
435
|
+
- 修复分支:`fix/xxx`
|
|
436
|
+
- 热修复分支:`hotfix/xxx`
|
|
437
|
+
- Commit message 使用 Conventional Commits
|
|
438
|
+
- `feat:` 新功能
|
|
439
|
+
- `fix:` 修复
|
|
440
|
+
- `docs:` 文档
|
|
441
|
+
- `style:` 格式调整
|
|
442
|
+
- `refactor:` 重构
|
|
443
|
+
- `test:` 测试
|
|
444
|
+
- `chore:` 构建/工具
|
|
445
|
+
|
|
446
|
+
### 7. 文案规范
|
|
447
|
+
|
|
448
|
+
- 中英文之间加空格
|
|
449
|
+
- 中文与数字之间加空格
|
|
450
|
+
- 中文标点使用全角
|
|
451
|
+
- 界面文案避免机器翻译腔
|
|
452
|
+
- 按钮使用具体动作,如"保存"、"确认删除"
|
|
453
|
+
|
|
454
|
+
## 执行规则
|
|
455
|
+
|
|
456
|
+
1. 当任务涉及规范问题时,先读取 `docs/standards/README.md`
|
|
457
|
+
2. 根据具体场景读取对应规范文件:
|
|
458
|
+
- 命名 / 代码风格 → `code-style.md`
|
|
459
|
+
- 组件设计 → `component.md`
|
|
460
|
+
- API 对接 → `api.md`
|
|
461
|
+
- Git 提交 → `git-workflow.md`
|
|
462
|
+
- 中文文案 → `copywriting.md`
|
|
463
|
+
3. 如果规范文件不存在,向用户说明缺少的文档,并建议使用本 skill 的默认约定
|
|
464
|
+
4. 执行任务时严格遵循已读取的规范
|
|
465
|
+
|
|
466
|
+
## 输出要求
|
|
467
|
+
|
|
468
|
+
引用规范执行任务后,简要说明依据了哪条规范,方便用户理解和复核。
|