feat: QR 자산 스캔 점검, 모바일 웹뷰 및 관리자 승인 시스템 구현 (DB 기반 맵 좌표 저장 단일화 포함)
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
} from './ModalUtils';
|
||||
import { CORP_LIST, LOCATION_DATA, CATEGORY_TYPE_MAP, HW_STATUS_LIST, ORG_LIST, IMAGE_LOCATIONS, TYPE_PREFIX_MAP } from './SharedData';
|
||||
import { BaseModal } from './BaseModal';
|
||||
import { QRPrinter } from '../../core/qr_print';
|
||||
|
||||
/**
|
||||
* 하드웨어 자산 상세 모달 (Styled Main Edition)
|
||||
@@ -30,9 +31,10 @@ class HwAssetModal extends BaseModal {
|
||||
<div id="hw-asset-modal" class="modal-overlay hidden">
|
||||
<div class="modal-content wide">
|
||||
<div class="modal-header">
|
||||
<div class="header-left">
|
||||
<h2 id="hw-modal-title" class="modal-title">${this.title}</h2>
|
||||
<div id="hw-header-identity" class="header-identity"></div>
|
||||
<div class="header-left" style="display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap;">
|
||||
<h2 id="hw-modal-title" class="modal-title" style="display: none;">${this.title}</h2>
|
||||
<div id="hw-header-identity" class="header-identity" style="display: inline-flex; gap: 0.5rem; align-items: center;"></div>
|
||||
<button id="btn-print-hw-qr" class="btn btn-outline btn-primary hidden" style="padding: 2px 8px; font-size: 11px; height: 22px; margin: 0; line-height: 1; display: inline-flex; align-items: center; justify-content: center; cursor: pointer;">QR 인쇄</button>
|
||||
</div>
|
||||
<button id="btn-close-hw-modal" class="btn-icon" aria-label="닫기">×</button>
|
||||
</div>
|
||||
@@ -264,6 +266,21 @@ class HwAssetModal extends BaseModal {
|
||||
const detailSelect = document.getElementById('hw-location_detail') as HTMLSelectElement;
|
||||
|
||||
this.fetchMapConfig();
|
||||
|
||||
const qrPrintBtn = document.getElementById('btn-print-hw-qr');
|
||||
qrPrintBtn?.addEventListener('click', () => {
|
||||
if (this.currentAsset && this.currentAsset.asset_code) {
|
||||
QRPrinter.print([{
|
||||
type: 'asset',
|
||||
code: this.currentAsset.asset_code,
|
||||
title: '[ HM IT ASSET ]',
|
||||
subtitle: this.currentAsset.model_name || this.currentAsset.asset_purpose || this.currentAsset.category || 'IT 자산',
|
||||
dept: this.currentAsset.current_dept || '-',
|
||||
user: this.currentAsset.user_current || '-'
|
||||
}]);
|
||||
}
|
||||
});
|
||||
|
||||
this.fetchMasterComponents().then(() => {
|
||||
this.bindAutocomplete('hw-cpu', 'hw-cpu-list', 'CPU');
|
||||
this.bindAutocomplete('hw-ram', 'hw-ram-list', 'RAM');
|
||||
@@ -299,7 +316,7 @@ class HwAssetModal extends BaseModal {
|
||||
const prefix = TYPE_PREFIX_MAP[cat] || 'ETC';
|
||||
const purchaseDate = (document.getElementById('hw-purchase_date') as HTMLInputElement)?.value || '';
|
||||
try {
|
||||
const res = await fetch(`http://${location.hostname}:3000/api/generate-asset-code?prefix=${prefix}&purchaseDate=${purchaseDate}`);
|
||||
const res = await fetch(`/api/generate-asset-code?prefix=${prefix}&purchaseDate=${purchaseDate}`);
|
||||
const data = await res.json();
|
||||
if (data.nextCode) setFieldValue('hw-asset_code', data.nextCode);
|
||||
} catch (err) { console.error('코드 생성 실패:', err); }
|
||||
@@ -317,7 +334,7 @@ class HwAssetModal extends BaseModal {
|
||||
const reader = new FileReader();
|
||||
reader.onload = async () => {
|
||||
try {
|
||||
const res = await fetch(`http://${location.hostname}:3000/api/upload`, {
|
||||
const res = await fetch('/api/upload', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ fileName: file.name, fileData: reader.result })
|
||||
@@ -326,7 +343,7 @@ class HwAssetModal extends BaseModal {
|
||||
if (data.success) {
|
||||
setFieldValue('hw-approval_document', data.filePath);
|
||||
if (fileLinkContainer) {
|
||||
fileLinkContainer.innerHTML = `<a href="http://${location.hostname}:3000${data.filePath}" target="_blank" class="btn btn-outline btn-sm">[파일 보기]</a>`;
|
||||
fileLinkContainer.innerHTML = `<a href="${data.filePath}" target="_blank" class="btn btn-outline btn-sm">[파일 보기]</a>`;
|
||||
}
|
||||
}
|
||||
} catch (err) { console.error('파일 업로드 실패:', err); alert('파일 업로드 중 오류가 발생했습니다.'); }
|
||||
@@ -385,7 +402,7 @@ class HwAssetModal extends BaseModal {
|
||||
const prefix = TYPE_PREFIX_MAP[cat] || 'ETC';
|
||||
const purchaseDate = (document.getElementById('hw-purchase_date') as HTMLInputElement)?.value || '';
|
||||
try {
|
||||
const res = await fetch(`http://${location.hostname}:3000/api/generate-asset-code?prefix=${prefix}&purchaseDate=${purchaseDate}`);
|
||||
const res = await fetch(`/api/generate-asset-code?prefix=${prefix}&purchaseDate=${purchaseDate}`);
|
||||
const data = await res.json();
|
||||
if (data.nextCode) {
|
||||
setFieldValue('hw-asset_code', data.nextCode);
|
||||
@@ -621,7 +638,7 @@ class HwAssetModal extends BaseModal {
|
||||
if (docName) docName.textContent = asset.approval_document ? asset.approval_document.split('/').pop() : '파일 선택...';
|
||||
const fileLinkContainer = document.getElementById('hw-file-link-container');
|
||||
if (fileLinkContainer && asset.approval_document) {
|
||||
fileLinkContainer.innerHTML = `<a href="http://${location.hostname}:3000${asset.approval_document}" target="_blank" class="btn btn-outline btn-sm">[파일 보기]</a>`;
|
||||
fileLinkContainer.innerHTML = `<a href="${asset.approval_document}" target="_blank" class="btn btn-outline btn-sm">[파일 보기]</a>`;
|
||||
} else if (fileLinkContainer) {
|
||||
fileLinkContainer.innerHTML = '';
|
||||
}
|
||||
@@ -642,6 +659,13 @@ class HwAssetModal extends BaseModal {
|
||||
protected onAfterOpen(asset: any, mode: string): void {
|
||||
const genBtn = document.getElementById('btn-gen-hw-code');
|
||||
if (genBtn) genBtn.style.display = (mode === 'add') ? 'inline-flex' : 'none';
|
||||
|
||||
const qrBtn = document.getElementById('btn-print-hw-qr');
|
||||
if (qrBtn) {
|
||||
const hasCode = asset && asset.asset_code && asset.asset_code.trim() !== '';
|
||||
qrBtn.classList.toggle('hidden', mode !== 'view' || !hasCode);
|
||||
}
|
||||
|
||||
this.toggleFileUploadUI(mode !== 'view');
|
||||
this.toggleEditOnlyBtns(mode !== 'view');
|
||||
this.updateMapButtonVisibility();
|
||||
|
||||
Reference in New Issue
Block a user