fix(534-3): E05 길 저장 · 갱신 · 초기화가 옛 모듈을 부름 · 시트 서명 수 꼴 맞춤 · 화면 높이
- 길: asyncio.to_thread(build.save · refresh · reset) → store(나눈 storage 모듈) — PUT 500 고침 - 시트 서명: 수를 float 로 맞춤 — 화면(JS)을 거친 10.0 → 10 을 사용자 고침으로 잘못 알리던 덮임 알림 고침 - 화면: 본문 칸이 min-height 뿐이라 내장 엑셀 격자 높이 0 — 본문 높이 calc(100dvh - 머리) - 그림: 우기 · 지진 임계면 점선(건기와 겹쳐도 보임) · 해석 방법 글 짧게(Bishop) - 시험: 길(TestClient — 판 409 · 저장 · 갱신 · 그림 · xlsx · 초기화) · 서명 화면 왕복 같음 — 7 통과 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -48,7 +48,7 @@ LOWEST_N = 5 # representative.json 이 없을 때 — 최소 안전율 하위 N
|
||||
CASES = ("dry", "wet", "seismic")
|
||||
SIDE_NAMES = {"cut": "깎기", "fill": "쌓기"}
|
||||
METHOD_NAMES = {
|
||||
"bishop": "Bishop 간편법",
|
||||
"bishop": "Bishop",
|
||||
"janbu": "Janbu 보정",
|
||||
"janbu_corrected": "Janbu 보정",
|
||||
"ordinary": "Fellenius",
|
||||
@@ -589,5 +589,16 @@ def sheet_sign(sheet: dict[str, Any]) -> str:
|
||||
"행": {k: v for k, v in (sheet.get("행") or {}).items() if v},
|
||||
"열": {k: v for k, v in (sheet.get("열") or {}).items() if v},
|
||||
}
|
||||
text = json.dumps(body, ensure_ascii=False, sort_keys=True)
|
||||
text = json.dumps(_numbers(body), ensure_ascii=False, sort_keys=True)
|
||||
return hashlib.sha1(text.encode("utf-8")).hexdigest()
|
||||
|
||||
|
||||
def _numbers(value: Any) -> Any:
|
||||
"""수는 float 로 — 화면(JS)을 거치면 10.0 이 10 으로 옴(같은 값을 다르다고 보지 않게)."""
|
||||
if isinstance(value, dict):
|
||||
return {k: _numbers(v) for k, v in value.items()}
|
||||
if isinstance(value, list):
|
||||
return [_numbers(v) for v in value]
|
||||
if isinstance(value, int | float) and not isinstance(value, bool):
|
||||
return round(float(value), 9)
|
||||
return value
|
||||
|
||||
@@ -21,6 +21,7 @@ BAND_W, BAND_H = 684, 320
|
||||
OK, NG, MUTED, INK = "#2E7D32", "#C00000", "#9E9E9E", "#222222"
|
||||
CONDITION_COLORS = {"dry": "#D32F2F", "wet": "#1565C0", "seismic": "#7B1FA2"}
|
||||
CONDITION_NAMES = {"dry": "건기", "wet": "우기", "seismic": "지진"}
|
||||
SLIP_DASH = {"wet": "7 4", "seismic": "2 3"} # 건기 · 우기 임계면이 겹쳐도 둘 다 보이게
|
||||
FONT = "font-family='Malgun Gothic, sans-serif'"
|
||||
|
||||
|
||||
@@ -155,7 +156,9 @@ def section_svg(
|
||||
# 임계 활동면
|
||||
for slip in slips:
|
||||
color = CONDITION_COLORS.get(slip["condition"], NG)
|
||||
out.append(_poly(screen(slip["points"]), stroke=color, stroke_width="2.2"))
|
||||
dash = SLIP_DASH.get(slip["condition"])
|
||||
extra = {"stroke_dasharray": dash} if dash else {}
|
||||
out.append(_poly(screen(slip["points"]), stroke=color, stroke_width="2.2", **extra))
|
||||
# 치수 — 노폭 · 비탈 높이
|
||||
if road:
|
||||
r_off, l_off = road
|
||||
@@ -206,7 +209,7 @@ def section_svg(
|
||||
(
|
||||
CONDITION_COLORS.get(slip["condition"], NG),
|
||||
f"{name} 임계면 Fs {f:.2f}" if f else name,
|
||||
"",
|
||||
SLIP_DASH.get(slip["condition"], ""),
|
||||
)
|
||||
)
|
||||
if wet:
|
||||
|
||||
@@ -137,7 +137,7 @@ async def put_report(project_id: UUID, payload: SaveRequest) -> dict[str, Any]:
|
||||
status_code=409, detail="다른 곳에서 보고서가 바뀌었습니다 — 다시 여세요."
|
||||
)
|
||||
try:
|
||||
await asyncio.to_thread(build.save, root, payload.book)
|
||||
await asyncio.to_thread(store.save, root, payload.book)
|
||||
except RecalcError as error:
|
||||
raise _recalc_errors(error) from error
|
||||
return {"status": "success", **await asyncio.to_thread(_state, root)}
|
||||
@@ -153,7 +153,7 @@ async def refresh_report(project_id: UUID, payload: RevRequest) -> dict[str, Any
|
||||
status_code=409, detail="다른 곳에서 보고서가 바뀌었습니다 — 다시 여세요."
|
||||
)
|
||||
try:
|
||||
result = await asyncio.to_thread(build.refresh, root)
|
||||
result = await asyncio.to_thread(store.refresh, root)
|
||||
except build.MissingInput as error:
|
||||
raise HTTPException(status_code=409, detail=str(error)) from error
|
||||
except (RecalcError, PrintError) as error:
|
||||
@@ -169,7 +169,7 @@ async def refresh_report(project_id: UUID, payload: RevRequest) -> dict[str, Any
|
||||
async def reset_report(project_id: UUID) -> dict[str, Any]:
|
||||
root, _ = await _project(project_id)
|
||||
async with _lock(project_id):
|
||||
if not await asyncio.to_thread(build.reset, root):
|
||||
if not await asyncio.to_thread(store.reset, root):
|
||||
raise HTTPException(status_code=404, detail="초기값이 없습니다.")
|
||||
return {"status": "success", **await asyncio.to_thread(_state, root)}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
.e05-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
height: calc(100dvh - var(--app-header-h)); /* 본문 칸은 min-height 뿐 — 100% 가 안 풀림 */
|
||||
min-height: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user