From 696fcfa85d5f70281ef949c47dddc5a29cdc216a Mon Sep 17 00:00:00 2001 From: yuyx <237899745@qq.com> Date: Wed, 10 Dec 2025 21:42:28 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20=E6=B7=BB=E5=8A=A0=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E8=87=AA=E5=8A=A8=E5=AE=A1=E6=A0=B8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 系统配置新增:自动审核开关、每小时注册限制、赠送VIP天数 - 数据库:添加 auto_approve_enabled, auto_approve_hourly_limit, auto_approve_vip_days 字段 - 后端API:支持保存和读取自动审核配置 - 管理后台:新增注册自动审核配置区域(绿色背景) - 注册逻辑:支持自动审核通过并赠送VIP 功能说明: 1. 启用自动审核后,新用户注册自动通过,无需管理员审批 2. 每小时注册限制防止恶意注册 3. 可配置注册赠送VIP天数(设为0则不赠送) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- app.py | 41 +++++++++++++++++++++-- database.py | 48 ++++++++++++++++++++++++--- templates/admin.html | 78 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+), 6 deletions(-) diff --git a/app.py b/app.py index 42c21c3..5923cc3 100755 --- a/app.py +++ b/app.py @@ -460,9 +460,32 @@ def register(): return jsonify({"error": "验证码错误次数过多,IP已被锁定1小时"}), 429 return jsonify({"error": message}), 400 + # 获取自动审核配置 + system_config = database.get_system_config() + auto_approve_enabled = system_config.get('auto_approve_enabled', 0) == 1 + auto_approve_hourly_limit = system_config.get('auto_approve_hourly_limit', 10) + auto_approve_vip_days = system_config.get('auto_approve_vip_days', 7) + + # 检查每小时注册限制 + if auto_approve_enabled: + hourly_count = database.get_hourly_registration_count() + if hourly_count >= auto_approve_hourly_limit: + return jsonify({"error": f"注册人数过多,请稍后再试(每小时限制{auto_approve_hourly_limit}人)"}), 429 + user_id = database.create_user(username, password, email) if user_id: - return jsonify({"success": True, "message": "注册成功,请等待管理员审核"}) + # 自动审核处理 + if auto_approve_enabled: + # 自动审核通过 + database.approve_user(user_id) + # 赠送VIP天数 + if auto_approve_vip_days > 0: + database.set_user_vip(user_id, auto_approve_vip_days) + return jsonify({"success": True, "message": f"注册成功!已自动审核通过,赠送{auto_approve_vip_days}天VIP"}) + else: + return jsonify({"success": True, "message": "注册成功!已自动审核通过"}) + else: + return jsonify({"success": True, "message": "注册成功,请等待管理员审核"}) else: return jsonify({"error": "用户名已存在"}), 400 @@ -2320,6 +2343,9 @@ def update_system_config_api(): schedule_weekdays = data.get('schedule_weekdays') new_max_concurrent_per_account = data.get('max_concurrent_per_account') new_max_screenshot_concurrent = data.get('max_screenshot_concurrent') + auto_approve_enabled = data.get('auto_approve_enabled') + auto_approve_hourly_limit = data.get('auto_approve_hourly_limit') + auto_approve_vip_days = data.get('auto_approve_vip_days') # 验证参数 if max_concurrent is not None: @@ -2353,6 +2379,14 @@ def update_system_config_api(): except (ValueError, AttributeError): return jsonify({"error": "星期格式错误"}), 400 + if auto_approve_hourly_limit is not None: + if not isinstance(auto_approve_hourly_limit, int) or auto_approve_hourly_limit < 1: + return jsonify({"error": "每小时注册限制必须大于0"}), 400 + + if auto_approve_vip_days is not None: + if not isinstance(auto_approve_vip_days, int) or auto_approve_vip_days < 0: + return jsonify({"error": "注册赠送VIP天数不能为负数"}), 400 + # 更新数据库 if database.update_system_config( max_concurrent=max_concurrent, @@ -2361,7 +2395,10 @@ def update_system_config_api(): schedule_browse_type=schedule_browse_type, schedule_weekdays=schedule_weekdays, max_concurrent_per_account=new_max_concurrent_per_account, - max_screenshot_concurrent=new_max_screenshot_concurrent + max_screenshot_concurrent=new_max_screenshot_concurrent, + auto_approve_enabled=auto_approve_enabled, + auto_approve_hourly_limit=auto_approve_hourly_limit, + auto_approve_vip_days=auto_approve_vip_days ): # 如果修改了并发数,更新全局变量和信号量 if max_concurrent is not None and max_concurrent != max_concurrent_global: diff --git a/database.py b/database.py index cf08260..c823480 100755 --- a/database.py +++ b/database.py @@ -111,6 +111,9 @@ def init_database(): proxy_api_url TEXT DEFAULT '', proxy_expire_minutes INTEGER DEFAULT 3, enable_screenshot INTEGER DEFAULT 1, + auto_approve_enabled INTEGER DEFAULT 0, + auto_approve_hourly_limit INTEGER DEFAULT 10, + auto_approve_vip_days INTEGER DEFAULT 7, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ''') @@ -236,8 +239,9 @@ def init_database(): INSERT INTO system_config ( id, max_concurrent_global, max_concurrent_per_account, max_screenshot_concurrent, schedule_enabled, schedule_time, schedule_browse_type, schedule_weekdays, - proxy_enabled, proxy_api_url, proxy_expire_minutes, enable_screenshot - ) VALUES (1, 2, 1, 3, 0, '02:00', '应读', '1,2,3,4,5,6,7', 0, '', 3, 1) + proxy_enabled, proxy_api_url, proxy_expire_minutes, enable_screenshot, + auto_approve_enabled, auto_approve_hourly_limit, auto_approve_vip_days + ) VALUES (1, 2, 1, 3, 0, '02:00', '应读', '1,2,3,4,5,6,7', 0, '', 3, 1, 0, 10, 7) ''') conn.commit() print("✓ 已创建系统配置(默认并发2,定时任务关闭)") @@ -325,6 +329,15 @@ def _migrate_to_v1(conn): if 'max_concurrent_per_account' not in columns: cursor.execute('ALTER TABLE system_config ADD COLUMN max_concurrent_per_account INTEGER DEFAULT 1') print(" ✓ 添加 max_concurrent_per_account 字段") + if 'auto_approve_enabled' not in columns: + cursor.execute('ALTER TABLE system_config ADD COLUMN auto_approve_enabled INTEGER DEFAULT 0') + print(" ✓ 添加 auto_approve_enabled 字段") + if 'auto_approve_hourly_limit' not in columns: + cursor.execute('ALTER TABLE system_config ADD COLUMN auto_approve_hourly_limit INTEGER DEFAULT 10') + print(" ✓ 添加 auto_approve_hourly_limit 字段") + if 'auto_approve_vip_days' not in columns: + cursor.execute('ALTER TABLE system_config ADD COLUMN auto_approve_vip_days INTEGER DEFAULT 7') + print(" ✓ 添加 auto_approve_vip_days 字段") # 检查并添加 duration 字段到 task_logs cursor.execute("PRAGMA table_info(task_logs)") @@ -980,14 +993,18 @@ def get_system_config(): 'proxy_enabled': 0, 'proxy_api_url': '', 'proxy_expire_minutes': 3, - 'enable_screenshot': 1 + 'enable_screenshot': 1, + 'auto_approve_enabled': 0, + 'auto_approve_hourly_limit': 10, + 'auto_approve_vip_days': 7 } def update_system_config(max_concurrent=None, schedule_enabled=None, schedule_time=None, schedule_browse_type=None, schedule_weekdays=None, max_concurrent_per_account=None, max_screenshot_concurrent=None, proxy_enabled=None, - proxy_api_url=None, proxy_expire_minutes=None): + proxy_api_url=None, proxy_expire_minutes=None, + auto_approve_enabled=None, auto_approve_hourly_limit=None, auto_approve_vip_days=None): """更新系统配置""" with db_pool.get_db() as conn: cursor = conn.cursor() @@ -1034,6 +1051,18 @@ def update_system_config(max_concurrent=None, schedule_enabled=None, schedule_ti updates.append('proxy_expire_minutes = ?') params.append(proxy_expire_minutes) + if auto_approve_enabled is not None: + updates.append('auto_approve_enabled = ?') + params.append(auto_approve_enabled) + + if auto_approve_hourly_limit is not None: + updates.append('auto_approve_hourly_limit = ?') + params.append(auto_approve_hourly_limit) + + if auto_approve_vip_days is not None: + updates.append('auto_approve_vip_days = ?') + params.append(auto_approve_vip_days) + if updates: updates.append('updated_at = CURRENT_TIMESTAMP') sql = f"UPDATE system_config SET {', '.join(updates)} WHERE id = 1" @@ -1044,6 +1073,17 @@ def update_system_config(max_concurrent=None, schedule_enabled=None, schedule_ti return False +def get_hourly_registration_count(): + """获取最近一小时内的注册用户数""" + with db_pool.get_db() as conn: + cursor = conn.cursor() + cursor.execute(''' + SELECT COUNT(*) FROM users + WHERE created_at >= datetime('now', '-1 hour') + ''') + return cursor.fetchone()[0] + + # ==================== 任务日志管理 ==================== def create_task_log(user_id, account_id, username, browse_type, status, diff --git a/templates/admin.html b/templates/admin.html index c895f2e..99e320b 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -713,6 +713,42 @@ + + +
+

✅ 注册自动审核

+ +
+ +
+ 开启后,新用户注册将自动通过审核,无需管理员手动审批 +
+
+ +
+ + +
+ 限制每小时内最多允许注册的用户数量,防止恶意注册 +
+
+ +
+ + +
+ 新用户注册成功后自动赠送的VIP天数(设为0表示不赠送) +
+
+ +
+ +
+
+ @@ -1398,6 +1434,11 @@ // 显示/隐藏定时任务选项 toggleSchedule(config.schedule_enabled === 1); + + // 加载自动审核配置 + document.getElementById('autoApproveEnabled').checked = config.auto_approve_enabled === 1; + document.getElementById('autoApproveHourlyLimit').value = config.auto_approve_hourly_limit || 10; + document.getElementById('autoApproveVipDays').value = config.auto_approve_vip_days || 7; } } catch (error) { console.error('加载系统配置失败:', error); @@ -1471,6 +1512,43 @@ } } + async function saveAutoApproveConfig() { + const autoApproveEnabled = document.getElementById('autoApproveEnabled').checked ? 1 : 0; + const autoApproveHourlyLimit = parseInt(document.getElementById('autoApproveHourlyLimit').value) || 10; + const autoApproveVipDays = parseInt(document.getElementById('autoApproveVipDays').value) || 0; + + if (autoApproveHourlyLimit < 1) { + alert('❌ 每小时注册限制必须大于0'); + return; + } + + if (autoApproveVipDays < 0) { + alert('❌ VIP天数不能为负数'); + return; + } + + try { + const response = await fetch('/yuyx/api/system/config', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + auto_approve_enabled: autoApproveEnabled, + auto_approve_hourly_limit: autoApproveHourlyLimit, + auto_approve_vip_days: autoApproveVipDays + }) + }); + + const data = await response.json(); + if (data.message) { + showNotification('✓ 自动审核配置已保存', 'success'); + } else if (data.error) { + showNotification('✗ ' + data.error, 'error'); + } + } catch (error) { + showNotification('保存失败: ' + error.message, 'error'); + } + } + async function testProxy() { const apiUrl = document.getElementById('proxyApiUrl').value.trim();