feat: 大屏效果初步完成

This commit is contained in:
caoqianming 2023-08-16 13:56:12 +08:00
parent 2d6ad430a4
commit 4f4a0c85a9
4 changed files with 566 additions and 6 deletions

View File

@ -12,7 +12,7 @@ VUE_APP_TITLE = '托克逊能源管理平台'
#VUE_APP_API_BASEURL = http://10.99.5.79:20309/api #VUE_APP_API_BASEURL = http://10.99.5.79:20309/api
VUE_APP_API_BASEURL = http://49.232.14.174:2226/api VUE_APP_API_BASEURL = http://49.232.14.174:2226/api
# VUE_APP_API_BASEURL = http://127.0.0.1:2226/api # VUE_APP_API_BASEURL = http://127.0.0.1:2226/api
#VUE_APP_BASEURL = http://127.0.0.1:8000 VUE_APP_BASEURL = http://49.232.14.174:2226
# 本地端口 # 本地端口

View File

@ -11,6 +11,10 @@
"@element-plus/icons-vue": "2.0.10", "@element-plus/icons-vue": "2.0.10",
"@tinymce/tinymce-vue": "5.0.0", "@tinymce/tinymce-vue": "5.0.0",
"axios": "1.3.4", "axios": "1.3.4",
"babylon": "^6.18.0",
"babylonjs": "^6.16.0",
"babylonjs-gui": "^6.16.0",
"babylonjs-loaders": "^6.16.0",
"codemirror": "5.65.5", "codemirror": "5.65.5",
"core-js": "3.29.0", "core-js": "3.29.0",
"cropperjs": "1.5.13", "cropperjs": "1.5.13",
@ -29,6 +33,7 @@
"print-js": "^1.6.0", "print-js": "^1.6.0",
"qrcodejs2": "0.0.2", "qrcodejs2": "0.0.2",
"sortablejs": "1.15.0", "sortablejs": "1.15.0",
"three": "^0.155.0",
"tinymce": "6.3.2", "tinymce": "6.3.2",
"vue": "3.2.47", "vue": "3.2.47",
"vue-i18n": "9.2.2", "vue-i18n": "9.2.2",

BIN
public/img/header_bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 KiB

View File

@ -1,17 +1,572 @@
<template> <template>
<div class="dashboard"> <div class="dashboard">
<header>
<h1 class="title">托克逊建材厂能管系统</h1>
</header>
<div class="left_main">
<div class="panel">
<div class="panel_title">全厂主要数据</div>
<el-row :gutter="16" style="height: 34px;">
<el-col :span="12" class="panel_item">
<span class="panel_label">用电量</span>
<span class="panel_value">1000</span>
<span class="panel_unit">KWH</span>
</el-col>
<el-col :span="12" class="panel_item">
<span class="panel_label">用电量</span>
<span class="panel_value">1000</span>
<span class="panel_unit">KWH</span>
</el-col>
</el-row>
<el-row :gutter="16" style="height: 34px;">
<el-col :span="12" class="panel_item">
<span class="panel_label">用电量</span>
<span class="panel_value">1000</span>
<span class="panel_unit">KWH</span>
</el-col>
<el-col :span="12" class="panel_item">
<span class="panel_label">用电量</span>
<span class="panel_value">1000</span>
<span class="panel_unit">KWH</span>
</el-col>
</el-row>
<el-row :gutter="16" style="height: 34px;">
<el-col :span="12" class="panel_item">
<span class="panel_label">用电量</span>
<span class="panel_value">1000</span>
<span class="panel_unit">KWH</span>
</el-col>
<el-col :span="12" class="panel_item">
<span class="panel_label">用电量</span>
<span class="panel_value">1000</span>
<span class="panel_unit">KWH</span>
</el-col>
</el-row>
</div>
</div> </div>
<div class="model">
<div id="loadingScreen">
工厂模型加载中.....{{loadedPercent}}%
</div>
<canvas id="renderCanvas" ></canvas>
</div>
<div class="right_main">
<div class="panel">
<div class="panel_title">工段主要数据</div>
<el-row :gutter="16" style="height: 34px;">
<el-col :span="12" class="panel_item">
<span class="panel_label">用电量</span>
<span class="panel_value">1000</span>
<span class="panel_unit">KWH</span>
</el-col>
<el-col :span="12" class="panel_item">
<span class="panel_label">用电量</span>
<span class="panel_value">1000</span>
<span class="panel_unit">KWH</span>
</el-col>
</el-row>
<el-row :gutter="16" style="height: 34px;">
<el-col :span="12" class="panel_item">
<span class="panel_label">用电量</span>
<span class="panel_value">1000</span>
<span class="panel_unit">KWH</span>
</el-col>
<el-col :span="12" class="panel_item">
<span class="panel_label">用电量</span>
<span class="panel_value">1000</span>
<span class="panel_unit">KWH</span>
</el-col>
</el-row>
<el-row :gutter="16" style="height: 34px;">
<el-col :span="12" class="panel_item">
<span class="panel_label">用电量</span>
<span class="panel_value">1000</span>
<span class="panel_unit">KWH</span>
</el-col>
<el-col :span="12" class="panel_item">
<span class="panel_label">用电量</span>
<span class="panel_value">1000</span>
<span class="panel_unit">KWH</span>
</el-col>
</el-row>
</div>
</div>
<div class="left_other">
<div class="panel">
<div class="panel_title">图表1</div>
<div class="chart" id="chart1"></div>
</div>
<div class="panel">
<div class="panel_title">图表2</div>
<div class="chart" id="chart2"></div>
</div>
<div class="panel">
<div class="panel_title">图表3</div>
<div class="chart" id="chart3"></div>
</div>
</div>
<div class="right_other">
<div class="panel">
<div class="panel_title">图表4</div>
<div class="chart" id="chart4"></div>
</div>
<div class="panel">
<div class="panel_title">图表5</div>
<div class="chart" id="chart5"></div>
</div>
<div class="panel">
<div class="panel_title">图表6</div>
<div class="chart" id="chart6"></div>
</div>
</div>
</div>
</template> </template>
<script> <script>
import * as echarts from "echarts";
import * as BABYLON from "babylonjs"
import * as BABYLON_GUI from "babylonjs-gui"
import 'babylonjs-loaders';
export default {
data() {
return {
initialAlpha: -Math.PI / 0.89,
initialBeta: Math.PI / 3.2,
initialRadius: 22,
initialTarget: null,
scene: null,
is_mainviewpoint: false,
resizeTimeout: null,
engine: null,
loadedPercent: 0,
chart1: null,
chart2: null,
chart3: null,
chart4: null,
chart5: null,
chart6: null,
chart1Option: {},
chart2Option: {},
chart3Option: {},
chart4Option: {},
chart5Option: {},
chart6Option: {},
}
},
mounted() {
var that = this;
this.initDomStyle();
this.$nextTick(() => {
this.initChart('chart1');
this.initChart('chart2');
this.initChart('chart3');
this.initChart('chart4');
this.initChart('chart5');
this.initChart('chart6');
this.addListener();
setTimeout(function () {
that.initFactory();
}, 1000);
});
},
methods: {
addListener() {
var that = this;
window.addEventListener('resize', function () {
// resizeTimeout
if (this.resizeTimeout) {
clearTimeout(this.resizeTimeout);
}
// resizeTimeout
this.resizeTimeout = setTimeout(function () {
that.initDomStyle()
}, 300); // 300
});
},
initDomStyle() {
//
var windowHeight = window.innerHeight;
var windowWidth = window.innerWidth;
var chartsHeight = window.innerWidth*1.8;
//
var left_main = document.getElementsByClassName('left_main')[0];
var left_other = document.getElementsByClassName('left_other')[0];
var right_main = document.getElementsByClassName('right_main')[0];
var right_other = document.getElementsByClassName('right_other')[0];
var model = document.getElementsByClassName('model')[0];
if (windowWidth > 960) {
//
left_main.style.position = 'absolute';
left_main.style.width = '20%';
right_main.style.position = 'absolute';
right_main.style.width = '20%';
left_other.style.position = 'absolute';
left_other.style.width = '20%';
left_other.style.height = (windowHeight - 220) + 'px';;
right_other.style.position = 'absolute';
right_other.style.width = '20%';
right_other.style.height = (windowHeight - 220) + 'px';;
model.style.height = (windowHeight - 60) + 'px';
}
else {
left_main.style.position = 'static';
left_main.style.width = '100%';
right_main.style.position = 'static';
right_main.style.width = '100%';
left_other.style.position = 'static';
left_other.style.width = '100%';
left_other.style.height = chartsHeight + 'px';
right_other.style.position = 'static';
right_other.style.width = '100%';
right_other.style.height = chartsHeight + 'px';
model.style.height = windowWidth*0.6;;
}
if(this.engine != null){
this.engine.resize();
}
this.resizeChart('chart1');
this.resizeChart('chart2');
this.resizeChart('chart3');
this.resizeChart('chart4');
this.resizeChart('chart5');
this.resizeChart('chart6');
},
resizeChart(name){
// name resize chart
var myChart = echarts.getInstanceByDom(document.getElementById(name));
if(myChart!=undefined){
console.log(name+' :resize')
myChart.resize();
}
},
initChart(name, option=null) {
// name , optionoption
var myChart = echarts.getInstanceByDom(document.getElementById(name));
if(myChart==undefined){
myChart = echarts.init(document.getElementById(name), 'dark');
}
if (option==null){
option = {
backgroundColor: '',
tooltip: {},
legend: {
data: ['销量']
},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
},
yAxis: {},
series: [
{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}
],
grid: { //
top: "10%",
left: "12%",
right: "0px",
bottom: "20%"
}
};
}
myChart.setOption(option);
},
initFactory() {
var that = this;
const canvas = document.getElementById("renderCanvas"); // Get the canvas element
const engine = new BABYLON.Engine(canvas, true); // Generate the BABYLON 3D engine
BABYLON.DefaultLoadingScreen.prototype.displayLoadingUI = function () {
}
BABYLON.DefaultLoadingScreen.prototype.hideLoadingUI = function(){
document.getElementById("loadingScreen").style.display = "none";
}
engine.displayLoadingUI();
// Add your code here matching the playground format
const createScene = function () {
const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.ArcRotateCamera("camera", that.initialAlpha, that.initialBeta, that.initialRadius, new BABYLON.Vector3(0, 0, 0));
that.initialTarget = camera.getTarget();
camera.upperBetaLimit = Math.PI / 2.2; //
camera.attachControl(canvas, true);
//
camera.lowerRadiusLimit = 6;
camera.upperRadiusLimit = 26;
//
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0));
light.intensity = 1.8;
// GUI
const advancedTexture = BABYLON_GUI.AdvancedDynamicTexture.CreateFullscreenUI("myUI");
var name_panel = new BABYLON_GUI.StackPanel();
name_panel.isVertical = false
name_panel.top = '-30%';
name_panel.left = '-20%';
advancedTexture.addControl(name_panel);
var name_rect = new BABYLON_GUI.Rectangle();
name_rect.width = "150px";
name_rect.height = "40px";
name_rect.cornerRadius = 10;
name_rect.color = "white";
name_rect.thickness = 4;
name_rect.background = "gray";
name_panel.addControl(name_rect);
var name_text = new BABYLON_GUI.TextBlock();
name_text.text = "托克逊建材厂";
name_text.color = "white"
name_rect.addControl(name_text);
var button_main = BABYLON_GUI.Button.CreateSimpleButton("button_main", "主视角");
button_main.width = "100px"
button_main.height = "40px";
button_main.color = "white";
button_main.cornerRadius = 20;
button_main.background = "green";
name_panel.addControl(button_main)
button_main.onPointerClickObservable.add(() => {
if (camera.alpha != that.initialAlpha || camera.beta != that.initialBeta || camera.radius != that.initialRadius) {
name_rect.text = '托克逊建材厂';
var cameraPosition = new BABYLON.Vector3(
0 + that.initialRadius * Math.sin(that.initialBeta) * Math.cos(that.initialAlpha),
0 + that.initialRadius * Math.cos(that.initialBeta),
0 + that.initialRadius * Math.sin(that.initialBeta) * Math.sin(that.initialAlpha)
);
var ease = new BABYLON.CubicEase();
ease.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT);
BABYLON.Animation.CreateAndStartAnimation('at6', camera, 'position', 45, 200, camera.position, cameraPosition, 0, ease);
BABYLON.Animation.CreateAndStartAnimation('at61', camera, 'target', 45, 200, camera.target, that.initialTarget, 0, ease);
}
})
var remoteGlbUrl = process.env.VUE_APP_BASEURL + "/media/model/factory.glb";
BABYLON.SceneLoader.Append(remoteGlbUrl, "", scene, function (scene) {
scene.meshes.forEach(function (mesh) {
if (mesh.name.indexOf('.') != -1) {
mesh.actionManager = new BABYLON.ActionManager(scene);
mesh.actionManager.registerAction(
new BABYLON.ExecuteCodeAction(
BABYLON.ActionManager.OnPickTrigger,
function (evt) {
name_text.text = mesh.name;
}
)
);
}
if (mesh.name == '柱体.023') {
const rect1 = new BABYLON_GUI.Rectangle();
rect1.width = 0.06;
rect1.height = "40px";
rect1.cornerRadius = 4;
rect1.color = "Orange";
rect1.thickness = 2;
rect1.background = "green";
advancedTexture.addControl(rect1);
var label = new BABYLON_GUI.TextBlock();
label.text = "水泥磨";
label.color = 'white'
rect1.addControl(label);
rect1.linkWithMesh(mesh);
rect1.linkOffsetY = -50;
//
// StackPanel
const data_view = new BABYLON_GUI.StackPanel('data_view');
data_view.width = '100px'; // StackPanel
data_view.bottom = rect1.bottom + 50 + 'px';
data_view.background = 'darkblue'
data_view.cornerRadius = 4;
//
const textLines = ["电耗: 123", "产量: 123"];
for (let i = 0; i < textLines.length; i++) {
let textLine = textLines[i];
const textA = new BABYLON_GUI.TextBlock('textA');
textA.height = "20px"
textA.color = "white"
textA.text = textLine;
// text.fontSize = textLines[i].fontSize;
data_view.addControl(textA);
}
// StackPanelGUI
advancedTexture.addControl(data_view);
data_view.linkWithMesh(mesh);
data_view.linkOffsetY = -100;
rect1.onPointerDownObservable.add(() => {
//
var cameraPosition = new BABYLON.Vector3(
mesh.position.x + 9 * Math.sin(camera.beta) * Math.cos(Math.PI),
mesh.position.y + 9 * Math.cos(camera.beta),
mesh.position.z + 9 * Math.sin(camera.beta) * Math.sin(Math.PI)
);
var ease = new BABYLON.CubicEase();
ease.setEasingMode(BABYLON.EasingFunction.EASINGMODE_EASEINOUT);
BABYLON.Animation.CreateAndStartAnimation('at5', camera, 'position', 45, 200, camera.position, cameraPosition, 0, ease);
BABYLON.Animation.CreateAndStartAnimation('at51', camera, 'target', 45, 200, camera.target, mesh.position, 0, ease);
});
}
});
// mesh = scene.getMeshByName(".023") //
engine.hideLoadingUI()
}, function(evt){
var loadedPercent = 0;
if (evt.lengthComputable) {
loadedPercent = (evt.loaded * 100 / evt.total).toFixed();
} else {
var dlCount = evt.loaded / (1024 * 1024);
loadedPercent = Math.floor(dlCount * 100.0) / 100.0;
}
that.loadedPercent = loadedPercent;
})
return scene;
};
const scene = createScene(); //Call the createScene function
// Register a render loop to repeatedly render the scene
engine.runRenderLoop(function () {
scene.render();
});
this.engine = engine;
// Watch for browser/canvas resize events
window.addEventListener("resize", function () {
engine.resize();
});
}
}
}
</script> </script>
<style scoped> <style scoped>
.dashboard { .dashboard {
background-color: black;
/* background-color: #0b2e4a; */
font-family: Inter, "-apple-system", BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "noto sans", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
header {
height: 60px;
/* 调整头部高度 */
background-image: url('/public/img/header_bg.png');
/* 替换为实际的背景图片路径 */
background-size: cover;
background-position: center;
display: flex; display: flex;
flex-direction: column; justify-content: center;
justify-content: space-between;
align-items: center; align-items: center;
height: 100vh; }
background-color: #f0f0f0;
.title {
text-align: center;
color: white;
font-size: 24px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
}
.model {
width: 100%;
}
#renderCanvas {
width: 100%;
height: 100%
}
#loadingScreen {
position: absolute;
width: 100%;
height: 100%;
color: white;
display:flex;
align-items:center;
justify-content:center;
font-size: 30px;
}
.left_main,
.right_main {
position: absolute;
top: 60px;
width: 20%;
}
.right_main {
right: 0;
}
.left_other,
.right_other {
position: absolute;
top: 220px;
display: flex;
width: 20%;
flex-direction: column;
}
.right_other {
right: 0
}
.panel {
flex: 1;
padding: 4px 8px;
overflow: auto;
background: linear-gradient(#99fffe, #99fffe) left -3px top 0, linear-gradient(#99fffe, #99fffe) left -3px top -3px, linear-gradient(#99fffe, #99fffe) right -3px top 0, linear-gradient(#99fffe, #99fffe) right -3px top -3px, linear-gradient(#99fffe, #99fffe) left -3px bottom 0, linear-gradient(#99fffe, #99fffe) left -3px bottom -3px, linear-gradient(#99fffe, #99fffe) right -3px bottom 0, linear-gradient(#99fffe, #99fffe) right -3px bottom -3px;
background-color: rgba(0, 34, 51, 0.5);
background-repeat: no-repeat;
background-size: 20px 20px, 20px 20px;
background-size: 3px 16px, 16px 3px;
border: 1px solid transparent;
margin: 6px 6px;
}
.panel_title {
height: 30px;
margin-bottom: 4px;
font-size: 18px;
font-weight: bold;
color: #fff;
}
.panel_item {
display: flex;
align-items: center;
color: #fff;
padding: 6px;
background: linear-gradient(40deg, rgba(11, 101, 140, 0.451), rgba(0, 34, 48, 0.335));
}
.panel_label {
font-size: 16px;
flex: 1;
}
.panel_value {
font-size: 18px;
font-weight: bold;
}
.panel_unit {
color: #aebfe9;
margin-left: 4px;
}
.chart {
width: 100%;
height: 220px;
} }
</style> </style>