import json
import datetime
from typing import Dict, List, Optional
class DataReportSkill:
"""
数据报告撰写Skill:自动生成图文并茂的HTML数据报告
支持:自定义数据、分析目标、报告风格,自动生成图表+分析文案
"""
# 报告风格配置(内嵌CSS类,基于Tailwind CSS)
STYLE_TEMPLATES = {
"商务正式": {
"primary_color": "bg-blue-900 text-white",
"card_bg": "bg-white shadow-lg rounded-lg p-6",
"font": "font-sans",
"title_size": "text-3xl font-bold"
},
"简洁清爽": {
"primary_color": "bg-teal-600 text-white",
"card_bg": "bg-gray-50 border border-gray-200 rounded-lg p-5",
"font": "font-sans",
"title_size": "text-2xl font-semibold"
},
"可视化聚焦": {
"primary_color": "bg-purple-700 text-white",
"card_bg": "bg-white shadow-md rounded-xl p-6",
"font": "font-mono",
"title_size": "text-3xl font-bold text-purple-800"
}
}
def __init__(
self,
report_title: str,
analyze_data: Dict,
analyze_target: str,
report_style: str = "商务正式",
author: str = "数据分析师"
):
"""
初始化报告Skill
:param report_title: 报告标题
:param analyze_data: 分析数据(字典格式,支持一维/二维数据)
:param analyze_target: 分析目标(如:季度销售复盘、用户增长分析、业务效率评估)
:param report_style: 报告风格(商务正式/简洁清爽/可视化聚焦)
:param author: 报告作者
"""
self.title = report_title
self.data = analyze_data
self.target = analyze_target
self.style = self.STYLE_TEMPLATES.get(report_style, self.STYLE_TEMPLATES["商务正式"])
self.author = author
self.date = datetime.datetime.now().strftime("%Y年%m月%d日")
self.chart_id = f"chart_{int(datetime.datetime.now().timestamp())}"
def _auto_select_chart_type(self) -> str:
"""自动根据数据结构选择图表类型:饼图(占比)/折线图(趋势)/柱状图(对比)"""
data_values = list(self.data.values())
# 饼图:数据总和为100%(占比类数据)
if all(0 <= v <= 100 for v in data_values) and abs(sum(data_values) - 100) <= 1:
return "pie"
# 折线图:时间序列/趋势数据(键为日期/月份)
if any(key in ["1月","2月","Q1","周一","2024"] for key in self.data.keys()):
return "line"
# 默认柱状图:分类对比数据
return "bar"
def _generate_analysis_text(self) -> List[str]:
"""自动生成数据分析文案:核心结论、数据洞察、优化建议"""
if not self.data:
return ["无有效数据可分析"]
max_key = max(self.data, key=self.data.get)
min_key = min(self.data, key=self.data.get)
max_val = self.data[max_key]
min_val = self.data[min_key]
total = sum(self.data.values())
# 核心结论
conclusion = f"【核心结论】本次{self.target}中,{max_key}表现最优,数值为{max_val};{min_key}表现最弱,数值为{min_val}。"
# 数据洞察
insight = f"【数据洞察】整体数据总量为{total},数据分布呈现{max_key}主导的特征,符合{self.target}的业务预期。"
# 优化建议
suggestion = f"【优化建议】针对{min_key}的短板,建议结合业务场景制定提升策略,缩小与头部指标{max_key}的差距。"
return [conclusion, insight, suggestion]
def _generate_chart_config(self) -> str:
"""生成Chart.js图表配置(内嵌HTML)"""
chart_type = self._auto_select_chart_type()
labels = json.dumps(list(self.data.keys()))
values = json.dumps(list(self.data.values()))
return f"""
const ctx = document.getElementById('{self.chart_id}').getContext('2d');
new Chart(ctx, {{
type: '{chart_type}',
data: {{
labels: {labels},
datasets: [{{
label: '{self.target}',
data: {values},
backgroundColor: [
'rgba(54, 162, 235, 0.6)',
'rgba(255, 99, 132, 0.6)',
'rgba(255, 206, 86, 0.6)',
'rgba(75, 192, 192, 0.6)',
'rgba(153, 102, 255, 0.6)'
],
borderWidth: 1
}}]
}},
options: {{
responsive: true,
maintainAspectRatio: false,
plugins: {{
legend: {{ position: 'top' }},
title: {{ display: true, text: '{self.target}数据可视化' }}
}}
}}
}});
"""
def generate_html_report(self, save_path: str = "data_report.html") -> str:
"""
生成最终HTML报告并保存
:param save_path: HTML文件保存路径
:return: 保存路径
"""
# 自动生成分析文案
analysis_paragraphs = self._generate_analysis_text()
# 图表配置
chart_script = self._generate_chart_config()
# 风格样式
style = self.style
# HTML完整模板(内嵌CDN,无外部依赖)
html_template = f"""
分析目标:{self.target} | 作者:{self.author} | 生成时间:{self.date}
{"".join([f'
{p}
' for p in analysis_paragraphs])}
| 指标 | 数值 |
|---|---|
| {k} | {v} |
document.addEventListener('DOMContentLoaded', function() {{
{chart_script}
}});
"""
# 保存HTML文件
with open(save_path, "w", encoding="utf-8") as f:
f.write(html_template)
print(f"✅ 报告生成成功!保存路径:{save_path}")
return save_path
共 1 个版本