feat: 新增可拖拽modal框
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ems_frontend_vue3",
|
"name": "ems_frontend_vue3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "核心网管理系统",
|
"description": "核心网管理平台",
|
||||||
"author": "TsMask",
|
"author": "TsMask",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0"
|
"node": ">=18.0.0"
|
||||||
@@ -17,6 +17,8 @@
|
|||||||
"@codemirror/lang-javascript": "^6.2.1",
|
"@codemirror/lang-javascript": "^6.2.1",
|
||||||
"@codemirror/merge": "^6.1.2",
|
"@codemirror/merge": "^6.1.2",
|
||||||
"@codemirror/theme-one-dark": "^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",
|
"ant-design-vue": "^3.2.20",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
|
|||||||
125
src/components/DraggableModal/index.vue
Normal file
125
src/components/DraggableModal/index.vue
Normal 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>
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { toggle, isFullscreen } from '@/utils/fullscreen-utils';
|
import { useFullscreen } from '@vueuse/core';
|
||||||
import useI18n from '@/hooks/useI18n';
|
import useI18n from '@/hooks/useI18n';
|
||||||
import useAppStore from '@/store/modules/app';
|
import useAppStore from '@/store/modules/app';
|
||||||
import useUserStore from '@/store/modules/user';
|
import useUserStore from '@/store/modules/user';
|
||||||
import useAlarmStore from '@/store/modules/alarm';
|
import useAlarmStore from '@/store/modules/alarm';
|
||||||
|
const { isFullscreen, toggle } = useFullscreen();
|
||||||
const { t, changeLocale, optionsLocale } = useI18n();
|
const { t, changeLocale, optionsLocale } = useI18n();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
@@ -64,7 +65,7 @@ function fnChangeLocale(e: any) {
|
|||||||
<template #title>{{ t('loayouts.rightContent.fullscreen') }}</template>
|
<template #title>{{ t('loayouts.rightContent.fullscreen') }}</template>
|
||||||
<a-button type="text" @click="toggle">
|
<a-button type="text" @click="toggle">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<FullscreenExitOutlined v-if="isFullscreen()" />
|
<FullscreenExitOutlined v-if="isFullscreen" />
|
||||||
<FullscreenOutlined v-else />
|
<FullscreenOutlined v-else />
|
||||||
</template>
|
</template>
|
||||||
</a-button>
|
</a-button>
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
|
||||||
@@ -869,7 +869,7 @@ onMounted(() => {
|
|||||||
</a-card>
|
</a-card>
|
||||||
|
|
||||||
<!-- 新增框或修改框 -->
|
<!-- 新增框或修改框 -->
|
||||||
<a-modal
|
<DraggableModal
|
||||||
width="800px"
|
width="800px"
|
||||||
:keyboard="false"
|
:keyboard="false"
|
||||||
:mask-closable="false"
|
:mask-closable="false"
|
||||||
@@ -1013,10 +1013,10 @@ onMounted(() => {
|
|||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</DraggableModal>
|
||||||
|
|
||||||
<!-- 批量新增框 -->
|
<!-- 批量新增框 -->
|
||||||
<a-modal
|
<DraggableModal
|
||||||
width="800px"
|
width="800px"
|
||||||
:keyboard="false"
|
:keyboard="false"
|
||||||
:mask-closable="false"
|
:mask-closable="false"
|
||||||
@@ -1178,10 +1178,10 @@ onMounted(() => {
|
|||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</DraggableModal>
|
||||||
|
|
||||||
<!-- 批量删除框 -->
|
<!-- 批量删除框 -->
|
||||||
<a-modal
|
<DraggableModal
|
||||||
width="500px"
|
width="500px"
|
||||||
:keyboard="false"
|
:keyboard="false"
|
||||||
:mask-closable="false"
|
:mask-closable="false"
|
||||||
@@ -1191,7 +1191,12 @@ onMounted(() => {
|
|||||||
@ok="fnBatchDelModalOk"
|
@ok="fnBatchDelModalOk"
|
||||||
@cancel="fnBatchDelModalCancel"
|
@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-row :gutter="16">
|
||||||
<a-col :lg="24" :md="24" :xs="24">
|
<a-col :lg="24" :md="24" :xs="24">
|
||||||
<a-form-item
|
<a-form-item
|
||||||
@@ -1231,7 +1236,7 @@ onMounted(() => {
|
|||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</DraggableModal>
|
||||||
|
|
||||||
<!-- 上传导入表格数据文件框 -->
|
<!-- 上传导入表格数据文件框 -->
|
||||||
<UploadModal
|
<UploadModal
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ let tableColumns: ColumnsType = [
|
|||||||
title: 'Subscribed Data',
|
title: 'Subscribed Data',
|
||||||
dataIndex: 'smData',
|
dataIndex: 'smData',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 10,
|
width: 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'EPS Flag',
|
title: 'EPS Flag',
|
||||||
@@ -1104,7 +1104,7 @@ onMounted(() => {
|
|||||||
</a-card>
|
</a-card>
|
||||||
|
|
||||||
<!-- 新增框或修改框 -->
|
<!-- 新增框或修改框 -->
|
||||||
<a-modal
|
<DraggableModal
|
||||||
width="800px"
|
width="800px"
|
||||||
:body-style="{ height: '650px', 'overflow-y': 'scroll' }"
|
:body-style="{ height: '650px', 'overflow-y': 'scroll' }"
|
||||||
:keyboard="false"
|
:keyboard="false"
|
||||||
@@ -1118,7 +1118,7 @@ onMounted(() => {
|
|||||||
<a-form
|
<a-form
|
||||||
name="modalStateFrom"
|
name="modalStateFrom"
|
||||||
layout="horizontal"
|
layout="horizontal"
|
||||||
:label-col="{ span: 7.5 }"
|
:label-col="{ span: 6 }"
|
||||||
:labelWrap="true"
|
:labelWrap="true"
|
||||||
>
|
>
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
@@ -1532,10 +1532,10 @@ onMounted(() => {
|
|||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</DraggableModal>
|
||||||
|
|
||||||
<!-- 批量增加框 -->
|
<!-- 批量增加框 -->
|
||||||
<a-modal
|
<DraggableModal
|
||||||
width="800px"
|
width="800px"
|
||||||
:body-style="{ height: '650px', 'overflow-y': 'scroll' }"
|
:body-style="{ height: '650px', 'overflow-y': 'scroll' }"
|
||||||
:keyboard="false"
|
:keyboard="false"
|
||||||
@@ -1549,7 +1549,7 @@ onMounted(() => {
|
|||||||
<a-form
|
<a-form
|
||||||
name="modalStateBatchFrom"
|
name="modalStateBatchFrom"
|
||||||
layout="horizontal"
|
layout="horizontal"
|
||||||
:label-col="{ span: 7.5 }"
|
:label-col="{ span: 6 }"
|
||||||
:labelWrap="true"
|
:labelWrap="true"
|
||||||
>
|
>
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
@@ -1963,10 +1963,10 @@ onMounted(() => {
|
|||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</DraggableModal>
|
||||||
|
|
||||||
<!-- 批量删除框 -->
|
<!-- 批量删除框 -->
|
||||||
<a-modal
|
<DraggableModal
|
||||||
width="500px"
|
width="500px"
|
||||||
:keyboard="false"
|
:keyboard="false"
|
||||||
:mask-closable="false"
|
:mask-closable="false"
|
||||||
@@ -1979,7 +1979,7 @@ onMounted(() => {
|
|||||||
<a-form
|
<a-form
|
||||||
name="modalStateBatchDelFrom"
|
name="modalStateBatchDelFrom"
|
||||||
layout="horizontal"
|
layout="horizontal"
|
||||||
:label-col="{ span: 7.5 }"
|
:label-col="{ span: 6 }"
|
||||||
:labelWrap="true"
|
:labelWrap="true"
|
||||||
>
|
>
|
||||||
<a-row :gutter="16">
|
<a-row :gutter="16">
|
||||||
@@ -2021,7 +2021,7 @@ onMounted(() => {
|
|||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</DraggableModal>
|
||||||
|
|
||||||
<!-- 上传导入表格数据文件框 -->
|
<!-- 上传导入表格数据文件框 -->
|
||||||
<UploadModal
|
<UploadModal
|
||||||
|
|||||||
Reference in New Issue
Block a user