fix: 修复弹窗编辑嵌套异常问题 (#10089)

This commit is contained in:
liaoxuezhi 2024-04-23 19:51:07 +08:00 committed by GitHub
parent c3bcbf2a70
commit b48173a314
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 73 additions and 26 deletions

View File

@ -13,7 +13,6 @@ export interface DocProps {
export function mdComment(fun: Function) {
const txt = fun.toString();
debugger;
return txt;
}

View File

@ -12,7 +12,7 @@ import {
} from 'amis-editor-core';
import React from 'react';
import {observer} from 'mobx-react';
import {JSONTraverse, JSONValueMap, RendererProps} from 'amis-core';
import {JSONTraverse, JSONValueMap, RendererProps, guid} from 'amis-core';
import {
Button,
FormField,
@ -41,6 +41,9 @@ export interface LocalModal {
isNew?: boolean;
isModified?: boolean;
isActive?: boolean;
// 是否被引用
isRefered?: boolean;
// 是否为当前动作内嵌的弹窗
isCurrentActionModal?: boolean;
@ -104,16 +107,33 @@ function DialogActionPanel({
.filter(
item => item.isModified && item !== currentModal && item.modal.$$ref
)
.forEach(({modal}) => {
.forEach(({modal, isRefered}) => {
const {$$originId: originId, ...def} = modal as any;
if (originId) {
const parent = JSONGetParentById(schema, originId);
if (!parent) {
if (id === originId) {
return;
} else if (!parent) {
// 找不到就丢回去,上层去处理
def.$$originId = originId;
} else if (isRefered === false) {
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({
...modal,
$$originId: undefined,
$$ref: undefined
})
});
// 不要写下面的 defintions 了
return;
} else {
// TODO 这里要不要再加个判断?
// 只更新当前动作中关联的弹窗?
const modalType = def.type === 'drawer' ? 'drawer' : 'dialog';
schema = JSONUpdate(schema, parent.$$id, {
...parent,
@ -196,6 +216,8 @@ function DialogActionPanel({
// 然后都引用这个 definition
let refKey: string = '';
[schema, refKey] = addModal(schema, currentModal.modal);
// 需要记录原始的弹窗 id方便上层处理合并
schema.definitions[refKey].$$originId = currentModal.modal.$$id;
newActionSchema = {
...actionSchema,
__actionModals: undefined,
@ -235,6 +257,30 @@ function DialogActionPanel({
});
}
// 如果弹窗里面又弹窗指向自己,那么也要更新
const currentModalId = currentModal.modal.$$id;
let refIds: string[] = [];
JSONTraverse(currentModal.modal, (value: any, key: string, host: any) => {
if (key === '$ref' && host.$$originId === currentModalId) {
refIds.push(host.$$id);
}
});
if (refIds.length) {
let refKey = '';
[schema, refKey] = addModal(schema, currentModal.modal);
schema = JSONUpdate(schema, actionSchema.$$id, {
[modalType]: JSONPipeIn({
$ref: refKey
})
});
refIds.forEach(refId => {
schema = JSONUpdate(schema, refId, {
$ref: refKey,
$$originId: undefined
});
});
}
// 原来的动作也要更新
if (originActionId && newRefName) {
schema = JSONUpdate(
@ -419,11 +465,6 @@ function DialogActionPanel({
let arr = members;
Object.keys(definitions).forEach(key => {
// 弹窗里面用到了才更新
if (!refs.includes(key)) {
return;
}
// 要修改就复制一份,避免污染原始数据
if (arr === members) {
arr = members.concat();
@ -431,7 +472,9 @@ function DialogActionPanel({
const {$$originId, ...modal} = definitions[key];
const idx = arr.findIndex(item =>
$$originId ? item.value === $$originId : item.modal.$$ref === key
$$originId
? (item.modal.$$originId || item.modal.$$id) === $$originId
: item.modal.$$ref === key
);
const label = `${
modal.editorSetting?.displayName || modal.title || '未命名弹窗'
@ -449,9 +492,10 @@ function DialogActionPanel({
label: label,
tip: tip,
modal: {...modal, $$ref: key, $$originId},
isModified: true
isModified: true,
isRefered: refs.includes(key)
});
} else {
} else if (refs.includes(key)) {
if ($$originId) {
throw new Error('Definition merge exception');
}
@ -481,9 +525,8 @@ function DialogActionPanel({
skipForm?: boolean,
closePopOver?: () => void
) => {
manager.openSubEditor({
title: '新建弹窗',
value: {
const modal = {
$$id: guid(),
type: 'dialog',
title: '未命名弹窗',
body: [
@ -493,9 +536,14 @@ function DialogActionPanel({
}
],
definitions: modalsToDefinitions(modals.map(item => item.modal))
},
};
const modalId = modal.$$id;
manager.openSubEditor({
title: '新建弹窗',
value: modal,
onChange: ({definitions, ...modal}: any, diff: any) => {
modal = JSONPipeIn(modal);
// 不能变 $$id 如果有内部有引用,就找不到了
modal = JSONPipeIn({...modal, $$id: modalId});
let arr = modals.concat();
if (!arr.some(item => item.isNew)) {
arr.push({