From 47ad515964b18ed9b6bea66b7298be1e95ad4de5 Mon Sep 17 00:00:00 2001 From: zhaowei <zhaowei> Date: 星期四, 24 十月 2024 15:22:27 +0800 Subject: [PATCH] 1、新增设备综合效率分析以及报警分析页面 2、新增总控车间看板跳转第三方页面及外部应用功能 3、调整分控车间看板每日生产计划表格一直显示3条记录 --- src/views/mdc/base/alarmAnalysis.vue | 57 ++ src/views/mdc/base/SubControlWorkshopSignage.vue | 18 src/views/mdc/base/modules/OEEAnalysis/OEEAnalysisList.vue | 507 ++++++++++++++++++++++++ src/views/mdc/base/MasterControlWorkshopSignage.vue | 46 + src/views/mdc/base/modules/SparePartsManagement/SparePartsModal.vue | 18 src/views/mdc/base/OEEAnalysis.vue | 59 ++ src/views/mdc/base/modules/alarmAnalysis/alarmAnalysisMain.vue | 539 +++++++++++++++++++++++++ src/views/mdc/base/modules/SubControlWorkshopSignage/SignageModal.vue | 5 8 files changed, 1,231 insertions(+), 18 deletions(-) diff --git a/src/views/mdc/base/MasterControlWorkshopSignage.vue b/src/views/mdc/base/MasterControlWorkshopSignage.vue index 69ef55e..ab55d40 100644 --- a/src/views/mdc/base/MasterControlWorkshopSignage.vue +++ b/src/views/mdc/base/MasterControlWorkshopSignage.vue @@ -30,7 +30,7 @@ </div> <div class="workshop-bg"> <div class="navigate-container" style="top:0;left: 5%;"> - <div @click="navigateTo(item)" v-for="item in productionLineList" :key="item.id" + <div @click="navigateToSubWorkshopSignage(item)" v-for="item in productionLineList" :key="item.id" class="navigate-item"> <template v-if="item.productionOrder<5"> <div :style="{backgroundColor:productionLineBackgroundColorList[item.productionOrder%4]}" @@ -45,7 +45,7 @@ </div> </div> <div class="navigate-container" style="bottom:0;right: 5%;"> - <div @click="navigateTo(item)" v-for="item in productionLineList" :key="item.id" + <div @click="navigateToSubWorkshopSignage(item)" v-for="item in productionLineList" :key="item.id" class="navigate-item"> <template v-if="item.productionOrder>=5"> <div :style="{backgroundColor:productionLineBackgroundColorList[item.productionOrder%4]}" @@ -61,7 +61,7 @@ </div> </div> <div class="switch-container"> - <div @click="activeIndex=index" class="switch-item" v-for="(item,index) in switchList" :key="index" + <div class="switch-item" v-for="(item,index) in switchList" :key="index" @click="navigateToOthers(item,index)" :style="{backgroundColor:activeIndex===index?'#848284':'#6B6D6B',color:activeIndex==index?'#27A2DB':'#000'}"> {{item.label}} </div> @@ -113,23 +113,38 @@ switchList: [ { label: 'MES', - index: 0 + index: 0, + isNavigateToWeb: true, + webUrl: 'http://172.16.52.71:8081', + batPath: '' }, { label: '鍒�鍏风鐞�', - index: 1 + index: 1, + isNavigateToWeb: true, + webUrl: 'http://172.16.52.99/tms', + batPath: '' }, { - label: '鏁呴殰', - index: 2 + label: '璁惧璇婃柇', + index: 2, + isNavigateToWeb: false, + webUrl: '', + batPath: 'yituoSBZD://' }, { - label: '3D', - index: 3 + label: '涓夌淮鐩戞帶', + index: 3, + isNavigateToWeb: false, + webUrl: '', + batPath: 'yituoVR://' }, { label: '瀹夐槻', - index: 4 + index: 4, + isNavigateToWeb: false, + webUrl: '', + batPath: 'yituoAF://' } ], rightColChart1: '', @@ -2148,7 +2163,7 @@ return s }, - navigateTo(record) { + navigateToSubWorkshopSignage(record) { const url = this.$router.resolve({ path: '/SubControlWorkshopSignage', query: { @@ -2160,6 +2175,15 @@ window.open(url, '_blank') }, + navigateToOthers(record, index) { + this.activeIndex = index + if (record.isNavigateToWeb && record.webUrl) { + window.open(record.webUrl, '_blank') + } else { + window.location.href = record.batPath + } + }, + /** * 绐楀彛灏哄鍙樺寲鏃惰Е鍙� * 璋冩暣鍥捐〃灏哄浠ラ�傚簲鍒嗚鲸鐜� diff --git a/src/views/mdc/base/OEEAnalysis.vue b/src/views/mdc/base/OEEAnalysis.vue new file mode 100644 index 0000000..b51ecbf --- /dev/null +++ b/src/views/mdc/base/OEEAnalysis.vue @@ -0,0 +1,59 @@ +<template> + <div style="width: 100%; height: 100%;"> + <a-card :bordered="false"> + <a-row type="flex" :gutter="16"> + <a-col :md="5"> + <a-tabs :activeKey="activeKey" @change="tabChange"> + <a-tab-pane key="1" tab="杞﹂棿灞傜骇" force-render> + <base-tree @getCurrSelected="changeSelectionNode" :filterAbnormalDeviceKey="'1'"></base-tree> + </a-tab-pane> + </a-tabs> + </a-col> + + <a-col :md="19"> + <OEEAnalysisList ref="deviceList" :nodeTree='selectEquipment' :nodePeople='selectPeople' + :Type="selectTypeTree"/> + </a-col> + </a-row> + </a-card> + </div> + +</template> + +<script> + import { JeecgListMixin } from '@/mixins/JeecgListMixin' + import BaseTree from '../common/BaseTree' + import OEEAnalysisList from './modules/OEEAnalysis/OEEAnalysisList' + + export default { + name: 'OEEAnalysis', + components: { + OEEAnalysisList, + BaseTree, + }, + data() { + return { + activeKey: '1', + description: '璁惧淇℃伅', + selectEquipment: {}, + selectTypeTree: '', + selectPeople: {}, + isDepartType: '' + } + }, + methods: { + tabChange(val) { + this.activeKey = val + this.selectTypeTree = val + }, + changeSelectionNode(val) { + this.selectEquipment = val + this.selectTypeTree = '1' + }, + changeSelectionNodedd(val) { + this.selectPeople = val + this.selectTypeTree = '2' + } + } + } +</script> \ No newline at end of file diff --git a/src/views/mdc/base/SubControlWorkshopSignage.vue b/src/views/mdc/base/SubControlWorkshopSignage.vue index 9d66565..10d2242 100644 --- a/src/views/mdc/base/SubControlWorkshopSignage.vue +++ b/src/views/mdc/base/SubControlWorkshopSignage.vue @@ -59,6 +59,22 @@ <td>{{item.clazz}}</td> </template> </tr> + <template v-if="todayProductionPlanList.length<=3"> + <tr v-for="(item,index) in 3-todayProductionPlanList.length" + :key="index"> + <td colspan="2"></td> + <td colspan="2"></td> + <td colspan="2"></td> + <td colspan="2"></td> + <td></td> + <td></td> + <td></td> + <td></td> + <td colspan="2"></td> + <td colspan="2"></td> + <td></td> + </tr> + </template> </tbody> </table> @@ -102,7 +118,7 @@ <template v-for="(listItem,listIndex) in maxBrandToolLifeListLength"> <template> <tr> - <td style="width: 7vw">棰濆畾瀵垮懡</td> + <td style="width: 5vw;min-width: 5vw">棰濆畾瀵垮懡</td> <template v-for="(item,index) in toolLife.brandList"> <td rowspan="2" style="width: 2.5vw"> {{toolLife.lifeList[index][listIndex]?toolLife.lifeList[index][listIndex]?toolLife.lifeList[index][listIndex].tid:'':''}} diff --git a/src/views/mdc/base/alarmAnalysis.vue b/src/views/mdc/base/alarmAnalysis.vue new file mode 100644 index 0000000..8363bd8 --- /dev/null +++ b/src/views/mdc/base/alarmAnalysis.vue @@ -0,0 +1,57 @@ +<template> + <div style="width: 100%; height: 100%;"> + <a-card :bordered="false"> + <a-row type="flex" :gutter="16"> + <a-col :md="5"> + <a-tabs :activeKey="activeKey" @change="tabChange"> + <a-tab-pane key="1" tab="杞﹂棿灞傜骇" force-render> + <base-tree @getCurrSelected="changeSelectionNode"></base-tree> + </a-tab-pane> + </a-tabs> + </a-col> + <a-col :md="19"> + <alarm-analysis-main ref="alarmAnalysisMain" :nodePeople='selectPeople' :nodeTree = 'selectEquipment' :Type="selectTypeTree"></alarm-analysis-main> + </a-col> + </a-row> + </a-card> + </div> + +</template> + +<script> + import { JeecgListMixin } from '@/mixins/JeecgListMixin' + import BaseTree from '../common/BaseTree' + import alarmAnalysisMain from './modules/alarmAnalysis/alarmAnalysisMain' + export default { + name: 'alarmAnalysis', + components: { + BaseTree, + alarmAnalysisMain + }, + data() { + return { + activeKey: '1', + description: '璁惧淇℃伅', + selectEquipment: {}, + selectPeople:{}, + selectTypeTree:"", + isDepartType:'', + } + }, + methods: { + tabChange(val) { + this.activeKey = val + this.selectTypeTree = val + }, + changeSelectionNode(val) { + this.selectEquipment = val + this.selectTypeTree = "1" + }, + changeSelectionNodedd(val) { + this.selectPeople = val + this.selectTypeTree = "2" + } + } + + } +</script> diff --git a/src/views/mdc/base/modules/OEEAnalysis/OEEAnalysisList.vue b/src/views/mdc/base/modules/OEEAnalysis/OEEAnalysisList.vue new file mode 100644 index 0000000..3824b64 --- /dev/null +++ b/src/views/mdc/base/modules/OEEAnalysis/OEEAnalysisList.vue @@ -0,0 +1,507 @@ +<template> + <div style="width: 100%;"> + <div :bordered="false"> + <!-- 鏌ヨ鍖哄煙 --> + <div class="seach-content"> + <div class="table-page-search-wrapper"> + <a-form layout="inline" @keyup.enter.native="searchQuery"> + <a-row :gutter="24"> + <a-col :md="6" :sm="6" :xs="6"> + <a-form-item label="鏃堕棿"> + <a-range-picker @change="dateParamChange" :disabledDate="disabledDate" format="YYYYMMDD" + v-model="dates" :allowClear="false"/> + </a-form-item> + </a-col> + <a-col :md="4" :sm="4" :xs="4"> + <a-form-item label="鐝"> + <a-select v-model="queryParam.shiftSubId" placeholder="璇烽�夋嫨鐝" allow-clear> + <a-select-option key="01" value="01">鏃╃彮</a-select-option> + <a-select-option key="02" value="02">涓彮</a-select-option> + <a-select-option key="03" value="03">鏅氱彮</a-select-option> + </a-select> + </a-form-item> + </a-col> + <a-col :md="14" :sm="14" :xs="14" + style="display: flex;justify-content: space-between;align-items: flex-start"> + <div> + <a-space style="margin-right: 20px"> + <a-button type="primary" @click="searchQuery" icon="search">鏌ヨ</a-button> + <a-button type="primary" @click="searchReset" icon="reload">閲嶇疆</a-button> + <a-button type="primary" @click="exportExcel" icon="download">瀵煎嚭</a-button> + </a-space> + </div> + <table cellpadding="5" cellspacing="1" style="border: 1px solid darkgray;"> + <tr> + <td v-for="(item, index) in identifying">{{item.title}}</td> + </tr> + <tr> + <td style="text-align:center;" v-for="(item, index) in identifying"> + <div class="identifyingclass" :style="{background: item.color}"></div> + </td> + </tr> + </table> + </a-col> + </a-row> + </a-form> + </div> + </div> + <a-spin :spinning="spinning"> + <div class="container" id="EfficiencyShift" style="margin-top: 20px;"> + <div class="table2"> + <table class="dataContent table" border="1" cellspacing="0" cellpadding="0" v-if="dataList.length>0"> + <thead> + <tr class="thead fixed equipname"> + <th class="thgu dong1 name" rowspan="2" style="min-width: 100px; max-width: 100px;width: 100px;">璁惧缂栧彿 + </th> + <th class="thgu dong2 name" rowspan="2" style="min-width: 162px; max-width: 162px;width: 162px;">璁惧鍚嶇О + </th> + <th class="thgu dong3 name" rowspan="2" style="min-width: 100px; max-width: 100px;width: 100px;">璁惧绫诲瀷 + </th> + <template v-for="(tableHead, index) in tableHeads"> + <th class="timeth">{{tableHead}}</th> + </template> + + </tr> + <tr class="thead notfixed gudingth"> + <template v-for="(tableHead, index) in tableHeads"> + <th>OEE</th> + </template> + </tr> + </thead> + <tbody> + <tr class="mathData" v-for="(item, index) in dataList"> + <td class="tdgu1 kaitou">{{item.equipmentId}}</td> + <td class="tdgu2 kaitou" style="min-width: 162px; max-width: 162px;width: 162px;"> + {{item.equipmentName}} + </td> + <td class="tdgu3 kaitou">{{item.equipmentType}}</td> + + <template v-for="(tableHead, index) in item.dataList"> + <td :style="{background:tableHead.color }"> + {{tableHead.oeeRate | numFilter}} + </td> + </template> + </tr> + </tbody> + </table> + </div> + </div> + </a-spin> + </div> + </div> +</template> + +<script> + import moment from 'moment' + import { putAction, getAction } from '@/api/manage' + import '@/components/table2excel/table2excel' + import { ajaxGetDictItems, getDictItemsFromCache, duplicateCheck } from '@/api/api' + import api from '@/api/mdc' + + export default { + name: 'EfficiencyShiftList', + components: {}, + data() { + return { + typeTree: '', + typeParent: 1, + typeEquipment: 1, + dates: [], + identifying: [], + queryParam: {}, + queryParams: { + equipmentType: [], + driveType: [], + deviceLevel: [], + deviceCategory: [] + }, + queryParamEquip: {}, + queryParamPeople: {}, + dataList: [], + url: { + list: '/mdc/mdcOeeInfo/list', + listByType: '/mdc/MdcUtilizationRate/getByType' + }, + tableHeads: [], + spinning: false + } + }, + props: { nodeTree: '', Type: '', nodePeople: '' }, + created() { + this.showIdentifying() + this.dates = [moment().subtract('days', 7), moment().subtract('days', 1)] + this.queryParam.startTime = moment(this.dates[0]).format('YYYYMMDD') + this.queryParam.endTime = moment(this.dates[1]).format('YYYYMMDD') + this.queryParam.typeTree = '1' + this.loadData() + }, + mounted() { + window.addEventListener('resize', this.handleWindowResize) + this.handleWindowResize() + }, + watch: { + Type(valmath) { + this.dataList = [] + this.queryParam.typeTree = valmath + }, + nodeTree(val) { //鐩戝惉currSelected 鍙樺寲锛屽皢鍙樺寲鍚庣殑鏁板�间紶閫掔粰 getCurrSelected 浜嬩欢 + if (JSON.stringify(val) != '{}') { + if (val.equipmentId != null) { + this.queryParamEquip.parentId = '' + this.queryParamEquip.equipmentId = val.equipmentId + } else { + this.queryParamEquip.parentId = val.key + this.queryParamEquip.equipmentId = '' + } + this.searchQuery() + } + }, + nodePeople(val) { + if (JSON.stringify(val) != '{}') { + if (val.equipmentId != null) { + this.queryParamPeople.parentId = val.equipmentId + this.queryParamPeople.equipmentId = '' + } else { + this.queryParamPeople.parentId = val.key + this.queryParamPeople.equipmentId = '' + } + this.searchQuery() + } + } + }, + filters: { + numFilter(value) { + if (value) { + return parseFloat((value * 100).toFixed(2)) + } else { + return '0' + } + }, + + /** + * 鏍煎紡鍖栨椂闂� + * @param seconds 绉掓暟 + * @returns '' 鏍煎紡鍖栧悗鏃堕棿瀛楃涓� + */ + getFormattedTime(seconds) { + if (seconds) { + return parseFloat((seconds / 3600).toFixed(2)) + } else { + return '0' + } + } + }, + methods: { + checkSameData(dataList) { + let cache = {} //瀛樺偍鐨勬槸閿槸kclx 鐨勫�硷紝鍊兼槸kclx 鍦╥ndeces涓暟缁勭殑涓嬫爣 + let indices = [] //鏁扮粍涓瘡涓�涓�兼槸涓�涓暟缁勶紝鏁扮粍涓殑姣忎竴涓厓绱犳槸鍘熸暟缁勪腑鐩稿悓kclx鐨勪笅鏍� + dataList.map((item, index) => { + let level1 = item.level1 + let _index = cache[level1] + if (_index !== undefined) { + indices[_index].push(index) + } else { + cache[level1] = indices.length + indices.push([index]) + } + }) + let result = [] + indices.map((item) => { + item.map((index) => { + result.push(dataList[index]) + }) + }) + this.dataList = result + }, + checkSameData1(dataList) { + let cache = {} //瀛樺偍鐨勬槸閿槸kclx 鐨勫�硷紝鍊兼槸kclx 鍦╥ndeces涓暟缁勭殑涓嬫爣 + let indices = [] //鏁扮粍涓瘡涓�涓�兼槸涓�涓暟缁勶紝鏁扮粍涓殑姣忎竴涓厓绱犳槸鍘熸暟缁勪腑鐩稿悓kclx鐨勪笅鏍� + dataList.map((item, index) => { + let level2 = item.level2 + let _index = cache[level2] + if (_index !== undefined) { + indices[_index].push(index) + } else { + cache[level2] = indices.length + indices.push([index]) + } + }) + let result = [] + indices.map((item) => { + item.map((index) => { + result.push(dataList[index]) + }) + }) + this.dataList = result + }, + checkSameData2(dataList) { + let cache = {} //瀛樺偍鐨勬槸閿槸kclx 鐨勫�硷紝鍊兼槸kclx 鍦╥ndeces涓暟缁勭殑涓嬫爣 + let indices = [] //鏁扮粍涓瘡涓�涓�兼槸涓�涓暟缁勶紝鏁扮粍涓殑姣忎竴涓厓绱犳槸鍘熸暟缁勪腑鐩稿悓kclx鐨勪笅鏍� + dataList.map((item, index) => { + let level3 = item.level3 + let _index = cache[level3] + if (_index !== undefined) { + indices[_index].push(index) + } else { + cache[level3] = indices.length + indices.push([index]) + } + }) + let result = [] + indices.map((item) => { + item.map((index) => { + result.push(dataList[index]) + }) + }) + this.dataList = result + }, + // 鍚堝苟 + combineCell() { + let list = this.dataList + for (let field in list[0]) { + var k = 0 + while (k < list.length) { + list[k][field + 'span'] = 1 + list[k][field + 'dis'] = false + for (var i = k + 1; i <= list.length - 1; i++) { + if (list[k][field] == list[i][field] && list[k][field] != '') { + list[k][field + 'span']++ + list[k][field + 'dis'] = false + list[i][field + 'span'] = 1 + list[i][field + 'dis'] = true + } else { + break + } + } + k = i + } + } + return list + }, + disabledDate(current) { + //Can not slect days before today and today + return current && current > moment().subtract('days', 1) + }, + initDeviceType(deviceList) { + let dictCode = 'mdc_equipmentType' + let items = [] + items = getDictItemsFromCache(dictCode) + if (deviceList && items.length > 0) { + for (let a = 0; a < deviceList.length; a++) { + if (items && items.length > 0) { + for (let i = 0; i < items.length; i++) { + if (deviceList[a].equipmentType == items[i].value) { + deviceList[a].equipmentType = items[i].title + } + } + } else { + ajaxGetDictItems(dictCode, null).then((res) => { + if (res.success) { + let items = res.result + for (let i = 0; i < items.length; i++) { + if (deviceList[a].equipmentType == items[i].value) { + deviceList[a].equipmentType = items[i].title + } + } + } + }) + } + } + } + }, + exportExcel() { + $('#EfficiencyShift').table2excel({ + exclude: '.noExl', + name: 'Excel Document Name', + filename: '鐝鍒╃敤鐜�', + exclude_img: true, + fileext: '.xls', + exclude_links: true, + exclude_inputs: true + }) + }, + showIdentifying() { + getAction(this.url.listByType, { type: 'oee' }).then(res => { + if (res.success) { + this.identifying = res.result + } + }) + }, + dateParamChange(v1, v2) { + this.queryParam.startTime = v2[0] + this.queryParam.endTime = v2[1] + // 鐐瑰嚮鏃堕棿閫夋嫨鍣ㄧ殑娓呯┖鎸夐挳鏃朵細瑙﹀彂姝ゅ垽鏂�(鐐瑰嚮閲嶇疆鎸夐挳涓嶄細瑙﹀彂)锛屽疄鐜伴噸缃垪琛ㄥ姛鑳斤紝鍒囧疄鏀瑰彉鍒楄〃鏄剧ず鏁堟灉 + // if(!this.queryParam.startTime&&!this.queryParam.endTime)this.searchReset() + }, + searchQuery() { + if (this.queryParam.typeTree == '1') { + this.queryParam.parentId = this.queryParamEquip.parentId + this.queryParam.equipmentId = this.queryParamEquip.equipmentId + } else { + this.queryParam.parentId = this.queryParamPeople.parentId + this.queryParam.equipmentId = '' + } + Object.keys(this.queryParams).forEach(item => { + this.queryParam[item] = this.queryParams[item].join() + // 姝ゅ涓轰繚璇佹帴鍙e弬鏁颁笉澶氫綑锛屽彲鐪佺暐 + if (this.queryParams[item].length === 0) delete this.queryParam[item] + }) + this.loadData() + }, + searchReset() { + this.typeTree = this.queryParam.typeTree + this.typeParent = this.queryParam.parentId + this.typeEquipment = this.queryParam.equipmentId + this.queryParam = {} + this.dates = [moment().subtract('days', 7), moment().subtract('days', 1)] + this.queryParam.startTime = moment(this.dates[0]).format('YYYYMMDD') + this.queryParam.endTime = moment(this.dates[1]).format('YYYYMMDD') + this.queryParam.typeTree = this.typeTree + this.queryParam.parentId = this.typeParent + this.queryParam.equipmentId = this.typeEquipment + this.queryParams = {} + this.loadData() + }, + loadData() { + this.spinning = true + this.tableHeads = [] + this.dataList = [] + getAction(this.url.list, this.queryParam).then(res => { + if (res.success) { + console.log('res=', res) + this.tableHeads = res.result.dates + this.dataList = res.result.mdcOeeListDtoList + if (res.result.mdcOeeListDtoList && !res.result.mdcOeeListDtoList.length) { + this.$notification.info({ + message: '娑堟伅', + description: '鏆傛棤璇ョ被鍨嬫暟鎹�' + }) + } + this.checkSameData(this.dataList) + this.checkSameData1(this.dataList) + this.checkSameData2(this.dataList) + this.combineCell() + } + }).finally(() => { + this.spinning = false + }) + }, + + /** + * 鍒嗚鲸鐜囨敼鍙樻椂鍚屾椂鏀瑰彉琛ㄦ牸楂樺害宸蹭繚璇侀椤典竴杩涘叆涓嶆嫋鍔ㄥ瀭鐩存粴鍔ㄦ潯鏃跺嵆鍙嫋鍔ㄨ〃鏍兼按骞虫粴鍔ㄦ潯 + */ + handleWindowResize() { + const tableContainer = document.getElementById('EfficiencyShift') // 琛ㄦ牸瀹瑰櫒 + const clientHeight = document.documentElement.clientHeight || document.body.clientHeight // 娴忚鍣ㄥ彲瑙嗗尯鍩熼珮搴� + const containerTopToClientTopHeight = tableContainer.getBoundingClientRect().top // 琛ㄦ牸瀹瑰櫒椤堕儴鍒版祻瑙堝櫒鍙鍖哄煙椤堕儴鐨勯棿璺� + tableContainer.style.height = (clientHeight - containerTopToClientTopHeight - 32) + 'px' + } + } + } +</script> +<style scoped> + .table2 { + width: 100%; + height: 100%; + overflow: auto; + } + + .table2 thead tr th:first-child, + .table tbody tr .tdgu { + position: sticky; + left: 0; + z-index: 1; + } + + .table tbody tr .wenzi { + transform: rotate(360deg); + writing-mode: vertical-lr; + letter-spacing: 2px; + } + + .table tbody tr .kaitou { + z-index: 1; + background-color: white; + } + + .table tbody tr .tdgu1 { + position: sticky; + left: 0; + z-index: 2; + } + + .table tbody tr .tdgu2 { + position: sticky; + left: 100px; + z-index: 2; + } + + .table tbody tr .tdgu3 { + position: sticky; + left: 262px; + z-index: 2; + } + + .table2 thead tr .timeth, + .table2 thead tr .thgu { + position: sticky; + top: 0; + z-index: 3; + } + + .table2 thead .gudingth th { + position: sticky; + top: 32px; + z-index: 2; + } + + .table2 thead .equipname .name { + z-index: 3; + } + + .table2 thead .equipname .dong1 { + z-index: 5; + left:0; + } + + .table2 thead .equipname .dong2 { + z-index: 5; + left:100px; + } + + .table2 thead .equipname .dong3 { + z-index: 5; + left: 262px; + } + + #EfficiencyShift { + overflow: hidden; + } + + .identifyingclass { + width: 55px; + height: 15px; + display: inline-block + } + + .dataContent { + white-space: nowrap; + border-collapse: separate; + border-spacing: 0; + border: 1px solid #ccc; + width: 100%; + text-align: center; + } + + .dataContent .thead th { + background-color: #fafafa; + text-align: center; + height: 30px; + padding: 5px; + } + + .dataContent .mathData td { + padding: 10px; + } + +</style> \ No newline at end of file diff --git a/src/views/mdc/base/modules/SparePartsManagement/SparePartsModal.vue b/src/views/mdc/base/modules/SparePartsManagement/SparePartsModal.vue index 6102800..200e688 100644 --- a/src/views/mdc/base/modules/SparePartsManagement/SparePartsModal.vue +++ b/src/views/mdc/base/modules/SparePartsManagement/SparePartsModal.vue @@ -59,13 +59,14 @@ <a-col :span="12"> <a-form-model-item prop="overallFlag" label="鏄惁涓鸿嚜鍔ㄧ嚎" :labelCol="{xs: { span: 24 },sm: { span: 8 }}" :wrapperCol="{xs: { span: 24 },sm: { span: 16 }}"> - <j-switch v-model="model.overallFlag"></j-switch> + <j-switch v-model="model.overallFlag" @change="handleSwitchChange"></j-switch> </a-form-model-item> </a-col> - <a-col :span="12"> + <a-col :span="12" v-if="model.overallFlag==='N'"> <a-form-model-item prop="equipmentId" label="鐢熶骇璁惧" :labelCol="labelCol" :wrapperCol="wrapperCol"> - <a-select v-model="model.equipmentId" placeholder="璇烽�夋嫨鐢熶骇璁惧" style="width: 100%"> + <a-select v-model="model.equipmentId" placeholder="璇烽�夋嫨鐢熶骇璁惧" mode="multiple" :maxTagCount="1" + style="width: 100%" allow-clear> <a-select-option v-for="(item,index) in equipmentList" :key="index" :value="item.equipmentId"> {{item.equipmentId}} </a-select-option> @@ -80,7 +81,7 @@ <template slot="footer"> - <a-popconfirm title="纭畾鏀惧純鎿嶄綔锛�" @confirm="visible=false" okText="纭畾" cancelText="鍙栨秷"> + <a-popconfirm title="纭畾鏀惧純鎿嶄綔锛�" @confirm="handleModalClose" okText="纭畾" cancelText="鍙栨秷"> <a-button style="margin-right: .8rem">鍙栨秷</a-button> </a-popconfirm> <a-button @click="handleSubmit" type="primary" :loading="confirmLoading">鎻愪氦</a-button> @@ -185,6 +186,7 @@ edit(record) { this.visible = true this.model = Object.assign({}, record) + this.model.equipmentId = this.model.equipmentId.split(',') console.log('model', this.model) this.getProductionLineByApi() this.$nextTick(() => { @@ -199,6 +201,8 @@ if (valid) { that.confirmLoading = true let obj + if (!this.model.equipmentId) this.model.equipmentId = '' + else this.model.equipmentId = this.model.equipmentId.join(',') if (this.title == '鏂板') { obj = api.addSparePartApi(this.model) } else { @@ -249,6 +253,11 @@ this.getEquipmentListByProductionId() }, + handleSwitchChange(value) { + console.log('value', value) + if (value === 'Y') delete this.model.equipmentId + }, + getEquipmentListByProductionId() { api.getEquipmentListByProductionIdApi(this.model.productionId) .then(res => { @@ -260,6 +269,7 @@ handleModalClose() { this.visible = false this.equipmentList = [] + this.removeValidate() }, /** diff --git a/src/views/mdc/base/modules/SubControlWorkshopSignage/SignageModal.vue b/src/views/mdc/base/modules/SubControlWorkshopSignage/SignageModal.vue index 647e42c..eda6923 100644 --- a/src/views/mdc/base/modules/SubControlWorkshopSignage/SignageModal.vue +++ b/src/views/mdc/base/modules/SubControlWorkshopSignage/SignageModal.vue @@ -1,6 +1,7 @@ <template> <a-modal title="褰撴棩鐢熶骇璁″垝" :width="modalWidth" :visible="modalVisible" :footer="null" @cancel="$emit('closeModal')"> - <a-table :columns="modalTableColumns" :dataSource="todayProductionPlanList" :pagination="false" :loading="loading" rowKey="equipmentId"></a-table> + <a-table :columns="modalTableColumns" :dataSource="todayProductionPlanList" :pagination="false" + rowKey="equipmentId"></a-table> </a-modal> </template> @@ -14,7 +15,7 @@ default: 1448 }, todayProductionPlanList: { - type: Object + type: Array }, modalVisible: { type: Boolean diff --git a/src/views/mdc/base/modules/alarmAnalysis/alarmAnalysisMain.vue b/src/views/mdc/base/modules/alarmAnalysis/alarmAnalysisMain.vue new file mode 100644 index 0000000..8b9b9df --- /dev/null +++ b/src/views/mdc/base/modules/alarmAnalysis/alarmAnalysisMain.vue @@ -0,0 +1,539 @@ +<template> + <div class="efficiency_list" style="width: 100%;height: 100%;"> + <div :bordered="false" style="height: 100%"> + <!-- 鏌ヨ鍖哄煙 --> + <div class="table-page-search-wrapper"> + <a-form layout="inline" @keyup.enter.native="searchQuery"> + <a-row :gutter="24"> + <a-col :md="7" :sm="7"> + <a-form-item label="鏃堕棿"> + <a-range-picker @change="dateParamChange" :disabledDate="disabledDate" format="YYYYMMDD" + v-model="dates" :allowClear="false"/> + </a-form-item> + </a-col> + <a-col :lg="2" :md="2" :sm="2" :xs="2"> + <a-button type="primary" @click="searchQuery" icon="search">鏌ヨ</a-button> + </a-col> + </a-row> + </a-form> + </div> + <div id="DeviceList"> + <div class="openRateTrendDg"> + <a-table :columns="columns" :data-source="dataList" bordered :pagination="false" :scroll="{y:210}" + :customRow="customRow" + rowKey="alarmCode" @expand="handleExpandChange" :loading="outerDataLoading" + > + <span slot="timeCount" slot-scope="text">{{text | getFormattedTime}}</span> + <a-table + slot="expandedRowRender" + slot-scope="row" + :columns="innerColumns" + :data-source="row.innerDataList" + :pagination="false" + rowKey="rowIndex" + :loading="innerDataLoading" + > + <span slot="duration" slot-scope="text">{{text | getFormattedTime}}</span> + </a-table> + </a-table> + </div> + + <a-spin :spinning="echartLoading"> + <div style="width: 100%;height: 100%;display: flex;"> + <div id="MdcEquipmentWarningPie" style="height: 100%;width: 35%;"></div> + <div id="MdcEquipmentWarningLine" style="height: 100%;width: 65%;"></div> + </div> + </a-spin> + </div> + </div> + </div> +</template> + +<script> + import moment from 'moment' + import { putAction, getAction } from '@/api/manage' + import $ from 'jquery' + import '@/components/table2excel/table2excel' + import { ajaxGetDictItems, getDictItemsFromCache, duplicateCheck } from '@/api/api' + import { + JeecgListMixin + } from '@/mixins/JeecgListMixin' + + const columns = [ + { title: '鎶ヨ鍙�', dataIndex: 'alarmCode', key: 'alarmCode', align: 'center' }, + { title: '鍑虹幇娆℃暟', dataIndex: 'count', key: 'count', align: 'center', sorter: (a, b) => b.count - a.count }, + { + title: '鍚堣鎸佺画鏃堕棿', + dataIndex: 'timeCount', + key: 'timeCount', + scopedSlots: { customRender: 'timeCount' }, + align: 'center', + sorter: (a, b) => b.timeCount - a.timeCount + }, + { title: '鎶ヨ淇℃伅', dataIndex: 'alarmContent', key: 'alarmContent', align: 'center', ellipsis: true } + ] + + const innerColumns = [ + { + title: '', + dataIndex: 'rowIndex', + key: 'rowIndex', + width: 60, + align: 'center', + customRender: function(t, r, index) { + return parseInt(index) + 1 + } + }, + { title: '璁惧缂栧彿', dataIndex: 'equipmentId', key: 'equipmentId', align: 'center' }, + { title: '璁惧鍚嶇О', dataIndex: 'equipmentName', key: 'equipmentName', align: 'center' }, + { title: '鎶ヨ鏃堕棿', dataIndex: 'startTime', key: 'startTime', align: 'center' }, + { title: '缁撴潫鏃堕棿', dataIndex: 'endTime', key: 'endTime', align: 'center' }, + { + title: '鎸佺画鏃堕棿', + dataIndex: 'duration', + key: 'duration', + scopedSlots: { customRender: 'duration' }, + align: 'center' + } + ] + + export default { + // mixins: [JeecgListMixin], + name: 'alarmAnalysisMain', + components: {}, + data() { + return { + dataSource: [], + /* table鍔犺浇鐘舵�� */ + outerDataLoading: false, + innerDataLoading: false, + echartLoading: false, + typeTree: '', + typeParent: 1, + typeEquipment: 1, + TreeIDOne: 1, + TreeIDTwo: 2, + deviceTypeDict: '', + dates: [], + identifying: [], + queryParam: {}, + queryParams: {}, + queryParamEquip: {}, + queryParamPeople: {}, + efficiencyOptions: [ + { label: '鍒╃敤鐜�', value: 'lyl' }, + { label: '寮�鏈虹巼', value: 'kjl' }, + { label: '寮�鏈烘椂闂�', value: 'kjsj' }, + { label: '鍔犲伐鏃堕棿', value: 'jgsj' }, + { label: '寰呮満鏃堕棿', value: 'djsj' }, + { label: '鍏虫満鏃堕棿', value: 'gjsj' } + ], + checkedList: ['lyl'], + dataList: [], + url: { + efficiencyList: '/mdc/alarmAnalyze/alarmList', + listByType: '/mdc/MdcUtilizationRate/getByType', + alarmTrend: '/mdc/alarmAnalyze/alarmTrend', + equipmentAlarmList: '/mdc/alarmAnalyze/equipmentAlarmList' + }, + tableHeads: [], + pieDate: [0], + XData: [0], + YData: [0], + columns, + innerColumns, + hasRequsetAlarmCodeList: [] + } + }, + props: { nodeTree: '', Type: '', nodePeople: '' }, + /** + * 鐢熷懡鍛ㄦ湡 鎸傝浇鍓� + * */ + created() { + this.dates = [moment().subtract('days', 8), moment().subtract('days', 1)] + this.queryParam.startDate = moment(this.dates[0]).format('YYYYMMDD') + this.queryParam.endDate = moment(this.dates[1]).format('YYYYMMDD') + this.queryParam.typeTree = '1' + this.loadData1() + + }, + mounted() { + this.drawWrin() + window.addEventListener('resize', this.handleWindowResize) + }, + beforeDestroy() { + window.removeEventListener('resize', this.handleWindowResize) + }, + watch: { + Type(valmath) { + this.dataList = [] + this.queryParam.typeTree = valmath + }, + nodeTree(val) { //鐩戝惉currSelected 鍙樺寲锛屽皢鍙樺寲鍚庣殑鏁板�间紶閫掔粰 getCurrSelected 浜嬩欢 + if (JSON.stringify(val) != '{}') { + if (val.equipmentId != null) { + this.queryParamEquip.parentId = '' + this.queryParamEquip.equipmentId = val.equipmentId + } else { + this.queryParamEquip.parentId = val.key + this.queryParamEquip.equipmentId = '' + } + /*杩欓噷浣犳槸鐩戝惉鍒版爲寰楀彉鍖� 鏄笉鏄姹備竴娆�*/ + this.searchQuery() + } + }, + nodePeople(val) { + if (JSON.stringify(val) != '{}') { + if (val.equipmentId != null) { + this.queryParamPeople.parentId = val.equipmentId + this.queryParamPeople.equipmentId = '' + } else { + this.queryParamPeople.parentId = val.key + this.queryParamPeople.equipmentId = '' + } + this.searchQuery() + } + } + }, + filters: { + numFilter(value) { + if (value) { + return parseFloat((value * 100).toFixed(2)) + } else { + return '0' + } + }, + + /** + * 鏍煎紡鍖栨椂闂� + * @param seconds 绉掓暟 + * @returns '' 鏍煎紡鍖栧悗鏃堕棿瀛楃涓� + */ + getFormattedTime(seconds) { + var hours = Math.floor(seconds / 3600) + var minutes = Math.floor((seconds % 3600) / 60) + var secs = seconds % 60 + + if (hours === 0) { + if (minutes === 0) { + return secs === 0 ? 0 : `${secs}绉抈 + } else { + if (secs === 0) { + return `${minutes}鍒哷 + } + return `${minutes}鍒� ${secs}绉抈 + } + } else { + if (minutes === 0 && secs === 0) { + return `${hours}灏忔椂` + } else if (minutes !== 0 && secs === 0) { + return `${hours}灏忔椂 ${minutes}鍒哷 + } + } + return `${hours}灏忔椂 ${minutes}鍒� ${secs}绉抈 + } + }, + methods: { + numBerTwo(value) { + if (value) { + return parseFloat((value * 100).toFixed(2)) + } else { + return '0' + } + }, + TableDraw(key, val) { + let that = this + that.echartLoading = true + that.queryParam.alarmCode = val.alarmCode + console.log(this.queryParam) + getAction(that.url.alarmTrend, that.queryParam) + .then(res => { + if (res.success) { + that.pieDate = res.result.equipmentCountList.map(item => { + return { + name: item.key, + value: item.count + } + }) + that.XData = res.result.dateCountList.map(item => item.key) + that.YData = res.result.dateCountList.map(item => item.count) + + // this.tableHeads = res.result.dates + // this.dataList = res.result + // this.draw() + // this.checkSameData(this.dataList) + // this.checkSameData1(this.dataList) + // this.checkSameData2(this.dataList) + // this.combineCell(); + // this.initDeviceType(this.dataList) + that.drawWrin() + } + }) + .finally(() => { + that.echartLoading = false + }) + console.log(this.YData) + + }, + disabledDate(current) { + //Can not slect days before today and today + return current && current > moment().subtract('days', 1) + }, + initDeviceType(deviceList) { + let dictCode = 'mdc_equipmentType' + let items = [] + items = getDictItemsFromCache(dictCode) + if (deviceList && items.length > 0) { + for (let a = 0; a < deviceList.length; a++) { + if (items && items.length > 0) { + for (let i = 0; i < items.length; i++) { + if (deviceList[a].equipmentType == items[i].value) { + deviceList[a].equipmentType = items[i].title + } + } + } else { + ajaxGetDictItems(dictCode, null).then((res) => { + if (res.success) { + let items = res.result + for (let i = 0; i < items.length; i++) { + if (deviceList[a].equipmentType == items[i].value) { + deviceList[a].equipmentType = items[i].title + } + } + } + }) + } + } + } + }, + dateParamChange(v1, v2) { + this.queryParam.startDate = v2[0] + this.queryParam.endDate = v2[1] + }, + searchQuery() { + if (this.queryParam.typeTree == '1') { + this.queryParam.parentId = this.queryParamEquip.parentId + this.queryParam.equipmentId = this.queryParamEquip.equipmentId + } else { + this.queryParam.parentId = this.queryParamPeople.parentId + this.queryParam.equipmentId = '' + } + this.loadData1() + }, + loadData1() { + this.outerDataLoading = true + this.tableHeads = [] + this.dataList = [] + getAction(this.url.efficiencyList, this.queryParam).then(res => { + if (res.success) { + // this.tableHeads = res.result.dates + this.dataList = res.result + this.hasRequsetAlarmCodeList = [] + // this.draw() + // this.checkSameData(this.dataList) + // this.checkSameData1(this.dataList) + // this.checkSameData2(this.dataList) + // this.combineCell(); + // this.initDeviceType(this.dataList) + + } + }).finally(() => { + this.outerDataLoading = false + }) + }, + drawWrin() { + this.equipmentWarningPie = this.$echarts.init(document.getElementById('MdcEquipmentWarningPie'), 'macarons') + let equipmentWarningPieOption = { + title: { + text: '鍚勮澶囧嚭鐜版鎶ヨ鐨勬瘮渚�', + x: 'center', + y: 'bottom', + textStyle: { + color: '#4FAEDC' + } + }, + tooltip: { + trigger: 'item', + formatter: '<br/>{b} : {c} ({d}%)' + }, + calculable: true, + series: [{ + type: 'pie', + radius: '60%', + itemStyle: { + color: function(params) { + var colorList = ['#5AB1EF', '#2EC7C9', '#B6A2DE', '#FFB980', '#D87A80', '#8D98B3'] + return colorList[params.dataIndex] + }, + label: { + show: true, + // position: 'top', + formatter: '{b}\n{c}', + color: function(params) { + var colorList = ['#5AB1EF', '#2EC7C9', '#B6A2DE', '#FFB980', '#D87A80', '#8D98B3'] + return colorList[params.dataIndex] + } + } + }, + data: this.pieDate + // data:[{name:'jjjjjjj',value:'2'}] + }] + } + this.equipmentWarningPie.setOption(equipmentWarningPieOption, true) + this.equipmentWarningLine = this.$echarts.init(document.getElementById('MdcEquipmentWarningLine'), 'macarons') + let equipmentWarningLineOption = { + title: { + text: '姣忓ぉ鍑虹幇姝ゆ姤璀︾殑鏁伴噺璧板娍', + x: 'center', + y: 'bottom', + textStyle: { + color: '#4FAEDC' + } + }, + tooltip: { + trigger: 'axis' + }, + calculable: true, + xAxis: [ + { + type: 'category', + show: true, + data: this.XData + /*axisLabel :{ + interval:0 + }*/, + axisLine: { + //x杞寸嚎鐨勯鑹蹭互鍙婂搴� + show: true, + lineStyle: { + width: 2, + color: '#4FAEDC' + } + } + } + ], + yAxis: [ + { + type: 'value', + name: '娆℃暟', + axisLine: { + //x杞寸嚎鐨勯鑹蹭互鍙婂搴� + show: true, + lineStyle: { + width: 2, + color: '#4FAEDC' + } + } + } + ], + series: [ + { + name: '鎶ヨ鏁伴噺', + type: 'line', + data: this.YData, + markPoint: { + data: [ + { type: 'max', name: '鏈�澶у��' }, + { type: 'min', name: '鏈�灏忓��' } + ], + label: { + color: '#fff' + } + }, + itemStyle: { + color: '#2EC7C9' + } + } + ] + } + this.equipmentWarningLine.setOption(equipmentWarningLineOption, true) + }, + + /** + * 鑷畾涔夎〃鏍艰瑙﹀彂 + * @param record 褰撳墠琛屼俊鎭� + * @param index 褰撳墠琛屼笅鏍� + * @returns {{on: {click: on.click}}} 杩斿洖瀵硅薄 + */ + customRow(record, index) { + return { + on: { + click: (event) => { + // 濡傛灉鐐瑰嚮鐨勪笉鏄睍寮�鍥炬爣鍖哄煙鍒欐覆鏌撳浘琛紝鐩稿弽鍒欑浉褰撲簬鐐瑰嚮灞曞紑鍥炬爣 + if (event.target.className !== 'ant-table-row-expand-icon-cell') { + this.TableDraw(index, record) + } else { + if (event.target.children && event.target.children.length > 0) event.target.children[0].click() + } + } + } + } + }, + + /** + * 鑷畾涔夎〃鏍艰瑙﹀彂 + * @param expanded 褰撳墠琛屾槸鍚︿负灞曞紑鐘舵�� + * @param record 褰撳墠琛屼俊鎭� + */ + handleExpandChange(expanded, record) { + let _this = this + // 褰撳睍寮�鏃惰嫢璇ヨ鏈灞曞紑杩囨墠浼氳姹傚悗鍙版暟鎹紝灞曞紑杩囩殑鏁版嵁浼氳缂撳瓨鏃犻渶閲嶅璇锋眰 + this.queryParam.alarmCode = record.alarmCode + if (expanded && !this.hasRequsetAlarmCodeList.includes(record.alarmCode)) { + this.innerDataLoading = true + getAction(this.url.equipmentAlarmList, this.queryParam).then(res => { + if (res.success) { + _this.dataList.forEach(item => { + if (item.alarmCode === record.alarmCode) { + item.innerDataList = res.result + } + }) + _this.hasRequsetAlarmCodeList.push(record.alarmCode) + } + }) + .finally(() => { + _this.innerDataLoading = false + }) + } + }, + + /** + * 褰撴祻瑙堝櫒鍙绐楀彛灏哄鍙戠敓鏀瑰彉鏃惰Е鍙� + */ + handleWindowResize() { + if (this.equipmentWarningPie) this.equipmentWarningPie.resize() + if (this.equipmentWarningLine) this.equipmentWarningLine.resize() + } + } + } +</script> +<style scoped> + .efficiency_list #DeviceList { + height: 90% !important; + } + + /deep/ .ant-table-body .ant-table-row td { + padding-top: 10px; + padding-bottom: 10px; + } + + /deep/ .ant-table-scroll > .ant-table-body > table > .ant-table-tbody > .ant-table-row td { + cursor: pointer; + } + + /deep/ .ant-spin-nested-loading { + height: 55%; + } + + /deep/ .ant-spin-container { + height: 100%; + } + + /deep/ .ant-table.ant-table-bordered { + height: 265px; + } + + /deep/ .ant-table-scroll > .ant-table-placeholder { + height: 210px; + } +</style> \ No newline at end of file -- Gitblit v1.9.3