今天,我们要构建一个数据看板系统。在这个过程中,我们会利用 MySQL 来存储数据,使用 Python 搭建后端 API,还会借助 Chart.js 在前端呈现各式各样的图表。
整个流程涵盖多个环节,首先要进行数据库表的设计,接着将数据插入到数据库中,然后搭建后端的数据接口,最后在前端通过 JavaScript 动态渲染图表,如此便形成了完整的数据看板系统。
1. 安装依赖
在运行代码前,确保安装了必要的 Python 依赖:
pip install flask pymysql
2. 创建 MySQL 数据表
运行以下 SQL 代码,创建用于存储数据的 your_table
表:
CREATE TABLE kb (
id INT AUTO_INCREMENT PRIMARY KEY,
category VARCHAR(50),
year INT,
month INT,
value INT
);
3. 数据库插入数据
运行以下 SQL 代码,插入数据:
INSERT INTO kb (category, year, month, value) VALUES ('人事', 2023, 1, 399);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2023, 1, 410);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2023, 1, 208);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2023, 2, 291);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2023, 2, 172);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2023, 2, 199);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2023, 3, 370);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2023, 3, 454);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2023, 3, 207);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2023, 4, 397);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2023, 4, 228);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2023, 4, 151);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2023, 5, 373);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2023, 5, 429);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2023, 5, 307);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2023, 6, 485);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2023, 6, 419);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2023, 6, 468);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2023, 7, 169);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2023, 7, 185);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2023, 7, 289);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2023, 8, 282);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2023, 8, 232);
INSERTINTO kb (category, year, month, value) VALUES ('财务', 2023, 8, 339);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2023, 9, 269);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2023, 9, 274);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2023, 9, 435);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2023, 10, 463);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2023, 10, 108);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2023, 10, 295);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2023, 11, 168);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2023, 11, 351);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2023, 11, 162);
INSERTINTO kb (category, year, month, value) VALUES ('财务', 2023, 12, 395);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2023, 12, 428);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2023, 12, 339);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2024, 1, 192);
INSERTINTO kb (category, year, month, value) VALUES ('财务', 2024, 1, 156);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 1, 130);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2024, 2, 442);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2024, 2, 149);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2024, 2, 460);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 3, 293);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2024, 3, 228);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2024, 3, 231);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2024, 4, 288);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2024, 4, 242);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 4, 205);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 5, 491);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2024, 5, 144);
INSERTINTO kb (category, year, month, value) VALUES ('财务', 2024, 5, 255);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2024, 6, 128);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2024, 6, 439);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 6, 177);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2024, 7, 486);
INSERTINTO kb (category, year, month, value) VALUES ('财务', 2024, 7, 411);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2024, 7, 338);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 8, 456);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2024, 8, 93);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2024, 8, 63);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2024, 9, 149);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 9, 248);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2024, 9, 158);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2024, 10, 255);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2024, 10, 493);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2024, 10, 234);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2024, 11, 383);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 11, 128);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 11, 116);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2024, 12, 438);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2024, 12, 449);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2024, 12, 426);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2025, 1, 171);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2025, 1, 270);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2025, 1, 350);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2025, 2, 351);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2025, 2, 260);
INSERTINTO kb (category, year, month, value) VALUES ('供应链', 2025, 2, 186);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2025, 3, 51);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 3, 410);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2025, 3, 294);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2025, 4, 495);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 4, 436);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 4, 363);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2025, 5, 406);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2025, 5, 149);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2025, 5, 329);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2025, 6, 187);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2025, 6, 490);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 6, 471);
INSERTINTO kb (category, year, month, value) VALUES ('财务', 2025, 7, 387);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 7, 481);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 7, 249);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 8, 177);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2025, 8, 160);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2025, 8, 423);
INSERTINTO kb (category, year, month, value) VALUES ('销售', 2025, 9, 111);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2025, 9, 131);
INSERTINTO kb (category, year, month, value) VALUES ('人事', 2025, 9, 426);
INSERTINTO kb (category, year, month, value) VALUES ('市场', 2025, 10, 448);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2025, 10, 317);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2025, 10, 58);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2025, 11, 311);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2025, 11, 343);
INSERTINTO kb (category, year, month, value) VALUES ('运营', 2025, 11, 284);
INSERTINTO kb (category, year, month, value) VALUES ('研发', 2025, 12, 312);
INSERTINTO kb (category, year, month, value) VALUES ('财务', 2025, 12, 95);
INSERTINTO kb (category, year, month, value) VALUES ('客服', 2025, 12, 400);
4. python后端(server.py)
from flask import Flask, jsonify, render_template
import pymysql.cursors
app = Flask(__name__)
# 连接 MySQL 数据库
def get_db_connection():
return pymysql.connect(
host="localhost",
user="root", # 修改为你的数据库用户名
password="root", # 修改为你的数据库密码
database="demo2", # 修改为你的数据库名称
port=3306,
cursorclass=pymysql.cursors.DictCursor
)
# API:获取数据
@app.route("/api/data")
def get_data():
connection = get_db_connection()
with connection.cursor() as cursor:
cursor.execute("SELECT year, month, category, value FROM kb ORDER BY year, month")
data = cursor.fetchall()
connection.close()
return jsonify(data)
# 前端页面
@app.route("/")
def index():
return render_template("index.html")
if __name__ == "__main__":
app.run(debug=True)
5. 前端页面(templates/index.html)
在 templates/
目录下创建 index.html
文件:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据看板</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
body {
font-family: 'Arial', sans-serif;
background: linear-gradient(to right, #141e30, #243b55);
color: white;
text-align: center;
padding: 20px;
}
h2 {
font-size: 2rem;
margin-bottom: 20px;
}
.chart-container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
justify-items: center;
padding: 20px;
}
.chart-box {
width: 1000px; /* 根据需求可继续调大或调小 */
height: 500px; /* 根据需求可继续调大或调小 */
background: rgba(255, 255, 255, 0.1);
padding: 20px;
border-radius: 15px;
box-shadow: 0px 0px 15px rgba(255, 255, 255, 0.3);
transition: transform 0.3s;
display: flex;
align-items: center;
justify-content: center;
}
.chart-box:hover {
transform: scale(1.05);
}
canvas {
width: 100% !important;
height: 100% !important;
}
</style>
</head>
<body>
<h2>✨ 数据看板 ✨</h2>
<div class="chart-container">
<div class="chart-box"><canvas id="barChart"></canvas></div>
<div class="chart-box"><canvas id="pieChart"></canvas></div>
<div class="chart-box"><canvas id="lineChart"></canvas></div>
<div class="chart-box"><canvas id="scatterChart"></canvas></div>
</div>
<script>
fetch('/api/data')
.then(response => response.json())
.then(data => {
// 1. 准备数据
const categories = [...new Set(data.map(item => item.category))];
const months = Array.from({ length: 12 }, (_, i) => `${i + 1}月`);
let datasetMap = {};
categories.forEach(category => {
datasetMap[category] = Array(12).fill(0);
});
data.forEach(item => {
datasetMap[item.category][item.month - 1] = item.value;
});
// 2. 随机色
const colors = categories.map(() => `hsl(${Math.random()*360}, 80%, 60%)`);
// 3. 柱状图
const ctxBar = document.getElementById('barChart').getContext('2d');
new Chart(ctxBar, {
type: 'bar',
data: {
labels: months,
datasets: categories.map((category, i) => ({
label: category,
data: datasetMap[category],
backgroundColor: colors[i],
borderColor: 'white',
borderWidth: 1
}))
},
options: { responsive: true }
});
// 4. 饼图
const ctxPie = document.getElementById('pieChart').getContext('2d');
new Chart(ctxPie, {
type: 'doughnut',
data: {
labels: categories,
datasets: [{
data: categories.map(category => datasetMap[category].reduce((a, b) => a + b, 0)),
backgroundColor: colors,
borderColor: 'white'
}]
},
options: { responsive: true }
});
// 5. 折线图(鼠标悬浮时显示数值)
const ctxLine = document.getElementById('lineChart').getContext('2d');
new Chart(ctxLine, {
type: 'line',
data: {
labels: months,
datasets: categories.map((category, i) => ({
label: category,
data: datasetMap[category],
borderColor: colors[i],
fill: false,
tension: 0.4,
pointBackgroundColor: 'white'
}))
},
options: {
responsive: true,
// 关键:鼠标悬浮显示数值
interaction: {
mode: 'index',
intersect: false
},
plugins: {
tooltip: {
enabled: true,
callbacks: {
// 回调函数,自定义显示的文本
label: function(context) {
let label = context.dataset.label || '';
let value = context.parsed.y !== undefined ? context.parsed.y : '';
return `${label}: ${value}`;
}
}
}
}
}
});
// 6. 散点图
const ctxScatter = document.getElementById('scatterChart').getContext('2d');
new Chart(ctxScatter, {
type: 'scatter',
data: {
datasets: categories.map((category, i) => ({
label: category,
data: datasetMap[category].map((value, index) => ({ x: index + 1, y: value })),
backgroundColor: colors[i],
borderColor: 'white',
pointRadius: 6
}))
},
options: { responsive: true }
});
})
.catch(error => console.error('数据加载失败:', error));
</script>
</body>
</html>
6. 运行 Flask 服务器
python server.py
然后打开浏览器,访问:
http://127.0.0.1:5000
点击阅读原文:《用 python、MySQL 和 Chart.js 打造炫酷数据看板》实战案例笔记
原创 IT小本本 IT小本本 2025年03月11日 21:21 北京
最终效果: