静态大屏组件

This commit is contained in:
DESKTOP-AD8UBUJ\ling
2026-05-11 09:45:39 +08:00
parent 5aa00e61a9
commit 71e37a9559
2 changed files with 1588 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,260 @@
<!--
* @Descripttion: 大屏设计器 -- 预览
* @Author: Devli
* @Date: 2021-3-13 11:04:24
* @Last Modified by: Raod
* @Last Modified time: 2022-5-6 11:04:24
!-->
<template>
<div class="layout">
<div :style="bigScreenStyle" class="drillDrownViewLayout">
<!-- 关键优化 1: v-if 包裹整个渲染区域避免空数据时渲染 -->
<template v-if="dataLoaded">
<!-- 关键优化 2: 分批渲染避免一次性创建过多 DOM 节点 -->
<static-content :screenData="screenData"></static-content>
</template>
</div>
<el-dialog :title="''" class="dialogDrillDrown dialogDrillDrownView" :visible.sync="visiableDrillView">
<drill-drown-view :screenData="screenData"></drill-drown-view>
</el-dialog>
</div>
</template>
<script>
import staticContent from "./components/static";
import DrillDrownView from "./drillDrownView";
import { detailDashboard } from "@/api/bigscreen";
export default {
name: "Login",
components: {
staticContent,
DrillDrownView
},
data() {
return {
bigScreenStyle: {},
dashboard:{},
widgets: [],
screenData:{
dashboard: { },
widgets: []
},
visiableDrillView:false,
dataLoaded: false, // 数据加载标志
refreshTimer: null, // 定时刷新定时器
renderBatches: [], // 分批渲染的批次
batchSize: 10, // 每批渲染的组件数量 (轻量级)
renderTimer: null, // 分批渲染定时器
renderedCount: 0 // 已渲染的组件数量
};
},
mounted() {
this.getData();
window.onresize=this.Debounce(this.setScale,500);
},
beforeDestroy() {
console.log('[Viewer] beforeDestroy 开始清理资源');
// 1. 清除定时刷新定时器
if (this.refreshTimer) {
clearTimeout(this.refreshTimer);
this.refreshTimer = null;
console.log('[Viewer] 已清除定时刷新定时器');
}
// 2. 清除分批渲染定时器
if (this.renderTimer) {
clearTimeout(this.renderTimer);
this.renderTimer = null;
console.log('[Viewer] 已清除分批渲染定时器');
}
// 3. 清空大型数据引用,释放内存
this.widgets = [];
this.renderBatches = [];
this.dashboard = {};
this.screenData = { dashboard: {}, widgets: [] };
// 4. 移除 window 事件监听
if (window.onresize) {
window.onresize = null;
}
console.log('[Viewer] 资源清理完成');
},
methods: {
oepnTheDrillView(val){
this.screenData=val
this.visiableDrillView=true
},
async getData() {
try {
const reportCode = 'demotest';
const { code, data } = await detailDashboard(reportCode);
console.log(data)
if (code != 200) {
console.error('[Viewer] 获取大屏数据失败:', code);
return;
}
this.dashboard = data.dashboard || {};
const equipment = document.body.clientWidth;
const ratioEquipment = equipment / data.dashboard.width;
const ratioEquipmentHeight = window.innerHeight / data.dashboard.height;
this.bigScreenStyle = {
width: data.dashboard.width + "px",
height: data.dashboard.height + "px",
"background-color": data.dashboard.backgroundColor,
"background-image": "url(" + data.dashboard.backgroundImage + ")",
"background-position": "0% 0%",
"background-size": "100% 100%",
"background-repeat": "initial",
"background-attachment": "initial",
"background-origin": "initial",
"background-clip": "initial",
transform: `scale(${ratioEquipment}, ${ratioEquipmentHeight})`,
"transform-origin": "0 0"
};
// 关键优化:冻结组件数据,避免 Vue 的响应式系统占用大量内存
const frozenWidgets = Object.freeze(data.dashboard.widgets.map((item, index) => {
item.value.widgetId = item.value.setup.widgetId;
item.value.widgetCode = item.value.setup.widgetCode;
if (item.value.setup.componentLinkage && item.value.setup.componentLinkage.length) {
this.$store.commit('SET_ALL_COMPONENT_LINKAGE', {
index,
widgetId: item.value.widgetId,
linkageArr: item.value.setup.componentLinkage
});
}
return item;
}));
// 赋值给 widgets 用于分批渲染
this.widgets = frozenWidgets;
console.log(`[Viewer] 数据加载完成,共 ${this.widgets.length} 个组件,开始分批渲染`);
// 标记数据已加载
this.dataLoaded = true;
// 开始分批渲染组件
this.startBatchRender();
// 定时刷新 - 保存定时器引用以便清理
if(data.dashboard.refreshSeconds > 0) {
this.refreshTimer = setTimeout(() => {
console.log('[Viewer] 定时刷新触发');
window.location.reload();
}, data.dashboard.refreshSeconds * 1000);
}
} catch (error) {
console.error('[Viewer] 获取数据异常:', error);
this.dataLoaded = false;
}
},
Debounce:(fn,t)=>{
const delay=t||500;
let timer=null;
return(...args)=>{
if(timer){
clearTimeout(timer);
}
const context=this
timer=setTimeout(()=>{
fn.apply(context,args);
},delay);
}
},
setScale(){
const scale=this.getScale();
// this.bigScreenStyle.transform='scale('+scale.scalex+','+scale.scaley+')'
this.bigScreenStyle.transform = `scale(${scale.scalex},${scale.scaley})`
},
getScale(){
let width = this.dashboard.width
let height = this.dashboard.height
// 固定宽度比例
const scalex = window.innerWidth / width
// // 高度按相同比例缩放,但允许超出屏幕高度
// const scaley = scalex
// 高度按屏幕高度比例
const scaley = window.innerHeight / height
return {
scalex,
scaley
}
},
/**
* 分批渲染组件,避免一次性创建过多 DOM 节点导致页面卡顿
*/
startBatchRender() {
this.renderedCount = 0;
this.renderBatches = [];
const renderNextBatch = () => {
if (this.renderedCount >= this.widgets.length) {
console.log('[Viewer] 所有组件渲染完成,总数:', this.widgets.length);
return;
}
// 计算本批次要渲染的组件
const start = this.renderedCount;
const end = Math.min(start + this.batchSize, this.widgets.length);
// 使用 slice 创建新批次,避免引用原数组
const batch = Object.freeze(this.widgets.slice(start, end));
// 添加到渲染批次
this.renderBatches.push(batch);
this.renderedCount = end;
console.log(`[Viewer] 渲染第 ${this.renderBatches.length} 批,组件 ${start}-${end-1}`);
// 继续渲染下一批
if (this.renderedCount < this.widgets.length) {
this.renderTimer = setTimeout(renderNextBatch, 100); // 每批间隔 100ms
}
};
// 开始渲染第一批
renderNextBatch();
},
}
};
</script>
<style lang="scss">
.layout {
width: 100%;
height: 100vh;
text-align: center;
}
.dialogDrillDrownView .el-dialog{
width:auto;
margin-top:0 !important;
transform: scale(0.6, 0.6);
.el-dialog__body{
padding:0;
max-height:calc(100vh - 34px);
overflow:auto;
&::-webkit-scrollbar {
display: none; /* 隐藏滚动条 */
}
}
.el-dialog__header .el-dialog__headerbtn{
top: 6px;
}
}
.bottom-text {
width: 100%;
color: #a0a0a0;
position: fixed;
bottom: 16px;
z-index: 9999;
}
</style>