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
e99b344b
Commit
e99b344b
authored
Dec 19, 2025
by
Forest
Browse files
refactor(backend): 引入端口接口模式
parent
7fd94ab7
Changes
45
Hide whitespace changes
Inline
Side-by-side
backend/internal/service/redeem_service.go
View file @
e99b344b
...
...
@@ -8,7 +8,8 @@ import (
"fmt"
"strings"
"sub2api/internal/model"
"sub2api/internal/repository"
"sub2api/internal/pkg/pagination"
"sub2api/internal/service/ports"
"time"
"github.com/redis/go-redis/v9"
...
...
@@ -49,8 +50,8 @@ type RedeemCodeResponse struct {
// RedeemService 兑换码服务
type
RedeemService
struct
{
redeemRepo
*
repository
.
RedeemCodeRepository
userRepo
*
repository
.
UserRepository
redeemRepo
ports
.
RedeemCodeRepository
userRepo
ports
.
UserRepository
subscriptionService
*
SubscriptionService
rdb
*
redis
.
Client
billingCacheService
*
BillingCacheService
...
...
@@ -58,8 +59,8 @@ type RedeemService struct {
// NewRedeemService 创建兑换码服务实例
func
NewRedeemService
(
redeemRepo
*
repository
.
RedeemCodeRepository
,
userRepo
*
repository
.
UserRepository
,
redeemRepo
ports
.
RedeemCodeRepository
,
userRepo
ports
.
UserRepository
,
subscriptionService
*
SubscriptionService
,
rdb
*
redis
.
Client
,
billingCacheService
*
BillingCacheService
,
...
...
@@ -337,7 +338,7 @@ func (s *RedeemService) GetByCode(ctx context.Context, code string) (*model.Rede
}
// List 获取兑换码列表(管理员功能)
func
(
s
*
RedeemService
)
List
(
ctx
context
.
Context
,
params
repository
.
PaginationParams
)
([]
model
.
RedeemCode
,
*
repository
.
PaginationResult
,
error
)
{
func
(
s
*
RedeemService
)
List
(
ctx
context
.
Context
,
params
pagination
.
PaginationParams
)
([]
model
.
RedeemCode
,
*
pagination
.
PaginationResult
,
error
)
{
codes
,
pagination
,
err
:=
s
.
redeemRepo
.
List
(
ctx
,
params
)
if
err
!=
nil
{
return
nil
,
nil
,
fmt
.
Errorf
(
"list redeem codes: %w"
,
err
)
...
...
backend/internal/service/setting_service.go
View file @
e99b344b
...
...
@@ -7,7 +7,7 @@ import (
"strconv"
"sub2api/internal/config"
"sub2api/internal/model"
"sub2api/internal/
repository
"
"sub2api/internal/
service/ports
"
"gorm.io/gorm"
)
...
...
@@ -18,12 +18,12 @@ var (
// SettingService 系统设置服务
type
SettingService
struct
{
settingRepo
*
repository
.
SettingRepository
settingRepo
ports
.
SettingRepository
cfg
*
config
.
Config
}
// NewSettingService 创建系统设置服务实例
func
NewSettingService
(
settingRepo
*
repository
.
SettingRepository
,
cfg
*
config
.
Config
)
*
SettingService
{
func
NewSettingService
(
settingRepo
ports
.
SettingRepository
,
cfg
*
config
.
Config
)
*
SettingService
{
return
&
SettingService
{
settingRepo
:
settingRepo
,
cfg
:
cfg
,
...
...
backend/internal/service/subscription_service.go
View file @
e99b344b
...
...
@@ -7,7 +7,8 @@ import (
"time"
"sub2api/internal/model"
"sub2api/internal/repository"
"sub2api/internal/pkg/pagination"
"sub2api/internal/service/ports"
)
var
(
...
...
@@ -23,14 +24,16 @@ var (
// SubscriptionService 订阅服务
type
SubscriptionService
struct
{
repos
*
repository
.
Repositories
groupRepo
ports
.
GroupRepository
userSubRepo
ports
.
UserSubscriptionRepository
billingCacheService
*
BillingCacheService
}
// NewSubscriptionService 创建订阅服务
func
NewSubscriptionService
(
repos
*
repository
.
Repositor
ies
,
billingCacheService
*
BillingCacheService
)
*
SubscriptionService
{
func
NewSubscriptionService
(
groupRepo
ports
.
GroupRepository
,
userSubRepo
ports
.
UserSubscription
Repositor
y
,
billingCacheService
*
BillingCacheService
)
*
SubscriptionService
{
return
&
SubscriptionService
{
repos
:
repos
,
groupRepo
:
groupRepo
,
userSubRepo
:
userSubRepo
,
billingCacheService
:
billingCacheService
,
}
}
...
...
@@ -47,7 +50,7 @@ type AssignSubscriptionInput struct {
// AssignSubscription 分配订阅给用户(不允许重复分配)
func
(
s
*
SubscriptionService
)
AssignSubscription
(
ctx
context
.
Context
,
input
*
AssignSubscriptionInput
)
(
*
model
.
UserSubscription
,
error
)
{
// 检查分组是否存在且为订阅类型
group
,
err
:=
s
.
repos
.
Group
.
GetByID
(
ctx
,
input
.
GroupID
)
group
,
err
:=
s
.
groupRepo
.
GetByID
(
ctx
,
input
.
GroupID
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"group not found: %w"
,
err
)
}
...
...
@@ -56,7 +59,7 @@ func (s *SubscriptionService) AssignSubscription(ctx context.Context, input *Ass
}
// 检查是否已存在订阅
exists
,
err
:=
s
.
repos
.
UserSubscription
.
ExistsByUserIDAndGroupID
(
ctx
,
input
.
UserID
,
input
.
GroupID
)
exists
,
err
:=
s
.
userSubRepo
.
ExistsByUserIDAndGroupID
(
ctx
,
input
.
UserID
,
input
.
GroupID
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -90,7 +93,7 @@ func (s *SubscriptionService) AssignSubscription(ctx context.Context, input *Ass
// 如果没有订阅:创建新订阅
func
(
s
*
SubscriptionService
)
AssignOrExtendSubscription
(
ctx
context
.
Context
,
input
*
AssignSubscriptionInput
)
(
*
model
.
UserSubscription
,
bool
,
error
)
{
// 检查分组是否存在且为订阅类型
group
,
err
:=
s
.
repos
.
Group
.
GetByID
(
ctx
,
input
.
GroupID
)
group
,
err
:=
s
.
groupRepo
.
GetByID
(
ctx
,
input
.
GroupID
)
if
err
!=
nil
{
return
nil
,
false
,
fmt
.
Errorf
(
"group not found: %w"
,
err
)
}
...
...
@@ -99,7 +102,7 @@ func (s *SubscriptionService) AssignOrExtendSubscription(ctx context.Context, in
}
// 查询是否已有订阅
existingSub
,
err
:=
s
.
repos
.
UserSubscription
.
GetByUserIDAndGroupID
(
ctx
,
input
.
UserID
,
input
.
GroupID
)
existingSub
,
err
:=
s
.
userSubRepo
.
GetByUserIDAndGroupID
(
ctx
,
input
.
UserID
,
input
.
GroupID
)
if
err
!=
nil
{
// 不存在记录是正常情况,其他错误需要返回
existingSub
=
nil
...
...
@@ -124,13 +127,13 @@ func (s *SubscriptionService) AssignOrExtendSubscription(ctx context.Context, in
}
// 更新过期时间
if
err
:=
s
.
repos
.
UserSubscription
.
ExtendExpiry
(
ctx
,
existingSub
.
ID
,
newExpiresAt
);
err
!=
nil
{
if
err
:=
s
.
userSubRepo
.
ExtendExpiry
(
ctx
,
existingSub
.
ID
,
newExpiresAt
);
err
!=
nil
{
return
nil
,
false
,
fmt
.
Errorf
(
"extend subscription: %w"
,
err
)
}
// 如果订阅已过期或被暂停,恢复为active状态
if
existingSub
.
Status
!=
model
.
SubscriptionStatusActive
{
if
err
:=
s
.
repos
.
UserSubscription
.
UpdateStatus
(
ctx
,
existingSub
.
ID
,
model
.
SubscriptionStatusActive
);
err
!=
nil
{
if
err
:=
s
.
userSubRepo
.
UpdateStatus
(
ctx
,
existingSub
.
ID
,
model
.
SubscriptionStatusActive
);
err
!=
nil
{
return
nil
,
false
,
fmt
.
Errorf
(
"update subscription status: %w"
,
err
)
}
}
...
...
@@ -142,7 +145,7 @@ func (s *SubscriptionService) AssignOrExtendSubscription(ctx context.Context, in
newNotes
+=
"
\n
"
}
newNotes
+=
input
.
Notes
if
err
:=
s
.
repos
.
UserSubscription
.
UpdateNotes
(
ctx
,
existingSub
.
ID
,
newNotes
);
err
!=
nil
{
if
err
:=
s
.
userSubRepo
.
UpdateNotes
(
ctx
,
existingSub
.
ID
,
newNotes
);
err
!=
nil
{
// 备注更新失败不影响主流程
}
}
...
...
@@ -158,7 +161,7 @@ func (s *SubscriptionService) AssignOrExtendSubscription(ctx context.Context, in
}
// 返回更新后的订阅
sub
,
err
:=
s
.
repos
.
UserSubscription
.
GetByID
(
ctx
,
existingSub
.
ID
)
sub
,
err
:=
s
.
userSubRepo
.
GetByID
(
ctx
,
existingSub
.
ID
)
return
sub
,
true
,
err
// true 表示是续期
}
...
...
@@ -205,12 +208,12 @@ func (s *SubscriptionService) createSubscription(ctx context.Context, input *Ass
sub
.
AssignedBy
=
&
input
.
AssignedBy
}
if
err
:=
s
.
repos
.
UserSubscription
.
Create
(
ctx
,
sub
);
err
!=
nil
{
if
err
:=
s
.
userSubRepo
.
Create
(
ctx
,
sub
);
err
!=
nil
{
return
nil
,
err
}
// 重新获取完整订阅信息(包含关联)
return
s
.
repos
.
UserSubscription
.
GetByID
(
ctx
,
sub
.
ID
)
return
s
.
userSubRepo
.
GetByID
(
ctx
,
sub
.
ID
)
}
// BulkAssignSubscriptionInput 批量分配订阅输入
...
...
@@ -260,12 +263,12 @@ func (s *SubscriptionService) BulkAssignSubscription(ctx context.Context, input
// RevokeSubscription 撤销订阅
func
(
s
*
SubscriptionService
)
RevokeSubscription
(
ctx
context
.
Context
,
subscriptionID
int64
)
error
{
// 先获取订阅信息用于失效缓存
sub
,
err
:=
s
.
repos
.
UserSubscription
.
GetByID
(
ctx
,
subscriptionID
)
sub
,
err
:=
s
.
userSubRepo
.
GetByID
(
ctx
,
subscriptionID
)
if
err
!=
nil
{
return
err
}
if
err
:=
s
.
repos
.
UserSubscription
.
Delete
(
ctx
,
subscriptionID
);
err
!=
nil
{
if
err
:=
s
.
userSubRepo
.
Delete
(
ctx
,
subscriptionID
);
err
!=
nil
{
return
err
}
...
...
@@ -284,20 +287,20 @@ func (s *SubscriptionService) RevokeSubscription(ctx context.Context, subscripti
// ExtendSubscription 延长订阅
func
(
s
*
SubscriptionService
)
ExtendSubscription
(
ctx
context
.
Context
,
subscriptionID
int64
,
days
int
)
(
*
model
.
UserSubscription
,
error
)
{
sub
,
err
:=
s
.
repos
.
UserSubscription
.
GetByID
(
ctx
,
subscriptionID
)
sub
,
err
:=
s
.
userSubRepo
.
GetByID
(
ctx
,
subscriptionID
)
if
err
!=
nil
{
return
nil
,
ErrSubscriptionNotFound
}
// 计算新的过期时间
newExpiresAt
:=
sub
.
ExpiresAt
.
AddDate
(
0
,
0
,
days
)
if
err
:=
s
.
repos
.
UserSubscription
.
ExtendExpiry
(
ctx
,
subscriptionID
,
newExpiresAt
);
err
!=
nil
{
if
err
:=
s
.
userSubRepo
.
ExtendExpiry
(
ctx
,
subscriptionID
,
newExpiresAt
);
err
!=
nil
{
return
nil
,
err
}
// 如果订阅已过期,恢复为active状态
if
sub
.
Status
==
model
.
SubscriptionStatusExpired
{
if
err
:=
s
.
repos
.
UserSubscription
.
UpdateStatus
(
ctx
,
subscriptionID
,
model
.
SubscriptionStatusActive
);
err
!=
nil
{
if
err
:=
s
.
userSubRepo
.
UpdateStatus
(
ctx
,
subscriptionID
,
model
.
SubscriptionStatusActive
);
err
!=
nil
{
return
nil
,
err
}
}
...
...
@@ -312,17 +315,17 @@ func (s *SubscriptionService) ExtendSubscription(ctx context.Context, subscripti
}()
}
return
s
.
repos
.
UserSubscription
.
GetByID
(
ctx
,
subscriptionID
)
return
s
.
userSubRepo
.
GetByID
(
ctx
,
subscriptionID
)
}
// GetByID 根据ID获取订阅
func
(
s
*
SubscriptionService
)
GetByID
(
ctx
context
.
Context
,
id
int64
)
(
*
model
.
UserSubscription
,
error
)
{
return
s
.
repos
.
UserSubscription
.
GetByID
(
ctx
,
id
)
return
s
.
userSubRepo
.
GetByID
(
ctx
,
id
)
}
// GetActiveSubscription 获取用户对特定分组的有效订阅
func
(
s
*
SubscriptionService
)
GetActiveSubscription
(
ctx
context
.
Context
,
userID
,
groupID
int64
)
(
*
model
.
UserSubscription
,
error
)
{
sub
,
err
:=
s
.
repos
.
UserSubscription
.
GetActiveByUserIDAndGroupID
(
ctx
,
userID
,
groupID
)
sub
,
err
:=
s
.
userSubRepo
.
GetActiveByUserIDAndGroupID
(
ctx
,
userID
,
groupID
)
if
err
!=
nil
{
return
nil
,
ErrSubscriptionNotFound
}
...
...
@@ -331,24 +334,24 @@ func (s *SubscriptionService) GetActiveSubscription(ctx context.Context, userID,
// ListUserSubscriptions 获取用户的所有订阅
func
(
s
*
SubscriptionService
)
ListUserSubscriptions
(
ctx
context
.
Context
,
userID
int64
)
([]
model
.
UserSubscription
,
error
)
{
return
s
.
repos
.
UserSubscription
.
ListByUserID
(
ctx
,
userID
)
return
s
.
userSubRepo
.
ListByUserID
(
ctx
,
userID
)
}
// ListActiveUserSubscriptions 获取用户的所有有效订阅
func
(
s
*
SubscriptionService
)
ListActiveUserSubscriptions
(
ctx
context
.
Context
,
userID
int64
)
([]
model
.
UserSubscription
,
error
)
{
return
s
.
repos
.
UserSubscription
.
ListActiveByUserID
(
ctx
,
userID
)
return
s
.
userSubRepo
.
ListActiveByUserID
(
ctx
,
userID
)
}
// ListGroupSubscriptions 获取分组的所有订阅
func
(
s
*
SubscriptionService
)
ListGroupSubscriptions
(
ctx
context
.
Context
,
groupID
int64
,
page
,
pageSize
int
)
([]
model
.
UserSubscription
,
*
repository
.
PaginationResult
,
error
)
{
params
:=
repository
.
PaginationParams
{
Page
:
page
,
PageSize
:
pageSize
}
return
s
.
repos
.
UserSubscription
.
ListByGroupID
(
ctx
,
groupID
,
params
)
func
(
s
*
SubscriptionService
)
ListGroupSubscriptions
(
ctx
context
.
Context
,
groupID
int64
,
page
,
pageSize
int
)
([]
model
.
UserSubscription
,
*
pagination
.
PaginationResult
,
error
)
{
params
:=
pagination
.
PaginationParams
{
Page
:
page
,
PageSize
:
pageSize
}
return
s
.
userSubRepo
.
ListByGroupID
(
ctx
,
groupID
,
params
)
}
// List 获取所有订阅(分页,支持筛选)
func
(
s
*
SubscriptionService
)
List
(
ctx
context
.
Context
,
page
,
pageSize
int
,
userID
,
groupID
*
int64
,
status
string
)
([]
model
.
UserSubscription
,
*
repository
.
PaginationResult
,
error
)
{
params
:=
repository
.
PaginationParams
{
Page
:
page
,
PageSize
:
pageSize
}
return
s
.
repos
.
UserSubscription
.
List
(
ctx
,
params
,
userID
,
groupID
,
status
)
func
(
s
*
SubscriptionService
)
List
(
ctx
context
.
Context
,
page
,
pageSize
int
,
userID
,
groupID
*
int64
,
status
string
)
([]
model
.
UserSubscription
,
*
pagination
.
PaginationResult
,
error
)
{
params
:=
pagination
.
PaginationParams
{
Page
:
page
,
PageSize
:
pageSize
}
return
s
.
userSubRepo
.
List
(
ctx
,
params
,
userID
,
groupID
,
status
)
}
// CheckAndActivateWindow 检查并激活窗口(首次使用时)
...
...
@@ -358,7 +361,7 @@ func (s *SubscriptionService) CheckAndActivateWindow(ctx context.Context, sub *m
}
now
:=
time
.
Now
()
return
s
.
repos
.
UserSubscription
.
ActivateWindows
(
ctx
,
sub
.
ID
,
now
)
return
s
.
userSubRepo
.
ActivateWindows
(
ctx
,
sub
.
ID
,
now
)
}
// CheckAndResetWindows 检查并重置过期的窗口
...
...
@@ -367,7 +370,7 @@ func (s *SubscriptionService) CheckAndResetWindows(ctx context.Context, sub *mod
// 日窗口重置(24小时)
if
sub
.
NeedsDailyReset
()
{
if
err
:=
s
.
repos
.
UserSubscription
.
ResetDailyUsage
(
ctx
,
sub
.
ID
,
now
);
err
!=
nil
{
if
err
:=
s
.
userSubRepo
.
ResetDailyUsage
(
ctx
,
sub
.
ID
,
now
);
err
!=
nil
{
return
err
}
sub
.
DailyWindowStart
=
&
now
...
...
@@ -376,7 +379,7 @@ func (s *SubscriptionService) CheckAndResetWindows(ctx context.Context, sub *mod
// 周窗口重置(7天)
if
sub
.
NeedsWeeklyReset
()
{
if
err
:=
s
.
repos
.
UserSubscription
.
ResetWeeklyUsage
(
ctx
,
sub
.
ID
,
now
);
err
!=
nil
{
if
err
:=
s
.
userSubRepo
.
ResetWeeklyUsage
(
ctx
,
sub
.
ID
,
now
);
err
!=
nil
{
return
err
}
sub
.
WeeklyWindowStart
=
&
now
...
...
@@ -385,7 +388,7 @@ func (s *SubscriptionService) CheckAndResetWindows(ctx context.Context, sub *mod
// 月窗口重置(30天)
if
sub
.
NeedsMonthlyReset
()
{
if
err
:=
s
.
repos
.
UserSubscription
.
ResetMonthlyUsage
(
ctx
,
sub
.
ID
,
now
);
err
!=
nil
{
if
err
:=
s
.
userSubRepo
.
ResetMonthlyUsage
(
ctx
,
sub
.
ID
,
now
);
err
!=
nil
{
return
err
}
sub
.
MonthlyWindowStart
=
&
now
...
...
@@ -411,7 +414,7 @@ func (s *SubscriptionService) CheckUsageLimits(ctx context.Context, sub *model.U
// RecordUsage 记录使用量到订阅
func
(
s
*
SubscriptionService
)
RecordUsage
(
ctx
context
.
Context
,
subscriptionID
int64
,
costUSD
float64
)
error
{
return
s
.
repos
.
UserSubscription
.
IncrementUsage
(
ctx
,
subscriptionID
,
costUSD
)
return
s
.
userSubRepo
.
IncrementUsage
(
ctx
,
subscriptionID
,
costUSD
)
}
// SubscriptionProgress 订阅进度
...
...
@@ -438,14 +441,14 @@ type UsageWindowProgress struct {
// GetSubscriptionProgress 获取订阅使用进度
func
(
s
*
SubscriptionService
)
GetSubscriptionProgress
(
ctx
context
.
Context
,
subscriptionID
int64
)
(
*
SubscriptionProgress
,
error
)
{
sub
,
err
:=
s
.
repos
.
UserSubscription
.
GetByID
(
ctx
,
subscriptionID
)
sub
,
err
:=
s
.
userSubRepo
.
GetByID
(
ctx
,
subscriptionID
)
if
err
!=
nil
{
return
nil
,
ErrSubscriptionNotFound
}
group
:=
sub
.
Group
if
group
==
nil
{
group
,
err
=
s
.
repos
.
Group
.
GetByID
(
ctx
,
sub
.
GroupID
)
group
,
err
=
s
.
groupRepo
.
GetByID
(
ctx
,
sub
.
GroupID
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -535,7 +538,7 @@ func (s *SubscriptionService) GetSubscriptionProgress(ctx context.Context, subsc
// GetUserSubscriptionsWithProgress 获取用户所有订阅及进度
func
(
s
*
SubscriptionService
)
GetUserSubscriptionsWithProgress
(
ctx
context
.
Context
,
userID
int64
)
([]
SubscriptionProgress
,
error
)
{
subs
,
err
:=
s
.
repos
.
UserSubscription
.
ListActiveByUserID
(
ctx
,
userID
)
subs
,
err
:=
s
.
userSubRepo
.
ListActiveByUserID
(
ctx
,
userID
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -554,7 +557,7 @@ func (s *SubscriptionService) GetUserSubscriptionsWithProgress(ctx context.Conte
// UpdateExpiredSubscriptions 更新过期订阅状态(定时任务调用)
func
(
s
*
SubscriptionService
)
UpdateExpiredSubscriptions
(
ctx
context
.
Context
)
(
int64
,
error
)
{
return
s
.
repos
.
UserSubscription
.
BatchUpdateExpiredStatus
(
ctx
)
return
s
.
userSubRepo
.
BatchUpdateExpiredStatus
(
ctx
)
}
// ValidateSubscription 验证订阅是否有效
...
...
@@ -567,7 +570,7 @@ func (s *SubscriptionService) ValidateSubscription(ctx context.Context, sub *mod
}
if
sub
.
IsExpired
()
{
// 更新状态
_
=
s
.
repos
.
UserSubscription
.
UpdateStatus
(
ctx
,
sub
.
ID
,
model
.
SubscriptionStatusExpired
)
_
=
s
.
userSubRepo
.
UpdateStatus
(
ctx
,
sub
.
ID
,
model
.
SubscriptionStatusExpired
)
return
ErrSubscriptionExpired
}
return
nil
...
...
backend/internal/service/usage_service.go
View file @
e99b344b
...
...
@@ -5,7 +5,8 @@ import (
"errors"
"fmt"
"sub2api/internal/model"
"sub2api/internal/repository"
"sub2api/internal/pkg/pagination"
"sub2api/internal/service/ports"
"time"
"gorm.io/gorm"
...
...
@@ -41,24 +42,24 @@ type CreateUsageLogRequest struct {
// UsageStats 使用统计
type
UsageStats
struct
{
TotalRequests
int64
`json:"total_requests"`
TotalInputTokens
int64
`json:"total_input_tokens"`
TotalOutputTokens
int64
`json:"total_output_tokens"`
TotalCacheTokens
int64
`json:"total_cache_tokens"`
TotalTokens
int64
`json:"total_tokens"`
TotalCost
float64
`json:"total_cost"`
TotalActualCost
float64
`json:"total_actual_cost"`
AverageDurationMs
float64
`json:"average_duration_ms"`
TotalRequests
int64
`json:"total_requests"`
TotalInputTokens
int64
`json:"total_input_tokens"`
TotalOutputTokens
int64
`json:"total_output_tokens"`
TotalCacheTokens
int64
`json:"total_cache_tokens"`
TotalTokens
int64
`json:"total_tokens"`
TotalCost
float64
`json:"total_cost"`
TotalActualCost
float64
`json:"total_actual_cost"`
AverageDurationMs
float64
`json:"average_duration_ms"`
}
// UsageService 使用统计服务
type
UsageService
struct
{
usageRepo
*
repository
.
UsageLogRepository
userRepo
*
repository
.
UserRepository
usageRepo
ports
.
UsageLogRepository
userRepo
ports
.
UserRepository
}
// NewUsageService 创建使用统计服务实例
func
NewUsageService
(
usageRepo
*
repository
.
UsageLogRepository
,
userRepo
*
repository
.
UserRepository
)
*
UsageService
{
func
NewUsageService
(
usageRepo
ports
.
UsageLogRepository
,
userRepo
ports
.
UserRepository
)
*
UsageService
{
return
&
UsageService
{
usageRepo
:
usageRepo
,
userRepo
:
userRepo
,
...
...
@@ -127,7 +128,7 @@ func (s *UsageService) GetByID(ctx context.Context, id int64) (*model.UsageLog,
}
// ListByUser 获取用户的使用日志列表
func
(
s
*
UsageService
)
ListByUser
(
ctx
context
.
Context
,
userID
int64
,
params
repository
.
PaginationParams
)
([]
model
.
UsageLog
,
*
repository
.
PaginationResult
,
error
)
{
func
(
s
*
UsageService
)
ListByUser
(
ctx
context
.
Context
,
userID
int64
,
params
pagination
.
PaginationParams
)
([]
model
.
UsageLog
,
*
pagination
.
PaginationResult
,
error
)
{
logs
,
pagination
,
err
:=
s
.
usageRepo
.
ListByUser
(
ctx
,
userID
,
params
)
if
err
!=
nil
{
return
nil
,
nil
,
fmt
.
Errorf
(
"list usage logs: %w"
,
err
)
...
...
@@ -136,7 +137,7 @@ func (s *UsageService) ListByUser(ctx context.Context, userID int64, params repo
}
// ListByApiKey 获取API Key的使用日志列表
func
(
s
*
UsageService
)
ListByApiKey
(
ctx
context
.
Context
,
apiKeyID
int64
,
params
repository
.
PaginationParams
)
([]
model
.
UsageLog
,
*
repository
.
PaginationResult
,
error
)
{
func
(
s
*
UsageService
)
ListByApiKey
(
ctx
context
.
Context
,
apiKeyID
int64
,
params
pagination
.
PaginationParams
)
([]
model
.
UsageLog
,
*
pagination
.
PaginationResult
,
error
)
{
logs
,
pagination
,
err
:=
s
.
usageRepo
.
ListByApiKey
(
ctx
,
apiKeyID
,
params
)
if
err
!=
nil
{
return
nil
,
nil
,
fmt
.
Errorf
(
"list usage logs: %w"
,
err
)
...
...
@@ -145,7 +146,7 @@ func (s *UsageService) ListByApiKey(ctx context.Context, apiKeyID int64, params
}
// ListByAccount 获取账号的使用日志列表
func
(
s
*
UsageService
)
ListByAccount
(
ctx
context
.
Context
,
accountID
int64
,
params
repository
.
PaginationParams
)
([]
model
.
UsageLog
,
*
repository
.
PaginationResult
,
error
)
{
func
(
s
*
UsageService
)
ListByAccount
(
ctx
context
.
Context
,
accountID
int64
,
params
pagination
.
PaginationParams
)
([]
model
.
UsageLog
,
*
pagination
.
PaginationResult
,
error
)
{
logs
,
pagination
,
err
:=
s
.
usageRepo
.
ListByAccount
(
ctx
,
accountID
,
params
)
if
err
!=
nil
{
return
nil
,
nil
,
fmt
.
Errorf
(
"list usage logs: %w"
,
err
)
...
...
@@ -233,15 +234,15 @@ func (s *UsageService) GetDailyStats(ctx context.Context, userID int64, days int
}
result
=
append
(
result
,
map
[
string
]
interface
{}{
"date"
:
date
,
"total_requests"
:
stats
.
TotalRequests
,
"total_input_tokens"
:
stats
.
TotalInputTokens
,
"total_output_tokens"
:
stats
.
TotalOutputTokens
,
"total_cache_tokens"
:
stats
.
TotalCacheTokens
,
"total_tokens"
:
stats
.
TotalTokens
,
"total_cost"
:
stats
.
TotalCost
,
"total_actual_cost"
:
stats
.
TotalActualCost
,
"average_duration_ms"
:
stats
.
AverageDurationMs
,
"date"
:
date
,
"total_requests"
:
stats
.
TotalRequests
,
"total_input_tokens"
:
stats
.
TotalInputTokens
,
"total_output_tokens"
:
stats
.
TotalOutputTokens
,
"total_cache_tokens"
:
stats
.
TotalCacheTokens
,
"total_tokens"
:
stats
.
TotalTokens
,
"total_cost"
:
stats
.
TotalCost
,
"total_actual_cost"
:
stats
.
TotalActualCost
,
"average_duration_ms"
:
stats
.
AverageDurationMs
,
})
}
...
...
backend/internal/service/user_service.go
View file @
e99b344b
...
...
@@ -6,16 +6,17 @@ import (
"fmt"
"sub2api/internal/config"
"sub2api/internal/model"
"sub2api/internal/repository"
"sub2api/internal/pkg/pagination"
"sub2api/internal/service/ports"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
var
(
ErrUserNotFound
=
errors
.
New
(
"user not found"
)
ErrPasswordIncorrect
=
errors
.
New
(
"current password is incorrect"
)
ErrInsufficientPerms
=
errors
.
New
(
"insufficient permissions"
)
ErrUserNotFound
=
errors
.
New
(
"user not found"
)
ErrPasswordIncorrect
=
errors
.
New
(
"current password is incorrect"
)
ErrInsufficientPerms
=
errors
.
New
(
"insufficient permissions"
)
)
// UpdateProfileRequest 更新用户资料请求
...
...
@@ -32,12 +33,12 @@ type ChangePasswordRequest struct {
// UserService 用户服务
type
UserService
struct
{
userRepo
*
repository
.
UserRepository
userRepo
ports
.
UserRepository
cfg
*
config
.
Config
}
// NewUserService 创建用户服务实例
func
NewUserService
(
userRepo
*
repository
.
UserRepository
,
cfg
*
config
.
Config
)
*
UserService
{
func
NewUserService
(
userRepo
ports
.
UserRepository
,
cfg
*
config
.
Config
)
*
UserService
{
return
&
UserService
{
userRepo
:
userRepo
,
cfg
:
cfg
,
...
...
@@ -133,7 +134,7 @@ func (s *UserService) GetByID(ctx context.Context, id int64) (*model.User, error
}
// List 获取用户列表(管理员功能)
func
(
s
*
UserService
)
List
(
ctx
context
.
Context
,
params
repository
.
PaginationParams
)
([]
model
.
User
,
*
repository
.
PaginationResult
,
error
)
{
func
(
s
*
UserService
)
List
(
ctx
context
.
Context
,
params
pagination
.
PaginationParams
)
([]
model
.
User
,
*
pagination
.
PaginationResult
,
error
)
{
users
,
pagination
,
err
:=
s
.
userRepo
.
List
(
ctx
,
params
)
if
err
!=
nil
{
return
nil
,
nil
,
fmt
.
Errorf
(
"list users: %w"
,
err
)
...
...
Prev
1
2
3
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