Files

107 lines
4.5 KiB
Plaintext

@{
ViewData["Title"] = "System Admin";
}
<div class="container mt-4">
<div class="card border-danger shadow">
<div class="card-header bg-danger text-white">
<h4 class="mb-0">🛠️ System Engineering - Discovery Mode</h4>
</div>
<div class="card-body">
<section class="mb-5">
<h5>1. 하니웰 Asset 모델 탐사 (Crawler)</h5>
<p class="text-muted">서버의 모든 노드를 훑어 <code>Honeywell_FullMap.csv</code> 파일을 생성합니다. <br>
<small class="text-danger">* 주의: 노드 수가 많을 경우 하니웰 서버와 네트워크에 부하가 발생할 수 있습니다.</small></p>
<button id="btnRunCrawler" class="btn btn-danger btn-lg" onclick="runCrawler()">
<span id="spinnerCrawler" class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
🚀 탐사 및 CSV 생성 시작
</button>
</section>
<hr>
<section class="mt-4">
<h5>2. DB 동기화 (CSV to Database)</h5>
<p class="text-muted">생성된 CSV 파일을 읽어 PostgreSQL <code>raw_node_map</code> 테이블에 일괄 저장합니다.</p>
<button id="btnImportCsv" class="btn btn-warning btn-lg" onclick="importCsvToDb()">
<span id="spinnerImport" class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
📥 CSV 데이터를 DB로 가져오기
</button>
</section>
</div>
<div class="card-footer bg-light">
<div id="statusMessage" class="fw-bold"></div>
</div>
</div>
</div>
@section Scripts {
<script>
async function runCrawler() {
const btn = document.getElementById('btnRunCrawler');
const spinner = document.getElementById('spinnerCrawler');
const status = document.getElementById('statusMessage');
if (!confirm("전체 노드 탐사를 시작하시겠습니까? (ns=1;s=$assetmodel 기준)")) return;
try {
// 버튼 비활성화 및 로딩 시작
btn.disabled = true;
spinner.classList.remove('d-none');
status.innerText = "⏳ 하니웰 서버 탐사 중... 잠시만 기다려 주세요.";
status.className = "text-primary fw-bold";
const response = await fetch('/Engineering/RunCrawler', { method: 'POST' });
const result = await response.json();
if (response.ok) {
alert("✅ 성공: " + result.message);
status.innerText = "✅ 탐사 완료: " + result.message;
status.className = "text-success fw-bold";
} else {
throw new Error(result.message || "탐사 실패");
}
} catch (error) {
alert("❌ 에러 발생: " + error.message);
status.innerText = "❌ 오류: " + error.message;
status.className = "text-danger fw-bold";
} finally {
btn.disabled = false;
spinner.classList.add('d-none');
}
}
async function importCsvToDb() {
const btn = document.getElementById('btnImportCsv');
const spinner = document.getElementById('spinnerImport');
const status = document.getElementById('statusMessage');
if (!confirm("CSV 데이터를 DB에 덮어씌우시겠습니까? (기존 데이터는 삭제됩니다.)")) return;
try {
btn.disabled = true;
spinner.classList.remove('d-none');
status.innerText = "⏳ DB 동기화 작업 중...";
const response = await fetch('/Engineering/ImportCsv', { method: 'POST' });
const result = await response.json();
if (response.ok) {
alert("✅ 성공: " + result.message);
status.innerText = "✅ DB 동기화 완료!";
status.className = "text-success fw-bold";
} else {
throw new Error(result.message || "동기화 실패");
}
} catch (error) {
alert("❌ 에러 발생: " + error.message);
status.innerText = "❌ 오류: " + error.message;
status.className = "text-danger fw-bold";
} finally {
btn.disabled = false;
spinner.classList.add('d-none');
}
}
</script>
}