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 { ...@@ -18,6 +18,7 @@ import {
} from "antd"; } from "antd";
import classNames from "classnames"; import classNames from "classnames";
import { isEqual } from "lodash-es"; import { isEqual } from "lodash-es";
import { type OverlayScrollbarsComponentRef } from "overlayscrollbars-react";
import { memo, useEffect, useRef, useState } from "react"; import { memo, useEffect, useRef, useState } from "react";
import { DndProvider, useDrag, useDrop } from "react-dnd"; import { DndProvider, useDrag, useDrop } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend"; import { HTML5Backend } from "react-dnd-html5-backend";
...@@ -207,13 +208,14 @@ const Search: React.FC = () => { ...@@ -207,13 +208,14 @@ const Search: React.FC = () => {
); );
const [searchResult, setSearchResult] = useState<CardMeta[]>([]); const [searchResult, setSearchResult] = useState<CardMeta[]>([]);
const sortRef = useRef<(a: CardMeta, b: CardMeta) => number>( const defaultSort = (a: CardMeta, b: CardMeta) => a.id - b.id;
(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) => { const setSortRef = (sort: (a: CardMeta, b: CardMeta) => number) => {
sortRef.current = sort; sortRef.current = sort;
setSearchResult([...searchResult.sort(sortRef.current)]); setSearchResult([...searchResult.sort(sortRef.current)]);
setSortEdited(true);
}; };
const genSort = (key: keyof CardMeta["data"], scale: 1 | -1 = 1) => { const genSort = (key: keyof CardMeta["data"], scale: 1 | -1 = 1) => {
...@@ -282,6 +284,13 @@ const Search: React.FC = () => { ...@@ -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 ( return (
<div className={styles.container} ref={dropRef}> <div className={styles.container} ref={dropRef}>
<div className={styles.title}> <div className={styles.title}>
...@@ -320,7 +329,11 @@ const Search: React.FC = () => { ...@@ -320,7 +329,11 @@ const Search: React.FC = () => {
placement="bottom" placement="bottom"
arrow arrow
> >
<Button block type="text" icon={<SortAscendingOutlined />}> <Button
block
type={sortEdited ? "primary" : "text"}
icon={<SortAscendingOutlined />}
>
<span> <span>
排列 排列
<span className={styles["search-count"]}> <span className={styles["search-count"]}>
...@@ -333,14 +346,18 @@ const Search: React.FC = () => { ...@@ -333,14 +346,18 @@ const Search: React.FC = () => {
block block
type="text" type="text"
icon={<DeleteOutlined />} icon={<DeleteOutlined />}
onClick={() => setSearchConditions(emptySearchConditions)} onClick={() => {
setSearchConditions(emptySearchConditions);
setSortRef(defaultSort);
setSortEdited(false);
}}
> >
重置 重置
</Button> </Button>
</div> </div>
<ScrollableArea className={styles["search-cards-container"]}> <ScrollableArea className={styles["search-cards-container"]} ref={ref}>
{searchResult.length ? ( {searchResult.length ? (
<SearchResults results={searchResult} /> <SearchResults results={searchResult} scrollToTop={scrollToTop} />
) : ( ) : (
<div className={styles.empty}> <div className={styles.empty}>
<IconFont type="icon-empty" size={40} /> <IconFont type="icon-empty" size={40} />
...@@ -410,13 +427,14 @@ const DeckZone: React.FC<{ ...@@ -410,13 +427,14 @@ const DeckZone: React.FC<{
/** 搜索区的搜索结果,使用memo避免重复渲染 */ /** 搜索区的搜索结果,使用memo避免重复渲染 */
const SearchResults: React.FC<{ const SearchResults: React.FC<{
results: CardMeta[]; results: CardMeta[];
}> = memo(({ results }) => { scrollToTop: () => void;
}> = memo(({ results, scrollToTop }) => {
const handleClick = (card: CardMeta) => { const handleClick = (card: CardMeta) => {
const type = isExtraDeckCard(card.data.type ?? 0) ? "extra" : "main"; const type = isExtraDeckCard(card.data.type ?? 0) ? "extra" : "main";
editDeckStore.canAdd(card, type).result && editDeckStore.add(type, card); editDeckStore.canAdd(card, type).result && editDeckStore.add(type, card);
}; };
const itemsPerPage = 200; // 每页显示的数据数量 const itemsPerPage = 196; // 每页显示的数据数量
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
useEffect(() => { useEffect(() => {
...@@ -442,8 +460,12 @@ const SearchResults: React.FC<{ ...@@ -442,8 +460,12 @@ const SearchResults: React.FC<{
<div style={{ textAlign: "center", padding: "10px 0 20px" }}> <div style={{ textAlign: "center", padding: "10px 0 20px" }}>
<Pagination <Pagination
current={currentPage} current={currentPage}
onChange={(page) => setCurrentPage(page)} onChange={(page) => {
setCurrentPage(page);
scrollToTop();
}}
total={results.length} total={results.length}
pageSize={itemsPerPage}
showSizeChanger={false} showSizeChanger={false}
showLessItems showLessItems
hideOnSinglePage 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