<script lang="ts">
import { defineComponent, defineAsyncComponent } from "vue";
export default defineComponent({
  name: "CommonModal",
});
</script>

<script lang="ts" setup>
import { ref, watch } from "vue";
import Icon from "@/components/Module/Icon/index.vue";

const emits = defineEmits(["update:open"]);

const asyncContent = defineAsyncComponent({
  loader: () => import("@/components/Module/AsyncContent/index.vue"),
  delay: 2000,
});

interface propsType {
  open: boolean;
  title?: string | null;
  zIndex?: number | string;
  loading?: boolean;
  containDom?: any; // 挂载dom
  showConfirm?: boolean;
  showCancel?: boolean;
  confirmText?: string;
  cancelText?: string;
  onConfirm?: null | (() => void | Promise<void>);
  onCancel?: null | (() => void | Promise<void>);
}

let props = withDefaults(defineProps<propsType>(), {
  // 默认值
  open: false,
  title: null,
  zIndex: 1000,
  loading: false,
  confirmText: "确定",
  cancelText: "取消",
  onConfirm: null,
  onCancel: null,
  showConfirm: true,
  showCancel: true,
});

const useOpen = ref<boolean>(props.open);

const onConfirmHandle = () => {
  if (props.onConfirm) {
    props.onConfirm();
  } else {
    emits("update:open", false);
    useOpen.value = false;
  }
};

const onCancel = () => {
  if (props.onCancel) {
    props.onCancel();
  } else {
    emits("update:open", false);
    useOpen.value = false;
  }
};

watch(
  () => props.open,
  (val) => {
    useOpen.value = val;
  },
);

let globalModalRef = ref<HTMLElement>();

const prefix = "_global-modal";
</script>

<template>
  <div ref="globalModalRef" :class="prefix">
    <a-modal
      :zIndex="props.zIndex"
      v-bind="$attrs"
      :getContainer="() => props.containDom || globalModalRef"
      :closable="false"
      v-model:open="useOpen"
      :footer="null"
      @cancel="onCancel"
    >
      <slot name="header">
        <div :class="`${prefix}-head`">
          <div :class="`${prefix}-head-label`">
            {{ props.title }}
          </div>
          <button :class="`${prefix}-head-close`" @click="onCancel">
            <Icon name="close" />
          </button>
        </div>
      </slot>
      <Suspense>
        <asyncContent>
          <a-spin :spinning="props.loading">
            <div :class="`${prefix}-container`">
              <div class="modal-content-center">
                <asyncContent>
                  <slot></slot>
                </asyncContent>
              </div>
            </div>
          </a-spin>
          <slot name="footer">
            <div :class="`${prefix}-footer`">
              <div :class="`${prefix}-footer__grid`" v-if="props.showCancel">
                <a-button @click="onCancel">{{ cancelText }}</a-button>
              </div>
              <div :class="`${prefix}-footer__grid`" v-if="props.showConfirm">
                <a-button type="primary" @click="onConfirmHandle" :loading="props.loading">{{
                  confirmText
                }}</a-button>
              </div>
            </div>
          </slot>
        </asyncContent>
        <template #fallback>
          <div class="modal-content load-box">
            <a-spin />
          </div>
        </template>
      </Suspense>
    </a-modal>
  </div>
</template>

<style lang="scss" scoped>
$prefix: "_global-modal";

.#{$prefix} {
  &-head {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-radius: 16px 16px 0 0;
    background-color: #d9d9d9;
    margin-bottom: 20px;
    &-close {
      width: 20px;
      height: 20px;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 20px;
      font-weight: 500;
      color: #333;
    }
  }
  &-container {
    padding: 0 16px;
    width: 100%;
    flex: 1;
    align-self: stretch;
  }
  &-footer {
    padding: 12px 16px;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: end;
    gap: 20px;
  }

  :deep(.ant-modal-content) {
    padding: 0;
    .ant-modal-body {
      padding: 0;
      display: flex;
      align-items: start;
      justify-content: start;
      flex-direction: column;
    }
  }
  :deep(.ant-spin-nested-loading) {
    width: 100%;
  }
}
</style>
