BUG修复:添加分离式刷新按钮
This commit is contained in:
parent
ec5c2db848
commit
00617621f9
@ -195,13 +195,18 @@ function getAliyunRegions($configId) {
|
||||
*/
|
||||
function getAliyunSwasRegions($configId) {
|
||||
return [
|
||||
'cn-hangzhou', // 华东1(杭州)
|
||||
'cn-shanghai', // 华东2(上海)
|
||||
'cn-qingdao', // 华北1(青岛)
|
||||
'cn-beijing', // 华北2(北京)
|
||||
'cn-zhangjiakou', // 华北3(张家口)
|
||||
'cn-huhehaote', // 华北5(呼和浩特)
|
||||
'cn-wulanchabu', // 华北6(乌兰察布)
|
||||
'cn-hangzhou', // 华东1(杭州)
|
||||
'cn-shanghai', // 华东2(上海)
|
||||
'cn-nanjing', // 华东5(南京)
|
||||
'cn-fuzhou', // 华东6(福州)
|
||||
'cn-shenzhen', // 华南1(深圳)
|
||||
'cn-heyuan', // 华南2(河源)
|
||||
'cn-guangzhou', // 华南3(广州)
|
||||
'cn-chengdu', // 西南1(成都)
|
||||
'cn-hongkong', // 中国香港
|
||||
'ap-southeast-1', // 新加坡
|
||||
|
||||
@ -141,10 +141,61 @@ 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,
|
||||
UNIQUE(site_url, account)
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
");
|
||||
|
||||
// 迁移:如果存在旧的UNIQUE约束,需要重建表
|
||||
migrateConfigsTable($db);
|
||||
}
|
||||
|
||||
/**
|
||||
* 迁移configs表,删除UNIQUE(site_url, account)约束
|
||||
* 允许同一个源添加多个不同的AccessKey
|
||||
*/
|
||||
function migrateConfigsTable($db) {
|
||||
try {
|
||||
// 检查是否存在旧的唯一约束
|
||||
$result = $db->query("PRAGMA index_list(configs)");
|
||||
$hasOldConstraint = false;
|
||||
|
||||
foreach ($result as $index) {
|
||||
if (isset($index['name']) && strpos($index['name'], 'site_url') !== false) {
|
||||
$hasOldConstraint = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($hasOldConstraint) {
|
||||
// 需要迁移:创建新表 -> 复制数据 -> 删除旧表 -> 重命名
|
||||
$db->execute("ALTER TABLE configs RENAME TO configs_old");
|
||||
|
||||
$db->execute("
|
||||
CREATE TABLE configs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
api_label TEXT NOT NULL UNIQUE,
|
||||
site_type TEXT NOT NULL,
|
||||
site_url TEXT,
|
||||
account TEXT NOT NULL,
|
||||
api_key TEXT NOT NULL,
|
||||
auto_monitor BOOLEAN DEFAULT 1,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
");
|
||||
|
||||
$db->execute("
|
||||
INSERT INTO configs (id, api_label, site_type, site_url, account, api_key, auto_monitor, created_at, updated_at)
|
||||
SELECT id, api_label, site_type, site_url, account, api_key, auto_monitor, created_at, updated_at
|
||||
FROM configs_old
|
||||
");
|
||||
|
||||
$db->execute("DROP TABLE configs_old");
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// 迁移失败不影响正常使用,记录日志即可
|
||||
error_log("[迁移警告] configs表迁移失败: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -9,33 +9,34 @@ from datetime import datetime
|
||||
|
||||
class DatabaseManager:
|
||||
"""数据库管理器"""
|
||||
|
||||
|
||||
def __init__(self, db_dir=None):
|
||||
if db_dir is None:
|
||||
db_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'db')
|
||||
|
||||
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):
|
||||
"""获取数据库连接"""
|
||||
conn = sqlite3.connect(db_path)
|
||||
conn.row_factory = sqlite3.Row
|
||||
return conn
|
||||
|
||||
|
||||
def init_vps_db(self):
|
||||
"""初始化vps.db - VPS配置表"""
|
||||
conn = self.get_connection(self.vps_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS configs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
@ -46,19 +47,18 @@ class DatabaseManager:
|
||||
api_key TEXT NOT NULL,
|
||||
auto_monitor BOOLEAN DEFAULT 1,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(site_url, account)
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
''')
|
||||
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
def init_vpslist_db(self):
|
||||
"""初始化vpslist.db - VPS列表缓存表"""
|
||||
conn = self.get_connection(self.vpslist_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS vps_list (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
@ -80,19 +80,22 @@ class DatabaseManager:
|
||||
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)')
|
||||
|
||||
|
||||
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()
|
||||
|
||||
|
||||
def init_status_db(self):
|
||||
"""初始化status.db - Ping状态记录和摘要统计表"""
|
||||
conn = self.get_connection(self.status_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS ping_status (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
@ -103,7 +106,7 @@ class DatabaseManager:
|
||||
check_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
''')
|
||||
|
||||
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS vps_summary (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
@ -120,36 +123,40 @@ class DatabaseManager:
|
||||
UNIQUE(vps_id, date)
|
||||
)
|
||||
''')
|
||||
|
||||
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)')
|
||||
cursor.execute('CREATE INDEX IF NOT EXISTS idx_summary_date ON vps_summary(date)')
|
||||
|
||||
|
||||
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)')
|
||||
cursor.execute(
|
||||
'CREATE INDEX IF NOT EXISTS idx_summary_date ON vps_summary(date)')
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
# ==================== vps.db 操作 ====================
|
||||
|
||||
|
||||
def add_config(self, api_label, site_type, account, api_key, site_url=None, auto_monitor=True):
|
||||
"""添加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 (?, ?, ?, ?, ?, ?)
|
||||
''', (api_label, site_type, site_url, account, api_key, auto_monitor))
|
||||
|
||||
|
||||
config_id = cursor.lastrowid
|
||||
conn.commit()
|
||||
return config_id
|
||||
@ -158,82 +165,83 @@ class DatabaseManager:
|
||||
raise e
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def get_all_configs(self):
|
||||
"""获取所有配置"""
|
||||
conn = self.get_connection(self.vps_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
||||
cursor.execute('SELECT * FROM configs ORDER BY id')
|
||||
configs = [dict(row) for row in cursor.fetchall()]
|
||||
|
||||
|
||||
conn.close()
|
||||
return configs
|
||||
|
||||
|
||||
def get_config_by_id(self, config_id):
|
||||
"""根据ID获取配置"""
|
||||
conn = self.get_connection(self.vps_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
||||
cursor.execute('SELECT * FROM configs WHERE id = ?', (config_id,))
|
||||
row = cursor.fetchone()
|
||||
|
||||
|
||||
conn.close()
|
||||
return dict(row) if row else None
|
||||
|
||||
|
||||
def update_config(self, config_id, **kwargs):
|
||||
"""更新配置"""
|
||||
if not kwargs:
|
||||
return False
|
||||
|
||||
|
||||
conn = self.get_connection(self.vps_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
||||
fields = ', '.join([f"{key} = ?" for key in kwargs.keys()])
|
||||
values = list(kwargs.values())
|
||||
values.append(config_id)
|
||||
|
||||
cursor.execute(f'UPDATE configs SET {fields}, updated_at = CURRENT_TIMESTAMP WHERE id = ?', values)
|
||||
|
||||
|
||||
cursor.execute(
|
||||
f'UPDATE configs SET {fields}, updated_at = CURRENT_TIMESTAMP WHERE id = ?', values)
|
||||
|
||||
affected = cursor.rowcount
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
return affected > 0
|
||||
|
||||
|
||||
def delete_config(self, config_id):
|
||||
"""删除配置"""
|
||||
conn = self.get_connection(self.vps_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
||||
cursor.execute('DELETE FROM configs WHERE id = ?', (config_id,))
|
||||
|
||||
|
||||
affected = cursor.rowcount
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
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)
|
||||
@ -248,7 +256,7 @@ class DatabaseManager:
|
||||
config['created_at'],
|
||||
config['updated_at']
|
||||
))
|
||||
|
||||
|
||||
cursor.execute('DROP TABLE IF EXISTS configs_backup')
|
||||
conn.commit()
|
||||
return True
|
||||
@ -257,35 +265,35 @@ class DatabaseManager:
|
||||
raise e
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
# ==================== vpslist.db 操作 ====================
|
||||
|
||||
|
||||
def get_next_available_id(self):
|
||||
"""获取下一个可用的ID(填补空缺)"""
|
||||
conn = self.get_connection(self.vpslist_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
||||
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)
|
||||
@ -296,29 +304,29 @@ class DatabaseManager:
|
||||
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()
|
||||
conn.close()
|
||||
|
||||
|
||||
return record_id
|
||||
|
||||
|
||||
def batch_add_vps(self, vps_list):
|
||||
"""批量添加VPS,基于vps_id和ip_address去重"""
|
||||
conn = self.get_connection(self.vpslist_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
||||
for vps in vps_list:
|
||||
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
|
||||
@ -360,87 +368,90 @@ class DatabaseManager:
|
||||
vps.get('nextduedate'),
|
||||
vps.get('section', False)
|
||||
))
|
||||
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
def get_all_vps(self):
|
||||
"""获取所有VPS"""
|
||||
conn = self.get_connection(self.vpslist_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
||||
cursor.execute('SELECT * FROM vps_list ORDER BY config_id, vps_id')
|
||||
vps_list = [dict(row) for row in cursor.fetchall()]
|
||||
|
||||
|
||||
conn.close()
|
||||
return vps_list
|
||||
|
||||
|
||||
def get_vps_by_config(self, config_id):
|
||||
"""根据配置ID获取VPS列表"""
|
||||
conn = self.get_connection(self.vpslist_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute('SELECT * FROM vps_list WHERE config_id = ? ORDER BY vps_id', (config_id,))
|
||||
|
||||
cursor.execute(
|
||||
'SELECT * FROM vps_list WHERE config_id = ? ORDER BY vps_id', (config_id,))
|
||||
vps_list = [dict(row) for row in cursor.fetchall()]
|
||||
|
||||
|
||||
conn.close()
|
||||
return vps_list
|
||||
|
||||
|
||||
def update_vps_details(self, vps_id, **kwargs):
|
||||
"""更新VPS详细信息"""
|
||||
if not kwargs:
|
||||
return False
|
||||
|
||||
|
||||
conn = self.get_connection(self.vpslist_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
||||
fields = ', '.join([f"{key} = ?" for key in kwargs.keys()])
|
||||
values = list(kwargs.values())
|
||||
values.append(vps_id)
|
||||
|
||||
cursor.execute(f'UPDATE vps_list SET {fields}, last_check = CURRENT_TIMESTAMP WHERE vps_id = ?', values)
|
||||
|
||||
|
||||
cursor.execute(
|
||||
f'UPDATE vps_list SET {fields}, last_check = CURRENT_TIMESTAMP WHERE vps_id = ?', values)
|
||||
|
||||
affected = cursor.rowcount
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
return affected > 0
|
||||
|
||||
|
||||
def update_vps_status(self, vps_id, status):
|
||||
"""更新VPS状态"""
|
||||
return self.update_vps_details(vps_id, status=status)
|
||||
|
||||
|
||||
def get_monitored_vps(self):
|
||||
"""获取所有标记为需要监控的VPS"""
|
||||
conn = self.get_connection(self.vpslist_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute('SELECT * FROM vps_list WHERE section = 1 ORDER BY config_id, vps_id')
|
||||
|
||||
cursor.execute(
|
||||
'SELECT * FROM vps_list WHERE section = 1 ORDER BY config_id, vps_id')
|
||||
vps_list = [dict(row) for row in cursor.fetchall()]
|
||||
|
||||
|
||||
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)
|
||||
@ -462,7 +473,7 @@ class DatabaseManager:
|
||||
vps.get('section', 0),
|
||||
vps.get('last_check')
|
||||
))
|
||||
|
||||
|
||||
cursor.execute('DROP TABLE IF EXISTS vps_list_backup')
|
||||
conn.commit()
|
||||
return True
|
||||
@ -471,27 +482,27 @@ class DatabaseManager:
|
||||
raise e
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
# ==================== status.db 操作 ====================
|
||||
|
||||
|
||||
def save_ping_status(self, vps_id, target, status, latency_ms=None):
|
||||
"""保存Ping状态记录"""
|
||||
conn = self.get_connection(self.status_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
||||
cursor.execute('''
|
||||
INSERT INTO ping_status (vps_id, target, status, latency_ms)
|
||||
VALUES (?, ?, ?, ?)
|
||||
''', (vps_id, target, status, latency_ms))
|
||||
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
def get_ping_records(self, vps_id, date=None):
|
||||
"""获取Ping记录"""
|
||||
conn = self.get_connection(self.status_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
||||
if date:
|
||||
cursor.execute('''
|
||||
SELECT * FROM ping_status
|
||||
@ -504,35 +515,37 @@ class DatabaseManager:
|
||||
WHERE vps_id = ?
|
||||
ORDER BY check_time DESC
|
||||
''', (vps_id,))
|
||||
|
||||
|
||||
records = [dict(row) for row in cursor.fetchall()]
|
||||
conn.close()
|
||||
|
||||
|
||||
return records
|
||||
|
||||
|
||||
def cleanup_old_ping_records(self, days=30):
|
||||
"""清理旧的Ping记录"""
|
||||
from datetime import timedelta
|
||||
|
||||
|
||||
conn = self.get_connection(self.status_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
cutoff_date = (datetime.now() - timedelta(days=days)).strftime('%Y-%m-%d %H:%M:%S')
|
||||
cursor.execute('DELETE FROM ping_status WHERE check_time < ?', (cutoff_date,))
|
||||
|
||||
|
||||
cutoff_date = (datetime.now() - timedelta(days=days)
|
||||
).strftime('%Y-%m-%d %H:%M:%S')
|
||||
cursor.execute(
|
||||
'DELETE FROM ping_status WHERE check_time < ?', (cutoff_date,))
|
||||
|
||||
deleted = cursor.rowcount
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
return deleted
|
||||
|
||||
|
||||
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):
|
||||
count_under_100, count_100_to_300, count_300_to_500,
|
||||
count_abnormal, availability):
|
||||
"""保存VPS摘要统计"""
|
||||
conn = self.get_connection(self.status_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
||||
cursor.execute('''
|
||||
INSERT OR REPLACE INTO vps_summary
|
||||
(vps_id, date, avg_latency_ms, max_latency_ms, min_latency_ms,
|
||||
@ -541,32 +554,35 @@ class DatabaseManager:
|
||||
''', (vps_id, date, avg_latency, max_latency, min_latency,
|
||||
count_under_100, count_100_to_300, count_300_to_500,
|
||||
count_abnormal, availability))
|
||||
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
def get_vps_summary(self, vps_id, date=None):
|
||||
"""获取VPS摘要统计"""
|
||||
conn = self.get_connection(self.status_db)
|
||||
cursor = conn.cursor()
|
||||
|
||||
|
||||
if date:
|
||||
cursor.execute('SELECT * FROM vps_summary WHERE vps_id = ? AND date = ?', (vps_id, date))
|
||||
cursor.execute(
|
||||
'SELECT * FROM vps_summary WHERE vps_id = ? AND date = ?', (vps_id, date))
|
||||
else:
|
||||
cursor.execute('SELECT * FROM vps_summary WHERE vps_id = ? ORDER BY date DESC LIMIT 1', (vps_id,))
|
||||
|
||||
cursor.execute(
|
||||
'SELECT * FROM vps_summary WHERE vps_id = ? ORDER BY date DESC LIMIT 1', (vps_id,))
|
||||
|
||||
row = cursor.fetchone()
|
||||
conn.close()
|
||||
|
||||
|
||||
return dict(row) if row else None
|
||||
|
||||
|
||||
def get_all_summaries(self, date=None):
|
||||
"""获取所有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,))
|
||||
cursor.execute(
|
||||
'SELECT * FROM vps_summary WHERE date = ? ORDER BY vps_id', (date,))
|
||||
else:
|
||||
cursor.execute('''
|
||||
SELECT vs.* FROM vps_summary vs
|
||||
@ -577,10 +593,10 @@ class DatabaseManager:
|
||||
) latest ON vs.vps_id = latest.vps_id AND vs.date = latest.max_date
|
||||
ORDER BY vs.vps_id
|
||||
''')
|
||||
|
||||
|
||||
summaries = [dict(row) for row in cursor.fetchall()]
|
||||
conn.close()
|
||||
|
||||
|
||||
return summaries
|
||||
|
||||
|
||||
|
||||
86
index.php
86
index.php
@ -87,8 +87,52 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$errorMsg = $result['error'] ?? $result['msg'] ?? '未知错误';
|
||||
$message = '<div class="error-message"><h3>❌ 操作失败</h3><p>' . htmlspecialchars($errorMsg) . '</p></div>';
|
||||
}
|
||||
} elseif ($action === 'refresh_single_config') {
|
||||
// 单独刷新某个配置
|
||||
$configId = intval($_POST['config_id'] ?? 0);
|
||||
|
||||
if ($configId > 0) {
|
||||
$configDb = getVpsDB();
|
||||
$config = $configDb->queryOne('SELECT * FROM configs WHERE id = ?', [$configId]);
|
||||
|
||||
if ($config) {
|
||||
$success = false;
|
||||
$typeName = '';
|
||||
|
||||
if ($config['site_type'] === 'mofang') {
|
||||
require_once __DIR__ . '/mofangidc.php';
|
||||
$success = refreshVpsListForConfig($configId);
|
||||
$typeName = '魔方平台';
|
||||
} elseif ($config['site_type'] === 'tencent') {
|
||||
require_once __DIR__ . '/tencentcloud.php';
|
||||
// 同时刷新CVM和轻量
|
||||
$cvmSuccess = refreshTencentCvmListForConfig($configId);
|
||||
$lhSuccess = refreshTencentLighthouseListForConfig($configId);
|
||||
$success = $cvmSuccess || $lhSuccess;
|
||||
$typeName = '腾讯云';
|
||||
} elseif ($config['site_type'] === 'aliyun') {
|
||||
require_once __DIR__ . '/aliyun.php';
|
||||
$success = refreshAliyunEcsListForConfig($configId);
|
||||
$typeName = '阿里云ECS';
|
||||
} elseif ($config['site_type'] === 'aliyun_swas') {
|
||||
require_once __DIR__ . '/aliyun.php';
|
||||
$success = refreshAliyunSwasListForConfig($configId);
|
||||
$typeName = '阿里云轻量';
|
||||
}
|
||||
|
||||
if ($success) {
|
||||
$message = '<div class="success-message"><h3>✅ 刷新成功</h3><p>已刷新配置「' . htmlspecialchars($config['api_label']) . '」(' . $typeName . ')的VPS列表</p></div>';
|
||||
} else {
|
||||
$message = '<div class="error-message"><h3>❌ 刷新失败</h3><p>配置「' . htmlspecialchars($config['api_label']) . '」刷新失败,请检查API凭证和网络连接</p></div>';
|
||||
}
|
||||
} else {
|
||||
$message = '<div class="error-message">❌ 配置不存在</div>';
|
||||
}
|
||||
} else {
|
||||
$message = '<div class="error-message">❌ 无效的配置ID</div>';
|
||||
}
|
||||
} elseif ($action === 'refresh_vps_list') {
|
||||
// 手动刷新VPS列表
|
||||
// 手动刷新VPS列表(全部)
|
||||
$count = 0;
|
||||
|
||||
// 刷新魔方平台的VPS列表
|
||||
@ -201,6 +245,12 @@ foreach ($vpsList as $vps) {
|
||||
$vpsByApiLabel[$apiLabel][] = $vps;
|
||||
}
|
||||
|
||||
// 构建api_label到config_id的映射(用于单独刷新)
|
||||
$apiLabelToConfigId = [];
|
||||
foreach ($configs as $config) {
|
||||
$apiLabelToConfigId[$config['api_label']] = $config['id'];
|
||||
}
|
||||
|
||||
// 统计信息
|
||||
$totalCount = count($vpsList);
|
||||
$runningCount = 0;
|
||||
@ -245,6 +295,11 @@ foreach ($vpsList as $vps) {
|
||||
.btn-refresh:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
.config-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
/* 消息自动消失动画 */
|
||||
.success-message, .error-message {
|
||||
transition: opacity 0.5s ease-out;
|
||||
@ -417,9 +472,9 @@ foreach ($vpsList as $vps) {
|
||||
|
||||
<!-- 工具栏 -->
|
||||
<div class="toolbar">
|
||||
<form method="POST" style="display: inline;">
|
||||
<form method="POST" style="display: inline;" onsubmit="return confirmRefreshAll()">
|
||||
<button type="submit" name="action" value="refresh_vps_list" class="btn-refresh">
|
||||
🔄 手动刷新VPS列表
|
||||
🔄 刷新全部列表
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@ -454,13 +509,21 @@ foreach ($vpsList as $vps) {
|
||||
<?php foreach ($vpsByApiLabel as $apiLabel => $labelVps): ?>
|
||||
<div class="config-section">
|
||||
<div class="config-title">
|
||||
<?php echo htmlspecialchars($apiLabel); ?>
|
||||
- <?php echo count($labelVps); ?> 台VPS
|
||||
<span>
|
||||
<?php echo htmlspecialchars($apiLabel); ?>
|
||||
- <?php echo count($labelVps); ?> 台VPS
|
||||
</span>
|
||||
<form method="POST" style="display: inline; margin-left: 15px;" onsubmit="return confirm('确认刷新此配置的VPS列表?')">
|
||||
<input type="hidden" name="config_id" value="<?php echo $apiLabelToConfigId[$apiLabel] ?? 0; ?>">
|
||||
<button type="submit" name="action" value="refresh_single_config" class="btn-refresh" style="padding: 5px 12px; font-size: 13px;">
|
||||
🔄 刷新此配置
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php if (empty($labelVps)): ?>
|
||||
<div class="empty-state" style="background: white; padding: 40px;">
|
||||
<p>此配置下暂无VPS,请点击“手动刷新VPS列表”获取</p>
|
||||
<p>此配置下暂无VPS,请点击右上角“🔄 刷新此配置”按钮获取</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="vps-grid">
|
||||
@ -627,6 +690,17 @@ foreach ($vpsList as $vps) {
|
||||
}, 5000); // 5秒后开始淡出
|
||||
});
|
||||
});
|
||||
|
||||
// 刷新全部列表确认
|
||||
function confirmRefreshAll() {
|
||||
return confirm('⚠️ 警告:资源消耗占用较高\n\n' +
|
||||
'刷新全部列表会同时请求所有配置的API,可能会导致:\n' +
|
||||
'• 页面卡顿或响应缓慢\n' +
|
||||
'• API超时导致报错中断\n' +
|
||||
'• 部分配置刷新失败\n\n' +
|
||||
'建议优先使用分离式刷新功能(点击每个配置右上角的🔄按钮)\n\n' +
|
||||
'确定要继续刷新全部列表吗?');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user