大家好!我是CSDN的Python新手博主~ 上一篇我们完成了看板的移动端适配与企业微信深度集成,打通了全场景办公链路,但很多小伙伴反馈两个核心痛点:① 数据来源太单一,实际工作中数据可能分散在Excel、数据库、CSV文件中,需要手动汇总后导入看板,效率极低;② 图表是静态图片,无法缩放、筛选,想查看某一部门/时间段的细分数据只能重新生成,交互性差。今天就带来超落地的新手实战项目------办公看板多数据源整合+ECharts高级交互式可视化!
本次基于之前的"全场景适配云端看板"代码,新增4大核心功能:① 多数据源统一读取(支持Excel、MySQL数据库、CSV文件,自动适配数据格式);② ECharts交互式图表集成(替换静态图表,实现缩放、点击筛选、多图表联动);③ 自定义图表配置(支持切换图表类型、选择数据维度,如按部门/日期/人员统计);④ 多数据源数据融合分析(如关联MySQL客户数据与Excel销售数据)。全程基于现有技术栈(Flask+HTML),新增数据库连接、ECharts初始化逻辑,代码注释详细,新手只需配置数据源参数,跟着步骤复制操作就能成功,让办公看板具备专业数据分析工具的核心能力~
一、本次学习目标
-
掌握Python读取多数据源(Excel/MySQL/CSV)的方法,封装统一数据读取接口,适配不同数据存储场景;
-
了解ECharts基础语法与配置逻辑,学会在Flask项目中集成ECharts交互式图表;
-
实现图表自定义功能(切换类型、选择维度、筛选条件),适配多样化数据分析需求;
-
掌握多数据源数据融合技巧,实现跨来源数据关联分析(如销售数据关联客户信息);
-
确保多数据源访问与现有权限体系联动,实现数据访问权限精准管控。
二、前期准备
- 安装核心依赖库
安装核心依赖(pymysql对接MySQL,pandas处理数据,openpyxl读取Excel)
pip3 install pymysql pandas openpyxl python-dotenv -i https://pypi.tuna.tsinghua.edu.cn/simple
确保已有依赖正常(Flask、requests等)
pip3 install --upgrade flask flask-login gunicorn requests -i https://pypi.tuna.tsinghua.edu.cn/simple
说明:ECharts为前端框架,无需后端安装,直接通过CDN引入即可;python-dotenv用于安全存储数据库账号密码,避免硬编码。
- 数据源准备与配置
-
Excel数据源(复用原有):/home/office_dashboard/每日销售报表/(存储每日销售明细);
-
MySQL数据源(新增):搭建本地/云端MySQL数据库,创建"customer"表(存储客户信息,关联销售数据),记录数据库地址、端口、账号、密码、数据库名;
-
CSV数据源(新增):/home/office_dashboard/部门配置.csv(存储部门与负责人关联关系,用于图表维度补充);
-
安全配置:创建.env文件存储数据库敏感信息,避免代码泄露。
- ECharts资源准备
三、实战:多数据源整合+ECharts可视化升级
- 第一步:封装多数据源统一读取接口
-- coding: utf-8 --
datasource.py 多数据源读取脚本
import os
import pandas as pd
import pymysql
from dotenv import load_dotenv
from pathlib import Path
加载环境变量(存储数据库敏感信息)
load_dotenv() # 读取.env文件
====================== 数据源配置(新手修改这里) ======================
1. Excel配置
EXCEL_DIR = "/home/office_dashboard/每日销售报表"
EXCEL_SUFFIX = [".xlsx", ".xls"]
2. MySQL配置(从环境变量读取,避免硬编码)
MYSQL_CONFIG = {
"host": os.getenv("MYSQL_HOST", "localhost"),
"port": int(os.getenv("MYSQL_PORT", 3306)),
"user": os.getenv("MYSQL_USER", "root"),
"password": os.getenv("MYSQL_PASSWORD", "123456"),
"database": os.getenv("MYSQL_DB", "office_data"),
"charset": "utf8mb4"
}
3. CSV配置
CSV_FILE = "/home/office_dashboard/部门配置.csv"
====================== 核心读取函数 ======================
def read_excel_data(date=None):
"""读取Excel销售数据(按日期筛选,无日期则读取全部)"""
try:
excel_files = [f for f in os.listdir(EXCEL_DIR) if any(f.endswith(suf) for suf in EXCEL_SUFFIX)]
if not excel_files:
return pd.DataFrame(), "未找到Excel数据文件"
# 按日期筛选文件(假设文件名格式:20260119_销售报表.xlsx)
if date:
target_file = next((f for f in excel_files if date in f), None)
if not target_file:
return pd.DataFrame(), f"未找到{date}的Excel数据"
file_path = os.path.join(EXCEL_DIR, target_file)
df = pd.read_excel(file_path)
else:
# 读取所有Excel文件并合并
df_list = []
for f in excel_files:
file_path = os.path.join(EXCEL_DIR, f)
df_list.append(pd.read_excel(file_path))
df = pd.concat(df_list, ignore_index=True)
# 数据标准化(统一列名、格式)
df.columns = ["date", "name", "dept", "sales", "order_count", "qualified"]
df["date"] = pd.to_datetime(df["date"]).dt.strftime("%Y-%m-%d")
return df, "Excel数据读取成功"
except Exception as e:
return pd.DataFrame(), f"Excel数据读取失败:{str(e)}"
def read_mysql_data(table_name="customer"):
"""读取MySQL数据库数据(默认读取客户表)"""
try:
连接MySQL数据库
conn = pymysql.connect(**MYSQL_CONFIG)
sql = f"SELECT * FROM {table_name};"
df = pd.read_sql(sql, conn)
conn.close()
# 数据标准化(关联销售数据的客户ID列)
df.columns = ["customer_id", "customer_name", "contact", "dept", "create_time"]
df["create_time"] = pd.to_datetime(df["create_time"]).dt.strftime("%Y-%m-%d")
return df, "MySQL数据读取成功"
except Exception as e:
return pd.DataFrame(), f"MySQL数据读取失败:{str(e)}"
def read_csv_data():
"""读取CSV部门配置数据"""
try:
if not os.path.exists(CSV_FILE):
return pd.DataFrame(), "未找到CSV部门配置文件"
df = pd.read_csv(CSV_FILE, encoding="utf-8")
# 数据标准化
df.columns = ["dept", "manager", "dept_code"]
return df, "CSV数据读取成功"
except Exception as e:
return pd.DataFrame(), f"CSV数据读取失败:{str(e)}"
def get_combined_data(date=None):
"""多数据源数据融合(销售数据+客户数据+部门配置)"""
try:
读取各数据源
excel_df, excel_msg = read_excel_data(date)
mysql_df, mysql_msg = read_mysql_data()
csv_df, csv_msg = read_csv_data()
# 数据融合(按部门关联)
combined_df = excel_df.merge(csv_df, on="dept", how="left") # 销售数据关联部门配置
combined_df = combined_df.merge(mysql_df[["customer_name", "dept"]], on="dept", how="left") # 关联客户数据
# 处理缺失值
combined_df.fillna({"manager": "未分配", "customer_name": "未知客户"}, inplace=True)
return combined_df, "数据融合成功"
except Exception as e:
return pd.DataFrame(), f"数据融合失败:{str(e)}"
测试数据源读取功能
if name == "main ":
combined_df, msg = get_combined_data(date="2026-01-19")
print(msg)
print(combined_df.head())
- 第二步:创建.env文件,安全存储数据库信息
进入项目目录
cd /home/office_dashboard
创建并编辑.env文件
vim .env
.env 文件(敏感信息配置)
MYSQL_HOST=47.108.xxx.xxx # 数据库地址(本地为localhost)
MYSQL_PORT=3306 # 数据库端口(默认3306)
MYSQL_USER=office_user # 数据库账号
MYSQL_PASSWORD=xxxxxxxx # 数据库密码
MYSQL_DB=office_data # 数据库名
chmod 600 .env # 仅当前用户可读写
- 第三步:集成ECharts,实现交互式可视化
(1)引入ECharts CDN,添加图表容器
{% block content %}
图表配置
折线图(销售额趋势) 柱状图(部门销售额对比) 饼图(部门销售额占比) 按日期维度 按部门维度 按人员维度 刷新图表
达标率分布
部门负责人业绩关联
{% endblock %}
(2)编写ECharts初始化与交互脚本
{% block script %}
{% endblock %}
- 第四步:修改后端路由,传递融合数据并管控权限
在app.py中修改dashboard路由
from datasource import get_combined_data
import json
@app.route("/")
@login_required
def dashboard():
selected_date = request.args.get("date", TODAY)
available_dates = get_available_dates()
# 1. 获取多数据源融合数据
combined_df, combine_msg = get_combined_data(date=selected_date)
if combined_df.empty:
flash(f"数据加载失败:{combine_msg}", "error")
combined_data = []
else:
# 2. 基于用户角色过滤数据(权限管控)
if current_user.role == "leader":
# 管理员可查看全部数据
filtered_df = combined_df
elif current_user.role == "dept":
# 部门负责人仅查看本部门数据
filtered_df = combined_df[combined_df["dept"] == current_user.dept]
else:
# 普通员工仅查看个人数据
filtered_df = combined_df[combined_df["name"] == current_user.name]
# 3. 转换为JSON格式,传递给前端
combined_data = filtered_df.to_dict("records")
# 4. 原有数据汇总、图表路径逻辑保留
summary, detail_data = get_summary_data(filtered_df) # 基于过滤后的数据生成汇总
chart_path = get_chart_path(selected_date) # 保留原有静态图表路径(备用)
return render_template(
"dashboard.html",
summary=summary,
detail_data=detail_data,
combined_data=combined_data, # 传递融合数据给前端ECharts
chart_path=chart_path,
available_dates=available_dates,
selected_date=selected_date,
current_user=current_user
)
新增:数据导出接口(支持多格式、自定义字段)
@app.route("/export/data", methods=["POST"])
@login_required
def export_data():
data = request.get_json()
export_format = data.get("format", "excel") # excel/csv
fields = data.get("fields", ["date", "name", "dept", "sales"]) # 自定义导出字段
# 获取融合数据并过滤
selected_date = data.get("date", TODAY)
combined_df, _ = get_combined_data(date=selected_date)
if current_user.role != "leader":
combined_df = combined_df[combined_df["dept"] == current_user.dept]
# 筛选导出字段
export_df = combined_df[fields]
# 生成导出文件
filename = f"办公数据_{selected_date}.{export_format}"
if export_format == "excel":
response = make_response(export_df.to_excel(index=False, engine="openpyxl"))
response.headers["Content-Disposition"] = f"attachment; filename={filename}"
response.headers["Content-Type"] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
else:
response = make_response(export_df.to_csv(index=False, encoding="utf-8-sig"))
response.headers["Content-Disposition"] = f"attachment; filename={filename}"
response.headers["Content-Type"] = "text/csv"
return response
- 第五步:测试验证功能
重启Gunicorn和Nginx
kill -9 (ps aux \| grep gunicorn \| grep -v grep \| awk '{print 2}')
nohup gunicorn -w 4 -b 0.0.0.0:5000 app:app &
systemctl restart nginx
-
多数据源读取:访问看板,验证是否加载Excel销售数据、MySQL客户数据、CSV部门配置数据,数据融合正常;
-
图表交互:切换图表类型(折线/柱状/饼图)、数据维度(日期/部门/人员),图表是否实时刷新,支持缩放、鼠标悬浮查看详情;
-
多图表联动:点击主图表某一数据项,验证是否触发详细数据筛选(可结合前端表格插件完善);
-
权限管控:用不同角色账号登录,验证是否仅能查看对应范围的数据,导出功能也受权限限制;
-
数据导出:测试导出功能,验证是否能自定义字段,导出Excel/CSV格式文件正常。
五、新手避坑小贴士
-
MySQL连接失败:优先检查3点------① .env文件中数据库参数是否正确;② 数据库是否允许外网访问(云数据库需配置安全组);③ 服务器是否安装MySQL客户端,网络能否ping通数据库地址;
-
数据格式不统一:确保各数据源的关联字段(如"dept")格式一致(大小写、名称统一),可在read_*函数中添加格式校验;
-
ECharts图表不显示:检查CDN是否引入成功,图表容器是否设置宽高,后端传递的combined_data是否为JSON格式,控制台打印是否有报错;
-
中文乱码问题:CSV文件读取时指定encoding="utf-8",MySQL数据库charset设置为utf8mb4,导出CSV时用encoding="utf-8-sig";
-
数据量过大导致卡顿:在数据聚合时限制时间范围(按日期筛选),ECharts启用数据分页或抽样展示,避免一次性加载过多数据;
-
导出功能报错:确保导出字段在融合数据中存在,Excel导出需安装openpyxl引擎,避免字段名包含特殊字符。
六、进阶扩展(新手可选)
-
实时数据更新:集成WebSocket,实现多数据源数据实时推送,图表自动刷新,无需手动刷新页面;
-
更多图表类型支持:扩展ECharts配置,添加雷达图(多维度对比)、散点图(数据分布)、热力图(关联分析);
-
数据脱敏功能:对导出和展示的数据进行脱敏(如隐藏客户联系方式、员工手机号),符合数据合规要求;
-
自定义报表模板:支持用户保存常用图表配置和导出字段,生成个性化报表模板,一键加载;
-
大数据量优化:引入Redis缓存热点数据,使用Pandas分块读取大文件,ECharts开启增量渲染,提升页面加载速度。
七、总结与系列数据能力闭环
-
AI增强分析:结合之前的OpenAI集成,让ECharts图表支持自然语言生成(如"生成近7天各部门销售额对比柱状图");
-
数据中台对接:集成企业数据中台API,实现更广泛的数据源接入(ERP、CRM、OA系统);
-
报表自动化分发:按预设规则定时生成可视化报表,自动推送至企业微信/邮箱,无需手动操作。
如果这篇文章对你有帮助,欢迎点赞收藏+关注!如果在多数据源配置、ECharts图表调试、数据导出时遇到问题,随时在评论区留言,我会逐一解答~ 新手不用怕多数据源整合和可视化开发,跟着步骤一步步测试,就能让你的办公看板具备专业数据分析能力,用数据赋能团队高效工作!