Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/components/articleList/ArticleList.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,23 @@
gap: 1rem;
}

/* 胶囊布局:标题/搜索栏和分页固定,仅卡片区域滚动 */
.articleListScrollable .listHeader {
flex: 0 0 auto;
}

.articleListScrollable .articles {
flex: 1 1 auto;
min-height: 0;
overflow-x: hidden;
overflow-y: auto;
overscroll-behavior: contain;
}

.articleListScrollable .pagination {
flex: 0 0 auto;
}

/* 当文章数量少于每页数量时,用占位空间填充 */
.articles::after {
content: "";
Expand Down
24 changes: 20 additions & 4 deletions src/components/articleList/ArticleList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,19 @@ interface ArticleListProps {
categoryName?: string;
searchKeyword?: string;
headerRight?: React.ReactNode;
/** 胶囊布局下让标题/搜索栏与分页固定,仅卡片区域滚动 */
scrollable?: boolean;
}

const ArticleList: React.FC<ArticleListProps> = ({ labelId, labelName, categoryId, categoryName, searchKeyword, headerRight }) => {
const ArticleList: React.FC<ArticleListProps> = ({
labelId,
labelName,
categoryId,
categoryName,
searchKeyword,
headerRight,
scrollable = false,
}) => {
const [searchParams, setSearchParams] = useSearchParams();
const currentPage = parseInt(searchParams.get("page") || "1", 10);
const itemsPerPage = 6;
Expand All @@ -35,11 +45,12 @@ const ArticleList: React.FC<ArticleListProps> = ({ labelId, labelName, categoryI
const [loading, setLoading] = useState(true);
const navigate = useNavigate();
const { t } = useTranslation("article");
const articlesRef = useRef<HTMLDivElement>(null);

// 切换页码
const handlePageChange = (page: number) => {
setSearchParams({ page: String(page) });
// 滚动到顶部
// 经典布局滚动窗口;胶囊布局由下方 effect 重置卡片区域
window.scrollTo({ top: 0, behavior: "smooth" });
};

Expand Down Expand Up @@ -155,6 +166,11 @@ const ArticleList: React.FC<ArticleListProps> = ({ labelId, labelName, categoryI
};
}, [currentPage, labelId, categoryId, searchKeyword, t]);

// 筛选或翻页后让卡片区域回到顶部
useEffect(() => {
articlesRef.current?.scrollTo({ top: 0 });
}, [currentPage, labelId, categoryId, searchKeyword]);

const totalPages = Math.ceil(totalArticles / itemsPerPage);
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = startIndex + articles.length;
Expand Down Expand Up @@ -190,7 +206,7 @@ const ArticleList: React.FC<ArticleListProps> = ({ labelId, labelName, categoryI
};

return (
<div className={styles.articleList}>
<div className={`${styles.articleList} ${scrollable ? styles.articleListScrollable : ""}`}>
<div className={styles.listHeader}>
<h2 className={styles.title}>
{labelName
Expand All @@ -201,7 +217,7 @@ const ArticleList: React.FC<ArticleListProps> = ({ labelId, labelName, categoryI
</h2>
{headerRight && <div className={styles.headerRight}>{headerRight}</div>}
</div>
<div className={styles.articles}>
<div ref={articlesRef} className={styles.articles}>
{loading ? (
Array.from({ length: 5 }, (_, index) => (
<div key={index} className={styles.articleItem}>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/home/IndexPage.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
flex: 2;
min-width: 0;
min-height: 0;
overflow-y: auto;
overflow: hidden;
display: flex;
flex-direction: column;
scrollbar-width: none;
Expand Down
1 change: 1 addition & 0 deletions src/pages/home/IndexPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ const IndexPage: React.FC = () => {
categoryId={selectedCategoryId}
categoryName={selectedCategoryName}
searchKeyword={searchKeyword}
scrollable
headerRight={
<SearchBox
placeholder={t("searchPlaceholder")}
Expand Down
Loading