Newer
Older
intelligentRobot / src / layouts / index.vue
wangxitong on 3 Sep 12 KB first commit
<script lang="ts" setup name="Layout">
import hotkeys from 'hotkeys-js'
import NewHeader from './components/Header/index.vue'
import MainSidebar from './components/MainSidebar/index.vue'
import SubSidebar from './components/SubSidebar/index.vue'
import Topbar from './components/Topbar/index.vue'
import Search from './components/Search/index.vue'
import AppSetting from './components/AppSetting/index.vue'
import HotkeysIntro from './components/HotkeysIntro/index.vue'
import useSettingsStore from '@/store/modules/settings'
import useKeepAliveStore from '@/store/modules/keepAlive'
import useMenuStore from '@/store/modules/menu'
import {dataRecord, softwareStop} from "@/api/home/robot/robot";
import {ElMessage} from "element-plus";
import {getRobotList} from "@/api/home/robot/robot";
import {ref} from "vue";
import robotImg from '@/assets/images//机器人.png'
import singalImg from '@/assets/images/robot/信号.png'
import singalFullImg from '@/assets/images/robot/信号满.png'
import alarmImg from '@/assets/images/robot/告警.png'
import noAlarmImg from '@/assets/images/robot/没告警.png'
import powerImg from '@/assets/images/robot/power.png'
import useWebsocketStore from "@/store/modules/websocket";
import dayjs from "dayjs";

const routeInfo = useRoute()

const settingsStore = useSettingsStore()
const keepAliveStore = useKeepAliveStore()
const menuStore = useMenuStore()
const robotList = ref<any[]>([]) // 机器人
const robotIndex = ref<number>(0)
const width = ref<any>('16px')
const img1 = ref<any>('')
const img2 = ref<any>('')
const isStop = ref(false)

function changeRobot(num: number) {
  robotIndex.value += num
  settingsStore.setRobot(robotList.value[robotIndex.value])

  // socket重连
  websocket.destroyWebSocket()
  websocket.initWebSocket()

  // 更新机器人急停信息
  getRobotList({}).then((response) => {
    isStop.value = response.data.filter((item: { id: any }) => item.id === settingsStore.robot.id)[0].statusInfo.soft === 1 ? true : false
  })
}

function getRobot() {
  getRobotList({}).then((response) => {
    robotList.value = response.data
    if(response.data.length !== 0) {
      if(localStorage.getItem('robot_id') === null) {
        settingsStore.setRobot(response.data[0])
      } else if(!settingsStore.robot.hasOwnProperty('id')) {
        settingsStore.setRobot(response.data.filter((item: any) => item.id === localStorage.getItem('robot_id'))[0])
      }
      if(settingsStore.robot.hasOwnProperty('id')) {
        response.data.forEach((item: any, index: number) => {
          if(item.id === settingsStore.robot.id) {
            robotIndex.value = index
            changeRobot(0)
          }
        })
      } else {
        robotIndex.value = 0
        changeRobot(0)
      }
    }
  })
}

function stop() {
  softwareStop({
    control: 1,
    robotId: settingsStore.robot.id,
  }).then((response) => {
    if (response.code === 200) {
      // 更新机器人信息
      setTimeout(() => {
        getRobotList({}).then((response) => {
          isStop.value = response.data.filter((item: { id: any }) => item.id === settingsStore.robot.id)[0].statusInfo.soft === 1 ? true : false
        })
      }, 2000)
      // if(response.data === 1) {
      //   ElMessage.success('急停成功')
      // } else if(response.data === 0) {
      //   ElMessage.error('急停失败')
      // }
    }
  })
}
function run() {
  softwareStop({
    control: 0,
    robotId: settingsStore.robot.id,
  }).then((response) => {
    if (response.code === 200) {
      // 更新机器人信息
      setTimeout(() => {
        getRobotList({}).then((response) => {
          isStop.value = response.data.filter((item: { id: any }) => item.id === settingsStore.robot.id)[0].statusInfo.soft === 1 ? true : false
        })
      }, 2000)

      // if(response.data === 1) {
      //   ElMessage.success('启动成功')
      // } else if(response.data === 0) {
      //   ElMessage.error('启动失败')
      // }
    }
  })
}
watch(() => settingsStore.menu.subMenuCollapse, (val) => {
  if (settingsStore.mode === 'mobile') {
    if (!val) {
      document.body.classList.add('hidden')
    }
    else {
      document.body.classList.remove('hidden')
    }
  }
})

watch(() => routeInfo.path, () => {
  if (settingsStore.mode === 'mobile') {
    settingsStore.$patch((state) => {
      state.menu.subMenuCollapse = true
    })
  }
})
const websocket = useWebsocketStore()
onMounted(() => {
  getRobot()
  img1.value = singalFullImg
  img2.value = noAlarmImg
  hotkeys('f5', (e) => {
    if (settingsStore.toolbar.enablePageReload) {
      e.preventDefault()
      useMainPage().reload()
    }
  })
  hotkeys('alt+`', (e) => {
    if (settingsStore.menu.enableHotkeys) {
      e.preventDefault()
      useMenu().switchTo(menuStore.actived + 1 < menuStore.allMenus.length ? menuStore.actived + 1 : 0)
    }
  })
})
onUnmounted(() => {
  hotkeys.unbind('f5')
  hotkeys.unbind('alt+`')
  websocket.destroyWebSocket()
})
const router = useRouter()
function clickAlarm() {
  img2.value = noAlarmImg
  router.push({
    name: 'Alarm',
  })
}

const unwatch = watch(websocket, (newVal) => {
  if (newVal.robotData && Object.keys(newVal.robotData).length >= 1 ) {
    newVal.robotData.connStatus === 1 ?  img1.value = singalFullImg: img1.value = singalImg
    width.value = (Number(newVal.robotData.electricityQuantity) / 100 * 16) + 'px'
  } else if (newVal.alarmData && Object.keys(newVal.alarmData).length >= 1 ) {
    img2.value = alarmImg
  }
})
onBeforeUnmount(() => {
  unwatch()
})
</script>

<template>
  <div class="layout">
     <div id="app-main">
      <new-header />
      <div class="wrapper">
        <div v-if="settingsStore.menu.menuMode !== 'top'" class="sidebar-container" :class="{ show: settingsStore.mode === 'mobile' && !settingsStore.menu.subMenuCollapse }">
          <main-sidebar />
          <sub-sidebar />
        </div>
        <div v-if="settingsStore.menu.menuMode !== 'top'" class="sidebar-mask" :class="{ show: settingsStore.mode === 'mobile' && !settingsStore.menu.subMenuCollapse }" @click="settingsStore.toggleSidebarCollapse()" />
        <div class="main-container" :style="{ 'padding-bottom': $route.meta.paddingBottom }">
          <topbar v-if="!(settingsStore.menu.menuMode === 'head' && !settingsStore.menu.enableSubMenuCollapseButton && !settingsStore.breadcrumb.enable)" />
          <div class="main">
            <router-view v-slot="{ Component, route }">
              <transition name="main" mode appear>
                <keep-alive :include="keepAliveStore.list">
                  <component :is="Component" :key="route.fullPath" />
                </keep-alive>
              </transition>
            </router-view>
          </div>
<!--          <copyright />-->
        </div>
      </div>
      <el-backtop :right="20" :bottom="20" title="回到顶部" />
<!--       左侧红色按钮-->
      <div v-show="!settingsStore.subMenuCollapseLastStatus && !isStop" class="stop" @click="stop"/>
      <div v-show="!settingsStore.subMenuCollapseLastStatus && isStop" class="run" @click="run"/>
<!--      选择机器人-->
       <div class="select-robot">
        <el-avatar shape="square" size="medium" :src="robotImg" style="background: #00000000"></el-avatar>
        <div style="margin-top: -6px;margin-left: -12px">{{settingsStore.robot?.robotName}}</div>
        <el-icon v-if="robotIndex>0" style="position: absolute;top: 10px;left: 60px;cursor: pointer" @click="changeRobot(-1)">
          <svg-icon name="icon-up" />
        </el-icon>
        <el-icon v-if="robotIndex<robotList.length-1" style="position: absolute;top: 30px;left: 60px;cursor: pointer" @click="changeRobot(1)">
          <svg-icon name="icon-down" />
        </el-icon>
      </div>
      <div class="current">
        <el-image shape="square" size="small" :src="img1" style="width: 24px;height: 20px;margin-top: 4px"></el-image>
        <el-avatar shape="square" size="small" :src="img2" style="background: #00000000;margin: 0 15px;cursor: pointer" @click="clickAlarm()"></el-avatar>
        <el-image shape="square" size="small" :src="powerImg" style="width: 22px;height: 14px;margin-top: 5px;transform:rotateY(180deg);"></el-image>
        <div class="power" :style="{width}"/>
      </div>
      <copyright v-show="!settingsStore.subMenuCollapseLastStatus" class="copy"/>
    </div>
    <search />
    <app-setting />
    <hotkeys-intro />
  </div>
</template>

<style lang="scss" scoped>
.power {
  position: absolute;
  top: 7px;
  right: 101px;
  cursor: pointer;
  background-color: #1af72b;
  z-index: 99999999;
  height: 10px;
  border-radius: 1px;
}
[data-mode="mobile"] {
  .sidebar-container {
    transform: translateX(calc((var(--g-main-sidebar-width) + var(--g-sub-sidebar-width)) * -1));

    &.show {
      transform: translateX(0);
    }
  }

  .main-container {
    margin-left: 0 !important;
  }

  &[data-menu-mode="single"] {
    .sidebar-container {
      transform: translateX(calc(var(--g-sub-sidebar-width) * -1));

      &.show {
        transform: translateX(0);
      }
    }
  }
}

.layout {
  height: 100%;
}

#app-main {
  width: 100%;
  height: 100%;
  margin: 0 auto;
  transition: all 0.2s;
}
.current {
  position: absolute;
  top: 18px;
  right: 130px;
  width: 200px;
  height: 40px;
  z-index: 9999999;
  color: white;
  font-weight: bolder;
  font-size: 14px;
  display: flex;
}
.select-robot {
  position: absolute;
  top: 5px;
  left: 340px;
  width: 200px;
  height: 40px;
  z-index: 9999999;
  color: white;
  font-weight: bolder;
  font-size: 14px;
}
.stop {
  position: absolute;
  bottom: 35px;
  left: 42px;
  width: 96px;
  height: 96px;
  z-index: 111111111;
  background: url("@/assets/images/robot/急停.png") no-repeat right center;

  &:hover {
    background: url("@/assets/images/robot/急停按下.png") no-repeat right center;
  }
}
.run {
   position: absolute;
   bottom: 35px;
   left: 42px;
   width: 96px;
   height: 96px;
   z-index: 111111111;
   background: url("@/assets/images/robot/启动.png") no-repeat right center;

   &:hover {
     background: url("@/assets/images/robot/启动按下.png") no-repeat right center;
   }
 }
.copy {
  position: absolute;
  bottom: 10px;
  left: 0px;
  z-index: 99999999999;
}
.wrapper {
  position: relative;
  width: 100%;
  height: 100%;
  box-shadow: -1px 0 0 0 var(--g-box-shadow-color);
  transition: padding-top 0.3s;

  .sidebar-container {
    position: fixed;
    z-index: 1010;
    top: 0;
    bottom: 0;
    display: flex;
    transition: transform 0.3s, top 0.3s;
    width: calc(var(--g-main-sidebar-actual-width) + var(--g-sub-sidebar-actual-width));
  }

  .sidebar-mask {
    position: fixed;
    z-index: 1000;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgb(0 0 0 / 50%);
    backdrop-filter: blur(2px);
    transition: all 0.2s;
    transform: translateZ(0);
    opacity: 0;
    visibility: hidden;

    &.show {
      opacity: 1;
      visibility: visible;
    }
  }

  .main-sidebar-container:not(.main-sidebar-leave-active) + .sub-sidebar-container {
    left: var(--g-main-sidebar-width);
  }

  .main-container {
    display: flex;
    flex-direction: column;
    min-height: 100%;
    margin-left: calc(var(--g-main-sidebar-actual-width) + var(--g-sub-sidebar-actual-width));
    background-color: var(--g-main-bg);
    transition: margin-left 0.3s, background-color 0.3s;

    .topbar-container {
      top: 0;
      z-index: 998;
    }

    .main {
      height: 100%;
      flex: auto;
      position: relative;
      // overflow: hidden;
      transition: 0.3s;
    }

    .topbar-container + .main {
      margin: var(--g-topbar-height) 0 0;
    }
  }
}

header:not(.header-leave-active) + .wrapper {
  padding-top: var(--g-header-height);

  .sidebar-container {
    top: var(--g-header-height);

    :deep(.sidebar-logo) {
      display: none;
    }

    :deep(.el-menu) {
      padding-top: 0;
    }
  }

  .main-container {
    .topbar-container {
      top: var(--g-header-height);

      :deep(.tools) {
        display: none;
      }
    }
  }
}

// 主内容区动画
.main-enter-active {
  transition: 0.2s;
}

.main-leave-active {
  transition: 0.15s;
}

.main-enter-from {
  opacity: 0;
  margin-left: -20px;
}

.main-leave-to {
  opacity: 0;
  margin-left: 20px;
}
</style>