From 34fc2d15b7adc70cb46ca29b84458a4f33989583 Mon Sep 17 00:00:00 2001 From: chengkai3 Date: Tue, 9 Jun 2026 10:29:21 +0800 Subject: [PATCH] =?UTF-8?q?[fix/feat]:[FL-60][=E7=BA=BF=E8=B7=AF=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E4=B8=AD=E8=B5=B0=E5=90=91=E5=9B=BE=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E4=B8=8D=E5=87=BA=E6=9D=A5]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: multica-agent --- MEMORY.md | 1 + memory/2026-06-09.md | 29 +++++++++++++++++++ .../elevation-preview-cesium-map.tsx | 3 +- .../components/lightning-distribution-map.tsx | 11 ++++--- web/src/components/power-line-cesium-map.tsx | 3 +- 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/MEMORY.md b/MEMORY.md index f659ad0..fae271d 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -758,6 +758,7 @@ - 支持按风险着色、塔号显隐、居中重置。 - 走向图统计信息固定包含:有效坐标、缺失坐标、断点段数、线路估算长度(Haversine)。 - 对序号断档采用分段折线渲染,避免缺失坐标导致的跨段误连线。 +- 当前部署默认启用 `NEXT_PUBLIC_APP_BASE_PATH=/fl`;Cesium 组件初始化时,`window.CESIUM_BASE_URL` 必须通过 `withBasePath("/cesium")` 生成,禁止硬编码根路径 `"/cesium"`,否则子路径部署下会因静态资源 404 导致 Viewer 初始化失败、页面空白。 ## 雷电流数据管理口径(2026-04-25) diff --git a/memory/2026-06-09.md b/memory/2026-06-09.md index 2dfc7cc..b483cc5 100644 --- a/memory/2026-06-09.md +++ b/memory/2026-06-09.md @@ -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")`,不能再硬编码根路径。 diff --git a/web/src/components/elevation-preview-cesium-map.tsx b/web/src/components/elevation-preview-cesium-map.tsx index 5fe295f..7a07ac8 100644 --- a/web/src/components/elevation-preview-cesium-map.tsx +++ b/web/src/components/elevation-preview-cesium-map.tsx @@ -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; diff --git a/web/src/components/lightning-distribution-map.tsx b/web/src/components/lightning-distribution-map.tsx index 592e154..8e983f6 100644 --- a/web/src/components/lightning-distribution-map.tsx +++ b/web/src/components/lightning-distribution-map.tsx @@ -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(null); - const viewerRef = useRef(null); - const cesiumRef = useRef(null); + const viewerRef = useRef(null); + const cesiumRef = useRef(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)); diff --git a/web/src/components/power-line-cesium-map.tsx b/web/src/components/power-line-cesium-map.tsx index 81072f1..7b021fa 100644 --- a/web/src/components/power-line-cesium-map.tsx +++ b/web/src/components/power-line-cesium-map.tsx @@ -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;