1015 lines
22 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==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;"
@click="navigator.to('/pages/devops/takeOrders/takeOrders')"
>
当前范围内可接单车辆
<label style="margin-left: 5px;">{{orderCount}}</label>
<uni-icons type="right" size="12" color="white"></uni-icons>
</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 v-show="selRight.lx=='hd'" @click="changeBatteries">
<uni-icons type="scan" :color="iconcolor" :size="iconsize" />
<div>换电</div>
</div>
<div v-show="selRight.lx=='dd'" @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 class="divSlider">
<div style="text-align: right;">电量筛选</div>
<div style="flex: 1;">
<slider show-value block-size="20" :value="quantityCount" :active-color="quantityColor"
:block-color="quantityColor" @change="quantityChange" />
</div>
</div>
</div>
<div v-show="showBikeInfo" style="padding: 0px 10px;">
<div style="position:absolute;right:10px;top: -5px;" @click="colseBikeInfo">
<uni-icons custom-prefix="iconfont" type="icon-ebikeguanbi" size="20" color="#777777" />
</div>
<devops-home-bikeinfo :data="dataBikeInfo" />
</div>
<div v-show="showDD">
<div class="divFlex">
<div>
<div class="divCount">
{{dd_count.sxjg}}
</div>
<div class="divCountLabel">
筛选结果
</div>
</div>
<div>
<div class="divCount" :style="{color:color_down}">
{{dd_count.ccyyq}}
</div>
<div class="divCountLabel">
超出运营区域
</div>
</div>
<div>
<div class="divCount" :style="{color:color_middle}">
{{dd_count.bztcq}}
</div>
<div class="divCountLabel">
不在停车区
</div>
</div>
</div>
<div class="divSlider">
<div>无单筛选</div>
<div style="flex: 1;">
<slider show-value block-size="20" :max="showDD_LX_Max" :value="dd_selvalue"
@change="changeDDSelvalue" />
</div>
<div @click="changeDDLX">
<label class="divSliderLable" v-show="showDD_LX===1"> 天数</label>
<label class="divSliderLable" v-show="showDD_LX===2"> 小时</label>
</div>
</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 AMapWX from "@/utils/amap-wx.130.js";
import navigator from '@/utils/navigator.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";
import config from "@/utils/config.js";
var amapsdk = new AMapWX({
key: map.sdkKey
});
const systemInfo = uni.getSystemInfoSync();
const height = (systemInfo.screenHeight - systemInfo.statusBarHeight - 95) + "px";
//权限
const arrRight = ref([{
name: "换电",
lx: "hd"
},
{
name: "调度",
lx: "dd"
},
{
name: "维修",
lx: "wx"
}
]);
const selRight = ref({
index: 0,
...arrRight.value[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(17);
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 showBikeInfo = ref(false);
const dataBikeInfo = ref({
bikeCode: "",
arrTag: [],
time: "",
color: "",
soc: "",
distance: "",
icon: ""
})
const showDD = ref(false);
const showDD_LX = ref(1); // 1天数 2小时
const showDD_LX_Max = ref(7);
const dd_count = ref({
sxjg: 0, //筛选结果
ccyyq: 0, //超出语音区域
bztcq: 0 //不在停车区
});
const dd_selvalue = ref(0); //筛选值
let locationPoint = null; //当前行政区划
const arrAreaData = ref(null); //行政区划
const mapData_opt = []; //运营区数据
let arrSelData=[];
let selArea = null; //选中行政区划
const selAreaStore = useSelarea();
const showMore = ref(false); //显示更多
const showBike = ref(true); //显示车辆
const showRegion = ref(false); //显示站点
const showColor = "#1088FD";
let loadeTime=null;
let minLat = 0;
let maxLat = 0;
let minLng = 0;
let maxLng = 0;
function changeDDSelvalue(e) {
const {
detail: {
value
}
} = e;
dd_selvalue.value = value;
showModelMessage("该功能暂未实现!");
}
//调度查询类型
function changeDDLX() {
let lx = 1;
let max = 7;
if (showDD_LX.value == 1) {
lx = 2;
max = 120;
}
showDD_LX.value = lx;
showDD_LX_Max.value = max;
}
//加载后
onMounted(() => {
mapContext = map.getMap("mapRef", getCurrentInstance());
getLocation();
// setTimeout(()=>{
// generatePoints(1000);
// },2000);
// return;
getZone((arrData) => {
//获取当前定位
map.getLoalcation(mapContext, (res) => {
const {
latitude: lat,
longitude: lng
} = res;
mapcenter.value = {
latitude: lat,
longitude: lng
};
map.reverseGeocoder(amapsdk, lng, lat, (res) => {
const{name,formatted_address,adcode,province,city,district}=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;
mapcenter.value={
longitude:longitude,
latitude:latitude
}
scale.value = 17;
})
}
//显示区域
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
});
loadeTime=Date.now();
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;
const params={
operationRegionId:arrRegionID
}
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_2,
icnt_0,
icnt_1 */
} = res;
arrMakers = arrData;
const{icnt_2,
icnt_0,
icnt_1}=showMarker();
q_cnt.value = icnt_2;
q_cnt0.value = icnt_0;
q_cnt2.value = icnt_1;
mapdata = {
...mapdata,
bikeData: {
arrData,
icnt_2,
icnt_0,
icnt_1
}
};
mapData_opt[mapDataIndex] = mapdata;
//loadMapBikeData(showBike.value, mapdata);
})
})
}
//地图数据
function loadMapData(data) {
const{bikeData:{arrData,icnt_2,
icnt_0,
icnt_1 }}=data;
arrMakers = arrData;
q_cnt.value = icnt_2;
q_cnt0.value = icnt_0;
q_cnt2.value = icnt_1;
showMarker();
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
} = bikeData;
showMarker();
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;
showMarker();
}
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() {
uni.navigateTo({
url: "/pages/devops/changebatteries/changebatteries"
})
}
//查询工单
function queryOrders(lx, index) {
selRight.value = {
index,
...arrRight.value[index]
}
switch (index) {
case 0:
showDD.value = false;
showQC.value = true;
showBikeInfo.value = false;
break;
case 1:
showDD.value = true;
showQC.value = false;
showBikeInfo.value = false;
break;
}
}
//关闭电量信息
function colseBikeInfo() {
const {
lx
} = selRight.value;
switch (lx) {
case "dd":
showDD.value = true;
break;
case "hd":
showQC.value = true;
break;
}
showBikeInfo.value = false;
dataBikeInfo.value={};
polylines.value=[];
}
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 == dataBikeInfo.value.bikeCode) {
return;
}
map.getLoalcation(mapContext, (res) => {
const {
latitude: slat,
longitude: slng
} = res;
const options = {
mapsdk:amapsdk,
slng,
slat,
elng,
elat,
success: (res) => {
let {
arrPoint,
distance
} = res;
const {
color,
icon
} = getQCIcon(soc);
showQC.value = false;
showDD.value = false;
showBikeInfo.value = true;
dataBikeInfo.value = {
...selMarker,
bikeCode: bikeCode,
arrTag: [{
title: "低电量",
type: "red"
}, {
title: "待使用",
type: "green"
}],
time: updatedAt,
color,
soc: soc,
distance: distance,
icon,
rightlx: selRight.value.lx
}
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) {
const {
type,
causedBy,
region,
scale
} = e.detail;
if (type != "end") return;
minLat = region.southwest.latitude;
maxLat = region.northeast.latitude;
minLng = region.southwest.longitude;
maxLng = region.northeast.longitude;
const l=Math.floor((Date.now()-loadeTime)/1000);
if(l>=1){
showMarker();
}
}
function showMarker(){
// let icnt_2 = 0;
// let icnt_0 = 0;
// let icnt_1 = 0;
let oData={};
if(arrMakers.length==0){
orderCount.value=0;
markers.value=[];
}
else{
const{lx}=selRight.value;
const maxcnt=100;
switch(lx){
case "hd":
oData=showMarker_HD(lx,maxcnt);
break;
case "dd":
break;
case "wx":
break;
}
/* let showCount=0;
let arrPoints=[];
let ordercnt=0;
const maxcnt=100;
arrMakers.map((item,index) => {
item = {
...item,
soc: item.soc || 0
}
const {
bikeId,
longitude:lng,
latitude:lat,
soc
} = item;
if (soc <= 20) {
icnt_0++;
} else if (soc <= 60) {
icnt_1++;
} else {
icnt_2++;
}
if(!(lng<=maxLng&&lng>=minLng&&lat<=maxLat&&lat>=minLat)) {
switch(lx){
case "hd":
if(soc>quantityCount.value) return;
break;
case "dd":
break;
case "wx":
break;
}
}
switch(lx){
case "hd":
if(soc<=20) ordercnt++;
break;
case "dd":
break;
case "wx":
break;
}
showCount++;
arrPoints.push(map.addMarker_Q(index, item,showCount>maxcnt,lx));
});
if(showCount>maxcnt){
for(let i=0;i<=maxcnt;i++){
arrPoints[i]={...arrPoints[i],joinCluster:true}
}
} */
orderCount.value=oData.ordercnt;
markers.value=oData.arrPoints;
}
const {icnt_2,icnt_0,icnt_1,showCount,orderCount,arrPoints}=oData
return {icnt_2,icnt_0,icnt_1};
}
function showMarker_HD(lx,maxcnt){
let icnt_2 = 0;
let icnt_0 = 0;
let icnt_1 = 0;
let showCount=0;
let arrPoints=[];
let ordercnt=0;
arrMakers.map((item,index) => {
item = {
...item,
soc: item.soc || 0
}
const {
bikeId,
longitude:lng,
latitude:lat,
soc
} = item;
if (soc <= 20) {
icnt_0++;
} else if (soc <= 60) {
icnt_1++;
} else {
icnt_2++;
}
if(!(lng<=maxLng&&lng>=minLng&&lat<=maxLat&&lat>=minLat) ||soc>quantityCount.value) return;
if(soc<=20) ordercnt++;
showCount++;
arrPoints.push(map.addMarker_Q(index, item,showCount>maxcnt,lx));
});
return {icnt_2,icnt_0,icnt_1,showCount,orderCount,arrPoints};
}
function showMarker_DD(lx,maxcnt){
let icnt_0 = 0;
let icnt_1 = 0;
let icnt_2 = 0;
let showCount=0;
let arrPoints=[];
let ordercnt=0;
arrMakers.map((item,index) => {
const {
bikeId,
longitude:lng,
latitude:lat,
inOperation,
inParking,
intervalTime
} = item;
if(inOperation) {
icnt_1++;
}
else if(inParking) {
icnt_2++;
}
else{
return;
}
if(!(lng<=maxLng&&lng>=minLng&&lat<=maxLat&&lat>=minLat) ) return;
let cnt=dd_selvalue.value;
if(showDD_LX.value=="1") cnt=cnt*24;
if(intervalTime<=cont) ordercnt++;
showCount++;
arrPoints.push(map.addMarker_Q(index, item,showCount>maxcnt,lx));
});
return {icnt_2,icnt_0,icnt_1,showCount,orderCount,arrPoints};
}
</script>
<style scoped>
@import url("home.css");
</style>