|
|
<script setup lang="ts"> import { getContainerList } from 'apis/container' import logoutIcon from 'assets/images/logout.svg' import Check from 'components/check/index.vue' import Liquid from 'components/home/Liquid/index.vue' import Stop from 'components/Stop/index.vue' import { useActivateDebug } from 'hooks/useActivateDebug' import { useServerTime } from 'hooks/useServerTime' import { isClose } from 'libs/socket' import { authRoutes } from 'router/routes' import { useSystemStore } from 'stores/systemStore' import { computed, onMounted, onUnmounted, ref, watch } from 'vue' import { useRouter } from 'vue-router'
const { handleLogoClick } = useActivateDebug()
const { currentTime } = useServerTime() const systemStore = useSystemStore() const router = useRouter()
watch(() => currentTime.value, () => { systemStore.currentTime = currentTime.value })
watch(() => systemStore.systemStatus, () => { if (!systemStore.systemStatus.currentUser) { router.push('/login') } if (!systemStore.systemStatus.selfTest && systemStore.systemStatus.currentUser && systemStore.systemStatus.currentUser?.username !== 'test') { isCheck.value = true } })
onMounted(async () => { if (!systemStore.systemStatus.selfTest && systemStore.systemStatus.currentUser && systemStore.systemStatus.currentUser?.username !== 'test') { isCheck.value = true } if (!systemStore.systemStatus.currentUser) { console.log(11233) await router.push('/login') } })
onUnmounted(() => { // clearInterval(timeInterval)
}) // meta的isDefault=true 并且 当isDebug=true时,把debug路由的页面也显示
const menuList = computed(() => { return authRoutes.filter((item) => { if (item.meta?.isDefault) { return true } return (item.path === '/debug' && systemStore.isDebug) }) })
watch(() => systemStore.isDebug, () => { console.log('isDebug', systemStore.isDebug) if (!systemStore.isDebug && router.currentRoute.value.path === '/debug') { router.push('/') } })
const isCheck = ref(false)
const containerList = ref<Container.ContainerItem[]>() const getSolution = async () => { const res = await getContainerList() containerList.value = res.filter(item => item.type === 0) }
const statusMap = { start: { type: 'primary', name: '指令开始执行', }, success: { type: 'success', name: '指令执行成功', }, fail: { type: 'danger', name: '指令执行异常', }, } </script>
<template> <el-container class="main"> <el-header class="header"> <div class="logo"> <img src="../assets/images/logo.svg" alt="" @click="handleLogoClick"> <span class="title" @click="handleLogoClick">长春黄金研究院有限公司</span> <img :class="systemStore.menuExpand ? 'expand-icon' : 'fold-icon'" src="../assets/images/expand.svg" alt="" @click="systemStore.updateMenuExpand()"> </div> <div class="header-right"> <el-dropdown class="wifi-dropdown" trigger="click"> <div class="wifi-icon"> <img v-if="isClose" src="../assets/images/wifi.svg" alt=""> <img v-else src="../assets/images/wifi-active.svg" alt=""> </div> <template #dropdown> <el-dropdown-menu> <el-dropdown-item @click="systemStore.logout()"> <div class="logout"> <span v-if="!isClose">已连接</span> <span v-else>已断开</span> </div> </el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown>
<div class="time"> {{ systemStore.currentTime }} </div> <div class="user"> <el-dropdown class="user-dropdown" trigger="click"> <div class="user-dropdown-item"> <img src="../assets/images/user.svg" alt=""> <span>{{ systemStore.systemStatus.currentUser?.nickname || systemStore.systemStatus.currentUser?.username }}</span> </div> <template #dropdown> <el-dropdown-menu> <el-dropdown-item @click="systemStore.logout()"> <div class="logout"> <img :src="logoutIcon" alt=""> <span>退出登录</span> </div> </el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown> </div> </div> </el-header> <el-container class="container"> <el-aside class="aside" :class="{ 'aside-off': !systemStore.menuExpand }"> <div v-for="item in menuList" :key="item.path" class="aside-item" :class="{ 'aside-item-active': router.currentRoute.value.path.includes(item.path) }" @click="router.push(item.path)" > <img class="swing-icon" :src="((router.currentRoute.value.path.includes(item.path) ? item.meta!.activeIcon : item.meta!.icon) as string)" alt=""> <span class="text">{{ item.meta!.title }}</span> </div> </el-aside> <el-main> <router-view v-slot="{ Component }" class="content"> <transition name="el-fade-in-linear"> <component :is="Component" /> </transition> </router-view> </el-main> </el-container> <el-footer class="footer" :class="{ 'footer-expand': !systemStore.menuExpand }"> <el-row> <el-col :span="16"> <div class="footer-left"> <img src="../assets/images/run.svg" alt=""> <span v-if="!systemStore.systemLogList.length" class="text">设备运行状态</span> <el-popover v-else width="auto" trigger="click" placement="top"> <template #reference> <el-tag style="width: 100%" :type="statusMap[systemStore.systemLogList[0]?.status as keyof typeof statusMap].type"> {{ systemStore.systemLogList[0]?.cmdName }}: {{ statusMap[systemStore.systemLogList[0]?.status as keyof typeof statusMap].name }} {{ systemStore.systemLogList[0]?.time }} </el-tag> </template> <template #default> <div class="log-box"> <el-tag v-for="(item, key) in systemStore.systemLogList" :key :type="statusMap[item?.status as keyof typeof statusMap].type" > {{ item.cmdName }}: {{ statusMap[item.status as keyof typeof statusMap].name }} {{ item.time }} </el-tag> </div> </template> </el-popover> </div> </el-col>
<el-col :span="8"> <el-popover placement="top-start" width="auto" trigger="click" @show="getSolution" > <template #reference> <div class="footer-right"> <div class="status" /> <span class="text">溶液容器余量正常</span> </div> </template> <template #default> <div class="container-box"> <Liquid v-for="item in containerList" :key="item.id" :data="item" /> </div> </template> </el-popover> </el-col> </el-row> </el-footer> <FtStream :visible="systemStore.streamVisible" /> <Check v-if="isCheck" @close="isCheck = false" /> <Stop v-if="systemStore.systemStatus.emergencyStop" /> </el-container> </template>
<style scoped lang="scss"> .main { box-sizing: border-box; height: 100%; background: #F6F6F6; .header, .footer { height: 50px; width: 100%; display: flex; align-items: center; justify-content: space-between; padding: 10px 15px; } .header { color: #393F46;
.logo { height: 100%; display: flex; align-items: center; .title { margin:0 10px; color: #8799AB; font-weight: 600; } img { height: 100%; } .expand-icon { height: 15px; transition: all 0.3s; } .fold-icon { height: 15px; transform: rotate(90deg); transition: all 0.3s; } } .header-right { display: flex; align-items: center; height: 100%; .wifi-dropdown { height: 100%; .wifi-icon { width: 40px; height: 100%; background: #fff; border-radius: 5px; display: flex; align-items: center; justify-content: center; img { height: 50%; } } }
.time { margin:0 10px; height: 100%; padding: 0 10px; display: flex; align-items: center; background: #fff; border-radius: 5px; } } } .container { height: calc(100% - 100px); } } .aside { width: 170px; overflow: auto; padding-left: 10px; //transition: all 0.1s ease;
.aside-item { width: 100%; height: 50px; border-radius: 10px; color: #1989FA; margin: 10px 0; padding: 0 10px; display: flex; align-items: center; overflow: hidden; img { height: 80%; margin-right: 20px; } .text { transition: opacity 0.3s ease; white-space: nowrap; } } .aside-item-active { background: #1989FA; color: #fff; } }
.aside-off { width: 70px; //transition: all 0.1s ease;
.aside-item { .text { opacity: 0 } } .aside-item-active { background: rgba(0,0,0,0); color: #fff; } } .user-dropdown-item { display: flex; align-items: center; height: 100%; color: #393F46; font-weight: bold; img { height: 30px; margin-right: 10px; } } .el-main { padding: 0 15px; height: 100%; position: relative; } .content { width: 100%; height: 100%; background: #fff; border-radius: 10px; box-shadow: 0 0 1px rgba(0, 0, 0, 0.1); padding: 10px; } .footer-expand { padding: 10px 15px 10px 85px !important; } .main .footer { padding: 10px 15px 10px 185px; .el-row { width: 100%; height: 100%; .el-col { height: 100%; } } .footer-left, .footer-right { width: 100%; height: 100%; background: #fff; border-radius: 5px; display: flex ; align-items: center; padding: 0 20px; } .footer-left { border-right: 5px solid #F6F6F6; display: flex; align-items: center; justify-content: space-between;
img { height: 60%; margin-right: 20px; } .text { color: #1C1C1C ;
font-size: 14px; } } .footer-right { border-left: 10px solid #F6F6F6; .status { width: 15px; height: 15px; border-radius: 50%; background: #4EE993; } .text { color: #1C1C1C ; margin-left: 10px; font-size: 14px; } } } .aside-item:hover { .swing-icon { animation: swing 1s ease-in-out; } } .logout { display: flex; img { width: 15px; margin-right: 10px; } }
.container-box { width: 400px; display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(2, 1fr); grid-gap: 10px; }
.log-box { width: 500px; height: 400px; overflow: auto; .el-tag { margin: 5px 0; width: 100%; } }
@keyframes swing { 0% { transform: rotate(0deg); } 25% { transform: rotate(-30deg); } 50% { transform: rotate(30deg); } 75% { transform: rotate(-15deg); } 100% { transform: rotate(0deg); } } </style>
|