|
|
<script setup lang="ts"> import { getContainerList } from 'apis/container' import { craftList } from 'apis/crafts' import { getSolsList } from 'apis/solution' import logoutIcon from 'assets/images/logout.svg' import CheckCraft from 'components/home/CheckCraft/index.vue' import Liquid from 'components/home/Liquid/index.vue' import Check from 'components/system/Check/index.vue' import EditDate from 'components/system/EditDate/index.vue' import Stop from 'components/system/Stop/index.vue' import { useActivateDebug } from 'hooks/useActivateDebug' import { useServerTime } from 'hooks/useServerTime' import { isClose } from 'libs/socket' import { authRoutes } from 'router/routes' import { useDebugStore } from 'stores/debugStore' import { useSystemStore } from 'stores/systemStore' import { computed, onMounted, 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 (() => isClose.value, async (newVal) => { if (newVal) { await checkCraft() } })
watch(() => systemStore.systemStatus, () => { if (!systemStore.systemStatus.currentUser) { router.push('/login') } isCheck.value = !systemStore.systemStatus.selfTest }) onMounted(async () => { console.log('systemStatus', systemStore.systemStatus) if (!systemStore.systemStatus.currentUser) { await router.push('/login') } solutionList.value = (await getSolsList()).list if (!systemStore.systemStatus.selfTest && systemStore.systemStatus.currentUser?.username !== 'test') { isCheck.value = true } await checkCraft() })
const checkCraftVisible = ref(false) const checkCraft = async () => { const res = await craftList() systemStore.errorCraft = res && res.length > 0 // if (res && res.length > 0) {
// ElMessageBox.confirm(
// '发现有异常工艺, 是否处理恢复? ',
// '提示',
// {
// confirmButtonText: '确认',
// cancelButtonText: '取消',
// closeOnClickModal: false,
// closeOnPressEscape: false,
// type: 'warning',
// customClass: 'init-message',
// },
// ).then(async () => {
// await craftRestore(true)
// checkCraftVisible.value = true
// }).catch(async () => {
// await craftRestore(false)
// })
// }
}
// meta的isDefault=true 并且 当isDebug=true时,把debug路由的页面也显示
const menuList = computed(() => { return authRoutes.filter((item) => { if (item.meta?.isDefault) { return true } return (['/debug', '/positionDebug'].includes(item.path) && 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 solutionList = ref<Solution.SolutionItem[]>()
const getContainer = async () => { containerList.value = await getContainerList() }
const statusMap = { start: { type: 'primary', name: '指令开始执行', }, success: { type: 'success', name: '指令执行成功', }, fail: { type: 'danger', name: '指令执行异常', }, }
const commandHandle = async (command: string, params?: unknown) => { const data = { commandId: Date.now().toString(), command, params, } await useDebugStore().sendControl(data) }
const editDateVisible = ref(false) </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"> <ft-button v-if="systemStore.isDebug" type="primary" :click-handle="() => commandHandle('stop_all_motor')"> 停止所有电机 </ft-button> <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> <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" @click="editDateVisible = true"> {{ 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" > <div style="display: flex;justify-content: space-between;width: 100%"> <span> <span>{{ item.cmdName }}: </span> <span>{{ statusMap[item.status as keyof typeof statusMap].name }}</span> </span>
<span>{{ item.time }}</span> </div> <!-- {{ 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="getContainer" > <template #reference> <div class="footer-right"> <div class="status" /> <span class="text">溶液容器余量正常</span> </div> </template> <template #default> <div class="container-box"> <div v-for="item in containerList" :key="item.id" class="container-main" > <Liquid :data="item" /> <span>{{ solutionList?.find(s => s.id === item.solutionId)?.name }}</span> </div> </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" /> <CheckCraft v-if="checkCraftVisible" @close="checkCraftVisible = false" /> <EditDate v-if="editDateVisible" @close="editDateVisible = false" @ok="editDateVisible = false" /> </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; img { height: 60%; margin-right: 20px; } .text { color: #1C1C1C; margin-left: 10px; 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(1, 1fr); grid-gap: 10px; .container-main { display: flex; flex-direction: column; align-items: center; } } .log-box { width: 500px; height: 400px; overflow: auto; :deep(.el-tag) { margin: 5px 0; width: 100%; .el-tag__content { 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>
|