feat: 보고서 지도캡처 + 드론/CCTV/확산예측 UI 기능 개선 #91

병합
jhkang feature/function_develop 에서 develop 로 27 commits 를 머지했습니다 2026-03-16 18:30:04 +09:00
2개의 변경된 파일10개의 추가작업 그리고 10개의 파일을 삭제
Showing only changes of commit 939bd0fc88 - Show all commits

파일 보기

@ -105,7 +105,7 @@ export function OilSpillView() {
const [isSelectingLocation, setIsSelectingLocation] = useState(false)
const [oilTrajectory, setOilTrajectory] = useState<Array<{ lat: number; lon: number; time: number; particle?: number; model?: PredictionModel }>>([])
const [isRunningSimulation, setIsRunningSimulation] = useState(false)
const [selectedModels, setSelectedModels] = useState<Set<PredictionModel>>(new Set(['KOSPS']))
const [selectedModels, setSelectedModels] = useState<Set<PredictionModel>>(new Set(['POSEIDON']))
const [predictionTime, setPredictionTime] = useState(48)
const [spillType, setSpillType] = useState('연속')
const [oilType, setOilType] = useState('벙커C유')
@ -163,7 +163,7 @@ export function OilSpillView() {
// 분석 탭 초기 진입 시 기본 데모 자동 표시
useEffect(() => {
if (activeSubTab === 'analysis' && oilTrajectory.length === 0 && !selectedAnalysis) {
const models = Array.from(selectedModels.size > 0 ? selectedModels : new Set<PredictionModel>(['KOSPS']))
const models = Array.from(selectedModels.size > 0 ? selectedModels : new Set<PredictionModel>(['POSEIDON']))
const demoTrajectory = generateDemoTrajectory(incidentCoord, models, predictionTime)
setOilTrajectory(demoTrajectory)
const demoBooms = generateAIBoomLines(demoTrajectory, incidentCoord, algorithmSettings)

파일 보기

@ -338,14 +338,18 @@ const PredictionInputSection = ({
{/* Model Selection (다중 선택) */}
<div className="flex flex-wrap gap-[3px]">
{([
{ id: 'KOSPS' as PredictionModel, color: 'var(--cyan)' },
{ id: 'POSEIDON' as PredictionModel, color: 'var(--red)' },
{ id: 'OpenDrift' as PredictionModel, color: 'var(--blue)' },
{ id: 'KOSPS' as PredictionModel, color: 'var(--cyan)', ready: false },
{ id: 'POSEIDON' as PredictionModel, color: 'var(--red)', ready: true },
{ id: 'OpenDrift' as PredictionModel, color: 'var(--blue)', ready: true },
] as const).map(m => (
<div
key={m.id}
className={`prd-mc ${selectedModels.has(m.id) ? 'on' : ''} cursor-pointer`}
onClick={() => {
if (!m.ready) {
alert(`${m.id} 모델은 현재 준비중입니다.`)
return
}
const next = new Set(selectedModels)
if (next.has(m.id)) {
next.delete(m.id)
@ -362,11 +366,7 @@ const PredictionInputSection = ({
<div
className={`prd-mc ${selectedModels.size === ALL_MODELS.length ? 'on' : ''} cursor-pointer`}
onClick={() => {
if (selectedModels.size === ALL_MODELS.length) {
onModelsChange(new Set(['KOSPS']))
} else {
onModelsChange(new Set(ALL_MODELS))
}
alert('앙상블 모델은 현재 준비중입니다.')
}}
>
<span className="prd-md" style={{ background: 'var(--purple)' }} />