const express = require('express'); const { v4: uuidv4 } = require('uuid'); const { optionalAuth } = require('../middleware/auth'); const conversionService = require('../services/conversionService'); const ConversionTask = require('../models/ConversionTask'); const File = require('../models/File'); const router = express.Router(); /** * @route POST /api/convert/start * @desc 开始一个新的文件转换任务 * @access Private (optional) */ router.post('/start', optionalAuth, async (req, res, next) => { try { const { fileId, outputFormat, options = {} } = req.body; if (!fileId || !outputFormat) { return res.status(400).json({ success: false, message: '缺少必要参数:fileId和outputFormat' }); } // 验证文件是否存在 const file = await File.findOne({ fileId }); if (!file) { return res.status(404).json({ success: false, message: '文件未找到' }); } // 创建转换任务 const task = await ConversionTask.create({ taskId: uuidv4(), fileId, outputFormat, options, userId: req.user?.userId || null, sourceFile: { name: file.fileName, size: file.size, type: file.mimeType } }); // 异步开始转换,不阻塞响应 conversionService.startConversion(task.taskId); res.status(202).json({ success: true, message: '转换任务已创建', data: { taskId: task.taskId, status: task.status, progress: task.progress } }); } catch (error) { next(error); } }); /** * @route GET /api/convert/status/:taskId * @desc 查询转换任务的状态 * @access Public */ router.get('/status/:taskId', async (req, res, next) => { try { const { taskId } = req.params; const task = await ConversionTask.findOne({ taskId }).lean(); if (!task) { return res.status(404).json({ success: false, message: '转换任务未找到' }); } res.json({ success: true, data: task }); } catch (error) { next(error); } }); /** * @route GET /api/convert/result/:taskId * @desc 获取转换任务的结果 * @access Public */ router.get('/result/:taskId', async (req, res, next) => { try { const { taskId } = req.params; const task = await ConversionTask.findOne({ taskId }).lean(); if (!task) { return res.status(404).json({ success: false, message: '转换任务未找到' }); } if (task.status !== 'completed') { return res.status(400).json({ success: false, message: '转换尚未完成' }); } res.json({ success: true, data: { taskId: task.taskId, resultUrl: task.resultFile.downloadUrl, fileName: task.resultFile.fileName, fileSize: task.resultFile.fileSize } }); } catch (error) { next(error); } }); /** * @route POST /api/convert/batch * @desc 开始批量转换任务 * @access Private (optional) */ router.post('/batch', optionalAuth, async (req, res, next) => { try { const { fileIds, outputFormat, options = {} } = req.body; if (!fileIds || !Array.isArray(fileIds) || fileIds.length === 0) { return res.status(400).json({ success: false, message: '请提供要转换的文件ID列表' }); } if (fileIds.length > 10) { return res.status(400).json({ success: false, message: '批量转换最多支持10个文件' }); } const batchId = uuidv4(); const createdTasks = []; for (const fileId of fileIds) { const file = await File.findOne({ fileId }); if (file) { const task = await ConversionTask.create({ taskId: uuidv4(), batchId, fileId, outputFormat, options, userId: req.user?.userId || null, sourceFile: { name: file.fileName, size: file.size, type: file.mimeType } }); createdTasks.push(task); // 异步开始转换 conversionService.startConversion(task.taskId); } } res.status(202).json({ success: true, message: '批量转换任务已创建', data: { batchId, taskCount: createdTasks.length, tasks: createdTasks.map(t => ({ taskId: t.taskId, status: t.status })) } }); } catch (error) { next(error); } }); /** * @route POST /api/convert/cancel/:taskId * @desc 取消一个正在进行的转换任务 * @access Private (optional) */ router.post('/cancel/:taskId', optionalAuth, async (req, res, next) => { try { const { taskId } = req.params; const task = await ConversionTask.findOne({ taskId }); if (!task) { return res.status(404).json({ success: false, message: '转换任务未找到' }); } // 权限检查:确保用户只能取消自己的任务 if (task.userId && (!req.user || task.userId !== req.user.userId)) { return res.status(403).json({ success: false, message: '无权操作此任务' }); } await task.cancel(); res.json({ success: true, message: '转换任务已取消' }); } catch (error) { next(error); } }); module.exports = router;