123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- <template>
- <Modal
- v-model:open="show"
- :width="width"
- :wrap-style="{ overflow: 'hidden' }"
- :destroyOnClose="true"
- :maskClosable="false"
- >
- <template #title>
- <div ref="modalTitleRef" style="width: 100%; cursor: move">{{ title }}</div>
- </template>
- <template #modalRender="{ originVNode }">
- <div :style="transformStyle">
- <component :is="originVNode" />
- </div>
- </template>
- <Editor v-model:code="code" v-bind="$attrs" :language="language"/>
- <template #footer>
- <slot name="footer">
- <Button @click="close">取消</Button>
- <Button type="primary" @click="handleOk">确定</Button>
- </slot>
- </template>
- </Modal>
- </template>
- <script lang="ts">
- import { Modal, Button } from "ant-design-vue";
- import { ref, defineComponent, watch, watchEffect, computed, CSSProperties } from "vue";
- import Editor, { Language } from "./Editor.vue";
- import { useDraggable } from '@vueuse/core';
- export default defineComponent({
- name: "DEditorModal",
- components: {
- Modal,
- Editor,
- Button
- },
- props: {
- title: {
- type: String,
- default: "编辑",
- },
- width: {
- type: Number,
- default: 800,
- },
- },
- emits: ["ok"],
- setup(_, { emit }) {
- const show = ref(false);
- const code = ref("");
- const language = ref<Language>();
- const modalTitleRef = ref<HTMLElement>();
- 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 titleRect = modalTitleRef.value?.getBoundingClientRect() || { width: 0, height: 0 };
- dragRect.value.right = bodyRect.width - titleRect.width;
- dragRect.value.bottom = bodyRect.height - titleRect.height;
- preTransformX.value = transformX.value;
- preTransformY.value = transformY.value;
- }
- startedDrag.value = true;
- });
- watch(isDragging, () => {
- if (!isDragging) {
- startedDrag.value = false;
- }
- });
- watchEffect(() => {
- if (startedDrag.value) {
- transformX.value =
- preTransformX.value +
- Math.min(Math.max(dragRect.value.left, x.value), dragRect.value.right) -
- startX.value;
- transformY.value =
- preTransformY.value +
- Math.min(Math.max(dragRect.value.top, y.value), dragRect.value.bottom) -
- startY.value;
- }
- });
- const transformStyle = computed<CSSProperties>(() => {
- return {
- transform: `translate(${transformX.value}px, ${transformY.value}px)`,
- };
- });
- const handleOk = () => {
- // TODO: 检验code
- emit("ok", code.value);
- show.value = false;
- };
- const open = (codeStr: string, lang: Language = 'javascript') => {
- show.value = true;
- code.value = codeStr;
- language.value = lang;
- };
- const close = () => {
- show.value = false;
- };
- return {
- open,
- close,
- code,
- handleOk,
- show,
- language,
- modalTitleRef,
- transformStyle
- };
- },
- });
- </script>
- <style scoped></style>
|