package service import ( "ego/internal/model" "ego/internal/serializer" "ego/internal/types" "ego/pkg/logger" "fmt" "os" "time" "github.com/gin-gonic/gin" "gorm.io/gorm" ) // SysDeployProjectService 部署项目服务 type SysDeployProjectService struct { Db *gorm.DB } // NewSysDeployProjectService 构建部署项目服务 func NewSysDeployProjectService(db *gorm.DB) *SysDeployProjectService { return &SysDeployProjectService{ Db: db, } } // Create 创建部署项目记录 func (s *SysDeployProjectService) Create(c *gin.Context) serializer.Response { var deployProject model.SysDeployProject if err := c.ShouldBind(&deployProject); err != nil { logger.Error(c, "参数绑定失败!") return serializer.ParamErr("参数绑定失败!", err) } // 验证必填字段 if deployProject.Domain == "" { logger.Error(c, "域名不能为空!") return serializer.ParamErr("域名不能为空!", fmt.Errorf("域名不能为空")) } // 检查域名是否已存在 var existingDeployProject model.SysDeployProject if err := s.Db.Where("domain = ? AND del_flag = ?", deployProject.Domain, "0").First(&existingDeployProject).Error; err == nil { logger.Error(c, "域名已存在!") return serializer.ParamErr("域名已存在,请使用其他域名!", fmt.Errorf("域名已存在")) } // 生成部署ID if id, err := SysSequenceServiceBuilder(deployProject.TableName()).GenerateId(); err == nil { deployProject.DeployId = id } else { return serializer.DBErr("序列生成失败!", err) } // 设置默认部署路径 deployProject.DeployPath = fmt.Sprintf("/home/%s", deployProject.Domain) // 设置默认值 now := time.Now() deployProject.CreateTime = &now deployProject.Status = model.DeployProjectStatusNormal deployProject.DeployStatus = model.DeployStatusNotDeployed deployProject.DelFlag = "0" // 获取当前用户 if createBy := c.GetString("id"); createBy != "" { deployProject.CreateBy = createBy } // 开始事务处理 tx := s.Db.Begin() // 创建部署项目记录 if err := tx.Create(&deployProject).Error; err != nil { tx.Rollback() logger.Error(c, "创建部署项目记录失败!") return serializer.DBErr("创建部署项目记录失败!", err) } // 如果提供了FileId,则更新关联的部署文件记录的ParentId if deployProject.FileId != "" { // 检查文件是否存在且属于当前用户 currentUserId := c.GetString("id") var deployFile model.SysDeployFile if err := tx.Where("file_id = ? AND del_flag = ? AND create_by = ?", deployProject.FileId, "0", currentUserId).First(&deployFile).Error; err != nil { tx.Rollback() logger.Error(c, "关联的部署文件不存在或无权限访问!") return serializer.ParamErr("关联的部署文件不存在或无权限访问!", err) } // 更新部署文件的ParentId为当前项目的DeployId if err := tx.Model(&model.SysDeployFile{}).Where("file_id = ?", deployProject.FileId). Updates(map[string]interface{}{ "parent_id": deployProject.DeployId, "update_time": time.Now(), "update_by": currentUserId, }).Error; err != nil { tx.Rollback() logger.Error(c, "更新部署文件关联信息失败!") return serializer.DBErr("更新部署文件关联信息失败!", err) } } // 提交事务 tx.Commit() return serializer.Succ("创建部署项目记录成功!", deployProject) } // GetByID 根据ID获取部署项目记录 func (s *SysDeployProjectService) GetByID(c *gin.Context) serializer.Response { // 获取当前用户ID currentUserId := c.GetString("id") if currentUserId == "" { return serializer.ParamErr("用户信息获取失败!", nil) } var deployProject model.SysDeployProject if err := s.Db.Where("deploy_id = ? AND del_flag = ? AND create_by = ?", c.Param("id"), "0", currentUserId).First(&deployProject).Error; err != nil { logger.Error(c, "获取部署项目记录失败!") return serializer.DBErr("获取部署项目记录失败!", err) } return serializer.Succ("查询成功!", deployProject) } // UpdateByID 根据ID更新部署项目记录 func (s *SysDeployProjectService) UpdateByID(c *gin.Context) serializer.Response { var deployProject model.SysDeployProject if err := c.ShouldBind(&deployProject); err != nil { logger.Error(c, "参数绑定失败!") return serializer.ParamErr("参数绑定失败!", err) } id := deployProject.DeployId if id == "" { logger.Error(c, "id 不可为空!") return serializer.ParamErr("id不可为空!", fmt.Errorf("id不可为空")) } // 获取当前用户ID currentUserId := c.GetString("id") if currentUserId == "" { return serializer.ParamErr("用户信息获取失败!", nil) } // 检查权限:只能更新自己创建的数据 var existingDeployProject model.SysDeployProject if err := s.Db.Where("deploy_id = ? AND del_flag = ? AND create_by = ?", id, "0", currentUserId).First(&existingDeployProject).Error; err != nil { logger.Error(c, "部署项目记录不存在或无权限访问!") return serializer.ParamErr("部署项目记录不存在或无权限访问!", err) } // 设置更新时间 now := time.Now() deployProject.UpdateTime = &now // 获取当前用户 deployProject.UpdateBy = currentUserId if err := s.Db.Model(&deployProject).Where("deploy_id = ? AND del_flag = ? AND create_by = ?", id, "0", currentUserId).Updates(&deployProject).Error; err != nil { logger.Error(c, "更新部署项目记录失败!") return serializer.DBErr("更新部署项目记录失败!", err) } return serializer.Succ("更新部署项目记录成功!", deployProject) } // DeleteByID 根据ID删除部署项目记录 func (s *SysDeployProjectService) DeleteByID(c *gin.Context) serializer.Response { id := c.Param("id") if id == "" { logger.Error(c, "id 不可为空!") return serializer.ParamErr("id不可为空!", fmt.Errorf("id不可为空")) } // 获取当前用户ID currentUserId := c.GetString("id") if currentUserId == "" { return serializer.ParamErr("用户信息获取失败!", nil) } // 开始事务处理 tx := s.Db.Begin() // 获取要删除的项目信息 deployProject := model.SysDeployProject{} if err := tx.Where("deploy_id = ? AND create_by = ?", id, currentUserId).First(&deployProject).Error; err != nil { tx.Rollback() logger.Error(c, "获取部署项目记录失败或无权限访问!") return serializer.DBErr("获取部署项目记录失败或无权限访问!", err) } // 删除 /home/:domain 目录 err := os.RemoveAll(deployProject.DeployPath) if err != nil { tx.Rollback() logger.Error(c, "删除部署文件夹失败!") return serializer.DBErr("删除部署文件夹失败!", err) } // 软删除关联的文件记录 fileData := map[string]any{ "del_flag": "1", "update_time": time.Now(), "update_by": currentUserId, } if err := tx.Model(&model.SysDeployFile{}).Where("parent_id = ?", id).Updates(fileData).Error; err != nil { tx.Rollback() logger.Error(c, "删除关联文件记录失败!") return serializer.DBErr("删除关联文件记录失败!", err) } // 软删除项目记录 projectData := map[string]any{ "del_flag": "1", "update_time": time.Now(), "update_by": currentUserId, } if err := tx.Model(&model.SysDeployProject{}).Where("deploy_id = ? AND create_by = ?", id, currentUserId).Updates(projectData).Error; err != nil { tx.Rollback() logger.Error(c, "删除部署项目记录失败!") return serializer.DBErr("删除部署项目记录失败!", err) } // 提交事务 tx.Commit() return serializer.Succ("删除部署项目记录成功!", nil) } // GetByCondition 条件查询部署项目记录 func (s *SysDeployProjectService) GetByCondition(c *gin.Context) serializer.Response { var p types.Params if err := c.ShouldBind(&p); err != nil { return serializer.ParamErr("参数绑定失败!", err) } queryStr, args, err := p.ConvertToGormConditions() if err != nil { logger.Error(c, "参数绑定失败!") return serializer.ParamErr("参数绑定失败!", err) } var total int64 var deployProjects []model.SysDeployProject offset := (p.Page - 1) * p.Limit // 获取当前用户ID currentUserId := c.GetString("id") if currentUserId == "" { return serializer.ParamErr("用户信息获取失败!", nil) } // 构建基础查询 db := s.Db.Model(&model.SysDeployProject{}) // 如果有查询条件,添加条件 if queryStr != "" { db = db.Where(queryStr, args...) } // 添加用户权限过滤:只能查询自己创建的数据 db = db.Where("create_by = ?", currentUserId) // 排序 if p.Sort != "" { db = db.Order(p.Sort) } else { db = db.Order("create_time DESC") } // 执行分页查询 if err := db.Where("del_flag = ?", "0").Offset(offset).Limit(p.Limit).Find(&deployProjects).Error; err != nil { logger.Error(c, "获取部署项目记录失败!") return serializer.DBErr("获取部署项目记录失败!", err) } // 执行总数查询 if err := db.Where("del_flag = ?", "0").Count(&total).Error; err != nil { logger.Error(c, "获取部署项目记录总数失败!") return serializer.DBErr("获取部署项目记录总数失败!", err) } return serializer.Succ("查询成功!", gin.H{ "total": total, "items": deployProjects, "page": p.Page, "limit": p.Limit, }) } // UpdateDeployStatus 更新部署状态 func (s *SysDeployProjectService) UpdateDeployStatus(deployId, status, errorMsg string) error { data := map[string]any{ "deploy_status": status, "update_time": time.Now(), } if status == model.DeployStatusSuccess { now := time.Now() data["deploy_time"] = &now } if errorMsg != "" { data["error_msg"] = errorMsg } return s.Db.Model(&model.SysDeployProject{}).Where("deploy_id = ?", deployId).Updates(data).Error } // UpdateAccessInfo 更新访问信息 func (s *SysDeployProjectService) UpdateAccessInfo(deployId string) error { now := time.Now() return s.Db.Model(&model.SysDeployProject{}). Where("deploy_id = ?", deployId). Updates(map[string]any{ "last_access_time": &now, "access_count": gorm.Expr("access_count + 1"), }).Error } // GetByDomain 根据域名获取部署项目记录 func (s *SysDeployProjectService) GetByDomain(domain string) (*model.SysDeployProject, error) { var deployProject model.SysDeployProject err := s.Db.Where("domain = ? AND status = ? AND del_flag = ?", domain, model.DeployProjectStatusNormal, "0").First(&deployProject).Error if err != nil { return nil, err } return &deployProject, nil }