237 lines
7.0 KiB
Vue
237 lines
7.0 KiB
Vue
<template>
|
||
<div class="right-sidebar" :class="{ contracted: isContracted }">
|
||
<div class="device-status">
|
||
<div
|
||
v-for="(item, index) in deviceStatus"
|
||
:key="index"
|
||
class="device-item"
|
||
>
|
||
<div class="device-icon">
|
||
<img
|
||
:src="
|
||
require(`@/assets/img/device/${
|
||
item.state > 0 ? item.icon + '-h' + '.png' : item.icon + '.png'
|
||
}`)
|
||
"
|
||
alt=""
|
||
/>
|
||
</div>
|
||
<div class="device-info">
|
||
<div class="device-name">{{ item.state }}</div>
|
||
<div class="device-num">/{{ item.num }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="markers">
|
||
<div class="title">
|
||
<img
|
||
src="@/assets/img/positionTitle.png"
|
||
alt=""
|
||
@click="handleTitleClick(true, 'all')"
|
||
/>
|
||
</div>
|
||
<ul>
|
||
<li
|
||
v-for="(item, index) in positionData"
|
||
:key="index"
|
||
@click="handlePositionClick(item)"
|
||
>
|
||
<div class="left">
|
||
<img src="@/assets/img/positionPiont.png" alt="" />
|
||
</div>
|
||
<div class="main">
|
||
<div class="top_main">
|
||
<div class="text">{{ item.name }}</div>
|
||
</div>
|
||
<div class="top_main">
|
||
<div class="text1">{{ item.address }}</div>
|
||
</div>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div class="right-contract" @click="handleContractClick">
|
||
<img :src="isContracted ? leftContract : rightContract" alt="" />
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { allPositions, allDevices } from "../index.js";
|
||
export default {
|
||
name: "RightSidebar",
|
||
props: {
|
||
homeData: {
|
||
type: Object,
|
||
default: () => ({})
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
leftContract: require("@/assets/img/left-contracts.png"),
|
||
rightContract: require("@/assets/img/right-contracts.png"),
|
||
deviceStatus: [],
|
||
positionData: [],
|
||
isContracted: false,
|
||
lastPositionsHash: null // 初始化为 null,避免首次误判
|
||
};
|
||
},
|
||
watch: {
|
||
"homeData.positions": {
|
||
handler(newPositions) {
|
||
newPositions = newPositions || [];
|
||
|
||
const currentHash = JSON.stringify(newPositions);
|
||
|
||
// 比较新旧数据(首次加载时 lastPositionsHash 为 null)
|
||
if (
|
||
this.lastPositionsHash !== null &&
|
||
currentHash === this.lastPositionsHash
|
||
) {
|
||
return;
|
||
}
|
||
|
||
// 数据变化或首次加载
|
||
if (newPositions.length > 0) {
|
||
this.lastPositionsHash = currentHash; // 更新缓存
|
||
this.positionData = newPositions;
|
||
this.homeView = this.homeData;
|
||
this.$nextTick(() => {
|
||
this.handleTitleClick(true, "all");
|
||
});
|
||
}
|
||
},
|
||
immediate: true // 初始加载时触发
|
||
}
|
||
},
|
||
mounted() {},
|
||
methods: {
|
||
handleContractClick() {
|
||
this.isContracted = !this.isContracted; // 切换状态
|
||
},
|
||
handleTitleClick(show, type) {
|
||
if (type === "all") {
|
||
// 获取所有位置的设备数据
|
||
const allData = this.positionData.flatMap((item) => item.devices || []);
|
||
|
||
// 创建一个映射来统计每种 icon 的总数和在线数量
|
||
const deviceStats = {};
|
||
|
||
// 统计所有设备的数量
|
||
allData.forEach((device) => {
|
||
if (!deviceStats[device.icon]) {
|
||
deviceStats[device.icon] = {
|
||
total: 0,
|
||
online: 0,
|
||
name: device.model
|
||
};
|
||
}
|
||
deviceStats[device.icon].total += 1;
|
||
if (device.isOnline) {
|
||
deviceStats[device.icon].online += 1;
|
||
}
|
||
});
|
||
|
||
// 将统计结果转换为 deviceStatus 数组
|
||
this.deviceStatus = Object.entries(deviceStats).map(
|
||
([icon, stats], index) => ({
|
||
id: index + 1,
|
||
name: stats.name || `设备类型${icon}`,
|
||
icon: icon,
|
||
num: stats.total,
|
||
state: stats.online
|
||
})
|
||
);
|
||
allDevices(this.positionData, "all", true); // 显示所有设备信息
|
||
}
|
||
console.log(this.positionData, "this.positionData");
|
||
let positionData = this.processGeojsonData(this.positionData);
|
||
allPositions(positionData, show, "all"); // 显示所有位置信息
|
||
},
|
||
handlePositionClick(value) {
|
||
console.log(value, "value");
|
||
this.deviceStatus = [];
|
||
// 获取设备列表
|
||
const devices = value.devices || [];
|
||
|
||
// 创建一个映射来统计每种 icon 的总数和在线数量
|
||
const deviceStats = {};
|
||
|
||
// 统计设备数量
|
||
devices.forEach((device) => {
|
||
if (!deviceStats[device.icon]) {
|
||
deviceStats[device.icon] = {
|
||
total: 0,
|
||
online: 0,
|
||
name: device.model // 假设使用 model 作为名称,如果需要其他字段可以修改
|
||
};
|
||
}
|
||
deviceStats[device.icon].total += 1;
|
||
if (device.isOnline) {
|
||
deviceStats[device.icon].online += 1;
|
||
}
|
||
});
|
||
|
||
// 将统计结果转换为 deviceStatus 数组
|
||
this.deviceStatus = Object.entries(deviceStats).map(
|
||
([icon, stats], index) => ({
|
||
id: index + 1,
|
||
name: stats.name || `设备类型${icon}`, // 如果没有名称,使用默认值
|
||
icon: icon,
|
||
num: stats.total,
|
||
state: stats.online
|
||
})
|
||
);
|
||
this.handleTitleClick(false, "one");
|
||
let positionData = this.processGeojsonData([value]);
|
||
allPositions(positionData, true, "one", value); // 显示所有位置信息
|
||
let deviceData = this.positionData.find((item) => item.id === value.id);
|
||
allDevices(deviceData, "one", true); // 显示所有设备信息
|
||
},
|
||
processGeojsonData(value) {
|
||
// 存储所有设备的 GeoJSON 数据
|
||
let geojsonArray = [];
|
||
// 遍历所有设备
|
||
value.forEach((item) => {
|
||
if (typeof item.regionJson === "string") {
|
||
item.regionJson = JSON.parse(item.regionJson); // 解析 GeoJSON 数据
|
||
}
|
||
if (item.regionJson?.type === "MultiPolygon") {
|
||
const polygons = item.regionJson.coordinates.map((polygon, index) => {
|
||
// 返回标准化的 GeoJSON Feature
|
||
return {
|
||
type: "Feature",
|
||
name: item.source,
|
||
geometry: {
|
||
type: "Polygon",
|
||
coordinates: polygon // 保持原始坐标
|
||
},
|
||
properties: {
|
||
shape: "polygon",
|
||
deviceId: item.id, // 添加设备 ID 以区分来源
|
||
source: item.source // 可选:添加设备名称
|
||
}
|
||
};
|
||
});
|
||
|
||
// 将当前设备的多边形添加到总数组
|
||
geojsonArray = geojsonArray.concat(polygons);
|
||
}
|
||
});
|
||
|
||
return geojsonArray; // 返回所有设备的 GeoJSON 数据
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.right-sidebar {
|
||
transition: transform 0.5s;
|
||
}
|
||
|
||
.right-sidebar.contracted {
|
||
transform: translateX(90%);
|
||
}
|
||
</style>
|