index.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. <script setup lang="tsx">
  2. import { dialogKeyType, DialogState, dialogStore } from "./index";
  3. import { ElButton } from "element-plus";
  4. import XEUtils from "xe-utils";
  5. import sleep from "@/utils/sleep";
  6. import { nextTick, renderSlot } from "vue";
  7. function next(item: DialogState, data: any) {
  8. if (item.closeValue === "confirm") {
  9. item.resolve(data);
  10. } else {
  11. item.reject({ value: item.closeValue, data });
  12. }
  13. item.visible = false;
  14. }
  15. async function handleCancel(item: DialogState, emits = false, value = null) {
  16. if (emits) {
  17. item.closeValue = "cancel";
  18. next(item, value);
  19. return;
  20. }
  21. try {
  22. const fn = item.componentRef?.cancel ?? XEUtils.noop;
  23. const data = await fn();
  24. item.closeValue = "cancel";
  25. next(item, data);
  26. } catch {}
  27. }
  28. async function handleConfirm(item: DialogState, emits = false, value = null) {
  29. if (emits) {
  30. item.closeValue = "confirm";
  31. next(item, value);
  32. return;
  33. }
  34. const fn = item.componentRef?.confirm ?? XEUtils.noop;
  35. try {
  36. const data = await fn();
  37. item.closeValue = "confirm";
  38. next(item, data);
  39. } catch {}
  40. }
  41. async function closed(item: DialogState, index: number) {
  42. item.reject({ value: item.closeValue, data: null });
  43. await nextTick();
  44. await sleep();
  45. dialogStore.value.splice(index, 1);
  46. }
  47. function setRef(el, item) {
  48. item.componentRef = el;
  49. }
  50. const ConfigProvider = defineComponent({
  51. props: {
  52. item: Object,
  53. },
  54. setup(props, { slots }) {
  55. provide(dialogKeyType, props.item);
  56. return () => renderSlot(slots, "default");
  57. },
  58. });
  59. </script>
  60. <template>
  61. <el-dialog
  62. v-for="(item, index) in dialogStore"
  63. :key="`Cy-dialog_${item.dialogKey}`"
  64. :style="{ '--el-dialog-border-radius': '14px' }"
  65. v-model="item.visible"
  66. draggable
  67. v-bind="item.dialogProps"
  68. @closed="closed(item, index)"
  69. >
  70. <ConfigProvider :item="item">
  71. <component
  72. :is="item.component"
  73. :ref="el => setRef(el, item)"
  74. v-bind="item.params"
  75. @cyDialogCancel="
  76. (value: any, isEmits = true) => handleCancel(item, isEmits, value)
  77. "
  78. @cyDialogConfirm="
  79. (value: any, isEmits = true) => handleConfirm(item, isEmits, value)
  80. "
  81. :cyDialog="item"
  82. />
  83. </ConfigProvider>
  84. <template #footer v-if="item.showFooter">
  85. <el-button
  86. size="default"
  87. v-if="item.showCancel"
  88. @click="handleCancel(item)"
  89. >
  90. {{ item.cancelText || "取消" }}
  91. </el-button>
  92. <el-button
  93. v-if="item.showConfirm"
  94. type="primary"
  95. size="default"
  96. color="hsl(240 5.9% 10%)"
  97. @click="handleConfirm(item)"
  98. >
  99. {{ item.confirmText || "确认" }}
  100. </el-button>
  101. </template>
  102. </el-dialog>
  103. </template>
  104. <style lang="scss">
  105. .el-dialog.is-fullscreen {
  106. display: flex;
  107. flex-direction: column;
  108. .el-dialog__body {
  109. flex: 1;
  110. height: 0;
  111. }
  112. }
  113. </style>