feat: load standard scene
This commit is contained in:
parent
e3edde1b16
commit
713cf8a022
@ -6,6 +6,7 @@ import type { GroupSceneDetail, SceneDetail, SceneInfo } from './type';
|
|||||||
const enum API {
|
const enum API {
|
||||||
获取场景 = '/scene/getById',
|
获取场景 = '/scene/getById',
|
||||||
保存场景 = '/scene/saveById',
|
保存场景 = '/scene/saveById',
|
||||||
|
推送场景 = '/scene/pushById',
|
||||||
|
|
||||||
获取组场景 = '/scene/getByGroupId',
|
获取组场景 = '/scene/getByGroupId',
|
||||||
保存组场景 = '/scene/saveByGroupId',
|
保存组场景 = '/scene/saveByGroupId',
|
||||||
@ -39,6 +40,20 @@ export async function saveSceneById(id: SceneInfo['id'], json: string): Promise<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function pushSceneById(id: SceneInfo['id']): Promise<boolean> {
|
||||||
|
if (!id) return false;
|
||||||
|
type B = { id: string };
|
||||||
|
type D = void;
|
||||||
|
try {
|
||||||
|
const body = { id };
|
||||||
|
await http.post<D, B>(API.推送场景, body);
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.debug(error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function getSceneByGroupId(
|
export async function getSceneByGroupId(
|
||||||
id: RobotGroup['id'],
|
id: RobotGroup['id'],
|
||||||
sid: RobotGroup['sid'],
|
sid: RobotGroup['sid'],
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getSceneById } from '@api/scene';
|
import { getSceneById, pushSceneById } from '@api/scene';
|
||||||
import { EditorService } from '@core/editor.service';
|
import { EditorService } from '@core/editor.service';
|
||||||
import { decodeTextFile, downloadFile, selectFile, textToBlob } from '@core/utils';
|
import { decodeTextFile, downloadFile, selectFile, textToBlob } from '@core/utils';
|
||||||
|
import { Modal } from 'ant-design-vue';
|
||||||
import { computed, watch } from 'vue';
|
import { computed, watch } from 'vue';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { onMounted, provide, shallowRef } from 'vue';
|
import { onMounted, provide, shallowRef } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
const EDITOR_KEY = Symbol('editor-key');
|
const EDITOR_KEY = Symbol('editor-key');
|
||||||
|
|
||||||
@ -13,12 +15,18 @@ type Props = {
|
|||||||
};
|
};
|
||||||
const props = defineProps<Props>();
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
//#region 接口
|
//#region 接口
|
||||||
const readScene = async () => {
|
const readScene = async () => {
|
||||||
const res = await getSceneById(props.id);
|
const res = await getSceneById(props.id);
|
||||||
title.value = res?.label ?? '';
|
title.value = res?.label ?? '';
|
||||||
editor.value?.load(res?.json, editable.value);
|
editor.value?.load(res?.json, editable.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const pushScene = async () => {
|
||||||
|
await pushSceneById(props.id);
|
||||||
|
};
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
const title = ref<string>('');
|
const title = ref<string>('');
|
||||||
@ -38,6 +46,17 @@ onMounted(() => {
|
|||||||
const editable = ref<boolean>(false);
|
const editable = ref<boolean>(false);
|
||||||
watch(editable, (v) => editor.value?.setState(v));
|
watch(editable, (v) => editor.value?.setState(v));
|
||||||
|
|
||||||
|
const toPush = () =>
|
||||||
|
Modal.confirm({
|
||||||
|
class: 'confirm',
|
||||||
|
title: t('您确定要推送该场景文件至数据库吗?'),
|
||||||
|
content: t('请确保当前场景已经保存,否则可能导致推送的文件版本不正确。'),
|
||||||
|
centered: true,
|
||||||
|
cancelText: t('返回'),
|
||||||
|
okText: t('推送'),
|
||||||
|
onOk: () => pushScene(),
|
||||||
|
});
|
||||||
|
|
||||||
const importScene = async () => {
|
const importScene = async () => {
|
||||||
const file = await selectFile('.scene');
|
const file = await selectFile('.scene');
|
||||||
if (!file?.size) return;
|
if (!file?.size) return;
|
||||||
@ -93,6 +112,7 @@ const selectRobot = (id: string) => {
|
|||||||
<i class="icon edit size-18 mr-8" />
|
<i class="icon edit size-18 mr-8" />
|
||||||
<span>{{ $t('启用编辑器') }}</span>
|
<span>{{ $t('启用编辑器') }}</span>
|
||||||
</a-button>
|
</a-button>
|
||||||
|
<a-button @click="toPush">{{ $t('同步') }}</a-button>
|
||||||
<a-button @click="importScene">{{ $t('导入') }}</a-button>
|
<a-button @click="importScene">{{ $t('导入') }}</a-button>
|
||||||
<a-button @click="exportScene">{{ $t('导出') }}</a-button>
|
<a-button @click="exportScene">{{ $t('导出') }}</a-button>
|
||||||
</a-space>
|
</a-space>
|
||||||
|
@ -35,13 +35,14 @@ export class EditorService extends Meta2d {
|
|||||||
scene.robots = detail.robots;
|
scene.robots = detail.robots;
|
||||||
}
|
}
|
||||||
const { robotGroups, robots, points, routes, areas } = scene;
|
const { robotGroups, robots, points, routes, areas } = scene;
|
||||||
this.open(undefined, false);
|
this.open();
|
||||||
await this.#loadScenePoints(points);
|
|
||||||
const data = this.data();
|
|
||||||
data.robotGroups = robotGroups;
|
|
||||||
data.robots = robots;
|
|
||||||
this.open(data, true);
|
|
||||||
this.setState(editable);
|
this.setState(editable);
|
||||||
|
this.#loadRobots(robotGroups, robots);
|
||||||
|
await this.#loadScenePoints(points);
|
||||||
|
this.#loadSceneRoutes(routes);
|
||||||
|
await this.#loadSceneAreas(areas);
|
||||||
|
this.store.historyIndex = undefined;
|
||||||
|
this.store.histories = [];
|
||||||
}
|
}
|
||||||
public save(): string {
|
public save(): string {
|
||||||
const scene: StandardScene = {
|
const scene: StandardScene = {
|
||||||
@ -55,6 +56,11 @@ export class EditorService extends Meta2d {
|
|||||||
return JSON.stringify(scene);
|
return JSON.stringify(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#loadRobots(groups?: RobotGroup[], robots?: RobotInfo[]): void {
|
||||||
|
this.#robotMap.clear();
|
||||||
|
robots?.forEach((v) => this.#robotMap.set(v.id, v));
|
||||||
|
this.#robotGroups$$.next(groups ?? []);
|
||||||
|
}
|
||||||
async #loadScenePoints(points?: StandardScenePoint[]): Promise<void> {
|
async #loadScenePoints(points?: StandardScenePoint[]): Promise<void> {
|
||||||
if (!points?.length) return;
|
if (!points?.length) return;
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
@ -68,6 +74,31 @@ export class EditorService extends Meta2d {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#loadSceneRoutes(routes?: StandardSceneRoute[]): void {
|
||||||
|
if (!routes?.length) return;
|
||||||
|
routes.map((v) => {
|
||||||
|
const { id, desc, from, to, type, pass, c1, c2, properties } = v;
|
||||||
|
this.addRoute([from, to], <MapRouteType>type, id);
|
||||||
|
this.setValue(
|
||||||
|
{ id, desc, properties, route: { type, pass, c1, c2 } },
|
||||||
|
{ render: false, history: false, doEvent: false },
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async #loadSceneAreas(areas?: StandardSceneArea[]): Promise<void> {
|
||||||
|
if (!areas?.length) return;
|
||||||
|
await Promise.all(
|
||||||
|
areas.map(async (v) => {
|
||||||
|
const { id, name, desc, x, y, w, h, type, points, routes, properties } = v;
|
||||||
|
await this.addArea({ x, y }, { x: x + w, y: y + h }, type, id);
|
||||||
|
this.setValue(
|
||||||
|
{ id, label: name, desc, properties, area: { type, points, routes } },
|
||||||
|
{ render: false, history: false, doEvent: false },
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#mapScenePoint(pen?: MapPen): StandardScenePoint | null {
|
#mapScenePoint(pen?: MapPen): StandardScenePoint | null {
|
||||||
if (!pen?.id || isEmpty(pen?.point)) return null;
|
if (!pen?.id || isEmpty(pen?.point)) return null;
|
||||||
const { id, label, desc, properties } = pen;
|
const { id, label, desc, properties } = pen;
|
||||||
@ -433,23 +464,26 @@ export class EditorService extends Meta2d {
|
|||||||
const w = Math.abs(p1.x - p2.x);
|
const w = Math.abs(p1.x - p2.x);
|
||||||
const h = Math.abs(p1.y - p2.y);
|
const h = Math.abs(p1.y - p2.y);
|
||||||
if (w * scale < 50 || h * scale < 60) return;
|
if (w * scale < 50 || h * scale < 60) return;
|
||||||
const selected = <MapPen[]>this.store.active;
|
|
||||||
id ||= s8();
|
|
||||||
const points = new Array<string>();
|
const points = new Array<string>();
|
||||||
const routes = new Array<string>();
|
const routes = new Array<string>();
|
||||||
switch (type) {
|
if (id) {
|
||||||
case MapAreaType.库区:
|
const selected = <MapPen[]>this.store.active;
|
||||||
selected?.filter(({ point }) => point?.type === MapPointType.动作点).forEach(({ id }) => points.push(id!));
|
switch (type) {
|
||||||
break;
|
case MapAreaType.库区:
|
||||||
case MapAreaType.互斥区:
|
selected?.filter(({ point }) => point?.type === MapPointType.动作点).forEach(({ id }) => points.push(id!));
|
||||||
selected?.filter(({ point }) => point?.type).forEach(({ id }) => points.push(id!));
|
break;
|
||||||
selected?.filter(({ route }) => route?.type).forEach(({ id }) => routes.push(id!));
|
case MapAreaType.互斥区:
|
||||||
break;
|
selected?.filter(({ point }) => point?.type).forEach(({ id }) => points.push(id!));
|
||||||
case MapAreaType.非互斥区:
|
selected?.filter(({ route }) => route?.type).forEach(({ id }) => routes.push(id!));
|
||||||
selected?.filter(({ point }) => point?.type).forEach(({ id }) => points.push(id!));
|
break;
|
||||||
break;
|
case MapAreaType.非互斥区:
|
||||||
default:
|
selected?.filter(({ point }) => point?.type).forEach(({ id }) => points.push(id!));
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
id = s8();
|
||||||
}
|
}
|
||||||
const pen: MapPen = {
|
const pen: MapPen = {
|
||||||
id,
|
id,
|
||||||
@ -464,9 +498,8 @@ export class EditorService extends Meta2d {
|
|||||||
area: { type, points, routes },
|
area: { type, points, routes },
|
||||||
locked: LockState.DisableMoveScale,
|
locked: LockState.DisableMoveScale,
|
||||||
};
|
};
|
||||||
const area = await this.addPen(pen, false, true, true);
|
const area = await this.addPen(pen, true, true, true);
|
||||||
this.bottom(area);
|
this.bottom(area);
|
||||||
// this.pushHistory({ type: EditType.Add, pens: [cloneDeep(pen)] });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateArea(id: string, info: Partial<MapAreaInfo>): void {
|
public updateArea(id: string, info: Partial<MapAreaInfo>): void {
|
||||||
@ -493,12 +526,6 @@ export class EditorService extends Meta2d {
|
|||||||
|
|
||||||
#load(theme: string): void {
|
#load(theme: string): void {
|
||||||
this.setTheme(theme);
|
this.setTheme(theme);
|
||||||
|
|
||||||
const { robots, robotGroups } = this.data();
|
|
||||||
this.#robotMap.clear();
|
|
||||||
robots?.forEach((r) => this.#robotMap.set(r.id, r));
|
|
||||||
this.#robotGroups$$.next(robotGroups ?? []);
|
|
||||||
|
|
||||||
this.find('point').forEach((pen) => {
|
this.find('point').forEach((pen) => {
|
||||||
if (!pen.point?.type) return;
|
if (!pen.point?.type) return;
|
||||||
if (pen.point.type < 10) return;
|
if (pen.point.type < 10) return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user