Merge remote-tracking branch 'origin/main_laptop_1' into sub_laptop_3
This commit is contained in:
@@ -237,7 +237,7 @@ def find(q: str, limit: int = 30) -> list[dict]:
|
||||
for r in _rows():
|
||||
hay = " ".join(str(r.get(k) or "") for k in ("이름", "규격", "별칭", "상세구분", "키"))
|
||||
hay = hay.lower()
|
||||
if all(w in hay for w in words):
|
||||
if all(w in hay for w in words) and not r.get("비활성"): # 끈 기계 뺌(842-2)
|
||||
out.append(_brief(r))
|
||||
if len(out) >= limit:
|
||||
break
|
||||
|
||||
@@ -241,8 +241,10 @@ def rows(
|
||||
hits = [r for r in hits if sub in {r.get(s) for s in cm.MERGED.values()}]
|
||||
if detail: # 인력 상세구분 · 기계 상세구분(기종)
|
||||
hits = [r for r in hits if r.get("상세구분") == detail]
|
||||
if state: # 인력 상태
|
||||
hits = [r for r in hits if r.get("상태") == state]
|
||||
if state: # 인력 상태 · 기계 「켜짐」 = 비활성 뺌(842-2)
|
||||
hits = [
|
||||
r for r in hits if (not r.get(cm.OFF) if state == "켜짐" else r.get("상태") == state)
|
||||
]
|
||||
if unlinked: # 품셈재료 — 아직 못 이은 줄
|
||||
hits = [r for r in hits if not r.get("연결")]
|
||||
page, size = max(page, 1), min(max(size, 1), 500)
|
||||
@@ -463,7 +465,7 @@ def elements(group: str, q: str, limit: int) -> dict:
|
||||
if data.get("그룹") != group:
|
||||
continue
|
||||
for row in data.get(items_key(data)) or []:
|
||||
if _hit(row, q):
|
||||
if _hit(row, q) and not row.get(cm.OFF): # 끈 기계 뺌(842-2)
|
||||
more = {"별칭": row.get("별칭") or ""} if group == "로직" else {} # 208-1
|
||||
hits.append({**_brief(str(row.get("키")), row), "file": name, **more})
|
||||
return {"total": len(hits), "items": hits[: min(max(limit, 1), 200)]}
|
||||
|
||||
@@ -70,7 +70,8 @@ export function openPickTable(opt: PickTableOptions): void {
|
||||
const mine = ++seq;
|
||||
try {
|
||||
const q = search.value.trim();
|
||||
const got = await fetchRows(FILES[opt.kind], page, size, q);
|
||||
const on = opt.kind === "기계" ? "켜짐" : ""; // 끈 기계 뺌(842-2)
|
||||
const got = await fetchRows(FILES[opt.kind], page, size, q, false, "", "", on);
|
||||
if (mine !== seq) return; // 최신 응답만
|
||||
if (!got.total && fallback) {
|
||||
const next = [...(q.includes(" ") ? [q.split(/\s+/)[0]] : []), ...(opt.alt ?? [])].find(
|
||||
|
||||
@@ -66,3 +66,17 @@ table.m01-master__grid.m01-machine__grid {
|
||||
max-height: 240px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* 「사용」 열(842-2) — 스위치 · 끈 줄은 흐림 */
|
||||
.m01-machine__grid th.m01-machine__use {
|
||||
width: 64px;
|
||||
}
|
||||
|
||||
.m01-machine__grid td.m01-machine__use {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.m01-machine__row.is-off td:not(.m01-machine__use) {
|
||||
color: var(--color-text-muted);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
@@ -3,15 +3,18 @@
|
||||
* M01 기계 목록(PLAN 821-2 · 요구 790-2) — 표는 목록용 열만(이름 · 규격 · 구분 · 가격 · 손료계수 ·
|
||||
* 주연료 · 인력 줄 요약 · 시간당 경비(서버 값) · 별칭 · 비고) · 줄을 누르면 상세 페이지 · [새 기계] = 양식.
|
||||
* 단위 · 출처 열 없음 · 고친 것 · 새 줄 · 지울 줄은 초안(노랑 · 새 · 지움 표시) — 저장은 페이지 [저장].
|
||||
* 「사용」 열(842-2) = 스위치 · 끄면 줄 맨 위 칸 `비활성: true`(초안 → [저장]) · 끈 줄은 흐림 ·
|
||||
* 머리 「비활성 같이 보기」 끄면 서버가 끈 줄을 뺌(`rows` state 「켜짐」).
|
||||
* ========================================================================== */
|
||||
|
||||
import { createButton, el, showToast } from "@ui/ui_template_elements";
|
||||
import { t as L } from "@ui/ui_template_locale";
|
||||
import { createEmpty } from "@ui/ui_template_empty";
|
||||
import { createToggle } from "@ui/ui_template_toggle";
|
||||
import { guessRows, pageKeepFirst, watchFit } from "@ui/ui_template_pager";
|
||||
import { code, crewOf } from "../common_util/common_util_machine_crew";
|
||||
import { fetchRows, type Row, type RowsPage } from "./M01_MasterData_Api_Fetch";
|
||||
import { onDraftChange, peek, same } from "./M01_MasterData_Draft";
|
||||
import { editRow, onDraftChange, peek, same } from "./M01_MasterData_Draft";
|
||||
import { fetchMachineHourly } from "./M01_MasterData_Machine_Api";
|
||||
import { buildPager } from "./M01_MasterData_UI_Cells";
|
||||
import { saveView, type Pick } from "./M01_MasterData_UI_Side";
|
||||
@@ -41,6 +44,8 @@ const COLS: [string, (r: Row) => string][] = [
|
||||
],
|
||||
];
|
||||
const val = (r: Row): Record<string, unknown> => (r["값"] ?? {}) as Record<string, unknown>;
|
||||
const OFF = "비활성"; // 842-2 기계 줄 맨 위 칸 — true 만 · 켜짐 = 칸 없음
|
||||
let showOff = true; // 「비활성 같이 보기」(페이지 안에서 기억)
|
||||
|
||||
/** 돌려받은 함수 = 걷기. `open(target)` = 상세(키 · 새 줄 `add:<차례>` · 새 기계 `new`). */
|
||||
export function renderMachines(
|
||||
@@ -56,9 +61,31 @@ export function renderMachines(
|
||||
const hourly = new Map<string, string>();
|
||||
|
||||
const hourText = (key: string): string => hourly.get(key) ?? "…";
|
||||
/** 「사용」 칸 — 스위치(새 줄은 빈 칸) · 바꾸면 초안 */
|
||||
const useCell = (row: Row, cur: Row, key: string): HTMLElement => {
|
||||
const td = el("td", { className: "m01-machine__use" });
|
||||
if (!key || !data) return td;
|
||||
const version = data.version;
|
||||
const sw = createToggle({
|
||||
label: "",
|
||||
size: 20,
|
||||
checked: !cur[OFF],
|
||||
onChange: (on) => {
|
||||
const next: Row = { ...cur };
|
||||
if (on) delete next[OFF];
|
||||
else next[OFF] = true;
|
||||
editRow(file, version, key, row, next);
|
||||
},
|
||||
});
|
||||
sw.root.setAttribute("aria-label", L("M01_MachineUse"));
|
||||
sw.root.addEventListener("click", (e) => e.stopPropagation());
|
||||
td.classList.toggle("is-changed", !!cur[OFF] !== !!row[OFF]);
|
||||
td.append(sw.root);
|
||||
return td;
|
||||
};
|
||||
const line = (row: Row, cur: Row, cls: string, target: string, key = ""): HTMLElement => {
|
||||
const tr = el("tr", {
|
||||
className: `m01-machine__row ${cls}`.trim(),
|
||||
className: `m01-machine__row ${cls} ${cur[OFF] ? "is-off" : ""}`.trim(),
|
||||
attrs: { "data-key": key || target },
|
||||
children: [
|
||||
...COLS.map(([, get]) => {
|
||||
@@ -74,6 +101,7 @@ export function renderMachines(
|
||||
}),
|
||||
el("td", { text: String(cur["별칭"] ?? ""), attrs: { title: String(cur["별칭"] ?? "") } }),
|
||||
el("td", { text: String(cur["비고"] ?? ""), attrs: { title: String(cur["비고"] ?? "") } }),
|
||||
useCell(row, cur, key),
|
||||
],
|
||||
});
|
||||
tr.addEventListener("click", () => open(target));
|
||||
@@ -94,12 +122,21 @@ export function renderMachines(
|
||||
}
|
||||
const add = createButton({ label: L("M01_MachineNew"), variant: "ghost", iconStart: "plus" });
|
||||
add.addEventListener("click", () => open("new"));
|
||||
const offSwitch = createToggle({
|
||||
label: L("M01_MachineShowOff"),
|
||||
checked: showOff,
|
||||
onChange: (on) => {
|
||||
showOff = on;
|
||||
page = 1;
|
||||
void load();
|
||||
},
|
||||
});
|
||||
const empty =
|
||||
d.rows.length || draft?.adds.length
|
||||
? []
|
||||
: [createEmpty({ text: L("M01_NoRows"), small: true })];
|
||||
host.replaceChildren(
|
||||
el("div", { className: "ui-toolbar m01-master__bar", children: [add] }),
|
||||
el("div", { className: "ui-toolbar m01-master__bar", children: [add, offSwitch.root] }),
|
||||
el("div", {
|
||||
className: "ui-table-wrap m01-master__grid-wrap m01-machine__wrap",
|
||||
children: [
|
||||
@@ -114,6 +151,7 @@ export function renderMachines(
|
||||
el("th", { text: `${L("M01_MachineHourly")}(원)` }),
|
||||
el("th", { text: "별칭" }),
|
||||
el("th", { text: "비고" }),
|
||||
el("th", { className: "m01-machine__use", text: L("M01_MachineUse") }),
|
||||
],
|
||||
}),
|
||||
],
|
||||
@@ -155,7 +193,8 @@ export function renderMachines(
|
||||
const load = async (): Promise<void> => {
|
||||
const mine = ++ticket;
|
||||
try {
|
||||
const got = await fetchRows(file, page, size, q, false, pick.sub, pick.detail, pick.state);
|
||||
const state = showOff ? pick.state : "켜짐";
|
||||
const got = await fetchRows(file, page, size, q, false, pick.sub, pick.detail, state);
|
||||
if (mine !== ticket) return;
|
||||
data = got;
|
||||
saveView(pick.group, { page: data.page });
|
||||
|
||||
Reference in New Issue
Block a user