!19 新增封装分割面板组件

Merge pull request !19 from 莫名点/develop
This commit is contained in:
就眠儀式 2022-01-20 05:38:53 +00:00 committed by Gitee
commit 1fc3e3c411
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
8 changed files with 459 additions and 4 deletions

View File

@ -0,0 +1,138 @@
::: anchor
:::
::: title 基础使用
:::
::: demo
<template>
<div>
<lay-split-panel style="height: 300px">
<lay-split-panel-item>A</lay-split-panel-item>
<lay-split-panel-item>B</lay-split-panel-item>
<lay-split-panel-item>C</lay-split-panel-item>
</lay-split-panel>
</div>
</template>
<script>
export default {
setup() {
}
}
</script>
:::
::: title 自定义比例
:::
::: demo
<template>
<div>
<lay-split-panel style="height: 300px">
<lay-split-panel-item :space="30">1</lay-split-panel-item>
<lay-split-panel-item :space="20">2</lay-split-panel-item>
<lay-split-panel-item :space="50">3</lay-split-panel-item>
</lay-split-panel>
</div>
</template>
<script>
export default {
setup() {
}
}
</script>
:::
::: title 垂直布局
:::
::: demo
<template>
<div>
<lay-split-panel :vertical="true" style="height: 600px; width: 100%">
<lay-split-panel-item>1</lay-split-panel-item>
<lay-split-panel-item>2</lay-split-panel-item>
<lay-split-panel-item>3</lay-split-panel-item>
</lay-split-panel>
</div>
</template>
<script>
export default {
setup() {
}
}
</script>
:::
::: title 组合用法
:::
::: demo
<template>
<div>
<lay-split-panel style="height: 600px;">
<lay-split-panel-item :space="60">
<lay-split-panel :vertical="true" style="height: 600px; width: 100%">
<lay-split-panel-item :space="40">1</lay-split-panel-item>
<lay-split-panel-item :space="40">2</lay-split-panel-item>
</lay-split-panel>
</lay-split-panel-item>
<lay-split-panel-item :space="40">2</lay-split-panel-item>
</lay-split-panel>
</div>
</template>
<script>
export default {
setup() {
}
}
</script>
:::
::: title splitPanel属性
:::
::: table
| 属性 | 描述 | 类型 |可选值 | 默认值|
| ----- | ---- | ------ | ---| ---|
| vertical | 是否垂直布局 | Boolean |`true` `false`| false |
| minSize | 块拉动最小范围(按像素 `px`) | number | - | 50 |
:::
::: title splitPanelItem属性
:::
::: table
| 属性 | 描述 | 类型 |可选值 | 默认值|
| ----- | ---- | ------ | ---| ---|
| space | 默认每个站多大比例(`%`, 设置一个,<br/> 其他的都需要设置,合计为(`100` | number | - | 按照个数平分 |
:::
::: comment
:::
::: previousNext splitPanel
:::

View File

@ -76,6 +76,12 @@ const zhCN = [
component: Component, component: Component,
meta: { title: "组件" }, meta: { title: "组件" },
children: [ children: [
{
path: "/zh-CN/components/splitPanel",
component: () =>
import("../../docs/zh-CN/components/splitPanel.md"),
meta: { title: "分割面板" },
},
{ {
path: "/zh-CN/components/skeleton", path: "/zh-CN/components/skeleton",
component: () => import("../../docs/zh-CN/components/skeleton.md"), component: () => import("../../docs/zh-CN/components/skeleton.md"),

View File

@ -71,9 +71,13 @@ import LaySkeleton from "./module/skeleton/index";
import LaySkeletonItem from "./module/skeletonItem/index"; import LaySkeletonItem from "./module/skeletonItem/index";
import LayStep from "./module/step/index"; import LayStep from "./module/step/index";
import LayStepItem from "./module/stepItem/index"; import LayStepItem from "./module/stepItem/index";
import LaySubMenu from "./module/subMenu/index" import LaySubMenu from "./module/subMenu/index";
import LaySplitPanel from "./module/splitPanel/index";
import LaySplitPanelItem from "./module/splitPanelItem/index";
export const components: Record<string, IDefineComponent> = { const components: Record<string, IDefineComponent> = {
LaySplitPanel,
LaySplitPanelItem,
LayRadio, LayRadio,
LayButton, LayButton,
LayIcon, LayIcon,
@ -139,7 +143,7 @@ export const components: Record<string, IDefineComponent> = {
LayCountUp, LayCountUp,
LayStep, LayStep,
LayStepItem, LayStepItem,
LaySubMenu LaySubMenu,
}; };
const install = (app: App, options?: InstallOptions): void => { const install = (app: App, options?: InstallOptions): void => {
@ -152,6 +156,8 @@ const install = (app: App, options?: InstallOptions): void => {
}; };
export { export {
LaySplitPanel,
LaySplitPanelItem,
LayRadio, LayRadio,
LayButton, LayButton,
LayIcon, LayIcon,
@ -217,7 +223,7 @@ export {
LayCountUp, LayCountUp,
LayStep, LayStep,
LayStepItem, LayStepItem,
LaySubMenu LaySubMenu,
}; };
export { layer }; export { layer };

View File

@ -0,0 +1,63 @@
.lay-split-panel{
height: 100%;
display: flex;
position: relative;
.lay-split-panel-item {
height: 100%;
flex-grow: 1;
border: 1px #eeeeee solid;
}
.lay-split-panel-item-move{
user-select: none;
pointer-events: none;
cursor: col-resize;
}
.lay-split-panel-line{
height: 100%;
width: 3px;
border: 1px #eeeeee solid;
background-color: #fafafa;
border-left: none;
border-right: none;
cursor: col-resize;
display: flex;
align-items: center;
&:before{
content: "";
height: 6px;
width: 100%;
border: 2px solid #dcdee2;
border-left: 0;
border-right: 0;
}
}
}
.lay-split-panel-vertical{
flex-direction: column;
position: relative;
.lay-split-panel-item-move{
user-select: none;
pointer-events: none;
cursor: row-resize;
}
.lay-split-panel-line{
display: flex;
justify-content: center;
width: 100%;
height: 3px;
cursor: row-resize;
border: 1px #eeeeee solid;
background-color: #fafafa;
border-top: none;
border-bottom: none;
&:before{
content: "";
height: 100%;
width: 6px;
border: 2px solid #dcdee2;
border-top: none;
border-bottom: none;
}
}
}

View File

@ -0,0 +1,9 @@
import type { App } from "vue";
import Component from "./index.vue";
import type { IDefineComponent } from "../type/index";
Component.install = (app: App) => {
app.component(Component.name || "laySplitPanel", Component);
};
export default Component as IDefineComponent;

View File

@ -0,0 +1,128 @@
<template>
<div
ref="target"
:class="['lay-split-panel', vertical ? 'lay-split-panel-vertical' : '']"
:style="{
cursor: domStatus ? (!vertical ? 'col-resize' : 'row-resize') : '',
}"
v-on="{ mouseup: mouseup }"
>
<slot></slot>
</div>
</template>
<script setup name="laySplitPanel" lang="ts">
import { ref, watch, provide, defineProps, withDefaults, onMounted } from "vue";
import "./index.less";
//
export interface LayStepProps {
vertical?: boolean;
minSize?: number;
}
// props
const props = withDefaults(defineProps<LayStepProps>(), {
vertical: false,
minSize: 50,
});
let domEvent = ref();
let domStatus = ref(false);
const target = ref();
onMounted(() => {
const boxWidth = target.value.offsetWidth;
const boxHeight = target.value.offsetHeight;
window.addEventListener("scroll", (event) => {
console.log(event);
});
target.value.addEventListener(
"mousemove",
(event: { layerX: any; layerY: any }) => {
if (domStatus.value) {
const prevDom = domEvent.value.target.previousElementSibling;
const nextDom = domEvent.value.target.nextElementSibling;
if (!props.vertical) {
const prevDomLeft =
domEvent.value.target.previousElementSibling.offsetLeft;
const prevDomWidth =
domEvent.value.target.previousElementSibling.offsetWidth;
const nextDomWidth =
domEvent.value.target.nextElementSibling.offsetWidth;
const otherWidth = boxWidth - (prevDomWidth + nextDomWidth + 5);
const otherWidthPercentage =
((prevDomWidth + nextDomWidth + 5) / boxWidth) * 100;
if (
event.layerX - prevDomLeft < props.minSize ||
boxWidth - (event.layerX - prevDomLeft) - otherWidth < props.minSize
) {
return false;
}
prevDom.style.width =
((event.layerX - prevDomLeft) / (prevDomWidth + nextDomWidth + 5)) *
otherWidthPercentage +
"%";
nextDom.style.width =
((boxWidth - (event.layerX - prevDomLeft) - otherWidth) /
(prevDomWidth + nextDomWidth + 5)) *
otherWidthPercentage +
"%";
} else {
const prevDomTop =
domEvent.value.target.previousElementSibling.offsetTop;
const prevDomHeight =
domEvent.value.target.previousElementSibling.offsetHeight;
const nextDomHeight =
domEvent.value.target.nextElementSibling.offsetHeight;
const otherHeight = boxHeight - (prevDomHeight + nextDomHeight + 5);
const otherHeightPercentage =
((prevDomHeight + nextDomHeight + 5) / boxHeight) * 100;
if (
event.layerY - prevDomTop < props.minSize ||
boxHeight - (event.layerY - prevDomTop) - otherHeight <
props.minSize
) {
return false;
}
prevDom.style.height =
((event.layerY - prevDomTop) /
(prevDomHeight + nextDomHeight + 5)) *
otherHeightPercentage +
"%";
nextDom.style.height =
((boxHeight - (event.layerY - prevDomTop) - otherHeight) /
(prevDomHeight + nextDomHeight + 5)) *
otherHeightPercentage +
"%";
}
}
}
);
});
const moveChange = (event: any, status: boolean) => {
domEvent.value = event;
domStatus.value = status;
};
const mouseup = () => {
domStatus.value = false;
};
//
const steps = ref([]);
// lay-split-panel-item
watch(steps, () => {
steps.value.forEach(
(instance: { setIndex: (arg0: any) => void }, index: any) => {
instance.setIndex(index);
}
);
});
// lay-split-panel-item
provide("laySplitPanel", {
props,
steps,
moveChange,
});
</script>

View File

@ -0,0 +1,9 @@
import type { App } from "vue";
import Component from "./index.vue";
import type { IDefineComponent } from "../type/index";
Component.install = (app: App) => {
app.component(Component.name || "laySplitPanelItem", Component);
};
export default Component as IDefineComponent;

View File

@ -0,0 +1,96 @@
<template>
<div
v-if="!isStart"
:class="[!isStart ? 'lay-split-panel-line' : '']"
ref="el"
v-on="{ mousedown: mousedown, mouseup: mouseup }"
></div>
<div
v-if="isVertical"
:class="['lay-split-panel-item']"
:style="{ height: `${space ? space : (100 + space) / stepsCount}%` }"
>
<slot></slot>
</div>
<div
v-else
:class="['lay-split-panel-item']"
:style="{ width: `${space ? space : (100 + space) / stepsCount}%` }"
>
<slot></slot>
</div>
</template>
<script setup name="laySplitPanelItem" lang="ts">
import {
ref,
inject,
onMounted,
computed,
getCurrentInstance,
onBeforeUnmount,
reactive,
defineProps,
withDefaults,
watch,
} from "vue";
import type { ComputedRef } from "vue";
export interface LayStepItemProps {
space?: number;
}
const props = withDefaults(defineProps<LayStepItemProps>(), {
space: 0,
});
const index = ref(-1);
const parents: any = inject("laySplitPanel");
const currentInstance: any = getCurrentInstance();
const moveStatus = ref(false);
const setIndex = (val: number) => {
index.value = val;
};
const mousedown = (event: any) => {
moveStatus.value = true;
parents.moveChange(event, true);
};
const mouseup = (event: any) => {
moveStatus.value = false;
};
const stepsCount = computed(() => {
return parents.steps.value.length;
});
const isVertical = computed(() => {
return parents.props.vertical;
});
const isLast: ComputedRef<boolean> = computed(() => {
return (
parents.steps.value[stepsCount.value - 1]?.itemId === currentInstance.uid
);
});
const isStart: ComputedRef<boolean> = computed(() => {
return parents.steps.value[0]?.itemId === currentInstance.uid;
});
const stepItemState = reactive({
itemId: computed(() => currentInstance?.uid),
setIndex,
width: [],
});
parents.steps.value = [...parents.steps.value, stepItemState];
onMounted(() => {});
onBeforeUnmount(() => {
parents.steps.value = parents.steps.value.filter(
(instance: { itemId: any }) => instance.itemId !== currentInstance.uid
);
});
</script>