feat(est-test): 표지·갑지 상세편집, 산출 줄 글자모양, 수량산출서 인쇄, 엑셀형 셀 테두리·음영·수량붙여넣기
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,9 @@ const EstQuantityTable = (() => {
|
||||
p.align && `text-align:${p.align}`,
|
||||
p.indent && `padding-left:${p.indent * 8}px`,
|
||||
row.title && "font-weight:bold;font-size:20px;color:#800000",
|
||||
p.bold && "font-weight:bold",
|
||||
p.size && `font-size:${p.size}px`,
|
||||
p.color && `color:${p.color}`,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(";");
|
||||
@@ -155,6 +158,7 @@ const EstQuantityTable = (() => {
|
||||
sheet.tableEdited = true;
|
||||
}, false);
|
||||
} else if (name === "qt-mul-load" || name === "qt-mul-take") mulLoad(name, state, node);
|
||||
else if (name === "qt-print") print(state);
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
@@ -175,7 +179,23 @@ const EstQuantityTable = (() => {
|
||||
throw Error("정렬은 left·center·right 입니다.");
|
||||
const indent = Number(prompt("들여쓰기(칸)", String(sheet.rows[index].para?.indent ?? 0)));
|
||||
if (!(indent >= 0 && indent <= 40)) throw Error("들여쓰기는 0~40 칸입니다.");
|
||||
change(() => (sheet.rows[index].para = { align, indent }));
|
||||
// 글자모양(mnuFormatFont): 크기·굵게·색
|
||||
const size =
|
||||
Number(prompt("글자 크기(px, 0 = 기본)", String(sheet.rows[index].para?.size ?? 0))) || 0,
|
||||
bold = confirm("굵게 할까요?"),
|
||||
color =
|
||||
prompt("글자색(#RRGGBB, 비우면 기본)", sheet.rows[index].para?.color || "")?.trim() || "";
|
||||
if (color && !/^#[0-9a-f]{6}$/i.test(color)) throw Error("글자색은 #RRGGBB 꼴입니다.");
|
||||
change(
|
||||
() =>
|
||||
(sheet.rows[index].para = {
|
||||
align,
|
||||
indent,
|
||||
...(size && { size }),
|
||||
...(bold && { bold }),
|
||||
...(color && { color }),
|
||||
}),
|
||||
);
|
||||
} else if (name === "qt-image") {
|
||||
const picker = document.createElement("input");
|
||||
picker.type = "file";
|
||||
@@ -233,6 +253,36 @@ const EstQuantityTable = (() => {
|
||||
state.notice = `「${src.Name}」 산출서를 불러왔습니다.`;
|
||||
}
|
||||
|
||||
// 수량산출서 인쇄(btnPrint → TfrmMulPrintRange): 현재 산출서 또는 모두(산출서마다 간지 고르기), 산출 줄·표 그대로
|
||||
function print(state) {
|
||||
const sheets = state.project.quantitySheets || [];
|
||||
if (!sheets.length) throw Error("수량산출서가 없습니다.");
|
||||
const all = confirm("모든 수량산출서를 인쇄할까요? (취소 = 현재 산출서만)"),
|
||||
gangi = all && confirm("산출서마다 간지를 넣을까요?"),
|
||||
list = all ? sheets : [sheetOf(state)].filter(Boolean),
|
||||
{ esc } = EstApp;
|
||||
const body = list
|
||||
.map((sheet) => {
|
||||
const rows = sheet.rows
|
||||
.map((r) =>
|
||||
r.image
|
||||
? `<img src="${esc(r.image)}" style="max-width:100%">`
|
||||
: r.table
|
||||
? `<table>${r.table.map((tr) => `<tr>${tr.map((c) => (c.vmerge ? "" : `<td${c.vtop ? ` rowspan="${c.vtop}"` : ""}>${esc(c.text)}</td>`)).join("")}</tr>`).join("")}</table>`
|
||||
: `<div style="white-space:pre-wrap;${paraStyle(r)}">${esc(EstText.clean(r.LineData || ""))}</div>`,
|
||||
)
|
||||
.join("");
|
||||
return `${gangi ? `<section class="gangi"><div>${esc(sheet.Name)}</div></section>` : ""}<section class="sheet"><h2>${esc(sheet.Name)} ${esc(sheet.Size || "")}</h2>${rows}</section>`;
|
||||
})
|
||||
.join("");
|
||||
const win = open("", "_blank");
|
||||
if (!win) throw Error("새 창을 열 수 없습니다. 팝업 차단을 확인하세요.");
|
||||
win.document.write(
|
||||
`<!doctype html><meta charset="utf-8"><title>수량산출서</title><style>body{font:10pt "Malgun Gothic",sans-serif}table{border-collapse:collapse}td{border:1px solid #777;padding:2px 4px}.sheet{break-after:page}.gangi{break-after:page;height:250mm;display:flex;align-items:center;justify-content:center;font-size:28pt;font-weight:bold}</style>${body}<script>print()<\/script>`,
|
||||
);
|
||||
win.document.close();
|
||||
}
|
||||
|
||||
function install() {
|
||||
document.addEventListener("click", (event) => {
|
||||
const td = event.target.closest("[data-qt]");
|
||||
|
||||
Reference in New Issue
Block a user