mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-30 02:48:55 +08:00
fix(amis-editor): 数据源构造器兼容历史存量Schema
This commit is contained in:
parent
56b6e3110d
commit
d8e4d31fc2
@ -585,8 +585,8 @@ export function JsonGenerateID(json: any) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (json.type) {
|
||||
// && !json.id
|
||||
/** 脚手架构建的Schema提前构建好了组件 ID,此时无需生成 ID,避免破坏事件动作 */
|
||||
if (json.type && (!json.__origin || json.__origin !== 'scaffold')) {
|
||||
json.id = generateNodeId();
|
||||
}
|
||||
|
||||
|
@ -94,8 +94,9 @@ export class ApiDSBuilder extends DSBuilder<
|
||||
return (this.constructor as typeof ApiDSBuilder).key;
|
||||
}
|
||||
|
||||
match(schema: any) {
|
||||
const apiSchema = schema?.api;
|
||||
match(schema: any, key?: string) {
|
||||
const sourceKey = key && typeof key === 'string' ? key : 'api';
|
||||
const apiSchema = schema?.[sourceKey];
|
||||
|
||||
if (schema?.dsType === this.key || apiSchema?.sourceType === this.key) {
|
||||
return true;
|
||||
@ -112,9 +113,17 @@ export class ApiDSBuilder extends DSBuilder<
|
||||
return false;
|
||||
}
|
||||
|
||||
const maybeApiUrl =
|
||||
typeof apiSchema === 'string'
|
||||
? apiSchema
|
||||
: isObject(apiSchema)
|
||||
? apiSchema?.url || ''
|
||||
: '';
|
||||
|
||||
if (
|
||||
typeof apiSchema === 'string' &&
|
||||
/^(get|post|put|delete|option):/.test(apiSchema)
|
||||
typeof maybeApiUrl === 'string' &&
|
||||
(/^(get|post|put|delete|patch|option|jsonp):/.test(apiSchema) ||
|
||||
!~maybeApiUrl.indexOf('api://'))
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
@ -1359,13 +1368,12 @@ export class ApiDSBuilder extends DSBuilder<
|
||||
primaryField = 'id',
|
||||
listApi,
|
||||
editApi,
|
||||
bulkEditApi,
|
||||
simpleQueryFields
|
||||
bulkEditApi
|
||||
} = scaffoldConfig || {};
|
||||
const enableBulkEdit = feats?.includes('BulkEdit');
|
||||
const enableBulkDelete = feats?.includes('BulkDelete');
|
||||
const enableEdit = feats?.includes('Edit');
|
||||
const multiple = enableBulkEdit || enableBulkDelete;
|
||||
const enableMultiple = enableBulkEdit || enableBulkDelete;
|
||||
|
||||
const id = generateNodeId();
|
||||
/** 暂时不考虑 cards 和 list */
|
||||
@ -1375,18 +1383,10 @@ export class ApiDSBuilder extends DSBuilder<
|
||||
mode: 'table2',
|
||||
dsType: this.key,
|
||||
syncLocation: true,
|
||||
multiple: multiple,
|
||||
/** 通过脚手架创建的单条操作入口都在操作列中,所以rowSelection暂时不需要radio */
|
||||
...(multiple
|
||||
? {
|
||||
rowSelection: {
|
||||
type: 'checkbox',
|
||||
keyField: primaryField
|
||||
}
|
||||
}
|
||||
: {}),
|
||||
loadType: 'pagination',
|
||||
/** CRUD2使用 selectable + multiple 控制,Table2使用 rowSelection 控制 */
|
||||
...(enableMultiple ? {selectable: true, multiple: true} : {}),
|
||||
primaryField: primaryField,
|
||||
loadType: 'pagination',
|
||||
api: listApi,
|
||||
...(enableBulkEdit ? {quickSaveApi: bulkEditApi} : {}),
|
||||
...(enableEdit ? {quickSaveItemApi: editApi} : {}),
|
||||
|
@ -67,7 +67,7 @@ export interface DSBuilderInterface<
|
||||
filterByFeat(feat: any): boolean;
|
||||
|
||||
/** 根据schema,判断是否匹配当前数据源 */
|
||||
match(schema?: any): boolean;
|
||||
match(schema?: any, key?: string): boolean;
|
||||
|
||||
/** 当前上下文中使用的字段 */
|
||||
getContextFields(options: T): Promise<any>;
|
||||
@ -209,7 +209,7 @@ export abstract class DSBuilder<T extends DSBuilderBaseOptions>
|
||||
return feat && this.features.includes(feat);
|
||||
}
|
||||
|
||||
abstract match(schema?: any): boolean;
|
||||
abstract match(schema?: any, key?: string): boolean;
|
||||
|
||||
abstract getContextFields(options: T): Promise<any>;
|
||||
|
||||
|
@ -4,7 +4,10 @@
|
||||
*/
|
||||
|
||||
import {builderFactory, DSBuilderInterface} from './DSBuilder';
|
||||
import {EditorManager} from 'amis-editor-core';
|
||||
|
||||
import type {EditorManager} from 'amis-editor-core';
|
||||
import type {GenericSchema} from './type';
|
||||
import type {Option} from 'amis-core';
|
||||
|
||||
export class DSBuilderManager {
|
||||
private builders: Map<string, DSBuilderInterface>;
|
||||
@ -42,6 +45,11 @@ export class DSBuilderManager {
|
||||
return builder ? builder : this.getDefaultBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认构建器Key
|
||||
*
|
||||
* @returns 返回默认构建器Key
|
||||
*/
|
||||
getDefaultBuilderKey() {
|
||||
const collections = Array.from(this.builders.entries()).filter(
|
||||
([_, builder]) => builder?.disabledOn?.() !== true
|
||||
@ -56,6 +64,11 @@ export class DSBuilderManager {
|
||||
return defaultKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认构建器
|
||||
*
|
||||
* @returns {Object} 默认构建器
|
||||
*/
|
||||
getDefaultBuilder() {
|
||||
const collections = Array.from(this.builders.entries()).filter(
|
||||
([_, builder]) => builder?.disabledOn?.() !== true
|
||||
@ -70,6 +83,11 @@ export class DSBuilderManager {
|
||||
return defaultBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可用的构建器列表
|
||||
*
|
||||
* @returns 返回可用构建器的列表
|
||||
*/
|
||||
getAvailableBuilders() {
|
||||
return Array.from(this.builders.entries())
|
||||
.filter(([_, builder]) => builder?.disabledOn?.() !== true)
|
||||
@ -78,24 +96,65 @@ export class DSBuilderManager {
|
||||
});
|
||||
}
|
||||
|
||||
getDSSelectorSchema(patch: Record<string, any>) {
|
||||
/**
|
||||
* 获取数据选择器Schema
|
||||
*
|
||||
* @param patch - 需要进行补丁修复的配置对象
|
||||
* @param config - 包含运行上下文和源键的配置对象
|
||||
* @returns 返回一个对象,包含类型、标签、名称、可见性、选项、默认值和pipeIn等属性
|
||||
*/
|
||||
getDSSelectorSchema(
|
||||
patch: Record<string, any>,
|
||||
config?: {
|
||||
/** 组件 Schema */
|
||||
schema: GenericSchema;
|
||||
/** 组件数据源 Key */
|
||||
sourceKey: string;
|
||||
/** 获取默认值函数 */
|
||||
getDefautlValue?: (key: string, builder: DSBuilderInterface) => Boolean;
|
||||
}
|
||||
) {
|
||||
const {schema, sourceKey, getDefautlValue} = config || {};
|
||||
const builders = this.getAvailableBuilders();
|
||||
const options = builders.map(([key, builder]) => ({
|
||||
label: builder.name,
|
||||
value: key
|
||||
}));
|
||||
let defaultValue: string | undefined = schema?.dsType;
|
||||
const options: Option[] = [];
|
||||
|
||||
for (const [key, builder] of builders) {
|
||||
if (schema && !defaultValue) {
|
||||
if (
|
||||
getDefautlValue &&
|
||||
typeof getDefautlValue === 'function' &&
|
||||
getDefautlValue(key, builder)
|
||||
) {
|
||||
defaultValue = key;
|
||||
} else if (builder.match(schema, sourceKey)) {
|
||||
defaultValue = key;
|
||||
}
|
||||
}
|
||||
|
||||
options.push({
|
||||
label: builder.name,
|
||||
value: key
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'radios',
|
||||
label: '数据来源',
|
||||
name: 'dsType',
|
||||
visible: options.length > 0,
|
||||
selectFirst: true,
|
||||
options: options,
|
||||
...(defaultValue ? {value: defaultValue} : {}),
|
||||
...patch
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 从构建器中生成集合
|
||||
*
|
||||
* @param callback 回调函数,用于处理每个构建器、构建器键和索引
|
||||
* @returns 返回生成的集合
|
||||
*/
|
||||
buildCollectionFromBuilders(
|
||||
callback: (
|
||||
builder: DSBuilderInterface,
|
||||
|
@ -128,3 +128,7 @@ export const FormOperatorMap: Record<FormOperatorValue, FormOperator> = {
|
||||
};
|
||||
|
||||
export const ModelDSBuilderKey = 'model-entity';
|
||||
|
||||
export const ApiDSBuilderKey = 'api';
|
||||
|
||||
export const ApiCenterDSBuilderKey = 'apicenter';
|
||||
|
@ -25,7 +25,8 @@ import {
|
||||
DSBuilderManager,
|
||||
DSFeatureEnum,
|
||||
DSFeatureType,
|
||||
ModelDSBuilderKey
|
||||
ModelDSBuilderKey,
|
||||
ApiDSBuilderKey
|
||||
} from '../../builder';
|
||||
import {
|
||||
getEventControlConfig,
|
||||
@ -58,11 +59,11 @@ export class BaseCRUDPlugin extends BasePlugin {
|
||||
|
||||
rendererName = 'crud2';
|
||||
|
||||
name = '增删改查';
|
||||
name = '表格2.0';
|
||||
|
||||
panelTitle = '增删改查';
|
||||
panelTitle = '表格2.0';
|
||||
|
||||
subPanelTitle = '增删改查';
|
||||
subPanelTitle = '表格2.0';
|
||||
|
||||
icon = 'fa fa-table';
|
||||
|
||||
@ -320,6 +321,9 @@ export class BaseCRUDPlugin extends BasePlugin {
|
||||
scaffoldConfig: config
|
||||
});
|
||||
|
||||
/** 脚手架构建的 Schema 加个标识符,避免addChild替换 Schema ID */
|
||||
schema.__origin = 'scaffold';
|
||||
|
||||
return schema;
|
||||
},
|
||||
validate: (data: CRUDScaffoldConfig, form: IFormStore) => {
|
||||
@ -515,13 +519,11 @@ export class BaseCRUDPlugin extends BasePlugin {
|
||||
renderBasicPropsCollapse(context: BuildPanelEventContext) {
|
||||
/** 动态加载的配置集合 */
|
||||
const dc = this.dynamicControls;
|
||||
|
||||
return {
|
||||
title: '基本',
|
||||
order: 1,
|
||||
body: [
|
||||
/** 数据源类型 */
|
||||
this.dsManager.getDSSelectorSchema({
|
||||
/** 数据源控件 */
|
||||
const generateDSControls = () => {
|
||||
/** 数据源类型 */
|
||||
const dsTypeSelector = this.dsManager.getDSSelectorSchema(
|
||||
{
|
||||
type: 'select',
|
||||
label: '数据源',
|
||||
onChange: (
|
||||
@ -546,12 +548,19 @@ export class BaseCRUDPlugin extends BasePlugin {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}),
|
||||
/** 数据源配置 */
|
||||
...this.dsManager.buildCollectionFromBuilders((builder, builderKey) => {
|
||||
},
|
||||
{schema: context?.schema, sourceKey: 'api'}
|
||||
);
|
||||
/** 默认数据源类型 */
|
||||
const defaultDsType = dsTypeSelector.value;
|
||||
/** 数据源配置 */
|
||||
const dsSettings = this.dsManager.buildCollectionFromBuilders(
|
||||
(builder, builderKey) => {
|
||||
return {
|
||||
type: 'container',
|
||||
visibleOn: `data.dsType == null || data.dsType === '${builderKey}'`,
|
||||
visibleOn: `data.dsType == null ? '${builderKey}' === '${
|
||||
defaultDsType || ApiDSBuilderKey
|
||||
}' : data.dsType === '${builderKey}'`,
|
||||
body: builder.makeSourceSettingForm({
|
||||
feat: 'List',
|
||||
renderer: 'crud',
|
||||
@ -563,9 +572,55 @@ export class BaseCRUDPlugin extends BasePlugin {
|
||||
/** 因为会使用 container 包裹,所以加一个 margin-bottom */
|
||||
className: 'mb-3'
|
||||
};
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
return [dsTypeSelector, ...dsSettings];
|
||||
};
|
||||
|
||||
return {
|
||||
title: '基本',
|
||||
order: 1,
|
||||
body: [
|
||||
...generateDSControls(),
|
||||
/** 主键配置,TODO:支持联合主键 */
|
||||
dc?.primaryField?.(context),
|
||||
/** 可选择配置,这里的配置会覆盖底层 Table 的 rowSelection 中的配置 */
|
||||
getSchemaTpl('switch', {
|
||||
name: 'selectable',
|
||||
label: tipedLabel('可选择', '开启后支持选择表格行数据'),
|
||||
pipeIn: (value: boolean | undefined, formStore: IFormStore) => {
|
||||
if (typeof value === 'boolean') {
|
||||
return value;
|
||||
}
|
||||
|
||||
const rowSelection = formStore?.data?.rowSelection;
|
||||
return rowSelection && isObject(rowSelection);
|
||||
}
|
||||
}),
|
||||
{
|
||||
type: 'container',
|
||||
className: 'ae-ExtendMore mb-3',
|
||||
visibleOn:
|
||||
"data.selectable || (data.rowSelection && data.rowSelection?.type !== 'radio')",
|
||||
body: [
|
||||
getSchemaTpl('switch', {
|
||||
name: 'multiple',
|
||||
label: '可多选',
|
||||
pipeIn: (value: boolean | undefined, formStore: IFormStore) => {
|
||||
if (typeof value === 'boolean') {
|
||||
return value;
|
||||
}
|
||||
|
||||
const rowSelection = formStore?.data?.rowSelection;
|
||||
|
||||
return rowSelection && isObject(rowSelection)
|
||||
? rowSelection.type !== 'radio'
|
||||
: false;
|
||||
}
|
||||
})
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'placeholder',
|
||||
pipeIn: defaultValue('暂无数据'),
|
||||
|
@ -25,7 +25,8 @@ import {
|
||||
DSFeatureType,
|
||||
DSBuilderManager,
|
||||
DSFeatureEnum,
|
||||
ModelDSBuilderKey
|
||||
ModelDSBuilderKey,
|
||||
ApiDSBuilderKey
|
||||
} from '../../builder';
|
||||
import {FormOperatorMap} from '../../builder/constants';
|
||||
import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
@ -538,6 +539,9 @@ export class FormPlugin extends BasePlugin {
|
||||
scaffoldConfig: config
|
||||
});
|
||||
|
||||
/** 脚手架构建的 Schema 加个标识符,避免addChild替换 Schema ID */
|
||||
schema.__origin = 'scaffold';
|
||||
|
||||
return schema;
|
||||
},
|
||||
validate: (data: FormScaffoldConfig, form: IFormStore) => {
|
||||
@ -625,6 +629,89 @@ export class FormPlugin extends BasePlugin {
|
||||
).startsWith('model://')) &&
|
||||
!schema.api.strategy;
|
||||
|
||||
/** 数据源控件 */
|
||||
const generateDSControls = () => {
|
||||
const dsTypeSelector = this.dsManager.getDSSelectorSchema(
|
||||
{
|
||||
type: 'select',
|
||||
label: '数据源',
|
||||
onChange: (
|
||||
value: string,
|
||||
oldValue: string,
|
||||
model: IFormItemStore,
|
||||
form: IFormStore
|
||||
) => {
|
||||
if (value !== oldValue) {
|
||||
const data = form.data;
|
||||
|
||||
Object.keys(data).forEach(key => {
|
||||
if (
|
||||
/^(insert|edit|bulkEdit)Fields$/i.test(key) ||
|
||||
/^(insert|edit|bulkEdit)Api$/i.test(key)
|
||||
) {
|
||||
form.deleteValueByName(key);
|
||||
}
|
||||
});
|
||||
form.deleteValueByName('__fields');
|
||||
form.deleteValueByName('__relations');
|
||||
form.deleteValueByName('initApi');
|
||||
form.deleteValueByName('api');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
{
|
||||
schema: context?.schema,
|
||||
sourceKey: 'api',
|
||||
getDefautlValue: (key, builder) => {
|
||||
const schema = context?.schema;
|
||||
let dsType = schema?.dsType;
|
||||
|
||||
// TODO: api和initApi可能是混合模式的场景
|
||||
if (
|
||||
builder.match(schema, 'api') ||
|
||||
builder.match(schema, 'initApi')
|
||||
) {
|
||||
dsType = key;
|
||||
}
|
||||
|
||||
return dsType;
|
||||
}
|
||||
}
|
||||
);
|
||||
/** 默认数据源类型 */
|
||||
const defaultDsType = dsTypeSelector.value;
|
||||
/** 数据源配置 */
|
||||
const dsSettings = flatten(
|
||||
this.Features.map(feat =>
|
||||
this.dsManager.buildCollectionFromBuilders(
|
||||
(builder, builderKey, index) => ({
|
||||
type: 'container',
|
||||
className: 'form-item-gap',
|
||||
visibleOn: `data.feat === '${
|
||||
feat.value
|
||||
}' && (data.dsType == null ? '${builderKey}' === '${
|
||||
defaultDsType || ApiDSBuilderKey
|
||||
}' : data.dsType === '${builderKey}')`,
|
||||
body: flatten([
|
||||
builder.makeSourceSettingForm({
|
||||
feat: feat.value,
|
||||
renderer: 'form',
|
||||
inScaffold: false,
|
||||
sourceSettings: {
|
||||
renderLabel: true,
|
||||
userOrders: false
|
||||
}
|
||||
})
|
||||
])
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return [dsTypeSelector, ...dsSettings];
|
||||
};
|
||||
|
||||
return [
|
||||
getSchemaTpl('tabs', [
|
||||
{
|
||||
@ -639,8 +726,25 @@ export class FormPlugin extends BasePlugin {
|
||||
type: 'select',
|
||||
name: 'feat',
|
||||
label: '使用场景',
|
||||
value: DSFeatureEnum.Insert,
|
||||
options: this.Features,
|
||||
pipeIn: (
|
||||
value: FormPluginFeat | undefined,
|
||||
formStore: IFormStore
|
||||
) => {
|
||||
let feat = value;
|
||||
|
||||
if (!value) {
|
||||
feat =
|
||||
formStore?.data?.initApi != null
|
||||
? DSFeatureEnum.Edit
|
||||
: DSFeatureEnum.Insert;
|
||||
}
|
||||
|
||||
/** 存量数据可能未设置过feat, 需要在数据域中 set 一下 */
|
||||
formStore.setValueByName('feat', feat);
|
||||
|
||||
return feat;
|
||||
},
|
||||
onChange: (
|
||||
value: FormPluginFeat,
|
||||
oldValue: FormPluginFeat,
|
||||
@ -660,83 +764,7 @@ export class FormPlugin extends BasePlugin {
|
||||
}
|
||||
}
|
||||
},
|
||||
this.dsManager.getDSSelectorSchema({
|
||||
type: 'select',
|
||||
label: '数据源',
|
||||
pipeIn: (value: any, form: any) => {
|
||||
if (value !== undefined) {
|
||||
return value;
|
||||
}
|
||||
|
||||
const api = form.data?.api || form.data?.initApi;
|
||||
let dsType = 'api';
|
||||
|
||||
if (!api) {
|
||||
} else if (typeof api === 'string') {
|
||||
dsType = api.startsWith('api://')
|
||||
? 'apicenter'
|
||||
: 'api';
|
||||
} else if (api?.url) {
|
||||
dsType = api.url.startsWith('api://')
|
||||
? 'apicenter'
|
||||
: 'api';
|
||||
} else if (api?.entity) {
|
||||
dsType = ModelDSBuilderKey;
|
||||
}
|
||||
|
||||
// 需要 set 一下,否则 buildCollectionFromBuilders 里的内容条件不满足
|
||||
form.setValueByName('dsType', dsType);
|
||||
|
||||
return dsType;
|
||||
},
|
||||
onChange: (
|
||||
value: string,
|
||||
oldValue: string,
|
||||
model: IFormItemStore,
|
||||
form: IFormStore
|
||||
) => {
|
||||
if (value !== oldValue) {
|
||||
const data = form.data;
|
||||
|
||||
Object.keys(data).forEach(key => {
|
||||
if (
|
||||
/^(insert|edit|bulkEdit)Fields$/i.test(key) ||
|
||||
/^(insert|edit|bulkEdit)Api$/i.test(key)
|
||||
) {
|
||||
form.deleteValueByName(key);
|
||||
}
|
||||
});
|
||||
form.deleteValueByName('__fields');
|
||||
form.deleteValueByName('__relations');
|
||||
form.deleteValueByName('initApi');
|
||||
form.deleteValueByName('api');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}),
|
||||
/** 数据源配置 */
|
||||
...flatten(
|
||||
this.Features.map(feat =>
|
||||
this.dsManager.buildCollectionFromBuilders(
|
||||
(builder, builderKey, index) => ({
|
||||
type: 'container',
|
||||
className: 'form-item-gap',
|
||||
visibleOn: `data.feat === '${feat.value}' && (data.dsType === '${builderKey}' || (!data.dsType && ${index} === 0))`,
|
||||
body: flatten([
|
||||
builder.makeSourceSettingForm({
|
||||
feat: feat.value,
|
||||
renderer: 'form',
|
||||
inScaffold: false,
|
||||
sourceSettings: {
|
||||
renderLabel: true,
|
||||
userOrders: false
|
||||
}
|
||||
})
|
||||
])
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
...generateDSControls()
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
tipedLabel
|
||||
} from 'amis-editor-core';
|
||||
import {DSBuilderManager} from '../builder/DSBuilderManager';
|
||||
import {DSFeatureEnum, ModelDSBuilderKey} from '../builder';
|
||||
import {DSFeatureEnum, ModelDSBuilderKey, ApiDSBuilderKey} from '../builder';
|
||||
import {getEventControlConfig} from '../renderer/event-control/helper';
|
||||
|
||||
import type {
|
||||
@ -186,66 +186,75 @@ export class ServicePlugin extends BasePlugin {
|
||||
|
||||
panelBodyCreator = (context: BaseEventContext) => {
|
||||
const dsManager = this.dsManager;
|
||||
/** 数据来源选择器 */
|
||||
const dsTypeSelect = () =>
|
||||
dsManager.getDSSelectorSchema({
|
||||
type: 'select',
|
||||
mode: 'horizontal',
|
||||
horizontal: {
|
||||
justify: true,
|
||||
left: 'col-sm-4'
|
||||
},
|
||||
onChange: (value: any, oldValue: any, model: any, form: any) => {
|
||||
if (value !== oldValue) {
|
||||
const data = form.data;
|
||||
Object.keys(data).forEach(key => {
|
||||
if (
|
||||
key?.toLowerCase()?.endsWith('fields') ||
|
||||
key?.toLowerCase().endsWith('api')
|
||||
) {
|
||||
form.deleteValueByName(key);
|
||||
}
|
||||
});
|
||||
form.deleteValueByName('__fields');
|
||||
form.deleteValueByName('__relations');
|
||||
form.setValueByName('api', undefined);
|
||||
/** 数据源控件 */
|
||||
const generateDSControls = () => {
|
||||
const dsTypeSelector = dsManager.getDSSelectorSchema(
|
||||
{
|
||||
type: 'select',
|
||||
mode: 'horizontal',
|
||||
horizontal: {
|
||||
justify: true,
|
||||
left: 'col-sm-4'
|
||||
},
|
||||
onChange: (value: any, oldValue: any, model: any, form: any) => {
|
||||
if (value !== oldValue) {
|
||||
const data = form.data;
|
||||
Object.keys(data).forEach(key => {
|
||||
if (
|
||||
key?.toLowerCase()?.endsWith('fields') ||
|
||||
key?.toLowerCase().endsWith('api')
|
||||
) {
|
||||
form.deleteValueByName(key);
|
||||
}
|
||||
});
|
||||
form.deleteValueByName('__fields');
|
||||
form.deleteValueByName('__relations');
|
||||
form.setValueByName('api', undefined);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
});
|
||||
/** 数据源配置 */
|
||||
const dsSetting = dsManager.buildCollectionFromBuilders(
|
||||
(builder, builderKey) => {
|
||||
return {
|
||||
type: 'container',
|
||||
visibleOn: `this.dsType == null || this.dsType === '${builderKey}'`,
|
||||
body: flattenDeep([
|
||||
builder.makeSourceSettingForm({
|
||||
feat: 'View',
|
||||
renderer: 'service',
|
||||
inScaffold: false,
|
||||
sourceSettings: {
|
||||
name: 'api',
|
||||
label: '接口配置',
|
||||
mode: 'horizontal',
|
||||
...(builderKey === 'api' || builderKey === 'apicenter'
|
||||
? {
|
||||
horizontalConfig: {
|
||||
labelAlign: 'left',
|
||||
horizontal: {
|
||||
justify: true,
|
||||
left: 4
|
||||
},
|
||||
{schema: context?.schema, sourceKey: 'api'}
|
||||
);
|
||||
/** 默认数据源类型 */
|
||||
const defaultDsType = dsTypeSelector.value;
|
||||
const dsSettings = dsManager.buildCollectionFromBuilders(
|
||||
(builder, builderKey) => {
|
||||
return {
|
||||
type: 'container',
|
||||
visibleOn: `data.dsType == null ? '${builderKey}' === '${
|
||||
defaultDsType || ApiDSBuilderKey
|
||||
}' : data.dsType === '${builderKey}'`,
|
||||
body: flattenDeep([
|
||||
builder.makeSourceSettingForm({
|
||||
feat: 'View',
|
||||
renderer: 'service',
|
||||
inScaffold: false,
|
||||
sourceSettings: {
|
||||
name: 'api',
|
||||
label: '接口配置',
|
||||
mode: 'horizontal',
|
||||
...(builderKey === 'api' || builderKey === 'apicenter'
|
||||
? {
|
||||
horizontalConfig: {
|
||||
labelAlign: 'left',
|
||||
horizontal: {
|
||||
justify: true,
|
||||
left: 4
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
: {}),
|
||||
useFieldManager: builderKey === ModelDSBuilderKey
|
||||
}
|
||||
})
|
||||
])
|
||||
};
|
||||
}
|
||||
);
|
||||
: {}),
|
||||
useFieldManager: builderKey === ModelDSBuilderKey
|
||||
}
|
||||
})
|
||||
])
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
return [dsTypeSelector, ...dsSettings];
|
||||
};
|
||||
|
||||
return getSchemaTpl('tabs', [
|
||||
{
|
||||
@ -257,8 +266,7 @@ export class ServicePlugin extends BasePlugin {
|
||||
title: '基本',
|
||||
body: [
|
||||
getSchemaTpl('layout:originPosition', {value: 'left-top'}),
|
||||
dsTypeSelect(),
|
||||
...dsSetting
|
||||
...generateDSControls()
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -30,6 +30,7 @@ import {
|
||||
import {resolveArrayDatasource} from '../util';
|
||||
|
||||
import type {SchemaObject} from 'amis';
|
||||
import type {IFormItemStore, IFormStore} from 'amis-core';
|
||||
import type {EditorManager} from 'amis-editor-core';
|
||||
|
||||
export const Table2RenderereEvent: RendererPluginEvent[] = [
|
||||
@ -741,7 +742,7 @@ export class Table2Plugin extends BasePlugin {
|
||||
}
|
||||
|
||||
panelBodyCreator = (context: BaseEventContext) => {
|
||||
const isCRUDBody = this.isCRUDContext(context);
|
||||
const isCRUDContext = this.isCRUDContext(context);
|
||||
const dc = this.dynamicControls;
|
||||
|
||||
return getSchemaTpl('tabs', [
|
||||
@ -755,13 +756,13 @@ export class Table2Plugin extends BasePlugin {
|
||||
getSchemaTpl('layout:originPosition', {value: 'left-top'}),
|
||||
getSchemaTpl('formulaControl', {
|
||||
label: tipedLabel('数据源', '绑定当前上下文变量'),
|
||||
hidden: isCRUDBody,
|
||||
hidden: isCRUDContext,
|
||||
name: 'source',
|
||||
pipeIn: defaultValue('${items}')
|
||||
}),
|
||||
dc?.primaryField?.(context),
|
||||
isCRUDBody ? null : dc?.quickSaveApi?.(context),
|
||||
isCRUDBody ? null : dc?.quickSaveItemApi?.(context),
|
||||
isCRUDContext ? null : dc?.primaryField?.(context),
|
||||
isCRUDContext ? null : dc?.quickSaveApi?.(context),
|
||||
isCRUDContext ? null : dc?.quickSaveItemApi?.(context),
|
||||
getSchemaTpl('switch', {
|
||||
name: 'title',
|
||||
label: '显示标题',
|
||||
@ -824,7 +825,7 @@ export class Table2Plugin extends BasePlugin {
|
||||
}
|
||||
}),
|
||||
getSchemaTpl('tablePlaceholder', {
|
||||
hidden: isCRUDBody
|
||||
hidden: isCRUDContext
|
||||
})
|
||||
// TODD: 组件功能没有支持,暂时隐藏
|
||||
// {
|
||||
@ -844,7 +845,7 @@ export class Table2Plugin extends BasePlugin {
|
||||
pipeIn: (value: any) => !!value,
|
||||
pipeOut: (value: any) => value
|
||||
}),
|
||||
isCRUDBody
|
||||
isCRUDContext
|
||||
? null
|
||||
: {
|
||||
type: 'ae-Switch-More',
|
||||
@ -894,28 +895,44 @@ export class Table2Plugin extends BasePlugin {
|
||||
mode: 'normal',
|
||||
name: 'rowSelection',
|
||||
label: '可选择',
|
||||
visibleOn: 'data.selectable',
|
||||
hiddenOnDefault: true,
|
||||
formType: 'extend',
|
||||
form: {
|
||||
body: [
|
||||
dc?.rowSelectionKeyField?.(context),
|
||||
{
|
||||
name: 'rowSelection.type',
|
||||
label: '选择类型',
|
||||
type: 'button-group-select',
|
||||
options: [
|
||||
{
|
||||
label: '多选',
|
||||
value: 'checkbox'
|
||||
/** 如果为 CRUD 背景下,主键配置、选择类型在 CRUD 面板中,此处应该隐藏 */
|
||||
isCRUDContext
|
||||
? null
|
||||
: dc?.rowSelectionKeyField?.(context),
|
||||
isCRUDContext
|
||||
? null
|
||||
: {
|
||||
name: 'rowSelection.type',
|
||||
label: '选择类型',
|
||||
type: 'button-group-select',
|
||||
options: [
|
||||
{
|
||||
label: '多选',
|
||||
value: 'checkbox'
|
||||
},
|
||||
{
|
||||
label: '单选',
|
||||
value: 'radio'
|
||||
}
|
||||
],
|
||||
pipeIn: (value: any, formStore: IFormStore) => {
|
||||
if (value != null && typeof value === 'string') {
|
||||
return value;
|
||||
}
|
||||
|
||||
const schema = formStore?.data;
|
||||
|
||||
return schema?.selectable === true
|
||||
? schema.multiple
|
||||
? 'checkbox'
|
||||
: 'radio'
|
||||
: 'checkbox';
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '单选',
|
||||
value: 'radio'
|
||||
}
|
||||
],
|
||||
pipeIn: defaultValue('checkbox')
|
||||
},
|
||||
getSchemaTpl('switch', {
|
||||
name: 'rowSelection.fixed',
|
||||
label: '固定选择列'
|
||||
@ -980,7 +997,7 @@ export class Table2Plugin extends BasePlugin {
|
||||
}));
|
||||
}
|
||||
}
|
||||
]
|
||||
].filter(Boolean)
|
||||
}
|
||||
},
|
||||
getSchemaTpl('formulaControl', {
|
||||
|
@ -439,6 +439,7 @@ export class FieldSetting extends React.Component<
|
||||
className={'w-full'}
|
||||
hasError={!!fieldState.error}
|
||||
searchable
|
||||
simpleValue
|
||||
disabled={false}
|
||||
clearable={false}
|
||||
popOverContainer={popOverContainer}
|
||||
@ -522,6 +523,7 @@ export class FieldSetting extends React.Component<
|
||||
className={'w-full'}
|
||||
hasError={!!fieldState.error}
|
||||
searchable
|
||||
simpleValue
|
||||
disabled={false}
|
||||
clearable={false}
|
||||
popOverContainer={popOverContainer}
|
||||
|
@ -1695,6 +1695,7 @@ setSchemaTpl('anchorNavTitle', {
|
||||
required: true
|
||||
});
|
||||
|
||||
/** 给 CRUD2 使用 */
|
||||
setSchemaTpl('primaryField', {
|
||||
type: 'input-text',
|
||||
name: 'primaryField',
|
||||
@ -1702,5 +1703,17 @@ setSchemaTpl('primaryField', {
|
||||
'主键',
|
||||
'每行记录的唯一标识符,通常用于行选择、批量操作等场景。'
|
||||
),
|
||||
pipeIn: defaultValue('id')
|
||||
pipeIn: (value: any, formStore: any) => {
|
||||
const rowSelection = formStore?.data?.rowSelection;
|
||||
|
||||
if (value == null || typeof value !== 'string') {
|
||||
return rowSelection &&
|
||||
rowSelection?.keyField &&
|
||||
typeof rowSelection.keyField === 'string'
|
||||
? rowSelection?.keyField
|
||||
: 'id';
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
});
|
||||
|
@ -126,6 +126,7 @@
|
||||
margin-left: px2rem(4px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&-singleValue {
|
||||
|
Loading…
Reference in New Issue
Block a user