fix(api): 修复用户列表接口查询和去重逻辑
- 移除无效的查询参数处理,简化SQL查询语句 - 修复对用户ID的重复数据去重逻辑,确保结果唯一 - 统一代码格式和缩进,提高代码可读性 - 保留按user_id升序排序及查询限制功能 - 保证接口在无匹配路由时返回404状态码
This commit is contained in:
parent
9c34250d3e
commit
5608897284
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue