feat: 新增可拖拽modal框

This commit is contained in:
TsMask
2023-11-24 17:06:18 +08:00
parent 018196eb88
commit f3fc415338
6 changed files with 153 additions and 45 deletions

View File

@@ -1,7 +1,7 @@
{
"name": "ems_frontend_vue3",
"type": "module",
"description": "核心网管理系统",
"description": "核心网管理平台",
"author": "TsMask",
"engines": {
"node": ">=18.0.0"
@@ -17,6 +17,8 @@
"@codemirror/lang-javascript": "^6.2.1",
"@codemirror/merge": "^6.1.2",
"@codemirror/theme-one-dark": "^6.1.2",
"@vueuse/components": "^10.6.1",
"@vueuse/core": "^10.6.1",
"ant-design-vue": "^3.2.20",
"codemirror": "^6.0.1",
"dayjs": "^1.11.10",

View File

@@ -0,0 +1,125 @@
<script setup lang="ts">
import { ref, watch, watchEffect, CSSProperties, computed } from 'vue';
import { useDraggable } from '@vueuse/core';
const emit = defineEmits(['update:visible', 'ok', 'cancel']);
const props = defineProps({
/**是否弹出显示,必传 */
visible: {
type: Boolean,
required: true,
},
/**窗口标题 */
title: {
type: String,
default: '',
},
/**窗口宽度 */
width: {
type: [String, Number],
default: '520px',
},
/**确认按钮加载 */
confirmLoading: {
type: Boolean,
default: false,
},
});
// 对标题进行监听
const modalTitleRef = ref<HTMLElement | null>(null);
const { x, y, isDragging } = useDraggable(modalTitleRef);
const startX = ref<number>(0);
const startY = ref<number>(0);
const startedDrag = ref(false);
const transformX = ref(0);
const transformY = ref(0);
const preTransformX = ref(0);
const preTransformY = ref(0);
const dragRect = ref({ left: 0, right: 0, top: 0, bottom: 0 });
watch([x, y], () => {
if (!startedDrag.value) {
startX.value = x.value;
startY.value = y.value;
const bodyRect = document.body.getBoundingClientRect();
const titleRectEl = modalTitleRef.value;
if (titleRectEl) {
const titleRect = titleRectEl.getBoundingClientRect();
dragRect.value.right = bodyRect.width - (titleRect.width + 24);
dragRect.value.bottom = bodyRect.height - (titleRect.height + 16);
}
preTransformX.value = transformX.value;
preTransformY.value = transformY.value;
}
startedDrag.value = true;
});
watchEffect(() => {
if (!isDragging.value) {
startedDrag.value = false;
}
if (startedDrag.value) {
const dragRectX = Math.min(
Math.max(dragRect.value.left + 24, x.value),
dragRect.value.right
);
transformX.value = preTransformX.value + dragRectX - startX.value;
const dragRectY = Math.min(
Math.max(dragRect.value.top + 16, y.value),
dragRect.value.bottom
);
transformY.value = preTransformY.value + dragRectY - startY.value;
}
});
// 位移
const transformStyle = computed<CSSProperties>(() => {
return {
transform: `translate(${transformX.value}px, ${transformY.value}px)`,
};
});
/**监听是否显示,位置还原 */
watch(
() => props.visible,
val => {
if (val) {
transformX.value = 0;
transformY.value = 0;
}
}
);
</script>
<template>
<a-modal
:width="props.width"
:keyboard="false"
:mask-closable="false"
:visible="props.visible"
:confirm-loading="props.confirmLoading"
@ok="e => emit('ok', e)"
@cancel="e => emit('cancel', e)"
>
<template #title>
<div ref="modalTitleRef" class="draggable-title">
Draggable Modal {{ title }}
</div>
</template>
<template #modalRender="{ originVNode }">
<div :style="transformStyle">
<component :is="originVNode" />
</div>
</template>
<slot></slot>
</a-modal>
</template>
<style lang="less" scoped>
.draggable-title {
width: 100%;
cursor: move;
}
</style>

View File

@@ -1,11 +1,12 @@
<script setup lang="ts">
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { useRouter } from 'vue-router';
import { toggle, isFullscreen } from '@/utils/fullscreen-utils';
import { useFullscreen } from '@vueuse/core';
import useI18n from '@/hooks/useI18n';
import useAppStore from '@/store/modules/app';
import useUserStore from '@/store/modules/user';
import useAlarmStore from '@/store/modules/alarm';
const { isFullscreen, toggle } = useFullscreen();
const { t, changeLocale, optionsLocale } = useI18n();
const userStore = useUserStore();
const appStore = useAppStore();
@@ -64,7 +65,7 @@ function fnChangeLocale(e: any) {
<template #title>{{ t('loayouts.rightContent.fullscreen') }}</template>
<a-button type="text" @click="toggle">
<template #icon>
<FullscreenExitOutlined v-if="isFullscreen()" />
<FullscreenExitOutlined v-if="isFullscreen" />
<FullscreenOutlined v-else />
</template>
</a-button>

View File

@@ -1,25 +0,0 @@
/**进入全屏 */
function enterFullscreen() {
const element = document.documentElement;
if (element.requestFullscreen) {
element.requestFullscreen();
}
}
/**退出全屏 */
function exitFullscreen() {
if (document.exitFullscreen) {
document.exitFullscreen();
}
}
/**是否全屏 */
export function isFullscreen() {
return !!document.fullscreenElement;
}
/**变更 */
export function toggle() {
return isFullscreen() ? exitFullscreen() : enterFullscreen();
}

View File

@@ -869,7 +869,7 @@ onMounted(() => {
</a-card>
<!-- 新增框或修改框 -->
<a-modal
<DraggableModal
width="800px"
:keyboard="false"
:mask-closable="false"
@@ -1013,10 +1013,10 @@ onMounted(() => {
</a-col>
</a-row>
</a-form>
</a-modal>
</DraggableModal>
<!-- 批量新增框 -->
<a-modal
<DraggableModal
width="800px"
:keyboard="false"
:mask-closable="false"
@@ -1178,10 +1178,10 @@ onMounted(() => {
</a-col>
</a-row>
</a-form>
</a-modal>
</DraggableModal>
<!-- 批量删除框 -->
<a-modal
<DraggableModal
width="500px"
:keyboard="false"
:mask-closable="false"
@@ -1191,7 +1191,12 @@ onMounted(() => {
@ok="fnBatchDelModalOk"
@cancel="fnBatchDelModalCancel"
>
<a-form name="modalStateBatchDelFrom" layout="horizontal">
<a-form
name="modalStateBatchDelFrom"
layout="horizontal"
:label-col="{ span: 6 }"
:labelWrap="true"
>
<a-row :gutter="16">
<a-col :lg="24" :md="24" :xs="24">
<a-form-item
@@ -1231,7 +1236,7 @@ onMounted(() => {
</a-col>
</a-row>
</a-form>
</a-modal>
</DraggableModal>
<!-- 上传导入表格数据文件框 -->
<UploadModal

View File

@@ -138,7 +138,7 @@ let tableColumns: ColumnsType = [
title: 'Subscribed Data',
dataIndex: 'smData',
align: 'center',
width: 10,
width: 5,
},
{
title: 'EPS Flag',
@@ -1104,7 +1104,7 @@ onMounted(() => {
</a-card>
<!-- 新增框或修改框 -->
<a-modal
<DraggableModal
width="800px"
:body-style="{ height: '650px', 'overflow-y': 'scroll' }"
:keyboard="false"
@@ -1118,7 +1118,7 @@ onMounted(() => {
<a-form
name="modalStateFrom"
layout="horizontal"
:label-col="{ span: 7.5 }"
:label-col="{ span: 6 }"
:labelWrap="true"
>
<a-row :gutter="16">
@@ -1532,10 +1532,10 @@ onMounted(() => {
</a-tooltip>
</a-form-item>
</a-form>
</a-modal>
</DraggableModal>
<!-- 批量增加框 -->
<a-modal
<DraggableModal
width="800px"
:body-style="{ height: '650px', 'overflow-y': 'scroll' }"
:keyboard="false"
@@ -1549,7 +1549,7 @@ onMounted(() => {
<a-form
name="modalStateBatchFrom"
layout="horizontal"
:label-col="{ span: 7.5 }"
:label-col="{ span: 6 }"
:labelWrap="true"
>
<a-row :gutter="16">
@@ -1963,10 +1963,10 @@ onMounted(() => {
</a-tooltip>
</a-form-item>
</a-form>
</a-modal>
</DraggableModal>
<!-- 批量删除框 -->
<a-modal
<DraggableModal
width="500px"
:keyboard="false"
:mask-closable="false"
@@ -1979,7 +1979,7 @@ onMounted(() => {
<a-form
name="modalStateBatchDelFrom"
layout="horizontal"
:label-col="{ span: 7.5 }"
:label-col="{ span: 6 }"
:labelWrap="true"
>
<a-row :gutter="16">
@@ -2021,7 +2021,7 @@ onMounted(() => {
</a-col>
</a-row>
</a-form>
</a-modal>
</DraggableModal>
<!-- 上传导入表格数据文件框 -->
<UploadModal