DeployHelper/internal/service/sys_deploy_file_service.go

362 lines
11 KiB
Go
Raw Normal View History

2025-08-01 16:38:08 +08:00
package service
import (
"crypto/md5"
"ego/internal/model"
"ego/internal/serializer"
"ego/internal/types"
"ego/pkg/logger"
"fmt"
"io"
"os"
"path/filepath"
"strings"
2025-08-01 16:38:08 +08:00
"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 {
// 获取上传的文件
file, err := c.FormFile("file")
if err != nil {
logger.Error(c, "获取上传文件失败!")
return serializer.ParamErr("获取上传文件失败!", err)
2025-08-01 16:38:08 +08:00
}
// 校验文件类型
if !strings.HasSuffix(strings.ToLower(file.Filename), ".zip") {
logger.Error(c, "只支持zip格式文件!")
return serializer.ParamErr("只支持zip格式文件!", nil)
}
// 获取文件名(不包含扩展名)
filename := strings.TrimSuffix(file.Filename, filepath.Ext(file.Filename))
var deployFile model.SysDeployFile
deployFile.FileName = filename
// 生成文件ID
2025-08-01 16:38:08 +08:00
if id, err := SysSequenceServiceBuilder(deployFile.TableName()).GenerateId(); err == nil {
deployFile.FileId = id
2025-08-01 16:38:08 +08:00
} else {
return serializer.DBErr("序列生成失败!", err)
}
// 生成新的文件名使用文件ID + .zip 后缀
newFileName := deployFile.FileId + ".zip"
// 设置文件保存路径
deployFile.FilePath = filepath.Join("/data", newFileName)
// 保存文件到指定路径
if err := c.SaveUploadedFile(file, deployFile.FilePath); err != nil {
logger.Error(c, "保存文件失败!")
return serializer.ParamErr("保存文件失败!", err)
}
// 打开保存的文件以计算哈希值
savedFile, err := os.Open(deployFile.FilePath)
if err != nil {
logger.Error(c, "打开保存的文件失败!")
return serializer.ParamErr("打开保存的文件失败!", err)
}
defer savedFile.Close()
// 计算文件哈希值
deployFile.FileHash, err = s.CalculateFileHash(savedFile)
if err != nil {
logger.Error(c, "计算文件哈希值失败!")
return serializer.ParamErr("计算文件哈希值失败!", err)
}
// 获取文件大小(从保存的文件获取更准确)
fileInfo, err := savedFile.Stat()
if err != nil {
logger.Error(c, "获取文件信息失败!")
return serializer.ParamErr("获取文件信息失败!", err)
}
deployFile.FileSize = fileInfo.Size()
2025-08-01 16:38:08 +08:00
// 设置默认值
now := time.Now()
deployFile.CreateTime = &now
deployFile.Status = model.FileStatusNotUsed
2025-08-01 16:38:08 +08:00
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)
}
2025-08-01 16:38:08 +08:00
var deployFile model.SysDeployFile
if err := s.Db.Where("file_id = ? AND del_flag = ? AND create_by = ?", c.Param("id"), "0", currentUserId).First(&deployFile).Error; err != nil {
2025-08-01 16:38:08 +08:00
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.FileId
2025-08-01 16:38:08 +08:00
if id == "" {
logger.Error(c, "id 不可为空!")
return serializer.ParamErr("id不可为空!", fmt.Errorf("id不可为空"))
}
if deployFile.ParentId == "" {
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("file_id = ? AND del_flag = ? AND create_by = ?", id, "0", currentUserId).First(&existingDeployFile).Error; err != nil {
logger.Error(c, "部署文件记录不存在或无权限访问!")
return serializer.ParamErr("部署文件记录不存在或无权限访问!", err)
}
2025-08-01 16:38:08 +08:00
// 设置更新时间
now := time.Now()
deployFile.UpdateTime = &now
// 获取当前用户
deployFile.UpdateBy = currentUserId
2025-08-01 16:38:08 +08:00
if err := s.Db.Model(&deployFile).Where("file_id = ? AND del_flag = ? AND create_by = ?", id, "0", currentUserId).Updates(&deployFile).Error; err != nil {
2025-08-01 16:38:08 +08:00
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)
}
2025-08-01 16:38:08 +08:00
// 软删除
data := map[string]any{
"del_flag": "1",
"update_time": time.Now(),
"update_by": currentUserId,
2025-08-01 16:38:08 +08:00
}
// 删除数据库记录
if err := s.Db.Model(&model.SysDeployFile{}).Where("file_id = ? AND create_by = ?", id, currentUserId).Updates(data).Error; err != nil {
2025-08-01 16:38:08 +08:00
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)
}
2025-08-01 16:38:08 +08:00
// 构建基础查询
db := s.Db.Model(&model.SysDeployFile{})
// 如果有查询条件,添加条件
if queryStr != "" {
db = db.Where(queryStr, args...)
}
// 添加用户权限过滤:只能查询自己创建的数据
db = db.Where("create_by = ?", currentUserId)
2025-08-01 16:38:08 +08:00
// 排序
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,
})
}
// GetByParentID 根据项目ID获取文件列表
func (s *SysDeployFileService) GetByParentID(c *gin.Context) serializer.Response {
parentId := c.Param("parentId")
if parentId == "" {
logger.Error(c, "项目ID不可为空!")
return serializer.ParamErr("项目ID不可为空!", fmt.Errorf("项目ID不可为空"))
2025-08-01 16:38:08 +08:00
}
// 获取当前用户ID
currentUserId := c.GetString("id")
if currentUserId == "" {
return serializer.ParamErr("用户信息获取失败!", nil)
2025-08-01 16:38:08 +08:00
}
var deployFiles []model.SysDeployFile
if err := s.Db.Where("parent_id = ? AND del_flag = ? AND create_by = ?", parentId, "0", currentUserId).
Order("create_time DESC").Find(&deployFiles).Error; err != nil {
logger.Error(c, "获取文件列表失败!")
return serializer.DBErr("获取文件列表失败!", err)
2025-08-01 16:38:08 +08:00
}
return serializer.Succ("查询成功!", deployFiles)
2025-08-01 16:38:08 +08:00
}
// SetActiveFile 设置活跃文件
func (s *SysDeployFileService) SetActiveFile(c *gin.Context) serializer.Response {
fileId := c.Param("id")
if fileId == "" {
logger.Error(c, "文件ID不可为空!")
return serializer.ParamErr("文件ID不可为空!", fmt.Errorf("文件ID不可为空"))
}
// 获取当前用户ID
currentUserId := c.GetString("id")
if currentUserId == "" {
return serializer.ParamErr("用户信息获取失败!", nil)
}
// 获取文件信息
var deployFile model.SysDeployFile
if err := s.Db.Where("file_id = ? AND del_flag = ? AND create_by = ?", fileId, "0", currentUserId).First(&deployFile).Error; err != nil {
logger.Error(c, "文件不存在或无权限访问!")
return serializer.ParamErr("文件不存在或无权限访问!", err)
}
// 开始事务
tx := s.Db.Begin()
// 将同项目下的其他文件设为未使用状态
if err := tx.Model(&model.SysDeployFile{}).
Where("parent_id = ? AND del_flag = ? AND create_by = ?", deployFile.ParentId, "0", currentUserId).
2025-08-01 16:38:08 +08:00
Updates(map[string]any{
"status": model.FileStatusNotUsed,
"update_time": time.Now(),
"update_by": currentUserId,
}).Error; err != nil {
tx.Rollback()
logger.Error(c, "更新文件状态失败!")
return serializer.DBErr("更新文件状态失败!", err)
}
// 将当前文件设为使用中状态
if err := tx.Model(&model.SysDeployFile{}).
Where("file_id = ?", fileId).
Updates(map[string]any{
"status": model.FileStatusInUse,
"update_time": time.Now(),
"update_by": currentUserId,
}).Error; err != nil {
tx.Rollback()
logger.Error(c, "设置活跃文件失败!")
return serializer.DBErr("设置活跃文件失败!", err)
}
tx.Commit()
return serializer.Succ("设置活跃文件成功!", nil)
2025-08-01 16:38:08 +08:00
}
// GetActiveFileByParentID 根据项目ID获取当前使用中的文件
func (s *SysDeployFileService) GetActiveFileByParentID(parentId string) (*model.SysDeployFile, error) {
2025-08-01 16:38:08 +08:00
var deployFile model.SysDeployFile
err := s.Db.Where("parent_id = ? AND status = ? AND del_flag = ?",
parentId, model.FileStatusInUse, "0").First(&deployFile).Error
2025-08-01 16:38:08 +08:00
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
}