Commit 5d6b93e2 authored by timel's avatar timel

feat: scroll to top when changing page

parent 30650297
Pipeline #23042 failed with stages
in 2 minutes and 22 seconds
......@@ -18,6 +18,7 @@ import {
} from "antd";
import classNames from "classnames";
import { isEqual } from "lodash-es";
import { type OverlayScrollbarsComponentRef } from "overlayscrollbars-react";
import { memo, useEffect, useRef, useState } from "react";
import { DndProvider, useDrag, useDrop } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
......@@ -207,13 +208,14 @@ const Search: React.FC = () => {
);
const [searchResult, setSearchResult] = useState<CardMeta[]>([]);
const sortRef = useRef<(a: CardMeta, b: CardMeta) => number>(
(a: CardMeta, b: CardMeta) => a.id - b.id
);
const defaultSort = (a: CardMeta, b: CardMeta) => a.id - b.id;
const sortRef = useRef<(a: CardMeta, b: CardMeta) => number>(defaultSort);
const [sortEdited, setSortEdited] = useState(false);
const setSortRef = (sort: (a: CardMeta, b: CardMeta) => number) => {
sortRef.current = sort;
setSearchResult([...searchResult.sort(sortRef.current)]);
setSortEdited(true);
};
const genSort = (key: keyof CardMeta["data"], scale: 1 | -1 = 1) => {
......@@ -282,6 +284,13 @@ const Search: React.FC = () => {
});
};
/** 滚动条的ref */
const ref = useRef<OverlayScrollbarsComponentRef<"div">>(null);
const scrollToTop = () => {
const viewport = ref.current?.osInstance()?.elements().viewport;
if (viewport) viewport.scrollTop = 0;
};
return (
<div className={styles.container} ref={dropRef}>
<div className={styles.title}>
......@@ -320,7 +329,11 @@ const Search: React.FC = () => {
placement="bottom"
arrow
>
<Button block type="text" icon={<SortAscendingOutlined />}>
<Button
block
type={sortEdited ? "primary" : "text"}
icon={<SortAscendingOutlined />}
>
<span>
排列
<span className={styles["search-count"]}>
......@@ -333,14 +346,18 @@ const Search: React.FC = () => {
block
type="text"
icon={<DeleteOutlined />}
onClick={() => setSearchConditions(emptySearchConditions)}
onClick={() => {
setSearchConditions(emptySearchConditions);
setSortRef(defaultSort);
setSortEdited(false);
}}
>
重置
</Button>
</div>
<ScrollableArea className={styles["search-cards-container"]}>
<ScrollableArea className={styles["search-cards-container"]} ref={ref}>
{searchResult.length ? (
<SearchResults results={searchResult} />
<SearchResults results={searchResult} scrollToTop={scrollToTop} />
) : (
<div className={styles.empty}>
<IconFont type="icon-empty" size={40} />
......@@ -410,13 +427,14 @@ const DeckZone: React.FC<{
/** 搜索区的搜索结果,使用memo避免重复渲染 */
const SearchResults: React.FC<{
results: CardMeta[];
}> = memo(({ results }) => {
scrollToTop: () => void;
}> = memo(({ results, scrollToTop }) => {
const handleClick = (card: CardMeta) => {
const type = isExtraDeckCard(card.data.type ?? 0) ? "extra" : "main";
editDeckStore.canAdd(card, type).result && editDeckStore.add(type, card);
};
const itemsPerPage = 200; // 每页显示的数据数量
const itemsPerPage = 196; // 每页显示的数据数量
const [currentPage, setCurrentPage] = useState(1);
useEffect(() => {
......@@ -442,8 +460,12 @@ const SearchResults: React.FC<{
<div style={{ textAlign: "center", padding: "10px 0 20px" }}>
<Pagination
current={currentPage}
onChange={(page) => setCurrentPage(page)}
onChange={(page) => {
setCurrentPage(page);
scrollToTop();
}}
total={results.length}
pageSize={itemsPerPage}
showSizeChanger={false}
showLessItems
hideOnSinglePage
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment