mirror of
https://gitee.com/goploy/goploy.git
synced 2024-11-30 03:07:59 +08:00
Merge pull request #51 from itzgyw/master
Add monitor script, project tag.
This commit is contained in:
commit
261da44560
@ -12,6 +12,8 @@ import (
|
|||||||
"github.com/zhenorzz/goploy/internal/server/response"
|
"github.com/zhenorzz/goploy/internal/server/response"
|
||||||
"github.com/zhenorzz/goploy/model"
|
"github.com/zhenorzz/goploy/model"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Monitor API
|
type Monitor API
|
||||||
@ -41,36 +43,80 @@ func (Monitor) GetList(gp *server.Goploy) server.Response {
|
|||||||
|
|
||||||
func (Monitor) Check(gp *server.Goploy) server.Response {
|
func (Monitor) Check(gp *server.Goploy) server.Response {
|
||||||
type ReqData struct {
|
type ReqData struct {
|
||||||
Type int `json:"type" validate:"oneof=1 2 3 4 5"`
|
Type int `json:"type" validate:"oneof=1 2 3 4 5"`
|
||||||
Target string `json:"target" validate:"required"`
|
Target string `json:"target" validate:"required"`
|
||||||
|
SuccessServerID int64 `json:"successServerId"`
|
||||||
|
SuccessScript string `json:"successScript"`
|
||||||
|
FailServerID int64 `json:"failServerId"`
|
||||||
|
FailScript string `json:"failScript"`
|
||||||
}
|
}
|
||||||
var reqData ReqData
|
var reqData ReqData
|
||||||
if err := decodeJson(gp.Body, &reqData); err != nil {
|
if err := decodeJson(gp.Body, &reqData); err != nil {
|
||||||
return response.JSON{Code: response.Error, Message: err.Error()}
|
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||||
}
|
}
|
||||||
|
|
||||||
ms, err := monitor.NewMonitorFromTarget(reqData.Type, reqData.Target)
|
ms, err := monitor.NewMonitorFromTarget(reqData.Type, reqData.Target,
|
||||||
|
monitor.NewScript(reqData.SuccessServerID, reqData.SuccessScript),
|
||||||
|
monitor.NewScript(reqData.FailServerID, reqData.FailScript),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return response.JSON{Code: response.Error, Message: err.Error()}
|
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sb := strings.Builder{}
|
||||||
if err := ms.Check(); err != nil {
|
if err := ms.Check(); err != nil {
|
||||||
return response.JSON{Code: response.Error, Message: err.Error()}
|
sb.WriteString("MonitorErr : ")
|
||||||
|
sb.WriteString(err.Error())
|
||||||
|
var serverId int64
|
||||||
|
if e, ok := err.(monitor.ScriptError); ok {
|
||||||
|
serverId = e.ServerId
|
||||||
|
}
|
||||||
|
|
||||||
|
err := ms.RunFailScript(serverId)
|
||||||
|
if err != nil {
|
||||||
|
sb.WriteString("\nFailScriptErr : ")
|
||||||
|
sb.WriteString(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
sb.WriteString("Monitor : Success \n")
|
||||||
|
for _, item := range ms.Items {
|
||||||
|
serverId, err := strconv.ParseInt(item, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
err = ms.RunSuccessScript(0)
|
||||||
|
} else {
|
||||||
|
err = ms.RunSuccessScript(serverId)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
sb.WriteString("SuccessScriptErr: \n")
|
||||||
|
sb.WriteString(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return response.JSON{Message: "Connected"}
|
if sb.Len() != 19 {
|
||||||
|
return response.JSON{Code: response.Error, Message: sb.String()}
|
||||||
|
} else {
|
||||||
|
return response.JSON{Message: "SUCCESS"}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Monitor) Add(gp *server.Goploy) server.Response {
|
func (Monitor) Add(gp *server.Goploy) server.Response {
|
||||||
type ReqData struct {
|
type ReqData struct {
|
||||||
Name string `json:"name" validate:"required"`
|
Name string `json:"name" validate:"required"`
|
||||||
Type int `json:"type" validate:"oneof=1 2 3 4 5"`
|
Type int `json:"type" validate:"oneof=1 2 3 4 5"`
|
||||||
Target string `json:"target" validate:"required"`
|
Target string `json:"target" validate:"required"`
|
||||||
Second int `json:"second" validate:"gt=0"`
|
Second int `json:"second" validate:"gt=0"`
|
||||||
Times uint16 `json:"times" validate:"gt=0"`
|
Times uint16 `json:"times" validate:"gt=0"`
|
||||||
SilentCycle int `json:"silentCycle" validate:"required"`
|
SilentCycle int `json:"silentCycle" validate:"required"`
|
||||||
NotifyType uint8 `json:"notifyType" validate:"gt=0"`
|
NotifyType uint8 `json:"notifyType" validate:"gt=0"`
|
||||||
NotifyTarget string `json:"notifyTarget" validate:"required"`
|
NotifyTarget string `json:"notifyTarget" validate:"required"`
|
||||||
Description string `json:"description" validate:"max=255"`
|
Description string `json:"description" validate:"max=255"`
|
||||||
|
FailScript string `json:"failScript" `
|
||||||
|
SuccessScript string `json:"successScript" `
|
||||||
|
SuccessServerID int64 `json:"successServerId" `
|
||||||
|
FailServerID int64 `json:"failServerId" `
|
||||||
}
|
}
|
||||||
var reqData ReqData
|
var reqData ReqData
|
||||||
if err := decodeJson(gp.Body, &reqData); err != nil {
|
if err := decodeJson(gp.Body, &reqData); err != nil {
|
||||||
@ -78,16 +124,20 @@ func (Monitor) Add(gp *server.Goploy) server.Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
id, err := model.Monitor{
|
id, err := model.Monitor{
|
||||||
NamespaceID: gp.Namespace.ID,
|
NamespaceID: gp.Namespace.ID,
|
||||||
Name: reqData.Name,
|
Name: reqData.Name,
|
||||||
Type: reqData.Type,
|
Type: reqData.Type,
|
||||||
Target: reqData.Target,
|
Target: reqData.Target,
|
||||||
Second: reqData.Second,
|
Second: reqData.Second,
|
||||||
Times: reqData.Times,
|
Times: reqData.Times,
|
||||||
SilentCycle: reqData.SilentCycle,
|
SilentCycle: reqData.SilentCycle,
|
||||||
NotifyType: reqData.NotifyType,
|
NotifyType: reqData.NotifyType,
|
||||||
NotifyTarget: reqData.NotifyTarget,
|
NotifyTarget: reqData.NotifyTarget,
|
||||||
Description: reqData.Description,
|
Description: reqData.Description,
|
||||||
|
FailScript: reqData.FailScript,
|
||||||
|
SuccessScript: reqData.SuccessScript,
|
||||||
|
SuccessServerID: reqData.SuccessServerID,
|
||||||
|
FailServerID: reqData.FailServerID,
|
||||||
}.AddRow()
|
}.AddRow()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -102,32 +152,40 @@ func (Monitor) Add(gp *server.Goploy) server.Response {
|
|||||||
|
|
||||||
func (Monitor) Edit(gp *server.Goploy) server.Response {
|
func (Monitor) Edit(gp *server.Goploy) server.Response {
|
||||||
type ReqData struct {
|
type ReqData struct {
|
||||||
ID int64 `json:"id" validate:"gt=0"`
|
ID int64 `json:"id" validate:"gt=0"`
|
||||||
Name string `json:"name" validate:"required"`
|
Name string `json:"name" validate:"required"`
|
||||||
Type int `json:"type" validate:"oneof=1 2 3 4 5"`
|
Type int `json:"type" validate:"oneof=1 2 3 4 5"`
|
||||||
Target string `json:"target" validate:"required"`
|
Target string `json:"target" validate:"required"`
|
||||||
Second int `json:"second" validate:"gt=0"`
|
Second int `json:"second" validate:"gt=0"`
|
||||||
Times uint16 `json:"times" validate:"gt=0"`
|
Times uint16 `json:"times" validate:"gt=0"`
|
||||||
SilentCycle int `json:"silentCycle" validate:"required"`
|
SilentCycle int `json:"silentCycle" validate:"required"`
|
||||||
NotifyType uint8 `json:"notifyType" validate:"gt=0"`
|
NotifyType uint8 `json:"notifyType" validate:"gt=0"`
|
||||||
NotifyTarget string `json:"notifyTarget" validate:"required"`
|
NotifyTarget string `json:"notifyTarget" validate:"required"`
|
||||||
Description string `json:"description" validate:"max=255"`
|
Description string `json:"description" validate:"max=255"`
|
||||||
|
FailScript string `json:"failScript" `
|
||||||
|
SuccessScript string `json:"successScript" `
|
||||||
|
SuccessServerID int64 `json:"successServerId" `
|
||||||
|
FailServerID int64 `json:"failServerId" `
|
||||||
}
|
}
|
||||||
var reqData ReqData
|
var reqData ReqData
|
||||||
if err := decodeJson(gp.Body, &reqData); err != nil {
|
if err := decodeJson(gp.Body, &reqData); err != nil {
|
||||||
return response.JSON{Code: response.Error, Message: err.Error()}
|
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||||
}
|
}
|
||||||
err := model.Monitor{
|
err := model.Monitor{
|
||||||
ID: reqData.ID,
|
ID: reqData.ID,
|
||||||
Name: reqData.Name,
|
Name: reqData.Name,
|
||||||
Type: reqData.Type,
|
Type: reqData.Type,
|
||||||
Target: reqData.Target,
|
Target: reqData.Target,
|
||||||
Second: reqData.Second,
|
Second: reqData.Second,
|
||||||
Times: reqData.Times,
|
Times: reqData.Times,
|
||||||
SilentCycle: reqData.SilentCycle,
|
SilentCycle: reqData.SilentCycle,
|
||||||
NotifyType: reqData.NotifyType,
|
NotifyType: reqData.NotifyType,
|
||||||
NotifyTarget: reqData.NotifyTarget,
|
NotifyTarget: reqData.NotifyTarget,
|
||||||
Description: reqData.Description,
|
Description: reqData.Description,
|
||||||
|
FailScript: reqData.FailScript,
|
||||||
|
SuccessScript: reqData.SuccessScript,
|
||||||
|
SuccessServerID: reqData.SuccessServerID,
|
||||||
|
FailServerID: reqData.FailServerID,
|
||||||
}.EditRow()
|
}.EditRow()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -28,6 +28,7 @@ type Project API
|
|||||||
func (p Project) Handler() []server.Route {
|
func (p Project) Handler() []server.Route {
|
||||||
return []server.Route{
|
return []server.Route{
|
||||||
server.NewRoute("/project/getList", http.MethodGet, p.GetList).Permissions(config.ShowProjectPage),
|
server.NewRoute("/project/getList", http.MethodGet, p.GetList).Permissions(config.ShowProjectPage),
|
||||||
|
server.NewRoute("/project/tagList", http.MethodGet, p.TagList),
|
||||||
server.NewRoute("/project/pingRepos", http.MethodGet, p.PingRepos),
|
server.NewRoute("/project/pingRepos", http.MethodGet, p.PingRepos),
|
||||||
server.NewRoute("/project/getRemoteBranchList", http.MethodGet, p.GetRemoteBranchList),
|
server.NewRoute("/project/getRemoteBranchList", http.MethodGet, p.GetRemoteBranchList),
|
||||||
server.NewRoute("/project/getBindServerList", http.MethodGet, p.GetBindServerList),
|
server.NewRoute("/project/getBindServerList", http.MethodGet, p.GetBindServerList),
|
||||||
@ -54,6 +55,23 @@ func (p Project) Handler() []server.Route {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (Project) TagList(gp *server.Goploy) server.Response {
|
||||||
|
var tagList []string
|
||||||
|
var err error
|
||||||
|
if _, ok := gp.Namespace.PermissionIDs[config.GetAllProjectList]; ok {
|
||||||
|
tagList, err = model.Project{NamespaceID: gp.Namespace.ID}.GetTagList()
|
||||||
|
} else {
|
||||||
|
tagList, err = model.Project{NamespaceID: gp.Namespace.ID, UserID: gp.UserInfo.ID}.GetTagList()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||||
|
}
|
||||||
|
return response.JSON{
|
||||||
|
Data: struct {
|
||||||
|
List []string `json:"list"`
|
||||||
|
}{List: tagList},
|
||||||
|
}
|
||||||
|
}
|
||||||
func (Project) GetList(gp *server.Goploy) server.Response {
|
func (Project) GetList(gp *server.Goploy) server.Response {
|
||||||
var projectList model.Projects
|
var projectList model.Projects
|
||||||
var err error
|
var err error
|
||||||
@ -297,6 +315,7 @@ func (Project) Add(gp *server.Goploy) server.Response {
|
|||||||
Name string `json:"name" validate:"required"`
|
Name string `json:"name" validate:"required"`
|
||||||
RepoType string `json:"repoType" validate:"required"`
|
RepoType string `json:"repoType" validate:"required"`
|
||||||
URL string `json:"url" validate:"required"`
|
URL string `json:"url" validate:"required"`
|
||||||
|
Tag string `json:"tag"`
|
||||||
Path string `json:"path" validate:"required"`
|
Path string `json:"path" validate:"required"`
|
||||||
Environment uint8 `json:"environment" validate:"required"`
|
Environment uint8 `json:"environment" validate:"required"`
|
||||||
Branch string `json:"branch" validate:"required"`
|
Branch string `json:"branch" validate:"required"`
|
||||||
@ -330,6 +349,7 @@ func (Project) Add(gp *server.Goploy) server.Response {
|
|||||||
Name: reqData.Name,
|
Name: reqData.Name,
|
||||||
RepoType: reqData.RepoType,
|
RepoType: reqData.RepoType,
|
||||||
URL: reqData.URL,
|
URL: reqData.URL,
|
||||||
|
Tag: reqData.Tag,
|
||||||
Path: reqData.Path,
|
Path: reqData.Path,
|
||||||
Environment: reqData.Environment,
|
Environment: reqData.Environment,
|
||||||
Branch: reqData.Branch,
|
Branch: reqData.Branch,
|
||||||
@ -383,6 +403,7 @@ func (Project) Edit(gp *server.Goploy) server.Response {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
RepoType string `json:"repoType"`
|
RepoType string `json:"repoType"`
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
|
Tag string `json:"tag"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
SymlinkPath string `json:"symlinkPath"`
|
SymlinkPath string `json:"symlinkPath"`
|
||||||
SymlinkBackupNumber uint8 `json:"symlinkBackupNumber"`
|
SymlinkBackupNumber uint8 `json:"symlinkBackupNumber"`
|
||||||
@ -421,6 +442,7 @@ func (Project) Edit(gp *server.Goploy) server.Response {
|
|||||||
Name: reqData.Name,
|
Name: reqData.Name,
|
||||||
RepoType: reqData.RepoType,
|
RepoType: reqData.RepoType,
|
||||||
URL: reqData.URL,
|
URL: reqData.URL,
|
||||||
|
Tag: reqData.Tag,
|
||||||
Path: reqData.Path,
|
Path: reqData.Path,
|
||||||
Environment: reqData.Environment,
|
Environment: reqData.Environment,
|
||||||
Branch: reqData.Branch,
|
Branch: reqData.Branch,
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/zhenorzz/goploy/internal/log"
|
"github.com/zhenorzz/goploy/internal/log"
|
||||||
"github.com/zhenorzz/goploy/internal/monitor"
|
"github.com/zhenorzz/goploy/internal/monitor"
|
||||||
"github.com/zhenorzz/goploy/model"
|
"github.com/zhenorzz/goploy/model"
|
||||||
|
"strconv"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -79,7 +80,10 @@ func monitorTask() {
|
|||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
if int(now-monitorCache.time) >= m.Second {
|
if int(now-monitorCache.time) >= m.Second {
|
||||||
monitorCache.time = now
|
monitorCache.time = now
|
||||||
ms, err := monitor.NewMonitorFromTarget(m.Type, m.Target)
|
ms, err := monitor.NewMonitorFromTarget(m.Type, m.Target,
|
||||||
|
monitor.NewScript(m.SuccessServerID, m.SuccessScript),
|
||||||
|
monitor.NewScript(m.FailServerID, m.FailScript),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = m.TurnOff(err.Error())
|
_ = m.TurnOff(err.Error())
|
||||||
log.Error("m " + m.Name + " encounter error, " + err.Error())
|
log.Error("m " + m.Name + " encounter error, " + err.Error())
|
||||||
@ -105,8 +109,29 @@ func monitorTask() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var serverId int64
|
||||||
|
if e, ok := err.(monitor.ScriptError); ok {
|
||||||
|
serverId = e.ServerId
|
||||||
|
}
|
||||||
|
err = ms.RunFailScript(serverId)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to run fail script ." + err.Error())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
for _, item := range ms.Items {
|
||||||
|
serverId, err := strconv.ParseInt(item, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
err = ms.RunSuccessScript(0)
|
||||||
|
} else {
|
||||||
|
err = ms.RunSuccessScript(serverId)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Failed to run successful script ." + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
monitorCache.errorTimes = 0
|
monitorCache.errorTimes = 0
|
||||||
|
|
||||||
}
|
}
|
||||||
monitorCaches[m.ID] = monitorCache
|
monitorCaches[m.ID] = monitorCache
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/zhenorzz/goploy/model"
|
"github.com/zhenorzz/goploy/model"
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@ -18,19 +19,51 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Monitor struct {
|
type ScriptError struct {
|
||||||
Type int
|
Message string
|
||||||
Items []string
|
ServerId int64
|
||||||
Timeout time.Duration
|
|
||||||
Process string
|
|
||||||
Script string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMonitorFromTarget(t int, target string) (Monitor, error) {
|
func (ce ScriptError) Error() string {
|
||||||
|
return ce.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ce ScriptError) Server() int64 {
|
||||||
|
return ce.ServerId
|
||||||
|
}
|
||||||
|
|
||||||
|
type Script struct {
|
||||||
|
ServerId int64
|
||||||
|
Script string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ce Script) IsValid() bool {
|
||||||
|
return ce.Script != ""
|
||||||
|
}
|
||||||
|
func NewScript(serverId int64, script string) Script {
|
||||||
|
return Script{
|
||||||
|
ServerId: serverId,
|
||||||
|
Script: script,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Monitor struct {
|
||||||
|
Type int
|
||||||
|
Items []string
|
||||||
|
Timeout time.Duration
|
||||||
|
Process string
|
||||||
|
Script string
|
||||||
|
FailScript Script
|
||||||
|
SuccessScript Script
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMonitorFromTarget(t int, target string, successScript Script, failScript Script) (Monitor, error) {
|
||||||
var m Monitor
|
var m Monitor
|
||||||
if err := json.Unmarshal([]byte(target), &m); err != nil {
|
if err := json.Unmarshal([]byte(target), &m); err != nil {
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
m.FailScript = failScript
|
||||||
|
m.SuccessScript = successScript
|
||||||
m.Type = t
|
m.Type = t
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
@ -109,17 +142,7 @@ func (m Monitor) CheckScript() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
server, err := (model.Server{ID: serverID}).GetData()
|
session, err := NewSession(serverID, m.Timeout*time.Second)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if server.State == model.Disable {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
client, err := server.ToSSHConfig().SetTimeout(m.Timeout * time.Second).Dial()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
session, err := client.NewSession()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -127,8 +150,58 @@ func (m Monitor) CheckScript() error {
|
|||||||
session.Stdout = &stdout
|
session.Stdout = &stdout
|
||||||
session.Stderr = &stderr
|
session.Stderr = &stderr
|
||||||
if err := session.Run(m.Script); err != nil {
|
if err := session.Run(m.Script); err != nil {
|
||||||
return errors.New(err.Error() + ", stdout: " + stdout.String() + ", stderr: " + stderr.String())
|
return ScriptError{Message: err.Error() + ", stdout: " + stdout.String() + ", stderr: " + stderr.String(), ServerId: serverID}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func (m Monitor) RunFailScript(serverId int64) error {
|
||||||
|
if m.FailScript.IsValid() {
|
||||||
|
sId := m.FailScript.ServerId
|
||||||
|
if sId == -1 {
|
||||||
|
if serverId == 0 {
|
||||||
|
return errors.New("the executor is not clear")
|
||||||
|
} else {
|
||||||
|
sId = serverId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
session, err := NewSession(sId, m.Timeout*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return session.Run(m.FailScript.Script)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (m Monitor) RunSuccessScript(serverId int64) error {
|
||||||
|
if m.SuccessScript.IsValid() {
|
||||||
|
sId := m.SuccessScript.ServerId
|
||||||
|
if sId == -1 {
|
||||||
|
if serverId == 0 {
|
||||||
|
return errors.New("the executor is not clear")
|
||||||
|
} else {
|
||||||
|
sId = serverId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
session, err := NewSession(sId, m.Timeout*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return session.Run(m.SuccessScript.Script)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSession(serverId int64, timeout time.Duration) (session *ssh.Session, err error) {
|
||||||
|
server, err := (model.Server{ID: serverId}).GetData()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if server.State == model.Disable {
|
||||||
|
return nil, errors.New("Server Disable [" + server.Name + "]")
|
||||||
|
}
|
||||||
|
client, err := server.ToSSHConfig().SetTimeout(timeout).Dial()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return client.NewSession()
|
||||||
|
}
|
||||||
|
@ -16,28 +16,32 @@ import (
|
|||||||
const monitorTable = "`monitor`"
|
const monitorTable = "`monitor`"
|
||||||
|
|
||||||
type Monitor struct {
|
type Monitor struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
NamespaceID int64 `json:"namespaceId"`
|
NamespaceID int64 `json:"namespaceId"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Type int `json:"type"`
|
Type int `json:"type"`
|
||||||
Target string `json:"target"`
|
Target string `json:"target"`
|
||||||
Second int `json:"second"`
|
Second int `json:"second"`
|
||||||
Times uint16 `json:"times"`
|
Times uint16 `json:"times"`
|
||||||
SilentCycle int `json:"silentCycle"`
|
SilentCycle int `json:"silentCycle"`
|
||||||
NotifyType uint8 `json:"notifyType"`
|
NotifyType uint8 `json:"notifyType"`
|
||||||
NotifyTarget string `json:"notifyTarget"`
|
NotifyTarget string `json:"notifyTarget"`
|
||||||
Description string `json:"description"`
|
SuccessServerID int64 `json:"successServerId"`
|
||||||
ErrorContent string `json:"errorContent"`
|
SuccessScript string `json:"successScript"`
|
||||||
State uint8 `json:"state"`
|
FailServerID int64 `json:"failServerId"`
|
||||||
InsertTime string `json:"insertTime"`
|
FailScript string `json:"failScript"`
|
||||||
UpdateTime string `json:"updateTime"`
|
Description string `json:"description"`
|
||||||
|
ErrorContent string `json:"errorContent"`
|
||||||
|
State uint8 `json:"state"`
|
||||||
|
InsertTime string `json:"insertTime"`
|
||||||
|
UpdateTime string `json:"updateTime"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Monitors []Monitor
|
type Monitors []Monitor
|
||||||
|
|
||||||
func (m Monitor) GetList() (Monitors, error) {
|
func (m Monitor) GetList() (Monitors, error) {
|
||||||
rows, err := sq.
|
rows, err := sq.
|
||||||
Select("id, name, type, target, second, times, silent_cycle, notify_type, notify_target, description, error_content, state, insert_time, update_time").
|
Select("id, name, type, target, second, times, silent_cycle, notify_type, notify_target, description, error_content, state, success_script, fail_script, success_server_id, fail_server_id, insert_time, update_time").
|
||||||
From(monitorTable).
|
From(monitorTable).
|
||||||
Where(sq.Eq{
|
Where(sq.Eq{
|
||||||
"namespace_id": m.NamespaceID,
|
"namespace_id": m.NamespaceID,
|
||||||
@ -65,6 +69,10 @@ func (m Monitor) GetList() (Monitors, error) {
|
|||||||
&monitor.Description,
|
&monitor.Description,
|
||||||
&monitor.ErrorContent,
|
&monitor.ErrorContent,
|
||||||
&monitor.State,
|
&monitor.State,
|
||||||
|
&monitor.SuccessScript,
|
||||||
|
&monitor.FailScript,
|
||||||
|
&monitor.SuccessServerID,
|
||||||
|
&monitor.FailServerID,
|
||||||
&monitor.InsertTime,
|
&monitor.InsertTime,
|
||||||
&monitor.UpdateTime); err != nil {
|
&monitor.UpdateTime); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -78,13 +86,13 @@ func (m Monitor) GetList() (Monitors, error) {
|
|||||||
func (m Monitor) GetData() (Monitor, error) {
|
func (m Monitor) GetData() (Monitor, error) {
|
||||||
var monitor Monitor
|
var monitor Monitor
|
||||||
err := sq.
|
err := sq.
|
||||||
Select("id, name, type, target, second, times, silent_cycle, notify_type, notify_target, state").
|
Select("id, name, type, target, second, times, silent_cycle, notify_type, notify_target, state", "success_script", "fail_script", "success_server_id", "fail_server_id").
|
||||||
From(monitorTable).
|
From(monitorTable).
|
||||||
Where(sq.Eq{"id": m.ID}).
|
Where(sq.Eq{"id": m.ID}).
|
||||||
OrderBy("id DESC").
|
OrderBy("id DESC").
|
||||||
RunWith(DB).
|
RunWith(DB).
|
||||||
QueryRow().
|
QueryRow().
|
||||||
Scan(&monitor.ID, &monitor.Name, &monitor.Type, &monitor.Target, &monitor.Second, &monitor.Times, &monitor.SilentCycle, &monitor.NotifyType, &monitor.NotifyTarget, &monitor.State)
|
Scan(&monitor.ID, &monitor.Name, &monitor.Type, &monitor.Target, &monitor.Second, &monitor.Times, &monitor.SilentCycle, &monitor.NotifyType, &monitor.NotifyTarget, &monitor.State, &monitor.SuccessScript, &monitor.FailScript, &monitor.SuccessServerID, &monitor.FailServerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return monitor, err
|
return monitor, err
|
||||||
}
|
}
|
||||||
@ -93,7 +101,7 @@ func (m Monitor) GetData() (Monitor, error) {
|
|||||||
|
|
||||||
func (m Monitor) GetAllByState() (Monitors, error) {
|
func (m Monitor) GetAllByState() (Monitors, error) {
|
||||||
rows, err := sq.
|
rows, err := sq.
|
||||||
Select("id, name, type, target, second, times, silent_cycle, notify_type, notify_target, description, update_time").
|
Select("id, name, type, target, second, times, silent_cycle, notify_type, notify_target, success_script, fail_script, success_server_id, fail_server_id, description, update_time").
|
||||||
From(monitorTable).
|
From(monitorTable).
|
||||||
Where(sq.Eq{
|
Where(sq.Eq{
|
||||||
"state": m.State,
|
"state": m.State,
|
||||||
@ -117,6 +125,10 @@ func (m Monitor) GetAllByState() (Monitors, error) {
|
|||||||
&monitor.SilentCycle,
|
&monitor.SilentCycle,
|
||||||
&monitor.NotifyType,
|
&monitor.NotifyType,
|
||||||
&monitor.NotifyTarget,
|
&monitor.NotifyTarget,
|
||||||
|
&monitor.SuccessScript,
|
||||||
|
&monitor.FailScript,
|
||||||
|
&monitor.SuccessServerID,
|
||||||
|
&monitor.FailServerID,
|
||||||
&monitor.Description,
|
&monitor.Description,
|
||||||
&monitor.UpdateTime,
|
&monitor.UpdateTime,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
@ -131,8 +143,8 @@ func (m Monitor) GetAllByState() (Monitors, error) {
|
|||||||
func (m Monitor) AddRow() (int64, error) {
|
func (m Monitor) AddRow() (int64, error) {
|
||||||
result, err := sq.
|
result, err := sq.
|
||||||
Insert(monitorTable).
|
Insert(monitorTable).
|
||||||
Columns("namespace_id", "name", "type", "target", "second", "times", "silent_cycle", "notify_type", "notify_target", "description", "error_content").
|
Columns("namespace_id", "name", "type", "target", "second", "times", "silent_cycle", "notify_type", "notify_target", "description", "error_content", "success_script", "fail_script", "success_server_id", "fail_server_id").
|
||||||
Values(m.NamespaceID, m.Name, m.Type, m.Target, m.Second, m.Times, m.SilentCycle, m.NotifyType, m.NotifyTarget, m.Description, "").
|
Values(m.NamespaceID, m.Name, m.Type, m.Target, m.Second, m.Times, m.SilentCycle, m.NotifyType, m.NotifyTarget, m.Description, "", m.SuccessScript, m.FailScript, m.SuccessServerID, m.FailServerID).
|
||||||
RunWith(DB).
|
RunWith(DB).
|
||||||
Exec()
|
Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -146,15 +158,19 @@ func (m Monitor) EditRow() error {
|
|||||||
_, err := sq.
|
_, err := sq.
|
||||||
Update(monitorTable).
|
Update(monitorTable).
|
||||||
SetMap(sq.Eq{
|
SetMap(sq.Eq{
|
||||||
"name": m.Name,
|
"name": m.Name,
|
||||||
"type": m.Type,
|
"type": m.Type,
|
||||||
"target": m.Target,
|
"target": m.Target,
|
||||||
"second": m.Second,
|
"second": m.Second,
|
||||||
"times": m.Times,
|
"times": m.Times,
|
||||||
"silent_cycle": m.SilentCycle,
|
"silent_cycle": m.SilentCycle,
|
||||||
"notify_type": m.NotifyType,
|
"notify_type": m.NotifyType,
|
||||||
"notify_target": m.NotifyTarget,
|
"notify_target": m.NotifyTarget,
|
||||||
"description": m.Description,
|
"description": m.Description,
|
||||||
|
"success_script": m.SuccessScript,
|
||||||
|
"fail_script": m.FailScript,
|
||||||
|
"success_server_id": m.SuccessServerID,
|
||||||
|
"fail_server_id": m.FailServerID,
|
||||||
}).
|
}).
|
||||||
Where(sq.Eq{"id": m.ID}).
|
Where(sq.Eq{"id": m.ID}).
|
||||||
RunWith(DB).
|
RunWith(DB).
|
||||||
|
@ -22,6 +22,7 @@ type Project struct {
|
|||||||
RepoType string `json:"repoType"`
|
RepoType string `json:"repoType"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
|
Tag string `json:"tag"`
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
Environment uint8 `json:"environment"`
|
Environment uint8 `json:"environment"`
|
||||||
Branch string `json:"branch"`
|
Branch string `json:"branch"`
|
||||||
@ -88,6 +89,7 @@ func (p Project) AddRow() (int64, error) {
|
|||||||
"name",
|
"name",
|
||||||
"repo_type",
|
"repo_type",
|
||||||
"url",
|
"url",
|
||||||
|
"tag",
|
||||||
"path",
|
"path",
|
||||||
"environment",
|
"environment",
|
||||||
"branch",
|
"branch",
|
||||||
@ -110,6 +112,7 @@ func (p Project) AddRow() (int64, error) {
|
|||||||
p.Name,
|
p.Name,
|
||||||
p.RepoType,
|
p.RepoType,
|
||||||
p.URL,
|
p.URL,
|
||||||
|
p.Tag,
|
||||||
p.Path,
|
p.Path,
|
||||||
p.Environment,
|
p.Environment,
|
||||||
p.Branch,
|
p.Branch,
|
||||||
@ -136,6 +139,45 @@ func (p Project) AddRow() (int64, error) {
|
|||||||
return id, err
|
return id, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p Project) GetTagList() (tags []string, err error) {
|
||||||
|
builder := sq.Select("tag").
|
||||||
|
From(projectTable).
|
||||||
|
Where(sq.Eq{
|
||||||
|
"namespace_id": p.NamespaceID,
|
||||||
|
"state": Enable,
|
||||||
|
}).
|
||||||
|
Distinct()
|
||||||
|
|
||||||
|
if p.UserID > 0 {
|
||||||
|
builder = builder.
|
||||||
|
Join(projectUserTable + " ON project_user.project_id = project.id").
|
||||||
|
Where(sq.Eq{"user_id": p.UserID})
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := builder.
|
||||||
|
RunWith(DB).
|
||||||
|
Query()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tagMap := map[string]bool{}
|
||||||
|
for rows.Next() {
|
||||||
|
var tag string
|
||||||
|
rows.Scan(&tag)
|
||||||
|
if tag != "" {
|
||||||
|
for _, item := range strings.Split(tag, ",") {
|
||||||
|
tagMap[item] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tags = make([]string, len(tagMap))
|
||||||
|
var i int
|
||||||
|
for k := range tagMap {
|
||||||
|
tags[i] = k
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return tags, nil
|
||||||
|
}
|
||||||
func (p Project) EditRow() error {
|
func (p Project) EditRow() error {
|
||||||
_, err := sq.
|
_, err := sq.
|
||||||
Update(projectTable).
|
Update(projectTable).
|
||||||
@ -143,6 +185,7 @@ func (p Project) EditRow() error {
|
|||||||
"name": p.Name,
|
"name": p.Name,
|
||||||
"repo_type": p.RepoType,
|
"repo_type": p.RepoType,
|
||||||
"url": p.URL,
|
"url": p.URL,
|
||||||
|
"tag": p.Tag,
|
||||||
"path": p.Path,
|
"path": p.Path,
|
||||||
"environment": p.Environment,
|
"environment": p.Environment,
|
||||||
"branch": p.Branch,
|
"branch": p.Branch,
|
||||||
@ -255,6 +298,7 @@ func (p Project) GetList() (Projects, error) {
|
|||||||
name,
|
name,
|
||||||
repo_type,
|
repo_type,
|
||||||
url,
|
url,
|
||||||
|
tag,
|
||||||
path,
|
path,
|
||||||
environment,
|
environment,
|
||||||
branch,
|
branch,
|
||||||
@ -304,6 +348,7 @@ func (p Project) GetList() (Projects, error) {
|
|||||||
&project.Name,
|
&project.Name,
|
||||||
&project.RepoType,
|
&project.RepoType,
|
||||||
&project.URL,
|
&project.URL,
|
||||||
|
&project.Tag,
|
||||||
&project.Path,
|
&project.Path,
|
||||||
&project.Environment,
|
&project.Environment,
|
||||||
&project.Branch,
|
&project.Branch,
|
||||||
@ -340,6 +385,7 @@ func (p Project) GetDeployList() (Projects, error) {
|
|||||||
project.repo_type,
|
project.repo_type,
|
||||||
project.transfer_type,
|
project.transfer_type,
|
||||||
project.url,
|
project.url,
|
||||||
|
project.tag,
|
||||||
project.publisher_id,
|
project.publisher_id,
|
||||||
project.publisher_name,
|
project.publisher_name,
|
||||||
IFNULL(publish_trace.ext, '{}'),
|
IFNULL(publish_trace.ext, '{}'),
|
||||||
@ -382,6 +428,7 @@ func (p Project) GetDeployList() (Projects, error) {
|
|||||||
&project.RepoType,
|
&project.RepoType,
|
||||||
&project.TransferType,
|
&project.TransferType,
|
||||||
&project.URL,
|
&project.URL,
|
||||||
|
&project.Tag,
|
||||||
&project.PublisherID,
|
&project.PublisherID,
|
||||||
&project.PublisherName,
|
&project.PublisherName,
|
||||||
&project.PublishExt,
|
&project.PublishExt,
|
||||||
@ -411,6 +458,7 @@ func (p Project) GetData() (Project, error) {
|
|||||||
name,
|
name,
|
||||||
repo_type,
|
repo_type,
|
||||||
url,
|
url,
|
||||||
|
tag,
|
||||||
path,
|
path,
|
||||||
environment,
|
environment,
|
||||||
branch,
|
branch,
|
||||||
@ -443,6 +491,7 @@ func (p Project) GetData() (Project, error) {
|
|||||||
&project.Name,
|
&project.Name,
|
||||||
&project.RepoType,
|
&project.RepoType,
|
||||||
&project.URL,
|
&project.URL,
|
||||||
|
&project.Tag,
|
||||||
&project.Path,
|
&project.Path,
|
||||||
&project.Environment,
|
&project.Environment,
|
||||||
&project.Branch,
|
&project.Branch,
|
||||||
|
5
model/sql/2023-05-06.sql
Normal file
5
model/sql/2023-05-06.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
alter table monitor add success_script longtext;
|
||||||
|
alter table monitor add fail_script longtext ;
|
||||||
|
alter table monitor add success_server_id int(10) default -1;
|
||||||
|
alter table monitor add fail_server_id int(10) default -1 ;
|
||||||
|
alter table project add tag varchar(255) default '';
|
2
web/components.d.ts
vendored
2
web/components.d.ts
vendored
@ -25,7 +25,6 @@ declare module '@vue/runtime-core' {
|
|||||||
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
||||||
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
||||||
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
|
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
|
||||||
ElEmpty: typeof import('element-plus/es')['ElEmpty']
|
|
||||||
ElForm: typeof import('element-plus/es')['ElForm']
|
ElForm: typeof import('element-plus/es')['ElForm']
|
||||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||||
ElIcon: typeof import('element-plus/es')['ElIcon']
|
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||||
@ -50,7 +49,6 @@ declare module '@vue/runtime-core' {
|
|||||||
ElTabPane: typeof import('element-plus/es')['ElTabPane']
|
ElTabPane: typeof import('element-plus/es')['ElTabPane']
|
||||||
ElTabs: typeof import('element-plus/es')['ElTabs']
|
ElTabs: typeof import('element-plus/es')['ElTabs']
|
||||||
ElTag: typeof import('element-plus/es')['ElTag']
|
ElTag: typeof import('element-plus/es')['ElTag']
|
||||||
ElTimeSelect: typeof import('element-plus/es')['ElTimeSelect']
|
|
||||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
||||||
ElUpload: typeof import('element-plus/es')['ElUpload']
|
ElUpload: typeof import('element-plus/es')['ElUpload']
|
||||||
Hamburger: typeof import('./src/components/Hamburger/index.vue')['default']
|
Hamburger: typeof import('./src/components/Hamburger/index.vue')['default']
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
"cronstrue": "^1.113.0",
|
"cronstrue": "^1.113.0",
|
||||||
"diff": "^5.0.0",
|
"diff": "^5.0.0",
|
||||||
"echarts": "^5.2.1",
|
"echarts": "^5.2.1",
|
||||||
"element-plus": "^2.2.28",
|
"element-plus": "^2.3.4",
|
||||||
"js-cookie": "^2.2.1",
|
"js-cookie": "^2.2.1",
|
||||||
"listenercount": "^1.0.1",
|
"listenercount": "^1.0.1",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
|
@ -11,6 +11,7 @@ export interface ProjectData {
|
|||||||
path: string
|
path: string
|
||||||
environment: number
|
environment: number
|
||||||
branch: string
|
branch: string
|
||||||
|
tag: string
|
||||||
symlinkPath: string
|
symlinkPath: string
|
||||||
symlinkBackupNumber: number
|
symlinkBackupNumber: number
|
||||||
review: number
|
review: number
|
||||||
@ -107,6 +108,14 @@ export class ProjectList extends Request {
|
|||||||
list: ProjectData[]
|
list: ProjectData[]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export class TagList extends Request {
|
||||||
|
readonly url = '/project/tagList'
|
||||||
|
readonly method = 'get'
|
||||||
|
|
||||||
|
public declare datagram: {
|
||||||
|
list: string[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class ProjectPingRepos extends Request {
|
export class ProjectPingRepos extends Request {
|
||||||
readonly url = '/project/pingRepos'
|
readonly url = '/project/pingRepos'
|
||||||
@ -151,6 +160,7 @@ export class ProjectAdd extends Request {
|
|||||||
name: string
|
name: string
|
||||||
repoType: string
|
repoType: string
|
||||||
url: string
|
url: string
|
||||||
|
tag: string
|
||||||
path: string
|
path: string
|
||||||
environment: number
|
environment: number
|
||||||
branch: string
|
branch: string
|
||||||
@ -183,6 +193,7 @@ export class ProjectEdit extends Request {
|
|||||||
name: string
|
name: string
|
||||||
repoType: string
|
repoType: string
|
||||||
url: string
|
url: string
|
||||||
|
tag: string
|
||||||
path: string
|
path: string
|
||||||
symlinkPath: string
|
symlinkPath: string
|
||||||
review: number
|
review: number
|
||||||
|
21
web/src/const/const.ts
Normal file
21
web/src/const/const.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
const scriptLang = {
|
||||||
|
Option: [
|
||||||
|
{ label: 'sh', value: 'sh', lang: 'sh' },
|
||||||
|
{ label: 'zsh', value: 'zsh', lang: 'sh' },
|
||||||
|
{ label: 'bash', value: 'bash', lang: 'sh' },
|
||||||
|
{ label: 'python', value: 'python', lang: 'python' },
|
||||||
|
{ label: 'php', value: 'php', lang: 'php' },
|
||||||
|
{ label: 'bat', value: 'cmd', lang: 'batchfile' },
|
||||||
|
],
|
||||||
|
getScriptLang: function (scriptMode = '') {
|
||||||
|
if (scriptMode !== '') {
|
||||||
|
const scriptInfo = scriptLang.Option.find(
|
||||||
|
(elem) => elem.value === scriptMode
|
||||||
|
)
|
||||||
|
return scriptInfo ? scriptInfo['lang'] : ''
|
||||||
|
} else {
|
||||||
|
return 'sh'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
export { scriptLang }
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"default": "Default",
|
"default": "Default",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
|
"tag": "Tag",
|
||||||
"script": "Script",
|
"script": "Script",
|
||||||
"owner": "Owner",
|
"owner": "Owner",
|
||||||
"user": "User",
|
"user": "User",
|
||||||
@ -48,7 +49,7 @@
|
|||||||
"reject": "Reject",
|
"reject": "Reject",
|
||||||
"manage": "Manage",
|
"manage": "Manage",
|
||||||
"interval": "Interval",
|
"interval": "Interval",
|
||||||
"sort" : "Sort",
|
"sort": "Sort",
|
||||||
"asc": "ASC",
|
"asc": "ASC",
|
||||||
"desc": "DESC",
|
"desc": "DESC",
|
||||||
"size": "Size",
|
"size": "Size",
|
||||||
@ -115,11 +116,29 @@
|
|||||||
"state": "State",
|
"state": "State",
|
||||||
"current": "Current",
|
"current": "Current",
|
||||||
"unlimited": "Unlimited",
|
"unlimited": "Unlimited",
|
||||||
"stateOption": ["Disable", "Enable"],
|
"stateOption": [
|
||||||
"switchOption": ["Close", "Open"],
|
"Disable",
|
||||||
"boolOption": ["No", "Yes"],
|
"Enable"
|
||||||
"runOption": ["Not run", "Run"],
|
],
|
||||||
"envOption": ["Unknown", "Production", "Pre-release", "Test", "Development"],
|
"switchOption": [
|
||||||
|
"Close",
|
||||||
|
"Open"
|
||||||
|
],
|
||||||
|
"boolOption": [
|
||||||
|
"No",
|
||||||
|
"Yes"
|
||||||
|
],
|
||||||
|
"runOption": [
|
||||||
|
"Not run",
|
||||||
|
"Run"
|
||||||
|
],
|
||||||
|
"envOption": [
|
||||||
|
"Unknown",
|
||||||
|
"Production",
|
||||||
|
"Pre-release",
|
||||||
|
"Test",
|
||||||
|
"Development"
|
||||||
|
],
|
||||||
"webhookOption": {
|
"webhookOption": {
|
||||||
"0": "Nothing",
|
"0": "Nothing",
|
||||||
"1": "WeCom",
|
"1": "WeCom",
|
||||||
@ -289,24 +308,36 @@
|
|||||||
"saveTemplate": "Save template"
|
"saveTemplate": "Save template"
|
||||||
},
|
},
|
||||||
"monitorPage": {
|
"monitorPage": {
|
||||||
"typeOption": ["Unknown", "Site check", "Port check", "Ping check", "Process check", "Custom script check"],
|
"defaultServer": "Follow Host",
|
||||||
|
"scriptMode": "Script mode",
|
||||||
|
"typeOption": [
|
||||||
|
"Unknown",
|
||||||
|
"Site check",
|
||||||
|
"Port check",
|
||||||
|
"Ping check",
|
||||||
|
"Process check",
|
||||||
|
"Custom script check"
|
||||||
|
],
|
||||||
|
|
||||||
|
"successScriptLabel": "Success Script",
|
||||||
|
"failScriptLabel": "Fail Script",
|
||||||
|
"failScriptTips": "Script files executed when listening to unhealthy results .\n If the script is not filled in, it will not be executed",
|
||||||
|
"successScriptTips": "Script file executed when listening to healthy results .\n If the script is not filled in, it will not be executed",
|
||||||
|
"baseInfoLabel": "Base Info",
|
||||||
"testState": "Test state",
|
"testState": "Test state",
|
||||||
"failTimes": "Failure times",
|
"failTimes": "Failure times",
|
||||||
"silentCycle": "Silent cycle",
|
"silentCycle": "Silent cycle",
|
||||||
"notifyTimes": "Notice times",
|
"notifyTimes": "Notice times",
|
||||||
"errorContent": "Error content",
|
"errorContent": "Error content",
|
||||||
"toggleStateTips":
|
"toggleStateTips": "This action will suspend the monitoring application({monitorName}), continue?",
|
||||||
"This action will suspend the monitoring application({monitorName}), continue?",
|
"removeMontiorTips": "This action will no longer monitor the app({monitorName}), continue?"
|
||||||
"removeMontiorTips":
|
|
||||||
"This action will no longer monitor the app({monitorName}), continue?"
|
|
||||||
},
|
},
|
||||||
"JSONPage": {
|
"JSONPage": {
|
||||||
"expandAll": "Expand all",
|
"expandAll": "Expand all",
|
||||||
"collapseAll": "Collapse all",
|
"collapseAll": "Collapse all",
|
||||||
"unmarkAll": "Unmark all",
|
"unmarkAll": "Unmark all",
|
||||||
"copyAll": "Copy all",
|
"copyAll": "Copy all",
|
||||||
"tips":
|
"tips": "1.Hold down ALT and click label to achieve highlighting<br>2.Hold down SHIFT and click label to view the JSON path"
|
||||||
"1.Hold down ALT and click label to achieve highlighting<br>2.Hold down SHIFT and click label to view the JSON path"
|
|
||||||
},
|
},
|
||||||
"projectPage": {
|
"projectPage": {
|
||||||
"testConnection": "Test",
|
"testConnection": "Test",
|
||||||
@ -348,7 +379,11 @@
|
|||||||
"resetStateTips": "This action will reset project state, continue?",
|
"resetStateTips": "This action will reset project state, continue?",
|
||||||
"reviewDeploy": "Review deploy",
|
"reviewDeploy": "Review deploy",
|
||||||
"reviewTips": "This action will approve commit, continue?",
|
"reviewTips": "This action will approve commit, continue?",
|
||||||
"reviewStateOption": ["Wait", "Reviewed", "Rejected"],
|
"reviewStateOption": [
|
||||||
|
"Wait",
|
||||||
|
"Reviewed",
|
||||||
|
"Rejected"
|
||||||
|
],
|
||||||
"removeProjectTaskTips": "This action will delete the crontab task in {projectName}, continue?",
|
"removeProjectTaskTips": "This action will delete the crontab task in {projectName}, continue?",
|
||||||
"publishCommitTips": "This action will rebuild {commit}, continue?"
|
"publishCommitTips": "This action will rebuild {commit}, continue?"
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"default": "默认",
|
"default": "默认",
|
||||||
"name": "名称",
|
"name": "名称",
|
||||||
|
"tag": "标签",
|
||||||
"script": "脚本",
|
"script": "脚本",
|
||||||
"owner": "拥有者",
|
"owner": "拥有者",
|
||||||
"user": "用户",
|
"user": "用户",
|
||||||
@ -290,12 +291,19 @@
|
|||||||
"saveTemplate": "保存模板"
|
"saveTemplate": "保存模板"
|
||||||
},
|
},
|
||||||
"monitorPage": {
|
"monitorPage": {
|
||||||
|
"scriptMode": "脚本类型",
|
||||||
|
"defaultServer": "跟随宿主机",
|
||||||
"typeOption": ["未知", "站点检测", "端口检测", "Ping检测", "进程检测", "自定义脚本检测"],
|
"typeOption": ["未知", "站点检测", "端口检测", "Ping检测", "进程检测", "自定义脚本检测"],
|
||||||
"testState": "测试状态",
|
"testState": "测试状态",
|
||||||
"failTimes": "连续失败次数",
|
"failTimes": "连续失败次数",
|
||||||
"silentCycle": "通道沉默周期",
|
"silentCycle": "通道沉默周期",
|
||||||
"notifyTimes": "通知次数",
|
"notifyTimes": "通知次数",
|
||||||
"errorContent": "错误内容",
|
"errorContent": "错误内容",
|
||||||
|
"baseInfoLabel": "基本信息",
|
||||||
|
"successScriptLabel": "成功运行脚本",
|
||||||
|
"failScriptLabel": "失败运行脚本",
|
||||||
|
"failScriptTips": "监听结果不健康时执行的脚本文件.\n如果未填写脚本,则不会执行",
|
||||||
|
"successScriptTips": "监听结果健康时执行的脚本文件.\n如果未填写脚本,则不会执行",
|
||||||
"toggleStateTips": "此操作将暂停监控应用({monitorName}), 是否继续?",
|
"toggleStateTips": "此操作将暂停监控应用({monitorName}), 是否继续?",
|
||||||
"removeMontiorTips": "此操作将不再监控应用({monitorName}), 是否继续?"
|
"removeMontiorTips": "此操作将不再监控应用({monitorName}), 是否继续?"
|
||||||
},
|
},
|
||||||
|
@ -29,6 +29,22 @@
|
|||||||
<el-option :label="$t('envOption[3]')" :value="3" />
|
<el-option :label="$t('envOption[3]')" :value="3" />
|
||||||
<el-option :label="$t('envOption[4]')" :value="4" />
|
<el-option :label="$t('envOption[4]')" :value="4" />
|
||||||
</el-select>
|
</el-select>
|
||||||
|
<el-select
|
||||||
|
v-model="searchProject.tag"
|
||||||
|
:max-collapse-tags="1"
|
||||||
|
style="width: 300px"
|
||||||
|
multiple
|
||||||
|
collapse-tags
|
||||||
|
collapse-tags-tooltip
|
||||||
|
placeholder="Filter the project tag"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in tagList"
|
||||||
|
:key="item"
|
||||||
|
:label="item"
|
||||||
|
:value="item"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="searchProject.name"
|
v-model="searchProject.name"
|
||||||
style="width: 300px"
|
style="width: 300px"
|
||||||
@ -59,51 +75,58 @@
|
|||||||
style="margin-right: 5px; color: var(--el-color-warning)"
|
style="margin-right: 5px; color: var(--el-color-warning)"
|
||||||
icon-class="pin"
|
icon-class="pin"
|
||||||
/>
|
/>
|
||||||
<span
|
<el-tooltip
|
||||||
v-if="row.environment === 1"
|
class="box-item"
|
||||||
style="
|
effect="dark"
|
||||||
flex: 1;
|
:content="row.tag"
|
||||||
overflow: hidden;
|
placement="bottom"
|
||||||
text-overflow: ellipsis;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
white-space: nowrap;
|
|
||||||
color: var(--el-color-danger);
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
{{ row.name }} -
|
<span
|
||||||
{{ $t(`envOption[${row.environment || 0}]`) }}
|
v-if="row.environment === 1"
|
||||||
</span>
|
style="
|
||||||
<span
|
flex: 1;
|
||||||
v-else-if="row.environment === 3"
|
overflow: hidden;
|
||||||
style="
|
text-overflow: ellipsis;
|
||||||
flex: 1;
|
font-size: 14px;
|
||||||
overflow: hidden;
|
font-weight: 600;
|
||||||
text-overflow: ellipsis;
|
white-space: nowrap;
|
||||||
font-size: 14px;
|
color: var(--el-color-danger);
|
||||||
font-weight: 600;
|
"
|
||||||
white-space: nowrap;
|
>
|
||||||
color: var(--el-color-warning);
|
{{ row.name }} -
|
||||||
"
|
{{ $t(`envOption[${row.environment || 0}]`) }}
|
||||||
>
|
</span>
|
||||||
{{ row.name }} -
|
<span
|
||||||
{{ $t(`envOption[${row.environment || 0}]`) }}
|
v-else-if="row.environment === 3"
|
||||||
</span>
|
style="
|
||||||
<span
|
flex: 1;
|
||||||
v-else
|
overflow: hidden;
|
||||||
style="
|
text-overflow: ellipsis;
|
||||||
flex: 1;
|
font-size: 14px;
|
||||||
overflow: hidden;
|
font-weight: 600;
|
||||||
text-overflow: ellipsis;
|
white-space: nowrap;
|
||||||
font-size: 14px;
|
color: var(--el-color-warning);
|
||||||
font-weight: 600;
|
"
|
||||||
white-space: nowrap;
|
>
|
||||||
color: var(--el-color-info);
|
{{ row.name }} -
|
||||||
"
|
{{ $t(`envOption[${row.environment || 0}]`) }}
|
||||||
>
|
</span>
|
||||||
{{ row.name }} -
|
<span
|
||||||
{{ $t(`envOption[${row.environment || 0}]`) }}
|
v-else
|
||||||
</span>
|
style="
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
white-space: nowrap;
|
||||||
|
color: var(--el-color-info);
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ row.name }} -
|
||||||
|
{{ $t(`envOption[${row.environment || 0}]`) }}
|
||||||
|
</span>
|
||||||
|
</el-tooltip>
|
||||||
<el-dropdown
|
<el-dropdown
|
||||||
trigger="click"
|
trigger="click"
|
||||||
@command="(funcName: string) => cardMoreFunc[funcName](row)"
|
@command="(funcName: string) => cardMoreFunc[funcName](row)"
|
||||||
@ -188,7 +211,9 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
>
|
>
|
||||||
{{ $t('submit') }}
|
{{ $t('submit') }}
|
||||||
<el-icon class="el-icon--right"><arrow-down /></el-icon>
|
<el-icon class="el-icon--right">
|
||||||
|
<arrow-down />
|
||||||
|
</el-icon>
|
||||||
</el-button>
|
</el-button>
|
||||||
<span v-else>{{ $t('deploy') }}</span>
|
<span v-else>{{ $t('deploy') }}</span>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
@ -209,7 +234,9 @@
|
|||||||
>
|
>
|
||||||
<el-button size="small" type="warning">
|
<el-button size="small" type="warning">
|
||||||
{{ $t('func') }}
|
{{ $t('func') }}
|
||||||
<el-icon class="el-icon--right"><arrow-down /></el-icon>
|
<el-icon class="el-icon--right">
|
||||||
|
<arrow-down />
|
||||||
|
</el-icon>
|
||||||
</el-button>
|
</el-button>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu
|
<el-dropdown-menu
|
||||||
@ -387,7 +414,7 @@ import {
|
|||||||
DeployResetState,
|
DeployResetState,
|
||||||
DeployGreyPublish,
|
DeployGreyPublish,
|
||||||
} from '@/api/deploy'
|
} from '@/api/deploy'
|
||||||
import { ProjectServerList, ProjectData } from '@/api/project'
|
import { ProjectServerList, ProjectData, TagList } from '@/api/project'
|
||||||
import RepoURL from '@/components/RepoURL/index.vue'
|
import RepoURL from '@/components/RepoURL/index.vue'
|
||||||
import { parseTime } from '@/utils'
|
import { parseTime } from '@/utils'
|
||||||
import TheDetailDialog from './TheDetailDialog.vue'
|
import TheDetailDialog from './TheDetailDialog.vue'
|
||||||
@ -420,11 +447,13 @@ const searchProject = ref({
|
|||||||
sort: getSort(),
|
sort: getSort(),
|
||||||
name: '',
|
name: '',
|
||||||
environment: '',
|
environment: '',
|
||||||
|
tag: [] as string[],
|
||||||
pin: '',
|
pin: '',
|
||||||
})
|
})
|
||||||
const selectedItem = ref({} as ProjectData)
|
const selectedItem = ref({} as ProjectData)
|
||||||
const tableloading = ref(false)
|
const tableloading = ref(false)
|
||||||
const tableData = ref<any[]>([])
|
const tableData = ref<any[]>([])
|
||||||
|
const tagList = ref<string[]>([])
|
||||||
const pagination = ref({ page: 1, rows: 20 })
|
const pagination = ref({ page: 1, rows: 20 })
|
||||||
const greyServerForm = ref<InstanceType<typeof ElForm>>()
|
const greyServerForm = ref<InstanceType<typeof ElForm>>()
|
||||||
const greyServerFormProps = ref({
|
const greyServerFormProps = ref({
|
||||||
@ -463,6 +492,13 @@ const tablePage = computed(() => {
|
|||||||
(item) => item.pin === searchProject.value.pin
|
(item) => item.pin === searchProject.value.pin
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (searchProject.value.tag.length > 0) {
|
||||||
|
_tableData = _tableData.filter((item) =>
|
||||||
|
String(item.tag)
|
||||||
|
.split(',')
|
||||||
|
.find((p) => searchProject.value.tag.indexOf(p) > -1)
|
||||||
|
)
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
list: _tableData.slice(
|
list: _tableData.slice(
|
||||||
(pagination.value.page - 1) * pagination.value.rows,
|
(pagination.value.page - 1) * pagination.value.rows,
|
||||||
@ -510,6 +546,7 @@ watch(
|
|||||||
)
|
)
|
||||||
|
|
||||||
getList()
|
getList()
|
||||||
|
getTagList()
|
||||||
|
|
||||||
function getList() {
|
function getList() {
|
||||||
tableloading.value = true
|
tableloading.value = true
|
||||||
@ -550,6 +587,11 @@ function getList() {
|
|||||||
tableloading.value = false
|
tableloading.value = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
function getTagList() {
|
||||||
|
new TagList().request().then((response) => {
|
||||||
|
tagList.value = response.data.list
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function stickChange() {
|
function stickChange() {
|
||||||
tableData.value = tableData.value.map((_) => {
|
tableData.value = tableData.value.map((_) => {
|
||||||
|
@ -2,34 +2,15 @@
|
|||||||
<el-row class="app-container">
|
<el-row class="app-container">
|
||||||
<el-row class="app-bar" type="flex" justify="space-between">
|
<el-row class="app-bar" type="flex" justify="space-between">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-input
|
<el-input v-model="monitorName" style="width: 200px" placeholder="Filter the name" />
|
||||||
v-model="monitorName"
|
|
||||||
style="width: 200px"
|
|
||||||
placeholder="Filter the name"
|
|
||||||
/>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-button
|
<el-button :loading="tableLoading" type="primary" :icon="Refresh" @click="refresList" />
|
||||||
:loading="tableLoading"
|
<Button type="primary" :icon="Plus" :permissions="[pms.AddMonitor]" @click="handleAdd" />
|
||||||
type="primary"
|
|
||||||
:icon="Refresh"
|
|
||||||
@click="refresList"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
:icon="Plus"
|
|
||||||
:permissions="[pms.AddMonitor]"
|
|
||||||
@click="handleAdd"
|
|
||||||
/>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row class="app-table">
|
<el-row class="app-table">
|
||||||
<el-table
|
<el-table v-loading="tableLoading" height="100%" highlight-current-row :data="tablePage.list">
|
||||||
v-loading="tableLoading"
|
|
||||||
height="100%"
|
|
||||||
highlight-current-row
|
|
||||||
:data="tablePage.list"
|
|
||||||
>
|
|
||||||
<el-table-column prop="id" label="ID" width="100" />
|
<el-table-column prop="id" label="ID" width="100" />
|
||||||
<el-table-column prop="name" :label="$t('name')" min-width="120" />
|
<el-table-column prop="name" :label="$t('name')" min-width="120" />
|
||||||
<el-table-column prop="type" :label="$t('type')" min-width="120">
|
<el-table-column prop="type" :label="$t('type')" min-width="120">
|
||||||
@ -69,307 +50,231 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column prop="second" :label="$t('interval') + '(s)'" width="95" />
|
||||||
prop="second"
|
<el-table-column prop="times" :label="$t('monitorPage.failTimes')" width="115" />
|
||||||
:label="$t('interval') + '(s)'"
|
|
||||||
width="95"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
prop="times"
|
|
||||||
:label="$t('monitorPage.failTimes')"
|
|
||||||
width="115"
|
|
||||||
/>
|
|
||||||
<el-table-column prop="notifyType" :label="$t('notice')" width="90">
|
<el-table-column prop="notifyType" :label="$t('notice')" width="90">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ $t(`webhookOption[${scope.row.notifyType || 0}]`) }}
|
{{ $t(`webhookOption[${scope.row.notifyType || 0}]`) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column prop="state" :label="$t('state')" width="120" align="center">
|
||||||
prop="state"
|
|
||||||
:label="$t('state')"
|
|
||||||
width="120"
|
|
||||||
align="center"
|
|
||||||
>
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ $t(`switchOption[${scope.row.state || 0}]`) }}
|
{{ $t(`switchOption[${scope.row.state || 0}]`) }}
|
||||||
<Switch
|
<Switch :model-value="scope.row.state === 1" active-color="#13ce66" inactive-color="#ff4949"
|
||||||
:model-value="scope.row.state === 1"
|
:permissions="[pms.EditMonitor]" @change="handleToggle(scope.row)" />
|
||||||
active-color="#13ce66"
|
|
||||||
inactive-color="#ff4949"
|
|
||||||
:permissions="[pms.EditMonitor]"
|
|
||||||
@change="handleToggle(scope.row)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column prop="errorContent" :label="$t('monitorPage.errorContent')" min-width="140"
|
||||||
prop="errorContent"
|
show-overflow-tooltip />
|
||||||
:label="$t('monitorPage.errorContent')"
|
<el-table-column prop="insertTime" :label="$t('insertTime')" width="160" align="center" />
|
||||||
min-width="140"
|
<el-table-column prop="updateTime" :label="$t('updateTime')" width="160" align="center" />
|
||||||
show-overflow-tooltip
|
<el-table-column prop="operation" :label="$t('op')" width="130" align="center" fixed="right">
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
prop="insertTime"
|
|
||||||
:label="$t('insertTime')"
|
|
||||||
width="160"
|
|
||||||
align="center"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
prop="updateTime"
|
|
||||||
:label="$t('updateTime')"
|
|
||||||
width="160"
|
|
||||||
align="center"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
prop="operation"
|
|
||||||
:label="$t('op')"
|
|
||||||
width="130"
|
|
||||||
align="center"
|
|
||||||
fixed="right"
|
|
||||||
>
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<Button
|
<Button type="primary" :icon="Edit" :permissions="[pms.EditMonitor]" @click="handleEdit(scope.row)" />
|
||||||
type="primary"
|
<Button type="danger" :icon="Delete" :permissions="[pms.DeleteMonitor]" @click="handleRemove(scope.row)" />
|
||||||
:icon="Edit"
|
|
||||||
:permissions="[pms.EditMonitor]"
|
|
||||||
@click="handleEdit(scope.row)"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
type="danger"
|
|
||||||
:icon="Delete"
|
|
||||||
:permissions="[pms.DeleteMonitor]"
|
|
||||||
@click="handleRemove(scope.row)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row type="flex" justify="end" class="app-page">
|
<el-row type="flex" justify="end" class="app-page">
|
||||||
<el-pagination
|
<el-pagination :total="tablePage.total" :page-size="pagination.rows" background layout="total, prev, pager, next"
|
||||||
:total="tablePage.total"
|
@current-change="handlePageChange" />
|
||||||
:page-size="pagination.rows"
|
|
||||||
background
|
|
||||||
layout="total, prev, pager, next"
|
|
||||||
@current-change="handlePageChange"
|
|
||||||
/>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-dialog
|
<el-dialog v-model="dialogVisible" :title="$t('setting')" :fullscreen="$store.state.app.device === 'mobile'"
|
||||||
v-model="dialogVisible"
|
:close-on-click-modal="false">
|
||||||
:title="$t('setting')"
|
<el-form ref="form" v-loading="formProps.loading"
|
||||||
:fullscreen="$store.state.app.device === 'mobile'"
|
:class="$store.state.app.device === 'desktop' ? 'monitor-dialog' : ''" :model="formData" label-width="120px"
|
||||||
:close-on-click-modal="false"
|
|
||||||
>
|
|
||||||
<el-form
|
|
||||||
ref="form"
|
|
||||||
v-loading="formProps.loading"
|
|
||||||
:class="$store.state.app.device === 'desktop' ? 'monitor-dialog' : ''"
|
|
||||||
:model="formData"
|
|
||||||
label-width="120px"
|
|
||||||
:label-position="
|
:label-position="
|
||||||
$store.state.app.device === 'desktop' ? 'right' : 'top'
|
$store.state.app.device === 'desktop' ? 'right' : 'top'
|
||||||
"
|
">
|
||||||
>
|
<el-tabs type="border-card" class="demo-tabs">
|
||||||
<el-form-item
|
<el-tab-pane>
|
||||||
:label="$t('name')"
|
<template #label>
|
||||||
prop="name"
|
<span style="vertical-align: middle; padding-right: 4px">
|
||||||
:rules="[
|
{{ $t('monitorPage.baseInfoLabel') }}
|
||||||
{ required: true, message: 'Name required', trigger: 'blur' },
|
</span>
|
||||||
]"
|
</template>
|
||||||
>
|
|
||||||
<el-input v-model="formData.name" autocomplete="off" />
|
<el-form-item :label="$t('name')" prop="name" :rules="[
|
||||||
</el-form-item>
|
{ required: true, message: 'Name required', trigger: 'blur' },
|
||||||
<el-form-item
|
]">
|
||||||
:label="$t('type')"
|
<el-input v-model="formData.name" autocomplete="off" />
|
||||||
prop="type"
|
</el-form-item>
|
||||||
:rules="[
|
<el-form-item :label="$t('type')" prop="type" :rules="[
|
||||||
{ required: true, message: 'Type required', trigger: 'blur' },
|
{ required: true, message: 'Type required', trigger: 'blur' },
|
||||||
]"
|
]">
|
||||||
>
|
<el-select v-model="formData.type" style="width: 100%" @change="handleTypeChange">
|
||||||
<el-select
|
<el-option :label="$t('monitorPage.typeOption[1]')" :value="1" />
|
||||||
v-model="formData.type"
|
<el-option :label="$t('monitorPage.typeOption[2]')" :value="2" />
|
||||||
style="width: 100%"
|
<el-option :label="$t('monitorPage.typeOption[3]')" :value="3" />
|
||||||
@change="handleTypeChange"
|
<el-option :label="$t('monitorPage.typeOption[4]')" :value="4" />
|
||||||
>
|
<el-option :label="$t('monitorPage.typeOption[5]')" :value="5" />
|
||||||
<el-option :label="$t('monitorPage.typeOption[1]')" :value="1" />
|
</el-select>
|
||||||
<el-option :label="$t('monitorPage.typeOption[2]')" :value="2" />
|
</el-form-item>
|
||||||
<el-option :label="$t('monitorPage.typeOption[3]')" :value="3" />
|
<template v-if="0 < formData.type && formData.type < 4">
|
||||||
<el-option :label="$t('monitorPage.typeOption[4]')" :value="4" />
|
<el-form-item :label="$t('target')">
|
||||||
<el-option :label="$t('monitorPage.typeOption[5]')" :value="5" />
|
<el-button type="primary" :icon="Plus" plain @click="formProps.items.push('')"></el-button>
|
||||||
</el-select>
|
<el-input v-for="(_, index) in formProps.items" :key="index" v-model="formProps.items[index]"
|
||||||
</el-form-item>
|
:placeholder="formProps.itemPlaceholder[formData.type]" clearable>
|
||||||
<template v-if="0 < formData.type && formData.type < 4">
|
<template #append>
|
||||||
<el-form-item :label="$t('target')">
|
<el-button :icon="Minus" @click="formProps.items.splice(index, 1)" />
|
||||||
<el-button
|
</template>
|
||||||
type="primary"
|
</el-input>
|
||||||
:icon="Plus"
|
</el-form-item>
|
||||||
plain
|
</template>
|
||||||
@click="formProps.items.push('')"
|
<template v-else-if="formData.type === 4">
|
||||||
></el-button>
|
<el-form-item :label="$t('target')">
|
||||||
<el-input
|
<el-select v-model="formProps.items" multiple filterable style="width: 100%">
|
||||||
v-for="(_, index) in formProps.items"
|
<el-option v-for="item in serverOption" :key="item.label" :label="item.label"
|
||||||
:key="index"
|
:value="item.id.toString()" />
|
||||||
v-model="formProps.items[index]"
|
</el-select>
|
||||||
:placeholder="formProps.itemPlaceholder[formData.type]"
|
</el-form-item>
|
||||||
clearable
|
<el-form-item :label="$t('process')">
|
||||||
>
|
<el-input v-model="formProps.process" autocomplete="off" placeholder="The name within ps -ef" />
|
||||||
<template #append>
|
</el-form-item>
|
||||||
<el-button
|
</template>
|
||||||
:icon="Minus"
|
<template v-else-if="formData.type === 5">
|
||||||
@click="formProps.items.splice(index, 1)"
|
<el-form-item :label="$t('target')">
|
||||||
/>
|
<el-select v-model="formProps.items" multiple filterable style="width: 100%">
|
||||||
</template>
|
<el-option v-for="item in serverOption" :key="item.label" :label="item.label"
|
||||||
</el-input>
|
:value="item.id.toString()" />
|
||||||
</el-form-item>
|
</el-select>
|
||||||
</template>
|
</el-form-item>
|
||||||
<template v-else-if="formData.type === 4">
|
<el-form-item :label="$t('script')">
|
||||||
<el-form-item :label="$t('target')">
|
<VAceEditor v-model:value="formProps.script" lang="sh" theme="github" style="height: 360px; width: 100%"
|
||||||
<el-select
|
:options="{ newLineMode: 'unix' }" />
|
||||||
v-model="formProps.items"
|
</el-form-item>
|
||||||
multiple
|
</template>
|
||||||
filterable
|
<el-form-item :label="$t('timeout') + '(s)'">
|
||||||
style="width: 100%"
|
<el-input v-model="formProps.timeout" autocomplete="off" placeholder="" />
|
||||||
>
|
</el-form-item>
|
||||||
<el-option
|
<el-form-item :label="$t('interval') + '(s)'" prop="second" :rules="[
|
||||||
v-for="item in serverOption"
|
{
|
||||||
:key="item.label"
|
type: 'number',
|
||||||
:label="item.label"
|
required: true,
|
||||||
:value="item.id.toString()"
|
min: 1,
|
||||||
/>
|
message: 'Interval required',
|
||||||
</el-select>
|
trigger: 'blur',
|
||||||
</el-form-item>
|
},
|
||||||
<el-form-item :label="$t('process')">
|
]">
|
||||||
<el-input
|
<el-radio-group v-model="formData.second">
|
||||||
v-model="formProps.process"
|
<el-radio :label="60">1 min</el-radio>
|
||||||
autocomplete="off"
|
<el-radio :label="300">5 min</el-radio>
|
||||||
placeholder="The name within ps -ef"
|
<el-radio :label="900">15 min</el-radio>
|
||||||
/>
|
<el-radio :label="1800">30 min</el-radio>
|
||||||
</el-form-item>
|
<el-radio :label="3600">60 min</el-radio>
|
||||||
</template>
|
</el-radio-group>
|
||||||
<template v-else-if="formData.type === 5">
|
</el-form-item>
|
||||||
<el-form-item :label="$t('target')">
|
<el-form-item :label="$t('monitorPage.failTimes')" prop="times" :rules="[
|
||||||
<el-select
|
{
|
||||||
v-model="formProps.items"
|
type: 'number',
|
||||||
multiple
|
required: true,
|
||||||
filterable
|
min: 1,
|
||||||
style="width: 100%"
|
max: 65535,
|
||||||
>
|
message: 'Times required',
|
||||||
<el-option
|
trigger: 'blur',
|
||||||
v-for="item in serverOption"
|
},
|
||||||
:key="item.label"
|
]">
|
||||||
:label="item.label"
|
<el-radio-group v-model="formData.times">
|
||||||
:value="item.id.toString()"
|
<el-radio :label="1">1</el-radio>
|
||||||
/>
|
<el-radio :label="2">2</el-radio>
|
||||||
</el-select>
|
<el-radio :label="3">3</el-radio>
|
||||||
</el-form-item>
|
<el-radio :label="4">4</el-radio>
|
||||||
<el-form-item :label="$t('script')">
|
<el-radio :label="5">5</el-radio>
|
||||||
<VAceEditor
|
</el-radio-group>
|
||||||
v-model:value="formProps.script"
|
</el-form-item>
|
||||||
lang="sh"
|
<el-form-item :label="$t('monitorPage.silentCycle')">
|
||||||
theme="github"
|
<el-select v-model="formData.silentCycle" style="width: 100%" filterable>
|
||||||
style="height: 360px; width: 100%"
|
<el-option label="5 min" :value="5" />
|
||||||
:options="{ newLineMode: 'unix' }"
|
<el-option label="10 min" :value="10" />
|
||||||
/>
|
<el-option label="15 min" :value="15" />
|
||||||
</el-form-item>
|
<el-option label="30 min" :value="30" />
|
||||||
</template>
|
<el-option label="60 min" :value="60" />
|
||||||
<el-form-item :label="$t('timeout') + '(s)'">
|
<el-option label="3 hour" :value="180" />
|
||||||
<el-input
|
<el-option label="6 hour" :value="360" />
|
||||||
v-model="formProps.timeout"
|
<el-option label="12 hour" :value="720" />
|
||||||
autocomplete="off"
|
<el-option label="24 hour" :value="1440" />
|
||||||
placeholder=""
|
</el-select>
|
||||||
/>
|
</el-form-item>
|
||||||
</el-form-item>
|
<el-form-item :label="$t('notice')" prop="notifyTarget"
|
||||||
<el-form-item
|
:rules="[{ required: true, message: 'Webhook required' }]">
|
||||||
:label="$t('interval') + '(s)'"
|
<el-row type="flex" style="width: 100%">
|
||||||
prop="second"
|
<el-select v-model="formData.notifyType">
|
||||||
:rules="[
|
<el-option :label="$t('webhookOption[1]')" :value="1" />
|
||||||
{
|
<el-option :label="$t('webhookOption[2]')" :value="2" />
|
||||||
type: 'number',
|
<el-option :label="$t('webhookOption[3]')" :value="3" />
|
||||||
required: true,
|
<el-option :label="$t('webhookOption[255]')" :value="255" />
|
||||||
min: 1,
|
</el-select>
|
||||||
message: 'Interval required',
|
<el-input v-model.trim="formData.notifyTarget" style="flex: 1" autocomplete="off"
|
||||||
trigger: 'blur',
|
placeholder="webhook" />
|
||||||
},
|
</el-row>
|
||||||
]"
|
</el-form-item>
|
||||||
>
|
<el-form-item :label="$t('description')" prop="description" :rules="[
|
||||||
<el-radio-group v-model="formData.second">
|
{ max: 255, message: 'Max 255 characters', trigger: 'blur' },
|
||||||
<el-radio :label="60">1 min</el-radio>
|
]">
|
||||||
<el-radio :label="300">5 min</el-radio>
|
<el-input v-model="formData.description" type="textarea" :autosize="{ minRows: 2 }" />
|
||||||
<el-radio :label="900">15 min</el-radio>
|
</el-form-item>
|
||||||
<el-radio :label="1800">30 min</el-radio>
|
</el-tab-pane>
|
||||||
<el-radio :label="3600">60 min</el-radio>
|
<el-tab-pane>
|
||||||
</el-radio-group>
|
<template #label>
|
||||||
</el-form-item>
|
<span style="vertical-align: middle; padding-right: 4px">
|
||||||
<el-form-item
|
{{ $t('monitorPage.successScriptLabel') }}
|
||||||
:label="$t('monitorPage.failTimes')"
|
</span>
|
||||||
prop="times"
|
<el-tooltip class="item" effect="dark" placement="bottom">
|
||||||
:rules="[
|
<template #content>
|
||||||
{
|
<div style="white-space: pre-line">
|
||||||
type: 'number',
|
{{ $t('monitorPage.successScriptTips') }}
|
||||||
required: true,
|
</div>
|
||||||
min: 1,
|
</template>
|
||||||
max: 65535,
|
<el-icon style="vertical-align: middle" :size="16">
|
||||||
message: 'Times required',
|
<question-filled />
|
||||||
trigger: 'blur',
|
</el-icon>
|
||||||
},
|
</el-tooltip>
|
||||||
]"
|
</template>
|
||||||
>
|
<el-form-item prop="successServerId" :label="$t('target')">
|
||||||
<el-radio-group v-model="formData.times">
|
<el-select v-model="formData.successServerId" style="width: 100%">
|
||||||
<el-radio :label="1">1</el-radio>
|
<el-option v-for="item in [
|
||||||
<el-radio :label="2">2</el-radio>
|
{ id: -1, label: $t('monitorPage.defaultServer') },
|
||||||
<el-radio :label="3">3</el-radio>
|
...serverOption,
|
||||||
<el-radio :label="4">4</el-radio>
|
]" :key="item.label" :label="item.label" :value="item.id" />
|
||||||
<el-radio :label="5">5</el-radio>
|
</el-select>
|
||||||
</el-radio-group>
|
</el-form-item>
|
||||||
</el-form-item>
|
|
||||||
<el-form-item :label="$t('monitorPage.silentCycle')">
|
<el-form-item prop="successScript" :label="$t('script')">
|
||||||
<el-select
|
<VAceEditor v-model:value="formData.successScript" lang="sh" theme="github"
|
||||||
v-model="formData.silentCycle"
|
style="height: 360px; width: 100%" :options="{ newLineMode: 'unix' }" />
|
||||||
style="width: 100%"
|
</el-form-item>
|
||||||
filterable
|
</el-tab-pane>
|
||||||
>
|
<el-tab-pane>
|
||||||
<el-option label="5 min" :value="5" />
|
<template #label>
|
||||||
<el-option label="10 min" :value="10" />
|
<span style="vertical-align: middle">
|
||||||
<el-option label="15 min" :value="15" />
|
{{ $t('monitorPage.failScriptLabel') }}
|
||||||
<el-option label="30 min" :value="30" />
|
</span>
|
||||||
<el-option label="60 min" :value="60" />
|
<el-tooltip class="item" effect="dark" placement="bottom">
|
||||||
<el-option label="3 hour" :value="180" />
|
<template #content>
|
||||||
<el-option label="6 hour" :value="360" />
|
<div style="white-space: pre-line">
|
||||||
<el-option label="12 hour" :value="720" />
|
{{ $t('monitorPage.failScriptTips') }}
|
||||||
<el-option label="24 hour" :value="1440" />
|
</div>
|
||||||
</el-select>
|
</template>
|
||||||
</el-form-item>
|
<el-icon style="vertical-align: middle" :size="16">
|
||||||
<el-form-item
|
<question-filled />
|
||||||
:label="$t('notice')"
|
</el-icon>
|
||||||
prop="notifyTarget"
|
</el-tooltip>
|
||||||
:rules="[{ required: true, message: 'Webhook required' }]"
|
</template>
|
||||||
>
|
<el-form-item prop="failServerId" :label="$t('target')">
|
||||||
<el-row type="flex" style="width: 100%">
|
<el-select v-model="formData.failServerId" style="width: 100%">
|
||||||
<el-select v-model="formData.notifyType">
|
<el-option v-for="item in [
|
||||||
<el-option :label="$t('webhookOption[1]')" :value="1" />
|
{ id: -1, label: $t('monitorPage.defaultServer') },
|
||||||
<el-option :label="$t('webhookOption[2]')" :value="2" />
|
...serverOption,
|
||||||
<el-option :label="$t('webhookOption[3]')" :value="3" />
|
]" :key="item.label" :label="item.label" :value="item.id" />
|
||||||
<el-option :label="$t('webhookOption[255]')" :value="255" />
|
</el-select>
|
||||||
</el-select>
|
</el-form-item>
|
||||||
<el-input
|
<el-form-item prop="failScript" :label="$t('script')">
|
||||||
v-model.trim="formData.notifyTarget"
|
<VAceEditor v-model:value="formData.failScript" lang="sh" theme="github"
|
||||||
style="flex: 1"
|
style="height: 360px; width: 100%" :options="{ newLineMode: 'unix' }" />
|
||||||
autocomplete="off"
|
</el-form-item>
|
||||||
placeholder="webhook"
|
</el-tab-pane>
|
||||||
/>
|
</el-tabs>
|
||||||
</el-row>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item
|
|
||||||
:label="$t('description')"
|
|
||||||
prop="description"
|
|
||||||
:rules="[
|
|
||||||
{ max: 255, message: 'Max 255 characters', trigger: 'blur' },
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<el-input
|
|
||||||
v-model="formData.description"
|
|
||||||
type="textarea"
|
|
||||||
:autosize="{ minRows: 2 }"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-row type="flex" justify="space-between">
|
<el-row type="flex" justify="space-between">
|
||||||
@ -380,11 +285,7 @@
|
|||||||
<el-button @click="dialogVisible = false">
|
<el-button @click="dialogVisible = false">
|
||||||
{{ $t('cancel') }}
|
{{ $t('cancel') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button :disabled="formProps.disabled" type="primary" @click="submit">
|
||||||
:disabled="formProps.disabled"
|
|
||||||
type="primary"
|
|
||||||
@click="submit"
|
|
||||||
>
|
|
||||||
{{ $t('confirm') }}
|
{{ $t('confirm') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -399,7 +300,14 @@ export default { name: 'MonitorIndex' }
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import pms from '@/permission'
|
import pms from '@/permission'
|
||||||
import { Button, Switch } from '@/components/Permission'
|
import { Button, Switch } from '@/components/Permission'
|
||||||
import { Refresh, Plus, Edit, Delete, Minus } from '@element-plus/icons-vue'
|
import {
|
||||||
|
Refresh,
|
||||||
|
Plus,
|
||||||
|
Edit,
|
||||||
|
Delete,
|
||||||
|
Minus,
|
||||||
|
QuestionFilled,
|
||||||
|
} from '@element-plus/icons-vue'
|
||||||
import { VAceEditor } from 'vue3-ace-editor'
|
import { VAceEditor } from 'vue3-ace-editor'
|
||||||
import * as ace from 'ace-builds/src-noconflict/ace'
|
import * as ace from 'ace-builds/src-noconflict/ace'
|
||||||
import { ServerOption } from '@/api/server'
|
import { ServerOption } from '@/api/server'
|
||||||
@ -413,10 +321,13 @@ import {
|
|||||||
MonitorData,
|
MonitorData,
|
||||||
} from '@/api/monitor'
|
} from '@/api/monitor'
|
||||||
import type { ElForm } from 'element-plus'
|
import type { ElForm } from 'element-plus'
|
||||||
|
import { scriptLang } from '@/const/const'
|
||||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||||
import { ref, watch, computed } from 'vue'
|
import { ref, watch, computed } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { useDark } from '@vueuse/core'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
ace.config.set(
|
ace.config.set(
|
||||||
@ -445,7 +356,13 @@ const tempFormData = {
|
|||||||
notifyType: 1,
|
notifyType: 1,
|
||||||
notifyTarget: '',
|
notifyTarget: '',
|
||||||
description: '',
|
description: '',
|
||||||
|
successServerId: -1,
|
||||||
|
successScript: '',
|
||||||
|
failServerId: -1,
|
||||||
|
failScript: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isDark = useDark()
|
||||||
const formData = ref(tempFormData)
|
const formData = ref(tempFormData)
|
||||||
const formProps = ref({
|
const formProps = ref({
|
||||||
loading: false,
|
loading: false,
|
||||||
@ -478,10 +395,10 @@ watch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
;(async () => {
|
; (async () => {
|
||||||
await getServerOption()
|
await getServerOption()
|
||||||
await getList()
|
await getList()
|
||||||
})()
|
})()
|
||||||
|
|
||||||
const tablePage = computed(() => {
|
const tablePage = computed(() => {
|
||||||
let _tableData = tableData.value
|
let _tableData = tableData.value
|
||||||
@ -622,6 +539,10 @@ function check() {
|
|||||||
formProps.value.loading = true
|
formProps.value.loading = true
|
||||||
formProps.value.disabled = true
|
formProps.value.disabled = true
|
||||||
new MonitorCheck({
|
new MonitorCheck({
|
||||||
|
failServerId: formData.value.failServerId,
|
||||||
|
failScript: formData.value.failScript,
|
||||||
|
successServerId: formData.value.successServerId,
|
||||||
|
successScript: formData.value.successScript,
|
||||||
type: formData.value.type,
|
type: formData.value.type,
|
||||||
target: target,
|
target: target,
|
||||||
})
|
})
|
||||||
@ -728,9 +649,10 @@ function restoreFormData() {
|
|||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import '@/styles/mixin.scss';
|
@import '@/styles/mixin.scss';
|
||||||
|
|
||||||
.monitor-dialog {
|
.monitor-dialog {
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
max-height: 50vh;
|
max-height: 55vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@include scrollBar();
|
@include scrollBar();
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,28 @@
|
|||||||
<el-row class="app-bar" type="flex" justify="space-between">
|
<el-row class="app-bar" type="flex" justify="space-between">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-input
|
<el-input
|
||||||
v-model="projectName"
|
v-model="searchProject.projectName"
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
placeholder="Filter the project name"
|
placeholder="Filter the project name"
|
||||||
/>
|
/>
|
||||||
|
<el-select
|
||||||
|
v-model="searchProject.tag"
|
||||||
|
:max-collapse-tags="1"
|
||||||
|
style="width: 300px"
|
||||||
|
multiple
|
||||||
|
collapse-tags
|
||||||
|
collapse-tags-tooltip
|
||||||
|
placeholder="Filter the project tag"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in tagList"
|
||||||
|
:key="item"
|
||||||
|
:label="item"
|
||||||
|
:value="item"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-button
|
<el-button
|
||||||
:loading="tableLoading"
|
:loading="tableLoading"
|
||||||
@ -40,7 +57,9 @@
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
{{ scope.row.name }}
|
{{ scope.row.name }}
|
||||||
<el-icon><Link /></el-icon>
|
<el-icon>
|
||||||
|
<Link />
|
||||||
|
</el-icon>
|
||||||
</el-link>
|
</el-link>
|
||||||
<span v-else>{{ scope.row.name }}</span>
|
<span v-else>{{ scope.row.name }}</span>
|
||||||
</template>
|
</template>
|
||||||
@ -174,6 +193,7 @@
|
|||||||
placeholder="goploy"
|
placeholder="goploy"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item
|
<el-form-item
|
||||||
prop="url"
|
prop="url"
|
||||||
:rules="[
|
:rules="[
|
||||||
@ -409,6 +429,28 @@
|
|||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('tag')" prop="tag">
|
||||||
|
<el-select
|
||||||
|
v-model="formData.tag"
|
||||||
|
style="width: 100%"
|
||||||
|
:max-collapse-tags="5"
|
||||||
|
allow-create
|
||||||
|
:reserve-keyword="false"
|
||||||
|
collapse-tags-tooltip
|
||||||
|
multiple
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
default-first-option
|
||||||
|
placeholder="TAG"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in tagList"
|
||||||
|
:key="item"
|
||||||
|
:label="item"
|
||||||
|
:value="item"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane name="review">
|
<el-tab-pane name="review">
|
||||||
<template #label>
|
<template #label>
|
||||||
@ -534,7 +576,7 @@
|
|||||||
@change="handleAfterPullScriptModeChange"
|
@change="handleAfterPullScriptModeChange"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="(item, index) in scriptLangOption"
|
v-for="(item, index) in scriptLang.Option"
|
||||||
:key="index"
|
:key="index"
|
||||||
:label="item.label"
|
:label="item.label"
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
@ -644,7 +686,7 @@
|
|||||||
<!-- <span>No support for demo</span> -->
|
<!-- <span>No support for demo</span> -->
|
||||||
<v-ace-editor
|
<v-ace-editor
|
||||||
v-model:value="formData.afterPullScript"
|
v-model:value="formData.afterPullScript"
|
||||||
:lang="getScriptLang(formData.afterPullScriptMode)"
|
:lang="scriptLang.getScriptLang(formData.afterPullScriptMode)"
|
||||||
:theme="isDark ? 'one_dark' : 'github'"
|
:theme="isDark ? 'one_dark' : 'github'"
|
||||||
style="height: 400px; width: 100%"
|
style="height: 400px; width: 100%"
|
||||||
placeholder="Already switched to project directory..."
|
placeholder="Already switched to project directory..."
|
||||||
@ -682,7 +724,7 @@
|
|||||||
@change="handleAfterDeployScriptModeChange"
|
@change="handleAfterDeployScriptModeChange"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="(item, index) in scriptLangOption"
|
v-for="(item, index) in scriptLang.Option"
|
||||||
:key="index"
|
:key="index"
|
||||||
:label="item.label"
|
:label="item.label"
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
@ -816,7 +858,7 @@
|
|||||||
<!-- <span>No support for demo</span> -->
|
<!-- <span>No support for demo</span> -->
|
||||||
<v-ace-editor
|
<v-ace-editor
|
||||||
v-model:value="formData.afterDeployScript"
|
v-model:value="formData.afterDeployScript"
|
||||||
:lang="getScriptLang(formData.afterDeployScriptMode)"
|
:lang="scriptLang.getScriptLang(formData.afterDeployScriptMode)"
|
||||||
:theme="isDark ? 'one_dark' : 'github'"
|
:theme="isDark ? 'one_dark' : 'github'"
|
||||||
style="height: 400px; width: 100%"
|
style="height: 400px; width: 100%"
|
||||||
:options="{
|
:options="{
|
||||||
@ -900,6 +942,7 @@ export default { name: 'ProjectIndex' }
|
|||||||
</script>
|
</script>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import pms from '@/permission'
|
import pms from '@/permission'
|
||||||
|
import { scriptLang } from '@/const/const'
|
||||||
import Button from '@/components/Permission/Button.vue'
|
import Button from '@/components/Permission/Button.vue'
|
||||||
import {
|
import {
|
||||||
Search,
|
Search,
|
||||||
@ -930,12 +973,14 @@ import {
|
|||||||
ProjectRemove,
|
ProjectRemove,
|
||||||
ProjectAutoDeploy,
|
ProjectAutoDeploy,
|
||||||
ProjectData,
|
ProjectData,
|
||||||
|
TagList,
|
||||||
} from '@/api/project'
|
} from '@/api/project'
|
||||||
import type { ElRadioGroup, ElForm, FormItemRule } from 'element-plus'
|
import type { ElRadioGroup, ElForm, FormItemRule } from 'element-plus'
|
||||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import { useDark } from '@vueuse/core'
|
import { useDark } from '@vueuse/core'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const isDark = useDark()
|
const isDark = useDark()
|
||||||
|
|
||||||
@ -947,15 +992,11 @@ ace.config.set(
|
|||||||
'themePath',
|
'themePath',
|
||||||
'https://cdn.jsdelivr.net/npm/ace-builds@' + ace.version + '/src-noconflict/'
|
'https://cdn.jsdelivr.net/npm/ace-builds@' + ace.version + '/src-noconflict/'
|
||||||
)
|
)
|
||||||
const scriptLangOption = [
|
|
||||||
{ label: 'sh', value: 'sh', lang: 'sh' },
|
const searchProject = ref<{ projectName: string; tag: string[] }>({
|
||||||
{ label: 'zsh', value: 'zsh', lang: 'sh' },
|
projectName: '',
|
||||||
{ label: 'bash', value: 'bash', lang: 'sh' },
|
tag: [],
|
||||||
{ label: 'python', value: 'python', lang: 'python' },
|
})
|
||||||
{ label: 'php', value: 'php', lang: 'php' },
|
|
||||||
{ label: 'bat', value: 'cmd', lang: 'batchfile' },
|
|
||||||
]
|
|
||||||
const projectName = ref('')
|
|
||||||
const dialogVisible = ref(false)
|
const dialogVisible = ref(false)
|
||||||
const dialogAutoDeployVisible = ref(false)
|
const dialogAutoDeployVisible = ref(false)
|
||||||
const serverOption = ref<ServerOption['datagram']['list']>([])
|
const serverOption = ref<ServerOption['datagram']['list']>([])
|
||||||
@ -963,6 +1004,7 @@ const userOption = ref<NamespaceUserOption['datagram']['list']>([])
|
|||||||
const selectedItem = ref({} as ProjectData)
|
const selectedItem = ref({} as ProjectData)
|
||||||
const tableLoading = ref(false)
|
const tableLoading = ref(false)
|
||||||
const tableData = ref<ProjectList['datagram']['list']>([])
|
const tableData = ref<ProjectList['datagram']['list']>([])
|
||||||
|
const tagList = ref<TagList['datagram']['list']>([])
|
||||||
const pagination = ref({ page: 1, rows: 20 })
|
const pagination = ref({ page: 1, rows: 20 })
|
||||||
const form = ref<InstanceType<typeof ElForm>>()
|
const form = ref<InstanceType<typeof ElForm>>()
|
||||||
const formProps = ref({
|
const formProps = ref({
|
||||||
@ -1009,6 +1051,7 @@ const formProps = ref({
|
|||||||
reviewURLParam: ['callback=__CALLBACK__'],
|
reviewURLParam: ['callback=__CALLBACK__'],
|
||||||
symlink: false,
|
symlink: false,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
tag: [] as string[],
|
||||||
branch: [] as string[],
|
branch: [] as string[],
|
||||||
pinging: false,
|
pinging: false,
|
||||||
lsBranchLoading: false,
|
lsBranchLoading: false,
|
||||||
@ -1017,6 +1060,7 @@ const formProps = ref({
|
|||||||
const tempFormData = {
|
const tempFormData = {
|
||||||
id: 0,
|
id: 0,
|
||||||
name: '',
|
name: '',
|
||||||
|
tag: [] as string[],
|
||||||
repoType: 'git',
|
repoType: 'git',
|
||||||
url: '',
|
url: '',
|
||||||
path: '',
|
path: '',
|
||||||
@ -1059,12 +1103,18 @@ const autoDeployFormData = ref({ id: 0, autoDeploy: 0 })
|
|||||||
|
|
||||||
getOptions()
|
getOptions()
|
||||||
getList()
|
getList()
|
||||||
|
getTagList()
|
||||||
|
|
||||||
const tablePage = computed(() => {
|
const tablePage = computed(() => {
|
||||||
let _tableData = tableData.value
|
let _tableData = tableData.value
|
||||||
if (projectName.value !== '') {
|
if (searchProject.value.projectName !== '') {
|
||||||
_tableData = tableData.value.filter(
|
_tableData = tableData.value.filter(
|
||||||
(item) => item.name.indexOf(projectName.value) !== -1
|
(item) => item.name.indexOf(searchProject.value.projectName) !== -1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (searchProject.value.tag.length > 0) {
|
||||||
|
_tableData = _tableData.filter((item) =>
|
||||||
|
item.tag.split(',').find((p) => searchProject.value.tag.indexOf(p) !== -1)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@ -1097,6 +1147,12 @@ function getList() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getTagList() {
|
||||||
|
new TagList().request().then((response) => {
|
||||||
|
tagList.value = response.data.list
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function handleAdd() {
|
function handleAdd() {
|
||||||
if (formData.value.id > 0) {
|
if (formData.value.id > 0) {
|
||||||
restoreFormData()
|
restoreFormData()
|
||||||
@ -1112,6 +1168,8 @@ function handleEdit(data: ProjectData) {
|
|||||||
formProps.value.reviewURL = ''
|
formProps.value.reviewURL = ''
|
||||||
formProps.value.reviewURLParam = []
|
formProps.value.reviewURLParam = []
|
||||||
formProps.value.disabled = true
|
formProps.value.disabled = true
|
||||||
|
formData.value.tag = data.tag.split(',')
|
||||||
|
|
||||||
Promise.all([
|
Promise.all([
|
||||||
new ProjectUserList({ id: data.id }).request(),
|
new ProjectUserList({ id: data.id }).request(),
|
||||||
new ProjectServerList({ id: data.id }).request(),
|
new ProjectServerList({ id: data.id }).request(),
|
||||||
@ -1152,6 +1210,7 @@ function handleRemove(data: ProjectData) {
|
|||||||
new ProjectRemove({ id: data.id }).request().then(() => {
|
new ProjectRemove({ id: data.id }).request().then(() => {
|
||||||
ElMessage.success('Success')
|
ElMessage.success('Success')
|
||||||
getList()
|
getList()
|
||||||
|
getTagList()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
@ -1159,17 +1218,6 @@ function handleRemove(data: ProjectData) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function getScriptLang(scriptMode = '') {
|
|
||||||
if (scriptMode !== '') {
|
|
||||||
const scriptInfo = scriptLangOption.find(
|
|
||||||
(elem) => elem.value === scriptMode
|
|
||||||
)
|
|
||||||
return scriptInfo ? scriptInfo['lang'] : ''
|
|
||||||
} else {
|
|
||||||
return 'sh'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSymlinkPath(projectPath: string) {
|
function getSymlinkPath(projectPath: string) {
|
||||||
return path.normalize(
|
return path.normalize(
|
||||||
path.dirname(projectPath) + '/goploy-symlink/' + path.basename(projectPath)
|
path.dirname(projectPath) + '/goploy-symlink/' + path.basename(projectPath)
|
||||||
@ -1248,15 +1296,25 @@ function submit() {
|
|||||||
} else {
|
} else {
|
||||||
formData.value.reviewURL = ''
|
formData.value.reviewURL = ''
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
formData.value.tag.filter((p) => String(p).indexOf(',') !== -1).length > 0
|
||||||
|
) {
|
||||||
|
ElMessage.error('Tag is not allowed to contain , ')
|
||||||
|
return false
|
||||||
|
}
|
||||||
;(formData.value.id === 0
|
;(formData.value.id === 0
|
||||||
? new ProjectAdd(formData.value)
|
? new ProjectAdd({ ...formData.value, tag: formData.value.tag.join(',') })
|
||||||
: new ProjectEdit(formData.value)
|
: new ProjectEdit({
|
||||||
|
...formData.value,
|
||||||
|
tag: formData.value.tag.join(','),
|
||||||
|
})
|
||||||
)
|
)
|
||||||
.request()
|
.request()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
ElMessage.success('Success')
|
ElMessage.success('Success')
|
||||||
getList()
|
getList()
|
||||||
|
getTagList()
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
formProps.value.disabled = false
|
formProps.value.disabled = false
|
||||||
@ -1333,7 +1391,11 @@ function getRemoteBranchList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function refresList() {
|
function refresList() {
|
||||||
projectName.value = ''
|
searchProject.value = {
|
||||||
|
projectName: '',
|
||||||
|
tag: [],
|
||||||
|
}
|
||||||
|
|
||||||
pagination.value.page = 1
|
pagination.value.page = 1
|
||||||
getList()
|
getList()
|
||||||
getOptions()
|
getOptions()
|
||||||
|
3563
web/yarn.lock
3563
web/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user