package handlers import ( "context" "errors" "net/http" "time" "go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options" "yh_web/server/config" "yh_web/server/models" "yh_web/server/utils" "github.com/gin-gonic/gin" ) func GetUsers(c *gin.Context) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() coll := config.GetDB(config.DBName).Collection("users") page := 1 pageSize := 20 if p := c.Query("page"); p != "" { if v, err := parseInt(p); err == nil && v > 0 { page = v } } if ps := c.Query("page_size"); ps != "" { if v, err := parseInt(ps); err == nil && v > 0 && v <= 100 { pageSize = v } } skip := (page - 1) * pageSize opts := options.Find().SetSkip(int64(skip)).SetLimit(int64(pageSize)).SetSort(bson.D{{Key: "_id", Value: -1}}) cursor, err := coll.Find(ctx, bson.M{}, opts) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } defer cursor.Close(ctx) var users []models.User if err = cursor.All(ctx, &users); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } total, _ := coll.CountDocuments(ctx, bson.M{}) c.JSON(http.StatusOK, gin.H{ "list": users, "total": total, "page": page, "page_size": pageSize, }) } func GetUserByID(c *gin.Context) { id := c.Param("id") oid, err := bson.ObjectIDFromHex(id) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的 ID"}) return } ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() var user models.User err = config.GetDB(config.DBName).Collection("users").FindOne(ctx, bson.M{"_id": oid}).Decode(&user) if err != nil { if errors.Is(err, mongo.ErrNoDocuments) { c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"}) return } c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, user) } func CreateUser(c *gin.Context) { var input models.UserCreateInput if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() coll := config.GetDB(config.DBName).Collection("users") // 检查用户名是否已存在 var exist models.User if err := coll.FindOne(ctx, bson.M{"username": input.Username}).Decode(&exist); err == nil { c.JSON(http.StatusConflict, gin.H{"error": "用户名已存在"}) return } if err := coll.FindOne(ctx, bson.M{"email": input.Email}).Decode(&exist); err == nil { c.JSON(http.StatusConflict, gin.H{"error": "邮箱已存在"}) return } if input.Role == "" { input.Role = "user" } roleID := input.RoleID if roleID == 0 { roleID = models.RoleIDUser } doc := bson.M{ "username": input.Username, "email": input.Email, "password": utils.HashPassword(input.Password), "role": input.Role, "role_id": roleID, "is_beta": input.IsBeta, } if input.TrialStartDate != "" { doc["trial_start_date"] = input.TrialStartDate } if input.TrialEndDate != "" { doc["trial_end_date"] = input.TrialEndDate } if input.LLM != "" { doc["llm"] = input.LLM } res, err := coll.InsertOne(ctx, doc) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, gin.H{"id": res.InsertedID, "message": "创建成功"}) } func UpdateUser(c *gin.Context) { id := c.Param("id") oid, err := bson.ObjectIDFromHex(id) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的 ID"}) return } var input models.UserUpdateInput if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() update := bson.M{} if input.Username != nil { update["username"] = *input.Username } if input.Email != nil { update["email"] = *input.Email } if input.Password != nil && *input.Password != "" { update["password"] = utils.HashPassword(*input.Password) } if input.Role != nil { update["role"] = *input.Role } if input.IsBeta != nil { update["is_beta"] = *input.IsBeta } if input.TrialStartDate != nil { update["trial_start_date"] = *input.TrialStartDate } if input.TrialEndDate != nil { update["trial_end_date"] = *input.TrialEndDate } if input.LLM != nil { update["llm"] = *input.LLM } if input.RoleID != nil { update["role_id"] = *input.RoleID } if len(update) == 0 { c.JSON(http.StatusBadRequest, gin.H{"error": "无有效更新字段"}) return } res, err := config.GetDB(config.DBName).Collection("users").UpdateOne(ctx, bson.M{"_id": oid}, bson.M{"$set": update}) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } if res.MatchedCount == 0 { c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"}) return } c.JSON(http.StatusOK, gin.H{"message": "更新成功"}) } func DeleteUser(c *gin.Context) { id := c.Param("id") oid, err := bson.ObjectIDFromHex(id) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无效的 ID"}) return } ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() res, err := config.GetDB(config.DBName).Collection("users").DeleteOne(ctx, bson.M{"_id": oid}) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } if res.DeletedCount == 0 { c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"}) return } c.JSON(http.StatusOK, gin.H{"message": "删除成功"}) }