- JDL 줄 = 탭 구분 + \x05/\x07 덧붙임(검사기 0x504d20 · 고정폭 표는 죽은 고리 — 34 §17.9 바로잡음) · 단가 목록 7종·Main·GongJong 머리·Global.Ini 상수 키 · zip 받기 - 구버전 판 가리기(Chk_Data 0x459280) · 7.x/DOS 표별 필드 대응 · B→X 조건 = 단위 X - 엑셀 역등록 PRPT「속성」·PRIN「대상」·PROUT「저장」 = PR/RR 줄만 · 원본 BDQTY 4건 일치 - 자재 = 재료비 수량집계표 엑셀 내보내기(주요건설자재현황 시트) - 그림 코드 = COSTN I 코드 IFORM · SIZE = 그림 클래스 이름 - 지식DB 37번 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
91 lines
2.7 KiB
Python
91 lines
2.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""그림 코드 끼워 넣기 API — I 코드 목록 · 그림 보기(받기) · 그림 넣기(그림저장).
|
|
|
|
근거: img_code.py 머리(STmate.Cpm TwM_Boxa 0x514df0 · 0x514bc0 · 0x5155a8)
|
|
쓰기는 tools/stmate-test/work_dbf/ 아래만(server.WORK_DBF_ROOT) · 바뀌는 파일은 COSTN.DBF · COSTN.SMT 둘뿐.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import base64
|
|
import pathlib
|
|
from urllib.parse import quote
|
|
|
|
from fastapi import APIRouter, HTTPException
|
|
from fastapi.responses import Response
|
|
from img_code import get_image, list_images, put_image
|
|
from pydantic import BaseModel
|
|
from stc_project import safe_name, write_output
|
|
from stc_read import Source
|
|
|
|
router = APIRouter()
|
|
EXT = {"TJPEGIMAGE": ".jpg", "TBITMAP": ".bmp", "TICON": ".ico", "TMETAFILE": ".emf"}
|
|
|
|
|
|
def _root() -> pathlib.Path:
|
|
import server
|
|
|
|
return server.WORK_DBF_ROOT
|
|
|
|
|
|
def _src(path: str) -> Source:
|
|
try:
|
|
return Source(path)
|
|
except FileNotFoundError:
|
|
raise HTTPException(404, f"경로 없음: {path}")
|
|
except ValueError as e:
|
|
raise HTTPException(400, str(e))
|
|
|
|
|
|
def _guard(fn, *a, **k):
|
|
try:
|
|
return fn(*a, **k)
|
|
except (ValueError, KeyError) as e:
|
|
raise HTTPException(400, str(e))
|
|
|
|
|
|
class ImgReq(BaseModel):
|
|
source_path: str
|
|
code: str = ""
|
|
|
|
|
|
class ImgPutReq(BaseModel):
|
|
source_path: str
|
|
code: str
|
|
data_b64: str
|
|
filename: str
|
|
to_jpeg: bool = False
|
|
target_folder_name: str = ""
|
|
|
|
|
|
@router.post("/api/img/list")
|
|
def img_list(req: ImgReq):
|
|
return {"rows": _guard(list_images, _src(req.source_path).files)}
|
|
|
|
|
|
@router.post("/api/img/get")
|
|
def img_get(req: ImgReq):
|
|
"""그림 바이트 — 브라우저가 못 그리는 꼴(TMETAFILE)은 mime 없이(받기만)."""
|
|
data, kind, mime = _guard(get_image, _src(req.source_path).files, req.code)
|
|
if not data:
|
|
raise HTTPException(404, f"{req.code} 그림 없음")
|
|
name = quote(f"{req.code.strip()}{EXT.get(kind, '.bin')}")
|
|
head = {"X-Img-Kind": kind or "?", "Content-Disposition": f"inline; filename*=UTF-8''{name}"}
|
|
return Response(content=data, media_type=mime or "application/octet-stream", headers=head)
|
|
|
|
|
|
@router.post("/api/img/put")
|
|
def img_put(req: ImgPutReq):
|
|
"""그림 넣기 → work_dbf/<이름>/ 와 STC(COSTN.DBF · COSTN.SMT 만 바뀜)."""
|
|
s = _src(req.source_path)
|
|
try:
|
|
data = base64.b64decode(req.data_b64.split(",", 1)[-1])
|
|
except ValueError:
|
|
raise HTTPException(400, "base64 아님")
|
|
changed, rep = _guard(put_image, s.files, req.code, data, req.filename, req.to_jpeg)
|
|
files = dict(s.files) | changed
|
|
res = write_output(
|
|
_root(), safe_name(req.target_folder_name or s.path.stem), files, s.names, s.entries
|
|
)
|
|
return {**res, "report": rep}
|