Merge remote-tracking branch 'origin/master'

master
suixy 3 days ago
commit 5d7e8f1ef6

@ -226,7 +226,7 @@ export function repairHoursStatList(query) {
})
}
// 设备 OEE 分析报表 (注塑车间计算版本)
// 注塑车间 OEE 分析报表:页面入口沿用设备 OEE 分析,后端按 A/P/Q 计算完整 OEE。
export function deviceOeeAnalysisList(query) {
return request({
url: '/report/injectionOee/deviceOeeAnalysis',

@ -35,55 +35,75 @@
<div class="charts-container">
<el-card class="chart-card">
<div slot="header" class="chart-title">设备 OEE 对比 (注塑车间班次计算版)</div>
<div slot="header" class="chart-title">每台设备 OEE 对比</div>
<div ref="barChart" class="chart-content" />
</el-card>
</div>
<el-table v-loading="loading" :data="reportList" style="margin-top: 10px; width: 100%" border>
<el-table-column label="班次日期" align="center" prop="SHIFT_DATE" width="105" />
<el-table-column label="班次" align="center" prop="SHIFT_NAME" width="80" />
<el-table-column label="设备编码" align="center" prop="DEVICE_CODE" width="120" />
<el-table-column label="设备名称" align="center" prop="DEVICE_NAME" min-width="120" show-overflow-tooltip />
<el-table-column label="利用率(A)" align="center" prop="AVAILABILITY" width="90">
<el-table-column label="设备编码" align="center" prop="DEVICE_CODE" width="130" />
<el-table-column label="设备名称" align="center" prop="DEVICE_NAME" min-width="160" show-overflow-tooltip />
<el-table-column label="班次" align="center" prop="SHIFT_NAME" width="90" />
<el-table-column label="OEE" align="center" prop="OEE" width="100">
<template slot-scope="scope">
<span>{{ formatPercent(scope.row.AVAILABILITY) }}</span>
<span class="oee-value">{{ formatPercent(scope.row.OEE) }}</span>
</template>
</el-table-column>
<el-table-column label="性能(P)" align="center" prop="PERFORMANCE" width="90">
<el-table-column label="设备利用率(A)" align="center" prop="AVAILABILITY" width="130">
<template slot-scope="scope">
<span :title="'诊断值: ' + formatPercent(scope.row.DIAGNOSTIC_PERFORMANCE)">{{ formatPercent(scope.row.PERFORMANCE) }}</span>
<span class="util util-total">{{ formatPercent(scope.row.AVAILABILITY) }}</span>
</template>
</el-table-column>
<el-table-column label="良品率(Q)" align="center" prop="QUALITY" width="90">
<el-table-column label="性能稼动率(P)" align="center" prop="PERFORMANCE" width="130">
<template slot-scope="scope">
<span>{{ formatPercent(scope.row.PERFORMANCE) }}</span>
</template>
</el-table-column>
<el-table-column label="良品率(Q)" align="center" prop="QUALITY" width="110">
<template slot-scope="scope">
<span>{{ formatPercent(scope.row.QUALITY) }}</span>
</template>
</el-table-column>
<el-table-column label="OEE" align="center" prop="OEE" width="90">
<el-table-column label="总利用率(A)" align="center" prop="TOTAL_AVAILABILITY" width="130">
<template slot-scope="scope">
<span style="font-weight: bold; color: #409EFF;">{{ formatPercent(scope.row.OEE) }}</span>
<span>{{ formatPercent(scope.row.TOTAL_AVAILABILITY) }}</span>
</template>
</el-table-column>
<el-table-column label="运行时间" align="center" width="100">
<el-table-column label="周利用率(A)" align="center" prop="WEEK_AVAILABILITY" width="130">
<template slot-scope="scope">
<span>{{ (scope.row.ACTUAL_RUN_SECONDS / 60).toFixed(1) }} 分钟</span>
<span class="util util-week">{{ formatPercent(scope.row.WEEK_AVAILABILITY) }}</span>
</template>
</el-table-column>
<el-table-column label="计划时间" align="center" width="90">
<el-table-column label="本日利用率(A)" align="center" prop="TODAY_AVAILABILITY" width="140">
<template slot-scope="scope">
<span>{{ scope.row.PLANNED_TIME_MINUTES }} 分钟</span>
<span class="util util-today">{{ formatPercent(scope.row.TODAY_AVAILABILITY) }}</span>
</template>
</el-table-column>
<el-table-column label="开模数" align="center" prop="SHOTS" width="80" />
<el-table-column label="模腔数" align="center" prop="CAVITIES" width="70" />
<el-table-column label="产出数" align="center" prop="OUTPUT_QTY" width="90" />
<el-table-column label="标准周期" align="center" width="100">
<el-table-column label="运行时间(分钟)" align="center" prop="RUN_TIME_MINUTES" width="130">
<template slot-scope="scope">
<span :title="scope.row.CYCLE_SOURCE">{{ scope.row.STANDARD_CYCLE.toFixed(2) }} </span>
<span>{{ formatNumber(scope.row.RUN_TIME_MINUTES, 1) }}</span>
</template>
</el-table-column>
<el-table-column label="开模次数" align="center" prop="SHOTS" width="110" />
<el-table-column label="模腔数" align="center" prop="CAVITIES" width="90" />
<el-table-column label="产出件数" align="center" prop="OUTPUT_QTY" width="110">
<template slot-scope="scope">
<span>{{ formatNumber(scope.row.OUTPUT_QTY, 0) }}</span>
</template>
</el-table-column>
<el-table-column label="标准周期(s)" align="center" prop="STANDARD_CYCLE_SECONDS" width="130">
<template slot-scope="scope">
<span :title="scope.row.STANDARD_CYCLE_SOURCE">{{ formatNumber(scope.row.STANDARD_CYCLE_SECONDS, 2) }}</span>
</template>
</el-table-column>
<el-table-column label="数据说明" align="center" prop="DOWNGRADE_REASON" min-width="220" show-overflow-tooltip>
<template slot-scope="scope">
<el-tag v-if="scope.row.DOWNGRADE_REASON" class="notice-tag" type="warning" size="mini">
{{ scope.row.DOWNGRADE_REASON }}
</el-tag>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="降级说明" align="center" prop="DOWNGRADE_REASON" min-width="150" show-overflow-tooltip />
</el-table>
</div>
</template>
@ -118,9 +138,23 @@ export default {
mounted() {
this.$nextTick(() => {
this.barChart = echarts.init(this.$refs.barChart)
this.initBarChart()
window.addEventListener('resize', this.handleResize)
})
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize)
if (this.barChart) {
this.barChart.dispose()
this.barChart = null
}
},
methods: {
handleResize() {
if (this.barChart) {
this.barChart.resize()
}
},
/** 查询报表数据 */
getList() {
this.loading = true
@ -154,31 +188,36 @@ export default {
/** 初始化柱状图 */
initBarChart() {
if (!this.barChart) return
// X
const xData = (this.reportList || []).map(item => {
const devName = item.DEVICE_NAME || item.DEVICE_CODE
return `${devName}\n(${item.SHIFT_NAME})`
})
const yData = (this.reportList || []).map(item => item.OEE || 0)
const xData = (this.reportList || []).map(item => item.DEVICE_NAME || item.DEVICE_CODE)
const yDataOee = (this.reportList || []).map(item => item.OEE || 0)
const yDataA = (this.reportList || []).map(item => item.AVAILABILITY || 0)
const yDataP = (this.reportList || []).map(item => item.PERFORMANCE || 0)
const yDataQ = (this.reportList || []).map(item => item.QUALITY || 0)
const option = {
tooltip: {
trigger: 'axis',
axisPointer: { type: 'shadow' },
formatter: params => {
if (!params || !params.length) return ''
const p = params[0]
const item = this.reportList[p.dataIndex]
if (!item) return `${p.name}<br/>OEE${this.formatPercent(p.data)}`
return `${item.DEVICE_NAME || item.DEVICE_CODE} (${item.SHIFT_DATE} ${item.SHIFT_NAME})<br/>` +
`OEE${this.formatPercent(item.OEE)}<br/>` +
`└ 利用率(A)${this.formatPercent(item.AVAILABILITY)}<br/>` +
`└ 性能(P)${this.formatPercent(item.PERFORMANCE)} (诊断值: ${this.formatPercent(item.DIAGNOSTIC_PERFORMANCE)})<br/>` +
`└ 良品率(Q)${this.formatPercent(item.QUALITY)}`
const devName = params[0].name
let html = `<div style="font-weight: bold; margin-bottom: 5px;">${devName}</div>`
params.forEach(p => {
html += `${p.marker} ${p.seriesName}${(p.value * 100).toFixed(2)}%<br/>`
})
return html
}
},
legend: {
data: ['OEE', 'A 设备利用率', 'P 性能稼动率', 'Q 良品率'],
top: '0%'
},
grid: {
left: '3%',
right: '4%',
bottom: '10%',
top: '15%',
containLabel: true
},
xAxis: {
@ -191,6 +230,7 @@ export default {
},
yAxis: {
type: 'value',
max: 1,
axisLabel: {
formatter: value => `${(value * 100).toFixed(0)}%`
}
@ -199,11 +239,43 @@ export default {
{
name: 'OEE',
type: 'bar',
data: yData
barGap: '15%',
itemStyle: {
color: '#2f7ed8',
borderRadius: [4, 4, 0, 0]
},
data: yDataOee
},
{
name: 'A 设备利用率',
type: 'bar',
itemStyle: {
color: '#00a889',
borderRadius: [4, 4, 0, 0]
},
data: yDataA
},
{
name: 'P 性能稼动率',
type: 'bar',
itemStyle: {
color: '#7b4ee6',
borderRadius: [4, 4, 0, 0]
},
data: yDataP
},
{
name: 'Q 良品率',
type: 'bar',
itemStyle: {
color: '#ff9f43',
borderRadius: [4, 4, 0, 0]
},
data: yDataQ
}
]
}
this.barChart.setOption(option)
this.barChart.setOption(option, true)
},
/** 百分比格式化 */
formatPercent(val) {
@ -211,6 +283,13 @@ export default {
const num = Number(val)
if (isNaN(num)) return '-'
return (num * 100).toFixed(2) + '%'
},
/** 数值格式化,用于 OEE 业务量字段展示 */
formatNumber(val, digits) {
if (val == null || val === undefined) return '-'
const num = Number(val)
if (isNaN(num)) return '-'
return num.toFixed(digits)
}
}
}
@ -230,4 +309,23 @@ export default {
font-size: 16px;
font-weight: bold;
}
.oee-value {
color: #2f7ed8;
font-weight: bold;
}
.util {
font-weight: bold;
}
.util-total {
color: #00a889;
}
.util-week {
color: #7b4ee6;
}
.util-today {
color: #409EFF;
}
.notice-tag {
max-width: 100%;
}
</style>

Loading…
Cancel
Save