回车重连.

This commit is contained in:
lijiahang
2024-04-23 11:07:01 +08:00
parent c8c947d8a8
commit b6ee28731b
10 changed files with 46 additions and 122 deletions

View File

@@ -1,8 +1,20 @@
> 版本号严格遵循 Semver 规范。 > 版本号严格遵循 Semver 规范。
***sql 脚本可以在 adminer 中执行。** ***sql 脚本可以在 adminer 中执行。**
***应用不支持跨版本升级, 可以进行多次升级。** ***应用不支持跨版本升级, 可以进行多次升级。**
## v1.0.6
`2024-05-` `release`
* 🐞 修复 终端页签关闭后不会自动切换
* 🩰 修改 命令执行日志 UI 修改
* 🌈 新增 命令执行模板配置默认主机
* 🌈 新增 主机终端书签路径
* 🔨 优化 退出登录不重定向
* 🔨 优化 动态设置页面标题
* 🔨 优化 终端断开后回车重连
## v1.0.5 ## v1.0.5
`2024-04-22` `release` `2024-04-22` `release`

View File

@@ -1,8 +1,6 @@
## 功能排期 ## 功能排期
* 默认主机
* 批量上传 * 批量上传
* 文件夹书签
* 站内消息 * 站内消息
* 终端背景图片 * 终端背景图片
* 资产授权 UI 改版 * 资产授权 UI 改版

View File

@@ -169,9 +169,12 @@ export default defineStore('terminal', {
async reOpenSession(sessionId: string, panelIndex: number = 0) { async reOpenSession(sessionId: string, panelIndex: number = 0) {
// 切换到终端面板页面 // 切换到终端面板页面
this.tabManager.openTab(TerminalTabs.TERMINAL_PANEL); this.tabManager.openTab(TerminalTabs.TERMINAL_PANEL);
// 获取当前面板并且分配新的 sessionId // 获取当前面板 tab 并且分配新的 sessionId
const panel = this.panelManager.getPanel(panelIndex); const panel = this.panelManager.getPanel(panelIndex);
const tab = panel.getTab(sessionId); const tab = panel.items.find(s => s.sessionId === sessionId);
if (!tab) {
return;
}
const newSessionId = tab.sessionId = nextId(10); const newSessionId = tab.sessionId = nextId(10);
// 添加到最近连接 // 添加到最近连接
this.hosts.latestHosts = [...new Set([tab.hostId, ...this.hosts.latestHosts])]; this.hosts.latestHosts = [...new Set([tab.hostId, ...this.hosts.latestHosts])];

View File

@@ -63,24 +63,21 @@
// 监听 tab 切换 // 监听 tab 切换
watch(() => props.panel.active, (active, before) => { watch(() => props.panel.active, (active, before) => {
console.log(active);
console.log(before);
console.log(props.panel);
// 失焦自动终端 // 失焦自动终端
if (before) { if (before) {
const beforeTab = props.panel.items.find(s => s.key === before); const beforeTab = props.panel.items.find(s => s.key === before);
if (beforeTab && beforeTab?.type === PanelSessionType.SSH.type) { if (beforeTab && beforeTab?.type === PanelSessionType.SSH.type) {
sessionManager.getSession<ISshSession>(before)?.blur(); sessionManager.getSession<ISshSession>(beforeTab.sessionId)?.blur();
} }
} }
// 终端自动聚焦 // 终端自动聚焦
if (active) { if (active) {
const activeTab = props.panel.items.find(s => s.key === active); const activeTab = props.panel.items.find(s => s.key === active);
if (activeTab && activeTab?.type === PanelSessionType.SSH.type) { if (activeTab && activeTab?.type === PanelSessionType.SSH.type) {
sessionManager.getSession<ISshSession>(active)?.focus(); sessionManager.getSession<ISshSession>(activeTab.sessionId)?.focus();
} }
} }
// 无终端自动关闭 FIXME // 无终端自动关闭
if (!props.panel.items.length) { if (!props.panel.items.length) {
close(); close();
} }

View File

@@ -53,8 +53,9 @@
:title="closeMessage"> :title="closeMessage">
已断开: {{ closeMessage }} 已断开: {{ closeMessage }}
</a-tag> </a-tag>
<!-- 重连 FIXME --> <!-- 重连 -->
<a-tooltip position="top" <a-tooltip v-if="session?.canReconnect"
position="top"
:mini="true" :mini="true"
:overlay-inverse="true" :overlay-inverse="true"
:auto-fix-position="false" :auto-fix-position="false"

View File

@@ -168,7 +168,6 @@
// 连接成功回调 // 连接成功回调
const connectCallback = () => { const connectCallback = () => {
// FIXME TEST
loadFiles(currentPath.value || '~'); loadFiles(currentPath.value || '~');
}; };

View File

@@ -96,8 +96,11 @@ export default class SshSession implements ISshSession {
if (this.handler.checkPreventDefault(e)) { if (this.handler.checkPreventDefault(e)) {
e.preventDefault(); e.preventDefault();
} }
// 重新连接 // 检查重新连接
if (!this.connected && this.canReconnect && e.key === 'Enter') { if (!this.connected && this.canReconnect && e.key === 'Enter') {
// 防止重复回车
this.canReconnect = false;
// 异步作用域重新连接
setTimeout(async () => { setTimeout(async () => {
await useTerminalStore().reOpenSession(this.sessionId); await useTerminalStore().reOpenSession(this.sessionId);
}, 50); }, 50);

View File

@@ -1,5 +1,5 @@
import type { ITerminalPanelManager } from '../types/terminal.type'; import type { ITerminalPanelManager, TerminalPanelTabItem } from '../types/terminal.type';
import TerminalPanelTabManager from '../handler/terminal-panel-tab-manager'; import TerminalTabManager from '../handler/terminal-tab-manager';
// 终端面板管理器实现 // 终端面板管理器实现
export default class TerminalPanelManager implements ITerminalPanelManager { export default class TerminalPanelManager implements ITerminalPanelManager {
@@ -7,15 +7,15 @@ export default class TerminalPanelManager implements ITerminalPanelManager {
// 当前面板 // 当前面板
active: number; active: number;
// 面板列表 // 面板列表
panels: Array<TerminalPanelTabManager>; panels: Array<TerminalTabManager<TerminalPanelTabItem>>;
constructor() { constructor() {
this.active = 0; this.active = 0;
this.panels = [new TerminalPanelTabManager()]; this.panels = [new TerminalTabManager()];
} }
// 获取当前面板 // 获取当前面板
getCurrentPanel(): TerminalPanelTabManager { getCurrentPanel(): TerminalTabManager<TerminalPanelTabItem> {
return this.panels[this.active]; return this.panels[this.active];
} }
@@ -25,7 +25,7 @@ export default class TerminalPanelManager implements ITerminalPanelManager {
}; };
// 获取面板 // 获取面板
getPanel(index: number): TerminalPanelTabManager { getPanel(index: number): TerminalTabManager<TerminalPanelTabItem> {
return this.panels[index]; return this.panels[index];
}; };
@@ -41,7 +41,7 @@ export default class TerminalPanelManager implements ITerminalPanelManager {
panel.clear(); panel.clear();
} }
this.active = 0; this.active = 0;
this.panels = [new TerminalPanelTabManager()]; this.panels = [new TerminalTabManager()];
}; };
} }

View File

@@ -1,91 +0,0 @@
import type { ITerminalTabManager, TerminalPanelTabItem } from '../types/terminal.type';
// 终端面板 tab 管理器实现
export default class TerminalPanelTabManager implements ITerminalTabManager<TerminalPanelTabItem> {
public active: string;
public items: Array<TerminalPanelTabItem>;
constructor(def: TerminalPanelTabItem | undefined = undefined) {
if (def) {
this.active = def.sessionId;
this.items = [def];
} else {
this.active = undefined as unknown as string;
this.items = [];
}
}
// 获取当前 tab
getCurrentTab() {
if (!this.active) {
return undefined;
}
return this.items.find(s => s.sessionId === this.active);
}
// 获取 tab
getTab(sessionId: string): TerminalPanelTabItem {
return this.items.find(s => s.sessionId === sessionId) as TerminalPanelTabItem;
}
// 点击 tab
clickTab(sessionId: string): void {
this.active = sessionId;
}
// 删除 tab
deleteTab(sessionId: string): void {
// 获取当前 tab
const tabIndex = this.items.findIndex(s => s.sessionId === sessionId);
// 删除 tab
this.items.splice(tabIndex, 1);
if (sessionId === this.active && this.items.length !== 0) {
// 切换为前一个 tab
this.active = this.items[Math.max(tabIndex - 1, 0)].sessionId;
} else {
this.active = undefined as unknown as string;
}
}
// 打开 tab
openTab(tab: TerminalPanelTabItem): void {
// 不存在则创建 tab
if (!this.items.find(s => s.sessionId === tab.sessionId)) {
this.items.push(tab);
}
this.active = tab.sessionId;
}
// 切换到前一个 tab
changeToPrevTab() {
this.changeToIndex(this.getCurrentTabIndex() - 1);
}
// 切换到后一个 tab
changeToNextTab() {
this.changeToIndex(this.getCurrentTabIndex() + 1);
}
// 切换索引 tab
changeToIndex(index: number) {
if (index < 0 || index >= this.items.length) {
return;
}
// 切换 tab
this.active = this.items[index].sessionId;
}
// 获取当前索引
private getCurrentTabIndex(): number {
return this.items.findIndex(s => s.sessionId === this.active);
}
// 清空
clear() {
this.active = undefined as unknown as string;
this.items = [];
}
}

View File

@@ -1,13 +1,13 @@
import type { ITerminalTabManager, TerminalTabItem } from '../types/terminal.type'; import type { ITerminalTabManager, TerminalTabItem } from '../types/terminal.type';
// 终端 tab 管理器实现 // 终端 tab 管理器实现
export default class TerminalTabManager implements ITerminalTabManager { export default class TerminalTabManager<T extends TerminalTabItem = TerminalTabItem> implements ITerminalTabManager<T> {
public active: string; public active: string;
public items: Array<TerminalTabItem>; public items: Array<T>;
constructor(def: TerminalTabItem | undefined = undefined) { constructor(def: T | undefined = undefined) {
if (def) { if (def) {
this.active = def.key; this.active = def.key;
this.items = [def]; this.items = [def];
@@ -26,8 +26,8 @@ export default class TerminalTabManager implements ITerminalTabManager {
} }
// 获取 tab // 获取 tab
getTab(key: string): TerminalTabItem { getTab(key: string): T {
return this.items.find(s => s.key === key) as TerminalTabItem; return this.items.find(s => s.key === key) as T;
} }
// 点击 tab // 点击 tab
@@ -41,16 +41,18 @@ export default class TerminalTabManager implements ITerminalTabManager {
const tabIndex = this.items.findIndex(s => s.key === key); const tabIndex = this.items.findIndex(s => s.key === key);
// 删除 tab // 删除 tab
this.items.splice(tabIndex, 1); this.items.splice(tabIndex, 1);
if (key === this.active && this.items.length !== 0) { if (this.items.length !== 0) {
// 切换为前一个 tab if (key === this.active) {
this.active = this.items[Math.max(tabIndex - 1, 0)].key; // 关闭的为当前 tab 切换为前一个 tab
this.active = this.items[Math.max(tabIndex - 1, 0)].key;
}
} else { } else {
this.active = undefined as unknown as string; this.active = undefined as unknown as string;
} }
} }
// 打开 tab // 打开 tab
openTab(tab: TerminalTabItem): void { openTab(tab: T): void {
// 不存在则创建 tab // 不存在则创建 tab
if (!this.items.find(s => s.key === tab.key)) { if (!this.items.find(s => s.key === tab.key)) {
this.items.push(tab); this.items.push(tab);