index.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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. ) {
  65. fullscreen.value = options?.fullscreen ?? false;
  66. if (options?.[event] && isFunction(options?.[event])) {
  67. return options?.[event]({ options, index });
  68. }
  69. }
  70. function handleClose(
  71. options: DialogOptions,
  72. index: number,
  73. args = { command: "close" }
  74. ) {
  75. closeDialog(options, index, args);
  76. eventsCallBack("close", options, index);
  77. }
  78. </script>
  79. <template>
  80. <el-dialog
  81. v-for="(options, index) in dialogStore"
  82. :key="index"
  83. v-bind="options"
  84. v-model="options.visible"
  85. class="pure-dialog"
  86. :fullscreen="fullscreen ? true : options?.fullscreen ? true : false"
  87. @closed="handleClose(options, index)"
  88. @opened="eventsCallBack('open', options, index)"
  89. @openAutoFocus="eventsCallBack('openAutoFocus', options, index)"
  90. @closeAutoFocus="eventsCallBack('closeAutoFocus', options, index)"
  91. >
  92. <!-- header -->
  93. <template
  94. v-if="options?.fullscreenIcon || options?.headerRenderer"
  95. #header="{ close, titleId, titleClass }"
  96. >
  97. <div
  98. v-if="options?.fullscreenIcon"
  99. class="flex items-center justify-between"
  100. >
  101. <span :id="titleId" :class="titleClass">{{ options?.title }}</span>
  102. <i
  103. v-if="!options?.fullscreen"
  104. :class="fullscreenClass"
  105. @click="fullscreen = !fullscreen"
  106. >
  107. <IconifyIconOffline
  108. class="pure-dialog-svg"
  109. :icon="
  110. options?.fullscreen
  111. ? ExitFullscreen
  112. : fullscreen
  113. ? ExitFullscreen
  114. : Fullscreen
  115. "
  116. />
  117. </i>
  118. </div>
  119. <component
  120. :is="options?.headerRenderer({ close, titleId, titleClass })"
  121. v-else
  122. />
  123. </template>
  124. <component
  125. v-bind="options?.props"
  126. :is="options.contentRenderer({ options, index })"
  127. @close="args => handleClose(options, index, args)"
  128. />
  129. <!-- footer -->
  130. <template v-if="!options?.hideFooter" #footer>
  131. <template v-if="options?.footerRenderer">
  132. <component :is="options?.footerRenderer({ options, index })" />
  133. </template>
  134. <span v-else>
  135. <el-button
  136. v-for="(btn, key) in footerButtons(options)"
  137. :key="key"
  138. v-bind="btn"
  139. @click="
  140. btn.btnClick({
  141. dialog: { options, index },
  142. button: { btn, index: key }
  143. })
  144. "
  145. >
  146. {{ btn?.label }}
  147. </el-button>
  148. </span>
  149. </template>
  150. </el-dialog>
  151. </template>