From d85836bf6b1574122830f6db8770e98184edd51c Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期六, 20 九月 2025 09:49:01 +0800
Subject: [PATCH] 巡检上传页面

---
 src/pages/equipmentManagement/inspection/index.vue      |    2 
 src/pages/index.vue                                     |    6 
 src/pages/inspectionUpload/components/formDia.vue       |  256 +++++++++
 src/pages.json                                          |    7 
 src/api/inspectionUpload/index.js                       |   43 +
 src/api/inspectionManagement/index.js                   |   61 ++
 src/api/equipmentManagement/inspection.js               |  433 ++++++++++----
 src/pages/inspectionUpload/index.vue                    |  597 +++++++++++++++++++++
 src/pages/inspectionUpload/components/qrCodeFormDia.vue |  254 +++++++++
 9 files changed, 1,517 insertions(+), 142 deletions(-)

diff --git a/src/api/equipmentManagement/inspection.js b/src/api/equipmentManagement/inspection.js
index 5545b4e..c3113a8 100644
--- a/src/api/equipmentManagement/inspection.js
+++ b/src/api/equipmentManagement/inspection.js
@@ -1,220 +1,377 @@
-import request from "@/utils/request";
+import request from '@/utils/request'
+
+// ==================== 宸℃浠诲姟绠$悊 ====================
 
 /**
- * @desc 鑾峰彇宸℃娓呭崟鍒楄〃
- * @param {Object} params - 鏌ヨ鍙傛暟
- * @param {string} params.date - 宸℃鏃ユ湡
- * @param {string} params.inspector - 宸℃鍛�
- * @param {number} params.status - 宸℃鐘舵�� 0:寰呭贰妫� 1:宸℃涓� 2:宸插畬鎴�
+ * @desc 鏌ヨ宸℃浠诲姟鍒楄〃
+ * @param {Object} query - 鏌ヨ鍙傛暟
+ * @param {string} query.date - 宸℃鏃ユ湡
+ * @param {string} query.status - 浠诲姟鐘舵��
+ * @param {string} query.inspector - 宸℃鍛�
  * @returns {Promise}
  */
-export const getInspectionList = (params) => {
+export function getInspectionTaskList(query) {
   return request({
-    url: "/device/inspection/list",
-    method: "get",
-    params,
-  });
-};
+    url: '/equipment/inspection/task/list',
+    method: 'get',
+    params: query
+  })
+}
 
 /**
- * @desc 鑾峰彇宸℃璇︽儏
- * @param {string|number} id - 宸℃ID
+ * @desc 鏌ヨ宸℃浠诲姟璇︾粏
+ * @param {string|number} id - 浠诲姟ID
  * @returns {Promise}
  */
-export const getInspectionDetail = (id) => {
+export function getInspectionTask(id) {
   return request({
-    url: `/device/inspection/${id}`,
-    method: "get",
-  });
-};
+    url: '/equipment/inspection/task/' + id,
+    method: 'get'
+  })
+}
 
 /**
- * @desc 寮�濮嬪贰妫�
- * @param {Object} data - 宸℃鏁版嵁
- * @param {string|number} data.inspectionId - 宸℃ID
- * @param {string} data.startTime - 寮�濮嬫椂闂�
+ * @desc 鍒涘缓宸℃浠诲姟
+ * @param {Object} data - 浠诲姟鏁版嵁
  * @returns {Promise}
  */
-export const startInspection = (data) => {
+export function createInspectionTask(data) {
   return request({
-    url: "/device/inspection/start",
-    method: "post",
-    data,
-  });
-};
+    url: '/equipment/inspection/task',
+    method: 'post',
+    data: data
+  })
+}
+
+/**
+ * @desc 鏇存柊宸℃浠诲姟
+ * @param {Object} data - 浠诲姟鏁版嵁
+ * @returns {Promise}
+ */
+export function updateInspectionTask(data) {
+  return request({
+    url: '/equipment/inspection/task',
+    method: 'put',
+    data: data
+  })
+}
+
+/**
+ * @desc 鍒犻櫎宸℃浠诲姟
+ * @param {string|number} id - 浠诲姟ID
+ * @returns {Promise}
+ */
+export function deleteInspectionTask(id) {
+  return request({
+    url: '/equipment/inspection/task/' + id,
+    method: 'delete'
+  })
+}
+
+/**
+ * @desc 寮�濮嬪贰妫�浠诲姟
+ * @param {string|number} taskId - 浠诲姟ID
+ * @returns {Promise}
+ */
+export function startInspectionTask(taskId) {
+  return request({
+    url: '/equipment/inspection/task/' + taskId + '/start',
+    method: 'post'
+  })
+}
+
+/**
+ * @desc 瀹屾垚宸℃浠诲姟
+ * @param {string|number} taskId - 浠诲姟ID
+ * @param {Object} data - 瀹屾垚鏁版嵁
+ * @returns {Promise}
+ */
+export function completeInspectionTask(taskId, data) {
+  return request({
+    url: '/equipment/inspection/task/' + taskId + '/complete',
+    method: 'post',
+    data: data
+  })
+}
+
+// ==================== 宸℃璁板綍绠$悊 ====================
 
 /**
  * @desc 鎻愪氦宸℃璁板綍
  * @param {Object} data - 宸℃璁板綍鏁版嵁
- * @param {string|number} data.deviceId - 璁惧ID
- * @param {string} data.deviceCode - 璁惧缂栫爜
- * @param {string} data.inspectionDate - 宸℃鏃ユ湡
- * @param {string} data.inspector - 宸℃鍛�
- * @param {string} data.scanTime - 鎵爜鏃堕棿
- * @param {Array} data.items - 宸℃椤圭洰鍒楄〃
- * @param {string} data.completedAt - 瀹屾垚鏃堕棿
  * @returns {Promise}
  */
-export const submitInspectionRecord = (data) => {
+export function submitInspectionRecord(data) {
   return request({
-    url: "/device/inspection/submit",
-    method: "post",
-    data,
-  });
-};
+    url: '/equipment/inspection/record/submit',
+    method: 'post',
+    data: data
+  })
+}
 
 /**
- * @desc 鏇存柊宸℃椤圭洰
- * @param {Object} data - 宸℃椤圭洰鏁版嵁
- * @param {string|number} data.inspectionId - 宸℃ID
- * @param {string|number} data.itemId - 椤圭洰ID
- * @param {string} data.result - 宸℃缁撴灉 normal:姝e父 abnormal:寮傚父
- * @param {string} data.abnormalDesc - 寮傚父鎻忚堪
- * @param {Array} data.images - 鍥剧墖鍒楄〃
- * @param {Array} data.videos - 瑙嗛鍒楄〃
- * @param {string} data.remark - 澶囨敞
+ * @desc 鏌ヨ宸℃璁板綍鍒楄〃
+ * @param {Object} query - 鏌ヨ鍙傛暟
  * @returns {Promise}
  */
-export const updateInspectionItem = (data) => {
+export function getInspectionRecordList(query) {
   return request({
-    url: "/device/inspection/item/update",
-    method: "put",
-    data,
-  });
-};
+    url: '/equipment/inspection/record/list',
+    method: 'get',
+    params: query
+  })
+}
 
 /**
- * @desc 鎵爜鎵撳崱
- * @param {Object} data - 鎵撳崱鏁版嵁
- * @param {string|number} data.inspectionId - 宸℃ID
- * @param {string} data.deviceCode - 璁惧缂栫爜
- * @param {string} data.qrCode - 浜岀淮鐮佸唴瀹�
- * @param {string} data.checkInTime - 鎵撳崱鏃堕棿
- * @param {string} data.location - 鎵撳崱浣嶇疆
+ * @desc 鏌ヨ宸℃璁板綍璇︽儏
+ * @param {string|number} id - 璁板綍ID
  * @returns {Promise}
  */
-export const checkInByQRCode = (data) => {
+export function getInspectionRecord(id) {
   return request({
-    url: "/device/inspection/checkin",
-    method: "post",
-    data,
-  });
-};
+    url: '/equipment/inspection/record/' + id,
+    method: 'get'
+  })
+}
+
+// ==================== 鏂囦欢涓婁紶 ====================
 
 /**
- * @desc 涓婁紶宸℃鏂囦欢锛堝浘鐗�/瑙嗛锛�
+ * @desc 涓婁紶宸℃鍥剧墖
+ * @param {File} file - 鍥剧墖鏂囦欢
+ * @returns {Promise}
+ */
+export function uploadInspectionImage(file) {
+  return request({
+    url: '/equipment/inspection/upload/image',
+    method: 'post',
+    data: file,
+    headers: {
+      'Content-Type': 'multipart/form-data'
+    }
+  })
+}
+
+/**
+ * @desc 涓婁紶宸℃瑙嗛
+ * @param {File} file - 瑙嗛鏂囦欢
+ * @returns {Promise}
+ */
+export function uploadInspectionVideo(file) {
+  return request({
+    url: '/equipment/inspection/upload/video',
+    method: 'post',
+    data: file,
+    headers: {
+      'Content-Type': 'multipart/form-data'
+    }
+  })
+}
+
+/**
+ * @desc 鎵归噺涓婁紶鏂囦欢
  * @param {FormData} formData - 鏂囦欢鏁版嵁
  * @returns {Promise}
  */
-export const uploadInspectionFile = (formData) => {
+export function batchUploadFiles(formData) {
   return request({
-    url: "/device/inspection/upload",
-    method: "post",
+    url: '/equipment/inspection/upload/batch',
+    method: 'post',
     data: formData,
     headers: {
       'Content-Type': 'multipart/form-data'
     }
-  });
-};
+  })
+}
+
+// ==================== 寮傚父鎶ュ绠$悊 ====================
+
+/**
+ * @desc 鎶ュ寮傚父鎯呭喌
+ * @param {Object} data - 寮傚父鎶ュ鏁版嵁
+ * @returns {Promise}
+ */
+export function reportAbnormalSituation(data) {
+  return request({
+    url: '/equipment/inspection/abnormal/report',
+    method: 'post',
+    data: data
+  })
+}
+
+/**
+ * @desc 鏌ヨ寮傚父鎶ュ鍒楄〃
+ * @param {Object} query - 鏌ヨ鍙傛暟
+ * @returns {Promise}
+ */
+export function getAbnormalReportList(query) {
+  return request({
+    url: '/equipment/inspection/abnormal/list',
+    method: 'get',
+    params: query
+  })
+}
+
+/**
+ * @desc 鏌ヨ寮傚父鎶ュ璇︽儏
+ * @param {string|number} id - 鎶ュID
+ * @returns {Promise}
+ */
+export function getAbnormalReport(id) {
+  return request({
+    url: '/equipment/inspection/abnormal/' + id,
+    method: 'get'
+  })
+}
+
+/**
+ * @desc 澶勭悊寮傚父鎶ュ
+ * @param {string|number} id - 鎶ュID
+ * @param {Object} data - 澶勭悊鏁版嵁
+ * @returns {Promise}
+ */
+export function handleAbnormalReport(id, data) {
+  return request({
+    url: '/equipment/inspection/abnormal/' + id + '/handle',
+    method: 'post',
+    data: data
+  })
+}
+
+/**
+ * @desc 杞淳寮傚父鎶ュ
+ * @param {string|number} id - 鎶ュID
+ * @param {Object} data - 杞淳鏁版嵁
+ * @returns {Promise}
+ */
+export function transferAbnormalReport(id, data) {
+  return request({
+    url: '/equipment/inspection/abnormal/' + id + '/transfer',
+    method: 'post',
+    data: data
+  })
+}
+
+/**
+ * @desc 鍏抽棴寮傚父鎶ュ
+ * @param {string|number} id - 鎶ュID
+ * @param {Object} data - 鍏抽棴鏁版嵁
+ * @returns {Promise}
+ */
+export function closeAbnormalReport(id, data) {
+  return request({
+    url: '/equipment/inspection/abnormal/' + id + '/close',
+    method: 'post',
+    data: data
+  })
+}
+
+// ==================== 缁熻鍒嗘瀽 ====================
 
 /**
  * @desc 鑾峰彇宸℃缁熻鏁版嵁
  * @param {Object} params - 鏌ヨ鍙傛暟
- * @param {string} params.startDate - 寮�濮嬫棩鏈�
- * @param {string} params.endDate - 缁撴潫鏃ユ湡
- * @param {string} params.inspector - 宸℃鍛�
  * @returns {Promise}
  */
-export const getInspectionStats = (params) => {
+export function getInspectionStats(params) {
   return request({
-    url: "/device/inspection/stats",
-    method: "get",
-    params,
-  });
-};
+    url: '/equipment/inspection/stats',
+    method: 'get',
+    params: params
+  })
+}
 
 /**
- * @desc 鑾峰彇宸℃鍘嗗彶璁板綍
+ * @desc 鑾峰彇寮傚父缁熻鏁版嵁
  * @param {Object} params - 鏌ヨ鍙傛暟
- * @param {string|number} params.deviceId - 璁惧ID
- * @param {number} params.current - 褰撳墠椤�
- * @param {number} params.size - 椤甸潰澶у皬
  * @returns {Promise}
  */
-export const getInspectionHistory = (params) => {
+export function getAbnormalStats(params) {
   return request({
-    url: "/device/inspection/history",
-    method: "get",
-    params,
-  });
-};
+    url: '/equipment/inspection/abnormal/stats',
+    method: 'get',
+    params: params
+  })
+}
 
 /**
- * @desc 瀵煎嚭宸℃璁板綍
+ * @desc 瀵煎嚭宸℃鎶ュ憡
  * @param {Object} params - 瀵煎嚭鍙傛暟
- * @param {string} params.startDate - 寮�濮嬫棩鏈�
- * @param {string} params.endDate - 缁撴潫鏃ユ湡
- * @param {string} params.inspector - 宸℃鍛�
- * @param {Array} params.deviceIds - 璁惧ID鍒楄〃
  * @returns {Promise}
  */
-export const exportInspectionRecords = (params) => {
+export function exportInspectionReport(params) {
   return request({
-    url: "/device/inspection/export",
-    method: "get",
-    params,
+    url: '/equipment/inspection/export/report',
+    method: 'get',
+    params: params,
     responseType: 'blob'
-  });
-};
+  })
+}
 
 /**
- * @desc 鍒犻櫎宸℃璁板綍
- * @param {string|number} id - 宸℃璁板綍ID
+ * @desc 瀵煎嚭寮傚父鎶ュ璁板綍
+ * @param {Object} params - 瀵煎嚭鍙傛暟
  * @returns {Promise}
  */
-export const deleteInspectionRecord = (id) => {
+export function exportAbnormalRecords(params) {
   return request({
-    url: `/device/inspection/${id}`,
-    method: "delete",
-  });
-};
+    url: '/equipment/inspection/abnormal/export',
+    method: 'get',
+    params: params,
+    responseType: 'blob'
+  })
+}
 
-/**
- * @desc 鎵归噺鍒犻櫎宸℃璁板綍
- * @param {Array} ids - 宸℃璁板綍ID鍒楄〃
- * @returns {Promise}
- */
-export const batchDeleteInspectionRecords = (ids) => {
-  return request({
-    url: "/device/inspection/batch/delete",
-    method: "delete",
-    data: { ids },
-  });
-};
+// ==================== 璁惧浜岀淮鐮� ====================
 
 /**
  * @desc 鑾峰彇璁惧浜岀淮鐮�
  * @param {string|number} deviceId - 璁惧ID
  * @returns {Promise}
  */
-export const getDeviceQRCode = (deviceId) => {
+export function getDeviceQRCode(deviceId) {
   return request({
-    url: `/device/qrcode/${deviceId}`,
-    method: "get",
-  });
-};
+    url: `/equipment/device/${deviceId}/qrcode`,
+    method: 'get'
+  })
+}
 
 /**
  * @desc 楠岃瘉璁惧浜岀淮鐮�
  * @param {Object} data - 楠岃瘉鏁版嵁
- * @param {string} data.qrCode - 浜岀淮鐮佸唴瀹�
- * @param {string|number} data.deviceId - 璁惧ID
  * @returns {Promise}
  */
-export const verifyDeviceQRCode = (data) => {
+export function verifyDeviceQRCode(data) {
   return request({
-    url: "/device/qrcode/verify",
-    method: "post",
-    data,
-  });
-};
\ No newline at end of file
+    url: '/equipment/device/qrcode/verify',
+    method: 'post',
+    data: data
+  })
+}
+
+// ==================== 妯℃澘绠$悊 ====================
+
+/**
+ * @desc 鑾峰彇宸℃妯℃澘鍒楄〃
+ * @param {Object} query - 鏌ヨ鍙傛暟
+ * @returns {Promise}
+ */
+export function getInspectionTemplateList(query) {
+  return request({
+    url: '/equipment/inspection/template/list',
+    method: 'get',
+    params: query
+  })
+}
+
+/**
+ * @desc 鑾峰彇宸℃妯℃澘璇︽儏
+ * @param {string|number} id - 妯℃澘ID
+ * @returns {Promise}
+ */
+export function getInspectionTemplate(id) {
+  return request({
+    url: '/equipment/inspection/template/' + id,
+    method: 'get'
+  })
+}
\ No newline at end of file
diff --git a/src/api/inspectionManagement/index.js b/src/api/inspectionManagement/index.js
new file mode 100644
index 0000000..d0c444a
--- /dev/null
+++ b/src/api/inspectionManagement/index.js
@@ -0,0 +1,61 @@
+// 宸℃绠$悊
+import request from '@/utils/request'
+
+// 宸℃浠诲姟琛ㄨ〃鏌ヨ
+export function inspectionTaskList(query) {
+    return request({
+        url: '/inspectionTask/list',
+        method: 'get',
+        params: query
+    })
+}
+// 宸℃浠诲姟琛ㄦ柊澧炰慨鏀�
+export function addOrEditInspectionTask(query) {
+    return request({
+        url: '/inspectionTask/addOrEditInspectionTask',
+        method: 'post',
+        data: query
+    })
+}
+// 宸℃浠诲姟琛ㄥ垹闄�
+export function delInspectionTask(query) {
+    return request({
+        url: '/inspectionTask/delInspectionTask',
+        method: 'delete',
+        data: query
+    })
+}
+// 瀹氭椂宸℃浠诲姟琛ㄥ垹闄�
+export function delTimingTask(query) {
+    return request({
+        url: '/timingTask/delTimingTask',
+        method: 'delete',
+        data: query
+    })
+}
+
+// /inspectionTask/addOrEditInspectionTask
+// 宸℃涓婁紶
+export function uploadInspectionTask(query) {
+    return request({
+        url: '/inspectionTask/addOrEditInspectionTask',
+        method: 'post',
+        data: query
+    })
+}
+// 瀹氭椂宸℃浠诲姟琛ㄦ煡璇�
+export function timingTaskList(query) {
+    return request({
+        url: '/timingTask/list',
+        method: 'get',
+        params: query
+    })
+}
+// 瀹氭椂宸℃浠诲姟琛ㄦ柊澧炰慨鏀�
+export function addOrEditTimingTask(query) {
+    return request({
+        url: '/timingTask/addOrEditTimingTask',
+        method: 'post',
+        data: query
+    })
+}
\ No newline at end of file
diff --git a/src/api/inspectionUpload/index.js b/src/api/inspectionUpload/index.js
new file mode 100644
index 0000000..0d954e2
--- /dev/null
+++ b/src/api/inspectionUpload/index.js
@@ -0,0 +1,43 @@
+// 宸℃涓婁紶
+import request from '@/utils/request'
+
+// 浜岀淮鐮佺鐞嗚〃鏌ヨ
+export function qrCodeList(query) {
+    return request({
+        url: '/qrCode/list',
+        method: 'get',
+        params: query
+    })
+}
+// 浜岀淮鐮佹壂鐮佽褰曡〃鏌ヨ
+export function qrCodeScanRecordList(query) {
+    return request({
+        url: '/qrCodeScanRecord/list',
+        method: 'get',
+        params: query
+    })
+}
+// 浜岀淮鐮佺鐞嗚〃鏂板淇敼
+export function addOrEditQrCode(query) {
+    return request({
+        url: '/qrCode/addOrEditQrCode',
+        method: 'post',
+        data: query
+    })
+}
+// 浜岀淮鐮佹壂鐮佽褰曡〃鏂板淇敼
+export function addOrEditQrCodeRecord(query) {
+    return request({
+        url: '/qrCodeScanRecord/addOrEditQrCodeRecord',
+        method: 'post',
+        data: query
+    })
+}
+// 浜岀淮鐮佹壂鐮佽褰曡〃鏂板淇敼
+export function delQrCode(query) {
+    return request({
+        url: '/qrCode/delQrCode',
+        method: 'delete',
+        data: query
+    })
+}
\ No newline at end of file
diff --git a/src/pages.json b/src/pages.json
index 8fd1a91..3937f03 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -385,6 +385,13 @@
         "navigationBarTitleText": "缁撴灉楠岃瘉",
         "navigationStyle": "custom"
       }
+    },
+    {
+      "path": "pages/inspectionUpload/index",
+      "style": {
+        "navigationBarTitleText": "宸℃涓婁紶",
+        "navigationStyle": "custom"
+      }
     }
   ],
   "subPackages": [
diff --git a/src/pages/equipmentManagement/inspection/index.vue b/src/pages/equipmentManagement/inspection/index.vue
index d647dea..bb949fa 100644
--- a/src/pages/equipmentManagement/inspection/index.vue
+++ b/src/pages/equipmentManagement/inspection/index.vue
@@ -96,7 +96,7 @@
 import { ref, computed, onMounted } from 'vue'
 import { onShow } from '@dcloudio/uni-app'
 import PageHeader from '@/components/PageHeader.vue'
-import { getInspectionList } from '@/api/equipmentManagement/inspection'
+// import { getInspectionList } from '@/api/inspectionUpload/index'
 import dayjs from 'dayjs'
 
 // 閫変腑鐨勬棩鏈�
diff --git a/src/pages/index.vue b/src/pages/index.vue
index ceb1000..2062b64 100644
--- a/src/pages/index.vue
+++ b/src/pages/index.vue
@@ -269,7 +269,7 @@
 	},
 	{
 		icon: '/static/images/icon/shebeixunjian@2x.png',
-		label: '璁惧宸℃',
+		label: '宸℃涓婁紶',
 	},
 	{
 		icon: 'flash',
@@ -377,9 +377,9 @@
 				url: '/pages/equipmentManagement/upkeep/index'
 			});
 			break;
-		case '璁惧宸℃':
+		case '宸℃涓婁紶':
 			uni.navigateTo({
-				url: '/pages/equipmentManagement/inspection/index'
+				url: '/pages/inspectionUpload/index'
 			});
 			break;
 		case '鏅鸿兘娲惧崟':
diff --git a/src/pages/inspectionUpload/components/formDia.vue b/src/pages/inspectionUpload/components/formDia.vue
new file mode 100644
index 0000000..41837cb
--- /dev/null
+++ b/src/pages/inspectionUpload/components/formDia.vue
@@ -0,0 +1,256 @@
+<template>
+  <u-popup 
+    v-model="dialogVisitable" 
+    mode="center" 
+    :round="10"
+    :closeable="true"
+    @close="cancel"
+  >
+    <view class="popup-content">
+      <view class="popup-header">
+        <text class="popup-title">涓婁紶</text>
+      </view>
+      
+      <view class="upload-container">
+        <view class="form-container">
+          <view class="title">鐢熶骇鍓�</view>
+          <u-upload
+            :fileList="beforeModelValue"
+            @afterRead="afterRead"
+            @delete="deleteFile"
+            name="before"
+            multiple
+            :maxCount="10"
+            :maxSize="1024 * 1024"
+            accept="video/*"
+            :previewFullImage="true"
+          ></u-upload>
+        </view>
+        
+        <view class="form-container">
+          <view class="title">鐢熶骇鍚�</view>
+          <u-upload
+            :fileList="afterModelValue"
+            @afterRead="afterRead"
+            @delete="deleteFile"
+            name="after"
+            multiple
+            :maxCount="10"
+            :maxSize="1024 * 1024"
+            accept="video/*"
+            :previewFullImage="true"
+          ></u-upload>
+        </view>
+        
+        <view class="form-container">
+          <view class="title">鐢熶骇闂</view>
+          <u-upload
+            :fileList="issueModelValue"
+            @afterRead="afterRead"
+            @delete="deleteFile"
+            name="issue"
+            multiple
+            :maxCount="10"
+            :maxSize="1024 * 1024"
+            accept="video/*"
+            :previewFullImage="true"
+          ></u-upload>
+        </view>
+      </view>
+      
+      <view class="popup-footer">
+        <u-button @click="cancel" :customStyle="{ marginRight: '10px' }">鍙栨秷</u-button>
+        <u-button type="primary" @click="submitForm">淇濆瓨</u-button>
+      </view>
+    </view>
+  </u-popup>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { submitInspectionRecord } from '@/api/equipmentManagement/inspection.js'
+
+const emit = defineEmits(['closeDia'])
+
+const dialogVisitable = ref(false)
+const beforeModelValue = ref([])
+const afterModelValue = ref([])
+const issueModelValue = ref([])
+const infoData = ref(null)
+
+// 鏂囦欢涓婁紶澶勭悊
+const afterRead = (event) => {
+  const { name, file } = event
+  
+  // 涓婁紶鏂囦欢鍒版湇鍔″櫒
+  uni.uploadFile({
+    url: '/api/upload', // 鏇挎崲涓哄疄闄呯殑涓婁紶鎺ュ彛
+    filePath: file.url,
+    name: 'file',
+    success: (res) => {
+      const data = JSON.parse(res.data)
+      if (data.code === 200) {
+        const fileItem = {
+          url: data.data.url,
+          name: file.name,
+          status: 'success'
+        }
+        
+        // 鏍规嵁name娣诲姞鍒板搴旂殑鏁扮粍
+        if (name === 'before') {
+          beforeModelValue.value.push(fileItem)
+        } else if (name === 'after') {
+          afterModelValue.value.push(fileItem)
+        } else if (name === 'issue') {
+          issueModelValue.value.push(fileItem)
+        }
+        
+        uni.showToast({
+          title: '涓婁紶鎴愬姛',
+          icon: 'success'
+        })
+      } else {
+        uni.showToast({
+          title: '涓婁紶澶辫触',
+          icon: 'error'
+        })
+      }
+    },
+    fail: () => {
+      uni.showToast({
+        title: '涓婁紶澶辫触',
+        icon: 'error'
+      })
+    }
+  })
+}
+
+// 鍒犻櫎鏂囦欢
+const deleteFile = (event) => {
+  const { name, index } = event
+  
+  if (name === 'before') {
+    beforeModelValue.value.splice(index, 1)
+  } else if (name === 'after') {
+    afterModelValue.value.splice(index, 1)
+  } else if (name === 'issue') {
+    issueModelValue.value.splice(index, 1)
+  }
+}
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = async () => {
+  try {
+    let arr = []
+    if (beforeModelValue.value.length > 0) {
+      arr.push(...beforeModelValue.value.map(item => ({ ...item, statusType: 0 })))
+    }
+    if (afterModelValue.value.length > 0) {
+      arr.push(...afterModelValue.value.map(item => ({ ...item, statusType: 1 })))
+    }
+    if (issueModelValue.value.length > 0) {
+      arr.push(...issueModelValue.value.map(item => ({ ...item, statusType: 2 })))
+    }
+    
+    // 鎻愪氦鏁版嵁
+    infoData.value.storageBlobDTO = arr
+    await submitInspectionRecord({ ...infoData.value })
+    
+    uni.showToast({
+      title: '鎻愪氦鎴愬姛',
+      icon: 'success'
+    })
+    
+    cancel()
+  } catch (error) {
+    console.error('鎻愪氦澶辫触:', error)
+    uni.showToast({
+      title: '鎻愪氦澶辫触',
+      icon: 'error'
+    })
+  }
+}
+
+// 鎵撳紑寮规
+const openDialog = async (row) => {
+  infoData.value = row
+  dialogVisitable.value = true
+  
+  // 娓呯┖涔嬪墠鐨勬暟鎹�
+  beforeModelValue.value = []
+  afterModelValue.value = []
+  issueModelValue.value = []
+}
+
+// 鍏抽棴寮规
+const cancel = () => {
+  dialogVisitable.value = false
+  emit('closeDia')
+}
+
+defineExpose({ openDialog })
+</script>
+
+<style scoped lang="scss">
+.popup-content {
+  width: 90vw;
+  max-width: 400px;
+  background-color: #fff;
+  border-radius: 10px;
+  overflow: hidden;
+}
+
+.popup-header {
+  padding: 20px 20px 10px;
+  text-align: center;
+  border-bottom: 1px solid #f0f0f0;
+}
+
+.popup-title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #333;
+}
+
+.upload-container {
+  padding: 20px;
+  max-height: 60vh;
+  overflow-y: auto;
+}
+
+.form-container {
+  margin-bottom: 20px;
+  
+  &:last-child {
+    margin-bottom: 0;
+  }
+}
+
+.title {
+  font-size: 14px;
+  color: #1890ff;
+  line-height: 20px;
+  font-weight: 600;
+  padding-left: 10px;
+  position: relative;
+  margin: 6px 0 10px;
+  
+  &::before {
+    content: "";
+    position: absolute;
+    left: 0;
+    top: 3px;
+    width: 4px;
+    height: 14px;
+    background-color: #1890ff;
+  }
+}
+
+.popup-footer {
+  display: flex;
+  justify-content: center;
+  padding: 15px 20px;
+  border-top: 1px solid #f0f0f0;
+  background-color: #fafafa;
+}
+</style>
diff --git a/src/pages/inspectionUpload/components/qrCodeFormDia.vue b/src/pages/inspectionUpload/components/qrCodeFormDia.vue
new file mode 100644
index 0000000..07a94cd
--- /dev/null
+++ b/src/pages/inspectionUpload/components/qrCodeFormDia.vue
@@ -0,0 +1,254 @@
+<template>
+  <u-popup 
+    v-model="dialogVisitable" 
+    mode="center" 
+    :round="10"
+    :closeable="true"
+    @close="cancel"
+  >
+    <view class="popup-content">
+      <view class="popup-header">
+        <text class="popup-title">宸℃</text>
+      </view>
+      
+      <view class="form-container">
+        <u-form :model="form" ref="formRef" :rules="rules">
+          <u-form-item label="璁惧鍚嶇О" prop="deviceName" labelWidth="80">
+            <u-input 
+              v-model="form.deviceName" 
+              placeholder="璇疯緭鍏ヨ澶囧悕绉�" 
+              :maxlength="30" 
+              :disabled="true"
+            />
+          </u-form-item>
+          
+          <u-form-item label="鍦扮偣" prop="location" labelWidth="80">
+            <u-input 
+              v-model="form.location" 
+              placeholder="璇疯緭鍏ュ湴鐐�" 
+              :maxlength="30" 
+              :disabled="true"
+            />
+          </u-form-item>
+          
+          <u-form-item label="闄勪欢" prop="storageBlobDTO" labelWidth="80">
+            <u-upload
+              :fileList="form.storageBlobDTO"
+              @afterRead="afterRead"
+              @delete="deleteFile"
+              name="files"
+              multiple
+              :maxCount="10"
+              :maxSize="1024 * 1024"
+              accept="video/*"
+              :previewFullImage="true"
+            ></u-upload>
+          </u-form-item>
+          
+          <u-form-item label="宸℃浜�" prop="scannerName" labelWidth="80">
+            <u-input 
+              v-model="form.scannerName" 
+              :disabled="true" 
+              placeholder="璇疯緭鍏�" 
+            />
+          </u-form-item>
+          
+          <u-form-item label="宸℃鏃堕棿" prop="scanTime" labelWidth="80">
+            <u-input 
+              v-model="form.scanTime" 
+              :disabled="true" 
+              placeholder="璇疯緭鍏�" 
+            />
+          </u-form-item>
+        </u-form>
+      </view>
+      
+      <view class="popup-footer">
+        <u-button @click="cancel" :customStyle="{ marginRight: '10px' }">鍙栨秷</u-button>
+        <u-button type="primary" @click="submitForm">淇濆瓨</u-button>
+      </view>
+    </view>
+  </u-popup>
+</template>
+
+<script setup>
+import { reactive, ref, onMounted } from 'vue'
+import { addOrEditQrCodeRecord } from '@/api/inspectionUpload/index.js'
+import useUserStore from '@/store/modules/user.ts'
+
+const emit = defineEmits(['closeDia'])
+
+const dialogVisitable = ref(false)
+const formRef = ref(null)
+const userStore = useUserStore()
+const userInfo = ref({})
+
+// 鑾峰彇褰撳墠鏃堕棿
+function getCurrentDateTime() {
+  const now = new Date()
+  const year = now.getFullYear()
+  const month = String(now.getMonth() + 1).padStart(2, '0')
+  const day = String(now.getDate()).padStart(2, '0')
+  const hours = String(now.getHours()).padStart(2, '0')
+  const minutes = String(now.getMinutes()).padStart(2, '0')
+  const seconds = String(now.getSeconds()).padStart(2, '0')
+  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
+}
+
+// 琛ㄥ崟鏁版嵁
+const form = reactive({
+  deviceName: '',
+  location: '',
+  scannerName: '',
+  scannerId: '',
+  scanTime: '',
+  storageBlobDTO: [],
+  qrCode: {
+    id: ''
+  }
+})
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const rules = reactive({
+  deviceName: [{ required: true, message: '璇疯緭鍏ヨ澶囧悕绉�', trigger: 'blur' }],
+  location: [{ required: true, message: '璇疯緭鍏ュ湴鐐�', trigger: 'blur' }]
+})
+
+// 鑾峰彇鐢ㄦ埛淇℃伅
+onMounted(async () => {
+  try {
+    const res = await userStore.getInfo()
+    userInfo.value = res.user
+    form.scannerName = userInfo.value.nickName
+    form.scannerId = userInfo.value.userId
+    form.scanTime = getCurrentDateTime()
+  } catch (error) {
+    console.error('鑾峰彇鐢ㄦ埛淇℃伅澶辫触:', error)
+  }
+})
+
+// 鏂囦欢涓婁紶澶勭悊
+const afterRead = (event) => {
+  const { file } = event
+  
+  // 涓婁紶鏂囦欢鍒版湇鍔″櫒
+  uni.uploadFile({
+    url: '/api/upload', // 鏇挎崲涓哄疄闄呯殑涓婁紶鎺ュ彛
+    filePath: file.url,
+    name: 'file',
+    success: (res) => {
+      const data = JSON.parse(res.data)
+      if (data.code === 200) {
+        const fileItem = {
+          url: data.data.url,
+          name: file.name,
+          status: 'success'
+        }
+        
+        form.storageBlobDTO.push(fileItem)
+        
+        uni.showToast({
+          title: '涓婁紶鎴愬姛',
+          icon: 'success'
+        })
+      } else {
+        uni.showToast({
+          title: '涓婁紶澶辫触',
+          icon: 'error'
+        })
+      }
+    },
+    fail: () => {
+      uni.showToast({
+        title: '涓婁紶澶辫触',
+        icon: 'error'
+      })
+    }
+  })
+}
+
+// 鍒犻櫎鏂囦欢
+const deleteFile = (event) => {
+  const { index } = event
+  form.storageBlobDTO.splice(index, 1)
+}
+
+// 鎵撳紑寮规
+const openDialog = async (row) => {
+  dialogVisitable.value = true
+  form.deviceName = row.deviceName || ''
+  form.location = row.location || ''
+  form.qrCodeId = row.qrCodeId || row.id || ''
+  form.storageBlobDTO = []
+}
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = async () => {
+  try {
+    // 琛ㄥ崟楠岃瘉
+    const valid = await formRef.value.validate()
+    if (!valid) return
+    
+    form.qrCode.id = form.qrCodeId
+    
+    await addOrEditQrCodeRecord({ ...form })
+    
+    uni.showToast({
+      title: '鎻愪氦鎴愬姛',
+      icon: 'success'
+    })
+    
+    cancel()
+  } catch (error) {
+    console.error('鎻愪氦澶辫触:', error)
+    uni.showToast({
+      title: '鎻愪氦澶辫触',
+      icon: 'error'
+    })
+  }
+}
+
+// 鍏抽棴寮规
+const cancel = () => {
+  dialogVisitable.value = false
+  emit('closeDia')
+}
+
+defineExpose({ openDialog })
+</script>
+
+<style scoped lang="scss">
+.popup-content {
+  width: 90vw;
+  max-width: 400px;
+  background-color: #fff;
+  border-radius: 10px;
+  overflow: hidden;
+}
+
+.popup-header {
+  padding: 20px 20px 10px;
+  text-align: center;
+  border-bottom: 1px solid #f0f0f0;
+}
+
+.popup-title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #333;
+}
+
+.form-container {
+  padding: 20px;
+  max-height: 60vh;
+  overflow-y: auto;
+}
+
+.popup-footer {
+  display: flex;
+  justify-content: center;
+  padding: 15px 20px;
+  border-top: 1px solid #f0f0f0;
+  background-color: #fafafa;
+}
+</style>
diff --git a/src/pages/inspectionUpload/index.vue b/src/pages/inspectionUpload/index.vue
new file mode 100644
index 0000000..5c57b4e
--- /dev/null
+++ b/src/pages/inspectionUpload/index.vue
@@ -0,0 +1,597 @@
+<template>
+  <view class="inspection-upload-page">
+    <!-- 椤甸潰澶撮儴 -->
+    <PageHeader title="宸℃涓婁紶" />
+    
+    <!-- 鏍囩椤� -->
+    <view class="tabs-container">
+      <view class="custom-tabs">
+        <view 
+          v-for="(tab, index) in tabs" 
+          :key="index"
+          class="tab-item"
+          :class="{ 'tab-active': currentTabIndex === index }"
+          @click="handleTabChange(index)"
+        >
+          {{ tab.name }}
+        </view>
+        <view class="tab-line" :style="{ left: currentTabIndex * 50 + '%' }"></view>
+      </view>
+    </view>
+    
+    <!-- 鎵爜妯″潡 -->
+    <view v-if="activeTab === 'qrCode'" class="scan-section">
+      <view class="scan-controls">
+        <u-button 
+          :type="isScanning ? 'error' : 'primary'"
+          :loading="scanLoading"
+          @click="toggleScan"
+        >
+          {{ scanButtonText }}
+        </u-button>
+      </view>
+      
+      <!-- 鎵爜鍖哄煙 -->
+      <view v-show="isScanning" class="qr-scan-container">
+        <camera 
+          class="qr-camera"
+          device-position="back"
+          flash="off"
+          @scancode="handleScanCode"
+          @error="handleCameraError"
+        ></camera>
+        <view class="scan-overlay">
+          <view class="scan-frame"></view>
+          <view class="scan-tip">璇峰皢浜岀淮鐮佹斁鍏ユ鍐�</view>
+        </view>
+      </view>
+      
+      <!-- 鐘舵�佹彁绀� -->
+      <view class="status-info">
+        <u-alert 
+          v-if="cameraError"
+          :title="cameraError"
+          type="error"
+          :showIcon="true"
+          :closable="true"
+          @close="cameraError = ''"
+        ></u-alert>
+        <view v-if="isScanning" class="scanning-text">
+          <u-loading-icon mode="circle" color="#1890ff" size="20"></u-loading-icon>
+          <text class="scanning-label">姝e湪鎵弿浜岀淮鐮�...</text>
+        </view>
+      </view>
+    </view>
+    
+    <!-- 鏁版嵁鍒楄〃 -->
+    <view class="table-section">
+      <!-- 鐢熶骇宸℃鍒楄〃 -->
+      <view v-if="activeTab === 'task'" class="task-list">
+        <view 
+          v-for="(item, index) in tableData" 
+          :key="index"
+          class="task-item"
+          @click="handleAdd(item)"
+        >
+          <view class="task-header">
+            <view class="task-info">
+              <text class="task-name">{{ item.taskName }}</text>
+              <text class="task-location">{{ item.inspectionLocation }}</text>
+            </view>
+            <view class="task-actions">
+              <u-button 
+                type="primary" 
+                size="small"
+                @click.stop="handleAdd(item)"
+                :customStyle="{
+                  borderRadius: '15px',
+                  height: '30px',
+                  fontSize: '12px'
+                }"
+              >
+                涓婁紶
+              </u-button>
+            </view>
+          </view>
+          <view class="task-details">
+            <view class="detail-item">
+              <text class="detail-label">澶囨敞锛�</text>
+              <text class="detail-value">{{ item.remarks || '鏃�' }}</text>
+            </view>
+            <view class="detail-item">
+              <text class="detail-label">鎵ц浜猴細</text>
+              <text class="detail-value">{{ item.inspector }}</text>
+            </view>
+          </view>
+        </view>
+      </view>
+      
+      <!-- 鐜板満宸℃鍒楄〃 -->
+      <view v-if="activeTab === 'qrCode'" class="qr-list">
+        <view 
+          v-for="(item, index) in tableData" 
+          :key="index"
+          class="qr-item"
+          @click="viewFile(item)"
+        >
+          <view class="qr-header">
+            <view class="qr-info">
+              <text class="device-name">{{ item.qrCode?.deviceName }}</text>
+              <text class="device-location">{{ item.qrCode?.location }}</text>
+            </view>
+            <view class="qr-actions">
+              <u-button 
+                type="primary" 
+                size="small"
+                @click.stop="viewFile(item)"
+                :customStyle="{
+                  borderRadius: '15px',
+                  height: '30px',
+                  fontSize: '12px'
+                }"
+              >
+                鏌ョ湅闄勪欢
+              </u-button>
+            </view>
+          </view>
+          <view class="qr-details">
+            <view class="detail-item">
+              <text class="detail-label">宸℃浜猴細</text>
+              <text class="detail-value">{{ item.scanner }}</text>
+            </view>
+            <view class="detail-item">
+              <text class="detail-label">宸℃鏃堕棿锛�</text>
+              <text class="detail-value">{{ item.scanTime }}</text>
+            </view>
+          </view>
+        </view>
+      </view>
+      
+      <!-- 绌虹姸鎬� -->
+      <view v-if="tableData.length === 0 && !tableLoading" class="empty-state">
+        <u-empty 
+          mode="data" 
+          text="鏆傛棤鏁版嵁"
+          :iconSize="80"
+        ></u-empty>
+      </view>
+      
+      <!-- 鍔犺浇鐘舵�� -->
+      <view v-if="tableLoading" class="loading-state">
+        <u-loading-icon mode="circle" color="#1890ff" size="40"></u-loading-icon>
+        <text class="loading-text">鍔犺浇涓�...</text>
+      </view>
+    </view>
+    
+    <!-- 鍒嗛〉 -->
+    <view v-if="total > 0" class="pagination-container">
+      <u-pagination 
+        :total="total"
+        :current="pageNum"
+        :pageSize="pageSize"
+        @change="handlePageChange"
+        :showTotal="true"
+        :showSizer="false"
+        :showJumper="false"
+      ></u-pagination>
+    </view>
+    
+    <!-- 寮圭獥缁勪欢 -->
+    <form-dia ref="formDia" @closeDia="handleQuery"></form-dia>
+    <qr-code-form-dia ref="qrCodeFormDia" @closeDia="handleQuery"></qr-code-form-dia>
+  </view>
+</template>
+
+<script setup>
+import { onMounted, ref, reactive, computed, nextTick } from 'vue'
+import { onShow } from '@dcloudio/uni-app'
+import PageHeader from '@/components/PageHeader.vue'
+import FormDia from './components/formDia.vue'
+import QrCodeFormDia from './components/qrCodeFormDia.vue'
+import { qrCodeScanRecordList } from '@/api/inspectionUpload/index.js'
+import { getInspectionTaskList } from '@/api/equipmentManagement/inspection.js'
+import {inspectionTaskList} from "@/api/inspectionManagement";
+// import ViewQrCodeFiles from '@/pages/inspectionManagement/components/viewQrCodeFiles.vue'
+
+// 缁勪欢寮曠敤
+const formDia = ref()
+const qrCodeFormDia = ref()
+
+// 褰撳墠鏍囩
+const activeTab = ref('task')
+
+const tabName = ref('task')
+const currentTabIndex = ref(0)
+
+// 鏍囩椤垫暟鎹�
+const tabs = reactive([
+  { name: '鐢熶骇宸℃' },
+  { name: '鐜板満宸℃' }
+])
+
+// 琛ㄦ牸鏁版嵁
+const tableData = ref([])
+const tableLoading = ref(false)
+const total = ref(0)
+const pageNum = ref(1)
+const pageSize = ref(10)
+
+// 鎵爜鐩稿叧鐘舵��
+const isScanning = ref(false)
+const scanLoading = ref(false)
+const cameraError = ref('')
+
+// 璁$畻灞炴��
+const scanButtonText = computed(() => {
+  if (scanLoading.value) return '姝e湪鍒濆鍖�...'
+  return isScanning.value ? '鍋滄鎵爜' : '寮�濮嬫壂鐮�'
+})
+
+// 鐢熷懡鍛ㄦ湡
+onMounted(() => {
+  // 寤惰繜鍒濆鍖栵紝纭繚DOM宸叉覆鏌�
+  nextTick(() => {
+    handleTabClick({ props: { name: 'task' } })
+  })
+})
+
+onShow(() => {
+  // 椤甸潰鏄剧ず鏃跺埛鏂版暟鎹�
+  getList()
+})
+
+// 鏍囩椤靛垏鎹�
+const handleTabChange = (index) => {
+  currentTabIndex.value = index
+  const tabNames = ['task', 'qrCode']
+  activeTab.value = tabNames[index]
+  tabName.value = tabNames[index]
+  tableData.value = []
+  pageNum.value = 1
+  getList()
+}
+
+// 鏍囩椤电偣鍑伙紙鍏煎鏃ф柟娉曪級
+const handleTabClick = (tab) => {
+  tabName.value = tab.props.name
+  activeTab.value = tab.props.name
+  tableData.value = []
+  getList()
+}
+
+// 鏌ヨ鏁版嵁
+const handleQuery = () => {
+  pageNum.value = 1
+  pageSize.value = 10
+  getList()
+}
+
+// 鑾峰彇鍒楄〃鏁版嵁
+const getList = () => {
+  tableLoading.value = true
+  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 handlePageChange = (page) => {
+  pageNum.value = page
+  getList()
+}
+
+// 涓婁紶
+const handleAdd = (row) => {
+  nextTick(() => {
+    formDia.value?.openDialog(row)
+  })
+}
+
+// 鏌ョ湅闄勪欢
+const viewFile = (row) => {
+  console.log('鏌ョ湅闄勪欢:', row)
+  uni.showToast({
+    title: '鏌ョ湅闄勪欢鍔熻兘寮�鍙戜腑',
+    icon: 'none'
+  })
+}
+
+// 鎵爜鐩稿叧鏂规硶
+const toggleScan = async () => {
+  if (isScanning.value) {
+    await stopScan()
+  } else {
+    await startScan()
+  }
+}
+
+const startScan = async () => {
+  try {
+    // 浣跨敤uniapp鐨勬壂鐮丄PI
+    uni.scanCode({
+      success: (res) => {
+        handleScanSuccess(res)
+      },
+      fail: (err) => {
+        console.error('鎵爜澶辫触:', err)
+        uni.showToast({
+          title: '鎵爜澶辫触',
+          icon: 'error'
+        })
+      }
+    })
+  } catch (e) {
+    console.error('鍚姩鎵爜澶辫触:', e)
+    uni.showToast({
+      title: '鍚姩鎵爜澶辫触',
+      icon: 'error'
+    })
+  }
+}
+
+const stopScan = async () => {
+  isScanning.value = false
+}
+
+// 鎵爜鎴愬姛澶勭悊
+const handleScanSuccess = async (result) => {
+  try {
+    uni.showToast({
+      title: '璇嗗埆鎴愬姛',
+      icon: 'success'
+    })
+    
+    // 瑙f瀽浜岀淮鐮佹暟鎹�
+    let qrData
+    try {
+      qrData = JSON.parse(result.result)
+    } catch (e) {
+      qrData = { deviceName: result.result, location: '' }
+    }
+    
+    callBackendAPI(qrData)
+  } catch (error) {
+    uni.showToast({
+      title: error.message || '鏁版嵁瑙f瀽澶辫触',
+      icon: 'error'
+    })
+  }
+}
+
+const callBackendAPI = (result) => {
+  nextTick(() => {
+    qrCodeFormDia.value?.openDialog(result)
+  })
+}
+
+// 鎵爜澶勭悊
+const handleScanCode = (result) => {
+  console.log('鎵爜缁撴灉:', result)
+  handleScanSuccess(result)
+}
+
+// 鎽勫儚澶撮敊璇鐞�
+const handleCameraError = (error) => {
+  console.error('鎽勫儚澶撮敊璇�:', error)
+  cameraError.value = '鎽勫儚澶磋闂け璐ワ紝璇锋鏌ユ潈闄愯缃�'
+}
+</script>
+
+<style scoped lang="scss">
+.inspection-upload-page {
+  min-height: 100vh;
+  background-color: #f5f5f5;
+}
+
+.tabs-container {
+  background-color: #fff;
+  margin: 0;
+  border-bottom: 1px solid #e8e8e8;
+}
+
+.custom-tabs {
+  display: flex;
+  position: relative;
+  background-color: #fff;
+  width: 100%;
+}
+
+.tab-item {
+  flex: 1;
+  text-align: center;
+  padding: 20px 0;
+  font-size: 16px;
+  font-weight: 500;
+  color: #606266;
+  transition: all 0.3s ease;
+  cursor: pointer;
+  position: relative;
+  z-index: 2;
+}
+
+.tab-item.tab-active {
+  color: #1890ff;
+  font-weight: 600;
+}
+
+.tab-line {
+  position: absolute;
+  bottom: 0;
+  width: 50%;
+  height: 3px;
+  background-color: #1890ff;
+  transition: left 0.3s ease;
+}
+
+.scan-section {
+  background-color: #fff;
+	padding: 10px;
+}
+
+.scan-controls {
+  display: flex;
+  justify-content: center;
+}
+
+.qr-scan-container {
+  position: relative;
+  width: 100%;
+  max-width: 500px;
+  margin: 0 auto;
+  background: #000;
+  border-radius: 8px;
+  overflow: hidden;
+}
+
+.qr-camera {
+  width: 100%;
+  height: 300px;
+}
+
+.scan-overlay {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  width: 70%;
+  height: 70%;
+  border: 3px solid #1890ff;
+  border-radius: 8px;
+  box-shadow: 0 0 20px rgba(24, 144, 255, 0.3);
+  animation: pulse 2s infinite;
+}
+
+.scan-frame {
+  width: 100%;
+  height: 100%;
+  border: 2px solid #fff;
+  border-radius: 4px;
+}
+
+.scan-tip {
+  position: absolute;
+  bottom: -30px;
+  left: 50%;
+  transform: translateX(-50%);
+  color: #fff;
+  font-size: 14px;
+  text-align: center;
+}
+
+@keyframes pulse {
+  0% { opacity: 0.8; }
+  50% { opacity: 0.4; }
+  100% { opacity: 0.8; }
+}
+
+.status-info {
+  margin-top: 16px;
+  text-align: center;
+}
+
+.scanning-text {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: #1890ff;
+  margin-top: 8px;
+}
+
+.scanning-label {
+  margin-left: 8px;
+  font-size: 14px;
+}
+
+.table-section {
+  padding: 0 15px;
+}
+
+.task-list, .qr-list {
+  .task-item, .qr-item {
+    background-color: #fff;
+    border-radius: 8px;
+    margin-bottom: 10px;
+    padding: 15px;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+  }
+}
+
+.task-header, .qr-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: flex-start;
+  margin-bottom: 10px;
+}
+
+.task-info, .qr-info {
+  flex: 1;
+}
+
+.task-name, .device-name {
+  font-size: 16px;
+  font-weight: 600;
+  color: #333;
+  margin-bottom: 4px;
+}
+
+.task-location, .device-location {
+  font-size: 14px;
+  color: #666;
+}
+
+.task-actions, .qr-actions {
+  margin-left: 10px;
+}
+
+.task-details, .qr-details {
+  .detail-item {
+    display: flex;
+    margin-bottom: 6px;
+    
+    .detail-label {
+      font-size: 14px;
+      color: #666;
+      min-width: 60px;
+    }
+    
+    .detail-value {
+      font-size: 14px;
+      color: #333;
+      flex: 1;
+    }
+  }
+}
+
+.empty-state, .loading-state {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  padding: 40px 20px;
+  background-color: #fff;
+  border-radius: 8px;
+  margin: 10px 15px;
+}
+
+.loading-text {
+  margin-top: 10px;
+  font-size: 14px;
+  color: #666;
+}
+
+.pagination-container {
+  padding: 20px 15px;
+  background-color: #fff;
+  margin-top: 10px;
+}
+</style>
\ No newline at end of file

--
Gitblit v1.9.3