/** * 用户管理模块 JavaScript * 提供用户的查看、创建、编辑、删除功能 */ (function() { 'use strict'; // 引用全局的翻译函数 // 翻译函数由 i18n-helper.js 提供 // 密码哈希工具函数(使用crypto-js库) function sha256(message) { if (typeof CryptoJS !== 'undefined' && CryptoJS.SHA256) { return CryptoJS.SHA256(message).toString(); } else { console.error(t('error.cryptoJsNotLoaded')); throw new Error(t('error.encryptionLibraryNotLoaded')); } } // 模块私有状态 let usersPaginator = null; let editingId = null; let container = null; // 用户管理模块 const UserManagement = { init: function(containerElement) { container = containerElement; this.initPaginators(); this.initEventListeners(); // 等待 i18next 初始化完成后再加载数据 const loadData = () => { this.loadUsers(); }; // 检查 i18next 是否已可用(通过测试一个翻译键) const checkI18nReady = () => { if (window.i18next && window.i18next.t) { try { const test = window.i18next.t('common.loading'); // 如果翻译键正常工作(返回值不是键名本身),开始加载数据 if (test && test !== 'common.loading') { loadData(); return true; } } catch (e) { // i18next 还没准备好 } } return false; }; // 立即检查一次 if (checkI18nReady()) { return; } // 等待 i18next 初始化 const checkI18n = setInterval(() => { if (checkI18nReady()) { clearInterval(checkI18n); } }, 100); // 超时保护(10秒后强制加载) setTimeout(() => { clearInterval(checkI18n); console.warn('i18next initialization timeout or check failed, loading data anyway'); loadData(); }, 10000); }, initPaginators: function() { // 初始化用户管理分页器 usersPaginator = createPaginator('users', { initialPage: 1, initialPageSize: 20, onPageChange: (page, pageSize) => { this.loadUsers(); }, onPageSizeChange: (pageSize) => { this.loadUsers(); } }); }, initEventListeners: function() { // 添加用户按钮 const addUserBtn = container.querySelector('#addUserBtn'); if (addUserBtn) { addUserBtn.addEventListener('click', () => { this.showUserForm(); }); } }, loadUsers: async function() { if (!usersPaginator) return; try { const skip = usersPaginator.getSkip(); const limit = usersPaginator.getLimit(); const users = await apiGet(`/users/?skip=${skip}&limit=${limit}`); // 获取总数:如果返回的数据量小于limit,说明这是最后一页 // 如果等于limit,可能还有更多数据,尝试获取下一页来判断 let totalCount; if (users.length < limit) { totalCount = skip + users.length; } else { // 尝试获取下一页来判断是否还有更多数据 try { const nextPage = await apiGet(`/users/?skip=${skip + limit}&limit=1`); if (nextPage.length > 0) { // 还有更多数据,但不知道总数,使用估算值(当前页数 * 每页数量 + 1) totalCount = (skip + limit) + 1; } else { // 没有更多数据了 totalCount = skip + limit; } } catch (error) { // 如果获取失败,假设还有更多数据 totalCount = (skip + limit) + 1; } } usersPaginator.setTotalCount(totalCount); this.renderUsersTable(users); } catch (error) { console.error('加载用户失败:', error); showError(`${t('user.loadFailed')}: ${error.message || t('error.unknownError')}`); } }, renderUsersTable: function(users) { const tbody = container.querySelector('#usersTableBody'); const paginationContainer = container.querySelector('#usersPaginationContainer'); // 如果元素不存在,说明容器已被清空,需要重新初始化 if (!tbody) { console.warn('Users table body not found, container may have been cleared'); return; } if (users.length === 0) { tbody.innerHTML = `${t('user.noUsers')}`; if (paginationContainer) paginationContainer.style.display = 'none'; return; } tbody.innerHTML = users.map(user => ` ${user.id} ${escapeHtml(user.username)} ${escapeHtml(user.full_name || '-')} ${escapeHtml(user.organization || '-')} ${escapeHtml(user.team || '-')} ${escapeHtml(user.species || '-')} ${user.is_active ? t('status.active') : t('status.inactive')} ${user.is_superuser ? t('user.isSuperuser') : t('user.isUser')} ${formatDateTime(user.created_at)} `).join(''); // 显示分页器 if (paginationContainer && usersPaginator) { paginationContainer.style.display = 'block'; usersPaginator.render(); } }, showUserForm: function(user = null) { editingId = user ? user.id : null; const title = user ? t('user.editUser') : t('user.addUser'); const content = `
`; openModal(title, content, async () => { await this.saveUser(); }); }, saveUser: async function() { const username = document.getElementById('username').value; const full_name = document.getElementById('full_name').value; const organization = document.getElementById('organization').value; const team = document.getElementById('team').value; const species = document.getElementById('species').value; const password = document.getElementById('password').value; const is_active = document.getElementById('is_active').checked; const is_superuser = document.getElementById('is_superuser').checked; try { const data = { username, full_name: full_name || null, organization: organization || null, team: team || null, species: species || null, is_active, is_superuser }; if (password) { // 对密码进行SHA-256哈希(用于创建/更新用户,不需要时间戳) const passwordHash = sha256(password); data.password = passwordHash; } if (editingId) { await apiPut(`/users/${editingId}`, data); showSuccess(t('user.updateSuccess')); } else { if (!password) { alert(t('user.passwordRequired')); return; } await apiPost('/users/', data); showSuccess(t('user.createSuccess')); } closeModal(); // 如果是新建用户,重置到第一页 if (!editingId && usersPaginator) { usersPaginator.reset(); } this.loadUsers(); } catch (error) { showError(`${t('user.saveFailed')}: ${error.message || t('error.unknownError')}`); } }, editUser: async function(userId) { try { const user = await apiGet(`/users/${userId}`); this.showUserForm(user); } catch (error) { showError(`${t('user.loadFailed')}: ${error.message || t('error.unknownError')}`); } }, deleteUser: async function(userId) { if (!confirm(t('user.deleteConfirm'))) { return; } try { await apiDelete(`/users/${userId}`); showSuccess(t('user.deleteSuccess')); // 如果当前页没有数据了,回到上一页 if (usersPaginator) { usersPaginator.adjustPageAfterDelete(); } this.loadUsers(); } catch (error) { showError(`${t('user.deleteFailed')}: ${error.message || t('error.unknownError')}`); } }, destroy: function() { // 清理资源 usersPaginator = null; editingId = null; container = null; } }; // 暴露到全局 window.UserManagement = UserManagement; })();