2025-05-16 16:45:03 +08:00

895 lines
20 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>
<div class="divHead">
<label :class="selRight==index?'divHeadSel':''" v-for="(item,index) in arrRight" :key="index"
@click="queryOrders(item.lx,index)">
{{item.name}}
</label>
</div>
<div style="">
<div class="divTag">
<uni-row>
<uni-col :span="8">
<label class="divbgColor mapFont"
style="padding: 5px 10px;border-radius:15px;font-weight: bold;border: 1px solid #80808061;"
@click="onShowDrawer">
<label style="margin-left: 5px;">
<uni-icons custom-prefix="iconfont" type="icon-ebikeqiehuan" :color="iconcolor"
:size="iconsize" />
</label>
切区
</label>
</uni-col>
<uni-col :span="14">
<label style="padding: 5px 15px;border-radius: 15px;background-color: #35374dc2;color: white;">
当前范围内可接单车辆
<label style="margin-left: 5px;">{{orderCount}}</label>
</label>
</uni-col>
</uni-row>
</div>
<div class="divLowerLeft">
<div class="divBtn">
<div style="padding: 10px 10px 5px 10px;">
<uni-icons custom-prefix="iconfont" type="icon-ebikejia" :color="iconcolor" :size="iconsize"
@click="onZoom('out')" />
</div>
<div style="padding: 5px 10px 10px 10px;">
<uni-icons custom-prefix="iconfont" type="icon-ebikejian" :color="iconcolor" :size="iconsize"
@click="onZoom('in')" />
</div>
</div>
<div class="divBtn">
<div class="divBtnTitle" @click="getLocation">
<uni-icons custom-prefix="iconfont" type="icon-ebikedingwei2" :color="iconcolor" :size="iconsize" />
<div>定位</div>
</div>
<div class="divBtnTitle" @click="refreshArea">
<uni-icons custom-prefix="iconfont" type="icon-ebikeshuaxin" :color="iconcolor" :size="iconsize" />
<div>刷新</div>
</div>
<div class="divBtnTitle" style="padding-bottom: 10px;" @click="()=>{showMore=!showMore}">
<uni-icons custom-prefix="iconfont" type="icon-ebikea-gengduo3x" :color="iconcolor"
:size="iconsize" />
<div>更多</div>
</div>
</div>
<div v-if="showMore" class="divLowerLeftMore">
<div class="divBtn divLowerLeftMoreBtn" @click="showRegionData">
<uni-icons custom-prefix="iconfont" type="icon-ebikeP" :color="showRegion?showColor:iconcolor"
:size="iconsize" />
<div :style="{color:showRegion?showColor:iconcolor}">站点</div>
</div>
<div class="divBtn divLowerLeftMoreBtn" @click="showBikeData">
<uni-icons custom-prefix="iconfont" type="icon-ebikedianpingchechongdianzhuang"
:color="showBike?showColor:iconcolor" :size="iconsize" />
<div :style="{color:showBike?showColor:iconcolor}">车辆</div>
</div>
</div>
</div>
<div class="divLowerRight">
<div @click="changeBatteries">
<uni-icons type="scan" :color="iconcolor" :size="iconsize" />
<div>批量换电</div>
</div>
</div>
<div class="divBottom">
<div class="divBottomBack">
<div v-show="showQC">
<uni-row>
<uni-col :span="8">
<div class="divQuantity">
<div class="divQuantityCount" :style="{color:color_down}">{{q_cnt0}}</div>
<div>
<label>
<uni-icons custom-prefix="iconfont" type="icon-ebikedianliang"
:color="color_down" :size="iconsize" />
</label>
低电量
</div>
</div>
</uni-col>
<uni-col :span="8">
<div class="divQuantity">
<div class="divQuantityCount" :style="{color:color_middle}">{{q_cnt2}}</div>
<div>
<label><uni-icons custom-prefix="iconfont" :type="icon-ebikedianliang1"
:color="color_middle" :size="iconsize" />
</label>
中电量
</div>
</div>
</uni-col>
<uni-col :span="8">
<div class="divQuantity">
<div class="divQuantityCount" :style="{color:color_high}">{{q_cnt}}</div>
<div>
<label><uni-icons custom-prefix="iconfont" type="icon-ebikedianliang2"
:color="color_high" :size="iconsize" />
</label>
高电量
</div>
</div>
</uni-col>
</uni-row>
<div style="padding-top: 10px;">
<uni-row>
<uni-col :span="6">
<div style="text-align: right;">电量筛选</div>
</uni-col>
<uni-col :span="16">
<slider show-value block-size="20" :value="quantityCount" :active-color="quantityColor"
:block-color="quantityColor" @change="quantityChange" />
</uni-col>
</uni-row>
</div>
</div>
<div v-show="showQC_info" style="padding: 0px 10px;">
<div style="position:absolute;right:10px;top: -5px;" @click="colseQC_Info">
<uni-icons custom-prefix="iconfont" type="icon-ebikeguanbi" size="20" color="#777777" />
</div>
<devops-home-bikeinfo :data="dataQC" />
</div>
<!-- <div v-show="showQC_info" style="padding: 0px 10px;">
<div style="position:absolute;right:10px;top: -5px;" @click="colseQC_Info">
<uni-icons custom-prefix="iconfont" type="icon-ebikeguanbi" size="20" color="#777777" />
</div>
<div class="divRowQC">
<lable class="lbNoQC">{{dataQC.bikeCode}}</lable>
<label v-for="(item,index) in dataQC.arrTag" :key="index" :class="getTagClass(item.type)">
{{item.title}}
</label>
</div>
<div class="divRowQC" style="color:#adb3b3;font-size: 14px;">
电量刷新时间:{{dataQC.time}}
</div>
<div class="divRowQC" style="display:flex;justify-content: space-between;font-size: 14px;">
<label>
<label :style="{color:dataQC.color}">
<uni-icons custom-prefix="iconfont" :type="dataQC.icon" :color="dataQC.color"
:size="iconsize" />
{{dataQC.soc}}%
</label>
<lable style="color: #00C57C;margin-left: 10px;">
(
<label>
<uni-icons custom-prefix="iconfont" type="icon-ebikecheliangguanli"
color="#00C57C" />
</label>
<label>{{dataQC.distance}}</label>
)
</lable>
</label>
<div style="background-color:#E2F8FF;border-radius:15px;padding: 3px 15px;">
<label>
<uni-icons custom-prefix="iconfont" type="icon-ebikeyinlianglabashengyin"
color="#0084FF" size="16" />
</label>
<label style="color: #0084FF;" @click="findBike">寻车铃</label>
</div>
</div>
<div style="margin-top:15px;display:flex;justify-content:space-between;">
<label class="divBtnBlue" @click="openBikeInfo">车辆详情</label>
<label class="divBtnBlue" @click="openBattery">电池开仓</label>
<label class="divBtnBlue" @click="changeBatteries">完成换电</label>
</div>
</div> -->
</div>
</div>
<uni-drawer ref="showArea" mode="right" :width="300">
<div class="divArea">
<div v-for="(item,index) in arrAreaData" :key="index">
<div style="margin-bottom: 10px;padding-left: 10px;">
<label style="font-size: 1.2rem;">{{item.city}}</label>
</div>
<uni-row>
<uni-col :span="12" v-for="(data,indexd) in item.country" :key="indexd">
<div style="padding:2px 10px;margin-bottom:5px;">
<div style="line-height:30px;text-align:center;border-radius:20rpx;background-color:#8080801a;color:#056cec;"
@click="clickArea(data)">
{{data.name}}
</div>
</div>
</uni-col>
</uni-row>
</div>
</div>
</uni-drawer>
<map :style="{width: '100%',height:height}" show-location id="mapRef" ref="mapRef" :scale="scale"
:markers="markers" :longitude="mapcenter.longitude" :latitude="mapcenter.latitude" :circles="circles"
:polygons="polygons" :polyline="polylines" @markertap="markerTap" @labeltap="markerTap"
@regionchange="regionchange" />
</div>
</template>
<script setup>
import QQMapWX from "@/utils/qqmap-wx-jssdk.js";
import * as map from "@/utils/map.js";
import {
ref,
onMounted,
getCurrentInstance
} from 'vue';
import {
showModelMessage
} from "@/utils/tools.js";
import * as api from "@/utils/api.js";
import {
findIndex,
find
} from "lodash";
import {
useSelarea
} from "@/stores/selarea.js";
var qqmapsdk = new QQMapWX({
key: map.sdkKey
});
const systemInfo = uni.getSystemInfoSync();
const height = (systemInfo.screenHeight - systemInfo.statusBarHeight - 95) + "px";
//权限
const arrRight = ref([{
name: "换电",
lx: "changebatteries"
},
{
name: "调度",
lx: "deploy"
},
{
name: "维修",
lx: "maintenance"
}
]);
const selRight = ref(0);
const mapRef = ref("mapRef");
let mapContext = null;
const iconsize = 16;
const iconcolor = "#6f7777";
const showArea = ref(null);
const mapcenter = ref({
longitude: null,
latitude: null
});
const scale = ref(15);
const markers = ref([]); //点
const polygons = ref([]); //面
const polylines = ref([]);
const circles = ref([]); //圆
let arrMakers = [];
const orderCount = ref(0); //接单数量
const quantityCount = ref(100); // 电量
const color_down = "#EF4B4D"; //低电量
const color_middle = "#F29710"; //中电量
const color_high = "#3DB71A"; //高电量
const quantityColor = ref(color_high);
const q_cnt = ref(0);
const q_cnt0 = ref(0);
const q_cnt2 = ref(0);
const showQC = ref(true);
const showQC_info = ref(false);
const dataQC = ref({
bikeCode: "",
arrTag: [],
time: "",
color: "",
soc: "",
distance: "",
icon: ""
})
let locationPoint = null; //当前行政区划
const arrAreaData = ref(null); //行政区划
const mapData_opt = []; //运营区数据
let selArea = null; //选中行政区划
const selAreaStore = useSelarea();
const showMore = ref(false); //显示更多
const showBike = ref(true); //显示车辆
const showRegion = ref(false); //显示站点
const showColor = "#1088FD";
//加载后
onMounted(() => {
mapContext = map.getMap("mapRef", getCurrentInstance());
getZone((arrData) => {
//获取当前定位
map.getLoalcation(mapContext, (res) => {
const {
latitude: lat,
longitude: lng
} = res;
mapcenter.value = {
latitude: lat,
longitude: lng
};
// mapcenter.value = {
// latitude: 30.644955,
// longitude: 103.978296
// };
map.reverseGeocoder(qqmapsdk, lng, lat, (res) => {
const {
ad_info: {
adcode,
city,
district
}
} = res;
const data = {
id: adcode,
name: district,
lat,
lng
};
locationPoint = {
city: "当前定位" + city,
country: [data]
}
arrData = arrData || [];
arrData.splice(0, 0, locationPoint);
arrAreaData.value = arrData;
changeArea(data);
}, (res) => {
showModelMessage("切换区域失败!");
});
})
});
});
//获取行政区划
function getZone(callback) {
api.callOperateApi("ebikeRegion/getZone", null, "get").then((res) => {
const arrData = [];
const {
code,
data,
message
} = res;
if (code != 200) {
showModelMessage(message);
if (callback) callback(arrData);
return;
}
if (data && data.length > 0) {
data.map(item => {
const {
id,
name,
lng,
lat,
cityName
} = item;
let index = findIndex(arrData, {
city: cityName
});
let oData = arrData[index];
const obj = {
id,
name,
lat,
lng
};
if (index == "-1") {
index = 0;
oData = {
city: cityName,
country: [obj]
}
} else {
oData["country"].push(obj);
}
arrData[index] = oData;
});
}
if (locationPoint) {
arrData.splice(0, 0, locationPoint);
}
if (callback) callback(arrData);
});
}
//定位
function getLocation() {
map.getLoalcation(mapContext, (res) => {
const {
latitude,
longitude
} = res;
scale.value = 13;
})
}
//显示区域
function onShowDrawer() {
showArea.value.open();
}
//切换区域
function clickArea(data) {
changeArea(data);
showArea.value.close();
}
function changeArea(data, refresh) {
const {
id,
lng,
lat
} = data;
selArea = data;
selAreaStore.setValue(id);
const zoneId = id;
mapcenter.value = {
latitude: lat,
longitude: lng
};
let mapDataIndex = findIndex(mapData_opt, {
zoneId
});
if (!refresh) {
if (mapDataIndex > -1) {
loadMapData(mapData_opt[mapDataIndex]);
return;
}
}
uni.showLoading({
title: '加载中'
});
map.getOperation(zoneId, (res) => {
uni.hideLoading();
if (!res) return;
const {
arrRegionID,
arrCircles,
arrPolygons,
arrData
} = res;
let mapdata = {
zoneId,
arrCircles,
arrPolygons,
arrData
};
polygons.value = arrPolygons;
circles.value = arrCircles;
mapDataIndex = mapDataIndex == -1 ? mapData_opt.length : mapDataIndex;
mapData_opt[mapDataIndex] = mapdata;
//站点
if (arrRegionID.length == 0) return;
map.getRegionData(arrRegionID, (res) => {
const {
arrData,
arrCircles,
arrPolygons
} = res;
mapdata = {
...mapdata,
regionData: {
arrData,
arrCircles,
arrPolygons
}
};
mapData_opt[mapDataIndex] = mapdata;
loadMapRegionData(showRegion.value, mapdata);
})
//车辆
map.getBikeData(arrRegionID, (res) => {
const {
arrData,
arrPoints,
icnt,
icnt_0,
icnt_2
} = res;
mapdata = {
...mapdata,
bikeData: {
arrData,
arrPoints
}
};
mapData_opt[mapDataIndex] = mapdata;
q_cnt.value = icnt;
q_cnt0.value = icnt_0;
q_cnt2.value = icnt_2;
arrMakers = arrData;
loadMapBikeData(showBike.value, mapdata);
})
})
/* const params = {
zoneId
}
api.callOperateApi("ebikeRegion/getOperation", params, "get").then((res) => {
uni.hideLoading();
const {
code,
message,
data
} = res;
if (code == 200) {
const arrCircles = [];
const arrPolygons = [];
const arrRegionID = [];
data.map((item, index) => {
const {
shapeType,
regionId,
radius,
points
} = item;
arrRegionID.push(regionId);
const scolor = "#578FD4";
const fcolor = "#C0DAF5";
if (shapeType == 1) {
const {
longitude: lng,
latitude: lat
} = points[0];
arrCircles.push(map.addCirle(scolor, fcolor, lng, lat, radius));
} else if (shapeType == 2) {
const arrPoint = points.map(p => {
return {
longitude: p.longitude,
latitude: p.latitude
}
})
arrPolygons.push(map.addPolygon(scolor, fcolor, arrPoint));
}
});
let mapdata = {
zoneId,
arrCircles,
arrPolygons,
arrData: data
};
polygons.value = arrPolygons;
circles.value = arrCircles;
mapDataIndex = mapDataIndex == -1 ? mapData_opt.length : mapDataIndex;
mapData_opt[mapDataIndex] = mapdata;
//站点
if (arrRegionID.length == 0) return;
map.getRegionData(arrRegionID, (res) => {
const {
arrData,
arrCircles,
arrPolygons
} = res;
mapdata = {
...mapdata,
regionData: {
arrData,
arrCircles,
arrPolygons
}
};
mapData_opt[mapDataIndex] = mapdata;
loadMapRegionData(showRegion.value, mapdata);
//车辆
if (arrRegionID.length == 0) return;
map.getBikeData(arrRegionID, (res) => {
const {
arrData,
arrPoints,
icnt,
icnt_0,
icnt_2
} = res;
mapdata = {
...mapdata,
bikeData: {
arrData,
arrPoints
}
};
mapData_opt[mapDataIndex] = mapdata;
q_cnt.value = icnt;
q_cnt0.value = icnt_0;
q_cnt2.value = icnt_2;
arrMakers = arrData;
loadMapBikeData(showBike.value, mapdata);
})
})
} else {
showModelMessage(message);
}
});
*/
}
//地图数据
function loadMapData(data) {
loadMapBikeData(showBike.value, data);
loadMapRegionData(showRegion.value, data);
}
//显示隐藏车辆
function showBikeData() {
const show = !showBike.value
showBike.value = show;
const {
id
} = selArea;
const data = find(mapData_opt, {
zoneId: id
});
if (!data) return;
loadMapBikeData(show, data);
};
function loadMapBikeData(show, data) {
const {
bikeData
} = data;
if (show) {
if (bikeData) {
const {
arrData,
arrPoints
} = bikeData;
markers.value = arrPoints;
return;
}
}
markers.value = [];
}
//显示隐藏站点
function showRegionData() {
const show = !showRegion.value;
showRegion.value = show;
const {
id
} = selArea;
const data = find(mapData_opt, {
zoneId: id
});
if (!data) return;
loadMapRegionData(show, data);
}
function loadMapRegionData(show, data) {
const {
arrCircles,
arrPolygons,
regionData
} = data;
if (show) {
if (regionData) {
polygons.value = [...arrPolygons, ...regionData.arrPolygons];
circles.value = [...arrCircles, ...regionData.arrCircles];
return;
}
}
polygons.value = arrPolygons;
circles.value = arrCircles;
};
//刷新
function refreshArea() {
changeArea(selArea, true);
}
//缩放
function onZoom(lx) {
switch (lx) {
case "out":
scale.value = scale.value + 1;
break;
case "in":
scale.value = scale.value - 1;
break;
}
}
//电量筛选
function quantityChange(e) {
const {
detail: {
value
}
} = e;
quantityCount.value = value;
const {
color
} = getQCIcon(value);
quantityColor.value = color;
const {
id
} = selArea;
const data = find(mapData_opt, {
zoneId: id
});
if (!data) {
markers.value = [];
return;
}
const arrPoints = [];
const {
bikeData
} = data;
if (!bikeData) return;
const {
arrData
} = bikeData;
arrMakers = [];
arrData.map((item, index) => {
const {
soc
} = item;
if (soc > value) return;
arrMakers.push(item);
arrPoints.push(map.addMarker_Q(index, item));
});
markers.value = arrPoints;
}
function getQCIcon(value) {
let scolor = "";
let icon = "";
if (value <= 20) {
scolor = color_down;
icon = "icon-ebikedianliang";
} else if (value <= 60) {
scolor = color_middle;
icon = "icon-ebikedianliang1";
} else {
scolor = color_high;
icon = "icon-ebikedianliang2";
}
return {
color: scolor,
icon
};
}
//批量换电
function changeBatteries() {
showModelMessage("该功能暂未实现!");
}
//查询工单
function queryOrders(lx, index) {
selRight.value = index;
console.log("11111111111111111111", lx, index)
showModelMessage("该功能暂未实现!");
}
//关闭电量信息
function colseQC_Info() {
showQC.value = true;
showQC_info.value = false;
}
function markerTap(e) {
const {
markerId
} = e.detail;
const selMarker = arrMakers[markerId];
if (!selMarker) {
console.log("markerTap未找到点")
return;
}
const {
updatedAt,
bikeCode,
soc,
state,
usageStatus,
longitude: elng,
latitude: elat
} = selMarker;
if (bikeCode == dataQC.value.bikeCode) {
return;
}
map.getLoalcation(mapContext, (res) => {
const {
latitude: slat,
longitude: slng
} = res;
const options = {
qqmapsdk,
slng,
slat,
elng,
elat,
success: (res) => {
let {
arrPoint,
distance
} = res;
const {
color,
icon
} = getQCIcon(soc);
showQC.value = false;
showQC_info.value = true;
dataQC.value = {
...selMarker,
bikeCode: bikeCode,
arrTag: [{
title: "低电量",
type: "red"
}, {
title: "待使用",
type: "green"
}],
time: updatedAt,
color,
soc: soc,
distance: distance,
icon
}
mapContext.includePoints({
points: arrPoint,
padding: [50, 50, 50, 50], // 视野边缘与点的间距
success: () => {
polylines.value = [map.addLine("#1082FF", arrPoint)]
}
});
},
fail: (res) => {
console.log("fail", res);
}
}
map.direction(options)
}, null, true);
}
function regionchange(e) {
console.log("1111111111111111111111111", e)
// "centerLocation": {
// "latitude": 30.633169,
// "longitude": 103.975094
// },
// "region": {
// "southwest": {
// "latitude": 30.628234,
// "longitude": 103.971932
// },
// "northeast": {
// "latitude": 30.638104,
// "longitude": 103.978255
// }
// }
const {
type,causedBy,region
} = e.detail;
if (type != "end") return;
const minLat= region.southwest.latitude;
const maxLat= region.northeast.latitude;
const minLng=region.southwest.longitude;
const maxLng= region.northeast.longitude;
}
</script>
<style scoped>
@import url("home.css");
</style>