(function initMediaMTXAdminList(root, factory) { "use strict"; const api = factory(); if (typeof module !== "undefined" && module.exports) module.exports = api; else root.MediaMTXAdminList = api; }(typeof globalThis !== "undefined" ? globalThis : this, () => { "use strict"; class PageLoadError extends Error { constructor(label, page, cause) { const detail = cause?.message ? `:${cause.message}` : "。"; super(`${label}第 ${page + 1} 页加载失败${detail}`); this.name = "PageLoadError"; this.status = Number.isInteger(cause?.status) ? cause.status : 0; this.page = page; this.cause = cause; } } function limitConcurrency(fetcher, requestedLimit) { const limit = Math.max(1, Number(requestedLimit) || 1); let active = 0; const queue = []; function runNext() { while (active < limit && queue.length > 0) { const task = queue.shift(); active += 1; Promise.resolve() .then(() => fetcher(...task.args)) .then(task.resolve, task.reject) .finally(() => { active -= 1; runNext(); }); } } return (...args) => new Promise((resolve, reject) => { queue.push({ args, resolve, reject }); runNext(); }); } function pageURL(endpoint, page, pageSize) { const separator = endpoint.includes("?") ? "&" : "?"; const query = new URLSearchParams({ itemsPerPage: String(pageSize), page: String(page), }); return `${endpoint}${separator}${query}`; } function validatePage(payload, label, page) { if (!payload || !Array.isArray(payload.items) || !Number.isInteger(payload.itemCount) || payload.itemCount < 0 || !Number.isInteger(payload.pageCount) || payload.pageCount < 0) { throw new PageLoadError(label, page, new Error("API 返回了无效的分页数据。")); } return payload; } async function fetchPage(fetcher, endpoint, label, page, pageSize) { try { const payload = await fetcher(pageURL(endpoint, page, pageSize)); return validatePage(payload, label, page); } catch (error) { if (error instanceof PageLoadError) throw error; throw new PageLoadError(label, page, error); } } async function fetchAllPages(fetcher, endpoint, options = {}) { const label = options.label || "列表"; const pageSize = options.pageSize || 100; const concurrency = Math.max(1, options.concurrency || 4); const onProgress = typeof options.onProgress === "function" ? options.onProgress : () => {}; const first = await fetchPage(fetcher, endpoint, label, 0, pageSize); const pageCount = first.pageCount; const pages = new Array(Math.max(1, pageCount)); pages[0] = first.items; let loaded = first.items.length; let pagesLoaded = 1; let stopped = false; onProgress({ label, loaded, total: first.itemCount, pagesLoaded, pageCount }); let nextPage = 1; const workerCount = Math.min(concurrency, Math.max(0, pageCount - 1)); const workers = Array.from({ length: workerCount }, async () => { while (!stopped && nextPage < pageCount) { const page = nextPage; nextPage += 1; let payload; try { payload = await fetchPage(fetcher, endpoint, label, page, pageSize); } catch (error) { stopped = true; throw error; } if (stopped) return; pages[page] = payload.items; loaded += payload.items.length; pagesLoaded += 1; onProgress({ label, loaded, total: first.itemCount, pagesLoaded, pageCount }); } }); await Promise.all(workers); return { items: pages.flat(), itemCount: first.itemCount, pageCount, }; } function uniqueSortedByName(items) { const byName = new Map(); for (const item of items) { const name = String(item?.name || ""); if (name) byName.set(name, item); } return Array.from(byName.values()).sort((left, right) => { const leftName = String(left.name); const rightName = String(right.name); if (leftName < rightName) return -1; if (leftName > rightName) return 1; return 0; }); } function filterConfigs(items, query, statusFilter, getStatus) { const normalizedQuery = String(query || "").trim().toLocaleLowerCase(); return items.filter((item) => { const matchesQuery = !normalizedQuery || String(item.name).toLocaleLowerCase().includes(normalizedQuery) || String(item.sourceMasked).toLocaleLowerCase().includes(normalizedQuery); const matchesStatus = statusFilter === "all" || getStatus(item) === statusFilter; return matchesQuery && matchesStatus; }); } function countStatuses(items, getStatus) { const result = { total: items.length, online: 0, offline: 0, idle: 0 }; for (const item of items) { const status = getStatus(item); if (Object.prototype.hasOwnProperty.call(result, status)) result[status] += 1; } return result; } function paginateItems(items, requestedPage, requestedPageSize) { const pageSize = [25, 50, 100].includes(Number(requestedPageSize)) ? Number(requestedPageSize) : 50; const totalPages = Math.max(1, Math.ceil(items.length / pageSize)); const page = Math.min(Math.max(1, Number(requestedPage) || 1), totalPages); const startIndex = (page - 1) * pageSize; const pageItems = items.slice(startIndex, startIndex + pageSize); return { items: pageItems, page, pageSize, totalItems: items.length, totalPages, start: pageItems.length === 0 ? 0 : startIndex + 1, end: pageItems.length === 0 ? 0 : startIndex + pageItems.length, }; } return { PageLoadError, countStatuses, fetchAllPages, filterConfigs, limitConcurrency, pageURL, paginateItems, uniqueSortedByName, }; }));