Skip to content

Commit

Permalink
chore: 调整弹窗编辑逻辑支持子弹窗中可以选择打开父级其他弹窗 (baidu#9747)
Browse files Browse the repository at this point in the history
  • Loading branch information
2betop committed Mar 7, 2024
1 parent 108b46c commit a2dc129
Show file tree
Hide file tree
Showing 5 changed files with 339 additions and 81 deletions.
36 changes: 20 additions & 16 deletions packages/amis-editor-core/src/component/Panel/DialogList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {ClassNamesFn} from 'amis-core';
import {observer} from 'mobx-react';
import React from 'react';
import {EditorStoreType} from '../../store/editor';
import {translateSchema} from '../../util';
import {modalsToDefinitions, translateSchema} from '../../util';
import {Button, Icon, ListMenu, PopOverContainer, confirm} from 'amis';

export interface DialogListProps {
Expand All @@ -17,20 +17,23 @@ export default observer(function DialogList({
const modals = store.modals;

const handleAddDialog = React.useCallback(() => {
const modal = {
type: 'dialog',
title: '未命名弹窗',
definitions: modalsToDefinitions(store.modals),
body: [
{
type: 'tpl',
tpl: '弹窗内容'
}
]
};

store.openSubEditor({
title: '编辑弹窗',
value: {
type: 'dialog',
title: '未命名弹窗',
body: [
{
type: 'tpl',
tpl: '弹窗内容'
}
]
},
onChange: (value: any, diff: any) => {
store.addModal(value);
value: modal,
onChange: ({definitions, ...modal}: any, diff: any) => {
store.addModal(modal, definitions);
}
});
}, []);
Expand All @@ -42,10 +45,11 @@ export default observer(function DialogList({
title: '编辑弹窗',
value: {
type: 'dialog',
...(dialog as any)
...(dialog as any),
definitions: modalsToDefinitions(store.modals)
},
onChange: (value: any, diff: any) => {
store.updateModal(dialog.$$id!, value);
onChange: ({definitions, ...modal}: any, diff: any) => {
store.updateModal(dialog.$$id!, modal, definitions);
}
});
}, []);
Expand Down
44 changes: 36 additions & 8 deletions packages/amis-editor-core/src/store/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import {
guid,
appTranslate,
JSONGetByPath,
addModal
addModal,
mergeDefinitions
} from '../../src/util';
import {
InsertEventContext,
Expand Down Expand Up @@ -125,6 +126,16 @@ export interface TargetName {
editorId: string;
}

export type EditorModalBody = (DialogSchema | DrawerSchema) & {
// 节点 ID
$$id?: string;
// 如果是公共弹窗,在 definitions 中的 key
$$ref?: string;

// 弹出方式
actionType?: string;
};

export const MainStore = types
.model('EditorRoot', {
isMobile: false,
Expand Down Expand Up @@ -1001,7 +1012,7 @@ export const MainStore = types
},

// 获取弹窗大纲列表
get modals(): Array<DialogSchema | DrawerSchema> {
get modals(): Array<EditorModalBody> {
const schema = self.schema;
const modals: Array<DialogSchema | DrawerSchema> = [];
Object.keys(schema.definitions || {}).forEach(key => {
Expand Down Expand Up @@ -1033,7 +1044,7 @@ export const MainStore = types
},

get modalOptions() {
return this.modals.map((modal: any) => {
return this.modals.map((modal: EditorModalBody) => {
return {
label: `${
modal.editorSetting?.displayName || modal.title || '未命名弹窗'
Expand Down Expand Up @@ -1666,8 +1677,8 @@ export const MainStore = types
self.jsonSchemaUri = schemaUri;
},

addModal(modal?: DialogSchema | DrawerSchema) {
const [schema] = addModal(self.schema, modal);
addModal(modal?: DialogSchema | DrawerSchema, definitions?: any) {
const [schema] = addModal(self.schema, modal, definitions);
this.traceableSetSchema(schema);
},

Expand Down Expand Up @@ -1728,20 +1739,36 @@ export const MainStore = types
this.traceableSetSchema(schema);
},

updateModal(id: string, modal: DialogSchema | DrawerSchema) {
updateModal(
id: string,
modal: DialogSchema | DrawerSchema,
definitions?: any
) {
let schema = self.schema;
schema = JSONUpdate(schema, id, modal);
const parent = JSONGetParentById(schema, id);

if (!parent) {
throw new Error('modal not found');
}

if (definitions && isPlainObject(definitions)) {
schema = mergeDefinitions(schema, definitions, modal);
}

const newHostKey =
((modal as any).actionType || modal.type) === 'drawer'
? 'drawer'
: 'dialog';

if (parent === schema.definitions) {
schema = JSONUpdate(schema, id, modal);

// 如果编辑的是公共弹窗
if (!parent.actionType) {
const modalKey = Object.keys(parent).find(
key => parent[key]?.$$id === id
);

// 所有引用的地方都要更新
JSONTraverse(schema, (value: any, key: string, host: any) => {
if (
key === 'actionType' &&
Expand All @@ -1761,6 +1788,7 @@ export const MainStore = types
return value;
});
} else {
// 内嵌弹窗只用改自己就行了
schema = JSONUpdate(schema, parent.$$id, {
actionType: (modal as any).actionType || modal.type,
args: undefined,
Expand Down
95 changes: 94 additions & 1 deletion packages/amis-editor-core/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import isEqual from 'lodash/isEqual';
import isNumber from 'lodash/isNumber';
import debounce from 'lodash/debounce';
import merge from 'lodash/merge';
import {EditorModalBody} from './store/editor';

const {
guid,
Expand Down Expand Up @@ -1393,9 +1394,14 @@ export const scrollToActive = debounce((selector: string) => {
}
}, 200);

export function addModal(schema: any, modal: any) {
export function addModal(schema: any, modal: any, definitions?: any) {
schema = {...schema, definitions: {...schema.definitions}};

// 如果有传入definitions,则合并到schema中
if (definitions && isPlainObject(definitions)) {
schema = mergeDefinitions(schema, definitions, modal);
}

let idx = 1;
while (true) {
if (!schema.definitions[`modal-ref-${idx}`]) {
Expand All @@ -1414,3 +1420,90 @@ export function addModal(schema: any, modal: any) {

return [schema, `modal-ref-${idx}`];
}

/**
* 弹窗转成 definitions 定义
* 这样打开子弹窗的时候,可以把父级的弹窗列表透传到子弹窗里面去
*
* 这样子弹窗里面打开弹窗才能选到外面的弹窗
* @param modals
* @param definitions
* @returns
*/
export function modalsToDefinitions(
modals: Array<EditorModalBody>,
definitions: any = {}
) {
let schema = {
definitions
};
modals.forEach((modal, idx) => {
if (modal.$$ref) {
schema.definitions[modal.$$ref] = JSONPipeIn(modal);
} else {
[schema] = addModal(schema, {...modal, $$originId: modal.$$id});
}
});
return schema.definitions;
}

/**
* 从子弹窗的 definitions 合并回来到主弹窗的 definitions
*
* @param originSchema
* @param definitions
* @param modal
* @returns
*/
export function mergeDefinitions(
originSchema: any,
definitions: any,
modal: any
) {
const refs: Array<string> = [];
JSONTraverse(modal, (value, key) => {
if (key === '$ref') {
refs.push(value);
}
});

let schema = originSchema;
Object.keys(definitions).forEach(key => {
// 弹窗里面用到了才更新
if (!refs.includes(key)) {
return;
}

// 要修改就复制一份,避免污染原始数据
if (schema === originSchema) {
schema = {...schema, definitions: {...schema.definitions}};
}

const {$$originId, ...def} = definitions[key];

if ($$originId) {
const parent = JSONGetParentById(schema, $$originId);
if (!parent) {
throw new Error('Can not find modal action.');
}

const modalType = def.type === 'drawer' ? 'drawer' : 'dialog';
schema = JSONUpdate(schema, parent.$$id, {
...parent,
__actionModals: undefined,
args: undefined,
dialog: undefined,
drawer: undefined,
actionType: def.actionType ?? modalType,
[modalType]: JSONPipeIn({
$ref: key
})
});
schema.definitions[key] = JSONPipeIn(def);
} else {
schema.definitions[key] = JSONPipeIn(def);
}
});

return schema;
}

0 comments on commit a2dc129

Please sign in to comment.