/** * Copyright (c) 2013-Now https://jeesite.com All rights reserved. * No deletion without permission, or be held responsible to law. * @author Vben、ThinkGem */ import type { ModalFunc, ModalFuncProps } from 'ant-design-vue/lib/modal/Modal'; import { Modal, message as Message, notification } from 'ant-design-vue'; import { InfoCircleFilled, CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons-vue'; import { NotificationArgsProps, ConfigProps } from 'ant-design-vue/lib/notification'; import { useI18n } from './useI18n'; import { isString } from '@jeesite/core/utils/is'; import { Icon } from '@jeesite/core/components/Icon'; import type { ConfigOnClose, MessageType } from 'ant-design-vue/lib/message'; import type { JointContent } from 'ant-design-vue/es/message/interface'; export interface NotifyApi { info(config: NotificationArgsProps): void; success(config: NotificationArgsProps): void; error(config: NotificationArgsProps): void; warn(config: NotificationArgsProps): void; warning(config: NotificationArgsProps): void; open(args: NotificationArgsProps): void; close(key: string): void; config(options: ConfigProps): void; destroy(): void; } export declare type NotificationPlacement = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight'; export declare type IconType = 'success' | 'info' | 'error' | 'warning'; export interface ModalOptionsEx extends Omit { iconType: 'warning' | 'success' | 'error' | 'info'; icon?: any; title?: any; content?: any; } export type ModalOptionsPartial = Partial & Pick; interface ConfirmOptions { info: ModalFunc; success: ModalFunc; error: ModalFunc; warn: ModalFunc; warning: ModalFunc; } function getIcon(iconType: string) { if (iconType === 'warning') { return ; } else if (iconType === 'success') { return ; } else if (iconType === 'info') { return ; } else { return ; } } function renderContent({ content }: Pick) { if (isString(content)) { return
${content as string}
`}>; } else { return content; } } /** * @description: Create confirmation box */ function createConfirm(options: ModalOptionsEx) { const iconType = options.iconType || 'info'; Reflect.deleteProperty(options, 'iconType'); const opt: ModalFuncProps = { centered: true, icon: getIcon(iconType), ...options, content: renderContent(options), maskClosable: false, }; return Modal.confirm(opt); } const getBaseOptions = () => { const { t } = useI18n(); return { okText: t('common.okText'), centered: true, }; }; function createModalOptions(options: ModalOptionsPartial, icon: string): ModalOptionsPartial | any { return { ...getBaseOptions(), ...options, content: renderContent(options), icon: getIcon(icon), maskClosable: false, }; } function createSuccessModal(options: ModalOptionsPartial) { return Modal.success(createModalOptions(options, 'success')); } function createErrorModal(options: ModalOptionsPartial) { return Modal.error(createModalOptions(options, 'close')); } function createInfoModal(options: ModalOptionsPartial) { return Modal.info(createModalOptions(options, 'info')); } function createWarningModal(options: ModalOptionsPartial) { return Modal.warning(createModalOptions(options, 'warning')); } function contains(str, searchs) { if (typeof str === 'object' && str.content) { str = str.content; } if (typeof str === 'object' && str.props?.innerHTML) { str = str.props?.innerHTML; } if (typeof str === 'string' && searchs) { const ss = searchs.split(','); for (let i = 0; i < ss.length; i++) { if (str.indexOf(ss[i]) >= 0) { return true; } } } return false; } const MESSAGE_DEDUPE_INTERVAL = 1200; const GENERIC_SUCCESS_MESSAGE_KEY = '__jeesite_generic_success_message__'; const recentMessageMap = new Map(); function getContentText(content: any): string { if (typeof content === 'string') return content; if (typeof content === 'number') return String(content); if (content?.content) return getContentText(content.content); if (content?.props?.innerHTML) return String(content.props.innerHTML); return ''; } function normalizeMessageText(content: any) { return getContentText(content).trim(); } function isGenericSuccessMessage(content: any) { return normalizeMessageText(content).replace(/[!!。.\s]/g, '') === '操作成功'; } function shouldSkipDuplicateMessage(type: string, content: any) { const text = normalizeMessageText(content); if (!text) return false; const key = `${type}:${text}`; const now = Date.now(); const lastTime = recentMessageMap.get(key) || 0; recentMessageMap.set(key, now); return now - lastTime < MESSAGE_DEDUPE_INTERVAL; } function buildGenericSuccessConfig(content: JointContent, duration?: number, onClose?: ConfigOnClose) { if (typeof content === 'object' && content && 'content' in content) { return { ...content, key: (content as any).key || GENERIC_SUCCESS_MESSAGE_KEY, duration: (content as any).duration ?? duration, onClose: (content as any).onClose ?? onClose, }; } return { content, key: GENERIC_SUCCESS_MESSAGE_KEY, duration, onClose, }; } function showDedupeMessage(type: string, content: JointContent, duration?: number, onClose?: ConfigOnClose) { if (shouldSkipDuplicateMessage(type, content)) { return () => {}; } if (type === 'success') { if (isGenericSuccessMessage(content)) { return Message.success(buildGenericSuccessConfig(content, duration, onClose)); } Message.destroy(GENERIC_SUCCESS_MESSAGE_KEY); } if (type === 'error') { return Message.error(content, duration, onClose); } else if (type === 'warning') { return Message.warning(content, duration, onClose); } else if (type === 'success') { return Message.success(content, duration, onClose); } else { return Message.info(content, duration, onClose); } } function createDedupeMessageApi() { return new Proxy(Message as any, { get(target: any, prop: string | symbol) { if (typeof prop === 'string' && ['success', 'error', 'warning', 'warn', 'info'].includes(prop)) { const type = prop === 'warn' ? 'warning' : prop; return (content: JointContent, duration?: number, onClose?: ConfigOnClose) => showDedupeMessage(type, content, duration, onClose); } return target[prop]; }, }) as typeof Message; } function showMessageModal(options: ModalOptionsPartial | string, type?: string) { const { t } = useI18n(); if (typeof options === 'string') options = { content: options }; if (typeof options.content === 'string' && options.content.startsWith('posfull:')) { options.content = ''; options.width = '80%'; } if (type === 'error' || contains(options.content, t('sys.message.error'))) { return Modal.error(createModalOptions(options, 'close')); } else if (type === 'warning' || contains(options.content, t('sys.message.warning'))) { return Modal.warning(createModalOptions(options, 'warning')); } else if (type === 'success' || contains(options.content, t('sys.message.success'))) { return Modal.success(createModalOptions(options, 'success')); } else { return Modal.info(createModalOptions(options, 'info')); } } function showMessage(content: JointContent, type?: string, duration?: number, onClose?: ConfigOnClose) { const { t } = useI18n(); let messageRemove = () => {}; if (typeof content === 'string' && content.startsWith('posfull:')) { content = { content: (
setTimeout(messageRemove, 1000)}>
messageRemove()}>
), duration, }; } if (type === 'error' || contains(content, t('sys.message.error'))) { messageRemove = showDedupeMessage('error', content, duration, onClose); } else if (type === 'warning' || contains(content, t('sys.message.warning'))) { messageRemove = showDedupeMessage('warning', content, duration, onClose); } else if (type === 'success' || contains(content, t('sys.message.success')) || isGenericSuccessMessage(content)) { messageRemove = showDedupeMessage('success', content, duration, onClose); } else { messageRemove = showDedupeMessage('info', content, duration, onClose); } return messageRemove; } notification.config({ placement: 'topRight', duration: 3, }); /** * @description: message */ export function useMessage() { return { createMessage: createDedupeMessageApi(), notification: notification as NotifyApi, createConfirm: createConfirm, createSuccessModal, createErrorModal, createInfoModal, createWarningModal, showMessageModal, showMessage, }; }