<!-- 设备装箱详情 --> <script lang="ts" setup name="EquipementResumeEncasementDetail"> import { ref } from 'vue' import dayjs from 'dayjs' import { ElLoading, ElMessage } from 'element-plus' import type { IBoxList, IEquipmentList, IForm } from './encasement-interface' import { getStaffList } from '@/api/resource/register' import useUserStore from '@/store/modules/user' import { getDictByCode } from '@/api/system/dict' import type { dictType } from '@/global' import SelectEquipmentDialog from '@/views/business/fieldTest/approve/dialog/selectEquipmentDialog.vue' import { useCheckList } from '@/commonMethods/useCheckList' import { useArrayDataUnique } from '@/commonMethods/useArrayDataUnique' import { useDoubleClickTableRow, useSetAllRowReadable } from '@/commonMethods/useSetAllRowReadable' import { addResumeEncasementList, getInfo, updateResumeEncasementList } from '@/api/equipment/resume/encasement' // import type { IOptions } from '@/views/device/standardEquipment/standard_interface' const user = useUserStore() // 用户信息 const textMap: { [key: string]: string } = { edit: '编辑', add: '新建', detail: '详情', }// 字典 const $router = useRouter() // 关闭页面使用 const $route = useRoute() // 路由参数 const pageType = ref('add') // 页面类型: add, edit, detail const infoId = ref('') // 列表id const ruleFormRef = ref() // 表单ref const form = ref<IForm>({ labCode: '', // 实验室 groupCode: '', // 部门(字典code) groupCodeName: '', // 部门(字典value) formNo: '', // 装箱单编号 formName: '', // 装箱单名称 createUserId: '', // 创建人id createUserName: '', // 创建人 createTime: '', // 创建时间 packingTime: '', // 装箱日期 transportType: '', // 运输类型 }) // 校验规则 const formRules = ref({ labCode: [{ required: true, message: '实验室不能为空', trigger: ['blur', 'change'] }], groupCode: [{ required: true, message: '部门不能为空', trigger: ['blur', 'change'] }], packingTime: [{ required: true, message: '装箱时间不能为空', trigger: ['blur', 'change'] }], transportType: [{ required: true, message: '运输类型不能为空', trigger: ['blur', 'change'] }], }) const isMulti = ref(false) // 是否多选 // -------------------------------------------字典------------------------------------------ const userList = ref<{ [key: string]: string }[]>([]) // 用户列表 const labCodeList = ref<dictType[]>([]) // 实验室 const groupCodeList = ref<dictType[]>([]) // 部门 const transportTypeList = ref<dictType[]>([]) // 运输类型 // 获取字典值 async function getDict() { // 实验室 // getDictByCode('bizLabCode').then((response) => { getDictByCode('bizGroupCodeEquipment').then((response) => { labCodeList.value = response.data }) // 部门 getDictByCode('bizGroupCode').then((response) => { groupCodeList.value = response.data }) // 运输类型 getDictByCode('bizTransportType').then((response) => { transportTypeList.value = response.data }) } // ----------------------------------路由参数-------------------------------------------- if ($route.params && $route.params.type) { pageType.value = $route.params.type as string console.log(pageType.value) if ($route.params.id) { infoId.value = $route.params.id as string } } // ----------------------------------------包装箱----------------------------------------------- const list = ref<IBoxList[]>([]) // 装箱内容 const table = ref() const checkoutEquipment = ref<IBoxList[]>([]) // 选中设备 const columns = [ // 表头 // { text: '统一编号', value: 'equipmentNo', align: 'center', required: true }, { text: '设备名称', value: 'equipmentName', align: 'center', required: true }, { text: '规格型号', value: 'model', align: 'center', required: true }, { text: '出厂编号', value: 'equipmentNo', align: 'center', required: true }, { text: '数量', value: 'quantity', align: 'center', required: true }, ] const addObj = { id: '', // 更新/删除使用参数 packageNo: '', // 包装箱号 packageUser: user.name, // 装箱人 packingId: '', // 装箱单id traceFlag: 0, // 是否是设备溯源任务(1/0)默认否 checked: false, // 默认不被选中 packIndex: 1, // 包装箱索引 attachment: '', // 附件及资料 } // 检查包装箱列表是否符合规范 const checkPackList = () => { list.value.forEach((item) => { if (!item.packageNo) { ElMessage.warning(`第${item.packIndex}个包装箱的的包装箱号不能为空`) // eslint-disable-next-line no-throw-literal throw false } else if (!item.packageUser) { ElMessage.warning(`第${item.packIndex}个包装箱的的装箱人不能为空`) // eslint-disable-next-line no-throw-literal throw false } else if (!item.equipmentList.length) { ElMessage.warning(`第${item.packIndex}个包装箱的的设备不能为空`) // eslint-disable-next-line no-throw-literal throw false } else { if (!useCheckList(item.equipmentList, columns, `第${item.packIndex}个包装箱`)) { // eslint-disable-next-line no-throw-literal throw false } } }) } // 新增包装箱 const add = () => { checkPackList() list.value.unshift({ ...addObj, packIndex: list.value.length + 1, equipmentList: [] }) } // 删除包装箱 const del = () => { const delArr = list.value.filter(item => item.checked) if (!delArr.length) { ElMessage.warning('请选中要删除的包装箱') return false } list.value = list.value.filter(item => !item.checked) // 删除 // 刷新索引 list.value = list.value.map((item, index) => { return { ...item, packIndex: list.value.length - index, } }) } // 点击增加行 const addRow = (index: number) => { if (useCheckList(list.value[index].equipmentList, columns, `第${list.value[index].packIndex}个包装箱`)) { isMulti.value = false useSetAllRowReadable(list.value[index].equipmentList) list.value[index].equipmentList.push({ equipmentId: '', // 设备id(外部设备该字段为空) equipmentName: '', // 设备名称 equipmentNo: '', // 设备编号传出厂编号(编号、名称、型号、数量都要传) model: '', // 规格型号 quantity: '', // 数量 editable: true, }) } } // 点击删除行 const deleteRow = (index: number) => { if (!checkoutEquipment.value.length) { ElMessage.warning('请选中要删除的行') return false } list.value[index].equipmentList = list.value[index].equipmentList.filter((item: any) => { return !checkoutEquipment.value.includes(item) }) // 清除选中 for (let i = 0; i < table.value.length; i++) { table.value[i].clearSelection() } } // 选中设备 const handleTechSelectionChange = (e: any) => { checkoutEquipment.value = e } // 双击行 const rowDblclick = (row: IEquipmentList, index: number) => { if (pageType.value !== 'detail') { useDoubleClickTableRow(row, list.value[index].equipmentList) } } // -----------------------------------------批量增加设备---------------------------------------- const selectEquipmentDialogRef = ref() // 选择设备编号组件ref const multiAddIndex = ref(0) // 批量增加索引(第几个包装箱) // 确定选择设备 const confirmSelectEquipment = (val: any) => { if (val.length) { val.forEach((item: any) => { list.value[multiAddIndex.value].equipmentList.push({ equipmentId: item.id, // 设备id equipmentNo: item.manufactureNo, // 设备编号传出厂编号 equipmentName: item.equipmentName, // 设备名称 model: item.model, // 规格型号 quantity: '', // 数量 editable: true, }) }) } } // 点击批量增加 const multiAddRow = (index: number) => { isMulti.value = true multiAddIndex.value = index selectEquipmentDialogRef.value.initDialog() } // -------------------------------------------按钮---------------------------------------------- // 关闭新增页面的回调 const close = () => { $router.back() } // 点击编辑按钮 const edit = () => { pageType.value = 'edit' } // 保存 const save = () => { if (!list.value.length) { ElMessage.warning('装箱内容不能为空') return false } checkPackList() // 检查装箱内容 if (!checkArrayPackageNoUnique()) { return false } if (!checkArrayPackageNoUnique()) { return false } if (!checkArrayDataUnique()) { return false } ruleFormRef.value!.validate((valid: boolean) => { if (valid) { const loading = ElLoading.service({ lock: true, background: 'rgba(255, 255, 255, 0.8)', }) const tempArr = [] as any list.value.forEach((item) => { if (item.equipmentList.length) { item.equipmentList.forEach((i) => { tempArr.push({ ...item, ...i, traceFlag: item.traceFlag == 1, packageNo: item.packageNo, // 包装箱号 packageUser: item.packageUser, // 装箱人 attachment: item.attachment, // 附件及资料 }) }) } }) const params = { ...form.value, id: infoId.value, thingList: tempArr, formNo: '', } // 新建 if (pageType.value === 'add') { // 新建 addResumeEncasementList(params).then((res) => { ElMessage.success('保存成功') form.value.formNo = res.data.formNo // 记录表单号 infoId.value = res.data.id // id pageType.value = 'detail' loading.close() }).catch(() => { loading.close() }) } // 保存 else if (pageType.value === 'edit') { // 编辑 updateResumeEncasementList(params).then((res) => { ElMessage.success('保存成功') pageType.value = 'detail' loading.close() }).catch(() => { loading.close() }) } } else { console.log('表单校验不通过') } }) } // -------------------------------------------获取详情信息-------------------------------------------------- // 获取详情信息 const fetchInfo = () => { const loading = ElLoading.service({ lock: true, background: 'rgba(255, 255, 255, 0.8)', }) getInfo({ id: infoId.value }).then((res) => { form.value = res.data list.value = res.data.detailThingList.map((item: any, index: number) => { return { ...item, packIndex: index + 1, traceFlag: item.traceFlag == 1, attachment: item.equipmentList[0].attachment, // 附件及资料 } }) if (pageType.value === 'edit') { list.value = list.value.reverse() } loading.close() }) } // 包装箱号重复 function checkArrayPackageNoUnique() { const tempList = list.value for (let i = 0; i < tempList.length; i++) { for (let j = 0; j < tempList.length; j++) { if (i !== j && tempList[i].packageNo === tempList[j].packageNo) { ElMessage.warning(`第${i + 1}和第${j + 1}个包装箱的 包装箱号 重复`) return false } } } return true } // 不同的包装箱不能有同一个设备 function checkArrayDataUnique() { const compArr = [] as any list.value.forEach((item) => { if (item.equipmentList.length) { item.equipmentList.forEach((i: any) => { compArr.push({ ...i, packIndex: item.packIndex, // 包装箱索引 packageNo: item.packageNo, // 包装箱号 }) }) } }) for (let i = 0; i < compArr.length; i++) { for (let j = 0; j < compArr.length; j++) { if (i !== j && compArr[i].equipmentId === compArr[j].equipmentId) { ElMessage.warning(`第${compArr[i].packIndex}个包装箱,箱号:【${compArr[i].packageNo}】 和 第${compArr[j].packIndex}个包装箱,箱号:【${compArr[j].packageNo}】不能同时含有设备 【${compArr[i].equipmentNo}-${compArr[i].equipmentName}-${compArr[i].model}】`) return false } } } return true } onMounted(async () => { getDict().then(() => { // await fetchStaffList() form.value.createUserId = user.id// 创建人 form.value.createUserName = user.name // 创建人名字 form.value.formName = '设备运输装箱清单' // 记录单名称 form.value.createTime = dayjs().format('YYYY-MM-DD HH-mm:ss')// 创建时间 if (pageType.value !== 'add') { fetchInfo() } else { // 新建 form.value.labCode = user.bizLabCode // 实验室 form.value.groupCode = user.groupNo // 部门名称 } }) }) </script> <template> <div class="resume-encasement"> <app-container> <detail-page :title="`设备运输装箱管理-${textMap[pageType]}`"> <template #btns> <el-button v-if="pageType !== 'detail'" type="primary" @click="save"> 保存 </el-button> <el-button v-if="pageType === 'detail'" type="primary" @click="edit"> 编辑 </el-button> <el-button type="info" @click="close"> 关闭 </el-button> </template> <el-form ref="ruleFormRef" :model="form" label-width="120" label-position="right" :rules="formRules" > <el-row :gutter="24"> <el-col :span="6"> <el-form-item label="文件编号:" prop="formNo"> <el-input v-model="form.formNo" class="full-width-input" disabled placeholder="系统自动生成" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="文件名称:" prop="formName"> <el-input v-model="form.formName" class="full-width-input" disabled placeholder="请输入记录单名称" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="创建人:" prop="createUserName"> <el-input v-model="form.createUserName" class="full-width-input" :placeholder="pageType === 'detail' ? '' : '创建人'" disabled /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="创建时间:" prop="createTime"> <el-date-picker v-model="form.createTime" type="datetime" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" class="full-width-input" disabled /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="实验室" prop="labCode"> <el-select v-model="form.labCode" :placeholder="pageType === 'detail' ? ' ' : '请选择实验室'" :disabled="pageType === 'detail'" class="full-width-input"> <el-option v-for="item in labCodeList" :key="item.id" :label="item.name" :value="item.value" /> </el-select> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="部门" prop="groupCode"> <el-select v-model="form.groupCode" :placeholder="pageType === 'detail' ? ' ' : '请选择部门'" :disabled="pageType === 'detail'" class="full-width-input"> <el-option v-for="item in groupCodeList" :key="item.id" :label="item.name" :value="item.value" /> </el-select> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="装箱时间:" prop="packingTime"> <el-date-picker v-model="form.packingTime" type="datetime" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" class="full-width-input" placeholder="请选择装箱时间" :disabled="pageType === 'detail'" /> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="运输类型:" prop="transportType"> <el-radio-group v-model="form.transportType" :disabled="pageType === 'detail'"> <el-radio label="1"> 设备出实验室 </el-radio> <el-radio label="2"> 设备回实验室 </el-radio> </el-radio-group> </el-form-item> </el-col> </el-row> </el-form> </detail-page> <detail-block title="装箱内容" style="padding-bottom: 10px;"> <template v-if="pageType !== 'detail'" #btns> <el-button type="primary" @click="add"> 增加包装箱 </el-button> <el-button type="info" @click="del"> 删除包装箱 </el-button> </template> </detail-block> <detail-block v-for="(item, index) in list" :key="index" title="" style="padding-bottom: 20px;"> <div style="display: flex;"> <el-checkbox v-if="pageType !== 'detail'" v-model="item.checked" /> <div class="step"> {{ item.packIndex }} </div> </div> <div style="display: flex; justify-content: space-between;align-items: center;"> <div style="display: flex;align-items: center;margin-bottom: 20px;"> <div style="display: flex;margin-right: 20px;align-items: center;"> <span style="white-space: nowrap;margin-right: 10px;">包装箱号:</span> <el-input v-model.trim="item.packageNo" class="full-width-input" :disabled="pageType === 'detail'" :placeholder="pageType === 'detail' ? ' ' : '请输入包装箱号'" /> </div> <div style="display: flex;margin-right: 30px;align-items: center;"> <span style="white-space: nowrap;margin-right: 10px;">装箱人:</span> <el-input v-model="item.packageUser" class="full-width-input" :disabled="pageType === 'detail'" :placeholder="pageType === 'detail' ? ' ' : '请输入装箱人'" /> </div> <el-checkbox v-model="item.traceFlag" :disabled="pageType === 'detail'"> 是否是设备溯源任务 </el-checkbox> <div style="display: flex;margin: 0 30px;align-items: center;"> <span style="white-space: nowrap;margin-right: 10px;">附件及资料:</span> <el-input v-model="item.attachment" type="textarea" autosize class="full-width-input" :disabled="pageType === 'detail'" :placeholder="pageType === 'detail' ? ' ' : '请输入附件及资料'" /> </div> </div> <div v-if="pageType !== 'detail'"> <el-button type="primary" @click="multiAddRow(index)"> 批量增加 </el-button> <el-button type="primary" @click="addRow(index)"> 增加行 </el-button> <el-button type="info" @click="deleteRow(index)"> 删除行 </el-button> </div> </div> <el-table ref="table" :data="item.equipmentList" border style="width: 100%;" @selection-change="handleTechSelectionChange" @row-dblclick="(row: any) => rowDblclick(row, index)" > <el-table-column v-if="pageType !== 'detail'" type="selection" width="38" /> <el-table-column align="center" label="序号" width="80" type="index" /> <el-table-column v-for="item in columns" :key="item.value" :prop="item.value" :label="item.text" align="center" > <template #header> <span v-show="item.required" style="color: red;">*</span><span>{{ item.text }}</span> </template> <template #default="scope"> <el-input v-if="pageType !== 'detail' && item.value !== 'quantity' && !scope.row.equipmentId" v-model="scope.row[item.value]" :autofocus="true" :placeholder="`${item.text}`" class="input" /> <el-input-number v-if="pageType !== 'detail' && item.value === 'quantity'" v-model="scope.row[item.value]" :placeholder="`${item.text}`" :min="1" :step="1" :precision="0" /> <span v-if="(pageType !== 'detail' && item.value !== 'quantity' && scope.row.equipmentId) || pageType === 'detail'" >{{ scope.row[item.value] }}</span> <!-- <span v-if="(!scope.row.editable || pageType === 'detail') || (isMulti && (item.value === 'equipmentNo' || item.value === 'equipmentName' || item.value === 'model'))">{{ 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> </detail-block> </app-container> <!-- 选择设备台账 --> <select-equipment-dialog ref="selectEquipmentDialogRef" :is-multi="true" @confirm="confirmSelectEquipment" /> </div> </template> <style lang="scss" scoped> .step { line-height: 28px; font-size: 20px; color: #3d7eff; font-weight: bold; margin-bottom: 5px; width: fit-content; } </style> <style lang="scss"> .resume-encasement { .el-radio__label { display: block !important; } } </style>