zhaowei
2025-05-12 cd3313781f48c15a8fa0f0b46e2fdcde02969e87
车间布局管理页面新增分级看板以及维修看板页面
已添加39个文件
已修改2个文件
5830 ■■■■■ 文件已修改
src/api/signage.js 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/back.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/background-line.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/background.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/company/inspection-analysis.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/company/maintenance-analysis.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/company/navigator-active.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/company/navigator.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/company/rate-analysis-container.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/company/repair-analysis.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/equipment/day-rate-analysis.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/equipment/equipment-info-line.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/equipment/equipmentId-container.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/equipment/left-bottom-container.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/equipment/left-top-container.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/equipment/month-rate-analysis.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/equipment/product-qualified-rate.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/equipment/status-container.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/font/方正兰亭特黑简体.ttf 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/font/百度综艺简体.ttf 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/repair/average-fault-rate.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/repair/fault-type-analysis.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/repair/repair-analysis.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/repair/repaired-rank.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/repair/table-container.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/repair/top-left-container.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/section/search-input.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/title.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/workshop/navigator-long-active.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/workshop/navigator-long.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/workshop/navigator-middle-active.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/signage/workshop/navigator-middle.png 补丁 | 查看 | 原始文档 | blame | 历史
src/config/router.config.js 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/GradeWorkshopSignage.vue 293 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/RepairWorkshopSignage.vue 919 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/WorkshopSignageEntrance.vue 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/modules/GradeSignage/CompanySignage.vue 1059 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/modules/GradeSignage/EquipmentSignage.vue 1042 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/modules/GradeSignage/SectionSignage.vue 1350 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/modules/GradeSignage/WorkshopSignage.vue 1079 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/signage.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
import {
  getAction,
  deleteAction,
  putAction,
  postAction,
  httpAction,
  uploadAction,
  requestGetDownLoad,
  downloadFile
} from '@/api/manage'
import querystring from 'querystring'
export default {
  //-------------------------分级看板------------------------------------------------
  // èŽ·å–ç‚¹æ£€ç»Ÿè®¡å›¾è¡¨æ•°æ®
  getInspectionAnalysisApi: productionId => getAction('/eam/dashboard/equipmentInspectionStatistics', { productionId }),
  // èŽ·å–å‘¨ä¿ç»Ÿè®¡å›¾è¡¨æ•°æ®
  getMaintenanceAnalysisApi: productionId => getAction('/eam/dashboard/equipmentMaintenanceStatistics', { productionId }),
  // èŽ·å–ç»´ä¿®ç»Ÿè®¡å›¾è¡¨æ•°æ®
  getRepairAnalysisApi: productionId => getAction('/eam/dashboard/equipmentRepairStatistics', { productionId }),
  // èŽ·å–ç»´ä¿çŠ¶æ€å›¾è¡¨æ•°æ®
  getRepairAndMaintenanceStatusApi: productionId => getAction('/eam/dashboard/equipmentStatusStatistics', { productionId }),
  // èŽ·å–è½¦é—´åˆ†ç»„
  getWorkshopListByProductionIdApi: productionId => getAction('/mdc/board/proList', { productionId }),
  // èŽ·å–è®¾å¤‡è¿è¡ŒçŠ¶æ€ç»Ÿè®¡
  getEquipmentStatusAnalysisApi: productionId => getAction('/mdc/board/equipmentStatusStatistics', { productionId }),
  // èŽ·å–çŽ‡åˆ†æžèµ°åŠ¿å›¾æ•°æ®
  getRateAnalysisTrendApi: productionId => getAction('/mdc/board/rateAnalysisTrend', { productionId }),
  // èŽ·å–æ—¥çŽ‡åˆ†æž
  getDayRateAnalysisApi: equipmentId => getAction('/mdc/board/rateAnalysisTrendDay', { equipmentId }),
  // èŽ·å–æœˆçŽ‡åˆ†æžå’Œåˆæ ¼çŽ‡
  getMonthRateAnalysisAndQualifiedRateApi: equipmentId => getAction('/mdc/board/rateAnalysisTrendMonth', { equipmentId }),
  // èŽ·å–è®¾å¤‡åˆ—è¡¨
  getEquipmentListByProductionIdApi: productionId => getAction('/mdc/board/equipmentList', { productionId }),
  // èŽ·å–è®¾å¤‡è¿è¡ŒçŠ¶æ€åŠè¿è¡Œå‚æ•°ä¿¡æ¯
  getEquipmentOperationStatusAndInfoApi: equipmentId => getAction('/mdc/board/equipmentRealTimeDetail', { equipmentId }),
  //-------------------------维修看板------------------------------------------------
  // èŽ·å–ç»´ä¿®çŠ¶æ€ç»Ÿè®¡
  getRepairStatusStatisticsApi: () => getAction('/eam/dashboard/repairStatusStatistics'),
  // èŽ·å–ç»´ä¿®åˆ—è¡¨
  getRepairListApi: () => getAction('/eam/dashboard/repairList'),
  // èŽ·å–ç»´ä¿®å·¥æŽ’å
  getRepairerRankApi: () => getAction('/eam/dashboard/repairmanRanking'),
  // èŽ·å–æ•…éšœç±»åž‹ç»Ÿè®¡
  getFaultTypeStatisticsApi: () => getAction('/eam/dashboard/faultTypeStatistics')
}
src/assets/signage/back.png
src/assets/signage/background-line.png
src/assets/signage/background.png
src/assets/signage/company/inspection-analysis.png
src/assets/signage/company/maintenance-analysis.png
src/assets/signage/company/navigator-active.png
src/assets/signage/company/navigator.png
src/assets/signage/company/rate-analysis-container.png
src/assets/signage/company/repair-analysis.png
src/assets/signage/equipment/day-rate-analysis.png
src/assets/signage/equipment/equipment-info-line.png
src/assets/signage/equipment/equipmentId-container.png
src/assets/signage/equipment/left-bottom-container.png
src/assets/signage/equipment/left-top-container.png
src/assets/signage/equipment/month-rate-analysis.png
src/assets/signage/equipment/product-qualified-rate.png
src/assets/signage/equipment/status-container.png
src/assets/signage/font/·½ÕýÀ¼Í¤ÌغڼòÌå.ttf
Binary files differ
src/assets/signage/font/°Ù¶È×ÛÒÕ¼òÌå.ttf
Binary files differ
src/assets/signage/logo.png
src/assets/signage/repair/average-fault-rate.png
src/assets/signage/repair/fault-type-analysis.png
src/assets/signage/repair/repair-analysis.png
src/assets/signage/repair/repaired-rank.png
src/assets/signage/repair/table-container.png
src/assets/signage/repair/top-left-container.png
src/assets/signage/section/search-input.png
src/assets/signage/title.png
src/assets/signage/workshop/navigator-long-active.png
src/assets/signage/workshop/navigator-long.png
src/assets/signage/workshop/navigator-middle-active.png
src/assets/signage/workshop/navigator-middle.png
src/config/router.config.js
@@ -49,7 +49,7 @@
        path: 'alteration',
        name: 'alteration',
        component: () => import(/* webpackChunkName: "user" */ '@/views/user/alteration/Alteration')
      },
      }
    ]
  },
  {
@@ -63,7 +63,7 @@
        path: 'login',
        name: 'oauth2-app-login',
        component: () => import(/* webpackChunkName: "oauth2-app.login" */ '@/views/user/oauth2/OAuth2Login')
      },
      }
    ]
  },
@@ -84,8 +84,16 @@
    component: () => import('@/views/mdc/base/MdcWorkshopSignage.vue')
  },
  {
    path: '/GradeWorkshopSignage',
    component: () => import('@/views/mdc/base/GradeWorkshopSignage.vue')
  },
  {
    path: '/RepairWorkshopSignage',
    component: () => import('@/views/mdc/base/RepairWorkshopSignage.vue')
  },
  {
    path: '/404',
    component: () => import(/* webpackChunkName: "fail" */ '@/views/exception/404')
  },
  }
]
src/views/mdc/base/GradeWorkshopSignage.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,293 @@
<template>
  <div class="full-screen-container">
    <div class="background-line-container">
      <div class="page-header">
        <div>
          <img src="@/assets/signage/logo.png" style="height: 1.67vw"/>
          æ³•士特沃克齿轮有限公司
        </div>
        <div>{{signageList[currentSignageIndex].signageTitle}}</div>
        <div>
          {{currentDateAndTime}}
          <span>{{currentDayOfWeek}}</span>
          <div class="back-img-container" v-if="currentSignageIndex!==0" @click="backToPreSignage">
            <img src="@/assets/signage/back.png"/>
          </div>
        </div>
      </div>
      <div class="content-container">
        <dv-decoration-10 class="dv-decoration" :color="['#4D9BEF','#222E4A']"/>
        <Component :is="currentSignage" @nextSignage="switchToNextSignage" ref="componentRef"
                   :currentProductionId="signageList[currentSignageIndex].productionId"
                   :preSignageProductionId="currentSignageIndex!==0?signageList[currentSignageIndex-1].productionId:''"
                   @switchEquipmentSignageProductionId="switchEquipmentSignageProductionId"
                   @startPageLoading="pageLoading=true" @loadFinished="pageLoading=false">
          <template v-slot:loading>
            <dv-loading class="dv-loading" v-if="pageLoading">加载中...</dv-loading>
          </template>
        </Component>
      </div>
    </div>
  </div>
</template>
<script>
  import moment from 'moment'
  import CompanySignage from './modules/GradeSignage/CompanySignage.vue'
  import WorkshopSignage from './modules/GradeSignage/WorkshopSignage.vue'
  import SectionSignage from './modules/GradeSignage/SectionSignage.vue'
  import EquipmentSignage from './modules/GradeSignage/EquipmentSignage.vue'
  export default {
    productionName: 'GradeWorkshopSignage',
    components: {
      CompanySignage,
      WorkshopSignage,
      SectionSignage,
      EquipmentSignage
    },
    data() {
      return {
        pageLoading: false,
        currentDateAndTime: null,
        currentDayOfWeek: null,
        getDateAndTimeInterval: null,
        getDayOfWeekInterval: null,
        signageList: [
          {
            signageLevel: 'CompanySignage',
            signageTitle: '法士特沃克齿轮有限公司',
            productionId: ''
          },
          {
            signageLevel: 'WorkshopSignage',
            signageTitle: '',
            productionId: ''
          },
          {
            signageLevel: 'SectionSignage',
            signageTitle: '',
            productionId: ''
          },
          {
            signageLevel: 'EquipmentSignage',
            signageTitle: '设备看板',
            productionId: ''
          }
        ],
        currentSignage: 'CompanySignage',
        currentSignageIndex: 0
      }
    },
    created() {
      this.pageLoading = true
      this.getCurrentDateAndTime()
      this.getCurrentDayOfWeek()
    },
    beforeDestroy() {
      if (this.getDateAndTimeInterval) {
        clearInterval(this.getDateAndTimeInterval)
        this.getDateAndTimeInterval = null
      }
      if (this.getDayOfWeekInterval) {
        clearInterval(this.getDayOfWeekInterval)
        this.getDayOfWeekInterval = null
      }
    },
    methods: {
      /**
       * åˆ‡æ¢åˆ°ä¸‹ä¸€çº§çœ‹æ¿
       * @param record è·³è½¬æŒ‰é’®ä¿¡æ¯
       */
      switchToNextSignage(record) {
        this.pageLoading = true
        this.currentSignageIndex++
        if (this.currentSignageIndex !== this.signageList.length - 1) {
          this.signageList[this.currentSignageIndex].signageTitle = record.productionName + '看板'
        }
        this.signageList[this.currentSignageIndex].productionId = record.id
        this.currentSignage = this.signageList[this.currentSignageIndex].signageLevel
      },
      // è¿”回前一级看板
      backToPreSignage() {
        this.pageLoading = true
        this.currentSignageIndex--
        if (this.currentSignageIndex + 1 !== this.signageList.length - 1) this.signageList[this.currentSignageIndex + 1].signageTitle = ''
        this.signageList[this.currentSignageIndex + 1].productionId = ''
        this.currentSignage = this.signageList[this.currentSignageIndex].signageLevel
      },
      /**
       * åˆ‡æ¢è®¾å¤‡çœ‹æ¿ä¸­çš„设备编号时触发
       * @param productionId çœ‹æ¿å¯¹åº”编号
       */
      switchEquipmentSignageProductionId(productionId) {
        this.signageList[this.currentSignageIndex].productionId = productionId
      },
      // èŽ·å–å½“å‰æ—¥æœŸå’Œæ—¶é—´ï¼ˆ1秒更新1次)
      getCurrentDateAndTime() {
        this.getDateAndTimeInterval = setInterval(() => this.currentDateAndTime = moment().format('YYYY-MM-DD HH:mm:ss'), 1000)
      },
      // èŽ·å–å½“å¤©æ˜¯æ˜ŸæœŸå‡ ï¼ˆ1天更新1次)
      getCurrentDayOfWeek() {
        let timer = setTimeout(() => {
          this.currentDayOfWeek = moment().format('dddd')
          clearTimeout(timer)
          timer = null
        })
        this.getDayOfWeekInterval = setInterval(() => {
          this.currentDayOfWeek = moment().format('dddd')
        }, 1000 * 60 * 60 * 24)
      }
    }
  }
</script>
<style lang="less">
  @font-face {
    font-family: 'LanTing';
    src: url('../../../assets/signage/font/方正兰亭特黑简体.ttf') format('truetype');
  }
  @font-face {
    font-family: 'ZongYi';
    src: url('../../../assets/signage/font/百度综艺简体.ttf') format('truetype');
  }
  .full-screen-container {
    width: 100vw;
    height: 56.25vw;
    background-image: url("../../../assets/signage/background.png");
    background-size: 100% 100%;
    padding: 0.5%;
    color: #eee;
    .background-line-container {
      background-image: url("../../../assets/signage/background-line.png");
      background-size: 100% 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
      .page-header {
        display: flex;
        letter-spacing: 0.05vw;
        > div:first-child {
          color: #0071B6;
          font-size: 1.05vw;
        }
        > div:nth-child(2) {
          font-size: 1.7vw;
          text-align: center;
          text-shadow: 0 0.4vw 0 rgba(255, 255, 255, .2);
          font-family: 'ZongYi';
          letter-spacing: 0.25vw;
        }
        > div:last-child {
          text-align: right;
          font-family: 'ZongYi';
          font-size: 1.25vw;
          position: relative;
          span {
            font-weight: normal;
            font-size: 1.05vw;
          }
          .back-img-container {
            position: absolute;
            bottom: -2vw;
            right: 1vw;
            cursor: pointer;
            img {
              width: 1.77vw;
              height: 1.77vw;
            }
          }
        }
        > div:not(div:nth-child(2)) {
          font-weight: bold;
        }
        > div {
          width: 33%;
        }
      }
      .content-container {
        flex: 1;
        margin: 4.5vw 3.3vw 3vw 3vw;
        .right-container {
          display: flex;
          flex-direction: column;
          justify-content: space-between;
          > div:first-child {;
            position: relative;
            img {
              height: 100%;
              position: absolute;
            }
            .right-chart-container {
              width: 73.59vw;
              height: 25.31vw;
            }
          }
          > div:last-child {
            display: flex;
            justify-content: space-between;
            > div {
              position: relative;
              img {
                height: 100%;
                position: absolute;
              }
              .right-chart-container {
                width: 23.125vw;
                height: 19.42vw;
              }
            }
          }
        }
      }
    }
    .dv-decoration {
      width: 90%;
      height: 0.25vw;
      max-width: 90%;
      position: absolute;
      top: -1.5vw;
      left: 5%
    }
    .dv-loading {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: rgba(0, 0, 0, .5);
      z-index: 9999
    }
  }
</style>
src/views/mdc/base/RepairWorkshopSignage.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,919 @@
<template>
  <div class="full-screen-container">
    <dv-loading class="dv-loading" v-if="pageLoading">加载中...</dv-loading>
    <div class="background-line-container">
      <div class="page-header">
        <div>
          <img src="@/assets/signage/logo.png" style="height: 1.67vw"/>
          æ³•士特沃克齿轮有限公司
        </div>
        <div>维修看板</div>
        <div>
          {{currentDateAndTime}}
          <span>{{currentDayOfWeek}}</span>
        </div>
      </div>
      <div class="content-container">
        <dv-decoration-10 class="dv-decoration" :color="['#4D9BEF','#222E4A']"/>
        <div class=content-top-container>
          <div>
            <img src="@/assets/signage/repair/top-left-container.png"/>
            <div>
              <img src="@/assets/signage/title.png" class="title-image"/>
              <span>待接单:<span>{{repairStatusObj.waitRepair|addPrefix0WhenLessThan0}}</span></span>
            </div>
            <div>
              <img src="@/assets/signage/title.png" class="title-image"/>
              <span>维修中:<span>{{repairStatusObj.underRepair|addPrefix0WhenLessThan0}}</span></span>
            </div>
            <div>
              <img src="@/assets/signage/title.png" class="title-image"/>
              <span>等备件:<span>{{repairStatusObj.waitSpares|addPrefix0WhenLessThan0}}</span></span>
            </div>
            <div>
              <img src="@/assets/signage/title.png" class="title-image"/>
              <span>待确认:<span>{{repairStatusObj.waitConfirm|addPrefix0WhenLessThan0}}</span></span>
            </div>
            <div>
              <img src="@/assets/signage/title.png" class="title-image"/>
              <span>待指派:<span>{{repairStatusObj.waitRepair|addPrefix0WhenLessThan0}}</span></span>
            </div>
          </div>
          <div>
            <img src="@/assets/signage/repair/table-container.png"/>
            <dv-scroll-board class="scroll-table-container" :config="scrollTableConfig"/>
            <!--<table>-->
            <!--<thead>-->
            <!--<tr>-->
            <!--<th>设备编号</th>-->
            <!--<th>设备名称</th>-->
            <!--<th>所属车间</th>-->
            <!--<th>安装位置</th>-->
            <!--<th>报修人</th>-->
            <!--<th>报修时间</th>-->
            <!--<th>维修人</th>-->
            <!--<th>接单时间</th>-->
            <!--<th>故障持续时间</th>-->
            <!--<th>状态</th>-->
            <!--</tr>-->
            <!--</thead>-->
            <!--<tbody>-->
            <!--<tr v-for="item in 8">-->
            <!--</tr>-->
            <!--</tbody>-->
            <!--</table>-->
          </div>
          <div>
            <img src="@/assets/signage/repair/repaired-rank.png"/>
            <dv-scroll-ranking-board class="scroll-rank-container" :config="scrollRankConfig"/>
          </div>
        </div>
        <div class="content-bottom-container">
          <div>
            <img src="@/assets/signage/repair/repair-analysis.png"/>
            <div class="chart-container" id="bottom-chart-1"></div>
          </div>
          <div>
            <img src="@/assets/signage/repair/average-fault-rate.png"/>
            <div class="chart-container" id="bottom-chart-2"></div>
          </div>
          <div>
            <img src="@/assets/signage/repair/fault-type-analysis.png"/>
            <div class="chart-container" id="bottom-chart-3"></div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  import moment from 'moment'
  import signageApi from '@/api/signage'
  export default {
    name: 'RepairWorkshopSignage',
    data() {
      return {
        pageLoading: false,
        repairStatusObj: {},
        scrollTableConfig: {},
        scrollRankConfig: {},
        bottomChart1: null,
        bottomChart2: null,
        bottomChart3: null,
        bottomChart1And2Data: [],
        bottomChart2Data: [],
        bottomChart3Data: [],
        apiCount: 5,
        hasLoadedApiCount: 0,
        currentDateAndTime: null,
        currentDayOfWeek: null,
        getDateAndTimeInterval: null,
        getDayOfWeekInterval: null
      }
    },
    watch: {
      hasLoadedApiCount: {
        handler(val) {
          if (val === this.apiCount) this.pageLoading = false
        }
      }
    },
    mounted() {
      this.pageLoading = true
      this.getRepairStatusStatisticsByApi()
      this.getTableDataByApi()
      this.getRankDataByApi()
      this.getChartDataByApi()
      window.addEventListener('resize', this.handleWindowResize)
      this.getCurrentDateAndTime()
      this.getCurrentDayOfWeek()
    },
    beforeDestroy() {
      if (this.getDateAndTimeInterval) {
        clearInterval(this.getDateAndTimeInterval)
        this.getDateAndTimeInterval = null
      }
      if (this.getDayOfWeekInterval) {
        clearInterval(this.getDayOfWeekInterval)
        this.getDayOfWeekInterval = null
      }
      window.removeEventListener('resize', this.handleWindowResize)
    },
    filters: {
      addPrefix0WhenLessThan0(value) {
        return +value < 10 ? `0${value}` : value
      }
    },
    methods: {
      // è°ƒç”¨æŽ¥å£èŽ·å–ç»´ä¿®çŠ¶æ€ç»Ÿè®¡
      getRepairStatusStatisticsByApi() {
        const that = this
        signageApi.getRepairStatusStatisticsApi()
          .then(res => {
            if (res.success) that.repairStatusObj = res.result
          })
          .finally(() => {
            that.hasLoadedApiCount++
          })
      },
      // è°ƒç”¨æŽ¥å£èŽ·å–ç»´ä¿®åˆ—è¡¨
      getTableDataByApi() {
        const that = this
        signageApi.getRepairListApi()
          .then(res => {
            if (res.success) {
              const dataList = res.result.map(item => [item.equipmentCode, `<a-tooltip title="${item.orgId_dictText}">${item.orgId_dictText ? item.orgId_dictText : ''}</a-tooltip>`, item.installationPosition, item.reportOperator_dictText, item.faultStartTime, item.repairOperator_dictText, item.repairStartTime, item.faultDuration, item.reportStatus_dictText])
              that.scrollTableConfig = {
                header: ['设备编号', '所属车间', '安装位置', '报修人', '故障开始时间', '维修人', '接单时间', '故障持续(MIN)', '工单状态'],
                data: dataList,
                columnWidth: [250, 200, 140, 120, 250, 120, 250, 220, 150],
                align: ['center', 'center', 'center', 'center', 'center', 'center', 'center', 'center', 'center', 'center'],
                carousel: 'single',
                headerHeight: 52,
                rowNum: 7,
                headerBGC: '#0E7F9E',
                oddRowBGC: '#193262',
                evenRowBGC: '#2B5894'
              }
            }
          })
          .finally(() => {
            that.hasLoadedApiCount++
          })
      },
      // è°ƒç”¨æŽ¥å£èŽ·å–ç»´ä¿®å®ŒæˆæŽ’å
      getRankDataByApi() {
        const that = this
        signageApi.getRepairerRankApi()
          .then(res => {
            if (res.success) {
              const dataList = res.result.map(item => {
                return {
                  name: item.repairer_dictText,
                  value: item.repairNumber
                }
              })
              that.scrollRankConfig = {
                data: dataList,
                rowNum: 7
              }
            }
          })
          .finally(() => {
            that.hasLoadedApiCount++
          })
      },
      getChartDataByApi() {
        this.getBottomChart1And2DataByApi()
        this.getBottomChart3DataByApi()
      },
      getBottomChart1And2DataByApi() {
        const that = this
        signageApi.getRepairAnalysisApi()
          .then(res => {
            if (res.success) that.bottomChart1And2Data = res.result
            that.initBottomChart1()
            that.initBottomChart2()
          })
          .finally(() => {
            that.hasLoadedApiCount++
          })
      },
      getBottomChart3DataByApi() {
        const that = this
        signageApi.getFaultTypeStatisticsApi()
          .then(res => {
            if (res.success) that.bottomChart3Data = res.result
            that.initBottomChart3()
          })
          .finally(() => {
            that.hasLoadedApiCount++
          })
      },
      initBottomChart1() {
        this.bottomChart1 = this.$echarts.init(document.getElementById('bottom-chart-1'))
        const option = {
          tooltip: {
            trigger: 'axis'
          },
          grid: {
            bottom: '5%',
            top: '30%',
            left: '10%',
            right: '10%',
            containLabel: true
          },
          legend: {
            top: 80,
            right: '10%',
            itemGap: 15,
            textStyle: {
              fontSize: 14,
              fontFamily: 'LanTing',
              color: '#eee',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['报修数', '完成数']
          },
          xAxis: {
            type: 'category',
            data: [],
            axisLine: {
              lineStyle: {
                color: '#eee'
              }
            },
            axisLabel: {
              interval: 0,
              margin: 14,
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              rotate: 45
            },
            axisTick: {
              show: true
            }
          },
          yAxis: [
            {
              type: 'value',
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              },
              axisLabel: {
                fontSize: 14,
                color: '#eee',
                fontWeight: 'bold',
                margin: 14
              }
            }
          ],
          series: [
            {
              type: 'bar',
              barWidth: 12,
              name: '报修数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#295485'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#2F95F9'
                    }
                  ]
                )
              }
            },
            {
              type: 'bar',
              barWidth: 12,
              name: '完成数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#35535E'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#92F7AD'
                    }
                  ]
                )
              }
            }
          ]
        }
        option.xAxis.data = this.bottomChart1And2Data.map(item => item.monthStr)
        option.series[0].data = this.bottomChart1And2Data.map(item => {
          return {
            name: item.monthStr,
            value: item.reportNumber
          }
        })
        option.series[1].data = this.bottomChart1And2Data.map(item => {
          return {
            name: item.monthStr,
            value: item.repairedNumber
          }
        })
        this.$nextTick(() => this.bottomChart1.setOption(option, true))
      },
      initBottomChart2() {
        this.bottomChart2 = this.$echarts.init(document.getElementById('bottom-chart-2'))
        const option = {
          tooltip: {
            trigger: 'axis'
          },
          grid: {
            bottom: '5%',
            top: '30%',
            left: '10%',
            right: '10%',
            containLabel: true
          },
          legend: {
            top: 80,
            right: '10%',
            itemGap: 15,
            textStyle: {
              fontSize: 14,
              fontFamily: 'LanTing',
              color: '#eee',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['设备平均故障率']
          },
          xAxis: {
            type: 'category',
            data: [],
            axisLine: {
              lineStyle: {
                color: '#eee'
              }
            },
            axisLabel: {
              interval: 0,
              margin: 14,
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              rotate: 45
            },
            axisTick: {
              show: true
            }
          },
          yAxis: [
            {
              type: 'value',
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              },
              axisLabel: {
                fontSize: 14,
                color: '#eee',
                fontWeight: 'bold',
                margin: 14,
                formatter(value) {
                  return value + '%'
                }
              }
            }
          ],
          series: {
            type: 'bar',
            barWidth: 35,
            name: '设备平均故障率',
            data: [],
            label: {
              show: false,
              lineHeight: 10,
              formatter: params => {
                if (+params.value === 0) return ''
                else return params.value
              },
              position: 'inside',
              textStyle: {
                color: '#eee',
                fontSize: 12
              }
            },
            itemStyle: {
              color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                [
                  {//只要修改前四个参数就ok
                    offset: 0,
                    color: '#295485'
                  }, //柱图渐变色
                  {
                    offset: 1,
                    color: '#2F95F9'
                  }
                ]
              )
            }
          }
        }
        option.xAxis.data = this.bottomChart1And2Data.map(item => item.monthStr)
        option.series.data = this.bottomChart1And2Data.map(item => {
          return {
            name: item.monthStr,
            value: item.reportNumber
          }
        })
        this.$nextTick(() => this.bottomChart2.setOption(option, true))
      },
      initBottomChart3() {
        this.bottomChart3 = this.$echarts.init(document.getElementById('bottom-chart-3'))
        const option = {
          tooltip: {
            trigger: 'axis'
          },
          grid: {
            bottom: '5%',
            top: '30%',
            left: '10%',
            right: '10%',
            containLabel: true
          },
          legend: {
            top: 80,
            right: '10%',
            itemGap: 15,
            textStyle: {
              fontSize: 14,
              fontFamily: 'LanTing',
              color: '#eee',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['维修工单数']
          },
          xAxis: {
            type: 'category',
            data: [],
            axisLine: {
              lineStyle: {
                color: '#eee'
              }
            },
            axisLabel: {
              interval: 0,
              margin: 14,
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing'
            },
            axisTick: {
              show: true
            }
          },
          yAxis: [
            {
              type: 'value',
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              },
              axisLabel: {
                fontSize: 14,
                color: '#eee',
                fontWeight: 'bold',
                margin: 14
              }
            }
          ],
          series: {
            type: 'bar',
            barWidth: 35,
            name: '维修工单数',
            data: [],
            label: {
              show: false,
              lineHeight: 10,
              formatter: params => {
                if (+params.value === 0) return ''
                else return params.value
              },
              position: 'inside',
              textStyle: {
                color: '#eee',
                fontSize: 12
              }
            },
            itemStyle: {
              color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                [
                  {//只要修改前四个参数就ok
                    offset: 0,
                    color: '#295485'
                  }, //柱图渐变色
                  {
                    offset: 1,
                    color: '#2F95F9'
                  }
                ]
              )
            }
          }
        }
        option.xAxis.data = this.bottomChart3Data.map(item => item.faultType_dictText)
        option.series.data = this.bottomChart3Data.map(item => {
          return {
            name: item.faultType_dictText,
            value: item.faultCount
          }
        })
        this.$nextTick(() => this.bottomChart3.setOption(option, true))
      },
      // èŽ·å–å½“å‰æ—¥æœŸå’Œæ—¶é—´ï¼ˆ1秒更新1次)
      getCurrentDateAndTime() {
        this.getDateAndTimeInterval = setInterval(() => this.currentDateAndTime = moment().format('YYYY-MM-DD HH:mm:ss'), 1000)
      },
      // èŽ·å–å½“å¤©æ˜¯æ˜ŸæœŸå‡ ï¼ˆ1天更新1次)
      getCurrentDayOfWeek() {
        let timer = setTimeout(() => {
          this.currentDayOfWeek = moment().format('dddd')
          clearTimeout(timer)
          timer = null
        })
        this.getDayOfWeekInterval = setInterval(() => {
          this.currentDayOfWeek = moment().format('dddd')
        }, 1000 * 60 * 60 * 24)
      },
      handleWindowResize() {
        if (this.bottomChart1) this.bottomChart1.resize()
        if (this.bottomChart2) this.bottomChart2.resize()
        if (this.bottomChart3) this.bottomChart3.resize()
      }
    }
  }
</script>
<style lang="less">
  @font-face {
    font-family: 'LanTing';
    src: url('../../../assets/signage/font/方正兰亭特黑简体.ttf') format('truetype');
  }
  @font-face {
    font-family: 'ZongYi';
    src: url('../../../assets/signage/font/百度综艺简体.ttf') format('truetype');
  }
  .full-screen-container {
    /*background: #000;*/
    width: 100vw;
    height: 56.25vw;
    background-image: url("../../../assets/signage/background.png");
    background-size: 100% 100%;
    padding: 0.5%;
    color: #eee;
    .background-line-container {
      background-image: url("../../../assets/signage/background-line.png");
      background-size: 100% 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
      .page-header {
        display: flex;
        letter-spacing: 0.05vw;
        > div:first-child {
          color: #0071B6;
          font-size: 1.05vw;
        }
        > div:nth-child(2) {
          font-size: 1.7vw;
          text-align: center;
          text-shadow: 0 0.4vw 0 rgba(255, 255, 255, .2);
          font-family: 'ZongYi';
          letter-spacing: 0.25vw;
        }
        > div:last-child {
          text-align: right;
          font-family: 'ZongYi';
          font-size: 1.25vw;
          position: relative;
          span {
            font-weight: normal;
            font-size: 1.05vw;
          }
          .back-img-container {
            position: absolute;
            bottom: -2vw;
            right: 1vw;
            cursor: pointer;
            img {
              width: 1.77vw;
              height: 1.77vw;
            }
          }
        }
        > div:not(div:nth-child(2)) {
          font-weight: bold;
        }
        > div {
          width: 33%;
        }
      }
      .content-container {
        flex: 1;
        margin: 4vw 3.8vw 3.2vw;
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        img:not(.title-image) {
          width: 100%;
          height: 100%;
          position: absolute;
          z-index: 0;
        }
        .content-top-container {
          height: 25.62vw;
          display: flex;
          justify-content: space-between;
          > div {
            position: relative;
            z-index: 1;
            &:first-child {
              width: 15.1vw;
              display: flex;
              flex-direction: column;
              align-items: center;
              justify-content: space-evenly;
              > div {
                width: 100%;
                height: 3.6vw;
                position: relative;
                display: flex;
                .title-image {
                  height: 100%;
                  position: absolute;
                  top: 50%;
                  left: 50%;
                  transform: translate(-50%, -50%);
                  z-index: 1;
                }
                > span {
                  position: relative;
                  z-index: 2;
                  font-size: 1.2vw;
                  font-family: 'ZongYi';
                  margin: auto;
                  letter-spacing: 0.25vw;
                  span {
                    font-family: 'LanTing';
                    color: #FCFF00;
                  }
                }
              }
            }
            &:nth-child(2) {
              width: 60.2vw;
              display: flex;
              justify-content: center;
              align-items: center;
              .scroll-table-container {
                width: 94%;
                height: 85%;
                color: #eee;
                .header-item {
                  font-family: 'ZongYi';
                  font-size: 0.9vw;
                }
                .row-item {
                  font-family: 'LanTing';
                  font-size: 0.8vw;
                  > div:nth-child(5), > div:nth-child(7) {
                    /*white-space: normal;*/
                    /*overflow: visible;*/
                    /*text-overflow: initial;*/
                  }
                }
              }
            }
            &:last-child {
              width: 15.1vw;
              display: flex;
              justify-content: center;
              align-items: flex-end;
              -webkit-align-items: flex-end;
              .scroll-rank-container {
                width: 80%;
                height: 78%;
                margin-bottom: 7%;
                position: relative;
                z-index: 2;
                .rank, .info-name {
                  color: #eee;
                  font-weight: bold;
                }
                .ranking-value {
                  color: #F4E005;
                  font-weight: bold;
                }
                .inside-column {
                  background: linear-gradient(to right, #2E93FF, #52F0FF);
                  background: -webkit-linear-gradient(to right, #2E93FF, #52F0FF);
                  background: -moz-linear-gradient(to right, #2E93FF, #52F0FF);
                }
              }
            }
          }
        }
        .content-bottom-container {
          height: 19.42vw;
          display: flex;
          justify-content: space-between;
          > div {
            position: relative;
            z-index: 0;
            &:not(:nth-child(2)) {
              width: 28.22vw;
            }
            &:nth-child(2) {
              width: 33.22vw;
            }
            .chart-container {
              height: 100%;
            }
          }
        }
      }
    }
    .dv-decoration {
      width: 90%;
      height: 0.25vw;
      max-width: 90%;
      position: absolute;
      top: -1.2vw;
      left: 5%
    }
    .dv-loading {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: rgba(0, 0, 0, .5);
      z-index: 9999
    }
  }
</style>
src/views/mdc/base/WorkshopSignageEntrance.vue
@@ -1,10 +1,22 @@
<template>
  <div class="page-container">
    <h1>车间布局看板</h1>
    <a-list
      :grid="{ gutter: [{xs: 0, sm: 24, md: 24, lg: 56, xl: 64, xxl: 80},20], xs: 1, sm: 2, md: 2, lg: 3, xl: 4, xxl: 4 }"
      :grid="{gutter: 16, xs: 1, sm: 2, md: 4, lg: 4, xl: 6, xxl: 3 }"
      :data-source="workshopList">
      <a-list-item slot="renderItem" slot-scope="item, index">
        <div class="workshop-name" @click="navigateToWorkshopSignage(item.id)">{{item.workshopName}}</div>
      </a-list-item>
    </a-list>
    <h1>分级看板</h1>
    <a-list
      :grid="{gutter: 16, column:4}">
      <a-list-item>
        <div class="workshop-name" @click="navigateToWorkshopSignageByUrl('/GradeWorkshopSignage')">分级看板</div>
      </a-list-item>
      <a-list-item>
        <div class="workshop-name" @click="navigateToWorkshopSignageByUrl('/RepairWorkshopSignage')">维修看板</div>
      </a-list-item>
    </a-list>
  </div>
@@ -33,6 +45,16 @@
        const url = this.$router.resolve(`/MdcWorkshopSignage/${id}`).href
        window.open(url, '_blank')
      },
      /**
       * é€šè¿‡è½¦é—´Url地址跳转至对应大屏看板
       * @param httpUrl è½¦é—´Url地址
       */
      navigateToWorkshopSignageByUrl(httpUrl) {
        const url = this.$router.resolve(httpUrl).href
        window.open(url, '_blank')
      },
      /**
       * èŽ·å–è½¦é—´åˆ—è¡¨
       */
@@ -53,7 +75,7 @@
    padding: 30px 30px 0;
    .workshop-name {
      width: 100%;
      /*width: 100%;*/
      background: #fff;
      padding: 55px 0;
      border-radius: 20px;
@@ -63,6 +85,7 @@
      text-overflow: ellipsis;
      font-size: 30px;
      cursor: pointer;
      margin: 0 8px;
    }
  }
src/views/mdc/base/modules/GradeSignage/CompanySignage.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1059 @@
<template>
  <div class="component-container">
    <slot name="loading"/>
    <div class="left-container">
      <div>
        <div class="title-container">
          <img src="@/assets/signage/title.png"/>
          <span>设备状态</span>
        </div>
        <div class="left-chart-container" id="left-chart-1"></div>
      </div>
      <div>
        <div class="title-container">
          <img src="@/assets/signage/title.png"/>
          <span>维保状态</span>
        </div>
        <div class="left-chart-container" id="left-chart-2"></div>
      </div>
      <div>
        <div v-for="(item,index) in workshopList" class="navigator-container" @mouseenter="activeIndex=index"
             @mouseleave="activeIndex=null" @click="$emit('nextSignage', item)">
          <img v-if="activeIndex!==index" src="@/assets/signage/company/navigator.png"/>
          <img v-else src="@/assets/signage/company/navigator-active.png"/>
          <span>{{item.productionName}}</span>
        </div>
      </div>
    </div>
    <div class="right-container">
      <div>
        <img src="@/assets/signage/company/rate-analysis-container.png"/>
        <div class="right-chart-container" id="right-top-chart"></div>
      </div>
      <div>
        <div>
          <img src="@/assets/signage/company/repair-analysis.png"/>
          <div class="right-chart-container" id="right-bottom-chart-1"></div>
        </div>
        <div>
          <img src="@/assets/signage/company/inspection-analysis.png"/>
          <div class="right-chart-container" id="right-bottom-chart-2"></div>
        </div>
        <div>
          <img src="@/assets/signage/company/maintenance-analysis.png"/>
          <div class="right-chart-container" id="right-bottom-chart-3"></div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  import signageApi from '@/api/signage'
  export default {
    name: 'CompanySignage',
    data() {
      return {
        leftChart1: null,
        leftChart2: null,
        rightTopChart: null,
        rightBottomChart1: null,
        rightBottomChart2: null,
        rightBottomChart3: null,
        leftChart1Data: [],
        leftChart2Data: [],
        rightTopChartData: [],
        rightBottomChart1Data: [],
        rightBottomChart2Data: [],
        rightBottomChart3Data: [],
        chartQuantity: 6,
        hasLoadedChartDataQuantity: 0,
        workshopList: [],
        activeIndex: null
      }
    },
    watch: {
      hasLoadedChartDataQuantity: {
        handler(val) {
          if (val === this.chartQuantity) this.$emit('loadFinished')
        }
      }
    },
    mounted() {
      this.getWorkshopListByApi()
      this.getChartDataByApi()
      this.handleWindowResize()
      window.addEventListener('resize', this.handleWindowResize)
    },
    beforeDestroy() {
      window.removeEventListener('resize', this.handleWindowResize)
    },
    methods: {
      getWorkshopListByApi() {
        signageApi.getWorkshopListByProductionIdApi()
          .then(res => {
            if (res.success) this.workshopList = res.result
          })
      },
      getChartDataByApi() {
        this.getLeftChart1DataByApi()
        this.getLeftChart2DataByApi()
        this.geRightTopChartDataByApi()
        this.geRightBottomChartData1ByApi()
        this.geRightBottomChartData2ByApi()
        this.geRightBottomChartData3ByApi()
      },
      getLeftChart1DataByApi() {
        const that = this
        signageApi.getEquipmentStatusAnalysisApi()
          .then(res => {
            if (res.success) {
              this.leftChart1Data = res.result.equipmentStatus
            }
            this.initLeftChart1()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      getLeftChart2DataByApi() {
        const that = this
        signageApi.getRepairAndMaintenanceStatusApi()
          .then(res => {
            if (res.success) {
              this.leftChart2Data = res.result.map(item => {
                return {
                  name: item.statusText,
                  value: item.totalNumber
                }
              })
            }
            this.initLeftChart2()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      geRightTopChartDataByApi() {
        const that = this
        signageApi.getRateAnalysisTrendApi()
          .then(res => {
            console.log('res', res)
            if (res.success) this.rightTopChartData = res.result
            this.initRightTopChart()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      geRightBottomChartData1ByApi() {
        const that = this
        signageApi.getRepairAnalysisApi()
          .then(res => {
            if (res.success) this.rightBottomChart1Data = res.result
            this.initRightBottomChart1()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      geRightBottomChartData2ByApi() {
        const that = this
        signageApi.getInspectionAnalysisApi()
          .then(res => {
            if (res.success) this.rightBottomChart2Data = res.result
            this.initRightBottomChart2()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      geRightBottomChartData3ByApi() {
        const that = this
        signageApi.getMaintenanceAnalysisApi()
          .then(res => {
            if (res.success) this.rightBottomChart3Data = res.result
            this.initRightBottomChart3()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      initLeftChart1() {
        this.leftChart1 = this.$echarts.init(document.getElementById('left-chart-1'))
        const { alarmCount, closeCount, runCount, waitCount } = this.leftChart1Data
        const dataList = [
          {
            'value': closeCount,
            'name': '关机'
          },
          {
            'value': waitCount,
            'name': '待机'
          },
          {
            'value': runCount,
            'name': '运行'
          },
          {
            'value': alarmCount,
            'name': '报警'
          }
        ]
        const option = {
          tooltip: {
            show: true
          },
          title: {
            text: `{a|${dataList.reduce((total, item) => total + +item.value, 0)}}`,
            x: 'center',
            y: '50%',
            textStyle: {
              rich: {
                a: {
                  fontSize: 30,
                  color: '#eee'
                }
              }
            }
          },
          legend: {
            top: 10,
            left: 'center',
            itemGap: 15,
            textStyle: {
              color: '#eee',
              fontSize: 14,
              fontFamily: 'LanTing',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['关机', '待机', '运行', '报警']
          },
          grid: {
            containLabel: true
          },
          series: [
            {
              type: 'pie',
              radius: ['30%', '55%'],
              center: ['50%', '55%'],
              color: [
                '#238DF5',
                '#6FDB6F',
                '#10ABAE',
                '#C7A46C'
              ],
              label: {
                position: 'outside',
                show: true,
                color: 'inherit',
                fontSize: 16,
                fontWeight: 'bold',
                formatter: function(params) {
                  return params.value
                }
              },
              labelLine: {
                show: true
              },
              data: dataList
            }
          ]
        }
        this.$nextTick(() => this.leftChart1.setOption(option, true))
      },
      initLeftChart2() {
        this.leftChart2 = this.$echarts.init(document.getElementById('left-chart-2'))
        const option = {
          tooltip: {
            show: true
          },
          title: {
            text: '',
            x: 'center',
            y: '50%',
            textStyle: {
              rich: {
                a: {
                  fontSize: 30,
                  color: '#eee'
                }
              }
            }
          },
          legend: {
            top: 10,
            left: 'center',
            itemGap: 15,
            textStyle: {
              color: '#eee',
              fontSize: 14,
              fontFamily: 'LanTing',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['正常', 'ç»´ä¿®', '点检', '保养']
          },
          grid: {
            containLabel: true
          },
          series: [
            {
              type: 'pie',
              radius: ['30%', '55%'],
              center: ['50%', '55%'],
              color: ['#238DF5', '#6FDB6F', '#10ABAE', '#C7A46C'],
              label: {
                position: 'outside',
                show: true,
                color: 'inherit',
                fontWeight: 'bold',
                fontSize: 16,
                formatter: function(params) {
                  return params.value
                }
              },
              labelLine: {
                show: true
              },
              data: []
            }
          ]
        }
        option.series[0].data = this.leftChart2Data
        option.title.text = `{a|${this.leftChart2Data.reduce((total, item) => total + +item.value, 0)}}`
        this.$nextTick(() => this.leftChart2.setOption(option, true))
      },
      initRightTopChart() {
        this.rightTopChart = this.$echarts.init(document.getElementById('right-top-chart'))
        const { dataList, dateList } = this.rightTopChartData
        const newData = {
          xAxis: dateList,
          yAxis: [
            {
              name: 'OEE',
              value: dataList.map(item => item.oee)
            },
            {
              name: '利用率',
              value: dataList.map(item => item.utilizationRate)
            },
            {
              name: '开机率',
              value: dataList.map(item => item.openRate)
            },
            {
              name: '开动率',
              value: dataList.map(item => item.startRate)
            }
          ]
        }
        let legendData = []
        let seriesData = []
        let colorArr = ['#4D9BEF', '#FFA800', '#00FF18', '#C06FFF']
        legendData = newData.yAxis.map((item) => item.name)
        seriesData = newData.yAxis.map((item1, index1) => {
          return {
            name: item1.name,
            type: 'line',
            symbol: 'circle',
            symbolSize: 8,
            itemStyle: {
              color: colorArr[index1]
            },
            yAxisIndex: 1,
            data: item1.value // æŠ˜çº¿å›¾çš„æ•°æ®
          }
        })
        const option = {
          grid: {
            containLabel: true,
            bottom: '3%',
            top: '25%',
            left: '5%',
            right: '5%'
          },
          tooltip: {
            trigger: 'axis'
          },
          legend: {
            top: 70,
            right: '5%',
            data: legendData,
            itemGap: 30,
            textStyle: {
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            }
          },
          xAxis: {
            triggerEvent: true,
            data: newData.xAxis || [],
            axisLabel: {
              interval: 0,
              show: true,
              fontSize: 14,
              color: '#eee',
              margin: 14,
              fontFamily: 'LanTing'
            },
            axisLine: {
              show: true,
              lineStyle: {
                color: '#eee'
              }
            },
            axisTick: {
              show: true
            },
            splitLine: {
              show: true
            }
          },
          yAxis: [
            {
              type: 'value',
              position: 'left',
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              splitLine: {
                show: false
              }
            },
            {
              type: 'value',
              position: 'left',
              axisLabel: {
                show: true,
                color: '#eee',
                margin: 14,
                fontSize: 14,
                fontWeight: 'bold',
                formatter(value) {
                  return value + '%'
                }
              },
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              }
            }
          ],
          series: seriesData
        }
        this.rightTopChart.setOption(option, true)
      },
      initRightBottomChart1() {
        this.rightBottomChart1 = this.$echarts.init(document.getElementById('right-bottom-chart-1'))
        const option = {
          tooltip: {
            trigger: 'axis'
          },
          grid: {
            bottom: '5%',
            top: '30%',
            left: '10%',
            right: '10%',
            containLabel: true
          },
          legend: {
            top: 80,
            right: '10%',
            itemGap: 15,
            textStyle: {
              fontSize: 14,
              fontFamily: 'LanTing',
              color: '#eee',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['报修数', '完成数']
          },
          xAxis: {
            type: 'category',
            data: [],
            axisLine: {
              lineStyle: {
                color: '#eee'
              }
            },
            axisLabel: {
              interval: 0,
              margin: 14,
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              rotate: 45
            },
            axisTick: {
              show: true
            }
          },
          yAxis: [
            {
              type: 'value',
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              },
              axisLabel: {
                fontSize: 14,
                color: '#eee',
                fontWeight: 'bold',
                margin: 14
              }
            }
          ],
          series: [
            {
              type: 'bar',
              barWidth: 12,
              name: '报修数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#295485'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#2F95F9'
                    }
                  ]
                )
              }
            },
            {
              type: 'bar',
              barWidth: 12,
              name: '完成数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#35535E'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#92F7AD'
                    }
                  ]
                )
              }
            }
          ]
        }
        option.xAxis.data = this.rightBottomChart1Data.map(item => item.monthStr)
        option.series[0].data = this.rightBottomChart1Data.map(item => {
          return {
            name: item.monthStr,
            value: item.reportNumber
          }
        })
        option.series[1].data = this.rightBottomChart1Data.map(item => {
          return {
            name: item.monthStr,
            value: item.repairedNumber
          }
        })
        this.$nextTick(() => this.rightBottomChart1.setOption(option, true))
      },
      initRightBottomChart2() {
        this.rightBottomChart2 = this.$echarts.init(document.getElementById('right-bottom-chart-2'))
        const option = {
          tooltip: {
            trigger: 'axis'
          },
          grid: {
            bottom: '5%',
            top: '30%',
            left: '10%',
            right: '10%',
            containLabel: true
          },
          legend: {
            top: 80,
            right: '10%',
            itemGap: 15,
            textStyle: {
              fontSize: 14,
              fontFamily: 'LanTing',
              color: '#eee',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['点检计划数', '点检完成数']
          },
          xAxis: {
            type: 'category',
            data: [],
            axisLine: {
              lineStyle: {
                color: '#eee'
              }
            },
            axisLabel: {
              margin: 14,
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              interval: 0,
              rotate: 45
            },
            axisTick: {
              show: true
            }
          },
          yAxis: [
            {
              type: 'value',
              minInterval: 1,
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              },
              axisLabel: {
                fontSize: 14,
                color: '#eee',
                fontWeight: 'bold',
                margin: 14
              }
            }
          ],
          series: [
            {
              type: 'bar',
              barWidth: 12,
              name: '点检计划数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#295485'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#2F95F9'
                    }
                  ]
                )
              }
            },
            {
              type: 'bar',
              barWidth: 12,
              name: '点检完成数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#35535E'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#92F7AD'
                    }
                  ]
                )
              }
            }
          ]
        }
        option.xAxis.data = this.rightBottomChart2Data.map(item => item.monthStr)
        option.series[0].data = this.rightBottomChart2Data.map(item => {
          return {
            name: item.monthStr,
            value: item.planNumber
          }
        })
        option.series[1].data = this.rightBottomChart2Data.map(item => {
          return {
            name: item.monthStr,
            value: item.completeNumber
          }
        })
        this.$nextTick(() => this.rightBottomChart2.setOption(option, true))
      },
      initRightBottomChart3() {
        this.rightBottomChart3 = this.$echarts.init(document.getElementById('right-bottom-chart-3'))
        const option = {
          tooltip: {
            trigger: 'axis'
          },
          grid: {
            bottom: '5%',
            top: '30%',
            left: '10%',
            right: '10%',
            containLabel: true
          },
          legend: {
            top: 80,
            right: '10%',
            itemGap: 15,
            textStyle: {
              fontSize: 14,
              fontFamily: 'LanTing',
              color: '#eee',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['保养计划数', '保养完成数']
          },
          xAxis: {
            type: 'category',
            data: [],
            axisLine: {
              lineStyle: {
                color: '#eee'
              }
            },
            axisLabel: {
              margin: 14,
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              interval: 0,
              rotate: 45
            },
            axisTick: {
              show: true
            }
          },
          yAxis: [
            {
              type: 'value',
              minInterval: 1,
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              },
              axisLabel: {
                fontSize: 14,
                color: '#eee',
                fontWeight: 'bold',
                margin: 14
              }
            }
          ],
          series: [
            {
              type: 'bar',
              barWidth: 12,
              name: '保养计划数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#295485'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#2F95F9'
                    }
                  ]
                )
              }
            },
            {
              type: 'bar',
              barWidth: 12,
              name: '保养完成数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#35535E'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#92F7AD'
                    }
                  ]
                )
              }
            }
          ]
        }
        option.xAxis.data = this.rightBottomChart3Data.map(item => item.monthStr)
        option.series[0].data = this.rightBottomChart3Data.map(item => {
          return {
            name: item.monthStr,
            value: item.planNumber
          }
        })
        option.series[1].data = this.rightBottomChart3Data.map(item => {
          return {
            name: item.monthStr,
            value: item.completeNumber
          }
        })
        this.$nextTick(() => this.rightBottomChart3.setOption(option, true))
      },
      handleWindowResize() {
        if (this.leftChart1) this.leftChart1.resize()
        if (this.leftChart2) this.leftChart2.resize()
        if (this.rightTopChart) this.rightTopChart.resize()
        if (this.rightBottomChart1) this.rightBottomChart1.resize()
        if (this.rightBottomChart2) this.rightBottomChart2.resize()
        if (this.rightBottomChart3) this.rightBottomChart3.resize()
      }
    }
  }
</script>
<style scoped lang="less">
  .component-container {
    display: flex;
    height: 100%;
    justify-content: space-between;
    .left-container {
      width: 18%;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      /*图表区域*/
      > div:not(div:last-child) {
        height: 45%;
        .title-container {
          position: relative;
          width: 100%;
          height: 3.6vw;
          display: flex;
          img {
            height: 100%;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 0;
          }
          span {
            position: relative;
            z-index: 1;
            font-size: 1.2vw;
            font-family: 'ZongYi';
            margin: auto;
            letter-spacing: 0.25vw;
          }
        }
        .left-chart-container {
          height: calc(100% - 3.6vw);
        }
      }
      /*导航区域*/
      > div:last-child {
        height: 4.27vw;
        display: flex;
        justify-content: space-between;
        font-size: 0;
        line-height: 0;
        .navigator-container {
          position: relative;
          width: 100%;
          cursor: pointer;
          text-align: center;
          img {
            height: 100%;
          }
          span {
            width: 100%;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            font-size: 0.8vw;
            font-family: 'ZongYi';
            letter-spacing: 0.1vw;
            padding-left: 0.1vw;
          }
        }
      }
    }
  }
</style>
src/views/mdc/base/modules/GradeSignage/EquipmentSignage.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1042 @@
<template>
  <div class="component-container">
    <slot name="loading"/>
    <div class="left-container">
      <div>
        <img src="@/assets/signage/equipment/left-top-container.png"/>
        <div class="left-top-content-container">
          <div>
            <img src="@/assets/signage/equipment/equipmentId-container.png"/>
            <span style="font-family: LanTing;letter-spacing: 0.1vw">{{currentProductionId}}</span>
          </div>
          <div>
            <img src="@/assets/signage/equipment/status-container.png"/>
            <span>设备状态:<span
              :style="{color:setEquipmentStatusFontColor(equipmentStatusAndInfoObj.oporationDict)}">{{equipmentStatusAndInfoObj.oporationDict}}</span></span>
          </div>
          <div>
            <img src="@/assets/signage/equipment/status-container.png"/>
            <span>维保状态:<span
              :style="{color:setEquipmentStatusFontColor(equipmentStatusAndInfoObj.maintenanceStatus)}">{{equipmentStatusAndInfoObj.maintenanceStatus}}</span></span>
          </div>
        </div>
      </div>
      <div>
        <img src="@/assets/signage/equipment/left-bottom-container.png"/>
        <div>
          <table>
            <thead>
            <tr>
              <th>设备编号</th>
              <th>设备名称</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="item in equipmentList" :key="item.id" @click="handleSelectEquipment(item.equipmentId)"
                :style="{color:currentProductionId===item.equipmentId?'#EECA03':''}">
              <td>
                <a-tooltip :title="item.equipmentId" placement="left">
                  <span>{{item.equipmentId}}</span>
                </a-tooltip>
              </td>
              <a-tooltip :title="item.equipmentName" placement="right">
                <td>{{item.equipmentName}}</td>
              </a-tooltip>
            </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
    <div class="right-container">
      <div>
        <img src="@/assets/signage/equipment/equipment-info-line.png"/>
        <div class="right-top-content-container">
          <div>
            <div>
              <dv-decoration-9 class="rotate-circle" :color="['#4B95E6', '#EECA03']">设备实时信息</dv-decoration-9>
            </div>
            <div>
              <table>
                <tr>
                  <td>设备名称</td>
                  <a-tooltip :title="setTooltipTittle(equipmentStatusAndInfoObj.equipmentName)">
                    <td :style="{color:setNullValueFontColor(equipmentStatusAndInfoObj.equipmentName)}">
                      {{equipmentStatusAndInfoObj.equipmentName|filterNullValue}}
                    </td>
                  </a-tooltip>
                </tr>
                <tr>
                  <td>设备型号</td>
                  <a-tooltip :title="setTooltipTittle(equipmentStatusAndInfoObj.equipmentModel)">
                    <td :style="{color:setNullValueFontColor(equipmentStatusAndInfoObj.equipmentModel)}">
                      {{equipmentStatusAndInfoObj.equipmentModel|filterNullValue}}
                    </td>
                  </a-tooltip>
                </tr>
                <tr>
                  <td>操作系统</td>
                  <a-tooltip :title="setTooltipTittle(equipmentStatusAndInfoObj.systemType)">
                    <td :style="{color:setNullValueFontColor(equipmentStatusAndInfoObj.systemType)}">
                      {{equipmentStatusAndInfoObj.systemType|filterNullValue}}
                    </td>
                  </a-tooltip>
                </tr>
                <tr>
                  <td>设备管理员</td>
                  <a-tooltip :title="setTooltipTittle(equipmentStatusAndInfoObj.equipmentManager)">
                    <td :style="{color:setNullValueFontColor(equipmentStatusAndInfoObj.equipmentManager)}">
                      {{equipmentStatusAndInfoObj.equipmentManager|filterNullValue}}
                    </td>
                  </a-tooltip>
                </tr>
                <tr>
                  <td>安装位置</td>
                  <a-tooltip :title="setTooltipTittle(equipmentStatusAndInfoObj.installationPosition)">
                    <td :style="{color:setNullValueFontColor(equipmentStatusAndInfoObj.installationPosition)}">
                      {{equipmentStatusAndInfoObj.installationPosition|filterNullValue}}
                    </td>
                  </a-tooltip>
                </tr>
              </table>
            </div>
            <div>
              <table>
                <tr>
                  <td>加工程序</td>
                  <a-tooltip :title="setTooltipTittle(equipmentStatusAndInfoObj.sequenceNumber)">
                    <td :style="{color:setNullValueFontColor(equipmentStatusAndInfoObj.sequenceNumber)}">
                      {{equipmentStatusAndInfoObj.sequenceNumber|filterNullValue}}
                    </td>
                  </a-tooltip>
                </tr>
                <tr>
                  <td>主轴转速</td>
                  <a-tooltip :title="setTooltipTittle(equipmentStatusAndInfoObj.spindleSpeed)">
                    <td :style="{color:setNullValueFontColor(equipmentStatusAndInfoObj.spindleSpeed)}">
                      {{equipmentStatusAndInfoObj.spindleSpeed|filterNullValue}}
                    </td>
                  </a-tooltip>
                </tr>
                <tr>
                  <td>主轴负载</td>
                  <a-tooltip :title="setTooltipTittle(equipmentStatusAndInfoObj.spindleLoad)">
                    <td :style="{color:setNullValueFontColor(equipmentStatusAndInfoObj.spindleLoad)}">
                      {{equipmentStatusAndInfoObj.spindleLoad|filterNullValue}}
                    </td>
                  </a-tooltip>
                </tr>
                <tr>
                  <td>主轴倍率</td>
                  <a-tooltip :title="setTooltipTittle(equipmentStatusAndInfoObj.spindlebeilv)">
                    <td :style="{color:setNullValueFontColor(equipmentStatusAndInfoObj.spindlebeilv)}">
                      {{equipmentStatusAndInfoObj.spindlebeilv|filterNullValue}}
                    </td>
                  </a-tooltip>
                </tr>
                <tr>
                  <td>进给倍率</td>
                  <a-tooltip :title="setTooltipTittle(equipmentStatusAndInfoObj.feedbeilv)">
                    <td :style="{color:setNullValueFontColor(equipmentStatusAndInfoObj.feedbeilv)}">
                      {{equipmentStatusAndInfoObj.feedbeilv|filterNullValue}}
                    </td>
                  </a-tooltip>
                </tr>
              </table>
            </div>
            <div>
              <table>
                <tr>
                  <td>班次</td>
                  <a-tooltip :title="setTooltipTittle(equipmentStatusAndInfoObj.shift)">
                    <td :style="{color:setNullValueFontColor(equipmentStatusAndInfoObj.shift)}">
                      {{equipmentStatusAndInfoObj.shift|filterNullValue}}
                    </td>
                  </a-tooltip>
                </tr>
                <tr>
                  <td>设备报警</td>
                  <a-tooltip :title="setTooltipTittle(equipmentStatusAndInfoObj.alarm)">
                    <td :style="{color:setNullValueFontColor(equipmentStatusAndInfoObj.alarm)}">
                      {{equipmentStatusAndInfoObj.alarm|filterNullValue}}
                    </td>
                  </a-tooltip>
                </tr>
                <tr>
                  <td>报修情况</td>
                  <a-tooltip :title="setTooltipTittle(equipmentStatusAndInfoObj.reportRepairStatus)">
                    <td :style="{color:setNullValueFontColor(equipmentStatusAndInfoObj.reportRepairStatus)}">
                      {{equipmentStatusAndInfoObj.reportRepairStatus|filterNullValue}}
                    </td>
                  </a-tooltip>
                </tr>
                <tr>
                  <td>本次点检</td>
                  <a-tooltip :title="setTooltipTittle(equipmentStatusAndInfoObj.nextInspection)">
                    <td :style="{color:setNullValueFontColor(equipmentStatusAndInfoObj.nextInspection)}">
                      {{equipmentStatusAndInfoObj.nextInspection|filterNullValue}}
                    </td>
                  </a-tooltip>
                </tr>
                <tr>
                  <td>本次保养</td>
                  <a-tooltip :title="setTooltipTittle(equipmentStatusAndInfoObj.nextMaintenance)">
                    <td :style="{color:setNullValueFontColor(equipmentStatusAndInfoObj.nextMaintenance)}">
                      {{equipmentStatusAndInfoObj.nextMaintenance|filterNullValue}}
                    </td>
                  </a-tooltip>
                </tr>
              </table>
            </div>
          </div>
          <div>
            <div v-for="(item,index) in navigatorList" :key="index" @click="navigateToPage(item.routeName)">
              <img src="@/assets/signage/title.png"/>
              <span>{{item.name}}</span>
            </div>
          </div>
        </div>
      </div>
      <div>
        <div>
          <img src="@/assets/signage/equipment/day-rate-analysis.png"/>
          <div class="right-chart-container" id="right-bottom-chart-1"></div>
        </div>
        <div>
          <img src="@/assets/signage/equipment/month-rate-analysis.png"/>
          <div class="right-chart-container" id="right-bottom-chart-2"></div>
        </div>
        <div>
          <img src="@/assets/signage/equipment/product-qualified-rate.png"/>
          <div class="right-chart-container" id="right-bottom-chart-3"></div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  import signageApi from '@/api/signage'
  export default {
    name: 'EquipmentSignage',
    props: {
      currentProductionId: {
        type: String
      },
      preSignageProductionId: {
        type: String
      }
    },
    data() {
      return {
        rightBottomChart1: null,
        rightBottomChart2: null,
        rightBottomChart3: null,
        rightBottomChart1Data: [],
        rightBottomChart2And3Data: [],
        chartQuantity: 3,
        hasLoadedChartDataQuantity: 0,
        equipmentList: [],
        equipmentStatusAndInfoObj: {},
        navigatorList: [
          {
            name: '台账',
            routeName: 'eam-equipment'
          },
          {
            name: 'ç»´ä¿®',
            routeName: 'eam-repair-EamRepairOrderList'
          },
          {
            name: '点检',
            routeName: 'eam-maintenance-EamInspectionOrderList'
          },
          {
            name: '保养',
            routeName: 'eam-maintenance-week_maintenance'
          }
        ]
      }
    },
    watch: {
      hasLoadedChartDataQuantity: {
        handler(val) {
          if (val === this.chartQuantity) this.$emit('loadFinished')
        }
      }
    },
    filters: {
      filterNullValue(value) {
        return value ? value : '无'
      }
    },
    mounted() {
      this.getEquipmentListByApi()
      this.handleWindowResize()
      window.addEventListener('resize', this.handleWindowResize)
    },
    beforeDestroy() {
      window.removeEventListener('resize', this.handleWatchHistory)
    },
    methods: {
      getEquipmentListByApi() {
        const that = this
        signageApi.getEquipmentListByProductionIdApi(this.preSignageProductionId)
          .then(res => {
            if (res.success) {
              that.equipmentList = res.result
              this.handleSelectEquipment(this.currentProductionId, true)
            }
          })
      },
      getEquipmentStatusAndInfoByApi() {
        const that = this
        this.equipmentStatusAndInfoObj = {}
        signageApi.getEquipmentOperationStatusAndInfoApi(this.currentProductionId)
          .then(res => {
            if (res.success) {
              that.equipmentStatusAndInfoObj = res.result
            }
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      /**
       * è®¾å¤‡åˆ—表选中时触发
       * @param equipmentId
       */
      handleSelectEquipment(equipmentId, isFirstLoading = false) {
        if (!isFirstLoading) this.$emit('switchEquipmentSignageProductionId', equipmentId)
        this.$nextTick(() => {
          this.hasLoadedChartDataQuantity = 0
          this.$emit('startPageLoading')
          this.getChartDataByApi()
          this.getEquipmentStatusAndInfoByApi()
        })
      },
      /**
       * ç‚¹å‡»è·³è½¬æŒ‰é’®æ—¶è§¦å‘携带equipmentId参数跳转至对应页面
       * @param routeName è·¯ç”±åç§°
       */
      navigateToPage(routeName) {
        // console.log('routeName', routeName)
        // this.$router.push({
        //   name: routeName,
        //   params: { equipmentId: this.currentProductionId }
        // })
        const url = this.$router.resolve({ name: routeName }).href
        window.open(url, '_blank')
      },
      getChartDataByApi() {
        this.geRightBottomChart1DataByApi()
        this.geRightBottomChart2And3DataByApi()
      },
      geRightBottomChart1DataByApi() {
        const that = this
        signageApi.getDayRateAnalysisApi(this.currentProductionId)
          .then(res => {
            if (res.success) that.rightBottomChart1Data = res.result
            else that.rightBottomChart1Data = { dataList: [], dateList: [] }
            that.initRightBottomChart1()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      geRightBottomChart2And3DataByApi() {
        const that = this
        signageApi.getMonthRateAnalysisAndQualifiedRateApi(this.currentProductionId)
          .then(res => {
            if (res.success) that.rightBottomChart2And3Data = res.result
            else that.rightBottomChart2And3Data = { dataList: [], dateList: [] }
            that.initRightBottomChart2()
            that.initRightBottomChart3()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      initRightBottomChart1() {
        this.rightBottomChart1 = this.$echarts.init(document.getElementById('right-bottom-chart-1'))
        const { dateList, dataList } = this.rightBottomChart1Data
        const newData = {
          xAxis: dateList,
          yAxis: [
            {
              name: 'OEE',
              value: dataList.map(item => item.oee)
            },
            {
              name: 'TEEP',
              value: dataList.map(item => item.utilizationRate)
            }
          ]
        }
        let legendData = []
        let seriesData = []
        let colorArr = ['#2F95FA', '#92F7AD']
        legendData = newData.yAxis.map((item) => item.name)
        seriesData = newData.yAxis.map((item1, index1) => {
          return {
            name: item1.name,
            type: 'line',
            symbol: 'circle',
            symbolSize: 8,
            itemStyle: {
              color: colorArr[index1]
            },
            yAxisIndex: 1,
            data: item1.value // æŠ˜çº¿å›¾çš„æ•°æ®
          }
        })
        const option = {
          grid: {
            bottom: '5%',
            top: '30%',
            left: '10%',
            right: '15%',
            containLabel: true
          },
          tooltip: {
            trigger: 'axis'
          },
          legend: {
            top: 80,
            right: '5%',
            data: legendData,
            itemGap: 30,
            textStyle: {
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            }
          },
          xAxis: {
            triggerEvent: true,
            data: newData.xAxis || [],
            axisLabel: {
              interval: 0,
              show: true,
              fontSize: 14,
              color: '#eee',
              margin: 14,
              fontFamily: 'LanTing',
              rotate: 45
            },
            axisLine: {
              show: true,
              lineStyle: {
                color: '#eee'
              }
            },
            axisTick: {
              show: true
            },
            splitLine: {
              show: false
            }
          },
          yAxis: [
            {
              type: 'value',
              position: 'left',
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              splitLine: {
                show: false
              }
            },
            {
              type: 'value',
              position: 'left',
              axisLabel: {
                show: true,
                color: '#eee',
                margin: 14,
                fontSize: 14,
                fontWeight: 'bold',
                formatter(value) {
                  return value + '%'
                }
              },
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              }
            }
          ],
          series: seriesData
        }
        this.$nextTick(() => this.rightBottomChart1.setOption(option, true))
      },
      initRightBottomChart2() {
        this.rightBottomChart2 = this.$echarts.init(document.getElementById('right-bottom-chart-2'))
        const { dateList, dataList } = this.rightBottomChart2And3Data
        const newData = {
          xAxis: dateList,
          yAxis: [
            {
              name: 'OEE',
              value: dataList.map(item => item.oee)
            },
            {
              name: 'TEEP',
              value: dataList.map(item => item.utilizationRate)
            }
          ]
        }
        let legendData = []
        let seriesData = []
        let colorArr = ['#2F95FA', '#92F7AD']
        legendData = newData.yAxis.map((item) => item.name)
        seriesData = newData.yAxis.map((item1, index1) => {
          return {
            name: item1.name,
            type: 'line',
            symbol: 'circle',
            symbolSize: 8,
            itemStyle: {
              color: colorArr[index1]
            },
            yAxisIndex: 1,
            data: item1.value // æŠ˜çº¿å›¾çš„æ•°æ®
          }
        })
        const option = {
          grid: {
            bottom: '8%',
            top: '30%',
            left: '10%',
            right: '15%',
            containLabel: true
          },
          tooltip: {
            trigger: 'axis'
          },
          legend: {
            top: 80,
            right: '5%',
            data: legendData,
            itemGap: 30,
            textStyle: {
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            }
          },
          xAxis: {
            triggerEvent: true,
            data: newData.xAxis || [],
            axisLabel: {
              interval: 0,
              show: true,
              fontSize: 14,
              color: '#eee',
              margin: 14,
              fontFamily: 'LanTing'
            },
            axisLine: {
              show: true,
              lineStyle: {
                color: '#eee'
              }
            },
            axisTick: {
              show: true
            },
            splitLine: {
              show: false
            }
          },
          yAxis: [
            {
              type: 'value',
              position: 'left',
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              splitLine: {
                show: false
              }
            },
            {
              type: 'value',
              position: 'left',
              axisLabel: {
                show: true,
                color: '#eee',
                margin: 14,
                fontSize: 14,
                fontWeight: 'bold',
                formatter(value) {
                  return value + '%'
                }
              },
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              }
            }
          ],
          series: seriesData
        }
        this.$nextTick(() => this.rightBottomChart2.setOption(option, true))
      },
      initRightBottomChart3() {
        this.rightBottomChart3 = this.$echarts.init(document.getElementById('right-bottom-chart-3'))
        const { dateList, dataList } = this.rightBottomChart2And3Data
        const newData = {
          xAxis: dateList,
          yAxis: [
            {
              name: '合格率',
              value: dataList.map(item => item.passRate)
            }
          ]
        }
        let legendData = []
        let seriesData = []
        let colorArr = ['#2F95FA', '#92F7AD']
        legendData = newData.yAxis.map((item) => item.name)
        seriesData = newData.yAxis.map((item1, index1) => {
          return {
            name: item1.name,
            type: 'line',
            symbol: 'circle',
            symbolSize: 8,
            itemStyle: {
              color: colorArr[index1]
            },
            yAxisIndex: 1,
            data: item1.value // æŠ˜çº¿å›¾çš„æ•°æ®
          }
        })
        const option = {
          grid: {
            bottom: '8%',
            top: '30%',
            left: '10%',
            right: '15%',
            containLabel: true
          },
          tooltip: {
            trigger: 'axis'
          },
          legend: {
            top: 80,
            right: '5%',
            data: legendData,
            itemGap: 30,
            textStyle: {
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            }
          },
          xAxis: {
            triggerEvent: true,
            data: newData.xAxis || [],
            axisLabel: {
              interval: 0,
              show: true,
              fontSize: 14,
              color: '#eee',
              margin: 14,
              fontFamily: 'LanTing'
            },
            axisLine: {
              show: true,
              lineStyle: {
                color: '#eee'
              }
            },
            axisTick: {
              show: true
            },
            splitLine: {
              show: false
            }
          },
          yAxis: [
            {
              type: 'value',
              position: 'left',
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              splitLine: {
                show: false
              }
            },
            {
              type: 'value',
              position: 'left',
              axisLabel: {
                show: true,
                color: '#eee',
                margin: 14,
                fontSize: 14,
                fontWeight: 'bold',
                formatter(value) {
                  return value + '%'
                }
              },
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              }
            }
          ],
          series: seriesData
        }
        this.$nextTick(() => this.rightBottomChart3.setOption(option, true))
      },
      /**
       * è®¾ç½®è¡¨æ ¼å•元格悬浮标题
       * @param value è¡¨æ ¼å•元格值
       * @returns {string} æ‚¬æµ®æ ‡é¢˜å†…容
       */
      setTooltipTittle(value) {
        return value && value !== '无' ? value : ''
      },
      /**
       * è®¾ç½®è¡¨æ ¼å­—体颜色
       * @param value è¡¨æ ¼å•元格值
       * @returns {string} é¢œè‰²ç 
       */
      setNullValueFontColor(value) {
        return value ? '' : '#8A8A8A'
      },
      /**
       * è®¾ç½®è®¾å¤‡çŠ¶æ€å­—ä½“é¢œè‰²
       * @param value è®¾å¤‡çŠ¶æ€æ–‡å­—
       * @returns {string} é¢œè‰²ç 
       */
      setEquipmentStatusFontColor(value) {
        switch (value) {
          case '正常':
          case '运行':
            return '#06FF00'
          case '保养':
          case '点检':
          case '待机':
            return '#FFF600'
          case '报警':
          case 'ç»´ä¿®':
            return '#FF5757'
          case '关机':
            return '#8A8A8A'
        }
      },
      handleWindowResize() {
        if (this.rightBottomChart1) this.rightBottomChart1.resize()
        if (this.rightBottomChart2) this.rightBottomChart2.resize()
        if (this.rightBottomChart3) this.rightBottomChart3.resize()
      }
    }
  }
</script>
<style scoped lang="less">
  .component-container {
    display: flex;
    height: 100%;
    justify-content: space-between;
    .left-container {
      width: 18%;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      > div:first-child {
        position: relative;
        height: 17.76vw;
        > img {
          height: 100%;
          position: absolute;
        }
        .left-top-content-container {
          height: 100%;
          display: flex;
          flex-direction: column;
          justify-content: space-evenly;
          align-items: center;
          > div {
            position: relative;
            display: flex;
            &:first-child {
              height: 3.43vw;
            }
            &:not(:first-child) {
              height: 3.59vw;
            }
            img {
              height: 100%;
              position: absolute;
              top: 50%;
              left: 50%;
              transform: translate(-50%, -50%);
              z-index: 0;
            }
            > span {
              position: relative;
              z-index: 1;
              font-size: 1.2vw;
              font-family: 'ZongYi';
              margin: auto;
              letter-spacing: 0.25vw;
            }
          }
        }
      }
      > div:last-child {
        position: relative;
        height: 25.62vw;
        display: flex;
        flex-direction: column;
        justify-content: center;
        img {
          height: 100%;
          position: absolute;
          z-index: 0;
        }
        > div {
          height: 93%;
          padding: 0 6% 0 7%;
          overflow: hidden auto;
          position: relative;
          z-index: 1;
          table {
            width: 100%;
            table-layout: fixed;
            td, th {
              width: 50%;
              text-align: center;
              height: 1.85vw;
              white-space: nowrap;
              overflow: hidden;
              text-overflow: ellipsis;
            }
            th {
              background-color: #0E4D9C;
              font-family: 'ZongYi';
              font-weight: normal;
              font-size: 1vw;
              position: sticky;
              top: 0;
              z-index: 2;
            }
            tr {
              td {
                font-family: 'LanTing';
                font-size: 0.9vw;
                cursor: pointer;
              }
              &:nth-child(odd) {
                td {
                  background-color: #162E58;
                }
              }
              &:nth-child(even) {
                td {
                  background-color: #2C5894;
                }
              }
            }
          }
        }
      }
    }
    .right-top-content-container {
      width: 72.7vw;
      height: 25.31vw;
      display: flex;
      flex-direction: column;
      padding: 0 2.5%;
      position: relative;
      z-index: 1;
      > div {
        display: flex;
        justify-content: space-between;
        align-items: center;
        &:first-child {
          flex: 0.8;
          > div:first-child {
            .rotate-circle {
              width: 14vw;
              height: 14vw;
              font-size: 1vw;
              font-family: ZongYi;
            }
          }
          > div:not(:first-child) {
            flex: 0.3;
            table {
              text-align: center;
              width: 100%;
              table-layout: fixed;
              td {
                width: 50%;
                font-family: 'ZongYi';
                font-size: 1.1vw;
                height: calc(14vw / 5);
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
              }
              tr {
                &:nth-child(odd) {
                  td {
                    background-color: #2C5894;
                  }
                }
                &:nth-child(even) {
                  td {
                    background-color: #162E58;
                  }
                }
              }
            }
          }
        }
        &:last-child {
          flex: 0.2;
          > div {
            width: 13vw;
            height: 3.59vw;
            position: relative;
            display: flex;
            cursor: pointer;
            img {
              width: 100%;
              height: 100%;
              position: absolute;
              top: 50%;
              left: 50%;
              transform: translate(-50%, -50%);
              z-index: 0;
            }
            span {
              font-size: 1.2vw;
              font-family: ZongYi;
              position: relative;
              z-index: 1;
              margin: auto;
              text-align: center;
            }
          }
        }
      }
    }
  }
</style>
src/views/mdc/base/modules/GradeSignage/SectionSignage.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1350 @@
<template>
  <div class="component-container">
    <slot name="loading"/>
    <div class="left-container">
      <div>
        <div class="title-container">
          <img src="@/assets/signage/title.png"/>
          <span>设备状态</span>
        </div>
        <div class="left-chart-container" id="left-chart-1"></div>
      </div>
      <div>
        <div class="title-container">
          <img src="@/assets/signage/title.png"/>
          <span>维保状态</span>
        </div>
        <div class="left-chart-container" id="left-chart-2"></div>
      </div>
      <div>
        <div class="title-container">
          <img src="@/assets/signage/title.png"/>
          <span>设备检索</span>
        </div>
        <div class="equipment-search-container">
          <img src="@/assets/signage/section/search-input.png"/>
          <a-auto-complete @select="handleSelectChange" placeholder="回车键查询" :filter-option="filterOption"
                           :dataSource="equipmentList.map(item=>item.equipmentId)"
                           style="position: absolute;width: 15vw;height: 2.24vw;"/>
        </div>
      </div>
    </div>
    <div class="right-container">
      <div>
        <img src="@/assets/signage/company/rate-analysis-container.png"/>
        <div class="right-chart-container" id="right-top-chart"></div>
      </div>
      <div>
        <div>
          <img src="@/assets/signage/company/repair-analysis.png"/>
          <div class="right-chart-container" id="right-bottom-chart-1"></div>
        </div>
        <div>
          <img src="@/assets/signage/company/inspection-analysis.png"/>
          <div class="right-chart-container" id="right-bottom-chart-2"></div>
        </div>
        <div>
          <img src="@/assets/signage/company/maintenance-analysis.png"/>
          <div class="right-chart-container" id="right-bottom-chart-3"></div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  import signageApi from '@/api/signage'
  export default {
    name: 'SectionSignage',
    props: {
      currentProductionId: {
        type: String
      }
    },
    data() {
      return {
        leftChart1: null,
        leftChart2: null,
        rightTopChart: null,
        rightBottomChart1: null,
        rightBottomChart2: null,
        rightBottomChart3: null,
        leftChart1Data: [],
        leftChart2Data: [],
        rightTopChartData: [],
        rightBottomChart1Data: [],
        rightBottomChart2Data: [],
        rightBottomChart3Data: [],
        chartQuantity: 6,
        hasLoadedChartDataQuantity: 0,
        activeIndex: null,
        equipmentList: [
          {
            'id': '1694181185660579842',
            'createBy': 'admin',
            'createTime': '2023-08-23 10:54:05',
            'updateBy': 'admin',
            'updateTime': '2024-09-14 09:15:10',
            'equipmentId': '2140342',
            'equipmentName': '数控卧车',
            'equipmentType': '复合机床',
            'productionName': null,
            'orgCodeTxt': null,
            'systemVersion': null,
            'devicePower': null,
            'equipmentIp': '192.168.86.44',
            'dataPort': '8193',
            'driveType': 'FANUC',
            'equipmentModel': 'GLS-200',
            'controlSystem': 'FANUC',
            'systemType': null,
            'deviceCategory': null,
            'alarm': null,
            'collectTime': null,
            'oporation': null,
            'saveTableName': 'FANUC_2140342',
            'deviceAbnormalStatus': 1,
            'equipmentStatus': 0,
            'deviceLevel': 'A',
            'deviceImportanceLevel': null,
            'sortNo': null,
            'remark': null,
            'selectedDeparts': null,
            'selectedProduction': null
          },
          {
            'id': '1694181274449801217',
            'createBy': 'admin',
            'createTime': '2023-08-23 10:54:26',
            'updateBy': 'admin',
            'updateTime': '2024-09-12 13:27:27',
            'equipmentId': '2140345',
            'equipmentName': '数控卧式车床',
            'equipmentType': '车床',
            'productionName': null,
            'orgCodeTxt': null,
            'systemVersion': null,
            'devicePower': null,
            'equipmentIp': '192.168.86.45',
            'dataPort': '8193',
            'driveType': 'FANUC',
            'equipmentModel': 'FTC-350L',
            'controlSystem': 'FANUC',
            'systemType': null,
            'deviceCategory': null,
            'alarm': null,
            'collectTime': null,
            'oporation': null,
            'saveTableName': 'FANUC_2140345',
            'deviceAbnormalStatus': 1,
            'equipmentStatus': 0,
            'deviceLevel': null,
            'deviceImportanceLevel': null,
            'sortNo': null,
            'remark': null,
            'selectedDeparts': null,
            'selectedProduction': null
          },
          {
            'id': '1694182117068697602',
            'createBy': 'admin',
            'createTime': '2023-08-23 10:57:47',
            'updateBy': 'admin',
            'updateTime': '2024-01-31 11:30:00',
            'equipmentId': '2640236',
            'equipmentName': '立式加工中心',
            'equipmentType': '加工中心',
            'productionName': null,
            'orgCodeTxt': null,
            'systemVersion': null,
            'devicePower': null,
            'equipmentIp': '192.168.86.17',
            'dataPort': '8193',
            'driveType': 'FANUC',
            'equipmentModel': 'VNP-32A',
            'controlSystem': 'FANUC',
            'systemType': null,
            'deviceCategory': null,
            'alarm': null,
            'collectTime': null,
            'oporation': null,
            'saveTableName': 'FANUC_2640236',
            'deviceAbnormalStatus': 1,
            'equipmentStatus': 0,
            'deviceLevel': null,
            'deviceImportanceLevel': null,
            'sortNo': null,
            'remark': null,
            'selectedDeparts': null,
            'selectedProduction': null
          },
          {
            'id': '1694182375483961346',
            'createBy': 'admin',
            'createTime': '2023-08-23 10:58:49',
            'updateBy': 'admin',
            'updateTime': '2024-01-31 11:29:19',
            'equipmentId': '2640263',
            'equipmentName': '数控加工中心',
            'equipmentType': '加工中心',
            'productionName': null,
            'orgCodeTxt': null,
            'systemVersion': null,
            'devicePower': null,
            'equipmentIp': '192.168.86.74',
            'dataPort': '8193',
            'driveType': 'FANUC',
            'equipmentModel': 'SW-850',
            'controlSystem': 'FANUC',
            'systemType': null,
            'deviceCategory': null,
            'alarm': null,
            'collectTime': null,
            'oporation': null,
            'saveTableName': 'FANUC_2640263',
            'deviceAbnormalStatus': 1,
            'equipmentStatus': 0,
            'deviceLevel': null,
            'deviceImportanceLevel': null,
            'sortNo': null,
            'remark': null,
            'selectedDeparts': null,
            'selectedProduction': null
          },
          {
            'id': '1701169612893388801',
            'createBy': 'admin',
            'createTime': '2023-09-11 17:43:36',
            'updateBy': 'admin',
            'updateTime': '2023-11-29 16:45:11',
            'equipmentId': '2640315',
            'equipmentName': '加工中心',
            'equipmentType': '车床',
            'productionName': null,
            'orgCodeTxt': null,
            'systemVersion': null,
            'devicePower': null,
            'equipmentIp': '192.168.86.90',
            'dataPort': '19000',
            'driveType': 'LSV2',
            'equipmentModel': 'C32U',
            'controlSystem': 'LSV2',
            'systemType': null,
            'deviceCategory': null,
            'alarm': null,
            'collectTime': null,
            'oporation': null,
            'saveTableName': 'LSV2_2640315',
            'deviceAbnormalStatus': 1,
            'equipmentStatus': 0,
            'deviceLevel': null,
            'deviceImportanceLevel': null,
            'sortNo': null,
            'remark': null,
            'selectedDeparts': null,
            'selectedProduction': null
          },
          {
            'id': '1728950536953856002',
            'createBy': 'admin',
            'createTime': '2023-11-27 09:35:05',
            'updateBy': 'admin',
            'updateTime': '2024-01-31 11:29:01',
            'equipmentId': '2140111',
            'equipmentName': '数控车床',
            'equipmentType': '车床',
            'productionName': null,
            'orgCodeTxt': null,
            'systemVersion': null,
            'devicePower': null,
            'equipmentIp': '192.168.86.167',
            'dataPort': '502',
            'driveType': 'ZUOLAN',
            'equipmentModel': 'SSCKZ40-1000',
            'controlSystem': 'ZUOLAN',
            'systemType': null,
            'deviceCategory': null,
            'alarm': null,
            'collectTime': null,
            'oporation': null,
            'saveTableName': 'ZUOLAN_2140111',
            'deviceAbnormalStatus': 1,
            'equipmentStatus': 0,
            'deviceLevel': null,
            'deviceImportanceLevel': null,
            'sortNo': null,
            'remark': null,
            'selectedDeparts': null,
            'selectedProduction': null
          },
          {
            'id': '1753259512871624705',
            'createBy': 'admin',
            'createTime': '2024-02-02 11:30:16',
            'updateBy': null,
            'updateTime': null,
            'equipmentId': '3102038',
            'equipmentName': '电火花成型机',
            'equipmentType': null,
            'productionName': null,
            'orgCodeTxt': null,
            'systemVersion': null,
            'devicePower': null,
            'equipmentIp': '192.168.86.23',
            'dataPort': '502',
            'driveType': 'ZUOLAN',
            'equipmentModel': 'DM7150',
            'controlSystem': 'ZUOLAN',
            'systemType': null,
            'deviceCategory': null,
            'alarm': null,
            'collectTime': null,
            'oporation': null,
            'saveTableName': 'ZUOLAN_3102038',
            'deviceAbnormalStatus': 1,
            'equipmentStatus': 0,
            'deviceLevel': null,
            'deviceImportanceLevel': null,
            'sortNo': null,
            'remark': '222333',
            'selectedDeparts': null,
            'selectedProduction': null
          }
        ],
      }
    },
    watch: {
      hasLoadedChartDataQuantity: {
        handler(val) {
          if (val === this.chartQuantity) this.$emit('loadFinished')
        }
      }
    },
    mounted() {
      this.getEquipmentListByApi()
      this.getChartDataByApi()
      this.handleWindowResize()
      window.addEventListener('resize', this.handleWindowResize)
    },
    beforeDestroy() {
      window.removeEventListener('resize', this.handleWatchHistory)
    },
    methods: {
      getEquipmentListByApi() {
        const that = this
        signageApi.getEquipmentListByProductionIdApi(this.currentProductionId)
          .then(res => {
            if (res.success) that.equipmentList = res.result
          })
      },
      getChartDataByApi() {
        this.getLeftChart1DataByApi()
        this.getLeftChart2DataByApi()
        this.geRightTopChartDataByApi()
        this.geRightBottomChartData1ByApi()
        this.geRightBottomChartData2ByApi()
        this.geRightBottomChartData3ByApi()
      },
      getLeftChart1DataByApi() {
        const that = this
        signageApi.getEquipmentStatusAnalysisApi(this.currentProductionId)
          .then(res => {
            if (res.success) {
              this.leftChart1Data = res.result.equipmentStatus
            }
            this.initLeftChart1()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      getLeftChart2DataByApi() {
        const that = this
        signageApi.getRepairAndMaintenanceStatusApi(this.currentProductionId)
          .then(res => {
            if (res.success) {
              this.leftChart2Data = res.result.map(item => {
                return {
                  name: item.statusText,
                  value: item.totalNumber
                }
              })
            }
            this.initLeftChart2()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      geRightTopChartDataByApi() {
        const that = this
        signageApi.getRateAnalysisTrendApi(this.currentProductionId)
          .then(res => {
            if (res.success) this.rightTopChartData = res.result
            this.initRightTopChart()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      geRightBottomChartData1ByApi() {
        const that = this
        signageApi.getRepairAnalysisApi(this.currentProductionId)
          .then(res => {
            if (res.success) this.rightBottomChart1Data = res.result
            this.initRightBottomChart1()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      geRightBottomChartData2ByApi() {
        const that = this
        signageApi.getInspectionAnalysisApi(this.currentProductionId)
          .then(res => {
            if (res.success) this.rightBottomChart2Data = res.result
            this.initRightBottomChart2()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      geRightBottomChartData3ByApi() {
        const that = this
        signageApi.getMaintenanceAnalysisApi(this.currentProductionId)
          .then(res => {
            if (res.success) this.rightBottomChart3Data = res.result
            this.initRightBottomChart3()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      initLeftChart1() {
        this.leftChart1 = this.$echarts.init(document.getElementById('left-chart-1'))
        const { alarmCount, closeCount, runCount, waitCount } = this.leftChart1Data
        const dataList = [
          {
            'value': closeCount,
            'name': '关机'
          },
          {
            'value': waitCount,
            'name': '待机'
          },
          {
            'value': runCount,
            'name': '运行'
          },
          {
            'value': alarmCount,
            'name': '报警'
          }
        ]
        const option = {
          tooltip: {
            show: true
          },
          title: {
            text: `{a|${dataList.reduce((total, item) => total + +item.value, 0)}}`,
            x: 'center',
            y: '50%',
            textStyle: {
              rich: {
                a: {
                  fontSize: 30,
                  color: '#eee'
                }
              }
            }
          },
          legend: {
            top: 10,
            left: 'center',
            itemGap: 15,
            textStyle: {
              color: '#eee',
              fontSize: 14,
              fontFamily: 'LanTing',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['关机', '待机', '运行', '报警']
          },
          grid: {
            containLabel: true
          },
          series: [
            {
              type: 'pie',
              radius: ['30%', '55%'],
              center: ['50%', '55%'],
              color: [
                '#238DF5',
                '#6FDB6F',
                '#10ABAE',
                '#C7A46C'
              ],
              label: {
                position: 'outside',
                show: true,
                color: 'inherit',
                fontSize: 16,
                fontWeight: 'bold',
                formatter: function(params) {
                  return params.value
                }
              },
              labelLine: {
                show: true
              },
              data: dataList
            }
          ]
        }
        this.$nextTick(() => this.leftChart1.setOption(option, true))
      },
      initLeftChart2() {
        this.leftChart2 = this.$echarts.init(document.getElementById('left-chart-2'))
        const option = {
          tooltip: {
            show: true
          },
          title: {
            text: '',
            x: 'center',
            y: '50%',
            textStyle: {
              rich: {
                a: {
                  fontSize: 30,
                  color: '#eee'
                }
              }
            }
          },
          legend: {
            top: 10,
            left: 'center',
            itemGap: 15,
            textStyle: {
              color: '#eee',
              fontSize: 14,
              fontFamily: 'LanTing',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['正常', 'ç»´ä¿®', '点检', '保养']
          },
          grid: {
            containLabel: true
          },
          series: [
            {
              type: 'pie',
              radius: ['30%', '55%'],
              center: ['50%', '55%'],
              color: ['#238DF5', '#6FDB6F', '#10ABAE', '#C7A46C'],
              label: {
                position: 'outside',
                show: true,
                color: 'inherit',
                fontWeight: 'bold',
                fontSize: 16,
                formatter: function(params) {
                  return params.value
                }
              },
              labelLine: {
                show: true
              },
              data: []
            }
          ]
        }
        option.series[0].data = this.leftChart2Data
        option.title.text = `{a|${this.leftChart2Data.reduce((total, item) => total + +item.value, 0)}}`
        this.$nextTick(() => this.leftChart2.setOption(option, true))
      },
      initRightTopChart() {
        this.rightTopChart = this.$echarts.init(document.getElementById('right-top-chart'))
        const { dataList, dateList } = this.rightTopChartData
        const newData = {
          xAxis: dateList,
          yAxis: [
            {
              name: 'OEE',
              value: dataList.map(item => item.oee)
            },
            {
              name: '利用率',
              value: dataList.map(item => item.utilizationRate)
            },
            {
              name: '开机率',
              value: dataList.map(item => item.openRate)
            },
            {
              name: '开动率',
              value: dataList.map(item => item.startRate)
            }
          ]
        }
        let legendData = []
        let seriesData = []
        let colorArr = ['#4D9BEF', '#FFA800', '#00FF18', '#C06FFF']
        legendData = newData.yAxis.map((item) => item.name)
        seriesData = newData.yAxis.map((item1, index1) => {
          return {
            name: item1.name,
            type: 'line',
            symbol: 'circle',
            symbolSize: 8,
            itemStyle: {
              color: colorArr[index1]
            },
            yAxisIndex: 1,
            data: item1.value // æŠ˜çº¿å›¾çš„æ•°æ®
          }
        })
        const option = {
          grid: {
            containLabel: true,
            bottom: '3%',
            top: '25%',
            left: '5%',
            right: '5%'
          },
          tooltip: {
            trigger: 'axis'
          },
          legend: {
            top: 70,
            right: '5%',
            data: legendData,
            itemGap: 30,
            textStyle: {
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            }
          },
          xAxis: {
            triggerEvent: true,
            data: newData.xAxis || [],
            axisLabel: {
              interval: 0,
              show: true,
              fontSize: 14,
              color: '#eee',
              margin: 14,
              fontFamily: 'LanTing'
            },
            axisLine: {
              show: true,
              lineStyle: {
                color: '#eee'
              }
            },
            axisTick: {
              show: true
            },
            splitLine: {
              show: true
            }
          },
          yAxis: [
            {
              type: 'value',
              position: 'left',
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              splitLine: {
                show: false
              }
            },
            {
              type: 'value',
              position: 'left',
              axisLabel: {
                show: true,
                color: '#eee',
                margin: 14,
                fontSize: 14,
                fontWeight: 'bold',
                formatter(value) {
                  return value + '%'
                }
              },
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              }
            }
          ],
          series: seriesData
        }
        this.rightTopChart.setOption(option, true)
      },
      initRightBottomChart1() {
        this.rightBottomChart1 = this.$echarts.init(document.getElementById('right-bottom-chart-1'))
        const option = {
          tooltip: {
            trigger: 'axis'
          },
          grid: {
            bottom: '5%',
            top: '30%',
            left: '10%',
            right: '10%',
            containLabel: true
          },
          legend: {
            top: 80,
            right: '10%',
            itemGap: 15,
            textStyle: {
              fontSize: 14,
              fontFamily: 'LanTing',
              color: '#eee',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['报修数', '完成数']
          },
          xAxis: {
            type: 'category',
            data: [],
            axisLine: {
              lineStyle: {
                color: '#eee'
              }
            },
            axisLabel: {
              interval: 0,
              margin: 14,
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              rotate: 45
            },
            axisTick: {
              show: true
            }
          },
          yAxis: [
            {
              type: 'value',
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              },
              axisLabel: {
                fontSize: 14,
                color: '#eee',
                fontWeight: 'bold',
                margin: 14
              }
            }
          ],
          series: [
            {
              type: 'bar',
              barWidth: 12,
              name: '报修数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#295485'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#2F95F9'
                    }
                  ]
                )
              }
            },
            {
              type: 'bar',
              barWidth: 12,
              name: '完成数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#35535E'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#92F7AD'
                    }
                  ]
                )
              }
            }
          ]
        }
        option.xAxis.data = this.rightBottomChart1Data.map(item => item.monthStr)
        option.series[0].data = this.rightBottomChart1Data.map(item => {
          return {
            name: item.monthStr,
            value: item.reportNumber
          }
        })
        option.series[1].data = this.rightBottomChart1Data.map(item => {
          return {
            name: item.monthStr,
            value: item.repairedNumber
          }
        })
        this.$nextTick(() => this.rightBottomChart1.setOption(option, true))
      },
      initRightBottomChart2() {
        this.rightBottomChart2 = this.$echarts.init(document.getElementById('right-bottom-chart-2'))
        const option = {
          tooltip: {
            trigger: 'axis'
          },
          grid: {
            bottom: '5%',
            top: '30%',
            left: '10%',
            right: '10%',
            containLabel: true
          },
          legend: {
            top: 80,
            right: '10%',
            itemGap: 15,
            textStyle: {
              fontSize: 14,
              fontFamily: 'LanTing',
              color: '#eee',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['点检计划数', '点检完成数']
          },
          xAxis: {
            type: 'category',
            data: [],
            axisLine: {
              lineStyle: {
                color: '#eee'
              }
            },
            axisLabel: {
              margin: 14,
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              interval: 0,
              rotate: 45
            },
            axisTick: {
              show: true
            }
          },
          yAxis: [
            {
              type: 'value',
              minInterval: 1,
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              },
              axisLabel: {
                fontSize: 14,
                color: '#eee',
                fontWeight: 'bold',
                margin: 14
              }
            }
          ],
          series: [
            {
              type: 'bar',
              barWidth: 12,
              name: '点检计划数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#295485'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#2F95F9'
                    }
                  ]
                )
              }
            },
            {
              type: 'bar',
              barWidth: 12,
              name: '点检完成数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#35535E'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#92F7AD'
                    }
                  ]
                )
              }
            }
          ]
        }
        option.xAxis.data = this.rightBottomChart2Data.map(item => item.monthStr)
        option.series[0].data = this.rightBottomChart2Data.map(item => {
          return {
            name: item.monthStr,
            value: item.planNumber
          }
        })
        option.series[1].data = this.rightBottomChart2Data.map(item => {
          return {
            name: item.monthStr,
            value: item.completeNumber
          }
        })
        this.$nextTick(() => this.rightBottomChart2.setOption(option, true))
      },
      initRightBottomChart3() {
        this.rightBottomChart3 = this.$echarts.init(document.getElementById('right-bottom-chart-3'))
        const option = {
          tooltip: {
            trigger: 'axis'
          },
          grid: {
            bottom: '5%',
            top: '30%',
            left: '10%',
            right: '10%',
            containLabel: true
          },
          legend: {
            top: 80,
            right: '10%',
            itemGap: 15,
            textStyle: {
              fontSize: 14,
              fontFamily: 'LanTing',
              color: '#eee',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['保养计划数', '保养完成数']
          },
          xAxis: {
            type: 'category',
            data: [],
            axisLine: {
              lineStyle: {
                color: '#eee'
              }
            },
            axisLabel: {
              margin: 14,
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              interval: 0,
              rotate: 45
            },
            axisTick: {
              show: true
            }
          },
          yAxis: [
            {
              type: 'value',
              minInterval: 1,
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              },
              axisLabel: {
                fontSize: 14,
                color: '#eee',
                fontWeight: 'bold',
                margin: 14
              }
            }
          ],
          series: [
            {
              type: 'bar',
              barWidth: 12,
              name: '保养计划数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#295485'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#2F95F9'
                    }
                  ]
                )
              }
            },
            {
              type: 'bar',
              barWidth: 12,
              name: '保养完成数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#35535E'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#92F7AD'
                    }
                  ]
                )
              }
            }
          ]
        }
        option.xAxis.data = this.rightBottomChart3Data.map(item => item.monthStr)
        option.series[0].data = this.rightBottomChart3Data.map(item => {
          return {
            name: item.monthStr,
            value: item.planNumber
          }
        })
        option.series[1].data = this.rightBottomChart3Data.map(item => {
          return {
            name: item.monthStr,
            value: item.completeNumber
          }
        })
        this.$nextTick(() => this.rightBottomChart3.setOption(option, true))
      },
      filterOption(input, option) {
        return (
          option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
        )
      },
      /**
       * è¾“入框选择改变后触发
       * @param equipmentId è®¾å¤‡ç¼–号
       */
      handleSelectChange(equipmentId) {
        // this.equipmentId = value
        console.log('equipment', equipmentId)
        this.$emit('nextSignage', { id: equipmentId })
      },
      handleWindowResize() {
        if (this.leftChart1) this.leftChart1.resize()
        if (this.leftChart2) this.leftChart2.resize()
        if (this.rightTopChart) this.rightTopChart.resize()
        if (this.rightBottomChart1) this.rightBottomChart1.resize()
        if (this.rightBottomChart2) this.rightBottomChart2.resize()
        if (this.rightBottomChart3) this.rightBottomChart3.resize()
      }
    }
  }
</script>
<style scoped lang="less">
  .component-container {
    display: flex;
    height: 100%;
    justify-content: space-between;
    .left-container {
      width: 18%;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      /*图表区域*/
      > div:not(div:last-child) {
        height: 40%;
        .title-container {
          position: relative;
          width: 100%;
          height: 3.6vw;
          display: flex;
          img {
            height: 100%;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 0;
          }
          span {
            position: relative;
            z-index: 1;
            font-size: 1.2vw;
            font-family: 'ZongYi';
            margin: auto;
            letter-spacing: 0.25vw;
          }
        }
        .left-chart-container {
          height: calc(100% - 3.6vw);
        }
      }
      /*导航区域*/
      > div:last-child {
        flex: 1;
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        .title-container {
          position: relative;
          width: 100%;
          height: 3.6vw;
          display: flex;
          img {
            height: 100%;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 0;
          }
          span {
            position: relative;
            z-index: 1;
            font-size: 1.3vw;
            font-family: 'ZongYi';
            margin: auto;
            letter-spacing: 0.25vw;
          }
        }
        .equipment-search-container {
          height: calc(100% - 3.6vw);
          display: flex;
          justify-content: center;
          align-items: center;
          position: relative;
          img {
            height: 2.24vw;
          }
          /deep/ .ant-select-selection {
            background: transparent !important;
          }
          /deep/ .ant-select-selection__clear {
            background: transparent !important;
            color: #fff;
          }
          /deep/ .ant-select {
            color: #fff;
          }
          /deep/ .ant-input {
            height: 2.24vw;
            border: none;
            color: #fff;
            font-size: 0.8vw;
            background: transparent !important;
          }
        }
      }
    }
  }
</style>
src/views/mdc/base/modules/GradeSignage/WorkshopSignage.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1079 @@
<template>
  <div class="component-container">
    <slot name="loading"/>
    <div class="left-container">
      <div class="left-single-container">
        <div class="title-container">
          <img src="@/assets/signage/title.png"/>
          <span>设备状态</span>
        </div>
        <div class="left-chart-container" id="left-chart-1"></div>
      </div>
      <div class="left-single-container">
        <div class="title-container">
          <img src="@/assets/signage/title.png"/>
          <span>维保状态</span>
        </div>
        <div class="left-chart-container" id="left-chart-2"></div>
      </div>
      <div
        :style="{justifyContent:workshopList.length<=3?'center':'space-between'}">
        <div v-for="(item,index) in workshopList" class="navigator-container" @mouseenter="activeIndex=index"
             @mouseleave="activeIndex=null" @click="$emit('nextSignage', item)">
          <template v-if="workshopList.length<=3">
            <img v-if="activeIndex!==index" src="@/assets/signage/workshop/navigator-long.png" style="height: 3.38vw"/>
            <img v-else src="@/assets/signage/workshop/navigator-long-active.png" style="height: 3.38vw"/>
            <span style="font-size: 1.2vw;letter-spacing: 0.25vw;padding-left: 0.25vw">{{item.productionName}}</span>
          </template>
          <template v-else>
            <img v-if="activeIndex!==index" src="@/assets/signage/workshop/navigator-middle.png" style="height: 3.1vw"/>
            <img v-else src="@/assets/signage/workshop/navigator-middle-active.png" style="height: 3.1vw"/>
            <span style="font-size: 0.8vw;letter-spacing:0.1vw;padding-left: 0.1vw">{{item.productionName }}</span>
          </template>
        </div>
      </div>
    </div>
    <div class="right-container">
      <div>
        <img src="@/assets/signage/company/rate-analysis-container.png"/>
        <div class="right-chart-container" id="right-top-chart"></div>
      </div>
      <div>
        <div>
          <img src="@/assets/signage/company/repair-analysis.png"/>
          <div class="right-chart-container" id="right-bottom-chart-1"></div>
        </div>
        <div>
          <img src="@/assets/signage/company/inspection-analysis.png"/>
          <div class="right-chart-container" id="right-bottom-chart-2"></div>
        </div>
        <div>
          <img src="@/assets/signage/company/maintenance-analysis.png"/>
          <div class="right-chart-container" id="right-bottom-chart-3"></div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  import signageApi from '@/api/signage'
  export default {
    name: 'WorkshopSignage',
    props: {
      currentProductionId: {
        type: String
      }
    },
    data() {
      return {
        leftChart1: null,
        leftChart2: null,
        rightTopChart: null,
        rightBottomChart1: null,
        rightBottomChart2: null,
        rightBottomChart3: null,
        leftChart1Data: [],
        leftChart2Data: [],
        rightTopChartData: [],
        rightBottomChart1Data: [],
        rightBottomChart2Data: [],
        rightBottomChart3Data: [],
        chartQuantity: 6,
        hasLoadedChartDataQuantity: 0,
        workshopList: [],
        activeIndex: null
      }
    },
    watch: {
      hasLoadedChartDataQuantity: {
        handler(val) {
          if (val === this.chartQuantity) this.$emit('loadFinished')
        }
      }
    },
    mounted() {
      this.getWorkshopListByApi()
      this.handleWindowResize()
      window.addEventListener('resize', this.handleWindowResize)
    },
    beforeDestroy() {
      window.removeEventListener('resize', this.handleWatchHistory)
    },
    methods: {
      getWorkshopListByApi() {
        signageApi.getWorkshopListByProductionIdApi(this.currentProductionId)
          .then(res => {
            if (res.success) {
              this.getLeftChartContainerHeight(res.result ? res.result : [])
              this.getChartDataByApi()
            }
          })
      },
      getLeftChartContainerHeight(workshopList) {
        const outerHeight = workshopList.length <= 3 ? `calc((100% - 3.38vw * ${workshopList.length}) / 2)` : `calc((100% - 3.1vw * ${Math.round(workshopList.length / 2)}) / 2)`
        document.querySelectorAll('.left-single-container').forEach(item => item.style.height = outerHeight)
        this.workshopList = workshopList
      },
      getChartDataByApi() {
        this.getLeftChart1DataByApi()
        this.getLeftChart2DataByApi()
        this.geRightTopChartDataByApi()
        this.geRightBottomChartData1ByApi()
        this.geRightBottomChartData2ByApi()
        this.geRightBottomChartData3ByApi()
      },
      getLeftChart1DataByApi() {
        const that = this
        signageApi.getEquipmentStatusAnalysisApi(this.currentProductionId)
          .then(res => {
            if (res.success) {
              this.leftChart1Data = res.result.equipmentStatus
            }
            this.initLeftChart1()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      getLeftChart2DataByApi() {
        const that = this
        signageApi.getRepairAndMaintenanceStatusApi(this.currentProductionId)
          .then(res => {
            if (res.success) {
              this.leftChart2Data = res.result.map(item => {
                return {
                  name: item.statusText,
                  value: item.totalNumber
                }
              })
            }
            this.initLeftChart2()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      geRightTopChartDataByApi() {
        const that = this
        console.log('this.currentProductionId', this.currentProductionId)
        signageApi.getRateAnalysisTrendApi(this.currentProductionId)
          .then(res => {
            console.log('res', res)
            if (res.success) this.rightTopChartData = res.result
            this.initRightTopChart()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      geRightBottomChartData1ByApi() {
        const that = this
        signageApi.getRepairAnalysisApi(this.currentProductionId)
          .then(res => {
            if (res.success) this.rightBottomChart1Data = res.result
            this.initRightBottomChart1()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      geRightBottomChartData2ByApi() {
        const that = this
        signageApi.getInspectionAnalysisApi(this.currentProductionId)
          .then(res => {
            if (res.success) this.rightBottomChart2Data = res.result
            this.initRightBottomChart2()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      geRightBottomChartData3ByApi() {
        const that = this
        signageApi.getMaintenanceAnalysisApi(this.currentProductionId)
          .then(res => {
            if (res.success) this.rightBottomChart3Data = res.result
            this.initRightBottomChart3()
          })
          .finally(() => {
            that.hasLoadedChartDataQuantity++
          })
      },
      initLeftChart1() {
        this.leftChart1 = this.$echarts.init(document.getElementById('left-chart-1'))
        const { alarmCount, closeCount, runCount, waitCount } = this.leftChart1Data
        const dataList = [
          {
            'value': closeCount,
            'name': '关机'
          },
          {
            'value': waitCount,
            'name': '待机'
          },
          {
            'value': runCount,
            'name': '运行'
          },
          {
            'value': alarmCount,
            'name': '报警'
          }
        ]
        const option = {
          tooltip: {
            show: true
          },
          title: {
            text: `{a|${dataList.reduce((total, item) => total + +item.value, 0)}}`,
            x: 'center',
            y: '50%',
            textStyle: {
              rich: {
                a: {
                  fontSize: 30,
                  color: '#eee'
                }
              }
            }
          },
          legend: {
            top: 10,
            left: 'center',
            itemGap: 15,
            textStyle: {
              color: '#eee',
              fontSize: 14,
              fontFamily: 'LanTing',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['关机', '待机', '运行', '报警']
          },
          grid: {
            containLabel: true
          },
          series: [
            {
              type: 'pie',
              radius: ['30%', '55%'],
              center: ['50%', '55%'],
              color: [
                '#238DF5',
                '#6FDB6F',
                '#10ABAE',
                '#C7A46C'
              ],
              label: {
                position: 'outside',
                show: true,
                color: 'inherit',
                fontSize: 16,
                fontWeight: 'bold',
                formatter: function(params) {
                  return params.value
                }
              },
              labelLine: {
                show: true
              },
              data: dataList
            }
          ]
        }
        this.$nextTick(() => this.leftChart1.setOption(option, true))
      },
      initLeftChart2() {
        this.leftChart2 = this.$echarts.init(document.getElementById('left-chart-2'))
        const option = {
          tooltip: {
            show: true
          },
          title: {
            text: '',
            x: 'center',
            y: '50%',
            textStyle: {
              rich: {
                a: {
                  fontSize: 30,
                  color: '#eee'
                }
              }
            }
          },
          legend: {
            top: 10,
            left: 'center',
            itemGap: 15,
            textStyle: {
              color: '#eee',
              fontSize: 14,
              fontFamily: 'LanTing',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['正常', 'ç»´ä¿®', '点检', '保养']
          },
          grid: {
            containLabel: true
          },
          series: [
            {
              type: 'pie',
              radius: ['30%', '55%'],
              center: ['50%', '55%'],
              color: ['#238DF5', '#6FDB6F', '#10ABAE', '#C7A46C'],
              label: {
                position: 'outside',
                show: true,
                color: 'inherit',
                fontWeight: 'bold',
                fontSize: 16,
                formatter: function(params) {
                  return params.value
                }
              },
              labelLine: {
                show: true
              },
              data: []
            }
          ]
        }
        option.series[0].data = this.leftChart2Data
        option.title.text = `{a|${this.leftChart2Data.reduce((total, item) => total + +item.value, 0)}}`
        this.$nextTick(() => this.leftChart2.setOption(option, true))
      },
      initRightTopChart() {
        this.rightTopChart = this.$echarts.init(document.getElementById('right-top-chart'))
        const { dataList, dateList } = this.rightTopChartData
        const newData = {
          xAxis: dateList,
          yAxis: [
            {
              name: 'OEE',
              value: dataList.map(item => item.oee)
            },
            {
              name: '利用率',
              value: dataList.map(item => item.utilizationRate)
            },
            {
              name: '开机率',
              value: dataList.map(item => item.openRate)
            },
            {
              name: '开动率',
              value: dataList.map(item => item.startRate)
            }
          ]
        }
        let legendData = []
        let seriesData = []
        let colorArr = ['#4D9BEF', '#FFA800', '#00FF18', '#C06FFF']
        legendData = newData.yAxis.map((item) => item.name)
        seriesData = newData.yAxis.map((item1, index1) => {
          return {
            name: item1.name,
            type: 'line',
            symbol: 'circle',
            symbolSize: 8,
            itemStyle: {
              color: colorArr[index1]
            },
            yAxisIndex: 1,
            data: item1.value // æŠ˜çº¿å›¾çš„æ•°æ®
          }
        })
        const option = {
          grid: {
            containLabel: true,
            bottom: '3%',
            top: '25%',
            left: '5%',
            right: '5%'
          },
          tooltip: {
            trigger: 'axis'
          },
          legend: {
            top: 70,
            right: '5%',
            data: legendData,
            itemGap: 30,
            textStyle: {
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            }
          },
          xAxis: {
            triggerEvent: true,
            data: newData.xAxis || [],
            axisLabel: {
              interval: 0,
              show: true,
              fontSize: 14,
              color: '#eee',
              margin: 14,
              fontFamily: 'LanTing'
            },
            axisLine: {
              show: true,
              lineStyle: {
                color: '#eee'
              }
            },
            axisTick: {
              show: true
            },
            splitLine: {
              show: true
            }
          },
          yAxis: [
            {
              type: 'value',
              position: 'left',
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              splitLine: {
                show: false
              }
            },
            {
              type: 'value',
              position: 'left',
              axisLabel: {
                show: true,
                color: '#eee',
                margin: 14,
                fontSize: 14,
                fontWeight: 'bold',
                formatter(value) {
                  return value + '%'
                }
              },
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              }
            }
          ],
          series: seriesData
        }
        this.rightTopChart.setOption(option, true)
      },
      initRightBottomChart1() {
        this.rightBottomChart1 = this.$echarts.init(document.getElementById('right-bottom-chart-1'))
        const option = {
          tooltip: {
            trigger: 'axis'
          },
          grid: {
            bottom: '5%',
            top: '30%',
            left: '10%',
            right: '10%',
            containLabel: true
          },
          legend: {
            top: 80,
            right: '10%',
            itemGap: 15,
            textStyle: {
              fontSize: 14,
              fontFamily: 'LanTing',
              color: '#eee',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['报修数', '完成数']
          },
          xAxis: {
            type: 'category',
            data: [],
            axisLine: {
              lineStyle: {
                color: '#eee'
              }
            },
            axisLabel: {
              interval: 0,
              margin: 14,
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              rotate: 45
            },
            axisTick: {
              show: true
            }
          },
          yAxis: [
            {
              type: 'value',
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              },
              axisLabel: {
                fontSize: 14,
                color: '#eee',
                fontWeight: 'bold',
                margin: 14
              }
            }
          ],
          series: [
            {
              type: 'bar',
              barWidth: 12,
              name: '报修数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#295485'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#2F95F9'
                    }
                  ]
                )
              }
            },
            {
              type: 'bar',
              barWidth: 12,
              name: '完成数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#35535E'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#92F7AD'
                    }
                  ]
                )
              }
            }
          ]
        }
        option.xAxis.data = this.rightBottomChart1Data.map(item => item.monthStr)
        option.series[0].data = this.rightBottomChart1Data.map(item => {
          return {
            name: item.monthStr,
            value: item.reportNumber
          }
        })
        option.series[1].data = this.rightBottomChart1Data.map(item => {
          return {
            name: item.monthStr,
            value: item.repairedNumber
          }
        })
        this.$nextTick(() => this.rightBottomChart1.setOption(option, true))
      },
      initRightBottomChart2() {
        this.rightBottomChart2 = this.$echarts.init(document.getElementById('right-bottom-chart-2'))
        const option = {
          tooltip: {
            trigger: 'axis'
          },
          grid: {
            bottom: '5%',
            top: '30%',
            left: '10%',
            right: '10%',
            containLabel: true
          },
          legend: {
            top: 80,
            right: '10%',
            itemGap: 15,
            textStyle: {
              fontSize: 14,
              fontFamily: 'LanTing',
              color: '#eee',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['点检计划数', '点检完成数']
          },
          xAxis: {
            type: 'category',
            data: [],
            axisLine: {
              lineStyle: {
                color: '#eee'
              }
            },
            axisLabel: {
              margin: 14,
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              interval: 0,
              rotate: 45
            },
            axisTick: {
              show: true
            }
          },
          yAxis: [
            {
              type: 'value',
              minInterval: 1,
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              },
              axisLabel: {
                fontSize: 14,
                color: '#eee',
                fontWeight: 'bold',
                margin: 14
              }
            }
          ],
          series: [
            {
              type: 'bar',
              barWidth: 12,
              name: '点检计划数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#295485'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#2F95F9'
                    }
                  ]
                )
              }
            },
            {
              type: 'bar',
              barWidth: 12,
              name: '点检完成数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#35535E'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#92F7AD'
                    }
                  ]
                )
              }
            }
          ]
        }
        option.xAxis.data = this.rightBottomChart2Data.map(item => item.monthStr)
        option.series[0].data = this.rightBottomChart2Data.map(item => {
          return {
            name: item.monthStr,
            value: item.planNumber
          }
        })
        option.series[1].data = this.rightBottomChart2Data.map(item => {
          return {
            name: item.monthStr,
            value: item.completeNumber
          }
        })
        this.$nextTick(() => this.rightBottomChart2.setOption(option, true))
      },
      initRightBottomChart3() {
        this.rightBottomChart3 = this.$echarts.init(document.getElementById('right-bottom-chart-3'))
        const option = {
          tooltip: {
            trigger: 'axis'
          },
          grid: {
            bottom: '5%',
            top: '30%',
            left: '10%',
            right: '10%',
            containLabel: true
          },
          legend: {
            top: 80,
            right: '10%',
            itemGap: 15,
            textStyle: {
              fontSize: 14,
              fontFamily: 'LanTing',
              color: '#eee',
              height: 10,
              rich: {
                a: {
                  verticalAlign: 'bottom'
                }
              }
            },
            data: ['保养计划数', '保养完成数']
          },
          xAxis: {
            type: 'category',
            data: [],
            axisLine: {
              lineStyle: {
                color: '#eee'
              }
            },
            axisLabel: {
              margin: 14,
              fontSize: 14,
              color: '#eee',
              fontFamily: 'LanTing',
              interval: 0,
              rotate: 45
            },
            axisTick: {
              show: true
            }
          },
          yAxis: [
            {
              type: 'value',
              minInterval: 1,
              axisLine: {
                show: true,
                lineStyle: {
                  color: '#eee'
                }
              },
              axisTick: {
                show: true
              },
              splitLine: {
                show: false
              },
              axisLabel: {
                fontSize: 14,
                color: '#eee',
                fontWeight: 'bold',
                margin: 14
              }
            }
          ],
          series: [
            {
              type: 'bar',
              barWidth: 12,
              name: '保养计划数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#295485'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#2F95F9'
                    }
                  ]
                )
              }
            },
            {
              type: 'bar',
              barWidth: 12,
              name: '保养完成数',
              data: [],
              label: {
                show: false,
                lineHeight: 10,
                formatter: params => {
                  if (+params.value === 0) return ''
                  else return params.value
                },
                position: 'inside',
                textStyle: {
                  color: '#eee',
                  fontSize: 12
                }
              },
              itemStyle: {
                color: new this.$echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {//只要修改前四个参数就ok
                      offset: 0,
                      color: '#35535E'
                    }, //柱图渐变色
                    {
                      offset: 1,
                      color: '#92F7AD'
                    }
                  ]
                )
              }
            }
          ]
        }
        option.xAxis.data = this.rightBottomChart3Data.map(item => item.monthStr)
        option.series[0].data = this.rightBottomChart3Data.map(item => {
          return {
            name: item.monthStr,
            value: item.planNumber
          }
        })
        option.series[1].data = this.rightBottomChart3Data.map(item => {
          return {
            name: item.monthStr,
            value: item.completeNumber
          }
        })
        this.$nextTick(() => this.rightBottomChart3.setOption(option, true))
      },
      handleWindowResize() {
        if (this.leftChart1) this.leftChart1.resize()
        if (this.leftChart2) this.leftChart2.resize()
        if (this.rightTopChart) this.rightTopChart.resize()
        if (this.rightBottomChart1) this.rightBottomChart1.resize()
        if (this.rightBottomChart2) this.rightBottomChart2.resize()
        if (this.rightBottomChart3) this.rightBottomChart3.resize()
      }
    }
  }
</script>
<style scoped lang="less">
  .component-container {
    display: flex;
    height: 100%;
    justify-content: space-between;
    .left-container {
      width: 18%;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      /*图表区域*/
      > div:not(div:last-child) {
        .title-container {
          position: relative;
          width: 100%;
          height: 3.6vw;
          display: flex;
          img {
            height: 100%;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 0;
          }
          span {
            position: relative;
            z-index: 1;
            font-size: 1.2vw;
            font-family: 'ZongYi';
            margin: auto;
            letter-spacing: 0.25vw;
          }
        }
        .left-chart-container {
          height: calc(100% - 3.6vw);
        }
      }
      /*导航区域*/
      > div:last-child {
        display: flex;
        justify-content: space-between;
        align-items: center;
        flex-wrap: wrap;
        .navigator-container {
          position: relative;
          /*width: 100%;*/
          cursor: pointer;
          text-align: center;
          img {
            height: 3.38vw;
          }
          span {
            width: 100%;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            font-family: 'ZongYi';
          }
        }
      }
    }
  }
</style>