index.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. <template>
  2. <a-modal
  3. ref="modalRef"
  4. :wrap-style="{ overflow: 'hidden' }"
  5. @ok="handleOk"
  6. @cancel="close"
  7. :closable="false"
  8. v-bind="{
  9. cancelText: '取消',
  10. okText: '确定',
  11. ...props
  12. }"
  13. :confirmLoading="state.confirmLoading"
  14. >
  15. <template #title>
  16. <div ref="modalTitleRef" style="width: 100%; cursor: move">{{props.label || 'model'}}</div>
  17. </template>
  18. <template #modalRender="{ originVNode }">
  19. <div :style="transformStyle">
  20. <component :is="originVNode" />
  21. </div>
  22. </template>
  23. <slot></slot>
  24. </a-modal>
  25. </template>
  26. <script lang="ts" setup >
  27. import { useDraggable } from '@vueuse/core'
  28. import { ModalProps } from 'ant-design-vue'
  29. import { ref, watch, watchEffect, computed, CSSProperties, reactive, onMounted } from 'vue'
  30. export interface ModalProPorps extends ModalProps {
  31. label: string,
  32. openConfirmLoading?: boolean,
  33. cancel?: () => void
  34. }
  35. export interface ModalOkProps {
  36. confirmed: () => void
  37. confirmStart: () => void
  38. }
  39. const emit = defineEmits<{
  40. (e: 'close'): void
  41. (e: 'ok', { confirmStart, confirmed }: ModalOkProps): void
  42. }>()
  43. const props = defineProps<ModalProPorps>()
  44. interface StateProps {
  45. confirmLoading: boolean
  46. }
  47. const state = reactive<Partial<StateProps>>({})
  48. const close = () => emit('close')
  49. const handleOk = async () => {
  50. console.log('modal-pro:-----ok')
  51. emit('ok', {
  52. confirmStart: () => state.confirmLoading = true,
  53. confirmed: () => state.confirmLoading = false
  54. })
  55. }
  56. // 拖拽相关的代码
  57. const modalTitleRef = ref()
  58. const { x, y, isDragging } = useDraggable(modalTitleRef)
  59. const startX = ref<number>(0)
  60. const startY = ref<number>(0)
  61. const startedDrag = ref(false)
  62. const transformX = ref(0)
  63. const transformY = ref(0)
  64. const preTransformX = ref(0)
  65. const preTransformY = ref(0)
  66. const dragRect = ref({ left: 0, right: 0, top: 0, bottom: 0 })
  67. watch([x, y], () => {
  68. if (!startedDrag.value) {
  69. startX.value = x.value
  70. startY.value = y.value
  71. const bodyRect = document.body.getBoundingClientRect()
  72. const titleRect = modalTitleRef.value.getBoundingClientRect()
  73. dragRect.value.right = bodyRect.width - titleRect.width
  74. dragRect.value.bottom = bodyRect.height - titleRect.height
  75. preTransformX.value = transformX.value
  76. preTransformY.value = transformY.value
  77. }
  78. startedDrag.value = true
  79. })
  80. watch(isDragging, () => {
  81. if (!isDragging) {
  82. startedDrag.value = false
  83. }
  84. })
  85. watchEffect(() => {
  86. if (startedDrag.value) {
  87. transformX.value =
  88. preTransformX.value +
  89. Math.min(Math.max(dragRect.value.left, x.value), dragRect.value.right) -
  90. startX.value
  91. transformY.value =
  92. preTransformY.value +
  93. Math.min(Math.max(dragRect.value.top, y.value), dragRect.value.bottom) -
  94. startY.value
  95. }
  96. })
  97. const transformStyle = computed<CSSProperties>(() => {
  98. return {
  99. transform: `translate(${transformX.value}px, ${transformY.value}px)`
  100. }
  101. })
  102. // 拖拽相关的代码
  103. </script>
  104. <style>
  105. </style>