From cd3313781f48c15a8fa0f0b46e2fdcde02969e87 Mon Sep 17 00:00:00 2001 From: zhaowei <zhaowei> Date: 星期一, 12 五月 2025 14:55:52 +0800 Subject: [PATCH] 车间布局管理页面新增分级看板以及维修看板页面 --- src/assets/signage/equipment/product-qualified-rate.png | 0 src/assets/signage/equipment/status-container.png | 0 src/views/mdc/base/WorkshopSignageEntrance.vue | 27 src/assets/signage/repair/table-container.png | 0 src/assets/signage/equipment/month-rate-analysis.png | 0 src/views/mdc/base/modules/GradeSignage/WorkshopSignage.vue | 1079 +++++++++++ src/assets/signage/company/navigator-active.png | 0 src/assets/signage/company/inspection-analysis.png | 0 src/assets/signage/workshop/navigator-long-active.png | 0 src/assets/signage/back.png | 0 src/assets/signage/background-line.png | 0 src/assets/signage/equipment/equipment-info-line.png | 0 src/config/router.config.js | 14 src/assets/signage/font/方正兰亭特黑简体.ttf | 0 src/assets/signage/company/maintenance-analysis.png | 0 src/assets/signage/workshop/navigator-middle-active.png | 0 src/assets/signage/repair/average-fault-rate.png | 0 src/assets/signage/equipment/day-rate-analysis.png | 0 src/views/mdc/base/modules/GradeSignage/SectionSignage.vue | 1350 +++++++++++++ src/assets/signage/logo.png | 0 src/assets/signage/equipment/left-top-container.png | 0 src/assets/signage/background.png | 0 src/assets/signage/font/百度综艺简体.ttf | 0 src/assets/signage/repair/repair-analysis.png | 0 src/assets/signage/company/rate-analysis-container.png | 0 src/views/mdc/base/modules/GradeSignage/EquipmentSignage.vue | 1042 ++++++++++ src/assets/signage/title.png | 0 src/assets/signage/repair/fault-type-analysis.png | 0 src/assets/signage/equipment/left-bottom-container.png | 0 src/views/mdc/base/GradeWorkshopSignage.vue | 293 ++ src/views/mdc/base/modules/GradeSignage/CompanySignage.vue | 1059 ++++++++++ src/assets/signage/company/navigator.png | 0 src/assets/signage/workshop/navigator-middle.png | 0 src/assets/signage/repair/repaired-rank.png | 0 src/assets/signage/company/repair-analysis.png | 0 src/assets/signage/section/search-input.png | 0 src/views/mdc/base/RepairWorkshopSignage.vue | 919 +++++++++ src/api/signage.js | 47 src/assets/signage/equipment/equipmentId-container.png | 0 src/assets/signage/repair/top-left-container.png | 0 src/assets/signage/workshop/navigator-long.png | 0 41 files changed, 5,825 insertions(+), 5 deletions(-) diff --git a/src/api/signage.js b/src/api/signage.js new file mode 100644 index 0000000..f26ec97 --- /dev/null +++ b/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') +} \ No newline at end of file diff --git a/src/assets/signage/back.png b/src/assets/signage/back.png new file mode 100644 index 0000000..b822b2e --- /dev/null +++ b/src/assets/signage/back.png Binary files differ diff --git a/src/assets/signage/background-line.png b/src/assets/signage/background-line.png new file mode 100644 index 0000000..9609378 --- /dev/null +++ b/src/assets/signage/background-line.png Binary files differ diff --git a/src/assets/signage/background.png b/src/assets/signage/background.png new file mode 100644 index 0000000..748832e --- /dev/null +++ b/src/assets/signage/background.png Binary files differ diff --git a/src/assets/signage/company/inspection-analysis.png b/src/assets/signage/company/inspection-analysis.png new file mode 100644 index 0000000..4b19d90 --- /dev/null +++ b/src/assets/signage/company/inspection-analysis.png Binary files differ diff --git a/src/assets/signage/company/maintenance-analysis.png b/src/assets/signage/company/maintenance-analysis.png new file mode 100644 index 0000000..386834c --- /dev/null +++ b/src/assets/signage/company/maintenance-analysis.png Binary files differ diff --git a/src/assets/signage/company/navigator-active.png b/src/assets/signage/company/navigator-active.png new file mode 100644 index 0000000..880eea6 --- /dev/null +++ b/src/assets/signage/company/navigator-active.png Binary files differ diff --git a/src/assets/signage/company/navigator.png b/src/assets/signage/company/navigator.png new file mode 100644 index 0000000..97a7a50 --- /dev/null +++ b/src/assets/signage/company/navigator.png Binary files differ diff --git a/src/assets/signage/company/rate-analysis-container.png b/src/assets/signage/company/rate-analysis-container.png new file mode 100644 index 0000000..81ac24d --- /dev/null +++ b/src/assets/signage/company/rate-analysis-container.png Binary files differ diff --git a/src/assets/signage/company/repair-analysis.png b/src/assets/signage/company/repair-analysis.png new file mode 100644 index 0000000..703c6fe --- /dev/null +++ b/src/assets/signage/company/repair-analysis.png Binary files differ diff --git a/src/assets/signage/equipment/day-rate-analysis.png b/src/assets/signage/equipment/day-rate-analysis.png new file mode 100644 index 0000000..85da518 --- /dev/null +++ b/src/assets/signage/equipment/day-rate-analysis.png Binary files differ diff --git a/src/assets/signage/equipment/equipment-info-line.png b/src/assets/signage/equipment/equipment-info-line.png new file mode 100644 index 0000000..ca391c5 --- /dev/null +++ b/src/assets/signage/equipment/equipment-info-line.png Binary files differ diff --git a/src/assets/signage/equipment/equipmentId-container.png b/src/assets/signage/equipment/equipmentId-container.png new file mode 100644 index 0000000..8531daa --- /dev/null +++ b/src/assets/signage/equipment/equipmentId-container.png Binary files differ diff --git a/src/assets/signage/equipment/left-bottom-container.png b/src/assets/signage/equipment/left-bottom-container.png new file mode 100644 index 0000000..d8ecef4 --- /dev/null +++ b/src/assets/signage/equipment/left-bottom-container.png Binary files differ diff --git a/src/assets/signage/equipment/left-top-container.png b/src/assets/signage/equipment/left-top-container.png new file mode 100644 index 0000000..e13a580 --- /dev/null +++ b/src/assets/signage/equipment/left-top-container.png Binary files differ diff --git a/src/assets/signage/equipment/month-rate-analysis.png b/src/assets/signage/equipment/month-rate-analysis.png new file mode 100644 index 0000000..0e1b752 --- /dev/null +++ b/src/assets/signage/equipment/month-rate-analysis.png Binary files differ diff --git a/src/assets/signage/equipment/product-qualified-rate.png b/src/assets/signage/equipment/product-qualified-rate.png new file mode 100644 index 0000000..49dc253 --- /dev/null +++ b/src/assets/signage/equipment/product-qualified-rate.png Binary files differ diff --git a/src/assets/signage/equipment/status-container.png b/src/assets/signage/equipment/status-container.png new file mode 100644 index 0000000..8e14c94 --- /dev/null +++ b/src/assets/signage/equipment/status-container.png Binary files differ diff --git "a/src/assets/signage/font/\346\226\271\346\255\243\345\205\260\344\272\255\347\211\271\351\273\221\347\256\200\344\275\223.ttf" "b/src/assets/signage/font/\346\226\271\346\255\243\345\205\260\344\272\255\347\211\271\351\273\221\347\256\200\344\275\223.ttf" new file mode 100644 index 0000000..8d2fb5d --- /dev/null +++ "b/src/assets/signage/font/\346\226\271\346\255\243\345\205\260\344\272\255\347\211\271\351\273\221\347\256\200\344\275\223.ttf" Binary files differ diff --git "a/src/assets/signage/font/\347\231\276\345\272\246\347\273\274\350\211\272\347\256\200\344\275\223.ttf" "b/src/assets/signage/font/\347\231\276\345\272\246\347\273\274\350\211\272\347\256\200\344\275\223.ttf" new file mode 100644 index 0000000..e47ae1f --- /dev/null +++ "b/src/assets/signage/font/\347\231\276\345\272\246\347\273\274\350\211\272\347\256\200\344\275\223.ttf" Binary files differ diff --git a/src/assets/signage/logo.png b/src/assets/signage/logo.png new file mode 100644 index 0000000..cc38bc1 --- /dev/null +++ b/src/assets/signage/logo.png Binary files differ diff --git a/src/assets/signage/repair/average-fault-rate.png b/src/assets/signage/repair/average-fault-rate.png new file mode 100644 index 0000000..6ac2e05 --- /dev/null +++ b/src/assets/signage/repair/average-fault-rate.png Binary files differ diff --git a/src/assets/signage/repair/fault-type-analysis.png b/src/assets/signage/repair/fault-type-analysis.png new file mode 100644 index 0000000..2310069 --- /dev/null +++ b/src/assets/signage/repair/fault-type-analysis.png Binary files differ diff --git a/src/assets/signage/repair/repair-analysis.png b/src/assets/signage/repair/repair-analysis.png new file mode 100644 index 0000000..c331dff --- /dev/null +++ b/src/assets/signage/repair/repair-analysis.png Binary files differ diff --git a/src/assets/signage/repair/repaired-rank.png b/src/assets/signage/repair/repaired-rank.png new file mode 100644 index 0000000..0c688f4 --- /dev/null +++ b/src/assets/signage/repair/repaired-rank.png Binary files differ diff --git a/src/assets/signage/repair/table-container.png b/src/assets/signage/repair/table-container.png new file mode 100644 index 0000000..5b72404 --- /dev/null +++ b/src/assets/signage/repair/table-container.png Binary files differ diff --git a/src/assets/signage/repair/top-left-container.png b/src/assets/signage/repair/top-left-container.png new file mode 100644 index 0000000..6902383 --- /dev/null +++ b/src/assets/signage/repair/top-left-container.png Binary files differ diff --git a/src/assets/signage/section/search-input.png b/src/assets/signage/section/search-input.png new file mode 100644 index 0000000..e9535d8 --- /dev/null +++ b/src/assets/signage/section/search-input.png Binary files differ diff --git a/src/assets/signage/title.png b/src/assets/signage/title.png new file mode 100644 index 0000000..baa6719 --- /dev/null +++ b/src/assets/signage/title.png Binary files differ diff --git a/src/assets/signage/workshop/navigator-long-active.png b/src/assets/signage/workshop/navigator-long-active.png new file mode 100644 index 0000000..e1774ff --- /dev/null +++ b/src/assets/signage/workshop/navigator-long-active.png Binary files differ diff --git a/src/assets/signage/workshop/navigator-long.png b/src/assets/signage/workshop/navigator-long.png new file mode 100644 index 0000000..ff64e14 --- /dev/null +++ b/src/assets/signage/workshop/navigator-long.png Binary files differ diff --git a/src/assets/signage/workshop/navigator-middle-active.png b/src/assets/signage/workshop/navigator-middle-active.png new file mode 100644 index 0000000..c316cfc --- /dev/null +++ b/src/assets/signage/workshop/navigator-middle-active.png Binary files differ diff --git a/src/assets/signage/workshop/navigator-middle.png b/src/assets/signage/workshop/navigator-middle.png new file mode 100644 index 0000000..76cd0a3 --- /dev/null +++ b/src/assets/signage/workshop/navigator-middle.png Binary files differ diff --git a/src/config/router.config.js b/src/config/router.config.js index 2154e1f..5b46888 100644 --- a/src/config/router.config.js +++ b/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') - }, + } ] diff --git a/src/views/mdc/base/GradeWorkshopSignage.vue b/src/views/mdc/base/GradeWorkshopSignage.vue new file mode 100644 index 0000000..98fbcb1 --- /dev/null +++ b/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> \ No newline at end of file diff --git a/src/views/mdc/base/RepairWorkshopSignage.vue b/src/views/mdc/base/RepairWorkshopSignage.vue new file mode 100644 index 0000000..fe0c56c --- /dev/null +++ b/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> \ No newline at end of file diff --git a/src/views/mdc/base/WorkshopSignageEntrance.vue b/src/views/mdc/base/WorkshopSignageEntrance.vue index 05b5f38..9b698eb 100644 --- a/src/views/mdc/base/WorkshopSignageEntrance.vue +++ b/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; } } diff --git a/src/views/mdc/base/modules/GradeSignage/CompanySignage.vue b/src/views/mdc/base/modules/GradeSignage/CompanySignage.vue new file mode 100644 index 0000000..7a3b1ef --- /dev/null +++ b/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: ['姝e父', '缁翠慨', '鐐规', '淇濆吇'] + }, + 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> \ No newline at end of file diff --git a/src/views/mdc/base/modules/GradeSignage/EquipmentSignage.vue b/src/views/mdc/base/modules/GradeSignage/EquipmentSignage.vue new file mode 100644 index 0000000..3bd6fe9 --- /dev/null +++ b/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() + }) + }, + + /** + * 鐐瑰嚮璺宠浆鎸夐挳鏃惰Е鍙戞惡甯quipmentId鍙傛暟璺宠浆鑷冲搴旈〉闈� + * @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 '姝e父': + 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> \ No newline at end of file diff --git a/src/views/mdc/base/modules/GradeSignage/SectionSignage.vue b/src/views/mdc/base/modules/GradeSignage/SectionSignage.vue new file mode 100644 index 0000000..cffc7c0 --- /dev/null +++ b/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: ['姝e父', '缁翠慨', '鐐规', '淇濆吇'] + }, + 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> \ No newline at end of file diff --git a/src/views/mdc/base/modules/GradeSignage/WorkshopSignage.vue b/src/views/mdc/base/modules/GradeSignage/WorkshopSignage.vue new file mode 100644 index 0000000..4d7c7f5 --- /dev/null +++ b/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: ['姝e父', '缁翠慨', '鐐规', '淇濆吇'] + }, + 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> \ No newline at end of file -- Gitblit v1.9.3