feat(563-1): D03 떠날 때 선만 저장(beforeLeave) · 시점 · 종점은 network 응답 base 로

- 단계 아이콘 · [<] [>] · 머리 메뉴 · 뒤로 = 고친 선이 있으면 PUT plan/network 뒤 이동 · 실패면 머묾
- D02 points 따로 부르지 않음(562-2 GET network 의 base · year_start)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-27 20:18:43 +09:00
co-authored by Claude Opus 5.5
parent 65e7a404b8
commit 1bb7a2c957
2 changed files with 13 additions and 9 deletions
+4 -5
View File
@@ -1,7 +1,7 @@
/* =============================================================================
* D03_PlanAnalysis_Api.ts
* D03 분석 화면 서버 요청(PLAN 563-1) — 전체 시점 · 종점(D02 정본) · 지형 받기 범위 · 받기 · 진행 ·
* 사업 전체 지형면 한 벌(`models_plan/` · 격자) · 그은 선 정본(562-2 GET · PUT network).
* D03 분석 화면 서버 요청(PLAN 563-1) — 지형 받기 범위 · 받기 · 진행 ·
* 사업 전체 지형면 한 벌(`models_plan/` · 격자) · 그은 선 정본(562-2 GET · PUT network · 응답에 D02 시점 · 종점).
* ========================================================================== */
import { API_BASE_URL } from "@config/config_frontend";
@@ -53,6 +53,8 @@ export interface ServerNetwork {
}
export interface PlanNetworkView {
/** D02 정본 전체 시점 · 종점. */
base: PlanBaseView;
network: ServerNetwork | null;
derived: {
lines: Array<{ id: string; length_m: number; stations: number[] }>;
@@ -85,9 +87,6 @@ async function request<T>(path: string, init: RequestInit = {}): Promise<T> {
const base = (projectId: string): string => `/projects/${projectId}/plan`;
export const fetchPlanBase = (projectId: string): Promise<PlanBaseView> =>
request(`${base(projectId)}/points`);
/** 받기 전 범위 — `extra` = 더 덮을 점(그은 꺾임점). */
export const fetchTerrainExtent = (
projectId: string,
+9 -4
View File
@@ -39,7 +39,6 @@ import { prepareLayer } from "../B04_PreProcess/logic/B04_PreProcess_UI_MapRende
import { heightAt as gridHeightAt } from "../common_util/common_util_surface_sampler";
import { stationLabel } from "../common_util/common_util_station";
import {
fetchPlanBase,
fetchPlanNetwork,
fetchPlanProgress,
fetchPlanSurface,
@@ -164,7 +163,12 @@ export async function renderD03PlanAnalysis(root: HTMLElement): Promise<void> {
panel.className = "ui-sidebar-panel d03-plan__panel";
panel.append(terrainCard, drawCard, pieceCard, actions);
attachCollapsible(panel);
mountGroupStep(root, ROUTES.D03_PLAN_ANALYSIS, { mainContent: main, leftPanel: panel });
// 떠날 때(단계 아이콘 · [<] [>] · 머리 메뉴 · 뒤로) 선만 저장 · 실패면 머묾
mountGroupStep(root, ROUTES.D03_PLAN_ANALYSIS, {
mainContent: main,
leftPanel: panel,
beforeLeave: async () => !editable || !dirty() || (await save()),
});
root.querySelector(".ui-workflow-layout")?.classList.add("d03-plan-layout");
const allVertices = (): Vertex[] => network.lines.flatMap((line) => line.vertices);
@@ -558,7 +562,8 @@ export async function renderD03PlanAnalysis(root: HTMLElement): Promise<void> {
try {
editable = !!(await fetchSessionUser())?.is_forest_service;
draw.setEditable(editable);
const base = await fetchPlanBase(projectId);
const view = await fetchPlanNetwork(projectId);
const base = view.base;
if (!base.start || !base.end || !base.epsg) {
terrainText.textContent = "시점 · 종점이 비었습니다 — 1단계(기준 지정)에서 정하세요.";
return;
@@ -566,7 +571,7 @@ export async function renderD03PlanAnalysis(root: HTMLElement): Promise<void> {
start = [base.start.x, base.start.y];
end = [base.end.x, base.end.y];
epsg = base.epsg;
takeServer(await fetchPlanNetwork(projectId));
takeServer(view);
const draft = readState<Draft>("d03-plan", projectId);
if (draft?.version === DRAFT_VERSION && draft.network?.lines?.length) network = draft.network;
map.update({ fit: [start, end, ...allVertices()] });