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
5c2e7ae2
Commit
5c2e7ae2
authored
Dec 20, 2025
by
shaw
Browse files
fix: 调整订阅计费时间窗口为每日0点
- 窗口激活/重置时使用当天零点而非精确时间 - 使用服务器本地时区计算零点(支持 UTC+8 等时区) - 窗口重置时失效 Redis 缓存,避免数据不一致
parent
420bedd6
Changes
1
Hide whitespace changes
Inline
Side-by-side
backend/internal/service/subscription_service.go
View file @
5c2e7ae2
...
...
@@ -354,45 +354,61 @@ func (s *SubscriptionService) List(ctx context.Context, page, pageSize int, user
return
s
.
userSubRepo
.
List
(
ctx
,
params
,
userID
,
groupID
,
status
)
}
// startOfDay 返回给定时间所在日期的零点(保持原时区)
func
startOfDay
(
t
time
.
Time
)
time
.
Time
{
return
time
.
Date
(
t
.
Year
(),
t
.
Month
(),
t
.
Day
(),
0
,
0
,
0
,
0
,
t
.
Location
())
}
// CheckAndActivateWindow 检查并激活窗口(首次使用时)
func
(
s
*
SubscriptionService
)
CheckAndActivateWindow
(
ctx
context
.
Context
,
sub
*
model
.
UserSubscription
)
error
{
if
sub
.
IsWindowActivated
()
{
return
nil
}
now
:=
time
.
Now
()
return
s
.
userSubRepo
.
ActivateWindows
(
ctx
,
sub
.
ID
,
now
)
// 使用当天零点作为窗口起始时间
windowStart
:=
startOfDay
(
time
.
Now
())
return
s
.
userSubRepo
.
ActivateWindows
(
ctx
,
sub
.
ID
,
windowStart
)
}
// CheckAndResetWindows 检查并重置过期的窗口
func
(
s
*
SubscriptionService
)
CheckAndResetWindows
(
ctx
context
.
Context
,
sub
*
model
.
UserSubscription
)
error
{
now
:=
time
.
Now
()
// 使用当天零点作为新窗口起始时间
windowStart
:=
startOfDay
(
time
.
Now
())
needsInvalidateCache
:=
false
// 日窗口重置(24小时)
if
sub
.
NeedsDailyReset
()
{
if
err
:=
s
.
userSubRepo
.
ResetDailyUsage
(
ctx
,
sub
.
ID
,
now
);
err
!=
nil
{
if
err
:=
s
.
userSubRepo
.
ResetDailyUsage
(
ctx
,
sub
.
ID
,
windowStart
);
err
!=
nil
{
return
err
}
sub
.
DailyWindowStart
=
&
now
sub
.
DailyWindowStart
=
&
windowStart
sub
.
DailyUsageUSD
=
0
needsInvalidateCache
=
true
}
// 周窗口重置(7天)
if
sub
.
NeedsWeeklyReset
()
{
if
err
:=
s
.
userSubRepo
.
ResetWeeklyUsage
(
ctx
,
sub
.
ID
,
now
);
err
!=
nil
{
if
err
:=
s
.
userSubRepo
.
ResetWeeklyUsage
(
ctx
,
sub
.
ID
,
windowStart
);
err
!=
nil
{
return
err
}
sub
.
WeeklyWindowStart
=
&
now
sub
.
WeeklyWindowStart
=
&
windowStart
sub
.
WeeklyUsageUSD
=
0
needsInvalidateCache
=
true
}
// 月窗口重置(30天)
if
sub
.
NeedsMonthlyReset
()
{
if
err
:=
s
.
userSubRepo
.
ResetMonthlyUsage
(
ctx
,
sub
.
ID
,
now
);
err
!=
nil
{
if
err
:=
s
.
userSubRepo
.
ResetMonthlyUsage
(
ctx
,
sub
.
ID
,
windowStart
);
err
!=
nil
{
return
err
}
sub
.
MonthlyWindowStart
=
&
now
sub
.
MonthlyWindowStart
=
&
windowStart
sub
.
MonthlyUsageUSD
=
0
needsInvalidateCache
=
true
}
// 如果有窗口被重置,失效 Redis 缓存以保持一致性
if
needsInvalidateCache
&&
s
.
billingCacheService
!=
nil
{
_
=
s
.
billingCacheService
.
InvalidateSubscription
(
ctx
,
sub
.
UserID
,
sub
.
GroupID
)
}
return
nil
...
...
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