BirkhoffLee commited on
Commit
50428e9
·
unverified ·
1 Parent(s): cf2569a

feat: 增加了预览功能

Browse files
Files changed (1) hide show
  1. app/static/index.html +83 -9
app/static/index.html CHANGED
@@ -242,6 +242,24 @@
242
  }
243
 
244
  #toast.show { opacity: 1; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  </style>
246
  </head>
247
  <body>
@@ -323,7 +341,7 @@
323
  <label class="bool-item"><input type="checkbox" id="append_type"> append_type</label>
324
  <label class="bool-item"><input type="checkbox" id="scv"> scv</label>
325
  <label class="bool-item"><input type="checkbox" id="append_info" checked> append_info</label>
326
- <label class="bool-item"><input type="checkbox" id="new_name" checked> new_name</label>
327
  </div>
328
  </div>
329
  </div>
@@ -340,6 +358,10 @@
340
  <div class="result-actions">
341
  <button class="btn btn-sm" id="copy-btn" type="button">复制</button>
342
  <button class="btn btn-sm" id="open-btn" type="button">在新标签打开</button>
 
 
 
 
343
  </div>
344
  </div>
345
  </div>
@@ -359,6 +381,20 @@ advancedToggle.addEventListener('click', () => {
359
  toggleIcon.textContent = open ? '▼' : '▶';
360
  });
361
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
  // 生成链接
363
  document.getElementById('gen-btn').addEventListener('click', async () => {
364
  const url = document.getElementById('url').value.trim();
@@ -382,13 +418,12 @@ document.getElementById('gen-btn').addEventListener('click', async () => {
382
 
383
  const extra = targetMap[targetVal] || { target: targetVal };
384
 
385
- // 读取 bool 开关(仅将被勾选 checkbox 后端)
386
- const boolFields = ['emoji','udp','tfo','sort','fdn','expand','append_type','scv','append_info','new_name'];
387
  const boolValues = {};
388
  boolFields.forEach(id => {
389
- const el = document.getElementById(id);
390
- // 只把勾选状态传递(后端处理 None = 不传)
391
- boolValues[id] = el.checked;
392
  });
393
 
394
  // list 来自 extra(clash-list 模式)
@@ -408,10 +443,9 @@ document.getElementById('gen-btn').addEventListener('click', async () => {
408
  ...boolValues,
409
  };
410
 
411
- // 去掉 undefined/null 的 bool(后端会过滤 None,但前端先清理)
412
- // bool 字段全部传,后端自己判断
413
-
414
  hideError();
 
 
415
 
416
  try {
417
  const res = await fetch('/api/convert', {
@@ -434,6 +468,7 @@ document.getElementById('gen-btn').addEventListener('click', async () => {
434
  // 绑定按钮(每次生成都重新绑,避免重复监听器)
435
  const copyBtn = document.getElementById('copy-btn');
436
  const openBtn = document.getElementById('open-btn');
 
437
 
438
  copyBtn.onclick = () => {
439
  navigator.clipboard.writeText(fullUrl).then(() => showToast());
@@ -441,11 +476,50 @@ document.getElementById('gen-btn').addEventListener('click', async () => {
441
 
442
  openBtn.onclick = () => window.open(fullUrl, '_blank');
443
 
 
 
444
  } catch (e) {
445
  showError('网络错误:' + e.message);
446
  }
447
  });
448
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
449
  function showError(msg) {
450
  const el = document.getElementById('error-msg');
451
  el.textContent = msg;
 
242
  }
243
 
244
  #toast.show { opacity: 1; }
245
+
246
+ /* 预览区域 */
247
+ #preview-section { margin-top: 0.75rem; display: none; }
248
+ #preview-section.show { display: block; }
249
+ #preview-content {
250
+ background: #0a0c10;
251
+ border: 1px solid #2d3348;
252
+ border-radius: 8px;
253
+ padding: 0.75rem 1rem;
254
+ font-family: monospace;
255
+ font-size: 0.75rem;
256
+ color: #94a3b8;
257
+ max-height: 400px;
258
+ overflow-y: auto;
259
+ white-space: pre;
260
+ line-height: 1.4;
261
+ }
262
+ #preview-content.error { color: #fca5a5; }
263
  </style>
264
  </head>
265
  <body>
 
341
  <label class="bool-item"><input type="checkbox" id="append_type"> append_type</label>
342
  <label class="bool-item"><input type="checkbox" id="scv"> scv</label>
343
  <label class="bool-item"><input type="checkbox" id="append_info" checked> append_info</label>
344
+ <label class="bool-item"><input type="checkbox" id="new_name"> new_name</label>
345
  </div>
346
  </div>
347
  </div>
 
358
  <div class="result-actions">
359
  <button class="btn btn-sm" id="copy-btn" type="button">复制</button>
360
  <button class="btn btn-sm" id="open-btn" type="button">在新标签打开</button>
361
+ <button class="btn btn-sm" id="preview-btn" type="button">预览内容</button>
362
+ </div>
363
+ <div id="preview-section">
364
+ <pre id="preview-content"></pre>
365
  </div>
366
  </div>
367
  </div>
 
381
  toggleIcon.textContent = open ? '▼' : '▶';
382
  });
383
 
384
+ // subconverter 实际默认值,与之相同的 bool 不传(null = 后端跳过)
385
+ const BOOL_DEFAULTS = {
386
+ emoji: true,
387
+ udp: false,
388
+ tfo: false,
389
+ sort: false,
390
+ fdn: false,
391
+ expand: true,
392
+ append_type: false,
393
+ scv: false,
394
+ append_info: true,
395
+ new_name: false,
396
+ };
397
+
398
  // 生成链接
399
  document.getElementById('gen-btn').addEventListener('click', async () => {
400
  const url = document.getElementById('url').value.trim();
 
418
 
419
  const extra = targetMap[targetVal] || { target: targetVal };
420
 
421
+ // 只传与默认值不同的 bool,相同的传 null(后端跳过
422
+ const boolFields = Object.keys(BOOL_DEFAULTS);
423
  const boolValues = {};
424
  boolFields.forEach(id => {
425
+ const val = document.getElementById(id).checked;
426
+ boolValues[id] = (val === BOOL_DEFAULTS[id]) ? null : val;
 
427
  });
428
 
429
  // list 来自 extra(clash-list 模式)
 
443
  ...boolValues,
444
  };
445
 
 
 
 
446
  hideError();
447
+ // 重置预览区
448
+ hidePreview();
449
 
450
  try {
451
  const res = await fetch('/api/convert', {
 
468
  // 绑定按钮(每次生成都重新绑,避免重复监听器)
469
  const copyBtn = document.getElementById('copy-btn');
470
  const openBtn = document.getElementById('open-btn');
471
+ const previewBtn = document.getElementById('preview-btn');
472
 
473
  copyBtn.onclick = () => {
474
  navigator.clipboard.writeText(fullUrl).then(() => showToast());
 
476
 
477
  openBtn.onclick = () => window.open(fullUrl, '_blank');
478
 
479
+ previewBtn.onclick = () => togglePreview(fullUrl, previewBtn);
480
+
481
  } catch (e) {
482
  showError('网络错误:' + e.message);
483
  }
484
  });
485
 
486
+ // 预览内容 toggle
487
+ async function togglePreview(fullUrl, btn) {
488
+ const section = document.getElementById('preview-section');
489
+ const content = document.getElementById('preview-content');
490
+
491
+ // 已展开则收起
492
+ if (section.classList.contains('show')) {
493
+ hidePreview();
494
+ return;
495
+ }
496
+
497
+ btn.textContent = '加载中…';
498
+ btn.disabled = true;
499
+
500
+ try {
501
+ const res = await fetch(fullUrl);
502
+ const text = await res.text();
503
+ const lines = text.split('\n');
504
+ content.textContent = lines.slice(0, 500).join('\n') + (lines.length > 500 ? '\n... (已截断)' : '');
505
+ content.classList.remove('error');
506
+ } catch (e) {
507
+ content.textContent = 'Error: ' + e.message;
508
+ content.classList.add('error');
509
+ }
510
+
511
+ section.classList.add('show');
512
+ btn.textContent = '预览内容';
513
+ btn.disabled = false;
514
+ }
515
+
516
+ function hidePreview() {
517
+ document.getElementById('preview-section').classList.remove('show');
518
+ document.getElementById('preview-content').textContent = '';
519
+ const btn = document.getElementById('preview-btn');
520
+ if (btn) { btn.textContent = '预览内容'; btn.disabled = false; }
521
+ }
522
+
523
  function showError(msg) {
524
  const el = document.getElementById('error-msg');
525
  el.textContent = msg;