🔨 sftp 表格.
This commit is contained in:
@@ -1,14 +1,14 @@
|
|||||||
spring:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
druid:
|
druid:
|
||||||
url: jdbc:mysql://127.0.0.1:3306/orion-ops-pro?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true
|
url: jdbc:mysql://116.62.194.246:3306/orion-ops-pro?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai&autoReconnect=true
|
||||||
username: root
|
username: root
|
||||||
password: Data@123456
|
password: Data@123456
|
||||||
initial-size: 0
|
initial-size: 0
|
||||||
min-idle: 1
|
min-idle: 1
|
||||||
max-active: 5
|
max-active: 5
|
||||||
redis:
|
redis:
|
||||||
host: 127.0.0.1
|
host: 116.62.194.246
|
||||||
port: 6379
|
port: 6379
|
||||||
database: 0
|
database: 0
|
||||||
password: lijiahang
|
password: lijiahang
|
||||||
|
|||||||
@@ -3,10 +3,7 @@ package com.orion.ops.module.asset.handler.host.terminal.enums;
|
|||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.handler.*;
|
import com.orion.ops.module.asset.handler.host.terminal.handler.*;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.model.request.TerminalCheckRequest;
|
import com.orion.ops.module.asset.handler.host.terminal.model.request.*;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.model.request.TerminalConnectRequest;
|
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.model.request.TerminalInputRequest;
|
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.model.request.TerminalResizeRequest;
|
|
||||||
import com.orion.spring.SpringHolder;
|
import com.orion.spring.SpringHolder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -55,27 +52,46 @@ public enum InputTypeEnum {
|
|||||||
TerminalBasePayload.class),
|
TerminalBasePayload.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改大小
|
* SSH 修改大小
|
||||||
*/
|
*/
|
||||||
RESIZE("rs",
|
SSH_RESIZE("rs",
|
||||||
TerminalResizeHandler.class,
|
SshResizeHandler.class,
|
||||||
new String[]{"type", "sessionId", "cols", "rows"},
|
new String[]{"type", "sessionId", "cols", "rows"},
|
||||||
TerminalResizeRequest.class),
|
SshResizeRequest.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输入
|
* SSH 输入
|
||||||
*/
|
*/
|
||||||
INPUT("i",
|
SSH_INPUT("i",
|
||||||
TerminalInputHandler.class,
|
SshInputHandler.class,
|
||||||
new String[]{"type", "sessionId", "command"},
|
new String[]{"type", "sessionId", "command"},
|
||||||
TerminalInputRequest.class),
|
SshInputRequest.class),
|
||||||
|
|
||||||
// LS
|
/**
|
||||||
// MK
|
* SFTP 文件列表
|
||||||
// RM
|
*/
|
||||||
// MV
|
SFTP_LIST("ls",
|
||||||
// TC
|
SftpListHandler.class,
|
||||||
// CD
|
new String[]{"type", "sessionId", "path"},
|
||||||
|
SftpListRequest.class),
|
||||||
|
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// MKDIR
|
||||||
|
// TOUCH
|
||||||
|
|
||||||
|
// REMOVE
|
||||||
|
// MOVE
|
||||||
|
// TRUNCATE
|
||||||
|
|
||||||
|
// CHMOD
|
||||||
|
|
||||||
|
// GET
|
||||||
|
// SAVE
|
||||||
|
|
||||||
|
// COPY
|
||||||
|
// UPLOAD
|
||||||
|
// DOWNLOAD
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -36,9 +36,14 @@ public enum OutputTypeEnum {
|
|||||||
PONG("p", "${type}"),
|
PONG("p", "${type}"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输出
|
* SSH 输出
|
||||||
*/
|
*/
|
||||||
OUTPUT("o", "${type}|${sessionId}|${body}"),
|
SSH_OUTPUT("o", "${type}|${sessionId}|${body}"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SFTP 文件列表
|
||||||
|
*/
|
||||||
|
SFTP_LIST("ls", "${type}|${sessionId}|${result}|${path}|${body}"),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package com.orion.ops.module.asset.handler.host.terminal.handler;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.orion.lang.utils.Strings;
|
||||||
|
import com.orion.ops.framework.common.enums.BooleanBit;
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager;
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.model.request.SftpListRequest;
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpFileResponse;
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpListResponse;
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.session.ISftpSession;
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.session.ITerminalSession;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sftp 文件列表
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2023/12/29 15:32
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class SftpListHandler extends AbstractTerminalHandler<SftpListRequest> {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TerminalManager terminalManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(WebSocketSession channel, SftpListRequest payload) {
|
||||||
|
// 获取会话
|
||||||
|
ITerminalSession session = terminalManager.getSession(channel.getId(), payload.getSessionId());
|
||||||
|
String path = payload.getPath();
|
||||||
|
log.info("SftpListHandler-handle session: {}, path: {}", payload.getSessionId(), path);
|
||||||
|
if (session instanceof ISftpSession) {
|
||||||
|
Exception ex = null;
|
||||||
|
List<SftpFileResponse> list = null;
|
||||||
|
try {
|
||||||
|
// 空目录则直接获取 home 目录
|
||||||
|
if (Strings.isBlank(path)) {
|
||||||
|
path = ((ISftpSession) session).getHome();
|
||||||
|
}
|
||||||
|
// 文件列表
|
||||||
|
list = ((ISftpSession) session).list(path);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("SftpListHandler-handle error", e);
|
||||||
|
ex = e;
|
||||||
|
}
|
||||||
|
// 返回
|
||||||
|
this.send(channel,
|
||||||
|
OutputTypeEnum.SFTP_LIST,
|
||||||
|
SftpListResponse.builder()
|
||||||
|
.sessionId(payload.getSessionId())
|
||||||
|
.result(BooleanBit.of(ex == null).getValue())
|
||||||
|
.path(path)
|
||||||
|
.body(list == null ? null : JSON.toJSONString(list))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.orion.ops.module.asset.handler.host.terminal.handler;
|
package com.orion.ops.module.asset.handler.host.terminal.handler;
|
||||||
|
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager;
|
import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.model.request.TerminalInputRequest;
|
import com.orion.ops.module.asset.handler.host.terminal.model.request.SshInputRequest;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.session.ISshSession;
|
import com.orion.ops.module.asset.handler.host.terminal.session.ISshSession;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.session.ITerminalSession;
|
import com.orion.ops.module.asset.handler.host.terminal.session.ITerminalSession;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -11,7 +11,7 @@ import org.springframework.web.socket.WebSocketSession;
|
|||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理输入处理器
|
* ssh 处理输入处理器
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@@ -19,13 +19,13 @@ import javax.annotation.Resource;
|
|||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class TerminalInputHandler extends AbstractTerminalHandler<TerminalInputRequest> {
|
public class SshInputHandler extends AbstractTerminalHandler<SshInputRequest> {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private TerminalManager terminalManager;
|
private TerminalManager terminalManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(WebSocketSession channel, TerminalInputRequest payload) {
|
public void handle(WebSocketSession channel, SshInputRequest payload) {
|
||||||
// 获取会话
|
// 获取会话
|
||||||
ITerminalSession session = terminalManager.getSession(channel.getId(), payload.getSessionId());
|
ITerminalSession session = terminalManager.getSession(channel.getId(), payload.getSessionId());
|
||||||
if (session instanceof ISshSession) {
|
if (session instanceof ISshSession) {
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.orion.ops.module.asset.handler.host.terminal.handler;
|
package com.orion.ops.module.asset.handler.host.terminal.handler;
|
||||||
|
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager;
|
import com.orion.ops.module.asset.handler.host.terminal.manager.TerminalManager;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.model.request.TerminalResizeRequest;
|
import com.orion.ops.module.asset.handler.host.terminal.model.request.SshResizeRequest;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.session.ISshSession;
|
import com.orion.ops.module.asset.handler.host.terminal.session.ISshSession;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.session.ITerminalSession;
|
import com.orion.ops.module.asset.handler.host.terminal.session.ITerminalSession;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -11,7 +11,7 @@ import org.springframework.web.socket.WebSocketSession;
|
|||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改大小处理器
|
* ssh 修改大小处理器
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@@ -19,13 +19,13 @@ import javax.annotation.Resource;
|
|||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class TerminalResizeHandler extends AbstractTerminalHandler<TerminalResizeRequest> {
|
public class SshResizeHandler extends AbstractTerminalHandler<SshResizeRequest> {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private TerminalManager terminalManager;
|
private TerminalManager terminalManager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(WebSocketSession channel, TerminalResizeRequest payload) {
|
public void handle(WebSocketSession channel, SshResizeRequest payload) {
|
||||||
// 获取会话
|
// 获取会话
|
||||||
ITerminalSession session = terminalManager.getSession(channel.getId(), payload.getSessionId());
|
ITerminalSession session = terminalManager.getSession(channel.getId(), payload.getSessionId());
|
||||||
if (session instanceof ISshSession) {
|
if (session instanceof ISshSession) {
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.orion.ops.module.asset.handler.host.terminal.model.request;
|
||||||
|
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sftp 修改文件权限 实体对象
|
||||||
|
* <p>
|
||||||
|
* i|eff00a1|path|mode
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/2/6 13:31
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(name = "SftpChangeModeRequest", description = "sftp 修改文件权限 实体对象")
|
||||||
|
public class SftpChangeModeRequest extends TerminalBasePayload {
|
||||||
|
|
||||||
|
@Schema(description = "path")
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
@Schema(description = "权限")
|
||||||
|
private String mode;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.orion.ops.module.asset.handler.host.terminal.model.request;
|
||||||
|
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sftp 列表请求 实体对象
|
||||||
|
* <p>
|
||||||
|
* i|eff00a1|path
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/2/6 13:31
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(name = "SftpListRequest", description = "sftp 列表请求 实体对象")
|
||||||
|
public class SftpListRequest extends TerminalBasePayload {
|
||||||
|
|
||||||
|
@Schema(description = "path")
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.orion.ops.module.asset.handler.host.terminal.model.request;
|
||||||
|
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sftp 创建文件夹 实体对象
|
||||||
|
* <p>
|
||||||
|
* i|eff00a1|path
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/2/6 13:31
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(name = "SftpMakeDirectoryRequest", description = "sftp 创建文件夹 实体对象")
|
||||||
|
public class SftpMakeDirectoryRequest extends TerminalBasePayload {
|
||||||
|
|
||||||
|
@Schema(description = "path")
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.orion.ops.module.asset.handler.host.terminal.model.request;
|
||||||
|
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sftp 移动文件 实体对象
|
||||||
|
* <p>
|
||||||
|
* i|eff00a1|source|target
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/2/6 13:31
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(name = "SftpMoveRequest", description = "sftp 移动文件 实体对象")
|
||||||
|
public class SftpMoveRequest extends TerminalBasePayload {
|
||||||
|
|
||||||
|
@Schema(description = "source")
|
||||||
|
private String source;
|
||||||
|
|
||||||
|
@Schema(description = "target")
|
||||||
|
private String target;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.orion.ops.module.asset.handler.host.terminal.model.request;
|
||||||
|
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sftp 删除文件 实体对象
|
||||||
|
* <p>
|
||||||
|
* i|eff00a1|path
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/2/6 13:31
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(name = "SftpRemoveRequest", description = "sftp 删除文件 实体对象")
|
||||||
|
public class SftpRemoveRequest extends TerminalBasePayload {
|
||||||
|
|
||||||
|
@Schema(description = "path")
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.orion.ops.module.asset.handler.host.terminal.model.request;
|
||||||
|
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sftp 创建文件 实体对象
|
||||||
|
* <p>
|
||||||
|
* i|eff00a1|path
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/2/6 13:31
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(name = "SftpTouchRequest", description = "sftp 创建文件 实体对象")
|
||||||
|
public class SftpTouchRequest extends TerminalBasePayload {
|
||||||
|
|
||||||
|
@Schema(description = "path")
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.orion.ops.module.asset.handler.host.terminal.model.request;
|
||||||
|
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sftp 截断文件 实体对象
|
||||||
|
* <p>
|
||||||
|
* i|eff00a1|path
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/2/6 13:31
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(name = "SftpTruncateRequest", description = "sftp 截断文件 实体对象")
|
||||||
|
public class SftpTruncateRequest extends TerminalBasePayload {
|
||||||
|
|
||||||
|
@Schema(description = "path")
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ import lombok.NoArgsConstructor;
|
|||||||
import lombok.experimental.SuperBuilder;
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输入请求 实体对象
|
* ssh 输入请求 实体对象
|
||||||
* <p>
|
* <p>
|
||||||
* i|eff00a1|command
|
* i|eff00a1|command
|
||||||
*
|
*
|
||||||
@@ -22,8 +22,8 @@ import lombok.experimental.SuperBuilder;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Schema(name = "TerminalInputRequest", description = "输入请求 实体对象")
|
@Schema(name = "SshInputRequest", description = "ssh 输入请求 实体对象")
|
||||||
public class TerminalInputRequest extends TerminalBasePayload {
|
public class SshInputRequest extends TerminalBasePayload {
|
||||||
|
|
||||||
@Schema(description = "command")
|
@Schema(description = "command")
|
||||||
private String command;
|
private String command;
|
||||||
@@ -9,7 +9,7 @@ import lombok.NoArgsConstructor;
|
|||||||
import lombok.experimental.SuperBuilder;
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改大小请求 实体对象
|
* ssh 修改大小请求 实体对象
|
||||||
* <p>
|
* <p>
|
||||||
* rs|eff00a1|100|20
|
* rs|eff00a1|100|20
|
||||||
*
|
*
|
||||||
@@ -22,8 +22,8 @@ import lombok.experimental.SuperBuilder;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Schema(name = "TerminalResizeRequest", description = "修改大小请求 实体对象")
|
@Schema(name = "SshResizeRequest", description = "ssh 修改大小请求 实体对象")
|
||||||
public class TerminalResizeRequest extends TerminalBasePayload {
|
public class SshResizeRequest extends TerminalBasePayload {
|
||||||
|
|
||||||
@Schema(description = "列数")
|
@Schema(description = "列数")
|
||||||
private Integer cols;
|
private Integer cols;
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package com.orion.ops.module.asset.handler.host.terminal.model.response;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sftp 文件响应 实体对象
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/2/6 13:57
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Schema(name = "SftpFileResponse", description = "sftp 文件响应 实体对象")
|
||||||
|
public class SftpFileResponse {
|
||||||
|
|
||||||
|
@Schema(description = "名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "绝对路径")
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
@Schema(description = "文件后缀")
|
||||||
|
private String suffix;
|
||||||
|
|
||||||
|
@Schema(description = "文件大小")
|
||||||
|
private String size;
|
||||||
|
|
||||||
|
@Schema(description = "文件大小(byte)")
|
||||||
|
private Long sizeByte;
|
||||||
|
|
||||||
|
@Schema(description = "属性")
|
||||||
|
private String attr;
|
||||||
|
|
||||||
|
@Schema(description = "是否为目录")
|
||||||
|
private Boolean isDir;
|
||||||
|
|
||||||
|
@Schema(description = "10进制表现的8进制权限")
|
||||||
|
private Integer permission;
|
||||||
|
|
||||||
|
@Schema(description = "用户id")
|
||||||
|
private Integer uid;
|
||||||
|
|
||||||
|
@Schema(description = "组id")
|
||||||
|
private Integer gid;
|
||||||
|
|
||||||
|
@Schema(description = "更新时间")
|
||||||
|
private Date modifyTime;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.orion.ops.module.asset.handler.host.terminal.model.response;
|
||||||
|
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sftp 列表响应 实体对象
|
||||||
|
*
|
||||||
|
* @author Jiahang Li
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2024/2/6 16:20
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@SuperBuilder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Schema(name = "SftpListResponse", description = "sftp 列表响应 实体对象")
|
||||||
|
public class SftpListResponse extends TerminalBasePayload {
|
||||||
|
|
||||||
|
@Schema(description = "检查结果")
|
||||||
|
private Integer result;
|
||||||
|
|
||||||
|
@Schema(description = "path")
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
@Schema(description = "body")
|
||||||
|
private String body;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ import lombok.NoArgsConstructor;
|
|||||||
import lombok.experimental.SuperBuilder;
|
import lombok.experimental.SuperBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主机输出响应 实体对象
|
* ssh 输出响应 实体对象
|
||||||
*
|
*
|
||||||
* @author Jiahang Li
|
* @author Jiahang Li
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@@ -20,8 +20,8 @@ import lombok.experimental.SuperBuilder;
|
|||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Schema(name = "TerminalOutputResponse", description = "主机输出响应 实体对象")
|
@Schema(name = "SshOutputResponse", description = "ssh 输出响应 实体对象")
|
||||||
public class TerminalOutputResponse extends TerminalBasePayload {
|
public class SshOutputResponse extends TerminalBasePayload {
|
||||||
|
|
||||||
@Schema(description = "body")
|
@Schema(description = "body")
|
||||||
private String body;
|
private String body;
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
package com.orion.ops.module.asset.handler.host.terminal.session;
|
package com.orion.ops.module.asset.handler.host.terminal.session;
|
||||||
|
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpFileResponse;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sftp 会话定义
|
* sftp 会话定义
|
||||||
*
|
*
|
||||||
@@ -14,4 +18,19 @@ public interface ISftpSession extends ITerminalSession {
|
|||||||
*/
|
*/
|
||||||
void connect();
|
void connect();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 home 路径
|
||||||
|
*
|
||||||
|
* @return homePath
|
||||||
|
*/
|
||||||
|
String getHome();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件列表
|
||||||
|
*
|
||||||
|
* @param path path
|
||||||
|
* @return list
|
||||||
|
*/
|
||||||
|
List<SftpFileResponse> list(String path);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,23 @@
|
|||||||
package com.orion.ops.module.asset.handler.host.terminal.session;
|
package com.orion.ops.module.asset.handler.host.terminal.session;
|
||||||
|
|
||||||
|
import com.orion.lang.utils.Strings;
|
||||||
|
import com.orion.lang.utils.convert.TypeStore;
|
||||||
|
import com.orion.lang.utils.io.FileType;
|
||||||
|
import com.orion.lang.utils.io.Files1;
|
||||||
import com.orion.lang.utils.io.Streams;
|
import com.orion.lang.utils.io.Streams;
|
||||||
import com.orion.net.host.SessionStore;
|
import com.orion.net.host.SessionStore;
|
||||||
import com.orion.net.host.sftp.SftpExecutor;
|
import com.orion.net.host.sftp.SftpExecutor;
|
||||||
|
import com.orion.net.host.sftp.SftpFile;
|
||||||
import com.orion.ops.framework.common.constant.Const;
|
import com.orion.ops.framework.common.constant.Const;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalConfig;
|
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalConfig;
|
||||||
|
import com.orion.ops.module.asset.handler.host.terminal.model.response.SftpFileResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.socket.WebSocketSession;
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 终端 ssh 会话
|
* 终端 ssh 会话
|
||||||
*
|
*
|
||||||
@@ -40,6 +50,20 @@ public class SftpSession extends TerminalSession implements ISftpSession {
|
|||||||
executor.connect();
|
executor.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHome() {
|
||||||
|
return executor.getHome();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SftpFileResponse> list(String path) {
|
||||||
|
// 查询文件
|
||||||
|
List<SftpFile> files = executor.listFilesFilter(path, f -> !f.getName().startsWith("."), false, true);
|
||||||
|
return files.stream()
|
||||||
|
.map(SftpSession::fileMapping)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void keepAlive() {
|
public void keepAlive() {
|
||||||
try {
|
try {
|
||||||
@@ -56,4 +80,29 @@ public class SftpSession extends TerminalSession implements ISftpSession {
|
|||||||
Streams.close(sessionStore);
|
Streams.close(sessionStore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件映射
|
||||||
|
*
|
||||||
|
* @param sftpFile sftpFile
|
||||||
|
* @return file
|
||||||
|
*/
|
||||||
|
private static SftpFileResponse fileMapping(SftpFile sftpFile) {
|
||||||
|
SftpFileResponse file = new SftpFileResponse();
|
||||||
|
file.setName(sftpFile.getName());
|
||||||
|
file.setPath(sftpFile.getPath());
|
||||||
|
file.setSuffix(Files1.getSuffix(sftpFile.getName()));
|
||||||
|
file.setSize(Files1.getSize(sftpFile.getSize()));
|
||||||
|
file.setSizeByte(sftpFile.getSize());
|
||||||
|
file.setPermission(sftpFile.getPermission());
|
||||||
|
file.setUid(sftpFile.getUid());
|
||||||
|
file.setGid(sftpFile.getGid());
|
||||||
|
file.setAttr(sftpFile.getPermissionString());
|
||||||
|
file.setModifyTime(sftpFile.getModifyTime());
|
||||||
|
Boolean isDir = Optional.ofNullable(FileType.of(file.getAttr()))
|
||||||
|
.map(FileType.DIRECTORY::equals)
|
||||||
|
.orElse(false);
|
||||||
|
file.setIsDir(isDir);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import com.orion.ops.module.asset.handler.host.terminal.constant.TerminalMessage
|
|||||||
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
|
import com.orion.ops.module.asset.handler.host.terminal.enums.OutputTypeEnum;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalConfig;
|
import com.orion.ops.module.asset.handler.host.terminal.model.TerminalConfig;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.model.response.TerminalCloseResponse;
|
import com.orion.ops.module.asset.handler.host.terminal.model.response.TerminalCloseResponse;
|
||||||
import com.orion.ops.module.asset.handler.host.terminal.model.response.TerminalOutputResponse;
|
import com.orion.ops.module.asset.handler.host.terminal.model.response.SshOutputResponse;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.socket.WebSocketSession;
|
import org.springframework.web.socket.WebSocketSession;
|
||||||
@@ -117,12 +117,12 @@ public class SshSession extends TerminalSession implements ISshSession {
|
|||||||
while (channel.isOpen() && (read = in.read(bs)) != -1) {
|
while (channel.isOpen() && (read = in.read(bs)) != -1) {
|
||||||
String body = lastLine = new String(bs, 0, read, config.getCharset());
|
String body = lastLine = new String(bs, 0, read, config.getCharset());
|
||||||
// 响应
|
// 响应
|
||||||
TerminalOutputResponse resp = TerminalOutputResponse.builder()
|
SshOutputResponse resp = SshOutputResponse.builder()
|
||||||
.type(OutputTypeEnum.OUTPUT.getType())
|
.type(OutputTypeEnum.SSH_OUTPUT.getType())
|
||||||
.sessionId(sessionId)
|
.sessionId(sessionId)
|
||||||
.body(body)
|
.body(body)
|
||||||
.build();
|
.build();
|
||||||
WebSockets.sendText(channel, OutputTypeEnum.OUTPUT.format(resp));
|
WebSockets.sendText(channel, OutputTypeEnum.SSH_OUTPUT.format(resp));
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
log.error("terminal 读取流失败", ex);
|
log.error("terminal 读取流失败", ex);
|
||||||
|
|||||||
@@ -81,6 +81,147 @@ body[terminal-theme='dark'] {
|
|||||||
|
|
||||||
// arco 亮色配色
|
// arco 亮色配色
|
||||||
body .host-terminal-layout, .arco-modal-container {
|
body .host-terminal-layout, .arco-modal-container {
|
||||||
|
--red-1: 255, 236, 232;
|
||||||
|
--red-2: 253, 205, 197;
|
||||||
|
--red-3: 251, 172, 163;
|
||||||
|
--red-4: 249, 137, 129;
|
||||||
|
--red-5: 247, 101, 96;
|
||||||
|
--red-6: 245, 63, 63;
|
||||||
|
--red-7: 203, 39, 45;
|
||||||
|
--red-8: 161, 21, 30;
|
||||||
|
--red-9: 119, 8, 19;
|
||||||
|
--red-10: 77, 0, 10;
|
||||||
|
--orangered-1: 255, 243, 232;
|
||||||
|
--orangered-2: 253, 221, 195;
|
||||||
|
--orangered-3: 252, 197, 159;
|
||||||
|
--orangered-4: 250, 172, 123;
|
||||||
|
--orangered-5: 249, 144, 87;
|
||||||
|
--orangered-6: 247, 114, 52;
|
||||||
|
--orangered-7: 204, 81, 32;
|
||||||
|
--orangered-8: 162, 53, 17;
|
||||||
|
--orangered-9: 119, 31, 6;
|
||||||
|
--orangered-10: 77, 14, 0;
|
||||||
|
--orange-1: 255, 247, 232;
|
||||||
|
--orange-2: 255, 228, 186;
|
||||||
|
--orange-3: 255, 207, 139;
|
||||||
|
--orange-4: 255, 182, 93;
|
||||||
|
--orange-5: 255, 154, 46;
|
||||||
|
--orange-6: 255, 125, 0;
|
||||||
|
--orange-7: 210, 95, 0;
|
||||||
|
--orange-8: 166, 69, 0;
|
||||||
|
--orange-9: 121, 46, 0;
|
||||||
|
--orange-10: 77, 27, 0;
|
||||||
|
--gold-1: 255, 252, 232;
|
||||||
|
--gold-2: 253, 244, 191;
|
||||||
|
--gold-3: 252, 233, 150;
|
||||||
|
--gold-4: 250, 220, 109;
|
||||||
|
--gold-5: 249, 204, 69;
|
||||||
|
--gold-6: 247, 186, 30;
|
||||||
|
--gold-7: 204, 146, 19;
|
||||||
|
--gold-8: 162, 109, 10;
|
||||||
|
--gold-9: 119, 75, 4;
|
||||||
|
--gold-10: 77, 45, 0;
|
||||||
|
--yellow-1: 254, 255, 232;
|
||||||
|
--yellow-2: 254, 254, 190;
|
||||||
|
--yellow-3: 253, 250, 148;
|
||||||
|
--yellow-4: 252, 242, 107;
|
||||||
|
--yellow-5: 251, 232, 66;
|
||||||
|
--yellow-6: 250, 220, 25;
|
||||||
|
--yellow-7: 207, 175, 15;
|
||||||
|
--yellow-8: 163, 132, 8;
|
||||||
|
--yellow-9: 120, 93, 3;
|
||||||
|
--yellow-10: 77, 56, 0;
|
||||||
|
--lime-1: 252, 255, 232;
|
||||||
|
--lime-2: 237, 248, 187;
|
||||||
|
--lime-3: 220, 241, 144;
|
||||||
|
--lime-4: 201, 233, 104;
|
||||||
|
--lime-5: 181, 226, 65;
|
||||||
|
--lime-6: 159, 219, 29;
|
||||||
|
--lime-7: 126, 183, 18;
|
||||||
|
--lime-8: 95, 148, 10;
|
||||||
|
--lime-9: 67, 112, 4;
|
||||||
|
--lime-10: 42, 77, 0;
|
||||||
|
--green-1: 232, 255, 234;
|
||||||
|
--green-2: 175, 240, 181;
|
||||||
|
--green-3: 123, 225, 136;
|
||||||
|
--green-4: 76, 210, 99;
|
||||||
|
--green-5: 35, 195, 67;
|
||||||
|
--green-6: 0, 180, 42;
|
||||||
|
--green-7: 0, 154, 41;
|
||||||
|
--green-8: 0, 128, 38;
|
||||||
|
--green-9: 0, 102, 34;
|
||||||
|
--green-10: 0, 77, 28;
|
||||||
|
--cyan-1: 232, 255, 251;
|
||||||
|
--cyan-2: 183, 244, 236;
|
||||||
|
--cyan-3: 137, 233, 224;
|
||||||
|
--cyan-4: 94, 223, 214;
|
||||||
|
--cyan-5: 55, 212, 207;
|
||||||
|
--cyan-6: 20, 201, 201;
|
||||||
|
--cyan-7: 13, 165, 170;
|
||||||
|
--cyan-8: 7, 130, 139;
|
||||||
|
--cyan-9: 3, 97, 108;
|
||||||
|
--cyan-10: 0, 66, 77;
|
||||||
|
--blue-1: 232, 247, 255;
|
||||||
|
--blue-2: 195, 231, 254;
|
||||||
|
--blue-3: 159, 212, 253;
|
||||||
|
--blue-4: 123, 192, 252;
|
||||||
|
--blue-5: 87, 169, 251;
|
||||||
|
--blue-6: 52, 145, 250;
|
||||||
|
--blue-7: 32, 108, 207;
|
||||||
|
--blue-8: 17, 75, 163;
|
||||||
|
--blue-9: 6, 48, 120;
|
||||||
|
--blue-10: 0, 26, 77;
|
||||||
|
--arcoblue-1: 232, 243, 255;
|
||||||
|
--arcoblue-2: 190, 218, 255;
|
||||||
|
--arcoblue-3: 148, 191, 255;
|
||||||
|
--arcoblue-4: 106, 161, 255;
|
||||||
|
--arcoblue-5: 64, 128, 255;
|
||||||
|
--arcoblue-6: 22, 93, 255;
|
||||||
|
--arcoblue-7: 14, 66, 210;
|
||||||
|
--arcoblue-8: 7, 44, 166;
|
||||||
|
--arcoblue-9: 3, 26, 121;
|
||||||
|
--arcoblue-10: 0, 13, 77;
|
||||||
|
--purple-1: 245, 232, 255;
|
||||||
|
--purple-2: 221, 190, 246;
|
||||||
|
--purple-3: 195, 150, 237;
|
||||||
|
--purple-4: 168, 113, 227;
|
||||||
|
--purple-5: 141, 78, 218;
|
||||||
|
--purple-6: 114, 46, 209;
|
||||||
|
--purple-7: 85, 29, 176;
|
||||||
|
--purple-8: 60, 16, 143;
|
||||||
|
--purple-9: 39, 6, 110;
|
||||||
|
--purple-10: 22, 0, 77;
|
||||||
|
--pinkpurple-1: 255, 232, 251;
|
||||||
|
--pinkpurple-2: 247, 186, 239;
|
||||||
|
--pinkpurple-3: 240, 142, 230;
|
||||||
|
--pinkpurple-4: 232, 101, 223;
|
||||||
|
--pinkpurple-5: 225, 62, 219;
|
||||||
|
--pinkpurple-6: 217, 26, 217;
|
||||||
|
--pinkpurple-7: 176, 16, 182;
|
||||||
|
--pinkpurple-8: 138, 9, 147;
|
||||||
|
--pinkpurple-9: 101, 3, 112;
|
||||||
|
--pinkpurple-10: 66, 0, 77;
|
||||||
|
--magenta-1: 255, 232, 241;
|
||||||
|
--magenta-2: 253, 194, 219;
|
||||||
|
--magenta-3: 251, 157, 199;
|
||||||
|
--magenta-4: 249, 121, 183;
|
||||||
|
--magenta-5: 247, 84, 168;
|
||||||
|
--magenta-6: 245, 49, 157;
|
||||||
|
--magenta-7: 203, 30, 131;
|
||||||
|
--magenta-8: 161, 16, 105;
|
||||||
|
--magenta-9: 119, 6, 79;
|
||||||
|
--magenta-10: 77, 0, 52;
|
||||||
|
--gray-1: 247, 248, 250;
|
||||||
|
--gray-2: 242, 243, 245;
|
||||||
|
--gray-3: 229, 230, 235;
|
||||||
|
--gray-4: 201, 205, 212;
|
||||||
|
--gray-5: 169, 174, 184;
|
||||||
|
--gray-6: 134, 144, 156;
|
||||||
|
--gray-7: 107, 119, 133;
|
||||||
|
--gray-8: 78, 89, 105;
|
||||||
|
--gray-9: 39, 46, 59;
|
||||||
|
--gray-10: 29, 33, 41;
|
||||||
|
|
||||||
--color-white: #ffffff;
|
--color-white: #ffffff;
|
||||||
--color-black: #000000;
|
--color-black: #000000;
|
||||||
--color-border: rgb(var(--gray-3));
|
--color-border: rgb(var(--gray-3));
|
||||||
@@ -154,6 +295,147 @@ body .host-terminal-layout, .arco-modal-container {
|
|||||||
body[terminal-theme='dark'],
|
body[terminal-theme='dark'],
|
||||||
body[terminal-theme='dark'] .host-terminal-layout,
|
body[terminal-theme='dark'] .host-terminal-layout,
|
||||||
body[terminal-theme='dark'] .arco-modal-container {
|
body[terminal-theme='dark'] .arco-modal-container {
|
||||||
|
--red-1: 77, 0, 10;
|
||||||
|
--red-2: 119, 6, 17;
|
||||||
|
--red-3: 161, 22, 31;
|
||||||
|
--red-4: 203, 46, 52;
|
||||||
|
--red-5: 245, 78, 78;
|
||||||
|
--red-6: 247, 105, 101;
|
||||||
|
--red-7: 249, 141, 134;
|
||||||
|
--red-8: 251, 176, 167;
|
||||||
|
--red-9: 253, 209, 202;
|
||||||
|
--red-10: 255, 240, 236;
|
||||||
|
--orangered-1: 77, 14, 0;
|
||||||
|
--orangered-2: 119, 30, 5;
|
||||||
|
--orangered-3: 162, 55, 20;
|
||||||
|
--orangered-4: 204, 87, 41;
|
||||||
|
--orangered-5: 247, 126, 69;
|
||||||
|
--orangered-6: 249, 146, 90;
|
||||||
|
--orangered-7: 250, 173, 125;
|
||||||
|
--orangered-8: 252, 198, 161;
|
||||||
|
--orangered-9: 253, 222, 197;
|
||||||
|
--orangered-10: 255, 244, 235;
|
||||||
|
--orange-1: 77, 27, 0;
|
||||||
|
--orange-2: 121, 48, 4;
|
||||||
|
--orange-3: 166, 75, 10;
|
||||||
|
--orange-4: 210, 105, 19;
|
||||||
|
--orange-5: 255, 141, 31;
|
||||||
|
--orange-6: 255, 150, 38;
|
||||||
|
--orange-7: 255, 179, 87;
|
||||||
|
--orange-8: 255, 205, 135;
|
||||||
|
--orange-9: 255, 227, 184;
|
||||||
|
--orange-10: 255, 247, 232;
|
||||||
|
--gold-1: 77, 45, 0;
|
||||||
|
--gold-2: 119, 75, 4;
|
||||||
|
--gold-3: 162, 111, 15;
|
||||||
|
--gold-4: 204, 150, 31;
|
||||||
|
--gold-5: 247, 192, 52;
|
||||||
|
--gold-6: 249, 204, 68;
|
||||||
|
--gold-7: 250, 220, 108;
|
||||||
|
--gold-8: 252, 233, 149;
|
||||||
|
--gold-9: 253, 244, 190;
|
||||||
|
--gold-10: 255, 252, 232;
|
||||||
|
--yellow-1: 77, 56, 0;
|
||||||
|
--yellow-2: 120, 94, 7;
|
||||||
|
--yellow-3: 163, 134, 20;
|
||||||
|
--yellow-4: 207, 179, 37;
|
||||||
|
--yellow-5: 250, 225, 60;
|
||||||
|
--yellow-6: 251, 233, 75;
|
||||||
|
--yellow-7: 252, 243, 116;
|
||||||
|
--yellow-8: 253, 250, 157;
|
||||||
|
--yellow-9: 254, 254, 198;
|
||||||
|
--yellow-10: 254, 255, 240;
|
||||||
|
--lime-1: 42, 77, 0;
|
||||||
|
--lime-2: 68, 112, 6;
|
||||||
|
--lime-3: 98, 148, 18;
|
||||||
|
--lime-4: 132, 183, 35;
|
||||||
|
--lime-5: 168, 219, 57;
|
||||||
|
--lime-6: 184, 226, 75;
|
||||||
|
--lime-7: 203, 233, 112;
|
||||||
|
--lime-8: 222, 241, 152;
|
||||||
|
--lime-9: 238, 248, 194;
|
||||||
|
--lime-10: 253, 255, 238;
|
||||||
|
--green-1: 0, 77, 28;
|
||||||
|
--green-2: 4, 102, 37;
|
||||||
|
--green-3: 10, 128, 45;
|
||||||
|
--green-4: 18, 154, 55;
|
||||||
|
--green-5: 29, 180, 64;
|
||||||
|
--green-6: 39, 195, 70;
|
||||||
|
--green-7: 80, 210, 102;
|
||||||
|
--green-8: 126, 225, 139;
|
||||||
|
--green-9: 178, 240, 183;
|
||||||
|
--green-10: 235, 255, 236;
|
||||||
|
--cyan-1: 0, 66, 77;
|
||||||
|
--cyan-2: 6, 97, 108;
|
||||||
|
--cyan-3: 17, 131, 139;
|
||||||
|
--cyan-4: 31, 166, 170;
|
||||||
|
--cyan-5: 48, 201, 201;
|
||||||
|
--cyan-6: 63, 212, 207;
|
||||||
|
--cyan-7: 102, 223, 215;
|
||||||
|
--cyan-8: 144, 233, 225;
|
||||||
|
--cyan-9: 190, 244, 237;
|
||||||
|
--cyan-10: 240, 255, 252;
|
||||||
|
--blue-1: 0, 26, 77;
|
||||||
|
--blue-2: 5, 47, 120;
|
||||||
|
--blue-3: 19, 76, 163;
|
||||||
|
--blue-4: 41, 113, 207;
|
||||||
|
--blue-5: 70, 154, 250;
|
||||||
|
--blue-6: 90, 170, 251;
|
||||||
|
--blue-7: 125, 193, 252;
|
||||||
|
--blue-8: 161, 213, 253;
|
||||||
|
--blue-9: 198, 232, 254;
|
||||||
|
--blue-10: 234, 248, 255;
|
||||||
|
--arcoblue-1: 0, 13, 77;
|
||||||
|
--arcoblue-2: 4, 27, 121;
|
||||||
|
--arcoblue-3: 14, 50, 166;
|
||||||
|
--arcoblue-4: 29, 77, 210;
|
||||||
|
--arcoblue-5: 48, 111, 255;
|
||||||
|
--arcoblue-6: 60, 126, 255;
|
||||||
|
--arcoblue-7: 104, 159, 255;
|
||||||
|
--arcoblue-8: 147, 190, 255;
|
||||||
|
--arcoblue-9: 190, 218, 255;
|
||||||
|
--arcoblue-10: 234, 244, 255;
|
||||||
|
--purple-1: 22, 0, 77;
|
||||||
|
--purple-2: 39, 6, 110;
|
||||||
|
--purple-3: 62, 19, 143;
|
||||||
|
--purple-4: 90, 37, 176;
|
||||||
|
--purple-5: 123, 61, 209;
|
||||||
|
--purple-6: 142, 81, 218;
|
||||||
|
--purple-7: 169, 116, 227;
|
||||||
|
--purple-8: 197, 154, 237;
|
||||||
|
--purple-9: 223, 194, 246;
|
||||||
|
--purple-10: 247, 237, 255;
|
||||||
|
--pinkpurple-1: 66, 0, 77;
|
||||||
|
--pinkpurple-2: 101, 3, 112;
|
||||||
|
--pinkpurple-3: 138, 13, 147;
|
||||||
|
--pinkpurple-4: 176, 27, 182;
|
||||||
|
--pinkpurple-5: 217, 46, 217;
|
||||||
|
--pinkpurple-6: 225, 61, 219;
|
||||||
|
--pinkpurple-7: 232, 102, 223;
|
||||||
|
--pinkpurple-8: 240, 146, 230;
|
||||||
|
--pinkpurple-9: 247, 193, 240;
|
||||||
|
--pinkpurple-10: 255, 242, 253;
|
||||||
|
--magenta-1: 77, 0, 52;
|
||||||
|
--magenta-2: 119, 8, 80;
|
||||||
|
--magenta-3: 161, 23, 108;
|
||||||
|
--magenta-4: 203, 43, 136;
|
||||||
|
--magenta-5: 245, 69, 166;
|
||||||
|
--magenta-6: 247, 86, 169;
|
||||||
|
--magenta-7: 249, 122, 184;
|
||||||
|
--magenta-8: 251, 158, 200;
|
||||||
|
--magenta-9: 253, 195, 219;
|
||||||
|
--magenta-10: 255, 232, 241;
|
||||||
|
--gray-1: 23, 23, 26;
|
||||||
|
--gray-2: 46, 46, 48;
|
||||||
|
--gray-3: 72, 72, 73;
|
||||||
|
--gray-4: 95, 95, 96;
|
||||||
|
--gray-5: 120, 120, 122;
|
||||||
|
--gray-6: 146, 146, 147;
|
||||||
|
--gray-7: 171, 171, 172;
|
||||||
|
--gray-8: 197, 197, 197;
|
||||||
|
--gray-9: 223, 223, 223;
|
||||||
|
--gray-10: 246, 246, 246;
|
||||||
|
|
||||||
--color-white: rgba(255, 255, 255, 0.9);
|
--color-white: rgba(255, 255, 255, 0.9);
|
||||||
--color-black: #000000;
|
--color-black: #000000;
|
||||||
--color-border: #333335;
|
--color-border: #333335;
|
||||||
|
|||||||
@@ -64,8 +64,7 @@ export default defineStore('terminal', {
|
|||||||
} as TerminalShortcutSetting,
|
} as TerminalShortcutSetting,
|
||||||
},
|
},
|
||||||
hosts: {} as AuthorizedHostQueryResponse,
|
hosts: {} as AuthorizedHostQueryResponse,
|
||||||
// fixme
|
tabManager: new TerminalTabManager(TerminalTabs.NEW_CONNECTION),
|
||||||
tabManager: new TerminalTabManager(TerminalTabs.TERMINAL_PANEL),
|
|
||||||
panelManager: new TerminalPanelManager(),
|
panelManager: new TerminalPanelManager(),
|
||||||
sessionManager: new TerminalSessionManager()
|
sessionManager: new TerminalSessionManager()
|
||||||
}),
|
}),
|
||||||
|
|||||||
457
orion-ops-ui/src/views/host/terminal/components/sftp/data.ts
Normal file
457
orion-ops-ui/src/views/host/terminal/components/sftp/data.ts
Normal file
@@ -0,0 +1,457 @@
|
|||||||
|
export default [{
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1639399737000,
|
||||||
|
'name': '04',
|
||||||
|
'path': '/root/04',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '34.2 MB',
|
||||||
|
'sizeByte': 35845278,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': 'drwxr-xr-x',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': true,
|
||||||
|
'modifyTime': 1662630786000,
|
||||||
|
'name': 'j3',
|
||||||
|
'path': '/root/j3',
|
||||||
|
'permission': 755,
|
||||||
|
'size': '4 KB',
|
||||||
|
'sizeByte': 4096,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1658895079000,
|
||||||
|
'name': '123',
|
||||||
|
'path': '/root/123',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '13 B',
|
||||||
|
'sizeByte': 13,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--rwx',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1664427351000,
|
||||||
|
'name': 'bug.txt',
|
||||||
|
'path': '/root/bug.txt',
|
||||||
|
'permission': 647,
|
||||||
|
'size': '50.3 KB',
|
||||||
|
'sizeByte': 51491,
|
||||||
|
'suffix': 'txt',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': 'drwxr-xr-x',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': true,
|
||||||
|
'modifyTime': 1659888021000,
|
||||||
|
'name': 'ops-monitor-agent',
|
||||||
|
'path': '/root/ops-monitor-agent',
|
||||||
|
'permission': 755,
|
||||||
|
'size': '4 KB',
|
||||||
|
'sizeByte': 4096,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1635143381000,
|
||||||
|
'name': '04_体验一下面试官对于消息队列的7个连环炮.zip',
|
||||||
|
'path': '/root/04_体验一下面试官对于消息队列的7个连环炮.zip',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '34.2 MB',
|
||||||
|
'sizeByte': 35845278,
|
||||||
|
'suffix': 'zip',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1637921002000,
|
||||||
|
'name': '一个超长的文件一个超长的文件一个超长的文件一个超长的文件一个超长的文件一个超长的文件',
|
||||||
|
'path': '/root/一个超长的文件一个超长的文件一个超长的文件一个超长的文件一个超长的文件一个超长的文件',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '4 B',
|
||||||
|
'sizeByte': 4,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1662627298000,
|
||||||
|
'name': 'WebStorm-2021.2.2.exe',
|
||||||
|
'path': '/root/WebStorm-2021.2.2.exe',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '366.2 MB',
|
||||||
|
'sizeByte': 383998600,
|
||||||
|
'suffix': 'exe',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': 'drwxrwxr-x',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': true,
|
||||||
|
'modifyTime': 1557936457000,
|
||||||
|
'name': 'redis-5.0.5',
|
||||||
|
'path': '/root/redis-5.0.5',
|
||||||
|
'permission': 775,
|
||||||
|
'size': '4 KB',
|
||||||
|
'sizeByte': 4096,
|
||||||
|
'suffix': '5',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': 'drwxr-xr-x',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': true,
|
||||||
|
'modifyTime': 1643003400000,
|
||||||
|
'name': 'pic',
|
||||||
|
'path': '/root/pic',
|
||||||
|
'permission': 755,
|
||||||
|
'size': '4 KB',
|
||||||
|
'sizeByte': 4096,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1635127278000,
|
||||||
|
'name': 'pvzβv6.25-R4.7z',
|
||||||
|
'path': '/root/pvzβv6.25-R4.7z',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '37.2 MB',
|
||||||
|
'sizeByte': 38978762,
|
||||||
|
'suffix': '7z',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1652947847000,
|
||||||
|
'name': '1.txt',
|
||||||
|
'path': '/root/1.txt',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '133 B',
|
||||||
|
'sizeByte': 133,
|
||||||
|
'suffix': 'txt',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': 'drw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': true,
|
||||||
|
'modifyTime': 1653015555000,
|
||||||
|
'name': 'write',
|
||||||
|
'path': '/root/write',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '4 KB',
|
||||||
|
'sizeByte': 4096,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1660552691000,
|
||||||
|
'name': 'k.pub',
|
||||||
|
'path': '/root/k.pub',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '401 B',
|
||||||
|
'sizeByte': 401,
|
||||||
|
'suffix': 'pub',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1625065314000,
|
||||||
|
'name': 'ideaIU-2021.1.1.exe',
|
||||||
|
'path': '/root/ideaIU-2021.1.1.exe',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '729.3 MB',
|
||||||
|
'sizeByte': 764705864,
|
||||||
|
'suffix': 'exe',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1636525624000,
|
||||||
|
'name': '文本.txt',
|
||||||
|
'path': '/root/文本.txt',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '0 B',
|
||||||
|
'sizeByte': 0,
|
||||||
|
'suffix': 'txt',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1635090233000,
|
||||||
|
'name': '数据头.txt',
|
||||||
|
'path': '/root/数据头.txt',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '4.3 KB',
|
||||||
|
'sizeByte': 4376,
|
||||||
|
'suffix': 'txt',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': 'drwxr-xr-x',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': true,
|
||||||
|
'modifyTime': 1662627659000,
|
||||||
|
'name': 'j1',
|
||||||
|
'path': '/root/j1',
|
||||||
|
'permission': 755,
|
||||||
|
'size': '4 KB',
|
||||||
|
'sizeByte': 4096,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1642956894000,
|
||||||
|
'name': 'PowerShell-7.1.4-win-x64.msi',
|
||||||
|
'path': '/root/PowerShell-7.1.4-win-x64.msi',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '94.9 MB',
|
||||||
|
'sizeByte': 99524608,
|
||||||
|
'suffix': 'msi',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-------',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1660552691000,
|
||||||
|
'name': 'k',
|
||||||
|
'path': '/root/k',
|
||||||
|
'permission': 600,
|
||||||
|
'size': '1.7 KB',
|
||||||
|
'sizeByte': 1766,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': 'drwxr-xr-x',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': true,
|
||||||
|
'modifyTime': 1652942938000,
|
||||||
|
'name': 'bbb',
|
||||||
|
'path': '/root/bbb',
|
||||||
|
'permission': 755,
|
||||||
|
'size': '4 KB',
|
||||||
|
'sizeByte': 4096,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': 'drwxr-xr-x',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': true,
|
||||||
|
'modifyTime': 1675653580000,
|
||||||
|
'name': 'swapper',
|
||||||
|
'path': '/root/swapper',
|
||||||
|
'permission': 755,
|
||||||
|
'size': '4 KB',
|
||||||
|
'sizeByte': 4096,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1639443147000,
|
||||||
|
'name': 'tmp2.txt',
|
||||||
|
'path': '/root/tmp2.txt',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '184 B',
|
||||||
|
'sizeByte': 184,
|
||||||
|
'suffix': 'txt',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': 'drwxr-xr-x',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': true,
|
||||||
|
'modifyTime': 1653277297000,
|
||||||
|
'name': 'test',
|
||||||
|
'path': '/root/test',
|
||||||
|
'permission': 755,
|
||||||
|
'size': '4 KB',
|
||||||
|
'sizeByte': 4096,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1625064193000,
|
||||||
|
'name': 'a1.rar',
|
||||||
|
'path': '/root/a1.rar',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '52 MB',
|
||||||
|
'sizeByte': 54528512,
|
||||||
|
'suffix': 'rar',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rwxrwxrwx',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1704289282000,
|
||||||
|
'name': 'bridge.sh',
|
||||||
|
'path': '/root/bridge.sh',
|
||||||
|
'permission': 777,
|
||||||
|
'size': '396 B',
|
||||||
|
'sizeByte': 396,
|
||||||
|
'suffix': 'sh',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': 'drwxr-xr-x',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': true,
|
||||||
|
'modifyTime': 1663829274000,
|
||||||
|
'name': 'orion-ops',
|
||||||
|
'path': '/root/orion-ops',
|
||||||
|
'permission': 755,
|
||||||
|
'size': '4 KB',
|
||||||
|
'sizeByte': 4096,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1668680082000,
|
||||||
|
'name': 'ub.txt',
|
||||||
|
'path': '/root/ub.txt',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '71.7 MB',
|
||||||
|
'sizeByte': 75167744,
|
||||||
|
'suffix': 'txt',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rwxrwxrwx',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1668594989000,
|
||||||
|
'name': 'osx.d',
|
||||||
|
'path': '/root/osx.d',
|
||||||
|
'permission': 777,
|
||||||
|
'size': '170 B',
|
||||||
|
'sizeByte': 170,
|
||||||
|
'suffix': 'd',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': 'drwxr-xr-x',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': true,
|
||||||
|
'modifyTime': 1636337848000,
|
||||||
|
'name': 'temp',
|
||||||
|
'path': '/root/temp',
|
||||||
|
'permission': 755,
|
||||||
|
'size': '4 KB',
|
||||||
|
'sizeByte': 4096,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1659524667000,
|
||||||
|
'name': '46746619-175F-41c0-8D0E-0007E9271507.png',
|
||||||
|
'path': '/root/46746619-175F-41c0-8D0E-0007E9271507.png',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '158.1 KB',
|
||||||
|
'sizeByte': 161927,
|
||||||
|
'suffix': 'png',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': 'drwxr-xr-x',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': true,
|
||||||
|
'modifyTime': 1646190836000,
|
||||||
|
'name': 'video',
|
||||||
|
'path': '/root/video',
|
||||||
|
'permission': 755,
|
||||||
|
'size': '4 KB',
|
||||||
|
'sizeByte': 4096,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1625136042000,
|
||||||
|
'name': 'sql1.txt',
|
||||||
|
'path': '/root/sql1.txt',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '16.9 KB',
|
||||||
|
'sizeByte': 17334,
|
||||||
|
'suffix': 'txt',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1665545226000,
|
||||||
|
'name': 'ts.txt',
|
||||||
|
'path': '/root/ts.txt',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '101.6 KB',
|
||||||
|
'sizeByte': 104004,
|
||||||
|
'suffix': 'txt',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1635090505000,
|
||||||
|
'name': 'shop.xlsx',
|
||||||
|
'path': '/root/shop.xlsx',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '87.9 KB',
|
||||||
|
'sizeByte': 89993,
|
||||||
|
'suffix': 'xlsx',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1635127741000,
|
||||||
|
'name': 'Java 8实战.pdf',
|
||||||
|
'path': '/root/Java 8实战.pdf',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '12.9 MB',
|
||||||
|
'sizeByte': 13490536,
|
||||||
|
'suffix': 'pdf',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': '-rw-r--r--',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': false,
|
||||||
|
'modifyTime': 1662626999000,
|
||||||
|
'name': 'Postman-win64-6.5.3-Setup.exe',
|
||||||
|
'path': '/root/Postman-win64-6.5.3-Setup.exe',
|
||||||
|
'permission': 644,
|
||||||
|
'size': '68.1 MB',
|
||||||
|
'sizeByte': 71401080,
|
||||||
|
'suffix': 'exe',
|
||||||
|
'uid': 0
|
||||||
|
}, {
|
||||||
|
'attr': 'drwxr-xr-x',
|
||||||
|
'gid': 0,
|
||||||
|
'isDir': true,
|
||||||
|
'modifyTime': 1662627183000,
|
||||||
|
'name': 'jar',
|
||||||
|
'path': '/root/jar',
|
||||||
|
'permission': 755,
|
||||||
|
'size': '4 KB',
|
||||||
|
'sizeByte': 4096,
|
||||||
|
'suffix': '',
|
||||||
|
'uid': 0
|
||||||
|
}];
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
<template>
|
||||||
|
<a-table row-key="name"
|
||||||
|
class="sftp-table"
|
||||||
|
label-align="left"
|
||||||
|
:columns="columns"
|
||||||
|
v-model:selected-keys="selectedKeys"
|
||||||
|
:row-selection="rowSelection"
|
||||||
|
:sticky-header="true"
|
||||||
|
:data="list"
|
||||||
|
:pagination="false"
|
||||||
|
:bordered="false"
|
||||||
|
@cell-mouse-enter="setEditable"
|
||||||
|
@cell-mouse-leave="unsetEditable">
|
||||||
|
<!-- 文件搜索框 -->
|
||||||
|
<template #nameFilter="{ filterValue, setFilterValue, handleFilterConfirm, handleFilterReset}">
|
||||||
|
<div class="name-filter">
|
||||||
|
<a-space direction="vertical">
|
||||||
|
<!-- 过滤输入框 -->
|
||||||
|
<a-input size="small"
|
||||||
|
:model-value="filterValue[0]"
|
||||||
|
@input="(value) => setFilterValue([value])" />
|
||||||
|
<!-- 按钮 -->
|
||||||
|
<div class="name-filter-footer">
|
||||||
|
<a-button size="small" @click="handleFilterConfirm">过滤</a-button>
|
||||||
|
<a-button size="small" @click="handleFilterReset">重置</a-button>
|
||||||
|
</div>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<!-- 文件大小 -->
|
||||||
|
<template #size="{ record }">
|
||||||
|
<span v-if="editRecord.name === record.name">操作</span>
|
||||||
|
<span v-else>{{ record.size }}</span>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'sftpTable'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { TableData } from '@arco-design/web-vue/es/table/interface';
|
||||||
|
import type { SftpFile } from '../../types/terminal.type';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useRowSelection } from '@/types/table';
|
||||||
|
import columns from './types/table.columns';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
list: Array<SftpFile>;
|
||||||
|
loading: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const rowSelection = useRowSelection();
|
||||||
|
const selectedKeys = ref<Array<string>>([]);
|
||||||
|
const editRecord = ref<TableData>({});
|
||||||
|
|
||||||
|
// 设置选中状态
|
||||||
|
const setEditable = (record: TableData) => {
|
||||||
|
editRecord.value = record;
|
||||||
|
record.hover = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 设置未选中状态
|
||||||
|
const unsetEditable = (record: TableData) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (record.name === editRecord.value.name && !record.hover) {
|
||||||
|
editRecord.value = {};
|
||||||
|
}
|
||||||
|
}, 20);
|
||||||
|
record.hover = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.sftp-table {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name-filter {
|
||||||
|
padding: 12px;
|
||||||
|
background: var(--color-bg-5);
|
||||||
|
border: 1px solid var(--color-neutral-3);
|
||||||
|
border-radius: var(--border-radius-medium);
|
||||||
|
box-shadow: 0 2px 5px rgb(0 0 0 / 10%);
|
||||||
|
|
||||||
|
&-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -1,8 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="sftp-container">
|
||||||
{{ tab }}
|
<!-- 头部 -->
|
||||||
<div>header</div>
|
<div class="sftp-header">
|
||||||
<div>table</div>
|
<!-- 左侧操作 -->
|
||||||
|
<div class="sftp-header-left">
|
||||||
|
home input
|
||||||
|
</div>
|
||||||
|
<!-- 右侧操作 -->
|
||||||
|
<div class="sftp-header-right">
|
||||||
|
上传 下载 删除 刷新 copy touch mk
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a-split class="split-view"
|
||||||
|
v-model:size="splitSize"
|
||||||
|
:min="0.3"
|
||||||
|
:disabled="!editView">
|
||||||
|
<!-- 表格 -->
|
||||||
|
<template #first>
|
||||||
|
<sftp-table :list="list"
|
||||||
|
:loading="loading" />
|
||||||
|
</template>
|
||||||
|
<template #second v-if="editView">
|
||||||
|
<div>editor</div>
|
||||||
|
</template>
|
||||||
|
</a-split>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -13,14 +34,75 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { TerminalTabItem } from '../../types/terminal.type';
|
import type { ISftpSession, SftpFile, TerminalTabItem } from '../../types/terminal.type';
|
||||||
|
import { onMounted, onUnmounted, ref } from 'vue';
|
||||||
|
import { useTerminalStore } from '@/store';
|
||||||
|
import useLoading from '@/hooks/loading';
|
||||||
|
import data from './data';
|
||||||
|
import SftpTable from '@/views/host/terminal/components/sftp/sftp-table.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
tab: TerminalTabItem
|
tab: TerminalTabItem
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const { preference, sessionManager } = useTerminalStore();
|
||||||
|
const { loading, setLoading } = useLoading(true);
|
||||||
|
|
||||||
|
const session = ref<ISftpSession>();
|
||||||
|
const currentPath = ref<string>('');
|
||||||
|
const list = ref<Array<SftpFile>>(data);
|
||||||
|
const splitSize = ref(1);
|
||||||
|
const editView = ref(true);
|
||||||
|
|
||||||
|
// 初始化会话
|
||||||
|
onMounted(async () => {
|
||||||
|
// 创建终端处理器
|
||||||
|
session.value = await sessionManager.openSftp(props.tab, {
|
||||||
|
list,
|
||||||
|
currentPath,
|
||||||
|
setLoading
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 关闭会话
|
||||||
|
onUnmounted(() => {
|
||||||
|
sessionManager.closeSession(props.tab.key);
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
@sftp-header-height: 36px;
|
||||||
|
|
||||||
|
.sftp-container {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100vh - var(--header-height) - var(--panel-nav-height));
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.split-view {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - @sftp-header-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sftp-header {
|
||||||
|
width: 100%;
|
||||||
|
height: @sftp-header-height;
|
||||||
|
padding: 0 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
background: var(--color-bg-panel-bar);
|
||||||
|
|
||||||
|
&-left, &-right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-right {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
|
||||||
|
import { dateFormat } from '@/utils';
|
||||||
|
|
||||||
|
// 表格列
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
slotName: 'name',
|
||||||
|
fixed: 'left',
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
},
|
||||||
|
filterable: {
|
||||||
|
filter: (value, record) => record.name.includes(value),
|
||||||
|
slotName: 'nameFilter',
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
title: '大小',
|
||||||
|
dataIndex: 'sizeByte',
|
||||||
|
slotName: 'size',
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
title: '属性',
|
||||||
|
dataIndex: 'attr',
|
||||||
|
slotName: 'attr',
|
||||||
|
}, {
|
||||||
|
title: '修改时间',
|
||||||
|
dataIndex: 'modifyTime',
|
||||||
|
slotName: 'modifyTime',
|
||||||
|
align: 'center',
|
||||||
|
sortable: {
|
||||||
|
sortDirections: ['ascend', 'descend'],
|
||||||
|
},
|
||||||
|
render: ({ record }) => {
|
||||||
|
return dateFormat(new Date(record.modifyTime));
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'actions',
|
||||||
|
slotName: 'actions',
|
||||||
|
align: 'left',
|
||||||
|
fixed: 'right',
|
||||||
|
},
|
||||||
|
] as TableColumnData[];
|
||||||
|
|
||||||
|
export default columns;
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import type { ISftpSession, ISftpSessionResolver, SftpDataRef, SftpFile } from '../types/terminal.type';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
// sftp 会话接收器实现
|
||||||
|
export default class SftpSessionResolver implements ISftpSessionResolver {
|
||||||
|
|
||||||
|
private readonly dataRef: SftpDataRef;
|
||||||
|
|
||||||
|
private readonly session: ISftpSession;
|
||||||
|
|
||||||
|
constructor(session: ISftpSession,
|
||||||
|
dataRef: SftpDataRef) {
|
||||||
|
this.session = session;
|
||||||
|
this.dataRef = dataRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 接受文件列表响应
|
||||||
|
resolveList(result: string, path: string, list: Array<SftpFile>) {
|
||||||
|
const success = !!Number.parseInt(result);
|
||||||
|
this.dataRef.setLoading(false);
|
||||||
|
if (!success) {
|
||||||
|
Message.error('查询失败');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.dataRef.currentPath = path;
|
||||||
|
this.dataRef.list = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { ISftpSession, ITerminalChannel } from '../types/terminal.type';
|
import type { ISftpSession, ISftpSessionResolver, ITerminalChannel, SftpDataRef } from '../types/terminal.type';
|
||||||
import { InputProtocol } from '../types/terminal.protocol';
|
import { InputProtocol } from '../types/terminal.protocol';
|
||||||
|
import SftpSessionResolver from './sftp-session-resolver';
|
||||||
|
|
||||||
// sftp 会话实现
|
// sftp 会话实现
|
||||||
export default class SftpSession implements ISftpSession {
|
export default class SftpSession implements ISftpSession {
|
||||||
@@ -10,6 +11,10 @@ export default class SftpSession implements ISftpSession {
|
|||||||
|
|
||||||
public connected: boolean;
|
public connected: boolean;
|
||||||
|
|
||||||
|
public resolver: ISftpSessionResolver;
|
||||||
|
|
||||||
|
private dataRef: SftpDataRef;
|
||||||
|
|
||||||
private readonly channel: ITerminalChannel;
|
private readonly channel: ITerminalChannel;
|
||||||
|
|
||||||
constructor(hostId: number,
|
constructor(hostId: number,
|
||||||
@@ -19,13 +24,33 @@ export default class SftpSession implements ISftpSession {
|
|||||||
this.sessionId = sessionId;
|
this.sessionId = sessionId;
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
|
this.dataRef = undefined as unknown as SftpDataRef;
|
||||||
|
this.resolver = undefined as unknown as ISftpSessionResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
init(dataRef: SftpDataRef): void {
|
||||||
|
this.dataRef = dataRef;
|
||||||
|
// 处理器
|
||||||
|
this.resolver = new SftpSessionResolver(this, dataRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置已连接
|
// 设置已连接
|
||||||
connect(): void {
|
connect(): void {
|
||||||
this.connected = true;
|
this.connected = true;
|
||||||
|
// 加载 home 目录文件数据
|
||||||
|
this.list(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查询文件列表
|
||||||
|
list(path: string | undefined) {
|
||||||
|
this.dataRef.setLoading(true);
|
||||||
|
this.channel.send(InputProtocol.SFTP_LIST, {
|
||||||
|
sessionId: this.sessionId,
|
||||||
|
path
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// 断开连接
|
// 断开连接
|
||||||
disconnect(): void {
|
disconnect(): void {
|
||||||
// 发送关闭消息
|
// 发送关闭消息
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ export default class SshSession implements ISshSession {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 输入
|
// 输入
|
||||||
this.channel.send(InputProtocol.INPUT, {
|
this.channel.send(InputProtocol.SSH_INPUT, {
|
||||||
sessionId: this.sessionId,
|
sessionId: this.sessionId,
|
||||||
command: s
|
command: s
|
||||||
});
|
});
|
||||||
@@ -134,7 +134,7 @@ export default class SshSession implements ISshSession {
|
|||||||
if (!this.connected) {
|
if (!this.connected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.channel.send(InputProtocol.RESIZE, {
|
this.channel.send(InputProtocol.SSH_RESIZE, {
|
||||||
sessionId: this.sessionId,
|
sessionId: this.sessionId,
|
||||||
cols,
|
cols,
|
||||||
rows
|
rows
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ISshSession, ITerminalChannel, ITerminalOutputProcessor, ITerminalSessionManager, OutputPayload } from '../types/terminal.type';
|
import { ISftpSession, ISshSession, ITerminalChannel, ITerminalOutputProcessor, ITerminalSessionManager, OutputPayload } from '../types/terminal.type';
|
||||||
import { InputProtocol } from '../types/terminal.protocol';
|
import { InputProtocol } from '../types/terminal.protocol';
|
||||||
import { TerminalStatus } from '../types/terminal.const';
|
import { TerminalStatus } from '../types/terminal.const';
|
||||||
import { useTerminalStore } from '@/store';
|
import { useTerminalStore } from '@/store';
|
||||||
@@ -42,8 +42,9 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
|
|||||||
// sftp 会话
|
// sftp 会话
|
||||||
if (success) {
|
if (success) {
|
||||||
// 检查成功发送 connect 命令
|
// 检查成功发送 connect 命令
|
||||||
// TODO
|
this.channel.send(InputProtocol.CONNECT, {
|
||||||
|
sessionId,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// 未成功提示错误信息
|
// 未成功提示错误信息
|
||||||
Message.error(msg || '建立 SFTP 失败');
|
Message.error(msg || '建立 SFTP 失败');
|
||||||
@@ -105,10 +106,17 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
|
|||||||
// console.log('pong');
|
// console.log('pong');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理输出消息
|
// 处理 SSH 输出消息
|
||||||
processOutput({ sessionId, body }: OutputPayload): void {
|
processSshOutput({ sessionId, body }: OutputPayload): void {
|
||||||
const session = this.sessionManager.getSession<ISshSession>(sessionId);
|
const session = this.sessionManager.getSession<ISshSession>(sessionId);
|
||||||
session && session.write(body);
|
session && session.write(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理 SFTP 文件列表
|
||||||
|
processSftpList({ sessionId, result, path, body }: OutputPayload): void {
|
||||||
|
// 获取会话
|
||||||
|
const session = this.sessionManager.getSession<ISftpSession>(sessionId);
|
||||||
|
session && session.resolver.resolveList(result, path, JSON.parse(body));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
import type { ISftpSession, ITerminalChannel, ITerminalSession, ITerminalSessionManager, TerminalTabItem, XtermDomRef } from '../types/terminal.type';
|
import type {
|
||||||
|
ISftpSession,
|
||||||
|
ITerminalChannel,
|
||||||
|
ITerminalSession,
|
||||||
|
ITerminalSessionManager,
|
||||||
|
SftpDataRef,
|
||||||
|
TerminalTabItem,
|
||||||
|
XtermDomRef
|
||||||
|
} from '../types/terminal.type';
|
||||||
import { sleep } from '@/utils';
|
import { sleep } from '@/utils';
|
||||||
import { InputProtocol } from '../types/terminal.protocol';
|
import { InputProtocol } from '../types/terminal.protocol';
|
||||||
import { PanelSessionType } from '../types/terminal.const';
|
import { PanelSessionType } from '../types/terminal.const';
|
||||||
@@ -54,7 +62,7 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 打开 sftp 会话
|
// 打开 sftp 会话
|
||||||
async openSftp(tab: TerminalTabItem): Promise<ISftpSession> {
|
async openSftp(tab: TerminalTabItem, dataRef: SftpDataRef): Promise<ISftpSession> {
|
||||||
const sessionId = tab.key;
|
const sessionId = tab.key;
|
||||||
const hostId = tab.hostId as number;
|
const hostId = tab.hostId as number;
|
||||||
// 初始化客户端
|
// 初始化客户端
|
||||||
@@ -65,6 +73,8 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
|
|||||||
sessionId,
|
sessionId,
|
||||||
this.channel
|
this.channel
|
||||||
);
|
);
|
||||||
|
// 初始化
|
||||||
|
session.init(dataRef);
|
||||||
// 添加会话
|
// 添加会话
|
||||||
this.sessions[sessionId] = session;
|
this.sessions[sessionId] = session;
|
||||||
// 发送会话初始化请求
|
// 发送会话初始化请求
|
||||||
|
|||||||
@@ -55,11 +55,11 @@ export const ExtraSshAuthType = {
|
|||||||
// 面板会话 tab 类型
|
// 面板会话 tab 类型
|
||||||
export const PanelSessionType = {
|
export const PanelSessionType = {
|
||||||
SSH: {
|
SSH: {
|
||||||
type: 'ssh',
|
type: 'SSH',
|
||||||
icon: 'icon-desktop'
|
icon: 'icon-desktop'
|
||||||
},
|
},
|
||||||
SFTP: {
|
SFTP: {
|
||||||
type: 'sftp',
|
type: 'SFTP',
|
||||||
icon: 'icon-folder'
|
icon: 'icon-folder'
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,16 +20,21 @@ export const InputProtocol = {
|
|||||||
type: 'p',
|
type: 'p',
|
||||||
template: ['type']
|
template: ['type']
|
||||||
},
|
},
|
||||||
// 修改大小
|
// SSH 修改大小
|
||||||
RESIZE: {
|
SSH_RESIZE: {
|
||||||
type: 'rs',
|
type: 'rs',
|
||||||
template: ['type', 'sessionId', 'cols', 'rows']
|
template: ['type', 'sessionId', 'cols', 'rows']
|
||||||
},
|
},
|
||||||
// 输入
|
// SSH 输入
|
||||||
INPUT: {
|
SSH_INPUT: {
|
||||||
type: 'i',
|
type: 'i',
|
||||||
template: ['type', 'sessionId', 'command']
|
template: ['type', 'sessionId', 'command']
|
||||||
}
|
},
|
||||||
|
// SFTP 文件列表
|
||||||
|
SFTP_LIST: {
|
||||||
|
type: 'ls',
|
||||||
|
template: ['type', 'sessionId', 'path']
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// 输出协议
|
// 输出协议
|
||||||
@@ -58,10 +63,16 @@ export const OutputProtocol = {
|
|||||||
template: ['type'],
|
template: ['type'],
|
||||||
processMethod: 'processPong'
|
processMethod: 'processPong'
|
||||||
},
|
},
|
||||||
// 输出
|
// SSH 输出
|
||||||
OUTPUT: {
|
SSH_OUTPUT: {
|
||||||
type: 'o',
|
type: 'o',
|
||||||
template: ['type', 'sessionId', 'body'],
|
template: ['type', 'sessionId', 'body'],
|
||||||
processMethod: 'processOutput'
|
processMethod: 'processSshOutput'
|
||||||
|
},
|
||||||
|
// SFTP 文件列表
|
||||||
|
SFTP_LIST: {
|
||||||
|
type: 'ls',
|
||||||
|
template: ['type', 'sessionId', 'result', 'path', 'body'],
|
||||||
|
processMethod: 'processSftpList'
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ export interface ITerminalSessionManager {
|
|||||||
// 打开 ssh 会话
|
// 打开 ssh 会话
|
||||||
openSsh: (tab: TerminalTabItem, domRef: XtermDomRef) => Promise<ISshSession>;
|
openSsh: (tab: TerminalTabItem, domRef: XtermDomRef) => Promise<ISshSession>;
|
||||||
// 打开 sftp 会话
|
// 打开 sftp 会话
|
||||||
openSftp: (tab: TerminalTabItem) => Promise<ISftpSession>;
|
openSftp: (tab: TerminalTabItem, dataRef: SftpDataRef) => Promise<ISftpSession>;
|
||||||
// 获取终端会话
|
// 获取终端会话
|
||||||
getSession: <T extends ITerminalSession>(sessionId: string) => T;
|
getSession: <T extends ITerminalSession>(sessionId: string) => T;
|
||||||
// 关闭终端会话
|
// 关闭终端会话
|
||||||
@@ -176,18 +176,20 @@ export interface ITerminalOutputProcessor {
|
|||||||
processClose: (payload: OutputPayload) => void;
|
processClose: (payload: OutputPayload) => void;
|
||||||
// 处理 pong 消息
|
// 处理 pong 消息
|
||||||
processPong: (payload: OutputPayload) => void;
|
processPong: (payload: OutputPayload) => void;
|
||||||
// 处理输出消息
|
// 处理 SSH 输出消息
|
||||||
processOutput: (payload: OutputPayload) => void;
|
processSshOutput: (payload: OutputPayload) => void;
|
||||||
|
// 处理 SFTP 文件列表
|
||||||
|
processSftpList: (payload: OutputPayload) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 终端 dom 元素引用
|
// xterm dom 元素引用
|
||||||
export interface XtermDomRef {
|
export interface XtermDomRef {
|
||||||
el: HTMLElement;
|
el: HTMLElement;
|
||||||
searchModal: any;
|
searchModal: any;
|
||||||
editorModal: any;
|
editorModal: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 终端插件
|
// xterm 插件
|
||||||
export interface XtermAddons {
|
export interface XtermAddons {
|
||||||
fit: FitAddon;
|
fit: FitAddon;
|
||||||
webgl: WebglAddon;
|
webgl: WebglAddon;
|
||||||
@@ -197,6 +199,16 @@ export interface XtermAddons {
|
|||||||
image: ImageAddon;
|
image: ImageAddon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sftp 数据引用
|
||||||
|
export interface SftpDataRef {
|
||||||
|
// 文件列表
|
||||||
|
list: any;
|
||||||
|
// 当前路径
|
||||||
|
currentPath: any;
|
||||||
|
// 设置加载状态
|
||||||
|
setLoading: (loading: boolean) => void;
|
||||||
|
}
|
||||||
|
|
||||||
// 终端会话定义
|
// 终端会话定义
|
||||||
export interface ITerminalSession {
|
export interface ITerminalSession {
|
||||||
hostId: number;
|
hostId: number;
|
||||||
@@ -288,5 +300,32 @@ export interface ISshSessionHandler {
|
|||||||
|
|
||||||
// sftp 会话定义
|
// sftp 会话定义
|
||||||
export interface ISftpSession extends ITerminalSession {
|
export interface ISftpSession extends ITerminalSession {
|
||||||
|
// 接收器
|
||||||
|
resolver: ISftpSessionResolver;
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
init: (dataRef: SftpDataRef) => void;
|
||||||
|
// 查询文件列表
|
||||||
|
list: (path: string | undefined) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sftp 会话接收器定义
|
||||||
|
export interface ISftpSessionResolver {
|
||||||
|
// 接受文件列表响应
|
||||||
|
resolveList: (result: string, path: string, list: Array<SftpFile>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sftp 文件
|
||||||
|
export interface SftpFile {
|
||||||
|
name: string;
|
||||||
|
path: string;
|
||||||
|
suffix: string;
|
||||||
|
size: string;
|
||||||
|
sizeByte: number;
|
||||||
|
attr: string;
|
||||||
|
isDir: boolean;
|
||||||
|
permission: number;
|
||||||
|
uid: number;
|
||||||
|
gid: number;
|
||||||
|
modifyTime: number;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user