feat:iot-map

pull/789/head
alwayssuper 2025-07-04 17:54:05 +08:00
parent 10ca38c609
commit 7115a84a76
3 changed files with 104 additions and 27 deletions

View File

@ -26,6 +26,12 @@ export enum DeviceTypeEnum {
GATEWAY_SUB = 1, // 网关子设备
GATEWAY = 2 // 网关设备
}
// IOT 产品定位类型枚举类 0: 手动定位, 1: IP 定位, 2: 定位模块定位
export enum LocationTypeEnum {
MANUAL = 0, // 手动定位
IP = 1, // IP 定位
MODULE = 2 // 定位模块定位
}
// IOT 数据格式(编解码器类型)枚举类
export enum CodecTypeEnum {
ALINK = 'Alink' // 阿里云 Alink 协议

View File

@ -1,7 +1,7 @@
<template>
<div v-if="props.isWrite">
<el-form ref="form" label-width="120px">
<el-form-item label="设备位置:">
<el-form-item label="定位位置:">
<el-select
style="width: 100%"
v-model="state.address"
@ -9,7 +9,7 @@
filterable
remote
reserve-keyword
placeholder="请输入地址"
placeholder="可输入地址查询经纬度"
:remote-method="autoSearch"
@change="regeoCode"
:loading="state.loading"
@ -176,6 +176,10 @@ const getAddress = (lnglat) => {
}
})
}
// 使访
defineExpose({
regeoCode
})
onMounted(() => {
loadMap()

View File

@ -77,30 +77,33 @@
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="设备经度" prop="longitude" type="number">
<el-input v-model="formData.longitude" placeholder="请输入设备经度">
<template #append>
<el-link
:underline="false"
href="https://api.map.baidu.com/lbsapi/getpoint/index.html"
target="_blank"
>坐标拾取</el-link
>
</template>
</el-input>
</el-form-item>
<el-form-item label="设备维度" prop="latitude" type="number">
<el-input v-model="formData.latitude" placeholder="请输入设备维度">
<template #append>
<el-link
:underline="false"
href="https://api.map.baidu.com/lbsapi/getpoint/index.html"
target="_blank"
>坐标拾取</el-link
>
</template>
</el-input>
</el-form-item>
<!-- 只在定位类型为GPS时显示坐标和地图 -->
<template v-if="showCoordinates">
<el-form-item label="设备经度" prop="longitude" type="number">
<el-input
v-model="formData.longitude"
placeholder="请输入设备经度"
@blur="updateLocationFromCoordinates"
/>
</el-form-item>
<el-form-item label="设备维度" prop="latitude" type="number">
<el-input
v-model="formData.latitude"
placeholder="请输入设备维度"
@blur="updateLocationFromCoordinates"
/>
</el-form-item>
<div class="pl-0 w-full ml-[-18px]" v-if="showMap">
<Map
:isWrite="true"
:clickMap="true"
:center="formData.location"
@locateChange="handleLocationChange"
ref="mapRef"
class="h-[400px] w-full"
/>
</div>
</template>
</el-collapse-item>
</el-collapse>
</el-form>
@ -113,9 +116,11 @@
<script setup lang="ts">
import { DeviceApi, DeviceVO } from '@/api/iot/device/device'
import { DeviceGroupApi } from '@/api/iot/device/group'
import { DeviceTypeEnum, ProductApi, ProductVO } from '@/api/iot/product/product'
import { DeviceTypeEnum, LocationTypeEnum, ProductApi, ProductVO } from '@/api/iot/product/product'
import { UploadImg } from '@/components/UploadFile'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import Map from '@/components/Map/index.vue'
import { ref } from 'vue'
/** IoT 设备表单 */
defineOptions({ name: 'IoTDeviceForm' })
@ -127,6 +132,17 @@ const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const showMap = ref(false) //
const mapRef = ref(null)
//
const showCoordinates = computed(() => {
return (
formData.value.locationType !== LocationTypeEnum.IP &&
formData.value.locationType !== LocationTypeEnum.MODULE
)
})
const formData = ref({
id: undefined,
productId: undefined,
@ -139,8 +155,19 @@ const formData = ref({
locationType: undefined as number | undefined,
longitude: undefined,
latitude: undefined,
location: '', // : ","
groupIds: [] as number[]
})
// location
watch([() => formData.value.longitude, () => formData.value.latitude], ([newLong, newLat]) => {
if (newLong && newLat) {
formData.value.location = `${newLong},${newLat}`
//
showMap.value = true
}
})
const formRules = reactive({
productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }],
deviceName: [
@ -191,15 +218,25 @@ const open = async (type: string, id?: number) => {
formType.value = type
resetForm()
//
showMap.value = false
//
if (id) {
formLoading.value = true
try {
formData.value = await DeviceApi.getDevice(id)
// location
if (formData.value.longitude && formData.value.latitude) {
formData.value.location = `${formData.value.longitude},${formData.value.latitude}`
}
} finally {
formLoading.value = false
}
}
//
showMap.value = true
//
try {
@ -228,6 +265,16 @@ const submitForm = async () => {
formLoading.value = true
try {
const data = formData.value as unknown as DeviceVO
// IPMODULE
if (
data.locationType === LocationTypeEnum.IP ||
data.locationType === LocationTypeEnum.MODULE
) {
data.longitude = undefined
data.latitude = undefined
}
if (formType.value === 'create') {
await DeviceApi.createDevice(data)
message.success(t('common.createSuccess'))
@ -257,9 +304,12 @@ const resetForm = () => {
locationType: undefined,
longitude: undefined,
latitude: undefined,
location: '',
groupIds: []
}
formRef.value?.resetFields()
//
showMap.value = false
}
/** 产品选择变化 */
@ -272,4 +322,21 @@ const handleProductChange = (productId: number) => {
formData.value.deviceType = product?.deviceType
formData.value.locationType = product?.locationType
}
/** 处理位置变化 */
const handleLocationChange = (lnglat) => {
formData.value.longitude = lnglat[0]
formData.value.latitude = lnglat[1]
}
/** 根据经纬度更新地图位置 */
const updateLocationFromCoordinates = () => {
//
if (formData.value.longitude && formData.value.latitude) {
// location
formData.value.location = `${formData.value.longitude},${formData.value.latitude}`
console.log('更新location字段:', formData.value.location)
mapRef.value.regeoCode(formData.value.location)
}
}
</script>