diff --git a/frontend/src/components/account/AccountTable.vue b/frontend/src/components/account/AccountTable.vue
index af0db30..a7b8e9b 100644
--- a/frontend/src/components/account/AccountTable.vue
+++ b/frontend/src/components/account/AccountTable.vue
@@ -42,7 +42,7 @@ const getStatusInfo = (name: string, selected: boolean) => {
if (obj.ok) return { text: '成功', cls: 'status-success' }
const msg = String(obj.message || '')
if (msg.includes('库存已耗完')) return { text: '库存耗尽', cls: 'status-warn' }
- if (msg.includes('兑换上限')) return { text: '已达上限', cls: 'status-warn' }
+ if (msg.includes('兑换上限') || msg.includes('已抢到')) return { text: '已抢到', cls: 'status-success' }
if (msg.includes('未绑定')) return { text: '未绑定', cls: 'status-fail' }
if (msg.includes('精英手册')) return { text: '资格不足', cls: 'status-fail' }
return { text: selected ? '未命中' : '失败', cls: selected ? 'status-warn' : 'status-fail' }
diff --git a/frontend/src/components/modal/SettingsModal.vue b/frontend/src/components/modal/SettingsModal.vue
index 1ed09aa..d167c90 100644
--- a/frontend/src/components/modal/SettingsModal.vue
+++ b/frontend/src/components/modal/SettingsModal.vue
@@ -145,9 +145,8 @@ defineExpose({ open, close })
⚠️ 自动停止条件
- - 成功 - 抢到商品
+ - 成功 - 抢到商品(含兑换上限)
- 库存耗尽 - 商品本次活动库存已耗完
- - 兑换上限 - 该账号已达本次活动兑换上限
- 未绑定 - 账号未绑定角色
- 资格不足 - 需要开通精英手册
- 超时 - 75秒抢购窗口结束
diff --git a/internal/seckill/scheduler.go b/internal/seckill/scheduler.go
index 1843508..6a208f6 100644
--- a/internal/seckill/scheduler.go
+++ b/internal/seckill/scheduler.go
@@ -391,7 +391,7 @@ func (s *Scheduler) executeRound(attempts []types.ExchangeAttempt) roundOutcome
mu.Unlock()
} else {
logger.LogEvent("抢购", "info", "尝试: %s %s 第%d包 %s", result.Account, result.Product, result.Attempt, result.Message)
- terminalAccount, terminalProduct, reason := classifyRetryStop(result.Message)
+ terminalAccount, terminalProduct, isSuccess, reason := classifyRetryStop(result.Message)
if terminalAccount || terminalProduct {
mu.Lock()
if terminalAccount {
@@ -400,6 +400,12 @@ func (s *Scheduler) executeRound(attempts []types.ExchangeAttempt) roundOutcome
if terminalProduct {
outcome.stoppedProducts[attempt.Product.CommodityID] = reason
}
+ // 兑换上限也算成功
+ if isSuccess {
+ outcome.successAccounts[attempt.Account.Name] = true
+ logger.LogEvent("抢购", "success", "成功(兑换上限): %s %s 第%d包", result.Account, result.Product, result.Attempt)
+ go image.SaveSuccessImage(attempt.Account, attempt.Product, result.RoleName, s.font, s.paths.SuccessDir)
+ }
mu.Unlock()
}
}
@@ -430,18 +436,18 @@ func jitterDuration(base time.Duration) time.Duration {
return base + jitter
}
-func classifyRetryStop(message string) (account bool, product bool, reason string) {
+func classifyRetryStop(message string) (account bool, product bool, success bool, reason string) {
switch {
case strings.Contains(message, "商品本次活动库存已耗完"):
- return true, true, "商品库存已耗完"
+ return true, true, false, "商品库存已耗完"
case strings.Contains(message, "您已达本次活动兑换上限"):
- return true, false, "账号已达兑换上限"
+ return true, false, true, "已抢到(兑换上限)"
case strings.Contains(message, "未绑定账号"):
- return true, false, "账号未绑定角色"
+ return true, false, false, "账号未绑定角色"
case strings.Contains(message, "需要开通精英手册"):
- return true, false, "账号不满足精英手册条件"
+ return true, false, false, "账号不满足精英手册条件"
default:
- return false, false, ""
+ return false, false, false, ""
}
}