index.vue 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <template>
  2. <n-modal
  3. v-model:show="show"
  4. class="modal-box"
  5. :style="{ width: modalOptions.width, ...modalOptions.modalStyle }"
  6. :preset="undefined"
  7. size="huge"
  8. :bordered="false"
  9. @after-leave="onAfterLeave"
  10. >
  11. <n-card :style="modalOptions.contentStyle" :closable="modalOptions.closable" @close="close()">
  12. <template #header>
  13. <header class="modal-header">
  14. {{ modalOptions.title }}
  15. </header>
  16. </template>
  17. <slot />
  18. <!-- 底部按钮 -->
  19. <template #footer>
  20. <slot name="footer">
  21. <footer v-if="modalOptions.showFooter" class="flex justify-end">
  22. <n-button v-if="modalOptions.showCancel" @click="handleCancel()">
  23. {{ modalOptions.cancelText }}
  24. </n-button>
  25. <n-button
  26. v-if="modalOptions.showOk"
  27. type="primary"
  28. :loading="modalOptions.okLoading"
  29. class="ml-20"
  30. @click="handleOk()"
  31. >
  32. {{ modalOptions.okText }}
  33. </n-button>
  34. </footer>
  35. </slot>
  36. </template>
  37. </n-card>
  38. </n-modal>
  39. </template>
  40. <script setup>
  41. import { initDrag } from './utils'
  42. const props = defineProps({
  43. width: {
  44. type: String,
  45. default: '800px',
  46. },
  47. title: {
  48. type: String,
  49. default: '',
  50. },
  51. closable: {
  52. type: Boolean,
  53. default: true,
  54. },
  55. cancelText: {
  56. type: String,
  57. default: '取消',
  58. },
  59. okText: {
  60. type: String,
  61. default: '确定',
  62. },
  63. showFooter: {
  64. type: Boolean,
  65. default: true,
  66. },
  67. showCancel: {
  68. type: Boolean,
  69. default: true,
  70. },
  71. showOk: {
  72. type: Boolean,
  73. default: true,
  74. },
  75. modalStyle: {
  76. type: Object,
  77. default: () => {},
  78. },
  79. contentStyle: {
  80. type: Object,
  81. default: () => {},
  82. },
  83. onOk: {
  84. type: Function,
  85. default: () => {},
  86. },
  87. onCancel: {
  88. type: Function,
  89. default: () => {},
  90. },
  91. })
  92. // 声明一个show变量,用于控制模态框的显示与隐藏
  93. const show = ref(false)
  94. // 声明一个modalOptions变量,用于存储模态框的配置信息
  95. const modalOptions = ref({})
  96. const okLoading = computed({
  97. get() {
  98. return !!modalOptions.value?.okLoading
  99. },
  100. set(v) {
  101. if (modalOptions.value) {
  102. modalOptions.value.okLoading = v
  103. }
  104. },
  105. })
  106. // 打开模态框
  107. async function open(options = {}) {
  108. // 将props和options合并赋值给modalOptions
  109. modalOptions.value = { ...props, ...options }
  110. // 将show的值设置为true
  111. show.value = true
  112. await nextTick()
  113. initDrag(
  114. Array.prototype.at.call(document.querySelectorAll('.modal-header'), -1),
  115. Array.prototype.at.call(document.querySelectorAll('.modal-box'), -1),
  116. )
  117. }
  118. // 定义一个close函数,用于关闭模态框
  119. function close() {
  120. show.value = false
  121. }
  122. // 定义一个handleOk函数,用于处理模态框确定操作
  123. async function handleOk(data) {
  124. // 如果modalOptions中没有onOk函数,则直接关闭模态框
  125. if (typeof modalOptions.value.onOk !== 'function') {
  126. return close()
  127. }
  128. try {
  129. // 调用onOk函数,传入data参数
  130. const res = await modalOptions.value.onOk(data)
  131. // 如果onOk函数的返回值不为false,则关闭模态框
  132. if (res !== false)
  133. close()
  134. }
  135. catch (error) {
  136. console.error(error)
  137. okLoading.value = false
  138. }
  139. }
  140. // 定义一个handleCancel函数,用于处理模态框取消操作
  141. async function handleCancel(data) {
  142. // 如果modalOptions中没有onCancel函数,则直接关闭模态框
  143. if (typeof modalOptions.value.onCancel !== 'function') {
  144. return close()
  145. }
  146. try {
  147. // 调用onCancel函数,传入data参数
  148. const res = await modalOptions.value.onCancel(data)
  149. // 如果onCancel函数的返回值不为false,则关闭模态框
  150. if (res !== false)
  151. close()
  152. }
  153. catch (error) {
  154. console.error(error)
  155. okLoading.value = false
  156. }
  157. }
  158. async function onAfterLeave() {
  159. await nextTick()
  160. initDrag(
  161. Array.prototype.at.call(document.querySelectorAll('.modal-header'), -1),
  162. Array.prototype.at.call(document.querySelectorAll('.modal-box'), -1),
  163. )
  164. }
  165. // 定义一个defineExpose函数,用于暴露open、close、handleOk、handleCancel函数
  166. defineExpose({
  167. open,
  168. close,
  169. handleOk,
  170. handleCancel,
  171. okLoading,
  172. options: modalOptions,
  173. })
  174. </script>