Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
4c1a23d6
authored
Nov 10, 2023
by
CaIon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
完善兑换码界面
parent
78e05b8e
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
197 additions
and
75 deletions
+197
-75
controller/token.go
+2
-1
model/token.go
+6
-2
web/src/components/RedemptionsTable.js
+73
-24
web/src/components/TokensTable.js
+13
-3
web/src/pages/Redemption/EditRedemption.js
+88
-35
web/src/pages/Redemption/index.js
+9
-3
web/src/pages/Token/EditToken.js
+2
-2
web/src/pages/Token/index.js
+4
-5
No files found.
controller/token.go
View file @
4c1a23d6
...
@@ -39,7 +39,8 @@ func GetAllTokens(c *gin.Context) {
...
@@ -39,7 +39,8 @@ func GetAllTokens(c *gin.Context) {
func
SearchTokens
(
c
*
gin
.
Context
)
{
func
SearchTokens
(
c
*
gin
.
Context
)
{
userId
:=
c
.
GetInt
(
"id"
)
userId
:=
c
.
GetInt
(
"id"
)
keyword
:=
c
.
Query
(
"keyword"
)
keyword
:=
c
.
Query
(
"keyword"
)
tokens
,
err
:=
model
.
SearchUserTokens
(
userId
,
keyword
)
token
:=
c
.
Query
(
"token"
)
tokens
,
err
:=
model
.
SearchUserTokens
(
userId
,
keyword
,
token
)
if
err
!=
nil
{
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"success"
:
false
,
...
...
model/token.go
View file @
4c1a23d6
...
@@ -5,6 +5,7 @@ import (
...
@@ -5,6 +5,7 @@ import (
"fmt"
"fmt"
"gorm.io/gorm"
"gorm.io/gorm"
"one-api/common"
"one-api/common"
"strings"
)
)
type
Token
struct
{
type
Token
struct
{
...
@@ -28,8 +29,11 @@ func GetAllUserTokens(userId int, startIdx int, num int) ([]*Token, error) {
...
@@ -28,8 +29,11 @@ func GetAllUserTokens(userId int, startIdx int, num int) ([]*Token, error) {
return
tokens
,
err
return
tokens
,
err
}
}
func
SearchUserTokens
(
userId
int
,
keyword
string
)
(
tokens
[]
*
Token
,
err
error
)
{
func
SearchUserTokens
(
userId
int
,
keyword
string
,
token
string
)
(
tokens
[]
*
Token
,
err
error
)
{
err
=
DB
.
Where
(
"user_id = ?"
,
userId
)
.
Where
(
"name LIKE ?"
,
keyword
+
"%"
)
.
Find
(
&
tokens
)
.
Error
if
token
!=
""
{
token
=
strings
.
Trim
(
token
,
"sk-"
)
}
err
=
DB
.
Where
(
"user_id = ?"
,
userId
)
.
Where
(
"name LIKE ? or key LIKE ?"
,
keyword
+
"%"
,
token
+
"%"
)
.
Find
(
&
tokens
)
.
Error
return
tokens
,
err
return
tokens
,
err
}
}
...
...
web/src/components/RedemptionsTable.js
View file @
4c1a23d6
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
Form
,
Label
,
Popup
,
Pagination
}
from
'semantic-ui-react'
;
import
{
Link
}
from
'react-router-dom'
;
import
{
Link
}
from
'react-router-dom'
;
import
{
API
,
copy
,
showError
,
showInfo
,
showSuccess
,
showWarning
,
timestamp2string
}
from
'../helpers'
;
import
{
API
,
copy
,
showError
,
showInfo
,
showSuccess
,
showWarning
,
timestamp2string
}
from
'../helpers'
;
import
{
ITEMS_PER_PAGE
}
from
'../constants'
;
import
{
ITEMS_PER_PAGE
}
from
'../constants'
;
import
{
renderQuota
}
from
'../helpers/render'
;
import
{
renderQuota
}
from
'../helpers/render'
;
import
{
Button
,
Modal
,
Popconfirm
,
Popover
,
Table
,
Tag
}
from
"@douyinfe/semi-ui"
;
import
{
Button
,
Modal
,
Popconfirm
,
Popover
,
Table
,
Tag
,
Form
}
from
"@douyinfe/semi-ui"
;
import
EditRedemption
from
"../pages/Redemption/EditRedemption"
;
import
editRedemption
from
"../pages/Redemption/EditRedemption"
;
function
renderTimestamp
(
timestamp
)
{
function
renderTimestamp
(
timestamp
)
{
return
(
return
(
...
@@ -73,6 +74,17 @@ const RedemptionsTable = () => {
...
@@ -73,6 +74,17 @@ const RedemptionsTable = () => {
},
},
},
},
{
{
title
:
'兑换人ID'
,
dataIndex
:
'used_user_id'
,
render
:
(
text
,
record
,
index
)
=>
{
return
(
<
div
>
{
text
===
0
?
'无'
:
text
}
<
/div
>
);
},
},
{
title
:
''
,
title
:
''
,
dataIndex
:
'operate'
,
dataIndex
:
'operate'
,
render
:
(
text
,
record
,
index
)
=>
(
render
:
(
text
,
record
,
index
)
=>
(
...
@@ -125,14 +137,14 @@ const RedemptionsTable = () => {
...
@@ -125,14 +137,14 @@ const RedemptionsTable = () => {
record
record
);
);
}
}
}
disabled
=
{
record
.
status
===
3
}
>
启用
<
/Button
>
}
disabled
=
{
record
.
status
===
3
}
>
启用
<
/Button
>
}
<
Button
theme
=
'light'
type
=
'tertiary'
style
=
{{
marginRight
:
1
}}
onClick
=
{
()
=>
{
setEditingRedemption
(
record
);
setShowEdit
(
true
);
}
}
{
/*<Button theme='light' type='tertiary' style={{marginRight: 1}} onClick={*/
}
}
disabled
=
{
record
.
status
!==
1
}
>
编辑
<
/Button
>
{
/* () => {*/
}
{
/* setEditingToken(record);*/
}
{
/* setShowEdit(true);*/
}
{
/* }*/
}
{
/*}>编辑</Button>*/
}
<
/div
>
<
/div
>
),
),
},
},
...
@@ -145,10 +157,18 @@ const RedemptionsTable = () => {
...
@@ -145,10 +157,18 @@ const RedemptionsTable = () => {
const
[
searching
,
setSearching
]
=
useState
(
false
);
const
[
searching
,
setSearching
]
=
useState
(
false
);
const
[
tokenCount
,
setTokenCount
]
=
useState
(
ITEMS_PER_PAGE
);
const
[
tokenCount
,
setTokenCount
]
=
useState
(
ITEMS_PER_PAGE
);
const
[
selectedKeys
,
setSelectedKeys
]
=
useState
([]);
const
[
selectedKeys
,
setSelectedKeys
]
=
useState
([]);
const
[
editingRedemption
,
setEditingRedemption
]
=
useState
({
id
:
undefined
,
});
const
[
showEdit
,
setShowEdit
]
=
useState
(
false
);
const
closeEdit
=
()
=>
{
setShowEdit
(
false
);
}
const
loadRedemptions
=
async
(
startIdx
)
=>
{
const
loadRedemptions
=
async
(
startIdx
)
=>
{
const
res
=
await
API
.
get
(
`/api/redemption/?p=
${
startIdx
}
`
);
const
res
=
await
API
.
get
(
`/api/redemption/?p=
${
startIdx
}
`
);
const
{
success
,
message
,
data
}
=
res
.
data
;
const
{
success
,
message
,
data
}
=
res
.
data
;
if
(
success
)
{
if
(
success
)
{
if
(
startIdx
===
0
)
{
if
(
startIdx
===
0
)
{
setRedemptions
(
data
);
setRedemptions
(
data
);
...
@@ -180,11 +200,11 @@ const RedemptionsTable = () => {
...
@@ -180,11 +200,11 @@ const RedemptionsTable = () => {
showSuccess
(
'已复制到剪贴板!'
);
showSuccess
(
'已复制到剪贴板!'
);
}
else
{
}
else
{
// setSearchKeyword(text);
// setSearchKeyword(text);
Modal
.
error
({
title
:
'无法复制到剪贴板,请手动复制'
,
content
:
text
});
Modal
.
error
({
title
:
'无法复制到剪贴板,请手动复制'
,
content
:
text
});
}
}
}
}
const
onPaginationChange
=
(
e
,
{
activePage
})
=>
{
const
onPaginationChange
=
(
e
,
{
activePage
})
=>
{
(
async
()
=>
{
(
async
()
=>
{
if
(
activePage
===
Math
.
ceil
(
redemptions
.
length
/
ITEMS_PER_PAGE
)
+
1
)
{
if
(
activePage
===
Math
.
ceil
(
redemptions
.
length
/
ITEMS_PER_PAGE
)
+
1
)
{
// In this case we have to load more data and then append them.
// In this case we have to load more data and then append them.
...
@@ -202,8 +222,12 @@ const RedemptionsTable = () => {
...
@@ -202,8 +222,12 @@ const RedemptionsTable = () => {
});
});
},
[]);
},
[]);
const
refresh
=
async
()
=>
{
await
loadRedemptions
(
activePage
-
1
);
};
const
manageRedemption
=
async
(
id
,
action
,
record
)
=>
{
const
manageRedemption
=
async
(
id
,
action
,
record
)
=>
{
let
data
=
{
id
};
let
data
=
{
id
};
let
res
;
let
res
;
switch
(
action
)
{
switch
(
action
)
{
case
'delete'
:
case
'delete'
:
...
@@ -218,7 +242,7 @@ const RedemptionsTable = () => {
...
@@ -218,7 +242,7 @@ const RedemptionsTable = () => {
res
=
await
API
.
put
(
'/api/redemption/?status_only=true'
,
data
);
res
=
await
API
.
put
(
'/api/redemption/?status_only=true'
,
data
);
break
;
break
;
}
}
const
{
success
,
message
}
=
res
.
data
;
const
{
success
,
message
}
=
res
.
data
;
if
(
success
)
{
if
(
success
)
{
showSuccess
(
'操作成功完成!'
);
showSuccess
(
'操作成功完成!'
);
let
redemption
=
res
.
data
.
data
;
let
redemption
=
res
.
data
.
data
;
...
@@ -244,7 +268,7 @@ const RedemptionsTable = () => {
...
@@ -244,7 +268,7 @@ const RedemptionsTable = () => {
}
}
setSearching
(
true
);
setSearching
(
true
);
const
res
=
await
API
.
get
(
`/api/redemption/search?keyword=
${
searchKeyword
}
`
);
const
res
=
await
API
.
get
(
`/api/redemption/search?keyword=
${
searchKeyword
}
`
);
const
{
success
,
message
,
data
}
=
res
.
data
;
const
{
success
,
message
,
data
}
=
res
.
data
;
if
(
success
)
{
if
(
success
)
{
setRedemptions
(
data
);
setRedemptions
(
data
);
setActivePage
(
1
);
setActivePage
(
1
);
...
@@ -254,7 +278,7 @@ const RedemptionsTable = () => {
...
@@ -254,7 +278,7 @@ const RedemptionsTable = () => {
setSearching
(
false
);
setSearching
(
false
);
};
};
const
handleKeywordChange
=
async
(
e
,
{
value
}
)
=>
{
const
handleKeywordChange
=
async
(
value
)
=>
{
setSearchKeyword
(
value
.
trim
());
setSearchKeyword
(
value
.
trim
());
};
};
...
@@ -276,7 +300,8 @@ const RedemptionsTable = () => {
...
@@ -276,7 +300,8 @@ const RedemptionsTable = () => {
setActivePage
(
page
);
setActivePage
(
page
);
if
(
page
===
Math
.
ceil
(
redemptions
.
length
/
ITEMS_PER_PAGE
)
+
1
)
{
if
(
page
===
Math
.
ceil
(
redemptions
.
length
/
ITEMS_PER_PAGE
)
+
1
)
{
// In this case we have to load more data and then append them.
// In this case we have to load more data and then append them.
loadRedemptions
(
page
-
1
).
then
(
r
=>
{});
loadRedemptions
(
page
-
1
).
then
(
r
=>
{
});
}
}
};
};
...
@@ -293,12 +318,15 @@ const RedemptionsTable = () => {
...
@@ -293,12 +318,15 @@ const RedemptionsTable = () => {
return
(
return
(
<>
<>
<
EditRedemption
refresh
=
{
refresh
}
editingRedemption
=
{
editingRedemption
}
visiable
=
{
showEdit
}
handleClose
=
{
closeEdit
}
><
/EditRedemption
>
<
Form
onSubmit
=
{
searchRedemptions
}
>
<
Form
onSubmit
=
{
searchRedemptions
}
>
<
Form
.
Input
<
Form
.
Input
label
=
'搜索关键字'
field
=
'keyword'
icon
=
'search'
icon
=
'search'
fluid
iconPosition
=
'left'
iconPosition
=
'left'
placeholder
=
'搜索兑换码的 ID 和名称 ...
'
placeholder
=
'关键字(id或者名称)
'
value
=
{
searchKeyword
}
value
=
{
searchKeyword
}
loading
=
{
searching
}
loading
=
{
searching
}
onChange
=
{
handleKeywordChange
}
onChange
=
{
handleKeywordChange
}
...
@@ -319,6 +347,27 @@ const RedemptionsTable = () => {
...
@@ -319,6 +347,27 @@ const RedemptionsTable = () => {
onPageChange
:
handlePageChange
,
onPageChange
:
handlePageChange
,
}}
loading
=
{
loading
}
rowSelection
=
{
rowSelection
}
>
}}
loading
=
{
loading
}
rowSelection
=
{
rowSelection
}
>
<
/Table
>
<
/Table
>
<
Button
theme
=
'light'
type
=
'primary'
style
=
{{
marginRight
:
8
}}
onClick
=
{
()
=>
{
setEditingRedemption
({
id
:
undefined
,
});
setShowEdit
(
true
);
}
}
>
添加兑换码
<
/Button
>
<
Button
label
=
'复制所选兑换码'
type
=
"warning"
onClick
=
{
async
()
=>
{
if
(
selectedKeys
.
length
===
0
)
{
showError
(
'请至少选择一个兑换码!'
);
return
;
}
let
keys
=
""
;
for
(
let
i
=
0
;
i
<
selectedKeys
.
length
;
i
++
)
{
keys
+=
selectedKeys
[
i
].
name
+
" sk-"
+
selectedKeys
[
i
].
key
+
"\n"
;
}
await
copyText
(
keys
);
}
}
>
复制所选兑换码到剪贴板
<
/Button
>
<
/
>
<
/
>
);
);
};
};
...
...
web/src/components/TokensTable.js
View file @
4c1a23d6
...
@@ -179,6 +179,7 @@ const TokensTable = () => {
...
@@ -179,6 +179,7 @@ const TokensTable = () => {
const
[
loading
,
setLoading
]
=
useState
(
true
);
const
[
loading
,
setLoading
]
=
useState
(
true
);
const
[
activePage
,
setActivePage
]
=
useState
(
1
);
const
[
activePage
,
setActivePage
]
=
useState
(
1
);
const
[
searchKeyword
,
setSearchKeyword
]
=
useState
(
''
);
const
[
searchKeyword
,
setSearchKeyword
]
=
useState
(
''
);
const
[
searchToken
,
setSearchToken
]
=
useState
(
''
);
const
[
searching
,
setSearching
]
=
useState
(
false
);
const
[
searching
,
setSearching
]
=
useState
(
false
);
const
[
showTopUpModal
,
setShowTopUpModal
]
=
useState
(
false
);
const
[
showTopUpModal
,
setShowTopUpModal
]
=
useState
(
false
);
const
[
targetTokenIdx
,
setTargetTokenIdx
]
=
useState
(
0
);
const
[
targetTokenIdx
,
setTargetTokenIdx
]
=
useState
(
0
);
...
@@ -188,9 +189,6 @@ const TokensTable = () => {
...
@@ -188,9 +189,6 @@ const TokensTable = () => {
const
closeEdit
=
()
=>
{
const
closeEdit
=
()
=>
{
setShowEdit
(
false
);
setShowEdit
(
false
);
// setEditingToken({
// id: undefined,
// });
}
}
const
setTokensFormat
=
(
tokens
)
=>
{
const
setTokensFormat
=
(
tokens
)
=>
{
...
@@ -401,6 +399,10 @@ const TokensTable = () => {
...
@@ -401,6 +399,10 @@ const TokensTable = () => {
setSearchKeyword
(
value
.
trim
());
setSearchKeyword
(
value
.
trim
());
};
};
const
handleSearchTokenChange
=
async
(
value
)
=>
{
setSearchToken
(
value
.
trim
());
};
const
sortToken
=
(
key
)
=>
{
const
sortToken
=
(
key
)
=>
{
if
(
tokens
.
length
===
0
)
return
;
if
(
tokens
.
length
===
0
)
return
;
setLoading
(
true
);
setLoading
(
true
);
...
@@ -447,6 +449,14 @@ const TokensTable = () => {
...
@@ -447,6 +449,14 @@ const TokensTable = () => {
loading
=
{
searching
}
loading
=
{
searching
}
onChange
=
{
handleKeywordChange
}
onChange
=
{
handleKeywordChange
}
/
>
/
>
<
Form
.
Input
field
=
"token"
label
=
'Key'
placeholder
=
'密钥'
value
=
{
searchToken
}
loading
=
{
searching
}
onChange
=
{
handleSearchTokenChange
}
/
>
<
Button
label
=
'查询'
type
=
"primary"
htmlType
=
"submit"
className
=
"btn-margin-right"
<
Button
label
=
'查询'
type
=
"primary"
htmlType
=
"submit"
className
=
"btn-margin-right"
onClick
=
{
searchTokens
}
style
=
{{
marginRight
:
8
}}
>
查询
<
/Button
>
onClick
=
{
searchTokens
}
style
=
{{
marginRight
:
8
}}
>
查询
<
/Button
>
<
/Form
>
<
/Form
>
...
...
web/src/pages/Redemption/EditRedemption.js
View file @
4c1a23d6
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
Button
,
Form
,
Header
,
Segment
}
from
'semantic-ui-react'
;
import
{
useParams
,
useNavigate
}
from
'react-router-dom'
;
import
{
useParams
,
useNavigate
}
from
'react-router-dom'
;
import
{
API
,
downloadTextAsFile
,
showError
,
showSuccess
}
from
'../../helpers'
;
import
{
API
,
downloadTextAsFile
,
isMobile
,
showError
,
showSuccess
}
from
'../../helpers'
;
import
{
renderQuota
,
renderQuotaWithPrompt
}
from
'../../helpers/render'
;
import
{
renderQuota
,
renderQuotaWithPrompt
}
from
'../../helpers/render'
;
import
{
SideSheet
,
Space
,
Spin
,
Button
,
Input
,
Typography
,
AutoComplete
,
Modal
}
from
"@douyinfe/semi-ui"
;
import
Title
from
"@douyinfe/semi-ui/lib/es/typography/title"
;
import
{
Divider
}
from
"semantic-ui-react"
;
const
EditRedemption
=
()
=>
{
const
EditRedemption
=
(
props
)
=>
{
const
params
=
useParams
();
const
isEdit
=
props
.
editingRedemption
.
id
!==
undefined
;
const
navigate
=
useNavigate
();
const
redemptionId
=
params
.
id
;
const
isEdit
=
redemptionId
!==
undefined
;
const
[
loading
,
setLoading
]
=
useState
(
isEdit
);
const
[
loading
,
setLoading
]
=
useState
(
isEdit
);
const
params
=
useParams
();
const
navigate
=
useNavigate
()
const
originInputs
=
{
const
originInputs
=
{
name
:
''
,
name
:
''
,
quota
:
100000
,
quota
:
100000
,
...
@@ -19,15 +21,16 @@ const EditRedemption = () => {
...
@@ -19,15 +21,16 @@ const EditRedemption = () => {
const
{
name
,
quota
,
count
}
=
inputs
;
const
{
name
,
quota
,
count
}
=
inputs
;
const
handleCancel
=
()
=>
{
const
handleCancel
=
()
=>
{
navigate
(
'/redemption'
);
props
.
handleClose
(
);
}
;
}
const
handleInputChange
=
(
e
,
{
name
,
value
}
)
=>
{
const
handleInputChange
=
(
name
,
value
)
=>
{
setInputs
((
inputs
)
=>
({
...
inputs
,
[
name
]:
value
}));
setInputs
((
inputs
)
=>
({
...
inputs
,
[
name
]:
value
}));
};
};
const
loadRedemption
=
async
()
=>
{
const
loadRedemption
=
async
()
=>
{
let
res
=
await
API
.
get
(
`/api/redemption/
${
redemptionId
}
`
);
setLoading
(
true
);
let
res
=
await
API
.
get
(
`/api/redemption/
${
props
.
editingRedemption
.
id
}
`
);
const
{
success
,
message
,
data
}
=
res
.
data
;
const
{
success
,
message
,
data
}
=
res
.
data
;
if
(
success
)
{
if
(
success
)
{
setInputs
(
data
);
setInputs
(
data
);
...
@@ -36,20 +39,28 @@ const EditRedemption = () => {
...
@@ -36,20 +39,28 @@ const EditRedemption = () => {
}
}
setLoading
(
false
);
setLoading
(
false
);
};
};
useEffect
(()
=>
{
useEffect
(()
=>
{
if
(
isEdit
)
{
if
(
isEdit
)
{
loadRedemption
().
then
();
loadRedemption
().
then
(
()
=>
{
// console.log(inputs);
}
);
}
else
{
setInputs
(
originInputs
);
}
}
},
[]);
},
[
props
.
editingRedemption
.
id
]);
const
submit
=
async
()
=>
{
const
submit
=
async
()
=>
{
if
(
!
isEdit
&&
inputs
.
name
===
''
)
return
;
if
(
!
isEdit
&&
inputs
.
name
===
''
)
return
;
setLoading
(
true
);
let
localInputs
=
inputs
;
let
localInputs
=
inputs
;
localInputs
.
count
=
parseInt
(
localInputs
.
count
);
localInputs
.
count
=
parseInt
(
localInputs
.
count
);
localInputs
.
quota
=
parseInt
(
localInputs
.
quota
);
localInputs
.
quota
=
parseInt
(
localInputs
.
quota
);
let
res
;
let
res
;
if
(
isEdit
)
{
if
(
isEdit
)
{
res
=
await
API
.
put
(
`/api/redemption/`
,
{
...
localInputs
,
id
:
parseInt
(
redemptionI
d
)
});
res
=
await
API
.
put
(
`/api/redemption/`
,
{
...
localInputs
,
id
:
parseInt
(
props
.
editingRedemption
.
i
d
)
});
}
else
{
}
else
{
res
=
await
API
.
post
(
`/api/redemption/`
,
{
res
=
await
API
.
post
(
`/api/redemption/`
,
{
...
localInputs
...
localInputs
...
@@ -59,9 +70,13 @@ const EditRedemption = () => {
...
@@ -59,9 +70,13 @@ const EditRedemption = () => {
if
(
success
)
{
if
(
success
)
{
if
(
isEdit
)
{
if
(
isEdit
)
{
showSuccess
(
'兑换码更新成功!'
);
showSuccess
(
'兑换码更新成功!'
);
props
.
refresh
();
props
.
handleClose
();
}
else
{
}
else
{
showSuccess
(
'兑换码创建成功!'
);
showSuccess
(
'兑换码创建成功!'
);
setInputs
(
originInputs
);
setInputs
(
originInputs
);
props
.
refresh
();
props
.
handleClose
();
}
}
}
else
{
}
else
{
showError
(
message
);
showError
(
message
);
...
@@ -71,56 +86,94 @@ const EditRedemption = () => {
...
@@ -71,56 +86,94 @@ const EditRedemption = () => {
for
(
let
i
=
0
;
i
<
data
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
data
.
length
;
i
++
)
{
text
+=
data
[
i
]
+
"\n"
;
text
+=
data
[
i
]
+
"\n"
;
}
}
// downloadTextAsFile(text, `${inputs.name}.txt`);
Modal
.
confirm
({
title
:
'兑换码创建成功'
,
content
:
(
<
div
>
<
p
>
兑换码创建成功,是否下载兑换码?
<
/p
>
<
p
>
兑换码将以文本文件的形式下载,文件名为兑换码的名称。
<
/p
>
<
/div
>
),
onOk
:
()
=>
{
downloadTextAsFile
(
text
,
`
${
inputs
.
name
}
.txt`
);
downloadTextAsFile
(
text
,
`
${
inputs
.
name
}
.txt`
);
}
}
});
}
setLoading
(
false
);
};
};
return
(
return
(
<>
<>
<
Segment
loading
=
{
loading
}
>
<
SideSheet
<
Header
as
=
'h3'
>
{
isEdit
?
'更新兑换码信息'
:
'创建新的兑换码'
}
<
/Header
>
placement
=
{
isEdit
?
'right'
:
'left'
}
<
Form
autoComplete
=
'new-password'
>
title
=
{
<
Title
level
=
{
3
}
>
{
isEdit
?
'更新兑换码信息'
:
'创建新的兑换码'
}
<
/Title>
}
<
Form
.
Field
>
headerStyle
=
{{
borderBottom
:
'1px solid var(--semi-color-border)'
}}
<
Form
.
Input
bodyStyle
=
{{
borderBottom
:
'1px solid var(--semi-color-border)'
}}
visible
=
{
props
.
visiable
}
footer
=
{
<
div
style
=
{{
display
:
'flex'
,
justifyContent
:
'flex-end'
}}
>
<
Space
>
<
Button
theme
=
'solid'
size
=
{
'large'
}
onClick
=
{
submit
}
>
提交
<
/Button
>
<
Button
theme
=
'solid'
size
=
{
'large'
}
type
=
{
'tertiary'
}
onClick
=
{
handleCancel
}
>
取消
<
/Button
>
<
/Space
>
<
/div
>
}
closeIcon
=
{
null
}
onCancel
=
{()
=>
handleCancel
()}
width
=
{
isMobile
()
?
'100%'
:
600
}
>
<
Spin
spinning
=
{
loading
}
>
<
Input
style
=
{{
marginTop
:
20
}}
label
=
'名称'
label
=
'名称'
name
=
'name'
name
=
'name'
placeholder
=
{
'请输入名称'
}
placeholder
=
{
'请输入名称'
}
onChange
=
{
handleInputChange
}
onChange
=
{
value
=>
handleInputChange
(
'name'
,
value
)
}
value
=
{
name
}
value
=
{
name
}
autoComplete
=
'new-password'
autoComplete
=
'new-password'
required
=
{
!
isEdit
}
required
=
{
!
isEdit
}
/
>
/
>
<
/Form.Field
>
<
Divider
/>
<
Form
.
Field
>
<
div
style
=
{{
marginTop
:
20
}}
>
<
Form
.
Input
<
Typography
.
Text
>
{
`额度
${
renderQuotaWithPrompt
(
quota
)}
`
}
<
/Typography.Text
>
label
=
{
`额度
${
renderQuotaWithPrompt
(
quota
)}
`
}
<
/div
>
<
AutoComplete
style
=
{{
marginTop
:
8
}}
name
=
'quota'
name
=
'quota'
placeholder
=
{
'请输入
单个兑换码中包含的
额度'
}
placeholder
=
{
'请输入额度'
}
onChange
=
{
handleInputChange
}
onChange
=
{
(
value
)
=>
handleInputChange
(
'quota'
,
value
)
}
value
=
{
quota
}
value
=
{
quota
}
autoComplete
=
'new-password'
autoComplete
=
'new-password'
type
=
'number'
type
=
'number'
position
=
{
'bottom'
}
data
=
{[
{
value
:
500000
,
label
:
'1$'
},
{
value
:
5000000
,
label
:
'10$'
},
{
value
:
25000000
,
label
:
'50$'
},
{
value
:
50000000
,
label
:
'100$'
},
{
value
:
250000000
,
label
:
'500$'
},
{
value
:
500000000
,
label
:
'1000$'
},
]}
/
>
/
>
<
/Form.Field
>
{
{
!
isEdit
&&
<>
!
isEdit
&&
<>
<
Form
.
Field
>
<
Divider
/>
<
Form
.
Input
<
Typography
.
Text
>
生成数量
<
/Typography.Text
>
<
Input
style
=
{{
marginTop
:
8
}}
label
=
'生成数量'
label
=
'生成数量'
name
=
'count'
name
=
'count'
placeholder
=
{
'请输入生成数量'
}
placeholder
=
{
'请输入生成数量'
}
onChange
=
{
handleInputChange
}
onChange
=
{
value
=>
handleInputChange
(
'count'
,
value
)
}
value
=
{
count
}
value
=
{
count
}
autoComplete
=
'new-password'
autoComplete
=
'new-password'
type
=
'number'
type
=
'number'
/>
/>
<
/Form.Field
>
<
/
>
<
/
>
}
}
<
Button
positive
onClick
=
{
submit
}
>
提交
<
/Button
>
<
/Spin
>
<
Button
onClick
=
{
handleCancel
}
>
取消
<
/Button
>
<
/SideSheet
>
<
/Form
>
<
/Segment
>
<
/
>
<
/
>
);
);
};
};
...
...
web/src/pages/Redemption/index.js
View file @
4c1a23d6
import
React
from
'react'
;
import
React
from
'react'
;
import
{
Segment
,
Header
}
from
'semantic-ui-react'
;
import
{
Segment
,
Header
}
from
'semantic-ui-react'
;
import
RedemptionsTable
from
'../../components/RedemptionsTable'
;
import
RedemptionsTable
from
'../../components/RedemptionsTable'
;
import
TokensTable
from
"../../components/TokensTable"
;
import
{
Layout
}
from
"@douyinfe/semi-ui"
;
const
Redemption
=
()
=>
(
const
Redemption
=
()
=>
(
<>
<>
<
Segment
>
<
Layout
>
<
Header
as
=
'h3'
>
管理兑换码
<
/Header
>
<
Layout
.
Header
>
<
h3
>
管理兑换码
<
/h3
>
<
/Layout.Header
>
<
Layout
.
Content
>
<
RedemptionsTable
/>
<
RedemptionsTable
/>
<
/Segment
>
<
/Layout.Content
>
<
/Layout
>
<
/
>
<
/
>
);
);
...
...
web/src/pages/Token/EditToken.js
View file @
4c1a23d6
...
@@ -63,7 +63,7 @@ const EditToken = (props) => {
...
@@ -63,7 +63,7 @@ const EditToken = (props) => {
if
(
isEdit
)
{
if
(
isEdit
)
{
loadToken
().
then
(
loadToken
().
then
(
()
=>
{
()
=>
{
console
.
log
(
inputs
);
//
console.log(inputs);
}
}
);
);
}
else
{
}
else
{
...
@@ -72,8 +72,8 @@ const EditToken = (props) => {
...
@@ -72,8 +72,8 @@ const EditToken = (props) => {
},
[
props
.
editingToken
.
id
]);
},
[
props
.
editingToken
.
id
]);
const
submit
=
async
()
=>
{
const
submit
=
async
()
=>
{
setLoading
(
true
);
if
(
!
isEdit
&&
inputs
.
name
===
''
)
return
;
if
(
!
isEdit
&&
inputs
.
name
===
''
)
return
;
setLoading
(
true
);
let
localInputs
=
inputs
;
let
localInputs
=
inputs
;
localInputs
.
remain_quota
=
parseInt
(
localInputs
.
remain_quota
);
localInputs
.
remain_quota
=
parseInt
(
localInputs
.
remain_quota
);
if
(
localInputs
.
expired_time
!==
-
1
)
{
if
(
localInputs
.
expired_time
!==
-
1
)
{
...
...
web/src/pages/Token/index.js
View file @
4c1a23d6
import
React
from
'react'
;
import
React
from
'react'
;
import
TokensTable
from
'../../components/TokensTable'
;
import
TokensTable
from
'../../components/TokensTable'
;
import
{
Layout
}
from
"@douyinfe/semi-ui"
;
import
{
Layout
}
from
"@douyinfe/semi-ui"
;
const
{
Content
,
Header
}
=
Layout
;
const
Token
=
()
=>
(
const
Token
=
()
=>
(
<>
<>
<
Layout
>
<
Layout
>
<
Header
>
<
Layout
.
Header
>
<
h3
>
我的令牌
<
/h3
>
<
h3
>
我的令牌
<
/h3
>
<
/Header
>
<
/
Layout.
Header
>
<
Content
>
<
Layout
.
Content
>
<
TokensTable
/>
<
TokensTable
/>
<
/Content
>
<
/
Layout.
Content
>
<
/Layout
>
<
/Layout
>
<
/
>
<
/
>
);
);
...
...
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