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
0b3efe57
authored
Jun 16, 2023
by
JustSong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: record used quota & request count (close #102, #165)
parent
ba2a5f09
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
44 additions
and
12 deletions
+44
-12
controller/relay.go
+1
-0
model/user.go
+14
-0
web/src/components/UsersTable.js
+7
-3
web/src/helpers/render.js
+22
-9
No files found.
controller/relay.go
View file @
0b3efe57
...
@@ -261,6 +261,7 @@ func relayHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
...
@@ -261,6 +261,7 @@ func relayHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode {
}
}
userId
:=
c
.
GetInt
(
"id"
)
userId
:=
c
.
GetInt
(
"id"
)
model
.
RecordLog
(
userId
,
model
.
LogTypeConsume
,
fmt
.
Sprintf
(
"使用模型 %s 消耗 %d 点额度(模型倍率 %.2f,分组倍率 %.2f)"
,
textRequest
.
Model
,
quota
,
modelRatio
,
groupRatio
))
model
.
RecordLog
(
userId
,
model
.
LogTypeConsume
,
fmt
.
Sprintf
(
"使用模型 %s 消耗 %d 点额度(模型倍率 %.2f,分组倍率 %.2f)"
,
textRequest
.
Model
,
quota
,
modelRatio
,
groupRatio
))
model
.
UpdateUserUsedQuotaAndRequestCount
(
userId
,
quota
)
}
}
}()
}()
...
...
model/user.go
View file @
0b3efe57
...
@@ -23,6 +23,8 @@ type User struct {
...
@@ -23,6 +23,8 @@ type User struct {
VerificationCode
string
`json:"verification_code" gorm:"-:all"`
// this field is only for Email verification, don't save it to database!
VerificationCode
string
`json:"verification_code" gorm:"-:all"`
// this field is only for Email verification, don't save it to database!
AccessToken
string
`json:"access_token" gorm:"type:char(32);column:access_token;uniqueIndex"`
// this token is for system management
AccessToken
string
`json:"access_token" gorm:"type:char(32);column:access_token;uniqueIndex"`
// this token is for system management
Quota
int
`json:"quota" gorm:"type:int;default:0"`
Quota
int
`json:"quota" gorm:"type:int;default:0"`
UsedQuota
int
`json:"used_quota" gorm:"type:int;default:0;column:used_quota"`
// used quota
RequestCount
int
`json:"request_count" gorm:"type:int;default:0;"`
// request number
Group
string
`json:"group" gorm:"type:varchar(32);default:'default'"`
Group
string
`json:"group" gorm:"type:varchar(32);default:'default'"`
}
}
...
@@ -262,3 +264,15 @@ func GetRootUserEmail() (email string) {
...
@@ -262,3 +264,15 @@ func GetRootUserEmail() (email string) {
DB
.
Model
(
&
User
{})
.
Where
(
"role = ?"
,
common
.
RoleRootUser
)
.
Select
(
"email"
)
.
Find
(
&
email
)
DB
.
Model
(
&
User
{})
.
Where
(
"role = ?"
,
common
.
RoleRootUser
)
.
Select
(
"email"
)
.
Find
(
&
email
)
return
email
return
email
}
}
func
UpdateUserUsedQuotaAndRequestCount
(
id
int
,
quota
int
)
{
err
:=
DB
.
Model
(
&
User
{})
.
Where
(
"id = ?"
,
id
)
.
Updates
(
map
[
string
]
interface
{}{
"used_quota"
:
gorm
.
Expr
(
"used_quota + ?"
,
quota
),
"request_count"
:
gorm
.
Expr
(
"request_count + ?"
,
1
),
},
)
.
Error
if
err
!=
nil
{
common
.
SysError
(
"Failed to update user used quota and request count: "
+
err
.
Error
())
}
}
web/src/components/UsersTable.js
View file @
0b3efe57
...
@@ -4,7 +4,7 @@ import { Link } from 'react-router-dom';
...
@@ -4,7 +4,7 @@ import { Link } from 'react-router-dom';
import
{
API
,
showError
,
showSuccess
}
from
'../helpers'
;
import
{
API
,
showError
,
showSuccess
}
from
'../helpers'
;
import
{
ITEMS_PER_PAGE
}
from
'../constants'
;
import
{
ITEMS_PER_PAGE
}
from
'../constants'
;
import
{
renderGroup
,
renderText
}
from
'../helpers/render'
;
import
{
renderGroup
,
render
Number
,
render
Text
}
from
'../helpers/render'
;
function
renderRole
(
role
)
{
function
renderRole
(
role
)
{
switch
(
role
)
{
switch
(
role
)
{
...
@@ -197,7 +197,7 @@ const UsersTable = () => {
...
@@ -197,7 +197,7 @@ const UsersTable = () => {
sortUser
(
'quota'
);
sortUser
(
'quota'
);
}}
}}
>
>
剩余额度
统计信息
<
/Table.HeaderCell
>
<
/Table.HeaderCell
>
<
Table
.
HeaderCell
<
Table
.
HeaderCell
style
=
{{
cursor
:
'pointer'
}}
style
=
{{
cursor
:
'pointer'
}}
...
@@ -241,7 +241,11 @@ const UsersTable = () => {
...
@@ -241,7 +241,11 @@ const UsersTable = () => {
<
/Table.Cell
>
<
/Table.Cell
>
<
Table
.
Cell
>
{
renderGroup
(
user
.
group
)}
<
/Table.Cell
>
<
Table
.
Cell
>
{
renderGroup
(
user
.
group
)}
<
/Table.Cell
>
<
Table
.
Cell
>
{
user
.
email
?
renderText
(
user
.
email
,
30
)
:
'无'
}
<
/Table.Cell
>
<
Table
.
Cell
>
{
user
.
email
?
renderText
(
user
.
email
,
30
)
:
'无'
}
<
/Table.Cell
>
<
Table
.
Cell
>
{
user
.
quota
}
<
/Table.Cell
>
<
Table
.
Cell
>
<
Popup
content
=
'剩余额度'
trigger
=
{
<
Label
>
{
renderNumber
(
user
.
quota
)}
<
/Label>} /
>
<
Popup
content
=
'已用额度'
trigger
=
{
<
Label
>
{
renderNumber
(
user
.
used_quota
)}
<
/Label>} /
>
<
Popup
content
=
'请求次数'
trigger
=
{
<
Label
>
{
renderNumber
(
user
.
request_count
)}
<
/Label>} /
>
<
/Table.Cell
>
<
Table
.
Cell
>
{
renderRole
(
user
.
role
)}
<
/Table.Cell
>
<
Table
.
Cell
>
{
renderRole
(
user
.
role
)}
<
/Table.Cell
>
<
Table
.
Cell
>
{
renderStatus
(
user
.
status
)}
<
/Table.Cell
>
<
Table
.
Cell
>
{
renderStatus
(
user
.
status
)}
<
/Table.Cell
>
<
Table
.
Cell
>
<
Table
.
Cell
>
...
...
web/src/helpers/render.js
View file @
0b3efe57
...
@@ -8,19 +8,31 @@ export function renderText(text, limit) {
...
@@ -8,19 +8,31 @@ export function renderText(text, limit) {
}
}
export
function
renderGroup
(
group
)
{
export
function
renderGroup
(
group
)
{
if
(
group
===
""
)
{
if
(
group
===
''
)
{
return
<
Label
>
default
<
/Label
>
return
<
Label
>
default
<
/Label>
;
}
}
let
groups
=
group
.
split
(
","
);
let
groups
=
group
.
split
(
','
);
groups
.
sort
();
groups
.
sort
();
return
<>
return
<>
{
groups
.
map
((
group
)
=>
{
{
groups
.
map
((
group
)
=>
{
if
(
group
===
"vip"
||
group
===
"pro"
)
{
if
(
group
===
'vip'
||
group
===
'pro'
)
{
return
<
Label
color
=
'yellow'
>
{
group
}
<
/Label
>
return
<
Label
color
=
'yellow'
>
{
group
}
<
/Label>
;
}
else
if
(
group
===
"svip"
||
group
===
"premium"
)
{
}
else
if
(
group
===
'svip'
||
group
===
'premium'
)
{
return
<
Label
color
=
'red'
>
{
group
}
<
/Label
>
return
<
Label
color
=
'red'
>
{
group
}
<
/Label>
;
}
}
return
<
Label
>
{
group
}
<
/Label
>
return
<
Label
>
{
group
}
<
/Label>
;
})}
})}
<
/
>
<
/>
;
}
export
function
renderNumber
(
num
)
{
if
(
num
>=
1000000000
)
{
return
(
num
/
1000000000
).
toFixed
(
1
)
+
'B'
;
}
else
if
(
num
>=
1000000
)
{
return
(
num
/
1000000
).
toFixed
(
1
)
+
'M'
;
}
else
if
(
num
>=
10000
)
{
return
(
num
/
1000
).
toFixed
(
1
)
+
'k'
;
}
else
{
return
num
;
}
}
}
\ No newline at end of file
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