94 lines
2.9 KiB
Go
94 lines
2.9 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"strings"
|
|
|
|
"affiliate_dash/internal/model"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// Token 生命周期事件类型。
|
|
const (
|
|
rockTokenEventCreated = "created"
|
|
rockTokenEventStatusChanged = "status_changed"
|
|
rockTokenEventDeleted = "deleted"
|
|
rockTokenEventRestored = "restored"
|
|
)
|
|
|
|
// Token 状态来源,用于前端展示流转原因。
|
|
const (
|
|
rockTokenSourceAssign = "assign"
|
|
rockTokenSourceBindCheck = "bindcheck"
|
|
rockTokenSourceRedeem = "redeem"
|
|
rockTokenSourceRefresh = "refresh"
|
|
rockTokenSourceRelease = "release"
|
|
rockTokenSourceReset = "reset"
|
|
rockTokenSourceManual = "manual"
|
|
rockTokenSourceOrderCancel = "order_cancel"
|
|
rockTokenSourcePurchase = "purchase"
|
|
rockTokenSourcePackageSync = "package_sync"
|
|
rockTokenSourceDelete = "delete"
|
|
rockTokenSourceRestore = "restore"
|
|
)
|
|
|
|
// writeRockTokenStatusLog 记录 Token 生命周期/状态变化。
|
|
//
|
|
// 采用 best-effort:日志写入失败只打印错误,不影响主流程(避免因为审计表异常阻断发货)。
|
|
func writeRockTokenStatusLog(tx *gorm.DB, token *model.RockToken, eventType, from, to, source, reason string, forced bool, actorUserID *uint) {
|
|
if tx == nil || token == nil || token.ID == 0 {
|
|
return
|
|
}
|
|
entry := &model.RockTokenStatusLog{
|
|
TokenID: token.ID,
|
|
UpstreamTokenID: strings.TrimSpace(token.UpstreamTokenID),
|
|
EventType: eventType,
|
|
FromStatus: from,
|
|
ToStatus: to,
|
|
Source: source,
|
|
Reason: truncateRunes(strings.TrimSpace(reason), 240),
|
|
Forced: forced,
|
|
ActorUserID: actorUserID,
|
|
}
|
|
if err := tx.Create(entry).Error; err != nil {
|
|
log.Printf("[Rock] 写入 Token 状态日志失败 token=%d %s->%s: %v", token.ID, from, to, err)
|
|
}
|
|
}
|
|
|
|
// writeRockTokenStatusChange 仅在状态确实发生变化时写日志。
|
|
func writeRockTokenStatusChange(tx *gorm.DB, token *model.RockToken, from, to, source, reason string, forced bool, actorUserID *uint) {
|
|
if strings.TrimSpace(from) == strings.TrimSpace(to) {
|
|
return
|
|
}
|
|
writeRockTokenStatusLog(tx, token, rockTokenEventStatusChanged, from, to, source, reason, forced, actorUserID)
|
|
}
|
|
|
|
func truncateRunes(value string, limit int) string {
|
|
if limit <= 0 {
|
|
return ""
|
|
}
|
|
runes := []rune(value)
|
|
if len(runes) <= limit {
|
|
return value
|
|
}
|
|
return string(runes[:limit])
|
|
}
|
|
|
|
// ListTokenStatusLogs 返回指定 Token 的状态历史(最新在前)。
|
|
func (s *RockService) ListTokenStatusLogs(ctx context.Context, tokenID uint) ([]model.RockTokenStatusLog, error) {
|
|
var token model.RockToken
|
|
if err := s.db.WithContext(ctx).Unscoped().First(&token, tokenID).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
var logs []model.RockTokenStatusLog
|
|
if err := s.db.WithContext(ctx).
|
|
Where("token_id = ?", tokenID).
|
|
Order("id DESC").
|
|
Limit(200).
|
|
Find(&logs).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return logs, nil
|
|
}
|