@agile-team/wl-skills-kit 2.4.1 → 2.5.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 +53 -1
- package/README.md +104 -39
- package/bin/wl-skills.js +344 -44
- package/docs/ai/345/205/250/346/231/257/345/210/206/346/236/220.md +3 -3
- package/files/.github/copilot-instructions.md +361 -322
- package/files/.github/guides/architecture.md +6 -3
- package/files/.github/guides/usage.md +48 -13
- package/files/.github/skills/_compat/README.md +4 -2
- package/files/.github/skills/_registry.md +18 -16
- package/files/.github/skills/core/page-codegen/SKILL.md +149 -74
- package/files/.github/skills/core/page-codegen/USAGE.md +33 -12
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-DETAIL-TABS.md +80 -48
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-FORM-ROUTE.md +183 -55
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-LIST.md +110 -21
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-MASTER-DETAIL.md +29 -9
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-RECORD-FORM.md +93 -48
- package/files/.github/skills/core/page-codegen/templates/universal/TPL-TREE-LIST.md +49 -29
- package/files/.github/skills/sync/menu-sync/SKILL.md +27 -13
- package/mcp/server.js +279 -195
- package/mcp/tools/menuSync.js +416 -96
- package/mcp/tools/projectTools.js +336 -124
- package/package.json +31 -2
package/bin/wl-skills.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* wl-skills-kit CLI v2.
|
|
4
|
+
* wl-skills-kit CLI v2.5.0
|
|
5
5
|
*
|
|
6
6
|
* 命令:
|
|
7
7
|
* init 全量安装(默认,向后兼容)
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* clean 构建清理(移除 AI 指令/文档/样例,保留组件和类型)
|
|
10
10
|
* check 环境预检(工具链 / MCP 配置 / manifest)
|
|
11
11
|
* diff 对比已安装文件与当前 kit 版本
|
|
12
|
-
* validate 静态检查 src/views
|
|
12
|
+
* validate 静态检查 src/views 页面文件完整性、AGGrid、skills-ui runtime、mock
|
|
13
|
+
* validate-page validate 的别名,适用于单页/目录检查
|
|
14
|
+
* doctor-ui 检查 @agile-team/wk-skills-ui 接入完整性
|
|
13
15
|
* export 导出 SYS_MENU / SYS_DICT / SYS_PERMISSION 为 xlsx
|
|
14
16
|
* --help 帮助
|
|
15
17
|
* --dry-run 预览模式(所有命令均支持)
|
|
@@ -44,7 +46,9 @@ if (showHelp) {
|
|
|
44
46
|
clean 构建清理(移除开发期 AI 文件,保留 src/components + src/types)
|
|
45
47
|
check 环境预检(Node / 工具链 / MCP 配置 / manifest)
|
|
46
48
|
diff 对比已安装文件与当前 kit 版本的差异
|
|
47
|
-
validate 静态检查 src/views
|
|
49
|
+
validate 静态检查 src/views 页面文件、AGGrid、skills-ui runtime、mock
|
|
50
|
+
validate-page validate 的别名,适用于单页/目录检查
|
|
51
|
+
doctor-ui 检查 @agile-team/wk-skills-ui 接入完整性
|
|
48
52
|
export 导出 reports/SYS_* 数据为 xlsx
|
|
49
53
|
|
|
50
54
|
选项:
|
|
@@ -60,6 +64,8 @@ if (showHelp) {
|
|
|
60
64
|
npx @agile-team/wl-skills-kit check 检查本地环境
|
|
61
65
|
npx @agile-team/wl-skills-kit diff 查看当前项目与最新 kit 差异
|
|
62
66
|
npx @agile-team/wl-skills-kit validate 检查 src/views 页面文件
|
|
67
|
+
npx @agile-team/wl-skills-kit validate-page src/views/mdata/model/demo
|
|
68
|
+
npx @agile-team/wl-skills-kit doctor-ui 检查 wk-skills-ui 接入
|
|
63
69
|
npx @agile-team/wl-skills-kit export 导出菜单/字典/权限 xlsx
|
|
64
70
|
npx @agile-team/wl-skills-kit clean 清理开发期文件
|
|
65
71
|
npx @agile-team/wl-skills-kit clean --keep-reports 保留 reports/中的菜单/字典数据
|
|
@@ -143,7 +149,7 @@ function removeFileAndEmptyParents(filePath) {
|
|
|
143
149
|
} else {
|
|
144
150
|
break;
|
|
145
151
|
}
|
|
146
|
-
} catch
|
|
152
|
+
} catch {
|
|
147
153
|
break;
|
|
148
154
|
}
|
|
149
155
|
}
|
|
@@ -154,7 +160,7 @@ function readManifest() {
|
|
|
154
160
|
if (fs.existsSync(MANIFEST_PATH)) {
|
|
155
161
|
try {
|
|
156
162
|
return JSON.parse(fs.readFileSync(MANIFEST_PATH, "utf8"));
|
|
157
|
-
} catch
|
|
163
|
+
} catch {
|
|
158
164
|
return null;
|
|
159
165
|
}
|
|
160
166
|
}
|
|
@@ -332,9 +338,11 @@ function runInstall(incremental) {
|
|
|
332
338
|
if (dryRun) {
|
|
333
339
|
const exists = fs.existsSync(dest);
|
|
334
340
|
console.log(" " + (exists ? "覆盖" : "新增") + " " + relPath);
|
|
335
|
-
exists
|
|
341
|
+
if (exists) updated++;
|
|
342
|
+
else created++;
|
|
336
343
|
} else {
|
|
337
|
-
copyFileSafe(src, dest) === "created"
|
|
344
|
+
if (copyFileSafe(src, dest) === "created") created++;
|
|
345
|
+
else updated++;
|
|
338
346
|
}
|
|
339
347
|
}
|
|
340
348
|
|
|
@@ -372,9 +380,11 @@ function runInstall(incremental) {
|
|
|
372
380
|
console.log(
|
|
373
381
|
" " + (ecExists ? "覆盖" : "新增") + " [编辑器] " + ecPath,
|
|
374
382
|
);
|
|
375
|
-
ecExists
|
|
383
|
+
if (ecExists) updated++;
|
|
384
|
+
else created++;
|
|
376
385
|
} else {
|
|
377
|
-
writeFile(ecDest, ecContent) === "created"
|
|
386
|
+
if (writeFile(ecDest, ecContent) === "created") created++;
|
|
387
|
+
else updated++;
|
|
378
388
|
}
|
|
379
389
|
}
|
|
380
390
|
}
|
|
@@ -411,6 +421,20 @@ function runInstall(incremental) {
|
|
|
411
421
|
|
|
412
422
|
if (!dryRun) writeManifest(newManifest);
|
|
413
423
|
|
|
424
|
+
// ── Step 5: 非耦合桥接提醒(不自动安装 wk-skills-ui)───────────────────────
|
|
425
|
+
|
|
426
|
+
const targetPkgPath = path.join(TARGET_DIR, "package.json");
|
|
427
|
+
let hasUiPackage = false;
|
|
428
|
+
if (fs.existsSync(targetPkgPath)) {
|
|
429
|
+
try {
|
|
430
|
+
const targetPkg = JSON.parse(fs.readFileSync(targetPkgPath, "utf8"));
|
|
431
|
+
const deps = { ...targetPkg.dependencies, ...targetPkg.devDependencies };
|
|
432
|
+
hasUiPackage = Boolean(deps["@agile-team/wk-skills-ui"]);
|
|
433
|
+
} catch {
|
|
434
|
+
hasUiPackage = false;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
414
438
|
// ── 输出统计 ──────────────────────────────────────────────────────
|
|
415
439
|
|
|
416
440
|
const total = created + updated + unchanged;
|
|
@@ -455,6 +479,19 @@ function runInstall(incremental) {
|
|
|
455
479
|
}
|
|
456
480
|
}
|
|
457
481
|
console.log("");
|
|
482
|
+
if (hasUiPackage) {
|
|
483
|
+
console.log(
|
|
484
|
+
" ℹ 检测到 @agile-team/wk-skills-ui:两包独立分工,可组合触发 UI 风格对齐流程。",
|
|
485
|
+
);
|
|
486
|
+
} else {
|
|
487
|
+
console.log(
|
|
488
|
+
" ℹ 可选桥接:如需统一 UI 风格/老项目化妆层,可安装 @agile-team/wk-skills-ui。",
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
console.log(
|
|
492
|
+
" ℹ 规范插件:建议执行 npx @robot-admin/git-standards init 接入代码质量与提交规范。",
|
|
493
|
+
);
|
|
494
|
+
console.log("");
|
|
458
495
|
}
|
|
459
496
|
|
|
460
497
|
// ─── 命令: clean ────────────────────────────────────────────────────────
|
|
@@ -537,7 +574,11 @@ function expectedManifestFiles() {
|
|
|
537
574
|
for (const relPath of files) {
|
|
538
575
|
expected[relPath] = fileMd5(path.join(FILES_DIR, relPath));
|
|
539
576
|
}
|
|
540
|
-
const instructionsSrc = path.join(
|
|
577
|
+
const instructionsSrc = path.join(
|
|
578
|
+
FILES_DIR,
|
|
579
|
+
".github",
|
|
580
|
+
"copilot-instructions.md",
|
|
581
|
+
);
|
|
541
582
|
if (fs.existsSync(instructionsSrc)) {
|
|
542
583
|
const raw = fs.readFileSync(instructionsSrc, "utf8");
|
|
543
584
|
for (const [ecPath, ecContent] of getEditorConfigs(raw)) {
|
|
@@ -567,19 +608,34 @@ function runCheck() {
|
|
|
567
608
|
|
|
568
609
|
const toolFiles = [".prettierrc.js", "eslint.config.ts", ".husky"];
|
|
569
610
|
for (const rel of toolFiles) {
|
|
570
|
-
add(
|
|
611
|
+
add(
|
|
612
|
+
rel,
|
|
613
|
+
fs.existsSync(path.join(TARGET_DIR, rel)),
|
|
614
|
+
fs.existsSync(path.join(TARGET_DIR, rel)) ? "存在" : "缺失",
|
|
615
|
+
);
|
|
571
616
|
}
|
|
572
617
|
|
|
573
618
|
const manifest = readManifest();
|
|
574
|
-
add(
|
|
619
|
+
add(
|
|
620
|
+
MANIFEST_NAME,
|
|
621
|
+
Boolean(manifest),
|
|
622
|
+
manifest ? "已安装 v" + manifest.version : "未安装",
|
|
623
|
+
);
|
|
575
624
|
|
|
576
|
-
const envPath = path.join(
|
|
625
|
+
const envPath = path.join(
|
|
626
|
+
TARGET_DIR,
|
|
627
|
+
".github",
|
|
628
|
+
"skills",
|
|
629
|
+
"sync",
|
|
630
|
+
"env.local.json",
|
|
631
|
+
);
|
|
577
632
|
let envOk = false;
|
|
578
633
|
let envDetail = "缺失";
|
|
579
634
|
if (fs.existsSync(envPath)) {
|
|
580
635
|
try {
|
|
581
636
|
const env = JSON.parse(fs.readFileSync(envPath, "utf8"));
|
|
582
|
-
const gatewayOk =
|
|
637
|
+
const gatewayOk =
|
|
638
|
+
env.gatewayPath && !String(env.gatewayPath).includes("你的网关");
|
|
583
639
|
const tokenOk = env.token && !String(env.token).includes("Bearer Token");
|
|
584
640
|
envOk = Boolean(gatewayOk && tokenOk);
|
|
585
641
|
envDetail = envOk ? "已填写 gatewayPath/token" : "存在但仍含占位值";
|
|
@@ -589,15 +645,33 @@ function runCheck() {
|
|
|
589
645
|
}
|
|
590
646
|
add("MCP env.local.json", envOk, envDetail);
|
|
591
647
|
|
|
592
|
-
const mcpServer = path.join(
|
|
593
|
-
|
|
648
|
+
const mcpServer = path.join(
|
|
649
|
+
TARGET_DIR,
|
|
650
|
+
"node_modules",
|
|
651
|
+
"@agile-team",
|
|
652
|
+
"wl-skills-kit",
|
|
653
|
+
"mcp",
|
|
654
|
+
"server.js",
|
|
655
|
+
);
|
|
656
|
+
add(
|
|
657
|
+
"MCP server",
|
|
658
|
+
fs.existsSync(mcpServer) ||
|
|
659
|
+
fs.existsSync(path.join(__dirname, "..", "mcp", "server.js")),
|
|
660
|
+
"server.js 可发现",
|
|
661
|
+
);
|
|
594
662
|
|
|
595
663
|
for (const item of checks) {
|
|
596
|
-
console.log(
|
|
664
|
+
console.log(
|
|
665
|
+
" " + statusIcon(item.ok) + " " + item.name + " — " + item.detail,
|
|
666
|
+
);
|
|
597
667
|
}
|
|
598
668
|
const failed = checks.filter((item) => !item.ok).length;
|
|
599
669
|
console.log("");
|
|
600
|
-
console.log(
|
|
670
|
+
console.log(
|
|
671
|
+
failed === 0
|
|
672
|
+
? " ✔ 环境预检通过"
|
|
673
|
+
: " ⚠ 环境预检完成,发现 " + failed + " 项需处理",
|
|
674
|
+
);
|
|
601
675
|
console.log("");
|
|
602
676
|
if (failed > 0) process.exitCode = 1;
|
|
603
677
|
}
|
|
@@ -633,7 +707,9 @@ function runDiff() {
|
|
|
633
707
|
}
|
|
634
708
|
}
|
|
635
709
|
|
|
636
|
-
console.log(
|
|
710
|
+
console.log(
|
|
711
|
+
" 当前 manifest: " + (manifest ? "v" + manifest.version : "未找到"),
|
|
712
|
+
);
|
|
637
713
|
console.log(" 最新 kit: v" + PKG.version);
|
|
638
714
|
console.log(" 新增/缺失: " + added.length);
|
|
639
715
|
console.log(" 内容不同: " + changed.length);
|
|
@@ -645,7 +721,8 @@ function runDiff() {
|
|
|
645
721
|
if (list.length === 0) return;
|
|
646
722
|
console.log(" " + title + ":");
|
|
647
723
|
for (const relPath of list.slice(0, 80)) console.log(" - " + relPath);
|
|
648
|
-
if (list.length > 80)
|
|
724
|
+
if (list.length > 80)
|
|
725
|
+
console.log(" ... 还有 " + (list.length - 80) + " 项");
|
|
649
726
|
console.log("");
|
|
650
727
|
}
|
|
651
728
|
|
|
@@ -668,27 +745,53 @@ function scanPageDirs(scanRel) {
|
|
|
668
745
|
const pages = [];
|
|
669
746
|
for (const [dir, names] of dirs.entries()) {
|
|
670
747
|
if (!names.has("index.vue")) continue;
|
|
671
|
-
|
|
748
|
+
const indexPath = path.join(TARGET_DIR, dir, "index.vue");
|
|
749
|
+
const indexContent = fs.existsSync(indexPath)
|
|
750
|
+
? fs.readFileSync(indexPath, "utf8")
|
|
751
|
+
: "";
|
|
672
752
|
const dataPath = path.join(TARGET_DIR, dir, "data.ts");
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
753
|
+
const dataContent = fs.existsSync(dataPath)
|
|
754
|
+
? fs.readFileSync(dataPath, "utf8")
|
|
755
|
+
: "";
|
|
756
|
+
let apiConfigCount = 0;
|
|
757
|
+
if (dataContent)
|
|
758
|
+
apiConfigCount = (dataContent.match(/API_CONFIG/g) || []).length;
|
|
676
759
|
pages.push({
|
|
677
760
|
dir,
|
|
678
761
|
hasDataTs: names.has("data.ts"),
|
|
679
762
|
hasIndexScss: names.has("index.scss"),
|
|
680
763
|
hasApiMd: names.has("api.md"),
|
|
681
764
|
apiConfigCount,
|
|
765
|
+
baseTableCount: (indexContent.match(/<BaseTable\b/g) || []).length,
|
|
766
|
+
agGridCount: (indexContent.match(/render-type=["']agGrid["']/g) || [])
|
|
767
|
+
.length,
|
|
768
|
+
cidBindCount: (indexContent.match(/\bcid=|:cid=/g) || []).length,
|
|
769
|
+
hasDefineColumns: /defineColumns\s*\(/.test(dataContent),
|
|
770
|
+
hasRenderOps: /renderOps\s*\(/.test(dataContent),
|
|
771
|
+
hasOperationsArray: /operations\s*:/.test(dataContent),
|
|
772
|
+
hasEmptyOnClick: /onClick\s*:\s*\(\s*[^)]*\s*\)\s*=>\s*\{\s*\}/.test(
|
|
773
|
+
dataContent,
|
|
774
|
+
),
|
|
775
|
+
apiUrls: Array.from(
|
|
776
|
+
dataContent.matchAll(/:\s*["']([^"']+\/[^"']+)["']/g),
|
|
777
|
+
).map((m) => m[1]),
|
|
682
778
|
});
|
|
683
779
|
}
|
|
684
780
|
return pages.sort((a, b) => a.dir.localeCompare(b.dir));
|
|
685
781
|
}
|
|
686
782
|
|
|
783
|
+
function findMockFiles() {
|
|
784
|
+
const mockDir = path.join(TARGET_DIR, "mock");
|
|
785
|
+
if (!fs.existsSync(mockDir)) return [];
|
|
786
|
+
return walkDir(mockDir, TARGET_DIR).filter((rel) => /\.(ts|js)$/.test(rel));
|
|
787
|
+
}
|
|
788
|
+
|
|
687
789
|
function runValidate() {
|
|
688
|
-
const scanPath =
|
|
790
|
+
const scanPath =
|
|
791
|
+
args.find((a) => !a.startsWith("-") && a !== command) || "src/views";
|
|
689
792
|
const pages = scanPageDirs(scanPath);
|
|
690
793
|
console.log("");
|
|
691
|
-
console.log(" wl-skills-kit v" + PKG.version + " [
|
|
794
|
+
console.log(" wl-skills-kit v" + PKG.version + " [" + command + "]");
|
|
692
795
|
console.log(" 扫描目录: " + scanPath);
|
|
693
796
|
console.log("");
|
|
694
797
|
|
|
@@ -700,28 +803,195 @@ function runValidate() {
|
|
|
700
803
|
}
|
|
701
804
|
|
|
702
805
|
const issues = [];
|
|
806
|
+
const mockFiles = findMockFiles();
|
|
807
|
+
const mockContent = mockFiles
|
|
808
|
+
.map((rel) => fs.readFileSync(path.join(TARGET_DIR, rel), "utf8"))
|
|
809
|
+
.join("\n");
|
|
703
810
|
for (const page of pages) {
|
|
704
|
-
if (!page.hasDataTs)
|
|
705
|
-
|
|
706
|
-
|
|
811
|
+
if (!page.hasDataTs)
|
|
812
|
+
issues.push({
|
|
813
|
+
level: "warn",
|
|
814
|
+
dir: page.dir,
|
|
815
|
+
text: "缺 data.ts(需结合页面复杂度判断)",
|
|
816
|
+
});
|
|
817
|
+
if (!page.hasIndexScss)
|
|
818
|
+
issues.push({ level: "warn", dir: page.dir, text: "缺 index.scss" });
|
|
819
|
+
if (page.apiConfigCount > 0 && !page.hasApiMd)
|
|
820
|
+
issues.push({
|
|
821
|
+
level: "warn",
|
|
822
|
+
dir: page.dir,
|
|
823
|
+
text: "检测到 API_CONFIG 但缺 api.md",
|
|
824
|
+
});
|
|
825
|
+
if (page.baseTableCount > 0 && page.agGridCount < page.baseTableCount)
|
|
826
|
+
issues.push({
|
|
827
|
+
level: "error",
|
|
828
|
+
dir: page.dir,
|
|
829
|
+
text: 'BaseTable 必须显式 render-type="agGrid"',
|
|
830
|
+
});
|
|
831
|
+
if (page.baseTableCount > 0 && page.cidBindCount < page.baseTableCount)
|
|
832
|
+
issues.push({
|
|
833
|
+
level: "error",
|
|
834
|
+
dir: page.dir,
|
|
835
|
+
text: "BaseTable 必须配置全局唯一 cid / :cid",
|
|
836
|
+
});
|
|
837
|
+
if (page.hasDataTs && page.baseTableCount > 0 && !page.hasDefineColumns)
|
|
838
|
+
issues.push({
|
|
839
|
+
level: "error",
|
|
840
|
+
dir: page.dir,
|
|
841
|
+
text: "表格列必须使用 wk-skills-ui defineColumns()",
|
|
842
|
+
});
|
|
843
|
+
if (page.hasOperationsArray)
|
|
844
|
+
issues.push({
|
|
845
|
+
level: "error",
|
|
846
|
+
dir: page.dir,
|
|
847
|
+
text: "操作列禁止 operations 数组,必须使用 defaultSlot + renderOps()",
|
|
848
|
+
});
|
|
849
|
+
if (
|
|
850
|
+
page.hasDataTs &&
|
|
851
|
+
page.baseTableCount > 0 &&
|
|
852
|
+
!page.hasRenderOps &&
|
|
853
|
+
/操作|_action/.test(
|
|
854
|
+
fs.readFileSync(path.join(TARGET_DIR, page.dir, "data.ts"), "utf8"),
|
|
855
|
+
)
|
|
856
|
+
)
|
|
857
|
+
issues.push({
|
|
858
|
+
level: "warn",
|
|
859
|
+
dir: page.dir,
|
|
860
|
+
text: "疑似存在操作列但未使用 renderOps()",
|
|
861
|
+
});
|
|
862
|
+
if (page.hasEmptyOnClick)
|
|
863
|
+
issues.push({
|
|
864
|
+
level: "error",
|
|
865
|
+
dir: page.dir,
|
|
866
|
+
text: "存在空 onClick: () => {}",
|
|
867
|
+
});
|
|
868
|
+
if (page.apiConfigCount > 0 && mockFiles.length === 0)
|
|
869
|
+
issues.push({
|
|
870
|
+
level: "warn",
|
|
871
|
+
dir: page.dir,
|
|
872
|
+
text: "检测到 API_CONFIG 但项目 mock/ 目录无 mock 文件",
|
|
873
|
+
});
|
|
874
|
+
for (const url of page.apiUrls.filter((item) => item.startsWith("/"))) {
|
|
875
|
+
const mockUrl = `/dev-api${url}`;
|
|
876
|
+
if (mockContent && !mockContent.includes(mockUrl))
|
|
877
|
+
issues.push({
|
|
878
|
+
level: "warn",
|
|
879
|
+
dir: page.dir,
|
|
880
|
+
text: "mock 中未发现端点 " + mockUrl,
|
|
881
|
+
});
|
|
882
|
+
}
|
|
707
883
|
}
|
|
708
884
|
|
|
709
885
|
console.log(" 页面目录: " + pages.length);
|
|
710
886
|
console.log(" 提示项: " + issues.length);
|
|
711
887
|
console.log("");
|
|
888
|
+
const errors = issues.filter((issue) => issue.level === "error").length;
|
|
712
889
|
for (const issue of issues) {
|
|
713
|
-
|
|
890
|
+
const icon = issue.level === "error" ? "✖" : "⚠";
|
|
891
|
+
console.log(" " + icon + " " + issue.dir + " — " + issue.text);
|
|
714
892
|
}
|
|
715
893
|
if (issues.length === 0) console.log(" ✔ 页面文件完整性检查通过");
|
|
716
894
|
console.log("");
|
|
717
|
-
if (issues.length > 0) process.exitCode = 1;
|
|
895
|
+
if (errors > 0 || issues.length > 0) process.exitCode = 1;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
function readJsonSafe(filePath) {
|
|
899
|
+
if (!fs.existsSync(filePath)) return null;
|
|
900
|
+
try {
|
|
901
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
902
|
+
} catch {
|
|
903
|
+
return null;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
function runDoctorUi() {
|
|
908
|
+
console.log("");
|
|
909
|
+
console.log(" wl-skills-kit v" + PKG.version + " [doctor-ui]");
|
|
910
|
+
console.log(" 目标目录: " + TARGET_DIR);
|
|
911
|
+
console.log("");
|
|
912
|
+
|
|
913
|
+
const checks = [];
|
|
914
|
+
function add(name, ok, detail) {
|
|
915
|
+
checks.push({ name, ok, detail });
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
const pkg = readJsonSafe(path.join(TARGET_DIR, "package.json"));
|
|
919
|
+
const deps = pkg ? { ...pkg.dependencies, ...pkg.devDependencies } : {};
|
|
920
|
+
add(
|
|
921
|
+
"@agile-team/wk-skills-ui",
|
|
922
|
+
Boolean(deps["@agile-team/wk-skills-ui"]),
|
|
923
|
+
deps["@agile-team/wk-skills-ui"] || "未安装",
|
|
924
|
+
);
|
|
925
|
+
add(
|
|
926
|
+
"@element-plus/icons-vue",
|
|
927
|
+
Boolean(deps["@element-plus/icons-vue"]),
|
|
928
|
+
deps["@element-plus/icons-vue"] || "未安装",
|
|
929
|
+
);
|
|
930
|
+
|
|
931
|
+
const files = fs.existsSync(TARGET_DIR)
|
|
932
|
+
? walkDir(TARGET_DIR, TARGET_DIR)
|
|
933
|
+
: [];
|
|
934
|
+
const sourceFiles = files.filter(
|
|
935
|
+
(rel) =>
|
|
936
|
+
/\.(ts|vue|scss|html)$/.test(rel) && !rel.startsWith("node_modules/"),
|
|
937
|
+
);
|
|
938
|
+
const readAll = (pattern) =>
|
|
939
|
+
sourceFiles
|
|
940
|
+
.filter((rel) => pattern.test(rel))
|
|
941
|
+
.map((rel) => fs.readFileSync(path.join(TARGET_DIR, rel), "utf8"))
|
|
942
|
+
.join("\n");
|
|
943
|
+
const allSource = readAll(/.*/);
|
|
944
|
+
|
|
945
|
+
add(
|
|
946
|
+
"design tokens",
|
|
947
|
+
/@agile-team\/wk-skills-ui\/design\/tokens|dist\/tokens\.css/.test(
|
|
948
|
+
allSource,
|
|
949
|
+
),
|
|
950
|
+
"需引入 design tokens",
|
|
951
|
+
);
|
|
952
|
+
add(
|
|
953
|
+
"styles preset",
|
|
954
|
+
/@agile-team\/wk-skills-ui\/styles/.test(allSource),
|
|
955
|
+
"需引入 styles 或 skin preset",
|
|
956
|
+
);
|
|
957
|
+
add(
|
|
958
|
+
"installCommonPreset",
|
|
959
|
+
/installCommonPreset\s*\(/.test(allSource),
|
|
960
|
+
"需在入口或业务 preset 中调用",
|
|
961
|
+
);
|
|
962
|
+
add(
|
|
963
|
+
"defineColumns",
|
|
964
|
+
/defineColumns\s*\(/.test(allSource),
|
|
965
|
+
"页面列定义需使用 defineColumns",
|
|
966
|
+
);
|
|
967
|
+
add("renderOps", /renderOps\s*\(/.test(allSource), "操作列需使用 renderOps");
|
|
968
|
+
|
|
969
|
+
for (const item of checks) {
|
|
970
|
+
console.log(
|
|
971
|
+
" " + statusIcon(item.ok) + " " + item.name + " — " + item.detail,
|
|
972
|
+
);
|
|
973
|
+
}
|
|
974
|
+
const failed = checks.filter((item) => !item.ok).length;
|
|
975
|
+
console.log("");
|
|
976
|
+
console.log(
|
|
977
|
+
failed === 0
|
|
978
|
+
? " ✔ wk-skills-ui 接入检查通过"
|
|
979
|
+
: " ⚠ wk-skills-ui 接入仍有 " + failed + " 项需处理",
|
|
980
|
+
);
|
|
981
|
+
console.log("");
|
|
982
|
+
if (failed > 0) process.exitCode = 1;
|
|
718
983
|
}
|
|
719
984
|
|
|
720
985
|
function parseMarkdownTable(content) {
|
|
721
986
|
return content
|
|
722
987
|
.split(/\r?\n/)
|
|
723
988
|
.filter((line) => /^\|.*\|$/.test(line) && !/^\|\s*-+/.test(line))
|
|
724
|
-
.map((line) =>
|
|
989
|
+
.map((line) =>
|
|
990
|
+
line
|
|
991
|
+
.split("|")
|
|
992
|
+
.slice(1, -1)
|
|
993
|
+
.map((cell) => cell.trim()),
|
|
994
|
+
);
|
|
725
995
|
}
|
|
726
996
|
|
|
727
997
|
function runExport() {
|
|
@@ -743,7 +1013,11 @@ function runExport() {
|
|
|
743
1013
|
if (!fs.existsSync(full)) continue;
|
|
744
1014
|
const content = fs.readFileSync(full, "utf8");
|
|
745
1015
|
let rows = parseMarkdownTable(content);
|
|
746
|
-
if (rows.length === 0)
|
|
1016
|
+
if (rows.length === 0)
|
|
1017
|
+
rows = content
|
|
1018
|
+
.split(/\r?\n/)
|
|
1019
|
+
.filter(Boolean)
|
|
1020
|
+
.map((line) => [line]);
|
|
747
1021
|
sheets.push([sheetName, rows]);
|
|
748
1022
|
addedSheets++;
|
|
749
1023
|
}
|
|
@@ -764,13 +1038,19 @@ function runExport() {
|
|
|
764
1038
|
let XLSX;
|
|
765
1039
|
try {
|
|
766
1040
|
XLSX = require("xlsx");
|
|
767
|
-
} catch
|
|
768
|
-
console.error(
|
|
1041
|
+
} catch {
|
|
1042
|
+
console.error(
|
|
1043
|
+
" ✖ 未找到 xlsx 依赖,请重新安装最新 @agile-team/wl-skills-kit",
|
|
1044
|
+
);
|
|
769
1045
|
process.exit(1);
|
|
770
1046
|
}
|
|
771
1047
|
const wb = XLSX.utils.book_new();
|
|
772
1048
|
for (const [sheetName, rows] of sheets) {
|
|
773
|
-
XLSX.utils.book_append_sheet(
|
|
1049
|
+
XLSX.utils.book_append_sheet(
|
|
1050
|
+
wb,
|
|
1051
|
+
XLSX.utils.aoa_to_sheet(rows),
|
|
1052
|
+
sheetName,
|
|
1053
|
+
);
|
|
774
1054
|
}
|
|
775
1055
|
fs.mkdirSync(outDir, { recursive: true });
|
|
776
1056
|
XLSX.writeFile(wb, outFile);
|
|
@@ -783,14 +1063,34 @@ function runExport() {
|
|
|
783
1063
|
// ─── 主路由 ─────────────────────────────────────────────────────────────
|
|
784
1064
|
|
|
785
1065
|
switch (command) {
|
|
786
|
-
case "init":
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
case "
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
case "
|
|
1066
|
+
case "init":
|
|
1067
|
+
runInstall(false);
|
|
1068
|
+
break;
|
|
1069
|
+
case "update":
|
|
1070
|
+
runInstall(true);
|
|
1071
|
+
break;
|
|
1072
|
+
case "clean":
|
|
1073
|
+
runClean();
|
|
1074
|
+
break;
|
|
1075
|
+
case "check":
|
|
1076
|
+
runCheck();
|
|
1077
|
+
break;
|
|
1078
|
+
case "diff":
|
|
1079
|
+
runDiff();
|
|
1080
|
+
break;
|
|
1081
|
+
case "validate":
|
|
1082
|
+
case "validate-page":
|
|
1083
|
+
runValidate();
|
|
1084
|
+
break;
|
|
1085
|
+
case "doctor-ui":
|
|
1086
|
+
runDoctorUi();
|
|
1087
|
+
break;
|
|
1088
|
+
case "export":
|
|
1089
|
+
runExport();
|
|
1090
|
+
break;
|
|
793
1091
|
default:
|
|
794
|
-
console.error(
|
|
1092
|
+
console.error(
|
|
1093
|
+
' ✖ 未知命令: "' + command + '",请使用 --help 查看可用命令',
|
|
1094
|
+
);
|
|
795
1095
|
process.exit(1);
|
|
796
1096
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AI 辅助开发全景分析 & 架构演进蓝图
|
|
2
2
|
|
|
3
|
-
> **基于 wl-skills-kit v2.4.
|
|
3
|
+
> **基于 wl-skills-kit v2.4.x 架构**
|
|
4
4
|
> **日期**:2026-05-02
|
|
5
5
|
> **目标**:企业级通用 · 质量精度高 · 速度快 · 节省 token · 还原度高 · 开箱即用 · 支持 Agent Pipeline
|
|
6
6
|
|
|
@@ -33,7 +33,7 @@ L7 自演化体系 🔭 需要足够审计报告与模板样本后再规
|
|
|
33
33
|
|
|
34
34
|
---
|
|
35
35
|
|
|
36
|
-
## 3. v2.4.
|
|
36
|
+
## 3. v2.4.x 关键能力
|
|
37
37
|
|
|
38
38
|
### 3.1 Agent Pipeline
|
|
39
39
|
|
|
@@ -134,7 +134,7 @@ wls_code_scan
|
|
|
134
134
|
|
|
135
135
|
## 6. 结论
|
|
136
136
|
|
|
137
|
-
v2.4.
|
|
137
|
+
v2.4.x 后,wl-skills-kit 已具备搭建通用智能体的基础条件:
|
|
138
138
|
|
|
139
139
|
- 有 Skills 作为结构化能力单元
|
|
140
140
|
- 有 MCP 作为实时项目感知与副作用执行工具
|