From 0eb5fad72f98251f5421ca55228cb9bdfbc675df Mon Sep 17 00:00:00 2001 From: zk Date: Thu, 23 May 2024 15:05:34 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=9C=B0=E5=9B=BE=E5=85=83?= =?UTF-8?q?=E7=B4=A0=E6=B8=85=E7=A9=BA=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E9=99=84=E8=BF=91=E5=8C=BB=E9=99=A2=E8=B7=AF=E7=BA=BF?= =?UTF-8?q?=E8=A7=84=E5=88=92=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/mapUtils/commonFun.ts | 2 - src/assets/mapUtils/map.ts | 151 ++++++++++++++++- src/assets/mapUtils/mapConstant.ts | 5 +- src/components/chinaMap/chinaHooks.ts | 5 +- src/components/chinaMap/chinaMap.vue | 131 ++++++++++++++- .../chinaMap/components/routePanel.vue | 120 ++++++++++++++ src/enum/pageEnum.ts | 13 +- src/utils/socket.ts | 10 +- src/views/components/emergencyDialog.vue | 38 ++++- src/views/index.vue | 156 +++++++++++++++++- src/views/types.ts | 11 ++ 11 files changed, 611 insertions(+), 31 deletions(-) create mode 100644 src/components/chinaMap/components/routePanel.vue create mode 100644 src/views/types.ts diff --git a/src/assets/mapUtils/commonFun.ts b/src/assets/mapUtils/commonFun.ts index 75d8b05..c814711 100644 --- a/src/assets/mapUtils/commonFun.ts +++ b/src/assets/mapUtils/commonFun.ts @@ -92,5 +92,3 @@ export function getCenter(list = []) { let centerObj = turf.center(features); return centerObj?.geometry?.coordinates; } - -// export function \ No newline at end of file diff --git a/src/assets/mapUtils/map.ts b/src/assets/mapUtils/map.ts index e2edaf0..7edc0dc 100644 --- a/src/assets/mapUtils/map.ts +++ b/src/assets/mapUtils/map.ts @@ -2,7 +2,7 @@ import AMapLoader from '@amap/amap-jsapi-loader'; import china from '/@/assets/lngLat/china.ts'; import chinaInner from '/@/assets/lngLat/chinaInner.ts'; import { createCircle, createIcon, getCenter, getLonLat, typeToIcon } from '/@/assets/mapUtils/commonFun.ts'; -import { aircraftContent, alarmIcon } from '/@/components/chinaMap/chinaHooks.ts'; +import { aircraftContent, alarmIcon, female, male } from '/@/components/chinaMap/chinaHooks.ts'; import { isFunction } from '/@/utils/is.ts'; import { Callback, ExtDataType, InitMap, MarkerOption, ResultType } from '/@/assets/mapUtils/mapFunTypes.ts'; import { defaultOption, getZoom, mapKey, mapPlugin } from '/@/assets/mapUtils/mapConstant.ts'; @@ -17,6 +17,8 @@ export const Map = { placeSearch: null, //地点查询 marker: null, // 健康终端报警 infoWindow: null, //地图弹窗 + driveLine: null, // 导航轨迹线 + emergencyMarker: null, // 应急人员marker /** * @desc 地图舒适化 * @param el dom元素 id选择器 @@ -31,7 +33,6 @@ export const Map = { }).then((res) => { AMap = res; const { zoom, center, mapStyle } = { ...defaultOption, ...option }; - console.log(zoom, center); //基本地图加载 this.map = new AMap.Map(el, { resizeEnable: true, @@ -314,4 +315,150 @@ export const Map = { this.infoWindow = null; } }, + /** + * @desc 计算两个坐标点的距离 + * @param {Array} listA 坐标点数组 + * @param {Array} listB 坐标点数组 + * @return {Number} 距离 + */ + getDistance(listA: number[], listB: number[]) { + let lnglatA = new AMap.LngLat(listA[0], listA[1]); + let lnglatB = new AMap.LngLat(listB[0], listB[1]); + return lnglatA.distance(lnglatB); + }, + /** + * @desc 计算两个坐标点的驾车时间 + * @param {Array} listA 坐标点数组 + * @param {Array} listB 坐标点数组 + * @param {Function} callback 回调 + * @return {Number} 时间 + */ + getDriveTime(listA: number[], listB: number[], callback?: Callback) { + let lnglatA = new AMap.LngLat(listA[0], listA[1]); + let lnglatB = new AMap.LngLat(listB[0], listB[1]); + const drivingOptions = { + policy: AMap.DrivingPolicy.LEAST_TIME, + }; + let driving = new AMap.Driving(drivingOptions); + return new Promise((resolve, reject) => { + driving.search(lnglatA, lnglatB, (status, result) => { + if (status === 'complete') { + // console.log('result', result); + if (callback && isFunction(callback)) { + callback(result); + } + return resolve(result.routes[0]); + } + }); + }); + }, + + /** + * @desc 创建导航轨迹线路 + * @param {Array} listA 坐标点数组 + * @param {Array} listB 坐标点数组 + * + */ + createNaviLine(listA: number[], listB: number[]) { + this.clearNaviLine(); + let lnglatA = new AMap.LngLat(listA[0], listA[1]); + let lnglatB = new AMap.LngLat(listB[0], listB[1]); + const drivingOptions = { + policy: AMap.DrivingPolicy.LEAST_TIME, + map: this.map, + autoFitView: true, + // panel: 'driving-panel', + }; + this.driveLine = new AMap.Driving(drivingOptions); + this.driveLine.search(lnglatA, lnglatB, (status, result) => { + if (status === 'complete') { + // console.log('result', result); + } + }); + this.driveLine.on('error', function (result) { + let str = '定位失败:'; + console.log('error', result); + switch (result.info) { + case 'PERMISSION_DENIED': + str += '浏览器阻止了定位操作'; + break; + case 'POSITION_UNAVAILBLE': + str += '无法获得当前位置'; + break; + case 'TIMEOUT': + str += '定位超时'; + break; + default: + str += '未知错误'; + break; + } + console.log(str); + return false; + }); + }, + /** + * @desc 清除导航轨迹线路 + */ + clearNaviLine() { + if (this.driveLine) { + this.driveLine.clear(); + } + }, + /** + * @desc 创建应急人员Marker + */ + createEmergencyMarker(option) { + this.clearEmergencyMarker(); + const { sex, address, name, position } = option; + const icon = sex == '1' ? female : male; + this.emergencyMarker = new AMap.Marker({ + position: position, + icon: createIcon({ icon: icon, iconSize: [36, 36], imageSize: [36, 36] }), + offset: new AMap.Pixel(0, 0), //设置偏移量 + label: { + content: `
+
${name}
+
${address}
+
`, + offset: new AMap.Pixel(-100, 55), + }, + }); + this.map.add(this.emergencyMarker); + this.setZoomCenter(position); + }, + /** + * @desc 清除应急人员Marker + */ + clearEmergencyMarker() { + if (this.emergencyMarker) { + this.emergencyMarker?.setMap(null); + this.emergencyMarker = null; + } + }, + /** + * @desc 根据坐标获取地址信息 + * @param {Array} list 坐标点数组 + */ + getAddressByPoint(list: number[]) { + const geocoder = new AMap.Geocoder({ + city: '全国', + radius: 1000, + }); + let lnglat = new AMap.LngLat(list[0], list[1]); + return new Promise((resolve, reject) => { + geocoder.getAddress(lnglat, (status, result) => { + if (status === 'complete' && result.regeocode) { + return resolve(result.regeocode.formattedAddress); + } + return reject(result); + }); + }); + }, + /** + * @desc 清除导航元素 + */ + clearNavigationElements() { + this.clearNaviLine(); + this.clearEmergencyMarker(); + }, }; diff --git a/src/assets/mapUtils/mapConstant.ts b/src/assets/mapUtils/mapConstant.ts index e1ff279..0b74702 100644 --- a/src/assets/mapUtils/mapConstant.ts +++ b/src/assets/mapUtils/mapConstant.ts @@ -1,4 +1,4 @@ -// 西安地图默认配置 +// 地图默认配置 export const defaultOption = { center: [108.660704, 36.386058], //地图中心点 zoom: 6.5, //地图显示的缩放级别 @@ -12,7 +12,8 @@ export const YinChuanOption = { // 地图key export const mapKey = '4bbcb216b889f2d612cbed05ae6979c8'; -export const mapPlugin = ['AMap.ToolBar', 'AMap.Driving', 'AMap.GeoJSON', 'AMap.MarkerCluster', 'AMap.PlaceSearch']; +// 地图插件 +export const mapPlugin = ['AMap.ToolBar', 'AMap.Driving', 'AMap.GeoJSON', 'AMap.MarkerCluster', 'AMap.PlaceSearch', 'AMap.Driving', 'AMap.Geocoder']; //根据数据量设置地图层级 export function getZoom(list = []) { diff --git a/src/components/chinaMap/chinaHooks.ts b/src/components/chinaMap/chinaHooks.ts index 5264269..4e9de20 100644 --- a/src/components/chinaMap/chinaHooks.ts +++ b/src/components/chinaMap/chinaHooks.ts @@ -47,7 +47,8 @@ export const tabList = [ export const helicopter = new URL('/@/assets/img/helicopter.png', import.meta.url).href; export const mapbg = new URL('/@/assets/img/helicopter.png', import.meta.url).href; export const alarmIcon = new URL('/@/assets/img/alarm-icon.png', import.meta.url).href; - +export const male = new URL('/@/assets/img/male.png', import.meta.url).href; +export const female = new URL('/@/assets/img/female.png', import.meta.url).href; // 直升机位置数据 export const aircraft = [ { @@ -171,4 +172,4 @@ export function getKmStr(distance: number): string { if (!distance) return ''; let d = convertMetersToKilometers(distance); return d >= 1 ? d + '公里' : d * 100 + '米'; -} \ No newline at end of file +} diff --git a/src/components/chinaMap/chinaMap.vue b/src/components/chinaMap/chinaMap.vue index 83f57e1..2223af2 100644 --- a/src/components/chinaMap/chinaMap.vue +++ b/src/components/chinaMap/chinaMap.vue @@ -36,6 +36,16 @@
暂无数据
+
+ +
+
@@ -58,35 +68,62 @@
累计处置
+ +
+
+
{{ item.name }}
+
相距{{ item.distance }}
+
驾车大约{{ item.driveTime }}
+
+
diff --git a/src/components/chinaMap/components/routePanel.vue b/src/components/chinaMap/components/routePanel.vue new file mode 100644 index 0000000..f65d420 --- /dev/null +++ b/src/components/chinaMap/components/routePanel.vue @@ -0,0 +1,120 @@ + + + diff --git a/src/enum/pageEnum.ts b/src/enum/pageEnum.ts index 15d3994..57e08d5 100644 --- a/src/enum/pageEnum.ts +++ b/src/enum/pageEnum.ts @@ -1,12 +1,10 @@ import { LOGOUT_CURRENT_PATH } from '/@/enum/cacheEnum.ts'; export enum PageEnum { - // basic login path - BASE_LOGIN = '/login', //西安登录页 - BASE_HOME = '/home', //西安首页 - BASE_LOGIN_YINCHUAN = '/screenLogin', //银川登录页 - YINCHUAN_HOME = '/yinChuanHome', //银川首页 - //other + BASE_LOGIN = '/login', + BASE_HOME = '/home', + BASE_LOGIN_YINCHUAN = '/screenLogin', + YINCHUAN_HOME = '/yinChuanHome', } export function setBaseLogin(baseLogin) { @@ -19,9 +17,8 @@ export function getBaseLogin() { //根据当前路径跳转登录页 export function toLoginByNowPath(nowPath: string) { - //西安的页面路径 const xianPath = ['/home', '/secondScreen', '/']; - //银川的页面路径 + const yinchuanPath = ['/yinChuanHome']; if (xianPath.includes(nowPath)) { return PageEnum.BASE_LOGIN; diff --git a/src/utils/socket.ts b/src/utils/socket.ts index 9a8e477..cd7fd06 100644 --- a/src/utils/socket.ts +++ b/src/utils/socket.ts @@ -47,10 +47,10 @@ export function useSocket(p = basicPath) { //这里发送一个心跳,后端收到后,返回一个心跳消息, //onmessage拿到返回的心跳就说明连接正常 if (socket.value.readyState === WebSocket.OPEN) { - console.log('连接正常' + new Date().toLocaleString()); + //console.log('连接正常' + new Date().toLocaleString()); socket.value.send('ping'); } else { - console.log('连接断开'); + //console.log('连接断开'); init(); } self.serverTimeoutObj = setTimeout(function () { @@ -74,7 +74,7 @@ export function useSocket(p = basicPath) { socket.value.onclose = function () { reconnect(path.value); - // console.log('连接关闭', new Date().toLocaleString()); + // //console.log('连接关闭', new Date().toLocaleString()); }; socket.value.onerror = function () { reconnect(path.value); @@ -82,12 +82,12 @@ export function useSocket(p = basicPath) { }; socket.value.onopen = function () { heartCheck.reset().start(); //心跳检测重置 - // console.log('连接成功:' + new Date().toLocaleString()); + // //console.log('连接成功:' + new Date().toLocaleString()); }; socket.value.onmessage = function (event) { //如果获取到消息,心跳检测重置 heartCheck.reset().start(); //拿到任何消息都说明当前连接是正常的 - console.log('收到消息:', event.data); + //console.log('收到消息:', event.data); if (event.data != 'pong') { let data = JSON.parse(event.data); socketData.value = data; diff --git a/src/views/components/emergencyDialog.vue b/src/views/components/emergencyDialog.vue index 1eb445e..4c627a1 100644 --- a/src/views/components/emergencyDialog.vue +++ b/src/views/components/emergencyDialog.vue @@ -3,7 +3,7 @@ diff --git a/src/views/index.vue b/src/views/index.vue index 7a56785..257c20b 100644 --- a/src/views/index.vue +++ b/src/views/index.vue @@ -14,7 +14,7 @@
- +
@@ -24,12 +24,12 @@
- +