@agile-team/wl-skills-ui 1.6.9 → 1.6.12
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 +31 -0
- package/README.md +22 -10
- package/SKILL.md +1 -1
- package/bin/wl-ui.js +172 -4
- package/design/tokens/index.css +1 -1
- package/examples/migration-operations-to-renderOps.md +2 -2
- package/mcp/server.js +30 -30
- package/package.json +1 -1
- package/scanner/coverage.mjs +36 -24
- package/scanner/exempt.mjs +3 -3
- package/scanner/index.mjs +27 -27
- package/scanner/integration.mjs +14 -14
- package/scanner/report.mjs +9 -9
- package/scanner/rules/componentFamily.mjs +4 -4
- package/scanner/rules/index.mjs +1 -1
- package/scanner/snapshot.mjs +7 -7
- package/scripts/check-docs.mjs +54 -4
- package/skills/_meta/_compat/headers/agents.txt +1 -1
- package/skills/_meta/_compat/headers/claude-code.txt +2 -2
- package/skills/_meta/_compat/headers/cline.txt +2 -2
- package/skills/_meta/_compat/vendors.json +73 -0
- package/skills/element/component-family/SKILL.md +5 -5
- package/skills/ops/scan/USAGE.md +1 -1
- package/styles/index.scss +6 -6
- package/styles/presets/full.scss +2 -2
- package/styles/presets/security.scss +1 -1
- package/styles/presets/skin.scss +1 -1
- package/styles/presets/tokens-only.scss +1 -1
- package/styles/vendors/_base-components.scss +94 -9
- package/styles/vendors/_base-query-toolbar.scss +51 -0
- package/styles/vendors/_portal.scss +2 -2
- package/styles/vendors/index.scss +1 -1
- /package/examples/{wk-exempt.example.json → wl-exempt.example.json} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,37 @@ 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.6.12] - 2026-05-12
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- 修复表单 label 单行省略样式覆盖后,必填星号、错误 label、错误提示和错误边框红色态不明显的问题。
|
|
12
|
+
|
|
13
|
+
## [1.6.11] - 2026-05-11
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- 优化 BaseToolbar 下拉/分裂按钮组样式,统一高度、圆角、间距和下拉菜单 hover 可读性。
|
|
18
|
+
- 优化 AG Grid 操作列内 `jh-op-*` 操作按钮,取消 active 缩放并提升选中行可读性。
|
|
19
|
+
- 补齐输入控件 focus 品牌色边框、统一圆角、长表单 label 单行省略和弹窗图标居中尺寸规则。
|
|
20
|
+
|
|
21
|
+
## [1.6.10] - 2026-05-11
|
|
22
|
+
|
|
23
|
+
### Removed
|
|
24
|
+
|
|
25
|
+
- 移除所有 `wk-skills-ui` / `wk-ui` / `wk-scan` / `wks_ui_*` / `.wk-snapshot` / `wk-exempt` 旧命名(运行时、注释、文档、headers、MCP 工具名、scanner、styles),未来不再兼容旧前缀。
|
|
26
|
+
- `examples/wk-exempt.example.json` 重命名为 `examples/wl-exempt.example.json`。
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- 新增 vendor 单一事实源 `skills/_meta/_compat/vendors.json`,承载 Base / jh / C / AG Grid / custom 的 id、priority、patterns、baseline、styles。`scanner/coverage.mjs` 启动时一次性 parse + 编译 RegExp,长生命周期复用,零运行时性能开销。
|
|
31
|
+
- 新增 CLI 子命令 `wl-ui add-vendor <tag> [--family <id>] [--dry-run]`,一键生成专项 SCSS、`@forward` 注册、vendors.json baseline 追加、scanner 规则草稿。
|
|
32
|
+
- `npm run docs:check` 扩展校验范围至 `.md/.mjs/.js/.ts/.scss/.css/.txt/.json/.vue`,新增 `wk-scan` / `.wk-snapshot` / `wk-exempt` / `wks_ui_` 禁忌词、vendor 优先级一致性、`jh-components` SKILL 全量通配语义校验。
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- MCP 工具前缀统一为 `wl_ui_*`(原 `wks_ui_*`),server name 同步为 `wl-skills-ui`。
|
|
37
|
+
|
|
7
38
|
## [1.6.9] - 2026-05-11
|
|
8
39
|
|
|
9
40
|
### Changed
|
package/README.md
CHANGED
|
@@ -193,7 +193,19 @@ yarn add @agile-team/wl-skills-ui
|
|
|
193
193
|
|
|
194
194
|
## 版本亮点
|
|
195
195
|
|
|
196
|
-
当前 v1.6.
|
|
196
|
+
当前 v1.6.12 版本继续强化“统一规则源 + 单一事实源 + 项目集群封装必覆盖 + UI 细节精准修复”的闭环,并补齐销售报价页暴露出的通用 UI 细节:
|
|
197
|
+
|
|
198
|
+
- 修复表单必填星号、错误 label、错误提示和错误边框红色态,避免校验反馈被通用 label/input 样式覆盖
|
|
199
|
+
- 优化 BaseToolbar 下拉/分裂按钮组,让“主动作 + 下拉动作”按一个动作组展示,避免视觉割裂
|
|
200
|
+
- 优化 AG Grid 操作列 `jh-op-*` 图标/胶囊/文字按钮,取消按压缩放抖动,并提升选中行下的可读性
|
|
201
|
+
- 补齐输入控件 focus 品牌色边框、统一圆角、长 label 单行省略和自定义弹窗图标居中尺寸规则
|
|
202
|
+
- 全量移除旧 `wk-` 前缀命名(包名 / CLI / 快照目录 / 豁免配置 / MCP 工具名),不再兼容(详见 CHANGELOG v1.6.10)
|
|
203
|
+
- 新增 `skills/_meta/_compat/vendors.json` 作为 L2 Project Vendors 的单一事实源(id / priority / patterns / baseline / styles),`scanner/coverage.mjs` 启动时一次性编译 RegExp,零运行时开销
|
|
204
|
+
- 新增 `wl-ui add-vendor <tag> [--family <id>] [--dry-run]` 脚手架命令:一键生成专项 SCSS、`@forward` 注册、`vendors.json` baseline 追加、scanner 规则草稿
|
|
205
|
+
- MCP 工具前缀统一为 `wl_ui_*`(`wl_ui_check` / `wl_ui_scan` / `wl_ui_fix_dry_run` / `wl_ui_skill_prompt` / `wl_ui_route_intent` / `wl_ui_recommend_flow`)
|
|
206
|
+
- `npm run docs:check` 扩展到全部代码与文档类型,新增禁忌词、vendor 优先级一致性、`jh-components` 全量通配语义防回归
|
|
207
|
+
|
|
208
|
+
历史亮点(v1.6.9):
|
|
197
209
|
|
|
198
210
|
- `skills/**/*.md` 作为唯一规则源,`wl-ui init/update` 会按编辑器格式转换并覆盖写入目标 rules
|
|
199
211
|
- `skills/_meta/_compat/editors.json` 作为 AI 编辑器安装配置唯一来源,CLI 不再维护第二份编辑器路径映射
|
|
@@ -508,20 +520,20 @@ export const myRules = [
|
|
|
508
520
|
|
|
509
521
|
| MCP Tool | 作用 |
|
|
510
522
|
| ----------------------- | ---------------------------------------------------------- |
|
|
511
|
-
| `
|
|
512
|
-
| `
|
|
513
|
-
| `
|
|
514
|
-
| `
|
|
515
|
-
| `
|
|
516
|
-
| `
|
|
523
|
+
| `wl_ui_check` | 检查 tokens/styles/runtime 接入完整性 |
|
|
524
|
+
| `wl_ui_scan` | 扫描 UI 风格偏差,输出 Markdown 或 JSON |
|
|
525
|
+
| `wl_ui_fix_dry_run` | 预览自动修复,不实际写入 |
|
|
526
|
+
| `wl_ui_skill_prompt` | 输出 AI 触发提示 |
|
|
527
|
+
| `wl_ui_route_intent` | 根据自然语言识别 UI 治理意图并推荐 flow/tool/skill |
|
|
528
|
+
| `wl_ui_recommend_flow` | 根据扫描 JSON 推荐 nextActions 和 `wl-skills-kit` 桥接动作 |
|
|
517
529
|
|
|
518
530
|
推荐智能体流程:
|
|
519
531
|
|
|
520
532
|
```text
|
|
521
533
|
用户自然语言
|
|
522
|
-
→
|
|
523
|
-
→
|
|
524
|
-
→
|
|
534
|
+
→ wl_ui_route_intent
|
|
535
|
+
→ wl_ui_scan --output json
|
|
536
|
+
→ wl_ui_recommend_flow
|
|
525
537
|
→ 先保证样式统一
|
|
526
538
|
→ 如需规范化,再桥接 wl-skills-kit validate-page / doctor-ui
|
|
527
539
|
```
|
package/SKILL.md
CHANGED
|
@@ -25,7 +25,7 @@ npx wl-ui clean --project . --dry-run
|
|
|
25
25
|
npx wl-ui prompts
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
可选编辑器:`github-copilot`、`cursor`、`windsurf`、`kiro`、`trae`、`claude-code`、`cline`、`agents-generic`、`qoder`、`all`。`update` 未指定编辑器时会刷新 manifest 与项目中已存在的编辑器规则目录;修复前优先使用 `--dry-run` 或 MCP 工具 `
|
|
28
|
+
可选编辑器:`github-copilot`、`cursor`、`windsurf`、`kiro`、`trae`、`claude-code`、`cline`、`agents-generic`、`qoder`、`all`。`update` 未指定编辑器时会刷新 manifest 与项目中已存在的编辑器规则目录;修复前优先使用 `--dry-run` 或 MCP 工具 `wl_ui_fix_dry_run`。
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
## 一、适用场景
|
package/bin/wl-ui.js
CHANGED
|
@@ -57,6 +57,7 @@ const SUBCOMMANDS = new Set([
|
|
|
57
57
|
"fix",
|
|
58
58
|
"all",
|
|
59
59
|
"add-preset",
|
|
60
|
+
"add-vendor",
|
|
60
61
|
"snapshot",
|
|
61
62
|
]);
|
|
62
63
|
let subcommand = "help";
|
|
@@ -231,6 +232,28 @@ if (subcommand === "add-preset") {
|
|
|
231
232
|
process.exit(0);
|
|
232
233
|
}
|
|
233
234
|
|
|
235
|
+
// ── add-vendor ─────────────────────────────────────────────────────────────────
|
|
236
|
+
if (subcommand === "add-vendor") {
|
|
237
|
+
const tag = rawArgs[0];
|
|
238
|
+
if (!tag) {
|
|
239
|
+
console.error(
|
|
240
|
+
"[wl-ui add-vendor] 请提供 vendor 标签名,例如:wl-ui add-vendor jh-upload --family jh",
|
|
241
|
+
);
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
const { values } = parseArgs({
|
|
245
|
+
args: rawArgs.slice(1),
|
|
246
|
+
options: {
|
|
247
|
+
family: { type: "string", default: "" },
|
|
248
|
+
"dry-run": { type: "boolean", default: false },
|
|
249
|
+
},
|
|
250
|
+
strict: false,
|
|
251
|
+
});
|
|
252
|
+
const family = values.family || inferVendorFamily(tag);
|
|
253
|
+
scaffoldVendor({ tag, family, dryRun: values["dry-run"] });
|
|
254
|
+
process.exit(0);
|
|
255
|
+
}
|
|
256
|
+
|
|
234
257
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
235
258
|
// 工具函数
|
|
236
259
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
@@ -557,6 +580,149 @@ function capitalize(s) {
|
|
|
557
580
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
558
581
|
}
|
|
559
582
|
|
|
583
|
+
/** 根据 tag 名推断 vendor family(jh / base / c / ag-grid / custom) */
|
|
584
|
+
function inferVendorFamily(tag) {
|
|
585
|
+
if (/^jh-/i.test(tag)) return "jh";
|
|
586
|
+
if (/^Base[A-Z]|^base-/.test(tag)) return "base";
|
|
587
|
+
if (/^C_|^c-/.test(tag)) return "c";
|
|
588
|
+
if (/ag[-_]?grid/i.test(tag)) return "ag-grid";
|
|
589
|
+
return "custom";
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/** 脚手架新 vendor 专项覆盖:生成 SCSS、scanner 规则草稿、Skill 基线追加 */
|
|
593
|
+
function scaffoldVendor({ tag, family, dryRun }) {
|
|
594
|
+
const safe = tag.replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
|
|
595
|
+
const VENDORS_JSON = join(
|
|
596
|
+
PKG_ROOT,
|
|
597
|
+
"skills",
|
|
598
|
+
"_meta",
|
|
599
|
+
"_compat",
|
|
600
|
+
"vendors.json",
|
|
601
|
+
);
|
|
602
|
+
const SCSS_PATH = join(PKG_ROOT, "styles", "vendors", `_${safe}.scss`);
|
|
603
|
+
const VENDORS_INDEX = join(PKG_ROOT, "styles", "vendors", "index.scss");
|
|
604
|
+
const SKILL_DIR = join(
|
|
605
|
+
PKG_ROOT,
|
|
606
|
+
"skills",
|
|
607
|
+
"vendors",
|
|
608
|
+
family === "jh" ? "jh-components" : `${family}-components`,
|
|
609
|
+
);
|
|
610
|
+
const SKILL_FILE = join(SKILL_DIR, "SKILL.md");
|
|
611
|
+
|
|
612
|
+
const actions = [];
|
|
613
|
+
|
|
614
|
+
// 1) SCSS 模板
|
|
615
|
+
if (existsSync(SCSS_PATH)) {
|
|
616
|
+
console.warn(`[wl-ui add-vendor] 已存在,跳过:${SCSS_PATH}`);
|
|
617
|
+
} else {
|
|
618
|
+
const scss = `// styles/vendors/_${safe}.scss — ${tag} 专项视觉覆盖
|
|
619
|
+
// family: ${family}
|
|
620
|
+
//
|
|
621
|
+
// 准入条件(详见 standards/architecture/01-layer-boundaries.md):
|
|
622
|
+
// - 复杂 DOM / 多 Element Plus 组合
|
|
623
|
+
// - 默认样式偏离 tokens(颜色/间距/圆角/密度)
|
|
624
|
+
// - 高频出现于核心页面
|
|
625
|
+
// - scanner 反复反馈或 AI 修复不稳定
|
|
626
|
+
//
|
|
627
|
+
// 约束:
|
|
628
|
+
// - 仅使用 design/tokens/base.css 中的 CSS 变量
|
|
629
|
+
// - 不写死颜色/间距/圆角;不污染全局选择器
|
|
630
|
+
// - 选择器范围必须收敛到 .${safe}__root 或 ${tag} 标签
|
|
631
|
+
|
|
632
|
+
.${safe},
|
|
633
|
+
${tag} {
|
|
634
|
+
// TODO: 用 var(--el-*) / var(--wl-*) tokens 替换硬编码
|
|
635
|
+
}
|
|
636
|
+
`;
|
|
637
|
+
actions.push({ type: "create", path: SCSS_PATH, content: scss });
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// 2) styles/vendors/index.scss 追加 @forward
|
|
641
|
+
const idx = readFileSync(VENDORS_INDEX, "utf8");
|
|
642
|
+
if (!idx.includes(`'./_${safe}'`) && !idx.includes(`"./_${safe}"`)) {
|
|
643
|
+
const insertLine = `@forward './_${safe}'; // ${tag} 专项覆盖(${family})\n`;
|
|
644
|
+
const anchor = "@forward './_base-table';";
|
|
645
|
+
const next = idx.includes(anchor)
|
|
646
|
+
? idx.replace(anchor, insertLine + anchor)
|
|
647
|
+
: idx + "\n" + insertLine;
|
|
648
|
+
actions.push({ type: "update", path: VENDORS_INDEX, content: next });
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// 3) vendors.json baseline 追加
|
|
652
|
+
const reg = JSON.parse(readFileSync(VENDORS_JSON, "utf8"));
|
|
653
|
+
const entry = reg.vendors.find((v) => v.id === family);
|
|
654
|
+
if (entry && !entry.baseline.includes(tag)) {
|
|
655
|
+
entry.baseline.push(tag);
|
|
656
|
+
if (!entry.styles.includes(`_${safe}.scss`))
|
|
657
|
+
entry.styles.push(`_${safe}.scss`);
|
|
658
|
+
actions.push({
|
|
659
|
+
type: "update",
|
|
660
|
+
path: VENDORS_JSON,
|
|
661
|
+
content: JSON.stringify(reg, null, 2) + "\n",
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// 4) Skill 文档代表性基线追加(仅 jh family 自动追加,其它给提示)
|
|
666
|
+
if (family === "jh" && existsSync(SKILL_FILE)) {
|
|
667
|
+
const skill = readFileSync(SKILL_FILE, "utf8");
|
|
668
|
+
if (!skill.includes(tag)) {
|
|
669
|
+
const hint = `\n<!-- add-vendor: 建议在「代表性基线」表中补充一行 ${tag} -->\n`;
|
|
670
|
+
actions.push({ type: "update", path: SKILL_FILE, content: skill + hint });
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// 5) scanner 规则草稿(仅生成模板,不强制注册)
|
|
675
|
+
const RULE_PATH = join(
|
|
676
|
+
PKG_ROOT,
|
|
677
|
+
"scanner",
|
|
678
|
+
"rules",
|
|
679
|
+
`vendor-${safe}.draft.mjs`,
|
|
680
|
+
);
|
|
681
|
+
if (!existsSync(RULE_PATH)) {
|
|
682
|
+
const rule = `/**
|
|
683
|
+
* scanner/rules/vendor-${safe}.draft.mjs — ${tag} 专项规则草稿
|
|
684
|
+
*
|
|
685
|
+
* 启用方式:
|
|
686
|
+
* 1) 改名为 vendor-${safe}.mjs
|
|
687
|
+
* 2) 在 scanner/rules/index.mjs 中 import 并 push 到 BUILT_IN_RULES
|
|
688
|
+
*/
|
|
689
|
+
export const ${safe.replace(/-/g, "_")}Rules = [
|
|
690
|
+
{
|
|
691
|
+
id: "V-${safe.toUpperCase()}-001",
|
|
692
|
+
category: "vendor",
|
|
693
|
+
severity: "warning",
|
|
694
|
+
description: "${tag} 视觉应统一覆盖到 tokens(草稿规则)",
|
|
695
|
+
check(ctx) {
|
|
696
|
+
// ctx: { file, content, addIssue(...) }
|
|
697
|
+
// TODO: 实现检测逻辑
|
|
698
|
+
return [];
|
|
699
|
+
},
|
|
700
|
+
},
|
|
701
|
+
];
|
|
702
|
+
`;
|
|
703
|
+
actions.push({ type: "create", path: RULE_PATH, content: rule });
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
// 执行 / 预览
|
|
707
|
+
for (const act of actions) {
|
|
708
|
+
const rel = relative(PKG_ROOT, act.path).replace(/\\/g, "/");
|
|
709
|
+
if (dryRun) {
|
|
710
|
+
console.log(`[dry-run] ${act.type}: ${rel}`);
|
|
711
|
+
} else {
|
|
712
|
+
writeFileSync(act.path, act.content, "utf8");
|
|
713
|
+
console.log(`[wl-ui add-vendor] ${act.type}: ${rel}`);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
if (actions.length === 0) {
|
|
717
|
+
console.log("[wl-ui add-vendor] 无变更(已存在)");
|
|
718
|
+
} else if (!dryRun) {
|
|
719
|
+
console.log("\n下一步:");
|
|
720
|
+
console.log(` 1. 编辑 styles/vendors/_${safe}.scss 用 tokens 覆盖样式`);
|
|
721
|
+
console.log(" 2. 如需检测规则,把 vendor-*.draft.mjs 改名并在 rules/index.mjs 注册");
|
|
722
|
+
console.log(" 3. 运行 npm run docs:check && npm run lint && npm run build");
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
560
726
|
function installSupportFiles({ projectRoot, dryRun }) {
|
|
561
727
|
const files = [
|
|
562
728
|
{
|
|
@@ -604,9 +770,9 @@ function triggerPrompts() {
|
|
|
604
770
|
|
|
605
771
|
## 智能触发
|
|
606
772
|
|
|
607
|
-
- 用户说"样式乱 / 不统一 / 老项目化妆":先调用
|
|
773
|
+
- 用户说"样式乱 / 不统一 / 老项目化妆":先调用 wl_ui_route_intent,再调用 wl_ui_scan --mode skin
|
|
608
774
|
- 用户说"卡片 / Tab / 详情 / 树 / 抽屉 / 上传 / 步骤条 / 更多操作":触发对应 Element Plus 组件族 skill
|
|
609
|
-
- 扫描 JSON 返回后:调用
|
|
775
|
+
- 扫描 JSON 返回后:调用 wl_ui_recommend_flow 判断 recommendedFlows、nextActions 和 kitBridge
|
|
610
776
|
|
|
611
777
|
## 单点触发
|
|
612
778
|
|
|
@@ -625,7 +791,7 @@ function triggerPrompts() {
|
|
|
625
791
|
|
|
626
792
|
- 扫描只读,修复前必须等待用户确认
|
|
627
793
|
- skin 模式只处理 L0/L1/L2,不改业务布局和 runtime
|
|
628
|
-
- fix 前建议先 dry-run 或通过 MCP 调用
|
|
794
|
+
- fix 前建议先 dry-run 或通过 MCP 调用 wl_ui_fix_dry_run
|
|
629
795
|
- 涉及 BaseTable render-type/cid、renderOps 或页面结构规范时,视觉统一后再桥接 wl-skills-kit validate-page / doctor-ui
|
|
630
796
|
`;
|
|
631
797
|
}
|
|
@@ -825,6 +991,8 @@ wl-ui — @agile-team/wl-skills-ui 统一 CLI v${PKG.version}
|
|
|
825
991
|
wl-ui snapshot clean [--keep <N>] 清理旧快照
|
|
826
992
|
|
|
827
993
|
wl-ui add-preset <name> 脚手架一个新的业务预设文件
|
|
994
|
+
wl-ui add-vendor <tag> [--family <id>] [--dry-run]
|
|
995
|
+
脚手架新 vendor 专项覆盖(SCSS + scanner 草稿 + vendors.json 注册)
|
|
828
996
|
|
|
829
997
|
参数:
|
|
830
998
|
--project 项目根目录(默认 .)
|
|
@@ -833,7 +1001,7 @@ wl-ui — @agile-team/wl-skills-ui 统一 CLI v${PKG.version}
|
|
|
833
1001
|
scan: skin(只看L0/L1/L2) | native(全量)
|
|
834
1002
|
--layer scan 过滤:L0/L1/L2/L3/L4(逗号分隔)
|
|
835
1003
|
--vendor scan 过滤:element/base-table/jh-components/...(逗号分隔)
|
|
836
|
-
--exempt 豁免配置文件路径(默认 .
|
|
1004
|
+
--exempt 豁免配置文件路径(默认 .wl-exempt.json)
|
|
837
1005
|
--dry-run 预览模式,不实际写入文件
|
|
838
1006
|
--no-snapshot fix 时跳过快照创建
|
|
839
1007
|
--skills-only 仅安装 skill 文件,不处理 index.html
|
package/design/tokens/index.css
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* design/tokens/index.css — 设计系统 Token 入口
|
|
2
2
|
*
|
|
3
3
|
* 在 index.html 中最先加载:
|
|
4
|
-
* <link rel="stylesheet" href="/node_modules/@agile-team/
|
|
4
|
+
* <link rel="stylesheet" href="/node_modules/@agile-team/wl-skills-ui/design/tokens/index.css" />
|
|
5
5
|
*
|
|
6
6
|
* 注意:dist/tokens.css 保留用于兼容旧版本引用路径,内容与此文件相同。
|
|
7
7
|
*/
|
|
@@ -98,10 +98,10 @@ Scanner 规则 R013 会自动检测旧格式 `operations: [...]`。
|
|
|
98
98
|
|
|
99
99
|
```bash
|
|
100
100
|
# 扫描所有旧格式
|
|
101
|
-
npx
|
|
101
|
+
npx wl-scan scan --target src --layer L4
|
|
102
102
|
|
|
103
103
|
# 查看影响文件
|
|
104
|
-
npx
|
|
104
|
+
npx wl-scan scan --target src --output json | jq '.issues[] | select(.rule == "R013") | .file'
|
|
105
105
|
```
|
|
106
106
|
|
|
107
107
|
> 注意:operations → renderOps 不可自动修复,需要人工确认每个操作的图标类型和回调。
|
package/mcp/server.js
CHANGED
|
@@ -12,9 +12,9 @@ const PKG = require("../package.json");
|
|
|
12
12
|
|
|
13
13
|
const TOOLS = [
|
|
14
14
|
{
|
|
15
|
-
name: "
|
|
15
|
+
name: "wl_ui_check",
|
|
16
16
|
description:
|
|
17
|
-
"检查当前项目是否已正确接入 @agile-team/
|
|
17
|
+
"检查当前项目是否已正确接入 @agile-team/wl-skills-ui 的 tokens/styles/runtime。",
|
|
18
18
|
inputSchema: {
|
|
19
19
|
type: "object",
|
|
20
20
|
properties: {
|
|
@@ -27,7 +27,7 @@ const TOOLS = [
|
|
|
27
27
|
},
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
|
-
name: "
|
|
30
|
+
name: "wl_ui_scan",
|
|
31
31
|
description:
|
|
32
32
|
"扫描 Vue 项目的 UI 风格偏差,支持 skin/native、layer、vendor、exempt 过滤。",
|
|
33
33
|
inputSchema: {
|
|
@@ -51,8 +51,8 @@ const TOOLS = [
|
|
|
51
51
|
},
|
|
52
52
|
},
|
|
53
53
|
{
|
|
54
|
-
name: "
|
|
55
|
-
description: "预览
|
|
54
|
+
name: "wl_ui_fix_dry_run",
|
|
55
|
+
description: "预览 wl-skills-ui 自动修复会修改哪些文件,不实际写入。",
|
|
56
56
|
inputSchema: {
|
|
57
57
|
type: "object",
|
|
58
58
|
properties: {
|
|
@@ -66,15 +66,15 @@ const TOOLS = [
|
|
|
66
66
|
},
|
|
67
67
|
},
|
|
68
68
|
{
|
|
69
|
-
name: "
|
|
69
|
+
name: "wl_ui_skill_prompt",
|
|
70
70
|
description:
|
|
71
|
-
"输出
|
|
71
|
+
"输出 wl-skills-ui 推荐触发语和下一步操作,引导 AI 加载正确 Skill/Flow。",
|
|
72
72
|
inputSchema: { type: "object", properties: {}, required: [] },
|
|
73
73
|
},
|
|
74
74
|
{
|
|
75
|
-
name: "
|
|
75
|
+
name: "wl_ui_route_intent",
|
|
76
76
|
description:
|
|
77
|
-
"根据用户自然语言判断 UI 样式治理意图,并推荐
|
|
77
|
+
"根据用户自然语言判断 UI 样式治理意图,并推荐 wl-skills-ui flow/tool/skill。",
|
|
78
78
|
inputSchema: {
|
|
79
79
|
type: "object",
|
|
80
80
|
properties: {
|
|
@@ -84,9 +84,9 @@ const TOOLS = [
|
|
|
84
84
|
},
|
|
85
85
|
},
|
|
86
86
|
{
|
|
87
|
-
name: "
|
|
87
|
+
name: "wl_ui_recommend_flow",
|
|
88
88
|
description:
|
|
89
|
-
"根据
|
|
89
|
+
"根据 wl_ui_scan --output json 的扫描结果推荐后续 flow、tool 和 wl-skills-kit 桥接动作。",
|
|
90
90
|
inputSchema: {
|
|
91
91
|
type: "object",
|
|
92
92
|
properties: {
|
|
@@ -143,14 +143,14 @@ function runScanner(command, args = {}) {
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
function skillPrompt() {
|
|
146
|
-
return "#
|
|
146
|
+
return "# wl-skills-ui Skill 触发提示\n\n核心原则:wl-skills-ui 优先保证样式绝对管控,覆盖纯 Element Plus、老项目封装、Base*/jh*/C_* 以及 wl-skills-kit 最佳写法。\n\n推荐触发语:\n\n- 新项目:用 wl-ui 的 new-project-init 流程接入统一 UI 风格\n- 老项目:用 wl-ui 的 legacy-skin-align 流程做老项目化妆对齐\n- 只审计:用 wl-ui 的 full-audit 流程扫描当前项目,不修改代码\n- 渐进迁移:用 wl-ui 的 progressive-migrate 流程从 skin 迁移到 runtime\n- 表格/弹窗/卡片/Tab/详情/树/抽屉/上传/步骤条/更多操作样式不统一:先调用 wl_ui_route_intent,再调用 wl_ui_scan\n- 单点修复:用 wl-ui 的 vendors/base-table、element/el-table 或 element 组件族 skill 检查当前文件\n\n执行约束:\n\n- 扫描只读,修复前必须先给用户摘要并等待确认\n- 老项目 skin 模式只处理 L0/L1/L2,不改业务布局和 runtime\n- 若扫描结果涉及页面结构、BaseTable render-type/cid 或 renderOps,视觉统一后再建议 wl-skills-kit validate-page / doctor-ui。";
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
function routeIntent(args = {}) {
|
|
150
150
|
const text = String(args.text || "").toLowerCase();
|
|
151
151
|
const matchedComponents = [];
|
|
152
152
|
const recommendedSkills = [];
|
|
153
|
-
const recommendedTools = ["
|
|
153
|
+
const recommendedTools = ["wl_ui_scan"];
|
|
154
154
|
let intent = "full-audit";
|
|
155
155
|
let recommendedFlow = "full-audit";
|
|
156
156
|
|
|
@@ -196,14 +196,14 @@ function routeIntent(args = {}) {
|
|
|
196
196
|
if (/老项目|旧项目|样式乱|不统一|化妆|统一视觉|skin/.test(text)) {
|
|
197
197
|
intent = "legacy-skin-align";
|
|
198
198
|
recommendedFlow = "legacy-skin-align";
|
|
199
|
-
recommendedTools.push("
|
|
199
|
+
recommendedTools.push("wl_ui_fix_dry_run");
|
|
200
200
|
} else if (/迁移|runtime|token|硬编码|颜色/.test(text)) {
|
|
201
201
|
intent = "progressive-migrate";
|
|
202
202
|
recommendedFlow = "progressive-migrate";
|
|
203
203
|
} else if (/新项目|初始化|接入/.test(text)) {
|
|
204
204
|
intent = "new-project-init";
|
|
205
205
|
recommendedFlow = "new-project-init";
|
|
206
|
-
recommendedTools.unshift("
|
|
206
|
+
recommendedTools.unshift("wl_ui_check");
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
const shouldUseKit =
|
|
@@ -218,11 +218,11 @@ function routeIntent(args = {}) {
|
|
|
218
218
|
recommendedTools: [...new Set(recommendedTools)],
|
|
219
219
|
shouldUseKit,
|
|
220
220
|
nextActions: [
|
|
221
|
-
"先执行
|
|
222
|
-
"如需修复,先执行
|
|
221
|
+
"先执行 wl_ui_scan 做只读扫描,确认 componentCoverage 与 issues",
|
|
222
|
+
"如需修复,先执行 wl_ui_fix_dry_run 预览,不直接写入",
|
|
223
223
|
shouldUseKit
|
|
224
224
|
? "若要规范化页面结构,再桥接 wl-skills-kit validate-page / doctor-ui"
|
|
225
|
-
: "优先由
|
|
225
|
+
: "优先由 wl-skills-ui skin/native 样式层完成视觉统一",
|
|
226
226
|
],
|
|
227
227
|
};
|
|
228
228
|
}
|
|
@@ -244,7 +244,7 @@ function buildKitBridge(needed) {
|
|
|
244
244
|
needed,
|
|
245
245
|
reason: needed
|
|
246
246
|
? "扫描结果涉及页面结构、BaseTable 或操作列规范,建议视觉统一后桥接 wl-skills-kit。"
|
|
247
|
-
: "当前由
|
|
247
|
+
: "当前由 wl-skills-ui 负责样式绝对管控即可,不强制桥接 wl-skills-kit。",
|
|
248
248
|
commands: needed
|
|
249
249
|
? ["wl-skills validate-page <page>", "wl-skills doctor-ui <project>"]
|
|
250
250
|
: [],
|
|
@@ -267,7 +267,7 @@ function recommendFromScan(args = {}) {
|
|
|
267
267
|
nextActions.add(
|
|
268
268
|
"先用 skin/native 样式层完成视觉统一,再判断是否需要代码级修复",
|
|
269
269
|
);
|
|
270
|
-
nextActions.add("修复前调用
|
|
270
|
+
nextActions.add("修复前调用 wl_ui_fix_dry_run 并向用户展示摘要");
|
|
271
271
|
} else {
|
|
272
272
|
recommendedFlows.add("full-audit");
|
|
273
273
|
nextActions.add("当前扫描未发现规则问题,建议保留周期性 full-audit");
|
|
@@ -276,7 +276,7 @@ function recommendFromScan(args = {}) {
|
|
|
276
276
|
if (categories.has("color") || categories.has("token")) {
|
|
277
277
|
recommendedFlows.add("progressive-migrate");
|
|
278
278
|
nextActions.add(
|
|
279
|
-
"硬编码色值应迁移为
|
|
279
|
+
"硬编码色值应迁移为 wl-skills-ui tokens 或 Element Plus 变量",
|
|
280
280
|
);
|
|
281
281
|
}
|
|
282
282
|
|
|
@@ -288,8 +288,8 @@ function recommendFromScan(args = {}) {
|
|
|
288
288
|
componentCoverage: coverage,
|
|
289
289
|
recommendedTools:
|
|
290
290
|
issues.length > 0
|
|
291
|
-
? ["
|
|
292
|
-
: ["
|
|
291
|
+
? ["wl_ui_scan", "wl_ui_fix_dry_run"]
|
|
292
|
+
: ["wl_ui_scan"],
|
|
293
293
|
kitBridge: buildKitBridge(shouldUseKit),
|
|
294
294
|
nextActions: [...nextActions].sort(),
|
|
295
295
|
};
|
|
@@ -297,7 +297,7 @@ function recommendFromScan(args = {}) {
|
|
|
297
297
|
|
|
298
298
|
async function dispatchTool(id, name, args) {
|
|
299
299
|
try {
|
|
300
|
-
if (name === "
|
|
300
|
+
if (name === "wl_ui_check") {
|
|
301
301
|
const result = await runScanner("check", args);
|
|
302
302
|
sendResult(id, {
|
|
303
303
|
content: [{ type: "text", text: result.text }],
|
|
@@ -305,7 +305,7 @@ async function dispatchTool(id, name, args) {
|
|
|
305
305
|
});
|
|
306
306
|
return;
|
|
307
307
|
}
|
|
308
|
-
if (name === "
|
|
308
|
+
if (name === "wl_ui_scan") {
|
|
309
309
|
const result = await runScanner("scan", args);
|
|
310
310
|
sendResult(id, {
|
|
311
311
|
content: [{ type: "text", text: result.text }],
|
|
@@ -313,7 +313,7 @@ async function dispatchTool(id, name, args) {
|
|
|
313
313
|
});
|
|
314
314
|
return;
|
|
315
315
|
}
|
|
316
|
-
if (name === "
|
|
316
|
+
if (name === "wl_ui_fix_dry_run") {
|
|
317
317
|
const result = await runScanner("fix", args);
|
|
318
318
|
sendResult(id, {
|
|
319
319
|
content: [{ type: "text", text: result.text }],
|
|
@@ -321,11 +321,11 @@ async function dispatchTool(id, name, args) {
|
|
|
321
321
|
});
|
|
322
322
|
return;
|
|
323
323
|
}
|
|
324
|
-
if (name === "
|
|
324
|
+
if (name === "wl_ui_skill_prompt") {
|
|
325
325
|
sendResult(id, { content: [{ type: "text", text: skillPrompt() }] });
|
|
326
326
|
return;
|
|
327
327
|
}
|
|
328
|
-
if (name === "
|
|
328
|
+
if (name === "wl_ui_route_intent") {
|
|
329
329
|
sendResult(id, {
|
|
330
330
|
content: [
|
|
331
331
|
{ type: "text", text: JSON.stringify(routeIntent(args), null, 2) },
|
|
@@ -333,7 +333,7 @@ async function dispatchTool(id, name, args) {
|
|
|
333
333
|
});
|
|
334
334
|
return;
|
|
335
335
|
}
|
|
336
|
-
if (name === "
|
|
336
|
+
if (name === "wl_ui_recommend_flow") {
|
|
337
337
|
sendResult(id, {
|
|
338
338
|
content: [
|
|
339
339
|
{
|
|
@@ -379,7 +379,7 @@ process.stdin.on("data", (chunk) => {
|
|
|
379
379
|
sendResult(id, {
|
|
380
380
|
protocolVersion: "2024-11-05",
|
|
381
381
|
capabilities: { tools: {} },
|
|
382
|
-
serverInfo: { name: "
|
|
382
|
+
serverInfo: { name: "wl-skills-ui", version: PKG.version },
|
|
383
383
|
});
|
|
384
384
|
} else if (method === "tools/list") {
|
|
385
385
|
sendResult(id, { tools: TOOLS });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agile-team/wl-skills-ui",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.12",
|
|
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",
|
package/scanner/coverage.mjs
CHANGED
|
@@ -1,3 +1,34 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
|
|
5
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const VENDOR_REGISTRY_PATH = resolve(
|
|
7
|
+
__dirname,
|
|
8
|
+
"..",
|
|
9
|
+
"skills",
|
|
10
|
+
"_meta",
|
|
11
|
+
"_compat",
|
|
12
|
+
"vendors.json",
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
// 启动时一次性 parse + 编译 RegExp,复用整个进程生命周期;不引入运行时性能开销
|
|
16
|
+
const VENDOR_REGISTRY = (() => {
|
|
17
|
+
const raw = JSON.parse(readFileSync(VENDOR_REGISTRY_PATH, "utf8"));
|
|
18
|
+
return raw.vendors
|
|
19
|
+
.filter((v) => Array.isArray(v.patterns) && v.patterns.length > 0)
|
|
20
|
+
.map((v) => ({
|
|
21
|
+
id: v.id,
|
|
22
|
+
label: v.label,
|
|
23
|
+
vendor: v.label,
|
|
24
|
+
skill: v.skill,
|
|
25
|
+
baseline: v.baseline || [],
|
|
26
|
+
pattern: new RegExp(v.patterns.join("|"), "g"),
|
|
27
|
+
}));
|
|
28
|
+
})();
|
|
29
|
+
|
|
30
|
+
const VENDOR_PATTERNS = VENDOR_REGISTRY;
|
|
31
|
+
|
|
1
32
|
const ELEMENT_SKILL_MAP = {
|
|
2
33
|
"el-table": "element/el-table",
|
|
3
34
|
"el-table-column": "element/el-table",
|
|
@@ -37,26 +68,7 @@ const ELEMENT_SKILL_MAP = {
|
|
|
37
68
|
"el-collapse": "element/el-feedback",
|
|
38
69
|
};
|
|
39
70
|
|
|
40
|
-
|
|
41
|
-
{
|
|
42
|
-
pattern: /<\/?Base[A-Z][\w-]*/g,
|
|
43
|
-
vendor: "Base*",
|
|
44
|
-
skill: "vendors/base-table",
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
pattern: /<\/?base-[\w-]+/g,
|
|
48
|
-
vendor: "base-*",
|
|
49
|
-
skill: "vendors/base-table",
|
|
50
|
-
},
|
|
51
|
-
{ pattern: /<\/?jh-[\w-]+/g, vendor: "jh-*", skill: "vendors/jh-components" },
|
|
52
|
-
{ pattern: /<\/?C_[\w-]+/g, vendor: "C_*", skill: "vendors/c-components" },
|
|
53
|
-
{ pattern: /<\/?c-[\w-]+/g, vendor: "c-*", skill: "vendors/c-components" },
|
|
54
|
-
{
|
|
55
|
-
pattern: /ag-grid|agGrid|\.ag-root-wrapper/g,
|
|
56
|
-
vendor: "AG Grid",
|
|
57
|
-
skill: "vendors/ag-grid",
|
|
58
|
-
},
|
|
59
|
-
];
|
|
71
|
+
// VENDOR_PATTERNS 现由 vendors.json 单一事实源驱动(见文件顶部 VENDOR_REGISTRY)
|
|
60
72
|
|
|
61
73
|
const LAYOUT_PATTERNS = [
|
|
62
74
|
{
|
|
@@ -233,13 +245,13 @@ export function recommendFlows({ issues = [], coverage = {} } = {}) {
|
|
|
233
245
|
if (issues.length === 0) {
|
|
234
246
|
flows.push("full-audit");
|
|
235
247
|
nextActions.push(
|
|
236
|
-
"保持
|
|
248
|
+
"保持 wl-skills-ui 样式入口,定期运行 wl_ui_scan 做只读审计",
|
|
237
249
|
);
|
|
238
250
|
} else {
|
|
239
251
|
flows.push("legacy-skin-align");
|
|
240
|
-
nextActions.push("先运行
|
|
252
|
+
nextActions.push("先运行 wl_ui_scan --mode skin 确认 L0/L1/L2 样式偏差");
|
|
241
253
|
nextActions.push(
|
|
242
|
-
"修复前运行
|
|
254
|
+
"修复前运行 wl_ui_fix_dry_run 预览改动,不直接写入业务文件",
|
|
243
255
|
);
|
|
244
256
|
}
|
|
245
257
|
|
|
@@ -278,7 +290,7 @@ export function recommendFlows({ issues = [], coverage = {} } = {}) {
|
|
|
278
290
|
needed: shouldUseKit,
|
|
279
291
|
reason: shouldUseKit
|
|
280
292
|
? "扫描结果涉及页面结构、BaseTable 或操作列规范,建议在视觉统一后使用 wl-skills-kit 做规范化生成/修复。"
|
|
281
|
-
: "当前更适合由
|
|
293
|
+
: "当前更适合由 wl-skills-ui 先完成样式绝对管控,无需强制切换到 wl-skills-kit。",
|
|
282
294
|
commands: shouldUseKit
|
|
283
295
|
? ["wl-skills validate-page <page>", "wl-skills doctor-ui <project>"]
|
|
284
296
|
: [],
|