feat(ContentSelection): 添加搜索功能并优化分页逻辑

- 在PopupHeader组件中添加onSearch回调支持
- 将Input组件替换为Input.Search以支持搜索按钮
- 重构selectionPopup组件,移除useCallback并优化搜索和分页处理
- 减少每页显示数量从20改为10
- 简化空状态显示逻辑
This commit is contained in:
2025-08-28 17:56:12 +08:00
parent 7430f4deb8
commit e2ff3dd7c5
2 changed files with 56 additions and 54 deletions

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect, useCallback } from "react"; import React, { useState, useEffect } from "react";
import { Checkbox, Popup } from "antd-mobile"; import { Checkbox, Popup } from "antd-mobile";
import { getContentLibraryList } from "./api"; import { getContentLibraryList } from "./api";
import style from "./index.module.scss"; import style from "./index.module.scss";
@@ -15,7 +15,7 @@ interface SelectionPopupProps {
onConfirm?: (libraries: ContentItem[]) => void; onConfirm?: (libraries: ContentItem[]) => void;
} }
const PAGE_SIZE = 20; const PAGE_SIZE = 10;
// 类型标签文本 // 类型标签文本
const getTypeText = (type?: number) => { const getTypeText = (type?: number) => {
@@ -60,40 +60,39 @@ const SelectionPopup: React.FC<SelectionPopupProps> = ({
); );
// 获取内容库列表支持keyword和分页 // 获取内容库列表支持keyword和分页
const fetchLibraries = useCallback( const fetchLibraries = async (page: number, keyword: string = "") => {
async (page: number, keyword: string = "") => { setLoading(true);
setLoading(true); try {
try { const params: any = {
const params: any = { page,
page, limit: PAGE_SIZE,
limit: PAGE_SIZE, };
}; if (keyword.trim()) {
if (keyword.trim()) { params.keyword = keyword.trim();
params.keyword = keyword.trim(); }
} const response = await getContentLibraryList(params);
const response = await getContentLibraryList(params); if (response && response.list) {
if (response && response.list) { setLibraries(response.list);
setLibraries(response.list); setTotalLibraries(response.total || 0);
setTotalLibraries(response.total || 0); setTotalPages(Math.ceil((response.total || 0) / PAGE_SIZE));
setTotalPages(Math.ceil((response.total || 0) / PAGE_SIZE)); } else {
} else { // 如果没有返回列表数据,设置为空数组
// 如果没有返回列表数据,设置为空数组
setLibraries([]);
setTotalLibraries(0);
setTotalPages(1);
}
} catch (error) {
console.error("获取内容库列表失败:", error);
// 请求失败时,设置为空数组
setLibraries([]); setLibraries([]);
setTotalLibraries(0); setTotalLibraries(0);
setTotalPages(1); setTotalPages(1);
} finally {
setLoading(false);
} }
}, } catch (error) {
[], console.error("获取内容库列表失败:", error);
); // 请求失败时,设置为空数组
setLibraries([]);
setTotalLibraries(0);
setTotalPages(1);
} finally {
setTimeout(() => {
setLoading(false);
});
}
};
// 打开弹窗时获取第一页 // 打开弹窗时获取第一页
useEffect(() => { useEffect(() => {
@@ -109,23 +108,26 @@ const SelectionPopup: React.FC<SelectionPopupProps> = ({
// 关闭弹窗时重置加载状态,确保下次打开时显示加载中 // 关闭弹窗时重置加载状态,确保下次打开时显示加载中
setLoading(true); setLoading(true);
} }
}, [visible, fetchLibraries, selectedOptions]); }, [visible, selectedOptions]);
// 搜索防抖 // 搜索处理函数
useEffect(() => { const handleSearch = (query: string) => {
if (!visible) return; if (!visible) return;
const timer = setTimeout(() => { setCurrentPage(1);
setCurrentPage(1); fetchLibraries(1, query);
fetchLibraries(1, searchQuery); };
}, 500);
return () => clearTimeout(timer);
}, [searchQuery, visible, fetchLibraries]);
// 翻页时重新请求 // 搜索输入变化时的处理
useEffect(() => { const handleSearchChange = (query: string) => {
if (!visible || currentPage === 1) return; setSearchQuery(query);
fetchLibraries(currentPage, searchQuery); };
}, [currentPage, visible, fetchLibraries, searchQuery]);
// 翻页处理函数
const handlePageChange = (page: number) => {
if (!visible || page === currentPage) return;
setCurrentPage(page);
fetchLibraries(page, searchQuery);
};
// 处理内容库选择 // 处理内容库选择
const handleLibraryToggle = (library: ContentItem) => { const handleLibraryToggle = (library: ContentItem) => {
@@ -175,11 +177,7 @@ const SelectionPopup: React.FC<SelectionPopupProps> = ({
</div> </div>
) : ( ) : (
<div className={style.emptyBox}> <div className={style.emptyBox}>
<div className={style.emptyText}> <div className={style.emptyText}></div>
{searchQuery
? `没有找到包含"${searchQuery}"的内容库`
: "没有找到内容库"}
</div>
</div> </div>
); );
}; };
@@ -197,9 +195,10 @@ const SelectionPopup: React.FC<SelectionPopupProps> = ({
<PopupHeader <PopupHeader
title="选择内容库" title="选择内容库"
searchQuery={searchQuery} searchQuery={searchQuery}
setSearchQuery={setSearchQuery} setSearchQuery={handleSearchChange}
searchPlaceholder="搜索内容库" searchPlaceholder="搜索内容库"
loading={loading} loading={loading}
onSearch={handleSearch}
onRefresh={() => fetchLibraries(currentPage, searchQuery)} onRefresh={() => fetchLibraries(currentPage, searchQuery)}
/> />
} }
@@ -210,7 +209,7 @@ const SelectionPopup: React.FC<SelectionPopupProps> = ({
totalPages={totalPages} totalPages={totalPages}
loading={loading} loading={loading}
selectedCount={tempSelectedOptions.length} selectedCount={tempSelectedOptions.length}
onPageChange={setCurrentPage} onPageChange={handlePageChange}
onCancel={onClose} onCancel={onClose}
onConfirm={handleConfirm} onConfirm={handleConfirm}
/> />

View File

@@ -11,6 +11,7 @@ interface PopupHeaderProps {
searchPlaceholder?: string; searchPlaceholder?: string;
loading?: boolean; loading?: boolean;
onRefresh?: () => void; onRefresh?: () => void;
onSearch?: (query: string) => void;
showRefresh?: boolean; showRefresh?: boolean;
showSearch?: boolean; showSearch?: boolean;
showTabs?: boolean; showTabs?: boolean;
@@ -28,6 +29,7 @@ const PopupHeader: React.FC<PopupHeaderProps> = ({
searchPlaceholder = "搜索...", searchPlaceholder = "搜索...",
loading = false, loading = false,
onRefresh, onRefresh,
onSearch,
showRefresh = true, showRefresh = true,
showSearch = true, showSearch = true,
showTabs = false, showTabs = false,
@@ -42,10 +44,11 @@ const PopupHeader: React.FC<PopupHeaderProps> = ({
{showSearch && ( {showSearch && (
<div className={style.popupSearchRow}> <div className={style.popupSearchRow}>
<div className={style.popupSearchInputWrap}> <div className={style.popupSearchInputWrap}>
<Input <Input.Search
placeholder={searchPlaceholder} placeholder={searchPlaceholder}
value={searchQuery} value={searchQuery}
onChange={e => setSearchQuery(e.target.value)} onChange={e => setSearchQuery(e.target.value)}
onSearch={() => onSearch && onSearch(searchQuery)}
prefix={<SearchOutlined />} prefix={<SearchOutlined />}
size="large" size="large"
/> />