Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bb19141edc | |||
| c960048042 | |||
| 51f7ee9ad0 | |||
| ea904fb2b2 | |||
| 21240dc108 | |||
| 1d7f4c2bed | |||
| 88c11277cf | |||
| e5ae822ed2 |
10
README.md
10
README.md
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
## 版本信息
|
## 版本信息
|
||||||
|
|
||||||
- **当前版本**: v3.4.0
|
- **当前版本**: v3.4.1
|
||||||
- **端口**: 16022
|
- **端口**: 16022
|
||||||
- **更新日期**: 2026-06-01
|
- **更新日期**: 2026-06-01
|
||||||
|
|
||||||
@@ -158,7 +158,13 @@ python3 app_main.py
|
|||||||
|
|
||||||
## 更新日志
|
## 更新日志
|
||||||
|
|
||||||
### v3.4.0 (2026-06-01)
|
### v3.4.1 (2026-06-01)
|
||||||
|
- 🎯 **模块化重构**: 将 3700+ 行单文件拆分为多个模块
|
||||||
|
- 📁 **清晰结构**: config、database、utils、routes、templates 分离
|
||||||
|
- 🔧 **易于维护**: 每个模块职责明确,便于扩展和维护
|
||||||
|
- ✅ **功能完整**: 保留所有原有网页功能
|
||||||
|
|
||||||
|
### v3.4.0 (2026-06-01) [已废弃]
|
||||||
- 🎯 **模块化重构**: 将 3700+ 行单文件拆分为多个模块
|
- 🎯 **模块化重构**: 将 3700+ 行单文件拆分为多个模块
|
||||||
- 📁 **清晰结构**: config、database、utils、routes、templates 分离
|
- 📁 **清晰结构**: config、database、utils、routes、templates 分离
|
||||||
- 🔧 **易于维护**: 每个模块职责明确,便于扩展和维护
|
- 🔧 **易于维护**: 每个模块职责明确,便于扩展和维护
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -20,7 +20,7 @@ ALERT_CONFIG_FILE = 'alert_config.json'
|
|||||||
|
|
||||||
# 应用配置
|
# 应用配置
|
||||||
APP_NAME = "项目服务管理面板"
|
APP_NAME = "项目服务管理面板"
|
||||||
APP_VERSION = "v3.4.0"
|
APP_VERSION = "v3.4.1"
|
||||||
APP_PORT = 16022
|
APP_PORT = 16022
|
||||||
|
|
||||||
# 监控配置
|
# 监控配置
|
||||||
|
|||||||
14
logs/app.log
14
logs/app.log
@@ -30317,3 +30317,17 @@ Press CTRL+C to quit
|
|||||||
[2026-06-01 12:30:38] ⚠️ 进程收到 SIGTERM 信号,即将退出!
|
[2026-06-01 12:30:38] ⚠️ 进程收到 SIGTERM 信号,即将退出!
|
||||||
[2026-06-01 12:31:16] 项目服务管理面板 v3.4.0 初始化完成
|
[2026-06-01 12:31:16] 项目服务管理面板 v3.4.0 初始化完成
|
||||||
[2026-06-01 12:31:16] 启动 项目服务管理面板,端口: 16022
|
[2026-06-01 12:31:16] 启动 项目服务管理面板,端口: 16022
|
||||||
|
[2026-06-01 15:53:53] 项目服务管理面板 v3.4.0 初始化完成
|
||||||
|
[2026-06-01 15:53:53] 启动 项目服务管理面板,端口: 16022
|
||||||
|
[2026-06-01 15:55:35] 项目服务管理面板 v3.4.0 初始化完成
|
||||||
|
[2026-06-01 15:55:35] 启动 项目服务管理面板,端口: 16022
|
||||||
|
[2026-06-01 15:56:16] 项目服务管理面板 v3.4.0 初始化完成
|
||||||
|
[2026-06-01 15:56:16] 启动 项目服务管理面板,端口: 16022
|
||||||
|
[2026-06-01 15:57:03] 项目服务管理面板 v3.4.1 初始化完成
|
||||||
|
[2026-06-01 15:57:03] 启动 项目服务管理面板,端口: 16022
|
||||||
|
[2026-06-01 16:02:13] 项目服务管理面板 v3.4.1 初始化完成
|
||||||
|
[2026-06-01 16:02:13] 启动 项目服务管理面板,端口: 16022
|
||||||
|
[2026-06-01 16:02:39] 项目服务管理面板 v3.4.1 初始化完成
|
||||||
|
[2026-06-01 16:02:39] 启动 项目服务管理面板,端口: 16022
|
||||||
|
[2026-06-01 16:10:23] 项目服务管理面板 v3.4.1 初始化完成
|
||||||
|
[2026-06-01 16:10:23] 启动 项目服务管理面板,端口: 16022
|
||||||
|
|||||||
@@ -20,10 +20,25 @@ def register_project_routes(app):
|
|||||||
"""获取项目列表"""
|
"""获取项目列表"""
|
||||||
projects = load_projects()
|
projects = load_projects()
|
||||||
|
|
||||||
# 添加状态信息
|
# 添加状态信息(结构化对象,前端期望 status.status 和 status.ports)
|
||||||
for project in projects:
|
for project in projects:
|
||||||
ports = project.get('ports', [])
|
ports = project.get('ports', [])
|
||||||
project['status'] = 'running' if all(check_port(p) for p in ports) else 'stopped'
|
port_statuses = {}
|
||||||
|
for p in ports:
|
||||||
|
port_statuses[str(p)] = {'running': check_port(p)}
|
||||||
|
|
||||||
|
running_count = sum(1 for ps in port_statuses.values() if ps['running'])
|
||||||
|
if running_count == len(ports) and len(ports) > 0:
|
||||||
|
overall = 'running'
|
||||||
|
elif running_count > 0:
|
||||||
|
overall = 'partial'
|
||||||
|
else:
|
||||||
|
overall = 'stopped'
|
||||||
|
|
||||||
|
project['status'] = {
|
||||||
|
'status': overall,
|
||||||
|
'ports': port_statuses
|
||||||
|
}
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'projects': projects,
|
'projects': projects,
|
||||||
@@ -169,10 +184,25 @@ def register_project_routes(app):
|
|||||||
data = load_projects_full()
|
data = load_projects_full()
|
||||||
services = data.get('external_services', [])
|
services = data.get('external_services', [])
|
||||||
|
|
||||||
# 添加状态
|
# 添加状态(结构化对象,前端期望 status.status 和 status.ports)
|
||||||
for service in services:
|
for service in services:
|
||||||
ports = service.get('ports', [])
|
ports = service.get('ports', [])
|
||||||
service['status'] = 'running' if all(check_port(p) for p in ports) else 'stopped'
|
port_statuses = {}
|
||||||
|
for p in ports:
|
||||||
|
port_statuses[str(p)] = {'running': check_port(p)}
|
||||||
|
|
||||||
|
running_count = sum(1 for ps in port_statuses.values() if ps['running'])
|
||||||
|
if running_count == len(ports) and len(ports) > 0:
|
||||||
|
overall = 'running'
|
||||||
|
elif running_count > 0:
|
||||||
|
overall = 'partial'
|
||||||
|
else:
|
||||||
|
overall = 'stopped'
|
||||||
|
|
||||||
|
service['status'] = {
|
||||||
|
'status': overall,
|
||||||
|
'ports': port_statuses
|
||||||
|
}
|
||||||
|
|
||||||
return jsonify({'services': services})
|
return jsonify({'services': services})
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
from flask import jsonify
|
from datetime import datetime
|
||||||
|
from flask import jsonify, request
|
||||||
from utils import log_message, get_cpu_temperatures, load_alert_config
|
from utils import log_message, get_cpu_temperatures, load_alert_config
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -46,6 +47,7 @@ def register_system_routes(app):
|
|||||||
disk = psutil.disk_usage('/')
|
disk = psutil.disk_usage('/')
|
||||||
disk_total_gb = round(disk.total / (1024**3), 2)
|
disk_total_gb = round(disk.total / (1024**3), 2)
|
||||||
disk_used_gb = round(disk.used / (1024**3), 2)
|
disk_used_gb = round(disk.used / (1024**3), 2)
|
||||||
|
disk_free_gb = round(disk.free / (1024**3), 2)
|
||||||
disk_percent = disk.percent
|
disk_percent = disk.percent
|
||||||
|
|
||||||
# 网速(需要计算差值)
|
# 网速(需要计算差值)
|
||||||
@@ -82,10 +84,15 @@ def register_system_routes(app):
|
|||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'available': True,
|
'available': True,
|
||||||
|
'system': {
|
||||||
|
'uptime': uptime_str,
|
||||||
|
'boot_time': datetime.fromtimestamp(boot_time).strftime('%Y-%m-%d %H:%M:%S'),
|
||||||
|
'process_count': process_count
|
||||||
|
},
|
||||||
'cpu': {
|
'cpu': {
|
||||||
'percent': cpu_percent,
|
'percent': cpu_percent,
|
||||||
'count_physical': cpu_count,
|
'count': cpu_count,
|
||||||
'count_logical': cpu_count_logical,
|
'logical': cpu_count_logical,
|
||||||
'temp_package_0': cpu_temps.get('package_0'),
|
'temp_package_0': cpu_temps.get('package_0'),
|
||||||
'temp_package_1': cpu_temps.get('package_1')
|
'temp_package_1': cpu_temps.get('package_1')
|
||||||
},
|
},
|
||||||
@@ -98,17 +105,19 @@ def register_system_routes(app):
|
|||||||
'disk': {
|
'disk': {
|
||||||
'total_gb': disk_total_gb,
|
'total_gb': disk_total_gb,
|
||||||
'used_gb': disk_used_gb,
|
'used_gb': disk_used_gb,
|
||||||
|
'free_gb': disk_free_gb,
|
||||||
'percent': disk_percent
|
'percent': disk_percent
|
||||||
},
|
},
|
||||||
'network': {
|
'network': {
|
||||||
'upload_speed_kb': round(upload_speed, 2),
|
'sent_mb': round(net.bytes_sent / (1024**2), 2),
|
||||||
'download_speed_kb': round(download_speed, 2)
|
'recv_mb': round(net.bytes_recv / (1024**2), 2),
|
||||||
},
|
'sent_speed': round(upload_speed, 2),
|
||||||
'process_count': process_count,
|
'recv_speed': round(download_speed, 2)
|
||||||
'uptime': uptime_str
|
}
|
||||||
})
|
})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({'error': str(e)}), 500
|
log_message(f"系统监控API错误: {e}")
|
||||||
|
return jsonify({'error': str(e), 'available': False}), 500
|
||||||
|
|
||||||
@app.route('/api/system/processes')
|
@app.route('/api/system/processes')
|
||||||
def api_system_processes():
|
def api_system_processes():
|
||||||
@@ -117,6 +126,9 @@ def register_system_routes(app):
|
|||||||
return jsonify({'error': 'psutil未安装'}), 500
|
return jsonify({'error': 'psutil未安装'}), 500
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
limit = int(request.args.get('limit', 10))
|
||||||
|
limit = max(1, min(50, limit))
|
||||||
|
|
||||||
processes = []
|
processes = []
|
||||||
for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent', 'status']):
|
for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent', 'status']):
|
||||||
try:
|
try:
|
||||||
@@ -132,7 +144,7 @@ def register_system_routes(app):
|
|||||||
|
|
||||||
# 按CPU排序
|
# 按CPU排序
|
||||||
processes.sort(key=lambda x: x['cpu'], reverse=True)
|
processes.sort(key=lambda x: x['cpu'], reverse=True)
|
||||||
processes = processes[:50] # 只返回前50个
|
processes = processes[:limit]
|
||||||
|
|
||||||
return jsonify({'processes': processes})
|
return jsonify({'processes': processes})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -167,7 +179,6 @@ def register_system_routes(app):
|
|||||||
@app.route('/api/alerts', methods=['POST'])
|
@app.route('/api/alerts', methods=['POST'])
|
||||||
def api_save_alerts():
|
def api_save_alerts():
|
||||||
"""保存预警配置"""
|
"""保存预警配置"""
|
||||||
from flask import request
|
|
||||||
import json
|
import json
|
||||||
from config import ALERT_CONFIG_FILE
|
from config import ALERT_CONFIG_FILE
|
||||||
|
|
||||||
|
|||||||
@@ -16,9 +16,12 @@ def get_html_template():
|
|||||||
with open(template_file, 'r', encoding='utf-8') as f:
|
with open(template_file, 'r', encoding='utf-8') as f:
|
||||||
template_content = f.read()
|
template_content = f.read()
|
||||||
|
|
||||||
# 替换版本号
|
# 替换版本号(支持多种格式)
|
||||||
template_content = template_content.replace('v2.1', APP_VERSION)
|
template_content = template_content.replace('v2.1', APP_VERSION)
|
||||||
template_content = template_content.replace('v3.3.1', APP_VERSION)
|
template_content = template_content.replace('v3.3.1', APP_VERSION)
|
||||||
|
template_content = template_content.replace('v3.3.5', APP_VERSION)
|
||||||
|
template_content = template_content.replace('v3.4.0', APP_VERSION)
|
||||||
|
template_content = template_content.replace('v3.4.1', APP_VERSION) # 预留未来版本
|
||||||
|
|
||||||
return template_content
|
return template_content
|
||||||
except:
|
except:
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
# ==================== HTML 模板 ====================
|
<!DOCTYPE html>
|
||||||
|
|
||||||
HTML_TEMPLATE = '''<!DOCTYPE html>
|
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
@@ -2353,14 +2351,4 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
|||||||
}, 10000);
|
}, 10000);
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
os.makedirs(os.path.join(BASE_DIR, 'logs'), exist_ok=True)
|
|
||||||
os.makedirs(CRON_BACKUP_DIR, exist_ok=True)
|
|
||||||
init_db()
|
|
||||||
|
|
||||||
log_message("=" * 50)
|
|
||||||
log_message("项目服务管理面板 v2.0.0 启动")
|
|
||||||
Reference in New Issue
Block a user