feat: 分页
This commit is contained in:
@@ -267,7 +267,12 @@ class ToolsRoute(Route):
|
||||
return Response().error(f"删除 MCP 服务器失败: {str(e)}").__dict__
|
||||
|
||||
async def get_mcp_markets(self):
|
||||
BASE_URL = "https://api.soulter.top/astrbot/mcpservers"
|
||||
page = request.args.get("page", 1, type=int)
|
||||
page_size = request.args.get("page_size", 10, type=int)
|
||||
BASE_URL = "https://api.soulter.top/astrbot/mcpservers?page={}&page_size={}".format(
|
||||
page,
|
||||
page_size,
|
||||
)
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(f"{BASE_URL}") as response:
|
||||
@@ -282,3 +287,4 @@ class ToolsRoute(Route):
|
||||
)
|
||||
except Exception as _:
|
||||
logger.error(traceback.format_exc())
|
||||
return Response().error("获取市场数据失败").__dict__
|
||||
@@ -277,8 +277,9 @@
|
||||
class="mx-2"
|
||||
style="max-width: 300px"
|
||||
clearable
|
||||
@update:model-value="searchMarketplaceServers"
|
||||
></v-text-field>
|
||||
<v-btn color="primary" prepend-icon="mdi-refresh" variant="text" @click="fetchMarketplaceServers" :loading="marketplaceLoading">
|
||||
<v-btn color="primary" prepend-icon="mdi-refresh" variant="text" @click="fetchMarketplaceServers(1)" :loading="marketplaceLoading">
|
||||
刷新
|
||||
</v-btn>
|
||||
</v-card-title>
|
||||
@@ -293,25 +294,29 @@
|
||||
</div>
|
||||
|
||||
<!-- 无数据 -->
|
||||
<div v-else-if="marketplaceServers.length === 0" class="text-center pa-8">
|
||||
<div v-else-if="filteredMarketplaceServers.length === 0" class="text-center pa-8">
|
||||
<v-icon size="64" color="grey-lighten-1">mdi-store-off</v-icon>
|
||||
<p class="text-grey mt-4">暂无可用的 MCP 服务器</p>
|
||||
</div>
|
||||
|
||||
<!-- 服务器列表 -->
|
||||
<v-row v-else>
|
||||
<v-col v-for="(server, index) in marketplaceServers" :key="index" cols="12" md="6" lg="4">
|
||||
<v-col v-for="(server, index) in filteredMarketplaceServers" :key="index" cols="12" md="6" lg="4">
|
||||
<v-card class="marketplace-card hover-elevation" height="100%">
|
||||
<v-card-title class="d-flex align-center pb-1 pt-3">
|
||||
<span class="text-h6 text-truncate" :title="server.name">
|
||||
{{ server.name_h }}({{ server.name }})
|
||||
</span>
|
||||
<v-btn
|
||||
icon="mdi-open-in-new"
|
||||
variant="text"
|
||||
color="primary"
|
||||
class="ms-auto"
|
||||
@click.stop="openurl(server.origin)"
|
||||
></v-btn>
|
||||
</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<!-- <p class="text-body-2 mb-3 text-truncate-2" :title="server.AbstractCN">
|
||||
{{ server.AbstractCN || server.Abstract || '暂无描述' }}
|
||||
</p> -->
|
||||
|
||||
<div class="d-flex align-center mb-2">
|
||||
<v-icon size="small" color="grey" class="me-2">mdi-tools</v-icon>
|
||||
@@ -348,6 +353,18 @@
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<!-- 分页控件 -->
|
||||
<div class="d-flex justify-center mt-4">
|
||||
<v-pagination
|
||||
v-if="!marketplaceLoading && totalMarketPages > 1"
|
||||
v-model="currentMarketPage"
|
||||
:length="totalMarketPages"
|
||||
total-visible="7"
|
||||
rounded
|
||||
@update:model-value="changePage"
|
||||
></v-pagination>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-window-item>
|
||||
@@ -618,6 +635,12 @@ export default {
|
||||
marketplaceSearch: '',
|
||||
selectedMarketplaceServer: null,
|
||||
selectedServerConfigDisplay: '',
|
||||
|
||||
// 分页相关
|
||||
currentMarketPage: 1,
|
||||
marketPageSize: 9, // 每页显示9个服务器,适合3列布局
|
||||
totalMarketPages: 1,
|
||||
totalMarketItems: 0,
|
||||
}
|
||||
},
|
||||
|
||||
@@ -655,6 +678,11 @@ export default {
|
||||
return '未设置配置';
|
||||
}
|
||||
},
|
||||
|
||||
// 过滤后的市场服务器
|
||||
filteredMarketplaceServers() {
|
||||
return this.marketplaceServers;
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
@@ -860,11 +888,34 @@ export default {
|
||||
// MCP 市场相关方法
|
||||
|
||||
// 获取市场服务器列表
|
||||
fetchMarketplaceServers() {
|
||||
fetchMarketplaceServers(page = 1) {
|
||||
this.marketplaceLoading = true;
|
||||
axios.get('/api/tools/mcp/market')
|
||||
|
||||
// 构建请求参数
|
||||
const params = {
|
||||
page: page,
|
||||
page_size: this.marketPageSize
|
||||
};
|
||||
|
||||
// 如果有搜索关键词,添加到请求参数
|
||||
if (this.marketplaceSearch.trim()) {
|
||||
params.search = this.marketplaceSearch.trim();
|
||||
}
|
||||
|
||||
axios.get('/api/tools/mcp/market', { params })
|
||||
.then(response => {
|
||||
this.marketplaceServers = response.data.data.mcpservers || [];
|
||||
|
||||
// 更新分页信息
|
||||
if (response.data.data.pagination) {
|
||||
this.totalMarketItems = response.data.data.pagination.total || 0;
|
||||
this.totalMarketPages = response.data.data.pagination.totalPages || 1;
|
||||
this.currentMarketPage = response.data.data.pagination.currentPage || 1;
|
||||
} else {
|
||||
// 如果后端没有返回分页信息,根据返回的数据量估算
|
||||
this.totalMarketPages = Math.ceil(this.marketplaceServers.length / this.marketPageSize) || 1;
|
||||
}
|
||||
|
||||
this.marketplaceLoading = false;
|
||||
})
|
||||
.catch(error => {
|
||||
@@ -873,6 +924,18 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
// 搜索市场服务器
|
||||
searchMarketplaceServers() {
|
||||
// 重置到第一页,然后获取结果
|
||||
this.currentMarketPage = 1;
|
||||
this.fetchMarketplaceServers(1);
|
||||
},
|
||||
|
||||
// 切换分页
|
||||
changePage(page) {
|
||||
this.fetchMarketplaceServers(page);
|
||||
},
|
||||
|
||||
// 显示服务器详情
|
||||
showServerDetail(server) {
|
||||
this.selectedMarketplaceServer = server;
|
||||
|
||||
Reference in New Issue
Block a user