From c67384ef791e66de82b0a415261785320b14dd3f Mon Sep 17 00:00:00 2001 From: liutao <790864623@qq.com> Date: Tue, 16 Jun 2026 17:47:43 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E5=8F=B0=E8=B4=A6=E7=82=B9?= =?UTF-8?q?=E6=A3=80=E8=AE=B0=E5=BD=95=E5=8F=8A=E4=BF=9D=E5=85=BB=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E5=8F=8A=E4=BF=9D=E4=BF=AE=E8=AE=B0=E5=BD=95=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/locales/en-US.js | 9 +- src/locales/zh-CN.js | 10 +- .../pages/equipmentLedger/detail.vue | 316 +++++++++++++++--- 3 files changed, 285 insertions(+), 50 deletions(-) diff --git a/src/locales/en-US.js b/src/locales/en-US.js index 00fa9aa..fe16782 100644 --- a/src/locales/en-US.js +++ b/src/locales/en-US.js @@ -390,7 +390,6 @@ export default { totalSuffix: '', confirmDeleteHistory: 'Confirm delete this history record?', operateTime: 'Operate Time', - operator: 'Operator' }, moldInspectionItems: { moduleName: 'Inspection Items', @@ -914,9 +913,17 @@ export default { confirmDeleteContent: 'Confirm delete equipment [{name}]?', checkHistory: 'Inspection', maintainHistory: 'Maintenance', + maintainMethod: 'Maintenance Method', + maintainTime: 'Maintenance Time', repairHistory: 'Repair', + repairProject: 'Repair Project', + projectContent: 'Project Content', + finishTime: 'Finish Time', operator: 'Operator', noHistoryData: 'No history data', + inspectionMethod: 'Inspection Method', + criteria: 'Judgment Criteria', + inspectionTime: 'Inspection Time', resultPass: 'Pass', resultFail: 'Fail', repairPending: 'Pending', diff --git a/src/locales/zh-CN.js b/src/locales/zh-CN.js index b80a5b3..02c25a1 100644 --- a/src/locales/zh-CN.js +++ b/src/locales/zh-CN.js @@ -390,7 +390,6 @@ export default { totalSuffix: ' 条', confirmDeleteHistory: '确认删除该历史记录吗?', operateTime: '操作时间', - operator: '操作人' }, moldInspectionItems: { moduleName: '点检项库', @@ -917,9 +916,17 @@ export default { confirmDeleteContent: '确认删除设备【{name}】吗?', checkHistory: '点检记录', maintainHistory: '保养记录', + maintainMethod: '保养方法', + maintainTime: '保养时间', repairHistory: '报修记录', + repairProject: '维修项目', + projectContent: '项目内容', + finishTime: '完成时间', operator: '操作人', noHistoryData: '暂无历史记录', + inspectionMethod: '点检方法', + criteria: '判定标准', + inspectionTime: '点检时间', resultPass: '合格', resultFail: '不合格', repairPending: '待处理', @@ -1406,7 +1413,6 @@ export default { purchaseUnit: '采购单位', convertRatio: '换算关系', defaultWarehouse: '默认仓库/库区', - selectSparepart: '选择备件', selectedSpareparts: '已选备件', noSelectedSparepart: '请扫码或选择备件', alreadySelected: '该备件已添加', diff --git a/src/pages_function/pages/equipmentLedger/detail.vue b/src/pages_function/pages/equipmentLedger/detail.vue index a1d83dd..23b2b6c 100644 --- a/src/pages_function/pages/equipmentLedger/detail.vue +++ b/src/pages_function/pages/equipmentLedger/detail.vue @@ -62,7 +62,7 @@ {{ t('equipmentLedger.factoryEntryDate') }} {{ formatDateValue(detailData?.factoryEntryDate) }} - + {{ t('equipmentLedger.productionDate') }} {{ formatDateValue(detailData?.outgoingTime) }} @@ -108,45 +108,65 @@ - {{ t('equipmentLedger.noHistoryData') }} - - - {{ formatDateTime(item.inspectionTime) }} - {{ getResultText(item.inspectionResult) }} + {{ t('functionCommon.loading') }} + {{ t('equipmentLedger.noHistoryData') }} + + + {{ group.time }} + {{ group.operator }} - - {{ item.inspectionItemName || item.name || '-' }} - {{ t('equipmentLedger.operator') }}: {{ item.operatorName || item.inspectorName || '-' }} + + + {{ item.name }} + {{ item.resultLabel }} + + {{ t('equipmentLedger.inspectionMethod') }}{{ item.method || '-' }} + {{ t('equipmentLedger.criteria') }}{{ item.criteria || '-' }} + {{ t('equipmentLedger.inspectionTime') }}{{ item.taskTimeLabel || '-' }} + {{ t('equipmentLedger.remark') }}{{ item.remark || '-' }} + + + - - - {{ t('equipmentLedger.noHistoryData') }} - - - {{ formatDateTime(item.maintainTime || item.inspectionTime) }} - {{ getResultText(item.maintainResult || item.inspectionResult) }} + {{ t('functionCommon.loading') }} + {{ t('equipmentLedger.noHistoryData') }} + + + {{ group.time }} + {{ group.operator }} - - {{ item.maintainItemName || item.inspectionItemName || item.name || '-' }} - {{ t('equipmentLedger.operator') }}: {{ item.operatorName || item.inspectorName || '-' }} + + + {{ item.name }} + {{ item.resultLabel }} + + {{ t('equipmentLedger.maintainMethod') }}{{ item.method || '-' }} + {{ t('equipmentLedger.criteria') }}{{ item.criteria || '-' }} + {{ t('equipmentLedger.maintainTime') }}{{ item.taskTimeLabel || '-' }} + {{ t('equipmentLedger.remark') }}{{ item.remark || '-' }} + + + - - - {{ t('equipmentLedger.noHistoryData') }} - - - {{ formatDateTime(item.createTime) }} - {{ getRepairStatusText(item.status) }} + {{ t('functionCommon.loading') }} + {{ t('equipmentLedger.noHistoryData') }} + + + {{ row.repairNo || row.description || '-' }} + {{ row.resultLabel }} - - {{ item.repairNo || item.description || '-' }} - {{ t('equipmentLedger.operator') }}: {{ item.creatorName || '-' }} + {{ t('equipmentLedger.repairProject') }}{{ row.subjectName || row.subjectCode || '-' }} + {{ t('equipmentLedger.projectContent') }}{{ row.subjectContent || '-' }} + {{ t('equipmentLedger.finishTime') }}{{ row.finishDateLabel || '-' }} + {{ t('equipmentLedger.remark') }}{{ row.remark || '-' }} + + @@ -174,6 +194,59 @@ const detailData = ref(null) const deviceTypeList = ref([]) const activeTab = ref('check') const inspectionList = ref([]) +const inspectionLoading = ref(false) + +const inspectionGroups = computed(() => + buildStepGroups(inspectionList.value, { + timeFieldCandidates: ['taskTime', 'inspectionTime', 'createTime'], + nameFieldCandidates: ['inspectionItemName', 'name', 'itemName'], + resultFieldCandidates: ['inspectionResult', 'result'], + methodFieldCandidates: ['inspectionMethod', 'method'], + criteriaFieldCandidates: ['judgmentCriteria', 'criteria'], + imagesFieldCandidates: ['images'], + remarkFieldCandidates: ['remark'] + }) +) +const maintainLoading = ref(false) + +const maintainGroups = computed(() => + buildStepGroups(maintainList.value, { + timeFieldCandidates: ['taskTime', 'inspectionTime', 'createTime'], + nameFieldCandidates: ['maintainItemName', 'inspectionItemName', 'name', 'itemName'], + resultFieldCandidates: ['maintainResult', 'inspectionResult', 'result'], + methodFieldCandidates: ['inspectionMethod', 'method'], + criteriaFieldCandidates: ['judgmentCriteria', 'criteria'], + imagesFieldCandidates: ['images'], + remarkFieldCandidates: ['remark'] + }) +) + +const repairLoading = ref(false) + +const repairRecords = computed(() => { + const rows = Array.isArray(repairList.value) ? repairList.value : [] + return rows.map((row, index) => { + const resultMeta = formatRepairResult(row?.status) + return { + ...row, + key: String(row?.id ?? row?.repairCode ?? index), + finishDateLabel: formatDateTime(row?.finishDate || row?.createTime), + resultLabel: resultMeta.label, + resultType: resultMeta.type, + images: parseImages(row?.malfunctionUrl || row?.malfunctionImages || row?.images) + } + }) +}) + +function formatRepairResult(value) { + const raw = value === null || value === undefined ? '' : String(value).trim() + if (raw === '2') return { label: t('equipmentLedger.repairCompleted'), type: 'success' } + if (raw === '1') return { label: t('equipmentLedger.repairProcessing'), type: 'warning' } + if (raw === '0') return { label: t('equipmentLedger.repairPending'), type: 'info' } + return { label: textValue(value), type: 'info' } +} + + const maintainList = ref([]) const repairList = ref([]) const statusUpdating = ref(false) @@ -256,29 +329,44 @@ function normalizeDetail(res) { } async function fetchInspectionHistory() { + if (!detailId.value) return + inspectionLoading.value = true try { const res = await request({ url: '/admin-api/mes/ticket-management/getInspectionByDeviceId', method: 'get', params: { deviceId: detailId.value } }) const data = res && res.data !== undefined ? res.data : res - inspectionList.value = Array.isArray(data) ? data : [] - } catch (e) { inspectionList.value = [] } + inspectionList.value = normalizeListData(data) + } catch (e) { + inspectionList.value = [] + } finally { + inspectionLoading.value = false + } } - async function fetchMaintainHistory() { + if (!detailId.value) return + maintainLoading.value = true try { const res = await request({ url: '/admin-api/mes/ticket-management/getMaintenanceByDeviceId', method: 'get', params: { deviceId: detailId.value } }) const data = res && res.data !== undefined ? res.data : res - maintainList.value = Array.isArray(data) ? data : [] - } catch (e) { maintainList.value = [] } + maintainList.value = normalizeListData(data) + } catch (e) { + maintainList.value = [] + } finally { + maintainLoading.value = false + } } - async function fetchRepairHistory() { + if (!detailId.value) return + repairLoading.value = true try { const res = await request({ url: '/admin-api/mes/dv-repair/getRepairListByDeviceId', method: 'get', params: { deviceId: detailId.value } }) const data = res && res.data !== undefined ? res.data : res - repairList.value = Array.isArray(data) ? data : [] - } catch (e) { repairList.value = [] } + repairList.value = normalizeListData(data) + } catch (e) { + repairList.value = [] + } finally { + repairLoading.value = false + } } - function switchTab(key) { activeTab.value = key } @@ -321,6 +409,68 @@ async function onStatusChange(e) { } } + +function normalizeListData(res) { + const root = res && res.data !== undefined ? res.data : res + if (Array.isArray(root?.records)) return root.records + if (Array.isArray(root?.data?.list)) return root.data.list + if (Array.isArray(root?.data?.rows)) return root.data.rows + if (Array.isArray(root?.data?.records)) return root.data.records + if (Array.isArray(root)) return root + return [] +} + +function pickFirst(row, candidates) { + if (!row || typeof row !== 'object') return undefined + for (const key of candidates) { + const v = row[key] + if (v !== undefined && v !== null && v !== '') return v + } + return undefined +} + +function parseImages(value) { + if (!value) return [] + if (Array.isArray(value)) return value.map(String).filter(Boolean) + return String(value).split(',').map(s => s.trim()).filter(Boolean) +} + +function buildStepGroups(list, options) { + if (!Array.isArray(list) || !list.length) return [] + const groupsMap = new Map() + list.forEach((row, index) => { + const operator = pickFirst(row, ['inspectorName', 'operatorName', 'creatorName', 'createByName']) || '-' + const time = pickFirst(row, options.timeFieldCandidates) + const groupKey = time ? String(time) + '_' + operator : 'g_' + index + const resultRaw = pickFirst(row, options.resultFieldCandidates) + const resultType = (resultRaw === 'PASS' || resultRaw === 'pass' || resultRaw === 'OK' || resultRaw === 'ok' || resultRaw === 1 || resultRaw === '1') ? 'pass' : + (resultRaw === 'FAIL' || resultRaw === 'fail' || resultRaw === 'NG' || resultRaw === 'ng' || resultRaw === 0 || resultRaw === '0') ? 'fail' : 'unknown' + const resultLabel = resultType === 'pass' ? t('equipmentLedger.resultPass') : resultType === 'fail' ? t('equipmentLedger.resultFail') : String(resultRaw || '-') + const item = { + key: 'i_' + index + '_' + (row.id || index), + name: pickFirst(row, options.nameFieldCandidates) || '-', + resultType, + resultLabel, + method: pickFirst(row, options.methodFieldCandidates), + criteria: pickFirst(row, options.criteriaFieldCandidates), + remark: pickFirst(row, options.remarkFieldCandidates), + images: parseImages(pickFirst(row, options.imagesFieldCandidates)), + taskTimeLabel: formatDateTime(time) + } + if (!groupsMap.has(groupKey)) { + groupsMap.set(groupKey, { key: groupKey, time: formatDateTime(time) || '-', operator, items: [item] }) + } else { + groupsMap.get(groupKey).items.push(item) + } + }) + return Array.from(groupsMap.values()) +} + +function previewImages(list, current) { + if (!list || !list.length) return + uni.previewImage({ urls: list, current }) +} + function getResultText(result) { if (result === 'PASS' || result === 'pass' || result === 'OK' || result === 'ok' || result === 1 || result === '1') return t('equipmentLedger.resultPass') if (result === 'FAIL' || result === 'fail' || result === 'NG' || result === 'ng' || result === 0 || result === '0') return t('equipmentLedger.resultFail') @@ -422,14 +572,86 @@ function formatDateTime(value) { .tab-text { font-size: 28rpx; color: #8a9099; } .tab-item.active .tab-text { color: #1a3a5c; font-weight: 700; } .tab-item.active::after { content: ''; position: absolute; bottom: -2rpx; left: 30%; right: 30%; height: 4rpx; background: #1a3a5c; border-radius: 2rpx; } +.record-card { + margin-bottom: 20rpx; + padding: 24rpx; + border-radius: 22rpx; + background: linear-gradient(180deg, #ffffff 0%, #fbfcfe 100%); + border: 1rpx solid #edf2f7; +} +.timeline-meta { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16rpx; + margin-bottom: 18rpx; +} +.timeline-time { + font-size: 28rpx; + color: #1f4f81; + font-weight: 700; +} +.timeline-operator { + font-size: 24rpx; + color: #64748b; +} +.history-title-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12rpx; + margin-bottom: 10rpx; +} +.history-item-name { + font-size: 28rpx; + color: #1f2937; + font-weight: 600; + flex: 1; + min-width: 0; +} +.result-badge { + font-size: 22rpx; + font-weight: 700; + padding: 4rpx 14rpx; + border-radius: 8rpx; + flex-shrink: 0; +} +.result-pass { color: #15803d; background: #dcfce7; } +.result-fail { color: #b91c1c; background: #fee2e2; } +.result-unknown { color: #92400e; background: #fef3c7; } +.record-row { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 20rpx; + margin-bottom: 10rpx; +} +.record-label { + font-size: 24rpx; + color: #94a3b8; + flex-shrink: 0; + min-width: 120rpx; +} +.record-value { + flex: 1; + font-size: 27rpx; + color: #1f2937; + font-weight: 500; + line-height: 1.4; + text-align: right; +} +.history-images { + display: flex; + flex-wrap: wrap; + gap: 12rpx; + margin-top: 14rpx; +} +.history-image { + width: 150rpx; + height: 150rpx; + border-radius: 14rpx; + background: #edf2f7; +} .tab-content { min-height: 200rpx; } -.empty-tip { text-align: center; padding: 40rpx 0; color: #99a1aa; font-size: 26rpx; } -.history-item { padding: 20rpx 0; border-bottom: 1rpx solid #f0f2f5; } -.history-item:last-child { border-bottom: none; } -.history-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10rpx; } -.history-time { font-size: 24rpx; color: #8a9099; } -.history-result { font-size: 26rpx; font-weight: 600; } -.history-body { display: flex; justify-content: space-between; align-items: center; } -.history-name { font-size: 28rpx; color: #30363d; } -.history-operator { font-size: 24rpx; color: #8a9099; } +