- 원본 통합 검색처럼 자료 7종을 검색어로 찾고 하위 연결째 현재 공사로 가져옴 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
70 lines
2.3 KiB
JavaScript
70 lines
2.3 KiB
JavaScript
// 원본 통합 검색(TFRMMULTISERCH: 일위대가·단가산출·기계경비·견적·실적·자재·노임 고르기, 검색어, 검색위치) —
|
|
// 웹은 이 앱에 저장된 작업(data/*.json)을 검색 위치로 쓴다. 검색어 낱말이 모두 코드·품명·규격에 들어 있으면 찾음.
|
|
const fs = require("node:fs");
|
|
const path = require("node:path");
|
|
|
|
const sources = {
|
|
103: ["HeadTitleDat", "일위대가"],
|
|
104: ["CostTitleDat", "단가산출"],
|
|
105: ["MachTitleDat", "기계경비"],
|
|
101: ["EstiMateDat", "견적단가"],
|
|
21: ["SilJukDat", "실적단가"],
|
|
5: ["StuffcDat", "자재단가"],
|
|
6: ["LaborcDat", "노임단가"],
|
|
};
|
|
const LIMIT = 300;
|
|
const fold = (value) =>
|
|
String(value ?? "")
|
|
.normalize("NFKC")
|
|
.toLowerCase()
|
|
.replace(/\s+/g, "");
|
|
|
|
function search(directory, query, kinds, exclude = "") {
|
|
const words = String(query ?? "")
|
|
.split(/\s+/)
|
|
.map(fold)
|
|
.filter(Boolean);
|
|
if (!words.length) throw Error("검색어를 입력하세요.");
|
|
const wanted = (kinds?.length ? kinds : Object.keys(sources))
|
|
.map(Number)
|
|
.filter((k) => sources[k]);
|
|
if (!wanted.length) throw Error("검색할 자료를 하나 이상 고르세요.");
|
|
if (!fs.existsSync(directory)) return { hits: [], total: 0 };
|
|
const hits = [];
|
|
let total = 0;
|
|
for (const name of fs.readdirSync(directory).filter((n) => /^[a-f0-9]{24}\.json$/.test(n))) {
|
|
const id = name.slice(0, -5);
|
|
if (id === exclude) continue;
|
|
let project;
|
|
try {
|
|
project = JSON.parse(fs.readFileSync(path.join(directory, name), "utf8"));
|
|
} catch {
|
|
continue;
|
|
}
|
|
for (const kind of wanted) {
|
|
const [table, label] = sources[kind];
|
|
for (const row of project.tables?.[table] || []) {
|
|
if (!row?.Code) continue;
|
|
const text = fold(`${row.Code} ${row.Name} ${row.Size}`);
|
|
if (!words.every((w) => text.includes(w))) continue;
|
|
total++;
|
|
if (hits.length < LIMIT)
|
|
hits.push({
|
|
id,
|
|
project: project.name || id,
|
|
kind,
|
|
label,
|
|
Code: row.Code,
|
|
Name: row.Name ?? "",
|
|
Size: row.Size ?? "",
|
|
Unite: row.Unite ?? "",
|
|
price: Number(row.TC) || 0,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
return { hits, total };
|
|
}
|
|
|
|
module.exports = { search, sources };
|