feat: 新增可拖拽modal框
This commit is contained in:
@@ -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",
|
||||
|
||||
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">
|
||||
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>
|
||||
|
||||
@@ -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-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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user