From a16ab222adf5feed4161b5a554b81e15cf268287 Mon Sep 17 00:00:00 2001 From: wang-xh Date: Sat, 19 Jul 2025 11:41:54 +0800 Subject: [PATCH 1/9] =?UTF-8?q?fix:=20=E6=94=BE=E5=BC=80=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E5=B7=B2=E6=9C=89=E6=96=B9=E6=B3=95=EF=BC=9B=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E8=A1=A8=E5=8D=95=E6=A0=A1=E9=AA=8C=E6=96=87=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../composition/use-form-validation.ts | 24 +++++++++---------- .../types/toolbox/pc-rtc-toolbox.json | 6 ----- .../command-source.component.tsx | 13 +++++----- .../src/components/card-view.component.tsx | 2 +- 4 files changed, 19 insertions(+), 26 deletions(-) diff --git a/packages/designer/src/components/composition/use-form-validation.ts b/packages/designer/src/components/composition/use-form-validation.ts index 469513ac2fa..cb1f12cad5d 100644 --- a/packages/designer/src/components/composition/use-form-validation.ts +++ b/packages/designer/src/components/composition/use-form-validation.ts @@ -20,8 +20,8 @@ export function useFormValidation(useFormSchema: UseFormSchema, formCommandServi if (!vmCommand) { const controlInfo = useFormSchema.getControlBasicInfoMap().get(boundEvent.id); const controlName = (controlInfo && controlInfo.parentPathName) || boundEvent.id; - let msg = `控件【CCC】的【XXX】配置的命令已被移除,请重新选择。`; - msg = msg.replace('CCC', controlName).replace('XXX', boundEvent.eventName); + let msg = `【ControlName】的【EventName】绑定的命令已被移除,请重新选择。`; + msg = msg.replace('ControlName', controlName).replace('EventName', boundEvent.eventName); FMessageBoxService.warning(msg, ''); return false; } @@ -134,8 +134,8 @@ export function useFormValidation(useFormSchema: UseFormSchema, formCommandServi for (const communicationId of communicationIds) { const communication = communications.find(item => item.id === communicationId); if (!communication) { - let msg = `控件【CCC】配置的【XXX】已被移除,请重新选择。`; - msg = msg.replace('CCC', controlName).replace('XXX', boundEvent.eventName); + let msg = `【ControlName】的【EventName】绑定的通讯已被移除,请重新选择。`; + msg = msg.replace('ControlName', controlName).replace('EventName', boundEvent.eventName); FMessageBoxService.warning(msg, ''); return false; } @@ -144,15 +144,15 @@ export function useFormValidation(useFormSchema: UseFormSchema, formCommandServi const isSourceComplete = source && source.formId && source.componentId && source.event; const isTargetComplete = target && target.formId && target.commandCode; if (!isSourceComplete || !isTargetComplete) { - let msg = `控件【CCC】配置的组件通讯事件不完整,请检查。`; - msg = msg.replace('CCC', controlName); + let msg = `【ControlName】配置的组件通讯事件不完整,请检查。`; + msg = msg.replace('ControlName', controlName); FMessageBoxService.warning(msg, ''); return false; } // 检查通讯内的事件、名称等是否有效 if (!checkCommunicationSource(source) || !checkCommunicationTarget(target)) { - let msg = `控件【CCC】配置的组件通讯事件已失效,请检查。`; - msg = msg.replace('CCC', controlName); + let msg = `【ControlName】配置的组件通讯事件已失效,请检查。`; + msg = msg.replace('ControlName', controlName); FMessageBoxService.warning(msg, ''); return false; } @@ -162,15 +162,15 @@ export function useFormValidation(useFormSchema: UseFormSchema, formCommandServi for (const paramMapping of paramMappings) { const isParamValid = paramMapping.sourceValue && paramMapping.targetVariable; if (!isParamValid) { - let msg = `控件【CCC】配置的组件通讯事件参数不完整,请检查。`; - msg = msg.replace('CCC', controlName); + let msg = `【ControlName】配置的组件通讯事件参数不完整,请检查。`; + msg = msg.replace('ControlName', controlName); FMessageBoxService.warning(msg, ''); return false; } // 检查参是否数失效 if (!checkCommunicationTargetState(target, paramMapping)) { - let msg = `控件【CCC】配置的组件通讯事件参数已失效,请检查。`; - msg = msg.replace('CCC', controlName); + let msg = `【ControlName】配置的组件通讯事件参数已失效,请检查。`; + msg = msg.replace('ControlName', controlName); FMessageBoxService.warning(msg, ''); return false; } diff --git a/packages/designer/src/components/types/toolbox/pc-rtc-toolbox.json b/packages/designer/src/components/types/toolbox/pc-rtc-toolbox.json index 1a4128db789..2a5084fb695 100644 --- a/packages/designer/src/components/types/toolbox/pc-rtc-toolbox.json +++ b/packages/designer/src/components/types/toolbox/pc-rtc-toolbox.json @@ -122,12 +122,6 @@ "type": "content-container", "name": "容器", "category": "container" - }, - { - "id": "ExternalContainer", - "type": "external-container", - "name": "外部容器", - "category": "container" } ] }, diff --git a/packages/ui-vue/components/events-editor/src/components/command-source/command-source.component.tsx b/packages/ui-vue/components/events-editor/src/components/command-source/command-source.component.tsx index d1cc8ab2fa7..5c55649b082 100644 --- a/packages/ui-vue/components/events-editor/src/components/command-source/command-source.component.tsx +++ b/packages/ui-vue/components/events-editor/src/components/command-source/command-source.component.tsx @@ -179,15 +179,14 @@ export default defineComponent({
openMetadataSelector()}>引入控制器
- { useFormSchema.designerMode !== 'PC_RTC' && -
-
-
generateNewFunc()}>添加新方法
-
} - {/* {props.haveBoundCommand &&
+
+
+
generateNewFunc()}>添加新方法
+
+ {props.haveBoundCommand &&
showBoundEvents()}>已有方法
-
} */} +
} {shoulShowCommunication.value &&
openFormCommunicationPanel()}>添加组件通讯事件
diff --git a/packages/ui-vue/components/schema-selector/src/components/card-view.component.tsx b/packages/ui-vue/components/schema-selector/src/components/card-view.component.tsx index 070e165d858..506799e0bf2 100644 --- a/packages/ui-vue/components/schema-selector/src/components/card-view.component.tsx +++ b/packages/ui-vue/components/schema-selector/src/components/card-view.component.tsx @@ -37,7 +37,7 @@ export default defineComponent({ searchResult.value = resultItems; updateListViewDataScource(searchResult.value); - showPagination.value = !newValue; + // showPagination.value = !newValue; }); function renderListViewContent({ item, index, selectedItem }) { return ( -- Gitee From f9bf99e6fffa1a517abf2c7c85f87fcd5e41a451 Mon Sep 17 00:00:00 2001 From: wang-xh Date: Thu, 24 Jul 2025 17:00:16 +0800 Subject: [PATCH 2/9] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=BB=84=E5=90=88?= =?UTF-8?q?=E8=A1=A8=E5=8D=95=E9=80=9A=E8=AE=AF=E9=85=8D=E7=BD=AE=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=9B=E4=BF=AE=E6=94=B9=E8=BE=93=E5=85=A5=E6=8E=A7?= =?UTF-8?q?=E4=BB=B6=E7=A9=BA=E7=BB=91=E5=AE=9A=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../composition/use-update-controls.ts | 15 +-- .../components/code-view.component.tsx | 12 +-- .../composition/handler/frm-cmp-builder.ts | 92 +++++++++++----- .../composition/command.service.tsx | 15 ++- .../composition/events-editor-utils.ts | 6 +- .../composition/use-form-validation.ts | 24 ++--- .../composition/use-parameter-editor-data.ts | 23 ++-- .../src/composition/use-field-selection.ts | 17 ++- .../checkbox.property-config.ts | 33 +++++- .../split-form-component.component.tsx | 9 +- .../data-grid-column.property-config.ts | 2 +- .../src/schema/data-grid-column.schema.json | 5 +- .../src/schema/data-grid.schema.json | 5 +- .../date-picker.property-config.ts | 30 +++++- .../designer/form-group-use-designer-rules.ts | 4 +- .../combine-form/combine-form.component.tsx | 4 +- .../components/combine-form/combine-form.scss | 29 ++++- .../combine-form/select-command.component.tsx | 25 +++-- .../select-parameter.component.tsx | 35 +++--- .../select-source-control.component.tsx | 8 +- .../select-target-form.component.tsx | 6 +- .../command-source.component.tsx | 17 +-- .../command-source/command-source.css | 100 ++++++++++-------- .../external-container.design.component.tsx | 2 +- .../import-external-schema.component.tsx | 12 ++- .../src/designer/import-external-schema.css | 3 +- .../external-container.property-config.ts | 55 ++++++++-- .../response-layout-item-designer-rules.ts | 6 +- .../src/components/card-view.component.tsx | 11 +- .../src/components/list-view.component.tsx | 8 +- .../src/schema-selector-editor.component.tsx | 2 +- .../src/schema-selector.component.tsx | 22 +++- .../schema-selector/src/schema-selector.css | 1 - .../property-config/switch.property-config.ts | 49 +++++++-- 34 files changed, 478 insertions(+), 209 deletions(-) diff --git a/packages/designer/src/components/components/change-set/composition/use-update-controls.ts b/packages/designer/src/components/components/change-set/composition/use-update-controls.ts index 66901031eb1..cd5b36390a7 100644 --- a/packages/designer/src/components/components/change-set/composition/use-update-controls.ts +++ b/packages/designer/src/components/components/change-set/composition/use-update-controls.ts @@ -376,14 +376,17 @@ export function useUpdateControls( const fieldTypeName = updateChanges.find(c => c.propPath === 'type.name'); if (fieldTypeName) { control.editor.showTime = fieldTypeName.newValue === 'DateTime'; - if (!control.editor.showTime) { - control.editor.displayFormat = 'yyyy-MM-dd'; - if (control.formatter?.dateFormat) { - control.formatter.dateFormat = 'yyyy-MM-dd'; - } + const formatValue = control.editor.showTime ? 'yyyy-MM-dd HH:mm:ss' : 'yyyy-MM-dd'; + + control.editor.displayFormat = formatValue; + if (control.formatter?.dateFormat) { + control.formatter.dateFormat = formatValue; + } + if (control.editor.showTime) { + control.editor.valueFormat = formatValue; + } else { delete control.editor.valueFormat; } - } } diff --git a/packages/designer/src/components/components/code-view/components/code-view.component.tsx b/packages/designer/src/components/components/code-view/components/code-view.component.tsx index 7c641069eae..75315e983de 100644 --- a/packages/designer/src/components/components/code-view/components/code-view.component.tsx +++ b/packages/designer/src/components/components/code-view/components/code-view.component.tsx @@ -16,7 +16,7 @@ import { computed, defineComponent, inject, onMounted, onUnmounted, provide, ref, SetupContext, watch } from 'vue'; import { codeViewProps, CodeViewProps } from '../props/code-view.props'; import FNavTreeDesign from './nav-tree.component'; -import { FSplitter, FSplitterPane, FNotifyService, FLoadingService } from '@farris/ui-vue/components'; +import { FSplitter, FSplitterPane, FLoadingService } from '@farris/ui-vue/components'; import './code-view.scss'; import FDesignCodeTabs from './code-tabs.component'; import { EditorController } from '../composition/handler/editor.controller'; @@ -33,7 +33,7 @@ export default defineComponent({ props: codeViewProps, emits: ['changeView', 'saveAll'] as (string[] & ThisType) | undefined, setup(props: CodeViewProps, context: SetupContext) { - const notifyService: any = new FNotifyService(); + const messagerService: any = inject('FMessageBoxService'); const loadingService: any = inject('FLoadingService'); const formBasicInfo = ref(props.formBasicInfo); const frmCmpBuilder = new FrmCmpBuilder(formBasicInfo.value); @@ -167,7 +167,7 @@ export default defineComponent({ function openAndGoTo(data: any) { // console.log('打开并跳转', data, fileTreeInstance.value.controllers()); const { command, controller } = data; - if (controller) { + if (controller) { const controllerFileName = controller.label + '.ts'; const controllerFiles = flattenTreeData(fileTreeInstance.value.controllers() || []); @@ -179,7 +179,7 @@ export default defineComponent({ editorController.openFile(controllFile); filePath.value = controllFile.path; - editorController.sendNotification(controllFile.path, {eventName: 'GotoMethod', eventPayload: { methodCode: command.handlerName, methodName: command.name } }); + editorController.sendNotification(controllFile.path, { eventName: 'GotoMethod', eventPayload: { methodCode: command.handlerName, methodName: command.name } }); } } } @@ -233,10 +233,10 @@ export default defineComponent({ return; // 用户点击取消 } if (result.hasError) { - notifyService.error(result && result.errorTip || '构件创建失败,请刷新后重试'); + messagerService.error(result && result.errorTip || '构件创建失败,请刷新后重试'); } else { // 打开文件 - editorController.openFile(result); + editorController.openFile({ path: result.tsFilePath, webCommandId: result.webCommandId, webComponentId: result.webComponentId }); } if (result.hasNewFile) { fileTreeInstance.value.reloadTreeData(result.tsFilePath); diff --git a/packages/designer/src/components/components/code-view/composition/handler/frm-cmp-builder.ts b/packages/designer/src/components/components/code-view/composition/handler/frm-cmp-builder.ts index a3bdc7abae7..ce7dee7e067 100644 --- a/packages/designer/src/components/components/code-view/composition/handler/frm-cmp-builder.ts +++ b/packages/designer/src/components/components/code-view/composition/handler/frm-cmp-builder.ts @@ -20,6 +20,10 @@ export interface CmpBuildResult { hasError?: boolean; /** 错误提示信息 */ errorTip?: string; + /** web构件id,用于运行时定制场景 */ + webComponentId?: string; + /** 命令构件id,用于运行时定制场景 */ + webCommandId?: string; } /** 构件元数据基本信息 */ interface CmpBuildInfo { @@ -231,33 +235,53 @@ export class FrmCmpBuilder { buildInfo.tsFilePathName = '/' + buildInfo.relativePath + '/' + buildInfo.code + '.ts'; const webCmpFileName = buildInfo.code + '.webcmp'; const webCmdFileName = buildInfo.code + '.webcmd'; - let webCmp; - let webCmd; - this.metadataService.queryRelatedComponentMetadata(this.formBasicInfo.rtcId).then(data => { - webCmp = data.find(metadata => metadata.fileName === webCmpFileName); - webCmd = data.find(metadata => metadata.fileName === webCmdFileName); - }); - if (webCmp && webCmd) { - return { tsFilePath: buildInfo.tsFilePathName, hasNewFile: false }; - } - const createWebCmpError = !webCmp && (await this.createRtcWebCmp(buildInfo, webCmpFileName)); - if (createWebCmpError) { - return { - hasError: true, - errorTip: createWebCmpError, - tsFilePath: '', hasNewFile: true - }; + const componentData = await this.metadataService.queryRelatedComponentMetadata(this.formBasicInfo.rtcId); + + const webCmp = componentData?.find(metadata => metadata.fileName === webCmpFileName); + const webCmd = componentData?.find(metadata => metadata.fileName === webCmdFileName); + + let webComponentId = webCmp ? webCmp.id : ''; + let webCommandId = webCmd ? webCmd.id : ''; + let hasNewFile = false; + + // 创建web构件 + if (!webCmp) { + const result: any = await this.createRtcWebCmp(buildInfo, webCmpFileName); + if (result?.error) { + return { + hasError: true, + errorTip: result.error, + tsFilePath: '', + hasNewFile: true + }; + } else { + webComponentId = result.metadataId; + hasNewFile = true; + } } - const createWebCmdError = !webCmd && (await this.createRtcWebCmd(buildInfo, webCmdFileName)); - if (createWebCmdError) { - return { - hasError: true, - errorTip: createWebCmdError, - tsFilePath: '', hasNewFile: true - }; + // 创建命令构件 + if (!webCmd) { + const result: any = await this.createRtcWebCmd(buildInfo, webCmdFileName); + if (result?.error) { + return { + hasError: true, + errorTip: result.error, + tsFilePath: '', + hasNewFile: true + }; + } else { + webCommandId = result.metadataId; + hasNewFile = true; + } } - return { tsFilePath: buildInfo.tsFilePathName, hasNewFile: true }; + + return { + tsFilePath: buildInfo.tsFilePathName, + hasNewFile, + webCommandId, + webComponentId + }; } /** * 运行时定制:新增WebComponent构件 @@ -267,15 +291,21 @@ export class FrmCmpBuilder { '', buildInfo.namespace, buildInfo.code, buildInfo.name, fileName, 'WebComponent', buildInfo.bizObjId, buildInfo.relativePath, JSON.stringify(buildInfo.extendProperty), '', false, this.formBasicInfo.nameLanguage ); + const errorMessage = '构件元数据文件创建失败,请刷新后重试'; + let metadataId = ''; - // 不存在web构件,先创建web构件 return this.metadataService.initializeRtcMetadataEntity(metadatadto, this.formBasicInfo.rtcId || '').then((data) => { data.fileName = metadatadto.fileName; + metadataId = data.id; return this.metadataService.createRtcMetadata(data); }).then(result => { if (!result || !result.ok) { - return '构件元数据文件创建失败,请刷新后重试'; + return { error: errorMessage }; + } else { + return { metadataId }; } + }).catch(error => { + return { error: error?.response?.data?.Message || errorMessage }; }); } @@ -287,15 +317,21 @@ export class FrmCmpBuilder { '', buildInfo.namespace, buildInfo.code, buildInfo.name, fileName, 'WebCommand', buildInfo.bizObjId, buildInfo.relativePath, JSON.stringify(buildInfo.extendProperty), '', false, this.formBasicInfo.nameLanguage ); + const errorMessage = '构件元数据文件创建失败,请刷新后重试'; - // 不存在web构件,先创建web构件 + let metadataId = ''; return this.metadataService.initializeRtcMetadataEntity(metadatadto, this.formBasicInfo.rtcId || '').then((data) => { data.fileName = metadatadto.fileName; + metadataId = data.id; return this.metadataService.createRtcMetadata(data); }).then(result => { if (!result || !result.ok) { - return '构件元数据文件创建失败,请刷新后重试'; + return { error: errorMessage }; + } else { + return { metadataId }; } + }).catch(error => { + return { error: error?.response?.data?.Message || errorMessage }; }); } diff --git a/packages/designer/src/components/composition/command.service.tsx b/packages/designer/src/components/composition/command.service.tsx index 32a08a88a82..4fa5dc66715 100644 --- a/packages/designer/src/components/composition/command.service.tsx +++ b/packages/designer/src/components/composition/command.service.tsx @@ -76,6 +76,7 @@ export function useFormCommandService(formSchemaService: UseFormSchema, useFormS assembleSchemaFieldsByComponent, assembleStateVariables, assembleSchemaFieldsUnderBoundEntity, + getViewModelName } = useParameterEditorData(formSchemaService); function getCommands() { return commands; @@ -93,7 +94,7 @@ export function useFormCommandService(formSchemaService: UseFormSchema, useFormS loadingInstance.value?.close(); resolve([]); }).catch((error) => { - messageService.warning(error); + messageService.warning(error?.response?.data?.Message || '加载控制器失败'); loadingInstance.value?.close(); reject(error); }); @@ -139,7 +140,7 @@ export function useFormCommandService(formSchemaService: UseFormSchema, useFormS }); axios.all(requestCommandsMetadata).then(axios.spread((...metadataList) => { // !!item进行转化 - const metadataContentList = metadataList.filter(item => item !== undefined && item !== null).map(item => { + const metadataContentList = metadataList.filter(item => !!item).map(item => { const content = new CommandMetadataConvertor().InitFromJobject(JSON.parse(item['content'])); const supportedCommands = item.nameSpace.includes('.Front') ? content.Commands : filterSupportedCommand(content); content.Commands = supportedCommands; @@ -151,7 +152,9 @@ export function useFormCommandService(formSchemaService: UseFormSchema, useFormS reject(error); }); - }); + }).catch((error) => { + reject(error); + });; }); } /** @@ -435,7 +438,8 @@ export function useFormCommandService(formSchemaService: UseFormSchema, useFormS }); } - const controlEventPropertyIDList = schemaMap[componentsItem.type]?.events; + const componentType = componentsItem.type === 'form-group' && componentsItem.editor ? componentsItem.editor.type : componentsItem.type; + const controlEventPropertyIDList = schemaMap[componentType]?.events; if (controlEventPropertyIDList) { const eventKeys = Object.keys(controlEventPropertyIDList); for (let i = 0; i < eventKeys.length; i++) { @@ -1285,7 +1289,8 @@ export function useFormCommandService(formSchemaService: UseFormSchema, useFormS assembleSchemaFieldsByComponent, assembleStateVariables, assembleSchemaFieldsUnderBoundEntity, - getEventParameterData + getEventParameterData, + getViewModelName }; } diff --git a/packages/designer/src/components/composition/events-editor-utils.ts b/packages/designer/src/components/composition/events-editor-utils.ts index a05730086b7..67a866b13b0 100644 --- a/packages/designer/src/components/composition/events-editor-utils.ts +++ b/packages/designer/src/components/composition/events-editor-utils.ts @@ -62,9 +62,9 @@ export function useEventsEditorUtils(commandService: UseFormCommandService, form }; // 画布选中外部容器 - if (propertyData.type === 'external-container' && propertyData.externalComponent) { - communication.formId = propertyData.externalComponent.id; - communication.formCode = propertyData.externalComponent.code; + if (propertyData.type === 'external-container') { + communication.formId = propertyData.externalComponent?.id; + communication.formCode = propertyData.externalComponent?.code; communication.externalContainerId = propertyData.id; } else { // 画布选中当前表单的控件 diff --git a/packages/designer/src/components/composition/use-form-validation.ts b/packages/designer/src/components/composition/use-form-validation.ts index cb1f12cad5d..edeeb22b997 100644 --- a/packages/designer/src/components/composition/use-form-validation.ts +++ b/packages/designer/src/components/composition/use-form-validation.ts @@ -105,7 +105,7 @@ export function useFormValidation(useFormSchema: UseFormSchema, formCommandServi // 当前表单id const currentFormId = useFormSchema.getFormMetadataBasicInfo().id; // 当前引入的所有子表单 - const {externalFormSchema} = useFormSchema; + const { externalFormSchema } = useFormSchema; // 目标表单元数据 const targetForm = currentFormId === target.formId ? useFormSchema.getFormSchema() : externalFormSchema.get(target.externalContainerId)?.content; @@ -113,7 +113,7 @@ export function useFormValidation(useFormSchema: UseFormSchema, formCommandServi return false; } // 检查目标表单的命令是否存在 - const isCommandExisted = checkStateExisted(targetForm, target.commandViewmodelId, paramMapping.targetVariable); + const isCommandExisted = checkStateExisted(targetForm, paramMapping.targetVariableViewModelId, paramMapping.targetVariable); if (!isCommandExisted) { return false; } @@ -134,8 +134,8 @@ export function useFormValidation(useFormSchema: UseFormSchema, formCommandServi for (const communicationId of communicationIds) { const communication = communications.find(item => item.id === communicationId); if (!communication) { - let msg = `【ControlName】的【EventName】绑定的通讯已被移除,请重新选择。`; - msg = msg.replace('ControlName', controlName).replace('EventName', boundEvent.eventName); + let msg = `【ControlName(ControlId)】的【EventName】绑定的通讯已被移除,请重新选择。`; + msg = msg.replace('ControlName', controlName).replace('EventName', boundEvent.eventName).replace('ControlId', boundEvent.id); FMessageBoxService.warning(msg, ''); return false; } @@ -144,15 +144,15 @@ export function useFormValidation(useFormSchema: UseFormSchema, formCommandServi const isSourceComplete = source && source.formId && source.componentId && source.event; const isTargetComplete = target && target.formId && target.commandCode; if (!isSourceComplete || !isTargetComplete) { - let msg = `【ControlName】配置的组件通讯事件不完整,请检查。`; - msg = msg.replace('ControlName', controlName); + let msg = `【ControlName(ControlId)】配置的组件通讯不完整,请检查。`; + msg = msg.replace('ControlName', controlName).replace('ControlId', boundEvent.id);; FMessageBoxService.warning(msg, ''); return false; } // 检查通讯内的事件、名称等是否有效 if (!checkCommunicationSource(source) || !checkCommunicationTarget(target)) { - let msg = `【ControlName】配置的组件通讯事件已失效,请检查。`; - msg = msg.replace('ControlName', controlName); + let msg = `【ControlName(ControlId)】配置的组件通讯已失效,请检查。`; + msg = msg.replace('ControlName', controlName).replace('ControlId', boundEvent.id);; FMessageBoxService.warning(msg, ''); return false; } @@ -162,15 +162,15 @@ export function useFormValidation(useFormSchema: UseFormSchema, formCommandServi for (const paramMapping of paramMappings) { const isParamValid = paramMapping.sourceValue && paramMapping.targetVariable; if (!isParamValid) { - let msg = `【ControlName】配置的组件通讯事件参数不完整,请检查。`; - msg = msg.replace('ControlName', controlName); + let msg = `【ControlName(ControlId)】配置的组件通讯参数不完整,请检查。`; + msg = msg.replace('ControlName', controlName).replace('ControlId', boundEvent.id);; FMessageBoxService.warning(msg, ''); return false; } // 检查参是否数失效 if (!checkCommunicationTargetState(target, paramMapping)) { - let msg = `【ControlName】配置的组件通讯事件参数已失效,请检查。`; - msg = msg.replace('ControlName', controlName); + let msg = `【ControlName(ControlId)】配置的组件通讯参数已失效,请检查。`; + msg = msg.replace('ControlName', controlName).replace('ControlId', boundEvent.id);; FMessageBoxService.warning(msg, ''); return false; } diff --git a/packages/designer/src/components/composition/use-parameter-editor-data.ts b/packages/designer/src/components/composition/use-parameter-editor-data.ts index f19f19e3b7d..fbfc76e5ffb 100644 --- a/packages/designer/src/components/composition/use-parameter-editor-data.ts +++ b/packages/designer/src/components/composition/use-parameter-editor-data.ts @@ -64,12 +64,9 @@ export function useParameterEditorData(useFormSchemaComposition: UseFormSchema) return '表格组件'; } - function getViewModelName(viewModelId: string, componentName: string) { - const component = useFormSchemaComposition.getComponentByViewModelId(viewModelId); - if (!component || component.fakeDel) { - return; - } - switch (component.componentType) { + function getViewModelName(component: any, componentName: string) { + + switch (component?.componentType) { case ComponentType.Frame: { return '根组件'; } @@ -208,9 +205,10 @@ export function useParameterEditorData(useFormSchemaComposition: UseFormSchema) allComponents.forEach((cmp: FormComponent) => { const viewModelId = cmp.viewModel; let name: any = null; - const viewModel = useFormSchemaComposition.getViewModelById(viewModelId); - if (viewModel) { - name = getViewModelName(viewModelId, viewModel.name); + const viewModel = formSchema.module.viewmodels.find(item => item.id === viewModelId); + const component = formSchema.module.components.find(item => item.viewModel === viewModelId); + if (viewModel && component) { + name = getViewModelName(component, viewModel.name); } const cmpTreeData: ComponentTreeNode = { data: cmp, @@ -259,8 +257,10 @@ export function useParameterEditorData(useFormSchemaComposition: UseFormSchema) if (!viewModel || !viewModel.states || !viewModel.states.length) { return; } + const component = formSchema.module.components.find(item => item.viewModel === viewModel.id); + const viewModelName = getViewModelName(component, viewModel.name); const vmNode: ViewModelTreeNode = { - data: { id: viewModel.id, code: viewModel.code, name: viewModel.name + '视图模型', statePath: viewModel.id }, + data: { id: viewModel.id, code: viewModel.code, name: viewModelName || viewModel.name, statePath: viewModel.id }, id: viewModel.id, code: viewModel.code || viewModel.id, children: [] as ViewModelTreeNode[], @@ -268,7 +268,7 @@ export function useParameterEditorData(useFormSchemaComposition: UseFormSchema) expanded: true }; data.push(vmNode); - const componentId = useFormSchemaComposition.getComponentByViewModelId(viewModel.id)?.id; + const componentId = formSchema.module.components.find(item => item.viewModel === viewModel.id)?.id; viewModel.states.forEach(state => { vmNode.children.push({ data: { ...state, statePath: `/${componentId}/${state.code}` }, @@ -301,5 +301,6 @@ export function useParameterEditorData(useFormSchemaComposition: UseFormSchema) assembleSchemaFieldsByComponent, assembleStateVariables, assembleSchemaFieldsUnderBoundEntity, + getViewModelName }; } diff --git a/packages/ui-vue/components/binding-selector/src/composition/use-field-selection.ts b/packages/ui-vue/components/binding-selector/src/composition/use-field-selection.ts index dd059b51e06..1542f7627a3 100644 --- a/packages/ui-vue/components/binding-selector/src/composition/use-field-selection.ts +++ b/packages/ui-vue/components/binding-selector/src/composition/use-field-selection.ts @@ -2,7 +2,7 @@ import { FNotifyService } from "../../../notify"; import { FormBindingType, SchemaDOMMapping } from "@farris/ui-vue/components/property-panel"; import { merge } from "lodash-es"; import { BindingSelectorProps } from "../binding-selector.props"; -import { FormSchemaEntityField$Type } from "@farris/ui-vue/components/common"; +import { FormSchemaEntityField$Type, FormSchemaEntityFieldTypeName } from "@farris/ui-vue/components/common"; export function useFieldSelection(props: BindingSelectorProps) { @@ -55,6 +55,7 @@ export function useFieldSelection(props: BindingSelectorProps) { function updataViewModelField(bindingData: Record) { const currentSelectedField = merge({}, bindingData.rawData, { groupId: null, groupName: null }); const originalBinding = props.editorParams.componentSchema?.binding; + const originalLabel = props.editorParams.componentSchema?.label; const dgViewModel = designViewModelUtils.getDgViewModel(viewModelId); // 删除原始绑定信息 @@ -71,6 +72,9 @@ export function useFieldSelection(props: BindingSelectorProps) { if (props.editorParams.componentSchema?.editor?.type) { dgViewModel.changeField(currentSelectedField.id, { editor: currentSelectedField.editor }); } + if (originalLabel) { + dgViewModel.changeField(currentSelectedField.id, { name: originalLabel }); + } } function updataViewModelVariable(bindingData: Record) { @@ -155,6 +159,15 @@ export function useFieldSelection(props: BindingSelectorProps) { } } + /** + * 同步控件的最大长度属性(场景:控件从空绑定至绑定字段后,需要带出字段的长度属性) + */ + function updateComponentMaxLength(bindingData: any) { + const hasMaxLength = [FormSchemaEntityFieldTypeName.Number, FormSchemaEntityFieldTypeName.String, FormSchemaEntityFieldTypeName.Text].includes(bindingData.type.name) && bindingData.type?.length; + if (hasMaxLength && props.editorParams.componentSchema.editor && !Object.prototype.hasOwnProperty.call(props.editorParams.componentSchema.editor, 'maxLength')) { + props.editorParams.componentSchema.editor.maxLength = bindingData.type.length; + } + } /** * 更新控件schema数据 */ @@ -190,6 +203,8 @@ export function useFieldSelection(props: BindingSelectorProps) { props.editorParams.componentSchema.binding.type = bindingType; props.editorParams.componentSchema.path = bindingData.bindingPath; + updateComponentMaxLength(bindingData); + return props.editorParams.componentSchema.binding; } diff --git a/packages/ui-vue/components/checkbox/src/property-config/checkbox.property-config.ts b/packages/ui-vue/components/checkbox/src/property-config/checkbox.property-config.ts index e602d02248e..c766bd084a2 100644 --- a/packages/ui-vue/components/checkbox/src/property-config/checkbox.property-config.ts +++ b/packages/ui-vue/components/checkbox/src/property-config/checkbox.property-config.ts @@ -1,4 +1,5 @@ -import { InputBaseProperty } from "@farris/ui-vue/components/property-panel"; +import { FormSchemaEntityFieldTypeName } from "@farris/ui-vue/components/common"; +import { FormPropertyChangeObject, InputBaseProperty } from "@farris/ui-vue/components/property-panel"; export class CheckBoxProperty extends InputBaseProperty { @@ -44,4 +45,34 @@ export class CheckBoxProperty extends InputBaseProperty { // } }); } + /** + * 切换绑定属性 + */ + public changeBindingField(propertyData: any, changeObject: FormPropertyChangeObject, parameters?: any): any { + super.changeBindingField(propertyData, changeObject); + + + // 同步trueValue和falseValue属性值(场景:控件从空绑定至绑定日期时间类型字段) + const newBindingField = parameters; + if (propertyData.editor && newBindingField?.type?.name) { + let defaultTrueValue; + let defaultFalseValue; + if (newBindingField.type.name === FormSchemaEntityFieldTypeName.String) { + defaultTrueValue = 'true'; + defaultFalseValue = 'false'; + } + if (newBindingField.type.name === FormSchemaEntityFieldTypeName.Number) { + defaultTrueValue = 1; + defaultFalseValue = 0; + } + if (!Object.prototype.hasOwnProperty.call(propertyData.editor, 'trueValue') && defaultTrueValue !== undefined) { + propertyData.editor.trueValue = defaultTrueValue; + } + if (!Object.prototype.hasOwnProperty.call(propertyData.editor, 'falseValue') && defaultFalseValue !== undefined) { + propertyData.editor.falseValue = defaultFalseValue; + } + + } + + } } diff --git a/packages/ui-vue/components/component/src/components/split-form-component.component.tsx b/packages/ui-vue/components/component/src/components/split-form-component.component.tsx index d483614b5fe..ee544ae2155 100644 --- a/packages/ui-vue/components/component/src/components/split-form-component.component.tsx +++ b/packages/ui-vue/components/component/src/components/split-form-component.component.tsx @@ -68,6 +68,12 @@ export default defineComponent({ {!nodeData.isRemoved && !nodeData.isBindVariable && !nodeData.isComplexField ? {nodeData.bindingField} : ''} ; } + function renderNameCell(row: any) { + const controlData = row.raw?.control; + return <> + {controlData.label ? {controlData.label} : {controlData.id} } + ; + } return () => { return (
@@ -105,8 +111,7 @@ export default defineComponent({ hierarchy={hierarchyOption}> {{ 'cellTemplate': ({ cell, row }) => { - return cell.field === 'bindingPath' ? renderBindingPathCell(cell, row) : - (cell.data != null ? cell.data.toString() : cell.data); + return cell.field === 'bindingPath' ? renderBindingPathCell(cell, row) :renderNameCell(row); } }} diff --git a/packages/ui-vue/components/data-grid/src/property-config/data-grid-column.property-config.ts b/packages/ui-vue/components/data-grid/src/property-config/data-grid-column.property-config.ts index 2fd1322dfff..17fe2829c0a 100644 --- a/packages/ui-vue/components/data-grid/src/property-config/data-grid-column.property-config.ts +++ b/packages/ui-vue/components/data-grid/src/property-config/data-grid-column.property-config.ts @@ -158,7 +158,7 @@ export class DataGriColumnProperty extends BaseControlProperty { // 联动修改排序开关 propertyData.remoteSort = propertyData.columnSorted ? true : false; - if (propertyData.onClickLinkCommand) { + if (propertyData.onClickLinkCommand && !propertyData.onClickLinkCommand.includes('communication:')) { // 同步超链接模板 // 替换自定义模板 propertyData.columnTemplate = ` { return ( -
+
{shouldShowSourceControl.value && {communication.value?.target?.formId && <> - + } diff --git a/packages/ui-vue/components/events-editor/src/components/combine-form/combine-form.scss b/packages/ui-vue/components/events-editor/src/components/combine-form/combine-form.scss index dd32dd41857..5691998d609 100644 --- a/packages/ui-vue/components/events-editor/src/components/combine-form/combine-form.scss +++ b/packages/ui-vue/components/events-editor/src/components/combine-form/combine-form.scss @@ -10,6 +10,23 @@ color: #8DA3CE; } + .form-control-tip { + padding: 2px; + background: #F0F3F9; + border-radius: 5px; + color: #8da3ce; + width: 72px; + + >div { + color: #5b89fe; + background: #fff; + display: flex; + justify-content: center; + padding: 0 8px; + border-radius: 4px; + } + } + .form-control { border: 0; flex: 1; @@ -18,6 +35,8 @@ text-overflow: ellipsis; white-space: nowrap; overflow: hidden !important; + background-color: inherit; + padding-right: 20px; } .form-control:focus { @@ -86,7 +105,7 @@ .param-panel { padding: 6px; background-color: #F7FAFF; - box-shadow: 0px 14px 20px 0px rgba(3, 18, 51, 0.07); + box-shadow: 0px 0px 20px 0px rgba(3, 18, 51, 0.07); border-radius: 6px; .col-form-label { @@ -95,7 +114,7 @@ } .form-control { - padding-right: 10px; + padding-right: 10px !important; } } @@ -109,10 +128,12 @@ .fv-grid-row-selected { border-radius: 6px; } - .f-icon-flowline-warning{ + + .f-icon-flowline-warning { font-size: 14px; } - .f-icon-yxs_delete{ + + .f-icon-yxs_delete { font-size: 13px; } } \ No newline at end of file diff --git a/packages/ui-vue/components/events-editor/src/components/combine-form/select-command.component.tsx b/packages/ui-vue/components/events-editor/src/components/combine-form/select-command.component.tsx index fc50a455f54..344aeda4ae5 100644 --- a/packages/ui-vue/components/events-editor/src/components/combine-form/select-command.component.tsx +++ b/packages/ui-vue/components/events-editor/src/components/combine-form/select-command.component.tsx @@ -37,18 +37,22 @@ export default defineComponent({ } } - /** 获取所有模型下的变量 */ - function getAllCommands(viewModels: any[]) { - if (viewModels?.length === 0) { + /** 获取所有模型下的命令 */ + function getAllCommands(formSchema: any) { + const { viewmodels: viewModels, components } = formSchema.module; + if (viewModels?.length === 0 || components?.length === 0) { return []; } targetCommands.value = []; + const viewModelNameResolver = props.sourceCommunication?.parameterData?.getViewModelName; viewModels.forEach(viewModel => { if (!viewModel || !viewModel.commands || viewModel.commands.length === 0) { return []; } + const component = components.find(item => item.viewModel === viewModel.id); + const viewModelName = viewModelNameResolver && component ? viewModelNameResolver(component, viewModel.name) : ''; targetCommands.value.push({ - id: viewModel.id, code: viewModel.code, name: viewModel.name + id: viewModel.id, code: viewModel.code, name: viewModelName || viewModel.name }); viewModel.commands.forEach(command => { if (!command.isInvalid) { @@ -65,12 +69,12 @@ export default defineComponent({ } // 当前表单 if (communication.value.target.formId === formMetaBasicInfo.id) { - getAllCommands(useFormSchema.getViewModels()); + getAllCommands(useFormSchema.getFormSchema()); } else { // 外部表单 const targetFormSchema = useFormSchema.externalFormSchema.get(communication.value?.target?.externalContainerId); - if (targetFormSchema?.content?.module?.viewmodels) { - getAllCommands(targetFormSchema.content.module.viewmodels); + if (targetFormSchema?.content?.module) { + getAllCommands(targetFormSchema.content); } } @@ -112,11 +116,10 @@ export default defineComponent({ return () => { return (
-
- - +
+
目标命令
+ {isInValidCommand.value ? : ''} -
{shouldShowCommandList.value ?
请选择目标命令 diff --git a/packages/ui-vue/components/events-editor/src/components/combine-form/select-parameter.component.tsx b/packages/ui-vue/components/events-editor/src/components/combine-form/select-parameter.component.tsx index 6f89accd22b..452d40bc154 100644 --- a/packages/ui-vue/components/events-editor/src/components/combine-form/select-parameter.component.tsx +++ b/packages/ui-vue/components/events-editor/src/components/combine-form/select-parameter.component.tsx @@ -72,18 +72,23 @@ export default defineComponent({ }); /** 获取所有模型下的变量,组装成树结构 */ - function getAllVariables(viewModels: any[]) { - if (viewModels?.length === 0) { + function getAllVariables(formSchema: any) { + const { viewmodels: viewModels, components } = formSchema.module; + if (viewModels?.length === 0 || components?.length === 0) { return []; } const vmTree = [] as any; targetVariablePlainData.value = []; + const viewModelNameResolver = props.sourceCommunication?.parameterData?.getViewModelName; + viewModels.forEach(viewModel => { if (!viewModel || !viewModel.states || viewModel.states.length === 0) { return []; } const children = [] as any; + const component = components.find(item => item.viewModel === viewModel.id); + const viewModelName = viewModelNameResolver && component ? viewModelNameResolver(component, viewModel.name) : ''; viewModel.states.forEach(variable => { const data = { ...variable, statePath: viewModel.id + '.' + variable.code }; children.push({ data, children: [] }); @@ -91,7 +96,7 @@ export default defineComponent({ }); const rootVm = { - data: { id: viewModel.id, code: viewModel.code, name: viewModel.name, statePath: viewModel.id }, + data: { id: viewModel.id, code: viewModel.code, name: viewModelName || viewModel.name, statePath: viewModel.id }, children }; vmTree.push(rootVm); @@ -105,12 +110,12 @@ export default defineComponent({ } // 当前表单 if (communication.value.target.formId === formMetaBasicInfo.id) { - targetVariableTreeData.value = getAllVariables(useFormSchema.getViewModels()); + targetVariableTreeData.value = getAllVariables(useFormSchema.getFormSchema()); } else { // 外部表单 const targetFormSchema = useFormSchema.externalFormSchema.get(communication.value.target.externalContainerId); - if (targetFormSchema?.content?.module?.viewmodels) { - targetVariableTreeData.value = getAllVariables(targetFormSchema?.content?.module.viewmodels); + if (targetFormSchema?.content?.module) { + targetVariableTreeData.value = getAllVariables(targetFormSchema?.content); } } } @@ -166,7 +171,7 @@ export default defineComponent({ } shouldShowParam.value[parameter.id] = false; Object.assign(parameter, parameterForEditor); - + delete parameter.statePath; context.emit('changed'); } /** 关闭参数面板 */ @@ -191,7 +196,9 @@ export default defineComponent({ if (selections.newValue?.length) { const { statePath } = selections.newValue[0]; if (statePath?.indexOf('.') > 0) { - parameter.targetVariableViewModelId = statePath.slice(0, statePath.indexOf('.')); + const paths = statePath.split('.'); + parameter.targetVariableViewModelId = paths[0]; + parameter.targetVariable = paths[1]; } } // context.emit('changed'); @@ -202,7 +209,7 @@ export default defineComponent({ return { type: 'combo-tree', textField: 'name', - valueField: 'code', + valueField: 'statePath', idField: 'statePath', data: targetVariableTreeData.value, editable: false, @@ -225,7 +232,7 @@ export default defineComponent({ /** 渲染参数面板 */ function renderParamPanel(parameter: CommunicationParameter) { const parameterForEditor = cloneDeep(parameter); - + parameterForEditor['statePath'] = `${parameterForEditor.targetVariableViewModelId}.${parameterForEditor.targetVariable}`; const targetParameterEditor = resolveVariableTreeEditor(parameter); // 获取源页面的schema结构,以便于组装源页面相关的字段、变量等树形结构 @@ -257,7 +264,7 @@ export default defineComponent({ editable={true} > - onChangeTargetVariable(newValue, parameterForEditor, selections)}> @@ -283,9 +290,9 @@ export default defineComponent({ const displayText = paramDispayText.value(parameter); const isInValid = isInValidParam.value[parameter.targetVariable]; return (
-
- - onClickSelectedParam(parameter)}> +
+
参数映射
+ onClickSelectedParam(parameter)}> {isInValid ? : ''}
diff --git a/packages/ui-vue/components/events-editor/src/components/combine-form/select-source-control.component.tsx b/packages/ui-vue/components/events-editor/src/components/combine-form/select-source-control.component.tsx index cf2aeca15bc..a45113d4bac 100644 --- a/packages/ui-vue/components/events-editor/src/components/combine-form/select-source-control.component.tsx +++ b/packages/ui-vue/components/events-editor/src/components/combine-form/select-source-control.component.tsx @@ -192,11 +192,13 @@ export default defineComponent({
-
- - +
+
源控件
+ {isInValidControl.value ? : ''} +
+
请选择源控件 { return (
-
- - +
+
目标页面
+ {isInValidTarget.value ? : ''}
{shouldShowFormList.value ?
diff --git a/packages/ui-vue/components/events-editor/src/components/command-source/command-source.component.tsx b/packages/ui-vue/components/events-editor/src/components/command-source/command-source.component.tsx index 5c55649b082..298a8f7ee57 100644 --- a/packages/ui-vue/components/events-editor/src/components/command-source/command-source.component.tsx +++ b/packages/ui-vue/components/events-editor/src/components/command-source/command-source.component.tsx @@ -44,15 +44,6 @@ export default defineComponent({ const notifyService = new NotifyService(); const { checkIfNewControllerExists, addNewController } = methodsComposition; const controllers = ref(props.controllers); - - const actionButtonStyle = computed(() => { - return { - 'font-size': '15px', - 'margin': '5px', - 'color': '#226eff', - 'flex': '1 1 0' - }; - }); const useFormSchema = inject('useFormSchema') as any; const modalService = inject(F_MODAL_SERVICE_TOKEN) as any; let newFuncModal: any; @@ -176,19 +167,19 @@ export default defineComponent({ return (
-
+
openMetadataSelector()}>引入控制器
-
+
generateNewFunc()}>添加新方法
{props.haveBoundCommand &&
-
+
showBoundEvents()}>已有方法
} {shoulShowCommunication.value &&
-
+
openFormCommunicationPanel()}>添加组件通讯事件
}
diff --git a/packages/ui-vue/components/events-editor/src/components/command-source/command-source.css b/packages/ui-vue/components/events-editor/src/components/command-source/command-source.css index 20b1a81b337..b90808987d2 100644 --- a/packages/ui-vue/components/events-editor/src/components/command-source/command-source.css +++ b/packages/ui-vue/components/events-editor/src/components/command-source/command-source.css @@ -11,9 +11,9 @@ padding: 10px 10px 0 10px; display: flex; flex-direction: column; - } - - .f-page-events-editor-command-source::before { +} + +.f-page-events-editor-command-source::before { content: ''; width: 0; height: 0; @@ -23,9 +23,9 @@ border-width: 7px; border-style: solid; border-color: transparent transparent #e2e5e6; - } - - .f-page-events-editor-command-source::after { +} + +.f-page-events-editor-command-source::after { content: ''; width: 0; height: 0; @@ -35,18 +35,18 @@ border-width: 7px; border-style: solid dashed dashed; border-color: transparent transparent #ffffff; - } - - .f-page-command-source-choice { +} + +.f-page-command-source-choice { overflow-x: hidden; overflow-y: scroll; padding: 5px 0px; border-radius: 3px; min-width: 200px; flex: 2 2 0; - } - - /* .f-page-command-source-choice{ +} + +/* .f-page-command-source-choice{ height: 315px; overflow-x:hidden; overflow-y: scroll; @@ -54,9 +54,9 @@ border-radius: 3px; min-width: 200px; } */ - - - .f-page-events-editor-switch { + + +.f-page-events-editor-switch { background: #EFF5FF; border-radius: 10px; margin: 10px; @@ -64,9 +64,9 @@ height: 32px; display: flex; text-align: center; - } - - .namelist { +} + +.namelist { font-family: PingFangSC-Regular; font-size: 14px; color: #446a9fd9; @@ -74,9 +74,9 @@ margin: 8px 13px 8px 13px; flex-grow: 1; cursor: pointer; - } - - .namelist-focus { +} + +.namelist-focus { opacity: 0.6; font-family: PingFangSC-Regular; font-size: 14px; @@ -89,28 +89,42 @@ box-shadow: 0 4px 18px 0 rgb(2 75 193 / 20%); border-radius: 10px; cursor: pointer; - } - - .f-page-internals-new-command { +} + +.f-page-internals-new-command { margin: 0px 2px 0px 13px; - } - - .f-page-internals-new-command-func1 { +} + +.f-page-internals-new-command-func1 { display: flex; margin: 4px 1px; - } - - .f-page-internals-new-command-func2 { +} + +.f-page-internals-new-command-func2 { display: flex; margin: 4px 1px; - } - - .f-page-internals-new-command-func3 { +} + +.f-page-internals-new-command-func3 { display: flex; margin: 4px 1px; - } - - .f-function-class { +} + +.f-page-internals-new-command .f-icon { + font-size: 15px; + margin: 5px; + color: #226eff; + flex: 1 1 0; +} + +.f-page-internals-new-command .fd-i-Family { + font-size: 14px; + margin: 5px; + color: #226eff; + flex: 1 1 0; +} + +.f-function-class { margin: 0 0 0 5px; font-family: PingFangSC-Regular; color: #4f6b9d; @@ -121,9 +135,9 @@ line-height: 26px; font-weight: 400; flex: 10; - } - - .f-page-internals-close { +} + +.f-page-internals-close { font-family: PingFangSC-Regular; font-size: 13px; margin: 7.75px 10px; @@ -134,13 +148,13 @@ color: #425159; font-weight: 400; text-align: center; - } - - .f-command-breakline { +} + +.f-command-breakline { color: #B4BCCC; margin: 2px; overflow: hidden; white-space: nowrap; text-overflow: clip; height: 10px; - } \ No newline at end of file +} \ No newline at end of file diff --git a/packages/ui-vue/components/external-container/src/designer/external-container.design.component.tsx b/packages/ui-vue/components/external-container/src/designer/external-container.design.component.tsx index aa8b4fde2c0..edb69a64950 100644 --- a/packages/ui-vue/components/external-container/src/designer/external-container.design.component.tsx +++ b/packages/ui-vue/components/external-container/src/designer/external-container.design.component.tsx @@ -57,7 +57,7 @@ export default defineComponent({ recordExternalForm(); }, (error) => { - messagerService.exception(error?.error || `查询表单【${externalComponent.value.name}】失败`); + messagerService.error(error?.response?.data.Message || `查询表单【${externalComponent.value.name}】失败`); instance.value.close(); }); } diff --git a/packages/ui-vue/components/external-container/src/designer/import-external-schema.component.tsx b/packages/ui-vue/components/external-container/src/designer/import-external-schema.component.tsx index df3ed71e91c..2a2d0dde85e 100644 --- a/packages/ui-vue/components/external-container/src/designer/import-external-schema.component.tsx +++ b/packages/ui-vue/components/external-container/src/designer/import-external-schema.component.tsx @@ -5,6 +5,7 @@ import { FSchemaSelector } from '@farris/ui-vue/components/schema-selector'; import { FormSchemaRepositorySymbol } from '@farris/ui-vue/components/common'; import { FNotifyService } from '@farris/ui-vue/components/notify'; import './import-external-schema.css'; +import { FLoadingService } from '@farris/ui-vue/components/loading'; export default defineComponent({ name: 'FImportExteranlSchema', @@ -15,15 +16,17 @@ export default defineComponent({ const selectedItem = ref(); const notifyService: any = new FNotifyService(); notifyService.globalConfig = { position: 'top-center' }; + const loadingService: any | null = inject('FLoadingService'); const formBasicInfo = designerHostService.formSchemaUtils.getFormMetadataBasicInfo(); const schemaSelectorRef = ref(); async function checkFormValidtion(selectionFormInfo: any) { const formBasicInfo = designerHostService.formSchemaUtils.getFormMetadataBasicInfo(); - + const instance = loadingService.show(); return designerHostService.metadataService.getPickMetadata(formBasicInfo.relativePath, selectionFormInfo) .then((res: any) => { + instance.value?.close(); const metadata = JSON.parse(res?.metadata.content); const formSchema = metadata.Contents; const { templateId, name } = formSchema.module; @@ -31,11 +34,12 @@ export default defineComponent({ if (['list-component', 'tree-component'].includes(templateId)) { return true; } - const message = `表单【${name}】不属于组件类模板,无法被导入到当前表单。`; + const message = `表单【${name}】不属于组件类模板,无法被引入到当前表单。`; designerHostService.messagerService.warning(message); return false; }, (error) => { - designerHostService.exception(error?.error || `查询表单【${selectionFormInfo.name}】失败`); + designerHostService.messagerService.error(error?.response?.data.Message || `查询表单【${selectionFormInfo.name}】失败`); + instance.value?.close(); return false; }); } @@ -76,7 +80,7 @@ export default defineComponent({ context.emit('close'); } function onSelectionChange($event) { - selectedItem.value = $event[0]; + selectedItem.value = $event?.length ? $event[0] : null; } function renderFormSelectorComponent() { const formSelectorParams = { formBasicInfo }; diff --git a/packages/ui-vue/components/external-container/src/designer/import-external-schema.css b/packages/ui-vue/components/external-container/src/designer/import-external-schema.css index 7ab3f2b6e2b..9d2bea97284 100644 --- a/packages/ui-vue/components/external-container/src/designer/import-external-schema.css +++ b/packages/ui-vue/components/external-container/src/designer/import-external-schema.css @@ -6,6 +6,7 @@ height: 100%; display: flex; justify-content: center; + border: dotted 2px #e8e8e8; } .f-import-exteranl-component-button-center { @@ -14,4 +15,4 @@ padding: 6px 17px; color: #2A87FF; cursor: pointer; -} +} \ No newline at end of file diff --git a/packages/ui-vue/components/external-container/src/property-config/external-container.property-config.ts b/packages/ui-vue/components/external-container/src/property-config/external-container.property-config.ts index 80826e9b8b4..4e72cf78b14 100644 --- a/packages/ui-vue/components/external-container/src/property-config/external-container.property-config.ts +++ b/packages/ui-vue/components/external-container/src/property-config/external-container.property-config.ts @@ -1,10 +1,10 @@ -import { inject } from "vue"; import { FormSchemaRepositorySymbol } from "@farris/ui-vue/components/common"; import { DesignerComponentInstance } from "@farris/ui-vue/components/designer-canvas"; import { BaseControlProperty } from "@farris/ui-vue/components/property-panel"; import { FLoadingService } from "@farris/ui-vue/components/loading"; import { externalContainerConverter } from "./external-container.converter"; +import { FNotifyService } from "@farris/ui-vue/components/notify"; export class ExternalContainerProperty extends BaseControlProperty { @@ -18,16 +18,15 @@ export class ExternalContainerProperty extends BaseControlProperty { // 外观 this.propertyConfig.categories['appearance'] = this.getAppearanceConfig(propertyData); // 引入表单 - this.propertyConfig.categories['content'] = this.getContentConfig(); + this.propertyConfig.categories['content'] = this.getContentConfig(propertyData); this.propertyConfig.categories['eventsEditor'] = this.getEventPropConfig(propertyData); return this.propertyConfig; } - private getContentConfig() { + private getContentConfig(propertyData: any) { const self = this; - const loadingService: any | null = inject('FLoadingService'); return { description: '外部表单', @@ -61,8 +60,13 @@ export class ExternalContainerProperty extends BaseControlProperty { } } }, - $converter: externalContainerConverter - + $converter: externalContainerConverter, + refreshPanelAfterChanged: true + } + }, + setPropertyRelates(changeObject: any) { + if (changeObject?.propertyID === 'externalComponent') { + self.syncCommunicationAfterFormChanged(changeObject, propertyData); } } }; @@ -70,9 +74,11 @@ export class ExternalContainerProperty extends BaseControlProperty { private checkFormValidtion(selectionFormInfo: any) { const formBasicInfo = this.designerHostService.formSchemaUtils.getFormMetadataBasicInfo(); + const loadingInstance = FLoadingService.show(); return this.designerHostService.metadataService.getPickMetadata(formBasicInfo.relativePath, selectionFormInfo) .then((res: any) => { + (loadingInstance.value as any).close(); const metadata = JSON.parse(res?.metadata.content); const formSchema = metadata.Contents; const { templateId, name } = formSchema.module; @@ -80,11 +86,12 @@ export class ExternalContainerProperty extends BaseControlProperty { if (['list-component', 'tree-component'].includes(templateId)) { return true; } - const message = `表单【${name}】不属于组件类模板,无法被导入到当前表单。`; + const message = `表单【${name}】不属于组件类模板,无法被引入到当前表单。`; this.designerHostService.messagerService.warning(message); return false; }, (error) => { - this.designerHostService.exception(error?.error || `查询表单【${selectionFormInfo.name}】失败`); + (loadingInstance.value as any).close(); + this.designerHostService.messagerService.error(error?.response?.data.Message || `查询表单【${selectionFormInfo.name}】失败`); return false; }); } @@ -117,4 +124,36 @@ export class ExternalContainerProperty extends BaseControlProperty { } }; } + /** + * 切换外部表单后,同步更新组件通讯中的源表单(场景:已配置组件通讯,再切换外部表单) + */ + private syncCommunicationAfterFormChanged(changeObject, propertyData) { + if (!propertyData.onCommunication) { + return; + } + const communicationIds = propertyData.onCommunication.replace('communication:', '').split(';'); + if (!communicationIds?.length) { + return; + } + const formSchema = this.designerHostService.formSchemaUtils.getFormSchema(); + const communications = formSchema.module.communications || []; + let needNotify = false; + communicationIds.map(communicationId => { + const communication = communications.find(item => item.id === communicationId); + if (communication?.source && communication.source.formId !== propertyData.externalComponent.id) { + communication.source.formId = propertyData.externalComponent.id; + communication.source.formCode = propertyData.externalComponent.code; + communication.source.componentId = ''; + communication.source.event = ''; + + needNotify = true; + } + }); + if (needNotify) { + const notifyService: any = new FNotifyService(); + notifyService.globalConfig = { position: 'top-center' }; + notifyService.warning({ message: '切换引入表单后,请重新配置组件通讯。' }); + } + + } } diff --git a/packages/ui-vue/components/response-layout/src/designer/response-layout-item-designer-rules.ts b/packages/ui-vue/components/response-layout/src/designer/response-layout-item-designer-rules.ts index 5f6d2580bd8..5c4a0d0a63f 100644 --- a/packages/ui-vue/components/response-layout/src/designer/response-layout-item-designer-rules.ts +++ b/packages/ui-vue/components/response-layout/src/designer/response-layout-item-designer-rules.ts @@ -121,14 +121,14 @@ export function useDesignerRules(designItemContext: DesignerItemContext, designe } const sourceComponentInstance = sourceElement.componentInstance; const sourceComponentSchema = sourceComponentInstance.value.schema; - if (!sourceComponentSchema.binding || !sourceComponentSchema.binding.field) { - return; - } // 若拖拽的源组件是输入类控件,需要在当前布局项上增加form样式 if (sourceComponentSchema.type === 'form-group') { addFormClassToResponseLayoutItem(); } + if (!sourceComponentSchema.binding || !sourceComponentSchema.binding.field) { + return; + } const formMoveHandler = formUseDesignerRules(designItemContext, designerHostService); if (formMoveHandler.onAcceptMovedChildElement) { diff --git a/packages/ui-vue/components/schema-selector/src/components/card-view.component.tsx b/packages/ui-vue/components/schema-selector/src/components/card-view.component.tsx index 506799e0bf2..8fadf6f33ec 100644 --- a/packages/ui-vue/components/schema-selector/src/components/card-view.component.tsx +++ b/packages/ui-vue/components/schema-selector/src/components/card-view.component.tsx @@ -49,7 +49,7 @@ export default defineComponent({
-
{item.name}({item.code})
+
{item.name}({item.code})
{item.nameSpace}
@@ -73,7 +73,7 @@ export default defineComponent({ function selectionChangeEventHandler($event) { context.emit('selectionChange', $event); } - + async function loadData() { const loadingService: any | null = inject('FLoadingService', null); const loading = loadingService?.show(); @@ -88,6 +88,13 @@ export default defineComponent({ loadData(); }); + function clearSelection() { + listViewRef.value.clearSelection(); + listViewRef.value.updateSelectionByIds([]); + + } + context.expose({ clearSelection }); + return () => { return ( selectionChangeEventHandler(event)}> diff --git a/packages/ui-vue/components/schema-selector/src/components/list-view.component.tsx b/packages/ui-vue/components/schema-selector/src/components/list-view.component.tsx index 0d6b046786d..4489e25ebe8 100644 --- a/packages/ui-vue/components/schema-selector/src/components/list-view.component.tsx +++ b/packages/ui-vue/components/schema-selector/src/components/list-view.component.tsx @@ -1,4 +1,4 @@ - + import { defineComponent, inject, onMounted, Ref, ref, watch } from "vue"; import { FListView } from '../../../list-view'; import { FPagination } from '../../../pagination'; @@ -52,6 +52,12 @@ export default defineComponent({ onMounted(() => { loadData(); }); + function clearSelection() { + listViewRef.value.clearSelection(); + listViewRef.value.updateSelectionByIds([]); + + } + context.expose({ clearSelection }); function renderListViewContent({ item, index, selectedItem }) { return ( diff --git a/packages/ui-vue/components/schema-selector/src/schema-selector-editor.component.tsx b/packages/ui-vue/components/schema-selector/src/schema-selector-editor.component.tsx index c4568dcc890..e080ce29f9e 100644 --- a/packages/ui-vue/components/schema-selector/src/schema-selector-editor.component.tsx +++ b/packages/ui-vue/components/schema-selector/src/schema-selector-editor.component.tsx @@ -51,7 +51,7 @@ export default defineComponent({ function renderSchemaSelector() { if (viewType.value === 'controller') { - return ; + return ; } return { + if (viewRef.clearSelection) { + viewRef.clearSelection(); + } + }); + } + } function renderTabsContent() { - return viewOptions.value.map((viewOption: ViewOption) => { + return viewOptions.value.map((viewOption: ViewOption, index: number) => { if (viewsMap.has(viewOption.type)) { const SelectorDataView = viewsMap.get(viewOption.type) as any; const options = { @@ -55,7 +69,7 @@ export default defineComponent({ pagination: viewOption.pagination || false }; return - onSchemaSelect($event)}> + { if (view) { dataViewRef[index] = view; } }} {...options} onSelectionChange={($event) => onSchemaSelect($event)}> ; } }); @@ -75,7 +89,7 @@ export default defineComponent({ } function renderTabsView() { - return {{ default: renderTabsContent, headerSuffix: renderTabsHeaderSuffix }}; + return {{ default: renderTabsContent, headerSuffix: renderTabsHeaderSuffix }}; } function renderNavView() { diff --git a/packages/ui-vue/components/schema-selector/src/schema-selector.css b/packages/ui-vue/components/schema-selector/src/schema-selector.css index 5661cb21d0b..b40b5267a98 100644 --- a/packages/ui-vue/components/schema-selector/src/schema-selector.css +++ b/packages/ui-vue/components/schema-selector/src/schema-selector.css @@ -108,7 +108,6 @@ font-size: 13px; color: #8999b9; font-weight: 400; - background: #f7f9fc; border-radius: 4px; padding: 2px; text-overflow: ellipsis; diff --git a/packages/ui-vue/components/switch/src/property-config/switch.property-config.ts b/packages/ui-vue/components/switch/src/property-config/switch.property-config.ts index f8b96a2785f..a2f1d47051e 100644 --- a/packages/ui-vue/components/switch/src/property-config/switch.property-config.ts +++ b/packages/ui-vue/components/switch/src/property-config/switch.property-config.ts @@ -1,4 +1,5 @@ -import { InputBaseProperty } from "@farris/ui-vue/components/property-panel"; +import { FormSchemaEntityFieldTypeName } from "@/components/common"; +import { FormPropertyChangeObject, InputBaseProperty } from "@farris/ui-vue/components/property-panel"; export class SwitchProperty extends InputBaseProperty { @@ -7,14 +8,14 @@ export class SwitchProperty extends InputBaseProperty { } getEditorProperties(propertyData: any) { - return this.getComponentConfig(propertyData, { - type:"switch" + return this.getComponentConfig(propertyData, { + type: "switch" }, { disabled: { - visible:false + visible: false }, - placeholder:{ - visible:false + placeholder: { + visible: false }, onLabel: { description: "", @@ -36,11 +37,11 @@ export class SwitchProperty extends InputBaseProperty { title: "关闭背景色", type: "string" }, - size:{ + size: { description: "", title: "尺寸", type: "enum", - editor:{ + editor: { data: [ { id: "small", @@ -57,7 +58,7 @@ export class SwitchProperty extends InputBaseProperty { ] } }, - trueValue: { + trueValue: { description: "打开时的值", title: "打开的值", type: this.getBindingDataType(), @@ -77,5 +78,35 @@ export class SwitchProperty extends InputBaseProperty { } }); } + /** + * 切换绑定属性 + */ + public changeBindingField(propertyData: any, changeObject: FormPropertyChangeObject, parameters?: any): any { + super.changeBindingField(propertyData, changeObject); + + + // 同步trueValue和falseValue属性值(场景:控件从空绑定至绑定日期时间类型字段) + const newBindingField = parameters; + if (propertyData.editor && newBindingField?.type?.name) { + let defaultTrueValue; + let defaultFalseValue; + if (newBindingField.type.name === FormSchemaEntityFieldTypeName.String) { + defaultTrueValue = 'true'; + defaultFalseValue = 'false'; + } + if (newBindingField.type.name === FormSchemaEntityFieldTypeName.Number) { + defaultTrueValue = 1; + defaultFalseValue = 0; + } + if (!Object.prototype.hasOwnProperty.call(propertyData.editor, 'trueValue') && defaultTrueValue !== undefined) { + propertyData.editor.trueValue = defaultTrueValue; + } + if (!Object.prototype.hasOwnProperty.call(propertyData.editor, 'falseValue') && defaultFalseValue !== undefined) { + propertyData.editor.falseValue = defaultFalseValue; + } + + } + + } }; -- Gitee From d52d03185cf7236de5bbdc878cc6955e5a753734 Mon Sep 17 00:00:00 2001 From: wang-xh Date: Tue, 29 Jul 2025 15:06:02 +0800 Subject: [PATCH 3/9] =?UTF-8?q?fix:=20=E9=80=89=E6=8B=A9=E8=A1=A8=E5=8D=95?= =?UTF-8?q?=E7=9A=84=E7=AA=97=E5=8F=A3=E6=94=AF=E6=8C=81=E5=88=86=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../external-component-selector.component.tsx | 8 +++--- .../method-list/method-list.component.tsx | 5 ++-- .../external-container.design.component.tsx | 17 ++++++------ .../external-container.property-config.ts | 9 +++---- .../composition/use-response-layout.ts | 2 +- .../src/designer/use-designer-item-rules.ts | 10 +++++-- .../src/components/card-view.component.tsx | 27 ++++++++++++++----- .../property-config/switch.property-config.ts | 2 +- 8 files changed, 49 insertions(+), 31 deletions(-) diff --git a/packages/designer/src/components/components/form-designer/components/external-component-panel/components/external-component-selector/external-component-selector.component.tsx b/packages/designer/src/components/components/form-designer/components/external-component-panel/components/external-component-selector/external-component-selector.component.tsx index 1ca522ae997..bcb7d10ac41 100644 --- a/packages/designer/src/components/components/form-designer/components/external-component-panel/components/external-component-selector/external-component-selector.component.tsx +++ b/packages/designer/src/components/components/form-designer/components/external-component-panel/components/external-component-selector/external-component-selector.component.tsx @@ -22,8 +22,8 @@ export default defineComponent({ const formBasicInfo = formSchemaUtils.getFormMetadataBasicInfo(); const editorParams = { formBasicInfo }; const viewOptions = [ - { id: 'recommend', title: '推荐', type: 'Card', dataSource: 'Recommand', pagination: false }, - { id: 'total', title: '全部', type: 'Card', dataSource: 'Total', pagination: false } + { id: 'recommend', title: '推荐', type: 'Card', dataSource: 'Recommand', pagination: true }, + { id: 'total', title: '全部', type: 'Card', dataSource: 'Total', pagination: true } ]; const injectSymbolToken = computed(() => { return externalComponentType === 'Independence' ? FormSchemaRepositorySymbol : LookupSchemaRepositoryToken; @@ -35,9 +35,9 @@ export default defineComponent({ */ function onSelectionChange($event: any[]) { if (externalComponentType === 'Lookup') { - selectedComponent.value = $event[0].data; + selectedComponent.value = $event?.length ? $event[0].data : null; } else { - selectedComponent.value = $event[0]; + selectedComponent.value = $event?.length ? $event[0] : null;; } } diff --git a/packages/designer/src/components/components/view-model-designer/method-manager/components/method-list/method-list.component.tsx b/packages/designer/src/components/components/view-model-designer/method-manager/components/method-list/method-list.component.tsx index 8831dcd1b32..1b2527f1656 100644 --- a/packages/designer/src/components/components/view-model-designer/method-manager/components/method-list/method-list.component.tsx +++ b/packages/designer/src/components/components/view-model-designer/method-manager/components/method-list/method-list.component.tsx @@ -110,7 +110,7 @@ export default defineComponent({ /** * 由外部触发刷新方法 */ - function refreshMethodList(newCommandsData: Array, newActiveViewModel: FormViewModel, selectedCommandId?: string) { + function refreshMethodList(newCommandsData: Array, newActiveViewModel: FormViewModel, specifiedCommandId?: string) { commandsData.value = newCommandsData || []; // cleanData(commandsData.value); activeViewModel.value = newActiveViewModel; @@ -118,7 +118,8 @@ export default defineComponent({ treeGridRef.value.clearSelection(); if (commandsData.value.length) { - treeGridRef.value.selectItemById(selectedCommandId || selectedTreeNode.value?.id || commandsData.value[0].id); + const currentSelectedCommandId = selectedTreeNode.value && !selectedTreeNode.value.parent ? selectedTreeNode.value.id : ''; + treeGridRef.value.selectItemById(specifiedCommandId || currentSelectedCommandId || commandsData.value[0].id); } else { selectedTreeNode.value = null; paramsData.value = []; diff --git a/packages/ui-vue/components/external-container/src/designer/external-container.design.component.tsx b/packages/ui-vue/components/external-container/src/designer/external-container.design.component.tsx index edb69a64950..255a41efaaf 100644 --- a/packages/ui-vue/components/external-container/src/designer/external-container.design.component.tsx +++ b/packages/ui-vue/components/external-container/src/designer/external-container.design.component.tsx @@ -27,7 +27,6 @@ export default defineComponent({ const externalFormSchemaComponent = computed(() => externalFormSchema.value?.module?.components[0]); /** 是否显示引入表单的占位区域 */ const shouldShowImportSchema = computed(() => !externalFormSchema.value); - /** 记录外部容器id */ provide('external-container-id', componentInstance.value.schema.id); @@ -48,26 +47,26 @@ export default defineComponent({ async function loadFormMetadata() { const formBasicInfo = designerHostService.formSchemaUtils.getFormMetadataBasicInfo(); if (externalComponent.value?.id) { - const instance = loadingService?.show(); - designerHostService.metadataService.getPickMetadata(formBasicInfo.relativePath, externalComponent.value) + const instance = loadingService?.show({ message: '数据加载中,请稍候...' }); + return designerHostService.metadataService.getPickMetadata(formBasicInfo.relativePath, externalComponent.value) .then((res: any) => { const metadata = JSON.parse(res?.metadata.content); externalFormSchema.value = metadata.Contents; instance.value.close(); - recordExternalForm(); }, (error) => { messagerService.error(error?.response?.data.Message || `查询表单【${externalComponent.value.name}】失败`); instance.value.close(); }); } - } - watch(() => props.externalComponent, (newValue) => { + watch(() => props.externalComponent, async (newValue) => { if (!externalComponent.value || !newValue || JSON.stringify(externalComponent.value) !== JSON.stringify(newValue)) { externalComponent.value = newValue; - loadFormMetadata(); + await loadFormMetadata(); + // 触发更新属性面板 + designItemContext?.setupContext?.emit('dragEnd'); } else { externalComponent.value = newValue; } @@ -92,10 +91,10 @@ export default defineComponent({ ; } - function onFormSelected(formMetadaInfo: any) { + async function onFormSelected(formMetadaInfo: any) { componentInstance.value.schema.externalComponent = formMetadaInfo; externalComponent.value = formMetadaInfo; - loadFormMetadata(); + await loadFormMetadata(); // 触发更新属性面板 designItemContext?.setupContext?.emit('dragEnd'); diff --git a/packages/ui-vue/components/external-container/src/property-config/external-container.property-config.ts b/packages/ui-vue/components/external-container/src/property-config/external-container.property-config.ts index 4e72cf78b14..6698f2014aa 100644 --- a/packages/ui-vue/components/external-container/src/property-config/external-container.property-config.ts +++ b/packages/ui-vue/components/external-container/src/property-config/external-container.property-config.ts @@ -47,11 +47,11 @@ export class ExternalContainerProperty extends BaseControlProperty { }, viewOptions: this.formSchemaUtils.designerMode === 'PC_RTC' ? [ - { id: 'total', title: '全部', type: 'Card', dataSource: 'Total', pagination: false } + { id: 'total', title: '全部', type: 'Card', dataSource: 'Total', pagination: true } ] : [ - { id: 'recommend', title: '推荐', type: 'Card', dataSource: 'Recommand', pagination: false }, - { id: 'total', title: '全部', type: 'Card', dataSource: 'Total', pagination: false } + { id: 'recommend', title: '推荐', type: 'Card', dataSource: 'Recommand', pagination: true }, + { id: 'total', title: '全部', type: 'Card', dataSource: 'Total', pagination: true } ], repositoryToken: FormSchemaRepositorySymbol, validateFunction: (selection: any) => { @@ -60,8 +60,7 @@ export class ExternalContainerProperty extends BaseControlProperty { } } }, - $converter: externalContainerConverter, - refreshPanelAfterChanged: true + $converter: externalContainerConverter } }, setPropertyRelates(changeObject: any) { diff --git a/packages/ui-vue/components/response-layout/src/property-config/response-layout-splitter/composition/use-response-layout.ts b/packages/ui-vue/components/response-layout/src/property-config/response-layout-splitter/composition/use-response-layout.ts index 23db017eefc..c08db08825f 100644 --- a/packages/ui-vue/components/response-layout/src/property-config/response-layout-splitter/composition/use-response-layout.ts +++ b/packages/ui-vue/components/response-layout/src/property-config/response-layout-splitter/composition/use-response-layout.ts @@ -2,7 +2,7 @@ import { ComponentSchema } from "../../../../../designer-canvas"; import { getSchemaByType } from "../../../../../dynamic-resolver"; import { inject, Ref, ref, SetupContext } from "vue"; import { ResponseLayoutSplitterProps } from "../response-layout-splitter.props"; -import { FMessageBoxService } from "@/components/message-box"; +import { FMessageBoxService } from "@farris/ui-vue/components/message-box"; export function useResponseLayoutSplitter(props: ResponseLayoutSplitterProps, context: SetupContext) { diff --git a/packages/ui-vue/components/response-toolbar/src/designer/use-designer-item-rules.ts b/packages/ui-vue/components/response-toolbar/src/designer/use-designer-item-rules.ts index 60245de78d4..d376937fd84 100644 --- a/packages/ui-vue/components/response-toolbar/src/designer/use-designer-item-rules.ts +++ b/packages/ui-vue/components/response-toolbar/src/designer/use-designer-item-rules.ts @@ -401,9 +401,15 @@ export function useDesignerItemRules(designerItemContext: DesignerItemContext, d break; } case 'tab-toolbar-item': case 'section-toolbar-item': { - const parentComponentInstance = designerItemContext.parent?.parent?.componentInstance?.value; + let parentComponentInstance; + const parentDesignerItemContext = designerItemContext.parent?.parent; + if (parentDesignerItemContext?.schema.type === 'tabs' || parentDesignerItemContext?.schema.type === 'section') { + parentComponentInstance = parentDesignerItemContext.componentInstance?.value; + } else { + parentComponentInstance = parentDesignerItemContext?.parent?.componentInstance?.value; + } if (parentComponentInstance?.setComponentBasicInfoMap) { - parentComponentInstance?.setComponentBasicInfoMap(); + parentComponentInstance.setComponentBasicInfoMap(); } } } diff --git a/packages/ui-vue/components/schema-selector/src/components/card-view.component.tsx b/packages/ui-vue/components/schema-selector/src/components/card-view.component.tsx index 8fadf6f33ec..4a05b98f9dc 100644 --- a/packages/ui-vue/components/schema-selector/src/components/card-view.component.tsx +++ b/packages/ui-vue/components/schema-selector/src/components/card-view.component.tsx @@ -3,7 +3,7 @@ import { defineComponent, inject, onMounted, Ref, ref, watch } from "vue"; import { FListView } from '../../../list-view'; import { FPagination } from '../../../pagination'; import { SchemaViewProps, schemaViewProps } from "./schema-view.props"; -import { GetSchemaDataFunction, SchemaRepositoryPagination } from "../composition/types"; +import { GetSchemaDataFunction } from "../composition/types"; export default defineComponent({ name: 'FSchemaSelectCardView', @@ -21,11 +21,10 @@ export default defineComponent({ const searchValue = inject('F_SCHEMA_SELECTOR_SEARCH_VALUE'); const showPagination = ref(props.pagination); const currentPageIndex = ref(1); - const totalItems = ref(); + const totalItems = ref(0); + const pageSize = ref(21); function updateListViewDataScource(items: any[]) { listViewRef.value.updateDataSource(items); - - totalItems.value = items.length; } watch(() => searchValue?.value, (newValue, oldValue) => { let resultItems = dataList.value; @@ -37,7 +36,7 @@ export default defineComponent({ searchResult.value = resultItems; updateListViewDataScource(searchResult.value); - // showPagination.value = !newValue; + showPagination.value = props.pagination && !newValue; }); function renderListViewContent({ item, index, selectedItem }) { return ( @@ -55,16 +54,28 @@ export default defineComponent({
); } + /** 切换页码 */ + function onPageIndexChanged(pageInfo: { pageIndex: number }) { + const { pageIndex } = pageInfo; + + // 计算起始、结束索引 + const startIndex = (pageIndex - 1) * pageSize.value; + const endIndex = startIndex + pageSize.value; + const resultItems = dataList.value.slice(startIndex, endIndex); + updateListViewDataScource(resultItems); + } function renderListViewFooter() { return ( showPagination.value && + show-page-list={false} + onPageIndexChanged={onPageIndexChanged} > ); @@ -81,7 +92,9 @@ export default defineComponent({ dataList.value = data; searchResult.value = data; updateListViewDataScource(searchResult.value); + totalItems.value = data.length; + onPageIndexChanged({ pageIndex: 1 }); loading.value?.close(); } onMounted(() => { diff --git a/packages/ui-vue/components/switch/src/property-config/switch.property-config.ts b/packages/ui-vue/components/switch/src/property-config/switch.property-config.ts index a2f1d47051e..7dc109cd341 100644 --- a/packages/ui-vue/components/switch/src/property-config/switch.property-config.ts +++ b/packages/ui-vue/components/switch/src/property-config/switch.property-config.ts @@ -1,4 +1,4 @@ -import { FormSchemaEntityFieldTypeName } from "@/components/common"; +import { FormSchemaEntityFieldTypeName } from "@farris/ui-vue/components/common"; import { FormPropertyChangeObject, InputBaseProperty } from "@farris/ui-vue/components/property-panel"; export class SwitchProperty extends InputBaseProperty { -- Gitee From d6deafcf3efb5032961add92bf8b75f52485bd7c Mon Sep 17 00:00:00 2001 From: wang-xh Date: Wed, 30 Jul 2025 14:11:57 +0800 Subject: [PATCH 4/9] =?UTF-8?q?feature:=20=E6=94=AF=E6=8C=81=E8=A1=A8?= =?UTF-8?q?=E5=8D=95=E8=A7=86=E5=9B=BE=E5=92=8C=E4=BB=A3=E7=A0=81=E8=A7=86?= =?UTF-8?q?=E5=9B=BE=E5=90=8C=E6=97=B6=E8=BF=9B=E8=A1=8C=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/code-view.component.tsx | 12 ++++- .../composition/command.service.tsx | 11 ++-- .../src/components/designer.component.tsx | 52 ++++++++++++++----- .../designer/src/components/types/command.ts | 2 +- 4 files changed, 58 insertions(+), 19 deletions(-) diff --git a/packages/designer/src/components/components/code-view/components/code-view.component.tsx b/packages/designer/src/components/components/code-view/components/code-view.component.tsx index 75315e983de..8723c98fa0c 100644 --- a/packages/designer/src/components/components/code-view/components/code-view.component.tsx +++ b/packages/designer/src/components/components/code-view/components/code-view.component.tsx @@ -114,7 +114,15 @@ export default defineComponent({ */ async function handleSaveBtnClicked(): Promise { const results = await editorController.doSaveAllFile(props.directlyNotifySaveAllResults); - context.emit('saveAll', results); + context.emit('saveAll', { results }); + } + + /** + * 由外部触发的构件保存事件 + */ + async function triggerSaveAllFiles(loadingInstanceByDesigner: any): Promise { + const results = await editorController.doSaveAllFile(props.directlyNotifySaveAllResults); + context.emit('saveAll', { results, triggerByDesigner: true, loadingInstanceByDesigner }); } /** @@ -268,7 +276,7 @@ export default defineComponent({
*/}
; } - context.expose({ refreshNavTree, open, sendNotification, openAndGoTo }); + context.expose({ refreshNavTree, open, sendNotification, openAndGoTo, triggerSaveAllFiles }); return () => { return ( diff --git a/packages/designer/src/components/composition/command.service.tsx b/packages/designer/src/components/composition/command.service.tsx index 4fa5dc66715..96d482fea8a 100644 --- a/packages/designer/src/components/composition/command.service.tsx +++ b/packages/designer/src/components/composition/command.service.tsx @@ -82,8 +82,11 @@ export function useFormCommandService(formSchemaService: UseFormSchema, useFormS return commands; } /** 0.获取webcmd控制器(其参数为空)*/ - function checkCommands(): Promise { - const loadingInstance: any = FLoadingService.show({ message: '数据加载中,请稍候...' }); + function checkCommands(showLoading = true): Promise { + let loadingInstance: any; + if (showLoading) { + loadingInstance = FLoadingService.show({ message: '数据加载中,请稍候...' }); + } return new Promise((resolve, reject) => { loadWebcmd().then((webCmds) => { commands = cloneDeep(webCmds); @@ -91,11 +94,11 @@ export function useFormCommandService(formSchemaService: UseFormSchema, useFormS checkViewModelCommands(webCmds); updateViewModels(webCmds); syncActions(); - loadingInstance.value?.close(); + loadingInstance?.value?.close(); resolve([]); }).catch((error) => { messageService.warning(error?.response?.data?.Message || '加载控制器失败'); - loadingInstance.value?.close(); + loadingInstance?.value?.close(); reject(error); }); }); diff --git a/packages/designer/src/components/designer.component.tsx b/packages/designer/src/components/designer.component.tsx index 89d705d728e..2068c63da96 100644 --- a/packages/designer/src/components/designer.component.tsx +++ b/packages/designer/src/components/designer.component.tsx @@ -123,22 +123,33 @@ export default defineComponent({ /** * 保存表单 + * @param needRunForm 是否需要运行表单 + * @param triggerByCodeEditor 是否由代码编辑器触发的保存(在代码视图中点击保存按钮:先保存代码,然后触发表单的保存) + * @param showLoading 是否显示遮罩 */ - function saveFormMetadata(needRunForm: boolean = false) { + function saveFormMetadata(needRunForm: boolean = false, triggerByCodeEditor = false, showLoading = true) { if (formDesignerRef.value && !formDesignerRef.value.prepareBeforeSaveForm()) { return; }; - const loadingInstance = loadingService?.show({ message: '保存中,请稍候...' }); - useFormMetadataComposition.saveFormMetadata().then(() => { - !needRunForm && notifyService.success({ message: '表单保存成功' }); - loadingInstance.value.close(); + let loadingInstance: any; + if (showLoading) { + loadingInstance = loadingService?.show({ message: '保存中,请稍候...' }); + } + return useFormMetadataComposition.saveFormMetadata().then(async () => { + if (triggerByCodeEditor) { + !needRunForm && notifyService.success({ message: '保存成功' }); + loadingInstance?.value.close(); + } else { + await codeViewComponent.value.triggerSaveAllFiles(loadingInstance); + } + if (needRunForm && useFormMetadataComposition.runForm) { useFormMetadataComposition.runForm(loadingService, messageBoxService, designerContext, metadataPath); } }, (error) => { messageBoxService.error(error?.response?.data?.Message || '表单保存失败'); - loadingInstance.value.close(); + loadingInstance?.value.close(); }); } @@ -195,12 +206,31 @@ export default defineComponent({ currentViewType.value = 'codeEditor'; } } - // 代码编辑器保存的时候触发 - function onCodeViewSaveAll(results) { + /** + * 代码视图下,保存了全部文件后事件。 + * @param data result:各文件的保存结果;triggerByDesigner:是否由表单视图触发的保存;loadingInstanceByDesigner: 遮罩组件实例,若当前是由表单视图触发的保存,则此实例有值。 + */ + function onCodeViewSaveAll(data: { results: any, triggerByDesigner: boolean, loadingInstanceByDesigner: any }) { + const { results, triggerByDesigner, loadingInstanceByDesigner } = data; if (results) { const successes = results.filter(item => item.success); if (successes.length === results.length) { - notifyService.success({ message: '保存成功' }); + if (triggerByDesigner) { + formCommandService.checkCommands(false).then(() => { + formDesignerRef.value?.reloadPropertyPanel(); + loadingInstanceByDesigner?.value?.close(); + notifyService.success({ message: '保存成功' }); + }); + } else { + const loadingInstance = loadingService?.show({ message: '保存中,请稍候...' }); + formCommandService.checkCommands(false).then(async () => { + formDesignerRef.value?.reloadPropertyPanel(); + await saveFormMetadata(false, !triggerByDesigner, false); + loadingInstance?.value.close(); + }, () => { + loadingInstance?.value.close(); + }); + } } else { const failedResults = results.filter(item => !item.success); let message = ''; @@ -208,11 +238,9 @@ export default defineComponent({ message += `

${failedInfo.name} ${failedInfo.tip}

`; }); messageBoxService.error(message, ''); + loadingInstanceByDesigner?.value?.close(); } } - formCommandService.checkCommands().then(() => { - formDesignerRef.value?.reloadPropertyPanel(); - }); } /** diff --git a/packages/designer/src/components/types/command.ts b/packages/designer/src/components/types/command.ts index fed3f344e02..d051aa13dd7 100644 --- a/packages/designer/src/components/types/command.ts +++ b/packages/designer/src/components/types/command.ts @@ -8,7 +8,7 @@ export interface UseCommandBuilderService { jumpToCodeView: (param: { tsFilePathName: string, command: WebCommand }) => void; } export interface UseFormCommandService { - checkCommands: () => Promise; + checkCommands: (showLoading?: boolean) => Promise; commandsChanged: (newController) => void; generateInternalCommandList: () => any; viewModelDisplay: () => Array; -- Gitee From 5b92a7e18c70421938a1466c469970654a57c4e4 Mon Sep 17 00:00:00 2001 From: wang-xh Date: Wed, 13 Aug 2025 11:59:25 +0800 Subject: [PATCH 5/9] =?UTF-8?q?feature:=20=E4=BC=98=E5=8C=96=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E9=80=9A=E8=AE=AF=E4=BA=A4=E4=BA=92=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81=E5=90=8C=E6=97=B6=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E5=92=8C=E9=80=9A=E8=AE=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../method-list/method-list.component.tsx | 2 +- .../composition/command.service.tsx | 174 +++++++++-- .../composition/events-editor-utils.ts | 34 +- .../components/composition/use-form-schema.ts | 2 +- .../composition/use-form-validation.ts | 5 +- .../designer/src/components/types/command.ts | 2 + .../composition/data/use-data-view.ts | 2 +- .../src/dynamic-view.component.tsx | 18 +- .../bound-event-selector.component.tsx | 235 +++++++++++++- .../bound-event-selector.css | 46 ++- .../bound-event-selector.props.ts | 5 +- .../combine-command-item.component.tsx | 201 ++++++++++++ .../combine-form/combine-form.component.tsx | 121 +++----- .../components/combine-form/combine-form.scss | 248 ++++++++------- .../combine-form/select-command.component.tsx | 124 +++++--- .../select-parameter.component.tsx | 27 +- .../select-source-control.component.tsx | 83 +---- .../select-target-form.component.tsx | 115 ------- .../combine-form/use-communication.ts | 209 ++++++++++--- .../command-source.component.tsx | 21 +- .../command-source/command-source.props.ts | 5 +- .../interaction-button.component.tsx | 42 ++- .../interaction-item.component.tsx | 292 ++++++++++++++---- .../parameter-editor.component.tsx | 41 +-- .../parameter-editor/parameter-editor.css | 15 +- .../parameter-editor.props.ts | 4 +- .../events-editor/src/composition/types.ts | 6 +- .../src/composition/use-interaction.ts | 32 +- .../src/composition/use-methods.ts | 23 +- .../src/events-editor.component.tsx | 52 +++- .../events-editor/src/events-editor.css | 4 +- .../components/events-editor/src/types.ts | 5 +- .../external-container.design.component.tsx | 6 +- .../external-container.property-config.ts | 12 +- .../schema-selector/src/schema-selector.css | 4 +- 35 files changed, 1504 insertions(+), 713 deletions(-) create mode 100644 packages/ui-vue/components/events-editor/src/components/combine-form/combine-command-item.component.tsx delete mode 100644 packages/ui-vue/components/events-editor/src/components/combine-form/select-target-form.component.tsx diff --git a/packages/designer/src/components/components/view-model-designer/method-manager/components/method-list/method-list.component.tsx b/packages/designer/src/components/components/view-model-designer/method-manager/components/method-list/method-list.component.tsx index 1b2527f1656..8476e6ccb26 100644 --- a/packages/designer/src/components/components/view-model-designer/method-manager/components/method-list/method-list.component.tsx +++ b/packages/designer/src/components/components/view-model-designer/method-manager/components/method-list/method-list.component.tsx @@ -134,7 +134,7 @@ export default defineComponent({ if (!controllerLabel) { return false; } - return controllerLabel.indexOf(useFormSchemaComposition.getModule().code) > -1 + return controllerLabel.indexOf(useFormSchemaComposition.getModule().code) > -1; }; function onViewMethodSource($event) { diff --git a/packages/designer/src/components/composition/command.service.tsx b/packages/designer/src/components/composition/command.service.tsx index 4fa5dc66715..627f63ec710 100644 --- a/packages/designer/src/components/composition/command.service.tsx +++ b/packages/designer/src/components/composition/command.service.tsx @@ -17,6 +17,7 @@ import { ParamConfig } from "../components/view-model-designer/method-manager/en import { CallbackFn, useComponentProvider } from './use-component-provider'; import { DesignerMode } from "../types/designer-context"; +import { Communication } from '@farris/ui-vue/components/events-editor'; export function useFormCommandService(formSchemaService: UseFormSchema, useFormStateMachineComposition: UseFormStateMachine, loadingService: FLoadingService, webCmpBuilderService: UseCommandBuilderService): UseFormCommandService { const { externalComponentProps, externalComponents, externalParamterEditor } = useComponentProvider(); @@ -627,27 +628,81 @@ export function useFormCommandService(formSchemaService: UseFormSchema, useFormS }); checkViewModelCommands(commands); } - function generateCommunication(propertyData: any, event, events) { - const eventLabel = propertyData[event.label]; - const communicationIds = eventLabel.slice(eventLabel.indexOf(':') + 1, eventLabel.length); - const communicationIdArray = communicationIds.split(';'); - communicationIdArray.forEach(communicationId => { - const boundEventsListItem = { - command: {}, - controller: {}, - boundEvents: {}, - communication: { - id: communicationId, + /** + * 将同源的通讯配置合并为一个交互 + */ + function groupCommunicationBySource(communicationIdArray: string[]) { + const allCommunications = formSchemaService.getFormSchema().module.communications; + const currentCommunications = allCommunications?.filter(item => communicationIdArray.includes(item.id)); + // 创建映射表,key为source的唯一标识,value为该组的通信项数组 + const groups: Record = {}; + if (currentCommunications?.length) { + for (const comm of currentCommunications) { + const { formId, componentId, event, formCode, externalContainerId } = comm.source; + const key = [formId, componentId, event, formCode || '', externalContainerId || ''].join('|'); + if (!groups[key]) { + groups[key] = []; } - }; - events.forEach(each => { - if (each.label === event.label) { boundEventsListItem.boundEvents = cloneDeep(each); } - }); + groups[key].push({ id: comm.id }); + } + } + return Object.values(groups); + } + /** + * 组装控件的通讯类交互事件 + */ + function generateCommunication(event, events, communication: string) { + if (communication) { + const communicationIds = communication.replace(/communication:/g, ''); + const communicationIdArray = communicationIds.split(';'); - boundEventsList.push(cloneDeep(boundEventsListItem)); - }); + // 对于外部容器配置的通讯,将同源的通讯合并为一个交互,不同源的通讯是多条交互; + // 对于当前表单控件配置的通讯(已经是同源了),认为是一个交互下的多条通讯 + if (event.label === 'onCommunication') { + const groupedCommunications = groupCommunicationBySource(communicationIdArray); + groupedCommunications.map((item) => { + const boundEventsListItem = { + command: {}, + controller: {}, + boundEvents: {}, + communication: item + }; + events.forEach(each => { + if (each.label === event.label) { boundEventsListItem.boundEvents = cloneDeep(each); } + }); + boundEventsList.push(cloneDeep(boundEventsListItem)); + }); + } else { + return communicationIdArray.map(communicationId => { return { id: communicationId }; }); + } + } } + + /** + * 从控件schema中解析某一事件绑定的命令值和通讯值。因为事件中可能同时绑定命令和组件通讯 + * @param propertyData 控件schema + * @param eventLabel 事件编号 + */ + function splitCommandAndCommunicationFromEvent(propertyData: any, eventLabel: string) { + if (!propertyData[eventLabel]) { + return { command: '', communication: '' }; + } + let commandValue = propertyData[eventLabel]; + let communicationValue = ''; + if (propertyData[eventLabel].includes('communication:')) { + const valueArray = propertyData[eventLabel].split(';') || []; + const communicationItems = valueArray.filter(item => item.includes('communication:')); + const commandValueItems = valueArray.filter(item => !item.includes('communication:')); + if (communicationItems.length > 0) { + communicationValue = communicationItems.join(';'); + commandValue = commandValueItems.join(';'); + } + } + + return { command: commandValue, communication: communicationValue }; + } + /** * 事件面板调用-1 * a. 合并视图模型带参数的命令&控制器中无参数的命令 @@ -659,14 +714,36 @@ export function useFormCommandService(formSchemaService: UseFormSchema, useFormS // 1. 遍历当前container的组件dom结构的所有事件的值 events.forEach(event => { if (propertyData[event.label]) { - if (propertyData[event.label].includes('communication:')) { - generateCommunication(propertyData, event, events); - return; + const { command, communication } = splitCommandAndCommunicationFromEvent(propertyData, event.label); + const boundEventsListItem: any = { + command: { + }, + controller: { + }, + boundEvents: { + }, + communication: [] + }; + events.forEach(each => { + if (each.label === event.label) { boundEventsListItem.boundEvents = cloneDeep(each); } + }); + if (command) { + // 三段式path:root-viewmodel.items-component-viewmodel.itemsAddItem1 或 一段path:itemsAddItem1 + const paths = command.includes('.') ? command.split('.') : undefined; + const { recordCommand, recordController } = handleParams(viewModelData, paths, command, viewModelId, allComponentList); + const commandItem = generateBoundEventsList(event, events, recordController, recordCommand); + if (commandItem) { + Object.assign(boundEventsListItem, commandItem); + } + } + const communicationItems = generateCommunication(event, events, communication); + if (communicationItems?.length) { + boundEventsListItem.communication = communicationItems; + } + + if (boundEventsListItem.command?.id || boundEventsListItem.communication?.length) { + boundEventsList.push(boundEventsListItem); } - // 三段式path:root-viewmodel.items-component-viewmodel.itemsAddItem1 或 一段path:itemsAddItem1 - const paths = propertyData[event.label].includes('.') ? propertyData[event.label].split('.') : undefined; - const { recordCommand, recordController } = handleParams(viewModelData, paths, propertyData[event.label], viewModelId, allComponentList); - generateBoundEventsList(event, events, recordController, recordCommand); } }); return boundEventsList; @@ -821,7 +898,7 @@ export function useFormCommandService(formSchemaService: UseFormSchema, useFormS }); boundEventsListItem.controller = cloneDeep(recordController.controllerName); boundEventsListItem.command = cloneDeep(recordCommand); - boundEventsList.push(cloneDeep(boundEventsListItem)); + return boundEventsListItem; } } @@ -832,10 +909,11 @@ export function useFormCommandService(formSchemaService: UseFormSchema, useFormS const viewModelData = cloneDeep(formSchemaService.getViewModels()); events.forEach(event => { // 1. 遍历当前container的dom结构的所有事件的值 - if (propertyData[event.label] && !propertyData[event.label].includes('communication:')) { + const { command: commandValue } = splitCommandAndCommunicationFromEvent(propertyData, event.label); + if (commandValue) { // 三段式path:root-viewmodel.items-component-viewmodel.itemsAddItem1 或 一段path:itemsAddItem1 - const paths = propertyData[event.label].includes('.') ? propertyData[event.label].split('.') : undefined; - handleViewModel(viewModelData, paths, propertyData[event.label], viewModelId, domActions, propertyData); + const paths = commandValue.includes('.') ? commandValue.split('.') : undefined; + handleViewModel(viewModelData, paths, commandValue, viewModelId, domActions, propertyData); } }); formSchemaService.setViewmodels(cloneDeep(viewModelData)); @@ -1104,6 +1182,40 @@ export function useFormCommandService(formSchemaService: UseFormSchema, useFormS } return suffix; } + + /** + * 设置控件的事件属性(将普通命令和组件通讯合并,以逗号分隔) + * @param controlSchema 控件schmea + * @param eventLabel 控件事件编号 + * @param newCommandValue 新命令值,为空字符串代表清空值,为null代表保留已有命令 + * @param newCommunicationValue 新组件通讯值,为空字符串代表清空值,为null代表保留已有通讯 + */ + function setControlEventValue(controlSchema: any, eventLabel: string, newCommandValue: any, newCommunicationValue: any) { + let commandValue = ''; + let communicationValue = ''; + const valueArray = controlSchema[eventLabel] ? controlSchema[eventLabel].split(';') : []; + + if (controlSchema[eventLabel]?.includes('communication:')) { + communicationValue = valueArray.filter(item => item.startsWith('communication:')).join(';'); + } + commandValue = (controlSchema[eventLabel] || '').replace(communicationValue, '').replace(';', ''); + + if (newCommandValue !== null && newCommandValue !== undefined) { + commandValue = newCommandValue; + } + if (newCommunicationValue !== null && newCommunicationValue !== undefined) { + communicationValue = newCommunicationValue; + } + const newValueArray: any = []; + if (commandValue) { + newValueArray.push(commandValue); + } + if (communicationValue) { + newValueArray.push(communicationValue); + } + controlSchema[eventLabel] = newValueArray.join(';'); + + } /** * 代码视图返回新增方法的编号、名称后,由设计器将方法添加到控件上 * @param methodCode 新增方法的编号 @@ -1125,7 +1237,7 @@ export function useFormCommandService(formSchemaService: UseFormSchema, useFormS methodCode = codeSuffix > 0 ? methodCode + codeSuffix : methodCode; methodName = codeSuffix > 0 ? methodName + codeSuffix : methodName; // 1、控件绑定命令 - newControllerMethodBindingInfo.controlData[eventCode] = methodCode; + setControlEventValue(newControllerMethodBindingInfo.controlData, eventCode, methodCode, null); // 2、控件绑定命令后,可能会需要联动其他属性的变更 if (newControllerMethodBindingInfo.setPropertyRelates) { @@ -1298,6 +1410,8 @@ export function useFormCommandService(formSchemaService: UseFormSchema, useFormS checkCommands, commandsChanged, generateInternalCommandList, viewModelDisplay, findParamtersPosition, addControllerMethod, viewModelDomChanged, getCommands, bindNewMethodToControl, getInternalControllerFromControllerMetadata, getSupportedControllerMetadata, getEventParameterGeneralData, webCmpBuilderService, syncActions, findBoundEvent, - getUniqueEvent + getUniqueEvent, + setControlEventValue, + splitCommandAndCommunicationFromEvent }; } diff --git a/packages/designer/src/components/composition/events-editor-utils.ts b/packages/designer/src/components/composition/events-editor-utils.ts index 67a866b13b0..b609bf797a7 100644 --- a/packages/designer/src/components/composition/events-editor-utils.ts +++ b/packages/designer/src/components/composition/events-editor-utils.ts @@ -81,7 +81,6 @@ export function useEventsEditorUtils(commandService: UseFormCommandService, form if (parameters.isAddControllerMethod) { if (!parameters.controlInfo && propertyData.type) { - // parameters.controlInfo = { type: propertyData.type, name: DgControl[propertyData.type] && DgControl[propertyData.type].name }; parameters.controlInfo = { type: propertyData.type, name: propertyData.type }; } @@ -186,6 +185,7 @@ export function useEventsEditorUtils(commandService: UseFormCommandService, form }); return actions; } + /** * 将组件通讯数据保存到控件dom中 */ @@ -195,43 +195,47 @@ export function useEventsEditorUtils(commandService: UseFormCommandService, form return eventItem.boundEvents.label === event.label; } }); - if (data[event.label] && data[event.label].includes('communication:')) { - data[event.label] = null; - } + const communicationIds: string[] = []; + if (relatedBoundList.length) { - const communicationIds: string[] = []; relatedBoundList.map(boundCommunication => { - if (boundCommunication.communication) { - communicationIds.push(boundCommunication.communication.id); - deleteActionItem(data.id, event.label); + if (boundCommunication.communication?.length) { + boundCommunication.communication.map((item) => { + communicationIds.push(`communication:${item.id}`); + }); return; } }); if (communicationIds.length) { - data[event.label] = `communication:${communicationIds.join(';')}`; + commandService.setControlEventValue(data, event.label, null, communicationIds.join(';')); + } else { + commandService.setControlEventValue(data, event.label, null, ''); } + } else { + commandService.setControlEventValue(data, event.label, null, ''); } } /** 增删改组件dom中事件绑定值 */ function eventsValueChanged(data, actions, eventList, parameters) { // 增加或修改:data[事件id] = 'viewModelId.targetComponent-viewModelId.command'; actions.sourceComponent.map.forEach(mapItem => { + let newCommandValue; // 判断是存储为三段path或一段path if (mapItem.targetComponent.viewModelId && (actions.sourceComponent.viewModelId !== mapItem.targetComponent.viewModelId)) { - data[mapItem.event.label] = cloneDeep(`root-viewmodel.${mapItem.targetComponent.viewModelId}.${mapItem.command.label}`); + newCommandValue = cloneDeep(`root-viewmodel.${mapItem.targetComponent.viewModelId}.${mapItem.command.label}`); } else { - data[mapItem.event.label] = cloneDeep(`${mapItem.command.label}`); + newCommandValue = cloneDeep(`${mapItem.command.label}`); } + commandService.setControlEventValue(data, mapItem.event.label, newCommandValue, null); + }); /** 删除 data[事件id] = null */ eventList.forEach(event => { resolveCommunicationValue(data, event, parameters); - if (data[event.label]?.includes('communication:')) { - return; - } + const exist = actions.sourceComponent.map.find(mapItem => mapItem.event.label === event.label); if (!exist) { - data[event.label] = null; + commandService.setControlEventValue(data, event.label, '', null); deleteActionItem(data.id, event.label); } }); diff --git a/packages/designer/src/components/composition/use-form-schema.ts b/packages/designer/src/components/composition/use-form-schema.ts index 84dc6ced8a3..47c631d8f47 100644 --- a/packages/designer/src/components/composition/use-form-schema.ts +++ b/packages/designer/src/components/composition/use-form-schema.ts @@ -1260,7 +1260,7 @@ export function useFormSchema(): UseFormSchema { Object.keys(controlEventPropertyIDList).forEach(propertyId => { const propertyValue = componentSchema[propertyId]; if (propertyValue && propertyValue.includes('communication:')) { - const communicationIds = propertyValue.replace('communication:', '').split(';'); + const communicationIds = propertyValue.replace(/communication:/g, '').split(';'); formSchema.module.communications = formSchema.module.communications?.filter(communication => !communicationIds.includes(communication.id)); } }); diff --git a/packages/designer/src/components/composition/use-form-validation.ts b/packages/designer/src/components/composition/use-form-validation.ts index edeeb22b997..5931eae4032 100644 --- a/packages/designer/src/components/composition/use-form-validation.ts +++ b/packages/designer/src/components/composition/use-form-validation.ts @@ -123,12 +123,13 @@ export function useFormValidation(useFormSchema: UseFormSchema, formCommandServi * 校验控件的组件通讯配置是否完整 */ function checkCommunicationValid(boundEvent: any) { - const { commandLabel } = boundEvent; + const { commandLabel, eventLabel } = boundEvent; + const { communication } = formCommandService.splitCommandAndCommunicationFromEvent({ [eventLabel]: commandLabel }, eventLabel); const controlInfo = useFormSchema.getControlBasicInfoMap().get(boundEvent.id); // 控件名称 const controlName = (controlInfo && controlInfo.parentPathName) || boundEvent.id; - const communicationIds = commandLabel.replace('communication:', '').split(';'); + const communicationIds = communication.replace(/communication:/g, '').split(';'); if (communicationIds?.length) { const communications = useFormSchema.getFormSchema().module.communications || []; for (const communicationId of communicationIds) { diff --git a/packages/designer/src/components/types/command.ts b/packages/designer/src/components/types/command.ts index fed3f344e02..d92ad4959ce 100644 --- a/packages/designer/src/components/types/command.ts +++ b/packages/designer/src/components/types/command.ts @@ -24,6 +24,8 @@ export interface UseFormCommandService { syncActions: () => any; findBoundEvent: (components: any[], findEvents: any[], viewModelId: string, excludedEvents?: string[]) => any; getUniqueEvent: (allBoundEvents: any[]) => any[]; + setControlEventValue: (controlSchema: any, eventLabel: string, newCommandValue: any, newCommunicationValue: any) => void; + splitCommandAndCommunicationFromEvent: (propertyData: any, eventLabel: string) => { command: string, communication: string }; } diff --git a/packages/ui-vue/components/data-view/composition/data/use-data-view.ts b/packages/ui-vue/components/data-view/composition/data/use-data-view.ts index a1f6bd0a79f..d480277c271 100644 --- a/packages/ui-vue/components/data-view/composition/data/use-data-view.ts +++ b/packages/ui-vue/components/data-view/composition/data/use-data-view.ts @@ -41,7 +41,7 @@ export function useDataView( const sorters = ref([]); const groupComposition = useGroupData(props, useIdentifyCompostion); const { generateGroupData, groupFields, shouldGroupingData } = groupComposition; - const originalData = ref(props.data); + const originalData = ref(props.data||[]); const hierarchyDataComposition = useHierarchyData(props, originalData, useHierarchyCompostion, useIdentifyCompostion); const { collapseTo: collpaseToLayer, expandTo: expandToLayer, generateHierarchyData, hasRealChildren, insertSibling, insertChild, insertChildren, isVisibleInTree, diff --git a/packages/ui-vue/components/dynamic-view/src/dynamic-view.component.tsx b/packages/ui-vue/components/dynamic-view/src/dynamic-view.component.tsx index 214b5240826..1dc39883a9e 100644 --- a/packages/ui-vue/components/dynamic-view/src/dynamic-view.component.tsx +++ b/packages/ui-vue/components/dynamic-view/src/dynamic-view.component.tsx @@ -404,15 +404,21 @@ const FDynamicView = defineComponent({ } convertModelValueToProps(viewSchema); }); + function resolveInitialSchema(newSchema: any) { + if (newSchema) { + schema.value = newSchema; + const viewSchema = getFrameComponentSchema(); + if (!viewSchema) { + return; + } + convertSchemaToProps(viewSchema); + } + } watch(() => props.schema, (newSchema) => { - schema.value = newSchema; - const viewSchema = getFrameComponentSchema(); - if (!viewSchema) { - return; - } - convertSchemaToProps(viewSchema); + resolveInitialSchema(newSchema); }); + resolveInitialSchema(props.schema); setupContext.expose({ componentManager, rerender, getProps, invoke, setProps, selectItemById, getSchema, setSchema, convertPartialSchemaToProps, getControlValue }); diff --git a/packages/ui-vue/components/events-editor/src/components/bound-event-selector/bound-event-selector.component.tsx b/packages/ui-vue/components/events-editor/src/components/bound-event-selector/bound-event-selector.component.tsx index 346f34f132c..632c974c14c 100644 --- a/packages/ui-vue/components/events-editor/src/components/bound-event-selector/bound-event-selector.component.tsx +++ b/packages/ui-vue/components/events-editor/src/components/bound-event-selector/bound-event-selector.component.tsx @@ -1,4 +1,4 @@ -import { SetupContext, defineComponent, ref, onBeforeMount, inject } from "vue"; +import { SetupContext, defineComponent, ref, onBeforeMount, inject, computed } from "vue"; import { boundEventSelectorProps, BoundEventSelectorProps } from "./bound-event-selector.props"; import FInputGroup from '@farris/ui-vue/components/input-group'; import { cloneDeep } from "lodash-es"; @@ -16,8 +16,15 @@ export default defineComponent({ const viewModelDisplay = ref(); const viewModelData = ref([]); const groupIcon = ref(''); + const formMetaBasicInfo = props.useFormSchema.getFormMetadataBasicInfo(); const searchValue = ref(''); const selectedCommand = ref(); + /** 是否显示左侧页面列表。在组合表单场景中已有方法可以选择当前页面下的方法或者子表单下的方法 */ + const shouldShowPageList = ref(props.useFormSchema.externalFormSchema?.size > 0); + /** 当前选中的页面 */ + const selectedForm = ref(); + /** 外部页面的方法 */ + const methodsFromCombineForm: any = ref([]); onBeforeMount(() => { if (props.getEventPath) { @@ -34,8 +41,9 @@ export default defineComponent({ } }); - /** 匹配满足条件的方法并显示 */ - function matchCommand(changeValue = '') { + + /** 搜索当前页面的命令 */ + function matchCommandInCurrentForm(changeValue = '') { changeValue = changeValue.replace(/ /g, '').replace(/>/g, '').toLowerCase(); if (changeValue === '') { changeValue = ' '; @@ -57,20 +65,66 @@ export default defineComponent({ } + /** 搜索子表单下的命令 */ + function matchCommandInCombinedForm(changeValue = '') { + changeValue = changeValue.replace(/ /g, '').replace(/>/g, '').toLowerCase(); + methodsFromCombineForm.value.forEach(mapItem => { + if (!mapItem.isCommandNode) { + return; + } + const methodNameString = mapItem.name || ''; + const methodCodeString = mapItem.code || ''; + const methodViewmodelString = mapItem.viewmodelName || ''; + const searchContent = `${methodNameString}${methodCodeString}${methodViewmodelString}`.toLowerCase(); + if (changeValue && !searchContent.includes(changeValue)) { + mapItem['hide'] = true; + } else { + mapItem['hide'] = false; + } + }); + } + + /** 触发搜索 */ + function onSearch(changeValue = '') { + if (!selectedForm.value || selectedForm.value.id === formMetaBasicInfo.id) { + matchCommandInCurrentForm(changeValue); + } else { + matchCommandInCombinedForm(changeValue); + } + } + + /** 渲染搜索条 */ function renderViewModelSearchBar() { - return ( -