|
|
<template> <div class="service-all"> <div v-if="serviceTop" class="service-top-text" :class="!serviceTop ? 'false-active' : 'true-active'">AI处理终端</div> <!-- <i class="iconfont icon-zhongduanjiankong" />终端连接正常 --> <ul v-if="serviceTop" class="service-list"> <li v-for="(item, index) in serviceItems" :key="index"> <p :class="index <= currentIndex && item.status === 'running'? 'true-active' : 'false-active' "> {{ item.serviceName }} </p> <!-- {{ item.serviceName }} --> <!-- <i v-if="index <= currentIndex && item.status === 'running'" class="iconfont icon-shi" /> <i v-else-if="index <= currentIndex" class="iconfont icon-cuowu1" /> --> </li> </ul> <div v-if="servicesDisplayed && isAllServicesRunning" class="service-bottom-text" :class="{ 'fade-in': servicesDisplayed && isAllServicesRunning }" style="color: rgb(18, 196, 122);">所有服务均正常运行,请放心使用</div> <div v-else-if="servicesDisplayed && !isAllServicesRunning" class="service-bottom-text" :class="{ 'fade-in': servicesDisplayed &&!isAllServicesRunning }" style="color: #ED4A41;">请尽快联系系统维护人员进行恢复</div> <div v-if="!serviceTop" class="tip-service" :class="{ 'fade-in': !serviceTop }"> <i class="iconfont icon-lianjieduankai" /> <div class="tip-service-content"> <p>AI处理终端连接超时,请检查配置是否正确或终端是否运行成功!</p> <p>请尽快联系系统维护人员进行恢复</p> </div> </div> </div></template>
<script> import crudStockTask, { FetchAITerminalStatusQuery } from '@/api/stockTask/index' import { mapGetters } from 'vuex' export default { name: 'ServeTerminal', components: { }, props: { }, data() { return { service: { 'service_imgCamera': { 'last_heartbeat': 1736496962.2368362, 'status': '' }, 'service_imgProcess': { 'last_heartbeat': 1736496960.8598323, 'status': '' }, 'service_imgYolo': { 'last_heartbeat': 1736496961.953832, 'status': '' }, 'service_imgOcr': { 'last_heartbeat': 1736496961.6238313, 'status': '' }, 'service_imgResult': { 'last_heartbeat': 1736496963.4378026, 'status': '' } }, serviceItems: [], currentIndex: -1, timer: null, servicesDisplayed: false, serviceTop: false } }, computed: { ...mapGetters([ 'baseApi' ]), isAllServicesRunning() { return Object.values(this.service).every(service => service.status === 'running') } }, mounted() { }, methods: { initData() { crudStockTask.FetchInitSetting().then(res => { if (res) { this.handleService(res.ip) } }).catch(() => { }) }, handleService(ip) { this.servicesDisplayed = false FetchAITerminalStatusQuery({ 'ip': ip }).then(res => { // {
// "service_imgCamera":{"last_heartbeat":1736496962.2368362,"status":"running"},
// "service_imgProcess":{"last_heartbeat":1736496960.8598323,"status":"running"},
// "service_imgYolo":{"last_heartbeat":1736496961.953832,"status":"running"}
// "service_imgOcr":{"last_heartbeat":1736496961.6238313,"status":"running"},
// "service_imgResult":{"last_heartbeat":1736496963.4378026,"status":"running"},
// }
if (res) { this.serviceTop = true this.service = JSON.parse(res) this.serviceItems = [] const keysOrder = ['service_imgCamera', 'service_imgProcess', 'service_imgYolo', 'service_imgOcr', 'service_imgResult'] keysOrder.forEach(key => { let serviceName = '' switch (key) { case 'service_imgCamera': serviceName = '图像采集' break case 'service_imgProcess': serviceName = '图像处理' break case 'service_imgYolo': serviceName = '图像识别' break case 'service_imgOcr': serviceName = '文字识别' break case 'service_imgResult': serviceName = '同步服务' break } this.serviceItems.push({ serviceName: serviceName, status: this.service[key].status }) }) this.showServicesSequentially() } else { this.serviceTop = false } }).catch(() => { }) }, showServicesSequentially() { let index = 0 const interval = 300 this.timer = setInterval(() => { this.currentIndex = index index++ if (index >= this.serviceItems.length) { clearInterval(this.timer) setTimeout(() => { this.servicesDisplayed = true }, 500) } }, interval) } } } </script>
<style lang="scss" scoped> .tip-service{ display: flex; justify-content: center; color: #0C0E1E; font-size: 16px; line-height: 40px; padding: 40px 0; .iconfont{ font-size: 30px; margin-right: 10px; color: #ED4A41; } p{ &:first-child{ color: #ED4A41; } } }
.service-all{ position: relative; height: 230px; color: #0C0E1E; } .service-top-text{ position: relative; font-size: 12px; margin: 0 65px; height: 72px; text-align: center; background: url('~@/assets/images/serve1.png') no-repeat center center; background-size: 40px auto; &.false-active{ background: url('~@/assets/images/serve1-1.png') no-repeat center center; background-size: 40px auto; } &.true-active{ &::before{ content: ""; position: absolute; left: 50%; bottom: -10px; width: 1px; height: 16px; background-color:#9098a4; margin-left: -1px; } &::after{ content: ""; position: absolute; left: 0; bottom: -10px; width: 100%; height: 1px; background-color: #9098a4; margin-left: -1px; } } } .service-list{ display: flex; justify-content: space-between; padding: 30px 40px 10px 40px; li{ position: relative; &::before{ content: ""; position: absolute; left: 50%; top: -20px; width: 1px; height: 10px; background-color: #9098a4; margin-left: -1px; } p{ width: 50px; height: 70px; font-size: 12px; } &:nth-child(1){ p{ &.false-active{ background: url('~@/assets/images/ter1-1.png') no-repeat center center; background-size: 36px auto; } &.true-active{ background: url('~@/assets/images/ter1.png') no-repeat center center; background-size: 36px auto; } } } &:nth-child(2){ p{ &.false-active{ background: url('~@/assets/images/ter2-1.png') no-repeat center center; background-size: 32px auto; } &.true-active{ background: url('~@/assets/images/ter2.png') no-repeat center center; background-size: 32px auto; } } } &:nth-child(3){ p{ &.false-active{ background: url('~@/assets/images/ter3-1.png') no-repeat center center; background-size: 36px auto; } &.true-active{ background: url('~@/assets/images/ter3.png') no-repeat center center; background-size: 36px auto; } } } &:nth-child(4){ p{ &.false-active{ background: url('~@/assets/images/ter4-1.png') no-repeat center center; background-size: 36px auto; } &.true-active{ background: url('~@/assets/images/ter4.png') no-repeat center center; background-size: 36px auto; } } } &:nth-child(5){ p{ &.false-active{ background: url('~@/assets/images/ter5-1.png') no-repeat center center; background-size: 36px auto; } &.true-active{ background: url('~@/assets/images/ter5.png') no-repeat center center; background-size: 36px auto; } } } } } .service-bottom-text{ font-size: 12px; text-align: center; } .fade-enter-active, .fade-leave-active { transition: all 0.5s ease; } .fade-enter, .fade-leave-to { opacity: 0; transform: translateY(20px); } .fade-in { animation: fadeIn 0.5s ease; } @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } </style>
|