weaver-e10-builder 1.2.3 → 1.5.1
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/assets/org-employee-template.xlsx +0 -0
- package/dist/commands/actionflow.d.ts.map +1 -1
- package/dist/commands/actionflow.js +12 -25
- package/dist/commands/actionflow.js.map +1 -1
- package/dist/commands/designer-css.d.ts +15 -0
- package/dist/commands/designer-css.d.ts.map +1 -0
- package/dist/commands/designer-css.js +205 -0
- package/dist/commands/designer-css.js.map +1 -0
- package/dist/commands/form-button.d.ts.map +1 -1
- package/dist/commands/form-button.js +28 -5
- package/dist/commands/form-button.js.map +1 -1
- package/dist/commands/form-field-lang.d.ts.map +1 -1
- package/dist/commands/form-field-lang.js +4 -39
- package/dist/commands/form-field-lang.js.map +1 -1
- package/dist/commands/form-field-linkage.d.ts.map +1 -1
- package/dist/commands/form-field-linkage.js +27 -6
- package/dist/commands/form-field-linkage.js.map +1 -1
- package/dist/commands/form-formula-linkage.d.ts +3 -0
- package/dist/commands/form-formula-linkage.d.ts.map +1 -0
- package/dist/commands/form-formula-linkage.js +434 -0
- package/dist/commands/form-formula-linkage.js.map +1 -0
- package/dist/commands/form-formula.d.ts.map +1 -1
- package/dist/commands/form-formula.js +22 -3
- package/dist/commands/form-formula.js.map +1 -1
- package/dist/commands/form-layout-init.d.ts.map +1 -1
- package/dist/commands/form-layout-init.js +15 -10
- package/dist/commands/form-layout-init.js.map +1 -1
- package/dist/commands/form-layout.js +24 -21
- package/dist/commands/form-layout.js.map +1 -1
- package/dist/commands/form-list-click.d.ts.map +1 -1
- package/dist/commands/form-list-click.js +2 -1
- package/dist/commands/form-list-click.js.map +1 -1
- package/dist/commands/form-native.d.ts.map +1 -1
- package/dist/commands/form-native.js +192 -3
- package/dist/commands/form-native.js.map +1 -1
- package/dist/commands/form-validate.d.ts.map +1 -1
- package/dist/commands/form-validate.js +11 -3
- package/dist/commands/form-validate.js.map +1 -1
- package/dist/commands/form.d.ts.map +1 -1
- package/dist/commands/form.js +323 -192
- package/dist/commands/form.js.map +1 -1
- package/dist/commands/matrix.d.ts.map +1 -1
- package/dist/commands/matrix.js +175 -36
- package/dist/commands/matrix.js.map +1 -1
- package/dist/commands/menu.d.ts.map +1 -1
- package/dist/commands/menu.js +170 -23
- package/dist/commands/menu.js.map +1 -1
- package/dist/commands/org.d.ts +10 -0
- package/dist/commands/org.d.ts.map +1 -0
- package/dist/commands/org.js +278 -0
- package/dist/commands/org.js.map +1 -0
- package/dist/commands/role.d.ts.map +1 -1
- package/dist/commands/role.js +106 -62
- package/dist/commands/role.js.map +1 -1
- package/dist/commands/wf-form.d.ts +1 -0
- package/dist/commands/wf-form.d.ts.map +1 -1
- package/dist/commands/wf-form.js +545 -39
- package/dist/commands/wf-form.js.map +1 -1
- package/dist/commands/workflow-auth-resp.d.ts.map +1 -1
- package/dist/commands/workflow-auth-resp.js +53 -5
- package/dist/commands/workflow-auth-resp.js.map +1 -1
- package/dist/commands/workflow-create-auth-resp.d.ts.map +1 -1
- package/dist/commands/workflow-create-auth-resp.js +5 -1
- package/dist/commands/workflow-create-auth-resp.js.map +1 -1
- package/dist/commands/workflow-node-assign-flow.d.ts.map +1 -1
- package/dist/commands/workflow-node-assign-flow.js +1 -2
- package/dist/commands/workflow-node-assign-flow.js.map +1 -1
- package/dist/commands/workflow-node.d.ts.map +1 -1
- package/dist/commands/workflow-node.js +147 -2
- package/dist/commands/workflow-node.js.map +1 -1
- package/dist/commands/workflow-odoc.d.ts.map +1 -1
- package/dist/commands/workflow-odoc.js +56 -56
- package/dist/commands/workflow-odoc.js.map +1 -1
- package/dist/commands/workflow-setting.d.ts.map +1 -1
- package/dist/commands/workflow-setting.js +77 -1
- package/dist/commands/workflow-setting.js.map +1 -1
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +114 -89
- package/dist/commands/workflow.js.map +1 -1
- package/dist/core/client.d.ts +14 -0
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +28 -12
- package/dist/core/client.js.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/services/action-detail.d.ts.map +1 -1
- package/dist/services/action-detail.js +5 -4
- package/dist/services/action-detail.js.map +1 -1
- package/dist/services/actionflow/command_output.d.ts +7 -0
- package/dist/services/actionflow/command_output.d.ts.map +1 -1
- package/dist/services/actionflow/command_output.js +46 -0
- package/dist/services/actionflow/command_output.js.map +1 -1
- package/dist/services/actionflow/components/action_eb_add.d.ts.map +1 -1
- package/dist/services/actionflow/components/action_eb_add.js +14 -4
- package/dist/services/actionflow/components/action_eb_add.js.map +1 -1
- package/dist/services/actionflow/components/action_eb_add_compiler.d.ts.map +1 -1
- package/dist/services/actionflow/components/action_eb_add_compiler.js +29 -0
- package/dist/services/actionflow/components/action_eb_add_compiler.js.map +1 -1
- package/dist/services/actionflow/components/action_eb_update.d.ts.map +1 -1
- package/dist/services/actionflow/components/action_eb_update.js +23 -8
- package/dist/services/actionflow/components/action_eb_update.js.map +1 -1
- package/dist/services/actionflow/components/action_eb_update_compiler.d.ts.map +1 -1
- package/dist/services/actionflow/components/action_eb_update_compiler.js +261 -13
- package/dist/services/actionflow/components/action_eb_update_compiler.js.map +1 -1
- package/dist/services/actionflow/components/approve_create.d.ts.map +1 -1
- package/dist/services/actionflow/components/approve_create.js +6 -3
- package/dist/services/actionflow/components/approve_create.js.map +1 -1
- package/dist/services/actionflow/components/custom_set_form.d.ts +10 -0
- package/dist/services/actionflow/components/custom_set_form.d.ts.map +1 -0
- package/dist/services/actionflow/components/custom_set_form.js +99 -0
- package/dist/services/actionflow/components/custom_set_form.js.map +1 -0
- package/dist/services/actionflow/components/custom_trigger.d.ts +2 -2
- package/dist/services/actionflow/components/custom_trigger.d.ts.map +1 -1
- package/dist/services/actionflow/components/custom_trigger.js +11 -11
- package/dist/services/actionflow/components/custom_trigger.js.map +1 -1
- package/dist/services/actionflow/components/dml_execute.d.ts.map +1 -1
- package/dist/services/actionflow/components/dml_execute.js +7 -3
- package/dist/services/actionflow/components/dml_execute.js.map +1 -1
- package/dist/services/actionflow/components/document_actions.d.ts.map +1 -1
- package/dist/services/actionflow/components/document_actions.js +7 -3
- package/dist/services/actionflow/components/document_actions.js.map +1 -1
- package/dist/services/actionflow/components/enquiry_form.js +1 -1
- package/dist/services/actionflow/components/enquiry_form.js.map +1 -1
- package/dist/services/actionflow/components/hrm_actions.d.ts.map +1 -1
- package/dist/services/actionflow/components/hrm_actions.js +7 -3
- package/dist/services/actionflow/components/hrm_actions.js.map +1 -1
- package/dist/services/actionflow/components/multiple_execution.d.ts.map +1 -1
- package/dist/services/actionflow/components/multiple_execution.js +14 -5
- package/dist/services/actionflow/components/multiple_execution.js.map +1 -1
- package/dist/services/actionflow/components/output.d.ts.map +1 -1
- package/dist/services/actionflow/components/output.js +6 -1
- package/dist/services/actionflow/components/output.js.map +1 -1
- package/dist/services/actionflow/components/send_message.js +2 -2
- package/dist/services/actionflow/components/send_message.js.map +1 -1
- package/dist/services/actionflow/components/workflow_actions.d.ts.map +1 -1
- package/dist/services/actionflow/components/workflow_actions.js +7 -3
- package/dist/services/actionflow/components/workflow_actions.js.map +1 -1
- package/dist/services/actionflow/context_preflight.d.ts.map +1 -1
- package/dist/services/actionflow/context_preflight.js +25 -8
- package/dist/services/actionflow/context_preflight.js.map +1 -1
- package/dist/services/actionflow/context_provider.d.ts.map +1 -1
- package/dist/services/actionflow/context_provider.js +24 -4
- package/dist/services/actionflow/context_provider.js.map +1 -1
- package/dist/services/actionflow/custom_trigger_context.d.ts +10 -0
- package/dist/services/actionflow/custom_trigger_context.d.ts.map +1 -0
- package/dist/services/actionflow/custom_trigger_context.js +46 -0
- package/dist/services/actionflow/custom_trigger_context.js.map +1 -0
- package/dist/services/actionflow/dynamic_resources.d.ts.map +1 -1
- package/dist/services/actionflow/dynamic_resources.js +1 -1
- package/dist/services/actionflow/dynamic_resources.js.map +1 -1
- package/dist/services/actionflow/ebuilder_source.d.ts +19 -0
- package/dist/services/actionflow/ebuilder_source.d.ts.map +1 -0
- package/dist/services/actionflow/ebuilder_source.js +78 -0
- package/dist/services/actionflow/ebuilder_source.js.map +1 -0
- package/dist/services/actionflow/filter_rules.js +2 -2
- package/dist/services/actionflow/filter_rules.js.map +1 -1
- package/dist/services/actionflow/form_source.d.ts +51 -10
- package/dist/services/actionflow/form_source.d.ts.map +1 -1
- package/dist/services/actionflow/form_source.js +173 -29
- package/dist/services/actionflow/form_source.js.map +1 -1
- package/dist/services/actionflow/formula_service.d.ts +13 -2
- package/dist/services/actionflow/formula_service.d.ts.map +1 -1
- package/dist/services/actionflow/formula_service.js +104 -42
- package/dist/services/actionflow/formula_service.js.map +1 -1
- package/dist/services/actionflow/id_generator.d.ts +2 -0
- package/dist/services/actionflow/id_generator.d.ts.map +1 -1
- package/dist/services/actionflow/id_generator.js +13 -0
- package/dist/services/actionflow/id_generator.js.map +1 -1
- package/dist/services/actionflow/preflight_service.d.ts +6 -0
- package/dist/services/actionflow/preflight_service.d.ts.map +1 -1
- package/dist/services/actionflow/preflight_service.js +217 -4
- package/dist/services/actionflow/preflight_service.js.map +1 -1
- package/dist/services/actionflow/workflow_compiler.d.ts.map +1 -1
- package/dist/services/actionflow/workflow_compiler.js +172 -50
- package/dist/services/actionflow/workflow_compiler.js.map +1 -1
- package/dist/services/auth-resp-condition.d.ts +35 -0
- package/dist/services/auth-resp-condition.d.ts.map +1 -0
- package/dist/services/auth-resp-condition.js +111 -0
- package/dist/services/auth-resp-condition.js.map +1 -0
- package/dist/services/condition-rules.d.ts.map +1 -1
- package/dist/services/condition-rules.js +4 -1
- package/dist/services/condition-rules.js.map +1 -1
- package/dist/services/designer-css.d.ts +89 -0
- package/dist/services/designer-css.d.ts.map +1 -0
- package/dist/services/designer-css.js +163 -0
- package/dist/services/designer-css.js.map +1 -0
- package/dist/services/dom-structure.d.ts +42 -0
- package/dist/services/dom-structure.d.ts.map +1 -0
- package/dist/services/dom-structure.js +251 -0
- package/dist/services/dom-structure.js.map +1 -0
- package/dist/services/esb-interface/document-parser.d.ts.map +1 -1
- package/dist/services/esb-interface/document-parser.js +62 -5
- package/dist/services/esb-interface/document-parser.js.map +1 -1
- package/dist/services/form-association.d.ts +19 -0
- package/dist/services/form-association.d.ts.map +1 -1
- package/dist/services/form-association.js +64 -0
- package/dist/services/form-association.js.map +1 -1
- package/dist/services/form-button-action.d.ts +7 -0
- package/dist/services/form-button-action.d.ts.map +1 -1
- package/dist/services/form-button-action.js +11 -1
- package/dist/services/form-button-action.js.map +1 -1
- package/dist/services/form-create.d.ts +4 -0
- package/dist/services/form-create.d.ts.map +1 -1
- package/dist/services/form-create.js +18 -12
- package/dist/services/form-create.js.map +1 -1
- package/dist/services/form-field-patch.d.ts +25 -1
- package/dist/services/form-field-patch.d.ts.map +1 -1
- package/dist/services/form-field-patch.js +52 -9
- package/dist/services/form-field-patch.js.map +1 -1
- package/dist/services/form-formula-linkage.d.ts +349 -0
- package/dist/services/form-formula-linkage.d.ts.map +1 -0
- package/dist/services/form-formula-linkage.js +546 -0
- package/dist/services/form-formula-linkage.js.map +1 -0
- package/dist/services/form-i18n-label.d.ts +48 -0
- package/dist/services/form-i18n-label.d.ts.map +1 -0
- package/dist/services/form-i18n-label.js +91 -0
- package/dist/services/form-i18n-label.js.map +1 -0
- package/dist/services/form-layout-insert.d.ts +84 -0
- package/dist/services/form-layout-insert.d.ts.map +1 -0
- package/dist/services/form-layout-insert.js +244 -0
- package/dist/services/form-layout-insert.js.map +1 -0
- package/dist/services/form-linkage-condition.d.ts +159 -0
- package/dist/services/form-linkage-condition.d.ts.map +1 -0
- package/dist/services/form-linkage-condition.js +307 -0
- package/dist/services/form-linkage-condition.js.map +1 -0
- package/dist/services/form-style-template.d.ts +6 -2
- package/dist/services/form-style-template.d.ts.map +1 -1
- package/dist/services/form-style-template.js +8 -4
- package/dist/services/form-style-template.js.map +1 -1
- package/dist/services/formula-detail.d.ts +98 -6
- package/dist/services/formula-detail.d.ts.map +1 -1
- package/dist/services/formula-detail.js +208 -26
- package/dist/services/formula-detail.js.map +1 -1
- package/dist/services/matrix-rows.d.ts +43 -0
- package/dist/services/matrix-rows.d.ts.map +1 -0
- package/dist/services/matrix-rows.js +104 -0
- package/dist/services/matrix-rows.js.map +1 -0
- package/dist/services/menu-catalog.d.ts +84 -0
- package/dist/services/menu-catalog.d.ts.map +1 -0
- package/dist/services/menu-catalog.js +183 -0
- package/dist/services/menu-catalog.js.map +1 -0
- package/dist/services/org-department.d.ts +114 -0
- package/dist/services/org-department.d.ts.map +1 -0
- package/dist/services/org-department.js +209 -0
- package/dist/services/org-department.js.map +1 -0
- package/dist/services/org-employee.d.ts +87 -0
- package/dist/services/org-employee.d.ts.map +1 -0
- package/dist/services/org-employee.js +219 -0
- package/dist/services/org-employee.js.map +1 -0
- package/dist/services/role-member.d.ts +99 -0
- package/dist/services/role-member.d.ts.map +1 -0
- package/dist/services/role-member.js +206 -0
- package/dist/services/role-member.js.map +1 -0
- package/dist/services/workflow-add-step.d.ts +45 -0
- package/dist/services/workflow-add-step.d.ts.map +1 -0
- package/dist/services/workflow-add-step.js +122 -0
- package/dist/services/workflow-add-step.js.map +1 -0
- package/dist/services/workflow-assign-flow.d.ts +1 -6
- package/dist/services/workflow-assign-flow.d.ts.map +1 -1
- package/dist/services/workflow-assign-flow.js +3 -8
- package/dist/services/workflow-assign-flow.js.map +1 -1
- package/dist/services/workflow-drawback.d.ts +19 -0
- package/dist/services/workflow-drawback.d.ts.map +1 -0
- package/dist/services/workflow-drawback.js +59 -0
- package/dist/services/workflow-drawback.js.map +1 -0
- package/dist/services/workflow-info.d.ts +83 -0
- package/dist/services/workflow-info.d.ts.map +1 -0
- package/dist/services/workflow-info.js +97 -0
- package/dist/services/workflow-info.js.map +1 -0
- package/dist/services/workflow-links.d.ts +51 -0
- package/dist/services/workflow-links.d.ts.map +1 -0
- package/dist/services/workflow-links.js +162 -0
- package/dist/services/workflow-links.js.map +1 -0
- package/dist/services/workflow-node-layout.d.ts +45 -4
- package/dist/services/workflow-node-layout.d.ts.map +1 -1
- package/dist/services/workflow-node-layout.js +142 -41
- package/dist/services/workflow-node-layout.js.map +1 -1
- package/dist/services/workflow-odoc-setting.d.ts +43 -0
- package/dist/services/workflow-odoc-setting.d.ts.map +1 -0
- package/dist/services/workflow-odoc-setting.js +109 -0
- package/dist/services/workflow-odoc-setting.js.map +1 -0
- package/dist/services/workflow-tab-config.d.ts +54 -0
- package/dist/services/workflow-tab-config.d.ts.map +1 -0
- package/dist/services/workflow-tab-config.js +137 -0
- package/dist/services/workflow-tab-config.js.map +1 -0
- package/dist/types.d.ts +5 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/column-name.d.ts +24 -0
- package/dist/utils/column-name.d.ts.map +1 -1
- package/dist/utils/column-name.js +16 -0
- package/dist/utils/column-name.js.map +1 -1
- package/ecodecmd/package.json +1 -2
- package/ecodecmd/src/loaddep.js +19 -9
- package/package.json +48 -48
- package/skill-docs/SKILL.md +15 -11
- package/skill-docs/_catalog.md +85 -79
- package/skill-docs/actionflows/SKILL.md +173 -168
- package/skill-docs/actionflows/references/components/ebuilder/ActionEbAdd.md +38 -1
- package/skill-docs/actionflows/references/components/ebuilder/ActionEbUpdate.md +42 -0
- package/skill-docs/actionflows/references/components/ebuilder/EventButton.md +1 -1
- package/skill-docs/actionflows/references/components/logic/Output.md +2 -0
- package/skill-docs/actionflows/references/components/trigger/CustomTrigger.md +48 -11
- package/skill-docs/actionflows/references/components/workflow/ApproveCreate.md +1 -1
- package/skill-docs/assets/dom-structure/Bar.json +341 -0
- package/skill-docs/assets/dom-structure/BarStack.json +341 -0
- package/skill-docs/assets/dom-structure/Bubble.json +323 -0
- package/skill-docs/assets/dom-structure/Calendar.json +515 -0
- package/skill-docs/assets/dom-structure/Circular.json +337 -0
- package/skill-docs/assets/dom-structure/CollapsePanel.json +289 -0
- package/skill-docs/assets/dom-structure/Comment.json +617 -0
- package/skill-docs/assets/dom-structure/CountDown.json +755 -0
- package/skill-docs/assets/dom-structure/DigitalPanel.json +191 -0
- package/skill-docs/assets/dom-structure/EbButton.json +387 -0
- package/skill-docs/assets/dom-structure/FastCreate.json +242 -0
- package/skill-docs/assets/dom-structure/Gauge.json +282 -0
- package/skill-docs/assets/dom-structure/HBar.json +336 -0
- package/skill-docs/assets/dom-structure/HBarStack.json +337 -0
- package/skill-docs/assets/dom-structure/Line.json +341 -0
- package/skill-docs/assets/dom-structure/NList.json +712 -0
- package/skill-docs/assets/dom-structure/NavBar.json +274 -0
- package/skill-docs/assets/dom-structure/NavPanel.json +390 -0
- package/skill-docs/assets/dom-structure/NewTab.json +606 -0
- package/skill-docs/assets/dom-structure/Nightingale.json +336 -0
- package/skill-docs/assets/dom-structure/PageHeader.json +205 -0
- package/skill-docs/assets/dom-structure/Picture.json +209 -0
- package/skill-docs/assets/dom-structure/Pie.json +338 -0
- package/skill-docs/assets/dom-structure/ProgressChart.json +299 -0
- package/skill-docs/assets/dom-structure/SearchGlobal.json +628 -0
- package/skill-docs/assets/dom-structure/Slide.json +489 -0
- package/skill-docs/assets/dom-structure/Treemap.json +324 -0
- package/skill-docs/references/common/guide-plan-template.md +10 -4
- package/skill-docs/references/common/ref-cli-commands.md +67 -34
- package/skill-docs/references/ebuilder-designer/guide-designer-components.md +12 -1
- package/skill-docs/references/ebuilder-designer/guide-designer-css.md +127 -0
- package/skill-docs/references/ebuilder-designer/guide-designer.md +6 -5
- package/skill-docs/references/esb-interface/guide-import.md +4 -1
- package/skill-docs/references/form/guide-create-form.md +14 -1
- package/skill-docs/references/form/guide-field-linkage.md +2 -0
- package/skill-docs/references/form/guide-form-formula-functions.md +36 -0
- package/skill-docs/references/form/guide-form-layout-incremental.md +75 -0
- package/skill-docs/references/form/guide-form-layout-planning.md +1 -1
- package/skill-docs/references/form/guide-form-linkage.md +89 -5
- package/skill-docs/references/form/guide-formula-linkage.md +250 -0
- package/skill-docs/references/form/ref-form-fields.md +6 -0
- package/skill-docs/references/hrm/guide-matrix.md +79 -16
- package/skill-docs/references/hrm/guide-org-employee.md +56 -0
- package/skill-docs/references/menu/system-menus.md +12 -0
- package/skill-docs/references/workflow/guide-workflow-auth-resp.md +48 -22
- package/skill-docs/references/workflow/guide-workflow-odoc-setting.md +248 -0
- package/skill-docs/references/workflow/guide-workflow-odoc.md +25 -33
- package/skill-docs/references/workflow/guide-workflow.md +18 -3
package/dist/commands/wf-form.js
CHANGED
|
@@ -6,6 +6,10 @@ import { getRichType, resolveBrowserConfig, richIdUnits, BROWSER_TYPE_CATALOG }
|
|
|
6
6
|
import { dropFieldComponents, prepareLayoutForSave } from '../services/form-field-drop.js';
|
|
7
7
|
import { BROWSER_BEAN_SEARCH, pickBrowserBean, browserBeanCandidates, toBrowserType } from '../services/browser.js';
|
|
8
8
|
import { randomUUID } from 'node:crypto';
|
|
9
|
+
import { readFileSync } from 'node:fs';
|
|
10
|
+
import { buildConditionDetail, resolveWorkflowEffect, readLinkageConfig } from '../services/form-linkage-condition.js';
|
|
11
|
+
import { resolveFormulaRefs } from '../services/formula-detail.js';
|
|
12
|
+
import { FLOW_ROUTE, assertAssignableTarget, buildAssignExpression, buildDrivingColumnsBody, buildDrivingEventsBody, buildFdEffect, buildFormulaLinkageName, buildFormulaSavePayload, buildLinkageApiUrl, buildLinkageDeleteBody, buildLinkageListBody, buildLinkageQueryBody, buildLinkageSavePayload, buildLinkageUpdatePayload, buildMonitorActions, buildPreCheckBody, describeColumn, extractEffect, extractTriggerState, findColumnById, isAssignableTarget, moduleColumnsOf, partitionDrivingColumns, resolveDrivingColumn, resolveDrivingEvent, summarizeLinkage, targetDriftWarning, toBareLabel, } from '../services/form-formula-linkage.js';
|
|
9
13
|
/** 流程表单选项配色(对齐浏览器抓包 styleConfig.OptionBackground,循环取用)。 */
|
|
10
14
|
const OPTION_COLORS = ['#FFBD4F', '#FF716E', '#3BD8C3', '#5B8FF9', '#5AD8A6', '#F6BD16', '#E86452', '#6DC8EC', '#945FB9', '#FF99C3'];
|
|
11
15
|
/**
|
|
@@ -34,22 +38,37 @@ function canon(ck) {
|
|
|
34
38
|
textarea: 'TextArea', text: 'Text', number: 'Number', money: 'Money',
|
|
35
39
|
date: 'Date', datetime: 'DateTime', select: 'Select', selectmultiple: 'SelectMultiple',
|
|
36
40
|
// 平台的浏览按钮类型名是 RelateBrowser(不是 Browser)——写错会被拒「程序异常」
|
|
37
|
-
employee: 'Employee', department: 'Department', browser: 'RelateBrowser',
|
|
41
|
+
employee: 'Employee', department: 'Department', subcompany: 'SubCompany', browser: 'RelateBrowser',
|
|
38
42
|
relatebrowser: 'RelateBrowser', 浏览: 'RelateBrowser',
|
|
39
43
|
file: 'FileComponent', filecomponent: 'FileComponent', upload: 'FileComponent', 附件: 'FileComponent',
|
|
40
44
|
ebuilder: 'EBuilder', eb: 'EBuilder', flow: 'Flow',
|
|
41
45
|
};
|
|
42
46
|
return m[ck.toLowerCase()] || ck;
|
|
43
47
|
}
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
/**
|
|
49
|
+
* 读布局元信息。不传 `layoutMultiId` 读**默认布局**;传了则定位到那一套。
|
|
50
|
+
*
|
|
51
|
+
* 注意返回的两个 id 不是一回事:`layoutMultiId` 是布局列表里的 id(对外用它),
|
|
52
|
+
* `layoutId` 是**运行时 id**(initLayout 的 `layoutId` 要的是这个,实测等于 multiId+1)。
|
|
53
|
+
*/
|
|
54
|
+
async function getLayoutMeta(client, baseUrl, formId, layoutMultiId) {
|
|
55
|
+
const body = {
|
|
46
56
|
formId, module: MODULE, customParam: {}, formTableIdList: [],
|
|
47
57
|
designerParam: { onlyLayout: false, convert: false }, form: { id: formId },
|
|
48
|
-
}
|
|
58
|
+
};
|
|
59
|
+
if (layoutMultiId)
|
|
60
|
+
body.layoutMultiId = layoutMultiId;
|
|
61
|
+
const res = await client.post(`${baseUrl}${ROUTE}/builder/getFormLayout`, body, { ebbusinessid: formId });
|
|
49
62
|
if (res?.code !== 200 || !res?.status)
|
|
50
63
|
throw new Error(`getFormLayout 失败: ${res?.msg}`);
|
|
51
64
|
const fl = res.data?.formLayout || {}, flm = res.data?.formLayoutMultiple || {};
|
|
52
|
-
|
|
65
|
+
if (layoutMultiId && String(flm.id || '') !== String(layoutMultiId)) {
|
|
66
|
+
throw new Error(`按 layoutMultiId=${layoutMultiId} 定位不到布局(返回 ${flm.id || '空'})。为避免误改默认布局,已中止。`);
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
layoutId: fl.id || '', layoutMultiId: flm.id || '', layoutName: flm.name || '',
|
|
70
|
+
layoutType: flm.layoutType || 'FLOW', terminalType: flm.terminalType || 'PC',
|
|
71
|
+
};
|
|
53
72
|
}
|
|
54
73
|
async function readConfigs(client, baseUrl, formId) {
|
|
55
74
|
const meta = await getLayoutMeta(client, baseUrl, formId);
|
|
@@ -65,14 +84,17 @@ async function readConfigs(client, baseUrl, formId) {
|
|
|
65
84
|
/** 读取运行时布局(getFormLayout pageLayouts comps),返回 singleRow=true 的字段 ID 集合。
|
|
66
85
|
* getConfig 的 configs 不带已保存的 singleRow(设计视图默认 false);field-prop/group/layout init
|
|
67
86
|
* 重排前若不从运行时合并回来,独占一行字段会被 initLayout 冲掉(实测:group initLayout 后 客户地址 singleRow 丢失)。 */
|
|
68
|
-
async function fetchRuntimeSingleRows(client, baseUrl, formId) {
|
|
87
|
+
async function fetchRuntimeSingleRows(client, baseUrl, formId, layoutMultiId) {
|
|
69
88
|
// 读失败**必须抛错**:这里返回空 Set 等于「运行时一个 singleRow 都没有」,
|
|
70
89
|
// 后面的 initLayout 就会把用户已配的「独占一行」整批冲掉(历史上出过这个事故)。
|
|
71
90
|
// 宁可整条命令失败,也不静默丢配置。
|
|
72
|
-
const
|
|
91
|
+
const body = {
|
|
73
92
|
formId, module: MODULE, customParam: {}, formTableIdList: [],
|
|
74
93
|
designerParam: { onlyLayout: false, convert: false }, form: { id: formId },
|
|
75
|
-
}
|
|
94
|
+
};
|
|
95
|
+
if (layoutMultiId)
|
|
96
|
+
body.layoutMultiId = layoutMultiId;
|
|
97
|
+
const res = await client.post(`${baseUrl}${ROUTE}/builder/getFormLayout`, body, { ebbusinessid: formId });
|
|
76
98
|
if (res?.code !== 200 || !res?.status) {
|
|
77
99
|
throw new Error(`读取运行时布局失败(getFormLayout): ${res?.msg || '未知错误'};已中止,未改动布局`);
|
|
78
100
|
}
|
|
@@ -182,13 +204,19 @@ async function fetchFormGroups(client, baseUrl, formId) {
|
|
|
182
204
|
* hooks.preLayout: 在合并运行时 singleRow 之后、applyLoneSingleRows 之前介入(add-field --single-row 用此给新字段单标 singleRow)。 */
|
|
183
205
|
export async function initWorkflowFormLayout(client, baseUrl, formId, o = {}, hooks = {}) {
|
|
184
206
|
const ebb = { ebbusinessid: formId };
|
|
185
|
-
const
|
|
207
|
+
const defMeta = await getLayoutMeta(client, baseUrl, formId);
|
|
208
|
+
// 目标布局:`--layout-id` 指定则写那一套,否则就是默认布局本身
|
|
209
|
+
const meta = o.layoutId ? await getLayoutMeta(client, baseUrl, formId, o.layoutId) : defMeta;
|
|
186
210
|
if (!meta.layoutId)
|
|
187
211
|
throw new Error('无法获取 layoutId');
|
|
188
212
|
// 保留字段分组:getConfig/initLayout 带 groupFieldIds,否则 Collapse 折叠被冲掉
|
|
189
213
|
const groupIds = await fetchFormGroups(client, baseUrl, formId);
|
|
214
|
+
// ⚠️ configs **一律从默认布局取**,哪怕这次要写的是另一套布局。
|
|
215
|
+
// 实测:拿目标布局自己的 runtime id 去 getConfig 也能回一份 configs(字段数看着一样),
|
|
216
|
+
// 但拿它 initLayout **写不进目标布局** —— 接口回 200、回读 `comps: 0`,静默失败。
|
|
217
|
+
// 换成默认布局那份立刻落库。别改成 meta.layoutId。
|
|
190
218
|
const cfgRes = await client.post(`${baseUrl}${ROUTE}/view/relate/getConfig`, {
|
|
191
|
-
formId, module: MODULE, apiModule: 'workflow/form', layoutId:
|
|
219
|
+
formId, module: MODULE, apiModule: 'workflow/form', layoutId: defMeta.layoutId,
|
|
192
220
|
customParam: { terminal: '', objId: formId }, initMode: 5, groupFieldIds: groupIds,
|
|
193
221
|
designerParam: { sourceModule: MODULE },
|
|
194
222
|
}, ebb);
|
|
@@ -211,8 +239,14 @@ export async function initWorkflowFormLayout(client, baseUrl, formId, o = {}, ho
|
|
|
211
239
|
}
|
|
212
240
|
return out;
|
|
213
241
|
}));
|
|
214
|
-
// 合并运行时已保存的 singleRow(getConfig 不带,防 initLayout
|
|
242
|
+
// 合并运行时已保存的 singleRow(getConfig 不带,防 initLayout 冲掉独占一行)。
|
|
243
|
+
// 默认布局与目标布局**两份都并进来**:configs 取自默认布局,但独占一行可能任一侧配过,
|
|
244
|
+
// 只读一份就会把另一侧已配的冲掉。多并一份没有副作用(singleRow 只是布局属性)。
|
|
215
245
|
const initSrSet = await fetchRuntimeSingleRows(client, baseUrl, formId);
|
|
246
|
+
if (meta.layoutMultiId && meta.layoutMultiId !== defMeta.layoutMultiId) {
|
|
247
|
+
for (const id of await fetchRuntimeSingleRows(client, baseUrl, formId, meta.layoutMultiId))
|
|
248
|
+
initSrSet.add(id);
|
|
249
|
+
}
|
|
216
250
|
mergeRuntimeSingleRow(configs, initSrSet);
|
|
217
251
|
// 介入点:add-field --single-row 在此给新加字段单标 singleRow(早于 applyLoneSingleRows,让其 orphan 逻辑接得住)
|
|
218
252
|
if (hooks.preLayout)
|
|
@@ -228,7 +262,7 @@ export async function initWorkflowFormLayout(client, baseUrl, formId, o = {}, ho
|
|
|
228
262
|
configs: finalConfigs, addLayout: false, ecodeType: ['js', 'css'], initMode: '1',
|
|
229
263
|
groupFieldIds: groupIds,
|
|
230
264
|
customParam: { terminal: '', objId: formId },
|
|
231
|
-
formLayoutMultiple: { isSys: true, id: meta.layoutMultiId, name: meta.layoutName, terminalType:
|
|
265
|
+
formLayoutMultiple: { isSys: true, id: meta.layoutMultiId, name: meta.layoutName, terminalType: meta.terminalType, layoutType: meta.layoutType },
|
|
232
266
|
designerParam: { onlyLayout: false },
|
|
233
267
|
}, ebb);
|
|
234
268
|
if (initRes?.code !== 200 || !initRes?.status)
|
|
@@ -248,7 +282,7 @@ async function genIds(client, baseUrl, n) {
|
|
|
248
282
|
*/
|
|
249
283
|
export const WF_FORM_HANDLED = new Set([
|
|
250
284
|
'Number', 'Money', 'TextArea', 'Date', 'DateTime',
|
|
251
|
-
'Employee', 'Department', 'RelateBrowser', 'Select', 'EBuilder', 'Flow',
|
|
285
|
+
'Employee', 'Department', 'SubCompany', 'RelateBrowser', 'Select', 'EBuilder', 'Flow',
|
|
252
286
|
]);
|
|
253
287
|
/**
|
|
254
288
|
* 构建字段 jsonObj(add-field / add-fields 共用)。返回未带 fieldId 的模板,调用方填 fieldId。
|
|
@@ -297,6 +331,16 @@ export async function buildFieldJsonObj(client, baseUrl, fieldName, fieldType, t
|
|
|
297
331
|
jsonObj.defaultExtend = { date: { type: 'current' }, time: { customValue: '00:00', type: 'custom' } };
|
|
298
332
|
}
|
|
299
333
|
}
|
|
334
|
+
else if (ck === 'SubCompany') {
|
|
335
|
+
Object.assign(jsonObj, {
|
|
336
|
+
componentKey: 'Subcompany',
|
|
337
|
+
isSingle: o.multiple ? false : true,
|
|
338
|
+
displayType: 'space', defaultExtend: { type: 'custom', relation: 'current' },
|
|
339
|
+
viewDataDetail: true, showDimension: true,
|
|
340
|
+
pcDisplaySelectedCount: { type: 'default' },
|
|
341
|
+
mobileDisplaySelectedCount: { type: 'default' },
|
|
342
|
+
});
|
|
343
|
+
}
|
|
300
344
|
else if (ck === 'Employee' || ck === 'Department') {
|
|
301
345
|
jsonObj.isSingle = o.multiple ? false : true;
|
|
302
346
|
if (o.defaultCurrent && ck === 'Employee') {
|
|
@@ -423,13 +467,13 @@ export function registerWorkflowFormCommands(program) {
|
|
|
423
467
|
}
|
|
424
468
|
// ---------- wf-form add-field ----------
|
|
425
469
|
wfForm.command('add-field')
|
|
426
|
-
.description('给流程表单加字段(Text/TextArea/Number/Money/Date/DateTime/Select/Employee/Department/浏览按钮/EBuilder/Flow)')
|
|
470
|
+
.description('给流程表单加字段(Text/TextArea/Number/Money/Date/DateTime/Select/Employee/Department/SubCompany/浏览按钮/EBuilder/Flow)')
|
|
427
471
|
.argument('<formId>', '流程表单 formId')
|
|
428
472
|
.argument('<fieldName>', '字段名')
|
|
429
473
|
.argument('<fieldType>', '字段类型')
|
|
430
474
|
.argument('[title]', '字段显示名(不传同 fieldName)')
|
|
431
475
|
.option('--sub-form-id <id>', '在指定明细子表里加字段(明细表 subFormId)')
|
|
432
|
-
.option('--multiple', '多选(Employee/Department/浏览按钮/下拉Select→SelectMultiple)')
|
|
476
|
+
.option('--multiple', '多选(Employee/Department/SubCompany/浏览按钮/下拉Select→SelectMultiple)')
|
|
433
477
|
.option('--precision <n>', '小数位(Number 缺省 0 / Money 缺省 2 / 百分比缺省 1)')
|
|
434
478
|
.option('--percent', 'Number 百分比显示(numberType=percentage)')
|
|
435
479
|
.option('--default <value>', 'Number/Money 默认值')
|
|
@@ -834,7 +878,12 @@ export function registerWorkflowFormCommands(program) {
|
|
|
834
878
|
.description('显隐联动管理(/api/workflow/core/form/setting/viewlinkage)')
|
|
835
879
|
.argument('<formId>', '流程表单 formId')
|
|
836
880
|
.argument('<name>', '联动名称')
|
|
837
|
-
.requiredOption('--config <json>', '联动配置 JSON:{"conditions":[{"field":"请假天数","operator":"EQUAL","value":"3"}],"actions":[{"prop":"hide","fields":["请假事由"]}]}。prop: hide/show/edit/readonly/required/hideLine;
|
|
881
|
+
.requiredOption('--config <json>', '联动配置 JSON:{"conditions":[{"field":"请假天数","operator":"EQUAL","value":"3"}],"actions":[{"prop":"hide","fields":["请假事由"]}]}。prop: hide/show/edit/readonly/required/hideLine;'
|
|
882
|
+
+ 'operator: EQUAL/NOT_EQUAL/CONTAIN/NOT_CONTAIN/GREATER/LESS/GREATER_EQUAL/LESS_EQUAL,'
|
|
883
|
+
+ '**为空写 NULL(或 EMPTY,会归一)、不为空写 NOT_NULL**(默认 EQUAL);'
|
|
884
|
+
+ '顶层可选 "detailType":"AND|OR"(界面上「所有」/「任一」);'
|
|
885
|
+
+ '"effect" 指定生效维度:不写=当前表单,"workFlow"=当前工作流,"includeNode"=选择节点(后者另需 "nodeId")')
|
|
886
|
+
.option('--workflow-id <id>', '流程 ID。生效维度选「当前工作流」或「选择节点」时必给(该联动挂在流程上,refId 也是它)')
|
|
838
887
|
.action(async (formId, name, cmdOpts) => {
|
|
839
888
|
try {
|
|
840
889
|
const opts = program.opts();
|
|
@@ -844,13 +893,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
844
893
|
const client = new ApiClient(auth);
|
|
845
894
|
const baseUrl = auth.getBaseUrl();
|
|
846
895
|
const ebb = { ebbusinessid: formId };
|
|
847
|
-
|
|
848
|
-
try {
|
|
849
|
-
cfg = JSON.parse(cmdOpts.config);
|
|
850
|
-
}
|
|
851
|
-
catch {
|
|
852
|
-
throw new Error('config JSON 解析失败');
|
|
853
|
-
}
|
|
896
|
+
const cfg = readLinkageConfig(cmdOpts.config);
|
|
854
897
|
if (!Array.isArray(cfg.conditions) || !Array.isArray(cfg.actions) || !cfg.actions.length) {
|
|
855
898
|
throw new Error('config 需含 conditions[] 和非空 actions[]');
|
|
856
899
|
}
|
|
@@ -876,15 +919,18 @@ export function registerWorkflowFormCommands(program) {
|
|
|
876
919
|
// 这里曾写 `configs.find(c => !c.system)?.name ? '流程表单' : '流程表单'`——两个分支同值等于没写,
|
|
877
920
|
// 且 configs 是**布局字段**数组、取到的是字段名而非表单名,照字面"修好"反而会把字段名当表单名发出去。
|
|
878
921
|
const formName = '流程表单';
|
|
879
|
-
// conditions
|
|
922
|
+
// conditions。算子的归一与「为空不能带 sourceContent」那套规则和 eb 表那条路**同一份**
|
|
923
|
+
// (见 services/form-linkage-condition.ts)—— 两边都是同一个平台接口族,踩的是同一个坑。
|
|
924
|
+
const condWarnings = [];
|
|
880
925
|
const conditionDetails = cfg.conditions.map((c) => {
|
|
881
926
|
const f = findField(c.field);
|
|
882
927
|
if (!f)
|
|
883
928
|
throw new Error(`条件字段未找到: "${c.field}",可用: ${allFields.map((x) => x.name).join(', ')}`);
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
929
|
+
const { detail, warnings: w } = buildConditionDetail({
|
|
930
|
+
fieldId: String(f.id), operator: c.operator, value: c.value, options: c.options,
|
|
931
|
+
});
|
|
932
|
+
condWarnings.push(...w);
|
|
933
|
+
return detail;
|
|
888
934
|
});
|
|
889
935
|
// actions
|
|
890
936
|
const linkageDetails = cfg.actions.map((a) => ({
|
|
@@ -897,12 +943,30 @@ export function registerWorkflowFormCommands(program) {
|
|
|
897
943
|
}),
|
|
898
944
|
detailOptions: [],
|
|
899
945
|
}));
|
|
946
|
+
// 生效维度。工作流表单这条路由上设计器提供四种(当前表单 / 表单布局 / 当前工作流 / 选择节点),
|
|
947
|
+
// 解析统一收在 services/form-linkage-condition.ts 的 `resolveWorkflowEffect` 里 ——
|
|
948
|
+
// 函数联动那边用的是同一份,别再内联第二遍。
|
|
949
|
+
const { effect, refId } = await resolveWorkflowEffect(client, baseUrl, {
|
|
950
|
+
module: MODULE, route: ROUTE, formId,
|
|
951
|
+
dimension: cfg.effect,
|
|
952
|
+
workflowId: cmdOpts.workflowId,
|
|
953
|
+
nodeKey: cfg.nodeId || cfg.node,
|
|
954
|
+
layoutId: cfg.layoutId,
|
|
955
|
+
});
|
|
956
|
+
const fdEffect = buildFdEffect(formId, effect, MODULE);
|
|
900
957
|
const payload = {
|
|
901
|
-
fdEffect
|
|
902
|
-
|
|
958
|
+
fdEffect,
|
|
959
|
+
// targetName 设计器不发,去掉;targetModule 是 workflow
|
|
960
|
+
condition: { targetId: formId, targetModule: MODULE, conditionType: 'FIELD', conditionDetails, formulaId: '', formulaName: '' },
|
|
903
961
|
linkageDetails,
|
|
904
|
-
|
|
962
|
+
// ⚠ `refId` 是**这条联动挂在谁身上**,在这条路由上就是**流程 ID**;原来写死 formId 是错的。
|
|
963
|
+
// 注意它**不等于** optionList 的取值 —— 选「选择节点」时取值是节点 ID,refId 仍是流程 ID
|
|
964
|
+
// (设计器报文里这两处就是这么分的,别照着「取值」抄)。refId 由 resolveWorkflowEffect 一并给出。
|
|
965
|
+
module: MODULE, formId, refId,
|
|
966
|
+
enableState: '1', linkageName: name,
|
|
905
967
|
};
|
|
968
|
+
for (const w of condWarnings)
|
|
969
|
+
console.error(` ⚠ ${w}`);
|
|
906
970
|
const r = await client.post(`${baseUrl}${ROUTE}/setting/viewlinkage/add`, payload, ebb);
|
|
907
971
|
if (r?.code !== 200 || !r?.status)
|
|
908
972
|
throw new Error(`联动添加失败: ${r?.msg || '未知错误'}`);
|
|
@@ -970,6 +1034,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
970
1034
|
.requiredOption('--target <fieldId>', '目标字段 ID(公式结果写入此字段)')
|
|
971
1035
|
.option('--name <name>', '公式名称(默认自动生成)')
|
|
972
1036
|
.option('--return-type <type>', '返回类型: Number / String / Date', 'Number')
|
|
1037
|
+
.option('--formula-id <id>', '要**更新**的已有公式 ID(原地改,不新建)。不传则新建一条')
|
|
973
1038
|
.action(async (formId, cmdOpts) => {
|
|
974
1039
|
try {
|
|
975
1040
|
const opts = program.opts();
|
|
@@ -986,19 +1051,34 @@ export function registerWorkflowFormCommands(program) {
|
|
|
986
1051
|
process.exitCode = 1;
|
|
987
1052
|
return;
|
|
988
1053
|
}
|
|
989
|
-
|
|
1054
|
+
// `--formula-id` 传已有 id 就是**原地更新**那张公式(不新建、返回的 id 不变)。
|
|
1055
|
+
// 名字缺省沿用原公式名 —— 否则会被改成「公式_<时间戳>」,看着像新建了一条。
|
|
1056
|
+
let formulaName = cmdOpts.name;
|
|
1057
|
+
if (!formulaName && cmdOpts.formulaId) {
|
|
1058
|
+
try {
|
|
1059
|
+
const d = await client.post(`${baseUrl}/api/excel/formula/detail`, { formulaId: cmdOpts.formulaId });
|
|
1060
|
+
formulaName = d?.resultJson?.data?.name || undefined;
|
|
1061
|
+
}
|
|
1062
|
+
catch { /* 读不到就退回自动生成 */ }
|
|
1063
|
+
}
|
|
1064
|
+
formulaName = formulaName || `公式_${Date.now()}`;
|
|
990
1065
|
const savePayload = {
|
|
991
1066
|
expressSql: cmdOpts.expression, name: formulaName, parameters: parsed.parameters,
|
|
992
1067
|
returnType: cmdOpts.returnType, validateType: 'normal', referenceType: 'assign',
|
|
993
1068
|
extendParam: JSON.stringify({ exceptIds: cmdOpts.target, createType: 'once' }),
|
|
994
|
-
formulaId: null, dataSources: [], formulaType: 'normal', mainDataSource: [null],
|
|
1069
|
+
formulaId: cmdOpts.formulaId || null, dataSources: [], formulaType: 'normal', mainDataSource: [null],
|
|
995
1070
|
tempVariableList: [], nameAuto: false, module: MODULE, multiFuncSepType: 1,
|
|
996
1071
|
};
|
|
997
1072
|
const saveRes = await client.post(`${baseUrl}/api/excel/formula/save`, savePayload);
|
|
998
1073
|
if (!saveRes?.resultJson?.excute)
|
|
999
1074
|
throw new Error(`公式保存失败: ${saveRes?.resultJson?.error || saveRes?.msg || '未知错误'}`);
|
|
1000
1075
|
const expressId = saveRes.resultJson.id;
|
|
1001
|
-
|
|
1076
|
+
// 说要更新就必须真的更新了 —— 平台万一悄悄新建一条,绑定会跟过去、旧公式留成孤儿。
|
|
1077
|
+
if (cmdOpts.formulaId && String(expressId) !== String(cmdOpts.formulaId)) {
|
|
1078
|
+
throw new Error(`期望原地更新 ${cmdOpts.formulaId},平台返回的是 ${expressId}`
|
|
1079
|
+
+ '(很可能新建了一条,旧公式已成为孤儿,请先在公式列表里核对)');
|
|
1080
|
+
}
|
|
1081
|
+
console.error(` ${cmdOpts.formulaId ? '公式已更新' : '公式已创建'}: ${expressId} (${saveRes.resultJson.formula})`);
|
|
1002
1082
|
// ffExpress 绑字段(saveFormFieldNew 重存带 ffExpress)
|
|
1003
1083
|
try {
|
|
1004
1084
|
const gf = await client.post(`${baseUrl}${ROUTE}/field/manage/getFormField`, { module: MODULE, formTableField: { formField: { id: cmdOpts.target, form: { id: formId } } } }, ebb);
|
|
@@ -1264,7 +1344,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
1264
1344
|
.argument('<formId>', '流程表单 formId')
|
|
1265
1345
|
.argument('<fieldId>', '字段 fieldId(被带出的目标字段,如 联系方式)')
|
|
1266
1346
|
.option('--title <title>', '修改字段标题')
|
|
1267
|
-
.option('--multiple', '设为多选(Employee/Department/Browser isSingle=false;Select→SelectMultiple)')
|
|
1347
|
+
.option('--multiple', '设为多选(Employee/Department/SubCompany/Browser isSingle=false;Select→SelectMultiple)')
|
|
1268
1348
|
.option('--single', '设为单选(反向)')
|
|
1269
1349
|
.option('--relate-from <关联字段>', 'EB关联带出:选 EBuilder 关联记录(如关联客户)后自动带出本字段值。传关联字段名/fieldId')
|
|
1270
1350
|
.option('--relate-from-source <源字段>', '目标表单的源字段(如客户信息表的联系方式)fieldId 或字段名,--relate-from 必填。传字段名需 --sform-id 解析')
|
|
@@ -1291,7 +1371,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
1291
1371
|
if (o.multiple === true || o.single === true) {
|
|
1292
1372
|
const multi = o.multiple === true;
|
|
1293
1373
|
const t = jsonObj.type;
|
|
1294
|
-
if (t === 'Employee' || t === 'Department' || t === 'RelateBrowser') {
|
|
1374
|
+
if (t === 'Employee' || t === 'Department' || t === 'SubCompany' || t === 'RelateBrowser') {
|
|
1295
1375
|
jsonObj.isSingle = !multi;
|
|
1296
1376
|
changes.push(`isSingle=${!multi}`);
|
|
1297
1377
|
}
|
|
@@ -1301,7 +1381,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
1301
1381
|
changes.push(`type=${jsonObj.type}`);
|
|
1302
1382
|
}
|
|
1303
1383
|
else {
|
|
1304
|
-
throw new Error(`字段类型 ${t} 不支持多选切换(仅 Employee/Department/浏览按钮/Select)`);
|
|
1384
|
+
throw new Error(`字段类型 ${t} 不支持多选切换(仅 Employee/Department/SubCompany/浏览按钮/Select)`);
|
|
1305
1385
|
}
|
|
1306
1386
|
}
|
|
1307
1387
|
// EB关联带出(ffRelateField):选关联记录后自动带出目标表字段值
|
|
@@ -1780,7 +1860,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
1780
1860
|
configs: finalConfigs, addLayout: false, ecodeType: ['js', 'css'], initMode: '1',
|
|
1781
1861
|
groupFieldIds,
|
|
1782
1862
|
customParam: { terminal: '', objId: formId },
|
|
1783
|
-
formLayoutMultiple: { isSys: true, id: meta.layoutMultiId, name: meta.layoutName, terminalType:
|
|
1863
|
+
formLayoutMultiple: { isSys: true, id: meta.layoutMultiId, name: meta.layoutName, terminalType: meta.terminalType, layoutType: meta.layoutType },
|
|
1784
1864
|
designerParam: { onlyLayout: false },
|
|
1785
1865
|
}, ebb);
|
|
1786
1866
|
if (initRes?.code !== 200 || !initRes?.status)
|
|
@@ -1880,6 +1960,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
1880
1960
|
layoutCmd.command('init')
|
|
1881
1961
|
.description('初始化/重建流程表单布局(initLayout):按 layoutType 选模板(FLOW 默认)+ 设字段 readOnly/required/singleRow')
|
|
1882
1962
|
.argument('<formId>', '流程表单 formId')
|
|
1963
|
+
.option('--layout-id <id>', '要重建哪一套布局(formLayoutMultiple.id,即节点独立布局的 layoutId);不传 = 默认布局')
|
|
1883
1964
|
.option('--style-template <name|id>', '样式模板 id(默认按 layoutType:FLOW=820...01 / EXCEL=700...08)')
|
|
1884
1965
|
.option('--read-only', '字段只读')
|
|
1885
1966
|
.option('--required', '字段必填')
|
|
@@ -1985,7 +2066,7 @@ export function registerWorkflowFormCommands(program) {
|
|
|
1985
2066
|
configs: finalConfigs, addLayout: false, ecodeType: ['js', 'css'], initMode: '1',
|
|
1986
2067
|
groupFieldIds: groupIds,
|
|
1987
2068
|
customParam: { terminal: '', objId: formId },
|
|
1988
|
-
formLayoutMultiple: { isSys: true, id: meta.layoutMultiId, name: meta.layoutName, terminalType:
|
|
2069
|
+
formLayoutMultiple: { isSys: true, id: meta.layoutMultiId, name: meta.layoutName, terminalType: meta.terminalType, layoutType: meta.layoutType },
|
|
1989
2070
|
designerParam: { onlyLayout: false },
|
|
1990
2071
|
}, ebb);
|
|
1991
2072
|
if (initRes?.code !== 200 || !initRes?.status)
|
|
@@ -2000,6 +2081,431 @@ export function registerWorkflowFormCommands(program) {
|
|
|
2000
2081
|
process.exitCode = 1;
|
|
2001
2082
|
}
|
|
2002
2083
|
});
|
|
2084
|
+
// ---------- wf-form formula-linkage(流程表单的函数联动)----------
|
|
2085
|
+
const flCmd = wfForm.command('formula-linkage')
|
|
2086
|
+
.description('函数联动(流程表单,linkageType=excel):list / read / events / columns / add / update / delete');
|
|
2087
|
+
/** 这条路由的公共取数:驱动事件 + 驱动列(字段来源也从驱动列来,见 `drivingColumnsAsFieldSource`)。 */
|
|
2088
|
+
async function wfLinkageContext(client, baseUrl, formId, workflowId) {
|
|
2089
|
+
const ebb = { ebbusinessid: formId };
|
|
2090
|
+
const loc = { formId, refId: workflowId || formId };
|
|
2091
|
+
const [ev, col] = await Promise.all([
|
|
2092
|
+
client.post(`${baseUrl}${buildLinkageApiUrl(FLOW_ROUTE, 'findFormDrivingEvents')}`, buildDrivingEventsBody(FLOW_ROUTE, loc), ebb),
|
|
2093
|
+
client.post(`${baseUrl}${buildLinkageApiUrl(FLOW_ROUTE, 'findFormDrivingColumns')}`, buildDrivingColumnsBody(FLOW_ROUTE, loc), ebb),
|
|
2094
|
+
]);
|
|
2095
|
+
if (ev?.code !== 200 || !ev?.status)
|
|
2096
|
+
throw new Error(`查询触发事件失败: ${ev?.msg || '未知错误'}`);
|
|
2097
|
+
if (col?.code !== 200 || !col?.status)
|
|
2098
|
+
throw new Error(`查询可引用字段失败: ${col?.msg || '未知错误'}`);
|
|
2099
|
+
const columns = (col.data?.drivingColumns || []);
|
|
2100
|
+
return { events: (ev.data || []), columns, source: drivingColumnsAsFieldSource(columns) };
|
|
2101
|
+
}
|
|
2102
|
+
/** 解析这条路由的生效维度(四选一)。 */
|
|
2103
|
+
async function wfEffectOf(client, baseUrl, formId, o) {
|
|
2104
|
+
return resolveWorkflowEffect(client, baseUrl, {
|
|
2105
|
+
module: MODULE, route: ROUTE, formId,
|
|
2106
|
+
dimension: o.effect, workflowId: o.workflowId, nodeKey: o.node, layoutId: o.layoutId,
|
|
2107
|
+
});
|
|
2108
|
+
}
|
|
2109
|
+
/** 回读一条,读不到就报错。 */
|
|
2110
|
+
async function wfReadLinkage(client, baseUrl, formId, linkageId, workflowId) {
|
|
2111
|
+
const refId = workflowId || formId;
|
|
2112
|
+
const ebb = { ebbusinessid: formId };
|
|
2113
|
+
const res = await client.post(`${baseUrl}${buildLinkageApiUrl(FLOW_ROUTE, 'queryById')}`, buildLinkageQueryBody(FLOW_ROUTE, { id: linkageId, formId, refId }), ebb);
|
|
2114
|
+
if (res?.code !== 200 || !res?.status)
|
|
2115
|
+
throw new Error(`查询失败: ${res?.msg || '未知错误'}`);
|
|
2116
|
+
if (String(res?.data?.linkageType) !== 'excel') {
|
|
2117
|
+
throw new Error(`这条的 linkageType 是 ${res?.data?.linkageType},不是函数联动`);
|
|
2118
|
+
}
|
|
2119
|
+
return res.data;
|
|
2120
|
+
}
|
|
2121
|
+
flCmd.command('list')
|
|
2122
|
+
.description('列出该流程表单下的函数联动')
|
|
2123
|
+
.argument('<formId>', '流程表单 formId')
|
|
2124
|
+
.option('--workflow-id <id>', '流程 ID(refId;不给按 formId 兜底)')
|
|
2125
|
+
.option('--keyword <text>', '按联动名过滤')
|
|
2126
|
+
.action(async (formId, cmdOpts) => {
|
|
2127
|
+
try {
|
|
2128
|
+
const opts = program.opts();
|
|
2129
|
+
const auth = await AuthSession.fromOptions(opts);
|
|
2130
|
+
if (!auth)
|
|
2131
|
+
throw new Error('无法加载认证');
|
|
2132
|
+
const client = new ApiClient(auth);
|
|
2133
|
+
const baseUrl = auth.getBaseUrl();
|
|
2134
|
+
const refId = cmdOpts.workflowId || formId;
|
|
2135
|
+
const res = await client.post(`${baseUrl}${buildLinkageApiUrl(FLOW_ROUTE, 'fullPageQueryByFormId')}`, buildLinkageListBody(FLOW_ROUTE, { formId, refId, keyword: cmdOpts.keyword }), { ebbusinessid: formId });
|
|
2136
|
+
if (res?.code !== 200 || !res?.status)
|
|
2137
|
+
throw new Error(`查询失败: ${res?.msg || '未知错误'}`);
|
|
2138
|
+
const total = Number(res?.data?.total ?? 0);
|
|
2139
|
+
const records = res?.data?.records || [];
|
|
2140
|
+
if (opts.json) {
|
|
2141
|
+
console.log(JSON.stringify(records, null, 2));
|
|
2142
|
+
return;
|
|
2143
|
+
}
|
|
2144
|
+
console.log(`共 ${total} 条函数联动:`);
|
|
2145
|
+
for (const r of records) {
|
|
2146
|
+
const s = summarizeLinkage(r);
|
|
2147
|
+
console.log(` [${s.id}] ${s.name} (${s.state ? '启用' : '停用'})`);
|
|
2148
|
+
console.log(` 生效范围: ${wfEffectLabel(s.effect)}`);
|
|
2149
|
+
console.log(` 触发: ${s.eventNames.join('、') || '—'} ← ${s.triggerNames.join('、') || '—'}`);
|
|
2150
|
+
}
|
|
2151
|
+
if (records.length)
|
|
2152
|
+
console.log(' (列表不返回公式正文,要表达式/参数用 wf-form formula-linkage read)');
|
|
2153
|
+
if (total === 0)
|
|
2154
|
+
console.log(` ℹ 查不到时先确认 --workflow-id:不传是按 formId=${formId} 当 refId 查的`);
|
|
2155
|
+
}
|
|
2156
|
+
catch (e) {
|
|
2157
|
+
console.error(`查询函数联动失败: ${e.message}`);
|
|
2158
|
+
process.exitCode = 1;
|
|
2159
|
+
}
|
|
2160
|
+
});
|
|
2161
|
+
flCmd.command('read')
|
|
2162
|
+
.description('查看一条函数联动(含公式表达式与参数)')
|
|
2163
|
+
.argument('<formId>', '流程表单 formId')
|
|
2164
|
+
.argument('<linkageId>', '联动 ID')
|
|
2165
|
+
.option('--workflow-id <id>', '流程 ID(refId;不给按 formId 兜底)')
|
|
2166
|
+
.action(async (formId, linkageId, cmdOpts) => {
|
|
2167
|
+
try {
|
|
2168
|
+
const opts = program.opts();
|
|
2169
|
+
const auth = await AuthSession.fromOptions(opts);
|
|
2170
|
+
if (!auth)
|
|
2171
|
+
throw new Error('无法加载认证');
|
|
2172
|
+
const client = new ApiClient(auth);
|
|
2173
|
+
const baseUrl = auth.getBaseUrl();
|
|
2174
|
+
const data = await wfReadLinkage(client, baseUrl, formId, linkageId, cmdOpts.workflowId);
|
|
2175
|
+
if (opts.json) {
|
|
2176
|
+
console.log(JSON.stringify(data, null, 2));
|
|
2177
|
+
return;
|
|
2178
|
+
}
|
|
2179
|
+
const s = summarizeLinkage(data);
|
|
2180
|
+
console.log(`[${s.id}] ${s.name} (${s.state ? '启用' : '停用'})`);
|
|
2181
|
+
console.log(` refId: ${data?.refId || '—'}`);
|
|
2182
|
+
console.log(` 生效范围: ${wfEffectLabel(s.effect)}`);
|
|
2183
|
+
console.log(` 触发: ${s.eventNames.join('、') || '—'} ← ${s.triggerNames.join('、') || '—'}`);
|
|
2184
|
+
console.log(` 公式: ${s.excelName} (excelId=${s.excelId})`);
|
|
2185
|
+
console.log(` 表达式: ${s.expression || '-'}`);
|
|
2186
|
+
if (s.parameters.length) {
|
|
2187
|
+
console.log(` 参数 (${s.parameters.length}):`);
|
|
2188
|
+
for (const p of s.parameters)
|
|
2189
|
+
console.log(` ${p.fieldId} ${p.title || p.name || ''} [${p.properKey || ''}]`);
|
|
2190
|
+
}
|
|
2191
|
+
}
|
|
2192
|
+
catch (e) {
|
|
2193
|
+
console.error(`查询函数联动失败: ${e.message}`);
|
|
2194
|
+
process.exitCode = 1;
|
|
2195
|
+
}
|
|
2196
|
+
});
|
|
2197
|
+
flCmd.command('events')
|
|
2198
|
+
.description('列出可用的触发事件(供 --event 取值)')
|
|
2199
|
+
.argument('<formId>', '流程表单 formId')
|
|
2200
|
+
.option('--workflow-id <id>', '流程 ID(refId;不给按 formId 兜底)')
|
|
2201
|
+
.action(async (formId, cmdOpts) => {
|
|
2202
|
+
try {
|
|
2203
|
+
const opts = program.opts();
|
|
2204
|
+
const auth = await AuthSession.fromOptions(opts);
|
|
2205
|
+
if (!auth)
|
|
2206
|
+
throw new Error('无法加载认证');
|
|
2207
|
+
const client = new ApiClient(auth);
|
|
2208
|
+
const baseUrl = auth.getBaseUrl();
|
|
2209
|
+
const { events } = await wfLinkageContext(client, baseUrl, formId, cmdOpts.workflowId);
|
|
2210
|
+
if (opts.json) {
|
|
2211
|
+
console.log(JSON.stringify(events, null, 2));
|
|
2212
|
+
return;
|
|
2213
|
+
}
|
|
2214
|
+
console.log(`共 ${events.length} 个触发事件:`);
|
|
2215
|
+
for (const e of events) {
|
|
2216
|
+
console.log(` ${e.groupName} / ${e.name} ${e.type} ${e.selectColumn ? '(需 --trigger 指定字段)' : '(表单级,无需 --trigger)'}`);
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
catch (e) {
|
|
2220
|
+
console.error(`查询触发事件失败: ${e.message}`);
|
|
2221
|
+
process.exitCode = 1;
|
|
2222
|
+
}
|
|
2223
|
+
});
|
|
2224
|
+
flCmd.command('columns')
|
|
2225
|
+
.description('列出可用于公式引用与触发的字段')
|
|
2226
|
+
.argument('<formId>', '流程表单 formId')
|
|
2227
|
+
.option('--workflow-id <id>', '流程 ID(refId;不给按 formId 兜底)')
|
|
2228
|
+
.option('--keyword <text>', '按字段名过滤')
|
|
2229
|
+
.action(async (formId, cmdOpts) => {
|
|
2230
|
+
try {
|
|
2231
|
+
const opts = program.opts();
|
|
2232
|
+
const auth = await AuthSession.fromOptions(opts);
|
|
2233
|
+
if (!auth)
|
|
2234
|
+
throw new Error('无法加载认证');
|
|
2235
|
+
const client = new ApiClient(auth);
|
|
2236
|
+
const baseUrl = auth.getBaseUrl();
|
|
2237
|
+
const { columns } = await wfLinkageContext(client, baseUrl, formId, cmdOpts.workflowId);
|
|
2238
|
+
if (opts.json) {
|
|
2239
|
+
console.log(JSON.stringify(columns, null, 2));
|
|
2240
|
+
return;
|
|
2241
|
+
}
|
|
2242
|
+
const kw = cmdOpts.keyword;
|
|
2243
|
+
const shown = kw ? columns.filter((c) => String(c.name).includes(kw) || String(c.dataKey || '').includes(kw)) : columns;
|
|
2244
|
+
const { assignable, unassignable } = partitionDrivingColumns(shown, FLOW_ROUTE);
|
|
2245
|
+
const drifted = partitionDrivingColumns(columns, FLOW_ROUTE).drifted;
|
|
2246
|
+
console.log(`可作赋值目标 (${assignable.length}) —— 也能作引用与触发:`);
|
|
2247
|
+
for (const c of assignable)
|
|
2248
|
+
console.log(describeColumn(c, FLOW_ROUTE));
|
|
2249
|
+
console.log(`\n不可作赋值目标 (${unassignable.length}) —— 仍可作引用与触发:`);
|
|
2250
|
+
for (const c of unassignable)
|
|
2251
|
+
console.log(describeColumn(c, FLOW_ROUTE));
|
|
2252
|
+
if (drifted.length) {
|
|
2253
|
+
console.log(`\n⚠ ${drifted.length} 列形似系统字段但不在本路由的不可赋值清单里,已按「可赋值」处理:`);
|
|
2254
|
+
for (const c of drifted)
|
|
2255
|
+
console.log(` ${targetDriftWarning(c, FLOW_ROUTE)}`);
|
|
2256
|
+
}
|
|
2257
|
+
console.log(`\n共 ${columns.length} 列(其中 ${columns.filter((c) => isAssignableTarget(c, FLOW_ROUTE)).length} 列可作赋值目标)`);
|
|
2258
|
+
}
|
|
2259
|
+
catch (e) {
|
|
2260
|
+
console.error(`查询可引用字段失败: ${e.message}`);
|
|
2261
|
+
process.exitCode = 1;
|
|
2262
|
+
}
|
|
2263
|
+
});
|
|
2264
|
+
flCmd.command('add')
|
|
2265
|
+
.description('新增函数联动:事件 + 触发字段 + 赋值目标 + 公式')
|
|
2266
|
+
.argument('<formId>', '流程表单 formId')
|
|
2267
|
+
.requiredOption('--target <field>', '赋值目标字段(被写入)')
|
|
2268
|
+
.requiredOption('--expression <expr>', '公式右侧函数体;也接受整段赋值式,或用 @文件 传长表达式')
|
|
2269
|
+
.option('--event <event>', '触发事件(名称或 type,见 events),默认 changeField 值改变时', 'changeField')
|
|
2270
|
+
.option('--trigger <fields...>', '触发字段,可多个')
|
|
2271
|
+
.option('--effect <dimension>', '生效维度: form=当前表单(默认)/ formLayout=表单布局 / workFlow=当前工作流 / includeNode=选择节点')
|
|
2272
|
+
.option('--workflow-id <id>', '流程 ID(refId,也是 workFlow/includeNode 的取值来源;不给按 formId 兜底)')
|
|
2273
|
+
.option('--node <node>', 'includeNode 的节点(id 或节点名)')
|
|
2274
|
+
.option('--layout-id <id>', 'formLayout 指定的布局 id(不传取默认布局)')
|
|
2275
|
+
.option('--name <name>', '联动名称(默认「<公式名> - 公式_<时间戳>」)')
|
|
2276
|
+
.option('--formula-name <name>', '公式名称')
|
|
2277
|
+
.option('--formula-id <id>', '复用/更新已有公式(传了就原地更新那张公式)')
|
|
2278
|
+
.action(async (formId, cmdOpts) => {
|
|
2279
|
+
try {
|
|
2280
|
+
const opts = program.opts();
|
|
2281
|
+
const auth = await AuthSession.fromOptions(opts);
|
|
2282
|
+
if (!auth)
|
|
2283
|
+
throw new Error('无法加载认证');
|
|
2284
|
+
const client = new ApiClient(auth);
|
|
2285
|
+
const baseUrl = auth.getBaseUrl();
|
|
2286
|
+
const ebb = { ebbusinessid: formId };
|
|
2287
|
+
const refId = cmdOpts.workflowId || formId;
|
|
2288
|
+
const { events, columns, source } = await wfLinkageContext(client, baseUrl, formId, cmdOpts.workflowId);
|
|
2289
|
+
const event = resolveDrivingEvent(events, cmdOpts.event);
|
|
2290
|
+
const targetCol = resolveDrivingColumn(columns, cmdOpts.target, FLOW_ROUTE);
|
|
2291
|
+
assertAssignableTarget(targetCol, FLOW_ROUTE);
|
|
2292
|
+
const drift = targetDriftWarning(targetCol, FLOW_ROUTE);
|
|
2293
|
+
if (drift)
|
|
2294
|
+
console.error(` ⚠ ${drift}`);
|
|
2295
|
+
const triggerCols = (cmdOpts.trigger || []).map((t) => resolveDrivingColumn(columns, t, FLOW_ROUTE));
|
|
2296
|
+
if (!event.selectColumn && triggerCols.length) {
|
|
2297
|
+
console.error(` ⚠ 事件「${event.name}」是表单级的,不需要触发字段,--trigger 已忽略`);
|
|
2298
|
+
}
|
|
2299
|
+
const monitorActions = buildMonitorActions(event, triggerCols);
|
|
2300
|
+
const { effect } = await wfEffectOf(client, baseUrl, formId, cmdOpts);
|
|
2301
|
+
const { expression, stripped } = buildAssignExpression(targetCol, readExpressionArg(cmdOpts.expression));
|
|
2302
|
+
if (stripped)
|
|
2303
|
+
console.error(' ℹ 表达式自带赋值式,已按 --target 校验左侧并沿用右侧');
|
|
2304
|
+
console.error(` 联动: ${effect.effectName} / ${event.name} ← ${triggerCols.map((c) => toBareLabel(c)).join('、') || '(表单级)'} → 填 ${toBareLabel(targetCol)}(${targetCol.id})`);
|
|
2305
|
+
// 这条路由的 parameter **不带 appId 键**,所以 ctx 里不给 appId
|
|
2306
|
+
const parsed = resolveFormulaRefs(expression, {
|
|
2307
|
+
mainFields: source.mainFields, detailTables: source.detailTables,
|
|
2308
|
+
moduleColumns: moduleColumnsOf(columns, FLOW_ROUTE),
|
|
2309
|
+
formId, module: FLOW_ROUTE.module, hint: FLOW_ROUTE.columnsHint,
|
|
2310
|
+
});
|
|
2311
|
+
for (const w of parsed.warnings)
|
|
2312
|
+
console.error(` ⚠ ${w}`);
|
|
2313
|
+
if (parsed.errors.length) {
|
|
2314
|
+
for (const e of parsed.errors)
|
|
2315
|
+
console.error(` ❌ ${e}`);
|
|
2316
|
+
process.exitCode = 1;
|
|
2317
|
+
return;
|
|
2318
|
+
}
|
|
2319
|
+
if (parsed.parameters[0]?.fieldId !== String(targetCol.id)) {
|
|
2320
|
+
throw new Error(`赋值目标没有出现在公式参数表首位(首位是 ${parsed.parameters[0]?.fieldId ?? '空'}),已中止`);
|
|
2321
|
+
}
|
|
2322
|
+
const formulaName = cmdOpts.formulaName || '函数联动公式';
|
|
2323
|
+
const saveRes = await client.post(`${baseUrl}/api/excel/formula/save`, buildFormulaSavePayload({
|
|
2324
|
+
expression: parsed.normalizedExpression, name: formulaName,
|
|
2325
|
+
parameters: parsed.parameters, formulaId: cmdOpts.formulaId || null, route: FLOW_ROUTE,
|
|
2326
|
+
}));
|
|
2327
|
+
if (!saveRes?.resultJson?.excute) {
|
|
2328
|
+
throw new Error(`公式保存失败: ${saveRes?.resultJson?.error || saveRes?.msg || '未知错误'}`);
|
|
2329
|
+
}
|
|
2330
|
+
const excelId = String(saveRes.resultJson.id || '');
|
|
2331
|
+
console.error(` 公式: ${excelId} ${formulaName}`);
|
|
2332
|
+
const linkageName = cmdOpts.name || buildFormulaLinkageName(formulaName, new Date());
|
|
2333
|
+
const linkRes = await client.post(`${baseUrl}${buildLinkageApiUrl(FLOW_ROUTE, 'saveFormDataLinkage')}`, buildLinkageSavePayload({
|
|
2334
|
+
formId, appId: '', objId: '', linkageName, excelId, excelName: formulaName,
|
|
2335
|
+
monitorActions, route: FLOW_ROUTE, refId,
|
|
2336
|
+
}), ebb);
|
|
2337
|
+
if (linkRes?.code !== 200 || !linkRes?.status) {
|
|
2338
|
+
throw new Error(`联动保存失败: ${linkRes?.msg || '未知错误'}(公式已创建 excelId=${excelId},可用 --formula-id ${excelId} 复用重试)`);
|
|
2339
|
+
}
|
|
2340
|
+
const linkageId = String(linkRes?.data?.id || '');
|
|
2341
|
+
console.error(` 联动已创建: ${linkageId}`);
|
|
2342
|
+
// preCheck 不通过不中止 —— 联动已经落库了,中止只会让人以为没建成
|
|
2343
|
+
const pre = await client.post(`${baseUrl}${buildLinkageApiUrl(FLOW_ROUTE, 'preCheck')}`, buildPreCheckBody(FLOW_ROUTE, { formId, linkageIds: [linkageId], refId }), ebb);
|
|
2344
|
+
if (pre?.code !== 200 || !pre?.status) {
|
|
2345
|
+
console.error(` ⚠ 平台校验未通过: ${pre?.msg || '未知错误'}(联动已落库,请在设计器里复核)`);
|
|
2346
|
+
}
|
|
2347
|
+
const rb = await client.post(`${baseUrl}${buildLinkageApiUrl(FLOW_ROUTE, 'queryById')}`, buildLinkageQueryBody(FLOW_ROUTE, { id: linkageId, formId, refId }), ebb);
|
|
2348
|
+
const s = summarizeLinkage(rb?.data);
|
|
2349
|
+
if (s.expression && s.expression !== parsed.normalizedExpression) {
|
|
2350
|
+
console.error(` ⚠ 平台回读的表达式与提交不一致,以平台为准: ${s.expression}`);
|
|
2351
|
+
}
|
|
2352
|
+
const out = {
|
|
2353
|
+
success: true, linkageId, excelId, formId, refId, effect: effect.effectName,
|
|
2354
|
+
expression: s.expression || parsed.normalizedExpression,
|
|
2355
|
+
target: { id: targetCol.id, name: toBareLabel(targetCol) },
|
|
2356
|
+
event: event.type, triggers: triggerCols.map((c) => ({ id: c.id, name: toBareLabel(c) })),
|
|
2357
|
+
};
|
|
2358
|
+
console.log(opts.json ? JSON.stringify(out, null, 2)
|
|
2359
|
+
: `函数联动已创建: [${linkageId}] ${effect.effectName} / ${event.name} ← ${triggerCols.map((c) => toBareLabel(c)).join('、') || '(表单级)'} → ${toBareLabel(targetCol)}`);
|
|
2360
|
+
}
|
|
2361
|
+
catch (e) {
|
|
2362
|
+
console.error(`新增函数联动失败: ${e.message}`);
|
|
2363
|
+
process.exitCode = 1;
|
|
2364
|
+
}
|
|
2365
|
+
});
|
|
2366
|
+
flCmd.command('update')
|
|
2367
|
+
.description('改已有函数联动的触发条件/生效维度/名称/启停(不传的项沿用现有)')
|
|
2368
|
+
.argument('<formId>', '流程表单 formId')
|
|
2369
|
+
.argument('<linkageId>', '联动 ID')
|
|
2370
|
+
.option('--event <event>', '改触发事件')
|
|
2371
|
+
.option('--trigger <fields...>', '改触发字段')
|
|
2372
|
+
.option('--effect <dimension>', '改生效维度: form / formLayout / workFlow / includeNode')
|
|
2373
|
+
.option('--workflow-id <id>', '流程 ID(refId;不给沿用记录里的)')
|
|
2374
|
+
.option('--node <node>', 'includeNode 的节点')
|
|
2375
|
+
.option('--layout-id <id>', 'formLayout 指定的布局')
|
|
2376
|
+
.option('--name <name>', '改联动名称')
|
|
2377
|
+
.option('--state <onoff>', '启用或停用: on / off')
|
|
2378
|
+
.action(async (formId, linkageId, cmdOpts) => {
|
|
2379
|
+
try {
|
|
2380
|
+
const opts = program.opts();
|
|
2381
|
+
const auth = await AuthSession.fromOptions(opts);
|
|
2382
|
+
if (!auth)
|
|
2383
|
+
throw new Error('无法加载认证');
|
|
2384
|
+
const client = new ApiClient(auth);
|
|
2385
|
+
const baseUrl = auth.getBaseUrl();
|
|
2386
|
+
const ebb = { ebbusinessid: formId };
|
|
2387
|
+
const record = await wfReadLinkage(client, baseUrl, formId, linkageId, cmdOpts.workflowId);
|
|
2388
|
+
const refId = String(record?.refId || cmdOpts.workflowId || formId);
|
|
2389
|
+
const cur = extractTriggerState(record);
|
|
2390
|
+
const { events, columns } = await wfLinkageContext(client, baseUrl, formId, cmdOpts.workflowId);
|
|
2391
|
+
const event = resolveDrivingEvent(events, cmdOpts.event || cur.eventType);
|
|
2392
|
+
const triggerInput = cmdOpts.trigger?.length ? cmdOpts.trigger : cur.triggerIds;
|
|
2393
|
+
const triggerCols = [];
|
|
2394
|
+
for (const t of triggerInput) {
|
|
2395
|
+
const col = findColumnById(columns, t) || (() => { try {
|
|
2396
|
+
return resolveDrivingColumn(columns, t, FLOW_ROUTE);
|
|
2397
|
+
}
|
|
2398
|
+
catch {
|
|
2399
|
+
return undefined;
|
|
2400
|
+
} })();
|
|
2401
|
+
if (!col)
|
|
2402
|
+
throw new Error(`触发字段「${t}」在当前表单里找不到了(可能已被删除)。用 wf-form formula-linkage columns 复核`);
|
|
2403
|
+
triggerCols.push(col);
|
|
2404
|
+
}
|
|
2405
|
+
const monitorActions = buildMonitorActions(event, triggerCols);
|
|
2406
|
+
const effect = cmdOpts.effect
|
|
2407
|
+
? (await wfEffectOf(client, baseUrl, formId, cmdOpts)).effect
|
|
2408
|
+
: extractEffect(record);
|
|
2409
|
+
let linkageState = record?.linkageState !== false;
|
|
2410
|
+
if (cmdOpts.state) {
|
|
2411
|
+
const v = String(cmdOpts.state).toLowerCase();
|
|
2412
|
+
if (v !== 'on' && v !== 'off')
|
|
2413
|
+
throw new Error('--state 只接受 on / off');
|
|
2414
|
+
linkageState = v === 'on';
|
|
2415
|
+
}
|
|
2416
|
+
const res = await client.post(`${baseUrl}${buildLinkageApiUrl(FLOW_ROUTE, 'updateFormDataLinkage')}`, buildLinkageUpdatePayload(record, {
|
|
2417
|
+
appId: '', objId: '',
|
|
2418
|
+
linkageName: cmdOpts.name || String(record?.linkageName || ''),
|
|
2419
|
+
linkageState, monitorActions, effect, route: FLOW_ROUTE, refId,
|
|
2420
|
+
}), ebb);
|
|
2421
|
+
if (res?.code !== 200 || !res?.status)
|
|
2422
|
+
throw new Error(`更新失败: ${res?.msg || '未知错误'}`);
|
|
2423
|
+
await client.post(`${baseUrl}${buildLinkageApiUrl(FLOW_ROUTE, 'preCheck')}`, buildPreCheckBody(FLOW_ROUTE, { formId, linkageIds: [linkageId], refId }), ebb);
|
|
2424
|
+
const after = summarizeLinkage(await wfReadLinkage(client, baseUrl, formId, linkageId, refId));
|
|
2425
|
+
const out = { success: true, linkageId, name: after.name, state: after.state, effect: wfEffectLabel(after.effect), event: after.eventNames.join('、'), triggers: after.triggerNames };
|
|
2426
|
+
console.log(opts.json ? JSON.stringify(out, null, 2)
|
|
2427
|
+
: `函数联动已更新: [${linkageId}] ${after.name} (${after.state ? '启用' : '停用'}) ${wfEffectLabel(after.effect)} / ${after.eventNames.join('、')} ← ${after.triggerNames.join('、')}`);
|
|
2428
|
+
}
|
|
2429
|
+
catch (e) {
|
|
2430
|
+
console.error(`更新函数联动失败: ${e.message}`);
|
|
2431
|
+
process.exitCode = 1;
|
|
2432
|
+
}
|
|
2433
|
+
});
|
|
2434
|
+
flCmd.command('delete')
|
|
2435
|
+
.description('删除函数联动(支持批量)')
|
|
2436
|
+
.argument('<formId>', '流程表单 formId')
|
|
2437
|
+
.argument('<linkageIds...>', '联动 ID')
|
|
2438
|
+
.option('--workflow-id <id>', '流程 ID(refId;不给按 formId 兜底)')
|
|
2439
|
+
.action(async (formId, linkageIds, cmdOpts) => {
|
|
2440
|
+
try {
|
|
2441
|
+
const opts = program.opts();
|
|
2442
|
+
const auth = await AuthSession.fromOptions(opts);
|
|
2443
|
+
if (!auth)
|
|
2444
|
+
throw new Error('无法加载认证');
|
|
2445
|
+
const client = new ApiClient(auth);
|
|
2446
|
+
const baseUrl = auth.getBaseUrl();
|
|
2447
|
+
const refId = cmdOpts.workflowId || formId;
|
|
2448
|
+
const res = await client.post(`${baseUrl}${buildLinkageApiUrl(FLOW_ROUTE, 'deleteFormDataLinkage')}`, buildLinkageDeleteBody(FLOW_ROUTE, { ids: linkageIds, formId, refId }), { ebbusinessid: formId });
|
|
2449
|
+
if (res?.code !== 200 || !res?.status)
|
|
2450
|
+
throw new Error(`删除失败: ${res?.msg || '未知错误'}`);
|
|
2451
|
+
const deleted = res?.data || [];
|
|
2452
|
+
if (!deleted.length)
|
|
2453
|
+
throw new Error('没有删掉任何一条(回显 0 条)。先 list 核对 id 是否存在、是否属于本表单');
|
|
2454
|
+
// 服务端回显的 id 与传入的 linkageId 不是同一套(与 eb 表那条路由一样),
|
|
2455
|
+
// 所以打印**用户传的 id**,回显只在数量对不上时提一句
|
|
2456
|
+
const mismatch = deleted.length !== linkageIds.length;
|
|
2457
|
+
console.log(opts.json ? JSON.stringify({ success: true, deleted: linkageIds, serverEcho: deleted }, null, 2)
|
|
2458
|
+
: `已删除 ${linkageIds.length} 条函数联动: ${linkageIds.join(', ')}`);
|
|
2459
|
+
if (mismatch)
|
|
2460
|
+
console.error(` ⚠ 服务端回显 ${deleted.length} 条(${deleted.join(', ')}),与请求的 ${linkageIds.length} 条对不上,请用 list 复核`);
|
|
2461
|
+
}
|
|
2462
|
+
catch (e) {
|
|
2463
|
+
console.error(`删除函数联动失败: ${e.message}`);
|
|
2464
|
+
process.exitCode = 1;
|
|
2465
|
+
}
|
|
2466
|
+
});
|
|
2003
2467
|
return wfForm;
|
|
2004
2468
|
}
|
|
2469
|
+
/** `--expression @file` 支持:公式里常带引号与换行,走文件比在命令行里转义省事。 */
|
|
2470
|
+
function readExpressionArg(raw) {
|
|
2471
|
+
const v = String(raw || '');
|
|
2472
|
+
if (!v.startsWith('@'))
|
|
2473
|
+
return v;
|
|
2474
|
+
try {
|
|
2475
|
+
return readFileSync(v.slice(1), 'utf-8').trim();
|
|
2476
|
+
}
|
|
2477
|
+
catch (e) {
|
|
2478
|
+
throw new Error(`读取表达式文件失败: ${v.slice(1)}(${e?.message || e})`);
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
/** 生效维度的可读写法:当前表单 / 表单布局(布局名)/ 当前工作流(流程名【V1】)/ 选择节点(节点名)。 */
|
|
2482
|
+
function wfEffectLabel(e) {
|
|
2483
|
+
if (!e || e.effectType === 'form')
|
|
2484
|
+
return '当前表单';
|
|
2485
|
+
return e.optionName ? `${e.effectName}(${e.optionName})` : String(e.effectName || e.effectType);
|
|
2486
|
+
}
|
|
2487
|
+
/**
|
|
2488
|
+
* 把驱动列映射成 `resolveFormulaRefs` 认的字段来源(形状对齐 eb 表 `getEbField` 的 main/detail)。
|
|
2489
|
+
*
|
|
2490
|
+
* **故意不走 `getConfig`**:那条路要先拿 `getFormLayout` 给的 layoutId,而流程表单这个接口
|
|
2491
|
+
* 对部分表单直接 500(`Form.isPhysicalTable()` 上 NPE,`form` 为 null),连既有的
|
|
2492
|
+
* `wf-form read` 都读不出来;退一步用空 layoutId 调 `getConfig`,回的是 9 个系统字段、**零业务字段**。
|
|
2493
|
+
* 而驱动列本来就是这条路由自己给的字段清单 —— 业务字段与模块字段都在里面,id/名称/类型齐备,够用。
|
|
2494
|
+
*/
|
|
2495
|
+
function drivingColumnsAsFieldSource(columns) {
|
|
2496
|
+
const business = columns.filter((c) => String(c.groupId) !== 'moduleField');
|
|
2497
|
+
const strayDetail = business.find((c) => c.address && String(c.address) !== '主表');
|
|
2498
|
+
if (strayDetail) {
|
|
2499
|
+
// 没有实测过流程表单的明细字段在驱动列里长什么样(连 detailTableId 都拿不到),
|
|
2500
|
+
// 与其猜一个 sFormId 发出去,不如停下来
|
|
2501
|
+
throw new Error(`驱动列里出现了非主表字段「${strayDetail.name}」(address=${strayDetail.address})。`
|
|
2502
|
+
+ '流程表单的明细字段尚未支持,请反馈这条表单的 findFormDrivingColumns 返回');
|
|
2503
|
+
}
|
|
2504
|
+
return {
|
|
2505
|
+
mainFields: business.map((c) => ({
|
|
2506
|
+
id: c.id, showName: toBareLabel(c), dataKey: c.dataKey, componentKey: c.descType,
|
|
2507
|
+
})),
|
|
2508
|
+
detailTables: [],
|
|
2509
|
+
};
|
|
2510
|
+
}
|
|
2005
2511
|
//# sourceMappingURL=wf-form.js.map
|