干燥机配套车间生产管理系统/云平台服务端
baoshiwei
2023-06-07 34ff338ff4d6575f9a25457286b3a5aad6b8823b
src/views/dry/monitor/WorkShop.vue
@@ -1,87 +1,92 @@
<template>
   <div class="workshop">
      <div class="eqp-row">
         <div v-for="(item, index) in eqps" :key="index">
            <div class="eqp-card">
               <div class="eqp-content">
                  <div class="chart">
                        <div>
                        <div class="progress">
                           <div style="">
                              <div>加热</div>
                              <div></div>
                           <span class="info-text">36</span> 分钟
                           </div>
                           <div style=" padding: 0 10px;width: 200px;height: 40px;">
                              <div style="padding-top: 10px">
                                    <Progress
                                       :stroke-color="{
                                          from: '#108ee9',
                                          to: '#87d068',
                                       }"
                                       :percent="55.9"
                                       status="active"
                                       :show-info="false">
                                 </Progress>
                              </div>
                           </div>
                           <div>
                              <div>预计 </div>
                              <div><span class="info-text">90</span>  分钟
                              </div>
                           </div>
                     </div>
                     <div style="height:50px; text-align: left; padding-left: 25px; display: flex;">
                        <div class="herbInfo">
                           <div>药材:<span class="info-text">当归</span></div>
                           <div>投料:<span class="info-text">16</span> 筐</div>
         <div class="eqp-card" v-for="(item, index) in eqps" :key="index">
            <div class="eqp-content">
               <div class="chart">
                  <div>
                     <div class="progress">
                        <div style="">
                           <div>加热</div>
                           <div></div>
                           <span class="info-text">{{ realTime.get(item.id)?.dryTime | 0 }}</span> 分钟
                        </div>
                        <div class="herbInfo">
                           <div>原始重量:<span class="info-text">160</span> Kg</div>
                           <div>实时重量:<span class="info-text">70</span> Kg</div>
                        </div>
                     </div>
                  </div>
                     <div class="eqpStatus">
                        <div > <span class="info-text">运行</span>  </div>
                     </div>
                  </div>
                  <!-- <div :id="'chartDom' + item.id" class="chart"> </div> -->
                  <div class="info">
                     <div class="leftInfo">
                        <!-- <div class="herbName"> 当归 </div> -->
                        <div class="eqpName">{{ item.name }}</div>
                        <div style="padding: 0 10px; width: 200px; height: 40px">
                           <div style="padding-top: 10px">
                              <Progress
                                 :stroke-color="{
                                    from: '#108ee9',
                                    to: '#87d068',
                                 }"
                                 :percent="realTime.get(item.id)?.percent"
                                 status="active"
                                 :show-info="false"
                              />
                           </div>
                        </div>
                        <div>
                           <div>预计 </div>
                           <div
                              ><span class="info-text">{{ (realTime.get(item.id)?.dryTime + realTime.get(item.id)?.remain) | 0 }}</span> 分钟
                           </div>
                        </div>
                     </div>
                     <div class="rightInfo">
                        <div style="width: 120px" >
                           <div style="    height: 1px;
    font-size: 10px;
    text-align: center;
    margin-top: 10px;
    margin-bottom: -10px; ">初始:{{ (mois[0] * 100).toFixed(2) }}%</div>
                           <div :id="'moisture' + item.id" style="width: 110px; height: 187px"></div>
                           <div style="height: 1px;
    font-size: 10px;
    text-align: center;
    margin-top: -25px;">目标:{{ (mois[2] * 100).toFixed(2) }}%</div>
                           <div style="    width: 110px;
    text-align: center;
    margin-top: 23px;">含水率</div>
                     <div style="height: 50px; text-align: left; padding-left: 25px; display: flex">
                        <div class="herbInfo">
                           <div
                              >药材:<span class="info-text">{{ realTime.get(item.id)?.herbName }}</span></div
                           >
                           <div
                              >投料:<span class="info-text">{{ realTime.get(item.id)?.feed | 0 }}</span> 筐</div
                           >
                        </div>
                        <div class="tempChart"   style="pointer-events: none; cursor: none;"  :id="'tempDom' + item.id">
                           <a-slider v-model:value="tempValue"
                            :min="0" range :max="100" :marks="marks" vertical />
                            <div>热风:<span class="info-text">{{ tempValue[0] }}</span> °C</div>
                        <div class="herbInfo">
                           <div
                              >原始重量:<span class="info-text">{{ realTime.get(item.id)?.originWeight | 0 }}</span> Kg</div
                           >
                           <div
                              >实时重量:<span class="info-text">{{ realTime.get(item.id)?.yield | 0 }}</span> Kg</div
                           >
                        </div>
                     </div>
                  </div>
                  <div class="eqpStatus">
                     <div> <span class="info-text">翻料</span> </div>
                  </div>
               </div>
               <!-- <div :id="'chartDom' + item.id" class="chart"> </div> -->
               <div class="info">
                  <div class="leftInfo">
                     <div style="width: 120px">
                        <div style="height: 1px; font-size: 10px; text-align: center; margin-top: 10px; margin-bottom: -10px"
                           >初始:{{ realTime.get(item.id)?.initial }}%</div
                        >
                        <div :id="'moisture' + item.id" style="width: 110px; height: 187px"></div>
                        <div style="height: 1px; font-size: 10px; text-align: center; margin-top: -25px">目标:{{ realTime.get(item.id)?.target }}%</div>
                        <div style="width: 110px; text-align: center; margin-top: 23px">含水率</div>
                     </div>
                     <!-- <div class="herbName"> 当归 </div> -->
                     <div style="flex: 1" @click="gotoEqp(item.id)"
                        ><div class="eqpName">{{ item.name }}</div></div
                     >
                  </div>
                  <div class="rightInfo">
                     <div class="tempChart" style="pointer-events: none; cursor: none" :id="'tempDom' + item.id">
                        <a-slider
                           v-if="realTime.get(item.id)"
                           v-model:value="realTime.get(item.id).tempValue"
                           :min="0"
                           range
                           :max="100"
                           :marks="marks"
                           vertical
                        />
                        <div
                           >热风:<span class="info-text">{{ realTime.get(item.id)?.windTemp | 0 }}</span> °C</div
                        >
                     </div>
                  </div>
               </div>
@@ -92,17 +97,22 @@
</template>
<script setup lang="ts">
   import { onMounted, ref } from 'vue'
   import { onMounted, ref, onUnmounted } from 'vue'
   import { Progress } from 'ant-design-vue'
   import * as echarts from 'echarts'
   import 'echarts-liquidfill'
   import { listAll } from '../api/DryEquipment.api'
   import { dryEquipment } from '../dataDefine/DryEquipment.data'
   import { router } from '/@/router'
   import { defHttp } from '/@/utils/http/axios'
   import { useUserStore } from '/@/store/modules/user'
   const eqps = ref([] as dryEquipment[])
   const mois = ref([0.3939,0.2112,0.11])
   const mois = ref([0, 0, 0])
   const userStore = useUserStore()
   const Timer = ref()
   const tempValue = ref(<Record<number, number>>([70, 100]))
   const realTime = ref(new Map())
   const marks = ref<Record<number, any>>({
      0: '0°C',
@@ -212,7 +222,8 @@
         .then((result) => {
            console.log(`output->result`, result)
            eqps.value = result
            setTimeout(initCharts, 1000)
            setTimeout(initCharts, 500)
            updateRealTime()
         })
         .catch((err) => {
            console.log(`output->err`, err)
@@ -221,150 +232,206 @@
   // var wetCharts: Map<string, echarts.ECharts> = new Map()
      var moistureCharts: Map<String, echarts.ECharts> = new Map()
   var moistureCharts: Map<String, echarts.ECharts> = new Map()
    function initCharts() {
   //    console.log(`output->initChart`)
       eqps.value.forEach((item) => {
   //       console.log(`output->item.id`, item.id)
          let domId = 'moisture' + item.id
   //       console.log(`output->domId`, domId)
          var chartDom: HTMLElement = document.getElementById(domId) as HTMLElement
   //       console.log(`output->chartDom`, chartDom)
          let myChart = echarts.init(chartDom)
       //   var option
//           option = {
//             grid: {
//                left: 30,
//                top: 15,
//                bottom: 13,
//                right: 45
//             },
//   xAxis: {
//     type: 'category',
//       show: false,
//     data: ['含水率'],
//       axisLine: {
//          show: false,
//       },
//       axisTick: {
//          show: false,
//       }
//   },
//   yAxis: {
//     type: 'value',
//       axisLine: {
//          show: false,
//       },
//       min: 0,
//       max: 100,
//       axisTick: {
//          show: true,
//       },
//       splitLine: {
//          show: false
//       }
//   },
//   series: [
//     {
//       data: [20],
//       type: 'bar',
//       showBackground: true,
//       backgroundStyle: {
//         color: 'rgba(180, 180, 180, 0.2)'
//       },
//          label: {
//             show: true,
//          },
//          barWidth: 20,
//          markLine: {
//             symbol: 'none',
//             data: [
//                {symbol: 'none',
//                   xAxis:0,
//                   x:60,
//                   yAxis:60,
//                   lineStyle:{
//                      color: '#000',
//                      width:1,
//                   },
//                   label: {
//                      formatter: '初始\n'+ '{c}%'
//                   }
//                },
//                {symbol: 'none',
//                   xAxis:0,
//                   x:60,
//                   yAxis:11,
//                   lineStyle:{
//                      color: '#000',
//                      width:1,
//                   },
//                   label: {
//                      formatter: '目标\n'+ '{c}%'
//                   }
//                },
   function initCharts() {
      //    console.log(`output->initChart`)
      eqps.value.forEach((item) => {
         //       console.log(`output->item.id`, item.id)
         let domId = 'moisture' + item.id
         //       console.log(`output->domId`, domId)
         var chartDom: HTMLElement = document.getElementById(domId) as HTMLElement
         //       console.log(`output->chartDom`, chartDom)
         let myChart = echarts.init(chartDom)
         //   var option
         //           option = {
         //             grid: {
         //                left: 30,
         //                top: 15,
         //                bottom: 13,
         //                right: 45
         //             },
         //   xAxis: {
         //     type: 'category',
         //       show: false,
         //     data: ['含水率'],
         //       axisLine: {
         //          show: false,
         //       },
         //       axisTick: {
         //          show: false,
         //       }
         //   },
         //   yAxis: {
         //     type: 'value',
//                // {yAxis: 0},
//                // {yAxis: 100}
//             ]
//          }
//     },
//   ]
// };
const option = {
         //       axisLine: {
         //          show: false,
         //       },
         //       min: 0,
         //       max: 100,
         //       axisTick: {
         //          show: true,
         //       },
         //       splitLine: {
         //          show: false
         //       }
         //   },
         //   series: [
         //     {
         //       data: [20],
         //       type: 'bar',
         //       showBackground: true,
         //       backgroundStyle: {
         //         color: 'rgba(180, 180, 180, 0.2)'
         //       },
         //          label: {
         //             show: true,
         //          },
         //          barWidth: 20,
         //          markLine: {
         //             symbol: 'none',
         //             data: [
         //                {symbol: 'none',
         //                   xAxis:0,
         //                   x:60,
         //                   yAxis:60,
    series: [{
        type: 'liquidFill',
            radius: '100%',
            //waveAnimation: false,
            amplitude: 3,
        animationDuration: 5,
        //animationDurationUpdate: 0,
        data: mois.value,
            shape: 'path://M828.817,706.209C828.817,881.725,686.98,1024,512,1024c-174.98,0-316.817-142.275-316.817-317.791C195.183,530.74,512,0,512,0s316.817,530.74,316.817,706.209z',
            outline: {
            show: false
        },
            label: {
         //                   lineStyle:{
         //                      color: '#000',
         //                      width:1,
               formatter: function(params) {
                  console.log(`output->params`,params,mois.value)
         //                   },
         //                   label: {
         //                      formatter: '初始\n'+ '{c}%'
         //                   }
         //                },
         //                {symbol: 'none',
         //                   xAxis:0,
         //                   x:60,
         //                   yAxis:11,
                  return ''
                  // +'初始'+(mois.value[0]*100).toFixed(2) + '%\n\n\n'
                  + (mois.value[1]*100).toFixed(2) + '%'
                  // + '\n\n\n目标'+(mois.value[2]*100).toFixed(2) + '%'
                  ;
         //                   lineStyle:{
         //                      color: '#000',
         //                      width:1,
         //                   },
         //                   label: {
         //                      formatter: '目标\n'+ '{c}%'
         //                   }
         //                },
         //                // {yAxis: 0},
         //                // {yAxis: 100}
         //             ]
         //          }
         //     },
         //   ]
         // };
         const option = {
            series: [
               {
                  type: 'liquidFill',
                  radius: '100%',
                  //waveAnimation: false,
                  amplitude: 3,
                  animationDuration: 5,
                  //animationDurationUpdate: 0,
                  data: mois.value,
                  shape:
                     'path://M828.817,706.209C828.817,881.725,686.98,1024,512,1024c-174.98,0-316.817-142.275-316.817-317.791C195.183,530.74,512,0,512,0s316.817,530.74,316.817,706.209z',
                  outline: {
                     show: false,
                  },
                  label: {
                     formatter: function () {
                        //console.log(`output->params`,params,mois.value)
                        return (
                           '' +
                           // +'初始'+(mois.value[0]*100).toFixed(2) + '%\n\n\n'
                           (mois.value[1] * 100).toFixed(2) +
                           '%'
                           // + '\n\n\n目标'+(mois.value[2]*100).toFixed(2) + '%'
                        )
                     },
                     fontSize: 10,
                     //position: ['50%',(100-mois.value[1]*100).toFixed(2) + '%'],
                  },
               },
               fontSize: 10,
               position: ['50%',(100-mois.value[1]*100).toFixed(2) + '%'],
            ],
         }
         option && myChart.setOption(option)
         moistureCharts.set(item.id, myChart)
      })
   }
   function gotoEqp(id: string) {
      router.push('/dashboard/eqp/' + id)
   }
   function updateRealTime() {
      console.log(`output->定时刷新数据`)
      eqps.value.forEach((item) => {
         queryRealTime(item)
      })
   }
   function queryRealTime(eqp: dryEquipment) {
      let tenantId = userStore.getTenant
      let eqpCode = eqp.code
      let queryRealTimeUrl = '/dry/real/getRealTimeData'
      defHttp.get({ url: queryRealTimeUrl, params: { tenantid: tenantId, machineid: eqpCode } }).then((res) => {
         console.log(`output->res`, res)
         if (res && res.trendVo) {
            res.tempValue = [res.windTemp, 100]
            res.percent = ((res.dryTime / res.et) * 100).toFixed(2)
            res.mois = [
               (res.trendVo.moisture / 100).toFixed(2),
               (res.trendVo.moisture / 100 / 1.5).toFixed(2),
               (res.trendVo.moisture / 100 / 3).toFixed(2),
            ]
            moistureCharts.get(eqp.id)?.setOption({
               series: [
                  {
                     data: res.mois,
                     label: {
                        formatter: function () {
                           return res.trendVo.moisture + '%'
                        },
                        fontSize: 10,
                        //position: ['50%',(100- res.trendVo.moisture)+ '%'],
                     },
                  },
               ],
            })
         } else {
            res = {
               tempValue: [0, 100],
               percent: 0,
               mois: [],
            }
    }]
};
         }
          option && myChart.setOption(option)
          moistureCharts.set(item.id, myChart)
       })
    }
         realTime.value.set(eqp.id, res)
      })
   }
   listAllEqp()
   // DOM挂载完成后渲染图表
   onMounted(() => {})
   onMounted(() => {
      Timer.value = setInterval(updateRealTime, 3000)
   })
   onUnmounted(() => {
      clearInterval(Timer.value)
      Timer.value = null
   })
</script>
<style>
<style scoped>
   .workshop {
   }
   .eqp-row {
@@ -376,6 +443,8 @@
      width: 566px;
      height: 400px;
      padding: 6px 6px;
      flex-grow: 0;
      flex-shrink: 0;
   }
   .eqp-content {
@@ -384,7 +453,7 @@
      background-image: url('../../../assets/images/dry/ganzaoji-x.png');
      background-repeat: no-repeat;
      background-size: 60% 60%;
      background-position: 10px 150px;
      background-position: 105px 150px;
      border-radius: 8px;
   }
@@ -395,30 +464,31 @@
      display: flex;
      text-align: center;
   }
   .progress {
      padding:25px 25px;
   :deep() .progress {
      padding: 25px 25px;
      width: 360px;
      display: flex;
   }
   .ant-progress-bg {
   :deep() .ant-progress-bg {
      height: 25px !important;
   }
   .eqpStatus {
      width:170px;
      background-position: 0 -10px;
      background-image: url('../../../assets/images/dry/ganzaoji.gif');
      background-size: 100% 100%;
      width: 170px;
      background-position: 0 0px;
      background-image: url('../../../assets/images/dry/refeng2.gif');
      background-size: 180px;
      background-repeat: no-repeat;
      display: inline-flex;
      flex-direction: column-reverse;
      padding: 15px;
   }
   .info {
      display: flex;
   }
   .leftInfo {
      width: 335px;
      width: 445px;
      display: flex;
      /* background: gray; */
   }
   .rightInfo {
@@ -445,29 +515,29 @@
   }
   .eqpName {
      margin-top: 68px;
      margin-left: 174px;
      margin-left: 150px;
      width: 95px;
      font-weight: bold;
      text-align: center;
      background-color: white;
      height: 22px;
   }
   .tempChart {
      padding-top: 10px;
      height: 150px;
      width: 100px;
   }
   .herbInfo {
   width: 160px;
      width: 160px;
   }
   .ant-slider-mark-text {
   :deep() .ant-slider-mark-text {
      padding-left: 15px;
      font-size: 10px;
   }
   .ant-slider-mark-text::before {
   :deep() .ant-slider-mark-text::before {
      content: '';
      display: block;
      width: 6px;
@@ -478,30 +548,30 @@
      top: 10px;
      left: 0px;
   }
   .ant-slider-rail {
   :deep() .ant-slider-rail {
      width: 6px !important;
      border-radius: 6px 6px 0 0;
      background: linear-gradient(to top, #ce0000 0%, #ce0000 40%, #ce0000 75%, rgb(160, 160, 160) 100%);
   }
   .ant-slider-track {
   :deep() .ant-slider-track {
      background: rgb(175, 175, 175);
      height: 20px;
      width: 6px !important;
      border-radius: 6px 6px 0 0;
   }
   .ant-slider-track:hover {
   :deep() .ant-slider-track:hover {
   }
   .ant-slider-handle {
   :deep() .ant-slider-handle {
      display: none;
   }
   .ant-slider-dot {
   :deep() .ant-slider-dot {
      display: none;
   }
   .ant-slider-step {
   :deep() .ant-slider-step {
      width: 10px !important;
   }
   .ant-slider-step > :first-child {
   :deep() .ant-slider-step > :first-child {
      display: block !important;
      width: 22px !important;
      height: 22px !important;