<!-- 委托方情况报告详情 --> <script name="SituationReportDetail" lang="ts" setup> import { ElLoading, ElMessage, ElMessageBox, dayjs } from 'element-plus' import type { ICustomerQuestionnaireInfo, IListQuery } from '../questionnaire/customer-questionnaire' import type { ICustomerSatisfaction, ISituationReportInfo } from './customer-report' import selectSuggestFormDialog from './dialog/selectSuggestFormDialog.vue' import type { TableColumn } from '@/components/NormalTable/table_interface' import type { IDictType } from '@/commonInterface/resource-interface' import useUserStore from '@/store/modules/user' import { detailSituationReport, getStream, saveSituationReport, updateSituationReport } from '@/api/resource/situationReport' import { getDictByCode } from '@/api/system/dict' import { getQuestionnaireList } from '@/api/resource/questionnaire' import FilterQuestionnaire from '@/views/resource/common/filterQuestionnaire.vue' import { calc } from '@/utils/useCalc' import { exportFile } from '@/utils/exportUtils' import { printPdf } from '@/utils/printUtils' import { uniqueArray } from '@/utils/Array' import { isInteger } from '@/utils/validate' // 从路由中传过来的参数 const type = ref<string>('') const id = ref<string>('') const userInfo = useUserStore() const route = useRoute() const router = useRouter() const title = ref('') // 关键字段是否可以编辑 const keyFieldsDisable = ref<boolean>(true) const reportFormRef = ref() const refQuestionnaireFilter = ref() const reportInfo = ref<ISituationReportInfo>({ id: '', customerName: '', labCode: '', labCodeName: '', reportNo: '', reportName: '委托方情况报告', customerAdvice: '', // 委托方反馈意见 customerAdviceHandle: '', // 对意见的处理 conclusion: '实现“委托方满意率高于90%,每年收到委托方投诉不大于2次”的目标', createUserId: '', createUserName: '', createTime: '', customerList: [], draft: '1', // 1/2是否是草稿箱 averageScore: '', // 平均分 totalScore: '', // 总分 rate: '', // 满意率 suggestId: '', // 委托方意见登记表id }) const quesQuery = ref<IListQuery>({ customerName: '', // 填写单位 writerName: '', writeTimeStart: '', writeTimeEnd: '', sendTimeStart: '', sendTimeEnd: '', offset: 1, limit: 2000, }) const reportFormRules = ref({ labCode: [{ required: true, message: '实验室代码不能为空', trigger: ['change', 'blur'] }], customerName: [{ required: true, message: '委托方不能为空', trigger: ['change', 'blur'] }], customerAdvice: [{ required: true, message: '委托方反馈意见不能为空', trigger: 'blur' }], customerAdviceHandle: [{ required: true, message: '对委托方意见的处理不能为空', trigger: 'blur' }], conclusion: [{ required: true, message: '结论不能为空', trigger: 'blur' }], }) // 表单验证规则 // 字典值 const labCodeDict = ref<IDictType[]>([]) const customerListXc = ref<ICustomerSatisfaction[]>([]) const customerListHk = ref<ICustomerSatisfaction[]>([]) const satisfactionColumns = ref<TableColumn[]>([ { text: '委托方名称', value: 'customerName', align: 'center' }, { text: '时间', value: 'proposeTime', align: 'center', width: '240' }, { text: '评分', value: 'score', align: 'center', width: '240' }, ]) // -----------------------------------表格操作----------------------------------------------- const customerSelectedXc = ref<ICustomerSatisfaction[]>([]) const customerSelectedHk = ref<ICustomerSatisfaction[]>([]) // 西昌多选 const xcMultiSelect = (e: any) => { customerSelectedXc.value = e } // 海口多选 const hkMultiSelect = (e: any) => { customerSelectedHk.value = e } // 计算总分、平均分、满意率 const caculate = (list: any = []) => { if (!list.length) { return } let sum = 0 // 总分 let ave = 0 // 平均分 let rate = 0 // 满意率 list.forEach((item: { score: number }) => { sum = Number(calc(Number(item.score), sum, '+')) }) ave = Number(calc(sum, list.length, '/')) const above90 = list.filter((item: { score: number }) => item.score >= 90) rate = Number(calc(above90.length, list.length, '/')) console.log('总分', sum) console.log('平均分', isInteger(ave) ? ave : ave.toFixed(2)) console.log('满意率', isInteger(Number(calc(rate, 100, '*'))) ? `${Number(calc(rate, 100, '*'))}%` : `${Number(calc(rate, 100, '*')).toFixed(2)}%`) return { sum, ave: isInteger(ave) ? ave : ave.toFixed(2), rate: isInteger(Number(calc(rate, 100, '*'))) ? `${Number(calc(rate, 100, '*'))}%` : `${Number(calc(rate, 100, '*')).toFixed(2)}%`, } } // 增加行 const addEditableRow = () => { refQuestionnaireFilter.value.showOrHideFilterDialog(true, reportInfo.value.labCode) } // 删除行 const delSatisfaction = () => { if (customerSelectedXc.value.length === 0 && customerSelectedHk.value.length === 0) { ElMessage.warning('请至少选择一行') return } // 前端界面删除 customerListXc.value = customerListXc.value.filter(item => customerSelectedXc.value.includes(item) === false) customerListHk.value = customerListHk.value.filter(item => customerSelectedHk.value.includes(item) === false) // 计算总分、平均分、满意率 const caculateList = reportInfo.value.labCode === 'X' ? customerListXc.value : reportInfo.value.labCode === 'H' ? customerListHk.value : [] const { sum, ave, rate } = caculate(caculateList)! reportInfo.value.averageScore = `${ave}`// 平均分 reportInfo.value.totalScore = `${sum}` // 总分 reportInfo.value.rate = rate// 满意率 } // 选好委托方满意度调查表 const questionnaireSelectedHandler = (rows: ICustomerQuestionnaireInfo[]) => { refQuestionnaireFilter.value.showOrHideFilterDialog(false) rows.forEach((row) => { if (row.labCode === 'X') { const existList = customerListXc.value.filter(xc => xc.id === row.id) if (existList.length === 0) { customerListXc.value.push({ ...row, questionnaireId: row.id, }) } } else if (row.labCode === 'H') { const existList = customerListHk.value.filter(hk => hk.id === row.id) if (existList.length === 0) { customerListHk.value.push({ ...row, questionnaireId: row.id, }) } } }) const caculateList = reportInfo.value.labCode === 'X' ? customerListXc.value : reportInfo.value.labCode === 'H' ? customerListHk.value : [] const { sum, ave, rate } = caculate(caculateList)! reportInfo.value.averageScore = `${ave}`// 平均分 reportInfo.value.totalScore = `${sum}` // 总分 reportInfo.value.rate = rate// 满意率 // 委托方名称 reportInfo.value.customerName = uniqueArray(caculateList.map(item => item.customerName)).join(',') } // ------------------------------------------------------------------------------------------------------------------ // 根据委托方名称查询满意度调查表 // 暂时不用 const searchQuestionnaire = () => { if (reportInfo.value.customerName !== '') { reportInfo.value.customerName = reportInfo.value.customerName.replace(',', ',') const customerList = reportInfo.value.customerName.split(',') customerList.forEach((customer: string) => { quesQuery.value.customerName = customer getQuestionnaireList(quesQuery.value).then((res) => { if (res.code === 200) { customerListXc.value = [] customerListHk.value = [] res.data.rows.forEach((item: ICustomerQuestionnaireInfo) => { if (item.writeStatus === '已提交') { if (item.labCode === 'X') { customerListXc.value.push({ id: item.id, labCode: item.labCode, customerName: item.customerName, proposeTime: item.writeTime, }) } else if (item.labCode === 'H') { customerListHk.value.push({ id: item.id, labCode: item.labCode, customerName: item.customerName, proposeTime: item.writeTime, }) } } }) } }) }) } } // 保存至草稿箱 const saveReportInfo = () => { reportInfo.value.createTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss') // 创建时间改为提交时间 const params = { ...reportInfo.value, draft: '1', customerList: reportInfo.value.customerList.map((item: any) => { return { ...item, id: '', } }), } saveSituationReport(params).then((res) => { if (res.code === 200) { // 提示保存成功 ElMessage.success('保存成功') // 设置返回的委托方id和委托方编号 reportInfo.value.reportNo = res.data.reportNo reportInfo.value.id = res.data.id id.value = res.data.id type.value = 'detail' keyFieldsDisable.value = true } else { // 提示失败信息 ElMessage.error(`保存失败:${res.message}`) } }) } // 编辑 const updateReportInfo = () => { updateSituationReport({ ...reportInfo.value, id: id.value }).then((res) => { if (res.code === 200) { // 提示保存成功 ElMessage.success('保存成功') } else { // 提示失败信息 ElMessage.error(`保存失败:${res.message}`) } }) } // 提交 const submit = () => { const params = { ...reportInfo.value, draft: '2', id: id.value, customerList: reportInfo.value.labCode === 'X' ? customerListXc.value : reportInfo.value.labCode === 'H' ? customerListHk.value : [], } updateSituationReport({ ...params, customerList: params.customerList.map((item) => { return { ...item, id: '', } }), }).then((res) => { if (res.code === 200) { // 提示保存成功 ElMessage.success('提交成功') type.value = 'detail' reportInfo.value.draft = '2' } else { // 提示失败信息 ElMessage.error(`保存失败:${res.message}`) } }) } // 新建时保存后的处理 获取返回的id const saveButtonHandler = async () => { if (!reportFormRef) { return } reportInfo.value.customerList = [] customerListXc.value.forEach((item) => { reportInfo.value.customerList.push(item) }) customerListHk.value.forEach((item) => { reportInfo.value.customerList.push(item) }) await reportFormRef.value.validate((valid: boolean, fields: any) => { if (valid === true) { ElMessageBox.confirm( '确认保存吗?', '提示', { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning', }, ).then(() => { if (type.value === 'create') { saveReportInfo() } else if (type.value === 'update') { updateReportInfo() } }) } }) } // 获取西昌实验室情况表、海口实验室情况表 const disSatisfByLabCode = () => { detailSituationReport({ id: reportInfo.value.id }).then((res) => { if (res.code === 200) { customerListXc.value = res.data.xCustomerList customerListHk.value = res.data.hCustomerList // 计算总分、平均分、满意率 const caculateList = reportInfo.value.labCode === 'X' ? customerListXc.value : reportInfo.value.labCode === 'H' ? customerListHk.value : [] const { sum, ave, rate } = caculate(caculateList)! reportInfo.value.averageScore = `${ave}`// 平均分 reportInfo.value.totalScore = `${sum}` // 总分 reportInfo.value.rate = rate// 满意率 } }) } // -----------------------------------选择委托方意见登记表--------------------------------------------- const selectSuggestFormRef = ref() // 委托方意见登记表组件ref // 点击选择委托委托方意见 const handleSelectSuggestForm = () => { selectSuggestFormRef.value.initDialog() } // 选好委托方意见登记表 const confirmSelectSuggestForm = (val: any) => { if (val && val.length) { reportInfo.value.customerAdvice = val[0].handleStatusName // 委托方反馈意见 reportInfo.value.customerAdviceHandle = val[0].suggestContent // 对意见的处理 reportInfo.value.suggestId = val[0].id // 委托方意见登记表id } } // -------------------------------------------------------------------------------------------------- const getLabCodeDict = async () => { // 缓存中没有则调用接口查询 await getDictByCode('bizGroupCodeEquipment').then((res) => { if (res.code === 200) { labCodeDict.value = res.data } }) } // 关闭 const resetForm = () => { sessionStorage.removeItem('situationReportInfo') // 返回列表时 将缓存中的数据删除 router.go(-1) } const initDialog = (params: any) => { // 从路由中获取参数 type.value = params.type id.value = params.id !== undefined ? params.id : '' switch (params.type) { case 'create' : title.value = '委托方情况报告(新增)' sessionStorage.removeItem('situationReportInfo') reportInfo.value.createUserId = userInfo.id reportInfo.value.createUserName = userInfo.name reportInfo.value.createTime = dayjs(new Date()).format('YYYY-MM-DD') // 新建时部门和实验实验室编辑 keyFieldsDisable.value = false break case 'update': title.value = '委托方情况报告(编辑)' reportInfo.value = JSON.parse(sessionStorage.getItem('situationReportInfo')!) reportInfo.value.draft = `${reportInfo.value.draft}` disSatisfByLabCode() break case 'detail': title.value = '委托方情况报告(详情)' id.value = params.id reportInfo.value = JSON.parse(sessionStorage.getItem('situationReportInfo')!) reportInfo.value.draft = `${reportInfo.value.draft}` disSatisfByLabCode() keyFieldsDisable.value = true break default: title.value = '' keyFieldsDisable.value = true break } } const initDict = () => { getLabCodeDict() } // 监听 显示中文 watch(() => reportInfo.value.labCode, (newVal) => { labCodeDict.value = JSON.parse(sessionStorage.getItem('bizLabCode')!) if (labCodeDict.value.length > 0) { const targetList = labCodeDict.value.filter(item => item.value === newVal) if (targetList.length > 0) { reportInfo.value.labCodeName = targetList[0].name } else { reportInfo.value.labCodeName = '' } } }) // --------------------------------导出word、pdf、打印---------------------------------------------------- const stream = ref() const streamNormal = ref(true) // 流是否正常 // 获取流 const fetchStream = async (isPdf = true) => { const loading = ElLoading.service({ lock: true, text: '加载中...', background: 'rgba(255, 255, 255, 0.6)', }) const res = await getStream({ id: id.value, pdf: isPdf }) stream.value = res.data loading.close() } // 打印Word const printToWord = () => { fetchStream(false).then(() => { if (streamNormal.value) { exportFile(stream.value, '委托方意见登记表.doc') } }) } // 导出PDF const printToPDF = () => { fetchStream().then(() => { if (streamNormal.value) { exportFile(new Blob([stream.value]), '委托方意见登记表.pdf') } }) } // 打印 const printClickedHandler = () => { fetchStream().then(() => { if (streamNormal.value) { const blobUrl = URL.createObjectURL(stream.value) printPdf(blobUrl) } }) } // 监听实验室修改, 清空表格 const changeLab = () => { customerSelectedXc.value = [] customerSelectedHk.value = [] customerListXc.value = [] customerListHk.value = [] } onMounted(() => { initDict() initDialog(route.query) }) </script> <template> <app-container> <el-form ref="reportFormRef" :model="reportInfo" :rules="reportFormRules" label-position="right" label-width="125px" border stripe> <detail-page :title="`${title}`"> <template #btns> <template v-if="type === 'detail'"> <el-button type="primary" @click="printToWord"> 导出Word </el-button> <el-button type="primary" @click="printToPDF"> 导出PDF </el-button> <el-button type="primary" @click="printClickedHandler"> 打印 </el-button> </template> <el-button v-if="(type === 'detail' || type === 'update') && reportInfo.draft === '1'" type="primary" @click="submit"> 提交 </el-button> <el-button v-if="type !== 'detail'" type="primary" @click="saveButtonHandler"> 保存 </el-button> <el-button type="info" @click="resetForm()"> 关闭 </el-button> </template> <el-row :gutter="24"> <!-- 第一行 第一列 --> <el-col :span="6"> <el-form-item label="实验室" prop="labCode"> <el-select v-model="reportInfo.labCode" placeholder="请选择实验室" :disabled="keyFieldsDisable" style="width: 100%;" @change="changeLab"> <el-option v-for="dict in labCodeDict" :key="dict.id" :label="dict.name" :value="dict.value" /> </el-select> <el-input v-model="reportInfo.labCodeName" type="hidden" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="报告单编号"> <el-input v-model="reportInfo.reportNo" placeholder="系统自动生成" :disabled="true" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="拟制人"> <el-input v-model="reportInfo.createUserId" type="hidden" /> <el-input v-model="reportInfo.createUserName" :disabled="true" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="拟制时间"> <el-input v-model="reportInfo.createTime" :disabled="true" /> </el-form-item> </el-col> </el-row> </detail-page> <detail-block title=""> <el-row :gutter="24"> <el-col :span="24"> <el-form-item label="委托方名称" prop="customerName"> <el-input v-model="reportInfo.customerName" placeholder="委托方名称,多个委托方用,隔开" :clearable="true" type="textarea" autosize :disabled="type === 'detail'" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="总分"> <el-input v-model="reportInfo.totalScore" placeholder="总分" disabled /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="平均分"> <el-input v-model="reportInfo.averageScore" placeholder="平均分" disabled /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="满意率"> <el-input v-model="reportInfo.rate" placeholder="满意率" disabled /> </el-form-item> </el-col> </el-row> <el-row :gutter="24"> <el-col :span="16"> <el-form-item label="委托方反馈意见" prop="customerAdvice"> <!-- <el-input v-model="reportInfo.customerAdvice" placeholder="请输入委托方反馈的意见" :clearable="true" :disabled="type === 'detail'" /> --> <el-input v-model="reportInfo.customerAdvice" placeholder="请选择" :disabled="true"> <template v-if="type !== 'detail'" #append> <el-button :disabled="type === 'detail'" @click="handleSelectSuggestForm"> 选择 </el-button> </template> </el-input> </el-form-item> </el-col> </el-row> <el-row :gutter="24"> <el-col :span="24"> <el-form-item label="对意见的处理" prop="customerAdviceHandle"> <el-input v-model="reportInfo.customerAdviceHandle" placeholder="请输入对委托方意见的处理" :clearable="true" type="textarea" autosize :disabled="type === 'detail'" /> </el-form-item> </el-col> </el-row> </detail-block> <table-container v-if="reportInfo.labCode === 'X'" title="西昌实验室情况"> <template v-if="type !== 'detail'" #btns-right> <el-button type="primary" @click="addEditableRow()"> 批量添加 </el-button> <el-button type="info" @click="delSatisfaction()"> 删除行 </el-button> </template> <el-table :data="customerListXc" border style="width: 100%;" @selection-change="xcMultiSelect"> <el-table-column v-if="type !== 'detail'" type="selection" align="center" width="38" /> <el-table-column align="center" label="序号" width="80" type="index" /> <el-table-column v-for="item in satisfactionColumns" :key="item.value" :prop="item.value" :label="item.text" :width="item.width" align="center" > <template #default="scope"> <span v-if="!scope.row.editable">{{ scope.row[item.value] }}</span> <el-input v-else v-model="scope.row[item.value]" :autofocus="true" :placeholder="`${item.text}`" class="input" /> </template> </el-table-column> </el-table> </table-container> <table-container v-if="reportInfo.labCode === 'H'" title="海口实验室情况"> <template v-if="type !== 'detail'" #btns-right> <el-button type="primary" @click="addEditableRow()"> 批量添加 </el-button> <el-button type="info" @click="delSatisfaction()"> 删除行 </el-button> </template> <el-table :data="customerListHk" border style="width: 100%;" @selection-change="hkMultiSelect"> <el-table-column v-if="type !== 'detail'" type="selection" align="center" width="38" /> <el-table-column align="center" label="序号" width="80" type="index" /> <el-table-column v-for="item in satisfactionColumns" :key="item.value" :prop="item.value" :label="item.text" :width="item.width" align="center" > <template #default="scope"> <span v-if="!scope.row.editable">{{ scope.row[item.value] }}</span> <el-input v-else v-model="scope.row[item.value]" :autofocus="true" :placeholder="`${item.text}`" class="input" /> </template> </el-table-column> </el-table> </table-container> <detail-block title=""> <el-row :gutter="24"> <el-col :span="24"> <el-form-item label="结论" prop="conclusion"> <el-input v-model="reportInfo.conclusion" :clearable="true" :disabled="type === 'detail'" /> </el-form-item> </el-col> </el-row> </detail-block> </el-form> <!-- 选择委托方满意度调查表 --> <filter-questionnaire ref="refQuestionnaireFilter" @record-selected="questionnaireSelectedHandler" /> <!-- 选择委托方意见登记表 --> <select-suggest-form-dialog ref="selectSuggestFormRef" @confirm="confirmSelectSuggestForm" /> </app-container> </template>