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
f79b0f0f
Commit
f79b0f0f
authored
Dec 25, 2025
by
ianshaw
Browse files
style(frontend): 统一 API 模块代码风格
- 移除所有语句末尾分号 - 统一对象属性尾随逗号格式 - 优化类型定义导入顺序 - 提升代码一致性和可读性
parent
34183b52
Changes
21
Hide whitespace changes
Inline
Side-by-side
frontend/src/api/admin/accounts.ts
View file @
f79b0f0f
...
...
@@ -12,7 +12,7 @@ import type {
AccountUsageInfo
,
WindowStats
,
ClaudeModel
,
AccountUsageStatsResponse
,
AccountUsageStatsResponse
}
from
'
@/types
'
/**
...
...
@@ -36,8 +36,8 @@ export async function list(
params
:
{
page
,
page_size
:
pageSize
,
...
filters
,
}
,
...
filters
}
})
return
data
}
...
...
@@ -129,7 +129,7 @@ export async function refreshCredentials(id: number): Promise<Account> {
*/
export
async
function
getStats
(
id
:
number
,
days
:
number
=
30
):
Promise
<
AccountUsageStatsResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
AccountUsageStatsResponse
>
(
`/admin/accounts/
${
id
}
/stats`
,
{
params
:
{
days
}
,
params
:
{
days
}
})
return
data
}
...
...
@@ -254,7 +254,7 @@ export async function bulkUpdate(
results
:
Array
<
{
account_id
:
number
;
success
:
boolean
;
error
?:
string
}
>
}
>
(
'
/admin/accounts/bulk-update
'
,
{
account_ids
:
accountIds
,
...
updates
,
...
updates
})
return
data
}
...
...
@@ -277,7 +277,7 @@ export async function getTodayStats(id: number): Promise<WindowStats> {
*/
export
async
function
setSchedulable
(
id
:
number
,
schedulable
:
boolean
):
Promise
<
Account
>
{
const
{
data
}
=
await
apiClient
.
post
<
Account
>
(
`/admin/accounts/
${
id
}
/schedulable`
,
{
schedulable
,
schedulable
})
return
data
}
...
...
@@ -335,7 +335,7 @@ export const accountsAPI = {
batchCreate
,
batchUpdateCredentials
,
bulkUpdate
,
syncFromCrs
,
syncFromCrs
}
export
default
accountsAPI
frontend/src/api/admin/dashboard.ts
View file @
f79b0f0f
...
...
@@ -3,16 +3,22 @@
* Provides system-wide statistics and metrics
*/
import
{
apiClient
}
from
'
../client
'
;
import
type
{
DashboardStats
,
TrendDataPoint
,
ModelStat
,
ApiKeyUsageTrendPoint
,
UserUsageTrendPoint
}
from
'
@/types
'
;
import
{
apiClient
}
from
'
../client
'
import
type
{
DashboardStats
,
TrendDataPoint
,
ModelStat
,
ApiKeyUsageTrendPoint
,
UserUsageTrendPoint
}
from
'
@/types
'
/**
* Get dashboard statistics
* @returns Dashboard statistics including users, keys, accounts, and token usage
*/
export
async
function
getStats
():
Promise
<
DashboardStats
>
{
const
{
data
}
=
await
apiClient
.
get
<
DashboardStats
>
(
'
/admin/dashboard/stats
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
DashboardStats
>
(
'
/admin/dashboard/stats
'
)
return
data
}
/**
...
...
@@ -20,33 +26,33 @@ export async function getStats(): Promise<DashboardStats> {
* @returns Real-time system metrics
*/
export
async
function
getRealtimeMetrics
():
Promise
<
{
active_requests
:
number
;
requests_per_minute
:
number
;
average_response_time
:
number
;
error_rate
:
number
;
active_requests
:
number
requests_per_minute
:
number
average_response_time
:
number
error_rate
:
number
}
>
{
const
{
data
}
=
await
apiClient
.
get
<
{
active_requests
:
number
;
requests_per_minute
:
number
;
average_response_time
:
number
;
error_rate
:
number
;
}
>
(
'
/admin/dashboard/realtime
'
)
;
return
data
;
active_requests
:
number
requests_per_minute
:
number
average_response_time
:
number
error_rate
:
number
}
>
(
'
/admin/dashboard/realtime
'
)
return
data
}
export
interface
TrendParams
{
start_date
?:
string
;
end_date
?:
string
;
granularity
?:
'
day
'
|
'
hour
'
;
user_id
?:
number
;
api_key_id
?:
number
;
start_date
?:
string
end_date
?:
string
granularity
?:
'
day
'
|
'
hour
'
user_id
?:
number
api_key_id
?:
number
}
export
interface
TrendResponse
{
trend
:
TrendDataPoint
[]
;
start_date
:
string
;
end_date
:
string
;
granularity
:
string
;
trend
:
TrendDataPoint
[]
start_date
:
string
end_date
:
string
granularity
:
string
}
/**
...
...
@@ -55,21 +61,21 @@ export interface TrendResponse {
* @returns Usage trend data
*/
export
async
function
getUsageTrend
(
params
?:
TrendParams
):
Promise
<
TrendResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
TrendResponse
>
(
'
/admin/dashboard/trend
'
,
{
params
})
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
TrendResponse
>
(
'
/admin/dashboard/trend
'
,
{
params
})
return
data
}
export
interface
ModelStatsParams
{
start_date
?:
string
;
end_date
?:
string
;
user_id
?:
number
;
api_key_id
?:
number
;
start_date
?:
string
end_date
?:
string
user_id
?:
number
api_key_id
?:
number
}
export
interface
ModelStatsResponse
{
models
:
ModelStat
[]
;
start_date
:
string
;
end_date
:
string
;
models
:
ModelStat
[]
start_date
:
string
end_date
:
string
}
/**
...
...
@@ -78,19 +84,19 @@ export interface ModelStatsResponse {
* @returns Model usage statistics
*/
export
async
function
getModelStats
(
params
?:
ModelStatsParams
):
Promise
<
ModelStatsResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
ModelStatsResponse
>
(
'
/admin/dashboard/models
'
,
{
params
})
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
ModelStatsResponse
>
(
'
/admin/dashboard/models
'
,
{
params
})
return
data
}
export
interface
ApiKeyTrendParams
extends
TrendParams
{
limit
?:
number
;
limit
?:
number
}
export
interface
ApiKeyTrendResponse
{
trend
:
ApiKeyUsageTrendPoint
[]
;
start_date
:
string
;
end_date
:
string
;
granularity
:
string
;
trend
:
ApiKeyUsageTrendPoint
[]
start_date
:
string
end_date
:
string
granularity
:
string
}
/**
...
...
@@ -98,20 +104,24 @@ export interface ApiKeyTrendResponse {
* @param params - Query parameters for filtering
* @returns API key usage trend data
*/
export
async
function
getApiKeyUsageTrend
(
params
?:
ApiKeyTrendParams
):
Promise
<
ApiKeyTrendResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
ApiKeyTrendResponse
>
(
'
/admin/dashboard/api-keys-trend
'
,
{
params
});
return
data
;
export
async
function
getApiKeyUsageTrend
(
params
?:
ApiKeyTrendParams
):
Promise
<
ApiKeyTrendResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
ApiKeyTrendResponse
>
(
'
/admin/dashboard/api-keys-trend
'
,
{
params
})
return
data
}
export
interface
UserTrendParams
extends
TrendParams
{
limit
?:
number
;
limit
?:
number
}
export
interface
UserTrendResponse
{
trend
:
UserUsageTrendPoint
[]
;
start_date
:
string
;
end_date
:
string
;
granularity
:
string
;
trend
:
UserUsageTrendPoint
[]
start_date
:
string
end_date
:
string
granularity
:
string
}
/**
...
...
@@ -120,18 +130,20 @@ export interface UserTrendResponse {
* @returns User usage trend data
*/
export
async
function
getUserUsageTrend
(
params
?:
UserTrendParams
):
Promise
<
UserTrendResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
UserTrendResponse
>
(
'
/admin/dashboard/users-trend
'
,
{
params
});
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
UserTrendResponse
>
(
'
/admin/dashboard/users-trend
'
,
{
params
})
return
data
}
export
interface
BatchUserUsageStats
{
user_id
:
number
;
today_actual_cost
:
number
;
total_actual_cost
:
number
;
user_id
:
number
today_actual_cost
:
number
total_actual_cost
:
number
}
export
interface
BatchUsersUsageResponse
{
stats
:
Record
<
string
,
BatchUserUsageStats
>
;
stats
:
Record
<
string
,
BatchUserUsageStats
>
}
/**
...
...
@@ -141,19 +153,19 @@ export interface BatchUsersUsageResponse {
*/
export
async
function
getBatchUsersUsage
(
userIds
:
number
[]):
Promise
<
BatchUsersUsageResponse
>
{
const
{
data
}
=
await
apiClient
.
post
<
BatchUsersUsageResponse
>
(
'
/admin/dashboard/users-usage
'
,
{
user_ids
:
userIds
,
})
;
return
data
;
user_ids
:
userIds
})
return
data
}
export
interface
BatchApiKeyUsageStats
{
api_key_id
:
number
;
today_actual_cost
:
number
;
total_actual_cost
:
number
;
api_key_id
:
number
today_actual_cost
:
number
total_actual_cost
:
number
}
export
interface
BatchApiKeysUsageResponse
{
stats
:
Record
<
string
,
BatchApiKeyUsageStats
>
;
stats
:
Record
<
string
,
BatchApiKeyUsageStats
>
}
/**
...
...
@@ -161,11 +173,16 @@ export interface BatchApiKeysUsageResponse {
* @param apiKeyIds - Array of API key IDs
* @returns Usage stats map keyed by API key ID
*/
export
async
function
getBatchApiKeysUsage
(
apiKeyIds
:
number
[]):
Promise
<
BatchApiKeysUsageResponse
>
{
const
{
data
}
=
await
apiClient
.
post
<
BatchApiKeysUsageResponse
>
(
'
/admin/dashboard/api-keys-usage
'
,
{
api_key_ids
:
apiKeyIds
,
});
return
data
;
export
async
function
getBatchApiKeysUsage
(
apiKeyIds
:
number
[]
):
Promise
<
BatchApiKeysUsageResponse
>
{
const
{
data
}
=
await
apiClient
.
post
<
BatchApiKeysUsageResponse
>
(
'
/admin/dashboard/api-keys-usage
'
,
{
api_key_ids
:
apiKeyIds
}
)
return
data
}
export
const
dashboardAPI
=
{
...
...
@@ -176,7 +193,7 @@ export const dashboardAPI = {
getApiKeyUsageTrend
,
getUserUsageTrend
,
getBatchUsersUsage
,
getBatchApiKeysUsage
,
}
;
getBatchApiKeysUsage
}
export
default
dashboardAPI
;
export
default
dashboardAPI
frontend/src/api/admin/groups.ts
View file @
f79b0f0f
...
...
@@ -3,14 +3,14 @@
* Handles API key group management for administrators
*/
import
{
apiClient
}
from
'
../client
'
;
import
{
apiClient
}
from
'
../client
'
import
type
{
Group
,
GroupPlatform
,
CreateGroupRequest
,
UpdateGroupRequest
,
PaginatedResponse
,
}
from
'
@/types
'
;
PaginatedResponse
}
from
'
@/types
'
/**
* List all groups with pagination
...
...
@@ -23,19 +23,19 @@ export async function list(
page
:
number
=
1
,
pageSize
:
number
=
20
,
filters
?:
{
platform
?:
GroupPlatform
;
status
?:
'
active
'
|
'
inactive
'
;
is_exclusive
?:
boolean
;
platform
?:
GroupPlatform
status
?:
'
active
'
|
'
inactive
'
is_exclusive
?:
boolean
}
):
Promise
<
PaginatedResponse
<
Group
>>
{
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
Group
>>
(
'
/admin/groups
'
,
{
params
:
{
page
,
page_size
:
pageSize
,
...
filters
,
}
,
})
;
return
data
;
...
filters
}
})
return
data
}
/**
...
...
@@ -46,8 +46,8 @@ export async function list(
export
async
function
getAll
(
platform
?:
GroupPlatform
):
Promise
<
Group
[]
>
{
const
{
data
}
=
await
apiClient
.
get
<
Group
[]
>
(
'
/admin/groups/all
'
,
{
params
:
platform
?
{
platform
}
:
undefined
})
;
return
data
;
})
return
data
}
/**
...
...
@@ -56,7 +56,7 @@ export async function getAll(platform?: GroupPlatform): Promise<Group[]> {
* @returns List of groups for the specified platform
*/
export
async
function
getByPlatform
(
platform
:
GroupPlatform
):
Promise
<
Group
[]
>
{
return
getAll
(
platform
)
;
return
getAll
(
platform
)
}
/**
...
...
@@ -65,8 +65,8 @@ export async function getByPlatform(platform: GroupPlatform): Promise<Group[]> {
* @returns Group details
*/
export
async
function
getById
(
id
:
number
):
Promise
<
Group
>
{
const
{
data
}
=
await
apiClient
.
get
<
Group
>
(
`/admin/groups/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
Group
>
(
`/admin/groups/
${
id
}
`
)
return
data
}
/**
...
...
@@ -75,8 +75,8 @@ export async function getById(id: number): Promise<Group> {
* @returns Created group
*/
export
async
function
create
(
groupData
:
CreateGroupRequest
):
Promise
<
Group
>
{
const
{
data
}
=
await
apiClient
.
post
<
Group
>
(
'
/admin/groups
'
,
groupData
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
post
<
Group
>
(
'
/admin/groups
'
,
groupData
)
return
data
}
/**
...
...
@@ -86,8 +86,8 @@ export async function create(groupData: CreateGroupRequest): Promise<Group> {
* @returns Updated group
*/
export
async
function
update
(
id
:
number
,
updates
:
UpdateGroupRequest
):
Promise
<
Group
>
{
const
{
data
}
=
await
apiClient
.
put
<
Group
>
(
`/admin/groups/
${
id
}
`
,
updates
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
put
<
Group
>
(
`/admin/groups/
${
id
}
`
,
updates
)
return
data
}
/**
...
...
@@ -96,8 +96,8 @@ export async function update(id: number, updates: UpdateGroupRequest): Promise<G
* @returns Success confirmation
*/
export
async
function
deleteGroup
(
id
:
number
):
Promise
<
{
message
:
string
}
>
{
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/admin/groups/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/admin/groups/
${
id
}
`
)
return
data
}
/**
...
...
@@ -106,11 +106,8 @@ export async function deleteGroup(id: number): Promise<{ message: string }> {
* @param status - New status
* @returns Updated group
*/
export
async
function
toggleStatus
(
id
:
number
,
status
:
'
active
'
|
'
inactive
'
):
Promise
<
Group
>
{
return
update
(
id
,
{
status
});
export
async
function
toggleStatus
(
id
:
number
,
status
:
'
active
'
|
'
inactive
'
):
Promise
<
Group
>
{
return
update
(
id
,
{
status
})
}
/**
...
...
@@ -119,18 +116,18 @@ export async function toggleStatus(
* @returns Group usage statistics
*/
export
async
function
getStats
(
id
:
number
):
Promise
<
{
total_api_keys
:
number
;
active_api_keys
:
number
;
total_requests
:
number
;
total_cost
:
number
;
total_api_keys
:
number
active_api_keys
:
number
total_requests
:
number
total_cost
:
number
}
>
{
const
{
data
}
=
await
apiClient
.
get
<
{
total_api_keys
:
number
;
active_api_keys
:
number
;
total_requests
:
number
;
total_cost
:
number
;
}
>
(
`/admin/groups/
${
id
}
/stats`
)
;
return
data
;
total_api_keys
:
number
active_api_keys
:
number
total_requests
:
number
total_cost
:
number
}
>
(
`/admin/groups/
${
id
}
/stats`
)
return
data
}
/**
...
...
@@ -145,13 +142,10 @@ export async function getGroupApiKeys(
page
:
number
=
1
,
pageSize
:
number
=
20
):
Promise
<
PaginatedResponse
<
any
>>
{
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
any
>>
(
`/admin/groups/
${
id
}
/api-keys`
,
{
params
:
{
page
,
page_size
:
pageSize
},
}
);
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
any
>>
(
`/admin/groups/
${
id
}
/api-keys`
,
{
params
:
{
page
,
page_size
:
pageSize
}
})
return
data
}
export
const
groupsAPI
=
{
...
...
@@ -164,7 +158,7 @@ export const groupsAPI = {
delete
:
deleteGroup
,
toggleStatus
,
getStats
,
getGroupApiKeys
,
}
;
getGroupApiKeys
}
export
default
groupsAPI
;
export
default
groupsAPI
frontend/src/api/admin/index.ts
View file @
f79b0f0f
...
...
@@ -3,16 +3,17 @@
* Centralized exports for all admin API modules
*/
import
dashboardAPI
from
'
./dashboard
'
;
import
usersAPI
from
'
./users
'
;
import
groupsAPI
from
'
./groups
'
;
import
accountsAPI
from
'
./accounts
'
;
import
proxiesAPI
from
'
./proxies
'
;
import
redeemAPI
from
'
./redeem
'
;
import
settingsAPI
from
'
./settings
'
;
import
systemAPI
from
'
./system
'
;
import
subscriptionsAPI
from
'
./subscriptions
'
;
import
usageAPI
from
'
./usage
'
;
import
dashboardAPI
from
'
./dashboard
'
import
usersAPI
from
'
./users
'
import
groupsAPI
from
'
./groups
'
import
accountsAPI
from
'
./accounts
'
import
proxiesAPI
from
'
./proxies
'
import
redeemAPI
from
'
./redeem
'
import
settingsAPI
from
'
./settings
'
import
systemAPI
from
'
./system
'
import
subscriptionsAPI
from
'
./subscriptions
'
import
usageAPI
from
'
./usage
'
import
geminiAPI
from
'
./gemini
'
/**
* Unified admin API object for convenient access
...
...
@@ -28,8 +29,21 @@ export const adminAPI = {
system
:
systemAPI
,
subscriptions
:
subscriptionsAPI
,
usage
:
usageAPI
,
};
gemini
:
geminiAPI
}
export
{
dashboardAPI
,
usersAPI
,
groupsAPI
,
accountsAPI
,
proxiesAPI
,
redeemAPI
,
settingsAPI
,
systemAPI
,
subscriptionsAPI
,
usageAPI
};
export
{
dashboardAPI
,
usersAPI
,
groupsAPI
,
accountsAPI
,
proxiesAPI
,
redeemAPI
,
settingsAPI
,
systemAPI
,
subscriptionsAPI
,
usageAPI
,
geminiAPI
}
export
default
adminAPI
;
export
default
adminAPI
frontend/src/api/admin/proxies.ts
View file @
f79b0f0f
...
...
@@ -3,13 +3,8 @@
* Handles proxy server management for administrators
*/
import
{
apiClient
}
from
'
../client
'
;
import
type
{
Proxy
,
CreateProxyRequest
,
UpdateProxyRequest
,
PaginatedResponse
,
}
from
'
@/types
'
;
import
{
apiClient
}
from
'
../client
'
import
type
{
Proxy
,
CreateProxyRequest
,
UpdateProxyRequest
,
PaginatedResponse
}
from
'
@/types
'
/**
* List all proxies with pagination
...
...
@@ -22,19 +17,19 @@ export async function list(
page
:
number
=
1
,
pageSize
:
number
=
20
,
filters
?:
{
protocol
?:
string
;
status
?:
'
active
'
|
'
inactive
'
;
search
?:
string
;
protocol
?:
string
status
?:
'
active
'
|
'
inactive
'
search
?:
string
}
):
Promise
<
PaginatedResponse
<
Proxy
>>
{
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
Proxy
>>
(
'
/admin/proxies
'
,
{
params
:
{
page
,
page_size
:
pageSize
,
...
filters
,
}
,
})
;
return
data
;
...
filters
}
})
return
data
}
/**
...
...
@@ -42,8 +37,8 @@ export async function list(
* @returns List of all active proxies
*/
export
async
function
getAll
():
Promise
<
Proxy
[]
>
{
const
{
data
}
=
await
apiClient
.
get
<
Proxy
[]
>
(
'
/admin/proxies/all
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
Proxy
[]
>
(
'
/admin/proxies/all
'
)
return
data
}
/**
...
...
@@ -52,9 +47,9 @@ export async function getAll(): Promise<Proxy[]> {
*/
export
async
function
getAllWithCount
():
Promise
<
Proxy
[]
>
{
const
{
data
}
=
await
apiClient
.
get
<
Proxy
[]
>
(
'
/admin/proxies/all
'
,
{
params
:
{
with_count
:
'
true
'
}
,
})
;
return
data
;
params
:
{
with_count
:
'
true
'
}
})
return
data
}
/**
...
...
@@ -63,8 +58,8 @@ export async function getAllWithCount(): Promise<Proxy[]> {
* @returns Proxy details
*/
export
async
function
getById
(
id
:
number
):
Promise
<
Proxy
>
{
const
{
data
}
=
await
apiClient
.
get
<
Proxy
>
(
`/admin/proxies/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
Proxy
>
(
`/admin/proxies/
${
id
}
`
)
return
data
}
/**
...
...
@@ -73,8 +68,8 @@ export async function getById(id: number): Promise<Proxy> {
* @returns Created proxy
*/
export
async
function
create
(
proxyData
:
CreateProxyRequest
):
Promise
<
Proxy
>
{
const
{
data
}
=
await
apiClient
.
post
<
Proxy
>
(
'
/admin/proxies
'
,
proxyData
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
post
<
Proxy
>
(
'
/admin/proxies
'
,
proxyData
)
return
data
}
/**
...
...
@@ -84,8 +79,8 @@ export async function create(proxyData: CreateProxyRequest): Promise<Proxy> {
* @returns Updated proxy
*/
export
async
function
update
(
id
:
number
,
updates
:
UpdateProxyRequest
):
Promise
<
Proxy
>
{
const
{
data
}
=
await
apiClient
.
put
<
Proxy
>
(
`/admin/proxies/
${
id
}
`
,
updates
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
put
<
Proxy
>
(
`/admin/proxies/
${
id
}
`
,
updates
)
return
data
}
/**
...
...
@@ -94,8 +89,8 @@ export async function update(id: number, updates: UpdateProxyRequest): Promise<P
* @returns Success confirmation
*/
export
async
function
deleteProxy
(
id
:
number
):
Promise
<
{
message
:
string
}
>
{
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/admin/proxies/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/admin/proxies/
${
id
}
`
)
return
data
}
/**
...
...
@@ -104,11 +99,8 @@ export async function deleteProxy(id: number): Promise<{ message: string }> {
* @param status - New status
* @returns Updated proxy
*/
export
async
function
toggleStatus
(
id
:
number
,
status
:
'
active
'
|
'
inactive
'
):
Promise
<
Proxy
>
{
return
update
(
id
,
{
status
});
export
async
function
toggleStatus
(
id
:
number
,
status
:
'
active
'
|
'
inactive
'
):
Promise
<
Proxy
>
{
return
update
(
id
,
{
status
})
}
/**
...
...
@@ -117,24 +109,24 @@ export async function toggleStatus(
* @returns Test result with IP info
*/
export
async
function
testProxy
(
id
:
number
):
Promise
<
{
success
:
boolean
;
message
:
string
;
latency_ms
?:
number
;
ip_address
?:
string
;
city
?:
string
;
region
?:
string
;
country
?:
string
;
success
:
boolean
message
:
string
latency_ms
?:
number
ip_address
?:
string
city
?:
string
region
?:
string
country
?:
string
}
>
{
const
{
data
}
=
await
apiClient
.
post
<
{
success
:
boolean
;
message
:
string
;
latency_ms
?:
number
;
ip_address
?:
string
;
city
?:
string
;
region
?:
string
;
country
?:
string
;
}
>
(
`/admin/proxies/
${
id
}
/test`
)
;
return
data
;
success
:
boolean
message
:
string
latency_ms
?:
number
ip_address
?:
string
city
?:
string
region
?:
string
country
?:
string
}
>
(
`/admin/proxies/
${
id
}
/test`
)
return
data
}
/**
...
...
@@ -143,20 +135,20 @@ export async function testProxy(id: number): Promise<{
* @returns Proxy usage statistics
*/
export
async
function
getStats
(
id
:
number
):
Promise
<
{
total_accounts
:
number
;
active_accounts
:
number
;
total_requests
:
number
;
success_rate
:
number
;
average_latency
:
number
;
total_accounts
:
number
active_accounts
:
number
total_requests
:
number
success_rate
:
number
average_latency
:
number
}
>
{
const
{
data
}
=
await
apiClient
.
get
<
{
total_accounts
:
number
;
active_accounts
:
number
;
total_requests
:
number
;
success_rate
:
number
;
average_latency
:
number
;
}
>
(
`/admin/proxies/
${
id
}
/stats`
)
;
return
data
;
total_accounts
:
number
active_accounts
:
number
total_requests
:
number
success_rate
:
number
average_latency
:
number
}
>
(
`/admin/proxies/
${
id
}
/stats`
)
return
data
}
/**
...
...
@@ -165,10 +157,8 @@ export async function getStats(id: number): Promise<{
* @returns List of accounts using the proxy
*/
export
async
function
getProxyAccounts
(
id
:
number
):
Promise
<
PaginatedResponse
<
any
>>
{
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
any
>>
(
`/admin/proxies/
${
id
}
/accounts`
);
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
any
>>
(
`/admin/proxies/
${
id
}
/accounts`
)
return
data
}
/**
...
...
@@ -176,21 +166,23 @@ export async function getProxyAccounts(id: number): Promise<PaginatedResponse<an
* @param proxies - Array of proxy data to create
* @returns Creation result with count of created and skipped
*/
export
async
function
batchCreate
(
proxies
:
Array
<
{
protocol
:
string
;
host
:
string
;
port
:
number
;
username
?:
string
;
password
?:
string
;
}
>
):
Promise
<
{
created
:
number
;
skipped
:
number
;
export
async
function
batchCreate
(
proxies
:
Array
<
{
protocol
:
string
host
:
string
port
:
number
username
?:
string
password
?:
string
}
>
):
Promise
<
{
created
:
number
skipped
:
number
}
>
{
const
{
data
}
=
await
apiClient
.
post
<
{
created
:
number
;
skipped
:
number
;
}
>
(
'
/admin/proxies/batch
'
,
{
proxies
})
;
return
data
;
created
:
number
skipped
:
number
}
>
(
'
/admin/proxies/batch
'
,
{
proxies
})
return
data
}
export
const
proxiesAPI
=
{
...
...
@@ -205,7 +197,7 @@ export const proxiesAPI = {
testProxy
,
getStats
,
getProxyAccounts
,
batchCreate
,
}
;
batchCreate
}
export
default
proxiesAPI
;
export
default
proxiesAPI
frontend/src/api/admin/redeem.ts
View file @
f79b0f0f
...
...
@@ -3,13 +3,13 @@
* Handles redeem code generation and management for administrators
*/
import
{
apiClient
}
from
'
../client
'
;
import
{
apiClient
}
from
'
../client
'
import
type
{
RedeemCode
,
GenerateRedeemCodesRequest
,
RedeemCodeType
,
PaginatedResponse
,
}
from
'
@/types
'
;
PaginatedResponse
}
from
'
@/types
'
/**
* List all redeem codes with pagination
...
...
@@ -22,19 +22,19 @@ export async function list(
page
:
number
=
1
,
pageSize
:
number
=
20
,
filters
?:
{
type
?:
RedeemCodeType
;
status
?:
'
active
'
|
'
used
'
|
'
expired
'
|
'
unused
'
;
search
?:
string
;
type
?:
RedeemCodeType
status
?:
'
active
'
|
'
used
'
|
'
expired
'
|
'
unused
'
search
?:
string
}
):
Promise
<
PaginatedResponse
<
RedeemCode
>>
{
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
RedeemCode
>>
(
'
/admin/redeem-codes
'
,
{
params
:
{
page
,
page_size
:
pageSize
,
...
filters
,
}
,
})
;
return
data
;
...
filters
}
})
return
data
}
/**
...
...
@@ -43,8 +43,8 @@ export async function list(
* @returns Redeem code details
*/
export
async
function
getById
(
id
:
number
):
Promise
<
RedeemCode
>
{
const
{
data
}
=
await
apiClient
.
get
<
RedeemCode
>
(
`/admin/redeem-codes/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
RedeemCode
>
(
`/admin/redeem-codes/
${
id
}
`
)
return
data
}
/**
...
...
@@ -66,19 +66,19 @@ export async function generate(
const
payload
:
GenerateRedeemCodesRequest
=
{
count
,
type
,
value
,
}
;
value
}
// 订阅类型专用字段
if
(
type
===
'
subscription
'
)
{
payload
.
group_id
=
groupId
;
payload
.
group_id
=
groupId
if
(
validityDays
&&
validityDays
>
0
)
{
payload
.
validity_days
=
validityDays
;
payload
.
validity_days
=
validityDays
}
}
const
{
data
}
=
await
apiClient
.
post
<
RedeemCode
[]
>
(
'
/admin/redeem-codes/generate
'
,
payload
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
post
<
RedeemCode
[]
>
(
'
/admin/redeem-codes/generate
'
,
payload
)
return
data
}
/**
...
...
@@ -87,8 +87,8 @@ export async function generate(
* @returns Success confirmation
*/
export
async
function
deleteCode
(
id
:
number
):
Promise
<
{
message
:
string
}
>
{
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/admin/redeem-codes/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/admin/redeem-codes/
${
id
}
`
)
return
data
}
/**
...
...
@@ -97,14 +97,14 @@ export async function deleteCode(id: number): Promise<{ message: string }> {
* @returns Success confirmation
*/
export
async
function
batchDelete
(
ids
:
number
[]):
Promise
<
{
deleted
:
number
;
message
:
string
;
deleted
:
number
message
:
string
}
>
{
const
{
data
}
=
await
apiClient
.
post
<
{
deleted
:
number
;
message
:
string
;
}
>
(
'
/admin/redeem-codes/batch-delete
'
,
{
ids
})
;
return
data
;
deleted
:
number
message
:
string
}
>
(
'
/admin/redeem-codes/batch-delete
'
,
{
ids
})
return
data
}
/**
...
...
@@ -113,8 +113,8 @@ export async function batchDelete(ids: number[]): Promise<{
* @returns Updated redeem code
*/
export
async
function
expire
(
id
:
number
):
Promise
<
RedeemCode
>
{
const
{
data
}
=
await
apiClient
.
post
<
RedeemCode
>
(
`/admin/redeem-codes/
${
id
}
/expire`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
post
<
RedeemCode
>
(
`/admin/redeem-codes/
${
id
}
/expire`
)
return
data
}
/**
...
...
@@ -122,22 +122,22 @@ export async function expire(id: number): Promise<RedeemCode> {
* @returns Statistics about redeem codes
*/
export
async
function
getStats
():
Promise
<
{
total_codes
:
number
;
active_codes
:
number
;
used_codes
:
number
;
expired_codes
:
number
;
total_value_distributed
:
number
;
by_type
:
Record
<
RedeemCodeType
,
number
>
;
total_codes
:
number
active_codes
:
number
used_codes
:
number
expired_codes
:
number
total_value_distributed
:
number
by_type
:
Record
<
RedeemCodeType
,
number
>
}
>
{
const
{
data
}
=
await
apiClient
.
get
<
{
total_codes
:
number
;
active_codes
:
number
;
used_codes
:
number
;
expired_codes
:
number
;
total_value_distributed
:
number
;
by_type
:
Record
<
RedeemCodeType
,
number
>
;
}
>
(
'
/admin/redeem-codes/stats
'
)
;
return
data
;
total_codes
:
number
active_codes
:
number
used_codes
:
number
expired_codes
:
number
total_value_distributed
:
number
by_type
:
Record
<
RedeemCodeType
,
number
>
}
>
(
'
/admin/redeem-codes/stats
'
)
return
data
}
/**
...
...
@@ -146,14 +146,14 @@ export async function getStats(): Promise<{
* @returns CSV data as blob
*/
export
async
function
exportCodes
(
filters
?:
{
type
?:
RedeemCodeType
;
status
?:
'
active
'
|
'
used
'
|
'
expired
'
;
type
?:
RedeemCodeType
status
?:
'
active
'
|
'
used
'
|
'
expired
'
}):
Promise
<
Blob
>
{
const
response
=
await
apiClient
.
get
(
'
/admin/redeem-codes/export
'
,
{
params
:
filters
,
responseType
:
'
blob
'
,
})
;
return
response
.
data
;
responseType
:
'
blob
'
})
return
response
.
data
}
export
const
redeemAPI
=
{
...
...
@@ -164,7 +164,7 @@ export const redeemAPI = {
batchDelete
,
expire
,
getStats
,
exportCodes
,
}
;
exportCodes
}
export
default
redeemAPI
;
export
default
redeemAPI
frontend/src/api/admin/settings.ts
View file @
f79b0f0f
...
...
@@ -3,37 +3,37 @@
* Handles system settings management for administrators
*/
import
{
apiClient
}
from
'
../client
'
;
import
{
apiClient
}
from
'
../client
'
/**
* System settings interface
*/
export
interface
SystemSettings
{
// Registration settings
registration_enabled
:
boolean
;
email_verify_enabled
:
boolean
;
registration_enabled
:
boolean
email_verify_enabled
:
boolean
// Default settings
default_balance
:
number
;
default_concurrency
:
number
;
default_balance
:
number
default_concurrency
:
number
// OEM settings
site_name
:
string
;
site_logo
:
string
;
site_subtitle
:
string
;
api_base_url
:
string
;
contact_info
:
string
;
doc_url
:
string
;
site_name
:
string
site_logo
:
string
site_subtitle
:
string
api_base_url
:
string
contact_info
:
string
doc_url
:
string
// SMTP settings
smtp_host
:
string
;
smtp_port
:
number
;
smtp_username
:
string
;
smtp_password
:
string
;
smtp_from_email
:
string
;
smtp_from_name
:
string
;
smtp_use_tls
:
boolean
;
smtp_host
:
string
smtp_port
:
number
smtp_username
:
string
smtp_password
:
string
smtp_from_email
:
string
smtp_from_name
:
string
smtp_use_tls
:
boolean
// Cloudflare Turnstile settings
turnstile_enabled
:
boolean
;
turnstile_site_key
:
string
;
turnstile_secret_key
:
string
;
turnstile_enabled
:
boolean
turnstile_site_key
:
string
turnstile_secret_key
:
string
}
/**
...
...
@@ -41,8 +41,8 @@ export interface SystemSettings {
* @returns System settings
*/
export
async
function
getSettings
():
Promise
<
SystemSettings
>
{
const
{
data
}
=
await
apiClient
.
get
<
SystemSettings
>
(
'
/admin/settings
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
SystemSettings
>
(
'
/admin/settings
'
)
return
data
}
/**
...
...
@@ -51,19 +51,19 @@ export async function getSettings(): Promise<SystemSettings> {
* @returns Updated settings
*/
export
async
function
updateSettings
(
settings
:
Partial
<
SystemSettings
>
):
Promise
<
SystemSettings
>
{
const
{
data
}
=
await
apiClient
.
put
<
SystemSettings
>
(
'
/admin/settings
'
,
settings
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
put
<
SystemSettings
>
(
'
/admin/settings
'
,
settings
)
return
data
}
/**
* Test SMTP connection request
*/
export
interface
TestSmtpRequest
{
smtp_host
:
string
;
smtp_port
:
number
;
smtp_username
:
string
;
smtp_password
:
string
;
smtp_use_tls
:
boolean
;
smtp_host
:
string
smtp_port
:
number
smtp_username
:
string
smtp_password
:
string
smtp_use_tls
:
boolean
}
/**
...
...
@@ -72,22 +72,22 @@ export interface TestSmtpRequest {
* @returns Test result message
*/
export
async
function
testSmtpConnection
(
config
:
TestSmtpRequest
):
Promise
<
{
message
:
string
}
>
{
const
{
data
}
=
await
apiClient
.
post
<
{
message
:
string
}
>
(
'
/admin/settings/test-smtp
'
,
config
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
post
<
{
message
:
string
}
>
(
'
/admin/settings/test-smtp
'
,
config
)
return
data
}
/**
* Send test email request
*/
export
interface
SendTestEmailRequest
{
email
:
string
;
smtp_host
:
string
;
smtp_port
:
number
;
smtp_username
:
string
;
smtp_password
:
string
;
smtp_from_email
:
string
;
smtp_from_name
:
string
;
smtp_use_tls
:
boolean
;
email
:
string
smtp_host
:
string
smtp_port
:
number
smtp_username
:
string
smtp_password
:
string
smtp_from_email
:
string
smtp_from_name
:
string
smtp_use_tls
:
boolean
}
/**
...
...
@@ -96,16 +96,19 @@ export interface SendTestEmailRequest {
* @returns Test result message
*/
export
async
function
sendTestEmail
(
request
:
SendTestEmailRequest
):
Promise
<
{
message
:
string
}
>
{
const
{
data
}
=
await
apiClient
.
post
<
{
message
:
string
}
>
(
'
/admin/settings/send-test-email
'
,
request
);
return
data
;
const
{
data
}
=
await
apiClient
.
post
<
{
message
:
string
}
>
(
'
/admin/settings/send-test-email
'
,
request
)
return
data
}
/**
* Admin API Key status response
*/
export
interface
AdminApiKeyStatus
{
exists
:
boolean
;
masked_key
:
string
;
exists
:
boolean
masked_key
:
string
}
/**
...
...
@@ -113,8 +116,8 @@ export interface AdminApiKeyStatus {
* @returns Status indicating if key exists and masked version
*/
export
async
function
getAdminApiKey
():
Promise
<
AdminApiKeyStatus
>
{
const
{
data
}
=
await
apiClient
.
get
<
AdminApiKeyStatus
>
(
'
/admin/settings/admin-api-key
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
AdminApiKeyStatus
>
(
'
/admin/settings/admin-api-key
'
)
return
data
}
/**
...
...
@@ -122,8 +125,8 @@ export async function getAdminApiKey(): Promise<AdminApiKeyStatus> {
* @returns The new full API key (only shown once)
*/
export
async
function
regenerateAdminApiKey
():
Promise
<
{
key
:
string
}
>
{
const
{
data
}
=
await
apiClient
.
post
<
{
key
:
string
}
>
(
'
/admin/settings/admin-api-key/regenerate
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
post
<
{
key
:
string
}
>
(
'
/admin/settings/admin-api-key/regenerate
'
)
return
data
}
/**
...
...
@@ -131,8 +134,8 @@ export async function regenerateAdminApiKey(): Promise<{ key: string }> {
* @returns Success message
*/
export
async
function
deleteAdminApiKey
():
Promise
<
{
message
:
string
}
>
{
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
'
/admin/settings/admin-api-key
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
'
/admin/settings/admin-api-key
'
)
return
data
}
export
const
settingsAPI
=
{
...
...
@@ -142,7 +145,7 @@ export const settingsAPI = {
sendTestEmail
,
getAdminApiKey
,
regenerateAdminApiKey
,
deleteAdminApiKey
,
}
;
deleteAdminApiKey
}
export
default
settingsAPI
;
export
default
settingsAPI
frontend/src/api/admin/subscriptions.ts
View file @
f79b0f0f
...
...
@@ -3,15 +3,15 @@
* Handles user subscription management for administrators
*/
import
{
apiClient
}
from
'
../client
'
;
import
{
apiClient
}
from
'
../client
'
import
type
{
UserSubscription
,
SubscriptionProgress
,
AssignSubscriptionRequest
,
BulkAssignSubscriptionRequest
,
ExtendSubscriptionRequest
,
PaginatedResponse
,
}
from
'
@/types
'
;
PaginatedResponse
}
from
'
@/types
'
/**
* List all subscriptions with pagination
...
...
@@ -24,19 +24,22 @@ export async function list(
page
:
number
=
1
,
pageSize
:
number
=
20
,
filters
?:
{
status
?:
'
active
'
|
'
expired
'
|
'
revoked
'
;
user_id
?:
number
;
group_id
?:
number
;
status
?:
'
active
'
|
'
expired
'
|
'
revoked
'
user_id
?:
number
group_id
?:
number
}
):
Promise
<
PaginatedResponse
<
UserSubscription
>>
{
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
UserSubscription
>>
(
'
/admin/subscriptions
'
,
{
params
:
{
page
,
page_size
:
pageSize
,
...
filters
,
},
});
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
UserSubscription
>>
(
'
/admin/subscriptions
'
,
{
params
:
{
page
,
page_size
:
pageSize
,
...
filters
}
}
)
return
data
}
/**
...
...
@@ -45,8 +48,8 @@ export async function list(
* @returns Subscription details
*/
export
async
function
getById
(
id
:
number
):
Promise
<
UserSubscription
>
{
const
{
data
}
=
await
apiClient
.
get
<
UserSubscription
>
(
`/admin/subscriptions/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
UserSubscription
>
(
`/admin/subscriptions/
${
id
}
`
)
return
data
}
/**
...
...
@@ -55,8 +58,8 @@ export async function getById(id: number): Promise<UserSubscription> {
* @returns Subscription progress with usage stats
*/
export
async
function
getProgress
(
id
:
number
):
Promise
<
SubscriptionProgress
>
{
const
{
data
}
=
await
apiClient
.
get
<
SubscriptionProgress
>
(
`/admin/subscriptions/
${
id
}
/progress`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
SubscriptionProgress
>
(
`/admin/subscriptions/
${
id
}
/progress`
)
return
data
}
/**
...
...
@@ -65,8 +68,8 @@ export async function getProgress(id: number): Promise<SubscriptionProgress> {
* @returns Created subscription
*/
export
async
function
assign
(
request
:
AssignSubscriptionRequest
):
Promise
<
UserSubscription
>
{
const
{
data
}
=
await
apiClient
.
post
<
UserSubscription
>
(
'
/admin/subscriptions/assign
'
,
request
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
post
<
UserSubscription
>
(
'
/admin/subscriptions/assign
'
,
request
)
return
data
}
/**
...
...
@@ -74,9 +77,14 @@ export async function assign(request: AssignSubscriptionRequest): Promise<UserSu
* @param request - Bulk assignment request
* @returns Created subscriptions
*/
export
async
function
bulkAssign
(
request
:
BulkAssignSubscriptionRequest
):
Promise
<
UserSubscription
[]
>
{
const
{
data
}
=
await
apiClient
.
post
<
UserSubscription
[]
>
(
'
/admin/subscriptions/bulk-assign
'
,
request
);
return
data
;
export
async
function
bulkAssign
(
request
:
BulkAssignSubscriptionRequest
):
Promise
<
UserSubscription
[]
>
{
const
{
data
}
=
await
apiClient
.
post
<
UserSubscription
[]
>
(
'
/admin/subscriptions/bulk-assign
'
,
request
)
return
data
}
/**
...
...
@@ -85,9 +93,15 @@ export async function bulkAssign(request: BulkAssignSubscriptionRequest): Promis
* @param request - Extension request with days
* @returns Updated subscription
*/
export
async
function
extend
(
id
:
number
,
request
:
ExtendSubscriptionRequest
):
Promise
<
UserSubscription
>
{
const
{
data
}
=
await
apiClient
.
post
<
UserSubscription
>
(
`/admin/subscriptions/
${
id
}
/extend`
,
request
);
return
data
;
export
async
function
extend
(
id
:
number
,
request
:
ExtendSubscriptionRequest
):
Promise
<
UserSubscription
>
{
const
{
data
}
=
await
apiClient
.
post
<
UserSubscription
>
(
`/admin/subscriptions/
${
id
}
/extend`
,
request
)
return
data
}
/**
...
...
@@ -96,8 +110,8 @@ export async function extend(id: number, request: ExtendSubscriptionRequest): Pr
* @returns Success confirmation
*/
export
async
function
revoke
(
id
:
number
):
Promise
<
{
message
:
string
}
>
{
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/admin/subscriptions/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/admin/subscriptions/
${
id
}
`
)
return
data
}
/**
...
...
@@ -115,10 +129,10 @@ export async function listByGroup(
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
UserSubscription
>>
(
`/admin/groups/
${
groupId
}
/subscriptions`
,
{
params
:
{
page
,
page_size
:
pageSize
}
,
params
:
{
page
,
page_size
:
pageSize
}
}
)
;
return
data
;
)
return
data
}
/**
...
...
@@ -136,10 +150,10 @@ export async function listByUser(
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
UserSubscription
>>
(
`/admin/users/
${
userId
}
/subscriptions`
,
{
params
:
{
page
,
page_size
:
pageSize
}
,
params
:
{
page
,
page_size
:
pageSize
}
}
)
;
return
data
;
)
return
data
}
export
const
subscriptionsAPI
=
{
...
...
@@ -151,7 +165,7 @@ export const subscriptionsAPI = {
extend
,
revoke
,
listByGroup
,
listByUser
,
}
;
listByUser
}
export
default
subscriptionsAPI
;
export
default
subscriptionsAPI
frontend/src/api/admin/system.ts
View file @
f79b0f0f
...
...
@@ -2,31 +2,31 @@
* System API endpoints for admin operations
*/
import
{
apiClient
}
from
'
../client
'
;
import
{
apiClient
}
from
'
../client
'
export
interface
ReleaseInfo
{
name
:
string
;
body
:
string
;
published_at
:
string
;
html_url
:
string
;
name
:
string
body
:
string
published_at
:
string
html_url
:
string
}
export
interface
VersionInfo
{
current_version
:
string
;
latest_version
:
string
;
has_update
:
boolean
;
release_info
?:
ReleaseInfo
;
cached
:
boolean
;
warning
?:
string
;
build_type
:
string
;
// "source" for manual builds, "release" for CI builds
current_version
:
string
latest_version
:
string
has_update
:
boolean
release_info
?:
ReleaseInfo
cached
:
boolean
warning
?:
string
build_type
:
string
// "source" for manual builds, "release" for CI builds
}
/**
* Get current version
*/
export
async
function
getVersion
():
Promise
<
{
version
:
string
}
>
{
const
{
data
}
=
await
apiClient
.
get
<
{
version
:
string
}
>
(
'
/admin/system/version
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
{
version
:
string
}
>
(
'
/admin/system/version
'
)
return
data
}
/**
...
...
@@ -35,14 +35,14 @@ export async function getVersion(): Promise<{ version: string }> {
*/
export
async
function
checkUpdates
(
force
=
false
):
Promise
<
VersionInfo
>
{
const
{
data
}
=
await
apiClient
.
get
<
VersionInfo
>
(
'
/admin/system/check-updates
'
,
{
params
:
force
?
{
force
:
'
true
'
}
:
undefined
,
})
;
return
data
;
params
:
force
?
{
force
:
'
true
'
}
:
undefined
})
return
data
}
export
interface
UpdateResult
{
message
:
string
;
need_restart
:
boolean
;
message
:
string
need_restart
:
boolean
}
/**
...
...
@@ -50,24 +50,24 @@ export interface UpdateResult {
* Downloads and applies the latest version
*/
export
async
function
performUpdate
():
Promise
<
UpdateResult
>
{
const
{
data
}
=
await
apiClient
.
post
<
UpdateResult
>
(
'
/admin/system/update
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
post
<
UpdateResult
>
(
'
/admin/system/update
'
)
return
data
}
/**
* Rollback to previous version
*/
export
async
function
rollback
():
Promise
<
UpdateResult
>
{
const
{
data
}
=
await
apiClient
.
post
<
UpdateResult
>
(
'
/admin/system/rollback
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
post
<
UpdateResult
>
(
'
/admin/system/rollback
'
)
return
data
}
/**
* Restart the service
*/
export
async
function
restartService
():
Promise
<
{
message
:
string
}
>
{
const
{
data
}
=
await
apiClient
.
post
<
{
message
:
string
}
>
(
'
/admin/system/restart
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
post
<
{
message
:
string
}
>
(
'
/admin/system/restart
'
)
return
data
}
export
const
systemAPI
=
{
...
...
@@ -75,7 +75,7 @@ export const systemAPI = {
checkUpdates
,
performUpdate
,
rollback
,
restartService
,
}
;
restartService
}
export
default
systemAPI
;
export
default
systemAPI
frontend/src/api/admin/usage.ts
View file @
f79b0f0f
...
...
@@ -3,39 +3,35 @@
* Handles admin-level usage logs and statistics retrieval
*/
import
{
apiClient
}
from
'
../client
'
;
import
type
{
UsageLog
,
UsageQueryParams
,
PaginatedResponse
,
}
from
'
@/types
'
;
import
{
apiClient
}
from
'
../client
'
import
type
{
UsageLog
,
UsageQueryParams
,
PaginatedResponse
}
from
'
@/types
'
// ==================== Types ====================
export
interface
AdminUsageStatsResponse
{
total_requests
:
number
;
total_input_tokens
:
number
;
total_output_tokens
:
number
;
total_cache_tokens
:
number
;
total_tokens
:
number
;
total_cost
:
number
;
total_actual_cost
:
number
;
average_duration_ms
:
number
;
total_requests
:
number
total_input_tokens
:
number
total_output_tokens
:
number
total_cache_tokens
:
number
total_tokens
:
number
total_cost
:
number
total_actual_cost
:
number
average_duration_ms
:
number
}
export
interface
SimpleUser
{
id
:
number
;
email
:
string
;
id
:
number
email
:
string
}
export
interface
SimpleApiKey
{
id
:
number
;
name
:
string
;
user_id
:
number
;
id
:
number
name
:
string
user_id
:
number
}
export
interface
AdminUsageQueryParams
extends
UsageQueryParams
{
user_id
?:
number
;
user_id
?:
number
}
// ==================== API Functions ====================
...
...
@@ -47,9 +43,9 @@ export interface AdminUsageQueryParams extends UsageQueryParams {
*/
export
async
function
list
(
params
:
AdminUsageQueryParams
):
Promise
<
PaginatedResponse
<
UsageLog
>>
{
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
UsageLog
>>
(
'
/admin/usage
'
,
{
params
,
})
;
return
data
;
params
})
return
data
}
/**
...
...
@@ -58,16 +54,16 @@ export async function list(params: AdminUsageQueryParams): Promise<PaginatedResp
* @returns Usage statistics
*/
export
async
function
getStats
(
params
:
{
user_id
?:
number
;
api_key_id
?:
number
;
period
?:
string
;
start_date
?:
string
;
end_date
?:
string
;
user_id
?:
number
api_key_id
?:
number
period
?:
string
start_date
?:
string
end_date
?:
string
}):
Promise
<
AdminUsageStatsResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
AdminUsageStatsResponse
>
(
'
/admin/usage/stats
'
,
{
params
,
})
;
return
data
;
params
})
return
data
}
/**
...
...
@@ -77,9 +73,9 @@ export async function getStats(params: {
*/
export
async
function
searchUsers
(
keyword
:
string
):
Promise
<
SimpleUser
[]
>
{
const
{
data
}
=
await
apiClient
.
get
<
SimpleUser
[]
>
(
'
/admin/usage/search-users
'
,
{
params
:
{
q
:
keyword
}
,
})
;
return
data
;
params
:
{
q
:
keyword
}
})
return
data
}
/**
...
...
@@ -89,24 +85,24 @@ export async function searchUsers(keyword: string): Promise<SimpleUser[]> {
* @returns List of matching API keys (max 30)
*/
export
async
function
searchApiKeys
(
userId
?:
number
,
keyword
?:
string
):
Promise
<
SimpleApiKey
[]
>
{
const
params
:
Record
<
string
,
unknown
>
=
{}
;
const
params
:
Record
<
string
,
unknown
>
=
{}
if
(
userId
!==
undefined
)
{
params
.
user_id
=
userId
;
params
.
user_id
=
userId
}
if
(
keyword
)
{
params
.
q
=
keyword
;
params
.
q
=
keyword
}
const
{
data
}
=
await
apiClient
.
get
<
SimpleApiKey
[]
>
(
'
/admin/usage/search-api-keys
'
,
{
params
,
})
;
return
data
;
params
})
return
data
}
export
const
adminUsageAPI
=
{
list
,
getStats
,
searchUsers
,
searchApiKeys
,
}
;
searchApiKeys
}
export
default
adminUsageAPI
;
export
default
adminUsageAPI
frontend/src/api/admin/users.ts
View file @
f79b0f0f
...
...
@@ -3,8 +3,8 @@
* Handles user management for administrators
*/
import
{
apiClient
}
from
'
../client
'
;
import
type
{
User
,
UpdateUserRequest
,
PaginatedResponse
}
from
'
@/types
'
;
import
{
apiClient
}
from
'
../client
'
import
type
{
User
,
UpdateUserRequest
,
PaginatedResponse
}
from
'
@/types
'
/**
* List all users with pagination
...
...
@@ -17,19 +17,19 @@ export async function list(
page
:
number
=
1
,
pageSize
:
number
=
20
,
filters
?:
{
status
?:
'
active
'
|
'
disabled
'
;
role
?:
'
admin
'
|
'
user
'
;
search
?:
string
;
status
?:
'
active
'
|
'
disabled
'
role
?:
'
admin
'
|
'
user
'
search
?:
string
}
):
Promise
<
PaginatedResponse
<
User
>>
{
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
User
>>
(
'
/admin/users
'
,
{
params
:
{
page
,
page_size
:
pageSize
,
...
filters
,
}
,
})
;
return
data
;
...
filters
}
})
return
data
}
/**
...
...
@@ -38,8 +38,8 @@ export async function list(
* @returns User details
*/
export
async
function
getById
(
id
:
number
):
Promise
<
User
>
{
const
{
data
}
=
await
apiClient
.
get
<
User
>
(
`/admin/users/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
User
>
(
`/admin/users/
${
id
}
`
)
return
data
}
/**
...
...
@@ -48,14 +48,14 @@ export async function getById(id: number): Promise<User> {
* @returns Created user
*/
export
async
function
create
(
userData
:
{
email
:
string
;
password
:
string
;
balance
?:
number
;
concurrency
?:
number
;
allowed_groups
?:
number
[]
|
null
;
email
:
string
password
:
string
balance
?:
number
concurrency
?:
number
allowed_groups
?:
number
[]
|
null
}):
Promise
<
User
>
{
const
{
data
}
=
await
apiClient
.
post
<
User
>
(
'
/admin/users
'
,
userData
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
post
<
User
>
(
'
/admin/users
'
,
userData
)
return
data
}
/**
...
...
@@ -65,8 +65,8 @@ export async function create(userData: {
* @returns Updated user
*/
export
async
function
update
(
id
:
number
,
updates
:
UpdateUserRequest
):
Promise
<
User
>
{
const
{
data
}
=
await
apiClient
.
put
<
User
>
(
`/admin/users/
${
id
}
`
,
updates
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
put
<
User
>
(
`/admin/users/
${
id
}
`
,
updates
)
return
data
}
/**
...
...
@@ -75,8 +75,8 @@ export async function update(id: number, updates: UpdateUserRequest): Promise<Us
* @returns Success confirmation
*/
export
async
function
deleteUser
(
id
:
number
):
Promise
<
{
message
:
string
}
>
{
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/admin/users/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/admin/users/
${
id
}
`
)
return
data
}
/**
...
...
@@ -96,9 +96,9 @@ export async function updateBalance(
const
{
data
}
=
await
apiClient
.
post
<
User
>
(
`/admin/users/
${
id
}
/balance`
,
{
balance
,
operation
,
notes
:
notes
||
''
,
})
;
return
data
;
notes
:
notes
||
''
})
return
data
}
/**
...
...
@@ -108,7 +108,7 @@ export async function updateBalance(
* @returns Updated user
*/
export
async
function
updateConcurrency
(
id
:
number
,
concurrency
:
number
):
Promise
<
User
>
{
return
update
(
id
,
{
concurrency
})
;
return
update
(
id
,
{
concurrency
})
}
/**
...
...
@@ -118,7 +118,7 @@ export async function updateConcurrency(id: number, concurrency: number): Promis
* @returns Updated user
*/
export
async
function
toggleStatus
(
id
:
number
,
status
:
'
active
'
|
'
disabled
'
):
Promise
<
User
>
{
return
update
(
id
,
{
status
})
;
return
update
(
id
,
{
status
})
}
/**
...
...
@@ -127,8 +127,8 @@ export async function toggleStatus(id: number, status: 'active' | 'disabled'): P
* @returns List of user's API keys
*/
export
async
function
getUserApiKeys
(
id
:
number
):
Promise
<
PaginatedResponse
<
any
>>
{
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
any
>>
(
`/admin/users/
${
id
}
/api-keys`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
any
>>
(
`/admin/users/
${
id
}
/api-keys`
)
return
data
}
/**
...
...
@@ -141,18 +141,18 @@ export async function getUserUsageStats(
id
:
number
,
period
:
string
=
'
month
'
):
Promise
<
{
total_requests
:
number
;
total_cost
:
number
;
total_tokens
:
number
;
total_requests
:
number
total_cost
:
number
total_tokens
:
number
}
>
{
const
{
data
}
=
await
apiClient
.
get
<
{
total_requests
:
number
;
total_cost
:
number
;
total_tokens
:
number
;
total_requests
:
number
total_cost
:
number
total_tokens
:
number
}
>
(
`/admin/users/
${
id
}
/usage`
,
{
params
:
{
period
}
,
})
;
return
data
;
params
:
{
period
}
})
return
data
}
export
const
usersAPI
=
{
...
...
@@ -165,7 +165,7 @@ export const usersAPI = {
updateConcurrency
,
toggleStatus
,
getUserApiKeys
,
getUserUsageStats
,
}
;
getUserUsageStats
}
export
default
usersAPI
;
export
default
usersAPI
frontend/src/api/auth.ts
View file @
f79b0f0f
...
...
@@ -3,29 +3,37 @@
* Handles user login, registration, and logout operations
*/
import
{
apiClient
}
from
'
./client
'
;
import
type
{
LoginRequest
,
RegisterRequest
,
AuthResponse
,
User
,
SendVerifyCodeRequest
,
SendVerifyCodeResponse
,
PublicSettings
}
from
'
@/types
'
;
import
{
apiClient
}
from
'
./client
'
import
type
{
LoginRequest
,
RegisterRequest
,
AuthResponse
,
User
,
SendVerifyCodeRequest
,
SendVerifyCodeResponse
,
PublicSettings
}
from
'
@/types
'
/**
* Store authentication token in localStorage
*/
export
function
setAuthToken
(
token
:
string
):
void
{
localStorage
.
setItem
(
'
auth_token
'
,
token
)
;
localStorage
.
setItem
(
'
auth_token
'
,
token
)
}
/**
* Get authentication token from localStorage
*/
export
function
getAuthToken
():
string
|
null
{
return
localStorage
.
getItem
(
'
auth_token
'
)
;
return
localStorage
.
getItem
(
'
auth_token
'
)
}
/**
* Clear authentication token from localStorage
*/
export
function
clearAuthToken
():
void
{
localStorage
.
removeItem
(
'
auth_token
'
)
;
localStorage
.
removeItem
(
'
auth_user
'
)
;
localStorage
.
removeItem
(
'
auth_token
'
)
localStorage
.
removeItem
(
'
auth_user
'
)
}
/**
...
...
@@ -34,13 +42,13 @@ export function clearAuthToken(): void {
* @returns Authentication response with token and user data
*/
export
async
function
login
(
credentials
:
LoginRequest
):
Promise
<
AuthResponse
>
{
const
{
data
}
=
await
apiClient
.
post
<
AuthResponse
>
(
'
/auth/login
'
,
credentials
)
;
const
{
data
}
=
await
apiClient
.
post
<
AuthResponse
>
(
'
/auth/login
'
,
credentials
)
// Store token and user data
setAuthToken
(
data
.
access_token
)
;
localStorage
.
setItem
(
'
auth_user
'
,
JSON
.
stringify
(
data
.
user
))
;
setAuthToken
(
data
.
access_token
)
localStorage
.
setItem
(
'
auth_user
'
,
JSON
.
stringify
(
data
.
user
))
return
data
;
return
data
}
/**
...
...
@@ -49,13 +57,13 @@ export async function login(credentials: LoginRequest): Promise<AuthResponse> {
* @returns Authentication response with token and user data
*/
export
async
function
register
(
userData
:
RegisterRequest
):
Promise
<
AuthResponse
>
{
const
{
data
}
=
await
apiClient
.
post
<
AuthResponse
>
(
'
/auth/register
'
,
userData
)
;
const
{
data
}
=
await
apiClient
.
post
<
AuthResponse
>
(
'
/auth/register
'
,
userData
)
// Store token and user data
setAuthToken
(
data
.
access_token
)
;
localStorage
.
setItem
(
'
auth_user
'
,
JSON
.
stringify
(
data
.
user
))
;
setAuthToken
(
data
.
access_token
)
localStorage
.
setItem
(
'
auth_user
'
,
JSON
.
stringify
(
data
.
user
))
return
data
;
return
data
}
/**
...
...
@@ -63,8 +71,8 @@ export async function register(userData: RegisterRequest): Promise<AuthResponse>
* @returns User profile data
*/
export
async
function
getCurrentUser
():
Promise
<
User
>
{
const
{
data
}
=
await
apiClient
.
get
<
User
>
(
'
/auth/me
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
User
>
(
'
/auth/me
'
)
return
data
}
/**
...
...
@@ -72,7 +80,7 @@ export async function getCurrentUser(): Promise<User> {
* Clears authentication token and user data from localStorage
*/
export
function
logout
():
void
{
clearAuthToken
()
;
clearAuthToken
()
// Optionally redirect to login page
// window.location.href = '/login';
}
...
...
@@ -82,7 +90,7 @@ export function logout(): void {
* @returns True if user has valid token
*/
export
function
isAuthenticated
():
boolean
{
return
getAuthToken
()
!==
null
;
return
getAuthToken
()
!==
null
}
/**
...
...
@@ -90,8 +98,8 @@ export function isAuthenticated(): boolean {
* @returns Public settings including registration and Turnstile config
*/
export
async
function
getPublicSettings
():
Promise
<
PublicSettings
>
{
const
{
data
}
=
await
apiClient
.
get
<
PublicSettings
>
(
'
/settings/public
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
PublicSettings
>
(
'
/settings/public
'
)
return
data
}
/**
...
...
@@ -99,9 +107,11 @@ export async function getPublicSettings(): Promise<PublicSettings> {
* @param request - Email and optional Turnstile token
* @returns Response with countdown seconds
*/
export
async
function
sendVerifyCode
(
request
:
SendVerifyCodeRequest
):
Promise
<
SendVerifyCodeResponse
>
{
const
{
data
}
=
await
apiClient
.
post
<
SendVerifyCodeResponse
>
(
'
/auth/send-verify-code
'
,
request
);
return
data
;
export
async
function
sendVerifyCode
(
request
:
SendVerifyCodeRequest
):
Promise
<
SendVerifyCodeResponse
>
{
const
{
data
}
=
await
apiClient
.
post
<
SendVerifyCodeResponse
>
(
'
/auth/send-verify-code
'
,
request
)
return
data
}
export
const
authAPI
=
{
...
...
@@ -114,7 +124,7 @@ export const authAPI = {
getAuthToken
,
clearAuthToken
,
getPublicSettings
,
sendVerifyCode
,
}
;
sendVerifyCode
}
export
default
authAPI
;
export
default
authAPI
frontend/src/api/client.ts
View file @
f79b0f0f
...
...
@@ -3,70 +3,70 @@
* Base client with interceptors for authentication and error handling
*/
import
axios
,
{
AxiosInstance
,
AxiosError
,
InternalAxiosRequestConfig
}
from
'
axios
'
;
import
type
{
ApiResponse
}
from
'
@/types
'
;
import
axios
,
{
AxiosInstance
,
AxiosError
,
InternalAxiosRequestConfig
}
from
'
axios
'
import
type
{
ApiResponse
}
from
'
@/types
'
// ==================== Axios Instance Configuration ====================
const
API_BASE_URL
=
import
.
meta
.
env
.
VITE_API_BASE_URL
||
'
/api/v1
'
;
const
API_BASE_URL
=
import
.
meta
.
env
.
VITE_API_BASE_URL
||
'
/api/v1
'
export
const
apiClient
:
AxiosInstance
=
axios
.
create
({
baseURL
:
API_BASE_URL
,
timeout
:
30000
,
headers
:
{
'
Content-Type
'
:
'
application/json
'
,
}
,
})
;
'
Content-Type
'
:
'
application/json
'
}
})
// ==================== Request Interceptor ====================
apiClient
.
interceptors
.
request
.
use
(
(
config
:
InternalAxiosRequestConfig
)
=>
{
// Attach token from localStorage
const
token
=
localStorage
.
getItem
(
'
auth_token
'
)
;
const
token
=
localStorage
.
getItem
(
'
auth_token
'
)
if
(
token
&&
config
.
headers
)
{
config
.
headers
.
Authorization
=
`Bearer
${
token
}
`
;
config
.
headers
.
Authorization
=
`Bearer
${
token
}
`
}
return
config
;
return
config
},
(
error
)
=>
{
return
Promise
.
reject
(
error
)
;
return
Promise
.
reject
(
error
)
}
)
;
)
// ==================== Response Interceptor ====================
apiClient
.
interceptors
.
response
.
use
(
(
response
)
=>
{
// Unwrap standard API response format { code, message, data }
const
apiResponse
=
response
.
data
as
ApiResponse
<
unknown
>
;
const
apiResponse
=
response
.
data
as
ApiResponse
<
unknown
>
if
(
apiResponse
&&
typeof
apiResponse
===
'
object
'
&&
'
code
'
in
apiResponse
)
{
if
(
apiResponse
.
code
===
0
)
{
// Success - return the data portion
response
.
data
=
apiResponse
.
data
;
response
.
data
=
apiResponse
.
data
}
else
{
// API error
return
Promise
.
reject
({
status
:
response
.
status
,
code
:
apiResponse
.
code
,
message
:
apiResponse
.
message
||
'
Unknown error
'
,
})
;
message
:
apiResponse
.
message
||
'
Unknown error
'
})
}
}
return
response
;
return
response
},
(
error
:
AxiosError
<
ApiResponse
<
unknown
>>
)
=>
{
// Handle common errors
if
(
error
.
response
)
{
const
{
status
,
data
}
=
error
.
response
;
const
{
status
,
data
}
=
error
.
response
// 401: Unauthorized - clear token and redirect to login
if
(
status
===
401
)
{
localStorage
.
removeItem
(
'
auth_token
'
)
;
localStorage
.
removeItem
(
'
auth_user
'
)
;
localStorage
.
removeItem
(
'
auth_token
'
)
localStorage
.
removeItem
(
'
auth_user
'
)
// Only redirect if not already on login page
if
(
!
window
.
location
.
pathname
.
includes
(
'
/login
'
))
{
window
.
location
.
href
=
'
/login
'
;
window
.
location
.
href
=
'
/login
'
}
}
...
...
@@ -74,16 +74,16 @@ apiClient.interceptors.response.use(
return
Promise
.
reject
({
status
,
code
:
data
?.
code
,
message
:
data
?.
message
||
error
.
message
,
})
;
message
:
data
?.
message
||
error
.
message
})
}
// Network error
return
Promise
.
reject
({
status
:
0
,
message
:
'
Network error. Please check your connection.
'
,
})
;
message
:
'
Network error. Please check your connection.
'
})
}
)
;
)
export
default
apiClient
;
export
default
apiClient
frontend/src/api/groups.ts
View file @
f79b0f0f
...
...
@@ -3,8 +3,8 @@
* Handles group-related operations for regular users
*/
import
{
apiClient
}
from
'
./client
'
;
import
type
{
Group
}
from
'
@/types
'
;
import
{
apiClient
}
from
'
./client
'
import
type
{
Group
}
from
'
@/types
'
/**
* Get available groups that the current user can bind to API keys
...
...
@@ -14,12 +14,12 @@ import type { Group } from '@/types';
* @returns List of available groups
*/
export
async
function
getAvailable
():
Promise
<
Group
[]
>
{
const
{
data
}
=
await
apiClient
.
get
<
Group
[]
>
(
'
/groups/available
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
Group
[]
>
(
'
/groups/available
'
)
return
data
}
export
const
userGroupsAPI
=
{
getAvailable
,
}
;
getAvailable
}
export
default
userGroupsAPI
;
export
default
userGroupsAPI
frontend/src/api/index.ts
View file @
f79b0f0f
...
...
@@ -4,20 +4,20 @@
*/
// Re-export the HTTP client
export
{
apiClient
}
from
'
./client
'
;
export
{
apiClient
}
from
'
./client
'
// Auth API
export
{
authAPI
}
from
'
./auth
'
;
export
{
authAPI
}
from
'
./auth
'
// User APIs
export
{
keysAPI
}
from
'
./keys
'
;
export
{
usageAPI
}
from
'
./usage
'
;
export
{
userAPI
}
from
'
./user
'
;
export
{
redeemAPI
,
type
RedeemHistoryItem
}
from
'
./redeem
'
;
export
{
userGroupsAPI
}
from
'
./groups
'
;
export
{
keysAPI
}
from
'
./keys
'
export
{
usageAPI
}
from
'
./usage
'
export
{
userAPI
}
from
'
./user
'
export
{
redeemAPI
,
type
RedeemHistoryItem
}
from
'
./redeem
'
export
{
userGroupsAPI
}
from
'
./groups
'
// Admin APIs
export
{
adminAPI
}
from
'
./admin
'
;
export
{
adminAPI
}
from
'
./admin
'
// Default export
export
{
default
}
from
'
./client
'
;
export
{
default
}
from
'
./client
'
frontend/src/api/keys.ts
View file @
f79b0f0f
...
...
@@ -3,13 +3,8 @@
* Handles CRUD operations for user API keys
*/
import
{
apiClient
}
from
'
./client
'
;
import
type
{
ApiKey
,
CreateApiKeyRequest
,
UpdateApiKeyRequest
,
PaginatedResponse
,
}
from
'
@/types
'
;
import
{
apiClient
}
from
'
./client
'
import
type
{
ApiKey
,
CreateApiKeyRequest
,
UpdateApiKeyRequest
,
PaginatedResponse
}
from
'
@/types
'
/**
* List all API keys for current user
...
...
@@ -17,11 +12,14 @@ import type {
* @param pageSize - Items per page (default: 10)
* @returns Paginated list of API keys
*/
export
async
function
list
(
page
:
number
=
1
,
pageSize
:
number
=
10
):
Promise
<
PaginatedResponse
<
ApiKey
>>
{
export
async
function
list
(
page
:
number
=
1
,
pageSize
:
number
=
10
):
Promise
<
PaginatedResponse
<
ApiKey
>>
{
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
ApiKey
>>
(
'
/keys
'
,
{
params
:
{
page
,
page_size
:
pageSize
}
,
})
;
return
data
;
params
:
{
page
,
page_size
:
pageSize
}
})
return
data
}
/**
...
...
@@ -30,8 +28,8 @@ export async function list(page: number = 1, pageSize: number = 10): Promise<Pag
* @returns API key details
*/
export
async
function
getById
(
id
:
number
):
Promise
<
ApiKey
>
{
const
{
data
}
=
await
apiClient
.
get
<
ApiKey
>
(
`/keys/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
ApiKey
>
(
`/keys/
${
id
}
`
)
return
data
}
/**
...
...
@@ -41,17 +39,21 @@ export async function getById(id: number): Promise<ApiKey> {
* @param customKey - Optional custom key value
* @returns Created API key
*/
export
async
function
create
(
name
:
string
,
groupId
?:
number
|
null
,
customKey
?:
string
):
Promise
<
ApiKey
>
{
const
payload
:
CreateApiKeyRequest
=
{
name
};
export
async
function
create
(
name
:
string
,
groupId
?:
number
|
null
,
customKey
?:
string
):
Promise
<
ApiKey
>
{
const
payload
:
CreateApiKeyRequest
=
{
name
}
if
(
groupId
!==
undefined
)
{
payload
.
group_id
=
groupId
;
payload
.
group_id
=
groupId
}
if
(
customKey
)
{
payload
.
custom_key
=
customKey
;
payload
.
custom_key
=
customKey
}
const
{
data
}
=
await
apiClient
.
post
<
ApiKey
>
(
'
/keys
'
,
payload
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
post
<
ApiKey
>
(
'
/keys
'
,
payload
)
return
data
}
/**
...
...
@@ -61,8 +63,8 @@ export async function create(name: string, groupId?: number | null, customKey?:
* @returns Updated API key
*/
export
async
function
update
(
id
:
number
,
updates
:
UpdateApiKeyRequest
):
Promise
<
ApiKey
>
{
const
{
data
}
=
await
apiClient
.
put
<
ApiKey
>
(
`/keys/
${
id
}
`
,
updates
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
put
<
ApiKey
>
(
`/keys/
${
id
}
`
,
updates
)
return
data
}
/**
...
...
@@ -71,8 +73,8 @@ export async function update(id: number, updates: UpdateApiKeyRequest): Promise<
* @returns Success confirmation
*/
export
async
function
deleteKey
(
id
:
number
):
Promise
<
{
message
:
string
}
>
{
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/keys/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
delete
<
{
message
:
string
}
>
(
`/keys/
${
id
}
`
)
return
data
}
/**
...
...
@@ -81,11 +83,8 @@ export async function deleteKey(id: number): Promise<{ message: string }> {
* @param status - New status
* @returns Updated API key
*/
export
async
function
toggleStatus
(
id
:
number
,
status
:
'
active
'
|
'
inactive
'
):
Promise
<
ApiKey
>
{
return
update
(
id
,
{
status
});
export
async
function
toggleStatus
(
id
:
number
,
status
:
'
active
'
|
'
inactive
'
):
Promise
<
ApiKey
>
{
return
update
(
id
,
{
status
})
}
export
const
keysAPI
=
{
...
...
@@ -94,7 +93,7 @@ export const keysAPI = {
create
,
update
,
delete
:
deleteKey
,
toggleStatus
,
}
;
toggleStatus
}
export
default
keysAPI
;
export
default
keysAPI
frontend/src/api/redeem.ts
View file @
f79b0f0f
...
...
@@ -3,24 +3,24 @@
* Handles redeem code redemption for users
*/
import
{
apiClient
}
from
'
./client
'
;
import
type
{
RedeemCodeRequest
}
from
'
@/types
'
;
import
{
apiClient
}
from
'
./client
'
import
type
{
RedeemCodeRequest
}
from
'
@/types
'
export
interface
RedeemHistoryItem
{
id
:
number
;
code
:
string
;
type
:
string
;
value
:
number
;
status
:
string
;
used_at
:
string
;
created_at
:
string
;
id
:
number
code
:
string
type
:
string
value
:
number
status
:
string
used_at
:
string
created_at
:
string
// 订阅类型专用字段
group_id
?:
number
;
validity_days
?:
number
;
group_id
?:
number
validity_days
?:
number
group
?:
{
id
:
number
;
name
:
string
;
}
;
id
:
number
name
:
string
}
}
/**
...
...
@@ -29,23 +29,23 @@ export interface RedeemHistoryItem {
* @returns Redemption result with updated balance or concurrency
*/
export
async
function
redeem
(
code
:
string
):
Promise
<
{
message
:
string
;
type
:
string
;
value
:
number
;
new_balance
?:
number
;
new_concurrency
?:
number
;
message
:
string
type
:
string
value
:
number
new_balance
?:
number
new_concurrency
?:
number
}
>
{
const
payload
:
RedeemCodeRequest
=
{
code
}
;
const
payload
:
RedeemCodeRequest
=
{
code
}
const
{
data
}
=
await
apiClient
.
post
<
{
message
:
string
;
type
:
string
;
value
:
number
;
new_balance
?:
number
;
new_concurrency
?:
number
;
}
>
(
'
/redeem
'
,
payload
)
;
message
:
string
type
:
string
value
:
number
new_balance
?:
number
new_concurrency
?:
number
}
>
(
'
/redeem
'
,
payload
)
return
data
;
return
data
}
/**
...
...
@@ -53,13 +53,13 @@ export async function redeem(code: string): Promise<{
* @returns List of redeemed codes
*/
export
async
function
getHistory
():
Promise
<
RedeemHistoryItem
[]
>
{
const
{
data
}
=
await
apiClient
.
get
<
RedeemHistoryItem
[]
>
(
'
/redeem/history
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
RedeemHistoryItem
[]
>
(
'
/redeem/history
'
)
return
data
}
export
const
redeemAPI
=
{
redeem
,
getHistory
,
}
;
getHistory
}
export
default
redeemAPI
;
export
default
redeemAPI
frontend/src/api/setup.ts
View file @
f79b0f0f
/**
* Setup API endpoints
*/
import
axios
from
'
axios
'
;
import
axios
from
'
axios
'
// Create a separate client for setup endpoints (not under /api/v1)
const
setupClient
=
axios
.
create
({
baseURL
:
''
,
timeout
:
30000
,
headers
:
{
'
Content-Type
'
:
'
application/json
'
,
}
,
})
;
'
Content-Type
'
:
'
application/json
'
}
})
export
interface
SetupStatus
{
needs_setup
:
boolean
;
step
:
string
;
needs_setup
:
boolean
step
:
string
}
export
interface
DatabaseConfig
{
host
:
string
;
port
:
number
;
user
:
string
;
password
:
string
;
dbname
:
string
;
sslmode
:
string
;
host
:
string
port
:
number
user
:
string
password
:
string
dbname
:
string
sslmode
:
string
}
export
interface
RedisConfig
{
host
:
string
;
port
:
number
;
password
:
string
;
db
:
number
;
host
:
string
port
:
number
password
:
string
db
:
number
}
export
interface
AdminConfig
{
email
:
string
;
password
:
string
;
email
:
string
password
:
string
}
export
interface
ServerConfig
{
host
:
string
;
port
:
number
;
mode
:
string
;
host
:
string
port
:
number
mode
:
string
}
export
interface
InstallRequest
{
database
:
DatabaseConfig
;
redis
:
RedisConfig
;
admin
:
AdminConfig
;
server
:
ServerConfig
;
database
:
DatabaseConfig
redis
:
RedisConfig
admin
:
AdminConfig
server
:
ServerConfig
}
export
interface
InstallResponse
{
message
:
string
;
restart
:
boolean
;
message
:
string
restart
:
boolean
}
/**
* Get setup status
*/
export
async
function
getSetupStatus
():
Promise
<
SetupStatus
>
{
const
response
=
await
setupClient
.
get
(
'
/setup/status
'
)
;
return
response
.
data
.
data
;
const
response
=
await
setupClient
.
get
(
'
/setup/status
'
)
return
response
.
data
.
data
}
/**
* Test database connection
*/
export
async
function
testDatabase
(
config
:
DatabaseConfig
):
Promise
<
void
>
{
await
setupClient
.
post
(
'
/setup/test-db
'
,
config
)
;
await
setupClient
.
post
(
'
/setup/test-db
'
,
config
)
}
/**
* Test Redis connection
*/
export
async
function
testRedis
(
config
:
RedisConfig
):
Promise
<
void
>
{
await
setupClient
.
post
(
'
/setup/test-redis
'
,
config
)
;
await
setupClient
.
post
(
'
/setup/test-redis
'
,
config
)
}
/**
* Perform installation
*/
export
async
function
install
(
config
:
InstallRequest
):
Promise
<
InstallResponse
>
{
const
response
=
await
setupClient
.
post
(
'
/setup/install
'
,
config
)
;
return
response
.
data
.
data
;
const
response
=
await
setupClient
.
post
(
'
/setup/install
'
,
config
)
return
response
.
data
.
data
}
frontend/src/api/subscriptions.ts
View file @
f79b0f0f
...
...
@@ -3,64 +3,68 @@
* API for regular users to view their own subscriptions and progress
*/
import
{
apiClient
}
from
'
./client
'
;
import
type
{
UserSubscription
,
SubscriptionProgress
}
from
'
@/types
'
;
import
{
apiClient
}
from
'
./client
'
import
type
{
UserSubscription
,
SubscriptionProgress
}
from
'
@/types
'
/**
* Subscription summary for user dashboard
*/
export
interface
SubscriptionSummary
{
active_count
:
number
;
active_count
:
number
subscriptions
:
Array
<
{
id
:
number
;
group_name
:
string
;
status
:
string
;
daily_progress
:
number
|
null
;
weekly_progress
:
number
|
null
;
monthly_progress
:
number
|
null
;
expires_at
:
string
|
null
;
days_remaining
:
number
|
null
;
}
>
;
id
:
number
group_name
:
string
status
:
string
daily_progress
:
number
|
null
weekly_progress
:
number
|
null
monthly_progress
:
number
|
null
expires_at
:
string
|
null
days_remaining
:
number
|
null
}
>
}
/**
* Get list of current user's subscriptions
*/
export
async
function
getMySubscriptions
():
Promise
<
UserSubscription
[]
>
{
const
response
=
await
apiClient
.
get
<
UserSubscription
[]
>
(
'
/subscriptions
'
)
;
return
response
.
data
;
const
response
=
await
apiClient
.
get
<
UserSubscription
[]
>
(
'
/subscriptions
'
)
return
response
.
data
}
/**
* Get current user's active subscriptions
*/
export
async
function
getActiveSubscriptions
():
Promise
<
UserSubscription
[]
>
{
const
response
=
await
apiClient
.
get
<
UserSubscription
[]
>
(
'
/subscriptions/active
'
)
;
return
response
.
data
;
const
response
=
await
apiClient
.
get
<
UserSubscription
[]
>
(
'
/subscriptions/active
'
)
return
response
.
data
}
/**
* Get progress for all user's active subscriptions
*/
export
async
function
getSubscriptionsProgress
():
Promise
<
SubscriptionProgress
[]
>
{
const
response
=
await
apiClient
.
get
<
SubscriptionProgress
[]
>
(
'
/subscriptions/progress
'
)
;
return
response
.
data
;
const
response
=
await
apiClient
.
get
<
SubscriptionProgress
[]
>
(
'
/subscriptions/progress
'
)
return
response
.
data
}
/**
* Get subscription summary for dashboard display
*/
export
async
function
getSubscriptionSummary
():
Promise
<
SubscriptionSummary
>
{
const
response
=
await
apiClient
.
get
<
SubscriptionSummary
>
(
'
/subscriptions/summary
'
)
;
return
response
.
data
;
const
response
=
await
apiClient
.
get
<
SubscriptionSummary
>
(
'
/subscriptions/summary
'
)
return
response
.
data
}
/**
* Get progress for a specific subscription
*/
export
async
function
getSubscriptionProgress
(
subscriptionId
:
number
):
Promise
<
SubscriptionProgress
>
{
const
response
=
await
apiClient
.
get
<
SubscriptionProgress
>
(
`/subscriptions/
${
subscriptionId
}
/progress`
);
return
response
.
data
;
export
async
function
getSubscriptionProgress
(
subscriptionId
:
number
):
Promise
<
SubscriptionProgress
>
{
const
response
=
await
apiClient
.
get
<
SubscriptionProgress
>
(
`/subscriptions/
${
subscriptionId
}
/progress`
)
return
response
.
data
}
export
default
{
...
...
@@ -68,5 +72,5 @@ export default {
getActiveSubscriptions
,
getSubscriptionsProgress
,
getSubscriptionSummary
,
getSubscriptionProgress
,
}
;
getSubscriptionProgress
}
frontend/src/api/usage.ts
View file @
f79b0f0f
...
...
@@ -3,59 +3,59 @@
* Handles usage logs and statistics retrieval
*/
import
{
apiClient
}
from
'
./client
'
;
import
{
apiClient
}
from
'
./client
'
import
type
{
UsageLog
,
UsageQueryParams
,
UsageStatsResponse
,
PaginatedResponse
,
TrendDataPoint
,
ModelStat
,
}
from
'
@/types
'
;
ModelStat
}
from
'
@/types
'
// ==================== Dashboard Types ====================
export
interface
UserDashboardStats
{
total_api_keys
:
number
;
active_api_keys
:
number
;
total_requests
:
number
;
total_input_tokens
:
number
;
total_output_tokens
:
number
;
total_cache_creation_tokens
:
number
;
total_cache_read_tokens
:
number
;
total_tokens
:
number
;
total_cost
:
number
;
// 标准计费
total_actual_cost
:
number
;
// 实际扣除
today_requests
:
number
;
today_input_tokens
:
number
;
today_output_tokens
:
number
;
today_cache_creation_tokens
:
number
;
today_cache_read_tokens
:
number
;
today_tokens
:
number
;
today_cost
:
number
;
// 今日标准计费
today_actual_cost
:
number
;
// 今日实际扣除
average_duration_ms
:
number
;
rpm
:
number
;
// 近5分钟平均每分钟请求数
tpm
:
number
;
// 近5分钟平均每分钟Token数
total_api_keys
:
number
active_api_keys
:
number
total_requests
:
number
total_input_tokens
:
number
total_output_tokens
:
number
total_cache_creation_tokens
:
number
total_cache_read_tokens
:
number
total_tokens
:
number
total_cost
:
number
// 标准计费
total_actual_cost
:
number
// 实际扣除
today_requests
:
number
today_input_tokens
:
number
today_output_tokens
:
number
today_cache_creation_tokens
:
number
today_cache_read_tokens
:
number
today_tokens
:
number
today_cost
:
number
// 今日标准计费
today_actual_cost
:
number
// 今日实际扣除
average_duration_ms
:
number
rpm
:
number
// 近5分钟平均每分钟请求数
tpm
:
number
// 近5分钟平均每分钟Token数
}
export
interface
TrendParams
{
start_date
?:
string
;
end_date
?:
string
;
granularity
?:
'
day
'
|
'
hour
'
;
start_date
?:
string
end_date
?:
string
granularity
?:
'
day
'
|
'
hour
'
}
export
interface
TrendResponse
{
trend
:
TrendDataPoint
[]
;
start_date
:
string
;
end_date
:
string
;
granularity
:
string
;
trend
:
TrendDataPoint
[]
start_date
:
string
end_date
:
string
granularity
:
string
}
export
interface
ModelStatsResponse
{
models
:
ModelStat
[]
;
start_date
:
string
;
end_date
:
string
;
models
:
ModelStat
[]
start_date
:
string
end_date
:
string
}
/**
...
...
@@ -72,17 +72,17 @@ export async function list(
):
Promise
<
PaginatedResponse
<
UsageLog
>>
{
const
params
:
UsageQueryParams
=
{
page
,
page_size
:
pageSize
,
}
;
page_size
:
pageSize
}
if
(
apiKeyId
!==
undefined
)
{
params
.
api_key_id
=
apiKeyId
;
params
.
api_key_id
=
apiKeyId
}
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
UsageLog
>>
(
'
/usage
'
,
{
params
,
})
;
return
data
;
params
})
return
data
}
/**
...
...
@@ -92,9 +92,9 @@ export async function list(
*/
export
async
function
query
(
params
:
UsageQueryParams
):
Promise
<
PaginatedResponse
<
UsageLog
>>
{
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
UsageLog
>>
(
'
/usage
'
,
{
params
,
})
;
return
data
;
params
})
return
data
}
/**
...
...
@@ -107,16 +107,16 @@ export async function getStats(
period
:
string
=
'
today
'
,
apiKeyId
?:
number
):
Promise
<
UsageStatsResponse
>
{
const
params
:
Record
<
string
,
unknown
>
=
{
period
}
;
const
params
:
Record
<
string
,
unknown
>
=
{
period
}
if
(
apiKeyId
!==
undefined
)
{
params
.
api_key_id
=
apiKeyId
;
params
.
api_key_id
=
apiKeyId
}
const
{
data
}
=
await
apiClient
.
get
<
UsageStatsResponse
>
(
'
/usage/stats
'
,
{
params
,
})
;
return
data
;
params
})
return
data
}
/**
...
...
@@ -133,17 +133,17 @@ export async function getStatsByDateRange(
):
Promise
<
UsageStatsResponse
>
{
const
params
:
Record
<
string
,
unknown
>
=
{
start_date
:
startDate
,
end_date
:
endDate
,
}
;
end_date
:
endDate
}
if
(
apiKeyId
!==
undefined
)
{
params
.
api_key_id
=
apiKeyId
;
params
.
api_key_id
=
apiKeyId
}
const
{
data
}
=
await
apiClient
.
get
<
UsageStatsResponse
>
(
'
/usage/stats
'
,
{
params
,
})
;
return
data
;
params
})
return
data
}
/**
...
...
@@ -162,17 +162,17 @@ export async function getByDateRange(
start_date
:
startDate
,
end_date
:
endDate
,
page
:
1
,
page_size
:
100
,
}
;
page_size
:
100
}
if
(
apiKeyId
!==
undefined
)
{
params
.
api_key_id
=
apiKeyId
;
params
.
api_key_id
=
apiKeyId
}
const
{
data
}
=
await
apiClient
.
get
<
PaginatedResponse
<
UsageLog
>>
(
'
/usage
'
,
{
params
,
})
;
return
data
;
params
})
return
data
}
/**
...
...
@@ -181,8 +181,8 @@ export async function getByDateRange(
* @returns Usage log details
*/
export
async
function
getById
(
id
:
number
):
Promise
<
UsageLog
>
{
const
{
data
}
=
await
apiClient
.
get
<
UsageLog
>
(
`/usage/
${
id
}
`
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
UsageLog
>
(
`/usage/
${
id
}
`
)
return
data
}
// ==================== Dashboard API ====================
...
...
@@ -192,8 +192,8 @@ export async function getById(id: number): Promise<UsageLog> {
* @returns Dashboard statistics for current user
*/
export
async
function
getDashboardStats
():
Promise
<
UserDashboardStats
>
{
const
{
data
}
=
await
apiClient
.
get
<
UserDashboardStats
>
(
'
/usage/dashboard/stats
'
)
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
UserDashboardStats
>
(
'
/usage/dashboard/stats
'
)
return
data
}
/**
...
...
@@ -202,8 +202,8 @@ export async function getDashboardStats(): Promise<UserDashboardStats> {
* @returns Usage trend data for current user
*/
export
async
function
getDashboardTrend
(
params
?:
TrendParams
):
Promise
<
TrendResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
TrendResponse
>
(
'
/usage/dashboard/trend
'
,
{
params
})
;
return
data
;
const
{
data
}
=
await
apiClient
.
get
<
TrendResponse
>
(
'
/usage/dashboard/trend
'
,
{
params
})
return
data
}
/**
...
...
@@ -211,19 +211,22 @@ export async function getDashboardTrend(params?: TrendParams): Promise<TrendResp
* @param params - Query parameters for filtering
* @returns Model usage statistics for current user
*/
export
async
function
getDashboardModels
(
params
?:
{
start_date
?:
string
;
end_date
?:
string
}):
Promise
<
ModelStatsResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
ModelStatsResponse
>
(
'
/usage/dashboard/models
'
,
{
params
});
return
data
;
export
async
function
getDashboardModels
(
params
?:
{
start_date
?:
string
end_date
?:
string
}):
Promise
<
ModelStatsResponse
>
{
const
{
data
}
=
await
apiClient
.
get
<
ModelStatsResponse
>
(
'
/usage/dashboard/models
'
,
{
params
})
return
data
}
export
interface
BatchApiKeyUsageStats
{
api_key_id
:
number
;
today_actual_cost
:
number
;
total_actual_cost
:
number
;
api_key_id
:
number
today_actual_cost
:
number
total_actual_cost
:
number
}
export
interface
BatchApiKeysUsageResponse
{
stats
:
Record
<
string
,
BatchApiKeyUsageStats
>
;
stats
:
Record
<
string
,
BatchApiKeyUsageStats
>
}
/**
...
...
@@ -231,11 +234,16 @@ export interface BatchApiKeysUsageResponse {
* @param apiKeyIds - Array of API key IDs
* @returns Usage stats map keyed by API key ID
*/
export
async
function
getDashboardApiKeysUsage
(
apiKeyIds
:
number
[]):
Promise
<
BatchApiKeysUsageResponse
>
{
const
{
data
}
=
await
apiClient
.
post
<
BatchApiKeysUsageResponse
>
(
'
/usage/dashboard/api-keys-usage
'
,
{
api_key_ids
:
apiKeyIds
,
});
return
data
;
export
async
function
getDashboardApiKeysUsage
(
apiKeyIds
:
number
[]
):
Promise
<
BatchApiKeysUsageResponse
>
{
const
{
data
}
=
await
apiClient
.
post
<
BatchApiKeysUsageResponse
>
(
'
/usage/dashboard/api-keys-usage
'
,
{
api_key_ids
:
apiKeyIds
}
)
return
data
}
export
const
usageAPI
=
{
...
...
@@ -249,7 +257,7 @@ export const usageAPI = {
getDashboardStats
,
getDashboardTrend
,
getDashboardModels
,
getDashboardApiKeysUsage
,
}
;
getDashboardApiKeysUsage
}
export
default
usageAPI
;
export
default
usageAPI
Prev
1
2
Next
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