feat(deploy): 新增部署项目管理功能
- 添加部署项目模型和相关服务 - 实现部署项目的增删改查接口 - 新增文件上传和管理功能- 优化数据库迁移和初始化逻辑
This commit is contained in:
parent
288526c5f9
commit
d024f0c9e0
|
@ -94,6 +94,8 @@ func initDatabase(connString string) error {
|
|||
zap.Int("maxOpenConns", 20),
|
||||
zap.Int("maxIdleConns", 10))
|
||||
|
||||
// 迁移数据库结构
|
||||
//Migration()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -146,6 +148,7 @@ func Migration() error {
|
|||
// 自动迁移模式
|
||||
models := []any{
|
||||
&model.SysDeployFile{},
|
||||
&model.SysDeployProject{},
|
||||
}
|
||||
|
||||
for _, model := range models {
|
||||
|
|
|
@ -40,7 +40,7 @@ func (h *SysDeployFileHandler) Create(c *gin.Context) {
|
|||
// @Tags 部署文件管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "部署ID"
|
||||
// @Param id path string true "文件ID"
|
||||
// @Success 200 {object} serializer.Response
|
||||
// @Router /deploy-files/{id} [get]
|
||||
func (h *SysDeployFileHandler) GetByID(c *gin.Context) {
|
||||
|
@ -54,7 +54,7 @@ func (h *SysDeployFileHandler) GetByID(c *gin.Context) {
|
|||
// @Tags 部署文件管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "部署ID"
|
||||
// @Param id path string true "文件ID"
|
||||
// @Param deployFile body model.SysDeployFile true "部署文件信息"
|
||||
// @Success 200 {object} serializer.Response
|
||||
// @Router /deploy-files/{id} [put]
|
||||
|
@ -69,7 +69,7 @@ func (h *SysDeployFileHandler) UpdateByID(c *gin.Context) {
|
|||
// @Tags 部署文件管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "部署ID"
|
||||
// @Param id path string true "文件ID"
|
||||
// @Success 200 {object} serializer.Response
|
||||
// @Router /deploy-files/{id} [delete]
|
||||
func (h *SysDeployFileHandler) DeleteByID(c *gin.Context) {
|
||||
|
@ -90,3 +90,31 @@ func (h *SysDeployFileHandler) GetByCondition(c *gin.Context) {
|
|||
logger.Info(c, "条件查询部署文件记录")
|
||||
c.JSON(200, h.deployFileService.GetByCondition(c))
|
||||
}
|
||||
|
||||
// GetByParentID 根据项目ID获取文件列表
|
||||
// @Summary 获取项目文件列表
|
||||
// @Description 根据项目ID获取关联的文件列表
|
||||
// @Tags 部署文件管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param parentId path string true "项目ID"
|
||||
// @Success 200 {object} serializer.Response
|
||||
// @Router /deploy-files/parent/{parentId} [get]
|
||||
func (h *SysDeployFileHandler) GetByParentID(c *gin.Context) {
|
||||
logger.Info(c, "根据项目ID获取文件列表", zap.String("parentId", c.Param("parentId")))
|
||||
c.JSON(200, h.deployFileService.GetByParentID(c))
|
||||
}
|
||||
|
||||
// SetActiveFile 设置活跃文件
|
||||
// @Summary 设置活跃文件
|
||||
// @Description 将指定文件设置为使用中状态,其他文件设为未使用状态
|
||||
// @Tags 部署文件管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "文件ID"
|
||||
// @Success 200 {object} serializer.Response
|
||||
// @Router /deploy-files/{id}/active [put]
|
||||
func (h *SysDeployFileHandler) SetActiveFile(c *gin.Context) {
|
||||
logger.Info(c, "设置活跃文件", zap.String("id", c.Param("id")))
|
||||
c.JSON(200, h.deployFileService.SetActiveFile(c))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
package handler
|
||||
|
||||
import (
|
||||
"ego/internal/service"
|
||||
"ego/pkg/logger"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// SysDeployProjectHandler 部署项目处理器
|
||||
type SysDeployProjectHandler struct {
|
||||
deployProjectService *service.SysDeployProjectService
|
||||
}
|
||||
|
||||
// NewSysDeployProjectHandler 构建部署项目处理器
|
||||
func NewSysDeployProjectHandler(deployProjectService *service.SysDeployProjectService) *SysDeployProjectHandler {
|
||||
return &SysDeployProjectHandler{
|
||||
deployProjectService: deployProjectService,
|
||||
}
|
||||
}
|
||||
|
||||
// Create 创建部署项目记录
|
||||
// @Summary 创建部署项目记录
|
||||
// @Description 创建新的部署项目记录
|
||||
// @Tags 部署项目管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param deployProject body model.SysDeployProject true "部署项目信息"
|
||||
// @Success 200 {object} serializer.Response
|
||||
// @Router /deploy-projects [post]
|
||||
func (h *SysDeployProjectHandler) Create(c *gin.Context) {
|
||||
logger.Info(c, "创建部署项目记录")
|
||||
c.JSON(200, h.deployProjectService.Create(c))
|
||||
}
|
||||
|
||||
// GetByID 根据ID获取部署项目记录
|
||||
// @Summary 获取部署项目记录
|
||||
// @Description 根据ID获取部署项目记录详情
|
||||
// @Tags 部署项目管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "部署ID"
|
||||
// @Success 200 {object} serializer.Response
|
||||
// @Router /deploy-projects/{id} [get]
|
||||
func (h *SysDeployProjectHandler) GetByID(c *gin.Context) {
|
||||
logger.Info(c, "获取部署项目记录", zap.String("id", c.Param("id")))
|
||||
c.JSON(200, h.deployProjectService.GetByID(c))
|
||||
}
|
||||
|
||||
// UpdateByID 根据ID更新部署项目记录
|
||||
// @Summary 更新部署项目记录
|
||||
// @Description 根据ID更新部署项目记录
|
||||
// @Tags 部署项目管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "部署ID"
|
||||
// @Param deployProject body model.SysDeployProject true "部署项目信息"
|
||||
// @Success 200 {object} serializer.Response
|
||||
// @Router /deploy-projects/{id} [put]
|
||||
func (h *SysDeployProjectHandler) UpdateByID(c *gin.Context) {
|
||||
logger.Info(c, "更新部署项目记录", zap.String("id", c.Param("id")))
|
||||
c.JSON(200, h.deployProjectService.UpdateByID(c))
|
||||
}
|
||||
|
||||
// DeleteByID 根据ID删除部署项目记录
|
||||
// @Summary 删除部署项目记录
|
||||
// @Description 根据ID删除部署项目记录
|
||||
// @Tags 部署项目管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "部署ID"
|
||||
// @Success 200 {object} serializer.Response
|
||||
// @Router /deploy-projects/{id} [delete]
|
||||
func (h *SysDeployProjectHandler) DeleteByID(c *gin.Context) {
|
||||
logger.Info(c, "删除部署项目记录", zap.String("id", c.Param("id")))
|
||||
c.JSON(200, h.deployProjectService.DeleteByID(c))
|
||||
}
|
||||
|
||||
// GetByCondition 条件查询部署项目记录
|
||||
// @Summary 条件查询部署项目记录
|
||||
// @Description 根据条件分页查询部署项目记录
|
||||
// @Tags 部署项目管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param params query types.Params true "查询参数"
|
||||
// @Success 200 {object} serializer.Response
|
||||
// @Router /deploy-projects [get]
|
||||
func (h *SysDeployProjectHandler) GetByCondition(c *gin.Context) {
|
||||
logger.Info(c, "条件查询部署项目记录")
|
||||
c.JSON(200, h.deployProjectService.GetByCondition(c))
|
||||
}
|
|
@ -1,33 +1,23 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"mime/multipart"
|
||||
"time"
|
||||
)
|
||||
|
||||
// SysDeployFile 部署文件记录表
|
||||
type SysDeployFile struct {
|
||||
DeployId string `gorm:"column:deploy_id;type:varchar(64);primary_key;comment:部署ID" json:"deployId"`
|
||||
FileName string `gorm:"column:file_name;type:varchar(255);not null;comment:原始文件名" json:"fileName"`
|
||||
ProjectName string `gorm:"column:project_name;type:varchar(100);not null;comment:项目名称" json:"projectName" binding:"required"`
|
||||
Domain string `gorm:"column:domain;type:varchar(255);not null;comment:访问域名" json:"domain" binding:"required"`
|
||||
File *multipart.FileHeader `gorm:"-" json:"file" binding:"required"`
|
||||
DeployPath string `gorm:"column:deploy_path;type:varchar(500);not null;comment:部署路径" json:"deployPath"`
|
||||
FileSize int64 `gorm:"column:file_size;type:bigint;comment:文件大小(字节)" json:"fileSize"`
|
||||
FileHash string `gorm:"column:file_hash;type:varchar(64);comment:文件哈希值" json:"fileHash"`
|
||||
Status string `gorm:"column:status;type:char(1);default:1;comment:状态(0停用 1正常 2部署中 3部署失败)" json:"status"`
|
||||
DeployStatus string `gorm:"column:deploy_status;type:char(1);default:0;comment:部署状态(0未部署 1部署成功 2部署失败)" json:"deployStatus"`
|
||||
ErrorMsg string `gorm:"column:error_msg;type:text;comment:错误信息" json:"errorMsg"`
|
||||
Version string `gorm:"column:version;type:varchar(50);comment:版本号" json:"version"`
|
||||
Description string `gorm:"column:description;type:varchar(500);comment:描述" json:"description"`
|
||||
DelFlag string `gorm:"column:del_flag;type:char(1);default:0;comment:删除标志(0代表存在 1代表删除)" json:"delFlag"`
|
||||
CreateBy string `gorm:"column:create_by;type:varchar(64);comment:创建者" json:"createBy"`
|
||||
CreateTime *time.Time `gorm:"column:create_time;type:datetime;comment:创建时间" json:"createTime"`
|
||||
UpdateBy string `gorm:"column:update_by;type:varchar(64);comment:更新者" json:"updateBy"`
|
||||
UpdateTime *time.Time `gorm:"column:update_time;type:datetime;comment:更新时间" json:"updateTime"`
|
||||
DeployTime *time.Time `gorm:"column:deploy_time;type:datetime;comment:部署时间" json:"deployTime"`
|
||||
LastAccessTime *time.Time `gorm:"column:last_access_time;type:datetime;comment:最后访问时间" json:"lastAccessTime"`
|
||||
AccessCount int64 `gorm:"column:access_count;type:bigint;default:0;comment:访问次数" json:"accessCount"`
|
||||
FileId string `gorm:"column:file_id;type:varchar(64);primary_key;comment:文件ID" json:"fileId"`
|
||||
ParentId string `gorm:"column:parent_id;type:varchar(64);not null;comment:项目ID" json:"parentId" binding:"required"`
|
||||
FileName string `gorm:"column:file_name;type:varchar(255);not null;comment:原始文件名" json:"fileName" binding:"required"`
|
||||
FileSize int64 `gorm:"column:file_size;type:bigint;comment:文件大小(字节)" json:"fileSize"`
|
||||
FileHash string `gorm:"column:file_hash;type:varchar(64);comment:文件哈希值" json:"fileHash"`
|
||||
FilePath string `gorm:"column:file_path;type:varchar(255);comment:文件路径" json:"filePath"`
|
||||
Status string `gorm:"column:status;type:char(1);default:0;comment:文件状态(0未使用 1使用中)" json:"status"`
|
||||
DelFlag string `gorm:"column:del_flag;type:char(1);default:0;comment:删除标志(0代表存在 1代表删除)" json:"delFlag"`
|
||||
CreateBy string `gorm:"column:create_by;type:varchar(64);comment:创建者" json:"createBy"`
|
||||
CreateTime *time.Time `gorm:"column:create_time;type:datetime;comment:创建时间" json:"createTime"`
|
||||
UpdateBy string `gorm:"column:update_by;type:varchar(64);comment:更新者" json:"updateBy"`
|
||||
UpdateTime *time.Time `gorm:"column:update_time;type:datetime;comment:更新时间" json:"updateTime"`
|
||||
}
|
||||
|
||||
// TableName 表名
|
||||
|
@ -35,17 +25,8 @@ func (m *SysDeployFile) TableName() string {
|
|||
return "sys_deploy_file"
|
||||
}
|
||||
|
||||
// DeployFileStatus 部署文件状态常量
|
||||
// FileStatus 文件状态常量
|
||||
const (
|
||||
DeployFileStatusDisabled = "0" // 停用
|
||||
DeployFileStatusNormal = "1" // 正常
|
||||
DeployFileStatusDeploying = "2" // 部署中
|
||||
DeployFileStatusFailed = "3" // 部署失败
|
||||
)
|
||||
|
||||
// DeployStatus 部署状态常量
|
||||
const (
|
||||
DeployStatusNotDeployed = "0" // 未部署
|
||||
DeployStatusSuccess = "1" // 部署成功
|
||||
DeployStatusFailed = "2" // 部署失败
|
||||
FileStatusNotUsed = "0" // 未使用
|
||||
FileStatusInUse = "1" // 使用中
|
||||
)
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
// SysDeployProject 部署项目记录表
|
||||
type SysDeployProject struct {
|
||||
DeployId string `gorm:"column:deploy_id;type:varchar(64);primary_key;comment:部署ID" json:"deployId"`
|
||||
ProjectName string `gorm:"column:project_name;type:varchar(100);not null;comment:项目名称" json:"projectName" binding:"required"`
|
||||
Domain string `gorm:"column:domain;type:varchar(255);not null;comment:访问域名" json:"domain" binding:"required"`
|
||||
DeployPath string `gorm:"column:deploy_path;type:varchar(500);not null;comment:部署路径" json:"deployPath"`
|
||||
Status string `gorm:"column:status;type:char(1);default:1;comment:状态(0停用 1正常 2部署中 3部署失败)" json:"status"`
|
||||
DeployStatus string `gorm:"column:deploy_status;type:char(1);default:0;comment:部署状态(0未部署 1部署成功 2部署失败)" json:"deployStatus"`
|
||||
ErrorMsg string `gorm:"column:error_msg;type:text;comment:错误信息" json:"errorMsg"`
|
||||
Version string `gorm:"column:version;type:varchar(50);comment:版本号" json:"version"`
|
||||
Description string `gorm:"column:description;type:varchar(500);comment:描述" json:"description"`
|
||||
DelFlag string `gorm:"column:del_flag;type:char(1);default:0;comment:删除标志(0代表存在 1代表删除)" json:"delFlag"`
|
||||
CreateBy string `gorm:"column:create_by;type:varchar(64);comment:创建者" json:"createBy"`
|
||||
CreateTime *time.Time `gorm:"column:create_time;type:datetime;comment:创建时间" json:"createTime"`
|
||||
UpdateBy string `gorm:"column:update_by;type:varchar(64);comment:更新者" json:"updateBy"`
|
||||
UpdateTime *time.Time `gorm:"column:update_time;type:datetime;comment:更新时间" json:"updateTime"`
|
||||
DeployTime *time.Time `gorm:"column:deploy_time;type:datetime;comment:部署时间" json:"deployTime"`
|
||||
LastAccessTime *time.Time `gorm:"column:last_access_time;type:datetime;comment:最后访问时间" json:"lastAccessTime"`
|
||||
AccessCount int64 `gorm:"column:access_count;type:bigint;default:0;comment:访问次数" json:"accessCount"`
|
||||
}
|
||||
|
||||
// TableName 表名
|
||||
func (m *SysDeployProject) TableName() string {
|
||||
return "sys_deploy_project"
|
||||
}
|
||||
|
||||
// DeployProjectStatus 部署项目状态常量
|
||||
const (
|
||||
DeployProjectStatusDisabled = "0" // 停用
|
||||
DeployProjectStatusNormal = "1" // 正常
|
||||
DeployProjectStatusDeploying = "2" // 部署中
|
||||
DeployProjectStatusFailed = "3" // 部署失败
|
||||
)
|
||||
|
||||
// DeployStatus 部署状态常量
|
||||
const (
|
||||
DeployStatusNotDeployed = "0" // 未部署
|
||||
DeployStatusSuccess = "1" // 部署成功
|
||||
DeployStatusFailed = "2" // 部署失败
|
||||
)
|
|
@ -31,4 +31,6 @@ func SysDeployFileHandlerRouter(group *gin.RouterGroup, h *handler.SysDeployFile
|
|||
g.PUT("/", h.UpdateByID)
|
||||
g.DELETE("/:id", h.DeleteByID)
|
||||
g.GET("", h.GetByCondition)
|
||||
g.GET("/parent/:parentId", h.GetByParentID)
|
||||
g.PUT("/:id/active", h.SetActiveFile)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package router
|
||||
|
||||
import (
|
||||
"ego/internal/handler"
|
||||
"ego/internal/middleware"
|
||||
"ego/internal/wire"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apiRouterFns = append(apiRouterFns, func(group *gin.RouterGroup) {
|
||||
SysDeployProjectHandlerRouter(group, wire.InjectSysDeployProjectHandler())
|
||||
})
|
||||
}
|
||||
|
||||
// SysDeployProjectHandlerRouter 部署项目相关路由
|
||||
// @Summary 部署项目管理路由
|
||||
// @Description 包含部署项目的增删改查等接口
|
||||
// @Tags 部署项目管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
func SysDeployProjectHandlerRouter(group *gin.RouterGroup, h *handler.SysDeployProjectHandler) {
|
||||
// 部署项目管理路由组
|
||||
g := group.Group("/DeployProjects")
|
||||
// 鉴权
|
||||
g.Use(middleware.AuthRequired())
|
||||
|
||||
g.POST("/", h.Create)
|
||||
g.GET("/:id", h.GetByID)
|
||||
g.PUT("/", h.UpdateByID)
|
||||
g.DELETE("/:id", h.DeleteByID)
|
||||
g.GET("", h.GetByCondition)
|
||||
}
|
|
@ -10,6 +10,7 @@ import (
|
|||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -30,37 +31,69 @@ func NewSysDeployFileService(db *gorm.DB) *SysDeployFileService {
|
|||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 校验文件类型
|
||||
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
|
||||
if err := c.ShouldBind(&deployFile); err != nil {
|
||||
logger.Error(c, "参数绑定失败!")
|
||||
return serializer.ParamErr("参数绑定失败!", err)
|
||||
}
|
||||
deployFile.FileName = filename
|
||||
|
||||
// 验证必填字段
|
||||
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
|
||||
// 生成文件ID
|
||||
if id, err := SysSequenceServiceBuilder(deployFile.TableName()).GenerateId(); err == nil {
|
||||
deployFile.DeployId = id
|
||||
deployFile.FileId = id
|
||||
} 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()
|
||||
|
||||
// 设置默认值
|
||||
now := time.Now()
|
||||
deployFile.CreateTime = &now
|
||||
deployFile.Status = model.DeployFileStatusNormal
|
||||
deployFile.DeployStatus = model.DeployStatusNotDeployed
|
||||
deployFile.Status = model.FileStatusNotUsed
|
||||
deployFile.DelFlag = "0"
|
||||
|
||||
// 获取当前用户
|
||||
|
@ -85,7 +118,7 @@ func (s *SysDeployFileService) GetByID(c *gin.Context) serializer.Response {
|
|||
}
|
||||
|
||||
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 {
|
||||
if err := s.Db.Where("file_id = ? AND del_flag = ? AND create_by = ?", c.Param("id"), "0", currentUserId).First(&deployFile).Error; err != nil {
|
||||
logger.Error(c, "获取部署文件记录失败!")
|
||||
return serializer.DBErr("获取部署文件记录失败!", err)
|
||||
}
|
||||
|
@ -100,12 +133,17 @@ func (s *SysDeployFileService) UpdateByID(c *gin.Context) serializer.Response {
|
|||
return serializer.ParamErr("参数绑定失败!", err)
|
||||
}
|
||||
|
||||
id := deployFile.DeployId
|
||||
id := deployFile.FileId
|
||||
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 == "" {
|
||||
|
@ -114,7 +152,7 @@ func (s *SysDeployFileService) UpdateByID(c *gin.Context) serializer.Response {
|
|||
|
||||
// 检查权限:只能更新自己创建的数据
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
|
@ -126,7 +164,7 @@ func (s *SysDeployFileService) UpdateByID(c *gin.Context) serializer.Response {
|
|||
// 获取当前用户
|
||||
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 {
|
||||
if err := s.Db.Model(&deployFile).Where("file_id = ? AND del_flag = ? AND create_by = ?", id, "0", currentUserId).Updates(&deployFile).Error; err != nil {
|
||||
logger.Error(c, "更新部署文件记录失败!")
|
||||
return serializer.DBErr("更新部署文件记录失败!", err)
|
||||
}
|
||||
|
@ -154,22 +192,8 @@ func (s *SysDeployFileService) DeleteByID(c *gin.Context) serializer.Response {
|
|||
"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.Domain))
|
||||
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 {
|
||||
if err := s.Db.Model(&model.SysDeployFile{}).Where("file_id = ? AND create_by = ?", id, currentUserId).Updates(data).Error; err != nil {
|
||||
logger.Error(c, "删除部署文件记录失败!")
|
||||
return serializer.DBErr("删除部署文件记录失败!", err)
|
||||
}
|
||||
|
@ -238,41 +262,89 @@ func (s *SysDeployFileService) GetByCondition(c *gin.Context) serializer.Respons
|
|||
})
|
||||
}
|
||||
|
||||
// UpdateDeployStatus 更新部署状态
|
||||
func (s *SysDeployFileService) UpdateDeployStatus(deployId, status, errorMsg string) error {
|
||||
data := map[string]any{
|
||||
"deploy_status": status,
|
||||
"update_time": time.Now(),
|
||||
// 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不可为空"))
|
||||
}
|
||||
|
||||
if status == model.DeployStatusSuccess {
|
||||
now := time.Now()
|
||||
data["deploy_time"] = &now
|
||||
// 获取当前用户ID
|
||||
currentUserId := c.GetString("id")
|
||||
if currentUserId == "" {
|
||||
return serializer.ParamErr("用户信息获取失败!", nil)
|
||||
}
|
||||
|
||||
if errorMsg != "" {
|
||||
data["error_msg"] = errorMsg
|
||||
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)
|
||||
}
|
||||
|
||||
return s.Db.Model(&model.SysDeployFile{}).Where("deploy_id = ?", deployId).Updates(data).Error
|
||||
return serializer.Succ("查询成功!", deployFiles)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
// 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不可为空"))
|
||||
}
|
||||
|
||||
// GetByDomain 根据域名获取部署文件记录
|
||||
func (s *SysDeployFileService) GetByDomain(domain string) (*model.SysDeployFile, error) {
|
||||
// 获取当前用户ID
|
||||
currentUserId := c.GetString("id")
|
||||
if currentUserId == "" {
|
||||
return serializer.ParamErr("用户信息获取失败!", nil)
|
||||
}
|
||||
|
||||
// 获取文件信息
|
||||
var deployFile model.SysDeployFile
|
||||
err := s.Db.Where("domain = ? AND status = ? AND del_flag = ?",
|
||||
domain, model.DeployFileStatusNormal, "0").First(&deployFile).Error
|
||||
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).
|
||||
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)
|
||||
}
|
||||
|
||||
// GetActiveFileByParentID 根据项目ID获取当前使用中的文件
|
||||
func (s *SysDeployFileService) GetActiveFileByParentID(parentId string) (*model.SysDeployFile, error) {
|
||||
var deployFile model.SysDeployFile
|
||||
err := s.Db.Where("parent_id = ? AND status = ? AND del_flag = ?",
|
||||
parentId, model.FileStatusInUse, "0").First(&deployFile).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -0,0 +1,289 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"ego/internal/model"
|
||||
"ego/internal/serializer"
|
||||
"ego/internal/types"
|
||||
"ego/pkg/logger"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"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)
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
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
|
||||
}
|
||||
|
||||
if err := s.Db.Create(&deployProject).Error; err != nil {
|
||||
logger.Error(c, "创建部署项目记录失败!")
|
||||
return serializer.DBErr("创建部署项目记录失败!", err)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// 软删除
|
||||
data := map[string]any{
|
||||
"del_flag": "1",
|
||||
"update_time": time.Now(),
|
||||
"update_by": currentUserId,
|
||||
}
|
||||
|
||||
// 删除已经部署的文件夹
|
||||
deployProject := model.SysDeployProject{}
|
||||
if err := s.Db.Where("deploy_id = ? AND create_by = ?", id, currentUserId).First(&deployProject).Error; err != nil {
|
||||
logger.Error(c, "获取部署项目记录失败或无权限访问!")
|
||||
return serializer.DBErr("获取部署项目记录失败或无权限访问!", err)
|
||||
}
|
||||
|
||||
// 删除 /home/:projectName
|
||||
err := os.RemoveAll(filepath.Join("/home", deployProject.Domain))
|
||||
if err != nil {
|
||||
logger.Error(c, "删除部署文件夹失败!")
|
||||
return serializer.DBErr("删除部署文件夹失败!", err)
|
||||
}
|
||||
|
||||
// 同时软删除关联的文件记录
|
||||
fileData := map[string]any{
|
||||
"del_flag": "1",
|
||||
"update_time": time.Now(),
|
||||
"update_by": currentUserId,
|
||||
}
|
||||
if err := s.Db.Model(&model.SysDeployFile{}).Where("parent_id = ?", id).Updates(fileData).Error; err != nil {
|
||||
logger.Error(c, "删除关联文件记录失败!")
|
||||
return serializer.DBErr("删除关联文件记录失败!", err)
|
||||
}
|
||||
|
||||
// 删除数据库记录
|
||||
if err := s.Db.Model(&model.SysDeployProject{}).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 *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
|
||||
}
|
|
@ -107,24 +107,66 @@ func (s *SysUploadService) UploadZip(c *gin.Context) serializer.Response {
|
|||
// 返回域名格式的结果
|
||||
domain := fmt.Sprintf("%s.unbug.cn", filename)
|
||||
|
||||
// 创建部署文件记录
|
||||
deployFile := model.SysDeployFile{
|
||||
FileName: file.Filename,
|
||||
ProjectName: filename,
|
||||
Domain: domain,
|
||||
DeployPath: targetDir,
|
||||
FileSize: file.Size,
|
||||
Status: model.DeployFileStatusNormal,
|
||||
DeployStatus: model.DeployStatusSuccess,
|
||||
Description: fmt.Sprintf("自动部署项目: %s", filename),
|
||||
// 先创建或获取项目记录
|
||||
var deployProject model.SysDeployProject
|
||||
currentUserId := c.GetString("id")
|
||||
|
||||
// 检查是否已存在相同域名的项目
|
||||
err = s.Db.Where("domain = ? AND del_flag = ?", domain, "0").First(&deployProject).Error
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
// 创建新项目
|
||||
deployProject = model.SysDeployProject{
|
||||
ProjectName: filename,
|
||||
Domain: domain,
|
||||
DeployPath: targetDir,
|
||||
Status: model.DeployProjectStatusNormal,
|
||||
DeployStatus: model.DeployStatusSuccess,
|
||||
Description: fmt.Sprintf("自动部署项目: %s", filename),
|
||||
DelFlag: "0",
|
||||
CreateBy: currentUserId,
|
||||
}
|
||||
|
||||
// 生成项目ID
|
||||
if id, err := SysSequenceServiceBuilder(deployProject.TableName()).GenerateId(); err == nil {
|
||||
deployProject.DeployId = id
|
||||
} else {
|
||||
logger.Error(c, "生成项目ID失败!", zap.Error(err))
|
||||
return serializer.DBErr("生成项目ID失败!", err)
|
||||
}
|
||||
|
||||
// 设置时间
|
||||
now := time.Now()
|
||||
deployProject.CreateTime = &now
|
||||
deployProject.DeployTime = &now
|
||||
|
||||
// 保存项目到数据库
|
||||
if err := s.Db.Create(&deployProject).Error; err != nil {
|
||||
logger.Error(c, "保存项目记录失败!", zap.Error(err))
|
||||
return serializer.DBErr("保存项目记录失败!", err)
|
||||
}
|
||||
} else {
|
||||
logger.Error(c, "查询项目记录失败!", zap.Error(err))
|
||||
return serializer.DBErr("查询项目记录失败!", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成部署ID
|
||||
// 创建文件记录
|
||||
deployFile := model.SysDeployFile{
|
||||
ParentId: deployProject.DeployId,
|
||||
FileName: file.Filename,
|
||||
FileSize: file.Size,
|
||||
Status: model.FileStatusInUse, // 新上传的文件设为使用中
|
||||
DelFlag: "0",
|
||||
CreateBy: currentUserId,
|
||||
}
|
||||
|
||||
// 生成文件ID
|
||||
if id, err := SysSequenceServiceBuilder(deployFile.TableName()).GenerateId(); err == nil {
|
||||
deployFile.DeployId = id
|
||||
deployFile.FileId = id
|
||||
} else {
|
||||
logger.Error(c, "生成部署ID失败!", zap.Error(err))
|
||||
return serializer.DBErr("生成部署ID失败!", err)
|
||||
logger.Error(c, "生成文件ID失败!", zap.Error(err))
|
||||
return serializer.DBErr("生成文件ID失败!", err)
|
||||
}
|
||||
|
||||
// 计算文件哈希值
|
||||
|
@ -135,24 +177,23 @@ func (s *SysUploadService) UploadZip(c *gin.Context) serializer.Response {
|
|||
// 设置时间
|
||||
now := time.Now()
|
||||
deployFile.CreateTime = &now
|
||||
deployFile.DeployTime = &now
|
||||
deployFile.DelFlag = "0"
|
||||
|
||||
// 获取当前用户
|
||||
if createBy := c.GetString("id"); createBy != "" {
|
||||
deployFile.CreateBy = createBy
|
||||
}
|
||||
// 将同项目下的其他文件设为未使用状态
|
||||
s.Db.Model(&model.SysDeployFile{}).
|
||||
Where("parent_id = ? AND del_flag = ?", deployProject.DeployId, "0").
|
||||
Update("status", model.FileStatusNotUsed)
|
||||
|
||||
// 保存到数据库
|
||||
// 保存文件记录到数据库
|
||||
if err := s.Db.Create(&deployFile).Error; err != nil {
|
||||
logger.Error(c, "保存部署文件记录失败!", zap.Error(err))
|
||||
logger.Error(c, "保存文件记录失败!", zap.Error(err))
|
||||
// 即使保存记录失败,也不影响文件部署
|
||||
}
|
||||
|
||||
return serializer.Succ("上传成功!", map[string]interface{}{
|
||||
"domain": domain,
|
||||
"path": targetDir,
|
||||
"deployId": deployFile.DeployId,
|
||||
"domain": domain,
|
||||
"path": targetDir,
|
||||
"projectId": deployProject.DeployId,
|
||||
"fileId": deployFile.FileId,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ var HandlerSet = wire.NewSet(
|
|||
handler.NewSysLoginLogHandler,
|
||||
handler.NewSysUploadHandler,
|
||||
handler.NewSysDeployFileHandler,
|
||||
handler.NewSysDeployProjectHandler,
|
||||
)
|
||||
|
||||
// UserServiceSet 定义 service 层依赖
|
||||
|
@ -45,6 +46,11 @@ var DeployFileServiceSet = wire.NewSet(
|
|||
service.NewSysDeployFileService,
|
||||
)
|
||||
|
||||
// DeployProjectServiceSet 部署项目服务层依赖
|
||||
var DeployProjectServiceSet = wire.NewSet(
|
||||
service.NewSysDeployProjectService,
|
||||
)
|
||||
|
||||
// InjectSysUserHandler 注入 handler
|
||||
func InjectSysUserHandler() *handler.SysUserHandler {
|
||||
panic(wire.Build(
|
||||
|
@ -68,3 +74,8 @@ func InjectSysUploadHandler() *handler.SysUploadHandler {
|
|||
func InjectSysDeployFileHandler() *handler.SysDeployFileHandler {
|
||||
panic(wire.Build(HandlerSet, DeployFileServiceSet, DBSet))
|
||||
}
|
||||
|
||||
// InjectSysDeployProjectHandler 注入部署项目处理器
|
||||
func InjectSysDeployProjectHandler() *handler.SysDeployProjectHandler {
|
||||
panic(wire.Build(HandlerSet, DeployProjectServiceSet, DBSet))
|
||||
}
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
-- 部署文件记录表
|
||||
CREATE TABLE `sys_deploy_file` (
|
||||
-- 部署项目记录表
|
||||
CREATE TABLE `sys_deploy_project` (
|
||||
`deploy_id` varchar(64) NOT NULL COMMENT '部署ID',
|
||||
`file_name` varchar(255) NOT NULL COMMENT '原始文件名',
|
||||
`project_name` varchar(100) NOT NULL COMMENT '项目名称',
|
||||
`domain` varchar(255) NOT NULL COMMENT '访问域名',
|
||||
`deploy_path` varchar(500) NOT NULL COMMENT '部署路径',
|
||||
`file_size` bigint DEFAULT NULL COMMENT '文件大小(字节)',
|
||||
`file_hash` varchar(64) DEFAULT NULL COMMENT '文件哈希值',
|
||||
`status` char(1) DEFAULT '1' COMMENT '状态(0停用 1正常 2部署中 3部署失败)',
|
||||
`deploy_status` char(1) DEFAULT '0' COMMENT '部署状态(0未部署 1部署成功 2部署失败)',
|
||||
`error_msg` text COMMENT '错误信息',
|
||||
|
@ -27,31 +24,81 @@ CREATE TABLE `sys_deploy_file` (
|
|||
KEY `idx_deploy_status` (`deploy_status`),
|
||||
KEY `idx_create_time` (`create_time`),
|
||||
KEY `idx_del_flag` (`del_flag`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='部署项目记录表';
|
||||
|
||||
-- 部署文件记录表
|
||||
CREATE TABLE `sys_deploy_file` (
|
||||
`file_id` varchar(64) NOT NULL COMMENT '文件ID',
|
||||
`parent_id` varchar(64) NOT NULL COMMENT '项目ID',
|
||||
`file_name` varchar(255) NOT NULL COMMENT '原始文件名',
|
||||
`file_size` bigint DEFAULT NULL COMMENT '文件大小(字节)',
|
||||
`file_hash` varchar(64) DEFAULT NULL COMMENT '文件哈希值',
|
||||
`status` char(1) DEFAULT '0' COMMENT '文件状态(0未使用 1使用中)',
|
||||
`del_flag` char(1) DEFAULT '0' COMMENT '删除标志(0代表存在 1代表删除)',
|
||||
`create_by` varchar(64) DEFAULT NULL COMMENT '创建者',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_by` varchar(64) DEFAULT NULL COMMENT '更新者',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (`file_id`),
|
||||
KEY `idx_parent_id` (`parent_id`),
|
||||
KEY `idx_file_name` (`file_name`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_create_time` (`create_time`),
|
||||
KEY `idx_del_flag` (`del_flag`),
|
||||
CONSTRAINT `fk_deploy_file_parent` FOREIGN KEY (`parent_id`) REFERENCES `sys_deploy_project` (`deploy_id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='部署文件记录表';
|
||||
|
||||
-- 插入示例数据
|
||||
INSERT INTO `sys_deploy_file` (
|
||||
INSERT INTO `sys_deploy_project` (
|
||||
`deploy_id`,
|
||||
`file_name`,
|
||||
`project_name`,
|
||||
`domain`,
|
||||
`deploy_path`,
|
||||
`file_size`,
|
||||
`status`,
|
||||
`deploy_status`,
|
||||
`description`,
|
||||
`create_by`,
|
||||
`create_time`
|
||||
) VALUES (
|
||||
'DEPLOY001',
|
||||
'my-project-v1.0.0.zip',
|
||||
'PROJECT001',
|
||||
'my-project',
|
||||
'my-project.unbug.cn',
|
||||
'/home/my-project',
|
||||
'1',
|
||||
'1',
|
||||
'示例项目',
|
||||
'admin',
|
||||
NOW()
|
||||
);
|
||||
|
||||
-- 插入示例文件数据
|
||||
INSERT INTO `sys_deploy_file` (
|
||||
`file_id`,
|
||||
`parent_id`,
|
||||
`file_name`,
|
||||
`file_size`,
|
||||
`file_hash`,
|
||||
`status`,
|
||||
`create_by`,
|
||||
`create_time`
|
||||
) VALUES
|
||||
(
|
||||
'FILE001',
|
||||
'PROJECT001',
|
||||
'my-project-v1.0.0.zip',
|
||||
1048576,
|
||||
'1',
|
||||
'1',
|
||||
'示例项目部署文件',
|
||||
'abc123def456',
|
||||
'1',
|
||||
'admin',
|
||||
NOW()
|
||||
),
|
||||
(
|
||||
'FILE002',
|
||||
'PROJECT001',
|
||||
'my-project-v1.0.1.zip',
|
||||
1024000,
|
||||
'def456ghi789',
|
||||
'0',
|
||||
'admin',
|
||||
NOW()
|
||||
);
|
Loading…
Reference in New Issue