修复地图 跳转的顺序问题

This commit is contained in:
mmc
2026-09-04 16:22:28 +08:00
parent ab193a3be9
commit f0e1c14644
5 changed files with 59 additions and 15 deletions

View File

@@ -0,0 +1,19 @@
# 2026-09-04
### 任务1:补全 SOP v2.0 文档
- 源文件:D:\工作\绩效文档\202609\机器人智慧服务系统_SOP_v2.0_目录可点击.docx
- 输出:同上 _已完善.docx
- 工作内容:
- 为 19 章 + 5 附录共 24 个标题插入 Word 书签
- 将目录条目改造为内部超链接(HYPERLINK \\l 锚点)
- 用 matplotlib 生成 27 张界面示意图,替换所有【截图 X-Y】占位符
- 在登录、监控、设备控制、任务控制、AI 编排等关键位置补充 💡 使用提示
- 工具:python-docx + matplotlib + Pillow,隔离 venv:C:\Users\15563\.workbuddy\binaries\python\envs\sopenv
### 任务2:编写版本发布说明(V2.4.1 / V2.4.0 / V2.3.x)
- 输出:D:\工作\绩效文档\202609\机器人智慧服务系统_版本发布说明_V2.4.1.docx(42.9 KB)
- 工作内容:
- 基于 git log 三个分支(master / feat-suanfaceshi-0817 / feat-yanshi0821 / feat-lazyLoad-0602)梳理实际迭代历史
- 覆盖三个发布版本,含 1.1-1.6 / 2.1-2.6 / 3.1-3.5 完整结构
- 含 1 张能力对比表(4 列 14 行)
- 22 个 Word 书签便于跨文档引用

View File

@@ -55,6 +55,21 @@ const CesiumMap = React.forwardRef(({ ifClear, ifClearPlanLine, ifClearNavLine,
const isCameraFlyingRef = useRef(false);
const lastFlightPromiseRef = useRef(null);
// ==============================
// 飞行优先级调度:优先级高的可打断低的;同级不重复起飞
// realtime(100) > focus(90) > devices(80) > track(70) > layer(10)
// ==============================
const lastFlightPriorityRef = useRef(-1);
const FLIGHT_PRIORITY = { realtime: 100, focus: 90, devices: 80, track: 70, layer: 10 };
const flyToView = (viewer, priority, config) => {
if (!viewer) return;
if (priority <= lastFlightPriorityRef.current) return; // 同级或更低不重复/覆盖;更高优先级才打断
lastFlightPriorityRef.current = priority;
try { viewer.camera.cancelFlight(); } catch (e) { /* 忽略取消异常 */ }
viewer.camera.flyTo(config);
};
const resetFlightPriority = () => { lastFlightPriorityRef.current = -1; };
const [drawPoints, setDrawPoints] = useState([]);
const drawLineRef = useRef(null);
const pointEntitiesRef = useRef([]);
@@ -262,7 +277,7 @@ const CesiumMap = React.forwardRef(({ ifClear, ifClearPlanLine, ifClearNavLine,
const p = validPoints[0];
viewer.scene.requestRender();
viewer.camera.flyTo({
flyToView(viewer, FLIGHT_PRIORITY.track, {
destination: Cesium.Cartesian3.fromDegrees(
p.lng,
p.lat,
@@ -284,7 +299,7 @@ const CesiumMap = React.forwardRef(({ ifClear, ifClearPlanLine, ifClearNavLine,
viewer.scene.requestRender();
viewer.camera.flyTo({
flyToView(viewer, FLIGHT_PRIORITY.track, {
destination: rectangle,
duration: 1.2
});
@@ -400,7 +415,7 @@ const CesiumMap = React.forwardRef(({ ifClear, ifClearPlanLine, ifClearNavLine,
const p = validPoints[0];
viewer.scene.requestRender();
viewer.camera.flyTo({
flyToView(viewer, FLIGHT_PRIORITY.track, {
destination: Cesium.Cartesian3.fromDegrees(
p.lng,
p.lat,
@@ -422,7 +437,7 @@ const CesiumMap = React.forwardRef(({ ifClear, ifClearPlanLine, ifClearNavLine,
viewer.scene.requestRender();
viewer.camera.flyTo({
flyToView(viewer, FLIGHT_PRIORITY.track, {
destination: rectangle,
duration: 1.2
});
@@ -435,6 +450,7 @@ const CesiumMap = React.forwardRef(({ ifClear, ifClearPlanLine, ifClearNavLine,
};
useEffect(() => {
resetFlightPriority();
if (polyPoints && polyPoints.length > 0) {
drawPolygon(polyPoints)
} else {
@@ -452,6 +468,7 @@ const CesiumMap = React.forwardRef(({ ifClear, ifClearPlanLine, ifClearNavLine,
useEffect(() => {
resetFlightPriority();
if (viewerRef.current) {
drawTrackLine(points);
}
@@ -527,7 +544,7 @@ const CesiumMap = React.forwardRef(({ ifClear, ifClearPlanLine, ifClearNavLine,
`;
}
const getCursorLngLat = (viewer, screenPos) => {
const getCursorLngLat = (viewer, screenPos) => {
const cartesian = viewer.camera.pickEllipsoid(screenPos, viewer.scene.globe.ellipsoid);
if (!window.Cesium.defined(cartesian)) return { lon: NaN, lat: NaN };
const cartographic = window.Cesium.Cartographic.fromCartesian(cartesian);
@@ -846,7 +863,7 @@ const getCursorLngLat = (viewer, screenPos) => {
const centerLon = (minx + maxx) / 2;
const centerLat = (miny + maxy) / 2;
viewerRef.current.camera.flyTo({
flyToView(viewerRef.current, FLIGHT_PRIORITY.layer, {
// 固定高度,第三个参数就是高度(单位米)
destination: window.Cesium.Cartesian3.fromDegrees(centerLon, centerLat, flyHeight),
orientation: {
@@ -994,9 +1011,12 @@ const getCursorLngLat = (viewer, screenPos) => {
};
}, []);
// 根据场站映射图层定位地图
// 根据场站映射图层定位地图:切换场站时始终飞向该场站的图层
// 不再用可能滞后的 devices 判断(避免用上一场站的机器决策);
// 若场站有机器,由 devices 效果按更高优先级接管飞向机器
useEffect(() => {
if (!mapLayer || !viewerRef.current) return;
resetFlightPriority();
flyToLayer(mapLayer, envConfig.geoserver_url, 100);
}, [mapLayer]);
@@ -1054,7 +1074,7 @@ const getCursorLngLat = (viewer, screenPos) => {
}
});
viewer.camera.flyTo({
flyToView(viewer, FLIGHT_PRIORITY.focus, {
destination: Cesium.Cartesian3.fromDegrees(Number(focusLocation.lon), Number(focusLocation.lat), focusLocation.height || 800),
orientation: {
heading: Cesium.Math.toRadians(0.0),
@@ -1081,7 +1101,7 @@ const getCursorLngLat = (viewer, screenPos) => {
});
const rectangle = window.Cesium.Rectangle.fromDegrees(west, south, east, north);
viewer.camera.flyTo({ destination: rectangle, duration: 1.5 });
flyToView(viewer, FLIGHT_PRIORITY.devices, { destination: rectangle, duration: 1.5 });
}
function parseLngLat(lon, lat) {
@@ -1530,7 +1550,7 @@ const getCursorLngLat = (viewer, screenPos) => {
const p = validPositions[0];
viewer.camera.flyTo({
flyToView(viewer, FLIGHT_PRIORITY.devices, {
destination: Cesium.Cartesian3.fromDegrees(
p.lon,
p.lat,
@@ -1548,7 +1568,7 @@ const getCursorLngLat = (viewer, screenPos) => {
maxLat
);
viewer.camera.flyTo({
flyToView(viewer, FLIGHT_PRIORITY.devices, {
destination: rectangle,
duration: 1.2
});
@@ -1731,6 +1751,7 @@ const getCursorLngLat = (viewer, screenPos) => {
realtimeLastPointRef.current = null;
realtimeHiddenRef.current = false;
hasFlownRef.current = false;
resetFlightPriority();
// 恢复所有设备显示
entityMapRef.current.forEach(e => {
@@ -1891,7 +1912,7 @@ const getCursorLngLat = (viewer, screenPos) => {
hasFlownRef.current = true;
if (getCameraMode() !== "realtime") return;
viewer.camera.flyTo({
flyToView(viewer, FLIGHT_PRIORITY.realtime, {
destination: Cesium.Cartesian3.fromDegrees(lon, lat, 30),
orientation: {
heading: 0,
@@ -2031,7 +2052,7 @@ const getCursorLngLat = (viewer, screenPos) => {
hasFlownRef.current = true;
if (getCameraMode() !== "realtime") return;
viewer.camera.flyTo({
flyToView(viewer, FLIGHT_PRIORITY.realtime, {
destination: Cesium.Cartesian3.fromDegrees(
lon,

View File

@@ -642,7 +642,7 @@ export default function DeviceOverviewPage() {
<div><span style={{ color: '#ff4d4f' }}>■</span>{t('devices.s9')}</div>
</div>
</div>
<CesiumMap devices={devicesAll} />
<CesiumMap devices={devicesAll} mapLayer={currentStation?.siteMapName} />
</div>
</Card>

View File

@@ -1245,6 +1245,7 @@ export default function RobotTaskPage() {
ifClearNavLine={clearNavLine}
ifClearPlanLine={clearPlanLine}
routeMode={routeMode}
mapLayer={currentStation?.siteMapName}
/>
{/* 机器人状态悬浮面板 - 绝对定位左上角 */}

View File

@@ -39,6 +39,8 @@ export default function WayLinePage({ onRefresh }) {
const { t } = useTranslation();
const { userInfo } = useSelector((state: RootState) => state.user);
const { stationId } = useSelector((state: RootState) => state.station);
const { currentStation } = useSelector((state: RootState) => state.station);
const fontSmall = 'clamp(10px, 0.7vw, 11px)';
const fontNormal = 'clamp(12px, 0.75vw, 13px)';
@@ -896,7 +898,8 @@ export default function WayLinePage({ onRefresh }) {
style={{ ...cardStyle, marginBottom: 10 }}
>
<div style={{ width: '100%', height: 420, background: '#e8f3ff url(https://picsum.photos/seed/solar_map_v2/1600/1000) center/cover', position: 'relative' }}>
<CesiumMap realtimePosition={realtimePosition} drawRealTime={true}
<CesiumMap realtimePosition={realtimePosition} drawRealTime={true} mapLayer={currentStation?.siteMapName}
points={points} focusLocation={focusLocation} from="device-control" realtimeType='plane' ifClearNavLine={clearNavLine} ifClearPlanLine={clearPlanLine} />
<div style={{ position: 'absolute', top: 16, left: 16, background: 'rgba(255,255,255,0.92)', backdropFilter: 'blur(8px)', padding: '14px 16px', borderRadius: 10, width: 150, boxShadow: '0 4px 12px rgba(0,0,0,0.1)' }}>
<div style={{ fontSize: fontSmall, display: 'flex', flexDirection: 'column', gap: 10 }}>