package handlers import ( "net/http" "strconv" "time" "giteapm/internal/middleware" "giteapm/internal/models" "github.com/gin-gonic/gin" ) type CreateProjectRequest struct { Name string `json:"name" binding:"required"` Description string `json:"description"` GiteaOrg string `json:"gitea_org"` Priority string `json:"priority"` StartDate *time.Time `json:"start_date"` EndDate *time.Time `json:"end_date"` } type AddMemberRequest struct { UserID uint `json:"user_id" binding:"required"` Role string `json:"role" binding:"required"` } func (h *Handlers) ListProjects(c *gin.Context) { page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20")) offset := (page - 1) * limit filters := make(map[string]interface{}) if status := c.Query("status"); status != "" { filters["status"] = status } if priority := c.Query("priority"); priority != "" { filters["priority"] = priority } currentUser, _ := middleware.GetCurrentUser(c) if currentUser.Role != "admin" { projects, err := models.GetProjectsByUser(currentUser.ID) if err != nil { c.JSON(http.StatusInternalServerError, ErrorResponse(500, "获取项目列表失败")) return } c.JSON(http.StatusOK, SuccessResponse(projects)) return } projects, total, err := models.ListProjects(offset, limit, filters) if err != nil { c.JSON(http.StatusInternalServerError, ErrorResponse(500, "获取项目列表失败")) return } c.JSON(http.StatusOK, PaginatedSuccessResponse(projects, total, page, limit)) } func (h *Handlers) CreateProject(c *gin.Context) { var req CreateProjectRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, ErrorResponse(400, "请求参数无效")) return } currentUser, err := middleware.GetCurrentUser(c) if err != nil { c.JSON(http.StatusUnauthorized, ErrorResponse(401, "获取当前用户失败")) return } project := &models.Project{ Name: req.Name, Description: req.Description, GiteaOrg: req.GiteaOrg, Status: "planning", Priority: req.Priority, StartDate: req.StartDate, EndDate: req.EndDate, OwnerID: currentUser.ID, } if project.Priority == "" { project.Priority = "medium" } if err := models.CreateProject(project); err != nil { c.JSON(http.StatusInternalServerError, ErrorResponse(500, "创建项目失败")) return } project.AddMember(currentUser.ID, "owner") c.JSON(http.StatusCreated, SuccessResponse(project)) } func (h *Handlers) GetProject(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, ErrorResponse(400, "无效的项目ID")) return } project, err := models.GetProjectByID(uint(id)) if err != nil { c.JSON(http.StatusNotFound, ErrorResponse(404, "项目不存在")) return } c.JSON(http.StatusOK, SuccessResponse(project)) } func (h *Handlers) UpdateProject(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, ErrorResponse(400, "无效的项目ID")) return } project, err := models.GetProjectByID(uint(id)) if err != nil { c.JSON(http.StatusNotFound, ErrorResponse(404, "项目不存在")) return } var updateData map[string]interface{} if err := c.ShouldBindJSON(&updateData); err != nil { c.JSON(http.StatusBadRequest, ErrorResponse(400, "请求参数无效")) return } if name, ok := updateData["name"].(string); ok { project.Name = name } if description, ok := updateData["description"].(string); ok { project.Description = description } if status, ok := updateData["status"].(string); ok { project.Status = status } if priority, ok := updateData["priority"].(string); ok { project.Priority = priority } if err := models.UpdateProject(project); err != nil { c.JSON(http.StatusInternalServerError, ErrorResponse(500, "更新项目失败")) return } c.JSON(http.StatusOK, SuccessResponse(project)) } func (h *Handlers) DeleteProject(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, ErrorResponse(400, "无效的项目ID")) return } if err := models.DeleteProject(uint(id)); err != nil { c.JSON(http.StatusInternalServerError, ErrorResponse(500, "删除项目失败")) return } c.JSON(http.StatusOK, SuccessResponse(gin.H{"message": "删除成功"})) } func (h *Handlers) AddProjectMember(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, ErrorResponse(400, "无效的项目ID")) return } var req AddMemberRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, ErrorResponse(400, "请求参数无效")) return } project, err := models.GetProjectByID(uint(id)) if err != nil { c.JSON(http.StatusNotFound, ErrorResponse(404, "项目不存在")) return } if err := project.AddMember(req.UserID, req.Role); err != nil { c.JSON(http.StatusInternalServerError, ErrorResponse(500, "添加成员失败")) return } c.JSON(http.StatusOK, SuccessResponse(gin.H{"message": "添加成员成功"})) } func (h *Handlers) RemoveProjectMember(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, ErrorResponse(400, "无效的项目ID")) return } userID, err := strconv.ParseUint(c.Param("user_id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, ErrorResponse(400, "无效的用户ID")) return } project, err := models.GetProjectByID(uint(id)) if err != nil { c.JSON(http.StatusNotFound, ErrorResponse(404, "项目不存在")) return } if err := project.RemoveMember(uint(userID)); err != nil { c.JSON(http.StatusInternalServerError, ErrorResponse(500, "移除成员失败")) return } c.JSON(http.StatusOK, SuccessResponse(gin.H{"message": "移除成员成功"})) } func (h *Handlers) GetProjectMembers(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, ErrorResponse(400, "无效的项目ID")) return } project, err := models.GetProjectByID(uint(id)) if err != nil { c.JSON(http.StatusNotFound, ErrorResponse(404, "项目不存在")) return } members, err := project.GetMembers() if err != nil { c.JSON(http.StatusInternalServerError, ErrorResponse(500, "获取成员列表失败")) return } c.JSON(http.StatusOK, SuccessResponse(members)) }