heli-mes/mes-ui/mes-ui-admin-vue3/src/views/heli/inspectionreport/detail.vue
Ledo a1dfeda855 1.文件本地预览问题
2.页面弹窗复选问题
2025-05-06 16:22:31 +08:00

449 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-card class="hl-card">
<template #header>
<span><span v-html="dialogTitle"></span>页</span>
</template>
<el-form ref="formRef" label-width="140px" :rules="formRules" :model="formData" v-loading="formLoading">
<!-- 基础信息 横向布局 -->
<el-card class="hl-card-info">
<template #header>
<div class="hl-card-info-icona"></div><span class="hl-card-info-text">基础信息</span>
</template>
<el-row>
<el-col :span="6">
<el-form-item label="项目编号" prop="projectCode">
<el-input class="!w-260px" v-model="formData.projectCode" :disabled="true" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="项目名称" prop="projectName">
<el-input class="!w-260px" v-model="formData.projectName" :disabled="true" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="子项目编号" prop="projectSubCode">
<el-input class="!w-260px" v-model="formData.projectSubCode" :disabled="true" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="子项目名称" prop="projectSubName">
<el-input class="!w-260px" v-model="formData.projectSubName" :disabled="true" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="6">
<el-form-item label="客户名称" prop="customerName">
<el-input class="!w-260px" v-model="formData.customerName" :disabled="true" />
</el-form-item>
</el-col>
</el-row>
</el-card>
<!-- 表格类信息 -->
<el-card class="hl-card-info">
<template #header>
<div class="hl-card-info-icona"></div><span class="hl-card-info-text">检验报告</span>
</template>
<el-row>
<el-col>
<el-card class="hl-incard">
<el-col v-if="active != 'detail'">
<el-upload
ref="compositionUploadRef" :file-list="compositionUploadFiles" multiple :action="uploadUrl" :headers="{
Authorization: 'Bearer ' + getAccessToken(),
'tenant-id': getTenantId()
}" name="files" :show-file-list="false" :auto-upload="false" :data="compositionUploadData" :on-change="compositionUploadChange" :on-error="handleError" :on-success="handleSuccess" :before-upload="before" class="upload-file-uploader">
<el-button type="primary">
<Icon icon="ep:upload-filled" />上传材质报告
</el-button>
</el-upload>
<el-upload
ref="heatUploadRef" :file-list="heatUploadFiles" multiple :action="uploadUrl" :headers="{
Authorization: 'Bearer ' + getAccessToken(),
'tenant-id': getTenantId()
}" name="files" :show-file-list="false" :auto-upload="false" :data="heatUploadData" :on-change="heatUploadChange" :on-error="handleError" :on-success="handleSuccess" :before-upload="before" class="upload-file-uploader">
<el-button type="primary">
<Icon icon="ep:upload-filled" />上传热处理报告
</el-button>
</el-upload>
<el-upload
ref="scanUploadRef" :file-list="scanUploadFiles" multiple :action="uploadUrl" :headers="{
Authorization: 'Bearer ' + getAccessToken(),
'tenant-id': getTenantId()
}" name="files" :show-file-list="false" :auto-upload="false" :data="scanUploadData" :on-change="scanUploadChange" :on-error="handleError" :on-success="handleSuccess" :before-upload="before" class="upload-file-uploader">
<el-button type="primary">
<Icon icon="ep:upload-filled" />上传扫描报告
</el-button>
</el-upload>
<el-upload
ref="triUploadRef" :file-list="triUploadFiles" multiple :action="uploadUrl" :headers="{
Authorization: 'Bearer ' + getAccessToken(),
'tenant-id': getTenantId()
}" name="files" :show-file-list="false" :auto-upload="false" :data="triUploadData" :on-change="triUploadChange" :on-error="handleError" :on-success="handleSuccess" :before-upload="before" class="upload-file-uploader">
<el-button type="primary">
<Icon icon="ep:upload-filled" />上传三坐标检测报告
</el-button>
</el-upload>
<el-upload
ref="certificateUploadRef" :file-list="certificateUploadFiles" multiple :action="uploadUrl" :headers="{
Authorization: 'Bearer ' + getAccessToken(),
'tenant-id': getTenantId()
}" name="files" :show-file-list="false" :auto-upload="false" :data="certificateUploadData" :on-change="certificateUploadChange" :on-error="handleError" :on-success="handleSuccess" :before-upload="before" class="upload-file-uploader">
<el-button type="primary">
<Icon icon="ep:upload-filled" />上传合格证
</el-button>
</el-upload>
</el-col>
<el-table :data="formData.attachments" v-loading.fullscreen.lock="uploading" element-loading-text="附件上传中..." element-loading-background="rgba(122, 122, 122, 0.6)" class="hl-table">
<el-table-column fixed type="index" width="100" label="序号" align="center" />
<el-table-column prop="name" label="文件名称" align="center" />
<el-table-column prop="businessFileType" label="文件类型" align="center">
<template #default="scope">
{{
getDictLabel(DICT_TYPE.HELI_BUSINESS_FILE_TYPE, scope.row.businessFileType)
}}
</template>
</el-table-column>
<el-table-column prop="createTime" align="center" label="上传时间" :formatter="dateFormatter" />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button v-if="active != 'detail'" link type="danger" size="small" @click="handleDeleteAttachment(scope.$index, scope.row.businessFileType)">
删除
</el-button>
<el-button v-if="!!scope.row.id" link type="primary" size="small" @click="downloadAttachment(scope.row.name, scope.row.url)">
下载
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</el-col>
</el-row>
</el-card>
</el-form>
<div class="hl-footer text-center">
<el-button @click="goback" size="large">取 消</el-button>
<el-button v-if="active != 'detail'" @click="submitForm('SAVE')" type="primary" :disabled="formLoading" size="large">保 存</el-button>
</div>
</el-card>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import * as InspectionReportApi from '@/api/heli/inspectionreport'
import { inject } from 'vue'
import { useUserStore } from '@/store/modules/user'
import { useCommonStore } from '@/store/modules/common'
import { getAccessToken, getTenantId } from '@/utils/auth'
import { dateFormatter } from '@/utils/formatTime'
import { DICT_TYPE, getDictLabel } from '@/utils/dict'
import { UploadUserFile } from 'element-plus'
import { deleteFileLogic, downloadFile, getFilePage } from '@/api/infra/file'
import download from '@/utils/download'
defineOptions({ name: 'InspectionReportDetail' })
const reload: any = inject('reload')
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const commonStore = useCommonStore()
const userStore = useUserStore()
const router = useRouter()
const active = toRef(commonStore.getStore('active'))
const currentId = toRef(commonStore.getStore('id'))
const formLoading = ref(false)
const dialogTitle = ref('')
const detailDisabled = ref(false)
const businessType = 'INSPECTION_REPORT'
const formData: any = ref({
projectId: undefined,
projectSubId: undefined,
attachments: []
})
const formRef = ref() // 表单 Ref
const subFormRef = ref()
const formRules = reactive({})
/** 重置表单 */
const resetForm = () => {
formData.value = {
projectId: undefined,
projectSubId: undefined,
attachments: []
}
formRef.value?.resetFields()
}
const subFormLoading = ref(false) // 子表单的加载中
const subFormRules = reactive({})
const queryData = async (id?: number) => {
resetForm()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await InspectionReportApi.getInspectionReport(id)
// 附件信息
let attParams = {
pageNo: 1,
pageSize: 99,
businessId: id,
businessType: businessType
}
formData.value.attachments = (await getFilePage(attParams)).list
} finally {
formLoading.value = false
}
}
}
const submitForm = async (operate) => {
// 提交请求
formLoading.value = true
try {
// 上传附件
if (compositionUploadFiles.value.length > 0) {
compositionUploadData.value.businessId = formData.value.projectSubId
await compositionUploadRef.value!.submit()
}
if (heatUploadFiles.value.length > 0) {
heatUploadData.value.businessId = formData.value.projectSubId
await heatUploadRef.value!.submit()
}
if (scanUploadFiles.value.length > 0) {
scanUploadData.value.businessId = formData.value.projectSubId
await scanUploadRef.value!.submit()
}
if (triUploadFiles.value.length > 0) {
triUploadData.value.businessId = formData.value.projectSubId
await triUploadRef.value!.submit()
}
if (certificateUploadFiles.value.length > 0) {
certificateUploadData.value.businessId = formData.value.projectSubId
await certificateUploadRef.value!.submit()
}
message.success(t('common.operationSuccess'))
reload()
} finally {
formLoading.value = false
}
}
const goback = () => {
router.back()
}
// ====================附件信息 开始=======================================
const uploading = ref(false)
const uploadUrl = ref(import.meta.env.VITE_UPLOAD_BATCH_URL)
const compositionUploadRef = ref()
const compositionUploadFiles = ref<UploadUserFile[]>([])
const compositionUploadData = ref({
businessType: businessType,
businessId: formData.value.projectSubId,
businessFileType: 'COMPOSITION_REPORT'
})
const heatUploadRef = ref()
const heatUploadFiles = ref<UploadUserFile[]>([])
const heatUploadData = ref({
businessType: businessType,
businessId: formData.value.projectSubId,
businessFileType: 'HEAT_TREATMENT_REPORT'
})
const scanUploadRef = ref()
const scanUploadFiles = ref<UploadUserFile[]>([])
const scanUploadData = ref({
businessType: businessType,
businessId: formData.value.projectSubId,
businessFileType: 'SCAN_REPORT'
})
const triUploadRef = ref()
const triUploadFiles = ref<UploadUserFile[]>([])
const triUploadData = ref({
businessType: businessType,
businessId: formData.value.projectSubId,
businessFileType: 'TRI_LINEAR_COORDINATES_MEASURING'
})
const certificateUploadRef = ref()
const certificateUploadFiles = ref<UploadUserFile[]>([])
const certificateUploadData = ref({
businessType: businessType,
businessId: formData.value.projectSubId,
businessFileType: 'CERTIFICATE_OF_QUALIFICATION'
})
const compositionUploadChange = (file, files) => {
compositionUploadFiles.value = files
refreshAttachments(files, 'COMPOSITION_REPORT')
}
const heatUploadChange = (file, files) => {
heatUploadFiles.value = files
refreshAttachments(files, 'HEAT_TREATMENT_REPORT')
}
const scanUploadChange = (file, files) => {
scanUploadFiles.value = files
refreshAttachments(files, 'SCAN_REPORT')
}
const triUploadChange = (file, files) => {
triUploadFiles.value = files
refreshAttachments(files, 'TRI_LINEAR_COORDINATES_MEASURING')
}
const certificateUploadChange = (file, files) => {
certificateUploadFiles.value = files
refreshAttachments(files, 'CERTIFICATE_OF_QUALIFICATION')
}
// 记录待上传、成功上传及失败上传的文件数量
const sumbefore = ref(0)
const successfulUploadsCount = ref(0)
const failedUploadsCount = ref(0)
const failedAttachments = ref<UploadUserFile[]>([])
const failedAttachmentsName = ref()
// 处理单个文件上传成功的情况
const handleSuccess = (response: any, file: UploadUserFile) => {
successfulUploadsCount.value++
}
// 处理单个文件上传失败的情况
const handleError = (error: Error, file: UploadUserFile) => {
failedUploadsCount.value++
if (failedUploadsCount.value > 0) {
// 当有上传错误时
// 将失败的附件添加到failedAttachments.value数组中
failedAttachments.value.push(file)
failedAttachmentsName.value = failedAttachments.value.map((value) => value.name)
}
}
// 储存已上传文件的名称唯一标识
const uploadedFiles = ref([]);
// 文件上传前的钩子用于检查文件是否已存在
const before = (file) => {
// console.log('文件名', file.name);
const fileName: any = file.name;
// 检查文件名是否存在并确保操作的原子性
if (!uploadedFiles.value.includes(fileName)) {
uploadedFiles.value.push(fileName);
sumbefore.value++
return true; // 允许上传
}
// console.log('文件已存在!');
return false; // 阻止上传
}
const newfiless: any = ref([])
const filess: any = ref([])
const refreshAttachments = (files, type) => {
files.forEach((file) => {
const hasDuplicate = newfiless.value.filter((item) => {
return file.name == item.name
})
if (hasDuplicate.length > 0) {
// console.log('重复文件', hasDuplicate)
} else {
newfiless.value.push(file)
formData.value.attachments = [
...formData.value.attachments,
{ ...file, businessFileType: type, createTime: new Date() }
]
}
})
// 排序
formData.value.attachments.sort((v1, v2) => v1.createTime - v2.createTime)
// 文件上传一遍 上传总数等于要上传文件时 刷新页面
const sum = successfulUploadsCount.value + failedUploadsCount.value
// console.log('上传总数', sum)
// console.log('要上传文件数量', sumbefore.value)
if (sumbefore.value !== sum && sumbefore.value !== 0 && sum !== 0) {
// console.log('要上传文件数量不等于上传总数时等待',uploading.value)
uploading.value = true
} else if (sum == sumbefore.value && sumbefore.value > 0 && sum > 0) {
// console.log('要上传文件数量等于上传总数 刷新页面并给出提示')
if (failedUploadsCount.value > 0) {
ElMessageBox.alert(
// 使用错误信息作为提示内容
`文件名为:${failedAttachmentsName.value.join(' / ')}上传失败`,
`文件格式不正确或网络问题 请您稍后再试`,
{
dangerouslyUseHTMLString: false, // 由于我们不是使用HTML字符串所以这里设置为false
confirmButtonText: '知道了',
center: true
}
)
}
reload()
uploading.value = false
}
}
// 删除附件
const handleDeleteAttachment = async (index, type) => {
const deletedAttachments = formData.value.attachments.splice(index, 1)
for (let i = 0; i < deletedAttachments.length; i++) {
const attachment = deletedAttachments[i]
if (attachment.id) {
// 清理已上传文件
await deleteFileLogic(attachment.id)
}
// 清理待上传文件
compositionUploadFiles.value = compositionUploadFiles.value.filter((file1) => {
return file1.name != attachment.name || file1.businessFileType != type
})
heatUploadFiles.value = heatUploadFiles.value.filter((file2) => {
return file2.name != attachment.name || file2.businessFileType != type
})
scanUploadFiles.value = scanUploadFiles.value.filter((file3) => {
return file3.name != attachment.name || file3.businessFileType != type
})
triUploadFiles.value = triUploadFiles.value.filter((file4) => {
return file4.name != attachment.name || file4.businessFileType != type
})
certificateUploadFiles.value = certificateUploadFiles.value.filter((file5) => {
return file5.name != attachment.name || file5.businessFileType != type
})
}
}
// 下载文件
const downloadAttachment = async (name, url) => {
const baseUrl = import.meta.env.VITE_BASE_URL;
url =baseUrl+'/admin-api/'+ url.split('/admin-api/')[1]; const data = await downloadFile(url)
download.any(data, name)
}
onMounted(() => {
dialogTitle.value = t('action.' + active.value)
if ('detail' == active.value) {
detailDisabled.value = true
}
queryData(currentId.value)
})
</script>
<style scoped>
.upload-file-uploader {
margin-bottom: 10px;
display: inline-block;
margin-right: 20px;
}
</style>