feat:新增部署列表接口

This commit is contained in:
黄明 2024-08-09 15:14:19 +08:00
parent cf3714b99a
commit eaecd00394
13 changed files with 549 additions and 8 deletions

View File

@ -82,3 +82,22 @@ type UploadReq struct {
type UploadRes struct {
FileUrl string `json:"fileurl"`
}
// DeployReq 项目部署
type DeployReq struct {
g.Meta `path:"/project/deploy" method:"post" tags:"项目" summary:"项目部署"`
adminin.ProjectDeployInp
}
type DeployRes struct {
FileUrl string `json:"fileurl"`
}
type DeployListReq struct {
g.Meta `path:"/project/deploy/list" method:"get" tags:"项目" summary:"获取项目列表"`
adminin.ProjectDeployListInp
}
type DeployListRes struct {
List []*adminin.ProjectDeployListModel `json:"list" dc:"数据列表"`
}

2
go.mod
View File

@ -3,10 +3,12 @@ module hotgo
go 1.21
require (
github.com/bndr/gojenkins v1.1.0
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.6.3
github.com/gogf/gf/contrib/nosql/redis/v2 v2.7.2
github.com/gogf/gf/v2 v2.7.2
github.com/golang-jwt/jwt/v5 v5.2.0
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
)
require (

12
go.sum
View File

@ -1,5 +1,7 @@
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/bndr/gojenkins v1.1.0 h1:TWyJI6ST1qDAfH33DQb3G4mD8KkrBfyfSUoZBHQAvPI=
github.com/bndr/gojenkins v1.1.0/go.mod h1:QeskxN9F/Csz0XV/01IC8y37CapKKWvOHa0UHLLX1fM=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
@ -9,6 +11,7 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
@ -71,6 +74,8 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
@ -81,12 +86,18 @@ go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucg
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -94,5 +105,6 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -47,6 +47,12 @@ var (
project.NewV1(),
)
})
s.Group("/attachment", func(group *ghttp.RouterGroup) {
group.Hook("/*", ghttp.HookBeforeServe, func(r *ghttp.Request) {
r.Response.CORSDefault()
})
})
s.Run()
return nil
},

View File

@ -2,13 +2,12 @@ package project
import (
"context"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"hotgo/internal/service"
"hotgo/api/project/v1"
)
func (c *ControllerV1) Delete(ctx context.Context, req *v1.DeleteReq) (res *v1.DeleteRes, err error) {
return nil, gerror.NewCode(gcode.CodeNotImplemented)
err = service.AdminProject().Delete(ctx, &req.ProjectDeleteInp)
return
}

View File

@ -0,0 +1,17 @@
package project
import (
"context"
"hotgo/api/project/v1"
"hotgo/internal/service"
)
func (c *ControllerV1) Deploy(ctx context.Context, req *v1.DeployReq) (res *v1.DeployRes, err error) {
err = service.AdminProject().Deploy(ctx, &req.ProjectDeployInp)
return
}
func (c *ControllerV1) DeployList(ctx context.Context, req *v1.DeployListReq) (res *v1.DeployListRes, err error) {
err = service.AdminProject().Deploy(ctx, &req.ProjectDeployInp)
return
}

View File

@ -5,18 +5,30 @@ package admin
import (
"context"
"encoding/json"
"fmt"
"github.com/bndr/gojenkins"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/grand"
"github.com/gogf/gf/v2/util/guid"
"hotgo/internal/dao"
"hotgo/internal/library/contexts"
"hotgo/internal/model"
"hotgo/internal/model/entity"
"hotgo/internal/model/input/adminin"
"hotgo/internal/service"
"hotgo/internal/utils"
"io"
"net/http"
"os"
"path/filepath"
"strings"
)
type sAdminProject struct{}
@ -29,6 +41,21 @@ func init() {
service.RegisterAdminProject(NewAdminProject())
}
const (
DEPLOY_BUILD_KEY = "deploy.build"
DEPLOY_BUILD_URL_KEY = DEPLOY_BUILD_KEY + "." + "url"
DEPLOY_BUILD_JOBNAME_KEY = DEPLOY_BUILD_KEY + "." + "jobName"
DEPLOY_BUILD_JOBDOWN_KEY = DEPLOY_BUILD_KEY + "." + "jobdown"
DEPLOY_BUILD_CALLBACK_KEY = DEPLOY_BUILD_KEY + "." + "callback"
DEPLOY_BUILD_MINIOPATH_KEY = DEPLOY_BUILD_KEY + "." + "ossPathPre"
DEPLOY_BUILD_UPLOAD_KEY = DEPLOY_BUILD_KEY + "." + "upload"
DEPLOY_BUILD_CONFIG_PATH = DEPLOY_BUILD_KEY + "." + "confPath"
DEPLOY_BUILD_FRONT_PATH = DEPLOY_BUILD_KEY + "." + "frontPath"
DEPLOY_BUILD_JOBTOKEN_KEY = DEPLOY_BUILD_KEY + "." + "jobToken"
DEPLOY_BUILD_JOBUSER_KEY = DEPLOY_BUILD_KEY + "." + "jobUser"
DEPLOY_BUILD_JOBPASSWORD_KEY = DEPLOY_BUILD_KEY + "." + "jobPassword"
)
// Model ORM模型
func (s *sAdminProject) Model(ctx context.Context) *gdb.Model {
return dao.AdminProject.Ctx(ctx).Handler(func(m *gdb.Model) *gdb.Model {
@ -66,6 +93,12 @@ func (s *sAdminProject) Delete(ctx context.Context, in *adminin.ProjectDeleteInp
err = gerror.New("没有找到项目!")
return err
}
var project *entity.AdminProject
err = s.Model(ctx).WherePri(in.Id).Scan(&project)
if project.Status == 1 {
err = gerror.New("项目已发布,无法删除!")
return err
}
_, err = s.Model(ctx).WherePri(in.Id).Delete()
return
}
@ -165,3 +198,193 @@ func (s *sAdminProject) ExistById(ctx context.Context, id int64) (exists bool, e
exists = count > 0
return
}
func (s *sAdminProject) Deploy(ctx context.Context, in *adminin.ProjectDeployInp) (err error) {
var tempName = guid.S()
var basePath = "resource/tmp/" + tempName
var project *entity.AdminProject
var jsonObj *model.JsonObj
err = s.Model(ctx).WherePri(in.Id).Scan(&project)
if project == nil {
err = gerror.New("项目不存在")
return
}
gconv.Struct(project.Content, &jsonObj)
fmt.Println(jsonObj.EditCanvasConfig.BackgroundImage)
if jsonObj.EditCanvasConfig.BackgroundImage != "" {
backimageUrl := gconv.String(jsonObj.EditCanvasConfig.BackgroundImage)
urlarr := strings.Split(backimageUrl, "?")
filename := filepath.Base(urlarr[0])
DownloadImage(ctx, urlarr[0], basePath+"/data/image/")
jsonObj.EditCanvasConfig.BackgroundImage = "/data/image/" + filename + "?" + urlarr[1]
}
componentList := jsonObj.ComponentList
for _, component := range componentList {
if component.Key == "Image" && component.Option.Dataset != nil {
fmt.Println("Image")
fmt.Println(component.Option.Dataset)
fileUrl := gconv.String(component.Option.Dataset)
filename := filepath.Base(fileUrl)
DownloadImage(ctx, fileUrl, basePath+"/data/image/")
component.Option.Dataset = "/data/image/" + filename
}
if component.Key == "Video" && component.Option.Dataset != nil {
fmt.Println("Video")
fmt.Println(component.Option.Dataset)
fileUrl := gconv.String(component.Option.Dataset)
filename := filepath.Base(fileUrl)
DownloadImage(ctx, fileUrl, basePath+"/data/video/")
component.Option.Dataset = "/data/video/" + filename
}
if component.Key == "ImageCarousel" && component.Option.Dataset != nil {
fmt.Println("ImageCarousel")
fmt.Println(component.Option.Dataset)
var datalist = gconv.SliceStr(component.Option.Dataset)
for i, fileUrl := range datalist {
filename := filepath.Base(fileUrl)
DownloadImage(ctx, fileUrl, basePath+"/data/image/")
datalist[i] = "/data/image/" + filename
}
component.Option.Dataset = datalist
}
}
jsonstr, err := json.Marshal(jsonObj)
os.WriteFile(basePath+"/project.json", jsonstr, 0666)
err = utils.ZipCompress(basePath, basePath+".zip")
if err != nil {
return err
}
g.Log().Debug(ctx, "压缩文件完成")
s.BuildTask(ctx, in.Url, basePath+".zip", in.Id)
//serverFile := basePath + tempName + ".zip"
return nil
}
func DownloadImage(ctx context.Context, url string, path string) error {
// 发送 GET 请求获取图片
resp, err := http.Get(url)
if err != nil {
g.Log().Error(ctx, err)
return fmt.Errorf("failed to fetch the image: %w", err)
}
defer resp.Body.Close()
// 检查响应状态码
if resp.StatusCode != http.StatusOK {
g.Log().Error(ctx, err)
return fmt.Errorf("request returned status code %d", resp.StatusCode)
}
// 获取图片扩展名
filename := filepath.Base(url)
// 确保目录存在
err = os.MkdirAll(path, os.ModePerm)
if err != nil {
g.Log().Error(ctx, err)
return fmt.Errorf("failed to create directory: %w", err)
}
// 打开或创建文件
file, err := os.Create(path + filename)
if err != nil {
g.Log().Error(ctx, err)
return fmt.Errorf("failed to create file: %w", err)
}
defer file.Close()
// 将图片数据写入文件
_, err = io.Copy(file, resp.Body)
if err != nil {
g.Log().Error(ctx, err)
return fmt.Errorf("failed to write data to file: %w", err)
}
return nil
}
func (s *sAdminProject) BuildTask(ctx context.Context, options string, resource string, projectId int64) (err error) {
serviceurl := s.GetCfgEnv(ctx, DEPLOY_BUILD_URL_KEY)
jobName := s.GetCfgEnv(ctx, DEPLOY_BUILD_JOBNAME_KEY)
callback := s.GetCfgEnv(ctx, DEPLOY_BUILD_CALLBACK_KEY)
uploadPath := s.GetCfgEnv(ctx, DEPLOY_BUILD_UPLOAD_KEY)
last := strings.LastIndex(resource, "/")
if last > 0 {
filename := resource
var uploadFile = ""
if gstr.ToLower("windows") == "linux" {
uploadFile = "bin/linux_amd64/hc-base-gf"
} else {
uploadFile = "bin/windows_amd64/hc-base-gf.exe"
}
paras := map[string]string{
"jobName": jobName,
"remote_path": "obj.ResUrl",
"project_id": gconv.String(projectId),
// "target_path": "target/project",
"target_path": "/projects/1panel/1panel/apps/jenkins/jenkins/data/_data/jenkins_output",
"file_name": filename,
"callback_url": callback, //"http://192.168.10.241:30621/port/getJobBuildBack",
"upload_path": uploadPath,
"deploy_env": "windows",
"auto_open_enable": "true",
"upload_file": uploadFile,
"front_path": "",
}
num, err, errMsg := s.buildJenkinsJob(ctx, serviceurl, paras, jobName)
g.Log().Info(ctx, fmt.Sprintf("构建任务:%s, num%d, err%s, errMsg%s", jobName, num, err, errMsg))
}
return err
}
func (s *sAdminProject) GetCfgEnv(ctx context.Context, key string) string {
v, _ := g.Cfg().GetWithEnv(ctx, key)
return v.String()
}
func (s *sAdminProject) buildJenkinsJob(ctx context.Context, baseUrl string, parameters map[string]string, pipelineJobName string) (num int64, err error, errMsg string) {
glog.Info(ctx, fmt.Sprintf("开始构建部署任务baseUrl%s, parameters%spipelineJobName%s", baseUrl, parameters, pipelineJobName))
// 替换为有效的用户名和 API Token
jobuser := s.GetCfgEnv(ctx, DEPLOY_BUILD_JOBUSER_KEY)
jobpassword := s.GetCfgEnv(ctx, DEPLOY_BUILD_JOBPASSWORD_KEY)
// 创建 HTTP 客户端
client := &http.Client{}
glog.Info(ctx, fmt.Sprintf("初始化Jenkins客户端baseUrl%s用户%s", baseUrl, jobuser))
jenkins, err := gojenkins.CreateJenkins(client, baseUrl, jobuser, jobpassword).Init(ctx)
if err != nil {
errMsg = fmt.Sprintf("Jenkins 客户端初始化失败baseUrl%s用户%s", baseUrl, jobuser)
glog.Errorf(ctx, errMsg, err)
return 0, err, errMsg
}
jobarr := strings.Split(pipelineJobName, "/")
newjobname := strings.Join(jobarr, "/job/")
glog.Info(ctx, fmt.Sprintf("触发流水线执行,任务名:%s", newjobname))
queId, err := jenkins.BuildJob(ctx, newjobname, parameters)
glog.Debug(ctx, queId)
if err != nil {
errMsg = fmt.Sprintf("触发流水线执行失败:流水线名:%s 错误信息:%s", newjobname, err.Error())
glog.Error(ctx, errMsg, err)
return 0, err, errMsg
}
//通过队列号获取不到构建,只用来刷新构建号获取值
build, err := jenkins.GetBuildFromQueueID(ctx, queId)
if build != nil {
glog.Debug(ctx, build.GetBuildNumber())
} else {
glog.Debug(ctx, queId)
}
job, err := jenkins.GetJob(ctx, newjobname)
lastbuild, err := job.GetLastBuild(ctx)
glog.Debug(ctx, "流水线执行已触发,构建号:", lastbuild.GetBuildNumber())
glog.Info(ctx, "部署任务执行成功,构建号:", lastbuild.GetBuildNumber())
return lastbuild.GetBuildNumber(), err, ""
}

View File

@ -125,3 +125,15 @@ type ProjectPublishModel struct{}
type ProjectUploadInp struct {
File *ghttp.UploadFile `json:"object" type:"file" dc:"文件"`
}
type ProjectDeployInp struct {
Id int64 `json:"id"`
Url string `json:"url"`
}
type ProjectDeployListInp struct {
Name string `json:"name"`
}
type ProjectDeployListModel struct {
}

109
internal/model/json_obj.go Normal file
View File

@ -0,0 +1,109 @@
package model
type JsonObj struct {
EditCanvasConfig *EditCanvasConfig `json:"editCanvasConfig"`
ComponentList []*Component `json:"componentList"`
RequestGlobalConfig interface{} `json:"requestGlobalConfig"`
StaticFile interface{} `json:"staticFile"`
GlobalVarList []interface{} `json:"globalVarList"`
}
type Component struct {
Id string `json:"id"`
IsGroup bool `json:"isGroup"`
Attr interface{} `json:"attr"`
Styles interface{} `json:"styles"`
Preview struct {
OverFlowHidden bool `json:"overFlowHidden"`
} `json:"preview"`
Status struct {
Lock bool `json:"lock"`
Hide bool `json:"hide"`
} `json:"status"`
Request interface{} `json:"request"`
Filter interface{} `json:"filter"`
Events interface{} `json:"events"`
Key string `json:"key"`
ChartConfig struct {
Key string `json:"key"`
ChartKey string `json:"chartKey"`
ConKey string `json:"conKey"`
Title string `json:"title"`
Category string `json:"category"`
CategoryName string `json:"categoryName"`
Package string `json:"package"`
ChartFrame string `json:"chartFrame"`
Image string `json:"image"`
} `json:"chartConfig"`
Option struct {
Type string `json:"type"`
Dataset interface{} `json:"dataset"`
Fit string `json:"fit"`
BorderRadius int `json:"borderRadius,omitempty"`
Loop bool `json:"loop,omitempty"`
Muted bool `json:"muted,omitempty"`
Autoplay bool `json:"autoplay,omitempty"`
Interval int `json:"interval,omitempty"`
SlidesPerview int `json:"slidesPerview,omitempty"`
Direction string `json:"direction,omitempty"`
Draggable bool `json:"draggable,omitempty"`
CenteredSlides bool `json:"centeredSlides,omitempty"`
Effect string `json:"effect,omitempty"`
ShowDots bool `json:"showDots,omitempty"`
DotType string `json:"dotType,omitempty"`
DotPlacement string `json:"dotPlacement,omitempty"`
ShowArrow bool `json:"showArrow,omitempty"`
} `json:"option"`
}
type EditCanvasConfig struct {
ProjectName string `json:"projectName"`
Width int `json:"width"`
Height int `json:"height"`
FilterShow bool `json:"filterShow"`
HueRotate int `json:"hueRotate"`
Saturate int `json:"saturate"`
Contrast int `json:"contrast"`
Brightness int `json:"brightness"`
Opacity int `json:"opacity"`
RotateZ int `json:"rotateZ"`
RotateX int `json:"rotateX"`
RotateY int `json:"rotateY"`
SkewX int `json:"skewX"`
SkewY int `json:"skewY"`
BlendMode string `json:"blendMode"`
Background interface{} `json:"background"`
BackgroundImage string `json:"backgroundImage"`
SelectColor bool `json:"selectColor"`
ChartThemeColor string `json:"chartThemeColor"`
ChartCustomThemeColorInfo interface{} `json:"chartCustomThemeColorInfo"`
ChartThemeSetting interface{} `json:"chartThemeSetting"`
PreviewScaleType string `json:"previewScaleType"`
}
type RequestObj struct {
RequestDataType int `json:"requestDataType"`
RequestHttpType string `json:"requestHttpType"`
RequestUrl string `json:"requestUrl"`
RequestInterval interface{} `json:"requestInterval"`
RequestIntervalUnit string `json:"requestIntervalUnit"`
RequestContentType int `json:"requestContentType"`
RequestParamsBodyType string `json:"requestParamsBodyType"`
RequestSQLContent struct {
Sql string `json:"sql"`
} `json:"requestSQLContent"`
RequestParams struct {
Body struct {
FormData struct {
} `json:"form-data"`
XWwwFormUrlencoded struct {
} `json:"x-www-form-urlencoded"`
Json string `json:"json"`
Xml string `json:"xml"`
} `json:"Body"`
Header struct {
} `json:"Header"`
Params struct {
} `json:"Params"`
} `json:"requestParams"`
}

View File

@ -27,6 +27,8 @@ type (
Publish(ctx context.Context, in *adminin.ProjectPublishInp) (err error)
// GetData 获取指定信息
GetData(ctx context.Context, in *adminin.ProjectGetDataInp) (res *adminin.ProjectGetDataModel, err error)
//项目部署
Deploy(ctx context.Context, in *adminin.ProjectDeployInp)(err error)
}
IAdminSite interface {
// Register 账号注册

20
internal/utils/file.go Normal file
View File

@ -0,0 +1,20 @@
package utils
import "os"
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil{
return true, nil
}
if os.IsNotExist(err) {
// 创建文件夹
err := os.MkdirAll(path, os.ModePerm)
if err != nil {
return false, err
} else {
return true, nil
}
}
return false, err
}

104
internal/utils/zip.go Normal file
View File

@ -0,0 +1,104 @@
/*
* @Descripttion:
* @version:
* @Author: lfzxs@qq.com
* @Date: 2023-09-20 16:06:07
* @LastEditors: lfzxs@qq.com
* @LastEditTime: 2023-09-21 16:48:23
*/
package utils
import (
"archive/zip"
"bytes"
"io"
"os"
"path/filepath"
"golang.org/x/exp/slog"
)
func ZipCompress(dirPath string, zipPath string) error {
// 创建一个缓冲区来存储压缩后的数据
buf := new(bytes.Buffer)
// 创建一个zip.Writer
zipWriter := zip.NewWriter(buf)
// 遍历目录下的文件和子目录
err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// 构建在zip中的相对路径
relPath, err := filepath.Rel(dirPath, path)
if err != nil {
return err
}
// 判断是否为文件
if !info.IsDir() {
// 将文件添加到zip中
zipFile, err := zipWriter.Create(relPath)
if err != nil {
return err
}
// 打开文件并复制到zip中
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(zipFile, file)
if err != nil {
return err
}
}
return nil
})
if err != nil {
slog.Error("遍历目录失败:","error",err)
return err
}
// 关闭zip写入器
err = zipWriter.Close()
if err != nil {
slog.Error("关闭zip写入器失败:","error",err)
return err
}
// 将压缩后的数据写入文件
fpath := filepath.Dir(zipPath)
_,err = PathExists(fpath)
if err != nil {
slog.Error("创建压缩文件失败:","error",err)
return err
}
zipFile, err := os.Create(zipPath)
if err != nil {
slog.Error("创建压缩文件失败:","error",err)
return err
}
defer zipFile.Close()
// 将压缩后的数据复制到文件中
_, err = io.Copy(zipFile, buf)
if err != nil {
slog.Error("复制压缩数据到文件失败:","error",err)
return err
}
return nil
}

View File

@ -35,7 +35,7 @@ server:
openapiPath: "/api.json" # OpenAPI接口文档地址
swaggerPath: "/swagger" # 内置SwaggerUI展示地址
serverRoot: "resource/public" # 静态文件服务的目录根路径配置时自动开启静态文件服务
DumpRouterMap: false # 是否在Server启动时打印所有的路由列表
DumpRouterMap: true # 是否在Server启动时打印所有的路由列表
logPath: "logs/server" # 服务日志保存路径
ErrorStack: true # 当Server捕获到异常时是否记录堆栈信息到日志中默认为true
ErrorLogEnabled: true # 是否记录异常日志信息到日志中默认为true
@ -43,7 +43,7 @@ server:
accessLogEnabled: true # 是否记录访问日志默认为false
accessLogPattern: "access/{Y-m-d}.log" # 访问日志文件格式默认为"access-{Ymd}.log"
maxHeaderBytes: "100KB" # 请求头大小限制请求头包括客户端提交的Cookie数据默认设置为100KB
clientMaxBodySize: "300MB" # 客户端提交的Body大小限制同时也影响文件上传大小默认设置为300MB
clientMaxBodySize: "600MB" # 客户端提交的Body大小限制同时也影响文件上传大小默认设置为300MB
serverAgent: "HG HTTP Server" # 服务端Agent信息默认为"HG HTTP Server"
# PProf配置
pprofEnabled: true # 是否开启PProf性能调试特性默认为false
@ -73,8 +73,8 @@ token:
storager:
# 通用配置
drive: "local" # 上传驱动local本地存储
fileSize: "10" # 上传图片大小限制单位MB
fileType: "doc,docx,pdf,zip,tar,xls,xlsx,rar,jpg,jpeg,gif,npm,png,svg" # 上传文件类型限制文件上传后缀类型限制
fileSize: "1000" # 上传图片大小限制单位MB
fileType: "doc,docx,pdf,zip,tar,xls,xlsx,rar,jpg,jpeg,gif,npm,png,svg,mp4" # 上传文件类型限制文件上传后缀类型限制
imageSize: "your_image_size_value" # 上传图片大小限制单位MB
imageType: "jpg,jpeg,gif,npm,png,svg" # 上传图片类型限制图片上传后缀类型限制
localPath: "attachment/" # 本地存储路径对外访问的相对路径
@ -101,3 +101,19 @@ database:
Prefix: "hg_"
deploy:
build:
#部署中间层服务地址
url: "http://192.168.1.100:8888"
#Jenkins任务名称
jobName: "local-deploy"
#Jenkins任务用户
jobUser: "root"
#Jenkins任务密码
jobPassword: "Gy,.2024"
#Jenkins任务token
jobToken: ""
#部署结果文件上传地址
upload: "http://192.168.10.241:30103/trade/deploy/bosavepath"
#部署打包中外部打包资源的回调接口的URL地址
callBackUrl: "http://192.168.10.241:30103/trade/deploy/packinfocall"