217 lines
8.0 KiB
JavaScript
217 lines
8.0 KiB
JavaScript
// 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("기기 삭제에 실패했습니다.");
|
|
}
|
|
}
|