425 lines
18 KiB
PHP
425 lines
18 KiB
PHP
<?php
|
||
/**
|
||
* VPS配置管理页面
|
||
* 用于添加和管理多平台VPS配置
|
||
*/
|
||
|
||
require_once __DIR__ . '/app/db_helper.php';
|
||
require_once __DIR__ . '/mofangidc.php';
|
||
|
||
// Token文件路径(存储API_PASS)
|
||
$tokenFile = __DIR__ . '/app/pass.php';
|
||
|
||
// 检查是否首次访问(需要设置API_PASS)
|
||
$needSetup = !file_exists($tokenFile);
|
||
|
||
// 处理API_PASS设置
|
||
if ($needSetup && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['setup_pass'])) {
|
||
$apiPass = trim($_POST['api_pass']);
|
||
|
||
if (empty($apiPass)) {
|
||
$setupError = '密码不能为空!';
|
||
} elseif (strlen($apiPass) < 8) {
|
||
$setupError = '密码至少8位!';
|
||
} elseif (!preg_match('/^[a-zA-Z0-9]+$/', $apiPass)) {
|
||
$setupError = '密码只能包含字母和数字!';
|
||
} else {
|
||
// 保存API_PASS
|
||
$content = "<?php\n";
|
||
$content .= "// API访问密码 - 自动生成\n";
|
||
$content .= "// 警告: 不要手动修改此文件\n\n";
|
||
$content .= "define('API_PASS', '" . addslashes($apiPass) . "');\n";
|
||
$content .= "?>\n";
|
||
|
||
if (file_put_contents($tokenFile, $content)) {
|
||
chmod($tokenFile, 0600);
|
||
header('Location: config_add.php?pass=' . urlencode($apiPass));
|
||
exit;
|
||
} else {
|
||
$setupError = '保存失败,请检查目录权限!';
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果需要设置密码,显示设置页面
|
||
if ($needSetup) {
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<link rel="shortcut icon" href="./static/favicon.ico" type="image/x-icon">
|
||
<link href="./static/initial.css" rel="stylesheet" type="text/css">
|
||
<title>初始设置 - VPS Hub</title>
|
||
</head>
|
||
<body>
|
||
<div class="config-container">
|
||
<div class="config-header">
|
||
<h1>🔐 初始设置</h1>
|
||
<p>请设置管理面板的访问密码</p>
|
||
</div>
|
||
|
||
<?php if (isset($setupError)): ?>
|
||
<div class="error-message">
|
||
❌ <?php echo htmlspecialchars($setupError); ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<div class="info-box">
|
||
💡 提示:此密码用于保护配置管理页面的访问权限。<br>
|
||
密码要求:至少8位,只能包含字母(a-z,A-Z)和数字(0-9)
|
||
</div>
|
||
|
||
<form method="POST" onsubmit="return validatePassword()">
|
||
<div class="form-group">
|
||
<label for="api_pass">设置访问密码</label>
|
||
<input type="password" id="api_pass" name="api_pass" required
|
||
placeholder="至少8位字母和数字"
|
||
pattern="[a-zA-Z0-9]{8,}"
|
||
title="至少8位,只能包含字母和数字">
|
||
</div>
|
||
|
||
<button type="submit" name="setup_pass" class="btn-submit">
|
||
✅ 保存并继续
|
||
</button>
|
||
</form>
|
||
</div>
|
||
|
||
<script>
|
||
function validatePassword() {
|
||
var password = document.getElementById('api_pass').value;
|
||
|
||
if (password.length < 8) {
|
||
alert('密码至少需要8位!');
|
||
return false;
|
||
}
|
||
|
||
if (!/^[a-zA-Z0-9]+$/.test(password)) {
|
||
alert('密码只能包含字母和数字!');
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|
||
<?php
|
||
exit;
|
||
}
|
||
|
||
// 加载API_PASS
|
||
if (file_exists($tokenFile)) {
|
||
include $tokenFile;
|
||
}
|
||
|
||
// 验证pass参数
|
||
$pass = isset($_GET['pass']) ? $_GET['pass'] : '';
|
||
|
||
if (!defined('API_PASS') || $pass !== API_PASS) {
|
||
header('Content-Type: application/json; charset=utf-8');
|
||
echo json_encode(['status' => 403, 'msg' => '访问密码错误'], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||
exit;
|
||
}
|
||
|
||
// 处理添加配置
|
||
$message = '';
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||
if (isset($_POST['add_config'])) {
|
||
$apiLabel = trim($_POST['api_label']);
|
||
$siteType = trim($_POST['site_type']);
|
||
$siteUrl = trim($_POST['site_url']);
|
||
$account = trim($_POST['account']);
|
||
$apiKey = trim($_POST['api_key']);
|
||
$autoMonitor = isset($_POST['auto_monitor']) ? 1 : 0;
|
||
|
||
if (empty($apiLabel) || empty($siteType) || empty($siteUrl) || empty($account) || empty($apiKey)) {
|
||
$message = '<div class="error-message">❌ API标识、网站类型、网站链接、账户和密钥不能为空!</div>';
|
||
} else {
|
||
// 验证URL格式:不允许包含路径
|
||
$parsedUrl = parse_url($siteUrl);
|
||
if (!$parsedUrl || !isset($parsedUrl['scheme']) || !isset($parsedUrl['host'])) {
|
||
$message = '<div class="error-message">❌ 网站链接格式错误!请输入完整的URL(例如: https://www.example.com)</div>';
|
||
} elseif (isset($parsedUrl['path']) && $parsedUrl['path'] !== '/') {
|
||
$message = '<div class="error-message">❌ 网站链接严禁包含路径部分!只允许输入根域名(例如: https://www.example.com),不要添加 /v1、/api 等路径</div>';
|
||
} else {
|
||
$db = getVpsDB();
|
||
|
||
// 检查API标识是否已存在
|
||
$existingConfig = $db->queryOne('SELECT id FROM configs WHERE api_label = ?', [$apiLabel]);
|
||
if ($existingConfig) {
|
||
$message = '<div class="error-message">❌ API标识 "' . htmlspecialchars($apiLabel) . '" 已存在,请使用其他标识!</div>';
|
||
} else {
|
||
$configId = $db->insert(
|
||
'INSERT INTO configs (api_label, site_type, site_url, account, api_key, auto_monitor) VALUES (?, ?, ?, ?, ?, ?)',
|
||
[$apiLabel, $siteType, $siteUrl, $account, $apiKey, $autoMonitor]
|
||
);
|
||
|
||
if ($configId) {
|
||
$message = '<div class="success-message">✅ 配置添加成功!ID: ' . $configId . '</div>';
|
||
|
||
// 如果是首次添加配置,提示运行install.sh
|
||
$configCount = $db->queryOne('SELECT COUNT(*) as count FROM configs')['count'];
|
||
if ($configCount == 1) {
|
||
$message .= '<div class="info-box">💡 这是第一个配置,请运行 <code>app/install.sh</code> 安装监控服务</div>';
|
||
|
||
// 尝试自动执行install.sh(需要PHP有执行权限)
|
||
$installScript = __DIR__ . '/app/install.sh';
|
||
if (file_exists($installScript)) {
|
||
// 检查exec函数是否可用
|
||
if (!function_exists('exec')) {
|
||
$message .= '<div class="warning-message">⚠️ exec函数被禁用,无法自动安装监控服务。请手动执行: sudo bash app/install.sh</div>';
|
||
} else {
|
||
// 先设置可执行权限
|
||
chmod($installScript, 0755);
|
||
|
||
// 执行安装脚本
|
||
$output = [];
|
||
$returnVar = 0;
|
||
exec("bash {$installScript} 2>&1", $output, $returnVar);
|
||
|
||
if ($returnVar === 0) {
|
||
$message .= '<div class="success-message">✅ 监控服务已自动安装并启动</div>';
|
||
} else {
|
||
$message .= '<div class="error-message">⚠️ 自动安装失败,请手动执行: sudo bash app/install.sh</div>';
|
||
// 输出错误信息以便调试
|
||
if (!empty($output)) {
|
||
$message .= '<details><summary>查看错误详情</summary><pre>' . htmlspecialchars(implode("\n", $output)) . '</pre></details>';
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 自动刷新VPS列表
|
||
if ($siteType === 'mofang') {
|
||
refreshVpsListForConfig($configId);
|
||
$message .= '<div class="info-box">✅ 已自动获取VPS列表</div>';
|
||
}
|
||
} else {
|
||
$message = '<div class="error-message">❌ 配置添加失败!</div>';
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} elseif (isset($_POST['delete_config'])) {
|
||
$configId = intval($_POST['config_id']);
|
||
$db = getVpsDB();
|
||
$db->execute('DELETE FROM configs WHERE id = ?', [$configId]);
|
||
$message = '<div class="success-message">✅ 配置已删除</div>';
|
||
}
|
||
}
|
||
|
||
// 获取所有配置
|
||
$db = getVpsDB();
|
||
$configs = $db->query('SELECT * FROM configs ORDER BY id');
|
||
?>
|
||
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<link rel="shortcut icon" href="./static/favicon.ico" type="image/x-icon">
|
||
<link href="./static/style.css" rel="stylesheet" type="text/css">
|
||
<title>配置管理 - VPS Hub</title>
|
||
<style>
|
||
.config-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
margin: 20px 0;
|
||
}
|
||
.config-table th, .config-table td {
|
||
padding: 12px;
|
||
text-align: left;
|
||
border-bottom: 1px solid #ddd;
|
||
}
|
||
.config-table th {
|
||
background-color: #f5f5f5;
|
||
font-weight: bold;
|
||
}
|
||
.config-table tr:hover {
|
||
background-color: #f9f9f9;
|
||
}
|
||
.btn-delete {
|
||
background-color: #dc3545;
|
||
color: white;
|
||
border: none;
|
||
padding: 6px 12px;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
}
|
||
.btn-delete:hover {
|
||
background-color: #c82333;
|
||
}
|
||
.form-section {
|
||
background: white;
|
||
padding: 20px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||
margin-bottom: 20px;
|
||
}
|
||
.form-row {
|
||
display: flex;
|
||
gap: 15px;
|
||
margin-bottom: 15px;
|
||
flex-wrap: wrap;
|
||
}
|
||
.form-group-inline {
|
||
flex: 1;
|
||
min-width: 200px;
|
||
}
|
||
.checkbox-group {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<div class="header">
|
||
<h1>⚙️ VPS配置管理</h1>
|
||
<p>添加和管理多平台VPS配置</p>
|
||
<a href="index.php?pass=<?php echo urlencode($pass); ?>" class="btn" style="float: right; margin-top: -60px;">返回首页</a>
|
||
</div>
|
||
|
||
<div class="content">
|
||
<?php echo $message; ?>
|
||
|
||
<!-- 添加配置表单 -->
|
||
<div class="form-section">
|
||
<h2>➕ 添加新配置</h2>
|
||
<form method="POST">
|
||
<div class="form-row">
|
||
<div class="form-group-inline">
|
||
<label>API标识 * <small>(例如: 核云、阿里云主账号)</small></label>
|
||
<input type="text" name="api_label" required placeholder="输入唯一标识" pattern="[a-zA-Z0-9\u4e00-\u9fa5_\-]+" title="只能包含字母、数字、中文、下划线和连字符">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-row">
|
||
<div class="form-group-inline">
|
||
<label>网站类型 *</label>
|
||
<select name="site_type" required onchange="toggleSiteUrl(this.value)">
|
||
<option value="mofang">魔方平台</option>
|
||
<option value="aliyun">阿里云(暂不支持)</option>
|
||
<option value="tencent">腾讯云(暂不支持)</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="form-group-inline" id="site_url_group">
|
||
<label>网站链接/API地址 *</label>
|
||
<input type="url" name="site_url" required placeholder="https://www.example.com" id="site_url_input">
|
||
<small style="color: #dc3545;">⚠️ 严禁包含路径部分(如 /v1、/api),只允许根域名</small>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-row">
|
||
<div class="form-group-inline">
|
||
<label>账户 * <small>(邮箱或手机号)</small></label>
|
||
<input type="text" name="account" required placeholder="输入账户">
|
||
</div>
|
||
|
||
<div class="form-group-inline">
|
||
<label>API密钥 *</label>
|
||
<input type="password" name="api_key" required placeholder="输入API密钥">
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-row">
|
||
<div class="checkbox-group">
|
||
<input type="checkbox" name="auto_monitor" id="auto_monitor" checked>
|
||
<label for="auto_monitor">开启自动开机监控</label>
|
||
</div>
|
||
</div>
|
||
|
||
<button type="submit" name="add_config" class="btn btn-success">
|
||
✅ 添加配置
|
||
</button>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- 配置列表 -->
|
||
<div class="form-section">
|
||
<h2>📋 现有配置</h2>
|
||
|
||
<?php if (empty($configs)): ?>
|
||
<p style="color: #999; text-align: center; padding: 40px;">暂无配置,请添加第一个配置</p>
|
||
<?php else: ?>
|
||
<table class="config-table">
|
||
<thead>
|
||
<tr>
|
||
<th>序号</th>
|
||
<th>API标识</th>
|
||
<th>网站类型</th>
|
||
<th>网站链接</th>
|
||
<th>账户</th>
|
||
<th>自动监控</th>
|
||
<th>创建时间</th>
|
||
<th>操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach ($configs as $config): ?>
|
||
<tr>
|
||
<td><?php echo $config['id']; ?></td>
|
||
<td><strong><?php echo htmlspecialchars($config['api_label']); ?></strong></td>
|
||
<td>
|
||
<?php
|
||
$typeMap = [
|
||
'mofang' => '魔方',
|
||
'aliyun' => '阿里云',
|
||
'tencent' => '腾讯云'
|
||
];
|
||
echo $typeMap[$config['site_type']] ?? $config['site_type'];
|
||
?>
|
||
</td>
|
||
<td><?php echo htmlspecialchars($config['site_url'] ?? '-'); ?></td>
|
||
<td><?php echo htmlspecialchars($config['account']); ?></td>
|
||
<td>
|
||
<?php echo $config['auto_monitor'] ? '✅ 开启' : '❌ 关闭'; ?>
|
||
</td>
|
||
<td><?php echo date('Y-m-d H:i', strtotime($config['created_at'])); ?></td>
|
||
<td>
|
||
<form method="POST" style="display: inline;"
|
||
onsubmit="return confirm('确认删除此配置?')">
|
||
<input type="hidden" name="config_id" value="<?php echo $config['id']; ?>">
|
||
<button type="submit" name="delete_config" class="btn-delete">
|
||
🗑️ 删除
|
||
</button>
|
||
</form>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
|
||
<center><div class="copyright">
|
||
© 2026 Gaming Master Cybersecurity |
|
||
<a href="https://git.masonliu.com/MasonLiu/VPSHUB" target="_blank">MasonLiu In Gitea</a>
|
||
</div></center>
|
||
</div>
|
||
|
||
<script>
|
||
function toggleSiteUrl(siteType) {
|
||
const urlGroup = document.getElementById('site_url_group');
|
||
const urlInput = document.getElementById('site_url_input');
|
||
|
||
if (siteType === 'mofang') {
|
||
urlInput.placeholder = '例如: https://www.heyunidc.cn';
|
||
} else if (siteType === 'aliyun') {
|
||
urlInput.placeholder = '例如: https://ecs.aliyuncs.com';
|
||
} else if (siteType === 'tencent') {
|
||
urlInput.placeholder = '例如: https://cvm.tencentcloudapi.com';
|
||
} else {
|
||
urlInput.placeholder = '例如: https://www.example.com';
|
||
}
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|