Files
web/server/handlers/user.go
2026-03-17 01:00:11 +08:00

235 lines
5.7 KiB
Go

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": "删除成功"})
}