Back to skills
extension
Category: Data & AnalyticsNo API key required

数据报告撰写

outputreport

personAuthor: user_2f63f22ahubcommunity

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"""
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{self.title}</title> <!-- Tailwind CSS 样式 --> <script src="https://cdn.tailwindcss.com"></script> <!-- Chart.js 图表库 --> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> </head> <body class="{style['font']} bg-gray-50 min-h-screen"> <!-- 报告头部 --> <header class="{style['primary_color']} py-8 px-6 mb-8"> <div class="max-w-6xl mx-auto"> <h1 class="{style['title_size']}">{self.title}</h1> <p class="mt-2 opacity-90">分析目标:{self.target} | 作者:{self.author} | 生成时间:{self.date}</p> </div> </header>
<!-- 报告主体 -->
<main class="max-w-6xl mx-auto px-4 pb-12">
    <!-- 数据可视化模块 -->
    <section class="{style['card_bg']} mb-8">
        <h2 class="text-xl font-bold mb-4 text-gray-800">📊 数据可视化图表</h2>
        <div class="h-96">
            <canvas id="{self.chart_id}"></canvas>
        </div>
    </section>

    <!-- 数据分析模块 -->
    <section class="{style['card_bg']} mb-8">
        <h2 class="text-xl font-bold mb-4 text-gray-800">📝 深度数据分析</h2>
        <div class="space-y-4 text-gray-700 leading-relaxed">
            {"".join([f'<p>{p}</p>' for p in analysis_paragraphs])}
        </div>
    </section>

    <!-- 原始数据模块 -->
    <section class="{style['card_bg']}">
        <h2 class="text-xl font-bold mb-4 text-gray-800">📋 原始数据明细</h2>
        <div class="overflow-x-auto">
            <table class="w-full border-collapse">
                <thead>
                    <tr class="bg-gray-100">
                        <th class="border p-3 text-left">指标</th>
                        <th class="border p-3 text-left">数值</th>
                    </tr>
                </thead>
                <tbody>
                    {"".join([f'<tr><td class="border p-3">{k}</td><td class="border p-3">{v}</td></tr>' for k, v in self.data.items()])}
                </tbody>
            </table>
        </div>
    </section>
</main>

<!-- 图表渲染脚本 -->
<script>
    document.addEventListener('DOMContentLoaded', function() {{
        {chart_script}
    }});
</script>
</body> </html> """
    # 保存HTML文件
    with open(save_path, "w", encoding="utf-8") as f:
        f.write(html_template)
    
    print(f"✅ 报告生成成功!保存路径:{save_path}")
    return save_path