import $ from 'jquery' import _ from 'lodash' import localforage from 'localforage' import JSON5 from 'json5' import hotkeys from 'hotkeys-js' import { defineComponent, h, markRaw, nextTick, reactive, toRaw, unref, type App, createApp, type Component } from 'vue' import { ElMessage, ElMessageBox, ElNotification } from 'element-plus' import { QuestionFilled } from '@element-plus/icons-vue' import { renderIcon, createShortUUID, setQueryParam, getQueryParams } from '@/utils/webutils.ts' import type { showDialogOption } from '@/SystemOption' import ShowDialogWrap from '@/components/ShowDialogWrap.vue' import LoadingDialog from '@/components/LoadingDialog.vue' export default class System { _ = _ $ = $ createApp = createApp toRaw = toRaw unref = unref nextTick = nextTick defer = _.defer defineComponent = defineComponent markRaw = markRaw reactive = reactive renderIcon = renderIcon hotkeys = hotkeys localforage = localforage JSON5 = JSON5 json5 = JSON5 app!: App errorDialogContent: string[] = reactive([]) errorDialogIsShowing: boolean = false /** * 对话框元素栈 */ rootElementList: { cmp: Component, props: any }[] = reactive([]) createUUID = createShortUUID setQueryParam = setQueryParam getQueryParams = getQueryParams constructor(app: App) { this.app = app window['_'] = _ window['$'] = $ window['JSON5'] = JSON5 } /** * 轻量级提示信息 * @param message 消息内容 * @param type 消息类型,默认为 'info' */ msg(message: string, type: 'success' | 'warning' | 'info' | 'error' = 'info'): void { console.trace(message) ElMessage({ message, type }) // const $body = $('body') // // $body.find('[xtype=tooltip]').remove() // const $w = $( // '
' + // '
' + // _.escape(message) + // '
' // ) // $body.append($w) // // const iframeWidth = $w.parent().width() as number // const iframeHeight = $w.parent().height() as number // // const windowWidth = $w.width() as number // const windowHeight = $w.height() as number // // let setWidth = (iframeWidth - windowWidth) / 2 // let setHeight = (iframeHeight - windowHeight) / 2 // if (iframeHeight < windowHeight || setHeight < 0) { // setHeight = 0 // } // if (iframeWidth < windowWidth || setWidth < 0) { // setWidth = 0 // } // $w.css({ left: setWidth, top: setHeight }) // setTimeout(() => { // $w.remove() // }, 3000) } /** * 弹出用户必须点击确认的错误信息 */ showErrorDialog(msgOrTitle: string, msg?: string, dangerouslyUseHTMLString?: boolean, closeCallBack?: () => void) { let title, message if (!msg) { console.trace(msgOrTitle) title = '错误' message = msgOrTitle } else { console.trace(msg) title = msgOrTitle message = msg } // 如果有一样的内容,就不添加 if (_.findIndex(this.errorDialogContent, r => r === message) >= 0) { return } this.errorDialogContent.push(message) if (!this.errorDialogIsShowing) { // 只有在没有弹出对话框的清空下才弹出 this.errorDialogIsShowing = true ElMessageBox.alert( //@ts-ignore () => { if (this.errorDialogContent.length <= 0) { return '' } return _.map(this.errorDialogContent, (item) => h('div', null, item) ) }, title, { dangerouslyUseHTMLString: false, closeOnPressEscape: true, closeOnClickModal: true, confirmButtonText: '关闭', type: 'error', draggable: true, callback: () => { this.errorDialogIsShowing = false nextTick(() => { this.errorDialogContent.splice(0, this.errorDialogContent.length) }) if (closeCallBack) closeCallBack() } } ) } } /** * 弹出用户必须确认的提示信息 */ showInfoDialog(content: string, option: showDialogOption = { confirmButtonText: '关闭', draggable: true, showCancelButton: false, showClose: false, dangerouslyUseHTMLString: true, autofocus: true, closeOnClickModal: false, closeOnPressEscape: true }) { return this.alert(content, option) } /** * 信息提示内容,强提示,必须用户点击确认 */ alert(msg: string, option?: showDialogOption): Promise { console.trace(msg) // 将 msg 转译为 html enable 格式 msg = _.join(_.split(_.escape(msg), '\n'), '
') const newOption = _.extend({ confirmButtonText: '关闭', draggable: true, showCancelButton: false, showClose: false, dangerouslyUseHTMLString: true, autofocus: true, closeOnClickModal: false, closeOnPressEscape: true }, option) //@ts-ignore return ElMessageBox.alert(msg, '提示', newOption) } /** * 弹出确认对话框 * @param msg 消息内容 */ confirm(msg: string): Promise { return new Promise((resolve, reject) => { ElMessageBox.confirm(msg, '再次确认', { confirmButtonText: '确定', cancelButtonText: '取消', icon: markRaw(QuestionFilled) } ).then(() => { resolve() }).catch(() => { reject() }) }) } showDialog(childCmp: Component, param: ShowDialogOption = {}) { return new Promise((resolve, reject) => { const fullProps: any = { title: '未命名对话框', draggable: true, width: 800, height: 600, showClose: true, showMax: true, modal: true, dialogClass: '', closeOnClickModal: false, closeOnPressEscape: true, _insId: _.uniqueId('tmp_dlg_'), showCancelButton: true, showOkButton: true, cancelButtonText: '取消', okButtonText: '确定', ...param, dialogResolve: resolve, dialogReject: reject, childCmp: markRaw(childCmp), _input: param.data || {} } system.rootElementList.push({ cmp: h(ShowDialogWrap, fullProps), props: fullProps }) }) } globalLoadingHandle = null // "正在载入..." 对话框 /** * 全局 “正在载入...” 对话框 */ public showLoading(msg?: string): void { if (this.globalLoadingHandle) { // 存在 "正在载入..." 对话框 this.clearLoading() } const _insId = _.uniqueId('_dlg') system.rootElementList.push({ cmp: markRaw(LoadingDialog), props: { _insId: _insId, msg: msg } }) this.globalLoadingHandle = () => { _.remove(system.rootElementList, (item: any) => item.props._insId === _insId) } } /** * 关闭 “正在载入...” 对话框 */ public clearLoading(): void { if (typeof this.globalLoadingHandle === 'function') { this.globalLoadingHandle() } this.globalLoadingHandle = null } } export interface ShowDialogOption { title?: string draggable?: boolean width?: number height?: number showClose?: boolean showMax?: boolean modal?: boolean dialogClass?: string closeOnClickModal?: boolean closeOnPressEscape?: boolean data?: any showCancelButton?: boolean showOkButton?: boolean cancelButtonText?: string okButtonText?: string }