package service import ( "crypto/md5" "ego/internal/model" "ego/internal/serializer" "ego/internal/types" "ego/pkg/logger" "fmt" "io" "os" "path/filepath" "time" "github.com/gin-gonic/gin" "gorm.io/gorm" ) // SysDeployFileService 部署文件服务 type SysDeployFileService struct { Db *gorm.DB } // NewSysDeployFileService 构建部署文件服务 func NewSysDeployFileService(db *gorm.DB) *SysDeployFileService { return &SysDeployFileService{ Db: db, } } // Create 创建部署文件记录 func (s *SysDeployFileService) Create(c *gin.Context) serializer.Response { var deployFile model.SysDeployFile if err := c.ShouldBind(&deployFile); err != nil { logger.Error(c, "参数绑定失败!") return serializer.ParamErr("参数绑定失败!", err) } // 验证必填字段 if deployFile.Domain == "" { logger.Error(c, "域名不能为空!") return serializer.ParamErr("域名不能为空!", fmt.Errorf("域名不能为空")) } // 检查域名是否已存在 var existingDeployFile model.SysDeployFile if err := s.Db.Where("domain = ? AND del_flag = ?", deployFile.Domain, "0").First(&existingDeployFile).Error; err == nil { logger.Error(c, "域名已存在!") return serializer.ParamErr("域名已存在,请使用其他域名!", fmt.Errorf("域名已存在")) } // 生成部署ID if id, err := SysSequenceServiceBuilder(deployFile.TableName()).GenerateId(); err == nil { deployFile.DeployId = id } else { return serializer.DBErr("序列生成失败!", err) } // 设置默认值 now := time.Now() deployFile.CreateTime = &now deployFile.Status = model.DeployFileStatusNormal deployFile.DeployStatus = model.DeployStatusNotDeployed deployFile.DelFlag = "0" // 获取当前用户 if createBy := c.GetString("id"); createBy != "" { deployFile.CreateBy = createBy } if err := s.Db.Create(&deployFile).Error; err != nil { logger.Error(c, "创建部署文件记录失败!") return serializer.DBErr("创建部署文件记录失败!", err) } return serializer.Succ("创建部署文件记录成功!", deployFile) } // GetByID 根据ID获取部署文件记录 func (s *SysDeployFileService) GetByID(c *gin.Context) serializer.Response { // 获取当前用户ID currentUserId := c.GetString("id") if currentUserId == "" { return serializer.ParamErr("用户信息获取失败!", nil) } var deployFile model.SysDeployFile if err := s.Db.Where("deploy_id = ? AND del_flag = ? AND create_by = ?", c.Param("id"), "0", currentUserId).First(&deployFile).Error; err != nil { logger.Error(c, "获取部署文件记录失败!") return serializer.DBErr("获取部署文件记录失败!", err) } return serializer.Succ("查询成功!", deployFile) } // UpdateByID 根据ID更新部署文件记录 func (s *SysDeployFileService) UpdateByID(c *gin.Context) serializer.Response { var deployFile model.SysDeployFile if err := c.ShouldBind(&deployFile); err != nil { logger.Error(c, "参数绑定失败!") return serializer.ParamErr("参数绑定失败!", err) } id := deployFile.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 existingDeployFile model.SysDeployFile if err := s.Db.Where("deploy_id = ? AND del_flag = ? AND create_by = ?", id, "0", currentUserId).First(&existingDeployFile).Error; err != nil { logger.Error(c, "部署文件记录不存在或无权限访问!") return serializer.ParamErr("部署文件记录不存在或无权限访问!", err) } // 设置更新时间 now := time.Now() deployFile.UpdateTime = &now // 获取当前用户 deployFile.UpdateBy = currentUserId if err := s.Db.Model(&deployFile).Where("deploy_id = ? AND del_flag = ? AND create_by = ?", id, "0", currentUserId).Updates(&deployFile).Error; err != nil { logger.Error(c, "更新部署文件记录失败!") return serializer.DBErr("更新部署文件记录失败!", err) } return serializer.Succ("更新部署文件记录成功!", deployFile) } // DeleteByID 根据ID删除部署文件记录 func (s *SysDeployFileService) 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) } // 软删除 data := map[string]any{ "del_flag": "1", "update_time": time.Now(), "update_by": currentUserId, } // 删除已经部署的文件夹 deployFile := model.SysDeployFile{} if err := s.Db.Where("deploy_id = ? AND create_by = ?", id, currentUserId).First(&deployFile).Error; err != nil { logger.Error(c, "获取部署文件记录失败或无权限访问!") return serializer.DBErr("获取部署文件记录失败或无权限访问!", err) } // 删除 /home/:projectName err := os.RemoveAll(filepath.Join("/home", deployFile.ProjectName)) if err != nil { logger.Error(c, "删除部署文件夹失败!") return serializer.DBErr("删除部署文件夹失败!", err) } // 删除数据库记录 if err := s.Db.Model(&model.SysDeployFile{}).Where("deploy_id = ? AND create_by = ?", id, currentUserId).Updates(data).Error; err != nil { logger.Error(c, "删除部署文件记录失败!") return serializer.DBErr("删除部署文件记录失败!", err) } return serializer.Succ("删除部署文件记录成功!", nil) } // GetByCondition 条件查询部署文件记录 func (s *SysDeployFileService) 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 deployFiles []model.SysDeployFile offset := (p.Page - 1) * p.Limit // 获取当前用户ID currentUserId := c.GetString("id") if currentUserId == "" { return serializer.ParamErr("用户信息获取失败!", nil) } // 构建基础查询 db := s.Db.Model(&model.SysDeployFile{}) // 如果有查询条件,添加条件 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(&deployFiles).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": deployFiles, "page": p.Page, "limit": p.Limit, }) } // UpdateDeployStatus 更新部署状态 func (s *SysDeployFileService) 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.SysDeployFile{}).Where("deploy_id = ?", deployId).Updates(data).Error } // UpdateAccessInfo 更新访问信息 func (s *SysDeployFileService) UpdateAccessInfo(deployId string) error { now := time.Now() return s.Db.Model(&model.SysDeployFile{}). Where("deploy_id = ?", deployId). Updates(map[string]any{ "last_access_time": &now, "access_count": gorm.Expr("access_count + 1"), }).Error } // GetByDomain 根据域名获取部署文件记录 func (s *SysDeployFileService) GetByDomain(domain string) (*model.SysDeployFile, error) { var deployFile model.SysDeployFile err := s.Db.Where("domain = ? AND status = ? AND del_flag = ?", domain, model.DeployFileStatusNormal, "0").First(&deployFile).Error if err != nil { return nil, err } return &deployFile, nil } // CalculateFileHash 计算文件哈希值 func (s *SysDeployFileService) CalculateFileHash(reader io.Reader) (string, error) { hash := md5.New() if _, err := io.Copy(hash, reader); err != nil { return "", err } return fmt.Sprintf("%x", hash.Sum(nil)), nil }