@qilitt-mickey/vue3-temp-skill 1.1.12 → 1.1.14
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/SKILL.md +13 -2
- package/package.json +1 -1
- package/references/api-check.md +2 -0
- package/references/code-quality.md +25 -8
- package/references/core-kernel.md +10 -3
- package/references/crud-pages.md +41 -9
- package/references/data-writeback.md +13 -0
- package/references/design-system.md +3 -1
- package/references/detail-page.md +43 -33
- package/references/download-export.md +20 -0
- package/references/feedback-loading.md +19 -0
- package/references/form-advanced.md +2 -0
- package/references/http-api.md +25 -0
- package/references/icons.md +12 -0
- package/references/layout-theme.md +11 -0
- package/references/permission-auth.md +16 -2
- package/references/project-inventory.md +1 -1
package/SKILL.md
CHANGED
|
@@ -24,11 +24,20 @@ tags: [vue3, typescript, element-plus, vant, pinia, vite, unocss, crud, componen
|
|
|
24
24
|
|
|
25
25
|
1. 先读 `references/core-kernel.md`
|
|
26
26
|
2. 复用仓库已有 `Re*` / Hook / utils;选型表指定库勿擅自替换
|
|
27
|
-
3.
|
|
27
|
+
3. 按命中模块内**强制完整样板**整段编写(禁止只抄 API 签名、丢掉 meta/配套段落)
|
|
28
28
|
4. 无对应能力 → 标注「待确认」,未经同意不引入新依赖
|
|
29
29
|
5. 真相源:`仓库已有封装` > `本 Skill 示例` > 通用 Vue 习惯
|
|
30
30
|
6. 命中 addon / 缺依赖时再读 `project-inventory.md` 第九节;精确版本安装,禁止 `@latest`
|
|
31
31
|
|
|
32
|
+
## 抗略读(全模块 · 提高命中率)
|
|
33
|
+
|
|
34
|
+
按需模块 ≠ 可浅读。命中即须落到该文件的**完整样板 / Must-do**,生成后靠 `code-quality` 硬失败表兜底。
|
|
35
|
+
|
|
36
|
+
1. **样板字段默认写出**:示例里写明的 `activePath` / `keepAlive` / `roles` / `responseType: "blob"` 等不得改成 `//` 注释再当可选项;仅业务明确不需要时才删除
|
|
37
|
+
2. **关联能力同批落盘**:列表→详情 = `crud-pages` + `detail-page` 三件套;有 API = 同步 `http-api`;有删除 = 确认框;有编辑回显 = `Object.assign`
|
|
38
|
+
3. **Hook ≠ 壳层自动**:`toDetail` 写 tag;侧栏高亮 / keepAlive 靠路由 meta;`http` 加解密靠环境开关,不靠单请求配置
|
|
39
|
+
4. **大范围交付仍须逐模块核对硬失败表**,禁止「lint 过了就算完」
|
|
40
|
+
|
|
32
41
|
## 模块路由表
|
|
33
42
|
|
|
34
43
|
### 始终加载
|
|
@@ -112,7 +121,8 @@ tags: [vue3, typescript, element-plus, vant, pinia, vite, unocss, crud, componen
|
|
|
112
121
|
|
|
113
122
|
- HTTP:`import { http } from '@/utils/http'`;方法跟后端(允许 GET/POST);`Result<T>`;`VITE_API_BASE_URL` → `http-api`
|
|
114
123
|
- 列表:`onSearch` / `reset` + 黄金样板 → `crud-pages`
|
|
115
|
-
- 独立详情:`toDetail`
|
|
124
|
+
- 独立详情:`toDetail` **不能替代** `activePath` / `keepAlive` / `moreTags`;三件套 → `detail-page`
|
|
125
|
+
- 权限:`meta.roles` + `v-auth`/`ReAuth` → `permission-auth`
|
|
116
126
|
- 不二次挂 Layout;`script setup` + `defineOptions({ name })`;`$t('中文')`;样式契约 → `core-kernel`
|
|
117
127
|
|
|
118
128
|
## 工作流
|
|
@@ -134,6 +144,7 @@ tags: [vue3, typescript, element-plus, vant, pinia, vite, unocss, crud, componen
|
|
|
134
144
|
## 代码质量审查
|
|
135
145
|
- 闸门:已执行 code-quality(生成后)
|
|
136
146
|
- 清单:选型 / 类型 / 组件 / API / 安全 / 业务 / 列表→详情(如适用) / 列表布局(如适用) / 风格 → 通过 | 已修正:…
|
|
147
|
+
- 硬失败:无 | 已拦截并修正:…
|
|
137
148
|
- 命令:`pnpm lint:fix` → …;`pnpm type-check` → …
|
|
138
149
|
- 待确认:…
|
|
139
150
|
|
package/package.json
CHANGED
package/references/api-check.md
CHANGED
|
@@ -9,6 +9,8 @@ tags: [api, backend, integration, contract, http, checklist, mock]
|
|
|
9
9
|
|
|
10
10
|
写法与示例 → **`http-api`**。本文件只做联调核对。权威源:`types/global.d.ts`、`src/utils/http.ts`、`src/api/**`、`mock/**`、`useTableSearch`。
|
|
11
11
|
|
|
12
|
+
**抗略读**:联调阶段仍须核对「下载是否带 blob」「分页字段是否 content/totalCount」;契约不过 = API 未完成,禁止只靠 lint 放行。
|
|
13
|
+
|
|
12
14
|
## 基本信息
|
|
13
15
|
|
|
14
16
|
- [ ] 业务 path 与后端文档一致;忌把 `/mock/...` 当生产约定
|
|
@@ -12,7 +12,7 @@ tags: [code-review, quality, checklist, lint, typescript, vue3, security, perfor
|
|
|
12
12
|
## 协议(按序)
|
|
13
13
|
|
|
14
14
|
1. 重读本文件
|
|
15
|
-
2.
|
|
15
|
+
2. 列出本轮改动路径,对照下方清单;**硬失败表命中则先改代码再继续**
|
|
16
16
|
3. 业务项目根目录必跑:`pnpm lint:fix` → `pnpm type-check`(无脚本则 `pnpm lint` / `pnpm exec eslint . --fix`;`pnpm exec vue-tsc --noEmit`)
|
|
17
17
|
4. 失败则修代码并重跑,直至通过或写明阻塞
|
|
18
18
|
5. 最终回复追加:
|
|
@@ -22,11 +22,29 @@ tags: [code-review, quality, checklist, lint, typescript, vue3, security, perfor
|
|
|
22
22
|
- 闸门:已执行 code-quality(生成后)
|
|
23
23
|
- 改动文件:`path/a`、`path/b`、…
|
|
24
24
|
- 清单:选型 ✅ / 类型 ✅ / 组件 ✅ / API ✅ / 安全 ✅ / 业务 ✅ / 列表→详情 ✅或N/A / 列表布局 ✅或N/A / 风格 ✅
|
|
25
|
+
- 硬失败:无 | 已拦截并修正:…
|
|
25
26
|
- 已修正:…(无则写「无」)
|
|
26
27
|
- 命令:`pnpm lint:fix` → …;`pnpm type-check` → …
|
|
27
28
|
- 待确认:…
|
|
28
29
|
```
|
|
29
30
|
|
|
31
|
+
## 硬失败(对照落盘文件;命中即未通过)
|
|
32
|
+
|
|
33
|
+
lint / type-check **过了也不能放过**下列项。发现即改代码,禁止「已知问题后续再说」。
|
|
34
|
+
|
|
35
|
+
| 触发条件(改动里出现) | 未通过条件 | 正确做法 |
|
|
36
|
+
|------------------------|------------|----------|
|
|
37
|
+
| `toDetail` / 独立 `*Detail` 路由 | 路由无 `activePath`,或 `showLink` 非 `false` | `detail-page` 三件套 |
|
|
38
|
+
| 同上 | 默认场景缺 `keepAlive`/`moreTags`(业务未声明不要缓存) | 样板默认写出;不要缓存再删 |
|
|
39
|
+
| 同上 | 详情页无 `initToDetail`,或 `name` 与路由不一致 | 对齐 `defineOptions` |
|
|
40
|
+
| 列表页 | 无 `el-card.vts-page-card` / 无 `tableHeight` / 分页在 ReTableBar 外 | `crud-pages` L1–L8 |
|
|
41
|
+
| `src/api/**` | 绕过 `@/utils/http`,或虚构 `/api` 前缀,或响应当 `success`/`code` | `http-api` |
|
|
42
|
+
| 下载/导出 API | 无 `responseType: "blob"` | `http-api` / `download-export` |
|
|
43
|
+
| 删除/危险操作 | 无确认框 | `feedback-loading` |
|
|
44
|
+
| 编辑回显 | 整表 `formData = res.data` 破坏响应式 | `Object.assign`(`data-writeback`) |
|
|
45
|
+
| 按钮权限需求 | 裸 `v-if` 角色判断,未用 `v-auth`/`ReAuth` | `permission-auth` |
|
|
46
|
+
| 新菜单路由 | 父级无 `icon` 或业务页二次挂 `Layout` | `icons` + `core-kernel` |
|
|
47
|
+
|
|
30
48
|
## 选型与硬约束
|
|
31
49
|
|
|
32
50
|
- [ ] 已读 `core-kernel`;addon/缺依赖时已读 `project-inventory`
|
|
@@ -34,8 +52,8 @@ tags: [code-review, quality, checklist, lint, typescript, vue3, security, perfor
|
|
|
34
52
|
- [ ] addon 缺包按 inventory 第九节精确版本(禁止 `@latest`)
|
|
35
53
|
- [ ] 列表方法名 `onSearch` / `reset`;HTTP 用 `@/utils/http` + `Result<T>`
|
|
36
54
|
- [ ] 业务路由未二次挂 Layout
|
|
37
|
-
- [ ]
|
|
38
|
-
- [ ] 列表布局按 `crud-pages` 黄金样板(`el-card`+`content`+固定 height、`tableHeight`、`otherRef`、分页在 ReTableBar
|
|
55
|
+
- [ ] 独立详情:对照路由文件确认 `showLink:false` + `activePath` + `keepAlive`/`moreTags`(默认)+ `toDetail` + `initToDetail`
|
|
56
|
+
- [ ] 列表布局按 `crud-pages` 黄金样板(`el-card.vts-page-card`+`content`+固定 height、`tableHeight`、`otherRef`、分页在 ReTableBar 内;内容区无外层滚动条)
|
|
39
57
|
|
|
40
58
|
## TypeScript
|
|
41
59
|
|
|
@@ -88,13 +106,12 @@ tags: [code-review, quality, checklist, lint, typescript, vue3, security, perfor
|
|
|
88
106
|
## 业务
|
|
89
107
|
|
|
90
108
|
- [ ] 提交前 `validate()`;删除有确认;提交有 loading;列表有 `v-loading`
|
|
91
|
-
- [ ]
|
|
109
|
+
- [ ] 编辑回显正确(`Object.assign`);分页切换会拉数
|
|
92
110
|
|
|
93
|
-
###
|
|
111
|
+
### 列表→详情(改动含 toDetail / *Detail 路由时强制,禁止 N/A 糊弄)
|
|
94
112
|
|
|
95
|
-
- [ ]
|
|
96
|
-
- [ ] 仅 `toDetail`;详情 `initToDetail`;`name`
|
|
97
|
-
- [ ] 按需 `keepAlive` / `moreTags`
|
|
113
|
+
- [ ] **打开落盘路由文件**核对:兄弟绝对 path;`showLink:false`;`activePath`=列表 path;非空 `title`;默认 `keepAlive`+`moreTags`
|
|
114
|
+
- [ ] 仅 `toDetail`;详情 `initToDetail`;`name` 对齐;`toDetail` 第 3 参 title 可辨识
|
|
98
115
|
|
|
99
116
|
### 列表布局(命中 crud-pages 时)
|
|
100
117
|
|
|
@@ -18,13 +18,13 @@ tags: [vue3, kernel, conventions, layout, router, http, crud, inventory]
|
|
|
18
18
|
| 3 | 方法跟后端文档,**允许 GET / POST**;POST → `data`,GET → `params` |
|
|
19
19
|
| 4 | 列表用 `useTableSearch`,方法名 **`onSearch` / `reset`** |
|
|
20
20
|
| 5 | 业务路由 **禁止** 再挂 `component: Layout` |
|
|
21
|
-
| 6 |
|
|
21
|
+
| 6 | 独立详情/编辑:按 **`detail-page` 三件套**(`showLink`+`activePath`+默认`keepAlive`/`moreTags` + `toDetail` + `initToDetail`);`toDetail`≠自动侧栏高亮/缓存 |
|
|
22
22
|
| 7 | 页面权限 `meta.roles`;按钮 `v-auth` / `ReAuth` |
|
|
23
23
|
| 8 | 环境只用 `import.meta.env.VITE_*` |
|
|
24
24
|
| 9 | i18n:`$t('中文key')` |
|
|
25
25
|
| 10 | 禁止用 `v-html` 渲染不可信内容 |
|
|
26
26
|
| 11 | 新依赖须用户确认;已有封装须复用;选型表指定库勿擅自替换 |
|
|
27
|
-
| 12 | 列表布局按 **`crud-pages` 黄金样板**(`el-card`+`content`+固定 height、`tableHeight`、`otherRef`、分页在 ReTableBar
|
|
27
|
+
| 12 | 列表布局按 **`crud-pages` 黄金样板**(`el-card.vts-page-card`+`content`+固定 height、`tableHeight`、`otherRef`、分页在 ReTableBar 内;仅表格体内滚动) |
|
|
28
28
|
| 13 | addon 按 `project-inventory` 第九节精确版本安装;禁止 `@latest` |
|
|
29
29
|
| 14 | 样式契约见下文「样式契约」 |
|
|
30
30
|
|
|
@@ -44,11 +44,15 @@ export default {
|
|
|
44
44
|
component: () => import("@/views/xxx/list/index.vue"),
|
|
45
45
|
meta: { title: "客户列表", roles: ["admin", "common"] },
|
|
46
46
|
},
|
|
47
|
-
// 独立详情:兄弟路由 + showLink
|
|
47
|
+
// 独立详情:兄弟路由 + showLink + activePath + keepAlive/moreTags,见 detail-page 三件套
|
|
48
48
|
],
|
|
49
49
|
} satisfies RouteConfigsTable;
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
### 抗略读
|
|
53
|
+
|
|
54
|
+
命中模块须照其**强制完整样板**落盘;样板中的字段默认写出。壳层行为(tag / 侧栏 / keep-alive)以路由 meta + 项目已有实现为准,不假设 Hook 会「全自动」。
|
|
55
|
+
|
|
52
56
|
### 权限
|
|
53
57
|
|
|
54
58
|
```vue
|
|
@@ -119,6 +123,8 @@ export function getCustomerList(data: CustomerQuery, url: string) {
|
|
|
119
123
|
|
|
120
124
|
### 独立功能页容器
|
|
121
125
|
|
|
126
|
+
定高且内部滚动(与列表卡同类场景):
|
|
127
|
+
|
|
122
128
|
```vue
|
|
123
129
|
<div
|
|
124
130
|
:style="{ height: `calc(100vh - 2 * var(--vts-margin) - ${headerHeight}px)` }"
|
|
@@ -126,6 +132,7 @@ export function getCustomerList(data: CustomerQuery, url: string) {
|
|
|
126
132
|
>
|
|
127
133
|
```
|
|
128
134
|
|
|
135
|
+
查询列表定高卡 → `crud-pages`(`el-card.vts-page-card` + `tableHeight`)。
|
|
129
136
|
## 六、资产分层
|
|
130
137
|
|
|
131
138
|
附加 Hook/组件按功能模块加载(WebSocket、微信、附件、图表等)→ 见各专项与 `project-inventory`。
|
package/references/crud-pages.md
CHANGED
|
@@ -9,6 +9,8 @@ tags: [vue3, crud, list, form, detail, table, useTableSearch, page, layout]
|
|
|
9
9
|
|
|
10
10
|
遵守 `core-kernel` / `http-api`。独立详情路由 → 同时加载 `detail-page`。回显 → `data-writeback`。
|
|
11
11
|
|
|
12
|
+
**抗略读**:列表页必须整段照抄「列表黄金样板」;有独立详情时 **同批** 落 `detail-page` 三件套(禁止只写 `toDetail`)。方法名固定 `onSearch` / `reset`。
|
|
13
|
+
|
|
12
14
|
## useTableSearch
|
|
13
15
|
|
|
14
16
|
```typescript
|
|
@@ -21,20 +23,29 @@ useTableSearch(formQuery, searchFn, url)
|
|
|
21
23
|
- 查询 / 重置:`onSearch()` / `reset()`
|
|
22
24
|
- 列表:`tableData.value.tableList`
|
|
23
25
|
- 分页请求:`pageNo` / `pageSize`;响应:`data.content` / `data.totalCount`
|
|
24
|
-
- 高度:`tableHeight
|
|
26
|
+
- 高度:`tableHeight` 由 Hook 按「卡片内容区底边 − 表格顶边 − 分页」实测;左右分栏、`--vts-card-padding`、工具栏、`otherRef`(表上方)均自动消化;空数据仍保留表格占位高度。业务页只绑定,不手算魔法数
|
|
27
|
+
|
|
28
|
+
## 内容区滚动约定
|
|
29
|
+
|
|
30
|
+
| 场景 | 做法 |
|
|
31
|
+
|------|------|
|
|
32
|
+
| 查询列表(定高) | `el-card.vts-page-card` + 固定 `height: calc(100vh - 2 * var(--vts-margin) - ${headerHeight}px)`;表格绑 `tableHeight`;**仅表格体内滚动**;分页在表格下方;整页无外层滚动条 |
|
|
33
|
+
| 树 + 表分栏 | 同上;左侧树、右侧表共用定高卡,高度仍走 `useTableSearch` 几何实测 |
|
|
34
|
+
| 长表单 / 详情 / 说明类 | 可用 `minHeight` 同公式;内容超出时由 `.app-main` 内 `el-scrollbar` 滚动 |
|
|
35
|
+
| Card 内边距 | 一律走 `--vts-card-padding`(桥接 `--card-padding`);换规范只改令牌,列表高度由 Hook 跟随 |
|
|
25
36
|
|
|
26
37
|
## 列表黄金样板(唯一完整示例)
|
|
27
38
|
|
|
28
39
|
| # | 必须 |
|
|
29
40
|
|---|------|
|
|
30
|
-
| L1 | `el-card` + `ref="content"`(禁止挂 `div`) |
|
|
41
|
+
| L1 | `el-card` + `class="vts-page-card"` + `ref="content"`(禁止挂 `div`) |
|
|
31
42
|
| L2 | 固定 `height: calc(100vh - 2 * var(--vts-margin) - ${headerHeight}px)`(禁止只用 `minHeight`) |
|
|
32
43
|
| L3 | 查询区 `bg-bg_color p-5`;展示区 `ReTableBar class="bg-bg_color"` |
|
|
33
44
|
| L4 | `ReGrid` `:gap="[0,20]"` + cols;表单项 `w-[100%] !mr-0`;`@should-show-collapse` |
|
|
34
45
|
| L5 | 操作列 `<ReGridItem suffix>` |
|
|
35
|
-
| L6 | 表格绑 `tableHeight`;分页在 `ReTableBar` `#default`
|
|
46
|
+
| L6 | 表格绑 `ref="multipleTableRef"` + `tableHeight`;分页在 `ReTableBar` `#default` 内、表格下方 |
|
|
36
47
|
| L7 | `RePagination`:`:pagination` + `@handle-current-change` / `@handle-size-change` |
|
|
37
|
-
| L8 |
|
|
48
|
+
| L8 | 查询与表之间的额外模块包一根元素绑 `otherRef`(须在表格上方,高度计入 `tableTop`) |
|
|
38
49
|
|
|
39
50
|
```vue
|
|
40
51
|
<script setup lang="ts">
|
|
@@ -112,6 +123,7 @@ function handleSizeChange(size: number) {
|
|
|
112
123
|
<div>
|
|
113
124
|
<el-card
|
|
114
125
|
ref="content"
|
|
126
|
+
class="vts-page-card"
|
|
115
127
|
shadow="never"
|
|
116
128
|
:style="{
|
|
117
129
|
height: `calc(100vh - 2 * var(--vts-margin) - ${headerHeight}px)`,
|
|
@@ -228,6 +240,8 @@ function handleSizeChange(size: number) {
|
|
|
228
240
|
|
|
229
241
|
## 列表 → 详情/编辑
|
|
230
242
|
|
|
243
|
+
有独立详情/编辑路由时:**必须同时命中并深读 `detail-page`**。禁止只抄下面的 `toDetail` 就交卷。
|
|
244
|
+
|
|
231
245
|
```typescript
|
|
232
246
|
import { useDetail } from "@/hooks/useDetail";
|
|
233
247
|
const { toDetail } = useDetail();
|
|
@@ -244,7 +258,24 @@ function onEdit(row: Customer, mark: "edit" | "view") {
|
|
|
244
258
|
}
|
|
245
259
|
```
|
|
246
260
|
|
|
247
|
-
|
|
261
|
+
**同批必落兄弟路由 meta**(完整三件套见 `detail-page`;此处不可省略):
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
{
|
|
265
|
+
path: "/customer/detail",
|
|
266
|
+
name: "CustomerDetail",
|
|
267
|
+
component: () => import("@/views/customer/detail/index.vue"),
|
|
268
|
+
meta: {
|
|
269
|
+
title: "客户详情",
|
|
270
|
+
showLink: false,
|
|
271
|
+
activePath: "/customer/list",
|
|
272
|
+
keepAlive: true,
|
|
273
|
+
moreTags: true,
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
详情页 `initToDetail` + `defineOptions({ name })` 对齐 → **`detail-page`**。
|
|
248
279
|
|
|
249
280
|
## 表单页
|
|
250
281
|
|
|
@@ -305,16 +336,17 @@ async function onSubmit() {
|
|
|
305
336
|
},
|
|
306
337
|
```
|
|
307
338
|
|
|
308
|
-
|
|
339
|
+
独立详情兄弟路由(含 `activePath` / `keepAlive` / `moreTags`)→ `detail-page`。禁止业务模块再挂 Layout。
|
|
309
340
|
|
|
310
341
|
## 反例(短表)
|
|
311
342
|
|
|
312
343
|
| 错误 | 正确 |
|
|
313
344
|
|------|------|
|
|
314
345
|
| `handleSearch` / 手写分页 | `onSearch` / `useTableSearch` |
|
|
315
|
-
| `ref="content"` 挂 div / 只用 minHeight | `el-card` + 固定 height |
|
|
316
|
-
| 不绑 `tableHeight` / 分页在卡片外 | 样板 L6/L7 |
|
|
346
|
+
| `ref="content"` 挂 div / 只用 minHeight / 缺 `vts-page-card` | `el-card.vts-page-card` + 固定 height |
|
|
347
|
+
| 不绑 `tableHeight` / 分页在卡片外 / 手写魔法数扣高度 | 样板 L6/L7;高度交给 `useTableSearch` |
|
|
317
348
|
| 额外模块不绑 `otherRef` | L8 |
|
|
318
|
-
|
|
|
349
|
+
| 只写 `toDetail`、详情路由缺 `activePath` | 三件套整段落盘(见 detail-page) |
|
|
350
|
+
| 裸 `router.push` 开详情 | `toDetail` + meta(见 detail-page) |
|
|
319
351
|
| `ReTableOperate :buttons` | `:list` |
|
|
320
352
|
| `@show-collapse` | `@should-show-collapse` |
|
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
> 按本文件示例编写,复用项目已有回显/回填约定与选择器回写方式,勿另起一套表单赋值实现。
|
|
4
4
|
|
|
5
|
+
**抗略读**:编辑回显**必须** `Object.assign(formData, res.data)`,禁止 `formData = res.data` 破坏响应式。提交按钮默认带 `loading`。
|
|
6
|
+
|
|
7
|
+
## 强制样板(编辑回显)
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
async function getDetail() {
|
|
11
|
+
const { id } = getParameter.value;
|
|
12
|
+
if (!id) return;
|
|
13
|
+
const res = await getDetailApi({ id });
|
|
14
|
+
if (res.status === 200 && res.data) Object.assign(formData, res.data);
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
5
18
|
## 表单回显
|
|
6
19
|
|
|
7
20
|
### 新增/编辑页
|
|
@@ -415,7 +415,8 @@ height: \d+px、padding: \d+px、font-size: \d+px、行内 style="...颜色 hex"
|
|
|
415
415
|
- [ ] 控件高度:input/button 计算高度 = 规范值(24/32/40 或规范预设)
|
|
416
416
|
- [ ] 圆角:input、button、card、dialog 均为规范圆角
|
|
417
417
|
- [ ] 表格:表头底色/文字色/字重符合规范
|
|
418
|
-
- [ ] 卡片内边距:`.el-card__body` =
|
|
418
|
+
- [ ] 卡片内边距:`.el-card__body` = 规范 `--vts-card-padding`(桥接 `--card-padding`)
|
|
419
|
+
- [ ] 定高列表页:`el-card.vts-page-card` + `useTableSearch` 的 `tableHeight`;换 `--card-padding` 后列表仍无外层滚动条、分页完整、仅表格体内滚动
|
|
419
420
|
- [ ] 表单标签:computed font-weight 为规范值(AntD/Semi = 400,非 700)
|
|
420
421
|
- [ ] 弹窗:`--ds-dialog-bg` 为 **主题色轻渐变**(`primary-bg → component-bg`),非写死蓝渐变;`ElMessageBox` 内容区用 `--message-box-content-padding`(比 `el-dialog` body 更紧凑)
|
|
421
422
|
- [ ] 侧栏:深色主题下 DevTools 检查 `.sidebar-container` computed `background` 为 **渐变**(非单色 `#001529`);激活项块色 = `--primary-6`;Logo 区 = `--sidebar-logo-bg`
|
|
@@ -608,6 +609,7 @@ height: \d+px、padding: \d+px、font-size: \d+px、行内 style="...颜色 hex"
|
|
|
608
609
|
5. `lay-content/index.vue`:`padding-top` 用 `--vts-layout-header-offset*`,禁止写死旧顶栏组合;**禁止**与 `$storage.configure.headerHeight` 双向联动
|
|
609
610
|
6. `lay-header`:布局/标签页变化须 `nextTick` 重测,且仅在高度变化时写回 `$storage.configure.headerHeight`
|
|
610
611
|
7. DevTools:顶栏 computed = **当前** `--header-height`;菜单项 = **当前** `--el-menu-item-height`(两者须不同)
|
|
612
|
+
8. 定高列表页:`--card-padding` / `--vts-card-padding` 变更后,抽查一页查询列表——内容区无外层滚动条、分页完整、`tableHeight` 随 padding 变化
|
|
611
613
|
|
|
612
614
|
#### 7.5.4 EP 菜单变量纪律
|
|
613
615
|
|
|
@@ -9,18 +9,13 @@ tags: [vue3, detail, toDetail, useDetail, activePath, showLink, multiTags, keepA
|
|
|
9
9
|
|
|
10
10
|
真相源:模版 `useDetail.ts`、`multiTags`、侧栏 `NavVertical`。列表打开独立路由页时按本文件落地。
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
**反认知偏差(必读)**:`toDetail` 只负责写顶部 tag 并跳转;**侧栏高亮靠 `meta.activePath`,缓存/多开靠 `meta.keepAlive` / `moreTags`**。三者缺一不可,禁止只写 `toDetail`。
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|------|------------|
|
|
16
|
-
| 不进左侧菜单 | 路由 `meta.showLink: false` |
|
|
17
|
-
| 顶部 tag(multiTags) | `useDetail().toDetail` → `handleTags('push')` |
|
|
18
|
-
| 侧栏高亮 | 路由 `meta.activePath` = 列表 path |
|
|
19
|
-
| 页面缓存 | `meta.keepAlive`;多开 tag 再加 `moreTags: true` |
|
|
14
|
+
## 详情三件套(强制完整样板 · 整段照抄再改名)
|
|
20
15
|
|
|
21
|
-
|
|
16
|
+
缺任一段 = 未完成。样板内字段**默认全部写出**(勿改成 `//` 注释再「按需打开」)。仅当业务明确不要缓存/多开时,才删掉对应行。
|
|
22
17
|
|
|
23
|
-
|
|
18
|
+
### ① 兄弟路由 meta
|
|
24
19
|
|
|
25
20
|
```typescript
|
|
26
21
|
{
|
|
@@ -31,36 +26,27 @@ tags: [vue3, detail, toDetail, useDetail, activePath, showLink, multiTags, keepA
|
|
|
31
26
|
title: "客户详情",
|
|
32
27
|
showLink: false,
|
|
33
28
|
activePath: "/customer/list",
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
keepAlive: true,
|
|
30
|
+
moreTags: true,
|
|
36
31
|
},
|
|
37
32
|
},
|
|
38
33
|
```
|
|
39
34
|
|
|
40
|
-
|
|
41
|
-
|------|------|
|
|
42
|
-
| `title` | 非空 |
|
|
43
|
-
| `showLink: false` | 必填 |
|
|
44
|
-
| `activePath` | = 列表 path |
|
|
45
|
-
| `name` | = `defineOptions({ name })` |
|
|
46
|
-
|
|
47
|
-
## 列表打开
|
|
35
|
+
### ② 列表页打开
|
|
48
36
|
|
|
49
37
|
```typescript
|
|
50
38
|
import { useDetail } from "@/hooks/useDetail";
|
|
51
39
|
const { toDetail } = useDetail();
|
|
52
40
|
|
|
53
41
|
toDetail("CustomerDetail", { webId: "0" }, "(新增)");
|
|
54
|
-
toDetail(
|
|
42
|
+
toDetail(
|
|
43
|
+
"CustomerDetail",
|
|
44
|
+
{ id: row.id, text: row.name, mark: "edit" },
|
|
45
|
+
`(编辑)【${row.name}】`,
|
|
46
|
+
);
|
|
55
47
|
```
|
|
56
48
|
|
|
57
|
-
|
|
58
|
-
toDetail(name, parameter, title?, model = "query") // model: "query" | "params"
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
写入 tag 时不要把路由上的 `showLink: false` 原样塞进 `handleTags` 的 meta。
|
|
62
|
-
|
|
63
|
-
## 详情页
|
|
49
|
+
### ③ 详情页初始化
|
|
64
50
|
|
|
65
51
|
```vue
|
|
66
52
|
<script setup lang="ts">
|
|
@@ -72,12 +58,36 @@ const { id, mark } = getParameter as DetailParameter;
|
|
|
72
58
|
</script>
|
|
73
59
|
```
|
|
74
60
|
|
|
75
|
-
|
|
61
|
+
## 概念
|
|
62
|
+
|
|
63
|
+
| 能力 | 字段 / API | 谁负责 |
|
|
64
|
+
|------|------------|--------|
|
|
65
|
+
| 不进左侧菜单 | `meta.showLink: false` | 路由 |
|
|
66
|
+
| 顶部 tag | `toDetail` → `handleTags('push')` | Hook |
|
|
67
|
+
| 侧栏高亮 | `meta.activePath` = 列表 path | 路由 |
|
|
68
|
+
| 页面缓存 / 多开 | `meta.keepAlive` + `moreTags: true` | 路由 |
|
|
69
|
+
|
|
70
|
+
`showLink` 只管侧栏是否显示,不控制顶部 tag。裸 `router.push` 只换路由、不写 tag。
|
|
71
|
+
|
|
72
|
+
| 字段 | 要求 |
|
|
73
|
+
|------|------|
|
|
74
|
+
| `title` | 非空 |
|
|
75
|
+
| `showLink: false` | 必填 |
|
|
76
|
+
| `activePath` | = 列表 path(必填) |
|
|
77
|
+
| `keepAlive` / `moreTags` | 默认 `true`;不要缓存/多开再删 |
|
|
78
|
+
| `name` | = `defineOptions({ name })` |
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
toDetail(name, parameter, title?, model = "query") // model: "query" | "params"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
写入 tag 时不要把路由上的 `showLink: false` 原样塞进 `handleTags` 的 meta。
|
|
85
|
+
|
|
86
|
+
`initToDetail` 标题:无 id → `(新增)`;`mark==='edit'` → `(编辑)【text】`;`view` → `(查看)【text】`。
|
|
76
87
|
|
|
77
88
|
## Must-do
|
|
78
89
|
|
|
79
|
-
1.
|
|
80
|
-
2.
|
|
81
|
-
3.
|
|
82
|
-
4.
|
|
83
|
-
5. 需缓存 / 多开时配 `keepAlive` / `moreTags`
|
|
90
|
+
1. 三件套整段落盘(路由 + `toDetail` + `initToDetail`)
|
|
91
|
+
2. `showLink: false` + `activePath` + 非空 `title` + 默认 `keepAlive`/`moreTags`
|
|
92
|
+
3. 列表只用 `toDetail`,禁止裸 `router.push`
|
|
93
|
+
4. 详情页必调 `initToDetail`;`name` 对齐;参数用 `getParameter`
|
|
@@ -4,6 +4,26 @@
|
|
|
4
4
|
|
|
5
5
|
规范文件下载、模板下载、文件流导出与附件预览。在需要下载文件、导出表格或预览附件时参照。
|
|
6
6
|
|
|
7
|
+
**抗略读**:导出/下载 API **必须**带 `responseType: "blob"`(默认写出,勿当可选项注释掉);前端用 `blobDown` / 项目已有 `download*`,禁止手写 `URL.createObjectURL` 另起一套(除非仓库无封装)。
|
|
8
|
+
|
|
9
|
+
## 强制样板(导出)
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
// api
|
|
13
|
+
export function exportExcel(data: Recordable) {
|
|
14
|
+
return http.request<Result<Blob>>(
|
|
15
|
+
"post",
|
|
16
|
+
`${import.meta.env.VITE_API_BASE_URL}/xxx/export`,
|
|
17
|
+
{ data },
|
|
18
|
+
{ responseType: "blob" },
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 页面
|
|
23
|
+
const res = await exportExcel(params);
|
|
24
|
+
blobDown(res.data, "导出.xlsx", res);
|
|
25
|
+
```
|
|
26
|
+
|
|
7
27
|
## 常用工具
|
|
8
28
|
|
|
9
29
|
项目集成了 `@pureadmin/utils` 与自定义工具:
|
|
@@ -4,6 +4,25 @@
|
|
|
4
4
|
|
|
5
5
|
规范系统 Loading、Message、MessageBox、NoticeBar 等反馈组件的使用。在需要提示用户或阻塞操作时参照。
|
|
6
6
|
|
|
7
|
+
**抗略读**:删除/危险操作**默认写出** `ElMessageBox.confirm`;列表请求接 `v-loading`;提交默认 `loading` 防重复。提示文案一律 `$t()`。
|
|
8
|
+
|
|
9
|
+
## 强制样板(删除确认)
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { ElMessageBox } from "element-plus";
|
|
13
|
+
import { message } from "@/utils/message";
|
|
14
|
+
|
|
15
|
+
async function onDelete(row: { id: string }) {
|
|
16
|
+
await ElMessageBox.confirm($t("确定删除吗?"), $t("温馨提醒"), {
|
|
17
|
+
confirmButtonText: $t("确定"),
|
|
18
|
+
cancelButtonText: $t("取消"),
|
|
19
|
+
type: "warning",
|
|
20
|
+
});
|
|
21
|
+
// await deleteApi({ id: row.id })
|
|
22
|
+
message($t("删除成功"), { type: "success" });
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
7
26
|
## Loading
|
|
8
27
|
|
|
9
28
|
### 局部 Loading
|
|
@@ -10,6 +10,8 @@ tags: [form, dialog, ReDialog, ReDialogResize, ReSelectQuery, ReCascader, iconPi
|
|
|
10
10
|
> 核心选择器与 CRUD 列表筛选项高频相关。
|
|
11
11
|
> **弹窗**:业务弹窗统一用 `ReDialog` / `ReDialogResize`,禁止业务页直接堆裸 `el-dialog`(除非用户明确要求)。
|
|
12
12
|
|
|
13
|
+
**抗略读**:弹窗走项目 `ReDialog` 黄金样板(含销毁/禁点遮罩等默认项),勿降级为裸 `el-dialog`。远程下拉用 `ReSelectQuery` 真实 props(`url`/`value`/`label`/`edit-data`),禁止臆造 `:api`。
|
|
14
|
+
|
|
13
15
|
## 依赖(缺则先装)
|
|
14
16
|
|
|
15
17
|
按用到的能力安装(先查 `package.json`):
|
package/references/http-api.md
CHANGED
|
@@ -9,6 +9,31 @@ tags: [axios, http, api, encryption, rsa, aes, download, request]
|
|
|
9
9
|
|
|
10
10
|
> 实现落点:`src/utils/http.ts`、`src/api/**`、全局 `Result<T>`。
|
|
11
11
|
|
|
12
|
+
**抗略读**:接口文件须整段按下方「强制样板」落盘;禁止组件内直接 `axios`/`fetch`。加解密靠 `VITE_ENCODE_SWITCH`,禁止臆造单请求 `crypto: true`。下载接口**默认写出** `responseType: "blob"`(勿注释掉)。
|
|
13
|
+
|
|
14
|
+
## 强制样板(新建 API 照抄)
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { http } from "@/utils/http";
|
|
18
|
+
|
|
19
|
+
export function getCustomerList(data: CustomerQuery) {
|
|
20
|
+
return http.request<Result<CustomerPage>>(
|
|
21
|
+
"post",
|
|
22
|
+
`${import.meta.env.VITE_API_BASE_URL}/customer/list`,
|
|
23
|
+
{ data },
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function downloadCustomer(data: Recordable) {
|
|
28
|
+
return http.request<Result<Blob>>(
|
|
29
|
+
"post",
|
|
30
|
+
`${import.meta.env.VITE_API_BASE_URL}/customer/export`,
|
|
31
|
+
{ data },
|
|
32
|
+
{ responseType: "blob" },
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
12
37
|
## Http 封装架构
|
|
13
38
|
|
|
14
39
|
项目使用自定义 `Http` 类封装 Axios,位于 `src/utils/http.ts`。核心特性:
|
package/references/icons.md
CHANGED
|
@@ -11,6 +11,18 @@ tags: [vue3, icon, svg-icon, ReSvgIcon, ReIconPicker, iconify, ep, ri, unocss, m
|
|
|
11
11
|
> **真相源**:`src/components/ReSvgIcon`、`src/components/ReIconPicker`、`src/icons/svg`、`main.ts`、`uno.config.ts`、`build/plugins/SvgSpriteLoader.ts` / `SvgLoader.ts`。
|
|
12
12
|
> 选型表见 `project-inventory`「图标」节;勿另起 IconFont / 未约定的图标库。
|
|
13
13
|
|
|
14
|
+
**抗略读**:新建菜单/父级路由时 **`meta.icon` 默认写出**(如 `ep:user`),禁止交无图标菜单。页面内优先 `<svg-icon name="..." />`,勿散落未约定图标库。
|
|
15
|
+
|
|
16
|
+
## 强制样板(菜单 icon)
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
meta: { title: "客户管理", icon: "ep:user", rank: 10 }
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```vue
|
|
23
|
+
<svg-icon name="ep:search" />
|
|
24
|
+
```
|
|
25
|
+
|
|
14
26
|
---
|
|
15
27
|
|
|
16
28
|
## 依赖(core,模板已装)
|
|
@@ -320,6 +320,17 @@ src/layout/
|
|
|
320
320
|
| 重测 | 切换 `layout`、`hideTabs`、`hiddenSideBar` 后 `nextTick` 再测一次(避免布局切换后仍用 localStorage 旧值) |
|
|
321
321
|
| 消费 | 业务页通过 `useApp().headerHeight` 读 `$storage.configure.headerHeight`;`lay-content` 的 `padding-top` 仍用 `--vts-layout-header-offset*`(勿与 storage 双向绑定,避免重测循环) |
|
|
322
322
|
|
|
323
|
+
### 内容区高度与滚动
|
|
324
|
+
|
|
325
|
+
| 场景 | 卡片 / 高度 | 滚动落点 |
|
|
326
|
+
|------|-------------|----------|
|
|
327
|
+
| 查询列表 | `el-card.vts-page-card` + 固定 `calc(100vh - 2 * var(--vts-margin) - ${headerHeight}px)`;表格绑 `useTableSearch().tableHeight` | 仅 `el-table` 体内;分页在表格下方 |
|
|
328
|
+
| 树 + 表分栏 | 同上定高卡;左右并排,高度走 Hook 几何实测 | 同查询列表 |
|
|
329
|
+
| 长表单 / 详情 / 说明 | 同公式可用 `minHeight`;不绑 `tableHeight` | `.app-main` 内 `el-scrollbar` |
|
|
330
|
+
| Card 内边距 | `--vts-card-padding` → `--card-padding` | 换规范只改令牌;列表高度由 Hook 实测跟随 |
|
|
331
|
+
|
|
332
|
+
`.vts-page-card`:`overflow: hidden`,`.el-card__body` 高度 100%。样式在 `element-plus.scss`。
|
|
333
|
+
|
|
323
334
|
### 混合布局路由结构
|
|
324
335
|
|
|
325
336
|
混合模式(mix)左侧栏只展示**一级**菜单,页面组件须挂在 **`children`** 下:
|
|
@@ -7,6 +7,20 @@ tags: [vue3, permission, auth, directive, hooks, v-auth, role, access-control]
|
|
|
7
7
|
|
|
8
8
|
# 权限控制与自定义指令
|
|
9
9
|
|
|
10
|
+
**抗略读**:有权限需求时,`meta.roles` 与 `v-auth`/`ReAuth` **默认写出**(勿注释成可选项)。禁止 `v-if="roles.includes(...)"` 手写角色判断。
|
|
11
|
+
|
|
12
|
+
## 强制样板(页面 + 按钮)
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
// 路由:roles 默认写出
|
|
16
|
+
meta: { title: "用户管理", roles: ["admin", "common"] }
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```vue
|
|
20
|
+
<el-button v-auth="['admin']" @click="onDelete">{{ $t("删除") }}</el-button>
|
|
21
|
+
<ReAuth :value="['admin']"><!-- 区域级 --></ReAuth>
|
|
22
|
+
```
|
|
23
|
+
|
|
10
24
|
## 权限体系概览
|
|
11
25
|
|
|
12
26
|
项目权限分为三个层级:
|
|
@@ -33,7 +47,7 @@ export default {
|
|
|
33
47
|
component: () => import("@/views/system/user/index.vue"),
|
|
34
48
|
meta: {
|
|
35
49
|
title: "用户管理",
|
|
36
|
-
roles: ["admin", "editor"],
|
|
50
|
+
roles: ["admin", "editor"],
|
|
37
51
|
},
|
|
38
52
|
},
|
|
39
53
|
{
|
|
@@ -42,7 +56,7 @@ export default {
|
|
|
42
56
|
component: () => import("@/views/system/config/index.vue"),
|
|
43
57
|
meta: {
|
|
44
58
|
title: "系统配置",
|
|
45
|
-
roles: ["admin"],
|
|
59
|
+
roles: ["admin"],
|
|
46
60
|
},
|
|
47
61
|
},
|
|
48
62
|
],
|
|
@@ -220,7 +220,7 @@
|
|
|
220
220
|
| **useApp** | 全局应用状态(布局、字典、登出等) | `baseCodeGet(codeType)`、`filterValue()`、`headerHeight`、`svgLoading` |
|
|
221
221
|
| **useDetail** | 列表→详情:写顶部 tag 并跳转 | `toDetail(name, params, title?, 'query'\|'params')`、`initToDetail(name)`、`getParameter`;路由配 `showLink:false`(不进侧栏)+`activePath`(见 `detail-page`) |
|
|
222
222
|
| **useFormCheck** | 多表单校验聚合 | 追踪各字段校验状态,emit `form-validate` 事件 |
|
|
223
|
-
| **useTableSearch** | 列表页搜索/分页/Loading/动态表高 | `content`(须绑 `el-card`)、`
|
|
223
|
+
| **useTableSearch** | 列表页搜索/分页/Loading/动态表高 | `content`(须绑 `el-card.vts-page-card`)、`multipleTableRef`(建议绑 `el-table`)、`otherRef`(表上方额外模块)、`tableHeight`(卡片底边 − 表格顶边 − 分页;空数据仍有占位高)、`paginationRef`、`tableData`、`pagination`、`loading`、`onSearch()`、`reset()`、`formRef`、`gridRef`、`collapsed` / `showCollapse` / `collapsedToggle` |
|
|
224
224
|
| **useTags** | 多标签页管理 | 右键菜单(刷新/关闭/关闭其他/全屏) |
|
|
225
225
|
| **useTheme** | 主题切换(暗色/亮色) | 主题色生成、布局预设、缓存重置 |
|
|
226
226
|
| **useWebSocket** | WebSocket 通信 | `subscribe()`、`send()`、`sendRaw()`、`isConnected` |
|