效果展示
1.动态实时更新数据效果图
2. 拖放后自动保存页面布局
3.鼠标右键切换主题
代码中预置了12个主题风格,实际开发中可根据实际情况二次增加。
一. 确定需求方案
1. 屏幕分辨率
这个案例的分辨率是16:9,最常用的的宽屏比。
根据电脑分辨率屏幕自适应显示,F11全屏查看;
2. 部署方式
B/S方式:支持Windows、Linux、Mac等各种主流操作系统;支持主流浏览器Chrome,Microsoft Edge,360等;服务器采用python语言编写,配置好python环境即可。
二. 整体架构设计
- 前端Echarts开源库:使用 WebStorm 编辑器;
- 后端 http服务器:基于 Python 实现,使用 Pycharm 或 VSCode 编辑器;
- 数据传输格式:JSON;
- 数据源类型:JSON文件。实际开发需求中,支持定制HTTP API接口方式或其它各种类型数据库,如PostgreSQL、MySQL、Oracle、Microsoft SQL Server、SQLite、Excel表格等。
- 数据更新方式:采用http get 轮询方式 。在实际应用中,也可以视情况选择j监测后端数据实时更新,实时推送到前端的方式;
三.编码实现 (基于篇幅及可读性考虑,此处展示部分关键代码)
1. 前端html代码
使用bootstrap container-fluid, row, col等实现。
<div id="vue_app" class="container-fluid">
<!-- 外框 在row这里设置样式-->
<div class="row" style="height: 100%;">
<!-- 左侧 -->
<div class="col-3">
<!-- 左侧第1行 -->
<div class="row" id="layout_l1" ondrop="drop(event)" ondragover="allowDrop(event)">
<div class="row" id="container_l1" draggable="true" ondragstart="drag(event)">
<div class="col-6" id="container_l1_1"></div>
<div class="col-6" id="container_l1_2"></div>
</div>
</div>
<!-- 左侧第2行 -->
<div class="row" id="layout_l2" ondrop="drop(event)" ondragover="allowDrop(event)">
<div class="row" id="container_l2" draggable="true" ondragstart="drag(event)">
</div>
</div>
<!-- 左侧第3行 -->
<div class="row" id="layout_l3" ondrop="drop(event)" ondragover="allowDrop(event)">
<div class="row" id="container_l3" draggable="true" ondragstart="drag(event)">
</div>
</div>
</div>
<!-- 中间 -->
<div class="col-6">
<div style="background-color:rgb(21,62,119);">
<!-- 中间第一行 -->
<div class="row" id="layout_m1" ondrop="drop(event)" ondragover="allowDrop(event)">
<div class="row" id="container_m1" draggable="true" ondragstart="drag(event)">
</div>
</div>
<!-- 中间第二行 -->
<div class="row" id="layout_m2" ondrop="drop(event)" ondragover="allowDrop(event)">
<div class="row" id="container_m2" draggable="true" ondragstart="drag(event)">
<div class="col-3" id="container_m2_1"></div>
<div class="col-3" id="container_m2_2"></div>
<div class="col-3" id="container_m2_3"></div>
<div class="col-3" id="container_m2_4"></div>
</div>
</div>
<!-- 中间第三行 -->
<div class="row" id="layout_m3" ondrop="drop(event)" ondragover="allowDrop(event)">
<div class="row" id="container_m3" draggable="true" ondragstart="drag(event)">
<div class="col-4" id="container_m3_1"></div>
<div class="col-4" id="container_m3_2"></div>
<div class="col-4" id="container_m3_3"></div>
</div>
</div>
</div>
</div>
<!-- 右侧 -->
<div class="col-3">
<!-- 右侧第一行 -->
<div class="row" id="layout_r1" ondrop="drop(event)" ondragover="allowDrop(event)">
<div class="row" id="container_r1" draggable="true" ondragstart="drag(event)">
<dv-scroll-board id="container_r1_1" :config="config" />
</div>
</div>
<!-- 右侧第二行 -->
<div class="row" id="layout_r2" ondrop="drop(event)" ondragover="allowDrop(event)">
<div class="row" id="container_r2" draggable="true" ondragstart="drag(event)">
</div>
</div>
<!-- 右侧第三行 -->
<div class="row" id="layout_r3" ondrop="drop(event)" ondragover="allowDrop(event)">
<div class="row" id="container_r3" draggable="true" ondragstart="drag(event)">
</div>
</div>
</div>
</div>
</div>
2. 拖放之ondragover
// 释放目标时触发的事件:
// ondragover - 当某被拖动的对象在另一对象容器范围内拖动时触发此事件
function allowDrop(ev) {
// 判断目标元素是否允许放入被拖动元素
if (ev.target.ondrop) {
ev.preventDefault();
}
}
3. 拖放之ondragstart
// 在拖动目标上触发事件(源元素);
// ondragstart 用户开始拖动元素时触发;
function drag(ev) {
ev.dataTransfer.setData("Text", ev.target.id);
}
4. 拖放之ondrop
// 释放目标时触发的事件:
// ondrop - 在一个拖动过程中,释放鼠标键时触发此事件
function drop(ev) {
ev.preventDefault();
var target = ev.target;
var target_child = target.firstChild;
var data = ev.dataTransfer.getData("Text");
var node = document.getElementById(data);
var src_parent = node.parentNode;
// 交换子节点
target.appendChild(node);
src_parent.appendChild(target_child);
echart_resize(target_child.id);
echart_resize(node.id);
save_layout(gen_layout());
}
5. 前端JS - 数据定时更新控制
支持在每个echarts图表中独立控制定时更新的间隔。
// 定时1s执行数据更新函数
setInterval(function () {
async_echart_bar_horizontal(
container,
path_bar_horizontal + "bar_horizontal.json"
);
}, 1000);
6.后端 flask 服务器
from flask import Flask
app = Flask(__name__, static_folder="static", template_folder="template")
# 主程序在这里
if __name__ == "__main__":
# 开启线程,触发动态数据
a = threading.Thread(target=asyncJson.loop)
a.start()
# 开启 flask 服务
app.run(host='0.0.0.0', port=88, debug=True)
四. 启动命令
<!-- 启动server命令 -->
python main.py
<!-- 浏览器中输入网址查看大屏(端口为 main.py 中的 port 参数定义) -->
http://localhost:88/static/index.html
<!-- 更多资料参考我的博客主页 -->
https://yydatav.blog.csdn.net/
<!-- 更多案例参考 -->
https://blog.csdn.net/lildkdkdkjf/article/details/120705616