@qilitt-mickey/vue3-temp-skill 1.1.25 → 1.1.26
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/SKILL.md +77 -37
- package/package.json +15 -1
- package/references/auth-pages.md +217 -0
- package/references/base-code-dict.md +7 -0
- package/references/chart-echarts.md +1 -1
- package/references/crud-pages.md +1 -1
- package/references/data-compare.md +7 -0
- package/references/data-mapping.md +7 -0
- package/references/data-screen.md +7 -0
- package/references/data-writeback.md +7 -0
- package/references/directives-advanced.md +7 -0
- package/references/download-export.md +7 -0
- package/references/feedback-loading.md +7 -0
- package/references/feedback-ui.md +7 -0
- package/references/file-management.md +7 -0
- package/references/flowchart-g6.md +7 -0
- package/references/form-advanced.md +1 -1
- package/references/graph-relation.md +7 -0
- package/references/i18n-localization.md +230 -0
- package/references/layout-theme.md +1 -1
- package/references/particles.md +7 -0
- package/references/project-inventory.md +7 -0
- package/references/qrcode-barcode.md +7 -0
- package/references/rich-text.md +7 -0
- package/references/seamless-scroll.md +7 -0
- package/references/table-vxe.md +1 -1
- package/references/tree-table.md +7 -0
- package/references/verify-captcha.md +7 -0
- package/references/websocket-realtime.md +7 -0
- package/references/workflow-bpmn.md +7 -0
- package/scripts/ai-content-audit.mjs +244 -0
- package/scripts/ai-match-audit.mjs +348 -0
- package/scripts/ai-workflow-sim.mjs +393 -0
- package/scripts/analyze-deps.mjs +278 -0
- package/scripts/check.cmd +7 -0
- package/scripts/check.mjs +95 -0
- package/scripts/cli.mjs +153 -0
- package/scripts/generate-index.mjs +214 -0
- package/scripts/match.py +323 -0
- package/scripts/modules.json +348 -0
- package/scripts/scaffold-module.mjs +232 -0
- package/scripts/validate.mjs +256 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AI 命中精度审计器
|
|
5
|
+
*
|
|
6
|
+
* 从 AI 使用角度审计技能的模块路由匹配系统:
|
|
7
|
+
* 1. 关键词重叠检测 — 同一关键词出现在多个模块中,AI 会产生歧义
|
|
8
|
+
* 2. 命中盲区检测 — 常见用户表述无对应关键词,AI 无法命中
|
|
9
|
+
* 3. 模块可命中性评分 — 每个模块的关键词覆盖度如何
|
|
10
|
+
* 4. 效果匹配规则审计 — SKILL.md 的效果匹配是否覆盖常见场景
|
|
11
|
+
* 5. 模块边界冲突 — 功能重叠的模块对,AI 难以区分
|
|
12
|
+
*
|
|
13
|
+
* 用法:
|
|
14
|
+
* node scripts/ai-match-audit.mjs # 全量审计
|
|
15
|
+
* node scripts/ai-match-audit.mjs --overlap # 只看关键词重叠
|
|
16
|
+
* node scripts/ai-match-audit.mjs --gaps # 只看命中盲区
|
|
17
|
+
* node scripts/ai-match-audit.mjs --score # 只看模块评分
|
|
18
|
+
* node scripts/ai-match-audit.mjs --json # JSON 输出
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import fs from "fs";
|
|
22
|
+
import path from "path";
|
|
23
|
+
import { fileURLToPath } from "url";
|
|
24
|
+
|
|
25
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
const ROOT = path.resolve(__dirname, "..");
|
|
27
|
+
const REFS_DIR = path.join(ROOT, "references");
|
|
28
|
+
const SKILL_FILE = path.join(ROOT, "SKILL.md");
|
|
29
|
+
|
|
30
|
+
const c = {
|
|
31
|
+
red: (s) => `\x1b[31m${s}\x1b[0m`,
|
|
32
|
+
green: (s) => `\x1b[32m${s}\x1b[0m`,
|
|
33
|
+
yellow: (s) => `\x1b[33m${s}\x1b[0m`,
|
|
34
|
+
cyan: (s) => `\x1b[36m${s}\x1b[0m`,
|
|
35
|
+
bold: (s) => `\x1b[1m${s}\x1b[0m`,
|
|
36
|
+
dim: (s) => `\x1b[2m${s}\x1b[0m`,
|
|
37
|
+
magenta: (s) => `\x1b[35m${s}\x1b[0m`,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// ── 从 SKILL.md 路由表提取模块关键词 ──────────────────────
|
|
41
|
+
function extractRoutingKeywords() {
|
|
42
|
+
const content = fs.readFileSync(SKILL_FILE, "utf-8");
|
|
43
|
+
|
|
44
|
+
// 标准业务面 + 专项能力包的关键词表
|
|
45
|
+
const tablePattern = /\|\s*\*\*(\w[\w-]*)\*\*\s*\|\s*(.+?)\s*\|/g;
|
|
46
|
+
const modules = {};
|
|
47
|
+
let m;
|
|
48
|
+
while ((m = tablePattern.exec(content)) !== null) {
|
|
49
|
+
const moduleId = m[1];
|
|
50
|
+
const keywordsStr = m[2];
|
|
51
|
+
// 跳过表头和非关键词行
|
|
52
|
+
if (moduleId === "模块" || keywordsStr.includes("------")) continue;
|
|
53
|
+
|
|
54
|
+
const keywords = keywordsStr
|
|
55
|
+
.split(/[、,,]/)
|
|
56
|
+
.map((k) => k.trim().replace(/[`*→]/g, "").trim())
|
|
57
|
+
.filter((k) => k.length > 0 && k !== "用法见各功能模块" && !k.startsWith("本文件仅索引"));
|
|
58
|
+
|
|
59
|
+
if (keywords.length > 0) {
|
|
60
|
+
modules[moduleId] = keywords;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return modules;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ── 从 SKILL.md 提取效果匹配规则 ──────────────────────────
|
|
67
|
+
function extractEffectRules() {
|
|
68
|
+
const content = fs.readFileSync(SKILL_FILE, "utf-8");
|
|
69
|
+
const rules = [];
|
|
70
|
+
const effectSection = content.match(/效果匹配:([\s\S]*?)(?:\n\d+\.\s|\n6\.\s)/);
|
|
71
|
+
if (effectSection) {
|
|
72
|
+
const lines = effectSection[1].split("\n");
|
|
73
|
+
for (const line of lines) {
|
|
74
|
+
const m = line.match(/-\s*(.+?)\s*→\s*(.+)/);
|
|
75
|
+
if (m) {
|
|
76
|
+
rules.push({ trigger: m[1].trim(), target: m[2].trim() });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return rules;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ── 常见用户表述(用于盲区检测)──────────────────────────
|
|
84
|
+
const commonPhrases = [
|
|
85
|
+
"表单", "搜索", "下拉选择", "拖拽", "拖动", "批量", "排序", "统计",
|
|
86
|
+
"日历", "时间选择", "日期选择", "树形", "树状", "卡片", "标签页",
|
|
87
|
+
"步骤条", "面包屑", "抽屉", "折叠面板", "穿梭框", "空状态",
|
|
88
|
+
"骨架屏", "分步表单", "条件筛选", "联动", "动态表单",
|
|
89
|
+
"数据看板", "仪表盘", "趋势图", "柱状图", "饼图", "折线图",
|
|
90
|
+
"地图", "热力图", "散点图", "雷达图",
|
|
91
|
+
"登录", "注册", "忘记密码", "扫码",
|
|
92
|
+
"打印", "水印", "全屏", "截图",
|
|
93
|
+
"拖拽排序", "行编辑", "单元格编辑", "虚拟列表",
|
|
94
|
+
"文件上传", "图片上传", "视频播放", "音频",
|
|
95
|
+
"PDF预览", "文档预览", "图片预览",
|
|
96
|
+
"工作流", "审批流", "流程设计",
|
|
97
|
+
"实时数据", "消息推送", "在线状态",
|
|
98
|
+
"响应式", "自适应", "断点",
|
|
99
|
+
"国际化", "多语言",
|
|
100
|
+
"暗色", "夜间模式", "换肤",
|
|
101
|
+
"拖拽上传", "断点续传",
|
|
102
|
+
"富文本", "Markdown",
|
|
103
|
+
"甘特图", "日历视图",
|
|
104
|
+
"组织架构", "部门树",
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
// ── 1. 关键词重叠检测 ─────────────────────────────────────
|
|
108
|
+
function detectOverlaps(modules) {
|
|
109
|
+
const keywordMap = {};
|
|
110
|
+
for (const [moduleId, keywords] of Object.entries(modules)) {
|
|
111
|
+
for (const kw of keywords) {
|
|
112
|
+
if (!keywordMap[kw]) keywordMap[kw] = [];
|
|
113
|
+
keywordMap[kw].push(moduleId);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const overlaps = [];
|
|
118
|
+
for (const [kw, mods] of Object.entries(keywordMap)) {
|
|
119
|
+
if (mods.length > 1) {
|
|
120
|
+
overlaps.push({ keyword: kw, modules: mods });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 模糊重叠:关键词包含关系("表格" 包含在 "高性能表格" 中)
|
|
125
|
+
const fuzzyOverlaps = [];
|
|
126
|
+
const allKeywords = Object.keys(keywordMap);
|
|
127
|
+
for (let i = 0; i < allKeywords.length; i++) {
|
|
128
|
+
for (let j = i + 1; j < allKeywords.length; j++) {
|
|
129
|
+
const a = allKeywords[i];
|
|
130
|
+
const b = allKeywords[j];
|
|
131
|
+
if (a !== b && (a.includes(b) || b.includes(a))) {
|
|
132
|
+
const modsA = keywordMap[a];
|
|
133
|
+
const modsB = keywordMap[b];
|
|
134
|
+
if (modsA.join(",") !== modsB.join(",")) {
|
|
135
|
+
fuzzyOverlaps.push({
|
|
136
|
+
keywordA: a, modulesA: modsA,
|
|
137
|
+
keywordB: b, modulesB: modsB,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return { overlaps, fuzzyOverlaps, keywordMap };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ── 2. 命中盲区检测 ───────────────────────────────────────
|
|
148
|
+
function detectGaps(modules, keywordMap) {
|
|
149
|
+
const allKeywords = new Set(Object.keys(keywordMap));
|
|
150
|
+
|
|
151
|
+
const gaps = [];
|
|
152
|
+
for (const phrase of commonPhrases) {
|
|
153
|
+
let matched = false;
|
|
154
|
+
for (const kw of allKeywords) {
|
|
155
|
+
if (phrase.includes(kw) || kw.includes(phrase)) {
|
|
156
|
+
matched = true;
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (!matched) {
|
|
161
|
+
gaps.push(phrase);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return gaps;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ── 3. 模块可命中性评分 ──────────────────────────────────
|
|
168
|
+
function scoreModules(modules, keywordMap) {
|
|
169
|
+
const scores = [];
|
|
170
|
+
for (const [moduleId, keywords] of Object.entries(modules)) {
|
|
171
|
+
let coverage = 0;
|
|
172
|
+
let specificity = 0;
|
|
173
|
+
let overlapCount = 0;
|
|
174
|
+
|
|
175
|
+
for (const kw of keywords) {
|
|
176
|
+
const mods = keywordMap[kw] || [];
|
|
177
|
+
if (mods.length === 1) coverage++;
|
|
178
|
+
else overlapCount++;
|
|
179
|
+
|
|
180
|
+
if (kw.length >= 4) specificity++;
|
|
181
|
+
else if (kw.length <= 2) specificity -= 0.5;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const coverageRate = keywords.length > 0 ? coverage / keywords.length : 0;
|
|
185
|
+
const totalScore = Math.round(
|
|
186
|
+
coverage * 10 +
|
|
187
|
+
specificity * 5 +
|
|
188
|
+
keywords.length * 2 -
|
|
189
|
+
overlapCount * 8
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
scores.push({
|
|
193
|
+
moduleId,
|
|
194
|
+
keywordCount: keywords.length,
|
|
195
|
+
uniqueKeywords: coverage,
|
|
196
|
+
overlappingKeywords: overlapCount,
|
|
197
|
+
coverageRate: `${Math.round(coverageRate * 100)}%`,
|
|
198
|
+
score: totalScore,
|
|
199
|
+
keywords,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
scores.sort((a, b) => b.score - a.score);
|
|
203
|
+
return scores;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ── 4. 模块边界冲突检测 ──────────────────────────────────
|
|
207
|
+
function detectBoundaryConflicts(modules) {
|
|
208
|
+
const conflicts = [
|
|
209
|
+
{
|
|
210
|
+
modules: ["crud-pages", "table-vxe"],
|
|
211
|
+
issue: "两者都是表格场景。用户说「表格」时 AI 无法区分标准 vs 高性能",
|
|
212
|
+
suggestion: "table-vxe 应明确「数据量大/虚拟滚动/复杂网格」为触发条件;crud-pages 明确「常规列表」",
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
modules: ["crud-pages", "tree-table"],
|
|
216
|
+
issue: "树形表格是列表的变体,但关键词「树表」不包含「表格」",
|
|
217
|
+
suggestion: "tree-table 增加「树形列表」「树状表格」关键词",
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
modules: ["form-advanced", "crud-pages"],
|
|
221
|
+
issue: "CRUD 编辑表单 vs 高级表单弹窗,边界不清",
|
|
222
|
+
suggestion: "form-advanced 明确「弹窗内表单/复杂交互表单」;crud-pages 的编辑表单为「行内/弹窗 CRUD 编辑」",
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
modules: ["workflow-bpmn", "flowchart-g6"],
|
|
226
|
+
issue: "用户说「流程图」时同时命中两个模块",
|
|
227
|
+
suggestion: "workflow-bpmn → 「BPMN 流程审批/审批流程」;flowchart-g6 → 「自定义流程图/G6 拓扑图」",
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
modules: ["feedback-loading", "feedback-ui"],
|
|
231
|
+
issue: "都是「反馈」类,AI 可能混淆",
|
|
232
|
+
suggestion: "feedback-loading → 「操作反馈(loading/message/确认框)」;feedback-ui → 「展示类UI(通知栏/水印/时间轴)」",
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
modules: ["chart-echarts", "data-screen"],
|
|
236
|
+
issue: "大屏包含图表,用户说「图表」时可能实际要大屏",
|
|
237
|
+
suggestion: "data-screen 明确「全屏数据可视化/大屏看板」;chart-echarts → 「页面内图表/统计图」",
|
|
238
|
+
},
|
|
239
|
+
];
|
|
240
|
+
return conflicts;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// ── 主审计逻辑 ───────────────────────────────────────────
|
|
244
|
+
function audit() {
|
|
245
|
+
const modules = extractRoutingKeywords();
|
|
246
|
+
const effectRules = extractEffectRules();
|
|
247
|
+
const { overlaps, fuzzyOverlaps, keywordMap } = detectOverlaps(modules);
|
|
248
|
+
const gaps = detectGaps(modules, keywordMap);
|
|
249
|
+
const scores = scoreModules(modules, keywordMap);
|
|
250
|
+
const boundaryConflicts = detectBoundaryConflicts(modules);
|
|
251
|
+
|
|
252
|
+
return { modules, effectRules, overlaps, fuzzyOverlaps, gaps, scores, boundaryConflicts };
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// ── 文本输出 ─────────────────────────────────────────────
|
|
256
|
+
function printText(result) {
|
|
257
|
+
const { modules, effectRules, overlaps, fuzzyOverlaps, gaps, scores, boundaryConflicts } = result;
|
|
258
|
+
|
|
259
|
+
console.log(c.bold(`\n${c.cyan("AI 命中精度审计")}\n`));
|
|
260
|
+
|
|
261
|
+
// 1. 关键词重叠
|
|
262
|
+
console.log(c.bold(`1. 关键词重叠(AI 歧义源)\n`));
|
|
263
|
+
if (overlaps.length === 0) {
|
|
264
|
+
console.log(c.green(" ✓ 无精确重叠"));
|
|
265
|
+
} else {
|
|
266
|
+
for (const o of overlaps) {
|
|
267
|
+
console.log(` ${c.yellow("!")} "${o.keyword}" → ${o.modules.join("、")}`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (fuzzyOverlaps.length > 0) {
|
|
271
|
+
console.log(c.dim("\n 模糊重叠(包含关系):"));
|
|
272
|
+
for (const f of fuzzyOverlaps) {
|
|
273
|
+
console.log(` ${c.yellow("!")} "${f.keywordA}"(${f.modulesA.join(",")}) ⊃/⊂ "${f.keywordB}"(${f.modulesB.join(",")})`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// 2. 命中盲区
|
|
278
|
+
console.log(c.bold(`\n2. 命中盲区(常见表述无匹配)\n`));
|
|
279
|
+
if (gaps.length === 0) {
|
|
280
|
+
console.log(c.green(" ✓ 无盲区"));
|
|
281
|
+
} else {
|
|
282
|
+
console.log(` ${c.red(gaps.length)} 个常见表述无法命中任何模块:\n`);
|
|
283
|
+
for (const g of gaps) {
|
|
284
|
+
console.log(` ${c.red("✗")} ${g}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// 3. 模块可命中性评分
|
|
289
|
+
console.log(c.bold(`\n3. 模块可命中性评分(从 AI 视角)\n`));
|
|
290
|
+
console.log(` ${c.dim("评分 = 独有词×10 + 长词×5 + 总词×2 - 重叠词×8")}\n`);
|
|
291
|
+
for (const s of scores) {
|
|
292
|
+
const bar = "█".repeat(Math.max(0, Math.min(20, s.score / 3))) +
|
|
293
|
+
c.dim("░".repeat(Math.max(0, 20 - Math.min(20, s.score / 3))));
|
|
294
|
+
const level = s.score >= 30 ? c.green("优") : s.score >= 15 ? c.yellow("中") : c.red("差");
|
|
295
|
+
console.log(` ${bar} ${c.bold(s.moduleId.padEnd(22))} ${String(s.score).padStart(3)} ${c.dim(`(独有${s.uniqueKeywords}/${s.keywordCount} 覆盖${s.coverageRate})`)} ${level}`);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// 4. 效果匹配规则
|
|
299
|
+
console.log(c.bold(`\n4. 效果匹配规则(${effectRules.length} 条)\n`));
|
|
300
|
+
for (const r of effectRules) {
|
|
301
|
+
console.log(` ${c.dim("→")} ${r.trigger} ${c.dim("→")} ${c.cyan(r.target)}`);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// 5. 模块边界冲突
|
|
305
|
+
console.log(c.bold(`\n5. 模块边界冲突(AI 难以区分的对)\n`));
|
|
306
|
+
for (const bc of boundaryConflicts) {
|
|
307
|
+
console.log(` ${c.red("!")} ${c.bold(bc.modules.join(" vs "))}`);
|
|
308
|
+
console.log(` ${c.yellow("问题:")} ${bc.issue}`);
|
|
309
|
+
console.log(` ${c.green("建议:")} ${bc.suggestion}`);
|
|
310
|
+
console.log("");
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// ── CLI 入口 ────────────────────────────────────────────────
|
|
315
|
+
const args = process.argv.slice(2);
|
|
316
|
+
const result = audit();
|
|
317
|
+
|
|
318
|
+
if (args.includes("--json")) {
|
|
319
|
+
console.log(JSON.stringify(result, null, 2));
|
|
320
|
+
} else if (args.includes("--overlap")) {
|
|
321
|
+
const { overlaps, fuzzyOverlaps } = result;
|
|
322
|
+
console.log(c.bold(`\n${c.cyan("关键词重叠检测")}\n`));
|
|
323
|
+
for (const o of overlaps) {
|
|
324
|
+
console.log(` ${c.yellow("!")} "${o.keyword}" → ${o.modules.join("、")}`);
|
|
325
|
+
}
|
|
326
|
+
console.log(c.dim("\n 模糊重叠:"));
|
|
327
|
+
for (const f of fuzzyOverlaps) {
|
|
328
|
+
console.log(` ${c.yellow("!")} "${f.keywordA}"(${f.modulesA.join(",")}) ⊂/⊃ "${f.keywordB}"(${f.modulesB.join(",")})`);
|
|
329
|
+
}
|
|
330
|
+
console.log("");
|
|
331
|
+
} else if (args.includes("--gaps")) {
|
|
332
|
+
console.log(c.bold(`\n${c.cyan("命中盲区检测")}\n`));
|
|
333
|
+
for (const g of result.gaps) {
|
|
334
|
+
console.log(` ${c.red("✗")} ${g}`);
|
|
335
|
+
}
|
|
336
|
+
console.log(`\n ${c.red(result.gaps.length)} 个常见表述无匹配\n`);
|
|
337
|
+
} else if (args.includes("--score")) {
|
|
338
|
+
console.log(c.bold(`\n${c.cyan("模块可命中性评分")}\n`));
|
|
339
|
+
for (const s of result.scores) {
|
|
340
|
+
const bar = "█".repeat(Math.max(0, Math.min(20, s.score / 3))) +
|
|
341
|
+
c.dim("░".repeat(Math.max(0, 20 - Math.min(20, s.score / 3))));
|
|
342
|
+
const level = s.score >= 30 ? c.green("优") : s.score >= 15 ? c.yellow("中") : c.red("差");
|
|
343
|
+
console.log(` ${bar} ${c.bold(s.moduleId.padEnd(22))} ${String(s.score).padStart(3)} ${c.dim(`(独有${s.uniqueKeywords}/${s.keywordCount})`)} ${level}`);
|
|
344
|
+
}
|
|
345
|
+
console.log("");
|
|
346
|
+
} else {
|
|
347
|
+
printText(result);
|
|
348
|
+
}
|