Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
@@ -75,6 +75,10 @@ public class HostTerminalServiceImpl implements HostTerminalService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<HostTerminalThemeVO> getTerminalThemes() {
|
public List<HostTerminalThemeVO> getTerminalThemes() {
|
||||||
|
// if (true) {
|
||||||
|
// String arr = "";
|
||||||
|
// return JSON.parseArray(arr, HostTerminalThemeVO.class);
|
||||||
|
// }
|
||||||
List<JSONObject> themes = dictValueApi.getDictValue(THEME_DICT_KEY);
|
List<JSONObject> themes = dictValueApi.getDictValue(THEME_DICT_KEY);
|
||||||
return themes.stream()
|
return themes.stream()
|
||||||
.map(s -> HostTerminalThemeVO.builder()
|
.map(s -> HostTerminalThemeVO.builder()
|
||||||
|
|||||||
@@ -28,13 +28,15 @@ public class TerminalThemeGenerator {
|
|||||||
List<File> files = Files1.listFiles("D:\\idea-project\\iTerm2-Color-Schemes\\vhs");
|
List<File> files = Files1.listFiles("D:\\idea-project\\iTerm2-Color-Schemes\\vhs");
|
||||||
// 过滤的 theme
|
// 过滤的 theme
|
||||||
List<String> schemaFilter = Lists.of(
|
List<String> schemaFilter = Lists.of(
|
||||||
"Dracula", "Atom",
|
"Dracula", "Builtin Tango Light",
|
||||||
"catppuccin-mocha", "MaterialDesignColors",
|
"Atom", "AtomOneLight",
|
||||||
"catppuccin-macchiato", "OneHalfDark",
|
"OneHalfDark", "OneHalfLight",
|
||||||
"Apple System Colors", "Builtin Tango Light",
|
"Apple System Colors", "Tomorrow",
|
||||||
"Duotone Dark", "BlulocoLight",
|
"catppuccin-mocha", "catppuccin-latte",
|
||||||
"Chester", "CLRS",
|
"catppuccin-macchiato", "BlulocoLight",
|
||||||
"Calamity", "Tomorrow"
|
"catppuccin-frappe", "MaterialDesignColors",
|
||||||
|
"GitHub Dark", "Github",
|
||||||
|
"DimmedMonokai", "Duotone Dark"
|
||||||
);
|
);
|
||||||
// 颜色大写
|
// 颜色大写
|
||||||
ValueFilter colorFilter = (Object object, String name, Object value) -> {
|
ValueFilter colorFilter = (Object object, String name, Object value) -> {
|
||||||
@@ -60,7 +62,7 @@ public class TerminalThemeGenerator {
|
|||||||
theme.setDark(Colors.isDarkColor(background));
|
theme.setDark(Colors.isDarkColor(background));
|
||||||
theme.setSchema(JSON.parseObject(JSON.toJSONString(schema), TerminalThemeSchema.class));
|
theme.setSchema(JSON.parseObject(JSON.toJSONString(schema), TerminalThemeSchema.class));
|
||||||
return theme;
|
return theme;
|
||||||
}).collect(Collectors.toList());
|
}).skip(0).limit(50).collect(Collectors.toList());
|
||||||
// 排序
|
// 排序
|
||||||
if (!Lists.isEmpty(schemaFilter)) {
|
if (!Lists.isEmpty(schemaFilter)) {
|
||||||
arr.sort(Comparator.comparing(s -> schemaFilter.indexOf(s.getName())));
|
arr.sort(Comparator.comparing(s -> schemaFilter.indexOf(s.getName())));
|
||||||
@@ -70,11 +72,12 @@ public class TerminalThemeGenerator {
|
|||||||
for (TerminalTheme theme : arr) {
|
for (TerminalTheme theme : arr) {
|
||||||
System.out.println("name: " + theme.name);
|
System.out.println("name: " + theme.name);
|
||||||
System.out.println("dark: " + theme.dark);
|
System.out.println("dark: " + theme.dark);
|
||||||
System.out.println("value: \n" + JSON.toJSONString(theme.schema, colorFilter));
|
System.out.println("value: " + JSON.toJSONString(theme.schema, colorFilter));
|
||||||
|
System.out.println("json: " + JSON.toJSONString(theme, colorFilter));
|
||||||
System.out.println();
|
System.out.println();
|
||||||
}
|
}
|
||||||
// String json = JSON.toJSONString(arr, colorFilter);
|
String json = JSON.toJSONString(arr, colorFilter);
|
||||||
// System.out.println("\n" + json);
|
System.out.println("\n" + json);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -49,22 +49,21 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { SidebarAction } from '../../types/define';
|
import type { SidebarAction } from '../../types/define';
|
||||||
import { useFullscreen } from '@vueuse/core';
|
|
||||||
import { computed } from 'vue';
|
|
||||||
import { useTerminalStore } from '@/store';
|
import { useTerminalStore } from '@/store';
|
||||||
import IconActions from '../layout/icon-actions.vue';
|
import IconActions from '../layout/icon-actions.vue';
|
||||||
|
|
||||||
const { isFullscreen, toggle: toggleFullScreen } = useFullscreen();
|
const emits = defineEmits(['fullscreen']);
|
||||||
|
|
||||||
const { tabManager } = useTerminalStore();
|
const { tabManager } = useTerminalStore();
|
||||||
|
|
||||||
// 顶部操作
|
// 顶部操作
|
||||||
const actions = computed<Array<SidebarAction>>(() => [
|
const actions: Array<SidebarAction> = [
|
||||||
{
|
{
|
||||||
icon: isFullscreen.value ? 'icon-fullscreen-exit' : 'icon-fullscreen',
|
icon: 'icon-fullscreen',
|
||||||
content: isFullscreen.value ? '点击退出全屏模式' : '点击切换全屏模式',
|
content: '全屏模式',
|
||||||
click: toggleFullScreen
|
click: () => emits('fullscreen')
|
||||||
},
|
},
|
||||||
]);
|
];
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -101,17 +100,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-tabs {
|
&-tabs {
|
||||||
width: calc(100% - @logo-width - var(--sidebar-icon-wrapper-size));
|
width: calc(100% - @logo-width - 100px);
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-right {
|
&-right {
|
||||||
width: var(--sidebar-icon-wrapper-size);
|
width: 100px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
|
||||||
&-actions {
|
&-actions {
|
||||||
width: var(--sidebar-icon-wrapper-size);
|
width: 100px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="host-terminal-layout" v-if="render">
|
<div v-if="render"
|
||||||
|
class="host-terminal-layout"
|
||||||
|
:class="{ 'terminal-full-layout': fullscreen }">
|
||||||
<!-- 头部区域 -->
|
<!-- 头部区域 -->
|
||||||
<header class="host-terminal-layout-header">
|
<header class="host-terminal-layout-header">
|
||||||
<layout-header />
|
<layout-header @fullscreen="enterFullscreen" />
|
||||||
</header>
|
</header>
|
||||||
<!-- 主体区域 -->
|
<!-- 主体区域 -->
|
||||||
<main class="host-terminal-layout-main">
|
<main class="host-terminal-layout-main">
|
||||||
@@ -29,6 +31,14 @@
|
|||||||
@screenshot="screenshot" />
|
@screenshot="screenshot" />
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
<!-- 退出全屏 -->
|
||||||
|
<a-button v-if="fullscreen"
|
||||||
|
class="exit-fullscreen"
|
||||||
|
shape="circle"
|
||||||
|
title="退出全屏"
|
||||||
|
@click="exitFullscreen">
|
||||||
|
<icon-fullscreen-exit />
|
||||||
|
</a-button>
|
||||||
<!-- 命令片段列表抽屉 -->
|
<!-- 命令片段列表抽屉 -->
|
||||||
<command-snippet-drawer ref="snippetRef" @closed="autoFocus" />
|
<command-snippet-drawer ref="snippetRef" @closed="autoFocus" />
|
||||||
<!-- 路径书签列表抽屉 -->
|
<!-- 路径书签列表抽屉 -->
|
||||||
@@ -50,6 +60,7 @@
|
|||||||
import { dictKeys, PanelSessionType, TerminalTabs } from './types/const';
|
import { dictKeys, PanelSessionType, TerminalTabs } from './types/const';
|
||||||
import { useCacheStore, useDictStore, useTerminalStore } from '@/store';
|
import { useCacheStore, useDictStore, useTerminalStore } from '@/store';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useFullscreen } from '@vueuse/core';
|
||||||
import useLoading from '@/hooks/loading';
|
import useLoading from '@/hooks/loading';
|
||||||
import debug from '@/utils/env';
|
import debug from '@/utils/env';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
@@ -66,6 +77,7 @@
|
|||||||
|
|
||||||
const { fetchPreference, getCurrentSession, openSession, preference, loadHosts, hosts, tabManager } = useTerminalStore();
|
const { fetchPreference, getCurrentSession, openSession, preference, loadHosts, hosts, tabManager } = useTerminalStore();
|
||||||
const { loading, setLoading } = useLoading(true);
|
const { loading, setLoading } = useLoading(true);
|
||||||
|
const { enter: enterFull, exit: exitFull } = useFullscreen();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
const originTitle = document.title;
|
const originTitle = document.title;
|
||||||
@@ -73,6 +85,7 @@
|
|||||||
const snippetRef = ref();
|
const snippetRef = ref();
|
||||||
const pathRef = ref();
|
const pathRef = ref();
|
||||||
const transferRef = ref();
|
const transferRef = ref();
|
||||||
|
const fullscreen = ref();
|
||||||
|
|
||||||
// 终端截屏
|
// 终端截屏
|
||||||
const screenshot = () => {
|
const screenshot = () => {
|
||||||
@@ -82,10 +95,18 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 关闭视口处理
|
// 进入全屏
|
||||||
const handleBeforeUnload = (event: any) => {
|
const enterFullscreen = () => {
|
||||||
event.preventDefault();
|
fullscreen.value = true;
|
||||||
event.returnValue = confirm('系统可能不会保存您所做的更改');
|
// 进入全屏
|
||||||
|
enterFull();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 退出全屏
|
||||||
|
const exitFullscreen = () => {
|
||||||
|
fullscreen.value = false;
|
||||||
|
// 退出全屏
|
||||||
|
exitFull();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 自动聚焦
|
// 自动聚焦
|
||||||
@@ -93,6 +114,12 @@
|
|||||||
getCurrentSession<ISshSession>(PanelSessionType.SSH.type)?.focus();
|
getCurrentSession<ISshSession>(PanelSessionType.SSH.type)?.focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 关闭视口处理
|
||||||
|
const handleBeforeUnload = (event: any) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.returnValue = confirm('系统可能不会保存您所做的更改');
|
||||||
|
};
|
||||||
|
|
||||||
// 打开默认打开页面
|
// 打开默认打开页面
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
// 打开默认 tab
|
// 打开默认 tab
|
||||||
@@ -105,18 +132,19 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 加载用户终端偏好
|
// 加载用户终端偏好
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(() => {
|
||||||
// 加载偏好
|
// 加载偏好
|
||||||
await fetchPreference();
|
fetchPreference().then(() => {
|
||||||
// 设置系统主题配色
|
// 设置系统主题配色
|
||||||
const dark = preference.theme.dark;
|
const dark = preference.theme.dark;
|
||||||
document.body.setAttribute('terminal-theme', dark ? 'dark' : 'light');
|
document.body.setAttribute('terminal-theme', dark ? 'dark' : 'light');
|
||||||
render.value = true;
|
render.value = true;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 加载字典值
|
// 加载字典值
|
||||||
onBeforeMount(async () => {
|
onBeforeMount(() => {
|
||||||
await useDictStore().loadKeys(dictKeys);
|
useDictStore().loadKeys(dictKeys);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 加载主机信息
|
// 加载主机信息
|
||||||
@@ -176,6 +204,24 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
color: var(--color-content-text-2);
|
color: var(--color-content-text-2);
|
||||||
|
|
||||||
|
&.terminal-full-layout {
|
||||||
|
.host-terminal-layout-header, .host-terminal-layout-left, .host-terminal-layout-right {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.host-terminal-layout-main {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
:deep(.host-terminal-layout-content) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.terminal-panels-container) {
|
||||||
|
height: 100vh !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&-header {
|
&-header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: var(--header-height);
|
height: var(--header-height);
|
||||||
@@ -212,6 +258,13 @@
|
|||||||
background: var(--color-bg-content);
|
background: var(--color-bg-content);
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.exit-fullscreen {
|
||||||
|
position: absolute;
|
||||||
|
right: 24px;
|
||||||
|
bottom: 24px;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -272,11 +272,13 @@
|
|||||||
|
|
||||||
// 添加后回调
|
// 添加后回调
|
||||||
const addedCallback = () => {
|
const addedCallback = () => {
|
||||||
|
formRef.value.resetFields();
|
||||||
loadMenuData(true);
|
loadMenuData(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 更新后回调
|
// 更新后回调
|
||||||
const updatedCallback = () => {
|
const updatedCallback = () => {
|
||||||
|
formRef.value.resetFields();
|
||||||
loadMenuData(true);
|
loadMenuData(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const columns = [
|
|||||||
title: '类型',
|
title: '类型',
|
||||||
dataIndex: 'type',
|
dataIndex: 'type',
|
||||||
slotName: 'type',
|
slotName: 'type',
|
||||||
width: 80,
|
width: 68,
|
||||||
}, {
|
}, {
|
||||||
title: '排序',
|
title: '排序',
|
||||||
dataIndex: 'sort',
|
dataIndex: 'sort',
|
||||||
@@ -32,20 +32,21 @@ const columns = [
|
|||||||
title: '权限标识',
|
title: '权限标识',
|
||||||
dataIndex: 'permission',
|
dataIndex: 'permission',
|
||||||
slotName: 'permission',
|
slotName: 'permission',
|
||||||
minWidth: 138,
|
minWidth: 168,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
tooltip: true
|
tooltip: true
|
||||||
}, {
|
}, {
|
||||||
title: '组件名称',
|
title: '组件名称',
|
||||||
dataIndex: 'component',
|
dataIndex: 'component',
|
||||||
slotName: 'component',
|
slotName: 'component',
|
||||||
minWidth: 138,
|
minWidth: 218,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
tooltip: true,
|
tooltip: true,
|
||||||
}, {
|
}, {
|
||||||
title: '链接路径',
|
title: '链接路径',
|
||||||
dataIndex: 'path',
|
dataIndex: 'path',
|
||||||
slotName: 'path',
|
slotName: 'path',
|
||||||
|
width: 168,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
tooltip: true,
|
tooltip: true,
|
||||||
}, {
|
}, {
|
||||||
|
|||||||
Reference in New Issue
Block a user