完善mc部署2

This commit is contained in:
小朱
2025-07-10 12:26:56 +08:00
parent b1a5956bec
commit 149e50ddb4
5 changed files with 193 additions and 23 deletions

View File

@@ -319,6 +319,44 @@ const GameDeploymentPage: React.FC = () => {
}
}
// 取消Minecraft下载
const cancelMinecraftDownload = async () => {
if (!currentDownloadId.current) {
addNotification({
type: 'error',
title: '取消失败',
message: '没有正在进行的下载任务'
})
return
}
try {
const response = await apiClient.cancelMinecraftDownload(currentDownloadId.current)
if (response.success) {
// 重置下载状态
setMinecraftDownloading(false)
setDownloadProgress(null)
currentDownloadId.current = null
addNotification({
type: 'info',
title: '下载已取消',
message: 'Minecraft服务端下载已取消'
})
} else {
throw new Error(response.message || '取消下载失败')
}
} catch (error: any) {
console.error('取消下载失败:', error)
addNotification({
type: 'error',
title: '取消失败',
message: error.message || '无法取消下载'
})
}
}
// 创建Minecraft实例
const createMinecraftInstance = async () => {
if (!instanceName.trim() || !downloadResult) {
@@ -782,28 +820,41 @@ const GameDeploymentPage: React.FC = () => {
</div>
{/* 下载按钮 */}
<button
onClick={downloadMinecraftServer}
disabled={
!selectedServer ||
!selectedVersion ||
!minecraftInstallPath.trim() ||
minecraftDownloading
}
className="w-full bg-green-600 hover:bg-green-700 disabled:bg-gray-400 text-white py-3 px-4 rounded-lg transition-colors flex items-center justify-center space-x-2"
>
{minecraftDownloading ? (
<>
<Loader className="w-4 h-4 animate-spin" />
<span>...</span>
</>
) : (
<>
<Download className="w-4 h-4" />
<span></span>
</>
<div className="space-y-2">
<button
onClick={downloadMinecraftServer}
disabled={
!selectedServer ||
!selectedVersion ||
!minecraftInstallPath.trim() ||
minecraftDownloading
}
className="w-full bg-green-600 hover:bg-green-700 disabled:bg-gray-400 text-white py-3 px-4 rounded-lg transition-colors flex items-center justify-center space-x-2"
>
{minecraftDownloading ? (
<>
<Loader className="w-4 h-4 animate-spin" />
<span>...</span>
</>
) : (
<>
<Download className="w-4 h-4" />
<span></span>
</>
)}
</button>
{/* 取消下载按钮 */}
{minecraftDownloading && (
<button
onClick={cancelMinecraftDownload}
className="w-full bg-red-600 hover:bg-red-700 text-white py-2 px-4 rounded-lg transition-colors flex items-center justify-center space-x-2"
>
<X className="w-4 h-4" />
<span></span>
</button>
)}
</button>
</div>
{/* 下载进度 */}
{(downloadProgress || minecraftDownloading) && (

View File

@@ -413,6 +413,10 @@ class ApiClient {
return this.post('/minecraft/download', data)
}
async cancelMinecraftDownload(downloadId: string) {
return this.post('/minecraft/cancel-download', { downloadId })
}
async createMinecraftInstance(data: {
name: string
description?: string

View File

@@ -406,10 +406,37 @@ export class FileManager {
export class MinecraftServerDownloader {
private onProgress?: ProgressCallback;
private onLog?: LogCallback;
private cancelled: boolean = false;
private downloadId?: string;
constructor(onProgress?: ProgressCallback, onLog?: LogCallback) {
constructor(onProgress?: ProgressCallback, onLog?: LogCallback, downloadId?: string) {
this.onProgress = onProgress;
this.onLog = onLog;
this.downloadId = downloadId;
}
/**
* 取消下载
*/
cancel(): void {
this.cancelled = true;
if (this.onLog) {
this.onLog('下载已被用户取消', 'warn');
}
}
/**
* 检查是否已取消
*/
isCancelled(): boolean {
return this.cancelled;
}
/**
* 获取下载ID
*/
getDownloadId(): string | undefined {
return this.downloadId;
}
/**
@@ -429,6 +456,11 @@ export class MinecraftServerDownloader {
const log = silent ? undefined : this.onLog;
try {
// 检查是否已取消
if (this.cancelled) {
throw new Error('下载已被取消');
}
// 验证Java环境除非跳过
if (!skipJavaCheck) {
if (log) log('检查Java环境...', 'info');
@@ -443,23 +475,43 @@ export class MinecraftServerDownloader {
throw new Error('缺少必要参数server 和 version');
}
// 检查是否已取消
if (this.cancelled) {
throw new Error('下载已被取消');
}
// 创建临时目录
if (log) log('创建临时工作目录...', 'info');
const tempDir = await FileManager.createTempDirectory();
if (log) log(`临时目录创建成功: ${tempDir}`, 'success');
try {
// 检查是否已取消
if (this.cancelled) {
throw new Error('下载已被取消');
}
// 获取下载地址
if (log) log('正在获取下载地址...', 'info');
const downloadData = await ApiService.getDownloadUrl(server, version);
if (log) log('下载地址获取成功。', 'success');
// 检查是否已取消
if (this.cancelled) {
throw new Error('下载已被取消');
}
// 下载服务端核心
const jarPath = FileManager.getServerJarPath(server, version);
if (log) log(`正在下载服务端核心到: ${jarPath}`, 'info');
await ApiService.downloadFile(downloadData.url, jarPath, this.onProgress, log);
if (log) log('服务端核心下载完成。', 'success');
// 检查是否已取消
if (this.cancelled) {
throw new Error('下载已被取消');
}
// 运行服务端直到EULA协议除非跳过
if (!skipServerRun) {
if (log) log('正在运行服务端核心...', 'info');
@@ -468,6 +520,11 @@ export class MinecraftServerDownloader {
if (log) log('服务端运行完成。', 'success');
}
// 检查是否已取消
if (this.cancelled) {
throw new Error('下载已被取消');
}
// 移动文件到目标目录
if (log) log(`正在移动文件到目标目录: ${targetDirectory}`, 'info');
await FileManager.moveFilesToTarget(targetDirectory, log);

View File

@@ -10,6 +10,9 @@ const router = Router()
let io: SocketIOServer
let instanceManager: InstanceManager
// 全局下载器管理器
const activeDownloads = new Map<string, MinecraftServerDownloader>()
// 设置Socket.IO和InstanceManager
export function setMinecraftDependencies(socketIO: SocketIOServer, instManager: InstanceManager) {
io = socketIO
@@ -39,6 +42,50 @@ router.get('/server-categories', async (req: Request, res: Response) => {
}
})
// 取消Minecraft服务端下载
router.post('/cancel-download', async (req: Request, res: Response) => {
try {
const { downloadId } = req.body
if (!downloadId) {
return res.status(400).json({
success: false,
message: '缺少下载ID参数'
})
}
// 查找活跃的下载任务
const downloader = activeDownloads.get(downloadId)
if (!downloader) {
return res.status(404).json({
success: false,
message: '未找到指定的下载任务'
})
}
// 取消下载
downloader.cancel()
// 从活跃下载列表中移除
activeDownloads.delete(downloadId)
logger.info(`下载任务已取消: ${downloadId}`)
res.json({
success: true,
message: '下载已取消'
})
} catch (error: any) {
logger.error('取消下载失败:', error)
res.status(500).json({
success: false,
message: error.message || '取消下载失败'
})
}
})
// 获取指定服务端的可用版本
router.get('/versions/:server', async (req: Request, res: Response) => {
try {
@@ -172,9 +219,14 @@ router.post('/download', async (req: Request, res: Response) => {
})
}
logger.info(`[${type.toUpperCase()}] ${message}`)
}
},
// 下载ID
downloadId
)
// 将下载器添加到活跃下载列表
activeDownloads.set(downloadId, downloader)
// 执行下载
await downloader.downloadServer({
server,
@@ -186,6 +238,9 @@ router.post('/download', async (req: Request, res: Response) => {
logger.info(`Minecraft服务端下载完成: ${server} ${version}`)
// 从活跃下载列表中移除
activeDownloads.delete(downloadId)
// 下载完成,发送完成事件
if (io && socketId) {
io.to(socketId).emit('minecraft-download-complete', {
@@ -203,6 +258,9 @@ router.post('/download', async (req: Request, res: Response) => {
} catch (error: any) {
logger.error('Minecraft服务端下载失败:', error)
// 从活跃下载列表中移除
activeDownloads.delete(downloadId)
// 发送错误事件
if (io && socketId) {
io.to(socketId).emit('minecraft-download-error', {