feat: 增加双向路线管理功能,支持获取、创建和删除双向路线,优化路线方向和类型的处理逻辑

This commit is contained in:
xudan 2025-09-09 10:31:18 +08:00
parent 82c474f8e2
commit 0a664afd14
2 changed files with 190 additions and 4 deletions

View File

@ -28,6 +28,56 @@ const route = computed<MapRouteInfo | null>(() => {
if (!v?.type) return null;
return v;
});
// 线
const connectedRoutes = computed<MapPen[]>(() => {
if (!pen.value) return [];
const [a1, a2] = pen.value.anchors ?? [];
if (!a1?.connectTo || !a2?.connectTo) return [];
return editor.value.getRoutesBetweenPoints(a1.connectTo, a2.connectTo);
});
const currentRoute = computed<MapPen | null>(() => {
return pen.value;
});
const oppositeRoute = computed<MapPen | null>(() => {
if (!currentRoute.value) return null;
const [a1, a2] = currentRoute.value.anchors ?? [];
if (!a1?.connectTo || !a2?.connectTo) return null;
return connectedRoutes.value.find(r => r.id !== currentRoute.value?.id) || null;
});
const isBidirectional = computed<boolean>(() => {
return connectedRoutes.value.length >= 2;
});
// 线
function handleDirectionChange(direction: any) {
if (!props.id) return;
editor.value.updateRoute(props.id, { direction: Number(direction) as -1 | 1 });
}
// 线
function handleRouteTypeChange(type: any) {
if (!props.id) return;
editor.value.changeRouteType(props.id, Number(type) as unknown as MapRouteType);
}
// 线
function handleOppositeDirectionChange(direction: any) {
if (!oppositeRoute.value?.id) return;
editor.value.updateRoute(oppositeRoute.value.id, { direction: Number(direction) as -1 | 1 });
}
//
function handlePassChange(pass: any) {
if (!props.id) return;
editor.value.updateRoute(props.id, { pass: Number(pass) as MapRoutePassType });
}
</script>
<template>
@ -37,7 +87,7 @@ const route = computed<MapRouteInfo | null>(() => {
<a-col :span="24">
<a-select
:value="route.pass ?? MapRoutePassType.无"
@change="editor.updateRoute(id, { pass: <number>$event })"
@change="handlePassChange($event)"
>
<a-select-option v-for="[l, v] in MAP_ROUTE_PASS_TYPES" :key="v">{{ $t(l) }}</a-select-option>
</a-select>
@ -76,8 +126,7 @@ const route = computed<MapRouteInfo | null>(() => {
<a-col flex="auto">
<a-select
:value="route.direction || 1"
@change="editor.updateRoute(id, { direction: <-1 | 1>$event })"
disabled
@change="handleDirectionChange($event)"
>
<a-select-option :value="1">{{ editor.getRouteLabel(id, 1) }}</a-select-option>
<a-select-option :value="-1">{{ editor.getRouteLabel(id, -1) }}</a-select-option>
@ -85,12 +134,30 @@ const route = computed<MapRouteInfo | null>(() => {
</a-col>
</a-row>
<!-- 反向路线方向如果存在双向路线 -->
<a-row v-if="isBidirectional && oppositeRoute" align="middle" :gutter="10" :wrap="false">
<a-col flex="none">
<a-typography-text>{{ $t('反向路线方向') }}:</a-typography-text>
</a-col>
<a-col flex="auto">
<a-select
:value="oppositeRoute.route?.direction || -1"
@change="handleOppositeDirectionChange($event)"
>
<a-select-option :value="1">{{ editor.getRouteLabel(oppositeRoute.id, 1) }}</a-select-option>
<a-select-option :value="-1">{{ editor.getRouteLabel(oppositeRoute.id, -1) }}</a-select-option>
</a-select>
</a-col>
</a-row>
<a-row align="middle" :gutter="10" :wrap="false">
<a-col flex="none">
<a-typography-text>{{ $t('路段类型') }}:</a-typography-text>
</a-col>
<a-col flex="auto">
<a-select :value="route.type" @change="editor.changeRouteType(id, <MapRouteType>$event)">
<a-select :value="route.type" @change="handleRouteTypeChange($event)">
<a-select-option v-for="[l, v] in MAP_ROUTE_TYPES" :key="v">{{ $t(l) }}</a-select-option>
</a-select>
</a-col>

View File

@ -1371,6 +1371,125 @@ export class EditorService extends Meta2d {
this.updateLineType(pen, type);
this.setValue({ id, route: { type } }, { render: true, history: true, doEvent: true });
}
/**
* 线
* @param point1Id ID
* @param point2Id ID
* @returns 线
*/
public getRoutesBetweenPoints(point1Id: string, point2Id: string): MapPen[] {
return this.find('route').filter(route => {
const [a1, a2] = route.anchors ?? [];
if (!a1?.connectTo || !a2?.connectTo) return false;
return (a1.connectTo === point1Id && a2.connectTo === point2Id) ||
(a1.connectTo === point2Id && a2.connectTo === point1Id);
});
}
/**
* 线线
* @param routeId 线ID
* @returns 线null
*/
public getReverseRoute(routeId: string): MapPen | null {
const route = this.getPenById(routeId);
if (!route) return null;
const [a1, a2] = route.anchors ?? [];
if (!a1?.connectTo || !a2?.connectTo) return null;
const reverseRoutes = this.getRoutesBetweenPoints(a1.connectTo, a2.connectTo);
return reverseRoutes.find(r => r.id !== routeId) || null;
}
/**
* 线
* @param p
* @param type 线线
* @param forwardId 线ID
* @param reverseId 线ID
*/
public addBidirectionalRoute(
p: [MapPen, MapPen],
type = MapRouteType.线,
forwardId?: string,
reverseId?: string
): void {
const [p1, p2] = p;
if (!p1?.anchors?.length || !p2?.anchors?.length) return;
// 创建正向路线
const forwardLine = this.connectLine(p1, p2, undefined, undefined, false);
forwardId ||= forwardLine.id!;
this.changePenId(forwardLine.id!, forwardId);
const forwardPen: MapPen = {
tags: ['route'],
route: { type, direction: 1 },
lineWidth: 1,
locked: LockState.DisableEdit,
canvasLayer: CanvasLayer.CanvasMain,
};
this.setValue({ id: forwardId, ...forwardPen }, { render: false, history: false, doEvent: false });
this.updateLineType(forwardLine, type);
// 创建反向路线
const reverseLine = this.connectLine(p2, p1, undefined, undefined, false);
reverseId ||= reverseLine.id!;
this.changePenId(reverseLine.id!, reverseId);
const reversePen: MapPen = {
tags: ['route'],
route: { type, direction: -1 },
lineWidth: 1,
locked: LockState.DisableEdit,
canvasLayer: CanvasLayer.CanvasMain,
};
this.setValue({ id: reverseId, ...reversePen }, { render: false, history: false, doEvent: false });
this.updateLineType(reverseLine, type);
// 将路线移到底层,确保点位能覆盖在路线之上
this.bottom([forwardLine, reverseLine]);
// 将反向路线移到正向路线之上,解决重叠选择问题
this.top([reverseLine]);
this.active(forwardId);
this.render();
}
/**
* 线
* @param routeId 线ID
*/
public removeBidirectionalRoute(routeId: string): void {
const route = this.getPenById(routeId);
if (!route) return;
const [a1, a2] = route.anchors ?? [];
if (!a1?.connectTo || !a2?.connectTo) return;
// 找到所有连接这两个点位的路线
const routesBetweenPoints = this.getRoutesBetweenPoints(a1.connectTo, a2.connectTo);
// 删除所有相关路线
routesBetweenPoints.forEach(r => {
this.delete([r]);
});
this.render();
}
/**
* 线
* @param point1Id ID
* @param point2Id ID
* @returns 线
*/
public hasBidirectionalRoute(point1Id: string, point2Id: string): boolean {
const routes = this.getRoutesBetweenPoints(point1Id, point2Id);
return routes.length >= 2;
}
//#endregion
//#region 区域