diff --git a/M02_MasterTemplete/M02_MasterTemplete_Structure.css b/M02_MasterTemplete/M02_MasterTemplete_Structure.css index 674d1bd2d..2284bcbfe 100644 --- a/M02_MasterTemplete/M02_MasterTemplete_Structure.css +++ b/M02_MasterTemplete/M02_MasterTemplete_Structure.css @@ -18,9 +18,7 @@ flex: none; grid-auto-rows: var(--m02-struct-card-h); grid-template-columns: repeat(3, minmax(0, 1fr)); /* 도면 · 일위대가 · 면적산출(40-2) */ - padding-top: var(--spacing-12); - border-top: 1px solid var(--color-border); - min-width: 0; + min-width: 0; /* 표와 사이 = 메인 칸 간격 하나 · 구분선 없음(45-5) */ } /* 상세 칸이 좁으면(카드 하나 300px 아래) 1열 — 좌측 패널을 접어도 맞게 상세 칸 폭으로 잼 @@ -46,9 +44,18 @@ overflow-y: auto; } -/* 표는 줄어들지 않음(줄면 표가 카드 위로 넘침) */ +/* 표는 줄어들지 않음(줄면 표가 카드 위로 넘침) · 표 높이만큼만(빈 칸 최소 높이 없음 · 45-5) */ .m02-main:has(> .m02-main__extra > .m02-struct:not([hidden])) > .m02-main__host { flex-shrink: 0; + min-height: 0; +} + +/* 분류 표 틀 아래 줄 없음 — 마지막 줄 칸 선이 표를 닫음(45-5) */ +.m02-main:has(> .m02-main__extra > .m02-struct:not([hidden])) + > .m02-main__host + > .ui-sheet--combo + > .ui-sheet__scroll { + border-bottom: 0; } /* 카드 = 제목 + 머리 + 본문 — 본문이 남는 높이를 채움 · 넘치면 카드 안 스크롤 */ diff --git a/resources/master_template/area/item1.json b/resources/master_template/area/item1.json index 02dfac0e2..7ae03696e 100644 --- a/resources/master_template/area/item1.json +++ b/resources/master_template/area/item1.json @@ -9,27 +9,112 @@ { "id": "s1", "이름": "면적산출", - "칸": {}, - "연결": [ - { - "키": "콘크리트 표층 인력포설|㎥", - "이름": "콘크리트 표층 인력포설", - "칸": "B6", - "단위": "㎥" + "칸": { + "E7": { + "값": "구 분" }, - { - "키": "와이어메시 바닥깔기|㎡", - "이름": "와이어메시 바닥깔기", - "칸": "D15", - "단위": "㎡" + "F7": { + "값": "규 격" }, - { - "키": "기계비빔타설|㎥", - "이름": "기계비빔타설", - "칸": "F14", - "단위": "㎥" + "G7": { + "값": "수 량" + }, + "H7": { + "값": "단 위" + }, + "I7": { + "값": "산 출 근 거" + }, + "J7": { + "값": "비 고" + }, + "E8": { + "값": "야면석" + }, + "E9": { + "값": "고임돌량" + }, + "E10": { + "값": "뒤채움돌" + }, + "E11": { + "값": "구조물터파기량" + }, + "E12": { + "값": "되메우기량" + }, + "E13": { + "값": "잔토량" + }, + "F8": { + "값": "뒤길이35cm" + }, + "F10": { + "값": "9~15cm" + }, + "G8": { + "값": 2.65 + }, + "G9": { + "값": 0.24 + }, + "G10": { + "값": 0.94 + }, + "G11": { + "값": 0.38 + }, + "G12": { + "값": 0.11 + }, + "G13": { + "값": 0.26 + }, + "H8": { + "값": "㎡" + }, + "H9": { + "값": "㎥" + }, + "H10": { + "값": "㎥" + }, + "H11": { + "값": "㎥" + }, + "H12": { + "값": "㎥" + }, + "H13": { + "값": "㎥" + }, + "I8": { + "값": "2.5m * 1.059m / 1.0 m * 1.0 m = 2.6475m" + }, + "I9": { + "값": "2.6475m * 0.09m /1.0 m = 0.2383㎥" + }, + "I10": { + "값": "(0.45 + 0.3)/2 * 2.5 * 1.0 = 0.9375" + }, + "I11": { + "값": "(1.1+1.4)/2 * 0.3 * 1.0 = 0.375" + }, + "I12": { + "값": "(0.3+0.45)/2 * 0.3 * 1.0 = 0.1125" + }, + "I13": { + "값": "0.375 - 0.1125 = 0.2625" } - ] + }, + "열": { + "E": { + "폭": 14.460318429129464 + }, + "I": { + "폭": 39.60316685267857 + } + } } ], "활성": "s1", diff --git a/resources/master_template/labor/item1.json b/resources/master_template/labor/item1.json index b9889e9e3..77ea48848 100644 --- a/resources/master_template/labor/item1.json +++ b/resources/master_template/labor/item1.json @@ -11,84 +11,98 @@ "담은로직": [ { "로직": "GC000198", + "별칭": null, "메모": "레미콘타설(장비) 무근,소형", "입력값": {}, "수량": null }, { "로직": "GC000214", + "별칭": null, "메모": "유로폼 설치 및 해체 보통", "입력값": {}, "수량": null }, { "로직": "GC000206", + "별칭": null, "메모": "철근가공 및 조립 Type-Ⅰ-1,현장가공조립", "입력값": {}, "수량": null }, { "로직": "GC000207", + "별칭": null, "메모": "철근가공 및 조립 Type-Ⅰ-1,현장가공조립", "입력값": {}, "수량": null }, { "로직": "GF000218", + "별칭": null, "메모": "기초다짐 및 뒤채움 소형 장비사용 시공 (실무 수는 옛 판 값)", "입력값": {}, "수량": null }, { "로직": "GF000225", + "별칭": null, "메모": "깬잡석찰붙임 L3=30cm내외", "입력값": {}, "수량": null }, { "로직": "GF000156", + "별칭": null, "메모": "콘크리트(기계비빔) 무근구조물 (실무 수는 옛 판 값)", "입력값": {}, "수량": null }, { "로직": "GF000226", + "별칭": null, "메모": "큰돌메쌓기 뒷길이 0.6~0.8m", "입력값": {}, "수량": null }, { "로직": "GF000214", + "별칭": null, "메모": "야면석채집 L3=45cm내외 (실무 수는 옛 판 값)", "입력값": {}, "수량": null }, { "로직": "GF000222", + "별칭": null, "메모": "찰쌓기(켜쌓기) L3=55cm이하 (실무 수는 옛 판 값)", "입력값": {}, "수량": null }, { "로직": "GC000677", + "별칭": null, "메모": "모르터바르기 1:3", "입력값": {}, "수량": null }, { "로직": "GF000221", + "별칭": null, "메모": "돌쌓기 찰(켜)쌓기,L3=55cm이하 (실무 수는 옛 판 값)", "입력값": {}, "수량": null }, { "로직": "GC000088", + "별칭": null, "메모": "구조물터파기(토사) 굴착기0.6m3", "입력값": {}, "수량": null }, { "로직": "GF000113", + "별칭": null, "메모": "구조물되메우기 굴착기0.6m3 (실무 수는 옛 판 값)", "입력값": {}, "수량": null diff --git a/resources/tester/test_m02_area_panel.py b/resources/tester/test_m02_area_panel.py index 0fc11d34a..cccd2e3f7 100644 --- a/resources/tester/test_m02_area_panel.py +++ b/resources/tester/test_m02_area_panel.py @@ -56,7 +56,7 @@ def test_칸_지정_모달은_setLink_만(): def test_빈_칸은_수량_없음_서버와_같음(): - """39-8 ② — 빈 칸에 이은 알약 = 수량 없음(반영 「—」 · 「수량 A1 = 빈 칸」) · 0 칸 = 0 · 값 칸 = 값.""" + """39-8 ② — 빈 칸에 이은 알약 = 수량 없음(반영 「—」 · 「수량 빈 칸(A1)」) · 0 칸 = 0 · 값 칸 = 값.""" from M02_MasterTemplete import M02_Labor_Doc as labor doc = { @@ -79,7 +79,7 @@ def test_빈_칸은_수량_없음_서버와_같음(): sheet = (ROOT / "A00_Common" / "spreadsheet" / "spreadsheet.ts").read_text(encoding="utf-8") assert 'const empty = !cell || (cell.식 === undefined && (cell.값 ?? "") === "");' in sheet rows = _text("M02_MasterTemplete_Labor_Rows.ts") - assert '${tc("Labor_Qty")} ${at} = ${tc("In_QtyEmpty")}' in rows + assert '${tc("Labor_Qty")} ${tc("In_QtyEmpty")}(${at})' in rows assert "if (!value) return `${link.칸} = ${TEXT.empty}`;" in _text( "M02_MasterTemplete_AreaLink.ts" ) diff --git a/resources/tester/ui_checks/45-5_분류표_카드_간격.js b/resources/tester/ui_checks/45-5_분류표_카드_간격.js new file mode 100644 index 000000000..1cf8bcf97 --- /dev/null +++ b/resources/tester/ui_checks/45-5_분류표_카드_간격.js @@ -0,0 +1,32 @@ +/* 45-5 — M02 구조물 조합 상세(항목 고른 화면) · 분류 표와 카드 셋(도면 정보 · 일위대가 · 면적산출) 사이 간격 · 구분선 + * 시작 화면: M02 마스터 템플릿 · 마스터 층(#/m02-master-template?open=구조물조합&root=master) · 나무에 item1 이 있음 + * 부르는 법: orca eval --expression "$(cat 이 파일)" (async 식 · JSON 글을 돌려줌) + * 기대 수치: + * - gap = 표 틀 아래 끝 ~ 첫 카드 위 끝 = 메인 칸 간격(12px 안팎 · 옛 107px) + * - tableLine = 0(표 틀 아래 줄 없음) · lastRow > 0(마지막 줄 칸 선이 표를 닫음) + * - cardsLine = 0 · cardsPad = 0(카드 칸 위 줄 · 안쪽 여백 없음) · hr = 0 + */ +(async () => { + const w = (ms) => new Promise((r) => setTimeout(r, ms)); + document.querySelector('[data-node="i|item1"]').click(); + for ( + let t = 0; + t < 5000 && !document.querySelector(".m02-struct:not([hidden]) .m02-struct__card"); + t += 100 + ) + await w(100); + await w(300); + const scroll = document.querySelector(".m02-main__host .ui-sheet__scroll"); + const struct = document.querySelector(".m02-struct"); + const card = struct.querySelector(".m02-struct__card"); + const cells = scroll.querySelectorAll("th, td"); + const cs = (e) => getComputedStyle(e); + return JSON.stringify({ + gap: Math.round(card.getBoundingClientRect().top - scroll.getBoundingClientRect().bottom), + tableLine: parseFloat(cs(scroll).borderBottomWidth), + lastRow: parseFloat(cs(cells[cells.length - 1]).borderBottomWidth), + cardsLine: parseFloat(cs(struct).borderTopWidth), + cardsPad: parseFloat(cs(struct).paddingTop), + hr: document.querySelectorAll(".m02-main hr").length, + }); +})();