Files
MonkeyCode/backend/internal/workspace/handler/http/v1/workspace.go

296 lines
8.8 KiB
Go
Raw Normal View History

package v1
import (
"fmt"
"log/slog"
"github.com/GoYoko/web"
"github.com/chaitin/MonkeyCode/backend/domain"
"github.com/chaitin/MonkeyCode/backend/internal/middleware"
)
type WorkspaceFileHandler struct {
usecase domain.WorkspaceFileUsecase
logger *slog.Logger
}
func NewWorkspaceFileHandler(
w *web.Web,
usecase domain.WorkspaceFileUsecase,
auth *middleware.AuthMiddleware,
active *middleware.ActiveMiddleware,
logger *slog.Logger,
) *WorkspaceFileHandler {
h := &WorkspaceFileHandler{
usecase: usecase,
logger: logger.With("handler", "workspace_file"),
}
// 设置路由
g := w.Group("/api/v1/workspace/files")
g.Use(auth.Auth(), active.Active("user"))
g.POST("", web.BindHandler(h.Create))
g.GET("/:id", web.BindHandler(h.GetByID))
g.PUT("/:id", web.BindHandler(h.Update))
g.DELETE("/:id", web.BaseHandler(h.Delete))
g.GET("", web.BindHandler(h.List))
g.POST("/batch", web.BindHandler(h.BatchCreate))
g.PUT("/batch", web.BindHandler(h.BatchUpdate))
g.POST("/sync", web.BindHandler(h.Sync))
g.GET("/by-path", web.BindHandler(h.GetByPath))
return h
}
// Create 创建工作区文件
//
// @Tags WorkspaceFile
// @Summary 创建工作区文件
// @Description 创建一个新的工作区文件
// @ID create-workspace-file
// @Accept json
// @Produce json
// @Param file body domain.CreateWorkspaceFileReq true "文件信息"
// @Success 200 {object} web.Resp{data=domain.WorkspaceFile}
// @Router /api/v1/workspace/files [post]
func (h *WorkspaceFileHandler) Create(c *web.Context, req domain.CreateWorkspaceFileReq) error {
user := middleware.GetUser(c)
req.UserID = user.ID
file, err := h.usecase.Create(c.Request().Context(), &req)
if err != nil {
h.logger.Error("failed to create workspace file", "error", err, "path", req.Path)
return err
}
return c.Success(file)
}
// GetByID 根据ID获取工作区文件
//
// @Tags WorkspaceFile
// @Summary 根据ID获取工作区文件
// @Description 根据文件ID获取工作区文件详情
// @ID get-workspace-file-by-id
// @Accept json
// @Produce json
// @Param id path string true "文件ID"
// @Success 200 {object} web.Resp{data=domain.WorkspaceFile}
// @Router /api/v1/workspace/files/{id} [get]
func (h *WorkspaceFileHandler) GetByID(c *web.Context, req struct {
ID string `param:"id" validate:"required"`
},
) error {
file, err := h.usecase.GetByID(c.Request().Context(), req.ID)
if err != nil {
h.logger.Error("failed to get workspace file", "error", err, "id", req.ID)
return err
}
return c.Success(file)
}
// GetAndSave
//
// @Tags WorkspaceFile
// @Summary 获取并保存工作区文件
// @Accept json
// @Produce json
// @Param req body domain.GetAndSaveReq true "请求参数"
// @Success 200 {object} web.Resp{}
// @Router /api/v1/workspace/files/get-and-save [post]
2025-07-25 17:54:38 +08:00
func (h *WorkspaceFileHandler) GetAndSave(ctx *web.Context, req *domain.GetAndSaveReq) error {
err := h.usecase.GetAndSave(ctx.Request().Context(), req)
2025-07-24 16:14:07 +08:00
if err != nil {
h.logger.Error("failed to get and save workspace files", "error", err, "count", len(req.FileMetas))
return err
2025-07-24 16:14:07 +08:00
}
return ctx.Success(nil)
2025-07-24 16:14:07 +08:00
}
// Update 更新工作区文件
//
// @Tags WorkspaceFile
// @Summary 更新工作区文件
// @Description 更新指定的工作区文件
// @ID update-workspace-file
// @Accept json
// @Produce json
// @Param id path string true "文件ID"
// @Param file body domain.UpdateWorkspaceFileReq true "更新信息"
// @Success 200 {object} web.Resp{data=domain.WorkspaceFile}
// @Router /api/v1/workspace/files/{id} [put]
func (h *WorkspaceFileHandler) Update(c *web.Context, req struct {
ID string `param:"id" validate:"required"`
domain.UpdateWorkspaceFileReq
},
) error {
req.UpdateWorkspaceFileReq.ID = req.ID
file, err := h.usecase.Update(c.Request().Context(), &req.UpdateWorkspaceFileReq)
if err != nil {
h.logger.Error("failed to update workspace file", "error", err, "id", req.ID)
return err
}
return c.Success(file)
}
// Delete 删除工作区文件
//
// @Tags WorkspaceFile
// @Summary 删除工作区文件
// @Description 删除指定的工作区文件
// @ID delete-workspace-file
// @Accept json
// @Produce json
// @Param id path string true "文件ID"
// @Success 200 {object} web.Resp{}
// @Router /api/v1/workspace/files/{id} [delete]
func (h *WorkspaceFileHandler) Delete(c *web.Context) error {
id := c.Param("id")
if id == "" {
return fmt.Errorf("file ID is required")
}
err := h.usecase.Delete(c.Request().Context(), id)
if err != nil {
h.logger.Error("failed to delete workspace file", "error", err, "id", id)
return err
}
return c.Success(nil)
}
// List 获取工作区文件列表
//
// @Tags WorkspaceFile
// @Summary 获取工作区文件列表
// @Description 分页获取工作区文件列表
// @ID list-workspace-files
// @Accept json
// @Produce json
// @Param query query domain.ListWorkspaceFileReq true "查询参数"
// @Success 200 {object} web.Resp{data=domain.ListWorkspaceFileResp}
// @Router /api/v1/workspace/files [get]
func (h *WorkspaceFileHandler) List(c *web.Context, req domain.ListWorkspaceFileReq) error {
user := middleware.GetUser(c)
// 如果没有指定用户ID则使用当前用户ID
if req.UserID == "" {
req.UserID = user.ID
}
resp, err := h.usecase.List(c.Request().Context(), &req)
if err != nil {
h.logger.Error("failed to list workspace files", "error", err)
return err
}
return c.Success(resp)
}
// BatchCreate 批量创建工作区文件
//
// @Tags WorkspaceFile
// @Summary 批量创建工作区文件
// @Description 批量创建多个工作区文件
// @ID batch-create-workspace-files
// @Accept json
// @Produce json
// @Param files body domain.BatchCreateWorkspaceFileReq true "文件列表"
// @Success 200 {object} web.Resp{data=[]domain.WorkspaceFile}
// @Router /api/v1/workspace/files/batch [post]
func (h *WorkspaceFileHandler) BatchCreate(c *web.Context, req domain.BatchCreateWorkspaceFileReq) error {
user := middleware.GetUser(c)
req.UserID = user.ID
files, err := h.usecase.BatchCreate(c.Request().Context(), &req)
if err != nil {
h.logger.Error("failed to batch create workspace files", "error", err, "count", len(req.Files))
return err
}
return c.Success(files)
}
// BatchUpdate 批量更新工作区文件
//
// @Tags WorkspaceFile
// @Summary 批量更新工作区文件
// @Description 批量更新多个工作区文件
// @ID batch-update-workspace-files
// @Accept json
// @Produce json
// @Param files body domain.BatchUpdateWorkspaceFileReq true "文件列表"
// @Success 200 {object} web.Resp{data=[]domain.WorkspaceFile}
// @Router /api/v1/workspace/files/batch [put]
func (h *WorkspaceFileHandler) BatchUpdate(c *web.Context, req domain.BatchUpdateWorkspaceFileReq) error {
files, err := h.usecase.BatchUpdate(c.Request().Context(), &req)
if err != nil {
h.logger.Error("failed to batch update workspace files", "error", err, "count", len(req.Files))
return err
}
return c.Success(files)
}
// Sync 同步工作区文件
//
// @Tags WorkspaceFile
// @Summary 同步工作区文件
// @Description 同步本地文件到工作区,智能检测新增、修改和删除
// @ID sync-workspace-files
// @Accept json
// @Produce json
// @Param sync body domain.SyncWorkspaceFileReq true "同步信息"
// @Success 200 {object} web.Resp{data=domain.SyncWorkspaceFileResp}
// @Router /api/v1/workspace/files/sync [post]
func (h *WorkspaceFileHandler) Sync(c *web.Context, req domain.SyncWorkspaceFileReq) error {
user := middleware.GetUser(c)
req.UserID = user.ID
resp, err := h.usecase.Sync(c.Request().Context(), &req)
if err != nil {
h.logger.Error("failed to sync workspace files", "error", err, "count", len(req.Files))
return err
}
return c.Success(resp)
}
// GetByPath 根据路径获取工作区文件
//
// @Tags WorkspaceFile
// @Summary 根据路径获取工作区文件
// @Description 根据用户ID、项目ID和文件路径获取工作区文件
// @ID get-workspace-file-by-path
// @Accept json
// @Produce json
// @Param user_id query string false "用户ID"
// @Param project_id query string true "项目ID"
// @Param path query string true "文件路径"
// @Success 200 {object} web.Resp{data=domain.WorkspaceFile}
// @Router /api/v1/workspace/files/by-path [get]
func (h *WorkspaceFileHandler) GetByPath(c *web.Context, req struct {
UserID string `query:"user_id"`
WorkspaceID string `query:"workspace_id" validate:"required"`
Path string `query:"path" validate:"required"`
},
) error {
user := middleware.GetUser(c)
// 如果没有指定用户ID则使用当前用户ID
if req.UserID == "" {
req.UserID = user.ID
}
file, err := h.usecase.GetByPath(c.Request().Context(), req.UserID, req.WorkspaceID, req.Path)
if err != nil {
h.logger.Error("failed to get workspace file by path", "error", err, "path", req.Path)
return err
}
return c.Success(file)
}