초기화
This commit is contained in:
@@ -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("기기 삭제에 실패했습니다.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user