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.

270 lines
8.6 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 v-model="dialogVisible" :title="dialogTitle" width="1100px">
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" :row-key="getRowKey">
<el-table-column
type="index"
:label="t('EquipmentManagement.WorkOrderManagement.index')"
align="center"
width="70"
/>
<el-table-column
:label="t('EquipmentManagement.WorkOrderManagement.inspectionItemName')"
align="center"
prop="inspectionItemName"
min-width="180"
/>
<el-table-column
:label="t('EquipmentManagement.WorkOrderManagement.inspectionMethod')"
align="center"
prop="inspectionMethod"
min-width="140"
>
<template #default="scope">
<dict-tag type="Inspection_method" :value="scope.row.inspectionMethod" />
</template>
</el-table-column>
<el-table-column
:label="t('EquipmentManagement.WorkOrderManagement.judgmentCriteria')"
align="center"
prop="judgmentCriteria"
min-width="160"
/>
<el-table-column
:label="t('EquipmentManagement.WorkOrderManagement.inspectionResult')"
align="center"
prop="inspectionResult"
width="120"
>
<template #default="scope">
<el-tag v-if="String(scope.row.inspectionResult) === '0'" type="info">
{{ t('EquipmentManagement.WorkOrderManagement.jobResultPending') }}
</el-tag>
<el-tag v-else-if="String(scope.row.inspectionResult) === '1'" type="success">
{{ t('EquipmentManagement.WorkOrderManagement.jobResultOk') }}
</el-tag>
<el-tag v-else-if="String(scope.row.inspectionResult) === '2'" type="danger">
{{ t('EquipmentManagement.WorkOrderManagement.jobResultNg') }}
</el-tag>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column
:label="t('EquipmentManagement.WorkOrderManagement.images')"
align="center"
prop="images"
width="160"
>
<template #default="scope">
<UploadImg
v-if="String(scope.row.inspectionResult) === '0'"
v-model="imageMap[String(scope.row.id)]"
:drag="false" :show-btn-text="false" width="64px" height="64px" />
<el-image
v-else-if="scope.row.images"
:src="parseFirstImage(scope.row.images)"
:preview-src-list="parseImages(scope.row.images)" preview-teleported fit="cover"
style="width: 64px; height: 64px" />
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column
:label="t('EquipmentManagement.WorkOrderManagement.remark')"
align="center"
prop="remark"
min-width="160"
/>
<el-table-column
:label="t('EquipmentManagement.WorkOrderManagement.operate')"
align="center"
width="200"
fixed="right"
>
<template #default="scope">
<el-radio-group v-if="String(scope.row.inspectionResult) === '0'" v-model="decisionMap[String(scope.row.id)]">
<el-radio :label="'1'">{{ t('EquipmentManagement.WorkOrderManagement.ok') }}</el-radio>
<el-radio :label="'2'">{{ t('EquipmentManagement.WorkOrderManagement.ng') }}</el-radio>
</el-radio-group>
<span v-else>-</span>
</template>
</el-table-column>
</el-table>
<el-pagination
v-show="total > 0"
v-model:current-page="queryParams.pageNo"
v-model:page-size="queryParams.pageSize"
:background="true"
:page-sizes="[10, 20, 30, 50, 100]"
:pager-count="7"
:total="total"
class="mt-15px mb-15px flex justify-end"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange" />
<div v-if="String(jobStatus) === '4'" class="mt-10px text-14px">
<span>{{ t('EquipmentManagement.WorkOrderManagement.jobStatus') }}</span>
<dict-tag :type="'job_status'" :value="jobStatus" />
<span class="ml-20px">取消原因:</span>
<span>{{ cancelReason || '-' }}</span>
</div>
<template #footer>
<el-button @click="dialogVisible = false">{{ t('EquipmentManagement.WorkOrderManagement.dialogCancel') }}</el-button>
<el-button
type="primary"
@click="handleSave"
:loading="submitLoading"
:disabled="submitLoading || !isAllPendingSelected()"
>
{{ t('EquipmentManagement.WorkOrderManagement.dialogSave') }}
</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { TicketManagementApi, TicketResultVO } from '@/api/mes/ticketManagement'
defineOptions({ name: 'TicketResultDialog' })
const emit = defineEmits(['success'])
const message = useMessage()
const { t } = useI18n()
const dialogVisible = ref(false)
const dialogTitle = ref(t('EquipmentManagement.WorkOrderManagement.dialogTitleDefault'))
const loading = ref(false)
const submitLoading = ref(false)
const list = ref<TicketResultVO[]>([])
const total = ref(0)
const managementId = ref<number | undefined>(undefined)
const jobStatus = ref<string | number | undefined>(undefined)
const cancelReason = ref<string | undefined>(undefined)
const decisionMap = reactive<Record<string, '1' | '2' | undefined>>({})
const imageMap = reactive<Record<string, string>>({})
const queryParams = reactive({
pageNo: 1,
pageSize: 10
})
const open = async (options: { managementId: number; title?: string; jobStatus?: string | number; cancelReason?: string }) => {
dialogVisible.value = true
dialogTitle.value = options.title || t('EquipmentManagement.WorkOrderManagement.dialogTitleDefault')
managementId.value = options.managementId
jobStatus.value = options.jobStatus
cancelReason.value = options.cancelReason
for (const key of Object.keys(decisionMap)) delete decisionMap[key]
for (const key of Object.keys(imageMap)) delete imageMap[key]
queryParams.pageNo = 1
await getList()
}
defineExpose({ open })
const getList = async () => {
if (!managementId.value) return
loading.value = true
try {
const data = await TicketManagementApi.getTicketResultsPage({
pageNo: queryParams.pageNo,
pageSize: queryParams.pageSize,
managementId: managementId.value
})
list.value = data.list
total.value = data.total
for (const row of list.value) {
const id = row?.id
if (!id) continue
if (row.images && !imageMap[String(id)]) {
imageMap[String(id)] = parseFirstImage(row.images)
}
}
} finally {
loading.value = false
}
}
const handleSizeChange = () => {
queryParams.pageNo = 1
getList()
}
const handleCurrentChange = () => {
getList()
}
const handleSave = async () => {
const hasUnselected = list.value.some((row) => {
if (!row?.id) return false
if (String(row.inspectionResult) !== '0') return false
const decision = decisionMap[String(row.id)]
return !decision
})
if (hasUnselected) {
message.error(t('EquipmentManagement.WorkOrderManagement.selectAllDecisionError'))
return
}
const payload: TicketResultVO[] = []
for (const row of list.value) {
if (!row?.id) continue
if (String(row.inspectionResult) !== '0') continue
const decision = decisionMap[String(row.id)]
if (!decision) continue
const img = imageMap[String(row.id)]
payload.push({ ...(row as any), inspectionResult: decision, images: img || row.images })
}
if (!payload.length) {
message.error(t('EquipmentManagement.WorkOrderManagement.selectDecisionError'))
return
}
submitLoading.value = true
try {
await TicketManagementApi.batchUpdateTicketResults(payload)
message.success(t('EquipmentManagement.WorkOrderManagement.updateSuccess'))
emit('success')
dialogVisible.value = false
} catch {
message.error(t('EquipmentManagement.WorkOrderManagement.updateFail'))
} finally {
submitLoading.value = false
}
}
const isAllPendingSelected = () => {
for (const row of list.value) {
if (!row?.id) continue
if (String(row.inspectionResult) !== '0') continue
const decision = decisionMap[String(row.id)]
if (!decision) return false
}
return true
}
const getRowKey = (row: TicketResultVO) => {
return String(row.id ?? '')
}
const parseImages = (value: any): string[] => {
if (!value) return []
if (Array.isArray(value)) return value.map(String).filter(Boolean)
return String(value)
.split(',')
.map((v) => v.trim())
.filter(Boolean)
}
const parseFirstImage = (value: any): string => {
return parseImages(value)[0] || ''
}
</script>
<style scoped lang="scss">
:deep(.el-upload) {
margin: 0 auto;
}
</style>