| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563 |
- <template>
- <div class="prepare-detail-container">
- <!-- 固定头部区域 -->
- <div class="header fixed-header">
- <div class="btns">
- <el-button v-for="(btn, index) in getButtonListByStatus" :key="index" :type="btn.type" @click="btn.callback">
- <el-icon v-if="btn.icon"><component :is="btn.icon" :key="index"/></el-icon>
- {{btn.title}}
- </el-button>
- </div>
- </div>
-
- <!-- 可滚动内容区域 -->
- <div class="scrollable-content">
- <div id="prepareDetail" v-loading="loading">
- <el-collapse :model-value="['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14']" class="custom-collapse-form" v-loading="functionalStore.loading">
- <!-- <el-collapse-item title="基础信息" name="1"><BasicInfo ref="basicInfoRef" :instanceId="instanceId" :isEdit="false"/></el-collapse-item> -->
- <!-- <el-collapse-item title="委托单位" name="2"><UnitInfo ref="unitInfoRef" :instanceId="instanceId" :isEdit="false"/></el-collapse-item> -->
- <!-- <el-collapse-item title="使用单位" name="3" v-if="['2636eba25f3aae0f04fc85706da9f748'].includes(baseInfo.acceptanceTemplateId)">
- <UseUnitInfo ref="useUnitInfoRef" :instanceId="instanceId" :isEdit="false"/>
- </el-collapse-item> -->
- <!-- <el-collapse-item title="样品信息" name="4"><SampleList :instanceId="instanceId" :isEdit="false"/></el-collapse-item> -->
- <!-- <el-collapse-item title="样品信息" name="5"><SampleProcessInfo ref="sampleProcessInfoRef" :instanceId="instanceId" :isEdit="false"/></el-collapse-item> -->
- <el-collapse-item title="检验信息" name="6"><CheckItemInfo ref="checkItemInfoRef" :instanceId="instanceId" :isEdit="false" :rollbackFlag="'authorized'"/></el-collapse-item>
- <!-- <el-collapse-item title="检验项目" name="7"><CheckItemList :instanceId="instanceId" :showChildren="true" :showTool="false" page="report"/></el-collapse-item> -->
- <el-collapse-item title="报告结论" name="13"><ReportConclusion ref="reportConclusionRef" :instanceId="instanceId" :isDetail="isDetail"/></el-collapse-item>
- <el-collapse-item title="报告附件" name="14" v-if="!isDetail">
- <el-row :gutter="36">
- <el-col :span="12" style="margin-bottom: 18px;">
- <el-button type="primary" @click="handleEditAttachment">编辑报告附件</el-button>
- </el-col>
- </el-row>
- </el-collapse-item>
- <!-- <el-collapse-item title="检验收费" name="8"><CheckFeeCopy ref="checkFeeRef" :instanceId="instanceId" :isEdit="false"/></el-collapse-item>
- <el-collapse-item title="报告信息" name="9"><ReportInfo :instanceId="instanceId" :isEdit="false"/></el-collapse-item>
- <el-collapse-item title="特殊要求" name="11"><SpecialRequirements :instanceId="instanceId" :isEdit="false"/></el-collapse-item>
- <el-collapse-item title="科技成果" name="12"><TechnicalAchievements :instanceId="instanceId" :isEdit="false"/></el-collapse-item> -->
- </el-collapse>
- </div>
- </div>
- </div>
-
- <EditSpreadRecord
- v-if="showPreviewReport"
- v-model:visible="showPreviewReport"
- :type="reportType"
- :reportUrl="currentInstance.reportConclusion.reportUrl"
- :templateParams="templateParams"
- @refresh="handleUpdateDetailData"
- />
- <!-- 型式试验 -->
- <EditSpreadEditOtherFileRecord
- v-if="showPreviewEditOtherFileReport"
- v-model:visible="showPreviewEditOtherFileReport"
- :type="showPreviewEditOtherFileReportType"
- :reportUrl="currentInstance.reportConclusion.typeInspectionReportUrl"
- :templateParams="editOtherFileTemplateParams"
- @refresh="handleUpdateDetailData"
- />
- <AuditUserDialog
- v-if="isShowApprovalByDialog"
- v-model="isShowApprovalByDialog"
- :apiFn="getAuditList"
- :apiParams="{roleCode: 'sysbgspr'}"
- title="请选择报告审批人"
- :deptIdDefaultFlag="true"
- selectedAlertText="已选择报告审批人"
- :columns="auditDialogColumns"
- :searchFormProps="labelWidthDefault"
- @confirm="handleApprovalBySelectConfirm"
- />
- <!-- 文件预览组件 -->
- <FilePreview
- v-if="previewVisible"
- v-model="previewVisible"
- :id="currentPreviewId"
- :filename="currentFilename"
- :title="'文件预览'"
- :isEditOtherFileFlag="typeFlag"
- @close="handlePreviewClose"
- />
- </template>
- <script lang="tsx" setup>
- const EditSpreadRecord = defineAsyncComponent(() => import('./EditSpreadRecord.vue'))
- const EditSpreadEditOtherFileRecord = defineAsyncComponent(() => import('./components/EditSpreadEditOtherFileRecord.vue'))
- const BasicInfo = defineAsyncComponent(() => import('@/views/Functional/components/BasicInfo.vue'))
- const UnitInfo = defineAsyncComponent(() => import('@/views/Functional/components/UnitInfo.vue'))
- const UseUnitInfo = defineAsyncComponent(() => import('@/views/Functional/components/UseUnitInfo.vue'))
- // const SampleList = defineAsyncComponent(() => import('@/views/Functional/components/SampleList.vue'))
- const SampleList = defineAsyncComponent(() => import('@/views/Task/components/SampleList.vue'))
- const SampleProcessInfo = defineAsyncComponent(() => import('@/views/Functional/components/SampleProcessInfo.vue'))
- const CheckItemInfo = defineAsyncComponent(() => import('@/views/Functional/components/CheckItemInfoCopy.vue'))
- // const CheckFee = defineAsyncComponent(() => import('@/views/Functional/components/CheckFee.vue'))
- const CheckFeeCopy = defineAsyncComponent(() => import('@/views/Functional/components/CheckFeeCopy.vue'))
- const ReportInfo = defineAsyncComponent(() => import('@/views/Functional/components/ReportInfo.vue'))
- const ReportDistributionMethod = defineAsyncComponent(() => import('@/views/Functional/components/ReportDistributionMethod.vue'))
- const SpecialRequirements = defineAsyncComponent(() => import('@/views/Functional/components/SpecialRequirements.vue'))
- const TechnicalAchievements = defineAsyncComponent(() => import('@/views/Functional/components/TechnicalAchievements.vue'))
- const ReportConclusion = defineAsyncComponent(() => import('./components/ReportConclusion.vue'))
- const CheckItemList = defineAsyncComponent(() => import('@/views/TaskEnter/components/CreateOrEditCheckRecord.vue'))
- const AuditUserDialog = defineAsyncComponent(() => import('@/views/Functional/components/AuditUserDialog.vue'))
- import FilePreview from './components/FilePreview.vue'
- import { DocumentCopy, Check, Close, CircleCheck, ArrowLeft, Document } from '@element-plus/icons-vue'
- import { useFunctionalStore } from '@/store/modules/laboratory/functional'
- import { useTagsViewStore } from '@/store/modules/tagsView'
- import { useRoute, useRouter } from "vue-router";
- import { getAuditList } from '@/api/laboratory/functional'
- import { updateReportFileUrl, previewPrepareReport, withdrawReportPreparation } from '@/api/laboratory/functional/report'
- import _ from 'lodash'
- import { useEmitt } from '@/hooks/web/useEmitt'
- const { emitter } = useEmitt()
- const currentFilename = ref<string>('')
- const currentFilesize = ref<string>('200')
- const currentPreviewId = ref<string>('')
- const previewVisible = ref<boolean>(false)
- const typeFlag = ref<boolean>(false)
- const tagsViewStore = useTagsViewStore()
- const functionalStore = useFunctionalStore()
- const route = useRoute()
- const router = useRouter()
- const reportConclusionRef = ref()
- const labelWidthDefault = ref({labelWidth: 'auto'})
- const auditDialogColumns = computed(() => [
- {
- type: 'selection',
- fieldProps: {
- reserveSelection: true
- }
- },
- {
- label: '姓名',
- prop: 'nickName',
- search: {
- type: 'input',
- span: 12,
- placeholder: '请输入姓名'
- },
- render: (row) => {
- return row?.nickname || '-'
- }
- },
- {
- label: '部门',
- prop: 'deptId',
- search: {
- type: 'DeptSelect',
- span: 12,
- placeholder: '请选择部门'
- },
- render: (row) => {
- return row?.deptName || '-'
- }
- }
- ])
- // 生成唯一实例ID(使用路由路径+参数)
- const instanceId = computed(() =>
- `reportPreparation-${route.query.id}`
- )
- // 获取当前实例状态(自动创建隔离状态)
- let currentInstance = reactive(functionalStore.getInstance(instanceId.value))
- console.log(currentInstance, 'currentInstance数据')
- const { baseInfo } = toRefs(currentInstance)
- const loading = ref(false)
- // 在onMounted中合并初始化请求
- onMounted(async () => {
- if(route.query?.id) {
- console.log('进入详情页')
- await functionalStore.getReportPreparationInfo(instanceId.value, route.query.id)
- }
- functionalStore.fecthDeptList(),
- functionalStore.fetchStandardClassList(),
- functionalStore.fetchUnitList()
- })
- // 组件卸载时清理状态(可选)
- onUnmounted(() => {
- functionalStore.clearInstance(instanceId.value)
- })
- const isShowApprovalByDialog = ref(false) // 审批人弹窗
- const buttonsList = shallowRef([
- {
- type: 'primary',
- title: '预览报告',
- icon: CircleCheck,
- callback: () => handlePreviewContracts(),
- show: () => !currentInstance.reportConclusion.reportUrl ? false : true,
- reportStatus: ['0', '1', '2', '3']
- },
- {
- type: 'warning',
- title: '预览型式试验报告',
- icon: CircleCheck,
- callback: () => handlePreviewTypeInspectionRepor(),
- show: () => !currentInstance.reportConclusion.typeInspectionReportUrl ? false : true,
- reportStatus: ['0', '1', '2', '3']
- },
- {
- type: 'warning',
- title: '编制型式试验报告',
- icon: Document,
- callback: () => handleEditOtherFileFn(),
- show: () => currentInstance.allTaskInfo?.businessAcceptanceRespVO?.isTypeTest =='1' ? true : false,
- reportStatus: ['0', '1', '3']
- },
- {
- type: 'primary',
- title: '编制报告',
- icon: Document,
- callback: () => handlePrepareReport(),
- reportStatus: ['0', '1', '3']
- },
- {
- type: 'success',
- title: '档案管理',
- icon: Document,
- callback: () => handleArchivesManagement(),
- reportStatus: ['0', '1', '2', '3']
- },
- {
- type: 'primary',
- title: '提交',
- icon: Check,
- callback: () => handleSubmit(),
- show: () => !currentInstance.reportConclusion.reportUrl ? false : true,
- reportStatus: ['0', '1', '3']
- },
- {
- type: 'primary',
- title: '保存数据',
- icon: DocumentCopy,
- callback: () => handleCache(),
- reportStatus: ['0', '1', '3']
- },
- {
- type: 'primary',
- title: '回退',
- icon: ArrowLeft,
- callback: () => handleRejectSubmit(),
- reportStatus: ['0', '1', '3']
- },
- {
- type: 'danger',
- title: '退出',
- icon: Close,
- callback: () => handleClose(),
- reportStatus: ['0', '1', '2', '3']
- }
- ])
- const isDetail = computed(()=> {
- return currentInstance.allTaskInfo.reportStatus == '2' ? true : false;
- })
- const getButtonListByStatus = computed(() => {
- console.log(currentInstance, 'currentInstance')
- return buttonsList.value.filter(item => {
- const checkTypeCondition = !_.has(item, 'checkType') || (item.checkType || []).some(x => currentInstance.CheckItemInfo.checkType.includes(x));
- const reportStatusCondition = item.reportStatus.includes(currentInstance.allTaskInfo.reportStatus);
- const showCondition = !item.show || item.show();
- return checkTypeCondition && reportStatusCondition && showCondition;
- });
- });
- // 提交详情页
- const showPreviewReport = ref(false)
- const showPreviewEditOtherFileReport = ref(false)
- const reportType = ref('')
- const showPreviewEditOtherFileReportType = ref('')
- const templateParams = ref({})
- const editOtherFileTemplateParams = ref({})
- // 必须要报告编制完成之后,才能提交审核
- const handleSubmit = async () => {
- if(!currentInstance.reportConclusion.reportUrl) {
- ElMessage.error('请先编制报告')
- return
- }
- //如果是型式试验 要判断型式试验报告url是否存在
- if (currentInstance.allTaskInfo?.businessAcceptanceRespVO?.isTypeTest =='1') {
- if(!currentInstance.reportConclusion.typeInspectionReportUrl) {
- ElMessage.error('请先编制型式试验报告')
- return
- }
- }
- // console.log(currentInstance, 'currentInstance')
- Promise.all([reportConclusionRef.value.validateForm()]).then(async () => {
- isShowApprovalByDialog.value = true
- }).catch(err => {
- ElMessage.error('存在未填写的必填项!')
- console.log(err)
- })
- }
- // 选择审批人
- const handleApprovalBySelectConfirm = async (res) => {
- currentInstance.reportConclusion.reportApprovalBy = res[0]
- const result = await functionalStore.submitReport(instanceId.value, route.query.id)
- if(result === 'success') {
- // 提交成功
- handleClose()
- }
- }
- // 暂存详情页
- const handleCache = async () => {
- const result = await functionalStore.reportCache(instanceId.value, route.query.id)
- if(result === 'success') {
- handleClose()
- }
- }
- // 退出详情页
- const handleClose = () => {
- functionalStore.clearInstance(instanceId.value)
- tagsViewStore.closeSelectedTag(route)
- router.push({ path: '/laboratory/reportPreparation/list' })
- emitter.emit('refresh-reportPreparationIndex-list')
- }
- const handlePreviewClose = () => {
- currentPreviewId.value = ''
- currentFilename.value = ''
- previewVisible.value = false
- }
- // 撤回
- const handleRejectSubmit = () => {
- ElMessageBox.confirm('确认回撤该已编制的报告吗?', '提示', {
- confirmButtonText: '确 认',
- cancelButtonText: '取 消'
- })
- .then(async () => {
- try {
- const result = await withdrawReportPreparation({id: route.query.id})
- if(result) {
- ElMessage.success('回撤成功!')
- handleClose()
- }
- } catch (err) {
- ElMessage.error('回撤失败' + JSON.stringify(err))
- }
- })
- .catch(() => console.info('取消回撤'))
- }
- // 预览并打印合同
- const handlePreviewContracts = async () => {
- if (!currentInstance.reportConclusion.reportUrl) {
- return ElMessage.error('请先编制报告')
- }
- typeFlag.value = false
- currentPreviewId.value = route.query.id?.toString()
- currentFilename.value = `报告编号 ${currentInstance.allTaskInfo.reportNo}`
- previewVisible.value = true
- // const result = await previewPrepareReport({id: route.query.id})
- // loading.value = true
- // const previewFile = await previewPrepareReport({id: route.query.id})
- // if(previewFile) {
- // const flow = new Blob([previewFile], { type: 'application/pdf' })
- // const url = window.URL.createObjectURL(flow)
- // window.open(url, '_blank')
- // loading.value = false
- // }
- }
- const handlePreviewTypeInspectionRepor = async () => {
- console.log(currentInstance.reportConclusion, 'currentInstance.reportConclusion')
- if (!currentInstance.reportConclusion.typeInspectionReportUrl) {
- return ElMessage.error('请先编制型式试验报告')
- }
- typeFlag.value = true
- currentPreviewId.value = route.query.id?.toString()
- currentFilename.value = `报告编号 ${currentInstance.allTaskInfo.reportNo}`
- previewVisible.value = true
- // const result = await previewPrepareReport({id: route.query.id})
- // loading.value = true
- // const previewFile = await previewPrepareReport({id: route.query.id})
- // if(previewFile) {
- // const flow = new Blob([previewFile], { type: 'application/pdf' })
- // const url = window.URL.createObjectURL(flow)
- // window.open(url, '_blank')
- // loading.value = false
- // }
- }
- // 编辑附件报告
- const handleEditAttachment = () => {
- // 先填写报告结论,并且保存报告结论后,才可以编制报告
- Promise.all([reportConclusionRef.value.validateField('checkConclusion')]).then(async () => {
- if (!currentInstance.reportConclusion.checkConclusionOld) {
- const result = await functionalStore.reportCache(instanceId.value, route.query.id)
- await functionalStore.getReportPreparationInfo(instanceId.value, route.query.id)
- if (result === 'success') {
- showPreviewReport.value = true
- templateParams.value = {
- type: '2'
- }
- }
- }else {
- showPreviewReport.value = true
- }
- }).catch(err => {
- return ElMessage.warning('请先填写检验结论')
- })
- }
- // 编制报告
- const handlePrepareReport = () => {
- const verifyStatusFlag = currentInstance.businessCheckProjectDOS.every(x => x.verifyStatus == '1');
- if (!verifyStatusFlag) {
- return ElMessage.error('存在待校核的检验项目')
- }
- if (currentInstance.businessCheckProjectDOS)
- // 先填写报告结论,并且保存报告结论后,才可以编制报告
- Promise.all([reportConclusionRef.value.validateField('checkConclusion')]).then(async () => {
- if (!currentInstance.reportConclusion.checkConclusionOld) {
- const result = await functionalStore.reportCache(instanceId.value, route.query.id)
- await functionalStore.getReportPreparationInfo(instanceId.value, route.query.id)
- if (result === 'success') {
- showPreviewReport.value = true
- }
- }else {
- showPreviewReport.value = true
- }
- }).catch(err => {
- return ElMessage.warning('请先填写检验结论')
- })
- }
- // 编制型式试验报告
- const handleEditOtherFileFn = () => {
- const verifyStatusFlag = currentInstance.businessCheckProjectDOS.every(x => x.verifyStatus == '1');
- if (!verifyStatusFlag) {
- return ElMessage.error('存在待校核的检验项目')
- }
- // 先填写报告结论,并且保存报告结论后,才可以编制报告
- Promise.all([reportConclusionRef.value.validateField('checkConclusion')]).then(async () => {
- if (!currentInstance.reportConclusion.checkConclusionOld) {
- const result = await functionalStore.reportCache(instanceId.value, route.query.id)
- await functionalStore.getReportPreparationInfo(instanceId.value, route.query.id)
- if (result === 'success') {
- showPreviewEditOtherFileReport.value = true
- }
- }else {
- showPreviewEditOtherFileReport.value = true
- }
- }).catch(err => {
- return ElMessage.warning('请先填写检验结论')
- })
- }
- const handleArchivesManagement = ()=> {
- router.push({ name: 'reportArchivedFilesDetail',
- query: {
- id: route.query.id,
- }})
- }
- const { reportConclusion } = toRefs(currentInstance)
- // 获取新的报告编制详情
- const handleUpdateDetailData = async () => {
- templateParams.value = {}
- // 缓存报告结论等
- const cacheConclusion = JSON.parse(JSON.stringify(currentInstance.reportConclusion))
- await functionalStore.getReportPreparationInfo(instanceId.value, route.query.id)
- // 将缓存的报告结论回填
- reportConclusion.value = {
- ...cacheConclusion,
- reportUrl: currentInstance.allTaskInfo.reportUrl || '',
- typeInspectionReportUrl: currentInstance.allTaskInfo.typeInspectionReportUrl || '',
- reportAttachmentSjs: currentInstance.allTaskInfo.reportAttachmentSjs
- }
- currentInstance = reactive(functionalStore.getInstance(instanceId.value))
- }
- </script>
- <style lang="scss" scoped>
- /* 主容器 - 使用flexbox布局 */
- .prepare-detail-container {
- height: calc(100vh - 200px);
- display: flex;
- flex-direction: column;
- overflow: hidden; /* 关键:阻止主容器出现滚动条 */
- }
- /* 固定头部 */
- .fixed-header {
- flex-shrink: 0; /* 防止头部被压缩 */
- background-color: #fff;
- border-bottom: 1px solid #ebeef5;
- padding: 0 12px 10px 20px;
- z-index: 100;
- }
- .header {
- display: flex;
- justify-content: flex-end;
- align-items: center;
-
- .btns {
- display: flex;
- gap: 8px;
- flex-wrap: wrap;
- }
- }
- /* 可滚动的内容区域 */
- .scrollable-content {
- flex: 1; /* 占用剩余空间 */
- overflow-y: auto; /* 只在这里显示滚动条 */
- overflow-x: hidden;
- padding: 20px;
-
- /* 优化滚动体验 */
- scroll-behavior: smooth;
-
- /* 自定义滚动条样式 */
- &::-webkit-scrollbar {
- width: 6px;
- }
-
- &::-webkit-scrollbar-track {
- background: #f1f1f1;
- border-radius: 3px;
- }
-
- &::-webkit-scrollbar-thumb {
- background: #c1c1c1;
- border-radius: 3px;
-
- &:hover {
- background: #a8a8a8;
- }
- }
-
- /* Firefox滚动条样式 */
- scrollbar-width: thin;
- scrollbar-color: #c1c1c1 #f1f1f1;
- }
- /* 确保collapse组件不会影响布局 */
- .custom-collapse-form {
- width: 100%;
- }
- /* 响应式调整 */
- @media (max-width: 768px) {
- .fixed-header {
- padding: 10px 15px;
- }
-
- .scrollable-content {
- padding: 15px;
- }
-
- .header .btns {
- gap: 6px;
- }
- }
- /* 如果页面有其他容器,可以调整高度 */
- .prepare-detail-container.with-navbar {
- height: calc(100vh - 60px); /* 减去导航栏高度 */
- }
- .prepare-detail-container.with-tabs {
- height: calc(100vh - 100px); /* 减去导航栏和标签页高度 */
- }
- </style>
|