/* * @Author: 疯狂秀才(Lucas Huang) * @LastEditors: 疯狂秀才(Lucas Huang) * @Company: Inspur * @Version: v0.0.15 * @Date: 2019-04-02 11:48:08 * @LastEditTime: 2019-10-26 16:38:34 */ import { Injectable, Injector, NgZone } from '@angular/core'; import { Subject, Observable, of } from 'rxjs'; import { BsModalService, BsModalRef, DialogButton } from '@farris/ui-modal'; import { MessagerConfig, MessagerDefaultConfig, MESSAGER_DEFAULT_CONFIG } from './messager.config'; import { MessagerComponent } from './messager.component'; import { LocaleService } from '@farris/ui-locale'; import { unescapeIdentifier } from '@angular/compiler'; @Injectable() export class MessagerService { version = '0.0.15'; currentId = -1; modals: { id: number; ref: BsModalRef }[] = []; private defaultMessagerConfig: MessagerConfig = null; private confirmSubject; private ngZone: NgZone; private localeService: LocaleService; constructor(private bsModalService: BsModalService, private injector: Injector) { const config = this.injector.get(MESSAGER_DEFAULT_CONFIG) || MessagerDefaultConfig; this.defaultMessagerConfig = Object.assign({}, MessagerDefaultConfig, config); this.ngZone = this.injector.get(NgZone); this.localeService = this.injector.get(LocaleService); } get okText() { return this.localeService.getValue('messager.ok'); } get cancelText() { return this.localeService.getValue('messager.cancel'); } get yesText() { return this.localeService.getValue('messager.yes'); } get noText() { return this.localeService.getValue('messager.no'); } get titleText() { return this.localeService.getValue('messager.title'); } get errorTitle() { return this.localeService.getValue('messager.errorTitle'); } escapeHtml(str) { if (str === null || str === undefined) { return ''; } return str .replace(/&/g, '&') .replace(//g, '>') .replace(/\"/g, '"') .replace(/\'/g, ''') .replace(/\//g, '/'); } /** * 显示信息提示框 * @param msgtype 消息类别 * @param message 提示消息一 * @param opts 参数 提供属性 fitContent:true支持自动适应宽度 * @param submsg 提示消息二级 */ show(msgtype: string, message: string, opts?: {}, submsg = '') { if (document.activeElement) { (document.activeElement as any).blur(); } const modalHeight = 180; let defaultOpts = { safeHtml: true, title: this.titleText, width: 390, height: modalHeight, showButtons: false, showMaxButton: false, resizable: false, initialState: { okText: this.okText, okHandle: () => { this.close(); } }, class: 'modal-message ' + (msgtype ? 'modal-message-type-' + msgtype : ''), showHeader: false, }; defaultOpts = Object.assign({}, this.defaultMessagerConfig, defaultOpts); let extendOpts = {}; switch (msgtype) { case 'prompt': // 弹出对话类型 extendOpts = { showHeader: true, modalHeight: 260 }; break; case 'error': // 错误 extendOpts = { title: this.errorTitle, width: 446, showHeader: true, showMaxButton: true, fitContent: true }; break; case 'exception': extendOpts = { safeHtml: false, title: this.errorTitle, width: 446, showHeader: true, fitContent: true }; break; default: // 默认其他 extendOpts = { width: submsg ? 446 : 390, fitContent: true }; } Object.assign(defaultOpts, extendOpts); if (opts) { Object.assign(defaultOpts, opts); } if (message && defaultOpts.safeHtml) { message = this.escapeHtml(message); } Object.assign(defaultOpts.initialState, { type: msgtype, message, msg: submsg, exception: opts && opts['exception'] ? opts['exception'] : null, showLines: opts && opts['showLines'] ? opts['showLines'] : 3 }); if (defaultOpts['buttons'] && defaultOpts['buttons'].length) { if (!defaultOpts.initialState['buttons'] || !defaultOpts.initialState['buttons'].length) { defaultOpts.initialState['buttons'] = defaultOpts['buttons']; } } const _modal = this.bsModalService.show(MessagerComponent, defaultOpts); // _modal.content.buttons = defaultOpts['buttons'] || []; this.confirmSubject = new Subject(); if (this.modals.length > 0) { const modalContainerComponent = _modal.dialog; modalContainerComponent.instance.isShown = true; modalContainerComponent.instance.moveTo( 15 * this.modals.length, 15 * this.modals.length ); } this.ngZone.runOutsideAngular(() => { // 第1个按钮获取焦点 setTimeout(() => { const btns = _modal.dialog.location.nativeElement.querySelectorAll('.modal-footer button'); if (btns.length) { btns.item(0)['focus'](); } }); }); this.msgMgr(_modal); return _modal; } private msgMgr(ref: BsModalRef) { const id = this.bsModalService.getModalsCount() + 1000; if (this.modals.length === 0) { this.modals.push({ id, ref }); } else { if (!this.getModalById(id)) { this.modals.push({ id, ref }); } else { this.getModalById(id).ref = ref; } } const cmp = this.getModalCmp(); cmp.closed.subscribe((level: number) => { this.removeMessager(id); this.confirmSubject.unsubscribe(); }); this.currentId = id; } question(message: string, okCallback: () => void, cancelCallback?: () => void, msg?: string, fitContent = true) { const questionDlg = this.show('question', message, { initialState: { okText: this.yesText, okHandle: () => { questionDlg.close(); if (okCallback) { okCallback(); } }, cancelText: this.noText, cancelHandle: () => { questionDlg.close(); if (cancelCallback) { cancelCallback(); } } }, fitContent }, msg); return questionDlg; } question2(messager: string, btns: DialogButton[], msg?: string, fitContent = true) { return this.show('question', messager, { initialState: { buttons: btns }, fitContent }, msg); } /** * 2020年3月7日因为textarea高度在不同浏览器下不一样,固定高度可能会出现滚动条 * @param title 标题 * @param msg 信息 * @param fitContent 自适应内容 */ prompt(title: string, msg?: string, fitContent = true) { const promptSubject = new Subject(); const dlg = this.show('prompt', msg, { title, initialState: { okText: this.okText, okHandle: () => { const mc = dlg.content as MessagerComponent; dlg.close(); promptSubject.next(mc.promptText.nativeElement.value); }, cancelText: this.cancelText, cancelHandle: () => { dlg.close(); promptSubject.next(false); } }, fitContent, closed: () => { promptSubject.unsubscribe(); } }, msg); return promptSubject; } prompt2(title: string, msg?: string, opts?: any) { const promptSubject = new Subject(); const _opts = { showOkButton: true, showCloseButton: true, showFontSize: false, fontSize: 18, readonly: false, saveSize: false, closeWhenever: true }; if (!opts) { opts = _opts; } else { opts = Object.assign(_opts, opts); } const _dialogOpts = { title, initialState: { showOkButton: opts.showOkButton === undefined ? true : opts.showOkButton, showCancelButton: opts.showCancelButton === undefined ? true : opts.showCancelButton, okText: this.okText, okHandle: () => { const mc = dlg.content as MessagerComponent; const val = mc.promptText.nativeElement.value; if (opts.closeWhenever) { dlg.close(); promptSubject.next(val); } else { promptSubject.next({val, dlg }); } }, cancelText: this.cancelText, cancelHandle: () => { dlg.close(); promptSubject.next(false); }, showFontSize: opts.showFontSize, fontSize: opts.fontSize || 18, enableWordCount: !!opts.enableWordCount, countType: opts.countType || 'length', maxLength: opts.maxLength, inputType: opts.inputType || 'textarea', placeholder: opts.placeholder || '' }, fitContent: false, showMaxButton: true, resizable: true, class: '', closed: () => { promptSubject.unsubscribe(); }, opened: () => { if (opts.inputType !== 'textarea') { return; } else { setTimeout(() => { const textareaEle = dlg.content.promptText.nativeElement; textareaEle.closest('section').style.padding = '15px'; textareaEle.style.resize = 'none'; textareaEle.style.height = '100%'; if (opts.readonly) { textareaEle.readOnly = true; } }); } }, beforeClose: (modalRef: any) => { if (opts.saveSize) { const data = { fontSize: dlg.content.fontSize, width: modalRef.config.width, height: modalRef.config.height }; this.saveTextAreaSizeInfo(data); } return of(true); } }; let dialogOpts = _dialogOpts; if (opts) { dialogOpts = Object.assign(dialogOpts, opts); } const dlg = this.show('prompt', msg, dialogOpts, msg); if (opts.inputType && dlg.content.promptText) { dlg.content.promptText.nativeElement.focus(); } return promptSubject; } getKeyString() { // 一台终端共用一个配置 // 保留最后一次的设置, // 保存窗口大小,字体大小 return 'IGIX-FARRIS-UI-TEXTAREA-ZOOM-SETTINGS'; } private saveTextAreaSizeInfo(data) { if (window.localStorage) { const key = this.getKeyString(); localStorage.setItem(key, JSON.stringify(data)); } } confirm(message: string, msg?: string, fitContent = true): Observable { const confirmSubject = new Subject(); const confirmDlg = this.show('question', message, { initialState: { okText: this.okText, okHandle: () => { confirmDlg.close(); confirmSubject.next(true); }, cancelText: this.cancelText, cancelHandle: () => { confirmDlg.close(); confirmSubject.next(false); } }, fitContent, closed: () => { confirmSubject.unsubscribe(); } }, msg); return confirmSubject.asObservable(); } info(message: string, callback?: () => void, msg?: string, fitContent = true) { const infoDlg = this.show('info', message, { initialState: { okText: this.okText, okHandle: () => { infoDlg.close(); if (callback) { callback(); } } }, fitContent }, msg); return infoDlg; } /** 操作成功提示, * message: 提示信息 * msg: 2级信息 * fitCountent: 默认为true * callback: 确定事件回调 */ success(message: string, msg?: string, fitContent = true, callback: () => void = null) { const successDlg = this.show('success', message, { initialState: { okText: this.okText, okHandle: () => { successDlg.close(); if (callback) { callback(); } } }, fitContent }, msg); return successDlg; } /** 提示错误信息, * message: 提示信息 * msg: 2级信息 * fitCountent: 默认为true * callback: 确定事件回调 */ error(message: string, msg?: string, fitContent = true, callback: () => void = null, safeHtml = true) { const errorDlg = this.show('error', message, { safeHtml, initialState: { okText: this.okText, okHandle: () => { errorDlg.close(); if (callback) { callback(); } } }, fitContent }, msg); return errorDlg; } warning(message: string, msg?: string, fitContent = true, callback: () => void = null) { const warningDlg = this.show('warning', message, { initialState: { okText: this.okText, okHandle: () => { warningDlg.close(); if (callback) { callback(); } } }, fitContent }, msg); return warningDlg; } showHtmlMsg(type: 'warning'| 'info'|'error'|'success', title: string, message?: string, callback:() => void = null) { const msgDlg = this.show(type, title, { safeHtml: false, initialState: { okText: this.okText, okHandle: () => { msgDlg.close(); if (callback) { callback(); } } }, fitContent: true }, message); return msgDlg; } private close() { if (this.modals.length) { const msgbox = this.getModalById(this.currentId); if (msgbox) { msgbox.ref.close(); } } } private getModalById(id: number) { return this.modals.find(item => item.id === id); } private getModalCmp() { return this.bsModalService.getCurrentModalContainer().instance; } private removeMessager(id) { this.modals = this.modals.filter(n => n.id !== id); if (!this.modals.length) { this.currentId = -1; } else { this.currentId = this.modals[this.modals.length - 1].id; } } }