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.
besure_web/src/views/mold/workOrderInquiry/components/TicketResultDialog.vue

316 lines
12 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="1500px">
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" :row-key="getRowKey">
<el-table-column type="index" :label="t('MoldManagement.TicketResultDialog.index')" align="center" width="70" />
<el-table-column :label="t('MoldManagement.TicketResultDialog.inspectionItemName')" align="center" prop="inspectionItemName" min-width="200" sortable />
<el-table-column :label="t('MoldManagement.TicketResultDialog.inspectionMethod')" align="center" prop="inspectionMethod" min-width="160">
<template #default="scope">
<dict-tag type="Inspection_method" :value="scope.row.inspectionMethod" />
</template>
</el-table-column>
<el-table-column :label="t('MoldManagement.TicketResultDialog.judgmentCriteria')" align="center" prop="judgmentCriteria" min-width="180" />
<el-table-column :label="t('MoldManagement.TicketResultDialog.inspectionResult')" align="center" prop="inspectionResult" min-width="140">
<template #default="scope">
<el-tag v-if="String(scope.row.inspectionResult) === '0'" type="info">{{ t('MoldManagement.TicketResultDialog.inspectionResultPending') }}</el-tag>
<el-tag v-else-if="String(scope.row.inspectionResult) === '1'" type="success">{{ t('MoldManagement.TicketResultDialog.inspectionResultPass') }}</el-tag>
<el-tag v-else-if="String(scope.row.inspectionResult) === '2'" type="danger">{{ t('MoldManagement.TicketResultDialog.inspectionResultFail') }}</el-tag>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column :label="t('MoldManagement.TicketResultDialog.images')" align="center" prop="images" min-width="260">
<template #default="scope">
<div
v-if="String(scope.row.inspectionResult) === '0'"
v-loading="isImageUploading(String(scope.row.id))"
element-loading-text="上传中"
class="ticket-result-images"
:class="{ 'is-full': (imageMap[String(scope.row.id)] || []).length >= 3 }"
>
<UploadImgs
v-model="imageMap[String(scope.row.id)]"
:limit="3"
width="64px"
height="64px"
@uploading-change="setImageUploading(String(scope.row.id), $event)"
/>
</div>
<div v-else-if="parseImages(scope.row.images).length" class="ticket-result-images">
<el-image
v-for="image in parseImages(scope.row.images)"
:key="image"
:src="image"
:preview-src-list="parseImages(scope.row.images)"
preview-teleported
fit="cover"
class="ticket-result-image"
/>
</div>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column :label="t('EquipmentManagement.DvSubject.valueType')" align="center" prop="valueType" width="120" sortable>
<template #default="scope">
<el-tag
v-if="scope.row.valueType !== undefined && scope.row.valueType !== null && String(scope.row.valueType) !== ''"
effect="light" :type="getTagType('value_types', scope.row.valueType)"
:color="getTagColor('value_types', scope.row.valueType)"
:style="getTagStyle('value_types', scope.row.valueType)" disable-transitions>
{{ getTagLabel('value_types', scope.row.valueType) }}
</el-tag>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column :label="t('MoldManagement.TicketResultDialog.inputValue')" align="center" min-width="150">
<template #default="scope">
<el-input
v-if="String(scope.row.valueType) === '0' || String(scope.row.valueType) === '2'"
v-model="scope.row.textInput"
:disabled="String(scope.row.inspectionResult) !== '0'"
clearable
:placeholder="t('common.inputText')"
/>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column :label="t('MoldManagement.TicketResultDialog.remark')" align="center" prop="remark" min-width="180">
<template #default="scope">
<el-input v-if="String(scope.row.inspectionResult) === '0'" v-model="scope.row.remark" clearable :placeholder="t('common.inputText')" />
<span v-else>{{ scope.row.remark || '-' }}</span>
</template>
</el-table-column>
<el-table-column :label="t('MoldManagement.TicketResultDialog.operate')" align="center" min-width="220" 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('MoldManagement.TicketResultDialog.pass') }}</el-radio>
<el-radio :label="'2'">{{ t('MoldManagement.TicketResultDialog.fail') }}</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('MoldManagement.MoldWorkOrderInquiry.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('MoldManagement.TicketResultDialog.cancel') }}</el-button>
<el-button v-if="String(jobStatus) === '0'" type="primary" @click="handleSave" :loading="submitLoading" :disabled="hasImageUploading">{{ t('MoldManagement.TicketResultDialog.save') }}</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { TicketManagementApi, TicketResultVO } from '@/api/mold/ticketManagement'
import { getStrDictOptions } from '@/utils/dict'
import { isHexColor } from '@/utils/color'
import { useDictStoreWithOut } from '@/store/modules/dict'
defineOptions({ name: 'TicketResultDialog' })
const emit = defineEmits(['success'])
const { t } = useI18n()
const message = useMessage()
const dictStore = useDictStoreWithOut()
const dictReady = ref(false)
const dialogVisible = ref(false)
const dialogTitle = ref('检验结果')
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 imageUploadingMap = reactive<Record<string, boolean>>({})
const hasImageUploading = computed(() => Object.values(imageUploadingMap).some(Boolean))
const setImageUploading = (key: string, value: boolean) => {
if (!key) return
if (value) {
imageUploadingMap[key] = true
} else {
delete imageUploadingMap[key]
}
}
const isImageUploading = (key: string) => {
return !!imageUploadingMap[key]
}
const getTagDict = (dictType: string, value: any) => {
if (!dictReady.value) return undefined
const v = value === '' || value === null || value === undefined ? undefined : String(value)
if (!v) return undefined
return getStrDictOptions(dictType).find((d) => d.value === v)
}
const getTagLabel = (dictType: string, value: any) => {
const found = getTagDict(dictType, value)
return found?.label ?? (value ?? '')
}
const getTagType = (dictType: string, value: any) => {
const found = getTagDict(dictType, value)
const type = found?.colorType
if (type + '' === 'primary' || type + '' === 'default') return '' as any
return (type ?? '') as any
}
const getTagColor = (dictType: string, value: any) => {
const found = getTagDict(dictType, value)
if (found?.cssClass && isHexColor(found.cssClass)) return found.cssClass
return ''
}
const getTagStyle = (dictType: string, value: any) => {
const color = getTagColor(dictType, value)
if (!color) return ''
return 'color: #fff'
}
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('MoldManagement.TicketResultDialog.moduleName')
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]
for (const key of Object.keys(imageUploadingMap)) delete imageUploadingMap[key]
queryParams.pageNo = 1
await getList()
}
defineExpose({ open })
onMounted(async () => {
await dictStore.setDictMap()
dictReady.value = true
})
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 (!imageMap[String(id)]) {
imageMap[String(id)] = parseImages(row.images).slice(0, 3)
}
}
} finally {
loading.value = false
}
}
const handleSizeChange = () => {
queryParams.pageNo = 1
getList()
}
const handleCurrentChange = () => {
getList()
}
const handleSave = async () => {
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 images = imageMap[String(row.id)]
payload.push({ ...(row as any), inspectionResult: decision, images: Array.isArray(images) ? images.join(',') : row.images })
}
if (!payload.length) {
message.error(t('MoldManagement.TicketResultDialog.selectDecisionTip'))
return
}
submitLoading.value = true
try {
await TicketManagementApi.batchUpdateTicketResults(payload)
message.success(t('MoldManagement.TicketResultDialog.updateSuccess'))
dialogVisible.value = false
emit('success')
} catch {
message.error(t('MoldManagement.TicketResultDialog.updateFail'))
} finally {
submitLoading.value = false
}
}
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)
}
</script>
<style scoped lang="scss">
:deep(.el-upload) {
margin: 0 auto;
}
.ticket-result-images {
display: flex;
justify-content: center;
min-height: 64px;
}
.ticket-result-images :deep(.el-upload-list--picture-card) {
display: flex;
flex-wrap: nowrap;
justify-content: center;
gap: 8px;
}
.ticket-result-images.is-full :deep(.el-upload--picture-card) {
display: none;
}
.ticket-result-image {
width: 64px;
height: 64px;
border: 1px solid var(--el-border-color-lighter);
border-radius: 6px;
}
</style>