diff --git a/.prettierignore b/.prettierignore index ad0c04318..fa1323d73 100644 --- a/.prettierignore +++ b/.prettierignore @@ -23,4 +23,7 @@ shrinkwrap.json # Build outputs dist -lib \ No newline at end of file +lib + +# Skill templates (contain placeholder syntax that formatters break) +skills/vtable-development-assistant/template/ \ No newline at end of file diff --git a/skills/vtable-development-assistant/SKILL.md b/skills/vtable-development-assistant/SKILL.md index f40f836cb..82dfa18a5 100644 --- a/skills/vtable-development-assistant/SKILL.md +++ b/skills/vtable-development-assistant/SKILL.md @@ -37,7 +37,7 @@ references/ | 属性、property | `references/knowledge/06-api-properties.md` | | 事件、on、监听、click、scroll | `references/knowledge/07-events.md` → `references/type/event-types.md` | | 维度、dimension、指标、indicator | `references/knowledge/08-pivot-dimensions.md` → `references/type/pivot-types.md` | -| 数据、records、dataSource | `references/knowledge/09-data-binding.md` | +| 数据、records、dataSource | `references/knowledge/09-data-bindingd.md` | | 交互、选择、hover、编辑、拖拽、排序 | `references/knowledge/10-interaction.md` | | 最佳实践、模式、怎么做 | `references/knowledge/11-common-patterns.md` → `references/examples/` | @@ -51,3 +51,36 @@ references/ 6. **销毁表格必须调用 `tableInstance.release()`** 7. 透视表数据分析需要配置 `dataConfig` 中的 `aggregationRules` 8. 自定义布局优先推荐 JSX 方案(`customLayout`),低级需求用 `customRender` + +## 脚本生成强制规则 + +- 所有输出必须通过脚本生成 HTML,不允许手写 HTML 或仅输出片段 +- 诊断场景使用 `scripts/generate_diagnosis_html.py` +- 生成/编辑场景使用 `scripts/generate_demo_html.py` +- 输出必须包含脚本命令与生成文件路径,确保可复现 +- 未输出脚本命令与文件路径时,必须补齐后再回答 +- 输入代码不得包含 `import` / `export`,需先移除再写入 spec.js 或 config.js +- 禁止创建或覆盖 `scripts/` 下脚本文件,必须直接调用已有脚本 + +**绝对路径调用示例**: + +```bash +python3 scripts/generate_demo_html.py --spec-file spec.js --output output/demo.html +``` + +**环境无关调用说明**: + +- 在任意目录运行脚本时,脚本会基于自身位置定位模板 +- 不需要使用绝对路径 + +**示例(诊断)**: + +```bash +python3 scripts/generate_diagnosis_html.py --config-file config.js --output output/diagnosis.html +``` + +**示例(生成/编辑)**: + +```bash +python3 scripts/generate_demo_html.py --spec-file spec.js --output output/demo.html +``` diff --git a/skills/vtable-development-assistant/scripts/generate_demo_html.py b/skills/vtable-development-assistant/scripts/generate_demo_html.py new file mode 100644 index 000000000..773f57082 --- /dev/null +++ b/skills/vtable-development-assistant/scripts/generate_demo_html.py @@ -0,0 +1,61 @@ +from pathlib import Path +import argparse + + +def escape_js_string(value: str) -> str: + return ( + value.replace("\\", "\\\\") + .replace("`", "\\`") + .replace("${", "\\${") + .replace("\n", "\\n") + .replace("\r", "\\r") + .replace("\t", "\\t") + ) + + +def main(): + parser = argparse.ArgumentParser(description="Generate VTable demo HTML") + parser.add_argument("--title", default="VTable 表格示例") + parser.add_argument("--desc", default="基于需求生成的可运行表格配置") + parser.add_argument("--feature", default="补充主要功能说明") + parser.add_argument("--tips", default="补充编辑提示") + parser.add_argument("--spec-file") + parser.add_argument("--output", default="output/demo.html") + args = parser.parse_args() + + template_path = Path(__file__).resolve().parent.parent / "template" / "demo.html" + if not template_path.exists(): + raise FileNotFoundError(f"模板不存在: {template_path}") + + if args.spec_file: + spec_path = Path(args.spec_file) + if not spec_path.exists(): + raise FileNotFoundError(f"配置文件不存在: {spec_path}") + spec_code = spec_path.read_text(encoding="utf-8") + else: + spec_code = """const tableInstance = new VTable.ListTable({ + container: document.getElementById('container'), + records: [{ name: "张三", age: 25 }], + columns: [ + { field: "name", title: "姓名", width: 100 }, + { field: "age", title: "年龄", width: 80 } + ], + width: 600, + height: 400 +});""" + + html = template_path.read_text(encoding="utf-8") + html = html.replace("{{REPORT_TITLE}}", args.title) + html = html.replace("{{REPORT_DESC}}", args.desc) + html = html.replace("{{FEATURE_DESC}}", args.feature) + html = html.replace("{{EDIT_TIPS}}", args.tips) + html = html.replace("{{INITIAL_CODE}}", escape_js_string(spec_code.strip())) + + output_path = Path(args.output) + output_path.parent.mkdir(parents=True, exist_ok=True) + output_path.write_text(html, encoding="utf-8") + print(f"生成完成: {output_path.resolve()}") + + +if __name__ == "__main__": + main() diff --git a/skills/vtable-development-assistant/scripts/generate_diagnosis_html.py b/skills/vtable-development-assistant/scripts/generate_diagnosis_html.py new file mode 100644 index 000000000..a1ad895d8 --- /dev/null +++ b/skills/vtable-development-assistant/scripts/generate_diagnosis_html.py @@ -0,0 +1,74 @@ +from pathlib import Path +import argparse + + +def main(): + parser = argparse.ArgumentParser(description="Generate VTable diagnosis HTML") + parser.add_argument("--title", default="VTable 问题诊断报告") + parser.add_argument("--desc", default="基于用户配置的诊断与修复结果") + parser.add_argument("--config-file") + parser.add_argument("--output", default="output/diagnosis.html") + args = parser.parse_args() + + template_path = Path(__file__).resolve().parent.parent / "template" / "diagnosis.html" + if not template_path.exists(): + raise FileNotFoundError(f"模板不存在: {template_path}") + + if args.config_file: + config_path = Path(args.config_file) + if not config_path.exists(): + raise FileNotFoundError(f"配置文件不存在: {config_path}") + config_block = config_path.read_text(encoding="utf-8") + else: + config_block = """const problemReview = { + specCode: `const tableInstance = new VTable.ListTable({ + container: document.getElementById('container'), + records: [{ name: "张三", age: 25 }], + columns: [ + { field: "name", title: "姓名", width: 100 }, + { field: "age", title: "年龄", width: 80 } + ], + width: 600, + height: 400 +});` +}; + +const diagnosis = { + problem: "示例问题描述", + cause: "示例原因分析", + suggestion: "示例修复建议" +}; + +const solutions = [ + { + title: "示例修复方案", + description: "修复方案描述", + specCode: `const tableInstance = new VTable.ListTable({ + container: document.getElementById('container'), + records: [{ name: "张三", age: 25 }], + columns: [ + { field: "name", title: "姓名", width: 120 }, + { field: "age", title: "年龄", width: 80 } + ], + width: 600, + height: 400 +});` + } +];""" + + html = template_path.read_text(encoding="utf-8") + if "{{CONFIG_BLOCK}}" not in html: + raise ValueError("模板缺少 CONFIG_BLOCK 占位符") + + html = html.replace("{{REPORT_TITLE}}", args.title) + html = html.replace("{{REPORT_DESC}}", args.desc) + html = html.replace("{{CONFIG_BLOCK}}", config_block) + + output_path = Path(args.output) + output_path.parent.mkdir(parents=True, exist_ok=True) + output_path.write_text(html, encoding="utf-8") + print(f"生成完成: {output_path.resolve()}") + + +if __name__ == "__main__": + main() diff --git a/skills/vtable-development-assistant/template/demo.html b/skills/vtable-development-assistant/template/demo.html new file mode 100644 index 000000000..e566a6c17 --- /dev/null +++ b/skills/vtable-development-assistant/template/demo.html @@ -0,0 +1,286 @@ + + + + + + VTable Demo + + + + + + + + + +
+
+

📊 {{REPORT_TITLE}}

+

{{REPORT_DESC}}

+
+
+
+

主要功能说明

+

{{FEATURE_DESC}}

+
+
+

编辑提示

+

{{EDIT_TIPS}}

+
+
+
+
+
VTable 配置
+
+
+
+
效果预览
+
+
+
+
+ + + diff --git a/skills/vtable-development-assistant/template/diagnosis.html b/skills/vtable-development-assistant/template/diagnosis.html new file mode 100644 index 000000000..1cf6ae68b --- /dev/null +++ b/skills/vtable-development-assistant/template/diagnosis.html @@ -0,0 +1,370 @@ + + + + + + VTable 诊断方案 + + + + + + + +
+
+

📊 {{REPORT_TITLE}}

+

{{REPORT_DESC}}

+
+
+
+ + + diff --git a/skills/vtable-development-assistant/workflows/scenario-1-diagnosis.md b/skills/vtable-development-assistant/workflows/scenario-1-diagnosis.md new file mode 100644 index 000000000..05e2a6f55 --- /dev/null +++ b/skills/vtable-development-assistant/workflows/scenario-1-diagnosis.md @@ -0,0 +1,53 @@ +# 场景一处理流程:VTable问题诊断 + +## 适用情况 + +- 用户提供现有代码并描述不工作、报错、显示异常 +- 用户询问如何优化或修复现有表格 + +## 需要收集的信息 + +- 完整的表格初始化代码 +- 数据样本(至少 3-5 条) +- 具体报错或异常表现 +- 期望效果 + +## 诊断流程 + +1. 确认表格类型(ListTable / PivotTable / PivotChart) +2. 检查必填字段(container、records/rows/columns/indicators) +3. 核对字段映射与数据结构一致性 +4. 逐项核对交互、样式、事件配置是否生效 +5. 给出可运行修复方案 + +## 输出要求 + +- 必须输出可运行 HTML +- 必须通过脚本生成 HTML,不允许手写 HTML 或只给片段 +- 包含问题回顾、诊断结论、修复方案 + - 若未输出脚本命令与文件路径,视为未完成 + +## 生成方式 + +使用脚本生成诊断 HTML: + +```bash +python3 scripts/generate_diagnosis_html.py --config-file config.js +``` + +输出必须包含脚本命令与生成文件路径,确保可复现。 + +## 输入代码规范 + +- config.js 中的 specCode 保留可执行配置代码 +- 移除 `import` / `export` 语句 + +配置文件结构: + +```javascript +const problemReview = { specCode: `...`, highlightLines: [1, 2] }; +const diagnosis = { problem: "...", cause: "...", suggestion: "..." }; +const solutions = [ + { title: "...", description: "...", specCode: `...`, highlightLines: [3] } +]; +``` diff --git a/skills/vtable-development-assistant/workflows/scenario-2-generation.md b/skills/vtable-development-assistant/workflows/scenario-2-generation.md new file mode 100644 index 000000000..4ad81c403 --- /dev/null +++ b/skills/vtable-development-assistant/workflows/scenario-2-generation.md @@ -0,0 +1,89 @@ +# 场景二处理流程:VTable配置生成 + +## 适用情况 + +- 用户从零创建表格 +- 用户在已有配置上新增功能或修改效果 + +## 生成模式 + +- 完整生成:无现有配置,输出完整可运行 HTML +- 增量生成:有现有配置,合并变更后输出完整可运行 HTML + +## 生成流程 + +1. 识别表格类型与核心需求 +2. 构建数据结构与列定义 +3. 加入交互、样式、事件配置 +4. 产出可运行 HTML + +## 输出要求 + +- 必须输出可运行 HTML +- 必须通过脚本生成 HTML,不允许手写 HTML 或只给片段 +- 示例包含可直接运行的完整初始化代码 + - 若未输出脚本命令与文件路径,视为未完成 + +## 生成方式 + +使用脚本生成演示 HTML: + +```bash +python3 scripts/generate_demo_html.py --spec-file spec.js +``` + +输出必须包含脚本命令与生成文件路径,确保可复现。 + +## 输入代码规范 + +- spec.js 仅保留可执行的表格配置代码 +- 移除 `import` / `export` 语句,避免在 HTML 中执行时报错 +- 支持复杂代码结构:可将数据、注册逻辑、配置分开定义,也可使用 try/catch 包裹 +- `container` 字段可写为 `document.getElementById('container')`,模板会自动替换为实际渲染容器 +- PivotChart + VChart 场景无需手动加载 VChart CDN,模板已内置 + +spec.js 简单示例: + +```javascript +const tableInstance = new VTable.ListTable({ + container: document.getElementById('container'), + records: [{ name: "张三", age: 25 }], + columns: [ + { field: "name", title: "姓名", width: 100 }, + { field: "age", title: "年龄", width: 80 } + ], + width: 600, + height: 400 +}); +``` + +spec.js 复杂示例(PivotChart + 外部数据): + +```javascript +const records = [ + { region: '华东', category: '办公用品', month: '1月', sales: 1200 }, + { region: '华东', category: '办公用品', month: '2月', sales: 1350 } +]; + +if (typeof VChart !== 'undefined' && VTable.register && typeof VTable.register.chartModule === 'function') { + VTable.register.chartModule('vchart', VChart); +} + +const options = { + container: document.getElementById('container'), + records, + rows: [{ dimensionKey: 'region', title: '地区', width: 120 }], + columns: [], + indicators: [{ + indicatorKey: 'sales', + title: '销售额趋势', + cellType: 'chart', + chartModule: 'vchart', + chartSpec: { type: 'line', xField: 'month', yField: 'sales' } + }], + width: 800, + height: 400 +}; + +const tableInstance = new VTable.PivotChart(options); +```