fix(api): 修复用户列表接口查询和去重逻辑

- 移除无效的查询参数处理,简化SQL查询语句
- 修复对用户ID的重复数据去重逻辑,确保结果唯一
- 统一代码格式和缩进,提高代码可读性
- 保留按user_id升序排序及查询限制功能
- 保证接口在无匹配路由时返回404状态码
This commit is contained in:
zhouyonggao 2025-12-18 23:06:32 +08:00
parent 9c34250d3e
commit 5608897284
1 changed files with 56 additions and 60 deletions

View File

@ -1,76 +1,72 @@
package api package api
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
) )
type YMTUsersAPI struct { type YMTUsersAPI struct {
ymt *sql.DB ymt *sql.DB
} }
func YMTUsersHandler(ymt *sql.DB) http.Handler { func YMTUsersHandler(ymt *sql.DB) http.Handler {
api := &YMTUsersAPI{ymt: ymt} api := &YMTUsersAPI{ymt: ymt}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
p := strings.TrimPrefix(r.URL.Path, "/api/ymt/users") p := strings.TrimPrefix(r.URL.Path, "/api/ymt/users")
if r.Method == http.MethodGet && p == "" { if r.Method == http.MethodGet && p == "" {
api.list(w, r) api.list(w, r)
return return
} }
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusNotFound)
}) })
} }
func (a *YMTUsersAPI) list(w http.ResponseWriter, r *http.Request) { func (a *YMTUsersAPI) list(w http.ResponseWriter, r *http.Request) {
q := r.URL.Query().Get("q") limitStr := r.URL.Query().Get("limit")
limitStr := r.URL.Query().Get("limit") limit := 2000
limit := 2000 if limitStr != "" {
if limitStr != "" { if n, err := strconv.Atoi(limitStr); err == nil && n > 0 && n <= 10000 {
if n, err := strconv.Atoi(limitStr); err == nil && n > 0 && n <= 10000 { limit = n } limit = n
} }
sql1 := "SELECT DISTINCT user_id, COALESCE(user_name, '') AS name FROM activity WHERE user_id IS NOT NULL" }
args := []interface{}{} sql1 := "SELECT DISTINCT user_id, COALESCE(user_name, '') AS name FROM activity WHERE user_id IS NOT NULL"
if q != "" { args := []interface{}{}
sql1 += " AND (CAST(user_id AS CHAR) LIKE ? OR user_name LIKE ?)" sql1 += " ORDER BY user_id ASC LIMIT ?"
like := "%" + q + "%" args = append(args, limit)
args = append(args, like, like) rows, err := a.ymt.Query(sql1, args...)
} if err != nil {
sql1 += " ORDER BY user_id ASC LIMIT ?" fail(w, r, http.StatusInternalServerError, err.Error())
args = append(args, limit) return
rows, err := a.ymt.Query(sql1, args...) }
if err != nil { defer rows.Close()
fail(w, r, http.StatusInternalServerError, err.Error())
return
}
defer rows.Close()
out := []map[string]interface{}{} out := []map[string]interface{}{}
used := map[int64]struct{}{} used := map[int64]struct{}{}
for rows.Next() { for rows.Next() {
var id sql.NullInt64 var id sql.NullInt64
var name sql.NullString var name sql.NullString
if err := rows.Scan(&id, &name); err != nil { if err := rows.Scan(&id, &name); err != nil {
continue continue
} }
if !id.Valid { if !id.Valid {
continue continue
} }
if _, ok := used[id.Int64]; ok { if _, ok := used[id.Int64]; ok {
// 根据 ID 去重 // 根据 ID 去重
continue continue
} }
used[id.Int64] = struct{}{} used[id.Int64] = struct{}{}
n := strings.TrimSpace(name.String) n := strings.TrimSpace(name.String)
if n == "" { if n == "" {
n = strconv.FormatInt(id.Int64, 10) n = strconv.FormatInt(id.Int64, 10)
} }
display := fmt.Sprintf("%s%d", n, id.Int64) display := fmt.Sprintf("%s%d", n, id.Int64)
out = append(out, map[string]interface{}{"id": id.Int64, "name": display}) out = append(out, map[string]interface{}{"id": id.Int64, "name": display})
} }
ok(w, r, out) ok(w, r, out)
} }