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("maxOpenConns", 20),
|
||||||
zap.Int("maxIdleConns", 10))
|
zap.Int("maxIdleConns", 10))
|
||||||
|
|
||||||
|
// 迁移数据库结构
|
||||||
|
//Migration()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +148,7 @@ func Migration() error {
|
||||||
// 自动迁移模式
|
// 自动迁移模式
|
||||||
models := []any{
|
models := []any{
|
||||||
&model.SysDeployFile{},
|
&model.SysDeployFile{},
|
||||||
|
&model.SysDeployProject{},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, model := range models {
|
for _, model := range models {
|
||||||
|
|
|
@ -40,7 +40,7 @@ func (h *SysDeployFileHandler) Create(c *gin.Context) {
|
||||||
// @Tags 部署文件管理
|
// @Tags 部署文件管理
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path string true "部署ID"
|
// @Param id path string true "文件ID"
|
||||||
// @Success 200 {object} serializer.Response
|
// @Success 200 {object} serializer.Response
|
||||||
// @Router /deploy-files/{id} [get]
|
// @Router /deploy-files/{id} [get]
|
||||||
func (h *SysDeployFileHandler) GetByID(c *gin.Context) {
|
func (h *SysDeployFileHandler) GetByID(c *gin.Context) {
|
||||||
|
@ -54,7 +54,7 @@ func (h *SysDeployFileHandler) GetByID(c *gin.Context) {
|
||||||
// @Tags 部署文件管理
|
// @Tags 部署文件管理
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path string true "部署ID"
|
// @Param id path string true "文件ID"
|
||||||
// @Param deployFile body model.SysDeployFile true "部署文件信息"
|
// @Param deployFile body model.SysDeployFile true "部署文件信息"
|
||||||
// @Success 200 {object} serializer.Response
|
// @Success 200 {object} serializer.Response
|
||||||
// @Router /deploy-files/{id} [put]
|
// @Router /deploy-files/{id} [put]
|
||||||
|
@ -69,7 +69,7 @@ func (h *SysDeployFileHandler) UpdateByID(c *gin.Context) {
|
||||||
// @Tags 部署文件管理
|
// @Tags 部署文件管理
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path string true "部署ID"
|
// @Param id path string true "文件ID"
|
||||||
// @Success 200 {object} serializer.Response
|
// @Success 200 {object} serializer.Response
|
||||||
// @Router /deploy-files/{id} [delete]
|
// @Router /deploy-files/{id} [delete]
|
||||||
func (h *SysDeployFileHandler) DeleteByID(c *gin.Context) {
|
func (h *SysDeployFileHandler) DeleteByID(c *gin.Context) {
|
||||||
|
@ -90,3 +90,31 @@ func (h *SysDeployFileHandler) GetByCondition(c *gin.Context) {
|
||||||
logger.Info(c, "条件查询部署文件记录")
|
logger.Info(c, "条件查询部署文件记录")
|
||||||
c.JSON(200, h.deployFileService.GetByCondition(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
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"mime/multipart"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SysDeployFile 部署文件记录表
|
// SysDeployFile 部署文件记录表
|
||||||
type SysDeployFile struct {
|
type SysDeployFile struct {
|
||||||
DeployId string `gorm:"column:deploy_id;type:varchar(64);primary_key;comment:部署ID" json:"deployId"`
|
FileId string `gorm:"column:file_id;type:varchar(64);primary_key;comment:文件ID" json:"fileId"`
|
||||||
FileName string `gorm:"column:file_name;type:varchar(255);not null;comment:原始文件名" json:"fileName"`
|
ParentId string `gorm:"column:parent_id;type:varchar(64);not null;comment:项目ID" json:"parentId" binding:"required"`
|
||||||
ProjectName string `gorm:"column:project_name;type:varchar(100);not null;comment:项目名称" json:"projectName" binding:"required"`
|
FileName string `gorm:"column:file_name;type:varchar(255);not null;comment:原始文件名" json:"fileName" binding:"required"`
|
||||||
Domain string `gorm:"column:domain;type:varchar(255);not null;comment:访问域名" json:"domain" binding:"required"`
|
FileSize int64 `gorm:"column:file_size;type:bigint;comment:文件大小(字节)" json:"fileSize"`
|
||||||
File *multipart.FileHeader `gorm:"-" json:"file" binding:"required"`
|
FileHash string `gorm:"column:file_hash;type:varchar(64);comment:文件哈希值" json:"fileHash"`
|
||||||
DeployPath string `gorm:"column:deploy_path;type:varchar(500);not null;comment:部署路径" json:"deployPath"`
|
FilePath string `gorm:"column:file_path;type:varchar(255);comment:文件路径" json:"filePath"`
|
||||||
FileSize int64 `gorm:"column:file_size;type:bigint;comment:文件大小(字节)" json:"fileSize"`
|
Status string `gorm:"column:status;type:char(1);default:0;comment:文件状态(0未使用 1使用中)" json:"status"`
|
||||||
FileHash string `gorm:"column:file_hash;type:varchar(64);comment:文件哈希值" json:"fileHash"`
|
DelFlag string `gorm:"column:del_flag;type:char(1);default:0;comment:删除标志(0代表存在 1代表删除)" json:"delFlag"`
|
||||||
Status string `gorm:"column:status;type:char(1);default:1;comment:状态(0停用 1正常 2部署中 3部署失败)" json:"status"`
|
CreateBy string `gorm:"column:create_by;type:varchar(64);comment:创建者" json:"createBy"`
|
||||||
DeployStatus string `gorm:"column:deploy_status;type:char(1);default:0;comment:部署状态(0未部署 1部署成功 2部署失败)" json:"deployStatus"`
|
CreateTime *time.Time `gorm:"column:create_time;type:datetime;comment:创建时间" json:"createTime"`
|
||||||
ErrorMsg string `gorm:"column:error_msg;type:text;comment:错误信息" json:"errorMsg"`
|
UpdateBy string `gorm:"column:update_by;type:varchar(64);comment:更新者" json:"updateBy"`
|
||||||
Version string `gorm:"column:version;type:varchar(50);comment:版本号" json:"version"`
|
UpdateTime *time.Time `gorm:"column:update_time;type:datetime;comment:更新时间" json:"updateTime"`
|
||||||
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 表名
|
// TableName 表名
|
||||||
|
@ -35,17 +25,8 @@ func (m *SysDeployFile) TableName() string {
|
||||||
return "sys_deploy_file"
|
return "sys_deploy_file"
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeployFileStatus 部署文件状态常量
|
// FileStatus 文件状态常量
|
||||||
const (
|
const (
|
||||||
DeployFileStatusDisabled = "0" // 停用
|
FileStatusNotUsed = "0" // 未使用
|
||||||
DeployFileStatusNormal = "1" // 正常
|
FileStatusInUse = "1" // 使用中
|
||||||
DeployFileStatusDeploying = "2" // 部署中
|
|
||||||
DeployFileStatusFailed = "3" // 部署失败
|
|
||||||
)
|
|
||||||
|
|
||||||
// DeployStatus 部署状态常量
|
|
||||||
const (
|
|
||||||
DeployStatusNotDeployed = "0" // 未部署
|
|
||||||
DeployStatusSuccess = "1" // 部署成功
|
|
||||||
DeployStatusFailed = "2" // 部署失败
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -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.PUT("/", h.UpdateByID)
|
||||||
g.DELETE("/:id", h.DeleteByID)
|
g.DELETE("/:id", h.DeleteByID)
|
||||||
g.GET("", h.GetByCondition)
|
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"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -30,37 +31,69 @@ func NewSysDeployFileService(db *gorm.DB) *SysDeployFileService {
|
||||||
|
|
||||||
// Create 创建部署文件记录
|
// Create 创建部署文件记录
|
||||||
func (s *SysDeployFileService) Create(c *gin.Context) serializer.Response {
|
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
|
var deployFile model.SysDeployFile
|
||||||
if err := c.ShouldBind(&deployFile); err != nil {
|
deployFile.FileName = filename
|
||||||
logger.Error(c, "参数绑定失败!")
|
|
||||||
return serializer.ParamErr("参数绑定失败!", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证必填字段
|
// 生成文件ID
|
||||||
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 {
|
if id, err := SysSequenceServiceBuilder(deployFile.TableName()).GenerateId(); err == nil {
|
||||||
deployFile.DeployId = id
|
deployFile.FileId = id
|
||||||
} else {
|
} else {
|
||||||
return serializer.DBErr("序列生成失败!", err)
|
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()
|
now := time.Now()
|
||||||
deployFile.CreateTime = &now
|
deployFile.CreateTime = &now
|
||||||
deployFile.Status = model.DeployFileStatusNormal
|
deployFile.Status = model.FileStatusNotUsed
|
||||||
deployFile.DeployStatus = model.DeployStatusNotDeployed
|
|
||||||
deployFile.DelFlag = "0"
|
deployFile.DelFlag = "0"
|
||||||
|
|
||||||
// 获取当前用户
|
// 获取当前用户
|
||||||
|
@ -85,7 +118,7 @@ func (s *SysDeployFileService) GetByID(c *gin.Context) serializer.Response {
|
||||||
}
|
}
|
||||||
|
|
||||||
var deployFile model.SysDeployFile
|
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, "获取部署文件记录失败!")
|
logger.Error(c, "获取部署文件记录失败!")
|
||||||
return serializer.DBErr("获取部署文件记录失败!", err)
|
return serializer.DBErr("获取部署文件记录失败!", err)
|
||||||
}
|
}
|
||||||
|
@ -100,12 +133,17 @@ func (s *SysDeployFileService) UpdateByID(c *gin.Context) serializer.Response {
|
||||||
return serializer.ParamErr("参数绑定失败!", err)
|
return serializer.ParamErr("参数绑定失败!", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
id := deployFile.DeployId
|
id := deployFile.FileId
|
||||||
if id == "" {
|
if id == "" {
|
||||||
logger.Error(c, "id 不可为空!")
|
logger.Error(c, "id 不可为空!")
|
||||||
return serializer.ParamErr("id不可为空!", fmt.Errorf("id不可为空"))
|
return serializer.ParamErr("id不可为空!", fmt.Errorf("id不可为空"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if deployFile.ParentId == "" {
|
||||||
|
logger.Error(c, "项目ID不能为空!")
|
||||||
|
return serializer.ParamErr("项目ID不能为空!", fmt.Errorf("项目ID不能为空"))
|
||||||
|
}
|
||||||
|
|
||||||
// 获取当前用户ID
|
// 获取当前用户ID
|
||||||
currentUserId := c.GetString("id")
|
currentUserId := c.GetString("id")
|
||||||
if currentUserId == "" {
|
if currentUserId == "" {
|
||||||
|
@ -114,7 +152,7 @@ func (s *SysDeployFileService) UpdateByID(c *gin.Context) serializer.Response {
|
||||||
|
|
||||||
// 检查权限:只能更新自己创建的数据
|
// 检查权限:只能更新自己创建的数据
|
||||||
var existingDeployFile model.SysDeployFile
|
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, "部署文件记录不存在或无权限访问!")
|
logger.Error(c, "部署文件记录不存在或无权限访问!")
|
||||||
return serializer.ParamErr("部署文件记录不存在或无权限访问!", err)
|
return serializer.ParamErr("部署文件记录不存在或无权限访问!", err)
|
||||||
}
|
}
|
||||||
|
@ -126,7 +164,7 @@ func (s *SysDeployFileService) UpdateByID(c *gin.Context) serializer.Response {
|
||||||
// 获取当前用户
|
// 获取当前用户
|
||||||
deployFile.UpdateBy = currentUserId
|
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, "更新部署文件记录失败!")
|
logger.Error(c, "更新部署文件记录失败!")
|
||||||
return serializer.DBErr("更新部署文件记录失败!", err)
|
return serializer.DBErr("更新部署文件记录失败!", err)
|
||||||
}
|
}
|
||||||
|
@ -154,22 +192,8 @@ func (s *SysDeployFileService) DeleteByID(c *gin.Context) serializer.Response {
|
||||||
"update_by": currentUserId,
|
"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, "删除部署文件记录失败!")
|
logger.Error(c, "删除部署文件记录失败!")
|
||||||
return serializer.DBErr("删除部署文件记录失败!", err)
|
return serializer.DBErr("删除部署文件记录失败!", err)
|
||||||
}
|
}
|
||||||
|
@ -238,41 +262,89 @@ func (s *SysDeployFileService) GetByCondition(c *gin.Context) serializer.Respons
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateDeployStatus 更新部署状态
|
// GetByParentID 根据项目ID获取文件列表
|
||||||
func (s *SysDeployFileService) UpdateDeployStatus(deployId, status, errorMsg string) error {
|
func (s *SysDeployFileService) GetByParentID(c *gin.Context) serializer.Response {
|
||||||
data := map[string]any{
|
parentId := c.Param("parentId")
|
||||||
"deploy_status": status,
|
if parentId == "" {
|
||||||
"update_time": time.Now(),
|
logger.Error(c, "项目ID不可为空!")
|
||||||
|
return serializer.ParamErr("项目ID不可为空!", fmt.Errorf("项目ID不可为空"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if status == model.DeployStatusSuccess {
|
// 获取当前用户ID
|
||||||
now := time.Now()
|
currentUserId := c.GetString("id")
|
||||||
data["deploy_time"] = &now
|
if currentUserId == "" {
|
||||||
|
return serializer.ParamErr("用户信息获取失败!", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if errorMsg != "" {
|
var deployFiles []model.SysDeployFile
|
||||||
data["error_msg"] = errorMsg
|
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 更新访问信息
|
// SetActiveFile 设置活跃文件
|
||||||
func (s *SysDeployFileService) UpdateAccessInfo(deployId string) error {
|
func (s *SysDeployFileService) SetActiveFile(c *gin.Context) serializer.Response {
|
||||||
now := time.Now()
|
fileId := c.Param("id")
|
||||||
return s.Db.Model(&model.SysDeployFile{}).
|
if fileId == "" {
|
||||||
Where("deploy_id = ?", deployId).
|
logger.Error(c, "文件ID不可为空!")
|
||||||
Updates(map[string]any{
|
return serializer.ParamErr("文件ID不可为空!", fmt.Errorf("文件ID不可为空"))
|
||||||
"last_access_time": &now,
|
}
|
||||||
"access_count": gorm.Expr("access_count + 1"),
|
|
||||||
}).Error
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetByDomain 根据域名获取部署文件记录
|
// 获取当前用户ID
|
||||||
func (s *SysDeployFileService) GetByDomain(domain string) (*model.SysDeployFile, error) {
|
currentUserId := c.GetString("id")
|
||||||
|
if currentUserId == "" {
|
||||||
|
return serializer.ParamErr("用户信息获取失败!", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取文件信息
|
||||||
var deployFile model.SysDeployFile
|
var deployFile model.SysDeployFile
|
||||||
err := s.Db.Where("domain = ? AND status = ? AND del_flag = ?",
|
if err := s.Db.Where("file_id = ? AND del_flag = ? AND create_by = ?", fileId, "0", currentUserId).First(&deployFile).Error; err != nil {
|
||||||
domain, model.DeployFileStatusNormal, "0").First(&deployFile).Error
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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)
|
domain := fmt.Sprintf("%s.unbug.cn", filename)
|
||||||
|
|
||||||
// 创建部署文件记录
|
// 先创建或获取项目记录
|
||||||
deployFile := model.SysDeployFile{
|
var deployProject model.SysDeployProject
|
||||||
FileName: file.Filename,
|
currentUserId := c.GetString("id")
|
||||||
ProjectName: filename,
|
|
||||||
Domain: domain,
|
// 检查是否已存在相同域名的项目
|
||||||
DeployPath: targetDir,
|
err = s.Db.Where("domain = ? AND del_flag = ?", domain, "0").First(&deployProject).Error
|
||||||
FileSize: file.Size,
|
if err != nil {
|
||||||
Status: model.DeployFileStatusNormal,
|
if err == gorm.ErrRecordNotFound {
|
||||||
DeployStatus: model.DeployStatusSuccess,
|
// 创建新项目
|
||||||
Description: fmt.Sprintf("自动部署项目: %s", filename),
|
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 {
|
if id, err := SysSequenceServiceBuilder(deployFile.TableName()).GenerateId(); err == nil {
|
||||||
deployFile.DeployId = id
|
deployFile.FileId = id
|
||||||
} else {
|
} else {
|
||||||
logger.Error(c, "生成部署ID失败!", zap.Error(err))
|
logger.Error(c, "生成文件ID失败!", zap.Error(err))
|
||||||
return serializer.DBErr("生成部署ID失败!", err)
|
return serializer.DBErr("生成文件ID失败!", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算文件哈希值
|
// 计算文件哈希值
|
||||||
|
@ -135,24 +177,23 @@ func (s *SysUploadService) UploadZip(c *gin.Context) serializer.Response {
|
||||||
// 设置时间
|
// 设置时间
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
deployFile.CreateTime = &now
|
deployFile.CreateTime = &now
|
||||||
deployFile.DeployTime = &now
|
|
||||||
deployFile.DelFlag = "0"
|
|
||||||
|
|
||||||
// 获取当前用户
|
// 将同项目下的其他文件设为未使用状态
|
||||||
if createBy := c.GetString("id"); createBy != "" {
|
s.Db.Model(&model.SysDeployFile{}).
|
||||||
deployFile.CreateBy = createBy
|
Where("parent_id = ? AND del_flag = ?", deployProject.DeployId, "0").
|
||||||
}
|
Update("status", model.FileStatusNotUsed)
|
||||||
|
|
||||||
// 保存到数据库
|
// 保存文件记录到数据库
|
||||||
if err := s.Db.Create(&deployFile).Error; err != nil {
|
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{}{
|
return serializer.Succ("上传成功!", map[string]interface{}{
|
||||||
"domain": domain,
|
"domain": domain,
|
||||||
"path": targetDir,
|
"path": targetDir,
|
||||||
"deployId": deployFile.DeployId,
|
"projectId": deployProject.DeployId,
|
||||||
|
"fileId": deployFile.FileId,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ var HandlerSet = wire.NewSet(
|
||||||
handler.NewSysLoginLogHandler,
|
handler.NewSysLoginLogHandler,
|
||||||
handler.NewSysUploadHandler,
|
handler.NewSysUploadHandler,
|
||||||
handler.NewSysDeployFileHandler,
|
handler.NewSysDeployFileHandler,
|
||||||
|
handler.NewSysDeployProjectHandler,
|
||||||
)
|
)
|
||||||
|
|
||||||
// UserServiceSet 定义 service 层依赖
|
// UserServiceSet 定义 service 层依赖
|
||||||
|
@ -45,6 +46,11 @@ var DeployFileServiceSet = wire.NewSet(
|
||||||
service.NewSysDeployFileService,
|
service.NewSysDeployFileService,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DeployProjectServiceSet 部署项目服务层依赖
|
||||||
|
var DeployProjectServiceSet = wire.NewSet(
|
||||||
|
service.NewSysDeployProjectService,
|
||||||
|
)
|
||||||
|
|
||||||
// InjectSysUserHandler 注入 handler
|
// InjectSysUserHandler 注入 handler
|
||||||
func InjectSysUserHandler() *handler.SysUserHandler {
|
func InjectSysUserHandler() *handler.SysUserHandler {
|
||||||
panic(wire.Build(
|
panic(wire.Build(
|
||||||
|
@ -68,3 +74,8 @@ func InjectSysUploadHandler() *handler.SysUploadHandler {
|
||||||
func InjectSysDeployFileHandler() *handler.SysDeployFileHandler {
|
func InjectSysDeployFileHandler() *handler.SysDeployFileHandler {
|
||||||
panic(wire.Build(HandlerSet, DeployFileServiceSet, DBSet))
|
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',
|
`deploy_id` varchar(64) NOT NULL COMMENT '部署ID',
|
||||||
`file_name` varchar(255) NOT NULL COMMENT '原始文件名',
|
|
||||||
`project_name` varchar(100) NOT NULL COMMENT '项目名称',
|
`project_name` varchar(100) NOT NULL COMMENT '项目名称',
|
||||||
`domain` varchar(255) NOT NULL COMMENT '访问域名',
|
`domain` varchar(255) NOT NULL COMMENT '访问域名',
|
||||||
`deploy_path` varchar(500) 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部署失败)',
|
`status` char(1) DEFAULT '1' COMMENT '状态(0停用 1正常 2部署中 3部署失败)',
|
||||||
`deploy_status` char(1) DEFAULT '0' COMMENT '部署状态(0未部署 1部署成功 2部署失败)',
|
`deploy_status` char(1) DEFAULT '0' COMMENT '部署状态(0未部署 1部署成功 2部署失败)',
|
||||||
`error_msg` text COMMENT '错误信息',
|
`error_msg` text COMMENT '错误信息',
|
||||||
|
@ -27,31 +24,81 @@ CREATE TABLE `sys_deploy_file` (
|
||||||
KEY `idx_deploy_status` (`deploy_status`),
|
KEY `idx_deploy_status` (`deploy_status`),
|
||||||
KEY `idx_create_time` (`create_time`),
|
KEY `idx_create_time` (`create_time`),
|
||||||
KEY `idx_del_flag` (`del_flag`)
|
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='部署文件记录表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='部署文件记录表';
|
||||||
|
|
||||||
-- 插入示例数据
|
-- 插入示例数据
|
||||||
INSERT INTO `sys_deploy_file` (
|
INSERT INTO `sys_deploy_project` (
|
||||||
`deploy_id`,
|
`deploy_id`,
|
||||||
`file_name`,
|
|
||||||
`project_name`,
|
`project_name`,
|
||||||
`domain`,
|
`domain`,
|
||||||
`deploy_path`,
|
`deploy_path`,
|
||||||
`file_size`,
|
|
||||||
`status`,
|
`status`,
|
||||||
`deploy_status`,
|
`deploy_status`,
|
||||||
`description`,
|
`description`,
|
||||||
`create_by`,
|
`create_by`,
|
||||||
`create_time`
|
`create_time`
|
||||||
) VALUES (
|
) VALUES (
|
||||||
'DEPLOY001',
|
'PROJECT001',
|
||||||
'my-project-v1.0.0.zip',
|
|
||||||
'my-project',
|
'my-project',
|
||||||
'my-project.unbug.cn',
|
'my-project.unbug.cn',
|
||||||
'/home/my-project',
|
'/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,
|
1048576,
|
||||||
'1',
|
'abc123def456',
|
||||||
'1',
|
'1',
|
||||||
'示例项目部署文件',
|
'admin',
|
||||||
|
NOW()
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'FILE002',
|
||||||
|
'PROJECT001',
|
||||||
|
'my-project-v1.0.1.zip',
|
||||||
|
1024000,
|
||||||
|
'def456ghi789',
|
||||||
|
'0',
|
||||||
'admin',
|
'admin',
|
||||||
NOW()
|
NOW()
|
||||||
);
|
);
|
Loading…
Reference in New Issue