fix:修复历史数据dialog没有type的兼容 (#8209)

* 修复编辑态获取焦点等事件触发drawer,新建弹窗切换到现有弹窗过滤自身

* 兼容历史弹窗schema没有type的修复
This commit is contained in:
ascend13 2023-09-22 15:11:55 +08:00 committed by GitHub
parent e3b74d4ac9
commit 707d5ef900
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 140 additions and 73 deletions

View File

@ -29,6 +29,10 @@ export class DrawerAction implements RendererAction {
renderer: ListenerContext,
event: RendererEvent<any>
) {
// 防止editor preview模式下执行
if ((action as any).$$id !== undefined) {
return;
}
renderer.props.onAction?.(
event,
{

View File

@ -21,7 +21,8 @@ import {
JSONGetById,
JSONPipeIn,
JSONPipeOut,
JSONUpdate
JSONUpdate,
getFixDialogType
} from '../util';
import {createObject, createObjectFromChain} from 'amis-core';
import {CommonConfigWrapper} from './CommonConfigWrapper';
@ -253,7 +254,7 @@ function addDefinitions(
schema: Schema,
definitions: Schema,
dialogMaxIndex: number,
selectDialog: Schema
selectDialog: any
) {
let newSchema;
let dialogRefsName = '';
@ -265,14 +266,20 @@ function addDefinitions(
}
});
}
let dialogType = getFixDialogType(schema, selectDialog.$$id);
let newDefinitions = {...definitions};
if (!dialogRefsName) {
dialogRefsName = dialogMaxIndex
? `dialog-${dialogMaxIndex + 1}`
: 'dialog-1';
? `${dialogType}-ref-${dialogMaxIndex + 1}`
: `${dialogType}-ref-1`;
}
// 防止definition被查找到替换为$ref重新生成一下
newDefinitions[dialogRefsName] = JSONPipeIn(JSONPipeOut({...selectDialog}));
newDefinitions[dialogRefsName] = JSONPipeIn(
JSONPipeOut({
...selectDialog,
type: dialogType
})
);
newSchema = {
...schema,
definitions: newDefinitions
@ -294,8 +301,8 @@ function currentDialogOnchagne(
let definitions = schema.definitions || {};
let dialogMaxIndex: number = 0;
Object.keys(definitions).forEach(k => {
if (k.includes('dialog-')) {
let index = Number(k.split('-')[1]);
if (k.includes('ref-')) {
let index = Number(k.split('-')[2]);
dialogMaxIndex = Math.max(dialogMaxIndex, index);
}
});

View File

@ -20,7 +20,8 @@ import {
guid,
appTranslate,
JSONGetByPath,
getDialogActions
getDialogActions,
getFixDialogType
} from '../../src/util';
import {
InsertEventContext,
@ -231,7 +232,13 @@ export const MainStore = types
get filteredSchema() {
let schema = self.schema;
if (self.previewDialogId) {
schema = this.getSchema(self.previewDialogId);
let originDialogSchema = this.getSchema(self.previewDialogId);
schema = {
...originDialogSchema,
type:
originDialogSchema.type ||
getFixDialogType(self.schema, self.previewDialogId)
};
}
return filterSchemaForEditor(
getEnv(self).schemaFilter?.(schema) ?? schema

View File

@ -1281,19 +1281,19 @@ export const getDialogActions = (
const definitions = object.definitions;
if (definitions) {
Object.keys(definitions).forEach(key => {
if (key.includes('dialog-')) {
if (key.includes('ref-')) {
if (listType === 'list') {
dialogActions.push(definitions[key]);
} else {
const dialog = definitions[key];
const dialogType =
const dialogTypeName =
dialog.type === 'drawer'
? '抽屉'
? '抽屉式弹窗'
: dialog.dialogType
? '确认对话框'
: '弹窗';
dialogActions.push({
label: `${dialog.title || '-'}${dialogType}`,
label: `${dialog.title || '-'}${dialogTypeName}`,
value: dialog
});
}
@ -1317,7 +1317,7 @@ export const getDialogActions = (
[
'drawer',
{
title: '弹窗',
title: '抽屉式弹窗',
body: 'drawer'
}
],
@ -1325,28 +1325,63 @@ export const getDialogActions = (
'confirmDialog',
{
title: '确认对话框',
body: 'dialog'
// 兼容历史args参数
body: ['dialog', 'args']
}
]
]);
let dialogBody = dialogBodyMap.get(value)?.body!;
let dialogBodyContent = Array.isArray(dialogBody)
? object[dialogBody[0]] || object[dialogBody[1]]
: object[dialogBody];
if (
dialogBodyMap.has(value) &&
object[dialogBody] &&
!object[dialogBody].$ref
dialogBodyContent &&
!dialogBodyContent.$ref
) {
if (listType == 'list') {
dialogActions.push(object[dialogBody]);
} else {
// 没有 type: dialog的历史数据兼容一下
dialogActions.push({
label: `${object[dialogBody]?.title || '-'}${
dialogBodyMap.get(value)?.title
}`,
value: object[dialogBody]
...dialogBodyContent,
type: dialogBody
});
} else {
// 新建弹窗切换到现有弹窗把自身过滤掉
if (!filterId || (filterId && filterId !== dialogBodyContent.id)) {
dialogActions.push({
label: `${dialogBodyContent?.title || '-'}${
dialogBodyMap.get(value)?.title
}`,
value: dialogBodyContent
});
}
}
}
}
});
return dialogActions;
};
/**
* definitions,由于历史数据可能没有type: dialog,
* @param json
* @param previewDialogId
*/
export const getFixDialogType = (json: Schema, dialogId: string) => {
const dialogBodyMap = {
dialog: 'dialog',
drawer: 'drawer',
confirmDialog: 'dialog'
};
let parentSchema = JSONGetParentById(json, dialogId);
// 事件中的弹窗
if (parentSchema.actionType) {
return dialogBodyMap[parentSchema.actionType as keyof typeof dialogBodyMap];
}
// definitions中的弹窗
else {
let dialogRefSchema = JSONGetById(parentSchema, dialogId);
return dialogRefSchema.type;
}
};

View File

@ -6,6 +6,7 @@ import {
BaseEventContext,
defaultValue,
EditorManager,
getFixDialogType,
getSchemaTpl,
JsonGenerateID,
JSONPipeIn,
@ -20,7 +21,6 @@ import {
DataSchema,
filterTree,
findTree,
JSONTraverse,
mapTree,
normalizeApi,
PlainObject,
@ -2911,7 +2911,8 @@ export const getEventControlConfig = (
actionConfigSubmitFormatter: (
config: ActionConfig,
type?: string,
actionData?: ActionData
actionData?: ActionData,
shcema?: Schema
) => {
let action: ActionConfig = {...config, groupType: undefined};
action.__title = findActionNode(
@ -3032,18 +3033,24 @@ export const getEventControlConfig = (
}
};
const chooseCurrentDialog = (action: ActionConfig) => {
const chooseCurrentDialog = (action: ActionConfig, schema: Schema) => {
const selectDialog = action.__selectDialog;
let dialogType = getFixDialogType(schema, selectDialog.$$id);
// 选择现有弹窗后为了使之前的弹窗和现有弹窗$$id唯一这里重新生成一下
let dialogCopy = JSONPipeIn(JSONPipeOut({...selectDialog}));
let dialogCopy = JSONPipeIn(
JSONPipeOut({
...selectDialog,
type: dialogType
})
);
// 在这里记录一下新dialogId
action.__relatedDialogId = dialogCopy.$$id;
if (selectDialog?.dialogType) {
action.actionType = 'dialog';
action.dialog = dialogCopy;
} else {
action.actionType = selectDialog.type;
action[selectDialog.type] = dialogCopy;
action.actionType = selectDialog.type || dialogType;
action[selectDialog.type || dialogType] = dialogCopy;
}
};
@ -3051,7 +3058,7 @@ export const getEventControlConfig = (
if (config.__dialogSource === 'new') {
setInitSchema(config.groupType, action);
} else if (config.__dialogSource === 'current') {
chooseCurrentDialog(action);
chooseCurrentDialog(action, shcema!);
}
}
// 编辑
@ -3071,7 +3078,7 @@ export const getEventControlConfig = (
};
}
} else if (config.__dialogSource === 'current') {
chooseCurrentDialog(action);
chooseCurrentDialog(action, shcema!);
}
}
}

View File

@ -11,7 +11,7 @@ import {
render as amisRender
} from 'amis';
import cloneDeep from 'lodash/cloneDeep';
import {FormControlProps, autobind, findTree} from 'amis-core';
import {FormControlProps, Schema, autobind, findTree} from 'amis-core';
import ActionDialog from './action-config-dialog';
import {
findActionNode,
@ -36,7 +36,8 @@ import {
RendererPluginAction,
RendererPluginEvent,
SubRendererPluginAction,
getDialogActions
getDialogActions,
getFixDialogType
} from 'amis-editor-core';
export * from './helper';
import {i18n as _i18n} from 'i18n-runtime';
@ -63,7 +64,8 @@ interface EventControlProps extends FormControlProps {
actionConfigSubmitFormatter?: (
actionConfig: ActionConfig,
type?: string,
actionData?: ActionData
actionData?: ActionData,
schema?: Schema
) => ActionConfig; // 动作配置提交时格式化
owner?: string; // 组件标识
}
@ -110,6 +112,12 @@ interface EventControlState {
appLocaleState?: number;
}
const dialogObjMap = {
dialog: 'dialog',
drawer: 'drawer',
confirmDialog: ['dialog', 'args']
};
export class EventControl extends React.Component<
EventControlProps,
EventControlState
@ -697,8 +705,18 @@ export class EventControl extends React.Component<
}
// 获取现有弹窗列表
getDialogList(manager: EditorManager) {
return getDialogActions(manager.store.schema, 'source');
getDialogList(
manager: EditorManager,
action?: ActionConfig,
actionType?: keyof typeof dialogObjMap
) {
if (action && actionType && dialogObjMap[actionType]) {
let dialogBodyContent = dialogObjMap[actionType];
let filterId = Array.isArray(dialogBodyContent)
? action[dialogBodyContent[0]].id || action[dialogBodyContent[1]].id
: action[dialogBodyContent].id;
return getDialogActions(manager.store.schema, 'source', filterId);
} else return getDialogActions(manager.store.schema, 'source');
}
// 唤起动作配置弹窗
@ -751,6 +769,8 @@ export class EventControl extends React.Component<
);
}
const actionGroupType = actionConfig?.__actionType || action.actionType;
data.actionData = {
eventKey: data.actionData!.eventKey,
actionIndex: data.actionData!.actionIndex,
@ -758,12 +778,12 @@ export class EventControl extends React.Component<
pluginActions,
getContextSchemas,
...actionConfig,
groupType: actionConfig?.__actionType || action.actionType,
groupType: actionGroupType,
__actionDesc: actionNode?.description ?? '', // 树节点描述
__actionSchema: actionNode!.schema, // 树节点schema
__subActions: hasSubActionNode?.actions, // 树节点子动作
__cmptTreeSource: supportComponents ?? [],
__dialogActions: this.getDialogList(manager),
__dialogActions: this.getDialogList(manager, action, actionGroupType),
__superCmptTreeSource: allComponents,
// __supersCmptTreeSource: '',
__setValueDs: setValueDs
@ -772,15 +792,12 @@ export class EventControl extends React.Component<
// 编辑时准备已选的弹窗来源和标题
if (actionConfig?.actionType == 'openDialog') {
const dialogActionType = data.actionData?.groupType;
const definitions = manager.store.schema.definitions;
const dialogObjMap = new Map([
['dialog', 'dialog'],
['drawer', 'drawer'],
['confirmDialog', 'dialog']
]);
const dialogObj = dialogObjMap.get(dialogActionType!);
let dialogBody =
dialogObjMap[actionGroupType as keyof typeof dialogObjMap];
const dialogObj = Array.isArray(dialogBody)
? dialogBody[0] || dialogBody[1]
: dialogBody;
const dialogRef = actionConfig?.[dialogObj!]?.$ref;
@ -861,7 +878,8 @@ export class EventControl extends React.Component<
) : null;
}
getRefsFromCurrentDialog(definitions: any, action: any) {
getRefsFromCurrentDialog(store: any, action: any) {
let definitions = store.schema.definitions;
let dialogMaxIndex: number = 0;
let dialogRefsName = '';
if (definitions) {
@ -870,16 +888,17 @@ export class EventControl extends React.Component<
if (dialog.$$id === action.__selectDialog.$$id) {
dialogRefsName = k;
}
if (k.includes('dialog-')) {
let index = Number(k.split('-')[1]);
if (k.includes('ref-')) {
let index = Number(k.split('-')[2]);
dialogMaxIndex = Math.max(dialogMaxIndex, index);
}
});
}
let dialogType = getFixDialogType(store.schema, action.__selectDialog.$$id);
if (!dialogRefsName) {
dialogRefsName = dialogMaxIndex
? `dialog-${dialogMaxIndex + 1}`
: 'dialog-1';
? `${dialogType}-ref-${dialogMaxIndex + 1}`
: `${dialogType}-ref-1`;
}
return dialogRefsName;
}
@ -890,14 +909,12 @@ export class EventControl extends React.Component<
const {actionData} = this.state;
const store = manager.store;
const action =
actionConfigSubmitFormatter?.(config, type, actionData) ?? config;
actionConfigSubmitFormatter?.(config, type, actionData, store.schema) ??
config;
delete action.__actionSchema;
if (type === 'add') {
if (
action.actionType === 'dialog' ||
action.actionType === 'drawer' ||
action.actionType === 'confirmDialog'
) {
if (['dialog', 'drawer', 'confirmDialog'].includes(action.actionType)) {
this.addAction?.(config.eventKey, action);
let args =
action.actionType === 'dialog'
? 'dialog'
@ -912,24 +929,18 @@ export class EventControl extends React.Component<
}/actions/${actionLength}/${args}`;
store.setActiveDialogPath(path);
} else if (config?.__dialogSource === 'current') {
let dialogRefsName = this.getRefsFromCurrentDialog(
store.schema.definitions,
action
);
let dialogRefsName = this.getRefsFromCurrentDialog(store, action);
let path = `definitions/${dialogRefsName}`;
store.setActiveDialogPath(path);
} else {
this.addAction?.(config.eventKey, action);
}
this.addAction?.(config.eventKey, action);
} else {
this.addAction?.(config.eventKey, action);
}
} else if (type === 'update') {
if (
action.actionType === 'dialog' ||
action.actionType === 'drawer' ||
action.actionType === 'confirmDialog'
) {
if (['dialog', 'drawer', 'confirmDialog'].includes(action.actionType)) {
this.updateAction?.(config.eventKey, config.actionIndex, action);
let args =
action.actionType === 'dialog'
? 'dialog'
@ -943,14 +954,10 @@ export class EventControl extends React.Component<
}/actions/${config.actionIndex}/${args}`;
store.setActiveDialogPath(path);
} else if (config.__dialogSource === 'current') {
let dialogRefsName = this.getRefsFromCurrentDialog(
store.schema.definitions,
action
);
let dialogRefsName = this.getRefsFromCurrentDialog(store, action);
let path = `definitions/${dialogRefsName}`;
store.setActiveDialogPath(path);
}
this.updateAction?.(config.eventKey, config.actionIndex, action);
} else {
this.updateAction?.(config.eventKey, config.actionIndex, action);
}