<template>
|
<div ref="layoutPanel" :class="panelClass" :style="panelStyle">
|
<div v-for="(layout, layoutIndex) in layouts" :key="layoutIndex"
|
class="layout-container"
|
:style="layoutContainerStyle(layoutIndex)">
|
|
|
|
<div v-for="(rect, rectIndex) in layout.rects" :key="rectIndex"
|
:ref="(el) => { if (el) rectsElements[layoutIndex + '-' + rectIndex] = el }"
|
:class="rectClass"
|
:style="rectStyle(rect, layoutIndex)"
|
@click="handleRectClick(layoutIndex, rectIndex)">
|
<div v-if="!rect.isRemain" class="rect-content">
|
<div class="size">{{ rect.w }}×{{ rect.h }}</div>
|
<div class="jia-hao">{{ rect.JiaHao }}</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, onMounted, onUnmounted } from 'vue';
|
|
const props = defineProps({
|
layoutData: {
|
type: Object,
|
required: true
|
},
|
gw: {
|
type: Number,
|
default: 1000
|
},
|
gh: {
|
type: Number,
|
default: 1000
|
},
|
style: {
|
type: String,
|
default: 'width:1000px;height:600px;display:block;background:gray'
|
}
|
});
|
|
const emit = defineEmits(['rectClicked']);
|
|
const layoutPanel = ref(null);
|
const rectsElements = ref({});
|
const focusIndex = ref(null);
|
const layouts = ref([]);
|
|
const panelClass = ref('');
|
const panelStyle = ref(props.style);
|
|
const rectClass = ref('layout-rect');
|
|
const layoutContainerStyle = (layoutIndex) => {
|
const containerWidth = (props.gw - 210) / 2; // 两列,每列宽度为gw的一半,减去右边距
|
const containerHeight = (props.gh - 100) / 3; // 三行,每行高度为gh的三分之一,减去下边距
|
const x = (layoutIndex % 2) * (containerWidth + 50); // 横向排列,加上50px间距
|
const y = Math.floor(layoutIndex / 2) * (containerHeight + 50); // 纵向排列,加上50px间距
|
return {
|
position: 'absolute',
|
left: `${x}px`,
|
top: `${y}px`,
|
width: `${containerWidth}px`,
|
height: `${containerHeight}px`,
|
overflow: 'visible', // 修改:设置为 visible,确保 layout-info 不被截断
|
border: '1px solid #ccc',
|
background: '#fff'
|
};
|
};
|
|
const rectStyle = (rect, layoutIndex) => {
|
const layout = layouts.value[layoutIndex];
|
const containerWidth = (props.gw - 100) / 2;
|
const containerHeight = (props.gh - 100) / 3;
|
const scale = Math.min(
|
containerWidth / layout.width,
|
containerHeight / layout.height
|
);
|
|
return {
|
position: 'absolute',
|
left: `${rect.x * scale}px`,
|
top: `${rect.y * scale}px`,
|
width: `${rect.w * scale}px`,
|
height: `${rect.h * scale}px`,
|
backgroundColor: rect.isRemain ? '#f0f0f0' : '#a0d8ef',
|
border: '1px solid #000',
|
cursor: 'pointer'
|
};
|
};
|
|
const handleRectClick = (layoutIndex, rectIndex) => {
|
focusIndex.value = { layoutIndex, rectIndex };
|
emit('rectClicked', layoutIndex, rectIndex);
|
};
|
|
const updateLayout = () => {
|
if (!layoutPanel.value) return;
|
|
layouts.value = props.layoutData.data.Layouts;
|
};
|
|
onMounted(() => {
|
updateLayout();
|
});
|
|
onUnmounted(() => {
|
rectsElements.value = {};
|
});
|
</script>
|
|
<style scoped>
|
.layout-container {
|
position: relative;
|
overflow: visible; /* 修改:设置为 visible,确保 layout-info 不被截断 */
|
}
|
|
.layout-info {
|
position: absolute;
|
top: 5px;
|
right: 5px;
|
color: #444;
|
font-size: 12px;
|
background-color: #ffffff;
|
padding: 5px;
|
border-radius: 3px;
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
z-index: 1000; /* 确保 layout-info 显示在其他元素的上方 */
|
}
|
|
.layout-rect {
|
transition: border-color 0.2s;
|
}
|
|
.rect-content {
|
display: grid;
|
grid-template-columns: 1fr;
|
grid-template-rows: 1fr;
|
padding: 5px;
|
}
|
|
.size {
|
grid-row: 1;
|
grid-column: 1;
|
color: #444;
|
font-size: 12px;
|
}
|
|
.jia-hao {
|
grid-row: 2;
|
grid-column: 1;
|
margin: auto;
|
font-size: 14px;
|
font-weight: bold;
|
}
|
</style>
|