feat: 支持搜索关注的 UP 主 (#588)

This commit is contained in:
ᴀᴍᴛᴏᴀᴇʀ
2026-01-05 00:39:45 +08:00
committed by GitHub
parent 0b5ae3d664
commit 56f5ed8e01
5 changed files with 44 additions and 17 deletions

View File

@@ -82,6 +82,7 @@ pub struct FollowedCollectionsRequest {
pub struct FollowedUppersRequest { pub struct FollowedUppersRequest {
pub page_num: Option<i32>, pub page_num: Option<i32>,
pub page_size: Option<i32>, pub page_size: Option<i32>,
pub name: Option<String>,
} }
#[derive(Deserialize, Validate)] #[derive(Deserialize, Validate)]

View File

@@ -153,7 +153,9 @@ pub async fn get_followed_uppers(
let credential = &VersionedConfig::get().read().credential; let credential = &VersionedConfig::get().read().credential;
let me = Me::new(bili_client.as_ref(), credential); let me = Me::new(bili_client.as_ref(), credential);
let (page_num, page_size) = (params.page_num.unwrap_or(1), params.page_size.unwrap_or(20)); let (page_num, page_size) = (params.page_num.unwrap_or(1), params.page_size.unwrap_or(20));
let bili_uppers = me.get_followed_uppers(page_num, page_size).await?; let bili_uppers = me
.get_followed_uppers(page_num, page_size, params.name.as_deref())
.await?;
let bili_uid: Vec<_> = bili_uppers.list.iter().map(|upper| upper.mid).collect(); let bili_uid: Vec<_> = bili_uppers.list.iter().map(|upper| upper.mid).collect();

View File

@@ -60,21 +60,31 @@ impl<'a> Me<'a> {
Ok(serde_json::from_value(resp["data"].take())?) Ok(serde_json::from_value(resp["data"].take())?)
} }
pub async fn get_followed_uppers(&self, page_num: i32, page_size: i32) -> Result<FollowedUppers> { pub async fn get_followed_uppers(
&self,
page_num: i32,
page_size: i32,
name: Option<&str>,
) -> Result<FollowedUppers> {
ensure!( ensure!(
!self.mid().is_empty(), !self.mid().is_empty(),
"未获取到用户 ID请确保填写设置中的 B 站认证信息" "未获取到用户 ID请确保填写设置中的 B 站认证信息"
); );
let mut resp = self let url = if name.is_some() {
"https://api.bilibili.com/x/relation/followings/search"
} else {
"https://api.bilibili.com/x/relation/followings"
};
let mut request = self
.client .client
.request( .request(Method::GET, url, self.credential)
Method::GET,
"https://api.bilibili.com/x/relation/followings",
self.credential,
)
.await .await
.query(&[("vmid", self.mid())]) .query(&[("vmid", self.mid())])
.query(&[("pn", page_num), ("ps", page_size)]) .query(&[("pn", page_num), ("ps", page_size)]);
if let Some(name) = name {
request = request.query(&[("name", name)]);
}
let mut resp = request
.send() .send()
.await? .await?
.error_for_status()? .error_for_status()?

View File

@@ -199,11 +199,13 @@ class ApiClient {
async getFollowedUppers( async getFollowedUppers(
pageNum?: number, pageNum?: number,
pageSize?: number pageSize?: number,
name?: string
): Promise<ApiResponse<UppersResponse>> { ): Promise<ApiResponse<UppersResponse>> {
const params = { const params = {
page_num: pageNum, page_num: pageNum,
page_size: pageSize page_size: pageSize,
name: name
}; };
return this.get<UppersResponse>('/me/uppers', params as Record<string, unknown>); return this.get<UppersResponse>('/me/uppers', params as Record<string, unknown>);
} }
@@ -294,8 +296,8 @@ const api = {
getCreatedFavorites: () => apiClient.getCreatedFavorites(), getCreatedFavorites: () => apiClient.getCreatedFavorites(),
getFollowedCollections: (pageNum?: number, pageSize?: number) => getFollowedCollections: (pageNum?: number, pageSize?: number) =>
apiClient.getFollowedCollections(pageNum, pageSize), apiClient.getFollowedCollections(pageNum, pageSize),
getFollowedUppers: (pageNum?: number, pageSize?: number) => getFollowedUppers: (pageNum?: number, pageSize?: number, name?: string) =>
apiClient.getFollowedUppers(pageNum, pageSize), apiClient.getFollowedUppers(pageNum, pageSize, name),
insertFavorite: (request: InsertFavoriteRequest) => apiClient.insertFavorite(request), insertFavorite: (request: InsertFavoriteRequest) => apiClient.insertFavorite(request),
insertCollection: (request: InsertCollectionRequest) => apiClient.insertCollection(request), insertCollection: (request: InsertCollectionRequest) => apiClient.insertCollection(request),
insertSubmission: (request: InsertSubmissionRequest) => apiClient.insertSubmission(request), insertSubmission: (request: InsertSubmissionRequest) => apiClient.insertSubmission(request),

View File

@@ -3,6 +3,7 @@
import { toast } from 'svelte-sonner'; import { toast } from 'svelte-sonner';
import SubscriptionCard from '$lib/components/subscription-card.svelte'; import SubscriptionCard from '$lib/components/subscription-card.svelte';
import Pagination from '$lib/components/pagination.svelte'; import Pagination from '$lib/components/pagination.svelte';
import SearchBar from '$lib/components/search-bar.svelte';
import { setBreadcrumb } from '$lib/stores/breadcrumb'; import { setBreadcrumb } from '$lib/stores/breadcrumb';
import api from '$lib/api'; import api from '$lib/api';
import type { Followed, ApiError } from '$lib/types'; import type { Followed, ApiError } from '$lib/types';
@@ -11,13 +12,14 @@
let totalCount = 0; let totalCount = 0;
let currentPage = 0; let currentPage = 0;
let loading = false; let loading = false;
let searchQuery = '';
const pageSize = 50; const pageSize = 50;
async function loadUppers(page: number = 0) { async function loadUppers(page: number = 0, name?: string) {
loading = true; loading = true;
try { try {
const response = await api.getFollowedUppers(page + 1, pageSize); // API 使用 1 基索引 const response = await api.getFollowedUppers(page + 1, pageSize, name || undefined); // API 使用 1 基索引
uppers = response.data.uppers; uppers = response.data.uppers;
totalCount = response.data.total; totalCount = response.data.total;
} catch (error) { } catch (error) {
@@ -32,12 +34,18 @@
function handleSubscriptionSuccess() { function handleSubscriptionSuccess() {
// 重新加载数据以获取最新状态 // 重新加载数据以获取最新状态
loadUppers(currentPage); loadUppers(currentPage, searchQuery);
} }
async function handlePageChange(page: number) { async function handlePageChange(page: number) {
currentPage = page; currentPage = page;
await loadUppers(page); await loadUppers(page, searchQuery);
}
async function handleSearch(query: string) {
searchQuery = query;
currentPage = 0;
await loadUppers(0, query);
} }
onMount(async () => { onMount(async () => {
@@ -53,6 +61,10 @@
</svelte:head> </svelte:head>
<div> <div>
<div class="mb-4 flex items-center justify-between">
<SearchBar placeholder="搜索 UP 主.." value={searchQuery} onSearch={handleSearch}></SearchBar>
</div>
<div class="mb-6 flex items-center justify-between"> <div class="mb-6 flex items-center justify-between">
<div class="flex items-center gap-6"> <div class="flex items-center gap-6">
{#if !loading} {#if !loading}