getInitError(); if ($initError) { echo json_encode(['initialized' => false, 'error' => $initError]); } else { echo json_encode([ 'initialized' => $app->isInitialized(), 'brand' => $app->getPublicBrand() ]); } exit; } if ($action === 'setup') { header('Content-Type: application/json'); if ($app->isInitialized()) { http_response_code(403); echo json_encode(['success' => false, 'message' => '系统已完成初始化']); exit; } $data = json_decode(file_get_contents('php://input'), true); try { if ($app->setup($data)) { $_SESSION['is_admin'] = true; echo json_encode(['success' => true]); } else { echo json_encode(['success' => false, 'message' => '初始化失败']); } } catch (Exception $e) { echo json_encode(['success' => false, 'message' => $e->getMessage()]); } exit; } if ($action === 'login') { $data = json_decode(file_get_contents('php://input'), true); try { if ($app->login($data['password'] ?? '')) { $_SESSION['is_admin'] = true; echo json_encode(['success' => true]); } else { echo json_encode(['success' => false, 'message' => '密码错误']); } } catch (Exception $e) { echo json_encode(['success' => false, 'message' => $e->getMessage()]); } exit; } if ($action === 'check_login') { echo json_encode(['logged_in' => isset($_SESSION['is_admin']) && $_SESSION['is_admin'] === true]); exit; } if ($action === 'brand_logo') { $dir = __DIR__ . '/data'; $files = array_merge( glob($dir . '/brand-logo.png') ?: [], glob($dir . '/brand-logo.jpg') ?: [], glob($dir . '/brand-logo.webp') ?: [] ); $file = $files[0] ?? ''; if ($file === '' || !is_file($file)) { http_response_code(404); exit; } $mimeMap = [ 'png' => 'image/png', 'jpg' => 'image/jpeg', 'webp' => 'image/webp' ]; $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION)); header('Content-Type: ' . ($mimeMap[$ext] ?? 'application/octet-stream')); header('Cache-Control: public, max-age=86400'); readfile($file); exit; } if ($action === 'get_status') { header('Content-Type: application/json; charset=utf-8'); $initError = $app->getInitError(); if ($initError) { echo json_encode(['error' => $initError]); } else { $isAdmin = isset($_SESSION['is_admin']) && $_SESSION['is_admin'] === true; if (!$isAdmin) { http_response_code(403); echo json_encode(['error' => '请先登录后再操作']); } else { echo json_encode($app->getStatusForFrontend(true)); } } exit; } // ---------------- 需鉴权接口 ---------------- if ($action !== 'view' && !isset($_SESSION['is_admin'])) { http_response_code(403); echo json_encode(['error' => '请先登录后再操作']); exit; } if ($action === 'get_config') { echo json_encode($app->getConfigForFrontend()); exit; } if ($action === 'save_config') { $data = json_decode(file_get_contents('php://input'), true); if ($app->updateConfig($data)) { echo json_encode(['success' => true]); } else { echo json_encode(['success' => false, 'message' => '保存失败']); } exit; } if ($action === 'upload_logo') { header('Content-Type: application/json; charset=utf-8'); echo json_encode($app->uploadLogo($_FILES['logo'] ?? [])); exit; } if ($action === 'send_test_email') { $data = json_decode(file_get_contents('php://input'), true); $result = $app->sendTestEmail($data['email'] ?? ''); echo json_encode(['success' => $result === true, 'message' => $result]); exit; } if ($action === 'send_test_telegram') { $data = json_decode(file_get_contents('php://input'), true); $result = $app->sendTestTelegram($data['telegram'] ?? []); echo json_encode(['success' => $result === true, 'message' => $result]); exit; } if ($action === 'send_test_webhook') { $data = json_decode(file_get_contents('php://input'), true); $result = $app->sendTestWebhook($data['webhook'] ?? []); echo json_encode(['success' => $result === true, 'message' => $result]); exit; } if ($action === 'refresh_account') { $data = json_decode(file_get_contents('php://input'), true); $id = $data['id'] ?? 0; $result = $app->refreshAccount($id); if ($result === false) { echo json_encode(['success' => false, 'message' => '刷新失败']); } elseif (is_array($result)) { // 流量/状态刷新成功,但账单获取失败 echo json_encode($result); } else { echo json_encode(['success' => true]); } exit; } if ($action === 'fetch_instances') { header('Content-Type: application/json; charset=utf-8'); $data = json_decode(file_get_contents('php://input'), true); try { $instances = $app->fetchInstances($data['accessKeyId'] ?? '', $data['accessKeySecret'] ?? '', $data['regionId'] ?? ''); echo json_encode(['success' => true, 'data' => $instances]); } catch (Exception $e) { http_response_code(400); echo json_encode(['success' => false, 'message' => $e->getMessage()]); } exit; } if ($action === 'test_account') { header('Content-Type: application/json; charset=utf-8'); $data = json_decode(file_get_contents('php://input'), true); try { $result = $app->testAccountCredentials($data['account'] ?? []); echo json_encode($result); } catch (Exception $e) { http_response_code(400); echo json_encode([ 'success' => false, 'message' => $e->getMessage() ]); } exit; } if ($action === 'sync_account_group') { header('Content-Type: application/json; charset=utf-8'); $data = json_decode(file_get_contents('php://input'), true) ?: []; try { echo json_encode($app->syncAccountGroup($data['groupKey'] ?? '')); } catch (Exception $e) { http_response_code(400); echo json_encode([ 'success' => false, 'message' => $e->getMessage() ]); } exit; } if ($action === 'restore_schedule_block') { header('Content-Type: application/json; charset=utf-8'); $data = json_decode(file_get_contents('php://input'), true) ?: []; try { echo json_encode($app->restoreScheduleAfterTrafficBlock($data['groupKey'] ?? '')); } catch (Exception $e) { http_response_code(400); echo json_encode([ 'success' => false, 'message' => $e->getMessage() ]); } exit; } if ($action === 'preview_ecs_create') { header('Content-Type: application/json; charset=utf-8'); $data = json_decode(file_get_contents('php://input'), true) ?: []; try { $result = $app->previewEcsCreate($data); $_SESSION['ecs_create_previews'] = $_SESSION['ecs_create_previews'] ?? []; $_SESSION['ecs_create_previews'][$result['previewId']] = [ 'summary' => $result['summary'], 'created_at' => time() ]; echo json_encode($result); } catch (Exception $e) { http_response_code(400); echo json_encode(['success' => false, 'message' => $e->getMessage()]); } exit; } if ($action === 'get_ecs_disk_options') { header('Content-Type: application/json; charset=utf-8'); $data = json_decode(file_get_contents('php://input'), true) ?: []; try { echo json_encode($app->getEcsDiskOptions($data)); } catch (Exception $e) { http_response_code(400); echo json_encode(['success' => false, 'message' => $e->getMessage()]); } exit; } if ($action === 'create_ecs') { header('Content-Type: application/json; charset=utf-8'); $data = json_decode(file_get_contents('php://input'), true) ?: []; $previewId = $data['previewId'] ?? ''; $confirmed = !empty($data['confirmed']); try { if (!$confirmed) { throw new Exception('请先确认配置清单和费用提示'); } $previewStore = $_SESSION['ecs_create_previews'][$previewId] ?? null; if (!$previewStore || (time() - ($previewStore['created_at'] ?? 0)) > 900) { throw new Exception('配置清单已过期,请重新预检'); } $result = $app->createEcsFromPreview($previewId, $previewStore['summary']); unset($_SESSION['ecs_create_previews'][$previewId]); echo json_encode($result); } catch (Exception $e) { http_response_code(400); echo json_encode(['success' => false, 'message' => $e->getMessage()]); } exit; } if ($action === 'get_ecs_create_task') { header('Content-Type: application/json; charset=utf-8'); $taskId = $_GET['taskId'] ?? ''; $task = $app->getEcsCreateTask($taskId); if (!$task) { http_response_code(404); echo json_encode(['success' => false, 'message' => '任务不存在']); } else { unset($task['login_password']); echo json_encode(['success' => true, 'data' => $task]); } exit; } // 修改:获取系统日志,支持 Tab if ($action === 'get_logs') { header('Content-Type: application/json; charset=utf-8'); $tab = $_GET['tab'] ?? 'action'; // 默认是动作日志 echo json_encode(['data' => $app->getSystemLogs($tab)]); exit; } // 新增:清空日志 if ($action === 'clear_logs') { $data = json_decode(file_get_contents('php://input'), true); $tab = $data['tab'] ?? 'action'; if ($app->clearSystemLogs($tab)) { echo json_encode(['success' => true]); } else { echo json_encode(['success' => false, 'message' => '清空失败']); } exit; } if ($action === 'get_history') { header('Content-Type: application/json; charset=utf-8'); $id = $_GET['id'] ?? 0; echo json_encode(['data' => $app->getAccountHistory($id)]); exit; } if ($action === 'logout') { session_destroy(); echo json_encode(['success' => true]); exit; } if ($action === 'get_all_instances') { header('Content-Type: application/json; charset=utf-8'); $sync = ($_GET['sync'] ?? '0') === '1'; echo json_encode(['data' => $app->getAllManagedInstances($sync)]); exit; } if ($action === 'control_instance') { $data = json_decode(file_get_contents('php://input'), true); $accountId = $data['accountId'] ?? 0; $actionType = $data['action'] ?? ''; $shutdownMode = $data['shutdownMode'] ?? 'KeepCharging'; if (!in_array($actionType, ['start', 'stop'])) { http_response_code(400); echo json_encode(['success' => false, 'message' => '无效的操作类型']); exit; } $result = $app->controlInstanceAction($accountId, $actionType, $shutdownMode); echo json_encode(['success' => $result]); exit; } if ($action === 'delete_instance') { $data = json_decode(file_get_contents('php://input'), true); $accountId = $data['accountId'] ?? 0; $forceStop = $data['forceStop'] ?? false; $result = $app->deleteInstanceAction($accountId, $forceStop); echo json_encode(['success' => $result]); exit; } if ($action === 'replace_instance_ip') { $data = json_decode(file_get_contents('php://input'), true); $accountId = $data['accountId'] ?? 0; $result = $app->replaceInstanceIpAction($accountId); echo json_encode($result); exit; } echo $app->renderTemplate();