Commit b4c7a74a by 吴春元

优化地图组件,添加设备筛选下拉框,调整样式,清理无用代码

parent d85c4224
......@@ -2,6 +2,8 @@
export {};
; declare global {
var __VLS_PROPS_FALLBACK: Record<string, unknown>;
const __VLS_directiveBindingRestFields: { instance: null, oldValue: null, modifiers: any, dir: any };
const __VLS_unref: typeof import('vue').unref;
const __VLS_placeholder: any;
......@@ -35,7 +37,7 @@ export {};
attrs?: any;
slots?: T extends { $slots: infer Slots } ? Slots : Record<string, any>;
emit?: T extends { $emit: infer Emit } ? Emit : {};
props?: (T extends { $props: infer Props } ? Props : {}) & Record<string, unknown>;
props?: typeof props;
expose?: (exposed: T) => void;
};
};
......
// 深蓝色主题变量
$primary-color: #1890FF; // 主蓝色
$primary-color: #1890ff; // 主蓝色
$secondary-color: #003a8c; // 次级蓝色
$text-color: #FFFFFF; // 白色文字
$text-color: #ffffff; // 白色文字
$dark-blue-bg: #001529; // 深蓝背景
$dark-blue-border: #004d99; // 边框蓝色
$light-gray-text: #D9D9D9; // 浅灰色文字
$light-gray-text: #d9d9d9; // 浅灰色文字
$blue-hover: #40a9ff; // 悬停蓝色
// 扩展的颜色变量
......@@ -19,7 +19,7 @@ $sidebar-width: 200px;
$container-padding: 20px;
// 字体变量
$font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
$font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
$font-size-base: 14px;
$font-size-lg: 16px;
$font-size-sm: 12px;
......
......@@ -80,6 +80,7 @@ button:focus-visible {
height: 100%;
padding: 20px;
}
/* 全局字体 */
@font-face {
font-family: "PangMen";
......
<template>
<!-- map-container上面加一个下拉框 -->
<div class="map-container w-full h-full relative" id="container">
<div class="absolute top-2 left-2 z-10">
<el-tree-select
style="width: 150px"
v-model="treeDataValue"
:data="treeDataList"
:props="{ value: 'id', label: 'name', children: 'children' }"
value-key="id"
placeholder="设备筛选"
check-strictly
:render-after-expand="false"
@change="handleSceneChange"
/>
</div>
</div>
</template>
<script setup>
import { onMounted, onUnmounted, nextTick, getCurrentInstance } from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";
import mapBg from "/src/assets/imgs/map-bg.png";
import closeIcon from "/src/assets/imgs/close-icon.png";
import { deviceList, deviceTypeList } from "@/api/iot/home";
import useDictStore from "@/store/modules/dict";
import { de } from "element-plus/es/locales.mjs";
import { handleTree } from "@/utils/ruoyi";
const instance = getCurrentInstance();
const { sys_type: sysType } = instance.proxy.useDict("sys_type");
let map = null;
let showInfoWindow = false;
let infoWindow = null;
var points = ref([]);
const treeDataValue = ref([]);
const treeDataList = ref([]);
const oneTypeId = ref("");
const twoTypeId = ref("");
const threeTypeId = ref("");
const fourTypeId = ref("");
const fiveTypeId = ref("");
const sixTypeId = ref("");
const props = defineProps({
deptId: {
type: Number,
default: 0,
},
});
onMounted(() => {
window._AMapSecurityConfig = {
securityJsCode: "40f496011ee130bf5a5713bc90291655",
};
});
function handleSceneChange(val) {
treeDataList.value.forEach((item) => {
if (item.id === val) {
const parentIds = item.parentIds;
const ids = parentIds
.split("|")
.filter((item) => item !== "" && item !== "0");
//将当前选中的类型赋值给对应的类型id
if (ids.length == 0) {
oneTypeId.value = val;
}
if (ids.length == 1) {
twoTypeId.value = val;
}
if (ids.length == 2) {
threeTypeId.value = val;
}
if (ids.length == 3) {
fourTypeId.value = val;
}
if (ids.length == 4) {
fiveTypeId.value = val;
}
if (ids.length == 5) {
sixTypeId.value = val;
}
}
});
// getDeviceList();
}
function initMap() {
AMapLoader.load({
key: "fee919a8e608c39d1d528ec662a2ca17", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [
"AMap.Scale",
"AMap.DistrictSearch",
"AMap.MarkerCluster",
"AMap.IndexCluster",
"AMap.ToolBar",
"AMap.InfoWindow",
], //需要使用的的插件列表,如比例尺'AMap.Scale',支持添加多个如:['...','...']
})
.then((AMap) => {
// 绘制省份边界
const district = new AMap.DistrictSearch({
subdistrict: 0,
extensions: "all",
level: "province",
});
district.search("山西", function (status, result) {
// 查询成功时,result即为对应的行政区信息
const bounds = result.districtList[0].boundaries;
const mask = [];
for (let i = 0; i < bounds.length; i++) {
mask.push([bounds[i]]);
}
const map = new AMap.Map("container", {
pitch: 30, // 倾斜角度
zoom: 6.7, // 设置当前显示级别
expandZoomRange: true, // 开启显示范围设置
animateEnable: true,
zooms: [3, 20], //最小显示级别为7,最大显示级别为20
center: [112.39, 36.99], // 设置地图中心点位置
viewMode: "3D", // 特别注意,设置为3D则其他地区不显示
zoomEnable: true, // 是否可以缩放地图
resizeEnable: true, // 是否开启地图自动调整大小
mapStyle: "amap://styles/darkblue", // 地图样式,默认值为amap://styles/normal
// mapStyle: "amap://styles/whitesmoke", //设置地图的显示样式
});
// 添加描边
for (let i = 0; i < bounds.length; i++) {
const polyline = new AMap.Polyline({
path: bounds[i], // polyline 路径,支持 lineString 和 MultiLineString
strokeColor: "blue", // 线条颜色,使用16进制颜色代码赋值。默认值为#00D3FC
strokeWeight: 5, // 轮廓线宽度,默认为:2
// map:map // 这种方式相当于: polyline.setMap(map);
});
polyline.setMap(map);
}
//添加图层MarkerClusterer
const cluster = new AMap.MarkerClusterer(
map, // 地图实例
points.value, // 海量点数据,数据中需包含经纬度信息字段 lnglat
{
gridSize: 10, // 聚合网格的像素大小,默认值为60
//聚合点样式
// renderClusterMarker: _renderClusterMarker,
//非聚合点样式
renderMarker: (context) => {
const item = context.data[0];
//设置非聚合点样式
context.marker.setContent(
`<img src="${item.twoType.pic}" alt="" style="width: 25px;height: 25px;">`
);
// 自定义点击事件
context.marker.on("click", function (e) {
var info = [];
info.push(
`<div style="background:url(${mapBg}) no-repeat; background-size: 100% 100%;width: 260px;height: 145px;">`
);
info.push(
"<div style='display: flex; align-items: center; justify-content: space-between;'>"
);
info.push(
"<div style='margin-left: 20px;margin-top: 5px; font-size: 16px;font-family: YouSheBiaoTiHei;'>设备信息</div>"
);
info.push(
`<div style="margin-right: 10px;background:url(${closeIcon}) no-repeat; background-size: 100% 100%;height: 20px;width: 20px;" class="close-info-window"></div></div>`
);
info.push("<div style='display: flex;'>");
info.push(
"<div style='font-size: 11px;color:#357abd;height: 150px'>"
);
info.push(
"<div class='form_info_font'> 设备类型 </div> <div class='form_info_font'> 设备名称 </div> <div class='form_info_font'> 系统类型 </div> <div class='form_info_font'>所属工程</div> <div class='form_info_font'>是否在线</div></div>"
);
info.push(
"<div style='font-size: 11px;color:#000;'> <div class='form_info_font1'> " +
showDeviceType(item) +
"</div> <div class='form_info_font1'>" +
item.name +
" </div> <div class='form_info_font1'>" +
showSysType(item) +
"</div> <div class='form_info_font1'> " +
item.sysDept.deptName +
"</div> <div class='form_info_font1'> " +
(item.state == 1 ? "在线" : "离线") +
"</div></div>"
);
infoWindow = new AMap.InfoWindow({
isCustom: true, // 是否自定义窗体
autoMove: true, // 是否自动调整窗体到视野内
offset: new AMap.Pixel(0, -35),
content: info.join(""), //使用默认信息窗体框样式,显示信息内容
});
infoWindow.open(map, context.marker.getPosition());
var closeBtn = document.querySelector(".close-info-window");
if (closeBtn) {
closeBtn.addEventListener("click", function () {
infoWindow.close(map, e.target.getPosition());
});
}
});
context.marker.on("mouseout", function (e) {
infoWindow.close(map, e.target.getPosition());
});
},
}
);
});
})
.catch((e) => {
console.log(e);
});
}
//显示设备类型
var showDeviceType = function (item) {
return item.twoType.name;
};
//显示系统类型
var showSysType = function (item) {
const sysTypeItem = sysType.value.find(
(i) => String(i.value) == String(item.sysType)
);
return sysTypeItem ? sysTypeItem.label : "-";
};
//关闭信息窗体
var closeInfoWindow = function () {
infoWindow.close();
};
//聚合点样式
var _renderClusterMarker = function (context) {
// debugger;
// let clusterCount = context.count; //聚合点内点数量
// let clusterData = context.clusterData; //聚合点数组
// let mainKey = context.index.mainKey; //聚合点对应索引
// let constData = clusterData[0][mainKey]; //当前层级(市/区)展示名
// 构建聚合点的显示内容
let content;
content = `
<div style="display: flex; align-items: center; justify-content: center; text-align: center;">
<img style="width:60px; height: 60px;" src="http://webapi.amap.com/theme/v1.3/m1.png"/>
<div style="font-size: 12px; text-align: center;">${111}</div>
</div>`;
context.marker.setContent(content);
// 自定义点击事件
context.marker.on("click", function (e) {
// touchend 移动端点击事件;mouseup pc点击
// let clickType = e.originEvent.type;
//创建窗体实例
// let infoWindow = new AMap.InfoWindow({
// content: "test", //窗体内容,支持插入dom.innerHTML
// anchor: "top-right", //锚点,窗体相对鼠标点击位置
// });
// //显示窗体
// //map:地图实例,[lng,lat]:窗体在地图中位置
// infoWindow.open(map, [e.lnglat.lng, e.lnglat.lat]);
// let infoWindow = new AMap.InfoWindow({ offset: new AMap.Pixel(0, -30) });
// infoWindow.open(map, [e.lnglat.lng, e.lnglat.lat]);
// 移动端
// if (clusterData.length != 0 && mainKey == "building") {
// setTimeout(() => {
// emits("pointsClick", clusterData); //向父组件传递点位信息
// }, 100);
// }
});
};
onUnmounted(() => {
map?.destroy();
});
function getDeviceList() {
deviceList(
props.deptId,
oneTypeId.value,
twoTypeId.value,
threeTypeId.value,
fourTypeId.value,
fiveTypeId.value,
sixTypeId.value
).then((res) => {
points.value = res.rows;
points.value.forEach((item) => {
item.lnglat = [item.longitude, item.latitude];
item.weight = 1;
});
initMap(); //
});
}
function getDeviceTypeList() {
deviceTypeList().then((res) => {
treeDataList.value = handleTree(res.data, "id");
});
}
getDeviceList();
getDeviceTypeList();
</script>
<style>
.form_info_font {
font-size: 12px;
color: #fff;
margin-left: 25px;
margin-top: 3px;
/* font-family: "YouSheBiaoTiHei"; */
}
.form_info_font1 {
font-size: 12px;
color: #fff;
margin-left: 10px;
margin-top: 3px;
font-family: "YouSheBiaoTiHei";
}
</style>
<template>
<!-- map-container上面加一个下拉框 -->
<div class="map-container w-full h-full relative" id="container">
<div class="absolute top-2 left-2 z-10">
<div class="w-full h-full relative">
<div class="map-container w-full h-full" id="container"></div>
<div class="absolute top-2 left-2 z-[999]">
<el-tree-select
style="width: 150px"
v-model="treeDataValue"
......@@ -35,13 +35,19 @@ let infoWindow = null;
var points = ref([]);
const treeDataValue = ref([]);
const treeDataList = ref([]);
const treeDataAllList = ref([]);
const oneTypeId = ref("");
const twoTypeId = ref("");
const threeTypeId = ref("");
const fourTypeId = ref("");
const fiveTypeId = ref("");
const sixTypeId = ref("");
const map_opt = [
{
city: "太原",
color: "red",
},
];
const props = defineProps({
deptId: {
type: Number,
......@@ -56,7 +62,7 @@ onMounted(() => {
});
function handleSceneChange(val) {
treeDataList.value.forEach((item) => {
treeDataAllList.value.forEach((item) => {
if (item.id === val) {
const parentIds = item.parentIds;
const ids = parentIds
......@@ -83,7 +89,11 @@ function handleSceneChange(val) {
}
}
});
// getDeviceList();
// 先清除现有地图(如果存在)
if (map) {
map.clearMap(); // 清除覆盖物而不是销毁地图
}
getDeviceList();
}
function initMap() {
......@@ -106,6 +116,7 @@ function initMap() {
extensions: "all",
level: "province",
});
district.search("山西", function (status, result) {
// 查询成功时,result即为对应的行政区信息
const bounds = result.districtList[0].boundaries;
......@@ -113,6 +124,7 @@ function initMap() {
for (let i = 0; i < bounds.length; i++) {
mask.push([bounds[i]]);
}
const map = new AMap.Map("container", {
pitch: 30, // 倾斜角度
zoom: 6.7, // 设置当前显示级别
......@@ -133,6 +145,8 @@ function initMap() {
strokeColor: "blue", // 线条颜色,使用16进制颜色代码赋值。默认值为#00D3FC
strokeWeight: 5, // 轮廓线宽度,默认为:2
// map:map // 这种方式相当于: polyline.setMap(map);
fillColor: "#80d8ff", // 填充颜色,使用16进制颜色代码赋值。默认值为#00D3FC
strokeColor: "blue", // 轮廓线颜色,使用16进制颜色代码赋值。默认值为#00D3FC
});
polyline.setMap(map);
}
......@@ -230,46 +244,7 @@ var closeInfoWindow = function () {
infoWindow.close();
};
//聚合点样式
var _renderClusterMarker = function (context) {
// debugger;
// let clusterCount = context.count; //聚合点内点数量
// let clusterData = context.clusterData; //聚合点数组
// let mainKey = context.index.mainKey; //聚合点对应索引
// let constData = clusterData[0][mainKey]; //当前层级(市/区)展示名
// 构建聚合点的显示内容
let content;
content = `
<div style="display: flex; align-items: center; justify-content: center; text-align: center;">
<img style="width:60px; height: 60px;" src="http://webapi.amap.com/theme/v1.3/m1.png"/>
<div style="font-size: 12px; text-align: center;">${111}</div>
</div>`;
context.marker.setContent(content);
// 自定义点击事件
context.marker.on("click", function (e) {
// touchend 移动端点击事件;mouseup pc点击
// let clickType = e.originEvent.type;
//创建窗体实例
// let infoWindow = new AMap.InfoWindow({
// content: "test", //窗体内容,支持插入dom.innerHTML
// anchor: "top-right", //锚点,窗体相对鼠标点击位置
// });
// //显示窗体
// //map:地图实例,[lng,lat]:窗体在地图中位置
// infoWindow.open(map, [e.lnglat.lng, e.lnglat.lat]);
// let infoWindow = new AMap.InfoWindow({ offset: new AMap.Pixel(0, -30) });
// infoWindow.open(map, [e.lnglat.lng, e.lnglat.lat]);
// 移动端
// if (clusterData.length != 0 && mainKey == "building") {
// setTimeout(() => {
// emits("pointsClick", clusterData); //向父组件传递点位信息
// }, 100);
// }
});
};
var _renderClusterMarker = function (context) {};
onUnmounted(() => {
map?.destroy();
......@@ -290,12 +265,13 @@ function getDeviceList() {
item.lnglat = [item.longitude, item.latitude];
item.weight = 1;
});
initMap(); //
initMap();
});
}
function getDeviceTypeList() {
deviceTypeList().then((res) => {
treeDataAllList.value = res.data;
treeDataList.value = handleTree(res.data, "id");
});
}
......@@ -319,4 +295,11 @@ getDeviceTypeList();
margin-top: 3px;
font-family: "YouSheBiaoTiHei";
}
.amap-copyright {
display: none !important;
}
.amap-logo {
display: none !important;
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment