Logankunfall commited on
Commit
01a4f9c
·
verified ·
1 Parent(s): d37e319

Upload 21 files

Browse files
Files changed (2) hide show
  1. frontend/assets/app.js +166 -2
  2. frontend/index.html +0 -1
frontend/assets/app.js CHANGED
@@ -8,6 +8,12 @@
8
  let soundEnabled = false;
9
  let soundUrl = "/ring/ring.mp3";
10
 
 
 
 
 
 
 
11
  // ===== 移动端后台恢复处理 =====
12
  // 修复手机切屏后回来无法输入的问题
13
  function handlePageResume() {
@@ -385,8 +391,146 @@
385
  }
386
  }
387
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
388
  // T2I
389
  async function handleT2I() {
 
 
 
390
  const payloadBase = {
391
  prompt: byId("t2i-prompt").value || "",
392
  negative: byId("t2i-negative").value || "",
@@ -466,6 +610,9 @@
466
 
467
  // I2I
468
  async function handleI2I() {
 
 
 
469
  const file = byId("i2i-image").files?.[0];
470
  if (!file) {
471
  toast("请上传输入图片", "error");
@@ -555,6 +702,9 @@
555
 
556
  // Inpaint
557
  async function handleInpaint() {
 
 
 
558
  const imgFile = byId("inpaint-image").files?.[0];
559
  const maskFile = byId("inpaint-mask").files?.[0];
560
  if (!imgFile || !maskFile) {
@@ -652,11 +802,16 @@
652
  ensureCountField("tab-i2i", "i2i-count");
653
  ensureCountField("tab-inpaint", "inpaint-count");
654
 
655
- byId("btn-load-config").addEventListener("click", loadConfig);
656
  byId("btn-save-config").addEventListener("click", saveConfig);
657
  const selOutBtn = byId("btn-select-output-dir");
658
  if (selOutBtn) {
659
  selOutBtn.addEventListener("click", async () => {
 
 
 
 
 
 
660
  try {
661
  loading.show();
662
  const res = await fetch("/api/select-output-dir");
@@ -690,6 +845,12 @@
690
  const openOutBtn = byId("btn-open-output-dir");
691
  if (openOutBtn) {
692
  openOutBtn.addEventListener("click", async () => {
 
 
 
 
 
 
693
  try {
694
  loading.show();
695
  const p = byId("cfg-output-dir")?.value || "";
@@ -728,6 +889,9 @@
728
  // 设置图片信息展开/收起功能
729
  setupImageInfoToggle();
730
 
731
- // Init
732
  loadConfig();
 
 
 
733
  })();
 
8
  let soundEnabled = false;
9
  let soundUrl = "/ring/ring.mp3";
10
 
11
+ // 检测是否为移动端设备
12
+ function isMobileDevice() {
13
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ||
14
+ (window.innerWidth <= 768);
15
+ }
16
+
17
  // ===== 移动端后台恢复处理 =====
18
  // 修复手机切屏后回来无法输入的问题
19
  function handlePageResume() {
 
391
  }
392
  }
393
 
394
+ // ===== localStorage 生成参数保存/恢复 =====
395
+ const STORAGE_KEY_T2I = 'nai_t2i_params';
396
+ const STORAGE_KEY_I2I = 'nai_i2i_params';
397
+ const STORAGE_KEY_INPAINT = 'nai_inpaint_params';
398
+
399
+ function saveT2IParams() {
400
+ const params = {
401
+ prompt: byId("t2i-prompt").value || "",
402
+ negative: byId("t2i-negative").value || "",
403
+ width: byId("t2i-width").value || "768",
404
+ height: byId("t2i-height").value || "768",
405
+ steps: byId("t2i-steps").value || "",
406
+ scale: byId("t2i-scale").value || "",
407
+ sampler: byId("t2i-sampler").value || "",
408
+ noise_schedule: byId("t2i-noise-schedule").value || "",
409
+ seed: byId("t2i-seed").value || "-1",
410
+ variety: byId("t2i-variety").checked,
411
+ decrisp: byId("t2i-decrisp").checked,
412
+ cfg_rescale: byId("t2i-cfg-rescale").value || "",
413
+ count: byId("t2i-count")?.value || "1"
414
+ };
415
+ try { localStorage.setItem(STORAGE_KEY_T2I, JSON.stringify(params)); } catch {}
416
+ }
417
+
418
+ function restoreT2IParams() {
419
+ try {
420
+ const saved = localStorage.getItem(STORAGE_KEY_T2I);
421
+ if (!saved) return;
422
+ const params = JSON.parse(saved);
423
+ if (params.prompt !== undefined) byId("t2i-prompt").value = params.prompt;
424
+ if (params.negative !== undefined) byId("t2i-negative").value = params.negative;
425
+ if (params.width) byId("t2i-width").value = params.width;
426
+ if (params.height) byId("t2i-height").value = params.height;
427
+ if (params.steps) byId("t2i-steps").value = params.steps;
428
+ if (params.scale) byId("t2i-scale").value = params.scale;
429
+ if (params.sampler !== undefined) byId("t2i-sampler").value = params.sampler;
430
+ if (params.noise_schedule !== undefined) byId("t2i-noise-schedule").value = params.noise_schedule;
431
+ if (params.seed !== undefined) byId("t2i-seed").value = params.seed;
432
+ if (params.variety !== undefined) byId("t2i-variety").checked = params.variety;
433
+ if (params.decrisp !== undefined) byId("t2i-decrisp").checked = params.decrisp;
434
+ if (params.cfg_rescale) byId("t2i-cfg-rescale").value = params.cfg_rescale;
435
+ if (params.count && byId("t2i-count")) byId("t2i-count").value = params.count;
436
+ } catch {}
437
+ }
438
+
439
+ function saveI2IParams() {
440
+ const params = {
441
+ positive: byId("i2i-positive").value || "",
442
+ negative: byId("i2i-negative").value || "",
443
+ width: byId("i2i-width").value || "",
444
+ height: byId("i2i-height").value || "",
445
+ steps: byId("i2i-steps").value || "",
446
+ scale: byId("i2i-scale").value || "",
447
+ sampler: byId("i2i-sampler").value || "",
448
+ noise_schedule: byId("i2i-noise-schedule").value || "",
449
+ seed: byId("i2i-seed").value || "-1",
450
+ strength: byId("i2i-strength").value || "0.5",
451
+ noise: byId("i2i-noise").value || "0.0",
452
+ variety: byId("i2i-variety").checked,
453
+ decrisp: byId("i2i-decrisp").checked,
454
+ cfg_rescale: byId("i2i-cfg-rescale").value || "",
455
+ count: byId("i2i-count")?.value || "1"
456
+ };
457
+ try { localStorage.setItem(STORAGE_KEY_I2I, JSON.stringify(params)); } catch {}
458
+ }
459
+
460
+ function restoreI2IParams() {
461
+ try {
462
+ const saved = localStorage.getItem(STORAGE_KEY_I2I);
463
+ if (!saved) return;
464
+ const params = JSON.parse(saved);
465
+ if (params.positive !== undefined) byId("i2i-positive").value = params.positive;
466
+ if (params.negative !== undefined) byId("i2i-negative").value = params.negative;
467
+ if (params.width) byId("i2i-width").value = params.width;
468
+ if (params.height) byId("i2i-height").value = params.height;
469
+ if (params.steps) byId("i2i-steps").value = params.steps;
470
+ if (params.scale) byId("i2i-scale").value = params.scale;
471
+ if (params.sampler !== undefined) byId("i2i-sampler").value = params.sampler;
472
+ if (params.noise_schedule !== undefined) byId("i2i-noise-schedule").value = params.noise_schedule;
473
+ if (params.seed !== undefined) byId("i2i-seed").value = params.seed;
474
+ if (params.strength !== undefined) byId("i2i-strength").value = params.strength;
475
+ if (params.noise !== undefined) byId("i2i-noise").value = params.noise;
476
+ if (params.variety !== undefined) byId("i2i-variety").checked = params.variety;
477
+ if (params.decrisp !== undefined) byId("i2i-decrisp").checked = params.decrisp;
478
+ if (params.cfg_rescale) byId("i2i-cfg-rescale").value = params.cfg_rescale;
479
+ if (params.count && byId("i2i-count")) byId("i2i-count").value = params.count;
480
+ } catch {}
481
+ }
482
+
483
+ function saveInpaintParams() {
484
+ const params = {
485
+ positive: byId("inpaint-positive").value || "",
486
+ negative: byId("inpaint-negative").value || "",
487
+ add_original: byId("inpaint-add-original").checked,
488
+ width: byId("inpaint-width").value || "",
489
+ height: byId("inpaint-height").value || "",
490
+ steps: byId("inpaint-steps").value || "",
491
+ scale: byId("inpaint-scale").value || "",
492
+ sampler: byId("inpaint-sampler").value || "",
493
+ noise_schedule: byId("inpaint-noise-schedule").value || "",
494
+ seed: byId("inpaint-seed").value || "-1",
495
+ strength: byId("inpaint-strength").value || "0.5",
496
+ noise: byId("inpaint-noise-val").value || "0.0",
497
+ variety: byId("inpaint-variety").checked,
498
+ decrisp: byId("inpaint-decrisp").checked,
499
+ cfg_rescale: byId("inpaint-cfg-rescale").value || "",
500
+ count: byId("inpaint-count")?.value || "1"
501
+ };
502
+ try { localStorage.setItem(STORAGE_KEY_INPAINT, JSON.stringify(params)); } catch {}
503
+ }
504
+
505
+ function restoreInpaintParams() {
506
+ try {
507
+ const saved = localStorage.getItem(STORAGE_KEY_INPAINT);
508
+ if (!saved) return;
509
+ const params = JSON.parse(saved);
510
+ if (params.positive !== undefined) byId("inpaint-positive").value = params.positive;
511
+ if (params.negative !== undefined) byId("inpaint-negative").value = params.negative;
512
+ if (params.add_original !== undefined) byId("inpaint-add-original").checked = params.add_original;
513
+ if (params.width) byId("inpaint-width").value = params.width;
514
+ if (params.height) byId("inpaint-height").value = params.height;
515
+ if (params.steps) byId("inpaint-steps").value = params.steps;
516
+ if (params.scale) byId("inpaint-scale").value = params.scale;
517
+ if (params.sampler !== undefined) byId("inpaint-sampler").value = params.sampler;
518
+ if (params.noise_schedule !== undefined) byId("inpaint-noise-schedule").value = params.noise_schedule;
519
+ if (params.seed !== undefined) byId("inpaint-seed").value = params.seed;
520
+ if (params.strength !== undefined) byId("inpaint-strength").value = params.strength;
521
+ if (params.noise !== undefined) byId("inpaint-noise-val").value = params.noise;
522
+ if (params.variety !== undefined) byId("inpaint-variety").checked = params.variety;
523
+ if (params.decrisp !== undefined) byId("inpaint-decrisp").checked = params.decrisp;
524
+ if (params.cfg_rescale) byId("inpaint-cfg-rescale").value = params.cfg_rescale;
525
+ if (params.count && byId("inpaint-count")) byId("inpaint-count").value = params.count;
526
+ } catch {}
527
+ }
528
+
529
  // T2I
530
  async function handleT2I() {
531
+ // 保存当前参数到 localStorage
532
+ saveT2IParams();
533
+
534
  const payloadBase = {
535
  prompt: byId("t2i-prompt").value || "",
536
  negative: byId("t2i-negative").value || "",
 
610
 
611
  // I2I
612
  async function handleI2I() {
613
+ // 保存当前参数到 localStorage
614
+ saveI2IParams();
615
+
616
  const file = byId("i2i-image").files?.[0];
617
  if (!file) {
618
  toast("请上传输入图片", "error");
 
702
 
703
  // Inpaint
704
  async function handleInpaint() {
705
+ // 保存当前参数到 localStorage
706
+ saveInpaintParams();
707
+
708
  const imgFile = byId("inpaint-image").files?.[0];
709
  const maskFile = byId("inpaint-mask").files?.[0];
710
  if (!imgFile || !maskFile) {
 
802
  ensureCountField("tab-i2i", "i2i-count");
803
  ensureCountField("tab-inpaint", "inpaint-count");
804
 
 
805
  byId("btn-save-config").addEventListener("click", saveConfig);
806
  const selOutBtn = byId("btn-select-output-dir");
807
  if (selOutBtn) {
808
  selOutBtn.addEventListener("click", async () => {
809
+ // 移动端检测:手机无法弹出服务器上的目录选择器
810
+ if (isMobileDevice()) {
811
+ toast("手机端请直接在输入框中填写目录路径", "info");
812
+ return;
813
+ }
814
+
815
  try {
816
  loading.show();
817
  const res = await fetch("/api/select-output-dir");
 
845
  const openOutBtn = byId("btn-open-output-dir");
846
  if (openOutBtn) {
847
  openOutBtn.addEventListener("click", async () => {
848
+ // 移动端检测:手机无法打开服务器上的目录
849
+ if (isMobileDevice()) {
850
+ toast("手机端无法打开服务器目录,请在电脑上操作", "info");
851
+ return;
852
+ }
853
+
854
  try {
855
  loading.show();
856
  const p = byId("cfg-output-dir")?.value || "";
 
889
  // 设置图片信息展开/收起功能
890
  setupImageInfoToggle();
891
 
892
+ // Init - 加载配置和恢复上次的生成参数
893
  loadConfig();
894
+ restoreT2IParams();
895
+ restoreI2IParams();
896
+ restoreInpaintParams();
897
  })();
frontend/index.html CHANGED
@@ -122,7 +122,6 @@
122
  </label>
123
  </div>
124
  <div class="actions">
125
- <button id="btn-load-config">读取配置</button>
126
  <button id="btn-select-output-dir">选择保存目录</button>
127
  <button id="btn-open-output-dir">打开保存目录</button>
128
  <button id="btn-save-config" class="primary">保存配置</button>
 
122
  </label>
123
  </div>
124
  <div class="actions">
 
125
  <button id="btn-select-output-dir">选择保存目录</button>
126
  <button id="btn-open-output-dir">打开保存目录</button>
127
  <button id="btn-save-config" class="primary">保存配置</button>