Commit e4e6b9f5 authored by timel's avatar timel

feat: search card

parent 479b78a7
Pipeline #22977 failed with stages
in 15 minutes and 25 seconds
......@@ -62,7 +62,7 @@ export async function fetchCard(id: number): Promise<CardMeta> {
* @returns 卡片数据
*
* */
export async function searchCard(
export async function searchCards(
query: string,
type?: number
): Promise<CardMeta[]> {
......@@ -77,7 +77,7 @@ export async function searchCard(
// @ts-ignore
window.fetchCard = fetchCard;
// @ts-ignore
window.searchCard = searchCard;
window.searchCard = searchCards;
export function getCardStr(meta: CardMeta, idx: number): string | undefined {
switch (idx) {
......
......@@ -102,3 +102,7 @@
gap: 10px;
}
}
.search-count {
font-size: 11px;
}
......@@ -26,6 +26,7 @@ import { CardDetail } from "./CardDetail";
import { DeckSelect } from "./DeckSelect";
import styles from "./index.module.scss";
import { LoaderFunction } from "react-router-dom";
import { searchCards, type CardMeta } from "@/api";
const theme: ThemeConfig = {
components: {
......@@ -147,14 +148,28 @@ const DeckEditor: React.FC<{
/** 卡片库,选择卡片加入正在编辑的卡组 */
const CardSelect: React.FC = () => {
const [searchResult, setSearchResult] = useState<number[]>([]);
const [searchWord, setSearchWord] = useState("");
const [searchResult, setSearchResult] = useState<CardMeta[]>([]);
const handleSearch = async () => {
const result = await searchCards(searchWord);
setSearchResult(result);
};
return (
<div className={styles.container}>
<div className={styles.title}>
<Input
placeholder="搜索卡片"
bordered={false}
suffix={<Button type="text" icon={<SearchOutlined />} />}
suffix={
<Button
type="text"
icon={<SearchOutlined />}
onClick={handleSearch}
/>
}
value={searchWord}
onChange={(e) => setSearchWord(e.target.value)}
onKeyUp={(e) => e.key === "Enter" && handleSearch()}
/>
</div>
<div className={styles["select-btns"]}>
......@@ -164,7 +179,12 @@ const CardSelect: React.FC = () => {
{false && <Badge dot offset={[5, -5]} />}
</Button>
<Button block type="text" icon={<SortAscendingOutlined />}>
排列
<span>
排列
<span className={styles["search-count"]}>
({searchResult.length})
</span>
</span>
{false && <Badge dot offset={[5, -5]} />}
</Button>
<Button block type="text" icon={<DeleteOutlined />}>
......@@ -173,8 +193,10 @@ const CardSelect: React.FC = () => {
</div>
<ScrollableArea className={styles["search-cards-container"]}>
<div className={styles["search-cards"]}>
{Array.from({ length: 60 }).map((_, i) => (
<div className={styles.card} key={i} />
{searchResult.map(({ id }, i) => (
<div className={styles.card} key={i}>
<YgoCard code={id} />
</div>
))}
</div>
</ScrollableArea>
......
......@@ -20,11 +20,13 @@ export const loader: LoaderFunction = async () => {
const user = getCookie<User>(CookieKeys.USER);
if (user) accountStore.login(user);
// 加载卡组
deckStore.initialize().then(() => (initStore.decks = true));
if (!initStore.decks)
deckStore.initialize().then(() => (initStore.decks = true));
// 加载ygodb
initSqlite().then(() => (initStore.sqlite.progress = 1));
initStore.sqlite.progress = 0.01;
if (!initStore.sqlite.progress) {
initSqlite().then(() => (initStore.sqlite.progress = 1));
initStore.sqlite.progress = 0.01;
}
return null;
};
......
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