提交 b78dc23c 编写于 作者: zhujiamin's avatar zhujiamin

update:支持抽屉

上级 1980ad1d
...@@ -93,4 +93,13 @@ export interface ViewDetail { ...@@ -93,4 +93,13 @@ export interface ViewDetail {
* @memberof ViewDetail * @memberof ViewDetail
*/ */
fileDir?: string; fileDir?: string;
/**
* 打开视图的方向
*
* @type {string}
* @memberof ViewDetail
*/
placement?: string;
} }
\ No newline at end of file
import { Subject } from 'rxjs';
import Router from '@/router';
import Antd from 'ant-design-vue';
import AppDrawerComponent from "./app-drawer.vue";
import IbizLoading from '@components/render/IbizLoading.vue';
import { IParam, ViewDetail } from '@core';
export class AppDrawer {
/**
* 实例对象
*
* @private
* @static
* @memberof AppDrawer
*/
private static drawer = new AppDrawer();
/**
* 构造方法
*
* @memberof AppDrawer
*/
constructor() {
if (AppDrawer.drawer) {
return AppDrawer.drawer;
}
}
/**
* 获取实例对象
*
* @static
* @returns
* @memberof AppDrawer
*/
public static getInstance() {
if (!AppDrawer.drawer) {
AppDrawer.drawer = new AppDrawer();
}
return AppDrawer.drawer;
}
/**
* 创建 Vue 实例对象
*
* @private
* @param {view} ViewDetail 视图对象
* @param {IParam} params 视图参数
* @param {IParam} [options] 模态配置项
* @return {*} {Subject<any>}
* @memberof AppDrawer
*/
private createVueExample(view: ViewDetail, params: IParam, options?: IParam): Subject<any> {
try {
let subject: null | Subject<any> = new Subject<any>();
let props = { view: view, context: params.context, viewParams: params.viewParams, isFullscreen: params.isFullscreen, subject: subject, options: options };
let dir = view.fileDir?.replace(/@page/, '');
//Vite 支持使用特殊的 import.meta.glob 函数从文件系统导入多个模块
const modules = import.meta.glob('../../page/*/*/index.ts');
const AsyncComp = defineAsyncComponent({
// 工厂函数
loader: modules['../../page' + dir + '/index.ts'],
// 加载异步组件时要使用的组件
loadingComponent: IbizLoading,
// 在显示 loadingComponent 之前的延迟 | 默认值:200(单位 ms)
delay: 0,
});
if (AsyncComp) {
const component = AppDrawerComponent;
const div = document.createElement('div');
document.body.appendChild(div);
const app = createApp(component,
{
close: () => { document.body.removeChild(div); app.unmount(); },
...props
}
);
app.component(view.name as string, AsyncComp);
app.use(Router).use(Antd).mount(div);
}
return subject;
} catch (error) {
console.error(error);
return new Subject<any>();
}
}
/**
* 打开抽屉
*
* @param {View} view 视图对象
* @param {IParam} params 视图参数
* @param {IParam} [options] 模态配置项
* @returns {Subject<any>}
* @memberof AppDrawer
*/
public openDrawer(view: ViewDetail, params: IParam, options?: IParam): Subject<any> {
try {
const subject = this.createVueExample(view, params, options);
return subject;
} catch (error) {
console.log(error);
return new Subject<any>();
}
}
/**
* 生成uuid
*
* @private
* @returns {string}
* @memberof AppDrawer
*/
private getUUID(): string {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}
}
\ No newline at end of file
<script setup lang="ts">
import { IParam, ViewDetail } from '@core';
import { Subject } from 'rxjs';
import { Ref, ref } from 'vue';
interface AppDrawerProps {
/**
* @description 视图
*/
view: ViewDetail;
/**
* @description 视图上下文参数
*/
context?: any;
/**
* @description 视图参数
*/
viewParams?: any;
/**
* @description 数据传递对象
*/
subject?: Subject<any>;
/**
* @description 关闭回调
*/
close: Function;
/**
* @description 是否全屏
*/
isFullscreen:boolean;
/**
* @description 模态参数
*/
option?: IParam;
}
const props = withDefaults(defineProps<AppDrawerProps>(), {
context: {},
viewParams: {},
});
/**
* 是否显示
*/
let isVisible: Ref<boolean> = ref(false);
/**
* 临时结果
*/
let tempResult = { ret: '' };
/**
* 视图名称
*/
let viewName: Ref<string> = ref('');
/**
* 抽屉的方向
*/
let placement: Ref<string> = ref('right');
/**
* 视图标题
*/
let title: string = '';
/**
* 视图宽度
*/
let width: Ref<number> = ref(0);
/**
* 视图高度
*/
let height: Ref<number> = ref(0);
/**
* 视图样式
*/
let style: any = {};
/**
* 暴露subject
*/
const getSubject = () => {
return props.subject;
};
/**
* Vue生命周期beforeMount
*/
onBeforeMount(() => {
if (props.view) {
viewName.value = props.view.name as string;
title = props.view.title || '';
placement.value = props.view.placement || 'right';
if (props.isFullscreen) {
Object.assign(style, { height: 'auto' });
} else {
if (!props.view.width || props.view.width === 0 || Object.is(props.view.width, '0px')) {
let viewWidth = 600;
if (window && window.innerWidth > 100) {
if (window.innerWidth > 100) {
viewWidth = window.innerWidth - 100;
} else {
viewWidth = window.innerWidth;
}
}
width.value = viewWidth;
} else {
width.value = props.view.width;
}
if (props.view.height && !Object.is(props.view.height, '0px')) {
Object.assign(style, { height: props.view.height + 'px' });
height.value = props.view.height;
} else {
height.value = 800;
}
}
}
});
/**
* Vue生命周期mounted
*/
onMounted(() => {
isVisible.value = true;
});
/**
* 视图关闭
*/
const close = (result: any) => {
if (result && Array.isArray(result) && result.length > 0) {
Object.assign(tempResult, { ret: 'OK' }, { datas: JSON.parse(JSON.stringify(result)) });
}
isVisible.value = false;
};
/**
* 视图数据变化
*/
const viewDataChange = (result: any) => {
tempResult = { ret: '' };
if (result && Array.isArray(result) && result.length > 0) {
Object.assign(tempResult, { ret: 'OK' }, { datas: JSON.parse(JSON.stringify(result)) });
}
};
/**
* 视图数据激活
*/
const viewDataActivated = (result: any) => {
if (result && Array.isArray(result) && result.length > 0) {
close(result);
}
};
/**
* 模态显示隐藏切换回调
*/
const onVisibleChange = ($event: any) => {
handleShowState($event);
props.close(tempResult);
};
/**
* 处理数据,向外抛值
*/
const handleShowState = ($event: any) => {
if (props.subject && tempResult) {
props.subject.next(tempResult);
}
};
</script>
<template>
<a-drawer
ref="curDrawer"
class="app-drawer"
v-model:visible="isVisible"
:placement="placement"
:title="title"
:footer="null"
:maskClosable="true"
:destroyOnClose="true"
:width="width"
:height="height"
:bodyStyle="style"
@close="onVisibleChange($event)"
>
<component
:is="viewName"
class="app-drawer-view-component"
:width="width"
:height="height"
:context="context"
:viewParams="viewParams"
:viewDefaultUsage="false"
:noViewCaption="true"
@viewDataChange="viewDataChange($event)"
@viewDataActivated="viewDataActivated($event)"
@close="close($event)"
:ref="viewName"
></component>
</a-drawer>
</template>
\ No newline at end of file
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import Router from '@/router';
import Antd from 'ant-design-vue'; import Antd from 'ant-design-vue';
import AppModalComponent from "./app-modal.vue"; import AppModalComponent from "./app-modal.vue";
import IbizLoading from '@components/render/IbizLoading.vue'; import IbizLoading from '@components/render/IbizLoading.vue';
...@@ -83,8 +84,8 @@ export class AppModal { ...@@ -83,8 +84,8 @@ export class AppModal {
...props ...props
} }
); );
app.component(view.name, AsyncComp); app.component(view.name as string, AsyncComp);
app.use(Antd).mount(div); app.use(Router).use(Antd).mount(div);
} }
return subject; return subject;
} catch (error) { } catch (error) {
......
...@@ -92,7 +92,7 @@ const getSubject = () => { ...@@ -92,7 +92,7 @@ const getSubject = () => {
*/ */
onBeforeMount(() => { onBeforeMount(() => {
if (props.view) { if (props.view) {
viewName.value = props.view.name; viewName.value = props.view.name as string;
title = props.view.title || ''; title = props.view.title || '';
if (props.isFullscreen) { if (props.isFullscreen) {
Object.assign(style, { height: 'auto' }); Object.assign(style, { height: 'auto' });
......
export { AppModal } from './app-modal/app-modal'; export { AppModal } from './app-modal/app-modal';
export { AppDrawer } from './app-drawer/app-drawer';
export { OpenViewService } from './open-view/open-view-service'; export { OpenViewService } from './open-view/open-view-service';
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册