和算法测试成功第一步 状态界面看到经纬度信息和保存可以成功

This commit is contained in:
mmc
2026-08-19 17:00:07 +08:00
parent 5073f64240
commit be8576b887
9 changed files with 237 additions and 180 deletions

10
env.js
View File

@@ -15,11 +15,13 @@ const envConfig = {
//mqtt_url: "ws://1.95.137.212:8083/mqtt", //mqtt_url: "ws://1.95.137.212:8083/mqtt",
//geoserver_url: "http://192.168.2.59:7000/geoserver" //geoserver_url: "http://192.168.2.59:7000/geoserver"
baseURL: 'http://1.95.137.212:8081',//http://192.168.2.56:8081 //baseURL: 'http://1.95.137.212:8081',//http://192.168.2.56:8081
baseURL: 'http://192.168.2.34:8081',//http://192.168.2.56:8081
//baseURL: 'https://serviceri.satabot.com', //baseURL: 'https://serviceri.satabot.com',
WS_URL: 'ws://1.95.137.212:9002/ws/', //WS_URL: 'ws://1.95.137.212:9002/ws/',
WS_URL: 'ws://192.168.2.34:9002/ws/',
mqtt_url: "ws://1.95.137.212:8083/mqtt", mqtt_url: "ws://1.95.137.212:8083/mqtt",
geoserver_url: "http://1.95.137.212:59018/geoserver" geoserver_url: "http://1.95.137.212:7900/geoserver"
//baseURL: 'http://1.95.137.212:59015',//http://192.168.2.56:8081 //baseURL: 'http://1.95.137.212:59015',//http://192.168.2.56:8081
////baseURL: 'https://serviceri.satabot.com', ////baseURL: 'https://serviceri.satabot.com',
@@ -40,7 +42,7 @@ const envConfig = {
//baseURL: 'https://serviceri.satabot.com', //baseURL: 'https://serviceri.satabot.com',
WS_URL: 'ws://1.95.137.212:9002/ws/', WS_URL: 'ws://1.95.137.212:9002/ws/',
mqtt_url: "ws://1.95.137.212:8083/mqtt", mqtt_url: "ws://1.95.137.212:8083/mqtt",
geoserver_url: "http://1.95.137.212:59018/geoserver" geoserver_url: "http://1.95.137.212:7900/geoserver"
}, },
}; };

View File

@@ -455,6 +455,15 @@ export function hasPermission(params) {
}) })
} }
///iot/workRecord/getTaskPath?taskId=74 get 获取算法回传的路径
export function getTaskPath(params) {
return request({
url: '/iot/workRecord/getTaskPath',
method: 'get',
params
})
}

View File

@@ -344,7 +344,7 @@ const CesiumMap = React.forwardRef(({ ifClear, ifClearPlanLine, ifClearNavLine,
}, [markedPoints]); }, [markedPoints]);
function showRobotTooltip(tooltip, robot, position) { function showRobotTooltip(tooltip, robot, position) {
const { t } = useTranslation(); const { t } = useTranslation();
const statusMap = { const statusMap = {
1: { text: t('common.working'), color: "#10b981" }, 1: { text: t('common.working'), color: "#10b981" },
2: { text: t('devices.idle'), color: "#f59e0b" }, 2: { text: t('devices.idle'), color: "#f59e0b" },
@@ -498,6 +498,9 @@ const CesiumMap = React.forwardRef(({ ifClear, ifClearPlanLine, ifClearNavLine,
if (index == 2 && from == "other") { if (index == 2 && from == "other") {
flyToLayer(layerIdentifier, baseUrl, 100); flyToLayer(layerIdentifier, baseUrl, 100);
} }
//if (index == 0 && from == "other") {
// flyToLayer(layerIdentifier, baseUrl, 100);
//}
//getLayerBoundsAndFit(wmsUrl, layerName); //getLayerBoundsAndFit(wmsUrl, layerName);
if (baseUrl.includes('/gwc/service/wms')) { if (baseUrl.includes('/gwc/service/wms')) {
@@ -1599,7 +1602,6 @@ const CesiumMap = React.forwardRef(({ ifClear, ifClearPlanLine, ifClearNavLine,
// 如果有航向角,设置旋转 // 如果有航向角,设置旋转
let rotation = 0; let rotation = 0;
console.log('realtimePosition.heading:', realtimePosition.heading);
if (realtimePosition?.heading !== undefined && !isNaN(Number(realtimePosition.heading))) { if (realtimePosition?.heading !== undefined && !isNaN(Number(realtimePosition.heading))) {

View File

@@ -484,7 +484,7 @@ export default function SmartDeviceManagement({
))} ))}
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item label={t('systemSetting.leader')} name="userId" rules={[{ required: true, message: t('systemSetting.fixed2PleaseSelectFixed2LeaderFixed2') }]}> <Form.Item label={t('systemSetting.leader')} name="userId" >
<Select <Select
placeholder={t('systemSetting.leaderFixed2')} placeholder={t('systemSetting.leaderFixed2')}
allowClear allowClear

View File

@@ -95,6 +95,7 @@ export default function DeviceStatusPage() {
const [connecting, setConnecting] = useState(false); const [connecting, setConnecting] = useState(false);
const [wsStatus, setWsStatus] = useState('disconnected'); const [wsStatus, setWsStatus] = useState('disconnected');
const [wsDeviceInfo, setWsDeviceInfo] = useState({}); const [wsDeviceInfo, setWsDeviceInfo] = useState({});
const [locationInfo, setLocationInfo] = useState({});
// 👇 加上这两个 // 👇 加上这两个
@@ -387,8 +388,9 @@ export default function DeviceStatusPage() {
const runningStatus = useMemo(() => { const runningStatus = useMemo(() => {
console.log(locationInfo, "locationInfo")
// 判断对象是否为空 // 判断对象是否为空
if ((!wsDeviceInfo || Object.keys(wsDeviceInfo).length === 0) && !isUAV) { if ((!wsDeviceInfo || Object.keys(wsDeviceInfo).length === 0) && (!locationInfo || Object.keys(locationInfo).length === 0) && !isUAV) {
return {}; return {};
} }
if (isUAV) { if (isUAV) {
@@ -403,8 +405,10 @@ export default function DeviceStatusPage() {
: { : {
...base, ...base,
...wsDeviceInfo, ...wsDeviceInfo,
...locationInfo
}; };
}, [device, wsDeviceInfo, isUAV]); }, [device, wsDeviceInfo, isUAV, locationInfo]);
console.log(runningStatus, "runningStatus")
const { video: robotVideo, error, ready } = useWebRTCPlayer( const { video: robotVideo, error, ready } = useWebRTCPlayer(
(!isUAV && isVideoPlaying) ? (device?.serialNumber || '') : '', (!isUAV && isVideoPlaying) ? (device?.serialNumber || '') : '',
@@ -433,8 +437,8 @@ export default function DeviceStatusPage() {
} }
// 2. 机器人:从 wsDeviceInfo / runningStatus 取实时经纬度 // 2. 机器人:从 wsDeviceInfo / runningStatus 取实时经纬度
const robotLon = runningStatus.longitude || wsDeviceInfo.longitude; const robotLon = runningStatus.longitude || locationInfo.longitude;
const robotLat = runningStatus.latitude || wsDeviceInfo.latitude; const robotLat = runningStatus.latitude || locationInfo.latitude;
if (robotLon && robotLat) { if (robotLon && robotLat) {
return { return {
@@ -453,6 +457,7 @@ export default function DeviceStatusPage() {
const controller = new DeviceController(userInfo, messageApi); const controller = new DeviceController(userInfo, messageApi);
controller.onDeviceInfoUpdate = setWsDeviceInfo; controller.onDeviceInfoUpdate = setWsDeviceInfo;
controller.onLocationInfoUpdate = setLocationInfo;
controller.onControlStatusChange = setIsControlled; controller.onControlStatusChange = setIsControlled;
controller.onHasControlRightChange = setHasControlRight; controller.onHasControlRightChange = setHasControlRight;
controller.onRequestControlStatusChange = setConnecting; controller.onRequestControlStatusChange = setConnecting;
@@ -485,6 +490,7 @@ export default function DeviceStatusPage() {
return; return;
} }
setWsDeviceInfo({}); setWsDeviceInfo({});
setLocationInfo({});
controllerRef.current.connectDevice(device); controllerRef.current.connectDevice(device);
@@ -656,103 +662,6 @@ export default function DeviceStatusPage() {
}; };
// 完成功能 - 调用路径规划接口 // 完成功能 - 调用路径规划接口
const handleComplete = async () => {
//如果时弓子模式
if (isLoopMode) {
if (markedPoints.length < 3) {
messageApi.warning(t('devices.minThreePoints'));
return;
}
try {
// 准备路径规划请求参数
const positionPoints = [...markedPoints];
const requestParams = {
reference: {
lat: positionPoints[0].lat,
lon: positionPoints[0].lon,
},
heading: 0,
outer: {
position: positionPoints.map(point => ({
lat: point.lat,
lon: point.lon,
})),
sideWidth: 0.0,
},
holes: [],
workType: 0,
};
const response = await fetch('https://servicepathplan.satabot.com/api/path', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestParams),
});
const result = await response.json();
if (result) {
const path = result?.data?.path?.map(p => {
return {
lng: p.lon,
lat: p.lat
}
})
setPoints(path);
setSavePath({
path: path, // 存储返回的路径结果
outer: requestParams?.outer?.position?.map(p => {
return {
lng: p.lon,
lat: p.lat
}
}
),
planModel: 0,
});
setCompleteFlag(true);
messageApi.success(t('devices.pathPlanDone'));
}
} catch (error) {
console.error('路径规划失败:', error);
messageApi.error(t('devices.pathPlanFailRetry'));
}
} else {
const positionPoints = [...markedPoints].map(item => {
return {
lng: item.lon,
lat: item.lat
}
});
setPoints(positionPoints);
setSavePath({
path: positionPoints, // 存储返回的路径结果
outer: [],
planModel: 2,
});
setCompleteFlag(true);
}
};
// 打开保存模态框
const handleOpenSaveModal = () => {
if (!completeFlag) {
messageApi.warning(t('devices.completePathFirst'));
return;
}
setPlotName('');
setIsSaveModalVisible(true);
};
// 保存功能
const handleSave = async () => { const handleSave = async () => {
if (!plotName.trim()) { if (!plotName.trim()) {
messageApi.warning(t('devices.inputPlotName')); messageApi.warning(t('devices.inputPlotName'));
@@ -761,6 +670,15 @@ export default function DeviceStatusPage() {
setIsSaving(true); setIsSaving(true);
try { try {
// ✅重点:接收handleComplete返回的path数据,不再读组件savePath state
const pathResult = await handleComplete();
if (!pathResult) {
messageApi.warning(t('devices.saveFail'));
// 路径规划失败/校验不通过直接终止
return;
}
// 1. 获取地图截图 // 1. 获取地图截图
let screenshotDataUrl = null; let screenshotDataUrl = null;
if (mapRef.current) { if (mapRef.current) {
@@ -776,18 +694,20 @@ export default function DeviceStatusPage() {
const file = dataUrlToFile(screenshotDataUrl, "screenshot.jpg"); const file = dataUrlToFile(screenshotDataUrl, "screenshot.jpg");
console.log("blob", file) console.log("blob", file)
if (file instanceof File) { if (file instanceof File) {
formData.append('file', file); formData.append('file', file);
} }
} }
// 4. 添加 workRecord // 4. 添加 workRecord,直接使用函数返回的 pathResult,不读取state savePath
const workRecord = { const workRecord = {
workName: plotName, workName: plotName,
siteId: stationId, siteId: stationId,
jsonData: savePath, orgId: currentStation?.orgId,
jsonData: pathResult, // 直接用返回值,彻底规避state异步延迟
mode: isLoopMode ? "coverage" : "single_point",//"区域还是单点"
}; };
console.log("workRecord", workRecord)
formData.append( formData.append(
"workRecord", "workRecord",
new Blob([JSON.stringify(workRecord)], { new Blob([JSON.stringify(workRecord)], {
@@ -795,8 +715,6 @@ export default function DeviceStatusPage() {
}) })
); );
//formData.append('workRecord', JSON.stringify(workRecord));
// 5. 调用保存接口 // 5. 调用保存接口
const res = await addRoute(formData); const res = await addRoute(formData);
@@ -818,6 +736,95 @@ export default function DeviceStatusPage() {
} }
}; };
/**
* 修改handleComplete:计算完成后 return路径对象;失败返回null
*/
const handleComplete = async () => {
//如果是闭环模式
if (isLoopMode) {
if (markedPoints.length < 3) {
messageApi.warning(t('devices.minThreePoints'));
return null; //校验失败返回null
}
try {
// 准备路径规划请求参数
let positionPoints = [...markedPoints];
// =========新增:保证闭环,第一个点和最后一个点一致=========
const firstPt = positionPoints[0];
const lastPt = positionPoints[positionPoints.length - 1];
// 判断经纬度是否相等,不相等就把首点追加到末尾
if (!(firstPt.lat === lastPt.lat && firstPt.lon === lastPt.lon)) {
positionPoints.push({ ...firstPt });
}
const requestParams = {
outer: {
position: positionPoints.map(point => ({
lat: point.lat,
lng: point.lon,
})),
},
};
const path = requestParams?.outer?.position
setPoints(path);
const resultObj = {
path: path,
outer: requestParams?.outer?.position?.map(p => {
return {
lng: p.lon,
lat: p.lat
}
}),
};
setSavePath(resultObj);
setCompleteFlag(true);
messageApi.success(t('devices.pathPlanDone'));
return resultObj; // ✅返回计算好的数据给上层调用
} catch (error) {
console.error('路径规划失败:', error);
messageApi.error(t('devices.pathPlanFailRetry'));
return null;
}
} else {
// 单点模式
const positionPoints = [...markedPoints].map(item => {
return {
lng: item.lon,
lat: item.lat
}
});
setPoints(positionPoints);
const resultObj = {
path: positionPoints,
outer: [],
};
setSavePath(resultObj);
setCompleteFlag(true);
return resultObj; // ✅返回
}
};
// 打开保存模态框
const handleOpenSaveModal = () => {
//if (!completeFlag) {
// messageApi.warning(t('devices.completePathFirst'));
// return;
//}
setPlotName('');
setIsSaveModalVisible(true);
};
const realtimeType = useMemo(() => { const realtimeType = useMemo(() => {
return isUAV ? 'plane' : 'car'; return isUAV ? 'plane' : 'car';
}, [isUAV]); }, [isUAV]);
@@ -856,8 +863,8 @@ export default function DeviceStatusPage() {
}} }}
> >
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}> <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<Text strong>{t('devices.pathPlanning')}:</Text> <Text strong>{t('devices.pathPlanning')}:</Text>
<Text type="secondary">{t('devices.markedPointsCount', { count: markedPoints.length })}</Text> <Text type="secondary">{t('devices.markedPointsCount', { count: markedPoints.length })}</Text>
</div> </div>
<Space size="middle"> <Space size="middle">
<Space> <Space>
@@ -882,18 +889,18 @@ export default function DeviceStatusPage() {
> >
{t('devices.clearMarks')} {t('devices.clearMarks')}
</Button> </Button>
<Button {/*<Button
type="primary" type="primary"
ghost ghost
onClick={handleComplete} onClick={handleComplete}
disabled={markedPoints.length < 2} disabled={markedPoints.length < 2}
> >
{t('devices.complete')} {t('devices.complete')}
</Button> </Button>*/}
<Button <Button
type="primary" type="primary"
onClick={handleOpenSaveModal} onClick={handleOpenSaveModal}
disabled={!completeFlag} //disabled={!completeFlag}
> >
{t('common.save')} {t('common.save')}
</Button> </Button>
@@ -961,7 +968,7 @@ export default function DeviceStatusPage() {
title={ title={
<> <>
<VideoCameraOutlined /> <VideoCameraOutlined />
{t('devices.stationVideo')} {t('devices.stationVideo')}
</> </>
} }
bordered={false} bordered={false}
@@ -1039,7 +1046,7 @@ export default function DeviceStatusPage() {
title={ title={
<> <>
<VideoCameraOutlined /> <VideoCameraOutlined />
{t('devices.droneVideo')} {t('devices.droneVideo')}
</> </>
} }
bordered={false} bordered={false}
@@ -1103,33 +1110,33 @@ export default function DeviceStatusPage() {
}}> }}>
<div style={{ marginBottom: 6, fontWeight: 600, color: '#1890ff' }}>{t('devices.robotStatus')}</div> <div style={{ marginBottom: 6, fontWeight: 600, color: '#1890ff' }}>{t('devices.robotStatus')}</div>
<div style={{ display: 'flex', gap: '3px 10px', flexWrap: 'wrap' }}> <div style={{ display: 'flex', gap: '3px 10px', flexWrap: 'wrap' }}>
<span>{t('devices.rtBattery')}</span> <span>{t('devices.rtBattery')}:</span>
<span style={{ color: (runningStatus.battery || 0) < 20 ? '#ff4d4f' : '#52c41a' }}> <span style={{ color: (runningStatus.battery || 0) < 20 ? '#ff4d4f' : '#52c41a' }}>
{runningStatus.battery !== undefined ? `${runningStatus.battery}%` : '-'} {runningStatus.battery !== undefined ? `${runningStatus.battery}%` : '-'}
</span> </span>
<span>{t('devices.rtVoltage')}</span> <span>{t('devices.rtVoltage')}:</span>
<span>{runningStatus.voltage !== undefined ? `${Number(runningStatus.voltage).toFixed(2)}V` : '-'}</span> <span>{runningStatus.voltage !== undefined ? `${Number(runningStatus.voltage).toFixed(2)}V` : '-'}</span>
<span>{t('devices.rtLeftMotor')}</span> <span>{t('devices.rtLeftMotor')}:</span>
<span>{runningStatus.leftCurrent !== undefined ? `${Number(runningStatus.leftCurrent).toFixed(2)}A` : '-'}</span> <span>{runningStatus.leftCurrent !== undefined ? `${Number(runningStatus.leftCurrent).toFixed(2)}A` : '-'}</span>
<span>{t('devices.rtRightMotor')}</span> <span>{t('devices.rtRightMotor')}:</span>
<span>{runningStatus.rightCurrent !== undefined ? `${Number(runningStatus.rightCurrent).toFixed(2)}A` : '-'}</span> <span>{runningStatus.rightCurrent !== undefined ? `${Number(runningStatus.rightCurrent).toFixed(2)}A` : '-'}</span>
<span>{t('devices.rtLeftSpeed')}</span> <span>{t('devices.rtLeftSpeed')}:</span>
<span>{runningStatus.leftMeasureSpeed !== undefined ? `${Number(runningStatus.leftMeasureSpeed).toFixed(1)}rpm` : '-'}</span> <span>{runningStatus.leftMeasureSpeed !== undefined ? `${Number(runningStatus.leftMeasureSpeed).toFixed(1)}rpm` : '-'}</span>
<span>{t('devices.rtRightSpeed')}</span> <span>{t('devices.rtRightSpeed')}:</span>
<span>{runningStatus.rightMeasureSpeed !== undefined ? `${Number(runningStatus.rightMeasureSpeed).toFixed(1)}rpm` : '-'}</span> <span>{runningStatus.rightMeasureSpeed !== undefined ? `${Number(runningStatus.rightMeasureSpeed).toFixed(1)}rpm` : '-'}</span>
<span>{t('devices.rtLeftTemp')}</span> <span>{t('devices.rtLeftTemp')}:</span>
<span>{runningStatus.leftMotorTemp !== undefined ? `${Number(runningStatus.leftMotorTemp).toFixed(1)}℃` : '-'}</span> <span>{runningStatus.leftMotorTemp !== undefined ? `${Number(runningStatus.leftMotorTemp).toFixed(1)}℃` : '-'}</span>
<span>{t('devices.rtRightTemp')}</span> <span>{t('devices.rtRightTemp')}:</span>
<span>{runningStatus.rightMotorTemp !== undefined ? `${Number(runningStatus.rightMotorTemp).toFixed(1)}℃` : '-'}</span> <span>{runningStatus.rightMotorTemp !== undefined ? `${Number(runningStatus.rightMotorTemp).toFixed(1)}℃` : '-'}</span>
<span>{t('devices.rtMainTemp')}</span> <span>{t('devices.rtMainTemp')}:</span>
<span>{runningStatus.chipTemp !== undefined ? `${Number(runningStatus.chipTemp).toFixed(1)}℃` : '-'}</span> <span>{runningStatus.chipTemp !== undefined ? `${Number(runningStatus.chipTemp).toFixed(1)}℃` : '-'}</span>
<span>{t('devices.rtHeadingAngle')}</span> <span>{t('devices.rtHeadingAngle')}:</span>
<span>{runningStatus.yaw !== undefined ? `${Number(runningStatus.yaw).toFixed(1)}°` : '-'}</span> <span>{runningStatus.yaw !== undefined ? `${Number(runningStatus.yaw).toFixed(1)}°` : '-'}</span>
<span>{t('devices.rtPitchAngle')}</span> <span>{t('devices.rtPitchAngle')}:</span>
<span>{runningStatus.pitch !== undefined ? `${Number(runningStatus.pitch).toFixed(1)}°` : '-'}</span> <span>{runningStatus.pitch !== undefined ? `${Number(runningStatus.pitch).toFixed(1)}°` : '-'}</span>
<span>{t('devices.rtHeadingStatus')}</span> <span>{t('devices.rtHeadingStatus')}:</span>
<span>{runningStatus.headingStatus !== undefined ? `${runningStatus.headingStatus == 1 ? t('devices.rtInitialized') : t('devices.uninitialized')}` : '-'}</span> <span>{runningStatus.headingStatus !== undefined ? `${runningStatus.headingStatus == 1 ? t('devices.rtInitialized') : t('devices.uninitialized')}` : '-'}</span>
<span>{t('devices.rtPositioning')}</span> <span>{t('devices.rtPositioning')}:</span>
<span> <span>
{runningStatus.qual == 0 ? t('constants.locationInvalid') : {runningStatus.qual == 0 ? t('constants.locationInvalid') :
runningStatus.qual == 1 ? t('devices.gpsSingle') : runningStatus.qual == 1 ? t('devices.gpsSingle') :
@@ -1137,9 +1144,9 @@ export default function DeviceStatusPage() {
runningStatus.qual == 4 ? t('devices.rtkFixed2') : runningStatus.qual == 4 ? t('devices.rtkFixed2') :
runningStatus.qual == 5 ? t('devices.rtkFloat') : t('constants.locationUnknown')} runningStatus.qual == 5 ? t('devices.rtkFloat') : t('constants.locationUnknown')}
</span> </span>
<span>{t('devices.rtSatellites')}</span> <span>{t('devices.rtSatellites')}:</span>
<span>{t('devices.satelliteCount', { count: runningStatus.satelliteCnt || 0 })}</span> <span>{t('devices.satelliteCount', { count: runningStatus.satelliteCnt || 0 })}</span>
<span>{t('devices.rtMode')}</span> <span>{t('devices.rtMode')}:</span>
<span> <span>
{runningStatus.controlMode == 1 ? t('devices.localMode') : {runningStatus.controlMode == 1 ? t('devices.localMode') :
runningStatus.controlMode == 3 ? t('devices.remoteMode') : t('constants.locationUnknown')} runningStatus.controlMode == 3 ? t('devices.remoteMode') : t('constants.locationUnknown')}
@@ -1322,7 +1329,7 @@ export default function DeviceStatusPage() {
title={ title={
<> <>
<ControlOutlined /> <ControlOutlined />
{t('devices.remoteControl')} {t('devices.remoteControl')}
</> </>
} }
bordered={false} bordered={false}

View File

@@ -5,7 +5,8 @@ import {
Modal, InputNumber, Modal, InputNumber,
TimePicker, TimePicker,
Popconfirm, Popconfirm,
App App,
Radio
} from 'antd'; } from 'antd';
import { import {
PlusOutlined, ImportOutlined, NodeIndexOutlined, PlusOutlined, ImportOutlined, NodeIndexOutlined,
@@ -35,6 +36,7 @@ import {
getSiteDeviceTaskHistory, getSiteDeviceTaskHistory,
getRouteByTask, getRouteByTask,
deleteRoute, deleteRoute,
getTaskPath,
} from '../../api/device'; } from '../../api/device';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import DraggableBox from '../Draggable'; import DraggableBox from '../Draggable';
@@ -116,6 +118,8 @@ export default function RobotTaskPage() {
robot: null, robot: null,
dateRange: null, dateRange: null,
}); });
// 取消任务模式 normal普通取消 force强制取消
const [cancelMode, setCancelMode] = useState<'normal' | 'force'>('normal');
@@ -244,7 +248,7 @@ export default function RobotTaskPage() {
useEffect(() => { useEffect(() => {
const controller = new DeviceController(userInfo, messageApi); const controller = new DeviceController(userInfo, messageApi);
controller.onDeviceInfoUpdate = setRobotRealtimePosition; controller.onLocationInfoUpdate = setRobotRealtimePosition;
controller.onIsFinished = handleFinish; controller.onIsFinished = handleFinish;
controller.handleArrivedPoint = handleFinishEdPoint; controller.handleArrivedPoint = handleFinishEdPoint;
@@ -394,22 +398,14 @@ export default function RobotTaskPage() {
// 调用接口获取路线详情 // 调用接口获取路线详情
const fetchRouteDetail = async () => { const fetchRouteDetail = async () => {
try { try {
const res = await getSingleRouteList({ id: selectedPathWork.id }); const res = await getTaskPath({ taskId: selectedPathWork.id })
//const res = await getSingleRouteList({ id: selectedPathWork.id });
if (res?.code === 200 && res?.data) { if (res?.code === 200 && res?.data) {
let pathPoints = []; let pathPoints = [];
let outerPoints = [];
let method = '';//0弓子 2 回子
try { try {
// 尝试解析 JSON // 尝试解析 JSON
if (res.data.jsonData) { pathPoints = res.data || [];
const data = typeof res.data.jsonData === 'string'
? JSON.parse(res.data.jsonData)
: res.data.jsonData;
pathPoints = data?.path || [];
outerPoints = data?.outer || [];
method = data?.planModel;
}
} catch (err) { } catch (err) {
console.error('解析路线数据失败:', err); console.error('解析路线数据失败:', err);
} }
@@ -417,15 +413,9 @@ export default function RobotTaskPage() {
if (pathPoints.length === 0) { if (pathPoints.length === 0) {
utils.message.warning(t('devices.route2')); utils.message.warning(t('devices.route2'));
} }
//if (outerPoints.length === 0 && method == 2) {
// utils.message.warning(t('devices.route2'));
//}
//if (method == 0) {
setPoints(pathPoints);
//} else {
// setPoints(outerPoints);
//} setPoints(pathPoints);
} else { } else {
setPoints([]); setPoints([]);
} }
@@ -653,13 +643,14 @@ export default function RobotTaskPage() {
}; };
// 取消任务 // 取消任务
const handleCancelTask = async (task) => { const handleCancelTask = async (task, mode) => {
try { try {
const params = { const params = {
taskId: task.id, taskId: task.id,
//deviceId: task.deviceId, //deviceId: task.deviceId,
siteId: stationId, siteId: stationId,
orgId: task.orgId, orgId: task.orgId,
forceCancel: mode === 'force' ? true : false,
}; };
const res = await cancelRoute(params); const res = await cancelRoute(params);
if (res.code === 200 && res.data == true) { if (res.code === 200 && res.data == true) {
@@ -832,15 +823,17 @@ export default function RobotTaskPage() {
dataIndex: 'taskStaus', dataIndex: 'taskStaus',
width: 100, width: 100,
render: (status, record) => { render: (status, record) => {
console.log('status', status, record);
const statusMap = { const statusMap = {
'NEW': { color: 'default', text: t('devices.statusNew') }, 'NEW': { color: 'default', text: t('devices.statusNew') },
'EXECUTING': { color: 'processing', text: t('workOrder.inProgress') }, 'EXECUTING': { color: 'processing', text: t('workOrder.inProgress') },
'PAUSE': { color: 'warning', text: t('devices.statusPaused') }, 'PAUSE': { color: 'warning', text: t('devices.statusPaused') },
'FINISH': { color: 'success', text: t('devices.statusFinished') }, 'FINISH': { color: 'success', text: t('devices.statusFinished') },
'FAILED': { color: 'error', text: t('devices.statusFailed') } 'FAILED': { color: 'error', text: t('devices.statusFailed') },
"CANCELING": { color: 'warning', text: t('devices.statusCanceling') },
}; };
const item = statusMap[status] || { color: 'default', text: record.taskStausTranslate || t('constants.locationUnknown') }; const item = statusMap[status] || { color: 'default', text: record.taskStausTranslate || t('constants.locationUnknown') };
return <Tag color={item.color}>{item.text}</Tag>; return <Tag color={item.color}>{record.taskStausTranslate}</Tag>;
} }
}, },
{ {
@@ -889,7 +882,8 @@ export default function RobotTaskPage() {
'EXECUTING': { color: 'processing', text: t('workOrder.inProgress') }, 'EXECUTING': { color: 'processing', text: t('workOrder.inProgress') },
'PAUSE': { color: 'warning', text: t('devices.statusPaused') }, 'PAUSE': { color: 'warning', text: t('devices.statusPaused') },
'FINISH': { color: 'success', text: t('devices.statusFinished') }, 'FINISH': { color: 'success', text: t('devices.statusFinished') },
'FAILED': { color: 'error', text: t('devices.statusFailed') } 'FAILED': { color: 'error', text: t('devices.statusFailed') },
"CANCELING": { color: 'warning', text: t('devices.statusCanceling') },
}; };
const item = statusMap[status] || { color: 'default', text: t('constants.locationUnknown') }; const item = statusMap[status] || { color: 'default', text: t('constants.locationUnknown') };
return <Tag color={item.color}>{item.text}</Tag>; return <Tag color={item.color}>{item.text}</Tag>;
@@ -909,27 +903,46 @@ export default function RobotTaskPage() {
<> <>
{/*{record.taskStaus === 'NEW' && (*/} {/*{record.taskStaus === 'NEW' && (*/}
<Popconfirm <Popconfirm
title={t('devices.confirmCancelTask')} title={t('devices.confirmCancelTask')}
onConfirm={() => handleCancelTask(record)} description={
okText={t('common.ok')} cancelText={t('common.cancel')} <Radio.Group
> value={cancelMode}
<Button type="text" size="small" danger icon={<CloseOutlined />} onClick={(e) => e.stopPropagation()}> onChange={(e) => setCancelMode(e.target.value)}
{t('common.cancel')} style={{ marginTop: 8 }}
</Button> >
</Popconfirm> <Space direction="vertical">
<Radio value="normal">{t('devices.normalCancel')}</Radio>
<Radio value="force">{t('devices.forceCancel')}</Radio>
</Space>
</Radio.Group>
}
onConfirm={() => handleCancelTask(record, cancelMode)}
okText={t('common.ok')}
cancelText={t('common.cancel')}
>
<Button
type="text"
size="small"
danger
icon={<CloseOutlined />}
onClick={(e) => e.stopPropagation()}
>
{t('common.cancel')}
</Button>
</Popconfirm>
{/*//)}*/} {/*//)}*/}
{/*{record.taskStaus === 'EXECUTING' && (*/} {/*{record.taskStaus === 'EXECUTING' && (*/}
<Popconfirm <Popconfirm
title={t('devices.confirmPauseTask')} title={t('devices.confirmPauseTask')}
onConfirm={() => handlePauseTask(record)} onConfirm={() => handlePauseTask(record)}
okText={t('common.ok')} cancelText={t('common.cancel')} okText={t('common.ok')} cancelText={t('common.cancel')}
> >
<Button type="text" size="small" style={{ color: '#FF9500' }} onClick={(e) => e.stopPropagation()}> <Button type="text" size="small" style={{ color: '#FF9500' }} onClick={(e) => e.stopPropagation()}>
{t('video.pause')} {t('video.pause')}
</Button> </Button>
</Popconfirm> </Popconfirm>
{/*)}/*/} {/*)}/*/}
{record.taskStaus === 'PAUSE' && ( {record.taskStaus === 'PAUSE' && (

View File

@@ -27,11 +27,14 @@ export default class DeviceController {
this.wsStatus = 'disconnected'; this.wsStatus = 'disconnected';
this.wsDeviceInfo = {}; this.wsDeviceInfo = {};
this.locationInfo = {};
this.controlTimeout = null; this.controlTimeout = null;
this.keepAliveInterval = null; // 后台保活定时器 this.keepAliveInterval = null; // 后台保活定时器
this.onDeviceInfoUpdate = null; this.onDeviceInfoUpdate = null;
this.onLocationInfoUpdate = null;
this.onControlStatusChange = null; this.onControlStatusChange = null;
this.onWsStatusChange = null; this.onWsStatusChange = null;
this.onHasControlRightChange = null; this.onHasControlRightChange = null;
@@ -156,6 +159,7 @@ export default class DeviceController {
this.connectedDeviceSn = null; this.connectedDeviceSn = null;
this.wsDeviceInfo = {}; this.wsDeviceInfo = {};
this.locationInfo = {};
this.isControlled = false; this.isControlled = false;
this.onControlStatusChange?.(false); this.onControlStatusChange?.(false);
@@ -263,6 +267,15 @@ export default class DeviceController {
this.onDeviceInfoUpdate?.(data); this.onDeviceInfoUpdate?.(data);
break; break;
} }
case 'locationInfo': {
const data = {};
msg.data.forEach((item) => {
data[item.name] = item.value;
});
this.locationInfo = data;
this.onLocationInfoUpdate?.(data);
break;
}
case 'AUTH': { case 'AUTH': {
if (msg.isAuth) { if (msg.isAuth) {

View File

@@ -989,6 +989,10 @@ const en = {
working: 'Working', working: 'Working',
workingCurrent: 'Working Current', workingCurrent: 'Working Current',
zoomLens: 'Zoom Lens', zoomLens: 'Zoom Lens',
controllerNotConnected: "controllerNotConnected",
otherWebConnected: "otherWebConnected",
clickToRequestControl: "clickToRequestControl",
control2: "connecting",
fixed2TaskSuspended2: 'Fixed2 Task Suspended2 态势', fixed2TaskSuspended2: 'Fixed2 Task Suspended2 态势',

View File

@@ -558,6 +558,13 @@ const zh = {
fillRequiredFields: '填写必填字段', fillRequiredFields: '填写必填字段',
firmwareVersion: '固件版本', firmwareVersion: '固件版本',
fixed: '固定', fixed: '固定',
controllerNotConnected: "控制器未连接",
otherWebConnected: "其他网页已连接",
clickToRequestControl: "点击请求控制",
control2: "已连接",
controlling: "控制中",
fixed2: '', fixed2: '',
fixedEnv: '固定环境', fixedEnv: '固定环境',
flightAltitude: '飞行高度', flightAltitude: '飞行高度',