| New file |
| | |
| | | <template> |
| | | <div class="setting-device-dialog-container"> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | center |
| | | title="设置编号" |
| | | width="80%" |
| | | :show-close="false" |
| | | class="scheduled-task-dialog" |
| | | > |
| | | <template #header> |
| | | <div class="setting-dialog-header"> |
| | | <span class="header-title">设置编号</span> |
| | | <img |
| | | :src="closeImg" |
| | | class="header-close" |
| | | @click="handleCancel" |
| | | alt="" |
| | | /> |
| | | </div> |
| | | </template> |
| | | <div class="setting-device-dialog-content"> |
| | | <div class="content-row1"> |
| | | <div class="row1-label">设备编号</div> |
| | | <div class="row1-inp-box"> |
| | | <input |
| | | v-model="devcieCode" |
| | | type="text" |
| | | class="row1-inp" |
| | | placeholder="请输入设备编号或扫码二维码" |
| | | /> |
| | | </div> |
| | | </div> |
| | | <div class="content-row2"> |
| | | <el-upload |
| | | v-loading="isUploading" |
| | | class="upload-demo" |
| | | drag |
| | | :show-file-list="false" |
| | | accept="image/*" |
| | | :limit="1" |
| | | :before-upload="onBeforeUpload" |
| | | > |
| | | <div class="el-upload__text"> |
| | | <img :src="uploadImg" class="upload-img" alt="" /> |
| | | <p class="upload-text">点击虚线区域选择文件并识别二维码</p> |
| | | <div class="upload-btn">二维码上传</div> |
| | | </div> |
| | | </el-upload> |
| | | </div> |
| | | </div> |
| | | <template #footer> |
| | | <div class="my-button cancel" @click="handleCancel">取消</div> |
| | | <div class="my-button confirm" @click="handleConfirm">确认</div> |
| | | <div class="my-button refresh" @click="handleRefresh">刷新</div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script lang="ts" setup> |
| | | import { ElMessage, UploadRawFile } from "element-plus"; |
| | | import { ref } from "vue"; |
| | | import { |
| | | BrowserMultiFormatReader, |
| | | NotFoundException, |
| | | ChecksumException, |
| | | FormatException, |
| | | } from "@zxing/library"; |
| | | import closeImg from "@/img/close.png"; |
| | | import uploadImg from "@/img/upload.png"; |
| | | import { useBedsideAuxiliaryScreenStore } from "@/store/bedsideAuxiliaryScreen"; |
| | | |
| | | const bedsideAuxiliaryScreenStore = useBedsideAuxiliaryScreenStore(); |
| | | |
| | | const isShow = ref(false); |
| | | const isUploading = ref(false); |
| | | const devcieCode = ref(""); |
| | | |
| | | const openDialog = () => { |
| | | devcieCode.value = bedsideAuxiliaryScreenStore.deviceCode + ""; |
| | | isShow.value = true; |
| | | }; |
| | | |
| | | const onBeforeUpload = async (uploadFile: UploadRawFile) => { |
| | | const file = uploadFile; |
| | | if (!file) return; |
| | | |
| | | isUploading.value = true; |
| | | try { |
| | | const result = await decodeQRCodeFromFile(file); |
| | | devcieCode.value = result; |
| | | ElMessage.success("识别成功"); |
| | | } catch (err) { |
| | | if (err instanceof NotFoundException) { |
| | | ElMessage.error("未找到二维码"); |
| | | } else if (err instanceof ChecksumException) { |
| | | ElMessage.error("校验错误"); |
| | | } else if (err instanceof FormatException) { |
| | | ElMessage.error("格式错误"); |
| | | } else { |
| | | ElMessage.error("识别错误请重新识别"); |
| | | console.error(err); |
| | | } |
| | | } finally { |
| | | isUploading.value = false; |
| | | } |
| | | return false; |
| | | }; |
| | | |
| | | const decodeQRCodeFromFile = async (file: File): Promise<string> => { |
| | | return new Promise((resolve, reject) => { |
| | | const reader = new FileReader(); |
| | | |
| | | reader.onload = async (e: any) => { |
| | | const imageBase64 = e.target.result; |
| | | const codeReader = new BrowserMultiFormatReader(); |
| | | |
| | | try { |
| | | const result = await codeReader.decodeFromImage(undefined, imageBase64); |
| | | resolve(result.getText()); |
| | | } catch (err) { |
| | | reject(err); |
| | | } |
| | | }; |
| | | |
| | | reader.onerror = () => reject(new Error("读取文件失败")); |
| | | reader.readAsDataURL(file); |
| | | }); |
| | | }; |
| | | |
| | | const handleCancel = () => { |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | const handleConfirm = () => { |
| | | bedsideAuxiliaryScreenStore.setDeviceCode(devcieCode.value + ""); |
| | | handleRefresh(); |
| | | handleCancel(); |
| | | }; |
| | | |
| | | const handleRefresh = () => { |
| | | bedsideAuxiliaryScreenStore.refresh( |
| | | `${import.meta.env.VITE_SSE_BASE_URL}${devcieCode.value}` |
| | | ); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .setting-device-dialog-container { |
| | | ::v-deep(.el-dialog) { |
| | | padding: 0; |
| | | border-radius: 6px; |
| | | overflow: hidden; |
| | | } |
| | | ::v-deep(.el-dialog__footer) { |
| | | padding: 4px; |
| | | } |
| | | ::v-deep(.el-upload-dragger) { |
| | | height: 65px; |
| | | padding: 0 !important; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | ::v-deep(.el-upload-dragger .el-icon--upload) { |
| | | display: none; |
| | | } |
| | | ::v-deep(.el-dialog__header) { |
| | | padding-bottom: 6px; |
| | | } |
| | | .setting-dialog-header { |
| | | position: relative; |
| | | height: 16px; |
| | | background: #769aff; |
| | | .header-title { |
| | | position: absolute; |
| | | left: 50%; |
| | | top: 50%; |
| | | transform: translateX(-50%) translateY(-50%); |
| | | font-family: AlibabaPuHuiTi, AlibabaPuHuiTi; |
| | | font-weight: 500; |
| | | font-size: 8px; |
| | | color: #ffffff; |
| | | line-height: 11px; |
| | | text-align: center; |
| | | } |
| | | .header-close { |
| | | position: absolute; |
| | | top: 50%; |
| | | transform: translateY(-50%); |
| | | right: 6px; |
| | | width: 15px; |
| | | height: 15px; |
| | | transition: transform 0.2s; |
| | | |
| | | &:active { |
| | | opacity: 0.6; |
| | | transform: translateY(-50%) scale(0.95); |
| | | } |
| | | } |
| | | } |
| | | .setting-device-dialog-content { |
| | | padding: 0 12px 6px; |
| | | margin-bottom: 4px; |
| | | border-bottom: 1px solid #d8d8d8; |
| | | .content-row1 { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 6px; |
| | | |
| | | .row1-label { |
| | | margin-right: 6px; |
| | | padding: 0 4px; |
| | | background: #769aff; |
| | | border-radius: 2px; |
| | | font-family: PingFangSC, PingFang SC; |
| | | font-weight: 600; |
| | | font-size: 8px; |
| | | line-height: 16px; |
| | | color: #ffffff; |
| | | font-style: normal; |
| | | } |
| | | .row1-inp-box { |
| | | flex: 1; |
| | | height: 16px; |
| | | border-radius: 2px; |
| | | border: 1px solid #979797; |
| | | overflow: hidden; |
| | | |
| | | .row1-inp { |
| | | width: 100%; |
| | | height: 100%; |
| | | border: none; |
| | | outline: none; |
| | | padding: 0 4px; |
| | | line-height: 16px; |
| | | font-size: 9px; |
| | | font-family: PingFangSC, PingFang SC; |
| | | vertical-align: middle; |
| | | box-sizing: border-box; // 避免padding撑高 |
| | | |
| | | &::placeholder { |
| | | font-family: inherit; |
| | | font-size: inherit; |
| | | line-height: inherit; |
| | | color: #aaaaaa; |
| | | opacity: 1; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .el-upload__text { |
| | | display: flex; |
| | | align-items: center; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | .upload-img { |
| | | height: 8px; |
| | | } |
| | | .upload-text { |
| | | font-family: PingFangSC, PingFang SC; |
| | | font-weight: 500; |
| | | font-size: 5px; |
| | | color: #5a6470; |
| | | letter-spacing: 0px; |
| | | text-align: center; |
| | | font-style: normal; |
| | | } |
| | | .upload-btn { |
| | | padding: 0 2px; |
| | | background-color: #409eff; |
| | | border-radius: 1px; |
| | | font-family: PingFangSC, PingFang SC; |
| | | font-size: 4px; |
| | | color: #fff; |
| | | letter-spacing: 0px; |
| | | line-height: 8px; |
| | | text-align: center; |
| | | font-style: normal; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .my-button { |
| | | display: inline-block; |
| | | border-radius: 2px; |
| | | padding: 0px 10px; |
| | | font-family: PingFangSC, PingFang SC; |
| | | font-weight: 500; |
| | | font-size: 7px; |
| | | color: #ffffff; |
| | | line-height: 16px; |
| | | letter-spacing: 1px; |
| | | text-align: center; |
| | | font-style: normal; |
| | | transition: transform 0.1s ease, opacity 0.1s ease; |
| | | cursor: pointer; |
| | | &:active { |
| | | transform: scale(0.95); |
| | | opacity: 0.8; |
| | | } |
| | | |
| | | &:not(:first-child) { |
| | | margin-left: 6px; |
| | | } |
| | | &.cancel { |
| | | background: #bbc6dd; |
| | | } |
| | | &.confirm { |
| | | background: #769aff; |
| | | } |
| | | &.refresh { |
| | | background: #e6a23c; |
| | | } |
| | | } |
| | | } |
| | | </style> |
| | | <style> |
| | | .scheduled-task-dialog { |
| | | margin: 0 auto; |
| | | top: 50% !important; |
| | | transform: translateY(-50%) !important; |
| | | } |
| | | </style> |