초기화

This commit is contained in:
2026-07-15 18:37:19 +09:00
commit 94abc5461d
1268 changed files with 380198 additions and 0 deletions
+216
View File
@@ -0,0 +1,216 @@
// ChemiFactory MES - Equipment Device Master Management Logic
const API_EQUIPMENT = "/api/equipment";
let allDevices = [];
document.addEventListener("DOMContentLoaded", () => {
initEvents();
loadDevices();
});
async function loadDevices() {
try {
const res = await fetch(API_EQUIPMENT);
if (!res.ok) throw new Error("Failed to fetch equipment devices");
allDevices = await res.json();
renderDevices(allDevices);
} catch (err) {
console.error(err);
document.getElementById("device-grid-container").innerHTML = `
<div style="grid-column: 1 / -1; padding: 40px; text-align: center; color: var(--accent-red);">
서버로부터 설비 정보를 조회하지 못했습니다. (DB 또는 네트워크 점검 필요)
</div>
`;
}
}
function renderDevices(devices) {
const container = document.getElementById("device-grid-container");
container.innerHTML = "";
if (devices.length === 0) {
container.innerHTML = `
<div style="grid-column: 1 / -1; padding: 40px; text-align: center; color: var(--text-muted);">
등록된 설비 기기가 없습니다.
</div>
`;
return;
}
devices.forEach(d => {
const card = document.createElement("div");
card.className = "device-card";
card.addEventListener("click", () => openEditModal(d));
// 상태 한글 변환
let statusText = "가동 가능";
let statusBadgeClass = "device-badge";
if (d.status === "maintenance") {
statusText = "점검 중";
} else if (d.status === "broken") {
statusText = "고장/정지";
}
card.innerHTML = `
<div>
<div class="device-card-header">
<span class="device-name">${d.name}</span>
<span class="${statusBadgeClass}">${statusText}</span>
</div>
<div style="font-size: 12px; color: var(--text-muted); margin-top:-8px; margin-bottom: 12px;">
IP: ${d.ip_address} | Prefix: ${d.line_prefix}
</div>
</div>
<div class="device-details">
<div class="detail-item">
<span class="detail-label">보빈 수</span>
<span class="detail-value">${d.yarn_bobbin_count}개</span>
</div>
<div class="detail-item">
<span class="detail-label">건조기 타입</span>
<span class="detail-value">${d.dryer_type}</span>
</div>
<div class="detail-item">
<span class="detail-label">소비 전력</span>
<span class="detail-value">${d.power_consumption} kW</span>
</div>
<div class="detail-item">
<span class="detail-label">최대 속도</span>
<span class="detail-value">Cut: ${d.max_cutting_speed} / Feed: ${d.max_feed_speed}</span>
</div>
</div>
`;
container.appendChild(card);
});
}
function initEvents() {
const modal = document.getElementById("device-modal");
const closeBtns = modal.querySelectorAll(".close-btn, .close-modal-btn");
const addBtn = document.getElementById("btn-add-device");
const form = document.getElementById("device-form");
const deleteBtn = document.getElementById("btn-delete-device");
const searchInput = document.getElementById("search-input");
// 모달 닫기
closeBtns.forEach(btn => {
btn.addEventListener("click", () => {
modal.style.display = "none";
});
});
// 신규 추가 오픈
addBtn.addEventListener("click", () => {
form.reset();
document.getElementById("device-id").value = "";
document.getElementById("modal-title").innerText = "신규 기기 등록";
deleteBtn.style.display = "none";
document.getElementById("delete-spacer").style.display = "none";
modal.style.display = "flex";
});
// 검색 필터링
searchInput.addEventListener("input", (e) => {
const query = e.target.value.toLowerCase().trim();
const filtered = allDevices.filter(d =>
d.name.toLowerCase().includes(query) ||
(d.dryer_type && d.dryer_type.toLowerCase().includes(query)) ||
(d.ip_address && d.ip_address.includes(query))
);
renderDevices(filtered);
});
// 폼 저장 제출
form.addEventListener("submit", saveDevice);
// 삭제 실행
deleteBtn.addEventListener("click", deleteDevice);
}
function openEditModal(device) {
const modal = document.getElementById("device-modal");
const deleteBtn = document.getElementById("btn-delete-device");
document.getElementById("device-id").value = device.id;
document.getElementById("device-name").value = device.name;
document.getElementById("device-bobbins").value = device.yarn_bobbin_count;
document.getElementById("device-dryer").value = device.dryer_type;
document.getElementById("device-power").value = device.power_consumption;
document.getElementById("device-max-cut").value = device.max_cutting_speed;
document.getElementById("device-max-feed").value = device.max_feed_speed;
document.getElementById("device-ip").value = device.ip_address;
document.getElementById("device-prefix").value = device.line_prefix;
document.getElementById("device-status").value = device.status;
document.getElementById("modal-title").innerText = "설비 정보 편집";
// 삭제 버튼 노출
deleteBtn.style.display = "block";
document.getElementById("delete-spacer").style.display = "block";
modal.style.display = "flex";
}
async function saveDevice(e) {
e.preventDefault();
const id = document.getElementById("device-id").value;
const payload = {
name: document.getElementById("device-name").value,
yarn_bobbin_count: parseInt(document.getElementById("device-bobbins").value),
dryer_type: document.getElementById("device-dryer").value,
power_consumption: parseFloat(document.getElementById("device-power").value),
max_cutting_speed: parseFloat(document.getElementById("device-max-cut").value),
max_feed_speed: parseFloat(document.getElementById("device-max-feed").value),
ip_address: document.getElementById("device-ip").value,
line_prefix: document.getElementById("device-prefix").value,
status: document.getElementById("device-status").value
};
try {
let res;
if (id) {
// 수정
res = await fetch(`${API_EQUIPMENT}/${id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload)
});
} else {
// 추가
res = await fetch(API_EQUIPMENT, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload)
});
}
if (!res.ok) throw new Error("Failed to save device data");
document.getElementById("device-modal").style.display = "none";
loadDevices();
} catch (err) {
console.error(err);
alert("기기 저장 중 요류가 발생했습니다.");
}
}
async function deleteDevice() {
const id = document.getElementById("device-id").value;
if (!id) return;
if (!confirm("정말로 해당 설비를 삭제하시겠습니까? 관련 데이터가 소실될 수 있습니다.")) {
return;
}
try {
const res = await fetch(`${API_EQUIPMENT}/${id}`, {
method: "DELETE"
});
if (!res.ok) throw new Error("Failed to delete device");
document.getElementById("device-modal").style.display = "none";
loadDevices();
} catch (err) {
console.error(err);
alert("기기 삭제에 실패했습니다.");
}
}