| src/api/equipmentManagement/inspection.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/api/inspectionManagement/index.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/api/inspectionUpload/index.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/equipmentManagement/inspection/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/inspectionUpload/components/formDia.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/inspectionUpload/components/qrCodeFormDia.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/pages/inspectionUpload/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
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:æ£å¸¸ 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, }); }; 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' }) } 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 }) } 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 }) } src/pages.json
@@ -385,6 +385,13 @@ "navigationBarTitleText": "ç»æéªè¯", "navigationStyle": "custom" } }, { "path": "pages/inspectionUpload/index", "style": { "navigationBarTitleText": "å·¡æ£ä¸ä¼ ", "navigationStyle": "custom" } } ], "subPackages": [ 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' // éä¸çæ¥æ 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 'æºè½æ´¾å': 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> 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> 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">æ£å¨æ«æäºç»´ç ...</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 'æ£å¨åå§å...' 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çæ«ç API 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' }) // è§£æäºç»´ç æ°æ® let qrData try { qrData = JSON.parse(result.result) } catch (e) { qrData = { deviceName: result.result, location: '' } } callBackendAPI(qrData) } catch (error) { uni.showToast({ title: error.message || 'æ°æ®è§£æå¤±è´¥', 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>