重写ssh前端组件,通用化
This commit is contained in:
parent
743255d5c5
commit
6d2f0cb95c
@ -4,6 +4,7 @@
|
||||
*/
|
||||
import React, { useRef, useState, useEffect } from 'react';
|
||||
import type { LayoutOrientation } from './types';
|
||||
import styles from './index.module.less';
|
||||
|
||||
interface TerminalSplitDividerProps {
|
||||
orientation: LayoutOrientation;
|
||||
@ -56,6 +57,7 @@ export const TerminalSplitDivider: React.FC<TerminalSplitDividerProps> = ({ orie
|
||||
? (orientation === 'horizontal' ? container.clientWidth : container.clientHeight)
|
||||
: undefined;
|
||||
|
||||
console.log(`[TerminalSplitDivider] onResize, orientation: ${orientation}, delta: ${delta}, containerSize: ${containerSize}`);
|
||||
onResize(delta, containerSize);
|
||||
lastMousePosRef.current = currentMousePos;
|
||||
};
|
||||
@ -79,6 +81,7 @@ export const TerminalSplitDivider: React.FC<TerminalSplitDividerProps> = ({ orie
|
||||
|
||||
const handleMouseDown = (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
console.log(`[TerminalSplitDivider] mouseDown, orientation: ${orientation}`);
|
||||
const initialPos = orientation === 'horizontal' ? e.clientX : e.clientY;
|
||||
startPosRef.current = initialPos;
|
||||
lastMousePosRef.current = initialPos;
|
||||
@ -88,33 +91,8 @@ export const TerminalSplitDivider: React.FC<TerminalSplitDividerProps> = ({ orie
|
||||
return (
|
||||
<div
|
||||
ref={dividerRef}
|
||||
className={`
|
||||
${orientation === 'horizontal' ? 'w-[2px] cursor-col-resize' : 'h-[2px] cursor-row-resize'}
|
||||
${isDragging ? 'bg-blue-500' : 'bg-gray-400 dark:bg-gray-600 hover:bg-blue-500'}
|
||||
transition-all duration-150
|
||||
relative
|
||||
group
|
||||
flex-shrink-0
|
||||
`}
|
||||
className={`${styles.divider} ${styles[orientation]} ${isDragging ? styles.dragging : ''}`}
|
||||
onMouseDown={handleMouseDown}
|
||||
>
|
||||
{/* 中心可见线 */}
|
||||
<div className={`
|
||||
absolute inset-0
|
||||
${orientation === 'horizontal' ? 'w-[1px] left-1/2 -translate-x-1/2' : 'h-[1px] top-1/2 -translate-y-1/2'}
|
||||
${isDragging ? 'bg-blue-600' : 'bg-gray-500 dark:bg-gray-500'}
|
||||
`} />
|
||||
|
||||
{/* 拖动热区 - 增加可拖动区域 */}
|
||||
<div
|
||||
className={`
|
||||
absolute
|
||||
${orientation === 'horizontal'
|
||||
? 'w-3 -left-1.5 top-0 bottom-0'
|
||||
: 'h-3 left-0 right-0 -top-1.5'
|
||||
}
|
||||
`}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -22,6 +22,21 @@
|
||||
border-bottom: 1px solid #374151;
|
||||
}
|
||||
|
||||
/* 搜索栏样式 */
|
||||
.searchBar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.5rem 1rem;
|
||||
background: #f9fafb;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
:global(.dark) .searchBar {
|
||||
background: #1f2937;
|
||||
border-bottom: 1px solid #374151;
|
||||
}
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -204,3 +219,29 @@
|
||||
width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 分隔线样式 */
|
||||
.divider {
|
||||
flex-shrink: 0;
|
||||
z-index: 10;
|
||||
background-color: #9ca3af;
|
||||
transition: all 150ms;
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(59 130 246 / 1);
|
||||
}
|
||||
|
||||
&.dragging {
|
||||
background-color: rgb(59 130 246 / 1);
|
||||
}
|
||||
|
||||
&.horizontal {
|
||||
width: 4px;
|
||||
cursor: col-resize;
|
||||
}
|
||||
|
||||
&.vertical {
|
||||
height: 4px;
|
||||
cursor: row-resize;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,22 @@ import { useState, useCallback } from 'react';
|
||||
import type { EditorGroup, TerminalTab, SplitDirection, SplitLayout, SplitNode, SplitContainer, LayoutOrientation } from './types';
|
||||
import { TerminalInstanceManager } from './core/TerminalInstanceManager';
|
||||
|
||||
/**
|
||||
* 根据容器尺寸和方向计算最小尺寸(像素)
|
||||
* @param containerSize 容器尺寸(px)
|
||||
* @param orientation 分割方向
|
||||
* @returns 最小尺寸(px)
|
||||
*/
|
||||
const getMinSize = (containerSize: number, orientation: LayoutOrientation): number => {
|
||||
if (orientation === 'horizontal') {
|
||||
// 左右分屏:最小宽度520px
|
||||
return 520;
|
||||
} else {
|
||||
// 上下分屏:根据容器高度计算,最小200px,最多占40%
|
||||
return Math.max(200, Math.min(containerSize * 0.4, 300));
|
||||
}
|
||||
};
|
||||
|
||||
interface UseSplitViewOptions {
|
||||
initialTab: TerminalTab;
|
||||
onWindowClose?: () => void; // 最后一个Tab关闭时的回调
|
||||
@ -370,12 +386,19 @@ export const useSplitView = ({ initialTab, onWindowClose }: UseSplitViewOptions)
|
||||
|
||||
// 调整分屏大小
|
||||
const resizeGroups = useCallback((nodeId: string, delta: number, containerSize?: number) => {
|
||||
console.log(`[useSplitView.resizeGroups] nodeId: ${nodeId}, delta: ${delta}, containerSize: ${containerSize}`);
|
||||
setLayout(prev => {
|
||||
const result = findParent(prev.root, nodeId);
|
||||
if (!result || !result.parent) return prev;
|
||||
if (!result || !result.parent) {
|
||||
console.log(`[useSplitView.resizeGroups] findParent failed`);
|
||||
return prev;
|
||||
}
|
||||
|
||||
const { parent, index } = result;
|
||||
if (index >= parent.children.length - 1) return prev;
|
||||
if (index >= parent.children.length - 1) {
|
||||
console.log(`[useSplitView.resizeGroups] index check failed: ${index} >= ${parent.children.length - 1}`);
|
||||
return prev;
|
||||
}
|
||||
|
||||
const current = parent.children[index];
|
||||
const next = parent.children[index + 1];
|
||||
@ -385,13 +408,15 @@ export const useSplitView = ({ initialTab, onWindowClose }: UseSplitViewOptions)
|
||||
// delta是像素值,需要转换为百分比:(delta / containerSize) * totalSize
|
||||
const deltaPercent = containerSize ? (delta / containerSize) * totalSize : delta;
|
||||
|
||||
// 计算最小尺寸百分比:520px / 容器尺寸 * 100
|
||||
// 如果没有容器尺寸,使用默认20%作为兜底
|
||||
const minSizePercent = containerSize ? Math.min(50, (520 / containerSize) * 100) : 20;
|
||||
// 计算最小尺寸百分比:使用totalSize的20%作为最小值
|
||||
// 这样每个分屏至少占两个分屏总和的20%(例如:总100%时,最小20%)
|
||||
const minSizePercent = totalSize * 0.2;
|
||||
|
||||
const newCurrentSize = Math.max(minSizePercent, Math.min(totalSize - minSizePercent, current.size + deltaPercent));
|
||||
const newNextSize = totalSize - newCurrentSize;
|
||||
|
||||
console.log(`[useSplitView.resizeGroups] current.size: ${current.size}, deltaPercent: ${deltaPercent}, newCurrentSize: ${newCurrentSize}, newNextSize: ${newNextSize}`);
|
||||
|
||||
const newChildren = parent.children.map((child, i) => {
|
||||
if (i === index) return { ...child, size: newCurrentSize };
|
||||
if (i === index + 1) return { ...child, size: newNextSize };
|
||||
|
||||
Loading…
Reference in New Issue
Block a user