From 14788fd59dc1b37452789c0a0d365bcfb1f9fff5 Mon Sep 17 00:00:00 2001 From: Viajero-tect <2737079298@qq.com> Date: Sat, 15 Nov 2025 21:24:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E2=80=9C=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- accounts/views.py | 5 +- db.sqlite3 | Bin 131072 -> 131072 bytes elastic/es_connect.py | 129 +++++++-------------------- elastic/templates/elastic/users.html | 9 +- elastic/urls.py | 4 +- elastic/views.py | 54 +++-------- main/views.py | 12 ++- 7 files changed, 64 insertions(+), 149 deletions(-) diff --git a/accounts/views.py b/accounts/views.py index ebc35ff..a294282 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -89,7 +89,10 @@ def login_submit(request): request.session["user_id"] = user["user_id"] request.session["username"] = user["username"] - request.session["permission"] = user["permission"] + try: + request.session["permission"] = int(user["permission"]) if user.get("permission") is not None else 1 + except Exception: + request.session["permission"] = 1 # Clear challenge to prevent reuse for k in ("challenge_username", "challenge_nonce"): diff --git a/db.sqlite3 b/db.sqlite3 index fb0e91432c6bfa8855172ad5addc19209f94e061..40cdfd4350b98a14be06cb9715af4c4750c7a3c0 100644 GIT binary patch delta 616 zcmajcNp90%0ES_k1St!O4^RZHM3;&D{~lsTY+M&bcI`N>T{mG<;yIq;IEfRdizaXY z1|zWoc5ExuikyNQbi+N67#1v$sCt9%dB4@Fwp!I*Z=+Xl9`NYZm*<~f)k*}D?w4Ed zE_ZjHY?a~%@qFE{-j!c)TsWkH!1Y7iOMt)hhYYX^I&%}s_Tovvm<>lPG9%0sO33oK)Ou=h`{IK2DTVbB+{$ZW*1s5)L0jJ}5Fk*ZLpFW)e$&{1> zUgq*irs5pLAyo&U4%r<*v>@4nYy&oFrU?-Qx&DL8nqy}+4rrGh1TO6YHk^~mY#y5y z3)l4T0PC|`12}~UENB!x7==PGD#~vkx81p{2@@gNkE|G^7STyfNDh@?pZ&`a9bK4( zHi^3)Gw}Fs+dfTrO5@aLs$$a}%`|&QO>*Je3I0C@fm1XEOX<_sdvB3DSd3sXw!t=+ zyZ9+4KCZ~?cJ_H`{yvobX#b$GX{!kkK_NzXuaOlmus_(!5L?8VE6Mw{V delta 557 zcmajbyKd7^00!Wg5)=uF*^8hNtf|g9Nu7&WOxm-$2LiPi7&Ao+Y3Q` z0H9ID6xdiRREazUufW24AaNNOkU-4;KYaf`pO@zI((4U|yt&_I$j7q}uS%B%R=j(; zj<3s`Pu3TBiC;Je8Bq^q151MJMH#8ZB2jz!tQ{Pa6z94l=D_J$4OPr-dspzX(CGRI zkS5NuT9Q%P%O;X%Svtyr3nS;0SGuXKJHFd@lt2!lB=S2QU+}sumYL{$;;V7T9)sb8HPGiGKw6# zYkBG7^ScdWEVl9Nl;TLE2f23AjDIGx=hAO+ppO6<`_hSf)KQ*MF-|~uEDT0mpGy;} z?DUSTB$6e$D);{ehL8hIun^yWy7Q%QgS{xQ7wn2%U6+B%;>T-*`QL_{ze;EvZcpn` xeW2OK#E6n4K|@y?bH0TlX9!^Ne08;2T`}JdxBh&p_+X7^{_QHh{ra7G_yeLnvQhv5 diff --git a/elastic/es_connect.py b/elastic/es_connect.py index 0197433..c0b1f3d 100644 --- a/elastic/es_connect.py +++ b/elastic/es_connect.py @@ -5,8 +5,6 @@ Django版本的ES连接和操作模块 from elasticsearch import Elasticsearch from elasticsearch_dsl import connections import os -import json -import re from .documents import AchievementDocument, UserDocument, GlobalDocument from .indexes import ACHIEVEMENT_INDEX_NAME, USER_INDEX_NAME, GLOBAL_INDEX_NAME import hashlib @@ -323,45 +321,23 @@ def _compute_hist(range_gte: str, interval: str, fmt: str): buckets = getattr(resp.aggs, 'b').buckets return [{"label": b.key_as_string, "count": b.doc_count} for b in buckets] -def _parse_type_from_data(data_str: str): - try: - obj = json.loads(data_str) - if isinstance(obj, dict): - for k in ("数据类型", "类型", "type"): - if k in obj and obj.get(k): - return str(obj.get(k)).strip().strip(';') - except Exception: - pass - try: - m = re.search(r'"数据类型"\s*:\s*"(.*?)"', data_str) - if m: - return str(m.group(1)).strip().strip(';') - except Exception: - pass - return None - -def _compute_type_counts_dynamic(range_gte: str): - s = AchievementDocument.search() - s = s.filter('range', time={'gte': range_gte, 'lte': 'now'}) - s = s.query('match_all') - counts_map = {} - for hit in s.scan(): - t = _parse_type_from_data(getattr(hit, 'data', '') or '') - if not t: - continue - counts_map[t] = counts_map.get(t, 0) + 1 - try: - ensure_type_in_list(t) - except Exception: - pass - return [{"type": k, "count": int(v)} for k, v in counts_map.items()] +def _compute_type_counts(range_gte: str, types: list): + counts = [] + for t in types: + s = AchievementDocument.search() + s = s.filter('range', time={'gte': range_gte, 'lte': 'now'}) + s = s.query('match_phrase', data=str(t)) + total = s.count() + counts.append({"type": str(t), "count": int(total)}) + return counts def compute_analytics(): + types = get_type_list() days = _compute_hist('now-10d/d', 'day', 'yyyy-MM-dd') weeks = _compute_hist('now-10w/w', 'week', 'yyyy-ww') months = _compute_hist('now-10M/M', 'month', 'yyyy-MM') - pie_1m = _compute_type_counts_dynamic('now-1M/M') - pie_12m = _compute_type_counts_dynamic('now-12M/M') + pie_1m = _compute_type_counts('now-1M/M', types) + pie_12m = _compute_type_counts('now-12M/M', types) return { "last_10_days": days[-10:], "last_10_weeks": weeks[-10:], @@ -406,11 +382,16 @@ def write_user_data(user_data): bool: 写入成功返回True,失败返回False """ try: + # enforce integer permission + try: + perm_val = int(user_data.get('permission', 1)) + except Exception: + perm_val = 1 user = UserDocument( user_id=user_data.get('user_id'), username=user_data.get('username'), password=user_data.get('password'), - permission=user_data.get('permission', 1) + permission=perm_val ) user.save() print(f"用户数据写入成功: {user_data.get('username')}") @@ -460,7 +441,7 @@ def get_user_by_username(username): "user_id": hit.user_id, "username": hit.username, "password": hit.password, - "permission": hit.permission + "permission": int(hit.permission) } return None except Exception as e: @@ -479,7 +460,7 @@ def get_all_users(): users.append({ "user_id": hit.user_id, "username": hit.username, - "permission": hit.permission + "permission": int(hit.permission) }) return users @@ -497,73 +478,22 @@ def get_user_by_id(user_id): return { "user_id": hit.user_id, "username": hit.username, - "permission": hit.permission, + "permission": int(hit.permission), } return None except Exception as e: print(f"获取用户数据失败: {str(e)}") return None -def delete_user_by_username(username): - """ - 根据用户名删除用户 - - 参数: - username (str): 用户名 - - 返回: - bool: 删除成功返回True,失败返回False - """ - try: - search = UserDocument.search() - search = search.query("term", username=username) - response = search.execute() - - if response.hits: - user = response.hits[0] - user.delete() - print(f"用户 {username} 删除成功") - return True - return False - except Exception as e: - print(f"删除用户失败: {str(e)}") - return False - -def update_user_permission(username, new_permission): - """ - 更新用户权限 - - 参数: - username (str): 用户名 - new_permission (int): 新权限级别 - - 返回: - bool: 更新成功返回True,失败返回False - """ - try: - search = UserDocument.search() - search = search.query("term", username=username) - response = search.execute() - - if response.hits: - user = response.hits[0] - user.permission = new_permission - user.save() - print(f"用户 {username} 权限更新为 {new_permission}") - return True - return False - except Exception as e: - print(f"更新用户权限失败: {str(e)}") - return False - def delete_user_by_id(user_id): try: search = UserDocument.search() search = search.query("term", user_id=int(user_id)) response = search.execute() if response.hits: - user = response.hits[0] - user.delete() + hit = response.hits[0] + doc = UserDocument.get(id=hit.meta.id) + doc.delete() return True return False except Exception as e: @@ -576,14 +506,15 @@ def update_user_by_id(user_id, username=None, permission=None, password=None): search = search.query("term", user_id=int(user_id)) response = search.execute() if response.hits: - user = response.hits[0] + hit = response.hits[0] + doc = UserDocument.get(id=hit.meta.id) if username is not None: - user.username = username + doc.username = username if permission is not None: - user.permission = int(permission) + doc.permission = int(permission) if password is not None: - user.password = password - user.save() + doc.password = password + doc.save() return True return False except Exception as e: diff --git a/elastic/templates/elastic/users.html b/elastic/templates/elastic/users.html index 406dc68..b42a75f 100644 --- a/elastic/templates/elastic/users.html +++ b/elastic/templates/elastic/users.html @@ -407,8 +407,8 @@ users.forEach(user => { const row = document.createElement('tr'); - // 根据权限值显示权限名称 - const permissionText = user.permission === 0 ? '管理员' : '普通用户'; + // 根据权限值显示权限名称 + const permissionText = Number(user.permission) === 0 ? '管理员' : '普通用户'; row.innerHTML = ` ${user.user_id} @@ -496,9 +496,9 @@ let response; if (userId) { - // 更新用户 response = await fetch(`/elastic/users/${userId}/update/`, { method: 'POST', + credentials: 'same-origin', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrftoken @@ -506,9 +506,9 @@ body: JSON.stringify(data) }); } else { - // 添加用户 response = await fetch('/elastic/users/add/', { method: 'POST', + credentials: 'same-origin', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrftoken @@ -540,6 +540,7 @@ const csrftoken = getCookie('csrftoken'); const response = await fetch(`/elastic/users/${userId}/delete/`, { method: 'POST', + credentials: 'same-origin', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrftoken diff --git a/elastic/urls.py b/elastic/urls.py index 39ae962..785a437 100644 --- a/elastic/urls.py +++ b/elastic/urls.py @@ -22,10 +22,8 @@ urlpatterns = [ # 用户管理 path('users/', views.get_users, name='get_users'), path('users/add/', views.add_user, name='add_user'), - path('users//delete/', views.delete_user, name='delete_user'), - path('users//update/', views.update_user, name='update_user'), - path('users//delete/', views.delete_user_by_id_view, name='delete_user_by_id'), path('users//update/', views.update_user_by_id_view, name='update_user_by_id'), + path('users//delete/', views.delete_user_by_id_view, name='delete_user_by_id'), # 图片上传与确认 path('upload-page/', views.upload_page, name='upload_page'), diff --git a/elastic/views.py b/elastic/views.py index 19db34c..940d00a 100644 --- a/elastic/views.py +++ b/elastic/views.py @@ -13,7 +13,7 @@ from django.views.decorators.http import require_http_methods from django.views.decorators.csrf import ensure_csrf_cookie from django.views.decorators.csrf import csrf_exempt, ensure_csrf_cookie, csrf_protect from .es_connect import * -from openai import OpenAI +from .es_connect import update_user_by_id as es_update_user_by_id, delete_user_by_id as es_delete_user_by_id from PIL import Image @@ -107,7 +107,7 @@ def delete_data(request, doc_id): if not existing: return JsonResponse({"status": "error", "message": "数据不存在"}, status=404) - is_admin = (user_existing.get('permission') ) == 0 + is_admin = int(user_existing.get('permission')) == 0 is_owner = str(existing.get("writer_id", "")) == str(request.session.get("user_id")) if not (is_admin or is_owner): @@ -143,7 +143,7 @@ def update_data(request, doc_id): if not existing: return JsonResponse({"status": "error", "message": "数据不存在"}, status=404) - is_admin = (user_existing.get('permission')) == 0 + is_admin = int(user_existing.get('permission')) == 0 is_owner = str(existing.get("writer_id", "")) == str(request.session.get("user_id")) if not (is_admin or is_owner): @@ -188,7 +188,7 @@ def get_data(request, doc_id): def add_user(request): if request.session.get("user_id") is None: return JsonResponse({"status": "error", "message": "未登录"}, status=401) - if request.session.get("permission", 1) != 0: + if int(request.session.get("permission", 1)) != 0: return JsonResponse({"status": "error", "message": "无权限"}, status=403) try: payload = json.loads(request.body.decode("utf-8")) @@ -224,7 +224,7 @@ def add_user(request): def get_users(request): if request.session.get("user_id") is None: return JsonResponse({"status": "error", "message": "未登录"}, status=401) - if request.session.get("permission", 1) != 0: + if int(request.session.get("permission", 1)) != 0: return JsonResponse({"status": "error", "message": "无权限"}, status=403) try: q = (request.GET.get("search") or "").strip() @@ -236,41 +236,12 @@ def get_users(request): return JsonResponse({"status": "error", "message": str(e)}, status=500) -@require_http_methods(["DELETE"]) -@csrf_exempt -def delete_user(request, username): - """删除用户""" - try: - success = delete_user_by_username(username) - if success: - return JsonResponse({"status": "success", "message": "用户删除成功"}) - else: - return JsonResponse({"status": "error", "message": "用户删除失败"}, status=500) - except Exception as e: - return JsonResponse({"status": "error", "message": str(e)}, status=500) - - -@require_http_methods(["PUT"]) -@csrf_exempt -def update_user(request, username): - """更新用户权限""" - try: - data = json.loads(request.body.decode('utf-8')) - new_permission = int(data.get('permission', 1)) - success = update_user_permission(username, new_permission) - if success: - return JsonResponse({"status": "success", "message": "用户权限更新成功"}) - else: - return JsonResponse({"status": "error", "message": "用户权限更新失败"}, status=500) - except Exception as e: - return JsonResponse({"status": "error", "message": str(e)}, status=500) - @require_http_methods(["POST"]) @csrf_protect def update_user_by_id_view(request, user_id): if request.session.get("user_id") is None: return JsonResponse({"status": "error", "message": "未登录"}, status=401) - if request.session.get("permission", 1) != 0: + if int(request.session.get("permission", 1)) != 0: return JsonResponse({"status": "error", "message": "无权限"}, status=403) try: payload = json.loads(request.body.decode("utf-8")) @@ -285,7 +256,7 @@ def update_user_by_id_view(request, user_id): return JsonResponse({"status": "error", "message": "用户名已存在"}, status=409) if new_password and len(new_password) < 6: return JsonResponse({"status": "error", "message": "密码长度至少为6位"}, status=400) - ok = update_user_by_id( + ok = es_update_user_by_id( user_id, username=new_username if new_username else None, permission=int(new_permission) if new_permission is not None else None, @@ -300,9 +271,9 @@ def update_user_by_id_view(request, user_id): def delete_user_by_id_view(request, user_id): if request.session.get("user_id") is None: return JsonResponse({"status": "error", "message": "未登录"}, status=401) - if request.session.get("permission", 1) != 0: + if int(request.session.get("permission", 1)) != 0: return JsonResponse({"status": "error", "message": "无权限"}, status=403) - ok = delete_user_by_id(user_id) + ok = es_delete_user_by_id(user_id) if not ok: return JsonResponse({"status": "error", "message": "用户删除失败"}, status=500) return JsonResponse({"status": "success", "message": "用户删除成功"}) @@ -325,6 +296,7 @@ def string_to_json(s): # 移植自 a.py 的核心:调用大模型进行 OCR/信息抽取 def ocr_and_extract_info(image_path: str): + from openai import OpenAI def encode_image(path: str) -> str: with open(path, "rb") as f: return base64.b64encode(f.read()).decode("utf-8") @@ -519,7 +491,9 @@ def manage_page(request): from django.shortcuts import redirect return redirect("/accounts/login/") - # is_admin = (request.session.get("permission", 1) == 0) + if int(request.session.get("permission", 1)) != 0: + from django.shortcuts import redirect + return redirect("/main/home/") raw_results = search_all() # if not is_admin: # uid = str(session_user_id) @@ -544,7 +518,7 @@ def user_manage(request): if session_user_id is None: from django.shortcuts import redirect return redirect("/accounts/login/") - if request.session.get("permission", 1) != 0: + if int(request.session.get("permission", 1)) != 0: from django.shortcuts import redirect return redirect("/main/home/") user_id_qs = request.GET.get("user_id") diff --git a/main/views.py b/main/views.py index eaa6fd3..db02461 100644 --- a/main/views.py +++ b/main/views.py @@ -16,10 +16,18 @@ def home(request): perm = request.session.get("permission") if perm is None and uid is not None: u = get_user_by_id(uid) - perm = (u or {}).get("permission", 1) + try: + perm = int((u or {}).get("permission", 1)) + except Exception: + perm = 1 request.session["permission"] = perm + else: + try: + perm = int(perm) + except Exception: + perm = 1 context = { "user_id": uid, - "is_admin": (perm == 0), + "is_admin": (int(perm) == 0), } return render(request, "main/home.html", context) \ No newline at end of file