🔨 修改终端逻辑.

This commit is contained in:
lijiahangmax
2024-07-31 00:42:02 +08:00
parent 8c04411458
commit 18c605354a
10 changed files with 104 additions and 36 deletions

View File

@@ -65,7 +65,7 @@ export default defineStore('terminal', {
} as TerminalShortcutSetting,
},
hosts: {} as AuthorizedHostQueryResponse,
tabManager: new TerminalTabManager(TerminalTabs.NEW_CONNECTION),
tabManager: new TerminalTabManager(),
panelManager: new TerminalPanelManager(),
sessionManager: new TerminalSessionManager(),
transferManager: new SftpTransferManager(),

File diff suppressed because one or more lines are too long

View File

@@ -180,6 +180,13 @@
@click="emits('openUpdate', record)">
修改
</a-button>
<!-- 配置 -->
<a-button type="text"
size="mini"
v-permission="['asset:host:update-config']"
@click="emits('openUpdateConfig', record)">
配置
</a-button>
<!-- 删除 -->
<a-popconfirm content="确认删除这条记录吗?"
position="left"
@@ -198,13 +205,6 @@
更多
</a-button>
<template #content>
<!-- 配置 -->
<a-doption v-permission="['asset:host:update-config']"
@click="emits('openUpdateConfig', record)">
<span class="more-doption normal">
配置
</span>
</a-doption>
<!-- 修改状态 -->
<a-doption v-permission="['asset:host:update-status']"
@click="updateStatus(record)">

View File

@@ -47,7 +47,7 @@ const columns = [
}, {
title: '操作',
slotName: 'handle',
width: 162,
width: 192,
align: 'center',
fixed: 'right',
},

View File

@@ -6,8 +6,6 @@
操作栏设置
</h3>
</div>
<!-- 提示 -->
<a-alert class="mb16">修改后会立刻保存, 立即生效 (无需刷新页面)</a-alert>
<!-- 非安全环境提示 -->
<a-alert v-if="!isSecureEnvironment"
type="warning"

View File

@@ -6,8 +6,6 @@
显示偏好
</h3>
</div>
<!-- 提示 -->
<a-alert class="mb16">修改后会立刻保存, 重新打开终端后生效 (无需刷新页面)</a-alert>
<!-- 内容区域 -->
<div class="terminal-setting-body block-body setting-body">
<a-form class="terminal-setting-form"
@@ -100,7 +98,7 @@
<div class="terminal-example">
<span class="vertical-form-label">预览效果</span>
<div class="terminal-example-wrapper"
:style="{ background: preference.theme.schema.background }">
:style="{ background: background }">
<terminal-example :schema="preference.theme.schema"
ref="previewTerminal" />
</div>
@@ -117,22 +115,24 @@
<script lang="ts" setup>
import type { TerminalDisplaySetting } from '@/store/modules/terminal/types';
import type { ISshSession } from '../../../types/define';
import { ref, watch, onMounted } from 'vue';
import { useDictStore, useTerminalStore } from '@/store';
import { fontFamilyKey, fontSizeKey, fontWeightKey, cursorStyleKey } from '../../../types/const';
import { fontFamilyKey, fontSizeKey, fontWeightKey, cursorStyleKey, PanelSessionType } from '../../../types/const';
import { labelFilter } from '@/types/form';
import { TerminalPreferenceItem } from '@/store/modules/terminal';
import { defaultFontFamily } from '@/types/xterm';
import TerminalExample from '../terminal-example.vue';
const { toOptions, toRadioOptions } = useDictStore();
const { preference, updateTerminalPreference } = useTerminalStore();
const { preference, updateTerminalPreference, sessionManager } = useTerminalStore();
const background = preference.theme.schema.background;
const previewTerminal = ref();
const formModel = ref<TerminalDisplaySetting>({});
// 监听内容变化
watch(formModel, (v) => {
watch(formModel, (v, before) => {
if (!v) {
return;
}
@@ -149,6 +149,26 @@
options[key] = (formModel.value as any)[key];
}
});
// 非初始化则修改终端样式
if (before) {
Object.values(sessionManager.sessions)
.filter(s => s.type === PanelSessionType.SSH.type)
.map(s => s as ISshSession)
.forEach(s => {
const options = s.inst.options;
s.inst;
// 修改样式
Object.keys(v).forEach(k => {
let value = v[k as keyof TerminalDisplaySetting];
if (k === 'fontFamily') {
value = value === '_' ? defaultFontFamily : `${value}, ${defaultFontFamily}`;
}
options[k as keyof typeof options] = value;
});
// 自适应
s.fit();
});
}
// 同步
updateTerminalPreference(TerminalPreferenceItem.DISPLAY_SETTING, formModel.value, true);
// 聚焦

View File

@@ -7,7 +7,7 @@
</h3>
</div>
<!-- 提示 -->
<a-alert class="mb16">修改后会立刻保存, 重新打开终端后生效 (无需刷新页面)</a-alert>
<a-alert class="mb16">修改后会立刻保存, 重新打开终端后生效</a-alert>
<!-- 非安全环境提示 -->
<a-alert v-if="!isSecureEnvironment"
type="warning"

View File

@@ -16,8 +16,6 @@
</a-skeleton>
<!-- 内容区域 -->
<div v-else class="terminal-setting-body terminal-theme-container">
<!-- 提示 -->
<a-alert class="mb16">选择后会立刻保存, 刷新页面后生效</a-alert>
<!-- 终端主题 -->
<div class="theme-row"
v-for="(themeArr, index) in themes"
@@ -57,15 +55,17 @@
<script lang="ts" setup>
import type { TerminalTheme } from '@/api/asset/host-terminal';
import type { ISshSession } from '../../../types/define';
import { useTerminalStore } from '@/store';
import { TerminalPreferenceItem } from '@/store/modules/terminal';
import { PanelSessionType } from '../../../types/const';
import { onMounted, ref } from 'vue';
import { getTerminalThemes } from '@/api/asset/host-terminal';
import { getPreference } from '@/api/user/preference';
import useLoading from '@/hooks/loading';
import TerminalExample from '../terminal-example.vue';
const { updateTerminalPreference } = useTerminalStore();
const { updateTerminalPreference, sessionManager } = useTerminalStore();
const { loading, setLoading } = useLoading();
const currentThemeName = ref();
@@ -73,8 +73,20 @@
// 选择主题
const selectTheme = async (theme: TerminalTheme) => {
// 修改主题色
document.body.setAttribute('terminal-theme', theme.dark ? 'dark' : 'light');
// 修改终端主题
Object.values(sessionManager.sessions)
.filter(s => s.type === PanelSessionType.SSH.type)
.map(s => s as ISshSession)
.forEach(s => {
s.inst.options.theme = theme.schema;
// 自适应
s.blur();
});
// 同步
currentThemeName.value = theme.name;
await updateTerminalPreference(TerminalPreferenceItem.THEME, theme);
await updateTerminalPreference(TerminalPreferenceItem.THEME, theme, true);
};
// 加载用户主题

View File

@@ -128,7 +128,7 @@ export default class SshSession extends BaseSession implements ISshSession {
// 启用响铃
if (preference.interactSetting.enableBell) {
this.inst.onBell(() => {
// 播放蜂鸣
// 播放响铃
playBell();
});
}

View File

@@ -13,7 +13,7 @@
<!-- 内容区域 -->
<main class="host-terminal-layout-content">
<!-- 主机加载中骨架 -->
<loading-skeleton v-if="contentLoading" />
<loading-skeleton v-if="loading" />
<!-- 终端内容区域 -->
<main-content v-else
@open-command-snippet="() => snippetRef.open()"
@@ -49,8 +49,10 @@
import { ref, onBeforeMount, onUnmounted, onMounted } from 'vue';
import { dictKeys, PanelSessionType, TerminalTabs } from './types/const';
import { useCacheStore, useDictStore, useTerminalStore } from '@/store';
import { useRoute } from 'vue-router';
import useLoading from '@/hooks/loading';
import debug from '@/utils/env';
import { Message } from '@arco-design/web-vue';
import LayoutHeader from './components/layout/layout-header.vue';
import LeftSidebar from './components/layout/left-sidebar.vue';
import RightSidebar from './components/layout/right-sidebar.vue';
@@ -62,10 +64,9 @@
import '@/assets/style/host-terminal-layout.less';
import '@xterm/xterm/css/xterm.css';
const terminalStore = useTerminalStore();
const dictStore = useDictStore();
const cacheStore = useCacheStore();
const { loading: contentLoading, setLoading: setContentLoading } = useLoading(true);
const { fetchPreference, getCurrentSession, openSession, preference, loadHosts, hosts, tabManager } = useTerminalStore();
const { loading, setLoading } = useLoading(true);
const route = useRoute();
const originTitle = document.title;
const render = ref(false);
@@ -75,7 +76,7 @@
// 终端截屏
const screenshot = () => {
const handler = terminalStore.getCurrentSession<ISshSession>(PanelSessionType.SSH.type, true)?.handler;
const handler = getCurrentSession<ISshSession>(PanelSessionType.SSH.type, true)?.handler;
if (handler && handler.enabledStatus('screenshot')) {
handler.screenshot();
}
@@ -87,27 +88,53 @@
event.returnValue = confirm('系统可能不会保存您所做的更改');
};
// 打开默认打开页面
onBeforeMount(() => {
// 打开默认 tab
let openTab;
const tab = route.query.tab;
if (tab) {
openTab = Object.values(TerminalTabs).find(s => s.key === tab);
}
tabManager.openTab(openTab || TerminalTabs.NEW_CONNECTION);
});
// 加载用户终端偏好
onBeforeMount(async () => {
await terminalStore.fetchPreference();
// 加载偏好
await fetchPreference();
// 设置系统主题配色
const dark = terminalStore.preference.theme.dark;
const dark = preference.theme.dark;
document.body.setAttribute('terminal-theme', dark ? 'dark' : 'light');
render.value = true;
});
// 加载字典值
onBeforeMount(async () => {
await dictStore.loadKeys(dictKeys);
await useDictStore().loadKeys(dictKeys);
});
// 加载主机信息
onMounted(async () => {
try {
await terminalStore.loadHosts();
// 加载主机
await loadHosts();
// 默认连接主机
const connect = route.query.connect;
if (connect) {
const connectHostId = Number.parseInt(connect as string);
const connectHost = hosts.hostList.find(s => s.id === connectHostId);
// 打开连接
if (connectHost) {
const type = Object.values(PanelSessionType).find(s => s.type === route.query.type) || PanelSessionType.SSH;
openSession(connectHost, type);
} else {
Message.error(`主机 ${connectHostId} 不存在/无权限`);
}
}
} catch (e) {
} finally {
setContentLoading(false);
setLoading(false);
}
});
@@ -124,7 +151,7 @@
// 卸载处理
onUnmounted(() => {
// 卸载时清除 cache
cacheStore.reset('authorizedHostKeys', 'authorizedHostIdentities', 'commandSnippetGroups', 'pathBookmarkGroups');
useCacheStore().reset('authorizedHostKeys', 'authorizedHostIdentities', 'commandSnippetGroups', 'pathBookmarkGroups');
// 移除关闭视口事件
window.removeEventListener('beforeunload', handleBeforeUnload);
// 去除 body style