充电和脱离
This commit is contained in:
@@ -11,7 +11,10 @@ import {
|
||||
getCurrentRosInspection,
|
||||
getRosCarList,
|
||||
getRosInspectionTaskDetail,
|
||||
startRosCharging,
|
||||
stopDispatchRosInspectionTask,
|
||||
undockRosCharging,
|
||||
type RosChargingResult,
|
||||
} from "@/api/rosCar";
|
||||
import { getToken } from "@/utils/auth";
|
||||
import { parseRosMapYaml } from "@/utils/rosMapYaml";
|
||||
@@ -42,6 +45,8 @@ interface RosCarRecord {
|
||||
cameraWebrtcUrl2?: string;
|
||||
liftHeight?: number;
|
||||
liftDeviceStatusDescription?: string;
|
||||
dockStatus?: string;
|
||||
dockActive?: boolean;
|
||||
}
|
||||
|
||||
interface RosCarListResult {
|
||||
@@ -69,6 +74,8 @@ interface CarStatusPushData {
|
||||
mapYamlUrl?: string;
|
||||
status?: number;
|
||||
signal?: string;
|
||||
dockStatus?: string;
|
||||
dockActive?: boolean;
|
||||
}
|
||||
|
||||
interface CarVelocityPushData {
|
||||
@@ -115,6 +122,8 @@ interface DeviceItem {
|
||||
mapYamlUrl: string;
|
||||
whiteLightUrl: string;
|
||||
infraredUrl: string;
|
||||
dockStatus?: string;
|
||||
dockActive?: boolean;
|
||||
}
|
||||
|
||||
interface ProjectItem {
|
||||
@@ -195,6 +204,11 @@ interface RosDispatchResultResponse {
|
||||
msg?: string;
|
||||
}
|
||||
|
||||
interface RosChargingResultResponse {
|
||||
data?: RosChargingResult;
|
||||
msg?: string;
|
||||
}
|
||||
|
||||
interface AlertItem {
|
||||
id: string;
|
||||
title: string;
|
||||
@@ -286,6 +300,8 @@ function normalizeDeviceRecord(car: RosCarRecord, index: number): DeviceItem {
|
||||
mapYamlUrl: car.mapYamlUrl || "",
|
||||
whiteLightUrl: car.cameraWebrtcUrl || "",
|
||||
infraredUrl: car.cameraWebrtcUrl2 || "",
|
||||
dockStatus: car.dockStatus,
|
||||
dockActive: car.dockActive ?? false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -494,6 +510,8 @@ const inspectionTaskId = ref("");
|
||||
const currentInspection = ref<RosInspectionRecord | null>(null);
|
||||
const inspectionLoading = ref(false);
|
||||
const inspectionActionLoading = ref(false);
|
||||
const chargingActionLoading = ref(false);
|
||||
const undockingActionLoading = ref(false);
|
||||
const lastDispatchTime = ref("");
|
||||
const alertLoading = ref(false);
|
||||
const alertError = ref("");
|
||||
@@ -614,6 +632,27 @@ const currentScenario = computed(() => navScenario);
|
||||
const hasRobotPose = computed(
|
||||
() => typeof currentRobot.value.poseX === "number" && typeof currentRobot.value.poseY === "number",
|
||||
);
|
||||
// 回充状态文案:由 charging_dock 节点的 /dock_status 上报,未上报时给出中性提示
|
||||
const chargingStatusText = computed(() => {
|
||||
const device = currentRobot.value;
|
||||
|
||||
if (device.dockActive) {
|
||||
return device.dockStatus || "自动回充进行中";
|
||||
}
|
||||
return device.dockStatus || "回充状态未上报";
|
||||
});
|
||||
const chargingButtonText = computed(() => {
|
||||
if (currentRobot.value.dockActive) {
|
||||
return "回充中...";
|
||||
}
|
||||
return chargingActionLoading.value ? "处理中..." : "自动回充";
|
||||
});
|
||||
const undockingButtonText = computed(() => {
|
||||
if (currentRobot.value.dockActive) {
|
||||
return "处理中...";
|
||||
}
|
||||
return undockingActionLoading.value ? "处理中..." : "充电脱离";
|
||||
});
|
||||
|
||||
// 将 ROS 米制坐标转换成地图图片像素坐标,路线和机器人定位共用同一套转换
|
||||
function rosPoseToMapPoint(poseX: number, poseY: number, poseYaw = 0): RobotMapPoint | null {
|
||||
@@ -861,6 +900,74 @@ function confirmStopInspection() {
|
||||
showConfirmDialog("停止巡检", "确认停止当前巡检任务吗?", () => runInspectionAction("stop"));
|
||||
}
|
||||
|
||||
// 手动触发一次自动回充;需要小车在线且车端已启动回充节点
|
||||
async function runStartCharging() {
|
||||
const carId = currentRobot.value.carId;
|
||||
|
||||
if (!carId) {
|
||||
window.$message.warning("未获取到小车ID,请先在设备管理中确认小车已保存");
|
||||
return;
|
||||
}
|
||||
|
||||
chargingActionLoading.value = true;
|
||||
|
||||
try {
|
||||
const response = (await startRosCharging(carId)) as RosChargingResultResponse;
|
||||
const accepted = response.data?.accepted ?? false;
|
||||
const message = response.data?.message
|
||||
|| response.msg
|
||||
|| (accepted ? "已触发自动回充" : "触发自动回充失败");
|
||||
|
||||
if (accepted) {
|
||||
window.$message.success(message);
|
||||
} else {
|
||||
window.$message.warning(message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
chargingActionLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function confirmStartCharging() {
|
||||
showConfirmDialog("自动回充", "确认让小车执行自动回充吗?", () => runStartCharging());
|
||||
}
|
||||
|
||||
// 手动触发一次脱离充电桩;用于充电完成后手动让小车离开充电桩
|
||||
async function runUndockCharging() {
|
||||
const carId = currentRobot.value.carId;
|
||||
|
||||
if (!carId) {
|
||||
window.$message.warning("未获取到小车ID,请先在设备管理中确认小车已保存");
|
||||
return;
|
||||
}
|
||||
|
||||
undockingActionLoading.value = true;
|
||||
|
||||
try {
|
||||
const response = (await undockRosCharging(carId)) as RosChargingResultResponse;
|
||||
const accepted = response.data?.accepted ?? false;
|
||||
const message = response.data?.message
|
||||
|| response.msg
|
||||
|| (accepted ? "已触发脱离充电桩" : "触发脱离充电桩失败");
|
||||
|
||||
if (accepted) {
|
||||
window.$message.success(message);
|
||||
} else {
|
||||
window.$message.warning(message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
undockingActionLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function confirmUndockCharging() {
|
||||
showConfirmDialog("充电脱离", "确认让小车脱离充电桩吗?", () => runUndockCharging());
|
||||
}
|
||||
|
||||
// 切换设备时将当前设备已有升降柱高度回显到目标高度输入框
|
||||
function syncLiftTargetFromDevice(device?: DeviceItem) {
|
||||
if (!device || device.liftHeight === "--") {
|
||||
@@ -921,6 +1028,8 @@ function applyCarStatusPush(data: CarStatusPushData) {
|
||||
poseYaw: typeof data.poseYaw === "number" ? data.poseYaw : currentDevice.poseYaw,
|
||||
mapPgmUrl: data.mapPgmUrl || currentDevice.mapPgmUrl,
|
||||
mapYamlUrl: data.mapYamlUrl || currentDevice.mapYamlUrl,
|
||||
dockStatus: typeof data.dockStatus === "string" ? data.dockStatus : currentDevice.dockStatus,
|
||||
dockActive: typeof data.dockActive === "boolean" ? data.dockActive : currentDevice.dockActive,
|
||||
};
|
||||
|
||||
projectDevices.value[0].devices.splice(deviceIndex, 1, nextDevice);
|
||||
@@ -1868,6 +1977,26 @@ function getStatusClass(status: DeviceItem["status"]) {
|
||||
>
|
||||
{{ inspectionActionLoading ? "处理中..." : "下发巡检" }}
|
||||
</button>
|
||||
<div class="charging-status-row">
|
||||
<span :class="['charging-status-dot', { active: currentRobot.dockActive }]"></span>
|
||||
<span class="charging-status-text">{{ chargingStatusText }}</span>
|
||||
</div>
|
||||
<button
|
||||
class="inspection-action-btn charging"
|
||||
type="button"
|
||||
:disabled="chargingActionLoading || currentRobot.dockActive"
|
||||
@click="confirmStartCharging"
|
||||
>
|
||||
{{ chargingButtonText }}
|
||||
</button>
|
||||
<button
|
||||
class="inspection-action-btn undock"
|
||||
type="button"
|
||||
:disabled="undockingActionLoading || currentRobot.dockActive"
|
||||
@click="confirmUndockCharging"
|
||||
>
|
||||
{{ undockingButtonText }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user