<template>
|
<u-popup
|
:show="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="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">
|
<view class="upload-container">
|
<u-upload
|
:fileList="form.storageBlobDTO"
|
@afterRead="afterRead"
|
@delete="deleteFile"
|
name="files"
|
multiple
|
:maxCount="10"
|
:maxSize="50 * 1024 * 1024"
|
accept="image/*,video/*"
|
:previewFullImage="true"
|
:camera="true"
|
:gallery="true"
|
></u-upload>
|
<view class="upload-actions">
|
<u-button
|
type="primary"
|
size="small"
|
@click="chooseImage"
|
:customStyle="{ marginRight: '10px' }"
|
>
|
拍照
|
</u-button>
|
<u-button
|
type="success"
|
size="small"
|
@click="chooseVideo"
|
>
|
录像
|
</u-button>
|
</view>
|
</view>
|
</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, nextTick } 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({})
|
const locationLoading = ref(false)
|
|
// 获取当前时间
|
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
|
console.log('文件选择:', file)
|
|
// 直接添加到文件列表,不上传到服务器
|
const fileItem = {
|
url: file.url,
|
name: file.name || `文件_${Date.now()}`,
|
status: 'success',
|
size: file.size || 0,
|
type: file.type || 'image/jpeg'
|
}
|
|
form.storageBlobDTO.push(fileItem)
|
|
uni.showToast({
|
title: '文件添加成功',
|
icon: 'success'
|
})
|
}
|
|
// 拍照
|
const chooseImage = () => {
|
uni.chooseImage({
|
count: 1,
|
sizeType: ['original', 'compressed'],
|
sourceType: ['camera'],
|
success: (res) => {
|
console.log('拍照成功:', res)
|
const tempFilePath = res.tempFilePaths[0]
|
|
const fileItem = {
|
url: tempFilePath,
|
name: `照片_${Date.now()}.jpg`,
|
status: 'success',
|
type: 'image/jpeg'
|
}
|
|
form.storageBlobDTO.push(fileItem)
|
|
uni.showToast({
|
title: '拍照成功',
|
icon: 'success'
|
})
|
},
|
fail: (err) => {
|
console.error('拍照失败:', err)
|
uni.showToast({
|
title: '拍照失败',
|
icon: 'error'
|
})
|
}
|
})
|
}
|
|
// 录像
|
const chooseVideo = () => {
|
uni.chooseVideo({
|
sourceType: ['camera'],
|
maxDuration: 60, // 最大60秒
|
camera: 'back',
|
success: (res) => {
|
console.log('录像成功:', res)
|
const tempFilePath = res.tempFilePath
|
|
const fileItem = {
|
url: tempFilePath,
|
name: `视频_${Date.now()}.mp4`,
|
status: 'success',
|
type: 'video/mp4',
|
duration: res.duration,
|
size: res.size
|
}
|
|
form.storageBlobDTO.push(fileItem)
|
|
uni.showToast({
|
title: '录像成功',
|
icon: 'success'
|
})
|
},
|
fail: (err) => {
|
console.error('录像失败:', err)
|
uni.showToast({
|
title: '录像失败',
|
icon: 'error'
|
})
|
}
|
})
|
}
|
|
// 删除文件
|
const deleteFile = (event) => {
|
const { index } = event
|
form.storageBlobDTO.splice(index, 1)
|
}
|
|
// 获取当前位置
|
const getCurrentLocation = () => {
|
locationLoading.value = true
|
uni.showLoading({ title: '获取位置中...' })
|
|
uni.getLocation({
|
type: 'gcj02',
|
success: (res) => {
|
// 使用逆地理编码获取地址信息
|
uni.request({
|
url: `https://restapi.amap.com/v3/geocode/regeo?key=c120a5dc69a9f61839f7763e6057005f&location=${res.longitude},${res.latitude}&radius=1000&extensions=all`,
|
success: (geoRes) => {
|
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) => {
|
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: (err) => {
|
uni.hideLoading()
|
locationLoading.value = false
|
uni.showToast({
|
title: '获取位置失败,请检查定位权限',
|
icon: 'error'
|
})
|
console.error('获取位置失败:', err)
|
|
// 失败时显示错误信息
|
form.location = '位置获取失败'
|
}
|
})
|
}
|
|
// 打开弹框
|
const openDialog = async (row) => {
|
console.log('弹框接收到的数据:', row)
|
console.log('弹框打开前状态:', dialogVisitable.value)
|
|
dialogVisitable.value = true
|
form.deviceName = row.deviceName || ''
|
form.location = row.location || ''
|
form.qrCodeId = row.qrCodeId || row.id || ''
|
form.storageBlobDTO = []
|
|
console.log('弹框打开后状态:', dialogVisitable.value)
|
console.log('弹框表单数据:', form)
|
|
// 强制更新视图
|
await nextTick()
|
console.log('nextTick后弹框状态:', dialogVisitable.value)
|
}
|
|
// 提交表单
|
const submitForm = async () => {
|
try {
|
console.log('开始提交表单,当前表单数据:', form)
|
|
// 表单验证
|
if (formRef.value) {
|
const valid = await formRef.value.validate()
|
if (!valid) {
|
console.log('表单验证失败')
|
return
|
}
|
}
|
|
// 检查必填字段
|
if (!form.deviceName) {
|
uni.showToast({
|
title: '请输入设备名称',
|
icon: 'error'
|
})
|
return
|
}
|
|
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,
|
qrCode: {
|
id: form.qrCodeId || form.qrCode.id
|
}
|
}
|
|
console.log('准备提交的数据:', submitData)
|
|
const response = await addOrEditQrCodeRecord(submitData)
|
console.log('提交响应:', response)
|
|
uni.showToast({
|
title: '提交成功',
|
icon: 'success'
|
})
|
|
cancel()
|
} catch (error) {
|
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: errorMessage,
|
icon: 'error',
|
duration: 3000
|
})
|
}
|
}
|
|
// 关闭弹框
|
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;
|
}
|
|
.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%;
|
}
|
|
.upload-actions {
|
display: flex;
|
justify-content: flex-start;
|
margin-top: 10px;
|
gap: 10px;
|
}
|
</style>
|