2025-06-16 14:42:26 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div class="page-container" ref="container">
|
|
|
|
|
|
<div class="layout-buttons">
|
|
|
|
|
|
<button @click="switchLayout('strategy1')">默认布局</button>
|
|
|
|
|
|
<button @click="switchLayout('strategy2')">策略2布局</button>
|
|
|
|
|
|
<button @click="switchLayout('strategy3')">策略3布局</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div>屏幕宽度:{{ screenWidth }}px</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="components-container">
|
|
|
|
|
|
<component
|
|
|
|
|
|
v-for="component in components"
|
|
|
|
|
|
:is="component.comp"
|
|
|
|
|
|
:key="component.id"
|
|
|
|
|
|
class="component"
|
|
|
|
|
|
:style="getComponentStyle(component)"
|
|
|
|
|
|
></component>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
import { ref, onMounted } from 'vue';
|
|
|
|
|
|
import Comp1 from './comp1.vue';
|
|
|
|
|
|
import Comp2 from './comp2.vue';
|
|
|
|
|
|
import Comp3 from './comp3.vue';
|
|
|
|
|
|
import Comp4 from './comp4.vue';
|
|
|
|
|
|
|
|
|
|
|
|
interface ComponentState {
|
|
|
|
|
|
id: string;
|
|
|
|
|
|
comp: ReturnType<typeof defineComponent>;
|
|
|
|
|
|
x: number | string;
|
|
|
|
|
|
y: number | string;
|
|
|
|
|
|
width?: number | string;
|
|
|
|
|
|
minWidth?: number | string;
|
|
|
|
|
|
maxWidth?: number | string;
|
|
|
|
|
|
height: number;
|
|
|
|
|
|
zIndex?: number | string;
|
|
|
|
|
|
background?: string;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const components = ref<ComponentState[]>([]);
|
|
|
|
|
|
const container = ref<HTMLElement | null>(null);
|
|
|
|
|
|
const screenWidth = ref(0);
|
|
|
|
|
|
const screenHeight = ref(0);
|
|
|
|
|
|
const layoutComp1 = shallowRef(Comp1);
|
|
|
|
|
|
const layoutComp2 = shallowRef(Comp2);
|
|
|
|
|
|
const layoutComp3 = shallowRef(Comp3);
|
|
|
|
|
|
const layoutComp4 = shallowRef(Comp4);
|
|
|
|
|
|
|
|
|
|
|
|
const layoutCompMap = {
|
|
|
|
|
|
comp1: layoutComp1,
|
|
|
|
|
|
comp2: layoutComp2,
|
|
|
|
|
|
comp3: layoutComp3,
|
|
|
|
|
|
comp4: layoutComp4,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const containerWidth = ref(0);
|
|
|
|
|
|
const containerHeight = ref(0);
|
|
|
|
|
|
const currentLayoutStrategy = ref<LayoutStrategy>('strategy1');
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
const observedElement = document.querySelector('#app');
|
|
|
|
|
|
if (observedElement) {
|
|
|
|
|
|
const resizeObserver = new ResizeObserver((entries) => {
|
|
|
|
|
|
const entry = entries[0];
|
|
|
|
|
|
const { width, height } = entry.contentRect;
|
|
|
|
|
|
screenWidth.value = width;
|
|
|
|
|
|
screenHeight.value = height;
|
|
|
|
|
|
|
|
|
|
|
|
console.log('screenWidth', width);
|
|
|
|
|
|
|
|
|
|
|
|
const compStyles = loadComponentWidthRange(currentLayoutStrategy.value, width);
|
|
|
|
|
|
if (compStyles) {
|
|
|
|
|
|
setComponentStyleByStrategy(compStyles);
|
|
|
|
|
|
}
|
|
|
|
|
|
// const screenResolution = getComponentWidthRange(width);
|
|
|
|
|
|
// if (screenResolution) {
|
|
|
|
|
|
// setComponentStyleByStrategy(screenResolution.compStyles);
|
|
|
|
|
|
// }
|
|
|
|
|
|
});
|
|
|
|
|
|
resizeObserver.observe(observedElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
type Coordinate = number | [number, number];
|
|
|
|
|
|
|
|
|
|
|
|
type ComponentWidthRange = {
|
|
|
|
|
|
width: [number, number];
|
|
|
|
|
|
height: number;
|
|
|
|
|
|
compName: string;
|
|
|
|
|
|
background?: string;
|
|
|
|
|
|
x: Coordinate;
|
|
|
|
|
|
y: Coordinate;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
type ScreenResolutionMap = {
|
|
|
|
|
|
[resolutionRange: string]: {
|
|
|
|
|
|
layoutStrategy: string;
|
|
|
|
|
|
compStyles: ComponentWidthRange[];
|
|
|
|
|
|
};
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
type LayoutStrategy = 'strategy1' | 'strategy2' | 'strategy3';
|
|
|
|
|
|
|
|
|
|
|
|
type Resolution = {
|
|
|
|
|
|
[resolutionRange: string]: ComponentWidthRange[];
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
type ScreenResolutionMap1 = {
|
|
|
|
|
|
layoutStrategy: LayoutStrategy;
|
|
|
|
|
|
resolution: Resolution;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const screenResolutionMap1: ScreenResolutionMap1[] = [
|
|
|
|
|
|
{
|
|
|
|
|
|
layoutStrategy: 'strategy1',
|
|
|
|
|
|
resolution: {
|
|
|
|
|
|
'[0, 768]': [
|
|
|
|
|
|
{ width: [498, 498], compName: 'comp1', height: 550, background: 'red', x: 266, y: 0 },
|
|
|
|
|
|
{ width: [498, 498], compName: 'comp2', height: 304, background: '#ccdc', x: [266, 266], y: 550 },
|
|
|
|
|
|
{ width: [266, 266], compName: 'comp3', height: 856, background: '#5E6673', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [768, 768], compName: 'comp4', height: 304, background: 'blue', x: 0, y: 856 },
|
|
|
|
|
|
],
|
|
|
|
|
|
'[769, 1280]': [
|
|
|
|
|
|
{ width: [498, 836], compName: 'comp1', height: 610, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [135, 222], compName: 'comp2', height: 610, background: '#ccdc', x: [498, 836], y: 0 },
|
|
|
|
|
|
{ width: [135, 222], compName: 'comp3', height: 908, background: '#5E6673', x: [768, 1012], y: 0 },
|
|
|
|
|
|
{ width: [768, 1012], compName: 'comp4', height: 356, background: 'blue', x: 0, y: 610 },
|
|
|
|
|
|
],
|
|
|
|
|
|
'[1281, 1440]': [
|
|
|
|
|
|
{ width: [836, 836], compName: 'comp1', height: 610, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [222, 302], compName: 'comp2', height: 610, background: '#ccdc', x: 836, y: 0 },
|
|
|
|
|
|
{ width: [222, 302], compName: 'comp3', height: 908, background: '#5E6673', x: [1058, 1138], y: 0 },
|
|
|
|
|
|
{ width: [1012, 1138], compName: 'comp4', height: 410, background: 'blue', x: 0, y: 610 },
|
|
|
|
|
|
],
|
|
|
|
|
|
'[1441, 1920]': [
|
|
|
|
|
|
{ width: [836, 1196], compName: 'comp1', height: 610, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [302, 362], compName: 'comp2', height: 610, background: '#ccdc', x: [836, 1196], y: 0 },
|
|
|
|
|
|
{ width: [302, 362], compName: 'comp3', height: 908, background: '#5E6673', x: [1138, 1158], y: 0 },
|
|
|
|
|
|
{ width: [1138, 1558], compName: 'comp4', height: 410, background: 'blue', x: 0, y: 610 },
|
|
|
|
|
|
],
|
|
|
|
|
|
'[1921, 3860]': [
|
|
|
|
|
|
{ width: [1196, 1696], compName: 'comp1', height: 610, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [362, 432], compName: 'comp2', height: 610, background: '#ccdc', x: [1196, 1696], y: 0 },
|
|
|
|
|
|
{ width: [362, 432], compName: 'comp3', height: 908, background: '#5E6673', x: [1558, 2128], y: 0 },
|
|
|
|
|
|
{ width: [1558, 2128], compName: 'comp4', height: 356, background: 'blue', x: 0, y: 610 },
|
|
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
layoutStrategy: 'strategy2',
|
|
|
|
|
|
resolution: {
|
|
|
|
|
|
'[0, 768]': [
|
|
|
|
|
|
{ width: [200, 300], compName: 'comp1', height: 500, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [300, 400], compName: 'comp2', height: 500, background: '#ccdc', x: [200, 300], y: 0 },
|
|
|
|
|
|
{ width: [300, 400], compName: 'comp3', height: 970, background: '#5E6673', x: [500, 700], y: 0 },
|
|
|
|
|
|
{ width: [300, 400], compName: 'comp4', height: 410, background: 'blue', x: 0, y: 500 },
|
|
|
|
|
|
],
|
|
|
|
|
|
'[769, 1280]': [
|
|
|
|
|
|
{ width: [200, 300], compName: 'comp1', height: 500, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [300, 400], compName: 'comp2', height: 500, background: '#ccdc', x: [200, 300], y: 0 },
|
|
|
|
|
|
{ width: [300, 400], compName: 'comp3', height: 970, background: '#5E6673', x: [500, 700], y: 0 },
|
|
|
|
|
|
{ width: [300, 400], compName: 'comp4', height: 410, background: 'blue', x: 0, y: 500 },
|
|
|
|
|
|
],
|
|
|
|
|
|
'[1281, 1440]': [
|
|
|
|
|
|
{ width: [280, 400], compName: 'comp1', height: 600, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [350, 450], compName: 'comp2', height: 500, background: '#ccdc', x: [280, 400], y: 0 },
|
|
|
|
|
|
{ width: [350, 450], compName: 'comp3', height: 970, background: '#5E6673', x: [630, 850], y: 0 },
|
|
|
|
|
|
{ width: [350, 450], compName: 'comp4', height: 410, background: 'blue', x: 0, y: 600 },
|
|
|
|
|
|
],
|
|
|
|
|
|
'[1441, 1920]': [
|
|
|
|
|
|
{ width: [320, 420], compName: 'comp1', height: 500, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [400, 500], compName: 'comp2', height: 500, background: '#ccdc', x: [320, 420], y: 0 },
|
|
|
|
|
|
{ width: [400, 500], compName: 'comp3', height: 970, background: '#5E6673', x: [720, 920], y: 0 },
|
|
|
|
|
|
{ width: [400, 500], compName: 'comp4', height: 410, background: 'blue', x: 0, y: 500 },
|
|
|
|
|
|
],
|
|
|
|
|
|
'[1921, 3860]': [
|
|
|
|
|
|
{ width: [800, 1000], compName: 'comp1', height: 600, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [500, 600], compName: 'comp2', height: 600, background: '#ccdc', x: [800, 1000], y: 0 },
|
|
|
|
|
|
{ width: [500, 600], compName: 'comp3', height: 1070, background: '#5E6673', x: [1300, 1600], y: 0 },
|
|
|
|
|
|
{ width: [500, 600], compName: 'comp4', height: 510, background: 'blue', x: 0, y: 600 },
|
|
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
layoutStrategy: 'strategy3',
|
|
|
|
|
|
resolution: {
|
|
|
|
|
|
'[0, 768]': [
|
|
|
|
|
|
{ width: [200, 300], compName: 'comp1', height: 500, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [300, 400], compName: 'comp2', height: 500, background: '#ccdc', x: [200, 300], y: 0 },
|
|
|
|
|
|
{ width: [300, 400], compName: 'comp3', height: 970, background: '#5E6673', x: [500, 700], y: 0 },
|
|
|
|
|
|
{ width: [300, 400], compName: 'comp4', height: 410, background: 'blue', x: 0, y: 500 },
|
|
|
|
|
|
],
|
|
|
|
|
|
'[769, 1280]': [
|
|
|
|
|
|
{ width: [200, 300], compName: 'comp1', height: 500, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [300, 400], compName: 'comp2', height: 500, background: '#ccdc', x: [200, 300], y: 0 },
|
|
|
|
|
|
{ width: [300, 400], compName: 'comp3', height: 970, background: '#5E6673', x: [500, 700], y: 0 },
|
|
|
|
|
|
{ width: [300, 400], compName: 'comp4', height: 410, background: 'blue', x: 0, y: 500 },
|
|
|
|
|
|
],
|
|
|
|
|
|
'[1281, 1440]': [
|
|
|
|
|
|
{ width: [280, 400], compName: 'comp1', height: 600, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [350, 450], compName: 'comp2', height: 500, background: '#ccdc', x: [280, 400], y: 0 },
|
|
|
|
|
|
{ width: [350, 450], compName: 'comp3', height: 970, background: '#5E6673', x: [630, 850], y: 0 },
|
|
|
|
|
|
{ width: [350, 450], compName: 'comp4', height: 410, background: 'blue', x: 0, y: 600 },
|
|
|
|
|
|
],
|
|
|
|
|
|
'[1441, 1920]': [
|
|
|
|
|
|
{ width: [320, 420], compName: 'comp1', height: 500, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [400, 500], compName: 'comp2', height: 500, background: '#ccdc', x: [320, 420], y: 0 },
|
|
|
|
|
|
{ width: [400, 500], compName: 'comp3', height: 970, background: '#5E6673', x: [720, 920], y: 0 },
|
|
|
|
|
|
{ width: [400, 500], compName: 'comp4', height: 410, background: 'blue', x: 0, y: 500 },
|
|
|
|
|
|
],
|
|
|
|
|
|
'[1921, 3860]': [
|
|
|
|
|
|
{ width: [800, 1000], compName: 'comp1', height: 600, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [500, 600], compName: 'comp2', height: 600, background: '#ccdc', x: [800, 1000], y: 0 },
|
|
|
|
|
|
{ width: [500, 600], compName: 'comp3', height: 1070, background: '#5E6673', x: [1300, 1600], y: 0 },
|
|
|
|
|
|
{ width: [500, 600], compName: 'comp4', height: 510, background: 'blue', x: 0, y: 600 },
|
|
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
// 创建屏幕分辨率宽度到组件宽度区间的映射表
|
|
|
|
|
|
const screenResolutionMap: ScreenResolutionMap = {
|
|
|
|
|
|
'[1024, 1280]': {
|
|
|
|
|
|
layoutStrategy: 'strategy1',
|
|
|
|
|
|
compStyles: [
|
|
|
|
|
|
{ width: [200, 300], compName: 'comp1', height: 500, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [300, 400], compName: 'comp2', height: 500, background: '#ccdc', x: [200, 300], y: 0 },
|
|
|
|
|
|
{ width: [300, 400], compName: 'comp3', height: 970, background: '#5E6673', x: [500, 700], y: 0 },
|
|
|
|
|
|
{ width: [300, 400], compName: 'comp4', height: 410, background: 'blue', x: 0, y: 500 },
|
|
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
'[1281, 1440]': {
|
|
|
|
|
|
layoutStrategy: 'strategy2',
|
|
|
|
|
|
compStyles: [
|
|
|
|
|
|
{ width: [280, 400], compName: 'comp1', height: 600, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [350, 450], compName: 'comp2', height: 500, background: '#ccdc', x: [280, 400], y: 0 },
|
|
|
|
|
|
{ width: [350, 450], compName: 'comp3', height: 970, background: '#5E6673', x: [630, 850], y: 0 },
|
|
|
|
|
|
{ width: [350, 450], compName: 'comp4', height: 410, background: 'blue', x: 0, y: 600 },
|
|
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
'[1441, 1920]': {
|
|
|
|
|
|
layoutStrategy: 'strategy3',
|
|
|
|
|
|
compStyles: [
|
|
|
|
|
|
{ width: [320, 420], compName: 'comp1', height: 500, background: 'red', x: [400, 500], y: 0 },
|
|
|
|
|
|
{ width: [400, 500], compName: 'comp2', height: 500, background: '#ccdc', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [400, 500], compName: 'comp3', height: 970, background: '#5E6673', x: [720, 920], y: 0 },
|
|
|
|
|
|
{ width: [400, 500], compName: 'comp4', height: 410, background: 'blue', x: 0, y: 500 },
|
|
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
'[1921, 3860]': {
|
|
|
|
|
|
layoutStrategy: 'strategy4',
|
|
|
|
|
|
compStyles: [
|
|
|
|
|
|
{ width: [800, 1000], compName: 'comp1', height: 600, background: 'red', x: 0, y: 0 },
|
|
|
|
|
|
{ width: [500, 600], compName: 'comp2', height: 600, background: '#ccdc', x: [800, 1000], y: 0 },
|
|
|
|
|
|
{ width: [500, 600], compName: 'comp3', height: 1070, background: '#5E6673', x: [1300, 1600], y: 0 },
|
|
|
|
|
|
{ width: [500, 600], compName: 'comp4', height: 510, background: 'blue', x: 0, y: 600 },
|
|
|
|
|
|
],
|
|
|
|
|
|
},
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function getComponentWidthRange(screenWidth: number): ScreenResolutionMap | null {
|
|
|
|
|
|
for (const resolutionRange in screenResolutionMap) {
|
|
|
|
|
|
const [minWidth, maxWidth] = JSON.parse(resolutionRange.replace('[', '[').replace(']', ']'));
|
|
|
|
|
|
if (screenWidth >= minWidth && screenWidth <= maxWidth) {
|
|
|
|
|
|
return screenResolutionMap[resolutionRange];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null; // 如果没有找到对应的分辨率范围,则返回null
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const getComponentWidthRange1 = (screenWidth: number, resolution: Resolution): ComponentWidthRange[] | null => {
|
|
|
|
|
|
for (const resolutionRange in resolution) {
|
|
|
|
|
|
const [minWidth, maxWidth] = JSON.parse(resolutionRange.replace('[', '[').replace(']', ']'));
|
|
|
|
|
|
if (screenWidth >= minWidth && screenWidth <= maxWidth) {
|
|
|
|
|
|
return resolution[resolutionRange];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null; // 如果没有找到对应的分辨率范围,则返回null
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const loadComponentWidthRange = (layoutStrategy: LayoutStrategy, screenWidth: number): ComponentWidthRange[] => {
|
|
|
|
|
|
let layoutStyles: ComponentWidthRange[] | null = [];
|
|
|
|
|
|
for (let item of screenResolutionMap1) {
|
|
|
|
|
|
console.log('layoutStrategy', item.layoutStrategy);
|
|
|
|
|
|
if (item.layoutStrategy === layoutStrategy) {
|
|
|
|
|
|
layoutStyles = getComponentWidthRange1(screenWidth, item.resolution);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!layoutStyles || layoutStyles.length === 0) {
|
|
|
|
|
|
layoutStyles = getComponentWidthRange1(screenWidth, screenResolutionMap1[0].resolution) as ComponentWidthRange[];
|
|
|
|
|
|
}
|
|
|
|
|
|
return layoutStyles;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const setComponentStyleByStrategy = (compStyles: ComponentWidthRange[]) => {
|
|
|
|
|
|
components.value = compStyles.map((item) => {
|
|
|
|
|
|
const compPosition = getRelativePosition(item, screenWidth.value);
|
|
|
|
|
|
return {
|
|
|
|
|
|
id: item.compName,
|
|
|
|
|
|
comp: layoutCompMap[item.compName],
|
|
|
|
|
|
x: compPosition.x,
|
|
|
|
|
|
y: item.y,
|
|
|
|
|
|
width: compPosition.width,
|
|
|
|
|
|
height: item.height,
|
|
|
|
|
|
zIndex: 1,
|
|
|
|
|
|
background: item.background,
|
|
|
|
|
|
};
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 计算组件相对位置和大小的函数
|
|
|
|
|
|
* @param compStyles - 组件的样式信息
|
|
|
|
|
|
* @param screenWidth - 屏幕宽度
|
|
|
|
|
|
* @returns 组件的计算位置和大小
|
|
|
|
|
|
*/
|
|
|
|
|
|
function getRelativePosition(compStyles: ComponentWidthRange, screenWidth: number): { x: string; width: string } {
|
|
|
|
|
|
const { x, width } = compStyles;
|
|
|
|
|
|
|
|
|
|
|
|
// 解析区间值
|
|
|
|
|
|
const parseRange = (value: Coordinate): { min: number; max: number } => {
|
|
|
|
|
|
if (Array.isArray(value)) {
|
|
|
|
|
|
const [min, max] = value;
|
|
|
|
|
|
return { min, max };
|
|
|
|
|
|
}
|
|
|
|
|
|
return { min: value, max: value };
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 转换为基于屏幕宽度的百分比
|
|
|
|
|
|
const toPercentage = (
|
|
|
|
|
|
range: { min: number; max: number },
|
|
|
|
|
|
screenWidth: number,
|
|
|
|
|
|
): { minPercentage: number; maxPercentage: number } => {
|
|
|
|
|
|
const minPercentage = (range.min / screenWidth) * 100;
|
|
|
|
|
|
const maxPercentage = (range.max / screenWidth) * 100;
|
|
|
|
|
|
return { minPercentage, maxPercentage };
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 解析并计算宽度和x值
|
|
|
|
|
|
const widthRange = parseRange(width);
|
|
|
|
|
|
const xRange = parseRange(x);
|
|
|
|
|
|
|
|
|
|
|
|
const widthPercentage = toPercentage(widthRange, screenWidth);
|
|
|
|
|
|
const xPercentage = toPercentage(xRange, screenWidth);
|
|
|
|
|
|
|
|
|
|
|
|
// 假设我们取区间的中间值作为最终值
|
|
|
|
|
|
const finalWidth = ((widthPercentage.minPercentage + widthPercentage.maxPercentage) / 2).toFixed(2);
|
|
|
|
|
|
const finalX = ((xPercentage.minPercentage + xPercentage.maxPercentage) / 2).toFixed(2);
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
x: finalX,
|
|
|
|
|
|
width: finalWidth,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
|
if (container.value) {
|
|
|
|
|
|
containerWidth.value = container.value.clientWidth;
|
|
|
|
|
|
containerHeight.value = container.value.clientHeight;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const switchLayout = (layoutStrategy: LayoutStrategy) => {};
|
|
|
|
|
|
|
|
|
|
|
|
function getComponentStyle(component: ComponentState) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
|
left: `${component.x}%`,
|
|
|
|
|
|
top: `${component.y}px`,
|
|
|
|
|
|
width: `${component.width}%`,
|
|
|
|
|
|
height: `${component.height}px`,
|
|
|
|
|
|
zIndex: component.zIndex,
|
|
|
|
|
|
background: component.background,
|
|
|
|
|
|
transition: 'all 0.25s ease',
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
2025-07-11 16:50:48 +08:00
|
|
|
|
<style lang="scss" scoped>
|
2025-06-16 14:42:26 +08:00
|
|
|
|
.page-container {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
.layout-buttons {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 5%;
|
|
|
|
|
|
}
|
|
|
|
|
|
.components-container {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 95%;
|
|
|
|
|
|
border: 1px solid #ccc;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
.component {
|
|
|
|
|
|
background-color: lightgray;
|
|
|
|
|
|
border: 1px solid #ccc;
|
|
|
|
|
|
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
transition: all 0.25s ease;
|
|
|
|
|
|
font-size: 24px;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|