@kne/form-creator 0.1.8 → 0.1.11

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/dist/index.js CHANGED
@@ -20,7 +20,7 @@ var SelectList__default = /*#__PURE__*/_interopDefaultLegacy(SelectList);
20
20
  var FormInfo__default = /*#__PURE__*/_interopDefaultLegacy(FormInfo);
21
21
  var InfoPage__default = /*#__PURE__*/_interopDefaultLegacy(InfoPage);
22
22
 
23
- var style = {"kne-responsive-boundary":"kne-form-creator_gh14z","kne-responsive-scroll":"kne-form-creator_Kfn6L","form-creator":"kne-form-creator_Xrjrk","editor-pane":"kne-form-creator_Skfuv","preview-pane":"kne-form-creator_v4Lsp","editor-header":"kne-form-creator_WaSS-","block-list-panel":"kne-form-creator_lx8An","form-actions-setting-btn":"kne-form-creator_NekU2","panel-toolbar":"kne-form-creator_t0WxZ","add-block-btn":"kne-form-creator_16Zre","add-inline-btn":"kne-form-creator_iCYdB","ant-btn-disabled":"kne-form-creator_LdGtv","block-list":"kne-form-creator_wK5eK","block-section":"kne-form-creator_15IiK","block-kind-formInfo":"kne-form-creator_D0hoK","block-kind-list":"kne-form-creator_JdPhy","block-kind-tableList":"kne-form-creator_gzd64","block-kind-multiField":"kne-form-creator_t0iOJ","block-kind-steps":"kne-form-creator_QNF9W","step-section":"kne-form-creator_22ajp","block-section-header":"kne-form-creator_wS4rL","block-header-left":"kne-form-creator_t4awC","block-title":"kne-form-creator_wSVJf","block-summary":"kne-form-creator_GzeW8","block-header-actions":"kne-form-creator_Ue-nT","block-body":"kne-form-creator_je1H0","item-blocks-section":"kne-form-creator_wq4bT","nested-block-list":"kne-form-creator_4NWH4","block-section-nested":"kne-form-creator_mUKom","add-field-dropdown":"kne-form-creator_9JS0d","add-field-dropdown-item":"kne-form-creator_Ql1z3","add-field-dropdown-item-icon":"kne-form-creator_ZHB5O","add-field-dropdown-item-desc":"kne-form-creator_dcsOS","add-field-dropdown-divider":"kne-form-creator_CUK0H","add-field-dropdown-label":"kne-form-creator_bPJ-2","section-toolbar":"kne-form-creator_LUO8S","section-toolbar-label":"kne-form-creator_7KQ79","field-list":"kne-form-creator_-B7WZ","step-list":"kne-form-creator_kc1pH","step-section-header":"kne-form-creator_wkhEX","step-section-title":"kne-form-creator_NBinE","step-index":"kne-form-creator_CCKZZ","field-row":"kne-form-creator_XMkdt","field-row-index":"kne-form-creator_a-cDo","field-row-main":"kne-form-creator_ftlwp","inline-empty":"kne-form-creator_yP-RF","action-group":"kne-form-creator_773yo","hover-reveal":"kne-form-creator_S234h","hover-reveal-active":"kne-form-creator_AE-6r","action-btn":"kne-form-creator_mLgqh","add-block-dropdown":"kne-form-creator_vmS-e","add-block-option":"kne-form-creator_gjg2Y","add-block-option-icon":"kne-form-creator_qh1hh","add-block-option-text":"kne-form-creator_G8iJO","add-block-option-title":"kne-form-creator_ETSvm","add-block-option-desc":"kne-form-creator_O0C3l","field-empty":"kne-form-creator_Nmpfl","field-label-tips-icon":"kne-form-creator_0VVaO","preview-header":"kne-form-creator_c4BT0","preview-title":"kne-form-creator_fPkK4","preview-body":"kne-form-creator_6JntQ","schema-form":"kne-form-creator_MxCWP","schema-body":"kne-form-creator_q9ydz","schema-actions":"kne-form-creator_Y4eEH","schema-actions-inner":"kne-form-creator_FT9Zf","choice-block":"kne-form-creator_RllJe","choice-selector":"kne-form-creator_5A1eM","choice-panels":"kne-form-creator_IO0MY","choice-panels-empty":"kne-form-creator_T0nND","choice-option-panel":"kne-form-creator_FQixN","choice-option-panel-title":"kne-form-creator_ofRo2","choice-option-summary":"kne-form-creator_pksH8","field-editor-form":"kne-form-creator_PGPHL","form-actions-editor":"kne-form-creator_fchMy","form-actions-switch-field":"kne-form-creator_6JE9x","form-actions-layout-panel":"kne-form-creator_rtm9D","form-actions-align-group":"kne-form-creator_51ZsV","form-actions-layout-title":"kne-form-creator_hFeiC","form-actions-gap-slider":"kne-form-creator_Gq0bk","editor-section":"kne-form-creator_jJy85","section-divider":"kne-form-creator_zA7L-","rule-editor":"kne-form-creator_bAlGU","options-editor":"kne-form-creator_AK4yO","super-select-props":"kne-form-creator_Iawhh","field-props-editor":"kne-form-creator_Gabf2","columns-editor":"kne-form-creator_DQW1N","prop-row":"kne-form-creator_7K54P","prop-label":"kne-form-creator_HAAyH","options-item":"kne-form-creator_dnOd2","table-row-card":"kne-form-creator_cwCYp","tree-options-editor":"kne-form-creator_s3nHO","tree-options-list":"kne-form-creator_Djs-E","tree-option-node":"kne-form-creator_XAcut","tree-option-row":"kne-form-creator_4K4Rj","tree-option-fields":"kne-form-creator_-4cjc","tree-option-actions":"kne-form-creator_IjCNI","tree-option-children":"kne-form-creator_pVPGJ","tree-add-sibling":"kne-form-creator_bl46P","rule-checkbox-group":"kne-form-creator_tDgVP","rule-len-row":"kne-form-creator_ATsae","rule-len-input":"kne-form-creator_jY4Ld","rule-len-sep":"kne-form-creator_jBDC8","options-list":"kne-form-creator_GUBNS","options-row":"kne-form-creator_uohD0","options-tip":"kne-form-creator_vrTmK","icon-square-btn":"kne-form-creator_DZjCf","icon-square-btn-sm":"kne-form-creator_GAh-t","is-mobile":"kne-form-creator_LtgJz"};
23
+ var style = {"kne-responsive-boundary":"kne-form-creator_gh14z","kne-responsive-scroll":"kne-form-creator_Kfn6L","form-creator":"kne-form-creator_Xrjrk","editor-pane":"kne-form-creator_Skfuv","preview-pane":"kne-form-creator_v4Lsp","editor-header":"kne-form-creator_WaSS-","block-list-panel":"kne-form-creator_lx8An","form-actions-setting-btn":"kne-form-creator_NekU2","panel-toolbar":"kne-form-creator_t0WxZ","add-block-btn":"kne-form-creator_16Zre","add-inline-btn":"kne-form-creator_iCYdB","ant-btn-disabled":"kne-form-creator_LdGtv","block-list":"kne-form-creator_wK5eK","block-section":"kne-form-creator_15IiK","block-kind-formInfo":"kne-form-creator_D0hoK","block-kind-list":"kne-form-creator_JdPhy","block-kind-tableList":"kne-form-creator_gzd64","block-kind-multiField":"kne-form-creator_t0iOJ","block-kind-steps":"kne-form-creator_QNF9W","step-section":"kne-form-creator_22ajp","block-section-header":"kne-form-creator_wS4rL","block-header-left":"kne-form-creator_t4awC","block-title":"kne-form-creator_wSVJf","block-summary":"kne-form-creator_GzeW8","block-header-actions":"kne-form-creator_Ue-nT","block-body":"kne-form-creator_je1H0","item-blocks-section":"kne-form-creator_wq4bT","nested-block-list":"kne-form-creator_4NWH4","block-section-nested":"kne-form-creator_mUKom","add-field-dropdown":"kne-form-creator_9JS0d","add-field-dropdown-item":"kne-form-creator_Ql1z3","add-field-dropdown-item-icon":"kne-form-creator_ZHB5O","add-field-dropdown-item-desc":"kne-form-creator_dcsOS","add-field-dropdown-divider":"kne-form-creator_CUK0H","add-field-dropdown-label":"kne-form-creator_bPJ-2","section-toolbar":"kne-form-creator_LUO8S","section-toolbar-label":"kne-form-creator_7KQ79","field-list":"kne-form-creator_-B7WZ","step-list":"kne-form-creator_kc1pH","step-section-header":"kne-form-creator_wkhEX","step-section-title":"kne-form-creator_NBinE","step-section-actions":"kne-form-creator_es-FC","step-index":"kne-form-creator_CCKZZ","field-row":"kne-form-creator_XMkdt","field-row-index":"kne-form-creator_a-cDo","field-row-main":"kne-form-creator_ftlwp","inline-empty":"kne-form-creator_yP-RF","action-group":"kne-form-creator_773yo","hover-reveal":"kne-form-creator_S234h","hover-reveal-active":"kne-form-creator_AE-6r","action-btn":"kne-form-creator_mLgqh","add-block-dropdown":"kne-form-creator_vmS-e","add-block-option":"kne-form-creator_gjg2Y","add-block-option-icon":"kne-form-creator_qh1hh","add-block-option-text":"kne-form-creator_G8iJO","add-block-option-title":"kne-form-creator_ETSvm","add-block-option-desc":"kne-form-creator_O0C3l","field-empty":"kne-form-creator_Nmpfl","field-label-tips-icon":"kne-form-creator_0VVaO","preview-header":"kne-form-creator_c4BT0","preview-title":"kne-form-creator_fPkK4","preview-body":"kne-form-creator_6JntQ","schema-form":"kne-form-creator_MxCWP","schema-body":"kne-form-creator_q9ydz","schema-actions":"kne-form-creator_Y4eEH","schema-actions-inner":"kne-form-creator_FT9Zf","choice-block":"kne-form-creator_RllJe","choice-selector":"kne-form-creator_5A1eM","choice-panels":"kne-form-creator_IO0MY","choice-panels-empty":"kne-form-creator_T0nND","choice-option-panel":"kne-form-creator_FQixN","choice-option-panel-title":"kne-form-creator_ofRo2","choice-option-summary":"kne-form-creator_pksH8","field-editor-form":"kne-form-creator_PGPHL","form-actions-editor":"kne-form-creator_fchMy","form-actions-switch-field":"kne-form-creator_6JE9x","form-actions-layout-panel":"kne-form-creator_rtm9D","form-actions-align-group":"kne-form-creator_51ZsV","form-actions-layout-title":"kne-form-creator_hFeiC","form-actions-gap-slider":"kne-form-creator_Gq0bk","editor-section":"kne-form-creator_jJy85","section-divider":"kne-form-creator_zA7L-","rule-editor":"kne-form-creator_bAlGU","options-editor":"kne-form-creator_AK4yO","super-select-props":"kne-form-creator_Iawhh","field-props-editor":"kne-form-creator_Gabf2","columns-editor":"kne-form-creator_DQW1N","prop-row":"kne-form-creator_7K54P","prop-label":"kne-form-creator_HAAyH","options-item":"kne-form-creator_dnOd2","table-row-card":"kne-form-creator_cwCYp","tree-options-editor":"kne-form-creator_s3nHO","tree-options-list":"kne-form-creator_Djs-E","tree-option-node":"kne-form-creator_XAcut","tree-option-row":"kne-form-creator_4K4Rj","tree-option-fields":"kne-form-creator_-4cjc","tree-option-actions":"kne-form-creator_IjCNI","tree-option-children":"kne-form-creator_pVPGJ","tree-add-sibling":"kne-form-creator_bl46P","rule-checkbox-group":"kne-form-creator_tDgVP","rule-len-row":"kne-form-creator_ATsae","rule-len-input":"kne-form-creator_jY4Ld","rule-len-sep":"kne-form-creator_jBDC8","options-list":"kne-form-creator_GUBNS","options-row":"kne-form-creator_uohD0","options-tip":"kne-form-creator_vrTmK","icon-square-btn":"kne-form-creator_DZjCf","icon-square-btn-sm":"kne-form-creator_GAh-t","is-mobile":"kne-form-creator_LtgJz"};
24
24
 
25
25
  const locale$1 = {
26
26
  addField: '添加填写项',
@@ -1489,6 +1489,37 @@ const FIELD_GROUPS = [{
1489
1489
  label: '业务选择',
1490
1490
  types: ['SelectFunction', 'SelectIndustry', 'SelectAddress']
1491
1491
  }];
1492
+ const optionEnumValues = field => {
1493
+ const options = field?.props?.options;
1494
+ if (!Array.isArray(options) || !options.length) {
1495
+ return undefined;
1496
+ }
1497
+ const values = options.map(item => item?.value).filter(value => value !== undefined && value !== null && value !== '');
1498
+ return values.length ? values : undefined;
1499
+ };
1500
+ const stringWithEnumSchema = field => {
1501
+ const schema = {
1502
+ type: 'string'
1503
+ };
1504
+ const enums = optionEnumValues(field);
1505
+ if (enums) {
1506
+ schema.enum = enums;
1507
+ }
1508
+ return schema;
1509
+ };
1510
+ const superSelectValueSchema = field => {
1511
+ if (field?.props?.single) {
1512
+ return {
1513
+ type: 'object'
1514
+ };
1515
+ }
1516
+ return {
1517
+ type: 'array',
1518
+ items: {
1519
+ type: 'object'
1520
+ }
1521
+ };
1522
+ };
1492
1523
  defineField('Input', {
1493
1524
  label: '单行文本',
1494
1525
  group: '基础字段',
@@ -1496,7 +1527,10 @@ defineField('Input', {
1496
1527
  defaultProps: {
1497
1528
  allowClear: true
1498
1529
  },
1499
- hasFieldProps: true
1530
+ hasFieldProps: true,
1531
+ valueSchema: {
1532
+ type: 'string'
1533
+ }
1500
1534
  });
1501
1535
  defineField('TextArea', {
1502
1536
  label: '多行文本',
@@ -1508,14 +1542,20 @@ defineField('TextArea', {
1508
1542
  defaults: {
1509
1543
  block: true
1510
1544
  },
1511
- hasFieldProps: true
1545
+ hasFieldProps: true,
1546
+ valueSchema: {
1547
+ type: 'string'
1548
+ }
1512
1549
  });
1513
1550
  defineField('InputNumber', {
1514
1551
  label: '数字',
1515
1552
  group: '基础字段',
1516
1553
  component: reactFormAntd.InputNumber,
1517
1554
  defaultProps: {},
1518
- hasFieldProps: true
1555
+ hasFieldProps: true,
1556
+ valueSchema: {
1557
+ type: 'number'
1558
+ }
1519
1559
  });
1520
1560
  defineField('Select', {
1521
1561
  label: '下拉选择',
@@ -1526,7 +1566,8 @@ defineField('Select', {
1526
1566
  allowClear: true
1527
1567
  },
1528
1568
  hasOptions: true,
1529
- hasFieldProps: true
1569
+ hasFieldProps: true,
1570
+ valueSchema: stringWithEnumSchema
1530
1571
  });
1531
1572
  defineField('RadioGroup', {
1532
1573
  label: '单选组',
@@ -1535,7 +1576,8 @@ defineField('RadioGroup', {
1535
1576
  defaultProps: {
1536
1577
  options: []
1537
1578
  },
1538
- hasOptions: true
1579
+ hasOptions: true,
1580
+ valueSchema: stringWithEnumSchema
1539
1581
  });
1540
1582
  defineField('CheckboxGroup', {
1541
1583
  label: '复选组',
@@ -1544,7 +1586,20 @@ defineField('CheckboxGroup', {
1544
1586
  defaultProps: {
1545
1587
  options: []
1546
1588
  },
1547
- hasOptions: true
1589
+ hasOptions: true,
1590
+ valueSchema: field => {
1591
+ const items = {
1592
+ type: 'string'
1593
+ };
1594
+ const enums = optionEnumValues(field);
1595
+ if (enums) {
1596
+ items.enum = enums;
1597
+ }
1598
+ return {
1599
+ type: 'array',
1600
+ items
1601
+ };
1602
+ }
1548
1603
  });
1549
1604
  defineField('SuperSelectList', {
1550
1605
  label: '普通下拉',
@@ -1559,7 +1614,8 @@ defineField('SuperSelectList', {
1559
1614
  },
1560
1615
  isSuperSelect: true,
1561
1616
  hasOptions: true,
1562
- optionsAllowDescription: true
1617
+ optionsAllowDescription: true,
1618
+ valueSchema: superSelectValueSchema
1563
1619
  });
1564
1620
  defineField('SuperSelectTableList', {
1565
1621
  label: '表格选择',
@@ -1576,7 +1632,8 @@ defineField('SuperSelectTableList', {
1576
1632
  isSuperSelect: true,
1577
1633
  hasOptions: true,
1578
1634
  hasColumns: true,
1579
- optionsAllowDescription: true
1635
+ optionsAllowDescription: true,
1636
+ valueSchema: superSelectValueSchema
1580
1637
  });
1581
1638
  defineField('SuperSelectTree', {
1582
1639
  label: '树形选择',
@@ -1592,7 +1649,8 @@ defineField('SuperSelectTree', {
1592
1649
  isSuperSelect: true,
1593
1650
  hasOptions: true,
1594
1651
  optionsAllowChildren: true,
1595
- optionsAllowDescription: true
1652
+ optionsAllowDescription: true,
1653
+ valueSchema: superSelectValueSchema
1596
1654
  });
1597
1655
  defineField('SuperSelectCascader', {
1598
1656
  label: '级联选择',
@@ -1610,7 +1668,8 @@ defineField('SuperSelectCascader', {
1610
1668
  hasOptions: true,
1611
1669
  hasOnlyLastLevel: true,
1612
1670
  optionsAllowChildren: true,
1613
- optionsAllowDescription: true
1671
+ optionsAllowDescription: true,
1672
+ valueSchema: superSelectValueSchema
1614
1673
  });
1615
1674
  defineField('SelectFunction', {
1616
1675
  label: '职能选择',
@@ -1621,7 +1680,8 @@ defineField('SelectFunction', {
1621
1680
  allowClear: true
1622
1681
  },
1623
1682
  isSuperSelect: true,
1624
- hasBuiltinData: true
1683
+ hasBuiltinData: true,
1684
+ valueSchema: superSelectValueSchema
1625
1685
  });
1626
1686
  defineField('SelectIndustry', {
1627
1687
  label: '行业选择',
@@ -1632,7 +1692,8 @@ defineField('SelectIndustry', {
1632
1692
  allowClear: true
1633
1693
  },
1634
1694
  isSuperSelect: true,
1635
- hasBuiltinData: true
1695
+ hasBuiltinData: true,
1696
+ valueSchema: superSelectValueSchema
1636
1697
  });
1637
1698
  defineField('SelectAddress', {
1638
1699
  label: '地址选择',
@@ -1643,14 +1704,18 @@ defineField('SelectAddress', {
1643
1704
  allowClear: true
1644
1705
  },
1645
1706
  isSuperSelect: true,
1646
- hasBuiltinData: true
1707
+ hasBuiltinData: true,
1708
+ valueSchema: superSelectValueSchema
1647
1709
  });
1648
1710
  defineField('Switch', {
1649
1711
  label: '开关',
1650
1712
  group: '基础字段',
1651
1713
  component: reactFormAntd.Switch,
1652
1714
  defaultProps: {},
1653
- hasFieldProps: true
1715
+ hasFieldProps: true,
1716
+ valueSchema: {
1717
+ type: 'boolean'
1718
+ }
1654
1719
  });
1655
1720
  defineField('Checkbox', {
1656
1721
  label: '复选框',
@@ -1658,6 +1723,9 @@ defineField('Checkbox', {
1658
1723
  component: reactFormAntd.Checkbox,
1659
1724
  defaultProps: {
1660
1725
  children: ''
1726
+ },
1727
+ valueSchema: {
1728
+ type: 'boolean'
1661
1729
  }
1662
1730
  });
1663
1731
  defineField('DatePicker', {
@@ -1672,7 +1740,17 @@ defineField('DatePicker', {
1672
1740
  showTime: false
1673
1741
  },
1674
1742
  hasFieldProps: true,
1675
- resolveComponent: props => props?.range ? reactFormAntd.DatePicker.RangePicker || reactFormAntd.DatePicker : reactFormAntd.DatePicker
1743
+ resolveComponent: props => props?.range ? reactFormAntd.DatePicker.RangePicker || reactFormAntd.DatePicker : reactFormAntd.DatePicker,
1744
+ valueSchema: field => field?.props?.range ? {
1745
+ type: 'array',
1746
+ items: {
1747
+ type: 'string'
1748
+ },
1749
+ minItems: 2,
1750
+ maxItems: 2
1751
+ } : {
1752
+ type: 'string'
1753
+ }
1676
1754
  });
1677
1755
 
1678
1756
  /**
@@ -1687,6 +1765,7 @@ defineField('DatePicker', {
1687
1765
  *
1688
1766
  * preset({ type, definition }) 的 fields 项还可传:
1689
1767
  * - groupName?: string 自定义类型下拉分组名;不传则归入「扩展字段」
1768
+ * - valueSchema?: object | (field) => object 提交值的 JSON Schema 片段;缺省回退 { type: 'string' }
1690
1769
  */
1691
1770
  const registerField = (type, definition) => {
1692
1771
  const propsSchema = Array.isArray(definition?.propsSchema) ? definition.propsSchema : undefined;
@@ -1766,6 +1845,50 @@ const applyFromPropsSchema = function (props, values, propsSchema) {
1766
1845
  });
1767
1846
  };
1768
1847
  const getFieldDefinition = type => registry.get(type);
1848
+
1849
+ /**
1850
+ * 解析字段提交值的 JSON Schema 片段。
1851
+ * 优先用 definition.valueSchema(对象或 (field)=>schema);缺省 { type: 'string' }。
1852
+ */
1853
+ const resolveFieldValueSchema = field => {
1854
+ if (!field || !field.type) {
1855
+ return {
1856
+ type: 'string'
1857
+ };
1858
+ }
1859
+ const definition = registry.get(field.type);
1860
+ const raw = definition?.valueSchema;
1861
+ let schema;
1862
+ if (typeof raw === 'function') {
1863
+ schema = raw(field);
1864
+ } else if (raw && typeof raw === 'object') {
1865
+ schema = {
1866
+ ...raw
1867
+ };
1868
+ } else {
1869
+ schema = {
1870
+ type: 'string'
1871
+ };
1872
+ }
1873
+ if (!schema || typeof schema !== 'object') {
1874
+ schema = {
1875
+ type: 'string'
1876
+ };
1877
+ } else {
1878
+ schema = {
1879
+ ...schema
1880
+ };
1881
+ }
1882
+ const title = field.label != null && String(field.label).trim() ? String(field.label).trim() : undefined;
1883
+ const description = field.description != null && String(field.description).trim() ? String(field.description).trim() : undefined;
1884
+ if (title && schema.title == null) {
1885
+ schema.title = title;
1886
+ }
1887
+ if (description && schema.description == null) {
1888
+ schema.description = description;
1889
+ }
1890
+ return schema;
1891
+ };
1769
1892
  const getFieldComponent = (type, field) => {
1770
1893
  const definition = registry.get(type);
1771
1894
  if (!definition) {
@@ -2332,6 +2455,7 @@ const BlockListPanel = _ref3 => {
2332
2455
  } = reactIntl.useIntl();
2333
2456
  const [addMenuOpen, setAddMenuOpen] = react.useState(false);
2334
2457
  const [addFieldMenuId, setAddFieldMenuId] = react.useState(null);
2458
+ const keepAddFieldMenuOpenRef = react.useRef(false);
2335
2459
  const renderAddBlockMenu = function (options, _temp) {
2336
2460
  let {
2337
2461
  onSelect,
@@ -2394,8 +2518,19 @@ const BlockListPanel = _ref3 => {
2394
2518
  }
2395
2519
  return /*#__PURE__*/jsxRuntime.jsx(antd.Dropdown, {
2396
2520
  open: menuOpen,
2397
- onOpenChange: open => setAddFieldMenuId(open ? menuKey : null),
2398
- trigger: ['hover'],
2521
+ onOpenChange: open => {
2522
+ if (open) {
2523
+ setAddFieldMenuId(menuKey);
2524
+ return;
2525
+ }
2526
+ // 已打开时再点触发器:antd 会 toggle 关闭,这里忽略,保持展开
2527
+ if (keepAddFieldMenuOpenRef.current) {
2528
+ keepAddFieldMenuOpenRef.current = false;
2529
+ return;
2530
+ }
2531
+ setAddFieldMenuId(null);
2532
+ },
2533
+ trigger: ['hover', 'click'],
2399
2534
  mouseEnterDelay: 0.1,
2400
2535
  mouseLeaveDelay: 0.15,
2401
2536
  getPopupContainer: trigger => trigger.parentElement || document.body,
@@ -2465,10 +2600,12 @@ const BlockListPanel = _ref3 => {
2465
2600
  size: "small",
2466
2601
  icon: /*#__PURE__*/jsxRuntime.jsx(icons.PlusOutlined, {}),
2467
2602
  className: btnClass,
2468
- onClick: () => {
2469
- onAddFieldClick();
2470
- setAddFieldMenuId(null);
2603
+ onMouseDown: () => {
2604
+ if (menuOpen) {
2605
+ keepAddFieldMenuOpenRef.current = true;
2606
+ }
2471
2607
  },
2608
+ onClick: () => setAddFieldMenuId(menuKey),
2472
2609
  children: formatMessage({
2473
2610
  id: 'addField'
2474
2611
  })
@@ -2553,6 +2690,7 @@ const BlockListPanel = _ref3 => {
2553
2690
  className: style['step-section-header'],
2554
2691
  children: [/*#__PURE__*/jsxRuntime.jsxs(antd.Space, {
2555
2692
  size: 8,
2693
+ wrap: true,
2556
2694
  className: style['step-section-title'],
2557
2695
  children: [/*#__PURE__*/jsxRuntime.jsx("span", {
2558
2696
  className: style['step-index'],
@@ -2577,45 +2715,50 @@ const BlockListPanel = _ref3 => {
2577
2715
  count: step.list?.length || 0
2578
2716
  })
2579
2717
  })]
2580
- }), /*#__PURE__*/jsxRuntime.jsxs(ActionGroup, {
2581
- children: [/*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2582
- title: formatMessage({
2583
- id: 'moveUp'
2584
- }),
2585
- icon: /*#__PURE__*/jsxRuntime.jsx(icons.ArrowUpOutlined, {}),
2586
- disabled: stepIndex === 0,
2587
- onClick: () => onMoveStep(block.id, step.id, 'up')
2588
- }), /*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2589
- title: formatMessage({
2590
- id: 'moveDown'
2591
- }),
2592
- icon: /*#__PURE__*/jsxRuntime.jsx(icons.ArrowDownOutlined, {}),
2593
- disabled: stepIndex === (block.items?.length || 0) - 1,
2594
- onClick: () => onMoveStep(block.id, step.id, 'down')
2595
- }), /*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2596
- title: formatMessage({
2597
- id: 'editStep'
2718
+ }), /*#__PURE__*/jsxRuntime.jsxs(antd.Space, {
2719
+ size: 4,
2720
+ wrap: true,
2721
+ className: style['step-section-actions'],
2722
+ children: [/*#__PURE__*/jsxRuntime.jsxs(ActionGroup, {
2723
+ children: [/*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2724
+ title: formatMessage({
2725
+ id: 'moveUp'
2726
+ }),
2727
+ icon: /*#__PURE__*/jsxRuntime.jsx(icons.ArrowUpOutlined, {}),
2728
+ disabled: stepIndex === 0,
2729
+ onClick: () => onMoveStep(block.id, step.id, 'up')
2730
+ }), /*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2731
+ title: formatMessage({
2732
+ id: 'moveDown'
2733
+ }),
2734
+ icon: /*#__PURE__*/jsxRuntime.jsx(icons.ArrowDownOutlined, {}),
2735
+ disabled: stepIndex === (block.items?.length || 0) - 1,
2736
+ onClick: () => onMoveStep(block.id, step.id, 'down')
2737
+ }), /*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2738
+ title: formatMessage({
2739
+ id: 'editStep'
2740
+ }),
2741
+ icon: /*#__PURE__*/jsxRuntime.jsx(icons.EditOutlined, {}),
2742
+ onClick: () => onEditStep(block.id, step)
2743
+ }), /*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2744
+ title: formatMessage({
2745
+ id: 'deleteStep'
2746
+ }),
2747
+ danger: true,
2748
+ icon: /*#__PURE__*/jsxRuntime.jsx(icons.DeleteOutlined, {}),
2749
+ onClick: () => onDeleteStep(block.id, step.id)
2750
+ })]
2751
+ }), renderAddFieldButton({
2752
+ menuKey: `${block.id}:${step.id}`,
2753
+ depth,
2754
+ onAddFieldClick: () => onAddField(block.id, {
2755
+ stepId: step.id
2598
2756
  }),
2599
- icon: /*#__PURE__*/jsxRuntime.jsx(icons.EditOutlined, {}),
2600
- onClick: () => onEditStep(block.id, step)
2601
- }), /*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2602
- title: formatMessage({
2603
- id: 'deleteStep'
2604
- }),
2605
- danger: true,
2606
- icon: /*#__PURE__*/jsxRuntime.jsx(icons.DeleteOutlined, {}),
2607
- onClick: () => onDeleteStep(block.id, step.id)
2757
+ onAddChildBlock: kind => onAddBlock(kind, {
2758
+ parentBlockId: block.id,
2759
+ stepId: step.id
2760
+ })
2608
2761
  })]
2609
- }), renderAddFieldButton({
2610
- menuKey: `${block.id}:${step.id}`,
2611
- depth,
2612
- onAddFieldClick: () => onAddField(block.id, {
2613
- stepId: step.id
2614
- }),
2615
- onAddChildBlock: kind => onAddBlock(kind, {
2616
- parentBlockId: block.id,
2617
- stepId: step.id
2618
- })
2619
2762
  })]
2620
2763
  }), renderFieldList(step.list, block.id, {
2621
2764
  stepId: step.id
@@ -2670,6 +2813,7 @@ const BlockListPanel = _ref3 => {
2670
2813
  className: style['step-section-header'],
2671
2814
  children: [/*#__PURE__*/jsxRuntime.jsxs(antd.Space, {
2672
2815
  size: 8,
2816
+ wrap: true,
2673
2817
  className: style['step-section-title'],
2674
2818
  children: [/*#__PURE__*/jsxRuntime.jsx("span", {
2675
2819
  className: style['step-index'],
@@ -2694,45 +2838,50 @@ const BlockListPanel = _ref3 => {
2694
2838
  count: option.list?.length || 0
2695
2839
  })
2696
2840
  })]
2697
- }), /*#__PURE__*/jsxRuntime.jsxs(ActionGroup, {
2698
- children: [/*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2699
- title: formatMessage({
2700
- id: 'moveUp'
2701
- }),
2702
- icon: /*#__PURE__*/jsxRuntime.jsx(icons.ArrowUpOutlined, {}),
2703
- disabled: optionIndex === 0,
2704
- onClick: () => onMoveChoiceOption(block.id, option.id, 'up')
2705
- }), /*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2706
- title: formatMessage({
2707
- id: 'moveDown'
2708
- }),
2709
- icon: /*#__PURE__*/jsxRuntime.jsx(icons.ArrowDownOutlined, {}),
2710
- disabled: optionIndex === (block.options?.length || 0) - 1,
2711
- onClick: () => onMoveChoiceOption(block.id, option.id, 'down')
2712
- }), /*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2713
- title: formatMessage({
2714
- id: 'editChoiceOption'
2841
+ }), /*#__PURE__*/jsxRuntime.jsxs(antd.Space, {
2842
+ size: 4,
2843
+ wrap: true,
2844
+ className: style['step-section-actions'],
2845
+ children: [/*#__PURE__*/jsxRuntime.jsxs(ActionGroup, {
2846
+ children: [/*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2847
+ title: formatMessage({
2848
+ id: 'moveUp'
2849
+ }),
2850
+ icon: /*#__PURE__*/jsxRuntime.jsx(icons.ArrowUpOutlined, {}),
2851
+ disabled: optionIndex === 0,
2852
+ onClick: () => onMoveChoiceOption(block.id, option.id, 'up')
2853
+ }), /*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2854
+ title: formatMessage({
2855
+ id: 'moveDown'
2856
+ }),
2857
+ icon: /*#__PURE__*/jsxRuntime.jsx(icons.ArrowDownOutlined, {}),
2858
+ disabled: optionIndex === (block.options?.length || 0) - 1,
2859
+ onClick: () => onMoveChoiceOption(block.id, option.id, 'down')
2860
+ }), /*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2861
+ title: formatMessage({
2862
+ id: 'editChoiceOption'
2863
+ }),
2864
+ icon: /*#__PURE__*/jsxRuntime.jsx(icons.EditOutlined, {}),
2865
+ onClick: () => onEditChoiceOption(block.id, option)
2866
+ }), /*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2867
+ title: formatMessage({
2868
+ id: 'deleteChoiceOption'
2869
+ }),
2870
+ danger: true,
2871
+ icon: /*#__PURE__*/jsxRuntime.jsx(icons.DeleteOutlined, {}),
2872
+ onClick: () => onDeleteChoiceOption(block.id, option.id)
2873
+ })]
2874
+ }), renderAddFieldButton({
2875
+ menuKey: `${block.id}:opt:${option.id}`,
2876
+ depth,
2877
+ onAddFieldClick: () => onAddField(block.id, {
2878
+ optionId: option.id
2715
2879
  }),
2716
- icon: /*#__PURE__*/jsxRuntime.jsx(icons.EditOutlined, {}),
2717
- onClick: () => onEditChoiceOption(block.id, option)
2718
- }), /*#__PURE__*/jsxRuntime.jsx(IconBtn, {
2719
- title: formatMessage({
2720
- id: 'deleteChoiceOption'
2721
- }),
2722
- danger: true,
2723
- icon: /*#__PURE__*/jsxRuntime.jsx(icons.DeleteOutlined, {}),
2724
- onClick: () => onDeleteChoiceOption(block.id, option.id)
2880
+ onAddChildBlock: kind => onAddBlock(kind, {
2881
+ parentBlockId: block.id,
2882
+ optionId: option.id
2883
+ })
2725
2884
  })]
2726
- }), renderAddFieldButton({
2727
- menuKey: `${block.id}:opt:${option.id}`,
2728
- depth,
2729
- onAddFieldClick: () => onAddField(block.id, {
2730
- optionId: option.id
2731
- }),
2732
- onAddChildBlock: kind => onAddBlock(kind, {
2733
- parentBlockId: block.id,
2734
- optionId: option.id
2735
- })
2736
2885
  })]
2737
2886
  }), renderFieldList(option.list, block.id, {
2738
2887
  optionId: option.id
@@ -4759,7 +4908,7 @@ const resolveSelectedIds = (value, mode) => {
4759
4908
  }
4760
4909
  return [String(value)];
4761
4910
  };
4762
- const clearUnselectedOptionFields = (openApi, keepIds, allOptions) => {
4911
+ const clearUnselectedOptionFields = (openApi, formData, keepIds, allOptions) => {
4763
4912
  if (!openApi?.setFields) {
4764
4913
  return;
4765
4914
  }
@@ -4769,7 +4918,11 @@ const clearUnselectedOptionFields = (openApi, keepIds, allOptions) => {
4769
4918
  return;
4770
4919
  }
4771
4920
  (option.list || []).forEach(field => {
4772
- if (field?.name) {
4921
+ if (!field?.name) {
4922
+ return;
4923
+ }
4924
+ const current = getByPath(formData, field.name);
4925
+ if (current !== undefined) {
4773
4926
  entries.push({
4774
4927
  name: field.name,
4775
4928
  value: undefined
@@ -4777,10 +4930,13 @@ const clearUnselectedOptionFields = (openApi, keepIds, allOptions) => {
4777
4930
  }
4778
4931
  });
4779
4932
  collectBlockFieldNames(option.blocks || []).forEach(name => {
4780
- entries.push({
4781
- name,
4782
- value: undefined
4783
- });
4933
+ const current = getByPath(formData, name);
4934
+ if (current !== undefined) {
4935
+ entries.push({
4936
+ name,
4937
+ value: undefined
4938
+ });
4939
+ }
4784
4940
  });
4785
4941
  });
4786
4942
  if (!entries.length) {
@@ -4857,14 +5013,16 @@ const ChoiceBlock = ({
4857
5013
  maxLength
4858
5014
  } = mode === 'multiple' ? resolveSelectLimits(block) : {};
4859
5015
  const firstOptionId = options[0] != null ? String(options[0].id) : undefined;
5016
+ const rawValue = getByPath(formData || {}, selectorName);
5017
+ // 仅随 selector 值变化;勿依赖整个 formData,否则清空未选支字段会触发 options 重算 → CheckboxGroup 死循环
5018
+ const selectorValueKey = mode === 'multiple' ? Array.isArray(rawValue) ? rawValue.map(String).join('\0') : String(rawValue ?? '') : String(rawValue ?? '');
4860
5019
 
4861
5020
  // 单选且未选时,写入第一项,保证预览/提交与选项面板一致
4862
5021
  react.useEffect(() => {
4863
5022
  if (mode !== 'single' || !firstOptionId || !openApi?.setFields) {
4864
5023
  return;
4865
5024
  }
4866
- const current = getByPath(formData || {}, selectorName);
4867
- if (current != null && current !== '') {
5025
+ if (selectorValueKey !== '') {
4868
5026
  return;
4869
5027
  }
4870
5028
  openApi.setFields([{
@@ -4873,11 +5031,10 @@ const ChoiceBlock = ({
4873
5031
  }], {
4874
5032
  runValidate: false
4875
5033
  });
4876
- }, [mode, firstOptionId, selectorName, openApi, formData]);
5034
+ }, [mode, firstOptionId, selectorName, openApi, selectorValueKey]);
5035
+ const selectedIdsFromValue = react.useMemo(() => resolveSelectedIds(rawValue, mode), [selectorValueKey, mode]);
4877
5036
  const selectorOptions = react.useMemo(() => {
4878
- const rawValue = getByPath(formData || {}, selectorName);
4879
- const selectedIds = resolveSelectedIds(rawValue, mode);
4880
- const atMax = mode === 'multiple' && maxLength != null && selectedIds.length >= maxLength;
5037
+ const atMax = mode === 'multiple' && maxLength != null && selectedIdsFromValue.length >= maxLength;
4881
5038
  return options.map((option, index) => {
4882
5039
  const value = String(option.id);
4883
5040
  return {
@@ -4887,17 +5044,16 @@ const ChoiceBlock = ({
4887
5044
  index: index + 1
4888
5045
  }) : `选项${index + 1}`),
4889
5046
  value,
4890
- disabled: atMax && !selectedIds.includes(value)
5047
+ disabled: atMax && !selectedIdsFromValue.includes(value)
4891
5048
  };
4892
5049
  });
4893
- }, [options, formatMessage, formData, selectorName, mode, maxLength]);
4894
- const rawValue = getByPath(formData || {}, selectorName);
4895
- let selectedIds = resolveSelectedIds(rawValue, mode);
5050
+ }, [options, formatMessage, selectedIdsFromValue, mode, maxLength]);
5051
+ let selectedIds = selectedIdsFromValue;
4896
5052
  if (mode === 'single' && !selectedIds.length && firstOptionId) {
4897
5053
  selectedIds = [firstOptionId];
4898
5054
  }
4899
5055
  const activeOptions = options.filter(option => selectedIds.includes(String(option.id)));
4900
- const handleChange = value => {
5056
+ const handleChange = react.useCallback(value => {
4901
5057
  let nextIds = resolveSelectedIds(value, mode);
4902
5058
  if (mode === 'multiple' && maxLength != null && nextIds.length > maxLength) {
4903
5059
  nextIds = nextIds.slice(0, maxLength);
@@ -4908,9 +5064,9 @@ const ChoiceBlock = ({
4908
5064
  runValidate: false
4909
5065
  });
4910
5066
  }
4911
- clearUnselectedOptionFields(openApi, nextIds, options);
4912
- };
4913
- const selectorRule = mode === 'multiple' && (minLength != null || maxLength != null) ? value => {
5067
+ clearUnselectedOptionFields(openApi, formData, nextIds, options);
5068
+ }, [mode, maxLength, openApi, selectorName, formData, options]);
5069
+ const selectorRule = react.useCallback(value => {
4914
5070
  const ids = resolveSelectedIds(value, 'multiple');
4915
5071
  if (minLength != null && ids.length < minLength) {
4916
5072
  return {
@@ -4936,10 +5092,11 @@ const ChoiceBlock = ({
4936
5092
  result: true,
4937
5093
  errMsg: ''
4938
5094
  };
4939
- } : undefined;
5095
+ }, [minLength, maxLength, formatMessage]);
5096
+ const hasSelectLimitRule = mode === 'multiple' && (minLength != null || maxLength != null);
4940
5097
  const Selector = mode === 'multiple' ? reactFormAntd.CheckboxGroup : reactFormAntd.RadioGroup;
4941
5098
  const selectorProps = {
4942
- key: 'choice-selector',
5099
+ key: `choice-selector-${mode}`,
4943
5100
  name: selectorName,
4944
5101
  label: titleText || (formatMessage ? formatMessage({
4945
5102
  id: 'choiceAreaTitle'
@@ -4947,7 +5104,7 @@ const ChoiceBlock = ({
4947
5104
  labelHidden: true,
4948
5105
  options: selectorOptions,
4949
5106
  onChange: handleChange,
4950
- ...(selectorRule ? {
5107
+ ...(hasSelectLimitRule ? {
4951
5108
  rule: selectorRule
4952
5109
  } : {}),
4953
5110
  ...(mode === 'single' ? {
@@ -4956,7 +5113,10 @@ const ChoiceBlock = ({
4956
5113
  ...(firstOptionId ? {
4957
5114
  defaultValue: firstOptionId
4958
5115
  } : {})
4959
- } : {})
5116
+ } : {
5117
+ // CheckboxGroup 需要数组初值,避免 undefined↔[] 来回同步
5118
+ defaultValue: []
5119
+ })
4960
5120
  };
4961
5121
  const contentChildren = [];
4962
5122
  activeOptions.forEach(option => {
@@ -5970,6 +6130,300 @@ const preset = function (_temp) {
5970
6130
  });
5971
6131
  };
5972
6132
 
6133
+ const createObjectLayer = () => ({
6134
+ properties: {},
6135
+ required: [],
6136
+ composites: []
6137
+ });
6138
+ const isReq = rule => parseRuleString(rule).presets.includes('REQ');
6139
+ const resolveChoiceSelectorName = block => {
6140
+ if (block.selectorName != null && String(block.selectorName).trim()) {
6141
+ return String(block.selectorName).trim();
6142
+ }
6143
+ if (block.discriminator?.propertyName) {
6144
+ return String(block.discriminator.propertyName).trim();
6145
+ }
6146
+ return `__choice_${block.id}`;
6147
+ };
6148
+ const mergeFieldIntoLayer = function (layer, field, _temp) {
6149
+ let {
6150
+ allowRequired = true
6151
+ } = _temp === void 0 ? {} : _temp;
6152
+ if (!field?.name) {
6153
+ return;
6154
+ }
6155
+ const name = String(field.name).trim();
6156
+ if (!name) {
6157
+ return;
6158
+ }
6159
+ layer.properties[name] = resolveFieldValueSchema(field);
6160
+ if (allowRequired && isReq(field.rule) && !layer.required.includes(name)) {
6161
+ layer.required.push(name);
6162
+ }
6163
+ };
6164
+ const mergeFieldsIntoLayer = (layer, fields, options) => {
6165
+ (fields || []).forEach(field => mergeFieldIntoLayer(layer, field, options));
6166
+ };
6167
+ const toFiniteInt = (value, minAllowed) => {
6168
+ if (value == null || value === '') {
6169
+ return undefined;
6170
+ }
6171
+ const num = Number(value);
6172
+ if (!Number.isFinite(num)) {
6173
+ return undefined;
6174
+ }
6175
+ const int = Math.floor(num);
6176
+ return int < minAllowed ? minAllowed : int;
6177
+ };
6178
+ const finalizeObjectSchema = function (layer, _temp2) {
6179
+ let {
6180
+ title,
6181
+ description
6182
+ } = _temp2 === void 0 ? {} : _temp2;
6183
+ const schema = {
6184
+ type: 'object',
6185
+ properties: {
6186
+ ...layer.properties
6187
+ }
6188
+ };
6189
+ if (layer.required.length) {
6190
+ schema.required = layer.required.slice();
6191
+ }
6192
+ if (title) {
6193
+ schema.title = title;
6194
+ }
6195
+ if (description) {
6196
+ schema.description = description;
6197
+ }
6198
+ if (layer.composites.length === 1) {
6199
+ Object.assign(schema, layer.composites[0]);
6200
+ } else if (layer.composites.length > 1) {
6201
+ schema.allOf = layer.composites.slice();
6202
+ }
6203
+ return schema;
6204
+ };
6205
+ const walkBlocks = function (blocks, layer, depth) {
6206
+ (blocks || []).forEach(block => {
6207
+ if (!block) {
6208
+ return;
6209
+ }
6210
+ walkBlock(block, layer);
6211
+ });
6212
+ };
6213
+ const walkBlock = function (block, layer, depth) {
6214
+ switch (block.kind) {
6215
+ case 'formInfo':
6216
+ {
6217
+ mergeFieldsIntoLayer(layer, block.list);
6218
+ walkBlocks(block.blocks, layer);
6219
+ return;
6220
+ }
6221
+ case 'object':
6222
+ {
6223
+ const name = block.name != null && String(block.name).trim() ? String(block.name).trim() : '';
6224
+ if (!name) {
6225
+ mergeFieldsIntoLayer(layer, block.list);
6226
+ walkBlocks(block.blocks, layer);
6227
+ return;
6228
+ }
6229
+ const nested = createObjectLayer();
6230
+ mergeFieldsIntoLayer(nested, block.list);
6231
+ walkBlocks(block.blocks, nested);
6232
+ layer.properties[name] = finalizeObjectSchema(nested, {
6233
+ title: block.title || undefined,
6234
+ description: block.subtitle || undefined
6235
+ });
6236
+ return;
6237
+ }
6238
+ case 'list':
6239
+ case 'tableList':
6240
+ {
6241
+ const name = block.name != null && String(block.name).trim() ? String(block.name).trim() : '';
6242
+ if (!name) {
6243
+ return;
6244
+ }
6245
+ const itemLayer = createObjectLayer();
6246
+ mergeFieldsIntoLayer(itemLayer, block.list);
6247
+ if (block.kind === 'list') {
6248
+ walkBlocks(block.itemBlocks, itemLayer);
6249
+ }
6250
+ const items = finalizeObjectSchema(itemLayer);
6251
+ const arraySchema = {
6252
+ type: 'array',
6253
+ items
6254
+ };
6255
+ if (block.title) {
6256
+ arraySchema.title = block.title;
6257
+ }
6258
+ const minItems = toFiniteInt(block.minLength, 0);
6259
+ const maxItems = toFiniteInt(block.maxLength, 1);
6260
+ if (minItems != null) {
6261
+ arraySchema.minItems = minItems;
6262
+ }
6263
+ if (maxItems != null) {
6264
+ arraySchema.maxItems = maxItems;
6265
+ }
6266
+ layer.properties[name] = arraySchema;
6267
+ return;
6268
+ }
6269
+ case 'multiField':
6270
+ {
6271
+ const name = block.name != null && String(block.name).trim() ? String(block.name).trim() : '';
6272
+ if (!name) {
6273
+ return;
6274
+ }
6275
+ const itemField = {
6276
+ type: block.fieldType || 'Input',
6277
+ label: block.label,
6278
+ props: {}
6279
+ };
6280
+ const arraySchema = {
6281
+ type: 'array',
6282
+ items: resolveFieldValueSchema(itemField)
6283
+ };
6284
+ if (block.label) {
6285
+ arraySchema.title = block.label;
6286
+ }
6287
+ layer.properties[name] = arraySchema;
6288
+ return;
6289
+ }
6290
+ case 'steps':
6291
+ {
6292
+ (block.items || []).forEach(step => {
6293
+ mergeFieldsIntoLayer(layer, step?.list);
6294
+ walkBlocks(step?.blocks, layer);
6295
+ });
6296
+ return;
6297
+ }
6298
+ case 'choice':
6299
+ {
6300
+ mergeChoiceIntoLayer(layer, block);
6301
+ return;
6302
+ }
6303
+ default:
6304
+ return;
6305
+ }
6306
+ };
6307
+
6308
+ /**
6309
+ * choice:single → oneOf;multiple → anyOf。
6310
+ * 每支为 object:单选支含 selector const;多选支为该 option 字段,selector 数组放在当前层。
6311
+ * 支内 REQ 可进 required;hidden 字段仍进入 schema。
6312
+ */
6313
+ const mergeChoiceIntoLayer = (layer, block, depth) => {
6314
+ const mode = block.mode === 'multiple' ? 'multiple' : 'single';
6315
+ const selectorInData = block.selectorInData !== false;
6316
+ const selectorName = resolveChoiceSelectorName(block);
6317
+ const options = block.options || [];
6318
+ const optionIds = options.map(option => String(option.id));
6319
+ const branches = options.map((option, index) => {
6320
+ const branch = createObjectLayer();
6321
+ const optionTitle = option.title || `选项${index + 1}`;
6322
+ if (selectorInData && mode === 'single') {
6323
+ branch.properties[selectorName] = {
6324
+ const: String(option.id),
6325
+ title: optionTitle
6326
+ };
6327
+ branch.required.push(selectorName);
6328
+ }
6329
+ mergeFieldsIntoLayer(branch, option.list, {
6330
+ allowRequired: true
6331
+ });
6332
+ walkBlocks(option.blocks, branch);
6333
+ return finalizeObjectSchema(branch, {
6334
+ title: optionTitle
6335
+ });
6336
+ });
6337
+ if (!branches.length) {
6338
+ if (selectorInData) {
6339
+ if (mode === 'multiple') {
6340
+ const selectorSchema = {
6341
+ type: 'array',
6342
+ items: {
6343
+ type: 'string'
6344
+ },
6345
+ uniqueItems: true
6346
+ };
6347
+ if (block.title) {
6348
+ selectorSchema.title = block.title;
6349
+ }
6350
+ const minItems = toFiniteInt(block.minLength, 0);
6351
+ const maxItems = toFiniteInt(block.maxLength, 1);
6352
+ if (minItems != null) {
6353
+ selectorSchema.minItems = minItems;
6354
+ }
6355
+ if (maxItems != null) {
6356
+ selectorSchema.maxItems = maxItems;
6357
+ }
6358
+ layer.properties[selectorName] = selectorSchema;
6359
+ } else {
6360
+ layer.properties[selectorName] = {
6361
+ type: 'string',
6362
+ title: block.title || undefined
6363
+ };
6364
+ }
6365
+ }
6366
+ return;
6367
+ }
6368
+ if (mode === 'multiple') {
6369
+ if (selectorInData) {
6370
+ const selectorSchema = {
6371
+ type: 'array',
6372
+ items: {
6373
+ type: 'string',
6374
+ ...(optionIds.length ? {
6375
+ enum: optionIds
6376
+ } : {})
6377
+ },
6378
+ uniqueItems: true
6379
+ };
6380
+ if (block.title) {
6381
+ selectorSchema.title = block.title;
6382
+ }
6383
+ const minItems = toFiniteInt(block.minLength, 0);
6384
+ const maxItems = toFiniteInt(block.maxLength, 1);
6385
+ if (minItems != null) {
6386
+ selectorSchema.minItems = minItems;
6387
+ }
6388
+ if (maxItems != null) {
6389
+ selectorSchema.maxItems = maxItems;
6390
+ }
6391
+ layer.properties[selectorName] = selectorSchema;
6392
+ }
6393
+ layer.composites.push({
6394
+ anyOf: branches
6395
+ });
6396
+ return;
6397
+ }
6398
+ layer.composites.push({
6399
+ oneOf: branches
6400
+ });
6401
+ };
6402
+
6403
+ /**
6404
+ * 将搭建 Schema 转为描述表单提交数据形状的 JSON Schema。
6405
+ * - 内置字段:fieldRegistry.valueSchema
6406
+ * - 扩展字段:registerField / preset 的 valueSchema;缺省 { type: 'string' }
6407
+ * - hidden 字段仍进入 data schema(可提交)
6408
+ * - choice:single → oneOf,multiple → anyOf
6409
+ */
6410
+ const schemaToDataSchema = function (schema, options) {
6411
+ if (options === void 0) {
6412
+ options = {};
6413
+ }
6414
+ const normalized = normalizeSchema(schema || {});
6415
+ const layer = createObjectLayer();
6416
+ walkBlocks(normalized.blocks, layer);
6417
+ const root = finalizeObjectSchema(layer, {
6418
+ title: normalized.title || undefined,
6419
+ description: options.description
6420
+ });
6421
+ if (options.$schema) {
6422
+ root.$schema = options.$schema;
6423
+ }
6424
+ return root;
6425
+ };
6426
+
5973
6427
  exports.FormCreator = FormCreator$1;
5974
6428
  exports.MAX_BLOCK_DEPTH = MAX_BLOCK_DEPTH;
5975
6429
  exports.RULE_LEN_PRESET = RULE_LEN_PRESET;
@@ -6014,5 +6468,7 @@ exports.pickFieldProps = pickFieldProps;
6014
6468
  exports.pickFromPropsSchema = pickFromPropsSchema;
6015
6469
  exports.preset = preset;
6016
6470
  exports.removeBlockInTree = removeBlockInTree;
6471
+ exports.resolveFieldValueSchema = resolveFieldValueSchema;
6472
+ exports.schemaToDataSchema = schemaToDataSchema;
6017
6473
  exports.updateBlocks = updateBlocks;
6018
6474
  //# sourceMappingURL=index.js.map