Files
Aislo/tools/est-test/native-views.js
T
eomsangdonandClaude Opus 5.5 cc1a6bcbde feat(est-test): 원가계산서 산출근거 약어로 표시
- 원본 popupSNameShow: 산출근거 식의 기호를 비목 약어로, 숫자를 요율 글자로 바꿔 화면·인쇄에 표시하고 편집 잠금, 저장 값은 그대로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-12 12:51:14 +09:00

156 lines
6.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const EstViews = (() => {
const enums = {
LinkIndex: [
[0, "직접입력"],
[5, "자재"],
[6, "노임"],
[21, "표준"],
[101, "견적"],
[103, "일위"],
[104, "단가산출"],
[105, "기계"],
[51, "소계"],
[52, "낙찰"],
[54, "순공사비"],
[55, "도급액"],
[57, "조달수수료"],
[58, "비율"],
[59, "경계"],
[61, "산근 소계"],
[62, "구간비율"],
[67, "내역비율"],
[68, "묶음끝"],
[99, "연차 배분"],
],
CalcIndex: [
[0, "계산·합산"],
[1, "고정·합산"],
[2, "계산·제외"],
[3, "고정·제외"],
],
ValueIndex: [
[0, "최저"],
[1, "평균"],
[2, "최고"],
[3, "출처선택"],
[4, "직접입력"],
],
DigetIndex: [
[0, "AUTO"],
[1, "사사오입"],
[2, "절사"],
[3, "올림식"],
],
SCheck: [
[0, "비목별"],
[1, "재료"],
[2, "노무"],
[3, "경비"],
[-1, "노무 소계"],
[-2, "재료 소계"],
[-3, "경비 소계"],
[-4, "실적 소계"],
[-5, "합계"],
],
BaseField: [
["", "직접 입력"],
["NC", "직접 노무"],
["GC", "직접 재료"],
["JC", "직접 경비"],
["SC", "직접 실적"],
["TC", "순공사비"],
],
};
function cell(table, index, key, value) {
const { esc } = EstApp,
label = EstModel.labels[key] || key;
const attrs = `data-table="${table}" data-row="${index}" data-field="${key}" aria-label="${esc(label)}"`;
if (enums[key])
return `<select ${attrs}>${enums[key].map(([v, name]) => `<option value="${v}" ${String(v) === String(value ?? (key === "BaseField" ? "" : 0)) ? "selected" : ""}>${esc(name)}</option>`).join("")}</select>`;
if (key === "LineData")
return `<textarea ${attrs} rows="1" spellcheck="false">${esc(EstText.display(value))}</textarea><button class="tiny" data-action="raw-line" data-row="${index}" title="산출근거 편집">…</button>`;
if (value && typeof value === "object") return `<span class="muted">바이너리 자료</span>`;
if (EstModel.numeric.has(key))
return `<input ${attrs} inputmode="decimal" type="number" step="any" value="${value ?? ""}">`;
return `<input ${attrs} type="text" value="${esc(value)}" maxlength="10000">`;
}
function grid(table, list, columns) {
const { esc, number, state } = EstApp;
const abbr =
table === "Wonga" &&
state.project.options.WongaSNameShow &&
typeof EstWongaTools !== "undefined"
? EstWongaTools.abbreviate(state.project.tables.Wonga || [], state.project.options)
: null;
return `<table class="sheet" data-grid="${table}"><thead><tr><th class="row-number">선택</th>${columns.map((key) => `<th class="col-${key}">${esc((table === "Wonga" && typeof EstJungSang !== "undefined" && EstJungSang.label(state.project, key)) || (typeof EstSources !== "undefined" && EstSources.label(state.project.options, table, key)) || EstModel.labels[key] || key)}</th>`).join("")}</tr></thead><tbody>${list.map(({ row, index }) => `<tr data-index="${index}" class="${state.selection.has(index) ? "selected " : ""}${Number(row.Index) > 0 ? "heading " : ""}${Number(row.Level) > 0 ? "level " : ""}${row.Error ? "error-row" : ""}"><th class="row-number"><label><input type="checkbox" data-select="${index}" ${state.selection.has(index) ? "checked" : ""}>${index + 1}</label></th>${columns.map((key) => `<td class="col-${key}"${key === "Name" && Number(row.LeftSpace) > 0 ? ` style="padding-left:${Number(row.LeftSpace) * 6}px"` : ""}>${abbr && key === "VSusic" ? `<span title="산출근거 약어 표시 중(편집 잠김)">${esc(abbr[index])}</span>` : cell(table, index, key, row[key])}</td>`).join("")}</tr>`).join("")}</tbody></table>`;
}
function render(state) {
const { project, view } = state,
{ byId, esc, number } = EstApp;
if (project.tables[view]) EstApp.visibleRows();
const grouped = ["HeadMainDat", "CostMainDat", "MachMainDat"].includes(view);
byId("group-pane").hidden = !grouped;
if (grouped) {
const records = EstNative.groups(project.tables[view] || []);
byId("group-list").innerHTML =
[...records]
.map(
([code, group]) =>
`<button data-group="${esc(code)}" class="${state.group === code ? "active" : ""}"><b>${esc(group.rows[0].Name || EstText.clean(group.rows[0].LineData))}</b><small>${esc(code)}</small><span>${number(group.rows[0].TC)}</span></button>`,
)
.join("") || '<p class="muted">자료가 없습니다. 묶음 추가를 누르세요.</p>';
}
byId("search").value = state.query;
byId("business-search").value = state.query;
byId("business-search").hidden = !["progress", "escalation", "change"].includes(view);
byId("standard-tools").hidden = !project.tables[view];
byId("add-group").hidden = !grouped;
const haljungBtn = byId("haljung-calc-btn");
if (haljungBtn) haljungBtn.hidden = view !== "HeadMainDat";
const vatBtn = byId("vat-calc-btn");
if (vatBtn) vatBtn.hidden = view !== "StuffcDat";
const sourcesBtn = byId("sources-btn");
if (sourcesBtn) sourcesBtn.hidden = !["StuffcDat", "LaborcDat"].includes(view);
const unitCalcBtn = byId("unit-calc-btn");
if (unitCalcBtn) unitCalcBtn.hidden = view !== "HeadMainDat";
byId("move-estimate-up").hidden = ![
"EstMainDat",
"HeadMainDat",
"CostMainDat",
"MachMainDat",
].includes(view);
byId("move-estimate-down").hidden = ![
"EstMainDat",
"HeadMainDat",
"CostMainDat",
"MachMainDat",
].includes(view);
if (project.tables[view]) {
const all = EstApp.visibleRows(),
start = state.page * 100,
list = all.slice(start, start + 100),
columns =
view === "Wonga" && typeof EstJungSang !== "undefined"
? EstJungSang.columns(project, EstModel.columns(view))
: typeof EstSources !== "undefined"
? EstSources.columns(project.options, view, EstModel.columns(view))
: EstModel.columns(view);
byId("work-content").innerHTML = grid(view, list, columns);
byId("paging").hidden = false;
byId("page-info").textContent =
`${all.length ? start + 1 : 0}–${Math.min(start + 100, all.length)} / ${all.length}행`;
byId("previous-page").disabled = state.page === 0;
byId("next-page").disabled = start + 100 >= all.length;
} else {
byId("paging").hidden = true;
EstExtra.render(state);
}
const chosen = [...state.selection][0],
row = project.tables[view]?.[chosen];
byId("selected-info").textContent = row
? `${chosen + 1}행 · ${row.Code || ""} ${row.Name || EstText.clean(row.LineData)}`
: "행 왼쪽을 선택한 뒤 복사·삭제·레벨 지정 등을 사용할 수 있습니다.";
}
return { render, grid, cell, enums };
})();