增加地图元素清空功能,完成附近医院路线规划功能

This commit is contained in:
zk
2024-05-23 15:05:34 +08:00
parent 1599ffd6d8
commit 0eb5fad72f
11 changed files with 611 additions and 31 deletions
-2
View File
@@ -92,5 +92,3 @@ export function getCenter(list = []) {
let centerObj = turf.center(features); let centerObj = turf.center(features);
return centerObj?.geometry?.coordinates; return centerObj?.geometry?.coordinates;
} }
// export function
+149 -2
View File
@@ -2,7 +2,7 @@ import AMapLoader from '@amap/amap-jsapi-loader';
import china from '/@/assets/lngLat/china.ts'; import china from '/@/assets/lngLat/china.ts';
import chinaInner from '/@/assets/lngLat/chinaInner.ts'; import chinaInner from '/@/assets/lngLat/chinaInner.ts';
import { createCircle, createIcon, getCenter, getLonLat, typeToIcon } from '/@/assets/mapUtils/commonFun.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 { isFunction } from '/@/utils/is.ts';
import { Callback, ExtDataType, InitMap, MarkerOption, ResultType } from '/@/assets/mapUtils/mapFunTypes.ts'; import { Callback, ExtDataType, InitMap, MarkerOption, ResultType } from '/@/assets/mapUtils/mapFunTypes.ts';
import { defaultOption, getZoom, mapKey, mapPlugin } from '/@/assets/mapUtils/mapConstant.ts'; import { defaultOption, getZoom, mapKey, mapPlugin } from '/@/assets/mapUtils/mapConstant.ts';
@@ -17,6 +17,8 @@ export const Map = {
placeSearch: null, //地点查询 placeSearch: null, //地点查询
marker: null, // 健康终端报警 marker: null, // 健康终端报警
infoWindow: null, //地图弹窗 infoWindow: null, //地图弹窗
driveLine: null, // 导航轨迹线
emergencyMarker: null, // 应急人员marker
/** /**
* @desc 地图舒适化 * @desc 地图舒适化
* @param el dom元素 id选择器 * @param el dom元素 id选择器
@@ -31,7 +33,6 @@ export const Map = {
}).then((res) => { }).then((res) => {
AMap = res; AMap = res;
const { zoom, center, mapStyle } = { ...defaultOption, ...option }; const { zoom, center, mapStyle } = { ...defaultOption, ...option };
console.log(zoom, center);
//基本地图加载 //基本地图加载
this.map = new AMap.Map(el, { this.map = new AMap.Map(el, {
resizeEnable: true, resizeEnable: true,
@@ -314,4 +315,150 @@ export const Map = {
this.infoWindow = null; 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: `<div class="alarm-content" style="width: 180px" >
<div style="text-align: center;padding-bottom: 6px">${name}</div>
<div style="text-wrap: wrap">${address}</div>
</div>`,
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();
},
}; };
+3 -2
View File
@@ -1,4 +1,4 @@
// 西安地图默认配置 // 地图默认配置
export const defaultOption = { export const defaultOption = {
center: [108.660704, 36.386058], //地图中心点 center: [108.660704, 36.386058], //地图中心点
zoom: 6.5, //地图显示的缩放级别 zoom: 6.5, //地图显示的缩放级别
@@ -12,7 +12,8 @@ export const YinChuanOption = {
// 地图key // 地图key
export const mapKey = '4bbcb216b889f2d612cbed05ae6979c8'; 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 = []) { export function getZoom(list = []) {
+3 -2
View File
@@ -47,7 +47,8 @@ export const tabList = [
export const helicopter = new URL('/@/assets/img/helicopter.png', import.meta.url).href; 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 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 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 = [ export const aircraft = [
{ {
@@ -171,4 +172,4 @@ export function getKmStr(distance: number): string {
if (!distance) return ''; if (!distance) return '';
let d = convertMetersToKilometers(distance); let d = convertMetersToKilometers(distance);
return d >= 1 ? d + '公里' : d * 100 + '米'; return d >= 1 ? d + '公里' : d * 100 + '米';
} }
+130 -1
View File
@@ -36,6 +36,16 @@
<div v-show="!routeList.length" class="empty-data"> 暂无数据</div> <div v-show="!routeList.length" class="empty-data"> 暂无数据</div>
</div> </div>
</div> </div>
<div v-show="showHospitalList" class="reset-map" @click="resetMap">
<RedoOutlined title="重置地图" />
</div>
<RoutePanel
class="driving-route-panel"
v-show="showDrivingPanel"
:drivingRoute="drivingRoute"
:drivingTitle="drivingTitle"
@out-click="showDrivingPanel = false"
/>
<div style="flex: 1; overflow: hidden; margin: 0 0 10px"> <div style="flex: 1; overflow: hidden; margin: 0 0 10px">
<div id="mapContainer" class="mapContainer"></div> <div id="mapContainer" class="mapContainer"></div>
</div> </div>
@@ -58,35 +68,62 @@
<div class="text">累计处置</div> <div class="text">累计处置</div>
</div> </div>
</div> </div>
<!-- 附近医院医疗点 -->
<div class="hospital-list" v-if="showHospitalList">
<div class="hospital-item" v-for="(item, index) in hospitalList" :key="index" @click="showDrivingLine(item)">
<div>{{ item.name }}</div>
<div>相距{{ item.distance }}</div>
<div>驾车大约{{ item.driveTime }}</div>
</div>
</div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, ref } from 'vue'; import { nextTick, onMounted, ref } from 'vue';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
import { RedoOutlined } from '@ant-design/icons-vue';
import { Map } from '/@/assets/mapUtils/map'; import { Map } from '/@/assets/mapUtils/map';
import { aircraft, getKmStr, getTimeStr, legendList, mapApiSwitch, tabList, TabType } from '/@/components/chinaMap/chinaHooks'; import { aircraft, getKmStr, getTimeStr, legendList, mapApiSwitch, tabList, TabType } from '/@/components/chinaMap/chinaHooks';
import { useDetailStore } from '/@/store/modules/detailData.ts'; import { useDetailStore } from '/@/store/modules/detailData.ts';
import RoutePanel from '/@/components/chinaMap/components/routePanel.vue';
const props = defineProps({ const props = defineProps({
//是否展示底部统计
showFooter: { showFooter: {
type: Boolean, type: Boolean,
default: () => { default: () => {
return true; return true;
}, },
}, },
//地图是否按照接口数据的中心点定位
computedCenter: { computedCenter: {
type: Boolean, type: Boolean,
default: () => { default: () => {
return true; return true;
}, },
}, },
// 地图配置
mapOptions: { mapOptions: {
type: Object, type: Object,
default: () => { default: () => {
return {}; return {};
}, },
}, },
//是否展示最近的三个医院
showHospitalList: {
type: Boolean,
default: () => {
return false;
},
},
hospitalList: {
type: Array,
default: () => {
return [];
},
},
}); });
const emits = defineEmits(['clearHospitalList']);
const useDetail = useDetailStore(); const useDetail = useDetailStore();
const formState = ref({ const formState = ref({
start: '', start: '',
@@ -98,6 +135,7 @@
function changeTab(item, i: number) { function changeTab(item, i: number) {
currentIndex.value = i; // 地方医院 currentIndex.value = i; // 地方医院
Map.clearActiveHospital(); Map.clearActiveHospital();
closeDrivingElement();
Map.map.off('moveend', logMapinfo); Map.map.off('moveend', logMapinfo);
if (TabType.diFangYiYuan == item.type) { if (TabType.diFangYiYuan == item.type) {
Map.removeOverlayGroup(); Map.removeOverlayGroup();
@@ -237,6 +275,36 @@
formState.value.start = ''; formState.value.start = '';
formState.value.end = ''; formState.value.end = '';
} }
// 驾车路线
const drivingRoute = ref([]);
const drivingTitle = ref('');
const showDrivingPanel = ref(false);
function showDrivingLine(item) {
nextTick(() => {
drivingTitle.value = '全程' + item.driveTime + item.distance;
drivingRoute.value = item.routeList?.map((item) => item?.instruction);
showDrivingPanel.value = true;
if (item.lon) {
Map.clearNaviLine();
Map.createNaviLine(item.userLocation, [item.lon, item.lat]);
}
});
}
function closeDrivingElement() {
Map.clearNavigationElements();
formState.value.start = '';
formState.value.end = '';
showDrivingPanel.value = false;
emits('clearHospitalList');
}
function resetMap() {
closeDrivingElement();
changeTab(list.value[currentIndex.value], currentIndex.value);
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.center-map { .center-map {
@@ -409,6 +477,34 @@
} }
} }
.reset-map {
position: absolute;
left: 0;
top: 50px;
z-index: 99;
font-size: 20px;
color: #05d5ff;
cursor: pointer;
background: #243b5d;
padding: 0px 6px;
}
//驾驶路线导航面板
.driving-route-panel {
position: absolute;
right: 0;
top: 86px;
width: 288px;
padding: 9px 18px;
min-height: 200px;
max-height: 473px;
overflow: auto;
background: #2a4164;
border-radius: 2px;
border: 1px solid #1b7ef2;
z-index: 99;
}
.mapContainer { .mapContainer {
flex: 1; flex: 1;
height: calc(100% + 22px); height: calc(100% + 22px);
@@ -472,5 +568,38 @@
} }
} }
} }
.hospital-list {
position: absolute;
bottom: 200px;
width: 800px;
left: 50%;
transform: translateX(-50%);
display: flex;
.hospital-item {
position: relative;
flex: 1;
gap: 20px;
min-width: 230px;
max-width: 230px;
height: 110px;
text-align: center;
padding: 10px;
margin: 0 10px;
color: #fff;
font-size: 16px;
background-color: #00152b;
border: 1px solid #1b7ef2;
border-radius: 12px;
box-shadow: 0 1px 11px 0 rgba(194, 189, 189, 0.5);
cursor: pointer;
}
.hospital-item:hover {
background-color: #192a46;
box-shadow: inset 0px 0px 16px 3px #2562a9;
}
}
} }
</style> </style>
@@ -0,0 +1,120 @@
<template>
<div class="route-panel">
<div v-show="drivingRoute.length" class="has-data">
<div class="line-title">
<div>{{ drivingTitle }}</div>
<div class="close-icon">
<CloseCircleOutlined style="font-size: 16px" @click="outClick" />
</div>
</div>
<div class="line-content">
<div class="start">起点</div>
<div class="line-body">
<div class="line"></div>
<div class="line-desc">
<p v-for="(item, i) in drivingRoute" :key="i">{{ item }}</p>
</div>
</div>
<div class="end">终点</div>
</div>
</div>
<div v-show="!drivingRoute.length" class="empty-data"> 暂无数据</div>
</div>
</template>
<script setup lang="ts">
import { CloseCircleOutlined } from '@ant-design/icons-vue';
const props = defineProps({
drivingRoute: {
type: Array,
default: () => [],
},
drivingTitle: {
type: String,
default: '',
},
});
const emit = defineEmits(['outClick']);
function outClick() {
emit('outClick', false);
}
</script>
<style scoped lang="less">
.route-panel {
.line-title {
position: relative;
margin-bottom: 9px;
font-size: 14px;
font-weight: 700;
color: rgba(255, 255, 255, 0.8);
.close-icon {
position: absolute;
top: 1px;
right: -13px;
}
}
.line-content {
font-size: 12px;
.start {
display: flex;
align-items: center;
&::before {
content: '起';
color: #fff;
width: 20px;
height: 20px;
margin-right: 7px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background: #1478f5;
}
}
.end {
display: flex;
align-items: center;
&::before {
content: '终';
color: #fff;
width: 20px;
height: 20px;
margin-right: 7px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
background: #1478f5;
}
}
.line-body {
display: flex;
//max-height: 370px;
}
.line {
width: 1px;
//max-height: 370px;
background-color: #1478f5;
margin: 5px 19px 5px 8px;
}
.line-sesc {
flex: 1;
}
}
.empty-data {
margin-top: 30%;
text-align: center;
}
}
</style>
+5 -8
View File
@@ -1,12 +1,10 @@
import { LOGOUT_CURRENT_PATH } from '/@/enum/cacheEnum.ts'; import { LOGOUT_CURRENT_PATH } from '/@/enum/cacheEnum.ts';
export enum PageEnum { export enum PageEnum {
// basic login path BASE_LOGIN = '/login',
BASE_LOGIN = '/login', //西安登录页 BASE_HOME = '/home',
BASE_HOME = '/home', //西安首页 BASE_LOGIN_YINCHUAN = '/screenLogin',
BASE_LOGIN_YINCHUAN = '/screenLogin', //银川登录页 YINCHUAN_HOME = '/yinChuanHome',
YINCHUAN_HOME = '/yinChuanHome', //银川首页
//other
} }
export function setBaseLogin(baseLogin) { export function setBaseLogin(baseLogin) {
@@ -19,9 +17,8 @@ export function getBaseLogin() {
//根据当前路径跳转登录页 //根据当前路径跳转登录页
export function toLoginByNowPath(nowPath: string) { export function toLoginByNowPath(nowPath: string) {
//西安的页面路径
const xianPath = ['/home', '/secondScreen', '/']; const xianPath = ['/home', '/secondScreen', '/'];
//银川的页面路径
const yinchuanPath = ['/yinChuanHome']; const yinchuanPath = ['/yinChuanHome'];
if (xianPath.includes(nowPath)) { if (xianPath.includes(nowPath)) {
return PageEnum.BASE_LOGIN; return PageEnum.BASE_LOGIN;
+5 -5
View File
@@ -47,10 +47,10 @@ export function useSocket(p = basicPath) {
//这里发送一个心跳,后端收到后,返回一个心跳消息, //这里发送一个心跳,后端收到后,返回一个心跳消息,
//onmessage拿到返回的心跳就说明连接正常 //onmessage拿到返回的心跳就说明连接正常
if (socket.value.readyState === WebSocket.OPEN) { if (socket.value.readyState === WebSocket.OPEN) {
console.log('连接正常' + new Date().toLocaleString()); //console.log('连接正常' + new Date().toLocaleString());
socket.value.send('ping'); socket.value.send('ping');
} else { } else {
console.log('连接断开'); //console.log('连接断开');
init(); init();
} }
self.serverTimeoutObj = setTimeout(function () { self.serverTimeoutObj = setTimeout(function () {
@@ -74,7 +74,7 @@ export function useSocket(p = basicPath) {
socket.value.onclose = function () { socket.value.onclose = function () {
reconnect(path.value); reconnect(path.value);
// console.log('连接关闭', new Date().toLocaleString()); // //console.log('连接关闭', new Date().toLocaleString());
}; };
socket.value.onerror = function () { socket.value.onerror = function () {
reconnect(path.value); reconnect(path.value);
@@ -82,12 +82,12 @@ export function useSocket(p = basicPath) {
}; };
socket.value.onopen = function () { socket.value.onopen = function () {
heartCheck.reset().start(); //心跳检测重置 heartCheck.reset().start(); //心跳检测重置
// console.log('连接成功:' + new Date().toLocaleString()); // //console.log('连接成功:' + new Date().toLocaleString());
}; };
socket.value.onmessage = function (event) { socket.value.onmessage = function (event) {
//如果获取到消息,心跳检测重置 //如果获取到消息,心跳检测重置
heartCheck.reset().start(); //拿到任何消息都说明当前连接是正常的 heartCheck.reset().start(); //拿到任何消息都说明当前连接是正常的
console.log('收到消息:', event.data); //console.log('收到消息:', event.data);
if (event.data != 'pong') { if (event.data != 'pong') {
let data = JSON.parse(event.data); let data = JSON.parse(event.data);
socketData.value = data; socketData.value = data;
+33 -5
View File
@@ -3,7 +3,7 @@
<Dialog :openVis="visible" width="30%" :title="title" @close="closeDialog" :maskClosable="false"> <Dialog :openVis="visible" width="30%" :title="title" @close="closeDialog" :maskClosable="false">
<template #container> <template #container>
<div class="police-con"> <div class="police-con">
<div class="sub-text">有一个员工刚刚发起应急求助,请马上处理!</div> <div class="sub-text"> 有一个员工刚刚发起应急求助,请马上处理</div>
<div class="con-item"> <div class="con-item">
<span>姓名</span> <span>姓名</span>
<span>{{ userInfo?.realName }}</span> <span>{{ userInfo?.realName }}</span>
@@ -13,25 +13,41 @@
<span>{{ userInfo?.age }}</span> <span>{{ userInfo?.age }}</span>
</div> </div>
<div class="con-item"> <div class="con-item">
<span>二级单位</span> <span>单位</span>
<span>{{ userInfo?.departName }}</span>
</div>
<div class="con-item">
<span>部门</span>
<span>{{ userInfo?.orgName }}</span> <span>{{ userInfo?.orgName }}</span>
</div> </div>
</div> </div>
<div class="btn-box">
<a-button type="primary" @click="confirmHelp">确认</a-button>
</div>
</template> </template>
</Dialog> </Dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Dialog from '/@/components/dialog/Dialog.vue'; import Dialog from '/@/components/dialog/Dialog.vue';
import { useDialog } from '/@/views/components/dialogHooks.ts'; import { useDialog } from '/@/views/components/dialogHooks.ts';
import { watch, ref } from 'vue'; import { watch, ref, Ref } from 'vue';
const props = defineProps({ const props = defineProps({
record: Object, record: Object,
}); });
const userInfo = ref({}); const emit = defineEmits(['confirmHelp']);
interface UserInfo {
realName?: string;
age?: string;
departName?: string;
orgName?: string;
}
const userInfo: Ref<UserInfo> = ref({});
watch( watch(
() => props.record, () => props.record,
(nVal) => { (nVal: UserInfo) => {
userInfo.value = nVal; userInfo.value = nVal;
} }
); );
@@ -40,6 +56,12 @@
defineExpose({ defineExpose({
openDialog, openDialog,
}); });
//确认帮助
function confirmHelp() {
closeDialog();
emit('confirmHelp', userInfo.value);
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.police-con { .police-con {
@@ -51,6 +73,7 @@
.sub-text { .sub-text {
font-weight: bold; font-weight: bold;
margin-left: 8px; margin-left: 8px;
font-size: 16px;
} }
.con-item { .con-item {
@@ -72,4 +95,9 @@
} }
} }
} }
.btn-box {
text-align: center;
margin-top: 2%;
}
</style> </style>
+152 -4
View File
@@ -14,7 +14,7 @@
<three-l :key="tabState" :setting="setting" :refreshState="refreshState" /> <three-l :key="tabState" :setting="setting" :refreshState="refreshState" />
</div> </div>
<div class="body-d-middle"> <div class="body-d-middle">
<china-map /> <china-map :showHospitalList="showHospitalList" :hospitalList="hospitalList" @clearHospitalList="clearHospitalList"></china-map>
</div> </div>
<div class="body-d-right"> <div class="body-d-right">
<one-r :setting="setting" :refreshState="refreshState" /> <one-r :setting="setting" :refreshState="refreshState" />
@@ -24,12 +24,12 @@
</div> </div>
<div class="bottom-d"></div> <div class="bottom-d"></div>
<EmployeeDialog ref="employeeDialogRef" :record="socketData" /> <EmployeeDialog ref="employeeDialogRef" :record="socketData" />
<EmergencyDialog ref="emergencyDialogRef" :record="emergencyData" /> <EmergencyDialog ref="emergencyDialogRef" :record="emergencyData" @confirmHelp="confirmHelp" />
<PhoneDialog ref="phoneDialogRef" :title="phoneDialogTitle" :useForm="true" :setting="setting" :phoneType="phoneType" /> <PhoneDialog ref="phoneDialogRef" :title="phoneDialogTitle" :useForm="true" :setting="setting" :phoneType="phoneType" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onUnmounted, ref, watch, nextTick, onMounted } from 'vue'; import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
import OneL from '/@/components/body-d-left/oneL.vue'; import OneL from '/@/components/body-d-left/oneL.vue';
import TwoL from '/@/components/body-d-left/twoL.vue'; import TwoL from '/@/components/body-d-left/twoL.vue';
import ThreeL from '/@/components/body-d-left/threeL.vue'; import ThreeL from '/@/components/body-d-left/threeL.vue';
@@ -46,6 +46,7 @@
import { DataType, getSettings } from '/@/utils/settings.ts'; import { DataType, getSettings } from '/@/utils/settings.ts';
import { ServerDetailType } from '/@/components/body-d-left/bodyLeftHooks.ts'; import { ServerDetailType } from '/@/components/body-d-left/bodyLeftHooks.ts';
import PhoneDialog from '/@/views/components/phoneDialog/phoneDialog.vue'; import PhoneDialog from '/@/views/components/phoneDialog/phoneDialog.vue';
import { Map } from '/@/assets/mapUtils/map.ts';
const { refreshState } = useRefresh(DEFAULT_TIME); const { refreshState } = useRefresh(DEFAULT_TIME);
const dayTimeO = ref(); const dayTimeO = ref();
@@ -85,6 +86,60 @@
// 健康监测工具报警 // 健康监测工具报警
const { socketData, setSocketData, closeSocket } = useSocket(basicPath + `${DataType.xian}`); const { socketData, setSocketData, closeSocket } = useSocket(basicPath + `${DataType.xian}`);
const employeeDialogRef = ref(); const employeeDialogRef = ref();
//模拟开启
function employeeDialogOpen() {
setEmergencyData({
userId: '001a9878fdaf401c844a03e2fc7c370b',
realName: '曹燕',
lon: 108.872442,
lat: 34.189956,
sex: 2,
age: 40,
orgCode: 'A01A33A05',
orgName: '地质研究所',
hospitalList: [
{
id: null,
name: '交大一附院',
lat: 34.22,
lon: 108.94,
type: null,
ambulance: null,
docNum: null,
nurseNum: null,
expertNum: null,
distance: null,
},
{
id: null,
name: '高新医院',
lat: 34.23,
lon: 108.88,
type: null,
ambulance: null,
docNum: null,
nurseNum: null,
expertNum: null,
distance: null,
},
{
id: null,
name: '人民医院',
lat: 34.24,
lon: 108.93,
type: null,
ambulance: null,
docNum: null,
nurseNum: null,
expertNum: null,
distance: null,
},
],
});
emergencyDialogRef.value.openDialog();
}
watch(socketData, (nVal) => { watch(socketData, (nVal) => {
if (nVal) { if (nVal) {
nextTick(() => { nextTick(() => {
@@ -94,7 +149,7 @@
} }
}); });
//应急求助 + `/${DataType.xian}` //应急求助
const { socketData: emergencyData, setSocketData: setEmergencyData, closeSocket: closeSocket2 } = useSocket(emergencyPath + `${DataType.xian}`); const { socketData: emergencyData, setSocketData: setEmergencyData, closeSocket: closeSocket2 } = useSocket(emergencyPath + `${DataType.xian}`);
const emergencyDialogRef = ref(); const emergencyDialogRef = ref();
@@ -137,6 +192,99 @@
}); });
} }
const hospitalList = ref([]); //医院列表
const showHospitalList = ref(false);
//确认应急求助
async function confirmHelp(data) {
if (!data.lon) return;
hospitalList.value = [];
//用户的坐标信息
let point = [data.lon, data.lat];
if (data.hospitalList.length > 0) {
try {
hospitalList.value = await getHospitalList(data.hospitalList, point);
showHospitalList.value = true;
} catch (error) {
console.log('获取医院列表时出错:', error);
}
}
Map.getAddressByPoint(point).then((res) => {
const option = {
lon: data.lon,
lat: data.lat,
position: point,
name: data.realName,
address: res,
sex: data.sex,
};
Map.createEmergencyMarker(option);
});
}
async function getHospitalList(hospitalList, userLocation) {
const hospitalPromises = hospitalList.map(async (item) => {
item.distance = getDistance(userLocation, [item.lon, item.lat]);
const { time, routeList } = await getDriveTime(userLocation, [item.lon, item.lat]);
item.driveTime = time;
item.routeList = routeList;
item.userLocation = userLocation;
return item; // 返回更新后的医院条目
});
return Promise.all(hospitalPromises);
}
// function getHospitalList(hospitalList, userLocation) {
// hospitalList.forEach(async (item) => {
// item.distance = getDistance(userLocation, [item.lon, item.lat]);
// let { time, routeList } = await getDriveTime(userLocation, [item.lon, item.lat]);
// item.driveTime = time;
// item.routeList = routeList;
// item.userLocation = userLocation;
// console.log('time', item.driveTime);
// });
// return hospitalList;
// }
function getDistance(userLocation, destination) {
const value = Map.getDistance(userLocation, destination);
return value > 1000 ? (value / 1000).toFixed(2) + 'km' : value + 'm';
}
async function getDriveTime(userLocation, destination) {
let { time, steps } = await Map.getDriveTime(userLocation, destination);
let h,
m,
s = 0;
if (time <= 60) {
return {
time: `${s}`,
routeList: steps,
};
}
if (time > 60 && time < 3600) {
m = Math.floor(time / 60);
return {
time: `${m}`,
routeList: steps,
};
}
if (time >= 3600) {
h = Math.floor(time / 3600);
m = Math.floor((time - h * 3600) / 60);
return {
time: `${h}小时${m}`,
routeList: steps,
};
}
}
function clearHospitalList() {
hospitalList.value = [];
showHospitalList.value = false;
}
//地图上绘制
// function test() { // function test() {
// let nVal = { // let nVal = {
// watchNo: 'CRFTQ22C03000080', // watchNo: 'CRFTQ22C03000080',
+11
View File
@@ -0,0 +1,11 @@
export interface HospitalList {
id: string;
name: string;
lat: number;
lon: number;
distance: string;
time: string;
routeList: any[];
[key: string]: any;
}