package api import ( "context" "fmt" "net/http" "strconv" "strings" "time" "server/internal/grpc" ) type YMTUsersAPI struct { grpcClient *grpc.UserClient } func YMTUsersHandler(grpcAddr string) http.Handler { var api *YMTUsersAPI if grpcAddr != "" { client, err := grpc.NewUserClient(grpcAddr) if err != nil { // 如果 gRPC 连接失败,记录错误但继续运行(降级处理) // 在实际调用时会返回错误 } else { api = &YMTUsersAPI{grpcClient: client} } } if api == nil { // 如果没有 gRPC 客户端,创建一个空的 API(会返回错误) api = &YMTUsersAPI{} } return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { p := strings.TrimPrefix(r.URL.Path, "/api/ymt/users") if r.Method == http.MethodGet && p == "" { api.list(w, r) return } w.WriteHeader(http.StatusNotFound) }) } func (a *YMTUsersAPI) list(w http.ResponseWriter, r *http.Request) { if a.grpcClient == nil { fail(w, r, http.StatusInternalServerError, "gRPC client not initialized") return } limitStr := r.URL.Query().Get("limit") limit := 2000 if limitStr != "" { if n, err := strconv.Atoi(limitStr); err == nil && n > 0 && n <= 10000 { limit = n } } // 获取搜索关键词(如果有) keyword := r.URL.Query().Get("q") // 创建带超时的 context ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second) defer cancel() // 调用 gRPC 服务 resp, err := a.grpcClient.SimpleListAllUser(ctx, keyword) if err != nil { fail(w, r, http.StatusInternalServerError, fmt.Sprintf("gRPC call failed: %v", err)) return } // 转换响应格式 out := []map[string]interface{}{} for i, user := range resp.GetList() { if i >= limit { break } if user == nil { continue } // 构建显示名称:realname(id)或 username(id) displayName := user.GetRealname() if displayName == "" { displayName = user.GetUsername() } userId := user.GetId() if displayName == "" { displayName = strconv.FormatInt(int64(userId), 10) } display := fmt.Sprintf("%s(%d)", displayName, userId) out = append(out, map[string]interface{}{ "id": userId, "name": display, }) } ok(w, r, out) }