import {Settings} from "./Setting.tsx"; // 保留导入,不修改 import {Leaflet_Map} from "./Map/Leaflet_Map.tsx" import {Aircraft_List} from "./Map/Aircraft_List.tsx"; import enhance from './core/enhance.tsx'; import {useEffect, useState} from 'react'; // @ts-ignore import {AppstoreOutlined, MailOutlined, SettingOutlined} from '@ant-design/icons'; import {Flex, Menu, MenuProps, Switch, message} from 'antd'; import {Routes, Route, Link, useNavigate, NavigateFunction, useLocation} from 'react-router-dom'; import React from 'react'; import ReactDOM, {Root} from 'react-dom/client'; import {BrowserRouter} from 'react-router-dom'; import FileList from "./FileList.tsx"; import {DSP} from "./DSP/DSP.tsx"; import {Navigate, Router} from "react-router"; import axios from "axios"; import {baseURL} from "./Global.tsx"; import {is_cesium_webgl_available, webgl_unavailable_message} from "./Map/WebGL_Support.ts"; import {Data_Source_Config} from "./Data_Source/Data_Source_Config.tsx"; import L from 'leaflet'; const Cesium_Map_View = React.lazy(() => import("./Map/Cesium_Map.tsx")); delete (L.Icon.Default.prototype as any)._getIconUrl; L.Icon.Default.mergeOptions({ iconUrl: '/ui/images/marker-icon.png', iconRetinaUrl: '/ui/images/marker-icon-2x.png', shadowUrl: '/ui/images/marker-shadow.png', }); class App extends enhance.Base { // ************************ 第一步:仅声明属性,不即时实例化 ************************ leaflet_map: Leaflet_Map | null = null; // 先赋值为null,延迟实例化 cesium_map: any = null; setting: Settings | null = null; aircraft_list: Aircraft_List | null = null; dsp: DSP | null = null; data_source_config: Data_Source_Config | null = null; // @ts-ignore navigate: NavigateFunction location: ReturnType | null = null; selected_key: string = '/map' version: string = '未加载版本信息'; start_device_time: number; webgl_supported: boolean = is_cesium_webgl_available(); menuItems: any = [] constructor() { super(); // ************************ 第二步:在构造函数中延迟实例化(确保依赖已初始化) ************************ this.initSubComponents(); // page 是我自定义的 this.menuItems = [ { label: '2D地图', icon: , key: '/map', }, { label: this.webgl_supported ? '3D地图' : '3D地图(WebGL不可用)', icon: , key: '/map3d', disabled: !this.webgl_supported, }, { label: '设置', icon: , key: '/settings', }, { label: '飞机列表', icon: , key: '/aircraftlist', }, // { // label: 'DSP', // icon: , // key: '/dsp', // }, ]; axios.post(`${baseURL}/version`, {}).then(res => { this.version = res.data.version this.flush(); }) axios.post(`${baseURL}/start_device_time`, {}).then(res => { this.start_device_time = res.data.start_device_time this.flush(); }) } // ************************ 新增:子组件初始化方法(统一管理,便于维护) ************************ initSubComponents = () => { // ************************ 第二步:在构造函数中延迟实例化(确保依赖已初始化) ************************ // 此时所有导入的类已完成初始化,可安全实例化 this.leaflet_map = new Leaflet_Map(); this.aircraft_list = new Aircraft_List(); this.dsp = new DSP(); this.data_source_config = new Data_Source_Config(this.on_data_sources_changed); // 延迟初始化Settings,避免“初始化前访问”错误 setTimeout(() => { this.setting = new Settings(); this.flush(); }, 0); }; on_data_sources_changed = () => { if (!this.data_source_config) return; if (this.leaflet_map) { this.leaflet_map.data_source_config = this.data_source_config; this.leaflet_map.data_source_show.data_source_config = this.data_source_config; this.leaflet_map.data_source_show.flush(); this.leaflet_map.flush(); } this.aircraft_list?.data_sources_changed(); this.cesium_map?.request_sync_data_sources?.(); this.flush(); }; use_hook() { this.navigate = useNavigate(); this.location = useLocation(); useEffect(() => { const path = this.location?.pathname || '/map'; this.selected_key = path.startsWith('/ui/') ? path.substring(3) : path; this.flush() }, [this.location]); useEffect(() => { const on_unavailable = () => { this.webgl_supported = false; const item = this.menuItems.find((menu_item: any) => menu_item.key === "/map3d"); if (item) { item.label = "3D地图(WebGL不可用)"; item.disabled = true; } this.flush(); }; window.addEventListener("ecap_cesium_webgl_unavailable", on_unavailable); return () => window.removeEventListener("ecap_cesium_webgl_unavailable", on_unavailable); }, []); }; get_Data_Source(key: string) { return this.data_source_config?.map(key) ?? null; } onClick: MenuProps['onClick'] = (e) => { if (e.key === "/map3d" && !this.webgl_supported) { message.warning(webgl_unavailable_message); this.navigate("/map"); return; } this.selected_key = e.key; this.navigate(this.selected_key); // 跳转到 /about 页面 this.flush(); }; formatTimestamp(ts: number | string): string { const n = Number(ts); if (!Number.isFinite(n) || n <= 0) { return ""; } // 10 位一般是秒级时间戳,13 位一般是毫秒级时间戳 const ms = n < 1e12 ? n * 1000 : n; const d = new Date(ms); const pad = (v: number) => String(v).padStart(2, "0"); return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ` + `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`; } render(props: any) { // ************************ 优化:渲染前校验子组件是否初始化完成,避免报错 ************************ if (!this.leaflet_map || !this.setting || !this.aircraft_list || !this.dsp || !this.data_source_config) { return
组件初始化中...
; } return (
({ key: item.key, icon: item.icon, label: item.label, disabled: item.disabled }))} />
{`服务开启时间:${this.formatTimestamp(this.start_device_time)} 版本:${this.version}`}
)} /> )} /> )} /> )} /> 3D地图加载中...}> : )} /> 3D地图加载中...}> : )} /> )} /> {/**/} {/*
*/} {/* */} {/*
*/} {/* */} {/* )}*/} {/*/>*/} }/> ) } } // ************************ 确认:App实例化在所有导入类完成后 ************************ export let app = new App(); const container = document.getElementById('root'); if (container) { // 清空容器现有内容(避免热更新重复绑定) container.innerHTML = ''; const root = ReactDOM.createRoot(container); root.render( ); }