diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/CodeGenerators.java b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/CodeGenerators.java
index bdabf5b9..1cd3bd16 100644
--- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/CodeGenerators.java
+++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/java/org/dromara/visor/framework/mybatis/core/generator/CodeGenerators.java
@@ -23,6 +23,8 @@
package org.dromara.visor.framework.mybatis.core.generator;
import cn.orionsec.kit.lang.constant.Const;
+import cn.orionsec.kit.lang.utils.Strings;
+import cn.orionsec.kit.lang.utils.Systems;
import cn.orionsec.kit.lang.utils.ansi.AnsiAppender;
import cn.orionsec.kit.lang.utils.ansi.style.AnsiFont;
import cn.orionsec.kit.lang.utils.ansi.style.color.AnsiForeground;
@@ -32,6 +34,8 @@ import org.dromara.visor.framework.mybatis.core.generator.template.Table;
import org.dromara.visor.framework.mybatis.core.generator.template.Template;
import java.io.File;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* 代码生成器
@@ -42,6 +46,8 @@ import java.io.File;
*/
public class CodeGenerators {
+ private static final Pattern ENV_VAR_PATTERN = Pattern.compile("\\$\\{([^:]+):([^}]+)\\}");
+
public static void main(String[] args) {
// 输出路径
String outputDir = "D:/MP/";
@@ -76,11 +82,6 @@ public class CodeGenerators {
.disableUnitTest()
.enableProviderApi()
.vue("system", "message")
- .dict("messageClassify", "classify", "messageClassify")
- .comment("消息分类")
- .fields("NOTICE", "TODO")
- .labels("通知", "待办")
- .valueUseFields()
.dict("messageType", "type", "messageType")
.comment("消息类型")
.fields("EXEC_FAILED", "UPLOAD_FAILED")
@@ -94,9 +95,9 @@ public class CodeGenerators {
// jdbc 配置 - 使用配置文件
File yamlFile = new File("orion-visor-launch/src/main/resources/application-dev.yaml");
YmlExt yaml = YmlExt.load(yamlFile);
- String url = yaml.getValue("spring.datasource.druid.url");
- String username = yaml.getValue("spring.datasource.druid.username");
- String password = yaml.getValue("spring.datasource.druid.password");
+ String url = resolveConfigValue(yaml.getValue("spring.datasource.druid.url"));
+ String username = resolveConfigValue(yaml.getValue("spring.datasource.druid.username"));
+ String password = resolveConfigValue(yaml.getValue("spring.datasource.druid.password"));
// 执行
runGenerator(outputDir, author,
@@ -147,4 +148,31 @@ public class CodeGenerators {
System.out.print(line);
}
+ /**
+ * 解析实际的配置
+ *
+ * @param value value
+ * @return value
+ */
+ private static String resolveConfigValue(String value) {
+ if (Strings.isBlank(value)) {
+ return value;
+ }
+ Matcher matcher = ENV_VAR_PATTERN.matcher(value);
+ StringBuffer resultString = new StringBuffer();
+ while (matcher.find()) {
+ // 环境变量名
+ String envVar = matcher.group(1);
+ // 默认值
+ String defaultValue = matcher.group(2);
+ // 获取环境变量的值
+ String envValue = Systems.getEnv(envVar, defaultValue);
+ // 替换占位符
+ matcher.appendReplacement(resultString, Matcher.quoteReplacement(envValue));
+ }
+ // 处理结尾的剩余部分
+ matcher.appendTail(resultString);
+ return resultString.toString();
+ }
+
}
diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-sql-dict.sql.vm b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-sql-dict.sql.vm
index a6779d46..2c1bb0ec 100644
--- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-sql-dict.sql.vm
+++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-sql-dict.sql.vm
@@ -11,10 +11,10 @@ SELECT @TYPE_KEY_ID:= id FROM dict_key WHERE key_name = 'operatorLogType' AND de
INSERT INTO dict_value
(`key_id`, `key_name`, `value`, `label`, `extra`, `sort`, `create_time`, `update_time`, `creator`, `updater`, `deleted`)
VALUES
- (@MODULE_KEY_ID, 'operatorLogModule', '${package.ModuleName}:${typeHyphen}', '$!{table.comment}', '{}', @MODULE_KEY_MAX_SORT + 10, now(), now(), '1', '1', 0),
- (@TYPE_KEY_ID, 'operatorLogType', '${typeHyphen}:create', '创建$!{table.comment}', '{}', 10, now(), now(), '1', '1', 0),
- (@TYPE_KEY_ID, 'operatorLogType', '${typeHyphen}:update', '更新$!{table.comment}', '{}', 20, now(), now(), '1', '1', 0),
- (@TYPE_KEY_ID, 'operatorLogType', '${typeHyphen}:delete', '删除$!{table.comment}', '{}', 30, now(), now(), '1', '1', 0);
+ (@MODULE_KEY_ID, 'operatorLogModule', '${package.ModuleName}:${typeHyphen}', '$!{table.comment}', '{}', @MODULE_KEY_MAX_SORT + 10, now(), now(), 'admin', 'admin', 0),
+ (@TYPE_KEY_ID, 'operatorLogType', '${typeHyphen}:create', '创建$!{table.comment}', '{}', 10, now(), now(), 'admin', 'admin', 0),
+ (@TYPE_KEY_ID, 'operatorLogType', '${typeHyphen}:update', '更新$!{table.comment}', '{}', 20, now(), now(), 'admin', 'admin', 0),
+ (@TYPE_KEY_ID, 'operatorLogType', '${typeHyphen}:delete', '删除$!{table.comment}', '{}', 30, now(), now(), 'admin', 'admin', 0);
#end
#if($dictMap.entrySet().size() > 0)
@@ -23,7 +23,7 @@ VALUES
INSERT INTO dict_key
(`key_name`, `value_type`, `extra_schema`, `description`, `create_time`, `update_time`, `creator`, `updater`, `deleted`)
VALUES
- ('$enumEntity.value.keyName', 'STRING', '$enumEntity.value.extraSchema', '$enumEntity.value.comment', now(), now(), '1', '1', 0);
+ ('$enumEntity.value.keyName', 'STRING', '$enumEntity.value.extraSchema', '$enumEntity.value.comment', now(), now(), 'admin', 'admin', 0);
-- 设置临时配置项id
SELECT @TMP_KEY_ID:=LAST_INSERT_ID();
@@ -35,7 +35,7 @@ VALUES
#set($count = $enumEntity.value.fields.size() - 1)
#foreach($index in [0..$count])
#set($sort = $index * 10 + 10)
- (@TMP_KEY_ID, '$enumEntity.value.keyName', '$enumEntity.value.values.get($index)', '$enumEntity.value.labels.get($index)', #if($enumEntity.value.extraJson.size() > $index)'$enumEntity.value.extraJson.get($index)'#else'{}'#end, $sort, now(), now(), '1', '1', 0)#if($foreach.hasNext),#else;#end
+ (@TMP_KEY_ID, '$enumEntity.value.keyName', '$enumEntity.value.values.get($index)', '$enumEntity.value.labels.get($index)', #if($enumEntity.value.extraJson.size() > $index)'$enumEntity.value.extraJson.get($index)'#else'{}'#end, $sort, now(), now(), 'admin', 'admin', 0)#if($foreach.hasNext),#else;#end
#end
#end
diff --git a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-sql-menu.sql.vm b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-sql-menu.sql.vm
index 44cf25a1..db7938fa 100644
--- a/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-sql-menu.sql.vm
+++ b/orion-visor-framework/orion-visor-spring-boot-starter-mybatis/src/main/resources/templates/orion-sql-menu.sql.vm
@@ -4,7 +4,7 @@
INSERT INTO system_menu
(parent_id, name, type, sort, visible, status, cache, component, creator, updater, deleted)
VALUES
- (0, '${table.comment}管理', 1, 10, 1, 1, 1, '${vue.moduleEntityFirstLower}Module', '1', '1', 0);
+ (0, '${table.comment}管理', 1, 10, 1, 1, 1, '${vue.moduleEntityFirstLower}Module', 'admin', 'admin', 0);
-- 设置临时父菜单id
SELECT @TMP_PARENT_ID:=LAST_INSERT_ID();
@@ -13,7 +13,7 @@ SELECT @TMP_PARENT_ID:=LAST_INSERT_ID();
INSERT INTO system_menu
(parent_id, name, type, sort, visible, status, cache, component, creator, updater, deleted)
VALUES
- (@TMP_PARENT_ID, '$table.comment', 2, 10, 1, 1, 1, '$vue.featureEntityFirstLower', '1', '1', 0);
+ (@TMP_PARENT_ID, '$table.comment', 2, 10, 1, 1, 1, '$vue.featureEntityFirstLower', 'admin', 'admin', 0);
-- 设置临时子菜单id
SELECT @TMP_SUB_ID:=LAST_INSERT_ID();
@@ -22,7 +22,7 @@ SELECT @TMP_SUB_ID:=LAST_INSERT_ID();
INSERT INTO system_menu
(parent_id, name, permission, type, sort, creator, updater, deleted)
VALUES
- (@TMP_SUB_ID, '查询$table.comment', '${package.ModuleName}:${typeHyphen}:query', 3, 10, '1', '1', 0),
- (@TMP_SUB_ID, '创建$table.comment', '${package.ModuleName}:${typeHyphen}:create', 3, 20, '1', '1', 0),
- (@TMP_SUB_ID, '修改$table.comment', '${package.ModuleName}:${typeHyphen}:update', 3, 30, '1', '1', 0),
- (@TMP_SUB_ID, '删除$table.comment', '${package.ModuleName}:${typeHyphen}:delete', 3, 40, '1', '1', 0);
+ (@TMP_SUB_ID, '查询$table.comment', '${package.ModuleName}:${typeHyphen}:query', 3, 10, 'admin', 'admin', 0),
+ (@TMP_SUB_ID, '创建$table.comment', '${package.ModuleName}:${typeHyphen}:create', 3, 20, 'admin', 'admin', 0),
+ (@TMP_SUB_ID, '修改$table.comment', '${package.ModuleName}:${typeHyphen}:update', 3, 30, 'admin', 'admin', 0),
+ (@TMP_SUB_ID, '删除$table.comment', '${package.ModuleName}:${typeHyphen}:delete', 3, 40, 'admin', 'admin', 0);
diff --git a/orion-visor-ui/src/store/modules/terminal/index.ts b/orion-visor-ui/src/store/modules/terminal/index.ts
index 73ca7c09..b9286daa 100644
--- a/orion-visor-ui/src/store/modules/terminal/index.ts
+++ b/orion-visor-ui/src/store/modules/terminal/index.ts
@@ -14,6 +14,7 @@ import { getCurrentAuthorizedHost } from '@/api/asset/asset-authorized-data';
import type { HostQueryResponse } from '@/api/asset/host';
import type { TerminalTheme, TerminalThemeSchema } from '@/api/asset/terminal';
import { getTerminalThemes } from '@/api/asset/terminal';
+import { markRaw } from 'vue';
import { defineStore } from 'pinia';
import { getPreference, updatePreference } from '@/api/user/preference';
import { getLatestConnectHostId } from '@/api/asset/terminal-connect-log';
@@ -73,7 +74,7 @@ export default defineStore('terminal', {
hosts: {} as AuthorizedHostQueryResponse,
tabManager: new TerminalTabManager(),
panelManager: new TerminalPanelManager(),
- sessionManager: new TerminalSessionManager(),
+ sessionManager: markRaw(new TerminalSessionManager()),
transferManager: new SftpTransferManager(),
}),
diff --git a/orion-visor-ui/src/views/host/terminal/components/sftp/sftp-table-header.vue b/orion-visor-ui/src/views/host/terminal/components/sftp/sftp-table-header.vue
index 62cb5890..f05e7b52 100644
--- a/orion-visor-ui/src/views/host/terminal/components/sftp/sftp-table-header.vue
+++ b/orion-visor-ui/src/views/host/terminal/components/sftp/sftp-table-header.vue
@@ -45,7 +45,7 @@
-
diff --git a/orion-visor-ui/src/views/host/terminal/components/ssh/ssh-view.vue b/orion-visor-ui/src/views/host/terminal/components/ssh/ssh-view.vue
index c3fb8164..817769ae 100644
--- a/orion-visor-ui/src/views/host/terminal/components/ssh/ssh-view.vue
+++ b/orion-visor-ui/src/views/host/terminal/components/ssh/ssh-view.vue
@@ -64,7 +64,7 @@
// 发送命令
const writeCommand = (value: string) => {
- if (session.value?.canWrite) {
+ if (session.value?.status.canWrite) {
session.value?.handler.pasteTrimEnd(value);
}
};
diff --git a/orion-visor-ui/src/views/host/terminal/handler/base-session.ts b/orion-visor-ui/src/views/host/terminal/handler/base-session.ts
index 28406f3f..7c55e19a 100644
--- a/orion-visor-ui/src/views/host/terminal/handler/base-session.ts
+++ b/orion-visor-ui/src/views/host/terminal/handler/base-session.ts
@@ -1,50 +1,66 @@
-import type { ITerminalSession, TerminalPanelTabItem } from '../types/define';
+import type { ITerminalSession, TerminalPanelTabItem, TerminalStatus } from '../types/define';
+import type { Reactive } from 'vue';
+import { reactive } from 'vue';
+import { TerminalSessionStatus } from '@/views/host/terminal/types/const';
// 会话基类
-export default abstract class BaseSession implements ITerminalSession {
+export default abstract class BaseSession implements ITerminalSession {
- public type: string;
- public hostId: number;
- public title: string;
- public address: string;
+ public readonly type: string;
+ public readonly hostId: number;
+ public readonly title: string;
+ public readonly address: string;
+ public readonly status: Reactive;
public sessionId: string;
- public connected: boolean;
- public canReconnect: boolean;
- public canWrite: boolean;
- protected constructor(type: string, tab: TerminalPanelTabItem) {
+ protected constructor(type: string, tab: TerminalPanelTabItem, status: Partial) {
this.type = type;
this.hostId = tab.hostId;
this.title = tab.title;
this.address = tab.address;
this.sessionId = tab.sessionId;
- this.connected = false;
- this.canWrite = false;
- this.canReconnect = false;
- }
-
- // 设置是否可写
- setCanWrite(canWrite: boolean): void {
- this.canWrite = canWrite;
- }
-
- // 设置已连接
- setConnected(): void {
- this.connected = true;
+ this.status = reactive({
+ connectStatus: TerminalSessionStatus.CONNECTING,
+ connected: false,
+ canWrite: false,
+ canReconnect: false,
+ ...status,
+ } as Status);
}
// 连接会话
connect(): void {
+ this.status.connectStatus = TerminalSessionStatus.CONNECTING;
}
// 断开连接
disconnect(): void {
- this.connected = false;
+ // 设置已关闭
+ this.setClosed();
}
// 关闭
close(): void {
- this.connected = false;
+ // 设置已关闭
+ this.setClosed();
+ }
+
+ // 设置是否可写
+ setCanWrite(canWrite: boolean): void {
+ this.status.canWrite = canWrite;
+ }
+
+ // 设置已连接
+ setConnected(): void {
+ this.status.connected = true;
+ this.status.connectStatus = TerminalSessionStatus.CONNECTED;
+ }
+
+ // 设置已关闭
+ setClosed(): void {
+ this.status.connected = false;
+ this.status.canWrite = false;
+ this.status.connectStatus = TerminalSessionStatus.CLOSED;
}
}
diff --git a/orion-visor-ui/src/views/host/terminal/handler/sftp-session.ts b/orion-visor-ui/src/views/host/terminal/handler/sftp-session.ts
index b2e5cff6..42eba81b 100644
--- a/orion-visor-ui/src/views/host/terminal/handler/sftp-session.ts
+++ b/orion-visor-ui/src/views/host/terminal/handler/sftp-session.ts
@@ -1,4 +1,4 @@
-import type { ISftpSession, ISftpSessionResolver, ITerminalChannel, TerminalPanelTabItem } from '../types/define';
+import type { ISftpSession, ISftpSessionResolver, ITerminalChannel, TerminalPanelTabItem, TerminalStatus } from '../types/define';
import { h } from 'vue';
import { InputProtocol } from '@/types/protocol/terminal.protocol';
import { PanelSessionType } from '../types/const';
@@ -6,7 +6,7 @@ import { Modal } from '@arco-design/web-vue';
import BaseSession from './base-session';
// sftp 会话实现
-export default class SftpSession extends BaseSession implements ISftpSession {
+export default class SftpSession extends BaseSession implements ISftpSession {
public resolver: ISftpSessionResolver;
@@ -16,7 +16,7 @@ export default class SftpSession extends BaseSession implements ISftpSession {
constructor(tab: TerminalPanelTabItem,
channel: ITerminalChannel) {
- super(PanelSessionType.SFTP.type, tab);
+ super(PanelSessionType.SFTP.type, tab, {});
this.channel = channel;
this.showHiddenFile = false;
this.resolver = undefined as unknown as ISftpSessionResolver;
@@ -27,13 +27,6 @@ export default class SftpSession extends BaseSession implements ISftpSession {
this.resolver = resolver;
}
- // 设置已连接
- setConnected(): void {
- super.setConnected();
- // 连接回调
- this.resolver.connectCallback();
- }
-
// 连接会话
connect(): void {
super.connect();
@@ -171,4 +164,11 @@ export default class SftpSession extends BaseSession implements ISftpSession {
});
}
+ // 设置已连接
+ setConnected(): void {
+ super.setConnected();
+ // 连接回调
+ this.resolver.connectCallback();
+ }
+
}
diff --git a/orion-visor-ui/src/views/host/terminal/handler/ssh-session-handler.ts b/orion-visor-ui/src/views/host/terminal/handler/ssh-session-handler.ts
index cef0a795..67de5031 100644
--- a/orion-visor-ui/src/views/host/terminal/handler/ssh-session-handler.ts
+++ b/orion-visor-ui/src/views/host/terminal/handler/ssh-session-handler.ts
@@ -91,9 +91,9 @@ export default class SshSessionHandler implements ISshSessionHandler {
case 'openSftp':
case 'uploadFile':
case 'checkAppendMissing':
- return this.session.canWrite;
+ return this.session.status.canWrite;
case 'disconnect':
- return this.session.connected;
+ return this.session.status.connected;
default:
return true;
}
@@ -197,7 +197,7 @@ export default class SshSessionHandler implements ISshSessionHandler {
// 字号增加
private fontSizeAdd(addSize: number) {
this.inst.options['fontSize'] = this.inst.options['fontSize'] as number + addSize;
- if (this.session.connected) {
+ if (this.session.status.connected) {
this.session.fit();
this.inst.focus();
}
diff --git a/orion-visor-ui/src/views/host/terminal/handler/ssh-session.ts b/orion-visor-ui/src/views/host/terminal/handler/ssh-session.ts
index 79c38480..1f9e7e1f 100644
--- a/orion-visor-ui/src/views/host/terminal/handler/ssh-session.ts
+++ b/orion-visor-ui/src/views/host/terminal/handler/ssh-session.ts
@@ -2,12 +2,12 @@ import type { UnwrapRef } from 'vue';
import type { ISearchOptions } from '@xterm/addon-search';
import { SearchAddon } from '@xterm/addon-search';
import type { TerminalPreference } from '@/store/modules/terminal/types';
-import type { ISshSession, ISshSessionHandler, ITerminalChannel, TerminalPanelTabItem, XtermDomRef } from '../types/define';
+import type { ISshSession, ISshSessionHandler, ITerminalChannel, TerminalPanelTabItem, TerminalStatus, XtermDomRef } from '../types/define';
import type { XtermAddons } from '@/types/xterm';
import { defaultFontFamily } from '@/types/xterm';
import { useTerminalStore } from '@/store';
import { InputProtocol } from '@/types/protocol/terminal.protocol';
-import { PanelSessionType, TerminalSessionStatus, TerminalShortcutType } from '../types/const';
+import { PanelSessionType, TerminalShortcutType } from '../types/const';
import { Terminal } from '@xterm/xterm';
import { FitAddon } from '@xterm/addon-fit';
import { WebLinksAddon } from '@xterm/addon-web-links';
@@ -21,12 +21,10 @@ import SshSessionHandler from './ssh-session-handler';
import BaseSession from './base-session';
// ssh 会话实现
-export default class SshSession extends BaseSession implements ISshSession {
+export default class SshSession extends BaseSession implements ISshSession {
public inst: Terminal;
- public status: number;
-
public handler: ISshSessionHandler;
private readonly channel: ITerminalChannel;
@@ -38,10 +36,9 @@ export default class SshSession extends BaseSession implements ISshSession {
constructor(tab: TerminalPanelTabItem,
channel: ITerminalChannel,
canUseWebgl: boolean) {
- super(PanelSessionType.SSH.type, tab);
+ super(PanelSessionType.SSH.type, tab, {});
this.channel = channel;
this.canUseWebgl = canUseWebgl;
- this.status = TerminalSessionStatus.CONNECTING;
this.inst = undefined as unknown as Terminal;
this.handler = undefined as unknown as ISshSessionHandler;
this.addons = {} as XtermAddons;
@@ -93,9 +90,9 @@ export default class SshSession extends BaseSession implements ISshSession {
e.preventDefault();
}
// 检查重新连接
- if (!this.connected && this.canReconnect && e.key === 'Enter') {
+ if (!this.status.connected && this.status.canReconnect && e.key === 'Enter') {
// 防止重复回车
- this.canReconnect = false;
+ this.status.canReconnect = false;
// 异步作用域重新连接
setTimeout(async () => {
await useTerminalStore().reOpenSession(this.sessionId);
@@ -120,7 +117,7 @@ export default class SshSession extends BaseSession implements ISshSession {
private registerEvent(dom: HTMLElement, preference: UnwrapRef) {
// 注册输入事件
this.inst.onData(s => {
- if (!this.canWrite || !this.connected) {
+ if (!this.status.canWrite || !this.status.connected) {
return;
}
// 输入
@@ -145,7 +142,7 @@ export default class SshSession extends BaseSession implements ISshSession {
}
// 注册 resize 事件
this.inst.onResize(({ cols, rows }) => {
- if (!this.connected) {
+ if (!this.status.connected) {
return;
}
this.channel.send(InputProtocol.SSH_RESIZE, {
@@ -158,7 +155,7 @@ export default class SshSession extends BaseSession implements ISshSession {
addEventListen(dom, 'contextmenu', async () => {
// 右键粘贴逻辑
if (preference.interactSetting.rightClickPaste) {
- if (!this.canWrite || !this.connected) {
+ if (!this.status.canWrite || !this.status.connected) {
return;
}
// 未开启右键选中 || 开启并无选中的内容则粘贴
@@ -204,29 +201,9 @@ export default class SshSession extends BaseSession implements ISshSession {
}
}
- // 设置已连接
- setConnected(): void {
- super.setConnected();
- // 设置状态
- this.status = TerminalSessionStatus.CONNECTED;
- this.inst.focus();
- }
-
- // 设置是否可写
- setCanWrite(canWrite: boolean): void {
- super.setCanWrite(canWrite);
- if (canWrite) {
- this.inst.options.cursorBlink = useTerminalStore().preference.displaySetting.cursorBlink;
- } else {
- this.inst.options.cursorBlink = false;
- }
- }
-
// 连接会话
connect(): void {
super.connect();
- // 设置状态
- this.status = TerminalSessionStatus.CONNECTING;
// 发送会话初始化请求
this.channel.send(InputProtocol.CHECK, {
sessionId: this.sessionId,
@@ -295,4 +272,20 @@ export default class SshSession extends BaseSession implements ISshSession {
}
}
+ // 设置已连接
+ setConnected(): void {
+ super.setConnected();
+ this.inst.focus();
+ }
+
+ // 设置是否可写
+ setCanWrite(canWrite: boolean): void {
+ super.setCanWrite(canWrite);
+ if (canWrite) {
+ this.inst.options.cursorBlink = useTerminalStore().preference.displaySetting.cursorBlink;
+ } else {
+ this.inst.options.cursorBlink = false;
+ }
+ }
+
}
diff --git a/orion-visor-ui/src/views/host/terminal/handler/terminal-channel.ts b/orion-visor-ui/src/views/host/terminal/handler/terminal-channel.ts
index 8b635132..b584a299 100644
--- a/orion-visor-ui/src/views/host/terminal/handler/terminal-channel.ts
+++ b/orion-visor-ui/src/views/host/terminal/handler/terminal-channel.ts
@@ -77,7 +77,7 @@ export default class TerminalChannel implements ITerminalChannel {
private closeCallback(): void {
// 关闭时将手动触发 close 消息, 有可能是其他原因关闭的, 没有接收到 close 消息, 导致已断开是终端还是显示已连接
Object.values(this.sessionManager.sessions).forEach(s => {
- if (!s?.connected) {
+ if (!s?.status.connected) {
return;
}
// close 消息
diff --git a/orion-visor-ui/src/views/host/terminal/handler/terminal-output-processor.ts b/orion-visor-ui/src/views/host/terminal/handler/terminal-output-processor.ts
index be1252a6..3dc8c51d 100644
--- a/orion-visor-ui/src/views/host/terminal/handler/terminal-output-processor.ts
+++ b/orion-visor-ui/src/views/host/terminal/handler/terminal-output-processor.ts
@@ -1,7 +1,7 @@
import type { ISftpSession, ISshSession, ITerminalChannel, ITerminalOutputProcessor, ITerminalSession, ITerminalSessionManager } from '../types/define';
import type { OutputPayload } from '@/types/protocol/terminal.protocol';
import { InputProtocol } from '@/types/protocol/terminal.protocol';
-import { PanelSessionType, TerminalSessionStatus } from '../types/const';
+import { PanelSessionType } from '../types/const';
import { useTerminalStore } from '@/store';
import { Message } from '@arco-design/web-vue';
@@ -21,7 +21,7 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
processCheck({ sessionId, result, msg }: OutputPayload): void {
const success = !!Number.parseInt(result);
const session = this.sessionManager.getSession(sessionId);
- session.canReconnect = !success;
+ session.status.canReconnect = !success;
// 处理
this.processWithType(session, ssh => {
// ssh 会话
@@ -35,9 +35,10 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
rows: ssh.inst.rows
});
} else {
+ // 设置已关闭
+ session.setClosed();
// 未成功展示错误信息
ssh.write(`[91m${msg || ''}[0m\r\n\r\n[91m输入回车重新连接...[0m\r\n\r\n`);
- ssh.status = TerminalSessionStatus.CLOSED;
}
}, sftp => {
// sftp 会话
@@ -47,6 +48,8 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
sessionId,
});
} else {
+ // 设置已关闭
+ session.setClosed();
// 未成功提示错误信息
sftp.resolver?.onClose(false, msg);
Message.error(msg || '建立 SFTP 失败');
@@ -58,29 +61,25 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
processConnect({ sessionId, result, msg }: OutputPayload): void {
const success = !!Number.parseInt(result);
const session = this.sessionManager.getSession(sessionId);
- session.canReconnect = !success;
+ session.status.canReconnect = !success;
+ if (success) {
+ // 设置可写
+ session.setCanWrite(true);
+ // 设置已连接
+ session.setConnected();
+ } else {
+ // 设置已关闭
+ session.setClosed();
+ }
// 处理
this.processWithType(session, ssh => {
- // ssh 会话
- if (success) {
- // 设置可写
- ssh.setCanWrite(true);
- // 设置已连接
- ssh.setConnected();
- } else {
- // 未成功展示错误信息
+ if (!success) {
+ // ssh 会话 未成功展示错误信息
ssh.write(`[91m${msg || ''}[0m\r\n\r\n[91m输入回车重新连接...[0m\r\n\r\n`);
- ssh.status = TerminalSessionStatus.CLOSED;
}
}, sftp => {
- // sftp 会话
- if (success) {
- // 设置可写
- sftp.setCanWrite(true);
- // 设置已连接
- sftp.setConnected();
- } else {
- // 未成功提示错误信息
+ if (!success) {
+ // sftp 会话 未成功提示错误信息
sftp.resolver?.onClose(false, msg);
Message.error(msg || '打开 SFTP 失败');
}
@@ -95,8 +94,9 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
return;
}
const isForceClose = !!Number.parseInt(forceClose);
- session.connected = false;
- session.canReconnect = !isForceClose;
+ session.status.canReconnect = !isForceClose;
+ // 设置已关闭
+ session.setClosed();
// 处理
this.processWithType(session, ssh => {
// ssh 拼接关闭消息
@@ -104,13 +104,7 @@ export default class TerminalOutputProcessor implements ITerminalOutputProcessor
if (!isForceClose) {
ssh.write('[91m输入回车重新连接...[0m\r\n\r\n');
}
- // 设置状态
- ssh.status = TerminalSessionStatus.CLOSED;
- // 设置不可写
- ssh.setCanWrite(false);
}, sftp => {
- // 设置不可写
- sftp.setCanWrite(false);
// sftp 设置状态
sftp.resolver?.onClose(isForceClose, msg);
});
diff --git a/orion-visor-ui/src/views/host/terminal/handler/terminal-session-manager.ts b/orion-visor-ui/src/views/host/terminal/handler/terminal-session-manager.ts
index ec87ab74..8983d368 100644
--- a/orion-visor-ui/src/views/host/terminal/handler/terminal-session-manager.ts
+++ b/orion-visor-ui/src/views/host/terminal/handler/terminal-session-manager.ts
@@ -104,7 +104,10 @@ export default class TerminalSessionManager implements ITerminalSessionManager {
// 移除 session
this.sessions[sessionId] = undefined as unknown as ITerminalSession;
// session 全部关闭后 关闭 channel
- if (Object.values(this.sessions).filter(Boolean).every(s => !s?.connected)) {
+ const allClosed = Object.values(this.sessions)
+ .filter(Boolean)
+ .every(s => !s?.status.connected);
+ if (allClosed) {
this.reset();
}
}
diff --git a/orion-visor-ui/src/views/host/terminal/types/define.ts b/orion-visor-ui/src/views/host/terminal/types/define.ts
index 9c6f58a4..f5cbe993 100644
--- a/orion-visor-ui/src/views/host/terminal/types/define.ts
+++ b/orion-visor-ui/src/views/host/terminal/types/define.ts
@@ -1,6 +1,6 @@
import type { Terminal } from '@xterm/xterm';
import type { ISearchOptions } from '@xterm/addon-search';
-import type { CSSProperties } from 'vue';
+import type { CSSProperties, Reactive } from 'vue';
import type { HostQueryResponse } from '@/api/asset/host';
import type { InputPayload, OutputPayload, Protocol } from '@/types/protocol/terminal.protocol';
@@ -196,38 +196,47 @@ export interface XtermDomRef {
uploadModal: any;
}
-// 终端会话定义
-export interface ITerminalSession {
- type: string;
- title: string;
- address: string;
- hostId: number;
- sessionId: string;
+// 终端状态
+export interface TerminalStatus {
+ // 连接状态
+ connectStatus: number;
// 是否已连接
connected: boolean;
- // 是否可以重新连接
- canReconnect: boolean;
// 是否可写
canWrite: boolean;
+ // 是否可以重新连接
+ canReconnect: boolean;
+}
+
+// 终端会话定义
+export interface ITerminalSession {
+ readonly type: string;
+ readonly title: string;
+ readonly address: string;
+ readonly hostId: number;
+ // 终端状态
+ readonly status: Reactive;
+ sessionId: string;
- // 设置是否可写
- setCanWrite: (canWrite: boolean) => void;
- // 设置已连接
- setConnected: () => void;
// 连接会话
connect: () => void;
// 断开连接
disconnect: () => void;
// 关闭
close: () => void;
+
+ // 设置是否可写
+ setCanWrite: (canWrite: boolean) => void;
+ // 设置已连接
+ setConnected: () => void;
+ // 设置已关闭
+ setClosed: () => void;
}
// ssh 会话定义
export interface ISshSession extends ITerminalSession {
// terminal 实例
inst: Terminal;
- // 状态
- status: number;
// 处理器
handler: ISshSessionHandler;