mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-03-15 02:04:46 +08:00
fix: 解决容器终端连接失败的问题
This commit is contained in:
parent
95a5db141f
commit
b7324d14dc
@ -1,16 +1,10 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||||
"github.com/1Panel-dev/1Panel/backend/global"
|
"github.com/1Panel-dev/1Panel/backend/global"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/terminal"
|
|
||||||
"github.com/docker/docker/api/types"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -231,63 +225,6 @@ func (b *BaseApi) Inspect(c *gin.Context) {
|
|||||||
helper.SuccessWithData(c, result)
|
helper.SuccessWithData(c, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BaseApi) ContainerExec(c *gin.Context) {
|
|
||||||
containerID := c.Query("containerid")
|
|
||||||
command := c.Query("command")
|
|
||||||
user := c.Query("user")
|
|
||||||
cols, err := strconv.Atoi(c.DefaultQuery("cols", "80"))
|
|
||||||
if err != nil {
|
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rows, err := strconv.Atoi(c.DefaultQuery("rows", "40"))
|
|
||||||
if err != nil {
|
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
|
||||||
if err != nil {
|
|
||||||
global.LOG.Errorf("gin context http handler failed, err: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer wsConn.Close()
|
|
||||||
|
|
||||||
client, err := docker.NewDockerClient()
|
|
||||||
if wshandleError(wsConn, errors.WithMessage(err, "New docker client failed.")) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
conf := types.ExecConfig{Tty: true, Cmd: []string{command}, AttachStderr: true, AttachStdin: true, AttachStdout: true}
|
|
||||||
if len(user) != 0 {
|
|
||||||
conf.User = user
|
|
||||||
}
|
|
||||||
ir, err := client.ContainerExecCreate(context.TODO(), containerID, conf)
|
|
||||||
if wshandleError(wsConn, errors.WithMessage(err, "failed to set exec conf.")) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
hr, err := client.ContainerExecAttach(c, ir.ID, types.ExecStartCheck{Detach: false, Tty: true})
|
|
||||||
if wshandleError(wsConn, errors.WithMessage(err, "failed to set up the connection.")) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer hr.Close()
|
|
||||||
|
|
||||||
sws, err := terminal.NewExecConn(cols, rows, wsConn, hr.Conn)
|
|
||||||
if wshandleError(wsConn, err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
quitChan := make(chan bool, 3)
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
sws.Start(ctx, quitChan)
|
|
||||||
<-quitChan
|
|
||||||
cancel()
|
|
||||||
|
|
||||||
if wshandleError(wsConn, err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Tags Container
|
// @Tags Container
|
||||||
// @Summary Container logs
|
// @Summary Container logs
|
||||||
// @Description 容器日志
|
// @Description 容器日志
|
||||||
|
@ -2,21 +2,15 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
|
||||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||||
"github.com/1Panel-dev/1Panel/backend/constant"
|
"github.com/1Panel-dev/1Panel/backend/constant"
|
||||||
"github.com/1Panel-dev/1Panel/backend/global"
|
"github.com/1Panel-dev/1Panel/backend/global"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/compose"
|
"github.com/1Panel-dev/1Panel/backend/utils/compose"
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/docker"
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/utils/terminal"
|
|
||||||
"github.com/docker/docker/api/types"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Tags Database Redis
|
// @Tags Database Redis
|
||||||
@ -253,64 +247,3 @@ func (b *BaseApi) UpdateRedisConfByFile(c *gin.Context) {
|
|||||||
|
|
||||||
helper.SuccessWithData(c, nil)
|
helper.SuccessWithData(c, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BaseApi) RedisExec(c *gin.Context) {
|
|
||||||
redisConf, err := redisService.LoadConf()
|
|
||||||
if err != nil {
|
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cols, err := strconv.Atoi(c.DefaultQuery("cols", "80"))
|
|
||||||
if err != nil {
|
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rows, err := strconv.Atoi(c.DefaultQuery("rows", "40"))
|
|
||||||
if err != nil {
|
|
||||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
|
||||||
if err != nil {
|
|
||||||
global.LOG.Errorf("gin context http handler failed, err: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer wsConn.Close()
|
|
||||||
|
|
||||||
client, err := docker.NewDockerClient()
|
|
||||||
if wshandleError(wsConn, errors.WithMessage(err, "New docker client failed.")) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
auth := "redis-cli"
|
|
||||||
if len(redisConf.Requirepass) != 0 {
|
|
||||||
auth = fmt.Sprintf("redis-cli -a %s --no-auth-warning", redisConf.Requirepass)
|
|
||||||
}
|
|
||||||
conf := types.ExecConfig{Tty: true, Cmd: []string{"bash"}, AttachStderr: true, AttachStdin: true, AttachStdout: true, User: "root"}
|
|
||||||
ir, err := client.ContainerExecCreate(context.TODO(), redisConf.ContainerName, conf)
|
|
||||||
if wshandleError(wsConn, errors.WithMessage(err, "failed to set exec conf.")) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
hr, err := client.ContainerExecAttach(c, ir.ID, types.ExecStartCheck{Detach: false, Tty: true})
|
|
||||||
if wshandleError(wsConn, errors.WithMessage(err, "failed to set up the connection.")) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer hr.Close()
|
|
||||||
|
|
||||||
sws, err := terminal.NewExecConn(cols, rows, wsConn, hr.Conn, auth)
|
|
||||||
if wshandleError(wsConn, err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
quitChan := make(chan bool, 3)
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
sws.Start(ctx, quitChan)
|
|
||||||
<-quitChan
|
|
||||||
cancel()
|
|
||||||
|
|
||||||
if wshandleError(wsConn, err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -103,11 +103,63 @@ func (b *BaseApi) RedisWsSsh(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer wsConn.Close()
|
defer wsConn.Close()
|
||||||
auth := ""
|
commands := fmt.Sprintf("docker exec -it %s redis-cli", redisConf.ContainerName)
|
||||||
if len(redisConf.Requirepass) != 0 {
|
if len(redisConf.Requirepass) != 0 {
|
||||||
auth = fmt.Sprintf("-a %s --no-auth-warning", redisConf.Requirepass)
|
commands = fmt.Sprintf("docker exec -it %s redis-cli -a %s --no-auth-warning", redisConf.ContainerName, redisConf.Requirepass)
|
||||||
}
|
}
|
||||||
slave, err := terminal.NewCommand(redisConf.ContainerName, auth)
|
slave, err := terminal.NewCommand(commands)
|
||||||
|
if wshandleError(wsConn, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer slave.Close()
|
||||||
|
|
||||||
|
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave)
|
||||||
|
if wshandleError(wsConn, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
quitChan := make(chan bool, 3)
|
||||||
|
tty.Start(quitChan)
|
||||||
|
go slave.Wait(quitChan)
|
||||||
|
|
||||||
|
<-quitChan
|
||||||
|
|
||||||
|
global.LOG.Info("websocket finished")
|
||||||
|
if wshandleError(wsConn, err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseApi) ContainerWsSsh(c *gin.Context) {
|
||||||
|
containerID := c.Query("containerid")
|
||||||
|
command := c.Query("command")
|
||||||
|
user := c.Query("user")
|
||||||
|
if len(command) == 0 || len(containerID) == 0 {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error param of command or containerID"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cols, err := strconv.Atoi(c.DefaultQuery("cols", "80"))
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rows, err := strconv.Atoi(c.DefaultQuery("rows", "40"))
|
||||||
|
if err != nil {
|
||||||
|
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
|
||||||
|
if err != nil {
|
||||||
|
global.LOG.Errorf("gin context http handler failed, err: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer wsConn.Close()
|
||||||
|
commands := fmt.Sprintf("docker exec -it %s %s", containerID, command)
|
||||||
|
if len(user) != 0 {
|
||||||
|
commands = fmt.Sprintf("docker exec -it -u %s %s %s", user, containerID, command)
|
||||||
|
}
|
||||||
|
slave, err := terminal.NewCommand(commands)
|
||||||
if wshandleError(wsConn, err) {
|
if wshandleError(wsConn, err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -92,10 +92,7 @@ func (u *HostService) SearchForTree(search dto.SearchForTree) ([]dto.HostTree, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *HostService) Create(req dto.HostOperate) (*dto.HostInfo, error) {
|
func (u *HostService) Create(req dto.HostOperate) (*dto.HostInfo, error) {
|
||||||
host, _ := hostRepo.Get(hostRepo.WithByAddr(req.Addr))
|
var host model.Host
|
||||||
if host.ID != 0 {
|
|
||||||
return nil, constant.ErrRecordExist
|
|
||||||
}
|
|
||||||
if err := copier.Copy(&host, &req); err != nil {
|
if err := copier.Copy(&host, &req); err != nil {
|
||||||
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
|
||||||
}
|
}
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
package terminal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/1Panel-dev/1Panel/backend/global"
|
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ExecWsSession struct {
|
|
||||||
conn net.Conn
|
|
||||||
wsConn *websocket.Conn
|
|
||||||
|
|
||||||
writeMutex sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewExecConn(cols, rows int, wsConn *websocket.Conn, hijacked net.Conn, commands ...string) (*ExecWsSession, error) {
|
|
||||||
_, _ = hijacked.Write([]byte(fmt.Sprintf("stty cols %d rows %d && clear \r", cols, rows)))
|
|
||||||
for _, command := range commands {
|
|
||||||
_, _ = hijacked.Write([]byte(fmt.Sprintf("%s \r", command)))
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ExecWsSession{
|
|
||||||
conn: hijacked,
|
|
||||||
wsConn: wsConn,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sws *ExecWsSession) Start(ctx context.Context, quitChan chan bool) {
|
|
||||||
go sws.handleSlaveEvent(ctx, quitChan)
|
|
||||||
go sws.receiveWsMsg(ctx, quitChan)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sws *ExecWsSession) handleSlaveEvent(ctx context.Context, exitCh chan bool) {
|
|
||||||
defer setQuit(exitCh)
|
|
||||||
|
|
||||||
buffer := make([]byte, 1024)
|
|
||||||
for {
|
|
||||||
n, err := sws.conn.Read(buffer)
|
|
||||||
if err != nil && errors.Is(err, net.ErrClosed) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := sws.masterWrite(buffer[:n]); err != nil {
|
|
||||||
if errors.Is(err, websocket.ErrCloseSent) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sws *ExecWsSession) masterWrite(data []byte) error {
|
|
||||||
sws.writeMutex.Lock()
|
|
||||||
defer sws.writeMutex.Unlock()
|
|
||||||
err := sws.wsConn.WriteMessage(websocket.TextMessage, data)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to write to master")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sws *ExecWsSession) receiveWsMsg(ctx context.Context, exitCh chan bool) {
|
|
||||||
wsConn := sws.wsConn
|
|
||||||
defer setQuit(exitCh)
|
|
||||||
for {
|
|
||||||
_, wsData, err := wsConn.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
msgObj := wsMsg{}
|
|
||||||
_ = json.Unmarshal(wsData, &msgObj)
|
|
||||||
switch msgObj.Type {
|
|
||||||
case wsMsgResize:
|
|
||||||
if msgObj.Cols > 0 && msgObj.Rows > 0 {
|
|
||||||
sws.ResizeTerminal(msgObj.Rows, msgObj.Cols)
|
|
||||||
}
|
|
||||||
case wsMsgCmd:
|
|
||||||
decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
|
||||||
if err != nil {
|
|
||||||
global.LOG.Errorf("websock cmd string base64 decoding failed, err: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sws.sendWebsocketInputCommandToSshSessionStdinPipe(decodeBytes)
|
|
||||||
case wsMsgClose:
|
|
||||||
_, _ = sws.conn.Write([]byte("exit\r"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sws *ExecWsSession) sendWebsocketInputCommandToSshSessionStdinPipe(cmdBytes []byte) {
|
|
||||||
_, _ = sws.conn.Write(cmdBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sws *ExecWsSession) ResizeTerminal(rows int, cols int) {
|
|
||||||
_, _ = sws.conn.Write([]byte(fmt.Sprintf("stty cols %d rows %d && clear \r", cols, rows)))
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
package terminal
|
package terminal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"syscall"
|
"syscall"
|
||||||
@ -27,8 +26,8 @@ type LocalCommand struct {
|
|||||||
ptyClosed chan struct{}
|
ptyClosed chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCommand(containerName string, auth string) (*LocalCommand, error) {
|
func NewCommand(commands string) (*LocalCommand, error) {
|
||||||
cmd := exec.Command("sh", "-c", fmt.Sprintf("docker exec -it %s redis-cli %s", containerName, auth))
|
cmd := exec.Command("sh", "-c", commands)
|
||||||
|
|
||||||
pty, err := pty.Start(cmd)
|
pty, err := pty.Start(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -35,6 +35,7 @@ func (sws *LocalWsSession) Start(quitChan chan bool) {
|
|||||||
|
|
||||||
func (sws *LocalWsSession) handleSlaveEvent(exitCh chan bool) {
|
func (sws *LocalWsSession) handleSlaveEvent(exitCh chan bool) {
|
||||||
defer setQuit(exitCh)
|
defer setQuit(exitCh)
|
||||||
|
defer global.LOG.Debug("thread of handle slave event has exited now")
|
||||||
|
|
||||||
buffer := make([]byte, 1024)
|
buffer := make([]byte, 1024)
|
||||||
for {
|
for {
|
||||||
@ -62,6 +63,7 @@ func (sws *LocalWsSession) masterWrite(data []byte) error {
|
|||||||
func (sws *LocalWsSession) receiveWsMsg(exitCh chan bool) {
|
func (sws *LocalWsSession) receiveWsMsg(exitCh chan bool) {
|
||||||
wsConn := sws.wsConn
|
wsConn := sws.wsConn
|
||||||
defer setQuit(exitCh)
|
defer setQuit(exitCh)
|
||||||
|
defer global.LOG.Debug("thread of receive ws msg has exited now")
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-exitCh:
|
case <-exitCh:
|
||||||
|
@ -37,7 +37,6 @@ func (w *safeBuffer) Reset() {
|
|||||||
const (
|
const (
|
||||||
wsMsgCmd = "cmd"
|
wsMsgCmd = "cmd"
|
||||||
wsMsgResize = "resize"
|
wsMsgResize = "resize"
|
||||||
wsMsgClose = "close"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type wsMsg struct {
|
type wsMsg struct {
|
||||||
|
@ -34,11 +34,11 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-button type="primary" v-if="!terminalOpen" @click="initTerm(formRef)">
|
<el-button v-if="!terminalOpen" @click="initTerm(formRef)">
|
||||||
{{ $t('commons.button.conn') }}
|
{{ $t('commons.button.conn') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" v-else @click="handleClose()">{{ $t('commons.button.disconn') }}</el-button>
|
<el-button v-else @click="handleClose()">{{ $t('commons.button.disconn') }}</el-button>
|
||||||
<div style="height: calc(100vh - 290px)" :id="'terminal-exec'"></div>
|
<div style="height: calc(100vh - 302px)" :id="'terminal-exec'"></div>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
@ -180,13 +180,13 @@ const isWsOpen = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function handleClose() {
|
function handleClose() {
|
||||||
terminalVisiable.value = false;
|
|
||||||
terminalOpen.value = false;
|
|
||||||
window.removeEventListener('resize', changeTerminalSize);
|
window.removeEventListener('resize', changeTerminalSize);
|
||||||
if (isWsOpen()) {
|
if (isWsOpen()) {
|
||||||
terminalSocket && terminalSocket.close();
|
terminalSocket && terminalSocket.close();
|
||||||
term.dispose();
|
term.dispose();
|
||||||
}
|
}
|
||||||
|
terminalVisiable.value = false;
|
||||||
|
terminalOpen.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeTerminalSize() {
|
function changeTerminalSize() {
|
||||||
|
@ -60,7 +60,7 @@ onUnmounted(() => {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.router_card {
|
.router_card {
|
||||||
--el-card-border-radius: 8px;
|
--el-card-border-radius: 8px;
|
||||||
--el-card-padding: 0;
|
--el-card-padding: 0 !important;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
padding-bottom: 2px;
|
padding-bottom: 2px;
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
|
@ -154,7 +154,8 @@ const submitAddHost = (formEl: FormInstance | undefined, ops: string) => {
|
|||||||
if (res.data.name.length !== 0) {
|
if (res.data.name.length !== 0) {
|
||||||
title = res.data.name + '-' + title;
|
title = res.data.name + '-' + title;
|
||||||
}
|
}
|
||||||
emit('on-conn-terminal', title, res.data.id, false);
|
let isLocal = hostInfo.addr === '127.0.0.1';
|
||||||
|
emit('on-conn-terminal', title, res.data.id, isLocal);
|
||||||
emit('load-host-tree');
|
emit('load-host-tree');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
style="background-color: #efefef; margin-top: 20px"
|
style="background-color: #efefef; margin-top: 20px"
|
||||||
v-model="terminalValue"
|
v-model="terminalValue"
|
||||||
:before-leave="beforeLeave"
|
:before-leave="beforeLeave"
|
||||||
|
@tab-change="quickCmd = ''"
|
||||||
@edit="handleTabsRemove"
|
@edit="handleTabsRemove"
|
||||||
>
|
>
|
||||||
<el-tab-pane
|
<el-tab-pane
|
||||||
@ -305,19 +306,16 @@ const onConnTerminal = async (title: string, wsID: number, isLocal?: boolean) =>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log('走到了这里');
|
|
||||||
terminalTabs.value.push({
|
terminalTabs.value.push({
|
||||||
index: tabIndex,
|
index: tabIndex,
|
||||||
title: title,
|
title: title,
|
||||||
wsID: wsID,
|
wsID: wsID,
|
||||||
status: res.data ? 'online' : 'closed',
|
status: res.data ? 'online' : 'closed',
|
||||||
});
|
});
|
||||||
console.log(terminalTabs.value);
|
|
||||||
terminalValue.value = tabIndex;
|
terminalValue.value = tabIndex;
|
||||||
if (!res.data && isLocal) {
|
if (!res.data && isLocal) {
|
||||||
dialogRef.value!.acceptParams({ isLocal: true });
|
dialogRef.value!.acceptParams({ isLocal: true });
|
||||||
}
|
}
|
||||||
console.log(terminalValue.value);
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
ctx.refs[`t-${terminalValue.value}`] &&
|
ctx.refs[`t-${terminalValue.value}`] &&
|
||||||
ctx.refs[`t-${terminalValue.value}`][0].acceptParams({
|
ctx.refs[`t-${terminalValue.value}`][0].acceptParams({
|
||||||
|
Loading…
x
Reference in New Issue
Block a user