修复Area组件最大化功能,确保填充满父容器
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
<template>
|
||||
<div class="vs-area-wrapper">
|
||||
<div class="vs-area select-none" :class="{ 'is-maximized': isMaximized }" :style="areaStyle">
|
||||
<div
|
||||
class="vs-area select-none"
|
||||
:class="{ 'is-maximized': isMaximized, 'is-normal': !isMaximized }"
|
||||
:style="areaStyle"
|
||||
>
|
||||
<!-- 顶部标题栏 -->
|
||||
<div v-if="showTitleBar" class="vs-title-bar">
|
||||
<div class="vs-title-left">
|
||||
@@ -44,9 +48,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 内容区域(空) -->
|
||||
<!-- 内容区域 -->
|
||||
<div class="vs-content">
|
||||
<!-- 内容区域已清空 -->
|
||||
<!-- 内容区域 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -59,35 +63,68 @@ const props = defineProps({
|
||||
id: { type: String, required: true },
|
||||
title: { type: String, default: '面板区' },
|
||||
resizable: { type: Boolean, default: true },
|
||||
// 新增:初始状态(支持中文值)
|
||||
// 初始状态(支持中文值)
|
||||
WindowState: { type: String, default: '正常' },
|
||||
// 新增:默认尺寸
|
||||
// 默认尺寸
|
||||
width: { type: Number, default: 300 },
|
||||
height: { type: Number, default: 250 },
|
||||
// 新增:控制标题栏显示
|
||||
showTitleBar: { type: Boolean, default: true }
|
||||
// 控制标题栏显示
|
||||
showTitleBar: { type: Boolean, default: true },
|
||||
// 位置属性,可选
|
||||
left: { type: Number, default: undefined },
|
||||
top: { type: Number, default: undefined }
|
||||
})
|
||||
|
||||
// 本地状态:不再向父组件发事件,内部维护最大化/还原
|
||||
// 本地状态
|
||||
const localState = ref(props.WindowState)
|
||||
// 保存原始位置和大小信息
|
||||
const originalPosition = ref({
|
||||
width: props.width,
|
||||
height: props.height,
|
||||
left: props.left,
|
||||
top: props.top
|
||||
})
|
||||
|
||||
// 根据本地状态计算是否最大化
|
||||
const isMaximized = computed(() => localState.value === '最大化' || localState.value === 'maximized')
|
||||
|
||||
// 新增:根据状态计算尺寸样式
|
||||
// 根据状态计算尺寸和位置样式
|
||||
const areaStyle = computed(() => {
|
||||
if (isMaximized.value) {
|
||||
return { width: '100%', height: '100%' }
|
||||
// 最大化时填充满父容器
|
||||
return {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
zIndex: 100
|
||||
}
|
||||
return { width: `${props.width}px`, height: `${props.height}px` }
|
||||
}
|
||||
|
||||
// 非最大化状态:使用原始位置或默认居中
|
||||
const style = {
|
||||
width: `${originalPosition.value.width}px`,
|
||||
height: `${originalPosition.value.height}px`
|
||||
}
|
||||
|
||||
// 如果有明确的位置,则使用指定位置
|
||||
if (originalPosition.value.left !== undefined) {
|
||||
style.left = `${originalPosition.value.left}px`
|
||||
}
|
||||
if (originalPosition.value.top !== undefined) {
|
||||
style.top = `${originalPosition.value.top}px`
|
||||
}
|
||||
|
||||
return style
|
||||
})
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
const emit = defineEmits(['close', 'update:WindowState'])
|
||||
|
||||
const onToggleMaximize = () => {
|
||||
const next = isMaximized.value ? '正常' : '最大化'
|
||||
// 直接更新本地状态,不再 emit 到父组件
|
||||
localState.value = next
|
||||
emit('update:WindowState', next)
|
||||
}
|
||||
|
||||
const onClose = () => emit('close')
|
||||
@@ -110,6 +147,15 @@ const onClose = () => emit('close')
|
||||
}
|
||||
|
||||
/* 容器 */
|
||||
.vs-area-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.vs-area {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -119,6 +165,23 @@ const onClose = () => emit('close')
|
||||
min-height: 250px;
|
||||
}
|
||||
|
||||
/* 正常状态样式 */
|
||||
.vs-area.is-normal {
|
||||
position: static;
|
||||
}
|
||||
|
||||
/* 最大化状态样式 */
|
||||
.vs-area.is-maximized {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
position: absolute !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
z-index: 100 !important;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 标题栏 */
|
||||
.vs-title-bar {
|
||||
height: 28px;
|
||||
@@ -195,17 +258,25 @@ const onClose = () => emit('close')
|
||||
:deep(::-webkit-scrollbar-thumb:hover) { background: linear-gradient(to bottom, #c1c7e2, #b2b8d9); }
|
||||
|
||||
:deep(*) { box-sizing: border-box; }
|
||||
.vs-area.is-maximized { width: 100%; height: 100%; }
|
||||
.vs-area.is-maximized {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
.vs-icon-stage { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: transparent; overflow: auto; }
|
||||
.vs-app-icon--x200 { width: 2800px; height: 2800px; }
|
||||
.vs-app-icon { width: 14px; height: 14px; display: inline-block; background: transparent; opacity: 0.95; }
|
||||
.vs-icon { width: 100%; height: 100%; shape-rendering: crispEdges; }
|
||||
.vs-app-icon svg { display: block; }
|
||||
|
||||
/* 外层包裹,居中内容 */
|
||||
/* 外层包裹,确保最大化时填充父容器,非最大化时居中 */
|
||||
.vs-area-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@@ -1,26 +1,33 @@
|
||||
<template>
|
||||
<div class="dock-layout">
|
||||
<!-- 主区域 -->
|
||||
<Area :WindowState="windowState" :showTitleBar="false" title="主区域" />
|
||||
|
||||
<!-- 浮动区域列表 -->
|
||||
<Area
|
||||
v-for="area in floatingAreas"
|
||||
:key="area.id"
|
||||
:id="area.id"
|
||||
:title="area.title"
|
||||
:WindowState="area.WindowState"
|
||||
v-model:WindowState="area.WindowState"
|
||||
:showTitleBar="area.showTitleBar"
|
||||
:width="area.width"
|
||||
:height="area.height"
|
||||
:style="{
|
||||
:left="area.WindowState !== '最大化' ? area.x : undefined"
|
||||
:top="area.WindowState !== '最大化' ? area.y : undefined"
|
||||
:style="area.WindowState !== '最大化' ? {
|
||||
position: 'absolute',
|
||||
left: area.x + 'px',
|
||||
top: area.y + 'px',
|
||||
zIndex: 10
|
||||
} : {
|
||||
zIndex: 100
|
||||
}"
|
||||
@close="onCloseFloatingArea(area.id)"
|
||||
/>
|
||||
|
||||
<!-- 主区域 -->
|
||||
<Area
|
||||
:WindowState="windowState"
|
||||
:showTitleBar="false"
|
||||
title="主区域"
|
||||
:style="{ position: 'relative', zIndex: 1 }"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -100,7 +107,7 @@ defineExpose({
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/* 浮动区域样式已直接应用到Area组件 */
|
||||
|
||||
4
AutoRobot/Windows/Robot/Web/src/DockLayout/ToDoList.md
Normal file
4
AutoRobot/Windows/Robot/Web/src/DockLayout/ToDoList.md
Normal file
@@ -0,0 +1,4 @@
|
||||
### Area
|
||||
1. 初始添加时,默认宽300px,高250px。位置相对父容器水平居中,垂直居中。
|
||||
2. 最大化时,填充满父容器。
|
||||
3. 还原时,恢复到最大化前的位置和大小。
|
||||
Reference in New Issue
Block a user