You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

656 lines
18 KiB

<template>
<div class="map-container">
<div class="input-search" id="targetElement">
<div class="search-box">
8 months ago
<input
type="text"
v-model="searchQuery.carPlate"
placeholder="请输入正确的车牌号"
/>
<i
class="el-icon-error icon-close"
v-show="searchQuery.carPlate"
@click="inputClear()"
></i>
<div class="search-btn" @click="handleSearch()"></div>
</div>
<el-collapse-transition>
<div v-show="show" class="search-list">
8 months ago
<div
class="list-item"
v-for="item in searchList"
:key="item.carId"
@click="handelLookCar(item)"
>
{{ item.carName }}
</div>
<div class="no-data" v-show="searchText">{{ searchText }}</div>
</div>
</el-collapse-transition>
</div>
8 months ago
<div class="albuginea" @click="initTilesetLayer()">
{{ show3D ? "关闭" : "开启" }}三维
</div>
<mars-map @mapLoad="mapLoad" :options="options"></mars-map>
<div class="multiple">
<div
@click="toggleSelection(item)"
:class="{ checkbox: true, checked: isSelected(item) }"
v-for="(item, index) in multipleList"
:key="index"
>
<img
8 months ago
:src="require(`../assets/images/${item}.png`)"
alt=""
class="btn-icon"
/>
{{ item }}
</div>
</div>
8 months ago
<!-- <div id="carMarker" style="display: none"></div> -->
</div>
</template>
<script>
import MarsMap from "@/components/mars-map";
import { getfindByPlateNums } from "@/api/yunkun/index.js";
8 months ago
import { getCarPoint, getCarByCarplate } from "@/api/yunkun/yunkun.js";
8 months ago
export default {
data() {
const basePathUrl = window.basePathUrl || "";
return {
7 months ago
timer: null,
8 months ago
searchList: [],
searchText: "",
8 months ago
searchQuery: {
carPlate: undefined, //车牌
plateColor: undefined, //车辆颜色
},
carQuery: {
teamId: 2, //该参数表示获取指定车队下所有层级子车队的车辆定位该参数优先级别高于carIds参数,
8 months ago
carIds: "", //车辆id 多个用逗号分开优先级低于teamId
},
8 months ago
list: [],
multipleList: ["营运线路", "维护线路", "临时任务"],
selectedItems: [],
graphicLayer: null,
baseUrl: basePathUrl + "lib/geoJson/tileset.json",
8 months ago
carUrl: basePathUrl + "static/qiche.gltf",
map: null,
8 months ago
mapLayer: {},
options: {
scene: {
center: {
8 months ago
lat: 31.019462,
lng: 120.635502,
alt: 13761.4,
heading: 357.9,
pitch: -31.5,
},
8 months ago
fog: false,
fxaa: false,
removeDblClick: true,
requestRenderMode: false,
scene3DOnly: false,
sceneMode: 3,
shadows: false,
showMoon: false,
showSkyAtmosphere: false,
showSkyBox: false,
showSun: false,
},
control: {
8 months ago
contextmenu: { preventDefault: false, hasDefault: false },
},
7 months ago
terrain: {
show: false,
},
basemaps: [
{
name: "影像地图",
type: "xyz",
url: process.env.VUE_APP_BASE_API2 + "/{z}/{y}/{x}.png",
minimumLevel: 1,
maximumLevel: 16,
show: true,
},
// {
// name: "mapbox影像图",
// icon: "img/basemaps/mapboxSatellite.png",
// type: "mapbox",
// username: "sharealex",
// styleId: "cly5i21fn00e901prgq643t4r",
// token:
// "pk.eyJ1Ijoic2hhcmVhbGV4IiwiYSI6ImNsaXNhZmRjbTFhbnczZmxib3h1OW05YXYifQ.PhlKv60ar3K359d8x2yBPw",
// tilesize: 256,
// scaleFactor: false,
// show: true,
// },
],
},
7 months ago
baimoUrl: process.env.VUE_APP_BASE_API3 + "/yunkun/tileset.json",
show: false,
showVideo: true,
8 months ago
show3D: false,
};
},
components: { MarsMap },
beforeDestroy() {
9 months ago
clearInterval(this.timer);
// 在组件销毁之前移除事件监听,防止内存泄漏
document.removeEventListener("click", this.handleClickOutside);
this.mapLayer.car.remove();
this.mapLayer.car = null;
},
8 months ago
mounted() {
// 在mounted钩子中添加全局点击事件监听
document.addEventListener("click", this.handleClickOutside);
},
methods: {
// 搜索下拉框控制
handleClickOutside(event) {
if (
this.show &&
!document.getElementById("targetElement").contains(event.target)
) {
this.show = false;
}
},
/**获取车辆接口 */
async carPoint(isBoole) {
let res = await getCarPoint(this.carQuery);
res.list = res.list.filter((item) => item.stateCn.includes("在线"));
if (isBoole) {
let carPlates = res.list.map((item) => item.carPlate).toString();
let mission = await getfindByPlateNums({
plateNum: carPlates,
});
res.list = res.list.map((item) => {
let missionItem = mission.data.filter(
(it) => it.plateNum == item.carPlate
);
if (missionItem.length > 0) {
let missionType = 1;
if (missionItem[0].missionType == "临时任务") {
missionType = 3;
} else {
missionType = missionItem[0].name.includes("维护") ? 2 : 1;
}
item = {
...item,
...{
missionName: missionItem[0].name,
missionType: missionType,
7 months ago
missionId: missionItem[0].id,
},
};
} else {
item = {
...item,
...{
missionName: "未识别",
missionType: 1,
7 months ago
missionId: null,
},
};
}
return item;
});
}
return res.list;
},
8 months ago
/**
8 months ago
* 加载姑苏区三维图层
8 months ago
*/
8 months ago
initTilesetLayer() {
if (this.map) {
if (!this.mapLayer.tiles3dLayer) {
this.mapLayer.tiles3dLayer = new mars3d.layer.TilesetLayer({
name: "姑苏区建筑物",
7 months ago
url: this.baimoUrl,
8 months ago
maximumScreenSpaceError: 16,
maximumMemoryUsage: 1024 / 2,
dynamicScreenSpaceError: false,
skipLevelOfDetail: true,
preferLeaves: true,
flyTo: false,
style: {
color: {
conditions: [["true", `color("rgba(42, 160, 224, 1)")`]],
},
},
});
this.map.addLayer(this.mapLayer.tiles3dLayer);
this.show3D = true;
} else {
this.mapLayer.tiles3dLayer.show = !this.mapLayer.tiles3dLayer.show;
this.show3D = !this.show3D;
}
} else {
}
},
8 months ago
/**地图渲染完毕 */
mapLoad(map) {
this.map = map;
map.fixedLight = true; // 固定光照避免gltf模型随时间存在亮度不一致。
// 创建矢量图层
this.mapLayer.car = new mars3d.layer.GraphicLayer();
this.map.addLayer(this.mapLayer.car);
this.createCar();
9 months ago
},
7 months ago
/**创建车辆 苏E17360*/
async createCar(type) {
this.list = await this.carPoint(true);
8 months ago
this.mapLayer.car.clear();
this.mapLayer.car.enabledEvent = false; // 关闭事件大数据addGraphic时影响加载时间
for (let index = 0; index < this.list.length; index++) {
let item = this.list[index];
if (item.missionId) {
//只显示有任务的车辆
const graphic = new mars3d.graphic.ModelEntity({
id: `car${item.carId}`,
// position: new mars3d.LngLatPoint(
// parseFloat(item.lng),
// parseFloat(item.lat),
// 30
// ),
style: {
url: this.carUrl,
scale: 0.5,
minimumPixelSize: 32,
8 months ago
silhouette: true,
silhouetteColor: "#008cff",
pitch: 0, //俯仰角
roll: 0, //翻滚角
highlight: {
type: "click",
silhouette: true,
silhouetteColor: "#FFB200",
},
9 months ago
},
8 months ago
circle: {
radius: 200,
fill: false,
materialType: mars3d.MaterialType.CircleWave,
materialOptions: {
color: "#FFB200",
count: 2,
speed: 6,
},
},
attr: {
index: item.carId,
missionId: item.missionId,
missionName: item.missionName,
missionType: item.missionType,
8 months ago
},
});
this.mapLayer.car.addGraphic(graphic);
this.mapLayer.car.enabledEvent = true; // 恢复事件
graphic.bindPopup(
() => {
let html = `<div id="car${item.carId}" class="carPlate">
<img src="${require(`../assets/images/carType${item.missionType}.png`)}" class="carType"/>
${item.carPlate}
</div>`;
return html;
8 months ago
},
{
closeButton: false, //去除关闭按钮
className: "car-page-popup",
pointerEvents: false, //DIV是否可以鼠标交互为false时可以穿透操作及缩放地图但无法进行鼠标交互及触发相关事件。
closeOnClick: false, //是否在单击Map地图时自动关闭当前弹窗
autoClose: false, //在打开弹窗时,是否自动关闭之前的弹窗
toggle: false, //是否打开状态下再次单击时关闭Popup
}
);
graphic.openPopup();
graphic.on(mars3d.EventType.highlightOpen, (e) => {
e.target.setOptions({
//添加圆效果
circle: {
fill: true,
},
});
this.handleCarActive({
id: e.target._id,
color: "#FFB200",
image: require(`../assets/images/carType${e.target.attr.missionType}-s.png`),
});
8 months ago
});
graphic.on(mars3d.EventType.highlightClose, (e) => {
e.target.setOptions({
circle: {
fill: false,
},
});
this.handleCarActive({
id: e.target._id,
color: "#008cff",
image: require(`../assets/images/carType${e.target.attr.missionType}.png`),
});
8 months ago
});
this.$nextTick(() => {
if (type) {
console.log(type);
// 开启高亮
graphic.openHighlight();
}
});
graphic.on(mars3d.EventType.click, (e) => {
const attr = e.target.attr;
if (!attr.missionId) {
this.$modal.msgError("该车辆暂无任务!");
return;
}
this.$router.push({
path: "/carInfo",
query: {
carId: e.target.attr.index,
missionId: attr.missionId,
missionName: item.missionName,
},
});
8 months ago
});
}
8 months ago
}
// 定时更新动态位置setInterval为演示
this.changePosition(0);
7 months ago
const interval = 10;
this.changePosition(interval);
//生产环境开启轮询
if (process.env.NODE_ENV === "production") {
this.time = setInterval(() => {
this.changePosition(interval);
}, interval * 1000);
}
9 months ago
},
async changePosition(interval) {
let list = await this.carPoint();
8 months ago
this.mapLayer.car.eachGraphic((graphic) => {
if (!graphic.show) return;
let carItam = list.filter((car) => `car${car.carId}` == graphic.id);
if (carItam.length > 0) {
let position = Cesium.Cartesian3.fromDegrees(
parseFloat(carItam[0].lng),
parseFloat(carItam[0].lat),
30
);
graphic.addDynamicPosition(position, interval); // 按time秒运动至指定位置
}
8 months ago
});
},
8 months ago
/**
* 处理车辆被选中
*/
handleCarActive(data) {
let carItem = document.getElementById(data.id);
// console.log(data, carItem);
8 months ago
let carIcon = carItem.getElementsByClassName("carType")[0];
carIcon.src = data.image;
carItem.style.borderColor = data.color;
},
/**根据车牌号查询车辆实时定位 */
async handleSearch() {
7 months ago
if (!this.searchQuery.carPlate) {
this.inputClear();
return;
}
// 清除轮询定时器
if (this.timer) clearInterval(this.timer);
const result = await getCarByCarplate(this.searchQuery);
if (result.list) {
7 months ago
if (result.list[0].stateCn.includes("离线")) {
this.$modal.msgError(`该车${result.list[0].stateCn}!`);
return;
}
this.searchList = result.list;
} else {
this.searchText = result.rspDesc;
}
8 months ago
this.show = true;
8 months ago
},
/**单击搜索结果 */
handelLookCar(item) {
this.carQuery.teamId = undefined;
this.carQuery.carIds = item.carId;
this.map.flyToPoint(
new mars3d.LngLatPoint(parseFloat(item.lng), parseFloat(item.lat))
);
this.createCar(true);
this.show = false;
},
/**
* 清除操作
*/
inputClear() {
if (this.timer) clearInterval(this.timer);
this.searchList = [];
this.searchText = "";
this.searchQuery = {
carPlate: undefined, //车牌
plateColor: undefined, //车辆颜色
};
this.carQuery = {
teamId: 2, //该参数表示获取指定车队下所有层级子车队的车辆定位该参数优先级别高于carIds参数,
carIds: "", //车辆id 多个用逗号分开优先级低于teamId
};
this.mapLayer.car.eachGraphic((graphic) => {
graphic.closeHighlight();
8 months ago
});
this.createCar();
this.show = false;
8 months ago
},
toggleSelection(item) {
// 切换选中状态
if (this.isSelected(item)) {
this.selectedItems = this.selectedItems.filter(
(selectedItem) => selectedItem !== item
);
} else {
this.selectedItems.push(item);
}
7 months ago
if (this.selectedItems.length == 0) {
this.mapLayer.car.eachGraphic((graphic) => {
if (graphic.show) return;
graphic.show = true;
graphic.openPopup();
});
7 months ago
return;
}
7 months ago
this.mapLayer.car.eachGraphic((graphic) => {
let missionTetx =
graphic.attr.missionType == 1
? "营运线路"
: graphic.attr.missionType == 2
? "维护线路"
: "临时任务";
if (this.selectedItems.includes(missionTetx)) {
if (!graphic.show) return;
graphic.show = false;
graphic.closePopup();
} else {
if (graphic.show) return;
graphic.show = true;
graphic.openPopup();
}
});
},
isSelected(item) {
// 检查某个项是否被选中
return this.selectedItems.includes(item);
},
},
};
</script>
<style lang="scss" scoped>
8 months ago
.albuginea {
cursor: pointer;
position: absolute;
top: 103px;
8 months ago
left: calc(554px + 24px);
8 months ago
z-index: 100;
width: 80px;
height: 32px;
text-align: center;
line-height: 32px;
background: #032b57;
border-radius: 2px;
border: 1px solid #0084ff;
font-weight: 400;
font-size: 14px;
color: #ffffff;
}
.albuginea:hover {
background: #0084ff;
}
.input-search {
position: absolute;
8 months ago
top: 103px;
left: 50%;
transform: translateX(-50%);
9 months ago
z-index: 100;
.search-box {
8 months ago
position: relative;
display: flex;
align-items: center;
height: 32px;
8 months ago
.icon-close {
cursor: pointer;
position: absolute;
left: 260px;
font-size: 14px;
color: #0084ff;
}
}
.search-btn {
cursor: pointer;
line-height: 32px;
background: #0084ff;
color: #ffffff;
font-size: 14px;
padding: 0 10px;
height: 100%;
border-radius: 0 3px 3px 0;
}
input {
font-size: 14px;
width: 280px;
height: 100%;
border: 1px solid #0084ff;
border-right: 0;
background: #032b57;
padding-left: 6px;
color: #ffffff;
}
input::placeholder {
color: #7c91a8;
}
input:focus-visible {
outline: none;
}
.search-list {
position: relative;
width: 280px;
background: #032b57;
color: #fff;
border: 1px solid #0084ff;
border-top: 0;
min-height: 150px;
& > div {
8 months ago
cursor: pointer;
font-size: 14px;
padding: 10px;
}
& > div:hover {
background: #0084ff;
}
.no-data {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.no-data:hover {
background: transparent;
}
}
}
.video-list {
position: absolute;
bottom: 25px;
left: 50%;
transform: translateX(-50%);
z-index: 50;
padding: 10px;
display: flex;
align-items: center;
border: 1px solid #415367;
border-radius: 10px;
background: rgba(28, 31, 34, 0.6);
}
.multiple {
position: absolute;
8 months ago
bottom: 20px;
left: 50%;
transform: translateX(-50%);
8 months ago
z-index: 100;
width: 880px;
height: 80px;
display: flex;
align-items: center;
justify-content: space-between;
background: url("../assets/images/multipleList.png");
background-size: 100% 100%;
8 months ago
padding: 0 220px;
.checkbox {
cursor: pointer;
width: 112px;
height: 32px;
line-height: 32px;
text-align: center;
font-size: 14px;
color: #ffffff;
background: linear-gradient(180deg, #072853 0%, #0079ff 100%);
border: 1px solid #0084ff;
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
8 months ago
opacity: 1;
}
.checked {
8 months ago
opacity: 0.5;
}
.btn-icon {
width: 15px;
height: 16px;
margin-right: 10px;
}
}
</style>