From d8e4d31fc21d6929f24b1f38e8da8579a4518501 Mon Sep 17 00:00:00 2001 From: lurunze1226 Date: Wed, 20 Sep 2023 21:33:27 +0800 Subject: [PATCH] =?UTF-8?q?fix(amis-editor):=20=E6=95=B0=E6=8D=AE=E6=BA=90?= =?UTF-8?q?=E6=9E=84=E9=80=A0=E5=99=A8=E5=85=BC=E5=AE=B9=E5=8E=86=E5=8F=B2?= =?UTF-8?q?=E5=AD=98=E9=87=8FSchema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/amis-editor-core/src/util.ts | 4 +- .../amis-editor/src/builder/ApiDSBuilder.ts | 36 ++-- packages/amis-editor/src/builder/DSBuilder.ts | 4 +- .../src/builder/DSBuilderManager.ts | 73 ++++++- packages/amis-editor/src/builder/constants.ts | 4 + .../amis-editor/src/plugin/CRUD2/BaseCRUD.tsx | 87 ++++++-- packages/amis-editor/src/plugin/Form/Form.tsx | 186 ++++++++++-------- packages/amis-editor/src/plugin/Service.tsx | 128 ++++++------ packages/amis-editor/src/plugin/Table2.tsx | 67 ++++--- .../amis-editor/src/renderer/FieldSetting.tsx | 2 + packages/amis-editor/src/tpl/common.tsx | 15 +- .../amis-ui/scss/components/_result-box.scss | 1 + 12 files changed, 397 insertions(+), 210 deletions(-) diff --git a/packages/amis-editor-core/src/util.ts b/packages/amis-editor-core/src/util.ts index b7cc0164b..217ee713d 100644 --- a/packages/amis-editor-core/src/util.ts +++ b/packages/amis-editor-core/src/util.ts @@ -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(); } diff --git a/packages/amis-editor/src/builder/ApiDSBuilder.ts b/packages/amis-editor/src/builder/ApiDSBuilder.ts index f99258c81..5cc2ba286 100644 --- a/packages/amis-editor/src/builder/ApiDSBuilder.ts +++ b/packages/amis-editor/src/builder/ApiDSBuilder.ts @@ -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} : {}), diff --git a/packages/amis-editor/src/builder/DSBuilder.ts b/packages/amis-editor/src/builder/DSBuilder.ts index aae22795e..20e9a311e 100644 --- a/packages/amis-editor/src/builder/DSBuilder.ts +++ b/packages/amis-editor/src/builder/DSBuilder.ts @@ -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; @@ -209,7 +209,7 @@ export abstract class DSBuilder return feat && this.features.includes(feat); } - abstract match(schema?: any): boolean; + abstract match(schema?: any, key?: string): boolean; abstract getContextFields(options: T): Promise; diff --git a/packages/amis-editor/src/builder/DSBuilderManager.ts b/packages/amis-editor/src/builder/DSBuilderManager.ts index bcaaafd6b..7d14d0109 100644 --- a/packages/amis-editor/src/builder/DSBuilderManager.ts +++ b/packages/amis-editor/src/builder/DSBuilderManager.ts @@ -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; @@ -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) { + /** + * 获取数据选择器Schema + * + * @param patch - 需要进行补丁修复的配置对象 + * @param config - 包含运行上下文和源键的配置对象 + * @returns 返回一个对象,包含类型、标签、名称、可见性、选项、默认值和pipeIn等属性 + */ + getDSSelectorSchema( + patch: Record, + 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, diff --git a/packages/amis-editor/src/builder/constants.ts b/packages/amis-editor/src/builder/constants.ts index 5dd259aa7..ca937f51a 100644 --- a/packages/amis-editor/src/builder/constants.ts +++ b/packages/amis-editor/src/builder/constants.ts @@ -128,3 +128,7 @@ export const FormOperatorMap: Record = { }; export const ModelDSBuilderKey = 'model-entity'; + +export const ApiDSBuilderKey = 'api'; + +export const ApiCenterDSBuilderKey = 'apicenter'; diff --git a/packages/amis-editor/src/plugin/CRUD2/BaseCRUD.tsx b/packages/amis-editor/src/plugin/CRUD2/BaseCRUD.tsx index 545d330a9..80f625f6f 100644 --- a/packages/amis-editor/src/plugin/CRUD2/BaseCRUD.tsx +++ b/packages/amis-editor/src/plugin/CRUD2/BaseCRUD.tsx @@ -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('暂无数据'), diff --git a/packages/amis-editor/src/plugin/Form/Form.tsx b/packages/amis-editor/src/plugin/Form/Form.tsx index 912d08aed..e08815fb2 100644 --- a/packages/amis-editor/src/plugin/Form/Form.tsx +++ b/packages/amis-editor/src/plugin/Form/Form.tsx @@ -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() ] }, { diff --git a/packages/amis-editor/src/plugin/Service.tsx b/packages/amis-editor/src/plugin/Service.tsx index eb4b82e30..a87b77c03 100644 --- a/packages/amis-editor/src/plugin/Service.tsx +++ b/packages/amis-editor/src/plugin/Service.tsx @@ -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() ] }, { diff --git a/packages/amis-editor/src/plugin/Table2.tsx b/packages/amis-editor/src/plugin/Table2.tsx index abab52be0..419e0e2f8 100644 --- a/packages/amis-editor/src/plugin/Table2.tsx +++ b/packages/amis-editor/src/plugin/Table2.tsx @@ -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', { diff --git a/packages/amis-editor/src/renderer/FieldSetting.tsx b/packages/amis-editor/src/renderer/FieldSetting.tsx index 0142441fe..99c6a7dd1 100644 --- a/packages/amis-editor/src/renderer/FieldSetting.tsx +++ b/packages/amis-editor/src/renderer/FieldSetting.tsx @@ -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} diff --git a/packages/amis-editor/src/tpl/common.tsx b/packages/amis-editor/src/tpl/common.tsx index 1fa2be180..fc522fa32 100644 --- a/packages/amis-editor/src/tpl/common.tsx +++ b/packages/amis-editor/src/tpl/common.tsx @@ -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; + } }); diff --git a/packages/amis-ui/scss/components/_result-box.scss b/packages/amis-ui/scss/components/_result-box.scss index 9d0039f20..e79610430 100644 --- a/packages/amis-ui/scss/components/_result-box.scss +++ b/packages/amis-ui/scss/components/_result-box.scss @@ -126,6 +126,7 @@ margin-left: px2rem(4px); display: flex; justify-content: center; + align-items: center; } &-singleValue {