diff --git a/.vscode/launch.json b/.vscode/launch.json
index 841f537c..5bbd7638 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -4,6 +4,7 @@
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
+
{
"name": "mayfly-go",
"type": "go",
@@ -12,6 +13,6 @@
"program": "${fileDirname}/main.go",
"env": {},
"args": []
- }
+ },
]
}
\ No newline at end of file
diff --git a/base/biz/bizerror.go b/base/biz/bizerror.go
index 07ab5f7e..56cc0184 100644
--- a/base/biz/bizerror.go
+++ b/base/biz/bizerror.go
@@ -6,18 +6,11 @@ type BizError struct {
err string
}
-const (
- SuccessCode = 200
- SuccessMsg = "success"
-
- BizErrorCode = 400
- BizErrorMsg = "error"
-
- ServerErrorCode = 500
- ServerErrorMsg = "server error"
-
- TokenErrorCode = 501
- TokenErrorMsg = "token error"
+var (
+ Success *BizError = NewBizErrCode(200, "success")
+ BizErr *BizError = NewBizErrCode(400, "biz error")
+ ServerError *BizError = NewBizErrCode(500, "server error")
+ PermissionErr *BizError = NewBizErrCode(501, "token error")
)
// 错误消息
@@ -32,7 +25,7 @@ func (e *BizError) Code() int16 {
// 创建业务逻辑错误结构体,默认为业务逻辑错误
func NewBizErr(msg string) *BizError {
- return &BizError{code: BizErrorCode, err: msg}
+ return &BizError{code: BizErr.code, err: msg}
}
// 创建业务逻辑错误结构体,可设置指定错误code
diff --git a/base/captcha/captcha.go b/base/captcha/captcha.go
new file mode 100644
index 00000000..3dd9f51d
--- /dev/null
+++ b/base/captcha/captcha.go
@@ -0,0 +1,28 @@
+package captcha
+
+import (
+ "mayfly-go/base/biz"
+
+ "github.com/mojocn/base64Captcha"
+)
+
+var store = base64Captcha.DefaultMemStore
+var driver base64Captcha.Driver = base64Captcha.DefaultDriverDigit
+
+// 生成验证码
+func Generate() (string, string) {
+ c := base64Captcha.NewCaptcha(driver, store)
+ // 获取
+ id, b64s, err := c.Generate()
+ biz.ErrIsNilAppendErr(err, "获取验证码错误: %s")
+ return id, b64s
+}
+
+// 验证验证码
+func Verify(id string, val string) bool {
+ if id == "" || val == "" {
+ return false
+ }
+ // 同时清理掉这个图片
+ return store.Verify(id, val, true)
+}
diff --git a/base/config/config.go b/base/config/config.go
index 43a4f807..865792a4 100644
--- a/base/config/config.go
+++ b/base/config/config.go
@@ -4,9 +4,13 @@ import (
"flag"
"fmt"
"mayfly-go/base/utils"
+ "mayfly-go/base/utils/assert"
"path/filepath"
)
+// 配置文件映射对象
+var Conf *Config
+
func init() {
configFilePath := flag.String("e", "./config.yml", "配置文件路径,默认为可执行文件目录")
flag.Parse()
@@ -18,6 +22,8 @@ func init() {
if err := utils.LoadYml(startConfigParam.ConfigFilePath, yc); err != nil {
panic(fmt.Sprintf("读取配置文件[%s]失败: %s", startConfigParam.ConfigFilePath, err.Error()))
}
+ // 校验配置文件内容信息
+ yc.Valid()
Conf = yc
}
@@ -33,12 +39,17 @@ var startConfigParam *CmdConfigParam
type Config struct {
App *App `yaml:"app"`
Server *Server `yaml:"server"`
+ Jwt *Jwt `yaml:"jwt"`
Redis *Redis `yaml:"redis"`
Mysql *Mysql `yaml:"mysql"`
+ Log *Log `yaml:"log"`
}
-// 配置文件映射对象
-var Conf *Config
+// 配置文件内容校验
+func (c *Config) Valid() {
+ assert.IsTrue(c.Jwt != nil, "配置文件的[jwt]信息不能为空")
+ c.Jwt.Valid()
+}
// 获取执行可执行文件时,指定的启动参数
func getStartConfig() *CmdConfigParam {
diff --git a/base/config/jwt.go b/base/config/jwt.go
new file mode 100644
index 00000000..a1492eb2
--- /dev/null
+++ b/base/config/jwt.go
@@ -0,0 +1,13 @@
+package config
+
+import "mayfly-go/base/utils/assert"
+
+type Jwt struct {
+ Key string `yaml:"key"`
+ ExpireTime uint64 `yaml:"expire-time"` // 过期时间,单位分钟
+}
+
+func (j *Jwt) Valid() {
+ assert.IsTrue(j.Key != "", "config.yml之 [jwt.key] 不能为空")
+ assert.IsTrue(j.ExpireTime != 0, "config.yml之 [jwt.expire-time] 不能为空")
+}
diff --git a/base/config/log.go b/base/config/log.go
new file mode 100644
index 00000000..ac9815be
--- /dev/null
+++ b/base/config/log.go
@@ -0,0 +1,30 @@
+package config
+
+import "path"
+
+type Log struct {
+ Level string `yaml:"level"`
+ File *LogFile `yaml:"file"`
+}
+
+type LogFile struct {
+ Name string `yaml:"name"`
+ Path string `yaml:"path"`
+}
+
+// 获取完整路径文件名
+func (l *LogFile) GetFilename() string {
+ var filepath, filename string
+ if fp := l.Path; fp == "" {
+ filepath = "./"
+ } else {
+ filepath = fp
+ }
+ if fn := l.Name; fn == "" {
+ filename = "default.log"
+ } else {
+ filename = fn
+ }
+
+ return path.Join(filepath, filename)
+}
diff --git a/base/config/server.go b/base/config/server.go
index bbced4be..381dcf32 100644
--- a/base/config/server.go
+++ b/base/config/server.go
@@ -6,6 +6,7 @@ type Server struct {
Port int `yaml:"port"`
Model string `yaml:"model"`
Cors bool `yaml:"cors"`
+ Tls *Tls `yaml:"tls"`
Static *[]*Static `yaml:"static"`
StaticFile *[]*StaticFile `yaml:"static-file"`
}
@@ -23,3 +24,9 @@ type StaticFile struct {
RelativePath string `yaml:"relative-path"`
Filepath string `yaml:"filepath"`
}
+
+type Tls struct {
+ Enable bool `yaml:"enable"` // 是否启用tls
+ KeyFile string `yaml:"key-file"` // 私钥文件路径
+ CertFile string `yaml:"cert-file"` // 证书文件路径
+}
diff --git a/base/ctx/log_handler.go b/base/ctx/log_handler.go
index 7335a284..f1e3309e 100644
--- a/base/ctx/log_handler.go
+++ b/base/ctx/log_handler.go
@@ -9,14 +9,9 @@ import (
"reflect"
"runtime/debug"
- log "github.com/sirupsen/logrus"
+ "github.com/sirupsen/logrus"
)
-func init() {
- log.SetFormatter(new(logger.LogFormatter))
- log.SetReportCaller(true)
-}
-
type LogInfo struct {
LogResp bool // 是否记录返回结果
Description string // 请求描述
@@ -37,7 +32,7 @@ func LogHandler(rc *ReqCtx) error {
return nil
}
- lfs := log.Fields{}
+ lfs := logrus.Fields{}
if la := rc.LoginAccount; la != nil {
lfs["uid"] = la.Id
lfs["uname"] = la.Username
@@ -47,10 +42,10 @@ func LogHandler(rc *ReqCtx) error {
lfs[req.Method] = req.URL.Path
if err := rc.Err; err != nil {
- log.WithFields(lfs).Error(getErrMsg(rc, err))
+ logger.Log.WithFields(lfs).Error(getErrMsg(rc, err))
return nil
}
- log.WithFields(lfs).Info(getLogMsg(rc))
+ logger.Log.WithFields(lfs).Info(getLogMsg(rc))
return nil
}
diff --git a/base/ctx/permission_handler.go b/base/ctx/permission_handler.go
index bcc97ec1..addc3ed4 100644
--- a/base/ctx/permission_handler.go
+++ b/base/ctx/permission_handler.go
@@ -4,6 +4,7 @@ import (
"fmt"
"mayfly-go/base/biz"
"mayfly-go/base/cache"
+ "mayfly-go/base/config"
"time"
)
@@ -37,7 +38,7 @@ type DefaultPermissionCodeRegistry struct {
func (r *DefaultPermissionCodeRegistry) SaveCodes(userId uint64, codes []string) {
if r.cache == nil {
- r.cache = cache.NewTimedCache(30*time.Minute, 5*time.Second).WithUpdateAccessTime(true)
+ r.cache = cache.NewTimedCache(time.Minute*time.Duration(config.Conf.Jwt.ExpireTime), 5*time.Second)
}
r.cache.Put(fmt.Sprintf("%v", userId), codes)
}
@@ -79,7 +80,7 @@ func SetPermissionCodeRegistery(pcr PermissionCodeRegistry) {
var (
permissionCodeRegistry PermissionCodeRegistry = &DefaultPermissionCodeRegistry{}
- permissionError = biz.NewBizErrCode(biz.TokenErrorCode, biz.TokenErrorMsg)
+ // permissionError = biz.NewBizErrCode(biz.TokenErrorCode, biz.TokenErrorMsg)
)
func PermissionHandler(rc *ReqCtx) error {
@@ -94,16 +95,16 @@ func PermissionHandler(rc *ReqCtx) error {
tokenStr = rc.GinCtx.Query("token")
}
if tokenStr == "" {
- return permissionError
+ return biz.PermissionErr
}
loginAccount, err := ParseToken(tokenStr)
if err != nil || loginAccount == nil {
- return permissionError
+ return biz.PermissionErr
}
// 权限不为nil,并且permission code不为空,则校验是否有权限code
if permission != nil && permission.Code != "" {
if !permissionCodeRegistry.HasCode(loginAccount.Id, permission.Code) {
- return permissionError
+ return biz.PermissionErr
}
}
diff --git a/base/ctx/req_ctx.go b/base/ctx/req_ctx.go
index 5b1fb221..8e9ff114 100644
--- a/base/ctx/req_ctx.go
+++ b/base/ctx/req_ctx.go
@@ -3,6 +3,7 @@ package ctx
import (
"mayfly-go/base/ginx"
"mayfly-go/base/model"
+ "mayfly-go/base/utils/assert"
"time"
"github.com/gin-gonic/gin"
@@ -37,9 +38,7 @@ func (rc *ReqCtx) Handle(handler HandlerFunc) {
// 应用所有请求后置处理器
ApplyHandlerInterceptor(afterHandlers, rc)
}()
- if ginCtx == nil {
- panic("ginContext == nil")
- }
+ assert.IsTrue(ginCtx != nil, "ginContext == nil")
// 默认为不记录请求参数,可在handler回调函数中覆盖赋值
rc.ReqParam = 0
diff --git a/base/ctx/token.go b/base/ctx/token.go
index d4993f71..db6176f1 100644
--- a/base/ctx/token.go
+++ b/base/ctx/token.go
@@ -4,15 +4,16 @@ import (
"errors"
"mayfly-go/base/biz"
+ "mayfly-go/base/config"
"mayfly-go/base/model"
"time"
"github.com/dgrijalva/jwt-go"
)
-const (
- JwtKey = "mykey"
- ExpTime = time.Hour * 24 * 7
+var (
+ JwtKey = config.Conf.Jwt.Key
+ ExpTime = config.Conf.Jwt.ExpireTime
)
// 创建用户token
@@ -22,7 +23,7 @@ func CreateToken(userId uint64, username string) string {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"id": userId,
"username": username,
- "exp": time.Now().Add(ExpTime).Unix(),
+ "exp": time.Now().Add(time.Minute * time.Duration(ExpTime)).Unix(),
})
// 使用自定义字符串加密 and get the complete encoded token as a string
diff --git a/base/ginx/ginx.go b/base/ginx/ginx.go
index 98e6e3af..1b3c665f 100644
--- a/base/ginx/ginx.go
+++ b/base/ginx/ginx.go
@@ -1,7 +1,6 @@
package ginx
import (
- "fmt"
"mayfly-go/base/biz"
"mayfly-go/base/global"
"mayfly-go/base/model"
@@ -13,14 +12,14 @@ import (
// 绑定并校验请求结构体参数
func BindJsonAndValid(g *gin.Context, data interface{}) {
- if err := g.BindJSON(data); err != nil {
+ if err := g.ShouldBindJSON(data); err != nil {
panic(biz.NewBizErr(err.Error()))
}
}
// 绑定查询字符串到
func BindQuery(g *gin.Context, data interface{}) {
- if err := g.BindQuery(data); err != nil {
+ if err := g.ShouldBindQuery(data); err != nil {
panic(biz.NewBizErr(err.Error()))
}
}
@@ -44,7 +43,6 @@ func QueryInt(g *gin.Context, qm string, defaultInt int) int {
// 获取路径参数
func PathParamInt(g *gin.Context, pm string) int {
value, _ := strconv.Atoi(g.Param(pm))
- biz.IsTrue(value != 0, fmt.Sprintf("%s不存在", pm))
return value
}
@@ -64,7 +62,7 @@ func SuccessRes(g *gin.Context, data interface{}) {
func ErrorRes(g *gin.Context, err interface{}) {
switch t := err.(type) {
case *biz.BizError:
- g.JSON(http.StatusOK, model.Error(t.Code(), t.Error()))
+ g.JSON(http.StatusOK, model.Error(t))
break
case error:
g.JSON(http.StatusOK, model.ServerError())
diff --git a/base/global/global.go b/base/global/global.go
index ee6bd001..3eb6cf3e 100644
--- a/base/global/global.go
+++ b/base/global/global.go
@@ -1,17 +1,11 @@
package global
import (
- "mayfly-go/base/config"
- "mayfly-go/base/logger"
-
+ "github.com/sirupsen/logrus"
"gorm.io/gorm"
)
-// 日志
-var Log = logger.Log
-
-// config.yml配置文件映射对象
-var Config = config.Conf
-
-// gorm
-var Db *gorm.DB
+var (
+ Log *logrus.Logger // 日志
+ Db *gorm.DB // gorm
+)
diff --git a/base/httpclient/httpclient.go b/base/httpclient/httpclient.go
index 6792e1b1..a52735fe 100644
--- a/base/httpclient/httpclient.go
+++ b/base/httpclient/httpclient.go
@@ -7,10 +7,14 @@ import (
"fmt"
"io"
"io/ioutil"
+ "mime/multipart"
"net/http"
+ "os"
"time"
)
+var client = &http.Client{}
+
// 默认超时
const DefTimeout = 60
@@ -22,6 +26,13 @@ type RequestWrapper struct {
header map[string]string
}
+type MultipartFile struct {
+ FieldName string // 字段名
+ FileName string // 文件名
+ FilePath string // 文件路径,文件路径不为空,则优先读取文件路径的内容
+ Bytes []byte // 文件内容
+}
+
// 创建一个请求
func NewRequest(url string) *RequestWrapper {
return &RequestWrapper{url: url}
@@ -31,12 +42,21 @@ func (r *RequestWrapper) Url(url string) *RequestWrapper {
r.url = url
return r
}
+
+func (r *RequestWrapper) Header(name, value string) *RequestWrapper {
+ if r.header == nil {
+ r.header = make(map[string]string)
+ }
+ r.header[name] = value
+ return r
+}
+
func (r *RequestWrapper) Timeout(timeout int) *RequestWrapper {
r.timeout = timeout
return r
}
-func (r *RequestWrapper) GetByParam(paramMap map[string]string) ResponseWrapper {
+func (r *RequestWrapper) GetByParam(paramMap map[string]string) *ResponseWrapper {
var params string
for k, v := range paramMap {
if params != "" {
@@ -50,13 +70,13 @@ func (r *RequestWrapper) GetByParam(paramMap map[string]string) ResponseWrapper
return r.Get()
}
-func (r *RequestWrapper) Get() ResponseWrapper {
+func (r *RequestWrapper) Get() *ResponseWrapper {
r.method = "GET"
r.body = nil
return request(r)
}
-func (r *RequestWrapper) PostJson(body string) ResponseWrapper {
+func (r *RequestWrapper) PostJson(body string) *ResponseWrapper {
buf := bytes.NewBufferString(body)
r.method = "POST"
r.body = buf
@@ -67,7 +87,7 @@ func (r *RequestWrapper) PostJson(body string) ResponseWrapper {
return request(r)
}
-func (r *RequestWrapper) PostObj(body interface{}) ResponseWrapper {
+func (r *RequestWrapper) PostObj(body interface{}) *ResponseWrapper {
marshal, err := json.Marshal(body)
if err != nil {
return createRequestError(errors.New("解析json obj错误"))
@@ -75,7 +95,7 @@ func (r *RequestWrapper) PostObj(body interface{}) ResponseWrapper {
return r.PostJson(string(marshal))
}
-func (r *RequestWrapper) PostParams(params string) ResponseWrapper {
+func (r *RequestWrapper) PostParams(params string) *ResponseWrapper {
buf := bytes.NewBufferString(params)
r.method = "POST"
r.body = buf
@@ -86,9 +106,54 @@ func (r *RequestWrapper) PostParams(params string) ResponseWrapper {
return request(r)
}
+func (r *RequestWrapper) PostMulipart(files []MultipartFile, reqParams map[string]string) *ResponseWrapper {
+ buf := &bytes.Buffer{}
+ // 文件写入 buf
+ writer := multipart.NewWriter(buf)
+ for _, uploadFile := range files {
+ var reader io.Reader
+ // 如果文件路径不为空,则读取该路径文件,否则使用bytes
+ if uploadFile.FilePath != "" {
+ file, err := os.Open(uploadFile.FilePath)
+ if err != nil {
+ return createRequestError(err)
+ }
+ defer file.Close()
+ reader = file
+ } else {
+ reader = bytes.NewBuffer(uploadFile.Bytes)
+ }
+
+ part, err := writer.CreateFormFile(uploadFile.FieldName, uploadFile.FileName)
+ if err != nil {
+ return createRequestError(err)
+ }
+ _, err = io.Copy(part, reader)
+ }
+ // 如果有其他参数,则写入body
+ if reqParams != nil {
+ for k, v := range reqParams {
+ if err := writer.WriteField(k, v); err != nil {
+ return createRequestError(err)
+ }
+ }
+ }
+ if err := writer.Close(); err != nil {
+ return createRequestError(err)
+ }
+
+ r.method = "POST"
+ r.body = buf
+ if r.header == nil {
+ r.header = make(map[string]string)
+ }
+ r.header["Content-type"] = writer.FormDataContentType()
+ return request(r)
+}
+
type ResponseWrapper struct {
StatusCode int
- Body string
+ Body []byte
Header http.Header
}
@@ -96,28 +161,33 @@ func (r *ResponseWrapper) IsSuccess() bool {
return r.StatusCode == 200
}
-func (r *ResponseWrapper) ToObj(obj interface{}) {
- if !r.IsSuccess() {
- return
- }
- _ = json.Unmarshal([]byte(r.Body), &obj)
+func (r *ResponseWrapper) BodyToObj(objPtr interface{}) error {
+ _ = json.Unmarshal(r.Body, &objPtr)
+ return r.getError()
}
-func (r *ResponseWrapper) ToMap() map[string]interface{} {
- if !r.IsSuccess() {
- return nil
- }
+func (r *ResponseWrapper) BodyToString() (string, error) {
+ return string(r.Body), r.getError()
+}
+
+func (r *ResponseWrapper) BodyToMap() (map[string]interface{}, error) {
var res map[string]interface{}
- err := json.Unmarshal([]byte(r.Body), &res)
+ err := json.Unmarshal(r.Body, &res)
if err != nil {
- return nil
+ return nil, err
}
- return res
+ return res, r.getError()
}
-func request(rw *RequestWrapper) ResponseWrapper {
- wrapper := ResponseWrapper{StatusCode: 0, Body: "", Header: make(http.Header)}
- client := &http.Client{}
+func (r *ResponseWrapper) getError() error {
+ if !r.IsSuccess() {
+ return errors.New(string(r.Body))
+ }
+ return nil
+}
+
+func request(rw *RequestWrapper) *ResponseWrapper {
+ wrapper := &ResponseWrapper{StatusCode: 0, Header: make(http.Header)}
timeout := rw.timeout
if timeout > 0 {
client.Timeout = time.Duration(timeout) * time.Second
@@ -132,17 +202,17 @@ func request(rw *RequestWrapper) ResponseWrapper {
setRequestHeader(req, rw.header)
resp, err := client.Do(req)
if err != nil {
- wrapper.Body = fmt.Sprintf("执行HTTP请求错误-%s", err.Error())
+ wrapper.Body = []byte(fmt.Sprintf("执行HTTP请求错误-%s", err.Error()))
return wrapper
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
- wrapper.Body = fmt.Sprintf("读取HTTP请求返回值失败-%s", err.Error())
+ wrapper.Body = []byte(fmt.Sprintf("读取HTTP请求返回值失败-%s", err.Error()))
return wrapper
}
wrapper.StatusCode = resp.StatusCode
- wrapper.Body = string(body)
+ wrapper.Body = body
wrapper.Header = resp.Header
return wrapper
@@ -155,7 +225,6 @@ func setRequestHeader(req *http.Request, header map[string]string) {
}
}
-func createRequestError(err error) ResponseWrapper {
- errorMessage := fmt.Sprintf("创建HTTP请求错误-%s", err.Error())
- return ResponseWrapper{0, errorMessage, make(http.Header)}
+func createRequestError(err error) *ResponseWrapper {
+ return &ResponseWrapper{0, []byte(fmt.Sprintf("创建HTTP请求错误-%s", err.Error())), make(http.Header)}
}
diff --git a/base/logger/logger.go b/base/logger/logger.go
index a123c1b7..c844bad0 100644
--- a/base/logger/logger.go
+++ b/base/logger/logger.go
@@ -2,6 +2,9 @@ package logger
import (
"fmt"
+ "mayfly-go/base/config"
+ "mayfly-go/base/global"
+ "os"
"strings"
"time"
@@ -11,12 +14,38 @@ import (
var Log = logrus.New()
func init() {
- // customFormatter := new(logrus.TextFormatter)
- // customFormatter.TimestampFormat = "2006-01-02 15:04:05.000"
- // customFormatter.FullTimestamp = true
Log.SetFormatter(new(LogFormatter))
Log.SetReportCaller(true)
- Log.SetLevel(logrus.DebugLevel)
+
+ logConf := config.Conf.Log
+ // 如果不存在日志配置信息,则默认debug级别
+ if logConf == nil {
+ Log.SetLevel(logrus.DebugLevel)
+ return
+ }
+
+ // 根据配置文件设置日志级别
+ if level := logConf.Level; level != "" {
+ l, err := logrus.ParseLevel(level)
+ if err != nil {
+ panic(fmt.Sprintf("日志级别不存在: %s", level))
+ }
+ Log.SetLevel(l)
+ } else {
+ Log.SetLevel(logrus.DebugLevel)
+ }
+
+ if logFile := logConf.File; logFile != nil {
+ //写入文件
+ file, err := os.OpenFile(logFile.GetFilename(), os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModeAppend|0666)
+ if err != nil {
+ panic(fmt.Sprintf("创建日志文件失败: %s", err.Error()))
+ }
+
+ Log.Out = file
+ }
+
+ global.Log = Log
}
type LogFormatter struct{}
diff --git a/base/model/model.go b/base/model/model.go
index 3e410729..3b108f05 100644
--- a/base/model/model.go
+++ b/base/model/model.go
@@ -2,6 +2,7 @@ package model
import (
"fmt"
+ "mayfly-go/base/biz"
"mayfly-go/base/global"
"strconv"
@@ -71,22 +72,13 @@ func GetById(model interface{}, id uint64, cols ...string) error {
// 根据id列表查询
func GetByIdIn(model interface{}, list interface{}, ids []uint64, orderBy ...string) {
- var idsStr string
- for i, v := range ids {
- idStr := strconv.Itoa(int(v))
- if i == 0 {
- idsStr += idStr
- } else {
- idsStr += ("," + idStr)
- }
- }
var orderByStr string
if orderBy == nil {
orderByStr = "id desc"
} else {
orderByStr = strings.Join(orderBy, ",")
}
- global.Db.Model(model).Where("id in (?)", idsStr).Order(orderByStr).Find(list)
+ global.Db.Model(model).Where("id in (?)", ids).Order(orderByStr).Find(list)
}
// 根据id列表查询
@@ -151,11 +143,11 @@ func GetByConditionTo(conditionModel interface{}, toModel interface{}) error {
}
// 获取分页结果
-func GetPage(pageParam *PageParam, conditionModel interface{}, toModels interface{}, orderBy ...string) PageResult {
+func GetPage(pageParam *PageParam, conditionModel interface{}, toModels interface{}, orderBy ...string) *PageResult {
var count int64
global.Db.Model(conditionModel).Where(conditionModel).Count(&count)
if count == 0 {
- return PageResult{Total: 0, List: []string{}}
+ return &PageResult{Total: 0, List: []string{}}
}
page := pageParam.PageNum
pageSize := pageParam.PageSize
@@ -165,12 +157,13 @@ func GetPage(pageParam *PageParam, conditionModel interface{}, toModels interfac
} else {
orderByStr = strings.Join(orderBy, ",")
}
- global.Db.Model(conditionModel).Where(conditionModel).Order(orderByStr).Limit(pageSize).Offset((page - 1) * pageSize).Find(toModels)
- return PageResult{Total: count, List: toModels}
+ err := global.Db.Model(conditionModel).Where(conditionModel).Order(orderByStr).Limit(pageSize).Offset((page - 1) * pageSize).Find(toModels).Error
+ biz.ErrIsNil(err, "查询失败")
+ return &PageResult{Total: count, List: toModels}
}
// 根据sql获取分页对象
-func GetPageBySql(sql string, param *PageParam, toModel interface{}, args ...interface{}) PageResult {
+func GetPageBySql(sql string, param *PageParam, toModel interface{}, args ...interface{}) *PageResult {
db := global.Db
selectIndex := strings.Index(sql, "SELECT ") + 7
fromIndex := strings.Index(sql, " FROM")
@@ -180,12 +173,13 @@ func GetPageBySql(sql string, param *PageParam, toModel interface{}, args ...int
var count int
db.Raw(countSql, args...).Scan(&count)
if count == 0 {
- return PageResult{Total: 0, List: []string{}}
+ return &PageResult{Total: 0, List: []string{}}
}
// 分页查询
limitSql := sql + " LIMIT " + strconv.Itoa(param.PageNum-1) + ", " + strconv.Itoa(param.PageSize)
- db.Raw(limitSql).Scan(toModel)
- return PageResult{Total: int64(count), List: toModel}
+ err := db.Raw(limitSql).Scan(toModel).Error
+ biz.ErrIsNil(err, "查询失败")
+ return &PageResult{Total: int64(count), List: toModel}
}
func GetListBySql(sql string, params ...interface{}) []map[string]interface{} {
@@ -194,6 +188,6 @@ func GetListBySql(sql string, params ...interface{}) []map[string]interface{} {
return maps
}
-func GetListBySql2Model(sql string, toEntity interface{}, params ...interface{}) {
- global.Db.Raw(sql, params).Find(toEntity)
+func GetListBySql2Model(sql string, toEntity interface{}, params ...interface{}) error {
+ return global.Db.Raw(sql, params).Find(toEntity).Error
}
diff --git a/base/model/result.go b/base/model/result.go
index 442503cf..93c340dc 100644
--- a/base/model/result.go
+++ b/base/model/result.go
@@ -3,20 +3,12 @@ package model
import (
"encoding/json"
"fmt"
+ "mayfly-go/base/biz"
)
const (
SuccessCode = 200
SuccessMsg = "success"
-
- BizErrorCode = 400
- BizErrorMsg = "error"
-
- ServerErrorCode = 500
- ServerErrorMsg = "server error"
-
- TokenErrorCode = 501
- TokenErrorMsg = "token error"
)
// 统一返回结果结构体
@@ -52,15 +44,19 @@ func SuccessNoData() *Result {
return &Result{Code: SuccessCode, Msg: SuccessMsg}
}
-// 返回服务器错误Result
-func ServerError() *Result {
- return &Result{Code: ServerErrorCode, Msg: ServerErrorMsg}
+func Error(bizerr *biz.BizError) *Result {
+ return &Result{Code: bizerr.Code(), Msg: bizerr.Error()}
}
-func Error(code int16, msg string) *Result {
- return &Result{Code: code, Msg: msg}
+// 返回服务器错误Result
+func ServerError() *Result {
+ return Error(biz.ServerError)
}
func TokenError() *Result {
- return &Result{Code: TokenErrorCode, Msg: TokenErrorMsg}
+ return Error(biz.PermissionErr)
+}
+
+func ErrorBy(code int16, msg string) *Result {
+ return &Result{Code: code, Msg: msg}
}
diff --git a/base/starter/gorm.go b/base/starter/gorm.go
index 3d0b2dc5..0a69bd2d 100644
--- a/base/starter/gorm.go
+++ b/base/starter/gorm.go
@@ -1,6 +1,7 @@
package starter
import (
+ "mayfly-go/base/config"
"mayfly-go/base/global"
"gorm.io/driver/mysql"
@@ -10,7 +11,7 @@ import (
)
func GormMysql() *gorm.DB {
- m := global.Config.Mysql
+ m := config.Conf.Mysql
if m == nil || m.Dbname == "" {
global.Log.Panic("未找到数据库配置信息")
return nil
diff --git a/base/starter/redis.go b/base/starter/redis.go
index 578099bb..000ae31b 100644
--- a/base/starter/redis.go
+++ b/base/starter/redis.go
@@ -2,6 +2,7 @@ package starter
import (
"fmt"
+ "mayfly-go/base/config"
"mayfly-go/base/global"
"github.com/go-redis/redis"
@@ -9,7 +10,7 @@ import (
func ConnRedis() *redis.Client {
// 设置redis客户端
- redisConf := global.Config.Redis
+ redisConf := config.Conf.Redis
if redisConf == nil {
global.Log.Panic("未找到redis配置信息")
}
diff --git a/base/starter/web-server.go b/base/starter/web-server.go
index 3616eddb..7dfb250a 100644
--- a/base/starter/web-server.go
+++ b/base/starter/web-server.go
@@ -1,17 +1,24 @@
package starter
import (
+ "mayfly-go/base/config"
"mayfly-go/base/global"
"github.com/gin-gonic/gin"
)
func RunWebServer(web *gin.Engine) {
- port := global.Config.Server.GetPort()
- if app := global.Config.App; app != nil {
+ server := config.Conf.Server
+ port := server.GetPort()
+ if app := config.Conf.App; app != nil {
global.Log.Infof("%s- Listening and serving HTTP on %s", app.GetAppInfo(), port)
} else {
global.Log.Infof("Listening and serving HTTP on %s", port)
}
- web.Run(port)
+
+ if server.Tls != nil && server.Tls.Enable {
+ web.RunTLS(port, server.Tls.CertFile, server.Tls.KeyFile)
+ } else {
+ web.Run(port)
+ }
}
diff --git a/base/utils/assert/assert.go b/base/utils/assert/assert.go
new file mode 100644
index 00000000..28855a14
--- /dev/null
+++ b/base/utils/assert/assert.go
@@ -0,0 +1,21 @@
+package assert
+
+import "fmt"
+
+// 断言条件为真,不满足的panic
+func IsTrue(condition bool, panicMsg string, params ...interface{}) {
+ if !condition {
+ if len(params) != 0 {
+ panic(fmt.Sprintf(panicMsg, params...))
+ }
+ panic(panicMsg)
+ }
+}
+
+func State(condition bool, panicMsg string, params ...interface{}) {
+ IsTrue(condition, panicMsg, params...)
+}
+
+func NotEmpty(str string, panicMsg string, params ...interface{}) {
+ IsTrue(str != "", panicMsg, params...)
+}
diff --git a/base/utils/jsonschemal_util.go b/base/utils/jsonschemal_util.go
new file mode 100644
index 00000000..6a7396f5
--- /dev/null
+++ b/base/utils/jsonschemal_util.go
@@ -0,0 +1,26 @@
+package utils
+
+import (
+ "errors"
+ "strings"
+
+ "github.com/xeipuuv/gojsonschema"
+)
+
+func ValidJsonString(schemal, json string) error {
+ scheme, jsonLoader := gojsonschema.NewStringLoader(schemal), gojsonschema.NewStringLoader(json)
+
+ result, err := gojsonschema.Validate(scheme, jsonLoader)
+ if err != nil {
+ return err
+ }
+ if result.Valid() {
+ return nil
+ }
+ errs := make([]string, 0)
+ for _, desc := range result.Errors() {
+ errs = append(errs, desc.String())
+ }
+
+ return errors.New(strings.Join(errs, "|"))
+}
diff --git a/base/utils/jsonschemal_util_test.go b/base/utils/jsonschemal_util_test.go
new file mode 100644
index 00000000..22df2c25
--- /dev/null
+++ b/base/utils/jsonschemal_util_test.go
@@ -0,0 +1,58 @@
+package utils
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/xeipuuv/gojsonschema"
+)
+
+func TestJsonSchemal(t *testing.T) {
+ schema := `{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "title": "Product",
+ "description": "A product from Acme's catalog",
+ "type": "object",
+ "properties": {
+ "id": {
+ "description": "The unique identifier for a product",
+ "type": "integer"
+ },
+ "name": {
+ "description": "Name of the product",
+ "type": "string"
+ },
+ "price": {
+ "type": "number",
+ "minimum": 0,
+ "exclusiveMinimum": true
+ }
+ },
+ "required": ["id", "name", "price"]
+ }
+ `
+
+ json := `{"id": 1, "name": "test", "price": -21}`
+
+ err := ValidJsonString(schema, json)
+ fmt.Print(err)
+}
+
+func TestJs(t *testing.T) {
+ schemaLoader := gojsonschema.NewStringLoader(`{"type": "object","properties":{"a":{"type":"object"}},"required":["a"]}`) // json格式
+ documentLoader := gojsonschema.NewStringLoader(`{"a":"b"}`) // 待校验的json数据
+
+ result, err := gojsonschema.Validate(schemaLoader, documentLoader)
+ if err != nil {
+ panic(err.Error())
+ }
+
+ if result.Valid() {
+ fmt.Printf("The document is valid\n")
+ } else {
+ fmt.Printf("The document is not valid. see errors :\n")
+ for _, desc := range result.Errors() {
+ fmt.Printf("- %s\n", desc)
+ }
+ }
+}
diff --git a/base/utils/yml.go b/base/utils/yml.go
index 4f0277d4..280e6ff2 100644
--- a/base/utils/yml.go
+++ b/base/utils/yml.go
@@ -20,3 +20,8 @@ func LoadYml(path string, out interface{}) error {
}
return nil
}
+
+func LoadYmlByString(yamlStr string, out interface{}) error {
+ // yaml解析
+ return yaml.Unmarshal([]byte(yamlStr), out)
+}
diff --git a/go.mod b/go.mod
index 9912f0ed..2c3e3e81 100644
--- a/go.mod
+++ b/go.mod
@@ -5,20 +5,23 @@ go 1.16
require (
// jwt
github.com/dgrijalva/jwt-go v3.2.0+incompatible
- github.com/gin-gonic/gin v1.6.2
- github.com/go-redis/redis v6.14.2+incompatible
- github.com/go-sql-driver/mysql v1.5.0
+ github.com/gin-gonic/gin v1.7.2
+ github.com/go-redis/redis v6.15.9+incompatible
github.com/gorilla/websocket v1.4.2
- github.com/onsi/ginkgo v1.16.1 // indirect
- github.com/onsi/gomega v1.11.0 // indirect
- github.com/pkg/sftp v1.12.0
+ // 验证码
+ github.com/mojocn/base64Captcha v1.3.4
+ github.com/onsi/ginkgo v1.16.4 // indirect
+ github.com/onsi/gomega v1.13.0 // indirect
+ github.com/pkg/sftp v1.13.1
// 定时任务
github.com/robfig/cron/v3 v3.0.1
- github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0
- github.com/sirupsen/logrus v1.6.0
+ github.com/sirupsen/logrus v1.8.1
+ // jsonschemal校验
+ github.com/xeipuuv/gojsonschema v1.2.0
// ssh
- golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
+ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
+ // gorm
gorm.io/driver/mysql v1.0.5
- gorm.io/gorm v1.21.6
+ gorm.io/gorm v1.21.11
)
diff --git a/go.sum b/go.sum
index 36abd997..5c6b7b67 100644
--- a/go.sum
+++ b/go.sum
@@ -8,21 +8,23 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
-github.com/gin-gonic/gin v1.6.2 h1:88crIK23zO6TqlQBt+f9FrPJNKm9ZEr7qjp9vl/d5TM=
-github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
+github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA=
+github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
-github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
-github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
-github.com/go-redis/redis v6.14.2+incompatible h1:UE9pLhzmWf+xHNmZsoccjXosPicuiNaInPgym8nzfg0=
-github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
+github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
+github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
+github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
+github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
@@ -31,12 +33,14 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
-github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@@ -48,8 +52,6 @@ github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI=
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
-github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
@@ -60,73 +62,91 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OH
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/mojocn/base64Captcha v1.3.4 h1:9+MZzjNSfBHniYOIpoP4xyDDPCXy14JIjsEFf89PlNw=
+github.com/mojocn/base64Captcha v1.3.4/go.mod h1:wAQCKEc5bDujxKRmbT6/vTnTt5CjStQ8bRfPWUuz/iY=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
-github.com/onsi/ginkgo v1.16.1 h1:foqVmeWDD6yYpK+Yz3fHyNIxFYNxswxqNFjSKe+vI54=
-github.com/onsi/ginkgo v1.16.1/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
+github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
+github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
+github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
-github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug=
-github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg=
+github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
+github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/sftp v1.12.0 h1:/f3b24xrDhkhddlaobPe2JgBqfdt+gC/NYl0QY9IOuI=
-github.com/pkg/sftp v1.12.0/go.mod h1:fUqqXB5vEgVCZ131L+9say31RAri6aF6KDViawhxKK8=
+github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs=
+github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
-github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0 h1:QIF48X1cihydXibm+4wfAc0r/qyPyuFiPFRNphdMpEE=
-github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
-github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
-github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
+github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
+github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
+github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
+github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
+github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
+github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
+github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
+github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
-golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI=
+golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/image v0.0.0-20190501045829-6d32002ffd75 h1:TbGuee8sSq15Iguxu4deQ7+Bqq/d2rsQejGcEtADAMQ=
+golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U=
-golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
+golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210112080510-489259a85091 h1:DMyOG0U+gKfu8JZzg2UQe9MeaC1X+xQWlAKcRnjxjCw=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
-golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
@@ -140,8 +160,10 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
-google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
@@ -158,5 +180,5 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gorm.io/driver/mysql v1.0.5 h1:WAAmvLK2rG0tCOqrf5XcLi2QUwugd4rcVJ/W3aoon9o=
gorm.io/driver/mysql v1.0.5/go.mod h1:N1OIhHAIhx5SunkMGqWbGFVeh4yTNWKmMo1GOAsohLI=
gorm.io/gorm v1.21.3/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
-gorm.io/gorm v1.21.6 h1:xEFbH7WShsnAM+HeRNv7lOeyqmDAK+dDnf1AMf/cVPQ=
-gorm.io/gorm v1.21.6/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
+gorm.io/gorm v1.21.11 h1:CxkXW6Cc+VIBlL8yJEHq+Co4RYXdSLiMKNvgoZPjLK4=
+gorm.io/gorm v1.21.11/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
diff --git a/mayfly_go_web/.env.production b/mayfly_go_web/.env.production
index 4f6692c6..e038d163 100644
--- a/mayfly_go_web/.env.production
+++ b/mayfly_go_web/.env.production
@@ -2,4 +2,4 @@
ENV = 'production'
# 线上环境接口地址
-VITE_API_URL = 'http://localhost:8888/api'
\ No newline at end of file
+VITE_API_URL = 'http://api.mayflygo.1yue.net/api'
\ No newline at end of file
diff --git a/mayfly_go_web/index.html b/mayfly_go_web/index.html
index 04d827ab..24eb58f5 100644
--- a/mayfly_go_web/index.html
+++ b/mayfly_go_web/index.html
@@ -18,6 +18,7 @@
+
diff --git a/mayfly_go_web/package.json b/mayfly_go_web/package.json
index 84ce3352..0f7c81eb 100644
--- a/mayfly_go_web/package.json
+++ b/mayfly_go_web/package.json
@@ -7,9 +7,9 @@
"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/"
},
"dependencies": {
- "core-js": "^3.6.5",
"axios": "^0.21.1",
"codemirror": "^5.61.0",
+ "core-js": "^3.6.5",
"countup.js": "^2.0.7",
"cropperjs": "^1.5.11",
"echarts": "^5.1.1",
diff --git a/mayfly_go_web/public/config.js b/mayfly_go_web/public/config.js
new file mode 100644
index 00000000..40d33388
--- /dev/null
+++ b/mayfly_go_web/public/config.js
@@ -0,0 +1,3 @@
+window.globalConfig = {
+ "BaseApiUrl": "http://localhost:8888/api"
+}
\ No newline at end of file
diff --git a/mayfly_go_web/src/common/Api.ts b/mayfly_go_web/src/common/Api.ts
index 6b4d3e03..3a7fc83e 100644
--- a/mayfly_go_web/src/common/Api.ts
+++ b/mayfly_go_web/src/common/Api.ts
@@ -48,7 +48,7 @@ class Api {
* 操作该权限,即请求对应的url
* @param {Object} param 请求该权限的参数
*/
- request(param: any): Promise {
+ request(param: any = null): Promise {
return request.send(this, param);
}
diff --git a/mayfly_go_web/src/common/assert.ts b/mayfly_go_web/src/common/assert.ts
index 65cb5854..6af5872c 100644
--- a/mayfly_go_web/src/common/assert.ts
+++ b/mayfly_go_web/src/common/assert.ts
@@ -3,7 +3,7 @@
*/
class AssertError extends Error {
constructor(message: string) {
- super(message); // (1)
+ super(message);
// 错误类名
this.name = "AssertError";
}
diff --git a/mayfly_go_web/src/common/config.ts b/mayfly_go_web/src/common/config.ts
index 72993fb7..aae770dd 100644
--- a/mayfly_go_web/src/common/config.ts
+++ b/mayfly_go_web/src/common/config.ts
@@ -1,5 +1,5 @@
const config = {
- baseApiUrl: import.meta.env.VITE_API_URL
+ baseApiUrl: (window as any).globalConfig.BaseApiUrl
}
export default config
\ No newline at end of file
diff --git a/mayfly_go_web/src/common/openApi.ts b/mayfly_go_web/src/common/openApi.ts
index 2afdb21f..2bd17f60 100644
--- a/mayfly_go_web/src/common/openApi.ts
+++ b/mayfly_go_web/src/common/openApi.ts
@@ -2,7 +2,7 @@ import request from './request'
export default {
login: (param: any) => request.request('POST', '/sys/accounts/login', param, null),
- captcha: () => request.request('GET', '/open/captcha', null, null),
+ captcha: () => request.request('GET', '/sys/captcha', null, null),
logout: (param: any) => request.request('POST', '/sys/accounts/logout/{token}', param, null),
getMenuRoute: (param: any) => request.request('Get', '/sys/resources/account', param, null)
}
\ No newline at end of file
diff --git a/mayfly_go_web/src/components/codemirror/codemirror.vue b/mayfly_go_web/src/components/codemirror/codemirror.vue
index 729af4fe..8a2c6087 100644
--- a/mayfly_go_web/src/components/codemirror/codemirror.vue
+++ b/mayfly_go_web/src/components/codemirror/codemirror.vue
@@ -53,6 +53,14 @@ export default defineComponent({
type: String,
default: null,
},
+ height: {
+ type: String,
+ default: "500px",
+ },
+ width: {
+ type: String,
+ default: "auto",
+ },
canChangeMode: {
type: Boolean,
default: false,
@@ -165,15 +173,14 @@ export default defineComponent({
}
);
- watch(
- () => props.options,
- (newValue, oldValue) => {
- console.log('options change', newValue);
- for (const key in newValue) {
- coder.setOption(key, newValue[key]);
- }
- }
- );
+ // watch(
+ // () => props.options,
+ // (newValue, oldValue) => {
+ // for (const key in newValue) {
+ // coder.setOption(key, newValue[key]);
+ // }
+ // }
+ // );
const init = () => {
if (props.options) {
@@ -195,6 +202,9 @@ export default defineComponent({
}
});
+ coder.setSize(props.width, props.height);
+ // editor.setSize('width','height');
+
// 修改编辑器的语法配置
setMode(language.value);
@@ -285,6 +295,7 @@ export default defineComponent({
coder.setValue(newVal);
state.content = newVal;
coder.scrollTo(scrollInfo.left, scrollInfo.top);
+ refresh()
}
};
@@ -292,6 +303,7 @@ export default defineComponent({
...toRefs(state),
textarea,
changeMode,
+ refresh,
};
},
});
diff --git a/mayfly_go_web/src/components/dynamic-form/DynamicForm.vue b/mayfly_go_web/src/components/dynamic-form/DynamicForm.vue
index 04c2c7f8..382df614 100755
--- a/mayfly_go_web/src/components/dynamic-form/DynamicForm.vue
+++ b/mayfly_go_web/src/components/dynamic-form/DynamicForm.vue
@@ -85,7 +85,7 @@ export default defineComponent({
});
const submit = () => {
- dynamicForm.validate((valid: boolean) => {
+ dynamicForm.value.validate((valid: boolean) => {
if (valid) {
// 提交的表单数据
const subform = { ...state.form };
diff --git a/mayfly_go_web/src/router/imports.ts b/mayfly_go_web/src/router/imports.ts
index bcc3a100..3c7eabd9 100644
--- a/mayfly_go_web/src/router/imports.ts
+++ b/mayfly_go_web/src/router/imports.ts
@@ -8,5 +8,9 @@ export const imports = {
"ResourceList": () => import('@/views/system/resource'),
"RoleList": () => import('@/views/system/role'),
"AccountList": () => import('@/views/system/account'),
- "SelectData": () => import('@/views/ops/db'),
+ "ProjectList": () => import('@/views/ops/project/ProjectList.vue'),
+ "DbList": () => import('@/views/ops/db/DbList.vue'),
+ "SqlExec": () => import('@/views/ops/db'),
+ "RedisList": () => import('@/views/ops/redis'),
+ "DataOperation": () => import('@/views/ops/redis/DataOperation.vue'),
}
\ No newline at end of file
diff --git a/mayfly_go_web/src/theme/app.scss b/mayfly_go_web/src/theme/app.scss
index c9cefdbe..b75076ef 100644
--- a/mayfly_go_web/src/theme/app.scss
+++ b/mayfly_go_web/src/theme/app.scss
@@ -14,8 +14,8 @@ body,
padding: 0;
width: 100%;
height: 100%;
- font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif;
- font-weight: 500;
+ font-family: Microsoft YaHei, Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, SimSun, sans-serif;
+ font-weight: 450;
-webkit-font-smoothing: antialiased;
-webkit-tap-highlight-color: transparent;
background-color: #f8f8f8;
@@ -274,7 +274,7 @@ body,
.toolbar {
width: 100%;
- padding: 8px;
+ padding: 6px;
background-color: #ffffff;
overflow: hidden;
line-height: 32px;
@@ -283,4 +283,10 @@ body,
.fl {
float: left;
+}
+
+.search-form {
+ .el-form-item {
+ margin-bottom: 3px;
+ }
}
\ No newline at end of file
diff --git a/mayfly_go_web/src/views/error/401.vue b/mayfly_go_web/src/views/error/401.vue
index 902e0262..05ec891d 100644
--- a/mayfly_go_web/src/views/error/401.vue
+++ b/mayfly_go_web/src/views/error/401.vue
@@ -4,10 +4,10 @@
401
-
您未被授权,没有操作权限
+
您未被授权或登录超时,没有操作权限
- 重新授权
+ 重新登录
diff --git a/mayfly_go_web/src/views/home/index.vue b/mayfly_go_web/src/views/home/index.vue
index 5712a5ac..e11caeb0 100644
--- a/mayfly_go_web/src/views/home/index.vue
+++ b/mayfly_go_web/src/views/home/index.vue
@@ -7,8 +7,8 @@
-
{{ currentTime }},admin!
-
超级管理
+
{{ `${currentTime}, ${getUserInfos.username}` }}
+
diff --git a/mayfly_go_web/src/views/login/component/Account.vue b/mayfly_go_web/src/views/login/component/Account.vue
index 7cb8b0f0..cb7db49e 100644
--- a/mayfly_go_web/src/views/login/component/Account.vue
+++ b/mayfly_go_web/src/views/login/component/Account.vue
@@ -1,10 +1,10 @@
-
-
+
+
-
+
-
+
-
1234
+
-
+
登 录
@@ -45,7 +52,7 @@
+
diff --git a/mayfly_go_web/src/views/ops/db/DbEdit.vue b/mayfly_go_web/src/views/ops/db/DbEdit.vue
new file mode 100644
index 00000000..8979bef2
--- /dev/null
+++ b/mayfly_go_web/src/views/ops/db/DbEdit.vue
@@ -0,0 +1,240 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mayfly_go_web/src/views/ops/db/DbList.vue b/mayfly_go_web/src/views/ops/db/DbList.vue
new file mode 100644
index 00000000..8aac35f2
--- /dev/null
+++ b/mayfly_go_web/src/views/ops/db/DbList.vue
@@ -0,0 +1,196 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+
+
+
+
+
+
+ 添加
+ 编辑
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ `${scope.row.host}:${scope.row.port}` }}
+
+
+
+
+
+
+
+
+
+ {{ $filters.dateFormat(scope.row.createTime) }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mayfly_go_web/src/views/ops/db/SelectData.vue b/mayfly_go_web/src/views/ops/db/SqlExec.vue
similarity index 52%
rename from mayfly_go_web/src/views/ops/db/SelectData.vue
rename to mayfly_go_web/src/views/ops/db/SqlExec.vue
index 51cf12ce..08f3f292 100644
--- a/mayfly_go_web/src/views/ops/db/SelectData.vue
+++ b/mayfly_go_web/src/views/ops/db/SqlExec.vue
@@ -1,15 +1,28 @@
-
-
+
+
-
+
-
+
-
+
-
+
-
+
+
-
-
+
diff --git a/mayfly_go_web/src/views/ops/machine/MachineList.vue b/mayfly_go_web/src/views/ops/machine/MachineList.vue
index bccf8c9b..8dc0b169 100644
--- a/mayfly_go_web/src/views/ops/machine/MachineList.vue
+++ b/mayfly_go_web/src/views/ops/machine/MachineList.vue
@@ -42,16 +42,19 @@
-
-
-
-
+
+
+ {{ `${scope.row.ip}:${scope.row.port}` }}
+
+
+
+
{{ $filters.dateFormat(scope.row.createTime) }}
-
-
+
+
{{ $filters.dateFormat(scope.row.updateTime) }}
@@ -59,7 +62,7 @@
- 监控
+
脚本管理
终端
@@ -75,6 +78,12 @@
:page-size="params.pageSize"
/>
+
+
@@ -82,40 +91,32 @@
-
-
+
diff --git a/mayfly_go_web/src/views/ops/project/api.ts b/mayfly_go_web/src/views/ops/project/api.ts
new file mode 100644
index 00000000..9603fe2a
--- /dev/null
+++ b/mayfly_go_web/src/views/ops/project/api.ts
@@ -0,0 +1,15 @@
+import Api from '@/common/Api';
+
+export const projectApi = {
+ // 获取账号可访问的项目列表
+ accountProjects: Api.create("/accounts/projects", 'get'),
+ projects: Api.create("/projects", 'get'),
+ saveProject: Api.create("/projects", 'post'),
+ // 获取项目下的环境信息
+ projectEnvs: Api.create("/projects/{projectId}/envs", 'get'),
+ saveProjectEnv: Api.create("/projects/{projectId}/envs", 'post'),
+ // 获取项目下的成员信息
+ projectMems: Api.create("/projects/{projectId}/members", 'get'),
+ saveProjectMem: Api.create("/projects/{projectId}/members", 'post'),
+ deleteProjectMem: Api.create("/projects/{projectId}/members/{accountId}", 'delete'),
+}
\ No newline at end of file
diff --git a/mayfly_go_web/src/views/ops/redis/DataOperation.vue b/mayfly_go_web/src/views/ops/redis/DataOperation.vue
new file mode 100644
index 00000000..94d871e7
--- /dev/null
+++ b/mayfly_go_web/src/views/ops/redis/DataOperation.vue
@@ -0,0 +1,281 @@
+
+
+
+
+
+
+
+
+ {{ ttlConveter(scope.row.ttl) }}
+
+
+
+
+ 查看
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mayfly_go_web/src/views/ops/redis/Info.vue b/mayfly_go_web/src/views/ops/redis/Info.vue
new file mode 100644
index 00000000..1404919e
--- /dev/null
+++ b/mayfly_go_web/src/views/ops/redis/Info.vue
@@ -0,0 +1,200 @@
+
+
+
+
+
+
+ redis_version(版本):
+ {{ info.Server.redis_version }}
+
+
+ tcp_port(端口):
+ {{ info.Server.tcp_port }}
+
+
+ redis_mode(模式):
+ {{ info.Server.redis_mode }}
+
+
+ os(宿主操作系统):
+ {{ info.Server.os }}
+
+
+ uptime_in_days(运行天数):
+ {{ info.Server.uptime_in_days }}
+
+
+ executable(可执行文件路径):
+ {{ info.Server.executable }}
+
+
+ config_file(配置文件路径):
+ {{ info.Server.config_file }}
+
+
+
+
+
+ connected_clients(已连接客户端数):
+ {{ info.Clients.connected_clients }}
+
+
+ blocked_clients(正在等待阻塞命令客户端数):
+ {{ info.Clients.blocked_clients }}
+
+
+
+
+ {{ key }}:
+ {{ value }}
+
+
+
+
+
+ total_commands_processed(总处理命令数):
+ {{ info.Stats.total_commands_processed }}
+
+
+ instantaneous_ops_per_sec(当前qps):
+ {{ info.Stats.instantaneous_ops_per_sec }}
+
+
+ total_net_input_bytes(网络入口流量字节数):
+ {{ info.Stats.total_net_input_bytes }}
+
+
+ total_net_output_bytes(网络出口流量字节数):
+ {{ info.Stats.total_net_output_bytes }}
+
+
+ expired_keys(过期key的总数量):
+ {{ info.Stats.expired_keys }}
+
+
+ instantaneous_ops_per_sec(当前qps):
+ {{ info.Stats.instantaneous_ops_per_sec }}
+
+
+
+
+
+ aof_enabled(是否启用aof):
+ {{ info.Persistence.aof_enabled }}
+
+
+ loading(是否正在载入持久化文件):
+ {{ info.Persistence.loading }}
+
+
+
+
+
+ cluster_enabled(是否启用集群模式):
+ {{ info.Cluster.cluster_enabled }}
+
+
+
+
+
+ used_memory(分配内存总量):
+ {{ info.Memory.used_memory_human }}
+
+
+ maxmemory(最大内存配置):
+ {{ info.Memory.maxmemory }}
+
+
+ used_memory_rss(已分配的内存总量,操作系统角度):
+ {{ info.Memory.used_memory_rss_human }}
+
+
+ mem_fragmentation_ratio(used_memory_rss和used_memory 之间的比率):
+ {{ info.Memory.mem_fragmentation_ratio }}
+
+
+ used_memory_peak(内存消耗峰值):
+ {{ info.Memory.used_memory_peak_human }}
+
+
+ total_system_memory(主机总内存):
+ {{ info.Memory.total_system_memory_human }}
+
+
+
+
+
+ used_cpu_sys(由Redis服务器消耗的系统CPU):
+ {{ info.CPU.used_cpu_sys }}
+
+
+ used_cpu_user(由Redis服务器消耗的用户CPU):
+ {{ info.CPU.used_cpu_user }}
+
+
+ used_cpu_sys_children(由后台进程消耗的系统CPU):
+ {{ info.CPU.used_cpu_sys_children }}
+
+
+ used_cpu_user_children(由后台进程消耗的用户CPU):
+ {{ info.CPU.used_cpu_user_children }}
+
+
+
+
+
+
+
+
+
+
diff --git a/mayfly_go_web/src/views/ops/redis/RedisEdit.vue b/mayfly_go_web/src/views/ops/redis/RedisEdit.vue
new file mode 100644
index 00000000..5c194435
--- /dev/null
+++ b/mayfly_go_web/src/views/ops/redis/RedisEdit.vue
@@ -0,0 +1,190 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mayfly_go_web/src/views/ops/redis/RedisList.vue b/mayfly_go_web/src/views/ops/redis/RedisList.vue
new file mode 100644
index 00000000..42bd3583
--- /dev/null
+++ b/mayfly_go_web/src/views/ops/redis/RedisList.vue
@@ -0,0 +1,369 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $filters.dateFormat(scope.row.createTime) }}
+
+
+
+
+
+ info
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mayfly_go_web/src/views/ops/redis/ValueDialog.vue b/mayfly_go_web/src/views/ops/redis/ValueDialog.vue
new file mode 100644
index 00000000..854b17e5
--- /dev/null
+++ b/mayfly_go_web/src/views/ops/redis/ValueDialog.vue
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mayfly_go_web/src/views/ops/redis/api.ts b/mayfly_go_web/src/views/ops/redis/api.ts
new file mode 100644
index 00000000..ecbd3a85
--- /dev/null
+++ b/mayfly_go_web/src/views/ops/redis/api.ts
@@ -0,0 +1,17 @@
+import Api from '@/common/Api';
+
+export const redisApi = {
+ redisList : Api.create("/redis", 'get'),
+ redisInfo: Api.create("/redis/{id}/info", 'get'),
+ saveRedis: Api.create("/redis", 'post'),
+ delRedis: Api.create("/redis/{id}", 'delete'),
+ // 获取权限列表
+ scan: Api.create("/redis/{id}/scan/{cursor}/{count}", 'get'),
+ getStringValue: Api.create("/redis/{id}/string-value", 'get'),
+ saveStringValue: Api.create("/redis/{id}/string-value", 'post'),
+ getHashValue: Api.create("/redis/{id}/hash-value", 'get'),
+ getSetValue: Api.create("/redis/{id}/set-value", 'get'),
+ saveHashValue: Api.create("/redis/{id}/hash-value", 'post'),
+ del: Api.create("/redis/{id}/scan/{cursor}/{count}", 'delete'),
+ delKey: Api.create("/redis/{id}/key", 'delete'),
+}
\ No newline at end of file
diff --git a/mayfly_go_web/src/views/ops/redis/index.ts b/mayfly_go_web/src/views/ops/redis/index.ts
new file mode 100644
index 00000000..bb536523
--- /dev/null
+++ b/mayfly_go_web/src/views/ops/redis/index.ts
@@ -0,0 +1 @@
+export { default } from './RedisList.vue';
\ No newline at end of file
diff --git a/mayfly_go_web/src/views/system/account/AccountEdit.vue b/mayfly_go_web/src/views/system/account/AccountEdit.vue
index 6acdccad..e094c511 100755
--- a/mayfly_go_web/src/views/system/account/AccountEdit.vue
+++ b/mayfly_go_web/src/views/system/account/AccountEdit.vue
@@ -3,14 +3,14 @@
-
+
-
+
@@ -61,13 +61,13 @@ export default defineComponent({
trigger: ['change', 'blur'],
},
],
- password: [
- {
- required: true,
- message: '请输入密码',
- trigger: ['change', 'blur'],
- },
- ],
+ // password: [
+ // {
+ // required: true,
+ // message: '请输入密码',
+ // trigger: ['change', 'blur'],
+ // },
+ // ],
},
});
diff --git a/mayfly_go_web/src/views/system/account/AccountList.vue b/mayfly_go_web/src/views/system/account/AccountList.vue
index 6ddcdce2..b75a6bab 100755
--- a/mayfly_go_web/src/views/system/account/AccountList.vue
+++ b/mayfly_go_web/src/views/system/account/AccountList.vue
@@ -19,6 +19,7 @@
>
禁用
+
+
+ {{ $filters.dateFormat(scope.row.lastLoginTime) }}
+
+
-
+
{{ $filters.dateFormat(scope.row.createTime) }}
@@ -58,8 +64,8 @@
{{ $filters.dateFormat(scope.row.updateTime) }}
-->
-
-
+
+
角色
@@ -70,14 +76,21 @@
- 禁用
启用 {
let id = row.id;
- let status = row.status ? 1 : -1;
- // await accountApi.changeStatus.request({
- // id,
- // status,
- // });
- // ElMessage.success('操作成功');
- // search();
+ let status = row.status == -1 ? 1 : -1;
+ await accountApi.changeStatus.request({
+ id,
+ status,
+ });
+ ElMessage.success('操作成功');
+ search();
};
const handlePageChange = (curPage: number) => {
@@ -267,12 +280,17 @@ export default defineComponent({
const deleteAccount = async () => {
try {
+ await ElMessageBox.confirm(`确定删除该账号?`, '提示', {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ });
await accountApi.del.request({ id: state.chooseId });
ElMessage.success('删除成功');
+ state.chooseData = null;
+ state.chooseId = null;
search();
- } catch (error) {
- ElMessage.error('刪除失败');
- }
+ } catch (err) {}
};
return {
diff --git a/mayfly_go_web/src/views/system/account/RoleEdit.vue b/mayfly_go_web/src/views/system/account/RoleEdit.vue
index b1e05344..e7381062 100755
--- a/mayfly_go_web/src/views/system/account/RoleEdit.vue
+++ b/mayfly_go_web/src/views/system/account/RoleEdit.vue
@@ -13,8 +13,9 @@
-
+
+
{{ scope.row.remark ? scope.row.remark : '暂无描述' }}
@@ -92,6 +93,11 @@ export default defineComponent({
search();
};
+ const selectable = (row: any) => {
+ // 角色code不以COMMON开头才可勾选
+ return row.code.indexOf('COMMON') != 0;
+ };
+
const select = (val: any, row: any) => {
let roles = state.roles;
// 如果账号的角色id存在则为取消该角色(删除角色id列表中的该记录id),否则为新增角色
@@ -164,6 +170,7 @@ export default defineComponent({
roleTable,
search,
handlePageChange,
+ selectable,
select,
btnOk,
cancel,
diff --git a/mayfly_go_web/src/views/system/api.ts b/mayfly_go_web/src/views/system/api.ts
index f28474d0..4d92df08 100644
--- a/mayfly_go_web/src/views/system/api.ts
+++ b/mayfly_go_web/src/views/system/api.ts
@@ -25,7 +25,7 @@ export const accountApi = {
save: Api.create("/sys/accounts", 'post'),
update: Api.create("/sys/accounts/{id}", 'put'),
del: Api.create("/sys/accounts/{id}", 'delete'),
- changeStatus: Api.create("/sys/accounts/{id}/{status}", 'put'),
+ changeStatus: Api.create("/sys/accounts/change-status/{id}/{status}", 'put'),
roleIds: Api.create("/sys/accounts/{id}/roleIds", 'get'),
roles: Api.create("/sys/accounts/{id}/roles", 'get'),
resources: Api.create("/sys/accounts/{id}/resources", 'get'),
diff --git a/mayfly_go_web/src/views/system/resource/ResourceEdit.vue b/mayfly_go_web/src/views/system/resource/ResourceEdit.vue
index f539e10b..00075be5 100644
--- a/mayfly_go_web/src/views/system/resource/ResourceEdit.vue
+++ b/mayfly_go_web/src/views/system/resource/ResourceEdit.vue
@@ -13,7 +13,7 @@
-
+
diff --git a/mayfly_go_web/src/views/system/role/RoleEdit.vue b/mayfly_go_web/src/views/system/role/RoleEdit.vue
index fa97a129..7154262a 100755
--- a/mayfly_go_web/src/views/system/role/RoleEdit.vue
+++ b/mayfly_go_web/src/views/system/role/RoleEdit.vue
@@ -5,6 +5,9 @@
+
+
+
diff --git a/mayfly_go_web/src/views/system/role/RoleList.vue b/mayfly_go_web/src/views/system/role/RoleList.vue
index e059133d..f4358621 100755
--- a/mayfly_go_web/src/views/system/role/RoleList.vue
+++ b/mayfly_go_web/src/views/system/role/RoleList.vue
@@ -44,6 +44,7 @@
+
diff --git a/mock-server/initialize/router.go b/mock-server/initialize/router.go
index 66e85c75..34f5c97e 100644
--- a/mock-server/initialize/router.go
+++ b/mock-server/initialize/router.go
@@ -1,7 +1,7 @@
package initialize
import (
- "mayfly-go/base/global"
+ "mayfly-go/base/config"
"mayfly-go/base/middleware"
"mayfly-go/mock-server/routers"
@@ -10,7 +10,7 @@ import (
func InitRouter() *gin.Engine {
// server配置
- serverConfig := global.Config.Server
+ serverConfig := config.Conf.Server
gin.SetMode(serverConfig.Model)
var router = gin.New()
diff --git a/server/__debug_bin b/server/__debug_bin
index 232f8915..c9d2aaeb 100755
Binary files a/server/__debug_bin and b/server/__debug_bin differ
diff --git a/server/config.yml b/server/config.yml
index 5c2a14ac..37119da9 100644
--- a/server/config.yml
+++ b/server/config.yml
@@ -1,5 +1,5 @@
app:
- name: devops
+ name: mayfly-go
version: 1.0.0
server:
@@ -7,6 +7,10 @@ server:
model: release
port: 8888
cors: true
+ tls:
+ enable: false
+ key-file: ./default.key
+ cert-file: ./default.pem
# 静态资源
static:
- relative-path: /assets
@@ -18,6 +22,11 @@ server:
- relative-path: /favicon.ico
filepath: ./static/favicon.ico
+jwt:
+ key: mykey
+ # 过期时间单位分钟
+ expire-time: 1440
+
redis:
host: 127.0.0.1
port: 6379
@@ -27,4 +36,11 @@ mysql:
username: root
password: 111049
db-name: mayfly-job
- config: charset=utf8&loc=Local&parseTime=true
\ No newline at end of file
+ config: charset=utf8&loc=Local&parseTime=true
+
+log:
+ # 日志等级, trace, debug, info, warn, error, fatal
+ level: info
+ # file:
+ # path: ./
+ # name: mayfly.log
\ No newline at end of file
diff --git a/server/default.key b/server/default.key
new file mode 100644
index 00000000..d050ae19
--- /dev/null
+++ b/server/default.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpgIBAAKCAQEA0CsawvEZl42Vf+0BlTuZ3Dp10yW8Oty1tjimxUj3s0WPeKil
+6+TehnQELS8vGJfek+yT99nyrt+bkRmg1kxZ57FtQFEuthG4OQZoaMDUz6Ab+8P1
+PQ9VH0XimnnYabxztJiQjl8HdJt6N4WP35kGlcul7qQ+Qc7iwjhSadfAhXVycqVI
+cGQyHiPPfbmYRjueAIC4czmMUxwFKCwjepGYkwzWuGkpMD0hg/SIXpFJE2dcqYPR
+2nCah1gxZZG00lHU1X2pehNmmgeHRkB5S7mrsCdyyV/33SAYk6T6PT7dOqY54bfn
+h3C0k+T7IzvKTXKG76eG63STmxVa6luVoKMvxwIDAQABAoIBAQCI2Y2CUpYMd9us
+edbskH4ZtaT35nrUB3y+Cog4cjvE8xnarKRHa/KOWX7VZYuEk3KTtJeh/Pn51K6k
+uUBvIUqJcq7r9XLL5uJBOuEw3HQK+qrq3GxAc+/12y+Zdji7alR2iUWfEwIHup6i
+GX/38tXNbE/tjrQO9z9Dh1tGkbvS/66tPn/T/oMxsRvZB6mCjB7yuOlEIwYTomYB
+pUFemELt8T5RtfxRa8T1VoITbfuj7zvecqlThW0H8UizsFxvrOCUaga7jtsJOCHo
+bcW5WvWwazoOfQ2BGpksKkBDf1N6pj85e4kOoYcVG9UN03ZwDvAGfQPWUlHB4YzW
+PybMwIQBAoGBAPfuOQ+ukVmkiEKj6wCBe3Z0pYeNqBGec9aj62bKFh79BCE3ZopS
+7JtGs8VfBKkBAaOy+MDuvJ2fvRNRtHT4BYe1U6ZRsmVFqHScACOaO/7TR0tz0ihL
+0QLCkbSwsXExG6bYbwP4jMHkhHArT7Hy8WXvup8PffjSiEs1A1uGvYSBAoGBANbx
+lHo+39nsc1OO8TUAWZChIQUib2hFIwzQYngSzINdfXQaGFT/omOsudAtfdjvp+qO
+Tr7WpwgFEFveDFsdJfZ2Kc2x9a3ty7IYIWaAjK2ghkAKz3Tt4gClreB6qG2SBycP
+4C2ImbY6hMaFHz3ENtTEzzTMdD1ByxQVMvoem3BHAoGBAJdaTmtMXl8jGivUdXnx
+kbVWsFZ4G8nluUGm/+XYKHjybLr6XxbCWL7SApzSzL1/Z8jPURw2od53za0li8x8
+PKQEBfTamtVIGPZW5Z7WYRnHURa2tezzm7zbmqd71lcLa54HMn5yFTuojVEMn7I6
+ZTOdjYfcpUJpA9slmc8eCkQBAoGBAJEIbxRRaoBEQMkH8Y++zbB+WKZ7RssHo4/Y
+6Ch3HtIg+i6mEPcBitRQzww+NeV0SExHe7Dfa9NIf3JNkO7F60CzGJ/3zXtvsftY
+tujQIpxhbVS3NqaCgPXI1VtbyFwupW7hEnYG7xj7wW2mk578z7afmeTZdDGFPH8v
+krccgeuvAoGBAPAwiqbZlXNx+ueI1B3T8VpXnG0ozKxG+l5B71kssZWa7xcv9yRd
+c15l2PSXNtnoT/mBID7+dqQOmfYxsDHAkUdd/BrxhXtdi9FR3AfHSEQz+VKsogAD
+uLyRd7jWTYqqGa2UToF/CBV+c6QyMB+6pzFNk5DmUEm4Gd6jcHDITYeI
+-----END RSA PRIVATE KEY-----
diff --git a/server/default.pem b/server/default.pem
new file mode 100644
index 00000000..ee7bff8d
--- /dev/null
+++ b/server/default.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDejCCAmICCQDQU4ZRt2G46TANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJ6
+aDEPMA0GA1UECAwGbWF5Zmx5MQswCQYDVQQHDAJ4bTEPMA0GA1UECgwGbWF5Zmx5
+MQ8wDQYDVQQLDAZtYXlmbHkxDzANBgNVBAMMBm1heWZseTEfMB0GCSqGSIb3DQEJ
+ARYQOTU0NTM3NDczQHFxLmNvbTAeFw0yMTA2MjQwMzI2MzBaFw0zMTA2MjIwMzI2
+MzBaMH8xCzAJBgNVBAYTAnpoMQ8wDQYDVQQIDAZtYXlmbHkxCzAJBgNVBAcMAnht
+MQ8wDQYDVQQKDAZtYXlmbHkxDzANBgNVBAsMBm1heWZseTEPMA0GA1UEAwwGbWF5
+Zmx5MR8wHQYJKoZIhvcNAQkBFhA5NTQ1Mzc0NzNAcXEuY29tMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0CsawvEZl42Vf+0BlTuZ3Dp10yW8Oty1tjim
+xUj3s0WPeKil6+TehnQELS8vGJfek+yT99nyrt+bkRmg1kxZ57FtQFEuthG4OQZo
+aMDUz6Ab+8P1PQ9VH0XimnnYabxztJiQjl8HdJt6N4WP35kGlcul7qQ+Qc7iwjhS
+adfAhXVycqVIcGQyHiPPfbmYRjueAIC4czmMUxwFKCwjepGYkwzWuGkpMD0hg/SI
+XpFJE2dcqYPR2nCah1gxZZG00lHU1X2pehNmmgeHRkB5S7mrsCdyyV/33SAYk6T6
+PT7dOqY54bfnh3C0k+T7IzvKTXKG76eG63STmxVa6luVoKMvxwIDAQABMA0GCSqG
+SIb3DQEBCwUAA4IBAQB/e8EO2XEtkYBxebR1w6i50vaegLsxQJR3l5qm7rsHu3Cr
+smJXGsc56axKCAqJ4XvSI65BT51FghAoGn62QNyiQgc0YoS99nwCCGFtnhZ2lmSe
+pfhUHegN/Qo4I8FemEMD+o9kGeAzwrnaIVIT/cNOEQgm+RzrgHHJh5QBn2XgJalU
+NeFTWaimyefwSezSa/vPbyMoAl9HkT6kdvnms/yOth4AOle6+5pM2StWjmMi4yx4
+16y3NvLTku6nAUazaHTOOu/MCqLWL2/qYTk3r7OCop2jr9Rp+HLbg5AfKLUIVXjG
+/1fnXJIuD+2u9qgDLN5PZNgz4MlU86ugtmYPFkVt
+-----END CERTIFICATE-----
diff --git a/server/devops/apis/db.go b/server/devops/apis/db.go
index 3cc1726a..35838a8d 100644
--- a/server/devops/apis/db.go
+++ b/server/devops/apis/db.go
@@ -6,6 +6,7 @@ import (
"mayfly-go/base/ctx"
"mayfly-go/base/ginx"
"mayfly-go/base/model"
+ "mayfly-go/base/utils"
"mayfly-go/server/devops/apis/form"
"mayfly-go/server/devops/apis/vo"
"mayfly-go/server/devops/application"
@@ -17,45 +18,73 @@ import (
)
type Db struct {
- DbApp application.IDb
+ DbApp application.Db
}
// @router /api/dbs [get]
func (d *Db) Dbs(rc *ctx.ReqCtx) {
- m := new(entity.Db)
+ g := rc.GinCtx
+ m := &entity.Db{EnvId: uint64(ginx.QueryInt(g, "envId", 0)),
+ ProjectId: uint64(ginx.QueryInt(g, "projectId", 0)),
+ Database: g.Query("database"),
+ }
+ ginx.BindQuery(g, m)
rc.ResData = d.DbApp.GetPageList(m, ginx.GetPageParam(rc.GinCtx), new([]vo.SelectDataDbVO))
}
-// @router /api/db/:dbId/select [get]
-func (d *Db) SelectData(rc *ctx.ReqCtx) {
+func (d *Db) Save(rc *ctx.ReqCtx) {
+ form := &form.DbForm{}
+ ginx.BindJsonAndValid(rc.GinCtx, form)
+
+ rc.ReqParam = form
+
+ db := new(entity.Db)
+ utils.Copy(db, form)
+ db.SetBaseInfo(rc.LoginAccount)
+ d.DbApp.Save(db)
+}
+
+func (d *Db) DeleteDb(rc *ctx.ReqCtx) {
+ d.DbApp.Delete(uint64(ginx.PathParamInt(rc.GinCtx, "id")))
+}
+
+// @router /api/db/:dbId/exec-sql [get]
+func (d *Db) ExecSql(rc *ctx.ReqCtx) {
g := rc.GinCtx
// 去除前后空格及换行符
- selectSql := strings.TrimFunc(g.Query("selectSql"), func(r rune) bool {
+ sql := strings.TrimFunc(g.Query("sql"), func(r rune) bool {
s := string(r)
return s == " " || s == "\n"
})
- rc.ReqParam = selectSql
+ rc.ReqParam = sql
- biz.NotEmpty(selectSql, "selectSql不能为空")
- res, err := d.DbApp.GetDbInstance(GetDbId(g)).SelectData(selectSql)
- if err != nil {
- panic(biz.NewBizErr(fmt.Sprintf("查询失败: %s", err.Error())))
- }
- rc.ResData = res
-}
-
-// @router /api/db/:dbId/exec-sql [post]
-func (d *Db) ExecSql(g *gin.Context) {
- rc := ctx.NewReqCtxWithGin(g).WithLog(ctx.NewLogInfo("sql执行"))
- rc.Handle(func(rc *ctx.ReqCtx) {
- selectSql := g.Query("sql")
- biz.NotEmpty(selectSql, "sql不能为空")
- num, err := d.DbApp.GetDbInstance(GetDbId(rc.GinCtx)).Exec(selectSql)
+ biz.NotEmpty(sql, "sql不能为空")
+ if strings.HasPrefix(sql, "SELECT") || strings.HasPrefix(sql, "select") {
+ colNames, res, err := d.DbApp.GetDbInstance(GetDbId(g)).SelectData(sql)
+ if err != nil {
+ panic(biz.NewBizErr(fmt.Sprintf("查询失败: %s", err.Error())))
+ }
+ colAndRes := make(map[string]interface{})
+ colAndRes["colNames"] = colNames
+ colAndRes["res"] = res
+ rc.ResData = colAndRes
+ } else {
+ rowsAffected, err := d.DbApp.GetDbInstance(GetDbId(g)).Exec(sql)
if err != nil {
panic(biz.NewBizErr(fmt.Sprintf("执行失败: %s", err.Error())))
}
- rc.ResData = num
- })
+ res := make([]map[string]string, 0)
+ resData := make(map[string]string)
+ resData["影响条数"] = fmt.Sprintf("%d", rowsAffected)
+ res = append(res, resData)
+
+ colAndRes := make(map[string]interface{})
+ colAndRes["colNames"] = []string{"影响条数"}
+ colAndRes["res"] = res
+
+ rc.ResData = colAndRes
+ }
+
}
// @router /api/db/:dbId/t-metadata [get]
@@ -74,21 +103,32 @@ func (d *Db) ColumnMA(rc *ctx.ReqCtx) {
// @router /api/db/:dbId/hint-tables [get]
func (d *Db) HintTables(rc *ctx.ReqCtx) {
dbi := d.DbApp.GetDbInstance(GetDbId(rc.GinCtx))
+ // 获取所有表
tables := dbi.GetTableMetedatas()
- res := make(map[string][]string)
+
+ tableNames := make([]string, 0)
for _, v := range tables {
- tableName := v["tableName"]
- columnMds := dbi.GetColumnMetadatas(tableName)
- columnNames := make([]string, len(columnMds))
- for i, v := range columnMds {
- comment := v["columnComment"]
- if comment != "" {
- columnNames[i] = v["columnName"] + " [" + comment + "]"
- } else {
- columnNames[i] = v["columnName"]
- }
+ tableNames = append(tableNames, v["tableName"])
+ }
+ // 获取所有表下的所有列信息
+ columnMds := dbi.GetColumnMetadatas(tableNames...)
+ // key = 表名,value = 列名数组
+ res := make(map[string][]string)
+
+ for _, v := range columnMds {
+ tName := v["tableName"]
+ if res[tName] == nil {
+ res[tName] = make([]string, 0)
}
- res[tableName] = columnNames
+
+ columnName := fmt.Sprintf("%s [%s]", v["columnName"], v["columnType"])
+ comment := v["columnComment"]
+ // 如果字段备注不为空,则加上备注信息
+ if comment != "" {
+ columnName = fmt.Sprintf("%s[%s]", columnName, comment)
+ }
+
+ res[tName] = append(res[tName], columnName)
}
rc.ResData = res
}
diff --git a/server/devops/apis/form/db.go b/server/devops/apis/form/db.go
new file mode 100644
index 00000000..b2b637e2
--- /dev/null
+++ b/server/devops/apis/form/db.go
@@ -0,0 +1,16 @@
+package form
+
+type DbForm struct {
+ Id uint64
+ Name string `binding:"required" json:"name"`
+ Type string `binding:"required" json:"type"` // 类型,mysql oracle等
+ Host string `binding:"required" json:"host"`
+ Port int `binding:"required" json:"port"`
+ Username string `binding:"required" json:"username"`
+ Password string `binding:"required" json:"password"`
+ Database string `binding:"required" json:"database"`
+ ProjectId uint64 `binding:"required" json:"projectId"`
+ Project string `json:"project"`
+ Env string `json:"env"`
+ EnvId uint64 `binding:"required" json:"envId"`
+}
diff --git a/server/devops/apis/form/form.go b/server/devops/apis/form/form.go
index 34be5e82..1e3e74f6 100644
--- a/server/devops/apis/form/form.go
+++ b/server/devops/apis/form/form.go
@@ -2,45 +2,46 @@ package form
type MachineForm struct {
Id uint64 `json:"id"`
- Name string `json:"name" valid:"Required"`
+ Name string `json:"name" binding:"required"`
// IP地址
- Ip string `json:"ip" valid:"Required"`
+ Ip string `json:"ip" binding:"required"`
// 用户名
- Username string `json:"username" valid:"Required"`
- Password string `json:"password" valid:"Required"`
+ Username string `json:"username" binding:"required"`
+ Password string `json:"password" binding:"required"`
// 端口号
- Port int `json:"port" valid:"Required"`
+ Port int `json:"port" binding:"required"`
}
type MachineRunForm struct {
- MachineId int64 `valid:"Required"`
- Cmd string `valid:"Required"`
+ MachineId int64 `binding:"required"`
+ Cmd string `binding:"required"`
}
type MachineFileForm struct {
Id uint64
- Name string `valid:"Required"`
- MachineId uint64 `valid:"Required"`
- Type int `valid:"Required"`
- Path string `valid:"Required"`
+ Name string `binding:"required"`
+ MachineId uint64 `binding:"required"`
+ Type int `binding:"required"`
+ Path string `binding:"required"`
}
type MachineScriptForm struct {
Id uint64
- Name string `valid:"Required"`
- MachineId uint64 `valid:"Required"`
- Type int `valid:"Required"`
- Description string `valid:"Required"`
- Script string `valid:"Required"`
+ Name string `binding:"required"`
+ MachineId uint64 `binding:"required"`
+ Type int `binding:"required"`
+ Description string `binding:"required"`
+ Params string
+ Script string `binding:"required"`
}
type DbSqlSaveForm struct {
- Sql string `valid:"Required"`
- Type int `valid:"Required"`
+ Sql string `binding:"required"`
+ Type int `binding:"required"`
}
type MachineFileUpdateForm struct {
- Content string `valid:"Required"`
- Id uint64 `valid:"Required"`
- Path string `valid:"Required"`
+ Content string `binding:"required"`
+ Id uint64 `binding:"required"`
+ Path string `binding:"required"`
}
diff --git a/server/devops/apis/form/redis.go b/server/devops/apis/form/redis.go
new file mode 100644
index 00000000..514ac363
--- /dev/null
+++ b/server/devops/apis/form/redis.go
@@ -0,0 +1,18 @@
+package form
+
+type Redis struct {
+ Id uint64
+ Host string `binding:"required" json:"host"`
+ Password string `json:"password"`
+ Db int `json:"db"`
+ ProjectId uint64 `binding:"required" json:"projectId"`
+ Project string `json:"project"`
+ Env string `json:"env"`
+ EnvId uint64 `binding:"required" json:"envId"`
+}
+
+type KeyValue struct {
+ Key string `binding:"required" json:"key"`
+ Value interface{} `binding:"required" json:"value"`
+ Timed uint64
+}
diff --git a/server/devops/apis/machine.go b/server/devops/apis/machine.go
index 8d7d29c2..573b5586 100644
--- a/server/devops/apis/machine.go
+++ b/server/devops/apis/machine.go
@@ -26,7 +26,7 @@ var WsUpgrader = websocket.Upgrader{
}
type Machine struct {
- MachineApp application.IMachine
+ MachineApp application.Machine
}
func (m *Machine) Machines(rc *ctx.ReqCtx) {
@@ -45,6 +45,12 @@ func (m *Machine) SaveMachine(rc *ctx.ReqCtx) {
m.MachineApp.Save(entity)
}
+func (m *Machine) DeleteMachine(rc *ctx.ReqCtx) {
+ id := uint64(ginx.PathParamInt(rc.GinCtx, "id"))
+ rc.ReqParam = id
+ m.MachineApp.Delete(id)
+}
+
// top命令信息
func (m *Machine) Top(rc *ctx.ReqCtx) {
rc.ResData = m.MachineApp.GetCli(GetMachineId(rc.GinCtx)).GetTop()
diff --git a/server/devops/apis/machine_file.go b/server/devops/apis/machine_file.go
index edc050ef..de119a9b 100644
--- a/server/devops/apis/machine_file.go
+++ b/server/devops/apis/machine_file.go
@@ -19,8 +19,8 @@ import (
)
type MachineFile struct {
- MachineFileApp application.IMachineFile
- MachineApp application.IMachine
+ MachineFileApp application.MachineFile
+ MachineApp application.Machine
}
const (
diff --git a/server/devops/apis/machine_script.go b/server/devops/apis/machine_script.go
index 0605e457..847cbf76 100644
--- a/server/devops/apis/machine_script.go
+++ b/server/devops/apis/machine_script.go
@@ -16,8 +16,8 @@ import (
)
type MachineScript struct {
- MachineScriptApp application.IMachineScript
- MachineApp application.IMachine
+ MachineScriptApp application.MachineScript
+ MachineApp application.Machine
}
func (m *MachineScript) MachineScripts(rc *ctx.ReqCtx) {
@@ -57,8 +57,12 @@ func (m *MachineScript) RunMachineScript(rc *ctx.ReqCtx) {
biz.NotNil(ms, "该脚本不存在")
biz.IsTrue(ms.MachineId == application.Common_Script_Machine_Id || ms.MachineId == machineId, "该脚本不属于该机器")
- vars := g.QueryMap("params")
- res, err := m.MachineApp.GetCli(machineId).Run(utils.TemplateParse(ms.Script, vars))
+ script := ms.Script
+ // 如果有脚本参数,则用脚本参数替换脚本中的模板占位符参数
+ if params := g.Query("params"); params != "" {
+ script = utils.TemplateParse(ms.Script, utils.Json2Map(params))
+ }
+ res, err := m.MachineApp.GetCli(machineId).Run(script)
// 记录请求参数
rc.ReqParam = fmt.Sprintf("[machineId: %d, scriptId: %d, name: %s]", machineId, scriptId, ms.Name)
if err != nil {
diff --git a/server/devops/apis/project.go b/server/devops/apis/project.go
new file mode 100644
index 00000000..b288422e
--- /dev/null
+++ b/server/devops/apis/project.go
@@ -0,0 +1,100 @@
+package apis
+
+import (
+ "fmt"
+ "mayfly-go/base/biz"
+ "mayfly-go/base/ctx"
+ "mayfly-go/base/ginx"
+ "mayfly-go/server/devops/apis/vo"
+ "mayfly-go/server/devops/application"
+ "mayfly-go/server/devops/domain/entity"
+ sys_applicaiton "mayfly-go/server/sys/application"
+ sys_entity "mayfly-go/server/sys/domain/entity"
+)
+
+type Project struct {
+ ProjectApp application.Project
+ AccountApp sys_applicaiton.Account
+}
+
+// 获取当前登录用户可以访问的项目列表
+func (p *Project) GetProjectsByLoginAccount(rc *ctx.ReqCtx) {
+ // 获取登录用户拥有的项目ids
+ projectMembers := &[]entity.ProjectMember{}
+ p.ProjectApp.ListMember(&entity.ProjectMember{AccountId: rc.LoginAccount.Id}, projectMembers)
+ var pids []uint64
+ for _, pm := range *projectMembers {
+ pids = append(pids, pm.ProjectId)
+ }
+
+ // 获取项目信息
+ projects := &vo.AccountProjects{}
+ p.ProjectApp.ListProjectByIds(pids, projects)
+ rc.ResData = projects
+}
+
+func (p *Project) GetProjects(rc *ctx.ReqCtx) {
+ condition := &entity.Project{}
+ ginx.BindQuery(rc.GinCtx, condition)
+ // condition.Name = rc.GinCtx.Query("name")
+ rc.ResData = p.ProjectApp.GetPageList(condition, ginx.GetPageParam(rc.GinCtx), new([]entity.Project))
+}
+
+func (p *Project) SaveProject(rc *ctx.ReqCtx) {
+ project := &entity.Project{}
+ ginx.BindJsonAndValid(rc.GinCtx, project)
+ rc.ReqParam = project
+
+ project.SetBaseInfo(rc.LoginAccount)
+ p.ProjectApp.SaveProject(project)
+}
+
+// 获取项目下的环境信息
+func (p *Project) GetProjectEnvs(rc *ctx.ReqCtx) {
+ projectEnvs := &[]entity.ProjectEnv{}
+ p.ProjectApp.ListEnvByProjectId(uint64(ginx.PathParamInt(rc.GinCtx, "projectId")), projectEnvs)
+ rc.ResData = projectEnvs
+}
+
+//保存项目下的环境信息
+func (p *Project) SaveProjectEnvs(rc *ctx.ReqCtx) {
+ projectEnv := &entity.ProjectEnv{}
+ ginx.BindJsonAndValid(rc.GinCtx, projectEnv)
+ rc.ReqParam = projectEnv
+
+ projectEnv.SetBaseInfo(rc.LoginAccount)
+ p.ProjectApp.SaveProjectEnv(projectEnv)
+}
+
+// 获取项目下的成员信息
+func (p *Project) GetProjectMembers(rc *ctx.ReqCtx) {
+ projectMems := &[]entity.ProjectMember{}
+ rc.ResData = p.ProjectApp.GetMemberPage(&entity.ProjectMember{ProjectId: uint64(ginx.PathParamInt(rc.GinCtx, "projectId"))},
+ ginx.GetPageParam(rc.GinCtx), projectMems)
+}
+
+//保存项目的成员信息
+func (p *Project) SaveProjectMember(rc *ctx.ReqCtx) {
+ projectMem := &entity.ProjectMember{}
+ ginx.BindJsonAndValid(rc.GinCtx, projectMem)
+ rc.ReqParam = projectMem
+
+ // 校验账号,并赋值username
+ account := &sys_entity.Account{}
+ account.Id = projectMem.AccountId
+ biz.ErrIsNil(p.AccountApp.GetAccount(account, "Id", "Username"), "账号不存在")
+ projectMem.Username = account.Username
+
+ projectMem.SetBaseInfo(rc.LoginAccount)
+ p.ProjectApp.SaveProjectMember(projectMem)
+}
+
+//删除项目成员
+func (p *Project) DelProjectMember(rc *ctx.ReqCtx) {
+ g := rc.GinCtx
+ pid := ginx.PathParamInt(g, "projectId")
+ aid := ginx.PathParamInt(g, "accountId")
+ rc.ReqParam = fmt.Sprintf("projectId: %d, accountId: %d", pid, aid)
+
+ p.ProjectApp.DeleteMember(uint64(pid), uint64(aid))
+}
diff --git a/server/devops/apis/redis.go b/server/devops/apis/redis.go
new file mode 100644
index 00000000..035bccad
--- /dev/null
+++ b/server/devops/apis/redis.go
@@ -0,0 +1,203 @@
+package apis
+
+import (
+ "mayfly-go/base/biz"
+ "mayfly-go/base/ctx"
+ "mayfly-go/base/ginx"
+ "mayfly-go/base/utils"
+ "mayfly-go/server/devops/apis/form"
+ "mayfly-go/server/devops/apis/vo"
+ "mayfly-go/server/devops/application"
+ "mayfly-go/server/devops/domain/entity"
+ "strconv"
+ "strings"
+ "time"
+)
+
+type Redis struct {
+ RedisApp application.Redis
+}
+
+func (r *Redis) RedisList(rc *ctx.ReqCtx) {
+ g := rc.GinCtx
+ m := &entity.Redis{EnvId: uint64(ginx.QueryInt(g, "envId", 0)),
+ ProjectId: uint64(ginx.QueryInt(g, "projectId", 0)),
+ }
+ ginx.BindQuery(g, m)
+ rc.ResData = r.RedisApp.GetPageList(m, ginx.GetPageParam(rc.GinCtx), new([]vo.Redis))
+}
+
+func (r *Redis) Save(rc *ctx.ReqCtx) {
+ form := &form.Redis{}
+ ginx.BindJsonAndValid(rc.GinCtx, form)
+
+ rc.ReqParam = form
+
+ redis := new(entity.Redis)
+ utils.Copy(redis, form)
+ redis.SetBaseInfo(rc.LoginAccount)
+ r.RedisApp.Save(redis)
+}
+
+func (r *Redis) DeleteRedis(rc *ctx.ReqCtx) {
+ r.RedisApp.Delete(uint64(ginx.PathParamInt(rc.GinCtx, "id")))
+}
+
+func (r *Redis) RedisInfo(rc *ctx.ReqCtx) {
+ res, _ := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(rc.GinCtx, "id"))).Cli.Info().Result()
+
+ datas := strings.Split(res, "\r\n")
+ i := 0
+ length := len(datas)
+
+ parseMap := make(map[string]map[string]string, 0)
+ for {
+ if i >= length {
+ break
+ }
+ if strings.Contains(datas[i], "#") {
+ key := utils.SubString(datas[i], strings.Index(datas[i], "#")+1, utils.StrLen(datas[i]))
+ i++
+ key = strings.Trim(key, " ")
+
+ sectionMap := make(map[string]string, 0)
+ for {
+ if i >= length || !strings.Contains(datas[i], ":") {
+ break
+ }
+ pair := strings.Split(datas[i], ":")
+ i++
+ if len(pair) != 2 {
+ continue
+ }
+ sectionMap[pair[0]] = pair[1]
+ }
+ parseMap[key] = sectionMap
+ } else {
+ i++
+ }
+ }
+ rc.ResData = parseMap
+}
+
+// scan获取redis的key列表信息
+func (r *Redis) Scan(rc *ctx.ReqCtx) {
+ g := rc.GinCtx
+
+ ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")))
+ keys, cursor := ri.Scan(uint64(ginx.PathParamInt(g, "cursor")), g.Query("match"), int64(ginx.PathParamInt(g, "count")))
+
+ var keyInfoSplit []string
+ if len(keys) > 0 {
+ keyInfoLua := `
+ local result = {}
+ -- KEYS[1]为第1个参数,lua数组下标从1开始
+ local ttl = redis.call('ttl', KEYS[1]);
+ local keyType = redis.call('type', KEYS[1]);
+ for i = 1, #KEYS do
+ local ttl = redis.call('ttl', KEYS[i]);
+ local keyType = redis.call('type', KEYS[i]);
+ table.insert(result, string.format("%d,%s", ttl, keyType['ok']));
+ end;
+ return table.concat(result, ".");`
+ // 通过lua获取 ttl,type.ttl2,type2格式,以便下面切割获取ttl和type。避免多次调用ttl和type函数
+ keyInfos, _ := ri.Cli.Eval(keyInfoLua, keys).Result()
+ keyInfoSplit = strings.Split(keyInfos.(string), ".")
+ }
+
+ kis := make([]*vo.KeyInfo, 0)
+ for i, k := range keys {
+ ttlType := strings.Split(keyInfoSplit[i], ",")
+ ttl, _ := strconv.Atoi(ttlType[0])
+ ki := &vo.KeyInfo{Key: k, Type: ttlType[1], Ttl: uint64(ttl)}
+ kis = append(kis, ki)
+ }
+
+ size, _ := ri.Cli.DBSize().Result()
+ rc.ResData = &vo.Keys{Cursor: cursor, Keys: kis, DbSize: size}
+}
+
+func (r *Redis) DeleteKey(rc *ctx.ReqCtx) {
+ g := rc.GinCtx
+ key := g.Query("key")
+ biz.NotEmpty(key, "key不能为空")
+
+ ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")))
+ rc.ReqParam = key
+ ri.Cli.Del(key)
+}
+
+func (r *Redis) checkKey(rc *ctx.ReqCtx) (*application.RedisInstance, string) {
+ g := rc.GinCtx
+ key := g.Query("key")
+ biz.NotEmpty(key, "key不能为空")
+
+ return r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id"))), key
+}
+
+func (r *Redis) GetStringValue(rc *ctx.ReqCtx) {
+ ri, key := r.checkKey(rc)
+ str, err := ri.Cli.Get(key).Result()
+ biz.ErrIsNilAppendErr(err, "获取字符串值失败: %s")
+ rc.ResData = str
+}
+
+func (r *Redis) GetHashValue(rc *ctx.ReqCtx) {
+ ri, key := r.checkKey(rc)
+ res, err := ri.Cli.HGetAll(key).Result()
+ biz.ErrIsNilAppendErr(err, "获取hash值失败: %s")
+ rc.ResData = res
+}
+
+func (r *Redis) GetSetValue(rc *ctx.ReqCtx) {
+ ri, key := r.checkKey(rc)
+ res, err := ri.Cli.SMembers(key).Result()
+ biz.ErrIsNilAppendErr(err, "获取set值失败: %s")
+ rc.ResData = res
+}
+
+func (r *Redis) Test(rc *ctx.ReqCtx) {
+ schema := `{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "title": "Product",
+ "description": "A product from Acme's catalog",
+ "type": "object",
+ "properties": {
+ "id": {
+ "description": "The unique identifier for a product",
+ "type": "integer"
+ },
+ "name": {
+ "description": "Name of the product",
+ "type": "string"
+ },
+ "price": {
+ "type": "number",
+ "minimum": 0,
+ "exclusiveMinimum": true
+ }
+ },
+ "required": ["id", "name", "price"]
+ }
+ `
+ // 获取请求报文的内容长度
+ len := rc.GinCtx.Request.ContentLength
+ // 新建一个字节切片,长度与请求报文的内容长度相同
+ body := make([]byte, len)
+
+ // 读取 r 的请求主体,并将具体内容读入 body 中
+ rc.GinCtx.Request.Body.Read(body)
+ err := utils.ValidJsonString(schema, string(body))
+ biz.ErrIsNilAppendErr(err, "%s")
+}
+
+func (r *Redis) SetStringValue(rc *ctx.ReqCtx) {
+ g := rc.GinCtx
+ keyValue := new(form.KeyValue)
+ ginx.BindJsonAndValid(g, keyValue)
+
+ ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")))
+ str, err := ri.Cli.Set(keyValue.Key, keyValue.Value, time.Second*time.Duration(keyValue.Timed)).Result()
+ biz.ErrIsNilAppendErr(err, "保存字符串值失败: %s")
+ rc.ResData = str
+}
diff --git a/server/devops/apis/vo/db.go b/server/devops/apis/vo/db.go
index 97d406b0..7e56b791 100644
--- a/server/devops/apis/vo/db.go
+++ b/server/devops/apis/vo/db.go
@@ -10,6 +10,11 @@ type SelectDataDbVO struct {
Port *int `json:"port"`
Type *string `json:"type"`
Database *string `json:"database"`
+ Username *string `json:"username"`
+ ProjectId *int64 `json:"projectId"`
+ Project *string `json:"project"`
+ Env *string `json:"env"`
+ EnvId *int64 `json:"envId"`
CreateTime *time.Time `json:"createTime"`
Creator *string `json:"creator"`
CreatorId *int64 `json:"creatorId"`
diff --git a/server/devops/apis/vo/project.go b/server/devops/apis/vo/project.go
new file mode 100644
index 00000000..511b19e1
--- /dev/null
+++ b/server/devops/apis/vo/project.go
@@ -0,0 +1,10 @@
+package vo
+
+// 用户选择项目
+type AccountProject struct {
+ Id uint64 `json:"id"`
+ Name string `json:"name"`
+ Remark string `json:"remark"`
+}
+
+type AccountProjects []AccountProject
diff --git a/server/devops/apis/vo/redis.go b/server/devops/apis/vo/redis.go
new file mode 100644
index 00000000..c53a24c3
--- /dev/null
+++ b/server/devops/apis/vo/redis.go
@@ -0,0 +1,29 @@
+package vo
+
+import "time"
+
+type Redis struct {
+ Id *int64 `json:"id"`
+ // Name *string `json:"name"`
+ Host *string `json:"host"`
+ Db int `json:"db"`
+ ProjectId *int64 `json:"projectId"`
+ Project *string `json:"project"`
+ Env *string `json:"env"`
+ EnvId *int64 `json:"envId"`
+ CreateTime *time.Time `json:"createTime"`
+ Creator *string `json:"creator"`
+ CreatorId *int64 `json:"creatorId"`
+}
+
+type Keys struct {
+ Cursor uint64 `json:"cursor"`
+ Keys []*KeyInfo `json:"keys"`
+ DbSize int64 `json:"dbSize"`
+}
+
+type KeyInfo struct {
+ Key string `json:"key"`
+ Ttl uint64 `json:"ttl"`
+ Type string `json:"type"`
+}
diff --git a/server/devops/apis/vo/vo.go b/server/devops/apis/vo/vo.go
index 22bbf4b9..4cc8096c 100644
--- a/server/devops/apis/vo/vo.go
+++ b/server/devops/apis/vo/vo.go
@@ -34,6 +34,7 @@ type MachineScriptVO struct {
Script *string `json:"script"`
Type *int `json:"type"`
Description *string `json:"description"`
+ Params *string `json:"params"`
MachineId *uint64 `json:"machineId"`
}
diff --git a/server/devops/application/db_app.go b/server/devops/application/db_app.go
index 6686f104..7b68c2ba 100644
--- a/server/devops/application/db_app.go
+++ b/server/devops/application/db_app.go
@@ -1,16 +1,22 @@
package application
import (
+ "database/sql"
+ "errors"
+ "fmt"
+ "mayfly-go/base/biz"
"mayfly-go/base/model"
"mayfly-go/server/devops/domain/entity"
"mayfly-go/server/devops/domain/repository"
- "mayfly-go/server/devops/infrastructure/db"
"mayfly-go/server/devops/infrastructure/persistence"
+ "strings"
+ "sync"
+ "time"
)
-type IDb interface {
+type Db interface {
// 分页获取机器脚本信息列表
- GetPageList(condition *entity.Db, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult
+ GetPageList(condition *entity.Db, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
// 根据条件获取
GetDbBy(condition *entity.Db, cols ...string) error
@@ -20,36 +26,260 @@ type IDb interface {
Save(entity *entity.Db)
- GetDbInstance(id uint64) *db.DbInstance
+ // 删除数据库信息
+ Delete(id uint64)
+
+ // 获取数据库连接实例
+ GetDbInstance(id uint64) *DbInstance
}
-type dbApp struct {
- dbRepo repository.Db
+type dbAppImpl struct {
+ dbRepo repository.Db
+ dbSqlRepo repository.DbSql
}
-var Db IDb = &dbApp{dbRepo: persistence.DbDao}
+var DbApp Db = &dbAppImpl{
+ dbRepo: persistence.DbDao,
+ dbSqlRepo: persistence.DbSqlDao,
+}
// 分页获取数据库信息列表
-func (d *dbApp) GetPageList(condition *entity.Db, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult {
+func (d *dbAppImpl) GetPageList(condition *entity.Db, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return d.dbRepo.GetDbList(condition, pageParam, toEntity, orderBy...)
}
// 根据条件获取
-func (d *dbApp) GetDbBy(condition *entity.Db, cols ...string) error {
+func (d *dbAppImpl) GetDbBy(condition *entity.Db, cols ...string) error {
return d.dbRepo.GetDb(condition, cols...)
}
// 根据id获取
-func (d *dbApp) GetById(id uint64, cols ...string) *entity.Db {
+func (d *dbAppImpl) GetById(id uint64, cols ...string) *entity.Db {
return d.dbRepo.GetById(id, cols...)
}
-func (d *dbApp) Save(entity *entity.Db) {
+func (d *dbAppImpl) Save(dbEntity *entity.Db) {
+ // 默认tcp连接
+ dbEntity.Network = "tcp"
+ // 测试连接
+ TestConnection(dbEntity)
+ // 查找是否存在该库
+ oldDb := &entity.Db{Host: dbEntity.Host, Port: dbEntity.Port, Database: dbEntity.Database}
+ err := d.GetDbBy(oldDb)
+
+ if dbEntity.Id == 0 {
+ biz.IsTrue(err != nil, "该库已存在")
+ d.dbRepo.Insert(dbEntity)
+ } else {
+ // 如果存在该库,则校验修改的库是否为该库
+ if err == nil {
+ biz.IsTrue(oldDb.Id == dbEntity.Id, "该库已存在")
+ }
+ // 先关闭数据库连接
+ CloseDb(dbEntity.Id)
+ d.dbRepo.Update(dbEntity)
+ }
}
-func (d *dbApp) GetDbInstance(id uint64) *db.DbInstance {
- return db.GetDbInstance(id, func(id uint64) *entity.Db {
- return d.dbRepo.GetById(id)
- })
+func (d *dbAppImpl) Delete(id uint64) {
+ // 关闭连接
+ CloseDb(id)
+ d.dbRepo.Delete(id)
+ // 删除该库下用户保存的所有sql信息
+ d.dbSqlRepo.DeleteBy(&entity.DbSql{DbId: id})
+}
+
+func (da *dbAppImpl) GetDbInstance(id uint64) *DbInstance {
+ // Id不为0,则为需要缓存
+ needCache := id != 0
+ if needCache {
+ load, ok := dbCache.Load(id)
+ if ok {
+ return load.(*DbInstance)
+ }
+ }
+ d := da.GetById(id)
+ biz.NotNil(d, "数据库信息不存在")
+ DB, err := sql.Open(d.Type, getDsn(d))
+ biz.ErrIsNil(err, fmt.Sprintf("Open %s failed, err:%v\n", d.Type, err))
+ perr := DB.Ping()
+ if perr != nil {
+ panic(biz.NewBizErr(fmt.Sprintf("数据库连接失败: %s", perr.Error())))
+ }
+
+ // 最大连接周期,超过时间的连接就close
+ DB.SetConnMaxLifetime(100 * time.Second)
+ // 设置最大连接数
+ DB.SetMaxOpenConns(2)
+ // 设置闲置连接数
+ DB.SetMaxIdleConns(1)
+
+ dbi := &DbInstance{Id: id, Type: d.Type, db: DB}
+ if needCache {
+ dbCache.LoadOrStore(d.Id, dbi)
+ }
+ return dbi
+}
+
+//------------------------------------------------------------------------------
+
+var dbCache sync.Map
+
+func GetDbInstanceByCache(id uint64) *DbInstance {
+ if load, ok := dbCache.Load(id); ok {
+ return load.(*DbInstance)
+ }
+ return nil
+}
+
+func TestConnection(d *entity.Db) {
+ biz.NotNil(d, "数据库信息不存在")
+ DB, err := sql.Open(d.Type, getDsn(d))
+ biz.ErrIsNil(err, "Open %s failed, err:%v\n", d.Type, err)
+ defer DB.Close()
+ perr := DB.Ping()
+ biz.ErrIsNilAppendErr(perr, "数据库连接失败: %s")
+}
+
+// db实例
+type DbInstance struct {
+ Id uint64
+ Type string
+ db *sql.DB
+}
+
+// 执行查询语句
+// 依次返回 列名数组,结果map,错误
+func (d *DbInstance) SelectData(sql string) ([]string, []map[string]string, error) {
+ sql = strings.Trim(sql, " ")
+ if !strings.HasPrefix(sql, "SELECT") && !strings.HasPrefix(sql, "select") {
+ return nil, nil, errors.New("该sql非查询语句")
+ }
+ // 没加limit,则默认限制50条
+ if !strings.Contains(sql, "limit") && !strings.Contains(sql, "LIMIT") {
+ sql = sql + " LIMIT 50"
+ }
+ rows, err := d.db.Query(sql)
+ if err != nil {
+ return nil, nil, err
+ }
+ // rows对象一定要close掉,如果出错,不关掉则会很迅速的达到设置最大连接数,
+ // 后面的链接过来直接报错或拒绝,实际上也没有起效果
+ defer func() {
+ if rows != nil {
+ rows.Close()
+ }
+ }()
+ cols, _ := rows.Columns()
+ // 这里表示一行填充数据
+ scans := make([]interface{}, len(cols))
+ // 这里表示一行所有列的值,用[]byte表示
+ vals := make([][]byte, len(cols))
+ // 这里scans引用vals,把数据填充到[]byte里
+ for k := range vals {
+ scans[k] = &vals[k]
+ }
+
+ result := make([]map[string]string, 0)
+ // 列名
+ colNames := make([]string, 0)
+ // 是否第一次遍历,列名数组只需第一次遍历时加入
+ isFirst := true
+ for rows.Next() {
+ // 不Scan也会导致等待,该链接实际处于未工作的状态,然后也会导致连接数迅速达到最大
+ err := rows.Scan(scans...)
+ if err != nil {
+ return nil, nil, err
+ }
+ // 每行数据
+ rowData := make(map[string]string)
+ // 把vals中的数据复制到row中
+ for k, v := range vals {
+ key := cols[k]
+ // 如果是密码字段,则脱敏显示
+ if key == "password" {
+ v = []byte("******")
+ }
+ if isFirst {
+ colNames = append(colNames, key)
+ }
+ // 这里把[]byte数据转成string
+ rowData[key] = string(v)
+ }
+ //放入结果集
+ result = append(result, rowData)
+ isFirst = false
+ }
+ return colNames, result, nil
+}
+
+// 执行 update, insert, delete,建表等sql
+// 返回影响条数和错误
+func (d *DbInstance) Exec(sql string) (int64, error) {
+ res, err := d.db.Exec(sql)
+ if err != nil {
+ return 0, err
+ }
+ return res.RowsAffected()
+}
+
+// 关闭连接,并从缓存中移除
+func (d *DbInstance) Close() {
+ d.db.Close()
+ dbCache.Delete(d.Id)
+}
+
+// 获取dataSourceName
+func getDsn(d *entity.Db) string {
+ if d.Type == "mysql" {
+ return fmt.Sprintf("%s:%s@%s(%s:%d)/%s", d.Username, d.Password, d.Network, d.Host, d.Port, d.Database)
+ }
+ return ""
+}
+
+func CloseDb(id uint64) {
+ if di := GetDbInstanceByCache(id); di != nil {
+ di.Close()
+ }
+}
+
+//-----------------------------------元数据-------------------------------------------
+
+const (
+ // mysql 表信息元数据
+ MYSQL_TABLE_MA = `SELECT table_name tableName, engine, table_comment tableComment,
+ create_time createTime from information_schema.tables
+ WHERE table_schema = (SELECT database())`
+
+ // mysql 列信息元数据
+ MYSQL_COLOUMN_MA = `SELECT table_name tableName, column_name columnName, column_type columnType,
+ column_comment columnComment, column_key columnKey, extra from information_schema.columns
+ WHERE table_name in (%s) AND table_schema = (SELECT database()) ORDER BY ordinal_position limit 15000`
+)
+
+func (d *DbInstance) GetTableMetedatas() []map[string]string {
+ var sql string
+ if d.Type == "mysql" {
+ sql = MYSQL_TABLE_MA
+ }
+ _, res, _ := d.SelectData(sql)
+ return res
+}
+
+func (d *DbInstance) GetColumnMetadatas(tableNames ...string) []map[string]string {
+ var sql, tableName string
+ for i := 0; i < len(tableNames); i++ {
+ if i != 0 {
+ tableName = tableName + ", "
+ }
+ tableName = tableName + "'" + tableNames[i] + "'"
+ }
+ if d.Type == "mysql" {
+ sql = fmt.Sprintf(MYSQL_COLOUMN_MA, tableName)
+ }
+
+ _, res, err := d.SelectData(sql)
+ biz.ErrIsNilAppendErr(err, "获取数据库列信息失败: %s")
+ return res
}
diff --git a/server/devops/application/machine_app.go b/server/devops/application/machine_app.go
index cde31a4c..714bf568 100644
--- a/server/devops/application/machine_app.go
+++ b/server/devops/application/machine_app.go
@@ -7,58 +7,95 @@ import (
"mayfly-go/server/devops/domain/repository"
"mayfly-go/server/devops/infrastructure/machine"
"mayfly-go/server/devops/infrastructure/persistence"
+
+ "gorm.io/gorm"
)
-type IMachine interface {
+type Machine interface {
// 根据条件获取账号信息
GetMachine(condition *entity.Machine, cols ...string) error
Save(entity *entity.Machine)
+ Delete(id uint64)
+
// 根据id获取
GetById(id uint64, cols ...string) *entity.Machine
// 分页获取机器信息列表
- GetMachineList(condition *entity.Machine, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult
+ GetMachineList(condition *entity.Machine, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
// 获取机器连接
GetCli(id uint64) *machine.Cli
}
-type machineApp struct {
+type machineAppImpl struct {
machineRepo repository.Machine
}
-var Machine IMachine = &machineApp{machineRepo: persistence.MachineDao}
+var MachineApp Machine = &machineAppImpl{machineRepo: persistence.MachineDao}
// 分页获取机器信息列表
-func (m *machineApp) GetMachineList(condition *entity.Machine, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult {
+func (m *machineAppImpl) GetMachineList(condition *entity.Machine, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return m.machineRepo.GetMachineList(condition, pageParam, toEntity, orderBy...)
}
// 根据条件获取机器信息
-func (m *machineApp) Save(entity *entity.Machine) {
- biz.ErrIsNil(machine.TestConn(entity), "该机器无法连接")
- if entity.Id != 0 {
- m.machineRepo.UpdateById(entity)
+func (m *machineAppImpl) Save(me *entity.Machine) {
+ biz.ErrIsNilAppendErr(machine.TestConn(me), "该机器无法连接: %s")
+
+ oldMachine := &entity.Machine{Ip: me.Ip, Port: me.Port, Username: me.Username}
+ err := m.GetMachine(oldMachine)
+
+ if me.Id != 0 {
+ // 如果存在该库,则校验修改的库是否为该库
+ if err == nil {
+ biz.IsTrue(oldMachine.Id == me.Id, "该机器信息已存在")
+ }
+ // 关闭连接
+ machine.Close(me.Id)
+ m.machineRepo.UpdateById(me)
} else {
- m.machineRepo.Create(entity)
+ biz.IsTrue(err != nil, "该机器信息已存在")
+ m.machineRepo.Create(me)
}
}
// 根据条件获取机器信息
-func (m *machineApp) GetMachine(condition *entity.Machine, cols ...string) error {
+func (m *machineAppImpl) Delete(id uint64) {
+ // 关闭连接
+ machine.Close(id)
+ model.Tx(
+ func(db *gorm.DB) error {
+ // 删除machine表信息
+ return db.Delete(new(entity.Machine), "id = ?", id).Error
+ },
+ func(db *gorm.DB) error {
+ // 删除machine_file
+ machineFile := &entity.MachineFile{MachineId: id}
+ return db.Where(machineFile).Delete(machineFile).Error
+ },
+ func(db *gorm.DB) error {
+ // 删除machine_script
+ machineScript := &entity.MachineScript{MachineId: id}
+ return db.Where(machineScript).Delete(machineScript).Error
+ },
+ )
+}
+
+// 根据条件获取机器信息
+func (m *machineAppImpl) GetMachine(condition *entity.Machine, cols ...string) error {
return m.machineRepo.GetMachine(condition, cols...)
}
-func (m *machineApp) GetById(id uint64, cols ...string) *entity.Machine {
+func (m *machineAppImpl) GetById(id uint64, cols ...string) *entity.Machine {
return m.machineRepo.GetById(id, cols...)
}
-func (m *machineApp) GetCli(id uint64) *machine.Cli {
+func (m *machineAppImpl) GetCli(id uint64) *machine.Cli {
cli, err := machine.GetCli(id, func(machineId uint64) *entity.Machine {
return m.GetById(machineId)
})
- biz.ErrIsNil(err, "获取客户端错误")
+ biz.ErrIsNilAppendErr(err, "获取客户端错误: %s")
return cli
}
diff --git a/server/devops/application/machine_file_app.go b/server/devops/application/machine_file_app.go
index 0e4bfeaf..f9e568fb 100644
--- a/server/devops/application/machine_file_app.go
+++ b/server/devops/application/machine_file_app.go
@@ -15,9 +15,9 @@ import (
"github.com/pkg/sftp"
)
-type IMachineFile interface {
+type MachineFile interface {
// 分页获取机器文件信息列表
- GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult
+ GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
// 根据条件获取
GetMachineFile(condition *entity.MachineFile, cols ...string) error
@@ -47,34 +47,34 @@ type IMachineFile interface {
RemoveFile(fileId uint64, path string)
}
-type machineFileApp struct {
+type machineFileAppImpl struct {
machineFileRepo repository.MachineFile
machineRepo repository.Machine
}
// 实现类单例
-var MachineFile IMachineFile = &machineFileApp{
+var MachineFileApp MachineFile = &machineFileAppImpl{
machineRepo: persistence.MachineDao,
machineFileRepo: persistence.MachineFileDao,
}
// 分页获取机器脚本信息列表
-func (m *machineFileApp) GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult {
+func (m *machineFileAppImpl) GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return m.machineFileRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
}
// 根据条件获取
-func (m *machineFileApp) GetMachineFile(condition *entity.MachineFile, cols ...string) error {
+func (m *machineFileAppImpl) GetMachineFile(condition *entity.MachineFile, cols ...string) error {
return m.machineFileRepo.GetMachineFile(condition, cols...)
}
// 根据id获取
-func (m *machineFileApp) GetById(id uint64, cols ...string) *entity.MachineFile {
+func (m *machineFileAppImpl) GetById(id uint64, cols ...string) *entity.MachineFile {
return m.machineFileRepo.GetById(id, cols...)
}
// 保存机器文件配置
-func (m *machineFileApp) Save(entity *entity.MachineFile) {
+func (m *machineFileAppImpl) Save(entity *entity.MachineFile) {
biz.NotNil(m.machineRepo.GetById(entity.MachineId, "Name"), "该机器不存在")
if entity.Id != 0 {
@@ -85,11 +85,11 @@ func (m *machineFileApp) Save(entity *entity.MachineFile) {
}
// 根据id删除
-func (m *machineFileApp) Delete(id uint64) {
+func (m *machineFileAppImpl) Delete(id uint64) {
m.machineFileRepo.Delete(id)
}
-func (m *machineFileApp) ReadDir(fid uint64, path string) []fs.FileInfo {
+func (m *machineFileAppImpl) ReadDir(fid uint64, path string) []fs.FileInfo {
path, machineId := m.checkAndReturnPathMid(fid, path)
if !strings.HasSuffix(path, "/") {
path = path + "/"
@@ -101,7 +101,7 @@ func (m *machineFileApp) ReadDir(fid uint64, path string) []fs.FileInfo {
return fis
}
-func (m *machineFileApp) ReadFile(fileId uint64, path string) ([]byte, fs.FileInfo) {
+func (m *machineFileAppImpl) ReadFile(fileId uint64, path string) ([]byte, fs.FileInfo) {
path, machineId := m.checkAndReturnPathMid(fileId, path)
sftpCli := m.getSftpCli(machineId)
// 读取文件内容
@@ -119,7 +119,7 @@ func (m *machineFileApp) ReadFile(fileId uint64, path string) ([]byte, fs.FileIn
}
// 写文件内容
-func (m *machineFileApp) WriteFileContent(fileId uint64, path string, content []byte) {
+func (m *machineFileAppImpl) WriteFileContent(fileId uint64, path string, content []byte) {
_, machineId := m.checkAndReturnPathMid(fileId, path)
sftpCli := m.getSftpCli(machineId)
@@ -133,7 +133,7 @@ func (m *machineFileApp) WriteFileContent(fileId uint64, path string, content []
}
// 上传文件
-func (m *machineFileApp) UploadFile(fileId uint64, path, filename string, content []byte) {
+func (m *machineFileAppImpl) UploadFile(fileId uint64, path, filename string, content []byte) {
path, machineId := m.checkAndReturnPathMid(fileId, path)
if !strings.HasSuffix(path, "/") {
path = path + "/"
@@ -148,7 +148,7 @@ func (m *machineFileApp) UploadFile(fileId uint64, path, filename string, conten
}
// 删除文件
-func (m *machineFileApp) RemoveFile(fileId uint64, path string) {
+func (m *machineFileAppImpl) RemoveFile(fileId uint64, path string) {
path, machineId := m.checkAndReturnPathMid(fileId, path)
sftpCli := m.getSftpCli(machineId)
@@ -164,12 +164,12 @@ func (m *machineFileApp) RemoveFile(fileId uint64, path string) {
}
// 获取sftp client
-func (m *machineFileApp) getSftpCli(machineId uint64) *sftp.Client {
- return Machine.GetCli(machineId).GetSftpCli()
+func (m *machineFileAppImpl) getSftpCli(machineId uint64) *sftp.Client {
+ return MachineApp.GetCli(machineId).GetSftpCli()
}
// 校验并返回实际可访问的文件path
-func (m *machineFileApp) checkAndReturnPathMid(fid uint64, inputPath string) (string, uint64) {
+func (m *machineFileAppImpl) checkAndReturnPathMid(fid uint64, inputPath string) (string, uint64) {
biz.IsTrue(fid != 0, "文件id不能为空")
mf := m.GetById(uint64(fid))
biz.NotNil(mf, "文件不存在")
diff --git a/server/devops/application/machine_script_app.go b/server/devops/application/machine_script_app.go
index 36a51682..7a2f4f71 100644
--- a/server/devops/application/machine_script_app.go
+++ b/server/devops/application/machine_script_app.go
@@ -8,9 +8,9 @@ import (
"mayfly-go/server/devops/infrastructure/persistence"
)
-type IMachineScript interface {
+type MachineScript interface {
// 分页获取机器脚本信息列表
- GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult
+ GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
// 根据条件获取
GetMachineScript(condition *entity.MachineScript, cols ...string) error
@@ -23,7 +23,7 @@ type IMachineScript interface {
Delete(id uint64)
}
-type machineScriptApp struct {
+type machineScriptAppImpl struct {
machineScriptRepo repository.MachineScript
machineRepo repository.Machine
}
@@ -31,27 +31,27 @@ type machineScriptApp struct {
const Common_Script_Machine_Id = 9999999
// 实现类单例
-var MachineScript IMachineScript = &machineScriptApp{
+var MachineScriptApp MachineScript = &machineScriptAppImpl{
machineRepo: persistence.MachineDao,
machineScriptRepo: persistence.MachineScriptDao}
// 分页获取机器脚本信息列表
-func (m *machineScriptApp) GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult {
+func (m *machineScriptAppImpl) GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return m.machineScriptRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
}
// 根据条件获取
-func (m *machineScriptApp) GetMachineScript(condition *entity.MachineScript, cols ...string) error {
+func (m *machineScriptAppImpl) GetMachineScript(condition *entity.MachineScript, cols ...string) error {
return m.machineScriptRepo.GetMachineScript(condition, cols...)
}
// 根据id获取
-func (m *machineScriptApp) GetById(id uint64, cols ...string) *entity.MachineScript {
+func (m *machineScriptAppImpl) GetById(id uint64, cols ...string) *entity.MachineScript {
return m.machineScriptRepo.GetById(id, cols...)
}
// 保存机器脚本
-func (m *machineScriptApp) Save(entity *entity.MachineScript) {
+func (m *machineScriptAppImpl) Save(entity *entity.MachineScript) {
// 如果机器id不为公共脚本id,则校验机器是否存在
if machineId := entity.MachineId; machineId != Common_Script_Machine_Id {
biz.NotNil(m.machineRepo.GetById(machineId, "Name"), "该机器不存在")
@@ -65,6 +65,6 @@ func (m *machineScriptApp) Save(entity *entity.MachineScript) {
}
// 根据id删除
-func (m *machineScriptApp) Delete(id uint64) {
+func (m *machineScriptAppImpl) Delete(id uint64) {
m.machineScriptRepo.Delete(id)
}
diff --git a/server/devops/application/project_app.go b/server/devops/application/project_app.go
new file mode 100644
index 00000000..dda10fbf
--- /dev/null
+++ b/server/devops/application/project_app.go
@@ -0,0 +1,95 @@
+package application
+
+import (
+ "mayfly-go/base/biz"
+ "mayfly-go/base/model"
+ "mayfly-go/server/devops/domain/entity"
+ "mayfly-go/server/devops/domain/repository"
+ "mayfly-go/server/devops/infrastructure/persistence"
+)
+
+type Project interface {
+ // 分页获取项目信息列表
+ GetPageList(condition *entity.Project, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
+
+ ListProjectByIds(ids []uint64, toEntity interface{}, orderBy ...string)
+
+ SaveProject(project *entity.Project)
+
+ // 根据项目id获取所有该项目下的环境信息列表
+ ListEnvByProjectId(projectId uint64, listPtr interface{})
+
+ // 保存项目环境信息
+ SaveProjectEnv(projectEnv *entity.ProjectEnv)
+
+ // 根据条件获取项目成员信息
+ ListMember(condition *entity.ProjectMember, toEntity interface{}, orderBy ...string)
+
+ SaveProjectMember(pm *entity.ProjectMember)
+
+ // 根据条件获取项目成员信息
+ GetMemberPage(condition *entity.ProjectMember, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
+
+ DeleteMember(projectId, accountId uint64)
+}
+
+type projectAppImpl struct {
+ projectRepo repository.Project
+ projectEnvRepo repository.ProjectEnv
+ projectMemberRepo repository.ProjectMemeber
+}
+
+var ProjectApp Project = &projectAppImpl{
+ projectRepo: persistence.ProjectRepo,
+ projectEnvRepo: persistence.ProjectEnvRepo,
+ projectMemberRepo: persistence.ProjectMemberRepo,
+}
+
+// 分页获取项目信息列表
+func (p *projectAppImpl) GetPageList(condition *entity.Project, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
+ return p.projectRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
+}
+
+func (p *projectAppImpl) ListProjectByIds(ids []uint64, toEntity interface{}, orderBy ...string) {
+ p.projectRepo.GetByIdIn(ids, toEntity, orderBy...)
+}
+
+func (p *projectAppImpl) SaveProject(project *entity.Project) {
+ if project.Id == 0 {
+ p.projectRepo.Save(project)
+ } else {
+ // 防止误传导致项目名更新
+ project.Name = ""
+ p.projectRepo.Update(project)
+ }
+}
+
+// 根据项目id获取所有该项目下的环境信息列表
+func (p *projectAppImpl) ListEnvByProjectId(projectId uint64, listPtr interface{}) {
+ p.projectEnvRepo.ListEnv(&entity.ProjectEnv{ProjectId: projectId}, listPtr)
+}
+
+// 保存项目环境信息
+func (p *projectAppImpl) SaveProjectEnv(projectEnv *entity.ProjectEnv) {
+ p.projectEnvRepo.Save(projectEnv)
+}
+
+// 根据条件获取项目成员信息
+func (p *projectAppImpl) ListMember(condition *entity.ProjectMember, toEntity interface{}, orderBy ...string) {
+ p.projectMemberRepo.ListMemeber(condition, toEntity, orderBy...)
+}
+
+func (p *projectAppImpl) SaveProjectMember(pm *entity.ProjectMember) {
+ pms := new([]entity.ProjectMember)
+ p.ListMember(&entity.ProjectMember{ProjectId: pm.ProjectId, AccountId: pm.AccountId}, pms)
+ biz.IsTrue(len(*pms) == 0, "该成员已存在")
+ p.projectMemberRepo.Save(pm)
+}
+
+func (p *projectAppImpl) GetMemberPage(condition *entity.ProjectMember, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
+ return p.projectMemberRepo.GetPageList(condition, pageParam, toEntity, orderBy...)
+}
+
+func (p *projectAppImpl) DeleteMember(projectId, accountId uint64) {
+ p.projectMemberRepo.DeleteByPidMid(projectId, accountId)
+}
diff --git a/server/devops/application/redis_app.go b/server/devops/application/redis_app.go
new file mode 100644
index 00000000..6517fc29
--- /dev/null
+++ b/server/devops/application/redis_app.go
@@ -0,0 +1,146 @@
+package application
+
+import (
+ "mayfly-go/base/biz"
+ "mayfly-go/base/model"
+ "mayfly-go/server/devops/domain/entity"
+ "mayfly-go/server/devops/domain/repository"
+ "mayfly-go/server/devops/infrastructure/persistence"
+ "sync"
+
+ "github.com/go-redis/redis"
+)
+
+type Redis interface {
+ // 分页获取机器脚本信息列表
+ GetPageList(condition *entity.Redis, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
+
+ // 根据id获取
+ GetById(id uint64, cols ...string) *entity.Redis
+
+ // 根据条件获取
+ GetRedisBy(condition *entity.Redis, cols ...string) error
+
+ Save(entity *entity.Redis)
+
+ // 删除数据库信息
+ Delete(id uint64)
+
+ // 获取数据库连接实例
+ GetRedisInstance(id uint64) *RedisInstance
+}
+
+type redisAppImpl struct {
+ redisRepo repository.Redis
+}
+
+var RedisApp Redis = &redisAppImpl{
+ redisRepo: persistence.RedisDao,
+}
+
+// 分页获取机器脚本信息列表
+func (r *redisAppImpl) GetPageList(condition *entity.Redis, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
+ return r.redisRepo.GetRedisList(condition, pageParam, toEntity, orderBy...)
+}
+
+// 根据id获取
+func (r *redisAppImpl) GetById(id uint64, cols ...string) *entity.Redis {
+ return r.redisRepo.GetById(id, cols...)
+}
+
+// 根据条件获取
+func (r *redisAppImpl) GetRedisBy(condition *entity.Redis, cols ...string) error {
+ return r.redisRepo.GetRedis(condition, cols...)
+}
+
+func (r *redisAppImpl) Save(re *entity.Redis) {
+ TestRedisConnection(re)
+
+ // 查找是否存在该库
+ oldRedis := &entity.Redis{Host: re.Host, Db: re.Db}
+ err := r.GetRedisBy(oldRedis)
+
+ if re.Id == 0 {
+ biz.IsTrue(err != nil, "该库已存在")
+ r.redisRepo.Insert(re)
+ } else {
+ // 如果存在该库,则校验修改的库是否为该库
+ if err == nil {
+ biz.IsTrue(re.Id == re.Id, "该库已存在")
+ }
+ // 先关闭数据库连接
+ CloseRedis(re.Id)
+ r.redisRepo.Update(re)
+ }
+}
+
+// 删除Redis信息
+func (r *redisAppImpl) Delete(id uint64) {
+ CloseRedis(id)
+ r.redisRepo.Delete(id)
+}
+
+// 获取数据库连接实例
+func (r *redisAppImpl) GetRedisInstance(id uint64) *RedisInstance {
+ // Id不为0,则为需要缓存
+ needCache := id != 0
+ if needCache {
+ load, ok := redisCache.Load(id)
+ if ok {
+ return load.(*RedisInstance)
+ }
+ }
+ // 缓存不存在,则回调获取redis信息
+ re := r.GetById(id)
+ biz.NotNil(re, "redis信息不存在")
+ rcli := redis.NewClient(&redis.Options{
+ Addr: re.Host,
+ Password: re.Password, // no password set
+ DB: re.Db, // use default DB
+ })
+ // 测试连接
+ _, e := rcli.Ping().Result()
+ biz.ErrIsNilAppendErr(e, "redis连接失败: %s")
+
+ ri := &RedisInstance{Id: id, Cli: rcli}
+ if needCache {
+ redisCache.LoadOrStore(re.Id, ri)
+ }
+ return ri
+}
+
+//------------------------------------------------------------------------------
+
+var redisCache sync.Map
+
+// redis实例
+type RedisInstance struct {
+ Id uint64
+ Cli *redis.Client
+}
+
+// 关闭redis连接
+func CloseRedis(id uint64) {
+ if load, ok := redisCache.Load(id); ok {
+ load.(*RedisInstance).Cli.Close()
+ redisCache.Delete(id)
+ }
+}
+
+func TestRedisConnection(re *entity.Redis) {
+ rcli := redis.NewClient(&redis.Options{
+ Addr: re.Host,
+ Password: re.Password, // no password set
+ DB: re.Db, // use default DB
+ })
+ defer rcli.Close()
+ // 测试连接
+ _, e := rcli.Ping().Result()
+ biz.ErrIsNilAppendErr(e, "Redis连接失败: %s")
+}
+
+func (r *RedisInstance) Scan(cursor uint64, match string, count int64) ([]string, uint64) {
+ keys, newcursor, err := r.Cli.Scan(cursor, match, count).Result()
+ biz.ErrIsNilAppendErr(err, "scan失败: %s")
+ return keys, newcursor
+}
diff --git a/server/devops/domain/entity/db.go b/server/devops/domain/entity/db.go
index e1a13175..2d7cd65f 100644
--- a/server/devops/domain/entity/db.go
+++ b/server/devops/domain/entity/db.go
@@ -7,12 +7,16 @@ import (
type Db struct {
model.Model
- Name string `orm:"column(name)" json:"name"`
- Type string `orm:"column(type)" json:"type"` // 类型,mysql oracle等
- Host string `orm:"column(host)" json:"host"`
- Port int `orm:"column(port)" json:"port"`
- Network string `orm:"column(network)" json:"network"`
- Username string `orm:"column(username)" json:"username"`
- Password string `orm:"column(password)" json:"-"`
- Database string `orm:"column(database)" json:"database"`
+ Name string `orm:"column(name)" json:"name"`
+ Type string `orm:"column(type)" json:"type"` // 类型,mysql oracle等
+ Host string `orm:"column(host)" json:"host"`
+ Port int `orm:"column(port)" json:"port"`
+ Network string `orm:"column(network)" json:"network"`
+ Username string `orm:"column(username)" json:"username"`
+ Password string `orm:"column(password)" json:"-"`
+ Database string `orm:"column(database)" json:"database"`
+ ProjectId uint64
+ Project string
+ EnvId uint64
+ Env string
}
diff --git a/server/devops/domain/entity/machine_script.go b/server/devops/domain/entity/machine_script.go
index f832b2ab..6f2a3792 100644
--- a/server/devops/domain/entity/machine_script.go
+++ b/server/devops/domain/entity/machine_script.go
@@ -4,12 +4,10 @@ import "mayfly-go/base/model"
type MachineScript struct {
model.Model
- Name string `json:"name"`
- // 机器id
- MachineId uint64 `json:"machineId"`
- Type int `json:"type"`
- // 脚本内容
- Description string `json:"description"`
- // 脚本内容
- Script string `json:"script"`
+ Name string `json:"name"`
+ MachineId uint64 `json:"machineId"` // 机器id
+ Type int `json:"type"`
+ Description string `json:"description"` // 脚本描述
+ Params string `json:"params"` // 参数列表json
+ Script string `json:"script"` // 脚本内容
}
diff --git a/server/devops/domain/entity/project.go b/server/devops/domain/entity/project.go
new file mode 100644
index 00000000..f0cf7d8c
--- /dev/null
+++ b/server/devops/domain/entity/project.go
@@ -0,0 +1,10 @@
+package entity
+
+import "mayfly-go/base/model"
+
+// 项目
+type Project struct {
+ model.Model
+ Name string `json:"name"` // 项目名
+ Remark string `json:"remark"` // 备注说明
+}
diff --git a/server/devops/domain/entity/project_env.go b/server/devops/domain/entity/project_env.go
new file mode 100644
index 00000000..b7fe06ef
--- /dev/null
+++ b/server/devops/domain/entity/project_env.go
@@ -0,0 +1,11 @@
+package entity
+
+import "mayfly-go/base/model"
+
+// 项目环境
+type ProjectEnv struct {
+ model.Model
+ Name string `json:"name"` // 环境名
+ ProjectId uint64 `json:"projectId"` // 项目id
+ Remark string `json:"remark"` // 备注说明
+}
diff --git a/server/devops/domain/entity/project_member.go b/server/devops/domain/entity/project_member.go
new file mode 100644
index 00000000..4a207688
--- /dev/null
+++ b/server/devops/domain/entity/project_member.go
@@ -0,0 +1,11 @@
+package entity
+
+import "mayfly-go/base/model"
+
+// 项目成员,用于对项目下组件的访问控制
+type ProjectMember struct {
+ model.Model
+ AccountId uint64 `json:"accountId"` // 账号
+ Username string `json:"username"` // 账号用户名
+ ProjectId uint64 `json:"projectId"` // 项目id
+}
diff --git a/server/devops/domain/entity/redis.go b/server/devops/domain/entity/redis.go
new file mode 100644
index 00000000..1bd2236d
--- /dev/null
+++ b/server/devops/domain/entity/redis.go
@@ -0,0 +1,17 @@
+package entity
+
+import (
+ "mayfly-go/base/model"
+)
+
+type Redis struct {
+ model.Model
+
+ Host string `orm:"column(host)" json:"host"`
+ Password string `orm:"column(password)" json:"-"`
+ Db int `orm:"column(database)" json:"db"`
+ ProjectId uint64
+ Project string
+ EnvId uint64
+ Env string
+}
diff --git a/server/devops/domain/repository/db.go b/server/devops/domain/repository/db.go
index c3fedc4d..b5bd7be0 100644
--- a/server/devops/domain/repository/db.go
+++ b/server/devops/domain/repository/db.go
@@ -7,11 +7,17 @@ import (
type Db interface {
// 分页获取机器信息列表
- GetDbList(condition *entity.Db, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult
+ GetDbList(condition *entity.Db, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
// 根据条件获取账号信息
GetDb(condition *entity.Db, cols ...string) error
// 根据id获取
GetById(id uint64, cols ...string) *entity.Db
+
+ Insert(db *entity.Db)
+
+ Update(db *entity.Db)
+
+ Delete(id uint64)
}
diff --git a/server/devops/domain/repository/db_sql.go b/server/devops/domain/repository/db_sql.go
new file mode 100644
index 00000000..947a93d2
--- /dev/null
+++ b/server/devops/domain/repository/db_sql.go
@@ -0,0 +1,7 @@
+package repository
+
+import "mayfly-go/server/devops/domain/entity"
+
+type DbSql interface {
+ DeleteBy(condition *entity.DbSql)
+}
diff --git a/server/devops/domain/repository/machine.go b/server/devops/domain/repository/machine.go
index a4e497de..9ef796f5 100644
--- a/server/devops/domain/repository/machine.go
+++ b/server/devops/domain/repository/machine.go
@@ -7,7 +7,7 @@ import (
type Machine interface {
// 分页获取机器信息列表
- GetMachineList(condition *entity.Machine, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult
+ GetMachineList(condition *entity.Machine, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
// 根据条件获取账号信息
GetMachine(condition *entity.Machine, cols ...string) error
diff --git a/server/devops/domain/repository/machine_file.go b/server/devops/domain/repository/machine_file.go
index 31432bc5..0d7231c3 100644
--- a/server/devops/domain/repository/machine_file.go
+++ b/server/devops/domain/repository/machine_file.go
@@ -7,7 +7,7 @@ import (
type MachineFile interface {
// 分页获取机器脚本信息列表
- GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult
+ GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
// 根据条件获取
GetMachineFile(condition *entity.MachineFile, cols ...string) error
diff --git a/server/devops/domain/repository/machine_script.go b/server/devops/domain/repository/machine_script.go
index 5a7ba637..8f1db1f6 100644
--- a/server/devops/domain/repository/machine_script.go
+++ b/server/devops/domain/repository/machine_script.go
@@ -7,7 +7,7 @@ import (
type MachineScript interface {
// 分页获取机器脚本信息列表
- GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult
+ GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
// 根据条件获取
GetMachineScript(condition *entity.MachineScript, cols ...string) error
diff --git a/server/devops/domain/repository/project.go b/server/devops/domain/repository/project.go
new file mode 100644
index 00000000..61ed754f
--- /dev/null
+++ b/server/devops/domain/repository/project.go
@@ -0,0 +1,16 @@
+package repository
+
+import (
+ "mayfly-go/base/model"
+ "mayfly-go/server/devops/domain/entity"
+)
+
+type Project interface {
+ GetPageList(condition *entity.Project, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
+
+ GetByIdIn(ids []uint64, toEntity interface{}, orderBy ...string)
+
+ Save(p *entity.Project)
+
+ Update(project *entity.Project)
+}
diff --git a/server/devops/domain/repository/project_env.go b/server/devops/domain/repository/project_env.go
new file mode 100644
index 00000000..27552031
--- /dev/null
+++ b/server/devops/domain/repository/project_env.go
@@ -0,0 +1,10 @@
+package repository
+
+import "mayfly-go/server/devops/domain/entity"
+
+type ProjectEnv interface {
+ // 获取项目环境列表
+ ListEnv(condition *entity.ProjectEnv, toEntity interface{}, orderBy ...string)
+
+ Save(entity *entity.ProjectEnv)
+}
diff --git a/server/devops/domain/repository/project_member.go b/server/devops/domain/repository/project_member.go
new file mode 100644
index 00000000..39136951
--- /dev/null
+++ b/server/devops/domain/repository/project_member.go
@@ -0,0 +1,19 @@
+package repository
+
+import (
+ "mayfly-go/base/model"
+ "mayfly-go/server/devops/domain/entity"
+)
+
+type ProjectMemeber interface {
+
+ // 获取项目成员列表
+ ListMemeber(condition *entity.ProjectMember, toEntity interface{}, orderBy ...string)
+
+ Save(mp *entity.ProjectMember)
+
+ GetPageList(condition *entity.ProjectMember, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
+
+ // 根据成员id和项目id删除关联关系
+ DeleteByPidMid(projectId, accountId uint64)
+}
diff --git a/server/devops/domain/repository/redis.go b/server/devops/domain/repository/redis.go
new file mode 100644
index 00000000..cdbdbe68
--- /dev/null
+++ b/server/devops/domain/repository/redis.go
@@ -0,0 +1,22 @@
+package repository
+
+import (
+ "mayfly-go/base/model"
+ "mayfly-go/server/devops/domain/entity"
+)
+
+type Redis interface {
+ // 分页获取机器信息列表
+ GetRedisList(condition *entity.Redis, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult
+
+ // 根据id获取
+ GetById(id uint64, cols ...string) *entity.Redis
+
+ GetRedis(condition *entity.Redis, cols ...string) error
+
+ Insert(redis *entity.Redis)
+
+ Update(redis *entity.Redis)
+
+ Delete(id uint64)
+}
diff --git a/server/devops/infrastructure/db/db.go b/server/devops/infrastructure/db/db.go
deleted file mode 100644
index a5fdcffc..00000000
--- a/server/devops/infrastructure/db/db.go
+++ /dev/null
@@ -1,131 +0,0 @@
-package db
-
-import (
- "database/sql"
- "errors"
- "fmt"
- "mayfly-go/base/biz"
- "mayfly-go/server/devops/domain/entity"
- "strings"
- "sync"
- "time"
-
- _ "github.com/go-sql-driver/mysql"
-)
-
-var dbCache sync.Map
-
-// db实例
-type DbInstance struct {
- Id uint64
- Type string
- db *sql.DB
-}
-
-// 执行查询语句
-func (d *DbInstance) SelectData(sql string) ([]map[string]string, error) {
- sql = strings.Trim(sql, " ")
- if !strings.HasPrefix(sql, "SELECT") && !strings.HasPrefix(sql, "select") {
- return nil, errors.New("该sql非查询语句")
- }
- rows, err := d.db.Query(sql)
- if err != nil {
- return nil, err
- }
- // rows对象一定要close掉,如果出错,不关掉则会很迅速的达到设置最大连接数,
- // 后面的链接过来直接报错或拒绝,实际上也没有起效果
- defer func() {
- if rows != nil {
- rows.Close()
- }
- }()
- cols, _ := rows.Columns()
- // 这里表示一行填充数据
- scans := make([]interface{}, len(cols))
- // 这里表示一行所有列的值,用[]byte表示
- vals := make([][]byte, len(cols))
- // 这里scans引用vals,把数据填充到[]byte里
- for k := range vals {
- scans[k] = &vals[k]
- }
- result := make([]map[string]string, 0)
- for rows.Next() {
- // 不Scan也会导致等待,该链接实际处于未工作的状态,然后也会导致连接数迅速达到最大
- err := rows.Scan(scans...)
- if err != nil {
- return nil, err
- }
- // 每行数据
- rowData := make(map[string]string)
- // 把vals中的数据复制到row中
- for k, v := range vals {
- key := cols[k]
- // 如果是密码字段,则脱敏显示
- if key == "password" {
- v = []byte("******")
- }
- // 这里把[]byte数据转成string
- rowData[key] = string(v)
- }
- //放入结果集
- result = append(result, rowData)
- }
- return result, nil
-}
-
-// 执行 update, insert, delete,建表等sql
-//
-// 返回影响条数和错误
-func (d *DbInstance) Exec(sql string) (int64, error) {
- res, err := d.db.Exec(sql)
- if err != nil {
- return 0, err
- }
- return res.RowsAffected()
-}
-
-// 关闭连接,并从缓存中移除
-func (d *DbInstance) Close() {
- d.db.Close()
- dbCache.Delete(d.Id)
-}
-
-// 获取dataSourceName
-func getDsn(d *entity.Db) string {
- if d.Type == "mysql" {
- return fmt.Sprintf("%s:%s@%s(%s:%d)/%s", d.Username, d.Password, d.Network, d.Host, d.Port, d.Database)
- }
- return ""
-}
-
-func GetDbInstance(id uint64, getDbInfo func(uint64) *entity.Db) *DbInstance {
- // Id不为0,则为需要缓存
- needCache := id != 0
- if needCache {
- load, ok := dbCache.Load(id)
- if ok {
- return load.(*DbInstance)
- }
- }
- d := getDbInfo(id)
- biz.NotNil(d, "数据库信息不存在")
- DB, err := sql.Open(d.Type, getDsn(d))
- biz.ErrIsNil(err, fmt.Sprintf("Open %s failed, err:%v\n", d.Type, err))
- perr := DB.Ping()
- if perr != nil {
- panic(biz.NewBizErr(fmt.Sprintf("数据库连接失败: %s", perr.Error())))
- }
-
- // 最大连接周期,超过时间的连接就close
- DB.SetConnMaxLifetime(100 * time.Second)
- // 设置最大连接数
- DB.SetMaxOpenConns(5)
- // 设置闲置连接数
- DB.SetMaxIdleConns(1)
-
- dbi := &DbInstance{Id: id, Type: d.Type, db: DB}
- if needCache {
- dbCache.LoadOrStore(d.Id, dbi)
- }
- return dbi
-}
diff --git a/server/devops/infrastructure/db/metadata.go b/server/devops/infrastructure/db/metadata.go
deleted file mode 100644
index 5fd5d645..00000000
--- a/server/devops/infrastructure/db/metadata.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package db
-
-import "fmt"
-
-const (
- // mysql 表信息元数据
- MYSQL_TABLE_MA = `SELECT table_name tableName, engine, table_comment tableComment,
- create_time createTime from information_schema.tables
- WHERE table_schema = (SELECT database())`
-
- // mysql 列信息元数据
- MYSQL_COLOUMN_MA = `SELECT column_name columnName, column_type columnType,
- column_comment columnComment, column_key columnKey, extra from information_schema.columns
- WHERE table_name = '%s' AND table_schema = (SELECT database()) ORDER BY ordinal_position`
-)
-
-func (d *DbInstance) GetTableMetedatas() []map[string]string {
- var sql string
- if d.Type == "mysql" {
- sql = MYSQL_TABLE_MA
- }
- res, _ := d.SelectData(sql)
- return res
-}
-
-func (d *DbInstance) GetColumnMetadatas(tableName string) []map[string]string {
- var sql string
- if d.Type == "mysql" {
- sql = fmt.Sprintf(MYSQL_COLOUMN_MA, tableName)
- }
- res, _ := d.SelectData(sql)
- return res
-}
diff --git a/server/devops/infrastructure/machine/machine.go b/server/devops/infrastructure/machine/machine.go
index 23501fc8..327b997b 100644
--- a/server/devops/infrastructure/machine/machine.go
+++ b/server/devops/infrastructure/machine/machine.go
@@ -42,7 +42,10 @@ func GetCli(machineId uint64, getMachine func(uint64) *entity.Machine) (*Cli, er
}
return c, nil
})
- return cli.(*Cli), err
+ if cli != nil {
+ return cli.(*Cli), err
+ }
+ return nil, err
}
//根据机器信息创建客户端对象
@@ -204,3 +207,10 @@ func (c *Cli) RunTerminal(shell string, stdout, stderr io.Writer) error {
session.Run(shell)
return nil
}
+
+// 关闭指定机器的连接
+func Close(id uint64) {
+ if cli, ok := cliCache.Get(fmt.Sprint(id)); ok {
+ cli.(*Cli).Close()
+ }
+}
diff --git a/server/devops/infrastructure/persistence/db_repo.go b/server/devops/infrastructure/persistence/db_repo.go
index fe785eab..2f63f9fe 100644
--- a/server/devops/infrastructure/persistence/db_repo.go
+++ b/server/devops/infrastructure/persistence/db_repo.go
@@ -1,6 +1,7 @@
package persistence
import (
+ "mayfly-go/base/biz"
"mayfly-go/base/model"
"mayfly-go/server/devops/domain/entity"
"mayfly-go/server/devops/domain/repository"
@@ -11,7 +12,7 @@ type dbRepo struct{}
var DbDao repository.Db = &dbRepo{}
// 分页获取数据库信息列表
-func (d *dbRepo) GetDbList(condition *entity.Db, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult {
+func (d *dbRepo) GetDbList(condition *entity.Db, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return model.GetPage(pageParam, condition, toEntity, orderBy...)
}
@@ -29,3 +30,15 @@ func (d *dbRepo) GetById(id uint64, cols ...string) *entity.Db {
}
return db
}
+
+func (d *dbRepo) Insert(db *entity.Db) {
+ biz.ErrIsNil(model.Insert(db), "新增数据库信息失败")
+}
+
+func (d *dbRepo) Update(db *entity.Db) {
+ biz.ErrIsNil(model.UpdateById(db), "更新数据库信息失败")
+}
+
+func (d *dbRepo) Delete(id uint64) {
+ model.DeleteById(new(entity.Db), id)
+}
diff --git a/server/devops/infrastructure/persistence/db_sql_repo.go b/server/devops/infrastructure/persistence/db_sql_repo.go
new file mode 100644
index 00000000..37bc8c48
--- /dev/null
+++ b/server/devops/infrastructure/persistence/db_sql_repo.go
@@ -0,0 +1,17 @@
+package persistence
+
+import (
+ "mayfly-go/base/biz"
+ "mayfly-go/base/model"
+ "mayfly-go/server/devops/domain/entity"
+ "mayfly-go/server/devops/domain/repository"
+)
+
+type dbSqlRepo struct{}
+
+var DbSqlDao repository.DbSql = &dbSqlRepo{}
+
+// 分页获取数据库信息列表
+func (d *dbSqlRepo) DeleteBy(condition *entity.DbSql) {
+ biz.ErrIsNil(model.DeleteByCondition(condition), "删除sql失败")
+}
diff --git a/server/devops/infrastructure/persistence/machine_file_repo.go b/server/devops/infrastructure/persistence/machine_file_repo.go
index 4d88641a..6a47dcf8 100644
--- a/server/devops/infrastructure/persistence/machine_file_repo.go
+++ b/server/devops/infrastructure/persistence/machine_file_repo.go
@@ -12,7 +12,7 @@ type machineFileRepo struct{}
var MachineFileDao repository.MachineFile = &machineFileRepo{}
// 分页获取机器文件信息列表
-func (m *machineFileRepo) GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult {
+func (m *machineFileRepo) GetPageList(condition *entity.MachineFile, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return model.GetPage(pageParam, condition, toEntity, orderBy...)
}
diff --git a/server/devops/infrastructure/persistence/machine_repo.go b/server/devops/infrastructure/persistence/machine_repo.go
index 519eebe7..39912d40 100644
--- a/server/devops/infrastructure/persistence/machine_repo.go
+++ b/server/devops/infrastructure/persistence/machine_repo.go
@@ -11,7 +11,7 @@ type machineRepo struct{}
var MachineDao repository.Machine = &machineRepo{}
// 分页获取机器信息列表
-func (m *machineRepo) GetMachineList(condition *entity.Machine, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult {
+func (m *machineRepo) GetMachineList(condition *entity.Machine, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return model.GetPage(pageParam, condition, toEntity, orderBy...)
}
diff --git a/server/devops/infrastructure/persistence/machine_script_repo.go b/server/devops/infrastructure/persistence/machine_script_repo.go
index d65eae39..65cd733c 100644
--- a/server/devops/infrastructure/persistence/machine_script_repo.go
+++ b/server/devops/infrastructure/persistence/machine_script_repo.go
@@ -12,7 +12,7 @@ type machineScriptRepo struct{}
var MachineScriptDao repository.MachineScript = &machineScriptRepo{}
// 分页获取机器信息列表
-func (m *machineScriptRepo) GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) model.PageResult {
+func (m *machineScriptRepo) GetPageList(condition *entity.MachineScript, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
return model.GetPage(pageParam, condition, toEntity, orderBy...)
}
diff --git a/server/devops/infrastructure/persistence/project_env_repo.go b/server/devops/infrastructure/persistence/project_env_repo.go
new file mode 100644
index 00000000..dacd70b7
--- /dev/null
+++ b/server/devops/infrastructure/persistence/project_env_repo.go
@@ -0,0 +1,20 @@
+package persistence
+
+import (
+ "mayfly-go/base/biz"
+ "mayfly-go/base/model"
+ "mayfly-go/server/devops/domain/entity"
+ "mayfly-go/server/devops/domain/repository"
+)
+
+type projectEnvRepo struct{}
+
+var ProjectEnvRepo repository.ProjectEnv = &projectEnvRepo{}
+
+func (p *projectEnvRepo) ListEnv(condition *entity.ProjectEnv, toEntity interface{}, orderBy ...string) {
+ model.ListByOrder(condition, toEntity, orderBy...)
+}
+
+func (p *projectEnvRepo) Save(entity *entity.ProjectEnv) {
+ biz.ErrIsNilAppendErr(model.Insert(entity), "保存环境失败:%s")
+}
diff --git a/server/devops/infrastructure/persistence/project_member_repo.go b/server/devops/infrastructure/persistence/project_member_repo.go
new file mode 100644
index 00000000..970f6c85
--- /dev/null
+++ b/server/devops/infrastructure/persistence/project_member_repo.go
@@ -0,0 +1,28 @@
+package persistence
+
+import (
+ "mayfly-go/base/biz"
+ "mayfly-go/base/model"
+ "mayfly-go/server/devops/domain/entity"
+ "mayfly-go/server/devops/domain/repository"
+)
+
+type projectMemeberRepo struct{}
+
+var ProjectMemberRepo repository.ProjectMemeber = &projectMemeberRepo{}
+
+func (p *projectMemeberRepo) ListMemeber(condition *entity.ProjectMember, toEntity interface{}, orderBy ...string) {
+ model.ListByOrder(condition, toEntity, orderBy...)
+}
+
+func (p *projectMemeberRepo) Save(pm *entity.ProjectMember) {
+ biz.ErrIsNilAppendErr(model.Insert(pm), "保存项目成员失败:%s")
+}
+
+func (p *projectMemeberRepo) GetPageList(condition *entity.ProjectMember, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
+ return model.GetPage(pageParam, condition, toEntity, orderBy...)
+}
+
+func (p *projectMemeberRepo) DeleteByPidMid(projectId, accountId uint64) {
+ model.DeleteByCondition(&entity.ProjectMember{ProjectId: projectId, AccountId: accountId})
+}
diff --git a/server/devops/infrastructure/persistence/project_repo.go b/server/devops/infrastructure/persistence/project_repo.go
new file mode 100644
index 00000000..172b67a7
--- /dev/null
+++ b/server/devops/infrastructure/persistence/project_repo.go
@@ -0,0 +1,28 @@
+package persistence
+
+import (
+ "mayfly-go/base/biz"
+ "mayfly-go/base/model"
+ "mayfly-go/server/devops/domain/entity"
+ "mayfly-go/server/devops/domain/repository"
+)
+
+type projectRepo struct{}
+
+var ProjectRepo repository.Project = &projectRepo{}
+
+func (p *projectRepo) GetPageList(condition *entity.Project, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
+ return model.GetPage(pageParam, condition, toEntity, orderBy...)
+}
+
+func (p *projectRepo) GetByIdIn(ids []uint64, toEntity interface{}, orderBy ...string) {
+ model.GetByIdIn(new(entity.Project), toEntity, ids, orderBy...)
+}
+
+func (p *projectRepo) Save(project *entity.Project) {
+ biz.ErrIsNil(model.Insert(project), "保存项目失败")
+}
+
+func (p *projectRepo) Update(project *entity.Project) {
+ biz.ErrIsNil(model.UpdateById(project), "更新项目信息")
+}
diff --git a/server/devops/infrastructure/persistence/redis_repo.go b/server/devops/infrastructure/persistence/redis_repo.go
new file mode 100644
index 00000000..47f28630
--- /dev/null
+++ b/server/devops/infrastructure/persistence/redis_repo.go
@@ -0,0 +1,42 @@
+package persistence
+
+import (
+ "mayfly-go/base/biz"
+ "mayfly-go/base/model"
+ "mayfly-go/server/devops/domain/entity"
+ "mayfly-go/server/devops/domain/repository"
+)
+
+type redisRepo struct{}
+
+var RedisDao repository.Redis = &redisRepo{}
+
+// 分页获取机器信息列表
+func (r *redisRepo) GetRedisList(condition *entity.Redis, pageParam *model.PageParam, toEntity interface{}, orderBy ...string) *model.PageResult {
+ return model.GetPage(pageParam, condition, toEntity, orderBy...)
+}
+
+// 根据id获取
+func (r *redisRepo) GetById(id uint64, cols ...string) *entity.Redis {
+ rd := new(entity.Redis)
+ if err := model.GetById(rd, id, cols...); err != nil {
+ return nil
+ }
+ return rd
+}
+
+func (r *redisRepo) GetRedis(condition *entity.Redis, cols ...string) error {
+ return model.GetBy(condition, cols...)
+}
+
+func (r *redisRepo) Insert(redis *entity.Redis) {
+ biz.ErrIsNilAppendErr(model.Insert(redis), "新增失败: %s")
+}
+
+func (r *redisRepo) Update(redis *entity.Redis) {
+ biz.ErrIsNilAppendErr(model.UpdateById(redis), "更新失败: %s")
+}
+
+func (r *redisRepo) Delete(id uint64) {
+ biz.ErrIsNilAppendErr(model.DeleteById(new(entity.Redis), id), "删除失败: %s")
+}
diff --git a/server/devops/routers/db.go b/server/devops/routers/db.go
index 2f6ac453..4d3971ea 100644
--- a/server/devops/routers/db.go
+++ b/server/devops/routers/db.go
@@ -11,16 +11,31 @@ import (
func InitDbRouter(router *gin.RouterGroup) {
db := router.Group("dbs")
{
- d := &apis.Db{DbApp: application.Db}
+ d := &apis.Db{DbApp: application.DbApp}
// 获取所有数据库列表
db.GET("", func(c *gin.Context) {
rc := ctx.NewReqCtxWithGin(c)
rc.Handle(d.Dbs)
})
- // db.GET(":dbId/select", controllers.SelectData)
- db.GET(":dbId/select", func(g *gin.Context) {
- rc := ctx.NewReqCtxWithGin(g).WithLog(ctx.NewLogInfo("执行数据库查询语句"))
- rc.Handle(d.SelectData)
+
+ saveDb := ctx.NewLogInfo("保存数据库信息")
+ db.POST("", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).
+ WithLog(saveDb).
+ Handle(d.Save)
+ })
+
+ deleteDb := ctx.NewLogInfo("删除数据库信息")
+ db.DELETE(":id", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).
+ WithLog(deleteDb).
+ Handle(d.DeleteDb)
+ })
+
+ // db.GET(":dbId/exec-sql", controllers.SelectData)
+ db.GET(":dbId/exec-sql", func(g *gin.Context) {
+ rc := ctx.NewReqCtxWithGin(g).WithLog(ctx.NewLogInfo("执行Sql语句"))
+ rc.Handle(d.ExecSql)
})
db.GET(":dbId/t-metadata", func(c *gin.Context) {
@@ -35,7 +50,7 @@ func InitDbRouter(router *gin.RouterGroup) {
})
db.POST(":dbId/sql", func(c *gin.Context) {
- rc := ctx.NewReqCtxWithGin(c).WithLog(ctx.NewLogInfo("保存sql内容"))
+ rc := ctx.NewReqCtxWithGin(c)
rc.Handle(d.SaveSql)
})
diff --git a/server/devops/routers/machine.go b/server/devops/routers/machine.go
index c722d1f7..53f0f230 100644
--- a/server/devops/routers/machine.go
+++ b/server/devops/routers/machine.go
@@ -9,15 +9,25 @@ import (
)
func InitMachineRouter(router *gin.RouterGroup) {
- m := &apis.Machine{MachineApp: application.Machine}
+ m := &apis.Machine{MachineApp: application.MachineApp}
db := router.Group("machines")
{
db.GET("", func(c *gin.Context) {
ctx.NewReqCtxWithGin(c).Handle(m.Machines)
})
+ saveMachine := ctx.NewLogInfo("保存机器信息")
db.POST("", func(c *gin.Context) {
- ctx.NewReqCtxWithGin(c).Handle(m.SaveMachine)
+ ctx.NewReqCtxWithGin(c).
+ WithLog(saveMachine).
+ Handle(m.SaveMachine)
+ })
+
+ delMachine := ctx.NewLogInfo("删除机器")
+ db.DELETE("/delete/:id", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).
+ WithLog(delMachine).
+ Handle(m.DeleteMachine)
})
db.GET(":machineId/top", func(c *gin.Context) {
diff --git a/server/devops/routers/machine_file.go b/server/devops/routers/machine_file.go
index 75cf823e..87ed011a 100644
--- a/server/devops/routers/machine_file.go
+++ b/server/devops/routers/machine_file.go
@@ -12,8 +12,8 @@ func InitMachineFileRouter(router *gin.RouterGroup) {
machineFile := router.Group("machines")
{
mf := &apis.MachineFile{
- MachineFileApp: application.MachineFile,
- MachineApp: application.Machine}
+ MachineFileApp: application.MachineFileApp,
+ MachineApp: application.MachineApp}
// 获取指定机器文件列表
machineFile.GET(":machineId/files", func(c *gin.Context) {
diff --git a/server/devops/routers/machine_script.go b/server/devops/routers/machine_script.go
index 797de73e..41eaa1b7 100644
--- a/server/devops/routers/machine_script.go
+++ b/server/devops/routers/machine_script.go
@@ -12,12 +12,12 @@ func InitMachineScriptRouter(router *gin.RouterGroup) {
machines := router.Group("machines")
{
ms := &apis.MachineScript{
- MachineScriptApp: application.MachineScript,
- MachineApp: application.Machine}
+ MachineScriptApp: application.MachineScriptApp,
+ MachineApp: application.MachineApp}
// 获取指定机器脚本列表
machines.GET(":machineId/scripts", func(c *gin.Context) {
- ctx.NewReqCtxWithGin(c).WithNeedToken(false).Handle(ms.MachineScripts)
+ ctx.NewReqCtxWithGin(c).Handle(ms.MachineScripts)
})
saveMachienScriptLog := ctx.NewLogInfo("保存脚本")
diff --git a/server/devops/routers/project.go b/server/devops/routers/project.go
new file mode 100644
index 00000000..bc85ba1a
--- /dev/null
+++ b/server/devops/routers/project.go
@@ -0,0 +1,74 @@
+package routers
+
+import (
+ "mayfly-go/base/ctx"
+ "mayfly-go/server/devops/apis"
+ "mayfly-go/server/devops/application"
+ sys_applicaiton "mayfly-go/server/sys/application"
+
+ "github.com/gin-gonic/gin"
+)
+
+func InitProjectRouter(router *gin.RouterGroup) {
+ m := &apis.Project{
+ ProjectApp: application.ProjectApp,
+ AccountApp: sys_applicaiton.AccountApp}
+
+ project := router.Group("/projects")
+ {
+ router.GET("/accounts/projects", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).Handle(m.GetProjectsByLoginAccount)
+ })
+
+ // 获取项目列表
+ project.GET("", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).Handle(m.GetProjects)
+ })
+
+ saveProjectLog := ctx.NewLogInfo("保存项目信息")
+ savePP := ctx.NewPermission("project:save")
+ // 保存项目下的环境信息
+ project.POST("", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).WithLog(saveProjectLog).
+ WithRequiredPermission(savePP).
+ Handle(m.SaveProject)
+ })
+
+ // 获取项目下的环境信息列表
+ project.GET("/:projectId/envs", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).Handle(m.GetProjectEnvs)
+ })
+
+ saveProjectEnvLog := ctx.NewLogInfo("新增项目环境信息")
+ savePeP := ctx.NewPermission("project:env:save")
+ // 保存项目下的环境信息
+ project.POST("/:projectId/envs", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).WithLog(saveProjectEnvLog).
+ WithRequiredPermission(savePeP).
+ Handle(m.SaveProjectEnvs)
+ })
+
+ // 获取项目下的成员信息列表
+ project.GET("/:projectId/members", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).Handle(m.GetProjectMembers)
+ })
+
+ // 保存项目成员
+ saveProjectMemLog := ctx.NewLogInfo("新增项目成员")
+ savePmP := ctx.NewPermission("project:member:add")
+ project.POST("/:projectId/members", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).WithLog(saveProjectMemLog).
+ WithRequiredPermission(savePmP).
+ Handle(m.SaveProjectMember)
+ })
+
+ // 删除项目成员
+ delProjectMemLog := ctx.NewLogInfo("删除项目成员")
+ savePmdP := ctx.NewPermission("project:member:del")
+ project.DELETE("/:projectId/members/:accountId", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).WithLog(delProjectMemLog).
+ WithRequiredPermission(savePmdP).
+ Handle(m.DelProjectMember)
+ })
+ }
+}
diff --git a/server/devops/routers/redis.go b/server/devops/routers/redis.go
new file mode 100644
index 00000000..d9afc0c6
--- /dev/null
+++ b/server/devops/routers/redis.go
@@ -0,0 +1,79 @@
+package routers
+
+import (
+ "mayfly-go/base/ctx"
+ "mayfly-go/server/devops/apis"
+ "mayfly-go/server/devops/application"
+
+ "github.com/gin-gonic/gin"
+)
+
+func InitRedisRouter(router *gin.RouterGroup) {
+ redis := router.Group("redis")
+ {
+ rs := &apis.Redis{
+ RedisApp: application.RedisApp,
+ }
+
+ // 获取redis list
+ redis.GET("", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).Handle(rs.RedisList)
+ })
+
+ save := ctx.NewLogInfo("保存redis信息")
+ redis.POST("", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).WithLog(save).Handle(rs.Save)
+ })
+
+ delRedis := ctx.NewLogInfo("删除redis信息")
+ redis.DELETE(":id", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).WithLog(delRedis).Handle(rs.DeleteRedis)
+ })
+
+ redis.GET(":id/info", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).Handle(rs.RedisInfo)
+ })
+
+ // 获取指定redis keys
+ redis.GET(":id/scan/:cursor/:count", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).Handle(rs.Scan)
+ })
+
+ // 删除key
+ deleteKeyL := ctx.NewLogInfo("redis删除key")
+ // deleteKey := ctx.NewPermission("project:save")
+ redis.DELETE(":id/key", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).WithLog(deleteKeyL).Handle(rs.DeleteKey)
+ })
+
+ // 获取string类型值
+ redis.GET(":id/string-value", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).Handle(rs.GetStringValue)
+ })
+
+ // 设置string类型值
+ redis.POST(":id/string-value", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).Handle(rs.SetStringValue)
+ })
+
+ // 获取hash类型值
+ redis.GET(":id/hash-value", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).Handle(rs.GetHashValue)
+ })
+
+ // 获取set类型值
+ redis.GET(":id/set-value", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).Handle(rs.GetSetValue)
+ })
+
+ // 设置hash类型值
+ redis.POST(":id/hash-value", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).Handle(rs.SetStringValue)
+ })
+
+ // 设置hash类型值
+ redis.POST("test", func(c *gin.Context) {
+ ctx.NewReqCtxWithGin(c).WithNeedToken(false).Handle(rs.Test)
+ })
+ }
+}
diff --git a/server/initialize/router.go b/server/initialize/router.go
index 9e3ebe46..23b60316 100644
--- a/server/initialize/router.go
+++ b/server/initialize/router.go
@@ -1,21 +1,29 @@
package initialize
import (
- "mayfly-go/base/global"
+ "fmt"
+ "mayfly-go/base/config"
"mayfly-go/base/middleware"
devops_routers "mayfly-go/server/devops/routers"
sys_routers "mayfly-go/server/sys/routers"
+ "net/http"
"github.com/gin-gonic/gin"
)
func InitRouter() *gin.Engine {
// server配置
- serverConfig := global.Config.Server
+ serverConfig := config.Conf.Server
gin.SetMode(serverConfig.Model)
var router = gin.New()
router.MaxMultipartMemory = 8 << 20
+
+ // 没有路由即 404返回
+ router.NoRoute(func(g *gin.Context) {
+ g.JSON(http.StatusNotFound, gin.H{"code": 404, "msg": fmt.Sprintf("not found '%s:%s'", g.Request.Method, g.Request.URL.Path)})
+ })
+
// 设置静态资源
if staticConfs := serverConfig.Static; staticConfs != nil {
for _, scs := range *staticConfs {
@@ -37,11 +45,15 @@ func InitRouter() *gin.Engine {
// 设置路由组
api := router.Group("/api")
{
+ sys_routers.InitCaptchaRouter(api)
+
sys_routers.InitAccountRouter(api) // 注册account路由
sys_routers.InitResourceRouter(api)
sys_routers.InitRoleRouter(api)
+ devops_routers.InitProjectRouter(api)
devops_routers.InitDbRouter(api)
+ devops_routers.InitRedisRouter(api)
devops_routers.InitMachineRouter(api)
devops_routers.InitMachineScriptRouter(api)
devops_routers.InitMachineFileRouter(api)
diff --git a/server/mayfly-go b/server/mayfly-go
deleted file mode 100755
index 27922fd1..00000000
Binary files a/server/mayfly-go and /dev/null differ
diff --git a/server/mayfly-go.sql b/server/mayfly-go.sql
index 997dda45..c212f1b8 100644
--- a/server/mayfly-go.sql
+++ b/server/mayfly-go.sql
@@ -5,69 +5,18 @@
Source Server Type : MySQL
Source Server Version : 80018
Source Host : localhost:3306
- Source Schema : mayfly-go
+ Source Schema : mayfly-job
Target Server Type : MySQL
Target Server Version : 80018
File Encoding : 65001
- Date: 08/06/2021 14:52:42
+ Date: 28/07/2021 17:30:54
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
--- ----------------------------
--- Table structure for t_account
--- ----------------------------
-DROP TABLE IF EXISTS `t_account`;
-CREATE TABLE `t_account` (
- `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
- `username` varchar(12) NOT NULL,
- `password` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
- `status` tinyint(4) DEFAULT NULL,
- `create_time` datetime NOT NULL,
- `creator_id` bigint(255) NOT NULL,
- `creator` varchar(12) NOT NULL,
- `update_time` datetime NOT NULL,
- `modifier_id` bigint(255) NOT NULL,
- `modifier` varchar(12) NOT NULL,
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-
--- ----------------------------
--- Records of t_account
--- ----------------------------
-BEGIN;
-INSERT INTO `t_account` VALUES (1, 'admin', '7b116d117002fad3f6dde6c718b885b9', 1, '2020-01-01 19:00:00', 1, 'admin', '2020-01-01 19:00:00', 1, 'admin');
-INSERT INTO `t_account` VALUES (2, 'admin2', 'e10adc3949ba59abbe56e057f20f883e', -1, '2020-09-09 12:00:09', 2, 'haha', '2020-09-09 12:00:09', 2, 'haha');
-COMMIT;
-
--- ----------------------------
--- Table structure for t_account_role
--- ----------------------------
-DROP TABLE IF EXISTS `t_account_role`;
-CREATE TABLE `t_account_role` (
- `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Id',
- `account_id` bigint(20) NOT NULL COMMENT '账号id',
- `role_id` bigint(20) NOT NULL COMMENT '角色id',
- `creator` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
- `creator_id` bigint(20) unsigned DEFAULT NULL,
- `create_time` datetime NOT NULL,
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8;
-
--- ----------------------------
--- Records of t_account_role
--- ----------------------------
-BEGIN;
-INSERT INTO `t_account_role` VALUES (23, 3, 6, 'admin', 1, '2021-05-28 16:19:21');
-INSERT INTO `t_account_role` VALUES (24, 2, 1, 'admin', 1, '2021-05-28 16:21:38');
-INSERT INTO `t_account_role` VALUES (25, 1, 1, 'admin', 1, '2021-05-28 16:21:45');
-INSERT INTO `t_account_role` VALUES (26, 4, 6, 'admin', 1, '2021-05-28 17:04:48');
-INSERT INTO `t_account_role` VALUES (29, 1, 6, 'admin', 1, '2021-06-02 16:07:44');
-COMMIT;
-
-- ----------------------------
-- Table structure for t_db
-- ----------------------------
@@ -82,6 +31,10 @@ CREATE TABLE `t_db` (
`type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '数据库类型(mysql...)',
`database` varchar(32) DEFAULT NULL,
`network` varchar(8) DEFAULT NULL,
+ `project_id` bigint(20) DEFAULT NULL,
+ `project` varchar(64) DEFAULT NULL,
+ `env_id` bigint(20) DEFAULT NULL COMMENT '环境id',
+ `env` varchar(255) DEFAULT NULL COMMENT '环境描述',
`remark` varchar(125) DEFAULT NULL COMMENT '备注,描述等',
`create_time` datetime DEFAULT NULL,
`creator_id` bigint(20) DEFAULT NULL,
@@ -90,16 +43,11 @@ CREATE TABLE `t_db` (
`modifier_id` bigint(20) DEFAULT NULL,
`modifier` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='数据库信息表';
+) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='数据库信息表';
-- ----------------------------
-- Records of t_db
-- ----------------------------
-BEGIN;
-INSERT INTO `t_db` VALUES (1, 'mayfly-go', 'localhost', 3306, 'root', '******', 'mysql', 'mayfly-job', 'tcp', NULL, '2020-12-14 15:04:43', NULL, NULL, '2020-12-14 15:04:48', NULL, NULL);
-INSERT INTO `t_db` VALUES (2, 'maylfy', '114.67.67.10', 3306, 'root', '******', 'mysql', 'mayfly', 'tcp', NULL, NULL, NULL, NULL, NULL, NULL, NULL);
-INSERT INTO `t_db` VALUES (3, 'mayfly-oracle', 'localhost', 1521, 'TEST', '******', 'godror', 'xe', 'tcp', NULL, NULL, NULL, NULL, NULL, NULL, NULL);
-COMMIT;
-- ----------------------------
-- Table structure for t_db_sql
@@ -117,14 +65,67 @@ CREATE TABLE `t_db_sql` (
`modifier_id` bigint(20) DEFAULT NULL,
`modifier` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='数据库sql信息';
-- ----------------------------
-- Records of t_db_sql
-- ----------------------------
BEGIN;
-INSERT INTO `t_db_sql` VALUES (2, 1, 'SELECT\n *\nFROM\n t_account\n \nSELECT\n *\nFROM\n t_db\n \nSELECT\n *\nFROM\n t_db_sql', 1, 1, 'admin', '2020-12-18 15:27:53', '2021-04-25 11:09:04', 1, 'admin');
+INSERT INTO `t_db_sql` VALUES (2, 1, 'SELECT\n *\nFROM\n t_sys_resource sr \n \nSELECT COUNT(*) FROM t_sys_account\n \nSELECT\n *\nFROM\n t_db td\n \nSELECT\n *\nFROM\n t_db_sql\n \nUPDATE t_sys_account t SET t.creator = \"admin\"', 1, 1, 'admin', '2020-12-18 15:27:53', '2021-07-22 10:10:25', 1, 'admin');
INSERT INTO `t_db_sql` VALUES (3, 2, 'SELECT\n *\nFROM\n t_account\n \nSELECT\n *\nFROM\n t_resource\n \nSELECT\n *\nFROM\n t_sys_operation_log\nORDER BY\n id DESC\nLIMIT\n 20', 1, 1, 'admin', '2020-12-18 17:13:36', '2021-04-21 10:16:21', 1, 'admin');
+INSERT INTO `t_db_sql` VALUES (4, 4, 'SELECT\n *\nFROM\n t_ci_corp_auth t WHERE t.fk_corp = \'1212\'\n \nSELECT * FROM t_ci_corp\n \nSELECT\n *\nFROM\n t_activity_user_record r\n LEFT JOIN t_activity a ON r.sequence_no = a.update_time\nWHERE\n r.channel_source = 1\n AND a.sequence_no = 12', 1, 1, 'admin', '2021-06-28 15:25:03', '2021-07-05 17:07:08', 1, 'admin');
+INSERT INTO `t_db_sql` VALUES (5, 5, 'SELECT * FROM t_sys_code\n\nSELECT * FROM t_sys_dict_data', 1, 1, 'admin', '2021-06-28 17:27:56', '2021-06-28 17:27:56', 1, 'admin');
+INSERT INTO `t_db_sql` VALUES (7, 10, 'SELECT * FROM t_account', 1, 1, 'admin', '2021-07-08 17:07:47', '2021-07-08 17:08:03', 1, 'admin');
+COMMIT;
+
+-- ----------------------------
+-- Table structure for t_gw_service
+-- ----------------------------
+DROP TABLE IF EXISTS `t_gw_service`;
+CREATE TABLE `t_gw_service` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `service_name` varchar(36) NOT NULL COMMENT '服务名',
+ `urls` varchar(125) DEFAULT NULL COMMENT 'urls'',''分割',
+ `create_time` datetime DEFAULT NULL,
+ `creator` varchar(36) DEFAULT NULL,
+ `creator_id` bigint(20) DEFAULT NULL,
+ `update_time` datetime DEFAULT NULL,
+ `modifier_id` bigint(20) DEFAULT NULL,
+ `modifier` varchar(36) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='网关服务';
+
+-- ----------------------------
+-- Records of t_gw_service
+-- ----------------------------
+BEGIN;
+COMMIT;
+
+-- ----------------------------
+-- Table structure for t_gw_service_api
+-- ----------------------------
+DROP TABLE IF EXISTS `t_gw_service_api`;
+CREATE TABLE `t_gw_service_api` (
+ `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `service_id` int(11) NOT NULL COMMENT '服务id',
+ `service_name` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+ `code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
+ `uri` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'uri地址',
+ `json_schemal` text COMMENT 'json schemal校验参数',
+ `enable_mock` tinyint(2) DEFAULT NULL COMMENT '是否启用mock',
+ `create_time` datetime DEFAULT NULL,
+ `creator_id` bigint(20) DEFAULT NULL,
+ `creator` varchar(36) DEFAULT NULL,
+ `update_time` datetime DEFAULT NULL,
+ `modifier_id` bigint(20) DEFAULT NULL,
+ `modifier` varchar(36) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='网关服务api';
+
+-- ----------------------------
+-- Records of t_gw_service_api
+-- ----------------------------
+BEGIN;
COMMIT;
-- ----------------------------
@@ -146,16 +147,11 @@ CREATE TABLE `t_machine` (
`modifier` varchar(12) DEFAULT NULL,
`modifier_id` bigint(32) DEFAULT NULL,
PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='机器信息';
-- ----------------------------
-- Records of t_machine
-- ----------------------------
-BEGIN;
-INSERT INTO `t_machine` VALUES (1, 'eatlife', '148.70.36.197', 22, 'root', '******', 1, '2020-01-01 10:10:10', NULL, NULL, '2020-01-01 10:10:10', NULL, NULL);
-INSERT INTO `t_machine` VALUES (2, 'JD云', '114.67.67.10', 22, 'root', '******', 1, '2020-08-18 10:00:00', NULL, NULL, '2020-08-18 10:00:00', NULL, NULL);
-INSERT INTO `t_machine` VALUES (4, '腾讯云', '118.24.26.101', 22, 'root', '******', NULL, '2021-05-10 15:57:49', 'admin', 1, '2021-05-10 15:57:49', 'admin', 1);
-COMMIT;
-- ----------------------------
-- Table structure for t_machine_file
@@ -174,25 +170,11 @@ CREATE TABLE `t_machine_file` (
`create_time` datetime NOT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8 COMMENT='机器文件';
+) ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8 COMMENT='机器文件';
-- ----------------------------
-- Records of t_machine_file
-- ----------------------------
-BEGIN;
-INSERT INTO `t_machine_file` VALUES (1, 1, 'redis配置文件', '/etc/my.cnf', '2', 1, 'admin', NULL, NULL, '2019-08-21 11:30:33', NULL);
-INSERT INTO `t_machine_file` VALUES (10, 2, 'java-dockerfile', '/usr/local/java/Dockerfile', '2', 1, 'admin', NULL, NULL, '2019-11-06 15:16:12', NULL);
-INSERT INTO `t_machine_file` VALUES (11, 1, 'usr', '/usr', '1', 1, 'admin', NULL, NULL, '2019-11-06 15:16:12', NULL);
-INSERT INTO `t_machine_file` VALUES (12, 1, 'opt', '/opt', '1', 1, 'admin', NULL, NULL, '2019-11-06 15:16:12', NULL);
-INSERT INTO `t_machine_file` VALUES (13, 3, '根目录', '/', '1', 1, 'admin', NULL, NULL, '2019-11-18 05:19:28', NULL);
-INSERT INTO `t_machine_file` VALUES (14, 1, 'usr', '/usr/local', '1', 1, 'admin', NULL, NULL, '2019-11-19 05:52:28', NULL);
-INSERT INTO `t_machine_file` VALUES (15, 2, 'usr', '/usr/', '1', 1, 'admin', NULL, NULL, '2019-11-19 08:35:19', NULL);
-INSERT INTO `t_machine_file` VALUES (16, 3, '软件安装目录', '/usr/local', '1', 1, 'admin', NULL, NULL, '2019-11-19 08:40:55', NULL);
-INSERT INTO `t_machine_file` VALUES (23, 4, '根目录', '/', '1', 1, 'admin', NULL, NULL, '2019-12-11 07:54:04', NULL);
-INSERT INTO `t_machine_file` VALUES (24, 4, '项目目录', '/usr/local/java', '1', 1, 'admin', NULL, NULL, '2020-03-07 07:12:20', NULL);
-INSERT INTO `t_machine_file` VALUES (25, 8, '软件安装位置', '/usr/local', '1', 1, 'admin', NULL, NULL, '2020-08-28 09:41:56', NULL);
-INSERT INTO `t_machine_file` VALUES (28, 2, 'java目录', '/usr/local/java', '1', 1, 'admin', 1, 'admin', '2021-05-08 17:32:25', '2021-05-08 17:32:25');
-COMMIT;
-- ----------------------------
-- Table structure for t_machine_monitor
@@ -221,6 +203,7 @@ CREATE TABLE `t_machine_script` (
`name` varchar(255) NOT NULL COMMENT '脚本名',
`machine_id` bigint(64) NOT NULL COMMENT '机器id[0:公共]',
`script` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '脚本内容',
+ `params` varchar(512) DEFAULT NULL COMMENT '脚本入参',
`description` varchar(255) DEFAULT NULL COMMENT '脚本描述',
`type` tinyint(8) DEFAULT NULL COMMENT '脚本类型[1: 有结果;2:无结果;3:实时交互]',
`creator_id` bigint(20) DEFAULT NULL,
@@ -230,36 +213,175 @@ CREATE TABLE `t_machine_script` (
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='机器脚本';
-- ----------------------------
-- Records of t_machine_script
-- ----------------------------
BEGIN;
-INSERT INTO `t_machine_script` VALUES (1, 'sys_info', 9999999, '# 获取系统cpu信息\nfunction get_cpu_info() {\n Physical_CPUs=$(grep \"physical id\" /proc/cpuinfo | sort | uniq | wc -l)\n Virt_CPUs=$(grep \"processor\" /proc/cpuinfo | wc -l)\n CPU_Kernels=$(grep \"cores\" /proc/cpuinfo | uniq | awk -F \': \' \'{print $2}\')\n CPU_Type=$(grep \"model name\" /proc/cpuinfo | awk -F \': \' \'{print $2}\' | sort | uniq)\n CPU_Arch=$(uname -m)\n echo -e \'\\n-------------------------- CPU信息 --------------------------\'\n cat <