[예측] - OpenDrift Python API 서버 및 스크립트 추가 (prediction/opendrift/) - 시뮬레이션 상태 폴링 훅(useSimulationStatus), 로딩 오버레이 추가 - HydrParticleOverlay: deck.gl 기반 입자 궤적 시각화 레이어 - OilSpillView/LeftPanel/RightPanel: 시뮬레이션 실행·결과 표시 UI 개편 - predictionService/predictionRouter: 시뮬레이션 CRUD 및 상태 관리 API - simulation.ts: OpenDrift 연동 엔드포인트 확장 - docs/PREDICTION-GUIDE.md: 예측 기능 개발 가이드 추가 [CCTV/항공방제] - CCTV 오일 감지 GPU 추론 연동 (OilDetectionOverlay, useOilDetection) - CCTV 안전관리 감지 기능 추가 (선박 출입, 침입 감지) - oil_inference_server.py: Python GPU 추론 서버 [관리자] - 관리자 화면 고도화 (사용자/권한/게시판/선박신호 패널) - AdminSidebar, BoardMgmtPanel, VesselSignalPanel 신규 컴포넌트 [기타] - DB: 시뮬레이션 결과, 선박보험 시드(1391건), 역할 정리 마이그레이션 - 팀 워크플로우 v1.6.1 동기화 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
124 lines
3.6 KiB
TypeScript
124 lines
3.6 KiB
TypeScript
interface SimulationLoadingOverlayProps {
|
|
status: 'PENDING' | 'RUNNING';
|
|
progress?: number;
|
|
}
|
|
|
|
const SimulationLoadingOverlay = ({ status, progress }: SimulationLoadingOverlayProps) => {
|
|
const displayProgress = progress ?? 0;
|
|
const statusText = status === 'PENDING' ? '모델 초기화 중...' : '입자 추적 계산 중...';
|
|
|
|
return (
|
|
<div
|
|
style={{
|
|
position: 'absolute',
|
|
inset: 0,
|
|
zIndex: 50,
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
background: 'rgba(10, 14, 26, 0.75)',
|
|
backdropFilter: 'blur(4px)',
|
|
}}
|
|
>
|
|
<div
|
|
style={{
|
|
width: 320,
|
|
background: 'var(--bg1)',
|
|
border: '1px solid var(--bd)',
|
|
borderRadius: 'var(--rM)',
|
|
padding: '28px 24px',
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: 16,
|
|
}}
|
|
>
|
|
{/* 아이콘 + 제목 */}
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
|
|
<div
|
|
style={{
|
|
width: 36,
|
|
height: 36,
|
|
borderRadius: '50%',
|
|
background: 'rgba(6, 182, 212, 0.12)',
|
|
border: '1px solid rgba(6, 182, 212, 0.3)',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
flexShrink: 0,
|
|
}}
|
|
>
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none">
|
|
<path
|
|
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 14l-4-4 1.41-1.41L11 13.17l6.59-6.59L19 8l-8 8z"
|
|
fill="var(--cyan)"
|
|
opacity="0.8"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<div style={{ color: 'var(--t1)', fontSize: 14, fontWeight: 600 }}>
|
|
확산 예측 분석 중
|
|
</div>
|
|
<div style={{ color: 'var(--t3)', fontSize: 12, marginTop: 2 }}>
|
|
{statusText}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 진행률 바 */}
|
|
<div>
|
|
<div
|
|
style={{
|
|
height: 6,
|
|
background: 'rgba(255, 255, 255, 0.06)',
|
|
borderRadius: 999,
|
|
overflow: 'hidden',
|
|
}}
|
|
>
|
|
<div
|
|
style={{
|
|
height: '100%',
|
|
width: `${displayProgress}%`,
|
|
background: 'linear-gradient(90deg, var(--cyan), var(--blue))',
|
|
borderRadius: 999,
|
|
transition: 'width 0.6s ease',
|
|
}}
|
|
/>
|
|
</div>
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
justifyContent: 'space-between',
|
|
marginTop: 8,
|
|
}}
|
|
>
|
|
<span style={{ color: 'var(--t3)', fontSize: 11 }}>
|
|
{status === 'PENDING' ? '대기 중' : '분석 진행 중'}
|
|
</span>
|
|
<span style={{ color: 'var(--cyan)', fontSize: 12, fontWeight: 600 }}>
|
|
{status === 'PENDING' ? '—' : `${displayProgress}%`}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 안내 문구 */}
|
|
<div
|
|
style={{
|
|
color: 'var(--t3)',
|
|
fontSize: 11,
|
|
lineHeight: 1.6,
|
|
borderTop: '1px solid var(--bdL)',
|
|
paddingTop: 12,
|
|
}}
|
|
>
|
|
OpenDrift 모델로 유류 확산을 시뮬레이션하고 있습니다.
|
|
<br />
|
|
완료되면 자동으로 결과가 표시됩니다.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default SimulationLoadingOverlay;
|