CatPtain commited on
Commit
227619b
·
verified ·
1 Parent(s): 695c76b

Upload public.js

Browse files
Files changed (1) hide show
  1. backend/src/routes/public.js +133 -23
backend/src/routes/public.js CHANGED
@@ -352,13 +352,13 @@ router.get('/screenshot/:userId/:pptId/:slideIndex?', async (req, res, next) =>
352
  }
353
  });
354
 
355
- // Image endpoint - Direct frontend export page
356
  router.get('/image/:userId/:pptId/:slideIndex?', async (req, res, next) => {
357
  try {
358
  const { userId, pptId, slideIndex = 0 } = req.params;
359
- const { format = 'jpeg', quality = 90 } = req.query;
360
 
361
- console.log(`Image export request: userId=${userId}, pptId=${pptId}, slideIndex=${slideIndex}`);
362
 
363
  // Get PPT data
364
  const fileName = `${pptId}.json`;
@@ -369,6 +369,7 @@ router.get('/image/:userId/:pptId/:slideIndex?', async (req, res, next) => {
369
  const result = await githubService.getFile(userId, fileName, i);
370
  if (result) {
371
  pptData = result.content;
 
372
  break;
373
  }
374
  } catch (error) {
@@ -377,32 +378,78 @@ router.get('/image/:userId/:pptId/:slideIndex?', async (req, res, next) => {
377
  }
378
 
379
  if (!pptData) {
380
- const errorPage = generateErrorPage('PPT Not Found', `PPT ${pptId} not found for user ${userId}`);
381
- res.setHeader('Content-Type', 'text/html; charset=utf-8');
382
- return res.status(404).send(errorPage);
 
 
 
 
 
 
 
 
 
383
  }
384
 
385
  const slideIdx = parseInt(slideIndex);
386
  if (slideIdx >= pptData.slides.length || slideIdx < 0) {
387
- const errorPage = generateErrorPage('Invalid Slide', `Slide ${slideIndex} not found in PPT`);
388
- res.setHeader('Content-Type', 'text/html; charset=utf-8');
389
- return res.status(404).send(errorPage);
 
 
 
 
 
 
 
 
 
390
  }
391
 
392
- // 使用共享模块生成导出页面
393
- const htmlPage = generateExportPage(pptData, slideIdx, {
394
- format,
395
- quality: parseInt(quality),
396
- autoDownload: true // Auto-generate and download
 
 
 
 
 
 
 
 
397
  });
398
 
399
- res.setHeader('Content-Type', 'text/html; charset=utf-8');
400
- res.setHeader('X-Screenshot-Strategy', 'frontend-export-page');
401
- res.setHeader('X-Generation-Time', '< 50ms');
402
- res.send(htmlPage);
 
 
 
 
 
 
 
 
403
 
404
  } catch (error) {
405
- next(error);
 
 
 
 
 
 
 
 
 
 
 
 
406
  }
407
  });
408
 
@@ -508,6 +555,61 @@ router.get('/screenshot-health', async (req, res, next) => {
508
  }
509
  });
510
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
511
  // 新增:PPT JSON导出端点
512
  router.get('/export-json/:userId/:pptId', async (req, res, next) => {
513
  try {
@@ -624,13 +726,13 @@ router.get('/presentation/:userId/:pptId', async (req, res, next) => {
624
  }
625
  });
626
 
627
- // 新增:直接返回图片的端点 - 返回纯SVG图片,可被其他网站直接引用
628
  router.get('/direct-image/:userId/:pptId/:slideIndex?', async (req, res, next) => {
629
  try {
630
  const { userId, pptId, slideIndex = 0 } = req.params;
631
  const { format = 'svg', quality = 90, width: requestWidth, height: requestHeight } = req.query;
632
 
633
- console.log(`Direct image request: userId=${userId}, pptId=${pptId}, slideIndex=${slideIndex}, format=${format}`);
634
 
635
  // Get PPT data
636
  const fileName = `${pptId}.json`;
@@ -641,6 +743,7 @@ router.get('/direct-image/:userId/:pptId/:slideIndex?', async (req, res, next) =
641
  const result = await githubService.getFile(userId, fileName, i);
642
  if (result) {
643
  pptData = result.content;
 
644
  break;
645
  }
646
  } catch (error) {
@@ -649,6 +752,7 @@ router.get('/direct-image/:userId/:pptId/:slideIndex?', async (req, res, next) =
649
  }
650
 
651
  if (!pptData) {
 
652
  // 返回404图片SVG
653
  const notFoundSvg = `<svg width="800" height="450" xmlns="http://www.w3.org/2000/svg">
654
  <rect width="100%" height="100%" fill="#f8f9fa"/>
@@ -658,12 +762,13 @@ router.get('/direct-image/:userId/:pptId/:slideIndex?', async (req, res, next) =
658
 
659
  res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
660
  res.setHeader('Cache-Control', 'no-cache');
661
- res.setHeader('Access-Control-Allow-Origin', '*'); // 允许跨域引用
662
  return res.send(notFoundSvg);
663
  }
664
 
665
  const slideIdx = parseInt(slideIndex);
666
  if (slideIdx >= pptData.slides.length || slideIdx < 0) {
 
667
  // 返回404幻灯片SVG
668
  const invalidSlideSvg = `<svg width="800" height="450" xmlns="http://www.w3.org/2000/svg">
669
  <rect width="100%" height="100%" fill="#f8f9fa"/>
@@ -677,6 +782,8 @@ router.get('/direct-image/:userId/:pptId/:slideIndex?', async (req, res, next) =
677
  return res.send(invalidSlideSvg);
678
  }
679
 
 
 
680
  // 计算图片尺寸
681
  const defaultWidth = pptData.viewportSize || 1000;
682
  const defaultHeight = Math.ceil(defaultWidth * (pptData.viewportRatio || 0.5625));
@@ -690,18 +797,21 @@ router.get('/direct-image/:userId/:pptId/:slideIndex?', async (req, res, next) =
690
  height: finalHeight
691
  });
692
 
 
 
693
  // 设置正确的响应头,使其可以被其他网站作为图片引用
694
  res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
695
  res.setHeader('Cache-Control', 'public, max-age=3600'); // 缓存1小时
696
  res.setHeader('Access-Control-Allow-Origin', '*'); // 允许跨域引用
697
  res.setHeader('X-Generation-Time', '< 10ms');
698
  res.setHeader('X-Content-Source', 'direct-svg-generation');
 
699
 
700
  // 直接返回SVG图片内容
701
  res.send(svgContent);
702
 
703
  } catch (error) {
704
- console.error('Direct image generation failed:', error);
705
 
706
  // 返回错误图片SVG
707
  const errorSvg = `<svg width="800" height="450" xmlns="http://www.w3.org/2000/svg">
 
352
  }
353
  });
354
 
355
+ // Image endpoint - 修改为直接返回图片,而不是截图工具页面
356
  router.get('/image/:userId/:pptId/:slideIndex?', async (req, res, next) => {
357
  try {
358
  const { userId, pptId, slideIndex = 0 } = req.params;
359
+ const { format = 'svg', quality = 90, width: requestWidth, height: requestHeight } = req.query;
360
 
361
+ console.log(`🖼️ Image request (direct): userId=${userId}, pptId=${pptId}, slideIndex=${slideIndex}, format=${format}`);
362
 
363
  // Get PPT data
364
  const fileName = `${pptId}.json`;
 
369
  const result = await githubService.getFile(userId, fileName, i);
370
  if (result) {
371
  pptData = result.content;
372
+ console.log(`✅ PPT data found in repository ${i}`);
373
  break;
374
  }
375
  } catch (error) {
 
378
  }
379
 
380
  if (!pptData) {
381
+ console.log(`❌ PPT not found: ${pptId}`);
382
+ // 返回404图片SVG
383
+ const notFoundSvg = `<svg width="800" height="450" xmlns="http://www.w3.org/2000/svg">
384
+ <rect width="100%" height="100%" fill="#f8f9fa"/>
385
+ <text x="400" y="200" text-anchor="middle" font-family="Arial, sans-serif" font-size="24" fill="#6c757d">PPT Not Found</text>
386
+ <text x="400" y="250" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#6c757d">PPT ${pptId} does not exist</text>
387
+ </svg>`;
388
+
389
+ res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
390
+ res.setHeader('Cache-Control', 'no-cache');
391
+ res.setHeader('Access-Control-Allow-Origin', '*');
392
+ return res.send(notFoundSvg);
393
  }
394
 
395
  const slideIdx = parseInt(slideIndex);
396
  if (slideIdx >= pptData.slides.length || slideIdx < 0) {
397
+ console.log(`❌ Invalid slide index: ${slideIndex}`);
398
+ // 返回404幻灯片SVG
399
+ const invalidSlideSvg = `<svg width="800" height="450" xmlns="http://www.w3.org/2000/svg">
400
+ <rect width="100%" height="100%" fill="#f8f9fa"/>
401
+ <text x="400" y="200" text-anchor="middle" font-family="Arial, sans-serif" font-size="24" fill="#6c757d">Invalid Slide</text>
402
+ <text x="400" y="250" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#6c757d">Slide ${slideIndex} not found</text>
403
+ </svg>`;
404
+
405
+ res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
406
+ res.setHeader('Cache-Control', 'no-cache');
407
+ res.setHeader('Access-Control-Allow-Origin', '*');
408
+ return res.send(invalidSlideSvg);
409
  }
410
 
411
+ console.log(`✅ Generating SVG for slide ${slideIdx}`);
412
+
413
+ // 计算图片尺寸
414
+ const defaultWidth = pptData.viewportSize || 1000;
415
+ const defaultHeight = Math.ceil(defaultWidth * (pptData.viewportRatio || 0.5625));
416
+ const finalWidth = requestWidth ? parseInt(requestWidth) : defaultWidth;
417
+ const finalHeight = requestHeight ? parseInt(requestHeight) : defaultHeight;
418
+
419
+ // 生成PPT幻灯片的SVG图片
420
+ const slide = pptData.slides[slideIdx];
421
+ const svgContent = generateSlideSVG(slide, pptData, {
422
+ width: finalWidth,
423
+ height: finalHeight
424
  });
425
 
426
+ console.log(`✅ SVG generated successfully, size: ${svgContent.length} characters`);
427
+
428
+ // 设置正确的响应头,使其可以被其他网站作为图片引用
429
+ res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
430
+ res.setHeader('Cache-Control', 'public, max-age=3600'); // 缓存1小时
431
+ res.setHeader('Access-Control-Allow-Origin', '*'); // 允许跨域引用
432
+ res.setHeader('X-Generation-Time', '< 10ms');
433
+ res.setHeader('X-Content-Source', 'direct-svg-generation');
434
+ res.setHeader('Content-Disposition', 'inline'); // 确保浏览器内联显示图片
435
+
436
+ // 直接返回SVG图片内容
437
+ res.send(svgContent);
438
 
439
  } catch (error) {
440
+ console.error('❌ Image generation failed:', error);
441
+
442
+ // 返回错误图片SVG
443
+ const errorSvg = `<svg width="800" height="450" xmlns="http://www.w3.org/2000/svg">
444
+ <rect width="100%" height="100%" fill="#ffe6e6"/>
445
+ <text x="400" y="200" text-anchor="middle" font-family="Arial, sans-serif" font-size="24" fill="#cc0000">Generation Error</text>
446
+ <text x="400" y="250" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#cc0000">Failed to generate image: ${error.message}</text>
447
+ </svg>`;
448
+
449
+ res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
450
+ res.setHeader('Cache-Control', 'no-cache');
451
+ res.setHeader('Access-Control-Allow-Origin', '*');
452
+ res.send(errorSvg);
453
  }
454
  });
455
 
 
555
  }
556
  });
557
 
558
+ // 新增:截图工具页面端点(原来的image端点功能)
559
+ router.get('/screenshot-tool/:userId/:pptId/:slideIndex?', async (req, res, next) => {
560
+ try {
561
+ const { userId, pptId, slideIndex = 0 } = req.params;
562
+ const { format = 'jpeg', quality = 90 } = req.query;
563
+
564
+ console.log(`Screenshot tool request: userId=${userId}, pptId=${pptId}, slideIndex=${slideIndex}`);
565
+
566
+ // Get PPT data
567
+ const fileName = `${pptId}.json`;
568
+ let pptData = null;
569
+
570
+ for (let i = 0; i < githubService.repositories.length; i++) {
571
+ try {
572
+ const result = await githubService.getFile(userId, fileName, i);
573
+ if (result) {
574
+ pptData = result.content;
575
+ console.log(`✅ PPT data found in repository ${i}`);
576
+ break;
577
+ }
578
+ } catch (error) {
579
+ continue;
580
+ }
581
+ }
582
+
583
+ if (!pptData) {
584
+ const errorPage = generateErrorPage('PPT Not Found', `PPT ${pptId} not found for user ${userId}`);
585
+ res.setHeader('Content-Type', 'text/html; charset=utf-8');
586
+ return res.status(404).send(errorPage);
587
+ }
588
+
589
+ const slideIdx = parseInt(slideIndex);
590
+ if (slideIdx >= pptData.slides.length || slideIdx < 0) {
591
+ const errorPage = generateErrorPage('Invalid Slide', `Slide ${slideIndex} not found in PPT`);
592
+ res.setHeader('Content-Type', 'text/html; charset=utf-8');
593
+ return res.status(404).send(errorPage);
594
+ }
595
+
596
+ // 使用共享模块生成导出页面
597
+ const htmlPage = generateExportPage(pptData, slideIdx, {
598
+ format,
599
+ quality: parseInt(quality),
600
+ autoDownload: false // 不自动下载,需要用户手动操作
601
+ });
602
+
603
+ res.setHeader('Content-Type', 'text/html; charset=utf-8');
604
+ res.setHeader('X-Screenshot-Strategy', 'frontend-screenshot-tool');
605
+ res.setHeader('X-Generation-Time', '< 50ms');
606
+ res.send(htmlPage);
607
+
608
+ } catch (error) {
609
+ next(error);
610
+ }
611
+ });
612
+
613
  // 新增:PPT JSON导出端点
614
  router.get('/export-json/:userId/:pptId', async (req, res, next) => {
615
  try {
 
726
  }
727
  });
728
 
729
+ // 新增:直接返回图片的端点 - 必须放在其他路由之前避免被覆盖
730
  router.get('/direct-image/:userId/:pptId/:slideIndex?', async (req, res, next) => {
731
  try {
732
  const { userId, pptId, slideIndex = 0 } = req.params;
733
  const { format = 'svg', quality = 90, width: requestWidth, height: requestHeight } = req.query;
734
 
735
+ console.log(`🖼️ Direct image request: userId=${userId}, pptId=${pptId}, slideIndex=${slideIndex}, format=${format}`);
736
 
737
  // Get PPT data
738
  const fileName = `${pptId}.json`;
 
743
  const result = await githubService.getFile(userId, fileName, i);
744
  if (result) {
745
  pptData = result.content;
746
+ console.log(`✅ PPT data found in repository ${i}`);
747
  break;
748
  }
749
  } catch (error) {
 
752
  }
753
 
754
  if (!pptData) {
755
+ console.log(`❌ PPT not found: ${pptId}`);
756
  // 返回404图片SVG
757
  const notFoundSvg = `<svg width="800" height="450" xmlns="http://www.w3.org/2000/svg">
758
  <rect width="100%" height="100%" fill="#f8f9fa"/>
 
762
 
763
  res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
764
  res.setHeader('Cache-Control', 'no-cache');
765
+ res.setHeader('Access-Control-Allow-Origin', '*');
766
  return res.send(notFoundSvg);
767
  }
768
 
769
  const slideIdx = parseInt(slideIndex);
770
  if (slideIdx >= pptData.slides.length || slideIdx < 0) {
771
+ console.log(`❌ Invalid slide index: ${slideIndex}`);
772
  // 返回404幻灯片SVG
773
  const invalidSlideSvg = `<svg width="800" height="450" xmlns="http://www.w3.org/2000/svg">
774
  <rect width="100%" height="100%" fill="#f8f9fa"/>
 
782
  return res.send(invalidSlideSvg);
783
  }
784
 
785
+ console.log(`✅ Generating SVG for slide ${slideIdx}`);
786
+
787
  // 计算图片尺寸
788
  const defaultWidth = pptData.viewportSize || 1000;
789
  const defaultHeight = Math.ceil(defaultWidth * (pptData.viewportRatio || 0.5625));
 
797
  height: finalHeight
798
  });
799
 
800
+ console.log(`✅ SVG generated successfully, size: ${svgContent.length} characters`);
801
+
802
  // 设置正确的响应头,使其可以被其他网站作为图片引用
803
  res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
804
  res.setHeader('Cache-Control', 'public, max-age=3600'); // 缓存1小时
805
  res.setHeader('Access-Control-Allow-Origin', '*'); // 允许跨域引用
806
  res.setHeader('X-Generation-Time', '< 10ms');
807
  res.setHeader('X-Content-Source', 'direct-svg-generation');
808
+ res.setHeader('Content-Disposition', 'inline'); // 确保浏览器内联显示图片
809
 
810
  // 直接返回SVG图片内容
811
  res.send(svgContent);
812
 
813
  } catch (error) {
814
+ console.error('Direct image generation failed:', error);
815
 
816
  // 返回错误图片SVG
817
  const errorSvg = `<svg width="800" height="450" xmlns="http://www.w3.org/2000/svg">