仓库初始化

This commit is contained in:
lwt
2026-05-22 00:16:08 +08:00
commit 95c96dce42
118 changed files with 23005 additions and 0 deletions
View File
+50
View File
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
"""GUI logging setup."""
import logging
from datetime import datetime
def setup_logging():
"""配置日志系统。日志属于软件配置,与软件一起走(存于 AppData/ServerManager/logs)。"""
# 创建根日志器
logger = logging.getLogger('server_manager')
logger.setLevel(logging.DEBUG)
logger.propagate = False
if logger.handlers:
return logger
log_format = '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
date_format = '%Y-%m-%d %H:%M:%S'
# 控制台处理器 - 只记录警告及以上
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.WARNING)
console_handler.setFormatter(logging.Formatter(log_format, date_format))
logger.addHandler(console_handler)
try:
from models.app_config import get_app_log_dir
log_dir = get_app_log_dir()
log_file = log_dir / f"server_manager_{datetime.now().strftime('%Y%m%d')}.log"
file_handler = logging.FileHandler(log_file, encoding='utf-8')
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(logging.Formatter(log_format, date_format))
logger.addHandler(file_handler)
# 清理旧日志(保留最近7天)
try:
for old_log in log_dir.glob('server_manager_*.log'):
if old_log != log_file:
file_time = datetime.fromtimestamp(old_log.stat().st_mtime)
if (datetime.now() - file_time).days > 7:
old_log.unlink()
except Exception:
pass
except Exception:
pass
return logger
logger = setup_logging()
+15
View File
@@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
"""Recent project persistence helpers."""
from typing import List
def load_recent_projects() -> List[str]:
"""加载最近打开的项目路径列表(来自软件配置)"""
from models.app_config import get_recent_projects
return get_recent_projects()
def save_recent_project(project_path: str):
"""将项目路径加入软件配置的最近列表并保存"""
from models.app_config import save_recent_project as _save
_save(project_path)
+109
View File
@@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-
"""Shared imports and runtime dependencies for the GUI package."""
import sys
import os
import re
import json
import subprocess
import threading
import logging
import tempfile
import time
from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List, Optional, Tuple
SRC_DIR = Path(__file__).resolve().parents[1]
from services.commands import (
IS_WINDOWS,
ensure_and_get_server_manager_config_dir,
get_local_ip,
get_server_manager_config_dir,
get_ebin_paths,
get_erl_cmd,
get_escript_cmd,
get_rebar3_cmd,
run_cmd_in_new_window,
register_launched_window,
get_launched_windows,
close_launched_windows,
build_start_command,
build_start_command_by_config,
build_stop_command,
build_remsh_command,
subprocess_args_to_display,
read_config_file,
read_merged_config,
write_config_file,
replace_placeholders,
get_template_file,
build_replace_map,
generate_start_config,
run_startup_migrations,
get_config_list,
get_server_list,
query_remote_servers_from_login_rpc,
get_login_db_name,
get_node_status_cache,
check_nodes_status,
check_node_status,
REBAR3_CMD,
)
from services.server_creator import (
get_existing_server_ids,
create_server,
get_id_range_from_config,
get_default_port,
get_default_server_name,
build_confirmation_message,
generate_server_dir_name,
get_server_type_name,
get_allowed_config_keys,
get_required_keys,
get_template_config_keys,
SERVER_TYPE_MAP,
)
from services.hot_update import (
get_current_version,
get_version_info,
fetch_update_manifest,
version_less,
get_delta_for_current,
download_file as updater_download_file,
run_installer_and_exit,
apply_delta_patch,
clean_up_old_version,
)
from views.logs.log_viewer_tab import LogViewerTab
from PyQt6.QtWidgets import (
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QTabWidget, QLabel, QLineEdit, QPushButton, QTextEdit, QComboBox,
QGroupBox, QFormLayout, QSpinBox, QMessageBox, QFileDialog,
QSplitter, QFrame, QScrollArea, QCheckBox, QGridLayout,
QListWidget, QListWidgetItem, QDialog, QDialogButtonBox,
QProgressBar, QRadioButton, QButtonGroup, QDateTimeEdit,
QTableWidget, QTableWidgetItem, QHeaderView, QStackedWidget,
QProgressDialog, QAbstractItemView, QSizePolicy,
)
from PyQt6.QtCore import Qt, QThread, pyqtSignal, QTimer, QDateTime, QSize, QPointF, QByteArray, QEvent
from PyQt6.QtGui import (
QFont, QColor, QPalette, QIcon, QAction, QCursor,
QPainter, QPen, QBrush, QPixmap, QPolygonF,
)
from PyQt6.QtSvg import QSvgRenderer
from .logging import logger
def get_terminal_launch_options(config) -> Dict[str, str]:
"""Return the currently configured terminal launch options for new windows."""
return {
"terminal_mode": config.get("terminal", "launch_mode", default="auto"),
"terminal_exe_path": config.get("terminal", "exe_path", default=""),
}
+23
View File
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
"""Small GUI formatting helpers."""
import re
def node_host_only(value: str) -> str:
"""Return the host part for Erlang node strings like name@ip."""
text = str(value or '').strip().strip("'\"")
if '@' in text:
return text.rsplit('@', 1)[1].strip()
return text
def _server_id_sort_key(server_id) -> tuple:
"""服务器 ID 的稳定排序键,优先按数值升序。"""
text = str(server_id or "").strip()
try:
return (0, int(text), text)
except ValueError:
match = re.search(r"\d+", text)
if match:
return (0, int(match.group(0)), text)
return (1, 0, text)