Files
tunnel-cloud-web/src/views/tunnel-simulate/index.vue
2025-01-02 21:31:46 +08:00

1004 lines
24 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div id="main">
<tunnel-title v-if="showTunnelTitle"/>
<div class="box-top">
<div class="back-tunnel" @click="router.push('/simulate/tunnel/list')">
<div class="back-icon"></div>
<span>返回</span>
</div>
<div class="top-length">
<span>隧道总长度: {{ tunnelLength }}</span>
<span class="all-btn" @click="startSimulate" v-if="isStartSimulate">开始模拟</span>
<div v-else>
<span class="all-btn" @click="simulatedBlasting">模拟爆破</span>
<span class="all-btn" @click="endSimulate">结束模拟</span>
</div>
<!-- <span class="all-btn" :style="{color:!isPreview?'#f7b500':'#0BE9FA'}" @click="changeTunnelSimulateMode(false)">编辑模式</span>-->
</div>
<div class="top-right" v-if="isPreview">
<!-- <div class="current-site">-->
<!-- <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>
<device-manage
v-if="showDevice"
@cancel="cancelDeviceManage"
@submit="submitDevice"
/>
<!-- 模拟隧道模式-->
<preview-scene-simulate
ref="previewRef"
id="tunnel-box"
:isedit="false"
:device-data="largeScreenData"
:tunnelLength="tunnelLength"
:tunnelId="tunnelId"
:tunnelAlias="tunnelAlias"
:devRealtimeData="socketData"
></preview-scene-simulate>
<!-- 一进去的话应该是预览模式所以引入这个组件1 -->
<!-- <preview-scene-->
<!-- id="tunnel-box"-->
<!-- :isedit="false"-->
<!-- :tunnelId="tunnelId"-->
<!-- :key="tunnelId"-->
<!-- :tunnelLen="tunnelLen"-->
<!-- :largeScreen="largeScreen"-->
<!-- :fanList="socketData.leftData"-->
<!-- ></preview-scene>-->
<div class="left" v-if="isPreview">
<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"
:isSimulate="true"
: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" v-if="isPreview">
<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"
:isSimulate="true"
:win-data="largeScreenData"
:loading="showWindLoading"
/>
<air-info
v-if="showFan"
:list="socketData.sensor"
:windSpeed="socketData.windSpeed"
:isSimulate="true"
:air-data="largeScreenData"
/>
<bad-gas-info
v-if="showFan"
:list="socketData.sensor"
:bad-gas-data="largeScreenData"
:isSimulate="true"
: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>
</template>
<script setup>
// import PreviewScene from "@/components/content/tunnelScene/PreviewScene.vue";
import PreviewSceneSimulate from "@/components/content/tunnelScene/TunnelSceneSimulate.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,
endSimulation,
blastingSimulation,
} from "@/api/largeScreen";
import {ElLoading, ElMessage, ElMessageBox} from "element-plus";
import {getUserInfo} from "@/api/login";
import {initSceneData} from "@/api/tunnelScene";
import {
getScreenSimulateTunnel,
getSimulateTunnelDetail,
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 previewRef = ref();
const isVisited = ref(false);
const isDetailVisited = ref(false);
const showFan = ref(false);
const showDevice = ref(false);
const drawerLeft = ref(true);
const showTunnelTitle = ref(true);
const isPreview = 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 isStartSimulate = ref(true);
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 tunnelAlias = ref('');
const constructionLength = ref(0);
const routeList = ref([]);
let socket = reactive("");
let pattern = reactive(new RegExp("[A-Za-z]+"));
let isTunnel = reactive(false);
// const equipmentOption = ref([])
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("");
let token = getToken();
let send = {
type: "ping",
};
const pageInfo = reactive({
pageNum: 1,
pageSize: 10,
});
const queryForm = ref();
const form = 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(() => {
getUser();
// getOtherInfo();
getScreenInfo(previewId);
getBasicData(previewId);
nextTick(() => {
showFan.value = true;
});
});
const startSimulate = () => {
isStartSimulate.value = false;
showDevice.value = true;
};
const cancelDeviceManage = () => {
isStartSimulate.value = true;
showDevice.value = false;
};
const submitDevice = () => {
isStartSimulate.value = false;
showDevice.value = false;
getScreenInfo(previewId);
// initWebSocket()
};
const simulatedBlasting = async () => {
await blastingSimulation(previewId, 10);
};
const endSimulate = async () => {
isStartSimulate.value = true;
await endSimulation(previewId);
ElMessage.success("结束模拟成功");
};
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.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 getBasicData = (id) => {
getSimulateTunnelDetail(id).then((res) => {
if (res?.code === 1000) {
tunnelLength.value = res.data.totalLength;
tunnelAlias.value = res.data.tunnelAlias;
serialNumber.value = res.data.serialNumber;
constructionLength.value = res.data.constructionLength;
initWebSocket();
} else {
ElMessage.warning(res.msg);
}
});
};
const getScreenInfo = (id) => {
if (id) {
tunnelId.value = id;
// equipmentOption.value = []
getScreenSimulateTunnel(id).then((res) => {
if (res?.code === 1000) {
if (res.data.frequencyChangerList.length !== 0) {
showFanLoading.value = 1;
} else {
showFanLoading.value = 1;
}
if (res.data.windPressureSensorList.length !== 0) {
showWindLoading.value = 1;
} else {
showWindLoading.value = 1;
}
if (res.data.sensorList.length !== 0) {
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;
nextTick(() => {
previewRef.value.TunnelSceneSimulateRender(res.data)
})
// console.log("largeScreenData.value", largeScreenData.value);
} else {
ElMessage.warning(res.msg);
}
});
}
};
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 {
tunnelList.value = res.data;
getScreenInfo(res.data[0]?.value);
}
}
}
});
};
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 initWebSocket = () => {
// let wsUrl = `ws://frp.toomewhy.top:38000/wstunnel/websocket/simulate/${token}/123`;
// let wsUrl = `ws://192.168.31.175:8000/wstunnel/websocket/simulate/${token}/123`;
let wsUrl = `ws://tunnel.feashow.com/api/wstunnel/websocket/simulate/${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}`;
// let wsUrl = `ws://frp.toomewhy.top:39000/websocket/simulate/${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 === "simulate") {
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);
};
</script>
<style lang="scss">
.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>
.box-top {
//display: flex;
//justify-content: space-between;
position: relative;
.all-btn {
cursor: pointer;
padding: 10px 20px;
border-radius: 11px;
border: 2px solid #08b7b8;
color: #0be9fa;
text-align: center;
margin-left: 40px;
font-size: 38px;
&:hover {
color: #f7b500;
}
}
.back-tunnel {
position: absolute;
top: 46px;
cursor: pointer;
margin: 0 0 0 70px;
display: flex;
align-items: center;
width: 178px;
height: 70px;
line-height: 70px;
border-radius: 11px;
border: 2px solid #08B7B8;
font-size: 38px;
color: #FFFFFF;
z-index: 9999;
.back-icon {
margin-right: 20px;
margin-left: 23px;
width: 33px;
height: 33px;
background-image: url('@/assets/images/site/zdgl_icon_fh.png');
}
}
}
#main {
height: 100%;
width: 100%;
background-color: #072348;
#tunnel-box {
height: 100%;
}
}
.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) {
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)) {
width: 70px;
height: 70px;
border: 1px solid #60ddde;
border-radius: 50%;
background-color: transparent;
font-size: 38px;
font-weight: bold;
color: #60ddde;
}
}
</style>