src/views/visualization.vue
@@ -104,7 +104,8 @@
                      style="font-size: 35px; font-weight: 600"
                      class="color_green"
                    >
                      {{ processingStatistics(taskData).finishNumber }}{{ taskData.Order.unit }}
                      {{ processingStatistics(taskData).finishNumber }}
<!--                      {{ taskData.Order.unit }}-->
                    </dd>
                  </dl>
                </div>
@@ -117,7 +118,8 @@
                      style="font-size: 35px; font-weight: 600"
                      class="color_green"
                    >
                      {{ processingStatistics(taskData).totalNumber }}{{ taskData.Order.unit }}
                      {{ processingStatistics(taskData).totalNumber }}
<!--                      {{ taskData.Order.unit }}-->
                    </dd>
                  </dl>
                </div>
@@ -125,8 +127,8 @@
            </div>
            <div class="content_right">
              <div class="gif" v-if="taskData.Procedure.ID" @click="processModelClick(taskData,index)">
                    <img v-if="taskData.isUpdateIcon"  src="../../public/shan.gif" />
                    <span v-else class="yuandian"></span>
                    <img class="blink" v-if="taskData.isUpdateIcon"  src="../../public/shan.gif" />
                    <span v-else class="tip"></span>
               </div>
              <el-descriptions :column="(activeName == 1||activeName == 3) ? 2 : 1" :colon="true">
                <el-descriptions-item label="产品名称">{{
@@ -143,9 +145,9 @@
                  {{ taskData.Procedure.procedure.workHours || "--" }}
                </el-descriptions-item>
                <el-descriptions-item label="计划时间"
                  >{{ formatDate(taskData.Order.startTime) || "--" }}
                  >{{ formatDate(taskData.Procedure.startTime) || "--" }}
                  -
                  {{ formatDate(taskData.Order.endTime) }}</el-descriptions-item
                  {{ formatDate(taskData.Procedure.endTime) }}</el-descriptions-item
                >
                <el-descriptions-item label="通道">
                  {{ channelNameConfig[taskData.Channel] || "--" }}
@@ -304,7 +306,7 @@
                      </div>
                      <div class="card_top-2">
                        <div style="line-height: 45px; text-align: center">
                          {{ taskData.Procedure.Status==3?'生产完成':'生产中' }}
                          {{ displayProcedureStatus(taskData) }}
                        </div>
                        <!-- <span class="card-top-r-t">完成进度:50%</span>
                          <span class="card-top-r-b">12月28日 08:24</span> -->
@@ -354,10 +356,11 @@
                  class="button-finish"
                  v-model="finishShow['finishShow&'+index]"
                  trigger="click"
                  :ref="'popoverRef_' + index"
                >
                  <p><i class="el-icon-error" style="color:red;margin-right:5px;"/>请确认是否已完成该生产任务?</p>
                  <div style="text-align: right; margin: 0">
                    <el-button size="mini" @click="finishShow['finishShow&'+index] = false">
                    <el-button size="mini" @click="closePopover(index)">
                      取消</el-button
                    >
                    <el-button
@@ -465,26 +468,28 @@
        </div>
        <div class="right-top-m">
          设备状态:
          <!-- 1断开2生产3待机 -->
          <span style="position: relative" v-if="plcStatus" >
            <el-popover
              v-if="plcStatus == 1&&plcNotConnected"
              width="180"
              :content="plcNotConnected"
              placement="top-end"
              trigger="click"
            >
              <span slot="reference">
                <img  src="../../public/duan.png" />
                断开
          <template v-for="(plcStatus, channel) in displayPLCStatus">
             <!-- 1断开2生产3待机 -->
            <span class="plc-status" style="position: relative" v-if="plcStatus">
              <el-popover
                v-if="plcStatus === 1&&plcNotConnected"
                width="180"
                :content="plcNotConnected"
                placement="top-end"
                trigger="click"
              >
                <span slot="reference">
                  <img src="../../public/duan.png"/>
                  断开
                </span>
              </el-popover>
              <span v-else>
                <img v-if="plcStatus === 1&&!plcNotConnected" src="../../public/duan.png"/>
                <img v-else src="../../public/lian.png"/>
                {{ plcStatus === 1 ? '断开' : (plcStatus === 2 ? '生产中' : '待机') }}
              </span>
            </el-popover>
            <span v-else>
              <img  v-if="plcStatus == 1&&!plcNotConnected"  src="../../public/duan.png" />
              <img  v-else src="../../public/lian.png" />
              {{ plcStatus==1?'断开':(plcStatus==2?'生产中':'待机') }}
            </span>
          </span>
          </template>
        </div>
        <div class="right-top-m-btn">
          <!-- <el-button type="primary" @click="controlClick"> 控制</el-button> -->
@@ -726,7 +731,7 @@
      cutdownTimer: null,
      ProcessModelTimer: null,
      TaskCount:0,
      plcStatus:0,
      PLCStatusMap:{0:0,1:0},
      isTipShow:false,
      // isFinsh:0,
      safeProduce:'',
@@ -781,31 +786,62 @@
    //   }
    // }
  },
  methods: {
    processingStatistics(taskData){
      const status = taskData?.Procedure?.Status;
    //   如果status = 2 加工中, 则加工数和目标数应取轮询接口中的 finishNumber 和 totalNumber
      // 如果status = 1 未开始, 目标数 取 taskData.Order.amount  加工数取 0
      // 如果status = 3 已完成, 目标数和加工数都取 amount
      let finishNumber = 0;
      let totalNumber = 0;
      if (status === 1){
        totalNumber = taskData?.Order?.amount ?? 0
        finishNumber = 0
      }else if (status === 2){
        totalNumber = taskData?.totalNumber ?? 0
        finishNumber = taskData?.finishNumber ?? 0
      }else if (status === 3){
        totalNumber = taskData?.Order?.amount  ?? 0
        finishNumber = taskData?.Order?.amount ?? 0
  computed:{
    displayPLCStatus(){
      let PLCStatus = []
      if (this.activeName===1){
        PLCStatus =[this.PLCStatusMap[0]]
      }else if (this.activeName===2){
        PLCStatus =[this.PLCStatusMap[0],this.PLCStatusMap[1]]
      }else if (this.activeName===3){
        PLCStatus =[this.PLCStatusMap[1]]
      }else {
        return []
      }
      console.log({
        /** 目标数 */
        totalNumber: +totalNumber,
        /** 加工数 */
        finishNumber: +finishNumber,
      })
      return PLCStatus
    }
  },
  methods: {
    newTaskPlaceholder(channel){
      return {
        Order: {},
        Procedure: {
          procedure: { inputMaterials: [], outputMaterials: [], workers: [] },
        },
        Channel:channel,
        inputMaterials: [],
        outputMaterials: [],
        procedureList: [],
      }
    },
    /**
     * 展示工序状态
     * 如果PLC的状态是待机要跟随PLC状态
     * @param taskData
     * @return {string}
     */
    displayProcedureStatus(taskData){
      if (taskData?.plcStatus === 3){
        return '待机'
      }
      if (!taskData?.Procedure?.Status){
        return ''
      }
      if (taskData.Procedure.Status===3){
        return '生产完成'
      }else{
        return '生产中'
      }
    },
    /**
     * 从任务中获取加工数和目标数
     * @param taskData
     * @return {{totalNumber: number, finishNumber: number}}
     */
    processingStatistics(taskData){
      const totalNumber = taskData?.totalNumber ?? 0
      const finishNumber = taskData?.finishNumber ?? 0
      return {
        /** 目标数 */
@@ -816,10 +852,13 @@
    },
    /**
     * 计算生产进度
     * @param statistics
     * @param {{totalNumber: number, finishNumber: number}} statistics
     * @return {number}  进度,0~100
     */
    calculateProgress(statistics){
      if (statistics.finishNumber === 0){
        return 0
      }
      if (statistics.finishNumber === statistics.totalNumber){
        return 100
      }
@@ -1119,29 +1158,22 @@
      this.TasksCopy=[]
      getTaskInfo({taskMode:2}).then((res) => {
        if (res.code == 200&&res.data) {
          // let arr=[]
          if(res.data.Tasks){
            res.data.Tasks.sort(function(a,b){
            return (a.Channel - b.Channel)
           })
          }
          this.TasksCopy = res.data.Tasks ? res.data.Tasks : [];
          this.TasksCopy = res.data?.Tasks ?? [];
          // this.safeProduce=res.data.Prompt.safeProduce?res.data.Prompt.safeProduce:''
          this.plcNotConnected=res.data.Prompt.plcNotConnected?res.data.Prompt.plcNotConnected:''
          this.ChannelAmount=res.data.ChannelAmount?res.data.ChannelAmount:1
          this.plcNotConnected=res.data.Prompt.plcNotConnected ?? ''
          this.ChannelAmount=res.data.ChannelAmount ?? 1
          // if(this.ChannelAmount>1 &&this.TasksCopy.length<2){
          //   this.TasksCopy.push(this.object)
          // }
          this.TaskCount=res.data.TaskCount?res.data.TaskCount:0
          this.TaskCount=res.data.TaskCount ?? 0
          if ((this.TasksCopy.length ==0 )||!this.TasksCopy) {
            if (this.activeName == 1||this.activeName == 3) {
              this.TasksCopy.push(this.object);
            } else {
              this.TasksCopy.push(this.object);
              this.TasksCopy.push(this.object);
            }
          }
          // 找出缺少任务数据的通道, 使用占位数据占住对应通道
          const channelNumbers = this.TasksCopy.map(task=>task.Channel)
          const allChannels = [0,1];
          const lackChannels = _.chain(allChannels).difference(channelNumbers).value()
          lackChannels.forEach(channel => this.TasksCopy.push(this.newTaskPlaceholder(channel)))
          this.TasksCopy.sort((a,b)=>a.Channel - b.Channel)
          this.workers=res.data.workers?res.data.workers:[]
          // 将值班人根据通道号分组
@@ -1159,6 +1191,7 @@
            this.TasksCopy[i].outputMaterials = [];
            this.TasksCopy[i].finishNumber = 0;
            this.TasksCopy[i].totalNumber = 0;
            this.TasksCopy[i].plcStatus = 0;
            this.TasksCopy[i].number=0;
            this.TasksCopy[i].isUpdateIcon=false;
            this.finishShow['finishShow&'+i]=false
@@ -1275,7 +1308,8 @@
            if (res.code == 200) {
              this.TasksCopy[i].finishNumber = res.data?.finishNumber ?? 0;
              this.TasksCopy[i].totalNumber = res.data?.totalNumber ?? 0;
              this.plcStatus = res.data?.plcStatus ?? 0
              this.TasksCopy[i].plcStatus = res.data?.plcStatus ?? 0
              this.PLCStatusMap[i] = res.data?.plcStatus ?? 0
            }
            this.resprocInfoTimer=res;
          });
@@ -1318,6 +1352,15 @@
      } else {
        this.$message.error("当前设备没有工序!");
      }
    },
    /**
     * 关闭 tooltip
     * @param index
     */
    closePopover(index){
      this.finishShow['finishShow&'+index] = false
      this.$refs?.['popoverRef_' + index]?.[0]?.doClose()
    },
    getRandomNumber(min, max) {
      return Math.floor(Math.random() * (max - min + 1) + min);
@@ -1609,6 +1652,28 @@
        // margin-top:-5px;
        vertical-align: middle;
      }
.tip {
  display:inline-block;
  // background: #15d815;
  background:red;
  border-radius: 50%;
  // margin-top:-5px;
  vertical-align: middle;
}
.blink{
  display: inline-block;
  width: 14px;
  height: 14px;
}
.tip, .blink{
  position: absolute;
  top: -6px;
  right: -6px;
  width: 14px;
  height: 14px;
}
.bottom_list {
  position: relative;
  padding: 10px;
@@ -1817,15 +1882,18 @@
        border-radius: 6px;
        position:relative;
        .gif{
          background: url("../../public/setting.png") no-repeat;
          background-size:100% 100%;
          position:absolute;
          right:15px;
          top:10px;
          width:35px;
          height: 35px;
          vertical-align: middle;
          cursor:pointer;
          img{
            width:100%;
          }
          //img{
          //  width:100%;
          //}
        }
        // background: #233b9e;
        .el-descriptions-row{
@@ -2197,4 +2265,24 @@
    padding: 12px;
  }
}
.plc-status{
  margin-right: 24px;
  position: relative;
  display: inline-block;
  height: 50px;
  &:after{
    content: '';
    position: absolute;
    top: 50%;
    right: -12px;
    margin-top: -15px;
    border-right: 2px solid #ffffff;
    height: 30px;
  }
}
.plc-status:last-child{
  &:after{
    display: none;
  }
}
</style>