修改preview监听捕获,弹窗上下文

This commit is contained in:
ascend13 2023-09-19 20:40:28 +08:00
parent 8dc01ff9ef
commit e440c744d6
10 changed files with 94 additions and 111 deletions

View File

@ -271,7 +271,6 @@
transform-origin: center top;
height: 100%;
display: block;
// flex-direction: column;
position: relative;
&::-webkit-scrollbar {

View File

@ -29,6 +29,7 @@ export interface IFramePreviewProps {
export default class IFramePreview extends React.Component<IFramePreviewProps> {
initialContent: string = '';
dialogMountRef: React.RefObject<HTMLDivElement> = React.createRef();
iframeRef: HTMLIFrameElement;
constructor(props: IFramePreviewProps) {
super(props);
@ -67,9 +68,9 @@ export default class IFramePreview extends React.Component<IFramePreviewProps> {
}
@autobind
iframeRef(iframe: any) {
iframeRefFunc(iframe: any) {
const store = this.props.store;
this.iframeRef = iframe;
isAlive(store) && store.setIframe(iframe);
}
@ -89,6 +90,11 @@ export default class IFramePreview extends React.Component<IFramePreviewProps> {
return this.dialogMountRef.current;
}
@autobind
iframeContentDidMount() {
this.iframeRef.contentWindow?.document.body.classList.add(`is-modalOpened`);
}
render() {
const {editable, store, appLocale, autoFocus, env, data, manager, ...rest} =
this.props;
@ -97,7 +103,8 @@ export default class IFramePreview extends React.Component<IFramePreviewProps> {
<Frame
className={`ae-PreviewIFrame`}
initialContent={this.initialContent}
ref={this.iframeRef}
ref={this.iframeRefFunc}
contentDidMount={this.iframeContentDidMount}
>
<InnerComponent store={store} editable={editable} manager={manager} />
<div ref={this.dialogMountRef} className="ae-Dialog-preview-mount-node">
@ -200,7 +207,7 @@ function InnerComponent({
doc!.addEventListener('click', handleBodyClick);
layer!.addEventListener('mouseleave', handleMouseLeave);
layer!.addEventListener('mousemove', handleMouseMove);
layer!.addEventListener('click', handleClick);
layer!.addEventListener('click', handleClick, true);
layer!.addEventListener('mouseover', handeMouseOver);
const unSensor = resizeSensor(doc!.body, () => {

View File

@ -276,7 +276,7 @@ export class OutlinePanel extends React.Component<PanelProps> {
const {store} = this.props;
const outlineTabsKey = store.outlineTabsKey || 'component-outline';
const options = store.outline;
const dialogOptions = store.dialogOutlineList(this.props.manager);
const dialogOptions = store.dialogOutlineList;
return (
<div className="ae-Outline-panel">

View File

@ -48,6 +48,7 @@ export interface PreviewState {
@observer
export default class Preview extends Component<PreviewProps> {
currentDom: HTMLElement; // 用于记录当前dom元素
dialogReaction: any;
env: RenderOptions = {
...this.props.manager.env,
notify: (type, msg, conf) => {
@ -78,16 +79,46 @@ export default class Preview extends Component<PreviewProps> {
this.currentDom.addEventListener('mousedown', this.handeMouseDown);
this.props.manager.on('after-update', this.handlePanelChange);
const store = this.props.store;
// 添加弹窗事件或弹窗列表进行弹窗切换后自动选中对应的弹窗
this.dialogReaction = reaction(
() =>
store.root.children?.length
? `${store.root.children[0]?.type}:${store.root.children[0]?.id}`
: '',
info => {
const type = info.split(':')[0];
if (type === 'dialog' || type === 'drawer') {
const dialogId = info.split(':')[1];
store.changeOutlineTabsKey('dialog-outline');
store.setPreviewDialogId(dialogId);
store.setActiveId(dialogId);
// 添加触发弹窗事件的上下文
const eventPaths = store
.getSchemaPath(dialogId)
?.split('/onEvent')[0]
?.split('/');
if (eventPaths.length) {
const triggerNode = store.getSchemaByPath(eventPaths);
store.setTriggerNodeId(triggerNode.$$id);
}
} else {
store.setActiveId(store.getRootId());
}
}
);
}
componentWillUnmount() {
if (this.currentDom) {
this.currentDom.removeEventListener('mouseleave', this.handleMouseLeave);
this.currentDom.removeEventListener('mousemove', this.handleMouseMove);
this.currentDom.removeEventListener('click', this.handleClick);
this.currentDom.removeEventListener('click', this.handleClick, true);
this.currentDom.removeEventListener('mouseover', this.handeMouseOver);
this.currentDom.removeEventListener('mousedown', this.handeMouseDown);
this.props.manager.off('after-update', this.handlePanelChange);
this.dialogReaction?.();
}
this.scrollLayer?.removeEventListener('scroll', this.handlePanelChange);
@ -95,6 +126,18 @@ export default class Preview extends Component<PreviewProps> {
setTimeout(() => clearStoresCache([this.env.session!]), 500);
}
componentDidUpdate() {
const store = this.props.store;
if (store.activeDialogPath) {
let activeId = store.getSchemaByPath(
store.activeDialogPath.split('/')
)?.$$id;
activeId && store.setPreviewDialogId(activeId);
store.setActiveDialogPath('');
}
}
unSensor?: () => void;
layer?: HTMLDivElement;
scrollLayer?: HTMLDivElement;
@ -593,7 +636,6 @@ export interface SmartPreviewProps {
}
@observer
class SmartPreview extends React.Component<SmartPreviewProps> {
dialogReaction: any;
dialogMountRef: React.RefObject<HTMLDivElement> = React.createRef();
componentDidMount() {
@ -615,43 +657,10 @@ class SmartPreview extends React.Component<SmartPreviewProps> {
} else {
this.props.manager.buildRenderersAndPanels();
}
// 添加弹窗事件或弹窗列表进行弹窗切换后自动选中对应的弹窗
this.dialogReaction = reaction(
() =>
store.root.children?.length
? `${store.root.children[0]?.type}:${store.root.children[0]?.id}`
: '',
info => {
const type = info.split(':')[0];
if (type === 'dialog' || type === 'drawer') {
const dialogId = info.split(':')[1];
store.changeOutlineTabsKey('dialog-outline');
store.setPreviewDialogId(dialogId);
store.setActiveId(dialogId);
// 添加触发弹窗事件的上下文
const eventPaths = store
.getSchemaPath(dialogId)
?.split('/onEvent')[0]
?.split('/');
if (eventPaths.length) {
const triggerNode = store.getSchemaByPath(eventPaths);
store.setTriggerNodeId(triggerNode.$$id);
}
} else {
store.setActiveId(store.getRootId());
}
}
);
}
componentWillUnmount() {
this.dialogReaction?.();
}
componentDidUpdate(prevProps: SmartPreviewProps) {
const props = this.props;
const store = props.store;
if (props.editable !== prevProps.editable) {
if (props.editable) {
@ -661,13 +670,6 @@ class SmartPreview extends React.Component<SmartPreviewProps> {
});
}
}
if (store.activeDialogPath) {
let activeId = store.getSchemaByPath(
store.activeDialogPath.split('/')
)?.$$id;
activeId && store.setPreviewDialogId(activeId);
store.setActiveDialogPath('');
}
}
@autobind

View File

@ -43,7 +43,7 @@ import {
JSONPipeOut,
JSONUpdate
} from '../util';
import type {JSONSchema} from 'amis';
import type {JSONSchema, Schema} from 'amis';
import {toast, resolveVariable} from 'amis';
import find from 'lodash/find';
import {InsertSubRendererPanel} from '../component/Panel/InsertSubRendererPanel';
@ -225,9 +225,7 @@ export const MainStore = types
/** 应用多语言状态,用于其它组件进行订阅 */
appLocaleState: types.optional(types.number, 0),
/** 当前触发弹窗的节点id */
triggerNodeId: '',
/** 所有触发弹窗节点的上下文 */
allHostDataSchema: types.optional(types.frozen(), {})
triggerNodeId: ''
})
.views(self => {
return {
@ -1027,9 +1025,9 @@ export const MainStore = types
},
// 获取弹窗大纲列表
dialogOutlineList(manager: any) {
get dialogOutlineList() {
const schema = self.schema;
let actions = getDialogActions(schema, 'list', manager);
let actions = getDialogActions(schema, 'list');
return actions;
}
};
@ -1928,14 +1926,6 @@ export const MainStore = types
setTriggerNodeId(id: string) {
self.triggerNodeId = id;
},
/** 收集所有触发弹窗节点的上下文 */
collectHostNodeDataSchema(id: string, data: JSONSchema[]) {
self.allHostDataSchema = {
...self.allHostDataSchema,
[id]: data
};
}
};
});

View File

@ -1266,7 +1266,6 @@ export const scrollToActive = debounce((selector: string) => {
export const getDialogActions = (
schema: Schema,
listType: 'list' | 'source',
manager?: any,
filterId?: string
) => {
let dialogActions: any[] = [];
@ -1332,21 +1331,6 @@ export const getDialogActions = (
) {
if (listType == 'list') {
dialogActions.push(object[dialogBody]);
const store = (window as any)?.editorStore;
const eventPaths = store
.getSchemaPath(object[dialogBody].$$id)
?.split('/onEvent')[0]
?.split('/');
if (eventPaths?.length) {
const triggerNodeId = store.getSchemaByPath(eventPaths)?.$$id;
if (triggerNodeId && !store.previewDialogId) {
manager.getContextSchemas(triggerNodeId).then((data: any) => {
store.collectHostNodeDataSchema(triggerNodeId, data);
});
}
}
} else {
dialogActions.push({
label: `${object[dialogBody]?.title || '-'}${

View File

@ -490,19 +490,20 @@ export class DialogPlugin extends BasePlugin {
}
}
// 数据链
const hostNodeDataSchema =
this.manager.store.allHostDataSchema[this.manager.store.triggerNodeId];
hostNodeDataSchema
?.filter(
(item: any) => !['system-variable', 'page-global'].includes(item.$id)
)
?.forEach((item: any) => {
dataSchema = {
...dataSchema,
...item.properties
};
});
// 弹窗改版无法可能会有多个按钮触发一个弹窗,无法确定按钮的上下文
// TODO 数据链
// const hostNodeDataSchema =
// await this.manager.config.getHostNodeDataSchema?.();
// hostNodeDataSchema
// ?.filter(
// (item: any) => !['system-variable', 'page-global'].includes(item.$id)
// )
// ?.forEach((item: any) => {
// dataSchema = {
// ...dataSchema,
// ...item.properties
// };
// });
}
return {

View File

@ -369,18 +369,18 @@ export class DrawerPlugin extends BasePlugin {
}
// 数据链
const hostNodeDataSchema =
this.manager.store.allHostDataSchema[this.manager.store.triggerNodeId];
hostNodeDataSchema
?.filter(
(item: any) => !['system-variable', 'page-global'].includes(item.$id)
)
?.forEach((item: any) => {
dataSchema = {
...dataSchema,
...item.properties
};
});
// const hostNodeDataSchema =
// await this.manager.config.getHostNodeDataSchema?.();
// hostNodeDataSchema
// ?.filter(
// (item: any) => !['system-variable', 'page-global'].includes(item.$id)
// )
// ?.forEach((item: any) => {
// dataSchema = {
// ...dataSchema,
// ...item.properties
// };
// });
}
return {

View File

@ -92,7 +92,7 @@ export class ContextMenu extends React.Component<
}
componentDidMount() {
document.body.addEventListener('click', this.handleOutClick, true);
document.body.addEventListener('click', this.handleOutClick);
document.addEventListener('keydown', this.handleKeyDown);
}

View File

@ -170,13 +170,13 @@ export class Modal extends React.Component<ModalProps, ModalState> {
}
handleEnter = () => {
const mobileUI = this.props.mobileUI;
if (mobileUI) {
const iframe = document.querySelector(
'.ae-PreviewIFrame'
) as HTMLIFrameElement;
iframe.contentWindow?.document.body.classList.add(`is-modalOpened`);
}
// const mobileUI = this.props.mobileUI;
// if (mobileUI) {
// const iframe = document.querySelector(
// '.ae-PreviewIFrame'
// ) as HTMLIFrameElement;
// iframe.contentWindow?.document.body.classList.add(`is-modalOpened`);
// }
document.body.classList.add(`is-modalOpened`);
if (
window.innerWidth - document.documentElement.clientWidth > 0 ||