修复地图 跳转的顺序问题
This commit is contained in:
19
.workbuddy/memory/2026-09-04.md
Normal file
19
.workbuddy/memory/2026-09-04.md
Normal 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 书签便于跨文档引用
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -1245,6 +1245,7 @@ export default function RobotTaskPage() {
|
||||
ifClearNavLine={clearNavLine}
|
||||
ifClearPlanLine={clearPlanLine}
|
||||
routeMode={routeMode}
|
||||
mapLayer={currentStation?.siteMapName}
|
||||
/>
|
||||
|
||||
{/* 机器人状态悬浮面板 - 绝对定位左上角 */}
|
||||
|
||||
@@ -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 }}>
|
||||
|
||||
Reference in New Issue
Block a user