feat(map): implement robust ID-based asset mapping and fix UI rendering inconsistencies
- Migrated map mapping from fuzzy coordinates to precise asset_id tracking - Updated MapEditor to allow explicit asset assignment via dropdown - Fixed LocationView rendering logic to search across all hardware categories - Standardized map indicators to always render as areas (boxes) with minimum size - Restored stable CSS max-height for detail modal photos to prevent clipping - Synced MapEditor saves directly to database via asset_id
This commit is contained in:
@@ -25,16 +25,21 @@ export async function renderLocationView(container: HTMLElement) {
|
||||
: [];
|
||||
const mapPath = locImages[currentPage] || '';
|
||||
|
||||
// 조회 모드: 자산이 등록된 구역만 필터링하여 노출
|
||||
// 조회 모드: 설정 파일에 정의된 asset_id를 기준으로 자산 데이터 매핑
|
||||
const allBoxes = mapConfig[mapPath] || [];
|
||||
const boxes = allBoxes.filter((box: any) =>
|
||||
state.masterData.hw.some(a =>
|
||||
a.location === currentLoc &&
|
||||
a.location_detail === currentDetail &&
|
||||
String(a.loc_x) === String(box.x) &&
|
||||
String(a.loc_y) === String(box.y)
|
||||
)
|
||||
);
|
||||
const boxes = allBoxes.filter((box: any) => box.asset_id != null);
|
||||
|
||||
// 모든 하드웨어 카테고리에서 자산 검색
|
||||
const allHwAssets = [
|
||||
...state.masterData.pc,
|
||||
...state.masterData.server,
|
||||
...state.masterData.storage,
|
||||
...state.masterData.network,
|
||||
...state.masterData.equipment,
|
||||
...state.masterData.survey,
|
||||
...state.masterData.officeSupplies,
|
||||
...state.masterData.pcParts
|
||||
];
|
||||
|
||||
container.innerHTML = `
|
||||
<div class="location-view-wrapper">
|
||||
@@ -81,14 +86,17 @@ export async function renderLocationView(container: HTMLElement) {
|
||||
<img src="${mapPath}" id="main-map-img" class="map-image">
|
||||
<div id="box-overlay" class="map-overlay">
|
||||
${boxes.map((box: any, idx: number) => {
|
||||
const name = box.name || `#${idx+1}`;
|
||||
const asset = allHwAssets.find(a => a.id === box.asset_id);
|
||||
const name = asset ? (asset.asset_purpose || asset.asset_code) : (box.name || `#${idx+1}`);
|
||||
// w, h가 없거나 너무 작으면 최소 크기(3%) 보장하여 영역으로 표시
|
||||
const width = Math.max(parseFloat(box.w || '3'), 3);
|
||||
const height = Math.max(parseFloat(box.h || '3'), 3);
|
||||
return `
|
||||
<div class="location-box-point"
|
||||
<div class="location-box-area"
|
||||
data-asset-id="${box.asset_id}"
|
||||
data-name="${name}"
|
||||
data-x="${box.x}"
|
||||
data-y="${box.y}"
|
||||
style="left:${box.x}%; top:${box.y}%; width:${box.w}%; height:${box.h}%;
|
||||
border: 2px solid var(--primary-color); background: rgba(30, 81, 73, 0.1); cursor:pointer; pointer-events: auto;">
|
||||
style="left:${box.x}%; top:${box.y}%; width:${width}%; height:${height}%;
|
||||
border: 2px solid var(--primary-color); background: rgba(30, 81, 73, 0.1); cursor:pointer; pointer-events: auto; position: absolute;">
|
||||
</div>
|
||||
`}).join('')}
|
||||
</div>
|
||||
@@ -170,20 +178,15 @@ export async function renderLocationView(container: HTMLElement) {
|
||||
chkBox.addEventListener('change', handleToggle);
|
||||
}
|
||||
|
||||
container.querySelectorAll('.location-box-point').forEach(box => {
|
||||
container.querySelectorAll('.location-box-area').forEach(box => {
|
||||
box.addEventListener('click', () => {
|
||||
const x = box.getAttribute('data-x');
|
||||
const y = box.getAttribute('data-y');
|
||||
const assetId = box.getAttribute('data-asset-id');
|
||||
if (!assetId) return;
|
||||
|
||||
const targetAsset = state.masterData.hw.find(a =>
|
||||
a.location === currentLoc &&
|
||||
a.location_detail === currentDetail &&
|
||||
String(a.loc_x) === String(x) &&
|
||||
String(a.loc_y) === String(y)
|
||||
);
|
||||
const targetAsset = allHwAssets.find(a => a.id === assetId);
|
||||
|
||||
if (targetAsset) renderAssetDetail(targetAsset);
|
||||
container.querySelectorAll('.location-box-point').forEach(b => (b as HTMLElement).style.background = 'rgba(30, 81, 73, 0.1)');
|
||||
container.querySelectorAll('.location-box-area').forEach(b => (b as HTMLElement).style.background = 'rgba(30, 81, 73, 0.1)');
|
||||
(box as HTMLElement).style.background = 'rgba(30, 81, 73, 0.4)';
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user