Commit 1af7d19a authored by lei's avatar lei

fix:修复bug

parent f01a7aba
<template>
<div class="monitor-map">
<!-- 学校标记 -->
<span
v-for="(school, index) in schools"
:key="'school-' + index"
class="school-marker"
:style="{ left: school.x + 'px', top: school.y + 'px' }"
>
{{ school.name }}
</span>
<!-- 设备点位 -->
<div v-if="showEquipment">
<div
v-for="(equip, index) in equipments"
:key="'equip-' + index"
class="equipment-dot"
:class="{ warning: equip.isWarning }"
:style="{ left: equip.x + 'px', top: equip.y + 'px' }"
@click="handleEquipmentClick(equip)"
>
<div class="tooltip">
<p v-for="(monitor, i) in equip.monitors" :key="i">
{{ monitor.name }}
</p>
</div>
</div>
</div>
<!-- 摄像头点位 -->
<div v-if="showCamera">
<div
v-for="(camera, index) in cameras"
:key="'camera-' + index"
class="camera-dot"
:class="{ offline: !camera.status }"
:style="{ left: camera.x + 'px', top: camera.y + 'px' }"
@click="handleCameraClick(camera)"
/>
</div>
<!-- 切换按钮 -->
<div class="toggle-buttons">
<el-checkbox-group v-model="toggleList">
<el-checkbox label="camera">监控</el-checkbox>
<el-checkbox label="equipment">监测设备</el-checkbox>
</el-checkbox-group>
</div>
</div>
</template>
<script>
export default {
props: {
equipments: Array,
cameras: Array,
schools: Array,
},
data() {
return {
toggleList: ["camera", "equipment"],
};
},
computed: {
showCamera() {
return this.toggleList.includes("camera");
},
showEquipment() {
return this.toggleList.includes("equipment");
},
},
methods: {
handleEquipmentClick(equip) {
this.$emit("equipment-click", equip);
},
handleCameraClick(camera) {
this.$emit("camera-click", camera);
},
},
};
</script>
<style scoped>
/* 样式代码 */
</style>
<template>
<div class="real-time-list">
<vue-seamless-scroll :data="data" :class-option="classOption" class="warp">
<ul class="item">
<div
v-for="(item, index) in data"
:key="index"
:class="activeIndex === index ? 'active' : ''"
@click="handleItemClick(item, index)"
>
<li class="list-item">
<el-row :gutter="16">
<el-col :span="6">
<img :src="getIconPath(item.typeId)" class="icon" />
</el-col>
<el-col :span="10">
<p class="name">{{ item.tpName }}</p>
<p class="time">{{ item.time }}</p>
</el-col>
<el-col :span="8">
<p class="value">
{{ formatValue(item.value) }}{{ item.unit }}
</p>
</el-col>
</el-row>
</li>
</div>
</ul>
</vue-seamless-scroll>
</div>
</template>
<script>
export default {
props: {
data: Array,
activeIndex: Number,
},
data() {
return {
classOption: {
singleHeight: 110,
hoverStop: true,
autoPlay: true,
},
};
},
methods: {
getIconPath(typeId) {
return require(`@/assets/images/screen/hjjc/${typeId}.png`);
},
formatValue(value) {
return value;
},
handleItemClick(item, index) {
this.$emit("item-click", item, index);
},
},
};
</script>
<style scoped>
/* 样式代码 */
</style>
<template>
<div class="monitor-container">
<!-- 左侧实时数据列表 -->
<RealTimeDataList :data="realTimeData" @item-click="handleItemClick" />
<!-- 中间地图区域 -->
<MonitorMap
:equipments="equipments"
:cameras="cameras"
@camera-click="handleCameraClick"
/>
<!-- 右侧图表区域 -->
<div class="right-panel">
<HistoryChart title="环境监测设备" :data="envChartData" />
<HistoryChart title="视频监测设备" :data="videoChartData" />
</div>
<!-- 弹窗组件 -->
<DataDetailModal
v-if="showDetailModal"
:data="selectedData"
@close="closeModal"
/>
<VideoModal
v-if="showVideoModal"
:video="selectedVideo"
@close="closeVideoModal"
/>
</div>
</template>
<script>
// 导入组件
import RealTimeDataList from "./components/RealTimeDataList";
import MonitorMap from "./components/MonitorMap";
import HistoryChart from "./components/HistoryChart";
import DataDetailModal from "./components/DataDetailModal";
import VideoModal from "./components/VideoModal";
// 导入API
import {
fetchRealTimeData,
fetchEquipmentData,
fetchCameraData,
fetchChartData,
} from "@/api/monitor";
export default {
components: {
RealTimeDataList,
MonitorMap,
HistoryChart,
DataDetailModal,
VideoModal,
},
data() {
return {
realTimeData: [],
equipments: [],
cameras: [],
envChartData: {},
videoChartData: {},
selectedData: null,
selectedVideo: null,
showDetailModal: false,
showVideoModal: false,
};
},
async created() {
await this.loadAllData();
},
methods: {
async loadAllData() {
try {
const [realTime, equipments, cameras, charts] = await Promise.all([
fetchRealTimeData(),
fetchEquipmentData(),
fetchCameraData(),
fetchChartData(),
]);
this.realTimeData = realTime;
this.equipments = equipments;
this.cameras = cameras;
this.envChartData = charts.env;
this.videoChartData = charts.video;
} catch (error) {
console.error("数据加载失败:", error);
}
},
handleItemClick(item) {
this.selectedData = item;
this.showDetailModal = true;
},
handleCameraClick(camera) {
this.selectedVideo = camera;
this.showVideoModal = true;
},
closeModal() {
this.showDetailModal = false;
},
closeVideoModal() {
this.showVideoModal = false;
},
},
};
</script>
<style scoped>
.monitor-container {
display: flex;
height: 100vh;
}
.right-panel {
display: flex;
flex-direction: column;
width: 300px;
}
</style>
......@@ -19,6 +19,7 @@
<div
class="sub-item"
:class="showMenu == 1 ? 'active' : ''"
key="rydw"
@click="changeMenu('rydw')"
>
<p>人员定位</p>
......@@ -26,7 +27,7 @@
<div
class="sub-item"
@click="changeMenu('hjjc')"
key=""
key="hjjc"
:class="showMenu == 2 ? 'active' : ''"
>
<p>监测监控</p>
......@@ -34,7 +35,7 @@
<div
class="sub-item"
@click="changeMenu('psxt')"
key=""
key="psxt"
:class="showMenu == 3 ? 'active' : ''"
>
<p>排水系统</p>
......@@ -42,9 +43,9 @@
</div>
<div class="sub-header-mid">
<div class="top-change">
<span @click="changeMenu('home')">首页</span>
<span @click="changeMenu('home')" key="home">首页</span>
<span @click="openVideo">企业宣传</span>
<span @click="changeMenu('tjfx')">系统分析</span>
<span @click="changeMenu('tjfx')" key="tjfx">系统分析</span>
<span @click="goToSys">后台管理</span>
</div>
</div>
......@@ -52,6 +53,7 @@
<div
class="sub-item"
:class="showMenu == 4 ? 'active' : ''"
key="tsj"
@click="changeMenu('tsj')"
>
<p>提升机系统</p>
......@@ -59,6 +61,7 @@
<div
class="sub-item"
:class="showMenu == 5 ? 'active' : ''"
key="tfxt"
@click="changeMenu('tfxt')"
>
<p>通风系统</p>
......@@ -66,6 +69,7 @@
<div
class="sub-item"
:class="showMenu == 6 ? 'active' : ''"
key="dlxt"
@click="changeMenu('dlxt')"
>
<p>电力系统</p>
......
<template>
<div>
<home
v-if="showMenu === 0"
style="position: absolute; top: 0; left: 0; right: 0; bottom: 0"
></home>
<!-- <psxt
v-if="showMenu === 3"
style="position: absolute; top: 0; left: 0; right: 0; bottom: 0"
></psxt> -->
<v-scale-screen
ref="scale-screen"
width="10390"
height="3117"
:fullScreen="false"
>
<!-- <dlxt
v-if="showMenu === 6"
style="position: absolute; top: 0; left: 0; right: 0; bottom: 0"
></dlxt> -->
<div class="container" :class="showMenu===0?'container0':''">
<!-- 头部 -->
<div class="header por">银洞坡金矿智能化综合管控平台</div>
<div class="sub-header">
<div class="sub-header-left">
<div
class="sub-item"
:class="showMenu == 1 ? 'active' : ''"
@click="changeMenu(1)"
>
<p>人员定位</p>
</div>
<div
class="sub-item"
@click="changeMenu(2)"
key=""
:class="showMenu == 2 ? 'active' : ''"
>
<p>环境监测</p>
</div>
<div
class="sub-item"
@click="changeMenu(3)"
key=""
:class="showMenu == 3 ? 'active' : ''"
>
<p>排水系统</p>
</div>
</div>
<div class="sub-header-mid">
<div class="top-change">
<span @click="changeMenu(0)">首页</span>
<span @click="openVideo">企业宣传</span>
<span @click="sysAnalysis">系统分析</span>
<span @click="goToSys">后台管理</span>
</div>
</div>
<div class="sub-header-right">
<div class="sub-item" :class="showMenu == 4 ? 'active' : ''" @click="changeMenu(4)"><p>提升机系统</p></div>
<div class="sub-item" :class="showMenu == 5 ? 'active' : ''" @click="changeMenu(5)"><p>风机系统</p></div>
<div class="sub-item" :class="showMenu == 6 ? 'active' : ''" @click="changeMenu(6)"><p>电力系统</p></div>
</div>
</div>
<!-- <rydw v-if="showMenu === 1" style="pointer-events: auto"></rydw>
<hjjc v-if="showMenu === 2" style="pointer-events: auto"></hjjc> -->
<!-- 底部 -->
<!-- <div class="footer">
</div> -->
</div>
</v-scale-screen>
</div>
</template>
<script>
// import * as echarts from "echarts";
// import { getScale } from "@/utils/tylerlcl";
import { listVideo } from "@/api/tyler/mainVideo";
import screenfull from "screenfull";
import rydw from "./items/rydw.vue";
import hjjc from "./items/hjjc.vue";
import psxt from "./items/psxt.vue";
import home from "./items/home.vue";
import dlxt from "./items/dlxt.vue";
export default {
name: "cockpit",
components: {
home,
rydw,
hjjc,
psxt,
dlxt,
},
data() {
return {
previewUrl: process.env.VUE_APP_API_TARGET,
showMenu: 0,
videoData:null,
};
},
mounted() {
this.getVideo()
if (screenfull && screenfull.enabled && !screenfull.isFullscreen) {
screenfull.request();
}
// this.areaCharts();
// this.alarm30();
},
methods: {
getVideo(){
this.videoData = null;
listVideo().then(res => {
this.videoData = this.previewUrl + res.data;
})
},
changeMenu(val) {
this.showMenu = val;
},
goToSys() {
var link = this.$router.resolve({
path: "/",
});
window.open(link.href);
return;
},
openVideo(){
window.open(this.videoData);
return;
},
sysAnalysis(){
},
},
};
</script>
<style lang="scss" scoped>
/* 标题 */
@font-face {
font-family: "ysbth";
src: url("~@/assets/font/syhtCN-Medium.ttf") format("truetype");
}
@font-face {
font-family: "number";
src: url("~@/assets/font/DS-Digital.ttf") format("truetype");
font-weight: normal;
font-style: normal;
}
.por {
position: relative;
}
.poa {
position: absolute;
}
.psxt-bg {
background: url("~@/assets/images/screen/psxt/bg.png") no-repeat center;
}
/* 基础容器 */
.container {
width: 100%;
height: 100%;
background: url("~@/assets/images/bigscreen/bg.png");
background-repeat: no-repeat;
background-position: center;
background-size: 100% 100%;
display: flex;
flex-direction: column;
padding: 0 240px;
// background-color: #08152a;
position: relative;
font-family: "SimHei";
pointer-events: none;
color: #fff;
}
.container0{
background: url("~@/assets/images/bigscreen/border.png");
background-repeat: no-repeat;
background-position: center;
background-size: 100% 100%;
}
/* 头部标题 */
.header {
// height: 80px;
text-align: center;
// margin-bottom: 20px;
// background: linear-gradient(90deg, rgba(0,72,143,0.8) 0%, rgba(0,36,71,0.6) 100%);
display: flex;
align-items: center;
justify-content: center;
// font-size: 2.5vw;
letter-spacing: 2px;
font-family: SimHei;
// font-weight: 500;
font-size: 120px;
font-weight: bold;
color: #ffffff;
line-height: 240px;
background: -webkit-gradient(
linear,
left top,
left bottom,
from(#ffffff),
color-stop(39.7216796875%, #f3f7fa),
to(#03a9ff)
);
background: linear-gradient(
180deg,
#ffffff 0%,
#f3f7fa 39.7216796875%,
#03a9ff 100%
);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.sub-header {
display: flex;
justify-content: space-between;
padding: 0 60px;
// transform-style: preserve-3d;
perspective: 1000px;
// transform: translateZ(-10px);
pointer-events: auto;
}
.sub-header-left,
.sub-header-right {
display: flex;
justify-content: space-between;
width: 2000px;
margin-top: -150px;
.sub-item {
width: 484px;
height: auto;
background: url("~@/assets/images/bigscreen/button_normal.png") no-repeat center;
background-size: 100%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
&.active {
background: url("~@/assets/images/bigscreen/button_click.png") no-repeat center;
background-size: 100%;
}
p {
font-family: Source Han Sans SC;
font-weight: bold;
font-size: 68px;
color: #ffffff;
line-height: 167px;
background: linear-gradient(
180deg,
#ffffff 0%,
#f3f7fa 39.7216796875%,
#03a9ff 100%
);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
padding-bottom: 20px;
}
}
}
.sub-header-left {
transform: rotateZ(2deg);
}
.sub-header-right {
transform: rotateZ(-2deg);
}
.top-change {
width: 1967px;
height: 300px;
background: url("~@/assets/images/bigscreen/top_bg.png") no-repeat center;
margin: -130px auto 0;
display: flex;
justify-content: space-evenly;
align-items: center;
font-size: 56px;
color: #11e0ff;
span {
cursor: pointer;
text-indent: 1em;
position: relative;
margin-top: 130px;
display: block;
}
span:nth-child(1)::after {
content: "";
width: 46px;
height: 46px;
position: absolute;
background: url("~@/assets/images/bigscreen/icon1.png") no-repeat center;
background-size: 100%;
left: -4px;
top: 10px;
z-index: 20;
}
span:nth-child(2)::after {
content: "";
width: 46px;
height: 46px;
position: absolute;
background: url("~@/assets/images/bigscreen/icon2.png") no-repeat center;
left: -4px;
top: 10px;
z-index: 20;
}
span:nth-child(3)::after {
content: "";
width: 46px;
height: 46px;
position: absolute;
background: url("~@/assets/images/bigscreen/icon3.png") no-repeat center;
left: -4px;
top: 10px;
z-index: 20;
}
span:nth-child(4)::after {
content: "";
width: 46px;
height: 46px;
position: absolute;
background: url("~@/assets/images/bigscreen/icon4.png") no-repeat center;
left: -4px;
top: 10px;
z-index: 20;
}
}
::v-deep .screen-box {
pointer-events: none;
}
</style>
<template>
<div>
<!-- 主体内容 -->
<div class="main-content">
<!-- 左侧 -->
<div class="sidebar sidebar-left">
<div class="sidebar-item H917">
<div class="sub-title por"><span>环境监测实时数据 </span></div>
<div class="table-box">
<vue-seamless-scroll
ref="sssjControl"
:data="tableData1"
:class-option="classOption"
class="warp"
>
<ul class="item">
<div
:class="upWindowData.upWindowActive === i ? 'active' : ''"
style="cursor: pointer"
v-for="(item, i) in tableData1"
:key="i + 'aaa'"
@click="lookRealData(item, i)"
>
<li class="table-item">
<el-row :gutter="16">
<el-col :span="6" class="jz">
<img
class="img-class"
:src="
require(`@/assets/images/screen/hjjc/${item.typeId}.png`)
"
/>
</el-col>
<el-col :span="10">
<p class="device-name">{{ item.tpName }}</p>
<p class="device-time">{{ item.time }}</p>
</el-col>
<el-col :span="8">
<p class="device-value">
{{ item.value | capitalize }}{{ item.unit }}
</p>
</el-col>
</el-row>
</li>
</div>
</ul>
</vue-seamless-scroll>
</div>
</div>
</div>
<!-- 中间 -->
<div class="main-area">
<!--一中、二中。。。-->
<span class="main-example" style="left: 0px; top: 190px">一中</span>
<span class="main-example" style="left: 0px; top: 321px">二中</span>
<span class="main-example" style="left: 0px; top: 446px">三中</span>
<span class="main-example" style="left: 0px; top: 569px">四中</span>
<span class="main-example" style="left: 0px; top: 705px">五中</span>
<!-- 设备点位 -->
<div v-if="checkList.includes('2')">
<div
class="dot"
v-for="(item, i) in equipmentList"
:key="i + 'bbb'"
:class="item.isWarning == 1 ? 'active' : ''"
:style="{ left: item.x + 'px', top: item.y + 'px' }"
>
<div class="dot1" @click="">
<div class="tip-box">
<p
v-for="(iitem, l) in item.monitorPositionList"
:key="l + 'ccc'"
:class="iitem.isWarning == 1 ? 'active' : ''"
>
{{ iitem.equipmentName }}
<span></span>
</p>
</div>
</div>
</div>
</div>
<!--监控点位-->
<div v-if="checkList.includes('1')">
<div
class="camera-item"
v-for="(item, i) in cameraList"
:key="i + 'ddd'"
:class="item.status == 0 ? 'offline' : ''"
:style="{ left: item.x + 'px', top: item.y + 'px' }"
@click="lookVideo(item, i)"
></div>
</div>
<!-- 现实设备切换按钮 -->
<div class="toggle-button">
<el-checkbox-group v-model="checkList">
<el-checkbox label="1">监控</el-checkbox>
<el-checkbox label="2">监测设备</el-checkbox>
</el-checkbox-group>
</div>
</div>
<!-- 右侧 -->
<div class="sidebar sidebar-right">
<!-- 右上历史数据图组件 -->
<div class="sidebar-item H286 alert-analysis">
<div class="sub-title por">
<span>历史数据图</span>
</div>
<div class="sub-con histrybox">
<div class="histrubox_left">
<div class="echarts_title">
<img
src="../../../assets/images/screen/jianceshebei.png"
alt=""
class="img_class"
/>
<span>环境监测设备</span>
</div>
<div class="chart_bg"></div>
<div id="EchartsPieLeft" class="chart_box"></div>
<div class="chart_number">
<span>{{ deviceStatusNum.total }}</span>
<br />
<span>总数</span>
</div>
</div>
<div class="histrubox_right">
<div class="echarts_title">
<img
src="../../../assets/images/screen/shipingshebei.png"
alt=""
class="img_class"
/>
<span>视频监测设备</span>
</div>
<div class="chart_bg_right"></div>
<div id="EchartsPieRight" class="chart_box"></div>
<div class="chart_number_right">
<span>{{ deviceStatusNum.cameraTotal }}</span>
<br />
<span>总数</span>
</div>
</div>
</div>
</div>
<!-- 右中设备监测曲线图 -->
<div class="sidebar-item H286 alert-analysis">
<div class="sub-title por">
<span>历史数据图</span>
<span class="scroll-title">{{ rightTopLssjData.name }}</span>
</div>
<div class="sub-con">
<div class="sub-con">
<span
v-for="(item, i) in rightTopLssjData.list"
:key="i + 'aab'"
:class="i == rightTopLssjData.mark ? 'active' : ''"
>{{ item.name }}
<p class="subscript"></p>
</span>
</div>
<div class="left-chart" ref="sssj" id="sssj"></div>
</div>
</div>
<!-- 右下设备监测曲线图 -->
<div class="sidebar-item H286 alert-analysis">
<div class="sub-title por">
<span>历史数据图</span>
<span class="scroll-title">{{ rightCenterLssjData.name }}</span>
</div>
<div class="sub-con">
<div class="sub-con">
<span
v-for="(item, i) in rightCenterLssjData.list"
:key="i + 'abb'"
:class="i == rightCenterLssjData.mark ? 'active' : ''"
>{{ item.name }}
<p class="subscript"></p>
</span>
</div>
<div class="left-chart" ref="right" id="rclssj"></div>
</div>
</div>
</div>
<!-- 弹窗内容 -->
<transition name="el-fade-in">
<div v-show="upWindowData.upWindowVisible" class="up-window">
<p><span></span>{{ upWindowData.title }}</p>
<i class="el-icon-close close-button" @click="closeUpWindow"></i>
<p class="date-title">{{ upWindowData.date }}</p>
<div class="chart-box" id="chartBox"></div>
</div>
</transition>
<!--视频弹窗-->
<transition name="el-fade-in">
<div v-show="video.upWindowVisible" class="up-window video-window">
<p><span></span>{{ video.title }}</p>
<i class="el-icon-close close-button" @click="closeVideoUpWindow"></i>
<video width="800" id="player" controls></video>
</div>
</transition>
</div>
</div>
</template>
<script>
import * as echarts from "echarts";
import {
getRealData,
getRtData,
getDeviceStatus,
getDeviceData,
getRcData,
getDeviceStatusNum,
} from "@/api/tyler/hjjc";
import { listVideoTable } from "@/api/tyler/videoTable";
import ScrollTable from "@/components/Tyler/ScrollTable.vue";
import screenfull from "screenfull";
import vueSeamlessScroll from "vue-seamless-scroll";
import Highcharts from "highcharts/highcharts";
import highcharts3d from "highcharts/highcharts-3d";
highcharts3d(Highcharts);
export default {
name: "cockpit",
components: {
ScrollTable,
vueSeamlessScroll,
},
data() {
return {
// 设备实施数据弹窗
upWindowData: {
upWindowActive: "",
upWindowVisible: false,
title: "",
date: "2025-03-19",
},
// 左边列表数据
tableData1: [],
// 左侧滚动 参数
classOption: {
singleHeight: 110,
hoverStop: true,
autoPlay: true,
},
// 设备定位分类开关
checkList: ["2", "1"],
// 左侧实施数据列表
rightTopLssjData: {
list: [
{
name: "",
value: [
{
data: {
xData: {
data: [],
},
yData: {
data: [],
},
},
},
],
},
],
// 右上设备轮播下标
mark: 0,
// 右上设备轮播名称
name: "",
},
// 左侧实施数据列表
rightCenterLssjData: {
list: [
{
name: "",
value: [
{
data: {
xData: {
data: [],
},
yData: {
data: [],
},
},
},
],
},
],
// 右上设备轮播下标
mark: 0,
// 右上设备轮播名称
name: "",
},
// 中间图片数据列表
equipmentList: [
{
isWarning: 0, //是否报警
x: 85,
y: 233,
name: "一中避险硐室",
// 监测点
monitorPositionList: [
{
equipmentName: "一中避险硐室氧气", //设备名称
equipmentTy: "", //设备类型
isWarning: 0, //是否报警
},
{
equipmentName: "一中避险硐室一氧化碳", //设备名称
equipmentTy: "", //设备类型
isWarning: 0, //是否报警
},
],
},
],
//摄像头数据
cameraListPostion: [
{
status: 1, //是否在线
x: 50,
y: 150,
name: "一中码头门",
},
{
status: 1, //是否在线
x: 53,
y: 277,
name: "二中码头门",
},
{
status: 1, //是否在线
x: 82,
y: 289,
name: "二中水泵房",
},
{
status: 1, //是否在线
x: 113,
y: 297,
name: "二中避险硐室",
},
{
status: 1, //是否在线
x: 152,
y: 294,
name: "二中空压机房",
},
{
status: 1, //是否在线
x: 71,
y: 411,
name: "三中码头门",
},
],
cameraList: [],
// 视频弹窗
video: {
upWindowVisible: false,
title: "",
videoUrl: "",
},
player: null,
//highCharts配置
highChartsOption: {},
deviceStatusNum: {
//设备总数
total: 0,
//摄像头总数
cameraTotal: 0,
},
};
},
mounted() {
if (screenfull && screenfull.enabled && !screenfull.isFullscreen) {
screenfull.request();
}
// this.initEchartBox("right", this.salvProName, this.salvProValue, 28);
// this.initEchartBox("sssj", this.salvProName, this.salvProValue, 28);
getRtData().then((res) => {
this.rightTopLssjData.list = res.data || [];
this.rtPlayFun(this.rightTopLssjData);
});
getRcData().then((res) => {
this.rightCenterLssjData.list = res.data || [];
console.log(res);
this.rcPlayFun(this.rightCenterLssjData);
});
getDeviceStatus().then((res) => {
// this.equipmentList = res.data;
let dataXY = [
{
name: "三中码头门",
x: "50",
y: "406",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "三中码头门风速",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "三中码头门风速",
equipmentTy: "风速",
isWarning: 0,
},
],
},
{
name: "二中空压机房",
x: "258",
y: "299",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "二中空压机房co",
equipmentTy: "一氧化碳500",
isWarning: 0,
},
{
equipmentName: "二中空压机房风速",
equipmentTy: "风速",
isWarning: 0,
},
],
},
{
name: "东风井",
x: "856",
y: "136",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "东风井风速",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "东风井开停",
equipmentTy: "开停",
isWarning: 0,
},
],
},
{
name: "二中避险硐室",
x: "75",
y: "288",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "二中避险硐室co",
equipmentTy: "一氧化碳500",
isWarning: 0,
},
{
equipmentName: "二中避险硐室氧气",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "一中避险硐室",
x: "85",
y: "153",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "一中避险硐室co",
equipmentTy: "一氧化碳500",
isWarning: 0,
},
{
equipmentName: "一中避险硐室氧气",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "五中避险硐室",
x: "102",
y: "677",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "五中避险硐室co",
equipmentTy: "一氧化碳500",
isWarning: 0,
},
{
equipmentName: "五中避险硐室氧气",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "四中避险硐室",
x: "96",
y: "541",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "四中避险硐室",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "四中避险硐室",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "四中车场",
x: "53",
y: "527",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "四中车场",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
],
},
{
name: "一中主运输巷",
x: "185",
y: "164",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "一中主运输巷co",
equipmentTy: "一氧化碳500",
isWarning: 0,
},
{
equipmentName: "一中主运输巷风速",
equipmentTy: "风速",
isWarning: 0,
},
],
},
{
name: "二中主运输巷",
x: "187",
y: "296",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "二中主运输巷CO",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "二中主运输巷co",
equipmentTy: "一氧化碳500",
isWarning: 0,
},
{
equipmentName: "二中主运输巷风速",
equipmentTy: "风速",
isWarning: 0,
},
],
},
{
name: "二中中运输巷",
x: "316",
y: "303",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "二中中运输巷风速",
equipmentTy: "风速",
isWarning: 0,
},
],
},
{
name: "三中避险硐室",
x: "93",
y: "411",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "三中避险硐室co",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "三中避险硐室氧气",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "五中车场",
x: "53",
y: "686",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "五中车场一氧化碳",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
],
},
{
name: "一中风机",
x: "145",
y: "159",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "一中风机",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "一中风机氧气",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "一中西采区",
x: "341",
y: "192",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "一中西采区CO",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "一中西采区风速",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "一中西采区风机",
equipmentTy: "开停",
isWarning: 0,
},
{
equipmentName: "一中西采区",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "三中运输巷",
x: "518",
y: "439",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "三中运输巷CO",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "三中运输巷风速",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "三中运输巷风机",
equipmentTy: "开停",
isWarning: 0,
},
{
equipmentName: "三中运输巷氧气",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "三中西采",
x: "566",
y: "499",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "三中西采",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "三中西采",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "三中西采",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "四中运输巷",
x: "206",
y: "559",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "四中运输巷",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "四中运输巷",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "四中运输巷风机",
equipmentTy: "开停",
isWarning: 0,
},
{
equipmentName: "四中运输巷",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "五中运输巷",
x: "166",
y: "697",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "五中运输巷",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "五中运输巷",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "五中运输巷风机",
equipmentTy: "开停",
isWarning: 0,
},
{
equipmentName: "五中运输巷",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "一中运输巷",
x: "367",
y: "168",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "一中运输巷风机",
equipmentTy: "开停",
isWarning: 0,
},
],
},
{
name: "二中西采区",
x: "237",
y: "339",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "二中西采区CO",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "二中西采区风速",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "二中西采区氧气",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "二中运输巷",
x: "415",
y: "311",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "二中运输巷风机",
equipmentTy: "开停",
isWarning: 0,
},
],
},
];
if (res.data && res.data.length) {
// 使用接口数据为基础,合并本地坐标数据
this.equipmentList = res.data.map((apiItem) => {
// 在dataXY中查找同名设备
const localItem = dataXY.find((xy) => xy.name === apiItem.name);
// 合并坐标数据,保留接口返回的其他字段
return {
...apiItem,
x: localItem ? localItem.x : 0, // 默认值处理
y: localItem ? localItem.y : 0,
monitorPositionList: apiItem.monitorPositionList || [],
};
});
} else {
// 降级方案:使用本地数据
}
});
//初始化获取左侧环境监测实施数据
getRealData().then((res) => {
this.tableData1 = res.data.map((el) => {
return {
...el,
value: el.value,
};
});
});
//初始化highCharts
getDeviceStatusNum().then((res) => {
if (res.code == 200) {
this.deviceStatusNum = {
total: res.data[0].online + res.data[0].offline,
cameraTotal: res.data[1].online + res.data[1].offline,
};
this.getHighChartsData(res.data);
}
});
this.initvideoPlayer();
},
created() {
listVideoTable().then((res) => {
if (res.code == 200) {
let list = res.rows.map((el) => {
// 根据cameraName动态设置坐标
const camera = this.cameraListPostion.find(
(c) => c.name === el.cameraName
);
if (camera) {
el.x = camera.x || 0; // 使用cameraList中的placeX,如果没有则设为0
el.y = camera.y || 0; // 使用cameraList中的placeY,如果没有则设为0
}
return el;
});
this.cameraList = list;
// this.cameraList = this.cameraListPostion;
}
});
},
methods: {
initvideoPlayer() {
this.player = new WebRtcStreamer("player", "http://127.0.0.1:8000");
},
// videoPlayer(url) {
// this.player.connect(
// "rtsp://192.168.10.150:8604/EUrl/3IRr6GG?params=eyJwcm90b2NvbCI6InJ0c3AiLCJ1c2VySWQiOiJhcGkiLCJ0IjoxLCJhIjoiNWQ4MGYxZjg5N2ZkNGZjOGJkZDc2ZTVhY2NlNzVmN2R8MHwwfDF8b3Blbl9hcGkifQ=="
// );
// },
// 查看视频
lookVideo(item, i) {
this.video.upWindowVisible = true;
this.video.title = item.cameraName;
this.video.videoUrl = item.cameraUrl;
this.player.connect(this.video.videoUrl);
},
closeVideoUpWindow() {
this.video.upWindowVisible = false;
},
getHighChartsData(value = []) {
this.highChartsOption = {
chart: {
type: "pie", //饼图
options3d: {
enabled: true, //使用3d功能
alpha: 60, //延y轴向内的倾斜角度
beta: 0,
},
backgroundColor: "rgba(64, 158, 255, 0)", // 不显示背景色
// spacingTop: -200, // 增加顶部间距
},
legend: {
enabled: true,
align: "center",
verticalAlign: "middle", // 修正为底部对齐
layout: "vertical", // 水平布局
y: 60, // 下移图例
itemStyle: {
color: "#fff",
fontSize: "12px", // 缩小字体
},
labelFormatter: function () {
return `${this.name}: ${this.y}`; // 在图例中显示数据
},
},
title: {
text: "", //图表的标题文字
},
subtitle: {
text: "", //副标题文字
},
plotOptions: {
pie: {
size: "55%", // 缩小饼图尺寸
allowPointSelect: false, // 允许点击,
cursor: "pointer",
innerSize: "65%", //内圆半径,
showInLegend: false,
center: ["50%", "34%"], // 调整饼图中心位置
depth: 15, //3d饼图的厚度,
dataLabels: {
enabled: false, // 启用数据标签
},
},
},
credits: {
enabled: false,
},
series: [
{
type: "pie",
name: "设备统计",
showInLegend: true,
data: [
{
name: "正常设备",
y: value[0].online,
color: "RGBA(37, 160, 238, 1)",
}, // 高数据部分
{
name: "异常设备",
y: value[0].offline,
color: "RGBA(252, 183, 62, 1)",
}, // 低数据部分
],
startAngle: 0, //起始角度,
label: {
show: false,
position: "outside",
formatter: "{b}:{d}%",
normal: {
show: false,
fontSize: 40,
formatter: [" {a|{b}:{d}%}"].join("\n"),
rich: {
a: {
left: 20,
padding: [0, -140, 0, -180],
},
},
},
},
},
],
};
Highcharts.chart("EchartsPieLeft", this.highChartsOption);
this.highChartsOption.series[0].data = [
{ name: "在线", y: value[1].online, color: "#02CD9B" }, // 高数据部分
{ name: "离线", y: value[1].offline, color: "RGBA(252, 183, 62, 1)" }, // 低数据部分
];
Highcharts.chart("EchartsPieRight", this.highChartsOption);
},
// 辅助方法:获取字段值
getItemField(item, fieldKey) {
return item[this.fieldMap[fieldKey]] || "";
},
// 初始化eChartDOM
initEchartBox(id, xData = [], yData = [], mkData = 28, step = 4, grid) {
let maxData = yData.length ? Math.ceil(Math.max(...yData)) : 0;
let minData = yData.length ? Math.floor(Math.min(...yData)) : 0; // 添加向下取整
let myChart = null;
myChart = echarts.init(document.getElementById(id));
let option = {
grid: grid,
xAxis: {
show: true,
type: "category",
boundaryGap: false,
data: xData,
axisLabel: {
show: true,
interval: step,
textStyle: {
color: "#FFFFFF", //更改坐标轴文字颜色
fontSize: 16, //更改坐标轴文字大小
},
},
axisTick: {
alignWithLabel: true,
},
splitLine: {
//网格线
lineStyle: {
type: "dashed", //设置网格线类型 dotted:虚线 solid:实线
opacity: 0.5,
},
show: true, //隐藏或显示
},
},
yAxis: {
type: "value",
max: mkData > maxData ? mkData : maxData,
min: minData,
boundaryGap: false,
axisTick: {
alignWithLabel: true,
},
axisLabel: {
show: true,
textStyle: {
color: "#FFFFFF", //更改坐标轴文字颜色
fontSize: 16, //更改坐标轴文字大小
},
},
splitLine: {
//网格线
lineStyle: {
type: "dashed", //设置网格线类型 dotted:虚线 solid:实线
opacity: 0.5,
},
show: true, //隐藏或显示
},
},
series: [
{
type: "line",
stack: "Total",
smooth: 0.2,
lineStyle: {
width: 2,
color: "#35B1F3",
},
markLine: {
data: [
{
name: "警戒线",
yAxis: mkData,
label: {
show: false,
},
},
],
symbol: ["none", "none"],
lineStyle: {
color: "red",
width: 2,
},
},
showSymbol: false,
areaStyle: {
opacity: 0.8,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgb(55, 184, 251,0.5)",
},
{
offset: 1,
color: "rgb(55, 184, 251,0.1)",
},
]),
},
emphasis: {
focus: "series",
},
data: yData,
},
],
};
myChart.setOption(option);
setTimeout(() => {
myChart.resize();
}, 600);
this.$on("hook:deactivated", () => {
if (myChart != null && myChart != "" && myChart != undefined) {
myChart.dispose();
}
myChart = null;
});
},
// 轮播eChart
// 更改数据达到轮播效果
rtPlayFun(data) {
// 启动定时器,每隔 15 秒执行一次
let i = 0;
let l = 0;
let timer = null;
let grid = {
left: "4%",
right: "5%",
bottom: "4%",
top: "7%",
containLabel: true,
};
if (!timer) {
// 页面进来的时候要触发一次
this.rightTopLssjData.mark = 0;
this.rightTopLssjData.name = data.list[0].value[0].name;
this.initEchartBox(
"sssj",
data.list[0].value[0].value.xData.data,
data.list[0].value[0].value.yData.data,
data.list[0].value[0].value.yData.alarm,
4,
grid
);
}
timer = setInterval(() => {
if (i < data.list.length) {
if (
Array.isArray(data.list[i].value) &&
l < data.list[i].value.length
) {
this.rightTopLssjData.mark = i;
this.rightTopLssjData.name = data.list[i].value[l].name;
this.initEchartBox(
"sssj",
data.list[i].value[l].value.xData.data,
data.list[i].value[l].value.yData.data,
data.list[i].value[l].value.yData.alarm,
4,
grid
);
l++;
} else {
// 需要l重置,否则进不去判断i错乱
l = 0;
i++;
}
} else {
i = 0;
l = 0;
}
}, 15000);
this.$on("hook:activated", () => {
if (timer === null) {
// 避免重复开启定时器
timer = setInterval(() => {
if (i < data.list.length) {
if (
Array.isArray(data.list[i].value) &&
l < data.list[i].value.length
) {
this.rightTopLssjData.mark = i;
this.rightTopLssjData.name = data.list[i].value[l].tpName;
this.initEchartBox(
"sssj",
data.list[i].value[l].data.xData.data,
data.list[i].value[l].data.yData.data,
data.list[i].value[l].data.yData.alarm,
4,
grid
);
l++;
} else {
l = 0;
i++;
}
} else {
i = 0;
l = 0;
}
}, 15000);
}
});
this.$on("hook:deactivated", () => {
clearInterval(timer);
timer = null;
});
},
// 更改数据达到轮播效果
rcPlayFun(data) {
// 启动定时器,每隔 3 秒执行一次
let i = 0;
let l = 0;
let timer = null;
let grid = {
left: "4%",
right: "5%",
bottom: "4%",
top: "7%",
containLabel: true,
};
if (!timer) {
this.rightCenterLssjData.mark = i;
this.rightCenterLssjData.name = data.list[i].value[l].name;
this.initEchartBox(
"rclssj",
data.list[i].value[l].value.xData.data,
data.list[i].value[l].value.yData.data,
data.list[i].value[l].value.yData.alarm,
4,
grid
);
}
timer = setInterval(() => {
if (i < data.list.length) {
if (
Array.isArray(data.list[i].value) &&
l < data.list[i].value.length
) {
this.rightCenterLssjData.mark = i;
this.rightCenterLssjData.name = data.list[i].value[l].name;
this.initEchartBox(
"rclssj",
data.list[i].value[l].value.xData.data,
data.list[i].value[l].value.yData.data,
data.list[i].value[l].value.yData.alarm,
4,
grid
);
l++;
} else {
l = 0;
i++;
}
} else {
i = 0;
l = 0;
}
}, 15000);
this.$on("hook:activated", () => {
if (timer === null) {
// 避免重复开启定时器
timer = setInterval(() => {
if (i < data.list.length) {
if (
Array.isArray(data.list[i].value) &&
l < data.list[i].value.length
) {
this.rightCenterLssjData.mark = i;
this.rightCenterLssjData.name = data.list[i].value[l].tpName;
this.initEchartBox(
"rclssj",
data.list[i].value[l].value.xData.data,
data.list[i].value[l].value.yData.data,
data.list[i].value[l].value.yData.alarm,
4,
grid
);
l++;
} else {
l = 0;
i++;
}
} else {
i = 0;
l = 0;
}
}, 15000);
}
});
this.$on("hook:deactivated", () => {
clearInterval(timer);
timer = null;
});
},
//自动滚动
autoScroll() {
const divData = this.$refs.scroll_List3;
// 拿到表格中承载数据的div元素
divData.scrollTop += 1;
if (
Math.round(divData.clientHeight + divData.scrollTop) + 1 >=
divData.scrollHeight
) {
// 重置table距离顶部距离
divData.scrollTop = 0;
}
this.scrolltimer3 = window.requestAnimationFrame(
this.autoScroll.bind(this)
);
},
// 查看设备24H实时数据
lookRealData(item, i) {
let grid = {
left: 0,
right: "1.7%",
bottom: "4%",
top: "7%",
containLabel: true,
};
let xData = [];
let yData = [];
getDeviceData({ id: item.id }).then((res) => {
if (res.code == 200) {
this.upWindowData.upWindowActive = i;
this.upWindowData.upWindowVisible = true;
this.upWindowData.title = item.tpName;
this.upWindowData.date = res.data.day;
this.classOption.autoPlay = false;
let threshold = 0;
res.data.envScreenEditDto.forEach((i) => {
xData.push(i.time);
yData.push(i.value);
});
threshold = res.data.threshold || 0;
this.initEchartBox("chartBox", xData, yData, threshold, 0, grid);
} else {
this.$message.error("数据请求失败!");
}
});
},
// 关闭弹窗
closeUpWindow() {
this.upWindowData.upWindowActive = "";
this.upWindowData.upWindowVisible = false;
this.classOption.autoPlay = true;
this.$refs.sssjControl._startMove();
},
goToSys() {
var link = this.$router.resolve({
path: "/",
});
window.open(link.href);
return;
},
// 左侧 鼠标滚动代码
handleScroll(e) {
// 改变组件内部 yPos 的值,这样html的translate(0, yPos)就会随之改变
// e.deltaY是滚动的距离
this.$refs.sssjControl.yPos = this.$refs.sssjControl.yPos - e.deltaY;
// 如果是正数 说明是往上滚
if (this.$refs.sssjControl.yPos > 0) {
this.$refs.sssjControl.yPos = 0;
return;
}
// 如果yPos超过内部实际高度的一半则重新到顶部滚动
// 一半的原因是因为组件实际上创建了两个dom,以达到无缝衔接的效果
if (
Math.abs(this.$refs.sssjControl.yPos) >
this.$refs.sssjControl.realBoxHeight / 2
) {
this.$refs.sssjControl.yPos = 0;
}
},
},
filters: {
capitalize: function (value) {
if (value === null || value === undefined) return "--";
console.log(value);
if (value == "" || value == "") {
return value;
}
const parsedValue = Number(value);
if (isNaN(parsedValue)) return "--";
// 整数判断
if (Number.isInteger(parsedValue)) {
return parsedValue.toFixed(1);
}
// 小数保留两位
return parsedValue.toFixed(1);
},
},
watch: {
tableData1: {
handler() {
this.$nextTick(() => {
this.$refs.sssjControl && this.$refs.sssjControl.reset(); // 添加存在性判断
});
},
immediate: true,
},
},
};
</script>
<style lang="scss" scoped>
.por {
position: relative;
}
.sidebar-left {
transform-origin: left center;
transform: scaleX(1) perspective(610px) rotateY(5deg);
}
.sidebar-right {
transform-origin: center right;
transform: scaleX(1) perspective(610px) rotateY(-5deg);
}
/* 主体内容 */
.main-content {
display: flex;
justify-content: space-between;
padding: 0 30px;
padding-top: 160px;
background: url("~@/assets/images/screen/bg12.png");
color: #fff;
}
.histrybox {
width: 100%;
height: 100%;
display: flex;
/**均分2部分 */
.histrubox_left {
width: 50%;
height: calc(100% - 46px);
.echarts_title {
height: 25px;
text-align: center;
span {
color: rgba(42, 207, 255, 1);
font-weight: 400;
font-size: 16px;
color: #2acfff;
}
}
}
.histrubox_right {
width: 50%;
height: calc(100% - 46px);
.echarts_title {
height: 25px;
text-align: center;
span {
color: rgba(42, 207, 255, 1);
font-weight: 400;
font-size: 16px;
color: #2acfff;
}
}
}
.chart_box {
width: 100%;
height: calc(100% - 25px);
}
.img_class {
width: 29px;
height: 25px;
display: inline-block;
line-height: 25px;
margin-right: 12px;
margin-bottom: -7px;
}
.chart_bg {
position: absolute;
width: 140px;
height: 150px;
background-image: url("~@/assets/images/screen/chart.png");
background-repeat: no-repeat;
background-position: cover;
background-size: 100% 100%;
// -webkit-transform: rotateX(65deg);
transform: rotateX(53deg);
left: 45px;
top: 89px;
}
.chart_bg_right {
position: absolute;
width: 140px;
height: 150px;
background-image: url("~@/assets/images/screen/chart.png");
background-repeat: no-repeat;
background-position: cover;
background-size: 100% 100%;
// -webkit-transform: rotateX(65deg);
transform: rotateX(53deg);
left: 275px;
top: 89px;
}
.chart_number {
position: absolute;
width: 100px;
height: 100px;
top: 109px;
left: 66px;
text-align: center;
span:nth-child(1) {
font-size: 30px;
font-weight: 400;
}
}
.chart_number_right {
position: absolute;
width: 100px;
height: 100px;
top: 109px;
left: 296px;
text-align: center;
span:nth-child(1) {
font-size: 30px;
font-weight: 400;
}
}
}
/* 左右侧边栏 */
.sidebar {
width: 460px;
border-radius: 8px;
flex: 1;
// display: flex;
// flex-direction: column;
// display: grid;
grid-template-rows: repeat(3, 1fr);
gap: 2px;
margin-top: -10px;
}
.H917 {
height: 917px;
}
.H286 {
height: 286px;
}
.sidebar-item {
width: 100%;
// height: 286px;
margin-bottom: 30px;
background: linear-gradient(
180deg,
rgba(1, 33, 58, 0.2) 0%,
rgba(8, 132, 233, 0.2) 100%
);
position: relative;
&::before {
content: "";
width: 460px;
height: 4px;
position: absolute;
background: url("~@/assets/images/screen/bottom.png") no-repeat center;
left: 0;
bottom: 0;
right: 0;
z-index: 20;
}
.sub-title {
width: 100%;
height: 46px;
background: url("~@/assets/images/screen/title1.png") no-repeat center;
font-weight: bold;
font-family: "fangsong";
span {
position: absolute;
top: -10px;
left: 30px;
font-size: 22px;
}
.scroll-title {
position: absolute;
top: -7px;
left: 157px;
font-weight: 800;
font-size: 18px;
color: #ffc62e;
}
}
.table-box {
height: 866px;
width: calc(100% - 4px);
.table-item {
height: 110px;
width: calc(100% - 46px);
margin: 0 auto;
border-bottom: 2px dashed rgba(100, 194, 255, 0.3);
padding-top: 9px;
.img-class {
display: block;
width: 85px;
height: 85px;
}
.device-name {
width: 100%;
font-weight: 400;
font-size: 18px;
color: #63c2ff;
font-family: Source Han Sans SC;
height: 15px;
}
.device-time {
font-weight: 400;
font-size: 16px;
color: #b4d5ea;
font-family: Source Han Sans SC;
}
.device-value {
font-family: Source Han Sans SC;
font-weight: 500;
font-size: 28px;
color: #ffffff;
background: linear-gradient(
0deg,
#3cbffa 0%,
#ffffff 56.005859375%,
#e2f6ff 100%
);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
width: 100%;
text-align: center;
}
}
.warp {
width: 100%;
height: 100%;
overflow: hidden;
font-family: "fangzhengyaoti";
ul {
list-style: none;
margin: 0 auto;
.active {
// width: 100%;
background: RGBA(2, 87, 149, 1);
}
}
}
}
.jz {
display: flex;
align-items: center;
justify-content: center;
}
}
/* 中间主区域 */
.main-area {
width: calc(100% - 920px);
background: url("~@/assets/images/screen/bg3.png") no-repeat center;
background-size: contain;
background-position-y: 10px;
text-align: center;
position: relative;
pointer-events: auto;
z-index: 999;
.main-example {
font-size: 18px;
color: #2ed5ff;
line-height: 36px;
font-weight: bold;
position: absolute;
font-family: "fangsong";
}
.dot {
width: 42px;
height: 70px;
position: absolute;
top: 100px;
left: 500px;
background: url("~@/assets/images/screen/hjjc/icon8.png") no-repeat center;
.dot1 {
position: relative;
.tip-box {
width: 216px;
background: linear-gradient(0deg, #062451 0%, #09162d 100%);
box-shadow: 0px 15px 11px 2px rgba(0, 20, 39, 0.31);
border-radius: 4px;
border: 1px solid #11b9ff;
position: absolute;
bottom: 10px;
left: -81px;
padding: 9px 14px 14px 14px;
z-index: 999;
display: none;
p {
font-family: Source Han Sans SC;
font-weight: 400;
font-size: 16px;
color: #1cd2ff;
margin: 5px 0 0 0;
text-align: left;
span {
display: none;
}
&.active {
color: rgba(255, 43, 58, 1);
span {
display: inline-block;
width: 16px;
height: 16px;
background: url("~@/assets/images/screen/hjjc/icon10.png")
no-repeat center;
margin-bottom: -3px;
}
}
}
}
}
&:hover {
background: url("~@/assets/images/screen/hjjc/icon8_hover.png") no-repeat
center;
.tip-box {
display: block;
}
}
&.active {
background: url("~@/assets/images/screen/hjjc/icon9.png") no-repeat center;
&:hover {
background: url("~@/assets/images/screen/hjjc/icon9_hover.png")
no-repeat center;
}
}
}
.camera-item {
width: 42px;
height: 70px;
position: absolute;
top: 100px;
left: 500px;
background: url("~@/assets/images/screen/hjjc/icon_normal.png") no-repeat
center;
cursor: pointer;
&:hover {
background: url("~@/assets/images/screen/hjjc/icon_hover.png") no-repeat
center;
}
&.offline {
background: url("~@/assets/images/screen/hjjc/icon_click.png") no-repeat
center;
}
}
.toggle-button {
width: 120px;
height: 90px;
background: RGBA(8, 27, 58, 1);
position: absolute;
bottom: 58px;
right: 0px;
.el-checkbox-group {
width: 100%;
height: 100%;
.el-checkbox {
margin-top: 16px;
color: #fdfeff;
font-size: 16px;
font-weight: 500;
font-family: "fangzhengyaoti";
}
}
}
}
/* 实时分布图区域 */
.distribution-map {
height: 300px;
background: rgba(8, 28, 49, 0.8);
border-radius: 8px;
}
.sub-con {
.sub-con {
height: 2em;
width: 100%;
// display: flex;
// justify-content: space-around;
// align-items: center;
font-family: "fangzhengyaoti";
span {
float: left;
margin-left: 25px;
min-width: 63px;
height: 2em;
font-size: 16px;
line-height: 16px;
font-weight: 500;
color: rgba(179, 240, 255, 1);
text-align: center;
}
.active {
color: rgba(46, 213, 255, 1);
.subscript {
height: 19px;
width: 100%;
margin-top: 3px;
background: url("~@/assets/images/screen/hjjc/icon7.png") no-repeat
center;
}
}
}
}
.left-chart {
width: 100%;
height: 12em;
}
.sub-con-scroll-table {
width: 95%;
margin: 0 auto;
height: 83%;
overflow: hidden;
}
.custom-header {
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr 1fr 2fr;
text-align: center;
color: #2ed5ff;
}
.custom-item {
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr 1fr 2fr;
text-align: center;
}
.custom-header2 {
width: 100%;
display: grid;
grid-template-columns: 1.5fr 2.2fr 1.3fr;
text-align: center;
color: #2ed5ff;
height: 36px;
line-height: 36px;
color: #2ed5ff;
font-size: 16px;
font-weight: 500;
background: linear-gradient(
0deg,
rgba(61, 98, 147, 0.35) 0%,
rgba(61, 98, 147, 0.03) 100%
);
}
.warp {
height: calc(100% - 36px);
overflow: hidden;
.item {
padding-left: 0px;
margin-bottom: 0px;
margin-top: 0px;
}
.custom-item2 {
width: 100%;
height: 36px;
display: grid;
grid-template-columns: 1.5fr 2.2fr 1.3fr;
text-align: center;
background: linear-gradient(
0deg,
rgba(61, 98, 147, 0.35) 0%,
rgba(61, 98, 147, 0.03) 100%
);
margin-top: 11px;
}
.custom-item-content2 {
font-family: Source Han Sans SC;
font-size: 16px;
line-height: 36px;
color: #bbd7ea;
}
}
.sub-con-r {
width: 100%;
display: flex;
justify-content: space-evenly;
align-items: center;
height: calc(100% - 70px);
.sub-con-r-left {
width: 127px;
height: 161px;
background: url("~@/assets/images/screen/icon3.png") no-repeat center;
background-size: 100%;
}
.sub-con-r-right {
width: 250px;
display: flex;
flex-direction: column;
// gap: 10px;
p {
display: grid;
grid-template-columns: 4fr 4fr 1fr;
font-size: 18px;
line-height: 24px;
color: #bbd7ea;
background-color: rgba(61, 98, 147, 0.2);
padding: 10px 10px;
text-align: justify;
box-sizing: border-box;
span:nth-child(2) {
color: rgba(187, 215, 234, 0.2);
}
span:nth-child(3) {
font-weight: bold;
font-size: 24px;
color: #bbd7ea;
background: linear-gradient(0deg, #47c5ff 0%, #fdfeff 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
}
}
.up-window {
position: absolute;
top: 50%;
left: 50%;
width: 1360px;
height: 480px;
transform: translate(-50%, -50%);
background: url("~@/assets/images/screen/hjjc/popup.png") no-repeat;
background-size: 1377px 501px;
box-shadow: 0px 15px 11px 2px rgba(0, 20, 39, 0.31);
padding: 28px 37px;
z-index: 999;
&.video-window {
width: 900px;
height: 562px;
background: #062451;
p {
width: 820px;
}
}
p {
width: 1271px;
height: 37px;
margin: 0px;
background: url("~@/assets/images/screen/hjjc/title-popup.png") no-repeat
center;
background-size: 100%;
font-weight: 500;
font-size: 22px;
color: #ffffff;
height: 37px;
background-position-y: 9px;
span {
width: 27px;
display: inline-block;
}
}
.close-button {
font-size: 30px;
position: absolute;
top: 16px;
right: 16px;
cursor: pointer;
&:hover {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
-webkit-transition: -webkit-transform 1s linear;
transition: transform 1s linear;
}
}
.date-title {
height: 18px;
font-weight: 500;
font-size: 22px;
color: #15f1ff;
background: none;
margin-left: 56px;
margin-top: 5px;
}
.chart-box {
width: 100%;
height: 355px;
}
}
</style>
// 设备位置配置
export const EQUIPMENT_POSITIONS = [
{
name: '一中避险硐室',
x: '85',
y: '153',
monitorPositionList: [
{ equipmentName: '一中避险硐室co', equipmentTy: '一氧化碳500', isWarning: 0 },
{ equipmentName: '一中避险硐室氧气', equipmentTy: '氧气', isWarning: 0 }
]
},
{
name: '三中码头门',
x: '50',
y: '406',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '三中码头门风速', equipmentTy: '风速', isWarning: 0 },
{ equipmentName: '三中码头门风速', equipmentTy: '风速', isWarning: 0 }
]
},
{
name: '二中空压机房',
x: '258',
y: '299',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '二中空压机房co', equipmentTy: '一氧化碳500', isWarning: 0 },
{ equipmentName: '二中空压机房风速', equipmentTy: '风速', isWarning: 0 }
]
},
{
name: '东风井',
x: '856',
y: '136',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '东风井风速', equipmentTy: '风速', isWarning: 0 },
{ equipmentName: '东风井开停', equipmentTy: '开停', isWarning: 0 }
]
},
{
name: '二中避险硐室',
x: '75',
y: '288',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '二中避险硐室co', equipmentTy: '一氧化碳500', isWarning: 0 },
{ equipmentName: '二中避险硐室氧气', equipmentTy: '氧气', isWarning: 0 }
]
},
{
name: '五中避险硐室',
x: '102',
y: '677',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '五中避险硐室co', equipmentTy: '一氧化碳500', isWarning: 0 },
{ equipmentName: '五中避险硐室氧气', equipmentTy: '氧气', isWarning: 0 }
]
},
{
name: '四中避险硐室',
x: '96',
y: '541',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '四中避险硐室', equipmentTy: '一氧化碳1000', isWarning: 0 },
{ equipmentName: '四中避险硐室', equipmentTy: '氧气', isWarning: 0 }
]
},
{
name: '四中车场',
x: '53',
y: '527',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '四中车场', equipmentTy: '一氧化碳1000', isWarning: 0 }
]
},
{
name: '一中主运输巷',
x: '185',
y: '164',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '一中主运输巷co', equipmentTy: '一氧化碳500', isWarning: 0 },
{ equipmentName: '一中主运输巷风速', equipmentTy: '风速', isWarning: 0 }
]
},
{
name: '二中主运输巷',
x: '187',
y: '296',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '二中主运输巷CO', equipmentTy: '一氧化碳1000', isWarning: 0 },
{ equipmentName: '二中主运输巷co', equipmentTy: '一氧化碳500', isWarning: 0 },
{ equipmentName: '二中主运输巷风速', equipmentTy: '风速', isWarning: 0 }
]
},
{
name: '二中中运输巷',
x: '316',
y: '303',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '二中中运输巷风速', equipmentTy: '风速', isWarning: 0 }
]
},
{
name: '三中避险硐室',
x: '93',
y: '411',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '三中避险硐室co', equipmentTy: '一氧化碳1000', isWarning: 0 },
{ equipmentName: '三中避险硐室氧气', equipmentTy: '氧气', isWarning: 0 }
]
},
{
name: '五中车场',
x: '53',
y: '686',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '五中车场一氧化碳', equipmentTy: '一氧化碳1000', isWarning: 0 }
]
},
{
name: '一中风机',
x: '145',
y: '159',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '一中风机', equipmentTy: '一氧化碳1000', isWarning: 0 },
{ equipmentName: '一中风机氧气', equipmentTy: '氧气', isWarning: 0 }
]
},
{
name: '一中西采区',
x: '341',
y: '192',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '一中西采区CO', equipmentTy: '一氧化碳1000', isWarning: 0 },
{ equipmentName: '一中西采区风速', equipmentTy: '风速', isWarning: 0 },
{ equipmentName: '一中西采区风机', equipmentTy: '开停', isWarning: 0 },
{ equipmentName: '一中西采区', equipmentTy: '氧气', isWarning: 0 }
]
},
{
name: '三中运输巷',
x: '518',
y: '439',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '三中运输巷CO', equipmentTy: '一氧化碳1000', isWarning: 0 },
{ equipmentName: '三中运输巷风速', equipmentTy: '风速', isWarning: 0 },
{ equipmentName: '三中运输巷风机', equipmentTy: '开停', isWarning: 0 },
{ equipmentName: '三中运输巷氧气', equipmentTy: '氧气', isWarning: 0 }
]
},
{
name: '三中西采',
x: '566',
y: '499',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '三中西采', equipmentTy: '一氧化碳1000', isWarning: 0 },
{ equipmentName: '三中西采', equipmentTy: '风速', isWarning: 0 },
{ equipmentName: '三中西采', equipmentTy: '氧气', isWarning: 0 }
]
},
{
name: '四中运输巷',
x: '206',
y: '559',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '四中运输巷', equipmentTy: '一氧化碳1000', isWarning: 0 },
{ equipmentName: '四中运输巷', equipmentTy: '风速', isWarning: 0 },
{ equipmentName: '四中运输巷风机', equipmentTy: '开停', isWarning: 0 },
{ equipmentName: '四中运输巷', equipmentTy: '氧气', isWarning: 0 }
]
},
{
name: '五中运输巷',
x: '166',
y: '697',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '五中运输巷', equipmentTy: '一氧化碳1000', isWarning: 0 },
{ equipmentName: '五中运输巷', equipmentTy: '风速', isWarning: 0 },
{ equipmentName: '五中运输巷风机', equipmentTy: '开停', isWarning: 0 },
{ equipmentName: '五中运输巷', equipmentTy: '氧气', isWarning: 0 }
]
},
{
name: '一中运输巷',
x: '367',
y: '168',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '一中运输巷风机', equipmentTy: '开停', isWarning: 0 }
]
},
{
name: '二中西采区',
x: '237',
y: '339',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '二中西采区CO', equipmentTy: '一氧化碳1000', isWarning: 0 },
{ equipmentName: '二中西采区风速', equipmentTy: '风速', isWarning: 0 },
{ equipmentName: '二中西采区氧气', equipmentTy: '氧气', isWarning: 0 }
]
},
{
name: '二中运输巷',
x: '415',
y: '311',
isWarning: 0,
monitorPositionList: [
{ equipmentName: '二中运输巷风机', equipmentTy: '开停', isWarning: 0 }
]
}
];
// 摄像头位置配置
export const CAMERA_POSITIONS = [
{ status: 1, x: 50, y: 150, name: '一中码头门' },
{ status: 1, x: 53, y: 277, name: '二中码头门' },
{ status: 1, x: 82, y: 289, name: '二中水泵房' },
{ status: 1, x: 113, y: 297, name: '二中避险硐室' },
{ status: 1, x: 152, y: 294, name: '二中空压机房' },
{ status: 1, x: 71, y: 411, name: '三中码头门' }
];
\ No newline at end of file
......@@ -18,7 +18,7 @@
:class="upWindowData.upWindowActive === i ? 'active' : ''"
style="cursor: pointer"
v-for="(item, i) in tableData1"
:key="i"
:key="i + 'aaa'"
@click="lookRealData(item, i)"
>
<li class="table-item">
......@@ -57,33 +57,40 @@
<span class="main-example" style="left: 0px; top: 569px">四中</span>
<span class="main-example" style="left: 0px; top: 705px">五中</span>
<!-- 设备点位 -->
<div
class="dot"
v-for="(item, i) in equipmentList"
:key="i"
:class="item.isWarning == 1 ? 'active' : ''"
:style="{ left: item.x + 'px', top: item.y + 'px' }"
>
<div class="dot1" @click="">
<div class="tip-box">
<p
v-for="(iitem, l) in item.monitorPositionList"
:key="l"
:class="iitem.isWarning == 1 ? 'active' : ''"
>
{{ iitem.equipmentName }}
<span></span>
</p>
<div v-if="checkList.includes('2')">
<div
class="dot"
v-for="(item, i) in filteredEquipmentList"
:key="i + 'bbb'"
:class="item.isWarning == 1 ? 'active' : ''"
:style="{ left: item.x + 'px', top: item.y + 'px' }"
>
<div class="dot1" @click="">
<div class="tip-box">
<p
v-for="(iitem, l) in item.monitorPositionList"
:key="l + 'ccc'"
:class="iitem.isWarning == 1 ? 'active' : ''"
>
{{ iitem.equipmentName }}
<span></span>
</p>
</div>
</div>
</div>
</div>
<div
class="camera-item"
v-for="(item, i) in cameraList"
:key="i"
:class="item.status == 0 ? 'offline' : ''"
:style="{ left: item.x + 'px', top: item.y + 'px' }"
></div>
<!--监控点位-->
<div v-if="checkList.includes('1')">
<div
class="camera-item"
v-for="(item, i) in filteredCameraList"
:key="i + 'ddd'"
:class="item.status == 0 ? 'offline' : ''"
:style="{ left: item.x + 'px', top: item.y + 'px' }"
@click="lookVideo(item, i)"
></div>
</div>
<!-- 现实设备切换按钮 -->
<div class="toggle-button">
<el-checkbox-group v-model="checkList">
......@@ -146,7 +153,7 @@
<div class="sub-con">
<span
v-for="(item, i) in rightTopLssjData.list"
:key="i"
:key="i + 'aab'"
:class="i == rightTopLssjData.mark ? 'active' : ''"
>{{ item.name }}
<p class="subscript"></p>
......@@ -165,7 +172,7 @@
<div class="sub-con">
<span
v-for="(item, i) in rightCenterLssjData.list"
:key="i"
:key="i + 'abb'"
:class="i == rightCenterLssjData.mark ? 'active' : ''"
>{{ item.name }}
<p class="subscript"></p>
......@@ -184,6 +191,14 @@
<div class="chart-box" id="chartBox"></div>
</div>
</transition>
<!--视频弹窗-->
<transition name="el-fade-in">
<div v-show="video.upWindowVisible" class="up-window video-window">
<p><span></span>{{ video.title }}</p>
<i class="el-icon-close close-button" @click="closeVideoUpWindow"></i>
<video width="800" id="player" controls></video>
</div>
</transition>
</div>
</div>
</template>
......@@ -197,12 +212,15 @@ import {
getRcData,
getDeviceStatusNum,
} from "@/api/tyler/hjjc";
import { listVideoTable } from "@/api/tyler/videoTable";
import ScrollTable from "@/components/Tyler/ScrollTable.vue";
import screenfull from "screenfull";
import vueSeamlessScroll from "vue-seamless-scroll";
import Highcharts from "highcharts/highcharts";
import highcharts3d from "highcharts/highcharts-3d";
import { EQUIPMENT_POSITIONS, CAMERA_POSITIONS } from "./hjjc-config";
highcharts3d(Highcharts);
export default {
name: "cockpit",
components: {
......@@ -227,8 +245,8 @@ export default {
autoPlay: true,
},
// 设备定位分类开关
checkList: ["2"],
// 左侧实施数据列表
checkList: ["2", "1"],
// 右侧上部分历史数据
rightTopLssjData: {
list: [
{
......@@ -247,12 +265,10 @@ export default {
],
},
],
// 右上设备轮播下标
mark: 0,
// 右上设备轮播名称
name: "",
},
// 左侧实施数据列表
// 右侧中间历史数据
rightCenterLssjData: {
list: [
{
......@@ -271,613 +287,193 @@ export default {
],
},
],
// 右上设备轮播下标
mark: 0,
// 右上设备轮播名称
name: "",
},
// 中间图片数据列表
equipmentList: [
{
isWarning: 0, //是否报警
x: 85,
y: 233,
name: "一中避险硐室",
// 监测点
monitorPositionList: [
{
equipmentName: "一中避险硐室氧气", //设备名称
equipmentTy: "", //设备类型
isWarning: 0, //是否报警
},
{
equipmentName: "一中避险硐室一氧化碳", //设备名称
equipmentTy: "", //设备类型
isWarning: 0, //是否报警
},
],
},
],
// 设备列表
equipmentList: [],
//摄像头数据
cameraList: [
{
status: 1, //是否在线
x: 50,
y: 150,
name: "一中码头门",
},
{
status: 1, //是否在线
x: 70,
y: 277,
name: "二中水泵房",
},
{
status: 1, //是否在线
x: 113,
y: 297,
name: "二中避险硐室",
},
{
status: 1, //是否在线
x: 152,
y: 294,
name: "二中空压机",
},
{
status: 1, //是否在线
x: 71,
y: 411,
name: "三中码头门",
},
],
cameraList: [],
// 视频弹窗
video: {
upWindowVisible: false,
title: "",
videoUrl: "",
},
player: null,
//highCharts配置
highChartsOption: {},
deviceStatusNum: {
//设备总数
total: 0,
//摄像头总数
cameraTotal: 0,
},
// 定时器管理
timers: {},
// ECharts实例管理
chartInstances: {},
};
},
computed: {
// 优化:计算属性替代v-if+v-for
filteredEquipmentList() {
return this.equipmentList.filter((item) => this.checkList.includes("2"));
},
filteredCameraList() {
return this.cameraList.filter((item) => this.checkList.includes("1"));
},
},
mounted() {
if (screenfull && screenfull.enabled && !screenfull.isFullscreen) {
screenfull.request();
}
// this.initEchartBox("right", this.salvProName, this.salvProValue, 28);
// this.initEchartBox("sssj", this.salvProName, this.salvProValue, 28);
getRtData().then((res) => {
this.rightTopLssjData.list = res.data || [];
this.rtPlayFun(this.rightTopLssjData);
});
getRcData().then((res) => {
this.rightCenterLssjData.list = res.data || [];
console.log(res);
this.rcPlayFun(this.rightCenterLssjData);
});
getDeviceStatus().then((res) => {
// this.equipmentList = res.data;
let dataXY = [
{
name: "三中码头门",
x: "50",
y: "406",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "三中码头门风速",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "三中码头门风速",
equipmentTy: "风速",
isWarning: 0,
},
],
},
{
name: "二中空压机房",
x: "258",
y: "299",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "二中空压机房co",
equipmentTy: "一氧化碳500",
isWarning: 0,
},
{
equipmentName: "二中空压机房风速",
equipmentTy: "风速",
isWarning: 0,
},
],
},
{
name: "东风井",
x: "856",
y: "136",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "东风井风速",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "东风井开停",
equipmentTy: "开停",
isWarning: 0,
},
],
},
{
name: "二中避险硐室",
x: "75",
y: "288",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "二中避险硐室co",
equipmentTy: "一氧化碳500",
isWarning: 0,
},
{
equipmentName: "二中避险硐室氧气",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "一中避险硐室",
x: "85",
y: "153",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "一中避险硐室co",
equipmentTy: "一氧化碳500",
isWarning: 0,
},
{
equipmentName: "一中避险硐室氧气",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "五中避险硐室",
x: "102",
y: "677",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "五中避险硐室co",
equipmentTy: "一氧化碳500",
isWarning: 0,
},
{
equipmentName: "五中避险硐室氧气",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "四中避险硐室",
x: "96",
y: "541",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "四中避险硐室",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "四中避险硐室",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "四中车场",
x: "53",
y: "527",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "四中车场",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
],
},
{
name: "一中主运输巷",
x: "185",
y: "164",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "一中主运输巷co",
equipmentTy: "一氧化碳500",
isWarning: 0,
},
{
equipmentName: "一中主运输巷风速",
equipmentTy: "风速",
isWarning: 0,
},
],
},
{
name: "二中主运输巷",
x: "187",
y: "296",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "二中主运输巷CO",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "二中主运输巷co",
equipmentTy: "一氧化碳500",
isWarning: 0,
},
{
equipmentName: "二中主运输巷风速",
equipmentTy: "风速",
isWarning: 0,
},
],
},
{
name: "二中中运输巷",
x: "316",
y: "303",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "二中中运输巷风速",
equipmentTy: "风速",
isWarning: 0,
},
],
},
{
name: "三中避险硐室",
x: "93",
y: "411",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "三中避险硐室co",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "三中避险硐室氧气",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "五中车场",
x: "53",
y: "686",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "五中车场一氧化碳",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
],
},
{
name: "一中风机",
x: "145",
y: "159",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "一中风机",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "一中风机氧气",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "一中西采区",
x: "341",
y: "192",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "一中西采区CO",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "一中西采区风速",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "一中西采区风机",
equipmentTy: "开停",
isWarning: 0,
},
{
equipmentName: "一中西采区",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "三中运输巷",
x: "518",
y: "439",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "三中运输巷CO",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "三中运输巷风速",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "三中运输巷风机",
equipmentTy: "开停",
isWarning: 0,
},
{
equipmentName: "三中运输巷氧气",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "三中西采",
x: "566",
y: "499",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "三中西采",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "三中西采",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "三中西采",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "四中运输巷",
x: "206",
y: "559",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "四中运输巷",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "四中运输巷",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "四中运输巷风机",
equipmentTy: "开停",
isWarning: 0,
},
{
equipmentName: "四中运输巷",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "五中运输巷",
x: "166",
y: "697",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "五中运输巷",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "五中运输巷",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "五中运输巷风机",
equipmentTy: "开停",
isWarning: 0,
},
{
equipmentName: "五中运输巷",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "一中运输巷",
x: "367",
y: "168",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "一中运输巷风机",
equipmentTy: "开停",
isWarning: 0,
},
],
},
{
name: "二中西采区",
x: "237",
y: "339",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "二中西采区CO",
equipmentTy: "一氧化碳1000",
isWarning: 0,
},
{
equipmentName: "二中西采区风速",
equipmentTy: "风速",
isWarning: 0,
},
{
equipmentName: "二中西采区氧气",
equipmentTy: "氧气",
isWarning: 0,
},
],
},
{
name: "二中运输巷",
x: "415",
y: "311",
isWarning: 0,
monitorPositionList: [
{
equipmentName: "二中运输巷风机",
equipmentTy: "开停",
isWarning: 0,
},
],
},
];
if (res.data && res.data.length) {
// 使用接口数据为基础,合并本地坐标数据
this.equipmentList = res.data.map((apiItem) => {
// 在dataXY中查找同名设备
const localItem = dataXY.find((xy) => xy.name === apiItem.name);
// 合并坐标数据,保留接口返回的其他字段
this.initPageData();
this.initvideoPlayer();
},
created() {
listVideoTable().then((res) => {
if (res.code === 200) {
this.cameraList = res.rows.map((el) => {
const camera = CAMERA_POSITIONS.find((c) => c.name === el.cameraName);
return {
...apiItem,
x: localItem ? localItem.x : 0, // 默认值处理
y: localItem ? localItem.y : 0,
monitorPositionList: apiItem.monitorPositionList || [],
...el,
x: camera?.x || 0,
y: camera?.y || 0,
};
});
} else {
// 降级方案:使用本地数据
}
});
//初始化获取左侧环境监测实施数据
getRealData().then((res) => {
this.tableData1 = res.data.map((el) => {
return {
...el,
value: el.value,
};
});
});
//初始化highCharts
getDeviceStatusNum().then((res) => {
if (res.code == 200) {
},
beforeDestroy() {
// 清理所有定时器
Object.values(this.timers).forEach((timer) => clearInterval(timer));
// 销毁所有图表实例
Object.values(this.chartInstances).forEach((instance) =>
instance.dispose()
);
// 清理播放器
if (this.player) {
this.player.disconnect();
this.player = null;
}
},
methods: {
// API请求优化:串行处理+错误处理
async initPageData() {
try {
// 并行请求关键数据
const [rtDataRes, rcDataRes, deviceStatusRes] = await Promise.all([
getRtData(),
getRcData(),
getDeviceStatus(),
]);
// 处理历史数据
this.rightTopLssjData.list = rtDataRes.data || [];
this.rtPlayFun(this.rightTopLssjData);
this.rightCenterLssjData.list = rcDataRes.data || [];
this.rcPlayFun(this.rightCenterLssjData);
// 处理设备状态
this.handleDeviceStatus(deviceStatusRes.data);
// 串行请求次要数据
await this.initRealData();
await this.initDeviceStatusNum();
} catch (error) {
console.error("页面初始化失败:", error);
this.$message.error("数据加载失败,请刷新页面重试");
}
},
async initRealData() {
const res = await getRealData();
this.tableData1 = res.data.map((el) => ({ ...el, value: el.value }));
},
async initDeviceStatusNum() {
const res = await getDeviceStatusNum();
if (res.code === 200) {
this.deviceStatusNum = {
total: res.data[0].online + res.data[0].offline,
cameraTotal: res.data[1].online + res.data[1].offline,
};
this.getHighChartsData(res.data);
}
});
},
created() {},
methods: {
},
handleDeviceStatus(apiData) {
if (apiData && apiData.length) {
this.equipmentList = apiData.map((apiItem) => {
const localItem = EQUIPMENT_POSITIONS.find(
(xy) => xy.name === apiItem.name
);
return {
...apiItem,
x: localItem?.x || 0,
y: localItem?.y || 0,
monitorPositionList: apiItem.monitorPositionList || [],
};
});
}
},
initvideoPlayer() {
this.player = new WebRtcStreamer("player", "http://127.0.0.1:8000");
},
// 查看视频
lookVideo(item, i) {
this.video.upWindowVisible = true;
this.video.title = item.cameraName;
this.video.videoUrl = item.cameraUrl;
this.player.connect(this.video.videoUrl);
},
closeVideoUpWindow() {
this.video.upWindowVisible = false;
},
getHighChartsData(value = []) {
this.highChartsOption = {
chart: {
type: "pie", //饼图
type: "pie",
options3d: {
enabled: true, //使用3d功能
alpha: 60, //延y轴向内的倾斜角度
enabled: true,
alpha: 60,
beta: 0,
},
backgroundColor: "rgba(64, 158, 255, 0)", // 不显示背景色
// spacingTop: -200, // 增加顶部间距
backgroundColor: "rgba(64, 158, 255, 0)",
},
legend: {
enabled: true,
align: "center",
verticalAlign: "middle", // 修正为底部对齐
layout: "vertical", // 水平布局
y: 60, // 下移图例
verticalAlign: "middle",
layout: "vertical",
y: 60,
itemStyle: {
color: "#fff",
fontSize: "12px", // 缩小字体
fontSize: "12px",
},
labelFormatter: function () {
return `${this.name}: ${this.y}`; // 在图例中显示数据
return `${this.name}: ${this.y}`;
},
},
title: {
text: "", //图表的标题文字
},
subtitle: {
text: "", //副标题文字
},
title: { text: "" },
subtitle: { text: "" },
plotOptions: {
pie: {
size: "55%", // 缩小饼图尺寸
allowPointSelect: false, // 允许点击,
size: "55%",
allowPointSelect: false,
cursor: "pointer",
innerSize: "65%", //内圆半径,
innerSize: "65%",
showInLegend: false,
center: ["50%", "34%"], // 调整饼图中心位置
depth: 15, //3d饼图的厚度,
dataLabels: {
enabled: false, // 启用数据标签
},
center: ["50%", "34%"],
depth: 15,
dataLabels: { enabled: false },
},
},
credits: {
enabled: false,
},
credits: { enabled: false },
series: [
{
type: "pie",
......@@ -888,51 +484,37 @@ export default {
name: "正常设备",
y: value[0].online,
color: "RGBA(37, 160, 238, 1)",
}, // 高数据部分
},
{
name: "异常设备",
y: value[0].offline,
color: "RGBA(252, 183, 62, 1)",
}, // 低数据部分
],
startAngle: 0, //起始角度,
label: {
show: false,
position: "outside",
formatter: "{b}:{d}%",
normal: {
show: false,
fontSize: 40,
formatter: [" {a|{b}:{d}%}"].join("\n"),
rich: {
a: {
left: 20,
padding: [0, -140, 0, -180],
},
},
},
},
],
startAngle: 0,
label: { show: false },
},
],
};
Highcharts.chart("EchartsPieLeft", this.highChartsOption);
this.highChartsOption.series[0].data = [
{ name: "在线", y: value[1].online, color: "#02CD9B" }, // 高数据部分
{ name: "离线", y: value[1].offline, color: "RGBA(252, 183, 62, 1)" }, // 低数据部分
{ name: "在线", y: value[1].online, color: "#02CD9B" },
{ name: "离线", y: value[1].offline, color: "RGBA(252, 183, 62, 1)" },
];
Highcharts.chart("EchartsPieRight", this.highChartsOption);
},
// 辅助方法:获取字段值
getItemField(item, fieldKey) {
return item[this.fieldMap[fieldKey]] || "";
},
// 初始化eChartDOM
initEchartBox(id, xData = [], yData = [], mkData = 28, step = 4, grid) {
// 销毁旧实例
if (this.chartInstances[id]) {
this.chartInstances[id].dispose();
}
let myChart = echarts.init(document.getElementById(id));
let maxData = yData.length ? Math.ceil(Math.max(...yData)) : 0;
let minData = yData.length ? Math.floor(Math.min(...yData)) : 0; // 添加向下取整
let myChart = null;
myChart = echarts.init(document.getElementById(id));
let minData = yData.length ? Math.floor(Math.min(...yData)) : 0;
let option = {
grid: grid,
xAxis: {
......@@ -943,21 +525,12 @@ export default {
axisLabel: {
show: true,
interval: step,
textStyle: {
color: "#FFFFFF", //更改坐标轴文字颜色
fontSize: 16, //更改坐标轴文字大小
},
},
axisTick: {
alignWithLabel: true,
textStyle: { color: "#FFFFFF", fontSize: 16 },
},
axisTick: { alignWithLabel: true },
splitLine: {
//网格线
lineStyle: {
type: "dashed", //设置网格线类型 dotted:虚线 solid:实线
opacity: 0.5,
},
show: true, //隐藏或显示
lineStyle: { type: "dashed", opacity: 0.5 },
show: true,
},
},
yAxis: {
......@@ -965,23 +538,14 @@ export default {
max: mkData > maxData ? mkData : maxData,
min: minData,
boundaryGap: false,
axisTick: {
alignWithLabel: true,
},
axisTick: { alignWithLabel: true },
axisLabel: {
show: true,
textStyle: {
color: "#FFFFFF", //更改坐标轴文字颜色
fontSize: 16, //更改坐标轴文字大小
},
textStyle: { color: "#FFFFFF", fontSize: 16 },
},
splitLine: {
//网格线
lineStyle: {
type: "dashed", //设置网格线类型 dotted:虚线 solid:实线
opacity: 0.5,
},
show: true, //隐藏或显示
lineStyle: { type: "dashed", opacity: 0.5 },
show: true,
},
},
series: [
......@@ -989,104 +553,71 @@ export default {
type: "line",
stack: "Total",
smooth: 0.2,
lineStyle: {
width: 2,
color: "#35B1F3",
},
lineStyle: { width: 2, color: "#35B1F3" },
markLine: {
data: [
{
name: "警戒线",
yAxis: mkData,
label: {
show: false,
},
label: { show: false },
},
],
symbol: ["none", "none"],
lineStyle: {
color: "red",
width: 2,
},
lineStyle: { color: "red", width: 2 },
},
showSymbol: false,
areaStyle: {
opacity: 0.8,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgb(55, 184, 251,0.5)",
},
{
offset: 1,
color: "rgb(55, 184, 251,0.1)",
},
{ offset: 0, color: "rgb(55, 184, 251,0.5)" },
{ offset: 1, color: "rgb(55, 184, 251,0.1)" },
]),
},
emphasis: {
focus: "series",
},
emphasis: { focus: "series" },
data: yData,
},
],
};
myChart.setOption(option);
setTimeout(() => {
myChart.resize();
}, 600);
setTimeout(() => myChart.resize(), 600);
// 保存实例引用
this.chartInstances[id] = myChart;
this.$on("hook:deactivated", () => {
if (myChart != null && myChart != "" && myChart != undefined) {
if (myChart && myChart !== "" && myChart !== undefined) {
myChart.dispose();
}
myChart = null;
});
},
// 轮播eChart
// 更改数据达到轮播效果
// 右上图表轮播
rtPlayFun(data) {
// 启动定时器,每隔 15 秒执行一次
let i = 0;
let l = 0;
let timer = null;
let grid = {
this.clearTimer("rtPlayTimer");
let i = 0,
l = 0;
const grid = {
left: "4%",
right: "5%",
bottom: "4%",
top: "7%",
containLabel: true,
};
if (!timer) {
// 页面进来的时候要触发一次
this.rightTopLssjData.mark = 0;
this.rightTopLssjData.name = data.list[0].value[0].name;
this.initEchartBox(
"sssj",
data.list[0].value[0].value.xData.data,
data.list[0].value[0].value.yData.data,
data.list[0].value[0].value.yData.alarm,
4,
grid
);
}
timer = setInterval(() => {
// 初始化首次渲染
this.updateRtChart(0, 0);
this.timers.rtPlayTimer = setInterval(() => {
if (i < data.list.length) {
if (
Array.isArray(data.list[i].value) &&
l < data.list[i].value.length
) {
this.rightTopLssjData.mark = i;
this.rightTopLssjData.name = data.list[i].value[l].name;
this.initEchartBox(
"sssj",
data.list[i].value[l].value.xData.data,
data.list[i].value[l].value.yData.data,
data.list[i].value[l].value.yData.alarm,
4,
grid
);
this.updateRtChart(i, l);
l++;
} else {
// 需要l重置,否则进不去判断i错乱
l = 0;
i++;
}
......@@ -1095,70 +626,47 @@ export default {
l = 0;
}
}, 15000);
},
this.$on("hook:activated", () => {
if (timer === null) {
// 避免重复开启定时器
timer = setInterval(() => {
if (i < data.list.length) {
if (
Array.isArray(data.list[i].value) &&
l < data.list[i].value.length
) {
this.rightTopLssjData.mark = i;
this.rightTopLssjData.name = data.list[i].value[l].tpName;
this.initEchartBox(
"sssj",
data.list[i].value[l].data.xData.data,
data.list[i].value[l].data.yData.data,
data.list[i].value[l].data.yData.alarm,
4,
grid
);
l++;
} else {
l = 0;
i++;
}
} else {
i = 0;
l = 0;
}
}, 15000);
}
});
this.$on("hook:deactivated", () => {
clearInterval(timer);
timer = null;
});
updateRtChart(i, l) {
const data = this.rightTopLssjData.list;
this.rightTopLssjData.mark = i;
this.rightTopLssjData.name = data[i].value[l].name;
this.initEchartBox(
"sssj",
data[i].value[l].value.xData.data,
data[i].value[l].value.yData.data,
data[i].value[l].value.yData.alarm,
4,
{ left: "4%", right: "5%", bottom: "4%", top: "7%", containLabel: true }
);
},
// 更改数据达到轮播效果
// 右中图表轮播
rcPlayFun(data) {
// 启动定时器,每隔 3 秒执行一次
let i = 0;
let l = 0;
let timer = null;
let grid = {
this.clearTimer("rcPlayTimer");
let i = 0,
l = 0;
const grid = {
left: "4%",
right: "5%",
bottom: "4%",
top: "7%",
containLabel: true,
};
if (!timer) {
this.rightCenterLssjData.mark = i;
this.rightCenterLssjData.name = data.list[i].value[l].name;
this.initEchartBox(
"rclssj",
data.list[i].value[l].value.xData.data,
data.list[i].value[l].value.yData.data,
data.list[i].value[l].value.yData.alarm,
4,
grid
);
}
timer = setInterval(() => {
this.rightCenterLssjData.mark = i;
this.rightCenterLssjData.name = data.list[i].value[l].name;
this.initEchartBox(
"rclssj",
data.list[i].value[l].value.xData.data,
data.list[i].value[l].value.yData.data,
data.list[i].value[l].value.yData.alarm,
4,
grid
);
this.timers.rcPlayTimer = setInterval(() => {
if (i < data.list.length) {
if (
Array.isArray(data.list[i].value) &&
......@@ -1184,60 +692,16 @@ export default {
l = 0;
}
}, 15000);
this.$on("hook:activated", () => {
if (timer === null) {
// 避免重复开启定时器
timer = setInterval(() => {
if (i < data.list.length) {
if (
Array.isArray(data.list[i].value) &&
l < data.list[i].value.length
) {
this.rightCenterLssjData.mark = i;
this.rightCenterLssjData.name = data.list[i].value[l].tpName;
this.initEchartBox(
"rclssj",
data.list[i].value[l].value.xData.data,
data.list[i].value[l].value.yData.data,
data.list[i].value[l].value.yData.alarm,
4,
grid
);
l++;
} else {
l = 0;
i++;
}
} else {
i = 0;
l = 0;
}
}, 15000);
}
});
this.$on("hook:deactivated", () => {
clearInterval(timer);
timer = null;
});
},
//自动滚动
autoScroll() {
const divData = this.$refs.scroll_List3;
// 拿到表格中承载数据的div元素
divData.scrollTop += 1;
if (
Math.round(divData.clientHeight + divData.scrollTop) + 1 >=
divData.scrollHeight
) {
// 重置table距离顶部距离
divData.scrollTop = 0;
// 清除定时器
clearTimer(timerName) {
if (this.timers[timerName]) {
clearInterval(this.timers[timerName]);
this.timers[timerName] = null;
}
this.scrolltimer3 = window.requestAnimationFrame(
this.autoScroll.bind(this)
);
},
// 查看设备24H实时数据
lookRealData(item, i) {
let grid = {
......@@ -1251,7 +715,7 @@ export default {
let xData = [];
let yData = [];
getDeviceData({ id: item.id }).then((res) => {
if (res.code == 200) {
if (res.code === 200) {
this.upWindowData.upWindowActive = i;
this.upWindowData.upWindowVisible = true;
this.upWindowData.title = item.tpName;
......@@ -1269,32 +733,26 @@ export default {
}
});
},
// 关闭弹窗
closeUpWindow() {
this.upWindowData.upWindowActive = "";
this.upWindowData.upWindowVisible = false;
this.classOption.autoPlay = true;
this.$refs.sssjControl._startMove();
},
goToSys() {
var link = this.$router.resolve({
path: "/",
});
var link = this.$router.resolve({ path: "/" });
window.open(link.href);
return;
},
// 左侧 鼠标滚动代码
handleScroll(e) {
// 改变组件内部 yPos 的值,这样html的translate(0, yPos)就会随之改变
// e.deltaY是滚动的距离
this.$refs.sssjControl.yPos = this.$refs.sssjControl.yPos - e.deltaY;
// 如果是正数 说明是往上滚
if (this.$refs.sssjControl.yPos > 0) {
this.$refs.sssjControl.yPos = 0;
return;
}
// 如果yPos超过内部实际高度的一半则重新到顶部滚动
// 一半的原因是因为组件实际上创建了两个dom,以达到无缝衔接的效果
if (
Math.abs(this.$refs.sssjControl.yPos) >
this.$refs.sssjControl.realBoxHeight / 2
......@@ -1304,80 +762,85 @@ export default {
},
},
filters: {
capitalize: function (value) {
capitalize(value) {
if (value === null || value === undefined) return "--";
console.log(value);
if (value == "" || value == "") {
if (value === "" || value === "") {
return value;
}
const parsedValue = Number(value);
if (isNaN(parsedValue)) return "--";
// 整数判断
if (Number.isInteger(parsedValue)) {
return parsedValue.toFixed(1);
}
// 小数保留两位
return parsedValue.toFixed(1);
},
},
watch: {
tableData1: {
handler() {
this.$nextTick(() => {
this.$refs.sssjControl && this.$refs.sssjControl.reset(); // 添加存在性判断
});
},
immediate: true,
return isNaN(parsedValue) ? "--" : parsedValue.toFixed(1);
},
},
};
</script>
<style lang="scss" scoped>
// 变量定义
$primary-color: #2ed5ff;
$bg-color: rgba(1, 33, 58, 0.2);
$border-radius: 8px;
$spacing: 16px;
// Mixin定义
@mixin sidebar-item {
width: 100%;
margin-bottom: $spacing;
background: linear-gradient(
180deg,
$bg-color 0%,
rgba(8, 132, 233, 0.2) 100%
);
position: relative;
border-radius: $border-radius;
&::before {
content: "";
width: 460px;
height: 4px;
position: absolute;
background: url("~@/assets/images/screen/title1.png") no-repeat center;
left: 0;
bottom: 0;
right: 0;
z-index: 20;
}
}
.por {
position: relative;
}
.sidebar-left {
transform-origin: left center;
transform: scaleX(1) perspective(610px) rotateY(5deg);
}
.sidebar-right {
transform-origin: center right;
transform: scaleX(1) perspective(610px) rotateY(-5deg);
}
/* 主体内容 */
.main-content {
display: flex;
justify-content: space-between;
padding: 0 30px;
padding-top: 160px;
padding: 0 $spacing;
padding-top: 16vh;
background: url("~@/assets/images/screen/bg12.png");
color: #fff;
min-height: 100vh;
box-sizing: border-box;
}
.histrybox {
width: 100%;
height: 100%;
display: flex;
/**均分2部分 */
.histrubox_left {
width: 50%;
height: calc(100% - 46px);
.echarts_title {
height: 25px;
text-align: center;
span {
color: rgba(42, 207, 255, 1);
font-weight: 400;
font-size: 16px;
color: #2acfff;
}
}
}
.histrubox_left,
.histrubox_right {
width: 50%;
height: calc(100% - 46px);
.echarts_title {
height: 25px;
text-align: center;
......@@ -1386,14 +849,16 @@ export default {
color: rgba(42, 207, 255, 1);
font-weight: 400;
font-size: 16px;
color: #2acfff;
color: $primary-color;
}
}
}
.chart_box {
width: 100%;
height: calc(100% - 25px);
}
.img_class {
width: 29px;
height: 25px;
......@@ -1402,7 +867,9 @@ export default {
margin-right: 12px;
margin-bottom: -7px;
}
.chart_bg {
.chart_bg,
.chart_bg_right {
position: absolute;
width: 140px;
height: 150px;
......@@ -1410,102 +877,73 @@ export default {
background-repeat: no-repeat;
background-position: cover;
background-size: 100% 100%;
// -webkit-transform: rotateX(65deg);
transform: rotateX(53deg);
left: 45px;
top: 89px;
}
.chart_bg {
left: 45px;
}
.chart_bg_right {
position: absolute;
width: 140px;
height: 150px;
background-image: url("~@/assets/images/screen/chart.png");
background-repeat: no-repeat;
background-position: cover;
background-size: 100% 100%;
// -webkit-transform: rotateX(65deg);
transform: rotateX(53deg);
left: 275px;
top: 89px;
}
.chart_number {
.chart_number,
.chart_number_right {
position: absolute;
width: 100px;
height: 100px;
top: 109px;
left: 66px;
text-align: center;
span:nth-child(1) {
font-size: 30px;
font-weight: 400;
}
}
.chart_number {
left: 66px;
}
.chart_number_right {
position: absolute;
width: 100px;
height: 100px;
top: 109px;
left: 296px;
text-align: center;
span:nth-child(1) {
font-size: 30px;
font-weight: 400;
}
}
}
/* 左右侧边栏 */
.sidebar {
width: 460px;
border-radius: 8px;
border-radius: $border-radius;
flex: 1;
// display: flex;
// flex-direction: column;
// display: grid;
grid-template-rows: repeat(3, 1fr);
gap: 2px;
margin-top: -10px;
}
.H917 {
height: 917px;
}
.H286 {
height: 286px;
}
.sidebar-item {
width: 100%;
// height: 286px;
margin-bottom: 30px;
background: linear-gradient(
180deg,
rgba(1, 33, 58, 0.2) 0%,
rgba(8, 132, 233, 0.2) 100%
);
@include sidebar-item;
position: relative;
&::before {
content: "";
width: 460px;
height: 4px;
position: absolute;
background: url("~@/assets/images/screen/bottom.png") no-repeat center;
left: 0;
bottom: 0;
right: 0;
z-index: 20;
}
.sub-title {
width: 100%;
height: 46px;
background: url("~@/assets/images/screen/title1.png") no-repeat center;
font-weight: bold;
font-family: "fangsong";
span {
position: absolute;
top: -10px;
left: 30px;
font-size: 22px;
}
.scroll-title {
position: absolute;
top: -7px;
......@@ -1515,34 +953,38 @@ export default {
color: #ffc62e;
}
}
.table-box {
height: 866px;
width: calc(100% - 4px);
.table-item {
height: 110px;
width: calc(100% - 46px);
margin: 0 auto;
border-bottom: 2px dashed rgba(100, 194, 255, 0.3);
padding-top: 9px;
.img-class {
display: block;
width: 85px;
height: 85px;
}
.device-name {
width: 100%;
font-weight: 400;
font-size: 18px;
color: #63c2ff;
font-family: Source Han Sans SC;
height: 15px;
}
.device-time {
font-weight: 400;
font-size: 16px;
color: #b4d5ea;
font-family: Source Han Sans SC;
}
.device-value {
font-family: Source Han Sans SC;
font-weight: 500;
......@@ -1560,26 +1002,29 @@ export default {
text-align: center;
}
}
.warp {
width: 100%;
height: 100%;
overflow: hidden;
font-family: "fangzhengyaoti";
ul {
list-style: none;
margin: 0 auto;
.active {
// width: 100%;
background: RGBA(2, 87, 149, 1);
}
}
.active {
background: RGBA(2, 87, 149, 1);
}
}
}
.jz {
display: flex;
align-items: center;
justify-content: center;
}
}
.jz {
display: flex;
align-items: center;
justify-content: center;
}
/* 中间主区域 */
......@@ -1592,14 +1037,16 @@ export default {
position: relative;
pointer-events: auto;
z-index: 999;
.main-example {
font-size: 18px;
color: #2ed5ff;
color: $primary-color;
line-height: 36px;
font-weight: bold;
position: absolute;
font-family: "fangsong";
}
.dot {
width: 42px;
height: 70px;
......@@ -1607,8 +1054,10 @@ export default {
top: 100px;
left: 500px;
background: url("~@/assets/images/screen/hjjc/icon8.png") no-repeat center;
.dot1 {
position: relative;
.tip-box {
width: 216px;
background: linear-gradient(0deg, #062451 0%, #09162d 100%);
......@@ -1621,6 +1070,7 @@ export default {
padding: 9px 14px 14px 14px;
z-index: 999;
display: none;
p {
font-family: Source Han Sans SC;
font-weight: 400;
......@@ -1628,32 +1078,38 @@ export default {
color: #1cd2ff;
margin: 5px 0 0 0;
text-align: left;
span {
display: none;
width: 16px;
height: 16px;
background: url("~@/assets/images/screen/hjjc/icon10.png") no-repeat
center;
margin-bottom: -3px;
}
&.active {
color: rgba(255, 43, 58, 1);
span {
display: inline-block;
width: 16px;
height: 16px;
background: url("~@/assets/images/screen/hjjc/icon10.png")
no-repeat center;
margin-bottom: -3px;
}
}
}
}
}
&:hover {
background: url("~@/assets/images/screen/hjjc/icon8_hover.png") no-repeat
center;
.tip-box {
display: block;
}
}
&.active {
background: url("~@/assets/images/screen/hjjc/icon9.png") no-repeat center;
&:hover {
background: url("~@/assets/images/screen/hjjc/icon9_hover.png")
no-repeat center;
......@@ -1670,15 +1126,18 @@ export default {
background: url("~@/assets/images/screen/hjjc/icon_normal.png") no-repeat
center;
cursor: pointer;
&:hover {
background: url("~@/assets/images/screen/hjjc/icon_hover.png") no-repeat
center;
}
&.offline {
background: url("~@/assets/images/screen/hjjc/icon_click.png") no-repeat
center;
}
}
.toggle-button {
width: 120px;
height: 90px;
......@@ -1686,9 +1145,11 @@ export default {
position: absolute;
bottom: 58px;
right: 0px;
.el-checkbox-group {
width: 100%;
height: 100%;
.el-checkbox {
margin-top: 16px;
color: #fdfeff;
......@@ -1704,17 +1165,15 @@ export default {
.distribution-map {
height: 300px;
background: rgba(8, 28, 49, 0.8);
border-radius: 8px;
border-radius: $border-radius;
}
.sub-con {
.sub-con {
height: 2em;
width: 100%;
// display: flex;
// justify-content: space-around;
// align-items: center;
font-family: "fangzhengyaoti";
span {
float: left;
margin-left: 25px;
......@@ -1725,51 +1184,56 @@ export default {
font-weight: 500;
color: rgba(179, 240, 255, 1);
text-align: center;
}
.active {
color: rgba(46, 213, 255, 1);
.subscript {
height: 19px;
width: 100%;
margin-top: 3px;
background: url("~@/assets/images/screen/hjjc/icon7.png") no-repeat
center;
&.active {
color: rgba(46, 213, 255, 1);
.subscript {
height: 19px;
width: 100%;
background: url("~@/assets/images/screen/hjjc/icon7.png") no-repeat
center;
}
}
}
}
}
.left-chart {
width: 100%;
height: 12em;
}
.sub-con-scroll-table {
width: 95%;
margin: 0 auto;
height: 83%;
overflow: hidden;
}
.custom-header {
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr 1fr 2fr;
text-align: center;
color: #2ed5ff;
color: $primary-color;
}
.custom-item {
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr 1fr 2fr;
text-align: center;
}
.custom-header2 {
width: 100%;
display: grid;
grid-template-columns: 1.5fr 2.2fr 1.3fr;
text-align: center;
color: #2ed5ff;
color: $primary-color;
height: 36px;
line-height: 36px;
color: #2ed5ff;
font-size: 16px;
font-weight: 500;
background: linear-gradient(
......@@ -1778,14 +1242,17 @@ export default {
rgba(61, 98, 147, 0.03) 100%
);
}
.warp {
height: calc(100% - 36px);
overflow: hidden;
.item {
padding-left: 0px;
margin-bottom: 0px;
margin-top: 0px;
}
.custom-item2 {
width: 100%;
height: 36px;
......@@ -1799,6 +1266,7 @@ export default {
);
margin-top: 11px;
}
.custom-item-content2 {
font-family: Source Han Sans SC;
font-size: 16px;
......@@ -1813,17 +1281,19 @@ export default {
justify-content: space-evenly;
align-items: center;
height: calc(100% - 70px);
.sub-con-r-left {
width: 127px;
height: 161px;
background: url("~@/assets/images/screen/icon3.png") no-repeat center;
background-size: 100%;
}
.sub-con-r-right {
width: 250px;
display: flex;
flex-direction: column;
// gap: 10px;
p {
display: grid;
grid-template-columns: 4fr 4fr 1fr;
......@@ -1834,9 +1304,11 @@ export default {
padding: 10px 10px;
text-align: justify;
box-sizing: border-box;
span:nth-child(2) {
color: rgba(187, 215, 234, 0.2);
}
span:nth-child(3) {
font-weight: bold;
font-size: 24px;
......@@ -1848,6 +1320,7 @@ export default {
}
}
}
.up-window {
position: absolute;
top: 50%;
......@@ -1860,6 +1333,17 @@ export default {
box-shadow: 0px 15px 11px 2px rgba(0, 20, 39, 0.31);
padding: 28px 37px;
z-index: 999;
&.video-window {
width: 900px;
height: 562px;
background: #062451;
p {
width: 820px;
}
}
p {
width: 1271px;
height: 37px;
......@@ -1872,24 +1356,26 @@ export default {
color: #ffffff;
height: 37px;
background-position-y: 9px;
span {
width: 27px;
display: inline-block;
}
}
.close-button {
font-size: 30px;
position: absolute;
top: 16px;
right: 16px;
cursor: pointer;
transition: transform 0.3s ease;
&:hover {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
-webkit-transition: -webkit-transform 1s linear;
transition: transform 1s linear;
}
}
.date-title {
height: 18px;
font-weight: 500;
......@@ -1899,6 +1385,7 @@ export default {
margin-left: 56px;
margin-top: 5px;
}
.chart-box {
width: 100%;
height: 355px;
......
......@@ -99,6 +99,9 @@ export default {
// 加载3D Tileset
Cesium.Cesium3DTileset.fromUrl("/terra_b3dms_yd/tileset.json", {
// Cesium.Cesium3DTileset.fromUrl(
// "http://localhost/terra_b3dms_yd/tileset.json",
// {
maximumScreenSpaceError: 1,
pickable: true,
})
......@@ -136,6 +139,19 @@ export default {
.then(() => {
// 添加标记点
this.addMarkers();
// 设置初始视角
this.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(
113.43050560273339, // 经度
32.542908886167876, // 纬度
200 // 高度(米),数值越小视角越近
),
orientation: {
heading: Cesium.Math.toRadians(0), // 朝向角度
pitch: Cesium.Math.toRadians(-45), // 俯仰角度
roll: 0.0,
},
});
})
.catch((error) => {
console.error("模型加载失败:", error);
......
<template>
<div class="main-content">
<div class="content">
<!--一中23线风机dom-->
<!--一中23线风机dom-->
<div
class="fengji"
v-for="(item, index) in fengjiList"
:key="index + 'fengji' + item.deviceId"
v-show="item.deviceName == '一中23线风机'"
v-show="item.deviceName == '一中23线风机'"
style="top: 74px; left: 96px"
>
<div class="fengji-title">一中23线风机</div>
<div class="fengji-title">一中23线风机</div>
<div class="fengji-content">
<img
src="../../../assets/images/screen/tfxt/device1.png"
......@@ -88,15 +88,15 @@
<div class="arrow-psition" style="top: 132px; left: 1398px">
<div class="fengji-arrow"></div>
</div>
<!--一中扇风机dom-->
<!--一中扇风机dom-->
<div
class="fengji"
v-for="(item, index) in fengjiList"
:key="index + 'yizhong' + item.deviceId"
v-show="item.deviceName == '一中扇风机'"
v-show="item.deviceName == '一中扇风机'"
style="left: 760px; top: 74px"
>
<div class="fengji-title">一中扇风机</div>
<div class="fengji-title">一中扇风机</div>
<div class="fengji-content">
<img
src="../../../assets/images/screen/tfxt/device1.png"
......@@ -152,15 +152,15 @@
<p>气体温度:{{ item.gasTemperature }}</p>
</div>
</div>
<!--东风井风机dom-->
<!--东风井风机dom-->
<div
class="fengji"
v-for="(item, index) in fengjiList"
:key="index + 'dongfeng1' + item.deviceId"
v-show="item.deviceName == '东风井风机'"
v-show="item.deviceName == '东风井风机'"
style="right: 80px; top: 74px"
>
<div class="fengji-title" style="margin-left: 50px">东风井风机</div>
<div class="fengji-title" style="margin-left: 50px">东风井风机</div>
<div class="fengji-content">
<div class="fengji-control">
<div
......@@ -279,15 +279,15 @@
<p>流速:0m³/s</p>
</div>
</div>
<!--二中扇风机dom-->
<!--二中扇风机dom-->
<div
class="fengji"
v-for="(item, index) in fengjiList"
:key="index + 'erzhong' + item.deviceId"
v-show="item.deviceName == '二中扇风机'"
v-show="item.deviceName == '二中扇风机'"
style="left: 1160px; top: 247px"
>
<div class="fengji-title" style="margin-left: 50px">二中扇风机</div>
<div class="fengji-title" style="margin-left: 50px">二中扇风机</div>
<div class="fengji-content">
<div class="fengji-control">
<div
......@@ -353,15 +353,15 @@
<div class="arrow-psition bevel" style="top: 282px; left: 1490px">
<div class="fengji-arrow"></div>
</div>
<!--三中扇风机dom-->
<!--三中扇风机dom-->
<div
class="fengji"
v-for="(item, index) in fengjiList"
:key="index + 'sanzhong' + item.deviceId"
v-show="item.deviceName == '三中扇风机'"
v-show="item.deviceName == '三中扇风机'"
style="left: 660px; top: 415px"
>
<div class="fengji-title">三中扇风机</div>
<div class="fengji-title">三中扇风机</div>
<div class="fengji-content">
<img
src="../../../assets/images/screen/tfxt/device1.png"
......@@ -400,15 +400,15 @@
<p>设定频率:{{ item.setFrequency | decimalFilter }}HZ</p>
</div>
</div>
<!--四中扇风机dom-->
<!--四中扇风机dom-->
<div
class="fengji"
v-for="(item, index) in fengjiList"
:key="index + 'sizhong' + item.deviceId"
v-show="item.deviceName == '四中扇风机'"
v-show="item.deviceName == '四中扇风机'"
style="left: 1190px; top: 583px"
>
<div class="fengji-title" style="margin-left: 50px">四中扇风机</div>
<div class="fengji-title" style="margin-left: 50px">四中扇风机</div>
<div class="fengji-content">
<div class="fengji-control">
<div
......@@ -471,15 +471,15 @@
<div class="arrow-psition bevel" style="top: 642px; left: 1068px">
<div class="fengji-arrow"></div>
</div>
<!--五中扇风机dom-->
<!--五中扇风机dom-->
<div
class="fengji"
v-for="(item, index) in fengjiList"
:key="index + 'wuzhong' + item.deviceId"
v-show="item.deviceName == '五中扇风机'"
v-show="item.deviceName == '五中扇风机'"
style="left: 400px; top: 750px"
>
<div class="fengji-title">五中扇风机</div>
<div class="fengji-title">五中扇风机</div>
<div class="fengji-content">
<img
src="../../../assets/images/screen/tfxt/device1.png"
......
......@@ -215,11 +215,11 @@
></span>
<span
class="custom-item-content custom-item-content1"
v-text="item.maintainUserName"
v-text="item.maintainState"
></span>
<span
class="custom-item-content custom-item-content1"
v-text="item.maintainState"
v-text="item.maintainUserName"
></span>
<span
class="custom-item-content custom-item-content1"
......@@ -749,12 +749,18 @@ export default {
//当月电力能耗情况chart
monthlyPowerChart() {
let myChart = echarts.init(document.getElementById("monthlyPower"));
//最大值处理
let maxValue = this.monthlyPowerData.reduce((max, item) => {
return item.value > max ? item.value : max;
}, 0);
this.monthlyPowerData.sort((a, b) => a.value - b.value);
let option = {
polar: {
radius: [30, "90%"],
},
angleAxis: {
max: 5555551,
max: maxValue,
startAngle: 90,
show: false, // 显示坐标轴
},
......@@ -789,7 +795,7 @@ export default {
type: "bar",
coordinateSystem: "polar",
stack: "a",
data: this.monthlyPowerData.map(() => 5555555), // 每个项总长度10
data: this.monthlyPowerData.map(() => maxValue), // 每个项总长度10
itemStyle: {
color: "RGBA(28, 57, 92, 0.3)",
},
......
......@@ -44,6 +44,14 @@
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
>重置</el-button
>
<el-button
icon="el-icon-download"
size="mini"
type="primary"
plain
@click="exportData"
>导出</el-button
>
</el-form-item>
</el-form>
......@@ -151,6 +159,14 @@ export default {
this.getList();
},
methods: {
/** 导出按钮操作 */
exportData() {
this.download(
"/business/pump/history/export ",
{},
`水泵运行历史数据_${new Date().getTime()}.xlsx`
);
},
/** 查询水泵历史信息列表 */
getList() {
this.loading = true;
......
......@@ -44,6 +44,14 @@
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
>重置</el-button
>
<el-button
icon="el-icon-download"
size="mini"
type="primary"
plain
@click="exportData"
>导出</el-button
>
</el-form-item>
</el-form>
......@@ -213,6 +221,14 @@ export default {
this.getList();
},
methods: {
/** 导出按钮操作 */
exportData() {
this.download(
"/business/pump/history/export ",
{},
`风机运行历史数据_${new Date().getTime()}.xlsx`
);
},
/** 查询风机基本信息列表 */
getList() {
this.loading = true;
......
......@@ -250,7 +250,7 @@ export default {
this.download(
"/business/history/export",
{},
`2502_${new Date().getTime()}.xlsx`
`监测监控设备历史数据_${new Date().getTime()}.xlsx`
);
},
},
......
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form
:model="queryParams"
ref="queryForm"
size="small"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="" prop="substationName">
<el-select v-model="queryParams.substationName" placeholder="变电站名称" clearable @change="substationNameChange">
<el-select
v-model="queryParams.substationName"
placeholder="变电站名称"
clearable
@change="substationNameChange"
>
<el-option
v-for="item in SubstationNameList"
:key="item.value"
......@@ -11,8 +23,16 @@
/>
</el-select>
</el-form-item>
<el-form-item label="" prop="eleboxName" v-if="queryParams.substationName">
<el-select v-model="queryParams.eleboxName" placeholder="电箱名称" @change="eleboxNameChange">
<el-form-item
label=""
prop="eleboxName"
v-if="queryParams.substationName"
>
<el-select
v-model="queryParams.eleboxName"
placeholder="电箱名称"
@change="eleboxNameChange"
>
<el-option
v-for="item in EleboxNameList"
:key="item.value"
......@@ -20,10 +40,17 @@
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="" prop="eleboxParameter" v-if="queryParams.eleboxName">
<el-select v-model="queryParams.eleboxParameter" placeholder="电箱参数" multiple>
<el-form-item
label=""
prop="eleboxParameter"
v-if="queryParams.eleboxName"
>
<el-select
v-model="queryParams.eleboxParameter"
placeholder="电箱参数"
multiple
>
<el-option
v-for="item in EleboxParameterList"
:key="item.value"
......@@ -31,7 +58,6 @@
:value="item.value"
/>
</el-select>
</el-form-item>
<!-- <el-form-item label="" prop="parameterData">
<el-input
......@@ -42,48 +68,84 @@
/>
</el-form-item> -->
<el-form-item label="">
<el-date-picker v-model="dateRange" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>搜索</el-button
>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
>重置</el-button
>
<el-button
icon="el-icon-download"
size="mini"
type="primary"
plain
@click="handleExport"
>导出</el-button
>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
<el-table
v-loading="loading"
:data="dataList"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="变电站名称" align="center" prop="substationName" />
<el-table-column
label="变电站名称"
align="center"
prop="substationName"
/>
<el-table-column label="电箱名称" align="center" prop="eleboxName" />
<el-table-column label="电箱参数" align="center" prop="eleboxParameter" />
<el-table-column label="参数值" align="center" prop="parameterData" />
<el-table-column label="数值单位" align="center" prop="dataUnits" />
<el-table-column label="记录时间" align="center" prop="logTime" width="180">
<el-table-column
label="记录时间"
align="center"
prop="logTime"
width="180"
>
<template slot-scope="scope">
<span>{{ parseTime(scope.row.logTime) }}</span>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
</template>
<script>
import {eleListData} from "@/api/tyler/power";
import {eleGetSubstationName,eleGetEleboxName,eleGetEleboxParameter} from "@/api/tyler/common";
import { eleListData } from "@/api/tyler/power";
import {
eleGetSubstationName,
eleGetEleboxName,
eleGetEleboxParameter,
} from "@/api/tyler/common";
export default {
export default {
name: "Data",
data() {
return {
......@@ -118,13 +180,13 @@
eleboxParameter: null,
parameterData: null,
dataUnits: null,
logTime: null
logTime: null,
},
// 表单参数
form: {},
SubstationNameList:[],
EleboxNameList:[],
EleboxParameterList:[],
SubstationNameList: [],
EleboxNameList: [],
EleboxParameterList: [],
};
},
created() {
......@@ -133,42 +195,49 @@
},
methods: {
//获取电站名称
getCommonSubstationName(){
eleGetSubstationName().then(res=>{
this.SubstationNameList = res.data
})
getCommonSubstationName() {
eleGetSubstationName().then((res) => {
this.SubstationNameList = res.data;
});
},
//选择电站名称
substationNameChange(){
substationNameChange() {
this.getCommonEleboxName();
this.queryParams.eleboxName = null;
this.queryParams.eleboxParameter = null;
},
//获取电箱名称
getCommonEleboxName(){
eleGetEleboxName({substationName:this.queryParams.substationName}).then(res=>{
this.EleboxNameList = res.data
})
getCommonEleboxName() {
eleGetEleboxName({
substationName: this.queryParams.substationName,
}).then((res) => {
this.EleboxNameList = res.data;
});
},
//选择电箱名称
eleboxNameChange(){
eleboxNameChange() {
this.getCommonEleboxParameter();
this.queryParams.eleboxParameter = null;
},
//获取电箱参数名称
getCommonEleboxParameter(){
eleGetEleboxParameter({substationName:this.queryParams.substationName,eleboxName:this.queryParams.eleboxName}).then(res=>{
this.EleboxParameterList = res.data
})
getCommonEleboxParameter() {
eleGetEleboxParameter({
substationName: this.queryParams.substationName,
eleboxName: this.queryParams.eleboxName,
}).then((res) => {
this.EleboxParameterList = res.data;
});
},
/** 查询电力系统-历史数据列表 */
getList() {
this.loading = true;
eleListData(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.dataList = response.rows;
this.total = response.total;
this.loading = false;
});
eleListData(this.addDateRange(this.queryParams, this.dateRange)).then(
(response) => {
this.dataList = response.rows;
this.total = response.total;
this.loading = false;
}
);
},
// 取消按钮
cancel() {
......@@ -184,7 +253,7 @@
eleboxParameter: null,
parameterData: null,
dataUnits: null,
logTime: null
logTime: null,
};
this.resetForm("form");
},
......@@ -201,9 +270,9 @@
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.multiple = !selection.length
this.ids = selection.map((item) => item.id);
this.single = selection.length !== 1;
this.multiple = !selection.length;
},
/** 新增按钮操作 */
handleAdd() {
......@@ -214,8 +283,8 @@
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const id = row.id || this.ids
getData(id).then(response => {
const id = row.id || this.ids;
getData(id).then((response) => {
this.form = response.data;
this.open = true;
this.title = "修改电力系统-历史数据";
......@@ -223,16 +292,16 @@
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
this.$refs["form"].validate((valid) => {
if (valid) {
if (this.form.id != null) {
updateData(this.form).then(response => {
updateData(this.form).then((response) => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addData(this.form).then(response => {
addData(this.form).then((response) => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
......@@ -244,19 +313,25 @@
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal.confirm('是否确认删除电力系统-历史数据编号为"' + ids + '"的数据项?').then(function() {
return delData(ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
this.$modal
.confirm('是否确认删除电力系统-历史数据编号为"' + ids + '"的数据项?')
.then(function () {
return delData(ids);
})
.then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
})
.catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
this.download('business/data/export', {
...this.queryParams
}, `data_${new Date().getTime()}.xlsx`)
}
}
this.download(
"/business/ele/export",
{},
`电力设备历史记录_${new Date().getTime()}.xlsx`
);
},
},
};
</script>
......@@ -2,44 +2,59 @@
<div class="">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>{{ selectedRow ? selectedRow.partName : '名称' }}</span>
<el-button style="float: right; padding: 3px 0" type="text" @click="handleAdd">添加摄像头</el-button>
<span>{{ selectedRow ? selectedRow.partName : "名称" }}</span>
<el-button
style="float: right; padding: 3px 0"
type="text"
@click="handleAdd"
>添加摄像头</el-button
>
</div>
<!-- 在这里可以添加其他逻辑,根据 selectedRow 渲染内容 -->
<el-table v-loading="loading" :data="tableList" @selection-change="handleSelectionChange">
<el-table
v-loading="loading"
:data="tableList"
@selection-change="handleSelectionChange"
>
<!-- <el-table-column type="selection" width="55" align="center" /> -->
<el-table-column label="序号" align="center" type="index" width="50"/>
<el-table-column label="序号" align="center" type="index" width="50" />
<el-table-column label="摄像头名称" align="center" prop="cameraName" />
<el-table-column label="摄像头编码" align="center" prop="cameraNum" />
<el-table-column label="摄像头通道编号" align="center" prop="cameraPassNum" />
<!-- <el-table-column label="摄像头编码" align="center" prop="cameraNum" /> -->
<!-- <el-table-column label="摄像头通道编号" align="center" prop="cameraPassNum" /> -->
<!-- <el-table-column label="摄像头ip" align="center" prop="cameraIp" /> -->
<el-table-column label="摄像头url" align="center" prop="cameraUrl" />
<el-table-column label="状态" align="center" prop="status">
<!-- <el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
<el-tag v-if="scope.row.status==1">正常</el-tag>
<el-tag v-else type="warning">异常</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
</el-table-column> -->
<el-table-column
label="操作"
align="center"
class-name="small-padding fixed-width"
>
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
>修改</el-button>
>修改</el-button
>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
......@@ -56,7 +71,10 @@
<el-input v-model="form.cameraNum" placeholder="请输入摄像头编码" />
</el-form-item>
<el-form-item label="通道编号" prop="cameraPassNum">
<el-input v-model="form.cameraPassNum" placeholder="请输入摄像头通道编号" />
<el-input
v-model="form.cameraPassNum"
placeholder="请输入摄像头通道编号"
/>
</el-form-item>
<!-- <el-form-item label="摄像头ip" prop="cameraIp">
<el-input v-model="form.cameraIp" placeholder="请输入摄像头ip" />
......@@ -64,9 +82,6 @@
<el-form-item label="摄像头url" prop="cameraUrl">
<el-input v-model="form.cameraUrl" placeholder="请输入摄像头url" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
......@@ -77,7 +92,13 @@
</template>
<script>
import {getVideoTable, listVideoTable, addVideoTable, updateVideoTable, delVideoTable } from "@/api/tyler/videoTable";
import {
getVideoTable,
listVideoTable,
addVideoTable,
updateVideoTable,
delVideoTable,
} from "@/api/tyler/videoTable";
export default {
name: "videoRight",
props: {
......@@ -119,20 +140,17 @@ export default {
cameraUrl: null,
partId: null,
cameraWeizhi: null,
flag: null
flag: null,
},
// 表单参数
form: {},
// 表单校验
rules: {
id: [
{ required: true, message: "不能为空", trigger: "blur" }
],
}
id: [{ required: true, message: "不能为空", trigger: "blur" }],
},
};
},
created() {
// this.getList();
},
watch: {
......@@ -141,7 +159,7 @@ export default {
immediate: true, // 立即执行
handler(newVal) {
if (newVal) {
this.queryParams.partId = newVal.id
this.queryParams.partId = newVal.id;
this.getList();
}
},
......@@ -151,7 +169,7 @@ export default {
/** 查询摄像头列表 */
getList() {
this.loading = true;
listVideoTable(this.queryParams).then(response => {
listVideoTable(this.queryParams).then((response) => {
this.tableList = response.rows;
this.total = response.total;
this.loading = false;
......@@ -174,7 +192,7 @@ export default {
partId: null,
remark: null,
cameraWeizhi: null,
flag: null
flag: null,
};
this.resetForm("form");
},
......@@ -190,22 +208,22 @@ export default {
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.multiple = !selection.length
this.ids = selection.map((item) => item.id);
this.single = selection.length !== 1;
this.multiple = !selection.length;
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.form.partId = this.selectedRow.id
this.form.partId = this.selectedRow.id;
this.title = "添加摄像头";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const id = row.id || this.ids
getVideoTable(id).then(response => {
const id = row.id || this.ids;
getVideoTable(id).then((response) => {
this.form = response.data;
this.open = true;
this.title = "修改摄像头";
......@@ -213,16 +231,16 @@ export default {
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
this.$refs["form"].validate((valid) => {
if (valid) {
if (this.form.id != null) {
updateVideoTable(this.form).then(response => {
updateVideoTable(this.form).then((response) => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addVideoTable(this.form).then(response => {
addVideoTable(this.form).then((response) => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
......@@ -234,14 +252,17 @@ export default {
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal.confirm('是否确认删除?').then(function() {
return delVideoTable(ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
this.$modal
.confirm("是否确认删除?")
.then(function () {
return delVideoTable(ids);
})
.then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
})
.catch(() => {});
},
},
};
</script>
\ No newline at end of file
</script>
<template>
<div class="app-container">
<el-row :gutter="20">
<splitpanes :horizontal="this.$store.getters.device === 'mobile'" class="default-theme">
<splitpanes
:horizontal="this.$store.getters.device === 'mobile'"
class="default-theme"
>
<!--部门数据-->
<pane size="16">
<el-col>
<div class="head-container">
<el-input v-model="deptName" placeholder="请输入部门名称" clearable size="small" prefix-icon="el-icon-search" style="margin-bottom: 20px" />
<el-input
v-model="deptName"
placeholder="请输入部门名称"
clearable
size="small"
prefix-icon="el-icon-search"
style="margin-bottom: 20px"
/>
</div>
<div class="head-container">
<el-tree
......@@ -26,16 +36,45 @@
<!--用户数据-->
<pane size="84">
<el-col>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="用户名称" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
<el-form
:model="queryParams"
ref="queryForm"
size="small"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="账号" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入用户名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
<el-input
v-model="queryParams.phonenumber"
placeholder="请输入手机号码"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="用户状态" clearable style="width: 240px">
<el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
<el-select
v-model="queryParams.status"
placeholder="用户状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间">
......@@ -50,67 +89,218 @@
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
<el-button
type="primary"
icon="el-icon-search"
size="mini"
@click="handleQuery"
>搜索</el-button
>
<el-button
icon="el-icon-refresh"
size="mini"
@click="resetQuery"
>重置</el-button
>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:user:add']">新增</el-button>
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['system:user:add']"
>新增</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['system:user:edit']"
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['system:user:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['system:user:remove']"
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['system:user:remove']"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="info" plain icon="el-icon-upload2" size="mini" @click="handleImport" v-hasPermi="['system:user:import']">导入</el-button>
<el-button
type="info"
plain
icon="el-icon-upload2"
size="mini"
@click="handleImport"
v-hasPermi="['system:user:import']"
>导入</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['system:user:export']">导出</el-button>
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['system:user:export']"
>导出</el-button
>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
<right-toolbar
:showSearch.sync="showSearch"
@queryTable="getList"
:columns="columns"
></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table
v-loading="loading"
:data="userList"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
<el-table-column label="账号" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
<el-table-column label="姓名" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" />
<el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible" :show-overflow-tooltip="true" />
<el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" />
<el-table-column label="状态" align="center" key="status" v-if="columns[5].visible">
<el-table-column
label="用户编号"
align="center"
key="userId"
prop="userId"
v-if="columns[0].visible"
/>
<el-table-column
label="账号"
align="center"
key="userName"
prop="userName"
v-if="columns[1].visible"
:show-overflow-tooltip="true"
/>
<el-table-column
label="姓名"
align="center"
key="nickName"
prop="nickName"
v-if="columns[2].visible"
:show-overflow-tooltip="true"
/>
<el-table-column
label="部门"
align="center"
key="deptName"
prop="dept.deptName"
v-if="columns[3].visible"
:show-overflow-tooltip="true"
/>
<el-table-column
label="手机号码"
align="center"
key="phonenumber"
prop="phonenumber"
v-if="columns[4].visible"
width="120"
/>
<el-table-column
label="状态"
align="center"
key="status"
v-if="columns[5].visible"
>
<template slot-scope="scope">
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
<el-switch
v-model="scope.row.status"
active-value="0"
inactive-value="1"
@change="handleStatusChange(scope.row)"
></el-switch>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" width="160">
<el-table-column
label="创建时间"
align="center"
prop="createTime"
v-if="columns[6].visible"
width="160"
>
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
<el-table-column
label="操作"
align="center"
width="160"
class-name="small-padding fixed-width"
>
<template slot-scope="scope" v-if="scope.row.userId !== 1">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:user:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:user:remove']">删除</el-button>
<el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:user:resetPwd', 'system:user:edit']">
<el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['system:user:edit']"
>修改</el-button
>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['system:user:remove']"
>删除</el-button
>
<el-dropdown
size="mini"
@command="(command) => handleCommand(command, scope.row)"
v-hasPermi="['system:user:resetPwd', 'system:user:edit']"
>
<el-button
size="mini"
type="text"
icon="el-icon-d-arrow-right"
>更多</el-button
>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="handleResetPwd" icon="el-icon-key" v-hasPermi="['system:user:resetPwd']">重置密码</el-dropdown-item>
<el-dropdown-item command="handleAuthRole" icon="el-icon-circle-check" v-hasPermi="['system:user:edit']">分配角色</el-dropdown-item>
<el-dropdown-item
command="handleResetPwd"
icon="el-icon-key"
v-hasPermi="['system:user:resetPwd']"
>重置密码</el-dropdown-item
>
<el-dropdown-item
command="handleAuthRole"
icon="el-icon-circle-check"
v-hasPermi="['system:user:edit']"
>分配角色</el-dropdown-item
>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</el-col>
</pane>
</splitpanes>
......@@ -121,37 +311,72 @@
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-row>
<el-col :span="12">
<el-form-item label="用户昵称" prop="nickName">
<el-input v-model="form.nickName" placeholder="请输入用户昵称" maxlength="30" />
<el-form-item label="姓名" prop="nickName">
<el-input
v-model="form.nickName"
placeholder="请输入用户昵称"
maxlength="30"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="归属部门" prop="deptId">
<treeselect v-model="form.deptId" :options="enabledDeptOptions" :show-count="true" placeholder="请选择归属部门" />
<treeselect
v-model="form.deptId"
:options="enabledDeptOptions"
:show-count="true"
placeholder="请选择归属部门"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="手机号码" prop="phonenumber">
<el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
<el-input
v-model="form.phonenumber"
placeholder="请输入手机号码"
maxlength="11"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
<el-input
v-model="form.email"
placeholder="请输入邮箱"
maxlength="50"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item v-if="form.userId == undefined" label="用户名称" prop="userName">
<el-input v-model="form.userName" placeholder="请输入用户名称" maxlength="30" />
<el-form-item
v-if="form.userId == undefined"
label="账号"
prop="userName"
>
<el-input
v-model="form.userName"
placeholder="请输入用户名称"
maxlength="30"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item v-if="form.userId == undefined" label="用户密码" prop="password">
<el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" show-password />
<el-form-item
v-if="form.userId == undefined"
label="用户密码"
prop="password"
>
<el-input
v-model="form.password"
placeholder="请输入用户密码"
type="password"
maxlength="20"
show-password
/>
</el-form-item>
</el-col>
</el-row>
......@@ -159,14 +384,24 @@
<el-col :span="12">
<el-form-item label="用户性别">
<el-select v-model="form.sex" placeholder="请选择性别">
<el-option v-for="dict in dict.type.sys_user_sex" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
<el-option
v-for="dict in dict.type.sys_user_sex"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态">
<el-radio-group v-model="form.status">
<el-radio v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
<el-radio
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.value"
>{{ dict.label }}</el-radio
>
</el-radio-group>
</el-form-item>
</el-col>
......@@ -174,15 +409,35 @@
<el-row>
<el-col :span="12">
<el-form-item label="岗位">
<el-select v-model="form.postIds" multiple placeholder="请选择岗位">
<el-option v-for="item in postOptions" :key="item.postId" :label="item.postName" :value="item.postId" :disabled="item.status == 1"></el-option>
<el-select
v-model="form.postIds"
multiple
placeholder="请选择岗位"
>
<el-option
v-for="item in postOptions"
:key="item.postId"
:label="item.postName"
:value="item.postId"
:disabled="item.status == 1"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="角色">
<el-select v-model="form.roleIds" multiple placeholder="请选择角色">
<el-option v-for="item in roleOptions" :key="item.roleId" :label="item.roleName" :value="item.roleId" :disabled="item.status == 1"></el-option>
<el-select
v-model="form.roleIds"
multiple
placeholder="请选择角色"
>
<el-option
v-for="item in roleOptions"
:key="item.roleId"
:label="item.roleName"
:value="item.roleId"
:disabled="item.status == 1"
></el-option>
</el-select>
</el-form-item>
</el-col>
......@@ -190,7 +445,11 @@
<el-row>
<el-col :span="24">
<el-form-item label="备注">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
<el-input
v-model="form.remark"
type="textarea"
placeholder="请输入内容"
></el-input>
</el-form-item>
</el-col>
</el-row>
......@@ -202,7 +461,12 @@
</el-dialog>
<!-- 用户导入对话框 -->
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
<el-dialog
:title="upload.title"
:visible.sync="upload.open"
width="400px"
append-to-body
>
<el-upload
ref="upload"
:limit="1"
......@@ -218,9 +482,19 @@
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<div class="el-upload__tip" slot="tip"><el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据</div>
<div class="el-upload__tip" slot="tip">
<el-checkbox
v-model="upload.updateSupport"
/>是否更新已经存在的用户数据
</div>
<span>仅允许导入xls、xlsx格式文件。</span>
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板</el-link>
<el-link
type="primary"
:underline="false"
style="font-size: 12px; vertical-align: baseline"
@click="importTemplate"
>下载模板</el-link
>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
......@@ -232,16 +506,25 @@
</template>
<script>
import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus, deptTreeSelect } from '@/api/system/user'
import { getToken } from '@/utils/auth'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { Splitpanes, Pane } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'
import {
listUser,
getUser,
delUser,
addUser,
updateUser,
resetUserPwd,
changeUserStatus,
deptTreeSelect,
} from "@/api/system/user";
import { getToken } from "@/utils/auth";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import { Splitpanes, Pane } from "splitpanes";
import "splitpanes/dist/splitpanes.css";
export default {
name: 'User',
dicts: ['sys_normal_disable', 'sys_user_sex'],
name: "User",
dicts: ["sys_normal_disable", "sys_user_sex"],
components: { Treeselect, Splitpanes, Pane },
data() {
return {
......@@ -260,7 +543,7 @@ export default {
// 用户表格数据
userList: null,
// 弹出层标题
title: '',
title: "",
// 所有部门树选项
deptOptions: undefined,
// 过滤掉已禁用部门树选项
......@@ -280,23 +563,23 @@ export default {
// 表单参数
form: {},
defaultProps: {
children: 'children',
label: 'label',
children: "children",
label: "label",
},
// 用户导入参数
upload: {
// 是否显示弹出层(用户导入)
open: false,
// 弹出层标题(用户导入)
title: '',
title: "",
// 是否禁用上传
isUploading: false,
// 是否更新已经存在的用户数据
updateSupport: 0,
// 设置上传的请求头部
headers: { Authorization: 'Bearer ' + getToken() },
headers: { Authorization: "Bearer " + getToken() },
// 上传的地址
url: process.env.VUE_APP_BASE_API + '/system/user/importData',
url: process.env.VUE_APP_BASE_API + "/system/user/importData",
},
// 查询参数
queryParams: {
......@@ -310,8 +593,8 @@ export default {
// 列信息
columns: [
{ key: 0, label: `用户编号`, visible: true },
{ key: 1, label: `用户名称`, visible: true },
{ key: 2, label: `用户昵称`, visible: true },
{ key: 1, label: `账号`, visible: true },
{ key: 2, label: `姓名`, visible: true },
{ key: 3, label: `部门`, visible: true },
{ key: 4, label: `手机号码`, visible: true },
{ key: 5, label: `状态`, visible: true },
......@@ -320,103 +603,123 @@ export default {
// 表单校验
rules: {
userName: [
{ required: true, message: '用户名称不能为空', trigger: 'blur' },
{ min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur' },
{ required: true, message: "用户名称不能为空", trigger: "blur" },
{
min: 2,
max: 20,
message: "用户名称长度必须介于 2 和 20 之间",
trigger: "blur",
},
],
nickName: [
{ required: true, message: "用户昵称不能为空", trigger: "blur" },
],
nickName: [{ required: true, message: '用户昵称不能为空', trigger: 'blur' }],
password: [
{ required: true, message: '用户密码不能为空', trigger: 'blur' },
{ min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' },
{ pattern: /^[^<>"'|\\]+$/, message: '不能包含非法字符:< > " \' \\ |', trigger: 'blur' },
{ required: true, message: "用户密码不能为空", trigger: "blur" },
{
min: 5,
max: 20,
message: "用户密码长度必须介于 5 和 20 之间",
trigger: "blur",
},
{
pattern: /^[^<>"'|\\]+$/,
message: "不能包含非法字符:< > \" ' \\ |",
trigger: "blur",
},
],
email: [
{
type: 'email',
message: '请输入正确的邮箱地址',
trigger: ['blur', 'change'],
type: "email",
message: "请输入正确的邮箱地址",
trigger: ["blur", "change"],
},
],
phonenumber: [
{
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
message: '请输入正确的手机号码',
trigger: 'blur',
message: "请输入正确的手机号码",
trigger: "blur",
},
],
},
}
};
},
watch: {
// 根据名称筛选部门树
deptName(val) {
this.$refs.tree.filter(val)
this.$refs.tree.filter(val);
},
},
created() {
this.getList()
this.getDeptTree()
this.getConfigKey('sys.user.initPassword').then((response) => {
this.initPassword = response.msg
})
this.getList();
this.getDeptTree();
this.getConfigKey("sys.user.initPassword").then((response) => {
this.initPassword = response.msg;
});
},
methods: {
/** 查询用户列表 */
getList() {
this.loading = true
listUser(this.addDateRange(this.queryParams, this.dateRange)).then((response) => {
this.userList = response.rows
this.total = response.total
this.loading = false
})
this.loading = true;
listUser(this.addDateRange(this.queryParams, this.dateRange)).then(
(response) => {
this.userList = response.rows;
this.total = response.total;
this.loading = false;
}
);
},
/** 查询部门下拉树结构 */
getDeptTree() {
deptTreeSelect().then((response) => {
this.deptOptions = response.data
this.enabledDeptOptions = this.filterDisabledDept(JSON.parse(JSON.stringify(response.data)))
})
this.deptOptions = response.data;
this.enabledDeptOptions = this.filterDisabledDept(
JSON.parse(JSON.stringify(response.data))
);
});
},
// 过滤禁用的部门
filterDisabledDept(deptList) {
return deptList.filter((dept) => {
if (dept.disabled) {
return false
return false;
}
if (dept.children && dept.children.length) {
dept.children = this.filterDisabledDept(dept.children)
dept.children = this.filterDisabledDept(dept.children);
}
return true
})
return true;
});
},
// 筛选节点
filterNode(value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
// 节点单击事件
handleNodeClick(data) {
this.queryParams.deptId = data.id
this.handleQuery()
this.queryParams.deptId = data.id;
this.handleQuery();
},
// 用户状态修改
handleStatusChange(row) {
let text = row.status === '0' ? '启用' : '停用'
let text = row.status === "0" ? "启用" : "停用";
this.$modal
.confirm('确认要"' + text + '""' + row.userName + '"用户吗?')
.then(function () {
return changeUserStatus(row.userId, row.status)
return changeUserStatus(row.userId, row.status);
})
.then(() => {
this.$modal.msgSuccess(text + '成功')
this.$modal.msgSuccess(text + "成功");
})
.catch(function () {
row.status = row.status === '0' ? '1' : '0'
})
row.status = row.status === "0" ? "1" : "0";
});
},
// 取消按钮
cancel() {
this.open = false
this.reset()
this.open = false;
this.reset();
},
// 表单重置
reset() {
......@@ -429,168 +732,178 @@ export default {
phonenumber: undefined,
email: undefined,
sex: undefined,
status: '0',
status: "0",
remark: undefined,
postIds: [],
roleIds: [],
}
this.resetForm('form')
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange = []
this.resetForm('queryForm')
this.queryParams.deptId = undefined
this.$refs.tree.setCurrentKey(null)
this.handleQuery()
this.dateRange = [];
this.resetForm("queryForm");
this.queryParams.deptId = undefined;
this.$refs.tree.setCurrentKey(null);
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map((item) => item.userId)
this.single = selection.length != 1
this.multiple = !selection.length
this.ids = selection.map((item) => item.userId);
this.single = selection.length != 1;
this.multiple = !selection.length;
},
// 更多操作触发
handleCommand(command, row) {
switch (command) {
case 'handleResetPwd':
this.handleResetPwd(row)
break
case 'handleAuthRole':
this.handleAuthRole(row)
break
case "handleResetPwd":
this.handleResetPwd(row);
break;
case "handleAuthRole":
this.handleAuthRole(row);
break;
default:
break
break;
}
},
/** 新增按钮操作 */
handleAdd() {
this.reset()
this.reset();
getUser().then((response) => {
this.postOptions = response.posts
this.roleOptions = response.roles
this.open = true
this.title = '添加用户'
this.form.password = this.initPassword
})
this.postOptions = response.posts;
this.roleOptions = response.roles;
this.open = true;
this.title = "添加用户";
this.form.password = this.initPassword;
});
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
const userId = row.userId || this.ids
this.reset();
const userId = row.userId || this.ids;
getUser(userId).then((response) => {
this.form = response.data
this.postOptions = response.posts
this.roleOptions = response.roles
this.$set(this.form, 'postIds', response.postIds)
this.$set(this.form, 'roleIds', response.roleIds)
this.open = true
this.title = '修改用户'
this.form.password = ''
})
this.form = response.data;
this.postOptions = response.posts;
this.roleOptions = response.roles;
this.$set(this.form, "postIds", response.postIds);
this.$set(this.form, "roleIds", response.roleIds);
this.open = true;
this.title = "修改用户";
this.form.password = "";
});
},
/** 重置密码按钮操作 */
handleResetPwd(row) {
this.$prompt('请输入"' + row.userName + '"的新密码', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
this.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
closeOnClickModal: false,
inputPattern: /^.{5,20}$/,
inputErrorMessage: '用户密码长度必须介于 5 和 20 之间',
inputErrorMessage: "用户密码长度必须介于 5 和 20 之间",
inputValidator: (value) => {
if (/<|>|"|'|\||\\/.test(value)) {
return '不能包含非法字符:< > " \' \\ |'
return "不能包含非法字符:< > \" ' \\ |";
}
},
})
.then(({ value }) => {
resetUserPwd(row.userId, value).then((response) => {
this.$modal.msgSuccess('修改成功,新密码是:' + value)
})
this.$modal.msgSuccess("修改成功,新密码是:" + value);
});
})
.catch(() => {})
.catch(() => {});
},
/** 分配角色操作 */
handleAuthRole: function (row) {
const userId = row.userId
this.$router.push('/system/user-auth/role/' + userId)
const userId = row.userId;
this.$router.push("/system/user-auth/role/" + userId);
},
/** 提交按钮 */
submitForm: function () {
this.$refs['form'].validate((valid) => {
this.$refs["form"].validate((valid) => {
if (valid) {
if (this.form.userId != undefined) {
updateUser(this.form).then((response) => {
this.$modal.msgSuccess('修改成功')
this.open = false
this.getList()
})
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addUser(this.form).then((response) => {
this.$modal.msgSuccess('新增成功')
this.open = false
this.getList()
})
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
})
});
},
/** 删除按钮操作 */
handleDelete(row) {
const userIds = row.userId || this.ids
const userIds = row.userId || this.ids;
this.$modal
.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?')
.then(function () {
return delUser(userIds)
return delUser(userIds);
})
.then(() => {
this.getList()
this.$modal.msgSuccess('删除成功')
this.getList();
this.$modal.msgSuccess("删除成功");
})
.catch(() => {})
.catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
this.download(
'system/user/export',
"system/user/export",
{
...this.queryParams,
},
`user_${new Date().getTime()}.xlsx`
)
);
},
/** 导入按钮操作 */
handleImport() {
this.upload.title = '用户导入'
this.upload.open = true
this.upload.title = "用户导入";
this.upload.open = true;
},
/** 下载模板操作 */
importTemplate() {
this.download('system/user/importTemplate', {}, `user_template_${new Date().getTime()}.xlsx`)
this.download(
"system/user/importTemplate",
{},
`user_template_${new Date().getTime()}.xlsx`
);
},
// 文件上传中处理
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true
this.upload.isUploading = true;
},
// 文件上传成功处理
handleFileSuccess(response, file, fileList) {
this.upload.open = false
this.upload.isUploading = false
this.$refs.upload.clearFiles()
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + '</div>', '导入结果', {
dangerouslyUseHTMLString: true,
})
this.getList()
this.upload.open = false;
this.upload.isUploading = false;
this.$refs.upload.clearFiles();
this.$alert(
"<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" +
response.msg +
"</div>",
"导入结果",
{
dangerouslyUseHTMLString: true,
}
);
this.getList();
},
// 提交上传文件
submitFileForm() {
this.$refs.upload.submit()
this.$refs.upload.submit();
},
},
}
</script>
\ No newline at end of file
};
</script>
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