和算法测试成功第一步 状态界面看到经纬度信息和保存可以成功
This commit is contained in:
10
env.js
10
env.js
@@ -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"
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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))) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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' && (
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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 态势',
|
||||||
|
|
||||||
|
|||||||
@@ -558,6 +558,13 @@ const zh = {
|
|||||||
fillRequiredFields: '填写必填字段',
|
fillRequiredFields: '填写必填字段',
|
||||||
firmwareVersion: '固件版本',
|
firmwareVersion: '固件版本',
|
||||||
fixed: '固定',
|
fixed: '固定',
|
||||||
|
controllerNotConnected: "控制器未连接",
|
||||||
|
otherWebConnected: "其他网页已连接",
|
||||||
|
clickToRequestControl: "点击请求控制",
|
||||||
|
control2: "已连接",
|
||||||
|
|
||||||
|
controlling: "控制中",
|
||||||
|
|
||||||
fixed2: '',
|
fixed2: '',
|
||||||
fixedEnv: '固定环境',
|
fixedEnv: '固定环境',
|
||||||
flightAltitude: '飞行高度',
|
flightAltitude: '飞行高度',
|
||||||
|
|||||||
Reference in New Issue
Block a user