From 5153017a80d5bdab53e34d7b4e1eb6e39ae92f65 Mon Sep 17 00:00:00 2001 From: spdis Date: Mon, 17 Nov 2025 23:59:16 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=E7=A0=81=E7=AE=A1=E7=90=86=E5=8F=8A=E9=A1=B5=E9=9D=A2=E5=8A=A8?= =?UTF-8?q?=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- elastic/es_connect.py | 49 ++++++++++++++ .../templates/elastic/registration_codes.html | 65 +++++++++++++++++-- elastic/urls.py | 2 + elastic/views.py | 28 ++++++++ 4 files changed, 140 insertions(+), 4 deletions(-) diff --git a/elastic/es_connect.py b/elastic/es_connect.py index 9811560..9abac50 100644 --- a/elastic/es_connect.py +++ b/elastic/es_connect.py @@ -197,6 +197,55 @@ def get_registration_code(code: str): except Exception: return None +def list_registration_codes(): + try: + search = RegistrationCodeDocument.search() + body = { + "sort": [{"created_at": {"order": "desc"}}], + "query": {"exists": {"field": "code"}} + } + search = search.update_from_dict(body) + resp = search.execute() + out = [] + now = datetime.now(timezone.utc) + for hit in resp: + try: + if not getattr(hit, 'code', None): + continue + except Exception: + continue + exp = getattr(hit, 'expires_at', None) + try: + if hasattr(exp, 'isoformat'): + exp_dt = exp + else: + exp_dt = datetime.fromisoformat(str(exp)) + except Exception: + exp_dt = None + active = bool(exp_dt and exp_dt > now) + out.append({ + "code": getattr(hit, 'code', ''), + "keys": list(getattr(hit, 'keys', []) or []), + "manage_keys": list(getattr(hit, 'manage_keys', []) or []), + "created_at": getattr(hit, 'created_at', None), + "expires_at": getattr(hit, 'expires_at', None), + "created_by": getattr(hit, 'created_by', None), + "active": active, + }) + return out + except Exception: + return [] + +def revoke_registration_code(code: str): + try: + doc = RegistrationCodeDocument.get(id=str(code)) + now = datetime.now(timezone.utc).isoformat() + doc.expires_at = now + doc.save() + return True + except Exception: + return False + def get_doc_id(data): """ 根据数据内容生成唯一ID(用于去重) diff --git a/elastic/templates/elastic/registration_codes.html b/elastic/templates/elastic/registration_codes.html index 18c9e80..19146de 100644 --- a/elastic/templates/elastic/registration_codes.html +++ b/elastic/templates/elastic/registration_codes.html @@ -23,6 +23,14 @@ .notice.success { background:#d4edda; color:#155724; border:1px solid #c3e6cb; } .notice.error { background:#f8d7da; color:#721c24; border:1px solid #f5c6cb; } .code-box { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; padding:12px; border:1px solid #e5e7eb; border-radius:8px; background:#fafafa; margin-top:10px; } + .overlay { position:fixed; inset:0; background:rgba(0,0,0,0.25); display:flex; align-items:center; justify-content:center; z-index:2000; } + .spinner { width:42px; height:42px; border:4px solid #cbd5e1; border-top-color:#4f46e5; border-radius:50%; animation:spin 0.8s linear infinite; } + @keyframes spin { to { transform: rotate(360deg); } } + .fade-in { animation: fadeUp 0.25s ease-out; } + @keyframes fadeUp { from { opacity:0; transform: translateY(6px); } to { opacity:1; transform: translateY(0); } } + table tr:hover { background-color:#f3f4f6; transition: background-color 0.2s ease; } + .btn { transition: transform 0.1s ease, box-shadow 0.2s ease; } + .btn:hover { transform: translateY(-1px); box-shadow:0 6px 16px rgba(31,35,40,0.12); } {% csrf_token %} +
-
+

管理注册码

@@ -116,6 +149,30 @@
+
+
+
+

已生成的注册码

+
+ +
+
+ + + + + + + + + + + + + +
codekeysmanage_keys创建时间过期时间状态操作
+
+