Merge branch 'main' of http://47.109.191.115:3000/ZengQingming/JoyD
This commit is contained in:
@@ -5,36 +5,6 @@
|
||||
<div class="flex items-center space-x-4">
|
||||
<h1 class="text-lg font-semibold text-gray-800">停靠式面板容器演示</h1>
|
||||
<div class="flex items-center space-x-2">
|
||||
<button
|
||||
@click="addPanel('left')"
|
||||
class="px-3 py-1 bg-blue-50 text-blue-600 rounded hover:bg-blue-100 text-sm"
|
||||
>
|
||||
添加左侧面板
|
||||
</button>
|
||||
<button
|
||||
@click="addPanel('right')"
|
||||
class="px-3 py-1 bg-blue-50 text-blue-600 rounded hover:bg-blue-100 text-sm"
|
||||
>
|
||||
添加右侧面板
|
||||
</button>
|
||||
<button
|
||||
@click="addPanel('top')"
|
||||
class="px-3 py-1 bg-blue-50 text-blue-600 rounded hover:bg-blue-100 text-sm"
|
||||
>
|
||||
添加顶部面板
|
||||
</button>
|
||||
<button
|
||||
@click="addPanel('bottom')"
|
||||
class="px-3 py-1 bg-blue-50 text-blue-600 rounded hover:bg-blue-100 text-sm"
|
||||
>
|
||||
添加底部面板
|
||||
</button>
|
||||
<button
|
||||
@click="addPanel('center')"
|
||||
class="px-3 py-1 bg-blue-50 text-blue-600 rounded hover:bg-blue-100 text-sm"
|
||||
>
|
||||
添加中心面板
|
||||
</button>
|
||||
<button
|
||||
@click="addFloatingPanel()"
|
||||
class="px-3 py-1 bg-blue-50 text-blue-600 rounded hover:bg-blue-100 text-sm"
|
||||
@@ -73,8 +43,51 @@
|
||||
</div>
|
||||
|
||||
<!-- 预留主区域(暂不放面板) -->
|
||||
<div class="flex-1 w-full h-[calc(100%-4rem)]">
|
||||
<!-- 预留区域:后续将放置 DockLayout 容器 -->
|
||||
<div ref="panelHost" class="flex-1 w-full h-[calc(100%-4rem)] relative bg-gray-100">
|
||||
<!-- 浮动面板渲染区 -->
|
||||
<div
|
||||
v-for="panel in floatingPanels"
|
||||
:key="panel.id"
|
||||
class="absolute bg-white shadow rounded border overflow-hidden"
|
||||
:style="{ top: panel.y + 'px', left: panel.x + 'px', width: panel.width + 'px', height: panel.height + 'px' }"
|
||||
>
|
||||
<div class="flex flex-col h-full">
|
||||
<!-- 标题栏:小三角移到右侧,压缩高度与间距 -->
|
||||
<div class="h-6 bg-[#435d9c] text-white px-2 flex items-center justify-between select-none">
|
||||
<div class="flex items-center">
|
||||
<span class="text-xs">{{ panel.title }}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-0.5">
|
||||
<button class="p-[2px] rounded hover:opacity-100 opacity-80" @click="toggleCollapse(panel.id)" aria-label="折叠/展开">
|
||||
<span class="icon-triangle-down"></span>
|
||||
</button>
|
||||
<button class="p-[2px] rounded hover:opacity-100 opacity-80" @click="maximizePanel(panel.id)" aria-label="最大化">
|
||||
<svg class="icon-square-svg" width="11" height="11" viewBox="0 0 11 11" aria-hidden="true">
|
||||
<!-- 外框与底色(仅1px边框) -->
|
||||
<rect x="0.5" y="0.5" width="10" height="10" fill="#cbd6ff" stroke="#8ea3d8" stroke-width="1" />
|
||||
<!-- 两行填充:上行1px浅蓝,下行标题栏色 -->
|
||||
<rect x="1" y="3" width="8.5" height="6.5" fill="#435d9c" />
|
||||
</svg>
|
||||
</button>
|
||||
<button class="p-[2px] rounded hover:opacity-100 opacity-80" @click="closePanel(panel.id)" aria-label="关闭">
|
||||
<span class="icon-x"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 工具栏:位于标题栏下方,右侧扩展钮 -->
|
||||
<div class="h-6 bg-[#d5e2f6] text-[#2c3e7a] px-2 flex items-center justify-between border-b border-[#c7d2ea]">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-xs">工具栏</span>
|
||||
<button v-if="panel.toolbarExpanded" class="px-2 py-0.5 text-xs bg-white/60 rounded hover:bg-white">示例按钮</button>
|
||||
</div>
|
||||
<button class="px-2 py-0.5 text-xs rounded hover:bg-white/40" @click="toggleToolbarExpand(panel.id)" aria-label="展开工具栏">
|
||||
<i class="fa-solid" :class="panel.toolbarExpanded ? 'fa-angles-left' : 'fa-angles-right'"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- 内容区:可折叠 -->
|
||||
<div class="bg-[#f5f7fb] flex-1" v-show="!panel.collapsed"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -82,15 +95,75 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
// 顶部控制栏按钮的占位逻辑(测试页下方暂未放面板容器)
|
||||
// 顶部控制栏按钮的引用
|
||||
const layoutFileInput = ref(null);
|
||||
const panelHost = ref(null);
|
||||
|
||||
// 浮动面板列表
|
||||
const floatingPanels = ref([]);
|
||||
let nextPanelIdx = 1;
|
||||
|
||||
function addPanel(position) {
|
||||
console.log('[DockLayoutTest] addPanel clicked:', position);
|
||||
}
|
||||
|
||||
function addFloatingPanel() {
|
||||
console.log('[DockLayoutTest] addFloatingPanel clicked');
|
||||
// 复原截图样式的默认面板参数
|
||||
const defaultSize = { width: 300, height: 180 };
|
||||
const offset = 16;
|
||||
const idx = nextPanelIdx++;
|
||||
const panel = {
|
||||
id: 'float-' + idx,
|
||||
title: '输出',
|
||||
x: offset * idx,
|
||||
y: offset * idx,
|
||||
width: defaultSize.width,
|
||||
height: defaultSize.height,
|
||||
collapsed: false,
|
||||
toolbarExpanded: false,
|
||||
maximized: false,
|
||||
};
|
||||
floatingPanels.value.push(panel);
|
||||
}
|
||||
|
||||
function closePanel(id) {
|
||||
floatingPanels.value = floatingPanels.value.filter(p => p.id !== id);
|
||||
}
|
||||
|
||||
function minimizePanel(id) {
|
||||
const p = floatingPanels.value.find(p => p.id === id);
|
||||
if (p) {
|
||||
p.minimized = !p.minimized;
|
||||
}
|
||||
}
|
||||
|
||||
function maximizePanel(id) {
|
||||
const p = floatingPanels.value.find(p => p.id === id);
|
||||
if (!p) return;
|
||||
const host = panelHost.value;
|
||||
const rect = host && host.getBoundingClientRect ? host.getBoundingClientRect() : null;
|
||||
|
||||
if (!p.maximized) {
|
||||
// 记录旧位置与尺寸
|
||||
p.__prev = { x: p.x, y: p.y, width: p.width, height: p.height };
|
||||
// 占满容器(留出1-2px避免外边框遮盖)
|
||||
const w = rect ? Math.floor(rect.width) - 2 : 800;
|
||||
const h = rect ? Math.floor(rect.height) - 2 : 600;
|
||||
p.x = 0;
|
||||
p.y = 0;
|
||||
p.width = Math.max(300, w);
|
||||
p.height = Math.max(180, h);
|
||||
p.maximized = true;
|
||||
} else {
|
||||
// 还原旧位置与尺寸
|
||||
if (p.__prev) {
|
||||
p.x = p.__prev.x;
|
||||
p.y = p.__prev.y;
|
||||
p.width = p.__prev.width;
|
||||
p.height = p.__prev.height;
|
||||
}
|
||||
p.maximized = false;
|
||||
}
|
||||
}
|
||||
|
||||
function exportLayout() {
|
||||
@@ -111,8 +184,78 @@ function handleLayoutFileSelect(event) {
|
||||
function resetLayout() {
|
||||
console.log('[DockLayoutTest] resetLayout clicked');
|
||||
}
|
||||
|
||||
function toggleCollapse(id) {
|
||||
const p = floatingPanels.value.find(p => p.id === id);
|
||||
if (p) {
|
||||
p.collapsed = !p.collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
function toggleToolbarExpand(id) {
|
||||
const p = floatingPanels.value.find(p => p.id === id);
|
||||
if (p) {
|
||||
p.toolbarExpanded = !p.toolbarExpanded;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 可按需添加页面专属样式 */
|
||||
.icon-triangle-down { /* 向下小三角(更小更细) */
|
||||
width: 0; height: 0;
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
border-top: 6px solid #cbd6ff;
|
||||
display: inline-block;
|
||||
}
|
||||
.icon-square { /* 最大化图标:外层浅蓝方块 + 内层细边框 */
|
||||
position: relative;
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
background: linear-gradient(180deg, #cbd6ff 0%, #b9c8ff 100%);
|
||||
border: 1px solid #b8c6ff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.icon-square::before { /* 内层小方框边线(回退为细线) */
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
top: 2px;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border: 1px solid #b8c6ff;
|
||||
box-sizing: border-box;
|
||||
background: transparent;
|
||||
}
|
||||
.icon-square::after { /* 顶部工具栏小块 */
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 3px; /* 内边距 1px */
|
||||
top: 3px;
|
||||
width: 5px; /* 与内框宽度对应 */
|
||||
height: 2px; /* 小工具栏高度 */
|
||||
background: #b8c6ff; /* 与边线同色,形成上沿条 */
|
||||
border-radius: 0.5px;
|
||||
}
|
||||
.icon-x { /* X(略小) */
|
||||
position: relative; width: 11px; height: 11px; display: inline-block;
|
||||
}
|
||||
.icon-x::before, .icon-x::after {
|
||||
content: ''; position: absolute; left: 5px; top: 0; width: 1px; height: 11px; background: #e6efff;
|
||||
}
|
||||
.icon-x::before { transform: rotate(45deg); }
|
||||
.icon-x::after { transform: rotate(-45deg); }
|
||||
</style>
|
||||
/* 禁用旧的最大化伪元素,避免影响SVG呈现 */
|
||||
.icon-square::before,
|
||||
.icon-square::after {
|
||||
content: none !important;
|
||||
display: none !important;
|
||||
border: 0 !important;
|
||||
}
|
||||
.icon-square-svg {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
display: inline-block;
|
||||
}
|
||||
Reference in New Issue
Block a user