feat: route
This commit is contained in:
parent
43f16303d8
commit
597967497d
File diff suppressed because one or more lines are too long
5
mocks/scene/saveById
Normal file
5
mocks/scene/saveById
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"code": 200,
|
||||
"success": false,
|
||||
"message": "模拟提示"
|
||||
}
|
@ -428,6 +428,25 @@
|
||||
}
|
||||
}
|
||||
|
||||
.ant-message-notice-content {
|
||||
padding: 0;
|
||||
background-color: none;
|
||||
box-shadow: none !important;
|
||||
|
||||
& > .ant-message-error {
|
||||
padding: 8px 15px;
|
||||
font: 400 14px/22px Roboto;
|
||||
color: get-color(text1);
|
||||
background-color: get-color(error_bg);
|
||||
border: 1px solid get-color(error_border);
|
||||
border-radius: 2px;
|
||||
|
||||
& > .anticon {
|
||||
margin-inline-end: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-modal.ant-modal-confirm .ant-modal-content {
|
||||
padding: 32px 32px 24px;
|
||||
background-color: get-color(popover);
|
||||
@ -601,8 +620,11 @@
|
||||
& > table {
|
||||
& > .ant-table-tbody > .ant-table-row > .ant-table-cell {
|
||||
padding: 9px 16px 8px;
|
||||
overflow: hidden;
|
||||
font: 400 14px/22px Roboto;
|
||||
color: get-color(text1);
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
background-color: transparent;
|
||||
border-color: get-color(divider);
|
||||
}
|
||||
|
@ -45,3 +45,4 @@ export interface MapAreaInfo {
|
||||
|
||||
export type Point = Record<'x' | 'y', number>;
|
||||
export type Rect = Record<'x' | 'y' | 'width' | 'height', number>;
|
||||
export type AnchorPosition = 't' | 'b' | 'l' | 'r';
|
||||
|
@ -4,6 +4,7 @@ import type { SceneDetail, SceneInfo } from './type';
|
||||
|
||||
const enum API {
|
||||
获取场景 = '/scene/getById',
|
||||
保存场景 = '/scene/saveById',
|
||||
}
|
||||
|
||||
export async function getSceneById(id: SceneInfo['id']): Promise<SceneDetail | null> {
|
||||
@ -19,3 +20,17 @@ export async function getSceneById(id: SceneInfo['id']): Promise<SceneDetail | n
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function saveSceneById(id: SceneInfo['id'], json: string): Promise<boolean> {
|
||||
if (!id) return false;
|
||||
type B = { id: string; json: string };
|
||||
type D = void;
|
||||
try {
|
||||
const body = { id, json };
|
||||
await http.post<D, B>(API.保存场景, body);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.debug(error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { type MapAreaInfo, MapAreaType, type MapPen } from '@api/map';
|
||||
import { type MapAreaInfo, MapAreaType, type MapPen, MapPointType } from '@api/map';
|
||||
import type { EditorService } from '@core/editor.service';
|
||||
import sTheme from '@core/theme.service';
|
||||
import { computed, inject, type InjectionKey, type ShallowRef } from 'vue';
|
||||
@ -20,6 +20,15 @@ const area = computed<MapAreaInfo | null>(() => {
|
||||
|
||||
const icon = computed<string>(() => `area${area.value?.type}-detail`);
|
||||
|
||||
const bindAction = computed<string>(
|
||||
() =>
|
||||
area.value?.points
|
||||
?.map((v) => editor.value.getPenById(v))
|
||||
.filter((v) => v?.point?.type === MapPointType.动作点)
|
||||
.map((v) => v?.label)
|
||||
.filter((v) => !!v)
|
||||
.join('、') ?? '',
|
||||
);
|
||||
const bindPoint = computed<string>(
|
||||
() =>
|
||||
area.value?.points
|
||||
@ -57,7 +66,7 @@ const bindRoute = computed<string>(
|
||||
<a-list-item v-if="MapAreaType.库区 === area.type">
|
||||
<a-flex :gap="8" vertical>
|
||||
<a-typography-text type="secondary">{{ $t('绑定动作点') }}</a-typography-text>
|
||||
<a-typography-text>{{ bindPoint || $t('暂无') }}</a-typography-text>
|
||||
<a-typography-text>{{ bindAction || $t('暂无') }}</a-typography-text>
|
||||
</a-flex>
|
||||
</a-list-item>
|
||||
<a-list-item v-if="[MapAreaType.互斥区, MapAreaType.非互斥区].includes(area.type)">
|
||||
|
@ -33,13 +33,14 @@ const points = computed<MapPen[]>(
|
||||
area.value?.points?.map((v) => editor.value.getPenById(v)).filter((v) => v?.label?.includes(pointKeyword.value))
|
||||
),
|
||||
);
|
||||
const actions = computed<MapPen[]>(() => points.value?.filter(({ point }) => point?.type === MapPointType.动作点));
|
||||
|
||||
const refBindRoute = shallowRef<RouteBindModalRef>();
|
||||
const routeKeyword = ref<string>('');
|
||||
const routes = computed<MapPen[]>(
|
||||
const routes = computed<string[]>(
|
||||
() =>
|
||||
<MapPen[]>(
|
||||
area.value?.routes?.map((v) => editor.value.getPenById(v)).filter((v) => v?.label?.includes(routeKeyword.value))
|
||||
<string[]>(
|
||||
area.value?.routes?.map((v) => editor.value.getRouteLabel(v)).filter((v) => v?.includes(routeKeyword.value))
|
||||
),
|
||||
);
|
||||
</script>
|
||||
@ -88,7 +89,7 @@ const routes = computed<MapPen[]>(
|
||||
|
||||
<a-collapse-panel v-if="MapAreaType.库区 === area.type" :header="$t('绑定动作点')">
|
||||
<template #extra>
|
||||
<a-button class="icon-btn" size="small" @click.stop="refBindPoint?.open(pen, [MapPointType.动作点])">
|
||||
<a-button class="icon-btn" size="small" @click.stop="refBindPoint?.open(pen, MapPointType.动作点)">
|
||||
<i class="mask plus" />
|
||||
</a-button>
|
||||
</template>
|
||||
@ -97,7 +98,7 @@ const routes = computed<MapPen[]>(
|
||||
<i class="icon search size-16" />
|
||||
</template>
|
||||
</a-input>
|
||||
<a-list rowKey="id" :data-source="points">
|
||||
<a-list rowKey="id" :data-source="actions">
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item class="ph-16" style="height: 36px">
|
||||
<a-typography-text>{{ item.label }}</a-typography-text>
|
||||
@ -143,7 +144,7 @@ const routes = computed<MapPen[]>(
|
||||
<a-list rowKey="id" :data-source="routes">
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item class="ph-16" style="height: 36px">
|
||||
<a-typography-text>{{ item.label }}</a-typography-text>
|
||||
<a-typography-text>{{ item }}</a-typography-text>
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
|
@ -28,7 +28,9 @@ const bindRobot = computed<string>(
|
||||
const bindAction = computed<string>(
|
||||
() =>
|
||||
point.value?.actions
|
||||
?.map((v) => editor.value.getPenById(v)?.label)
|
||||
?.map((v) => editor.value.getPenById(v))
|
||||
.filter((v) => v?.point?.type === MapPointType.动作点)
|
||||
.map((v) => v?.label)
|
||||
.filter((v) => !!v)
|
||||
.join('、') ?? '',
|
||||
);
|
||||
|
@ -110,7 +110,7 @@ const coArea2 = computed<MapPen[]>(() => editor.value.getBoundAreas(props.id, 'p
|
||||
:precision="0"
|
||||
:controls="false"
|
||||
:value="rect?.x?.toFixed()"
|
||||
@change="editor.updatePen(id, { x: <number>$event })"
|
||||
@change="editor.updatePen(id, { x: +$event })"
|
||||
/>
|
||||
</a-space>
|
||||
</a-col>
|
||||
@ -123,7 +123,7 @@ const coArea2 = computed<MapPen[]>(() => editor.value.getBoundAreas(props.id, 'p
|
||||
:precision="0"
|
||||
:controls="false"
|
||||
:value="rect?.y?.toFixed()"
|
||||
@change="editor.updatePen(id, { y: <number>$event })"
|
||||
@change="editor.updatePen(id, { y: +$event })"
|
||||
/>
|
||||
</a-space>
|
||||
</a-col>
|
||||
@ -159,7 +159,7 @@ const coArea2 = computed<MapPen[]>(() => editor.value.getBoundAreas(props.id, 'p
|
||||
|
||||
<a-collapse-panel v-if="MapPointType.等待点 === point.type" :header="$t('绑定动作点')">
|
||||
<template #extra>
|
||||
<a-button class="icon-btn" size="small" @click.stop="refBindPoint?.open(pen, [MapPointType.动作点])">
|
||||
<a-button class="icon-btn" size="small" @click.stop="refBindPoint?.open(pen, MapPointType.动作点)">
|
||||
<i class="mask plus" />
|
||||
</a-button>
|
||||
</template>
|
||||
|
@ -106,7 +106,7 @@ const route = computed<MapRouteInfo | null>(() => {
|
||||
:precision="0"
|
||||
:controls="false"
|
||||
:value="route?.c1?.x.toFixed()"
|
||||
@change="editor.updateRoute(id, { c1: { x: <number>$event, y: route?.c1?.y ?? 0 } })"
|
||||
@change="editor.updateRoute(id, { c1: { x: +$event, y: route?.c1?.y ?? 0 } })"
|
||||
/>
|
||||
</a-space>
|
||||
</a-col>
|
||||
@ -119,7 +119,7 @@ const route = computed<MapRouteInfo | null>(() => {
|
||||
:precision="0"
|
||||
:controls="false"
|
||||
:value="route?.c1?.y.toFixed()"
|
||||
@change="editor.updateRoute(id, { c1: { x: route?.c1?.x ?? 0, y: <number>$event } })"
|
||||
@change="editor.updateRoute(id, { c1: { x: route?.c1?.x ?? 0, y: +$event } })"
|
||||
/>
|
||||
</a-space>
|
||||
</a-col>
|
||||
@ -138,7 +138,7 @@ const route = computed<MapRouteInfo | null>(() => {
|
||||
:precision="0"
|
||||
:controls="false"
|
||||
:value="route?.c2?.x.toFixed()"
|
||||
@change="editor.updateRoute(id, { c2: { x: <number>$event, y: route?.c2?.y ?? 0 } })"
|
||||
@change="editor.updateRoute(id, { c2: { x: +$event, y: route?.c2?.y ?? 0 } })"
|
||||
/>
|
||||
</a-space>
|
||||
</a-col>
|
||||
@ -151,7 +151,7 @@ const route = computed<MapRouteInfo | null>(() => {
|
||||
:precision="0"
|
||||
:controls="false"
|
||||
:value="route?.c2?.y.toFixed()"
|
||||
@change="editor.updateRoute(id, { c2: { x: route?.c2?.x ?? 0, y: <number>$event } })"
|
||||
@change="editor.updateRoute(id, { c2: { x: route?.c2?.x ?? 0, y: +$event } })"
|
||||
/>
|
||||
</a-space>
|
||||
</a-col>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { MapAreaType } from '@api/map';
|
||||
import { saveSceneById } from '@api/scene';
|
||||
import type { EditorService } from '@core/editor.service';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import { inject, type InjectionKey, ref, type ShallowRef, watch } from 'vue';
|
||||
@ -12,6 +13,14 @@ type Props = {
|
||||
const props = defineProps<Props>();
|
||||
const editor = inject(props.token)!;
|
||||
|
||||
//#region 接口
|
||||
const updateScene = async () => {
|
||||
const json = editor.value.save();
|
||||
if (!json) return;
|
||||
await saveSceneById(props.id, json);
|
||||
};
|
||||
//#endregion
|
||||
|
||||
const mode = ref<MapAreaType>();
|
||||
watch(editor.value.mouseBrush, (v) => {
|
||||
if (!mode.value) return;
|
||||
@ -51,7 +60,7 @@ watch(editor.value.mouseBrush, (v) => {
|
||||
|
||||
<a-divider class="size-24 mh-8" type="vertical" />
|
||||
|
||||
<a-button class="icon-btn tool-btn" size="large">
|
||||
<a-button class="icon-btn tool-btn" size="large" @click="updateScene">
|
||||
<i class="mask save" />
|
||||
</a-button>
|
||||
<a-button class="icon-btn tool-btn ml-12" size="large" @click="editor.undo()">
|
||||
|
@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { type MapPen, MapPointType } from '@api/map';
|
||||
import type { EditorService } from '@core/editor.service';
|
||||
import { isNil } from 'lodash-es';
|
||||
import { computed, inject, type InjectionKey, ref, type ShallowRef, toRaw } from 'vue';
|
||||
|
||||
type Props = {
|
||||
@ -11,12 +12,12 @@ const editor = inject(props.token)!;
|
||||
|
||||
export type PointBindModalRef = Ref;
|
||||
type Ref = {
|
||||
open: (pen: MapPen, filter?: MapPointType[]) => void;
|
||||
open: (pen: MapPen, filter?: MapPointType) => void;
|
||||
};
|
||||
const open: Ref['open'] = (pen, filter = []) => {
|
||||
const open: Ref['open'] = (pen, type) => {
|
||||
if (!pen?.id) return;
|
||||
keyword.value = '';
|
||||
types.value = [MapPointType.禁行点, ...filter];
|
||||
filter.value = type;
|
||||
id.value = pen.id;
|
||||
sn.value = pen.name;
|
||||
switch (sn.value) {
|
||||
@ -37,10 +38,13 @@ defineExpose<Ref>({ open });
|
||||
const show = ref<boolean>(false);
|
||||
const keyword = ref<string>('');
|
||||
|
||||
const types = ref<MapPointType[]>([MapPointType.禁行点]);
|
||||
const filter = ref<MapPointType>();
|
||||
const points = computed<MapPen[]>(() =>
|
||||
editor.value.points.value
|
||||
.filter(({ point }) => point?.type && !types.value.includes(point.type))
|
||||
.filter(
|
||||
({ point }) =>
|
||||
point?.type && point.type !== MapPointType.禁行点 && (isNil(filter.value) || point.type === filter.value),
|
||||
)
|
||||
.filter(({ label }) => label?.includes(keyword.value)),
|
||||
);
|
||||
|
||||
|
@ -60,14 +60,14 @@ const submit = () => {
|
||||
bordered
|
||||
>
|
||||
<a-table-column dataIndex="label" :title="$t('路段')" />
|
||||
<a-table-column :dataIndex="['route', 'type']" :title="$t('路段类型')">
|
||||
<a-table-column :width="140" :dataIndex="['route', 'type']" :title="$t('路段类型')">
|
||||
<template #default="{ text }">
|
||||
{{ $t(MAP_ROUTE_TYPE[text]) }}
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column :dataIndex="['route', 'pass']" :title="$t('可通行类型')">
|
||||
<a-table-column :width="128" :dataIndex="['route', 'pass']" :title="$t('可通行类型')">
|
||||
<template #default="{ text }">
|
||||
{{ $t(MapRoutePassType[text]) }}
|
||||
{{ $t(MapRoutePassType[text ?? MapRoutePassType.无]) }}
|
||||
</template>
|
||||
</a-table-column>
|
||||
</a-table>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { MapAreaType, type MapPen, MapPointType } from '@api/map';
|
||||
import { MapAreaType, type MapPen, MapPointType, MapRoutePassType } from '@api/map';
|
||||
import type { EditorService } from '@core/editor.service';
|
||||
import { computed, inject, type InjectionKey, ref, type ShallowRef } from 'vue';
|
||||
|
||||
@ -20,6 +20,13 @@ const points = computed<MapPen[]>(() =>
|
||||
//#endregion
|
||||
|
||||
//#region 线路列表
|
||||
const routes = computed<MapPen[]>(() =>
|
||||
editor.value.routes.value.filter(({ label }) => {
|
||||
console.log(label);
|
||||
|
||||
return label?.includes(keyword.value);
|
||||
}),
|
||||
);
|
||||
//#endregion
|
||||
|
||||
//#region 区域列表
|
||||
@ -85,11 +92,56 @@ const areas = computed<MapPen[]>(() => editor.value.areas.value.filter(({ label
|
||||
</a-list>
|
||||
</a-collapse-panel>
|
||||
|
||||
<a-collapse-panel :header="$t('仅载货可通行路线')"></a-collapse-panel>
|
||||
<a-collapse-panel :header="$t('仅载货可通行路线')">
|
||||
<a-list
|
||||
rowKey="id"
|
||||
:data-source="routes.filter(({ route }) => route?.pass === MapRoutePassType.仅载货可通行)"
|
||||
>
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item
|
||||
class="ph-16"
|
||||
:class="{ selected: item.id === current }"
|
||||
style="height: 36px"
|
||||
@click="editor.active(item.id)"
|
||||
>
|
||||
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
</a-collapse-panel>
|
||||
|
||||
<a-collapse-panel :header="$t('仅空载可通行路线')"></a-collapse-panel>
|
||||
<a-collapse-panel :header="$t('仅空载可通行路线')">
|
||||
<a-list
|
||||
rowKey="id"
|
||||
:data-source="routes.filter(({ route }) => route?.pass === MapRoutePassType.仅空载可通行)"
|
||||
>
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item
|
||||
class="ph-16"
|
||||
:class="{ selected: item.id === current }"
|
||||
style="height: 36px"
|
||||
@click="editor.active(item.id)"
|
||||
>
|
||||
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
</a-collapse-panel>
|
||||
|
||||
<a-collapse-panel :header="$t('禁行路线')"></a-collapse-panel>
|
||||
<a-collapse-panel :header="$t('禁行路线')">
|
||||
<a-list rowKey="id" :data-source="routes.filter(({ route }) => route?.pass === MapRoutePassType.禁行)">
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item
|
||||
class="ph-16"
|
||||
:class="{ selected: item.id === current }"
|
||||
style="height: 36px"
|
||||
@click="editor.active(item.id)"
|
||||
>
|
||||
<a-typography-text type="secondary">{{ item.label }}</a-typography-text>
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
</a-collapse-panel>
|
||||
|
||||
<a-collapse-panel :header="$t('等待点')">
|
||||
<a-list rowKey="id" :data-source="points.filter(({ point }) => point?.type === MapPointType.等待点)">
|
||||
|
@ -1,21 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import type { EditorService } from '@core/editor.service';
|
||||
import sTheme from '@core/theme.service';
|
||||
import { inject, type InjectionKey, type ShallowRef } from 'vue';
|
||||
|
||||
type Props = {
|
||||
token: InjectionKey<ShallowRef<EditorService>>;
|
||||
editable?: boolean;
|
||||
current?: string;
|
||||
};
|
||||
const props = defineProps<Props>();
|
||||
const editor = inject(props.token)!;
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-row v-if="true"></a-row>
|
||||
<a-empty v-else :image="sTheme.empty" />
|
||||
</template>
|
||||
|
||||
<!-- <style scoped lang="scss"></style> -->
|
||||
<!-- <style scoped lang="scss"></style> -->
|
@ -1,65 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import type { EditorService } from '@core/editor.service';
|
||||
import { isEmpty } from 'lodash-es';
|
||||
import { inject, type InjectionKey, ref, type ShallowRef, watch } from 'vue';
|
||||
|
||||
const enum Mode {
|
||||
常规,
|
||||
添加点位 = 0x10,
|
||||
添加库区 = 0x31,
|
||||
添加互斥区,
|
||||
添加非互斥区,
|
||||
}
|
||||
|
||||
type Props = {
|
||||
editor: InjectionKey<ShallowRef<EditorService>>;
|
||||
editable?: boolean;
|
||||
};
|
||||
const props = defineProps<Props>();
|
||||
const editor = inject(props.editor)!;
|
||||
|
||||
const mode = ref<Mode>(Mode.常规);
|
||||
watch(editor.value.mouseClick, (v) => {
|
||||
if (mode.value !== Mode.添加点位) return;
|
||||
if (isEmpty(v)) return;
|
||||
editor.value.addPoint(v, 1);
|
||||
editor.value.addPoint(v, 11);
|
||||
});
|
||||
watch(editor.value.mouseBrush, (v) => {
|
||||
if (![Mode.添加库区, Mode.添加互斥区, Mode.添加非互斥区].includes(mode.value)) return;
|
||||
const [p1, p2] = v ?? [];
|
||||
if (isEmpty(p1) || isEmpty(p2)) return;
|
||||
editor.value.addArea(p1, p2, mode.value & 0xf);
|
||||
mode.value = Mode.常规;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-space class="scroll" direction="vertical">
|
||||
<a-button @click="mode = Mode.常规">常规</a-button>
|
||||
<a-button @click="mode = Mode.添加点位">点位</a-button>
|
||||
<!-- <a-button @click="editor.addRoute(PenRouteType.直线)">直线</a-button> -->
|
||||
<!-- <a-button @click="editor.addRoute(PenRouteType.三阶贝塞尔曲线)">曲线</a-button> -->
|
||||
<a-button @click="mode = Mode.添加库区">库区</a-button>
|
||||
<a-button @click="mode = Mode.添加互斥区">互斥区</a-button>
|
||||
<a-button @click="mode = Mode.添加非互斥区">非互斥区</a-button>
|
||||
|
||||
<a-button @click="mode = Mode.常规">常规</a-button>
|
||||
<a-button @click="mode = Mode.添加点位">点位</a-button>
|
||||
<!-- <a-button @click="editor.addRoute(PenRouteType.直线)">直线</a-button> -->
|
||||
<!-- <a-button @click="editor.addRoute(PenRouteType.三阶贝塞尔曲线)">曲线</a-button> -->
|
||||
<a-button @click="mode = Mode.添加库区">库区</a-button>
|
||||
<a-button @click="mode = Mode.添加互斥区">互斥区</a-button>
|
||||
<a-button @click="mode = Mode.添加非互斥区">非互斥区</a-button>
|
||||
|
||||
<a-button @click="mode = Mode.常规">常规</a-button>
|
||||
<a-button @click="mode = Mode.添加点位">点位</a-button>
|
||||
<!-- <a-button @click="editor.addRoute(PenRouteType.直线)">直线</a-button> -->
|
||||
<!-- <a-button @click="editor.addRoute(PenRouteType.三阶贝塞尔曲线)">曲线</a-button> -->
|
||||
<a-button @click="mode = Mode.添加库区">库区</a-button>
|
||||
<a-button @click="mode = Mode.添加互斥区">互斥区</a-button>
|
||||
<a-button @click="mode = Mode.添加非互斥区">非互斥区</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<!-- <style scoped lang="scss"></style> -->
|
@ -47,7 +47,6 @@ const importScene = async () => {
|
||||
const exportScene = () => {
|
||||
const json = editor.value?.save();
|
||||
if (!json) return;
|
||||
getSceneById(json);
|
||||
const blob = textToBlob(json);
|
||||
if (!blob?.size) return;
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
@ -1,4 +1,5 @@
|
||||
import {
|
||||
type AnchorPosition,
|
||||
EDITOR_CONFIG,
|
||||
type MapAreaInfo,
|
||||
MapAreaType,
|
||||
@ -26,12 +27,26 @@ export class EditorService extends Meta2d {
|
||||
this.setState(editable);
|
||||
|
||||
setTimeout(() => {
|
||||
this.addRoute(['21b74c90', '00f32a0']);
|
||||
this.addRoute(['21b74c90', '7f201a25'], 'bezier3');
|
||||
const pens = this.data().pens;
|
||||
this.addRoute([pens[4].id, pens[9].id]);
|
||||
|
||||
// this.addRoute(['21b74c90', '7f201a25'], 'bezier3');
|
||||
}, 1000);
|
||||
}
|
||||
public save(): string {
|
||||
const data = this.data();
|
||||
data.pens.forEach((pen: MapPen) => {
|
||||
remove(pen.point?.robots ?? [], (v) => !this.#robotMap.has(v));
|
||||
remove(pen.point?.actions ?? [], (v) => this.getPenById(v)?.point?.type !== MapPointType.动作点);
|
||||
remove(pen.area?.points ?? [], (v) => {
|
||||
const { point } = this.getPenById(v) ?? {};
|
||||
if (isNil(point)) return true;
|
||||
if (point.type === MapPointType.禁行点) return true;
|
||||
if (pen.area?.type === MapAreaType.库区 && point.type !== MapPointType.动作点) return true;
|
||||
return false;
|
||||
});
|
||||
remove(pen.area?.routes ?? [], (v) => isNil(this.getPenById(v)));
|
||||
});
|
||||
return JSON.stringify(data);
|
||||
}
|
||||
|
||||
@ -177,7 +192,7 @@ export class EditorService extends Meta2d {
|
||||
}
|
||||
|
||||
public updatePen(id: string, pen: Partial<MapPen>, record = true): void {
|
||||
this.setValue({ ...pen, id }, { render: record, history: record, doEvent: true });
|
||||
this.setValue({ ...pen, id }, { render: true, history: record, doEvent: true });
|
||||
}
|
||||
|
||||
//#region 点位
|
||||
@ -202,9 +217,6 @@ export class EditorService extends Meta2d {
|
||||
label: `P${id}`,
|
||||
point: { type },
|
||||
};
|
||||
const { x, y, width, height } = this.getPenRect(pen);
|
||||
pen.x = x - width / 2;
|
||||
pen.y = y - height / 2;
|
||||
await this.addPen(pen, false, true, true);
|
||||
// this.pushHistory({ type: EditType.Add, pens: [cloneDeep(pen)] });
|
||||
}
|
||||
@ -241,7 +253,7 @@ export class EditorService extends Meta2d {
|
||||
this.#change$$.pipe(
|
||||
filter((v) => v),
|
||||
debounceTime(100),
|
||||
map(() => this.find('route').map((v) => (v.label = this.getRouteLabel(v.id)))),
|
||||
map(() => this.find('route').map((v) => ({ ...v, label: this.getRouteLabel(v.id) }))),
|
||||
),
|
||||
{ initialValue: new Array<MapPen>() },
|
||||
);
|
||||
@ -259,12 +271,13 @@ export class EditorService extends Meta2d {
|
||||
return `${p1.label}${(d ?? direction) > 0 ? '→' : '←'}${p2.label}`;
|
||||
}
|
||||
|
||||
public addRoute(p: [string, string], type = MapRouteType.直线): void {
|
||||
public addRoute(p: [string, string], type = MapRouteType.直线, from?: AnchorPosition, to?: AnchorPosition): void {
|
||||
const [p1, p2] = p.map((v) => this.getPenById(v));
|
||||
if (!p1?.anchors?.length || !p2?.anchors?.length) return;
|
||||
const line = this.connectLine(p1, p2, p1.anchors[0], p2.anchors[0], false);
|
||||
const a1 = p1.anchors.find(({ id }) => id === from);
|
||||
const a2 = p2.anchors.find(({ id }) => id === to);
|
||||
const line = this.connectLine(p1, p2, a1, a2, false);
|
||||
const pen: MapPen = { tags: ['route'], route: { type }, lineWidth: 2, iconSize: 10 };
|
||||
// this.bottom(line);
|
||||
this.setValue({ id: line.id, ...pen }, { render: false, history: false, doEvent: false });
|
||||
this.updateLineType(line, type);
|
||||
// this.pushHistory({ type: EditType.Add, pens: [cloneDeep(line)] });
|
||||
@ -384,7 +397,20 @@ export class EditorService extends Meta2d {
|
||||
this.render();
|
||||
}
|
||||
|
||||
#onDelete(): void {}
|
||||
#onDelete(pens?: MapPen[]): void {
|
||||
pens?.forEach((pen) => {
|
||||
switch (pen.name) {
|
||||
case 'point':
|
||||
{
|
||||
const lines = this.getLines(pen);
|
||||
this.delete(lines, true, false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
#listen(e: unknown, v: any) {
|
||||
@ -398,7 +424,7 @@ export class EditorService extends Meta2d {
|
||||
this.#change$$.next(true);
|
||||
break;
|
||||
case 'delete':
|
||||
this.#onDelete();
|
||||
this.#onDelete(v);
|
||||
this.#change$$.next(true);
|
||||
break;
|
||||
case 'update':
|
||||
@ -413,34 +439,6 @@ export class EditorService extends Meta2d {
|
||||
this.#change$$.next(false);
|
||||
break;
|
||||
|
||||
// case 'undo':
|
||||
// case 'redo':
|
||||
// {
|
||||
// const { type, pens = [], initPens = [] } = data ?? {};
|
||||
// switch (type) {
|
||||
// case EditType.Add:
|
||||
// pens?.forEach((pen: SceneMapPen) => {
|
||||
// if (pen.name === 'point') {
|
||||
// const { image } = this.#mapPointType(pen.point!.type);
|
||||
// const rect = this.#editor?.getPenRect(pen);
|
||||
// this.#editor?.setValue({ id: pen.id, image, ...rect }, { render: true, history: false });
|
||||
// }
|
||||
// });
|
||||
// break;
|
||||
// case EditType.Update:
|
||||
// (event === 'undo' ? initPens : pens)?.forEach((pen: SceneMapPen) => {
|
||||
// if (pen.name === 'point') {
|
||||
// const { image } = this.#mapPointType(pen.point!.type);
|
||||
// this.#editor?.setValue({ id: pen.id, image }, { render: true, history: false });
|
||||
// }
|
||||
// });
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
|
||||
case 'click':
|
||||
case 'mousedown':
|
||||
case 'mouseup':
|
||||
|
Loading…
x
Reference in New Issue
Block a user