cuijian
2025-07-28 accebdce93486d3b4f26e55ffdea047549cce20c
src/views/mdc/base/modules/efficiencyReport/EfficiencyList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,705 @@
<template>
  <div class="efficiency_list" style="width: 100%">
    <div :bordered="false">
      <!-- æŸ¥è¯¢åŒºåŸŸ -->
      <div>
        <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="'#Efficiency'"
                              v-has="'efficiency: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"
                        style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap">{{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>
      </div>
      <a-spin :spinning="spinning">
        <div id="Efficiency" class="container" 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>
                <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 wenzi" :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 class="tdgu4 kaitou" style="min-width: 162px; max-width: 162px;width: 162px;">
                    {{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.utilizationRate | 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: 'EfficiencyList',
    components: {},
    data() {
      return {
        typeTree: '',
        typeParent: 1,
        typeEquipment: 1,
        TreeIDOne: 1,
        TreeIDTwo: 2,
        deviceTypeDict: '',
        dates: [],
        equipmentTypeList: [],
        driveTypeList: [],
        identifying: [],
        queryParam: {},
        queryParams: {
          equipmentType: [],
          driveType: [],
        },
        queryParamEquip: {},
        queryParamPeople: {},
        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/efficiencyList',
          listByType: '/mdc/MdcUtilizationRate/getByType',
          queryEquipmentType: '/mdc/mdcEquipmentType/queryEquipmentType'
        },
        tableHeads: [],
        distinguishColorList: [],
        utilizationRateRowAverage: '',
        openRateRowAverage: '',
        openLongRowAverage: '',
        processLongRowAverage: '',
        waitLongRowAverage: '',
        closeLongRowAverage: '',
        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'
        }
      }
    },
    computed: {},
    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() {
        $('#Efficiency').table2excel({
          exclude: '.noExl',
          name: 'Excel Document Name',
          filename: '设备利用率',
          exclude_img: true,
          fileext: '.xls',
          exclude_links: true,
          exclude_inputs: false
        })
      },
      showIdentifying() {
        getAction(this.url.listByType, { type: 'lyl' }).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.queryParams = {
          equipmentType: [],
          driveType: [],
        }
        this.loadData()
      },
      loadData() {
        this.tableHeads = []
        this.dataList = []
        this.spinning = true
        getAction(this.url.list, this.queryParam).then(res => {
          if (res.success) {
            this.tableHeads = res.result.dates
            this.dataList = res.result.mdcEfficiencyList
            if (res.result.mdcEfficiencyList && !res.result.mdcEfficiencyList.length) {
              this.$notification.info({
                message: '消息',
                description: '暂无该类型数据'
              })
            }
            this.distinguishColorList = res.result.utilizationRateList
            this.checkSameData(this.dataList)
            this.checkSameData1(this.dataList)
            this.checkSameData2(this.dataList)
            this.combineCell()
          }
        }).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.$notification.warning({
              message: '消息',
              description: res.message
            })
          }
        })
      },
      /**
       * è°ƒç”¨æŽ¥å£èŽ·å–æŽ§åˆ¶ç³»ç»Ÿç±»åž‹
       */
      getDriveTypeByApi() {
        api.getDriveTypeApi().then((res) => {
          if (res.success) this.driveTypeList = res.result
        })
      },
      /**
       * åˆ†è¾¨çŽ‡æ”¹å˜æ—¶åŒæ—¶æ”¹å˜è¡¨æ ¼é«˜åº¦å·²ä¿è¯é¦–é¡µä¸€è¿›å…¥ä¸æ‹–åŠ¨åž‚ç›´æ»šåŠ¨æ¡æ—¶å³å¯æ‹–åŠ¨è¡¨æ ¼æ°´å¹³æ»šåŠ¨æ¡
       */
      handleWindowResize() {
        const tableContainer = document.getElementById('Efficiency') // è¡¨æ ¼å®¹å™¨
        const clientHeight = document.documentElement.clientHeight || document.body.clientHeight // æµè§ˆå™¨å¯è§†åŒºåŸŸé«˜åº¦
        const containerTopToClientTopHeight = tableContainer.getBoundingClientRect().top // è¡¨æ ¼å®¹å™¨é¡¶éƒ¨åˆ°æµè§ˆå™¨å¯è§†åŒºåŸŸé¡¶éƒ¨çš„间距
        tableContainer.style.height = (clientHeight - containerTopToClientTopHeight - 32) + 'px'
      }
    }
  }
</script>
<style scoped>
  .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;
  }
  #Efficiency {
    overflow: hidden;
  }
  .identifyingclass {
    width: 55px;
    height: 15px;
    display: inline-block
  }
  .dataContent {
    white-space: nowrap;
    /*margin: 0;*/
    /*border: none;*/
    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 .mathData td {
    padding: 10px;
  }
  td {
    vertical-align: middle;
  }
</style>