| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- import { defineComponent, h, onMounted, render, ref, type VNode } from 'vue';
- import Modal from './Modal.vue';
- import Button from './Button.vue';
- import Icon from '@/components/Icon.vue';
- export type ModalConfirmType = 'info' | 'success' | 'warning' | 'error' | 'confirm';
- export interface ModalConfirmOptions {
- title?: string;
- content?: string | VNode;
- okText?: string;
- cancelText?: string;
- width?: string | number;
- maskClosable?: boolean;
- showCancel?: boolean;
- onOk?: () => void | Promise<void>;
- onCancel?: () => void;
- }
- const typeConfig: Record<ModalConfirmType, { icon: string; color: string }> = {
- info: { icon: 'icon-info-fill', color: '#1677ff' },
- success: { icon: 'icon-round-check-fill', color: '#00c49f' },
- warning: { icon: 'icon-warn-fill', color: '#ff8b2c' },
- error: { icon: 'icon-round-close-fill', color: '#ff4d4f' },
- confirm: { icon: 'icon-question-fill', color: '#ff8b2c' },
- };
- const ModalHolder = defineComponent({
- name: 'ModalConfirmHolder',
- props: {
- type: { type: String, required: true },
- options: { type: Object, required: true },
- onDestroy: { type: Function, required: true },
- },
- setup(props) {
- const show = ref(false);
- const okLoading = ref(false);
- const opt = props.options as ModalConfirmOptions;
- const cfg = typeConfig[props.type as ModalConfirmType];
- onMounted(() => {
- show.value = true;
- });
- function destroy() {
- (props.onDestroy as () => void)();
- }
- function handleClose() {
- show.value = false;
- }
- function handleUpdateShow(value: boolean) {
- show.value = value;
- if (!value) {
- setTimeout(destroy, 200);
- }
- }
- function handleOk() {
- const result = opt.onOk?.();
- if (result && typeof (result as Promise<void>).then === 'function') {
- okLoading.value = true;
- Promise.resolve(result)
- .then(handleClose)
- .catch(() => {})
- .finally(() => {
- okLoading.value = false;
- });
- } else {
- handleClose();
- }
- }
- function handleCancel() {
- opt.onCancel?.();
- handleClose();
- }
- return () =>
- h(
- Modal,
- {
- show: show.value,
- 'onUpdate:show': handleUpdateShow,
- title: opt.title,
- width: opt.width,
- maskClosable: opt.maskClosable,
- },
- {
- default: () =>
- h('div', { class: 'flex items-start gap-3' }, [
- h(Icon, { name: cfg.icon, size: '1.5rem', color: cfg.color, class: 'flex-shrink-0 mt-0.5' }),
- opt.content
- ? h(
- 'div',
- { class: 'flex-1 text-sm whitespace-pre-wrap break-words' },
- typeof opt.content === 'string' ? opt.content : opt.content,
- )
- : null,
- ]),
- footer: () =>
- h('div', { class: 'flex flex-row justify-end items-center gap-2' }, [
- opt.showCancel
- ? h(Button, { onClick: handleCancel }, { default: () => opt.cancelText ?? '取消' })
- : null,
- h(
- Button,
- { type: 'primary', loading: okLoading.value, onClick: handleOk },
- { default: () => opt.okText ?? '确定' },
- ),
- ]),
- },
- );
- },
- });
- function openConfirm(type: ModalConfirmType, options: ModalConfirmOptions = {}) {
- const container = document.createElement('div');
- document.body.appendChild(container);
- const destroy = () => {
- render(null, container);
- container.remove();
- };
- const vm = h(ModalHolder, { type, options, onDestroy: destroy });
- render(vm, container);
- }
- export const ModalApi = {
- info: (options?: ModalConfirmOptions) => openConfirm('info', { showCancel: false, ...options }),
- success: (options?: ModalConfirmOptions) => openConfirm('success', { showCancel: false, ...options }),
- warning: (options?: ModalConfirmOptions) => openConfirm('warning', { showCancel: false, ...options }),
- error: (options?: ModalConfirmOptions) => openConfirm('error', { showCancel: false, ...options }),
- confirm: (options?: ModalConfirmOptions) => openConfirm('confirm', { showCancel: true, ...options }),
- };
|