import express from 'express'; import { v4 as uuidv4 } from 'uuid'; import githubService from '../services/githubService.js'; import memoryStorageService from '../services/memoryStorageService.js'; const router = express.Router(); // 添加路由级别的日志中间件 router.use((req, res, next) => { console.log(`PPT Router - ${req.method} ${req.path} - Body:`, Object.keys(req.body || {})); next(); }); // 选择存储服务 const getStorageService = () => { // 如果GitHub Token未配置,使用内存存储 if (!process.env.GITHUB_TOKEN) { return memoryStorageService; } return githubService; }; // 获取用户的PPT列表 router.get('/list', async (req, res, next) => { try { const userId = req.user.userId; const storageService = getStorageService(); const pptList = await storageService.getUserPPTList(userId); res.json(pptList); } catch (error) { next(error); } }); // 获取指定PPT数据 router.get('/:pptId', async (req, res, next) => { try { const userId = req.user.userId; const { pptId } = req.params; const fileName = `${pptId}.json`; const storageService = getStorageService(); let pptData = null; // 如果是GitHub服务,尝试所有仓库 if (storageService === githubService && storageService.repositories) { for (let i = 0; i < storageService.repositories.length; i++) { try { const result = await storageService.getFile(userId, fileName, i); if (result) { pptData = result.content; break; } } catch (error) { continue; } } } else { // 内存存储服务 const result = await storageService.getFile(userId, fileName); if (result) { pptData = result.content; } } if (!pptData) { return res.status(404).json({ error: 'PPT not found' }); } res.json(pptData); } catch (error) { next(error); } }); // 保存PPT数据 router.post('/save', async (req, res, next) => { try { const userId = req.user.userId; const { pptId, title, slides, theme } = req.body; if (!pptId || !slides) { return res.status(400).json({ error: 'PPT ID and slides are required' }); } const fileName = `${pptId}.json`; const pptData = { id: pptId, title: title || '未命名演示文稿', slides: slides, theme: theme || {}, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() }; const storageService = getStorageService(); // 如果是GitHub服务,保存到第一个仓库 if (storageService === githubService) { await storageService.saveFile(userId, fileName, pptData, 0); } else { // 内存存储服务 await storageService.saveFile(userId, fileName, pptData); } res.json({ message: 'PPT saved successfully', pptId }); } catch (error) { next(error); } }); // 创建新PPT router.post('/create', async (req, res, next) => { try { const userId = req.user.userId; const { title } = req.body; if (!title) { return res.status(400).json({ error: 'Title is required' }); } const pptId = uuidv4(); const now = new Date().toISOString(); const pptData = { id: pptId, title, theme: { backgroundColor: '#ffffff', themeColor: '#d14424', fontColor: '#333333', fontName: 'Microsoft YaHei' }, slides: [ { id: uuidv4(), elements: [ { type: 'text', id: uuidv4(), left: 150, top: 200, width: 600, height: 100, content: title, fontSize: 32, fontName: 'Microsoft YaHei', defaultColor: '#333333', bold: true, align: 'center' } ], background: { type: 'solid', color: '#ffffff' } } ], createdAt: now, updatedAt: now }; const storageService = getStorageService(); const fileName = `${pptId}.json`; console.log(`Creating PPT for user ${userId}, using storage: ${storageService === githubService ? 'GitHub' : 'Memory'}`); try { await storageService.saveFile(userId, fileName, pptData); console.log(`PPT created successfully: ${pptId}`); res.json({ success: true, pptId, pptData }); } catch (saveError) { console.error('Error saving PPT:', saveError.message); // 如果GitHub保存失败,尝试使用内存存储作为fallback if (storageService === githubService) { console.log('GitHub save failed, falling back to memory storage'); try { await memoryStorageService.saveFile(userId, fileName, pptData); console.log(`PPT saved to memory storage: ${pptId}`); res.json({ success: true, pptId, pptData, warning: 'Saved to temporary storage due to GitHub connection issue' }); } catch (memoryError) { console.error('Memory storage also failed:', memoryError.message); throw new Error('Failed to save PPT to any storage'); } } else { throw saveError; } } } catch (error) { console.error('PPT creation error:', error); next(error); } }); // 删除PPT router.delete('/:pptId', async (req, res, next) => { try { const userId = req.user.userId; const { pptId } = req.params; const fileName = `${pptId}.json`; const storageService = getStorageService(); // 如果是GitHub服务,从所有仓库中删除 if (storageService === githubService && storageService.repositories) { for (let i = 0; i < storageService.repositories.length; i++) { try { await storageService.deleteFile(userId, fileName, i); } catch (error) { // 继续尝试其他仓库 continue; } } } else { // 内存存储服务 await storageService.deleteFile(userId, fileName); } res.json({ message: 'PPT deleted successfully' }); } catch (error) { next(error); } }); // 复制PPT router.post('/:pptId/copy', async (req, res, next) => { try { const userId = req.user.userId; const { pptId } = req.params; const { title } = req.body; const sourceFileName = `${pptId}.json`; const storageService = getStorageService(); // 获取源PPT数据 let sourcePPT = null; if (storageService === githubService && storageService.repositories) { for (let i = 0; i < storageService.repositories.length; i++) { try { const result = await storageService.getFile(userId, sourceFileName, i); if (result) { sourcePPT = result.content; break; } } catch (error) { continue; } } } else { const result = await storageService.getFile(userId, sourceFileName); if (result) { sourcePPT = result.content; } } if (!sourcePPT) { return res.status(404).json({ error: 'Source PPT not found' }); } // 创建新的PPT ID和数据 const newPptId = uuidv4(); const newFileName = `${newPptId}.json`; const newPPTData = { ...sourcePPT, id: newPptId, title: title || `${sourcePPT.title} - 副本`, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() }; // 保存复制的PPT if (storageService === githubService) { await storageService.saveFile(userId, newFileName, newPPTData, 0); } else { await storageService.saveFile(userId, newFileName, newPPTData); } res.json({ message: 'PPT copied successfully', pptId: newPptId, ppt: newPPTData }); } catch (error) { next(error); } }); export default router;