@nocobase/client-v2 2.2.0-alpha.1 → 2.2.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/APIClient.d.ts +1 -3
- package/es/BaseApplication.d.ts +3 -0
- package/es/PluginSettingsManager.d.ts +33 -0
- package/es/RouteRepository.d.ts +29 -6
- package/es/RouterManager.d.ts +15 -0
- package/es/authRedirect.d.ts +1 -0
- package/es/collection-field-interface/CollectionFieldInterface.d.ts +1 -0
- package/es/collection-field-interface/CollectionFieldInterfaceManager.d.ts +1 -0
- package/es/components/category-tabs/SortableCategoryTabs.d.ts +55 -0
- package/es/components/category-tabs/index.d.ts +9 -0
- package/es/components/form/JsonTextArea.d.ts +2 -1
- package/es/components/form/ScanInput/useCodeScanner.d.ts +3 -2
- package/es/components/form/TypedVariableInput.d.ts +31 -5
- package/es/components/form/VariableJsonTextArea.d.ts +19 -0
- package/es/components/form/filter/CollectionFilter.d.ts +2 -0
- package/es/components/form/filter/CollectionFilterItem.d.ts +11 -1
- package/es/components/form/filter/CollectionFilterPanel.d.ts +2 -0
- package/es/components/form/filter/index.d.ts +2 -0
- package/es/components/form/filter/useFilterActionProps.d.ts +2 -0
- package/es/components/form/index.d.ts +1 -0
- package/es/components/index.d.ts +2 -0
- package/es/entry-actions/EntryActionManager.d.ts +24 -0
- package/es/entry-actions/index.d.ts +9 -0
- package/es/flow/actions/afterSuccess.d.ts +8 -1
- package/es/flow/actions/index.d.ts +2 -2
- package/es/flow/actions/linkageRules.d.ts +2 -0
- package/es/flow/admin-shell/BaseLayoutModel.d.ts +6 -0
- package/es/flow/admin-shell/BaseLayoutRouteCoordinator.d.ts +7 -0
- package/es/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.d.ts +2 -0
- package/es/flow/admin-shell/admin-layout/AdminLayoutMenuFlowUtils.d.ts +2 -1
- package/es/flow/admin-shell/admin-layout/AdminLayoutMenuModels.d.ts +3 -0
- package/es/flow/admin-shell/admin-layout/AdminLayoutMenuUtils.d.ts +3 -2
- package/es/flow/admin-shell/admin-layout/AdminLayoutSlotModels.d.ts +5 -0
- package/es/flow/admin-shell/admin-layout/AppListRender.d.ts +2 -1
- package/es/flow/admin-shell/admin-layout/AppSwitcherActionPanelModel.d.ts +24 -0
- package/es/flow/admin-shell/admin-layout/index.d.ts +1 -0
- package/es/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.d.ts +6 -0
- package/es/flow/admin-shell/admin-layout/useApplications.d.ts +7 -2
- package/es/flow/components/FieldAssignExactDatePicker.d.ts +1 -0
- package/es/flow/components/FieldAssignRulesEditor.d.ts +3 -1
- package/es/flow/components/FieldAssignValueInput.d.ts +9 -0
- package/es/flow/components/FlowRoute.d.ts +2 -2
- package/es/flow/components/RunJSValueEditor.d.ts +1 -0
- package/es/flow/components/filter/FilterGroup.d.ts +1 -0
- package/es/flow/components/filter/VariableFilterItem.d.ts +6 -1
- package/es/flow/index.d.ts +1 -0
- package/es/flow/internal/registerDeviceTypeContext.d.ts +10 -0
- package/es/flow/models/base/ActionModelCore.d.ts +2 -0
- package/es/flow/models/base/BlockGridModel.d.ts +3 -0
- package/es/flow/models/base/GridModel.d.ts +1 -1
- package/es/flow/models/base/PageModel/PageModel.d.ts +12 -0
- package/es/flow/models/base/PageModel/PageModelTabBar.d.ts +22 -0
- package/es/flow/models/base/PageModel/PageTabModel.d.ts +12 -0
- package/es/flow/models/blocks/filter-form/FilterFormBlockModel.d.ts +5 -0
- package/es/flow/models/blocks/form/FormBlockModel.d.ts +4 -0
- package/es/flow/models/blocks/form/QuickEditFormModel.d.ts +17 -2
- package/es/flow/models/blocks/form/submitHandler.d.ts +1 -1
- package/es/flow/models/blocks/form/value-runtime/rules.d.ts +21 -0
- package/es/flow/models/blocks/form/value-runtime/runtime.d.ts +30 -0
- package/es/flow/models/blocks/form/value-runtime/types.d.ts +2 -2
- package/es/flow/models/blocks/js-block/JSBlock.d.ts +1 -0
- package/es/flow/models/blocks/table/TableActionsColumnModel.d.ts +1 -0
- package/es/flow/models/blocks/table/TableBlockModel.d.ts +1 -0
- package/es/flow/models/blocks/table/TableColumnModel.d.ts +1 -0
- package/es/flow/models/blocks/table/dragSort/dragSortHooks.d.ts +1 -1
- package/es/flow/models/blocks/table/dragSort/dragSortSettings.d.ts +2 -1
- package/es/flow/models/blocks/table/dragSort/dragSortUtils.d.ts +6 -4
- package/es/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.d.ts +2 -0
- package/es/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableColumnModel.d.ts +6 -0
- package/es/flow/models/fields/DateTimeFieldModel/dateLimit.d.ts +15 -7
- package/es/flow/resolveViewParamsToViewList.d.ts +1 -1
- package/es/flow/routeTransientInputArgs.d.ts +14 -0
- package/es/flow/utils/dataScopeRowSnapshot.d.ts +59 -0
- package/es/flow/utils/dateTimeDisplayProps.d.ts +49 -0
- package/es/flow/utils/formValueDeps.d.ts +32 -0
- package/es/flow-compat/FieldValidation.d.ts +2 -1
- package/es/flow-compat/fieldValidationConstants.d.ts +1 -1
- package/es/flow-compat/routeTypes.d.ts +1 -0
- package/es/index.d.ts +8 -1
- package/es/index.mjs +367 -181
- package/es/utils/getRouteRuntimeVersion.d.ts +23 -0
- package/es/utils/index.d.ts +1 -0
- package/es/utils/markdownSanitize.d.ts +11 -0
- package/lib/index.js +367 -181
- package/lib/locale/languageCodes.js +3 -1
- package/package.json +9 -7
- package/src/APIClient.ts +1 -10
- package/src/Application.tsx +4 -0
- package/src/BaseApplication.tsx +13 -6
- package/src/PluginSettingsManager.ts +53 -0
- package/src/RouteRepository.ts +151 -24
- package/src/RouterManager.tsx +142 -1
- package/src/__tests__/PluginSettingsManager.test.ts +13 -0
- package/src/__tests__/RouteRepository.test.ts +239 -0
- package/src/__tests__/RouterManager.test.ts +125 -0
- package/src/__tests__/app.test.tsx +73 -0
- package/src/__tests__/authRedirect.test.ts +17 -0
- package/src/__tests__/browserChecker.test.ts +61 -0
- package/src/__tests__/exports.test.ts +16 -0
- package/src/__tests__/getRouteRuntimeVersion.test.ts +68 -0
- package/src/__tests__/nocobase-buildin-plugin-auth.test.tsx +234 -2
- package/src/__tests__/plugin-manager.test.tsx +44 -2
- package/src/__tests__/settings-center.test.tsx +40 -1
- package/src/authRedirect.ts +38 -0
- package/src/collection-field-interface/CollectionFieldInterface.ts +1 -0
- package/src/collection-field-interface/CollectionFieldInterfaceManager.ts +1 -0
- package/src/collection-manager/field-configure.ts +1 -1
- package/src/collection-manager/field-validation.ts +1 -1
- package/src/collection-manager/interfaces/id.ts +1 -1
- package/src/collection-manager/interfaces/m2m.tsx +2 -2
- package/src/collection-manager/interfaces/m2o.tsx +2 -2
- package/src/collection-manager/interfaces/nanoid.ts +1 -1
- package/src/collection-manager/interfaces/o2m.tsx +2 -2
- package/src/collection-manager/interfaces/obo.tsx +2 -2
- package/src/collection-manager/interfaces/oho.tsx +2 -2
- package/src/collection-manager/interfaces/properties/index.ts +2 -2
- package/src/collection-manager/interfaces/uuid.ts +1 -1
- package/src/components/AppComponents.tsx +19 -3
- package/src/components/README.md +7 -1
- package/src/components/README.zh-CN.md +6 -1
- package/src/components/category-tabs/SortableCategoryTabs.tsx +210 -0
- package/src/components/category-tabs/index.ts +10 -0
- package/src/components/form/JsonTextArea.tsx +25 -11
- package/src/components/form/ScanInput/CodeScanner.tsx +79 -35
- package/src/components/form/ScanInput/__tests__/CodeScanner.test.tsx +101 -0
- package/src/components/form/ScanInput/__tests__/useCodeScanner.test.tsx +284 -11
- package/src/components/form/ScanInput/useCodeScanner.ts +332 -24
- package/src/components/form/TypedVariableInput.tsx +452 -101
- package/src/components/form/VariableJsonTextArea.tsx +175 -0
- package/src/components/form/__tests__/JsonTextArea.test.tsx +43 -0
- package/src/components/form/__tests__/TypedVariableInput.test.tsx +364 -12
- package/src/components/form/__tests__/VariableJsonTextArea.test.tsx +86 -0
- package/src/components/form/filter/CollectionFilter.tsx +4 -0
- package/src/components/form/filter/CollectionFilterItem.tsx +32 -7
- package/src/components/form/filter/CollectionFilterPanel.tsx +4 -0
- package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +38 -0
- package/src/components/form/filter/__tests__/useFilterActionProps.test.tsx +95 -0
- package/src/components/form/filter/index.ts +2 -0
- package/src/components/form/filter/useFilterActionProps.ts +37 -6
- package/src/components/form/index.tsx +1 -0
- package/src/components/index.ts +2 -0
- package/src/entry-actions/EntryActionManager.ts +76 -0
- package/src/entry-actions/index.ts +10 -0
- package/src/flow/FlowPage.tsx +38 -3
- package/src/flow/__tests__/FlowPage.test.tsx +201 -27
- package/src/flow/__tests__/FlowRoute.test.tsx +1181 -80
- package/src/flow/__tests__/PluginFlowEngine.test.ts +58 -0
- package/src/flow/__tests__/getKey.test.ts +7 -0
- package/src/flow/__tests__/resolveViewParamsToViewList.test.ts +34 -0
- package/src/flow/actions/__tests__/actionLinkageRules.forkProps.test.ts +115 -0
- package/src/flow/actions/__tests__/afterSuccess.test.ts +73 -0
- package/src/flow/actions/__tests__/dataScopeFilter.test.ts +120 -0
- package/src/flow/actions/__tests__/dataScopeFormValueClear.test.ts +1124 -0
- package/src/flow/actions/__tests__/fieldLinkageRules.scopeDepth.test.ts +150 -1
- package/src/flow/actions/__tests__/linkageAssignField.legacy.test.ts +135 -0
- package/src/flow/actions/__tests__/linkageRules.hiddenSync.restore.test.ts +19 -5
- package/src/flow/actions/__tests__/linkageRules.subFormSetFieldProps.test.ts +92 -0
- package/src/flow/actions/__tests__/linkageRules.tab.test.ts +171 -0
- package/src/flow/actions/__tests__/linkageRulesRefresh.test.ts +7 -3
- package/src/flow/actions/__tests__/openView.defineProps.route.test.tsx +164 -0
- package/src/flow/actions/__tests__/subFormFieldLinkageRules.inputArgs.test.ts +2 -2
- package/src/flow/actions/afterSuccess.tsx +142 -3
- package/src/flow/actions/customVariable.tsx +1 -2
- package/src/flow/actions/dataScopeFilter.ts +20 -1
- package/src/flow/actions/dateTimeFormat.tsx +42 -28
- package/src/flow/actions/index.ts +3 -1
- package/src/flow/actions/linkageRules.tsx +209 -47
- package/src/flow/actions/linkageRulesFormValueRefresh.ts +22 -130
- package/src/flow/actions/linkageRulesRefresh.tsx +2 -6
- package/src/flow/actions/openView.tsx +59 -5
- package/src/flow/actions/runjs.tsx +2 -14
- package/src/flow/actions/validation.tsx +62 -30
- package/src/flow/admin-shell/BaseLayoutModel.tsx +149 -3
- package/src/flow/admin-shell/BaseLayoutRouteCoordinator.ts +187 -42
- package/src/flow/admin-shell/__tests__/AdminLayoutRouteCoordinator.test.ts +1020 -110
- package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +74 -14
- package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.test.tsx +486 -0
- package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.tsx +64 -8
- package/src/flow/admin-shell/admin-layout/AdminLayoutMenuFlowUtils.ts +5 -3
- package/src/flow/admin-shell/admin-layout/AdminLayoutMenuModels.tsx +61 -9
- package/src/flow/admin-shell/admin-layout/AdminLayoutMenuUtils.tsx +71 -8
- package/src/flow/admin-shell/admin-layout/AdminLayoutModel.tsx +1 -1
- package/src/flow/admin-shell/admin-layout/AdminLayoutSlotModels.tsx +23 -9
- package/src/flow/admin-shell/admin-layout/AppListRender.tsx +13 -2
- package/src/flow/admin-shell/admin-layout/AppSwitcherActionPanelModel.tsx +289 -0
- package/src/flow/admin-shell/admin-layout/HelpLite.tsx +1 -3
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutComponent.test.tsx +435 -0
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutMenuModels.test.ts +99 -0
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutModel.test.tsx +518 -2
- package/src/flow/admin-shell/admin-layout/__tests__/TopbarActionsBar.test.tsx +214 -2
- package/src/flow/admin-shell/admin-layout/index.ts +1 -0
- package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.test.ts +20 -0
- package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.ts +33 -5
- package/src/flow/admin-shell/admin-layout/useApplications.tsx +81 -12
- package/src/flow/common/Markdown/Display.tsx +14 -3
- package/src/flow/common/Markdown/Edit.tsx +19 -7
- package/src/flow/common/Markdown/style.ts +4 -0
- package/src/flow/components/BlockItemCard.tsx +2 -2
- package/src/flow/components/DefaultValue.tsx +1 -2
- package/src/flow/components/DynamicFlowsIcon.tsx +447 -126
- package/src/flow/components/FieldAssignExactDatePicker.tsx +25 -11
- package/src/flow/components/FieldAssignRulesEditor.tsx +128 -21
- package/src/flow/components/FieldAssignValueInput.tsx +91 -20
- package/src/flow/components/FlowRoute.tsx +256 -53
- package/src/flow/components/RunJSValueEditor.tsx +9 -1
- package/src/flow/components/__tests__/DynamicFlowsIcon.test.tsx +148 -2
- package/src/flow/components/__tests__/FieldAssignRulesEditor.test.tsx +508 -4
- package/src/flow/components/__tests__/FieldAssignValueInput.context.test.tsx +216 -0
- package/src/flow/components/__tests__/fieldAssignOptions.test.ts +151 -3
- package/src/flow/components/code-editor/__tests__/useCodeRunner.test.tsx +2 -17
- package/src/flow/components/code-editor/hooks/useCodeRunner.ts +2 -14
- package/src/flow/components/code-editor/runjsDiagnostics.ts +8 -45
- package/src/flow/components/fieldAssignOptions.ts +155 -27
- package/src/flow/components/filter/FilterGroup.tsx +33 -5
- package/src/flow/components/filter/VariableFilterItem.tsx +158 -10
- package/src/flow/components/filter/__tests__/FilterGroup.test.tsx +45 -0
- package/src/flow/components/filter/__tests__/VariableFilterItem.leftMetaTree.test.tsx +9 -0
- package/src/flow/components/filter/__tests__/VariableFilterItem.test.tsx +70 -1
- package/src/flow/flows/editMarkdownFlow.tsx +1 -1
- package/src/flow/getViewDiffAndUpdateHidden.tsx +1 -0
- package/src/flow/index.ts +4 -1
- package/src/flow/internal/components/Markdown/util.ts +2 -1
- package/src/flow/internal/registerDeviceTypeContext.ts +39 -0
- package/src/flow/internal/utils/operatorSchemaHelper.ts +15 -1
- package/src/flow/models/actions/JSActionModel.tsx +2 -7
- package/src/flow/models/actions/JSCollectionActionModel.tsx +2 -7
- package/src/flow/models/actions/JSItemActionModel.tsx +2 -7
- package/src/flow/models/actions/JSRecordActionModel.tsx +2 -7
- package/src/flow/models/base/ActionModel.tsx +21 -8
- package/src/flow/models/base/ActionModelCore.tsx +11 -4
- package/src/flow/models/base/BlockGridModel.tsx +26 -0
- package/src/flow/models/base/CollectionBlockModel.tsx +6 -2
- package/src/flow/models/base/GridModel.tsx +38 -7
- package/src/flow/models/base/PageModel/PageModel.tsx +387 -50
- package/src/flow/models/base/PageModel/PageModelTabBar.tsx +114 -0
- package/src/flow/models/base/PageModel/PageTabModel.tsx +249 -18
- package/src/flow/models/base/PageModel/__tests__/PageModel.test.ts +817 -13
- package/src/flow/models/base/PageModel/__tests__/PageModelTabBar.module-isolation.test.tsx +130 -0
- package/src/flow/models/base/PageModel/__tests__/PageModelTabBar.test.tsx +118 -0
- package/src/flow/models/base/PageModel/__tests__/PageTabModel.test.ts +1075 -7
- package/src/flow/models/base/__tests__/ActionModel.test.ts +83 -0
- package/src/flow/models/base/__tests__/ActionModelCore.render.test.tsx +37 -0
- package/src/flow/models/base/__tests__/BlockGridModel.selectSceneActivation.test.ts +124 -0
- package/src/flow/models/base/__tests__/CollectionBlockModel.addAppends.test.ts +41 -0
- package/src/flow/models/base/__tests__/GridModel.dragSnapshotContainer.test.ts +239 -1
- package/src/flow/models/base/__tests__/transformRowsToSingleColumn.test.ts +48 -0
- package/src/flow/models/blocks/filter-form/FilterFormBlockModel.tsx +59 -6
- package/src/flow/models/blocks/filter-form/FilterFormItemModel.tsx +27 -12
- package/src/flow/models/blocks/filter-form/FilterFormJSActionModel.tsx +2 -7
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormItemModel.defineChildren.test.ts +36 -0
- package/src/flow/models/blocks/filter-form/__tests__/defaultValues.wiring.test.ts +143 -4
- package/src/flow/models/blocks/filter-form/fields/FilterFormCustomFieldModel.tsx +1 -1
- package/src/flow/models/blocks/filter-manager/flow-actions/__tests__/customizeFilterRender.test.tsx +56 -1
- package/src/flow/models/blocks/form/EditFormModel.tsx +1 -0
- package/src/flow/models/blocks/form/FormActionModel.tsx +1 -1
- package/src/flow/models/blocks/form/FormBlockModel.tsx +7 -0
- package/src/flow/models/blocks/form/JSFormActionModel.tsx +2 -7
- package/src/flow/models/blocks/form/QuickEditFormModel.tsx +189 -36
- package/src/flow/models/blocks/form/__tests__/FormBlockModel.test.tsx +17 -0
- package/src/flow/models/blocks/form/__tests__/QuickEditFormModel.quickEdit.test.ts +350 -2
- package/src/flow/models/blocks/form/__tests__/submitHandler.test.ts +54 -1
- package/src/flow/models/blocks/form/submitHandler.ts +17 -3
- package/src/flow/models/blocks/form/value-runtime/__tests__/runtime.test.ts +940 -75
- package/src/flow/models/blocks/form/value-runtime/rules.ts +445 -13
- package/src/flow/models/blocks/form/value-runtime/runtime.ts +348 -13
- package/src/flow/models/blocks/form/value-runtime/types.ts +2 -2
- package/src/flow/models/blocks/js-block/JSBlock.tsx +225 -9
- package/src/flow/models/blocks/js-block/__tests__/JSBlockModel.test.tsx +150 -0
- package/src/flow/models/blocks/table/JSColumnModel.tsx +1 -9
- package/src/flow/models/blocks/table/TableActionsColumnModel.tsx +38 -14
- package/src/flow/models/blocks/table/TableBlockModel.tsx +42 -19
- package/src/flow/models/blocks/table/TableColumnModel.tsx +72 -6
- package/src/flow/models/blocks/table/__tests__/TableActionsColumnModel.test.tsx +111 -1
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.dragSort.test.ts +127 -0
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.mobileSettingsButtons.test.tsx +78 -0
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.quickEditRefresh.test.ts +12 -0
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.rowSelection.test.tsx +1 -0
- package/src/flow/models/blocks/table/__tests__/TableColumnModel.test.tsx +243 -1
- package/src/flow/models/blocks/table/dragSort/dragSortHooks.tsx +28 -17
- package/src/flow/models/blocks/table/dragSort/dragSortSettings.ts +13 -6
- package/src/flow/models/blocks/table/dragSort/dragSortUtils.ts +15 -2
- package/src/flow/models/fields/AssociationFieldModel/AssociationFieldModel.tsx +1 -1
- package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/PopupSubTableFieldModel.tsx +31 -7
- package/src/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.tsx +61 -17
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableColumnModel.tsx +141 -19
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableField.tsx +13 -1
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/__tests__/SubTableColumnModel.rowRecord.test.ts +197 -0
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/__tests__/SubTableFieldModel.reset.test.ts +180 -0
- package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/index.tsx +6 -4
- package/src/flow/models/fields/AssociationFieldModel/__tests__/AssociationFieldModel.updateAssociation.test.ts +72 -0
- package/src/flow/models/fields/AssociationFieldModel/__tests__/RecordPickerFieldModel.itemContext.test.ts +23 -0
- package/src/flow/models/fields/ClickableFieldModel.tsx +5 -0
- package/src/flow/models/fields/DateTimeFieldModel/__tests__/DateTimeNoTzFieldModel.dateLimit.test.tsx +149 -0
- package/src/flow/models/fields/DateTimeFieldModel/dateLimit.ts +149 -113
- package/src/flow/models/fields/DisplayDateTimeFieldModel.tsx +29 -1
- package/src/flow/models/fields/InputFieldModel.tsx +40 -2
- package/src/flow/models/fields/JSEditableFieldModel.tsx +2 -11
- package/src/flow/models/fields/JSFieldModel.tsx +2 -7
- package/src/flow/models/fields/JSItemModel.tsx +2 -14
- package/src/flow/models/fields/SelectFieldModel.tsx +6 -4
- package/src/flow/models/fields/TextareaFieldModel.tsx +72 -3
- package/src/flow/models/fields/VariableFieldFormModel.tsx +3 -3
- package/src/flow/models/fields/__tests__/DisplayDateTimeFieldModel.test.tsx +96 -0
- package/src/flow/models/fields/__tests__/InputFieldModel.test.tsx +117 -1
- package/src/flow/models/fields/__tests__/SelectFieldModel.test.tsx +43 -0
- package/src/flow/models/fields/__tests__/TextareaFieldModel.test.tsx +131 -0
- package/src/flow/models/fields/__tests__/VariableFieldFormModel.test.tsx +51 -0
- package/src/flow/models/fields/mobile-components/MobileLazySelect.tsx +20 -10
- package/src/flow/models/fields/mobile-components/MobileSelect.tsx +24 -12
- package/src/flow/models/topbar/TopbarActionModel.tsx +168 -10
- package/src/flow/resolveViewParamsToViewList.tsx +11 -3
- package/src/flow/routeTransientInputArgs.ts +27 -0
- package/src/flow/utils/__tests__/dateTimeFormat.test.ts +300 -0
- package/src/flow/utils/dataScopeFormValueClear.ts +219 -81
- package/src/flow/utils/dataScopeRowSnapshot.ts +616 -0
- package/src/flow/utils/dateTimeDisplayProps.ts +135 -0
- package/src/flow/utils/formValueDeps.ts +170 -0
- package/src/flow-compat/FieldValidation.tsx +122 -60
- package/src/flow-compat/Popover.tsx +43 -4
- package/src/flow-compat/__tests__/Popover.test.tsx +34 -0
- package/src/flow-compat/fieldValidationConstants.ts +1 -1
- package/src/flow-compat/routeTypes.ts +1 -0
- package/src/index.ts +14 -1
- package/src/layout-manager/__tests__/LayoutRoute.test.tsx +41 -1
- package/src/locale/languageCodes.ts +3 -1
- package/src/nocobase-buildin-plugin/index.tsx +63 -15
- package/src/settings-center/AdminSettingsLayout.tsx +10 -2
- package/src/settings-center/SystemSettingsPage.tsx +1 -2
- package/src/settings-center/plugin-manager/PluginCard.tsx +2 -2
- package/src/settings-center/plugin-manager/index.tsx +3 -0
- package/src/settings-center/utils.tsx +0 -6
- package/src/utils/getRouteRuntimeVersion.ts +185 -0
- package/src/utils/index.tsx +1 -0
- package/src/utils/markdownSanitize.ts +88 -0
|
@@ -16,13 +16,9 @@ import {
|
|
|
16
16
|
FlowRuntimeContext,
|
|
17
17
|
useFlowContext,
|
|
18
18
|
useFlowEngine,
|
|
19
|
-
createSafeWindow,
|
|
20
|
-
createSafeDocument,
|
|
21
|
-
createSafeNavigator,
|
|
22
19
|
observer,
|
|
23
20
|
isRunJSValue,
|
|
24
21
|
normalizeRunJSValue,
|
|
25
|
-
runjsWithSafeGlobals,
|
|
26
22
|
} from '@nocobase/flow-engine';
|
|
27
23
|
import { evaluateConditions, FilterGroupType, removeInvalidFilterItems } from '@nocobase/utils/client';
|
|
28
24
|
import React from 'react';
|
|
@@ -40,7 +36,7 @@ import { FilterGroup } from '../components/filter/FilterGroup';
|
|
|
40
36
|
import { LinkageFilterItem } from '../components/filter';
|
|
41
37
|
import { CodeEditor } from '../components/code-editor';
|
|
42
38
|
import { FieldAssignRulesEditor } from '../components/FieldAssignRulesEditor';
|
|
43
|
-
import type { FieldAssignRuleItem } from '../components/FieldAssignRulesEditor';
|
|
39
|
+
import type { AssignMode, FieldAssignRuleItem } from '../components/FieldAssignRulesEditor';
|
|
44
40
|
import { collectFieldAssignCascaderOptions } from '../components/fieldAssignOptions';
|
|
45
41
|
import { useAssociationTitleFieldSync } from '../components/useAssociationTitleFieldSync';
|
|
46
42
|
import _ from 'lodash';
|
|
@@ -492,7 +488,7 @@ async function resolveLinkageAssignRuntimeValue(ctx: FlowContext, rawValue: any)
|
|
|
492
488
|
|
|
493
489
|
try {
|
|
494
490
|
const { code, version } = normalizeRunJSValue(rawValue);
|
|
495
|
-
const ret = await
|
|
491
|
+
const ret = await ctx.runjs(code, undefined, { version });
|
|
496
492
|
if (!ret?.success) {
|
|
497
493
|
return SKIP_RUNJS_ASSIGN_VALUE;
|
|
498
494
|
}
|
|
@@ -735,6 +731,41 @@ export const linkageSetMenuItemProps = defineAction({
|
|
|
735
731
|
},
|
|
736
732
|
});
|
|
737
733
|
|
|
734
|
+
export const linkageSetTabProps = defineAction({
|
|
735
|
+
name: 'linkageSetTabProps',
|
|
736
|
+
title: tExpr('Set tab state'),
|
|
737
|
+
scene: ActionScene.TAB_LINKAGE_RULES,
|
|
738
|
+
sort: 100,
|
|
739
|
+
uiSchema: {
|
|
740
|
+
value: {
|
|
741
|
+
type: 'string',
|
|
742
|
+
'x-component': (props) => {
|
|
743
|
+
const { value, onChange } = props;
|
|
744
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
745
|
+
const ctx = useFlowContext();
|
|
746
|
+
const t = ctx.model.translate.bind(ctx.model);
|
|
747
|
+
|
|
748
|
+
return (
|
|
749
|
+
<Select
|
|
750
|
+
value={value}
|
|
751
|
+
onChange={onChange}
|
|
752
|
+
placeholder={t('Please select state')}
|
|
753
|
+
style={{ width: '100%' }}
|
|
754
|
+
options={[
|
|
755
|
+
{ label: t('Visible'), value: 'visible' },
|
|
756
|
+
{ label: t('Hidden'), value: 'hidden' },
|
|
757
|
+
]}
|
|
758
|
+
allowClear
|
|
759
|
+
/>
|
|
760
|
+
);
|
|
761
|
+
},
|
|
762
|
+
},
|
|
763
|
+
},
|
|
764
|
+
handler(ctx, { value, setProps }) {
|
|
765
|
+
setProps(ctx.model, { hiddenModel: value === 'hidden' });
|
|
766
|
+
},
|
|
767
|
+
});
|
|
768
|
+
|
|
738
769
|
export const linkageSetFieldProps = defineAction({
|
|
739
770
|
name: 'linkageSetFieldProps',
|
|
740
771
|
title: tExpr('Set field state'),
|
|
@@ -888,6 +919,20 @@ type ArrayFieldComponentProps = {
|
|
|
888
919
|
|
|
889
920
|
const LEGACY_ASSIGN_RULE = { mode: 'assign', valueKey: 'assignValue' } as const;
|
|
890
921
|
const LEGACY_DEFAULT_RULE = { mode: 'default', valueKey: 'initialValue' } as const;
|
|
922
|
+
const LINKAGE_ASSIGN_MODE_PROP = '__linkageAssignMode';
|
|
923
|
+
|
|
924
|
+
function normalizeLinkageAssignMode(mode: unknown): AssignMode {
|
|
925
|
+
if (mode === 'default') return 'default';
|
|
926
|
+
if (mode === 'override') return 'override';
|
|
927
|
+
return 'assign';
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
type LinkageValuePatch = {
|
|
931
|
+
path: Array<string | number>;
|
|
932
|
+
value: unknown;
|
|
933
|
+
whenEmpty?: boolean;
|
|
934
|
+
mode?: AssignMode;
|
|
935
|
+
};
|
|
891
936
|
|
|
892
937
|
const FieldAssignRulesActionComponent: React.FC<
|
|
893
938
|
ArrayFieldComponentProps & {
|
|
@@ -1002,16 +1047,24 @@ export const linkageAssignField = defineAction({
|
|
|
1002
1047
|
continue;
|
|
1003
1048
|
}
|
|
1004
1049
|
|
|
1005
|
-
const mode = it?.mode
|
|
1050
|
+
const mode = normalizeLinkageAssignMode(it?.mode);
|
|
1006
1051
|
if (fieldModel) {
|
|
1007
1052
|
if (mode === 'default') {
|
|
1008
1053
|
setProps(fieldModel as FlowModel, { initialValue: finalValue });
|
|
1009
1054
|
} else {
|
|
1010
|
-
setProps(fieldModel as FlowModel, {
|
|
1055
|
+
setProps(fieldModel as FlowModel, {
|
|
1056
|
+
value: finalValue,
|
|
1057
|
+
...(mode === 'override' ? { [LINKAGE_ASSIGN_MODE_PROP]: mode } : {}),
|
|
1058
|
+
});
|
|
1011
1059
|
}
|
|
1012
1060
|
} else if (typeof addFormValuePatch === 'function') {
|
|
1013
1061
|
// 对关联字段子属性(如 user.name)等没有独立 FormItemModel 的目标,直接写入表单值
|
|
1014
|
-
addFormValuePatch({
|
|
1062
|
+
addFormValuePatch({
|
|
1063
|
+
path: targetPath,
|
|
1064
|
+
value: finalValue,
|
|
1065
|
+
whenEmpty: mode === 'default',
|
|
1066
|
+
...(mode === 'override' ? { mode } : {}),
|
|
1067
|
+
});
|
|
1015
1068
|
}
|
|
1016
1069
|
}
|
|
1017
1070
|
} catch (error) {
|
|
@@ -1177,7 +1230,7 @@ export const subFormLinkageAssignField = defineAction({
|
|
|
1177
1230
|
continue;
|
|
1178
1231
|
}
|
|
1179
1232
|
|
|
1180
|
-
const mode = it?.mode
|
|
1233
|
+
const mode = normalizeLinkageAssignMode(it?.mode);
|
|
1181
1234
|
const actionName = (ctx.model as any)?.getAclActionName?.() ?? (ctx.model as any)?.context?.actionName;
|
|
1182
1235
|
const isEditForm = actionName === 'update';
|
|
1183
1236
|
const isNewItem = (ctx as any)?.item?.__is_new__ === true;
|
|
@@ -1207,12 +1260,21 @@ export const subFormLinkageAssignField = defineAction({
|
|
|
1207
1260
|
continue;
|
|
1208
1261
|
}
|
|
1209
1262
|
|
|
1263
|
+
if (mode === 'override' && hasExplicitPathHit(targetPath)) {
|
|
1264
|
+
continue;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1210
1267
|
if (!fieldUid) {
|
|
1211
1268
|
if (mode === 'default' && hasExplicitPathHit(targetPath)) {
|
|
1212
1269
|
continue;
|
|
1213
1270
|
}
|
|
1214
1271
|
if (typeof addFormValuePatch === 'function') {
|
|
1215
|
-
addFormValuePatch({
|
|
1272
|
+
addFormValuePatch({
|
|
1273
|
+
path: targetPath,
|
|
1274
|
+
value: finalValue,
|
|
1275
|
+
whenEmpty: mode === 'default',
|
|
1276
|
+
...(mode === 'override' ? { mode } : {}),
|
|
1277
|
+
});
|
|
1216
1278
|
}
|
|
1217
1279
|
continue;
|
|
1218
1280
|
}
|
|
@@ -1223,7 +1285,10 @@ export const subFormLinkageAssignField = defineAction({
|
|
|
1223
1285
|
if (mode === 'default') {
|
|
1224
1286
|
setProps(model, { initialValue: finalValue });
|
|
1225
1287
|
} else {
|
|
1226
|
-
setProps(model, {
|
|
1288
|
+
setProps(model, {
|
|
1289
|
+
value: finalValue,
|
|
1290
|
+
...(mode === 'override' ? { [LINKAGE_ASSIGN_MODE_PROP]: mode } : {}),
|
|
1291
|
+
});
|
|
1227
1292
|
}
|
|
1228
1293
|
}
|
|
1229
1294
|
} catch (error) {
|
|
@@ -1309,6 +1374,7 @@ export const linkageRunjs = defineAction({
|
|
|
1309
1374
|
ActionScene.FIELD_LINKAGE_RULES,
|
|
1310
1375
|
ActionScene.ACTION_LINKAGE_RULES,
|
|
1311
1376
|
ActionScene.MENU_LINKAGE_RULES,
|
|
1377
|
+
ActionScene.TAB_LINKAGE_RULES,
|
|
1312
1378
|
ActionScene.DETAILS_FIELD_LINKAGE_RULES,
|
|
1313
1379
|
ActionScene.SUB_FORM_FIELD_LINKAGE_RULES,
|
|
1314
1380
|
],
|
|
@@ -1363,8 +1429,7 @@ export const linkageRunjs = defineAction({
|
|
|
1363
1429
|
}
|
|
1364
1430
|
|
|
1365
1431
|
try {
|
|
1366
|
-
|
|
1367
|
-
await ctx.runjs(script, { window: createSafeWindow({ navigator }), document: createSafeDocument(), navigator });
|
|
1432
|
+
await ctx.runjs(script);
|
|
1368
1433
|
} catch (error) {
|
|
1369
1434
|
console.error('Script execution error:', error);
|
|
1370
1435
|
// 可以选择显示错误信息给用户
|
|
@@ -1781,7 +1846,7 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
1781
1846
|
const modelsToApply = new Set<FlowModel>(allModels);
|
|
1782
1847
|
const patchPropsByModel = new Map<FlowModel, any>();
|
|
1783
1848
|
const clearValueOnHiddenModelUids = new Set<string>();
|
|
1784
|
-
const directValuePatches:
|
|
1849
|
+
const directValuePatches: LinkageValuePatch[] = [];
|
|
1785
1850
|
const rootCollection = getCollectionFromModel((ctx.model as any)?.context?.blockModel ?? ctx.model);
|
|
1786
1851
|
const isSafeToWriteAssociationSubpath = (namePath: any): boolean => {
|
|
1787
1852
|
if (!Array.isArray(namePath) || !namePath.length) return true;
|
|
@@ -1836,13 +1901,18 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
1836
1901
|
}
|
|
1837
1902
|
|
|
1838
1903
|
for (const patch of lastPatchByPathKey.values()) {
|
|
1839
|
-
if (!patch.whenEmpty) continue;
|
|
1904
|
+
if (!patch.whenEmpty && patch.mode !== 'default') continue;
|
|
1840
1905
|
runtime.recordDefaultValuePatch(patch.path, patch.value);
|
|
1841
1906
|
}
|
|
1842
1907
|
};
|
|
1843
|
-
const
|
|
1908
|
+
const getPatchMode = (patch: { mode?: unknown; whenEmpty?: boolean }): AssignMode => {
|
|
1909
|
+
if (patch?.mode === 'default') return 'default';
|
|
1910
|
+
if (patch?.mode === 'override') return 'override';
|
|
1911
|
+
return patch?.whenEmpty ? 'default' : 'assign';
|
|
1912
|
+
};
|
|
1913
|
+
const addFormValuePatch = (patch: { path: unknown; value: unknown; whenEmpty?: boolean; mode?: AssignMode }) => {
|
|
1844
1914
|
if (!patch) return;
|
|
1845
|
-
const path =
|
|
1915
|
+
const path = patch.path;
|
|
1846
1916
|
if (!path) return;
|
|
1847
1917
|
const resolvedPath = resolveNamePathForPatch(path);
|
|
1848
1918
|
if (!resolvedPath) {
|
|
@@ -1862,8 +1932,9 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
1862
1932
|
});
|
|
1863
1933
|
return;
|
|
1864
1934
|
}
|
|
1865
|
-
const
|
|
1866
|
-
const
|
|
1935
|
+
const mode = getPatchMode(patch);
|
|
1936
|
+
const whenEmpty = mode === 'default';
|
|
1937
|
+
const value = patch.value;
|
|
1867
1938
|
try {
|
|
1868
1939
|
const form = ctx.model?.context?.form;
|
|
1869
1940
|
const current = form?.getFieldValue?.(resolvedPath);
|
|
@@ -1878,6 +1949,15 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
1878
1949
|
return;
|
|
1879
1950
|
}
|
|
1880
1951
|
}
|
|
1952
|
+
if (mode === 'override') {
|
|
1953
|
+
const runtime = getDefaultPatchRuntime();
|
|
1954
|
+
if (
|
|
1955
|
+
typeof runtime?.canApplyOverrideValuePatch === 'function' &&
|
|
1956
|
+
!runtime.canApplyOverrideValuePatch(resolvedPath)
|
|
1957
|
+
) {
|
|
1958
|
+
return;
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1881
1961
|
if (_.isEqual(current, value)) {
|
|
1882
1962
|
return;
|
|
1883
1963
|
}
|
|
@@ -1889,6 +1969,7 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
1889
1969
|
path: resolvedPath,
|
|
1890
1970
|
value,
|
|
1891
1971
|
...(whenEmpty ? { whenEmpty: true } : {}),
|
|
1972
|
+
...(mode === 'override' ? { mode } : {}),
|
|
1892
1973
|
});
|
|
1893
1974
|
};
|
|
1894
1975
|
const removePendingFormValuePatches = (path: any) => {
|
|
@@ -1948,6 +2029,21 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
1948
2029
|
>;
|
|
1949
2030
|
return normalized.length ? normalized : null;
|
|
1950
2031
|
};
|
|
2032
|
+
const pathKeysEqual = (
|
|
2033
|
+
a: Array<string | number> | null | undefined,
|
|
2034
|
+
b: Array<string | number> | null | undefined,
|
|
2035
|
+
) => {
|
|
2036
|
+
if (!a || !b) return false;
|
|
2037
|
+
return namePathToPathKey(a) === namePathToPathKey(b);
|
|
2038
|
+
};
|
|
2039
|
+
const namePathEndsWith = (
|
|
2040
|
+
namePath: Array<string | number> | null | undefined,
|
|
2041
|
+
suffix: Array<string | number> | null | undefined,
|
|
2042
|
+
) => {
|
|
2043
|
+
if (!namePath || !suffix || suffix.length > namePath.length) return false;
|
|
2044
|
+
const offset = namePath.length - suffix.length;
|
|
2045
|
+
return suffix.every((seg, index) => namePath[offset + index] === seg);
|
|
2046
|
+
};
|
|
1951
2047
|
const getFieldIndexEntries = (fieldIndex: any): Array<{ name: string; index: number }> => {
|
|
1952
2048
|
if (!Array.isArray(fieldIndex)) return [];
|
|
1953
2049
|
return fieldIndex
|
|
@@ -1996,17 +2092,35 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
1996
2092
|
|
|
1997
2093
|
return out;
|
|
1998
2094
|
};
|
|
2095
|
+
const getTrustedFieldPathArray = (
|
|
2096
|
+
fieldPathArray: Array<string | number> | null,
|
|
2097
|
+
targetPath: string | null,
|
|
2098
|
+
fieldIndex: unknown,
|
|
2099
|
+
): Array<string | number> | null => {
|
|
2100
|
+
if (!fieldPathArray || !targetPath) return null;
|
|
2101
|
+
|
|
2102
|
+
const targetNamePath = normalizeNamePathForKey(
|
|
2103
|
+
parsePathString(targetPath).filter((seg) => typeof seg === 'string' || typeof seg === 'number'),
|
|
2104
|
+
);
|
|
2105
|
+
const resolvedTargetPath = normalizeNamePathForKey(resolveDynamicNamePath(targetPath, fieldIndex));
|
|
2106
|
+
const indexedRelativePath = resolveIndexedRelativePath(targetPath, fieldIndex);
|
|
2107
|
+
|
|
2108
|
+
if (
|
|
2109
|
+
pathKeysEqual(fieldPathArray, resolvedTargetPath) ||
|
|
2110
|
+
pathKeysEqual(fieldPathArray, indexedRelativePath) ||
|
|
2111
|
+
namePathEndsWith(fieldPathArray, targetNamePath)
|
|
2112
|
+
) {
|
|
2113
|
+
return fieldPathArray;
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
return null;
|
|
2117
|
+
};
|
|
1999
2118
|
const getModelTargetPathForHiddenClear = (model: any): string | Array<string | number> | null => {
|
|
2000
2119
|
const fieldPathArray = normalizeNamePathForKey(model?.context?.fieldPathArray);
|
|
2001
2120
|
const targetPath = getModelTargetPathForPatch(model);
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
: undefined;
|
|
2006
|
-
const fieldPathArrayLastString = [...fieldPathArray].reverse().find((seg) => typeof seg === 'string');
|
|
2007
|
-
if (!targetPathLastString || targetPathLastString === fieldPathArrayLastString) {
|
|
2008
|
-
return fieldPathArray;
|
|
2009
|
-
}
|
|
2121
|
+
const trustedFieldPathArray = getTrustedFieldPathArray(fieldPathArray, targetPath, model?.context?.fieldIndex);
|
|
2122
|
+
if (trustedFieldPathArray) {
|
|
2123
|
+
return trustedFieldPathArray;
|
|
2010
2124
|
}
|
|
2011
2125
|
|
|
2012
2126
|
if (!targetPath) return null;
|
|
@@ -2016,12 +2130,13 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
2016
2130
|
const getModelTargetPathKeys = (model: any): Set<string> => {
|
|
2017
2131
|
const keys = new Set<string>();
|
|
2018
2132
|
const fieldPathArray = normalizeNamePathForKey(model?.context?.fieldPathArray);
|
|
2019
|
-
|
|
2020
|
-
|
|
2133
|
+
const targetPath = getModelTargetPathForPatch(model);
|
|
2134
|
+
const trustedFieldPathArray = getTrustedFieldPathArray(fieldPathArray, targetPath, model?.context?.fieldIndex);
|
|
2135
|
+
if (trustedFieldPathArray) {
|
|
2136
|
+
keys.add(namePathToPathKey(trustedFieldPathArray));
|
|
2021
2137
|
return keys;
|
|
2022
2138
|
}
|
|
2023
2139
|
|
|
2024
|
-
const targetPath = getModelTargetPathForPatch(model);
|
|
2025
2140
|
if (targetPath) {
|
|
2026
2141
|
const fieldIndexEntries = getFieldIndexEntries(model?.context?.fieldIndex);
|
|
2027
2142
|
if (!fieldIndexEntries.length) {
|
|
@@ -2082,22 +2197,43 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
2082
2197
|
|
|
2083
2198
|
for (const action of actions) {
|
|
2084
2199
|
const setProps = (model: FlowModel & { __originalProps?: any; __shouldReset?: boolean }, props: any) => {
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2200
|
+
const normalizedProps =
|
|
2201
|
+
props && typeof props === 'object' && Object.prototype.hasOwnProperty.call(props, 'value')
|
|
2202
|
+
? {
|
|
2203
|
+
...props,
|
|
2204
|
+
[LINKAGE_ASSIGN_MODE_PROP]: normalizeLinkageAssignMode(props?.[LINKAGE_ASSIGN_MODE_PROP]),
|
|
2205
|
+
}
|
|
2206
|
+
: props;
|
|
2207
|
+
|
|
2208
|
+
// 只记录联动实际控制的属性,避免之后恢复状态时把标题、路由等无关的新配置回滚到旧快照。
|
|
2209
|
+
const originalProps = model.__originalProps || (model.__originalProps = {});
|
|
2210
|
+
const rememberOriginalProp = (key: string, value: unknown) => {
|
|
2211
|
+
if (!Object.prototype.hasOwnProperty.call(originalProps, key)) {
|
|
2212
|
+
originalProps[key] = value;
|
|
2213
|
+
}
|
|
2214
|
+
};
|
|
2215
|
+
Object.keys(normalizedProps || {}).forEach((key) => {
|
|
2216
|
+
if (key === 'hiddenModel') {
|
|
2217
|
+
rememberOriginalProp(
|
|
2218
|
+
key,
|
|
2219
|
+
Object.prototype.hasOwnProperty.call(model.props || {}, key) ? model.props?.[key] : model.hidden,
|
|
2220
|
+
);
|
|
2221
|
+
return;
|
|
2222
|
+
}
|
|
2223
|
+
|
|
2224
|
+
rememberOriginalProp(key, model.props?.[key]);
|
|
2225
|
+
if (key === 'hiddenText' && normalizedProps[key]) {
|
|
2226
|
+
rememberOriginalProp('title', model.props?.title);
|
|
2227
|
+
}
|
|
2228
|
+
if (key === 'required') {
|
|
2229
|
+
rememberOriginalProp('rules', model.props?.rules);
|
|
2230
|
+
}
|
|
2231
|
+
});
|
|
2096
2232
|
|
|
2097
2233
|
// 临时存起来,遍历完所有规则后,再统一处理
|
|
2098
2234
|
patchPropsByModel.set(model, {
|
|
2099
2235
|
...(patchPropsByModel.get(model) || {}),
|
|
2100
|
-
...
|
|
2236
|
+
...normalizedProps,
|
|
2101
2237
|
});
|
|
2102
2238
|
|
|
2103
2239
|
if (
|
|
@@ -2150,8 +2286,7 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
2150
2286
|
const newProps = { ...model.__originalProps, ...patchProps };
|
|
2151
2287
|
const prevHidden = !!model.hidden;
|
|
2152
2288
|
const nextHidden = !!newProps.hiddenModel;
|
|
2153
|
-
|
|
2154
|
-
model.setProps(_.omit(newProps, ['hiddenModel', 'value', 'hiddenText']));
|
|
2289
|
+
model.setProps(_.omit(newProps, ['hiddenModel', 'value', 'hiddenText', LINKAGE_ASSIGN_MODE_PROP]));
|
|
2155
2290
|
syncFieldOptionsToForks(model, patchProps);
|
|
2156
2291
|
if (typeof model.setHidden === 'function') {
|
|
2157
2292
|
model.setHidden(nextHidden);
|
|
@@ -2190,7 +2325,8 @@ const commonLinkageRulesHandler = async (ctx: FlowContext, params: any) => {
|
|
|
2190
2325
|
targetUid: model?.uid,
|
|
2191
2326
|
});
|
|
2192
2327
|
} else {
|
|
2193
|
-
|
|
2328
|
+
const mode = normalizeLinkageAssignMode(patchProps?.[LINKAGE_ASSIGN_MODE_PROP]);
|
|
2329
|
+
addFormValuePatch({ path: targetPath, value: newProps.value, ...(mode === 'override' ? { mode } : {}) });
|
|
2194
2330
|
}
|
|
2195
2331
|
}
|
|
2196
2332
|
|
|
@@ -2375,6 +2511,32 @@ export const menuLinkageRules = defineAction({
|
|
|
2375
2511
|
},
|
|
2376
2512
|
});
|
|
2377
2513
|
|
|
2514
|
+
export const tabLinkageRules = defineAction({
|
|
2515
|
+
name: 'tabLinkageRules',
|
|
2516
|
+
title: tExpr('Tab linkage rules'),
|
|
2517
|
+
uiMode: 'embed',
|
|
2518
|
+
uiSchema(ctx) {
|
|
2519
|
+
return {
|
|
2520
|
+
value: {
|
|
2521
|
+
type: 'array',
|
|
2522
|
+
'x-component': LinkageRulesUI,
|
|
2523
|
+
'x-component-props': {
|
|
2524
|
+
supportedActions: getSupportedActions(ctx, ActionScene.TAB_LINKAGE_RULES),
|
|
2525
|
+
title: tExpr('Tab linkage rules'),
|
|
2526
|
+
},
|
|
2527
|
+
},
|
|
2528
|
+
};
|
|
2529
|
+
},
|
|
2530
|
+
defaultParams: {
|
|
2531
|
+
value: [],
|
|
2532
|
+
},
|
|
2533
|
+
useRawParams: true,
|
|
2534
|
+
handler: async (ctx, params) => {
|
|
2535
|
+
const resolved = await resolveLinkageRulesParamsPreservingRunJsScripts(ctx, params);
|
|
2536
|
+
return commonLinkageRulesHandler(ctx, resolved);
|
|
2537
|
+
},
|
|
2538
|
+
});
|
|
2539
|
+
|
|
2378
2540
|
export const fieldLinkageRules = defineAction({
|
|
2379
2541
|
name: 'fieldLinkageRules',
|
|
2380
2542
|
title: tExpr('Field linkage rules'),
|
|
@@ -2842,7 +3004,7 @@ export const subFormFieldLinkageRules = defineAction({
|
|
|
2842
3004
|
}
|
|
2843
3005
|
} else {
|
|
2844
3006
|
await Promise.all(
|
|
2845
|
-
(grid.forks || []).map(async (forkModel: FlowModel) => {
|
|
3007
|
+
Array.from(grid.forks || []).map(async (forkModel: FlowModel) => {
|
|
2846
3008
|
if (forkModel.hidden) {
|
|
2847
3009
|
return;
|
|
2848
3010
|
}
|
|
@@ -15,17 +15,29 @@ import {
|
|
|
15
15
|
isRunJSValue,
|
|
16
16
|
} from '@nocobase/flow-engine';
|
|
17
17
|
import _ from 'lodash';
|
|
18
|
-
import { namePathToPathKey
|
|
18
|
+
import { namePathToPathKey } from '../models/blocks/form/value-runtime/path';
|
|
19
19
|
import {
|
|
20
20
|
collectStaticDepsFromRunJSValue,
|
|
21
21
|
collectStaticDepsFromTemplateValue,
|
|
22
22
|
recordDep,
|
|
23
23
|
type DepCollector,
|
|
24
24
|
} from '../models/blocks/form/value-runtime/deps';
|
|
25
|
+
import {
|
|
26
|
+
buildItemListRootPath,
|
|
27
|
+
buildItemRowPath,
|
|
28
|
+
dedupeNamePaths,
|
|
29
|
+
findFormValueChangeSource,
|
|
30
|
+
getChangedPathsFromPayload,
|
|
31
|
+
getFieldIndexEntriesFromContext,
|
|
32
|
+
isNamePathPrefix,
|
|
33
|
+
isSameNamePath,
|
|
34
|
+
minimizeNamePaths,
|
|
35
|
+
parseDependencyPath,
|
|
36
|
+
parsePathKey,
|
|
37
|
+
type NamePath,
|
|
38
|
+
} from '../utils/formValueDeps';
|
|
25
39
|
import { linkageRulesRefresh } from './linkageRulesRefresh';
|
|
26
40
|
|
|
27
|
-
type NamePath = Array<string | number>;
|
|
28
|
-
|
|
29
41
|
type LinkageRefreshDeps = {
|
|
30
42
|
wildcard: boolean;
|
|
31
43
|
valuePaths: NamePath[];
|
|
@@ -40,75 +52,11 @@ type LinkageRefreshBinding = {
|
|
|
40
52
|
dispose: () => void;
|
|
41
53
|
};
|
|
42
54
|
|
|
43
|
-
type FieldIndexEntry = {
|
|
44
|
-
name: string;
|
|
45
|
-
index: number;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
55
|
const FORM_VALUES_CHANGE_EVENT = 'formValuesChange';
|
|
49
56
|
const LINKAGE_REFRESH_BINDINGS_KEY = '__formValueDrivenLinkageRefreshBindings';
|
|
50
57
|
|
|
51
|
-
function isSameNamePath(a: NamePath, b: NamePath) {
|
|
52
|
-
return a.length === b.length && a.every((seg, index) => seg === b[index]);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function isNamePathPrefix(prefix: NamePath, path: NamePath) {
|
|
56
|
-
if (prefix.length > path.length) return false;
|
|
57
|
-
return prefix.every((seg, index) => seg === path[index]);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function dedupeNamePaths(paths: NamePath[]) {
|
|
61
|
-
const byKey = new Map<string, NamePath>();
|
|
62
|
-
for (const path of paths) {
|
|
63
|
-
if (!path?.length) continue;
|
|
64
|
-
byKey.set(namePathToPathKey(path), path);
|
|
65
|
-
}
|
|
66
|
-
return Array.from(byKey.values());
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function minimizeValueNamePaths(paths: NamePath[]) {
|
|
70
|
-
const deduped = dedupeNamePaths(paths);
|
|
71
|
-
return deduped.filter((path, index) => {
|
|
72
|
-
return !deduped.some((other, otherIndex) => otherIndex !== index && isNamePathPrefix(path, other));
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function parseFieldIndexEntries(fieldIndex: unknown): FieldIndexEntry[] {
|
|
77
|
-
const arr = Array.isArray(fieldIndex) ? fieldIndex : [];
|
|
78
|
-
const entries: FieldIndexEntry[] = [];
|
|
79
|
-
for (const it of arr) {
|
|
80
|
-
if (typeof it !== 'string') continue;
|
|
81
|
-
const [name, indexStr] = it.split(':');
|
|
82
|
-
const index = Number(indexStr);
|
|
83
|
-
if (!name || Number.isNaN(index)) continue;
|
|
84
|
-
entries.push({ name, index });
|
|
85
|
-
}
|
|
86
|
-
return entries;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function getFieldIndexEntriesFromContext(ctx: any): FieldIndexEntry[] {
|
|
90
|
-
return parseFieldIndexEntries(ctx?.model?.context?.fieldIndex ?? ctx?.fieldIndex);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function buildItemRowPath(entries: FieldIndexEntry[], parentDepth: number): NamePath | null {
|
|
94
|
-
const targetIndex = entries.length - 1 - parentDepth;
|
|
95
|
-
if (targetIndex < 0) return null;
|
|
96
|
-
|
|
97
|
-
const out: NamePath = [];
|
|
98
|
-
for (let i = 0; i <= targetIndex; i++) {
|
|
99
|
-
out.push(entries[i].name, entries[i].index);
|
|
100
|
-
}
|
|
101
|
-
return out;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function buildItemListRootPath(entries: FieldIndexEntry[], parentDepth: number): NamePath | null {
|
|
105
|
-
const rowPath = buildItemRowPath(entries, parentDepth);
|
|
106
|
-
if (!rowPath?.length) return null;
|
|
107
|
-
return rowPath.slice(0, -1);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
58
|
function resolveItemDependencyPath(ctx: FlowContext, depPath: NamePath): LinkageRefreshDeps {
|
|
111
|
-
const entries = getFieldIndexEntriesFromContext(ctx
|
|
59
|
+
const entries = getFieldIndexEntriesFromContext(ctx);
|
|
112
60
|
if (!entries.length) {
|
|
113
61
|
return { wildcard: true, valuePaths: [], structuralPaths: [] };
|
|
114
62
|
}
|
|
@@ -171,8 +119,7 @@ function addRunjsUsageToCollector(script: string, collector: DepCollector) {
|
|
|
171
119
|
collector.wildcard = true;
|
|
172
120
|
continue;
|
|
173
121
|
}
|
|
174
|
-
|
|
175
|
-
recordDep(segs, collector);
|
|
122
|
+
recordDep(parseDependencyPath(String(subPath)), collector);
|
|
176
123
|
continue;
|
|
177
124
|
}
|
|
178
125
|
if (varName === 'item') {
|
|
@@ -233,13 +180,13 @@ function collectLinkageRefreshDeps(ctx: FlowContext, params: any): LinkageRefres
|
|
|
233
180
|
wildcard = true;
|
|
234
181
|
continue;
|
|
235
182
|
}
|
|
236
|
-
valuePaths.push(
|
|
183
|
+
valuePaths.push(parsePathKey(inner));
|
|
237
184
|
continue;
|
|
238
185
|
}
|
|
239
186
|
|
|
240
187
|
if (depKey === 'ctx:item' || depKey.startsWith('ctx:item:')) {
|
|
241
188
|
const subPath = depKey === 'ctx:item' ? '' : depKey.slice('ctx:item:'.length);
|
|
242
|
-
const depPath = subPath ? (
|
|
189
|
+
const depPath = subPath ? parseDependencyPath(subPath) : [];
|
|
243
190
|
const resolved = resolveItemDependencyPath(ctx, depPath);
|
|
244
191
|
wildcard ||= resolved.wildcard;
|
|
245
192
|
valuePaths.push(...resolved.valuePaths);
|
|
@@ -249,7 +196,7 @@ function collectLinkageRefreshDeps(ctx: FlowContext, params: any): LinkageRefres
|
|
|
249
196
|
|
|
250
197
|
return {
|
|
251
198
|
wildcard,
|
|
252
|
-
valuePaths:
|
|
199
|
+
valuePaths: minimizeNamePaths(valuePaths),
|
|
253
200
|
structuralPaths: dedupeNamePaths(structuralPaths),
|
|
254
201
|
};
|
|
255
202
|
}
|
|
@@ -258,44 +205,9 @@ function hasLinkageRefreshDeps(deps: LinkageRefreshDeps) {
|
|
|
258
205
|
return deps.wildcard || deps.valuePaths.length > 0 || deps.structuralPaths.length > 0;
|
|
259
206
|
}
|
|
260
207
|
|
|
261
|
-
function getChangedPathsFromPayload(payload: any): NamePath[] {
|
|
262
|
-
const rawChangedPaths = Array.isArray(payload?.changedPaths) ? payload.changedPaths : [];
|
|
263
|
-
const out: NamePath[] = [];
|
|
264
|
-
|
|
265
|
-
for (const path of rawChangedPaths) {
|
|
266
|
-
if (Array.isArray(path)) {
|
|
267
|
-
if (path.length === 1 && typeof path[0] === 'string') {
|
|
268
|
-
const namePath = pathKeyToNamePath(path[0]);
|
|
269
|
-
if (namePath.length) out.push(namePath);
|
|
270
|
-
continue;
|
|
271
|
-
}
|
|
272
|
-
const segs = path.filter((seg) => typeof seg === 'string' || typeof seg === 'number') as NamePath;
|
|
273
|
-
if (segs.length) out.push(segs);
|
|
274
|
-
continue;
|
|
275
|
-
}
|
|
276
|
-
if (typeof path === 'string' && path) {
|
|
277
|
-
out.push(pathKeyToNamePath(path));
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
if (out.length) {
|
|
282
|
-
return out;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
const changedValues = payload?.changedValues;
|
|
286
|
-
if (changedValues && typeof changedValues === 'object') {
|
|
287
|
-
for (const key of Object.keys(changedValues)) {
|
|
288
|
-
const namePath = pathKeyToNamePath(key);
|
|
289
|
-
if (namePath.length) out.push(namePath);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
return out;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
208
|
function linkageRefreshDepsMatchPayload(deps: LinkageRefreshDeps, payload: any) {
|
|
297
209
|
if (!hasLinkageRefreshDeps(deps)) return false;
|
|
298
|
-
const changedPaths = getChangedPathsFromPayload(payload);
|
|
210
|
+
const changedPaths = getChangedPathsFromPayload(payload, { includeArrayChangedValues: true });
|
|
299
211
|
if (deps.wildcard) return true;
|
|
300
212
|
if (!changedPaths.length) return true;
|
|
301
213
|
|
|
@@ -330,28 +242,8 @@ function getLinkageRefreshBindings(model: any): Map<string, LinkageRefreshBindin
|
|
|
330
242
|
return (model[LINKAGE_REFRESH_BINDINGS_KEY] ||= new Map<string, LinkageRefreshBinding>());
|
|
331
243
|
}
|
|
332
244
|
|
|
333
|
-
function isFormBlockForLinkageRefresh(model: any) {
|
|
334
|
-
if (!model || typeof model !== 'object') return false;
|
|
335
|
-
if (!model.emitter || typeof model.emitter.on !== 'function' || typeof model.emitter.off !== 'function') return false;
|
|
336
|
-
return !!model.formValueRuntime || !!model.context?.form || typeof model.context?.setFormValues === 'function';
|
|
337
|
-
}
|
|
338
|
-
|
|
339
245
|
function findFormBlockForLinkageRefresh(ctx: FlowContext): any | null {
|
|
340
|
-
|
|
341
|
-
const push = (model: any) => {
|
|
342
|
-
if (model && !candidates.includes(model)) candidates.push(model);
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
push((ctx.model as any)?.context?.blockModel);
|
|
346
|
-
push(ctx.model);
|
|
347
|
-
|
|
348
|
-
let cursor: any = (ctx.model as any)?.parent;
|
|
349
|
-
while (cursor) {
|
|
350
|
-
push(cursor);
|
|
351
|
-
cursor = cursor?.parent;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
return candidates.find(isFormBlockForLinkageRefresh) || null;
|
|
246
|
+
return findFormValueChangeSource(ctx) as any;
|
|
355
247
|
}
|
|
356
248
|
|
|
357
249
|
function disposeLinkageRefreshBinding(model: any, key: string) {
|
|
@@ -35,12 +35,8 @@ export const linkageRulesRefresh = defineAction({
|
|
|
35
35
|
// Prefer running on the current model; fallback to blockModel when the current model doesn't own the flow.
|
|
36
36
|
if (!hasFlow) return;
|
|
37
37
|
|
|
38
|
-
//
|
|
38
|
+
// Skip master when unmounted forks can handle the same flow.
|
|
39
39
|
// Otherwise master is likely the rendered model and still needs refresh.
|
|
40
|
-
// In design mode, always refresh master so the currently edited model state stays in sync.
|
|
41
|
-
const flowSettingsEnabled = Boolean(
|
|
42
|
-
(ctx as any)?.flowSettingsEnabled || (model as any)?.context?.flowSettingsEnabled,
|
|
43
|
-
);
|
|
44
40
|
const hasForkWithFlow =
|
|
45
41
|
!model?.isFork &&
|
|
46
42
|
!!model?.forks?.size &&
|
|
@@ -49,7 +45,7 @@ export const linkageRulesRefresh = defineAction({
|
|
|
49
45
|
return !!fork?.getFlow?.(flowKey);
|
|
50
46
|
});
|
|
51
47
|
const isMasterMounted = Boolean((model as any)?.context?.ref?.current);
|
|
52
|
-
if (hasForkWithFlow && !isMasterMounted
|
|
48
|
+
if (hasForkWithFlow && !isMasterMounted) {
|
|
53
49
|
return;
|
|
54
50
|
}
|
|
55
51
|
|