Report Generation
by apconw
通用的报告生成技能,根据用户诉求生成各类数据分析报告,包括数据库查询、统计分析和 HTML 图表可视化
Skill Details
Repository Files
1 file in this skill directory
name: report-generation description: 通用的报告生成技能,根据用户诉求生成各类数据分析报告,包括数据库查询、统计分析和 HTML 图表可视化
通用报告生成技能
何时使用此技能
当用户需要生成任何类型的报告时使用此技能,包括但不限于:
- 业务报告:销售报告、收入分析、业绩统计、财务报表
- 数据分析报告:趋势分析、对比分析、分布分析、相关性分析
- 统计报告:汇总统计、排名报告、占比分析、异常检测
- 运营报告:用户行为分析、产品使用统计、系统监控报告、运营指标
- 自定义报告:根据用户具体需求定制的任何报告
关键特征:
- 能够理解用户的自然语言诉求
- 自动识别报告类型和数据需求
- 生成专业的可视化报告
- 支持多种报告格式和图表类型
⚠️ 重要约束:
- 禁止写入本地文件 - 所有生成的 HTML 报告必须直接上传到 MinIO,不允许使用任何文件系统工具保存到本地
- 只使用
upload_html_report_to_minio- 这是唯一允许的上传方法,直接传递 HTML 内容字符串 - 禁止使用
upload_html_file_to_minio- 该工具需要本地文件路径,不符合要求
工作流程
1. 理解用户诉求
仔细分析用户的报告需求,识别以下关键信息:
- 报告类型:用户想要什么类型的报告?(销售、用户、产品、运营、财务等)
- 数据维度:需要按什么维度分析?(时间、地区、类别、用户、产品等)
- 关键指标:用户关注哪些指标?(总量、平均值、增长率、排名、占比等)
- 时间范围:需要分析哪个时间段的数据?(最近一周、一个月、一年等)
- 对比需求:是否需要对比分析?(同比、环比、不同类别对比等)
- 可视化需求:用户希望看到什么类型的图表?(趋势图、对比图、分布图、排名图等)
- 报告格式:是否需要摘要、详细数据、图表、结论、建议等
常见报告诉求示例:
- "生成一份销售报告,显示过去一年的月度销售趋势"
- "分析用户活跃度,按地区统计用户数量并生成可视化报告"
- "生成产品库存报告,显示各产品的库存状态和预警"
- "创建一个收入分析报告,对比不同渠道的收入占比"
- "生成一份客户满意度报告,按月份统计评分趋势"
- "分析网站访问数据,生成用户行为分析报告"
- "生成员工绩效报告,按部门统计业绩排名"
2. 探索数据库架构
根据用户诉求,使用 sql_db_list_tables 和 sql_db_schema 查找相关表:
-
识别相关表:根据报告类型找到对应的数据表
- 销售报告 → 订单表、发票表、产品表
- 用户报告 → 用户表、活动表、登录表
- 产品报告 → 产品表、库存表、订单明细表
- 运营报告 → 日志表、事件表、指标表
-
查找关键字段:
- 日期/时间列:用于时间序列分析(created_at, updated_at, date, timestamp 等)
- 数值列:用于聚合计算(金额、数量、评分、计数等)
- 分类列:用于分组分析(地区、类别、状态、类型等)
- 标识列:用于关联和展示(ID、名称、代码等)
-
映射表关系:理解表之间的外键关系,确定如何 JOIN 多个表
3. 设计查询策略
根据报告需求设计 SQL 查询:
-
过滤条件:确定 WHERE 子句(时间范围、状态、类别、条件等)
-
聚合函数:选择合适的聚合函数
- SUM - 求和(金额、数量)
- COUNT - 计数(记录数、用户数)
- AVG - 平均值(评分、价格)
- MAX/MIN - 最值(最大值、最小值)
- STDDEV - 标准差(数据分布)
- PERCENTILE - 百分位数(中位数、分位数)
-
分组维度:确定 GROUP BY 字段(时间、地区、类别、用户等)
-
排序规则:确定 ORDER BY 字段(按数值降序、按时间升序等)
-
计算字段:需要时计算百分比、增长率、占比等衍生指标
-
数据限制:合理使用 LIMIT(默认显示前 N 条,除非用户要求全部)
查询设计原则:
- 只查询必要的列,避免 SELECT *
- 使用表别名提高可读性
- 对于复杂查询,先用
write_todos规划步骤 - 确保所有 JOIN 都有明确的连接条件
- 验证 GROUP BY 包含所有非聚合列
- 使用适当的日期函数处理时间维度
4. 生成带图表的 HTML 报告
根据报告类型和用户需求,生成专业的 HTML 报告。HTML 报告应包含:
报告结构:
-
报告标题 - 清晰描述报告内容和时间范围
-
摘要统计卡片 - 顶部展示关键指标(KPI),如总计、平均值、最大值、增长率等
-
可视化图表 - 使用 Chart.js 库创建交互式图表:
- 折线图 - 用于时间趋势分析(月度趋势、年度趋势、日趋势等)
- 柱状图 - 用于类别对比(地区对比、产品对比、部门对比等)
- 饼图/环形图 - 用于占比分布(市场份额、类别占比、状态分布等)
- 面积图 - 用于累积数据展示
- 组合图 - 多个指标在同一图表中展示(柱状图+折线图)
- 散点图 - 用于相关性分析
- 雷达图 - 用于多维度对比
-
详细数据表格 - 完整的数据列表,支持排序和筛选
-
分析结论 - 简要的数据洞察和发现(可选,根据用户需求)
图表类型选择指南:
- 时间序列数据 → 折线图或面积图
- 类别对比 → 柱状图(垂直或水平)
- 占比分析 → 饼图或环形图
- 多指标对比 → 组合图(柱状图+折线图)
- 排名展示 → 水平柱状图
- 相关性分析 → 散点图
- 多维度对比 → 雷达图
关于 HTML 生成的重要说明:
- 直接生成完整的 HTML 内容作为单个字符串
- 应用 UI/UX 最佳实践,包括专业的配色方案和优雅的排版
- 根据报告类型选择合适的配色方案(业务报告用专业色调,数据报告用清晰对比色)
- 禁止写入本地文件 - HTML 内容必须直接上传到 MinIO,不允许使用任何文件系统工具保存到本地
- HTML 字符串应传递给
upload_html_report_to_minio工具进行上传
5. 上传 HTML 报告到 MinIO 并返回 URL
重要: 生成 HTML 报告后,您必须自动将其上传到 MinIO 并向用户返回可点击的 URL。
⚠️ 严格禁止:
- 禁止使用任何文件系统工具写入本地文件(如
write_file、save_file等) - 禁止将 HTML 内容保存到本地文件系统
- 禁止使用
upload_html_file_to_minio工具(该工具需要本地文件路径) - 所有文件必须直接上传到 MinIO,不经过本地文件系统
唯一允许的上传方法:直接上传 HTML 内容字符串
将 HTML 内容生成为字符串后,必须使用 upload_html_report_to_minio 工具:
使用工具:upload_html_report_to_minio
参数:
- html_content: (字符串) 完整的 HTML 报告内容
- file_name: (可选) 自定义文件名,例如 "user_analysis_report_2024_01.html"
如果未提供,自动生成: "report_YYYYMMDD_HHMMSS.html"
- bucket_name: (可选) 默认为 "filedata"
标准工作流程(必须遵循):
- 将 HTML 内容生成为字符串变量(在内存中)
- 直接使用 HTML 内容字符串调用
upload_html_report_to_minio工具 - 工具返回预签名 URL(有效期为 7 天)
- 格式化并向用户返回 URL
错误示例(禁止):
- ❌ 使用
write_file将 HTML 保存到本地 - ❌ 使用
upload_html_file_to_minio上传本地文件 - ❌ 任何涉及本地文件系统的操作
正确示例(必须):
- ✅ 生成 HTML 字符串 → 直接调用
upload_html_report_to_minio(html_content=html_string)
以格式化的可点击链接形式向用户返回 URL:
📊 **报告已生成**
🔗 <a href="{report_url}" target="_blank" rel="noopener noreferrer">点击打开新标签页查看完整报告</a>
报告包含:
- 数据统计分析
- 可视化图表
- 详细数据表格
链接有效期:7天
- URL 是有效期为 7 天的预签名 URL
- 前端可以在新的浏览器标签页/窗口中直接打开此 URL
- 用户可以收藏或分享该 URL
关键要点:
- 始终使用上传工具 - 绝不跳过上传步骤
- 禁止写入本地文件 - 所有文件必须直接上传到 MinIO
- 只使用
upload_html_report_to_minio- 禁止使用需要本地文件路径的工具 - 工具自动处理所有 MinIO 操作
- 如果未指定,文件名会自动生成带时间戳
- MinIO URL 允许直接浏览器访问 - 7 天内无需身份验证
- 清晰地格式化响应,以便用户知道可以点击链接
- 包含报告中内容的简要描述
- 文件名应具有描述性,反映报告类型和内容
6. 应用 UI/UX Pro Max 设计原则
重要: 生成 HTML 时,应用 UI/UX Pro Max 设计原则以获得专业、美观的输出。
要应用的设计原则:
- 使用专业的配色方案和优雅的排版
- 确保响应式设计和可访问性
- 生成生产就绪的 HTML 代码
- 参考
ui-ux-pro-max技能获取设计指导
要使用子代理:
- 使用
task工具,设置agent: "html_generator" - 为 HTML 内容提供清晰的要求
- 子代理处理所有设计和实现细节
7. UI/UX 设计原则(由子代理自动应用)
html_generator 子代理自动应用这些原则。供参考:
-
配色方案 - 根据报告类型选择合适的配色方案
- 业务报告:使用专业色调(slate/gray/blue)
- 数据报告:使用清晰对比色(blue/green/purple)
- 财务报告:使用保守色调(navy/gray)
- 运营报告:使用活力色调(blue/teal/orange)
-
排版 - 选择优雅、可读的字体配对(Google Fonts)
- 标题:Playfair Display, Merriweather, Lora
- 正文:Inter, Roboto, Open Sans
-
布局和间距 - 适当的填充、边距和响应式设计
-
视觉层次 - 清晰的部分分隔、基于卡片的布局
-
深色/浅色模式 - 支持两种模式,具有适当的对比度
-
可访问性 - 确保足够的颜色对比度、可读字体
报告的关键 UI/UX 指南:
- 使用基于卡片的布局,带有微妙的阴影和边框
- 应用一致的间距(使用 Tailwind 间距比例:p-4, p-6, p-8)
- 使用专业的配色方案 - 避免明亮/霓虹色
- 确保文本的高对比度(最小 4.5:1 比例)
- 为悬停状态添加平滑过渡(150-300ms)
- 使图表响应式 - 使用容器查询或百分比宽度
- 如果数据量大,为图表包含加载状态
- 使用一致的图标集(Heroicons, Lucide)- 不使用表情符号作为图标
- 为所有交互元素添加 cursor-pointer
示例:应用 UI/UX 原则
1. 根据报告类型选择专业的配色方案
2. 选择优雅的排版(Google Fonts)
3. 使用具有适当间距的基于卡片的布局
4. 确保响应式设计(移动优先方法)
5. 添加平滑过渡和悬停效果
6. 支持浅色和深色模式
8. HTML 图表格式
通过 CDN 使用 Chart.js 创建交互式图表。HTML 应该:
- 从 CDN 包含 Chart.js 库
- 为每个图表创建 canvas 元素
- 将数据格式化为 JavaScript 数组
- 根据数据使用适当的图表类型
- 包含标签、颜色和图例
- 使图表响应式且视觉上吸引人
- 应用 UI/UX Pro Max 配色方案 - 使用专业、可访问的颜色
- 确保图表可访问性 - 高对比度、可读标签
示例:用户活跃度分析报告
步骤 1: 理解用户诉求 用户要求:"分析用户活跃度,按地区统计用户数量,并生成可视化报告"
步骤 2: 探索数据库架构
-- 查找用户相关表
sql_db_list_tables
sql_db_schema(table_name="users")
sql_db_schema(table_name="user_activities")
步骤 3: 查询用户活跃度数据
SELECT
u.region,
COUNT(DISTINCT u.user_id) as total_users,
COUNT(DISTINCT ua.activity_id) as total_activities,
AVG(ua.activity_count) as avg_activities_per_user,
MAX(ua.last_active_date) as last_active_date
FROM users u
LEFT JOIN user_activities ua ON u.user_id = ua.user_id
WHERE ua.last_active_date >= DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY u.region
ORDER BY total_users DESC;
步骤 4: 生成带图表的 HTML 报告并上传到 MinIO
在生成 HTML 之前,应用 UI/UX Pro Max 原则:
- 使用专业的配色方案(根据报告类型选择合适的色调)
- 应用优雅的排版(Google Fonts: Inter + Playfair Display)
- 使用具有适当间距的基于卡片的布局
- 确保响应式设计
- 支持浅色/深色模式
- 添加平滑过渡
首先,使用 UI/UX Pro Max 样式创建 HTML 内容:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户活跃度分析报告</title>
<!-- Google Fonts - 专业排版 -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Playfair+Display:wght@600;700&display=swap" rel="stylesheet">
<!-- Chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
:root {
/* 专业配色方案 - 浅色模式 */
--bg-primary: #ffffff;
--bg-secondary: #f8fafc;
--text-primary: #0f172a;
--text-secondary: #475569;
--border-color: #e2e8f0;
--accent-color: #3b82f6;
--accent-hover: #2563eb;
--card-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--card-shadow-hover: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
}
@media (prefers-color-scheme: dark) {
:root {
/* 深色模式颜色 */
--bg-primary: #0f172a;
--bg-secondary: #1e293b;
--text-primary: #f1f5f9;
--text-secondary: #cbd5e1;
--border-color: #334155;
--accent-color: #60a5fa;
--accent-hover: #3b82f6;
}
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background: var(--bg-secondary);
color: var(--text-primary);
line-height: 1.6;
padding: 2rem 1rem;
transition: background-color 0.3s ease, color 0.3s ease;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
/* 基于卡片的布局 */
.card {
background: var(--bg-primary);
border: 1px solid var(--border-color);
border-radius: 12px;
padding: 2rem;
margin-bottom: 2rem;
box-shadow: var(--card-shadow);
transition: box-shadow 0.3s ease, transform 0.2s ease;
}
.card:hover {
box-shadow: var(--card-shadow-hover);
}
/* 报告标题 */
.report-header {
text-align: center;
margin-bottom: 3rem;
}
.report-header h1 {
font-family: 'Playfair Display', serif;
font-size: 2.5rem;
font-weight: 700;
color: var(--text-primary);
margin-bottom: 0.5rem;
}
.report-header p {
font-size: 1.125rem;
color: var(--text-secondary);
}
/* 摘要统计卡片 */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.stat-card {
background: var(--bg-primary);
border: 1px solid var(--border-color);
border-radius: 8px;
padding: 1.5rem;
text-align: center;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.stat-card:hover {
transform: translateY(-2px);
box-shadow: var(--card-shadow-hover);
}
.stat-value {
font-size: 2rem;
font-weight: 700;
color: var(--accent-color);
margin-bottom: 0.5rem;
}
.stat-label {
font-size: 0.875rem;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.05em;
}
/* 图表容器 */
.chart-container {
width: 100%;
height: 400px;
margin: 2rem 0;
position: relative;
}
.chart-title {
font-size: 1.25rem;
font-weight: 600;
color: var(--text-primary);
margin-bottom: 1rem;
}
/* 表格样式 */
.table-wrapper {
overflow-x: auto;
border-radius: 8px;
}
table {
width: 100%;
border-collapse: collapse;
background: var(--bg-primary);
}
th {
background: var(--accent-color);
color: white;
padding: 1rem;
text-align: left;
font-weight: 600;
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.05em;
}
td {
padding: 1rem;
border-bottom: 1px solid var(--border-color);
color: var(--text-primary);
}
tr:hover {
background: var(--bg-secondary);
transition: background-color 0.2s ease;
}
/* 响应式设计 */
@media (max-width: 768px) {
body {
padding: 1rem 0.5rem;
}
.card {
padding: 1.5rem;
}
.report-header h1 {
font-size: 2rem;
}
.chart-container {
height: 300px;
}
.stats-grid {
grid-template-columns: 1fr;
}
}
/* 可访问性 */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
</style>
</head>
<body>
<div class="container">
<!-- 报告标题卡片 -->
<div class="card report-header">
<h1>用户活跃度分析报告</h1>
<p>期间:2024年1月 - 2024年12月</p>
</div>
<!-- 摘要统计卡片 -->
<div class="card">
<div class="stats-grid">
<div class="stat-card">
<div class="stat-value">15,234</div>
<div class="stat-label">总用户数</div>
</div>
<div class="stat-card">
<div class="stat-value">89,456</div>
<div class="stat-label">总活动数</div>
</div>
<div class="stat-card">
<div class="stat-value">5.87</div>
<div class="stat-label">平均活跃度</div>
</div>
</div>
</div>
<!-- 图表卡片 - 柱状图 -->
<div class="card">
<div class="chart-title">按地区用户数量分布</div>
<div class="chart-container">
<canvas id="barChart"></canvas>
</div>
</div>
<!-- 图表卡片 - 饼图 -->
<div class="card">
<div class="chart-title">各地区用户占比</div>
<div class="chart-container">
<canvas id="pieChart"></canvas>
</div>
</div>
<!-- 数据表格卡片 -->
<div class="card">
<div class="table-wrapper">
<table>
<thead>
<tr>
<th>地区</th>
<th>用户数</th>
<th>活动数</th>
<th>平均活跃度</th>
<th>最后活跃日期</th>
</tr>
</thead>
<tbody>
<!-- 数据行在这里 -->
<tr>
<td>华东</td>
<td>5,234</td>
<td>32,456</td>
<td>6.2</td>
<td>2024-12-25</td>
</tr>
<tr>
<td>华南</td>
<td>4,567</td>
<td>28,123</td>
<td>6.1</td>
<td>2024-12-24</td>
</tr>
<tr>
<td>华北</td>
<td>3,890</td>
<td>21,234</td>
<td>5.5</td>
<td>2024-12-23</td>
</tr>
<tr>
<td>西南</td>
<td>1,543</td>
<td>7,643</td>
<td>5.0</td>
<td>2024-12-22</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script>
// 检测颜色方案偏好
const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
// 专业配色方案
const colors = {
light: {
primary: '#3b82f6',
secondary: '#8b5cf6',
accent: '#10b981',
warning: '#f59e0b',
danger: '#ef4444',
background: 'rgba(59, 130, 246, 0.1)'
},
dark: {
primary: '#60a5fa',
secondary: '#a78bfa',
accent: '#34d399',
warning: '#fbbf24',
danger: '#f87171',
background: 'rgba(96, 165, 250, 0.1)'
}
};
const palette = isDarkMode ? colors.dark : colors.light;
// 柱状图配置
const barCtx = document.getElementById('barChart').getContext('2d');
new Chart(barCtx, {
type: 'bar',
data: {
labels: ['华东', '华南', '华北', '西南', '东北', '西北'],
datasets: [{
label: '用户数量',
data: [5234, 4567, 3890, 1543, 890, 110],
backgroundColor: palette.primary,
borderColor: palette.primary,
borderWidth: 2,
borderRadius: 8
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
display: false
},
legend: {
display: false
}
},
scales: {
x: {
grid: {
color: isDarkMode ? 'rgba(203, 213, 225, 0.1)' : 'rgba(226, 232, 240, 0.5)',
display: false
},
ticks: {
color: isDarkMode ? '#cbd5e1' : '#475569',
font: {
family: 'Inter',
size: 12
}
}
},
y: {
beginAtZero: true,
grid: {
color: isDarkMode ? 'rgba(203, 213, 225, 0.1)' : 'rgba(226, 232, 240, 0.5)',
display: true
},
ticks: {
color: isDarkMode ? '#cbd5e1' : '#475569',
font: {
family: 'Inter',
size: 12
}
}
}
}
}
});
// 饼图配置
const pieCtx = document.getElementById('pieChart').getContext('2d');
new Chart(pieCtx, {
type: 'pie',
data: {
labels: ['华东', '华南', '华北', '西南', '东北', '西北'],
datasets: [{
data: [5234, 4567, 3890, 1543, 890, 110],
backgroundColor: [
palette.primary,
palette.secondary,
palette.accent,
palette.warning,
'#a78bfa',
'#f472b6'
],
borderWidth: 2,
borderColor: isDarkMode ? '#1e293b' : '#ffffff'
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
display: false
},
legend: {
display: true,
position: 'right',
labels: {
font: {
family: 'Inter',
size: 12
},
color: isDarkMode ? '#cbd5e1' : '#475569',
usePointStyle: true,
padding: 15
}
}
}
}
});
</script>
</body>
</html>
折线图示例(用于时间趋势分析):
<!-- 折线图卡片 -->
<div class="card">
<div class="chart-title">月度活跃度趋势</div>
<div class="chart-container">
<canvas id="lineChart"></canvas>
</div>
</div>
<script>
// 折线图配置
const lineCtx = document.getElementById('lineChart').getContext('2d');
new Chart(lineCtx, {
type: 'line',
data: {
labels: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
datasets: [{
label: '活跃用户数',
data: [12000, 13500, 14200, 15800, 16500, 17200, 18000, 17500, 18200, 19000, 19500, 20000],
borderColor: palette.primary,
backgroundColor: palette.background,
tension: 0.4,
fill: true,
borderWidth: 3,
pointRadius: 5,
pointHoverRadius: 7,
pointBackgroundColor: palette.primary,
pointBorderColor: '#ffffff',
pointBorderWidth: 2
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
display: false
},
legend: {
display: true,
position: 'top',
labels: {
font: {
family: 'Inter',
size: 12
},
color: isDarkMode ? '#cbd5e1' : '#475569',
usePointStyle: true,
padding: 15
}
}
},
scales: {
x: {
grid: {
color: isDarkMode ? 'rgba(203, 213, 225, 0.1)' : 'rgba(226, 232, 240, 0.5)',
display: true
},
ticks: {
color: isDarkMode ? '#cbd5e1' : '#475569',
font: {
family: 'Inter',
size: 12
}
}
},
y: {
beginAtZero: true,
grid: {
color: isDarkMode ? 'rgba(203, 213, 225, 0.1)' : 'rgba(226, 232, 240, 0.5)',
display: true
},
ticks: {
color: isDarkMode ? '#cbd5e1' : '#475569',
font: {
family: 'Inter',
size: 12
}
}
}
}
}
});
</script>
组合图示例(柱状图+折线图,用于多指标对比):
<!-- 组合图卡片 -->
<div class="card">
<div class="chart-title">收入与增长率对比</div>
<div class="chart-container">
<canvas id="comboChart"></canvas>
</div>
</div>
<script>
// 组合图配置
const comboCtx = document.getElementById('comboChart').getContext('2d');
new Chart(comboCtx, {
type: 'bar',
data: {
labels: ['1月', '2月', '3月', '4月', '5月', '6月'],
datasets: [
{
type: 'bar',
label: '收入(万元)',
data: [120, 150, 180, 200, 220, 250],
backgroundColor: palette.primary,
borderColor: palette.primary,
borderWidth: 2,
borderRadius: 8,
yAxisID: 'y'
},
{
type: 'line',
label: '增长率(%)',
data: [0, 25, 20, 11, 10, 14],
borderColor: palette.accent,
backgroundColor: 'transparent',
borderWidth: 3,
tension: 0.4,
pointRadius: 5,
pointHoverRadius: 7,
yAxisID: 'y1'
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
display: false
},
legend: {
display: true,
position: 'top',
labels: {
font: {
family: 'Inter',
size: 12
},
color: isDarkMode ? '#cbd5e1' : '#475569',
usePointStyle: true,
padding: 15
}
}
},
scales: {
x: {
grid: {
color: isDarkMode ? 'rgba(203, 213, 225, 0.1)' : 'rgba(226, 232, 240, 0.5)',
display: false
},
ticks: {
color: isDarkMode ? '#cbd5e1' : '#475569',
font: {
family: 'Inter',
size: 12
}
}
},
y: {
type: 'linear',
display: true,
position: 'left',
beginAtZero: true,
grid: {
color: isDarkMode ? 'rgba(203, 213, 225, 0.1)' : 'rgba(226, 232, 240, 0.5)',
display: true
},
ticks: {
color: isDarkMode ? '#cbd5e1' : '#475569',
font: {
family: 'Inter',
size: 12
}
}
},
y1: {
type: 'linear',
display: true,
position: 'right',
beginAtZero: true,
grid: {
drawOnChartArea: false
},
ticks: {
color: isDarkMode ? '#cbd5e1' : '#475569',
font: {
family: 'Inter',
size: 12
},
callback: function(value) {
return value + '%';
}
}
}
}
}
});
</script>
然后使用工具自动上传到 MinIO:
使用工具:upload_html_report_to_minio
参数:
html_content: """<!DOCTYPE html>...""" # 您的完整 HTML 内容
file_name: "user_activity_report_2024_01.html" # 可选,如果未提供则自动生成
bucket_name: "filedata" # 可选,默认为 "filedata"
工具自动返回预签名 URL。
然后格式化响应:
📊 **报告已生成**
🔗 <a href="{report_url}" target="_blank" rel="noopener noreferrer">点击打开新标签页查看完整报告</a>
报告包含:
- 数据统计分析
- 可视化图表
- 详细数据表格
链接有效期:7天
图表类型选择指南
折线图 - 用于:
- 时间趋势
- 比较多个时间序列
- 显示变化和模式
- 预测趋势
柱状图 - 用于:
- 比较类别
- 排名项目
- 显示组间差异
- 对比不同维度
饼图 - 用于:
- 显示比例/百分比
- 整体的分布
- 当您有 2-7 个类别时
- 展示占比关系
面积图 - 用于:
- 时间上的累积值
- 显示数量/体积趋势
- 堆叠比较
- 展示累积变化
组合图 - 用于:
- 多个指标在同一图表中展示
- 不同量级的指标对比
- 趋势和总量的结合展示
质量指南
对于 SQL 查询:
- 始终使用适当的日期过滤器
- 包含有意义的聚合
- 按相关维度分组
- 逻辑地排序结果
- 限制为合理的行数(除非用户指定)
- 使用适当的日期函数处理时间维度
- 验证 JOIN 条件和 GROUP BY 子句
对于 HTML 报告:
重要:在生成 HTML 报告时,必须严格遵循以下 UI/UX Pro Max 设计原则。
核心 UI/UX 设计原则(基于 ui-ux-pro-max 技能):
-
配色方案:
- 使用专业的配色方案,根据报告类型选择:
- 数据分析报告:蓝色系(#3B82F6, #1E40AF)为主,辅以绿色(#10B981)表示增长
- 业务报告:深蓝/紫色系(#6366F1, #8B5CF6)为主,体现专业性
- 财务报告:深色背景(#1F2937)配金色/绿色强调(#F59E0B, #10B981)
- 确保文本对比度至少 4.5:1(WCAG AA 标准)
- 使用语义化颜色:成功=绿色,警告=黄色,错误=红色,信息=蓝色
- 使用专业的配色方案,根据报告类型选择:
-
排版和字体:
- 使用 Google Fonts,推荐字体配对:
- 标题:Inter, Playfair Display, Poppins(粗体 600-700)
- 正文:Inter, Roboto, Open Sans(常规 400)
- 字体大小:标题 24-32px,副标题 18-20px,正文 16px,小字 14px
- 行高:标题 1.2,正文 1.6-1.8
- 字间距:标题 0.5px,正文正常
- 使用 Google Fonts,推荐字体配对:
-
布局和间距:
- 使用基于卡片的布局,卡片间距 16-24px
- 卡片内边距:16-24px
- 使用 Tailwind CSS 的间距系统(4px 基准)
- 最大内容宽度:1200px,居中显示
- 使用网格系统:12 列或 Flexbox
-
响应式设计:
- 移动优先方法
- 断点:320px(手机),768px(平板),1024px(桌面)
- 使用 CSS Grid 和 Flexbox 实现响应式布局
- 图表和表格在小屏幕上可横向滚动
-
深色/浅色模式:
- 使用 CSS 变量定义颜色主题
- 支持
prefers-color-scheme: dark媒体查询 - 提供手动切换按钮(可选)
- 确保两种模式下都有足够的对比度
-
交互和动画:
- 悬停状态过渡:150-300ms ease-in-out
- 卡片悬停效果:轻微阴影增加(shadow-md → shadow-lg)
- 按钮悬停:颜色加深 10%,轻微缩放(scale-105)
- 避免过度动画,保持专业感
-
图标和视觉元素:
- 使用一致的图标库:Heroicons 或 Lucide
- 禁止使用表情符号作为图标
- 图标大小:16px(小),20px(中),24px(大)
- 图标颜色:使用主题色,保持一致性
-
图表设计:
- 使用 Chart.js 或 ECharts 等专业图表库
- 图表类型选择:
- 趋势数据:折线图或面积图
- 分类对比:柱状图或条形图
- 占比数据:饼图或环形图
- 分布数据:散点图或直方图
- 图表颜色:使用配色方案中的颜色,保持一致性
- 添加图例、坐标轴标签、数据标签
- 确保图表可访问性(ARIA 标签)
-
数据表格:
- 使用清晰的表头(背景色区分)
- 交替行颜色(zebra striping)提高可读性
- 悬停高亮当前行
- 重要数据使用粗体或颜色强调
- 数字右对齐,文本左对齐
- 支持排序和筛选(如需要)
-
报告结构:
- 标题区域:报告名称、日期范围、生成时间
- 摘要统计卡片:关键指标(KPI)突出显示
- 图表区域:主要可视化内容
- 详细数据表格:完整数据视图
- 结论和建议:文字总结(如需要)
-
技术实现:
- 使用 Tailwind CSS 进行样式设计
- 使用 CDN 引入 Google Fonts
- 使用 CDN 引入图表库(Chart.js, ECharts 等)
- 确保 HTML 文件可以独立运行(包含所有依赖)
- 优化加载性能:压缩 CSS,使用 CDN
-
文件处理:
- 始终将 HTML 文件上传到 MinIO 并返回 URL
- 在响应中将 URL 格式化为可点击链接(Markdown 格式:
[查看报告](URL)) - 使用描述性文件名:
{report_type}_{date_range}_{timestamp}.html - 例如:
sales_report_2024_Q1_20240126_143022.html
对于统计分析:
- 计算总计、平均值、计数
- 相关时显示百分比
- 比较时间段或类别
- 突出趋势和模式
- 识别表现最佳/最差者
- 计算增长率和变化率
常见报告模式
模式 1:时间序列报告
"显示过去一年的月度销售趋势" → 使用 DATE_TRUNC 查询,按月份 GROUP BY,按月份 ORDER BY → 使用折线图或柱状图
模式 2:类别比较
"按地区比较用户数量" → 使用 GROUP BY region 查询 → 使用柱状图或饼图
模式 3:表现最佳者
"显示销售额排名前 10 的产品" → 使用 ORDER BY sales DESC LIMIT 10 查询 → 使用柱状图(水平)
模式 4:趋势分析
"显示月度环比增长率" → 使用窗口函数或自连接查询 → 使用带百分比计算的折线图
模式 5:占比分析
"分析各渠道的收入占比" → 使用 GROUP BY 和百分比计算 → 使用饼图或环形图
模式 6:多维度分析
"分析用户行为,按地区和年龄段统计" → 使用多维度 GROUP BY → 使用组合图或分组柱状图
提示
- 执行前始终验证 SQL 查询
- 在 SQL 中使用适当的日期格式
- 在 HTML 中使用逗号和货币符号格式化数字
- 生成 HTML 之前,咨询
ui-ux-pro-max技能获取设计最佳实践 - 选择可访问且专业的图表颜色(使用 UI/UX Pro Max 配色方案)
- 为完整性包含可视化图表和数据表格
- 在报告标题中添加简要分析或见解
- 使用响应式设计以在不同屏幕上更好地显示
- 在最终确定 HTML 之前应用 UI/UX Pro Max 检查清单:
- 应用了专业配色方案
- 优雅的排版(Google Fonts)
- 具有适当间距的基于卡片的布局
- 在所有断点响应式
- 支持浅色/深色模式
- 高对比度以确保可访问性
- 平滑过渡(150-300ms)
- 不使用表情符号作为图标
- 一致的图标集(Heroicons/Lucide)
- 记住将 HTML 报告上传到 MinIO - 绝不直接返回 HTML 内容
- 禁止写入本地文件 - 必须使用
upload_html_report_to_minio直接上传 HTML 字符串 - MinIO URL 允许前端在新标签页/窗口中打开报告
- 文件名应具有描述性,并在相关时包含时间戳或日期范围
- 根据用户诉求灵活调整报告内容和格式
- 如果用户需求不明确,主动询问澄清关键信息
Related Skills
Attack Tree Construction
Build comprehensive attack trees to visualize threat paths. Use when mapping attack scenarios, identifying defense gaps, or communicating security risks to stakeholders.
Grafana Dashboards
Create and manage production Grafana dashboards for real-time visualization of system and application metrics. Use when building monitoring dashboards, visualizing metrics, or creating operational observability interfaces.
Matplotlib
Foundational plotting library. Create line plots, scatter, bar, histograms, heatmaps, 3D, subplots, export PNG/PDF/SVG, for scientific visualization and publication figures.
Scientific Visualization
Create publication figures with matplotlib/seaborn/plotly. Multi-panel layouts, error bars, significance markers, colorblind-safe, export PDF/EPS/TIFF, for journal-ready scientific plots.
Seaborn
Statistical visualization. Scatter, box, violin, heatmaps, pair plots, regression, correlation matrices, KDE, faceted plots, for exploratory analysis and publication figures.
Shap
Model interpretability and explainability using SHAP (SHapley Additive exPlanations). Use this skill when explaining machine learning model predictions, computing feature importance, generating SHAP plots (waterfall, beeswarm, bar, scatter, force, heatmap), debugging models, analyzing model bias or fairness, comparing models, or implementing explainable AI. Works with tree-based models (XGBoost, LightGBM, Random Forest), deep learning (TensorFlow, PyTorch), linear models, and any black-box model
Pydeseq2
Differential gene expression analysis (Python DESeq2). Identify DE genes from bulk RNA-seq counts, Wald tests, FDR correction, volcano/MA plots, for RNA-seq analysis.
Query Writing
For writing and executing SQL queries - from simple single-table queries to complex multi-table JOINs and aggregations
Pydeseq2
Differential gene expression analysis (Python DESeq2). Identify DE genes from bulk RNA-seq counts, Wald tests, FDR correction, volcano/MA plots, for RNA-seq analysis.
Scientific Visualization
Meta-skill for publication-ready figures. Use when creating journal submission figures requiring multi-panel layouts, significance annotations, error bars, colorblind-safe palettes, and specific journal formatting (Nature, Science, Cell). Orchestrates matplotlib/seaborn/plotly with publication styles. For quick exploration use seaborn or plotly directly.
