@agile-team/wl-skills-ui 1.8.16 → 1.9.0
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/CHANGELOG.md +29 -1
- package/README.md +24 -7
- package/SKILL.md +5 -5
- package/bin/wl-ui.js +75 -15
- package/docs/compat-matrix.md +1 -1
- package/docs/delivery-compatibility.md +31 -0
- package/docs/governance-long-term.md +6 -6
- package/docs/team-intro.md +1 -1
- package/es/index.d.ts +43 -1
- package/es/index.js +22 -0
- package/examples/migration-operations-to-renderOps.md +6 -6
- package/package.json +16 -8
- package/reference/ag-cell-renders.ts +2 -2
- package/scanner/fix.mjs +74 -63
- package/scanner/index.mjs +28 -2
- package/scanner/snapshot.mjs +74 -15
- package/skills/_flows/new-project-init.md +1 -1
- package/skills/_meta/_registry.md +1 -1
- package/skills/ops/fix/SKILL.md +10 -4
- package/skills/ops/fix/USAGE.md +7 -1
- package/skills/runtime/style-align/SKILL.md +2 -2
- package/standards/rules.json +10 -4
- package/standards/ui/02-button.md +20 -15
- package/styles/vendors/_base-components.scss +36 -39
- package/templates/ui-optimization-report/TPL-UI-OPTIM-REPORT.md +1 -1
- package/scanner/__tests__/fixtures/r001-fail.vue +0 -7
- package/scanner/__tests__/fixtures/r001-pass.vue +0 -7
- package/scanner/__tests__/fixtures/r002-fail.vue +0 -5
- package/scanner/__tests__/fixtures/r002-pass.vue +0 -5
- package/scanner/__tests__/fixtures/r006-fail.vue +0 -10
- package/scanner/__tests__/fixtures/r006-pass.vue +0 -10
- package/scanner/__tests__/fixtures/r011-fail.vue +0 -11
- package/scanner/__tests__/fixtures/r011-pass.vue +0 -14
- package/scanner/__tests__/fixtures/r016-fail.vue +0 -9
- package/scanner/__tests__/fixtures/r016-pass.vue +0 -9
- package/scanner/__tests__/fixtures/r021-fail.vue +0 -3
- package/scanner/__tests__/fixtures/r021-pass.vue +0 -3
- package/scanner/__tests__/fixtures/r025-fail.vue +0 -7
- package/scanner/__tests__/fixtures/r025-pass.vue +0 -7
- package/scanner/__tests__/fixtures/r026-fail.vue +0 -13
- package/scanner/__tests__/fixtures/r026-pass.vue +0 -11
- package/scanner/__tests__/fixtures/r027-fail.vue +0 -8
- package/scanner/__tests__/fixtures/r027-pass.vue +0 -8
- package/scanner/__tests__/fixtures/r028-fail.vue +0 -9
- package/scanner/__tests__/fixtures/r028-pass.vue +0 -9
- package/scanner/__tests__/scan.test.mjs +0 -145
- package/scripts/check-docs.mjs +0 -246
- package/scripts/check-scss.mjs +0 -99
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,34 @@ All notable changes to **@agile-team/wl-skills-ui** will be documented in this f
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
6
|
|
|
7
|
+
## [1.9.0] - 2026-07-18
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- 统一 CLI 正式暴露 `audit`、`drift`、`exempt`、`snapshot`,`audit --refresh-baseline` 可建立和收敛问题基线。
|
|
12
|
+
- 新增自动修复、快照路径边界、回退与 CLI 转发测试;新增包导出/运行时导入/规则目录与 fixer 一致性发布检查。
|
|
13
|
+
- 新增独立闭环与 kit 可选协同说明,明确 page-spec 只作为约定输入而非硬依赖。
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- `./runtime` package export 改为真实 `es/index.js` 与类型声明,不再错误导出包根目录。
|
|
18
|
+
- runtime 构建入口改为完整 `runtime/index.ts`,`createPreset/installPreset` 与文档一致;删除指向未发布 TypeScript 源码的失效 presets 通配导出。
|
|
19
|
+
- `add-preset` 改为在消费项目的 `src/wl-ui/presets` 安全生成,不再尝试写入安装包目录;名称和输出路径均做边界校验。
|
|
20
|
+
- 快照创建失败改为失败关闭;修复写入中断自动恢复本轮文件;快照和回退拒绝路径穿越及符号链接越界。
|
|
21
|
+
- `autoFixable` 与实际 fixer 能力收口:脚本配色、图标、loading-mask 和圆角等语义修复不再误标为自动修复。
|
|
22
|
+
- `fix` 完成后自动复检,`--fail-on-error` 在仍有强制问题时正确返回非零状态。
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- 最低 Node.js 版本提升为 22;新增统一 `verify`、`release:check` 与 `prepublishOnly` 发布门禁。
|
|
27
|
+
- npm 发布白名单排除 scanner 测试夹具与维护脚本,只保留运行时 scanner/rules,避免发布包污染。
|
|
28
|
+
|
|
29
|
+
## [1.8.17] - 2026-07-15
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- **操作列状态辨识**:全局化妆层把可用图标默认色改为柔和主题蓝 `--el-color-primary-light-2`,hover 继续使用原有蓝/绿/红语义色;原生禁用态统一浅灰且不响应 hover,选中行不再自动改变按钮语义色。业务页面无需改造,升级样式包即可生效。
|
|
34
|
+
|
|
7
35
|
## [1.8.16] - 2026-07-01
|
|
8
36
|
|
|
9
37
|
### Fixed
|
|
@@ -109,7 +137,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
109
137
|
### Notes
|
|
110
138
|
|
|
111
139
|
- R013(Upload 嵌入 operations[])由文档约束晋升为 `rules.json` 正式条目(`severity: review`,无 scanner 实现)。
|
|
112
|
-
- 推荐业务项目跟进:跑一次 `npx wl-ui audit --target src --
|
|
140
|
+
- 推荐业务项目跟进:跑一次 `npx wl-ui audit --target src --refresh-baseline` 建立基线,配合 `--baseline` 增量门槛使用(详见 `docs/governance-long-term.md`)。
|
|
113
141
|
|
|
114
142
|
## [1.7.1] - 2026-05-12
|
|
115
143
|
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> **企业级 UI 风格对齐框架** — 让 Vue + Element Plus 业务系统获得一致的视觉、可被 AI 精确识别和修复的设计规范,以及可演进的工程能力。
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@agile-team/wl-skills-ui)
|
|
6
|
-
[]()
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -187,7 +187,7 @@ npm i @agile-team/wl-skills-ui
|
|
|
187
187
|
yarn add @agile-team/wl-skills-ui
|
|
188
188
|
```
|
|
189
189
|
|
|
190
|
-
要求:Node ≥
|
|
190
|
+
要求:Node ≥ 22,Vue ≥ 3.2,Element Plus ≥ 2.2。
|
|
191
191
|
|
|
192
192
|
---
|
|
193
193
|
|
|
@@ -199,7 +199,7 @@ yarn add @agile-team/wl-skills-ui
|
|
|
199
199
|
|---|---|---|
|
|
200
200
|
| `element-plus` | **`2.2.6-prod.3`** | 集团 jh- 定制版;EP 2.3.0 起引入 `.el-input__wrapper`,与 jh-ui 3.x 不兼容 |
|
|
201
201
|
| `@jhlc/jh-ui` | **`3.1.0`** | SCSS 皮肤包,`.com-text` label 包裹 + `.has-colon` 冒号注入(wl-skills-ui 已统一屏蔽表单冒号) |
|
|
202
|
-
| `@agile-team/wl-skills-ui` | `^1.
|
|
202
|
+
| `@agile-team/wl-skills-ui` | `^1.9.0` | 已对齐上述组合的 DOM 假设 |
|
|
203
203
|
|
|
204
204
|
三种识别方式,任选其一:
|
|
205
205
|
|
|
@@ -213,7 +213,18 @@ yarn add @agile-team/wl-skills-ui
|
|
|
213
213
|
|
|
214
214
|
## 版本亮点
|
|
215
215
|
|
|
216
|
-
当前 v1.
|
|
216
|
+
当前 v1.9.0:
|
|
217
|
+
|
|
218
|
+
- **独立闭环**:不依赖 kit/design/bd 即可安装、审计、修复、复检、快照和回退;存在 kit 的 page-spec 时只复用页面模式与组件命名约定,不形成运行时硬依赖。
|
|
219
|
+
- **CLI 真实一致**:统一入口正式支持 `audit/drift/exempt/snapshot`,未知命令非零退出,`audit --refresh-baseline` 可维护增量治理基线。
|
|
220
|
+
- **修复失败安全**:快照失败即停止写入;快照与回退拒绝路径越界/符号链接越界;写入中断自动恢复本轮已写文件,修复结束自动复检。
|
|
221
|
+
- **发布面闭环**:修复 `./runtime` 导出,新增构建产物导入烟测、规则/fixer 一致性校验和 `verify/release:check/prepublishOnly` 门禁。
|
|
222
|
+
|
|
223
|
+
上一版 v1.8.17:
|
|
224
|
+
|
|
225
|
+
- **操作列状态辨识**:可用图标默认使用柔和主题蓝,hover 保留蓝/绿/红语义色;禁用态统一浅灰且不响应 hover,选中行不再改变按钮语义色
|
|
226
|
+
|
|
227
|
+
上一版 v1.8.16:
|
|
217
228
|
|
|
218
229
|
- **label 冒号通杀(根治"就它带冒号")**:jh-* 组件的 `showColon` 默认 true,渲染冒号走 `.com-text` 但不带 `.has-colon`,旧规则(仅 `.has-colon` 限定)命不中。新增不限 `.has-colon` 的通杀规则,咔嚓所有 `.el-form-item__label` 内冒号伪元素
|
|
219
230
|
|
|
@@ -400,7 +411,7 @@ npx wl-ui doctor --project .
|
|
|
400
411
|
{
|
|
401
412
|
"scripts": {
|
|
402
413
|
"ui:check": "wl-ui check --project .",
|
|
403
|
-
"ui:audit": "wl-ui
|
|
414
|
+
"ui:audit": "wl-ui audit --target src --outFile ui-audit.md",
|
|
404
415
|
"ui:fix": "wl-ui fix --target src --dry-run"
|
|
405
416
|
}
|
|
406
417
|
}
|
|
@@ -420,9 +431,13 @@ wl-ui doctor [--project .]
|
|
|
420
431
|
wl-ui prompts
|
|
421
432
|
wl-ui scan --target src [--layer L0,L1,L2] [--vendor base-table,jh]
|
|
422
433
|
[--mode skin|native] [--outFile report.md]
|
|
434
|
+
wl-ui audit --target src [--output json] [--refresh-baseline]
|
|
423
435
|
wl-ui check --project .
|
|
424
436
|
wl-ui fix --target src [--dry-run]
|
|
425
437
|
wl-ui all --project .
|
|
438
|
+
wl-ui drift --baseline .wl-baseline.json --current .wl-current.json
|
|
439
|
+
wl-ui exempt init --project . --target src
|
|
440
|
+
wl-ui snapshot list|diff|rollback|clean
|
|
426
441
|
wl-ui add-preset <name> # 脚手架新业务 preset
|
|
427
442
|
```
|
|
428
443
|
|
|
@@ -437,6 +452,8 @@ wl-ui add-preset <name> # 脚手架新业务 preset
|
|
|
437
452
|
|
|
438
453
|
> 可选桥接:如项目也安装了 `@agile-team/wl-skills-kit`,两者保持独立分工,不互相强依赖。kit 负责编码规范/页面生成/菜单字典权限,wl-skills-ui 负责 UI 风格/化妆层/Runtime 渲染。
|
|
439
454
|
|
|
455
|
+
具体独立使用、可选 page-spec 协同和验证边界见 [`docs/delivery-compatibility.md`](docs/delivery-compatibility.md)。
|
|
456
|
+
|
|
440
457
|
> 规范插件建议:项目可执行 `npx @robot-admin/git-standards init` 接入 ESLint/Prettier/Husky/提交规范,形成代码质量闭环。
|
|
441
458
|
|
|
442
459
|
---
|
|
@@ -481,12 +498,12 @@ Base* > jh-* > C_*/c_* > AG Grid > custom wrappers
|
|
|
481
498
|
|
|
482
499
|
```bash
|
|
483
500
|
npx wl-ui add-preset my-biz
|
|
484
|
-
#
|
|
501
|
+
# 在消费项目生成 src/wl-ui/presets/my-biz.ts,按提示填字段映射,然后:
|
|
485
502
|
```
|
|
486
503
|
|
|
487
504
|
```ts
|
|
488
505
|
// main.ts
|
|
489
|
-
import { installMyBizPreset } from "
|
|
506
|
+
import { installMyBizPreset } from "@/wl-ui/presets/my-biz";
|
|
490
507
|
installMyBizPreset();
|
|
491
508
|
```
|
|
492
509
|
|
package/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: |
|
|
3
3
|
UI 风格对齐 Skill —— 扫描 Vue SFC 文件,识别与 wl-skills-ui 五层规范不一致的控件写法,
|
|
4
|
-
|
|
4
|
+
生成整改清单,经用户确认后执行安全自动修复与语义人工修复,最终复检并记录未决项。
|
|
5
5
|
支持老项目 Skin 化妆模式(不改布局)和新项目 Native 原生模式(完整接入)。
|
|
6
6
|
applyTo: "**/*.vue"
|
|
7
7
|
---
|
|
@@ -79,7 +79,7 @@ npx wl-ui check --project [项目根目录]
|
|
|
79
79
|
|
|
80
80
|
询问用户:
|
|
81
81
|
1. 是否全量修复,还是指定规则/文件?
|
|
82
|
-
2.
|
|
82
|
+
2. 对于 `standards/rules.json` 标记为不可自动修复的问题,是否逐项人工处理?
|
|
83
83
|
|
|
84
84
|
**未经确认,禁止修改任何文件。**
|
|
85
85
|
|
|
@@ -93,7 +93,7 @@ npx wl-ui check --project [项目根目录]
|
|
|
93
93
|
|
|
94
94
|
### Phase 5 — 验证
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
`fix` 会自动复检;再运行 Phase 1 生成留档报告,验证强制问题归零,无法处理的偏差必须有显式豁免或未决记录。
|
|
97
97
|
|
|
98
98
|
---
|
|
99
99
|
|
|
@@ -401,7 +401,7 @@ npx wl-ui check --project [项目根目录]
|
|
|
401
401
|
|
|
402
402
|
## 八、新系统快速接入方案(推荐)
|
|
403
403
|
|
|
404
|
-
|
|
404
|
+
对于**全新业务系统**,使用本方案可让页面从第一行代码就采用统一基线,并通过持续扫描避免事后积累补丁。
|
|
405
405
|
|
|
406
406
|
> 详细接入步骤见 [README — 快速开始](../README.md#快速开始),以下仅列核心要点。
|
|
407
407
|
|
|
@@ -454,7 +454,7 @@ columnsDef(): TableColumnDesc<any>[] {
|
|
|
454
454
|
|---|---|
|
|
455
455
|
| 状态列彩色 Tag | `defineColumns` COLUMN_AUTO_MAP 自动配置 |
|
|
456
456
|
| 操作列图标按钮 | `renderOps([...])` 统一渲染系统 |
|
|
457
|
-
| 操作列条件显示 | `show: condition`
|
|
457
|
+
| 操作列条件显示 | `show: condition` 控制按钮显隐 |
|
|
458
458
|
| 自动分隔线 | 图标组与文字组之间 `renderOps` 自动插入 |
|
|
459
459
|
| 点击阻止冒泡 | `renderOps` 内部自动 `e.stopPropagation()` |
|
|
460
460
|
|
package/bin/wl-ui.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* wl-ui check → 委托给 scanner/index.mjs
|
|
10
10
|
* wl-ui fix → 委托给 scanner/index.mjs
|
|
11
11
|
* wl-ui all → 委托给 scanner/index.mjs
|
|
12
|
+
* wl-ui audit/drift/exempt/snapshot → 委托给 scanner/index.mjs
|
|
12
13
|
*
|
|
13
14
|
* 向后兼容:wl-scan 仍可用(直接调用 scanner/index.mjs)
|
|
14
15
|
*/
|
|
@@ -22,7 +23,7 @@ import {
|
|
|
22
23
|
rmSync,
|
|
23
24
|
unlinkSync,
|
|
24
25
|
} from "node:fs";
|
|
25
|
-
import { join, resolve, dirname, relative } from "node:path";
|
|
26
|
+
import { join, resolve, dirname, relative, isAbsolute } from "node:path";
|
|
26
27
|
import { fileURLToPath } from "node:url";
|
|
27
28
|
import { parseArgs } from "node:util";
|
|
28
29
|
import { createRequire } from "node:module";
|
|
@@ -53,12 +54,15 @@ const SUBCOMMANDS = new Set([
|
|
|
53
54
|
"doctor",
|
|
54
55
|
"prompts",
|
|
55
56
|
"scan",
|
|
57
|
+
"audit",
|
|
56
58
|
"check",
|
|
57
59
|
"fix",
|
|
58
60
|
"all",
|
|
59
61
|
"add-preset",
|
|
60
62
|
"add-vendor",
|
|
61
63
|
"snapshot",
|
|
64
|
+
"drift",
|
|
65
|
+
"exempt",
|
|
62
66
|
]);
|
|
63
67
|
let subcommand = "help";
|
|
64
68
|
|
|
@@ -66,10 +70,25 @@ if (rawArgs.length > 0 && SUBCOMMANDS.has(rawArgs[0])) {
|
|
|
66
70
|
subcommand = rawArgs.shift();
|
|
67
71
|
} else if (rawArgs.length === 0) {
|
|
68
72
|
subcommand = "help";
|
|
73
|
+
} else if (["--help", "-h", "--version", "-v"].includes(rawArgs[0])) {
|
|
74
|
+
subcommand = "help";
|
|
75
|
+
} else {
|
|
76
|
+
console.error(`[wl-ui] 未知命令:${rawArgs[0]}`);
|
|
77
|
+
console.error("运行 wl-ui --help 查看可用命令。");
|
|
78
|
+
process.exit(1);
|
|
69
79
|
}
|
|
70
80
|
|
|
71
81
|
// 非 init 子命令:直接委托给 scanner/index.mjs
|
|
72
|
-
const SCANNER_CMDS = new Set([
|
|
82
|
+
const SCANNER_CMDS = new Set([
|
|
83
|
+
"scan",
|
|
84
|
+
"audit",
|
|
85
|
+
"check",
|
|
86
|
+
"fix",
|
|
87
|
+
"all",
|
|
88
|
+
"snapshot",
|
|
89
|
+
"drift",
|
|
90
|
+
"exempt",
|
|
91
|
+
]);
|
|
73
92
|
if (SCANNER_CMDS.has(subcommand)) {
|
|
74
93
|
const scannerBin = join(PKG_ROOT, "scanner", "index.mjs");
|
|
75
94
|
try {
|
|
@@ -88,6 +107,10 @@ if (
|
|
|
88
107
|
rawArgs.includes("--help") ||
|
|
89
108
|
rawArgs.includes("-h")
|
|
90
109
|
) {
|
|
110
|
+
if (rawArgs.includes("--version") || rawArgs.includes("-v")) {
|
|
111
|
+
console.log(PKG.version);
|
|
112
|
+
process.exit(0);
|
|
113
|
+
}
|
|
91
114
|
printHelp();
|
|
92
115
|
process.exit(0);
|
|
93
116
|
}
|
|
@@ -235,7 +258,21 @@ if (subcommand === "add-preset") {
|
|
|
235
258
|
);
|
|
236
259
|
process.exit(1);
|
|
237
260
|
}
|
|
238
|
-
|
|
261
|
+
const { values } = parseArgs({
|
|
262
|
+
args: rawArgs.slice(1),
|
|
263
|
+
options: {
|
|
264
|
+
project: { type: "string", default: "." },
|
|
265
|
+
output: { type: "string", default: "src/wl-ui/presets" },
|
|
266
|
+
"dry-run": { type: "boolean", default: false },
|
|
267
|
+
},
|
|
268
|
+
strict: true,
|
|
269
|
+
});
|
|
270
|
+
scaffoldPreset({
|
|
271
|
+
name: presetName,
|
|
272
|
+
projectRoot: resolve(values.project),
|
|
273
|
+
outputDir: values.output,
|
|
274
|
+
dryRun: values["dry-run"],
|
|
275
|
+
});
|
|
239
276
|
process.exit(0);
|
|
240
277
|
}
|
|
241
278
|
|
|
@@ -542,19 +579,28 @@ ${
|
|
|
542
579
|
}
|
|
543
580
|
|
|
544
581
|
/** 脚手架新预设文件 */
|
|
545
|
-
function scaffoldPreset(name) {
|
|
546
|
-
|
|
582
|
+
function scaffoldPreset({ name, projectRoot, outputDir, dryRun }) {
|
|
583
|
+
if (!/^[a-z][a-z0-9-]*$/.test(name)) {
|
|
584
|
+
console.error("[wl-ui add-preset] 名称必须是小写 kebab-case");
|
|
585
|
+
process.exit(1);
|
|
586
|
+
}
|
|
587
|
+
const outPath = resolve(projectRoot, outputDir, `${name}.ts`);
|
|
588
|
+
const relPath = relative(projectRoot, outPath);
|
|
589
|
+
if (relPath.startsWith("..") || isAbsolute(relPath)) {
|
|
590
|
+
console.error("[wl-ui add-preset] 输出目录必须位于目标项目内");
|
|
591
|
+
process.exit(1);
|
|
592
|
+
}
|
|
547
593
|
if (existsSync(outPath)) {
|
|
548
594
|
console.error(`[wl-ui add-preset] 文件已存在:${outPath}`);
|
|
549
595
|
process.exit(1);
|
|
550
596
|
}
|
|
597
|
+
const symbol = toPascalCase(name);
|
|
551
598
|
const template = `/**
|
|
552
|
-
*
|
|
553
|
-
* 使用:import { install${
|
|
599
|
+
* ${relPath.replace(/\\/g, "/")} — ${name} 业务预设
|
|
600
|
+
* 使用:import { install${symbol}Preset } from '@/wl-ui/presets/${name}';
|
|
554
601
|
*/
|
|
555
|
-
import type { TagMapItem } from '
|
|
556
|
-
import { renderTagNode } from '
|
|
557
|
-
import { registerColumnAutoMaps } from '../core/registry';
|
|
602
|
+
import type { TagMapItem } from '@agile-team/wl-skills-ui/runtime';
|
|
603
|
+
import { registerColumnAutoMaps, renderTagNode } from '@agile-team/wl-skills-ui/runtime';
|
|
558
604
|
|
|
559
605
|
// ── 状态映射 ──────────────────────────────────────────────────────────────────
|
|
560
606
|
export const MY_STATUS_MAP: Record<string | number, TagMapItem> = {
|
|
@@ -568,7 +614,7 @@ export const renderMyStatus = (v: string | number | null | undefined) =>
|
|
|
568
614
|
renderTagNode(v, MY_STATUS_MAP);
|
|
569
615
|
|
|
570
616
|
// ── 安装 ──────────────────────────────────────────────────────────────────────
|
|
571
|
-
export function install${
|
|
617
|
+
export function install${symbol}Preset(): void {
|
|
572
618
|
registerColumnAutoMaps({
|
|
573
619
|
myStatus: {
|
|
574
620
|
width: 90,
|
|
@@ -578,13 +624,22 @@ export function install${capitalize(name)}Preset(): void {
|
|
|
578
624
|
});
|
|
579
625
|
}
|
|
580
626
|
`;
|
|
627
|
+
if (dryRun) {
|
|
628
|
+
console.log(`[wl-ui add-preset] [DRY-RUN] 将创建:${outPath}`);
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
581
632
|
writeFileSync(outPath, template, "utf8");
|
|
582
633
|
console.log(`[wl-ui add-preset] ✔ 创建预设文件:${outPath}`);
|
|
583
|
-
console.log(` 在 main.ts
|
|
634
|
+
console.log(` 在 main.ts 中引入并调用:install${symbol}Preset()`);
|
|
584
635
|
}
|
|
585
636
|
|
|
586
|
-
function
|
|
587
|
-
return
|
|
637
|
+
function toPascalCase(value) {
|
|
638
|
+
return value
|
|
639
|
+
.split("-")
|
|
640
|
+
.filter(Boolean)
|
|
641
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
642
|
+
.join("");
|
|
588
643
|
}
|
|
589
644
|
|
|
590
645
|
/** 根据 tag 名推断 vendor family(jh / base / c / ag-grid / custom) */
|
|
@@ -1023,6 +1078,8 @@ wl-ui — @agile-team/wl-skills-ui 统一 CLI v${PKG.version}
|
|
|
1023
1078
|
wl-ui scan --target <src> [--layer L0,L1,L2] [--vendor base-table,jh]
|
|
1024
1079
|
[--mode skin|native] [--outFile report.md]
|
|
1025
1080
|
[--exempt <config.json>]
|
|
1081
|
+
wl-ui audit --target <src> [--output json] [--refresh-baseline]
|
|
1082
|
+
scan 的只读审计别名;可显式刷新项目问题基线
|
|
1026
1083
|
wl-ui check --project <项目根目录>
|
|
1027
1084
|
wl-ui fix --target <src目录> [--dry-run] [--no-snapshot]
|
|
1028
1085
|
wl-ui all --project <项目根目录> [--outFile report.md]
|
|
@@ -1031,8 +1088,11 @@ wl-ui — @agile-team/wl-skills-ui 统一 CLI v${PKG.version}
|
|
|
1031
1088
|
wl-ui snapshot rollback [--id <id>] [--dry-run] 回退到快照(默认最新)
|
|
1032
1089
|
wl-ui snapshot diff [--id <id>] 查看快照与当前差异
|
|
1033
1090
|
wl-ui snapshot clean [--keep <N>] 清理旧快照
|
|
1091
|
+
wl-ui drift --baseline <基线.json> --current <当前.json> [--fail-on-error]
|
|
1092
|
+
wl-ui exempt init --project . --target src 生成豁免候选,需人工确认
|
|
1034
1093
|
|
|
1035
|
-
wl-ui add-preset <name>
|
|
1094
|
+
wl-ui add-preset <name> [--project .] [--output src/wl-ui/presets] [--dry-run]
|
|
1095
|
+
在消费项目内脚手架业务预设文件
|
|
1036
1096
|
wl-ui add-vendor <tag> [--family <id>] [--dry-run]
|
|
1037
1097
|
脚手架新 vendor 专项覆盖(SCSS + scanner 草稿 + vendors.json 注册)
|
|
1038
1098
|
|
package/docs/compat-matrix.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
| `element-plus` | **`2.2.6-prod.3`** | 集团 jh- 定制版,搭配 `@jhlc/jh-ui` 使用,DOM 仍为 `.el-input > .el-input__inner` 直挂结构(**EP 2.3.0 起才引入 `.el-input__wrapper`**) |
|
|
12
12
|
| `@jhlc/jh-ui` | **`3.1.0`** | SCSS 皮肤包,`.com-text` label 包裹、`.has-colon ::after` 冒号注入、`.el-form-item--default { margin-bottom: 24px }` 等强约束 |
|
|
13
13
|
| `@jhlc/common-core` | `3.1.0` 或 `3.1.0-prod.x` | 基础 util/types,`@jhlc/jh-ui` 间接依赖 |
|
|
14
|
-
| `@agile-team/wl-skills-ui` | `^1.
|
|
14
|
+
| `@agile-team/wl-skills-ui` | `^1.9.0` | 已对齐 jh-ui 3.1.0 + EP 2.2.6-prod.3 的 DOM 假设 |
|
|
15
15
|
|
|
16
16
|
## 项目集群当前实测
|
|
17
17
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# 独立闭环与可选协同
|
|
2
|
+
|
|
3
|
+
`wl-skills-ui` 是独立的 UI 工程包。它不要求业务项目安装 `wl-skills-design`、`wl-skills-kit` 或 `wl-skills-bd`,也不读取后端生成结果才能工作。
|
|
4
|
+
|
|
5
|
+
## 独立闭环
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
项目源码 → check/doctor → audit/scan → fix dry-run
|
|
9
|
+
→ 自动快照 + fix → 自动复检 → 人工语义修复
|
|
10
|
+
→ drift gate → snapshot rollback(需要时)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- `check/doctor` 验证接入、版本配对和样式入口。
|
|
14
|
+
- `audit/scan` 只读输出结构化问题与覆盖率。
|
|
15
|
+
- `fix` 只处理 `standards/rules.json` 明确标记的安全修复项,结束后自动复检。
|
|
16
|
+
- 快照失败时不写代码;回退拒绝项目外路径。
|
|
17
|
+
- `drift` 允许存量项目冻结历史欠债,只阻断新增污染。
|
|
18
|
+
|
|
19
|
+
## 与 kit 的天然协同
|
|
20
|
+
|
|
21
|
+
如果项目同时使用 `wl-skills-kit`,双方只共享稳定约定,不建立包依赖:
|
|
22
|
+
|
|
23
|
+
- kit 的 `page-spec.mode` 对应 UI 的 list-page、tree-list、form-dialog、detail-page 等布局语义。
|
|
24
|
+
- `platformComponents` 可用于选择 BaseTable、jh-*、Element Plus 等 vendor 规则,但 UI scanner 最终仍以实际源码为准。
|
|
25
|
+
- kit 负责业务代码结构、API 契约和页面完整性;UI 负责 token、视觉规则、组件族和样式回归,两者验证结果互不替代。
|
|
26
|
+
|
|
27
|
+
没有 page-spec 时,UI 通过源码、依赖和 DOM/组件族检测建立自己的审计上下文,能力不降级为“必须等待上游”。
|
|
28
|
+
|
|
29
|
+
## 非僵化原则
|
|
30
|
+
|
|
31
|
+
大屏、地图、流程设计器等特殊页面可以通过 `.wl-exempt.json` 做路径级或规则级豁免。豁免必须有原因、纳入版本控制并定期收敛;新增业务不能默认进入豁免区。
|
|
@@ -23,22 +23,22 @@
|
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
25
|
# 在主干分支建立基线(团队第一次接入时执行一次)
|
|
26
|
-
npx wl-ui audit --target src --
|
|
26
|
+
npx wl-ui audit --target src --refresh-baseline
|
|
27
27
|
git add .wl-baseline.json && git commit -m "chore: wl-ui baseline snapshot"
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
`.wl-baseline.json`
|
|
30
|
+
`.wl-baseline.json` 记录当前违规条目;漂移指纹使用 `(file, ruleId)` 和同类问题数量,行号变化不会制造假漂移。后续:
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
33
|
# PR 检查(仅报新增违规)
|
|
34
|
-
npx wl-ui scan --target src --baseline .wl-baseline.json --fail-on
|
|
34
|
+
npx wl-ui scan --target src --baseline .wl-baseline.json --fail-on-error
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
- **历史条目不再阻塞构建**(团队按计划逐步消化)
|
|
38
38
|
- **新代码引入新违规 → 立即红灯**
|
|
39
39
|
- 团队修复历史条目后跑 `npx wl-ui audit --refresh-baseline` 收敛基线
|
|
40
40
|
|
|
41
|
-
> 实现入口:`scanner/
|
|
41
|
+
> 实现入口:`audit --refresh-baseline` 生成问题基线,`scanner/drift.mjs` 负责增量比对;`scanner/snapshot.mjs` 是自动修复前的文件级回退快照,两种快照职责不同。
|
|
42
42
|
|
|
43
43
|
---
|
|
44
44
|
|
|
@@ -168,7 +168,7 @@ pnpm add -D @agile-team/wl-skills-ui
|
|
|
168
168
|
npx wl-ui init --project . --mode skin
|
|
169
169
|
|
|
170
170
|
# 3. 基线
|
|
171
|
-
npx wl-ui audit --target src --
|
|
171
|
+
npx wl-ui audit --target src --refresh-baseline
|
|
172
172
|
git add .wl-baseline.json
|
|
173
173
|
|
|
174
174
|
# 4. 豁免(如有)
|
|
@@ -176,7 +176,7 @@ cp node_modules/@agile-team/wl-skills-ui/.wl-exempt.example.json .wl-exempt.json
|
|
|
176
176
|
# 编辑为本项目实际豁免路径
|
|
177
177
|
|
|
178
178
|
# 5. CI 加 PR gate
|
|
179
|
-
# npx wl-ui scan --target src --baseline .wl-baseline.json --fail-on
|
|
179
|
+
# npx wl-ui scan --target src --baseline .wl-baseline.json --fail-on-error
|
|
180
180
|
|
|
181
181
|
# 6. 每季度 / 每次升级
|
|
182
182
|
npx wl-ui doctor --print-overrides # 版本对齐
|
package/docs/team-intro.md
CHANGED
|
@@ -159,7 +159,7 @@ AI 会按照 6 个阶段依次执行:接入 tokens → 引入 skin preset →
|
|
|
159
159
|
pnpm add @agile-team/wl-skills-ui
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
-
要求:Node ≥
|
|
162
|
+
要求:Node ≥ 22,Vue ≥ 3.2,Element Plus ≥ 2.2
|
|
163
163
|
|
|
164
164
|
NPM:[@agile-team/wl-skills-ui](https://www.npmjs.com/package/@agile-team/wl-skills-ui)
|
|
165
165
|
|
package/es/index.d.ts
CHANGED
|
@@ -29,4 +29,46 @@ declare function clearColumnAutoMap(name?: string): void;
|
|
|
29
29
|
*/
|
|
30
30
|
declare function defineColumns<T extends ColumnLike>(columns: T[]): T[];
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
/**
|
|
33
|
+
* runtime/presets/registry.ts — 预设注册系统
|
|
34
|
+
*
|
|
35
|
+
* 允许各业务模块通过 installPreset() 向 COLUMN_AUTO_MAP 注入字段映射,
|
|
36
|
+
* 实现"按需安装、互不干扰"的插件化架构。
|
|
37
|
+
*
|
|
38
|
+
* 使用方式:
|
|
39
|
+
* import { createPreset } from '@agile-team/wl-skills-ui/runtime';
|
|
40
|
+
* const myPreset = createPreset('my-biz', () => {
|
|
41
|
+
* registerColumnAutoMaps({ myField: { ... } });
|
|
42
|
+
* });
|
|
43
|
+
* myPreset.install();
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
interface PresetConfig {
|
|
47
|
+
/** 预设名称(唯一标识) */
|
|
48
|
+
name: string;
|
|
49
|
+
/** 列字段映射 */
|
|
50
|
+
columns: Record<string, Partial<ColumnLike>>;
|
|
51
|
+
/** 安装钩子(可选,注册后执行一次) */
|
|
52
|
+
onInstall?: () => void;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 安装一个预设:把 columns 批量注册进 COLUMN_AUTO_MAP
|
|
56
|
+
* 重复安装同名预设时自动跳过(幂等)
|
|
57
|
+
*/
|
|
58
|
+
declare function installPreset(config: PresetConfig): void;
|
|
59
|
+
/**
|
|
60
|
+
* 工厂:创建一个可延迟安装的预设对象
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* const safePreset = createPreset({ name: 'safe', columns: { riskLevel: { ... } } });
|
|
64
|
+
* safePreset.install(); // 按需调用
|
|
65
|
+
*/
|
|
66
|
+
declare function createPreset(config: PresetConfig): {
|
|
67
|
+
name: string;
|
|
68
|
+
install: () => void;
|
|
69
|
+
isInstalled: () => boolean;
|
|
70
|
+
};
|
|
71
|
+
/** 获取已安装预设名称列表(调试用) */
|
|
72
|
+
declare function getInstalledPresets(): ReadonlySet<string>;
|
|
73
|
+
|
|
74
|
+
export { ColumnLike, type PresetConfig, clearColumnAutoMap, createPreset, defineColumns, getColumnAutoMap, getInstalledPresets, installPreset, registerColumnAutoMap, registerColumnAutoMaps };
|
package/es/index.js
CHANGED
|
@@ -1 +1,23 @@
|
|
|
1
|
+
import { registerColumnAutoMaps } from './chunk-FMVZ54BY.js';
|
|
1
2
|
export { AUDIT_STATUS_MAP, ENABLE_STATUS_MAP, RATING_LEVEL_COLORS, VERIFY_STATUS_MAP, clearColumnAutoMap, defineColumns, getColumnAutoMap, registerColumnAutoMap, registerColumnAutoMaps, registerDictColorMap, registerDictColorMaps, renderAuditStatus, renderBadge, renderClassifyTag, renderCountBadge, renderDangerText, renderDictClassifyTag, renderEnableStatus, renderOps, renderRatingLevel, renderTagNode, renderTagSlot, renderVerifyStatus, setDictResolver } from './chunk-FMVZ54BY.js';
|
|
3
|
+
|
|
4
|
+
// runtime/presets/registry.ts
|
|
5
|
+
var _installedPresets = /* @__PURE__ */ new Set();
|
|
6
|
+
function installPreset(config) {
|
|
7
|
+
if (_installedPresets.has(config.name)) return;
|
|
8
|
+
registerColumnAutoMaps(config.columns);
|
|
9
|
+
config.onInstall?.();
|
|
10
|
+
_installedPresets.add(config.name);
|
|
11
|
+
}
|
|
12
|
+
function createPreset(config) {
|
|
13
|
+
return {
|
|
14
|
+
name: config.name,
|
|
15
|
+
install: () => installPreset(config),
|
|
16
|
+
isInstalled: () => _installedPresets.has(config.name)
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function getInstalledPresets() {
|
|
20
|
+
return _installedPresets;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { createPreset, getInstalledPresets, installPreset };
|
|
@@ -62,12 +62,12 @@ const columnsDef = [
|
|
|
62
62
|
|
|
63
63
|
| type | 图标 | 标题 | 颜色 |
|
|
64
64
|
|---|---|---|---|
|
|
65
|
-
| `view` | Eye (View) | 查看 | 蓝色 |
|
|
66
|
-
| `edit` | Edit | 编辑 | 绿色 |
|
|
67
|
-
| `del` | Delete | 删除 | 红色 |
|
|
68
|
-
| `log` | Document | 记录 |
|
|
69
|
-
| `ok` | CircleCheck | 审核 | 绿色 |
|
|
70
|
-
| `send` | Upload | 提交 | 蓝色 |
|
|
65
|
+
| `view` | Eye (View) | 查看 | 默认主题淡蓝,hover 蓝色 |
|
|
66
|
+
| `edit` | Edit | 编辑 | 默认主题淡蓝,hover 绿色 |
|
|
67
|
+
| `del` | Delete | 删除 | 默认主题淡蓝,hover 红色 |
|
|
68
|
+
| `log` | Document | 记录 | 默认主题淡蓝,hover 蓝色 |
|
|
69
|
+
| `ok` | CircleCheck | 审核 | 默认主题淡蓝,hover 绿色 |
|
|
70
|
+
| `send` | Upload | 提交 | 默认主题淡蓝,hover 蓝色 |
|
|
71
71
|
|
|
72
72
|
## 非预设操作(胶囊/文字)
|
|
73
73
|
|
package/package.json
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agile-team/wl-skills-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"description": "企业级 UI 风格对齐框架 — Vue + Element Plus 项目通用化妆/原生双模式(tokens / element / vendors / layouts / runtime / scanner / fixer / skills)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./es/index.js",
|
|
7
|
+
"types": "./es/index.d.ts",
|
|
7
8
|
"exports": {
|
|
8
9
|
".": {
|
|
9
10
|
"import": "./es/index.js",
|
|
10
11
|
"types": "./es/index.d.ts"
|
|
11
12
|
},
|
|
12
|
-
"./runtime":
|
|
13
|
+
"./runtime": {
|
|
14
|
+
"import": "./es/index.js",
|
|
15
|
+
"types": "./es/index.d.ts"
|
|
16
|
+
},
|
|
13
17
|
"./runtime/common-preset": {
|
|
14
18
|
"import": "./es/common-preset.js",
|
|
15
19
|
"types": "./es/common-preset.d.ts"
|
|
@@ -18,7 +22,6 @@
|
|
|
18
22
|
"import": "./es/presets/security.js",
|
|
19
23
|
"types": "./es/presets/security.d.ts"
|
|
20
24
|
},
|
|
21
|
-
"./runtime/presets/*": "./runtime/presets/*",
|
|
22
25
|
"./vite": "./runtime/vite/check.mjs",
|
|
23
26
|
"./styles": "./styles/index.scss",
|
|
24
27
|
"./styles/*": "./styles/*",
|
|
@@ -41,7 +44,7 @@
|
|
|
41
44
|
"build": "tsup && npm run sync:tokens",
|
|
42
45
|
"prepare": "npm run build",
|
|
43
46
|
"sync:tokens": "node -e \"import('fs').then(fs=>fs.copyFileSync('design/tokens/base.css','dist/tokens.css'))\"",
|
|
44
|
-
"test": "node --test scanner/__tests__
|
|
47
|
+
"test": "node --test scanner/__tests__/*.test.mjs",
|
|
45
48
|
"check:scss": "node scripts/check-scss.mjs",
|
|
46
49
|
"docs:check": "node scripts/check-docs.mjs",
|
|
47
50
|
"scan": "node scanner/index.mjs scan",
|
|
@@ -50,13 +53,19 @@
|
|
|
50
53
|
"all": "node scanner/index.mjs all",
|
|
51
54
|
"standards:init": "npx @robot-admin/git-standards init",
|
|
52
55
|
"cz": "git-cz",
|
|
53
|
-
"lint": "eslint ."
|
|
56
|
+
"lint": "eslint . --max-warnings 0",
|
|
57
|
+
"verify:package": "node scripts/verify-package.mjs",
|
|
58
|
+
"verify": "npm run lint && npm test && npm run check:scss && npm run docs:check && npm run build && npm run verify:package",
|
|
59
|
+
"pack:dry": "npm pack --dry-run --ignore-scripts",
|
|
60
|
+
"release:check": "npm run verify && npm pack --dry-run --ignore-scripts",
|
|
61
|
+
"prepublishOnly": "npm run verify"
|
|
54
62
|
},
|
|
55
63
|
"files": [
|
|
56
64
|
"dist",
|
|
57
65
|
"es",
|
|
58
66
|
"runtime/vite",
|
|
59
|
-
"scanner",
|
|
67
|
+
"scanner/*.mjs",
|
|
68
|
+
"scanner/rules",
|
|
60
69
|
"standards",
|
|
61
70
|
"styles",
|
|
62
71
|
"design",
|
|
@@ -64,7 +73,6 @@
|
|
|
64
73
|
"skills",
|
|
65
74
|
"templates",
|
|
66
75
|
"bin",
|
|
67
|
-
"scripts",
|
|
68
76
|
"mcp",
|
|
69
77
|
"reference",
|
|
70
78
|
"examples",
|
|
@@ -105,7 +113,7 @@
|
|
|
105
113
|
}
|
|
106
114
|
},
|
|
107
115
|
"engines": {
|
|
108
|
-
"node": ">=
|
|
116
|
+
"node": ">=22"
|
|
109
117
|
},
|
|
110
118
|
"keywords": [
|
|
111
119
|
"vue",
|
|
@@ -382,7 +382,7 @@ export function renderRatingLevel(
|
|
|
382
382
|
|
|
383
383
|
/**
|
|
384
384
|
* 内置图标预设(type: 'view' | 'edit' | 'del')
|
|
385
|
-
* 渲染为 26×26px
|
|
385
|
+
* 渲染为 26×26px 纯图标按钮,默认主题淡蓝,hover 变语义色
|
|
386
386
|
*/
|
|
387
387
|
const ICON_PRESETS = {
|
|
388
388
|
view: { icon: View, cls: "jh-op-view", title: "查看" },
|
|
@@ -429,7 +429,7 @@ export type OpItem = OpPreset | OpChip | OpLink;
|
|
|
429
429
|
* 渲染操作列按钮组(三层系统)
|
|
430
430
|
*
|
|
431
431
|
* 第一层 — 纯图标按钮(type: 'view'|'edit'|'del'|'log'|'ok'|'send')
|
|
432
|
-
* 26×26px
|
|
432
|
+
* 26×26px,默认主题淡蓝,hover 变语义色,tooltip 兜底
|
|
433
433
|
*
|
|
434
434
|
* 第二层 — 胶囊按钮(type: 'chip')
|
|
435
435
|
* 圆角胶囊,图标+文字,hover 淡蓝背景 + 主色文字
|