@nocobase/client-v2 2.2.0-beta.3 → 2.2.0-beta.6

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.
Files changed (133) hide show
  1. package/es/RouteRepository.d.ts +21 -6
  2. package/es/components/form/JsonTextArea.d.ts +2 -1
  3. package/es/components/form/VariableJsonTextArea.d.ts +19 -0
  4. package/es/components/form/index.d.ts +1 -0
  5. package/es/components/index.d.ts +1 -0
  6. package/es/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.d.ts +2 -0
  7. package/es/flow/admin-shell/admin-layout/AdminLayoutMenuFlowUtils.d.ts +2 -1
  8. package/es/flow/admin-shell/admin-layout/AdminLayoutMenuModels.d.ts +2 -0
  9. package/es/flow/admin-shell/admin-layout/AdminLayoutMenuUtils.d.ts +3 -2
  10. package/es/flow/admin-shell/admin-layout/AdminLayoutSlotModels.d.ts +4 -0
  11. package/es/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.d.ts +6 -0
  12. package/es/flow/components/FieldAssignRulesEditor.d.ts +3 -1
  13. package/es/flow/models/base/GridModel.d.ts +1 -1
  14. package/es/flow/models/blocks/filter-form/FilterFormBlockModel.d.ts +5 -0
  15. package/es/flow/models/blocks/form/FormBlockModel.d.ts +4 -0
  16. package/es/flow/models/blocks/form/value-runtime/rules.d.ts +21 -0
  17. package/es/flow/models/blocks/form/value-runtime/runtime.d.ts +21 -0
  18. package/es/flow/models/blocks/form/value-runtime/types.d.ts +2 -2
  19. package/es/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.d.ts +2 -0
  20. package/es/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableColumnModel.d.ts +1 -0
  21. package/es/flow/utils/dateTimeDisplayProps.d.ts +49 -0
  22. package/es/flow-compat/FieldValidation.d.ts +2 -1
  23. package/es/index.d.ts +2 -1
  24. package/es/index.mjs +167 -121
  25. package/lib/index.js +167 -121
  26. package/package.json +7 -7
  27. package/src/RouteRepository.ts +126 -24
  28. package/src/__tests__/RouteRepository.test.ts +216 -0
  29. package/src/__tests__/exports.test.ts +16 -0
  30. package/src/__tests__/settings-center.test.tsx +33 -0
  31. package/src/components/form/JsonTextArea.tsx +21 -11
  32. package/src/components/form/VariableJsonTextArea.tsx +175 -0
  33. package/src/components/form/__tests__/JsonTextArea.test.tsx +43 -0
  34. package/src/components/form/__tests__/VariableJsonTextArea.test.tsx +86 -0
  35. package/src/components/form/index.tsx +1 -0
  36. package/src/components/index.ts +1 -0
  37. package/src/flow/__tests__/FlowRoute.test.tsx +443 -5
  38. package/src/flow/actions/__tests__/fieldLinkageRules.scopeDepth.test.ts +150 -1
  39. package/src/flow/actions/__tests__/linkageAssignField.legacy.test.ts +135 -0
  40. package/src/flow/actions/__tests__/linkageRules.hiddenSync.restore.test.ts +19 -5
  41. package/src/flow/actions/__tests__/linkageRules.subFormSetFieldProps.test.ts +92 -0
  42. package/src/flow/actions/customVariable.tsx +1 -2
  43. package/src/flow/actions/dateTimeFormat.tsx +42 -28
  44. package/src/flow/actions/linkageRules.tsx +122 -34
  45. package/src/flow/actions/runjs.tsx +2 -14
  46. package/src/flow/actions/validation.tsx +62 -30
  47. package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +33 -10
  48. package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.test.tsx +310 -0
  49. package/src/flow/admin-shell/admin-layout/AdminLayoutEntryGuard.tsx +44 -8
  50. package/src/flow/admin-shell/admin-layout/AdminLayoutMenuFlowUtils.ts +5 -3
  51. package/src/flow/admin-shell/admin-layout/AdminLayoutMenuModels.tsx +61 -9
  52. package/src/flow/admin-shell/admin-layout/AdminLayoutMenuUtils.tsx +71 -8
  53. package/src/flow/admin-shell/admin-layout/AdminLayoutModel.tsx +1 -1
  54. package/src/flow/admin-shell/admin-layout/AdminLayoutSlotModels.tsx +21 -8
  55. package/src/flow/admin-shell/admin-layout/HelpLite.tsx +1 -3
  56. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutComponent.test.tsx +188 -0
  57. package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutMenuModels.test.ts +99 -0
  58. package/src/flow/admin-shell/admin-layout/__tests__/TopbarActionsBar.test.tsx +166 -2
  59. package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.test.ts +20 -0
  60. package/src/flow/admin-shell/admin-layout/resolveAdminRouteRuntimeTarget.ts +33 -5
  61. package/src/flow/components/DefaultValue.tsx +1 -2
  62. package/src/flow/components/DynamicFlowsIcon.tsx +447 -126
  63. package/src/flow/components/FieldAssignRulesEditor.tsx +62 -12
  64. package/src/flow/components/FlowRoute.tsx +56 -11
  65. package/src/flow/components/__tests__/DynamicFlowsIcon.test.tsx +148 -2
  66. package/src/flow/components/__tests__/FieldAssignRulesEditor.test.tsx +81 -4
  67. package/src/flow/components/code-editor/__tests__/useCodeRunner.test.tsx +2 -17
  68. package/src/flow/components/code-editor/hooks/useCodeRunner.ts +2 -14
  69. package/src/flow/components/code-editor/runjsDiagnostics.ts +8 -45
  70. package/src/flow/flows/editMarkdownFlow.tsx +1 -1
  71. package/src/flow/index.ts +1 -1
  72. package/src/flow/internal/utils/operatorSchemaHelper.ts +15 -1
  73. package/src/flow/models/actions/JSActionModel.tsx +2 -7
  74. package/src/flow/models/actions/JSCollectionActionModel.tsx +2 -7
  75. package/src/flow/models/actions/JSItemActionModel.tsx +2 -7
  76. package/src/flow/models/actions/JSRecordActionModel.tsx +2 -7
  77. package/src/flow/models/base/ActionModel.tsx +12 -1
  78. package/src/flow/models/base/GridModel.tsx +38 -7
  79. package/src/flow/models/base/PageModel/PageModel.tsx +4 -1
  80. package/src/flow/models/base/PageModel/__tests__/PageModel.test.ts +28 -4
  81. package/src/flow/models/base/__tests__/ActionModel.test.ts +83 -0
  82. package/src/flow/models/base/__tests__/GridModel.dragSnapshotContainer.test.ts +239 -1
  83. package/src/flow/models/base/__tests__/transformRowsToSingleColumn.test.ts +48 -0
  84. package/src/flow/models/blocks/filter-form/FilterFormBlockModel.tsx +31 -3
  85. package/src/flow/models/blocks/filter-form/FilterFormJSActionModel.tsx +2 -7
  86. package/src/flow/models/blocks/filter-form/__tests__/defaultValues.wiring.test.ts +77 -0
  87. package/src/flow/models/blocks/filter-manager/flow-actions/__tests__/customizeFilterRender.test.tsx +56 -1
  88. package/src/flow/models/blocks/form/EditFormModel.tsx +1 -0
  89. package/src/flow/models/blocks/form/FormBlockModel.tsx +7 -0
  90. package/src/flow/models/blocks/form/JSFormActionModel.tsx +2 -7
  91. package/src/flow/models/blocks/form/__tests__/FormBlockModel.test.tsx +17 -0
  92. package/src/flow/models/blocks/form/value-runtime/__tests__/runtime.test.ts +880 -102
  93. package/src/flow/models/blocks/form/value-runtime/rules.ts +445 -13
  94. package/src/flow/models/blocks/form/value-runtime/runtime.ts +257 -13
  95. package/src/flow/models/blocks/form/value-runtime/types.ts +2 -2
  96. package/src/flow/models/blocks/js-block/JSBlock.tsx +2 -7
  97. package/src/flow/models/blocks/table/JSColumnModel.tsx +1 -9
  98. package/src/flow/models/blocks/table/TableActionsColumnModel.tsx +1 -1
  99. package/src/flow/models/blocks/table/TableBlockModel.tsx +13 -3
  100. package/src/flow/models/blocks/table/TableColumnModel.tsx +36 -3
  101. package/src/flow/models/blocks/table/__tests__/TableActionsColumnModel.test.tsx +54 -0
  102. package/src/flow/models/blocks/table/__tests__/TableBlockModel.mobileSettingsButtons.test.tsx +78 -0
  103. package/src/flow/models/blocks/table/__tests__/TableColumnModel.test.tsx +159 -1
  104. package/src/flow/models/fields/AssociationFieldModel/AssociationFieldModel.tsx +1 -1
  105. package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/PopupSubTableFieldModel.tsx +29 -6
  106. package/src/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.tsx +16 -4
  107. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableColumnModel.tsx +24 -1
  108. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/SubTableField.tsx +13 -1
  109. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/__tests__/SubTableColumnModel.rowRecord.test.ts +12 -0
  110. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/__tests__/SubTableFieldModel.reset.test.ts +180 -0
  111. package/src/flow/models/fields/AssociationFieldModel/SubTableFieldModel/index.tsx +6 -4
  112. package/src/flow/models/fields/AssociationFieldModel/__tests__/AssociationFieldModel.updateAssociation.test.ts +72 -0
  113. package/src/flow/models/fields/AssociationFieldModel/__tests__/RecordPickerFieldModel.itemContext.test.ts +23 -0
  114. package/src/flow/models/fields/ClickableFieldModel.tsx +5 -0
  115. package/src/flow/models/fields/DisplayDateTimeFieldModel.tsx +29 -1
  116. package/src/flow/models/fields/InputFieldModel.tsx +14 -22
  117. package/src/flow/models/fields/JSEditableFieldModel.tsx +2 -11
  118. package/src/flow/models/fields/JSFieldModel.tsx +2 -7
  119. package/src/flow/models/fields/JSItemModel.tsx +2 -14
  120. package/src/flow/models/fields/SelectFieldModel.tsx +6 -4
  121. package/src/flow/models/fields/__tests__/DisplayDateTimeFieldModel.test.tsx +96 -0
  122. package/src/flow/models/fields/__tests__/InputFieldModel.test.tsx +17 -0
  123. package/src/flow/models/fields/__tests__/SelectFieldModel.test.tsx +43 -0
  124. package/src/flow/models/topbar/TopbarActionModel.tsx +93 -10
  125. package/src/flow/utils/__tests__/dateTimeFormat.test.ts +258 -0
  126. package/src/flow/utils/dateTimeDisplayProps.ts +135 -0
  127. package/src/flow-compat/FieldValidation.tsx +122 -60
  128. package/src/flow-compat/Popover.tsx +43 -4
  129. package/src/flow-compat/__tests__/Popover.test.tsx +34 -0
  130. package/src/index.ts +8 -1
  131. package/src/layout-manager/__tests__/LayoutRoute.test.tsx +41 -1
  132. package/src/settings-center/AdminSettingsLayout.tsx +3 -0
  133. package/src/settings-center/plugin-manager/index.tsx +3 -0
@@ -69,6 +69,72 @@ describe('linkage assign actions - legacy params', () => {
69
69
  expect(setProps).not.toHaveBeenCalledWith(fieldModel, { value: 'default-in-update' });
70
70
  });
71
71
 
72
+ it('linkageAssignField should mark override mode for field targets', async () => {
73
+ const fieldModel: any = { uid: 'f-override', fieldPath: 'a.b' };
74
+ const ctx: any = {
75
+ model: {
76
+ subModels: { grid: { subModels: { items: [fieldModel] } } },
77
+ },
78
+ engine: { getModel: vi.fn(() => ({ fieldPath: 'a.b' })) },
79
+ app: { jsonLogic: { apply: vi.fn() } },
80
+ };
81
+ const setProps = vi.fn();
82
+
83
+ await linkageAssignField.handler(ctx, {
84
+ value: [
85
+ {
86
+ key: 'r-override',
87
+ enable: true,
88
+ targetPath: 'a.b',
89
+ mode: 'override',
90
+ condition: { logic: '$and', items: [] },
91
+ value: 'override-value',
92
+ },
93
+ ],
94
+ setProps,
95
+ });
96
+
97
+ expect(setProps).toHaveBeenCalledTimes(1);
98
+ const [, props] = setProps.mock.calls[0];
99
+ expect(props).toMatchObject({
100
+ value: 'override-value',
101
+ __linkageAssignMode: 'override',
102
+ });
103
+ });
104
+
105
+ it('linkageAssignField should emit override patches for targets without form item models', async () => {
106
+ const ctx: any = {
107
+ model: { subModels: { grid: { subModels: { items: [] } } } },
108
+ engine: { getModel: vi.fn(() => null) },
109
+ app: { jsonLogic: { apply: vi.fn() } },
110
+ };
111
+ const setProps = vi.fn();
112
+ const addFormValuePatch = vi.fn();
113
+
114
+ await linkageAssignField.handler(ctx, {
115
+ value: [
116
+ {
117
+ key: 'r-override-direct',
118
+ enable: true,
119
+ targetPath: 'user.name',
120
+ mode: 'override',
121
+ condition: { logic: '$and', items: [] },
122
+ value: 'override-direct',
123
+ },
124
+ ],
125
+ setProps,
126
+ addFormValuePatch,
127
+ });
128
+
129
+ expect(setProps).not.toHaveBeenCalled();
130
+ expect(addFormValuePatch).toHaveBeenCalledWith({
131
+ path: 'user.name',
132
+ value: 'override-direct',
133
+ whenEmpty: false,
134
+ mode: 'override',
135
+ });
136
+ });
137
+
72
138
  it('subFormLinkageAssignField should apply legacy object params at runtime', () => {
73
139
  const forkModel: any = {
74
140
  uid: 'f1',
@@ -381,6 +447,75 @@ describe('linkage assign actions - legacy params', () => {
381
447
  expect(addFormValuePatch).toHaveBeenCalledTimes(1);
382
448
  });
383
449
 
450
+ it('subFormLinkageAssignField should skip override patch after user edits the target path', () => {
451
+ const ctx: any = {
452
+ model: {
453
+ uid: 'sub-form-override-path',
454
+ getAclActionName: vi.fn(() => 'create'),
455
+ context: {},
456
+ parent: {
457
+ getStepParams: (flowKey: string, stepKey: string) => {
458
+ if (flowKey === 'fieldSettings' && stepKey === 'init') {
459
+ return { fieldPath: 'M2M.M2M' };
460
+ }
461
+ return {};
462
+ },
463
+ },
464
+ subModels: { grid: { subModels: { items: [] } } },
465
+ },
466
+ engine: {
467
+ getModel: vi.fn(() => null),
468
+ },
469
+ app: { jsonLogic: { apply: vi.fn() } },
470
+ };
471
+ const addFormValuePatch = vi.fn();
472
+
473
+ subFormLinkageAssignField.handler(ctx, {
474
+ value: [
475
+ {
476
+ key: 'r-override-path-1',
477
+ enable: true,
478
+ targetPath: 'Name',
479
+ mode: 'override',
480
+ condition: { logic: '$and', items: [] },
481
+ value: 'override-1',
482
+ },
483
+ ],
484
+ addFormValuePatch,
485
+ setProps: vi.fn(),
486
+ });
487
+
488
+ expect(addFormValuePatch).toHaveBeenCalledTimes(1);
489
+ expect(addFormValuePatch).toHaveBeenNthCalledWith(1, {
490
+ path: 'M2M.M2M.Name',
491
+ value: 'override-1',
492
+ whenEmpty: false,
493
+ mode: 'override',
494
+ });
495
+
496
+ ctx.inputArgs = {
497
+ source: 'user',
498
+ changedPaths: [['M2M', 'M2M', 'Name']],
499
+ };
500
+
501
+ subFormLinkageAssignField.handler(ctx, {
502
+ value: [
503
+ {
504
+ key: 'r-override-path-2',
505
+ enable: true,
506
+ targetPath: 'Name',
507
+ mode: 'override',
508
+ condition: { logic: '$and', items: [] },
509
+ value: 'override-2',
510
+ },
511
+ ],
512
+ addFormValuePatch,
513
+ setProps: vi.fn(),
514
+ });
515
+
516
+ expect(addFormValuePatch).toHaveBeenCalledTimes(1);
517
+ });
518
+
384
519
  it('linkageAssignField should evaluate RunJS value before assign', async () => {
385
520
  const fieldModel: any = { uid: 'f-runjs-assign', fieldPath: 'a.b' };
386
521
  const runjs = vi.fn(async () => ({ success: true, value: 'from-runjs' }));
@@ -27,12 +27,12 @@ describe('linkageRules hidden state propagation', () => {
27
27
  const hostModel: any = {
28
28
  uid: 'host',
29
29
  hidden: false,
30
- context: { blockModel },
30
+ context: { blockModel, fieldPathArray: ['children'] },
31
31
  __allModels: [],
32
32
  setProps: vi.fn(),
33
33
  getFlow: vi.fn(() => ({})),
34
34
  getStepParams: vi.fn((_flowKey: string, stepKey: string) => {
35
- if (stepKey === 'init') return { fieldPath: 'org_m2o' };
35
+ if (stepKey === 'init') return { fieldPath: 'children' };
36
36
  return undefined;
37
37
  }),
38
38
  translate: (s: string) => s,
@@ -41,10 +41,22 @@ describe('linkageRules hidden state propagation', () => {
41
41
  const sameTargetModel: any = {
42
42
  uid: 'same-target',
43
43
  hidden: false,
44
- context: { blockModel },
44
+ context: { blockModel, fieldPathArray: ['children'] },
45
45
  setProps: vi.fn(),
46
46
  getStepParams: vi.fn((_flowKey: string, stepKey: string) => {
47
- if (stepKey === 'init') return { fieldPath: 'org_m2o' };
47
+ if (stepKey === 'init') return { fieldPath: 'children' };
48
+ return undefined;
49
+ }),
50
+ translate: (s: string) => s,
51
+ };
52
+
53
+ const nestedColumnModel: any = {
54
+ uid: 'nested-column',
55
+ hidden: true,
56
+ context: { blockModel, fieldPathArray: ['children'] },
57
+ setProps: vi.fn(),
58
+ getStepParams: vi.fn((_flowKey: string, stepKey: string) => {
59
+ if (stepKey === 'init') return { fieldPath: 'children.children' };
48
60
  return undefined;
49
61
  }),
50
62
  translate: (s: string) => s,
@@ -52,7 +64,7 @@ describe('linkageRules hidden state propagation', () => {
52
64
 
53
65
  const engine = {
54
66
  forEachModel: (visitor: (m: any) => void) => {
55
- [hostModel, sameTargetModel].forEach(visitor);
67
+ [hostModel, sameTargetModel, nestedColumnModel].forEach(visitor);
56
68
  },
57
69
  };
58
70
 
@@ -92,9 +104,11 @@ describe('linkageRules hidden state propagation', () => {
92
104
  });
93
105
  expect(hostModel.hidden).toBe(true);
94
106
  expect(sameTargetModel.hidden).toBe(true);
107
+ expect(nestedColumnModel.hidden).toBe(true);
95
108
 
96
109
  await actionLinkageRules.handler(ctx, { value: [] });
97
110
  expect(hostModel.hidden).toBe(false);
98
111
  expect(sameTargetModel.hidden).toBe(false);
112
+ expect(nestedColumnModel.hidden).toBe(true);
99
113
  });
100
114
  });
@@ -728,6 +728,98 @@ describe('linkageSetFieldProps action', () => {
728
728
  expect(form.setFieldValue).not.toHaveBeenCalled();
729
729
  });
730
730
 
731
+ it('should not clear the parent field when a nested same-name field inherits the parent path', async () => {
732
+ const setFormValues = vi.fn(async () => undefined);
733
+ const form = {
734
+ getFieldValue: vi.fn((path: Array<string | number>) => {
735
+ if (JSON.stringify(path) === JSON.stringify(['children', 'children'])) {
736
+ return [{ title: 'nested' }];
737
+ }
738
+ if (JSON.stringify(path) === JSON.stringify(['children'])) {
739
+ return [{ title: 'parent' }];
740
+ }
741
+ return undefined;
742
+ }),
743
+ setFieldValue: vi.fn(),
744
+ };
745
+ const fieldModel: any = {
746
+ uid: 'nested-children-field',
747
+ hidden: false,
748
+ context: {
749
+ form,
750
+ fieldPathArray: ['children'],
751
+ },
752
+ props: {
753
+ label: 'Children',
754
+ },
755
+ getStepParams: vi.fn((flowKey: string, stepKey: string) => {
756
+ if (flowKey === 'fieldSettings' && stepKey === 'init') {
757
+ return { fieldPath: 'children.children' };
758
+ }
759
+ }),
760
+ setProps(key: any, value?: any) {
761
+ if (typeof key === 'string') {
762
+ this.props[key] = value;
763
+ } else {
764
+ this.props = { ...this.props, ...key };
765
+ }
766
+ },
767
+ };
768
+ const ctx: any = {
769
+ app: {
770
+ jsonLogic: {
771
+ apply: vi.fn(() => true),
772
+ },
773
+ },
774
+ model: {
775
+ context: { form },
776
+ subModels: {
777
+ grid: {
778
+ subModels: {
779
+ items: [fieldModel],
780
+ },
781
+ },
782
+ },
783
+ },
784
+ setFormValues,
785
+ getAction: (name: string) => (name === 'linkageSetFieldProps' ? linkageSetFieldProps : null),
786
+ resolveJsonTemplate: vi.fn(async (value) => value),
787
+ };
788
+
789
+ await fieldLinkageRules.handler(ctx, {
790
+ value: [
791
+ {
792
+ key: 'rule-1',
793
+ enable: true,
794
+ condition: { logic: '$and', items: [] },
795
+ actions: [
796
+ {
797
+ key: 'action-1',
798
+ name: 'linkageSetFieldProps',
799
+ params: {
800
+ value: {
801
+ fields: ['nested-children-field'],
802
+ state: 'hidden',
803
+ },
804
+ },
805
+ },
806
+ ],
807
+ },
808
+ ],
809
+ });
810
+
811
+ expect(fieldModel.hidden).toBe(true);
812
+ expect(setFormValues).toHaveBeenCalledWith(
813
+ [{ path: ['children', 'children'], value: undefined }],
814
+ expect.objectContaining({ source: 'linkage' }),
815
+ );
816
+ expect(setFormValues).not.toHaveBeenCalledWith(
817
+ [{ path: ['children'], value: undefined }],
818
+ expect.objectContaining({ source: 'linkage' }),
819
+ );
820
+ expect(form.setFieldValue).not.toHaveBeenCalled();
821
+ });
822
+
731
823
  it('should keep hidden clear after same-round assignment for the same field', async () => {
732
824
  const formValues: { name?: string } = {};
733
825
  const setFormValues = vi.fn(async (patches: Array<{ path: Array<string | number>; value: string | undefined }>) => {
@@ -12,7 +12,6 @@ import {
12
12
  defineAction,
13
13
  isRunJSValue,
14
14
  normalizeRunJSValue,
15
- runjsWithSafeGlobals,
16
15
  tExpr,
17
16
  type RunJSValue,
18
17
  useFlowContext,
@@ -43,7 +42,7 @@ export const customVariable = defineAction({
43
42
  if (variable.type === 'runjs') {
44
43
  const getFunction = async () => {
45
44
  const { code, version } = normalizeRunJSValue(variable.runjs);
46
- return runjsWithSafeGlobals(ctx, code, { version });
45
+ return ctx.runjs(code, undefined, { version });
47
46
  };
48
47
  const metaFunction = () => ({
49
48
  title: variable.title,
@@ -11,13 +11,36 @@ import { css } from '@emotion/css';
11
11
  import { defineAction, tExpr } from '@nocobase/flow-engine';
12
12
  import { getPickerFormat } from '@nocobase/utils/client';
13
13
  import { DateFormatCom, ExpiresRadio } from '../components';
14
+ import {
15
+ getDateTimeFormatCollectionField,
16
+ isDateOnlyCollectionField,
17
+ isTimeCollectionField,
18
+ resolveDateTimeDisplayProps,
19
+ } from '../utils/dateTimeDisplayProps';
20
+
21
+ const isTableColumnFieldSubModel = (model) => {
22
+ const parent = model?.parent;
23
+ return (
24
+ parent?.subModels?.field === model &&
25
+ (parent?.use === 'TableColumnModel' || parent?.constructor?.name === 'TableColumnModel')
26
+ );
27
+ };
28
+
29
+ const syncTableColumnDateTimeFormatProps = (ctx, props) => {
30
+ const model = ctx.model;
31
+ if (!isTableColumnFieldSubModel(model) || !model?.parent?.collectionField?.isAssociationField?.()) {
32
+ return;
33
+ }
34
+
35
+ model.parent.setProps(props);
36
+ };
14
37
 
15
38
  export const dateTimeFormat = defineAction({
16
39
  title: tExpr('Date display format'),
17
40
  name: 'dateDisplayFormat',
18
41
  uiSchema: (ctx) => {
19
- const { collectionField } = ctx.model.context as any;
20
- const isTimeField = collectionField.type === 'time' || collectionField.interface === 'time';
42
+ const collectionField = getDateTimeFormatCollectionField({ model: ctx.model });
43
+ const isTimeField = isTimeCollectionField(collectionField);
21
44
  const timeFormatField = {
22
45
  type: 'string',
23
46
  title: '{{t("Time format")}}',
@@ -43,7 +66,7 @@ export const dateTimeFormat = defineAction({
43
66
  (field) => {
44
67
  if (!isTimeField) {
45
68
  const { showTime, picker } = field.form.values || {};
46
- field.hidden = !showTime || picker !== 'date';
69
+ field.hidden = isDateOnlyCollectionField(collectionField) || !showTime || picker !== 'date';
47
70
  }
48
71
  },
49
72
  ],
@@ -146,10 +169,11 @@ export const dateTimeFormat = defineAction({
146
169
  },
147
170
  },
148
171
  (field) => {
149
- const { collectionField } = ctx.model.context as any;
172
+ const collectionField = getDateTimeFormatCollectionField({ model: ctx.model });
150
173
  const { picker } = field.form.values || {};
151
- field.hidden = collectionField.type === 'dateOnly' || picker !== 'date';
152
- if (picker !== 'date') {
174
+ const isDateOnlyField = isDateOnlyCollectionField(collectionField);
175
+ field.hidden = isDateOnlyField || picker !== 'date';
176
+ if (isDateOnlyField || picker !== 'date') {
153
177
  field.value = false;
154
178
  }
155
179
  },
@@ -159,34 +183,24 @@ export const dateTimeFormat = defineAction({
159
183
  };
160
184
  },
161
185
  defaultParams: (ctx: any) => {
162
- const { showTime, dateFormat, format, timeFormat, picker }: any = {
163
- ...ctx.model.context.collectionField.getComponentProps(),
164
- ...ctx.model.props,
165
- };
166
- const collectionField = ctx.model.context.collectionField;
167
- const isTimeField = collectionField.type === 'time' || collectionField.interface === 'time';
186
+ const { showTime, dateFormat, timeFormat, picker } = resolveDateTimeDisplayProps({
187
+ model: ctx.model,
188
+ withDefaults: true,
189
+ });
168
190
  return {
169
191
  picker: picker || 'date',
170
192
  dateFormat: dateFormat || 'YYYY-MM-DD',
171
- timeFormat: timeFormat || (isTimeField ? format : undefined) || 'HH:mm:ss',
193
+ timeFormat: timeFormat || 'HH:mm:ss',
172
194
  showTime,
173
195
  };
174
196
  },
197
+ async beforeParamsSave(ctx: any, params) {
198
+ const props = resolveDateTimeDisplayProps({ model: ctx.model, params });
199
+ ctx.model.setProps(props);
200
+ syncTableColumnDateTimeFormatProps(ctx, props);
201
+ await ctx.model.save?.();
202
+ },
175
203
  handler(ctx: any, params) {
176
- const { collectionField } = ctx.model.context as any;
177
- const isTimeField = collectionField.type === 'time' || collectionField.interface === 'time';
178
- if (isTimeField) {
179
- const timeFormat = params?.timeFormat || params?.format || 'HH:mm:ss';
180
- ctx.model.setProps({
181
- ...params,
182
- timeFormat,
183
- format: timeFormat,
184
- });
185
- } else {
186
- ctx.model.setProps({
187
- ...params,
188
- format: params?.showTime ? `${params.dateFormat} ${params.timeFormat}` : params.dateFormat,
189
- });
190
- }
204
+ ctx.model.setProps(resolveDateTimeDisplayProps({ model: ctx.model, params }));
191
205
  },
192
206
  });