feat(B09): 칸 단위 근거 호버·등급색 배선 + 줄 사유 덮어쓰기 버그 수정
① 버그 — BillRow.note 한 칸에 덮어쓰던 13곳·이어 붙이던 7곳을 조각 배열 notes 로 옮김. 한 줄에 사유가 둘이면 하나가 조용히 사라지던 것이 멈춤. 조각마다 닿는 열 키를 함께 실어 호버가 그 칸에만 띄우게 함. 화면 비고 칸은 종전과 같은 꼴 유지. ② 사전 — B09_Estimation_Provenance.py 신설(기존 B09 파일이 700줄 초과). 8장 57열. 이미 있던 formula_text·source_label·base_label 은 그대로 쓰고 없는 것만 새로 적음. ③ 배선 — 라우터 5개 응답에 _with_provenance(), 표 여섯에 markProvenanceCell + attachProvenance. 개발환경이 아니면 응답에 칸 자체가 안 생김(로직 보안). ④ 등급색 토글을 탭 줄 끝에. 사전이 안 오면 단추도 안 세움. ⚠ 원가계산서 금액은 같은 열에서 중간줄과 마지막줄의 성격이 갈리는데 등급이 열에 하나뿐이라 calc 로 두고 rule 에 어느 줄이 final 인지 적음(PLAN 8-36 ① 에 남김). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GrXDD23Dvt2sR7q3X6oekp
This commit is contained in:
@@ -13,6 +13,12 @@
|
||||
* ========================================================================== */
|
||||
|
||||
import { ui_locales, currentLanguageIndex } from "@ui/ui_template_locale";
|
||||
import {
|
||||
attachProvenance,
|
||||
markProvenanceCell,
|
||||
type ProvenancePayload,
|
||||
type ProvenanceSheet,
|
||||
} from "@ui/ui_template_provenance";
|
||||
import { API_BASE_URL } from "@config/config_frontend";
|
||||
|
||||
function L(key: keyof typeof ui_locales): string {
|
||||
@@ -48,6 +54,8 @@ export interface BaseDataDto {
|
||||
material: BaseDataRow[];
|
||||
expense: BaseDataRow[];
|
||||
machine: MachineRow[];
|
||||
/** 근거 사전 — **개발환경에서만** 온다. 없으면 호버·등급색이 통째로 안 붙는다. */
|
||||
provenance?: ProvenancePayload;
|
||||
}
|
||||
|
||||
export async function fetchBaseData(projectId: string): Promise<BaseDataDto> {
|
||||
@@ -80,7 +88,19 @@ function note(text: string): HTMLElement {
|
||||
return el;
|
||||
}
|
||||
|
||||
function table(headers: string[], rows: string[][], leftCols: number[]): HTMLElement {
|
||||
/**
|
||||
* 표 한 장.
|
||||
*
|
||||
* `keys`·`sheet` 를 함께 주면 칸마다 근거 호버가 붙는다 — **사전이 없으면 아무 일도
|
||||
* 안 한다**(빈 카드를 띄우면 「설명이 있다」는 거짓만 남는다). 안 주는 표는 종전 그대로다.
|
||||
*/
|
||||
function table(
|
||||
headers: string[],
|
||||
rows: string[][],
|
||||
leftCols: number[],
|
||||
keys?: string[],
|
||||
sheet?: ProvenanceSheet,
|
||||
): HTMLElement {
|
||||
const el = document.createElement("table");
|
||||
el.className = "b09-sheet";
|
||||
const thead = document.createElement("thead");
|
||||
@@ -99,16 +119,20 @@ function table(headers: string[], rows: string[][], leftCols: number[]): HTMLEle
|
||||
const td = document.createElement("td");
|
||||
td.textContent = text;
|
||||
if (leftCols.includes(index)) td.className = "b09-left";
|
||||
const key = keys?.[index];
|
||||
const column = key ? sheet?.columns[key] : undefined;
|
||||
if (key && column) markProvenanceCell(td, key, column.tier);
|
||||
tr.append(td);
|
||||
});
|
||||
tbody.append(tr);
|
||||
}
|
||||
el.append(thead, tbody);
|
||||
attachProvenance(el, sheet);
|
||||
return el;
|
||||
}
|
||||
|
||||
/** 목록표 한 장 — 코드·명칭·규격·단위·단가·비고 (실무 시트와 같은 칸). */
|
||||
function catalogTable(rows: BaseDataRow[]): HTMLElement {
|
||||
function catalogTable(rows: BaseDataRow[], sheet?: ProvenanceSheet): HTMLElement {
|
||||
return table(
|
||||
["코드번호", "명 칭", "규 격", "단위", "단 가", "비 고"],
|
||||
rows.map((row) => [
|
||||
@@ -120,6 +144,8 @@ function catalogTable(rows: BaseDataRow[]): HTMLElement {
|
||||
row.note,
|
||||
]),
|
||||
[0, 1, 2, 5],
|
||||
["code", "name", "spec", "unit", "unit_price_krw", "note"],
|
||||
sheet,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -148,7 +174,7 @@ export function drawBaseDataTab(body: HTMLElement, data: BaseDataDto): void {
|
||||
body.append(note("아직 선 줄이 없습니다 — 값을 0 으로 채우지 않습니다."));
|
||||
continue;
|
||||
}
|
||||
body.append(catalogTable(rows));
|
||||
body.append(catalogTable(rows, data.provenance?.sheets?.catalog));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +200,18 @@ export function drawMachineTab(body: HTMLElement, data: BaseDataDto): void {
|
||||
row.note,
|
||||
]),
|
||||
[0, 1, 2, 8],
|
||||
[
|
||||
"code",
|
||||
"name",
|
||||
"spec",
|
||||
"unit",
|
||||
"total_krw",
|
||||
"labor_krw",
|
||||
"material_krw",
|
||||
"expense_krw",
|
||||
"note",
|
||||
],
|
||||
data.provenance?.sheets?.machine,
|
||||
),
|
||||
);
|
||||
// ⚠ 계산 과정을 감추지 않는다(PLAN 8-13). 조종원 환산이 실무와 다른 것을 여기서 밝힌다.
|
||||
|
||||
Reference in New Issue
Block a user