feat: kfz_token表增加login_name字段, 存储孔网登录账号

This commit is contained in:
ShenQiLun 2026-06-30 13:27:19 +08:00
parent 6c1e016672
commit fc9bd41b6d
6 changed files with 2200 additions and 53 deletions

View File

@ -70,6 +70,7 @@ func createTables() error {
CREATE TABLE IF NOT EXISTS kfz_token (
id INTEGER PRIMARY KEY AUTOINCREMENT,
login_name TEXT NOT NULL DEFAULT '',
username TEXT NOT NULL,
password TEXT NOT NULL DEFAULT '',
token TEXT NOT NULL,
@ -95,8 +96,9 @@ func createTables() error {
return err
}
// 兼容旧表:添加 password 列(已存在则忽略)
// 兼容旧表:添加 password / login_name 列(已存在则忽略)
DB.Exec(`ALTER TABLE kfz_token ADD COLUMN password TEXT NOT NULL DEFAULT ''`)
DB.Exec(`ALTER TABLE kfz_token ADD COLUMN login_name TEXT NOT NULL DEFAULT ''`)
return nil
}

View File

@ -61,10 +61,10 @@ func (h *KfzHandler) KfzLogin(w http.ResponseWriter, r *http.Request) {
userInfo.Token = token
// 保存账号密码和token到数据库
if err := h.tokenRepo.UpsertByUsername(username, password, token); err != nil {
if err := h.tokenRepo.UpsertByLoginName(username, userInfo.Nickname, password, token); err != nil {
log.Printf("[KfzLogin] 保存Token记录失败: err=%v, clientIP=%s", err, clientIP)
} else {
log.Printf("[KfzLogin] 账号密码已保存到数据库: username=%s", username)
log.Printf("[KfzLogin] 账号密码已保存到数据库: login_name=%s, nickname=%s", username, userInfo.Nickname)
}
log.Printf("[KfzLogin] 登录成功: username=%s, userId=%d, nickname=%s, 来源IP: %s", username, userInfo.UserID, userInfo.Nickname, clientIP)

View File

@ -71,7 +71,7 @@ func (h *TokenHandler) BatchAddTokens(w http.ResponseWriter, r *http.Request) {
continue
}
id, err := h.tokenRepo.Insert(input.Username, "", input.Token, true)
id, err := h.tokenRepo.Insert("", input.Username, "", input.Token, true)
if err != nil {
log.Printf("[Token/BatchAdd] 第%d条插入失败: username=%s, 错误=%v", i+1, input.Username, err)
failed = append(failed, input)
@ -196,7 +196,7 @@ func (h *TokenHandler) UpdateToken(w http.ResponseWriter, r *http.Request) {
}
log.Printf("[Token/Update] 更新: id=%d, username=%s, is_enable=%v, 来源IP: %s", id, username, isEnable, clientIP)
err = h.tokenRepo.Update(id, username, "", token, isEnable)
err = h.tokenRepo.Update(id, "", username, "", token, isEnable)
if err != nil {
log.Printf("[Token/Update] 更新失败: id=%d, 错误=%v, 来源IP: %s", id, err, clientIP)
w.Header().Set("Content-Type", "application/json")

View File

@ -12,6 +12,7 @@ import (
// KfzToken Token记录
type KfzToken struct {
ID int64
LoginName string
Username string
Password string
Token string
@ -66,11 +67,11 @@ func (r *TokenRepository) BatchInsert(tokens []string, username string) (int64,
return id, nil
}
// Insert 插入单条Token记录(含密码)
func (r *TokenRepository) Insert(username, password, token string, isEnable bool) (int64, error) {
query := `INSERT INTO kfz_token (username, password, token, is_enable) VALUES (?, ?, ?, ?)`
// Insert 插入单条Token记录
func (r *TokenRepository) Insert(loginName, username, password, token string, isEnable bool) (int64, error) {
query := `INSERT INTO kfz_token (login_name, username, password, token, is_enable) VALUES (?, ?, ?, ?, ?)`
result, err := database.DB.Exec(query, username, password, token, isEnable)
result, err := database.DB.Exec(query, loginName, username, password, token, isEnable)
if err != nil {
return 0, fmt.Errorf("插入失败: %w", err)
}
@ -83,35 +84,35 @@ func (r *TokenRepository) Insert(username, password, token string, isEnable bool
return id, nil
}
// UpsertByUsername 根据用户名插入或更新记录含密码和token
func (r *TokenRepository) UpsertByUsername(username, password, token string) error {
// UpsertByLoginName 根据登录名插入或更新记录
func (r *TokenRepository) UpsertByLoginName(loginName, username, password, token string) error {
var count int
err := database.DB.QueryRow("SELECT COUNT(*) FROM kfz_token WHERE username = ?", username).Scan(&count)
err := database.DB.QueryRow("SELECT COUNT(*) FROM kfz_token WHERE login_name = ?", loginName).Scan(&count)
if err != nil {
return fmt.Errorf("查询记录失败: %w", err)
}
if count == 0 {
_, err = database.DB.Exec(
`INSERT INTO kfz_token (username, password, token, is_enable) VALUES (?, ?, ?, 1)`,
username, password, token,
`INSERT INTO kfz_token (login_name, username, password, token, is_enable) VALUES (?, ?, ?, ?, 1)`,
loginName, username, password, token,
)
} else {
_, err = database.DB.Exec(
`UPDATE kfz_token SET password = ?, token = ?, is_enable = 1 WHERE username = ?`,
password, token, username,
`UPDATE kfz_token SET username = ?, password = ?, token = ?, is_enable = 1 WHERE login_name = ?`,
username, password, token, loginName,
)
}
if err != nil {
return fmt.Errorf("保存Token记录失败: %w", err)
}
log.Printf("[Repo/Token] 保存Token成功: username=%s", username)
log.Printf("[Repo/Token] 保存Token成功: login_name=%s, username=%s", loginName, username)
return nil
}
// GetAll 查询所有记录
func (r *TokenRepository) GetAll() ([]*KfzToken, error) {
query := `SELECT id, username, token, is_enable FROM kfz_token ORDER BY id ASC`
query := `SELECT id, login_name, username, token, is_enable FROM kfz_token ORDER BY id ASC`
rows, err := database.DB.Query(query)
if err != nil {
@ -122,7 +123,7 @@ func (r *TokenRepository) GetAll() ([]*KfzToken, error) {
var records []*KfzToken
for rows.Next() {
var rec KfzToken
err := rows.Scan(&rec.ID, &rec.Username, &rec.Token, &rec.IsEnable)
err := rows.Scan(&rec.ID, &rec.LoginName, &rec.Username, &rec.Token, &rec.IsEnable)
if err != nil {
return nil, fmt.Errorf("扫描失败: %w", err)
}
@ -134,12 +135,12 @@ func (r *TokenRepository) GetAll() ([]*KfzToken, error) {
// GetByID 根据ID查询单条记录
func (r *TokenRepository) GetByID(id int64) (*KfzToken, error) {
query := `SELECT id, username, password, token, is_enable FROM kfz_token WHERE id = ?`
query := `SELECT id, login_name, username, password, token, is_enable FROM kfz_token WHERE id = ?`
row := database.DB.QueryRow(query, id)
var rec KfzToken
err := row.Scan(&rec.ID, &rec.Username, &rec.Password, &rec.Token, &rec.IsEnable)
err := row.Scan(&rec.ID, &rec.LoginName, &rec.Username, &rec.Password, &rec.Token, &rec.IsEnable)
if err != nil {
if err == sql.ErrNoRows {
return nil, fmt.Errorf("记录不存在")
@ -150,29 +151,11 @@ func (r *TokenRepository) GetByID(id int64) (*KfzToken, error) {
return &rec, nil
}
// GetByUsername 根据用户名查询记录(含密码)
func (r *TokenRepository) GetByUsername(username string) (*KfzToken, error) {
query := `SELECT id, username, password, token, is_enable FROM kfz_token WHERE username = ?`
row := database.DB.QueryRow(query, username)
var rec KfzToken
err := row.Scan(&rec.ID, &rec.Username, &rec.Password, &rec.Token, &rec.IsEnable)
if err != nil {
if err == sql.ErrNoRows {
return nil, nil
}
return nil, fmt.Errorf("查询失败: %w", err)
}
return &rec, nil
}
// Update 更新记录
func (r *TokenRepository) Update(id int64, username, password, token string, isEnable bool) error {
query := `UPDATE kfz_token SET username = ?, password = ?, token = ?, is_enable = ? WHERE id = ?`
func (r *TokenRepository) Update(id int64, loginName, username, password, token string, isEnable bool) error {
query := `UPDATE kfz_token SET login_name = ?, username = ?, password = ?, token = ?, is_enable = ? WHERE id = ?`
result, err := database.DB.Exec(query, username, password, token, isEnable, id)
result, err := database.DB.Exec(query, loginName, username, password, token, isEnable, id)
if err != nil {
return fmt.Errorf("更新失败: %w", err)
}
@ -222,7 +205,7 @@ func (r *TokenRepository) Delete(id int64) error {
// GetEnabledTokens 获取所有启用状态的Token
func (r *TokenRepository) GetEnabledTokens() ([]*KfzToken, error) {
query := `SELECT id, username, password, token, is_enable FROM kfz_token WHERE is_enable = 1 ORDER BY id ASC`
query := `SELECT id, login_name, username, password, token, is_enable FROM kfz_token WHERE is_enable = 1 ORDER BY id ASC`
rows, err := database.DB.Query(query)
if err != nil {
@ -233,7 +216,7 @@ func (r *TokenRepository) GetEnabledTokens() ([]*KfzToken, error) {
var records []*KfzToken
for rows.Next() {
var rec KfzToken
err := rows.Scan(&rec.ID, &rec.Username, &rec.Password, &rec.Token, &rec.IsEnable)
err := rows.Scan(&rec.ID, &rec.LoginName, &rec.Username, &rec.Password, &rec.Token, &rec.IsEnable)
if err != nil {
return nil, fmt.Errorf("扫描失败: %w", err)
}

View File

@ -289,7 +289,7 @@ func (s *GoodsService) outGetAllGoods(isbn string, bookName string, author strin
s.tokenMu.Unlock()
token := tokens[currentIdx].Token
log.Printf("[outGetAllGoods] 使用token索引: index=%d, total=%d, username=%s", currentIdx, len(tokens), tokens[currentIdx].Username)
log.Printf("[outGetAllGoods] 使用token索引: index=%d, total=%d, login_name=%s, nickname=%s", currentIdx, len(tokens), tokens[currentIdx].LoginName, tokens[currentIdx].Username)
kfzUrl := "https://search.kongfz.com/pc-gw/search-web/client/pc/product/keyword/list?dataType=0&page=1&sortType=7&userArea=13003000000&quaSelect=2"
@ -346,12 +346,16 @@ func (s *GoodsService) doKfzSearch(kfzUrl, token string, tokenRecord *repository
errMsg := err.Error()
if strings.Contains(errMsg, "请登录") || strings.Contains(errMsg, "GO_LOGIN") || strings.Contains(errMsg, "errType=102") {
if attempt == 1 && tokenRecord.Password != "" {
log.Printf("[outGetAllGoods] Token已失效, 尝试自动重新登录: username=%s, id=%d", tokenRecord.Username, tokenRecord.ID)
newToken, refreshErr := s.TryRefreshToken(tokenRecord.ID, tokenRecord.Username, tokenRecord.Password)
loginName := tokenRecord.LoginName
if loginName == "" {
loginName = tokenRecord.Username
}
log.Printf("[outGetAllGoods] Token已失效, 尝试自动重新登录: login_name=%s, nickname=%s, id=%d", loginName, tokenRecord.Username, tokenRecord.ID)
newToken, refreshErr := s.TryRefreshToken(tokenRecord.ID, loginName, tokenRecord.Password)
if refreshErr != nil {
if refreshErr == ErrPasswordWrong {
s.goodsRepository.DisableToken(tokenRecord.ID)
s.reportBadPassword(tokenRecord.Username)
s.reportBadPassword(loginName)
return nil, refreshErr
}
log.Printf("[outGetAllGoods] 自动重新登录失败: err=%v", refreshErr)

File diff suppressed because it is too large Load Diff