Commit fa24bdd8 authored by 赵啸非's avatar 赵啸非

Merge remote-tracking branch 'origin/master'

parents 100399d3 72754f39
<template>
<div ref="threeDom" id="counter">
<div id="alert-css2"></div>
</div>
</template>
<script>
import * as THREE from "three";
import {
CSS2DRenderer,
CSS2DObject,
} from "three/examples/jsm/renderers/CSS2DRenderer";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader";
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min";
class PositionGUI {
constructor(obj, name) {
this.obj = obj;
this.name = name;
}
get modify() {
return this.obj[this.name];
}
set modify(v) {
this.obj[this.name] = v;
}
}
export default {
props: {
// 楼层
lv: {
type: String,
default: "1",
},
// 楼层图接口数据
floorArr: {
type: Array,
default: () => [],
},
},
data() {
return {
keyobj: {}, //窗口模型
modlObj: {}, //保存模型对象
checkedMesh: null, //选中模型
cloneMttl: null, //窗口材质备份
FPS: 30,
timeS: 0,
renderer: "",
camera: {},
scene: "",
controls: "",
labelRenderer: "",
Tips: "",
ambientLight: "",
directionalLight: "",
TWEENN: "",
SpotLight: "",
threeDate: {
isloading: true,
floorList: {}, //楼层图
floosrNum: "1",
checkWind: {}, //选中窗口
},
};
},
watch: {
lv(newVal) {
this.modlObj[this.threeDate.floosrNum].obj.visible = false; //隐藏未选中模型
this.modlObj[e].obj.visible = true; //显示选中模型
this.threeDate.floosrNum = newVal;
// this.css2DOM()
},
// floorArr: {
// handler: (newVal) => {
// console.log(this);
// let obj = {}; //转换成key为楼层的对象
// newVal.forEach((v) => {
// obj[v.lv] = v;
// });
// this.threeDate.floorList = obj;
// if (this.camera) {
// this._3Dloder();
// } else {
// this._initTree();
// }
// },
// deep: true,
// },
floorArr(newVal) {
let obj = {}; //转换成key为楼层的对象
newVal.forEach((v) => {
obj[v.lv] = v;
});
this.threeDate.floorList = obj;
if (this.camera) {
this._3Dloder();
} else {
this._initTree();
}
},
},
mounted() {
this._initTree();
},
methods: {
updateCamera() {
this.camera.updateProjectionMatrix();
},
// 渲染
animation() {
// TWEEN.update()
let clock = new THREE.Clock();
requestAnimationFrame(this.animation);
let T = clock.getDelta();
this.timeS = this.timeS + T;
let renderT = 1 / this.FPS;
// requestAnimationFrame默认调用render函数60次,通过时间判断,降低renderer.render执行频率
if (this.timeS > renderT) {
// 控制台查看渲染器渲染方法的调用周期,也就是间隔时间是多少
// console.log(`调用.render时间间隔`,timeS*1000+'毫秒');
this.controls.update();
this.renderer.render(this.scene, this.camera);
this.labelRenderer.render(this.scene, this.camera);
//renderer.render每执行一次,timeS置0
this.timeS = 0;
}
},
// 灯光
_Light() {
this.ambientLight = new THREE.AmbientLight(0xffffff, 1);
this.ambientLight.position.set(0, 0, 0);
this.scene.add(this.ambientLight);
this.directionalLight = new THREE.DirectionalLight(0xffffff, 1);
this.directionalLight.castShadow = true;
this.directionalLight.position.set(5, 10, 7.5);
this.scene.add(this.directionalLight);
},
//3d loader
_3Dloder() {
let threeDate = this.threeDate;
let _this = this;
let MTLLoaders = new MTLLoader();
let OBJLoaders = new OBJLoader();
let GLTFLoaders = new GLTFLoader();
OBJLoaders.setCrossOrigin("Anonymous"); //跨域问题
const { floorList } = threeDate;
for (const iterator in floorList) {
const mtl = floorList[iterator].mtl_url;
const obj = floorList[iterator].obj_url;
if (obj.search(/.obj/i) >= 0) {
// 模型
MTLLoaders.load(
"http://192.168.0.98:8090" + mtl,
function (materials) {
//obj的模型会和MaterialCreator包含的材质对应起来
OBJLoaders.setMaterials(materials);
OBJLoaders.load("http://192.168.0.98:8090" + obj, function (obj) {
if (_this.lv !== iterator) {
obj.visible = false;
}
_this.modlObj[iterator] = {
position: {
x: 0,
y: 0,
z: 0,
},
obj: obj,
};
threeDate.isloading = false;
_this.scene.add(obj); //返回的组对象插入场景中
});
}
);
} else if (obj.search(/.gltf/i) >= 0) {
GLTFLoaders.load("http://192.168.0.98:8090" + obj, function (obj) {
console.log(obj, "@@@@@@@");
const children = obj.scene.children[0].children;
children.forEach((element) => {
let objname = element.name;
// 窗口
if (/^\d_/.test(objname)) {
// 获取外部模型具体点击位置 obj模型没有位置
element.geometry.computeBoundingSphere();
// 球体中心点
let realPosition = element.geometry.boundingSphere.center;
element["positions"] = realPosition;
_this.keyobj[objname] = element;
}
});
if (_this.lv !== iterator) {
obj.scene.visible = false;
}
_this.modlObj[iterator] = {
position: {
x: 0,
y: 0,
z: 0,
},
obj: obj.scene,
};
console.log(obj.scene, iterator, _this.lv, "#########");
_this.scene.add(obj.scene); //返回的组对象插入场景中
threeDate.isloading = false;
});
}
}
},
// 初始化相机
_initCamera() {
this.camera.position.x = -500;
this.camera.position.y = 500;
this.camera.position.z = 1000;
},
// css2render
css2renderer() {
let threeDom = this.$refs.threeDom;
let screenW = threeDom.clientWidth;
let screenH = threeDom.clientHeight;
let css2dom = document.getElementById("alert-css2");
this.Tips = new CSS2DObject(css2dom);
this.Tips.position.set(0, 0, 0); //文字地址
this.Tips.visible = false;
this.scene.add(this.Tips);
this.labelRenderer = new CSS2DRenderer(); //新建CSS2DRenderer
this.labelRenderer.setSize(screenW, screenH);
this.labelRenderer.domElement.style.position = "absolute";
this.labelRenderer.domElement.style.top = 0;
threeDom.appendChild(this.labelRenderer.domElement);
},
// css2
css2controls() {
this.css2renderer();
this.controls = new OrbitControls(
this.camera,
this.labelRenderer.domElement
);
const counter = document.getElementById("counter");
counter.appendChild(this.renderer.domElement);
},
// 调试模式
initGui() {
let datGui = new GUI();
//声明一个保存需求修改的相关数据的对象
let gui = {
ambientLight: "#9b9ba3", //环境光源
directionalLight: "#0xffc288", //点光源
intensity: 1, //灯光强度
visible: true, //是否可见
castShadow: true,
exponent: 30,
target: "plane",
debug: false,
};
//将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值)
datGui.addColor(gui, "ambientLight").onChange(function (e) {
this.ambientLight.color = new THREE.Color(e);
});
datGui.add(gui, "intensity", 0, 5).onChange(function (e) {
this.ambientLight.intensity = e;
});
datGui.addColor(gui, "directionalLight").onChange(function (e) {
this.directionalLight.color = new THREE.Color(e);
});
datGui.add(gui, "intensity", 0, 5).onChange(function (e) {
this.directionalLight.intensity = e;
});
datGui.add(gui, "visible").onChange(function (e) {
this.directionalLight.visible = e;
});
datGui.add(gui, "castShadow").onChange(function (e) {
this.directionalLight.castShadow = e;
});
datGui.add(gui, "debug").onChange(function (e) {
if (e) {
let debug = new THREE.CameraHelper(
this.directionalLight.shadow.camera
);
debug.name = "debug";
this.scene.add(debug);
} else {
// let debug = this.scene.getObjectByName("debug");
// this.scene.remove(debug);
}
});
datGui.add(this.camera, "fov", 1, 18000).onChange(this.updateCamera);
datGui.add(this.camera, "near", 1, 20000).onChange(this.updateCamera);
datGui.add(this.camera, "far", 1, 20000).onChange(this.updateCamera);
const folder = datGui.addFolder("全局Position");
folder
.add(new PositionGUI(this.camera.position, "x"), "modify", 0, 20000)
.name("x");
folder
.add(new PositionGUI(this.camera.position, "y"), "modify", 0, 20000)
.name("y");
folder
.add(new PositionGUI(this.camera.position, "z"), "modify", 0, 20000)
.name("z");
},
// 初始化
_initTree() {
let threeDom = this.$refs.threeDom;
this.scene = new THREE.Scene();
let screenW = threeDom.clientWidth;
let screenH = threeDom.clientHeight;
this.camera = new THREE.PerspectiveCamera(
25,
screenW / screenH,
0.01,
20000
);
this._initCamera();
this.camera.lookAt(this.scene.position);
this.renderer = new THREE.WebGLRenderer({
antialias: true, //开启抗锯齿
logarithmicDepthBuffer: true, //对数深度缓存解决模型重叠
alpha: true, //背景透明
});
this.renderer.shadowMap.enabled = true;
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 设置投影类型, 这边的柔和投影
this.renderer.setSize(screenW, screenH);
threeDom.appendChild(this.renderer.domElement);
this._Light();
this.css2controls();
// controls.autoRotate = true
this.controls.minDistance = 500;
this.controls.maxDistance = 1000;
this.controls.maxPolarAngle = 1.3;
this.controls.minPolarAngle = 0.5;
// if(process.env.NODE_ENV == 'development'){
// // this.initGui()
// }
// initGui()
this.animation();
},
},
};
</script>
<style lang="less" scoped>
#counter {
position: relative;
}
</style>
\ No newline at end of file
......@@ -24,17 +24,17 @@
<div class="dev-total flex aic jcb mb30">
<div class="dev-total-item">
<img class="icon-img" src="@/assets/images/data/icon4.png" />
<div class="flex flexc jcb">
<div class="flex flexc jcb flex1">
<div class="title tar">设备总数(台)</div>
<div class="tar count">200</div>
<div class="tar count">{{ deviceTotalCount }}</div>
<img class="line-img" src="@/assets/images/data/icon8.png" />
</div>
</div>
<div class="dev-total-item">
<img class="icon-img" src="@/assets/images/data/icon3.png" />
<div class="flex flexc jcb">
<div class="flex flexc jcb flex1">
<div class="title tar">监控站点(个)</div>
<div class="tar count">200</div>
<div class="tar count">{{ siteSize }}</div>
<img class="line-img" src="@/assets/images/data/icon8.png" />
</div>
</div>
......@@ -61,26 +61,24 @@
</div>
</div>
</div>
<div class="center">
<Three class="three" :lv="lv" :floorArr="floorArr"></Three>
</div>
<div class="center"></div>
<div class="right">
<div class="right-content">
<!-- 设备告警汇总 -->
<div class="dev-total flex aic jcb mb30">
<div class="dev-total-item">
<img class="icon-img" src="@/assets/images/data/icon7.png" />
<div class="flex flexc jcb">
<div class="flex flexc jcb flex1">
<div class="title tar">今日告警次数(次)</div>
<div class="tar count">200</div>
<div class="tar count">{{ todayAlarmInfoCount }}</div>
<img class="line-img" src="@/assets/images/data/icon8.png" />
</div>
</div>
<div class="dev-total-item">
<img class="icon-img" src="@/assets/images/data/icon6.png" />
<div class="flex flexc jcb">
<div class="flex flexc jcb flex1">
<div class="title tar">今日告警设备(个)</div>
<div class="tar count">200</div>
<div class="tar count">{{ todayAlarmDeviceCount }}</div>
<img class="line-img" src="@/assets/images/data/icon8.png" />
</div>
</div>
......@@ -92,19 +90,25 @@
<div class="warning-info-item1">
<div class="item1-info">
<div class="title">危险</div>
<div class="percent">24%</div>
<div class="percent">
{{ alarmLevelCollect.危险 ? alarmLevelCollect.危险 : 0 }}%
</div>
</div>
</div>
<div class="warning-info-item2">
<div class="item2-info">
<div class="title">次要</div>
<div class="percent">24%</div>
<div class="percent">
{{ alarmLevelCollect.次要 ? alarmLevelCollect.次要 : 0 }}%
</div>
</div>
</div>
<div class="warning-info-item1">
<div class="item1-info">
<div class="title">一般</div>
<div class="percent">24%</div>
<div class="percent">
{{ alarmLevelCollect.一般 ? alarmLevelCollect.一般 : 0 }}%
</div>
</div>
</div>
</div>
......@@ -128,46 +132,17 @@
<script>
import HeaderSite from "./components/HeaderSite.vue";
import TitleItem from "./components/TitleItem.vue";
import Three from "@/components/three/Three.vue";
import session from "@/assets/utils/session";
export default {
components: {
HeaderSite,
TitleItem,
Three,
},
data() {
return {
siteId: session.getSession("siteid"),
warningInfo: {
data: [
{
name: "周口",
value: 55,
},
{
name: "南阳",
value: 120,
},
{
name: "西峡",
value: 78,
},
{
name: "驻马店",
value: 66,
},
{
name: "新乡",
value: 80,
},
{
name: "信阳",
value: 45,
},
{
name: "漯河",
value: 29,
},
],
data: [],
rowNum: 5,
waitTime: 2000,
},
......@@ -179,92 +154,95 @@ export default {
evenRowBGC: "#263963",
rowNum: 17,
align: ["center", "center", "center", "center"],
data: [
[
"一楼排号机",
"5",
"15:00",
"<span style='color:#5ceeff'>在线</span>",
],
["一楼排号机", "5", "15:00", "在线"],
[
"一楼排号机",
"5",
"15:00",
"<span style='color:#FF4A4A'>离线</span>",
],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "待激活"],
[
"一楼排号机",
"5",
"15:00",
"<span style='color:#FF964A'>停用</span>",
],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
["一楼排号机", "5", "15:00", "在线"],
],
data: [],
},
floorArr: [],
lv: "1",
deviceTotalCount: 0, // 总设备数量
siteSize: 0, // 监控站点数量
todayAlarmInfoCount: 0, // 今日告警次数
todayAlarmDeviceCount: 0, // 今日告警设备数量
siteDeviceCollect: {}, // 分站点统计设备数量
siteDeviceAlarmCollect: {}, // 分站点统计设备今日告警数量
deviceConnTypeCollect: {}, // 设备类型分布
alarmTypeCollect: {}, // 告警类型统计分布
deviceFirmCollect: {}, // 设备厂家排名
alarmLevelCollect: {}, // 今日告警等级分布
deviceAlarmMapInfoList: [], // 实施告警消息
};
},
mounted() {
this.getDevTypeDisEchart();
this.getWarningDisEchart();
this.getManufacturersTopEchart();
setTimeout(() => {
this.floorArr = [
{
id: 4,
building: 1,
lv: 1,
picture: "",
phonepicture: "",
mtl_url: "/uploads/floor/yibin2/L1.mtl",
obj_url: "/uploads/floor/L1-1/L1-1.gltf",
siteid: 1,
type: 1,
create_time: "2023-03-13 11:32:38",
update_time: "2023-04-08 11:40:07",
zip_url: "/uploads/floor/L1-1/L1-1.zip",
},
{
id: 5,
building: 1,
lv: 2,
picture: "",
phonepicture: "",
mtl_url: "/uploads/floor/yibin/L2.mtl",
obj_url: "/uploads/floor/L2-1/L2-1.gltf",
siteid: 1,
type: 1,
create_time: "2023-03-13 16:54:14",
update_time: "2023-04-08 11:40:21",
zip_url: "/uploads/floor/L2-1/L2-1.zip",
},
];
});
created() {
this.getDevAlarm();
this.getData();
},
methods: {
// 获取今日告警设备统计
getDevAlarm() {
this.$post("/device/alarm/info/stats", { siteId: this.siteId }).then(
(res) => {
let {
deviceTotalCount,
siteSize,
todayAlarmInfoCount,
todayAlarmDeviceCount,
siteDeviceCollect,
siteDeviceAlarmCollect,
deviceConnTypeCollect,
alarmTypeCollect,
deviceFirmCollect,
alarmLevelCollect,
deviceAlarmMapInfoList,
} = res.data;
this.deviceTotalCount = deviceTotalCount;
this.siteSize = siteSize;
this.todayAlarmInfoCount = todayAlarmInfoCount;
this.todayAlarmDeviceCount = todayAlarmDeviceCount;
this.siteDeviceCollect = siteDeviceCollect;
this.alarmTypeCollect = alarmTypeCollect;
this.deviceConnTypeCollect = deviceConnTypeCollect;
this.deviceFirmCollect = deviceFirmCollect;
this.siteDeviceAlarmCollect = siteDeviceAlarmCollect;
this.alarmLevelCollect = alarmLevelCollect;
this.deviceAlarmMapInfoList = deviceAlarmMapInfoList;
if (deviceAlarmMapInfoList.length) {
let arr = deviceAlarmMapInfoList.map((v) => {
return [
v.deviceName,
v.count,
v.alarmTime,
this.filterDevAlarmType(v.alarmType),
];
});
this.realTimeInfo = { ...this.realTimeInfo, data: arr };
}
let { 直连设备, 子设备, 网关设备 } = deviceConnTypeCollect;
let { 在线, 离线, 缺纸 } = alarmTypeCollect;
let firmName = Object.keys(deviceFirmCollect).map((key) => key);
let firmValues = Object.keys(deviceFirmCollect).map((key) =>
Number(deviceFirmCollect[key])
);
if (Object.keys(siteDeviceAlarmCollect).length) {
let arr = Object.keys(siteDeviceAlarmCollect).map((key) => {
return {
name: key,
value: siteDeviceAlarmCollect[key],
};
});
this.warningInfo = { ...this.warningInfo, data: arr };
}
this.$nextTick(() => {
// 设备类型发布
this.getDevTypeDisEchart(直连设备, 子设备, 网关设备);
// 设备告警类型分布
this.getWarningDisEchart(在线, 离线, 缺纸);
// 厂家top5
this.getManufacturersTopEchart(firmName, firmValues);
});
}
);
},
// 获取设备类型分布图标
getDevTypeDisEchart() {
getDevTypeDisEchart(direct, subset, network) {
let chartDom = document.getElementById("devTypeDis");
this.devType = this.$echarts.init(chartDom);
if (!this.devType) {
......@@ -307,7 +285,7 @@ export default {
left: "center",
top: "center",
style: {
text: "总数" + "\n\n" + 200,
text: "总数" + "\n\n" + this.deviceTotalCount,
textAlign: "center",
fill: "#fff",
width: 30,
......@@ -333,21 +311,21 @@ export default {
},
data: [
{
value: 1048,
value: subset || 0,
name: "子设备",
itemStyle: {
color: "#5CEEFF",
},
},
{
value: 735,
value: network || 0,
name: "网关设备",
itemStyle: {
color: "#5DA7FF",
},
},
{
value: 580,
value: direct || 0,
name: "直连设备",
itemStyle: {
color: "#FF964A",
......@@ -361,7 +339,7 @@ export default {
option && this.devType.setOption(option);
},
// 获取告警类型分布
getWarningDisEchart() {
getWarningDisEchart(onLine, offLine, lackPaper) {
let chartDom = document.getElementById("warningDis");
this.warningDis = this.$echarts.init(chartDom);
if (!this.warningDis) {
......@@ -404,7 +382,7 @@ export default {
left: "center",
top: "center",
style: {
text: "总数" + "\n\n" + 2000,
text: "总数" + "\n\n" + this.todayAlarmInfoCount,
textAlign: "center",
fill: "#fff",
width: 30,
......@@ -429,21 +407,21 @@ export default {
},
data: [
{
value: 1048,
value: onLine || 0,
name: "在线",
itemStyle: {
color: "#5CEEFF",
},
},
{
value: 735,
value: offLine || 0,
name: "离线",
itemStyle: {
color: "#5DA7FF",
},
},
{
value: 580,
value: lackPaper || 0,
name: "缺纸",
itemStyle: {
color: "#FF4A4A",
......@@ -457,7 +435,7 @@ export default {
option && this.warningDis.setOption(option);
},
// 获取厂家top5Echart
getManufacturersTopEchart() {
getManufacturersTopEchart(names = [], values = []) {
let chartDom = document.getElementById("manufacturersTop");
// 避免刷新数据时重新初始化图表
this.manufacturersTop = this.$echarts.getInstanceByDom(chartDom);
......@@ -480,18 +458,19 @@ export default {
textStyle: {
color: "#fff",
},
formatter: (params) => {
let str = "";
params.forEach((v) => {
str = `${v.name}${v.value}%`;
});
return str;
},
},
yAxis: [
{
type: "category",
inverse: true, // 反转渲染
data: [
"四川信宏翔科技有限公司",
"四川信宏翔科技有限公司",
"四川信宏翔科技有限公司",
"四川信宏翔科技有限公司",
"四川信宏翔科技有限公司",
],
data: names,
axisLine: {
show: false,
},
......@@ -537,7 +516,7 @@ export default {
{
type: "bar",
barWidth: "8px", // 柱体宽度
data: [100, 200, 100, 300, 400],
data: values,
// 数值
label: {
show: false,
......@@ -581,7 +560,7 @@ export default {
symbolSize: [2, 8],
symbolPosition: "start",
symbolOffset: [-1, 0],
data: [100, 200, 100, 300, 400],
data: values,
z: 66,
animationEasing: "elasticOut",
tooltip: {
......@@ -601,7 +580,7 @@ export default {
symbolSize: [2, 8],
symbolPosition: "start",
symbolOffset: [-1, 0],
data: [400, 400, 400, 400, 400],
data: [100, 100, 100, 100, 100],
z: 60,
animationEasing: "elasticOut",
tooltip: {
......@@ -613,6 +592,25 @@ export default {
option && this.manufacturersTop.setOption(option);
},
// 过滤设备告警类型
filterDevAlarmType(type) {
if (type == "离线") {
return `<span style='color:#FF4A4A'>${type}</span>`;
} else if (type == "在线") {
return `<span style='color:#5ceeff'>${type}</span>`;
} else if (type == "停用") {
return `<span style='color:#FF964A'>${type}</span>`;
}
},
// 定时获取数据
getData() {
this.timer = setInterval(() => {
this.getDevAlarm();
}, 1000 * 60);
},
},
beforeDestroy() {
clearInterval(this.timer);
},
};
</script>
......@@ -658,9 +656,13 @@ export default {
.main {
padding: 0px 50px;
}
.dev-total {
height: 120px;
}
.dev-total-item {
width: 240px;
height: 100%;
padding-right: 10px;
background: url("~@/assets/images/data/xk.png") no-repeat center;
background-size: 100% 100%;
display: flex;
......@@ -694,9 +696,6 @@ export default {
position: absolute;
left: 0px;
top: -20px;
.dev-total {
height: 120px;
}
.warning-list {
height: 230px;
......@@ -781,7 +780,7 @@ export default {
}
}
.real-time-list {
height: 522px;
height: 482px;
padding: 15px;
background: url("~@/assets/images/data/kuang3.png") no-repeat center;
background-size: 100% 100%;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment