From 001b025ff84dec3c614f0b0346e9a50491034f04 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 06 十一月 2025 11:09:16 +0800
Subject: [PATCH] 应收台账-查询修改
---
src/views/inspectionUpload/index.vue | 292 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 280 insertions(+), 12 deletions(-)
diff --git a/src/views/inspectionUpload/index.vue b/src/views/inspectionUpload/index.vue
index 559c05e..29f6c38 100644
--- a/src/views/inspectionUpload/index.vue
+++ b/src/views/inspectionUpload/index.vue
@@ -15,16 +15,74 @@
/>
</el-tabs>
<div>
+ <!-- 鎵爜妯″潡 -->
+ <div v-if="activeTab === 'qrCode'" class="scan-section">
+ <div class="scan-controls">
+ <el-button
+ type="primary"
+ :loading="scanLoading"
+ @click="toggleScan"
+ >
+ {{ scanButtonText }}
+ </el-button>
+ </div>
+
+ <!-- 鎵爜瑙嗛瀹瑰櫒 -->
+ <div v-show="isScanning" class="qr-video-container">
+ <video
+ ref="qrVideo"
+ class="qr-video"
+ playsinline
+ webkit-playsinline
+ ></video>
+ <div class="scan-overlay"></div>
+ </div>
+
+ <!-- 鐘舵�佹彁绀� -->
+ <div class="status-info">
+ <el-alert
+ v-if="cameraError"
+ :title="cameraError"
+ type="error"
+ show-icon
+ closable
+ />
+ <div v-if="isScanning" class="scanning-text">
+ <el-icon :color="statusColor"><Loading /></el-icon>
+ 姝e湪鎵弿浜岀淮鐮�...
+ </div>
+ </div>
+ </div>
<div>
- <el-table ref="table" :data="tableData" height="480" v-loading="tableLoading">
+ <el-table ref="table" :data="tableData" height="480" v-loading="tableLoading" v-if="activeTab !== 'qrCode'" border style="width: 100%;height: calc(100vh - 20em)">
<el-table-column label="搴忓彿" type="index" width="60" align="center" />
<el-table-column prop="taskName" label="宸℃浠诲姟鍚嶇О" :show-overflow-tooltip="true"></el-table-column>
- <el-table-column prop="port" label="鍦扮偣" :show-overflow-tooltip="true"></el-table-column>
+ <el-table-column prop="inspectionLocation" label="鍦扮偣" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="remarks" label="澶囨敞"></el-table-column>
<el-table-column prop="inspector" label="鎵ц宸℃浜�"></el-table-column>
<el-table-column fixed="right" label="鎿嶄綔">
<template #default="scope">
<el-button link type="primary" @click="handleAdd(scope.row)">涓婁紶</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ <el-table ref="table" :data="tableData" height="480" v-loading="tableLoading" v-if="activeTab === 'qrCode'" border style="width: 100%;height: calc(100vh - 23em)">
+ <el-table-column label="搴忓彿" type="index" width="60" align="center" />
+ <el-table-column prop="deviceName" label="璁惧鍚嶇О" :show-overflow-tooltip="true">
+ <template #default="scope">
+ {{scope.row.qrCode.deviceName}}
+ </template>
+ </el-table-column>
+ <el-table-column prop="location" label="鎵�鍦ㄤ綅缃弿杩�" :show-overflow-tooltip="true">
+ <template #default="scope">
+ {{scope.row.qrCode.location}}
+ </template>
+ </el-table-column>
+ <el-table-column prop="scanner" label="宸℃浜�"></el-table-column>
+ <el-table-column prop="scanTime" label="宸℃鏃堕棿"></el-table-column>
+ <el-table-column fixed="right" label="鎿嶄綔">
+ <template #default="scope">
+ <el-button link type="primary" @click="viewFile(scope.row)">鏌ョ湅闄勪欢</el-button>
</template>
</el-table-column>
</el-table>
@@ -40,22 +98,31 @@
</div>
</el-card>
<form-dia ref="formDia" @closeDia="handleQuery"></form-dia>
+ <qr-code-form-dia ref="qrCodeFormDia" @closeDia="handleQuery"></qr-code-form-dia>
+ <view-qr-code-files ref="viewQrCodeFiles"></view-qr-code-files>
</div>
</template>
<script setup>
import Pagination from "@/components/Pagination/index.vue";
-import {inspectionTaskList} from "@/api/inspectionManagement/index.js";
import {onMounted, ref} from "vue";
import FormDia from "@/views/inspectionUpload/components/formDia.vue";
+import {ElMessage} from "element-plus";
+import QrScanner from 'qr-scanner'
+import QrCodeFormDia from "@/views/inspectionUpload/components/qrCodeFormDia.vue";
+import {qrCodeList, qrCodeScanRecordList} from "@/api/inspectionUpload/index.js";
+import {inspectionTaskList} from "@/api/inspectionManagement/index.js";
+import ViewQrCodeFiles from "@/views/inspectionManagement/components/viewQrCodeFiles.vue";
const formDia = ref()
+const qrCodeFormDia = ref()
+const viewQrCodeFiles = ref()
// 褰撳墠鏍囩
const activeTab = ref("task");
const tabName = ref("task");
// 鏍囩椤垫暟鎹�
const tabs = reactive([
- { name: "task", label: "浠诲姟涓嬪彂" },
- { name: "qrCode", label: "浜岀淮鐮佺鐞�" },
+ { name: "task", label: "鐢熶骇宸℃" },
+ { name: "qrCode", label: "鐜板満宸℃" },
]);
// 琛ㄦ牸
const tableData = ref([]);
@@ -63,10 +130,32 @@
const total = ref(0);
const pageNum = ref(1);
const pageSize = ref(10);
+// 鎵爜鐩稿叧鐘舵��
+const qrVideo = ref(null)
+const isScanning = ref(false)
+const scanLoading = ref(false)
+const cameraError = ref(null)
+const scanner = ref(null)
+const hasInit = ref(false)
-onMounted(() => {
+const statusColor = computed(() => {
+ return isScanning.value ? '#67C23A' : '#F56C6C'
+})
+// 鐢熷懡鍛ㄦ湡绠$悊浼樺寲
+onMounted(async () => {
handleTabClick({ props: { name: "task" } });
-});
+ if (!import.meta.env.SSR && QrScanner) { // [!code focus]
+ await initScanner()
+ }
+})
+
+onBeforeUnmount(async () => {
+ if (scanner.value) {
+ await scanner.value.destroy()
+ scanner.value = null
+ }
+ hasInit.value = false
+})
// 鏍囩椤电偣鍑�
const handleTabClick = (tab) => {
tabName.value = tab.props.name;
@@ -81,11 +170,19 @@
}
const getList = () => {
tableLoading.value = true;
- inspectionTaskList({size: pageSize.value, current: pageNum.value}).then(res => {
- tableLoading.value = false;
- tableData.value = res.data.records;
- total.value = res.data.total;
- })
+ if (tabName.value === "task") {
+ inspectionTaskList({size: pageSize.value, current: pageNum.value}).then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ total.value = res.data.total;
+ })
+ } else {
+ qrCodeScanRecordList({size: pageSize.value, current: pageNum.value}).then(res => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ total.value = res.data.total;
+ })
+ }
};
// 涓婁紶
const handleAdd = (row) => {
@@ -93,10 +190,181 @@
formDia.value?.openDialog(row)
})
}
+// 鏌ョ湅闄勪欢
+const viewFile = (row) => {
+ nextTick(() => {
+ viewQrCodeFiles.value?.openDialog(row)
+ })
+}
+// 鎵爜鎸夐挳鏂囨湰
+const scanButtonText = computed(() => {
+ if (scanLoading.value) return '姝e湪鍒濆鍖�...'
+ return isScanning.value ? '鍋滄鎵爜' : '寮�濮嬫壂鐮�'
+})
+// 澧炲己鍨嬪垵濮嬪寲
+const initScanner = async () => {
+ try {
+ await nextTick() // 纭繚DOM鏇存柊
+ // 鏂板澶氶噸绌哄�兼牎楠�
+ if (!qrVideo.value || !QrScanner) {
+ throw new Error('渚濊禆鏈纭垵濮嬪寲')
+ }
+ // 澧炲姞鎽勫儚澶存潈闄愰妫�鏌�
+ const hasCamera = await QrScanner.hasCamera()
+ if (!hasCamera) {
+ throw new Error('鏈娴嬪埌鍙敤鎽勫儚澶�')
+ }
+ // 鏄惧紡閿�姣佹棫瀹炰緥
+ if (scanner.value) {
+ await scanner.value.destroy()
+ }
+ // 鍒涘缓鏂板疄渚�
+ scanner.value = new QrScanner(
+ qrVideo.value,
+ result => {
+ handleScanSuccess(result)
+ // stopScan()
+ },
+ {
+ preferredCamera: 'environment',
+ maxScansPerSecond: 5,
+ returnDetailedScanResult: true
+ }
+ )
+ // 鏂板纭欢鍔犻�熸娴�
+ if (!scanner.value._qrWorker) {
+ throw new Error('纭欢鍔犻�熶笉鍙敤')
+ }
+ hasInit.value = true
+ } catch (e) {
+ // handleInitError(e)
+ }
+}
+// 鎵弿鎴愬姛澶勭悊
+const handleScanSuccess = async (result) => {
+ try {
+ // 娣诲姞鏁版嵁鏍¢獙
+ ElMessage.success('璇嗗埆鎴愬姛')
+ callBackendAPI(JSON.parse(result.data))
+ await stopScan()
+ } catch (error) {
+ ElMessage.warning(error.message)
+ await startScan() // 鏁版嵁鏃犳晥鏃剁户缁壂鎻�
+ }
+}
+const callBackendAPI = (result) => {
+ nextTick(() => {
+ qrCodeFormDia.value?.openDialog(result)
+ })
+}
+// 鍒囨崲鎵爜鐘舵��
+const toggleScan = async () => {
+ if (isScanning.value) {
+ await stopScan()
+ } else {
+ await startScan()
+ }
+}
+
+// 澧炲己鍚姩鏂规硶
+const startScan = async () => {
+ if (!scanner.value || !hasInit.value) { // 鏂板鐘舵�佹鏌�
+ await initScanner()
+ }
+
+ try {
+ await scanner.value.start()
+ isScanning.value = true
+ } catch (e) {
+ ElMessage.error(`鍚姩澶辫触: ${e.message}`)
+ hasInit.value = false
+ }
+}
+
+// 鍋滄鎵爜
+const stopScan = async () => {
+ try {
+ await scanner.value.stop()
+ isScanning.value = false
+ } catch (err) {
+ console.error('鍋滄鎽勫儚澶村け璐�:', err)
+ }
+}
+
+
+// 閿欒澶勭悊澧炲己
+const handleInitError = (error) => {
+ console.error('鍒濆鍖栧け璐�:', error)
+ const msg = {
+ 'NotAllowedError': '璇峰厑璁告憚鍍忓ご鏉冮檺',
+ 'NotFoundError': '鏈壘鍒版憚鍍忓ご璁惧',
+ 'NotSupportedError': '娴忚鍣ㄤ笉鏀寔鎵爜鍔熻兘'
+ }[error.name] || error.message
+
+ ElMessage.error(`鍒濆鍖栧け璐�: ${msg}`)
+}
</script>
<style scoped>
+.qr-video-container {
+ position: relative;
+ width: 100%;
+ max-width: 500px;
+ margin: 0 auto;
+ background: #000;
+ border-radius: 8px;
+ overflow: hidden;
+}
+.qr-video {
+ width: 100%;
+ height: auto;
+ object-fit: cover;
+}
+
+.scan-overlay {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ width: 70%;
+ height: 70%;
+ border: 3px solid #409eff;
+ border-radius: 8px;
+ box-shadow: 0 0 20px rgba(64, 158, 255, 0.3);
+ animation: pulse 2s infinite;
+}
+
+@keyframes pulse {
+ 0% { opacity: 0.8; }
+ 50% { opacity: 0.4; }
+ 100% { opacity: 0.8; }
+}
+
+.status-info {
+ margin-top: 16px;
+ text-align: center;
+}
+
+.scanning-text {
+ color: #409eff;
+ margin-top: 8px;
+}
+
+.table-section {
+ margin-top: 24px;
+}
+
+/* 绉诲姩绔紭鍖� */
+@media (max-width: 768px) {
+ .qr-video-container {
+ height: 60vh;
+ }
+
+ .el-table {
+ font-size: 12px;
+ }
+}
</style>
\ No newline at end of file
--
Gitblit v1.9.3