From 88f7fc7141ca9ad1a2359548b957c4e84baf2b09 Mon Sep 17 00:00:00 2001 From: MasonLiu <2857911564@qq.com> Date: Sat, 30 May 2026 15:06:24 +0800 Subject: [PATCH] =?UTF-8?q?bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/db_helper.php | 54 ++---- app/db_manager.py | 419 ++++++++++++++++++++++++---------------------- app/logger.php | 102 +++++++++++ app/logs/php.log | 0 app/monitor.py | 42 +---- index.php | 100 +++++------ mofangidc.php | 337 +++++++++++++++++++++++-------------- view_log.php | 351 ++++++++++++++++++++++++++++++++++++++ 8 files changed, 949 insertions(+), 456 deletions(-) create mode 100644 app/logger.php create mode 100644 app/logs/php.log create mode 100644 view_log.php diff --git a/app/db_helper.php b/app/db_helper.php index 113a23f..734e10a 100644 --- a/app/db_helper.php +++ b/app/db_helper.php @@ -1,21 +1,13 @@ dbPath = $dbPath; - // 确保目录存在 $dir = dirname($dbPath); if (!is_dir($dir)) { mkdir($dir, 0755, true); @@ -32,9 +24,6 @@ class DBHelper { /** * 执行查询并返回所有结果 - * @param string $sql SQL语句 - * @param array $params 参数数组 - * @return array 结果数组 */ public function query($sql, $params = []) { try { @@ -42,16 +31,13 @@ class DBHelper { $stmt->execute($params); return $stmt->fetchAll(); } catch (PDOException $e) { - error_log("数据库查询错误: " . $e->getMessage() . " | SQL: " . $sql); + Logger::error("数据库查询错误: " . $e->getMessage() . " | SQL: " . $sql, 'DBHelper::query'); return []; } } /** * 执行查询并返回单条结果 - * @param string $sql SQL语句 - * @param array $params 参数数组 - * @return array|false 结果数组或false */ public function queryOne($sql, $params = []) { try { @@ -59,32 +45,26 @@ class DBHelper { $stmt->execute($params); return $stmt->fetch(); } catch (PDOException $e) { - error_log("数据库查询错误: " . $e->getMessage() . " | SQL: " . $sql); + Logger::error("数据库查询错误: " . $e->getMessage() . " | SQL: " . $sql, 'DBHelper::queryOne'); return false; } } /** * 执行插入、更新、删除操作 - * @param string $sql SQL语句 - * @param array $params 参数数组 - * @return bool 是否成功 */ public function execute($sql, $params = []) { try { $stmt = $this->db->prepare($sql); return $stmt->execute($params); } catch (PDOException $e) { - error_log("数据库执行错误: " . $e->getMessage() . " | SQL: " . $sql); + Logger::error("数据库执行错误: " . $e->getMessage() . " | SQL: " . $sql, 'DBHelper::execute'); return false; } } /** * 插入数据并返回最后插入的ID - * @param string $sql SQL语句 - * @param array $params 参数数组 - * @return int|false 最后插入的ID或false */ public function insert($sql, $params = []) { try { @@ -92,36 +72,23 @@ class DBHelper { $stmt->execute($params); return $this->db->lastInsertId(); } catch (PDOException $e) { - error_log("数据库插入错误: " . $e->getMessage() . " | SQL: " . $sql); + Logger::error("数据库插入错误: " . $e->getMessage() . " | SQL: " . $sql, 'DBHelper::insert'); return false; } } - /** - * 开始事务 - */ public function beginTransaction() { return $this->db->beginTransaction(); } - /** - * 提交事务 - */ public function commit() { return $this->db->commit(); } - /** - * 回滚事务 - */ public function rollBack() { return $this->db->rollBack(); } - /** - * 获取数据库连接对象(用于高级操作) - * @return PDO - */ public function getConnection() { return $this->db; } @@ -133,7 +100,6 @@ function getVpsDB() { if ($db === null) { $dbPath = __DIR__ . '/db/vps.db'; $db = new DBHelper($dbPath); - // 初始化表结构 initVpsTables($db); } return $db; @@ -156,7 +122,6 @@ function getStatusDB() { if ($db === null) { $dbPath = __DIR__ . '/db/status.db'; $db = new DBHelper($dbPath); - // 初始化表结构 initStatusTables($db); } return $db; @@ -176,7 +141,8 @@ function initVpsTables($db) { api_key TEXT NOT NULL, auto_monitor BOOLEAN DEFAULT 1, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE(site_url, account) ) "); } @@ -199,15 +165,17 @@ function initVpsListTables($db) { bandwidth TEXT, os_type TEXT, status TEXT, + amount TEXT, + nextduedate INTEGER, section BOOLEAN DEFAULT 0, last_check TIMESTAMP, - FOREIGN KEY (config_id) REFERENCES configs(id), - UNIQUE(config_id, vps_id) + FOREIGN KEY (config_id) REFERENCES configs(id) ) "); $db->execute('CREATE INDEX IF NOT EXISTS idx_vps_config ON vps_list(config_id)'); $db->execute('CREATE INDEX IF NOT EXISTS idx_vps_vps_id ON vps_list(vps_id)'); + $db->execute('CREATE INDEX IF NOT EXISTS idx_vps_unique ON vps_list(vps_id, ip_address)'); } /** diff --git a/app/db_manager.py b/app/db_manager.py index 0631a19..aadb753 100644 --- a/app/db_manager.py +++ b/app/db_manager.py @@ -1,9 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -""" -VPS Hub 数据库管理模块 -负责初始化和管理三个SQLite数据库: vps.db, vpslist.db, status.db -""" +"""VPS Hub 数据库管理模块""" import os import sqlite3 @@ -14,38 +11,24 @@ class DatabaseManager: """数据库管理器""" def __init__(self, db_dir=None): - """初始化数据库管理器 - - Args: - db_dir: 数据库文件目录,默认为app/db/ - """ if db_dir is None: db_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'db') self.db_dir = db_dir os.makedirs(db_dir, exist_ok=True) - # 数据库文件路径 self.vps_db = os.path.join(db_dir, 'vps.db') self.vpslist_db = os.path.join(db_dir, 'vpslist.db') self.status_db = os.path.join(db_dir, 'status.db') - # 初始化所有数据库 self.init_vps_db() self.init_vpslist_db() self.init_status_db() def get_connection(self, db_path): - """获取数据库连接 - - Args: - db_path: 数据库文件路径 - - Returns: - SQLite连接对象 - """ + """获取数据库连接""" conn = sqlite3.connect(db_path) - conn.row_factory = sqlite3.Row # 使结果可以通过列名访问 + conn.row_factory = sqlite3.Row return conn def init_vps_db(self): @@ -63,7 +46,8 @@ class DatabaseManager: api_key TEXT NOT NULL, auto_monitor BOOLEAN DEFAULT 1, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE(site_url, account) ) ''') @@ -89,16 +73,17 @@ class DatabaseManager: bandwidth TEXT, os_type TEXT, status TEXT, + amount TEXT, + nextduedate INTEGER, section BOOLEAN DEFAULT 0, last_check TIMESTAMP, - FOREIGN KEY (config_id) REFERENCES configs(id), - UNIQUE(config_id, vps_id) + FOREIGN KEY (config_id) REFERENCES configs(id) ) ''') - # 创建索引以提高查询性能 cursor.execute('CREATE INDEX IF NOT EXISTS idx_vps_config ON vps_list(config_id)') cursor.execute('CREATE INDEX IF NOT EXISTS idx_vps_vps_id ON vps_list(vps_id)') + cursor.execute('CREATE INDEX IF NOT EXISTS idx_vps_unique ON vps_list(vps_id, ip_address)') conn.commit() conn.close() @@ -108,7 +93,6 @@ class DatabaseManager: conn = self.get_connection(self.status_db) cursor = conn.cursor() - # Ping状态记录表 cursor.execute(''' CREATE TABLE IF NOT EXISTS ping_status ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -120,7 +104,6 @@ class DatabaseManager: ) ''') - # VPS摘要统计表 cursor.execute(''' CREATE TABLE IF NOT EXISTS vps_summary ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -138,7 +121,6 @@ class DatabaseManager: ) ''') - # 创建索引 cursor.execute('CREATE INDEX IF NOT EXISTS idx_ping_vps ON ping_status(vps_id)') cursor.execute('CREATE INDEX IF NOT EXISTS idx_ping_time ON ping_status(check_time)') cursor.execute('CREATE INDEX IF NOT EXISTS idx_summary_vps ON vps_summary(vps_id)') @@ -150,23 +132,19 @@ class DatabaseManager: # ==================== vps.db 操作 ==================== def add_config(self, api_label, site_type, account, api_key, site_url=None, auto_monitor=True): - """添加VPS配置 - - Args: - api_label: API标识(必填,唯一) - site_type: 网站类型 (mofang/aliyun/tencent) - account: 账户 - api_key: API密钥 - site_url: 网站链接 - auto_monitor: 是否开启自动监控 - - Returns: - 新配置的ID - """ + """添加VPS配置,基于site_url和account去重""" conn = self.get_connection(self.vps_db) cursor = conn.cursor() try: + existing = cursor.execute( + 'SELECT id FROM configs WHERE site_url = ? AND account = ?', + (site_url, account) + ).fetchone() + + if existing: + return existing['id'] + cursor.execute(''' INSERT INTO configs (api_label, site_type, site_url, account, api_key, auto_monitor) VALUES (?, ?, ?, ?, ?, ?) @@ -182,11 +160,7 @@ class DatabaseManager: conn.close() def get_all_configs(self): - """获取所有配置 - - Returns: - 配置列表 - """ + """获取所有配置""" conn = self.get_connection(self.vps_db) cursor = conn.cursor() @@ -197,14 +171,7 @@ class DatabaseManager: return configs def get_config_by_id(self, config_id): - """根据ID获取配置 - - Args: - config_id: 配置ID - - Returns: - 配置字典或None - """ + """根据ID获取配置""" conn = self.get_connection(self.vps_db) cursor = conn.cursor() @@ -215,22 +182,13 @@ class DatabaseManager: return dict(row) if row else None def update_config(self, config_id, **kwargs): - """更新配置 - - Args: - config_id: 配置ID - **kwargs: 要更新的字段 - - Returns: - 是否成功 - """ + """更新配置""" if not kwargs: return False conn = self.get_connection(self.vps_db) cursor = conn.cursor() - # 构建UPDATE语句 fields = ', '.join([f"{key} = ?" for key in kwargs.keys()]) values = list(kwargs.values()) values.append(config_id) @@ -244,14 +202,7 @@ class DatabaseManager: return affected > 0 def delete_config(self, config_id): - """删除配置 - - Args: - config_id: 配置ID - - Returns: - 是否成功 - """ + """删除配置""" conn = self.get_connection(self.vps_db) cursor = conn.cursor() @@ -263,30 +214,88 @@ class DatabaseManager: return affected > 0 + def reset_config_ids(self): + """重置configs表的ID序列,从1开始连续编号""" + conn = self.get_connection(self.vps_db) + cursor = conn.cursor() + + try: + cursor.execute('SELECT * FROM configs ORDER BY id') + configs = [dict(row) for row in cursor.fetchall()] + + if not configs: + return True + + cursor.execute('DROP TABLE IF EXISTS configs_backup') + cursor.execute(''' + CREATE TABLE configs_backup AS SELECT * FROM configs + ''') + + cursor.execute('DELETE FROM configs') + cursor.execute("DELETE FROM sqlite_sequence WHERE name='configs'") + + for config in configs: + cursor.execute(''' + INSERT INTO configs (api_label, site_type, site_url, account, api_key, auto_monitor, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + ''', ( + config['api_label'], + config['site_type'], + config['site_url'], + config['account'], + config['api_key'], + config['auto_monitor'], + config['created_at'], + config['updated_at'] + )) + + cursor.execute('DROP TABLE IF EXISTS configs_backup') + conn.commit() + return True + except Exception as e: + conn.rollback() + raise e + finally: + conn.close() + # ==================== vpslist.db 操作 ==================== - def add_vps(self, config_id, vps_id, domain=None, ip_address=None, - product_name=None, section=False): - """添加VPS到列表 - - Args: - config_id: 配置ID - vps_id: VPS在平台的ID - domain: 域名 - ip_address: IP地址 - product_name: 产品名称 - section: 是否标记为需要监控 - - Returns: - 新记录的ID - """ + def get_next_available_id(self): + """获取下一个可用的ID(填补空缺)""" conn = self.get_connection(self.vpslist_db) cursor = conn.cursor() - cursor.execute(''' - INSERT INTO vps_list (config_id, vps_id, domain, ip_address, product_name, section, last_check) - VALUES (?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) - ''', (config_id, vps_id, domain, ip_address, product_name, section)) + cursor.execute('SELECT id FROM vps_list ORDER BY id') + ids = [row['id'] for row in cursor.fetchall()] + conn.close() + + if not ids: + return 1 + + for i in range(1, max(ids) + 1): + if i not in ids: + return i + + return None + + def add_vps(self, config_id, vps_id, domain=None, ip_address=None, product_name=None, section=False, custom_id=None): + """添加VPS到列表,支持指定ID以填补空缺""" + conn = self.get_connection(self.vpslist_db) + cursor = conn.cursor() + + if custom_id is None: + custom_id = self.get_next_available_id() + + if custom_id: + cursor.execute(''' + INSERT INTO vps_list (id, config_id, vps_id, domain, ip_address, product_name, section, last_check) + VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) + ''', (custom_id, config_id, vps_id, domain, ip_address, product_name, section)) + else: + cursor.execute(''' + INSERT INTO vps_list (config_id, vps_id, domain, ip_address, product_name, section, last_check) + VALUES (?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) + ''', (config_id, vps_id, domain, ip_address, product_name, section)) record_id = cursor.lastrowid conn.commit() @@ -295,42 +304,68 @@ class DatabaseManager: return record_id def batch_add_vps(self, vps_list): - """批量添加VPS - - Args: - vps_list: VPS信息列表,每个元素是字典 - """ + """批量添加VPS,基于vps_id和ip_address去重""" conn = self.get_connection(self.vpslist_db) cursor = conn.cursor() - + for vps in vps_list: - cursor.execute(''' - INSERT OR REPLACE INTO vps_list - (config_id, vps_id, domain, ip_address, product_name, cpu_cores, memory_size, disk_size, bandwidth, os_type, section, last_check) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) - ''', ( - vps['config_id'], - vps['vps_id'], - vps.get('domain'), - vps.get('ip_address'), - vps.get('product_name'), - vps.get('cpu_cores'), - vps.get('memory_size'), - vps.get('disk_size'), - vps.get('bandwidth'), - vps.get('os_type'), - vps.get('section', False) - )) - + existing = cursor.execute( + 'SELECT id FROM vps_list WHERE vps_id = ? AND ip_address = ?', + (vps['vps_id'], vps.get('ip_address')) + ).fetchone() + + if existing: + continue + + custom_id = self.get_next_available_id() + + if custom_id: + cursor.execute(''' + INSERT INTO vps_list + (id, config_id, vps_id, domain, ip_address, product_name, cpu_cores, memory_size, disk_size, bandwidth, os_type, amount, nextduedate, section, last_check) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) + ''', ( + custom_id, + vps['config_id'], + vps['vps_id'], + vps.get('domain'), + vps.get('ip_address'), + vps.get('product_name'), + vps.get('cpu_cores'), + vps.get('memory_size'), + vps.get('disk_size'), + vps.get('bandwidth'), + vps.get('os_type'), + vps.get('amount'), + vps.get('nextduedate'), + vps.get('section', False) + )) + else: + cursor.execute(''' + INSERT INTO vps_list + (config_id, vps_id, domain, ip_address, product_name, cpu_cores, memory_size, disk_size, bandwidth, os_type, amount, nextduedate, section, last_check) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) + ''', ( + vps['config_id'], + vps['vps_id'], + vps.get('domain'), + vps.get('ip_address'), + vps.get('product_name'), + vps.get('cpu_cores'), + vps.get('memory_size'), + vps.get('disk_size'), + vps.get('bandwidth'), + vps.get('os_type'), + vps.get('amount'), + vps.get('nextduedate'), + vps.get('section', False) + )) + conn.commit() conn.close() def get_all_vps(self): - """获取所有VPS - - Returns: - VPS列表 - """ + """获取所有VPS""" conn = self.get_connection(self.vpslist_db) cursor = conn.cursor() @@ -341,14 +376,7 @@ class DatabaseManager: return vps_list def get_vps_by_config(self, config_id): - """根据配置ID获取VPS列表 - - Args: - config_id: 配置ID - - Returns: - VPS列表 - """ + """根据配置ID获取VPS列表""" conn = self.get_connection(self.vpslist_db) cursor = conn.cursor() @@ -359,15 +387,7 @@ class DatabaseManager: return vps_list def update_vps_details(self, vps_id, **kwargs): - """更新VPS详细信息 - - Args: - vps_id: VPS ID - **kwargs: 要更新的字段 - - Returns: - 是否成功 - """ + """更新VPS详细信息""" if not kwargs: return False @@ -387,23 +407,11 @@ class DatabaseManager: return affected > 0 def update_vps_status(self, vps_id, status): - """更新VPS状态 - - Args: - vps_id: VPS ID - status: 状态 (on/off/unknown) - - Returns: - 是否成功 - """ + """更新VPS状态""" return self.update_vps_details(vps_id, status=status) def get_monitored_vps(self): - """获取所有标记为需要监控的VPS - - Returns: - VPS列表 - """ + """获取所有标记为需要监控的VPS""" conn = self.get_connection(self.vpslist_db) cursor = conn.cursor() @@ -413,17 +421,61 @@ class DatabaseManager: conn.close() return vps_list + def reset_vps_list_ids(self): + """重置vps_list表的ID序列,从1开始连续编号""" + conn = self.get_connection(self.vpslist_db) + cursor = conn.cursor() + + try: + cursor.execute('SELECT * FROM vps_list ORDER BY id') + vps_items = [dict(row) for row in cursor.fetchall()] + + if not vps_items: + return True + + cursor.execute('DROP TABLE IF EXISTS vps_list_backup') + cursor.execute(''' + CREATE TABLE vps_list_backup AS SELECT * FROM vps_list + ''') + + cursor.execute('DELETE FROM vps_list') + cursor.execute("DELETE FROM sqlite_sequence WHERE name='vps_list'") + + for vps in vps_items: + cursor.execute(''' + INSERT INTO vps_list (config_id, vps_id, domain, ip_address, product_name, cpu_cores, memory_size, disk_size, bandwidth, os_type, amount, nextduedate, status, section, last_check) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ''', ( + vps['config_id'], + vps['vps_id'], + vps.get('domain'), + vps.get('ip_address'), + vps.get('product_name'), + vps.get('cpu_cores'), + vps.get('memory_size'), + vps.get('disk_size'), + vps.get('bandwidth'), + vps.get('os_type'), + vps.get('amount'), + vps.get('nextduedate'), + vps.get('status'), + vps.get('section', 0), + vps.get('last_check') + )) + + cursor.execute('DROP TABLE IF EXISTS vps_list_backup') + conn.commit() + return True + except Exception as e: + conn.rollback() + raise e + finally: + conn.close() + # ==================== status.db 操作 ==================== def save_ping_status(self, vps_id, target, status, latency_ms=None): - """保存Ping状态记录 - - Args: - vps_id: VPS ID - target: 目标(IP或域名) - status: 状态 (normal/abnormal) - latency_ms: 延迟(ms) - """ + """保存Ping状态记录""" conn = self.get_connection(self.status_db) cursor = conn.cursor() @@ -436,15 +488,7 @@ class DatabaseManager: conn.close() def get_ping_records(self, vps_id, date=None): - """获取Ping记录 - - Args: - vps_id: VPS ID - date: 日期 (YYYY-MM-DD),为空则获取所有记录 - - Returns: - Ping记录列表 - """ + """获取Ping记录""" conn = self.get_connection(self.status_db) cursor = conn.cursor() @@ -467,11 +511,7 @@ class DatabaseManager: return records def cleanup_old_ping_records(self, days=30): - """清理旧的Ping记录 - - Args: - days: 保留天数,默认30天 - """ + """清理旧的Ping记录""" from datetime import timedelta conn = self.get_connection(self.status_db) @@ -489,20 +529,7 @@ class DatabaseManager: def save_vps_summary(self, vps_id, date, avg_latency, max_latency, min_latency, count_under_100, count_100_to_300, count_300_to_500, count_abnormal, availability): - """保存VPS摘要统计 - - Args: - vps_id: VPS ID - date: 日期 (YYYY-MM-DD) - avg_latency: 平均延迟 - max_latency: 最大延迟 - min_latency: 最小延迟 - count_under_100: <100ms次数 - count_100_to_300: 100-300ms次数 - count_300_to_500: 300-500ms次数 - count_abnormal: 异常次数 - availability: 可用性评分 - """ + """保存VPS摘要统计""" conn = self.get_connection(self.status_db) cursor = conn.cursor() @@ -519,15 +546,7 @@ class DatabaseManager: conn.close() def get_vps_summary(self, vps_id, date=None): - """获取VPS摘要统计 - - Args: - vps_id: VPS ID - date: 日期,为空则获取最新一条 - - Returns: - 摘要统计字典或None - """ + """获取VPS摘要统计""" conn = self.get_connection(self.status_db) cursor = conn.cursor() @@ -542,21 +561,13 @@ class DatabaseManager: return dict(row) if row else None def get_all_summaries(self, date=None): - """获取所有VPS的摘要统计 - - Args: - date: 日期,为空则获取最新 - - Returns: - 摘要统计列表 - """ + """获取所有VPS的摘要统计""" conn = self.get_connection(self.status_db) cursor = conn.cursor() if date: cursor.execute('SELECT * FROM vps_summary WHERE date = ? ORDER BY vps_id', (date,)) else: - # 获取每个VPS的最新摘要 cursor.execute(''' SELECT vs.* FROM vps_summary vs INNER JOIN ( diff --git a/app/logger.php b/app/logger.php new file mode 100644 index 0000000..daed2e8 --- /dev/null +++ b/app/logger.php @@ -0,0 +1,102 @@ + diff --git a/app/logs/php.log b/app/logs/php.log new file mode 100644 index 0000000..e69de29 diff --git a/app/monitor.py b/app/monitor.py index a6e7fde..9acb35a 100644 --- a/app/monitor.py +++ b/app/monitor.py @@ -1,9 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -""" -VPS Hub 多平台监控程序 -功能:支持多平台(魔方/阿里云/腾讯云)的VPS监控、自动开机和可用性统计 -""" +"""VPS Hub 多平台监控程序""" import os import sys @@ -16,7 +13,6 @@ import schedule from datetime import datetime, timedelta from pathlib import Path -# 导入数据库管理器 from db_manager import DatabaseManager @@ -28,42 +24,13 @@ class PlatformAdapter: self.account = account self.api_key = api_key self.jwt_token = None - - def login(self): - """登录获取Token - 需要子类实现""" - raise NotImplementedError - - def get_vps_list(self): - """获取VPS列表 - 需要子类实现""" - raise NotImplementedError - - def get_vps_status(self, vps_id): - """获取VPS状态 - 需要子类实现""" - raise NotImplementedError - - def get_vps_details(self, vps_id): - """获取VPS详细信息 - 需要子类实现""" - raise NotImplementedError - - def power_on(self, vps_id): - """开机 - 需要子类实现""" - raise NotImplementedError - - def power_off(self, vps_id): - """关机 - 需要子类实现""" - raise NotImplementedError - - def hard_reboot(self, vps_id): - """硬重启 - 需要子类实现""" - raise NotImplementedError class MofangAdapter(PlatformAdapter): - """魔方平台适配器(核云IDC等使用此适配器)""" + """魔方平台适配器""" def __init__(self, site_url, account, api_key): super().__init__(site_url, account, api_key) - # 魔方平台的API路径统一为 /v1 if not self.site_url: raise ValueError("魔方平台必须提供网站链接(API地址)") @@ -79,7 +46,6 @@ class MofangAdapter(PlatformAdapter): def login(self): try: - # 魔方平台API统一在 /v1 路径下 url = f"{self.site_url}/v1/login_api" data = { 'account': self.account, @@ -729,7 +695,9 @@ class MonitorService: 'disk_size': disk_size, 'bandwidth': bandwidth, 'os_type': os_type, - 'section': config['auto_monitor'] # 根据配置的auto_monitor设置 + 'amount': host.get('amount'), + 'nextduedate': host.get('nextduedate'), + 'section': config['auto_monitor'] }) # 批量添加到数据库 diff --git a/index.php b/index.php index 1b24421..1a47463 100644 --- a/index.php +++ b/index.php @@ -1,5 +1,6 @@ query('SELECT * FROM configs ORDER BY id'); -// 构建配置ID到配置的映射 +// 构建配置ID到api_label的映射 $configMap = []; foreach ($configs as $config) { - $configMap[$config['id']] = $config; + $configMap[$config['id']] = $config['api_label']; } -// 获取所有VPS列表(只从vpslist.db查询) +// 获取所有VPS列表(从vpslist.db查询) $listDb = getVpsListDB(); $vpsList = $listDb->query('SELECT * FROM vps_list ORDER BY config_id, vps_id'); -// 为每个VPS添加site_type和site_url信息 +// 为每个VPS添加api_label foreach ($vpsList as &$vps) { $configId = $vps['config_id']; - if (isset($configMap[$configId])) { - $vps['site_type'] = $configMap[$configId]['site_type']; - // 修正site_url:移除末尾的/v1或/v1/ - $siteUrl = $configMap[$configId]['site_url']; - $siteUrl = rtrim($siteUrl, '/'); // 移除末尾的 / - if (substr($siteUrl, -3) === '/v1') { - $siteUrl = substr($siteUrl, 0, -3); // 移除 /v1 - } - $vps['site_url'] = $siteUrl; - } else { - $vps['site_type'] = 'unknown'; - $vps['site_url'] = ''; - } + $vps['api_label'] = $configMap[$configId] ?? 'Unknown'; } -unset($vps); // 解除引用 +unset($vps); -// 调试信息(临时) -error_log("Configs count: " . count($configs)); -error_log("VPS List count: " . count($vpsList)); +Logger::info("Total VPS count: " . count($vpsList), 'index.php'); if (!empty($vpsList)) { - error_log("First VPS: " . json_encode($vpsList[0])); + Logger::debug("First VPS: " . json_encode($vpsList[0]), 'index.php'); } -// 按配置分组 -$vpsByConfig = []; +// 按api_label分组 +$vpsByApiLabel = []; foreach ($vpsList as $vps) { - $configId = $vps['config_id']; - if (!isset($vpsByConfig[$configId])) { - $vpsByConfig[$configId] = []; + $apiLabel = $vps['api_label']; + if (!isset($vpsByApiLabel[$apiLabel])) { + $vpsByApiLabel[$apiLabel] = []; } - $vpsByConfig[$configId][] = $vps; + $vpsByApiLabel[$apiLabel][] = $vps; } // 统计信息 @@ -296,6 +283,15 @@ foreach ($vpsList as $vps) { .power-off { background-color: #dc3545; } + .power-process { + background-color: #ffc107; + box-shadow: 0 0 8px #ffc107; + animation: pulse 1.5s infinite; + } + @keyframes pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.5; } + } .power-unknown { background-color: #6c757d; } @@ -395,43 +391,37 @@ foreach ($vpsList as $vps) { - - '魔方平台', - 'aliyun' => '阿里云', - 'tencent' => '腾讯云' - ]; - $typeName = $typeMap[$config['site_type']] ?? $config['site_type']; - ?> + + $labelVps): ?>
此配置下暂无VPS,请点击"手动刷新VPS列表"获取
+此配置下暂无VPS,请点击“手动刷新VPS列表”获取
当系统运行时,日志将显示在这里
+