feat: 小程序展示报工超额快照

This commit is contained in:
souplearn
2026-07-25 21:12:17 +08:00
parent 25ed4e2da8
commit 4003625fb1
6 changed files with 280 additions and 33 deletions
+91 -10
View File
@@ -544,6 +544,34 @@ const formatWorkTime = minutes => {
return `${Math.round(safeMinutes * 100) / 100}分钟`
}
const snapshotValueText = value => (
value === null || value === undefined || value === '' ? '-' : String(value)
)
const hasSnapshotValue = value => (
value !== null && value !== undefined && value !== ''
)
const watermarkClassAt = index => (
['', 'lower-watermark', 'third-watermark', 'fourth-watermark', 'fifth-watermark', 'sixth-watermark'][index] || 'sixth-watermark'
)
const buildWatermarkClasses = flags => {
const classes = {}
let index = 0
const assign = (key, enabled) => {
classes[key] = enabled ? watermarkClassAt(index++) : ''
}
assign('overLimit', flags.hasOverLimit)
assign('state', flags.hasState)
assign('timeout', flags.isSystemAutoSubmitted)
assign('cleaning', flags.isCleaning)
assign('misc', flags.hasMisc)
assign('multiPerson', flags.hasMultiPerson)
assign('continuousDie', flags.hasContinuousDie)
return classes
}
const toCamelAllocation = row => ({
allocationDate: row.allocation_date || '',
dayMinutes: Number(row.day_minutes || 0),
@@ -577,6 +605,7 @@ const toCamelReportItem = row => {
const beatComparison = noOutputMetric ? classifyBeat(0, 0) : classifyBeat(actualBeat, standardBeat)
const workloadComparison = noOutputMetric ? classifyWorkload(0, 0) : classifyWorkload(goodQty, standardWorkload)
const corrections = row.corrections || {}
const overLimitStatus = row.over_limit_status || 'not_checked'
const correctionPairs = [
correctionPair(corrections, 'device_no', '设备号', row.device_no),
correctionPair(corrections, 'project_no', '项目号', row.project_no),
@@ -630,6 +659,26 @@ const toCamelReportItem = row => {
workloadCompareClass: workloadComparison.className,
workloadReason: workloadComparison.reason,
remark: row.remark || '',
overLimitStatus,
overLimitType: row.over_limit_type || '',
overLimitReason: row.over_limit_reason || '',
overLimitCheckedAt: row.over_limit_checked_at || '',
overLimitCheckSource: row.over_limit_check_source || '',
overLimitBatchNo: row.over_limit_batch_no || '',
overLimitProductGrossWeightKg: row.over_limit_product_gross_weight_kg ?? '',
overLimitIssuedWeightKg: row.over_limit_issued_weight_kg ?? '',
overLimitMaxReportableQty: row.over_limit_max_reportable_qty ?? '',
overLimitPreviousGoodQty: row.over_limit_previous_good_qty ?? '',
overLimitCurrentCumulativeQty: row.over_limit_current_cumulative_qty ?? '',
overLimitCurrentReportQty: row.over_limit_current_report_qty ?? '',
overLimitMaxReportableQtyText: snapshotValueText(row.over_limit_max_reportable_qty),
overLimitPreviousGoodQtyText: snapshotValueText(row.over_limit_previous_good_qty),
overLimitCurrentCumulativeQtyText: snapshotValueText(row.over_limit_current_cumulative_qty),
overLimitCurrentReportQtyText: snapshotValueText(row.over_limit_current_report_qty),
hasOverLimitMaxReportableQty: hasSnapshotValue(row.over_limit_max_reportable_qty),
hasOverLimitPreviousGoodQty: hasSnapshotValue(row.over_limit_previous_good_qty),
hasOverLimit: overLimitStatus === 'exceeded',
hasOverLimitNotice: overLimitStatus === 'exceeded' || overLimitStatus === 'uncheckable',
corrections,
correctionPairs,
hasCorrections: correctionPairs.length > 0,
@@ -673,6 +722,7 @@ const toCamelReport = row => {
const hasMisc = items.some(item => item.isMisc)
const hasContinuousDie = items.some(item => item.isContinuousDie)
const hasMultiPerson = items.some(item => item.isMultiPerson)
const hasOverLimit = !!row.has_over_limit || items.some(item => item.hasOverLimit)
const totalDefect = Math.round(items.reduce((sum, item) => sum + Number(item.defectQty || 0), 0) * 100) / 100
const corrections = row.corrections || {}
const reportCorrectionPairs = [
@@ -690,6 +740,15 @@ const toCamelReport = row => {
label: `${segment.displayName} ${pair.label}`,
}))
)))
const watermarkClasses = buildWatermarkClasses({
hasOverLimit,
hasState: !!row.is_voided || !!row.is_modified,
isSystemAutoSubmitted: !!row.is_system_auto_submitted,
isCleaning,
hasMisc,
hasMultiPerson,
hasContinuousDie,
})
return {
id: row.id,
attendancePointName: row.attendance_point_name || '',
@@ -715,6 +774,8 @@ const toCamelReport = row => {
submittedAtText: util.formatTime(row.submitted_at),
isSystemAutoSubmitted: !!row.is_system_auto_submitted,
autoSubmitReason: row.auto_submit_reason || '超时-系统自动提交',
hasOverLimit,
overLimitSummary: row.over_limit_summary || '',
isMultiPersonAssistant: !!row.is_multi_person_assistant,
multiPersonSourceReportId: row.multi_person_source_report_id || null,
isVoided: !!row.is_voided,
@@ -735,6 +796,7 @@ const toCamelReport = row => {
hasMisc,
hasContinuousDie,
hasMultiPerson,
watermarkClasses,
metrics: {
...toCamelMetrics(row.metrics || {}),
totalDefect,
@@ -1543,9 +1605,28 @@ const listDashboard = async (filters = {}) => {
})
return toCamelPage(data, row => {
const isMisc = !!row.is_misc || isMiscRow(row)
const noOutputMetric = isMisc || isCleaningRow(row)
const isCleaning = isCleaningRow(row)
const isContinuousDie = isContinuousDieRow(row)
const isMultiPerson = isMultiPersonRow(row)
const hasOverLimit = !!row.has_over_limit
const correctionPairs = (row.correction_pairs || []).map(pair => ({
key: pair.key,
label: pair.label,
oldValue: correctionDisplayValue(pair.old_value),
newValue: correctionDisplayValue(pair.new_value),
}))
const noOutputMetric = isMisc || isCleaning
const beatComparison = noOutputMetric ? classifyBeat(0, 0) : classifyBeat(row.actual_beat, row.standard_beat)
const workloadComparison = noOutputMetric ? classifyWorkload(0, 0) : classifyWorkload(row.total_good_qty, row.expected_workload)
const watermarkClasses = buildWatermarkClasses({
hasOverLimit,
hasState: !!row.is_voided || correctionPairs.length > 0,
isSystemAutoSubmitted: !!row.is_system_auto_submitted,
isCleaning,
hasMisc: isMisc,
hasMultiPerson: isMultiPerson,
hasContinuousDie: isContinuousDie,
})
return {
id: row.id,
attendancePointName: row.attendance_point_name || '',
@@ -1558,13 +1639,13 @@ const listDashboard = async (filters = {}) => {
processDisplayName: moldDisplayName(row.product_name, row.process_name, row.stamping_method),
rawMaterialBatchNo: row.raw_material_batch_no || '',
stampingMethod: row.stamping_method || '',
isCleaning: isCleaningRow(row),
isContinuousDie: isContinuousDieRow(row),
isCleaning,
isContinuousDie,
changeoverCount: row.changeover_count || 0,
isMisc,
isSystemAutoSubmitted: !!row.is_system_auto_submitted,
isVoided: !!row.is_voided,
isMultiPerson: isMultiPersonRow(row),
isMultiPerson,
isMultiPersonAssistant: !!row.is_multi_person_assistant,
workerType: row.worker_type || '正式工',
reportCount: row.report_count,
@@ -1584,6 +1665,11 @@ const listDashboard = async (filters = {}) => {
standardBeat: row.standard_beat,
processUnitPriceYuan: row.process_unit_price_yuan || 0,
referenceWage: round2(row.reference_wage || 0),
hasOverLimit,
overLimitSummary: row.over_limit_summary || '',
overLimitReasons: row.over_limit_reasons || '',
hasOverLimitNotice: !!(row.over_limit_summary || row.over_limit_reasons),
watermarkClasses,
expectedWorkload: row.expected_workload,
paceRate: row.pace_rate,
workloadRate: row.workload_rate,
@@ -1594,12 +1680,7 @@ const listDashboard = async (filters = {}) => {
workloadCompareClass: workloadComparison.className,
workloadReason: workloadComparison.reason,
reviewRemark: row.review_remark || '',
correctionPairs: (row.correction_pairs || []).map(pair => ({
key: pair.key,
label: pair.label,
oldValue: correctionDisplayValue(pair.old_value),
newValue: correctionDisplayValue(pair.new_value),
})),
correctionPairs,
}
})
}