1312 lines
35 KiB
Vue
1312 lines
35 KiB
Vue
<template>
|
||
<div id="main">
|
||
|
||
<div class="img-box" id="imghot">
|
||
<!-- @/assets/images/tunnel/img.png-->
|
||
<!-- <img :src="'data:image/png;base64,'+siteImage" style="width:3500px;height:1789px" id="imgModel" usemap="#image"-->
|
||
<!-- alt="" @click="clickHandler">-->
|
||
<div style="display: flex;justify-content: center;align-items: center;position: relative;" >
|
||
<img src="/images/img.png" alt="" class="imgModel" id="imgModel" usemap="#image" @click="handleImageClick"/>
|
||
<!-- 测量模式控制按钮 -->
|
||
<!-- <div v-if="isMeasuring" style="position: absolute; top: 20px; right: 20px; z-index: 1000;">-->
|
||
<!-- <button @click.stop="toggleMeasurementMode" -->
|
||
<!-- style="padding: 10px 20px; background-color: #409eff; color: white; border: none; border-radius: 4px; cursor: pointer; margin-right: 10px;">-->
|
||
<!-- 结束测量-->
|
||
<!-- </button>-->
|
||
<!-- <button @click.stop="clearMeasurementPoints" -->
|
||
<!-- style="padding: 10px 20px; background-color: #f56c6c; color: white; border: none; border-radius: 4px; cursor: pointer;">-->
|
||
<!-- 清除点位-->
|
||
<!-- </button>-->
|
||
<!-- </div>-->
|
||
<!-- <div v-else style="position: absolute; top: 20px; right: 20px; z-index: 1000;">-->
|
||
<!-- <button @click.stop="toggleMeasurementMode" -->
|
||
<!-- style="padding: 10px 20px; background-color: #67c23a; color: white; border: none; border-radius: 4px; cursor: pointer;">-->
|
||
<!-- 开始测量-->
|
||
<!-- </button>-->
|
||
<!-- </div>-->
|
||
</div>
|
||
<map name="image" id="image">
|
||
<area shape="poly" v-for="(item,index) in coordsList" :coords="item.coords" :key="index" alt=""
|
||
:title="item.title" style="cursor: pointer;" @click="clickHot(item.tunnelId,item.clickIndex)">
|
||
<!-- :href="'/' + item.tunnelId + '/' + siteId"-->
|
||
</map>
|
||
</div>
|
||
<div class="box-top">
|
||
<manage-btn
|
||
v-model="selectIndex"
|
||
@select="manageSelect"
|
||
:list="routeList"
|
||
v-if="showMenu"
|
||
/>
|
||
<tunnel-title v-if="showTunnelTitle" />
|
||
<div class="top-length">
|
||
<span>隧道总长度: {{ tunnelLength }}米</span>
|
||
<!-- <span>当前施工长度: {{ constructionLength }}米</span>-->
|
||
</div>
|
||
<div class="top-right">
|
||
<div class="current-site">
|
||
当前站点:<span>{{ currentSite }}</span>
|
||
<el-dropdown
|
||
trigger="click"
|
||
@command="handleChangeSite"
|
||
popper-class="dropdown-style"
|
||
>
|
||
<div class="toggle"></div>
|
||
<template #dropdown>
|
||
<el-dropdown-menu>
|
||
<el-dropdown-item
|
||
v-for="item in siteList"
|
||
:key="item.value"
|
||
:command="item"
|
||
>{{ item.label }}
|
||
</el-dropdown-item>
|
||
</el-dropdown-menu>
|
||
</template>
|
||
</el-dropdown>
|
||
<el-icon
|
||
size="50"
|
||
color="#0BE9FA"
|
||
style="margin-left: 50px; cursor: pointer"
|
||
@click="
|
||
isVisited = true;
|
||
getAlarmList();
|
||
"
|
||
>
|
||
<Bell />
|
||
</el-icon>
|
||
</div>
|
||
<div class="current-user">
|
||
你好!<span>{{ currentUser }}</span>
|
||
<span>今天是:{{ currentDate }}</span>
|
||
<div class="logout" @click="handleLogout"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- <tunnel-scene id="tunnel-box" :isedit="false" /> -->
|
||
<!-- 一进去的话应该是预览模式,所以引入这个组件1 -->
|
||
<!-- <preview-scene-->
|
||
<!-- id="tunnel-box"-->
|
||
<!-- :isedit="false"-->
|
||
<!-- :tunnelId="tunnelId"-->
|
||
<!-- :key="tunnelId"-->
|
||
<!-- :tunnelLen="tunnelLen"-->
|
||
<!-- :largeScreen="largeScreen"-->
|
||
<!-- :fanList="socketData.leftData"-->
|
||
<!-- :devRealtimeData="socketData"-->
|
||
<!-- ></preview-scene>-->
|
||
<div class="left">
|
||
<el-drawer
|
||
v-model="drawerLeft"
|
||
direction="ltr"
|
||
modal-class="modal-box"
|
||
:modal="false"
|
||
:show-close="false"
|
||
:close-on-click-modal="false"
|
||
:close-on-press-escape="false"
|
||
>
|
||
<fan-info
|
||
v-if="showFan"
|
||
:list="socketData.leftData"
|
||
:fan-data="largeScreenData"
|
||
:transducer-data="largeScreenData"
|
||
:loading="showFanLoading"
|
||
:tunnel-id="tunnelId"
|
||
/>
|
||
<used-ele
|
||
v-if="showFan"
|
||
:list="socketData.leftData"
|
||
:loading="showUsedLoading"
|
||
:ele-data="largeScreenData"
|
||
/>
|
||
</el-drawer>
|
||
<div v-if="drawerLeft" class="left-arrow" @click="closeLeft"></div>
|
||
<div v-else class="shrink-left" @click="closeLeft"></div>
|
||
</div>
|
||
<div class="right">
|
||
<el-drawer
|
||
v-model="drawerRight"
|
||
direction="rtl"
|
||
modal-class="modal-box"
|
||
:modal="false"
|
||
:show-close="false"
|
||
:close-on-click-modal="false"
|
||
:close-on-press-escape="false"
|
||
>
|
||
<wind-pressure-list
|
||
v-if="showFan"
|
||
:list="socketData.windPressure"
|
||
:win-data="largeScreenData"
|
||
:loading="showWindLoading"
|
||
/>
|
||
<air-info
|
||
v-if="showFan"
|
||
:list="socketData.sensor"
|
||
:windSpeed="socketData.windSpeed"
|
||
:air-data="largeScreenData"
|
||
/>
|
||
<bad-gas-info
|
||
v-if="showFan"
|
||
:list="socketData.sensor"
|
||
:bad-gas-data="largeScreenData"
|
||
:tunnelId="tunnelId"
|
||
:loading="showBadLoading"
|
||
/>
|
||
</el-drawer>
|
||
<div v-if="drawerRight" class="right-arrow" @click="closeRight"></div>
|
||
<div v-else class="shrink-right" @click="closeRight"></div>
|
||
</div>
|
||
<div class="switch-btn">
|
||
<div class="arrow" @click="previousBtn"></div>
|
||
<el-carousel height="150px" type="card" ref="tunnelBtn" :autoplay="false" :initial-index="initialIndex"
|
||
@change="changeTunnel">
|
||
<div class="btn">
|
||
<el-carousel-item v-for="item in tunnelList" :key="item.value">
|
||
{{ item.label }}
|
||
</el-carousel-item>
|
||
</div>
|
||
</el-carousel>
|
||
<div class="arrow right" @click="nextBtn"></div>
|
||
</div>
|
||
</div>
|
||
<div class="alarm-dialog alarm-tunnel">
|
||
<el-dialog
|
||
:close-on-click-modal="false"
|
||
v-model="isDetailVisited"
|
||
title="报警信息详情"
|
||
width="1500px"
|
||
>
|
||
<div class="detail">
|
||
<div>报警时间:</div>
|
||
{{ alarmDetail.alarmTime }}
|
||
</div>
|
||
<div class="detail">
|
||
<div>报警内容:</div>
|
||
{{ alarmDetail.alarmContent }}
|
||
</div>
|
||
</el-dialog>
|
||
</div>
|
||
<div class="alarm-tunnel">
|
||
<el-dialog
|
||
:close-on-click-modal="false"
|
||
v-model="isVisited"
|
||
title="报警信息"
|
||
width="2175px"
|
||
:modal="false"
|
||
>
|
||
<div class="left-top-icon"></div>
|
||
<div class="right-top-icon"></div>
|
||
<el-form
|
||
:model="queryParams"
|
||
inline
|
||
class="query-form"
|
||
ref="queryForm"
|
||
@submit.prevent="getAlarmList"
|
||
v-if="roleKey !== 'administrator'"
|
||
>
|
||
<el-form-item label="查阅状态" prop="lookupStatus">
|
||
<el-select
|
||
v-model="queryParams.lookupStatus"
|
||
placeholder="请选择查阅状态"
|
||
:fit-input-width="true"
|
||
:teleported="false"
|
||
clearable
|
||
filterable
|
||
>
|
||
<el-option label="已读" :value="true" />
|
||
<el-option label="未读" :value="false" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<el-button type="primary" @click="getAlarmList">搜索</el-button>
|
||
<el-button @click="handleReset">重置</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
<div class="device-table" :style="{ marginTop: roleKey === 'administrator' ? '10px' : '0' }">
|
||
<el-table stripe v-loading="loading" :empty-text="tableEmptyText"
|
||
style="background-color: #011c29;--el-table-border-color: none;"
|
||
:header-cell-style="{ backgroundColor: '#064B66', color: '#fff', fontSize: '40px', borderBottom: 'none' }"
|
||
:data="alarmList">
|
||
<el-table-column prop="tunnelName" label="隧道名称" align="center" width="400px" />
|
||
<el-table-column prop="alarmContent" label="告警信息" align="center" />
|
||
<el-table-column prop="alarmTime" label="告警时间" align="center" width="480px" />
|
||
<el-table-column prop="lookupStatus" label="查阅状态" align="center" width="200px"
|
||
v-if="roleKey !== 'administrator'">
|
||
<template #default="scope">
|
||
<el-tag :type="scope.row.lookupStatus ? 'success' : 'warning'"
|
||
>{{ scope.row.lookupStatus ? "已读" : "未读" }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" align="center" width="300px">
|
||
<template #default="scope">
|
||
<el-button
|
||
type="primary"
|
||
size="mini"
|
||
style="font-weight: bold"
|
||
@click="handleView(scope.row)"
|
||
link
|
||
>详情
|
||
</el-button>
|
||
<el-button
|
||
type="danger"
|
||
size="mini"
|
||
v-if="roleKey !== 'administrator'"
|
||
@click="handleDelete(scope.row)"
|
||
link
|
||
>删除
|
||
</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<div
|
||
class="pagination"
|
||
:style="{ bottom: roleKey === 'administrator' ? '-7px' : '0' }"
|
||
>
|
||
<el-pagination
|
||
background
|
||
v-model:current-page="pageInfo.pageNum"
|
||
v-model:page-size="pageInfo.pageSize"
|
||
:total="total" :pager-count="8"
|
||
prev-text="上一页"
|
||
next-text="下一页"
|
||
layout="prev, pager, next"
|
||
@current-change="handleCurrentChange"
|
||
:hide-on-single-page="true"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div class="left-bottom-icon"></div>
|
||
<div class="right-bottom-icon"></div>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import PreviewScene from "@/components/content/tunnelScene/PreviewScene.vue";
|
||
import FanInfo from "@/components/content/fanInfo/FanInfo.vue";
|
||
import UsedEle from "@/components/content/usedEle/UsedEle.vue";
|
||
import WindPressureList from "@/components/content/windPressure/WindPressureList.vue";
|
||
import AirInfo from "@/components/content/airInfo/AirInfo.vue";
|
||
import BadGasInfo from "@/components/content/badGasInfo/BadGasInfo.vue";
|
||
import ManageBtn from "@/components/manageBtn/index.vue";
|
||
import TunnelTitle from "@/components/tunnelTitle/index.vue";
|
||
import { dateFormat } from "@/utils/date.js";
|
||
import { getToken } from "@/utils/auth";
|
||
import { useAuthStore } from "@/store/userstore.js";
|
||
import {
|
||
getLargeScreen,
|
||
getLargeScreenInfo,
|
||
getTunnelBySiteId,
|
||
getAlarmInfo,
|
||
deleteAlarmSate,
|
||
getAlarmDetail,
|
||
updateAlarmState,
|
||
} from "@/api/largeScreen";
|
||
import { ElMessage, ElMessageBox } from "element-plus";
|
||
import { getUserInfo } from "@/api/login";
|
||
import { initSceneData } from "@/api/tunnelScene";
|
||
import { getTunnelList } from "@/api/tunnelManage";
|
||
import { debounce } from "lodash";
|
||
const authStore = useAuthStore();
|
||
const router = useRouter();
|
||
const previewId = reactive(router.currentRoute.value.params.tunnelId);
|
||
const siteId = reactive(router.currentRoute.value.params.siteId);
|
||
const tunnelIdFlag = reactive(router.currentRoute.value.params.tunnelId);
|
||
const selectIndex = ref(-1);
|
||
const isVisited = ref(false);
|
||
const isDetailVisited = ref(false);
|
||
const showFan = ref(false);
|
||
const drawerLeft = ref(true);
|
||
const showTunnelTitle = ref(true);
|
||
const loading = ref(false);
|
||
const tableEmptyText = ref("加载中~");
|
||
const initialIndex = ref(0);
|
||
const showFanLoading = ref(0);
|
||
const showUsedLoading = ref(0);
|
||
const showWindLoading = ref(0);
|
||
const showBadLoading = ref(0);
|
||
const drawerRight = ref(true);
|
||
const showMenu = ref(false);
|
||
const currentSiteId = ref(0);
|
||
const currentSite = ref("");
|
||
const siteList = ref([]);
|
||
const alarmList = ref([]);
|
||
const alarmDetail = ref([]);
|
||
const totalTunnelList = ref([]);
|
||
const currentUser = ref("");
|
||
const currentUserId = ref(0);
|
||
const currentDate = ref(dateFormat());
|
||
const tunnelBtn = ref();
|
||
const tunnelList = ref([]);
|
||
const tunnelId = ref(0);
|
||
const tunnelLength = ref(0);
|
||
const constructionLength = ref(0);
|
||
const routeList = ref([]);
|
||
let socket = reactive("");
|
||
let pattern = reactive(new RegExp("[A-Za-z]+"));
|
||
let isTunnel = reactive(false);
|
||
const coordsList = ref([
|
||
{
|
||
//厂房
|
||
clickIndex:0,
|
||
tunnelId: 98,
|
||
title: '厂房',
|
||
coords: '127,418,165,415,175,440,136,556,98,558,106,478',
|
||
}, {
|
||
//2#尾水
|
||
clickIndex:2,
|
||
tunnelId: 1,
|
||
title: '2#尾水隧洞',
|
||
coords: '283,489,840,170,886,67,869,64,831,155,272,471'
|
||
}, {
|
||
//5#支洞
|
||
clickIndex:1,
|
||
tunnelId: 109,
|
||
title: '5#支洞',
|
||
coords: '847,74,833,64,819,28,820,79,842,87'
|
||
}
|
||
])
|
||
const btnList = ref([
|
||
{
|
||
route: "/site",
|
||
icon: "sp_icon_zdgl.png",
|
||
name: "站点管理",
|
||
},
|
||
{
|
||
route: "/tunnel",
|
||
icon: "sp_icon_sdgl.png",
|
||
name: "隧道管理",
|
||
},
|
||
{
|
||
route: "/user",
|
||
icon: "sp_icon_yhgl.png",
|
||
name: "用户管理",
|
||
},
|
||
// {
|
||
// route: '/system',
|
||
// icon: 'sp_icon_xtgl.png',
|
||
// name: '系统管理'
|
||
// },
|
||
{
|
||
route: '/simulate',
|
||
icon: 'sp_icon_mngl.png',
|
||
name: '模拟仿真'
|
||
},
|
||
]);
|
||
const serialNumber = ref("");
|
||
const roleKey = ref("");
|
||
|
||
// 测量模式相关变量
|
||
const isMeasuring = ref(false);
|
||
const measurementPoints = ref([]);
|
||
|
||
|
||
let token = getToken();
|
||
let send = {
|
||
type: "ping",
|
||
};
|
||
const pageInfo = reactive({
|
||
pageNum: 1,
|
||
pageSize: 40,
|
||
});
|
||
const queryForm = ref();
|
||
const total = ref(10);
|
||
const largeScreenData = ref(null);
|
||
const socketData = reactive({
|
||
leftData: [],
|
||
windPressure: [],
|
||
sensor: [],
|
||
windSpeed: [],
|
||
});
|
||
let tunnelLen = computed(() => tunnelLength);
|
||
const queryParams = reactive({
|
||
equipmentId: "",
|
||
lookupStatus: "",
|
||
});
|
||
onMounted(() => {
|
||
getList();
|
||
getUser();
|
||
getOtherInfo();
|
||
nextTick(() => {
|
||
showFan.value = true;
|
||
});
|
||
});
|
||
|
||
|
||
function convertCoordsToArray(coordsArray) {
|
||
return coordsArray.map(point => `${point.x},${point.y}`).join(',');
|
||
}
|
||
|
||
// 示例使用:
|
||
const coordsData = [
|
||
{ x: 163, y: 487 },
|
||
{ x: 153, y: 483 },
|
||
{ x: 217, y: 480 },
|
||
{ x: 170, y: 644 },
|
||
{ x: 111, y: 640 },
|
||
{ x: 145, y: 483 }
|
||
];
|
||
|
||
const result = convertCoordsToArray(coordsData);
|
||
console.log(result);
|
||
// 输出: "163,487,153,483,217,480,170,644,111,640,145,483"
|
||
const clickHot = (id,index) => {
|
||
console.log('点击热区===============')
|
||
initialIndex.value=index
|
||
changeTunnel(index)
|
||
}
|
||
const changeName = (id) => {
|
||
for (let item of equipmentOption.value) {
|
||
if (item.value === id) {
|
||
return item.label;
|
||
}
|
||
}
|
||
return "";
|
||
};
|
||
const handleReset = () => {
|
||
queryForm.value.resetFields();
|
||
getAlarmList();
|
||
};
|
||
//点击页码进行分页功能
|
||
const handleCurrentChange = (val) => {
|
||
pageInfo.pageNum = val;
|
||
getAlarmList();
|
||
};
|
||
const handleDelete = (row) => {
|
||
ElMessageBox.confirm(`确认删除该报警信息吗?`, "系统提示", {
|
||
type: "warning",
|
||
closeOnClickModal: false,
|
||
}).then(() => {
|
||
deleteAlarmSate(row.alarmId).then((res) => {
|
||
if (res.code === 1000) {
|
||
ElMessage.success("删除成功");
|
||
getAlarmList();
|
||
}
|
||
});
|
||
});
|
||
};
|
||
//查看报警信息详情
|
||
const handleView = (row) => {
|
||
getAlarmDetail(row.alarmId).then((res) => {
|
||
if (res.code === 1000) {
|
||
isDetailVisited.value = true;
|
||
alarmDetail.value = res.data;
|
||
if (roleKey.value !== "administrator") {
|
||
if (!row.lookupStatus) {
|
||
handleChangeState(row);
|
||
}
|
||
}
|
||
}
|
||
});
|
||
};
|
||
const handleChangeState = (row) => {
|
||
updateAlarmState([
|
||
{
|
||
alarmId: row.alarmId,
|
||
lookupStatus: true,
|
||
userId: currentUserId.value,
|
||
},
|
||
]).then((res) => {
|
||
if (res.code === 1000) {
|
||
// ElMessage.success(res.msg);
|
||
getAlarmList();
|
||
} else {
|
||
// ElMessage.error(res.msg);
|
||
}
|
||
});
|
||
};
|
||
const getAlarmList = () => {
|
||
loading.value = true;
|
||
getAlarmInfo({
|
||
tunnelId: tunnelId.value,
|
||
lookupStatus: queryParams.lookupStatus,
|
||
...pageInfo,
|
||
}).then((res) => {
|
||
if (res.code === 1000) {
|
||
loading.value = false;
|
||
if (res.data.rows.length === 0) {
|
||
tableEmptyText.value = "暂无数据~";
|
||
} else {
|
||
tableEmptyText.value = "";
|
||
}
|
||
alarmList.value = res.data.rows;
|
||
total.value = res.data.total;
|
||
}
|
||
});
|
||
};
|
||
const getUser = () => {
|
||
getUserInfo().then((res) => {
|
||
currentUser.value = res.data.user.userName;
|
||
currentUserId.value = res.data.user.userId;
|
||
roleKey.value = res.data.roles[0];
|
||
localStorage.setItem("roleKey", res.data.roles[0]);
|
||
localStorage.setItem("userId", currentUserId.value);
|
||
});
|
||
};
|
||
|
||
const getOtherInfo = () => {
|
||
getLargeScreenInfo().then((res) => {
|
||
if (res?.code === 1000) {
|
||
let routeArr = [];
|
||
res.data.routeList.push('/simulate')
|
||
res.data.routeList.forEach((item) => {
|
||
for (let btn of btnList.value) {
|
||
if (item === btn.route) {
|
||
routeArr.push(btn);
|
||
}
|
||
}
|
||
});
|
||
routeList.value = routeArr;
|
||
showMenu.value = true;
|
||
siteList.value = res.data.siteOption;
|
||
tunnelList.value = res.data.tunnelOption;
|
||
|
||
if (siteId) {
|
||
currentSiteId.value = siteId;
|
||
currentSite.value = localStorage.getItem("site");
|
||
showTunnelTitle.value = false;
|
||
nextTick(() => {
|
||
showTunnelTitle.value = true;
|
||
});
|
||
getTunnel(siteId);
|
||
} else {
|
||
getTunnel(res.data.siteOption[0].value);
|
||
currentSiteId.value = res.data.siteOption[0].value;
|
||
currentSite.value = res.data.siteOption[0].label;
|
||
localStorage.setItem("site", currentSite.value);
|
||
localStorage.setItem("currentSiteId", currentSiteId.value);
|
||
}
|
||
}
|
||
});
|
||
};
|
||
const getScreenInfo = (id) => {
|
||
if (id) {
|
||
tunnelId.value = id;
|
||
// equipmentOption.value = []
|
||
getLargeScreen(id).then((res) => {
|
||
if (res?.code === 1000) {
|
||
if (res.data.frequencyChangerList.length !== 0) {
|
||
showFanLoading.value = 0;
|
||
} else {
|
||
showFanLoading.value = 1;
|
||
}
|
||
if (res.data.windPressureSensorList.length !== 0) {
|
||
showWindLoading.value = 0;
|
||
} else {
|
||
showWindLoading.value = 1;
|
||
}
|
||
if (res.data.sensorList.length !== 0) {
|
||
// res.data.sensorList.forEach((item) => {
|
||
// option = {
|
||
// value: item.equipmentId,
|
||
// label: item.equipmentName,
|
||
// }
|
||
// equipmentOption.value.push(option)
|
||
// })
|
||
res.data.sensorList.forEach((item) => {
|
||
if (
|
||
item.equipmentType === "dust" ||
|
||
item.equipmentType === "carbonDioxide" ||
|
||
item.equipmentType === "carbonMonoxide" ||
|
||
item.equipmentType === "hydrogenSulfide" ||
|
||
item.equipmentType === "sulfurDioxide" ||
|
||
item.equipmentType === "sulfurMonoxide" ||
|
||
item.equipmentType === "nitrogenDioxide"
|
||
) {
|
||
showBadLoading.value = 0;
|
||
} else {
|
||
showBadLoading.value = 1;
|
||
}
|
||
});
|
||
} else {
|
||
showBadLoading.value = 1;
|
||
}
|
||
largeScreenData.value = res.data;
|
||
} else {
|
||
ElMessage.warning(res.msg);
|
||
}
|
||
});
|
||
initSceneData(id).then((res) => {
|
||
tunnelLength.value = res.data.tunnelLength;
|
||
constructionLength.value = res.data.constructionLength;
|
||
// serialNumber.value = res.data.serialNumber.slice(0, -2)
|
||
serialNumber.value = res.data.serialNumberPrefix;
|
||
initWebSocket();
|
||
});
|
||
}
|
||
};
|
||
//这里可以获取隧道简称
|
||
const getList = () => {
|
||
getTunnelList({
|
||
siteId: siteId,
|
||
}).then((res) => {
|
||
if (res.code === 1000) {
|
||
if (res.data.rows.length !== 0) {
|
||
isTunnel = true;
|
||
totalTunnelList.value = res.data.rows;
|
||
} else {
|
||
isTunnel = false;
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
let largeScreen = computed(() => largeScreenData);
|
||
const getTunnel = (id) => {
|
||
getTunnelBySiteId(id).then((res) => {
|
||
if (res?.code === 1000) {
|
||
if (res.data.length === 0) {
|
||
if (isTunnel) {
|
||
ElMessage.warning("该站点下没有隧道可展示, 请添加设备后再试!");
|
||
} else {
|
||
ElMessage.warning("该站点下没有隧道, 请新增隧道后再试!");
|
||
}
|
||
} else {
|
||
if (!pattern.test(previewId)) {
|
||
getScreenInfo(previewId);
|
||
tunnelList.value.forEach((item, index) => {
|
||
if (item.value == previewId) {
|
||
initialIndex.value = index;
|
||
tunnelBtn.value.setActiveItem(index);
|
||
}
|
||
});
|
||
} else {
|
||
// console.info("🚀 ~method: tunnelList.value -----", tunnelList.value)
|
||
// tunnelList.value = res.data;
|
||
getScreenInfo(res.data[0]?.value);
|
||
}
|
||
}
|
||
}
|
||
});
|
||
};
|
||
const changeTunnel = (e) => {
|
||
// console.info("🚀 ~method:'tunnelList.value' -----", tunnelList.value)
|
||
console.info("🚀 ~method:'changeTunnel' -----", e)
|
||
if(socket){
|
||
socket.close()
|
||
}
|
||
let newObj = {}
|
||
tunnelList.value.forEach((item, index) => {
|
||
if (index == e) {
|
||
newObj = item;
|
||
}
|
||
});
|
||
// console.info("🚀 ~method:changeTunnel -----", newObj)
|
||
showFan.value = false;
|
||
showBadLoading.value = 0;
|
||
showWindLoading.value = 0;
|
||
showFanLoading.value = 0;
|
||
// showUsedLoading.value = 0
|
||
pageInfo.pageNum = 1;
|
||
getScreenInfo(newObj.value);
|
||
nextTick(() => {
|
||
showFan.value = true;
|
||
});
|
||
};
|
||
const manageSelect = (name) => {
|
||
if (name === "站点管理") {
|
||
if (currentUserId.value) {
|
||
router.push("/site/" + currentUserId.value + "/" + currentSiteId.value);
|
||
}
|
||
} else if (name === "隧道管理") {
|
||
if (currentSiteId.value && currentUserId.value) {
|
||
router.push(
|
||
"/tunnel/" +
|
||
localStorage.getItem("currentSiteId") +
|
||
"/byHome/" +
|
||
currentUserId.value
|
||
);
|
||
}
|
||
} else if (name === "用户管理") {
|
||
if (currentSiteId.value) {
|
||
router.push("/user/" + localStorage.getItem("currentSiteId"));
|
||
}
|
||
} else if (name === "模拟仿真") {
|
||
if (tunnelId.value) {
|
||
router.push("/simulate/tunnel/list");
|
||
}
|
||
}
|
||
if(socket){
|
||
socket.close()
|
||
}
|
||
};
|
||
const handleChangeSite = debounce((item) => {
|
||
if(socket){
|
||
socket.close()
|
||
}
|
||
currentSite.value = item.label
|
||
currentSiteId.value = item.value
|
||
getTunnel(item.value)
|
||
showFan.value = false
|
||
nextTick(() => {
|
||
showFan.value = true;
|
||
});
|
||
localStorage.setItem("site", currentSite.value);
|
||
localStorage.setItem("currentSiteId", currentSiteId.value);
|
||
if (tunnelIdFlag) {
|
||
router.push("/" + tunnelIdFlag + "/" + currentSiteId.value);
|
||
}
|
||
showTunnelTitle.value = false;
|
||
nextTick(() => {
|
||
showTunnelTitle.value = true;
|
||
});
|
||
}, 100);
|
||
const closeLeft = () => {
|
||
drawerLeft.value = !drawerLeft.value;
|
||
};
|
||
const closeRight = () => {
|
||
drawerRight.value = !drawerRight.value;
|
||
};
|
||
const handleLogout = () => {
|
||
ElMessageBox.confirm(`确认退出登录吗`, "系统提示", {
|
||
confirmButtonText: "确定",
|
||
cancelButtonText: "取消",
|
||
type: "warning",
|
||
}).then(() => {
|
||
authStore.userLogout();
|
||
router.push("/login");
|
||
});
|
||
};
|
||
const previousBtn = () => {
|
||
tunnelBtn.value.prev();
|
||
};
|
||
const nextBtn = () => {
|
||
tunnelBtn.value.next();
|
||
};
|
||
|
||
const initWebSocket = () => {
|
||
// let wsUrl = `ws://192.168.31.176:9000/websocket/equipment/${token}/${serialNumber.value}`
|
||
let wsUrl = `ws://tunnel.feashow.com/api/wstunnel/websocket/equipment/${token}/${serialNumber.value}`;
|
||
// let wsUrl = import.meta.env.VITE_BASE_WSURL+`/${token}/${serialNumber.value}`;
|
||
// let wsUrl = `ws://clay.frp.feashow.cn/wstunnel/websocket/equipment/${token}/${serialNumber.value}`;
|
||
socket = new WebSocket(wsUrl);
|
||
//连接发生错误的回调方法
|
||
socket.onerror = function () {
|
||
console.log("ws连接发生错误");
|
||
};
|
||
//连接成功建立的回调方法
|
||
socket.onopen = function () {
|
||
// console.log("ws连接成功");
|
||
};
|
||
//接收到消息的回调方法
|
||
socket.onmessage = function (event) {
|
||
// console.log("服务器返回的信息: ", JSON.parse(event.data));
|
||
const type = JSON.parse(event.data).type;
|
||
const data = JSON.parse(event.data).data;
|
||
if (type === "equipment") {
|
||
data.forEach((item) => {
|
||
if (item.typeKey === "frequency") {
|
||
socketData.leftData = data;
|
||
// console.log(socketData.leftData);
|
||
} else if (item.typeKey === "windPressure") {
|
||
socketData.windPressure = data;
|
||
} else if (item.typeKey === "sensor") {
|
||
socketData.sensor = data;
|
||
} else if (item.typeKey === "windSpeed") {
|
||
socketData.windSpeed = data;
|
||
}
|
||
});
|
||
}
|
||
};
|
||
//连接关闭的回调方法
|
||
socket.onclose = function () {
|
||
console.log("ws连接关闭");
|
||
// initWebSocket()
|
||
};
|
||
setInterval(() => {
|
||
socket.send(JSON.stringify(send));
|
||
}, 30000);
|
||
};
|
||
|
||
// 测量模式相关函数
|
||
const toggleMeasurementMode = () => {
|
||
isMeasuring.value = !isMeasuring.value;
|
||
if (!isMeasuring.value) {
|
||
// 退出测量模式时输出坐标数组
|
||
console.log('测量点坐标数组:', measurementPoints.value);
|
||
// 格式化输出坐标点(符合项目规范)
|
||
const formattedCoords = measurementPoints.value.map(point => `${point.x},${point.y}`).join(',');
|
||
console.log('格式化坐标点:', formattedCoords);
|
||
|
||
// 显示提示信息
|
||
ElMessage.success(`测量完成,共记录${measurementPoints.value.length}个点`);
|
||
} else {
|
||
// 进入测量模式时清空之前的坐标
|
||
measurementPoints.value = [];
|
||
|
||
// 清除之前的视觉反馈点
|
||
const points = document.querySelectorAll('.measurement-point');
|
||
points.forEach(point => point.remove());
|
||
|
||
// 显示提示信息
|
||
ElMessage.info('已进入测量模式,请在图片上点击记录坐标点');
|
||
}
|
||
};
|
||
|
||
const handleImageClick = (event) => {
|
||
// 如果不是测量模式,执行原来的getInfo逻辑
|
||
if (!isMeasuring.value) {
|
||
getInfo();
|
||
return;
|
||
}
|
||
|
||
// 获取图片元素和点击位置
|
||
const imgElement = document.getElementById('imgModel');
|
||
const rect = imgElement.getBoundingClientRect();
|
||
|
||
// 计算相对于图片的坐标
|
||
const x = event.clientX - rect.left;
|
||
const y = event.clientY - rect.top;
|
||
|
||
// 添加坐标到数组
|
||
measurementPoints.value.push({ x: Math.round(x), y: Math.round(y) });
|
||
|
||
// 在点击位置创建一个视觉反馈点
|
||
const pointElement = document.createElement('div');
|
||
pointElement.style.position = 'absolute';
|
||
pointElement.style.left = (event.clientX - 2) + 'px';
|
||
pointElement.style.top = (event.clientY - 2) + 'px';
|
||
pointElement.style.width = '4px';
|
||
pointElement.style.height = '4px';
|
||
pointElement.style.backgroundColor = 'red';
|
||
pointElement.style.borderRadius = '50%';
|
||
pointElement.style.zIndex = '9999';
|
||
pointElement.className = 'measurement-point';
|
||
document.body.appendChild(pointElement);
|
||
|
||
// 显示当前点数
|
||
ElMessage.info(`已记录${measurementPoints.value.length}个点`);
|
||
};
|
||
|
||
// 清除测量点
|
||
const clearMeasurementPoints = () => {
|
||
measurementPoints.value = [];
|
||
// 清除视觉反馈点
|
||
const points = document.querySelectorAll('.measurement-point');
|
||
points.forEach(point => point.remove());
|
||
ElMessage.info('已清除所有测量点');
|
||
};
|
||
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
.alarm-tunnel .device-table{
|
||
|
||
height: 1158px!important;
|
||
overflow-y: scroll;
|
||
.el-dialog__body{
|
||
height: 1158px!important;
|
||
overflow-y: scroll;
|
||
}
|
||
&::-webkit-scrollbar {
|
||
width: 16px;
|
||
}
|
||
|
||
// 滚动条轨道
|
||
&::-webkit-scrollbar-track {
|
||
background: transparent;
|
||
border-radius: 2px;
|
||
}
|
||
|
||
// 小滑块
|
||
&::-webkit-scrollbar-thumb {
|
||
background: rgb(8, 183, 184);
|
||
border-radius: 10px;
|
||
}
|
||
}
|
||
.el-drawer__header {
|
||
display: none;
|
||
}
|
||
|
||
.el-drawer__body {
|
||
padding: 160px 68px 0 68px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.el-dropdown__popper.el-popper {
|
||
background: transparent;
|
||
//border: none;
|
||
border: 1px solid #0e7daa;
|
||
border-radius: 10px;
|
||
}
|
||
|
||
.dropdown-style {
|
||
padding: 20px;
|
||
margin-left: 50px;
|
||
width: 150px;
|
||
background: rgba(7, 35, 72, 0.9);
|
||
|
||
.el-scrollbar__wrap {
|
||
.el-dropdown__list {
|
||
.el-dropdown-menu {
|
||
background-color: rgba(7, 35, 72, 0.9);
|
||
border-radius: 10px;
|
||
padding: 5px;
|
||
|
||
.el-dropdown-menu__item {
|
||
color: #ffffff;
|
||
//border:none;
|
||
padding: 5px;
|
||
|
||
border-bottom: 1px solid #05feff;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
}
|
||
}
|
||
|
||
.el-dropdown-menu__item.hover,
|
||
.el-dropdown-menu__item:hover {
|
||
background-color: transparent !important;
|
||
color: #f7b500;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.is-light {
|
||
background: rgba(7, 35, 72, 0.9);
|
||
}
|
||
}
|
||
</style>
|
||
|
||
<style lang="scss" scoped>
|
||
#main {
|
||
height: 100%;
|
||
width: 100%;
|
||
//background-color: #072348;
|
||
background-image: url('/images/background/background.png');
|
||
|
||
#tunnel-box {
|
||
height: 100%;
|
||
}
|
||
.img-box {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
.imgModel{
|
||
width: 1040px;
|
||
height: 646px;
|
||
}
|
||
}
|
||
|
||
.alarm-dialog {
|
||
:deep(.el-dialog) {
|
||
height: auto !important;
|
||
margin: 820px auto 0 auto;
|
||
}
|
||
}
|
||
|
||
:deep(.el-table__body-wrapper) {
|
||
height: 90px;
|
||
}
|
||
|
||
:deep(.el-table--fit) {
|
||
width: auto;
|
||
//height: 600px;
|
||
background-color: transparent !important;
|
||
|
||
.el-loading-mask {
|
||
background: rgba(6, 34, 71, 0.78);
|
||
|
||
.el-loading-spinner {
|
||
.circular {
|
||
width: 150px;
|
||
height: 150px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
:deep(.el-table__empty-block) {
|
||
height: 200px !important;
|
||
|
||
//display: none;
|
||
.el-table__empty-text {
|
||
font-size: 60px;
|
||
color: #08b7b8;
|
||
}
|
||
}
|
||
|
||
.query-form {
|
||
:deep(.el-form-item__label) {
|
||
font-size: 45px;
|
||
height: 70px;
|
||
line-height: 70px;
|
||
color: #ffffff;
|
||
}
|
||
|
||
:deep(.el-select__wrapper.is-hovering) {
|
||
.el-select__suffix {
|
||
.el-icon {
|
||
font-size: 55px;
|
||
}
|
||
}
|
||
}
|
||
|
||
:deep(.el-select-dropdown__item.is-hovering) {
|
||
background-color: #064b66 !important;
|
||
}
|
||
|
||
:deep(.el-select__wrapper) {
|
||
height: 70px;
|
||
line-height: 70px;
|
||
background-color: transparent;
|
||
border: 1px solid #08b7b8;
|
||
font-size: 35px;
|
||
width: 356px;
|
||
|
||
.el-select__suffix {
|
||
.el-icon {
|
||
font-size: 55px;
|
||
}
|
||
}
|
||
|
||
.el-select__placeholder {
|
||
color: #ffffff;
|
||
height: 70px;
|
||
line-height: 70px;
|
||
}
|
||
|
||
.el-select__placeholder.is-transparent {
|
||
height: 70px;
|
||
line-height: 70px;
|
||
}
|
||
}
|
||
|
||
:deep(.el-form-item__content) {
|
||
.el-select__popper {
|
||
margin-top: -12px !important;
|
||
background: #072247 !important;
|
||
border: 1px solid #0f82af !important;
|
||
|
||
.el-select-dropdown__item {
|
||
font-size: 38px !important;
|
||
height: 70px !important;
|
||
line-height: 70px !important;
|
||
|
||
> span {
|
||
color: #ffffff;
|
||
}
|
||
}
|
||
|
||
.el-select-dropdown__item.hover,
|
||
.el-select-dropdown__item:hover {
|
||
background-color: #064b66 !important;
|
||
}
|
||
}
|
||
|
||
.el-button {
|
||
height: 70px;
|
||
font-size: 40px;
|
||
border-radius: 10px;
|
||
}
|
||
|
||
.el-button--primary {
|
||
background: #064b66;
|
||
}
|
||
|
||
.el-input {
|
||
width: 380px;
|
||
height: 70px;
|
||
|
||
.el-input__wrapper {
|
||
font-size: 40px;
|
||
background-color: transparent;
|
||
border: 1px solid #08b7b8;
|
||
box-shadow: none;
|
||
|
||
.el-input__inner {
|
||
height: 70px;
|
||
color: #ffffff;
|
||
}
|
||
|
||
.el-input__suffix-inner {
|
||
.el-icon {
|
||
font-size: 55px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.device-table {
|
||
margin-top: 7px;
|
||
|
||
:deep(.el-button) {
|
||
font-size: 40px;
|
||
}
|
||
|
||
.active {
|
||
color: #ffffff;
|
||
background: #0f7da9;
|
||
}
|
||
|
||
.wind-switch {
|
||
margin-left: 65px;
|
||
}
|
||
|
||
.switch {
|
||
margin-top: 22px;
|
||
display: flex;
|
||
width: 200px;
|
||
height: 50px;
|
||
border-radius: 6px;
|
||
border: 1px solid #05feff;
|
||
overflow: hidden;
|
||
color: #51a2b3;
|
||
line-height: 40px;
|
||
font-size: 36px;
|
||
|
||
& > div {
|
||
flex: 1;
|
||
text-align: center;
|
||
cursor: pointer;
|
||
}
|
||
}
|
||
|
||
:deep(.el-table--fit) {
|
||
//width: 1780px !important;
|
||
width: auto;
|
||
}
|
||
|
||
:deep(.cell) {
|
||
height: 80px;
|
||
line-height: 80px;
|
||
color: #fff;
|
||
font-size: 38px;
|
||
}
|
||
|
||
:deep(.el-table tr) {
|
||
background-color: #1c5971;
|
||
}
|
||
|
||
:deep(
|
||
.el-table--enable-row-hover .el-table__body tr:hover > td.el-table__cell
|
||
) {
|
||
background-color: #1c5971;
|
||
}
|
||
|
||
:deep(.el-table__row--striped) {
|
||
background-color: #13849c !important;
|
||
}
|
||
|
||
:deep(
|
||
.el-table--striped
|
||
.el-table__body
|
||
tr.el-table__row--striped
|
||
td.el-table__cell
|
||
) {
|
||
background-color: #13849c !important;
|
||
}
|
||
|
||
:deep(.el-table__cell) {
|
||
.el-input {
|
||
width: 180px;
|
||
height: 53px;
|
||
}
|
||
|
||
.el-input__wrapper {
|
||
border-radius: 6px;
|
||
border: 1px solid #05feff;
|
||
background-color: transparent;
|
||
|
||
.el-input__inner {
|
||
color: #ffffff;
|
||
font-size: 40px;
|
||
height: auto;
|
||
line-height: normal;
|
||
}
|
||
}
|
||
}
|
||
|
||
:deep(.el-table__inner-wrapper::before) {
|
||
display: none;
|
||
}
|
||
}
|
||
|
||
.pagination {
|
||
display: flex;
|
||
align-items: center;
|
||
position: absolute;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
bottom: 0;
|
||
color: #60ddde;
|
||
font-size: 38px;
|
||
font-weight: bold;
|
||
|
||
:deep(.el-pagination.is-background) {
|
||
.btn-next,
|
||
.btn-prev {
|
||
background-color: transparent;
|
||
}
|
||
|
||
.el-pager {
|
||
li {
|
||
margin: 0 0 0 40px;
|
||
}
|
||
|
||
li.is-active {
|
||
background-color: #60ddde;
|
||
}
|
||
}
|
||
}
|
||
|
||
> span:first-child {
|
||
margin-right: 60px;
|
||
}
|
||
|
||
> span:last-child {
|
||
margin-left: 71px;
|
||
}
|
||
|
||
:deep(.btn-prev) {
|
||
background-color: transparent;
|
||
font-size: 38px;
|
||
font-weight: bold;
|
||
color: #60ddde;
|
||
margin-right: 20px;
|
||
}
|
||
|
||
:deep(.btn-next) {
|
||
background-color: transparent;
|
||
font-size: 38px;
|
||
font-weight: bold;
|
||
color: #60ddde;
|
||
margin-left: 30px;
|
||
}
|
||
|
||
:deep(.el-pager li.is-active) {
|
||
min-width: 70px;
|
||
height: 70px;
|
||
background: #60ddde;
|
||
border-radius: 50%;
|
||
color: #071f40;
|
||
font-size: 38px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
:deep(.el-pager li) {
|
||
margin-left: 40px !important;
|
||
}
|
||
|
||
:deep(.el-pager li:not(.is-active)) {
|
||
min-width: 70px;
|
||
height: 70px;
|
||
border: 1px solid #60ddde;
|
||
border-radius: 50%;
|
||
background-color: transparent;
|
||
font-size: 38px;
|
||
font-weight: bold;
|
||
color: #60ddde;
|
||
}
|
||
}
|
||
</style> |