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
40c626cb
authored
Nov 01, 2023
by
CaIon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
完善令牌界面
parent
607358c9
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
229 additions
and
163 deletions
+229
-163
web/src/components/TokensTable.js
+34
-8
web/src/pages/Token/EditToken.js
+195
-155
No files found.
web/src/components/TokensTable.js
View file @
40c626cb
...
...
@@ -5,6 +5,7 @@ import {API, copy, isAdmin, showError, showSuccess, showWarning, timestamp2strin
import
{
ITEMS_PER_PAGE
}
from
'../constants'
;
import
{
renderQuota
,
stringToColor
}
from
'../helpers/render'
;
import
{
Avatar
,
Tag
,
Table
,
Button
,
Popover
,
Form
,
Modal
,
Popconfirm
}
from
"@douyinfe/semi-ui"
;
import
EditToken
from
"../pages/Token/EditToken"
;
const
{
Column
}
=
Table
;
...
...
@@ -77,7 +78,7 @@ const TokensTable = () => {
render
:
(
text
,
record
,
index
)
=>
{
return
(
<
div
>
{
re
nderQuota
(
parseInt
(
text
))
}
{
re
cord
.
unlimited_quota
?
<
Tag
size
=
{
'large'
}
color
=
{
'white'
}
>
无限制
<
/Tag> : <Tag size={'large'} color={'light-blue'}>{renderQuota
(
parseInt
(
text
))
}</
Tag
>
}
<
/div
>
);
},
...
...
@@ -95,11 +96,11 @@ const TokensTable = () => {
},
{
title
:
'过期时间'
,
dataIndex
:
'
access
ed_time'
,
dataIndex
:
'
expir
ed_time'
,
render
:
(
text
,
record
,
index
)
=>
{
return
(
<
div
>
{
renderTimestamp
(
text
)}
{
re
cord
.
expired_time
===
-
1
?
"永不过期"
:
re
nderTimestamp
(
text
)}
<
/div
>
);
},
...
...
@@ -159,12 +160,18 @@ const TokensTable = () => {
}
}
>
启用
<
/Button
>
}
<
Button
theme
=
'light'
type
=
'tertiary'
style
=
{{
marginRight
:
1
}}
>
编辑
<
/Button
>
<
Button
theme
=
'light'
type
=
'tertiary'
style
=
{{
marginRight
:
1
}}
onClick
=
{
()
=>
{
setEditingToken
(
record
);
setShowEdit
(
true
);
}
}
>
编辑
<
/Button
>
<
/div
>
),
},
];
const
[
showEdit
,
setShowEdit
]
=
useState
(
false
);
const
[
tokens
,
setTokens
]
=
useState
([]);
const
[
selectedKeys
,
setSelectedKeys
]
=
useState
([]);
const
[
tokenCount
,
setTokenCount
]
=
useState
(
ITEMS_PER_PAGE
);
...
...
@@ -174,6 +181,16 @@ const TokensTable = () => {
const
[
searching
,
setSearching
]
=
useState
(
false
);
const
[
showTopUpModal
,
setShowTopUpModal
]
=
useState
(
false
);
const
[
targetTokenIdx
,
setTargetTokenIdx
]
=
useState
(
0
);
const
[
editingToken
,
setEditingToken
]
=
useState
({
id
:
undefined
,
});
const
closeEdit
=
()
=>
{
setShowEdit
(
false
);
setEditingToken
({
id
:
undefined
,
});
}
const
setTokensFormat
=
(
tokens
)
=>
{
setTokens
(
tokens
);
...
...
@@ -409,19 +426,17 @@ const TokensTable = () => {
const
rowSelection
=
{
onSelect
:
(
record
,
selected
)
=>
{
// console.log(`select row: ${selected}`, record);
},
onSelectAll
:
(
selected
,
selectedRows
)
=>
{
// console.log(`select all rows: ${selected}`, selectedRows);
},
onChange
:
(
selectedRowKeys
,
selectedRows
)
=>
{
// console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
setSelectedKeys
(
selectedRows
);
},
};
return
(
<>
<
EditToken
refresh
=
{
refresh
}
editingToken
=
{
editingToken
}
visiable
=
{
showEdit
}
handleClose
=
{
closeEdit
}
><
/EditToken
>
<
Form
layout
=
'horizontal'
style
=
{{
marginTop
:
10
}}
labelPosition
=
{
'left'
}
>
<
Form
.
Input
field
=
"keyword"
...
...
@@ -443,9 +458,20 @@ const TokensTable = () => {
onPageChange
:
handlePageChange
,
}}
loading
=
{
loading
}
rowSelection
=
{
rowSelection
}
>
<
/Table
>
<
Button
theme
=
'light'
type
=
'primary'
style
=
{{
marginRight
:
8
}}
>
添加令牌
<
/Button
>
<
Button
theme
=
'light'
type
=
'primary'
style
=
{{
marginRight
:
8
}}
onClick
=
{
()
=>
{
setEditingToken
({
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"
;
...
...
web/src/pages/Token/EditToken.js
View file @
40c626cb
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
Button
,
Form
,
Header
,
Message
,
Segment
}
from
'semantic-ui-react'
;
import
{
useParams
,
useNavigate
}
from
'react-router-dom'
;
import
{
API
,
showError
,
showSuccess
,
timestamp2string
}
from
'../../helpers'
;
import
{
renderQuota
,
renderQuotaWithPrompt
}
from
'../../helpers/render'
;
import
React
,
{
useEffect
,
useRef
,
useState
}
from
'react'
;
// import {Button, Form, Header, Message, Segment} from 'semantic-ui-react';
import
{
useParams
,
useNavigate
}
from
'react-router-dom'
;
import
{
API
,
isMobile
,
showError
,
showSuccess
,
timestamp2string
}
from
'../../helpers'
;
import
{
renderQuota
,
renderQuotaWithPrompt
}
from
'../../helpers/render'
;
import
{
Layout
,
SideSheet
,
Button
,
Space
,
Spin
,
Banner
,
Input
,
DatePicker
,
AutoComplete
,
Typography
}
from
"@douyinfe/semi-ui"
;
import
Title
from
"@douyinfe/semi-ui/lib/es/typography/title"
;
import
{
Divider
}
from
"semantic-ui-react"
;
const
EditToken
=
()
=>
{
const
params
=
useParams
();
const
tokenId
=
params
.
id
;
const
isEdit
=
tokenId
!==
undefined
;
const
[
loading
,
setLoading
]
=
useState
(
isEdit
);
const
originInputs
=
{
name
:
''
,
remain_quota
:
isEdit
?
0
:
500000
,
expired_time
:
-
1
,
unlimited_quota
:
false
};
const
[
inputs
,
setInputs
]
=
useState
(
originInputs
);
const
{
name
,
remain_quota
,
expired_time
,
unlimited_quota
}
=
inputs
;
const
navigate
=
useNavigate
();
const
handleInputChange
=
(
e
,
{
name
,
value
})
=>
{
setInputs
((
inputs
)
=>
({
...
inputs
,
[
name
]:
value
}));
};
const
handleCancel
=
()
=>
{
navigate
(
"/token"
);
}
const
setExpiredTime
=
(
month
,
day
,
hour
,
minute
)
=>
{
let
now
=
new
Date
();
let
timestamp
=
now
.
getTime
()
/
1000
;
let
seconds
=
month
*
30
*
24
*
60
*
60
;
seconds
+=
day
*
24
*
60
*
60
;
seconds
+=
hour
*
60
*
60
;
seconds
+=
minute
*
60
;
if
(
seconds
!==
0
)
{
timestamp
+=
seconds
;
setInputs
({
...
inputs
,
expired_time
:
timestamp2string
(
timestamp
)
});
}
else
{
setInputs
({
...
inputs
,
expired_time
:
-
1
});
const
EditToken
=
(
props
)
=>
{
const
isEdit
=
props
.
editingToken
.
id
!==
undefined
;
const
[
loading
,
setLoading
]
=
useState
(
isEdit
);
const
originInputs
=
{
name
:
''
,
remain_quota
:
isEdit
?
0
:
500000
,
expired_time
:
-
1
,
unlimited_quota
:
false
};
const
[
inputs
,
setInputs
]
=
useState
(
originInputs
);
const
{
name
,
remain_quota
,
expired_time
,
unlimited_quota
}
=
inputs
;
// const [visible, setVisible] = useState(false);
const
navigate
=
useNavigate
();
const
handleInputChange
=
(
name
,
value
)
=>
{
setInputs
((
inputs
)
=>
({...
inputs
,
[
name
]:
value
}));
};
const
handleCancel
=
()
=>
{
props
.
handleClose
();
}
};
const
setExpiredTime
=
(
month
,
day
,
hour
,
minute
)
=>
{
let
now
=
new
Date
();
let
timestamp
=
now
.
getTime
()
/
1000
;
let
seconds
=
month
*
30
*
24
*
60
*
60
;
seconds
+=
day
*
24
*
60
*
60
;
seconds
+=
hour
*
60
*
60
;
seconds
+=
minute
*
60
;
if
(
seconds
!==
0
)
{
timestamp
+=
seconds
;
setInputs
({...
inputs
,
expired_time
:
timestamp2string
(
timestamp
)});
}
else
{
setInputs
({...
inputs
,
expired_time
:
-
1
});
}
};
const
setUnlimitedQuota
=
()
=>
{
setInputs
({
...
inputs
,
unlimited_quota
:
!
unlimited_quota
});
};
const
setUnlimitedQuota
=
()
=>
{
setInputs
({...
inputs
,
unlimited_quota
:
!
unlimited_quota
});
};
const
loadToken
=
async
()
=>
{
let
res
=
await
API
.
get
(
`/api/token/
${
tokenId
}
`
);
const
{
success
,
message
,
data
}
=
res
.
data
;
if
(
success
)
{
if
(
data
.
expired_time
!==
-
1
)
{
data
.
expired_time
=
timestamp2string
(
data
.
expired_time
);
}
setInputs
(
data
);
}
else
{
showError
(
message
);
}
setLoading
(
false
);
};
useEffect
(()
=>
{
if
(
isEdit
)
{
loadToken
().
then
();
}
},
[]);
const
loadToken
=
async
()
=>
{
setLoading
(
true
);
let
res
=
await
API
.
get
(
`/api/token/
${
props
.
editingToken
.
id
}
`
);
const
{
success
,
message
,
data
}
=
res
.
data
;
if
(
success
)
{
if
(
data
.
expired_time
!==
-
1
)
{
data
.
expired_time
=
timestamp2string
(
data
.
expired_time
);
}
setInputs
(
data
);
}
else
{
showError
(
message
);
}
setLoading
(
false
);
};
useEffect
(()
=>
{
if
(
isEdit
)
{
loadToken
().
then
(
()
=>
{
console
.
log
(
inputs
);
}
);
}
else
{
setInputs
(
originInputs
);
}
},
[
props
.
editingToken
.
id
]);
const
submit
=
async
()
=>
{
if
(
!
isEdit
&&
inputs
.
name
===
''
)
return
;
let
localInputs
=
inputs
;
localInputs
.
remain_quota
=
parseInt
(
localInputs
.
remain_quota
);
if
(
localInputs
.
expired_time
!==
-
1
)
{
let
time
=
Date
.
parse
(
localInputs
.
expired_time
);
if
(
isNaN
(
time
))
{
showError
(
'过期时间格式错误!'
);
return
;
}
localInputs
.
expired_time
=
Math
.
ceil
(
time
/
1000
);
}
let
res
;
if
(
isEdit
)
{
res
=
await
API
.
put
(
`/api/token/`
,
{
...
localInputs
,
id
:
parseInt
(
tokenId
)
});
}
else
{
res
=
await
API
.
post
(
`/api/token/`
,
localInputs
);
}
const
{
success
,
message
}
=
res
.
data
;
if
(
success
)
{
if
(
isEdit
)
{
showSuccess
(
'令牌更新成功!'
);
}
else
{
showSuccess
(
'令牌创建成功,请在列表页面点击复制获取令牌!'
);
setInputs
(
originInputs
);
}
}
else
{
showError
(
message
);
}
};
const
submit
=
async
()
=>
{
setLoading
(
true
);
if
(
!
isEdit
&&
inputs
.
name
===
''
)
return
;
let
localInputs
=
inputs
;
localInputs
.
remain_quota
=
parseInt
(
localInputs
.
remain_quota
);
if
(
localInputs
.
expired_time
!==
-
1
)
{
let
time
=
Date
.
parse
(
localInputs
.
expired_time
);
if
(
isNaN
(
time
))
{
showError
(
'过期时间格式错误!'
);
return
;
}
localInputs
.
expired_time
=
Math
.
ceil
(
time
/
1000
);
}
let
res
;
if
(
isEdit
)
{
res
=
await
API
.
put
(
`/api/token/`
,
{...
localInputs
,
id
:
parseInt
(
props
.
editingToken
.
id
)});
}
else
{
res
=
await
API
.
post
(
`/api/token/`
,
localInputs
);
}
const
{
success
,
message
}
=
res
.
data
;
if
(
success
)
{
if
(
isEdit
)
{
showSuccess
(
'令牌更新成功!'
);
props
.
refresh
();
props
.
handleClose
();
}
else
{
showSuccess
(
'令牌创建成功,请在列表页面点击复制获取令牌!'
);
setInputs
(
originInputs
);
props
.
refresh
();
props
.
handleClose
();
}
}
else
{
showError
(
message
);
}
setLoading
(
false
);
};
return
(
<>
<
SideSheet
title
=
{
<
Title
level
=
{
3
}
>
{
isEdit
?
'更新令牌信息'
:
'创建新的令牌'
}
<
/Title>
}
headerStyle
=
{{
borderBottom
:
'1px solid var(--semi-color-border)'
}}
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
=
'名称'
name
=
'name'
placeholder
=
{
'请输入名称'
}
onChange
=
{(
value
)
=>
handleInputChange
(
'name'
,
value
)}
value
=
{
name
}
autoComplete
=
'new-password'
required
=
{
!
isEdit
}
/
>
<
Divider
/>
<
DatePicker
label
=
'过期时间'
name
=
'expired_time'
placeholder
=
{
'请选择过期时间'
}
onChange
=
{(
value
)
=>
handleInputChange
(
'expired_time'
,
value
)}
value
=
{
expired_time
}
autoComplete
=
'new-password'
type
=
'dateTime'
/>
<
div
style
=
{{
marginTop
:
20
}}
>
<
Space
>
<
Button
type
=
{
'tertiary'
}
onClick
=
{()
=>
{
setExpiredTime
(
0
,
0
,
0
,
0
);
}}
>
永不过期
<
/Button
>
<
Button
type
=
{
'tertiary'
}
onClick
=
{()
=>
{
setExpiredTime
(
0
,
0
,
1
,
0
);
}}
>
一小时
<
/Button
>
<
Button
type
=
{
'tertiary'
}
onClick
=
{()
=>
{
setExpiredTime
(
1
,
0
,
0
,
0
);
}}
>
一个月
<
/Button
>
<
Button
type
=
{
'tertiary'
}
onClick
=
{()
=>
{
setExpiredTime
(
0
,
1
,
0
,
0
);
}}
>
一天
<
/Button
>
<
/Space
>
<
/div
>
return
(
<>
<
Segment
loading
=
{
loading
}
>
<
Header
as
=
'h3'
>
{
isEdit
?
'更新令牌信息'
:
'创建新的令牌'
}
<
/Header
>
<
Form
autoComplete
=
'new-password'
>
<
Form
.
Field
>
<
Form
.
Input
label
=
'名称'
name
=
'name'
placeholder
=
{
'请输入名称'
}
onChange
=
{
handleInputChange
}
value
=
{
name
}
autoComplete
=
'new-password'
required
=
{
!
isEdit
}
/
>
<
/Form.Field
>
<
Form
.
Field
>
<
Form
.
Input
label
=
'过期时间'
name
=
'expired_time'
placeholder
=
{
'请输入过期时间,格式为 yyyy-MM-dd HH:mm:ss,-1 表示无限制'
}
onChange
=
{
handleInputChange
}
value
=
{
expired_time
}
autoComplete
=
'new-password'
type
=
'datetime-local'
/>
<
/Form.Field
>
<
div
style
=
{{
lineHeight
:
'40px'
}}
>
<
Button
type
=
{
'button'
}
onClick
=
{()
=>
{
setExpiredTime
(
0
,
0
,
0
,
0
);
}}
>
永不过期
<
/Button
>
<
Button
type
=
{
'button'
}
onClick
=
{()
=>
{
setExpiredTime
(
1
,
0
,
0
,
0
);
}}
>
一个月后过期
<
/Button
>
<
Button
type
=
{
'button'
}
onClick
=
{()
=>
{
setExpiredTime
(
0
,
1
,
0
,
0
);
}}
>
一天后过期
<
/Button
>
<
Button
type
=
{
'button'
}
onClick
=
{()
=>
{
setExpiredTime
(
0
,
0
,
1
,
0
);
}}
>
一小时后过期
<
/Button
>
<
Button
type
=
{
'button'
}
onClick
=
{()
=>
{
setExpiredTime
(
0
,
0
,
0
,
1
);
}}
>
一分钟后过期
<
/Button
>
<
/div
>
<
Message
>
注意,令牌的额度仅用于限制令牌本身的最大额度使用量,实际的使用受到账户的剩余额度限制。
<
/Message
>
<
Form
.
Field
>
<
Form
.
Input
label
=
{
`额度
${
renderQuotaWithPrompt
(
remain_quota
)}
`
}
name
=
'remain_quota'
placeholder
=
{
'请输入额度'
}
onChange
=
{
handleInputChange
}
value
=
{
remain_quota
}
autoComplete
=
'new-password'
type
=
'number'
disabled
=
{
unlimited_quota
}
/
>
<
/Form.Field
>
<
Button
type
=
{
'button'
}
onClick
=
{()
=>
{
setUnlimitedQuota
();
}}
>
{
unlimited_quota
?
'取消无限额度'
:
'设为无限额度'
}
<
/Button
>
<
Button
floated
=
'right'
positive
onClick
=
{
submit
}
>
提交
<
/Button
>
<
Button
floated
=
'right'
onClick
=
{
handleCancel
}
>
取消
<
/Button
>
<
/Form
>
<
/Segment
>
<
/
>
);
<
Divider
/>
<
Banner
type
=
{
'warning'
}
description
=
{
'注意,令牌的额度仅用于限制令牌本身的最大额度使用量,实际的使用受到账户的剩余额度限制。'
}
><
/Banner
>
<
div
style
=
{{
marginTop
:
20
}}
>
<
Typography
.
Text
>
{
`额度
${
renderQuotaWithPrompt
(
remain_quota
)}
`
}
<
/Typography.Text
>
<
/div
>
<
AutoComplete
style
=
{{
marginTop
:
8
}}
name
=
'remain_quota'
placeholder
=
{
'请输入额度'
}
onChange
=
{(
value
)
=>
handleInputChange
(
'remain_quota'
,
value
)}
value
=
{
remain_quota
}
autoComplete
=
'new-password'
type
=
'number'
position
=
{
'top'
}
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$'
},
]}
disabled
=
{
unlimited_quota
}
/
>
<
div
>
<
Button
style
=
{{
marginTop
:
8
}}
type
=
{
'warning'
}
onClick
=
{()
=>
{
setUnlimitedQuota
();
}}
>
{
unlimited_quota
?
'取消无限额度'
:
'设为无限额度'
}
<
/Button
>
<
/div
>
<
/Spin
>
<
/SideSheet
>
<
/
>
);
};
export
default
EditToken
;
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