update 设备状态时序图

This commit is contained in:
g7hoo 2022-09-22 11:18:48 +08:00
parent 1ad64efe59
commit 399589bb3b

View File

@ -4,13 +4,15 @@
<el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()"> <el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()">
<!-- 产线 --> <!-- 产线 -->
<el-form-item> <el-form-item>
<el-select v-model="dataForm.productlines" :placeholder="'产线'" clearable /> <el-select v-model="dataForm.productlines" :placeholder="'产线'" @change="handleProductLineChange" clearable>
<el-option v-for="productLine in productLineList" :key="productLine.id" :value="productLine.id" :label="productLine.name" />
</el-select>
</el-form-item> </el-form-item>
<!-- 工序 --> <!-- 工序 -->
<el-form-item> <el-form-item>
<!-- <el-select v-model="dataForm.factoryId" :placeholder="$t('eq.name') + ' / ' + $t('eq.code')" clearable></el-select> --> <!-- <el-select v-model="dataForm.factoryId" :placeholder="$t('eq.name') + ' / ' + $t('eq.code')" clearable></el-select> -->
<el-select v-model="dataForm.ftId" :placeholder="'工序'" clearable> <el-select v-model="dataForm.wsId" :placeholder="'工序'" clearable>
<el-option v-for="factory in factoryList" :key="factory.id" :value="factory.id" :label="factory.name" /> <el-option v-for="ws in wsList" :key="ws.id" :value="ws.id" :label="ws.name" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 日期选择 --> <!-- 日期选择 -->
@ -24,107 +26,168 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<base-table :data="dataList" :table-head-configs="tableConfigs" :max-height="calcMaxHeight(8)" @operate-event="handleOperations" @refreshDataList="getDataList" /> <div class="time-chart" style="margin-top: 10px;">
<el-pagination <div
@size-change="sizeChangeHandle" v-show="equipmentCount > 0"
@current-change="currentChangeHandle" id="time-chart__inner"
:current-page="pageIndex" ref="time-chart__inner"
:page-sizes="[10, 20, 50, 100]" class="time-chart__inner"
:page-size="pageSize" style="width: 100%; min-height: 50vh;"
:total="totalPage" :style="{ height: autoHeight + 'px' }"
layout="total, sizes, prev, pager, next, jumper" />
></el-pagination> <div v-show="equipmentCount === 0">请先查询数据</div>
<!-- <div v-show="equipmentCount === 0">{{ $t('module.basicData.visual.hints.searchFirst') }}</div> -->
</div>
</div> </div>
</template> </template>
<script> <script>
import i18n from '@/i18n' import * as echarts from 'echarts'
// import i18n from '@/i18n'
import BaseTable from '@/components/base-table' import BaseTable from '@/components/base-table'
import TableOperateComponent from '@/components/base-table/components/operationComponent'
import TableTextComponent from '@/components/base-table/components/detailComponent'
import { calcMaxHeight } from '@/utils' import { calcMaxHeight } from '@/utils'
import { timeFilter } from '@/utils/filters'
import moment from 'moment' import moment from 'moment'
// import TableOperateComponent from '@/components/base-table/components/operationComponent'
// import TableTextComponent from '@/components/base-table/components/detailComponent'
// import { timeFilter } from '@/utils/filters'
const tableConfigs = [ function renderItem(params, api) {
var categoryIndex = api.value(0)
var start = api.coord([api.value(1), categoryIndex])
var end = api.coord([api.value(2), categoryIndex])
var height = 32
return {
type: 'rect',
shape: echarts.graphic.clipRectByRect(
{ {
type: 'index', x: start[0],
name: i18n.t('index') y: start[1] - height / 2,
width: end[0] - start[0],
height: height
}, },
{ {
// name: i18n.t('createTime'), x: params.coordSys.x,
prop: 'factoryName', y: params.coordSys.y,
name: '工厂' width: params.coordSys.width,
height: params.coordSys.height
}
),
style: api.style()
}
}
class ChartOption {
constructor() {
this.color = ['#4caf50', '#ffb300', '#e53935']
this.legend = {
data: [
// i18n.t('module.basicData.visual.echartLegends.working'),
'正常',
'停机',
'故障'
],
bottom: '0%',
selectedMode: false,
textStyle: {
color: '#000'
}
}
this.tooltip = {
formatter: function(params) {
return moment(params.value[1]).format('YYYY-MM-DD HH:mm:ss') + ' - ' + moment(params.value[2]).format('YYYY-MM-DD HH:mm:ss') + ' : ' + params.name
}
}
this.title = {
// text: i18n.t('module.basicData.visual.echartTitles.eqStatus'),
text: '设备状态时序图',
left: 'center'
}
this.xAxis = {
type: 'time',
// min: +new Date().setHours(0, 0, 0, 0),
splitNumber: 24,
interval: 3600 * 1000,
axisTick: {
show: true,
alignWithLabel: true
}, },
{ prop: 'pdName', name: '产线' }, axisLine: {
{ prop: 'wsName', name: '工段' }, show: true
{ prop: 'eqName', name: '设备' },
{
name: '有效时间(h)',
children: [
{ prop: 'workTime', name: '工作时长(h)', width: 120, filter: val => `${val} 小时` },
{ prop: 'workRate', name: '工作时长比率', width: 120, filter: val => (val * 100).toFixed(2) + '%' }
]
}, },
axisLabel: {
formatter: function(val) {
const time = new Date(val)
const hour = time.getHours()
const minute = time.getMinutes()
const hours = hour >= 10 ? hour + '' : '0' + hour
const minutes = minute >= 10 ? minute + '' : '0' + minute
return hours + ':' + minutes
}
}
}
this.yAxis = {
// data: Object.keys(eqData).map(item => eqData[item].name)
data: []
}
this.series = [
{ name: /** i18n.t('module.basicData.visual.echartLegends.working') */ '正常', type: 'bar', data: [] },
{ name: '停机', type: 'bar', data: [] },
{ name: '故障', type: 'bar', data: [] },
{ {
name: '关机时间(h)', type: 'custom',
children: [ renderItem: renderItem,
{ prop: 'stopTime', name: '停机时长(h)', width: 120, filter: val => `${val} 小时` }, itemStyle: {
{ prop: 'stopRate', name: '停机比率', width: 120, filter: val => (val * 100).toFixed(2) + '%' } opacity: 0.8
]
}, },
{ encode: {
name: '中断损失', x: [1, 2],
children: [ y: 0
{ prop: 'downTime', name: '故障时长(h)', width: 120, filter: val => `${val} 小时` },
{ prop: 'downRate', name: '故障比率', width: 120, filter: val => (val * 100).toFixed(2) + '%' },
{ prop: 'timeEfficiency', name: '时间开动率', width: 120, filter: val => (val * 100).toFixed(2) + '%' }
]
}, },
{ data: []
name: '速度损失',
children: [
{ prop: 'realYield', name: '实际加工速度', width: 120, filter: val => `${val} 小时` },
{ prop: 'designYield', name: '理论加工速度', width: 120, filter: val => `${val} 小时` },
{ prop: 'peEfficiency', name: '速度开动率', width: 120, filter: val => (val * 100).toFixed(2) + '%' }
]
},
{
name: 'OEE',
prop: 'oee',
filter: val => (val * 100).toFixed(2) + '%'
},
{
name: 'TEEP',
prop: 'teep',
filter: val => (val * 100).toFixed(2) + '%'
},
{
prop: 'operations',
name: i18n.t('handle'),
fixed: 'right',
width: 180,
subcomponent: TableOperateComponent,
// options: ['edit', 'delete']
options: ['view-trend'] //
} }
] ]
}
setTitle(title) {
this.title.text = title
}
// date:
setXAxis(date) {
// this.xAxis.min = +new Date(date).setHours(0)
this.xAxis.min = +new Date(date).setHours(0, 0, 0, 0)
this.xAxis.max = this.xAxis.min + 3600 * 1000 * 24
}
setYAxis(data) {
this.yAxis.data = data
}
setData(data) {
this.series[3].data = data
}
}
export default { export default {
data() { data() {
return { return {
/** hfxny part */ /** hfxny part */
factoryList: [], wsList: [],
productLineList: [], productLineList: [],
/** */ chart: null,
chartOption: new ChartOption(),
equipments: {},
state: ['正常', '停机', '故障'],
colors: ['#4caf50', '#ffb300', '#e53935'],
queryBuffer: {},
// tableConfigs,
calcMaxHeight, calcMaxHeight,
tableConfigs,
timeType: 'range', timeType: 'range',
rawTime: null, // [] or datetime currentLine: null,
rawTime: null,
dataForm: { dataForm: {
type: 1, wsId: null,
ftId: null,
productlines: [], productlines: [],
startTime: null, startTime: null,
entTime: null entTime: null
@ -139,10 +202,18 @@ export default {
components: { components: {
BaseTable BaseTable
}, },
computed: {
autoHeight: function() {
return Object.keys(this.equipments).length * 100 || 500
},
equipmentCount: function() {
return Object.keys(this.equipments).length
}
},
created() { created() {
this.getFactoryList() this.getProductLineList().then(() => {
this.getProductLineList() this.getWorksetionList()
})
}, },
watch: { watch: {
timeType() { timeType() {
@ -151,27 +222,14 @@ export default {
} }
}, },
methods: { methods: {
// initChart() {
getFactoryList() { if (!this.chart) {
this.$http({ this.chart = echarts.init(this.$refs['time-chart__inner'])
url: this.$http.adornUrl('/monitoring/factory/page'),
method: 'get'
}).then(({ data }) => {
if (data && data.code === 0) {
this.factoryList = data.data.list
/** set default */
if (this.factoryList.length) {
this.dataForm.ftId = this.factoryList[0].id
} }
} else {
this.factoryList = []
this.dataForm.ftId = null
}
})
}, },
// 线 // 线
getProductLineList() { getProductLineList() {
this.$http({ return this.$http({
url: this.$http.adornUrl('/monitoring/productionLine/page'), url: this.$http.adornUrl('/monitoring/productionLine/page'),
method: 'get' method: 'get'
}).then(({ data }) => { }).then(({ data }) => {
@ -179,7 +237,7 @@ export default {
this.productLineList = data.data.list this.productLineList = data.data.list
/** set default */ /** set default */
if (this.productLineList.length) { if (this.productLineList.length) {
this.dataForm.productlines = [this.productLineList[0].id] this.dataForm.productlines = this.productLineList[0].id
} }
} else { } else {
this.productLineList = [] this.productLineList = []
@ -187,55 +245,116 @@ export default {
}) })
}, },
// //
getTimeRange() { getWorksetionList() {
let startTime // 线
let endTime this.$http({
if (this.rawTime instanceof Array) { // url: this.$http.adornUrl('/monitoring/workshopSection/list'),
startTime = this.rawTime[0] ? moment(this.rawTime[0]).format('YYYY-MM-DDTHH:mm:ss') : '' // axios使 url: this.$http.adornUrl('/monitoring/workshopSection/page'),
endTime = this.rawTime[1] ? moment(this.rawTime[1]).format('YYYY-MM-DDTHH:mm:ss') : '' method: 'get',
params: this.$http.adornParams({
limit: 99999,
page: 1,
lineId: this.dataForm.productlines ?? ''
})
}).then(({ data: res }) => {
if (res && res.code === 0) {
this.wsList = res.data.list
/** set default */
if (this.wsList.length) {
this.dataForm.wsId = this.wsList[0].id
}
} else { } else {
if (this.rawTime) { this.wsList.splice(0)
startTime = moment(this.rawTime).format('YYYY-MM-DDTHH:mm:ss') this.dataForm.wsId = '' // <== ...
endTime = moment(startTime) }
.add(1, 'd') })
.format('YYYY-MM-DDTHH:mm:ss') },
//
transformDataToEquipments(dataList) {
console.log('transformDataToEquipments() datalist: ', dataList)
const equipments = {}
dataList.map(item => {
if (equipments[item.eqId]) {
//
equipments[item.eqId].name = item.eqName
equipments[item.eqId].status.push({
startTime: +new Date(item.startTime),
endTime: +new Date(item.endTime),
status: this.state[item.status] // 0 1 2
})
} else { } else {
startTime = '' equipments[item.eqId] = {
endTime = '' name: item.eqName,
status: [
{
startTime: +new Date(item.startTime),
endTime: +new Date(item.endTime),
status: this.state[item.status] // 0 1 2
}
]
} }
} }
return { startTime, endTime } })
// console.log('items --- ', equipments)
return equipments
},
// echartsseries
transformEquipmentsToSeries(equipments) {
const seriesData = []
Object.entries(equipments).map(([key, item], index) => {
item.status.forEach(status => {
seriesData.push({
name: status.status,
value: [index, status.startTime, status.endTime],
itemStyle: {
normal: {
color: status.status === '正常' ? '#4caf50' : status.status === '停机' ? '#ffb300' : status.status === '故障' ? '#e53935' : null
}
}
})
})
})
return seriesData
}, },
// //
getDataList() { getDataList() {
const { startTime, endTime } = this.getTimeRange() let startTime = this.rawTime
? moment(this.rawTime)
.set({ date: 1, hour: 0, minute: 0, second: 0, millisecond: 0 })
.format('YYYY-MM-DDTHH:mm:ss')
: ''
let endTime = startTime
? moment(startTime)
.add(1, 'M')
.format('YYYY-MM-DDTHH:mm:ss')
: ''
this.dataListLoading = true this.dataListLoading = true
this.$http({ this.$http({
url: this.$http.adornUrl('/monitoring/eqAnalysis/oee'), url: this.$http.adornUrl('/monitoring/eqAnalysis/timeAndStatus'),
method: 'post', method: 'post',
data: { data: {
startTime, startTime,
endTime, endTime,
ftId: this.dataForm.ftId, productlines: [this.dataForm.productlines],
productlines: this.dataForm.productlines, wsId: this.dataForm.wsId
limit: this.pageIndex,
page: this.pageSize,
type: 1
} }
}).then(({ data: res }) => { }).then(({ data: res }) => {
console.log('oee data:', res) if (res.code === 500) {
if (res.length) {
this.dataList = res
this.totalPage = res.length
} else {
this.dataList.splice(0) this.dataList.splice(0)
this.totalPage = 0 this.$message.error(res.msg)
} else {
this.dataList = res.data
} }
}) })
}, },
handleProductLineChange(val) {
console.log('handleProductLineChange', this.dataForm.productlines)
this.getWorksetionList()
},
// //
sizeChangeHandle(val) { sizeChangeHandle(val) {
this.pageSize = val this.pageSize = val