fix: 模型表单无法编辑数据源配置; chore: 修复Form使用场景兼容逻辑执行环节错误问题

This commit is contained in:
lurunze1226 2023-11-16 16:25:11 +08:00
parent 90ec85977d
commit 4e968e8e91
2 changed files with 452 additions and 322 deletions

View File

@ -1,11 +1,10 @@
import cx from 'classnames';
import flatten from 'lodash/flatten';
import cloneDeep from 'lodash/cloneDeep';
import {isObject, getRendererByName} from 'amis-core';
import {isObject, getRendererByName, setVariable} from 'amis-core';
import {
BasePlugin,
tipedLabel,
getI18nEnabled,
ChangeEventContext,
BaseEventContext,
PluginEvent,
@ -31,6 +30,7 @@ import {
import {FormOperatorMap} from '../../builder/constants';
import {getEventControlConfig} from '../../renderer/event-control/helper';
import {FieldSetting} from '../../renderer/FieldSetting';
import {_isModelComp} from '../../util';
import type {FormSchema} from 'amis/lib/Schema';
import type {
@ -591,6 +591,29 @@ export class FormPlugin extends BasePlugin {
this._dynamicControls = {...this._dynamicControls, ...controls};
}
/** 获取可能的使用场景 */
guessDSFeatFromSchema(schema: Record<string, any>): FormPluginFeat {
const validFeat = [
DSFeatureEnum.Insert,
DSFeatureEnum.Edit,
DSFeatureEnum.BulkEdit,
DSFeatureEnum.View
];
if (schema.hasOwnProperty('feat')) {
return validFeat.includes(schema.feat)
? schema.feat
: DSFeatureEnum.Insert;
}
if (schema.initApi != null && schema.api != null) {
return DSFeatureEnum.Edit;
} else if (schema.initApi != null && schema.api == null) {
return DSFeatureEnum.View;
} else {
return DSFeatureEnum.Insert;
}
}
panelBodyCreator = (context: BaseEventContext) => {
const dc = this.dynamicControls;
const builder = this.dsManager.getBuilderBySchema(context.schema);
@ -611,25 +634,8 @@ export class FormPlugin extends BasePlugin {
justify: true
}
});
const i18nEnabled = getI18nEnabled();
const schema = context?.node?.schema ?? context?.schema;
/** 是否是模型表单 */
const isModelForm =
((typeof schema?.api === 'string'
? schema.api
: typeof schema?.api?.url === 'string'
? schema.api.url
: ''
).startsWith('model://') ||
(typeof schema?.initApi === 'string'
? schema.initApi
: typeof schema?.initApi?.url === 'string'
? schema.initApi.url
: ''
).startsWith('model://')) &&
!schema.api.strategy;
/** 数据源控件 */
/** 新版数据源控件 */
const generateDSControls = () => {
const dsTypeSelector = this.dsManager.getDSSelectorSchema(
{
@ -714,14 +720,71 @@ export class FormPlugin extends BasePlugin {
return [dsTypeSelector, ...dsSettings];
};
return [
getSchemaTpl('tabs', [
/** 数据源 */
const generateDSCollapse = () => {
if (isCRUDFilter) {
/** CRUD查询表头数据源交给CRUD托管 */
return null;
} else if (_isModelComp(schema)) {
/** 模型组件使用旧版数据源配置 */
return {
title: '数据源',
body: [
getSchemaTpl('apiControl', {
label: '保存接口',
sampleBuilder: () => {
return `{\n "status": 0,\n "msg": "",\n // 可以不返回,如果返回了数据将被 merge 进来。\n data: {}\n}`;
}
}),
getSchemaTpl('apiControl', {
name: 'asyncApi',
label: tipedLabel(
'异步检测接口',
'设置此属性后,表单提交发送保存接口后,还会继续轮询请求该接口,直到返回 finished 属性为 true 才 结束'
),
visibleOn: 'data.asyncApi != null'
}),
getSchemaTpl('apiControl', {
name: 'initAsyncApi',
label: tipedLabel(
'异步检测接口',
'设置此属性后,表单请求 initApi 后,还会继续轮询请求该接口,直到返回 finished 属性为 true 才 结束'
),
visibleOn: 'data.initAsyncApi != null'
}),
getSchemaTpl('apiControl', {
name: 'initApi',
label: '初始化接口',
sampleBuilder: () => {
const data = {};
const schema = context?.schema;
if (Array.isArray(schema?.body)) {
schema.body.forEach((control: any) => {
if (
control.name &&
!~['combo', 'input-array', 'form'].indexOf(control.type)
) {
setVariable(data, control.name, 'sample');
}
});
}
return JSON.stringify(
{
title: '属性',
body: getSchemaTpl('collapseGroup', [
isCRUDFilter || isModelForm
? null
: {
status: 0,
msg: '',
data: data
},
null,
2
);
}
})
]
};
} else {
return {
title: '数据源',
body: [
{
@ -736,15 +799,9 @@ export class FormPlugin extends BasePlugin {
let feat = value;
if (!value) {
feat =
formStore?.data?.initApi != null
? DSFeatureEnum.Edit
: DSFeatureEnum.Insert;
feat = this.guessDSFeatFromSchema(formStore?.data);
}
/** 存量数据可能未设置过feat, 需要在数据域中 set 一下 */
formStore.setValueByName('feat', feat);
return feat;
},
onChange: (
@ -768,7 +825,18 @@ export class FormPlugin extends BasePlugin {
},
...generateDSControls()
]
},
};
}
};
return [
getSchemaTpl('tabs', [
{
title: '属性',
body: getSchemaTpl(
'collapseGroup',
[
generateDSCollapse(),
{
title: '基本',
body: [
@ -817,13 +885,16 @@ export class FormPlugin extends BasePlugin {
items: {
type: 'input-text',
placeholder: '请输入字段名',
options: flatten(schema?.body ?? schema?.controls ?? [])
options: flatten(
schema?.body ?? schema?.controls ?? []
)
.map((item: Record<string, any>) => {
const isFormItem = getRendererByName(
item?.type
)?.isFormItem;
return isFormItem && typeof item?.name === 'string'
return isFormItem &&
typeof item?.name === 'string'
? {label: item.name, value: item.name}
: false;
})
@ -993,11 +1064,15 @@ export class FormPlugin extends BasePlugin {
body: [
getSchemaTpl('switch', {
name: 'debug',
label: tipedLabel('开启调试', '在表单顶部显示当前表单的数据')
label: tipedLabel(
'开启调试',
'在表单顶部显示当前表单的数据'
)
})
]
}
])
].filter(Boolean)
)
},
{
title: '外观',
@ -1184,7 +1259,11 @@ export class FormPlugin extends BasePlugin {
* form
*/
patchSchema(schema: Schema, info: RendererConfig, props: any) {
let shouldUpdateSchema = false;
let patchedSchema: Schema = {...schema};
if (
!(
Array.isArray(schema.actions) ||
schema.wrapWithPanel === false ||
(Array.isArray(schema.body) &&
@ -1197,23 +1276,38 @@ export class FormPlugin extends BasePlugin {
(item as any).type
)
))
)
) {
return;
}
return {
...schema,
shouldUpdateSchema = true;
patchedSchema = {
...patchedSchema,
actions: [
{
type: 'submit',
label:
props?.translate(props?.submitText) || schema.submitText || '提交',
props?.translate(props?.submitText) ||
schema.submitText ||
'提交',
primary: true
}
]
};
}
if (!_isModelComp(schema)) {
/** 存量数据可能未设置过feat, 需要添加一下 */
if (!schema.feat) {
shouldUpdateSchema = true;
patchedSchema = {
...patchedSchema,
feat: this.guessDSFeatFromSchema(schema)
};
}
}
return shouldUpdateSchema ? patchedSchema : undefined;
}
async getAvailableContextFields(
scopeNode: EditorNodeType,
target: EditorNodeType,

View File

@ -80,3 +80,39 @@ export function escapeFormula(conf: any, keys: string[] = ['tpl']) {
return value;
});
}
/**
* schema model
*
* @param schema schema
* @returns schema model true false
*/
export function _isModelComp(schema: Record<string, any>): boolean {
if (!schema) {
return false;
}
if (
schema.hasOwnProperty('$$m') &&
(schema.$$m?.type === 'list' || schema.$$m?.type === 'form')
) {
return true;
}
const extraEvaluation = ['source', 'api', 'initApi'].some(key => {
if (schema?.[key] && typeof schema[key] === 'string') {
return schema?.[key].startsWith('model://');
}
if (schema?.[key]?.url && typeof schema[key].url === 'string') {
return (
schema[key].url.startsWith('model://') &&
!schema[key].hasOwnProperty('strategy')
);
}
return false;
});
return extraEvaluation;
}