@qilitt-mickey/vue3-temp-skill 1.1.11 → 1.1.13
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 +22 -63
- package/SKILL.md +114 -273
- package/package.json +1 -1
- package/references/api-check.md +33 -313
- package/references/code-quality.md +63 -277
- package/references/core-kernel.md +76 -396
- package/references/crud-pages.md +252 -93
- package/references/data-writeback.md +2 -2
- package/references/design-handoff.md +92 -0
- package/references/design-system.md +70 -60
- package/references/detail-page.md +55 -72
- package/references/form-advanced.md +1 -2
- package/references/layout-theme.md +103 -180
- package/references/mobile-h5.md +11 -11
- package/references/project-inventory.md +9 -10
- package/references/table-vxe.md +7 -13
- package/references/tree-table.md +2 -2
- package/references/websocket-realtime.md +3 -3
|
@@ -1,49 +1,42 @@
|
|
|
1
1
|
---
|
|
2
2
|
skill: core-kernel
|
|
3
|
-
description:
|
|
3
|
+
description: 始终加载的架构内核。硬约束、应用壳摘要、样式契约、工程摘要。业务开发前必读。
|
|
4
4
|
scope: project
|
|
5
5
|
tags: [vue3, kernel, conventions, layout, router, http, crud, inventory]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# 核心内核(core-kernel)
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
> Vite / 包管理 / 入口启动链 **不是**独立 Skill,仅在本文件做只读摘要。
|
|
12
|
-
> 完整库与组件清单见同目录 `project-inventory.md`(一并查阅)。
|
|
10
|
+
始终加载。库/组件/安装表见 `project-inventory.md`(按需)。列表完整样板见 `crud-pages`;详情跳转见 `detail-page`;HTTP 细节见 `http-api`。
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## 一、硬约束(违反即不合格)
|
|
12
|
+
## 一、硬约束
|
|
18
13
|
|
|
19
14
|
| # | 约定 |
|
|
20
15
|
|---|------|
|
|
21
|
-
| 1 | HTTP 只用 `import { http } from '@/utils/http'
|
|
22
|
-
| 2 |
|
|
23
|
-
| 3 |
|
|
16
|
+
| 1 | HTTP 只用 `import { http } from '@/utils/http'` |
|
|
17
|
+
| 2 | 响应用全局 **`Result<T>`**(`status` / `statusText` / `data`) |
|
|
18
|
+
| 3 | 方法跟后端文档,**允许 GET / POST**;POST → `data`,GET → `params` |
|
|
24
19
|
| 4 | 列表用 `useTableSearch`,方法名 **`onSearch` / `reset`** |
|
|
25
|
-
| 5 |
|
|
26
|
-
| 6 |
|
|
27
|
-
| 7 |
|
|
28
|
-
| 8 |
|
|
29
|
-
| 9 |
|
|
30
|
-
| 10 |
|
|
31
|
-
| 11 |
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
## 二、应用壳(架构整体)
|
|
20
|
+
| 5 | 业务路由 **禁止** 再挂 `component: Layout` |
|
|
21
|
+
| 6 | 独立详情/编辑:路由与跳转按 **`detail-page`**(`showLink` / `activePath` / `toDetail` / `initToDetail`) |
|
|
22
|
+
| 7 | 页面权限 `meta.roles`;按钮 `v-auth` / `ReAuth` |
|
|
23
|
+
| 8 | 环境只用 `import.meta.env.VITE_*` |
|
|
24
|
+
| 9 | i18n:`$t('中文key')` |
|
|
25
|
+
| 10 | 禁止用 `v-html` 渲染不可信内容 |
|
|
26
|
+
| 11 | 新依赖须用户确认;已有封装须复用;选型表指定库勿擅自替换 |
|
|
27
|
+
| 12 | 列表布局按 **`crud-pages` 黄金样板**(`el-card.vts-page-card`+`content`+固定 height、`tableHeight`、`otherRef`、分页在 ReTableBar 内;仅表格体内滚动) |
|
|
28
|
+
| 13 | addon 按 `project-inventory` 第九节精确版本安装;禁止 `@latest` |
|
|
29
|
+
| 14 | 样式契约见下文「样式契约」 |
|
|
30
|
+
|
|
31
|
+
## 二、应用壳
|
|
38
32
|
|
|
39
33
|
### 路由
|
|
40
34
|
|
|
41
35
|
```typescript
|
|
42
|
-
// src/router/modules/xxx.ts
|
|
43
36
|
export default {
|
|
44
37
|
path: "/xxx",
|
|
45
38
|
redirect: "/xxx/list",
|
|
46
|
-
meta: { title: "客户管理", icon: "ep:user", rank: 10 },
|
|
39
|
+
meta: { title: "客户管理", icon: "ep:user", rank: 10 },
|
|
47
40
|
children: [
|
|
48
41
|
{
|
|
49
42
|
path: "/xxx/list",
|
|
@@ -51,9 +44,9 @@ export default {
|
|
|
51
44
|
component: () => import("@/views/xxx/list/index.vue"),
|
|
52
45
|
meta: { title: "客户列表", roles: ["admin", "common"] },
|
|
53
46
|
},
|
|
47
|
+
// 独立详情:兄弟路由 + showLink/activePath,完整约定见 detail-page
|
|
54
48
|
],
|
|
55
49
|
} satisfies RouteConfigsTable;
|
|
56
|
-
// ❌ 不要在业务模块根上再挂 Layout
|
|
57
50
|
```
|
|
58
51
|
|
|
59
52
|
### 权限
|
|
@@ -63,418 +56,105 @@ export default {
|
|
|
63
56
|
<ReAuth :value="['admin']"><!-- 区域 --></ReAuth>
|
|
64
57
|
```
|
|
65
58
|
|
|
66
|
-
### Store /
|
|
59
|
+
### Store / 主题
|
|
67
60
|
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
- 主题:`useTheme` + `--vts-*`
|
|
71
|
-
|
|
72
|
-
---
|
|
61
|
+
- Store:`user` / `app` / `setting` / `theme` / `lang` / `router` / `multiTags` / `baseCode`
|
|
62
|
+
- 顶部 tag + 详情跳转:`useDetail` → `detail-page`
|
|
63
|
+
- 主题:`useTheme` + `--vts-*` → `layout-theme`
|
|
73
64
|
|
|
74
65
|
## 三、数据通道
|
|
75
66
|
|
|
76
67
|
```typescript
|
|
77
68
|
import { http } from "@/utils/http";
|
|
78
69
|
|
|
79
|
-
/** 分页列表 — 可被 useTableSearch 作为 searchFn */
|
|
80
70
|
export function getCustomerList(data: CustomerQuery, url: string) {
|
|
81
71
|
return http.request<Result<CustomerPage>>("post", url, { data });
|
|
82
72
|
}
|
|
83
|
-
|
|
84
|
-
/** 详情 */
|
|
85
|
-
export function getCustomerDetail(data: { id: string }) {
|
|
86
|
-
return http.request<Result<Customer>>(
|
|
87
|
-
"post",
|
|
88
|
-
`${import.meta.env.VITE_API_BASE_URL}/console/customer/detail`,
|
|
89
|
-
{ data },
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
73
|
```
|
|
93
74
|
|
|
94
|
-
-
|
|
95
|
-
- 加解密由 `VITE_ENCODE_SWITCH` 全局控制(**无**单请求 `crypto: true`),细节见 `http-api`
|
|
96
|
-
- 字典:`useApp().baseCodeGet` / `filterValue`,见 `base-code-dict`
|
|
97
|
-
- 提示:`import { message } from '@/utils/message'`
|
|
98
|
-
|
|
99
|
-
---
|
|
75
|
+
细则:`http-api`。字典:`base-code-dict`。提示:`import { message } from '@/utils/message'`。
|
|
100
76
|
|
|
101
|
-
## 四、CRUD
|
|
102
|
-
|
|
103
|
-
### 核心 Hook
|
|
104
|
-
|
|
105
|
-
| Hook | 用途 |
|
|
106
|
-
|------|------|
|
|
107
|
-
| `useApp` | headerHeight、字典、svgLoading 等 |
|
|
108
|
-
| `useTableSearch` | 列表查询分页(`onSearch`/`reset`) |
|
|
109
|
-
| `useDetail` | 详情跳转与参数 |
|
|
110
|
-
| `useFormCheck` | 多表单校验聚合 |
|
|
111
|
-
| `useTags` / `useTheme` | 标签 / 主题 |
|
|
77
|
+
## 四、CRUD 积木
|
|
112
78
|
|
|
113
|
-
|
|
79
|
+
| Hook | 用途 | 详例 |
|
|
80
|
+
|------|------|------|
|
|
81
|
+
| `useApp` | headerHeight、字典、svgLoading | — |
|
|
82
|
+
| `useTableSearch` | 列表查询分页 | `crud-pages` |
|
|
83
|
+
| `useDetail` | 详情跳转与顶部 tag | `detail-page` |
|
|
84
|
+
| `useFormCheck` | 多表单校验 | `data-writeback` |
|
|
114
85
|
|
|
115
|
-
ReAuth、ReDialog、ReGrid、ReGridItem、RePagination、ReTableBar、ReTableOperate、ReHeaderPage、ReSvgIcon
|
|
86
|
+
核心 Re*:ReAuth、ReDialog、ReGrid、ReGridItem、RePagination、ReTableBar、ReTableOperate、ReHeaderPage、ReSvgIcon、ReText、ReLanguageSwitch、ReSegmented、ReSelectQuery、ReCascader、ReDatePicker、ReDateRangePicker、ReCollapsible
|
|
116
87
|
|
|
117
|
-
|
|
88
|
+
弹窗完整示例 → `form-advanced`。列表页完整示例 → `crud-pages`。
|
|
118
89
|
|
|
119
|
-
|
|
90
|
+
## 五、样式契约
|
|
120
91
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
#### 布局硬约束(违反即不合格)
|
|
124
|
-
|
|
125
|
-
| # | 必须 | 说明 |
|
|
126
|
-
|---|------|------|
|
|
127
|
-
| L1 | `el-card` + `ref="content"` | `useTableSearch` 通过 `content.$el` 算高度;`ref` 必须挂在 **组件**(`el-card`)上,禁止挂在原生 `div` |
|
|
128
|
-
| L2 | 卡片用固定 **`height`** | `height: calc(100vh - 2 * var(--vts-margin) - ${headerHeight}px)`;**禁止**只写 `minHeight`(否则 `tableHeight` 算不准,表格无法撑满) |
|
|
129
|
-
| L3 | 查询区与展示区分开 | 查询:`el-form` + `class="bg-bg_color p-5"`;展示:`ReTableBar class="bg-bg_color"`;两区视觉分离 |
|
|
130
|
-
| L4 | `ReGrid` 间距与栅格 | `:gap="[0, 20]"` + `:cols="{ xs: 1, sm: 2, md: 2, lg: 3, xl: 4 }"`;表单项 `class="w-[100%] !mr-0"`;事件为 `@should-show-collapse` |
|
|
131
|
-
| L5 | 操作按钮用 `suffix` | `<ReGridItem suffix>`,勿用随意 `index=99` 冒充后缀列 |
|
|
132
|
-
| L6 | 表格动态高度 | `:style="{ height: \`${tableHeight}px\` }"`;分页 **必须在** `ReTableBar` 的 `#default` 内、表格下方,保证空数据时仍占满剩余高度 |
|
|
133
|
-
| L7 | `RePagination` 真实 API | `:pagination="pagination"` + `@handle-current-change` / `@handle-size-change`;**禁止**虚构的 `v-model:current-page` |
|
|
134
|
-
| L8 | 查询条件之外的模块必须绑 `otherRef` | 卡片内除查询表单、表格+分页外还有任何模块(统计块/页签/提示条/子面板等),外层包一个根元素并 `ref="otherRef"`;`tableHeight` 会自动减去它的高度,不绑则表格高度算错(溢出或被压扁)。多个模块合并进**一个**根容器,禁止逐个散落 |
|
|
135
|
-
|
|
136
|
-
```vue
|
|
137
|
-
<script setup lang="ts">
|
|
138
|
-
import type { OperateButton } from "@/components/ReTableOperate";
|
|
139
|
-
import type { Customer, CustomerQuery } from "@/api/customer";
|
|
140
|
-
import { getCustomerList } from "@/api/customer";
|
|
141
|
-
import { ReGrid } from "@/components/ReGrid";
|
|
142
|
-
import { ReGridItem } from "@/components/ReGridItem";
|
|
143
|
-
import { RePagination } from "@/components/RePagination";
|
|
144
|
-
import { ReTableBar } from "@/components/ReTableBar";
|
|
145
|
-
import { ReTableOperate } from "@/components/ReTableOperate";
|
|
146
|
-
import { useApp } from "@/hooks/useApp";
|
|
147
|
-
import { useTableSearch } from "@/hooks/useTableSearch";
|
|
148
|
-
import { message } from "@/utils/message";
|
|
149
|
-
|
|
150
|
-
defineOptions({ name: "CustomerList" });
|
|
151
|
-
|
|
152
|
-
const { headerHeight, svgLoading } = useApp();
|
|
153
|
-
const formQuery = reactive<CustomerQuery>({ keyword: "", status: undefined });
|
|
154
|
-
|
|
155
|
-
const {
|
|
156
|
-
content,
|
|
157
|
-
otherRef,
|
|
158
|
-
tableHeight,
|
|
159
|
-
paginationRef,
|
|
160
|
-
loading,
|
|
161
|
-
formRef,
|
|
162
|
-
multipleTableRef,
|
|
163
|
-
pagination,
|
|
164
|
-
onSearch,
|
|
165
|
-
tableData,
|
|
166
|
-
gridRef,
|
|
167
|
-
showCollapse,
|
|
168
|
-
collapsed,
|
|
169
|
-
collapsedToggle,
|
|
170
|
-
upBold,
|
|
171
|
-
downBold,
|
|
172
|
-
reset,
|
|
173
|
-
} = useTableSearch(
|
|
174
|
-
formQuery,
|
|
175
|
-
getCustomerList,
|
|
176
|
-
`${import.meta.env.VITE_API_BASE_URL}/console/customer/list`,
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
const tableList = computed(() => tableData.value.tableList as Customer[]);
|
|
180
|
-
|
|
181
|
-
const operateButtons: OperateButton[] = [
|
|
182
|
-
{
|
|
183
|
-
label: $t("删除"),
|
|
184
|
-
type: "danger",
|
|
185
|
-
icon: "i-ep:delete",
|
|
186
|
-
onClick: (row) => handleDelete(row as Customer),
|
|
187
|
-
},
|
|
188
|
-
];
|
|
189
|
-
|
|
190
|
-
onMounted(() => {
|
|
191
|
-
onSearch();
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
function handleDelete(row: Customer) {
|
|
195
|
-
message($t("删除成功"), { type: "success" });
|
|
196
|
-
onSearch();
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function handleCurrentChange(cur: number) {
|
|
200
|
-
pagination.currentPage = cur;
|
|
201
|
-
onSearch();
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function handleSizeChange(size: number) {
|
|
205
|
-
pagination.pageSize = size;
|
|
206
|
-
onSearch();
|
|
207
|
-
}
|
|
208
|
-
</script>
|
|
209
|
-
|
|
210
|
-
<template>
|
|
211
|
-
<div>
|
|
212
|
-
<!-- L1/L2:ref=content 必须在 el-card;用 height 非 minHeight -->
|
|
213
|
-
<el-card
|
|
214
|
-
ref="content"
|
|
215
|
-
shadow="never"
|
|
216
|
-
:style="{
|
|
217
|
-
height: `calc(100vh - 2 * var(--vts-margin) - ${headerHeight}px)`,
|
|
218
|
-
}"
|
|
219
|
-
>
|
|
220
|
-
<!-- L3:查询区独立背景与内边距(formRef 高度自动参与 tableHeight 计算) -->
|
|
221
|
-
<div>
|
|
222
|
-
<el-form
|
|
223
|
-
ref="formRef"
|
|
224
|
-
:inline="true"
|
|
225
|
-
:model="formQuery"
|
|
226
|
-
class="bg-bg_color p-5"
|
|
227
|
-
>
|
|
228
|
-
<!-- L4:gap + cols;事件名 should-show-collapse -->
|
|
229
|
-
<ReGrid
|
|
230
|
-
ref="gridRef"
|
|
231
|
-
:collapsed="collapsed"
|
|
232
|
-
:gap="[0, 20]"
|
|
233
|
-
:cols="{ xs: 1, sm: 2, md: 2, lg: 3, xl: 4 }"
|
|
234
|
-
style="max-height: 300px; overflow-y: auto;"
|
|
235
|
-
@should-show-collapse="(val) => (showCollapse = val)"
|
|
236
|
-
>
|
|
237
|
-
<ReGridItem index="0">
|
|
238
|
-
<el-form-item :label="$t('关键词')" prop="keyword" class="w-[100%] !mr-0">
|
|
239
|
-
<el-input
|
|
240
|
-
v-model="formQuery.keyword"
|
|
241
|
-
clearable
|
|
242
|
-
:placeholder="$t('请输入')"
|
|
243
|
-
/>
|
|
244
|
-
</el-form-item>
|
|
245
|
-
</ReGridItem>
|
|
246
|
-
<ReGridItem index="1">
|
|
247
|
-
<el-form-item :label="$t('状态')" prop="status" class="w-[100%] !mr-0">
|
|
248
|
-
<el-select v-model="formQuery.status" clearable :placeholder="$t('请选择')">
|
|
249
|
-
<el-option :label="$t('启用')" :value="1" />
|
|
250
|
-
<el-option :label="$t('禁用')" :value="0" />
|
|
251
|
-
</el-select>
|
|
252
|
-
</el-form-item>
|
|
253
|
-
</ReGridItem>
|
|
254
|
-
<!-- L5:操作列用 suffix -->
|
|
255
|
-
<ReGridItem suffix>
|
|
256
|
-
<div class="flex flex-end">
|
|
257
|
-
<el-button
|
|
258
|
-
type="primary"
|
|
259
|
-
:loading="loading"
|
|
260
|
-
@click="pagination.currentPage = 1; pagination.pageSize = 10; onSearch()"
|
|
261
|
-
>
|
|
262
|
-
{{ $t("查询") }}
|
|
263
|
-
</el-button>
|
|
264
|
-
<el-button @click="reset">
|
|
265
|
-
{{ $t("重置") }}
|
|
266
|
-
</el-button>
|
|
267
|
-
<el-button
|
|
268
|
-
v-if="showCollapse"
|
|
269
|
-
type="primary"
|
|
270
|
-
link
|
|
271
|
-
class="!font-size-12"
|
|
272
|
-
@click="collapsedToggle"
|
|
273
|
-
>
|
|
274
|
-
{{ collapsed ? $t("展开") : $t("收起") }}
|
|
275
|
-
<el-icon class="el-icon--right">
|
|
276
|
-
<component :is="collapsed ? downBold : upBold" />
|
|
277
|
-
</el-icon>
|
|
278
|
-
</el-button>
|
|
279
|
-
</div>
|
|
280
|
-
</ReGridItem>
|
|
281
|
-
</ReGrid>
|
|
282
|
-
</el-form>
|
|
283
|
-
</div>
|
|
284
|
-
|
|
285
|
-
<!-- L8:查询条件以外的模块统一包一个根元素绑 otherRef(无额外模块时整段删除);
|
|
286
|
-
tableHeight 公式会自动减去它的高度:
|
|
287
|
-
content 高 − formRef 高 − paginationRef 高 − otherRef 高 − 50;
|
|
288
|
-
模块自身间距写在内部内容上,根容器保持零高度余量 -->
|
|
289
|
-
<div ref="otherRef">
|
|
290
|
-
<!-- 统计/页签/提示等额外模块放这里 -->
|
|
291
|
-
</div>
|
|
292
|
-
|
|
293
|
-
<!-- L3/L6:展示区在 ReTableBar 内;表格+分页同槽,保证空数据也撑满 -->
|
|
294
|
-
<ReTableBar class="bg-bg_color" :columns="[]" @refresh="onSearch">
|
|
295
|
-
<template #title>
|
|
296
|
-
<span class="truncate font-size-16 font-bold">{{ $t("展示列表") }}</span>
|
|
297
|
-
</template>
|
|
298
|
-
<template #buttons>
|
|
299
|
-
<el-button type="primary" v-auth="['admin']">
|
|
300
|
-
{{ $t("新增") }}
|
|
301
|
-
</el-button>
|
|
302
|
-
</template>
|
|
303
|
-
<template #default="{ size }">
|
|
304
|
-
<div class="vl-parent">
|
|
305
|
-
<el-table
|
|
306
|
-
ref="multipleTableRef"
|
|
307
|
-
v-loading.lock="loading"
|
|
308
|
-
:element-loading-text="$t('加载中')"
|
|
309
|
-
:element-loading-spinner="svgLoading"
|
|
310
|
-
element-loading-svg-view-box="0, 0, 20, 20"
|
|
311
|
-
:style="{ height: `${tableHeight}px` }"
|
|
312
|
-
:size="size"
|
|
313
|
-
:data="tableList"
|
|
314
|
-
:header-cell-style="{
|
|
315
|
-
background: 'var(--el-fill-color-light)',
|
|
316
|
-
color: 'var(--el-text-color-primary)',
|
|
317
|
-
}"
|
|
318
|
-
row-key="id"
|
|
319
|
-
>
|
|
320
|
-
<el-table-column prop="code" :label="$t('编号')" min-width="120" />
|
|
321
|
-
<el-table-column prop="name" :label="$t('名称')" min-width="140" />
|
|
322
|
-
<el-table-column :label="$t('操作')" width="160" fixed="right">
|
|
323
|
-
<template #default="{ row, $index }">
|
|
324
|
-
<ReTableOperate :list="operateButtons" :row="row" :index="$index" />
|
|
325
|
-
</template>
|
|
326
|
-
</el-table-column>
|
|
327
|
-
</el-table>
|
|
328
|
-
|
|
329
|
-
<!-- L7:真实分页 API;ref=paginationRef 参与 tableHeight 计算 -->
|
|
330
|
-
<RePagination
|
|
331
|
-
ref="paginationRef"
|
|
332
|
-
:size="size"
|
|
333
|
-
:pagination="pagination"
|
|
334
|
-
@handle-current-change="handleCurrentChange"
|
|
335
|
-
@handle-size-change="handleSizeChange"
|
|
336
|
-
/>
|
|
337
|
-
</div>
|
|
338
|
-
</template>
|
|
339
|
-
</ReTableBar>
|
|
340
|
-
</el-card>
|
|
341
|
-
</div>
|
|
342
|
-
</template>
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
`useTableSearch(formQuery, searchFn, url)`:`searchFn` 签名为 `(query, url) => Promise<Result<T>>`,分页字段为 `pageNo` / `pageSize`,列表数据取 `data.content`,总数 `data.totalCount`。返回值中的 `content` / `tableHeight` / `paginationRef` / `formRef` 必须按样板绑定,否则动态高度失效。
|
|
346
|
-
|
|
347
|
-
**动态高度真相**:`tableHeight = content.offsetHeight − formRef 高 − paginationRef 高 − otherRef 高 − 50`(ResizeObserver 实时计算)。`content` / `formRef` / `paginationRef` 是固定三件套;**页面出现查询条件以外的模块时必须解构 `otherRef` 并绑到这些模块的统一根元素上**(多个模块包进同一个根容器),高度随模块显隐/伸缩自动重算。禁止用写死像素、`calc()` 猜值或自行手写 ResizeObserver 替代该机制。
|
|
348
|
-
|
|
349
|
-
---
|
|
92
|
+
### UnoCSS
|
|
350
93
|
|
|
351
|
-
|
|
94
|
+
`presetRemToPx({ baseFontSize: 4 })`:间距数字即 px。类名**必须带连字符**:
|
|
352
95
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
项目 `presetRemToPx({ baseFontSize: 4 })`:**间距数字即像素**(`p-5` = 5px)。类名**必须带连字符**,无连字符写法不会产出任何 CSS(已用 dist 产物实证):
|
|
358
|
-
|
|
359
|
-
| ❌ 无效(无 CSS 产出) | ✅ 有效 | 说明 |
|
|
360
|
-
|---|---|---|
|
|
361
|
-
| `p5` / `p10` / `p20` / `m10` / `mt20` / `px5` / `gap10` | `p-5` / `p-10` / `p-20` / `m-10` / `mt-20` / `px-5` / `gap-10` | 间距类必须带连字符 |
|
|
362
|
-
| `w100%` / `h100%` / `w-100%` / `h-[100%]` | `w-full` / `h-full` | 满宽满高统一 `full` |
|
|
363
|
-
| `p-b-16` | `pb-16` | 方向前缀连写 |
|
|
364
|
-
| `bg-[#fff]` + `dark:bg-[#303030]` | `bg-bg_color` | 背景按语义取变量,自动适配暗黑 |
|
|
365
|
-
|
|
366
|
-
- 间距取 **4px 基数**(4/8/12/16/20);`p-5`(查询区内边距)等模版既有值保持原样。
|
|
367
|
-
- shortcuts 白名单:`flex-center` / `flex-end` / `flex-middle` / `flex-between` / `flex-col-center` / `break-word` / `ellipsis`,布局优先用它们。
|
|
368
|
-
- 字号用显式 px 档位:`text-xs`=12 / `text-sm`=14 / `text-base`=16 / `text-lg`=18 / `text-xl`=20 / `text-2xl`=24 / `text-3xl`=30。
|
|
369
|
-
|
|
370
|
-
### 2. 颜色纪律(按语义取变量,禁止成对硬编码)
|
|
96
|
+
| 无效 | 有效 |
|
|
97
|
+
|------|------|
|
|
98
|
+
| `p5` / `w100%` | `p-5` / `w-full` |
|
|
99
|
+
| `bg-[#fff] dark:bg-[#303030]` | `bg-bg_color` |
|
|
371
100
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
| 页面/卡片背景 | `bg-bg_color`(桥接 `--el-bg-color`);布局底 `--el-bg-color-page`;浮层 `--el-bg-color-overlay` |
|
|
375
|
-
| 文字 | `--el-text-color-primary` / `regular` / `secondary` / `placeholder` |
|
|
376
|
-
| 边框 | `--el-border-color`(及 `-light` / `-lighter` / `-dark`) |
|
|
377
|
-
| 浅填充(表头/hover 底) | `--el-fill-color-light` |
|
|
378
|
-
| 主色与梯度 | `--el-color-primary`(及 `-light-3/5/7/9`、`-dark-2`) |
|
|
379
|
-
| 状态色 | `--el-color-success` / `warning` / `danger` / `info` |
|
|
380
|
-
| 表格表头 | `--vts-table-header-bg` / `--vts-table-header-text`(el-table 与 vxe 共用) |
|
|
381
|
-
| 弹窗背景 | `--vts-dialog-bg` ← `--ds-dialog-bg`(主题渐变:`primary-bg → component-bg`) |
|
|
382
|
-
| 弹窗内边距 | `--dialog-header-padding` / `--dialog-body-padding` / `--message-box-content-padding` / `--dialog-footer-padding` |
|
|
101
|
+
- 间距 4px 基数;shortcuts:`flex-center` / `flex-end` / `flex-between` 等
|
|
102
|
+
- 字号:`text-xs`=12 … `text-3xl`=30
|
|
383
103
|
|
|
384
|
-
|
|
104
|
+
### 颜色
|
|
385
105
|
|
|
386
|
-
|
|
387
|
-
/** 读取 CSS 变量(canvas/G6/jsPlumb 等需要具体色值时使用) */
|
|
388
|
-
const getCssVar = (name: string, fallback = "") =>
|
|
389
|
-
getComputedStyle(document.documentElement).getPropertyValue(name).trim() || fallback;
|
|
106
|
+
语义变量:`bg-bg_color`、`--el-text-color-*`、`--el-border-color`、`--el-color-primary*`、`--vts-table-header-*`、`--vts-dialog-bg`。Canvas/G6 等需实色时用 `getComputedStyle` 读变量,禁止业务写死 hex。
|
|
390
107
|
|
|
391
|
-
|
|
392
|
-
edge: { type: "line", style: { stroke: getCssVar("--el-color-primary-light-5", "#9DC5EA") } }
|
|
393
|
-
```
|
|
108
|
+
### 组件尺寸
|
|
394
109
|
|
|
395
|
-
|
|
110
|
+
| 场景 | 档位 |
|
|
111
|
+
|------|------|
|
|
112
|
+
| 查询区表单/按钮、工具栏按钮 | default(不写 size) |
|
|
113
|
+
| 表格 / 分页 | `:size="size"`(ReTableBar 透出) |
|
|
114
|
+
| 弹窗内表单 | default |
|
|
115
|
+
| 登录/整屏主表单 | `large` |
|
|
116
|
+
| 移动端 Vant | 见 `mobile-h5` |
|
|
396
117
|
|
|
397
|
-
|
|
398
|
-
|---|---|---|
|
|
399
|
-
| **查询区 `el-form`(含输入/选择/按钮)** | **default(不写 size)** | 中号 32px,与 `--control-height` / `--el-component-size` 一致;**禁止**只给按钮写 `small` 而表单走 default |
|
|
400
|
-
| 查询区按钮(查询/重置/展开收起) | 随 `el-form` 继承 | **禁止**单独写 `size="small"` 导致与输入框档位不一致 |
|
|
401
|
-
| `ReTableBar` 工具栏按钮(新增/导入/导出/删除) | default(不写 size) | 列表页工具栏与查询区同档(中号) |
|
|
402
|
-
| 表格 | `:size="size"`(`ReTableBar` 插槽透出) | **禁止写死**,密度切换由用户控制 |
|
|
403
|
-
| 分页 | `RePagination :size="size"` | 跟随表格密度 |
|
|
404
|
-
| 弹窗内表单 | default(不写 size)+ `label-width="96px"` | `ReDialog` / `ReDialogResize` 内表单 |
|
|
405
|
-
| 登录页 / 整屏主表单 | `size="large"` | 低频全屏操作放大档位 |
|
|
406
|
-
| 移动端 Vant | 独立尺寸体系 | 不与 EP 档位混用,见 `mobile-h5` |
|
|
118
|
+
存在 `design-tokens.scss` 时:零新增硬编码裸值;适配流程见 `design-system`。
|
|
407
119
|
|
|
408
|
-
|
|
120
|
+
### 独立功能页容器
|
|
409
121
|
|
|
410
|
-
|
|
122
|
+
定高且内部滚动(与列表卡同类场景):
|
|
411
123
|
|
|
412
124
|
```vue
|
|
413
|
-
<!-- 独立功能页(图谱/流程图等常规页) -->
|
|
414
125
|
<div
|
|
415
126
|
:style="{ height: `calc(100vh - 2 * var(--vts-margin) - ${headerHeight}px)` }"
|
|
416
127
|
class="pos-relative bg-bg_color p-5 overflow-hidden"
|
|
417
128
|
>
|
|
418
129
|
```
|
|
419
130
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
### 5. 设计规范生效期(design-tokens.scss 存在时)
|
|
424
|
-
|
|
425
|
-
1. 生成代码前先确认 `src/styles/design-tokens.scss` 是否存在;存在则进入「规范期」。
|
|
426
|
-
2. 规范期**零新增硬编码**:颜色/控件高度/内边距/圆角/字号一律引用令牌或语义变量;设计稿与令牌冲突时回填令牌层,不在页面里写裸值。
|
|
427
|
-
3. 间距/边距仍按 4px 基数,优先对齐令牌 `--space-unit` 的倍数。
|
|
428
|
-
4. 命中 `design-system` 时按其工作流执行适配与存量扫描,本节约束与其一致不冲突。
|
|
429
|
-
|
|
430
|
-
---
|
|
431
|
-
|
|
432
|
-
## 五、资产分层(核心 vs 附加)
|
|
131
|
+
查询列表定高卡 → `crud-pages`(`el-card.vts-page-card` + `tableHeight`)。
|
|
132
|
+
## 六、资产分层
|
|
433
133
|
|
|
434
|
-
|
|
134
|
+
附加 Hook/组件按功能模块加载(WebSocket、微信、附件、图表等)→ 见各专项与 `project-inventory`。
|
|
435
135
|
|
|
436
|
-
|
|
437
|
-
|------|------|
|
|
438
|
-
| `useWebSocket` | websocket-realtime |
|
|
439
|
-
| `useWechat` | wechat-js / mobile-h5 |
|
|
440
|
-
|
|
441
|
-
### 附加组件(示例)
|
|
442
|
-
|
|
443
|
-
附件/预览、ECharts、富文本、验证码、码、图谱、工作流、移动选择器、反馈展示类等 → 见各专项模块与 `project-inventory.md`。
|
|
444
|
-
|
|
445
|
-
### 附加 Utils
|
|
446
|
-
|
|
447
|
-
`uploadManager` / `imageCompression` → file;`changeSummaryService` → data-compare;`websocket/**` / `wechat/**` / `vantRules` → 对应专项;`particles` / `particlesOptions` → **particles**;`motion` → feedback-ui / 登录页入场动画。
|
|
448
|
-
|
|
449
|
-
---
|
|
450
|
-
|
|
451
|
-
## 六、工程摘要(只读,非日常生成目标)
|
|
136
|
+
## 七、工程摘要(只读)
|
|
452
137
|
|
|
453
138
|
| 项 | 说明 |
|
|
454
139
|
|----|------|
|
|
455
|
-
| 包管理 | pnpm
|
|
456
|
-
| 默认插件 | Vue/JSX、AutoImport、SVG、UnoCSS、
|
|
457
|
-
|
|
|
458
|
-
| 功能附属插件 | FileViewer → `file-management`;vConsole → `mobile-h5`;精确版本与 `pnpm` 命令见 `project-inventory` 第九节 |
|
|
459
|
-
| addon 安装 | 裁剪项目缺依赖时:查 `package.json` → 按第九节精确版本征得确认后 `pnpm add` / `pnpm add -D` |
|
|
460
|
-
|
|
461
|
-
除非用户明确要求改构建配置,否则生成业务代码时**不要**改 `vite.config.ts` / `build/**`。
|
|
140
|
+
| 包管理 | pnpm;`dev` / `build` / `type-check` / `lint` / `lint:fix` |
|
|
141
|
+
| 默认插件 | Vue/JSX、AutoImport、SVG、UnoCSS、Mock、Gzip 等 |
|
|
142
|
+
| addon | FileViewer → `file-management`;vConsole → `mobile-h5`;安装见 inventory 第九节 |
|
|
462
143
|
|
|
463
|
-
|
|
144
|
+
非用户要求不改 `vite.config.ts` / `build/**`。
|
|
464
145
|
|
|
465
|
-
##
|
|
146
|
+
## 八、环境变量
|
|
466
147
|
|
|
467
|
-
`VITE_TITLE` / `VITE_PUBLIC_PATH` / `VITE_USE_MOCK` / `VITE_API_BASE_URL` / `VITE_ENCODE_*` / `VITE_SSO` / `
|
|
148
|
+
`VITE_TITLE` / `VITE_PUBLIC_PATH` / `VITE_USE_MOCK` / `VITE_API_BASE_URL` / `VITE_ENCODE_*` / `VITE_SSO` / `VITE_DEBUGGER` 等;附加 `VITE_WS_URL`、`VITE_VCONSOLE` 随专项。
|
|
468
149
|
|
|
469
|
-
|
|
150
|
+
## 九、模块指针
|
|
470
151
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
- 选型对照与全量组件表 → `project-inventory.md`
|
|
152
|
+
| 需求 | 模块 |
|
|
153
|
+
|------|------|
|
|
154
|
+
| 接口 | `http-api` |
|
|
155
|
+
| 列表/表单 CRUD | `crud-pages` |
|
|
156
|
+
| 详情跳转 | `detail-page` |
|
|
157
|
+
| 主题布局 | `layout-theme` |
|
|
158
|
+
| 设计规范适配 | `design-system` + 有产出时 `design-handoff` |
|
|
159
|
+
| 版本/安装 | `project-inventory` |
|
|
160
|
+
| 生成后审查 | `code-quality` |
|