Merge remote-tracking branch 'origin/main_laptop_1' into sub_desktop_1
This commit is contained in:
@@ -21,13 +21,25 @@
|
||||
background: var(--color-mist-violet);
|
||||
}
|
||||
|
||||
/* 이름 칸(45-7) — 칸은 표 칸 그대로(flex 면 칸 선이 끊김) · 코드 · 이름 · 설명은 글마다 한 줄 말줄임(전체 = title) */
|
||||
.m02-labrow__name {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
min-width: 12rem;
|
||||
}
|
||||
|
||||
.m02-labrow__name > * {
|
||||
display: block;
|
||||
max-width: 20rem;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.m02-labrow th,
|
||||
.m02-labrow__code,
|
||||
.m02-labrow__spec {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.m02-labrow__key,
|
||||
.m02-labrow__note,
|
||||
.m02-labrow__muted {
|
||||
@@ -129,9 +141,9 @@
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
/* 총합계 줄 전체 합계 칸(44-6) — 테두리 · 색 */
|
||||
/* 총합계 줄 전체 합계 칸(44-6) — 테두리 · 색 · 테두리는 안쪽 그림자(칸 선 굵기 안 바꿈 · 45-7) */
|
||||
.m02-labrow__sum .m02-labrow__total {
|
||||
border: 2px solid var(--color-primary);
|
||||
box-shadow: inset 0 0 0 2px var(--color-primary);
|
||||
background: var(--color-mist-violet);
|
||||
color: var(--color-primary);
|
||||
}
|
||||
@@ -232,6 +244,10 @@
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.m02-labrow .m02-labrow__name > * {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.m02-labrow .m02-labrow__no,
|
||||
.m02-labrow .m02-labrow__unit:not([data-label]),
|
||||
.m02-labrow .m02-labrow__code,
|
||||
|
||||
@@ -135,6 +135,12 @@ function moneyCell(
|
||||
});
|
||||
}
|
||||
|
||||
/** 이름 칸 글마다 title = 전체 글(한 줄 말줄임 · 45-7) */
|
||||
const titled = (td: HTMLElement): HTMLElement => {
|
||||
for (const c of td.children) c.setAttribute("title", c.textContent ?? "");
|
||||
return td;
|
||||
};
|
||||
|
||||
const table = (heads: string[], rows: HTMLElement[], foot: HTMLElement[]): HTMLElement =>
|
||||
el("div", {
|
||||
className: "ui-general-block__table-wrap",
|
||||
@@ -240,30 +246,32 @@ export function logicTable(data: LogicTableData, on?: RowHandlers): HTMLElement
|
||||
attrs: { "data-labor-logic": row.로직 },
|
||||
children: [
|
||||
el("td", { className: "m02-labrow__no", text: String(i + 1) }),
|
||||
el("td", {
|
||||
className: "m02-labrow__name",
|
||||
children: [
|
||||
el("span", { className: "m02-labrow__key", text: row.로직 }),
|
||||
el("strong", { text: logic?.이름 ?? row.로직 }),
|
||||
...(values.empty
|
||||
? [
|
||||
el("small", {
|
||||
className: "m02-labrow__empty",
|
||||
text: tc("Labor_Empty").replace("{n}", String(values.empty)),
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
...(row.메모 ? [el("small", { className: "m02-labrow__note", text: row.메모 })] : []),
|
||||
...(why
|
||||
? [
|
||||
el("small", {
|
||||
className: "m02-labrow__empty",
|
||||
text: `${tc("Labor_Calc_Fail")}: ${why}`,
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
],
|
||||
}),
|
||||
titled(
|
||||
el("td", {
|
||||
className: "m02-labrow__name",
|
||||
children: [
|
||||
el("span", { className: "m02-labrow__key", text: row.로직 }),
|
||||
el("strong", { text: logic?.이름 ?? row.로직 }),
|
||||
...(values.empty
|
||||
? [
|
||||
el("small", {
|
||||
className: "m02-labrow__empty",
|
||||
text: tc("Labor_Empty").replace("{n}", String(values.empty)),
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
...(row.메모 ? [el("small", { className: "m02-labrow__note", text: row.메모 })] : []),
|
||||
...(why
|
||||
? [
|
||||
el("small", {
|
||||
className: "m02-labrow__empty",
|
||||
text: `${tc("Labor_Calc_Fail")}: ${why}`,
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
],
|
||||
}),
|
||||
),
|
||||
aliasCell(row.별칭, on?.alias ? (v) => on.alias?.(i, v) : null),
|
||||
qtyCell(line, data.cells, on?.qty ? () => on.qty?.(i) : null),
|
||||
el("td", { className: "m02-labrow__unit", text: unit }),
|
||||
@@ -382,16 +390,22 @@ export function matTable(data: MatTableData, on?: Omit<RowHandlers, "move">): HT
|
||||
attrs: { "data-labor-mat": mat.코드 },
|
||||
children: [
|
||||
el("td", { className: "m02-labrow__code", text: mat.코드 }),
|
||||
titled(
|
||||
el("td", {
|
||||
className: "m02-labrow__name",
|
||||
children: [
|
||||
el("strong", { text: mat.이름 ?? "" }),
|
||||
...(line?.까닭
|
||||
? [el("small", { className: "m02-labrow__empty", text: line.까닭 })]
|
||||
: []),
|
||||
],
|
||||
}),
|
||||
),
|
||||
el("td", {
|
||||
className: "m02-labrow__name",
|
||||
children: [
|
||||
el("strong", { text: mat.이름 ?? "" }),
|
||||
...(line?.까닭
|
||||
? [el("small", { className: "m02-labrow__empty", text: line.까닭 })]
|
||||
: []),
|
||||
],
|
||||
className: "m02-labrow__spec",
|
||||
text: mat.규격 ?? "",
|
||||
attrs: { title: mat.규격 ?? "" },
|
||||
}),
|
||||
el("td", { className: "m02-labrow__spec", text: mat.규격 ?? "" }),
|
||||
qtyCell(qtyLine, data.cells, on?.qty ? () => on.qty?.(i) : null),
|
||||
el("td", {
|
||||
className: "m02-labrow__unit",
|
||||
|
||||
@@ -39,3 +39,12 @@
|
||||
## 추가 (10-5 · 원문 그대로)
|
||||
|
||||
다음으로 구조물 조합 분류 테이블과 상세컨테이너사이가 공간이 너무 넣어 그리고 구조물 분류 테이블의 하단에 구분선이 있는것같은데 삭제해줘. 컨테이너의 상단에도 구분선이 있어.
|
||||
|
||||
## 추가 2 (10-5 · 원문 그대로)
|
||||
|
||||
1. 구조물 조합의 ?버튼은 설명같은데 미리보기의 ? 버튼을 미리보기 항목 옆으로 이동하고 설명과 지금처럼 단축키와 기능 설명과 사용법을 작성해줘.
|
||||
2. 구조물 조합의 파일 불러오기 기능은 미리보기에서 보다는 상세 페이지에서 작업할 내용임. 미리보기에서는 항목 삭제
|
||||
3. M01의 단가산출 로직의 항목 상세에서 우측 패널에 대한 구현이 잘못됨. 우측 흐름도의 패널과 원문 패널을 별도로 구성하고 사용자가 두개의 패널을 각각 접었다 펼수 있어야함. 단 동시에 두개의 패널을 볼 경우는 없으며 폭정보는 공유하고 있고 둘다 접힌 상태일 수는 있음.
|
||||
4. 구조물 조합의 단가산출 상세화면에도 원문보기 우측 패널이 있어야함. 우측 패널은 단가산출 로직을 선택할 경우에 원문을 보여주는 기능이며 패널을 접었다 펼수 있어야함.
|
||||
5. 원문 패널 추가에 따라 현재 단가산출 로직 항목을 선택하면 옵션창이 보이나 선택하면 하이라이트를 하고 원문을 보일수 있게 함. 그리고 옵션설정에 대한 조정은 올리기, 내리기, 빼기 버튼의 이름을 위로, 아래로, 삭제로 변경하고 아래로 와 삭제 사이에 신규 버튼(이름 : 옵션)을 추가하여 선택할 수 있게 변경. 버튼 사이간격에 대해 템플릿화하여 적용.
|
||||
6. 구조물 조합의 면적산출 우측패널에 별도의 도면 패널 추가(기능은 4번 요청 확인)
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/* 45-7 — M02 구조물 조합 · 일위대가 표(단가산출 로직 · 자재목록) 이름 한 줄 · 칸 선 이어짐 — 카드 · 상세 두 곳
|
||||
* 시작 화면: M02 마스터 템플릿 · 마스터 층(#/m02-master-template?open=구조물조합&root=master) · 시스템 관리자 ·
|
||||
* 나무에 item1(구조물 조합 · 일위대가 로직 담김)이 있음
|
||||
* 부르는 법: orca eval --expression "$(tr '\n' ' ' < 이 파일)" (async 식 · JSON 글을 돌려줌 · 줄바꿈 있으면 orca 가 끊김)
|
||||
* 하는 일: item1 카드 표를 잼 → 일위대가 카드 [수정]으로 상세를 열어 잼 → item1 을 다시 눌러 카드 화면으로 돌아감(값 안 바꿈)
|
||||
* 기대 수치(카드 · 상세 각각):
|
||||
* - nameLines = 1(이름 칸 · 코드 · 규격 칸 글마다 줄 수 최대) · headLines = 1(머리 칸 글 줄 수 최대)
|
||||
* - spanBad = 0(각 줄 칸 수 = 머리 칸 수 · colspan 셈)
|
||||
* - broken = 0(칸 위·아래가 줄 위·아래와 어긋남 · 한 줄 안 아래 테두리 굵기가 다름 · 칸 사이 틈)
|
||||
* - ellipsis = 이름 글에 말줄임 꼴(text-overflow ellipsis) · titled = 이름 글마다 title
|
||||
* - 카드는 가로 스크롤 그대로(cardScroll = true · 표 폭 > 감싼 칸 폭)
|
||||
*/
|
||||
(async () => {
|
||||
const w = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
const until = async (fn, ms = 8000) => {
|
||||
for (let t = 0; t < ms; t += 150) {
|
||||
const v = fn();
|
||||
if (v) return v;
|
||||
await w(150);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const lines = (e) => {
|
||||
const r = document.createRange();
|
||||
r.selectNodeContents(e);
|
||||
const tops = [...r.getClientRects()].filter((q) => q.width > 0).map((q) => Math.round(q.top));
|
||||
return new Set(tops).size;
|
||||
};
|
||||
const span = (tr) => [...tr.cells].reduce((a, c) => a + (c.colSpan || 1), 0);
|
||||
const measure = (t) => {
|
||||
const head = span(t.tHead.rows[0]);
|
||||
const body = [...t.querySelectorAll("tbody tr, tfoot tr")];
|
||||
const texts = [
|
||||
...t.querySelectorAll(
|
||||
".m02-labrow__name > *, tbody .m02-labrow__code, tbody .m02-labrow__spec",
|
||||
),
|
||||
...t.querySelectorAll(".m02-labrow__name:not(:has(*))"),
|
||||
].filter((e) => e.textContent.trim());
|
||||
const kids = [...t.querySelectorAll(".m02-labrow__name > *")];
|
||||
let broken = 0;
|
||||
const why = [];
|
||||
for (const tr of body) {
|
||||
const R = tr.getBoundingClientRect();
|
||||
const cells = [...tr.cells].filter((c) => c.getClientRects().length);
|
||||
const widths = new Set(cells.map((c) => getComputedStyle(c).borderBottomWidth));
|
||||
if (widths.size > 1) (broken++, why.push(`굵기 ${tr.className} ${[...widths]}`));
|
||||
cells.forEach((c, i) => {
|
||||
const r = c.getBoundingClientRect();
|
||||
if (Math.abs(r.top - R.top) > 1 || Math.abs(r.bottom - R.bottom) > 1)
|
||||
(broken++,
|
||||
why.push(`높이 ${tr.className} ${c.className} ${Math.round(r.bottom - R.bottom)}`));
|
||||
const n = cells[i + 1];
|
||||
if (n && Math.abs(n.getBoundingClientRect().left - r.right) > 1)
|
||||
(broken++, why.push(`틈 ${tr.className} ${c.className}`));
|
||||
});
|
||||
}
|
||||
const wrap = t.parentElement;
|
||||
return {
|
||||
head,
|
||||
rows: body.length,
|
||||
spanBad: body.filter((tr) => span(tr) !== head).length,
|
||||
nameLines: Math.max(0, ...texts.map(lines)),
|
||||
headLines: Math.max(0, ...[...t.tHead.rows[0].cells].map(lines)),
|
||||
broken,
|
||||
why: why.slice(0, 6),
|
||||
ellipsis: kids.every((e) => getComputedStyle(e).textOverflow === "ellipsis"),
|
||||
titled: kids.every((e) => e.title === e.textContent),
|
||||
scroll: Math.round(t.getBoundingClientRect().width) > Math.round(wrap.clientWidth),
|
||||
};
|
||||
};
|
||||
const node = await until(() => document.querySelector('[data-node="i|item1"]'));
|
||||
if (!node) return JSON.stringify({ error: "item1 없음 — 기슭막이 폴더를 펼쳐 둘 것" });
|
||||
node.click();
|
||||
const card = await until(() =>
|
||||
[...document.querySelectorAll(".m02-struct__card")].find((c) =>
|
||||
c.querySelector("table.m02-labrow"),
|
||||
),
|
||||
);
|
||||
if (!card) return JSON.stringify({ error: "일위대가 카드 표 없음" });
|
||||
await w(1500);
|
||||
const out = { card: [...card.querySelectorAll("table.m02-labrow")].map(measure) };
|
||||
out.cardScroll = out.card[0]?.scroll ?? null;
|
||||
const edit = [...card.querySelectorAll(".m02-struct__card-tools button")].find(
|
||||
(b) => b.innerText.trim() === "수정",
|
||||
);
|
||||
if (!edit) return JSON.stringify({ ...out, error: "일위대가 [수정] 없음" });
|
||||
edit.click();
|
||||
await until(() =>
|
||||
[...document.querySelectorAll("table.m02-labrow")].find((t) => !t.closest(".m02-struct__card")),
|
||||
);
|
||||
await w(2000);
|
||||
out.detail = [...document.querySelectorAll("table.m02-labrow")]
|
||||
.filter((t) => !t.closest(".m02-struct__card"))
|
||||
.map(measure);
|
||||
/* 카드 화면으로 돌아감 */
|
||||
document.querySelector('[data-node="i|item1"]')?.click();
|
||||
await w(1000);
|
||||
out.back = !!document.querySelector(".m02-struct__card table.m02-labrow");
|
||||
return JSON.stringify(out);
|
||||
})();
|
||||
Reference in New Issue
Block a user