Commit d8217948 authored by timel's avatar timel

feat: card name behind cover, as placeholder

parent e4e6b9f5
Pipeline #22979 canceled with stages
in 28 seconds
...@@ -91,6 +91,28 @@ ...@@ -91,6 +91,28 @@
width: 100%; width: 100%;
background-color: rgba(255, 255, 255, 0.1); background-color: rgba(255, 255, 255, 0.1);
aspect-ratio: var(--card-ratio); aspect-ratio: var(--card-ratio);
position: relative;
background-size: contain;
.cardname {
font-size: 0.9rem;
position: absolute;
padding: 5px;
top: 0;
bottom: 0;
max-height: 100%;
margin: auto;
left: 0;
height: fit-content;
width: 100%;
text-align: center;
line-height: 1.75em;
overflow: hidden; //超出的文本隐藏
text-overflow: ellipsis; //溢出用省略号显示
}
.cardcover {
position: relative;
// z-index: 1;
}
} }
.search-cards-container { .search-cards-container {
......
...@@ -15,7 +15,7 @@ import { ...@@ -15,7 +15,7 @@ import {
Space, Space,
type ThemeConfig, type ThemeConfig,
} from "antd"; } from "antd";
import { useEffect, useState } from "react"; import { memo, useEffect, useState } from "react";
import { useSnapshot } from "valtio"; import { useSnapshot } from "valtio";
import { subscribeKey } from "valtio/utils"; import { subscribeKey } from "valtio/utils";
...@@ -26,7 +26,14 @@ import { CardDetail } from "./CardDetail"; ...@@ -26,7 +26,14 @@ import { CardDetail } from "./CardDetail";
import { DeckSelect } from "./DeckSelect"; import { DeckSelect } from "./DeckSelect";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
import { LoaderFunction } from "react-router-dom"; import { LoaderFunction } from "react-router-dom";
import { searchCards, type CardMeta } from "@/api"; import { searchCards, type CardMeta, fetchCard } from "@/api";
import { v4 as v4uuid } from "uuid";
import classNames from "classnames";
import {
iDeckToEditingDeck,
type EditingDeck,
editingDeckToIDeck,
} from "./utils";
const theme: ThemeConfig = { const theme: ThemeConfig = {
components: { components: {
...@@ -95,9 +102,14 @@ const DeckEditor: React.FC<{ ...@@ -95,9 +102,14 @@ const DeckEditor: React.FC<{
deck: IDeck; deck: IDeck;
onSave: (deck: IDeck) => void; onSave: (deck: IDeck) => void;
}> = ({ deck, onSave }) => { }> = ({ deck, onSave }) => {
const [editingDeck, setEditingDeck] = useState<IDeck>(deck); const [editingDeck, setEditingDeck] = useState<EditingDeck>({
deckName: deck.deckName,
main: [],
extra: [],
side: [],
});
useEffect(() => { useEffect(() => {
setEditingDeck(deck); iDeckToEditingDeck(deck).then(setEditingDeck);
}, [deck]); }, [deck]);
return ( return (
<div className={styles.container}> <div className={styles.container}>
...@@ -123,7 +135,7 @@ const DeckEditor: React.FC<{ ...@@ -123,7 +135,7 @@ const DeckEditor: React.FC<{
type="text" type="text"
size="small" size="small"
icon={<CheckOutlined />} icon={<CheckOutlined />}
onClick={() => onSave(editingDeck)} onClick={() => onSave(editingDeckToIDeck(editingDeck))}
> >
保存 保存
</Button> </Button>
...@@ -133,10 +145,8 @@ const DeckEditor: React.FC<{ ...@@ -133,10 +145,8 @@ const DeckEditor: React.FC<{
{(["main", "extra", "side"] as const).map((type) => ( {(["main", "extra", "side"] as const).map((type) => (
<div key={type} className={styles[type]}> <div key={type} className={styles[type]}>
<div className={styles["card-continer"]}> <div className={styles["card-continer"]}>
{editingDeck[type].map((code, i) => ( {editingDeck[type].map((item) => (
<div className={styles.card} key={i}> <Card value={item} key={v4uuid()} />
<YgoCard code={code} />
</div>
))} ))}
</div> </div>
</div> </div>
...@@ -192,14 +202,27 @@ const CardSelect: React.FC = () => { ...@@ -192,14 +202,27 @@ const CardSelect: React.FC = () => {
</Button> </Button>
</div> </div>
<ScrollableArea className={styles["search-cards-container"]}> <ScrollableArea className={styles["search-cards-container"]}>
<div className={styles["search-cards"]}> <SearchResults results={searchResult} />
{searchResult.map(({ id }, i) => (
<div className={styles.card} key={i}>
<YgoCard code={id} />
</div>
))}
</div>
</ScrollableArea> </ScrollableArea>
</div> </div>
); );
}; };
/** 搜索区的搜索结果,使用memo避免重复渲染 */
const SearchResults: React.FC<{
results: CardMeta[];
}> = memo(({ results }) => (
<div className={styles["search-cards"]}>
{results.map((item) => (
<Card value={item} key={v4uuid()} />
))}
</div>
));
/** 本组件内使用的单张卡片,增加了文字在图片下方 */
const Card: React.FC<{ value: CardMeta }> = memo(({ value }) => (
<div className={styles.card}>
<div className={styles.cardname}>{value.text.name}</div>
<YgoCard className={styles.cardcover} code={value.id} />
</div>
));
import { type CardMeta, fetchCard } from "@/api";
import { type IDeck } from "@/stores";
/** 用在卡组编辑 */
export interface EditingDeck {
deckName: string;
main: CardMeta[];
extra: CardMeta[];
side: CardMeta[];
}
export const iDeckToEditingDeck = async (
ideck: IDeck
): Promise<EditingDeck> => ({
deckName: ideck.deckName,
main: await Promise.all(ideck.main.map(fetchCard)),
extra: await Promise.all(ideck.extra.map(fetchCard)),
side: await Promise.all(ideck.side.map(fetchCard)),
});
export const editingDeckToIDeck = (deck: EditingDeck): IDeck => ({
deckName: deck.deckName,
main: deck.main.map((card) => card.id),
extra: deck.extra.map((card) => card.id),
side: deck.side.map((card) => card.id),
});
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