Merge remote-tracking branch 'origin/sub_laptop_1' into main_laptop_1
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
* 초안이 있으면 측점을 냄(새로고침 · 다시 열기 = 초안 측점 · 466).
|
||||
* 노선 초안을 버리면(되돌리기 · [저장 전으로]) 초안 전 상세 · 횡단 초안 칸 그대로(349-0k · 349-0o) · 가게 측점 ·
|
||||
* 종단 = 그 상세 측점 · 저장 기준(466) · 그 뒤 같은 측점 목록은 가게에 다시 안 냄(상세 측점이 묶음과 달라도 · 349-0q).
|
||||
* [저장](sub5)이 서버 정본 — 노선을 먼저 보내고 `pendingAlignment(DRAFT_ROUTE_ID)` 를 새 노선에 보냄.
|
||||
* [저장]이 서버 정본 — 노선 바뀐 [저장]의 계획고 = 저장분 옮김 대 손댐만(`routeGradeTouch` · 서버가 자기 옮김 위에 · 498-2).
|
||||
* ========================================================================== */
|
||||
|
||||
import { createDesignPipeline, type DesignPipeline } from "./logic/design_pipeline";
|
||||
@@ -91,6 +91,7 @@ import {
|
||||
createPlanlineStage,
|
||||
gradeRange,
|
||||
routeRange,
|
||||
type GradeTouch,
|
||||
} from "../../B05_Profile/logic/B05_Profile_Pipeline_Grade";
|
||||
import { groundPviAt, profileAt } from "./design_calc_profile";
|
||||
import {
|
||||
@@ -127,6 +128,7 @@ interface PagePipeline {
|
||||
detail(): SectionDetailResponse | null;
|
||||
/** 노선 초안 버림 동안(그리기 멈춤 ~ 풂) — 저장 노선 낡음 다시 셈을 안 띄움(472-5 덧). */
|
||||
holding(): boolean;
|
||||
touch(): Promise<GradeTouch | null>;
|
||||
commit(): void;
|
||||
dispose(): void;
|
||||
}
|
||||
@@ -137,6 +139,9 @@ type Facilities = Pick<DesignStoreValues, "pipes" | "structures">;
|
||||
const pages = new Map<string, PagePipeline>();
|
||||
const same = (a: unknown, b: unknown): boolean => JSON.stringify(a) === JSON.stringify(b);
|
||||
|
||||
/** 노선 바뀐 [저장]의 계획고 손댐(498-2) — 묶음이 없거나 못 가르면 null(본문 = 노선 0 칸 통째 · 옛 길). */
|
||||
export const routeGradeTouch = async (id: string) => (await pages.get(id)?.touch()) ?? null;
|
||||
|
||||
/** 편집기에 넘길 다리 — 그 프로젝트 묶음을 처음 부를 때 세움. */
|
||||
export function routeDraftBridge(
|
||||
projectId: string,
|
||||
@@ -271,7 +276,12 @@ function createPagePipeline(
|
||||
route.curves,
|
||||
(patch.pipes ?? inputs.pipes ?? []) as PlanPipe[],
|
||||
(patch.structures ?? inputs.structures ?? []) as PlanStructure[],
|
||||
{ intervalM: options.stationIntervalM, types: enabled, ...snapOptions(inputs.route, plan) },
|
||||
{
|
||||
intervalM: options.stationIntervalM,
|
||||
types: enabled,
|
||||
...snapOptions(inputs.route, plan),
|
||||
plus: patch.plusStations ?? inputs.plusStations ?? undefined, // stations 단계와 같게(498-2)
|
||||
},
|
||||
).map((station) => station.chainageM),
|
||||
});
|
||||
/** cross 서버 단계 맥락(511-B B-4) — 저장 노선 · 상세 · 시설 · 편집(`design_pipeline_cross_server`). */
|
||||
@@ -678,6 +688,7 @@ function createPagePipeline(
|
||||
ownsCross: Boolean(options.savedCross),
|
||||
detail: () => draftDetailOf(projectId),
|
||||
holding: () => holding,
|
||||
touch: async () => (await pipe.settled(), followStage.touch(pageSaved.storedEdits(), pipe)),
|
||||
commit: () => void (beforeDraft = null),
|
||||
dispose() {
|
||||
disposed = true;
|
||||
|
||||
@@ -82,6 +82,11 @@ export function createPageSaved(
|
||||
savedSource,
|
||||
canonChanged,
|
||||
savedEdits,
|
||||
/** 서버 저장분 계획고 편집(세션 초안 뺌) — 노선 바뀐 [저장]에서 서버가 옮기는 그 값(498-2). */
|
||||
storedEdits(): AlignmentEdits {
|
||||
const longitudinal = canonDetail()?.longitudinal;
|
||||
return (longitudinal && readAlignment(longitudinal)?.edits) ?? emptyEdits();
|
||||
},
|
||||
storedPvi,
|
||||
crossNow,
|
||||
drafted,
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* 노선(346-3 · 6-B) — 노선 초안이 마지막 저장과 다르면 같은 본문에 `route`(계약 `RouteDraft`) · `carry`(옛 노선
|
||||
* 세션 횡단 고침 원본)를 실음. 서버가 맨 앞에서 노선 저장(관 · 구조물 · 추가 측점 좌표 따라감 · 종횡단 · 계획고
|
||||
* 이월) → 관 · 구조물 초안 다시 얹기 → 새 노선으로 위 차례 → 횡단 = 세션 고침을 측점 열쇠로 넘긴 patch(같은 TS ·
|
||||
* Node). 이 때 조각은 기본 조각만(화면 몫 일 = 옛 노선 판이라 건너뜀) · 계획고 초안 = 노선 초안 칸 ?? 옛 노선 칸 ·
|
||||
* Node). 이 때 조각은 기본 조각만(화면 몫 일 = 옛 노선 판이라 건너뜀) · 계획고 = 손댐만(서버 옮김 위에 · 498-2) ·
|
||||
* 손 상단측은 안 보냄(요구 274) · [확정]도 [저장]으로(새 노선을 본 뒤 다시 [확정]) · 다 저장하면 페이지 다시 세움.
|
||||
*
|
||||
* ⚠ 차례를 바꾸면 결과가 갈린다 — 관 목록은 스냅샷이라 구간값(암거 옵션)보다 먼저, 상단측은
|
||||
@@ -49,6 +49,8 @@ import {
|
||||
} from "../../B05_Profile/B05_Profile_UI_RouteEdit_Apply";
|
||||
import type { RouteSaveBody } from "../../B05_Profile/B05_Profile_Api_Replan";
|
||||
import { designSignature, markDesignClean } from "./design_leave";
|
||||
import { routeGradeTouch } from "./design_pipeline_page";
|
||||
import type { GradeTouch } from "../../B05_Profile/logic/B05_Profile_Pipeline_Grade";
|
||||
|
||||
export interface DesignSaveContext {
|
||||
projectId: string;
|
||||
@@ -166,10 +168,12 @@ export function noticeDroppedEdits(saved: { dropped_edit_chainages?: number[] })
|
||||
/** 노선 초안 동안의 계획고 초안 칸 — `design_pipeline_page` 의 `DRAFT_ROUTE_ID` 와 같은 값(sub7). */
|
||||
const DRAFT_ROUTE_ID = 0;
|
||||
|
||||
/** 계획고 조각 — 노선이 바뀌면 노선 초안 칸(`DRAFT_ROUTE_ID`) ?? 옛 노선 칸의 초안(서버가 새 노선 번호로 고쳐
|
||||
* 씀 · 측점이 없는 자리는 버리고 알림 · 213-2) · 저장 뒤 두 칸 다 비움. */
|
||||
function alignmentPart(routeId: number, moved: boolean): SavePart | null {
|
||||
const draft = (moved ? pendingAlignment(DRAFT_ROUTE_ID) : null) ?? pendingAlignment(routeId);
|
||||
/** 계획고 조각 — 노선이 바뀌면 사용자 손댐(`touch` · 서버가 자기 옮김 위에 얹음 · 498-2) · 못 가르면 노선 초안
|
||||
* 칸(`DRAFT_ROUTE_ID`) ?? 옛 노선 칸의 초안 통째(서버가 새 노선 번호로 고쳐 씀) · 측점이 없는 자리는 버리고 알림
|
||||
* (213-2) · 저장 뒤 두 칸 다 비움. */
|
||||
function alignmentPart(routeId: number, moved: boolean, touch: GradeTouch | null): SavePart | null {
|
||||
const draft =
|
||||
touch?.edits ?? (moved ? pendingAlignment(DRAFT_ROUTE_ID) : null) ?? pendingAlignment(routeId);
|
||||
if (!draft) return null;
|
||||
return {
|
||||
body: { route_id: routeId, ...draft },
|
||||
@@ -188,6 +192,7 @@ async function defaultPart(
|
||||
routeId: number,
|
||||
confirm: boolean,
|
||||
moved: boolean,
|
||||
touch: GradeTouch | null,
|
||||
): Promise<SavePart | null> {
|
||||
switch (key) {
|
||||
case "settings": // 노선 뒤 — 노선 저장이 새로 만든 종단에도 경고 기준이 얹힘(448)
|
||||
@@ -199,7 +204,7 @@ async function defaultPart(
|
||||
case "plusStations": // 계획고 앞 — 추가 측점 자리의 계획고 편집이 버려지지 않게(368-2)
|
||||
return plusStationsPart(projectId);
|
||||
case "alignment":
|
||||
return alignmentPart(routeId, moved);
|
||||
return alignmentPart(routeId, moved, touch);
|
||||
case "culvertOptions":
|
||||
return culvertOptionsPart(stateKey("culvertopt", projectId, routeId));
|
||||
case "uphill":
|
||||
@@ -257,12 +262,13 @@ export async function saveDesign(
|
||||
const parts: Partial<Record<SavePartKey, SavePart | null>> = {};
|
||||
// 노선이 바뀌면 횡단 = 옛 노선 세션 고침 원본(서버가 새 측점에 넘김) · 화면 몫 조각은 옛 노선 판이라 안 씀
|
||||
const carried = route ? routeCarryPart(ctx.projectId, routeId) : null;
|
||||
const touch = route ? await routeGradeTouch(ctx.projectId) : null;
|
||||
for (const key of SAVE_PART_KEYS) {
|
||||
if (key === "cross") {
|
||||
parts.cross = carried ? carried.cross : await ctx.crossPart(confirm);
|
||||
continue;
|
||||
}
|
||||
const base = await defaultPart(key, ctx.projectId, routeId, confirm, !!route);
|
||||
const base = await defaultPart(key, ctx.projectId, routeId, confirm, !!route, touch);
|
||||
const own = route ? undefined : ctx.parts?.[key];
|
||||
parts[key] = own ? await own(base, confirm) : base;
|
||||
}
|
||||
@@ -272,7 +278,7 @@ export async function saveDesign(
|
||||
routeId,
|
||||
confirm,
|
||||
parts,
|
||||
route ? { route, carry: carried?.carry } : {},
|
||||
route ? { route, carry: carried?.carry, alignment_cleared: touch?.cleared } : {},
|
||||
);
|
||||
if (result.waited) showToast("앞 저장이 끝나기를 기다린 뒤 저장했습니다.", "info");
|
||||
// 저장 도중 고침(가림막 동안 키 · 되돌리기 포함 · 505-2) — 조각 정리가 그 고침까지 비우므로 건너뜀(서버는 낸
|
||||
|
||||
@@ -69,7 +69,7 @@ export async function postDesignSave(
|
||||
routeId: number,
|
||||
confirm: boolean,
|
||||
parts: Partial<Record<SavePartKey, SavePart | null>>,
|
||||
extra: { route?: unknown; carry?: unknown } = {},
|
||||
extra: { route?: unknown; carry?: unknown; alignment_cleared?: unknown } = {},
|
||||
): Promise<DesignSaveResult> {
|
||||
const body: Record<string, unknown> = { route_id: routeId, confirm, ...extra };
|
||||
for (const key of SAVE_PART_KEYS) {
|
||||
|
||||
Reference in New Issue
Block a user