index.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <script setup lang="ts">
  2. import {
  3. type EventType,
  4. type ButtonProps,
  5. type DrawerOptions,
  6. closeDrawer,
  7. drawerStore
  8. } from "./index";
  9. import { computed, ref } from "vue";
  10. import { isFunction } from "@pureadmin/utils";
  11. defineOptions({
  12. name: "ReDrawer"
  13. });
  14. const sureBtnMap = ref({});
  15. const footerButtons = computed(() => {
  16. return (options: DrawerOptions) => {
  17. return options?.footerButtons?.length > 0
  18. ? options.footerButtons
  19. : ([
  20. {
  21. label: "取消",
  22. text: true,
  23. bg: true,
  24. btnClick: ({ drawer: { options, index } }) => {
  25. const done = () =>
  26. closeDrawer(options, index, { command: "cancel" });
  27. if (options?.beforeCancel && isFunction(options?.beforeCancel)) {
  28. options.beforeCancel(done, { options, index });
  29. } else {
  30. done();
  31. }
  32. }
  33. },
  34. {
  35. label: "确定",
  36. type: "primary",
  37. text: true,
  38. bg: true,
  39. popConfirm: options?.popConfirm,
  40. btnClick: ({ drawer: { options, index } }) => {
  41. if (options?.sureBtnLoading) {
  42. sureBtnMap.value[index] = Object.assign(
  43. {},
  44. sureBtnMap.value[index],
  45. {
  46. loading: true
  47. }
  48. );
  49. }
  50. const closeLoading = () => {
  51. if (options?.sureBtnLoading) {
  52. sureBtnMap.value[index].loading = false;
  53. }
  54. };
  55. const done = () => {
  56. closeLoading();
  57. closeDrawer(options, index, { command: "sure" });
  58. };
  59. if (options?.beforeSure && isFunction(options?.beforeSure)) {
  60. options.beforeSure(done, { options, index, closeLoading });
  61. } else {
  62. done();
  63. }
  64. }
  65. }
  66. ] as Array<ButtonProps>);
  67. };
  68. });
  69. function eventsCallBack(
  70. event: EventType,
  71. options: DrawerOptions,
  72. index: number
  73. ) {
  74. if (options?.[event] && isFunction(options?.[event])) {
  75. return options?.[event]({ options, index });
  76. }
  77. }
  78. /**
  79. *
  80. * @param {DrawerOptions} options - 包含抽屉相关配置的对象
  81. * @param {number} index - 抽屉的索引
  82. * @param {Object} args - 传递给关闭抽屉操作的参数对象,默认为 { command: 'close' }
  83. * @returns {void} 这个函数不返回任何值
  84. */
  85. function handleClose(
  86. options: DrawerOptions,
  87. index: number,
  88. args = { command: "close" }
  89. ) {
  90. closeDrawer(options, index, args);
  91. eventsCallBack("close", options, index);
  92. }
  93. </script>
  94. <template>
  95. <el-drawer
  96. v-for="(options, index) in drawerStore"
  97. :key="index"
  98. v-bind="options"
  99. v-model="options.visible"
  100. class="pure-drawer"
  101. :append-to-body="!!options?.appendToBody"
  102. :append-to="options?.appendTo ? options.appendTo : 'body'"
  103. :destroy-on-close="!!options?.destroyOnClose"
  104. :lock-scroll="!!options?.lockScroll"
  105. @closed="handleClose(options, index)"
  106. @opened="eventsCallBack('open', options, index)"
  107. @open-auto-focus="eventsCallBack('openAutoFocus', options, index)"
  108. @close-auto-focus="eventsCallBack('closeAutoFocus', options, index)"
  109. >
  110. <!-- header -->
  111. <template
  112. v-if="options?.headerRenderer"
  113. #header="{ close, titleId, titleClass }"
  114. >
  115. <component
  116. :is="options?.headerRenderer({ close, titleId, titleClass })"
  117. />
  118. </template>
  119. <!-- body -->
  120. <component
  121. v-bind="options?.props"
  122. :is="options.contentRenderer({ options, index })"
  123. @close="args => handleClose(options, index, args)"
  124. />
  125. <!-- footer -->
  126. <template v-if="!options?.hideFooter" #footer>
  127. <template v-if="options?.footerRenderer">
  128. <component :is="options?.footerRenderer({ options, index })" />
  129. </template>
  130. <span v-else>
  131. <template v-for="(btn, key) in footerButtons(options)" :key="key">
  132. <el-popconfirm
  133. v-if="btn.popConfirm"
  134. v-bind="btn.popConfirm"
  135. @confirm="
  136. btn.btnClick({
  137. drawer: { options, index },
  138. button: { btn, index: key }
  139. })
  140. "
  141. >
  142. <template #reference>
  143. <el-button v-bind="btn">{{ btn?.label }}</el-button>
  144. </template>
  145. </el-popconfirm>
  146. <el-button
  147. v-else
  148. v-bind="btn"
  149. :loading="key === 1 && sureBtnMap[index]?.loading"
  150. @click="
  151. btn.btnClick({
  152. drawer: { options, index },
  153. button: { btn, index: key }
  154. })
  155. "
  156. >
  157. {{ btn?.label }}
  158. </el-button>
  159. </template>
  160. </span>
  161. </template>
  162. </el-drawer>
  163. </template>