Refactor flood disaster analysis workspace

This commit is contained in:
2026-05-14 16:30:14 +08:00
parent 729c5c2a7f
commit 9000feeee8
12 changed files with 1700 additions and 19 deletions
+5 -2
View File
@@ -1642,9 +1642,12 @@ function App() {
onToggleVisibility: setShowHazardPoints,
onScanComplete: fetchHazardPoints,
};
const waterPanel = {
const floodPanel = {
onShowSourceSceneOnMap: handleWaterSceneOnMap,
onShowReadyProductOnMap: handleWaterSceneOnMap,
onShowOnMap: handleWaterSceneOnMap,
onShowFloodOnMap: handleFloodEventOnMap,
onShowFloodRunOnMap: handleFloodEventOnMap,
onToggleFloodLayer: toggleFloodEventLayer,
};
const dinsarPanel = {
@@ -1736,7 +1739,7 @@ function App() {
pairingPanel={pairingPanel}
taskPanel={taskPanel}
hazardPanel={hazardPanel}
waterPanel={waterPanel}
floodPanel={floodPanel}
dinsarPanel={dinsarPanel}
aiPanel={aiPanel}
pairsPanel={pairsPanel}
File diff suppressed because it is too large Load Diff
+91
View File
@@ -0,0 +1,91 @@
import apiClient from './client';
export const getFloodSources = (params = {}) =>
apiClient.get('/flood/sources', { params });
export const refreshFloodSources = () =>
apiClient.post('/flood/sources/refresh');
export const getFloodSourceReadiness = (id) =>
apiClient.get(`/flood/sources/${id}/readiness`);
export const submitFloodPreprocess = (payload) =>
apiClient.post('/flood/preprocess', payload);
export const getFloodScenes = (limit = 20, offset = 0) =>
apiClient.get('/flood/scenes', { params: { limit, offset } });
export const getFloodDoneRadarIds = () =>
apiClient.get('/flood/scenes/done-radar-ids').then(r => r.data.ids);
export const getFloodActiveRadarIds = () =>
apiClient.get('/flood/scenes/active-radar-ids').then(r => r.data.ids);
export const resetFloodScene = (sceneId) =>
apiClient.post(`/flood/scenes/${sceneId}/reset`);
export const submitFloodWaterExtraction = (payload) =>
apiClient.post('/flood/water-extractions', payload);
export const getFloodWaterExtractions = (limit = 20, offset = 0, status = null) =>
apiClient.get('/flood/water-extractions', { params: { limit, offset, ...(status ? { status } : {}) } });
export const getFloodWaterExtractionPreview = (id) =>
apiClient.get(`/flood/water-extractions/${id}/preview`).then(r => r.data);
export const getFloodPreprocessRuns = (params = {}) =>
apiClient.get('/flood/preprocess-runs', { params });
export const getFloodReadyProducts = (params = {}) =>
apiClient.get('/flood/ready-products', { params });
export const getFloodReadyProductPreview = (id) =>
apiClient.get(`/flood/ready-products/${id}/preview`).then(r => r.data);
export const searchFloodPairs = (payload) =>
apiClient.post('/flood/pairs/search', payload);
export const saveFloodPair = (payload) =>
apiClient.post('/flood/pairs', payload);
export const getFloodPairs = (params = {}) =>
apiClient.get('/flood/pairs', { params });
export const deleteFloodPair = (id) =>
apiClient.delete(`/flood/pairs/${id}`);
export const submitFloodDetection = (payload) =>
apiClient.post('/flood/detections', payload);
export const getFloodDetections = (params = {}) =>
apiClient.get('/flood/detections', { params });
export const getFloodDetection = (id) =>
apiClient.get(`/flood/detections/${id}`);
export const getFloodDetectionPreview = (id, layer) =>
apiClient.get(`/flood/detections/${id}/preview/${layer}`).then(r => r.data);
export const vectorizeFloodDetection = (id, payload = {}) =>
apiClient.post(`/flood/detections/${id}/vectorize`, payload);
export const runFloodOverlay = (id, payload = {}) =>
apiClient.post(`/flood/detections/${id}/overlay`, payload);
export const getFloodImpact = (id) =>
apiClient.get(`/flood/detections/${id}/impact`).then(r => r.data);
export const getFloodResults = (params = {}) =>
apiClient.get('/flood/results', { params });
export const getFloodResult = (id) =>
apiClient.get(`/flood/results/${id}`);
export const getFloodResultManifest = (id) =>
apiClient.get(`/flood/results/${id}/manifest`).then(r => r.data);
export const createFloodReport = (payload) =>
apiClient.post('/flood/reports', payload);
export const getFloodReport = (id) =>
apiClient.get(`/flood/reports/${id}`).then(r => r.data);
+6 -9
View File
@@ -19,7 +19,7 @@ const LazyDataCopierPanel = lazy(() => import('../../DataCopierPanel'));
const LazyIDLAutomationPanel = lazy(() => import('../../IDLAutomationPanel'));
const LazyHazardPointPanel = lazy(() => import('../../HazardPointPanel'));
const LazyHealthCheckPanel = lazy(() => import('../../HealthCheckPanel'));
const LazyWaterMonitorPanel = lazy(() => import('../../WaterMonitorPanel'));
const LazyFloodAnalysisWorkspace = lazy(() => import('../../FloodAnalysisWorkspace'));
const LazyUserAdminPanel = lazy(() => import('../../UserAdminPanel'));
const LazyAuditLogPanel = lazy(() => import('../../AuditLogPanel'));
const LazyAiQualityPanel = lazy(() => import('../../panels/AiQualityPanel'));
@@ -57,7 +57,7 @@ export default function AppSidePanel({
pairingPanel,
taskPanel,
hazardPanel,
waterPanel,
floodPanel,
dinsarPanel,
aiPanel,
pairsPanel,
@@ -327,16 +327,13 @@ export default function AppSidePanel({
</div>
)}
{leftPanelTab === 'water' && (
{leftPanelTab === 'flood_analysis' && (
<div className="panel-content" style={{ flex: '1 1 auto', padding: 0, overflow: 'auto' }}>
<Suspense fallback={<PanelLoadingBody message="正在加载水体监测面板..." />}>
<LazyWaterMonitorPanel
<Suspense fallback={<PanelLoadingBody message="正在加载洪涝灾害分析工作台..." />}>
<LazyFloodAnalysisWorkspace
readOnly={isReadOnlyUser}
onShowOnMap={waterPanel.onShowOnMap}
onShowFloodOnMap={waterPanel.onShowFloodOnMap}
onToggleFloodLayer={waterPanel.onToggleFloodLayer}
onTaskStart={taskPanel.onTaskStart}
language={language}
floodPanel={floodPanel}
/>
</Suspense>
</div>
+2 -3
View File
@@ -101,7 +101,7 @@ export const LEFT_GROUP_LABELS = {
production_management: '生产管理',
insar_analysis: 'InSAR形变分析',
ai_analysis: 'AI分析',
water: '水体监测',
flood_analysis: '洪涝灾害分析',
ops: '运行维护',
};
@@ -150,7 +150,7 @@ export const LEFT_GROUP_TABS = {
production_management: [PRODUCTION_WORKSPACE_TAB],
insar_analysis: LEFT_GROUP_SECTIONS.insar_analysis.flatMap(section => section.tabs),
ai_analysis: LEFT_GROUP_SECTIONS.ai_analysis.flatMap(section => section.tabs),
water: ['water'],
flood_analysis: ['flood_analysis'],
ops: ['health', 'users', 'audit'],
};
@@ -188,7 +188,6 @@ export const ADMIN_ONLY_TABS = new Set([
'copier',
PRODUCTION_WORKSPACE_TAB,
...PRODUCTION_WORKSPACE_LEGACY_TABS,
'water',
'users',
'audit',
]);
+1 -1
View File
@@ -17,7 +17,7 @@
{ zh: '数据管理', en: 'Data' },
{ zh: '生产规划', en: 'Production' },
{ zh: 'D-InSAR 分析', en: 'D-InSAR Analysis' },
{ zh: '水体监测', en: 'Water Monitoring' },
{ zh: '水体监测(旧)', en: 'Water Monitoring (Legacy)' },
{ zh: '运行维护', en: 'Operations' },
{ zh: '入库监控', en: 'Ingest Monitor' },
+3 -1
View File
@@ -78,7 +78,9 @@ export const getLeftTabLabel = (tabKey, metrics = {}) => {
case 'uav_image_analysis':
return '无人机影像分析';
case 'water':
return '水体监测';
return '水体监测(旧)';
case 'flood_analysis':
return '洪涝灾害分析';
case 'health':
return '运维自检';
case 'users':