dlzn-ui 2.0.54 → 2.0.56
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/package.json +1 -1
- package/proj-template/.cursor/rules/type-check-after-edit.mdc +17 -0
- package/proj-template/.cursor/skills/refactor-page-list/SKILL.md +61 -6
- package/proj-template/.cursor/skills/refactor-page-list/examples.md +118 -0
- package/proj-template/src/layout/index.ts +1 -0
- package/proj-template/src/views/index.ts +4 -0
package/package.json
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: 修改代码后必须通过项目 TypeScript 校验(pnpm type-check)
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 修改后 TypeScript 校验
|
|
7
|
+
|
|
8
|
+
在本仓库**每次完成代码修改**(含新增/删除文件)后,结束任务前必须执行类型检查并处理与本次改动相关的结果:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pnpm type-check
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
- 等价于 `vue-tsc --build`,以项目 `tsconfig` 为准;不要仅用 `vue-tsc --noEmit` 代替。
|
|
15
|
+
- 若报错路径属于**本次修改的文件**,必须修到通过再结束。
|
|
16
|
+
- 若报错在未改动的历史文件,说明现状即可;不要为通过全量检查而扩大无关改动范围。
|
|
17
|
+
- 与页面迁移 skill 一致:除 TS 外,对改动的 `.vue`/`.ts` 仍应执行 `pnpm eslint <路径>`。
|
|
@@ -37,7 +37,7 @@ Task Progress:
|
|
|
37
37
|
- [ ] 3. 在 qc-ui 同路径创建 index.vue
|
|
38
38
|
- [ ] 4. 按映射表转换配置
|
|
39
39
|
- [ ] 5. 内联新增/编辑表单(不迁移 PageListItemForm)
|
|
40
|
-
- [ ] 6. 对**本次修改的文件**执行 `pnpm eslint <路径>` 与 `pnpm
|
|
40
|
+
- [ ] 6. 对**本次修改的文件**执行 `pnpm eslint <路径>` 与 `pnpm type-check`,确认无 ESLint/TS 报错后再结束(见 `.cursor/rules/type-check-after-edit.mdc`)
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
### Step 1:分析原页面
|
|
@@ -165,8 +165,22 @@ $confirm({
|
|
|
165
165
|
| `responseType: 'blob'` 导出 | `apis.export.method: '.../export'`(POST) |
|
|
166
166
|
| `refreshCache` 且原定义为 delete | `$alova.Delete('.../refreshCache', ...)` |
|
|
167
167
|
| `unlock/{userName}` 且无 method | `$alova.Get('monitor/logininfor/unlock/${userName}', ...)` |
|
|
168
|
+
| `useDataResult: false`(如 online/list) | list 请求保留 `meta: { useDataResult: false }`(响应 `{ rows, total }` 在顶层,不在 `data` 内) |
|
|
169
|
+
| `online/{tokenId}` + `method: 'delete'` | `$alova.Delete('monitor/online/${row.tokenId}', undefined, { meta: { useSuccessMsg: true } })` |
|
|
168
170
|
|
|
169
|
-
路径占位符 `{userName}`、`{id}` 在目标项目中通常拼进 URL 字符串,如 `` `monitor/logininfor/unlock/${row.userName}` ``。
|
|
171
|
+
路径占位符 `{userName}`、`{id}`、`{tokenId}` 在目标项目中通常拼进 URL 字符串,如 `` `monitor/logininfor/unlock/${row.userName}` ``。
|
|
172
|
+
|
|
173
|
+
**原 api 带 `useDataResult: false` 的 list**(如 `getOnlineList`):
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
list: {
|
|
177
|
+
method: (o: Record<string, any>) =>
|
|
178
|
+
$alova.Get('monitor/online/list', {
|
|
179
|
+
meta: { useDataResult: false },
|
|
180
|
+
params: o,
|
|
181
|
+
}),
|
|
182
|
+
},
|
|
183
|
+
```
|
|
170
184
|
|
|
171
185
|
**`$alova` 参数个数**(勿与 axios 混用;写完后对照项目内已有调用):
|
|
172
186
|
|
|
@@ -205,8 +219,37 @@ list: {
|
|
|
205
219
|
| `title: 'xxx'` | `title: 'xxx'`(不变) |
|
|
206
220
|
| `type: 'checkbox'` | 由 `apis.delete.showBatch: true` 自动处理 |
|
|
207
221
|
| `field: 'c-action'` | `colKey: '_operation'` |
|
|
222
|
+
| `field: 'c-action'` + `fixed: 'right'` | **不要**写 `fixed: 'right'`;TTable 对 `colKey: '_operation'` 默认右固定 |
|
|
208
223
|
| 删除按钮 | 由 TPageList 根据 `apis.delete` 自动追加 |
|
|
209
224
|
| `field: 'remark'` / `title: '备注'` | 加 `resize: { maxWidth: 300 }`(内容可能很长) |
|
|
225
|
+
| slot / 模板拼 `${row.xxx}%` | `align: 'right'` + `FormatNumber` | 见下方「百分比列」 |
|
|
226
|
+
|
|
227
|
+
### 百分比列
|
|
228
|
+
|
|
229
|
+
原项目用 slot 或 `cell: (_, { row }) => \`${row.usage}%\`` 拼百分号时,迁移改用 `FormatNumber`:
|
|
230
|
+
|
|
231
|
+
- **靠右对齐**:数字/百分比列加 `align: 'right'`
|
|
232
|
+
- **空值安全**:后端字段(如 `usage`)可能为空/无效,`FormatNumber` 返回空字符串,避免 `undefined%`
|
|
233
|
+
- **勿手写 `%`**:由 `config.unit: 'percent'` 格式化
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
{
|
|
237
|
+
align: 'right',
|
|
238
|
+
cell: {
|
|
239
|
+
component: 'FormatNumber',
|
|
240
|
+
config: {
|
|
241
|
+
style: 'unit',
|
|
242
|
+
unit: 'percent',
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
colKey: 'usage',
|
|
246
|
+
title: '已用百分比',
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
纯数字列(非百分比)同理:`align: 'right'` + `cell: { component: 'FormatNumber' }`(无 `unit`)。
|
|
251
|
+
|
|
252
|
+
参考:`qc-ui/src/views/monitor/server/index.vue` 磁盘「已用百分比」列。
|
|
210
253
|
|
|
211
254
|
### 权限
|
|
212
255
|
|
|
@@ -214,7 +257,7 @@ list: {
|
|
|
214
257
|
|
|
215
258
|
### 即时请求操作需 popconfirm
|
|
216
259
|
|
|
217
|
-
`operations`
|
|
260
|
+
`operations` 与操作列 `Buttons` 中点击即发请求的操作(强退、解锁、刷新缓存、同步、重置等),**必须**用 `popconfirm` 二次确认,不用 `onClick` 直接请求;原项目 `$confirm` + `$api` 一律改为 `popconfirm.onConfirm` + `$alova`:
|
|
218
261
|
|
|
219
262
|
```typescript
|
|
220
263
|
{
|
|
@@ -233,6 +276,12 @@ list: {
|
|
|
233
276
|
|
|
234
277
|
新增/编辑等打开弹窗的操作不需要 popconfirm。
|
|
235
278
|
|
|
279
|
+
### 仅列表 + 行内操作(无 CRUD)
|
|
280
|
+
|
|
281
|
+
部分 monitor 页只有 list 与行内自定义按钮(如在线用户强退),**不配置** `apis.delete` / `export`,也无需 `tableOtherProps.rowKey`(无批量删)。操作列手写 `Buttons` + `popconfirm`;成功后 `pageListRef.value!.query()` 刷新。原项目未写 `permission` 的按钮,目标也**不要**自行添加。
|
|
282
|
+
|
|
283
|
+
参考:`qc-ui/src/views/monitor/online/index.vue`(原 `yq-monitor-front/src/views/monitor/online/index.vue`)。
|
|
284
|
+
|
|
236
285
|
### 只读详情弹窗($dialog)
|
|
237
286
|
|
|
238
287
|
原项目用旧式 `$dialog({ title, showCancel: false, confirmText: '关闭' }, Component)` 展示只读详情时,目标项目**直接用 `h(TForm, ...)` 内联**,与 `formItemMap` 共用,**不单独建 `modules/Detail.vue`**:
|
|
@@ -296,6 +345,9 @@ onClick: () => {
|
|
|
296
345
|
| 系统页参考(dlzn-ui) | `dlzn-ui/packages/dlzn-ui/views/system/post/index.vue` |
|
|
297
346
|
| 含 dateRange + 刷新缓存 | `dlzn-ui/packages/dlzn-ui/views/system/dict/index.vue` |
|
|
298
347
|
| 只读详情弹窗 | `qc-ui/src/views/monitor/operlog/index.vue` |
|
|
348
|
+
| 仅列表 + 行内强退 | `qc-ui/src/views/monitor/online/index.vue` |
|
|
349
|
+
| 原:仅列表 + 行内强退 | `yq-monitor-front/src/views/monitor/online/index.vue` |
|
|
350
|
+
| 百分比列 FormatNumber | `qc-ui/src/views/monitor/server/index.vue`(usage 列) |
|
|
299
351
|
|
|
300
352
|
更多 before/after 片段见 [examples.md](examples.md)。
|
|
301
353
|
|
|
@@ -303,12 +355,15 @@ onClick: () => {
|
|
|
303
355
|
|
|
304
356
|
- [ ] 路径与原项目一致(`src/views/.../index.vue`)
|
|
305
357
|
- [ ] 筛选、分页列表正常
|
|
306
|
-
- [ ]
|
|
307
|
-
- [ ] 自定义 operations
|
|
358
|
+
- [ ] 新增、编辑、单删、批量删、导出(仅列表页可跳过 CRUD 项)
|
|
359
|
+
- [ ] 自定义 operations / 行内 Buttons(如强退、解锁、刷新缓存)
|
|
360
|
+
- [ ] `_operation` 列未重复写 `fixed: 'right'`
|
|
361
|
+
- [ ] 原 list 带 `useDataResult: false` 时已保留 `meta`
|
|
362
|
+
- [ ] 百分比列用 `FormatNumber` + `align: 'right'`,未手写 `` `${row.xxx}%` ``
|
|
308
363
|
- [ ] 权限码与后端一致
|
|
309
364
|
- [ ] 每个非 CRUD 操作(unlock、clean、refreshCache 等)的 HTTP 方法已与原 `@/api` 定义逐项核对
|
|
310
365
|
- [ ] 无路由组件缺失报错
|
|
311
366
|
- [ ] 修改文件 ESLint 通过(`pnpm eslint <文件路径>`)
|
|
312
|
-
- [ ] 修改文件 TS 通过(`pnpm
|
|
367
|
+
- [ ] 修改文件 TS 通过(`pnpm type-check`,至少无本次文件相关报错)
|
|
313
368
|
- [ ] `$alova.Get` 仅两参;带 meta 时写在第二参 config 对象内
|
|
314
369
|
- [ ] `formItemMap` 使用 `satisfies Record<string, FormItem>`;条件显示用 `__others`
|
|
@@ -259,3 +259,121 @@ export const refreshConfigCache = { url: `${prefix}/config/refreshCache`, method
|
|
|
259
259
|
```
|
|
260
260
|
|
|
261
261
|
`prefix` 通常为 `system`,目标直接使用 `system/config/...` 路径。
|
|
262
|
+
|
|
263
|
+
## 完整案例:monitor/online 在线用户
|
|
264
|
+
|
|
265
|
+
| 文件 | 项目 |
|
|
266
|
+
|------|------|
|
|
267
|
+
| 原 | `yq-monitor-front/src/views/monitor/online/index.vue` |
|
|
268
|
+
| 目标 | `qc-ui/src/views/monitor/online/index.vue` |
|
|
269
|
+
|
|
270
|
+
特点:仅 list + 行内「强退」,无新增/编辑/删除/导出,无 `PageListItemForm`。
|
|
271
|
+
|
|
272
|
+
## 原项目:list 带 useDataResult: false
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
// yq-monitor-front/src/api/monitor.ts
|
|
276
|
+
export const getOnlineList: apiConfig = {
|
|
277
|
+
url: `${prefix}/online/list`,
|
|
278
|
+
useDataResult: false,
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
RuoYi 分页 `{ rows, total }` 在响应顶层,须保留 `useDataResult: false`。
|
|
283
|
+
|
|
284
|
+
## 目标项目:等效写法
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
apis: {
|
|
288
|
+
list: {
|
|
289
|
+
method: (o: Record<string, any>) =>
|
|
290
|
+
$alova.Get('monitor/online/list', {
|
|
291
|
+
meta: { useDataResult: false },
|
|
292
|
+
params: o,
|
|
293
|
+
}),
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## 原项目:强退($confirm + delete)
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
{
|
|
302
|
+
text: '强退',
|
|
303
|
+
onClick: async ({ row }) => {
|
|
304
|
+
await $confirm(`是否确认强退名称为${row.userName}的用户?`)
|
|
305
|
+
await $api(forceOnlineLogout, { tokenId: row.tokenId })
|
|
306
|
+
pageListRef.value!.query()
|
|
307
|
+
},
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// api
|
|
311
|
+
export const forceOnlineLogout: apiConfig = {
|
|
312
|
+
url: `${prefix}/online/{tokenId}`,
|
|
313
|
+
method: 'delete',
|
|
314
|
+
msgOnSuccess: true,
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## 目标项目:等效写法
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
{
|
|
322
|
+
cell: {
|
|
323
|
+
buttons: [
|
|
324
|
+
({ row }) => ({
|
|
325
|
+
default: '强退',
|
|
326
|
+
popconfirm: {
|
|
327
|
+
content: `是否确认强退名称为${row.userName}的用户?`,
|
|
328
|
+
onConfirm: async () => {
|
|
329
|
+
await $alova.Delete(`monitor/online/${row.tokenId}`, undefined, {
|
|
330
|
+
meta: { useSuccessMsg: true },
|
|
331
|
+
})
|
|
332
|
+
pageListRef.value!.query()
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
}),
|
|
336
|
+
],
|
|
337
|
+
component: 'Buttons',
|
|
338
|
+
},
|
|
339
|
+
colKey: '_operation',
|
|
340
|
+
title: '操作',
|
|
341
|
+
// 不要写 fixed: 'right',TTable 对 _operation 默认右固定
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## _operation 列勿写 fixed
|
|
346
|
+
|
|
347
|
+
TTable 内置:`colKey === '_operation'` 时默认 `fixed: 'right'`。迁移时去掉原 `field: 'c-action'` 列上的 `fixed: 'right'`,避免重复配置。
|
|
348
|
+
|
|
349
|
+
## 百分比列:slot / 模板 → FormatNumber
|
|
350
|
+
|
|
351
|
+
场景:服务监控磁盘「已用百分比」等;后端 `usage` 可能为空。
|
|
352
|
+
|
|
353
|
+
### 错误 ❌
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
// 手写 cell 或 slot 拼 %
|
|
357
|
+
cell: (_, { row }) => `${row.usage}%`
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
`usage` 为空时显示 `undefined%`;数字列未右对齐。
|
|
361
|
+
|
|
362
|
+
### 正确 ✅
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
{
|
|
366
|
+
align: 'right',
|
|
367
|
+
cell: {
|
|
368
|
+
component: 'FormatNumber',
|
|
369
|
+
config: {
|
|
370
|
+
style: 'unit',
|
|
371
|
+
unit: 'percent',
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
colKey: 'usage',
|
|
375
|
+
title: '已用百分比',
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
参考:`qc-ui/src/views/monitor/server/index.vue`。
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default import.meta.glob('./**/*.vue') as Record<string, AsyncVueComponentLoaderDefault>
|