|
|
|
@ -1,4 +1,4 @@
@@ -1,4 +1,4 @@
|
|
|
|
|
<template> |
|
|
|
|
`<template> |
|
|
|
|
<div class="amap-designer"> |
|
|
|
|
<div class="headToolbar"> |
|
|
|
|
<ATooltip title="保存并发布" |
|
|
|
@ -15,6 +15,13 @@
@@ -15,6 +15,13 @@
|
|
|
|
|
<Icon icon="fa6-regular:window-restore" size="13"/>任务 |
|
|
|
|
</a-button> |
|
|
|
|
</ATooltip> |
|
|
|
|
<ATooltip title="调整标记点" |
|
|
|
|
placement="bottom" |
|
|
|
|
:arrowPointAtCenter="true"> |
|
|
|
|
<a-button type="primary" @click="handleOpenMapPoint"> |
|
|
|
|
<Icon icon="fa6-regular:window-restore" size="13"/>标记点 |
|
|
|
|
</a-button> |
|
|
|
|
</ATooltip> |
|
|
|
|
<ATooltip title="放大" |
|
|
|
|
placement="bottom" |
|
|
|
|
:arrowPointAtCenter="true"> |
|
|
|
@ -35,7 +42,7 @@
@@ -35,7 +42,7 @@
|
|
|
|
|
<ATooltip title="重置" |
|
|
|
|
placement="bottom" |
|
|
|
|
:arrowPointAtCenter="true"> |
|
|
|
|
<a-button @click=""> |
|
|
|
|
<a-button @click="handleMapReset"> |
|
|
|
|
<Icon icon="fa-solid:database" size="13"/> |
|
|
|
|
</a-button> |
|
|
|
|
</ATooltip> |
|
|
|
@ -49,14 +56,15 @@
@@ -49,14 +56,15 @@
|
|
|
|
|
<p title="隐藏">›</p> |
|
|
|
|
</div> |
|
|
|
|
<div class="operatePanel-form"> |
|
|
|
|
<AForm :labelCol="{ style: { width: '80px' } }" |
|
|
|
|
<AForm ref="formElRef" |
|
|
|
|
:labelCol="{ style: { width: '80px' } }" |
|
|
|
|
:wrapperCol="{ style: { width: '100%', 'margin-right': '10px' } }" |
|
|
|
|
:model="mapState.modelRef" |
|
|
|
|
> |
|
|
|
|
<AFormItem label="发单"> |
|
|
|
|
<ASelect v-model:value="mapState.modelRef.sendOrderId" |
|
|
|
|
:options="mapState.hospitalList" |
|
|
|
|
@select="handleTakeSpecimenSearch" |
|
|
|
|
@select="handleCourierUserSearch" |
|
|
|
|
/> |
|
|
|
|
</AFormItem> |
|
|
|
|
<AFormItem label="起点"> |
|
|
|
@ -68,13 +76,14 @@
@@ -68,13 +76,14 @@
|
|
|
|
|
<BasicTable @register="registerTable"/> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
<TaskModal @register="registerModal" @success="handleRefreshTable"/> |
|
|
|
|
<TaskModal @register="registerModal" @success=""/> |
|
|
|
|
<MapPointModal @register="mapPointRegisterModal" @success=""/> |
|
|
|
|
</div> |
|
|
|
|
</template> |
|
|
|
|
<script lang="ts" setup> |
|
|
|
|
import AMapLoader from '@amap/amap-jsapi-loader'; |
|
|
|
|
import { reactive, watchEffect, getCurrentInstance, onBeforeMount, onUnmounted } from 'vue'; |
|
|
|
|
import { smallHospitalMapList, specimenMapList, columns } from '../amap.data'; |
|
|
|
|
import {reactive, watchEffect, getCurrentInstance, onBeforeMount, onUnmounted, ref} from 'vue'; |
|
|
|
|
import { columns } from '../amap.data'; |
|
|
|
|
import hospital from '/@/assets/images/hospital.svg'; |
|
|
|
|
import medicalKit from '/@/assets/images/medical-kit.svg'; |
|
|
|
|
import hospitalTwinkle from '/@/assets/images/hospital-twinkle.gif'; |
|
|
|
@ -83,19 +92,43 @@
@@ -83,19 +92,43 @@
|
|
|
|
|
import { BasicTable, useTable } from '/@/components/Table'; |
|
|
|
|
import { useModal } from '/@/components/Modal'; |
|
|
|
|
import TaskModal from '../components/TaskModal.vue'; |
|
|
|
|
import MapPointModal from '../components/MapPointModal.vue'; |
|
|
|
|
import { propTypes } from '/@/utils/propTypes'; |
|
|
|
|
import { listHospital } from '/@/api/platform/common/controller/hospital'; |
|
|
|
|
import { listUser } from '/@/api/platform/system/controller/user'; |
|
|
|
|
import { listOrg } from '/@/api/platform/common/controller/org'; |
|
|
|
|
import AButton from "/@/components/Button/src/BasicButton.vue"; |
|
|
|
|
import { Icon } from '/@/components/Icon'; |
|
|
|
|
import { useUserStore } from "/@/store/modules/user"; |
|
|
|
|
import { split } from 'lodash-es'; |
|
|
|
|
import componentSetting from '/@/settings/componentSetting'; |
|
|
|
|
|
|
|
|
|
/** 类型规范统一声明定义区域 */ |
|
|
|
|
type MapCommonType = { |
|
|
|
|
value: string; |
|
|
|
|
label: string; |
|
|
|
|
mapLng: number; |
|
|
|
|
mapLat: number; |
|
|
|
|
mapOrientation: number; |
|
|
|
|
mapNotify?: boolean; |
|
|
|
|
}; |
|
|
|
|
interface MapState { |
|
|
|
|
loading: boolean; |
|
|
|
|
defaultZoom: number; |
|
|
|
|
toggleOperatePanelClass: Recordable; |
|
|
|
|
toggleStatus: boolean; |
|
|
|
|
modelRef: Recordable; |
|
|
|
|
courierUserList: MapCommonType[]; |
|
|
|
|
hospitalList: MapCommonType[]; |
|
|
|
|
orgList: MapCommonType[]; |
|
|
|
|
mapTask: Recordable[]; |
|
|
|
|
mapLogisticPoint: Recordable[]; |
|
|
|
|
mapConfig: Recordable; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const mapProps = defineProps({ |
|
|
|
|
options: propTypes.object.def({ |
|
|
|
|
|
|
|
|
|
}), |
|
|
|
|
sidebarControl: propTypes.bool.def(true), |
|
|
|
|
|
|
|
|
|
mapId: propTypes.string.def(''), |
|
|
|
|
sidebarControl: propTypes.bool.def(true) |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
let map; |
|
|
|
@ -104,8 +137,10 @@
@@ -104,8 +137,10 @@
|
|
|
|
|
let courierUserMarkerCluster; |
|
|
|
|
let scanCourierUserCircleRange; |
|
|
|
|
let driving; |
|
|
|
|
const userStore = useUserStore(); |
|
|
|
|
const instance = getCurrentInstance(); |
|
|
|
|
const mapState = reactive<any>({ |
|
|
|
|
const { mapDesigner } = componentSetting; |
|
|
|
|
const mapState = reactive<MapState>({ |
|
|
|
|
loading: false, |
|
|
|
|
defaultZoom: 1, |
|
|
|
|
toggleOperatePanelClass: { |
|
|
|
@ -125,24 +160,38 @@
@@ -125,24 +160,38 @@
|
|
|
|
|
/** 上级医检集合 */ |
|
|
|
|
orgList: [], |
|
|
|
|
/** 地图任务数据 */ |
|
|
|
|
mapTask: [], |
|
|
|
|
mapTask: [{ |
|
|
|
|
id: '001', |
|
|
|
|
taskName: '测试任务1' |
|
|
|
|
},{ |
|
|
|
|
id: '002', |
|
|
|
|
taskName: '测试任务2' |
|
|
|
|
}], |
|
|
|
|
/** 地图预览点数据 */ |
|
|
|
|
mapLogisticPoint: [] |
|
|
|
|
mapLogisticPoint: [], |
|
|
|
|
/** 地图配置数据 */ |
|
|
|
|
mapConfig: { |
|
|
|
|
amapKey: 'f278d021a80dcf81f071aee5bff08804', |
|
|
|
|
options: { |
|
|
|
|
pitch:60, |
|
|
|
|
viewMode:'3D', |
|
|
|
|
resizeEnable: true, |
|
|
|
|
center: split((userStore.getUserInfo.mapCenter || mapDesigner.mapCenter), ',', 2), |
|
|
|
|
zoom: 17, |
|
|
|
|
keyboardEnable: true |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
const AForm = Form; |
|
|
|
|
const AFormItem = Form.Item; |
|
|
|
|
const ASelect = Select; |
|
|
|
|
const ATooltip = Tooltip; |
|
|
|
|
const formElRef = ref(); |
|
|
|
|
const [registerTable, { reload }] = useTable({ |
|
|
|
|
title: '任务列表', |
|
|
|
|
rowKey: 'id', |
|
|
|
|
dataSource: [{ |
|
|
|
|
id: '001', |
|
|
|
|
taskName: '测试任务1' |
|
|
|
|
},{ |
|
|
|
|
id: '002', |
|
|
|
|
taskName: '测试任务2' |
|
|
|
|
}], |
|
|
|
|
dataSource: mapState.mapTask, |
|
|
|
|
columns, |
|
|
|
|
resizeHeightOffset: 80, |
|
|
|
|
showTableSetting: true, |
|
|
|
@ -151,23 +200,13 @@
@@ -151,23 +200,13 @@
|
|
|
|
|
fullScreen: true |
|
|
|
|
}, |
|
|
|
|
bordered: true, |
|
|
|
|
showIndexColumn: true |
|
|
|
|
showIndexColumn: true, |
|
|
|
|
}); |
|
|
|
|
const [registerModal, { openModal }] = useModal(); |
|
|
|
|
const [mapPointRegisterModal, { openModal: mapPointOpenModal }] = useModal(); |
|
|
|
|
|
|
|
|
|
onBeforeMount(() => { |
|
|
|
|
if (!instance) return; |
|
|
|
|
const mapConfig = { |
|
|
|
|
amapKey: 'f278d021a80dcf81f071aee5bff08804', |
|
|
|
|
options: { |
|
|
|
|
pitch:60, |
|
|
|
|
viewMode:'3D', |
|
|
|
|
resizeEnable: true, |
|
|
|
|
center: [112.919043, 28.288623], |
|
|
|
|
zoom: 17, |
|
|
|
|
keyboardEnable: true |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
mapState.loading = true; |
|
|
|
|
// 初始化地图组件所需数据 |
|
|
|
|
listHospital({ size: 40 }).then(res => { |
|
|
|
@ -201,12 +240,12 @@
@@ -201,12 +240,12 @@
|
|
|
|
|
}); |
|
|
|
|
// 初始化高德地图组件 |
|
|
|
|
AMapLoader.load({ |
|
|
|
|
key: mapConfig.amapKey, |
|
|
|
|
key: mapState.mapConfig.amapKey, |
|
|
|
|
version: '2.0', |
|
|
|
|
plugins: ['AMap.MarkerCluster', 'AMap.Driving'] |
|
|
|
|
}).then(AMap => { |
|
|
|
|
// 创建地图实例 |
|
|
|
|
map = new AMap.Map(instance.refs.mapview, mapConfig.options); |
|
|
|
|
map = new AMap.Map(instance.refs.mapview, mapState.mapConfig.options); |
|
|
|
|
map.plugin(['AMap.ToolBar', 'AMap.MapType', 'AMap.ControlBar', 'AMap.Scale'], () => { |
|
|
|
|
// 地图操作工具条插件 |
|
|
|
|
map.addControl(new AMap.ToolBar()); |
|
|
|
@ -380,6 +419,9 @@
@@ -380,6 +419,9 @@
|
|
|
|
|
zIndex: 50 |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// todo: 修改 |
|
|
|
|
|
|
|
|
|
// 构造路线导航类 |
|
|
|
|
driving = new AMap.Driving({ |
|
|
|
|
map: map, |
|
|
|
@ -396,6 +438,7 @@
@@ -396,6 +438,7 @@
|
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 加载完毕 |
|
|
|
|
complete(); |
|
|
|
|
}).catch(error => { |
|
|
|
@ -440,42 +483,57 @@
@@ -440,42 +483,57 @@
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** 处理收取标本收养员搜索 */ |
|
|
|
|
function handleTakeSpecimenSearch (value) { |
|
|
|
|
/** 处理收样员搜索 */ |
|
|
|
|
function handleCourierUserSearch(value) { |
|
|
|
|
// 查找当前下级医院数据 |
|
|
|
|
const smallHospitalMap = smallHospitalMapList.find(item => item.id == value); |
|
|
|
|
if (smallHospitalMap) { |
|
|
|
|
map.remove(scanTakeSpecimenCircleRange || {}); |
|
|
|
|
scanTakeSpecimenCircleRange.setCenter([smallHospitalMap.lng, smallHospitalMap.lat]); |
|
|
|
|
map.add(scanTakeSpecimenCircleRange); |
|
|
|
|
map.setFitView([ scanTakeSpecimenCircleRange ]); |
|
|
|
|
const smallHospitalMarker = new AMap.Marker({ |
|
|
|
|
position: [smallHospitalMap.lng, smallHospitalMap.lat], |
|
|
|
|
const hospitalMap = mapState.hospitalList.find(item => item.value == value); |
|
|
|
|
if (hospitalMap) { |
|
|
|
|
map.remove(scanCourierUserCircleRange || {}); |
|
|
|
|
scanCourierUserCircleRange.setCenter([hospitalMap.mapLng, hospitalMap.mapLat]); |
|
|
|
|
map.add(scanCourierUserCircleRange); |
|
|
|
|
map.setFitView([ scanCourierUserCircleRange ]); |
|
|
|
|
const hospitalMarker = new AMap.Marker({ |
|
|
|
|
position: [hospitalMap.mapLng, hospitalMap.mapLat], |
|
|
|
|
}); |
|
|
|
|
const smallHospitalPosition = smallHospitalMarker.getPosition(); |
|
|
|
|
// 计算最优先收样员顺序 |
|
|
|
|
const optimalSpecimen = specimenMapList.sort((firstEl, secondEl) => { |
|
|
|
|
const marker1 = new AMap.Marker({ |
|
|
|
|
position: [firstEl.lng, firstEl.lat], |
|
|
|
|
}),marker2 = new AMap.Marker({ |
|
|
|
|
position: [secondEl.lng, secondEl.lat], |
|
|
|
|
const hospitalPosition = hospitalMarker.getPosition(); |
|
|
|
|
// 根据距离优先级排序收养员,方便客服选择收养员 |
|
|
|
|
mapState.courierUserList = mapState.courierUserList.sort((firstEl, secondEl) => { |
|
|
|
|
const originMarker = new AMap.Marker({ |
|
|
|
|
position: [firstEl.mapLng, firstEl.mapLat], |
|
|
|
|
}),destinationMarker = new AMap.Marker({ |
|
|
|
|
position: [secondEl.mapLng, secondEl.mapLat], |
|
|
|
|
}); |
|
|
|
|
const position1 = marker1.getPosition(), |
|
|
|
|
position2 = marker2.getPosition(); |
|
|
|
|
return Math.round(smallHospitalPosition.distance(position1)) - Math.round(smallHospitalPosition.distance(position2)); |
|
|
|
|
const originPosition = originMarker.getPosition(), |
|
|
|
|
destinationPosition = destinationMarker.getPosition(); |
|
|
|
|
return Math.round(hospitalPosition.distance(originPosition)) - Math.round(hospitalPosition.distance(destinationPosition)); |
|
|
|
|
}); |
|
|
|
|
mapState.takeSpecimenList = optimalSpecimen.map(item => ({ value: item.id, label: item.title })); |
|
|
|
|
} else { |
|
|
|
|
throw '查找不到发单点数据,请检查发单点!'; |
|
|
|
|
console.warn('查找不到发单点数据,请检查发单点!'); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** 处理打开任务配置 */ |
|
|
|
|
function handleOpenTask() { |
|
|
|
|
openModal(true, { driving, formData: mapState.modelRef }); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function handleRefreshTable() { |
|
|
|
|
/** 处理打开地图标记点配置 */ |
|
|
|
|
function handleOpenMapPoint() { |
|
|
|
|
mapPointOpenModal(true, { driving }); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** 处理地图重置 */ |
|
|
|
|
function handleMapReset() { |
|
|
|
|
// 清除地图扫描圈 |
|
|
|
|
map.remove(scanCourierUserCircleRange || {}); |
|
|
|
|
// 清除表单数据 |
|
|
|
|
formElRef.value.resetFields(); |
|
|
|
|
formElRef.value.clearValidate(); |
|
|
|
|
// 清除任务数据 |
|
|
|
|
mapState.mapTask = []; |
|
|
|
|
mapState.mapLogisticPoint = []; |
|
|
|
|
// 重置地图画布 |
|
|
|
|
map.setZoomAndCenter(17, mapState.mapConfig.center); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
</script> |
|
|
|
@ -593,3 +651,4 @@
@@ -593,3 +651,4 @@
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
</style> |
|
|
|
|
` |
|
|
|
|