users.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. // 用户管理模块
  2. class UsersManager {
  3. constructor(options = {}) {
  4. this.apiBaseUrl = options.apiBaseUrl || 'http://localhost:3000';
  5. this.tbody = options.tbody || null;
  6. this.users = [];
  7. this.init();
  8. }
  9. init() {
  10. this.bindEvents();
  11. this.loadUsers();
  12. }
  13. bindEvents() {
  14. // 刷新按钮
  15. const refreshBtn = document.getElementById('refreshUsersBtn');
  16. if (refreshBtn) {
  17. refreshBtn.addEventListener('click', () => {
  18. this.loadUsers();
  19. });
  20. }
  21. // 编辑用户表单
  22. const editForm = document.getElementById('editUserForm');
  23. if (editForm) {
  24. editForm.addEventListener('submit', (e) => this.handleEditUser(e));
  25. }
  26. // 关闭编辑弹窗
  27. const closeEditModal = document.getElementById('closeEditUserModal');
  28. if (closeEditModal) {
  29. closeEditModal.addEventListener('click', () => {
  30. document.getElementById('editUserModal').style.display = 'none';
  31. });
  32. }
  33. const cancelEdit = document.getElementById('cancelEditUser');
  34. if (cancelEdit) {
  35. cancelEdit.addEventListener('click', () => {
  36. document.getElementById('editUserModal').style.display = 'none';
  37. });
  38. }
  39. }
  40. // 加载用户列表
  41. async loadUsers() {
  42. if (!this.tbody) return;
  43. this.tbody.innerHTML = '<tr><td colspan="6" class="loading-text">加载中...</td></tr>';
  44. try {
  45. const apiUrl = `${this.apiBaseUrl}/api/admin/users`;
  46. console.log('[UsersManager] 请求用户列表,URL:', apiUrl);
  47. const response = await fetch(apiUrl);
  48. console.log('[UsersManager] 响应状态:', response.status, response.statusText);
  49. if (!response.ok) {
  50. throw new Error(`加载用户列表失败: ${response.status} ${response.statusText}`);
  51. }
  52. const result = await response.json();
  53. console.log('[UsersManager] 获取到的数据:', result);
  54. if (result.success && result.users) {
  55. this.users = result.users;
  56. console.log('[UsersManager] 用户数量:', this.users.length);
  57. this.renderUsers();
  58. } else {
  59. console.warn('[UsersManager] 返回数据格式不正确或没有用户:', result);
  60. this.tbody.innerHTML = '<tr><td colspan="6" class="loading-text">暂无用户数据</td></tr>';
  61. }
  62. } catch (error) {
  63. console.error('[UsersManager] 加载用户失败:', error);
  64. const errorMessage = error.message || '未知错误';
  65. this.tbody.innerHTML = `<tr><td colspan="6" class="loading-text" style="color: #ef4444;">加载失败: ${errorMessage}<br>请确保服务器正在运行 (http://localhost:3000)</td></tr>`;
  66. }
  67. }
  68. // 渲染用户列表
  69. renderUsers() {
  70. if (!this.tbody) return;
  71. if (this.users.length === 0) {
  72. this.tbody.innerHTML = '<tr><td colspan="6" class="loading-text">暂无用户数据</td></tr>';
  73. return;
  74. }
  75. this.tbody.innerHTML = this.users.map(user => `
  76. <tr>
  77. <td>${user.id}</td>
  78. <td>${user.username}</td>
  79. <td>${user.phone || '-'}</td>
  80. <td>${user.points || 0}</td>
  81. <td>${user.created_at ? new Date(user.created_at).toLocaleString('zh-CN') : '-'}</td>
  82. <td>
  83. <div class="action-buttons">
  84. <button class="btn-edit" onclick="window.usersManagerInstance.editUser(${user.id})">编辑</button>
  85. </div>
  86. </td>
  87. </tr>
  88. `).join('');
  89. }
  90. // 编辑用户
  91. editUser(userId) {
  92. const user = this.users.find(u => u.id === userId);
  93. if (!user) return;
  94. document.getElementById('editUserId').value = user.id;
  95. document.getElementById('editUsername').value = user.username;
  96. document.getElementById('editPhone').value = user.phone || '';
  97. document.getElementById('editPoints').value = user.points || 0;
  98. document.getElementById('editUserModal').style.display = 'flex';
  99. }
  100. // 处理编辑用户
  101. async handleEditUser(e) {
  102. e.preventDefault();
  103. const userId = document.getElementById('editUserId').value;
  104. const username = document.getElementById('editUsername').value;
  105. const phone = document.getElementById('editPhone').value;
  106. const points = parseInt(document.getElementById('editPoints').value);
  107. try {
  108. const response = await fetch(`${this.apiBaseUrl}/api/admin/users/update`, {
  109. method: 'POST',
  110. headers: {
  111. 'Content-Type': 'application/json'
  112. },
  113. body: JSON.stringify({
  114. id: userId,
  115. username: username,
  116. phone: phone,
  117. points: points
  118. })
  119. });
  120. const result = await response.json();
  121. if (result.success) {
  122. this.showSuccess('修改成功');
  123. document.getElementById('editUserModal').style.display = 'none';
  124. this.loadUsers();
  125. } else {
  126. this.showError('修改失败: ' + (result.message || '未知错误'));
  127. }
  128. } catch (error) {
  129. console.error('[UsersManager] 修改用户失败:', error);
  130. this.showError('修改失败,请稍后重试');
  131. }
  132. }
  133. // 显示错误/成功消息
  134. showError(message) {
  135. if (window.showCustomAlert) {
  136. window.showCustomAlert(message);
  137. } else {
  138. console.error('[UsersManager] 错误:', message);
  139. }
  140. }
  141. showSuccess(message) {
  142. if (window.showCustomAlert) {
  143. window.showCustomAlert(message, 'success');
  144. } else {
  145. console.log('[UsersManager] 成功:', message);
  146. }
  147. }
  148. }
  149. // 导出
  150. if (typeof module !== 'undefined' && module.exports) {
  151. module.exports = UsersManager;
  152. } else {
  153. window.UsersManager = UsersManager;
  154. }