diff --git a/packages/designer/src/components/components/entity-tree-view/components/create-new-field.component.tsx b/packages/designer/src/components/components/entity-tree-view/components/create-new-field.component.tsx index b264bbac1dd25449e0c3228c57e06f9ed0ccecd2..48669cd7c749f8047f3545750f8e11b0aec0b9cb 100644 --- a/packages/designer/src/components/components/entity-tree-view/components/create-new-field.component.tsx +++ b/packages/designer/src/components/components/entity-tree-view/components/create-new-field.component.tsx @@ -2,7 +2,7 @@ import { FLoadingService, FNotifyService } from '@farris/ui-vue'; import { defineComponent, inject, ref, SetupContext, computed, onMounted } from 'vue'; import { ExtendFieldEntity, FieldTypeEnums } from '../composition/extend-field'; import { CreateNewFieldProps, createNewFieldProps } from './entity-tree-view.props'; -import { FComboList, FNumberSpinner, FSwitch, FSchemaSelectorEditor, LookupSchemaRepositoryToken, FComboTree, VisualData } from '@farris/ui-vue/components'; +import { FComboList, FNumberSpinner, FSwitch, FSchemaSelectorEditor, LookupSchemaRepositoryToken, FComboTree, VisualData, FPropertyEditor } from '@farris/ui-vue/components'; import { useNewFieldVerification } from '../composition/use-new-field-verification'; import { useNewFieldUtil } from '../composition/use-new-field-util'; @@ -26,6 +26,8 @@ export default defineComponent({ resolveFieldInfo, helpMetadataName, onSubmitHelpMetadata, onHelpMetadataSelected, helpSchemaTreeData, relatedHelpFieldIds, onHelpRelatedFieldsChanged, relatedFieldsTreeData, helpFieldId, onHelpBindingFieldsChanged } = useNewFieldUtil(props, extendField); + /** 默认值组件实例 */ + const defaultValueRef = ref(); /** 字段标签行样式 */ const fieldLabelSpanClass = computed(() => { @@ -37,16 +39,14 @@ export default defineComponent({ }; }); - onMounted(() => { - }); function onCancel() { context.emit('cancel'); } function onSubmit() { const loadingInstance = loadingService.show(); - if (!checkFieldValidation()) { + if (!checkFieldValidation(helpMetadataName, relatedHelpFieldIds, helpFieldId, defaultValueRef)) { loadingInstance.value.close(); return; } @@ -115,6 +115,34 @@ export default defineComponent({ onChange={onHelpBindingFieldsChanged} >; } + /** 渲染默认值编辑器 */ + function renderDefaultValueEditor() { + const valueTypes = ['Custom', 'Expression']; + const expressionConfig = { + dialogTitle: '默认值编辑器', + showMessage: false, + showDataPanel: false, + expressionInfo: { + expressionType: 'defaultValue', + targetId: extendField.value.id + } + }; + function onDefaultValueChanged(newValue: any) { + if (newValue?.type === 'Expression') { + extendField.value.defaultValue = { + type: 'expression', + value: newValue.expressionInfo?.value + }; + } else { + extendField.value.defaultValue = newValue; + + } + } + + return + ; + } return () => { return
@@ -161,6 +189,7 @@ export default defineComponent({ precision="0" max={maxPrecision.value}> )} + {renderEditor('字段默认值', renderDefaultValueEditor())} {renderEditor('是否必填', )} diff --git a/packages/designer/src/components/components/entity-tree-view/components/entity-tree-view.component.tsx b/packages/designer/src/components/components/entity-tree-view/components/entity-tree-view.component.tsx index e4886785ed964848562f4d7a8e2333c809bc2260..a2d037d151bfbab845467bfbfbd5c685ff7de714 100644 --- a/packages/designer/src/components/components/entity-tree-view/components/entity-tree-view.component.tsx +++ b/packages/designer/src/components/components/entity-tree-view/components/entity-tree-view.component.tsx @@ -15,12 +15,11 @@ */ import { defineComponent, inject, ref, SetupContext, watch, nextTick, onMounted, Ref } from 'vue'; import { FButton } from '@farris/ui-vue/components'; -import { FSearchBox } from "@farris/ui-vue/components"; import { FTreeView } from '@farris/ui-vue/components'; import { UseEntityTreeData } from '../composition/use-entity-tree-data'; import { entityTreeProps, EntityTreeProps } from './entity-tree-view.props'; import { useUpdateEntitySchema } from '../composition/use-update-entity-schema'; -import { UseControlCreator, UseDesignViewModel, UseFormSchema, UseSchemaService } from '../../../../components/types'; +import { UseControlCreator, UseDesignViewModel, UseSchemaService } from '../../../../components/types'; import { cloneDeep } from 'lodash-es'; import '../composition/entity-tree-view.css'; import './entity-tree-view.scss'; @@ -29,6 +28,7 @@ import { FLoadingService } from '@farris/ui-vue/components'; import { DesignerMode, UseDesignerContext } from '../../../../components/types/designer-context'; import { useOpenNewEntity } from '../composition/use-new-entity'; import { useOpenNewField } from '../composition/use-new-field-modal'; +import { useOpenModifyField } from '../composition/use-modify-field-modal'; export default defineComponent({ name: 'FEntityTreeView', @@ -108,7 +108,8 @@ export default defineComponent({ 'occupied': dataItem?.isOccupied, 'no-drag': !dataItem?.draggable, 'drag-copy': dataItem?.draggable, - [`id=${dataItem.id}`]: true + [`id=${dataItem.id}`]: true, + 'from-outside': dataItem?.rtFieldSourceType || dataItem.rtRelateParentSchemaField }; }, customRowStatus: (visualData: VisualData) => { @@ -140,8 +141,10 @@ export default defineComponent({ newEntityCodeList.value = []; }); const { openNewEntityModal } = useOpenNewEntity(useFormSchema, existedEntityCodes, refreshEntityTree, newEntityCodeList); - const { openNewFieldModal } = useOpenNewField(useFormSchema, newEntityCodeList, refreshEntityTree, treeViewData); + const { openNewFieldModal } = useOpenNewField(useFormSchema, newEntityCodeList, refreshEntityTree, serializedTreeData); + const { openModifyFieldModal } = useOpenModifyField(useFormSchema, designViewModelUtils, refreshEntityTree, serializedTreeData, context); + /** 低代码:刷新实体(同步视图对象) */ function renderHeader() { if (designerMode !== DesignerMode.PC_RTC) { return
@@ -154,11 +157,13 @@ export default defineComponent({ return () => { return
- {{ @@ -167,10 +172,18 @@ export default defineComponent({ const rowData = row.raw; return <> {rowData.name} - {designerMode === DesignerMode.PC_RTC && row.raw.nodeType === 'entity' &&
- openNewFieldModal(event, row.raw)}> - {!row.raw.parent && } -
+ {/* 运行时定制实体节点,支持新增字段和新增子表 */} + {designerMode === DesignerMode.PC_RTC && rowData.nodeType === 'entity' && +
+ openNewFieldModal(event, row.raw)}> + {!rowData.parent && } +
+ } + {/* 运行时定制字段节点,支持修改字段属性(be或vo的字段不支持修改) */} + {rowData.nodeType === 'field' && !rowData.rtFieldSourceType && !rowData.rtRelateParentSchemaField && +
+ openModifyFieldModal(event, row.raw)}> +
} ; }, diff --git a/packages/designer/src/components/components/entity-tree-view/components/entity-tree-view.props.ts b/packages/designer/src/components/components/entity-tree-view/components/entity-tree-view.props.ts index 1e321420472237a217c99461fec7d976680590fc..633bb0c8217c18cd4d3853e2db6f64ae66a245f9 100644 --- a/packages/designer/src/components/components/entity-tree-view/components/entity-tree-view.props.ts +++ b/packages/designer/src/components/components/entity-tree-view/components/entity-tree-view.props.ts @@ -45,3 +45,14 @@ export const createNewFieldProps = { } as Record; export type CreateNewFieldProps = ExtractPropTypes; +export const modifyFieldProps = { + useFormSchema: { type: Object }, + /** 当前实体 */ + entityCode: { type: String }, + /** 当前编辑的字段节点 */ + fieldNode: { type: Object }, + /** 当前实体中已有的字段 */ + existedAllFields: { type: Object }, +} as Record; +export type ModifyFieldProps = ExtractPropTypes; + diff --git a/packages/designer/src/components/components/entity-tree-view/components/entity-tree-view.scss b/packages/designer/src/components/components/entity-tree-view/components/entity-tree-view.scss index 58519e45e31b85e224ba9b5f41a3e955cb774bc6..64ea453192e50bdc42e655884ebcab9f2b4a7d34 100644 --- a/packages/designer/src/components/components/entity-tree-view/components/entity-tree-view.scss +++ b/packages/designer/src/components/components/entity-tree-view/components/entity-tree-view.scss @@ -13,4 +13,12 @@ width: 26px; padding: 0 !important; } + + .toolbar-action.need-mouse-in { + display: none; + } + + .fv-grid-row:hover .toolbar-action.need-mouse-in { + display: inline-flex; + } } \ No newline at end of file diff --git a/packages/designer/src/components/components/entity-tree-view/components/modify-field.component.tsx b/packages/designer/src/components/components/entity-tree-view/components/modify-field.component.tsx new file mode 100644 index 0000000000000000000000000000000000000000..28cfb400acc6b399c9924d55306344ce01d65d60 --- /dev/null +++ b/packages/designer/src/components/components/entity-tree-view/components/modify-field.component.tsx @@ -0,0 +1,187 @@ +import { FNotifyService, FPropertyEditor } from '@farris/ui-vue/components'; +import { DesignerMode, UseDesignerContext } from '../../../../components/types/designer-context'; +import { defineComponent, inject, onBeforeMount, onMounted, ref, SetupContext } from 'vue'; +import { modifyFieldProps, ModifyFieldProps } from './entity-tree-view.props'; + +/** + * 维护字段属性 + */ +export default defineComponent({ + name: 'FModifyField', + props: modifyFieldProps, + emits: ['cancel', 'submit'] as (string[] & ThisType) | undefined, + setup(props: ModifyFieldProps, context: SetupContext) { + const notifyService: any = new FNotifyService(); + notifyService.globalConfig = { position: 'top-center' }; + // 获取当前设计器运行环境 + const designerContext = inject('designerContext') as UseDesignerContext; + const designerMode = designerContext.designerMode as DesignerMode; + + /** 当前修改的字段 */ + const fieldNode = ref(props.fieldNode); + /** 当前修改的字段名称 */ + const fieldName = ref(props.fieldNode.name); + /** 字段名称是否有效 */ + const fieldNameValid = ref(true); + /** 当前修改的默认值 */ + const fieldDefaultValue = ref(props.fieldNode.defaultValue); + /** 默认值组件实例 */ + const defaultValueRef = ref(); + /** 是否支持修改默认值 */ + const canModifyDefaultValue = ref(true); + + /** 校验字段名称是否重复 */ + function checkFieldNameValid() { + if (props.existedAllFields) { + const names = props.existedAllFields.map(fieldNode => fieldNode.data.name); + if (names.includes(fieldName.value) && fieldName.value !== fieldNode.value.name) { + fieldNameValid.value = false; + } else { + fieldNameValid.value = true; + } + } + } + /** 获取字段的根节点。例如关联带出字段Company.Company_Name,此处返回的是关联的根字段节点Company */ + function getRootFieldNode() { + if (props.existedAllFields) { + let rootField = fieldNode.value; + if (fieldNode.value.bindingPath?.includes('.')) { + const rootLabel = fieldNode.value.bindingPath.slice(0, fieldNode.value.bindingPath.indexOf('.')); + const rootNode = props.existedAllFields.find(node => node.parent === node.entityId && node.label === rootLabel); + if (rootNode?.data) { + rootField = rootNode.data; + } + } + return rootField; + + } + } + /** + * 校验是否支持配置默认值 + */ + function checkShowDefaultValue() { + + // UDT字段以及UDT带出字段不支持配置默认值 + const rootField = getRootFieldNode(); + if (rootField?.type?.$type === 'ObjectType') { + canModifyDefaultValue.value = false; + } + // 若当前实体表包含分级码类的udt,则整个实体表的字段都不支持默认值 + const fenjimaUdtField = props.existedAllFields?.find(field => field?.data?.$type === 'ComplexField' && field?.data?.type?.$type === 'HierarchyType'); + if (fenjimaUdtField) { + canModifyDefaultValue.value = false; + } + + } + + onBeforeMount(() => { + checkShowDefaultValue(); + }); + function onCancel() { + context.emit('cancel'); + } + + + function onSubmit() { + if (!fieldName.value) { + notifyService.warning('字段名称不能为空'); + return; + } + if (!fieldNameValid.value) { + notifyService.warning('字段名称重复'); + return; + } + if (defaultValueRef.value?.currentPropertyType === 'Expression' && !fieldDefaultValue.value?.value) { + notifyService.warning('请填写默认值表达式'); + return; + } + context.emit('submit', { + name: fieldName.value, + defaultValue: fieldDefaultValue.value, + modified: designerMode === 'PC_RTC' + }); + + } + /** 渲染默认值编辑器 */ + function renderDefaultValueEditor() { + const defaultValue = fieldDefaultValue.value?.type === 'expression' ? { + type: 'Expression', + value: fieldDefaultValue.value?.value + } : fieldDefaultValue.value; + const valueTypes = ['Custom', 'Expression']; + const expressionConfig = { + dialogTitle: '默认值编辑器', + showMessage: false, + showDataPanel: false, + expressionInfo: { + expressionType: 'defaultValue', + targetId: fieldNode.value.id, + value: defaultValue?.value ? defaultValue.value : null + } + }; + + function onDefaultValueChanged(newValue: any) { + if (newValue?.type === 'Expression') { + fieldDefaultValue.value = { + type: 'expression', + value: newValue.expressionInfo?.value + }; + } else { + fieldDefaultValue.value = newValue; + + } + } + return + ; + } + return () => { + return
+
+
+
+ +
+ + {fieldName.value && !fieldNameValid.value && +
+ 名称已存在,请重新输入。 +
} +
+
+
+
+
+ +
+ + +
+
+
+ {designerMode === 'PC_RTC' && canModifyDefaultValue.value &&
+
+ +
+ {renderDefaultValueEditor()} +
+
+
} + +
+ +
; + }; + + + } +}); diff --git a/packages/designer/src/components/components/entity-tree-view/composition/entity-tree-view.css b/packages/designer/src/components/components/entity-tree-view/composition/entity-tree-view.css index b67b0b5a81db8ddcc02ebebd4bf7f7d8c0fd3603..482e5ae1ece67595d5d0ceb075980b96f7aa241f 100644 --- a/packages/designer/src/components/components/entity-tree-view/composition/entity-tree-view.css +++ b/packages/designer/src/components/components/entity-tree-view/composition/entity-tree-view.css @@ -28,4 +28,8 @@ .designer-schema-tree .fv-grid .fv-grid-row.occupied .f-icon-preview { color: #2a87ff !important; +} + +.designer-schema-tree .fv-grid .fv-grid-row.from-outside { + color: #878D99; } \ No newline at end of file diff --git a/packages/designer/src/components/components/entity-tree-view/composition/use-entity-tree-data.ts b/packages/designer/src/components/components/entity-tree-view/composition/use-entity-tree-data.ts index b3b9a4294050f174949dfed80a7cb1de2cb17939..e334b2866eb11e3fbfc7c9737fc0d071bbb133af 100644 --- a/packages/designer/src/components/components/entity-tree-view/composition/use-entity-tree-data.ts +++ b/packages/designer/src/components/components/entity-tree-view/composition/use-entity-tree-data.ts @@ -43,7 +43,7 @@ export function UseEntityTreeData(useFormSchema: UseFormSchema, schemaService: U /** * 将实体内的字段组装为树结构 */ - function resolveFieldNodesInEntity(fields: FormSchemaEntityField[], parentNode: any, occupiedFieldsMap: Map) { + function resolveFieldNodesInEntity(fields: FormSchemaEntityField[], parentNode: any, occupiedFieldsMap: Map, entityId?: string) { const treeData: any = []; fields.forEach(field => { @@ -54,7 +54,9 @@ export function UseEntityTreeData(useFormSchema: UseFormSchema, schemaService: U isOccupied: occupiedFieldsMap?.has(field.id), collapse: true, draggable: true, - children: [] + children: [], + nodeType: 'field', + entityId }; treeData.push(fieldTreeData); serializedTreeData.value.push(fieldTreeData); @@ -63,7 +65,7 @@ export function UseEntityTreeData(useFormSchema: UseFormSchema, schemaService: U if (field.type && field.type.fields && field.type.fields.length > 0) { fieldTreeData.collapse = false; fieldTreeData.draggable = false; - fieldTreeData.children = resolveFieldNodesInEntity(field.type.fields, field, occupiedFieldsMap); + fieldTreeData.children = resolveFieldNodesInEntity(field.type.fields, field, occupiedFieldsMap, entityId); } }); @@ -89,7 +91,7 @@ export function UseEntityTreeData(useFormSchema: UseFormSchema, schemaService: U existedEntityCodes.value.push(entity.code); if (entity.type && entity.type.fields && entity.type.fields.length > 0) { - entityTreeData.children = resolveFieldNodesInEntity(entity.type.fields, entity, occupiedFieldsMap); + entityTreeData.children = resolveFieldNodesInEntity(entity.type.fields, entity, occupiedFieldsMap, entity.id); } if (entity.type.entities && entity.type.entities.length > 0) { diff --git a/packages/designer/src/components/components/entity-tree-view/composition/use-modify-field-modal.tsx b/packages/designer/src/components/components/entity-tree-view/composition/use-modify-field-modal.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4796a18ccc674a3b3d219add786a3fed832ddad0 --- /dev/null +++ b/packages/designer/src/components/components/entity-tree-view/composition/use-modify-field-modal.tsx @@ -0,0 +1,141 @@ +import { FModalService, F_MODAL_SERVICE_TOKEN } from '@farris/ui-vue/components'; +import { UseDesignViewModel, UseFormSchema } from "../../../types"; +import { inject, Ref, ref, SetupContext } from 'vue'; +import ModifyFieldComponent from '../components/modify-field.component'; + +export function useOpenModifyField( + useFormSchema: UseFormSchema, + designViewModelUtils: UseDesignViewModel, + refreshEntityTree: any, + treeViewData: Ref, + context: SetupContext) { + + const modalService: FModalService | null = inject(F_MODAL_SERVICE_TOKEN, null); + const modalInstance = ref(); + + const currentTreeNode = ref(); + /** + * 关闭窗口 + */ + function onCloseModal() { + if (modalInstance.value.close) { + modalInstance.value.close(); + } + } + + /** + * 变更名称后同步ViewModel和控件 + */ + function syncViewModelAndControlAfterNameChanged() { + const { id: currentFieldId, name: currentFieldName } = currentTreeNode.value.data; + let hasBindingControl = false; + useFormSchema.getViewModels().forEach(viewModel => { + if (viewModel.fields && viewModel.fields.length) { + const dgViewModel = designViewModelUtils.getDgViewModel(viewModel.id); + const dgViewModelField = dgViewModel?.fields?.find( + (field) => field.id === currentFieldId + ); + if (dgViewModel && dgViewModelField) { + hasBindingControl = true; + let viewModelFieldSchema: any; + if (Object.prototype.hasOwnProperty.call(dgViewModelField, 'fieldSchema')) { + viewModelFieldSchema = dgViewModelField['fieldSchema']; + } + if (viewModelFieldSchema) { + viewModelFieldSchema.name = currentFieldName; + } else { + viewModelFieldSchema = { + name: currentFieldName, + }; + } + dgViewModel.changeField(currentFieldId, viewModelFieldSchema); + + const changeFieldNameControls = useFormSchema.getControlsInCmpWidthBinding(dgViewModel.id, currentFieldId); + if (changeFieldNameControls?.length) { + changeFieldNameControls.forEach(element => { + if (element.type === 'data-grid-column' || element.type === 'tree-grid-column"') { + element.title = currentFieldName; + } else { + element.label = currentFieldName; + } + + }); + } + } + } + }); + return hasBindingControl; + } + /** + * 确定修改字段 + */ + function onSubmit(fieldInfo: { name: string, defaultValue: any, modified: boolean }) { + if (!fieldInfo?.modified) { + onCloseModal(); + return; + } + const originalFieldName = currentTreeNode.value?.data?.name; + // 修改字段schema + if (currentTreeNode.value?.data) { + if (fieldInfo?.name) { + currentTreeNode.value.data.name = fieldInfo.name; + } + if (fieldInfo?.name) { + currentTreeNode.value.data.defaultValue = fieldInfo.defaultValue; + } + } + // 同步控件 + if (originalFieldName !== fieldInfo.name) { + const hasBindingControl = syncViewModelAndControlAfterNameChanged(); + // 刷新实体树以及画布 + if (hasBindingControl) { + context.emit('entityUpdated'); + onCloseModal(); + return; + } + + } + // 刷新实体树 + if (refreshEntityTree) { + refreshEntityTree(); + } + onCloseModal(); + } + function renderModifyFieldComponent(treeNode: any) { + const { entityId } = treeNode; + const existedAllFields = treeViewData.value.filter(node => node.entityId === entityId); + + return () => (<> + ); + } + + + function openModifyFieldModal(event: MouseEvent, treeNode: any) { + event.stopPropagation(); + event.preventDefault(); + if (!modalService) { + return; + } + currentTreeNode.value = treeNode; + const modalEditorRef = modalService.open({ + title: '字段信息', + width: 500, + height: useFormSchema.designerMode === 'PC_RTC' ? 250 : 210, + fitContent: false, + showButtons: false, + render: renderModifyFieldComponent(treeNode), + enableEsc: false, + draggable: true + }); + + modalInstance.value = modalEditorRef?.modalRef?.value; + } + + + return { openModifyFieldModal }; +} diff --git a/packages/designer/src/components/components/entity-tree-view/composition/use-new-field-modal.tsx b/packages/designer/src/components/components/entity-tree-view/composition/use-new-field-modal.tsx index 081ad162de55c471c34c42993331ea3a99ca13d0..2cef5457fbac536555de212a39573465fff990fd 100644 --- a/packages/designer/src/components/components/entity-tree-view/composition/use-new-field-modal.tsx +++ b/packages/designer/src/components/components/entity-tree-view/composition/use-new-field-modal.tsx @@ -42,7 +42,7 @@ export function useOpenNewField( function renderNewFieldComponent(treeNode: any) { const entityCode = treeNode?.data?.code; const isNewEntity = newEntityCodeList.value.includes(entityCode); - const existedAllFields = treeViewData.value.filter(node => node.parent === treeNode?.data?.id && node.data).map(node => node.data); + const existedAllFields = treeViewData.value.filter(node => node.entityId === treeNode?.data?.id && node.data).map(node => node.data); return () => (<>) { + if (defaultValueRef.value?.currentPropertyType === 'Expression' && !extendField.value.defaultValue?.value) { + notifyService.warning('请填写默认值表达式'); + return false; + } + return true; + } + function checkFieldValidation(helpMetadataName: Ref, relatedHelpFieldIds: Ref, helpFieldId: Ref, defaultValueRef: Ref) { if (!isFieldLabelValid.value) { return false; } @@ -153,24 +159,24 @@ export function useNewFieldVerification(props: CreateNewFieldProps, extendField: notifyService.warning('字段精度不能为空'); return false; } - // if (!checkDefaultValueValid()) { - // return false; - // } - - // if (extendField.value.type === ElementDataType.String && extendField.value.objectType === ElementObjectType.Association) { - // if (!helpMetadata) { - // notifyService.warning('请选择帮助!'); - // return false; - // } - // if (relatedFieldsTreeData.length === 0) { - // notifyService.warning('请选择关联字段!'); - // return false; - // } - // if (!helpField) { - // notifyService.warning('请选择帮助绑定字段!'); - // return false; - // } - // } + if (!checkDefaultValueValid(defaultValueRef)) { + return false; + } + + if (extendField.value.type === ElementDataType.String && extendField.value.objectType === ElementObjectType.Association) { + if (!helpMetadataName.value) { + notifyService.warning('请选择帮助!'); + return false; + } + if (!relatedHelpFieldIds.value?.length) { + notifyService.warning('请选择关联字段!'); + return false; + } + if (!helpFieldId.value) { + notifyService.warning('请选择帮助绑定字段!'); + return false; + } + } if (extendField.value.objectType === ElementObjectType.Enum && (!extendField.value.enumValues || !extendField.value.enumValues.length)) { diff --git a/packages/designer/src/components/components/entity-tree-view/composition/use-update-entity-schema.tsx b/packages/designer/src/components/components/entity-tree-view/composition/use-update-entity-schema.tsx index 1cf19e640c130230a2f6afb98d6c4e8b9364757f..9e23d358e3b51e1029be18de798349055571a27e 100644 --- a/packages/designer/src/components/components/entity-tree-view/composition/use-update-entity-schema.tsx +++ b/packages/designer/src/components/components/entity-tree-view/composition/use-update-entity-schema.tsx @@ -120,7 +120,7 @@ export function useUpdateEntitySchema( if (modalInstance?.value?.close) { modalInstance.value.close(); } - // 触发更新实体树 + // 触发更新实体树以及画布 context.emit('entityUpdated'); } /** 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 8b1d00de0f57271c79ac92cec904b6663b41831b..55f2de974fe2a25512c01bdda367d7d9a63776e3 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 @@ -12,13 +12,14 @@ import { UseFormSchema } from "../../../../../types"; import './method-list.scss'; import { useEventParameterData } from "../../../../../composition/use-event-parameter-data"; import { useParameterEditorData } from "../../../../../composition/use-parameter-editor-data"; +import { DesignerMode, UseDesignerContext } from "../../../../../types/designer-context"; export default defineComponent({ name: 'FMethodList', props: methodListProps, emits: [], setup(props: MethodListProps, context) { - + const designerContext = inject('designerContext') as UseDesignerContext; const useFormSchemaComposition = inject('useFormSchema')!; const useFormStateMachineComposition: any = inject('useFormStateMachine', null); /** 树表格实例 */ @@ -233,6 +234,7 @@ export default defineComponent({
(modelType: string) => { @@ -45,9 +47,10 @@ export default defineComponent({
  • onChangeModelTab('method')}> 方法
  • -
  • onChangeModelTab('variable')}> - 变量 -
  • + {designerContext.designerMode !== DesignerMode.PC_RTC && +
  • onChangeModelTab('variable')}> + 变量 +
  • }
    diff --git a/packages/designer/src/components/composition/command/supported-controllers/pc-supported-controller.json b/packages/designer/src/components/composition/command/supported-controllers/pc-supported-controller.json index 2da5bca0e9d7905f62622ad9397b82a11ccfa682..7e03a7f3d6de770bb8d0432e5df1ef8bd81c29ef 100644 --- a/packages/designer/src/components/composition/command/supported-controllers/pc-supported-controller.json +++ b/packages/designer/src/components/composition/command/supported-controllers/pc-supported-controller.json @@ -163,6 +163,18 @@ { "id": "45047397-5422-d878-fc63-67195172d5b4", "code": "Filter" + }, + { + "id": "9aaeafe1-d782-369d-2b42-8c1a617858a0", + "code": "AddWithDimension" + }, + { + "id": "835bc9e6-8d95-86ca-3a34-ac0191be1fa0", + "code": "EditWithDimension" + }, + { + "id": "8af6d57f-51eb-b004-2433-88058ea95674", + "code": "ViewWithDimension" } ], "d7ce1ba6-49c7-4a27-805f-f78f42e72725": [ diff --git a/packages/designer/src/components/composition/designer-context/use-pc-rtc-designer-context.ts b/packages/designer/src/components/composition/designer-context/use-pc-rtc-designer-context.ts index c059227de34545dea084f43135c81eaa3e6ab843..80655d4e5e8a32ce96b6d07fd58acca09b272563 100644 --- a/packages/designer/src/components/composition/designer-context/use-pc-rtc-designer-context.ts +++ b/packages/designer/src/components/composition/designer-context/use-pc-rtc-designer-context.ts @@ -1,5 +1,5 @@ import { DesignerMode, UseDesignerContext } from "../../types/designer-context"; -import ToolboxItems from '../../types/toolbox/pc-toolbox.json'; +import ToolboxItems from '../../types/toolbox/pc-rtc-toolbox.json'; import { usePCControlCreator } from "../control-creator/use-pc-control-creator.service"; import SupportedControllers from '../../composition/command/supported-controllers/pc-supported-controller.json'; import { FormComponent, UseFormSchema } from "../../../components/types"; @@ -163,7 +163,7 @@ export function usePCRtcDesignerContext(): UseDesignerContext { * 校验是否支持删除控件 */ function checkCanDeleteControl(propertyData: any, needNotify = true) { - if (!propertyData[identifyForNewControl]) { + if (propertyData && !propertyData[identifyForNewControl]) { if (needNotify) { notifyService.warning({ position: 'top-center', message: '不允许删除基础表单的控件' }); } diff --git a/packages/designer/src/components/composition/events-editor-utils.ts b/packages/designer/src/components/composition/events-editor-utils.ts index c9a95b50adf31a881900eb1c10f1ff27fba62171..6e61bd41dd9b9c87eaac768f6a45c1274d9bbe62 100644 --- a/packages/designer/src/components/composition/events-editor-utils.ts +++ b/packages/designer/src/components/composition/events-editor-utils.ts @@ -168,7 +168,7 @@ export function useEventsEditorUtils(commandService: UseFormCommandService, form handlerName: boundEventItem.command.handlerName, params: cloneDeep(boundEventItem.command.property), isNewGenerated: boundEventItem.command.isNewGenerated || false, - // isRtcCommand: boundEventItem.command['isRtcCommand'], + isRtcCommand: boundEventItem.command['isRtcCommand'], isInvalid: boundEventItem.command.isInvalid || false, }, controller: { diff --git a/packages/designer/src/components/composition/form-metadata-rtc.service.ts b/packages/designer/src/components/composition/form-metadata-rtc.service.tsx similarity index 42% rename from packages/designer/src/components/composition/form-metadata-rtc.service.ts rename to packages/designer/src/components/composition/form-metadata-rtc.service.tsx index 107b3d62439895ded6b0399039831f6c18b0edcd..1eb80f38f45b7e84df0ffc4dfa2e16e374d3114a 100644 --- a/packages/designer/src/components/composition/form-metadata-rtc.service.ts +++ b/packages/designer/src/components/composition/form-metadata-rtc.service.tsx @@ -6,6 +6,8 @@ import { useFormMetadata } from './form-metadata.service'; import { cloneDeep } from 'lodash-es'; import { RuntimeSchemaDiffService } from './runtime/runtime-schema-diff.service'; import { RuntimeComponentDiffService } from './runtime/runtime-component-diff.service'; +import { FModalService, F_MODAL_SERVICE_TOKEN, MenuLookupContainer, useMenuTreeGridCoordinator } from '@farris/ui-vue/components'; +import { inject, ref } from 'vue'; export function useRtcFormMetadata( props: DesignerProps, @@ -18,6 +20,14 @@ export function useRtcFormMetadata( /** 运行时定制,元数据查询、保存url */ const rtcMetadataUrl = '/api/runtime/bcc/v1.0/template'; + const modalService: FModalService | null = inject(F_MODAL_SERVICE_TOKEN, null); + /** 发布菜单的窗口实例 */ + const menuModalInstance = ref(); + /** 选中的菜单数据 */ + const menuSelectedData = ref(); + /** 菜单缓存 */ + const menuClearCache = ref(); + /** 获取表单元数据 */ function queryMetadata(): Promise { const { getHrefParam } = useLocation(); @@ -35,8 +45,8 @@ export function useRtcFormMetadata( const formMetadataBasicInfo = { id: formContent.Id, - code: formContent.Code, - name: formContent.Name, + code: formContent.code, + name: formContent.name, resourceMetadataId: response.data.resourceMetadataId, dimension1, dimension2, @@ -99,6 +109,140 @@ export function useRtcFormMetadata( return useFormMetadata(props, useFormSchemaComposition).queryFormTemplateRule(formModule); } - return { queryMetadata, saveFormMetadata, queryFormTemplateRule }; + /** + * 运行表单 + */ + function runForm(loadingService: any, messageBoxService: any) { + const currentFormSchema = useFormSchemaComposition.getFormSchema(); + const formBasicInfo = useFormSchemaComposition.getFormMetadataBasicInfo(); + const { dimension1, dimension2 } = formBasicInfo; + const stateMachineMap = {}; + if (currentFormSchema.module.stateMachines && currentFormSchema.module.stateMachines[0]) { + stateMachineMap[currentFormSchema.module.stateMachines[0].uri] = ""; + } + const formId = previousMetadataContent.Id; + const body = { + formId, + voId: currentFormSchema.module.entity[0].id, + eapiId: currentFormSchema.module.entity[0].eapiId, + stateMachineIds: stateMachineMap, + webCmdIds: currentFormSchema.module.webcmds.map(cmd => cmd.id) + }; + const loadingInstance = loadingService?.show({ message: '解析中,请稍候...' }); + axios.post(`${rtcMetadataUrl}/preview`, body).then((result) => { + if (result?.data?.success && result?.data?.extraMessages) { + const previewUrl = `${window.location.origin}/platform/common/web/renderer/index.html#/?dim1=${dimension1}&dim2=${dimension2}&metadataId=${formId}`; + const windowProxy = window.open(previewUrl); + if (!windowProxy) { + messageBoxService.error('预览失败,请调整浏览器安全设置后重试!'); + } + } else { + messageBoxService.error('表单编译失败!'); + } + loadingInstance.value.close(); + }, (error) => { + loadingInstance.value.close(); + messageBoxService.error(error || '表单解析失败'); + + }); + } + function onMenuCancel() { + if (menuModalInstance.value.close) { + menuModalInstance.value.close(); + } + } + /** + * 菜单加载服务 + */ + function getFetchNodeApiUrl(expandedNode?: any): string { + const enableLayeredLoading = false; // 待树列表滚动条问题修复后再启用分层加载 + if (enableLayeredLoading) { + const ROOT_NODE_ID = '0'; + const currentNodeId = expandedNode?.id || ROOT_NODE_ID; + return `/api/runtime/sys/v1.0/functions/layerFuncs/${currentNodeId}`; + } else { + if (expandedNode) { + return ''; + } + return '/api/runtime/sys/v1.0/functions/allfuncs'; + } + } + function renderPublichMenuComponent() { + const modalContainerRef = ref(); + const useMenuTreeGrid = useMenuTreeGridCoordinator({ targetType: 'menu', fetchNodeApi: getFetchNodeApiUrl, modelValue: '' }, modalContainerRef); + menuSelectedData.value = useMenuTreeGrid.selectedData; + menuClearCache.value = useMenuTreeGrid.clearCache; + + return () => (); + } + /** + * 选择菜单后事件 + */ + function onMenuConfirm(messageBoxService: any, notifyService: any) { + if (!menuSelectedData.value?.value) { + notifyService?.warning({ message: '请选择数据!', position: 'top-center' }); + return; + } + + const formBasicInfo = useFormSchemaComposition.getFormMetadataBasicInfo(); + const menuInfo = { + dim1: formBasicInfo.dimension1, + dim2: formBasicInfo.dimension2, + isRtc: '1', + metadataId: formBasicInfo.id, + menuId: menuSelectedData.value.value.id + }; + + axios.post(`${rtcMetadataUrl}/publishRtcMenu`, menuInfo).then(() => { + notifyService?.success('发布成功!'); + }, (error) => { + messageBoxService.error(error?.response?.data?.Message || '发布失败!'); + }); + + onMenuCancel(); + } + + /** + * 复制部署路径 + */ + function publishMenu(messageBoxService: any, notifyService: any) { + if (!modalService) { + return; + } + const modalEditorRef = modalService.open({ + title: '发布菜单', + width: 800, + height: 550, + fitContent: false, + showButtons: true, + render: renderPublichMenuComponent(), + enableEsc: false, + draggable: true, + closedCallback: () => { + if (menuClearCache.value) { + menuClearCache.value(); + } + }, + buttons: [ + { + class: 'btn btn-secondary', + text: '取消', + handle: () => { + onMenuCancel(); + }, + }, + { + class: 'btn btn-primary', + text: '确定', + handle: () => { + onMenuConfirm(messageBoxService, notifyService); + }, + } + ], + }); + + menuModalInstance.value = modalEditorRef?.modalRef?.value; + } + return { queryMetadata, saveFormMetadata, queryFormTemplateRule, runForm, publishMenu }; } diff --git a/packages/designer/src/components/composition/form-metadata.service.ts b/packages/designer/src/components/composition/form-metadata.service.ts index cab4a3f12beaa9a364a40c2bcb8d4d0aab19b2ec..ce8e1b2a6aca2d1b12509380675fc4f1712b3a17 100644 --- a/packages/designer/src/components/composition/form-metadata.service.ts +++ b/packages/designer/src/components/composition/form-metadata.service.ts @@ -5,6 +5,7 @@ import { FormMetadaDataDom, MetadataDto, MetadataPathToken, UseFormSchema, UseFo import { inject } from 'vue'; import { MetadataService } from './metadata.service'; import { FNotifyService } from '@farris/ui-vue/components'; +import { DesignerMode, UseDesignerContext } from '../types/designer-context'; export function useFormMetadata(props: DesignerProps, useFormSchemaComposition: UseFormSchema): UseFormMetadata { @@ -188,6 +189,63 @@ export function useFormMetadata(props: DesignerProps, useFormSchemaComposition: }; return axios.post(api, sendData, { headers: requestHeader }); } - return { queryMetadata, saveFormMetadata, queryFormTemplateRule, publishFormMetadata, deployFrontFile }; + + /** + * 运行表单 + */ + function runForm(loadingService, messageBoxService, designerContext: UseDesignerContext, metadataPath: string) { + const loadingInstance = loadingService?.show({ message: '解析中,请稍候...' }); + const metadataId = useFormSchemaComposition.getFormMetadataBasicInfo()?.id; + const relativePath = useFormSchemaComposition.getFormMetadataBasicInfo()?.relativePath; + const formCode = useFormSchemaComposition.getFormMetadataBasicInfo()?.code; + + publishFormMetadata().then((publishInfo) => { + if (publishInfo.result) { + loadingInstance.value.close(); + let previewUrl; + if (designerContext.designerMode === DesignerMode.Mobile) { + const component = useFormSchemaComposition.getComponents()[0]; + const uri = component?.route?.uri; + previewUrl = `${window.location.origin}/platform/common/web/mobile-renderer/index.html#/${formCode}/${uri}?metadataPath=${metadataPath}&projectPath=${relativePath}&metadataId=${metadataId}`; + } else { + previewUrl = `${window.location.origin}/platform/common/web/renderer/index.html#/preview?metadataPath=${metadataPath}&projectPath=${relativePath}&metadataId=${metadataId}`; + } + const windowProxy = window.open(previewUrl); + if (!windowProxy) { + messageBoxService.error('预览失败,请调整浏览器安全设置后重试!'); + } + } else { + loadingInstance.value.close(); + messageBoxService.error(publishInfo.error || '表单解析失败'); + } + }); + + } + + /** + * 复制部署路径 + */ + async function publishMenu(messageBoxService: any, notifyService: any) { + const metadataId = useFormSchemaComposition.getFormMetadataBasicInfo()?.id; + const publishUrl = `/platform/common/web/renderer/index.html#/?formMetadataId=${metadataId}`; + + const textarea = document.createElement("textarea"); + textarea.value = publishUrl; + document.body.appendChild(textarea); + textarea.select(); + try { + const success = document.execCommand("copy"); + if (success) { + notifyService.success({ message: '表单部署路径已复制到剪贴板,请前往框架【菜单】页面发布菜单。' }); + } else { + messageBoxService.warning(`复制失败,请手动复制以下路径: ${publishUrl}`); + } + } catch (err) { + messageBoxService.warning(`复制失败,请手动复制以下路径: ${publishUrl}`); + } + document.body.removeChild(textarea); + } + + return { queryMetadata, saveFormMetadata, queryFormTemplateRule, publishFormMetadata, deployFrontFile, runForm, publishMenu }; } diff --git a/packages/designer/src/components/composition/runtime/runtime-schema-diff.service.ts b/packages/designer/src/components/composition/runtime/runtime-schema-diff.service.ts index 3697479d54718cc66f4eea0e5ae65e0cb095a082..53ac616d7e96b935bafb6e1809b969a874abb160 100644 --- a/packages/designer/src/components/composition/runtime/runtime-schema-diff.service.ts +++ b/packages/designer/src/components/composition/runtime/runtime-schema-diff.service.ts @@ -1,4 +1,3 @@ -import { RuntimeSchemaService } from './runtime-schema.service'; import { FormMetaDataModule, FormSchemaEntity, FormSchemaEntityField, UseSchemaService } from '../../types'; /** @@ -217,7 +216,7 @@ export class RuntimeSchemaDiffService { if (this.addedTreeData.length === 0) { return false; } - const tableIndex = this.addedTreeData.findIndex(table => tableId === table.data.id) + const tableIndex = this.addedTreeData.findIndex(table => tableId === table.data.id); if (tableIndex < 0) { return false; } diff --git a/packages/designer/src/components/composition/schema.service.ts b/packages/designer/src/components/composition/schema.service.ts index de0dc8a34488ada20160204a4e7dccaa24faffad..d1d85d990c7d351e10a17509e8bbedf5387f629d 100644 --- a/packages/designer/src/components/composition/schema.service.ts +++ b/packages/designer/src/components/composition/schema.service.ts @@ -551,7 +551,8 @@ export function useSchemaService( draggable: children.length === 0, // 关联带出字段:记录父节点,用于添加schema节点 rtRelateParentSchemaField: rtRelateParentSchemaField, - entityId + entityId, + nodeType: 'field' }; treeData.push(node); @@ -591,8 +592,9 @@ export function useSchemaService( children: childNodes, draggable: childNodes.length === 0, rtFieldSourceType: rtElement.type, - rtFieldTag: rtElement.tag, - entityId: schemaEntity.id + // rtFieldTag: rtElement.tag, + entityId: schemaEntity.id, + nodeType: 'field' }; rtcSerializedAddedTreeNodes.value.push(newFieldTreeNode); 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 cc40bb891b210bb84a039506725409c8401e0d15..f19f19e3b7db7b046cce781262211757abfcd5c1 100644 --- a/packages/designer/src/components/composition/use-parameter-editor-data.ts +++ b/packages/designer/src/components/composition/use-parameter-editor-data.ts @@ -193,8 +193,10 @@ export function useParameterEditorData(useFormSchemaComposition: UseFormSchema) return treeData; } // 表单组件组装数据 - function assembleOutline() { - const formSchema = useFormSchemaComposition.getFormSchema(); + function assembleOutline(formSchema?: any) { + if (!formSchema) { + formSchema = useFormSchemaComposition.getFormSchema(); + } const allComponents = formSchema.module.components; // 表单组件 const rootComponentId = 'root-component'; @@ -224,8 +226,10 @@ export function useParameterEditorData(useFormSchemaComposition: UseFormSchema) return data; } - function assembleSchemaFieldsByComponent() { - const formSchema = useFormSchemaComposition.getFormSchema(); + function assembleSchemaFieldsByComponent(formSchema?: any) { + if (!formSchema) { + formSchema = useFormSchemaComposition.getFormSchema(); + } const entity = formSchema.module.entity[0]; const data: Omit[] = []; entity.entities.forEach(entity => { @@ -242,8 +246,10 @@ export function useParameterEditorData(useFormSchemaComposition: UseFormSchema) return data; } - function assembleStateVariables() { - const formSchema = useFormSchemaComposition.getFormSchema(); + function assembleStateVariables(formSchema?: any) { + if (!formSchema) { + formSchema = useFormSchemaComposition.getFormSchema(); + } const { viewmodels } = formSchema.module; if (!viewmodels || !viewmodels.length) { return; diff --git a/packages/designer/src/components/designer.component.tsx b/packages/designer/src/components/designer.component.tsx index 81d4d764861f32e60cfff291a0d0cc4a00332e4c..8612a133b77d451b26ea35895fa6c6168d661f9a 100644 --- a/packages/designer/src/components/designer.component.tsx +++ b/packages/designer/src/components/designer.component.tsx @@ -117,39 +117,7 @@ export default defineComponent({ } activeShowDesignerType.value = itemType; } - /** - * 运行表单 - */ - function runForm() { - const loadingInstance = loadingService?.show({ message: '解析中,请稍候...' }); - const metadataId = useFormSchemaComposition.getFormMetadataBasicInfo()?.id; - const relativePath = useFormSchemaComposition.getFormMetadataBasicInfo()?.relativePath; - const formCode = useFormSchemaComposition.getFormMetadataBasicInfo()?.code; - if (!useFormMetadataComposition.publishFormMetadata) { - return; - } - useFormMetadataComposition.publishFormMetadata().then((publishInfo) => { - if (publishInfo.result) { - loadingInstance.value.close(); - let previewUrl; - if (designerContext.designerMode === DesignerMode.Mobile) { - const component = useFormSchemaComposition.getComponents()[0]; - const uri = component?.route?.uri; - previewUrl = `${window.location.origin}/platform/common/web/mobile-renderer/index.html#/${formCode}/${uri}?metadataPath=${metadataPath}&projectPath=${relativePath}&metadataId=${metadataId}`; - } else { - previewUrl = `${window.location.origin}/platform/common/web/renderer/index.html#/preview?metadataPath=${metadataPath}&projectPath=${relativePath}&metadataId=${metadataId}`; - } - const windowProxy = window.open(previewUrl); - if (!windowProxy) { - messageBoxService.error('预览失败,请调整浏览器安全设置后重试!'); - } - } else { - loadingInstance.value.close(); - messageBoxService.error(publishInfo.error || '表单解析失败'); - } - }); - } /** * 保存表单 */ @@ -160,8 +128,8 @@ export default defineComponent({ useFormMetadataComposition.saveFormMetadata().then(() => { !needRunForm && notifyService.success({ message: '表单保存成功' }); loadingInstance.value.close(); - if (needRunForm) { - runForm(); + if (needRunForm && useFormMetadataComposition.runForm) { + useFormMetadataComposition.runForm(loadingService, messageBoxService, designerContext, metadataPath); } }, (error) => { messageBoxService.error(error?.response?.data?.Message || '表单保存失败'); @@ -169,35 +137,13 @@ export default defineComponent({ }); } - /** 复制部署路径 */ - async function publishMenu() { - const metadataId = useFormSchemaComposition.getFormMetadataBasicInfo()?.id; - const publishUrl = `/platform/common/web/renderer/index.html#/?metadataId=${metadataId}`; - // await navigator.clipboard.writeText(publishUrl); - - const textarea = document.createElement("textarea"); - textarea.value = publishUrl; - document.body.appendChild(textarea); - textarea.select(); - try { - const success = document.execCommand("copy"); - if (success) { - notifyService.success({ message: '表单部署路径已复制到剪贴板,请前往框架【菜单】页面发布菜单。' }); - } else { - messageBoxService.warning(`复制失败,请手动复制以下路径: ${publishUrl}`); - } - } catch (err) { - messageBoxService.warning(`复制失败,请手动复制以下路径: ${publishUrl}`); - } - document.body.removeChild(textarea); - } /** * 工具栏配置 */ const designerToolbarItems = [ { id: 'save', text: '保存', onClick: () => saveFormMetadata(false), class: 'btn-primary' }, { id: 'run', text: '运行', onClick: () => saveFormMetadata(true) }, - { id: 'publish', text: '复制部署路径', onClick: () => publishMenu() } + { id: 'publish', text: designerContext.designerMode === DesignerMode.PC_RTC ? '发布菜单' : '复制部署路径', onClick: () => useFormMetadataComposition.publishMenu(messageBoxService, notifyService) } ]; /** * 切换设计器视图与代码视图 diff --git a/packages/designer/src/components/types/metadata.ts b/packages/designer/src/components/types/metadata.ts index 9bdb4b9737c0930d701ba07becc5560c1e4a3ab2..3156b64a60cae3cdac08bcd37d7c0d21ba2053b9 100644 --- a/packages/designer/src/components/types/metadata.ts +++ b/packages/designer/src/components/types/metadata.ts @@ -2,7 +2,7 @@ import { Ref } from "vue"; import { ExternalComponentSchema } from "../components/form-designer/components/external-component-panpel/composition/types"; import { FormComponent, FormExpression, FormStateMachine, FormWebCmd } from "./basic"; import { DesignViewModel } from "./design-viewmodel"; -import { DesignerMode } from "./designer-context"; +import { DesignerMode, UseDesignerContext } from "./designer-context"; import { FormSchema, FormSchemaEntity, FormSchemaEntityField } from "./entity-schema"; import { FormVariable, FormViewModel, FormViewModelField } from "./view-model"; @@ -140,6 +140,8 @@ export interface MetadataDto { properties?: { framework: string, [propsName: string]: any } nameLanguage?: any; + dimension1?: string; + dimension2?: string; } export interface UseFormMetadata { /** 查询表单元数据 */ @@ -151,7 +153,12 @@ export interface UseFormMetadata { /** 发布表单 */ publishFormMetadata?: () => Promise<{ result: boolean, error?: string }>; /** 部署表单 */ - deployFrontFile?: (metadataId: string, path: string) => Promise + deployFrontFile?: (metadataId: string, path: string) => Promise; + /** 运行表单 */ + runForm: (loadingService: any, messageBoxService: any, designerContext: UseDesignerContext, metdataPath: string) => void; + /** 发布菜单 */ + publishMenu: (messageBoxService: any, notifyService: any) => void; + } export interface UseFormSchema { /** 设计器当前运行环境 */ diff --git a/packages/designer/src/components/types/toolbox/pc-rtc-toolbox.json b/packages/designer/src/components/types/toolbox/pc-rtc-toolbox.json new file mode 100644 index 0000000000000000000000000000000000000000..2a5084fb69529d983f33084d7e45b5d1f107faf3 --- /dev/null +++ b/packages/designer/src/components/types/toolbox/pc-rtc-toolbox.json @@ -0,0 +1,186 @@ +[ + { + "type": "input", + "name": "输入类控件", + "items": [ + { + "id": "TextBox", + "type": "input-group", + "name": "文本", + "category": "input" + }, + { + "id": "MultiTextBox", + "type": "textarea", + "name": "多行文本", + "category": "input" + }, + { + "id": "DateBox", + "type": "date-picker", + "name": "日期", + "category": "input" + }, + { + "id": "EnumField", + "type": "combo-list", + "name": "下拉列表", + "category": "input" + }, + { + "id": "NumericBox", + "type": "number-spinner", + "name": "数值", + "category": "input" + }, + { + "id": "CheckBox", + "type": "check-box", + "name": "复选框", + "category": "input" + }, + { + "id": "CheckBoxGroup", + "type": "check-group", + "name": "复选框组", + "category": "input" + }, + { + "id": "RadioGroup", + "type": "radio-group", + "name": "单选组", + "category": "input" + }, + { + "id": "SwitchField", + "type": "switch", + "name": "开关", + "category": "input" + }, + { + "id": "LookupEdit", + "type": "lookup", + "name": "帮助", + "category": "input" + }, + { + "id": "TimePicker", + "type": "time-picker", + "name": "时间选择", + "category": "input" + } + ] + }, + { + "type": "dataCollection", + "name": "数据集合类控件", + "items": [ + { + "id": "ResponseForm", + "type": "response-form", + "name": "卡片面板", + "category": "dataCollection" + }, + { + "id": "DataGrid", + "type": "data-grid", + "name": "表格", + "category": "dataCollection" + } + ] + }, + { + "type": "container", + "name": "容器类控件", + "items": [ + { + "id": "Tab", + "type": "tabs", + "name": "标签页区域", + "category": "container" + }, + { + "id": "HtmlTemplate", + "type": "html-template", + "name": "模版容器", + "category": "container" + }, + { + "id": "Section", + "type": "section", + "name": "分组面板", + "category": "container" + }, + { + "id": "Fieldset", + "type": "fieldset", + "name": "分组", + "category": "container" + }, + { + "id": "ContentContainer", + "type": "content-container", + "name": "容器", + "category": "container" + } + ] + }, + { + "type": "business", + "name": "业务类控件", + "items": [ + { + "id": "QuerySolution", + "type": "query-solution", + "name": "筛选方案", + "category": "container" + } + ] + }, + { + "type": "response-layout", + "name": "布局容器", + "items": [ + { + "id": "ResponseLayout2", + "type": "response-layout", + "name": "1列", + "category": "container", + "feature": { + "splitter": "12" + }, + "icon": "response-layout-1" + }, + { + "id": "ResponseLayout2", + "type": "response-layout", + "name": "2列", + "category": "container", + "feature": { + "splitter": "6:6" + }, + "icon": "response-layout-2" + }, + { + "id": "ResponseLayout3", + "type": "response-layout", + "name": "3列", + "category": "container", + "feature": { + "splitter": "4:4:4" + }, + "icon": "response-layout-3" + }, + { + "id": "ResponseLayout4", + "type": "response-layout", + "name": "4列", + "category": "container", + "feature": { + "splitter": "3:3:3:3" + }, + "icon": "response-layout-4" + } + ] + } +] \ No newline at end of file diff --git a/packages/ui-vue/components/binding-selector/src/binding-selector.component.tsx b/packages/ui-vue/components/binding-selector/src/binding-selector.component.tsx index cdeabe388a8ee3f515de358ceb36135cbfc98f42..898fd1bd04c28baf4235e66e8d623c82821d4f6b 100644 --- a/packages/ui-vue/components/binding-selector/src/binding-selector.component.tsx +++ b/packages/ui-vue/components/binding-selector/src/binding-selector.component.tsx @@ -81,9 +81,10 @@ export default defineComponent({ return false; } updateViewModel(bindingData.value[0], bindingType.value); + clearExpresssionConfig(bindingData.value[0]); const newBindingValue = updateComponentSchema(bindingData.value[0], bindingType.value); setDisplayText(newBindingValue); - clearExpresssionConfig(bindingData.value[0]); + // 触发变更 if (props.onFieldSelected && typeof props.onFieldSelected == 'function') { props.onFieldSelected(newBindingValue, undefined,bindingData.value[0]); diff --git a/packages/ui-vue/components/binding-selector/src/components/binding-selector-container.component.tsx b/packages/ui-vue/components/binding-selector/src/components/binding-selector-container.component.tsx index ef974ddd82030e82ce35115428de3c4e5ddd6262..2cda6ff0a7c2e455bce762f8b9ee3c392400f09d 100644 --- a/packages/ui-vue/components/binding-selector/src/components/binding-selector-container.component.tsx +++ b/packages/ui-vue/components/binding-selector/src/components/binding-selector-container.component.tsx @@ -10,7 +10,7 @@ import { FNotifyService } from "@farris/ui-vue/components/notify"; export default defineComponent({ name: 'FBindingSelectorContainer', props: bindingSelectorProps, - emits: ['selected', 'bindingTypeChange', 'cancel', 'submit'], + emits: ['selected', 'bindingTypeChange', 'cancel', 'submit', 'skip'], setup(props: BindingSelectorProps, context) { const dataSource = ref(props.data); @@ -142,6 +142,9 @@ export default defineComponent({ } context.emit('submit', { selectedData: bindingData.value[0], bindingType: bindingType.value }); } + function onSkipBinding() { + context.emit('skip'); + } return () => { return (
    @@ -151,6 +154,7 @@ export default defineComponent({ props.showCustomFooter ? : '' } 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 54ed88eadc1843e0e51a5d45faeeb472c7844c5f..dd059b51e0681b1754ef56a1667b71dc9efb7ee2 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 @@ -126,25 +126,29 @@ export function useFieldSelection(props: BindingSelectorProps) { return; } const originalBinding = props.editorParams.componentSchema.binding; - if (originalBinding && originalBinding.field === bindingData.id) { + if (!originalBinding || originalBinding.field === bindingData.id) { return; } - if (formSchemaUtils.expressions && formSchemaUtils.expressions.length) { - const { propertyData } = props.editorParams; - const expFieldIndex = formSchemaUtils.expressions.findIndex(e => e.target === originalBinding.field); + if (formSchemaUtils.getExpressions().length) { + const { componentSchema } = props.editorParams; + const expFieldIndex = formSchemaUtils.getExpressions().findIndex(e => e.target === originalBinding.field); if (expFieldIndex > -1) { - formSchemaUtils.expressions.splice(expFieldIndex, 1); + formSchemaUtils.getExpressions().splice(expFieldIndex, 1); notifyService.warning('切换绑定后,请重新配置表达式'); // 切换绑定后涉及到了表达式的移除,需要触发属性面板的更新 - Object.keys(propertyData).forEach(propertyID => { - if (propertyData[propertyID] && propertyData[propertyID].type === 'Expression') { - propertyData[propertyID].expressionId = ''; + Object.keys(componentSchema).forEach(propertyID => { + if (componentSchema[propertyID] && componentSchema[propertyID].type === 'Expression') { + componentSchema[propertyID].expressionId = ''; + } + + if (componentSchema.editor) { + Object.keys(componentSchema.editor).forEach(editorPropertyID => { + if (componentSchema.editor[editorPropertyID] && componentSchema.editor[editorPropertyID].type === 'Expression') { + componentSchema.editor[editorPropertyID].expressionId = ''; + } + + }); } - // if (propertyData[propertyID] && propertyData[propertyID].type === 'FormRule') { - // // 还原为默认值 - // const schema = this.schemaService.getFieldByID(propertyData.binding.field); - // propertyData[propertyID] = this.domService.getDefaultValueByFiledAndType(propertyID, schema, propertyData, this.formBasicService.envType); - // } }); } diff --git a/packages/ui-vue/components/components.ts b/packages/ui-vue/components/components.ts index 2464a1cffd50733a6105a15036f24a7375607e35..bc1ac464f2838d686544ec6fece6e3ed575884dd 100644 --- a/packages/ui-vue/components/components.ts +++ b/packages/ui-vue/components/components.ts @@ -110,3 +110,6 @@ export { default as FVerifyDetail, FVerifyDetailService } from './verify-detail' export type { VerifyDetailProps } from './verify-detail'; export { default as FItemCollectionEditor } from './radio-group/src/designer/item-collection-editor.component'; export { default as FSchemaSelectorEditor } from './schema-selector/src/schema-selector-editor.component'; +export { default as FPropertyEditor } from './property-editor'; +export { default as MenuLookupContainer } from './menu-lookup/src/components/modal-container.component'; +export { useMenuTreeGridCoordinator } from './menu-lookup/src/composition/use-tree-grid-coordinator'; diff --git a/packages/ui-vue/components/data-grid/src/designer/column-header.design.component.tsx b/packages/ui-vue/components/data-grid/src/designer/column-header.design.component.tsx index 4f8845325fc502f0bcdefc3f53fb94b2c311ae47..a288ac5b5fb1857ffdfc8b531283ae7a7fb27a12 100644 --- a/packages/ui-vue/components/data-grid/src/designer/column-header.design.component.tsx +++ b/packages/ui-vue/components/data-grid/src/designer/column-header.design.component.tsx @@ -93,7 +93,6 @@ export default function (
    - {headerCell.column?.editor?.required && *} column.data?.id === removedItem.id); + return designerContext.checkCanDeleteControl(columnNode, needNotify); } return true; } @@ -98,17 +99,19 @@ export default defineComponent({ } function convertTreeNodes2PlainObject(nodes: any[], r: any[] = []): any[] { if (nodes) { - const fieldColumnsIds = fieldColumns.map(column => column.binding.field); + // const fieldColumnsIds = fieldColumns.map(column => column.binding.field); nodes.forEach(n => { r.push(n); if (n.children) { convertTreeNodes2PlainObject(n.children, r); } // 附加定制标识,限制字段的删除 - if (designerContext.appendIdentifyForNewControl && !fieldColumnsIds.includes(n.data.id)) { - designerContext.appendIdentifyForNewControl(n); + if (designerContext.appendIdentifyForNewControl) { + const gridColumn = fieldColumns.find(column => column.binding?.field === n.data.id); + if (!gridColumn || gridColumn[designerContext.identifyForNewControl]) { + designerContext.appendIdentifyForNewControl(n); + } } - }); } return r; 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 6822147a078a04770ad7b6e270bc7ae2cb7ddba3..82227750ad769c49481fadff6f0262a2f9033e07 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 @@ -30,7 +30,7 @@ export class DataGriColumnProperty extends BaseControlProperty { this.propertyConfig.categories['behavior'] = this.getBehaviorConfig(propertyData, 'gridFieldEditor'); // 编辑器 this.getFieldEditorProperties(propertyData, gridData); - this.propertyConfig.categories['template'] = this.getTemplateProperties(propertyData); + // this.propertyConfig.categories['template'] = this.getTemplateProperties(propertyData); return this.propertyConfig; } diff --git a/packages/ui-vue/components/designer-canvas/src/composition/function/drag-resolve.tsx b/packages/ui-vue/components/designer-canvas/src/composition/function/drag-resolve.tsx index 4ead40183e4be989919063444bff989f8b0d2788..e9761fd4465af1727b7b0b4d268fbe5d93da2fbc 100644 --- a/packages/ui-vue/components/designer-canvas/src/composition/function/drag-resolve.tsx +++ b/packages/ui-vue/components/designer-canvas/src/composition/function/drag-resolve.tsx @@ -161,6 +161,15 @@ export function dragResolveService(designerHostService: DesignerHostService) { modalEditorRef?.modalRef?.value.close(); } } + /** + * 跳过绑定字段 + */ + function onSkipBindingField() { + componentResolveContext.bindingSourceContext = null; + if (modalEditorRef?.modalRef?.value.close) { + modalEditorRef?.modalRef?.value.close(); + } + } /** * 绑定字段弹窗 */ @@ -174,7 +183,13 @@ export function dragResolveService(designerHostService: DesignerHostService) { componentSchema: { editor: { type: componentResolveContext.componentType } } }; const bindingSettings = { enable: false }; - return () => (<> ); + return () => (<> ); } /** * 工具箱拖拽控件:弹出绑定字段的窗口 diff --git a/packages/ui-vue/components/event-parameter/src/event-parameter.component.tsx b/packages/ui-vue/components/event-parameter/src/event-parameter.component.tsx index d1d04525a6d516413f7356678cdfb2a079e4caa6..66f0845a248ba1691beabc945f0482a146877be9 100644 --- a/packages/ui-vue/components/event-parameter/src/event-parameter.component.tsx +++ b/packages/ui-vue/components/event-parameter/src/event-parameter.component.tsx @@ -63,7 +63,7 @@ export default defineComponent({ } function getModelValue(modelValue: any): any { - if(editorConfig.value?.checkAndProcessBeforeAssign){ + if (editorConfig.value?.checkAndProcessBeforeAssign) { return editorConfig.value.checkAndProcessBeforeAssign(modelValue); } if (editorConfig.value?.convertEventParamValue2EditorValue) { @@ -83,7 +83,7 @@ export default defineComponent({ modelValue.value = getModelValue(newModelValue.value); }, ); - + watch( editorConfig, () => { @@ -92,7 +92,7 @@ export default defineComponent({ ); watch(() => props.data, () => { - modelValue.value = getModelValue(modelValue.value); + modelValue.value = getModelValue(modelValue.value); }); const modalService = inject(F_MODAL_SERVICE_TOKEN) as any; @@ -132,7 +132,8 @@ export default defineComponent({ // 编辑器类型 type: editorConfig.value?.type, // 根据不同编辑器,设置不同编辑器的属性 - ...editorConfig.value?.componentProps + ...editorConfig.value?.componentProps, + readonly: props.readonly }; }); 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 d35519f188e27b1e9a60023a20a1f6db38e8a50c..6f89accd22b62828935be9943429bfffde1cb4be 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 @@ -37,7 +37,7 @@ export default defineComponent({ /** 变量文本框的展示文本 */ const paramDispayText = computed(() => (parameter: any) => { if (parameter.sourceValue && parameter.targetVariable) { - const targetVariable = targetVariablePlainData.value.find(param => param.statePath === parameter.targetVariableViewModelId); + const targetVariable = targetVariablePlainData.value.find(param => param.statePath === `${parameter.targetVariableViewModelId}.${parameter.targetVariable}`); if (targetVariable && targetVariable.name) { isInValidParam.value[parameter.targetVariable] = false; return `${parameter.sourceValue}-->${targetVariable.name}`; @@ -189,7 +189,10 @@ export default defineComponent({ /** 切换目标参数后,记录参数所属的模型路径 */ function onChangeTargetVariable(newValue: string, parameter: any, selections: any) { if (selections.newValue?.length) { - parameter.targetVariableViewModelId = selections.newValue[0].statePath; + const { statePath } = selections.newValue[0]; + if (statePath?.indexOf('.') > 0) { + parameter.targetVariableViewModelId = statePath.slice(0, statePath.indexOf('.')); + } } // context.emit('changed'); } @@ -211,7 +214,7 @@ export default defineComponent({ return visualData; } // 其他参数中已使用的变量,不可再次选择 - const existedParam = parameters.value.find(param => param.id !== currentParameter.id && param.targetVariableViewModelId === visualData.raw.statePath); + const existedParam = parameters.value.find(param => param.id !== currentParameter.id && `${param.targetVariableViewModelId}.${param.targetVariable}` === visualData.raw.statePath); if (existedParam) { visualData.disabled = true; } @@ -219,10 +222,20 @@ export default defineComponent({ } }; } + /** 渲染参数面板 */ function renderParamPanel(parameter: CommunicationParameter) { const parameterForEditor = cloneDeep(parameter); const targetParameterEditor = resolveVariableTreeEditor(parameter); + + // 获取源页面的schema结构,以便于组装源页面相关的字段、变量等树形结构 + let sourceFormSchema = useFormSchema.getFormSchema(); + if (communication.value.source.formId !== formMetaBasicInfo.id) { + const externalMetadata = useFormSchema.externalFormSchema.get(communication.value.source.externalContainerId); + if (externalMetadata?.content) { + sourceFormSchema = externalMetadata?.content; + } + } const { assembleSchemaFieldsByComponent, assembleOutline, assembleStateVariables } = props.sourceCommunication.parameterData; return
    @@ -237,9 +250,9 @@ export default defineComponent({
    diff --git a/packages/ui-vue/components/events-editor/src/components/interaction-item/interaction-item.component.tsx b/packages/ui-vue/components/events-editor/src/components/interaction-item/interaction-item.component.tsx index 1e7b6cebf6bf4b700cfbd4de14be191adc562fa3..9db1d1f9fd26eb9c31936a4cb4751a923b539ebc 100644 --- a/packages/ui-vue/components/events-editor/src/components/interaction-item/interaction-item.component.tsx +++ b/packages/ui-vue/components/events-editor/src/components/interaction-item/interaction-item.component.tsx @@ -166,6 +166,10 @@ export default defineComponent({ const cmpId = controllerName.id; const newMethod = { id: guid(), label: newName, name: `${method.name}${suffix}`, handlerName, hasPath, cmpId, property, componentLists }; interaction.value.command = updateCommandHasPath(controller, newMethod); + if (interaction.value.command && useFormSchema.designerMode === 'PC_RTC') { + interaction.value.command.isRtcCommand = true; + } + interaction.value.controller = { id: controllerName.id, label: controllerName.label, diff --git a/packages/ui-vue/components/events-editor/src/components/parameter-editor/parameter-editor.component.tsx b/packages/ui-vue/components/events-editor/src/components/parameter-editor/parameter-editor.component.tsx index 65368ecfabdeb2fe8fb186e801c94cda94651c25..e13e3dac2a84abd6e0656d5730eeb4164166bf04 100644 --- a/packages/ui-vue/components/events-editor/src/components/parameter-editor/parameter-editor.component.tsx +++ b/packages/ui-vue/components/events-editor/src/components/parameter-editor/parameter-editor.component.tsx @@ -1,4 +1,4 @@ -import { SetupContext, computed, defineComponent, reactive, ref } from "vue"; +import { SetupContext, computed, defineComponent, reactive, ref, inject } from "vue"; import { ParameterEditorProps, parameterEditorProps } from "./parameter-editor.props"; import ComboList from '@farris/ui-vue/components/combo-list'; import FEventParameter from "@farris/ui-vue/components/event-parameter"; @@ -35,6 +35,7 @@ export default defineComponent({ const shouldShowEditButton = computed(() => command.value.id !== 'abandoned' && command.value.id !== 'deleted'); const shouldShowParameterEditorGroup = ref(props.showParameter); + const useFormSchema = inject('useFormSchema') as any; function getDefaultTargetComponentVM(): string { const { targetComponent } = command.value; @@ -143,7 +144,7 @@ export default defineComponent({ context.emit('change', command.value); } - function renderParameterEditor(propertyItem) { + function renderParameterEditor(propertyItem: any, commandValue: any) { // todo: ide-parameter-editor const data = reactive(propertyItem.context.data); const { @@ -152,7 +153,9 @@ export default defineComponent({ assembleStateVariables, assembleSchemaFieldsUnderBoundEntity, } = propertyItem.context.generalData; + const { designerMode } = useFormSchema; return {/* 参数第三行-参数值输入框 */}
    - {renderParameterEditor(propertyItem)} + {renderParameterEditor(propertyItem, command.value)}
    ; }); diff --git a/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx b/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx index 04f7199bc99a6a937222c69ef82e691968280b88..4e7df32f6730d887b94d32b22c620d20c3037243 100644 --- a/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/expression-editor.component.tsx @@ -150,13 +150,14 @@ export default defineComponent({ class="form-control" style="resize:none;border:none;outline:1px solid var(--f-neutral-04);">
    } - - - - + {props.showDataPanel && + + + + }
    ); diff --git a/packages/ui-vue/components/expression-editor/src/expression-editor.props.ts b/packages/ui-vue/components/expression-editor/src/expression-editor.props.ts index 25e6d52092eb13a19da5c79f68a476132623891c..4733dc32542fb9b1b1863fb582177d79edd86839 100644 --- a/packages/ui-vue/components/expression-editor/src/expression-editor.props.ts +++ b/packages/ui-vue/components/expression-editor/src/expression-editor.props.ts @@ -1,4 +1,4 @@ - + /** * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. * @@ -58,7 +58,11 @@ export const expressionEditorProps = { }, showMessageType: { type: Boolean, - default: false + default: false + }, + showDataPanel: { + type: Boolean, + default: true } } as Record; diff --git a/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx b/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx index d28972cf0041fef94f533ef624d477d660a1b3d8..98fd2ac8ed78905773d134eb458af57942169633 100644 --- a/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx +++ b/packages/ui-vue/components/expression-editor/src/expression-textbox.component.tsx @@ -1,4 +1,4 @@ -import { defineComponent, inject, ref } from "vue"; +import { defineComponent, inject, ref, watch } from "vue"; import FButtonEdit from '../../button-edit/src/button-edit.component'; import { expressionTextboxProps, ExpressionTextboxProps } from "./expression-textbox.props"; @@ -133,6 +133,10 @@ export default defineComponent({ } } + watch(() => props.modelValue, (newValue) => { + modelValue.value = newValue; + }); + return () => { return
    ; diff --git a/packages/ui-vue/components/expression-editor/src/expression-textbox.props.ts b/packages/ui-vue/components/expression-editor/src/expression-textbox.props.ts index afde95bc56b21feb683af9053a202c7808b8a67c..557708f02362fbbfc85390d0b0a6a258fb34bbe3 100644 --- a/packages/ui-vue/components/expression-editor/src/expression-textbox.props.ts +++ b/packages/ui-vue/components/expression-editor/src/expression-textbox.props.ts @@ -91,8 +91,10 @@ export const expressionTextboxProps = { type: Function as PropType<() => Promise>, default: null }, - - + showDataPanel: { + type: Boolean, + default: true + } } as Record; diff --git a/packages/ui-vue/components/expression-editor/src/schema/expression-editor.schema.json b/packages/ui-vue/components/expression-editor/src/schema/expression-editor.schema.json index 963f26b1e654c62ac4f40a409294df982fb06859..1389e3887a6d0a86b05597d84d79111f08ee478a 100644 --- a/packages/ui-vue/components/expression-editor/src/schema/expression-editor.schema.json +++ b/packages/ui-vue/components/expression-editor/src/schema/expression-editor.schema.json @@ -95,6 +95,11 @@ "description": "The showMessageType of Expression Editor", "type": "boolean", "default": false + }, + "showDataPanel":{ + "description": "Show right panel", + "type": "boolean", + "default": true } }, "required": [ diff --git a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts index d34cad44aad9c2cdc7a01d8219963228f8e7b454..a40575a2435d9d90a79fc38dbb6209332311da9b 100644 --- a/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts +++ b/packages/ui-vue/components/lookup/src/property-config/lookup.property-config.ts @@ -42,9 +42,10 @@ export class LookupPropertyConfig extends InputBaseProperty { } getPropertyConfig(propertyData: any, componentInstance: DesignerComponentInstance | null) { - this.readonlyEditor = this.getPropertyEditorParams(propertyData, [], 'readonly'); - this.visibleEditor = this.getPropertyEditorParams(propertyData, [], 'visible'); - this.requiredEditor = this.getPropertyEditorParams(propertyData, ['Const', 'Variable', 'StateMachine', 'Expression'], 'required'); + const editorTypes = propertyData.binding?.field ? [] : ['Const', 'Variable', 'StateMachine']; + this.readonlyEditor = this.getPropertyEditorParams(propertyData, editorTypes, 'readonly'); + this.visibleEditor = this.getPropertyEditorParams(propertyData, editorTypes, 'visible'); + this.requiredEditor = this.getPropertyEditorParams(propertyData, editorTypes, 'required'); this.freeInputEditor = this.getPropertyEditorParams(propertyData, ['Const', 'Variable'], 'allowFreeInput'); const basic = this.getBasicProperties(propertyData, componentInstance); diff --git a/packages/ui-vue/components/menu-lookup/src/components/modal-container.component.tsx b/packages/ui-vue/components/menu-lookup/src/components/modal-container.component.tsx index 5d1fef04e9fe1d5086eba7c120c641a32df21f90..12c96ba24c8098ea6b62a72cf623e6d0c83941ab 100644 --- a/packages/ui-vue/components/menu-lookup/src/components/modal-container.component.tsx +++ b/packages/ui-vue/components/menu-lookup/src/components/modal-container.component.tsx @@ -125,7 +125,7 @@ export default defineComponent({ return () => { return ( - + {renderNavTree()} diff --git a/packages/ui-vue/components/menu-lookup/src/composition/types.ts b/packages/ui-vue/components/menu-lookup/src/composition/types.ts index d9648f09e93a6dc9e62c57b1544810bb3b209a32..173869eaffa6d2677ac65ccab1a32f85714b0718 100644 --- a/packages/ui-vue/components/menu-lookup/src/composition/types.ts +++ b/packages/ui-vue/components/menu-lookup/src/composition/types.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-use-before-define */ import { Ref } from 'vue'; export type TargetType = 'menu' | 'app'; diff --git a/packages/ui-vue/components/property-editor/index.ts b/packages/ui-vue/components/property-editor/index.ts index 4b58d5c871c264f7e92ef62b707c80efbbadc9bc..2f4d755190886dd562bd45362212554648b62d17 100644 --- a/packages/ui-vue/components/property-editor/index.ts +++ b/packages/ui-vue/components/property-editor/index.ts @@ -14,20 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import type { App } from 'vue'; -import PropertyEditor from './src/property-editor.component'; +import FPropertyEditor from './src/property-editor.component'; import { propsResolver } from './src/property-editor.props'; +import { withInstall } from '@farris/ui-vue/components/common'; export * from './src/property-editor.props'; -export { PropertyEditor }; -export default { - install(app: App): void { - app.component(PropertyEditor.name as string, PropertyEditor); - }, - register(componentMap: Record, propsResolverMap: Record, configResolverMap: Record, resolverMap: Record): void { - componentMap['property-editor'] = PropertyEditor; - propsResolverMap['property-editor'] = propsResolver; - } +FPropertyEditor.register = (componentMap: Record, propsResolverMap: Record, configResolverMap: Record, resolverMap: Record) => { + componentMap['property-editor'] = FPropertyEditor; + propsResolverMap['property-editor'] = propsResolver; }; +export { FPropertyEditor }; +export default withInstall(FPropertyEditor); diff --git a/packages/ui-vue/components/property-editor/src/components/expression/expression-property.component.tsx b/packages/ui-vue/components/property-editor/src/components/expression/expression-property.component.tsx index 95b1e1939541f80a9a3767104a35df07baf9125d..c675623ad679469ecfca715a8ec77348d3ce0ab3 100644 --- a/packages/ui-vue/components/property-editor/src/components/expression/expression-property.component.tsx +++ b/packages/ui-vue/components/property-editor/src/components/expression/expression-property.component.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ref, SetupContext } from 'vue'; +import { ref, SetupContext, watch } from 'vue'; import { ExpressionPropertyProps } from './expression-property.props'; import './expression-property.css'; import { UsePropertyValue } from '../../composition/types'; @@ -32,7 +32,7 @@ export default function ( /** 表达式相关方法 */ const { getExpressionValue } = useExpression(props, context, usePropertyValueComposition); /** 表达式属性值 */ - const expressionValue = getExpressionValue(); + let expressionValue = getExpressionValue(); const { expressionInfo } = expressionValue.value; /** 表达式的规则值 */ const expressionRule = ref(expressionInfo.value); @@ -41,14 +41,20 @@ export default function ( /** 表达式编辑器所需的配置 */ const expressionConfig = ref(props.expressionConfig); + watch(() => [props.expressionConfig], () => { + expressionConfig.value = props.expressionConfig; + expressionValue = getExpressionValue(); + expressionRule.value = expressionValue.value.expressionInfo.value; + }); + function onSubmitModal({ expression, message }) { if (!expression) { return; } expressionValue.value.expressionInfo.value = expression; - if(message){ + if (message) { expressionValue.value.expressionInfo.message = message; - }else{ + } else { delete expressionValue.value.expressionInfo.message; } triggerValueChange(expressionValue.value); diff --git a/packages/ui-vue/components/property-editor/src/composition/use-expression.ts b/packages/ui-vue/components/property-editor/src/composition/use-expression.ts index 106226409835669ffc79077abaeb05b4a411a68c..43707cb684c0bdba24bcc60b823e572504ae5c85 100644 --- a/packages/ui-vue/components/property-editor/src/composition/use-expression.ts +++ b/packages/ui-vue/components/property-editor/src/composition/use-expression.ts @@ -10,15 +10,12 @@ export function useExpression( const { getPropertyValue } = usePropertyValueComposition; const expressionType = props.id; - const { expressionConfig = {} } = props; - const { expressionInfo = { value: '', targetId: '', targetType: '', expressionType: '' } } = expressionConfig; - const { targetId } = expressionInfo; /** * 生成表达式内码 * @returns */ - function generateExpressionId(): string { + function generateExpressionId(targetId: string): string { return targetId + '_' + expressionType; } @@ -26,11 +23,11 @@ export function useExpression( * 生成一个空的表达式值 * @returns */ - function generateExpressionValue(): ExpressionValue { + function generateExpressionValue(expressionInfo: any): ExpressionValue { return { type: 'Expression', - expressionId: generateExpressionId(), - expressionInfo: expressionInfo + expressionId: generateExpressionId(expressionInfo?.targetId || ''), + expressionInfo }; } @@ -38,15 +35,18 @@ export function useExpression( * 获取表达式的值 */ function getExpressionValue(): Ref { + const { expressionInfo = { value: '', targetId: '', targetType: '', expressionType: '' } } = props.expressionConfig; + const propertyValue = getPropertyValue('Expression'); // 1、表达式为空,生成一个空的表达式值 if (!propertyValue.value) { - propertyValue.value = generateExpressionValue(); + propertyValue.value = generateExpressionValue(expressionInfo); return propertyValue; } // 2、记录expressionInfo的值 propertyValue.value.expressionInfo = expressionInfo; + propertyValue.value.expressionId = generateExpressionId(expressionInfo?.targetId); return propertyValue; } diff --git a/packages/ui-vue/components/property-editor/src/composition/use-property-type.ts b/packages/ui-vue/components/property-editor/src/composition/use-property-type.ts index 402132cce73290770daa6797eb8ff93794e8902b..25fbf9f4c7327ac44cc73b48996ccf16f836daf8 100644 --- a/packages/ui-vue/components/property-editor/src/composition/use-property-type.ts +++ b/packages/ui-vue/components/property-editor/src/composition/use-property-type.ts @@ -1,6 +1,6 @@ -import { Ref, SetupContext, ref } from "vue"; +import { Ref, SetupContext, ref, watch } from "vue"; import { PropertyEditorProps, PropertyType } from "../property-editor.props"; import { PROPERTY_TYPE_ENUMS } from "./datas"; import { ConstEnumItem, PropertyTypeItem, UsePropertyType } from "./types"; @@ -20,7 +20,6 @@ export function usePropertyType( /** 当前选择的属性类型 */ const currentPropertyType: Ref = ref(); - /** * 获取允许选择的属性类型数据 */ @@ -30,6 +29,11 @@ export function usePropertyType( return allowedPropertyTypeItems; } + watch(() => [props.propertyTypes], () => { + propertyTypes.value = props.propertyTypes; + getAllowedPropertyTypeItems(); + }); + /** * 判断是否是状态机(旧的状态机格式) * @param propertyValue diff --git a/packages/ui-vue/components/property-editor/src/composition/use-property-value.ts b/packages/ui-vue/components/property-editor/src/composition/use-property-value.ts index 904a95e963779dd7cc915f01209453c59d4cf806..b9af6f6d7a669dd00b94cc90d2581c2c45643bac 100644 --- a/packages/ui-vue/components/property-editor/src/composition/use-property-value.ts +++ b/packages/ui-vue/components/property-editor/src/composition/use-property-value.ts @@ -52,7 +52,7 @@ export function usePropertyValue( case 'Variable': return propertyValue && propertyValue.field; case 'Custom': - return propertyValue !== undefined; + return true; case 'Expression': return propertyValue && propertyValue.expressionInfo && propertyValue.expressionInfo.value; case 'StateMachine': diff --git a/packages/ui-vue/components/property-editor/src/property-editor.component.tsx b/packages/ui-vue/components/property-editor/src/property-editor.component.tsx index 604a13bed8f7ee485a05e6e73ad1ac72b712e8c9..591614e7dd1c94782c2e42e84fd5eb117efbe856 100644 --- a/packages/ui-vue/components/property-editor/src/property-editor.component.tsx +++ b/packages/ui-vue/components/property-editor/src/property-editor.component.tsx @@ -1,4 +1,4 @@ - + /** * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. * @@ -30,7 +30,7 @@ import './property-editor.css'; export default defineComponent({ name: 'FPropertyEditor', props: propertyEditorProps, - emits: ['valueChange','beforeOpenVariables'] as (string[] & ThisType) | undefined, + emits: ['valueChange', 'beforeOpenVariables'] as (string[] & ThisType) | undefined, setup(props: PropertyEditorProps, context: SetupContext) { const readOnly = ref(false); @@ -55,6 +55,7 @@ export default defineComponent({ return selectedPropertyType === currentPropertyType.value; }); + context.expose({ currentPropertyType }); /** * 左侧属性类型变化 */ @@ -63,7 +64,7 @@ export default defineComponent({ const propertyValue = getPropertyValue(currentPropertyType.value); // 2、如果属性值不为空,触发属性值变更 - if (isPropertyValueValid(currentPropertyType.value,propertyValue.value)) { + if (isPropertyValueValid(currentPropertyType.value, propertyValue.value)) { triggerValueChange(propertyValue.value); } } diff --git a/packages/ui-vue/components/property-editor/src/property-editor.props.ts b/packages/ui-vue/components/property-editor/src/property-editor.props.ts index 9ba44286bef8fb49191591af4f16e49b262e704e..8655d54befc054ab6ca601c401245cbd28142fcd 100644 --- a/packages/ui-vue/components/property-editor/src/property-editor.props.ts +++ b/packages/ui-vue/components/property-editor/src/property-editor.props.ts @@ -40,6 +40,7 @@ export const propertyEditorProps = { /** 属性类型列表 */ propertyTypes: { type: Array, default: [] }, + } as Record; export type PropertyEditorProps = ExtractPropTypes; diff --git a/packages/ui-vue/components/property-panel/src/composition/entity/base-property.ts b/packages/ui-vue/components/property-panel/src/composition/entity/base-property.ts index 18d39018d9b489a1f13830eccfadd18859ccc4a1..d37b0f6e2d7b8c78b67dc88bcb827c2be2e0553e 100644 --- a/packages/ui-vue/components/property-panel/src/composition/entity/base-property.ts +++ b/packages/ui-vue/components/property-panel/src/composition/entity/base-property.ts @@ -175,7 +175,13 @@ export class BaseControlProperty { } protected getVisibleProperty(propertyData, position = '') { - const editor = this.getPropertyEditorParams(propertyData, position === 'gridFieldEditor' ? ['Const', 'Expression'] : ['Const', 'Variable', 'StateMachine', 'Expression'], 'visible'); + let editorTypes = ['Const', 'Variable', 'StateMachine', 'Expression']; + if (position === 'gridFieldEditor') { + editorTypes = ['Const', 'Expression']; + } else if (position === 'form-group' && !propertyData.binding?.field) { + editorTypes = ['Const', 'Variable', 'StateMachine']; + } + const editor = this.getPropertyEditorParams(propertyData, editorTypes, 'visible'); return { visible: { title: "是否可见", diff --git a/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts index d976887149d4d74b734e1d164061c691eee538e3..c8640051d2ef7eead891e415a0f6be94a61c5690 100644 --- a/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts +++ b/packages/ui-vue/components/property-panel/src/composition/entity/expression-property.ts @@ -377,6 +377,7 @@ export class ExpressionProperty { return { description: "表达式", title: "表达式", + hide: !propertyData.binding, properties: { ...this.getExpressionEditorOptions(propertyData, type, expressionTypes, callback) } diff --git a/packages/ui-vue/components/property-panel/src/composition/entity/input-base-property.ts b/packages/ui-vue/components/property-panel/src/composition/entity/input-base-property.ts index ad4ad877bb5de19b82efce18428bd2cae6c8d5f5..b6d9671d2a485f72d2a0dcfa992640b002cd004d 100644 --- a/packages/ui-vue/components/property-panel/src/composition/entity/input-base-property.ts +++ b/packages/ui-vue/components/property-panel/src/composition/entity/input-base-property.ts @@ -27,7 +27,7 @@ export class InputBaseProperty extends BaseControlProperty { this.propertyConfig.categories['basic'] = this.getBasicProperties(propertyData, componentInstance); // 外观 this.propertyConfig.categories['appearance'] = this.getAppearanceProperties(propertyData, componentInstance); - this.propertyConfig.categories['behavior'] = this.getBehaviorConfig(propertyData); + this.propertyConfig.categories['behavior'] = this.getBehaviorConfig(propertyData,'form-group'); } public getPropertyConfig(propertyData: any, componentInstance: DesignerComponentInstance) { this.getCommonPropertyConfig(propertyData, componentInstance); @@ -338,9 +338,9 @@ export class InputBaseProperty extends BaseControlProperty { $converter: "/converter/property-editor.converter", parentPropertyID: 'editor' }, info); - - const readonlyEditor = this.getPropertyEditorParams(propertyData, [], 'readonly'); - const requiredEditor = this.getPropertyEditorParams(propertyData, [], 'required'); + const editorTypes = propertyData.binding?.field ? [] : ['Const', 'Variable', 'StateMachine']; + const readonlyEditor = this.getPropertyEditorParams(propertyData, editorTypes, 'readonly'); + const requiredEditor = this.getPropertyEditorParams(propertyData, editorTypes, 'required'); const editorProperties = { readonly: { description: "",