diff --git a/src/apis/map/type.ts b/src/apis/map/type.ts index ea507f2..868c120 100644 --- a/src/apis/map/type.ts +++ b/src/apis/map/type.ts @@ -48,7 +48,7 @@ export interface MapAreaInfo { //#endregion //#region 机器人 -export type MapRobotInfo = Pick; +export type MapRobotInfo = Pick; //#endregion export type Point = Record<'x' | 'y', number>; diff --git a/src/apis/robot/type.ts b/src/apis/robot/type.ts index 1aad5b1..160c5f4 100644 --- a/src/apis/robot/type.ts +++ b/src/apis/robot/type.ts @@ -42,4 +42,6 @@ export interface RobotRealtimeInfo extends RobotInfo { active?: boolean; // 是否运行 angle?: number; // 旋转角度 path?: Array; // 规划路径 + isWaring?: boolean; // 是否告警 + isFault?: boolean; // 是否故障 } diff --git a/src/assets/themes/editor-dark.json b/src/assets/themes/editor-dark.json index edfdc90..5145c90 100644 --- a/src/assets/themes/editor-dark.json +++ b/src/assets/themes/editor-dark.json @@ -35,6 +35,12 @@ "robot": { "stroke": "#01FDAF99", "fill": "#01FAAD33", - "line": "#01fdaf" + "line": "#01fdaf", + "stroke-normal": "#01FDAF99", + "fill-normal": "#01FAAD33", + "stroke-warning": "#FF851B99", + "fill-warning": "#FF851B33", + "stroke-fault": "#FF4D4F99", + "fill-fault": "#FF4D4F33" } } diff --git a/src/assets/themes/editor-light.json b/src/assets/themes/editor-light.json index 7f5581d..262cc2a 100644 --- a/src/assets/themes/editor-light.json +++ b/src/assets/themes/editor-light.json @@ -35,6 +35,12 @@ "robot": { "stroke": "#01FDAF99", "fill": "#01FAAD33", - "line": "#01fdaf" + "line": "#01fdaf", + "stroke-normal": "#01FDAF99", + "fill-normal": "#01FAAD33", + "stroke-warning": "#FF851B99", + "fill-warning": "#FF851B33", + "stroke-fault": "#FF4D4F99", + "fill-fault": "#FF4D4F33" } } diff --git a/src/pages/movement-supervision.vue b/src/pages/movement-supervision.vue index 1286708..5c65a81 100644 --- a/src/pages/movement-supervision.vue +++ b/src/pages/movement-supervision.vue @@ -33,13 +33,13 @@ const monitorScene = async () => { const ws = isMonitorMode.value ? await monitorRealSceneById(props.sid) : await monitorSceneById(props.sid); if (isNil(ws)) return; ws.onmessage = (e) => { - const { id, x, y, active, angle, path, ...rest } = JSON.parse(e.data || '{}'); + const { id, x, y, active, angle, path, isWaring, isFault, ...rest } = JSON.parse(e.data || '{}'); if (!editor.value?.checkRobotById(id)) return; editor.value?.updateRobot(id, rest); if (isNil(x) || isNil(y)) { editor.value.updatePen(id, { visible: false }); } else { - editor.value.refreshRobot(id, { x, y, active, angle, path }); + editor.value.refreshRobot(id, { x, y, active, angle, path, isWaring, isFault }); } }; client.value = ws; diff --git a/src/services/editor.service.ts b/src/services/editor.service.ts index 8c6b10a..97dec5d 100644 --- a/src/services/editor.service.ts +++ b/src/services/editor.service.ts @@ -574,14 +574,14 @@ export class EditorService extends Meta2d { const { rotate: or, robot } = pen ?? {}; if (!robot?.type) return; const { x: ox, y: oy } = this.getPenRect(pen!); - const { x: cx = 37, y: cy = 37, active, angle, path: points } = info; + const { x: cx = 37, y: cy = 37, active, angle, path: points, isWaring, isFault } = info; const x = cx - 37; const y = cy - 37; const rotate = angle ?? or; const path = points?.map((p) => ({ x: p.x - cx, y: p.y - cy })) ?? robot.path?.map((p) => ({ x: p.x + ox! - x, y: p.y + oy! - y })); - const o = { ...robot, ...omitBy({ active, path }, isNil) }; + const o = { ...robot, ...omitBy({ active, path, isWaring, isFault }, isNil) }; if (isNil(active)) { this.setValue({ id, x, y, rotate, robot: o, visible: true }, { render: true, history: false, doEvent: false }); } else { @@ -1133,6 +1133,27 @@ function drawArea(ctx: CanvasRenderingContext2D, pen: MapPen): void { ctx.restore(); } +/** + * 获取机器人状态 + * @param isWaring 是否告警 + * @param isFault 是否故障 + * @returns 机器人状态: 'fault' | 'warning' | 'normal' + * + * 判断逻辑: + * - isWaring=true, isFault=true → 故障 + * - isWaring=false, isFault=true → 故障 + * - isWaring=true, isFault=false → 告警 + * - isWaring=false, isFault=false → 正常 + */ +function getRobotStatus(isWaring?: boolean, isFault?: boolean): 'fault' | 'warning' | 'normal' { + // 只要 isFault 为 true,无论 isWaring 是什么,都是故障状态 + if (isFault) return 'fault'; + // 如果 isFault 为 false 但 isWaring 为 true,则是告警状态 + if (isWaring) return 'warning'; + // 两者都为 false 时,为正常状态 + return 'normal'; +} + /** * 绘制机器人的自定义函数 * @param ctx Canvas 2D绘制上下文 @@ -1142,16 +1163,20 @@ function drawRobot(ctx: CanvasRenderingContext2D, pen: MapPen): void { const theme = sTheme.editor; const { lineWidth: s = 1 } = pen.calculative ?? {}; const { x = 0, y = 0, width: w = 0, height: h = 0, rotate: deg = 0 } = pen.calculative?.worldRect ?? {}; - const { active, path } = pen.robot ?? {}; + const { active, path, isWaring, isFault } = pen.robot ?? {}; if (!active) return; + + // 根据机器人状态获取颜色 + const status = getRobotStatus(isWaring, isFault); + const ox = x + w / 2; const oy = y + h / 2; ctx.save(); ctx.ellipse(ox, oy, w / 2, h / 2, 0, 0, Math.PI * 2); - ctx.fillStyle = get(theme, 'robot.fill') ?? ''; + ctx.fillStyle = get(theme, `robot.fill-${status}`) ?? get(theme, 'robot.fill') ?? ''; ctx.fill(); - ctx.strokeStyle = get(theme, 'robot.stroke') ?? ''; + ctx.strokeStyle = get(theme, `robot.stroke-${status}`) ?? get(theme, 'robot.stroke') ?? ''; ctx.stroke(); if (path?.length) { ctx.strokeStyle = get(theme, 'robot.line') ?? '';