修改面板样式

This commit is contained in:
JoyD
2025-10-29 22:02:00 +08:00
parent 807e391900
commit 0d174901ff

View File

@@ -5,36 +5,6 @@
<div class="flex items-center space-x-4"> <div class="flex items-center space-x-4">
<h1 class="text-lg font-semibold text-gray-800">停靠式面板容器演示</h1> <h1 class="text-lg font-semibold text-gray-800">停靠式面板容器演示</h1>
<div class="flex items-center space-x-2"> <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 <button
@click="addFloatingPanel()" @click="addFloatingPanel()"
class="px-3 py-1 bg-blue-50 text-blue-600 rounded hover:bg-blue-100 text-sm" class="px-3 py-1 bg-blue-50 text-blue-600 rounded hover:bg-blue-100 text-sm"
@@ -73,8 +43,55 @@
</div> </div>
<!-- 预留主区域暂不放面板 --> <!-- 预留主区域暂不放面板 -->
<div class="flex-1 w-full h-[calc(100%-4rem)]"> <div ref="panelHost" class="flex-1 w-full h-[calc(100%-4rem)] relative bg-gray-100">
<!-- 预留区域后续将放置 DockLayout 容器 --> <!-- 浮动面板渲染区 -->
<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">
<!-- 外框与底色边框为1 -->
<rect x="0.5" y="0.5" width="10" height="10" fill="#cbd6ff" stroke="#8ea3d8" stroke-width="1" />
<!-- 内框细边边框为1 -->
<rect x="2.5" y="2.5" width="6" height="6" fill="none" stroke="#b8c6ff" stroke-width="1" />
<!-- 上行1/5高度约1px颜色保持浅蓝 -->
<rect x="3" y="3" width="5" height="1" fill="#b8c6ff" />
<!-- 下行4/5高度约5px颜色为标题栏色 -->
<rect x="3" y="4" width="5" height="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>
</div> </div>
</template> </template>
@@ -82,15 +99,75 @@
<script setup> <script setup>
import { ref } from 'vue'; import { ref } from 'vue';
// 顶部控制栏按钮的占位逻辑(测试页下方暂未放面板容器) // 顶部控制栏按钮的引用
const layoutFileInput = ref(null); const layoutFileInput = ref(null);
const panelHost = ref(null);
// 浮动面板列表
const floatingPanels = ref([]);
let nextPanelIdx = 1;
function addPanel(position) { function addPanel(position) {
console.log('[DockLayoutTest] addPanel clicked:', position); console.log('[DockLayoutTest] addPanel clicked:', position);
} }
function addFloatingPanel() { 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() { function exportLayout() {
@@ -111,8 +188,78 @@ function handleLayoutFileSelect(event) {
function resetLayout() { function resetLayout() {
console.log('[DockLayoutTest] resetLayout clicked'); 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> </script>
<style scoped> <style scoped>
/* 可按需添加页面专属样式 */ /* 可按需添加页面专属样式 */
</style> .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;
}