package projects import ( "errors" "net/http" "github.com/gin-gonic/gin" "gorm.io/gorm" "senlinai-agent/backend/internal/httpx" "senlinai-agent/backend/internal/logic/auth" ) // Handler 仅负责项目核心读写和工作区读取;任务、标签、资料、计划任务由各自 registrar 承担。 type Handler struct { service *Service } // NewHandler 创建项目核心 HTTP registrar。 func NewHandler(service *Service) *Handler { return &Handler{service: service} } // Register 将项目核心接口注册到上层提供的 /api/v1 路由组。 func (h *Handler) Register(router gin.IRouter) { router.POST("/projects", h.createProject) router.GET("/projects", h.listProjects) router.GET("/projects/:id", h.getProject) router.PATCH("/projects/:id", h.updateProject) router.GET("/projects/:id/workspace", h.workspace) } func (h *Handler) createProject(c *gin.Context) { userID, ok := auth.CurrentUserID(c) if !ok { httpx.Error(c, http.StatusUnauthorized, "unauthorized", "未登录或登录已失效") return } var input CreateProjectRequest if err := c.ShouldBindJSON(&input); err != nil { httpx.Error(c, http.StatusBadRequest, "invalid_request", "请求参数无效") return } project, err := h.service.CreateProjectWithInput(userID, input) if err != nil { writeProjectError(c, err) return } c.JSON(http.StatusCreated, projectDTO(*project)) } func (h *Handler) listProjects(c *gin.Context) { userID, ok := auth.CurrentUserID(c) if !ok { httpx.Error(c, http.StatusUnauthorized, "unauthorized", "未登录或登录已失效") return } projects, err := h.service.ListProjects(userID) if err != nil { httpx.Error(c, http.StatusInternalServerError, "internal_error", "项目列表加载失败") return } c.JSON(http.StatusOK, projects) } func (h *Handler) getProject(c *gin.Context) { userID, ok := auth.CurrentUserID(c) if !ok { httpx.Error(c, http.StatusUnauthorized, "unauthorized", "未登录或登录已失效") return } identity, ok := httpx.IdentityParam(c, "id") if !ok { return } project, err := h.service.GetProject(userID, identity) if err != nil { writeProjectError(c, err) return } c.JSON(http.StatusOK, project) } func (h *Handler) updateProject(c *gin.Context) { userID, ok := auth.CurrentUserID(c) if !ok { httpx.Error(c, http.StatusUnauthorized, "unauthorized", "未登录或登录已失效") return } identity, ok := httpx.IdentityParam(c, "id") if !ok { return } var input UpdateProjectRequest if err := c.ShouldBindJSON(&input); err != nil { httpx.Error(c, http.StatusBadRequest, "invalid_request", "请求参数无效") return } if err := h.service.UpdateProject(userID, identity, input); err != nil { writeProjectError(c, err) return } c.Status(http.StatusNoContent) } func (h *Handler) workspace(c *gin.Context) { userID, ok := auth.CurrentUserID(c) if !ok { httpx.Error(c, http.StatusUnauthorized, "unauthorized", "未登录或登录已失效") return } projectIdentity, ok := httpx.IdentityParam(c, "id") if !ok { return } workspace, err := h.service.Workspace(userID, projectIdentity) if err != nil { writeProjectError(c, err) return } c.JSON(http.StatusOK, workspace) } func writeProjectError(c *gin.Context, err error) { switch { case errors.Is(err, gorm.ErrRecordNotFound): httpx.Error(c, http.StatusNotFound, "not_found", "项目不存在") case errors.Is(err, ErrProjectIdentifierConflict): httpx.Error(c, http.StatusConflict, "conflict", "项目标识已存在") case errors.Is(err, ErrProjectNameRequired), errors.Is(err, ErrProjectIdentifierRequired): httpx.Error(c, http.StatusBadRequest, "invalid_request", "请求参数无效") default: httpx.Error(c, http.StatusInternalServerError, "internal_error", "项目操作失败") } }