vomebook commited on
Commit
3ec41fd
·
1 Parent(s): 946577b

Upload 3 files

Browse files
Files changed (3) hide show
  1. static/app.js +64 -9
  2. static/index.html +14 -2
  3. static/style.css +9 -0
static/app.js CHANGED
@@ -149,6 +149,8 @@ function cacheDOM() {
149
  DOM.filterExtList = $("#filter-ext-list");
150
  DOM.filterMinSize = $("#filter-min-size");
151
  DOM.filterMaxSize = $("#filter-max-size");
 
 
152
  DOM.closeFiltersBtn = $("#close-filters-btn");
153
  DOM.folderSelectAll = $("#folder-select-all");
154
  DOM.folderDeselectAll = $("#folder-deselect-all");
@@ -373,8 +375,8 @@ function syncStateToURL(replace = true) {
373
  if (DOM.sortSelect.value !== "relevance") {
374
  params.set("sort", DOM.sortSelect.value);
375
  }
376
- if (STATE.filterMinSize !== null) params.set("min_size", STATE.filterMinSize);
377
- if (STATE.filterMaxSize !== null) params.set("max_size", STATE.filterMaxSize);
378
  if (!STATE.searchFolders) params.set("search_folders", "false");
379
  if (STATE.exact) params.set("exact", "1");
380
 
@@ -406,12 +408,30 @@ function syncURLToState() {
406
  DOM.sortSelect.value = sort;
407
 
408
  const minSize = params.get("min_size");
409
- STATE.filterMinSize = minSize ? parseInt(minSize) : null;
410
- DOM.filterMinSize.value = minSize || "";
 
 
 
 
 
 
 
 
 
411
 
412
  const maxSize = params.get("max_size");
413
- STATE.filterMaxSize = maxSize ? parseInt(maxSize) : null;
414
- DOM.filterMaxSize.value = maxSize || "";
 
 
 
 
 
 
 
 
 
415
 
416
  const searchFolders = params.get("search_folders");
417
  STATE.searchFolders = searchFolders !== "false";
@@ -1229,6 +1249,7 @@ function clearAllFilters() {
1229
  STATE.filterMinSize = null; STATE.filterMaxSize = null;
1230
  STATE.page = 1; STATE.results = [];
1231
  DOM.filterMinSize.value = ""; DOM.filterMaxSize.value = "";
 
1232
  renderFilters(); doSearch(); showToast("已清空所有筛选条件");
1233
  syncStateToURL(true);
1234
  }
@@ -1337,9 +1358,43 @@ async function init() {
1337
  DOM.emptyRandomBtn.addEventListener('click', randomBook);
1338
 
1339
  let sizeTimer;
1340
- const onSize = () => { clearTimeout(sizeTimer); sizeTimer = setTimeout(() => { STATE.filterMinSize = DOM.filterMinSize.value ? parseInt(DOM.filterMinSize.value) : null; STATE.filterMaxSize = DOM.filterMaxSize.value ? parseInt(DOM.filterMaxSize.value) : null; STATE.page = 1; STATE.results = []; doSearch(); }, 500); };
1341
- DOM.filterMinSize.addEventListener("input", onSize);
1342
- DOM.filterMaxSize.addEventListener("input", onSize);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1343
 
1344
  DOM.extSelectAll.addEventListener("click", () => { STATE.filterExtensions = (STATE.extensionList || []).map(e => e.name); STATE.page = 1; STATE.results = []; doSearch(); renderExtensionFilter(); });
1345
  DOM.extDeselectAll.addEventListener("click", () => {
 
149
  DOM.filterExtList = $("#filter-ext-list");
150
  DOM.filterMinSize = $("#filter-min-size");
151
  DOM.filterMaxSize = $("#filter-max-size");
152
+ DOM.filterMinUnit = $("#filter-min-unit");
153
+ DOM.filterMaxUnit = $("#filter-max-unit");
154
  DOM.closeFiltersBtn = $("#close-filters-btn");
155
  DOM.folderSelectAll = $("#folder-select-all");
156
  DOM.folderDeselectAll = $("#folder-deselect-all");
 
375
  if (DOM.sortSelect.value !== "relevance") {
376
  params.set("sort", DOM.sortSelect.value);
377
  }
378
+ if (STATE.filterMinSize !== null) params.set("min_size", fmtSizeUrl(STATE.filterMinSize));
379
+ if (STATE.filterMaxSize !== null) params.set("max_size", fmtSizeUrl(STATE.filterMaxSize));
380
  if (!STATE.searchFolders) params.set("search_folders", "false");
381
  if (STATE.exact) params.set("exact", "1");
382
 
 
408
  DOM.sortSelect.value = sort;
409
 
410
  const minSize = params.get("min_size");
411
+ if (minSize) {
412
+ var parsed = parseSizeStr(minSize);
413
+ STATE.filterMinSize = parsed;
414
+ var disp = bytesToDisplay(parsed);
415
+ DOM.filterMinSize.value = disp.value;
416
+ DOM.filterMinUnit.value = disp.unit;
417
+ } else {
418
+ STATE.filterMinSize = null;
419
+ DOM.filterMinSize.value = "";
420
+ DOM.filterMinUnit.value = "MB";
421
+ }
422
 
423
  const maxSize = params.get("max_size");
424
+ if (maxSize) {
425
+ var parsedMx = parseSizeStr(maxSize);
426
+ STATE.filterMaxSize = parsedMx;
427
+ var dispMx = bytesToDisplay(parsedMx);
428
+ DOM.filterMaxSize.value = dispMx.value;
429
+ DOM.filterMaxUnit.value = dispMx.unit;
430
+ } else {
431
+ STATE.filterMaxSize = null;
432
+ DOM.filterMaxSize.value = "";
433
+ DOM.filterMaxUnit.value = "MB";
434
+ }
435
 
436
  const searchFolders = params.get("search_folders");
437
  STATE.searchFolders = searchFolders !== "false";
 
1249
  STATE.filterMinSize = null; STATE.filterMaxSize = null;
1250
  STATE.page = 1; STATE.results = [];
1251
  DOM.filterMinSize.value = ""; DOM.filterMaxSize.value = "";
1252
+ DOM.filterMinUnit.value = "MB"; DOM.filterMaxUnit.value = "MB";
1253
  renderFilters(); doSearch(); showToast("已清空所有筛选条件");
1254
  syncStateToURL(true);
1255
  }
 
1358
  DOM.emptyRandomBtn.addEventListener('click', randomBook);
1359
 
1360
  let sizeTimer;
1361
+ const sizeInputToBytes = (input, unitSelect) => {
1362
+ var val = parseFloat(input.value);
1363
+ if (isNaN(val) || val < 0) return null;
1364
+ var unit = unitSelect.value;
1365
+ if (unit === "KB") val *= 1024;
1366
+ else if (unit === "MB") val *= 1048576;
1367
+ else if (unit === "GB") val *= 1073741824;
1368
+ return Math.round(val);
1369
+ };
1370
+ const bytesToDisplay = (bytes) => {
1371
+ if (bytes === null || bytes === undefined || bytes === 0) return { value: "", unit: "MB" };
1372
+ if (bytes >= 1073741824) return { value: (bytes / 1073741824).toFixed(2).replace(/\.?0+$/, ""), unit: "GB" };
1373
+ if (bytes >= 1048576) return { value: (bytes / 1048576).toFixed(1).replace(/\.0$/, ""), unit: "MB" };
1374
+ if (bytes >= 1024) return { value: (bytes / 1024).toFixed(1).replace(/\.0$/, ""), unit: "KB" };
1375
+ return { value: String(bytes), unit: "B" };
1376
+ };
1377
+ const fmtSizeUrl = (bytes) => {
1378
+ if (bytes === null || bytes === undefined) return null;
1379
+ var d = bytesToDisplay(bytes);
1380
+ return d.value + d.unit;
1381
+ };
1382
+ const parseSizeStr = (str) => {
1383
+ if (!str) return null;
1384
+ var m = String(str).match(/^([\d.]+)\s*(GB|MB|KB|B)?$/i);
1385
+ if (!m) return parseInt(str) || null;
1386
+ var val = parseFloat(m[1]);
1387
+ var unit = (m[2] || "B").toUpperCase();
1388
+ if (unit === "GB") val *= 1073741824;
1389
+ else if (unit === "MB") val *= 1048576;
1390
+ else if (unit === "KB") val *= 1024;
1391
+ return Math.round(val);
1392
+ };
1393
+ const applySizeFilter = () => { clearTimeout(sizeTimer); sizeTimer = setTimeout(() => { STATE.filterMinSize = sizeInputToBytes(DOM.filterMinSize, DOM.filterMinUnit); STATE.filterMaxSize = sizeInputToBytes(DOM.filterMaxSize, DOM.filterMaxUnit); STATE.page = 1; STATE.results = []; doSearch(); }, 500); };
1394
+ DOM.filterMinSize.addEventListener("input", applySizeFilter);
1395
+ DOM.filterMaxSize.addEventListener("input", applySizeFilter);
1396
+ DOM.filterMinUnit.addEventListener("change", applySizeFilter);
1397
+ DOM.filterMaxUnit.addEventListener("change", applySizeFilter);
1398
 
1399
  DOM.extSelectAll.addEventListener("click", () => { STATE.filterExtensions = (STATE.extensionList || []).map(e => e.name); STATE.page = 1; STATE.results = []; doSearch(); renderExtensionFilter(); });
1400
  DOM.extDeselectAll.addEventListener("click", () => {
static/index.html CHANGED
@@ -214,9 +214,21 @@
214
  <div class="filter-section">
215
  <div class="filter-section-title">文件大小</div>
216
  <div class="filter-size-row">
217
- <input type="number" id="filter-min-size" class="size-input" placeholder="最小 (字节)" min="0" step="1">
 
 
 
 
 
 
218
  <span class="size-sep">—</span>
219
- <input type="number" id="filter-max-size" class="size-input" placeholder="最大 (字节)" min="0" step="1">
 
 
 
 
 
 
220
  </div>
221
  </div>
222
  </div>
 
214
  <div class="filter-section">
215
  <div class="filter-section-title">文件大小</div>
216
  <div class="filter-size-row">
217
+ <input type="number" id="filter-min-size" class="size-input" placeholder="最小" min="0" step="0.1">
218
+ <select id="filter-min-unit" class="size-unit">
219
+ <option value="B">B</option>
220
+ <option value="KB">KB</option>
221
+ <option value="MB" selected>MB</option>
222
+ <option value="GB">GB</option>
223
+ </select>
224
  <span class="size-sep">—</span>
225
+ <input type="number" id="filter-max-size" class="size-input" placeholder="最大" min="0" step="0.1">
226
+ <select id="filter-max-unit" class="size-unit">
227
+ <option value="B">B</option>
228
+ <option value="KB">KB</option>
229
+ <option value="MB" selected>MB</option>
230
+ <option value="GB">GB</option>
231
+ </select>
232
  </div>
233
  </div>
234
  </div>
static/style.css CHANGED
@@ -1030,6 +1030,15 @@ body.light .left-sidebar.expanded-wide .browser-item:nth-child(even) {
1030
  .size-input:focus {
1031
  border-color: var(--primary);
1032
  }
 
 
 
 
 
 
 
 
 
1033
 
1034
  .size-sep {
1035
  font-size: 12px;
 
1030
  .size-input:focus {
1031
  border-color: var(--primary);
1032
  }
1033
+ .size-unit {
1034
+ font-size: 12px;
1035
+ padding: 6px 4px;
1036
+ border: 1px solid var(--outline-variant);
1037
+ border-radius: var(--radius-sm);
1038
+ background: var(--surface);
1039
+ color: var(--on-surface);
1040
+ cursor: pointer;
1041
+ }
1042
 
1043
  .size-sep {
1044
  font-size: 12px;