cuijian
2025-07-28 accebdce93486d3b4f26e55ffdea047549cce20c
src/views/mdc/base/modules/efficiencyPOReport/EfficiencyPOList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,673 @@
<template>
  <div style="width: 100%;">
    <div :bordered="false">
      <!-- æŸ¥è¯¢åŒºåŸŸ -->
      <div class="table-page-search-wrapper">
        <a-form layout="inline" @keyup.enter.native="searchQuery">
          <a-row :gutter="24">
            <a-col :md="5" :sm="5">
              <a-form-item label="设备类型">
                <a-select
                  :value="queryParams.equipmentType"
                  mode="multiple"
                  placeholder="请选择设备类型"
                  allow-clear
                  :maxTagCount="1"
                  @change="selectChange($event,'equipmentType')"
                >
                  <a-select-option v-for="(item,index) in equipmentTypeList" :value="item.value" :key="index">
                    {{item.label}}
                  </a-select-option>
                </a-select>
              </a-form-item>
            </a-col>
            <a-col :md="5" :sm="5">
              <a-form-item label="驱动类型">
                <a-select
                  :value="queryParams.driveType"
                  mode="multiple"
                  placeholder="请选择驱动类型"
                  allow-clear
                  :maxTagCount="1"
                  @change="selectChange($event,'driveType')"
                >
                  <a-select-option v-for="(item,index) in driveTypeList" :value="item.value" :key="index">
                    {{item.label}}
                  </a-select-option>
                </a-select>
              </a-form-item>
            </a-col>
            <a-col :md="6" :sm="6">
              <a-form-item label="时间">
                <a-range-picker @change="dateParamChange" :disabledDate="disabledDate" format="YYYYMMDD" v-model="dates" :allowClear="false"/>
              </a-form-item>
            </a-col>
          </a-row>
          <a-row :gutter="24" type="flex" align="middle">
            <a-col :md="24" :sm="24" :xs="24"
                   style="display: flex;justify-content: space-between;align-items: flex-start">
              <div>
                <a-space style="margin-right: 20px">
                  <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
                  <a-button type="primary" @click="searchReset" icon="reload">重置</a-button>
                  <a-button type="primary" @click="exportExcel" icon="download">导出</a-button>
                  <a-button type="primary" icon="printer" v-print="'#EfficiencyPO'"
                            v-has="'EfficiencyPO:print'">打印
                  </a-button>
                </a-space>
                <a-checkbox-group :value="checkedList" :default-value="['lyl']" :options="efficiencyOptions"
                                  @change="efficiencyOptionsOnChange"/>
              </div>
              <table cellpadding="5" cellspacing="1" style="border: 1px solid darkgray;">
                <tr>
                  <td v-for="(item, index) in identifying">{{item.title}}</td>
                </tr>
                <tr>
                  <td style="text-align:center;" v-for="(item, index) in identifying">
                    <div class="identifyingclass" :style="{background: item.color}"></div>
                  </td>
                </tr>
              </table>
            </a-col>
          </a-row>
        </a-form>
      </div>
      <a-spin :spinning="spinning">
        <div class="container" id="EfficiencyPO" style="margin-top: 20px;" >
          <div class="table2">
            <table class="dataContent table" border="1" cellspacing="0" cellpadding="0" style="white-space: nowrap" v-if="dataList.length>0">
              <thead>
              <tr class="thead fixed equipname">
                <th class="thgu dong1 name" rowspan="2" style="min-width: 50px; max-width: 50px;width: 50px;height: 66px">公司</th>
                <th  class="thgu dong2 name" rowspan="2" style="min-width: 50px; max-width: 50px;width: 50px;">车间</th>
                <th  class="thgu dong3 name" rowspan="2" style="min-width: 50px; max-width: 50px;width: 50px;">工段</th>
                <th class="thgu dong4 name" rowspan="2" style="min-width: 100px; max-width: 100px;width: 100px;">设备编号</th>
                <th class="thgu dong5 name" rowspan="2" style="min-width: 162px; max-width: 162px;width: 162px;">安装位置</th>
                <th class="thgu dong6 name" rowspan="2" style="min-width: 100px; max-width: 100px;width: 100px;">设备类型</th>
                <!--<th rowspan="2">组别</th>-->
                <template v-for="(tableHead, index) in tableHeads">
                  <th class="timeth" :colspan="checkedList.length">{{tableHead}}</th>
                </template>
              </tr>
              <tr class="thead notfixed gudingth">
                <template v-for="(tableHead, index) in tableHeads">
                  <th v-if="checkedList.indexOf('lyl') > -1">开动率(%)</th>
                  <th v-if="checkedList.indexOf('kjl') > -1">开机率(%)</th>
                  <th v-if="checkedList.indexOf('kjsj') > -1">开机时间(小时)</th>
                  <th v-if="checkedList.indexOf('jgsj') > -1">加工时间(小时)</th>
                  <th v-if="checkedList.indexOf('djsj') > -1">待机时间(小时)</th>
                  <th v-if="checkedList.indexOf('gjsj') > -1">关机时间(小时)</th>
                </template>
              </tr>
              </thead>
              <tbody>
              <tr class="mathData" v-for="(item, index) in dataList">
                <template v-if="item.level1!=='合计'&&item.level1!=='平均值'">
                  <td  class="tdgu kaitou" :rowspan="item.level1span" :class="{hidden: item.level1dis,noExl:item.level1dis}"  v-show="!item.level1dis">
                    <div class="wenzi">
                      {{item.level1}}
                    </div>
                  </td>
                  <td  class="tdgu1 kaitou" :rowspan="item.level2span" :class="{hidden: item.level2dis,noExl:item.level2dis}"  v-show="!item.level2dis">
                    <div class="wenzi">
                      {{item.level2}}
                    </div>
                  </td>
                  <td  class="tdgu2 kaitou" :rowspan="item.level3span" :class="{hidden: item.level3dis,noExl:item.level3dis}"  v-show="!item.level3dis">
                    <div class="wenzi">
                      {{item.level3}}
                    </div>
                  </td>
                  <td  class="tdgu3  kaitou">{{item.equipmentId}}</td>
                  <td style="min-width: 162px; max-width: 162px;width: 162px;"  class="tdgu4 kaitou">{{item.equipmentName}}</td>
                  <td  class="tdgu5 kaitou">{{item.equipmentType}}</td>
                </template>
                <template v-else>
                  <td colspan="6" class="tdgu kaitou">{{item.level1}}</td>
                </template>
                <template v-for="(tableHead, index) in item.dataList">
                  <td :style="{background:tableHead.color }" v-if="checkedList.indexOf('lyl') > -1">{{tableHead.startRate | numFilter}}</td>
                  <td :style="{background:tableHead.color }" v-if="checkedList.indexOf('kjl') > -1">
                    {{tableHead.openRate | numFilter}}
                  </td>
                  <td :style="{background:tableHead.color }" v-if="checkedList.indexOf('kjsj') > -1">
                    {{tableHead.openLong | getFormattedTime}}
                  </td>
                  <td :style="{background:tableHead.color }" v-if="checkedList.indexOf('jgsj') > -1">
                    {{tableHead.processLong | getFormattedTime}}
                  </td>
                  <td :style="{background:tableHead.color }" v-if="checkedList.indexOf('djsj') > -1">
                    {{tableHead.waitLong | getFormattedTime}}
                  </td>
                  <td :style="{background:tableHead.color }" v-if="checkedList.indexOf('gjsj') > -1">
                    {{tableHead.closeLong | getFormattedTime}}
                  </td>
                </template>
              </tr>
              </tbody>
            </table>
          </div>
        </div>
      </a-spin>
    </div>
  </div>
</template>
<script>
import moment from 'moment'
import { putAction, getAction } from '@/api/manage'
import $ from 'jquery'
import '@/components/table2excel/table2excel'
import { ajaxGetDictItems, getDictItemsFromCache, duplicateCheck } from '@/api/api'
import api from '@/api/mdc'
export default {
  name: 'EfficiencyPOList',
  components: {},
  data() {
    return {
      typeTree:"",
      typeParent:1,
      typeEquipment:1,
      dates: [],
      equipmentTypeList:[],
      driveTypeList:[],
      queryParam: {},
      queryParams: {
        equipmentType: [],
        driveType: [],
      },
      queryParamEquip:{},
      queryParamPeople:{},
      identifying: [],
      efficiencyOptions: [
        { label: '开动率', value: 'lyl' },
        { label: '开机率', value: 'kjl' },
        { label: '开机时间', value: 'kjsj' },
        { label: '加工时间', value: 'jgsj' },
        { label: '待机时间', value: 'djsj' },
        { label: '关机时间', value: 'gjsj' }
      ],
      checkedList: ['lyl'],
      dataList: [],
      url: {
        list: '/mdc/efficiencyReport/efficiencyPOList',
        listByType: '/mdc/MdcUtilizationRate/getByType',
        queryEquipmentType: '/mdc/mdcEquipmentType/queryEquipmentType'
      },
      tableHeads: [],
      spinning:false
    }
  },
  props: { nodeTree: '', Type:'',nodePeople: ''},
  created() {
    this.showIdentifying()
    this.dates = [moment().subtract('days', 8), moment().subtract('days', 1)]
    this.queryParam.startTime = moment(this.dates[0]).format('YYYYMMDD')
    this.queryParam.endTime = moment(this.dates[1]).format('YYYYMMDD')
    this.queryParam.typeTree = "1"
    this.loadData()
    this.queryGroup()
    this.getDriveTypeByApi()
  },
  mounted() {
    window.addEventListener('resize', this.handleWindowResize)
    this.handleWindowResize()
  },
  watch: {
    Type(valmath){
      this.dataList = [];
      this.queryParam.typeTree = valmath
    },
    nodeTree(val) { //监听currSelected å˜åŒ–,将变化后的数值传递给 getCurrSelected äº‹ä»¶
      if (JSON.stringify(val) != '{}') {
        if (val.equipmentId != null) {
          this.queryParamEquip.parentId = ''
          this.queryParamEquip.equipmentId = val.equipmentId
        } else {
          this.queryParamEquip.parentId = val.key
          this.queryParamEquip.equipmentId = ''
        }
        this.searchQuery()
      }
    },
    nodePeople(val){
      if (JSON.stringify(val) != '{}') {
        if (val.equipmentId != null) {
          this.queryParamPeople.parentId = val.equipmentId
          this.queryParamPeople.equipmentId = ''
        } else {
          this.queryParamPeople.parentId = val.key
          this.queryParamPeople.equipmentId = ''
        }
        this.searchQuery()
      }
    }
  },
  filters: {
    numFilter(value) {
      if (value) {
        return parseFloat((value * 100).toFixed(2))
      } else {
        return '0'
      }
    },
    /**
     * æ ¼å¼åŒ–æ—¶é—´
     * @param seconds ç§’æ•°
     * @returns '' æ ¼å¼åŒ–后时间字符串
     */
    getFormattedTime(seconds) {
      if (seconds) {
        return parseFloat((seconds / 3600).toFixed(2))
      } else {
        return '0'
      }
    },
  },
  methods: {
    selectChange(value, key) {
      this.queryParams[key] = value
    },
    checkSameData(dataList){
      let cache = {};  //存储的是键是kclx çš„值,值是kclx åœ¨indeces中数组的下标
      let indices = [];  //数组中每一个值是一个数组,数组中的每一个元素是原数组中相同kclx的下标
      dataList.map((item,index)=>{
        let level1 = item.level1;
        let _index = cache[level1];
        if(_index!==undefined){
          indices[_index].push(index)
        }else{
          cache[level1] = indices.length
          indices.push([index])
        }
      })
      let result = [];
      indices.map((item)=>{
        item.map((index)=>{
          result.push(dataList[index])
        })
      })
      this.dataList = result
    },
    checkSameData1(dataList){
      let cache = {};  //存储的是键是kclx çš„值,值是kclx åœ¨indeces中数组的下标
      let indices = [];  //数组中每一个值是一个数组,数组中的每一个元素是原数组中相同kclx的下标
      dataList.map((item,index)=>{
        let level2 = item.level2;
        let _index = cache[level2];
        if(_index!==undefined){
          indices[_index].push(index)
        }else{
          cache[level2] = indices.length
          indices.push([index])
        }
      })
      let result = [];
      indices.map((item)=>{
        item.map((index)=>{
          result.push(dataList[index])
        })
      })
      this.dataList = result
    },
    checkSameData2(dataList){
      let cache = {};  //存储的是键是kclx çš„值,值是kclx åœ¨indeces中数组的下标
      let indices = [];  //数组中每一个值是一个数组,数组中的每一个元素是原数组中相同kclx的下标
      dataList.map((item,index)=>{
        let level3 = item.level3;
        let _index = cache[level3];
        if(_index!==undefined){
          indices[_index].push(index)
        }else{
          cache[level3] = indices.length
          indices.push([index])
        }
      })
      let result = [];
      indices.map((item)=>{
        item.map((index)=>{
          result.push(dataList[index])
        })
      })
      this.dataList = result
    },
    // åˆå¹¶
    combineCell() {
      console.log(this.dataList)
      let list =this.dataList;
      for (let field in list[0]) {
        var k = 0;
        while (k < list.length) {
          list[k][field + 'span'] = 1;
          list[k][field + 'dis'] = false;
          for (var i = k + 1; i <= list.length - 1; i++) {
            if (list[k][field] == list[i][field] && list[k][field] != '') {
              list[k][field + 'span']++;
              list[k][field + 'dis'] = false;
              list[i][field + 'span'] = 1;
              list[i][field + 'dis'] = true;
            } else {
              break;
            }
          }
          k = i;
        }
      }
      return list;
    },
    disabledDate(current){
      //Can not slect days before today and today
      return current && current > moment().subtract('days', 1);
    },
    initDeviceType(deviceList) {
      let dictCode = 'mdc_equipmentType'
      let items = []
      items = getDictItemsFromCache(dictCode)
      if (deviceList && items.length > 0) {
        for (let a = 0; a < deviceList.length; a++) {
          if (items && items.length > 0) {
            for (let i = 0; i < items.length; i++) {
              if (deviceList[a].equipmentType == items[i].value) {
                deviceList[a].equipmentType = items[i].title
              }
            }
          } else {
            ajaxGetDictItems(dictCode, null).then((res) => {
              if (res.success) {
                let items = res.result
                for (let i = 0; i < items.length; i++) {
                  if (deviceList[a].equipmentType == items[i].value) {
                    deviceList[a].equipmentType = items[i].title
                  }
                }
              }
            })
          }
        }
      }
    },
    exportExcel() {
      $("#EfficiencyPO").table2excel({
        exclude: ".noExl",
        name: "Excel Document Name",
        filename: "设备开动率",
        exclude_img: true,
        fileext: ".xls",
        exclude_links: true,
        exclude_inputs: true
      });
    },
    showIdentifying() {
      getAction(this.url.listByType, { type: 'kdl' }).then(res => {
        if (res.success) {
          this.identifying = res.result
        }
      })
    },
    dateParamChange(v1, v2) {
      this.queryParam.startTime = v2[0]
      this.queryParam.endTime = v2[1]
      // ç‚¹å‡»æ—¶é—´é€‰æ‹©å™¨çš„æ¸…空按钮时会触发此判断(点击重置按钮不会触发),实现重置列表功能,切实改变列表显示效果
      if(!this.queryParam.startTime&&!this.queryParam.endTime)this.searchReset()
    },
    efficiencyOptionsOnChange(checkedList) {
      // let index = checkedList.indexOf('lyl')
      // if (index < 0) {
      //   // this.$message.warn('不能取消查询利用率')
      //   this.$notification.warning({
      //     message:'消息',
      //     description:"不能取消查询利用率"
      //   })
      //   return false
      // }
      this.checkedList = checkedList
    },
    searchQuery() {
      if(this.queryParam.typeTree == "1"){
        this.queryParam.parentId =  this.queryParamEquip.parentId
        this.queryParam.equipmentId = this.queryParamEquip.equipmentId
      }else{
        this.queryParam.parentId = this.queryParamPeople.parentId
        this.queryParam.equipmentId = ""
      }
      Object.keys(this.queryParams).forEach(item => {
        this.queryParam[item] = this.queryParams[item].join()
        // æ­¤å¤„为保证接口参数不多余,可省略
        if (this.queryParams[item].length === 0) delete this.queryParam[item]
      })
      this.loadData()
    },
    searchReset() {
      this.typeTree = this.queryParam.typeTree
      this.typeParent =  this.queryParam.parentId
      this.typeEquipment = this.queryParam.equipmentId
      this.queryParam = {}
      this.queryParam.typeTree = this.typeTree
      this.queryParam.parentId = this.typeParent
      this.queryParam.equipmentId =  this.typeEquipment
      this.dates = [moment().subtract('days', 8), moment().subtract('days', 1)]
      this.queryParam.startTime = moment(this.dates[0]).format('YYYYMMDD')
      this.queryParam.endTime = moment(this.dates[1]).format('YYYYMMDD')
      // this.ipagination.current = 1
      this.queryParams = {
        equipmentType: [],
        driveType: [],
      }
      this.loadData();
    },
    loadData() {
      this.spinning=true
      this.tableHeads = []
      this.dataList = []
      getAction(this.url.list, this.queryParam).then(res => {
        if (res.success) {
          // console.log(res.result)
          this.tableHeads = res.result.dates
          this.dataList = res.result.mdcEfficiencyList
          if (res.result.mdcEfficiencyList && !res.result.mdcEfficiencyList.length) {
            this.$notification.info({
              message: '消息',
              description: '暂无该设备类型数据'
            })
          }
          this.checkSameData(this.dataList)
          this.checkSameData1(this.dataList)
          this.checkSameData2(this.dataList)
          this.combineCell();
          // this.initDeviceType(this.dataList)
        }
      }).finally(()=>{
        this.spinning=false
      })
    },
    queryGroup() {
      getAction(this.url.queryEquipmentType).then(res => {
        if (res.success) {
          this.equipmentTypeList = res.result.map(item => {
            return {
              label: item.equipmentTypeName,
              value: item.equipmentTypeName
            }
          })
        } else {
          // this.$message.warning(res.message)
          this.$notification.warning({
            message: '消息',
            description: res.message
          })
        }
      }).finally(() => {
        this.loading = false
      })
    },
    /**
     * è°ƒç”¨æŽ¥å£èŽ·å–æŽ§åˆ¶ç³»ç»Ÿç±»åž‹
     */
    getDriveTypeByApi(){
      api.getDriveTypeApi().then((res)=>{
        if (res.success) this.driveTypeList = res.result
      })
    },
    /**
     * åˆ†è¾¨çŽ‡æ”¹å˜æ—¶åŒæ—¶æ”¹å˜è¡¨æ ¼é«˜åº¦å·²ä¿è¯é¦–é¡µä¸€è¿›å…¥ä¸æ‹–åŠ¨åž‚ç›´æ»šåŠ¨æ¡æ—¶å³å¯æ‹–åŠ¨è¡¨æ ¼æ°´å¹³æ»šåŠ¨æ¡
     */
    handleWindowResize() {
      const tableContainer = document.getElementById('EfficiencyPO') // è¡¨æ ¼å®¹å™¨
      const clientHeight = document.documentElement.clientHeight || document.body.clientHeight // æµè§ˆå™¨å¯è§†åŒºåŸŸé«˜åº¦
      const containerTopToClientTopHeight = tableContainer.getBoundingClientRect().top // è¡¨æ ¼å®¹å™¨é¡¶éƒ¨åˆ°æµè§ˆå™¨å¯è§†åŒºåŸŸé¡¶éƒ¨çš„间距
      tableContainer.style.height = (clientHeight - containerTopToClientTopHeight - 32) + 'px'
    }
  }
}
</script>
<style scoped>
/*table样式*/
.table2{
  width: 100%;
  height: 100%;
  overflow: auto;
}
.table2 thead tr th:first-child,
.table tbody tr .tdgu{
  position: sticky;
  left: 0;
  z-index: 1;
}
.table tbody tr .wenzi{
  /*writing-mode: vertical-lr;*/
  /*text-orientation: upright;*/
  transform: rotate(360deg);
  writing-mode: vertical-lr;
  letter-spacing: 2px;
}
.table tbody tr .kaitou{
  z-index: 1;
  background-color: white;
}
.table tbody tr .tdgu1{
  position: sticky;
  left: 50px;
  z-index: 2;
}
.table tbody tr .tdgu2{
  position: sticky;
  left: 100px;
  z-index: 2;
}
.table tbody tr .tdgu3{
  position: sticky;
  left: 150px;
  z-index: 2;
}
.table tbody tr .tdgu4{
  position: sticky;
  left: 250px;
  z-index: 2;
}
.table tbody tr .tdgu5{
  position: sticky;
  left: 412px;
  z-index: 2;
}
.table2 thead tr .timeth,
.table2 thead tr  .thgu {
  position: sticky;
  top:0;
  z-index: 3;
}
.table2 thead .gudingth th{
  position: sticky;
  top: 32px;
  z-index: 2;
}
.table2 thead .equipname .name{
  z-index: 3;
}
.table2 thead .equipname .dong1{
  z-index: 4;
  left: 0;
}
.table2 thead .equipname .dong2{
  z-index: 5;
  left: 50px;
}
.table2 thead .equipname .dong3{
  z-index: 5;
  left: 100px;
}
.table2 thead .equipname .dong4{
  z-index: 5;
  left: 150px;
}
.table2 thead .equipname .dong5{
  z-index: 5;
  left: 250px;
}
.table2 thead .equipname .dong6{
  z-index: 5;
  left: 412px;
}
#EfficiencyPO{
  overflow: hidden;
}
.identifyingclass {
  width: 55px;
  height: 15px;
  display: inline-block
}
.dataContent {
  white-space: nowrap;
  /*margin: 0;*/
  border-collapse: separate;
  border-spacing: 0;
  /*table-layout: fixed;*/
  border: 1px solid #ccc;
  /*border: 1px solid #ccc;*/
  width: 100%;
  /*height: 100%;*/
  /*overflow: hidden;*/
  /*overflow-y: auto;*/
  text-align: center;
}
.dataContent .thead th {
  background-color: #fafafa;
  text-align: center;
  height: 30px;
  padding: 5px;
}
.dataContent .notfixed th {
  width: auto;
}
.dataContent .mathData td {
  padding: 10px;
}
</style>