486CHD commited on
Commit
c03ea64
·
verified ·
1 Parent(s): 12864ac

Upload 13 files

Browse files
Files changed (2) hide show
  1. index.html +14 -6
  2. server.js +55 -11
index.html CHANGED
@@ -871,13 +871,15 @@
871
  getDisplayImage(item) {
872
  if (!item) return '';
873
  const fullUrl = this.getFullImageUrl(item);
 
 
874
  if (Device.isMobile) {
 
875
  if (item.displayUrl) return item.displayUrl;
876
- const source = resolveAssetUrl(item.image) || fullUrl;
877
  if (source && source.startsWith('data:image')) {
878
  if (source.length > 1200000) {
879
- const thumbSrc = resolveAssetUrl(item.thumb || item.thumbUrl);
880
- return thumbSrc || fullUrl || PLACEHOLDER_IMAGE;
881
  }
882
  const objectUrl = this.dataUrlToObjectUrl(source);
883
  if (objectUrl) {
@@ -885,8 +887,14 @@
885
  return objectUrl;
886
  }
887
  }
 
 
 
 
 
 
888
  }
889
- return resolveAssetUrl(item.image) || fullUrl || '';
890
  },
891
 
892
  revokeDisplayUrl(item) {
@@ -1579,7 +1587,7 @@
1579
  const thumbSrc = resolveAssetUrl(item.thumb || item.thumbUrl);
1580
  const fullSrc = ImageHandler.getFullImageUrl(item) || resolveAssetUrl(item.imageUrl);
1581
  let displaySrc = thumbSrc || ImageHandler.getDisplayImage(item) || fullSrc;
1582
- if (Device.isMobile && isPriority && fullSrc) {
1583
  displaySrc = fullSrc;
1584
  }
1585
  if (Device.isMobile && isPriority) {
@@ -1701,7 +1709,7 @@
1701
  const thumbSrc = resolveAssetUrl(item.thumb || item.thumbUrl);
1702
  const fullSrc = ImageHandler.getFullImageUrl(item) || resolveAssetUrl(item.imageUrl);
1703
  let nextSrc = thumbSrc || ImageHandler.getDisplayImage(item) || fullSrc;
1704
- if (Device.isMobile && item.isNew && fullSrc) {
1705
  nextSrc = fullSrc;
1706
  }
1707
  if (nextSrc) {
 
871
  getDisplayImage(item) {
872
  if (!item) return '';
873
  const fullUrl = this.getFullImageUrl(item);
874
+ const thumbSrc = resolveAssetUrl(item.thumb || item.thumbUrl);
875
+ const rawSource = resolveAssetUrl(item.image);
876
  if (Device.isMobile) {
877
+ if (thumbSrc) return thumbSrc;
878
  if (item.displayUrl) return item.displayUrl;
879
+ const source = rawSource || fullUrl;
880
  if (source && source.startsWith('data:image')) {
881
  if (source.length > 1200000) {
882
+ return fullUrl || source || PLACEHOLDER_IMAGE;
 
883
  }
884
  const objectUrl = this.dataUrlToObjectUrl(source);
885
  if (objectUrl) {
 
887
  return objectUrl;
888
  }
889
  }
890
+ return fullUrl || source || '';
891
+ }
892
+ if (rawSource && rawSource.startsWith('data:image') && fullUrl) {
893
+ if (rawSource.length > 400000) {
894
+ return fullUrl;
895
+ }
896
  }
897
+ return rawSource || fullUrl || '';
898
  },
899
 
900
  revokeDisplayUrl(item) {
 
1587
  const thumbSrc = resolveAssetUrl(item.thumb || item.thumbUrl);
1588
  const fullSrc = ImageHandler.getFullImageUrl(item) || resolveAssetUrl(item.imageUrl);
1589
  let displaySrc = thumbSrc || ImageHandler.getDisplayImage(item) || fullSrc;
1590
+ if (Device.isMobile && isPriority && fullSrc && !thumbSrc) {
1591
  displaySrc = fullSrc;
1592
  }
1593
  if (Device.isMobile && isPriority) {
 
1709
  const thumbSrc = resolveAssetUrl(item.thumb || item.thumbUrl);
1710
  const fullSrc = ImageHandler.getFullImageUrl(item) || resolveAssetUrl(item.imageUrl);
1711
  let nextSrc = thumbSrc || ImageHandler.getDisplayImage(item) || fullSrc;
1712
+ if (Device.isMobile && item.isNew && fullSrc && !thumbSrc) {
1713
  nextSrc = fullSrc;
1714
  }
1715
  if (nextSrc) {
server.js CHANGED
@@ -403,8 +403,17 @@ const GeneratedImageStore = {
403
 
404
  async ensureThumbnailFromUrl(imageUrl) {
405
  if (!imageUrl || typeof imageUrl !== 'string') return null;
406
- if (!imageUrl.startsWith('/generated/')) return null;
407
- const filename = path.basename(imageUrl);
 
 
 
 
 
 
 
 
 
408
  const filePath = path.join(GENERATED_DIR, filename);
409
  const thumbName = this.buildThumbName(filename);
410
  const thumbPath = path.join(THUMB_DIR, thumbName);
@@ -831,11 +840,19 @@ app.post('/api/generate', authMiddleware, async (req, res) => {
831
  throw new Error('生成图片保存失败,请稍后重试');
832
  }
833
 
 
 
 
 
 
 
 
 
834
  const responsePayload = {
835
  success: true,
836
- imageUrl,
837
  imageId,
838
- thumbUrl,
839
  prompt: trimmedPrompt,
840
  inputImages: uploadedImages,
841
  timestamp: new Date().toISOString()
@@ -878,6 +895,13 @@ app.get('/api/public-gallery', async (req, res) => {
878
  const items = await PublicGalleryStore.getAll();
879
  let updated = false;
880
  const sanitized = [];
 
 
 
 
 
 
 
881
 
882
  for (const item of items) {
883
  const { deleteToken, ...rest } = item;
@@ -921,6 +945,13 @@ app.get('/api/public-gallery', async (req, res) => {
921
  delete rest.inputImages;
922
  }
923
 
 
 
 
 
 
 
 
924
  sanitized.push(rest);
925
  }
926
 
@@ -1026,13 +1057,26 @@ app.post('/api/public-gallery', authMiddleware, async (req, res) => {
1026
  deleteToken: generateDeleteToken()
1027
  };
1028
 
1029
- try {
1030
- await PublicGalleryStore.add(entry);
1031
- const { deleteToken, ...publicItem } = entry;
1032
- recordShareOnce(true);
1033
- res.json({
1034
- success: true,
1035
- item: publicItem,
 
 
 
 
 
 
 
 
 
 
 
 
 
1036
  deleteToken
1037
  });
1038
  } catch (error) {
 
403
 
404
  async ensureThumbnailFromUrl(imageUrl) {
405
  if (!imageUrl || typeof imageUrl !== 'string') return null;
406
+ let normalizedUrl = imageUrl;
407
+ if (/^https?:\/\//i.test(imageUrl)) {
408
+ try {
409
+ const parsed = new URL(imageUrl);
410
+ normalizedUrl = parsed.pathname;
411
+ } catch {
412
+ normalizedUrl = imageUrl;
413
+ }
414
+ }
415
+ if (!normalizedUrl.startsWith('/generated/')) return null;
416
+ const filename = path.basename(normalizedUrl);
417
  const filePath = path.join(GENERATED_DIR, filename);
418
  const thumbName = this.buildThumbName(filename);
419
  const thumbPath = path.join(THUMB_DIR, thumbName);
 
840
  throw new Error('生成图片保存失败,请稍后重试');
841
  }
842
 
843
+ const hostBase = `${req.protocol}://${req.get('host')}`;
844
+ const toAbsoluteUrl = (value) => {
845
+ if (typeof value === 'string' && value.startsWith('/')) {
846
+ return `${hostBase}${value}`;
847
+ }
848
+ return value;
849
+ };
850
+
851
  const responsePayload = {
852
  success: true,
853
+ imageUrl: toAbsoluteUrl(imageUrl),
854
  imageId,
855
+ thumbUrl: toAbsoluteUrl(thumbUrl),
856
  prompt: trimmedPrompt,
857
  inputImages: uploadedImages,
858
  timestamp: new Date().toISOString()
 
895
  const items = await PublicGalleryStore.getAll();
896
  let updated = false;
897
  const sanitized = [];
898
+ const hostBase = `${req.protocol}://${req.get('host')}`;
899
+ const toAbsoluteUrl = (value) => {
900
+ if (typeof value === 'string' && value.startsWith('/')) {
901
+ return `${hostBase}${value}`;
902
+ }
903
+ return value;
904
+ };
905
 
906
  for (const item of items) {
907
  const { deleteToken, ...rest } = item;
 
945
  delete rest.inputImages;
946
  }
947
 
948
+ if (rest.imageUrl) {
949
+ rest.imageUrl = toAbsoluteUrl(rest.imageUrl);
950
+ }
951
+ if (rest.thumbUrl) {
952
+ rest.thumbUrl = toAbsoluteUrl(rest.thumbUrl);
953
+ }
954
+
955
  sanitized.push(rest);
956
  }
957
 
 
1057
  deleteToken: generateDeleteToken()
1058
  };
1059
 
1060
+ try {
1061
+ await PublicGalleryStore.add(entry);
1062
+ const { deleteToken, ...publicItem } = entry;
1063
+ const hostBase = `${req.protocol}://${req.get('host')}`;
1064
+ const toAbsoluteUrl = (value) => {
1065
+ if (typeof value === 'string' && value.startsWith('/')) {
1066
+ return `${hostBase}${value}`;
1067
+ }
1068
+ return value;
1069
+ };
1070
+ if (publicItem.imageUrl) {
1071
+ publicItem.imageUrl = toAbsoluteUrl(publicItem.imageUrl);
1072
+ }
1073
+ if (publicItem.thumbUrl) {
1074
+ publicItem.thumbUrl = toAbsoluteUrl(publicItem.thumbUrl);
1075
+ }
1076
+ recordShareOnce(true);
1077
+ res.json({
1078
+ success: true,
1079
+ item: publicItem,
1080
  deleteToken
1081
  });
1082
  } catch (error) {