From b0c3707ccd09125512a791fd4e560c91517defc0 Mon Sep 17 00:00:00 2001 From: DSQ Date: Sun, 15 Mar 2026 17:11:31 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9C=80=E6=B5=8B=E8=AF=95[0.2.7.3][ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- accounts/templates/accounts/profile.html | 77 ++++++++++++++++++++++++ elastic/templates/elastic/users.html | 68 ++++++++++++++++++--- elastic/views.py | 10 +++ main/templates/main/home.html | 2 +- 4 files changed, 148 insertions(+), 9 deletions(-) diff --git a/accounts/templates/accounts/profile.html b/accounts/templates/accounts/profile.html index 4afde20..2431e5b 100644 --- a/accounts/templates/accounts/profile.html +++ b/accounts/templates/accounts/profile.html @@ -29,6 +29,13 @@ .image-item .info { padding: 10px; font-size: 12px; color: #888; text-align: center; } .no-data { text-align: center; color: #999; padding: 40px; } + .form-group { margin-bottom: 14px; } + .form-group label { display:block; margin-bottom: 6px; font-weight: 600; color: #333; } + .form-group input { width: 100%; padding: 10px 12px; border: 1px solid #d1d5db; border-radius: 8px; box-sizing: border-box; } + .btn { padding: 10px 14px; border: none; border-radius: 10px; cursor: pointer; background: #4f46e5; color: #fff; } + .msg { margin-top: 10px; font-size: 13px; } + .msg.error { color: #b91c1c; } + .msg.success { color: #166534; } /* 图片放大模态框 */ .image-modal { position: fixed; inset: 0; background: rgba(0,0,0,0.8); display: none; align-items: center; justify-content: center; z-index: 2000; } @@ -65,6 +72,28 @@ + {% if permission_name != "管理员" and not profile_user.manage_key %} +
+
+
+

修改密码

+
+
+
+
+ + +
+
+ + +
+ +
+
+
+ {% endif %} +
我的提交
{% if achievements %}
@@ -128,6 +157,54 @@ const modal = document.getElementById('imageModal'); if (event.target == modal) closeModal(); } + + const pwdForm = document.getElementById('pwdForm'); + if (pwdForm) { + pwdForm.addEventListener('submit', async (e) => { + e.preventDefault(); + const msg = document.getElementById('pwdMsg'); + msg.textContent = ''; + msg.className = 'msg'; + + const pwd = (document.getElementById('newPassword').value || '').trim(); + const cpwd = (document.getElementById('confirmPassword').value || '').trim(); + if (pwd !== cpwd) { + msg.textContent = '密码和确认密码不匹配'; + msg.className = 'msg error'; + return; + } + if (pwd.length < 6) { + msg.textContent = '密码长度至少为6位'; + msg.className = 'msg error'; + return; + } + try { + const csrftoken = getCookie('csrftoken'); + const resp = await fetch(`/elastic/users/{{ profile_user.user_id }}/update/`, { + method: 'POST', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrftoken || '' + }, + body: JSON.stringify({ password: pwd }) + }); + const data = await resp.json(); + if (resp.ok && data.status === 'success') { + msg.textContent = '修改成功'; + msg.className = 'msg success'; + document.getElementById('newPassword').value = ''; + document.getElementById('confirmPassword').value = ''; + } else { + msg.textContent = data.message || '操作失败'; + msg.className = 'msg error'; + } + } catch (err) { + msg.textContent = '操作失败'; + msg.className = 'msg error'; + } + }); + } diff --git a/elastic/templates/elastic/users.html b/elastic/templates/elastic/users.html index 9e8bf48..e501af4 100644 --- a/elastic/templates/elastic/users.html +++ b/elastic/templates/elastic/users.html @@ -134,6 +134,13 @@ border-radius: 6px; } + .search-container select { + padding: 8px 12px; + border: 1px solid #d1d5db; + border-radius: 6px; + background: #fff; + } + .search-container button { padding: 8px 15px; background: #4f46e5; @@ -262,8 +269,10 @@
+ +
@@ -272,6 +281,7 @@ 用户ID 用户名 + Key 权限 操作 @@ -364,11 +374,12 @@ } // 获取所有用户 - async function loadUsers(searchTerm = '') { + async function loadUsers(searchTerm = '', key = '') { try { - const url = searchTerm ? - `/elastic/users/?search=${encodeURIComponent(searchTerm)}` : - '/elastic/users/'; + const params = new URLSearchParams(); + if ((searchTerm || '').trim()) params.set('search', (searchTerm || '').trim()); + if ((key || '').trim()) params.set('key', (key || '').trim()); + const url = params.toString() ? `/elastic/users/?${params.toString()}` : '/elastic/users/'; const response = await fetch(url); const result = await response.json(); @@ -385,10 +396,13 @@ // 根据权限值显示权限名称 const permissionText = Number(user.permission) === 0 ? '管理员' : '普通用户'; + const keys = Array.isArray(user.key) ? user.key : (user.key ? [user.key] : []); + const keysText = keys.map(k => String(k || '').trim()).filter(Boolean).join('、') || '-'; row.innerHTML = ` ${user.user_id} ${user.username} + ${keysText} ${permissionText} @@ -407,6 +421,29 @@ } } + async function initKeyFilter() { + const select = document.getElementById('keyFilter'); + if (!select) return; + select.innerHTML = ''; + try { + const resp = await fetch('/elastic/keys-for-filter/', { credentials: 'same-origin' }); + const data = await resp.json(); + if (data.status !== 'success') return; + const keys = data.data || []; + keys.forEach(k => { + const opt = document.createElement('option'); + opt.value = String(k || '').trim(); + opt.textContent = String(k || '').trim(); + if (opt.value) select.appendChild(opt); + }); + } catch (e) { + } + select.addEventListener('change', () => { + const searchTerm = document.getElementById('searchInput').value; + loadUsers(searchTerm, select.value); + }); + } + // 打开添加用户模态框 function openAddModal() { document.getElementById('modalTitle').textContent = '添加用户'; @@ -558,7 +595,8 @@ if (searchBtn) { searchBtn.addEventListener('click', function() { const searchTerm = document.getElementById('searchInput').value; - loadUsers(searchTerm); + const key = (document.getElementById('keyFilter') || {}).value || ''; + loadUsers(searchTerm, key); }); } @@ -566,7 +604,19 @@ if (resetBtn) { resetBtn.addEventListener('click', function() { document.getElementById('searchInput').value = ''; - loadUsers(); + const select = document.getElementById('keyFilter'); + if (select) select.value = ''; + loadUsers('', ''); + }); + } + + const clearKeyBtn = document.getElementById('clearKeyBtn'); + if (clearKeyBtn) { + clearKeyBtn.addEventListener('click', function() { + const select = document.getElementById('keyFilter'); + if (select) select.value = ''; + const searchTerm = document.getElementById('searchInput').value; + loadUsers(searchTerm, ''); }); } @@ -609,6 +659,7 @@ // 页面加载时获取用户列表 document.addEventListener('DOMContentLoaded', function() { + initKeyFilter(); const selfForm = document.getElementById('selfPwdForm'); if (selfForm) { selfForm.addEventListener('submit', async (e) => { @@ -635,7 +686,8 @@ } const tbody = document.getElementById('usersTableBody'); if (tbody) { - loadUsers(); + const select = document.getElementById('keyFilter'); + loadUsers('', select ? select.value : ''); } }); @@ -654,4 +706,4 @@ }); - \ No newline at end of file + diff --git a/elastic/views.py b/elastic/views.py index 0878efe..b282624 100644 --- a/elastic/views.py +++ b/elastic/views.py @@ -444,6 +444,7 @@ def get_users(request): is_admin = int(request.session.get("permission", 1)) == 0 requester = get_user_by_id(uid) or {} mgr_keys = set(requester.get("manage_key") or []) + key_q = (request.GET.get("key") or "").strip() q = (request.GET.get("search") or "").strip() users = get_all_users() if is_admin: @@ -455,6 +456,15 @@ def get_users(request): filtered = [u for u in users if match_manage(u)] else: filtered = [u for u in users if str(u.get("user_id")) == str(uid)] + if key_q: + k = str(key_q).strip() + def match_key(user): + try: + ukeys = {str(x).strip() for x in (user.get("key") or []) if str(x).strip()} + except Exception: + ukeys = set() + return k in ukeys + filtered = [u for u in filtered if match_key(u)] if q: filtered = [u for u in filtered if q in str(u.get("username", ""))] return JsonResponse({"status": "success", "data": filtered}) diff --git a/main/templates/main/home.html b/main/templates/main/home.html index 779fa34..7b5af28 100644 --- a/main/templates/main/home.html +++ b/main/templates/main/home.html @@ -44,7 +44,7 @@ {% if is_admin or has_manage_key %} 数据管理 {% endif %} - {% if is_admin %} + {% if is_admin or has_manage_key %} 用户管理 {% endif %} 个人中心