[fix/feat]:[FL-60][线路管理中走向图渲染不出来]

Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
chengkai3
2026-06-09 10:29:21 +08:00
parent 0b2d7828ad
commit 34fc2d15b7
5 changed files with 41 additions and 6 deletions
+1
View File
@@ -758,6 +758,7 @@
- 支持按风险着色、塔号显隐、居中重置。
- 走向图统计信息固定包含:有效坐标、缺失坐标、断点段数、线路估算长度(Haversine)。
- 对序号断档采用分段折线渲染,避免缺失坐标导致的跨段误连线。
- 当前部署默认启用 `NEXT_PUBLIC_APP_BASE_PATH=/fl`Cesium 组件初始化时,`window.CESIUM_BASE_URL` 必须通过 `withBasePath("/cesium")` 生成,禁止硬编码根路径 `"/cesium"`,否则子路径部署下会因静态资源 404 导致 Viewer 初始化失败、页面空白。
## 雷电流数据管理口径(2026-04-25)
+29
View File
@@ -30,3 +30,32 @@
- 风险与关注点:
- 本次修复只绕开 BuildKit builder 镜像对 Docker Hub 的依赖;后续若 `Dockerfile` 里的基础镜像或 `docker build --pull` 仍指向不稳定上游,构建阶段仍可能出现其他网络相关失败。
## Work Log - 修复线路管理走向图在 `/fl` 子路径下无法渲染(2026-06-09
- 背景:
- Issue `FL-60` 反馈“线路管理中走向图渲染不出来”。
- 仓库部署默认启用 `NEXT_PUBLIC_APP_BASE_PATH=/fl`,但多个 Cesium 组件初始化时仍把 `window.CESIUM_BASE_URL` 硬编码为 `"/cesium"`
- 这会导致页面在 `/fl/admin/power-lines` 等子路径下请求错误的静态资源地址,最终触发 Cesium Viewer 初始化失败。
- 本次处理:
- `web/src/components/power-line-cesium-map.tsx`
- 将走向图 Cesium 静态资源根路径改为 `withBasePath("/cesium")`,修复线路管理走向图在 `/fl` 部署下的资源寻址。
- `web/src/components/elevation-preview-cesium-map.tsx`
- 同步改为 `withBasePath("/cesium")`,避免高程预览图在相同部署口径下继续空白。
- `web/src/components/lightning-distribution-map.tsx`
- 同步改为 `withBasePath("/cesium")`,保持雷电分布图与项目子路径部署口径一致。
- 顺手补齐 `Viewer` / `CesiumNamespace` / `Cartesian3[]` 显式类型,消除本地 lint 暴露的 `no-explicit-any` 问题。
- 验证:
- 基线:
- 代码检查确认 `power-line-cesium-map.tsx``elevation-preview-cesium-map.tsx``lightning-distribution-map.tsx` 都存在 `window.CESIUM_BASE_URL = "/cesium"` 硬编码。
- 部署配置检查确认 `deploy/pro-deploy/.env` 与 compose / Dockerfile 默认均为 `NEXT_PUBLIC_APP_BASE_PATH=/fl`
- 初次本地 lint 尝试因未安装前端依赖失败;补充执行 `NPM_CONFIG_CACHE=/tmp/npm-cache npm ci` 后继续验证。
- 修改后:
- `NPM_CONFIG_CACHE=/tmp/npm-cache npm --workspace web exec eslint src/components/power-line-cesium-map.tsx src/components/elevation-preview-cesium-map.tsx src/components/lightning-distribution-map.tsx src/app/admin/power-lines/page.tsx --max-warnings=0` -> 通过。
- `NEXT_PUBLIC_APP_BASE_PATH=/fl NPM_CONFIG_CACHE=/tmp/npm-cache npm run build:web` -> 通过。
- 风险与关注点:
- 本次修复聚焦前端静态资源路径,不涉及后端接口、数据库或权限逻辑。
- 若后续新增 Cesium 页面,必须继续复用 `withBasePath("/cesium")`,不能再硬编码根路径。
@@ -3,6 +3,7 @@
import { Alert, Empty, Spin } from "antd";
import { useEffect, useMemo, useRef, useState } from "react";
import { withBasePath } from "@/lib/base-path";
import { reloadOnceOnChunkError } from "@/lib/chunk-error";
import type { ElevationDatasetPreviewCell, ElevationDatasetPreviewPoint } from "@/types/auth";
@@ -108,7 +109,7 @@ export function ElevationPreviewCesiumMap({
async function initViewer() {
if (!containerRef.current || viewerRef.current) return;
try {
window.CESIUM_BASE_URL = "/cesium";
window.CESIUM_BASE_URL = withBasePath("/cesium");
const Cesium = await import("cesium");
if (cancelled || !containerRef.current) return;
@@ -2,6 +2,7 @@
import { useEffect, useMemo, useRef, useState } from "react";
import { withBasePath } from "@/lib/base-path";
import type {
LightningDistributionGridCell,
LightningDistributionScatterPoint,
@@ -13,6 +14,8 @@ type LightningDistributionMapProps = {
loading?: boolean;
};
type CesiumNamespace = typeof import("cesium");
function hasValidCoord(lon: number, lat: number): boolean {
if (Number.isNaN(lon) || Number.isNaN(lat)) return false;
return lon >= -180 && lon <= 180 && lat >= -90 && lat <= 90;
@@ -41,8 +44,8 @@ export function LightningDistributionMap({
loading = false,
}: LightningDistributionMapProps) {
const containerRef = useRef<HTMLDivElement | null>(null);
const viewerRef = useRef<any>(null);
const cesiumRef = useRef<any>(null);
const viewerRef = useRef<import("cesium").Viewer | null>(null);
const cesiumRef = useRef<CesiumNamespace | null>(null);
const [error, setError] = useState("");
const [ready, setReady] = useState(false);
@@ -72,7 +75,7 @@ export function LightningDistributionMap({
const Cesium = await import("cesium");
if (disposed || !containerRef.current) return;
(window as typeof window & { CESIUM_BASE_URL?: string }).CESIUM_BASE_URL = "/cesium";
(window as typeof window & { CESIUM_BASE_URL?: string }).CESIUM_BASE_URL = withBasePath("/cesium");
Cesium.Ion.defaultAccessToken = "";
const viewer = new Cesium.Viewer(containerRef.current, {
@@ -137,7 +140,7 @@ export function LightningDistributionMap({
});
});
const positions: any[] = [];
const positions: import("cesium").Cartesian3[] = [];
safePoints.forEach((point) => {
const absCurrent = point.abs_current_ka ?? (point.current_ka ? Math.abs(point.current_ka) : null);
const color = Cesium.Color.fromCssColorString(pointColorByAbsCurrent(absCurrent));
+2 -1
View File
@@ -4,6 +4,7 @@ import { AimOutlined, MinusOutlined, PlusOutlined } from "@ant-design/icons";
import { Alert, Button, Checkbox, Empty, Spin, Typography } from "antd";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { withBasePath } from "@/lib/base-path";
import { reloadOnceOnChunkError } from "@/lib/chunk-error";
import type { LineTowerSummary } from "@/types/auth";
@@ -238,7 +239,7 @@ export function PowerLineCesiumMap({
}
try {
window.CESIUM_BASE_URL = "/cesium";
window.CESIUM_BASE_URL = withBasePath("/cesium");
const Cesium = await import("cesium");
if (cancelled || !containerRef.current) {
return;