Browse Source

调整地图设计器数据结构

master
wangxiang 3 years ago
parent
commit
bd3420dff7
  1. 36
      src/components/AMap/src/AMapDesigner/index.vue
  2. 48
      src/components/AMap/src/amap.data.ts
  3. 293
      src/components/AMap/src/components/MapTaskModal.vue
  4. 2
      src/utils/dateUtil.ts
  5. 2
      src/views/system/config/index.vue

36
src/components/AMap/src/AMapDesigner/index.vue

@ -109,7 +109,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import AMapLoader from '@amap/amap-jsapi-loader'; import AMapLoader from '@amap/amap-jsapi-loader';
import { reactive, watchEffect, getCurrentInstance, onBeforeMount, onUnmounted, ref } from 'vue'; import { reactive, watchEffect, getCurrentInstance, onBeforeMount, onUnmounted, ref } from 'vue';
import { operatePanelColumns } from '../amap.data'; import { operatePanelColumns, MapData, MapPointType } from '../amap.data';
import hospital from '/@/assets/images/hospital.svg'; import hospital from '/@/assets/images/hospital.svg';
import medicalKit from '/@/assets/images/medical-kit.svg'; import medicalKit from '/@/assets/images/medical-kit.svg';
import hospitalTwinkle from '/@/assets/images/hospital-twinkle.gif'; import hospitalTwinkle from '/@/assets/images/hospital-twinkle.gif';
@ -132,45 +132,19 @@
import { commonUpload } from '/@/api/platform/core/controller/upload'; import { commonUpload } from '/@/api/platform/core/controller/upload';
/** 类型规范统一声明定义区域 */ /** 类型规范统一声明定义区域 */
type MapCommonType = {
value: string;
label: string;
mapLng: number;
mapLat: number;
mapOrientation: number;
mapNotify?: boolean;
};
interface MapState { interface MapState {
loading: boolean; loading: boolean;
defaultZoom: number; defaultZoom: number;
toggleOperatePanelClass: Recordable; toggleOperatePanelClass: Recordable;
toggleStatus: boolean; toggleStatus: boolean;
courierUserList: MapCommonType[]; courierUserList: MapPointType[];
hospitalList: MapCommonType[]; hospitalList: MapPointType[];
orgList: MapCommonType[]; orgList: MapPointType[];
mapConfig: { mapConfig: {
amapKey: string; amapKey: string;
options: Recordable; options: Recordable;
}; };
mapData: { mapData: MapData;
name: string;
courierUserId: string;
courierUserName: string;
courierLng: number | undefined;
courierLat: number | undefined;
sendOrderId: string;
sendOrderName: string;
sendOrderLng: number | undefined;
sendOrderLat: number | undefined;
fileId: string[];
estimateTime: string;
requireTime: string;
/** 地图任务数据 */
mapTask: Recordable[];
/** 地图预览点数据 */
mapLogisticPoint: Recordable[];
[key: string]: any;
};
rulesRef: Recordable; rulesRef: Recordable;
} }

48
src/components/AMap/src/amap.data.ts

@ -13,26 +13,34 @@ import { Tag } from 'ant-design-vue';
* @create: 2022/5/22 * @create: 2022/5/22
*/ */
type mapType = { export type MapPointType = {
id: string; value: string;
title: string; label: string;
orientation: number; mapLng: number;
lng: number; mapLat: number;
lat: number; mapOrientation: number;
notify?: boolean; mapNotify?: boolean;
}; };
export const largeHospitalMapList: mapType[] = [ export interface MapData {
{id: '001', title: '上级医检医院:金域', orientation: 0, lng: 112.919043, lat: 28.288623}, name: string;
{id: '002', title: '上级医检医院:康来', orientation: 0, lng: 112.919165, lat: 28.289924}, courierUserId: string;
{id: '003', title: '上级医检医院:附一', orientation: 0, lng: 112.919965, lat: 28.289924} courierUserName: string;
]; courierLng: number | undefined;
courierLat: number | undefined;
export const smallHospitalMapList: mapType[] = [ sendOrderId: string;
{id: '001', title: '下级医院:湘雅医院', orientation: 0, lng: 112.918119, lat: 28.282891, notify: true}, sendOrderName: string;
{id: '002', title: '下级医院:神经病医院', orientation: 0, lng: 112.918919, lat: 28.282991, notify: true}, sendOrderLng: number | undefined;
{id: '003', title: '下级医院:第三医院', orientation: 0, lng: 112.918019, lat: 28.283991, notify: true} sendOrderLat: number | undefined;
]; fileId: string[];
estimateTime: string;
requireTime: string;
/** 地图任务数据 */
mapTask: Recordable[];
/** 地图预览点数据 */
mapLogisticPoint: Recordable[];
[key: string]: any;
}
/** 操作面板表格列 */ /** 操作面板表格列 */
export const operatePanelColumns: BasicColumn[] = [ export const operatePanelColumns: BasicColumn[] = [
@ -180,6 +188,10 @@ export const taskPresetColumns: BasicColumn[] = [
}*/ }*/
]; ];
export const formMutualTaskSettingColumns: BasicColumn[] = [ export const formMutualTaskSettingColumns: BasicColumn[] = [
{ {
title: '收样员', title: '收样员',

293
src/components/AMap/src/components/MapTaskModal.vue

@ -1,75 +1,110 @@
<template> <template>
<BasicModal v-bind="$attrs" <BasicModal v-bind="$attrs"
:width="920" :width="990"
@register="registerModal" @register="registerModal"
@ok="handleSubmit" @ok="handleSubmit"
> >
<BasicTable @register="registerTable"> <!--普通任务表格-->
<BasicTable @register="taskOrdinaryRegisterTable">
<template #toolbar> <template #toolbar>
<a-button type="primary" <a-button type="primary"
@click="handleTaskAdd()" @click="handleTaskOrdinaryAdd"
>新增</a-button> >新增</a-button>
</template> </template>
<template #action="{ record, column }"> <template #action="{ record, column }">
<TableAction :actions="createActions(record, column)"/> <TableAction :actions="createTaskOrdinaryActions(record, column).concat([
{
label: '删除',
icon: 'ant-design:delete-outlined',
color: 'error',
onClick: handleTaskOrdinaryDelete.bind(null, record)
}
])"
/>
</template> </template>
</BasicTable> </BasicTable>
<BasicTable @register="schemeRegisterTable"> <!--交接任务表格-->
<BasicTable @register="taskPresetRegisterTable">
<template #toolbar> <template #toolbar>
<a-button type="primary" <a-button type="primary"
@click="handleMutualTaskAdd()" @click="handleTaskPresetAdd"
>新增</a-button> >新增</a-button>
</template> </template>
<template #action="{ record, column }"> <template #action="{ record, column }">
<TableAction :actions="[ <TableAction :actions="createTaskPresetActions(record, column).concat([
{ {
label: '转办', label: '转办',
icon: 'fa6-regular:pen-to-square', icon: 'fa6-regular:pen-to-square',
onClick: handleMutualTask.bind(null, record) onClick: handleOpenTaskPreset.bind(null, record)
}]" },
{
label: '删除',
icon: 'ant-design:delete-outlined',
color: 'error',
onClick: handleTaskPresetDelete.bind(null, record)
}
])"
/> />
<TableAction :actions="createMutualActions(record, column)"/>
</template> </template>
</BasicTable> </BasicTable>
<TaskPresetModal @register="taskPresetRegisterModal" @success=""/> <TaskPresetModal @register="taskPresetRegisterModal" @success="handleTaskPreset"/>
</BasicModal> </BasicModal>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive } from 'vue'; import { reactive } from 'vue';
import {BasicModal, ModalProps, useModal, useModalInner} from '/@/components/Modal'; import {BasicModal, ModalProps, useModal, useModalInner} from '/@/components/Modal';
import { BasicTable, useTable, EditRecordRow, BasicColumn, ActionItem, TableAction } from '/@/components/Table'; import { BasicTable, useTable, EditRecordRow, BasicColumn, ActionItem, TableAction } from '/@/components/Table';
import { taskColumns, taskPresetColumns, largeHospitalMapList, smallHospitalMapList, } from '../amap.data'; import { taskColumns, taskPresetColumns, MapData } from '../amap.data';
import { buildUUID } from '/@/utils/uuid';
import TaskPresetModal from './MapTaskPresetModal.vue'; import TaskPresetModal from './MapTaskPresetModal.vue';
import { buildUUID } from '/@/utils/uuid';
import { useMessage } from '/@/hooks/web/useMessage';
/** 类型规范统一声明定义区域 */ /** 类型规范统一声明定义区域 */
interface WindowState { interface WindowState {
currentEditKeyRef: string; taskOrdinaryCurrentEditKeyRef: string;
formData: Recordable; taskPresetCurrentEditKeyRef: string;
mapData: MapData | undefined;
} }
/** 通用变量统一声明区域 */ /** 通用变量统一声明区域 */
let driving;
const state = reactive<WindowState>({ const state = reactive<WindowState>({
currentEditKeyRef: '', taskOrdinaryCurrentEditKeyRef: '',
formData: {} taskPresetCurrentEditKeyRef: '',
}); mapData: {
const mutualState = reactive<WindowState>({ name: '',
currentEditKeyRef: '', courierUserId: '',
formData: {} courierUserName: '',
courierLng: undefined,
courierLat: undefined,
sendOrderId: '',
sendOrderName: '',
sendOrderLng: undefined,
sendOrderLat: undefined,
fileId: [],
estimateTime: '',
requireTime: '',
/** 地图任务数据 */
mapTask: [],
/** 地图预览点数据 */
mapLogisticPoint: [],
}
}); });
const emit = defineEmits(['success', 'register']); const emit = defineEmits(['success', 'register']);
const [registerModal, { setModalProps, closeModal }] = useModalInner(async data => { const [registerModal, { setModalProps, closeModal }] = useModalInner(async data => {
driving = data.driving; state.mapData.formData = data.formData;
state.formData = data.formData;
const props: Partial<ModalProps> = { confirmLoading: false }; const props: Partial<ModalProps> = { confirmLoading: false };
props.title = '任务配置'; props.title = '任务配置';
// : // :
setModalProps(props); setModalProps(props);
}); });
const { createMessage } = useMessage();
const [taskPresetRegisterModal, { openModal }] = useModal(); const [taskPresetRegisterModal, { openModal }] = useModal();
const [registerTable, { reload, getDataSource }] = useTable({ const [taskOrdinaryRegisterTable, {
reload: taskOrdinaryReload,
getDataSource: getTaskOrdinaryDataSource,
setTableData: setTaskOrdinaryTableData
}] = useTable({
rowKey: 'id',
title: '普通任务', title: '普通任务',
columns: taskColumns, columns: taskColumns,
pagination: { pagination: {
@ -89,7 +124,12 @@
slots: { customRender: 'action' }, slots: { customRender: 'action' },
} }
}); });
const [schemeRegisterTable, { reload: schemeReload, getDataSource: getTaskPresetDataSource, setProps }] = useTable({ const [taskPresetRegisterTable, {
reload: taskPresetReload,
getDataSource: getTaskPresetDataSource,
setTableData: setTaskPresetTableData
}] = useTable({
rowKey: 'id',
title: '交接任务', title: '交接任务',
columns: taskPresetColumns, columns: taskPresetColumns,
pagination: { pagination: {
@ -103,165 +143,162 @@
showIndexColumn: false, showIndexColumn: false,
canResize: false, canResize: false,
actionColumn: { actionColumn: {
width: 160, width: 240,
title: '操作', title: '操作',
dataIndex: 'action', dataIndex: 'action',
slots: { customRender: 'action' }, slots: { customRender: 'action' },
} }
}); });
/** 处理任务新增 */ /** 处理普通任务新增 */
function handleTaskAdd() { function handleTaskOrdinaryAdd() {
getDataSource().push({ getTaskOrdinaryDataSource().push({
name: '',
hospitalId: '', hospitalId: '',
orgId: '', orgId: '',
fileId: [] fileId: [],
key: buildUUID()
}); });
} }
/** 处理任务新增 */ /** 处理普通任务删除 */
function handleMutualTaskAdd() { function handleTaskOrdinaryDelete(record) {
const index = getTaskOrdinaryDataSource().findIndex(item => item.key == record.key);
if (index != -1) {
getTaskOrdinaryDataSource().splice(record.index, 1);
} else createMessage.error(`找不到key:${record.key}的数据,请刷新页面重试!`);
}
/** 处理交接任务新增 */
function handleTaskPresetAdd() {
getTaskPresetDataSource().push({ getTaskPresetDataSource().push({
name: '',
hospitalId: '', hospitalId: '',
orgId: '等待收样员设置!', orgId: '等待收样员设置!',
fileId: [] fileId: [],
key: buildUUID()
}); });
} }
function createMutualActions(record: EditRecordRow, column: BasicColumn): ActionItem[] { /** 处理交接任务删除 */
function handleTaskPresetDelete(record) {
const index = getTaskPresetDataSource().findIndex(item => item.key == record.key);
if (index != -1) {
getTaskPresetDataSource().splice(record.index, 1);
} else createMessage.error(`找不到key:${record.key}的数据,请刷新页面重试!`);
}
/** 创建普通任务操作列 */
function createTaskOrdinaryActions(record: EditRecordRow, column: BasicColumn): ActionItem[] {
if (!record.editable) { if (!record.editable) {
return [ return [
{ {
label: '编辑', label: '编辑',
disabled: mutualState.currentEditKeyRef ? mutualState.currentEditKeyRef !== record.key : false, disabled: state.taskOrdinaryCurrentEditKeyRef ? state.taskOrdinaryCurrentEditKeyRef !== record.key : false,
onClick: handleMutualEdit.bind(null, record), onClick: handleTaskOrdinaryEdit.bind(null, record),
} }
]; ];
} }
return [ return [
{ {
label: '保存', label: '保存',
onClick: handleMutualSave.bind(null, record, column) onClick: handleTaskOrdinarySave.bind(null, record, column)
}, },
{ {
label: '取消', label: '取消',
popConfirm: { popConfirm: {
title: '是否取消编辑', title: '是否取消编辑',
confirm: handleMutualCancel.bind(null, record, column) confirm: handleTaskOrdinaryCancel.bind(null, record, column)
} }
} }
]; ];
} }
/** 创建操作列 */ /** 处理普通任务表格编辑 */
function createActions(record: EditRecordRow, column: BasicColumn): ActionItem[] { function handleTaskOrdinaryEdit(record: EditRecordRow) {
state.taskOrdinaryCurrentEditKeyRef = record.key;
record.onEdit?.(true);
}
/** 处理普通任务表格编辑取消 */
function handleTaskOrdinaryCancel(record: EditRecordRow) {
state.taskOrdinaryCurrentEditKeyRef = '';
record.onEdit?.(false, false);
}
/** 处理普通任务表格编辑保存 */
async function handleTaskOrdinarySave(record: EditRecordRow) {
const valid = await record.onValid?.();
if (valid) {
const pass = await record.onEdit?.(false, true);
pass && (state.taskOrdinaryCurrentEditKeyRef = '');
}
}
/** 创建交接任务操作列 */
function createTaskPresetActions(record: EditRecordRow, column: BasicColumn): ActionItem[] {
if (!record.editable) { if (!record.editable) {
return [ return [
{ {
label: '编辑', label: '编辑',
disabled: state.currentEditKeyRef ? state.currentEditKeyRef !== record.key : false, disabled: state.taskPresetCurrentEditKeyRef ? state.taskPresetCurrentEditKeyRef !== record.key : false,
onClick: handleEdit.bind(null, record), onClick: handleTaskPresetEdit.bind(null, record),
} }
]; ];
} }
return [ return [
{ {
label: '保存', label: '保存',
onClick: handleSave.bind(null, record, column) onClick: handleTaskPresetSave.bind(null, record, column)
}, },
{ {
label: '取消', label: '取消',
popConfirm: { popConfirm: {
title: '是否取消编辑', title: '是否取消编辑',
confirm: handleCancel.bind(null, record, column) confirm: handleTaskPresetCancel.bind(null, record, column)
} }
} }
]; ];
} }
function handleEdit(record: EditRecordRow) { /** 处理交接任务表格编辑 */
state.currentEditKeyRef = record.key; function handleTaskPresetEdit(record: EditRecordRow) {
state.taskPresetCurrentEditKeyRef = record.key;
record.onEdit?.(true); record.onEdit?.(true);
} }
function handleCancel(record: EditRecordRow) { /** 处理交接任务表格编辑取消 */
state.currentEditKeyRef = ''; function handleTaskPresetCancel(record: EditRecordRow) {
state.taskPresetCurrentEditKeyRef = '';
record.onEdit?.(false, false); record.onEdit?.(false, false);
} }
async function handleSave(record: EditRecordRow) { /** 处理交接任务表格编辑保存 */
async function handleTaskPresetSave(record: EditRecordRow) {
const valid = await record.onValid?.(); const valid = await record.onValid?.();
if (valid) { if (valid) {
const pass = await record.onEdit?.(false, true); const pass = await record.onEdit?.(false, true);
pass && (state.currentEditKeyRef = ''); pass && (state.taskPresetCurrentEditKeyRef = '');
computeScheme();
} }
} }
function handleMutualEdit(record: EditRecordRow) {
mutualState.currentEditKeyRef = record.key;
record.onEdit?.(true);
}
function handleMutualCancel(record: EditRecordRow) {
mutualState.currentEditKeyRef = '';
record.onEdit?.(false, false);
}
async function handleMutualSave(record: EditRecordRow) { /** 处理打开交接任务 */
const valid = await record.onValid?.(); function handleOpenTaskPreset() {
if (valid) { openModal(true, {});
const pass = await record.onEdit?.(false, true);
pass && (mutualState.currentEditKeyRef = '');
}
} }
/** 智能计算方案 */ /** 处理地图任务预设点数据 */
function computeScheme() { function handleTaskPreset() {
const scheme = [];
const origin = state.formData.takeSpecimenId;
//
const taskDataSource = getDataSource();
const smallHospitalPositions:any[] = [];
const largeHospitalPositions:any[] = [];
taskDataSource.forEach(item => {
// ID
const key = buildUUID();
const smallHospital = smallHospitalMapList.find(index => index.id == item.hospitalId);
if(smallHospital) smallHospitalPositions.push([key, new AMap.LngLat(smallHospital.lng, smallHospital.lat)]);
const largeHospital = largeHospitalMapList.find(index => index.id == item.orgId);
if(largeHospital) largeHospitalPositions.push([key, new AMap.LngLat(largeHospital.lng, largeHospital.lat)]);
});
//
const waypoints:any[] = [];
//
let destination;
/** 1.计算预测大致的智能规划方案可行性数量 */
// }
const smallHospitalScheme = Array.from({ length: smallHospitalPositions.length }, () => Array(smallHospitalPositions.length).fill(0));
for(let i = 0; i < smallHospitalPositions.length; ++i) {
// ,
const oneDimensionArray = smallHospitalScheme[i];
// ,
let indexs = Object.keys(smallHospitalPositions);
const reverseIndexs = indexs.slice(0, i);
indexs.splice(0, i);
indexs.push(...reverseIndexs);
//
for(let j = 0; j < indexs.length; ++j) {
const index = indexs[j];
const smallHospitalPosition = smallHospitalPositions[index];
oneDimensionArray[j] = smallHospitalPosition;
}
}
// /** 处理弹出框提交 */
const composeScheme = mapSchemePermuteUnique([]); async function handleSubmit() {
console.log(getTaskOrdinaryDataSource());
} }
/** todo:地图动态组合排序算法暂时保留,等待下一版谈论是否做智能地图最优方案 */
/** 地图方案组合排列算法,可确保二叉树当存在数组内容相同排列不重复 */ /** 地图方案组合排列算法,可确保二叉树当存在数组内容相同排列不重复 */
function mapSchemePermuteUnique(composeQueue: number[]) { function mapSchemePermuteUnique(composeQueue: number[]) {
const ans: number[][] = []; const ans: number[][] = [];
@ -296,40 +333,4 @@
return ans; return ans;
} }
/** 处理打开交接任务 */
function handleMutualTask() {
openModal(true, { driving });
}
/** 处理路线预览 */
function handlePathPreview() {
}
/** 处理弹出框提交 */
async function handleSubmit() {
console.log(getDataSource());
/*try {
//
const formData = await formElRef.value.validate();
console.log(formData);
//
setModalProps({ confirmLoading: true });
// tag
switch (state.tag) {
case 'add':
//await addConfig(formData);
break;
case 'edit':
//await editConfig(formData);
break;
}
//
closeModal();
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}*/
}
</script> </script>

2
src/utils/dateUtil.ts

@ -22,7 +22,7 @@ export function formatToDate(date: moment.MomentInput = undefined, format = DATE
} }
/** 添加日期范围 */ /** 添加日期范围 */
export function convertDateRange(params: Recordable, dateRange: string): Recordable { export function convertDateRange(params: Recordable, dateRange: string[]): Recordable {
const search = params; const search = params;
search.beginTime = ''; search.beginTime = '';
search.endTime = ''; search.endTime = '';

2
src/views/system/config/index.vue

@ -30,7 +30,7 @@
</AFormItem> </AFormItem>
<AFormItem label="创建时间"> <AFormItem label="创建时间">
<ARangePicker v-model:value="state.dateRange" <ARangePicker v-model:value="state.dateRange"
style="width: '100%'" style="width: 100%"
valueFormat="YYYY-MM-DD" valueFormat="YYYY-MM-DD"
:placeholder="['开始日期', '结束日期']" :placeholder="['开始日期', '结束日期']"
/> />

Loading…
Cancel
Save