first commit

This commit is contained in:
muzi
2025-06-16 14:42:26 +08:00
commit 6f06721506
149 changed files with 56883 additions and 0 deletions

View File

@ -0,0 +1,39 @@
<!--
* @Author: 田鑫
* @Date: 2024-06-07 13:42:33
* @LastEditors: 田鑫
* @LastEditTime: 2024-06-07 18:27:25
* @Description:
-->
<template>
<div id="comp1">
comp1
<!-- <div class="flex-item">comp 1</div>
<div class="flex-item">comp 1</div>
<div class="flex-item">comp 1</div> -->
</div>
</template>
<script setup lang="ts"></script>
<style lang="less" scoped>
.flex-container {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
}
.flex-item {
background-color: #4caf50;
padding: 20px;
margin: 10px;
color: white;
font-size: 1.5em;
text-align: center;
border-radius: 5px;
flex: 1;
}
</style>

View File

@ -0,0 +1,13 @@
<!--
* @Author: 田鑫
* @Date: 2024-06-07 13:55:17
* @LastEditors: 田鑫
* @LastEditTime: 2024-06-07 18:27:29
* @Description:
-->
<template>
<div id="comp2">comp2</div>
</template>
<script setup lang="ts"></script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,13 @@
<!--
* @Author: 田鑫
* @Date: 2024-06-07 13:55:17
* @LastEditors: 田鑫
* @LastEditTime: 2024-06-07 18:27:32
* @Description:
-->
<template>
<div id="comp3">comp3</div>
</template>
<script setup lang="ts"></script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,13 @@
<!--
* @Author: 田鑫
* @Date: 2024-06-07 13:55:17
* @LastEditors: 田鑫
* @LastEditTime: 2024-06-07 18:27:35
* @Description:
-->
<template>
<div id="comp4">comp4</div>
</template>
<script setup lang="ts"></script>
<style lang="less" scoped></style>

View File

@ -0,0 +1,408 @@
<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>
<style lang="less" scoped>
.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>