feat(user): 添加QQ绑定功能并重构用户登录逻辑

- 在BaseSysUser模型中添加QQ字段,移除密码字段(暂时注释)
- 移除base.bbs.go中的GetUserInfo函数,将其迁移至base_sys_user.go
- 将登录服务中的外部API调用逻辑整合到BaseSysUserService
- 新增BindQQ方法实现QQ号绑定功能,包含重复绑定检查
- 更新GetUserInfo方法,完善用户信息获取和同步逻辑
- 优化导入包,移除未使用的依赖项
```
This commit is contained in:
昔念
2026-03-24 11:56:36 +08:00
parent 705eb31007
commit 5320dffdd8
4 changed files with 148 additions and 146 deletions

View File

@@ -3,7 +3,13 @@ package service
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/http/cookiejar"
"net/url"
"strings"
"blazing/cool"
@@ -68,6 +74,35 @@ func (s *BaseSysUserService) DuihuanGold(userId uint32, gold, free int64) {
}).Update()
}
func (s *BaseSysUserService) BindQQ(username string, passworid string, qq int64) (err error) {
var res *model.BaseSysUser
cool.DBM(s.Model).Where("qq", qq).Scan(&res)
if res != nil {
err = gerror.New("该QQ已绑定其他账号" + gconv.String(res.ID))
return
}
var res1 *model.BaseSysUser
cool.DBM(s.Model).Where("id", username).Scan(&res1)
if res1 == nil {
return gerror.New("用户未激活")
}
r, err := s.GetUserInfo(username, passworid)
if err != nil {
return
}
if r == nil {
err = gerror.New("用户不存在")
return
}
_, err = cool.DBM(s.Model).Where("id", username).Data("qq", qq).Update()
if err != nil {
return err
}
return
}
func (s *BaseSysUserService) UpdateFreeGold(userId uint32, gold int64) {
m := cool.DBM(s.Model).Where("id", userId)
@@ -162,6 +197,108 @@ func (s *BaseSysUserService) Gen(user UserAttributes) (data interface{}, err err
return
}
func (s *BaseSysUserService) GetUserInfo(username, password string) (*model.BaseSysUser, error) {
// 创建带 Cookie 存储的 HTTP 客户端
jar, err := cookiejar.New(nil)
if err != nil {
return nil, fmt.Errorf("创建 CookieJar 失败: %w", err)
}
client := &http.Client{Jar: jar}
// 1. POST 获取 token
tokenURL := bbsurl + "/api/token"
formData := url.Values{}
formData.Set("identification", username)
formData.Set("password", password)
req, err := http.NewRequest("POST", tokenURL, strings.NewReader(formData.Encode()))
if err != nil {
return nil, fmt.Errorf("创建请求失败: %w", err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("发送请求失败: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("读取响应失败: %w", err)
}
// 解析 token
var tokenResp TokenResponse
err = json.Unmarshal(body, &tokenResp)
if err != nil {
return nil, fmt.Errorf("解析 token 失败: %w", err)
}
// 提取 CSRF Token
csrfToken := resp.Header.Get("X-CSRF-Token")
// 2. GET 获取该用户的详细信息
usersURL := bbsurl + fmt.Sprintf("/api/users/%d", tokenResp.UserID)
req2, err := http.NewRequest("GET", usersURL, nil)
if err != nil {
return nil, fmt.Errorf("创建请求失败: %w", err)
}
req2.Header.Set("Authentication", tokenResp.Token)
req2.Header.Set("X-CSRF-Token", csrfToken)
resp2, err := client.Do(req2)
if err != nil {
return nil, fmt.Errorf("发送请求失败: %w", err)
}
defer resp2.Body.Close()
body2, err := io.ReadAll(resp2.Body)
if err != nil {
return nil, fmt.Errorf("读取响应失败: %w", err)
}
// 解析用户信息
var userResp UserResponse
err = json.Unmarshal(body2, &userResp)
if err != nil {
return nil, fmt.Errorf("解析用户信息失败: %w", err)
}
if !strings.EqualFold(userResp.Data.Attributes.Username, username) { //说明没查找到用户
return nil, gerror.New("账户或密码不正确~")
} else {
var user *model.BaseSysUser
m := cool.DBM(s.Model).Where("username=?", username)
m.Scan(&user)
if user == nil {
s.Gen(userResp.Data.Attributes)
m := cool.DBM(s.Model).Where("username=?", username)
m.Scan(&user)
} else {
if *user.Status == 0 {
err = gerror.New("账户被封禁~")
return nil, err
}
user.HeadImg = &userResp.Data.Attributes.AvatarUrl
var ttt = *user.PasswordV + 1
user.PasswordV = &ttt
_, err := m.Save(user)
if err != nil {
log.Fatal(err)
}
cool.CacheManager.Set(context.Background(), fmt.Sprintf("admin:passwordVersion:%d", user.ID), ttt, 0)
}
return user, nil
}
return nil, nil
}
// ServiceAdd 方法 添加用户
func (s *BaseSysUserService) ServiceAdd(ctx context.Context, req *cool.AddReq) (data interface{}, err error) {
var (