BUG修复:添加分离式刷新按钮

This commit is contained in:
MasonLiu 2026-06-30 23:56:57 +08:00
parent ec5c2db848
commit 00617621f9
4 changed files with 287 additions and 141 deletions

View File

@ -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', // 新加坡

View File

@ -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());
}
}
/**

View File

@ -12,7 +12,8 @@ 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)
@ -46,8 +47,7 @@ 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
)
''')
@ -81,9 +81,12 @@ class DatabaseManager:
)
''')
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()
@ -121,10 +124,14 @@ 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)')
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()
@ -193,7 +200,8 @@ class DatabaseManager:
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()
@ -380,7 +388,8 @@ class DatabaseManager:
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()
@ -398,7 +407,8 @@ class DatabaseManager:
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()
@ -415,7 +425,8 @@ class DatabaseManager:
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()
@ -517,8 +528,10 @@ class DatabaseManager:
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()
@ -551,9 +564,11 @@ class DatabaseManager:
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()
@ -566,7 +581,8 @@ class DatabaseManager:
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

View File

@ -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">
<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>