Browse Source

2026-08-31

代办中心显示总良率
master
fengyuan_yang 4 weeks ago
parent
commit
0a6e8f1299
  1. 221
      src/views/modules/todo/todoCenter.vue

221
src/views/modules/todo/todoCenter.vue

@ -167,8 +167,13 @@
<div class="todo-main-title">
{{ item.orderNo || '-' }}
</div>
<div class="todo-process-chip" :title="buildProcessExceptionLabel(item)">
{{ buildProcessExceptionLabel(item) }}
<div class="todo-process-metrics">
<div class="todo-process-chip" :title="buildProcessExceptionLabel(item)">
{{ buildProcessExceptionLabel(item) }}
</div>
<div class="todo-rate-chip" :title="buildMinTriggerTotalYieldRateLabel(item)">
{{ buildMinTriggerTotalYieldRateLabel(item) }}
</div>
</div>
</div>
@ -247,9 +252,14 @@
append-to-body>
<div slot="title" class="todo-detail-dialog-title">
<span class="todo-detail-dialog-title-main">{{ detailDialogTitle }}</span>
<span class="todo-detail-dialog-title-process" :title="buildProcessExceptionLabel({ mrbInspectionReport: detailProcessExceptionNo })">
{{ buildProcessExceptionLabel({ mrbInspectionReport: detailProcessExceptionNo }) }}
</span>
<div class="todo-detail-dialog-title-metrics">
<span class="todo-detail-dialog-title-process" :title="buildProcessExceptionLabel({ mrbInspectionReport: detailProcessExceptionNo })">
{{ buildProcessExceptionLabel({ mrbInspectionReport: detailProcessExceptionNo }) }}
</span>
<span class="todo-detail-dialog-title-rate" :title="buildMinTriggerTotalYieldRateLabel({ minTriggerTotalYieldRate: detailMinTriggerTotalYieldRate })">
{{ buildMinTriggerTotalYieldRateLabel({ minTriggerTotalYieldRate: detailMinTriggerTotalYieldRate }) }}
</span>
</div>
</div>
<div v-loading="detailDialogLoading" class="todo-detail-content">
<div v-if="detailSections.length === 0" class="todo-detail-empty-tip">
@ -288,7 +298,8 @@
:data="section.rowList"
border
style="width: 100%; margin-top: 10px;"
max-height="320">
max-height="320"
:span-method="detailObjectSpanMethod">
<el-table-column prop="rowNumber" label="NO." width="50" align="center"></el-table-column>
<el-table-column label="良品数" width="80" align="center">
<template slot-scope="scope">
@ -323,6 +334,11 @@
<div class="readonly-number yield">{{ scope.row.yieldRate }}</div>
</template>
</el-table-column>
<el-table-column label="总良率" width="88" align="center">
<template slot-scope="scope">
<div class="readonly-number total-yield">{{ scope.row.totalYieldRate }}</div>
</template>
</el-table-column>
<el-table-column label="总数" width="80" align="right">
<template slot-scope="scope">
<div class="readonly-number" style="text-align: right; padding-right: 10px;">
@ -418,6 +434,7 @@ export default {
detailDialogLoading: false,
detailDialogTitle: '创建分卷详情',
detailProcessExceptionNo: '',
detailMinTriggerTotalYieldRate: '',
detailSections: [],
showMrbRegisterFlag: false,
currentAuditTodo: null,
@ -565,6 +582,7 @@ export default {
resetDetailData () {
this.detailSections = []
this.detailProcessExceptionNo = ''
this.detailMinTriggerTotalYieldRate = ''
},
resolveProcessExceptionNo (row) {
if (!row) {
@ -573,10 +591,56 @@ export default {
const value = row.mrbInspectionReport || row.processExceptionNo || ''
return String(value).trim()
},
normalizePercentLabel (value) {
if (value === null || value === undefined) {
return ''
}
const text = String(value).trim().replace('%', '')
if (!text) {
return ''
}
const num = Number(text)
if (Number.isNaN(num)) {
return ''
}
return num.toFixed(2) + '%'
},
resolveMinTriggerTotalYieldRate (row) {
if (!row) {
return ''
}
const value = row.minTriggerTotalYieldRate || row.triggerMinTotalYieldRate || row.minTotalYieldRate || ''
return this.normalizePercentLabel(value)
},
resolveMinTriggerTotalYieldRateFromRows (rowList) {
const list = Array.isArray(rowList) ? rowList : []
let minRate = null
for (let i = 0; i < list.length; i++) {
const formattedRate = this.normalizePercentLabel(list[i] && list[i].totalYieldRate)
if (!formattedRate) {
continue
}
const num = Number(formattedRate.replace('%', ''))
if (Number.isNaN(num)) {
continue
}
if (minRate === null || num < minRate) {
minRate = num
}
}
if (minRate === null) {
return ''
}
return minRate.toFixed(2) + '%'
},
buildProcessExceptionLabel (row) {
const processExceptionNo = this.resolveProcessExceptionNo(row)
return processExceptionNo || '-'
},
buildMinTriggerTotalYieldRateLabel (row) {
const minTriggerTotalYieldRate = this.resolveMinTriggerTotalYieldRate(row)
return minTriggerTotalYieldRate || '-'
},
toInt (value) {
const num = Number(value)
if (Number.isNaN(num)) {
@ -598,8 +662,88 @@ export default {
}
return ((goodQty / totalQty) * 100).toFixed(2) + '%'
},
pickRollTextValue (rows, fieldName) {
const groupRows = Array.isArray(rows) ? rows : []
for (let i = 0; i < groupRows.length; i++) {
const current = groupRows[i] || {}
const value = current[fieldName]
if (value !== null && value !== undefined && String(value).trim() !== '') {
return String(value)
}
}
return ''
},
applyRollTotalYieldRate (rowList, rollCount) {
const list = Array.isArray(rowList) ? rowList.map(item => ({ ...item })) : []
if (list.length === 0) {
return list
}
const normalizedRollCount = this.toInt(rollCount)
if (!normalizedRollCount || normalizedRollCount <= 0) {
return list.map(item => ({
...item,
totalYieldRate: item.yieldRate || this.calcYieldRate(this.toNum(item.goodQty), this.toNum(item.defectQty)),
rollRowspan: 1
}))
}
const rowsPerRoll = Math.floor(list.length / normalizedRollCount)
const remainingRows = list.length % normalizedRollCount
let currentIndex = 0
for (let i = 0; i < normalizedRollCount; i++) {
const currentRollRows = rowsPerRoll + (i < remainingRows ? 1 : 0)
if (currentRollRows <= 0 || currentIndex >= list.length) {
continue
}
const endIndex = Math.min(currentIndex + currentRollRows, list.length)
let rollGoodQty = 0
let rollDefectQty = 0
for (let idx = currentIndex; idx < endIndex; idx++) {
rollGoodQty += this.toNum(list[idx].goodQty)
rollDefectQty += this.toNum(list[idx].defectQty)
}
const totalYieldRate = this.calcYieldRate(rollGoodQty, rollDefectQty)
const rollRows = list.slice(currentIndex, endIndex)
const mergedPackingList = this.pickRollTextValue(rollRows, 'packingList')
const mergedRemark = this.pickRollTextValue(rollRows, 'remark')
for (let idx = currentIndex; idx < endIndex; idx++) {
list[idx].totalYieldRate = totalYieldRate
list[idx].packingList = mergedPackingList
list[idx].remark = mergedRemark
list[idx].rollRowspan = idx === currentIndex ? (endIndex - currentIndex) : 0
}
currentIndex = endIndex
}
// 兜底:异常分组情况下,未赋值行按自身良率显示
for (let i = 0; i < list.length; i++) {
if (!list[i].totalYieldRate) {
list[i].totalYieldRate = list[i].yieldRate || this.calcYieldRate(this.toNum(list[i].goodQty), this.toNum(list[i].defectQty))
}
if (this.toInt(list[i].rollRowspan) === null) {
list[i].rollRowspan = 1
}
}
return list
},
detailObjectSpanMethod ({ row, column }) {
if (!row || !column) {
return
}
const needMerge = column.label === '总量率' || column.label === 'Packing List' || column.label === '备注'
if (!needMerge) {
return
}
const rowspan = this.toInt(row.rollRowspan)
if (rowspan !== null && rowspan > 0) {
return { rowspan: rowspan, colspan: 1 }
}
return { rowspan: 0, colspan: 0 }
},
mapCacheDetailRows (cacheList) {
return (cacheList || []).map(item => {
const mappedRows = (cacheList || []).map(item => {
const goodQty = this.toNum(item.goodQty)
const defectQty = this.toNum(item.defectQty)
const totalQty = goodQty + defectQty
@ -615,18 +759,21 @@ export default {
remark: item.remark || ''
}
})
return mappedRows.sort((a, b) => this.toInt(a.rowNumber) - this.toInt(b.rowNumber))
},
buildDetailSection (key, title, detailList) {
const list = detailList || []
const first = list.length > 0 ? list[0] : {}
const rollCount = this.toInt(first.rollCount) || 0
const rowList = this.mapCacheDetailRows(list)
return {
key: key,
title: title,
cacheTime: this.formatDateTime(first.createdTime),
fixture: first.fixtureNo || '',
rowCount: this.toInt(first.rowCount) || list.length,
rollCount: this.toInt(first.rollCount) || 0,
rowList: this.mapCacheDetailRows(list)
rollCount: rollCount,
rowList: this.applyRollTotalYieldRate(rowList, rollCount)
}
},
openTodoAuditModal (row) {
@ -737,6 +884,7 @@ export default {
this.detailDialogLoading = true
this.resetDetailData()
this.detailProcessExceptionNo = this.resolveProcessExceptionNo(row)
this.detailMinTriggerTotalYieldRate = this.resolveMinTriggerTotalYieldRate(row)
const query = {
site: row.site || this.searchData.site || this.$store.state.user.site,
@ -766,6 +914,10 @@ export default {
sections.push(this.buildDetailSection('report', '审核后最终报告数据', reportList))
}
this.detailSections = sections
const triggerSection = sections.find(section => section.key === 'trigger')
const triggerRateByRows = this.resolveMinTriggerTotalYieldRateFromRows(triggerSection ? triggerSection.rowList : [])
const triggerRateByResult = this.resolveMinTriggerTotalYieldRate(resultMap)
this.detailMinTriggerTotalYieldRate = triggerRateByRows || triggerRateByResult || this.detailMinTriggerTotalYieldRate
if (sections.length === 0) {
this.$message.warning('当前代办暂无详情数据')
return
@ -1089,8 +1241,17 @@ export default {
gap: 8px;
}
.todo-process-chip {
.todo-process-metrics {
max-width: 52%;
min-width: 0;
display: inline-flex;
align-items: center;
gap: 6px;
}
.todo-process-chip {
min-width: 0;
flex: 1 1 auto;
font-size: 11px;
color: #2f7ed8;
border: 1px solid #b3d8ff;
@ -1103,6 +1264,18 @@ export default {
text-overflow: ellipsis;
}
.todo-rate-chip {
flex: 0 0 auto;
font-size: 11px;
color: #3f51b5;
border: 1px solid #c5cae9;
background: #e8eaf6;
border-radius: 999px;
line-height: 18px;
padding: 0 8px;
white-space: nowrap;
}
.todo-detail-line {
margin-top: 6px;
display: flex;
@ -1213,8 +1386,17 @@ export default {
font-weight: 600;
}
.todo-detail-dialog-title-process {
.todo-detail-dialog-title-metrics {
flex-shrink: 0;
min-width: 0;
max-width: 380px;
display: flex;
align-items: center;
gap: 8px;
}
.todo-detail-dialog-title-process {
min-width: 0;
max-width: 310px;
color: #2f7ed8;
font-size: 12px;
@ -1228,6 +1410,18 @@ export default {
text-overflow: ellipsis;
}
.todo-detail-dialog-title-rate {
flex: 0 0 auto;
color: #3f51b5;
font-size: 12px;
border: 1px solid #c5cae9;
background: #e8eaf6;
border-radius: 999px;
padding: 2px 10px;
line-height: 18px;
white-space: nowrap;
}
.todo-detail-content {
min-height: 120px;
}
@ -1309,6 +1503,11 @@ export default {
font-weight: bold;
}
.todo-cache-detail-dialog .readonly-number.total-yield {
color: #409eff;
font-weight: bold;
}
.todo-cache-detail-dialog /deep/ .todo-detail-table td.remark-column,
.todo-cache-detail-dialog /deep/ .todo-detail-table td.packing-list-column {
padding: 0 !important;

Loading…
Cancel
Save