<!-- 任务单列表 --> <script lang="ts" setup name="Task"> import { ElLoading, ElMessage, ElMessageBox } from 'element-plus' import selectDevice from './selectDeviceMultiple.vue' import selectDeviceSinge from './selectDeviceSinge.vue' import showPhoto from '@/views/tested/device/info/components/showPhotoSinge.vue' import showPhotos from '@/views/tested/device/info/components/showPhoto.vue' import { uploadApi } from '@/api/system/notice' import { uniqueMultiArray } from '@/utils/Array' import { useCheckList } from '@/utils/useCheckList' import { getInfoDetail } from '@/api/eqpt/device/info' import scanEquipmentDialog from '@/components/scanEquipmentDialog/index.vue' import QRcodeDeviceDialog from '@/components/QRcodeDeviceDialog/index.vue' import { getPreTaskContent, getTaskTogether } from '@/api/eqpt/measurementPlan/task' const $props = defineProps({ data: { type: Array, default: () => ([]), }, form: { type: Object, default: () => ({}), }, }) const measureCompany = ref('') watch(() => $props.form, (newVal) => { if (!newVal) { return } if (newVal.measureCompany) { measureCompany.value = newVal.measureCompany } }, { deep: true, immediate: true, }) const $route = useRoute() // 表头显示标题 const columnsHandler = ref([ // { // text: '统一编号', // value: 'sampleNo', // required: true, // isBtn: true, // isUpload: false, // }, { text: '智能模型名称', value: 'sampleName', required: true, type: 'btn', }, { text: '规格型号', value: 'sampleModel', required: false, type: 'text', }, { text: '辅助字段', value: 'helpInstruction', required: false, type: 'text', }, { text: '出厂编号', value: 'sampleManufactureNo', required: false, type: 'text', }, // { // text: '厂商', // value: 'sampleManufacturer', // required: false, // type: 'text', // }, { text: '附件', value: 'appendixDescn', required: false, type: 'input', }, // { // text: '外观和功能检查', // value: 'appearanceInspect', // required: false, // isBtn: false, // isUpload: false, // }, { text: '特殊要求', value: 'specialRequire', required: false, type: 'input', }, // { // text: '检校项目', // value: 'measureContent', // required: false, // isBtn: false, // isUpload: false, // }, ]) const columnsDetail = ref([ // { // text: '统一编号', // value: 'sampleNo', // required: true, // isBtn: true, // isUpload: false, // }, { text: '智能模型名称', value: 'sampleName', required: true, type: 'text', }, { text: '规格型号', value: 'sampleModel', required: false, type: 'text', }, { text: '辅助字段', value: 'helpInstruction', required: false, type: 'text', }, { text: '出厂编号', value: 'sampleManufactureNo', required: false, type: 'text', }, { text: '厂商', value: 'sampleManufacturer', required: false, type: 'text', }, { text: '附件', value: 'appendixDescn', required: false, type: 'text', }, ]) const list = ref<any[]>([]) // 检查数据列表 function checkCertificateList() { return useCheckList(list.value, columnsHandler.value as any, '任务单列表') } // 将列表置为不可编辑状态 function setAllRowReadable() { for (const item of list.value) { item.editable = false } } // 双击行显示输入框 const dblclickRow = (row: any) => { if ($route.path.includes('detail')) { return } setAllRowReadable() row.editable = true } const SelectionList = ref() // 表格选中 const handleSelectionChange = (e: any[]) => { SelectionList.value = e } // 添加行 const addRow = () => { if (checkCertificateList()) { setAllRowReadable() list.value.push({ sampleManufacturer: '', appearanceInspect: '', appendixDescn: '无', measureContent: '', sampleModel: '', sampleId: '', sampleNo: '', sampleName: '', sampleManufactureNo: '', specialRequire: '无', editable: true, }) } } // 删除行 const removeRow = () => { list.value = list.value.filter((item) => { return !SelectionList.value.includes(item) }) } const initDialog = () => { list.value = $props.data } watch(() => $props.data, (newVal) => { if (newVal) { list.value = newVal fetchTogetherData() } }, { deep: true, }) initDialog() defineExpose({ list, checkCertificateList, }) // 智能模型弹窗组件 const deviceRef = ref() const deviceSingeRef = ref() // 选中的行 const selectRow = ref() // 单选智能模型 const select = (text: string, index: any) => { if (text === '智能模型名称') { deviceSingeRef.value.initDialog('plan') selectRow.value = index } } // 多选智能模型 const batch = () => { if (!checkCertificateList()) { return } setAllRowReadable() deviceRef.value.initDialog(true, 'plan') } // 确认选择智能模型 const confirm = (device: any) => { // 判断是单选还是多选 if (Array.isArray(device)) { // 多选 const ids = [] as string[] device.forEach((item) => { if (!list.value.filter((c: any) => c.sampleId === item.id).length) { ids.push(item.id) list.value.push({ appearanceInspect: '', appendixDescn: '无', measureContent: '', sampleManufacturer: item.manufacturer, sampleModel: item.model, sampleNo: item.equipmentNo, sampleId: item.id, sampleName: item.equipmentName, sampleManufactureNo: item.manufactureNo, helpInstruction: item.helpInstruction, specialRequire: '无', editable: true, }) } }) if (!ids.length) { return } // 获取上一份任务单 智能模型的附件和特殊要求 getPreTaskContent(ids).then((res) => { if (res.data.length) { console.log(res.data, '获取上一份任务单 智能模型的附件和特殊要求') res.data.forEach((item: any) => { const index = list.value.findIndex((citem: any) => citem.sampleId === item.sampleId) if (index !== -1) { list.value[index].appendixDescn = item.appendixDescn list.value[index].specialRequire = item.specialRequire } }) } }) } else { if (!list.value.filter((c: any) => c.sampleId === device.id).length) { // 单选 const row = { sampleManufacturer: device.manufacturer, appearanceInspect: '', appendixDescn: '无', measureContent: '', sampleModel: device.model, sampleId: device.id, sampleNo: device.equipmentNo, sampleName: device.equipmentName, specialRequire: '无', sampleManufactureNo: device.manufactureNo, helpInstruction: device.helpInstruction, editable: true, } list.value[selectRow.value] = row // 获取上一份任务单 智能模型的附件和特殊要求 getPreTaskContent([device.id]).then((res) => { if (res.data.length) { list.value[selectRow.value].appendixDescn = res.data[0].appendixDescn list.value[selectRow.value].specialRequire = res.data[0].specialRequire } }) } else { ElMessage.warning('智能模型已存在') } } } const fileRef = ref() // 文件上传input const currentIndex = ref() const onFileChange = (event: any) => { if (event.target.files?.length !== 0) { // 创建formdata对象 const fd = new FormData() const loading = ElLoading.service({ lock: true, background: 'rgba(255, 255, 255, 0.8)', }) fd.append('multipartFile', event.target.files[0]) uploadApi(fd).then((res) => { fileRef.value.value = '' if (res.code === 200) { list.value[currentIndex.value].appendixDescn = res.data[0] // 重置当前验证 ElMessage.success('文件上传成功') fileRef.value.value = '' loading.close() } else { ElMessage.error(res.message) fileRef.value.value = '' loading.close() } }).catch(() => { fileRef.value.value = '' loading.close() }) } } const uploadRef = ref() const upload = (index: number) => { currentIndex.value = index // window.onclick() fileRef.value.click() // deviceRef.value?.click() } const $router = useRouter() const deviceDetail = (row: any) => { console.log(row, 'row') // 获取智能模型详情 // getInfoDetail({ equipmentId: row.sampleId }).then((res) => { $router.push({ path: '/info/detail', query: { row: JSON.stringify({ id: row.sampleId, equipmentId: row.sampleId }), id: row.sampleId, statusName: '全部', }, }) // }) } const TextColor = computed(() => { return (name: string) => { let color = '' switch (name) { // case '未接收': // color = '#888' // break // case '已接收': // color = '#000' // break // case '已取消': // color = '#EAA341' // break // case '已退回': // color = '#F68787' // break // case '待取回': // color = '#82CD5E' // break // case '已取回': // color = '#89D961' // break case '检定中': color = '#40AAFF' break case '已检完': color = '#1afa29' break case '未检定': color = '#000' break case '已接收': color = '#1afa29' break case '未接收': color = '#000' break case '已退回': color = '#F68787' break case '待补送': color = '#EAA341' break default: color = '#000' break } return color } }) // --------------------------------------------标签绑定-------------------------------------------- const scanEquipmentRef = ref() // 点击扫描收添加 const scan = () => { // 参数:是标签绑定 scanEquipmentRef.value.initDialog(false, 'detail') } // 扫描结束 const scanOver = (value: any) => { console.log('***************************') console.log(value, 'value, 智能模型列表rfid') scanEquipmentRef.value.closeDialog() // 多选 const ids = [] as any value.forEach((item: any) => { if (!list.value.filter((c: any) => c.sampleId === item.id).length) { ids.push(item.id) list.value.push({ appearanceInspect: '', appendixDescn: '无', measureContent: '', sampleManufacturer: item.manufacturer, sampleManufactureNo: item.manufactureNo, sampleModel: item.model, sampleNo: item.equipmentNo, sampleId: item.id, sampleName: item.equipmentName, helpInstruction: item.helpInstruction, specialRequire: '无', editable: true, }) } }) if (!ids.length) { return } // 获取上一份任务单 智能模型的附件和特殊要求 getPreTaskContent(ids).then((res) => { if (res.data.length) { console.log(res.data, '获取上一份任务单 智能模型的附件和特殊要求') res.data.forEach((item: any) => { const index = list.value.findIndex((citem: any) => citem.sampleId === item.sampleId) if (index !== -1) { list.value[index].appendixDescn = item.appendixDescn list.value[index].specialRequire = item.specialRequire } }) } }) } // --------------------------------------------二维码扫描-------------------------------------------- const qrcodeRef = ref() // 二维码扫描 const qrcode = () => { qrcodeRef.value.initDialog() } // 扫描完成 const qrcodeOver = (value: any) => { console.log('***************************') console.log(value, 'value, 智能模型列表二维码') // 多选 const ids = [] as any value.forEach((item: any) => { if (!list.value.filter((c: any) => c.sampleId === item.id).length) { ids.push(item.id) list.value.push({ appearanceInspect: '', appendixDescn: '无', measureContent: '', sampleManufacturer: item.manufacturer, sampleManufactureNo: item.manufactureNo, sampleModel: item.model, sampleNo: item.equipmentNo, sampleId: item.id, sampleName: item.equipmentName, helpInstruction: item.helpInstruction, specialRequire: '无', editable: true, }) } }) if (!ids.length) { return } // 获取上一份任务单 智能模型的附件和特殊要求 getPreTaskContent(ids).then((res) => { if (res.data.length) { console.log(res.data, '获取上一份任务单 智能模型的附件和特殊要求') res.data.forEach((item: any) => { const index = list.value.findIndex((citem: any) => citem.sampleId === item.sampleId) if (index !== -1) { list.value[index].appendixDescn = item.appendixDescn list.value[index].specialRequire = item.specialRequire } }) } }) } // --------------------------------------------表格操作-------------------------------------------- // 表格标识 const tableFlag = ref('normal')// normal普通表格 together聚合表格 // 切换表格 const changeTable = () => { if (tableFlag.value === 'normal') { tableFlag.value = 'together' } else { tableFlag.value = 'normal' } } const togetherColumns = ref([ { text: '', value: '', align: 'center', width: '38', }, { text: '智能模型名称', value: 'sampleName', align: 'center', }, { text: '总计', value: 'deviceNum', align: 'center', }, ]) const togetherList = ref<any>([]) const expandList = ref<any>([]) function fetchTogetherData() { if (!$route.path.includes('detail')) { return } // const id = JSON.parse($route.query.row as string).id // getTaskTogether(id).then((res) => { // togetherList.value = res.data // }) togetherList.value = [] const equipmentNames = uniqueMultiArray(list.value, 'sampleName') equipmentNames.forEach((element: any) => { togetherList.value.push({ sampleName: element.sampleName, deviceNum: list.value.filter((citem: any) => citem.sampleName === element.sampleName).length, }) }) } const getRowKeys = (row: any) => { // 获取当前行id return row.sampleName // 这里看这一行中需要根据哪个属性值是id } // 控制展开行 const expands = ref<any[]>([]) const expandChange = (row: any, expandedRows: any) => { if (expandedRows.length) { expands.value = [] if (row) { expands.value.push(row.sampleName) } } else { expands.value = [] } } watch(() => expands.value, (newVal) => { expandList.value = list.value.filter((item: any) => item.sampleName === newVal[0]) }, { deep: true, }) </script> <template> <detail-block-switch title="任务单列表"> <!-- 扫描 --> <scan-equipment-dialog ref="scanEquipmentRef" :is-muit="true" title="RFID扫描" @confirm="scanOver" /> <!-- 二维码扫描 --> <q-rcode-device-dialog ref="qrcodeRef" @confirm="qrcodeOver" /> <!-- 选择智能模型弹窗 --> <select-device ref="deviceRef" :measure-company="measureCompany" @add="confirm" /> <select-device-singe ref="deviceSingeRef" :measure-company="measureCompany" @add="confirm" /> <!-- 上传组件 --> <input ref="fileRef" style="display: none;" type="file" @change="onFileChange"> <template #btns> <template v-if="!$route.path.includes('detail')"> <el-button type="primary" @click="qrcode"> 二维码扫描增加 </el-button> <el-button type="primary" @click="scan"> RFID扫描增加 </el-button> <el-button type="primary" @click="batch"> 批量增加 </el-button> <el-button type="primary" @click="addRow"> 增加行 </el-button> <el-button type="info" @click="removeRow"> 删除行 </el-button> </template> <template v-if="$route.path.includes('detail') && $route.query.statusName === '全部'"> <icon-button icon="icon-change" title="切换列表状态" @click="changeTable" /> </template> </template> <!-- 普通表格 --> <el-table v-show="tableFlag === 'normal'" ref="multipleTableRef" :data="list" style="width: 100%;" border @selection-change="handleSelectionChange" @row-dblclick="dblclickRow" > <el-table-column v-if="!$route.path.includes('detail')" type="selection" width="38" /> <el-table-column align="center" label="序号" width="80" type="index" /> <el-table-column v-for="item in ($route.path.includes('detail') && $route.query.statusName === '全部' ? columnsDetail : columnsHandler)" :key="item.value" :width="item.width" :prop="item.value" :label="item.text" align="center" > <template #header> <span v-show="item.required && !$route.path.includes('detail')" style="color: red;">*</span><span>{{ item.text }}</span> </template> <template #default="scope"> <!-- <el-button v-if="!scope.row.editable && !item.isUpload && item.text === '智能模型名称' && $route.path.includes('detail')" link type="primary" @click="deviceDetail(scope.row)"> {{ scope.row[item.value] }} </el-button> <span v-if="!scope.row.editable && !item.isUpload && (item.text !== '智能模型名称' || !$route.path.includes('detail'))">{{ scope.row[item.value] }}</span> <show-photos v-if="!scope.row.editable && item.isUpload" :minio-file-name="scope.row[item.value] " /> <el-input v-if="scope.row.editable && !item.isBtn && !item.isUpload" v-model="scope.row[item.value]" :autofocus="true" :placeholder="`${item.text}`" class="input" /> --> <span v-if="!scope.row.editable" :class="{ link: $route.query.statusName === '全部' && item.text === '智能模型名称' ? true : false }" @click="deviceDetail(scope.row)"> {{ scope.row[item.value] }}</span> <el-input v-if="scope.row.editable && item.type === 'input'" v-model="scope.row[item.value]" :autofocus="true" :placeholder="`${item.text}`" class="input" @focus="select(item.text, scope.$index)" /> <el-input v-if="scope.row.editable && item.type === 'btn'" v-model="scope.row[item.value]" :autofocus="true" :placeholder="`${item.text}`" class="input" @focus="select(item.text, scope.$index)" > <template #append> <span @click="select(item.text, scope.$index)">选择</span> </template> </el-input> <!-- <span v-if="scope.row.editable && item.isUpload && !item.isBtn" style="display: flex;"> --> <!-- <el-input ref="uploadRef" :value="scope.row[item.value]" :placeholder="`${item.text}`" /> --> <!-- @focus.once="upload(scope.$index)" --> <!-- <show-photo :minio-file-name="scope.row[item.value]" /> <el-button v-if="!$route.path.includes('detail')" type="primary" @click="upload(scope.$index)"> {{ scope.row[item.value] ? '更换' : '上传' }} </el-button> --> <!-- </span> --> </template> </el-table-column> <template v-if="$route.path.includes('detail') && $route.query.statusName === '全部'"> <el-table-column align="center" label="接收状态"> <template #default="scope"> <span :style="{ color: TextColor(scope.row.receiveStatusName) }"> {{ scope.row.receiveStatusName }} </span> </template> </el-table-column> <el-table-column align="center" label="接受状态说明"> <template #default="scope"> {{ scope.row.remark }} </template> </el-table-column> <el-table-column align="center" label="检定结果"> <template #default="scope"> <el-tag v-if="['合格', '不合格', '限用'].includes(scope.row.measureCompletePercent)" :type="scope.row.measureCompletePercent === '合格' ? 'success' : scope.row.measureCompletePercent === '不合格' ? 'danger' : scope.row.measureCompletePercent === '限用' ? 'warning' : '' " > {{ scope.row.measureCompletePercent }} </el-tag> <span v-else :style="{ color: TextColor(scope.row.measureCompletePercent) }"> {{ scope.row.measureCompletePercent }} </span> </template> </el-table-column> <el-table-column align="center" label="检定完成时间"> <template #default="scope"> {{ scope.row.measureCompleteTime }} </template> </el-table-column> <el-table-column align="center" label="检定说明"> <template #default="scope"> {{ scope.row.measureRemark }} </template> </el-table-column> </template> </el-table> <!-- 聚合表格 --> <!-- 头部 --> <normal-table v-show="tableFlag === 'together'" class="nortable-header" :data=" [] " :total=" 0 " :columns="togetherColumns as any" :options=" { needIndex: false, // 是否需要序号列 border: true, // 是否需要上方边框 } " :pagination=" false " :is-showmulti-select=" false " :query="{}" /> <!-- 身体 --> <el-table v-show="tableFlag === 'together'" ref="togetherTableRef" :data=" togetherList " border style="width: 100%;" :row-key=" getRowKeys " :expand-row-keys=" expands " :show-header=" false " @expand-change=" expandChange " > <el-table-column type="expand" width="38"> <template #default> <el-table ref="expandTableRef" :data=" expandList " border style="width: 100%;" > <el-table-column v-for="item in ($route.path.includes('detail') && $route.query.statusName === '全部' ? columnsDetail : columnsHandler)" :key="item.value" :label="item.text" :prop="item.value" align="center" /> <template v-if="$route.path.includes('detail') && $route.query.statusName === '全部'"> <el-table-column align="center" label="接收状态"> <template #default="scope"> <span :style="{ color: TextColor(scope.row.receiveStatusName) }"> {{ scope.row.receiveStatusName }} </span> </template> </el-table-column> <el-table-column align="center" label="接受状态说明"> <template #default="scope"> {{ scope.row.remark }} </template> </el-table-column> <el-table-column align="center" label="检定结果"> <template #default="scope"> <el-tag v-if="['合格', '不合格', '限用'].includes(scope.row.measureCompletePercent)" :type="scope.row.measureCompletePercent === '合格' ? 'success' : scope.row.measureCompletePercent === '不合格' ? 'danger' : scope.row.measureCompletePercent === '限用' ? 'warning' : '' " > {{ scope.row.measureCompletePercent }} </el-tag> <span v-else :style="{ color: TextColor(scope.row.measureCompletePercent) }"> {{ scope.row.measureCompletePercent }} </span> </template> </el-table-column> <el-table-column align="center" label="检定完成时间"> <template #default="scope"> {{ scope.row.measureCompleteTime }} </template> </el-table-column> <el-table-column align="center" label="检定说明"> <template #default="scope"> {{ scope.row.measureRemark }} </template> </el-table-column> </template> </el-table> </template> </el-table-column> <el-table-column label="智能模型名称" prop="sampleName" align="center" /> <el-table-column label="数量" align="center"> <template #default=" scope "> 共计{{ scope.row.deviceNum }}台 </template> </el-table-column> </el-table> </detail-block-switch> </template> <style lang="scss" scoped> .el-dialog { width: 700px; } .el-select { width: 100%; } .link { color: #40aaff; &:hover { cursor: pointer; text-decoration: underline; } } .nortable-header { ::v-deep(.el-table__body-wrapper) { display: none; } } ::v-deep(.el-table__expanded-cell) { padding: 0; } </style>