prepare($getAppSql); if (!$stmt) { log_error("应用所有权验证查询准备失败: " . $conn->error, __FILE__, __LINE__); header('Location: dashboard.php?error=验证应用所有权失败'); exit; } $stmt->bind_param("ii", $appId, $developerId); $stmt->execute(); $result = $stmt->get_result(); if ($result->num_rows === 0) { header('Location: dashboard.php?error=App不存在或无权访问'); exit; } $app = $result->fetch_assoc(); $platforms = json_decode($app['platforms'], true); $success = ''; $error = ''; // 处理版本上传请求 if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['upload_version'])) { // 验证版本信息 if (empty($_POST['version']) || empty($_FILES['app_file']['name'])) { $error = '版本号和安装包不能为空'; } else { // 处理App文件上传 $uploadDir = __DIR__ . '/../uploads/apps/'; if (!is_dir($uploadDir)) { mkdir($uploadDir, 0755, true); } // 验证文件大小 (500MB) if ($_FILES['app_file']['size'] > 500 * 1024 * 1024) { log_error('应用文件过大: ' . number_format($_FILES['app_file']['size'] / 1024 / 1024, 2) . 'MB', __FILE__, __LINE__); $error = '应用文件大小不能超过500MB'; } else { $appExtension = pathinfo($_FILES['app_file']['name'], PATHINFO_EXTENSION); // 生成6位随机数 $randomNumber = str_pad(mt_rand(0, 999999), 6, '0', STR_PAD_LEFT); // 清理应用名称中的特殊字符 $cleanAppName = preg_replace('/[^a-zA-Z0-9_]/', '_', $app['name']); $appFileName = $cleanAppName . '_' . $randomNumber . '.' . $appExtension; $appRelativePath = 'uploads/apps/' . $appFileName; $targetPath = $uploadDir . $appFileName; if (move_uploaded_file($_FILES['app_file']['tmp_name'], $targetPath)) { $version = $_POST['version']; $changelog = $_POST['changelog'] ?? ''; // 插入新版本记录 $insertVersionSql = "INSERT INTO app_versions (app_id, version, changelog, file_path) VALUES (?, ?, ?, ?)"; $verStmt = $conn->prepare($insertVersionSql); if (!$verStmt) { log_error("版本插入准备失败: " . $conn->error, __FILE__, __LINE__); $error = '版本保存失败,请稍后再试'; unlink($targetPath); // 清理已上传文件 } else { $verStmt->bind_param("isss", $appId, $version, $changelog, $appRelativePath); if ($verStmt->execute()) { // 更新应用表中的最新版本 $updateAppSql = "UPDATE apps SET version = ? WHERE id = ?"; $updStmt = $conn->prepare($updateAppSql); if (!$updStmt) { log_error("应用版本更新准备失败: " . $conn->error, __FILE__, __LINE__); $error = '更新应用版本失败,请稍后再试'; unlink($targetPath); // 数据库更新失败,删除文件 } else { $updStmt->bind_param("si", $version, $appId); $updStmt->execute(); $success = '版本上传成功'; } } else { $error = '版本保存失败: '. $conn->error; unlink($targetPath); // 数据库更新失败,删除文件 } } } else { $error = '文件上传失败'; } } } } // 处理版本修改请求 if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['version_id'])) { $versionId = $_POST['version_id']; $version = $_POST['version']; $changelog = $_POST['changelog'] ?? ''; // 检查是否有新文件上传 if (!empty($_FILES['new_app_file']['name'])) { $uploadDir = __DIR__ . '/../uploads/apps/'; if (!is_dir($uploadDir)) { mkdir($uploadDir, 0755, true); } // 验证文件大小 (500MB) if ($_FILES['new_app_file']['size'] > 500 * 1024 * 1024) { log_error('应用文件过大: ' . number_format($_FILES['new_app_file']['size'] / 1024 / 1024, 2) . 'MB', __FILE__, __LINE__); $error = '应用文件大小不能超过500MB'; } else { $appExtension = pathinfo($_FILES['new_app_file']['name'], PATHINFO_EXTENSION); // 生成6位随机数 $randomNumber = str_pad(mt_rand(0, 999999), 6, '0', STR_PAD_LEFT); // 清理应用名称中的特殊字符 $cleanAppName = preg_replace('/[^a-zA-Z0-9_]/', '_', $app['name']); $appFileName = $cleanAppName . '_' . $randomNumber . '.' . $appExtension; $appRelativePath = 'uploads/apps/' . $appFileName; $newFilePath = $uploadDir . $appFileName; if (move_uploaded_file($_FILES['new_app_file']['tmp_name'], $newFilePath)) { // 获取旧文件路径并删除 $getOldPathSql = "SELECT file_path FROM app_versions WHERE id = ?"; $getOldPathStmt = $conn->prepare($getOldPathSql); if (!$getOldPathStmt) { log_error("获取旧文件路径查询准备失败: " . $conn->error, __FILE__, __LINE__); $error = '版本修改失败,请稍后再试'; unlink($newFilePath); } else { $getOldPathStmt->bind_param("i", $versionId); $getOldPathStmt->execute(); $oldPathResult = $getOldPathStmt->get_result(); if ($oldPathResult->num_rows > 0) { $oldPathRow = $oldPathResult->fetch_assoc(); $oldFilePath = __DIR__ . '/../' . $oldPathRow['file_path']; if (file_exists($oldFilePath)) { unlink($oldFilePath); } } // 更新版本信息 $updateVersionSql = "UPDATE app_versions SET version = ?, changelog = ?, file_path = ? WHERE id = ?"; $updateVersionStmt = $conn->prepare($updateVersionSql); if (!$updateVersionStmt) { log_error("版本更新查询准备失败: " . $conn->error, __FILE__, __LINE__); $error = '版本修改失败,请稍后再试'; unlink($newFilePath); } else { $updateVersionStmt->bind_param("sssi", $version, $changelog, $appRelativePath, $versionId); if ($updateVersionStmt->execute()) { $success = '版本修改成功'; } else { $error = '版本修改失败: ' . $conn->error; unlink($newFilePath); } } } } else { $error = '文件上传失败'; } } } else { // 仅更新版本号和更新日志 $updateVersionSql = "UPDATE app_versions SET version = ?, changelog = ? WHERE id = ?"; $updateVersionStmt = $conn->prepare($updateVersionSql); if (!$updateVersionStmt) { log_error("版本更新查询准备失败: " . $conn->error, __FILE__, __LINE__); $error = '版本修改失败,请稍后再试'; } else { $updateVersionStmt->bind_param("ssi", $version, $changelog, $versionId); if ($updateVersionStmt->execute()) { $success = '版本修改成功'; } else { $error = '版本修改失败: ' . $conn->error; } } } } // 处理版本删除请求 if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_version'])) { // 设置内容类型为纯文本 header('Content-Type: text/plain'); $versionId = $_POST['version_id']; // 初始化消息变量 $message = ''; // 开始事务 $conn->begin_transaction(); try { // 1. 获取文件路径 $filePath = ''; $getFilePathSql = "SELECT file_path FROM app_versions WHERE id = ?"; $getFileStmt = $conn->prepare($getFilePathSql); if (!$getFileStmt) { throw new Exception("获取文件路径查询准备失败: " . $conn->error); } $getFileStmt->bind_param("i", $versionId); $getFileStmt->execute(); $fileResult = $getFileStmt->get_result(); if ($fileResult->num_rows > 0) { $fileRow = $fileResult->fetch_assoc(); $filePath = __DIR__ . '/../' . $fileRow['file_path']; } // 2. 从数据库删除版本记录 $deleteVersionSql = "DELETE FROM app_versions WHERE id = ?"; $deleteVersionStmt = $conn->prepare($deleteVersionSql); if (!$deleteVersionStmt) { throw new Exception("版本删除查询准备失败: " . $conn->error); } $deleteVersionStmt->bind_param("i", $versionId); if (!$deleteVersionStmt->execute()) { throw new Exception("版本删除执行失败: " . $conn->error); } // 检查是否有记录被删除 if ($deleteVersionStmt->affected_rows === 0) { throw new Exception("未找到要删除的版本记录"); } // 3. 如果数据库删除成功,尝试删除文件(即使文件删除失败也不回滚数据库操作) if (!empty($filePath) && file_exists($filePath)) { if (!unlink($filePath)) { log_error("文件删除失败: " . $filePath, __FILE__, __LINE__); // 文件删除失败不影响数据库操作,继续处理 } } // 提交事务 $conn->commit(); $message = '版本删除成功'; } catch (Exception $e) { // 回滚事务 $conn->rollback(); log_error("版本删除异常: " . $e->getMessage(), __FILE__, __LINE__); $message = '版本删除失败: ' . $e->getMessage(); } // 只输出消息,不包含任何HTML echo $message; // 确保脚本终止,不执行后续代码 exit; } // 获取现有版本列表 $versions = []; $getVersionsSql = "SELECT * FROM app_versions WHERE app_id = ? ORDER BY id DESC"; $verStmt = $conn->prepare($getVersionsSql); if (!$verStmt) { log_error("版本查询准备失败: " . $conn->error, __FILE__, __LINE__); $error = '获取版本列表失败,请稍后再试'; } else { $verStmt->bind_param("i", $appId); $verStmt->execute(); $versionsResult = $verStmt->get_result(); while ($ver = $versionsResult->fetch_assoc()) { $versions[] = $ver; } } ?>