From 0085c702666288f41297cf14ad7b9b0797869235 Mon Sep 17 00:00:00 2001 From: hz4th_coder Date: Mon, 1 Jun 2026 12:12:35 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=BB=9F=E4=B8=80=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E7=AE=A1=E7=90=86=20+=20Cron=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=90=8C=E6=AD=A5=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增配置导出/导入功能,支持一键下载和上传配置文件 - 配置文件包含:项目配置、外部服务、预警阈值、网页设置(对外IP、刷新间隔) - 预警阈值和网页设置保存到服务器端,不再使用localStorage - Cron任务同步改为清空旧任务,只同步当前账号实际存在的任务 - 新增API: /api/config/export, /api/config/import - 新增API: /api/web-settings, /api/alerts (增强版) - 优化前端:自动加载和保存网页设置 --- __pycache__/app.cpython-312.pyc | Bin 0 -> 192549 bytes alert_config.json | 12 ++ app.py | 366 +++++++++++++++++++++++++++++--- cron_manager.db | Bin 28672 -> 28672 bytes logs/app.log | 31 +++ logs/pdf-translate-web.log | 6 + 6 files changed, 384 insertions(+), 31 deletions(-) create mode 100644 __pycache__/app.cpython-312.pyc create mode 100644 alert_config.json create mode 100644 logs/pdf-translate-web.log diff --git a/__pycache__/app.cpython-312.pyc b/__pycache__/app.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9f9a0938700e3f8866a211a94ad01ce3c32a6580 GIT binary patch literal 192549 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 literal 0 HcmV?d00001 diff --git a/alert_config.json b/alert_config.json new file mode 100644 index 0000000..9002f40 --- /dev/null +++ b/alert_config.json @@ -0,0 +1,12 @@ +{ + "thresholds": { + "cpu": 75, + "memory": 80, + "disk": 85, + "interval": 60 + }, + "web_settings": { + "external_ip": "121.40.164.32", + "refresh_interval": 30 + } +} \ No newline at end of file diff --git a/app.py b/app.py index 7278620..c867f28 100644 --- a/app.py +++ b/app.py @@ -695,34 +695,34 @@ def api_cron_categories(): @app.route('/api/cron/sync', methods=['POST']) def api_cron_sync(): - """从系统 crontab 同步到数据库""" + """从系统 crontab 同步到数据库(清空旧的,只保留当前系统实际存在的)""" crons = get_system_crons() user_crons = [c for c in crons if c['source'] == 'user'] db = get_db() c = db.cursor() + # 清空数据库中的旧任务 + c.execute("DELETE FROM cron_history WHERE task_id IN (SELECT id FROM cron_tasks)") + c.execute("DELETE FROM cron_logs WHERE task_id IN (SELECT id FROM cron_tasks)") + c.execute("DELETE FROM cron_tasks") + synced_count = 0 for cron in user_crons: - # 检查是否已存在 - c.execute("SELECT id FROM cron_tasks WHERE expression = ? AND command = ?", (cron['expression'], cron['command'])) - existing = c.fetchone() + # 尝试从命令推断分类和名称 + name = guess_cron_name(cron['command']) + category = guess_cron_category(cron['command']) - if not existing: - # 尝试从命令推断分类和名称 - name = guess_cron_name(cron['command']) - category = guess_cron_category(cron['command']) - - c.execute('''INSERT INTO cron_tasks (name, expression, command, description, category, enabled) - VALUES (?, ?, ?, ?, ?, 1)''', - (name, cron['expression'], cron['command'], '', category)) - synced_count += 1 + c.execute('''INSERT INTO cron_tasks (name, expression, command, description, category, enabled) + VALUES (?, ?, ?, ?, ?, 1)''', + (name, cron['expression'], cron['command'], '', category)) + synced_count += 1 db.commit() - log_message(f"从系统 crontab 同步了 {synced_count} 个任务") + log_message(f"从系统 crontab 同步了 {synced_count} 个任务(已清空旧任务)") - return jsonify({'message': f'同步完成,新增 {synced_count} 个任务'}) + return jsonify({'message': f'同步完成,共 {synced_count} 个任务', 'count': synced_count}) # ==================== 系统资源监控 API ==================== @@ -929,6 +929,181 @@ def get_next_run_time(expression): return '无法计算' +# ==================== 配置管理 API ==================== + +CONFIG_FILE = 'config.json' + +def load_full_config(): + """加载完整配置(合并项目和预警配置)""" + # 加载 projects.json 完整数据 + try: + with open(PROJECTS_FILE, 'r', encoding='utf-8') as f: + projects_data = json.load(f) + except: + projects_data = {'server': {}, 'projects': [], 'external_services': []} + + # 加载预警配置 + alert_config = {} + if os.path.exists('alert_config.json'): + try: + with open('alert_config.json', 'r', encoding='utf-8') as f: + alert_config = json.load(f) + except: + pass + + # 合并配置 + config = { + "version": "1.0", + "exported_at": datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + "server": projects_data.get('server', {}), + "projects": projects_data.get('projects', []), + "external_services": projects_data.get('external_services', []), + "web_settings": { + "external_ip": alert_config.get('web_settings', {}).get('external_ip', '121.40.164.32'), + "refresh_interval": alert_config.get('web_settings', {}).get('refresh_interval', 30) + }, + "alerts": alert_config.get('alerts', alert_config) # 支持两种结构 + } + return config + +def save_full_config(config): + """保存完整配置""" + # 保存 projects 部分 + projects_data = { + "server": config.get('server', {}), + "projects": config.get('projects', []), + "external_services": config.get('external_services', []) + } + with open(PROJECTS_FILE, 'w', encoding='utf-8') as f: + json.dump(projects_data, f, ensure_ascii=False, indent=2) + + # 保存预警配置和网页设置 + alert_config = { + "web_settings": config.get('web_settings', {}), + "thresholds": config.get('alerts', {}).get('thresholds', config.get('alerts', {})) + } + with open('alert_config.json', 'w', encoding='utf-8') as f: + json.dump(alert_config, f, ensure_ascii=False, indent=2) + + return True + +@app.route('/api/config/export', methods=['GET']) +def api_config_export(): + """导出配置文件""" + try: + config = load_full_config() + return jsonify(config) + except Exception as e: + return jsonify({'error': str(e)}), 500 + +@app.route('/api/config/import', methods=['POST']) +def api_config_import(): + """导入配置文件""" + try: + config = request.get_json() + if not config: + return jsonify({'error': '无效的配置数据'}), 400 + + # 验证配置结构 + required_keys = ['server', 'projects'] + for key in required_keys: + if key not in config: + return jsonify({'error': f'缺少必要字段: {key}'}), 400 + + # 备份当前配置 + backup_time = datetime.now().strftime('%Y%m%d_%H%M%S') + if os.path.exists(PROJECTS_FILE): + shutil.copy(PROJECTS_FILE, f'{PROJECTS_FILE}.bak.{backup_time}') + if os.path.exists('alert_config.json'): + shutil.copy('alert_config.json', f'alert_config.json.bak.{backup_time}') + + # 保存新配置 + save_full_config(config) + + return jsonify({ + 'message': '配置导入成功', + 'projects_count': len(config.get('projects', [])), + 'services_count': len(config.get('external_services', [])) + }) + except Exception as e: + return jsonify({'error': str(e)}), 500 + +@app.route('/api/alerts', methods=['GET']) +def api_get_alerts(): + """获取预警配置""" + try: + if os.path.exists('alert_config.json'): + with open('alert_config.json', 'r', encoding='utf-8') as f: + return jsonify(json.load(f)) + return jsonify({}) + except Exception as e: + return jsonify({'error': str(e)}), 500 + +@app.route('/api/alerts', methods=['POST']) +def api_save_alerts(): + """保存预警配置""" + try: + config = request.get_json() + + # 加载现有配置 + existing_config = {} + if os.path.exists('alert_config.json'): + try: + with open('alert_config.json', 'r', encoding='utf-8') as f: + existing_config = json.load(f) + except: + pass + + # 合并配置(保留web_settings) + if 'thresholds' in config: + existing_config['thresholds'] = config['thresholds'] + if 'web_settings' in config: + existing_config['web_settings'] = config['web_settings'] + + with open('alert_config.json', 'w', encoding='utf-8') as f: + json.dump(existing_config, f, ensure_ascii=False, indent=2) + return jsonify({'message': '保存成功'}) + except Exception as e: + return jsonify({'error': str(e)}), 500 + +@app.route('/api/web-settings', methods=['GET']) +def api_get_web_settings(): + """获取网页设置""" + try: + if os.path.exists('alert_config.json'): + with open('alert_config.json', 'r', encoding='utf-8') as f: + config = json.load(f) + web_settings = config.get('web_settings', {}) + return jsonify(web_settings) + return jsonify({'external_ip': '121.40.164.32', 'refresh_interval': 30}) + except Exception as e: + return jsonify({'error': str(e)}), 500 + +@app.route('/api/web-settings', methods=['POST']) +def api_save_web_settings(): + """保存网页设置""" + try: + settings = request.get_json() + + # 加载现有配置 + existing_config = {} + if os.path.exists('alert_config.json'): + try: + with open('alert_config.json', 'r', encoding='utf-8') as f: + existing_config = json.load(f) + except: + pass + + # 更新网页设置 + existing_config['web_settings'] = settings + + with open('alert_config.json', 'w', encoding='utf-8') as f: + json.dump(existing_config, f, ensure_ascii=False, indent=2) + return jsonify({'message': '保存成功'}) + except Exception as e: + return jsonify({'error': str(e)}), 500 + + # ==================== 邮件通知 API ==================== @app.route('/api/email/send', methods=['POST']) @@ -1261,11 +1436,18 @@ HTML_TEMPLATE = '''

对外IP: - +
+ +
间隔: @@ -1962,24 +2144,50 @@ HTML_TEMPLATE = ''' } // 加载阈值设置 - function loadThresholds() { - const saved = localStorage.getItem('systemThresholds'); - if (saved) { - thresholds = JSON.parse(saved); - document.getElementById('thresholdCpu').value = thresholds.cpu || 80; - document.getElementById('thresholdMemory').value = thresholds.memory || 85; - document.getElementById('thresholdDisk').value = thresholds.disk || 90; - document.getElementById('thresholdInterval').value = thresholds.interval || 60; + async function loadThresholds() { + try { + const response = await fetch('/api/alerts'); + const config = await response.json(); + + if (config.thresholds) { + thresholds = config.thresholds; + document.getElementById('thresholdCpu').value = thresholds.cpu || 80; + document.getElementById('thresholdMemory').value = thresholds.memory || 85; + document.getElementById('thresholdDisk').value = thresholds.disk || 90; + document.getElementById('thresholdInterval').value = thresholds.interval || 60; + } + } catch (e) { + console.error('加载阈值配置失败:', e); } } // 保存阈值设置 - function saveThresholds() { + async function saveThresholds() { thresholds.cpu = parseInt(document.getElementById('thresholdCpu').value) || 80; thresholds.memory = parseInt(document.getElementById('thresholdMemory').value) || 85; thresholds.disk = parseInt(document.getElementById('thresholdDisk').value) || 90; thresholds.interval = parseInt(document.getElementById('thresholdInterval').value) || 60; - localStorage.setItem('systemThresholds', JSON.stringify(thresholds)); + + try { + // 先获取现有配置 + let config = {}; + try { + const response = await fetch('/api/alerts'); + config = await response.json(); + } catch (e) {} + + // 更新阈值 + config.thresholds = thresholds; + + // 保存到服务器 + await fetch('/api/alerts', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(config) + }); + } catch (e) { + console.error('保存阈值配置失败:', e); + } } // 桌面通知开关(已在外部声明 desktopNotifyEnabled) @@ -2278,9 +2486,19 @@ HTML_TEMPLATE = ''' } // IP 保存 - function saveExternalIp() { + async function saveExternalIp() { externalIp = document.getElementById('externalIp').value.trim(); - localStorage.setItem('externalIp', externalIp); + + try { + await fetch('/api/web-settings', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ external_ip: externalIp, refresh_interval: parseInt(document.getElementById('refreshInterval').value) || 30 }) + }); + } catch (e) { + console.error('保存失败:', e); + } + renderProjects(); } @@ -3360,6 +3578,64 @@ HTML_TEMPLATE = ''' } } + // 导出配置 + async function exportConfig() { + try { + const response = await fetch('/api/config/export'); + const config = await response.json(); + + // 创建下载文件 + const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `project-panel-config-${new Date().toISOString().slice(0,10)}.json`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + + alert('配置导出成功!'); + } catch (e) { + alert('导出失败: ' + e.message); + } + } + + // 导入配置 + async function importConfig(event) { + const file = event.target.files[0]; + if (!file) return; + + if (!confirm('导入配置将覆盖当前所有设置,是否继续?')) { + event.target.value = ''; + return; + } + + try { + const text = await file.text(); + const config = JSON.parse(text); + + const response = await fetch('/api/config/import', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(config) + }); + + const result = await response.json(); + + if (result.error) { + alert('导入失败: ' + result.error); + } else { + alert(`配置导入成功!\n项目数: ${result.projects_count}\n外部服务数: ${result.services_count}`); + location.reload(); + } + } catch (e) { + alert('导入失败: ' + e.message); + } + + event.target.value = ''; + } + function scrollToTop() { window.scrollTo({ top: 0, behavior: 'smooth' }); } function scrollToBottom() { window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }); } @@ -3382,15 +3658,43 @@ HTML_TEMPLATE = ''' // 初始化 loadProjects(); + loadWebSettings(); // 加载网页设置 - let refreshIntervalMs = parseInt(localStorage.getItem('refreshInterval') || '30') * 1000; - document.getElementById('refreshInterval').value = refreshIntervalMs / 1000; + let refreshIntervalMs = 30 * 1000; // 默认值 let refreshTimer = setInterval(() => { if (currentTab === 'projects') loadProjects(); }, refreshIntervalMs); + // 加载网页设置 + async function loadWebSettings() { + try { + const response = await fetch('/api/web-settings'); + const settings = await response.json(); + + if (settings.external_ip) { + externalIp = settings.external_ip; + document.getElementById('externalIp').value = settings.external_ip; + } + if (settings.refresh_interval) { + document.getElementById('refreshInterval').value = settings.refresh_interval; + clearInterval(refreshTimer); + refreshIntervalMs = settings.refresh_interval * 1000; + refreshTimer = setInterval(() => { if (currentTab === 'projects') loadProjects(); }, refreshIntervalMs); + } + } catch (e) { + console.error('加载网页设置失败:', e); + } + } + function updateRefreshInterval() { const seconds = Math.max(5, Math.min(300, parseInt(document.getElementById('refreshInterval').value) || 30)); document.getElementById('refreshInterval').value = seconds; - localStorage.setItem('refreshInterval', seconds); + + // 保存到服务器 + fetch('/api/web-settings', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ external_ip: externalIp, refresh_interval: seconds }) + }).catch(e => console.error('保存失败:', e)); + clearInterval(refreshTimer); refreshTimer = setInterval(() => { if (currentTab === 'projects') loadProjects(); }, seconds * 1000); } diff --git a/cron_manager.db b/cron_manager.db index 90ef91f2cf0fbdbfda5eec39ffea87cc8b1e14d7..671868c2b2a73faa1e5f1e2ea15b8589f30f5eae 100644 GIT binary patch delta 78 zcmZp8z}WDBae_1>_e2?IR&EBp-d`J2=JIc5bokG|Nr6RxgF%3Sflq`_WV4{dd;W<5 YteYI5g8bk3zrh421+Z*parnaz0F{&%6aWAK literal 28672 zcmeI4-EY%Y6u|AIZAjA(q#;!Zq298Ewm|AMDT8$rT2}(=)(=*K0I5>sI+w;Yv4icD z7POC~d}w2AFvi#zY^%fsLlYoP+F)J9zpkL{?I~hQiERhGm&o5n>pontVLuV{MgWr@}fQzgfrrQoGem z+rc+#$=RyvSC~4nuA#>7tE|3C4qyWUKmZ5;0U!VbfB+C!bp(d0sv6oG+2f)V$Kzsr zJSHfz6idn@YE0wR(c+P(doa=!ji8?X-H}7+(TZrG9~CRN=uKl{yj869H0zIYbOXW6Jcp4fT*;8JPA5P+8Uy3`GrtoOjYrPS>uc)OO znVT3V>O~`aBZFw)U{7Dy;9>M;xAn z?Wdh9>W>B^dm==3cVxezoZdgRg&2YMxOGx?dm8+H_H2{Q$7Dzmnfn!wQZmmxEl{X` zAd31A^!D0Xj$uV5yeyO@YDm0E(r$#u(+XB;I~}ooLXcA_UWzY*7RRcfh-uv}i_QqV zhDV4yE-J>7?ngzJu;t5Xtnek|80E4;hX=x9TP(=r9lf0#A`ZR`U6n_NHu1 zZSaP}bJJhX-^0n#zB5&gf;~`>Dd^do=ilf}s}!!Hz&Eh=MyiLoam(Lko+-q0Wv_ z&Qs%Kwl?M7uGJMTT)UmWIFr9{es+2~|G`vy5QPnGE%gvTf+YFN$0IKq#~3TI@3 zD#vFuIX27-qnUJDdV<qw1g~$OM8x<%E%H&?wo|tn2}U+G{2%!V^pf8MX3>7 zs=a=n$2r?uiY~*!a_kza=Sb}aVx_M6+*INE!~FFtb6;L8d~|d9dfJi3X}w{YSK^} zw52>dm)2j!%9u!^uSLM2`;$YBQ|YAyS(aa(-l;08_g<=ZTvSJ`4hGTAK**d^maDfj zGFn5`Df@9=Zqsv0p{3jc87tFwq|(Pc-fct?mkK?Chnbt3&QeRdtG3k*2xo z3O)8tdX3n7_hT|I8}nar@^r>tX)MK=ckwDGk%^ug3w5-$ceDj*VAD%VN43)SvPc*+ zqM9K$^vXorQMHT#?gVO@oldKk5Q~N}+{+x^>)muB@*BhZ{^_|3XN*+B9^0it?&Fmc zl9-n=>41<>NWv93A*Y5#tfxlii8A|k(&b||H0D&=H*@sb-Fn>ABFJfHW=CcMe1y*= zHI5fFag01H7!{LAl{4lV%hQXKry~N9yeWwv4ZlmuH|(-d?#co$d4rvOm!&aCrt@t6 z;pF^JKN!Z@!i9?owPWu3sPat?E^u#)^1j#lXUK5p=m{_9R=!c)er=mc9yrXzP4$zxtN}JVtx#{XhAm zf7pNk5C8%|00;m9AOHk_01yBIKmZ5;foGV2{!ji~^?xw+f08fQfB+Bx0zd!=00AHX z1b_e#00KY&2mpa+h(M*AWqmHU+w0Zu|Ka`rGh|v&1qc8EAOHk_01yBIKmZ5;0U!Vb JfItZX{{R|{b?^WH diff --git a/logs/app.log b/logs/app.log index 6da08d6..b0eb8fd 100644 --- a/logs/app.log +++ b/logs/app.log @@ -30271,3 +30271,34 @@ Press CTRL+C to quit 192.168.2.8 - - [24/Apr/2026 10:48:24] "GET /api/projects HTTP/1.1" 200 - 127.0.0.1 - - [24/Apr/2026 10:48:27] "GET / HTTP/1.1" 200 - 192.168.2.14 - - [24/Apr/2026 10:48:28] "GET /api/projects HTTP/1.1" 200 - +[2026-06-01 11:53:42] ⚠️ 进程收到 SIGTERM 信号,即将退出! +[2026-06-01 11:53:43] ================================================== +[2026-06-01 11:53:43] 项目服务管理面板 v2.0.0 启动 +[2026-06-01 11:53:43] 访问地址: http://localhost:16022 +[2026-06-01 11:53:43] 进程PID: 776708 +[2026-06-01 11:53:43] ================================================== +[2026-06-01 11:56:06] ⚠️ 进程收到 SIGTERM 信号,即将退出! +[2026-06-01 11:56:07] ================================================== +[2026-06-01 11:56:07] 项目服务管理面板 v2.0.0 启动 +[2026-06-01 11:56:07] 访问地址: http://localhost:16022 +[2026-06-01 11:56:07] 进程PID: 777176 +[2026-06-01 11:56:07] ================================================== +[2026-06-01 12:01:26] ⚠️ 进程收到 SIGTERM 信号,即将退出! +[2026-06-01 12:01:28] ================================================== +[2026-06-01 12:01:28] 项目服务管理面板 v2.0.0 启动 +[2026-06-01 12:01:28] 访问地址: http://localhost:16022 +[2026-06-01 12:01:28] 进程PID: 778445 +[2026-06-01 12:01:28] ================================================== +[2026-06-01 12:02:47] ⚠️ 进程收到 SIGTERM 信号,即将退出! +[2026-06-01 12:02:49] ================================================== +[2026-06-01 12:02:49] 项目服务管理面板 v2.0.0 启动 +[2026-06-01 12:02:49] 访问地址: http://localhost:16022 +[2026-06-01 12:02:49] 进程PID: 778757 +[2026-06-01 12:02:49] ================================================== +[2026-06-01 12:11:08] ⚠️ 进程收到 SIGTERM 信号,即将退出! +[2026-06-01 12:11:34] ================================================== +[2026-06-01 12:11:34] 项目服务管理面板 v2.0.0 启动 +[2026-06-01 12:11:34] 访问地址: http://localhost:16022 +[2026-06-01 12:11:34] 进程PID: 780597 +[2026-06-01 12:11:34] ================================================== +[2026-06-01 12:12:13] 从系统 crontab 同步了 0 个任务(已清空旧任务) diff --git a/logs/pdf-translate-web.log b/logs/pdf-translate-web.log new file mode 100644 index 0000000..cbfa2c8 --- /dev/null +++ b/logs/pdf-translate-web.log @@ -0,0 +1,6 @@ + +================================================== +[2026-06-01T11:59:52.266560] start +Command: mkdir -p logs && nohup /home/hz1/miniconda3/envs/openclaw/bin/python3.12 app.py > logs/app.log 2>&1 & disown +Directory: /home/openclaw/.openclaw/workspace-hz4th_coder/works/pdf-translate-web +/bin/sh: 1: disown: not found