Report To Visualization

将文本报告转换为可视化组件流。当用户需要将报告数据可视化或提到"可视化报告"、"用图表展示"、"图文并茂"时使用。

Audits

Pass

Install

openclaw skills install report-to-visualization

报告转可视化组件流

任务目标

将文本报告数据转换为可视化组件配置,输出严格的MODULE格式。

输入格式

用户需提供以下变量:

  • ${moduleData}: 报告数据内容

图表库规范

1. 折线图 (Chart.Line)

使用条件: 展示数据趋势,需至少5个连续、真实的时间点原始观测值 数据格式:

{
  "type": "Chart.Line",
  "data": [{"name": "时间标签,≤6字", "value": 数值, "category": "系列名称,≤8字"}],
  "config": {"xField": "name", "yField": "value", "title": "图表标题,≤12字"},
  "layoutRow": "r1", "layoutCol": "c1", "rowSize": "auto", "colSize": "auto"
}

约束:

  • 禁止基于平均值、最高/最低值、总计等聚合统计量推测或填充时间序列数据
  • value 必须为 number 类型(如 78.5),禁止使用字符串(如 "78.5"

2. 柱状图 (Chart.Column)

使用条件: 展示数据对比,一个或多个维度有不低于2个具体数值 数据格式:

{
  "type": "Chart.Column",
  "data": [{"name": "分类标签,≤8字", "value": 数值, "category": "指标名称,≤8字"}],
  "config": {"xField": "name", "yField": "value", "seriesField": "category", "isGroup": true, "title": "图表标题,≤12字"},
  "layoutRow": "r1", "layoutCol": "c1", "rowSize": "auto", "colSize": "auto"
}

约束:

  • value 必须为 number 类型(如 78.5),禁止使用字符串(如 "78.5"),字符串会导致图表排序和轴刻度异常
  • 如果原文给出范围值(如"60%-85%"),应拆分为两个数据点(如"线下摆摊(低) 60"和"线下摆摊(高) 85"),或改用 KeyValueCard 展示
  • {"name": "线下摆摊", "value": "60-85"} → ✅ 拆分为 {"name": "摆摊(低)", "value": 60}{"name": "摆摊(高)", "value": 85}
  • 禁止混合量纲:同一个柱状图中所有数据点的 value 必须属于同一量纲(如全部是百分比,或全部是绝对数值)。禁止将绝对数值(如曝光量 9500、成交金额 7800)与百分比(如点击率 2.3%、转化率 0.8%)放在同一个图表中,否则百分比的柱子会因数量级差异完全不可见。应拆分为两个独立的 Chart.Column,或将百分比指标改用 DataCard 展示
  • ❌ 曝光量(9500) + 点击率(2.3) + 成交金额(7800) 放在同一柱状图 → ✅ 拆分为"流量与销售"柱状图(绝对数值)+ "转化效率"DataCard 或柱状图(百分比)

3. DataCard (数据卡片)

使用条件: 展示核心指标值和环比数据,不低于4个指标 数据格式:

{
  "type": "DataCard",
  "data": [{"desc": "指标名称,≤12字", "value": "指标值", "cycle": "环比变化值或null"}],
  "config": {"title": "卡片标题,≤10字"},
  "layoutRow": "r1", "layoutCol": "c2", "rowSize": "auto", "colSize": "auto"
}

约束:

  • cycle 字段仅用于填写环比/同比的数值变化(如 "-0.26%""+5.3%"),或填 null
  • 禁止在 cycle 中填入描述性文字(如"下降""行业第一""占比47.2%")
  • 如果某指标没有环比/同比数据,cycle 必须为 null
  • {"desc": "斯凯奇份额", "value": "16.8%", "cycle": "行业第一"} → ✅ {"desc": "斯凯奇份额", "value": "16.8%", "cycle": null}

4. 饼图 (Chart.Pie)

使用条件: 展示数据占比,不低于2个指标,value值求和应为100(百分比)或1(小数) 数据格式:

{
  "type": "Chart.Pie",
  "data": [{"type": "类别名称,≤8字", "value": 数值}],
  "config": {"angleField": "value", "colorField": "type", "innerRadius": 0.6, "statistic": {"title": false, "content": false}, "title": "图表标题,≤12字"},
  "layoutRow": "r1", "layoutCol": "c2", "rowSize": "auto", "colSize": "auto"
}

约束:

  • value 必须为 number 类型,禁止字符串
  • 禁止推算补全:如果原文只给出一个占比数据而缺少互补项(如仅提到"35-55岁占61.3%"),不得自行用 100%-61.3%=38.7% 推算出其他类别的占比。应改用 DataCard 或 KeyValueCard 展示已有数据
  • {"type": "其他年龄", "value": 38.7} ← 原文无此数据,系推算捏造

5. 表格 (Chart.List)

使用条件: 当内容满足以下全部条件时,必须使用 Chart.List 而非 TextCard/KeyValueCard:

  1. 3 个以上的对比对象(如 5 个品牌、4 款产品、6 个成本项)
  2. 每个对象需要展示 3-4 个维度(如品牌 + 定位 + 优势 + 数据)
  3. 需要横向对比阅读 数据格式:
{
  "type": "Chart.List",
  "data": [{"list": [{"key": "列名,≤10字", "value": "列值,≤20字"}, {"key": "列名", "value": "列值"}]}],
  "config": {"title": "分组标题,≤10字"},
  "layoutRow": "r1", "layoutCol": "c1", "rowSize": "auto", "colSize": "auto"
}

典型场景:

  • ✅ 竞争品牌格局(5 个品牌 × 4 个维度)→ Chart.List
  • ✅ 成本结构明细(6 个成本项 × 3 个维度)→ Chart.List
  • ❌ 品牌格局用 TextCard 描述 → 违规

约束(总计行表达):

  • 如果表格需要展示总计/合计行,总计行的 key-value 结构必须与明细行保持一致,第一列的 key 不变,value 填"总计/合计",后续列正常填写汇总数据
  • {"list": [{"key": "成本项", "value": "约111.1元/双"}, {"key": "成本", "value": "-"}, {"key": "备注", "value": "含原材料25-40元"}]} ← 把金额塞进第一列,第二列留空,读者无法理解
  • {"list": [{"key": "成本项", "value": "总计"}, {"key": "成本", "value": "约111.1元/双"}, {"key": "备注", "value": "含原材料25-40元"}]} ← 第一列标明"总计",后续列正常填写数据

6. 文本卡片 (TextCard)

使用条件: 展示数据总结、趋势洞察、运营建议等定性内容,不少于2个标题 数据格式:

{
  "type": "TextCard",
  "data": [{"title": "标题,≤10字", "text": "内容,尽量2行,30-45字"}],
  "config": {"title": "卡片标题,≤10字"},
  "layoutRow": "r1", "layoutCol": "c1", "rowSize": "auto", "colSize": "auto"
}

约束(元素数量):

  • data 数组必须包含 至少 2 个元素(即至少 2 个 {"title": "...", "text": "..."} 对象),仅 1 个元素时应从原文上下文中提取更多观点/结论来补充,若确实无法补充则考虑将内容合并到相邻的组件中
  • "data": [{"title": "可行性结论", "text": "..."}] ← 仅 1 个元素,卡片单薄,信息密度过低
  • "data": [{"title": "可行性结论", "text": "..."}, {"title": "核心优势", "text": "..."}] ← 至少 2 个元素,内容充实

约束(内容聚合原则):

  • 同一主题下的多个子观点必须放在同一个 TextCard 的 data 数组中,禁止拆分成多个 TextCard
  • 如果某个大主题下有 2-5 个紧密相关的子主题 → 使用一个 TextCard,data 数组包含多项
  • ❌ 将"国家政策的 4 个方面"拆成 4 个独立的 TextCard
  • ❌ 将"产品创新的 4 个趋势"拆成 2-3 个 TextCard

约束(内容丰富度):

  • TextCard 每项的 text 字段内容尽量保持 2 行左右(30-60 字),避免内容过于单薄
  • 如果原文信息不足以撑满 2 行,应从原文上下文中提取补充信息(如具体数据、应用场景、代表案例等)进行丰富
  • "text": "北欧极简、无性别设计" ← 仅 1 行,信息密度过低
  • "text": "北欧极简、无性别设计成为主流趋势,通勤休闲轻运动场景无缝切换,满足全年龄段穿搭需求" ← 约 2 行,信息丰富

7. 键值对卡片 (KeyValueCard)

使用条件: 展示不低于2个分组,每个分组不低于2个指标 数据格式:

{
  "type": "KeyValueCard",
  "data": [{"title": "分组标题,≤8字", "list": [{"key": "指标名称,≤10字", "value": "格式化后的指标值,≤15字"}]}],
  "config": {"title": "卡片主标题,≤10字"},
  "layoutRow": "r1", "layoutCol": "c2", "rowSize": "auto", "colSize": "auto"
}

约束:

  • data 数组必须包含 至少 2 个分组(即至少 2 个 {"title": "...", "list": [...]} 对象),仅 1 个分组时应改用 DataCard 或 TextCard
  • 每个分组的 list 数组应包含 至少 2 个指标
  • "data": [{"title": "唯一分组", "list": [...]}] ← 仅 1 个分组独占一整张卡片,信息密度过低

8. 阶段卡片 (PhaseCard)

使用条件: 展示分阶段的内容规划或执行步骤 数据格式:

{
  "type": "PhaseCard",
  "data": [{"phaseNumber": "阶段序号,≤5字", "phaseName": "阶段名称,≤6字", "focusPoints": [{"label": "重点项标签,≤6字", "content": "重点项内容,≤50字"}]}],
  "config": {"title": "卡片标题,≤10字", "theme": "主题色,如'blue'"},
  "layoutRow": "r1", "layoutCol": "c1", "rowSize": "auto", "colSize": "auto"
}

约束:

  • 阶段数控制在 3-5 个,避免过度拆分导致信息碎片化
  • 每个阶段应包含 2-3 个 focusPoints,体现该阶段的多维度工作内容
  • 可将相关性强的建议合并为同一阶段(如"产品定位+技术创新"合并为"产品升级"阶段)
  • ❌ 将 6 条建议拆成 6 个阶段,每阶段仅 1 个 focusPoint → ✅ 合并为 3-4 个阶段,每阶段 2-3 个 focusPoints

9. 时间轴 (TimelineCard)

使用条件: 展示时间轴内容,如里程碑规划,不低于3个时间节点 数据格式:

{
  "type": "TimelineCard",
  "data": [{"month": "月份,≤6字", "title": "里程碑标题,≤8字", "description": "详细描述,≤40字", "target": "目标值,≤12字", "status": "completed或in-progress"}],
  "config": {"title": "标题,≤10字", "orientation": "horizontal或vertical"},
  "layoutRow": "r1", "layoutCol": "c1", "rowSize": "auto", "colSize": "auto"
}

约束:

  • data 数组必须包含 至少 3 个时间节点,少于 3 个节点无法体现时间线的连续感和阶段递进关系
  • 仅 1-2 个时间节点时,应从原文上下文中提取更多里程碑/阶段来补充,若确实无法补充则改用 PhaseCard 或 TextCard 承载
  • "data": [{"month": "1月", ...}] ← 仅 1 个节点,无法构成时间轴
  • "data": [{"month": "1月", ...}, {"month": "6月", ...}] ← 仅 2 个节点,时间线过于稀疏
  • "data": [{"month": "1月", ...}, {"month": "3月", ...}, {"month": "6月", ...}] ← 至少 3 个节点,时间线完整

10. 警告卡片 (AlertCard)

使用条件: 展示警告内容,如风险提示、注意事项,不低于2条警告 数据格式:

{
  "type": "AlertCard",
  "data": [{"issue": "问题描述,≤25字", "consequence": "后果,≤40字", "suggestion": "建议,≤30字", "level": "warning或info或error或success"}],
  "config": {"title": "卡片标题,≤10字", "showIcon": true},
  "layoutRow": "r1", "layoutCol": "c1", "rowSize": "auto", "colSize": "auto"
}

约束:

  • data 数组必须包含 至少 2 条警告,仅 1 条警告时应从原文上下文中提取更多风险/注意事项来补充,若确实无法补充则改用 TextCard 承载
  • "data": [{"issue": "唯一的风险提示", ...}] ← 仅 1 条警告,信息密度过低,卡片单薄
  • "data": [{"issue": "风险1", ...}, {"issue": "风险2", ...}] ← 至少 2 条,信息充实

11. 影响卡片 (InfluenceCard)

使用条件: 展示不同程度的影响内容,如关键转化杠杆、机会优先级 数据格式:

{
  "type": "InfluenceCard",
  "data": [{"name": "因素名称,≤10字", "influenceLevel": 1-5, "influenceLabel": "影响力标签,≤4字", "focusPoints": [{"label": "关注点标签,≤6字", "content": "关注点内容,≤50字"}], "warnings": [{"icon": "warning或info", "label": "警告标签,≤6字", "content": "警告内容,≤40字"}], "priority": 1-3}],
  "config": {"title": "主标题,≤12字"},
  "layoutRow": "r1", "layoutCol": "c1", "rowSize": "auto", "colSize": "auto"
}

约束:

  • 每个影响因素应包含 2-3 个 focusPoints,从不同维度(如技术/商业/用户/风险)展示影响
  • 如果原文对某个因素只有一句话描述,应从原文上下文中提取补充信息,而非仅用 1 个 focusPoint
  • ❌ 每个因素仅 1 个 focusPoint,信息密度过低 → ✅ 每个因素 2-3 个 focusPoints

输出格式

按报告章节分模块输出,所有模块统一组织在一个 JSON 对象的 modules 数组中,并使用 ```seller-report 代码块包裹。最终输出必须严格遵循以下结构,不允许在代码块外输出任何额外内容

{
  "modules": [
    {
      "components": [
        {
          "type": "Title",
          "content": "<章节子标题,≤8字,禁止以\"模块一\"、\"##\"等字符开头,应体现该章节的核心主题>"
        },
        {
          "type": "<图表组件类型,如 Chart.Column / DataCard / KeyValueCard 等>",
          "data": [ ... ],
          "config": { ... },
          "layoutRow": "r1",
          "layoutCol": "c1",
          "rowSize": "auto",
          "colSize": "auto"
        },
        {
          "type": "<图表组件类型>",
          "data": [ ... ],
          "config": { ... },
          "layoutRow": "r1",
          "layoutCol": "c2",
          "rowSize": "auto",
          "colSize": "auto"
        }
      ]
    },
    {
      "components": [
        {
          "type": "Title",
          "content": "<下一章节子标题>"
        },
        {
          "type": "<图表组件类型>",
          "data": [ ... ],
          "config": { ... },
          "layoutRow": "r1",
          "layoutCol": "c1",
          "rowSize": "auto",
          "colSize": "auto"
        }
      ]
    }
  ]
}

分模块规则

  1. 每个原文一级标题(## 级别)对应 modules 数组中一个独立的模块对象(即一个 {"components": [...]}
  2. 每个模块的第一个组件必须{"type": "Title", "content": "<章节子标题>"},用于标识该模块的核心主题(如"消费者需求""竞争格局""政策环境"),而非整个报告的标题;Title 组件不参与布局编号,无需 layoutRow/layoutCol/data/config 字段
  3. 每个模块的 components 数组中,除首个 Title 外的其他组件仅承载该章节相关的内容
  4. layoutRow 在每个模块内独立编号,从 r1 重新开始(Title 组件不占用行号)
  5. 整个输出必须是单个合法 JSON 对象,被 ```seller-report ... ``` 包裹;JSON 中不允许出现注释、尾随逗号等非标准语法

布局规范(强约束)

核心规则: 布局只能是一行一个组件或一行两个不同组件,不允许一行放两个相同组件。

组件分类

基础图表类(可两两组合): Chart.Line、Chart.Column、Chart.Pie、DataCard、KeyValueCard

整行展示类(必须独占一行): Chart.List、TextCard、PhaseCard、TimelineCard、AlertCard、InfluenceCard

布局分配原则

  1. 整行展示类组件必须独占一行
  2. 基础图表类组件优先考虑两两组合(如 Column+Pie、Column+KeyValueCard、DataCard+KeyValueCard)
  3. layoutRow 从 r1 开始递增,rowSize/colSize 统一用 "auto"
  4. 禁止浪费:如果某个模块内存在两个或以上的基础图表类组件各自独占一行,视为布局浪费,必须合并到同一行
  5. 布局自检(生成每个模块后必须检查):该模块内是否有基础图表类组件可以组合?layoutRow 是否从 r1 连续递增?
  6. 禁止连续使用同一图表类型:在同一个模块内(不计 Title 组件),相邻的两个组件不得使用相同的 type。如果内容需要多个同类型组件,必须在中间插入一个不同类型的组件来间隔,或将内容合并到同一个组件中
    • ❌ 同一模块内第 1 个组件是 TextCard,第 2 个组件也是 TextCard → 违规,应合并为一个 TextCard 或在中间插入其他类型组件
    • ❌ 同一模块内连续两个 Chart.List → 违规,应合并为一个 Chart.List 或用其他组件间隔
    • ✅ TextCard → KeyValueCard → TextCard(中间有不同类型间隔)

完整性规则(强约束)

报告的每一个章节都必须在可视化输出中有对应的组件体现,禁止跳过任何章节。

  1. 定性内容必须可视化:产品定位、使用场景、竞争分析等非数字内容,应使用 TextCard、KeyValueCard 等组件承载,不得因"没有数字"而跳过
  2. 章节覆盖与组件数量:总组件数不得少于原文一级标题(## 级别)数量的 1.5 倍(如 8 个一级标题至少 12 个组件)。每个一级标题至少有一个组件与之对应

组件选型优先级(强约束)

当内容符合以下条件时,必须使用对应组件,禁止用 TextCard/KeyValueCard 替代:

内容特征必须使用的组件判断标准
有风险提示、问题警示AlertCard内容包含"问题 - 后果 - 建议"结构
有执行步骤、阶段规划PhaseCard内容包含"第一步/第二步"或"阶段 1/阶段 2"
有影响力分级、优先级排序InfluenceCard内容包含"高/中/低影响"或"优先级 1/2/3"
有 3+ 对象的多维度对比Chart.List内容有 3 个以上对象需要对比多个维度
有时间节点、里程碑TimelineCard内容包含具体时间点或时间序列

工作流程

  1. 阅读反例约束(强制前置步骤): 使用 read_file 工具阅读 reference/anti-patterns.md 文件,理解跨组件的通用反例约束。此步骤不可跳过。
  2. 内部规划(不输出给用户): 在内部完成以下规划步骤,不要将规划过程输出给用户
    • 仔细阅读 ${moduleData},逐一列出所有一级标题和二级标题,形成章节清单
    • 识别报告核心主体,规划第一个模块的 KeyValueCard 内容
    • 为每个章节选择最合适的组件类型,确保不违反"禁止连续使用同一图表类型"约束
    • 逐一对照章节清单,确认覆盖率和组件数量满足要求
    • 按布局分配原则执行布局规划
  3. 生成输出: 最终只输出被 ```seller-report ... ``` 包裹的单个 JSON 对象,不输出任何分析过程、章节清单、规划说明等中间内容。用户看到的应该只有这一个 ```seller-report 代码块。

重要约束

  • 内容严格来自报告数据,禁止捏造数据
  • 对于表现不佳的数据,避免"立即暂停""彻底下架""完全停止"等极端措辞,采用"诊断—优化—再决策"的渐进式策略
  • 如果报告数据未提供有效信息,直接返回"暂无内容"
  • 禁止裸数字(全局约束,适用于所有组件):任何展示给用户的数值都必须附带含义标注,让用户无需上下文即可理解该数值代表什么。具体要求:
    • 数值必须包含单位或含义前缀/后缀(如"销量倍数 ×2.1"而非"×2.1","毛利率 35%"而非"35%")
    • 如果字段本身的 key/label 已经明确了含义(如 "desc": "毛利率", "value": "35%"),则 value 中无需重复标注
    • 但如果数值出现在缺乏语义上下文的字段中(如 TimelineCard 的 target、DataCard 的 value),必须在数值中内嵌含义
    • "target": "×2.1" ← 无法理解 2.1 是什么的倍数
    • "target": "搜索量×2.1""target": "销量增长2.1倍"
    • "value": "9500" ← 不知道 9500 是什么
    • "value": "9500次曝光" 或配合 "desc": "曝光量" 使用