Newer
Older
xc-business-system / src / components / scanEquipmentDialog / index.vue
<!-- 扫描操作弹窗--标签绑定和设备列表页 -->
<script setup lang="ts" name="BarCodeBind">
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import dayjs from 'dayjs'
import type { IEquipmentScan } from './scan-interface'
import scanImg from '@/assets/images/scan.png'
import { getDictByCode } from '@/api/system/dict'
import useWebsocketStore from '@/store/modules/websocket'
import { getReadList, getReaderEquipmentList } from '@/api/reader'
// 扫描状态,未开始0,正在扫描1,扫描结束2

const props = defineProps({
  // 对话框标题
  title: {
    type: String,
    default: '扫描收入',
  },
})
const emits = defineEmits(['confirm'])
const dialogVisible = ref(false) // 弹窗显示
const scanStatus = ref('1')
const isBinding = ref(false) // 是否是标签绑定
const pageType = ref('') // 页面类型、表格list、需要提醒是否绑定,detail详情不提醒
const singleChecked = ref('') // 单选选中id
const websocket = useWebsocketStore()
const columns = ref([]) as any
const columnsList = ref([
  { text: '设备名称', value: 'equipmentName', align: 'center' },
  { text: '规格型号', value: 'model', align: 'center' },
  { text: '出厂编号', value: 'manufactureNo', align: 'center' },
  { text: '生产厂家', value: 'manufacturer', align: 'center' },
  { text: '实验室', value: 'labCodeName', align: 'center' },
  { text: '部门', value: 'groupCodeName', align: 'center' },
  { text: '设备单价(万元)', value: 'unitPrice', align: 'center' },
  { text: '负责人', value: 'directorName', align: 'center', width: '120' },
  { text: '使用状态', value: 'usageStatusName', align: 'center', width: '90' },
  { text: '溯源单位', value: 'traceCompany', align: 'center' },
  { text: '检定有效期', value: 'measureValidDate', align: 'center', width: '120' },
  { text: '所属标准装置', value: 'meterStandardName', align: 'center', width: '120' },
  { text: '标签信息', value: 'label', align: 'center' },
])
const columnsLabel = ref([
  { text: '标签信息', value: 'label', 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 closeDialog = () => {
  list.value = []
  singleChecked.value = ''// 清除选中
  dialogVisible.value = false
}

// 点击确定,保存选择的成员配置
const confirm = () => {
  if (isBinding.value && !singleChecked.value) { // 标签绑定
    ElMessage.warning('请选中')
    return false
  }
  if (list.value.length) {
    if (isBinding.value) { // 标签绑定
      emits('confirm', singleChecked.value)
      singleChecked.value = '' // 清除单选选中
    }
    else {
      emits('confirm', list.value)
    }
  }
  else {
    ElMessage.warning('暂无样品数据, 请重新扫描或取消')
  }
}

// 扫描/ 重新扫描
const scan = (labelId: string) => {
  singleChecked.value = ''// 清除选中
  // 扫描到的标签及样品信息列表
  if (isBinding.value) { // 标签绑定
    list.value.push({
      label: labelId,
    })
    singleChecked.value = list.value[0].label
  }
  else {
    getReaderEquipmentList([labelId]).then((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],
            validDate: res.data[0].validDate ? dayjs(res.data[0].validDate).format('YYYY-MM-DD') : res.data[0].validDate,
            compulsoryVerification: res.data[0].compulsoryVerification === 1 ? '是' : res.data[0].compulsoryVerification === 0 ? '否' : '',
            mesureTypeName: mesureTypeMap.value[res.data[0].mesureType], // 检定方式
            managerStateName: managerStateMap.value[res.data[0].managerState], // 管理状态
          })
        }
        else {
          console.log(`${list.value[index].equipmentName}${list.value[index].model}${list.value[index].manufactureNo}已经添加过`)
        }
      }
    })
  }
}

/**
 * 打开弹窗
 * @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()
    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 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.label" 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>
    <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">
.wait-scan {
  font-size: 18px;
  font-weight: bold;
  text-align: center;
  line-height: 3;

  .scan-img {
    margin-top: 20px;
    width: 128px;
    height: 128px;
  }
}

.el-radio__label {
  display: none !important;
}
</style>