diff --git a/server.js b/server.js index 60f04f7..1dacc03 100644 --- a/server.js +++ b/server.js @@ -116,11 +116,10 @@ app.get('/api/assets/master', async (req, res) => { s.monitoring, s.price, s.monitor_inch, s.serial_num, l.location, l.location_detail, l.location_photo, l.loc_x, l.loc_y, n.ip_address, n.mac_address, n.remote_tool, n.remote_id, n.remote_pw, - (SELECT CONCAT(capacity, unit) FROM asset_volume WHERE asset_id = c.id AND disk_type = 'SSD' AND slot_no = 1 LIMIT 1) as ssd_1, - (SELECT CONCAT(capacity, unit) FROM asset_volume WHERE asset_id = c.id AND disk_type = 'SSD' AND slot_no = 2 LIMIT 1) as ssd_2, - (SELECT CONCAT(capacity, unit) FROM asset_volume WHERE asset_id = c.id AND disk_type = 'HDD' AND slot_no = 1 LIMIT 1) as hdd_1, - (SELECT CONCAT(capacity, unit) FROM asset_volume WHERE asset_id = c.id AND disk_type = 'HDD' AND slot_no = 2 LIMIT 1) as hdd_2, - (SELECT GROUP_CONCAT(CONCAT(disk_type, ': ', capacity, unit) SEPARATOR ', ') FROM asset_volume WHERE asset_id = c.id) as volume_summary + ( + SELECT JSON_ARRAYAGG(JSON_OBJECT('type', disk_type, 'capacity', capacity, 'unit', unit, 'slot', slot_no)) + FROM asset_volume WHERE asset_id = c.id + ) as volumes FROM asset_core c LEFT JOIN asset_spec s ON c.id = s.asset_id LEFT JOIN asset_location l ON l.id = ( @@ -194,26 +193,23 @@ app.post('/api/asset/:category/save', async (req, res) => { await connection.query(`INSERT INTO asset_spec (${specKeys.join(', ')}) VALUES (${specKeys.map(() => '?').join(', ')})`, Object.values(specData)); } - // 3.3 asset_volume (Legacy Parser) - const parseCapacity = (str) => { - if (!str || str.trim() === '' || str.toLowerCase() === 'null') return null; - const match = str.match(/(\d+(?:\.\d+)?)\s*([GT]B)?/i); - if (match) return { value: parseFloat(match[1]), unit: (match[2] || 'GB').toUpperCase() }; - return null; - }; - const storages = [ - { val: asset.ssd_1, type: 'SSD', slot: 1 }, - { val: asset.ssd_2, type: 'SSD', slot: 2 }, - { val: asset.hdd_1, type: 'HDD', slot: 1 }, - { val: asset.hdd_2, type: 'HDD', slot: 2 } - ]; + // 3.3 asset_volume await connection.query('DELETE FROM asset_volume WHERE asset_id = ?', [asset.id]); - for (const s of storages) { - const parsed = parseCapacity(s.val); - if (parsed) { - await connection.query('INSERT INTO asset_volume (asset_id, disk_type, capacity, unit, slot_no) VALUES (?, ?, ?, ?, ?)', - [asset.id, s.type, parsed.value, parsed.unit, s.slot]); - } + if (asset.volumes) { + try { + let vols = typeof asset.volumes === 'string' ? JSON.parse(asset.volumes) : asset.volumes; + if (Array.isArray(vols)) { + for (let i = 0; i < vols.length; i++) { + const v = vols[i]; + if (v.type && v.capacity) { + await connection.query( + 'INSERT INTO asset_volume (asset_id, disk_type, capacity, unit, slot_no) VALUES (?, ?, ?, ?, ?)', + [asset.id, v.type, v.capacity, v.unit || 'GB', v.slot || (i + 1)] + ); + } + } + } + } catch(e) { console.error('Volume parse error', e); } } // 3.4 asset_location diff --git a/src/components/Modal/HWModal.ts b/src/components/Modal/HWModal.ts index 29a22f4..9cd7916 100644 --- a/src/components/Modal/HWModal.ts +++ b/src/components/Modal/HWModal.ts @@ -19,161 +19,209 @@ class HwAssetModal extends BaseModal { } protected renderFrameHTML(): string { - // CSS 명세(modal.css)의 input 패딩(0.625rem)과 일치시켜 정렬을 완벽하게 잡는 스타일 - const standardBtnStyle = 'height: auto !important; padding: 0.625rem 1.25rem; font-size: 0.875rem; line-height: 1.2; display: inline-flex; align-items: center; justify-content: center;'; + const sharedStyle = 'height: 38px !important; box-sizing: border-box !important; font-size: 13px; margin: 0;'; + const inputStyle = sharedStyle; + const btnStyle = `padding: 0 16px; display: inline-flex; align-items: center; justify-content: center; font-weight: 600; white-space: nowrap; cursor: pointer; ${sharedStyle}`; return `