Commit 169a7810 authored by timel's avatar timel

feat: 组卡页ui

parent 848082e1
Pipeline #25890 failed with stages
in 1 minute and 11 seconds
...@@ -3,35 +3,30 @@ ...@@ -3,35 +3,30 @@
.detail { .detail {
z-index: 10; z-index: 10;
position: absolute; position: absolute;
left: -100%;
top: 0; top: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
padding: 0 0.625rem 1.25rem 0.625rem; padding: 0 0.625rem 1.25rem 0.625rem;
transition: 0.2s; transition: 0.1s;
opacity: 0;
pointer-events: none;
} }
.detail.open { .detail.open {
left: 0; opacity: 1;
pointer-events: unset;
} }
.container { .container {
height: 100%; height: 100%;
background: linear-gradient( // @include utils.noise-bg;
to bottom right,
hsla(0, 0%, 100%, 0.2),
hsla(0, 0%, 100%, 0)
);
box-shadow:
-1px 0 0 2px rgba(255, 255, 255, 0.15),
0 0 30px 0 #ffffff54;
backdrop-filter: blur(1.25rem);
@include utils.noise-bg;
padding: 1rem; padding: 1rem;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative; position: relative;
border-radius: 0.5rem; border: 1px solid rgba(255, 255, 255, 0.05);
background-color: hsla(0, 0%, 100%, 0.05);
backdrop-filter: blur(0.3rem);
} }
.btn-close { .btn-close {
...@@ -41,24 +36,18 @@ ...@@ -41,24 +36,18 @@
} }
.card { .card {
--width: 10rem; --width: 12rem;
width: var(--width); width: var(--width);
height: calc(var(--width) / var(--card-ratio)); height: calc(var(--width) / var(--card-ratio));
flex-shrink: 0; flex-shrink: 0;
border: 1px solid #ffffff52; border: 1px solid #ffffff52;
overflow: hidden; overflow: hidden;
box-shadow: 0 0 0.375rem 0.125rem #ffffff2b; box-shadow: 0 0 0.375rem 0.125rem #ffffff2b;
transition: 0.3s;
cursor: pointer; cursor: pointer;
&:hover {
--width: 13.75rem;
filter: contrast(1.1);
}
} }
.title { .title {
font-size: 1.25rem; font-size: 1.25rem;
font-family: var(--nato-serif-font);
margin: 1.25rem 0 1rem; margin: 1.25rem 0 1rem;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
......
...@@ -21,7 +21,8 @@ export const DeckSelect: React.FC<{ ...@@ -21,7 +21,8 @@ export const DeckSelect: React.FC<{
onDelete: (deckName: string) => Promise<any>; onDelete: (deckName: string) => Promise<any>;
onDownload: (deckName: string) => any; onDownload: (deckName: string) => any;
onCopy: (deckName: string) => Promise<any>; onCopy: (deckName: string) => Promise<any>;
}> = ({ decks, selected, onSelect, onDelete, onDownload, onCopy }) => { visible: boolean;
}> = ({ decks, selected, onSelect, onDelete, onDownload, onCopy, visible }) => {
const newDeck = useRef<IDeck[]>([]); const newDeck = useRef<IDeck[]>([]);
const { modal, message } = App.useApp(); const { modal, message } = App.useApp();
...@@ -63,42 +64,36 @@ export const DeckSelect: React.FC<{ ...@@ -63,42 +64,36 @@ export const DeckSelect: React.FC<{
}, },
}); });
/** 从剪贴板导入。为什么错误处理这么丑陋... */ /** 从剪贴板导入。尝试让错误处理更加简洁. */
const importFromClipboard = () => { const importFromClipboard = async () => {
try {
// 检查浏览器是否支持 Clipboard API // 检查浏览器是否支持 Clipboard API
if (navigator.clipboard) { if (!navigator.clipboard) {
// 获取剪贴板内容 throw new Error("浏览器不支持 Clipboard API");
navigator.clipboard }
.readText()
.then((text) => { // 使用 await 等待获取剪贴板内容
const text = await navigator.clipboard.readText();
const deck = YGOProDeck.fromYdkString(text); const deck = YGOProDeck.fromYdkString(text);
if (
!(deck.main.length + deck.extra.length + deck.side.length === 0) // 检查是否成功解析 YDK
) { if (deck.main.length + deck.extra.length + deck.side.length === 0) {
// YDK解析成功 throw new Error("解析失败,请检查格式是否正确。");
}
// YDK 解析成功
const deckName = new Date().toLocaleString(); const deckName = new Date().toLocaleString();
deckStore const result = await deckStore.add({ deckName, ...deck });
.add({
deckName, // 检查添加结果
...deck,
})
.then((result) => {
if (result) { if (result) {
message.success(`导入成功,卡组名为:${deckName}`); message.success(`导入成功,卡组名为:${deckName}`);
onSelect(deckName); onSelect(deckName);
} else { } else {
message.error(`解析失败,请检查格式是否正确。`); throw new Error("解析失败,请检查格式是否正确。");
} }
}); } catch (err: any) {
} else { message.error(`发生错误: ${err.message || err}`);
message.error(`解析失败,请检查格式是否正确。`);
}
})
.catch((err) => {
message.error("无法读取剪贴板内容:", err);
});
} else {
message.error("浏览器不支持 Clipboard API");
} }
}; };
...@@ -121,7 +116,7 @@ export const DeckSelect: React.FC<{ ...@@ -121,7 +116,7 @@ export const DeckSelect: React.FC<{
].map((_, key) => ({ ..._, key })); ].map((_, key) => ({ ..._, key }));
return ( return (
<> <div style={{ transition: "0.2s", opacity: visible ? 1 : 0 }}>
<div className={styles["deck-select"]}> <div className={styles["deck-select"]}>
{decks.map(({ deckName }) => ( {decks.map(({ deckName }) => (
<div <div
...@@ -173,7 +168,7 @@ export const DeckSelect: React.FC<{ ...@@ -173,7 +168,7 @@ export const DeckSelect: React.FC<{
size="large" size="large"
/> />
</Dropdown> </Dropdown>
</> </div>
); );
}; };
......
...@@ -86,6 +86,7 @@ export const loader: LoaderFunction = async () => { ...@@ -86,6 +86,7 @@ export const loader: LoaderFunction = async () => {
export const Component: React.FC = () => { export const Component: React.FC = () => {
const snapDecks = useSnapshot(deckStore); const snapDecks = useSnapshot(deckStore);
const { progress } = useSnapshot(initStore.sqlite); const { progress } = useSnapshot(initStore.sqlite);
const { open } = useSnapshot(selectedCard);
const [selectedDeck, setSelectedDeck] = useState<IDeck>( const [selectedDeck, setSelectedDeck] = useState<IDeck>(
deckStore.decks.at(0) ?? emptyDeck, deckStore.decks.at(0) ?? emptyDeck,
); );
...@@ -141,6 +142,7 @@ export const Component: React.FC = () => { ...@@ -141,6 +142,7 @@ export const Component: React.FC = () => {
if (deck) return await copyDeckToClipboard(deck); if (deck) return await copyDeckToClipboard(deck);
else return false; else return false;
}} }}
visible={!open}
/> />
</ScrollableArea> </ScrollableArea>
<HigherCardDetail /> <HigherCardDetail />
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
pointer-events: none; pointer-events: none;
z-index: 100; z-index: 100;
--bg-color: #323232; --bg-color: #323232;
width: 200px; width: 160px;
} }
.life-bar { .life-bar {
...@@ -24,16 +24,14 @@ ...@@ -24,16 +24,14 @@
padding: 1rem; padding: 1rem;
padding-bottom: 0.6rem; padding-bottom: 0.6rem;
border-radius: 8px; border-radius: 8px;
// text-align: left;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 8px;
.name { .name {
font-size: 0.8rem; font-size: 0.8rem;
font-weight: bold; font-weight: bold;
} }
.life { .life {
font-size: 1.8rem; font-size: 1.4rem;
} }
} }
.timer-container { .timer-container {
......
...@@ -31,7 +31,7 @@ export const theme: ThemeConfig = { ...@@ -31,7 +31,7 @@ export const theme: ThemeConfig = {
colorBgContainer: "hsla(0, 0%, 100%, 0.05)", colorBgContainer: "hsla(0, 0%, 100%, 0.05)",
}, },
Dropdown: { Dropdown: {
colorBgElevated: "#2e3c50", // colorBgElevated: "#2e3c50",
boxShadow: boxShadow:
"0 6px 16px 0 rgb(51 51 51 / 80%), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05)", "0 6px 16px 0 rgb(51 51 51 / 80%), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05)",
}, },
......
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