feat:设备维修逻辑重构

main
黄伟杰 12 hours ago
parent a1b5847161
commit 5980fc8750

@ -33,6 +33,33 @@ export interface DvRepairVO {
status: string // 单据状态 status: string // 单据状态
rejectReason?: string // 驳回理由 rejectReason?: string // 驳回理由
remark: string // 备注 remark: string // 备注
acceptanceHistoryList?: DvRepairAcceptanceHistoryVO[]
}
export interface DvRepairAcceptanceHistoryVO {
id?: number | string
repairId?: number | string
repairResult?: string | number
finishDate?: Date | string | number
confirmDate?: Date | string | number
confirmBy?: string
status?: string | number
rejectReason?: string
downtimeDuration?: string
faultReason?: string
handlingMeasures?: string
replacementParts?: string
repairContent?: string
repairedImages?: string
createTime?: Date | string | number
}
export interface DvRepairAcceptanceVO {
id: number | string
confirmBy: string
confirmDate?: Date | string | number
status: '1' | '2'
rejectReason?: string
} }
// 设备维修记录 API // 设备维修记录 API
@ -75,6 +102,10 @@ export const DvRepairApi = {
return await request.put({ url: `/mes/dv-repair/reject`, data }) return await request.put({ url: `/mes/dv-repair/reject`, data })
}, },
acceptanceDvRepair: async (data: DvRepairAcceptanceVO) => {
return await request.put({ url: `/mes/dv-repair/acceptance`, data })
},
// ==================== 子表(设备维修记录行) ==================== // ==================== 子表(设备维修记录行) ====================
// 获得设备维修记录行列表 // 获得设备维修记录行列表

@ -2277,6 +2277,9 @@ export default {
// Repair Order // Repair Order
DvRepair: { DvRepair: {
reportInfo: 'Repair Request Information',
processingResult: 'Processing Result',
historyRepairResult: 'Historical Processing Result',
repairCode: 'Repair Order No', repairCode: 'Repair Order No',
repairName: 'Repair Order', repairName: 'Repair Order',
machineryName: 'Device Name', machineryName: 'Device Name',
@ -2332,6 +2335,12 @@ export default {
rejectReasonPrompt: 'Please enter the rejection reason', rejectReasonPrompt: 'Please enter the rejection reason',
rejectReasonRequired: 'Rejection reason cannot be empty', rejectReasonRequired: 'Rejection reason cannot be empty',
rejectSuccess: 'Rejected successfully', rejectSuccess: 'Rejected successfully',
acceptance: 'Acceptance',
acceptanceResult: 'Acceptance Result',
acceptancePassed: 'Pass',
acceptanceRejected: 'Reject',
acceptanceSuccess: 'Acceptance submitted successfully',
validatorAcceptanceResultRequired: 'Please select an acceptance result',
creatorName: 'Creator', creatorName: 'Creator',
createTime: 'Create Time', createTime: 'Create Time',
operate: 'Operate', operate: 'Operate',

@ -2309,6 +2309,9 @@ export default {
// 维修单 // 维修单
DvRepair: { DvRepair: {
all: '全部', all: '全部',
reportInfo: '报修信息',
processingResult: '处理结果',
historyRepairResult: '历史处理结果',
repairCode: '维修单号', repairCode: '维修单号',
repairName: '维修单', repairName: '维修单',
machineryName: '设备名称', machineryName: '设备名称',
@ -2364,6 +2367,12 @@ export default {
rejectReasonPrompt: '请输入驳回理由', rejectReasonPrompt: '请输入驳回理由',
rejectReasonRequired: '驳回理由不能为空', rejectReasonRequired: '驳回理由不能为空',
rejectSuccess: '驳回成功', rejectSuccess: '驳回成功',
acceptance: '验收',
acceptanceResult: '验收结果',
acceptancePassed: '通过',
acceptanceRejected: '驳回',
acceptanceSuccess: '验收提交成功',
validatorAcceptanceResultRequired: '请选择验收结果',
creatorName: '创建人', creatorName: '创建人',
createTime: '创建时间', createTime: '创建时间',
operate: '操作', operate: '操作',

@ -259,6 +259,7 @@ export enum DICT_TYPE {
MES_PRODUCE_ITEM_REQUISITION = "mes_produce_item_requisition", MES_PRODUCE_ITEM_REQUISITION = "mes_produce_item_requisition",
MES_DATA_TYPE = "mes_data_type", MES_DATA_TYPE = "mes_data_type",
MES_MACHINE_STATUS = "mes_machine_status", MES_MACHINE_STATUS = "mes_machine_status",
EQUIPMENT_DOCUMENT_STATUS = "equipment_document_status",
MES_MACHINE_TYPE = "mes_machine_type", MES_MACHINE_TYPE = "mes_machine_type",
MES_FEEDING_TYPE = "mes_feeding_type", MES_FEEDING_TYPE = "mes_feeding_type",
MES_FEEDING_RECORD_STATUS = "mes_feeding_record_status", MES_FEEDING_RECORD_STATUS = "mes_feeding_record_status",

@ -9,7 +9,7 @@
<div class="dv-repair-dialog" v-loading="formLoading"> <div class="dv-repair-dialog" v-loading="formLoading">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px"> <el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px">
<section class="dv-repair-section"> <section class="dv-repair-section">
<div class="dv-repair-section__title">基本信息</div> <div class="dv-repair-section__title">{{ t('EquipmentManagement.DvRepair.reportInfo') }}</div>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="8"> <el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.repairCode')" prop="repairCode"> <el-form-item :label="t('EquipmentManagement.DvRepair.repairCode')" prop="repairCode">
@ -72,34 +72,6 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col v-if="formType !== 'create'" :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.acceptedBy')" prop="acceptedBy">
<el-select
v-model="formData.acceptedBy"
multiple
filterable
clearable
:placeholder="t('EquipmentManagement.DvRepair.placeholderAcceptedBy')"
class="!w-full"
:disabled="isRepairMetaReadonly"
>
<el-option v-for="item in users" :key="String(item.id)" :label="item.nickname" :value="String(item.id)" />
</el-select>
</el-form-item>
</el-col>
<el-col v-if="formType !== 'create'" :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.confirmBy')" prop="confirmBy">
<el-select
v-model="formData.confirmBy"
filterable
clearable
:placeholder="t('EquipmentManagement.DvRepair.placeholderConfirmBy')"
:disabled="isRepairMetaReadonly"
>
<el-option v-for="item in users" :key="String(item.id)" :label="item.nickname" :value="String(item.id)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.status')"> <el-form-item :label="t('EquipmentManagement.DvRepair.status')">
<el-input :model-value="statusLabel" disabled /> <el-input :model-value="statusLabel" disabled />
@ -232,8 +204,38 @@
</section> </section>
<section v-if="showRepairSection" class="dv-repair-section"> <section v-if="showRepairSection" class="dv-repair-section">
<div class="dv-repair-section__title">处理结果</div> <div class="dv-repair-section__title-row">
<div class="dv-repair-section__title">{{ t('EquipmentManagement.DvRepair.processingResult') }}</div>
<el-select
v-if="hasRepairHistory"
v-model="selectedRepairHistoryIndex"
class="dv-repair-history-select"
@change="changeRepairHistory"
>
<el-option
v-for="option in repairHistoryOptions"
:key="option.value"
:value="option.value"
:label="option.label"
/>
</el-select>
</div>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.acceptedBy')" prop="acceptedBy">
<el-select
v-model="formData.acceptedBy"
multiple
filterable
clearable
:placeholder="t('EquipmentManagement.DvRepair.placeholderAcceptedBy')"
class="!w-full"
:disabled="repairFieldsDisabled"
>
<el-option v-for="item in users" :key="String(item.id)" :label="item.nickname" :value="String(item.id)" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.repairResult')" prop="repairStatus"> <el-form-item :label="t('EquipmentManagement.DvRepair.repairResult')" prop="repairStatus">
<template #label> <template #label>
@ -270,24 +272,6 @@
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.confirmDate')" prop="confirmDate">
<template #label>
<span class="dv-repair-label" :class="{ 'is-required': formType === 'repair' }">
{{ t('EquipmentManagement.DvRepair.confirmDate') }}
</span>
</template>
<el-date-picker
v-model="formData.confirmDate"
type="datetime"
format="YYYY-MM-DD HH:mm:ss"
value-format="x"
:placeholder="t('EquipmentManagement.DvRepair.placeholderConfirmDate')"
class="!w-full"
:disabled="repairFieldsDisabled"
/>
</el-form-item>
</el-col>
</el-row> </el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="8"> <el-col :span="8">
@ -364,13 +348,37 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</section> <el-row v-if="hasRepairHistory" :gutter="20">
<el-col :span="8">
<section v-if="isDetailMode && String(formData.status) === '2'" class="dv-repair-section"> <el-form-item :label="t('EquipmentManagement.DvRepair.confirmBy')">
<div class="dv-repair-section__title">{{ t('EquipmentManagement.DvRepair.rejectionInfo') }}</div> <el-input :model-value="getUserLabel(displayedRepairHistory.confirmBy)" disabled />
<el-form-item :label="t('EquipmentManagement.DvRepair.rejectReason')"> </el-form-item>
<el-input :model-value="formData.rejectReason || '-'" type="textarea" :rows="3" disabled /> </el-col>
</el-form-item> <el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.confirmDate')">
<el-date-picker
:model-value="toTimestamp(displayedRepairHistory.confirmDate)"
type="datetime"
format="YYYY-MM-DD HH:mm:ss"
value-format="x"
class="!w-full"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.acceptanceResult')">
<el-input :model-value="getDocumentStatusLabel(displayedRepairHistory.status)" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row v-if="hasRepairHistory && String(displayedRepairHistory.status) === '2'" :gutter="20">
<el-col :span="24">
<el-form-item :label="t('EquipmentManagement.DvRepair.rejectReason')">
<el-input :model-value="displayedRepairHistory.rejectReason || '-'" type="textarea" :rows="3" disabled />
</el-form-item>
</el-col>
</el-row>
</section> </section>
<section class="dv-repair-section"> <section class="dv-repair-section">
@ -503,7 +511,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { DvRepairApi, DvRepairVO } from '@/api/mes/dvrepair' import { DvRepairAcceptanceHistoryVO, DvRepairApi, DvRepairVO } from '@/api/mes/dvrepair'
import { DeviceLedgerApi, DeviceLedgerVO } from '@/api/mes/deviceledger' import { DeviceLedgerApi, DeviceLedgerVO } from '@/api/mes/deviceledger'
import { DeviceTypeApi, DeviceTypeTreeVO } from '@/api/mes/devicetype' import { DeviceTypeApi, DeviceTypeTreeVO } from '@/api/mes/devicetype'
import { RepairItemsApi } from '@/api/mes/repairItems' import { RepairItemsApi } from '@/api/mes/repairItems'
@ -598,10 +606,11 @@ const currentRepairStatusValue = computed(() => {
const showRepairSection = computed(() => { const showRepairSection = computed(() => {
if (formType.value === 'repair') return true if (formType.value === 'repair') return true
if (formType.value === 'update') return currentStatusValue.value === '1' if (formType.value === 'update') return currentStatusValue.value === '1'
if (formType.value === 'detail') return currentRepairStatusValue.value !== '0' if (formType.value === 'detail') return hasRepairHistory.value || currentRepairStatusValue.value !== '0'
return false return false
}) })
const repairFieldsDisabled = computed(() => formType.value !== 'repair') const repairFieldsDisabled = computed(() => formType.value !== 'repair')
const documentStatusOptions = computed(() => getStrDictOptions(DICT_TYPE.EQUIPMENT_DOCUMENT_STATUS))
const submitButtonText = computed(() => { const submitButtonText = computed(() => {
if (formType.value === 'create') return '保存' if (formType.value === 'create') return '保存'
if (formType.value === 'repair') return '保存并提交' if (formType.value === 'repair') return '保存并提交'
@ -609,15 +618,66 @@ const submitButtonText = computed(() => {
}) })
const statusLabel = computed(() => { const statusLabel = computed(() => {
const status = formData.value.status return getDocumentStatusLabel(formData.value.status)
if (status === '' || status === null || status === undefined) return t('EquipmentManagement.DvRepair.statusPending')
return String(status) === '1'
? t('EquipmentManagement.DvRepair.statusFinished')
: String(status) === '2'
? t('EquipmentManagement.DvRepair.statusRejected')
: t('EquipmentManagement.DvRepair.statusPending')
}) })
const repairHistoryList = ref<DvRepairAcceptanceHistoryVO[]>([])
const selectedRepairHistoryIndex = ref<number>()
const hasRepairHistory = computed(() => repairHistoryList.value.length > 0)
const getHistoryTimestamp = (history: DvRepairAcceptanceHistoryVO) => {
const timestamp = toTimestamp(history.createTime ?? history.confirmDate ?? history.finishDate)
return timestamp === undefined ? Number.NEGATIVE_INFINITY : Number(timestamp)
}
const latestRepairHistoryIndex = computed(() => repairHistoryList.value.reduce((latestIndex, history, index) => {
return getHistoryTimestamp(history) >= getHistoryTimestamp(repairHistoryList.value[latestIndex]) ? index : latestIndex
}, 0))
const formatHistoryTime = (history: DvRepairAcceptanceHistoryVO) => {
const timestamp = toTimestamp(history.createTime ?? history.confirmDate ?? history.finishDate)
if (timestamp === undefined) return ''
const date = new Date(timestamp)
const pad = (value: number) => String(value).padStart(2, '0')
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
}
const repairHistoryOptions = computed(() => repairHistoryList.value.map((item, index) => ({
value: index,
label: `${t('EquipmentManagement.DvRepair.historyRepairResult')} ${index + 1}${formatHistoryTime(item) ? ` · ${formatHistoryTime(item)}` : ''}`
})))
const displayedRepairHistory = computed(() => selectedRepairHistoryIndex.value === undefined
? formData.value
: repairHistoryList.value[selectedRepairHistoryIndex.value] ?? formData.value)
const getDocumentStatusLabel = (value: unknown) => {
const status = value === '' || value === null || value === undefined ? '0' : String(value)
return documentStatusOptions.value.find((item) => String(item.value) === status)?.label ?? status
}
const applyRepairHistory = (source: Record<string, any>) => {
formData.value.repairResult = source.repairResult ?? ''
formData.value.repairStatus = normalizeRepairStatusValue(source.repairStatus ?? source.repairResult)
formData.value.finishDate = toTimestamp(source.finishDate)
formData.value.confirmDate = toTimestamp(source.confirmDate)
formData.value.confirmBy = normalizeUserId(source.confirmBy)
formData.value.rejectReason = source.rejectReason
formData.value.downtimeDuration = source.downtimeDuration
formData.value.faultReason = source.faultReason
formData.value.handlingMeasures = source.handlingMeasures
formData.value.replacementParts = source.replacementParts
formData.value.repairContent = source.repairContent
formData.value.repairedImages = normalizeImageString(source.repairedImages)
}
const changeRepairHistory = () => {
const source = selectedRepairHistoryIndex.value === undefined
? undefined
: repairHistoryList.value[selectedRepairHistoryIndex.value]
if (source) applyRepairHistory(source as Record<string, any>)
}
const showComponentSelect = computed(() => formData.value.machineryTypeId === 2) const showComponentSelect = computed(() => formData.value.machineryTypeId === 2)
const selectedDeviceText = computed(() => { const selectedDeviceText = computed(() => {
@ -695,6 +755,12 @@ const normalizeUserId = (value: any) => {
return matched ? String(matched.id) : str return matched ? String(matched.id) : str
} }
const getUserLabel = (value: any) => {
const normalizedValue = normalizeUserId(value)
if (!normalizedValue) return '-'
return users.value.find((user) => String(user.id) === normalizedValue)?.nickname ?? String(value)
}
const splitUserIds = (value: unknown) => { const splitUserIds = (value: unknown) => {
const values = Array.isArray(value) ? value : String(value ?? '').split(',') const values = Array.isArray(value) ? value : String(value ?? '').split(',')
return [...new Set(values.map((item) => normalizeUserId(item)).filter(Boolean) as string[])] return [...new Set(values.map((item) => normalizeUserId(item)).filter(Boolean) as string[])]
@ -1022,18 +1088,6 @@ const formRules = reactive({
trigger: 'change' trigger: 'change'
} }
], ],
confirmDate: [
{
validator: (_: any, value: any, callback: any) => {
if (formType.value === 'repair' && !value) {
callback(new Error(t('EquipmentManagement.DvRepair.validatorConfirmDateRequired')))
return
}
callback()
},
trigger: 'change'
}
],
repairStatus: [ repairStatus: [
{ {
validator: (_: any, value: any, callback: any) => { validator: (_: any, value: any, callback: any) => {
@ -1116,8 +1170,8 @@ const open = async (type: string, id?: number) => {
...createDefaultFormData(), ...createDefaultFormData(),
...detail, ...detail,
requireDate: toTimestamp(detail?.requireDate) ?? undefined, requireDate: toTimestamp(detail?.requireDate) ?? undefined,
finishDate: detail?.finishDate ?? undefined, finishDate: toTimestamp(detail?.finishDate) ?? undefined,
confirmDate: detail?.confirmDate ?? undefined, confirmDate: toTimestamp(detail?.confirmDate) ?? undefined,
repairResult: detail?.repairResult ?? '', repairResult: detail?.repairResult ?? '',
repairStatus: detail?.repairStatus === undefined || detail?.repairStatus === null || detail?.repairStatus === '' repairStatus: detail?.repairStatus === undefined || detail?.repairStatus === null || detail?.repairStatus === ''
? normalizeRepairStatusValue(detail?.repairResult) ? normalizeRepairStatusValue(detail?.repairResult)
@ -1151,6 +1205,9 @@ const open = async (type: string, id?: number) => {
formData.value.componentId = String(formData.value.componentId) formData.value.componentId = String(formData.value.componentId)
} }
} }
repairHistoryList.value = Array.isArray(detail?.acceptanceHistoryList) ? detail.acceptanceHistoryList : []
selectedRepairHistoryIndex.value = hasRepairHistory.value ? latestRepairHistoryIndex.value : undefined
changeRepairHistory()
await nextTick() await nextTick()
formRef.value?.clearValidate?.() formRef.value?.clearValidate?.()
} finally { } finally {
@ -1206,6 +1263,7 @@ const submitForm = async () => {
data.faultImages = normalizeImageString(data.faultImages) data.faultImages = normalizeImageString(data.faultImages)
data.repairedImages = normalizeImageString(data.repairedImages) data.repairedImages = normalizeImageString(data.repairedImages)
data.repairResult = data.repairStatus data.repairResult = data.repairStatus
delete data.acceptanceHistoryList
const requireDate = toTimestamp(data.requireDate) const requireDate = toTimestamp(data.requireDate)
if (formType.value === 'repair' && requireDate === undefined) { if (formType.value === 'repair' && requireDate === undefined) {
@ -1214,7 +1272,7 @@ const submitForm = async () => {
} }
if (formType.value === 'repair') { if (formType.value === 'repair') {
data.status = '1' data.status = '3'
} }
if (formData.value.deviceId != null && formData.value.deviceId !== '') { if (formData.value.deviceId != null && formData.value.deviceId !== '') {
data.machineryId = formData.value.deviceId data.machineryId = formData.value.deviceId
@ -1226,11 +1284,10 @@ const submitForm = async () => {
if (formType.value === 'repair') { if (formType.value === 'repair') {
await DvRepairApi.updateDvRepairStatus({ await DvRepairApi.updateDvRepairStatus({
id: data.id, id: data.id,
status: '3',
requireDate, requireDate,
acceptedBy: data.acceptedBy, acceptedBy: data.acceptedBy,
confirmBy: data.confirmBy,
finishDate: data.finishDate, finishDate: data.finishDate,
confirmDate: data.confirmDate,
repairStatus: data.repairStatus, repairStatus: data.repairStatus,
repairResult: data.repairResult, repairResult: data.repairResult,
faultLevel: data.faultLevel, faultLevel: data.faultLevel,
@ -1267,6 +1324,8 @@ const submitForm = async () => {
const resetForm = () => { const resetForm = () => {
formData.value = createDefaultFormData() formData.value = createDefaultFormData()
repairHistoryList.value = []
selectedRepairHistoryIndex.value = undefined
deviceOptionsLoaded.value = false deviceOptionsLoaded.value = false
componentOptions.value = [] componentOptions.value = []
formRef.value?.resetFields() formRef.value?.resetFields()
@ -1331,6 +1390,22 @@ const resetForm = () => {
} }
} }
.dv-repair-section__title-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
.dv-repair-section__title {
margin-bottom: 16px;
}
}
.dv-repair-history-select {
width: 260px;
margin-bottom: 16px;
}
.dv-repair-label { .dv-repair-label {
display: inline-flex; display: inline-flex;
gap: 4px; gap: 4px;

@ -189,11 +189,11 @@
<template #default="scope"> <template #default="scope">
<el-button <el-button
link type="primary" @click="openForm('repair', scope.row.id)" link type="primary" @click="openForm('repair', scope.row.id)"
v-if="String(scope.row.status) === '0' && !isProcessedRepair(scope.row.repairStatus)" v-hasPermi="['mes:dv-repair:update']"> v-if="canRepair(scope.row.status)" v-hasPermi="['mes:dv-repair:update']">
{{ t('EquipmentManagement.DvRepair.repair') }} {{ t('EquipmentManagement.DvRepair.repair') }}
</el-button> </el-button>
<el-button <el-button
v-if="String(scope.row.status) === '0' && !isProcessedRepair(scope.row.repairStatus)" v-if="String(scope.row.status) === '0'"
link type="primary" @click="openForm('update', scope.row.id)" link type="primary" @click="openForm('update', scope.row.id)"
v-hasPermi="['mes:dv-repair:update']"> v-hasPermi="['mes:dv-repair:update']">
{{ t('action.update') }} {{ t('action.update') }}
@ -205,10 +205,10 @@
{{ t('action.detail') }} {{ t('action.detail') }}
</el-button> </el-button>
<el-button <el-button
v-if="String(scope.row.status) === '1'" v-if="String(scope.row.status) === '3'"
link type="danger" :loading="String(rejectingId) === String(scope.row.id)" @click="handleReject(scope.row.id)" link type="primary" @click="openAcceptance(scope.row)"
v-hasPermi="['mes:dv-repair:update']"> v-hasPermi="['mes:dv-repair:update']">
{{ t('EquipmentManagement.DvRepair.reject') }} {{ t('EquipmentManagement.DvRepair.acceptance') }}
</el-button> </el-button>
<el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['mes:dv-repair:delete']"> <el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['mes:dv-repair:delete']">
{{ t('action.delete') }} {{ t('action.delete') }}
@ -224,14 +224,48 @@
</template> </template>
<DvRepairForm v-else ref="formRef" @success="getList" @closed="formVisible = false" /> <DvRepairForm v-else ref="formRef" @success="getList" @closed="formVisible = false" />
<Dialog v-model="acceptanceDialogVisible" :title="t('EquipmentManagement.DvRepair.acceptance')" width="560px" :appendToBody="true">
<el-form ref="acceptanceFormRef" :model="acceptanceForm" :rules="acceptanceRules" label-width="100px">
<el-form-item :label="t('EquipmentManagement.DvRepair.confirmBy')" prop="confirmBy">
<el-select v-model="acceptanceForm.confirmBy" filterable class="!w-full" :placeholder="t('EquipmentManagement.DvRepair.placeholderConfirmBy')">
<el-option v-for="item in users" :key="String(item.id)" :label="item.nickname" :value="String(item.id)" />
</el-select>
</el-form-item>
<el-form-item :label="t('EquipmentManagement.DvRepair.confirmDate')" prop="confirmDate">
<el-date-picker
v-model="acceptanceForm.confirmDate"
type="datetime"
format="YYYY-MM-DD HH:mm:ss"
value-format="x"
class="!w-full"
:placeholder="t('EquipmentManagement.DvRepair.placeholderConfirmDate')"
/>
</el-form-item>
<el-form-item :label="t('EquipmentManagement.DvRepair.acceptanceResult')" prop="status">
<el-radio-group v-model="acceptanceForm.status">
<el-radio label="1">{{ t('EquipmentManagement.DvRepair.acceptancePassed') }}</el-radio>
<el-radio label="2">{{ t('EquipmentManagement.DvRepair.acceptanceRejected') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="acceptanceForm.status === '2'" :label="t('EquipmentManagement.DvRepair.rejectReason')" prop="rejectReason">
<el-input v-model="acceptanceForm.rejectReason" type="textarea" :rows="3" :placeholder="t('EquipmentManagement.DvRepair.rejectReasonPrompt')" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="acceptanceDialogVisible = false">{{ t('common.cancel') }}</el-button>
<el-button type="primary" :loading="acceptanceLoading" @click="submitAcceptance">{{ t('common.ok') }}</el-button>
</template>
</Dialog>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { DICT_TYPE } from '@/utils/dict' import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
import { dateFormatter, dateFormatter2 } from '@/utils/formatTime' import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
import download from '@/utils/download' import download from '@/utils/download'
import { DvRepairApi, DvRepairVO } from '@/api/mes/dvrepair' import { DvRepairApi, DvRepairVO } from '@/api/mes/dvrepair'
import { getSimpleUserList, UserVO } from '@/api/system/user'
import DvRepairForm from './DvRepairForm.vue' import DvRepairForm from './DvRepairForm.vue'
/** 设备维修记录 列表 */ /** 设备维修记录 列表 */
@ -270,17 +304,15 @@ const counters = reactive({
allCount: 0, allCount: 0,
pendingCount: 0, pendingCount: 0,
finishedCount: 0, finishedCount: 0,
pendingRepairCount: 0, pendingAcceptanceCount: 0,
passedCount: 0, rejectedCount: 0
failedCount: 0
}) })
const statusCards = computed(() => [ const statusCards = computed(() => [
{ key: 'all', label: t('EquipmentManagement.DvRepair.all'), value: counters.allCount, status: undefined, repairStatus: undefined }, { key: 'all', label: t('EquipmentManagement.DvRepair.all'), value: counters.allCount, status: undefined, repairStatus: undefined },
{ key: 'pending', label: t('EquipmentManagement.DvRepair.statusPending'), value: counters.pendingCount, status: '0', repairStatus: undefined }, { key: 'pending', label: getStatusLabel('0'), value: counters.pendingCount, status: '0', repairStatus: undefined },
{ key: 'finished', label: t('EquipmentManagement.DvRepair.statusFinished'), value: counters.finishedCount, status: '1', repairStatus: undefined }, { key: 'pendingAcceptance', label: getStatusLabel('3'), value: counters.pendingAcceptanceCount, status: '3', repairStatus: undefined },
{ key: 'pendingRepair', label: t('EquipmentManagement.DvRepair.repairResultPending'), value: counters.pendingRepairCount, status: undefined, repairStatus: '0' }, { key: 'finished', label: getStatusLabel('1'), value: counters.finishedCount, status: '1', repairStatus: undefined },
{ key: 'passed', label: t('EquipmentManagement.DvRepair.repairResultOk'), value: counters.passedCount, status: undefined, repairStatus: '1' }, { key: 'rejected', label: getStatusLabel('2'), value: counters.rejectedCount, status: '2', repairStatus: undefined }
{ key: 'failed', label: t('EquipmentManagement.DvRepair.repairResultNg'), value: counters.failedCount, status: undefined, repairStatus: '2' }
]) ])
const changeStatus = (key: string, status?: string, repairStatus?: string) => { const changeStatus = (key: string, status?: string, repairStatus?: string) => {
currentStatusKey.value = key currentStatusKey.value = key
@ -297,11 +329,8 @@ const toggleFilters = () => {
updatePlanTableMaxHeight() updatePlanTableMaxHeight()
} }
const statusOptions = [ const documentStatusOptions = computed(() => getStrDictOptions(DICT_TYPE.EQUIPMENT_DOCUMENT_STATUS))
{ label: t('EquipmentManagement.DvRepair.statusPending'), value: '0' }, const statusOptions = computed(() => documentStatusOptions.value)
{ label: t('EquipmentManagement.DvRepair.statusFinished'), value: '1' },
{ label: t('EquipmentManagement.DvRepair.statusRejected'), value: '2' }
]
const repairStatusOptions = [ const repairStatusOptions = [
{ label: t('EquipmentManagement.DvRepair.repairResultPending'), value: '0' }, { label: t('EquipmentManagement.DvRepair.repairResultPending'), value: '0' },
@ -311,10 +340,7 @@ const repairStatusOptions = [
const getStatusLabel = (value: any) => { const getStatusLabel = (value: any) => {
const v = value === '' || value === null || value === undefined ? undefined : String(value) const v = value === '' || value === null || value === undefined ? undefined : String(value)
if (v === '0') return t('EquipmentManagement.DvRepair.statusPending') return documentStatusOptions.value.find((item) => String(item.value) === v)?.label ?? '-'
if (v === '1') return t('EquipmentManagement.DvRepair.statusFinished')
if (v === '2') return t('EquipmentManagement.DvRepair.statusRejected')
return '-'
} }
const getStatusTagType = (value: any) => { const getStatusTagType = (value: any) => {
@ -322,6 +348,7 @@ const getStatusTagType = (value: any) => {
if (v === '1') return 'success' if (v === '1') return 'success'
if (v === '0') return 'warning' if (v === '0') return 'warning'
if (v === '2') return 'danger' if (v === '2') return 'danger'
if (v === '3') return 'primary'
return 'info' return 'info'
} }
@ -341,10 +368,7 @@ const getResultTagType = (value: any) => {
return 'info' return 'info'
} }
const isProcessedRepair = (value: any) => { const canRepair = (status: any) => ['0', '2'].includes(String(status))
const v = value === '' || value === null || value === undefined ? '0' : String(value)
return v !== '0'
}
const tableRef = ref() const tableRef = ref()
const planTableMaxHeight = ref(520) const planTableMaxHeight = ref(520)
@ -359,7 +383,6 @@ const updatePlanTableMaxHeight = async () => {
planTableMaxHeight.value = Math.min(window.innerHeight, Math.max(240, Math.floor(availableHeight))) planTableMaxHeight.value = Math.min(window.innerHeight, Math.max(240, Math.floor(availableHeight)))
} }
const selectedIds = ref<number[]>([]) const selectedIds = ref<number[]>([])
const rejectingId = ref<number | string>()
const handleSelectionChange = (rows: any[]) => { const handleSelectionChange = (rows: any[]) => {
selectedIds.value = rows?.map((row) => row.id).filter((id) => id !== undefined) ?? [] selectedIds.value = rows?.map((row) => row.id).filter((id) => id !== undefined) ?? []
} }
@ -374,9 +397,8 @@ const getList = async () => {
counters.allCount = Number(data?.allCount ?? data?.total ?? 0) counters.allCount = Number(data?.allCount ?? data?.total ?? 0)
counters.pendingCount = Number(data?.pendingCount ?? 0) counters.pendingCount = Number(data?.pendingCount ?? 0)
counters.finishedCount = Number(data?.finishedCount ?? 0) counters.finishedCount = Number(data?.finishedCount ?? 0)
counters.pendingRepairCount = Number(data?.pendingRepairCount ?? 0) counters.pendingAcceptanceCount = Number(data?.pendingAcceptanceCount ?? 0)
counters.passedCount = Number(data?.passedCount ?? 0) counters.rejectedCount = Number(data?.rejectedCount ?? 0)
counters.failedCount = Number(data?.failedCount ?? 0)
} finally { } finally {
loading.value = false loading.value = false
updatePlanTableMaxHeight() updatePlanTableMaxHeight()
@ -436,25 +458,61 @@ const handleBatchDelete = async () => {
await handleDelete(selectedIds.value) await handleDelete(selectedIds.value)
} }
const handleReject = async (id: number | string) => { const users = ref<UserVO[]>([])
try { const acceptanceDialogVisible = ref(false)
const { value } = await ElMessageBox.prompt( const acceptanceLoading = ref(false)
t('EquipmentManagement.DvRepair.rejectReasonPrompt'), const acceptanceFormRef = ref()
t('EquipmentManagement.DvRepair.reject'), const acceptanceForm = reactive({
{ id: undefined as number | string | undefined,
confirmButtonText: t('common.ok'), confirmBy: undefined as string | undefined,
cancelButtonText: t('common.cancel'), confirmDate: Date.now() as number | string,
inputPattern: /^[\s\S]*.*\S[\s\S]*$/, status: '1' as '1' | '2',
inputErrorMessage: t('EquipmentManagement.DvRepair.rejectReasonRequired') rejectReason: undefined as string | undefined
})
const acceptanceRules = reactive({
confirmBy: [{ required: true, message: t('EquipmentManagement.DvRepair.placeholderConfirmBy'), trigger: 'change' }],
confirmDate: [{ required: true, message: t('EquipmentManagement.DvRepair.validatorConfirmDateRequired'), trigger: 'change' }],
status: [{ required: true, message: t('EquipmentManagement.DvRepair.validatorAcceptanceResultRequired'), trigger: 'change' }],
rejectReason: [{
validator: (_: any, value: any, callback: any) => {
if (acceptanceForm.status === '2' && !String(value ?? '').trim()) {
callback(new Error(t('EquipmentManagement.DvRepair.rejectReasonRequired')))
return
} }
) callback()
rejectingId.value = id },
await DvRepairApi.rejectDvRepair({ id, rejectReason: value }) trigger: 'blur'
message.success(t('EquipmentManagement.DvRepair.rejectSuccess')) }]
})
const openAcceptance = async (row: DvRepairVO) => {
if (!users.value.length) users.value = (await getSimpleUserList()) ?? []
acceptanceFormRef.value?.resetFields?.()
acceptanceForm.id = row.id
acceptanceForm.confirmBy = undefined
acceptanceForm.confirmDate = Date.now()
acceptanceForm.status = '1'
acceptanceForm.rejectReason = undefined
acceptanceDialogVisible.value = true
}
const submitAcceptance = async () => {
await acceptanceFormRef.value?.validate()
if (acceptanceForm.id === undefined || acceptanceForm.id === null) return
acceptanceLoading.value = true
try {
await DvRepairApi.acceptanceDvRepair({
id: acceptanceForm.id,
confirmBy: acceptanceForm.confirmBy!,
confirmDate: acceptanceForm.confirmDate,
status: acceptanceForm.status,
rejectReason: acceptanceForm.status === '2' ? acceptanceForm.rejectReason?.trim() : undefined
})
message.success(t('EquipmentManagement.DvRepair.acceptanceSuccess'))
acceptanceDialogVisible.value = false
await getList() await getList()
} catch {
} finally { } finally {
rejectingId.value = undefined acceptanceLoading.value = false
} }
} }

@ -582,7 +582,12 @@ const getHistoryTimestamp = (history: MoldRepairAcceptanceHistoryVO) => {
const toTimestamp = (value: any): any => { const toTimestamp = (value: any): any => {
if (value === undefined || value === null || value === '') return undefined if (value === undefined || value === null || value === '') return undefined
if (typeof value === 'number') return value if (typeof value === 'number') return value
const timestamp = new Date(value).getTime() const text = String(value).trim()
if (/^\d+$/.test(text)) {
const timestamp = Number(text)
return Number.isFinite(timestamp) ? timestamp : undefined
}
const timestamp = new Date(text.replace(/-/g, '/')).getTime()
return Number.isNaN(timestamp) ? undefined : timestamp return Number.isNaN(timestamp) ? undefined : timestamp
} }
@ -590,9 +595,17 @@ const latestRepairHistoryIndex = computed(() => repairHistoryList.value.reduce((
return getHistoryTimestamp(history) >= getHistoryTimestamp(repairHistoryList.value[latestIndex]) ? index : latestIndex return getHistoryTimestamp(history) >= getHistoryTimestamp(repairHistoryList.value[latestIndex]) ? index : latestIndex
}, 0)) }, 0))
const repairHistoryOptions = computed(() => repairHistoryList.value.map((_, index) => ({ const formatHistoryTime = (history: MoldRepairAcceptanceHistoryVO) => {
const timestamp = toTimestamp(history.createTime ?? history.confirmDate ?? history.finishDate)
if (timestamp === undefined) return ''
const date = new Date(timestamp)
const pad = (value: number) => String(value).padStart(2, '0')
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
}
const repairHistoryOptions = computed(() => repairHistoryList.value.map((item, index) => ({
value: index, value: index,
label: `${t('MoldManagement.MoldRepair.historyRepairResult')} ${index + 1}` label: `${t('MoldManagement.MoldRepair.historyRepairResult')} ${index + 1}${formatHistoryTime(item) ? ` · ${formatHistoryTime(item)}` : ''}`
}))) })))
const displayedRepairHistory = computed(() => { const displayedRepairHistory = computed(() => {

Loading…
Cancel
Save