import { CreateElement, defineComponent, getCurrentInstance, PropType, reactive, ref, VNode, } from 'vue'; import { useNamespace } from '@ibiz-template/vue-util'; import { isNumber } from 'lodash-es'; import { IModalOptions, IOverlayContainer } from '@ibiz-template/runtime'; import { useUIStore } from '@/store'; import '@ibiz-template/theme/style/components/util/modal/modal.scss'; import { OverlayContainer } from '../overlay-container/overlay-container'; export const AppModalComponent = defineComponent({ props: { opts: { type: Object as PropType<IModalOptions>, default: () => ({}), }, }, setup(props, ctx) { const ns = useNamespace('modal'); const { proxy } = getCurrentInstance()!; const isShow = ref(false); const { zIndex } = useUIStore(); const modalZIndex = zIndex.increment(); // 处理自定义样式,添加z-index变量 const customStyle = reactive<IData>({}); const { width, height } = props.opts; if (width) { customStyle.width = isNumber(width) ? `${width}px` : width; } if (height) { customStyle.height = isNumber(height) ? `${height}px` : height; } // 合并options const options = ref<IModalOptions>({ footerHide: true, modalClass: '' }); if (props.opts) { Object.assign(options.value, props.opts); } // 所有关闭方式最终都走这个 const onVisibleChange = (state: boolean) => { if (!state) { zIndex.decrement(); ctx.emit('dismiss'); document.body.removeChild(proxy.$el); } }; const dismiss = () => { isShow.value = false; }; const present = () => { isShow.value = true; }; return { ns, isShow, options, modalZIndex, customStyle, present, dismiss, onVisibleChange, }; }, render() { return ( <i-modal value={this.isShow} on-input={(val: boolean) => { this.isShow = val; }} class={[ this.ns.b(), this.options.placement && this.ns.m(this.options.placement), this.options.modalClass, ]} style={{ [this.ns.cssVarBlockName('z-index')]: this.modalZIndex }} styles={this.customStyle} footer-hide={this.options.footerHide} on-on-visible-change={this.onVisibleChange} > {this.$slots.default} </i-modal> ); }, }); /** * 创建模态框 * * @author lxm * @date 2022-11-09 18:11:57 * @export * @param {(_h: CreateElement) => VNode} render * @param {(IModalOptions | undefined)} [opts] * @returns {*} {IOverlayContainer} */ export function createModal( render: (_h: CreateElement) => VNode, opts?: IModalOptions | undefined, ): IOverlayContainer { return new OverlayContainer(AppModalComponent, render, opts); }