You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

636 lines
23 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<Dialog :title="dialogTitle" v-model="dialogVisible" width="1200px" @closed="handleDialogClosed">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
<el-row>
<el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.repairCode')" prop="repairCode">
<template #label>
<span>
{{ t('EquipmentManagement.DvRepair.repairCode') }}
<el-tooltip :content="t('EquipmentManagement.DvRepair.repairCode')" placement="top">
<Icon icon="ep:question-filled" />
</el-tooltip>
</span>
</template>
<el-row :gutter="10" style="width: 100%;">
<el-col :xs="24" :sm="18" :md="16" :lg="14" :xl="12">
<el-input
:disabled="formData.isCode == true || formType === 'update'"
v-model="formData.repairCode"
:placeholder="t('common.code')"
/>
</el-col>
<el-col :xs="24" :sm="6" :md="4" :lg="3" :xl="2">
<div>
<el-switch
v-model="formData.isCode"
:disabled="formType === 'update'"
/>
</div>
</el-col>
</el-row>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.repairName')" prop="repairName">
<el-input
v-model="formData.repairName"
:placeholder="t('EquipmentManagement.DvRepair.placeholderRepairName')"
:disabled="isRepairMode" />
</el-form-item>
</el-col>
</el-row>
<el-form-item :label="t('EquipmentManagement.DvRepair.machineryTypeId')" prop="machineryTypeId">
<el-radio-group v-model="formData.machineryTypeId" :disabled="isRepairMode">
<el-radio :label="1">{{ t('EquipmentManagement.DvRepair.machineryTypeDevice') }}</el-radio>
<el-radio :label="2">{{ t('EquipmentManagement.DvRepair.machineryTypeKeyItem') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-row>
<el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.device')" prop="deviceId">
<el-select
v-model="formData.deviceId" filterable clearable :loading="deviceLoading"
:disabled="isRepairMode"
:placeholder="t('EquipmentManagement.DvRepair.placeholderDevice')" class="!w-full">
<el-option v-for="opt in deviceOptions" :key="String(opt.value)" :label="opt.label" :value="opt.value" />
</el-select>
</el-form-item>
<el-form-item v-if="showComponentSelect" :label="t('EquipmentManagement.DvRepair.component')" prop="componentId">
<el-select
v-model="formData.componentId" clearable :loading="componentLoading" :disabled="isRepairMode"
:placeholder="t('EquipmentManagement.DvRepair.placeholderComponent')" class="!w-full">
<el-option
v-for="opt in componentOptions" :key="String(opt.value)" :label="opt.label"
:value="opt.value" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.machineryName')" prop="machineryName" :required="false">
<el-input
v-model="formData.machineryName"
:placeholder="t('EquipmentManagement.DvRepair.placeholderAutoFill')"
disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.machineryCode')" prop="machineryCode" :required="false">
<el-input
v-model="formData.machineryCode"
:placeholder="t('EquipmentManagement.DvRepair.placeholderAutoFill')"
disabled />
</el-form-item></el-col>
<el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.machinerySpec')" prop="machinerySpec" :required="false">
<el-input
v-model="formData.machinerySpec"
:placeholder="t('EquipmentManagement.DvRepair.placeholderAutoFill')"
disabled />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.acceptedBy')" prop="acceptedBy">
<el-select
v-model="formData.acceptedBy" filterable clearable
:placeholder="t('EquipmentManagement.DvRepair.placeholderAcceptedBy')" class="!w-full"
:disabled="isRepairMode">
<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-form-item :label="t('EquipmentManagement.DvRepair.confirmBy')" prop="confirmBy">
<el-select
v-model="formData.confirmBy" filterable clearable
:placeholder="t('EquipmentManagement.DvRepair.placeholderConfirmBy')" class="!w-full"
:disabled="isRepairMode">
<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-row>
<template v-if="showRepairFields">
<el-row>
<el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.requireDate')" prop="requireDate">
<el-date-picker
v-model="formData.requireDate" type="date" value-format="x"
:placeholder="t('EquipmentManagement.DvRepair.placeholderRequireDate')"
class="!w-full" :disabled="repairFieldsDisabled" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.finishDate')" prop="finishDate">
<el-date-picker
v-model="formData.finishDate" type="date" value-format="x"
:placeholder="t('EquipmentManagement.DvRepair.placeholderFinishDate')"
class="!w-full" :disabled="repairFieldsDisabled" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="t('EquipmentManagement.DvRepair.confirmDate')" prop="confirmDate">
<el-date-picker
v-model="formData.confirmDate" type="date" value-format="x"
:placeholder="t('EquipmentManagement.DvRepair.placeholderConfirmDate')"
class="!w-full" :disabled="repairFieldsDisabled" />
</el-form-item>
</el-col>
</el-row>
<el-form-item :label="t('EquipmentManagement.DvRepair.repairResult')" prop="repairResult">
<Editor v-model="formData.repairResult" height="150px" :readonly="repairFieldsDisabled" />
</el-form-item>
</template>
</el-form>
<!-- 子表的表单 -->
<el-tabs v-model="subTabsName">
<el-tab-pane :label="t('EquipmentManagement.DvRepair.repairLineTitle')" name="dvRepairLine">
<DvRepairLineForm ref="dvRepairLineFormRef" :repair-id="formData.id" :line-mode="lineMode" />
</el-tab-pane>
</el-tabs>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">{{ t('common.ok') }}</el-button>
<el-button @click="dialogVisible = false">{{ t('common.cancel') }}</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { DvRepairApi, DvRepairVO } from '@/api/mes/dvrepair'
import DvRepairLineForm from './components/DvRepairLineForm.vue'
import { DeviceLedgerApi, DeviceLedgerVO } from '@/api/mes/deviceledger'
import { RepairItemsApi } from '@/api/mes/repairItems'
import { getSimpleUserList, UserVO } from '@/api/system/user'
/** 设备维修记录 表单 */
defineOptions({ name: 'DvRepairForm' })
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref('') // 表单的类型create - 新增update - 修改
const isRepairMode = computed(() => formType.value === 'update' || formType.value === 'repair')
const showRepairFields = computed(() => formType.value === 'update' || formType.value === 'repair')
const repairFieldsDisabled = computed(() => formType.value !== 'repair')
const isHydrating = ref(false)
const emit = defineEmits(['success', 'closed']) // 定义 success 事件,用于操作成功后的回调
const formData = ref({
id: undefined,
repairCode: undefined,
repairName: undefined,
deviceId: undefined as number | undefined,
componentId: undefined as number | undefined,
machineryId: undefined,
machineryCode: undefined,
machineryName: undefined,
machineryBrand: undefined,
machinerySpec: undefined,
machineryTypeId: undefined,
requireDate: undefined,
finishDate: undefined,
confirmDate: undefined,
repairResult: undefined,
acceptedBy: undefined,
confirmBy: undefined,
status: undefined,
remark: undefined,
isCode: undefined
})
const lineMode = computed(() => {
if (formType.value === 'repair') return 'repair' as const
if (formType.value === 'update') {
const v = formData.value.status === '' || formData.value.status === null || formData.value.status === undefined
? undefined
: String(formData.value.status)
if (v === '1') return 'readonlyWithResult' as const
}
return 'edit' as const
})
const showComponentSelect = computed(() => formData.value.machineryTypeId === 2)
const deviceLoading = ref(false)
const deviceOptions = ref<{ label: string; value: number; raw?: DeviceLedgerVO }[]>([])
const deviceOptionsLoaded = ref(false)
const componentLoading = ref(false)
const componentOptions = ref<{ label: string; value: number }[]>([])
const users = ref<UserVO[]>([])
const ensureUsersLoaded = async () => {
if (users.value.length) return
users.value = (await getSimpleUserList()) ?? []
}
const normalizeUserId = (value: any) => {
if (value === undefined || value === null || value === '') return undefined
const str = String(value)
if (/^\d+$/.test(str)) return str
const matched = users.value.find((u) => u.nickname === str)
return matched ? String(matched.id) : str
}
const upsertDeviceOption = (
options: { label: string; value: number; raw?: DeviceLedgerVO }[],
option: { label: string; value: number; raw?: DeviceLedgerVO }
) => {
const existed = options.some((o) => o.value === option.value)
return existed ? options : [option, ...options]
}
const toComponentOption = (item: any) => {
const id = typeof item?.id === 'number' ? item.id : Number(item?.id)
if (Number.isNaN(id)) return undefined
const code = item?.code ?? item?.componentCode ?? item?.subjectCode
const name = item?.name ?? item?.componentName ?? item?.subjectName
const label = `${code ?? ''} ${name ?? ''}`.trim() || String(id)
return { label, value: id }
}
const loadComponentOptionsByDeviceId = async (deviceId: number) => {
componentLoading.value = true
try {
const data = await RepairItemsApi.getComponentList(deviceId)
const rows = (Array.isArray(data) ? data : data?.list ?? data?.data ?? []) as any[]
componentOptions.value = rows.map(toComponentOption).filter(Boolean) as { label: string; value: number }[]
} finally {
componentLoading.value = false
}
}
const ensureDeviceOptionsLoaded = async () => {
if (deviceOptionsLoaded.value) return
deviceLoading.value = true
try {
const data = await DeviceLedgerApi.getDeviceLedgerList({})
const rows = (Array.isArray(data) ? data : data?.list ?? data?.data ?? []) as DeviceLedgerVO[]
deviceOptions.value = rows
.filter((r) => typeof r?.id === 'number')
.map((r) => ({ label: `${r.deviceCode ?? ''} ${r.deviceName ?? ''}`.trim(), value: r.id, raw: r }))
deviceOptionsLoaded.value = true
} finally {
deviceLoading.value = false
}
}
watch(
() => formData.value.machineryTypeId,
(val) => {
if (isHydrating.value) return
formData.value.deviceId = undefined
formData.value.componentId = undefined
formData.value.machineryId = undefined
formData.value.machineryCode = undefined
formData.value.machineryName = undefined
formData.value.machineryBrand = undefined
formData.value.machinerySpec = undefined
componentOptions.value = []
setLineRows([])
}
)
watch(
() => formData.value.deviceId,
async (deviceId) => {
if (isHydrating.value) return
formData.value.componentId = undefined
componentOptions.value = []
if (typeof deviceId !== 'number') {
setLineRows([])
}
const option = deviceOptions.value.find((o) => o.value === deviceId)
if (option?.raw) {
formData.value.machineryCode = option.raw.deviceCode
formData.value.machineryName = option.raw.deviceName
formData.value.machinerySpec = option.raw.deviceSpec
formData.value.machineryBrand = option.raw.deviceBrand
}
if (formData.value.machineryTypeId === 2 && typeof deviceId === 'number') {
await loadComponentOptionsByDeviceId(deviceId)
}
if (formData.value.machineryTypeId === 1 && typeof deviceId === 'number') {
await prefillLinesByDeviceOrComponent({ deviceId, deviceType: 1 })
}
}
)
watch(
() => formData.value.componentId,
async (componentId) => {
if (isHydrating.value) return
if (formData.value.machineryTypeId !== 2) return
const deviceId = formData.value.deviceId
if (typeof deviceId !== 'number' || typeof componentId !== 'number') {
setLineRows([])
return
}
await prefillLinesByDeviceOrComponent({ deviceId, componentId, deviceType: 2 })
}
)
const formRules = reactive({
repairCode: [
{
validator: (_: any, value: any, callback: any) => {
if (formType.value === 'update') {
callback()
return
}
if (formData.value.isCode === true) {
callback()
return
}
if (value === undefined || value === null || String(value).trim() === '') {
callback(new Error(t('EquipmentManagement.DvRepair.validatorRepairCodeRequired')))
return
}
callback()
},
trigger: 'blur',
},
],
deviceId: [{ required: true, message: t('EquipmentManagement.DvRepair.validatorMachineryIdRequired'), trigger: 'change' }],
componentId: [
{
validator: (_: any, value: any, callback: any) => {
if (formData.value.machineryTypeId !== 2) {
callback()
return
}
if (value === undefined || value === null || value === '') {
callback(new Error(t('EquipmentManagement.DvRepair.validatorComponentRequired')))
return
}
callback()
},
trigger: 'change',
},
],
machineryId: [{ required: true, message: t('EquipmentManagement.DvRepair.validatorMachineryIdRequired'), trigger: 'blur' }],
machineryCode: [{ required: true, message: t('EquipmentManagement.DvRepair.validatorMachineryCodeRequired'), trigger: 'blur' }],
machineryName: [{ required: true, message: t('EquipmentManagement.DvRepair.validatorMachineryNameRequired'), trigger: 'blur' }],
machineryTypeId: [{ required: true, message: t('EquipmentManagement.DvRepair.validatorMachineryTypeIdRequired'), trigger: 'blur' }],
requireDate: [
{
validator: (_: any, value: any, callback: any) => {
if (formType.value === 'repair' && !value) {
callback(new Error(t('EquipmentManagement.DvRepair.validatorRequireDateRequired')))
return
}
callback()
},
trigger: 'change',
},
],
finishDate: [
{
validator: (_: any, value: any, callback: any) => {
if (formType.value === 'repair' && !value) {
callback(new Error(t('EquipmentManagement.DvRepair.validatorFinishDateRequired')))
return
}
callback()
},
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',
},
],
repairResult: [
{
validator: (_: any, value: any, callback: any) => {
if (formType.value === 'repair' && !value) {
callback(new Error(t('EquipmentManagement.DvRepair.validatorRepairResultRequired')))
return
}
callback()
},
trigger: 'blur',
},
],
})
const formRef = ref() // 表单 Ref
watch(
() => formData.value.isCode,
(val) => {
if (val === true) {
formData.value.repairCode = undefined
}
formRef.value?.clearValidate?.(['repairCode'])
}
)
/** 子表的表单 */
const subTabsName = ref('dvRepairLine')
const dvRepairLineFormRef = ref()
const normalizeDeviceOrComponentList = (data: any) => {
const rows = (Array.isArray(data) ? data : data?.list ?? data?.data ?? []) as any[]
return rows
}
const toDvRepairLineRow = (item: any) => {
const subjectId = item?.subjectId ?? item?.id
return {
id: undefined,
repairId: formData.value.id,
subjectId,
subjectCode: item?.subjectCode ?? item?.subject_code ?? item?.code,
subjectName: item?.subjectName ?? item?.subject_name ?? item?.name,
subjectType: item?.subjectType ?? item?.subject_type ?? item?.type,
subjectContent: item?.subjectContent ?? item?.projectContent ?? item?.subject_content,
subjectStandard: item?.subjectStandard ?? item?.judgmentCriteria ?? item?.subject_standard,
malfunction: undefined,
malfunctionUrl: undefined,
repairDes: undefined,
remark: undefined
}
}
const setLineRows = (rows: any[]) => {
dvRepairLineFormRef.value?.setData(rows)
}
const prefillLinesByDeviceOrComponent = async (params: { deviceId: number; componentId?: number; deviceType: number }) => {
if (formType.value !== 'create') return
const data = await RepairItemsApi.getDeviceOrComponentList(params)
const list = normalizeDeviceOrComponentList(data)
setLineRows(list.map(toDvRepairLineRow))
}
let openRequestId = 0
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
const currentOpenId = ++openRequestId
dialogVisible.value = true
dialogTitle.value = type === 'repair' ? '维修' : t('action.' + type)
formType.value = type
resetForm()
await ensureUsersLoaded()
await ensureDeviceOptionsLoaded()
if (currentOpenId !== openRequestId) return
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
isHydrating.value = true
formData.value = await DvRepairApi.getDvRepair(id)
if (currentOpenId !== openRequestId) return
; (formData.value as any).requireDate = (formData.value as any).requireDate ?? undefined
; (formData.value as any).finishDate = (formData.value as any).finishDate ?? undefined
; (formData.value as any).confirmDate = (formData.value as any).confirmDate ?? undefined
; (formData.value as any).repairResult = (formData.value as any).repairResult ?? ''
; (formData.value as any).acceptedBy = normalizeUserId((formData.value as any).acceptedBy)
; (formData.value as any).confirmBy = normalizeUserId((formData.value as any).confirmBy)
const typeId = typeof formData.value.machineryTypeId === 'number' ? formData.value.machineryTypeId : Number(formData.value.machineryTypeId)
formData.value.machineryTypeId = Number.isNaN(typeId) ? formData.value.machineryTypeId : typeId
const deviceId = (formData.value as any).deviceId
const resolvedDeviceId = typeof deviceId === 'number' ? deviceId : formData.value.machineryId
if (typeof resolvedDeviceId === 'number') {
formData.value.deviceId = resolvedDeviceId
const label = `${formData.value.machineryCode ?? ''} ${formData.value.machineryName ?? ''}`.trim() || `ID:${resolvedDeviceId}`
deviceOptions.value = upsertDeviceOption(deviceOptions.value, { label, value: resolvedDeviceId })
}
if (formData.value.machineryTypeId === 2 && typeof formData.value.deviceId === 'number') {
await loadComponentOptionsByDeviceId(formData.value.deviceId)
const componentId = (formData.value as any).componentId
const resolvedComponentId = typeof componentId === 'number' ? componentId : Number(componentId)
if (!Number.isNaN(resolvedComponentId)) {
formData.value.componentId = resolvedComponentId
}
}
} finally {
isHydrating.value = false
formLoading.value = false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
const handleDialogClosed = () => {
openRequestId++
emit('closed')
}
onBeforeUnmount(() => {
openRequestId++
})
/** 提交表单 */
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 校验子表单
try {
await dvRepairLineFormRef.value.validate()
} catch (e) {
subTabsName.value = 'dvRepairLine'
return
}
// 提交请求
formLoading.value = true
try {
const data = { ...(formData.value as any) } as DvRepairVO & { deviceId?: number; componentId?: number }
; (data as any).acceptedBy = normalizeUserId((data as any).acceptedBy)
; (data as any).confirmBy = normalizeUserId((data as any).confirmBy)
if (formType.value === 'repair') {
; (data as any).status = 1
}
if (typeof formData.value.deviceId === 'number') {
data.machineryId = formData.value.deviceId as any
}
; (data as any).deviceId = formData.value.deviceId
; (data as any).componentId = formData.value.machineryTypeId === 2 ? formData.value.componentId : undefined
const lineList = dvRepairLineFormRef.value.getData() || []
if (formType.value === 'repair') {
const requireDate = data.requireDate
const finishDate = data.finishDate
const confirmDate = data.confirmDate
const repairResult = data.repairResult
const updateReqVOList = lineList
await DvRepairApi.updateDvRepairStatus({
id: data.id,
requireDate,
finishDate,
confirmDate,
repairResult,
updateReqVOList,
})
message.success(t('common.updateSuccess'))
} else {
; (data as any).dvRepairLines = lineList
if (formType.value === 'create') {
await DvRepairApi.createDvRepair(data)
message.success(t('common.createSuccess'))
} else {
await DvRepairApi.updateDvRepair(data)
message.success(t('common.updateSuccess'))
}
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
repairCode: undefined,
repairName: undefined,
deviceId: undefined,
componentId: undefined,
machineryId: undefined,
machineryCode: undefined,
machineryName: undefined,
machineryBrand: undefined,
machinerySpec: undefined,
machineryTypeId: 1,
requireDate: undefined,
finishDate: undefined,
confirmDate: undefined,
repairResult: '',
acceptedBy: undefined,
confirmBy: undefined,
status: undefined,
remark: undefined,
isCode: true
}
deviceOptionsLoaded.value = false
componentOptions.value = []
formRef.value?.resetFields()
}
</script>