iot-fontend/src/views/iot/deviceMap/index.vue
Kven 7328db1a23 feat(iot): 优化设备和产品详情页面布局
-调整设备和产品详情页面的布局结构
- 添加设备和产品预览图片
- 优化事件记录展示方式
- 增加设备编辑功能
- 重构事件记录查询接口
2025-03-24 20:47:06 +08:00

207 lines
7.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<a-layout>
<a-layout-sider style="width:300px;background-color: transparent;" :resize-directions="['right']">
<!-- 搜索框 -->
<a-card>
<a-input-search
v-model="searchKeyword"
placeholder="设备名称"
@change="handleSearch"
@search="handleSearch"
style="margin-bottom: 16px"
/>
</a-card>
<!-- 设备列表 -->
<a-row>
<a-col
:span="24"
v-for="device in deviceList"
:key="device.id"
@click="selectDevice(device)"
>
<a-card hoverable :style="{ margin: '5px', height: '100px' }">
<div
:style="{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
}"
>
<span
:style="{ display: 'flex', alignItems: 'center', color: '#1D2129' }"
>
<a-avatar
shape="square"
:size="70"
>
<a-image
:src="getImageUrl(device.previewId)"
/>
</a-avatar>
<a-descriptions layout="inline-horizontal" :style="{ marginLeft: '10px'}">
<a-descriptions-item label="设备名称" :span="3">{{ device.name }}</a-descriptions-item>
<!-- <a-descriptions-item label="硬件版本">{{ device.hardwareVersion }}</a-descriptions-item>-->
<!-- <a-descriptions-item label="固件版本">{{ device.firmwareVersion }}</a-descriptions-item>-->
<a-descriptions-item label="所属产品">{{ device.productName }}</a-descriptions-item>
</a-descriptions>
</span>
</div>
</a-card>
</a-col>
</a-row>
</a-layout-sider>
<a-layout-content>
<div id="container"></div>
</a-layout-content>
</a-layout>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import AMapLoader from '@amap/amap-jsapi-loader';
import { DeviceRecord, queryDeviceByNameList, queryDeviceList } from '@/api/device';
import '@amap/amap-jsapi-types';
import router from '@/router';
import { Message } from '@arco-design/web-vue';
import { debounce } from '@arco-design/web-vue/es/_utils/debounce';
let map: any = null;
const deviceList = ref<DeviceRecord[]>([]);
const searchKeyword = ref(''); // 搜索关键字
const isLoading = ref(false); // 加载状态
let selectDevice = (device: DeviceRecord) => {
console.log(device);
};
// 获取图片 URL 的函数
const getImageUrl = (previewId: string) => {
if (!previewId) {
return 'https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/3ee5f13fb09879ecb5185e440cef6eb9.png~tplv-uwbnlip3yd-webp.webp';
}
return `/api/rest/attachment/${previewId}`;
};
// 防抖搜索函数
const handleSearch = debounce(async (value: string) => {
try {
isLoading.value = true; // 开始加载
if (value) {
const res = await queryDeviceByNameList({
name: value,
});
deviceList.value = res.data;
} else {
// 如果搜索框为空,恢复显示全部设备列表
const response = await queryDeviceByNameList({});
deviceList.value = response.data;
}
} catch (error) {
Message.error('搜索失败,请稍后重试');
} finally {
isLoading.value = false; // 结束加载
}
}, 300); // 防抖时间设置为 300ms
// const handleImageError = (event: Event) => {
// const img = event.target as HTMLImageElement;
// img.src = 'https://p1-arco.byteimg.com/tos-cn-i-uwbnlip3yd/3ee5f13fb09879ecb5185e440cef6eb9.png~tplv-uwbnlip3yd-webp.webp'; // 替换为默认图片
// };
AMapLoader.load({
key: 'a4e80eed798a56451b226dcfca81b846', // 申请好的Web端开发者Key首次调用 load 时必填
version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
})
.then((AMap) => {
map = new AMap.Map('container', {
// 设置地图容器id
viewMode: '3D', // 是否为3D地图模式
zoom: 11, // 初始化地图级别
center: [116.397428, 39.90923], // 初始化地图中心点位置
});
selectDevice = (device: DeviceRecord) => {
if (device.longitude && device.latitude) {
const lngLat = [device.longitude, device.latitude];
const content = document.createElement('div');
content.className = 'custom-content-marker';
const markerIcon = device.warning === '1'
? `/api/rest/attachment/${device.icon?.url}` // 警告标记
: `/api/rest/attachment/${device.icon?.url}`; // 默认标记
content.innerHTML = `<img src="${markerIcon}" alt="标记点" />`;
// 创建标记点
const marker = new AMap.Marker({
position: lngLat,
content,
});
// 将标记点添加到地图上
map.setCenter(lngLat);
map.setZoom(20);
map.add(marker);
const infoContent = [
`<br/><div style="width: 300px;margin-left: 20px;padding-bottom: 10px"><b>设备名称: ${device.name}</b>`,
`<span style="font-size: 16px; color: #333;">硬件版本: ${device.hardwareVersion}</span>`,
`<span style="font-size: 16px; color: #333;">固件版本: ${device.firmwareVersion}</span>`,
`<span style="font-size: 16px; color: #333;">所属产品: ${device.productName}</span>`,
`<a-button style="margin-left: 200px;color: #0960bd" onclick="handleViewDetail('${device.id}')">查看详情
</a-button></div>`,
];
window.handleViewDetail = (deviceId: number) => {
router.push({ name: 'deviceDetail', params: { id: deviceId } });
};
// 初始化信息窗体
const infoWindow = new AMap.InfoWindow({
content: infoContent.join('<br>'),
offset: new AMap.Pixel(10, 10), // 调整信息窗体的偏移量
});
// 绑定标记点点击事件
marker.on('click', () => {
infoWindow.open(map, lngLat); // 打开信息窗体
});
} else {
Message.error('设备缺少经纬度信息');
}
};
})
.catch((e) => {
Message.error('加载地图失败');
console.log(e);
});
// 将依赖于 AMap 的代码放在 then 回调中
onMounted(() => {
// 获取设备列表
queryDeviceByNameList({})
.then((response) => {
deviceList.value = response.data;
})
.catch(() => {
Message.error('获取设备列表失败');
});
});
// onUnmounted(() => {
// map?.destroy();
// });
</script>
<style scoped>
#container {
width: 100%;
height: 100vh;
}
.custom-content-marker img {
width: 100%;
height: 100%;
}
</style>