368 lines
11 KiB
Vue
368 lines
11 KiB
Vue
|
<!--
|
|||
|
/*
|
|||
|
* @Author: lb
|
|||
|
* @Date: 2022-07-21 13:30:00
|
|||
|
* @LastEditors: lb
|
|||
|
* @LastEditTime: 2022-07-21 13:30:00
|
|||
|
* @Description: 设备产量时序图
|
|||
|
*/
|
|||
|
-->
|
|||
|
<template>
|
|||
|
<div>
|
|||
|
<div class="app-container">
|
|||
|
<head-form :form-config="headFormConfig" @headBtnClick="btnClick" />
|
|||
|
|
|||
|
<transition mode="out-in" name="slide-to-left">
|
|||
|
<equipment-efficiency-graph v-if="showGraph" key="graph" ref="eegraph" @close-graph="showGraph = false" />
|
|||
|
<base-table
|
|||
|
v-else
|
|||
|
key="table"
|
|||
|
:page="listQuery.current"
|
|||
|
:limit="listQuery.size"
|
|||
|
:table-config="tableProps"
|
|||
|
:table-data="dataList"
|
|||
|
:is-loading="listLoading"
|
|||
|
:index-config="{ align: 'left', fixed: 'left' }"
|
|||
|
@emitFun="handleTableEvents"
|
|||
|
/>
|
|||
|
</transition>
|
|||
|
</div>
|
|||
|
<!-- <div class="app-container">
|
|||
|
<el-radio-group v-model="chartType" class="data-analysis-radio" size="mini" @change="changeChartType">
|
|||
|
<el-radio-button v-for="(item, index) in chartDataArr" :key="index" :label="index">
|
|||
|
{{ item.equipmentName }}
|
|||
|
</el-radio-button>
|
|||
|
</el-radio-group>
|
|||
|
<Line-chart :chart-data="chartDataItem" width="100%" height="400px" />
|
|||
|
</div> -->
|
|||
|
</div>
|
|||
|
</template>
|
|||
|
|
|||
|
<script>
|
|||
|
// import i18n from '@/lang'
|
|||
|
import HeadForm from '@/components/basicData/HeadForm'
|
|||
|
import BaseTable from '@/components/BaseTable/index-compound'
|
|||
|
// import LineChart from '@/components/Charts/LineChart'
|
|||
|
import { getLineList, getFactoryList, getOEE } from '@/api/DataAnalysis/equipmentEfficiency'
|
|||
|
import moment from 'moment'
|
|||
|
import commonBtn from '@/components/BaseTable/subcomponents/CommonBtn.vue'
|
|||
|
|
|||
|
import EquipmentEfficiencyGraph from './components/equipmentEfficiencyGraph.vue'
|
|||
|
// import { timeFormatter } from '@/filters'
|
|||
|
/**
|
|||
|
* 表格表头配置项 TypeScript接口注释
|
|||
|
* tableConfig<ConfigItem> = []
|
|||
|
*
|
|||
|
* Interface ConfigItem = {
|
|||
|
* prop: string,
|
|||
|
* label: string,
|
|||
|
* width: string,
|
|||
|
* align: string,
|
|||
|
* subcomponent: function,
|
|||
|
* filter: function
|
|||
|
* }
|
|||
|
*
|
|||
|
*
|
|||
|
*/
|
|||
|
|
|||
|
const tableProps = [
|
|||
|
{
|
|||
|
label: '工厂',
|
|||
|
prop: 'factoryName'
|
|||
|
},
|
|||
|
{
|
|||
|
label: '产线',
|
|||
|
prop: 'pdName'
|
|||
|
},
|
|||
|
{
|
|||
|
label: '工序',
|
|||
|
prop: 'wsName'
|
|||
|
},
|
|||
|
{
|
|||
|
label: '设备',
|
|||
|
prop: 'eqName'
|
|||
|
},
|
|||
|
{
|
|||
|
label: '有效时间(h)',
|
|||
|
children: [
|
|||
|
{ prop: 'workTime', label: '工作时长(小时)', width: 120, filter: val => `${val} 小时` },
|
|||
|
{ prop: 'workRate', label: '工作时长比率', width: 120, filter: val => (val * 100).toFixed(2) + '%' }
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
label: '关机时间(h)',
|
|||
|
children: [
|
|||
|
{ prop: 'stopTime', label: '停机时长(小时)', width: 120, filter: val => `${val} 小时` },
|
|||
|
{ prop: 'stopRate', label: '停机比率', filter: val => (val * 100).toFixed(2) + '%' }
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
label: '中断损失',
|
|||
|
children: [
|
|||
|
{ prop: 'downTime', label: '故障时长(小时)', width: 120, filter: val => `${val} 小时` },
|
|||
|
{ prop: 'downRate', label: '故障比率', filter: val => (val * 100).toFixed(2) + '%' }
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
label: '速度损失',
|
|||
|
children: [
|
|||
|
{ prop: 'realYield', label: '实际加工速度', width: 120, filter: val => `${val} 片/小时` }, // 片/小时
|
|||
|
{ prop: 'designYield', label: '理论加工速度', width: 120, filter: val => `${val} 片/小时` },
|
|||
|
{ prop: 'peEfficiency', label: '速度开动率', width: 120, filter: val => (val * 100).toFixed(2) + '%' }
|
|||
|
]
|
|||
|
},
|
|||
|
// {
|
|||
|
// prop: 'goodRate',
|
|||
|
// label: '良品率' // 暂时先隐藏
|
|||
|
// },
|
|||
|
{
|
|||
|
label: 'OEE',
|
|||
|
prop: 'oee',
|
|||
|
filter: val => (val * 100).toFixed(2) + '%'
|
|||
|
},
|
|||
|
{
|
|||
|
label: 'TEEP',
|
|||
|
prop: 'teep',
|
|||
|
filter: val => (val * 100).toFixed(2) + '%'
|
|||
|
},
|
|||
|
{
|
|||
|
label: '操作',
|
|||
|
subcomponent: commonBtn,
|
|||
|
emitFullData: true,
|
|||
|
buttonContent: '查看趋势',
|
|||
|
actionName: 'view-trend'
|
|||
|
}
|
|||
|
]
|
|||
|
|
|||
|
export default {
|
|||
|
name: 'EquipmentEfficiency',
|
|||
|
components: { BaseTable, HeadForm, EquipmentEfficiencyGraph /** LineChart */ },
|
|||
|
data() {
|
|||
|
return {
|
|||
|
addOrUpdateVisible: false,
|
|||
|
tableProps,
|
|||
|
dataList: [],
|
|||
|
total: 0,
|
|||
|
listLoading: false,
|
|||
|
listQuery: {
|
|||
|
current: 1,
|
|||
|
size: 20
|
|||
|
},
|
|||
|
lineList: [],
|
|||
|
headFormConfig: [
|
|||
|
// label: i18n.t('module.dataAnalysis.productionLineBalance.line'),
|
|||
|
// placeholder: this.$t('module.dataAnalysis.productionLineBalance.line'),
|
|||
|
// width: 300,
|
|||
|
{
|
|||
|
type: 'select',
|
|||
|
label: '工厂',
|
|||
|
param: 'factoryId',
|
|||
|
selectOptions: []
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'select',
|
|||
|
label: '产线',
|
|||
|
param: 'productLineIds',
|
|||
|
multiple: true,
|
|||
|
selectOptions: []
|
|||
|
},
|
|||
|
{
|
|||
|
// 对于日期:2022-7-1 ~ 2022-7-1 要转换为 2022/7/1T00:02:00 - 2022/7/2T00:02:00
|
|||
|
type: 'select',
|
|||
|
label: '时间类型',
|
|||
|
param: 'dateFilterType',
|
|||
|
defaultSelect: 0,
|
|||
|
selectOptions: [{ id: 0, name: '按时间段' }, { id: 1, name: '按日期' }],
|
|||
|
index: 2, // 记录下当前配置项的index,省的遍历的开销; index 和 extraOptions 要配合
|
|||
|
extraOptions: [
|
|||
|
{
|
|||
|
elDatePickerKey: '8dkfl', // 防止el-date-picker飞到左上角
|
|||
|
parent: 'dateFilterType',
|
|||
|
// 时间段选择
|
|||
|
type: 'datePicker',
|
|||
|
label: '时间段',
|
|||
|
dateType: 'daterange',
|
|||
|
format: 'yyyy-MM-dd',
|
|||
|
// valueFormat: 'yyyy-MM-dd',
|
|||
|
defaultTime: ['00:00:00', '00:00:00'],
|
|||
|
rangeSeparator: '-',
|
|||
|
startPlaceholder: this.$t('module.dataAnalysis.productionLineBalance.startTime'),
|
|||
|
endPlaceholder: this.$t('module.dataAnalysis.productionLineBalance.endTime'),
|
|||
|
param: 'timeValue'
|
|||
|
},
|
|||
|
{
|
|||
|
elDatePickerKey: '0lkfl',
|
|||
|
parent: 'dateFilterType',
|
|||
|
// 日期选择
|
|||
|
type: 'datePicker',
|
|||
|
label: '日期',
|
|||
|
dateType: 'date',
|
|||
|
placeholder: '选择日期',
|
|||
|
format: 'yyyy-MM-dd',
|
|||
|
// valueFormat: 'yyyy-MM-dd', // 需要返回Date()
|
|||
|
param: 'timeValue'
|
|||
|
}
|
|||
|
]
|
|||
|
},
|
|||
|
{
|
|||
|
type: 'button',
|
|||
|
btnName: 'btn.search',
|
|||
|
name: 'search',
|
|||
|
color: 'primary'
|
|||
|
}
|
|||
|
],
|
|||
|
headFormValue: {},
|
|||
|
showGraph: false
|
|||
|
}
|
|||
|
},
|
|||
|
created() {
|
|||
|
this.fetchList('factory')
|
|||
|
this.fetchList('product-line')
|
|||
|
// this.getList() // 时间间隔必填
|
|||
|
},
|
|||
|
methods: {
|
|||
|
// 获取各种列表
|
|||
|
fetchList(type) {
|
|||
|
switch (type) {
|
|||
|
case 'factory':
|
|||
|
return getFactoryList().then(res => {
|
|||
|
if (res.data) {
|
|||
|
this.headFormConfig[0].selectOptions = res.data.map(factory => ({ id: factory.id, name: factory.name }))
|
|||
|
// 设置defaultSelect
|
|||
|
this.headFormConfig[0].defaultSelect = this.headFormConfig[0].selectOptions[0].id
|
|||
|
}
|
|||
|
})
|
|||
|
case 'product-line':
|
|||
|
return getLineList().then(res => {
|
|||
|
if (res.data) {
|
|||
|
this.headFormConfig[1].selectOptions = res.data.map(line => ({ id: line.id, name: line.name }))
|
|||
|
// 设置defaultSelect
|
|||
|
this.headFormConfig[1].defaultSelect = [this.headFormConfig[1].selectOptions[0].id]
|
|||
|
}
|
|||
|
})
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
// 获取首页列表
|
|||
|
getList() {
|
|||
|
// this.listLoading = true
|
|||
|
|
|||
|
const ftId = this.headFormValue.factoryId ? this.headFormValue.factoryId : ''
|
|||
|
const productlines = this.headFormValue.productLineIds.length ? this.headFormValue.productLineIds : []
|
|||
|
let startTime
|
|||
|
let endTime
|
|||
|
|
|||
|
if (this.headFormValue.timeValue instanceof Array) {
|
|||
|
startTime = this.headFormValue.timeValue[0]
|
|||
|
? moment(this.headFormValue.timeValue[0]).format('YYYY-MM-DDTHH:mm:ss')
|
|||
|
: '' // 强制axios使用北京时间
|
|||
|
endTime = this.headFormValue.timeValue[1]
|
|||
|
? moment(this.headFormValue.timeValue[1]).format('YYYY-MM-DDTHH:mm:ss')
|
|||
|
: ''
|
|||
|
} else {
|
|||
|
if (this.headFormValue.timeValue) {
|
|||
|
startTime = moment(this.headFormValue.timeValue)
|
|||
|
.add(2, 'm')
|
|||
|
.format('YYYY-MM-DDTHH:mm:ss')
|
|||
|
endTime = moment(startTime)
|
|||
|
.add(1, 'd')
|
|||
|
.format('YYYY-MM-DDTHH:mm:ss')
|
|||
|
} else {
|
|||
|
startTime = ''
|
|||
|
endTime = ''
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
getOEE({ ...this.listQuery, type: 1, ftId, productlines, startTime, endTime })
|
|||
|
.then(res => {
|
|||
|
this.dataList = res.data
|
|||
|
// this.listLoading = false
|
|||
|
})
|
|||
|
.catch(err => {
|
|||
|
if (err.message === '该时间段内设备未连接到数据库') {
|
|||
|
this.dataList.splice(0)
|
|||
|
}
|
|||
|
})
|
|||
|
},
|
|||
|
|
|||
|
// 顶部查询按钮
|
|||
|
btnClick(val) {
|
|||
|
this.headFormValue = val
|
|||
|
if (this.headFormValue.btnName === 'search') {
|
|||
|
this.getList()
|
|||
|
}
|
|||
|
this.showGraph = false
|
|||
|
},
|
|||
|
// handlers
|
|||
|
handleTableEvents({ action, data }) {
|
|||
|
// 有查看趋势,和保留待用的OEE对比图(此者暂时不做)
|
|||
|
switch (action) {
|
|||
|
case 'view-trend':
|
|||
|
this.viewTrends(data)
|
|||
|
break
|
|||
|
case 'view-oee-compare':
|
|||
|
break
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
viewTrends(data) {
|
|||
|
const startTime = this.headFormValue.timeValue[0]
|
|||
|
? moment(this.headFormValue.timeValue[0]).format('YYYY-MM-DDTHH:mm:ss')
|
|||
|
: '' // 强制axios使用北京时间
|
|||
|
const endTime = this.headFormValue.timeValue[1]
|
|||
|
? moment(this.headFormValue.timeValue[1]).format('YYYY-MM-DDTHH:mm:ss')
|
|||
|
: ''
|
|||
|
const injectData = {
|
|||
|
// 时间段
|
|||
|
startTime,
|
|||
|
endTime,
|
|||
|
// 设备id
|
|||
|
equipmentId: data.eqId,
|
|||
|
equipmentName: data.eqName,
|
|||
|
// 时间类型, type 按年,按月,按日等
|
|||
|
type: 1, // 默认 type 1, 1无间隔;2按月分隔;3按周分隔;4按天分隔
|
|||
|
// 时长数据: 工作时长, 停机时长,故障时长
|
|||
|
workTime: data.workTime,
|
|||
|
stopTime: data.stopTime,
|
|||
|
downTime: data.downTime,
|
|||
|
// 比例数据: 工作时长比率,停机时长比率,故障时长比率,速度开动率,OEE,TEEP
|
|||
|
workRate: data.workRate,
|
|||
|
stopRate: data.stopRate,
|
|||
|
downRate: data.downRate,
|
|||
|
peEfficiency: data.peEfficiency
|
|||
|
}
|
|||
|
console.log('trends data: ', data)
|
|||
|
|
|||
|
this.showGraph = true
|
|||
|
|
|||
|
setTimeout(() => {
|
|||
|
console.log('befoer graph: ', this.$refs.eegraph)
|
|||
|
this.$refs.eegraph.init(injectData) // 注入初始数据,这些数据在组件内部用作条件,有可能会被更改
|
|||
|
}, 600) // 动画是500ms
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
<style scoped>
|
|||
|
.slide-to-left-enter-active,
|
|||
|
.slide-to-left-leave-active {
|
|||
|
transition: all 0.5s;
|
|||
|
}
|
|||
|
|
|||
|
.slide-to-left-enter {
|
|||
|
transform: translateX(10px);
|
|||
|
opacity: 0;
|
|||
|
}
|
|||
|
|
|||
|
.slide-to-left-leave-to {
|
|||
|
transform: translateX(-10px);
|
|||
|
opacity: 0;
|
|||
|
}
|
|||
|
|
|||
|
.slide-to-left-leave,
|
|||
|
.slide-to-left-enter-to {
|
|||
|
transform: translateX(0);
|
|||
|
}
|
|||
|
</style>
|