From 18eb4308e941a265daba8eda2f2ee91115963a3c Mon Sep 17 00:00:00 2001
From: haoxuan <haoxuan>
Date: 星期四, 18 四月 2024 17:06:04 +0800
Subject: [PATCH] 1
---
src/views/dashboard/components/DeviceStatusInfo.vue | 215 ++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 163 insertions(+), 52 deletions(-)
diff --git a/src/views/dashboard/components/DeviceStatusInfo.vue b/src/views/dashboard/components/DeviceStatusInfo.vue
index 1593dc7..3946950 100644
--- a/src/views/dashboard/components/DeviceStatusInfo.vue
+++ b/src/views/dashboard/components/DeviceStatusInfo.vue
@@ -1,11 +1,11 @@
<template>
<div class="device-status-info">
- <div v-if="type == 1" class="color-one">
+ <div v-if="type === 1" class="color-one">
璁惧鐘舵��
<!-- 1鏂紑2鐢熶骇3寰呮満 -->
- <span v-if="device.plcStatus" class="device-m">
+ <span v-if="plc?.plcStatus" class="device-m">
<el-popover
- v-if="device.plcStatus == 1 && device.plcNotConnected"
+ v-if="plc?.plcStatus === 1 && plc?.plcNotConnected"
:width="180"
placement="top-end"
trigger="click"
@@ -16,10 +16,10 @@
</el-icon>
鏂紑
</template>
- {{ device.plcNotConnected }}
+ {{ plc?.plcNotConnected }}
</el-popover>
<span v-else>
- <el-icon v-if="device.plcStatus == 1 && !device.plcNotConnected" class="duan">
+ <el-icon v-if="plc?.plcStatus == 1 && !plc?.plcNotConnected" class="duan">
<Link />
</el-icon>
<el-icon v-else class="lian">
@@ -30,63 +30,156 @@
'status-off': device.plcStatus != 2,
}" -->
<span class="status-running">
- {{ device.plcStatus == 1 ? '鏂紑' : device.plcStatus == 2 ? '鐢熶骇涓�' : '寰呮満' }}
+ {{ plc?.plcStatus === 1 ? '鏂紑' : plc?.plcStatus === 2 ? '鐢熶骇涓�' : '寰呮満' }}
</span>
</span>
</span>
- <div class="device-b">杩愯鏃堕棿锛�1澶�1灏忔椂23鍒�12绉�</div>
+ <div class="device-b">宸ュ簭杩愯鏃堕棿锛歿{ runningTime }}</div>
</div>
<div v-if="type == 2" class="color-two">
闆嗙兢鐘舵��
- <!-- 1鏂紑2鐢熶骇3寰呮満 -->
- <span v-if="device.plcStatus" class="device-m">
- <el-popover
- v-if="device.plcStatus == 1 && device.plcNotConnected"
- :width="180"
- placement="top-end"
- trigger="click"
- >
- <template #reference>
- <el-icon class="duan">
- <CircleCloseFilled />
+ <span class="device-m">
+ <span>
+ <template v-if="device?.clusterStatus">
+ <el-icon class="lian">
+ <SuccessFilled />
</el-icon>
- 鏂紑
+ <span class="status-running"> 鍦ㄧ嚎 </span>
</template>
- {{ device.plcNotConnected }}
- </el-popover>
- <span v-else>
- <el-icon v-if="device.plcStatus == 1 && !device.plcNotConnected" class="duan">
- <CircleCloseFilled />
- </el-icon>
- <el-icon v-else class="lian">
- <SuccessFilled />
- </el-icon>
- <!-- :class="{
- 'status-running': device.plcStatus == 2,
- 'status-off': device.plcStatus != 2,
- }" -->
- <span class="status-running">
- {{ device.plcStatus == 1 ? '鏂紑' : device.plcStatus == 2 ? '鍦ㄧ嚎' : '寰呮満' }}
- </span>
+
+ <template v-else>
+ <span>鏈姞鍏ラ泦缇�</span>
+ </template>
</span>
</span>
- <div class="device-info">涓昏妭鐐�</div>
- <div class="device-b title-bng"><span>鑺傜偣鏁�</span> <i>120</i></div>
+ <div
+ class="device-info"
+ :class="{ master: device?.clusterStatus === 'master', slave: device?.clusterStatus === 'slave' }"
+ >
+ {{ nodeTypeText }}
+ </div>
+ <div class="device-b title-bng">
+ <img src="~@/assets/images/leaf.png" alt="" />
+ <span>鑺傜偣鏁�</span> <i>{{ device?.clusterNodeQuantity ?? 0 }}</i>
+ </div>
</div>
</div>
</template>
<script setup lang="ts">
-import { toRefs } from 'vue'
-import { Link, CircleCloseFilled, SuccessFilled } from '@element-plus/icons-vue'
+import { computed, toRefs } from 'vue'
+import { Link, SuccessFilled } from '@element-plus/icons-vue'
+import type { Devices } from '@/api/device'
import type { PLCResponse } from '@/api/plc'
+import { useTasksStore } from '@/stores/tasks'
+import { storeToRefs } from 'pinia'
+import type { TasksGroupByChannel } from '@/api/task'
+import { isNumber } from 'lodash-es'
+import { useInterval } from '@vueuse/core'
export interface DeviceStatusInfoProps {
- device: PLCResponse
- type?: Number
+ plc?: PLCResponse
+ device?: Devices
+ /** 1: 璁惧鐘舵�� 2:闆嗙兢鐘舵��*/
+ type?: 1 | 2
}
-const props = defineProps<DeviceStatusInfoProps>()
-const { device, type } = toRefs(props)
+const props = withDefaults(defineProps<DeviceStatusInfoProps>(), {
+ type: 1,
+ device: undefined,
+ plc: undefined
+})
+const { type, plc, device } = toRefs(props)
+
+// 闆嗙兢鑺傜偣鏂囨湰
+const nodeTypeText = computed(() => {
+ switch (device?.value?.clusterStatus) {
+ case 'master':
+ return '涓昏妭鐐�'
+ case 'slave':
+ return '浠庤妭鐐�'
+ case '':
+ default:
+ return ''
+ }
+})
+
+/**
+ * 宸ュ簭杩愯鏃堕棿
+ * 鏍规嵁鎺ュ彛杩斿洖 realStartTime realEndTime 鍒ゆ柇濡備綍灞曠ず
+ * 濡傛灉 realEndTime 涓� 0 鍒� 鐢ㄥ綋鍓嶆椂闂� - realStartTime
+ * 濡傛灉 瀛樺湪 realEndTime, 鍒� realEndTime - realStartTime
+ * 娉ㄦ剰 realStartTime realEndTime 鏄帴鍙h繑鍥炵殑10浣嶆椂闂存埑
+ * @param realStartTime
+ * @param realEndTime
+ * @return
+ */
+function getTaskRunningTime(realStartTime?: number, realEndTime?: number) {
+ if (realStartTime && realEndTime) {
+ return calcRunningDuration(realStartTime * 1000, realEndTime * 1000)
+ } else if (!realEndTime && realStartTime) {
+ const now = Math.floor(new Date().getTime() / 1000) * 1000
+ return calcRunningDuration(realStartTime * 1000, now)
+ } else {
+ return '--'
+ }
+}
+
+/**
+ * 璁$畻鏃堕棿娈�, 娉ㄦ剰鍙傛暟瑕佹眰鏃堕棿鎴充负 JS Date 鐨�13浣嶆椂闂存埑
+ * @param startTime
+ * @param endTime
+ * @return
+ */
+function calcRunningDuration(startTime: number, endTime: number) {
+ let timeDuration = endTime - startTime
+ if (timeDuration < 0) {
+ return '0澶�0鏃�0鍒�'
+ }
+
+ let seconds = Math.floor(timeDuration / 1000)
+ let minutes = Math.floor(seconds / 60)
+
+ let days = Math.floor(timeDuration / 1000 / 60 / 60 / 24)
+ let hours = Math.floor(minutes / 60) - days * 24
+ let m = minutes - days * 24 * 60 - hours * 60
+ return `${days}澶�${hours}鏃�${m}鍒哷
+}
+
+/**
+ * 鑾峰彇鏌愪换鍔℃墍鍦ㄩ�氶亾鐨勮繍琛屼腑鐨勪换鍔�
+ * @param channelMap
+ * @param channelNumber
+ */
+function getChannelRunningTask(channelMap?: TasksGroupByChannel, channelNumber?: number) {
+ if (!channelMap || !isNumber(channelNumber)) {
+ return
+ }
+
+ const channel = channelMap[channelNumber]
+ if (channel) {
+ const taskList = channel?.Tasks ?? []
+
+ return taskList.find((ele) => ele.Procedure.Status === 2)
+ }
+}
+
+// 宸ュ簭杩愯鏃堕棿
+const taskStore = useTasksStore()
+const { activeTask, channels } = storeToRefs(taskStore)
+const { counter, reset } = useInterval(1000, { controls: true })
+const runningTime = computed(() => {
+ if (counter.value > 1000) {
+ // 鎷夸竴涓� counter 瀹氭椂瑙﹀彂宸ュ簭杩愯鏃堕棿鐨勯噸鏂拌绠楀拰娓叉煋, 闃叉婧㈠嚭闇�瑕侀噸缃�
+ reset()
+ }
+ // 濡傛灉褰撳墠閫変腑鐨勬槸宸插畬鎴愮殑浠诲姟, 浣跨敤褰撳墠閫変腑浠诲姟鏉ュ睍绀�
+ if (activeTask?.value?.Procedure?.Status === 3) {
+ return getTaskRunningTime(activeTask.value.Procedure?.realStartTime, activeTask.value.Procedure?.realEndTime)
+ }
+ // 濡傛灉褰撳墠閫変腑鐨勬槸杩愯涓垨鑰呮湭寮�濮嬬殑浠诲姟, 浣跨敤褰撳墠閫変腑浠诲姟鎵�鍦ㄩ�氶亾鐨勬澶勪簬杩愯涓殑浠诲姟鏉ュ睍绀�
+ const runningTask = getChannelRunningTask(channels?.value, activeTask?.value?.Channel)
+ return getTaskRunningTime(runningTask?.Procedure?.realStartTime, runningTask?.Procedure?.realEndTime)
+})
</script>
<style scoped lang="scss">
@@ -159,25 +252,43 @@
padding: 0px 6px;
font-size: 12px;
line-height: 20px;
- background: $status-running;
color: #fff;
border-radius: 8px;
+ &.master {
+ background: $status-running;
+ }
+ &.slave {
+ background-color: #3399ff;
+ }
}
.title-bng {
- height: 32px;
- line-height: 32px;
- background: url('../../../assets/images/number.png') no-repeat center center / cover;
- span {
- height: 32px;
- display: inline-block;
- text-align: center;
+ width: calc(90% - 1px);
+ margin: 10px auto 0;
+ height: 29px;
+ line-height: 29px;
+ font-size: 14px;
+ background: url('../../../assets/images/nodeNumber.png') no-repeat center center / cover;
+ img {
+ height: 16px;
display: inline-block;
float: left;
- margin-left: 35%;
+ margin: 8px 5px 0 5px;
+ }
+ span {
+ height: 29px;
+ display: inline-block;
+ line-height: 29px;
+ vertical-align: middle;
+ text-align: center;
+ font-size: 12px;
+ display: inline-block;
+ float: left;
+ font-weight: bold;
}
i {
float: right;
margin-right: 15px;
+ font-weight: bold;
}
}
}
--
Gitblit v1.8.0