You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

179 lines
3.5 KiB

import { cloneDeep } from "bolt-ui/utils/func";
import { BoDialog } from "bolt-ui";
import {
defineComponent,
Fragment,
h,
markRaw,
nextTick,
onScopeDispose,
reactive,
ref,
resolveComponent,
shallowRef,
useAttrs,
} from "vue";
import { createDialogContext } from "./context";
import { IDialogState } from "./type";
import useAsyncComponent from "bolt-ui/hooks/useAsyncComponent";
export interface LawDialogHookOptions {
props?: object;
dialogProps?: object;
title?: string;
argus?: object;
autoInject?: boolean;
renderUI: any;
}
let createComponentInModal = (opts: any) => {
const { state, renderUI, _ } = opts;
return defineComponent({
name: "LawDialog",
setup(props: any, { slots, expose }) {
const attrs = useAttrs() as any;
const haveDefaule = !!slots?.default;
const action = {
show: _.show,
hide: _.hide,
};
createDialogContext([state, action]);
const F = () => {
return h(renderUI, { ...attrs, ...state.props }, () => []);
};
const cloneAttrs = cloneDeep(attrs ?? {});
delete cloneAttrs.dialogProp
return () =>
h(
BoDialog,
{
show: state.visible,
["onUpdate:show"]: (e: any) => (state.visible = e),
...(attrs.dialogProps ?? {}),
...(state.dialogProps ?? {}),
},
{
default: () =>
h(Fragment, [
haveDefaule
? slots?.default?.({
...cloneAttrs,
...state.props,
})
: !!renderUI && h(F),
]),
}
);
},
});
};
function useDialog({
argus = {},
props = {},
dialogProps = {},
renderUI,
autoInject = true,
}: LawDialogHookOptions) {
if (!createComponentInModal) {
console.warn("请定义一个Modal组件控制器");
return new Proxy(
{},
{
get(target, p, receiver) {
console.warn("请定义一个Modal组件控制器");
return;
},
}
) as any;
}
const state = reactive<IDialogState>({
visible: false,
dialogProps: cloneDeep(dialogProps),
props: cloneDeep(props),
argus: cloneDeep(argus),
});
let showResolve;
function show(props, argus = {}) {
state.props = props;
state.argus = argus;
let newState: IDialogState = {
visible: true,
};
Object.assign(state, newState);
return new Promise((resolve, reject) => {
showResolve = resolve;
});
}
const _ = {
show,
hide(value) {
showResolve?.(value);
state.visible = false;
},
UI: null,
};
if (typeof renderUI === "function") {
renderUI = useAsyncComponent(renderUI);
}
const component = markRaw(
createComponentInModal({
state,
renderUI,
_,
})
);
_.UI = component;
let markRawUI = markRaw(_.UI);
if (autoInject) {
allModals.value.push(markRawUI);
// @ts-ignore
_.destory = () => {
let index = -1;
for (let i = 0; i < allModals.value.length; i++) {
const modal = allModals.value[i];
if (modal === markRawUI) {
index = i;
break;
}
}
if (index !== -1) {
allModals.value.splice(index, 1);
}
};
onScopeDispose(() => {
let index = -1;
for (let i = 0; i < allModals.value.length; i++) {
const modal = allModals.value[i];
if (modal === markRawUI) {
index = i;
break;
}
}
if (index !== -1) {
allModals.value.splice(index, 1);
}
});
}
return _;
}
const allModals = ref([]);
export function ModalContainer() {
const attrs = useAttrs()
return h(
Fragment,
{},
allModals.value.map((V) => {
return h(V, { dialogProps: attrs });
})
);
}
export { useDialog };
export default useDialog;