diff --git a/dashboard/src/i18n/locales/en-US/features/extension.json b/dashboard/src/i18n/locales/en-US/features/extension.json index 8184dcce4f..dbaa9ff1a9 100644 --- a/dashboard/src/i18n/locales/en-US/features/extension.json +++ b/dashboard/src/i18n/locales/en-US/features/extension.json @@ -185,6 +185,7 @@ "installTime": "Last Modified", "name": "Name", "stars": "Stars", + "downloads": "Downloads", "author": "Author", "updated": "Last Updated", "updateStatus": "Update Status", diff --git a/dashboard/src/i18n/locales/ru-RU/features/extension.json b/dashboard/src/i18n/locales/ru-RU/features/extension.json index b4ed54f3e8..4f684d2966 100644 --- a/dashboard/src/i18n/locales/ru-RU/features/extension.json +++ b/dashboard/src/i18n/locales/ru-RU/features/extension.json @@ -184,6 +184,7 @@ "installTime": "Дате установки", "name": "Имени", "stars": "Звездам", + "downloads": "Количеству скачиваний", "author": "Автору", "updated": "Дате обновления", "updateStatus": "Статусу обновления", diff --git a/dashboard/src/i18n/locales/zh-CN/features/extension.json b/dashboard/src/i18n/locales/zh-CN/features/extension.json index d7afc3971c..10f2ac06aa 100644 --- a/dashboard/src/i18n/locales/zh-CN/features/extension.json +++ b/dashboard/src/i18n/locales/zh-CN/features/extension.json @@ -185,6 +185,7 @@ "installTime": "最后修改时间", "name": "名称", "stars": "Star数", + "downloads": "下载量", "author": "作者名", "updated": "更新时间", "updateStatus": "更新状态", diff --git a/dashboard/src/views/extension/MarketPluginsTab.vue b/dashboard/src/views/extension/MarketPluginsTab.vue index 0bc8750e80..96eba7c26b 100644 --- a/dashboard/src/views/extension/MarketPluginsTab.vue +++ b/dashboard/src/views/extension/MarketPluginsTab.vue @@ -162,6 +162,7 @@ const currentSourceName = computed(() => { const marketSortItems = computed(() => [ { title: tm("sort.default"), value: "default" }, { title: tm("sort.stars"), value: "stars" }, + { title: tm("sort.downloads"), value: "downloads" }, { title: tm("sort.author"), value: "author" }, { title: tm("sort.updated"), value: "updated" }, ]); diff --git a/dashboard/src/views/extension/marketPluginSort.mjs b/dashboard/src/views/extension/marketPluginSort.mjs new file mode 100644 index 0000000000..fbafd9c17b --- /dev/null +++ b/dashboard/src/views/extension/marketPluginSort.mjs @@ -0,0 +1,29 @@ +// 自定义插件源可能没有 download_count 字段,因此未知下载量在升序和降序中都始终置底 +const normalizeDownloadCount = (value) => { + if (value === undefined || value === null || value === "") { + return undefined; + } + const parsed = Number(value); + if (!Number.isFinite(parsed)) { + return undefined; + } + return Math.max(0, Math.trunc(parsed)); +}; + +export const sortMarketPluginsByDownloads = (plugins, order = "desc") => { + const direction = order === "asc" ? 1 : -1; + return (Array.isArray(plugins) ? plugins : []) + .map((plugin, index) => ({ plugin, index })) + .sort((left, right) => { + const countA = normalizeDownloadCount(left.plugin?.download_count); + const countB = normalizeDownloadCount(right.plugin?.download_count); + if (countA === undefined && countB === undefined) { + return left.index - right.index; + } + if (countA === undefined) return 1; + if (countB === undefined) return -1; + const diff = (countA - countB) * direction; + return diff !== 0 ? diff : left.index - right.index; + }) + .map((item) => item.plugin); +}; diff --git a/dashboard/src/views/extension/useExtensionPage.js b/dashboard/src/views/extension/useExtensionPage.js index 7937bb2cb7..3c40637dd9 100644 --- a/dashboard/src/views/extension/useExtensionPage.js +++ b/dashboard/src/views/extension/useExtensionPage.js @@ -14,6 +14,7 @@ import { } from "@/utils/pluginSearch"; import { computed, onMounted, onUnmounted, reactive, ref, watch } from "vue"; import { useRoute, useRouter } from "vue-router"; +import { sortMarketPluginsByDownloads } from "./marketPluginSort.mjs"; const buildFailedPluginItems = (raw) => { return Object.entries(raw || {}).map(([dirName, info]) => { @@ -209,7 +210,7 @@ export const useExtensionPage = (initialTab = "installed") => { const marketSearch = ref(""); const debouncedMarketSearch = ref(""); const refreshingMarket = ref(false); - const sortBy = ref("default"); // default, stars, author, updated + const sortBy = ref("default"); // default, stars, downloads, author, updated const sortOrder = ref("desc"); // desc (降序) or asc (升序) const randomPluginNames = ref([]); const marketCategoryFilter = ref("all"); @@ -392,6 +393,9 @@ export const useExtensionPage = (initialTab = "installed") => { const starsB = b.stars ?? 0; return sortOrder.value === "desc" ? starsB - starsA : starsA - starsB; }); + } else if (sortBy.value === "downloads") { + // 按下载量排序 + plugins = sortMarketPluginsByDownloads(plugins, sortOrder.value); } else if (sortBy.value === "author") { // 按作者名字典序排序 plugins.sort((a, b) => {