fix: 자산번호 저장 누락 오류 수정 및 위치보기 도면 배치 보완
This commit is contained in:
@@ -377,6 +377,30 @@ class HwAssetModal extends BaseModal {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 자산코드가 비어있는 경우 자동 생성 처리
|
||||||
|
let assetCode = getFieldValue('hw-asset_code').trim();
|
||||||
|
if (!assetCode) {
|
||||||
|
const cat = categorySelect.value;
|
||||||
|
if (!cat) { alert('구분을 먼저 선택해주세요.'); return; }
|
||||||
|
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 data = await res.json();
|
||||||
|
if (data.nextCode) {
|
||||||
|
setFieldValue('hw-asset_code', data.nextCode);
|
||||||
|
assetCode = data.nextCode;
|
||||||
|
} else {
|
||||||
|
alert('자산코드 자동 생성에 실패했습니다. 수동으로 생성 버튼을 눌러주세요.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('코드 자동 생성 실패:', err);
|
||||||
|
alert('자산코드 자동 생성 중 오류가 발생했습니다.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 동적 볼륨 데이터 수집
|
// 동적 볼륨 데이터 수집
|
||||||
const vols: any[] = [];
|
const vols: any[] = [];
|
||||||
document.querySelectorAll('#hw-volume-container .volume-row').forEach((row, idx) => {
|
document.querySelectorAll('#hw-volume-container .volume-row').forEach((row, idx) => {
|
||||||
|
|||||||
@@ -125,10 +125,13 @@ export function setEditLock(
|
|||||||
const inputs = form.querySelectorAll('input, select, textarea');
|
const inputs = form.querySelectorAll('input, select, textarea');
|
||||||
inputs.forEach(input => {
|
inputs.forEach(input => {
|
||||||
const el = input as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
|
const el = input as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
|
||||||
// 자산번호 및 ID 필드는 편집 모드에서도 잠금 유지
|
// 자산번호 및 ID 필드는 편집 모드에서도 잠금 유지 (disabled는 해제하되 readOnly를 적용하여 폼 데이터 수집 가능하게 함)
|
||||||
if (el.name !== 'asset_code' && !el.id.includes('asset-id') && !el.id.includes('id-hidden')) {
|
if (el.name !== 'asset_code' && !el.id.includes('asset-id') && !el.id.includes('id-hidden')) {
|
||||||
el.disabled = false;
|
el.disabled = false;
|
||||||
if ('readOnly' in el) (el as HTMLInputElement).readOnly = false;
|
if ('readOnly' in el) (el as HTMLInputElement).readOnly = false;
|
||||||
|
} else {
|
||||||
|
el.disabled = false;
|
||||||
|
if ('readOnly' in el) (el as HTMLInputElement).readOnly = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -25,10 +25,6 @@ export async function renderLocationView(container: HTMLElement) {
|
|||||||
: [];
|
: [];
|
||||||
const mapPath = locImages[currentPage] || '';
|
const mapPath = locImages[currentPage] || '';
|
||||||
|
|
||||||
// 조회 모드: 설정 파일에 정의된 asset_id를 기준으로 자산 데이터 매핑
|
|
||||||
const allBoxes = mapConfig[mapPath] || [];
|
|
||||||
const boxes = allBoxes.filter((box: any) => box.asset_id != null);
|
|
||||||
|
|
||||||
// 모든 하드웨어 카테고리에서 자산 검색
|
// 모든 하드웨어 카테고리에서 자산 검색
|
||||||
const allHwAssets = [
|
const allHwAssets = [
|
||||||
...state.masterData.pc,
|
...state.masterData.pc,
|
||||||
@@ -41,6 +37,50 @@ export async function renderLocationView(container: HTMLElement) {
|
|||||||
...state.masterData.pcParts
|
...state.masterData.pcParts
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// map_config.json에 설정된 모든 박스를 복사해서 작업용으로 사용
|
||||||
|
const tempBoxes = (mapConfig[mapPath] || []).map((b: any) => ({ ...b }));
|
||||||
|
|
||||||
|
// DB 데이터에서 현재 지도(mapPath) 및 위치와 좌표 정보(loc_x, loc_y)가 일치하는 자산 추출
|
||||||
|
allHwAssets.forEach((asset: any) => {
|
||||||
|
const photoPath = asset.location_photo || asset.loc_img || '';
|
||||||
|
const hasCoords = asset.loc_x != null && asset.loc_y != null && asset.loc_x !== '' && asset.loc_y !== '' && asset.loc_x !== 'null' && asset.loc_y !== 'null';
|
||||||
|
|
||||||
|
if (hasCoords && photoPath.trim() === mapPath.trim()) {
|
||||||
|
const ax = parseFloat(asset.loc_x);
|
||||||
|
const ay = parseFloat(asset.loc_y);
|
||||||
|
|
||||||
|
// map_config.json에서 읽어온 박스들 중 x, y 좌표가 일치하는 빈 박스가 있는지 찾음 (오차범위 0.1 고려)
|
||||||
|
const matchedBox = tempBoxes.find((b: any) => {
|
||||||
|
const bx = parseFloat(b.x);
|
||||||
|
const by = parseFloat(b.y);
|
||||||
|
return Math.abs(bx - ax) < 0.1 && Math.abs(by - ay) < 0.1;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (matchedBox) {
|
||||||
|
// 이미 매칭된 박스가 존재하고 asset_id가 비어있다면 해당 박스에 asset_id를 주입
|
||||||
|
if (matchedBox.asset_id == null) {
|
||||||
|
matchedBox.asset_id = asset.id;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 일치하는 기존 박스가 없을 때만 4x4 크기의 임시 박스로 동적 생성
|
||||||
|
const alreadyMatched = tempBoxes.some((b: any) => b.asset_id === asset.id);
|
||||||
|
if (!alreadyMatched) {
|
||||||
|
tempBoxes.push({
|
||||||
|
asset_id: asset.id,
|
||||||
|
x: asset.loc_x,
|
||||||
|
y: asset.loc_y,
|
||||||
|
w: '4',
|
||||||
|
h: '4',
|
||||||
|
name: asset.asset_purpose || asset.asset_code || '미지정 자산'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 최종적으로 asset_id가 null이 아닌(자산이 정상 매핑되거나 갱신된) 박스들만 남겨서 렌더링
|
||||||
|
const boxes = tempBoxes.filter((b: any) => b.asset_id != null);
|
||||||
|
|
||||||
container.innerHTML = `
|
container.innerHTML = `
|
||||||
<div class="location-view-wrapper">
|
<div class="location-view-wrapper">
|
||||||
<!-- 상단 통합 바 (Unified Search Bar) -->
|
<!-- 상단 통합 바 (Unified Search Bar) -->
|
||||||
|
|||||||
Reference in New Issue
Block a user