Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
69cafe86
Commit
69cafe86
authored
Mar 12, 2026
by
wanXcode
Browse files
fix(dashboard): prefer username in user usage trend
parent
826090e0
Changes
4
Show whitespace changes
Inline
Side-by-side
backend/internal/pkg/usagestats/usage_log_types.go
View file @
69cafe86
...
@@ -96,6 +96,7 @@ type UserUsageTrendPoint struct {
...
@@ -96,6 +96,7 @@ type UserUsageTrendPoint struct {
Date
string
`json:"date"`
Date
string
`json:"date"`
UserID
int64
`json:"user_id"`
UserID
int64
`json:"user_id"`
Email
string
`json:"email"`
Email
string
`json:"email"`
Username
string
`json:"username"`
Requests
int64
`json:"requests"`
Requests
int64
`json:"requests"`
Tokens
int64
`json:"tokens"`
Tokens
int64
`json:"tokens"`
Cost
float64
`json:"cost"`
// 标准计费
Cost
float64
`json:"cost"`
// 标准计费
...
...
backend/internal/repository/usage_log_repo.go
View file @
69cafe86
...
@@ -1114,6 +1114,7 @@ func (r *usageLogRepository) GetUserUsageTrend(ctx context.Context, startTime, e
...
@@ -1114,6 +1114,7 @@ func (r *usageLogRepository) GetUserUsageTrend(ctx context.Context, startTime, e
TO_CHAR(u.created_at, '%s') as date,
TO_CHAR(u.created_at, '%s') as date,
u.user_id,
u.user_id,
COALESCE(us.email, '') as email,
COALESCE(us.email, '') as email,
COALESCE(us.username, '') as username,
COUNT(*) as requests,
COUNT(*) as requests,
COALESCE(SUM(u.input_tokens + u.output_tokens + u.cache_creation_tokens + u.cache_read_tokens), 0) as tokens,
COALESCE(SUM(u.input_tokens + u.output_tokens + u.cache_creation_tokens + u.cache_read_tokens), 0) as tokens,
COALESCE(SUM(u.total_cost), 0) as cost,
COALESCE(SUM(u.total_cost), 0) as cost,
...
@@ -1122,7 +1123,7 @@ func (r *usageLogRepository) GetUserUsageTrend(ctx context.Context, startTime, e
...
@@ -1122,7 +1123,7 @@ func (r *usageLogRepository) GetUserUsageTrend(ctx context.Context, startTime, e
LEFT JOIN users us ON u.user_id = us.id
LEFT JOIN users us ON u.user_id = us.id
WHERE u.user_id IN (SELECT user_id FROM top_users)
WHERE u.user_id IN (SELECT user_id FROM top_users)
AND u.created_at >= $4 AND u.created_at < $5
AND u.created_at >= $4 AND u.created_at < $5
GROUP BY date, u.user_id, us.email
GROUP BY date, u.user_id, us.email
, us.username
ORDER BY date ASC, tokens DESC
ORDER BY date ASC, tokens DESC
`
,
dateFormat
)
`
,
dateFormat
)
...
@@ -1142,7 +1143,7 @@ func (r *usageLogRepository) GetUserUsageTrend(ctx context.Context, startTime, e
...
@@ -1142,7 +1143,7 @@ func (r *usageLogRepository) GetUserUsageTrend(ctx context.Context, startTime, e
results
=
make
([]
UserUsageTrendPoint
,
0
)
results
=
make
([]
UserUsageTrendPoint
,
0
)
for
rows
.
Next
()
{
for
rows
.
Next
()
{
var
row
UserUsageTrendPoint
var
row
UserUsageTrendPoint
if
err
=
rows
.
Scan
(
&
row
.
Date
,
&
row
.
UserID
,
&
row
.
Email
,
&
row
.
Requests
,
&
row
.
Tokens
,
&
row
.
Cost
,
&
row
.
ActualCost
);
err
!=
nil
{
if
err
=
rows
.
Scan
(
&
row
.
Date
,
&
row
.
UserID
,
&
row
.
Email
,
&
row
.
Username
,
&
row
.
Requests
,
&
row
.
Tokens
,
&
row
.
Cost
,
&
row
.
ActualCost
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
results
=
append
(
results
,
row
)
results
=
append
(
results
,
row
)
...
...
frontend/src/types/index.ts
View file @
69cafe86
...
@@ -1155,6 +1155,7 @@ export interface UserUsageTrendPoint {
...
@@ -1155,6 +1155,7 @@ export interface UserUsageTrendPoint {
date
:
string
date
:
string
user_id
:
number
user_id
:
number
email
:
string
email
:
string
username
:
string
requests
:
number
requests
:
number
tokens
:
number
tokens
:
number
cost
:
number
// 标准计费
cost
:
number
// 标准计费
...
...
frontend/src/views/admin/DashboardView.vue
View file @
69cafe86
...
@@ -415,23 +415,29 @@ const lineOptions = computed(() => ({
...
@@ -415,23 +415,29 @@ const lineOptions = computed(() => ({
const
userTrendChartData
=
computed
(()
=>
{
const
userTrendChartData
=
computed
(()
=>
{
if
(
!
userTrend
.
value
?.
length
)
return
null
if
(
!
userTrend
.
value
?.
length
)
return
null
// Extract d
isplay
n
ame
from email (part before @)
const
getD
isplay
N
ame
=
(
point
:
UserUsageTrendPoint
):
string
=>
{
const
getDisplayName
=
(
email
:
string
,
userId
:
number
):
string
=>
{
const
username
=
point
.
username
?.
trim
()
if
(
email
&&
email
.
includes
(
'
@
'
)
)
{
if
(
username
)
{
return
email
.
split
(
'
@
'
)[
0
]
return
username
}
}
return
t
(
'
admin.redeem.userPrefix
'
,
{
id
:
userId
})
const
email
=
point
.
email
?.
trim
()
if
(
email
)
{
return
email
}
return
t
(
'
admin.redeem.userPrefix
'
,
{
id
:
point
.
user_id
})
}
}
// Group by user
// Group by user
_id to avoid merging different users with the same display name
const
userGroups
=
new
Map
<
string
,
{
name
:
string
;
data
:
Map
<
string
,
number
>
}
>
()
const
userGroups
=
new
Map
<
number
,
{
name
:
string
;
data
:
Map
<
string
,
number
>
}
>
()
const
allDates
=
new
Set
<
string
>
()
const
allDates
=
new
Set
<
string
>
()
userTrend
.
value
.
forEach
((
point
)
=>
{
userTrend
.
value
.
forEach
((
point
)
=>
{
allDates
.
add
(
point
.
date
)
allDates
.
add
(
point
.
date
)
const
key
=
getDisplayName
(
point
.
email
,
point
.
user_id
)
const
key
=
point
.
user_id
if
(
!
userGroups
.
has
(
key
))
{
if
(
!
userGroups
.
has
(
key
))
{
userGroups
.
set
(
key
,
{
name
:
key
,
data
:
new
Map
()
})
userGroups
.
set
(
key
,
{
name
:
getDisplayName
(
point
)
,
data
:
new
Map
()
})
}
}
userGroups
.
get
(
key
)
!
.
data
.
set
(
point
.
date
,
point
.
tokens
)
userGroups
.
get
(
key
)
!
.
data
.
set
(
point
.
date
,
point
.
tokens
)
})
})
...
...
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