Logankunfall commited on
Commit
dd0bb4d
·
verified ·
1 Parent(s): c7e25ff

Upload 21 files

Browse files
frontend/assets/app.js CHANGED
@@ -331,6 +331,47 @@
331
  return Math.max(1, Math.min(8, isNaN(n) ? def : n));
332
  }
333
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
  // T2I
335
  async function handleT2I() {
336
  const payloadBase = {
@@ -393,6 +434,15 @@
393
  }
394
  const paths = oks.map(o => o.saved_path || "").filter(Boolean).join(" | ");
395
  if (byId("t2i-saved")) byId("t2i-saved").value = paths;
 
 
 
 
 
 
 
 
 
396
  toast(`生成成功 ${oks.length} 张`, "success");
397
  } catch (err) {
398
  toast(String(err.message || err), "error");
@@ -473,6 +523,15 @@
473
  }
474
  const paths = oks.map(o => o.saved_path || "").filter(Boolean).join(" | ");
475
  if (byId("i2i-saved")) byId("i2i-saved").value = paths;
 
 
 
 
 
 
 
 
 
476
  toast(`生成成功 ${oks.length} 张`, "success");
477
  } catch (err) {
478
  toast(String(err.message || err), "error");
@@ -557,6 +616,15 @@
557
  }
558
  const paths = oks.map(o => o.saved_path || "").filter(Boolean).join(" | ");
559
  if (byId("inpaint-saved")) byId("inpaint-saved").value = paths;
 
 
 
 
 
 
 
 
 
560
  toast(`生成成功 ${oks.length} 张`, "success");
561
  } catch (err) {
562
  toast(String(err.message || err), "error");
@@ -641,6 +709,9 @@
641
  byId("btn-t2i").addEventListener("click", handleT2I);
642
  byId("btn-i2i").addEventListener("click", handleI2I);
643
  byId("btn-inpaint").addEventListener("click", handleInpaint);
 
 
 
644
 
645
  // Init
646
  loadConfig();
 
331
  return Math.max(1, Math.min(8, isNaN(n) ? def : n));
332
  }
333
 
334
+ // 展开/收起图片信息
335
+ function setupImageInfoToggle() {
336
+ document.addEventListener('click', (e) => {
337
+ if (e.target.classList.contains('image-info-toggle')) {
338
+ const targetId = e.target.getAttribute('data-target');
339
+ const content = document.getElementById(targetId);
340
+ if (content) {
341
+ const isExpanded = content.classList.contains('expanded');
342
+ if (isExpanded) {
343
+ content.classList.remove('expanded');
344
+ e.target.textContent = '展开 ▼';
345
+ } else {
346
+ content.classList.add('expanded');
347
+ e.target.textContent = '收起 ▲';
348
+ }
349
+ }
350
+ }
351
+ });
352
+ }
353
+
354
+ // 显示图片信息
355
+ function displayImageInfo(tabPrefix, data, prompt, negative) {
356
+ const infoEl = document.getElementById(`${tabPrefix}-info`);
357
+ const modelEl = document.getElementById(`${tabPrefix}-model`);
358
+ const resolutionEl = document.getElementById(`${tabPrefix}-resolution`);
359
+ const promptEl = document.getElementById(`${tabPrefix}-prompt-text`);
360
+ const negativeEl = document.getElementById(`${tabPrefix}-negative-text`);
361
+
362
+ if (infoEl && modelEl && resolutionEl && promptEl && negativeEl) {
363
+ // 获取配置中的模型
364
+ const model = byId('cfg-model')?.value || 'nai-diffusion-3';
365
+
366
+ // 显示信息
367
+ infoEl.style.display = 'block';
368
+ modelEl.textContent = model;
369
+ resolutionEl.textContent = `${data.width || 768} × ${data.height || 768}`;
370
+ promptEl.textContent = prompt || '无';
371
+ negativeEl.textContent = negative || '无';
372
+ }
373
+ }
374
+
375
  // T2I
376
  async function handleT2I() {
377
  const payloadBase = {
 
434
  }
435
  const paths = oks.map(o => o.saved_path || "").filter(Boolean).join(" | ");
436
  if (byId("t2i-saved")) byId("t2i-saved").value = paths;
437
+
438
+ // 显示第一张图片的信息
439
+ if (oks.length > 0) {
440
+ displayImageInfo('t2i', {
441
+ width: payloadBase.width,
442
+ height: payloadBase.height
443
+ }, payloadBase.prompt, payloadBase.negative);
444
+ }
445
+
446
  toast(`生成成功 ${oks.length} 张`, "success");
447
  } catch (err) {
448
  toast(String(err.message || err), "error");
 
523
  }
524
  const paths = oks.map(o => o.saved_path || "").filter(Boolean).join(" | ");
525
  if (byId("i2i-saved")) byId("i2i-saved").value = paths;
526
+
527
+ // 显示第一张图片的信息
528
+ if (oks.length > 0) {
529
+ displayImageInfo('i2i', {
530
+ width: payloadBase.width || 768,
531
+ height: payloadBase.height || 768
532
+ }, payloadBase.positive, payloadBase.negative);
533
+ }
534
+
535
  toast(`生成成功 ${oks.length} 张`, "success");
536
  } catch (err) {
537
  toast(String(err.message || err), "error");
 
616
  }
617
  const paths = oks.map(o => o.saved_path || "").filter(Boolean).join(" | ");
618
  if (byId("inpaint-saved")) byId("inpaint-saved").value = paths;
619
+
620
+ // 显示第一张图片的信息
621
+ if (oks.length > 0) {
622
+ displayImageInfo('inpaint', {
623
+ width: payloadBase.width || 768,
624
+ height: payloadBase.height || 768
625
+ }, payloadBase.positive, payloadBase.negative);
626
+ }
627
+
628
  toast(`生成成功 ${oks.length} 张`, "success");
629
  } catch (err) {
630
  toast(String(err.message || err), "error");
 
709
  byId("btn-t2i").addEventListener("click", handleT2I);
710
  byId("btn-i2i").addEventListener("click", handleI2I);
711
  byId("btn-inpaint").addEventListener("click", handleInpaint);
712
+
713
+ // 设置图片信息展开/收起功能
714
+ setupImageInfoToggle();
715
 
716
  // Init
717
  loadConfig();
frontend/assets/style.css CHANGED
@@ -597,60 +597,69 @@ select {
597
  display: none;
598
  }
599
 
600
- /* 顶部导航栏简化 */
601
  .app-header {
602
- padding: 12px 16px;
603
  flex-direction: row;
604
  align-items: center;
605
- gap: 12px;
 
606
  }
607
 
608
  .brand {
609
- font-size: 18px;
610
  flex: 1;
 
 
611
  }
612
 
613
- /* 主容器调整 */
614
  main {
615
- padding: 130px 12px 20px;
616
  max-width: 100%;
617
  }
618
 
619
- /* 卡片优化 */
620
  .card {
621
- padding: 16px 12px;
622
- border-radius: 16px;
623
  }
624
 
625
- /* 表单网格优化 - 移动端单列 */
626
  .form-grid {
627
- grid-template-columns: 1fr !important;
628
- gap: 16px;
 
 
 
 
 
629
  }
630
 
631
- /* 触控友好的输入框 */
632
  input[type="text"],
633
  input[type="password"],
634
  input[type="number"],
635
  input[type="color"],
636
- textarea,
637
  select {
638
- padding: 14px 16px;
639
- font-size: 16px;
640
- border-radius: 12px;
641
- min-height: 48px;
642
  }
643
 
644
  textarea {
645
- min-height: 100px;
 
 
646
  }
647
 
648
- /* 按钮优化 */
649
  button {
650
- padding: 14px 20px;
651
- font-size: 16px;
652
- min-height: 48px;
653
- border-radius: 12px;
654
  }
655
 
656
  /* 开关优化 */
@@ -716,60 +725,145 @@ select {
716
  padding-bottom: 90px;
717
  }
718
 
719
- /* 结果展示优化 */
720
  .result {
721
  margin-top: 16px;
722
- gap: 16px;
723
  }
724
 
725
  .result img {
726
- border-radius: 16px;
727
- box-shadow: 0 4px 12px rgba(0,0,0,0.1);
 
 
 
 
728
  }
729
 
730
- /* 保存路径显示优化 */
731
- .saved-path {
732
- grid-template-columns: 1fr;
733
- gap: 8px;
 
 
 
 
734
  }
735
 
736
- .saved-path label {
737
- font-size: 13px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
738
  }
739
 
740
- .saved-path input {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
741
  font-size: 13px;
742
- padding: 10px 12px;
 
743
  }
744
 
745
- /* Toast 优化 */
 
 
 
 
 
746
  .toast {
747
- bottom: 90px;
748
  max-width: calc(100% - 32px);
749
- padding: 12px 16px;
750
- font-size: 15px;
751
  }
752
 
753
- /* 标题优化 */
754
  h2 {
755
- font-size: 20px;
756
- margin: 0 0 16px;
 
757
  }
758
 
759
- /* 标签字体优化 */
760
  label {
761
- font-size: 15px;
762
  }
763
 
764
  label > span {
765
  font-weight: 600;
766
- margin-bottom: 4px;
767
  }
768
 
769
  /* 信息提示优化 */
770
  .message {
771
- font-size: 14px;
772
- margin-top: 12px;
773
  }
774
 
775
  /* 滚动条隐藏(更流畅的移动体验) */
 
597
  display: none;
598
  }
599
 
600
+ /* 顶部导航栏简化 - 更小更紧凑 */
601
  .app-header {
602
+ padding: 4px 10px;
603
  flex-direction: row;
604
  align-items: center;
605
+ gap: 8px;
606
+ min-height: 32px;
607
  }
608
 
609
  .brand {
610
+ font-size: 11px;
611
  flex: 1;
612
+ font-weight: 600;
613
+ letter-spacing: 0.3px;
614
  }
615
 
616
+ /* 主容器调整 - 减小padding,内容向上靠 */
617
  main {
618
+ padding: 36px 8px 10px;
619
  max-width: 100%;
620
  }
621
 
622
+ /* 卡片优化 - 减小padding */
623
  .card {
624
+ padding: 10px 8px;
625
+ border-radius: var(--radius);
626
  }
627
 
628
+ /* 表单网格优化 - 移动端两列(除了全宽) */
629
  .form-grid {
630
+ grid-template-columns: repeat(2, 1fr) !important;
631
+ gap: 8px;
632
+ }
633
+
634
+ /* 全宽元素(正负面提示词)保持单列 */
635
+ .form-grid label.full {
636
+ grid-column: 1 / -1;
637
  }
638
 
639
+ /* 触控友好的输入框 - 更紧凑 */
640
  input[type="text"],
641
  input[type="password"],
642
  input[type="number"],
643
  input[type="color"],
 
644
  select {
645
+ padding: 8px 10px;
646
+ font-size: 14px;
647
+ border-radius: var(--radius);
648
+ min-height: 36px;
649
  }
650
 
651
  textarea {
652
+ padding: 8px 10px;
653
+ font-size: 14px;
654
+ min-height: 70px;
655
  }
656
 
657
+ /* 按钮优化 - 更紧凑 */
658
  button {
659
+ padding: 10px 16px;
660
+ font-size: 14px;
661
+ min-height: 40px;
662
+ border-radius: var(--radius);
663
  }
664
 
665
  /* 开关优化 */
 
725
  padding-bottom: 90px;
726
  }
727
 
728
+ /* 结果展示优化 - 更大空间 */
729
  .result {
730
  margin-top: 16px;
731
+ gap: 12px;
732
  }
733
 
734
  .result img {
735
+ border-radius: var(--radius);
736
+ box-shadow: 0 4px 16px rgba(0,0,0,0.15);
737
+ max-width: 100%;
738
+ height: auto;
739
+ min-height: 300px;
740
+ object-fit: contain;
741
  }
742
 
743
+ /* 图片信息区域 */
744
+ .image-info {
745
+ background: var(--panel);
746
+ border: 1px solid var(--border);
747
+ border-radius: var(--radius);
748
+ padding: 12px;
749
+ font-size: 13px;
750
+ line-height: 1.6;
751
  }
752
 
753
+ .image-info-header {
754
+ display: flex;
755
+ justify-content: space-between;
756
+ align-items: center;
757
+ margin-bottom: 8px;
758
+ padding-bottom: 6px;
759
+ border-bottom: 1px solid var(--border);
760
+ }
761
+
762
+ .image-info-title {
763
+ font-weight: 700;
764
+ font-size: 14px;
765
+ color: var(--text);
766
+ }
767
+
768
+ .image-info-toggle {
769
+ appearance: none;
770
+ background: var(--card);
771
+ border: 1px solid var(--border);
772
+ color: var(--text);
773
+ cursor: pointer;
774
+ padding: 4px 12px;
775
+ font-size: 12px;
776
+ font-weight: 600;
777
+ border-radius: var(--radius);
778
+ transition: all 0.2s ease;
779
+ }
780
+
781
+ .image-info-toggle:active {
782
+ transform: scale(0.95);
783
+ }
784
+
785
+ .image-info-content {
786
+ display: none;
787
+ margin-top: 8px;
788
+ }
789
+
790
+ .image-info-content.expanded {
791
+ display: block;
792
+ animation: slideDown 0.2s ease;
793
+ }
794
+
795
+ @keyframes slideDown {
796
+ from {
797
+ opacity: 0;
798
+ transform: translateY(-5px);
799
+ }
800
+ to {
801
+ opacity: 1;
802
+ transform: translateY(0);
803
+ }
804
  }
805
 
806
+ .image-info-row {
807
+ margin-bottom: 10px;
808
+ word-break: break-word;
809
+ display: flex;
810
+ flex-direction: column;
811
+ gap: 4px;
812
+ }
813
+
814
+ .image-info-row:last-child {
815
+ margin-bottom: 0;
816
+ }
817
+
818
+ .image-info-label {
819
+ color: var(--muted);
820
+ font-weight: 700;
821
+ font-size: 12px;
822
+ text-transform: uppercase;
823
+ letter-spacing: 0.5px;
824
+ }
825
+
826
+ .image-info-value {
827
+ color: var(--text);
828
  font-size: 13px;
829
+ line-height: 1.5;
830
+ padding-left: 8px;
831
  }
832
 
833
+ /* 隐藏保存路径 */
834
+ .saved-path {
835
+ display: none;
836
+ }
837
+
838
+ /* Toast 优化 - 顶部不占位 */
839
  .toast {
840
+ top: 45px;
841
  max-width: calc(100% - 32px);
842
+ padding: 10px 12px;
843
+ font-size: 13px;
844
  }
845
 
846
+ /* 标题优化 - 更小 */
847
  h2 {
848
+ font-size: 15px;
849
+ margin: 0 0 10px;
850
+ font-weight: 700;
851
  }
852
 
853
+ /* 标签字体优化 - 更小 */
854
  label {
855
+ font-size: 12px;
856
  }
857
 
858
  label > span {
859
  font-weight: 600;
860
+ margin-bottom: 2px;
861
  }
862
 
863
  /* 信息提示优化 */
864
  .message {
865
+ font-size: 12px;
866
+ margin-top: 8px;
867
  }
868
 
869
  /* 滚动条隐藏(更流畅的移动体验) */
frontend/index.html CHANGED
@@ -217,6 +217,30 @@
217
  </div>
218
  <div class="result">
219
  <img id="t2i-img" alt="生成结果" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  <div class="saved-path">
221
  <label>保存路径</label>
222
  <input id="t2i-saved" type="text" readonly />
@@ -311,6 +335,30 @@
311
  </div>
312
  <div class="result">
313
  <img id="i2i-img" alt="生成结果" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
  <div class="saved-path">
315
  <label>保存路径</label>
316
  <input id="i2i-saved" type="text" readonly />
@@ -413,6 +461,30 @@
413
  </div>
414
  <div class="result">
415
  <img id="inpaint-img" alt="生成结果" />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
416
  <div class="saved-path">
417
  <label>保存路径</label>
418
  <input id="inpaint-saved" type="text" readonly />
 
217
  </div>
218
  <div class="result">
219
  <img id="t2i-img" alt="生成结果" />
220
+ <div class="image-info" id="t2i-info" style="display:none;">
221
+ <div class="image-info-header">
222
+ <span class="image-info-title">图片信息</span>
223
+ <button class="image-info-toggle" data-target="t2i-info-content">展开 ▼</button>
224
+ </div>
225
+ <div class="image-info-content" id="t2i-info-content">
226
+ <div class="image-info-row">
227
+ <span class="image-info-label">模型</span>
228
+ <span class="image-info-value" id="t2i-model"></span>
229
+ </div>
230
+ <div class="image-info-row">
231
+ <span class="image-info-label">分辨率</span>
232
+ <span class="image-info-value" id="t2i-resolution"></span>
233
+ </div>
234
+ <div class="image-info-row">
235
+ <span class="image-info-label">正面提示词</span>
236
+ <span class="image-info-value" id="t2i-prompt-text"></span>
237
+ </div>
238
+ <div class="image-info-row">
239
+ <span class="image-info-label">负面提示词</span>
240
+ <span class="image-info-value" id="t2i-negative-text"></span>
241
+ </div>
242
+ </div>
243
+ </div>
244
  <div class="saved-path">
245
  <label>保存路径</label>
246
  <input id="t2i-saved" type="text" readonly />
 
335
  </div>
336
  <div class="result">
337
  <img id="i2i-img" alt="生成结果" />
338
+ <div class="image-info" id="i2i-info" style="display:none;">
339
+ <div class="image-info-header">
340
+ <span class="image-info-title">图片信息</span>
341
+ <button class="image-info-toggle" data-target="i2i-info-content">展开 ▼</button>
342
+ </div>
343
+ <div class="image-info-content" id="i2i-info-content">
344
+ <div class="image-info-row">
345
+ <span class="image-info-label">模型</span>
346
+ <span class="image-info-value" id="i2i-model"></span>
347
+ </div>
348
+ <div class="image-info-row">
349
+ <span class="image-info-label">分辨率</span>
350
+ <span class="image-info-value" id="i2i-resolution"></span>
351
+ </div>
352
+ <div class="image-info-row">
353
+ <span class="image-info-label">正面提示词</span>
354
+ <span class="image-info-value" id="i2i-prompt-text"></span>
355
+ </div>
356
+ <div class="image-info-row">
357
+ <span class="image-info-label">负面提示词</span>
358
+ <span class="image-info-value" id="i2i-negative-text"></span>
359
+ </div>
360
+ </div>
361
+ </div>
362
  <div class="saved-path">
363
  <label>保存路径</label>
364
  <input id="i2i-saved" type="text" readonly />
 
461
  </div>
462
  <div class="result">
463
  <img id="inpaint-img" alt="生成结果" />
464
+ <div class="image-info" id="inpaint-info" style="display:none;">
465
+ <div class="image-info-header">
466
+ <span class="image-info-title">图片信息</span>
467
+ <button class="image-info-toggle" data-target="inpaint-info-content">展开 ▼</button>
468
+ </div>
469
+ <div class="image-info-content" id="inpaint-info-content">
470
+ <div class="image-info-row">
471
+ <span class="image-info-label">模型</span>
472
+ <span class="image-info-value" id="inpaint-model"></span>
473
+ </div>
474
+ <div class="image-info-row">
475
+ <span class="image-info-label">分辨率</span>
476
+ <span class="image-info-value" id="inpaint-resolution"></span>
477
+ </div>
478
+ <div class="image-info-row">
479
+ <span class="image-info-label">正面提示词</span>
480
+ <span class="image-info-value" id="inpaint-prompt-text"></span>
481
+ </div>
482
+ <div class="image-info-row">
483
+ <span class="image-info-label">负面提示词</span>
484
+ <span class="image-info-value" id="inpaint-negative-text"></span>
485
+ </div>
486
+ </div>
487
+ </div>
488
  <div class="saved-path">
489
  <label>保存路径</label>
490
  <input id="inpaint-saved" type="text" readonly />