486CHD commited on
Commit
b0c59b4
·
verified ·
1 Parent(s): a5e2a49

Upload 13 files

Browse files
Files changed (2) hide show
  1. index.html +122 -46
  2. style.css +20 -9
index.html CHANGED
@@ -21,9 +21,9 @@
21
  box-shadow: 0 2px 20px rgba(0,0,0,0.3) !important;
22
  }
23
 
24
- header {
25
- margin-top: 130px; /* 为输入区留空间 */
26
- }
27
 
28
  .history-container {
29
  padding-bottom: 20px !important;
@@ -31,13 +31,13 @@
31
 
32
  /* 调整输入区内部布局 */
33
  .control-bar {
34
- max-width: 1320px;
35
  margin: 0 auto;
36
  padding: 12px 20px !important;
37
  }
38
 
39
  .preview-bar {
40
- max-width: 1320px;
41
  margin: 0 auto;
42
  padding: 0 20px;
43
  }
@@ -47,9 +47,9 @@
47
  }
48
 
49
  /* 动态调整header间距 */
50
- .has-preview header {
51
- margin-top: 280px;
52
- }
53
 
54
  @media (max-width: 768px) {
55
  header {
@@ -167,13 +167,17 @@
167
  <div class="modal-img-area">
168
  <img id="m-img" src="">
169
  </div>
170
- <div class="modal-footer">
171
- <div class="input-refs" id="m-refs"></div>
172
- <div class="prompt-display" id="m-prompt"></div>
173
- <button class="btn-3d" id="m-reuse" style="width: 100%; padding: 12px;">
174
- 复用参数与图片
175
- </button>
176
- </div>
 
 
 
 
177
  </div>
178
  </div>
179
 
@@ -685,7 +689,7 @@
685
  init() {
686
  this.container = document.getElementById('gallery');
687
  this.loadMoreBtn = document.getElementById('gallery-load-more');
688
- this.pageSize = Device.isMobile ? 6 : 12;
689
  this.visibleCount = this.pageSize;
690
  if (this.loadMoreBtn) {
691
  this.loadMoreBtn.onclick = () => this.loadMore();
@@ -722,7 +726,7 @@
722
 
723
  loadMore() {
724
  const total = AppState.galleryData.length;
725
- if (!total) return;
726
  const scroller = this.container ? this.container.closest('.history-container') : null;
727
  const scrollTop = scroller ? scroller.scrollTop : window.scrollY;
728
  this.visibleCount = Math.min(total, (this.visibleCount || this.pageSize) + this.pageSize);
@@ -960,19 +964,23 @@
960
  // ============================================
961
  // 弹窗管理模块
962
  // ============================================
963
- const ModalManager = {
964
- modal: null,
965
- imgEl: null,
966
- promptEl: null,
967
- refsEl: null,
968
- reuseBtn: null,
969
-
970
- init() {
971
- this.modal = document.getElementById('modal');
972
- this.imgEl = document.getElementById('m-img');
973
- this.promptEl = document.getElementById('m-prompt');
974
- this.refsEl = document.getElementById('m-refs');
975
- this.reuseBtn = document.getElementById('m-reuse');
 
 
 
 
976
 
977
  // 点击背景关闭
978
  this.modal.onclick = (e) => {
@@ -1006,16 +1014,27 @@
1006
  });
1007
  }
1008
 
1009
- // 绑定复用按钮
1010
- this.reuseBtn.onclick = () => this.reuse();
1011
-
1012
- this.modal.style.display = 'flex';
1013
- },
1014
-
1015
- close() {
1016
- this.modal.style.display = 'none';
1017
- AppState.currentModalItem = null;
1018
- },
 
 
 
 
 
 
 
 
 
 
 
1019
 
1020
  reuse() {
1021
  const item = AppState.currentModalItem;
@@ -1034,10 +1053,41 @@
1034
  ImageHandler.clear();
1035
  }
1036
 
1037
- this.close();
1038
- textarea.focus();
1039
- }
1040
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1041
 
1042
  // ============================================
1043
  // 公共画廊管理模块
@@ -1066,7 +1116,7 @@
1066
  this.refreshBtn = document.getElementById('refresh-public-gallery');
1067
  this.hintEl = document.getElementById('public-gallery-hint');
1068
  this.loadMoreBtn = document.getElementById('public-gallery-load-more');
1069
- this.pageSize = Device.isMobile ? 6 : 12;
1070
  this.visibleCount = this.pageSize;
1071
  this.tokens = this.loadTokens();
1072
  if (this.hintEl && this.hintEl.textContent) {
@@ -1081,9 +1131,35 @@
1081
  this.loadMoreBtn.onclick = () => this.loadMore();
1082
  }
1083
 
 
1084
  this.initialFetch();
1085
  },
1086
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1087
  resetPagination() {
1088
  this.visibleCount = this.pageSize;
1089
  },
@@ -1114,7 +1190,7 @@
1114
 
1115
  loadMore() {
1116
  const total = AppState.publicGalleryData.length;
1117
- if (!total) return;
1118
  const scroller = this.container ? this.container.closest('.history-container') : null;
1119
  const scrollTop = scroller ? scroller.scrollTop : window.scrollY;
1120
  this.visibleCount = Math.min(total, (this.visibleCount || this.pageSize) + this.pageSize);
 
21
  box-shadow: 0 2px 20px rgba(0,0,0,0.3) !important;
22
  }
23
 
24
+ header {
25
+ margin-top: 115px; /* 为输入区留空间 */
26
+ }
27
 
28
  .history-container {
29
  padding-bottom: 20px !important;
 
31
 
32
  /* 调整输入区内部布局 */
33
  .control-bar {
34
+ max-width: 1400px;
35
  margin: 0 auto;
36
  padding: 12px 20px !important;
37
  }
38
 
39
  .preview-bar {
40
+ max-width: 1400px;
41
  margin: 0 auto;
42
  padding: 0 20px;
43
  }
 
47
  }
48
 
49
  /* 动态调整header间距 */
50
+ .has-preview header {
51
+ margin-top: 260px;
52
+ }
53
 
54
  @media (max-width: 768px) {
55
  header {
 
167
  <div class="modal-img-area">
168
  <img id="m-img" src="">
169
  </div>
170
+ <div class="modal-footer">
171
+ <div class="input-refs" id="m-refs"></div>
172
+ <div class="prompt-display" id="m-prompt"></div>
173
+ <div class="modal-actions">
174
+ <button class="icon-btn" id="m-fullscreen" title="全屏查看" aria-label="全屏查看">全屏</button>
175
+ <button class="icon-btn" id="m-download" title="保存图片" aria-label="保存图片">保存</button>
176
+ </div>
177
+ <button class="btn-3d" id="m-reuse" style="width: 100%; padding: 12px;">
178
+ 复用参数与图片
179
+ </button>
180
+ </div>
181
  </div>
182
  </div>
183
 
 
689
  init() {
690
  this.container = document.getElementById('gallery');
691
  this.loadMoreBtn = document.getElementById('gallery-load-more');
692
+ this.pageSize = Device.isMobile ? 12 : 12;
693
  this.visibleCount = this.pageSize;
694
  if (this.loadMoreBtn) {
695
  this.loadMoreBtn.onclick = () => this.loadMore();
 
726
 
727
  loadMore() {
728
  const total = AppState.galleryData.length;
729
+ if (!total || this.visibleCount >= total) return;
730
  const scroller = this.container ? this.container.closest('.history-container') : null;
731
  const scrollTop = scroller ? scroller.scrollTop : window.scrollY;
732
  this.visibleCount = Math.min(total, (this.visibleCount || this.pageSize) + this.pageSize);
 
964
  // ============================================
965
  // 弹窗管理模块
966
  // ============================================
967
+ const ModalManager = {
968
+ modal: null,
969
+ imgEl: null,
970
+ promptEl: null,
971
+ refsEl: null,
972
+ reuseBtn: null,
973
+ fullscreenBtn: null,
974
+ downloadBtn: null,
975
+
976
+ init() {
977
+ this.modal = document.getElementById('modal');
978
+ this.imgEl = document.getElementById('m-img');
979
+ this.promptEl = document.getElementById('m-prompt');
980
+ this.refsEl = document.getElementById('m-refs');
981
+ this.reuseBtn = document.getElementById('m-reuse');
982
+ this.fullscreenBtn = document.getElementById('m-fullscreen');
983
+ this.downloadBtn = document.getElementById('m-download');
984
 
985
  // 点击背景关闭
986
  this.modal.onclick = (e) => {
 
1014
  });
1015
  }
1016
 
1017
+ // 绑定复用按钮
1018
+ this.reuseBtn.onclick = () => this.reuse();
1019
+ if (this.fullscreenBtn) {
1020
+ this.fullscreenBtn.onclick = () => this.toggleFullscreen();
1021
+ }
1022
+ if (this.downloadBtn) {
1023
+ this.downloadBtn.onclick = () => this.downloadCurrent();
1024
+ }
1025
+
1026
+ this.modal.style.display = 'flex';
1027
+ },
1028
+
1029
+ close() {
1030
+ this.modal.style.display = 'none';
1031
+ AppState.currentModalItem = null;
1032
+ if (document.fullscreenElement && document.exitFullscreen) {
1033
+ document.exitFullscreen();
1034
+ } else if (document.webkitFullscreenElement && document.webkitExitFullscreen) {
1035
+ document.webkitExitFullscreen();
1036
+ }
1037
+ },
1038
 
1039
  reuse() {
1040
  const item = AppState.currentModalItem;
 
1053
  ImageHandler.clear();
1054
  }
1055
 
1056
+ this.close();
1057
+ textarea.focus();
1058
+ },
1059
+
1060
+ toggleFullscreen() {
1061
+ const target = this.modal;
1062
+ if (!target) return;
1063
+ if (document.fullscreenElement || document.webkitFullscreenElement) {
1064
+ if (document.exitFullscreen) {
1065
+ document.exitFullscreen();
1066
+ } else if (document.webkitExitFullscreen) {
1067
+ document.webkitExitFullscreen();
1068
+ }
1069
+ return;
1070
+ }
1071
+ if (target.requestFullscreen) {
1072
+ target.requestFullscreen();
1073
+ } else if (target.webkitRequestFullscreen) {
1074
+ target.webkitRequestFullscreen();
1075
+ }
1076
+ },
1077
+
1078
+ downloadCurrent() {
1079
+ const item = AppState.currentModalItem;
1080
+ if (!item) return;
1081
+ const src = ImageHandler.getDisplayImage(item) || item.image || item.imageUrl || item.thumb;
1082
+ if (!src) return;
1083
+ const link = document.createElement('a');
1084
+ link.href = src;
1085
+ link.download = `banana-pro-${item.id || Date.now()}.png`;
1086
+ document.body.appendChild(link);
1087
+ link.click();
1088
+ document.body.removeChild(link);
1089
+ }
1090
+ };
1091
 
1092
  // ============================================
1093
  // 公共画廊管理模块
 
1116
  this.refreshBtn = document.getElementById('refresh-public-gallery');
1117
  this.hintEl = document.getElementById('public-gallery-hint');
1118
  this.loadMoreBtn = document.getElementById('public-gallery-load-more');
1119
+ this.pageSize = Device.isMobile ? 12 : 12;
1120
  this.visibleCount = this.pageSize;
1121
  this.tokens = this.loadTokens();
1122
  if (this.hintEl && this.hintEl.textContent) {
 
1131
  this.loadMoreBtn.onclick = () => this.loadMore();
1132
  }
1133
 
1134
+ this.bindAutoLoad();
1135
  this.initialFetch();
1136
  },
1137
 
1138
+ bindAutoLoad() {
1139
+ if (!Device.isMobile || this.autoLoadBound) return;
1140
+ const scroller = document.querySelector('.history-container');
1141
+ if (!scroller) return;
1142
+ this.autoLoadBound = true;
1143
+ this.scroller = scroller;
1144
+ this.autoLoading = false;
1145
+
1146
+ const onScroll = () => {
1147
+ if (this.autoLoading) return;
1148
+ const total = (AppState.publicGalleryData || []).length;
1149
+ if (!total || this.visibleCount >= total) return;
1150
+ const nearBottom = scroller.scrollTop + scroller.clientHeight >= scroller.scrollHeight - 240;
1151
+ if (!nearBottom) return;
1152
+ this.autoLoading = true;
1153
+ this.loadMore();
1154
+ setTimeout(() => {
1155
+ this.autoLoading = false;
1156
+ }, 120);
1157
+ };
1158
+
1159
+ scroller.addEventListener('scroll', onScroll, { passive: true });
1160
+ this.autoLoadHandler = onScroll;
1161
+ },
1162
+
1163
  resetPagination() {
1164
  this.visibleCount = this.pageSize;
1165
  },
 
1190
 
1191
  loadMore() {
1192
  const total = AppState.publicGalleryData.length;
1193
+ if (!total || this.visibleCount >= total) return;
1194
  const scroller = this.container ? this.container.closest('.history-container') : null;
1195
  const scrollTop = scroller ? scroller.scrollTop : window.scrollY;
1196
  this.visibleCount = Math.min(total, (this.visibleCount || this.pageSize) + this.pageSize);
style.css CHANGED
@@ -156,7 +156,7 @@ body {
156
 
157
  /* --- Layout --- */
158
  .app-container {
159
- max-width: 1320px;
160
  margin: 0 auto;
161
  width: 100%;
162
  height: 100%;
@@ -314,7 +314,7 @@ header h2 {
314
 
315
 
316
  body.has-preview header {
317
- margin-top: 360px;
318
  }
319
 
320
  /* --- History Gallery --- */
@@ -1188,16 +1188,27 @@ body.has-preview header {
1188
  }
1189
  }
1190
 
1191
- .modal-footer {
1192
- padding: 20px;
1193
- background: rgba(30, 41, 59, 0.95);
1194
  backdrop-filter: blur(16px);
1195
  border-top: 1px solid var(--panel-border-strong);
1196
  display: flex;
1197
- flex-direction: column;
1198
- gap: 12px;
1199
- border-radius: 0 0 20px 20px;
1200
- }
 
 
 
 
 
 
 
 
 
 
 
1201
 
1202
  .input-refs {
1203
  display: flex;
 
156
 
157
  /* --- Layout --- */
158
  .app-container {
159
+ max-width: 1400px;
160
  margin: 0 auto;
161
  width: 100%;
162
  height: 100%;
 
314
 
315
 
316
  body.has-preview header {
317
+ margin-top: 260px;
318
  }
319
 
320
  /* --- History Gallery --- */
 
1188
  }
1189
  }
1190
 
1191
+ .modal-footer {
1192
+ padding: 20px;
1193
+ background: rgba(30, 41, 59, 0.95);
1194
  backdrop-filter: blur(16px);
1195
  border-top: 1px solid var(--panel-border-strong);
1196
  display: flex;
1197
+ flex-direction: column;
1198
+ gap: 12px;
1199
+ border-radius: 0 0 20px 20px;
1200
+ }
1201
+
1202
+ .modal-actions {
1203
+ display: flex;
1204
+ gap: 10px;
1205
+ flex-wrap: wrap;
1206
+ }
1207
+
1208
+ .modal-actions .icon-btn {
1209
+ min-width: 110px;
1210
+ height: 36px;
1211
+ }
1212
 
1213
  .input-refs {
1214
  display: flex;