You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

168 lines
4.5 KiB

  1. <script setup lang="ts">
  2. import {
  3. closeDialog,
  4. dialogStore,
  5. type EventType,
  6. type ButtonProps,
  7. type DialogOptions
  8. } from "./index";
  9. import { ref, computed } from "vue";
  10. import { isFunction } from "@pureadmin/utils";
  11. import Fullscreen from "@iconify-icons/ri/fullscreen-fill";
  12. import ExitFullscreen from "@iconify-icons/ri/fullscreen-exit-fill";
  13. const fullscreen = ref(false);
  14. const footerButtons = computed(() => {
  15. return (options: DialogOptions) => {
  16. return options?.footerButtons?.length > 0
  17. ? options.footerButtons
  18. : ([
  19. {
  20. label: "取消",
  21. text: true,
  22. bg: true,
  23. btnClick: ({ dialog: { options, index } }) => {
  24. const done = () =>
  25. closeDialog(options, index, { command: "cancel" });
  26. if (options?.beforeCancel && isFunction(options?.beforeCancel)) {
  27. options.beforeCancel(done, { options, index });
  28. } else {
  29. done();
  30. }
  31. }
  32. },
  33. {
  34. label: "确定",
  35. type: "primary",
  36. text: true,
  37. bg: true,
  38. btnClick: ({ dialog: { options, index } }) => {
  39. const done = () =>
  40. closeDialog(options, index, { command: "sure" });
  41. if (options?.beforeSure && isFunction(options?.beforeSure)) {
  42. options.beforeSure(done, { options, index });
  43. } else {
  44. done();
  45. }
  46. }
  47. }
  48. ] as Array<ButtonProps>);
  49. };
  50. });
  51. const fullscreenClass = computed(() => {
  52. return [
  53. "el-icon",
  54. "el-dialog__close",
  55. "-translate-x-2",
  56. "cursor-pointer",
  57. "hover:!text-[red]"
  58. ];
  59. });
  60. function eventsCallBack(
  61. event: EventType,
  62. options: DialogOptions,
  63. index: number,
  64. isClickFullScreen = false
  65. ) {
  66. if (!isClickFullScreen) fullscreen.value = options?.fullscreen ?? false;
  67. if (options?.[event] && isFunction(options?.[event])) {
  68. return options?.[event]({ options, index });
  69. }
  70. }
  71. function handleClose(
  72. options: DialogOptions,
  73. index: number,
  74. args = { command: "close" }
  75. ) {
  76. closeDialog(options, index, args);
  77. eventsCallBack("close", options, index);
  78. }
  79. </script>
  80. <template>
  81. <el-dialog
  82. v-for="(options, index) in dialogStore"
  83. :key="index"
  84. v-bind="options"
  85. v-model="options.visible"
  86. class="pure-dialog"
  87. :fullscreen="fullscreen ? true : options?.fullscreen ? true : false"
  88. @closed="handleClose(options, index)"
  89. @opened="eventsCallBack('open', options, index)"
  90. @openAutoFocus="eventsCallBack('openAutoFocus', options, index)"
  91. @closeAutoFocus="eventsCallBack('closeAutoFocus', options, index)"
  92. >
  93. <!-- header -->
  94. <template
  95. v-if="options?.fullscreenIcon || options?.headerRenderer"
  96. #header="{ close, titleId, titleClass }"
  97. >
  98. <div
  99. v-if="options?.fullscreenIcon"
  100. class="flex items-center justify-between"
  101. >
  102. <span :id="titleId" :class="titleClass">{{ options?.title }}</span>
  103. <i
  104. v-if="!options?.fullscreen"
  105. :class="fullscreenClass"
  106. @click="
  107. () => {
  108. fullscreen = !fullscreen;
  109. eventsCallBack(
  110. 'fullscreenCallBack',
  111. { ...options, fullscreen },
  112. index,
  113. true
  114. );
  115. }
  116. "
  117. >
  118. <IconifyIconOffline
  119. class="pure-dialog-svg"
  120. :icon="
  121. options?.fullscreen
  122. ? ExitFullscreen
  123. : fullscreen
  124. ? ExitFullscreen
  125. : Fullscreen
  126. "
  127. />
  128. </i>
  129. </div>
  130. <component
  131. :is="options?.headerRenderer({ close, titleId, titleClass })"
  132. v-else
  133. />
  134. </template>
  135. <component
  136. v-bind="options?.props"
  137. :is="options.contentRenderer({ options, index })"
  138. @close="args => handleClose(options, index, args)"
  139. />
  140. <!-- footer -->
  141. <template v-if="!options?.hideFooter" #footer>
  142. <template v-if="options?.footerRenderer">
  143. <component :is="options?.footerRenderer({ options, index })" />
  144. </template>
  145. <span v-else>
  146. <el-button
  147. v-for="(btn, key) in footerButtons(options)"
  148. :key="key"
  149. v-bind="btn"
  150. @click="
  151. btn.btnClick({
  152. dialog: { options, index },
  153. button: { btn, index: key }
  154. })
  155. "
  156. >
  157. {{ btn?.label }}
  158. </el-button>
  159. </span>
  160. </template>
  161. </el-dialog>
  162. </template>