chore: 规范 module 名称

This commit is contained in:
就眠儀式
2022-04-05 19:09:04 +08:00
parent 5a3482568a
commit 5f87bc67c7
215 changed files with 8 additions and 8 deletions

View File

@@ -0,0 +1,23 @@
<script lang="ts">
export default {
name: "CloseBtn",
};
</script>
<script lang="ts" setup>
import { computed, defineEmits } from "vue";
const emit = defineEmits(["closeHandle"]);
const closeHandle = () => {
emit("closeHandle");
};
</script>
<template>
<a
class="layui-layer-ico layui-layer-close layui-layer-close1"
href="javascript:;"
@click="closeHandle"
></a>
</template>

View File

@@ -0,0 +1,23 @@
<script lang="ts">
export default {
name: "Iframe",
};
</script>
<script lang="ts" setup>
export interface IframeProps {
src: string;
}
const props = defineProps<IframeProps>();
</script>
<template>
<iframe
scrolling="auto"
class="layui-layer-iframe"
allowtransparency="true"
frameborder="0"
:src="src"
></iframe>
</template>

View File

@@ -0,0 +1,9 @@
<script lang="ts">
export default {
name: "Resize",
};
</script>
<template>
<span class="layui-layer-resize"></span>
</template>

View File

@@ -0,0 +1,39 @@
<script lang="ts">
export default {
name: "Shade",
};
</script>
<script lang="ts" setup>
import { computed, defineEmits } from "vue";
const emit = defineEmits(["shadeClick"]);
export interface ShadeProps {
index: number;
opacity: string;
visible: boolean;
}
const props = defineProps<ShadeProps>();
const styles = computed(() => {
return {
opacity: props.opacity,
zIndex: props.index,
};
});
const shadeClick = () => {
emit("shadeClick");
};
</script>
<template>
<div
class="layui-layer-shade"
:style="styles"
@click="shadeClick"
v-if="visible"
></div>
</template>

View File

@@ -0,0 +1,26 @@
<script lang="ts">
export default {
name: "Title",
};
</script>
<script lang="ts" setup>
export interface HeaderProps {
title: string;
}
const renderContent = function (content: any) {
if (typeof content === "function") {
return content();
}
return content;
};
const props = defineProps<HeaderProps>();
</script>
<template>
<div class="layui-layer-title" style="cursor: move">
{{ renderContent(title) }}
</div>
</template>

View File

@@ -0,0 +1 @@
export { default as LayLayer } from "./index.vue"; // layer component

View File

@@ -0,0 +1,610 @@
<script lang="ts">
export default {
name: "LayLayer",
};
</script>
<script lang="ts" setup>
import Shade from "./Shade.vue";
import Iframe from "./Iframe.vue";
import Title from "./Title.vue";
import CloseBtn from "./CloseBtn.vue";
import Resize from "./Resize.vue";
import {
Ref,
ref,
watch,
computed,
useSlots,
VNodeTypes,
nextTick,
inject,
} from "vue";
import {
nextId,
maxArea,
maxOffset,
getArea,
calculateArea,
calculateOffset,
calculateContent,
calculateType,
minArea,
minOffset,
updateMinArrays,
getDrawerAnimationClass,
calculateDrawerArea,
} from "../utils";
import useMove from "../composable/useMove";
import useResize from "../composable/useResize";
import { zIndexKey } from "../tokens";
const slots = useSlots();
const layero = ref<HTMLElement | null>(null);
const emit = defineEmits(["close", "update:modelValue"]);
export interface LayModalProps {
title?: string | boolean | Function;
icon?: string | number;
skin?: string;
zIndex?: number | Function;
setTop?: boolean;
offset?: string[] | string;
area?: string[] | "auto";
modelValue?: boolean;
maxmin?: boolean | string;
btn?: Record<string, unknown>[] | false;
move?: boolean | string;
resize?: boolean | string;
type?: 0 | 1 | 2 | 3 | "dialog" | "page" | "iframe" | "loading" | "drawer";
content?: string | Function | object | VNodeTypes;
isHtmlFragment?: boolean;
shade?: boolean | string;
shadeClose?: boolean | string;
shadeOpacity?: string;
closeBtn?: boolean | string;
btnAlign?: "l" | "c" | "r";
time?: number;
load?: number;
anim?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
isOutAnim?: boolean;
destroy?: Function;
success?: Function;
end?: Function;
yes?: Function;
yesText?: string;
isFunction?: boolean;
isMessage?: boolean;
appContext?: any;
}
const props = withDefaults(defineProps<LayModalProps>(), {
title: "信息",
setTop: false,
offset: () => ["50%", "50%"],
area: "auto",
modelValue: false,
maxmin: false,
move: true,
type: 1,
time: 0,
shade: true,
shadeClose: true,
shadeOpacity: "0.1",
closeBtn: true,
btnAlign: "r",
load: 0,
anim: 0,
resize: false,
isHtmlFragment: false,
isOutAnim: true,
destroy: () => {},
success: () => {},
end: () => {},
yesText: "确定",
isFunction: false,
isMessage: false,
});
const id: Ref<string> = ref(nextId());
const max: Ref<boolean> = ref(false);
const min: Ref<boolean> = ref(false);
const type: number = calculateType(props.type);
const area: Ref<string[]> = ref(
calculateArea(props.type, props.area, props.offset)
);
const offset: Ref<string[]> = ref(
calculateOffset(props.offset, area.value, props.type)
);
const contentHeight = ref(
calculateContent(area.value[1], props.btn, type, props.isMessage)
);
const index: Ref<number | Function> = ref(
props.zIndex ?? inject(zIndexKey, 99999)
);
const visible: Ref<boolean> = ref(false);
const first: Ref<boolean> = ref(true);
const w: Ref<string> = ref(area.value[0]);
const h: Ref<string> = ref(area.value[1]);
const t: Ref<string> = ref(offset.value[0]);
const l: Ref<string> = ref(offset.value[1]);
const _w: Ref<string> = ref(area.value[0]);
const _h: Ref<string> = ref(area.value[0]);
const _t: Ref<string> = ref(offset.value[0]);
const _l: Ref<string> = ref(offset.value[1]);
/**
* 首次打开
* <p>
*/
const firstOpenDelayCalculation = function () {
nextTick(() => {
area.value = getArea(layero.value);
if (props.type === "drawer") {
area.value = calculateDrawerArea(props.offset, props.area);
}
offset.value = calculateOffset(props.offset, area.value, props.type);
w.value = area.value[0];
h.value = area.value[1];
t.value = offset.value[0];
l.value = offset.value[1];
_w.value = area.value[0];
_l.value = area.value[1];
_t.value = offset.value[0];
_l.value = offset.value[1];
supportMove();
});
};
/**
* 普通打开
* <p>
*/
const notFirstOpenLayerInit = function () {
w.value = _w.value;
h.value = _h.value;
t.value = _t.value;
l.value = _l.value;
supportMove();
};
/**
* Component 模式, 关闭事件
* <p>
* 在 Component 模式下, 隐藏前需要恢复正常窗体位置与尺寸, 保存
**/
const beforeCloseSaveData = function () {
if (min.value) minHandle();
if (max.value) maxHandle();
_w.value = w.value;
_h.value = h.value;
_t.value = t.value;
_l.value = l.value;
};
/**
* 弹层最大化
* <p>
*/
const maxHandle = () => {
if (max.value) {
w.value = _w.value;
h.value = _h.value;
t.value = _t.value;
l.value = _l.value;
} else {
_t.value = t.value;
_l.value = l.value;
_w.value = w.value;
_h.value = h.value;
w.value = maxArea().w;
h.value = maxArea().h;
t.value = maxOffset().t;
l.value = maxOffset().l;
}
max.value = !max.value;
};
/**
* 弹层最小化
* <p>
*/
const minHandle = () => {
let left = 180 * updateMinArrays(id.value, !min.value);
if (left > document.documentElement.clientWidth - 180) {
left = document.documentElement.clientWidth - 180;
}
if (min.value) {
w.value = _w.value;
h.value = _h.value;
t.value = _t.value;
l.value = _l.value;
} else {
_w.value = w.value;
_h.value = h.value;
_t.value = t.value;
_l.value = l.value;
h.value = minArea().h;
w.value = minArea().w;
t.value = minOffset(left).t;
l.value = minOffset(left).l;
}
min.value = !min.value;
};
/**
* 重置弹层
* <p>
*/
const reset = function () {
if (!first.value) {
min.value = false;
max.value = false;
w.value = area.value[0];
h.value = area.value[1];
t.value = offset.value[0];
l.value = offset.value[1];
_w.value = area.value[0];
_h.value = area.value[1];
_t.value = offset.value[0];
_l.value = offset.value[1];
}
if (!props.modelValue) {
emit("update:modelValue", true);
}
};
/**
* 监听 modalValue 的值
* <p>
* 只有 Component 模式会触发
*/
watch(
() => props.modelValue,
() => {
visible.value = props.modelValue;
if (visible.value) {
if (first.value) {
first.value = false;
firstOpenDelayCalculation();
} else {
notFirstOpenLayerInit();
}
} else {
beforeCloseSaveData();
}
},
{ deep: true }
);
/**
* 监听 visible 值
* <p>
*/
watch(
() => visible.value,
() => {
if (visible.value) {
if (props.isFunction) {
firstOpenDelayCalculation();
}
props.success();
} else {
props.end();
}
}
);
/**
* 高度监听
* <p>
*
* 在发生拖拽时, 需根据弹出层的外层高度计算 content 高度, 需要
* 考虑 btn 操作栏, 计算公式contentHeight = h - btnHeight
*
* @param h 弹层高度
* @param btn 操作栏
* @param type 弹层类型
*/
watch(
() => h.value,
() => {
contentHeight.value = calculateContent(
h.value,
props.btn,
type,
props.isMessage
);
}
);
/**
* 弹层类型
*
* @param type 类型
* @param isMessage 是消息
* @param icon 图标类型
*/
const boxClasses = computed(() => {
return [
type === 0 ? "layui-layer-dialog" : "",
type === 1 ? "layui-layer-page" : "",
type === 2 ? "layui-layer-iframe" : "",
type === 3 ? "layui-layer-loading" : "",
props.isMessage ? "layui-layer-msg" : "",
props.isMessage && !props.icon ? "layui-layer-hui" : "",
props.skin,
];
});
/**
* 拖拽拉伸
* <p>
*/
const supportMove = function () {
if (props.move && props.type != "drawer") {
nextTick(() => {
// @ts-ignore 拖拽
useMove(layero.value, (left, top) => {
l.value = left;
t.value = top;
});
// @ts-ignore 拉伸
useResize(layero.value, (width, height) => {
h.value = height;
w.value = width;
});
});
}
};
/**
* 弹层样式
* <p>
*/
const styles = computed(() => {
return {
top: t.value,
left: l.value,
width: w.value,
height: h.value,
zIndex: index.value,
};
});
/**
* 弹层内容
* <p>
* @param type 类型
* @param load 加载动画
* @param icon 图标
*/
const contentClasses = computed(() => {
return [
type === 3 ? `layui-layer-loading${props.load}` : "",
props.icon ? "layui-layer-padding" : "",
];
});
/**
* 关闭操作
* <p>
* @param null
*/
const closeHandle = () => {
emit("close");
emit("update:modelValue", false);
props.destroy();
};
/**
* 确定操作
* <p>
* @param null
*/
const yesHandle = () => {
if (props.yes != undefined) props.yes();
else closeHandle();
};
/**
* 遮盖层点击
* <p>
* @param null
*/
const shadeHandle = () => {
if (props.shadeClose) closeHandle();
};
/**
* 获取内容
* <p>
* @param content 文本 / 方法
*/
const renderContent = function (content: any) {
if (content instanceof Function) {
return content();
}
return content;
};
/**
* 弹层图标
* <p>
* @param icon 图标
*/
const iconClass = computed(() => {
return ["layui-layer-ico", `layui-layer-ico${props.icon}`];
});
/**
* 入场动画
* <p>
* @param type 类型
* @param anim 入场动画
*/
const enterActiveClass = computed(() => {
if (props.type === "drawer") {
return getDrawerAnimationClass(props.offset);
}
return `layer-anim layer-anim-0${props.anim}`;
});
/**
* 离场动画
* <p>
* @param type 类型
* @param isOutAnim 离场动画
*/
const leaveActiveClass = computed(() => {
if (props.type === "drawer") {
return getDrawerAnimationClass(props.offset, true);
}
return props.isOutAnim ? `layer-anim-close` : "";
});
/**
* 打卡弹层
* <p>
*/
const open = () => {
visible.value = true;
};
/**
* 关闭弹层
* <p>
*/
const close = () => {
visible.value = false;
};
/**
* 显示遮盖
* <p>
* @param visible 弹层状态
* @param shade 开启遮盖
* @param min 最小化
*/
const shadeVisible = computed(() => {
return visible.value && props.shade && !min.value;
});
/**
* 拉伸支持
* <p>
* @param resize 拉伸
* @param max 最大化
* @param min 最小化
*/
const showResize = computed(() => {
return props.resize && !max.value && !min.value;
});
/**
* 显示标题
* <p>
* @param title 标题
* @param type 类型
*/
const showTitle = computed(() => {
return props.title && props.type != 3;
});
defineExpose({ reset, open, close });
</script>
<template>
<div>
<!-- 遮盖层 -->
<Shade
:index="index"
:visible="shadeVisible"
:opacity="shadeOpacity"
@shadeClick="shadeHandle"
></Shade>
<!-- 动画容器 -->
<transition
:enter-active-class="enterActiveClass"
:leave-active-class="leaveActiveClass"
>
<!-- 弹出层 -->
<div
ref="layero"
class="layui-layer layui-layer-border"
:class="boxClasses"
:style="styles"
v-if="visible"
>
<!-- 标题 -->
<Title v-if="showTitle" :title="title"></Title>
<!-- 内容 -->
<div
class="layui-layer-content"
:style="{ height: contentHeight }"
:class="contentClasses"
>
<template v-if="type === 0 || type === 1">
<i v-if="icon" :class="iconClass"></i>
<slot v-if="slots.default"></slot>
<template v-else>
<template v-if="isHtmlFragment">
<span v-html="renderContent(props.content)"></span>
</template>
<template v-else>{{ renderContent(props.content) }}</template>
</template>
</template>
<Iframe v-if="type === 2" :src="props.content"></Iframe>
</div>
<!-- 工具栏 -->
<span class="layui-layer-setwin" v-if="type != 3">
<a
v-if="maxmin && !max"
class="layui-layer-min"
:class="[min ? 'layui-layer-ico layui-layer-maxmin' : '']"
href="javascript:;"
@click="minHandle"
>
<cite v-if="!min"></cite>
</a>
<a
v-if="maxmin && !min"
class="layui-layer-ico layui-layer-max"
:class="[max ? 'layui-layer-maxmin' : '']"
href="javascript:;"
@click="maxHandle"
></a>
<CloseBtn v-if="closeBtn" @closeHandle="closeHandle"></CloseBtn>
</span>
<!-- 操作栏 -->
<div
v-if="((btn && btn.length > 0) || type === 0) && !isMessage"
class="layui-layer-btn"
:class="[`layui-layer-btn-${btnAlign}`]"
>
<template v-if="btn && btn.length > 0">
<template v-for="(b, index) in btn" :key="index">
<a
:class="[`layui-layer-btn${index}`]"
@click="b.callback(props.domId)"
>{{ b.text }}</a
>
</template>
</template>
<template v-else>
<template v-if="type === 0">
<a class="layui-layer-btn0" @click="yesHandle()">{{ yesText }}</a>
</template>
</template>
</div>
<!-- 辅助栏 -->
<Resize v-if="showResize"></Resize>
</div>
</transition>
</div>
</template>

View File

@@ -0,0 +1,52 @@
const useMove = function (el: HTMLElement, callback: Function) {
el.style.position = "fixed";
let offsetX: number;
let offsetY: number;
if (el != null) {
el.addEventListener("mousedown", function (event: any) {
if (event.path[0].className === "layui-layer-title") {
if (event.button == 0 && el != null) {
const lexObj: any = getComputedStyle(el);
offsetX =
event.pageX - el.offsetLeft + parseInt(lexObj["margin-left"]);
offsetY =
event.pageY - el.offsetTop + parseInt(lexObj["margin-right"]);
const move = function (event: any) {
if (el != null) {
let x = event.pageX - offsetX;
let y = event.pageY - offsetY;
if (x < 0) {
x = 0;
} else if (
x >
document.documentElement.clientWidth - el.offsetWidth
) {
x = document.documentElement.clientWidth - el.offsetWidth;
}
if (y < 0) {
y = 0;
} else if (
y >
document.documentElement.clientHeight - el.offsetHeight
) {
y = document.documentElement.clientHeight - el.offsetHeight;
}
el.style.left = `${x}px`;
el.style.top = `${y}px`;
callback(el.style.left, el.style.top);
}
return false;
};
document.addEventListener("mousemove", move);
const stop = function () {
document.removeEventListener("mousemove", move);
document.removeEventListener("mouseup", stop);
};
document.addEventListener("mouseup", stop);
}
}
return false;
});
}
};
export default useMove;

View File

@@ -0,0 +1,34 @@
const useMove = function (el: HTMLElement, callback: Function) {
if (el != null) {
el.addEventListener("mousedown", function (event: any) {
if (event.path[0].className === "layui-layer-resize") {
if (event.button == 0 && el != null) {
var x = el.offsetLeft;
var y = el.offsetTop;
const move = function (moveEvent: any) {
if (el != null) {
var offsetX = moveEvent.clientX;
var offsetY = moveEvent.clientY;
var w = offsetX - x;
var h = offsetY - y;
w < 260 && (w = 260);
h < 115 && (h = 115);
el.style.width = `${w}px`;
el.style.height = `${h}px`;
callback(el.style.width, el.style.height);
}
return false;
};
document.addEventListener("mousemove", move);
const stop = function () {
document.removeEventListener("mousemove", move);
document.removeEventListener("mouseup", stop);
};
document.addEventListener("mouseup", stop);
}
}
return false;
});
}
};
export default useMove;

215
package/layer/src/index.ts Normal file
View File

@@ -0,0 +1,215 @@
import { render, h, isVNode, getCurrentInstance, AppContext, App } from "vue";
import LayLayer from "./component/index.vue";
import { InstallOptions } from "./types";
import { zIndexKey } from "./tokens";
import { nextId } from "./utils";
// 实例队列
const layerInstance: any = [];
// 新增实例
const addInstance = (instance: any) => {
layerInstance.push(instance);
};
// 删除实例
const delInstance = (id: any) => {
layerInstance.forEach((item: any, index: number) => {
if (item.modalContainer.id === id) {
// 删除元素
layerInstance.splice(index, 1);
}
});
};
// 清空实例
const cleanInstance = () => {
layerInstance.splice(0, layerInstance.length);
};
// 是否存在
const isExist = (id: any) => {
let b = false;
layerInstance.forEach((item: any, index: number) => {
if (item.modalContainer.id === id) {
b = true;
}
});
return b;
};
// 聚合 modal 配置
const mergeOption = (option: any, defaultOption: any) => {
if (option) defaultOption = Object.assign(defaultOption, option);
return defaultOption;
};
// 创建 modal 容器
const createContainer = () => {
const modalContainer = document.createElement("div");
modalContainer.id = nextId();
document.body.appendChild(modalContainer);
return modalContainer;
};
// modal 子 VNode
const modalChildrenVNode = (content: any) => {
if (typeof content === "function") {
return isVNode(content()) ? { default: () => content() } : undefined;
}
return isVNode(content) ? { default: () => content } : undefined;
};
const layer = {
// 上下文
_context: <AppContext | null>null,
// 页面
open: (option: any, callback: Function) => {
let defaultOption = {};
return layer.create(option, defaultOption, callback);
},
// 抽屉
drawer: (option: any, callback: Function) => {
let defaultOption = {
type: "drawer",
};
return layer.create(option, defaultOption, callback);
},
// 消息
msg: (message: string, option: any, callback: Function) => {
let defaultOption = {
type: 0,
title: false,
content: message,
closeBtn: false,
shadeClose: false,
isMessage: true,
shade: false,
time: 1000,
btn: false,
};
return layer.create(option, defaultOption, callback);
},
// 加载
load: (load: number, option: any, callback: Function) => {
let defaultOption = {
type: 3,
load: load,
anim: 5,
isOutAnim: false,
shadeClose: false,
};
return layer.create(option, defaultOption, callback);
},
// 确认
confirm: (msg: string, option: any, callback: Function) => {
let defaultOption = {
type: 0,
content: msg,
shadeClose: false,
};
return layer.create(option, defaultOption, callback);
},
// 创建弹出层
create: (option: any, defaultOption: any, callback: Function) => {
// 销毁定时
let timer: NodeJS.Timeout;
// 聚合配置 Opt
const options = mergeOption(option, defaultOption);
// 创建容器 Dom
const modalContainer = createContainer();
options.id = modalContainer;
// 创建虚拟 Dom
const modalInstance = h(
LayLayer,
{
...options,
isFunction: true,
destroy() {
clearTimeout(timer);
modalInstance.component?.exposed?.close();
setTimeout(() => {
render(null, modalContainer);
// 清空 dom
if (document.body.contains(modalContainer)) {
document.body.removeChild(modalContainer);
}
}, 2000);
delInstance(modalContainer.id);
},
},
modalChildrenVNode(options.content)
);
modalInstance.appContext = options.appContext || layer._context;
// 将虚拟 dom 渲染到 dom 容器
render(modalInstance, modalContainer);
// 调用 open 函数
modalInstance.component?.exposed?.open();
// 延时 time 销毁
if (defaultOption && defaultOption.time != undefined) {
timer = setTimeout(() => {
modalInstance.component?.exposed?.close();
if (callback) callback(modalContainer.id);
setTimeout(() => {
render(null, modalContainer);
if (document.body.contains(modalContainer)) {
document.body.removeChild(modalContainer);
}
}, 2000);
// 销毁实例
delInstance(modalContainer.id);
}, defaultOption.time);
}
// 维护实例
addInstance({ modalContainer, modalInstance });
// 返回实例
return { modalContainer, modalInstance };
},
// 关闭弹出层
close: (instance: any) => {
if (instance != null && isExist(instance.modalContainer.id)) {
instance.modalInstance.component?.exposed?.close();
setTimeout(() => {
render(null, instance.modalContainer);
if (document.body.contains(instance.modalContainer))
document.body.removeChild(instance.modalContainer);
}, 2000);
}
// 销毁实例
delInstance(instance.modalContainer.id);
},
// 关闭所有弹出层
closeAll: () => {
layerInstance.forEach((item: any) => {
item.modalInstance.component?.exposed?.close();
setTimeout(() => {
render(null, item.modalContainer);
if (document.body.contains(item.modalContainer))
document.body.removeChild(item.modalContainer);
}, 2000);
});
// 清空实例
cleanInstance();
},
// 重置位置
reset: (instance: any) => {
instance.modalInstance.component?.exposed?.reset();
},
};
// 全局安装
const install = (app: App, options?: InstallOptions): void => {
layer._context = app._context;
app.component(LayLayer.name, LayLayer);
app.config.globalProperties.$layer = layer;
if (options) {
app.provide(zIndexKey, options.zIndex);
}
};
export { layer, LayLayer };
export default { install };
import "./theme/index.css";

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -0,0 +1 @@
export const zIndexKey = Symbol("zIndex");

View File

@@ -0,0 +1,3 @@
export type StringObject = Record<string, unknown>;
export interface InstallOptions extends StringObject {}

View File

@@ -0,0 +1,235 @@
// 随机数
export function nextId() {
var s: any = [];
var hexDigits = "0123456789abcdef";
for (var i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4";
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
s[8] = s[13] = s[18] = s[23] = "-";
var uuid = s.join("");
return uuid;
}
export function calculateMinArea(minArea: any) {
if (!minArea) {
return ["120px", "100px"];
}
if (typeof minArea == "string") {
return [minArea];
}
return [minArea];
}
export function calculateArea(type: any, area: any, offset: any) {
return type != "drawer"
? calculateBaseArea(area)
: calculateDrawerArea(offset, area);
}
// 计算宽高
// @param area
// @param type
// @return 正确宽高
export function calculateBaseArea(area: any) {
if (area === "auto") {
return [];
}
// @ts-ignore
if (typeof area == "string") {
return [area];
}
return [...area];
}
// 抽屉宽/高
export function calculateDrawerArea(
offset: any,
drawerArea: string[] | string = "30%"
) {
if (drawerArea instanceof Array) {
return drawerArea;
}
if (drawerArea === "auto") {
drawerArea = "30%";
}
if (offset === "l" || offset === "r") {
return [drawerArea, "100%"];
} else if (offset === "t" || offset === "b") {
return ["100%", drawerArea];
}
return [drawerArea, "100%"];
}
// 计算偏移
// @param offset
// @param domSize
// @return 正确位置
export function calculateOffset(offset: any, area: any, type: any) {
var arr = ["t", "r", "b", "l", "lt", "lb", "rt", "rb"];
var t = offset[0];
var l = offset[1];
if (offset instanceof Array && type === "drawer") {
offset = "r";
}
// @ts-ignore
if (arr.indexOf(offset) > -1) {
t = "50%";
l = "50%";
}
// 预备处理
if (arr.indexOf(offset) != -1 || t.indexOf("%") > -1)
t = "calc(" + t + " - (" + (area === "auto" ? "100px" : area[1]) + "/2 ))";
if (arr.indexOf(offset) != -1 || l.indexOf("%") > -1)
l = "calc(" + l + " - (" + (area === "auto" ? "100px" : area[0]) + "/2 ))";
// 关键字处理
if (offset === "t") t = "0px";
else if (offset === "r") l = "calc(100% - " + area[0] + ")";
else if (offset === "b") t = "calc(100% - " + area[1] + ")";
else if (offset === "l") l = "0px";
else if (offset === "lt") {
t = "0px";
l = "0px";
} else if (offset === "lb") {
t = "calc(100% - " + area[1] + ")";
l = "0px";
} else if (offset === "rt") {
t = "0px";
l = "calc(100% - " + area[0] + ")";
} else if (offset === "rb") {
t = "calc(100% - " + area[1] + ")";
l = "calc(100% - " + area[0] + ")";
}
// 返回位置
return [t, l];
}
// 窗体类型
export function calculateType(modalType: number | string) {
if (modalType === "dialog" || modalType === 0 || modalType === "0") {
return 0;
} else if (
modalType === "page" ||
modalType === "drawer" ||
modalType === 1 ||
modalType === "1"
) {
return 1;
} else if (modalType === "iframe" || modalType === 2 || modalType === "2") {
return 2;
} else if (modalType === "loading" || modalType === 3 || modalType === "3") {
return 3;
}
return 0;
}
// 计算高度
// @param height 高度
// @param btn 操作集合
export function calculateContent(
height: any,
btn: any,
type: any,
isMessage?: boolean
) {
if (height && height.indexOf("%") != -1) {
height = "100%";
}
if (btn && btn.length > 0) {
if (type === 0) {
return "calc(" + height + " - 137px)";
}
if (type === 1) {
return "calc(" + height + " - 102px)";
}
if (type === 2) {
return "calc(" + height + " - 102px)";
}
} else {
if (type === 0) {
return isMessage ? height : "calc(" + height + " - 137px)";
}
if (type === 1) {
return "calc(" + height + " - 51px)";
}
if (type === 2) {
return "calc(" + height + " - 51px)";
}
}
}
// 尺寸常量
export function maxArea() {
return { w: "100%", h: "100%" };
}
// 初始位置
export function maxOffset() {
return { t: "0px", l: "0px" };
}
// 最小化尺寸
export function minArea() {
return { w: "180px", h: "51px" };
}
// 最小化位置
export function minOffset(left: any) {
return { t: "calc(100% - 51px)", l: left + "px" };
}
// 元素位置
// @param x 横坐标
// @param y 纵坐标
export function getPosition(dom: any) {
return { x: dom?.style.left, y: dom?.style.top };
}
// 元素宽高
export function getArea(dom: any) {
// @ts-ignore
let width = getComputedStyle(dom, null).width;
// @ts-ignore
let height = getComputedStyle(dom, null).height;
return [width, height];
}
// 最小化的队列
let minArrays: Array<String> = [];
// 更新最小化队列
export function updateMinArrays(id: string, state: Boolean) {
var i = 0;
if (state) {
const index = minArrays.findIndex((v) => v === undefined);
if (index === -1) {
minArrays.push(id);
i = minArrays.length - 1;
} else {
minArrays[index] = id;
i = index;
}
} else {
delete minArrays[minArrays.findIndex((v) => v == id)];
i = -1;
}
return i;
}
// 抽屉动画类
export function getDrawerAnimationClass(offset: any, isClose: boolean = false) {
const prefix = "layer-drawer-anim layer-anim";
let suffix = "rl";
if (offset === "l") {
suffix = "lr";
} else if (offset === "r") {
suffix = "rl";
} else if (offset === "t") {
suffix = "tb";
} else if (offset === "b") {
suffix = "bt";
}
return isClose ? `${prefix}-${suffix}-close` : `${prefix}-${suffix}`;
}