fix: aggreaget match and keyword trim

This commit is contained in:
shinya
2025-07-04 01:23:22 +08:00
parent f266ae0dc1
commit 6492191a2d
10 changed files with 36 additions and 27 deletions

View File

@@ -14,10 +14,10 @@ import PageLayout from '@/components/PageLayout';
function AggregatePageClient() {
const searchParams = useSearchParams();
const query = searchParams.get('q')?.trim() || '';
const title = searchParams.get('title')?.trim() || '';
const year = searchParams.get('year')?.trim() || '';
const type = searchParams.get('type')?.trim() || '';
const query = searchParams.get('q') || '';
const title = searchParams.get('title') || '';
const year = searchParams.get('year') || '';
const type = searchParams.get('type') || '';
const [results, setResults] = useState<SearchResult[]>([]);
const [loading, setLoading] = useState(true);
@@ -33,7 +33,9 @@ function AggregatePageClient() {
const fetchData = async () => {
try {
const res = await fetch(`/api/search?q=${encodeURIComponent(query)}`);
const res = await fetch(
`/api/search?q=${encodeURIComponent(query.trim())}`
);
if (!res.ok) {
throw new Error('搜索失败');
}
@@ -79,7 +81,7 @@ function AggregatePageClient() {
setResults(Array.from(map.values()).flat());
} else if (map.size > 1) {
// 存在多个匹配,跳转到搜索页
router.push(`/search?q=${encodeURIComponent(query)}`);
router.push(`/search?q=${encodeURIComponent(query.trim())}`);
}
} catch (e) {
setError(e instanceof Error ? e.message : '搜索失败');
@@ -189,7 +191,7 @@ function AggregatePageClient() {
key={src.source}
href={`/play?source=${src.source}&id=${
src.id
}&title=${encodeURIComponent(src.title)}${
}&title=${encodeURIComponent(src.title.trim())}${
src.year ? `&year=${src.year}` : ''
}&from=aggregate`}
className='group relative flex items-center justify-center w-full h-14 bg-gray-500/80 hover:bg-green-500 dark:bg-gray-700/80 dark:hover:bg-green-600 rounded-lg transition-colors'

View File

@@ -83,7 +83,7 @@ async function searchFromApi(
return {
id: item.vod_id,
title: item.vod_name,
title: item.vod_name.trim().replace(/\s+/g, ' '),
poster: item.vod_pic,
episodes,
source: apiSite.key,
@@ -151,7 +151,7 @@ async function searchFromApi(
return {
id: item.vod_id,
title: item.vod_name,
title: item.vod_name.trim().replace(/\s+/g, ' '),
poster: item.vod_pic,
episodes,
source: apiSite.key,

View File

@@ -58,7 +58,7 @@ function DetailPageClient() {
const detailData = await fetchVideoDetail({
source,
id,
fallbackTitle,
fallbackTitle: fallbackTitle.trim(),
fallbackYear,
});
setDetail(detailData);

View File

@@ -274,7 +274,7 @@ function PlayPageClient() {
const detailData = await fetchVideoDetail({
source: currentSource,
id: currentId,
fallbackTitle: videoTitle,
fallbackTitle: videoTitle.trim(),
fallbackYear: videoYear,
});
@@ -531,7 +531,7 @@ function PlayPageClient() {
try {
const response = await fetch(
`/api/search?q=${encodeURIComponent(query)}`
`/api/search?q=${encodeURIComponent(query.trim())}`
);
if (!response.ok) {
throw new Error('搜索失败');
@@ -614,7 +614,7 @@ function PlayPageClient() {
const newDetail = await fetchVideoDetail({
source: newSource,
id: newId,
fallbackTitle: newTitle,
fallbackTitle: newTitle.trim(),
fallbackYear: videoYear,
});
@@ -1100,7 +1100,7 @@ function PlayPageClient() {
onClick={() => {
if (videoTitle) {
window.location.href = `/aggregate?q=${encodeURIComponent(
videoTitle
videoTitle.trim()
)}${videoYear ? `&year=${encodeURIComponent(videoYear)}` : ''}`;
} else {
window.location.href = '/';
@@ -1125,7 +1125,7 @@ function PlayPageClient() {
// 返回选源页
if (videoTitle) {
window.location.href = `/aggregate?q=${encodeURIComponent(
videoTitle
videoTitle.trim()
)}${videoYear ? `&year=${encodeURIComponent(videoYear)}` : ''}`;
} else {
window.location.href = '/';

View File

@@ -78,7 +78,7 @@ function SearchPageClient() {
try {
setIsLoading(true);
const response = await fetch(
`/api/search?q=${encodeURIComponent(query)}`
`/api/search?q=${encodeURIComponent(query.trim())}`
);
const data = await response.json();
setSearchResults(data.results);
@@ -92,17 +92,20 @@ function SearchPageClient() {
const handleSearch = (e: React.FormEvent) => {
e.preventDefault();
if (!searchQuery.trim()) return;
const trimmed = searchQuery.trim().replace(/\s+/g, ' ');
if (!trimmed) return;
// 回显搜索框
setSearchQuery(trimmed);
setIsLoading(true);
setShowResults(true);
router.push(`/search?q=${encodeURIComponent(searchQuery)}`);
router.push(`/search?q=${encodeURIComponent(trimmed)}`);
// 直接发请求
fetchSearchResults(searchQuery);
fetchSearchResults(trimmed);
// 保存到搜索历史
addSearchHistory(searchQuery).then(async () => {
addSearchHistory(trimmed).then(async () => {
const history = await getSearchHistory();
setSearchHistory(history);
});
@@ -225,7 +228,9 @@ function SearchPageClient() {
<button
onClick={() => {
setSearchQuery(item);
router.push(`/search?q=${encodeURIComponent(item)}`);
router.push(
`/search?q=${encodeURIComponent(item.trim())}`
);
}}
className='px-4 py-2 bg-gray-500/10 hover:bg-gray-300 rounded-full text-sm text-gray-700 transition-colors duration-200 dark:bg-gray-700/50 dark:hover:bg-gray-600 dark:text-gray-300'
>

View File

@@ -119,7 +119,7 @@ const AggregateCard: React.FC<AggregateCardProps> = ({
return (
<Link
href={`/aggregate?q=${encodeURIComponent(
query
query.trim()
)}&title=${encodeURIComponent(first.title)}${
year ? `&year=${encodeURIComponent(year)}` : ''
}&type=${mostFrequentEpisodes > 1 ? 'tv' : 'movie'}`}

View File

@@ -53,7 +53,9 @@ const DemoCard = ({ id, title, poster, rate, type }: DemoCardProps) => {
const imgRef = useRef<HTMLImageElement>(null);
const handleClick = () => {
router.push(`/aggregate?q=${encodeURIComponent(title)}&type=${type}`);
router.push(
`/aggregate?q=${encodeURIComponent(title.trim())}&type=${type}`
);
};
return (

View File

@@ -154,7 +154,7 @@ export default function VideoCard({
return (
<Link
href={`/detail?source=${source}&id=${id}&title=${encodeURIComponent(
title
title.trim()
)}${year ? `&year=${year}` : ''}${from ? `&from=${from}` : ''}`}
>
<div

View File

@@ -34,7 +34,7 @@ export async function fetchVideoDetail({
if (fallbackTitle) {
try {
const searchResp = await fetch(
`/api/search?q=${encodeURIComponent(fallbackTitle)}`
`/api/search?q=${encodeURIComponent(fallbackTitle.trim())}`
);
if (searchResp.ok) {
const searchData = await searchResp.json();
@@ -61,7 +61,7 @@ export async function fetchVideoDetail({
return {
id: data?.videoInfo?.id || id,
title: data?.videoInfo?.title || fallbackTitle,
title: data?.videoInfo?.title.trim() || fallbackTitle.trim(),
poster: data?.videoInfo?.cover || '',
episodes: data?.episodes || [],
source: data?.videoInfo?.source || source,

View File

@@ -27,7 +27,7 @@ async function refreshRecordAndFavorites() {
promise = fetchVideoDetail({
source,
id,
fallbackTitle,
fallbackTitle: fallbackTitle.trim(),
fallbackYear: '',
});
detailCache.set(key, promise);