Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
N
Neos
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
love_飞影
Neos
Commits
f0a2423d
Commit
f0a2423d
authored
Aug 13, 2023
by
timel
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev/upload-deck' into 'main'
feat: upload deck See merge request
!256
parents
78112517
4cc684e9
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
111 additions
and
75 deletions
+111
-75
src/styles/inject.scss
src/styles/inject.scss
+6
-0
src/ui/BuildDeck/DeckSelect.tsx
src/ui/BuildDeck/DeckSelect.tsx
+101
-69
src/ui/BuildDeck/Filter.module.scss
src/ui/BuildDeck/Filter.module.scss
+2
-1
src/ui/BuildDeck/index.tsx
src/ui/BuildDeck/index.tsx
+1
-4
src/ui/theme.ts
src/ui/theme.ts
+1
-1
No files found.
src/styles/inject.scss
View file @
f0a2423d
...
@@ -25,8 +25,14 @@
...
@@ -25,8 +25,14 @@
.ant-modal-confirm-content
{
.ant-modal-confirm-content
{
max-width
:
100%
!
important
;
max-width
:
100%
!
important
;
width
:
100%
;
}
}
.ant-select-dropdown
{
.ant-select-dropdown
{
backdrop-filter
:
blur
(
10px
);
backdrop-filter
:
blur
(
10px
);
}
}
.ant-modal-confirm
.ant-modal-confirm-btns
{
display
:
flex
;
justify-content
:
end
;
}
src/ui/BuildDeck/DeckSelect.tsx
View file @
f0a2423d
...
@@ -2,18 +2,11 @@ import {
...
@@ -2,18 +2,11 @@ import {
DeleteOutlined
,
DeleteOutlined
,
DownloadOutlined
,
DownloadOutlined
,
FileAddOutlined
,
FileAddOutlined
,
InboxOutlined
,
PlusOutlined
,
PlusOutlined
,
Upload
Outlined
,
Copy
Outlined
,
}
from
"
@ant-design/icons
"
;
}
from
"
@ant-design/icons
"
;
import
{
import
{
App
,
Button
,
Dropdown
,
MenuProps
,
Upload
,
UploadProps
}
from
"
antd
"
;
App
,
Button
,
Dropdown
,
Input
,
MenuProps
,
Upload
,
UploadProps
,
}
from
"
antd
"
;
import
React
,
{
useRef
,
useState
}
from
"
react
"
;
import
React
,
{
useRef
,
useState
}
from
"
react
"
;
import
YGOProDeck
from
"
ygopro-deck-encode
"
;
import
YGOProDeck
from
"
ygopro-deck-encode
"
;
...
@@ -24,75 +17,105 @@ import styles from "./DeckSelect.module.scss";
...
@@ -24,75 +17,105 @@ import styles from "./DeckSelect.module.scss";
export
const
DeckSelect
:
React
.
FC
<
{
export
const
DeckSelect
:
React
.
FC
<
{
decks
:
readonly
{
deckName
:
string
}[];
decks
:
readonly
{
deckName
:
string
}[];
selected
:
string
;
selected
:
string
;
onSelect
:
(
deckName
:
string
)
=>
void
;
onSelect
:
(
deckName
:
string
)
=>
any
;
onDelete
:
(
deckName
:
string
)
=>
void
;
onDelete
:
(
deckName
:
string
)
=>
Promise
<
any
>
;
onDownload
:
(
deckName
:
string
)
=>
void
;
onDownload
:
(
deckName
:
string
)
=>
any
;
onAdd
:
()
=>
void
;
}
>
=
({
decks
,
selected
,
onSelect
,
onDelete
,
onDownload
})
=>
{
}
>
=
({
decks
,
selected
,
onSelect
,
onDelete
,
onDownload
,
onAdd
})
=>
{
const
newDeck
=
useRef
<
IDeck
[]
>
([]);
const
newDeck
=
useRef
<
IDeck
|
null
>
(
null
);
const
{
modal
,
message
}
=
App
.
useApp
();
const
newDeckName
=
useRef
<
string
|
null
>
(
null
);
const
{
modal
}
=
App
.
useApp
();
/** 创建卡组,直接给一个命名,用户可以手动修改,无需modal打断流程 */
const
modalProps
=
{
width
:
500
,
centered
:
true
,
icon
:
null
};
const
createNewDeck
=
async
()
=>
{
const
showCreateModal
=
()
=>
{
const
deckName
=
new
Date
().
toLocaleString
();
const
{
destroy
}
=
modal
.
info
({
await
deckStore
.
add
({
...
modalProps
,
deckName
,
title
:
"
请输入新卡组名称
"
,
main
:
[],
content
:
(
extra
:
[],
<
Input
side
:
[],
onChange=
{
(
e
)
=>
{
newDeckName
.
current
=
e
.
target
.
value
;
}
}
/>
),
okText
:
"
新建
"
,
onCancel
:
()
=>
destroy
(),
onOk
:
async
()
=>
{
if
(
newDeckName
.
current
&&
newDeckName
.
current
!==
""
)
{
await
deckStore
.
add
({
deckName
:
newDeckName
.
current
,
main
:
[],
extra
:
[],
side
:
[],
});
}
},
});
});
onSelect
(
deckName
);
};
};
const
showUploadModal
=
()
=>
{
const
{
destroy
}
=
modal
.
info
({
const
showUploadModal
=
()
=>
...
modalProps
,
modal
.
info
({
title
:
"
请上传YDK文件
"
,
width
:
600
,
centered
:
true
,
icon
:
null
,
content
:
(
content
:
(
<
DeckUploader
<
DeckUploader
onLoaded=
{
(
deck
)
=>
{
onLoaded=
{
(
deck
)
=>
{
newDeck
.
current
=
deck
;
newDeck
.
current
.
push
(
deck
)
;
}
}
}
}
/>
/>
),
),
okText
:
"
上传
"
,
okText
:
"
上传
"
,
onCancel
:
()
=>
destroy
()
,
maskClosable
:
true
,
onOk
:
async
()
=>
{
onOk
:
async
()
=>
{
if
(
newDeck
.
current
)
{
const
newDecks
=
await
Promise
.
all
(
await
deckStore
.
add
(
newDeck
.
current
);
newDeck
.
current
.
map
((
deck
)
=>
deckStore
.
add
(
deck
))
}
);
newDecks
.
every
(
Boolean
)
?
message
.
success
(
"
上传成功
"
)
:
message
.
error
(
"
部分文件上传失败
"
);
},
},
});
});
/** 从剪贴板导入。为什么错误处理这么丑陋... */
const
importFromClipboard
=
()
=>
{
// 检查浏览器是否支持 Clipboard API
if
(
navigator
.
clipboard
)
{
// 获取剪贴板内容
navigator
.
clipboard
.
readText
()
.
then
((
text
)
=>
{
const
deck
=
YGOProDeck
.
fromYdkString
(
text
);
if
(
!
(
deck
.
main
.
length
+
deck
.
extra
.
length
+
deck
.
side
.
length
===
0
)
)
{
// YDK解析成功
const
deckName
=
new
Date
().
toLocaleString
();
deckStore
.
add
({
deckName
,
...
deck
,
})
.
then
((
result
)
=>
{
if
(
result
)
{
message
.
success
(
`导入成功,卡组名为:
${
deckName
}
`
);
onSelect
(
deckName
);
}
else
{
message
.
error
(
`解析失败,请检查格式是否正确。`
);
}
});
}
else
{
message
.
error
(
`解析失败,请检查格式是否正确。`
);
}
})
.
catch
((
err
)
=>
{
message
.
error
(
"
无法读取剪贴板内容:
"
,
err
);
});
}
else
{
message
.
error
(
"
浏览器不支持 Clipboard API
"
);
}
};
};
const
items
:
MenuProps
[
"
items
"
]
=
[
const
items
:
MenuProps
[
"
items
"
]
=
[
{
{
key
:
"
1
"
,
label
:
"
新建卡组
"
,
label
:
"
新建卡组
"
,
icon
:
<
PlusOutlined
/>,
icon
:
<
PlusOutlined
/>,
onClick
:
showCreateModal
,
onClick
:
createNewDeck
,
},
},
{
{
key
:
"
2
"
,
label
:
"
从本地文件导入
"
,
label
:
"
导入卡组
"
,
icon
:
<
FileAddOutlined
/>,
icon
:
<
FileAddOutlined
/>,
onClick
:
showUploadModal
,
onClick
:
showUploadModal
,
},
},
];
{
label
:
"
从剪贴板导入
"
,
icon
:
<
CopyOutlined
/>,
onClick
:
importFromClipboard
,
},
].
map
((
_
,
key
)
=>
({
...
_
,
key
}));
return
(
return
(
<>
<>
...
@@ -111,7 +134,10 @@ export const DeckSelect: React.FC<{
...
@@ -111,7 +134,10 @@ export const DeckSelect: React.FC<{
icon=
{
<
DeleteOutlined
/>
}
icon=
{
<
DeleteOutlined
/>
}
type=
"text"
type=
"text"
size=
"small"
size=
"small"
onClick=
{
cancelBubble
(()
=>
onDelete
(
deckName
))
}
onClick=
{
cancelBubble
(
async
()
=>
{
await
onDelete
(
deckName
);
onSelect
(
decks
[
0
].
deckName
);
})
}
/>
/>
<
Button
<
Button
icon=
{
<
DownloadOutlined
/>
}
icon=
{
<
DownloadOutlined
/>
}
...
@@ -129,7 +155,6 @@ export const DeckSelect: React.FC<{
...
@@ -129,7 +155,6 @@ export const DeckSelect: React.FC<{
icon=
{
<
PlusOutlined
/>
}
icon=
{
<
PlusOutlined
/>
}
shape=
"circle"
shape=
"circle"
type=
"text"
type=
"text"
onClick=
{
onAdd
}
size=
"large"
size=
"large"
/>
/>
</
Dropdown
>
</
Dropdown
>
...
@@ -141,31 +166,29 @@ const DeckUploader: React.FC<{ onLoaded: (deck: IDeck) => void }> = ({
...
@@ -141,31 +166,29 @@ const DeckUploader: React.FC<{ onLoaded: (deck: IDeck) => void }> = ({
onLoaded
,
onLoaded
,
})
=>
{
})
=>
{
const
[
uploadState
,
setUploadState
]
=
useState
(
""
);
const
[
uploadState
,
setUploadState
]
=
useState
(
""
);
const
{
message
}
=
App
.
useApp
();
const
uploadProps
:
UploadProps
=
{
const
uploadProps
:
UploadProps
=
{
name
:
"
file
"
,
name
:
"
file
"
,
multiple
:
true
,
onChange
(
info
)
{
onChange
(
info
)
{
if
(
uploadState
!=
"
ERROR
"
)
{
if
(
uploadState
!=
"
ERROR
"
)
{
info
.
file
.
status
=
"
done
"
;
info
.
file
.
status
=
"
done
"
;
}
}
},
},
accept
:
"
.ydk
"
,
beforeUpload
(
file
,
_
)
{
beforeUpload
(
file
,
_
)
{
console
.
log
({
file
});
const
reader
=
new
FileReader
();
const
reader
=
new
FileReader
();
reader
.
readAsText
(
file
);
reader
.
readAsText
(
file
);
reader
.
onload
=
(
e
)
=>
{
reader
.
onload
=
(
e
)
=>
{
const
ydk
=
e
.
target
?.
result
as
string
;
const
ydk
=
e
.
target
?.
result
as
string
;
const
deck
=
YGOProDeck
.
fromYdkString
(
ydk
);
const
deck
=
YGOProDeck
.
fromYdkString
(
ydk
);
if
(
if
(
!
(
deck
.
main
.
length
+
deck
.
extra
.
length
+
deck
.
side
.
length
===
0
))
{
!
(
deck
.
main
.
length
===
0
&&
deck
.
extra
.
length
===
0
&&
deck
.
side
.
length
===
0
)
)
{
// YDK解析成功
// YDK解析成功
onLoaded
({
deckName
:
file
.
name
.
replace
(
/
\.
ydk/g
,
""
),
...
deck
});
onLoaded
({
deckName
:
file
.
name
.
replace
(
/
\.
ydk/g
,
""
),
...
deck
});
}
else
{
}
else
{
alert
(
`
${
file
.
name
}
解析失败,请检查格式是否正确。`
);
message
.
error
(
`
${
file
.
name
}
解析失败,请检查格式是否正确。`
);
setUploadState
(
"
ERROR
"
);
setUploadState
(
"
ERROR
"
);
}
}
};
};
...
@@ -173,9 +196,18 @@ const DeckUploader: React.FC<{ onLoaded: (deck: IDeck) => void }> = ({
...
@@ -173,9 +196,18 @@ const DeckUploader: React.FC<{ onLoaded: (deck: IDeck) => void }> = ({
};
};
return
(
return
(
<
Upload
{
...
uploadProps
}
>
<
div
>
<
Button
icon=
{
<
UploadOutlined
/>
}
>
点击上传
</
Button
>
<
Upload
.
Dragger
</
Upload
>
{
...
uploadProps
}
style=
{
{
width
:
"
100%
"
,
margin
:
"
20px 0 10px
"
}
}
>
<
p
className=
"ant-upload-drag-icon"
>
<
InboxOutlined
/>
</
p
>
<
p
className=
"ant-upload-text"
>
单击或拖动文件到此区域进行上传
</
p
>
<
p
className=
"ant-upload-hint"
>
仅支持后缀名为ydk的卡组文件。
</
p
>
</
Upload
.
Dragger
>
</
div
>
);
);
};
};
...
...
src/ui/BuildDeck/Filter.module.scss
View file @
f0a2423d
...
@@ -21,6 +21,7 @@
...
@@ -21,6 +21,7 @@
display
:
flex
;
display
:
flex
;
flex-direction
:
column
;
flex-direction
:
column
;
gap
:
20px
;
gap
:
20px
;
padding
:
8px
;
}
}
.btns
{
.btns
{
...
@@ -28,7 +29,7 @@
...
@@ -28,7 +29,7 @@
flex-direction
:
column
;
flex-direction
:
column
;
gap
:
10px
;
gap
:
10px
;
align-items
:
center
;
align-items
:
center
;
padding
:
5
0px
0
10px
;
padding
:
3
0px
0
10px
;
&
>
button
{
&
>
button
{
width
:
220px
;
width
:
220px
;
border-radius
:
3px
;
border-radius
:
3px
;
...
...
src/ui/BuildDeck/index.tsx
View file @
f0a2423d
...
@@ -104,11 +104,8 @@ export const Component: React.FC = () => {
...
@@ -104,11 +104,8 @@ export const Component: React.FC = () => {
onDelete=
{
async
(
name
)
=>
await
deckStore
.
delete
(
name
)
}
onDelete=
{
async
(
name
)
=>
await
deckStore
.
delete
(
name
)
}
onDownload=
{
(
name
)
=>
{
onDownload=
{
(
name
)
=>
{
const
deck
=
deckStore
.
get
(
name
);
const
deck
=
deckStore
.
get
(
name
);
if
(
deck
)
{
if
(
deck
)
downloadDeckAsYDK
(
deck
);
downloadDeckAsYDK
(
deck
);
}
}
}
}
}
onAdd=
{
()
=>
console
.
log
(
"
add
"
)
}
/>
/>
</
ScrollableArea
>
</
ScrollableArea
>
<
HigherCardDetail
/>
<
HigherCardDetail
/>
...
...
src/ui/theme.ts
View file @
f0a2423d
...
@@ -14,7 +14,7 @@ export const theme: ThemeConfig = {
...
@@ -14,7 +14,7 @@ export const theme: ThemeConfig = {
Modal
:
{
Modal
:
{
colorBgElevated
:
"
#1f2531
"
,
colorBgElevated
:
"
#1f2531
"
,
paddingMD
:
24
,
paddingMD
:
24
,
paddingContentHorizontalLG
:
48
,
paddingContentHorizontalLG
:
36
,
},
},
Select
:
{
Select
:
{
colorBgElevated
:
"
hsla(0, 0%, 20%, 0.3)
"
,
colorBgElevated
:
"
hsla(0, 0%, 20%, 0.3)
"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment