feat(ContentSelection): 添加搜索功能并优化分页逻辑
- 在PopupHeader组件中添加onSearch回调支持 - 将Input组件替换为Input.Search以支持搜索按钮 - 重构selectionPopup组件,移除useCallback并优化搜索和分页处理 - 减少每页显示数量从20改为10 - 简化空状态显示逻辑
This commit is contained in:
@@ -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}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -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"
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user