diff --git a/dashboard/src/i18n/locales/en-US/features/extension.json b/dashboard/src/i18n/locales/en-US/features/extension.json
index 8184dcce4f..13b023bab5 100644
--- a/dashboard/src/i18n/locales/en-US/features/extension.json
+++ b/dashboard/src/i18n/locales/en-US/features/extension.json
@@ -177,6 +177,7 @@
"sourceResolved": "Source resolved successfully",
"installPlugin": "Install Plugin",
"randomPlugins": "🎲 Random Plugins",
+ "itemsPerPage": "Items per page",
"sourceSafetyWarning": "Even with the default source, plugin stability and security cannot be fully guaranteed. Please verify carefully before use."
},
"sort": {
diff --git a/dashboard/src/i18n/locales/zh-CN/features/extension.json b/dashboard/src/i18n/locales/zh-CN/features/extension.json
index d7afc3971c..cd5175e8ed 100644
--- a/dashboard/src/i18n/locales/zh-CN/features/extension.json
+++ b/dashboard/src/i18n/locales/zh-CN/features/extension.json
@@ -177,6 +177,7 @@
"sourceResolved": "插件源可用",
"installPlugin": "安装插件",
"randomPlugins": "🎲 随机插件",
+ "itemsPerPage": "\u6bcf\u9875\u663e\u793a",
"sourceSafetyWarning": "即使是默认插件源,我们也不能完全保证插件的稳定性和安全性,使用前请谨慎核查。"
},
"sort": {
diff --git a/dashboard/src/views/extension/MarketPluginsTab.vue b/dashboard/src/views/extension/MarketPluginsTab.vue
index 0bc8750e80..052764bc4e 100644
--- a/dashboard/src/views/extension/MarketPluginsTab.vue
+++ b/dashboard/src/views/extension/MarketPluginsTab.vue
@@ -354,13 +354,30 @@ const openMarketPluginDetail = (plugin) => {
-
-
+
@@ -469,6 +486,45 @@ const openMarketPluginDetail = (plugin) => {
.market-filter-control :deep(.v-field__prepend-inner) {
font-size: 0.875rem;
}
+.market-pagination-footer {
+ display: grid;
+ grid-template-columns: 1fr auto 1fr;
+ align-items: center;
+ gap: 12px;
+ margin-top: 16px;
+}
+
+.market-pagination-footer__pagination {
+ display: flex;
+ justify-content: center;
+}
+
+.market-pagination-footer__page-size {
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ gap: 8px;
+}
+
+.market-pagination-footer__select {
+ width: 110px;
+}
+
+@media (max-width: 960px) {
+ .market-pagination-footer {
+ grid-template-columns: 1fr;
+ }
+
+ .market-pagination-footer__spacer {
+ display: none;
+ }
+
+ .market-pagination-footer__pagination,
+ .market-pagination-footer__page-size {
+ justify-content: center;
+ }
+}
+
@media (max-width: 700px) {
.market-header-row {
diff --git a/dashboard/src/views/extension/useExtensionPage.js b/dashboard/src/views/extension/useExtensionPage.js
index 7937bb2cb7..6841049852 100644
--- a/dashboard/src/views/extension/useExtensionPage.js
+++ b/dashboard/src/views/extension/useExtensionPage.js
@@ -206,6 +206,17 @@ export const useExtensionPage = (initialTab = "installed") => {
const upload_file = ref(null);
const uploadTab = ref("file");
const showPluginFullName = ref(false);
+ const marketItemsPerPageOptions = [9, 25, 50, 100];
+ const getInitialMarketItemsPerPage = () => {
+ if (typeof window !== "undefined" && window.localStorage) {
+ const rawValue = Number(localStorage.getItem("pluginMarketItemsPerPage"));
+ if (marketItemsPerPageOptions.includes(rawValue)) {
+ return rawValue;
+ }
+ }
+ return 9;
+ };
+ const marketItemsPerPage = ref(getInitialMarketItemsPerPage());
const marketSearch = ref("");
const debouncedMarketSearch = ref("");
const refreshingMarket = ref(false);
@@ -460,12 +471,12 @@ export const useExtensionPage = (initialTab = "installed") => {
const displayItemsPerPage = 9; // 固定每页显示9个卡片(3行)
const totalPages = computed(() => {
- return Math.ceil(sortedPlugins.value.length / displayItemsPerPage);
+ return Math.ceil(sortedPlugins.value.length / marketItemsPerPage.value);
});
const paginatedPlugins = computed(() => {
- const start = (currentPage.value - 1) * displayItemsPerPage;
- const end = start + displayItemsPerPage;
+ const start = (currentPage.value - 1) * marketItemsPerPage.value;
+ const end = start + marketItemsPerPage.value;
return sortedPlugins.value.slice(start, end);
});
@@ -2415,6 +2426,13 @@ export const useExtensionPage = (initialTab = "installed") => {
}, 300); // 300ms 防抖延迟
});
+ watch(marketItemsPerPage, (newVal) => {
+ currentPage.value = 1;
+ if (typeof window !== "undefined" && window.localStorage) {
+ localStorage.setItem("pluginMarketItemsPerPage", String(newVal));
+ }
+ });
+
watch(
[() => dialog.value, () => extension_url.value, () => uploadTab.value],
async ([dialogOpen, _, currentUploadTab]) => {
@@ -2569,6 +2587,8 @@ export const useExtensionPage = (initialTab = "installed") => {
randomPlugins,
shufflePlugins,
refreshRandomPlugins,
+ marketItemsPerPage,
+ marketItemsPerPageOptions,
displayItemsPerPage,
totalPages,
paginatedPlugins,