forked from mt-fe-group/mt-yd-ui
update 设备状态时序图
This commit is contained in:
parent
1ad64efe59
commit
399589bb3b
@ -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)
|
||||||
type: 'index',
|
var start = api.coord([api.value(1), categoryIndex])
|
||||||
name: i18n.t('index')
|
var end = api.coord([api.value(2), categoryIndex])
|
||||||
},
|
var height = 32
|
||||||
{
|
|
||||||
// name: i18n.t('createTime'),
|
return {
|
||||||
prop: 'factoryName',
|
type: 'rect',
|
||||||
name: '工厂'
|
shape: echarts.graphic.clipRectByRect(
|
||||||
},
|
{
|
||||||
{ prop: 'pdName', name: '产线' },
|
x: start[0],
|
||||||
{ prop: 'wsName', name: '工段' },
|
y: start[1] - height / 2,
|
||||||
{ prop: 'eqName', name: '设备' },
|
width: end[0] - start[0],
|
||||||
{
|
height: height
|
||||||
name: '有效时间(h)',
|
},
|
||||||
children: [
|
{
|
||||||
{ prop: 'workTime', name: '工作时长(h)', width: 120, filter: val => `${val} 小时` },
|
x: params.coordSys.x,
|
||||||
{ prop: 'workRate', name: '工作时长比率', width: 120, filter: val => (val * 100).toFixed(2) + '%' }
|
y: params.coordSys.y,
|
||||||
]
|
width: params.coordSys.width,
|
||||||
},
|
height: params.coordSys.height
|
||||||
{
|
}
|
||||||
name: '关机时间(h)',
|
),
|
||||||
children: [
|
style: api.style()
|
||||||
{ prop: 'stopTime', name: '停机时长(h)', width: 120, filter: val => `${val} 小时` },
|
|
||||||
{ prop: 'stopRate', name: '停机比率', width: 120, filter: val => (val * 100).toFixed(2) + '%' }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '中断损失',
|
|
||||||
children: [
|
|
||||||
{ 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) + '%' }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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'] // 查看趋势
|
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
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: [] },
|
||||||
|
{
|
||||||
|
type: 'custom',
|
||||||
|
renderItem: renderItem,
|
||||||
|
itemStyle: {
|
||||||
|
opacity: 0.8
|
||||||
|
},
|
||||||
|
encode: {
|
||||||
|
x: [1, 2],
|
||||||
|
y: 0
|
||||||
|
},
|
||||||
|
data: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
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',
|
||||||
} else {
|
params: this.$http.adornParams({
|
||||||
if (this.rawTime) {
|
limit: 99999,
|
||||||
startTime = moment(this.rawTime).format('YYYY-MM-DDTHH:mm:ss')
|
page: 1,
|
||||||
endTime = moment(startTime)
|
lineId: this.dataForm.productlines ?? ''
|
||||||
.add(1, 'd')
|
})
|
||||||
.format('YYYY-MM-DDTHH:mm:ss')
|
}).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 {
|
||||||
startTime = ''
|
this.wsList.splice(0)
|
||||||
endTime = ''
|
this.dataForm.wsId = '' // <== 不起作用...
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
return { startTime, endTime }
|
},
|
||||||
|
|
||||||
|
// 把服务器数据按照设备分组
|
||||||
|
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 {
|
||||||
|
equipments[item.eqId] = {
|
||||||
|
name: item.eqName,
|
||||||
|
status: [
|
||||||
|
{
|
||||||
|
startTime: +new Date(item.startTime),
|
||||||
|
endTime: +new Date(item.endTime),
|
||||||
|
status: this.state[item.status] // 0 正常、1 停机、2 故障
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// console.log('items --- ', equipments)
|
||||||
|
return equipments
|
||||||
|
},
|
||||||
|
// 把分组好的设备数据转换为echarts需要的series数据
|
||||||
|
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
|
||||||
|
Loading…
Reference in New Issue
Block a user