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
bcb4862a
authored
May 16, 2023
by
JustSong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor: bind quota to account instead of token (close #64, #31)
parent
349aca58
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
217 additions
and
153 deletions
+217
-153
common/constants.go
+2
-2
controller/token.go
+2
-51
controller/user.go
+31
-0
model/redemption.go
+4
-4
model/token.go
+53
-15
model/user.go
+11
-0
router/api-router.go
+1
-1
web/src/App.js
+11
-0
web/src/components/Header.js
+6
-0
web/src/components/TokensTable.js
+0
-73
web/src/pages/Token/EditToken.js
+2
-7
web/src/pages/TopUp/index.js
+94
-0
No files found.
common/constants.go
View file @
bcb4862a
...
@@ -50,10 +50,10 @@ var WeChatAccountQRCodeImageURL = ""
...
@@ -50,10 +50,10 @@ var WeChatAccountQRCodeImageURL = ""
var
TurnstileSiteKey
=
""
var
TurnstileSiteKey
=
""
var
TurnstileSecretKey
=
""
var
TurnstileSecretKey
=
""
var
QuotaForNewUser
=
10
0
var
QuotaForNewUser
=
0
var
ChannelDisableThreshold
=
5.0
var
ChannelDisableThreshold
=
5.0
var
AutomaticDisableChannelEnabled
=
false
var
AutomaticDisableChannelEnabled
=
false
var
QuotaRemindThreshold
=
1000
// TODO: QuotaRemindThreshold
var
QuotaRemindThreshold
=
1000
var
RootUserEmail
=
""
var
RootUserEmail
=
""
...
...
controller/token.go
View file @
bcb4862a
...
@@ -100,7 +100,6 @@ func GetTokenStatus(c *gin.Context) {
...
@@ -100,7 +100,6 @@ func GetTokenStatus(c *gin.Context) {
}
}
func
AddToken
(
c
*
gin
.
Context
)
{
func
AddToken
(
c
*
gin
.
Context
)
{
isAdmin
:=
c
.
GetInt
(
"role"
)
>=
common
.
RoleAdminUser
token
:=
model
.
Token
{}
token
:=
model
.
Token
{}
err
:=
c
.
ShouldBindJSON
(
&
token
)
err
:=
c
.
ShouldBindJSON
(
&
token
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -124,21 +123,8 @@ func AddToken(c *gin.Context) {
...
@@ -124,21 +123,8 @@ func AddToken(c *gin.Context) {
CreatedTime
:
common
.
GetTimestamp
(),
CreatedTime
:
common
.
GetTimestamp
(),
AccessedTime
:
common
.
GetTimestamp
(),
AccessedTime
:
common
.
GetTimestamp
(),
ExpiredTime
:
token
.
ExpiredTime
,
ExpiredTime
:
token
.
ExpiredTime
,
}
RemainQuota
:
token
.
RemainQuota
,
if
isAdmin
{
UnlimitedQuota
:
token
.
UnlimitedQuota
,
cleanToken
.
RemainQuota
=
token
.
RemainQuota
cleanToken
.
UnlimitedQuota
=
token
.
UnlimitedQuota
}
else
{
userId
:=
c
.
GetInt
(
"id"
)
quota
,
err
:=
model
.
GetUserQuota
(
userId
)
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
err
.
Error
(),
})
return
}
cleanToken
.
RemainQuota
=
quota
}
}
err
=
cleanToken
.
Insert
()
err
=
cleanToken
.
Insert
()
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -148,10 +134,6 @@ func AddToken(c *gin.Context) {
...
@@ -148,10 +134,6 @@ func AddToken(c *gin.Context) {
})
})
return
return
}
}
if
!
isAdmin
{
// update user quota
err
=
model
.
DecreaseUserQuota
(
c
.
GetInt
(
"id"
),
cleanToken
.
RemainQuota
)
}
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
true
,
"success"
:
true
,
"message"
:
""
,
"message"
:
""
,
...
@@ -240,34 +222,3 @@ func UpdateToken(c *gin.Context) {
...
@@ -240,34 +222,3 @@ func UpdateToken(c *gin.Context) {
})
})
return
return
}
}
type
topUpRequest
struct
{
Id
int
`json:"id"`
Key
string
`json:"key"`
}
func
TopUp
(
c
*
gin
.
Context
)
{
req
:=
topUpRequest
{}
err
:=
c
.
ShouldBindJSON
(
&
req
)
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
err
.
Error
(),
})
return
}
quota
,
err
:=
model
.
Redeem
(
req
.
Key
,
req
.
Id
)
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
err
.
Error
(),
})
return
}
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
true
,
"message"
:
""
,
"data"
:
quota
,
})
return
}
controller/user.go
View file @
bcb4862a
...
@@ -654,3 +654,34 @@ func EmailBind(c *gin.Context) {
...
@@ -654,3 +654,34 @@ func EmailBind(c *gin.Context) {
})
})
return
return
}
}
type
topUpRequest
struct
{
Key
string
`json:"key"`
}
func
TopUp
(
c
*
gin
.
Context
)
{
req
:=
topUpRequest
{}
err
:=
c
.
ShouldBindJSON
(
&
req
)
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
err
.
Error
(),
})
return
}
id
:=
c
.
GetInt
(
"id"
)
quota
,
err
:=
model
.
Redeem
(
req
.
Key
,
id
)
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
err
.
Error
(),
})
return
}
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
true
,
"message"
:
""
,
"data"
:
quota
,
})
return
}
model/redemption.go
View file @
bcb4862a
...
@@ -40,12 +40,12 @@ func GetRedemptionById(id int) (*Redemption, error) {
...
@@ -40,12 +40,12 @@ func GetRedemptionById(id int) (*Redemption, error) {
return
&
redemption
,
err
return
&
redemption
,
err
}
}
func
Redeem
(
key
string
,
token
Id
int
)
(
quota
int
,
err
error
)
{
func
Redeem
(
key
string
,
user
Id
int
)
(
quota
int
,
err
error
)
{
if
key
==
""
{
if
key
==
""
{
return
0
,
errors
.
New
(
"未提供兑换码"
)
return
0
,
errors
.
New
(
"未提供兑换码"
)
}
}
if
token
Id
==
0
{
if
user
Id
==
0
{
return
0
,
errors
.
New
(
"
未提供 token
id"
)
return
0
,
errors
.
New
(
"
无效的 user
id"
)
}
}
redemption
:=
&
Redemption
{}
redemption
:=
&
Redemption
{}
err
=
DB
.
Where
(
"`key` = ?"
,
key
)
.
First
(
redemption
)
.
Error
err
=
DB
.
Where
(
"`key` = ?"
,
key
)
.
First
(
redemption
)
.
Error
...
@@ -55,7 +55,7 @@ func Redeem(key string, tokenId int) (quota int, err error) {
...
@@ -55,7 +55,7 @@ func Redeem(key string, tokenId int) (quota int, err error) {
if
redemption
.
Status
!=
common
.
RedemptionCodeStatusEnabled
{
if
redemption
.
Status
!=
common
.
RedemptionCodeStatusEnabled
{
return
0
,
errors
.
New
(
"该兑换码已被使用"
)
return
0
,
errors
.
New
(
"该兑换码已被使用"
)
}
}
err
=
Increase
TokenQuota
(
token
Id
,
redemption
.
Quota
)
err
=
Increase
UserQuota
(
user
Id
,
redemption
.
Quota
)
if
err
!=
nil
{
if
err
!=
nil
{
return
0
,
err
return
0
,
err
}
}
...
...
model/token.go
View file @
bcb4862a
...
@@ -2,6 +2,7 @@ package model
...
@@ -2,6 +2,7 @@ package model
import
(
import
(
"errors"
"errors"
"fmt"
_
"gorm.io/driver/sqlite"
_
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm"
"one-api/common"
"one-api/common"
...
@@ -82,6 +83,16 @@ func GetTokenByIds(id int, userId int) (*Token, error) {
...
@@ -82,6 +83,16 @@ func GetTokenByIds(id int, userId int) (*Token, error) {
return
&
token
,
err
return
&
token
,
err
}
}
func
GetTokenById
(
id
int
)
(
*
Token
,
error
)
{
if
id
==
0
{
return
nil
,
errors
.
New
(
"id 为空!"
)
}
token
:=
Token
{
Id
:
id
}
var
err
error
=
nil
err
=
DB
.
First
(
&
token
,
"id = ?"
,
id
)
.
Error
return
&
token
,
err
}
func
(
token
*
Token
)
Insert
()
error
{
func
(
token
*
Token
)
Insert
()
error
{
var
err
error
var
err
error
err
=
DB
.
Create
(
token
)
.
Error
err
=
DB
.
Create
(
token
)
.
Error
...
@@ -116,26 +127,53 @@ func DeleteTokenById(id int, userId int) (err error) {
...
@@ -116,26 +127,53 @@ func DeleteTokenById(id int, userId int) (err error) {
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
quota
:=
token
.
RemainQuota
return
token
.
Delete
()
if
quota
!=
0
{
}
if
quota
>
0
{
err
=
IncreaseUserQuota
(
userId
,
quota
)
func
DecreaseTokenQuota
(
tokenId
int
,
quota
int
)
(
err
error
)
{
}
else
{
if
quota
<
0
{
err
=
DecreaseUserQuota
(
userId
,
-
quota
)
return
errors
.
New
(
"quota 不能为负数!"
)
}
token
,
err
:=
GetTokenById
(
tokenId
)
if
err
!=
nil
{
return
err
}
}
if
token
.
RemainQuota
<
quota
{
return
errors
.
New
(
"令牌额度不足"
)
}
}
userQuota
,
err
:=
GetUserQuota
(
token
.
UserId
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
return
token
.
Delete
()
if
userQuota
<
quota
{
}
return
errors
.
New
(
"用户额度不足"
)
}
func
IncreaseTokenQuota
(
id
int
,
quota
int
)
(
err
error
)
{
quotaTooLow
:=
userQuota
>=
common
.
QuotaRemindThreshold
&&
userQuota
-
quota
<
common
.
QuotaRemindThreshold
err
=
DB
.
Model
(
&
Token
{})
.
Where
(
"id = ?"
,
id
)
.
Update
(
"remain_quota"
,
gorm
.
Expr
(
"remain_quota + ?"
,
quota
))
.
Error
noMoreQuota
:=
userQuota
-
quota
<=
0
if
quotaTooLow
||
noMoreQuota
{
go
func
()
{
email
,
err
:=
GetUserEmail
(
token
.
UserId
)
if
err
!=
nil
{
common
.
SysError
(
"获取用户邮箱失败:"
+
err
.
Error
())
}
prompt
:=
"您的额度即将用尽"
if
noMoreQuota
{
prompt
=
"您的额度已用尽"
}
if
email
!=
""
{
topUpLink
:=
fmt
.
Sprintf
(
"%s/topup"
,
common
.
ServerAddress
)
err
=
common
.
SendEmail
(
prompt
,
email
,
fmt
.
Sprintf
(
"%s,剩余额度为 %d,为了不影响您的使用,请及时充值。<br/>充值链接:<a href='%s'>%s</a>"
,
prompt
,
userQuota
-
quota
,
topUpLink
,
topUpLink
))
if
err
!=
nil
{
common
.
SysError
(
"发送邮件失败:"
+
err
.
Error
())
}
}
}()
}
err
=
DB
.
Model
(
&
Token
{})
.
Where
(
"id = ?"
,
tokenId
)
.
Update
(
"remain_quota"
,
gorm
.
Expr
(
"remain_quota - ?"
,
quota
))
.
Error
if
err
!=
nil
{
return
err
return
err
}
}
err
=
DecreaseUserQuota
(
token
.
UserId
,
quota
)
func
DecreaseTokenQuota
(
id
int
,
quota
int
)
(
err
error
)
{
err
=
DB
.
Model
(
&
Token
{})
.
Where
(
"id = ?"
,
id
)
.
Update
(
"remain_quota"
,
gorm
.
Expr
(
"remain_quota - ?"
,
quota
))
.
Error
return
err
return
err
}
}
model/user.go
View file @
bcb4862a
...
@@ -225,12 +225,23 @@ func GetUserQuota(id int) (quota int, err error) {
...
@@ -225,12 +225,23 @@ func GetUserQuota(id int) (quota int, err error) {
return
quota
,
err
return
quota
,
err
}
}
func
GetUserEmail
(
id
int
)
(
email
string
,
err
error
)
{
err
=
DB
.
Model
(
&
User
{})
.
Where
(
"id = ?"
,
id
)
.
Select
(
"email"
)
.
Find
(
&
email
)
.
Error
return
email
,
err
}
func
IncreaseUserQuota
(
id
int
,
quota
int
)
(
err
error
)
{
func
IncreaseUserQuota
(
id
int
,
quota
int
)
(
err
error
)
{
if
quota
<
0
{
return
errors
.
New
(
"quota 不能为负数!"
)
}
err
=
DB
.
Model
(
&
User
{})
.
Where
(
"id = ?"
,
id
)
.
Update
(
"quota"
,
gorm
.
Expr
(
"quota + ?"
,
quota
))
.
Error
err
=
DB
.
Model
(
&
User
{})
.
Where
(
"id = ?"
,
id
)
.
Update
(
"quota"
,
gorm
.
Expr
(
"quota + ?"
,
quota
))
.
Error
return
err
return
err
}
}
func
DecreaseUserQuota
(
id
int
,
quota
int
)
(
err
error
)
{
func
DecreaseUserQuota
(
id
int
,
quota
int
)
(
err
error
)
{
if
quota
<
0
{
return
errors
.
New
(
"quota 不能为负数!"
)
}
err
=
DB
.
Model
(
&
User
{})
.
Where
(
"id = ?"
,
id
)
.
Update
(
"quota"
,
gorm
.
Expr
(
"quota - ?"
,
quota
))
.
Error
err
=
DB
.
Model
(
&
User
{})
.
Where
(
"id = ?"
,
id
)
.
Update
(
"quota"
,
gorm
.
Expr
(
"quota - ?"
,
quota
))
.
Error
return
err
return
err
}
}
...
...
router/api-router.go
View file @
bcb4862a
...
@@ -37,6 +37,7 @@ func SetApiRouter(router *gin.Engine) {
...
@@ -37,6 +37,7 @@ func SetApiRouter(router *gin.Engine) {
selfRoute
.
PUT
(
"/self"
,
controller
.
UpdateSelf
)
selfRoute
.
PUT
(
"/self"
,
controller
.
UpdateSelf
)
selfRoute
.
DELETE
(
"/self"
,
controller
.
DeleteSelf
)
selfRoute
.
DELETE
(
"/self"
,
controller
.
DeleteSelf
)
selfRoute
.
GET
(
"/token"
,
controller
.
GenerateAccessToken
)
selfRoute
.
GET
(
"/token"
,
controller
.
GenerateAccessToken
)
selfRoute
.
POST
(
"/topup"
,
controller
.
TopUp
)
}
}
adminRoute
:=
userRoute
.
Group
(
"/"
)
adminRoute
:=
userRoute
.
Group
(
"/"
)
...
@@ -74,7 +75,6 @@ func SetApiRouter(router *gin.Engine) {
...
@@ -74,7 +75,6 @@ func SetApiRouter(router *gin.Engine) {
{
{
tokenRoute
.
GET
(
"/"
,
controller
.
GetAllTokens
)
tokenRoute
.
GET
(
"/"
,
controller
.
GetAllTokens
)
tokenRoute
.
GET
(
"/search"
,
controller
.
SearchTokens
)
tokenRoute
.
GET
(
"/search"
,
controller
.
SearchTokens
)
tokenRoute
.
POST
(
"/topup"
,
controller
.
TopUp
)
tokenRoute
.
GET
(
"/:id"
,
controller
.
GetToken
)
tokenRoute
.
GET
(
"/:id"
,
controller
.
GetToken
)
tokenRoute
.
POST
(
"/"
,
controller
.
AddToken
)
tokenRoute
.
POST
(
"/"
,
controller
.
AddToken
)
tokenRoute
.
PUT
(
"/"
,
controller
.
UpdateToken
)
tokenRoute
.
PUT
(
"/"
,
controller
.
UpdateToken
)
...
...
web/src/App.js
View file @
bcb4862a
...
@@ -21,6 +21,7 @@ import EditToken from './pages/Token/EditToken';
...
@@ -21,6 +21,7 @@ import EditToken from './pages/Token/EditToken';
import
EditChannel
from
'./pages/Channel/EditChannel'
;
import
EditChannel
from
'./pages/Channel/EditChannel'
;
import
Redemption
from
'./pages/Redemption'
;
import
Redemption
from
'./pages/Redemption'
;
import
EditRedemption
from
'./pages/Redemption/EditRedemption'
;
import
EditRedemption
from
'./pages/Redemption/EditRedemption'
;
import
TopUp
from
'./pages/TopUp'
;
const
Home
=
lazy
(()
=>
import
(
'./pages/Home'
));
const
Home
=
lazy
(()
=>
import
(
'./pages/Home'
));
const
About
=
lazy
(()
=>
import
(
'./pages/About'
));
const
About
=
lazy
(()
=>
import
(
'./pages/About'
));
...
@@ -240,6 +241,16 @@ function App() {
...
@@ -240,6 +241,16 @@ function App() {
}
}
/
>
/
>
<
Route
<
Route
path
=
'/topup'
element
=
{
<
PrivateRoute
>
<
Suspense
fallback
=
{
<
Loading
><
/Loading>}
>
<
TopUp
/>
<
/Suspense
>
<
/PrivateRoute
>
}
/
>
<
Route
path
=
'/about'
path
=
'/about'
element
=
{
element
=
{
<
Suspense
fallback
=
{
<
Loading
><
/Loading>}
>
<
Suspense
fallback
=
{
<
Loading
><
/Loading>}
>
...
...
web/src/components/Header.js
View file @
bcb4862a
...
@@ -31,6 +31,12 @@ const headerButtons = [
...
@@ -31,6 +31,12 @@ const headerButtons = [
admin
:
true
,
admin
:
true
,
},
},
{
{
name
:
'充值'
,
to
:
'/topup'
,
icon
:
'cart'
,
admin
:
true
,
},
{
name
:
'用户'
,
name
:
'用户'
,
to
:
'/user'
,
to
:
'/user'
,
icon
:
'user'
,
icon
:
'user'
,
...
...
web/src/components/TokensTable.js
View file @
bcb4862a
...
@@ -36,8 +36,6 @@ const TokensTable = () => {
...
@@ -36,8 +36,6 @@ const TokensTable = () => {
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
);
const
[
redemptionCode
,
setRedemptionCode
]
=
useState
(
''
);
const
[
topUpLink
,
setTopUpLink
]
=
useState
(
''
);
const
loadTokens
=
async
(
startIdx
)
=>
{
const
loadTokens
=
async
(
startIdx
)
=>
{
const
res
=
await
API
.
get
(
`/api/token/?p=
${
startIdx
}
`
);
const
res
=
await
API
.
get
(
`/api/token/?p=
${
startIdx
}
`
);
...
@@ -77,13 +75,6 @@ const TokensTable = () => {
...
@@ -77,13 +75,6 @@ const TokensTable = () => {
.
catch
((
reason
)
=>
{
.
catch
((
reason
)
=>
{
showError
(
reason
);
showError
(
reason
);
});
});
let
status
=
localStorage
.
getItem
(
'status'
);
if
(
status
)
{
status
=
JSON
.
parse
(
status
);
if
(
status
.
top_up_link
)
{
setTopUpLink
(
status
.
top_up_link
);
}
}
},
[]);
},
[]);
const
manageToken
=
async
(
id
,
action
,
idx
)
=>
{
const
manageToken
=
async
(
id
,
action
,
idx
)
=>
{
...
@@ -156,28 +147,6 @@ const TokensTable = () => {
...
@@ -156,28 +147,6 @@ const TokensTable = () => {
setLoading
(
false
);
setLoading
(
false
);
};
};
const
topUp
=
async
()
=>
{
if
(
redemptionCode
===
''
)
{
return
;
}
const
res
=
await
API
.
post
(
'/api/token/topup/'
,
{
id
:
tokens
[
targetTokenIdx
].
id
,
key
:
redemptionCode
});
const
{
success
,
message
,
data
}
=
res
.
data
;
if
(
success
)
{
showSuccess
(
'充值成功!'
);
let
newTokens
=
[...
tokens
];
let
realIdx
=
(
activePage
-
1
)
*
ITEMS_PER_PAGE
+
targetTokenIdx
;
newTokens
[
realIdx
].
remain_quota
+=
data
;
setTokens
(
newTokens
);
setRedemptionCode
(
''
);
setShowTopUpModal
(
false
);
}
else
{
showError
(
message
);
}
}
return
(
return
(
<>
<>
<
Form
onSubmit
=
{
searchTokens
}
>
<
Form
onSubmit
=
{
searchTokens
}
>
...
@@ -279,15 +248,6 @@ const TokensTable = () => {
...
@@ -279,15 +248,6 @@ const TokensTable = () => {
>
>
复制
复制
<
/Button
>
<
/Button
>
<
Button
size
=
{
'small'
}
color
=
{
'yellow'
}
onClick
=
{()
=>
{
setTargetTokenIdx
(
idx
);
setShowTopUpModal
(
true
);
}}
>
充值
<
/Button
>
<
Popup
<
Popup
trigger
=
{
trigger
=
{
<
Button
size
=
'small'
negative
>
<
Button
size
=
'small'
negative
>
...
@@ -355,39 +315,6 @@ const TokensTable = () => {
...
@@ -355,39 +315,6 @@ const TokensTable = () => {
<
/Table.Row
>
<
/Table.Row
>
<
/Table.Footer
>
<
/Table.Footer
>
<
/Table
>
<
/Table
>
<
Modal
onClose
=
{()
=>
setShowTopUpModal
(
false
)}
onOpen
=
{()
=>
setShowTopUpModal
(
true
)}
open
=
{
showTopUpModal
}
size
=
{
'mini'
}
>
<
Modal
.
Header
>
通过兑换码为令牌「
{
tokens
[
targetTokenIdx
]?.
name
}
」充值
<
/Modal.Header
>
<
Modal
.
Content
>
<
Modal
.
Description
>
{
/*<Image src={status.wechat_qrcode} fluid />*/
}
{
topUpLink
&&
<
p
>
<
a
target
=
'_blank'
href
=
{
topUpLink
}
>
点击此处获取兑换码
<
/a
>
<
/p
>
}
<
Form
size
=
'large'
>
<
Form
.
Input
fluid
placeholder
=
'兑换码'
name
=
'redemptionCode'
value
=
{
redemptionCode
}
onChange
=
{(
e
)
=>
{
setRedemptionCode
(
e
.
target
.
value
);
}}
/
>
<
Button
color
=
''
fluid
size
=
'large'
onClick
=
{
topUp
}
>
充值
<
/Button
>
<
/Form
>
<
/Modal.Description
>
<
/Modal.Content
>
<
/Modal
>
<
/
>
<
/
>
);
);
};
};
...
...
web/src/pages/Token/EditToken.js
View file @
bcb4862a
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
Button
,
Form
,
Header
,
Segment
}
from
'semantic-ui-react'
;
import
{
Button
,
Form
,
Header
,
Segment
}
from
'semantic-ui-react'
;
import
{
useParams
}
from
'react-router-dom'
;
import
{
useParams
}
from
'react-router-dom'
;
import
{
API
,
isAdmin
,
showError
,
showSuccess
,
timestamp2string
}
from
'../../helpers'
;
import
{
API
,
showError
,
showSuccess
,
timestamp2string
}
from
'../../helpers'
;
const
EditToken
=
()
=>
{
const
EditToken
=
()
=>
{
const
params
=
useParams
();
const
params
=
useParams
();
...
@@ -14,7 +14,6 @@ const EditToken = () => {
...
@@ -14,7 +14,6 @@ const EditToken = () => {
expired_time
:
-
1
,
expired_time
:
-
1
,
unlimited_quota
:
false
unlimited_quota
:
false
};
};
const
isAdminUser
=
isAdmin
();
const
[
inputs
,
setInputs
]
=
useState
(
originInputs
);
const
[
inputs
,
setInputs
]
=
useState
(
originInputs
);
const
{
name
,
remain_quota
,
expired_time
,
unlimited_quota
}
=
inputs
;
const
{
name
,
remain_quota
,
expired_time
,
unlimited_quota
}
=
inputs
;
...
@@ -107,8 +106,6 @@ const EditToken = () => {
...
@@ -107,8 +106,6 @@ const EditToken = () => {
required
=
{
!
isEdit
}
required
=
{
!
isEdit
}
/
>
/
>
<
/Form.Field
>
<
/Form.Field
>
{
isAdminUser
&&
<>
<
Form
.
Field
>
<
Form
.
Field
>
<
Form
.
Input
<
Form
.
Input
label
=
'额度'
label
=
'额度'
...
@@ -121,11 +118,9 @@ const EditToken = () => {
...
@@ -121,11 +118,9 @@ const EditToken = () => {
disabled
=
{
unlimited_quota
}
disabled
=
{
unlimited_quota
}
/
>
/
>
<
/Form.Field
>
<
/Form.Field
>
<
Button
type
=
{
'button'
}
style
=
{{
marginBottom
:
'14px'
}}
onClick
=
{()
=>
{
<
Button
type
=
{
'button'
}
style
=
{{
marginBottom
:
'14px'
}}
onClick
=
{()
=>
{
setUnlimitedQuota
();
setUnlimitedQuota
();
}}
>
{
unlimited_quota
?
'取消无限额度'
:
'设置为无限额度'
}
<
/Button
>
}}
>
{
unlimited_quota
?
'取消无限额度'
:
'设置为无限额度'
}
<
/Button
>
<
/
>
}
<
Form
.
Field
>
<
Form
.
Field
>
<
Form
.
Input
<
Form
.
Input
label
=
'过期时间'
label
=
'过期时间'
...
...
web/src/pages/TopUp/index.js
0 → 100644
View file @
bcb4862a
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
Button
,
Form
,
Grid
,
Header
,
Segment
,
Statistic
}
from
'semantic-ui-react'
;
import
{
API
,
showError
,
showSuccess
}
from
'../../helpers'
;
const
TopUp
=
()
=>
{
const
[
redemptionCode
,
setRedemptionCode
]
=
useState
(
''
);
const
[
topUpLink
,
setTopUpLink
]
=
useState
(
''
);
const
[
userQuota
,
setUserQuota
]
=
useState
(
0
);
const
topUp
=
async
()
=>
{
if
(
redemptionCode
===
''
)
{
return
;
}
const
res
=
await
API
.
post
(
'/api/user/topup'
,
{
key
:
redemptionCode
});
const
{
success
,
message
,
data
}
=
res
.
data
;
if
(
success
)
{
showSuccess
(
'充值成功!'
);
setUserQuota
((
quota
)
=>
{
return
quota
+
data
;
});
setRedemptionCode
(
''
);
}
else
{
showError
(
message
);
}
};
const
openTopUpLink
=
()
=>
{
if
(
!
topUpLink
)
{
showError
(
'超级管理员未设置充值链接!'
);
return
;
}
window
.
open
(
topUpLink
,
'_blank'
);
};
const
getUserQuota
=
async
()
=>
{
let
res
=
await
API
.
get
(
`/api/user/self`
);
const
{
success
,
message
,
data
}
=
res
.
data
;
if
(
success
)
{
setUserQuota
(
data
.
quota
);
}
else
{
showError
(
message
);
}
}
useEffect
(()
=>
{
let
status
=
localStorage
.
getItem
(
'status'
);
if
(
status
)
{
status
=
JSON
.
parse
(
status
);
if
(
status
.
top_up_link
)
{
setTopUpLink
(
status
.
top_up_link
);
}
}
getUserQuota
().
then
();
},
[]);
return
(
<
Segment
>
<
Header
as
=
'h3'
>
充值额度
<
/Header
>
<
Grid
columns
=
{
2
}
stackable
>
<
Grid
.
Column
>
<
Form
>
<
Form
.
Input
placeholder
=
'兑换码'
name
=
'redemptionCode'
value
=
{
redemptionCode
}
onChange
=
{(
e
)
=>
{
setRedemptionCode
(
e
.
target
.
value
);
}}
/
>
<
Button
color
=
'green'
onClick
=
{
openTopUpLink
}
>
获取兑换码
<
/Button
>
<
Button
color
=
'yellow'
onClick
=
{
topUp
}
>
充值
<
/Button
>
<
/Form
>
<
/Grid.Column
>
<
Grid
.
Column
>
<
Statistic
.
Group
widths
=
'one'
>
<
Statistic
>
<
Statistic
.
Value
>
{
userQuota
}
<
/Statistic.Value
>
<
Statistic
.
Label
>
剩余额度
<
/Statistic.Label
>
<
/Statistic
>
<
/Statistic.Group
>
<
/Grid.Column
>
<
/Grid
>
<
/Segment
>
);
};
export
default
TopUp
;
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