feat:rock增加手动刷新Token按钮

This commit is contained in:
2026-11-03 12:37:05 +08:00
parent f69cdc6d8e
commit d6530b47f4
7 changed files with 166 additions and 16 deletions
+55 -16
View File
@@ -11,11 +11,12 @@ import (
"affiliate_dash/internal/model"
)
// RockLoginTestResult 是「测试登录」返回给管理端的结果,不含 token。
// RockLoginTestResult 是「测试登录 / 刷新 Token」返回给管理端的结果,不含 token。
type RockLoginTestResult struct {
Username string `json:"username"`
Role string `json:"role"`
Points float64 `json:"points"`
Username string `json:"username"`
Role string `json:"role"`
Points float64 `json:"points"`
RefreshedAt string `json:"refreshed_at,omitempty"`
}
func (s *RockService) hasLoginCredentials(cfg *model.RockConfig) bool {
@@ -90,17 +91,54 @@ func (s *RockService) loginAndSaveToken(ctx context.Context, cfg *model.RockConf
if latest.LastTokenRefreshAt != nil && time.Since(*latest.LastTokenRefreshAt) < 30*time.Second {
return nil
}
_, _, err = s.refreshTokenWithLogin(ctx, latest)
return err
}
password, err := s.decryptLoginPassword(latest)
// RefreshTokenNow 手动强制登录刷新 Token,不检查当前 token 是否有效。
func (s *RockService) RefreshTokenNow(ctx context.Context) (*RockLoginTestResult, error) {
s.tokenMu.Lock()
defer s.tokenMu.Unlock()
cfg, err := s.GetConfig(ctx)
if err != nil {
s.recordTokenError(ctx, latest.ID, err.Error())
return err
return nil, err
}
resp, err := s.client.Login(ctx, latest.LoginUsername, password)
if !s.hasLoginCredentials(cfg) {
return nil, errors.New("请先在配置中保存上游登录账号与密码")
}
resp, me, err := s.refreshTokenWithLogin(ctx, cfg)
if err != nil {
return nil, err
}
result := &RockLoginTestResult{
Username: resp.ResolveUsername(),
Role: resp.ResolveRole(),
RefreshedAt: time.Now().Format("2006-01-02 15:04:05"),
}
if me != nil {
result.Points = me.User.Points.Float64()
if result.Username == "" {
result.Username = me.User.Username
}
}
log.Printf("[RockService] 手动刷新 Token 成功: user=%s", result.Username)
return result, nil
}
// refreshTokenWithLogin 登录上游、保存新 token 并刷新用户快照;调用方需持有 tokenMu。
func (s *RockService) refreshTokenWithLogin(ctx context.Context, cfg *model.RockConfig) (*RockLoginResponse, *RockMeResponse, error) {
password, err := s.decryptLoginPassword(cfg)
if err != nil {
s.recordTokenError(ctx, cfg.ID, err.Error())
return nil, nil, err
}
resp, err := s.client.Login(ctx, cfg.LoginUsername, password)
if err != nil {
message := "上游登录失败: " + err.Error()
s.recordTokenError(ctx, latest.ID, message)
return errors.New(message)
s.recordTokenError(ctx, cfg.ID, message)
return nil, nil, errors.New(message)
}
now := time.Now()
@@ -114,17 +152,18 @@ func (s *RockService) loginAndSaveToken(ctx context.Context, cfg *model.RockConf
updates["username"] = username
}
if err := s.db.WithContext(ctx).Model(&model.RockConfig{}).
Where("id = ?", latest.ID).
Where("id = ?", cfg.ID).
Updates(updates).Error; err != nil {
return err
return nil, nil, err
}
// 新 token 立即拉一次用户信息,顺带刷新积分与心跳。
if me, meErr := s.client.GetMe(ctx, resp.Token); meErr == nil && me != nil {
s.markTokenHealthy(ctx, latest.ID, me)
var me *RockMeResponse
if latest, meErr := s.client.GetMe(ctx, resp.Token); meErr == nil && latest != nil {
me = latest
s.markTokenHealthy(ctx, cfg.ID, me)
}
log.Printf("[RockService] 自动登录刷新 Token 成功: user=%s", resp.ResolveUsername())
return nil
return resp, me, nil
}
func (s *RockService) markTokenHealthy(ctx context.Context, cfgID uint, me *RockMeResponse) {