index.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import { Component, ref, shallowRef } from "vue";
  2. import XEUtils from "xe-utils";
  3. interface DialogProps {
  4. title: string;
  5. fullscreen?: boolean;
  6. width?: number | string;
  7. top?: string | number;
  8. showClose?: boolean;
  9. alignCenter?: boolean;
  10. closeOnClickModal?: boolean;
  11. closeOnPressEscape?: boolean;
  12. }
  13. export type CloseValue = "close" | "confirm" | "cancel";
  14. export interface DialogExpose {
  15. // 如果报错了会阻止关闭弹窗
  16. confirm: () => any | Promise<any>;
  17. // 如果报错了会阻止关闭弹窗
  18. cancel: () => any | Promise<any>;
  19. }
  20. export namespace UseDialogType {
  21. export interface Expose extends DialogExpose {}
  22. export interface Emits {
  23. (e: "cyDialogConfirm" | "cyDialogCancel", value?: any): void;
  24. }
  25. }
  26. type FirstParam<T> =
  27. T extends Component<infer P, any, any, any, any, any>
  28. ? P extends Record<string, any>
  29. ? P
  30. : {}
  31. : never;
  32. export interface DialogOptions<P = Component> {
  33. dialogProps: DialogProps;
  34. params?: any;
  35. showCancel?: boolean;
  36. hideHeader?: boolean;
  37. showConfirm?: boolean;
  38. showFooter?: boolean;
  39. cancelText?: string;
  40. confirmText?: string;
  41. visible?: boolean;
  42. component?: any;
  43. componentRef?: DialogExpose;
  44. manuallyClose?: (
  45. cb: (value: CloseValue, data: any) => void,
  46. currentItem: DialogState
  47. ) => void;
  48. }
  49. export interface DialogState extends DialogOptions {
  50. resolve: (val: { value: CloseValue; data: any }) => void;
  51. reject: (val: { value: CloseValue; data: any }) => void;
  52. dialogKey?: number;
  53. closeValue?: CloseValue;
  54. }
  55. export const dialogStore = ref<DialogState[]>([]);
  56. export const dialogKey = ref(1);
  57. export function useDialog<R = any, C = Component>(
  58. component: C,
  59. props: DialogOptions<C>
  60. ) {
  61. return new Promise<R>((resolve, reject) => {
  62. props = {
  63. visible: true,
  64. component: shallowRef(component),
  65. showCancel: true,
  66. showConfirm: true,
  67. showFooter: true,
  68. hideHeader: false,
  69. ...props,
  70. };
  71. dialogKey.value++;
  72. const pushIndex = dialogStore.value.push({
  73. ...props,
  74. resolve: XEUtils.once(value => {
  75. resolve(value);
  76. }),
  77. reject: XEUtils.once(value => {
  78. reject(value);
  79. }),
  80. dialogKey: dialogKey.value,
  81. closeValue: "close",
  82. });
  83. if (props.manuallyClose) {
  84. const currentItem = dialogStore.value[pushIndex - 1];
  85. currentItem.dialogProps.showClose = false;
  86. currentItem.dialogProps.alignCenter =
  87. currentItem.dialogProps.alignCenter ?? true;
  88. currentItem.dialogProps.closeOnClickModal = false;
  89. currentItem.dialogProps.closeOnPressEscape = false;
  90. currentItem.showFooter = false;
  91. props.manuallyClose(
  92. (value: CloseValue, data: any) => {
  93. const item = dialogStore.value[pushIndex - 1];
  94. if (value === "confirm") {
  95. item.resolve(data);
  96. } else {
  97. item.reject({ value: item.closeValue, data });
  98. }
  99. item.visible = false;
  100. },
  101. dialogStore.value[pushIndex - 1]
  102. );
  103. }
  104. });
  105. }
  106. export const dialogKeyType: InjectionKey<DialogState> = Symbol("cyDialog");