Flask数据可视化大屏源码实战:多页面轮播与实时数据渲染 简介这份资源是一套基于Python与Flask框架搭建的轻量级数据可视化大屏展示系统面向需要快速落地企业数据监控与业务分析场景的开发者也适合作为前端工程化实战练手项目。系统支持多页面切换与实时数据渲染内置数据看板、空气质量监测、计算机性能指标等模块覆盖图表展示、环境数据监控与服务器性能观测等典型需求。压缩包共24个文件约1.02MB以Python后端脚本、JavaScript与HTML页面、CSS样式及PNG图片资源为主另含字体文件、说明文档与开源许可证目录结构清晰便于按模块阅读与二次开发。目前已有104人学习下载。读者可从中获得一套可直接运行的大屏系统源码理解Flask后端数据处理与前端动态渲染的协作方式并借助附赠的前端工程化资源降低定制门槛适合作为课程设计、毕业项目或企业内部监控原型的参考实现。1. 从一份 Flask 大屏源码说起它到底能替你省掉哪几天上周有个做运维的朋友找我说老板要一块“能挂在办公室电视上”的数据看板要求轮播三个页面业务数据、空气质量、服务器性能。他第一反应是上 Grafana结果发现数据源格式对不上、定制样式又得写插件折腾两天没出效果。我让他先看这份基于 Python 和 Flask 的轻量级数据可视化大屏源码包一个下午就跑起来了。这类前端工程化实战项目的价值不在于技术多新而在于它把“多页面轮播 实时数据渲染 大屏适配”这套组合拳提前打好了你拿到的是一个能直接改数据源就上墙的骨架而不是从零搭脚手架。适合谁会一点 Python、能看懂 HTML 模板、需要快速交付一块监控屏的从业者不适合想要复杂 BI 钻取分析的人。下面我按“它怎么组织 → 怎么跑起来 → 怎么接自己的数据 → 坑在哪”拆给你看。2. 拆开源码看骨架Flask 路由、模板继承与三个看板模块怎么咬合拿到一个压缩包别急着pip install先花十分钟看目录结构这一步能省掉后面一半的翻车。这份资源的组织方式很典型一个 Flask 应用入口、一个 templates 目录放 Jinja2 模板、一个 static 目录放 CSS/JS 和图表库、再加一个数据层可能是 JSON 文件或模拟数据脚本。理解它的关键不是逐个文件读而是搞清楚“页面切换”和“数据刷新”这两条链路各自走哪条路。2.1 目录结构与启动入口的对应关系常见做法是入口文件叫app.py或run.py里面用app.route注册几个页面路由每个路由render_template到对应的 HTML。大屏的“多页面切换”通常有两种实现一种是后端路由切换点导航跳 URL另一种是前端定时轮播一个页面里用 JS 定时切换 iframe 或 div。这份资源标题写的是“支持多页面切换”从轻量级定位判断大概率是后者——因为大屏挂在电视上没人点鼠标轮播才是刚需。你打开模板文件时重点看两处有没有setInterval之类的定时器以及页面容器是不是用iframe嵌了子页面。这决定了你后面改数据时是改一个文件还是改多个。先跑一条命令把结构摸清楚# 在解压后的项目根目录执行只看两层避免输出太长 find . -maxdepth 2 -type f | grep -v .git | sort这条命令列出所有文件路径你能快速判断模板在不在templates/、静态资源在不在static/、有没有requirements.txt、数据是.json还是.csv。如果发现模板直接堆在根目录说明作者没按 Flask 默认约定来那你启动时就得显式指定template_folder这是后面容易翻车的第一个点。2.2 三个看板模块的数据流差异标题里点了三个模块数据看板、空气质量监测、计算机性能指标。这三个的数据来源性质完全不同理解差异才能正确接自己的数据。数据看板通常是业务汇总数字订单量、销售额之类静态或低频更新即可空气质量监测是典型的时间序列需要按时间点渲染折线或柱状计算机性能指标CPU、内存、磁盘是实时性最强的往往几秒刷新一次。源码里如果三个模块共用一套刷新逻辑那实时性要求高的那个会被拖慢如果各自独立轮询那你要分别找到各自的接口。我一般会这样定位数据接口在模板里搜fetch(或axios或$.get看它请求哪个 URL再回到app.py找对应路由返回什么结构。这一步做完你就有了“数据契约”——字段名、时间格式、数值单位。后面替换成真实数据时只要保持契约不变前端一行不用改。这是这份资源最实用的地方它把契约用代码固定下来了你照着填就行。# 典型的 Flask 数据接口写法源码里大概率是类似结构 app.route(/api/air-quality) def air_quality(): # 真实场景替换为查数据库或调采集服务 data load_json(data/air_quality.json) return jsonify({ times: [d[time] for d in data], # 时间轴前端图表 x 轴 pm25: [d[pm25] for d in data], # 指标序列前端 y 轴 unit: μg/m³ # 单位避免前端硬编码 })这段代码的逻辑说明路由返回 JSONjsonify自动设置Content-Type: application/jsontimes和pm25两个数组长度必须一致否则 ECharts 这类库会渲染错位unit单独返回是为了让前端模板不用写死单位换监测项时只改后端。参数上要注意时间格式——如果前端用category轴字符串时间就行如果用time轴得是时间戳或YYYY-MM-DD HH:mm:ss格式不对图表直接空白这是血泪经验里最常见的一条。2.3 模板继承与静态资源的加载顺序Flask 的 Jinja2 模板继承{% extends %}{% block %}在大屏项目里几乎是标配因为三个页面共享同一套头部、导航和图表库引用。你打开base.html之类的文件会看到{% block content %}占位子模板只填内容区。这个设计的好处是换主题、换图表库只改一处坏处是如果你没注意到base.html里引了某个 CDN 的 JS而现场网络访问不了整个大屏白屏——这是部署时的高频翻车点。静态资源加载顺序也有讲究图表库ECharts 或 Chart.js必须在页面渲染脚本之前加载否则echarts is not defined。源码里如果用了defer或把脚本放/body前一般是安全的如果放在head里又没加defer而你的数据接口又慢可能出现图表容器已渲染但库还没就绪的竞态。排查方法很简单浏览器控制台看报错顺序先报库未定义就是加载顺序问题先报容器找不到就是 DOM 时序问题。3. 本地跑通到上墙环境、启动与实时刷新的参数怎么调骨架看明白了接下来是让它真正跑起来并适配你的屏幕。这一章的目标是从解压到浏览器看到轮播再到把刷新频率调到你需要的节奏。别小看“跑通”这一步Python 版本、依赖版本、端口占用、模板路径任何一个不对都能让你卡半小时。3.1 虚拟环境与依赖安装的最小步骤先确认 Python 版本。Flask 2.x 和 3.x 在部分 API 上有差异源码如果写于较早时期直接用最新 Python 可能报ImportError。我一般会先看requirements.txt里有没有钉版本号有就照着装没有就用一个中间版本比如 3.93.11稳妥些。# 创建并激活虚拟环境避免污染全局 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 安装依赖有 requirements.txt 就照装 pip install -r requirements.txt # 没有依赖清单时最小依赖通常就这两个 pip install flask flask-cors逻辑说明虚拟环境隔离是为了避免你机器上其他项目的 Flask 版本冲突flask-cors不是必须但如果你的数据接口和页面不同源比如前端单独起服务跨域会拦请求加上省事。参数上pip install不加版本号会装最新版如果启动报cannot import name url_quote之类多半是 Werkzeug 版本太新回退到Werkzeug2.2.3这类兼容版本即可。这一步的排查思路是报错信息里出现哪个包名就去钉哪个包的版本别盲目升级全部。3.2 启动参数与端口、调试模式的取舍启动命令看着简单但参数选错会影响你调试效率。开发阶段开debugTrue能热重载、能看到详细报错但上墙运行时必须关掉否则任何人访问都能触发调试器而且热重载会周期性重启进程大屏会闪。# 开发调试开 debug指定端口避免和本机其他服务冲突 flask --app app run --debug --port 5001 # 生产/上墙关 debug绑定 0.0.0.0 让局域网内电视能访问 flask --app app run --host 0.0.0.0 --port 5001逻辑说明--app app指定入口模块名如果你的入口文件叫run.py就改成--app run--host 0.0.0.0是关键默认只绑127.0.0.1电视或另一台机器访问会连接被拒这是“本地能开、电视打不开”的头号原因。参数上端口选 5001 而不是默认 5000是因为部分系统上 5000 被其他服务占用比如某些桌面环境的服务换端口能避开玄学冲突。如果启动后浏览器访问空白但终端无报错先看模板路径对不对再看静态资源 404——按 F12 的 Network 面板红色的一排就是缺的文件。3.3 轮播间隔与数据刷新频率的分离设置大屏的两个“频率”必须分开调页面轮播间隔多久换一个看板和数据刷新间隔多久拉一次新数据。这两个混在一起是新手常犯的错——把轮播设成 5 秒结果每个页面刚渲染完就被切走数据还没看清。合理做法是轮播 1530 秒数据刷新 310 秒实时性强的性能指标可以更快。// 页面轮播假设三个 iframe 或三个 section按索引切换 const pages document.querySelectorAll(.screen-page); let current 0; setInterval(() { pages[current].classList.remove(active); // 隐藏当前页 current (current 1) % pages.length; // 循环到下一页 pages[current].classList.add(active); // 显示下一页 }, 20000); // 20000ms 20 秒一轮播 // 数据刷新独立定时器只重拉当前页数据不打断轮播 setInterval(() { fetch(/api/performance) .then(r r.json()) .then(d updateCharts(d)); // 只更新图表不重建 DOM }, 5000); // 5 秒刷一次性能指标逻辑说明轮播用classList切换显隐比display:none更利于图表库计算容器尺寸有些库在display:none的容器里初始化会得到 0 宽高图表不显示数据刷新只调updateCharts更新setOption不重新init图表实例否则每次刷新都重建内存会涨、动画会闪。参数上20000和5000这两个数字按你的屏幕尺寸和观看距离调——远距离观看轮播可以更慢近距离操作可以更快。注意setInterval在标签页后台会被浏览器节流大屏一般前台常驻影响不大但如果用无头浏览器截图验证要留意这个行为。4. 换成自己的数据接口契约、字段映射与图表配置的三处改动跑通之后99% 的人下一步就是“把我的数据塞进去”。这一步的难点不在写代码而在保持契约。源码里的模拟数据字段名是作者定的你的真实数据字段名大概率不一样直接替换会导致图表空白或错位。我的做法是先列一张映射表再动代码改完一处验证一处。4.1 数据契约对照表与字段映射先把源码里每个接口的返回结构抄下来再对照你的数据源填一张表。这张表就是你的改造清单比在代码里到处搜字段靠谱得多。模块源码字段含义你的数据源字段类型/格式处理方式数据看板total汇总数值order_countint直接映射数据看板trend趋势数组daily_saleslist[float]长度对齐时间轴空气质量times时间轴collect_timestrHH:mm格式化后映射空气质量pm25PM2.5 值pm2_5float单位统一为 μg/m³性能指标cpuCPU 使用率cpu_percentfloat 0-100保留一位小数填表时重点看三列类型、格式、单位。类型不对字符串当数字图表会渲染成空白格式不对时间轴字符串格式和前端配置不匹配x 轴会乱序单位不统一一个用小数一个用百分比数值会差 100 倍。这张表填完改造就是机械劳动出错概率大幅下降。4.2 后端数据层替换从 JSON 到真实来源源码大概率用 JSON 文件模拟数据替换成真实来源时建议保留“读数据 → 组装契约 → 返回”这三段结构只换第一段。这样前端完全不用动出问题也容易定位是数据源的问题还是渲染的问题。import sqlite3 from flask import jsonify def get_performance(): # 第一段换数据源这里用 SQLite 举例实际可能是采集接口 conn sqlite3.connect(monitor.db) rows conn.execute( SELECT ts, cpu, mem FROM metrics ORDER BY ts DESC LIMIT 60 ).fetchall() conn.close() # 第二段组装成前端认识的契约字段名和顺序保持和源码一致 rows.reverse() # 时间正序图表从左到右 return { times: [r[0][-8:] for r in rows], # 只取 HH:mm:ss cpu: [round(r[1], 1) for r in rows], mem: [round(r[2], 1) for r in rows] } app.route(/api/performance) def performance(): return jsonify(get_performance()) # 第三段统一出口逻辑说明ORDER BY ts DESC LIMIT 60取最近 60 条再reverse是为了让图表显示“最近一小时”而不是“最早一小时”这个顺序坑很多人踩过r[0][-8:]截取时间字符串末 8 位得到HH:mm:ss前提是你的ts存的是标准格式如果存的是时间戳就得先转换。参数上LIMIT 60对应图表 x 轴点数太多会挤成一团60 个点在一屏宽度上刚好round(..., 1)保留一位小数避免浮点尾数让 tooltip 显示一长串。注意数据库连接用完必须closeFlask 开发服务器单线程时问题不大但并发上来连接不释放会耗尽。4.3 前端图表配置的适配点后端契约对齐后前端一般只需改三处图表容器的尺寸、坐标轴的类型、系列的配色。大屏适配的核心是“相对单位”容器宽高用百分比或vw/vh图表库resize监听窗口变化。如果源码里写死了width: 800px换到 1920 或 4K 屏上就会留白或溢出。// 图表初始化后监听容器尺寸变化大屏换分辨率不重开页面 const chart echarts.init(document.getElementById(cpu-chart)); window.addEventListener(resize, () chart.resize()); // 坐标轴类型要和后端时间格式匹配 const option { xAxis: { type: category, data: res.times }, // 字符串时间用 category yAxis: { type: value, max: 100, min: 0 }, // 百分比固定量程避免跳变 series: [{ type: line, data: res.cpu, smooth: true }] }; chart.setOption(option);逻辑说明chart.resize()必须绑在resize事件上否则浏览器窗口变化后图表还是旧尺寸这是大屏部署到不同电视上最常见的显示问题yAxis固定max:100 min:0是为了让 CPU 使用率的波动在视觉上稳定如果让库自动算量程数值在 2030 之间波动时会被放大成剧烈起伏看着吓人但不真实。参数上smooth: true让折线平滑适合趋势展示如果是精确读数场景比如告警阈值改成false更诚实。注意category轴的数据长度必须和series.data一致少一个点就会错位。5. 避坑与排查五个让大屏白屏或数据错位的真实原因这一章是我踩过的坑里挑出来最费时间的五个每个都按“现象 → 原因 → 解决”写。你照着对一遍能省掉至少一个下午。5.1 现象本地打开正常电视或另一台机器访问白屏原因Flask 默认只绑127.0.0.1局域网其他设备根本连不上或者模板里引用了localhost的接口地址电视上localhost指向电视自己。解决启动加--host 0.0.0.0把前端请求地址改成相对路径/api/xxx而不是写死http://localhost:5001/api/xxx。改完用手机浏览器访问http://你的电脑IP:5001验证能开再上电视。5.2 现象图表区域一片空白控制台报echarts is not defined原因图表库通过 CDN 引入现场网络访问不了那个 CDN或者脚本加载顺序在渲染脚本之后。解决把图表库下载到static/js/本地引用彻底摆脱外网依赖检查base.html里库的script是否在页面脚本之前。排查时看 Network 面板那个 JS 请求是不是红色失败是就换本地文件。5.3 现象数据在变但图表不动原因定时器在拉数据但更新时重新init了图表实例旧实例没销毁新实例叠在上面或者setOption没加notMerge参数新旧配置合并导致系列错乱。解决图表实例只init一次刷新时只调setOption(newData, true)第二个参数true表示不合并、整体替换。另外确认fetch的.then链里没有吞掉异常接口 500 时静默失败看起来就像“没更新”。5.4 现象时间轴顺序错乱最新的点跑到最左边原因后端查询用了ORDER BY ts DESC但没反转或者前端把时间当字符串排序9:00排在10:00后面。解决后端取完数据reverse()成正序前端如果必须字符串排序补零成09:00格式或者干脆用时间戳当 x 轴值、type: time。这个坑在空气质量模块尤其常见因为它的时间粒度细。5.5 现象跑几个小时后浏览器内存暴涨、页面卡死原因setInterval里每次都新建图表实例或 DOM 节点旧的不回收或者轮播切换时没暂停隐藏页的定时器三个页面各跑一套刷新请求量翻三倍。解决图表实例提到全局只建一次轮播切换时对非当前页clearInterval切回来再重建或者用visibility判断跳过刷新。上墙前挂一晚上观察内存曲线涨得厉害就按这个思路查。6. 进阶把轮播做成可配置并用无头浏览器做上墙前验证最后说一个我常用的收尾技巧把轮播间隔、页面顺序、每个看板的刷新频率抽到一个配置文件里而不是散落在 JS 各处。这样换场景比如从办公室演示换成车间大屏只改配置不改代码也方便交接给别人。常见做法是后端读一个config.json通过模板变量注入前端或者前端直接fetch(/api/config)拿。{ rotate_seconds: 20, pages: [ { id: dashboard, refresh_seconds: 30 }, { id: air, refresh_seconds: 10 }, { id: performance, refresh_seconds: 5 } ] }这份配置的读法是rotate_seconds控制轮播节奏pages数组的顺序就是轮播顺序每个页面的refresh_seconds独立。前端初始化时按这个数组生成定时器页面隐藏时暂停对应定时器。参数上性能指标 5 秒、空气质量 10 秒、业务看板 30 秒是按“数据变化速度”排的你可以按自己的采集频率调但别让刷新间隔小于采集间隔否则拉到的还是旧数据白白增加请求。验证环节我一般用无头浏览器截几张图确认三个页面都能渲染、图表不是空白再上墙。命令不复杂关键是等页面加载完再截# 用无头浏览器截当前页面等待 3 秒让图表渲染完 chromium --headless --disable-gpu --screenshotcheck.png \ --window-size1920,1080 --virtual-time-budget3000 \ http://127.0.0.1:5001/逻辑说明--virtual-time-budget3000让浏览器“虚拟等待”3 秒再截图给fetch和图表渲染留时间--window-size设成目标大屏分辨率能提前发现布局溢出。截出来的图如果图表区是空白回到第 5 章对排查项如果布局错位就是第 4.3 节的尺寸适配没做好。这个习惯帮我拦下过好几次“本地看着好、上墙就翻车”的情况。从那以后我每次交付大屏类项目都强制走一遍“配置外置 无头截图 挂机观察内存”这三步哪怕时间再紧也不省。希望帮到你。本文还有配套的精品资源点击获取