<!-- 扫描操作弹窗 --> <script setup lang="ts" name="BarCodeBind"> import { ref } from 'vue' import { ElMessage, ElMessageBox } from 'element-plus' import dayjs from 'dayjs' import scanImg from '@/assets/images/scan.png' import { getDictByCode } from '@/api/system/dict' import { getReadList, getReaderEquipmentList } from '@/api/reader' import useWebsocketStore from '@/store/modules/websocket' import { devcieOrderSelect } from '@/api/eqpt/device/info' // 扫描状态,未开始0,正在扫描1,扫描结束2 const props = defineProps({ // 对话框标题 title: { type: String, default: '扫描收入', }, isMuit: { type: Boolean, default: false, }, }) const emits = defineEmits(['confirm']) const $route = useRoute() const dialogVisible = ref(false) // 弹窗显示 const multipleTableRef = ref() const loading = ref(false) const scanStatus = ref('0') const isBinding = ref(false) // 是否是标签绑定 const pageType = ref('') // 页面类型、表格list、需要提醒是否绑定,detail详情不提醒 const singleChecked = ref('') // 单选选中id const columns = ref([]) as any const websocket = useWebsocketStore() const columnsList = ref([ { text: '设备名称', value: 'equipmentName', align: 'center', filters: true, }, { text: '规格型号', value: 'model', align: 'center', sortable: 'custom', filters: true, }, { text: '出厂编号', value: 'manufactureNo', align: 'center', sortable: 'custom', filters: true, }, { text: '生产厂家', value: 'manufacturer', align: 'center', // sortable: 'custom', filters: true, }, { text: '所在单位', value: 'companyName', align: 'center', // sortable: 'custom', filters: true, }, { text: '使用部门', value: 'deptName', align: 'center', // sortable: 'custom', filters: true, }, { text: '使用岗位', value: 'usePosition', align: 'center', filters: true, }, { text: '计量标识', value: 'meterIdentifyName', align: 'center', filters: true, }, // { // text: '检定周期', // value: 'checkCycle', // align: 'center', // }, { text: '证书有效期', value: 'certificateValid', align: 'center', sortable: 'custom', filters: true, }, { text: '使用状态', value: 'usageStatusName', align: 'center', sortable: 'custom', filters: true, }, { text: '标签信息', value: 'rfid', align: 'center', sortable: 'custom', filters: true, }, ]) const columnsLabel = ref([ { text: '标签信息', value: 'rfid', align: 'center' }, ]) // 扫描到的标签列表 const list = ref([]) as any // 获取数据 const mesureTypeMap = ref({}) as any const managerStateMap = ref({}) as any const getDict = async () => { // 获取检定方式 const responseMeasureType = await getDictByCode('measureType') responseMeasureType.data.forEach((item: { value: string; name: string }) => { mesureTypeMap.value[item.value] = item.name }) // 获取管理状态 const responseManagerState = await getDictByCode('managerState') responseManagerState.data.forEach((item: { value: string; name: string }) => { managerStateMap.value[item.value] = item.name }) } const checkList = ref([]) // 多选选中 // 多选 const handleSelectionChange = (val: any) => { checkList.value = val } // 关闭弹窗 const closeDialog = () => { list.value = [] singleChecked.value = ''// 清除选中 dialogVisible.value = false } // 点击确定,保存选择的成员配置 const confirm = () => { if (isBinding.value && (!singleChecked.value && !checkList.value.length)) { // 标签绑定 ElMessage.warning('请选中') return false } const message = isBinding.value ? '确认绑定吗?' : `确认${props.title}列表中的设备吗?` if (list.value.length) { if (isBinding.value) { // 标签绑定 // if (pageType.value === 'detail') { // emits('confirm', singleChecked.value) // singleChecked.value = '' // 清除单选选中 // } // else { // ElMessageBox.confirm( // message, // '提示', // { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning' }, // ).then(() => { // emits('confirm', singleChecked.value) // singleChecked.value = '' // }) // } emits('confirm', props.isMuit ? checkList.value : singleChecked.value) // singleChecked.value = '' // 清除单选选中 checkList.value = [] multipleTableRef.value.clearSelection() } else { emits('confirm', props.isMuit ? checkList.value : list.value) checkList.value = [] multipleTableRef.value.clearSelection() } } else { ElMessage.warning('暂无样品数据, 请重新扫描或取消') } } // 扫描/ 重新扫描 const scan = (labelId: string) => { singleChecked.value = ''// 清除选中 // 扫描到的标签及样品信息列表 if (isBinding.value) { // 标签绑定 list.value.push({ rfid: labelId, }) singleChecked.value = list.value[0].rfid } else { getReaderEquipmentList([labelId]).then(async (res) => { if (res && res.data && res.data.length) { const index = list.value.findIndex((item: { id: string }) => item.id === res.data[0].id) if (index === -1) { list.value.push({ ...res.data[0], certificateValid: res.data[0].certificateValid ? dayjs(res.data[0].certificateValid).format('YYYY-MM-DD') : res.data[0].certificateValid, }) } else { console.log(`${list.value[index].equipmentName}${list.value[index].model}${list.value[index].manufactureNo}已经添加过`) } } // 任务单-- 做校验全部勾选 if ($route.path.includes('meteringtask')) { loading.value = true // 任务单添加设备需要判断符不符合送检要求 const dataBak = JSON.parse(JSON.stringify(list.value)) list.value = [] await Promise.all(dataBak.map(async (item: any) => { await devcieOrderSelect({ limit: 1, offset: 1, checkDestination: '1', // 鉴定去向 计量室 equipmentName: item.equipmentName, directorName: item.directorName, manufactureNo: item.manufactureNo, manufacturer: item.manufacturer, }).then((res) => { if (res.data.rows.length) { list.value.push({ ...item, }) } }) })) // 自动全部勾选 multipleTableRef.value.toggleAllSelection() loading.value = false // 提示 ElMessage.warning(`共扫描到${dataBak.length}台设备,其中${dataBak.length - list.value.length}台不符合送检要求`) } }) } } /** * 打开弹窗 * @param isBindingValue 是否标签绑定 */ const initDialog = (isBindingValue = false, pageTypeParam = '') => { getDict().then(() => { isBinding.value = isBindingValue columns.value = isBindingValue ? columnsLabel.value : columnsList.value pageType.value = pageTypeParam scanStatus.value = '1' websocket.initWebSocket() // scan('E280689420005022C6508CBC') // scan('E280689420004022C655309D') // scanStatus.value = '2' dialogVisible.value = true }) } // 断开websocket function stopWebScket() { websocket.destroyWebSocket() } // 重连 const reStartWebScket = () => { websocket.reConnectWebsocket() } // 重新扫描 const reScan = () => { list.value = [] scanStatus.value = '1' stopWebScket() websocket.initWebSocket() } onBeforeMount(() => { stopWebScket() }) // 监听消息列表变化 watch(() => websocket.labelId, (newVal) => { console.log('监听到了标签数据', newVal) if (newVal) { scan(newVal) } }, { immediate: true }) // 监听websocket是否连接 watch(() => websocket.wsStatus, (newVal) => { console.log('监听到websocket是否连接', newVal) if (newVal) { // 连上 scanStatus.value = '2' } else { // 断开 scanStatus.value = '1' } }, { immediate: true, }) // ----定义对外暴露的方法 初始化弹窗, 关闭弹窗 defineExpose({ initDialog, closeDialog }) </script> <template> <el-dialog v-model="dialogVisible" :title="title" width="80%" append-to-body :before-close="closeDialog"> <div style="margin-top: -20px;width: 100%;"> <div v-if="scanStatus === '1'" class="wait-scan"> <div>请使读写器扫描标签</div> <el-image :src="scanImg" class="scan-img" /> </div> <!-- 扫描结果 --> <div v-else-if="scanStatus === '2'"> <div v-if="!isBinding" style="margin-top: 20px;"> 扫描到 <span style="font-weight: 600;">{{ list.length }} </span>个设备 </div> <div v-if="isBinding" style="margin-top: 20px;"> 扫描到 <span style="font-weight: 600;">{{ list.length }} </span> 个标签{{ list.length > 1 ? ',请选择需要绑定的标签' : '' }} </div> <el-table v-if="$route.path.includes('meteringtask')" ref="multipleTableRef" v-loading="loading" :data="list" style="width: 100%;margin-top: 10px;" border stripe @selection-change="handleSelectionChange"> <el-table-column type="index" label="序号" width="55" align="center" /> <el-table-column v-if="isBinding && !props.isMuit" label="" width="60" align="center"> <template #default="scope"> <el-radio v-model="singleChecked" :label="scope.row.rfid" class="radio" /> </template> </el-table-column> <el-table-column v-if="isBinding && props.isMuit" type="selection" width="60" align="center" /> <el-table-column v-if="!isBinding && props.isMuit" type="selection" width="60" align="center" /> <el-table-column v-if="!isBinding" show-overflow-tooltip prop="equipmentNo" label="设备编号" align="center" width="160px" /> <el-table-column v-if="!isBinding" show-overflow-tooltip prop="equipmentName" label="名称" align="center" /> <el-table-column v-if="!isBinding" show-overflow-tooltip prop="model" label="型号规格" align="center" /> <el-table-column v-if="!isBinding" show-overflow-tooltip prop="manufactureNo" label="出厂编号" align="center" width="90px" /> <el-table-column v-if="!isBinding" show-overflow-tooltip prop="checkCycle" label="检定周期" align="center" width="120px" /> <el-table-column v-if="!isBinding" show-overflow-tooltip prop="usePosition" label="使用岗位" align="center" width="120px" /> <el-table-column v-if="!isBinding" show-overflow-tooltip prop="directorName" label="负责人" align="center" /> <!-- <el-table-column v-if="!isBinding" show-overflow-tooltip prop="certificateValid" label="证书有效期" align="center" width="120px" /> --> <el-table-column show-overflow-tooltip prop="rfid" label="标签信息" align="center" /> <!-- <el-table-column v-if="!isBinding" label="操作" align="center" width="60px" fixed="right"> <template #default="scope"> <el-button size="small" link type="primary" @click="deleteRow (scope.$index)"> 详情 </el-button> </template> </el-table-column> --> </el-table> <el-table v-else ref="multipleTableRef" :data="list" style="width: 100%;margin-top: 10px;" border stripe> <el-table-column type="index" label="序号" width="55" align="center" /> <el-table-column v-if="isBinding" label="" width="60" align="center"> <template #default="scope"> <el-radio v-model="singleChecked" :label="scope.row.rfid" class="radio" /> </template> </el-table-column> <el-table-column v-for="item in columns" :key="item.value" :prop="item.value" :label="item.text" :width="item.width" align="center" > <template #header> <span>{{ item.text }}</span> </template> </el-table-column> </el-table> </div> </div> <!-- </div> --> <template #footer> <el-button v-if="websocket.wsStatus" type="danger" @click="stopWebScket"> 断开连接 </el-button> <!-- <el-button v-if="scanStatus === '1'" type="primary" @click="reScan"> 重新扫描 </el-button> --> <el-button v-if="isBinding" @click="closeDialog"> 取 消 </el-button> <el-button v-if="isBinding" type="primary" @click="confirm"> 确 定 </el-button> <el-button v-if="!isBinding" @click="closeDialog"> 关 闭 </el-button> </template> </el-dialog> </template> <style lang="scss" scoped> .wait-scan { font-size: 18px; font-weight: bold; text-align: center; line-height: 3; .scan-img { margin-top: 20px; width: 128px; height: 128px; } } .radio { ::v-deep(.el-radio__label) { display: none !important; } } </style>