@qilitt-mickey/vue3-temp-skill 1.0.8
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 +229 -0
- package/SKILL.md +621 -0
- package/bin/cli.js +579 -0
- package/package.json +46 -0
- package/references/advanced-ui.md +302 -0
- package/references/api-check.md +272 -0
- package/references/base-code-dict.md +48 -0
- package/references/build-optim.md +282 -0
- package/references/code-quality.md +235 -0
- package/references/crud-pages.md +316 -0
- package/references/data-compare.md +501 -0
- package/references/data-mapping.md +213 -0
- package/references/data-screen.md +79 -0
- package/references/data-writeback.md +104 -0
- package/references/detail-page.md +99 -0
- package/references/directives-advanced.md +93 -0
- package/references/download-export.md +68 -0
- package/references/feedback-loading.md +60 -0
- package/references/feedback-ui.md +111 -0
- package/references/file-management.md +132 -0
- package/references/flowchart-g6.md +244 -0
- package/references/form-advanced.md +137 -0
- package/references/graph-relation.md +253 -0
- package/references/http-api.md +188 -0
- package/references/layout-theme.md +540 -0
- package/references/mobile-h5.md +271 -0
- package/references/permission-auth.md +235 -0
- package/references/project-inventory.md +326 -0
- package/references/qrcode-barcode.md +92 -0
- package/references/rich-text.md +73 -0
- package/references/seamless-scroll.md +38 -0
- package/references/tree-table.md +111 -0
- package/references/ui-components.md +161 -0
- package/references/verify-captcha.md +96 -0
- package/references/vue-core.md +209 -0
- package/references/websocket-realtime.md +176 -0
- package/references/workflow-bpmn.md +206 -0
package/SKILL.md
ADDED
|
@@ -0,0 +1,621 @@
|
|
|
1
|
+
---
|
|
2
|
+
skill: vue3-temp-skill
|
|
3
|
+
description: Vue 3 企业级中后台项目开发规范技能包。用户通过 /vue3-temp-skill 命令描述需求,AI 自动匹配对应规范模块生成代码,并在生成后自动执行代码质量审查。
|
|
4
|
+
scope: project
|
|
5
|
+
tags: [vue3, typescript, element-plus, vant, pinia, vite, unocss, crud, component, api, permission, mobile, code-review, compare]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Vue 3 项目开发规范技能包
|
|
9
|
+
|
|
10
|
+
> 用户通过 `/vue3-temp-skill` + 自然语言描述需求,AI 应当:
|
|
11
|
+
> 1. 分析需求,自动匹配下方模块路由表中的对应模块
|
|
12
|
+
> 2. 加载匹配到的模块详细规范(`references/` 目录)
|
|
13
|
+
> 3. 严格按照规范生成代码
|
|
14
|
+
> 4. 生成完毕后,**必须自动执行代码质量审查**(见底部审查清单)
|
|
15
|
+
> 5. 如发现问题,直接修正后输出最终代码
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 使用方式
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
/vue3-temp-skill <用户的自然语言需求描述>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
示例:
|
|
26
|
+
- `/vue3-temp-skill 帮我开发一个客户管理模块,需要按客户名称、状态查询,字段包括客户编号、名称、联系方式、创建时间`
|
|
27
|
+
- `/vue3-temp-skill 封装一个部门选择器组件,支持远程搜索和分页`
|
|
28
|
+
- `/vue3-temp-skill 给这个页面加上按钮权限,只有 admin 角色能看到删除按钮`
|
|
29
|
+
- `/vue3-temp-skill 帮我写一个移动端的数据大屏,用 scale 缩放方案`
|
|
30
|
+
- `/vue3-temp-skill 给编辑页加上数据变更对比,支持字段高亮和变更汇总`
|
|
31
|
+
|
|
32
|
+
AI 接收到上述请求后,应当自行判断需要哪些模块的规范,无需用户手动指定。
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## ⛔ 项目优先原则(最高优先级,所有生成必须遵守)
|
|
37
|
+
|
|
38
|
+
> **核心规则:AI 生成代码前,必须先查阅项目已有的实现,禁止脱离项目自行选型。**
|
|
39
|
+
|
|
40
|
+
### 为什么需要这条规则
|
|
41
|
+
|
|
42
|
+
项目已经选定了一套完整的技术方案(图谱用 `relation-graph-vue3`、流程图用 `@antv/g6`、富文本用 `wangEditor` 等)。如果 AI 不查阅项目就直接生成代码,可能会引入完全不同的库(比如用 D3 做图谱、用 Mermaid 做流程图),导致:
|
|
43
|
+
- 项目依赖膨胀,出现功能重复的库
|
|
44
|
+
- 代码风格不统一,维护成本增加
|
|
45
|
+
- 与现有组件/Hook/工具无法集成
|
|
46
|
+
|
|
47
|
+
### 强制执行规则
|
|
48
|
+
|
|
49
|
+
**1. 先查后写**
|
|
50
|
+
生成任何功能代码之前,**必须先加载 `project-inventory` 模块**(`references/project-inventory.md`),查阅项目已有的三方库、组件、Hook、工具函数。
|
|
51
|
+
|
|
52
|
+
**2. 有则必用**
|
|
53
|
+
如果项目已有对应功能的库或组件,**必须直接使用**,不得引入替代方案。例如:
|
|
54
|
+
- 需要图表 → 必须用 `echarts` + `ReEchart`,不得用 Chart.js / D3
|
|
55
|
+
- 需要图谱 → 必须用 `relation-graph-vue3`,不得用 D3 / vis.js
|
|
56
|
+
- 需要流程图 → 必须用 `@antv/g6`,不得用 Mermaid / LogicFlow
|
|
57
|
+
- 需要富文本 → 必须用 `@wangeditor/editor` + `ReRichText`,不得用 Quill / TinyMCE
|
|
58
|
+
- 需要 HTTP 请求 → 必须用项目封装的 `src/utils/http.ts`,不得直接用 axios / fetch
|
|
59
|
+
|
|
60
|
+
完整的功能选型对照表见 `references/project-inventory.md` 第八节。
|
|
61
|
+
|
|
62
|
+
**3. 参考示例**
|
|
63
|
+
`src/views/` 下有大量功能示例页面(图谱、工作流、WebSocket、附件管理等)。遇到类似需求时,**必须先参考对应示例的代码模式**,而不是从零设计。
|
|
64
|
+
|
|
65
|
+
**4. 无则上报**
|
|
66
|
+
如果确实需要引入清单中没有的新库,**必须在输出中明确标注**:
|
|
67
|
+
```
|
|
68
|
+
⚠ 待确认:当前需求需要引入新依赖 [库名],项目中暂无对应实现。
|
|
69
|
+
原因:[为什么现有库无法满足]
|
|
70
|
+
建议版本:[x.x.x]
|
|
71
|
+
请确认是否允许引入。
|
|
72
|
+
```
|
|
73
|
+
未经用户确认,不得自行引入。
|
|
74
|
+
|
|
75
|
+
**5. 复用优先**
|
|
76
|
+
- 已有组件 → 直接使用,不重新封装
|
|
77
|
+
- 已有 Hook → 直接调用,不重新编写
|
|
78
|
+
- 已有工具函数 → 直接 import,不重新实现
|
|
79
|
+
- 已有 Store → 直接读取,不新建同功能 Store
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 模块路由表(AI 内部匹配用)
|
|
84
|
+
|
|
85
|
+
当用户的需求涉及以下场景时,**必须加载对应模块的详细规范**来指导代码生成。一个需求可能匹配多个模块。
|
|
86
|
+
|
|
87
|
+
| 模块 | 匹配场景 | 关键词 |
|
|
88
|
+
|------|---------|--------|
|
|
89
|
+
| **vue-core** | 项目初始化、新建组件、配置路由/状态管理/i18n | 组件、目录、路由、pinia、store、i18n、技术栈、命名 |
|
|
90
|
+
| **http-api** | 编写 API 接口调用、文件上传下载、加密请求 | 接口、请求、http、axios、上传、下载、加密、API |
|
|
91
|
+
| **ui-components** | 开发 Re* 前缀公共组件、组件库维护 | Re组件、公共组件、组件库、封装、type.ts |
|
|
92
|
+
| **crud-pages** | 开发查询列表页、表单页、详情/编辑页 | 列表、表格、表单、新增、编辑、详情、CRUD、查询、管理模块 |
|
|
93
|
+
| **advanced-ui** | 使用选择器、高级表格、图表、工作流等 | 选择器、树形、级联、vxe-table、echarts、图表、bpmn |
|
|
94
|
+
| **layout-theme** | 修改布局、主题、暗黑模式、CSS 变量、Design Tokens、UnoCSS 桥接、响应式适配、PC/移动端双端、ui-ux-pro-max 设计输出衔接 | 布局、主题、暗色、暗黑、dark-mode、CSS变量、design-tokens、配色、色阶、chroma-js、响应式、双端、ui-ux-pro-max、样式 |
|
|
95
|
+
| **permission-auth** | 配置页面权限、按钮权限、自定义指令、编写 Hooks | 权限、角色、v-auth、指令、directive、hook |
|
|
96
|
+
| **mobile-h5** | 开发移动端页面、Vant 组件、微信 JS-SDK | 移动端、H5、vant、微信、weixin、wechat、tabbar |
|
|
97
|
+
| **build-optim** | Vite 构建配置、代码分割、ESLint/Stylelint 工具链 | 构建、打包、vite、分包、eslint、stylelint |
|
|
98
|
+
| **code-quality** | 始终加载 — 所有生成代码必须经过此模块审查 | (始终生效,无需关键词触发) |
|
|
99
|
+
| **project-inventory** | 始终加载 — 生成代码前必须查阅项目已有资产(库/组件/Hook/工具),禁止自行选型 | (始终生效,无需关键词触发) |
|
|
100
|
+
| **api-check** | 涉及前后端接口联调、契约验证、Mock 数据 | 联调、对接、接口检查、mock、参数、响应 |
|
|
101
|
+
| **feedback-loading** | Loading 遮罩、Message 提示、MessageBox 弹窗确认 | loading、message、提示、弹窗、确认、警告、feedback |
|
|
102
|
+
| **base-code-dict** | 码表/字典数据获取、缓存、映射显示 | 字典、码表、baseCode、枚举、enum、下拉数据、filterValue |
|
|
103
|
+
| **download-export** | 文件下载、模板下载、文件流导出、附件预览 | 导出、下载、excel、blob、模板、附件、attachment |
|
|
104
|
+
| **seamless-scroll** | 无缝滚动、公告栏、排行榜滚动 | 滚动、无缝、公告、跑马灯、seamless、marquee |
|
|
105
|
+
| **qrcode-barcode** | 二维码生成/展示、条形码生成 | 二维码、qrcode、条形码、barcode、扫码 |
|
|
106
|
+
| **rich-text** | 富文本编辑器录入、图文混排 | 富文本、editor、wangeditor、图文、编辑器 |
|
|
107
|
+
| **verify-captcha** | 滑块验证、拖拽验证、图片验证码、短信倒计时 | 验证码、captcha、滑块、拖拽验证、短信、sms |
|
|
108
|
+
| **data-screen** | 数据大屏/可视化大屏开发 | 大屏、可视化、dataScreen、scale、数据展示、全屏 |
|
|
109
|
+
| **form-advanced** | 图标选择器、分段控制器、卡片选择、锚点、折叠面板、地址解析 | 图标选择、分段、卡片选择、锚点、折叠、地址解析、iconPicker |
|
|
110
|
+
| **feedback-ui** | 通知栏、水印、时间轴、闪烁点、打字机动画 | 通知栏、水印、watermark、时间轴、闪烁、打字机、typeit |
|
|
111
|
+
| **graph-relation** | 知识图谱、关系图谱、力导向布局 | 图谱、关系图、knowledge graph、relation-graph、力导向、节点高亮 |
|
|
112
|
+
| **workflow-bpmn** | BPMN 工作流查看、流程审批可视化 | bpmn、工作流、流程审批、WorkflowViewer、XML |
|
|
113
|
+
| **flowchart-g6** | G6 流程图、树形流程、Vue 节点渲染 | 流程图、g6、flowchart、树形图、compact-box、Vue 节点 |
|
|
114
|
+
| **data-mapping** | JsPlumb 字段映射、拖拽连线 | 映射、jsplumb、字段映射、连线、拖拽、数据对照 |
|
|
115
|
+
| **websocket-realtime** | WebSocket 实时通信、多实例管理 | websocket、ws、实时、长连接、推送、多实例 |
|
|
116
|
+
| **file-management** | 附件上传管理、文件预览 | 附件、attachment、上传、文件预览、ReAttachment、ReFileViewer |
|
|
117
|
+
| **directives-advanced** | 高级自定义指令(复制、自适应字体) | v-copy、v-auto-font、指令、directive、复制、字体自适应 |
|
|
118
|
+
| **data-compare** | 编辑页数据变更对比、高亮、汇总弹窗、表格行增删改对比 | 变更对比、数据对比、v-compare、变更汇总、ChangeSummary、对比高亮、原值、compareStore、.table |
|
|
119
|
+
| **detail-page** | 详情页/编辑页跳转与数据回显 | 详情页、useDetail、toDetail、编辑页、参数传递、tab 标题 |
|
|
120
|
+
| **data-writeback** | 表单数据回显、编辑回填、多表单校验 | 回显、回填、writeback、Object.assign、编辑、useFormCheck、多表单 |
|
|
121
|
+
| **tree-table** | 树形表格、树结构转换、树形连线 | 树表、tree-table、handleTree、树形结构、ReTreeLine、层级 |
|
|
122
|
+
|
|
123
|
+
### 匹配规则
|
|
124
|
+
|
|
125
|
+
1. **单模块**:需求明确属于某一类 → 直接按该模块规范执行。
|
|
126
|
+
2. **多模块组合**:复杂需求涉及多个方面 → 同时参照多个模块。
|
|
127
|
+
- 例:"开发一个带权限控制的客户管理模块" → `crud-pages` + `permission-auth` + `http-api`
|
|
128
|
+
3. **默认兜底**:无法明确匹配时,默认参照 `vue-core` 基础规范。
|
|
129
|
+
4. **code-quality 和 project-inventory 始终生效**:无论匹配到什么模块,生成代码前必须先查阅项目资产清单(project-inventory),生成代码后都必须执行质量审查(code-quality)。
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 项目技术栈概览
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
const techStack = {
|
|
137
|
+
vue: "3.5.x", // Composition API + <script setup>
|
|
138
|
+
typescript: "6.x", // 严格类型
|
|
139
|
+
vite: "8.x", // Rolldown 构建引擎
|
|
140
|
+
elementPlus: "2.14.x", // PC 端 UI
|
|
141
|
+
vant: "4.10.x", // 移动端 UI
|
|
142
|
+
pinia: "3.x", // 状态管理 + 持久化
|
|
143
|
+
vueRouter: "5.x", // Hash 模式 + 动态路由
|
|
144
|
+
unocss: "66.x", // 原子化 CSS(presetWind3)
|
|
145
|
+
axios: "1.18.x", // HTTP 请求(自定义封装)
|
|
146
|
+
vueI18n: "11.x", // 国际化
|
|
147
|
+
};
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## 目录结构
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
src/
|
|
154
|
+
├── api/ # API 接口(按业务模块分文件)
|
|
155
|
+
├── components/ # 可复用组件(Re* 前缀)
|
|
156
|
+
├── hooks/ # 组合式函数
|
|
157
|
+
├── store/ # Pinia 状态管理
|
|
158
|
+
├── router/ # 路由配置(PC + 移动端)
|
|
159
|
+
├── utils/ # 工具函数
|
|
160
|
+
├── styles/ # 全局样式
|
|
161
|
+
├── views/ # 页面组件
|
|
162
|
+
├── directives/ # 自定义指令
|
|
163
|
+
├── layout/ # 布局系统
|
|
164
|
+
└── locales/ # 国际化文件
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## 核心约定速查
|
|
168
|
+
|
|
169
|
+
以下是所有模块共享的基础约定,详细规则见 `references/` 下各模块文档。
|
|
170
|
+
|
|
171
|
+
### 组件规范
|
|
172
|
+
|
|
173
|
+
```vue
|
|
174
|
+
<script setup lang="ts">
|
|
175
|
+
import type { ComponentNameProps, ComponentNameEmits } from "./type";
|
|
176
|
+
|
|
177
|
+
defineOptions({ name: "ReComponentName" });
|
|
178
|
+
|
|
179
|
+
const props = withDefaults(defineProps<ComponentNameProps>(), {});
|
|
180
|
+
const emit = defineEmits<ComponentNameEmits>();
|
|
181
|
+
</script>
|
|
182
|
+
|
|
183
|
+
<template>
|
|
184
|
+
<div class="re-component-name"><!-- 内容 --></div>
|
|
185
|
+
</template>
|
|
186
|
+
|
|
187
|
+
<style lang="scss" scoped>
|
|
188
|
+
.re-component-name { /* 样式 */ }
|
|
189
|
+
</style>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
- 始终使用 `<script setup lang="ts">`,禁止 Options API
|
|
193
|
+
- Props/Emits 类型抽取到同目录 `type.ts`
|
|
194
|
+
- 自定义组件 `Re*` 前缀,class 名 `re-*` 前缀
|
|
195
|
+
- Element Plus / Vant 自动引入,Re 组件需显式 import
|
|
196
|
+
|
|
197
|
+
### API 调用
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
// src/api/xxx.ts
|
|
201
|
+
import http from "@/utils/http";
|
|
202
|
+
import type { Result } from "@/utils/http/types";
|
|
203
|
+
|
|
204
|
+
export function getXxxListApi(data: XxxQuery) {
|
|
205
|
+
return http.request<Result<XxxListResult>>("post", "/api/xxx/list", { data });
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
- 所有接口统一 POST,参数通过 `data` 传递
|
|
210
|
+
- 接口函数封装在 `src/api/` 目录,不在组件中直接调用 http
|
|
211
|
+
- 返回值必须声明 `Result<T>` 泛型
|
|
212
|
+
|
|
213
|
+
### 状态管理
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
import { defineStore } from "pinia";
|
|
217
|
+
|
|
218
|
+
export const useXxxStore = defineStore("xxx", {
|
|
219
|
+
state: () => ({ /* ... */ }),
|
|
220
|
+
actions: { /* ... */ },
|
|
221
|
+
persist: { key: "xxx-store", paths: ["field"] },
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
export const useXxxStoreHook = () => useXxxStore();
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### 权限控制
|
|
228
|
+
|
|
229
|
+
```vue
|
|
230
|
+
<!-- 按钮级权限 -->
|
|
231
|
+
<el-button v-auth="['admin']">删除</el-button>
|
|
232
|
+
|
|
233
|
+
<!-- 区域级权限 -->
|
|
234
|
+
<ReAuth :value="['admin']"><!-- 内容 --></ReAuth>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### 列表页标准模式
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
import { useTableSearch } from "@/hooks/useTableSearch";
|
|
241
|
+
|
|
242
|
+
const { content, pagination, loading, handleSearch, handleReset } =
|
|
243
|
+
useTableSearch(formQuery, getXxxListApi);
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### 国际化
|
|
247
|
+
|
|
248
|
+
- 所有用户可见文案使用 `$t()` 或 `t()`
|
|
249
|
+
- 开发阶段可先用中文占位,后续替换
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## 各模块速查索引
|
|
254
|
+
|
|
255
|
+
### vue-core — 项目基础
|
|
256
|
+
|
|
257
|
+
- 组件命名:`Re[Name]`(自定义)、大驼峰(页面)
|
|
258
|
+
- 路由:`satisfies RouteConfigsTable`,`meta.rank` 排序,`meta.roles` 权限
|
|
259
|
+
- Store:`useXxxStoreHook()` 供组件外部调用
|
|
260
|
+
- 类型定义放 `type.ts`,不内联
|
|
261
|
+
|
|
262
|
+
### http-api — 接口调用
|
|
263
|
+
|
|
264
|
+
- 统一 POST + `data`,不用 GET + `params`
|
|
265
|
+
- 加密请求:`{ data, crypto: true }`
|
|
266
|
+
- 文件下载:`responseType: "blob"` + `blobDown()`
|
|
267
|
+
- Java `Long` → TS `string`(精度),`BigDecimal` → `string`
|
|
268
|
+
|
|
269
|
+
### ui-components — Re 组件开发
|
|
270
|
+
|
|
271
|
+
- 目录结构:`ReXxx/src/xxx.vue` + `index.ts` + `type.ts`
|
|
272
|
+
- 导出:`export const ReXxx = xxx`
|
|
273
|
+
- Props 每个字段必须有 JSDoc 注释
|
|
274
|
+
|
|
275
|
+
### crud-pages — CRUD 页面
|
|
276
|
+
|
|
277
|
+
- 列表页:`useTableSearch` + `ReGrid` + `ReTableBar` + `ReTableOperate`
|
|
278
|
+
- 表单页:`reactive<T>()` + `FormRules<T>` + `formRef.validate()`
|
|
279
|
+
- 详情页:`route.query.id` 传参,`Object.assign(formData, data)` 回填
|
|
280
|
+
- 提交按钮必须有 `loading` 防重复
|
|
281
|
+
|
|
282
|
+
### advanced-ui — 高级组件
|
|
283
|
+
|
|
284
|
+
- 简单下拉 → `el-select`,搜索+分页 → `RESelectQuery`
|
|
285
|
+
- 树形选择 → `el-tree-select`,级联 → `ReCascader`
|
|
286
|
+
- 大数据表格 → `vxe-table`(>1000 行)
|
|
287
|
+
- 图表:`onUnmounted` 中 `dispose()`,用 `ResizeObserver` 自适应
|
|
288
|
+
|
|
289
|
+
### layout-theme — 设计系统与布局主题
|
|
290
|
+
|
|
291
|
+
- **CSS 变量三层体系**:`--vts-*`(全局基础)→ `--vts-theme-*`(侧边栏 8 套配色)→ `--el-*`(EP 动态色阶)
|
|
292
|
+
- **8 套侧边栏预设**:light / default / saucePurple / pink / dusk / volcano / mingQing / auroraGreen
|
|
293
|
+
- **主色色阶**:`chroma-js` 自动生成 `--el-color-primary-light-1~9`(brighten)和 `-dark-1~2`(darken)
|
|
294
|
+
- **暗黑模式**:`html.dark` 类名 + View Transitions API 圆形扩散动画,覆盖变量在 `dark.scss`
|
|
295
|
+
- **Design Tokens**:间距 4px 基数(UnoCSS `p-*`/`m-*`),字号 12px~128px,字体 Alibaba PuHuiTi 3.0
|
|
296
|
+
- **布局 3 模式**:垂直 210px / 水平 0 / 混合 210px,侧边栏 mixin × 3 调用
|
|
297
|
+
- **UnoCSS 桥接**:`presetRemToPx(baseFontSize:4)` → 1 单位 = 1px,`theme.colors` 映射 EP 变量
|
|
298
|
+
- **ui-ux-pro-max 衔接**:设计输出颜色必须映射为 CSS 变量,禁止硬编码;暗黑模式必须同步适配
|
|
299
|
+
- **硬编码颜色清单**:`element-plus.scss` 中有 9 处硬编码未做暗黑适配,新增样式时注意
|
|
300
|
+
- PC/移动端:`isMobile` 条件渲染,移动端用 Vant 组件
|
|
301
|
+
- 数据大屏:1920x1080 + `scale` 缩放
|
|
302
|
+
|
|
303
|
+
### permission-auth — 权限指令
|
|
304
|
+
|
|
305
|
+
- 页面级:路由 `meta.roles`
|
|
306
|
+
- 按钮级:`v-auth` 指令 / `ReAuth` 组件
|
|
307
|
+
- JS 中:`useAuth().hasAuth(['admin'])`
|
|
308
|
+
- 指令放在 `src/directives/`,统一注册
|
|
309
|
+
|
|
310
|
+
### mobile-h5 — 移动端
|
|
311
|
+
|
|
312
|
+
- 页面放 `src/views/mobile/`,路由前缀 `/m`
|
|
313
|
+
- 列表:`van-list` 触底加载,不用分页
|
|
314
|
+
- 选择器:`van-popup` + `van-picker`
|
|
315
|
+
- 微信:`useWechat` Hook,先判断 `isWechatBrowser`
|
|
316
|
+
|
|
317
|
+
### build-optim — 构建工程化
|
|
318
|
+
|
|
319
|
+
- 分包:`vue-vendor` / `ui-vendor` / `chart-vendor` 分离
|
|
320
|
+
- 压缩:`oxc`(不用 terser)
|
|
321
|
+
- 工具链:oxlint + eslint(@antfu) + stylelint + commitlint + husky
|
|
322
|
+
- 提交规范:`type(scope): description`
|
|
323
|
+
|
|
324
|
+
### code-quality — 代码审查
|
|
325
|
+
|
|
326
|
+
- 8 大检查项:类型 / 组件 / API / 安全 / 性能 / 样式 / 业务 / 风格
|
|
327
|
+
- 禁止 `any`、禁止 `console.log` 残留、禁止 `v-html` 渲染用户输入
|
|
328
|
+
- 生成代码后必须逐项自查(详见下方完整审查清单)
|
|
329
|
+
|
|
330
|
+
### project-inventory — 项目资产清单(始终加载)
|
|
331
|
+
|
|
332
|
+
- 三方库选型表:58 个生产依赖按功能分类,明确每个场景的指定方案
|
|
333
|
+
- Re* 组件清单:37 个自定义组件,开发前必须先查是否已有
|
|
334
|
+
- Hook / 工具 / 指令 / Store 清单:所有可复用的基础设施
|
|
335
|
+
- 示例页面索引:20 个 views 目录对应功能参考
|
|
336
|
+
- **功能选型对照表**:20+ 场景的"禁止替代"规则(图谱必须用 relation-graph,流程图必须用 G6 等)
|
|
337
|
+
- 核心原则:先查后写、有则必用、无则上报、复用优先
|
|
338
|
+
|
|
339
|
+
### api-check — 接口对接
|
|
340
|
+
|
|
341
|
+
- 6 步检查:URL / 参数 / 响应 / 特殊场景 / 联调排查 / Mock
|
|
342
|
+
- 参数放 `data` 不是 `params`
|
|
343
|
+
- 金额用 `string`,日期确认格式
|
|
344
|
+
- 联调问题先查 Network 面板
|
|
345
|
+
|
|
346
|
+
### feedback-loading — 反馈与 Loading
|
|
347
|
+
|
|
348
|
+
- 局部 Loading:`v-loading.lock`,全屏:`v-loading.lock.fullscreen`
|
|
349
|
+
- 统一 SVG:`useApp().svgLoading`
|
|
350
|
+
- Message:`import { message } from "@/utils/message"`,默认 grouping + plain
|
|
351
|
+
- MessageBox 文案用 `$t()`
|
|
352
|
+
|
|
353
|
+
### base-code-dict — 基础代码(字典)
|
|
354
|
+
|
|
355
|
+
- 获取:`useApp().baseCodeGet(codeType)`,首次自动请求+缓存
|
|
356
|
+
- 映射:`filterValue(code, list, "code", "value")`
|
|
357
|
+
- 刷新缓存:`{ refresh: true }`
|
|
358
|
+
- 相同码表用相同 `codeType`,避免重复请求
|
|
359
|
+
|
|
360
|
+
### download-export — 下载与导出
|
|
361
|
+
|
|
362
|
+
- 文件流:`blobDown(res.data, "文件名.xlsx", res)`
|
|
363
|
+
- 模板下载:`download("模板名")`
|
|
364
|
+
- 在线资源:`downloadByUrl()` / `downloadByOnlineUrl()` / `downloadByBase64()`
|
|
365
|
+
- 文件名优先从响应头解析
|
|
366
|
+
|
|
367
|
+
### seamless-scroll — 无缝滚动
|
|
368
|
+
|
|
369
|
+
- 组件:`ReSeamlessScroll`,配置 `direction` / `step` / `hoverStop`
|
|
370
|
+
- `limitMoveNum` 控制最小启动数据量
|
|
371
|
+
- 垂直滚动容器需固定高度,水平滚动内容需足够宽
|
|
372
|
+
|
|
373
|
+
### qrcode-barcode — 二维码与条形码
|
|
374
|
+
|
|
375
|
+
- 二维码:`ReQrcode`(支持 logo、颜色配置、过期遮罩)
|
|
376
|
+
- 条形码:`ReBarcode`(支持 CODE128/EAN13 等多种编码)
|
|
377
|
+
- 内容为空不渲染,需 `v-if` 处理
|
|
378
|
+
|
|
379
|
+
### rich-text — 富文本编辑器
|
|
380
|
+
|
|
381
|
+
- 组件:`ReRichText`(封装 wangEditor)
|
|
382
|
+
- `v-model` 同步 HTML,`v-model:attachment-ids` 同步附件 ID
|
|
383
|
+
- 自定义上传走 `getUploadUrl` 接口
|
|
384
|
+
- 实例在 `onBeforeUnmount` 中销毁
|
|
385
|
+
|
|
386
|
+
### verify-captcha — 验证码与校验
|
|
387
|
+
|
|
388
|
+
- 滑块拼图:`ReVerify`,拖拽验证:`ReDragVerify`
|
|
389
|
+
- 图片验证码:`ReImageVerify`,支持 `getImgCode()` 刷新
|
|
390
|
+
- 短信倒计时:`ReSmsCode`,内置手机号校验
|
|
391
|
+
- 前端仅做防刷,关键业务需后端二次校验
|
|
392
|
+
|
|
393
|
+
### data-screen — 数据大屏
|
|
394
|
+
|
|
395
|
+
- 设计稿 1920x1080,`transform: scale()` 等比缩放
|
|
396
|
+
- 内部元素按设计稿像素开发,不写响应式单位
|
|
397
|
+
- 图表 `resize` 时调用 `chart.resize()`
|
|
398
|
+
- 大屏使用独立布局,不显示菜单/页头
|
|
399
|
+
|
|
400
|
+
### form-advanced — 高级表单组件
|
|
401
|
+
|
|
402
|
+
- 图标选择器:`ReIconPicker`,返回值用于 `svg-icon` 的 `name`
|
|
403
|
+
- 分段控制器:`ReSegmented`,支持 icon/tip/disabled
|
|
404
|
+
- 卡片选择:`ReCheckCard`,支持多选
|
|
405
|
+
- 锚点导航:`ReAnchor`,弹窗场景指定 `scrollContent`
|
|
406
|
+
- 地址解析:`address-parse` 库
|
|
407
|
+
|
|
408
|
+
### feedback-ui — 展示类反馈组件
|
|
409
|
+
|
|
410
|
+
- 通知栏:`ReNoticeBar`,长文本自动滚动
|
|
411
|
+
- 水印:`useWatermark()`,传容器 DOM 可局部水印
|
|
412
|
+
- 时间轴:`ReTimeLine`,数据项含 title + date
|
|
413
|
+
- 闪烁点:`useRenderFlicker()` 返回组件
|
|
414
|
+
- 打字机:`TypeIt` 组件
|
|
415
|
+
|
|
416
|
+
### graph-relation — 知识图谱
|
|
417
|
+
|
|
418
|
+
- 组件库:`relation-graph-vue3`,力导向/圆形/树形多种布局
|
|
419
|
+
- 数据格式:`GraphNode`(id, text, color, width, height)+ `GraphLine`(from, to, text, color)
|
|
420
|
+
- 初始化:`graphRef.value.setJsonData({ rootId, nodes, lines }, callback)`
|
|
421
|
+
- 力导向布局需 `layoutMask` 遮罩,渲染完成后隐藏
|
|
422
|
+
- 节点点击高亮:遍历关联线设置 `color`,非关联线置灰
|
|
423
|
+
- 搜索定位:`graphRef.value.getInstance().moveNodeToCenter(nodeId)`
|
|
424
|
+
|
|
425
|
+
### workflow-bpmn — BPMN 工作流查看
|
|
426
|
+
|
|
427
|
+
- 使用 `bpmn-js/lib/Viewer`(只读模式,不用 Modeler)
|
|
428
|
+
- 核心组件:`WorkflowViewer`,props 接收 `xml` + `processInfo`
|
|
429
|
+
- 高亮流程:`canvas.addMarker(elementId, 'active' | 'finished')`,CSS 类控制颜色
|
|
430
|
+
- 生命周期:`onBeforeUnmount` 中 `viewer.destroy()` 防止内存泄漏
|
|
431
|
+
- 类型定义:`BpmnElementType`、`ProcessInfo`、`BpmnWorkflowData` 在 `types/bpmn.ts`
|
|
432
|
+
|
|
433
|
+
### flowchart-g6 — G6 流程图
|
|
434
|
+
|
|
435
|
+
- 依赖:`@antv/g6` v5 + `g6-extension-vue`(支持 Vue 组件作为节点)
|
|
436
|
+
- Vue 节点:`defineComponent` + TSX 渲染,通过 `register(ExtensionCategory.NODE, 'vue-node', VueNode)` 注册
|
|
437
|
+
- 布局:`compact-box`(紧凑树),`getLayoutData` 配置横向/纵向
|
|
438
|
+
- 动态导入:`const G6 = await import('@antv/g6')` 避免首屏加载
|
|
439
|
+
- 响应式:`useResizeObserver` 监听容器变化,调用 `graph.resize()` + `graph.fitView()`
|
|
440
|
+
- 销毁:`onBeforeUnmount` 中 `graph.destroy()`
|
|
441
|
+
|
|
442
|
+
### data-mapping — JsPlumb 字段映射
|
|
443
|
+
|
|
444
|
+
- 使用 `jsPlumb.getInstance({ Container: 'mapping-container' })` 创建实例
|
|
445
|
+
- 源/目标注册:`makeSource(el, config)` + `makeTarget(el, config)`
|
|
446
|
+
- 连线配置:`Connector: 'Bezier'`,`PaintStyle` 控制线宽/颜色
|
|
447
|
+
- 端点样式:`Endpoint: 'Dot'`,`EndpointStyle` 控制大小/颜色
|
|
448
|
+
- 获取映射结果:遍历 `getConnections()` 提取 sourceId/targetId
|
|
449
|
+
- 清理:`jsPlumbInstance.reset()` + 移除事件监听
|
|
450
|
+
|
|
451
|
+
### websocket-realtime — WebSocket 实时通信
|
|
452
|
+
|
|
453
|
+
- 全局管理:`initWebSocket(url, name?)` 创建命名实例,支持多连接并存
|
|
454
|
+
- Hook 使用:`useWebSocket(instanceName?)` 返回 `{ isConnected, subscribe, unsubscribe, send, sendRaw }`
|
|
455
|
+
- 标准消息:`{ type: string, data: any }` 格式,自动派发到对应 type 事件
|
|
456
|
+
- 原生消息:非标准格式自动派发到 `'message'` 事件
|
|
457
|
+
- 自动清理:`onUnmounted` 时移除当前组件所有监听器
|
|
458
|
+
- 关闭连接:`closeWebSocket(name)` 销毁指定实例
|
|
459
|
+
|
|
460
|
+
### file-management — 文件管理
|
|
461
|
+
|
|
462
|
+
- 附件组件:`ReAttachment`,`v-model` 格式 `{ attachmentType, attachmentList }`
|
|
463
|
+
- Props:`required`、`accepts`(文件类型)、`limit`(数量)、`size`(大小限制)、`pageStatus`(create/edit/view)
|
|
464
|
+
- 远程数据适配:`mapRemote()` 将后端字段映射为 `UploadUserFile` 格式
|
|
465
|
+
- 删除逻辑:本地文件直接 splice,远程文件调 `deleteAttachmentById` 接口
|
|
466
|
+
- 文件预览:`ReFileViewer` 组件,支持图片/PDF/Office 等多种格式
|
|
467
|
+
- 工具函数:`formatFileSize`(字节→可读)、`checkFileType`(后缀→类型)、`downloadAttachment`
|
|
468
|
+
|
|
469
|
+
### directives-advanced — 高级自定义指令
|
|
470
|
+
|
|
471
|
+
- `v-copy`:双击复制文本,`:click` 修饰符改为单击复制,`.stop` 阻止冒泡
|
|
472
|
+
- `v-auto-font`:根据容器宽度自动缩放字体,参数 `scale`/`min`/`max` 控制缩放比例和范围
|
|
473
|
+
- 指令目录:`src/directives/{copy,autoFont,compare}/`,统一在 `index.ts` 注册
|
|
474
|
+
- 数据变更对比(`v-compare` 全套)见 **data-compare** 模块,勿在本模块展开
|
|
475
|
+
|
|
476
|
+
### data-compare — 数据变更对比
|
|
477
|
+
|
|
478
|
+
- 指令:`v-compare` + `.map` / `.mapArr` / `.table`;开关用 `enabled`(无 `newValue` 字段)
|
|
479
|
+
- 编排:父页 `provide(oldDataInfo, compareDisabled)`,子表单 inject;对比的是映射后显示文案
|
|
480
|
+
- 控件:input 直接挂;日期包 `div`;下拉 `.map`/`composeOptions`;树/级联用 `value` 覆盖名称
|
|
481
|
+
- 封装组件:`ReSelectQuery`/`ReCascader` 用 `compare-config` + `compare-key` + `compare-modifiers`
|
|
482
|
+
- 表格:`.table` + `tableRowStatus` I/U/D/B + `getRowClassByFlag`;汇总矩阵
|
|
483
|
+
- 汇总:`useCompareStore` + `ChangeSummaryService` + `ChangeSummaryDialog`;定位靠 `data-compare-*`
|
|
484
|
+
- 示例:`src/views/form/moreForm/`(`/form/moreFormAnchor`)
|
|
485
|
+
|
|
486
|
+
### detail-page — 详情页开发
|
|
487
|
+
|
|
488
|
+
- Hook:`useDetail()` 返回 `{ toDetail, initToDetail, getParameter }`
|
|
489
|
+
- 跳转:`toDetail({ id, mark, text })`,`text` 自动生成为 tab 标题
|
|
490
|
+
- 参数获取:`getParameter()` 从 `route.query` 解析 `id`/`mark`/`text`
|
|
491
|
+
- 数据回显:`Object.assign(formData, detailData)` 保留响应式
|
|
492
|
+
- 注意:组件 `name` 必须与路由 `name` 一致,否则 tab 标题异常
|
|
493
|
+
|
|
494
|
+
### data-writeback — 数据回显
|
|
495
|
+
|
|
496
|
+
- 表单回显:`Object.assign(formData, apiResponse)` 保持响应式引用
|
|
497
|
+
- 下拉组件回填:`ReSelectQuery` 需设 `edit-data`,`el-tree-select` 需设 `cache-data`,`ReCascader` 需传完整路径数组
|
|
498
|
+
- 表格行编辑:备份原始数据 `_backup`,取消时恢复
|
|
499
|
+
- 多表单校验:`Promise.all(forms.map(f => f.validate()))` 并行校验
|
|
500
|
+
- 表单检查 Hook:`useFormCheck()` 聚合多个表单的校验状态
|
|
501
|
+
|
|
502
|
+
### tree-table — 树形表格
|
|
503
|
+
|
|
504
|
+
- 扁平转树:`handleTree(data, id, parentId, children)` 将列表数据转为树结构
|
|
505
|
+
- 树加层级:`buildHierarchyTree(data)` 添加 `level`/`isLeaf`/`path` 等层级信息
|
|
506
|
+
- el-table 树形:配置 `row-key` + `tree-props: { children, checkStrictly }`
|
|
507
|
+
- 树+表格布局:`el-row` + `el-col` 左右分栏,左侧 `el-tree`/`el-tree-v2`,右侧表格
|
|
508
|
+
- `ReTreeLine`:树形连线组件,兼容 `el-tree` 和 `el-tree-v2`,虚拟树必须传 `:tree-data`
|
|
509
|
+
|
|
510
|
+
---
|
|
511
|
+
|
|
512
|
+
## 代码生成工作流
|
|
513
|
+
|
|
514
|
+
AI 在接收到 `/vue3-temp-skill` 命令后,必须严格按以下流程执行:
|
|
515
|
+
|
|
516
|
+
### 第一步:需求分析
|
|
517
|
+
|
|
518
|
+
- 理解用户描述的业务需求
|
|
519
|
+
- 提取关键字段、查询条件、交互行为等信息
|
|
520
|
+
- 根据模块路由表,判断需要加载哪些模块的规范
|
|
521
|
+
|
|
522
|
+
### 第二步:加载规范
|
|
523
|
+
|
|
524
|
+
- 读取匹配模块在 `references/` 目录下的详细文档
|
|
525
|
+
- 结合上方"核心约定速查"中的基础约定
|
|
526
|
+
- **同时加载 `project-inventory` 模块**(项目资产清单),无论需求匹配了什么模块,此模块必须加载
|
|
527
|
+
|
|
528
|
+
### 第三步:项目探查(必须执行,禁止跳过)
|
|
529
|
+
|
|
530
|
+
在生成任何代码之前,AI **必须**完成以下探查:
|
|
531
|
+
|
|
532
|
+
1. **查阅项目资产清单**:读取 `references/project-inventory.md`,确认需求涉及的三方库、组件、Hook、工具函数是否已在项目中存在
|
|
533
|
+
2. **对照功能选型表**:检查清单第八节"功能选型对照表",确认项目已选定的技术方案
|
|
534
|
+
3. **查找示例页面**:检查清单第七节"示例页面索引",看是否有对应功能的参考实现
|
|
535
|
+
4. **确定技术方案**:
|
|
536
|
+
- 如果项目已有对应实现 → 直接使用,不引入替代方案
|
|
537
|
+
- 如果项目没有对应实现 → 标记为"待确认",在输出中说明需要引入的新依赖及原因
|
|
538
|
+
- 如果不确定 → 在项目中搜索相关代码确认
|
|
539
|
+
|
|
540
|
+
**禁止行为**:
|
|
541
|
+
- ❌ 不查阅清单就直接开始写代码
|
|
542
|
+
- ❌ 项目已有 `relation-graph-vue3`,却引入 D3 做图谱
|
|
543
|
+
- ❌ 项目已有 `useWebSocket` Hook,却重新写一个 WebSocket 管理类
|
|
544
|
+
- ❌ 项目已有 `ReAttachment` 组件,却用 el-upload 从零搭建
|
|
545
|
+
- ❌ 不参考 `src/views/` 下的示例页面,自行设计代码结构
|
|
546
|
+
|
|
547
|
+
### 第四步:生成代码
|
|
548
|
+
|
|
549
|
+
- 严格按照加载的规范生成完整代码
|
|
550
|
+
- 代码必须可直接使用,不用省略号或占位符
|
|
551
|
+
- 包含完整的类型定义、注释、样式
|
|
552
|
+
|
|
553
|
+
### 第五步:自动质量审查(必须执行)
|
|
554
|
+
|
|
555
|
+
代码生成完毕后,AI **必须自动执行以下审查**,不得跳过。如发现问题,直接修正后输出最终版本。
|
|
556
|
+
|
|
557
|
+
#### 审查清单
|
|
558
|
+
|
|
559
|
+
**0. 项目选型合规(最高优先级)**
|
|
560
|
+
- [ ] 是否查阅了 `project-inventory` 模块?→ 必须查阅
|
|
561
|
+
- [ ] 使用的三方库是否与项目选型一致?→ 对照功能选型表
|
|
562
|
+
- [ ] 是否复用了项目已有的 Re* 组件?→ 不重新造轮子
|
|
563
|
+
- [ ] 是否复用了项目已有的 Hook / 工具函数?→ 不重复编写
|
|
564
|
+
- [ ] 是否参考了 `src/views/` 下的示例页面?→ 遵循已有代码模式
|
|
565
|
+
- [ ] 如需引入新依赖,是否已标注"待确认"?→ 不得自行引入
|
|
566
|
+
|
|
567
|
+
**1. 类型安全**
|
|
568
|
+
- [ ] 是否存在 `any` 类型?→ 替换为具体类型或 `unknown`
|
|
569
|
+
- [ ] Props 是否声明了完整类型?→ 检查 `type.ts` 是否齐全
|
|
570
|
+
- [ ] API 返回值是否声明了 `Result<T>` 泛型?
|
|
571
|
+
- [ ] 事件 emit 是否声明了类型?
|
|
572
|
+
|
|
573
|
+
**2. 组件规范**
|
|
574
|
+
- [ ] 是否使用了 `<script setup lang="ts">`?
|
|
575
|
+
- [ ] 自定义组件是否有 `defineOptions({ name: "ReXxx" })`?
|
|
576
|
+
- [ ] Props/Emits 是否抽到了 `type.ts`?
|
|
577
|
+
- [ ] class 命名是否遵循 `re-*` 前缀?
|
|
578
|
+
|
|
579
|
+
**3. API 对接**
|
|
580
|
+
- [ ] 是否统一使用 POST + `data`?(不是 GET + `params`)
|
|
581
|
+
- [ ] API 函数是否封装在 `src/api/` 目录?
|
|
582
|
+
- [ ] 组件内是否避免了直接调用 `http`?
|
|
583
|
+
- [ ] Java Long/BigDecimal 类型是否映射为 `string`?
|
|
584
|
+
|
|
585
|
+
**4. 安全检查**
|
|
586
|
+
- [ ] 是否存在 `v-html` 渲染用户输入?→ 禁止
|
|
587
|
+
- [ ] 是否有硬编码的密钥/token?→ 移除
|
|
588
|
+
- [ ] 用户输入是否做了校验?
|
|
589
|
+
|
|
590
|
+
**5. 性能检查**
|
|
591
|
+
- [ ] 大数据列表是否考虑了虚拟滚动?
|
|
592
|
+
- [ ] 图表实例是否在 `onUnmounted` 中销毁?
|
|
593
|
+
- [ ] 是否有不必要的 `watch` 或重复计算?→ 用 `computed` 替代
|
|
594
|
+
- [ ] 大组件是否考虑了异步加载?
|
|
595
|
+
|
|
596
|
+
**6. 样式检查**
|
|
597
|
+
- [ ] 是否使用了 `<style scoped>`?
|
|
598
|
+
- [ ] 颜色是否使用 CSS 变量而非硬编码?
|
|
599
|
+
- [ ] 是否遵循 UnoCSS 原子类优先原则?
|
|
600
|
+
- [ ] 新增全局样式是否同步添加了暗黑模式覆盖?
|
|
601
|
+
- [ ] 是否通过 `setEpThemeColor()` 设置主色而非直接改 `--el-color-primary`?
|
|
602
|
+
- [ ] 侧边栏样式是否通过 `html[data-theme]` 选择器设置?
|
|
603
|
+
|
|
604
|
+
**7. 业务逻辑**
|
|
605
|
+
- [ ] 列表页是否使用了 `useTableSearch`?
|
|
606
|
+
- [ ] 表单提交按钮是否有 `loading` 防重复?
|
|
607
|
+
- [ ] 详情页是否正确处理了 `route.query.id`?
|
|
608
|
+
- [ ] 需要权限的地方是否加了 `v-auth` / `ReAuth`?
|
|
609
|
+
|
|
610
|
+
**8. 代码风格**
|
|
611
|
+
- [ ] 是否有 `console.log` 残留?→ 删除
|
|
612
|
+
- [ ] 是否有未使用的 import?→ 删除
|
|
613
|
+
- [ ] 是否有冗余的逻辑或死代码?→ 清理
|
|
614
|
+
- [ ] 命名是否语义化、一致?
|
|
615
|
+
- [ ] 国际化文案是否使用了 `$t()`?
|
|
616
|
+
|
|
617
|
+
### 第六步:输出结果
|
|
618
|
+
|
|
619
|
+
- 输出最终代码(已包含审查修正)
|
|
620
|
+
- 简要说明匹配了哪些模块、做了哪些关键决策
|
|
621
|
+
- 如有需要用户确认的点(如字段类型、接口地址),列出待确认项
|