mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-09-10 16:46:26 +08:00
feat: 完成主机管理界面
This commit is contained in:
parent
89432bc1b8
commit
0fdf519808
34 changed files with 651 additions and 157 deletions
|
@ -9,7 +9,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *BaseApi) CreateGroup(c *gin.Context) {
|
func (b *BaseApi) CreateGroup(c *gin.Context) {
|
||||||
var req dto.GroupCreate
|
var req dto.GroupOperate
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
return
|
return
|
||||||
|
@ -26,17 +26,13 @@ func (b *BaseApi) CreateGroup(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BaseApi) DeleteGroup(c *gin.Context) {
|
func (b *BaseApi) DeleteGroup(c *gin.Context) {
|
||||||
var req dto.DeleteByName
|
id, err := helper.GetParamID(c)
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := global.VALID.Struct(req); err != nil {
|
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := groupService.Delete(req.Name); err != nil {
|
if err := groupService.Delete(id); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -44,7 +40,7 @@ func (b *BaseApi) DeleteGroup(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BaseApi) UpdateGroup(c *gin.Context) {
|
func (b *BaseApi) UpdateGroup(c *gin.Context) {
|
||||||
var req dto.GroupUpdate
|
var req dto.GroupOperate
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
return
|
return
|
||||||
|
@ -59,17 +55,39 @@ func (b *BaseApi) UpdateGroup(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
upMap := make(map[string]interface{})
|
if err := groupService.Update(id, req.Name); err != nil {
|
||||||
upMap["name"] = req.Name
|
|
||||||
if err := groupService.Update(id, upMap); err != nil {
|
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
helper.SuccessWithData(c, nil)
|
helper.SuccessWithData(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *BaseApi) GetGroupInfo(c *gin.Context) {
|
||||||
|
id, err := helper.GetParamID(c)
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
group, err := groupService.GetGroupInfo(id)
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithData(c, group)
|
||||||
|
}
|
||||||
|
|
||||||
func (b *BaseApi) ListGroup(c *gin.Context) {
|
func (b *BaseApi) ListGroup(c *gin.Context) {
|
||||||
list, err := groupService.Search()
|
var req dto.GroupSearch
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := global.VALID.Struct(req); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
list, err := groupService.List(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -5,11 +5,12 @@ import (
|
||||||
"github.com/1Panel-dev/1Panel/app/dto"
|
"github.com/1Panel-dev/1Panel/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/constant"
|
"github.com/1Panel-dev/1Panel/constant"
|
||||||
"github.com/1Panel-dev/1Panel/global"
|
"github.com/1Panel-dev/1Panel/global"
|
||||||
|
"github.com/1Panel-dev/1Panel/utils/copier"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *BaseApi) CreateHost(c *gin.Context) {
|
func (b *BaseApi) CreateHost(c *gin.Context) {
|
||||||
var req dto.HostCreate
|
var req dto.HostOperate
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
return
|
return
|
||||||
|
@ -42,6 +43,25 @@ func (b *BaseApi) HostTree(c *gin.Context) {
|
||||||
helper.SuccessWithData(c, data)
|
helper.SuccessWithData(c, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *BaseApi) GetHostInfo(c *gin.Context) {
|
||||||
|
id, err := helper.GetParamID(c)
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
host, err := hostService.GetHostInfo(id)
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var hostDto dto.HostInfo
|
||||||
|
if err := copier.Copy(&hostDto, host); err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
helper.SuccessWithData(c, hostDto)
|
||||||
|
}
|
||||||
|
|
||||||
func (b *BaseApi) DeleteHost(c *gin.Context) {
|
func (b *BaseApi) DeleteHost(c *gin.Context) {
|
||||||
var req dto.BatchDeleteReq
|
var req dto.BatchDeleteReq
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
@ -61,7 +81,7 @@ func (b *BaseApi) DeleteHost(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BaseApi) UpdateHost(c *gin.Context) {
|
func (b *BaseApi) UpdateHost(c *gin.Context) {
|
||||||
var req dto.HostUpdate
|
var req dto.HostOperate
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
return
|
return
|
||||||
|
@ -78,7 +98,7 @@ func (b *BaseApi) UpdateHost(c *gin.Context) {
|
||||||
|
|
||||||
upMap := make(map[string]interface{})
|
upMap := make(map[string]interface{})
|
||||||
upMap["name"] = req.Name
|
upMap["name"] = req.Name
|
||||||
upMap["group"] = req.Group
|
upMap["group_belong"] = req.GroupBelong
|
||||||
upMap["addr"] = req.Addr
|
upMap["addr"] = req.Addr
|
||||||
upMap["port"] = req.Port
|
upMap["port"] = req.Port
|
||||||
upMap["user"] = req.User
|
upMap["user"] = req.User
|
||||||
|
|
|
@ -32,7 +32,7 @@ func (b *BaseApi) WsSsh(c *gin.Context) {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
host, err := hostService.GetConnInfo(uint(id))
|
host, err := hostService.GetHostInfo(uint(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -10,6 +10,7 @@ type CommandUpdate struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommandInfo struct {
|
type CommandInfo struct {
|
||||||
|
ID string `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Command string `json:"command"`
|
Command string `json:"command"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package dto
|
||||||
|
|
||||||
type SearchWithPage struct {
|
type SearchWithPage struct {
|
||||||
PageInfo
|
PageInfo
|
||||||
Name string `json:"name" validate:"required"`
|
Info string `json:"info" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PageInfo struct {
|
type PageInfo struct {
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
package dto
|
package dto
|
||||||
|
|
||||||
type GroupCreate struct {
|
type GroupOperate struct {
|
||||||
Name string `json:"name" validate:"required"`
|
Name string `json:"name" validate:"required"`
|
||||||
Type string `json:"type" validate:"required"`
|
Type string `json:"type" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GroupUpdate struct {
|
type GroupSearch struct {
|
||||||
Name string `json:"name" validate:"required"`
|
Type string `json:"type" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GroupInfo struct {
|
||||||
|
ID uint `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Type string `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,15 +4,15 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HostCreate struct {
|
type HostOperate struct {
|
||||||
Group string `json:"group" validate:"required"`
|
GroupBelong string `json:"groupBelong" validate:"required"`
|
||||||
Name string `json:"name" validate:"required"`
|
Name string `json:"name" validate:"required"`
|
||||||
Addr string `json:"addr" validate:"required,ip"`
|
Addr string `json:"addr" validate:"required,ip"`
|
||||||
Port uint `json:"port" validate:"required,number,max=65535,min=1"`
|
Port uint `json:"port" validate:"required,number,max=65535,min=1"`
|
||||||
User string `json:"user" validate:"required"`
|
User string `json:"user" validate:"required"`
|
||||||
AuthMode string `json:"authMode" validate:"oneof=password key"`
|
AuthMode string `json:"authMode" validate:"oneof=password key"`
|
||||||
PrivateKey string `json:"privateKey"`
|
PrivateKey string `json:"privateKey"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
|
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
}
|
}
|
||||||
|
@ -22,36 +22,25 @@ type SearchForTree struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type HostInfo struct {
|
type HostInfo struct {
|
||||||
ID uint `json:"id"`
|
ID uint `json:"id"`
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
Group string `json:"group"`
|
GroupBelong string `json:"groupBelong"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Addr string `json:"addr"`
|
Addr string `json:"addr"`
|
||||||
Port uint `json:"port"`
|
Port uint `json:"port"`
|
||||||
User string `json:"user"`
|
User string `json:"user"`
|
||||||
AuthMode string `json:"authMode"`
|
AuthMode string `json:"authMode"`
|
||||||
|
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HostTree struct {
|
type HostTree struct {
|
||||||
|
ID uint `json:"id"`
|
||||||
Label string `json:"label"`
|
Label string `json:"label"`
|
||||||
Children []TreeChild `json:"children"`
|
Children []TreeChild `json:"children"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TreeChild struct {
|
type TreeChild struct {
|
||||||
|
ID uint `json:"id"`
|
||||||
Label string `json:"label"`
|
Label string `json:"label"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HostUpdate struct {
|
|
||||||
Group string `json:"group" validate:"required"`
|
|
||||||
Name string `json:"name" validate:"required"`
|
|
||||||
Addr string `json:"addr" validate:"required,ip"`
|
|
||||||
Port uint `json:"port" validate:"required,number,max=65535,min=1"`
|
|
||||||
User string `json:"user" validate:"required"`
|
|
||||||
AuthMode string `json:"authMode" validate:"oneof=password key"`
|
|
||||||
PrivateKey string `json:"privateKey"`
|
|
||||||
Password string `json:"password"`
|
|
||||||
|
|
||||||
Description string `json:"description"`
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,6 +4,6 @@ import "gorm.io/gorm"
|
||||||
|
|
||||||
type Command struct {
|
type Command struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Name string `gorm:"type:varchar(64));unique;not null" json:"name"`
|
Name string `gorm:"type:varchar(64);unique;not null" json:"name"`
|
||||||
Command string `gorm:"type:varchar(256);unique;not null" json:"command"`
|
Command string `gorm:"type:varchar(256);not null" json:"command"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,5 +5,5 @@ import "gorm.io/gorm"
|
||||||
type Group struct {
|
type Group struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Name string `gorm:"type:varchar(64);not null" json:"name"`
|
Name string `gorm:"type:varchar(64);not null" json:"name"`
|
||||||
Type string `gorm:"type:varchar(16);unique;not null" json:"type"`
|
Type string `gorm:"type:varchar(16);not null" json:"type"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,14 +4,14 @@ import "gorm.io/gorm"
|
||||||
|
|
||||||
type Host struct {
|
type Host struct {
|
||||||
gorm.Model
|
gorm.Model
|
||||||
Group string `gorm:"type:varchar(64);not null" json:"group"`
|
GroupBelong string `gorm:"type:varchar(64);not null" json:"groupBelong"`
|
||||||
Name string `gorm:"type:varchar(64);unique;not null" json:"name"`
|
Name string `gorm:"type:varchar(64);unique;not null" json:"name"`
|
||||||
Addr string `gorm:"type:varchar(16);unique;not null" json:"addr"`
|
Addr string `gorm:"type:varchar(16);unique;not null" json:"addr"`
|
||||||
Port int `gorm:"type:varchar(5);not null" json:"port"`
|
Port int `gorm:"type:varchar(5);not null" json:"port"`
|
||||||
User string `gorm:"type:varchar(64);not null" json:"user"`
|
User string `gorm:"type:varchar(64);not null" json:"user"`
|
||||||
AuthMode string `gorm:"type:varchar(16);not null" json:"authMode"`
|
AuthMode string `gorm:"type:varchar(16);not null" json:"authMode"`
|
||||||
Password string `gorm:"type:varchar(64)" json:"password"`
|
Password string `gorm:"type:varchar(64)" json:"password"`
|
||||||
PrivateKey string `gorm:"type:varchar(256)" json:"privateKey"`
|
PrivateKey string `gorm:"type:varchar(256)" json:"privateKey"`
|
||||||
|
|
||||||
Description string `gorm:"type:varchar(256)" json:"description"`
|
Description string `gorm:"type:varchar(256)" json:"description"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package repo
|
||||||
import (
|
import (
|
||||||
"github.com/1Panel-dev/1Panel/app/model"
|
"github.com/1Panel-dev/1Panel/app/model"
|
||||||
"github.com/1Panel-dev/1Panel/global"
|
"github.com/1Panel-dev/1Panel/global"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type GroupRepo struct{}
|
type GroupRepo struct{}
|
||||||
|
@ -10,6 +11,7 @@ type GroupRepo struct{}
|
||||||
type IGroupRepo interface {
|
type IGroupRepo interface {
|
||||||
Get(opts ...DBOption) (model.Group, error)
|
Get(opts ...DBOption) (model.Group, error)
|
||||||
GetList(opts ...DBOption) ([]model.Group, error)
|
GetList(opts ...DBOption) ([]model.Group, error)
|
||||||
|
WithByType(groupType string) DBOption
|
||||||
Create(group *model.Group) error
|
Create(group *model.Group) error
|
||||||
Update(id uint, vars map[string]interface{}) error
|
Update(id uint, vars map[string]interface{}) error
|
||||||
Delete(opts ...DBOption) error
|
Delete(opts ...DBOption) error
|
||||||
|
@ -39,6 +41,12 @@ func (u *GroupRepo) GetList(opts ...DBOption) ([]model.Group, error) {
|
||||||
return groups, err
|
return groups, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *GroupRepo) WithByType(groupType string) DBOption {
|
||||||
|
return func(g *gorm.DB) *gorm.DB {
|
||||||
|
return g.Where("type = ?", groupType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (u *GroupRepo) Create(group *model.Group) error {
|
func (u *GroupRepo) Create(group *model.Group) error {
|
||||||
return global.DB.Create(group).Error
|
return global.DB.Create(group).Error
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ type IHostRepo interface {
|
||||||
GetList(opts ...DBOption) ([]model.Host, error)
|
GetList(opts ...DBOption) ([]model.Host, error)
|
||||||
WithByInfo(info string) DBOption
|
WithByInfo(info string) DBOption
|
||||||
Create(host *model.Host) error
|
Create(host *model.Host) error
|
||||||
|
ChangeGroup(oldGroup, newGroup string) error
|
||||||
Update(id uint, vars map[string]interface{}) error
|
Update(id uint, vars map[string]interface{}) error
|
||||||
Delete(opts ...DBOption) error
|
Delete(opts ...DBOption) error
|
||||||
}
|
}
|
||||||
|
@ -55,6 +56,10 @@ func (u *HostRepo) Create(host *model.Host) error {
|
||||||
return global.DB.Create(host).Error
|
return global.DB.Create(host).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *HostRepo) ChangeGroup(oldGroup, newGroup string) error {
|
||||||
|
return global.DB.Model(&model.Host{}).Where("group_belong = ?", oldGroup).Updates(map[string]interface{}{"group_belong": newGroup}).Error
|
||||||
|
}
|
||||||
|
|
||||||
func (u *HostRepo) Update(id uint, vars map[string]interface{}) error {
|
func (u *HostRepo) Update(id uint, vars map[string]interface{}) error {
|
||||||
return global.DB.Model(&model.Host{}).Where("id = ?", id).Updates(vars).Error
|
return global.DB.Model(&model.Host{}).Where("id = ?", id).Updates(vars).Error
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ func (u *CommandService) Search() ([]model.Command, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *CommandService) SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error) {
|
func (u *CommandService) SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error) {
|
||||||
total, commands, err := commandRepo.Page(search.Page, search.PageSize, commonRepo.WithLikeName(search.Name))
|
total, commands, err := commandRepo.Page(search.Page, search.PageSize, commonRepo.WithLikeName(search.Info))
|
||||||
var dtoCommands []dto.CommandInfo
|
var dtoCommands []dto.CommandInfo
|
||||||
for _, command := range commands {
|
for _, command := range commands {
|
||||||
var item dto.CommandInfo
|
var item dto.CommandInfo
|
||||||
|
|
|
@ -2,7 +2,6 @@ package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/1Panel-dev/1Panel/app/dto"
|
"github.com/1Panel-dev/1Panel/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/app/model"
|
|
||||||
"github.com/1Panel-dev/1Panel/constant"
|
"github.com/1Panel-dev/1Panel/constant"
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -11,25 +10,46 @@ import (
|
||||||
type GroupService struct{}
|
type GroupService struct{}
|
||||||
|
|
||||||
type IGroupService interface {
|
type IGroupService interface {
|
||||||
Search() ([]model.Group, error)
|
GetGroupInfo(id uint) (*dto.GroupInfo, error)
|
||||||
Create(groupDto dto.GroupCreate) error
|
List(req dto.GroupSearch) ([]dto.GroupInfo, error)
|
||||||
Update(id uint, upMap map[string]interface{}) error
|
Create(groupDto dto.GroupOperate) error
|
||||||
Delete(name string) error
|
Update(id uint, name string) error
|
||||||
|
Delete(id uint) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIGroupService() IGroupService {
|
func NewIGroupService() IGroupService {
|
||||||
return &GroupService{}
|
return &GroupService{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *GroupService) Search() ([]model.Group, error) {
|
func (u *GroupService) GetGroupInfo(id uint) (*dto.GroupInfo, error) {
|
||||||
groups, err := groupRepo.GetList()
|
group, err := groupRepo.Get(commonRepo.WithByID(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, constant.ErrRecordNotFound
|
return nil, constant.ErrRecordNotFound
|
||||||
}
|
}
|
||||||
return groups, err
|
var dtoGroup dto.GroupInfo
|
||||||
|
if err := copier.Copy(&dtoGroup, &group); err != nil {
|
||||||
|
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||||
|
}
|
||||||
|
return &dtoGroup, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *GroupService) Create(groupDto dto.GroupCreate) error {
|
func (u *GroupService) List(req dto.GroupSearch) ([]dto.GroupInfo, error) {
|
||||||
|
groups, err := groupRepo.GetList(groupRepo.WithByType(req.Type))
|
||||||
|
if err != nil {
|
||||||
|
return nil, constant.ErrRecordNotFound
|
||||||
|
}
|
||||||
|
var dtoUsers []dto.GroupInfo
|
||||||
|
for _, group := range groups {
|
||||||
|
var item dto.GroupInfo
|
||||||
|
if err := copier.Copy(&item, &group); err != nil {
|
||||||
|
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||||
|
}
|
||||||
|
dtoUsers = append(dtoUsers, item)
|
||||||
|
}
|
||||||
|
return dtoUsers, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *GroupService) Create(groupDto dto.GroupOperate) error {
|
||||||
group, _ := groupRepo.Get(commonRepo.WithByName(groupDto.Name), commonRepo.WithByName(groupDto.Name))
|
group, _ := groupRepo.Get(commonRepo.WithByName(groupDto.Name), commonRepo.WithByName(groupDto.Name))
|
||||||
if group.ID != 0 {
|
if group.ID != 0 {
|
||||||
return constant.ErrRecordExist
|
return constant.ErrRecordExist
|
||||||
|
@ -43,14 +63,27 @@ func (u *GroupService) Create(groupDto dto.GroupCreate) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *GroupService) Delete(name string) error {
|
func (u *GroupService) Delete(id uint) error {
|
||||||
group, _ := groupRepo.Get(commonRepo.WithByName(name))
|
group, _ := groupRepo.Get(commonRepo.WithByID(id))
|
||||||
if group.ID == 0 {
|
if group.ID == 0 {
|
||||||
return constant.ErrRecordNotFound
|
return constant.ErrRecordNotFound
|
||||||
}
|
}
|
||||||
return groupRepo.Delete(commonRepo.WithByID(group.ID))
|
if err := hostRepo.ChangeGroup(group.Name, "default"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return groupRepo.Delete(commonRepo.WithByID(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *GroupService) Update(id uint, upMap map[string]interface{}) error {
|
func (u *GroupService) Update(id uint, name string) error {
|
||||||
|
group, _ := groupRepo.Get(commonRepo.WithByID(id))
|
||||||
|
if group.ID == 0 {
|
||||||
|
return constant.ErrRecordNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
upMap := make(map[string]interface{})
|
||||||
|
upMap["name"] = name
|
||||||
|
if err := hostRepo.ChangeGroup(group.Name, name); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return groupRepo.Update(id, upMap)
|
return groupRepo.Update(id, upMap)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,9 @@ import (
|
||||||
type HostService struct{}
|
type HostService struct{}
|
||||||
|
|
||||||
type IHostService interface {
|
type IHostService interface {
|
||||||
GetConnInfo(id uint) (*model.Host, error)
|
GetHostInfo(id uint) (*model.Host, error)
|
||||||
SearchForTree(search dto.SearchForTree) ([]dto.HostTree, error)
|
SearchForTree(search dto.SearchForTree) ([]dto.HostTree, error)
|
||||||
Create(hostDto dto.HostCreate) (*dto.HostInfo, error)
|
Create(hostDto dto.HostOperate) (*dto.HostInfo, error)
|
||||||
Update(id uint, upMap map[string]interface{}) error
|
Update(id uint, upMap map[string]interface{}) error
|
||||||
BatchDelete(ids []uint) error
|
BatchDelete(ids []uint) error
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ func NewIHostService() IHostService {
|
||||||
return &HostService{}
|
return &HostService{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *HostService) GetConnInfo(id uint) (*model.Host, error) {
|
func (u *HostService) GetHostInfo(id uint) (*model.Host, error) {
|
||||||
host, err := hostRepo.Get(commonRepo.WithByID(id))
|
host, err := hostRepo.Get(commonRepo.WithByID(id))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, constant.ErrRecordNotFound
|
return nil, constant.ErrRecordNotFound
|
||||||
|
@ -34,26 +34,30 @@ func (u *HostService) GetConnInfo(id uint) (*model.Host, error) {
|
||||||
|
|
||||||
func (u *HostService) SearchForTree(search dto.SearchForTree) ([]dto.HostTree, error) {
|
func (u *HostService) SearchForTree(search dto.SearchForTree) ([]dto.HostTree, error) {
|
||||||
hosts, err := hostRepo.GetList(hostRepo.WithByInfo(search.Info))
|
hosts, err := hostRepo.GetList(hostRepo.WithByInfo(search.Info))
|
||||||
distinctMap := make(map[string][]string)
|
if err != nil {
|
||||||
for _, host := range hosts {
|
return nil, err
|
||||||
if _, ok := distinctMap[host.Group]; !ok {
|
|
||||||
distinctMap[host.Group] = []string{fmt.Sprintf("%s@%s:%d", host.User, host.Addr, host.Port)}
|
|
||||||
} else {
|
|
||||||
distinctMap[host.Group] = append(distinctMap[host.Group], fmt.Sprintf("%s@%s:%d", host.User, host.Addr, host.Port))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var data []dto.HostTree
|
groups, err := groupRepo.GetList()
|
||||||
for key, value := range distinctMap {
|
if err != nil {
|
||||||
var children []dto.TreeChild
|
return nil, err
|
||||||
for _, label := range value {
|
|
||||||
children = append(children, dto.TreeChild{Label: label})
|
|
||||||
}
|
|
||||||
data = append(data, dto.HostTree{Label: key, Children: children})
|
|
||||||
}
|
}
|
||||||
return data, err
|
var datas []dto.HostTree
|
||||||
|
for _, group := range groups {
|
||||||
|
var data dto.HostTree
|
||||||
|
data.ID = group.ID + 10000
|
||||||
|
data.Label = group.Name
|
||||||
|
for _, host := range hosts {
|
||||||
|
label := fmt.Sprintf("%s@%s:%d", host.User, host.Addr, host.Port)
|
||||||
|
if host.GroupBelong == group.Name {
|
||||||
|
data.Children = append(data.Children, dto.TreeChild{ID: host.ID, Label: label})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
datas = append(datas, data)
|
||||||
|
}
|
||||||
|
return datas, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *HostService) Create(hostDto dto.HostCreate) (*dto.HostInfo, error) {
|
func (u *HostService) Create(hostDto dto.HostOperate) (*dto.HostInfo, error) {
|
||||||
host, _ := hostRepo.Get(commonRepo.WithByName(hostDto.Name))
|
host, _ := hostRepo.Get(commonRepo.WithByName(hostDto.Name))
|
||||||
if host.ID != 0 {
|
if host.ID != 0 {
|
||||||
return nil, constant.ErrRecordExist
|
return nil, constant.ErrRecordExist
|
||||||
|
|
|
@ -44,7 +44,7 @@ func (u *UserService) Get(id uint) (*dto.UserInfo, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *UserService) Page(search dto.SearchWithPage) (int64, interface{}, error) {
|
func (u *UserService) Page(search dto.SearchWithPage) (int64, interface{}, error) {
|
||||||
total, users, err := userRepo.Page(search.Page, search.PageSize, commonRepo.WithLikeName(search.Name))
|
total, users, err := userRepo.Page(search.Page, search.PageSize, commonRepo.WithLikeName(search.Info))
|
||||||
var dtoUsers []dto.UserInfo
|
var dtoUsers []dto.UserInfo
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
var item dto.UserInfo
|
var item dto.UserInfo
|
||||||
|
|
|
@ -35,6 +35,15 @@ var AddTableOperationLog = &gormigrate.Migration{
|
||||||
var AddTableHost = &gormigrate.Migration{
|
var AddTableHost = &gormigrate.Migration{
|
||||||
ID: "20200818-add-table-host",
|
ID: "20200818-add-table-host",
|
||||||
Migrate: func(tx *gorm.DB) error {
|
Migrate: func(tx *gorm.DB) error {
|
||||||
return tx.AutoMigrate(&model.Host{})
|
if err := tx.AutoMigrate(&model.Host{}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := tx.AutoMigrate(&model.Group{}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := tx.AutoMigrate(&model.Command{}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,8 @@ func Routers() *gin.Engine {
|
||||||
systemRouter.InitBaseRouter(PrivateGroup)
|
systemRouter.InitBaseRouter(PrivateGroup)
|
||||||
systemRouter.InitUserRouter(PrivateGroup)
|
systemRouter.InitUserRouter(PrivateGroup)
|
||||||
systemRouter.InitHostRouter(PrivateGroup)
|
systemRouter.InitHostRouter(PrivateGroup)
|
||||||
|
systemRouter.InitGroupRouter(PrivateGroup)
|
||||||
|
systemRouter.InitCommandRouter(PrivateGroup)
|
||||||
systemRouter.InitTerminalRouter(PrivateGroup)
|
systemRouter.InitTerminalRouter(PrivateGroup)
|
||||||
systemRouter.InitOperationLogRouter(PrivateGroup)
|
systemRouter.InitOperationLogRouter(PrivateGroup)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ type RouterGroup struct {
|
||||||
BaseRouter
|
BaseRouter
|
||||||
UserRouter
|
UserRouter
|
||||||
HostRouter
|
HostRouter
|
||||||
|
GroupRouter
|
||||||
|
CommandRouter
|
||||||
OperationLogRouter
|
OperationLogRouter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
package router
|
|
||||||
|
|
||||||
import (
|
|
||||||
v1 "github.com/1Panel-dev/1Panel/app/api/v1"
|
|
||||||
"github.com/1Panel-dev/1Panel/middleware"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
type GroupRouter struct{}
|
|
||||||
|
|
||||||
func (s *GroupRouter) InitGroupRouter(Router *gin.RouterGroup) {
|
|
||||||
userRouter := Router.Group("group")
|
|
||||||
userRouter.Use(middleware.JwtAuth()).Use(middleware.SessionAuth())
|
|
||||||
withRecordRouter := userRouter.Use(middleware.OperationRecord())
|
|
||||||
baseApi := v1.ApiGroupApp.BaseApi
|
|
||||||
{
|
|
||||||
withRecordRouter.POST("", baseApi.CreateGroup)
|
|
||||||
withRecordRouter.POST("/del", baseApi.DeleteGroup)
|
|
||||||
userRouter.GET("", baseApi.ListGroup)
|
|
||||||
userRouter.PUT(":id", baseApi.UpdateGroup)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,8 +17,8 @@ func (s *CommandRouter) InitCommandRouter(Router *gin.RouterGroup) {
|
||||||
{
|
{
|
||||||
withRecordRouter.POST("", baseApi.CreateCommand)
|
withRecordRouter.POST("", baseApi.CreateCommand)
|
||||||
withRecordRouter.POST("/del", baseApi.DeleteCommand)
|
withRecordRouter.POST("/del", baseApi.DeleteCommand)
|
||||||
|
withRecordRouter.PUT(":id", baseApi.UpdateCommand)
|
||||||
userRouter.POST("/search", baseApi.SearchCommand)
|
userRouter.POST("/search", baseApi.SearchCommand)
|
||||||
userRouter.GET("", baseApi.ListCommand)
|
userRouter.GET("", baseApi.ListCommand)
|
||||||
userRouter.PUT(":id", baseApi.UpdateCommand)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
23
backend/router/ro_group.go
Normal file
23
backend/router/ro_group.go
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
v1 "github.com/1Panel-dev/1Panel/app/api/v1"
|
||||||
|
"github.com/1Panel-dev/1Panel/middleware"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GroupRouter struct{}
|
||||||
|
|
||||||
|
func (s *GroupRouter) InitGroupRouter(Router *gin.RouterGroup) {
|
||||||
|
userRouter := Router.Group("groups").Use(middleware.JwtAuth()).Use(middleware.SessionAuth())
|
||||||
|
withRecordRouter := Router.Group("groups").Use(middleware.JwtAuth()).Use(middleware.SessionAuth()).Use(middleware.OperationRecord())
|
||||||
|
baseApi := v1.ApiGroupApp.BaseApi
|
||||||
|
{
|
||||||
|
withRecordRouter.POST("", baseApi.CreateGroup)
|
||||||
|
withRecordRouter.DELETE(":id", baseApi.DeleteGroup)
|
||||||
|
userRouter.POST("/search", baseApi.ListGroup)
|
||||||
|
userRouter.GET(":id", baseApi.GetGroupInfo)
|
||||||
|
userRouter.PUT(":id", baseApi.UpdateGroup)
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,14 +10,14 @@ import (
|
||||||
type HostRouter struct{}
|
type HostRouter struct{}
|
||||||
|
|
||||||
func (s *HostRouter) InitHostRouter(Router *gin.RouterGroup) {
|
func (s *HostRouter) InitHostRouter(Router *gin.RouterGroup) {
|
||||||
userRouter := Router.Group("hosts")
|
hostRouter := Router.Group("hosts").Use(middleware.JwtAuth()).Use(middleware.SessionAuth())
|
||||||
userRouter.Use(middleware.JwtAuth()).Use(middleware.SessionAuth())
|
withRecordRouter := Router.Group("hosts").Use(middleware.JwtAuth()).Use(middleware.SessionAuth()).Use(middleware.OperationRecord())
|
||||||
withRecordRouter := userRouter.Use(middleware.OperationRecord())
|
|
||||||
baseApi := v1.ApiGroupApp.BaseApi
|
baseApi := v1.ApiGroupApp.BaseApi
|
||||||
{
|
{
|
||||||
withRecordRouter.POST("", baseApi.CreateHost)
|
withRecordRouter.POST("", baseApi.CreateHost)
|
||||||
withRecordRouter.POST("/del", baseApi.DeleteHost)
|
withRecordRouter.DELETE(":id", baseApi.DeleteHost)
|
||||||
userRouter.POST("/search", baseApi.HostTree)
|
hostRouter.POST("/search", baseApi.HostTree)
|
||||||
userRouter.PUT(":id", baseApi.UpdateHost)
|
hostRouter.GET(":id", baseApi.GetHostInfo)
|
||||||
|
hostRouter.PUT(":id", baseApi.UpdateHost)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
17
frontend/src/api/interface/command.ts
Normal file
17
frontend/src/api/interface/command.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { ReqPage } from '.';
|
||||||
|
|
||||||
|
export namespace Command {
|
||||||
|
export interface CommandInfo {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
command: string;
|
||||||
|
}
|
||||||
|
export interface CommandOperate {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
command: string;
|
||||||
|
}
|
||||||
|
export interface CommandSearch extends ReqPage {
|
||||||
|
info: string;
|
||||||
|
}
|
||||||
|
}
|
15
frontend/src/api/interface/group.ts
Normal file
15
frontend/src/api/interface/group.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
export namespace Group {
|
||||||
|
export interface GroupInfo {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
export interface GroupOperate {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
export interface GroupSearch {
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,11 +2,17 @@ import { CommonModel } from '.';
|
||||||
|
|
||||||
export namespace Host {
|
export namespace Host {
|
||||||
export interface HostTree {
|
export interface HostTree {
|
||||||
|
id: number;
|
||||||
|
label: string;
|
||||||
|
children: Array<TreeNode>;
|
||||||
|
}
|
||||||
|
export interface TreeNode {
|
||||||
|
id: number;
|
||||||
label: string;
|
label: string;
|
||||||
children: Array<string>;
|
|
||||||
}
|
}
|
||||||
export interface Host extends CommonModel {
|
export interface Host extends CommonModel {
|
||||||
name: string;
|
name: string;
|
||||||
|
groupBelong: string;
|
||||||
addr: string;
|
addr: string;
|
||||||
port: number;
|
port: number;
|
||||||
user: string;
|
user: string;
|
||||||
|
@ -16,6 +22,7 @@ export namespace Host {
|
||||||
export interface HostOperate {
|
export interface HostOperate {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
|
groupBelong: string;
|
||||||
addr: string;
|
addr: string;
|
||||||
port: number;
|
port: number;
|
||||||
user: string;
|
user: string;
|
||||||
|
|
|
@ -12,7 +12,7 @@ export namespace User {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ReqGetUserParams extends ReqPage {
|
export interface ReqGetUserParams extends ReqPage {
|
||||||
name?: string;
|
info?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
24
frontend/src/api/modules/command.ts
Normal file
24
frontend/src/api/modules/command.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import http from '@/api';
|
||||||
|
import { ResPage } from '../interface';
|
||||||
|
import { Command } from '../interface/command';
|
||||||
|
|
||||||
|
export const getCommandList = () => {
|
||||||
|
return http.get<Array<Command.CommandInfo>>(`/commands`, {});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getCommandPage = (params: Command.CommandSearch) => {
|
||||||
|
return http.post<ResPage<Command.CommandInfo>>(`/commands/search`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addCommand = (params: Command.CommandOperate) => {
|
||||||
|
return http.post<Command.CommandOperate>(`/commands`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const editCommand = (params: Command.CommandOperate) => {
|
||||||
|
console.log(params.id);
|
||||||
|
return http.put(`/commands/${params.id}`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteCommand = (params: { ids: number[] }) => {
|
||||||
|
return http.post(`/commands/del`, params);
|
||||||
|
};
|
18
frontend/src/api/modules/group.ts
Normal file
18
frontend/src/api/modules/group.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import http from '@/api';
|
||||||
|
import { Group } from '../interface/group';
|
||||||
|
|
||||||
|
export const getGroupList = (params: Group.GroupSearch) => {
|
||||||
|
return http.post<Array<Group.GroupInfo>>(`/groups/search`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addGroup = (params: Group.GroupOperate) => {
|
||||||
|
return http.post<Group.GroupOperate>(`/groups`, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const editGroup = (params: Group.GroupOperate) => {
|
||||||
|
return http.put(`/groups/` + params.id, params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteGroup = (id: number) => {
|
||||||
|
return http.delete(`/groups/` + id);
|
||||||
|
};
|
|
@ -5,6 +5,10 @@ export const getHostList = (params: Host.ReqSearch) => {
|
||||||
return http.post<Array<Host.HostTree>>(`/hosts/search`, params);
|
return http.post<Array<Host.HostTree>>(`/hosts/search`, params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getHostInfo = (id: number) => {
|
||||||
|
return http.get<Host.Host>(`/hosts/` + id);
|
||||||
|
};
|
||||||
|
|
||||||
export const addHost = (params: Host.HostOperate) => {
|
export const addHost = (params: Host.HostOperate) => {
|
||||||
return http.post<Host.HostOperate>(`/hosts`, params);
|
return http.post<Host.HostOperate>(`/hosts`, params);
|
||||||
};
|
};
|
||||||
|
@ -14,6 +18,6 @@ export const editHost = (params: Host.HostOperate) => {
|
||||||
return http.put(`/hosts/` + params.id, params);
|
return http.put(`/hosts/` + params.id, params);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deleteHost = (params: { ids: number[] }) => {
|
export const deleteHost = (id: number) => {
|
||||||
return http.post(`/hosts/del`, params);
|
return http.delete(`/hosts/` + id);
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,11 +13,13 @@ export default {
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
name: '名称',
|
name: '名称',
|
||||||
|
group: '组',
|
||||||
createdAt: '创建时间',
|
createdAt: '创建时间',
|
||||||
date: '时间',
|
date: '时间',
|
||||||
updatedAt: '更新时间',
|
updatedAt: '更新时间',
|
||||||
operate: '操作',
|
operate: '操作',
|
||||||
message: '信息',
|
message: '信息',
|
||||||
|
description: '描述信息',
|
||||||
},
|
},
|
||||||
msg: {
|
msg: {
|
||||||
delete: '此操作不可回滚,是否继续',
|
delete: '此操作不可回滚,是否继续',
|
||||||
|
@ -94,6 +96,7 @@ export default {
|
||||||
conn: '连接',
|
conn: '连接',
|
||||||
hostList: '主机信息',
|
hostList: '主机信息',
|
||||||
quickCmd: '快捷命令',
|
quickCmd: '快捷命令',
|
||||||
|
command: '命令',
|
||||||
addHost: '添加主机',
|
addHost: '添加主机',
|
||||||
localhost: '本地服务器',
|
localhost: '本地服务器',
|
||||||
name: '名称',
|
name: '名称',
|
||||||
|
@ -110,6 +113,8 @@ export default {
|
||||||
detail: {
|
detail: {
|
||||||
users: '用户',
|
users: '用户',
|
||||||
hosts: '主机',
|
hosts: '主机',
|
||||||
|
groups: '组',
|
||||||
|
command: '快捷命令',
|
||||||
auth: '用户',
|
auth: '用户',
|
||||||
post: '创建',
|
post: '创建',
|
||||||
put: '更新',
|
put: '更新',
|
||||||
|
|
|
@ -92,7 +92,7 @@ const search = async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const fmtOperation = (row: ResOperationLog) => {
|
const fmtOperation = (row: ResOperationLog) => {
|
||||||
if (row.method.toLocaleLowerCase() !== 'put') {
|
if (row.method.toLocaleLowerCase() === 'post') {
|
||||||
if (row.source == '' && row.action == '') {
|
if (row.source == '' && row.action == '') {
|
||||||
return (
|
return (
|
||||||
i18n.global.t('operations.detail.' + row.group.toLocaleLowerCase()) +
|
i18n.global.t('operations.detail.' + row.group.toLocaleLowerCase()) +
|
||||||
|
@ -118,7 +118,6 @@ const fmtOperation = (row: ResOperationLog) => {
|
||||||
i18n.global.t('operations.detail.' + row.source.toLocaleLowerCase())
|
i18n.global.t('operations.detail.' + row.source.toLocaleLowerCase())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return '';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fmtBody = (value: string) => {
|
const fmtBody = (value: string) => {
|
||||||
|
|
154
frontend/src/views/terminal/command/index.vue
Normal file
154
frontend/src/views/terminal/command/index.vue
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<ComplexTable :pagination-config="paginationConfig" v-model:selects="selects" :data="data" @search="search">
|
||||||
|
<template #toolbar>
|
||||||
|
<el-button @click="onCreate()">{{ $t('commons.button.create') }}</el-button>
|
||||||
|
<el-button type="danger" plain :disabled="selects.length === 0" @click="batchDelete(null)">{{
|
||||||
|
$t('commons.button.delete')
|
||||||
|
}}</el-button>
|
||||||
|
</template>
|
||||||
|
<el-table-column type="selection" fix />
|
||||||
|
<el-table-column :label="$t('commons.table.name')" min-width="100" prop="name" fix />
|
||||||
|
<el-table-column :label="$t('terminal.command')" min-width="300" show-overflow-tooltip prop="command" />
|
||||||
|
<fu-table-operations type="icon" :buttons="buttons" :label="$t('commons.table.operate')" fix />
|
||||||
|
</ComplexTable>
|
||||||
|
|
||||||
|
<el-dialog v-model="cmdVisiable" :title="$t('terminal.addHost')" width="30%">
|
||||||
|
<el-form ref="commandInfoRef" label-width="100px" label-position="left" :model="commandInfo" :rules="rules">
|
||||||
|
<el-form-item :label="$t('commons.table.name')" prop="name">
|
||||||
|
<el-input clearable v-model="commandInfo.name" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('terminal.command')" prop="command">
|
||||||
|
<el-input type="textarea" clearable v-model="commandInfo.command" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="cmdVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="submitAddCommand(commandInfoRef)">
|
||||||
|
{{ $t('commons.button.confirm') }}
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import ComplexTable from '@/components/complex-table/index.vue';
|
||||||
|
import { Command } from '@/api/interface/command';
|
||||||
|
import { addCommand, editCommand, deleteCommand, getCommandPage } from '@/api/modules/command';
|
||||||
|
import { onMounted, reactive, ref } from '@vue/runtime-core';
|
||||||
|
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||||
|
import type { ElForm } from 'element-plus';
|
||||||
|
import { Rules } from '@/global/form-rues';
|
||||||
|
import i18n from '@/lang';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
|
||||||
|
const data = ref();
|
||||||
|
const selects = ref<any>([]);
|
||||||
|
const paginationConfig = reactive({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 5,
|
||||||
|
total: 0,
|
||||||
|
});
|
||||||
|
const commandSearch = reactive({
|
||||||
|
page: 1,
|
||||||
|
pageSize: 5,
|
||||||
|
info: '',
|
||||||
|
});
|
||||||
|
type FormInstance = InstanceType<typeof ElForm>;
|
||||||
|
const commandInfoRef = ref<FormInstance>();
|
||||||
|
const rules = reactive({
|
||||||
|
name: [Rules.requiredInput],
|
||||||
|
command: [Rules.requiredInput],
|
||||||
|
});
|
||||||
|
let operate = ref<string>('create');
|
||||||
|
|
||||||
|
let commandInfo = reactive<Command.CommandOperate>({
|
||||||
|
id: 0,
|
||||||
|
name: '',
|
||||||
|
command: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const cmdVisiable = ref<boolean>(false);
|
||||||
|
|
||||||
|
const onCreate = async () => {
|
||||||
|
restcommandForm();
|
||||||
|
operate.value = 'create';
|
||||||
|
cmdVisiable.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const submitAddCommand = (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return;
|
||||||
|
formEl.validate(async (valid) => {
|
||||||
|
if (!valid) return;
|
||||||
|
console.log(commandInfo.id);
|
||||||
|
if (operate.value === 'create') {
|
||||||
|
await addCommand(commandInfo);
|
||||||
|
} else {
|
||||||
|
await editCommand(commandInfo);
|
||||||
|
}
|
||||||
|
cmdVisiable.value = false;
|
||||||
|
search();
|
||||||
|
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onEdit = async (row: Command.CommandInfo | null) => {
|
||||||
|
if (row !== null) {
|
||||||
|
console.log(row.id);
|
||||||
|
// commandInfo.id = row.id;
|
||||||
|
// commandInfo.name = row.name;
|
||||||
|
// commandInfo.command = row.command;
|
||||||
|
// operate.value = 'edit';
|
||||||
|
// cmdVisiable.value = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const batchDelete = async (row: Command.CommandInfo | null) => {
|
||||||
|
let ids: Array<number> = [];
|
||||||
|
if (row === null) {
|
||||||
|
selects.value.forEach((item: Command.CommandInfo) => {
|
||||||
|
ids.push(item.id);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ids.push(row.id);
|
||||||
|
}
|
||||||
|
await useDeleteData(deleteCommand, { ids: ids }, 'commons.msg.delete');
|
||||||
|
search();
|
||||||
|
};
|
||||||
|
|
||||||
|
function restcommandForm() {
|
||||||
|
if (commandInfoRef.value) {
|
||||||
|
commandInfoRef.value.resetFields();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const buttons = [
|
||||||
|
{
|
||||||
|
label: i18n.global.t('commons.button.edit'),
|
||||||
|
icon: 'Edit',
|
||||||
|
click: onEdit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: i18n.global.t('commons.button.delete'),
|
||||||
|
icon: 'Delete',
|
||||||
|
click: batchDelete,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const search = async () => {
|
||||||
|
commandSearch.page = paginationConfig.page;
|
||||||
|
commandSearch.pageSize = paginationConfig.pageSize;
|
||||||
|
const res = await getCommandPage(commandSearch);
|
||||||
|
data.value = res.data.items;
|
||||||
|
for (const d of data.value) {
|
||||||
|
d.id = d.id + '';
|
||||||
|
}
|
||||||
|
paginationConfig.total = res.data.total;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
search();
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -2,22 +2,64 @@
|
||||||
<el-row style="margin: 20px; margin-left: 20px" class="row-box" :gutter="20">
|
<el-row style="margin: 20px; margin-left: 20px" class="row-box" :gutter="20">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-card class="el-card">
|
<el-card class="el-card">
|
||||||
<el-button icon="Plus" @click="readyForCreate" size="small" />
|
<el-tooltip class="box-item" effect="dark" content="创建连接" placement="top-start">
|
||||||
<el-button icon="FolderAdd" @click="(folderCreate = true), (newGroupName = '')" size="small" />
|
<el-button icon="Plus" @click="restHostForm" size="small" />
|
||||||
<el-button icon="Expand" @click="setTreeStatus(true)" size="small" />
|
</el-tooltip>
|
||||||
<el-button icon="Fold" @click="setTreeStatus(false)" size="small" />
|
<el-tooltip class="box-item" effect="dark" content="创建分组" placement="top-start">
|
||||||
<el-input size="small" @input="loadHost" clearable style="margin-top: 5px" v-model="searcConfig.info">
|
<el-button icon="FolderAdd" @click="onGroupCreate" size="small" />
|
||||||
<template #append><el-button icon="search" @click="loadHost" /></template>
|
</el-tooltip>
|
||||||
|
<el-tooltip class="box-item" effect="dark" content="展开" placement="top-start">
|
||||||
|
<el-button icon="Expand" @click="setTreeStatus(true)" size="small" />
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip class="box-item" effect="dark" content="收缩" placement="top-start">
|
||||||
|
<el-button icon="Fold" @click="setTreeStatus(false)" size="small" />
|
||||||
|
</el-tooltip>
|
||||||
|
<el-input
|
||||||
|
size="small"
|
||||||
|
@input="loadHostTree"
|
||||||
|
clearable
|
||||||
|
style="margin-top: 5px"
|
||||||
|
v-model="searcConfig.info"
|
||||||
|
>
|
||||||
|
<template #append><el-button icon="search" @click="loadHostTree" /></template>
|
||||||
</el-input>
|
</el-input>
|
||||||
<el-input size="small" v-if="folderCreate" clearable style="margin-top: 5px" v-model="newGroupName">
|
<el-input
|
||||||
|
size="small"
|
||||||
|
v-if="groupInputShow"
|
||||||
|
clearable
|
||||||
|
style="margin-top: 5px"
|
||||||
|
v-model="groupInputValue"
|
||||||
|
>
|
||||||
<template #append>
|
<template #append>
|
||||||
<el-button-group>
|
<el-button-group>
|
||||||
<el-button icon="Check" @click="loadHost" />
|
<el-button icon="Check" @click="onCreateGroup" />
|
||||||
<el-button icon="Close" @click="folderCreate = false" />
|
<el-button icon="Close" @click="groupInputShow = false" />
|
||||||
</el-button-group>
|
</el-button-group>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
<el-tree ref="tree" :default-expand-all="true" :data="hostTree" :props="defaultProps" />
|
<el-tree
|
||||||
|
ref="tree"
|
||||||
|
:expand-on-click-node="false"
|
||||||
|
node-key="id"
|
||||||
|
:default-expand-all="true"
|
||||||
|
:data="hostTree"
|
||||||
|
:props="defaultProps"
|
||||||
|
draggable
|
||||||
|
>
|
||||||
|
<template #default="{ node, data }">
|
||||||
|
<span class="custom-tree-node" @mouseover="hover = data.id" @mouseleave="hover = null">
|
||||||
|
<span>
|
||||||
|
<a @click="onEdit(node, data)">{{ node.label }}</a>
|
||||||
|
</span>
|
||||||
|
<el-button-group
|
||||||
|
v-if="!(node.level === 1 && data.label === 'default') && data.id === hover"
|
||||||
|
>
|
||||||
|
<el-button icon="Edit" size="small" @click="onEdit(node, data)" />
|
||||||
|
<el-button icon="Delete" size="small" @click="onDelete(node, data)" />
|
||||||
|
</el-button-group>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-tree>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="16">
|
<el-col :span="16">
|
||||||
|
@ -26,6 +68,11 @@
|
||||||
<el-form-item :label="$t('commons.table.name')" prop="name">
|
<el-form-item :label="$t('commons.table.name')" prop="name">
|
||||||
<el-input clearable v-model="hostInfo.name" />
|
<el-input clearable v-model="hostInfo.name" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('commons.table.group')" prop="groupBelong">
|
||||||
|
<el-select v-model="hostInfo.groupBelong" clearable style="width: 100%">
|
||||||
|
<el-option v-for="item in groupList" :key="item.id" :label="item.name" :value="item.name" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="IP" prop="addr">
|
<el-form-item label="IP" prop="addr">
|
||||||
<el-input clearable v-model="hostInfo.addr" />
|
<el-input clearable v-model="hostInfo.addr" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
@ -51,10 +98,19 @@
|
||||||
<el-form-item :label="$t('terminal.key')" v-if="hostInfo.authMode === 'key'" prop="privateKey">
|
<el-form-item :label="$t('terminal.key')" v-if="hostInfo.authMode === 'key'" prop="privateKey">
|
||||||
<el-input clearable type="textarea" v-model="hostInfo.privateKey" />
|
<el-input clearable type="textarea" v-model="hostInfo.privateKey" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('commons.table.description')" prop="description">
|
||||||
|
<el-input clearable type="textarea" v-model="hostInfo.description" />
|
||||||
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="submitAddHost(hostInfoRef)">
|
<el-button @click="restHostForm">
|
||||||
|
{{ $t('commons.button.reset') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button v-if="hostOperation === 'create'" type="primary" @click="submitAddHost(hostInfoRef)">
|
||||||
{{ $t('commons.button.create') }}
|
{{ $t('commons.button.create') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button v-if="hostOperation === 'edit'" type="primary" @click="submitAddHost(hostInfoRef)">
|
||||||
|
{{ $t('commons.button.confirm') }}
|
||||||
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
@ -67,14 +123,19 @@ import { ref, reactive, onMounted } from 'vue';
|
||||||
import type { ElForm } from 'element-plus';
|
import type { ElForm } from 'element-plus';
|
||||||
import { Rules } from '@/global/form-rues';
|
import { Rules } from '@/global/form-rues';
|
||||||
import { Host } from '@/api/interface/host';
|
import { Host } from '@/api/interface/host';
|
||||||
import { getHostList, addHost } from '@/api/modules/host';
|
import { Group } from '@/api/interface/group';
|
||||||
|
import { getHostList, getHostInfo, addHost, editHost, deleteHost } from '@/api/modules/host';
|
||||||
|
import { getGroupList, addGroup, editGroup, deleteGroup } from '@/api/modules/group';
|
||||||
|
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
|
import type Node from 'element-plus/es/components/tree/src/model/node';
|
||||||
|
|
||||||
type FormInstance = InstanceType<typeof ElForm>;
|
type FormInstance = InstanceType<typeof ElForm>;
|
||||||
const hostInfoRef = ref<FormInstance>();
|
const hostInfoRef = ref<FormInstance>();
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
name: [Rules.requiredInput, Rules.name],
|
name: [Rules.requiredInput, Rules.name],
|
||||||
|
group: [Rules.requiredSelect],
|
||||||
addr: [Rules.requiredInput, Rules.ip],
|
addr: [Rules.requiredInput, Rules.ip],
|
||||||
port: [Rules.requiredInput, Rules.port],
|
port: [Rules.requiredInput, Rules.port],
|
||||||
user: [Rules.requiredInput],
|
user: [Rules.requiredInput],
|
||||||
|
@ -82,10 +143,11 @@ const rules = reactive({
|
||||||
password: [Rules.requiredInput],
|
password: [Rules.requiredInput],
|
||||||
privateKey: [Rules.requiredInput],
|
privateKey: [Rules.requiredInput],
|
||||||
});
|
});
|
||||||
|
let hostOperation = ref<string>('create');
|
||||||
let hostInfo = reactive<Host.HostOperate>({
|
let hostInfo = reactive<Host.HostOperate>({
|
||||||
id: 0,
|
id: 0,
|
||||||
name: '',
|
name: '',
|
||||||
|
groupBelong: 'default',
|
||||||
addr: '',
|
addr: '',
|
||||||
port: 22,
|
port: 22,
|
||||||
user: '',
|
user: '',
|
||||||
|
@ -95,30 +157,47 @@ let hostInfo = reactive<Host.HostOperate>({
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
interface Tree {
|
||||||
|
id: number;
|
||||||
|
label: string;
|
||||||
|
children?: Tree[];
|
||||||
|
}
|
||||||
|
|
||||||
let searcConfig = reactive<Host.ReqSearch>({
|
let searcConfig = reactive<Host.ReqSearch>({
|
||||||
info: '',
|
info: '',
|
||||||
});
|
});
|
||||||
const tree = ref<any>(null);
|
const tree = ref<any>(null);
|
||||||
|
const hover = ref();
|
||||||
const hostTree = ref<Array<Host.HostTree>>();
|
const hostTree = ref<Array<Host.HostTree>>();
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
children: 'children',
|
|
||||||
label: 'label',
|
label: 'label',
|
||||||
|
children: 'children',
|
||||||
};
|
};
|
||||||
const newGroupName = ref();
|
|
||||||
const folderCreate = ref<boolean>(false);
|
|
||||||
|
|
||||||
const loadHost = async () => {
|
const groupList = ref<Array<Group.GroupInfo>>();
|
||||||
|
|
||||||
|
let groupInputValue = ref();
|
||||||
|
let currentGroupID = ref();
|
||||||
|
let groupOperation = ref<string>('create');
|
||||||
|
let groupInputShow = ref<boolean>(false);
|
||||||
|
|
||||||
|
const loadHostTree = async () => {
|
||||||
const res = await getHostList(searcConfig);
|
const res = await getHostList(searcConfig);
|
||||||
hostTree.value = res.data;
|
hostTree.value = res.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const loadGroups = async () => {
|
||||||
|
const res = await getGroupList({ type: 'host' });
|
||||||
|
groupList.value = res.data;
|
||||||
|
};
|
||||||
|
|
||||||
function setTreeStatus(expend: boolean) {
|
function setTreeStatus(expend: boolean) {
|
||||||
for (let i = 0; i < tree.value.store._getAllNodes().length; i++) {
|
for (let i = 0; i < tree.value.store._getAllNodes().length; i++) {
|
||||||
tree.value.store._getAllNodes()[i].expanded = expend;
|
tree.value.store._getAllNodes()[i].expanded = expend;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function readyForCreate() {
|
function restHostForm() {
|
||||||
if (hostInfoRef.value) {
|
if (hostInfoRef.value) {
|
||||||
hostInfoRef.value.resetFields();
|
hostInfoRef.value.resetFields();
|
||||||
}
|
}
|
||||||
|
@ -128,17 +207,92 @@ const submitAddHost = (formEl: FormInstance | undefined) => {
|
||||||
if (!formEl) return;
|
if (!formEl) return;
|
||||||
formEl.validate(async (valid) => {
|
formEl.validate(async (valid) => {
|
||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
try {
|
if (hostOperation.value === 'create') {
|
||||||
await addHost(hostInfo);
|
await addHost(hostInfo);
|
||||||
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
} else {
|
||||||
// loadHost();
|
await editHost(hostInfo);
|
||||||
} catch (error) {
|
|
||||||
ElMessage.success(i18n.global.t('commons.msg.loginSuccess') + ':' + error);
|
|
||||||
}
|
}
|
||||||
|
restHostForm();
|
||||||
|
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
|
loadHostTree();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onGroupCreate = () => {
|
||||||
|
groupInputShow.value = true;
|
||||||
|
groupInputValue.value = '';
|
||||||
|
groupOperation.value = 'create';
|
||||||
|
};
|
||||||
|
const onCreateGroup = async () => {
|
||||||
|
console.log(groupOperation.value);
|
||||||
|
if (groupOperation.value === 'create') {
|
||||||
|
let group = { id: 0, name: groupInputValue.value, type: 'host' };
|
||||||
|
await addGroup(group);
|
||||||
|
groupOperation.value = '';
|
||||||
|
groupInputShow.value = false;
|
||||||
|
} else {
|
||||||
|
let group = { id: currentGroupID.value, name: groupInputValue.value, type: 'host' };
|
||||||
|
await editGroup(group);
|
||||||
|
}
|
||||||
|
ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
|
||||||
|
groupOperation.value = '';
|
||||||
|
groupInputShow.value = false;
|
||||||
|
loadHostTree();
|
||||||
|
loadGroups();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDelete = async (node: Node, data: Tree) => {
|
||||||
|
if (node.level === 1 && data.label === 'default') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (node.level === 1) {
|
||||||
|
await useDeleteData(deleteGroup, data.id - 10000, '移除组后,组内所有连接将迁移到 default 组内,是否确认?');
|
||||||
|
loadGroups();
|
||||||
|
} else {
|
||||||
|
await useDeleteData(deleteHost, data.id, 'commons.msg.delete');
|
||||||
|
}
|
||||||
|
loadHostTree();
|
||||||
|
loadGroups();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onEdit = async (node: Node, data: Tree) => {
|
||||||
|
if (node.level === 1 && data.label === 'default') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(node.level === 1);
|
||||||
|
if (node.level === 1) {
|
||||||
|
groupInputShow.value = true;
|
||||||
|
groupInputValue.value = data.label;
|
||||||
|
currentGroupID.value = data.id - 10000;
|
||||||
|
groupOperation.value = 'edit';
|
||||||
|
console.log(groupOperation.value);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
const res = await getHostInfo(data.id);
|
||||||
|
hostInfo.id = res.data.id;
|
||||||
|
hostInfo.name = res.data.name;
|
||||||
|
hostInfo.groupBelong = res.data.groupBelong;
|
||||||
|
hostInfo.addr = res.data.addr;
|
||||||
|
hostInfo.port = res.data.port;
|
||||||
|
hostInfo.user = res.data.user;
|
||||||
|
hostInfo.description = res.data.description;
|
||||||
|
hostOperation.value = 'edit';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadHost();
|
loadHostTree();
|
||||||
|
loadGroups();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.custom-tree-node {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
Loading…
Add table
Reference in a new issue