This commit is contained in:
chndfang 2025-04-30 00:17:09 +08:00
parent 0c9a59a98c
commit e523f7317b
13 changed files with 151 additions and 28 deletions

View File

@ -1 +1,2 @@
ENV_APP_TITLE=运输控制系统(开发)
ENV_APP_TITLE=运输控制系统(开发)
ENV_HTTP_BASE=/mocks

49
mocks/robot/getAll Normal file
View File

@ -0,0 +1,49 @@
{
"code": 200,
"success": true,
"data": [
{
"id": "mock-robot-1",
"label": "模拟机器人A",
"brand": "模拟品牌A",
"type": 1,
"ip": "127.0.1.1"
},
{
"id": "mock-robot-2",
"label": "模拟机器人B",
"brand": "模拟品牌A",
"type": 2,
"ip": "127.0.1.2"
},
{
"id": "mock-robot-3",
"label": "模拟机器人C",
"brand": "模拟品牌A",
"type": 3,
"ip": "127.0.1.3"
},
{
"id": "mock-robot-4",
"label": "模拟机器人D",
"brand": "模拟品牌B",
"type": 1,
"ip": "127.0.2.1"
},
{
"id": "mock-robot-5",
"label": "模拟机器人E",
"brand": "模拟品牌B",
"type": 2,
"ip": "127.0.2.2"
},
{
"id": "mock-robot-6",
"label": "模拟机器人F",
"brand": "模拟品牌B",
"type": 3,
"ip": "127.0.2.3"
}
],
"message": "模拟提示"
}

11
mocks/scene/getById Normal file
View File

@ -0,0 +1,11 @@
{
"code": 200,
"success": true,
"data": {
"id": "mock-scene-1",
"label": "模拟场景A",
"robotGroups": [],
"map": ""
},
"message": "模拟提示"
}

View File

@ -0,0 +1,18 @@
// @use 'asset/themes/dark' as dark;
// @use 'asset/themes/light' as light;
// $theme: dark;
// :root {
// [theme='dark'] {
// $theme: dark !global;
// }
// [theme='light'] {
// $theme: light !global;
// }
// }
// .ant-typography {
// color: #{$theme}.$text-1;
// }

View File

@ -0,0 +1,13 @@
import http from '@core/http';
import type { RobotInfo } from './type';
const enum API {
= '/robot/getAll',
}
export async function getAllRobot(): Promise<RobotInfo[]> {
type D = RobotInfo[];
const data = await http.get<D>(API.);
return data ?? [];
}

View File

@ -1,30 +1,30 @@
import type { RobotBrand, RobotState, RobotType } from './constant';
export interface RobotGroup {
id: number; // 机器人组id
id: string; // 机器人组id
label: string; // 机器人组名称
robotIds: number[]; // 机器人id列表
}
export interface RobotInfo {
group?: number; // 机器人组id
id: number; // 机器人id
id: string; // 机器人id
label: string; // 机器人名称
brand: RobotBrand; // 机器人品牌
type: RobotType; // 机器人类型
ip: string; // 机器人ip
isConnected?: boolean; // 机器人连接状态
}
export interface RobotDetail extends RobotInfo {
group?: string; // 机器人组id
isSimulative?: boolean; // 是否仿真机器人
battery?: number; // 机器人电量
minBattery?: number; // 最小电量
maxBattery?: number; // 最大电量
chargeBattery?: number; // 充电电量
swapBattery?: number; // 交换电量
isConnected?: boolean; // 机器人连接状态
state?: RobotState; // 机器人状态
canOrder?: boolean; // 接单状态
canStop?: boolean; // 急停状态
canControl?: boolean; // 控制状态
}
export interface RobotDetail extends RobotInfo {
isSimulative?: boolean; // 是否仿真机器人
minBattery?: number; // 最小电量
maxBattery?: number; // 最大电量
chargeBattery?: number; // 充电电量
swapBattery?: number; // 交换电量
}

View File

@ -1,5 +1,16 @@
import http from '@core/http';
import type { SceneDetail, SceneInfo } from './type';
const enum API {
= '/scene/getById',
}
export function getSceneById(id: number) {}
export async function getSceneById(id: SceneInfo['id']): Promise<SceneDetail | null> {
if (!id) return null;
type B = { id: string };
type D = SceneDetail;
const body = { id };
const data = await http.post<D, B>(API., body);
return data ?? null;
}

View File

@ -1,8 +1,10 @@
import type { RobotGroup } from '@api/robot';
export interface SceneInfo {
id: number; // 场景id
id: string; // 场景id
label: string; // 场景名称
robotGrroups?: RobotGroup[]; // 机器人组列表
}
export interface SceneDetail extends SceneInfo {
robotGroups?: RobotGroup[]; // 机器人组列表
map?: string; // 地图JSON
}

View File

@ -0,0 +1 @@
$text-1: #ffffffd9 !global;

View File

@ -0,0 +1 @@
$text-1: #000000d9 !global;

View File

@ -1,9 +0,0 @@
{
"token": {
"colorInfo": "#0ea278",
"colorPrimary": "#0dbb8a",
"colorTextBase": "#fafafa",
"colorBgBase": "#2a2c2c",
"colorBorderSecondary": "#595e5e"
}
}

View File

@ -1,5 +1,10 @@
<script setup lang="ts">
import type { RobotGroup } from '@api/robot';
import { getSceneById } from '@api/scene';
import { EditorService } from '@core/editor.service';
import { isEmpty } from 'lodash-es';
import { watch } from 'vue';
import { ref } from 'vue';
import { onMounted, provide, shallowRef } from 'vue';
const EDITOR_KEY = Symbol('editor-key');
@ -9,17 +14,37 @@ type Props = {
};
const props = defineProps<Props>();
const title = ref<string>('');
const groups = ref<RobotGroup[]>([]);
const map = ref<string>('');
onMounted(() => {
getSceneById(props.id).then((res) => {
title.value = res?.label ?? '';
groups.value = res?.robotGroups ?? [];
map.value = res?.map ?? '';
});
});
watch(map, (v) => {
editor.value?.load(v, !editable.value);
});
const container = shallowRef<HTMLDivElement>();
const editor = shallowRef<EditorService>();
provide(EDITOR_KEY, editor);
onMounted(() => {
editor.value = new EditorService(container.value!);
});
const editable = ref<boolean>(false);
</script>
<template>
<a-layout class="full">
<a-layout-header>header</a-layout-header>
<a-layout-header class="ph-16" style="height: 64px">
<a-flex justify="space-between">
<a-typography-text strong>{{ title }}</a-typography-text>
</a-flex>
</a-layout-header>
<a-layout>
<a-layout-sider>

View File

@ -28,8 +28,8 @@ http.interceptors.response.use(
);
type HttpInstance = Omit<AxiosInstance, 'get' | 'post'> & {
get: <R = void>(url: string, config?: AxiosRequestConfig) => Promise<R | undefined>;
post: <R = void, D = unknown>(url: string, data?: D, config?: AxiosRequestConfig<D>) => Promise<R | undefined>;
get: <D = void>(url: string, config?: AxiosRequestConfig) => Promise<D | undefined>;
post: <D = void, B = unknown>(url: string, body?: B, config?: AxiosRequestConfig<B>) => Promise<D | undefined>;
};
type CommonRes<T = void> = {