| | |
| | | <template> |
| | | <u-popup |
| | | v-model="dialogVisitable" |
| | | :show="dialogVisitable" |
| | | mode="center" |
| | | :round="10" |
| | | :closeable="true" |
| | |
| | | <u-input |
| | | v-model="form.location" |
| | | placeholder="请输入地点" |
| | | :maxlength="30" |
| | | :maxlength="100" |
| | | :disabled="true" |
| | | /> |
| | | > |
| | | <template #suffix> |
| | | <u-icon |
| | | name="map" |
| | | @click="getCurrentLocation" |
| | | class="location-icon" |
| | | :class="{ 'loading': locationLoading }" |
| | | /> |
| | | </template> |
| | | </u-input> |
| | | </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> |
| | | <view class="upload-container"> |
| | | <ImageUpload |
| | | v-model="form.storageBlobDTO" |
| | | :limit="10" |
| | | :fileSize="50" |
| | | :fileType="['jpg', 'jpeg', 'png', 'mp4', 'mov']" |
| | | :maxVideoDuration="60" |
| | | :statusType="0" |
| | | @update:modelValue="handleStorageBlobUpdate" |
| | | /> |
| | | </view> |
| | | </u-form-item> |
| | | |
| | | <u-form-item label="巡检人" prop="scannerName" labelWidth="80"> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { reactive, ref, onMounted } from 'vue' |
| | | import { reactive, ref, onMounted, onUnmounted, nextTick } from 'vue' |
| | | import { addOrEditQrCodeRecord } from '@/api/inspectionUpload/index.js' |
| | | import useUserStore from '@/store/modules/user.ts' |
| | | import ImageUpload from '@/components/imageUpload/index.vue' |
| | | |
| | | const emit = defineEmits(['closeDia']) |
| | | |
| | |
| | | const formRef = ref(null) |
| | | const userStore = useUserStore() |
| | | const userInfo = ref({}) |
| | | const locationLoading = ref(false) |
| | | |
| | | // 请求取消标志 |
| | | let isRequestCancelled = false |
| | | |
| | | // 获取当前时间 |
| | | function getCurrentDateTime() { |
| | |
| | | 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() |
| | | // 检查组件是否还存在 |
| | | if (!isRequestCancelled && userInfo.value !== undefined) { |
| | | 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 |
| | | // 处理storageBlobDTO数据更新 |
| | | const handleStorageBlobUpdate = (value) => { |
| | | form.storageBlobDTO = value || [] |
| | | } |
| | | |
| | | // 获取当前位置 |
| | | const getCurrentLocation = () => { |
| | | // 检查组件是否还存在 |
| | | if (isRequestCancelled) return |
| | | |
| | | // 上传文件到服务器 |
| | | uni.uploadFile({ |
| | | url: '/api/upload', // 替换为实际的上传接口 |
| | | filePath: file.url, |
| | | name: 'file', |
| | | locationLoading.value = true |
| | | uni.showLoading({ title: '获取位置中...' }) |
| | | |
| | | uni.getLocation({ |
| | | type: 'gcj02', |
| | | 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' |
| | | }) |
| | | // 检查组件是否还存在 |
| | | if (isRequestCancelled) { |
| | | uni.hideLoading() |
| | | return |
| | | } |
| | | |
| | | // 使用逆地理编码获取地址信息 |
| | | uni.request({ |
| | | url: `https://restapi.amap.com/v3/geocode/regeo?key=c120a5dc69a9f61839f7763e6057005f&location=${res.longitude},${res.latitude}&radius=1000&extensions=all`, |
| | | success: (geoRes) => { |
| | | // 检查组件是否还存在 |
| | | if (isRequestCancelled) { |
| | | uni.hideLoading() |
| | | return |
| | | } |
| | | |
| | | uni.hideLoading() |
| | | locationLoading.value = false |
| | | |
| | | if (geoRes.data.status === '1' && geoRes.data.regeocode) { |
| | | const regeocode = geoRes.data.regeocode |
| | | const address = regeocode.formatted_address |
| | | |
| | | // 优先显示详细地址 |
| | | if (address) { |
| | | form.location = address |
| | | uni.showToast({ |
| | | title: '位置获取成功', |
| | | icon: 'success' |
| | | }) |
| | | } else { |
| | | // 如果没有详细地址,尝试组合地址信息 |
| | | const addressComponent = regeocode.addressComponent |
| | | const combinedAddress = `${addressComponent.province}${addressComponent.city}${addressComponent.district}${addressComponent.township}` |
| | | form.location = combinedAddress |
| | | uni.showToast({ |
| | | title: '位置获取成功', |
| | | icon: 'success' |
| | | }) |
| | | } |
| | | } else { |
| | | // API调用成功但没有返回地址信息 |
| | | const fallbackAddress = `位置: ${res.latitude.toFixed(4)}, ${res.longitude.toFixed(4)}` |
| | | form.location = fallbackAddress |
| | | uni.showToast({ |
| | | title: '获取到位置,但地址解析失败', |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | // 检查组件是否还存在 |
| | | if (isRequestCancelled) { |
| | | uni.hideLoading() |
| | | return |
| | | } |
| | | |
| | | uni.hideLoading() |
| | | locationLoading.value = false |
| | | console.error('逆地理编码失败:', err) |
| | | |
| | | // 逆地理编码失败时,显示简化的位置信息 |
| | | const fallbackAddress = `位置: ${res.latitude.toFixed(4)}, ${res.longitude.toFixed(4)}` |
| | | form.location = fallbackAddress |
| | | uni.showToast({ |
| | | title: '位置获取成功,但地址解析失败', |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | fail: () => { |
| | | fail: (err) => { |
| | | // 检查组件是否还存在 |
| | | if (isRequestCancelled) { |
| | | uni.hideLoading() |
| | | return |
| | | } |
| | | |
| | | uni.hideLoading() |
| | | locationLoading.value = false |
| | | uni.showToast({ |
| | | title: '上传失败', |
| | | title: '获取位置失败,请检查定位权限', |
| | | icon: 'error' |
| | | }) |
| | | console.error('获取位置失败:', err) |
| | | |
| | | // 失败时显示错误信息 |
| | | form.location = '位置获取失败' |
| | | } |
| | | }) |
| | | } |
| | | |
| | | // 删除文件 |
| | | const deleteFile = (event) => { |
| | | const { index } = event |
| | | form.storageBlobDTO.splice(index, 1) |
| | | } |
| | | |
| | | // 打开弹框 |
| | | const openDialog = async (row) => { |
| | | console.log('弹框接收到的数据:', row) |
| | | dialogVisitable.value = true |
| | | form.deviceName = row.deviceName || '' |
| | | form.location = row.location || '' |
| | | form.qrCodeId = row.qrCodeId || row.id || '' |
| | | form.qrCodeId = row.qrCodeId |
| | | form.storageBlobDTO = [] |
| | | console.log('弹框表单数据:', form) |
| | | |
| | | // 强制更新视图 |
| | | await nextTick() |
| | | console.log('nextTick后弹框状态:', dialogVisitable.value) |
| | | } |
| | | |
| | | // 提交表单 |
| | | const submitForm = async () => { |
| | | try { |
| | | // 检查组件是否还存在 |
| | | if (isRequestCancelled) return |
| | | |
| | | console.log('开始提交表单,当前表单数据:', form) |
| | | |
| | | // 表单验证 |
| | | const valid = await formRef.value.validate() |
| | | if (!valid) return |
| | | if (formRef.value) { |
| | | const valid = await formRef.value.validate() |
| | | if (!valid) { |
| | | console.log('表单验证失败') |
| | | return |
| | | } |
| | | } |
| | | |
| | | form.qrCode.id = form.qrCodeId |
| | | // 检查必填字段 |
| | | if (!form.deviceName) { |
| | | uni.showToast({ |
| | | title: '请输入设备名称', |
| | | icon: 'error' |
| | | }) |
| | | return |
| | | } |
| | | |
| | | await addOrEditQrCodeRecord({ ...form }) |
| | | if (!form.location) { |
| | | uni.showToast({ |
| | | title: '请获取位置信息', |
| | | icon: 'error' |
| | | }) |
| | | return |
| | | } |
| | | |
| | | // 准备提交数据 |
| | | const submitData = { |
| | | deviceName: form.deviceName, |
| | | location: form.location, |
| | | scannerName: form.scannerName, |
| | | scannerId: form.scannerId, |
| | | scanTime: form.scanTime, |
| | | storageBlobDTO: form.storageBlobDTO.map(file => ({ |
| | | id: file.id, // 添加id字段 |
| | | url: file.url, |
| | | bucketFilename: file.bucketFilename || file.name, |
| | | downloadUrl: file.downloadUrl || file.url, |
| | | type: 0, |
| | | size: file.size, |
| | | createTime: file.createTime || new Date().getTime() |
| | | })), |
| | | qrCode: { |
| | | id: form.qrCodeId |
| | | } |
| | | } |
| | | |
| | | console.log('准备提交的数据:', submitData) |
| | | |
| | | const response = await addOrEditQrCodeRecord(submitData) |
| | | |
| | | // 检查组件是否还存在 |
| | | if (isRequestCancelled) return |
| | | |
| | | console.log('提交响应:', response) |
| | | |
| | | uni.showToast({ |
| | | title: '提交成功', |
| | |
| | | |
| | | cancel() |
| | | } catch (error) { |
| | | // 检查组件是否还存在 |
| | | if (isRequestCancelled) return |
| | | |
| | | console.error('提交失败:', error) |
| | | |
| | | // 显示更详细的错误信息 |
| | | let errorMessage = '提交失败' |
| | | if (error.response) { |
| | | errorMessage = error.response.data?.message || `服务器错误: ${error.response.status}` |
| | | } else if (error.message) { |
| | | errorMessage = error.message |
| | | } |
| | | |
| | | uni.showToast({ |
| | | title: '提交失败', |
| | | icon: 'error' |
| | | title: errorMessage, |
| | | icon: 'error', |
| | | duration: 3000 |
| | | }) |
| | | } |
| | | } |
| | |
| | | dialogVisitable.value = false |
| | | emit('closeDia') |
| | | } |
| | | |
| | | // 组件销毁时的清理 |
| | | onUnmounted(() => { |
| | | // 设置取消标志,阻止后续的异步操作 |
| | | isRequestCancelled = true |
| | | |
| | | // 清理状态 |
| | | if (locationLoading.value) { |
| | | locationLoading.value = false |
| | | } |
| | | |
| | | // 关闭弹窗 |
| | | if (dialogVisitable.value) { |
| | | dialogVisitable.value = false |
| | | } |
| | | |
| | | // 隐藏可能显示的加载提示 |
| | | uni.hideLoading() |
| | | }) |
| | | |
| | | defineExpose({ openDialog }) |
| | | </script> |
| | |
| | | border-top: 1px solid #f0f0f0; |
| | | background-color: #fafafa; |
| | | } |
| | | |
| | | .location-icon { |
| | | color: #1890ff; |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | } |
| | | |
| | | .location-icon:hover { |
| | | color: #40a9ff; |
| | | } |
| | | |
| | | .location-icon.loading { |
| | | color: #999; |
| | | animation: spin 1s linear infinite; |
| | | } |
| | | |
| | | @keyframes spin { |
| | | from { transform: rotate(0deg); } |
| | | to { transform: rotate(360deg); } |
| | | } |
| | | |
| | | .upload-container { |
| | | width: 100%; |
| | | } |
| | | </style> |