feat: 자산 추가/수정 모달에 사용자 자동완성(사번, 직급, 부서 자동 연계) 기능 추가
This commit is contained in:
@@ -110,9 +110,14 @@ class HwAssetModal extends BaseModal {
|
||||
<label>${ASSET_SCHEMA.MANAGER_SUB.ui}</label>
|
||||
<input type="text" id="hw-manager_secondary" name="manager_secondary" />
|
||||
</div>
|
||||
<div class="form-group personal-only">
|
||||
<div class="form-group personal-only relative">
|
||||
<label>${ASSET_SCHEMA.CURRENT_USER.ui}</label>
|
||||
<input type="text" id="hw-user_current" name="user_current" />
|
||||
<input type="text" id="hw-user_current" name="user_current" autocomplete="off" />
|
||||
<div id="hw-user-current-list" class="autocomplete-list hidden"></div>
|
||||
</div>
|
||||
<div class="form-group personal-only">
|
||||
<label>${ASSET_SCHEMA.EMP_NO.ui}</label>
|
||||
<input type="text" id="hw-emp_no" name="emp_no" readonly style="background-color: #f1f5f9; cursor: not-allowed;" />
|
||||
</div>
|
||||
<div class="form-group personal-only">
|
||||
<label>${ASSET_SCHEMA.USER_POSITION.ui}</label>
|
||||
@@ -286,6 +291,7 @@ class HwAssetModal extends BaseModal {
|
||||
this.bindAutocomplete('hw-cpu', 'hw-cpu-list', 'CPU');
|
||||
this.bindAutocomplete('hw-ram', 'hw-ram-list', 'RAM');
|
||||
this.bindAutocomplete('hw-gpu', 'hw-gpu-list', 'GPU');
|
||||
this.bindUserAutocomplete();
|
||||
});
|
||||
|
||||
categorySelect.addEventListener('change', () => {
|
||||
@@ -604,6 +610,7 @@ class HwAssetModal extends BaseModal {
|
||||
setFieldValue('hw-manager_primary', asset.manager_primary || '');
|
||||
setFieldValue('hw-manager_secondary', asset.manager_secondary || '');
|
||||
setFieldValue('hw-user_current', asset.user_current || '');
|
||||
setFieldValue('hw-emp_no', asset.emp_no || '');
|
||||
setFieldValue('hw-user_position', asset.user_position || '');
|
||||
setFieldValue('hw-previous_user', asset.previous_user || '');
|
||||
setFieldValue('hw-model_name', asset.model_name || '');
|
||||
@@ -958,6 +965,89 @@ class HwAssetModal extends BaseModal {
|
||||
overlay.querySelector('#btn-preview-close')?.addEventListener('click', () => overlay.remove());
|
||||
}
|
||||
|
||||
private bindUserAutocomplete() {
|
||||
const input = document.getElementById('hw-user_current') as HTMLInputElement;
|
||||
const list = document.getElementById('hw-user-current-list') as HTMLDivElement;
|
||||
const deptSelect = document.getElementById('hw-current_dept') as HTMLSelectElement;
|
||||
const positionInput = document.getElementById('hw-user_position') as HTMLInputElement;
|
||||
const empNoInput = document.getElementById('hw-emp_no') as HTMLInputElement;
|
||||
|
||||
if (!input || !list) return;
|
||||
|
||||
const showList = (filterText: string = '') => {
|
||||
if (!this.isEditMode) return;
|
||||
const users = state.masterData.users || [];
|
||||
const query = filterText.trim().toLowerCase();
|
||||
|
||||
const filtered = query
|
||||
? users.filter((u: any) =>
|
||||
u.user_name.toLowerCase().includes(query) ||
|
||||
(u.dept_name && u.dept_name.toLowerCase().includes(query)) ||
|
||||
(u.emp_no && u.emp_no.toLowerCase().includes(query))
|
||||
)
|
||||
: users;
|
||||
|
||||
if (filtered.length === 0) {
|
||||
list.innerHTML = '<div class="autocomplete-item" style="color: #94a3b8; cursor: default;">일치하는 사원 없음</div>';
|
||||
} else {
|
||||
const seen = new Set();
|
||||
const uniqueFiltered = filtered.filter((u: any) => {
|
||||
const key = `${u.user_name}-${u.dept_name}-${u.emp_no}`;
|
||||
if (seen.has(key)) return false;
|
||||
seen.add(key);
|
||||
return true;
|
||||
}).slice(0, 15);
|
||||
|
||||
list.innerHTML = uniqueFiltered.map((u: any) => `
|
||||
<div class="autocomplete-item user-suggestion-item"
|
||||
data-name="${u.user_name}"
|
||||
data-dept="${u.dept_name || ''}"
|
||||
data-pos="${u.position || ''}"
|
||||
data-emp="${u.emp_no || ''}">
|
||||
<div style="font-weight: 600; color: #1e293b;">${u.user_name}</div>
|
||||
<div style="font-size: 0.75rem; color: #64748b; margin-top: 2px;">
|
||||
${u.dept_name || '부서 없음'} / 사번: ${u.emp_no || '-'} / ${u.position || '직급 없음'}
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
list.classList.remove('hidden');
|
||||
};
|
||||
|
||||
input.addEventListener('focus', () => showList(input.value));
|
||||
input.addEventListener('input', () => showList(input.value));
|
||||
|
||||
list.addEventListener('mousedown', (e) => {
|
||||
const item = (e.target as HTMLElement).closest('.user-suggestion-item');
|
||||
if (item) {
|
||||
const name = item.getAttribute('data-name') || '';
|
||||
const dept = item.getAttribute('data-dept') || '';
|
||||
const pos = item.getAttribute('data-pos') || '';
|
||||
const emp = item.getAttribute('data-emp') || '';
|
||||
|
||||
input.value = name;
|
||||
if (positionInput) positionInput.value = pos;
|
||||
if (empNoInput) empNoInput.value = emp;
|
||||
|
||||
if (deptSelect && dept) {
|
||||
for (let i = 0; i < deptSelect.options.length; i++) {
|
||||
if (deptSelect.options[i].value === dept) {
|
||||
deptSelect.selectedIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
list.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('mousedown', (e) => {
|
||||
if (e.target !== input && !list.contains(e.target as Node)) {
|
||||
list.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private renderHistory(assetId: string) {
|
||||
const container = document.getElementById('hw-history-list');
|
||||
if (!container) return;
|
||||
|
||||
Reference in New Issue
Block a user