diff --git a/frontend/src/components/console/ControlStrip.vue b/frontend/src/components/console/ControlStrip.vue
index 359692b..d95ad94 100644
--- a/frontend/src/components/console/ControlStrip.vue
+++ b/frontend/src/components/console/ControlStrip.vue
@@ -7,12 +7,11 @@ const { scheduleActive, startNow, startSchedule, cancelSchedule, restoreSchedule
const { reloadAccounts, queryAllScore } = useAccounts()
// 从本地缓存恢复定时设置
-const { savedTime, savedAdv } = restoreSchedule()
+const { savedTime } = restoreSchedule()
const targetTime = ref(savedTime || '18:00:00')
-const advance = ref(savedAdv)
const handleSchedule = () => {
- startSchedule(targetTime.value, advance.value)
+ startSchedule(targetTime.value)
}
@@ -47,17 +46,6 @@ const handleSchedule = () => {
step="1"
>
-
-
-
- ms
-
diff --git a/frontend/src/composables/useScheduler.ts b/frontend/src/composables/useScheduler.ts
index 71cefe9..b85bf2b 100644
--- a/frontend/src/composables/useScheduler.ts
+++ b/frontend/src/composables/useScheduler.ts
@@ -47,7 +47,7 @@ export function useScheduler() {
}
}
- const startSchedule = async (targetTime: string, advance: number) => {
+ const startSchedule = async (targetTime: string) => {
const ap = buildAccountProducts(selectedProductId.value || '')
if (!ap) return
@@ -72,13 +72,12 @@ export function useScheduler() {
clearLocalResults()
markSelectedPending('定时配置中,等待后端确认')
setRunState('定时配置中')
- addLocalLog(`设置定时: ${fullTime}, 提前=${advance}ms`, 'i')
+ addLocalLog(`设置定时: ${fullTime}`, 'i')
try {
const d = await App.SetSchedule({
accountProducts: ap,
- targetTime: fullTime,
- advance
+ targetTime: fullTime
})
if (d?.success === false) {
throw new Error(d.error || '定时设置失败')
@@ -86,7 +85,6 @@ export function useScheduler() {
scheduleActive.value = true
localStorage.setItem('targetTime', timeStr)
- localStorage.setItem('advance', String(advance))
markSelectedPending(`定时等待触发: ${d.triggerTime || fullTime}`)
setRunState(`定时已开启,触发 ${d.triggerTime}`)
@@ -113,7 +111,6 @@ export function useScheduler() {
scheduleActive.value = false
localStorage.removeItem('targetTime')
- localStorage.removeItem('advance')
stopCountdown()
setRunState('定时已停止')
showToast('定时已停止', '抢购任务已取消', 'warn')
@@ -153,8 +150,7 @@ export function useScheduler() {
const restoreSchedule = () => {
const savedTime = localStorage.getItem('targetTime')
- const savedAdv = localStorage.getItem('advance')
- return { savedTime, savedAdv: savedAdv ? parseInt(savedAdv) : 300 }
+ return { savedTime }
}
return {
diff --git a/internal/constants/constants.go b/internal/constants/constants.go
index 92ac158..119e0a8 100644
--- a/internal/constants/constants.go
+++ b/internal/constants/constants.go
@@ -25,7 +25,7 @@ const (
BindInfoURL = BaseURL + "/japi/carnivalApi/v2/tencent/bindInfo?actAlias=" + ActAlias
ScoreURL = BaseURL + "/japi/oms/web/peace/credit/balance"
UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36"
- DefaultAttempts = 1
+ DefaultAttempts = 2
DefaultConcurrency = 150
ProductCacheTTL = 30 * time.Second
diff --git a/internal/seckill/scheduler.go b/internal/seckill/scheduler.go
index 834b125..4971384 100644
--- a/internal/seckill/scheduler.go
+++ b/internal/seckill/scheduler.go
@@ -33,6 +33,8 @@ const (
seckillMaxDuration = 75 * time.Second
behaviorCooldown = 5 * time.Second
clickFastCooldown = 3 * time.Second
+ internalAdvance = 100 * time.Millisecond
+ maxCooldownCount = 5
)
type roundOutcome struct {
@@ -386,6 +388,7 @@ func (s *Scheduler) RunNow(accountProducts map[string]string) {
stoppedAccounts := make(map[string]string)
stoppedProducts := make(map[string]string)
cooldownAccounts := make(map[string]time.Time)
+ cooldownCount := make(map[string]int)
totalAccounts := uniqueAttemptAccounts(allAttempts)
totalAttempts := 0
startTime := time.Now()
@@ -463,8 +466,13 @@ func (s *Scheduler) RunNow(accountProducts map[string]string) {
for account, until := range outcome.cooldownAccounts {
if until.After(cooldownAccounts[account]) {
cooldownAccounts[account] = until
- logger.LogAccountEvent("抢购", "warn", account, "账号临时降频: 账号=%s 冷却至=%s",
- account, until.In(constants.CST).Format("15:04:05.000"))
+ cooldownCount[account]++
+ logger.LogAccountEvent("抢购", "warn", account, "账号临时降频: 账号=%s 冷却至=%s (第%d次)",
+ account, until.In(constants.CST).Format("15:04:05.000"), cooldownCount[account])
+ if cooldownCount[account] >= maxCooldownCount {
+ stoppedAccounts[account] = "冷却次数过多"
+ logger.LogAccountEvent("抢购", "warn", account, "账号停止重试: 账号=%s 原因=冷却次数过多(%d次)", account, cooldownCount[account])
+ }
}
}
@@ -1092,8 +1100,7 @@ func (s *Scheduler) ScheduleRun(req types.SeckillRequest) (map[string]any, error
calibration := s.calibrateDouyuTime("定时")
serverTime := calibration.EstimatedServerNow()
- advance := time.Duration(req.Advance) * time.Millisecond
- triggerTime := targetTime.Add(-advance)
+ triggerTime := targetTime.Add(-internalAdvance)
remain := triggerTime.Sub(serverTime)
if remain <= 0 {
return nil, errors.New("目标时间已过")
@@ -1127,7 +1134,7 @@ func (s *Scheduler) ScheduleRun(req types.SeckillRequest) (map[string]any, error
logger.LogEvent("定时", "success", "定时已设置: 目标=%s 触发=%s 提前=%dms 斗鱼估算=%s 本地偏移=%dms 误差<=%dms RTT=%dms 预热=%s 复校=%s",
targetTime.In(constants.CST).Format("2006-01-02 15:04:05.000"),
triggerTime.In(constants.CST).Format("2006-01-02 15:04:05.000"),
- req.Advance,
+ internalAdvance.Milliseconds(),
serverTime.In(constants.CST).Format("2006-01-02 15:04:05.000"),
calibration.Offset.Milliseconds(),
calibration.ErrorBound.Milliseconds(),
@@ -1139,10 +1146,7 @@ func (s *Scheduler) ScheduleRun(req types.SeckillRequest) (map[string]any, error
return map[string]any{
"success": true,
"targetTime": targetTime.In(constants.CST).Format("2006-01-02 15:04:05"),
- "triggerTime": triggerTime.In(constants.CST).Format("2006-01-02 15:04:05.000"),
- "advance": req.Advance,
- "remainSecond": int(remain.Seconds()),
- "serverTime": serverTime.In(constants.CST).Format("2006-01-02 15:04:05.000"),
+ "triggerTime": triggerTime.In(constants.CST).Format("2006-01-02 15:04:05"),
"offsetMs": calibration.Offset.Milliseconds(),
"errorBoundMs": calibration.ErrorBound.Milliseconds(),
"rttMs": calibration.RTT.Milliseconds(),
diff --git a/internal/types/types.go b/internal/types/types.go
index c815fea..75c53b1 100644
--- a/internal/types/types.go
+++ b/internal/types/types.go
@@ -90,7 +90,6 @@ type AccountView struct {
type SeckillRequest struct {
AccountProducts map[string]string `json:"accountProducts"`
TargetTime string `json:"targetTime"`
- Advance int `json:"advance"`
}
// APIResponse 斗鱼 API 通用响应。