mt-yd-ui/src/views/modules/monitoring/productAnalysis.vue
2023-03-24 17:23:26 +05:30

720 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="mod-config">
<el-form :inline="true" @keyup.enter.native="getDataList()" class="blueTip" size="small">
<el-form-item>
{{ $t('pl.name') }}
</el-form-item>
<el-form-item>
<el-select v-model="lineIds" :placeholder="$t('pl.name')" clearable filterable multiple>
<el-option v-for="line in lineList" :key="line.code" :value="line.id" :label="line.name" />
</el-select>
</el-form-item>
<el-form-item>
{{ $t('time') }}
</el-form-item>
<el-form-item>
<!-- type="datetimerange" -->
<!-- <el-date-picker
type="daterange"
v-model="datetime"
value-format="yyyy-MM-ddTHH:mm:ss"
:start-placeholder="$t('startTime')"
:end-placeholder="$t('endTime')"
:range-separator="$t('to')"
:default-time="['00:00:00', '23:59:59']"
:picker-options="quickOptions"
clearable /> -->
<el-date-picker v-model="datetime" type="month" :placeholder="$t('hints.date')" format="yyyy-MM" value-format="yyyy-MM" />
</el-form-item>
<el-form-item>
<el-button class="buttonColor" @click="getDataList()">{{ $t('query') }}</el-button>
<!-- <el-button v-if="$hasPermission('monitoring:qualityinspectionrecord:save')" type="primary" @click="addOrUpdateHandle()">{{ $t('add') }}</el-button> -->
</el-form-item>
</el-form>
<div class="quality-inspection-current base-container">
<!-- <el-row>
<el-col>
<small-title :size="'md'">{{ $t('inspect.ioTotal') }}</small-title>
<el-row style="margin-top: 12px;">
<base-table :data="dataListStatic" :table-head-configs="tableConfigStatic" :max-height="500" @operate-event="handleOperations" @refreshDataList="getDataList" />
</el-row>
</el-col>
</el-row> -->
<!-- style="margin-top: 28px;" -->
<el-row>
<el-col>
<el-row>
<small-title :size="'md'">{{ $t('eq.productionAnalysis') }}</small-title>
</el-row>
<!-- <el-row style="margin-top: 8px">
<el-radio-group v-model="dataType" size="medium" @change="handleDataTypeChange">
<el-radio-button :label="$t('table2')"></el-radio-button>
<el-radio-button :label="$t('graph')"></el-radio-button>
</el-radio-group>
</el-row> -->
<!-- style="margin-top: 12px" -->
<el-row>
<!-- v-if="!showGraph" -->
<base-table :data="dataList" :table-head-configs="tableConfigDynamic" :max-height="500" @operate-event="handleOperations" @refreshDataList="getDataList" />
</el-row>
<!-- :series-data="echartsData" -->
<!-- v-else -->
<el-row style="margin-top: 8px">
<fake-chart
:categories="echartCategories"
:type-list="echartCheckTypes"
:series-data1="echartsData1"
:series-data2="echartsData2"
:series-data3="echartsData3"
:series-data4="echartsData4" />
</el-row>
</el-col>
</el-row>
</div>
</div>
</template>
<script>
import { calcMaxHeight } from '@/utils'
import { timeFilter } from '@/utils/filters'
import moment from 'moment'
import i18n from '@/i18n'
import BaseTable from '@/components/base-table'
import SmallTitle from '@/components/small-title'
import * as echarts from 'echarts'
// const tableConfigStatic = [
// { type: 'index', width: 100, name: i18n.t('index') },
// { name: i18n.t('pl.title'), prop: 'lineName' },
// { name: i18n.t('inspect.inTotal'), prop: 'sumUp' },
// { name: i18n.t('inspect.outTotal'), prop: 'sumDown' },
// { name: i18n.t('inspect.checkTotal'), prop: 'sumCheck' },
// { name: i18n.t('inspect.rate'), prop: 'scrapRatio', filter: (val) => (val || val === 0 ? `${val}%` : '-') }
// ]
const tableConfigDynamic = [
{ type: 'index', width: 100, name: i18n.t('index') },
{ name: i18n.t('pl.name'), prop: '0' }
]
const FakeChart = {
name: 'FakeChart',
props: {
categories: {
type: Array,
default: () => []
},
typeList: {
type: Array,
default: () => []
},
seriesData1: {
type: Array,
default: () => []
},
seriesData2: {
type: Array,
default: () => []
},
seriesData3: {
type: Array,
default: () => []
},
seriesData4: {
type: Array,
default: () => []
}
},
data() {
return {
calcMaxHeight,
chart: null,
// 新加
echartsData1: [],
echartsData2: [],
echartsData3: [],
echartsData4: [],
pass: [],
defaultOpts: {
grid: {
left: '5%',
right: '12%',
top: '20%',
bottom: '10%'
},
title: {
text: i18n.t('eq.productQuantity')
},
tooltip: {
trigger: 'axis', //坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用
axisPointer: {
// 坐标轴指示器,坐标轴触发有效
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
legend: {
orient: 'vertical',
type: 'scroll',
top: 10,
right: 0,
width: '12%',
/** 修复文本太长时显示问题 */
// formatter: function (name) {
// return echarts.format.truncateText(name, 120, '14px Microsoft Yahei', '...')
// },
tooltip: {
show: true
},
/** end */
data: []
// selected:{'产线1':(this.echartsData1 === [] ? false : true) , 'Line 1':(this.echartsData1 === [] ? false : true) ,
// '产线2':(this.echartsData2 === [] ? false : true) , 'Line 2':(this.echartsData2 === [] ? false : true) }
},
xAxis: {
type: 'category',
data: [],
// axisLine: {
// show: true,
// lineStyle: {
// color: 'rgba(219,225,255,1)',
// width: 1,
// type: 'solid'
// }
// },
axisLabel: {
//设置x轴的字
show: true,
rotate: 0,
interval: 0 //使x轴横坐标全部显示
// textStyle: {
// //x轴字体样式
// color: 'rgba(219,225,255,1)',
// margin: 15
// }
}
// data: ['下片1', '上片1', '磨边机1', '设备13', '钢化炉2', '磨边机2', '设备15', '清洗机1', '钢化炉3']
},
yAxis: {
type: 'value'
},
series: [
// dynamic
{
name: this.$t('eq.line1'),
type: 'line',
data: [],
label: {
normal: {
show: true,
position: 'top'
},
formatter: '{@value}'
}
},
{
name: this.$t('eq.line2'),
type: 'line',
data: [],
label: {
normal: {
show: true,
position: 'top'
},
formatter: '{@value}'
}
},
{
name: this.$t('eq.line3'),
type: 'line',
data: [],
label: {
normal: {
show: true,
position: 'top'
},
formatter: '{@value}'
}
},
{
name: this.$t('eq.line4'),
type: 'line',
data: [],
label: {
normal: {
show: true,
position: 'top'
},
formatter: '{@value}'
}
}
// {
// data: [120, 200, 150, 80, 70, 110, 130],
// type: 'bar'
// }
]
}
}
},
watch: {
categories: {
handler: function (val, oldVal) {
if (val && val !== oldVal) {
// this.defaultOpts.xAxis.data.push(...val)
this.defaultOpts.xAxis.data = val
}
},
immediate: true
},
typeList: {
handler: function (val, oldVal) {
if (val && val !== oldVal) {
// this.defaultOpts.legend.data.push(...val)
this.defaultOpts.legend.data = val
}
},
immediate: true
},
seriesData1: {
// this.defaultOpts.series[0].data.push 会循环增加横坐标和数据,改成 =
handler: function (val, oldVal) {
if (val && val !== oldVal) {
// this.defaultOpts.series[0].data.push(...val)
this.defaultOpts.series[0].data = val
}
},
immediate: true
},
seriesData2: {
handler: function (val, oldVal) {
if (val && val !== oldVal) {
// this.defaultOpts.series[1].data.push(...val)
this.defaultOpts.series[1].data = val
}
},
immediate: true
},
seriesData3: {
// this.defaultOpts.series[0].data.push 注意
handler: function (val, oldVal) {
if (val && val !== oldVal) {
// this.defaultOpts.series[2].data.push(...val)
this.defaultOpts.series[2].data = val
}
},
immediate: true
},
seriesData4: {
handler: function (val, oldVal) {
if (val && val !== oldVal) {
// this.defaultOpts.series[3].data.push(...val)
this.defaultOpts.series[3].data = val
}
},
immediate: true
},
defaultOpts: {
handler: function (val) {
// console.log('defaullt opts change: ', val)
this.setOptions()
},
immediate: true,
deep: true
}
},
mounted() {
this.$nextTick(() => {
// console.log('echarts data1: ', this.echartsData1)
// console.log('echarts data2: ', this.echartsData2)
// console.log('echarts data3: ', this.echartsData3)
// console.log('echarts data4: ', this.echartsData4)
this.initChart()
// console.log('this.defaultOpts.xAxis.data', this.defaultOpts.xAxis.data)
this.setOptions()
window.addEventListener('resize', () => {
//监听浏览器窗口大小
this.chart.resize()
})
})
},
methods: {
initChart() {
if (!this.chart) {
this.chart = echarts.init(document.getElementById('bar-chart'))
this.chart.resize()
}
},
setOptions(opts) {
/** prop options */
if (opts) {
}
if (this.chart) this.chart.setOption(this.defaultOpts, true)
}
},
render: function (h) {
return h('div', { attrs: { id: 'bar-chart' }, style: { background: '#eee', width: '100%', height: '300px', padding: '8px' } }, '')
}
}
const dict = [i18n.t('table2'), i18n.t('graph')]
export default {
name: 'QualityInspectionCurrent',
components: { BaseTable, SmallTitle, FakeChart },
data() {
return {
echartsData1: [],
echartsData2: [],
echartsData3: [],
echartsData4: [],
count: 0,
lineIds: [],
lineList: [],
// tableConfigStatic,
tableConfigDynamic,
datetime: new Date(),
dataListStatic: [],
dataListDynamic: [],
dataList: [],
dict,
dataType: dict[0], // 表格 | 图形
showGraph: false,
// quickOptions: {
// shortcuts: [
// {
// text: i18n.t('today'),
// onClick(picker) {
// const baseTime = moment().set({ hour: 0, minute: 0, second: 0, millisecond: 0 })
// const startTime = baseTime.format('yyyy-MM-DDTHH:mm:ss')
// const endTime = baseTime.set({ hour: 23, minute: 59, second: 59, millisecond: 999 }).format('yyyy-MM-DDTHH:mm:ss')
// picker.$emit('pick', [startTime, endTime])
// }
// }
// ]
// },
echartCategories: null,
echartCheckTypes: [],
interval: null
}
},
created() {
this.getLineList()
// this.getDataList()
this.interval = setInterval(() => {
this.$message.info(i18n.t('refresh'))
// this.dataListStatic.splice(0)
this.dataListDynamic.splice(0)
this.getDataList()
}, 1000 * 5 * 60)
},
deactivated() {
if (this.interval) {
clearInterval(this.interval)
this.interval = null
}
},
methods: {
// 产线
getLineList() {
this.$http({
url: this.$http.adornUrl('/monitoring/productionLine/list'),
method: 'get'
}).then(({ data }) => {
if (data && data.code === 0) {
this.lineList = data.data
// console.log('产线数组', this.lineList)
/** set default 默认 */
// if (this.lineList.length) {
// this.lineIds = [this.lineList[this.lineList.length - 1].id]
// }
} else {
this.lineList = []
}
// 这样可以出数据
this.getDataList()
})
},
handleOperations() {},
handleDataTypeChange(value) {
this.showGraph = value === dict[0] ? false : true
},
getDataList() {
// for (var z = 0; z < this.defaultOpts.series.length; z++) {
// this.defaultOpts.series[z].data = []
// }
// this.echartCategories = []
// 下面全部要初始化,清空数据
this.echartsData1 = []
this.echartsData2 = []
this.echartsData3 = []
this.echartsData4 = []
this.dataListDynamic = []
this.dataList = []
this.count = 0
this.showGraph = false
this.dataType = i18n.t('table2')
this.echartCategories = null
this.echartCheckTypes.splice(0)
/** 设置默认日期 */
// const startTime = this.datetime[0] || moment().set({ hour: 0, minute: 0, second: 0 }).format('yyyy-MM-DDTHH:mm:ss')
// const endTime = this.datetime[1] || moment().set({ hour: 23, minute: 59, second: 59 }).format('yyyy-MM-DDTHH:mm:ss')
// console.log('this.datatime',this.datatime)
// const startTime = this.datetime ? this.datetime + '-01T00:00:00' : null
const startTime = this.datetime ? moment(this.datetime).format('YYYY-MM') + '-01T00:00:00' : null
// const endTime = this.datetime ? moment(this.datetime).format('YYYY-MM-DD') + 'T23:59:59' : null
const endTime = this.datetime ? this.getMonthSE(moment(this.datetime).format('YYYY-MM')) + 'T23:59:59' : null
/** 获取产品质量分析数据 */
// this.fetchList(startTime, endTime, lineIds).then(({ data: res }) => {
this.$http({
url: this.$http.adornUrl('/monitoring/eqAnalysis/productAnalysis'),
method: 'POST',
data: {
startTime,
endTime,
// 加个判断防止为空时传参[]报错
lineIds: this.lineIds.length == 0 ? null : this.lineIds
// lineIds: this.lineIds.length == 0 ? ["1"] : this.lineIds
}
})
.then((res) => {
// console.log('res: ', res)
/** TODO: 解析 nameData */
// 新加
this.tableConfigDynamic = [
{ type: 'index', width: 100, name: i18n.t('index') },
{ name: i18n.t('pl.name'), prop: '0' },
{ name: i18n.t('pl.sum'), prop: '1' },
...Array.from(new Set(res.data.data[0].records.map((item) => moment(item.recordTime).format('MM-DD')))).map((name) => ({ prop: String(++this.count + 1), name }))
/**
这一行无敌的,记一下:
1. '...'是扩展运算符是ES6的语法用于取出参数对象的所有可遍历属性然后拷贝到当前对象之中。例如
let foo = { ...['a', 'b', 'c'] };
foo
// {0: "a", 1: "b", 2: "c"}
2.Array.from(new Set())是JS的数组去重
3.map() 方法定义在JavaScript的Array中它返回一个新的数组数组中的元素为原始数组调用函数处理后的值。
4.moment(time).format()时间格式化
5.String(),因为prop只能接收String,需要把数字转化
6.++this.count是定义了个从0开始自增的常量count用来标注一个月每天的下标this.count++会从每个月2号开始因此是 ++this.count
7.要在getDataList() 中
this.dataList = []
this.count = 0
初始化一下,否则连续按按钮会空一个
8.因为后期加了个"合计"字段,所以++this.count + 1右移一位
*/
]
// console.log('this.tableConfigDynamic', this.tableConfigDynamic)
// this.dataListDynamic = this.parseDynamicData(res.data.data) || []
for (let i = 0; i < res.data.data.length; i++) {
this.dataListDynamic[i] = res.data.data[i].records.map((item) => item.outputNum) || []
this.dataListDynamic[i].unshift(res.data.data[i].sum)
this.dataListDynamic[i].unshift(res.data.data[i].records[i].lineName)
var json = {}
for (var j = 0; j < this.dataListDynamic[i].length; j++) {
json[j] = this.dataListDynamic[i][j]
}
this.dataList.push(json)
// console.log('this.dataList', this.dataList)
// this.dataListDynamic[i] =JSON.stringify(this.dataListDynamic[i])
}
/** echarts related */
// this.echartCategories = subProps.map((item) => item.name)
// console.log('res.data.data[0].records.map((item) => moment(item.recordTime)',res.data.data[0].records.map((item) => moment(item.recordTime).format('MM-DD')));
// 创建横坐标
this.echartCategories = res.data.data[0].records.map((item) => moment(item.recordTime).format('MM-DD'))
// this.parseTableProps(res.data.nameData)
// console.log('this.echartCategories', this.echartCategories)
// console.log('this.dataListDynamic', this.dataListDynamic)
// console.log('this.dataList', this.dataList)
this.buildGraphData()
})
.catch((err) => {
// 忽略掉0报错
// console.error(err)
})
},
setOptions(opts) {
/** prop options */
if (opts) {
}
if (this.chart) this.chart.setOption(this.defaultOpts, true)
},
// 失效函数
parseTableProps(nameData) {
const subProps = []
const labelNameMap = new Map()
// if (nameData.length) {
// /** 处理 nameData */
// nameData.forEach((item) => {
// if (!labelNameMap.get(item.name)) {
// labelNameMap.set(item.name, 1)
// subProps.push({ name: item.name, prop: item.name })
// }
// })
// }
this.tableConfigDynamic = [
{ type: 'index', width: 100, name: i18n.t('index') },
{ name: i18n.t('pl.name'), prop: '0' },
...Array.from(new Set(res.data.data[0].records.map((item) => moment(item.recordTime).format('MM-DD')))).map((name) => ({ prop: String(++this.count), name }))
]
/** echarts related */
// this.echartCategories = subProps.map((item) => item.name)
this.echartCategories = this.dataListDynamic.map((item) => item.name)
},
// parseDynamicData(data) {
// this.echartCheckTypes.splice(0)
// return data.map((item) => {
// /** echarts related */
// this.echartCheckTypes.push(item.inspectionContent)
// if (item.data.length) {
// /** 解析子数组 */
// item.data.forEach((subitem) => {
// item[subitem.dynamicName] = subitem.dynamicValue
// })
// }
// return item
// })
// },
buildGraphData() {
/** 构造 echart 需要的数据 */
const result = []
// this.echartCheckTypes.forEach((ect) => {
// result.push({ name: ect, type: 'bar', data: [] })
// })
// console.log('echartCheckTypes', this.echartCheckTypes)
// console.log('this.echartCategories', this.echartCategories)
// console.log('this.dataListDynamic', this.dataListDynamic)
// this.dataListDynamic.forEach((inspection, index) => {
// // console.log('inspection: ', inspection)
// this.echartCategories.forEach((cate) => {
// if (cate in inspection) {
// result[index].data.push(inspection[cate])
// } else {
// result[index].data.push('0')
// }
// })
// })
// this.dataListDynamic[0].shift()
// this.dataListDynamic[1].shift()
// this.dataListDynamic[2].shift()
// this.dataListDynamic[3].shift()
for (var key = 0; key < this.dataListDynamic.length; key++) {
if (this.dataListDynamic[key][0].indexOf('1') != -1) {
this.echartsData1 = this.dataListDynamic[key]
} else if (this.dataListDynamic[key][0].indexOf('2') != -1) {
this.echartsData2 = this.dataListDynamic[key]
} else if (this.dataListDynamic[key][0].indexOf('3') != -1) {
this.echartsData3 = this.dataListDynamic[key]
} else if (this.dataListDynamic[key][0].indexOf('4') != -1) {
this.echartsData4 = this.dataListDynamic[key]
}
}
// this.echartsData1 = this.dataListDynamic[0]
// this.echartsData2 = this.dataListDynamic[1]
// this.echartsData3 = this.dataListDynamic[2]
// this.echartsData4 = this.dataListDynamic[3]
// 不抛出老是报shift错误
try {
// 因为又加了“合计”字段,所以再多删除一次
this.echartsData1.shift()
this.echartsData2.shift()
this.echartsData3.shift()
this.echartsData4.shift()
this.echartsData1.shift()
this.echartsData2.shift()
this.echartsData3.shift()
this.echartsData4.shift()
} catch (error) {}
// this.echartsData = result
// console.log('this.echartsData1', this.echartsData1)
// [
// { name: '11', type: 'bar', data: [/**产线1*/ 2, /**产线2*/ 3] },
// { name: '222', type: 'bar', data: [1, 2, 3] }
// ]
// 没有数据的产线legend隐藏
if (this.echartsData1.length !== 0) {
this.echartCheckTypes.push(this.$t('eq.line1'))
}
if (this.echartsData2.length !== 0) {
this.echartCheckTypes.push(this.$t('eq.line2'))
}
if (this.echartsData3.length !== 0) {
this.echartCheckTypes.push(this.$t('eq.line3'))
}
if (this.echartsData4.length !== 0) {
this.echartCheckTypes.push(this.$t('eq.line4'))
}
// console.log('this.echartCheckTypes', this.echartCheckTypes)
// console.log(this.echartsData1.length)
// console.log(this.echartsData2.length)
// console.log(this.echartsData3)
// console.log(this.echartsData4)
},
fetchList(startTime, endTime, lineIds) {
this.$http({
url: this.$http.adornUrl('/monitoring/eqAnalysis/productQualityAnalysis'),
method: 'POST',
data: {
startTime,
endTime,
lineIds: this.lineIds
}
}).catch((err) => {
console.error(err)
})
},
/**
* 默认当前月
* date 带月份的日期2021-8
* 返回月初至月末数组,例:[2021-8-1, 2021-8-31]
*/
getMonthSE(date) {
let nowdays = date ? new Date(date) : new Date()
let year = nowdays.getFullYear()
let month = nowdays.getMonth() + 1
if (month < 10) {
month = '0' + month
}
let myDate = new Date(year, month, 0)
let startDate = year + '-' + month + '-01'
let endDate = year + '-' + month + '-' + myDate.getDate()
// return [startDate, endDate]
return endDate
}
// 数组转对象
// toObject(pairs) {
// return Array.from(pairs).reduce((acc, [key, value]) => Object.assign(acc, { [key]: value }), {})
// }
}
}
</script>
<style scoped>
.base-container {
min-height: 60vh;
background: #fff;
padding: 12px;
}
.buttonColor {
color: #fff;
background: #0b58ff;
}
</style>