mirror of
https://github.com/chaos-zhu/easynode.git
synced 2026-10-06 15:13:18 +08:00
feat: 单窗口模式多终端支持放大
This commit is contained in:
+1
-1
@@ -6,7 +6,7 @@
|
||||
<meta name="viewport"
|
||||
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0">
|
||||
<title>EasyNode</title>
|
||||
<script src="//at.alicdn.com/t/c/font_3309550_zznptezhsva.js"></script>
|
||||
<script src="//at.alicdn.com/t/c/font_3309550_6nmd68hw8cb.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -10,7 +10,11 @@
|
||||
<div
|
||||
v-for="(panel, index) in layoutPanels"
|
||||
:key="panel.terminal.key"
|
||||
:class="['terminal_panel', { 'active': focusedTerminalKey === panel.terminal.key }]"
|
||||
:class="[
|
||||
'terminal_panel',
|
||||
{ 'active': focusedTerminalKey === panel.terminal.key },
|
||||
{ 'maximized': maximizedTerminalKey === panel.terminal.key }
|
||||
]"
|
||||
:style="panel.style"
|
||||
>
|
||||
<!-- 终端标题栏 -->
|
||||
@@ -26,8 +30,21 @@
|
||||
<svg-icon name="icon-daima" class="icon" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="terminal_close" @click.stop="handleCloseTerminal(panel.terminal.key)">
|
||||
<el-icon class="close_icon"><Close /></el-icon>
|
||||
<div class="terminal_actions">
|
||||
<!-- 最大化/最小化图标,只在终端数量>=2时显示且布局模式为一屏展示时显示 -->
|
||||
<div
|
||||
v-if="props.terminalTabs.length >= 2 "
|
||||
class="terminal_maximize"
|
||||
@click.stop="handleToggleMaximize(panel.terminal.key)"
|
||||
>
|
||||
<span class="maximize_icon">
|
||||
<svg-icon v-if="maximizedTerminalKey !== panel.terminal.key" name="icon-fangdachuangkou" class="icon" />
|
||||
<svg-icon v-else name="icon-suoxiaochuangkou" class="icon" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="terminal_close" @click.stop="handleCloseTerminal(panel.terminal.key)">
|
||||
<el-icon class="close_icon"><Close /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -80,7 +97,7 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch, nextTick, onMounted, onBeforeUnmount } from 'vue'
|
||||
import { Close } from '@element-plus/icons-vue'
|
||||
import { Close, FullScreen, Aim } from '@element-plus/icons-vue'
|
||||
import Terminal from './terminal.vue'
|
||||
import { terminalStatusList } from '@/utils/enum'
|
||||
import ScriptInput from './script-input.vue'
|
||||
@@ -120,6 +137,7 @@ const emit = defineEmits(['close-terminal', 'terminal-input', 'ping-data', 'rese
|
||||
|
||||
// 响应式数据
|
||||
const focusedTerminalKey = ref(null)
|
||||
const maximizedTerminalKey = ref(null) // 新增:存储当前最大化的终端key
|
||||
const terminalRefs = ref({})
|
||||
const isDragging = ref(false)
|
||||
const dragInfo = ref(null)
|
||||
@@ -549,6 +567,11 @@ const handlePanelClick = (terminalKey) => {
|
||||
}
|
||||
|
||||
const handleCloseTerminal = (terminalKey) => {
|
||||
// 如果关闭的是当前最大化的终端,重置最大化状态
|
||||
if (maximizedTerminalKey.value === terminalKey) {
|
||||
maximizedTerminalKey.value = null
|
||||
}
|
||||
|
||||
emit('close-terminal', terminalKey)
|
||||
|
||||
// 关闭终端后,延迟触发resize确保布局重新计算
|
||||
@@ -709,7 +732,20 @@ const handleMouseUp = () => {
|
||||
})
|
||||
}
|
||||
|
||||
// 同步输入处理已移至 handleInputCommand 中
|
||||
// 最大化/最小化功能
|
||||
const handleToggleMaximize = (terminalKey) => {
|
||||
if (maximizedTerminalKey.value === terminalKey) {
|
||||
maximizedTerminalKey.value = null // 取消最大化
|
||||
} else {
|
||||
maximizedTerminalKey.value = terminalKey // 最大化
|
||||
// 设置焦点到最大化的终端
|
||||
focusedTerminalKey.value = terminalKey
|
||||
}
|
||||
nextTick(() => {
|
||||
terminalRefs.value[terminalKey]?.focusTab()
|
||||
terminalRefs.value[terminalKey]?.handleResize()
|
||||
})
|
||||
}
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
@@ -729,6 +765,16 @@ watch(() => props.terminalTabs, (newTabs, oldTabs) => {
|
||||
focusedTerminalKey.value = newTabs[0].key
|
||||
}
|
||||
|
||||
// 检查最大化的终端是否仍然存在
|
||||
if (maximizedTerminalKey.value && !newTabs.find(tab => tab.key === maximizedTerminalKey.value)) {
|
||||
maximizedTerminalKey.value = null
|
||||
}
|
||||
|
||||
// 如果终端数量小于2,取消最大化状态
|
||||
if (newTabs.length < 2 && maximizedTerminalKey.value) {
|
||||
maximizedTerminalKey.value = null
|
||||
}
|
||||
|
||||
// 清理已关闭终端的引用和脚本输入状态
|
||||
Object.keys(terminalRefs.value).forEach(key => {
|
||||
if (!newTabs.find(tab => tab.key === key)) {
|
||||
@@ -885,6 +931,18 @@ defineExpose({
|
||||
&.active {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
&.maximized {
|
||||
position: absolute !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
z-index: 9 !important; /* 确保最大化终端在最上层 */
|
||||
border: none !important; /* 移除边框,因为它是全屏的 */
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5) !important;
|
||||
pointer-events: auto !important; /* 允许点击 */
|
||||
}
|
||||
}
|
||||
|
||||
.terminal_panels_wrapper.scroll_mode .terminal_panel {
|
||||
@@ -952,6 +1010,23 @@ defineExpose({
|
||||
}
|
||||
}
|
||||
|
||||
.terminal_actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.terminal_maximize {
|
||||
cursor: pointer;
|
||||
margin-right: 8px;
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.maximize_icon {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.terminal_close {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
||||
Reference in New Issue
Block a user