@para-ui/core 5.0.0-beta.12 → 5.0.0-beta.13
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/AGENTS.md +315 -0
- package/AlignBox/component.json +89 -0
- package/Anchor/component.json +130 -0
- package/Argv/component.json +216 -0
- package/AutoBox/component.json +133 -0
- package/AutoButton/component.json +109 -0
- package/AutoTips/component.json +121 -0
- package/Badge/component.json +92 -0
- package/Breadcrumbs/component.json +142 -0
- package/Button/component.json +168 -0
- package/ButtonGroup/component.json +132 -0
- package/Card/component.json +162 -0
- package/Carousel/component.json +142 -0
- package/Cascader/component.json +196 -0
- package/Checkbox/component.json +138 -0
- package/CheckboxGroup/component.json +152 -0
- package/CodeEditor/component.json +189 -0
- package/Collapse/component.json +166 -0
- package/CollapseBox/component.json +84 -0
- package/CollapseLayout/component.json +155 -0
- package/ColorPicker/component.json +142 -0
- package/ComboSelect/component.json +181 -0
- package/Container/component.json +111 -0
- package/ContentBox/component.json +81 -0
- package/CopyText/component.json +118 -0
- package/CycleSelector/component.json +98 -0
- package/DatePicker/component.json +192 -0
- package/Descriptions/component.json +142 -0
- package/Desktop/component.json +171 -0
- package/DragVerify/component.json +114 -0
- package/Drawer/component.json +200 -0
- package/Dropdown/component.json +147 -0
- package/DynamicMultiBox/component.json +278 -0
- package/Empty/component.json +123 -0
- package/FieldForm/component.json +196 -0
- package/Form/component.json +161 -0
- package/FormItem/component.json +171 -0
- package/FunctionModal/component.json +197 -0
- package/Help/component.json +118 -0
- package/HelperText/component.json +126 -0
- package/Image/component.json +165 -0
- package/InputCode/component.json +191 -0
- package/InputLang/component.json +205 -0
- package/InputNumber/component.json +162 -0
- package/Label/component.json +126 -0
- package/Loading/component.json +91 -0
- package/Menu/component.json +180 -0
- package/Message/component.json +246 -0
- package/Modal/component.json +277 -0
- package/MultiBox/component.json +216 -0
- package/Notification/component.json +184 -0
- package/OperateBtn/component.json +134 -0
- package/PageHeader/component.json +112 -0
- package/Pagination/component.json +181 -0
- package/PasswordRules/component.json +105 -0
- package/PopConfirm/component.json +227 -0
- package/PopMenu/component.json +131 -0
- package/Popover/component.json +165 -0
- package/Progress/component.json +161 -0
- package/Prompt/component.json +144 -0
- package/Querying/component.json +96 -0
- package/QuickReply/component.json +129 -0
- package/Radio/component.json +136 -0
- package/RadioGroup/component.json +149 -0
- package/RangeInput/component.json +198 -0
- package/Result/component.json +104 -0
- package/ScrollBar/component.json +115 -0
- package/Search/component.json +177 -0
- package/Select/component.json +244 -0
- package/SelectInput/component.json +184 -0
- package/Selector/component.json +203 -0
- package/SelectorPicker/component.json +179 -0
- package/SingleBox/component.json +151 -0
- package/Slider/component.json +181 -0
- package/SortBox/component.json +108 -0
- package/Status/component.json +104 -0
- package/Stepper/component.json +129 -0
- package/Switch/component.json +207 -0
- package/Table/component.json +547 -0
- package/Tabs/component.json +227 -0
- package/Tag/component.json +221 -0
- package/TextEditor/component.json +186 -0
- package/TextField/component.json +290 -0
- package/TimePicker/component.json +176 -0
- package/Timeline/component.json +110 -0
- package/Title/component.json +156 -0
- package/ToggleButton/component.json +153 -0
- package/Tooltip/component.json +176 -0
- package/Transfer/component.json +157 -0
- package/Tree/component.json +512 -0
- package/Upload/component.json +450 -0
- package/ai-workflows/01-crud-list-multi-drawer.md +278 -0
- package/ai-workflows/02-rbac-operation-buttons.md +290 -0
- package/ai-workflows/03-complex-form-async-cascade.md +350 -0
- package/ai-workflows/04-array-field-form.md +281 -0
- package/ai-workflows/05-popconfirm-async-message-queue.md +333 -0
- package/ai-workflows/06-modal-drawer-form-workflow.md +385 -0
- package/ai-workflows/07-search-filter-table-trio.md +387 -0
- package/ai-workflows/08-table-advanced-features.md +365 -0
- package/ai-workflows/09-batch-operation-export-progress.md +367 -0
- package/ai-workflows/10-cross-component-state-coordination.md +412 -0
- package/es/AlignBox/component.json +89 -0
- package/es/AlignBox/index.css +1 -1
- package/es/AlignBox/index.d.ts +6 -2
- package/es/AlignBox/index.js +1 -1
- package/es/AlignBox/style/index.css +1 -1
- package/es/Anchor/anchorMenu/index.d.ts +2 -1
- package/es/Anchor/anchorMenu/index.js +36 -33
- package/es/Anchor/component.json +130 -0
- package/es/Anchor/index.js +50 -47
- package/es/Anchor/type.d.ts +8 -4
- package/es/Argv/component.json +216 -0
- package/es/Argv/index.d.ts +5 -6
- package/es/AutoBox/component.json +133 -0
- package/es/AutoBox/index.d.ts +3 -3
- package/es/AutoBox/index.js +1 -1
- package/es/AutoBox/protal.d.ts +2 -2
- package/es/AutoBox/protal.js +32 -29
- package/es/AutoButton/component.json +109 -0
- package/es/AutoButton/index.js +1 -1
- package/es/AutoTips/autoTipsMultiline/index.d.ts +1 -1
- package/es/AutoTips/autoTipsMultiline/index.js +1 -1
- package/es/AutoTips/component.json +121 -0
- package/es/Badge/component.json +92 -0
- package/es/Breadcrumbs/component.json +142 -0
- package/es/Breadcrumbs/index.js +1 -1
- package/es/Button/SplitButton.d.ts +2 -2
- package/es/Button/component.json +168 -0
- package/es/Button/index.js +44 -44
- package/es/ButtonGroup/component.json +132 -0
- package/es/ButtonGroup/index.d.ts +1 -1
- package/es/Card/component.json +162 -0
- package/es/Card/index.d.ts +2 -2
- package/es/Card/index.js +2 -2
- package/es/Carousel/component.json +142 -0
- package/es/Carousel/index.d.ts +1 -1
- package/es/Cascader/component.json +196 -0
- package/es/Cascader/hooks/useEntities.js +7 -7
- package/es/Cascader/interface.d.ts +1 -0
- package/es/Cascader/utils/commonUtil.d.ts +1 -1
- package/es/Cascader/utils/commonUtil.js +16 -16
- package/es/Cascader/utils/treeUtil.d.ts +14 -5
- package/es/Cascader/utils/treeUtil.js +1 -1
- package/es/Checkbox/component.json +138 -0
- package/es/CheckboxGroup/component.json +152 -0
- package/es/CodeEditor/component.json +189 -0
- package/es/CodeEditor/index.d.ts +10 -9
- package/es/Collapse/component.json +166 -0
- package/es/Collapse/index.d.ts +1 -1
- package/es/Collapse/index.js +23 -22
- package/es/CollapseBox/component.json +84 -0
- package/es/CollapseLayout/component.json +155 -0
- package/es/ColorPicker/component.json +142 -0
- package/es/ComboSelect/component.json +181 -0
- package/es/ComboSelect/index.js +73 -68
- package/es/ComboSelect/interface.d.ts +2 -2
- package/es/ComboSelect/utils.d.ts +3 -3
- package/es/ComboSelect/utils.js +1 -1
- package/es/Container/component.json +111 -0
- package/es/ContentBox/component.json +81 -0
- package/es/CopyText/component.json +118 -0
- package/es/CycleSelector/component.json +98 -0
- package/es/CycleSelector/index.js +14 -13
- package/es/DatePicker/component.json +192 -0
- package/es/DatePicker/generatePicker/generateRangePicker.js +10 -10
- package/es/DatePicker/generatePicker/generateSinglePicker.js +1 -1
- package/es/Descriptions/component.json +142 -0
- package/es/Descriptions/index.d.ts +1 -1
- package/es/Desktop/component.json +171 -0
- package/es/DragVerify/component.json +114 -0
- package/es/DragVerify/index.js +19 -19
- package/es/Drawer/component.json +200 -0
- package/es/Drawer/index.js +86 -86
- package/es/Drawer/interface.d.ts +1 -1
- package/es/Drawer/util.d.ts +1 -6
- package/es/Drawer/util.js +9 -6
- package/es/Dropdown/component.json +147 -0
- package/es/DynamicMultiBox/component.json +278 -0
- package/es/DynamicMultiBox/formItem.d.ts +1 -1
- package/es/DynamicMultiBox/rowForm.d.ts +2 -2
- package/es/Empty/component.json +123 -0
- package/es/Empty/index.css +1 -1
- package/es/Empty/index.d.ts +2 -2
- package/es/Empty/index.js +27 -26
- package/es/Empty/style/index.css +1 -1
- package/es/FieldForm/FieldFormItem/MemoInput.d.ts +2 -2
- package/es/FieldForm/FieldFormItem/index.d.ts +6 -6
- package/es/FieldForm/Form.d.ts +2 -2
- package/es/FieldForm/FormList.d.ts +2 -2
- package/es/FieldForm/component.json +196 -0
- package/es/FieldForm/context.d.ts +5 -1
- package/es/FieldForm/context.js +2 -2
- package/es/FieldForm/hooks/useForm.d.ts +4 -3
- package/es/FieldForm/hooks/useFormInstance.d.ts +1 -1
- package/es/FieldForm/hooks/useFormItemStatus.d.ts +9 -5
- package/es/FieldForm/hooks/useFormItemStatus.js +2 -2
- package/es/FieldForm/hooks/useItemRef.d.ts +1 -1
- package/es/FieldForm/hooks/useItemRef.js +6 -6
- package/es/Form/component.json +161 -0
- package/es/Form/index.d.ts +52 -49
- package/es/FormItem/compoments/defaultCompoments/index.d.ts +5 -5
- package/es/FormItem/compoments/defaultCompoments/index.js +12 -11
- package/es/FormItem/compoments/formCheckboxGroup/index.d.ts +2 -2
- package/es/FormItem/compoments/formFile/index.js +8 -8
- package/es/FormItem/compoments/formRadioGroup/index.d.ts +1 -1
- package/es/FormItem/compoments/formSelect/index.d.ts +1 -1
- package/es/FormItem/component.json +171 -0
- package/es/FormItem/index.d.ts +5 -5
- package/es/FormItem/index.js +23 -23
- package/es/FormItem/itemType.js +1 -1
- package/es/FunctionModal/component.json +197 -0
- package/es/FunctionModal/dialog.d.ts +1 -1
- package/es/FunctionModal/modalContext.d.ts +4 -1
- package/es/Help/component.json +118 -0
- package/es/HelperText/component.json +126 -0
- package/es/Image/component.json +165 -0
- package/es/InputCode/component.json +191 -0
- package/es/InputCode/index.d.ts +2 -2
- package/es/InputLang/component.json +205 -0
- package/es/InputLang/index.js +1 -1
- package/es/InputNumber/component.json +162 -0
- package/es/Label/component.json +126 -0
- package/es/Label/index.d.ts +2 -2
- package/es/Loading/component.json +91 -0
- package/es/Menu/component.json +180 -0
- package/es/Message/component.json +246 -0
- package/es/Message/index.d.ts +2 -2
- package/es/Message/index.js +2 -2
- package/es/Modal/Confirm/index.d.ts +1 -1
- package/es/Modal/component.json +277 -0
- package/es/Modal/index.d.ts +85 -5
- package/es/Modal/index.js +159 -122
- package/es/Modal/interface.d.ts +1 -0
- package/es/MultiBox/component.json +216 -0
- package/es/MultiBox/index.js +19 -14
- package/es/Notification/component.json +184 -0
- package/es/OperateBtn/component.json +134 -0
- package/es/OperateBtn/index.d.ts +3 -3
- package/es/PageHeader/component.json +112 -0
- package/es/Pagination/component.json +181 -0
- package/es/Pagination/index.js +15 -15
- package/es/PasswordRules/component.json +105 -0
- package/es/PasswordRules/index.d.ts +4 -4
- package/es/PopConfirm/component.json +227 -0
- package/es/PopConfirm/index.d.ts +1 -1
- package/es/PopConfirm/index.js +1 -1
- package/es/PopMenu/component.json +131 -0
- package/es/PopMenu/hooks.d.ts +1 -1
- package/es/PopMenu/index.js +8 -8
- package/es/Popover/component.json +165 -0
- package/es/Popover/index.js +1 -1
- package/es/Progress/component.json +161 -0
- package/es/Prompt/component.json +144 -0
- package/es/Querying/component.json +96 -0
- package/es/Querying/index.css +1 -1
- package/es/Querying/index.d.ts +2 -2
- package/es/Querying/index.js +20 -19
- package/es/Querying/style/index.css +1 -1
- package/es/QuickReply/component.json +129 -0
- package/es/QuickReply/index.d.ts +1 -1
- package/es/Radio/component.json +136 -0
- package/es/RadioGroup/component.json +149 -0
- package/es/RangeInput/component.json +198 -0
- package/es/RangeInput/index.js +1 -1
- package/es/Result/component.json +104 -0
- package/es/ScrollBar/component.json +115 -0
- package/es/Search/component.json +177 -0
- package/es/Search/index.d.ts +1 -1
- package/es/Select/component.json +244 -0
- package/es/Select/index.js +113 -113
- package/es/SelectInput/component.json +184 -0
- package/es/Selector/component.json +203 -0
- package/es/Selector/index.js +28 -27
- package/es/Selector/interface.d.ts +1 -1
- package/es/Selector/selectorMain/index.js +2 -2
- package/es/Selector/selectorNode/index.js +1 -1
- package/es/Selector/util.d.ts +2 -2
- package/es/SelectorPicker/component.json +179 -0
- package/es/SelectorPicker/index.d.ts +5 -5
- package/es/SelectorPicker/index.js +15 -15
- package/es/SingleBox/component.json +151 -0
- package/es/SingleBox/index.d.ts +2 -2
- package/es/Slider/component.json +181 -0
- package/es/SortBox/component.json +108 -0
- package/es/Status/component.json +104 -0
- package/es/Stepper/component.json +129 -0
- package/es/Stepper/index.d.ts +2 -2
- package/es/Switch/component.json +207 -0
- package/es/Switch/index.css +1 -1
- package/es/Switch/index.d.ts +3 -2
- package/es/Switch/index.js +60 -59
- package/es/Switch/style/index.css +1 -1
- package/es/Table/component.json +547 -0
- package/es/Table/index.d.ts +2 -2
- package/es/Table/index.js +414 -414
- package/es/Table/interface.d.ts +6 -0
- package/es/Tabs/component.json +227 -0
- package/es/Tag/component.json +221 -0
- package/es/Tag/index.css +1 -1
- package/es/Tag/index.d.ts +1 -1
- package/es/Tag/index.js +20 -20
- package/es/Tag/style/index.css +1 -1
- package/es/TextEditor/component.json +186 -0
- package/es/TextEditor/index.d.ts +5 -5
- package/es/TextField/component.json +290 -0
- package/es/TextField/index.d.ts +2 -2
- package/es/TimePicker/component.json +176 -0
- package/es/Timeline/component.json +110 -0
- package/es/Title/component.json +156 -0
- package/es/ToggleButton/component.json +153 -0
- package/es/Tooltip/component.json +176 -0
- package/es/Tooltip/index.js +58 -53
- package/es/Tooltip/interface.d.ts +14 -1
- package/es/Tooltip/utils.js +6 -6
- package/es/Transfer/component.json +157 -0
- package/es/Tree/component.json +512 -0
- package/es/Upload/component.json +450 -0
- package/es/Utils/type.d.ts +0 -2
- package/es/index.d.ts +2 -0
- package/es/index.js +1 -1
- package/es/locale/en_US.d.ts +361 -0
- package/es/locale/en_US.js +364 -0
- package/es/locale/index.d.ts +1 -723
- package/es/locale/index2.js +10 -0
- package/es/locale/zh_CN.d.ts +361 -0
- package/es/locale/zh_CN.js +364 -0
- package/lib/AlignBox/component.json +89 -0
- package/lib/AlignBox/index.css +1 -1
- package/lib/AlignBox/index.d.ts +6 -2
- package/lib/AlignBox/index.js +1 -1
- package/lib/AlignBox/style/index.css +1 -1
- package/lib/Anchor/anchorMenu/index.d.ts +2 -1
- package/lib/Anchor/anchorMenu/index.js +1 -1
- package/lib/Anchor/component.json +130 -0
- package/lib/Anchor/index.js +1 -1
- package/lib/Anchor/type.d.ts +8 -4
- package/lib/Argv/component.json +216 -0
- package/lib/Argv/index.d.ts +5 -6
- package/lib/AutoBox/component.json +133 -0
- package/lib/AutoBox/index.d.ts +3 -3
- package/lib/AutoBox/index.js +1 -1
- package/lib/AutoBox/protal.d.ts +2 -2
- package/lib/AutoBox/protal.js +1 -1
- package/lib/AutoButton/component.json +109 -0
- package/lib/AutoButton/index.js +1 -1
- package/lib/AutoTips/autoTipsMultiline/index.d.ts +1 -1
- package/lib/AutoTips/autoTipsMultiline/index.js +1 -1
- package/lib/AutoTips/component.json +121 -0
- package/lib/Badge/component.json +92 -0
- package/lib/Breadcrumbs/component.json +142 -0
- package/lib/Breadcrumbs/index.js +1 -1
- package/lib/Button/SplitButton.d.ts +2 -2
- package/lib/Button/component.json +168 -0
- package/lib/Button/index.js +1 -1
- package/lib/ButtonGroup/component.json +132 -0
- package/lib/ButtonGroup/index.d.ts +1 -1
- package/lib/Card/component.json +162 -0
- package/lib/Card/index.d.ts +2 -2
- package/lib/Card/index.js +1 -1
- package/lib/Carousel/component.json +142 -0
- package/lib/Carousel/index.d.ts +1 -1
- package/lib/Cascader/component.json +196 -0
- package/lib/Cascader/hooks/useEntities.js +1 -1
- package/lib/Cascader/interface.d.ts +1 -0
- package/lib/Cascader/utils/commonUtil.d.ts +1 -1
- package/lib/Cascader/utils/commonUtil.js +1 -1
- package/lib/Cascader/utils/treeUtil.d.ts +14 -5
- package/lib/Cascader/utils/treeUtil.js +1 -1
- package/lib/Checkbox/component.json +138 -0
- package/lib/CheckboxGroup/component.json +152 -0
- package/lib/CodeEditor/component.json +189 -0
- package/lib/CodeEditor/index.d.ts +10 -9
- package/lib/Collapse/component.json +166 -0
- package/lib/Collapse/index.d.ts +1 -1
- package/lib/Collapse/index.js +1 -1
- package/lib/CollapseBox/component.json +84 -0
- package/lib/CollapseLayout/component.json +155 -0
- package/lib/ColorPicker/component.json +142 -0
- package/lib/ComboSelect/component.json +181 -0
- package/lib/ComboSelect/index.js +1 -1
- package/lib/ComboSelect/interface.d.ts +2 -2
- package/lib/ComboSelect/utils.d.ts +3 -3
- package/lib/ComboSelect/utils.js +1 -1
- package/lib/Container/component.json +111 -0
- package/lib/ContentBox/component.json +81 -0
- package/lib/CopyText/component.json +118 -0
- package/lib/CycleSelector/component.json +98 -0
- package/lib/CycleSelector/index.js +1 -1
- package/lib/DatePicker/component.json +192 -0
- package/lib/DatePicker/generatePicker/generateRangePicker.js +1 -1
- package/lib/DatePicker/generatePicker/generateSinglePicker.js +1 -1
- package/lib/Descriptions/component.json +142 -0
- package/lib/Descriptions/index.d.ts +1 -1
- package/lib/Desktop/component.json +171 -0
- package/lib/DragVerify/component.json +114 -0
- package/lib/DragVerify/index.js +1 -1
- package/lib/Drawer/component.json +200 -0
- package/lib/Drawer/index.js +1 -1
- package/lib/Drawer/interface.d.ts +1 -1
- package/lib/Drawer/util.d.ts +1 -6
- package/lib/Drawer/util.js +1 -1
- package/lib/Dropdown/component.json +147 -0
- package/lib/DynamicMultiBox/component.json +278 -0
- package/lib/DynamicMultiBox/formItem.d.ts +1 -1
- package/lib/DynamicMultiBox/rowForm.d.ts +2 -2
- package/lib/Empty/component.json +123 -0
- package/lib/Empty/index.css +1 -1
- package/lib/Empty/index.d.ts +2 -2
- package/lib/Empty/index.js +1 -1
- package/lib/Empty/style/index.css +1 -1
- package/lib/FieldForm/FieldFormItem/MemoInput.d.ts +2 -2
- package/lib/FieldForm/FieldFormItem/index.d.ts +6 -6
- package/lib/FieldForm/Form.d.ts +2 -2
- package/lib/FieldForm/FormList.d.ts +2 -2
- package/lib/FieldForm/component.json +196 -0
- package/lib/FieldForm/context.d.ts +5 -1
- package/lib/FieldForm/context.js +1 -1
- package/lib/FieldForm/hooks/useForm.d.ts +4 -3
- package/lib/FieldForm/hooks/useFormInstance.d.ts +1 -1
- package/lib/FieldForm/hooks/useFormItemStatus.d.ts +9 -5
- package/lib/FieldForm/hooks/useFormItemStatus.js +1 -1
- package/lib/FieldForm/hooks/useItemRef.d.ts +1 -1
- package/lib/FieldForm/hooks/useItemRef.js +1 -1
- package/lib/Form/component.json +161 -0
- package/lib/Form/index.d.ts +52 -49
- package/lib/FormItem/compoments/defaultCompoments/index.d.ts +5 -5
- package/lib/FormItem/compoments/defaultCompoments/index.js +1 -1
- package/lib/FormItem/compoments/formCheckboxGroup/index.d.ts +2 -2
- package/lib/FormItem/compoments/formFile/index.js +1 -1
- package/lib/FormItem/compoments/formRadioGroup/index.d.ts +1 -1
- package/lib/FormItem/compoments/formSelect/index.d.ts +1 -1
- package/lib/FormItem/component.json +171 -0
- package/lib/FormItem/index.d.ts +5 -5
- package/lib/FormItem/index.js +1 -1
- package/lib/FormItem/itemType.js +1 -1
- package/lib/FunctionModal/component.json +197 -0
- package/lib/FunctionModal/dialog.d.ts +1 -1
- package/lib/FunctionModal/modalContext.d.ts +4 -1
- package/lib/Help/component.json +118 -0
- package/lib/HelperText/component.json +126 -0
- package/lib/Image/component.json +165 -0
- package/lib/InputCode/component.json +191 -0
- package/lib/InputCode/index.d.ts +2 -2
- package/lib/InputLang/component.json +205 -0
- package/lib/InputLang/index.js +1 -1
- package/lib/InputNumber/component.json +162 -0
- package/lib/Label/component.json +126 -0
- package/lib/Label/index.d.ts +2 -2
- package/lib/Loading/component.json +91 -0
- package/lib/Menu/component.json +180 -0
- package/lib/Message/component.json +246 -0
- package/lib/Message/index.d.ts +2 -2
- package/lib/Message/index.js +1 -1
- package/lib/Modal/Confirm/index.d.ts +1 -1
- package/lib/Modal/component.json +277 -0
- package/lib/Modal/index.d.ts +85 -5
- package/lib/Modal/index.js +1 -1
- package/lib/Modal/interface.d.ts +1 -0
- package/lib/MultiBox/component.json +216 -0
- package/lib/MultiBox/index.js +1 -1
- package/lib/Notification/component.json +184 -0
- package/lib/OperateBtn/component.json +134 -0
- package/lib/OperateBtn/index.d.ts +3 -3
- package/lib/PageHeader/component.json +112 -0
- package/lib/Pagination/component.json +181 -0
- package/lib/Pagination/index.js +1 -1
- package/lib/PasswordRules/component.json +105 -0
- package/lib/PasswordRules/index.d.ts +4 -4
- package/lib/PopConfirm/component.json +227 -0
- package/lib/PopConfirm/index.d.ts +1 -1
- package/lib/PopConfirm/index.js +1 -1
- package/lib/PopMenu/component.json +131 -0
- package/lib/PopMenu/hooks.d.ts +1 -1
- package/lib/PopMenu/index.js +1 -1
- package/lib/Popover/component.json +165 -0
- package/lib/Popover/index.js +1 -1
- package/lib/Progress/component.json +161 -0
- package/lib/Prompt/component.json +144 -0
- package/lib/Querying/component.json +96 -0
- package/lib/Querying/index.css +1 -1
- package/lib/Querying/index.d.ts +2 -2
- package/lib/Querying/index.js +1 -1
- package/lib/Querying/style/index.css +1 -1
- package/lib/QuickReply/component.json +129 -0
- package/lib/QuickReply/index.d.ts +1 -1
- package/lib/Radio/component.json +136 -0
- package/lib/RadioGroup/component.json +149 -0
- package/lib/RangeInput/component.json +198 -0
- package/lib/RangeInput/index.js +1 -1
- package/lib/Result/component.json +104 -0
- package/lib/ScrollBar/component.json +115 -0
- package/lib/Search/component.json +177 -0
- package/lib/Search/index.d.ts +1 -1
- package/lib/Select/component.json +244 -0
- package/lib/Select/index.js +1 -1
- package/lib/SelectInput/component.json +184 -0
- package/lib/Selector/component.json +203 -0
- package/lib/Selector/index.js +1 -1
- package/lib/Selector/interface.d.ts +1 -1
- package/lib/Selector/selectorMain/index.js +1 -1
- package/lib/Selector/selectorNode/index.js +1 -1
- package/lib/Selector/util.d.ts +2 -2
- package/lib/SelectorPicker/component.json +179 -0
- package/lib/SelectorPicker/index.d.ts +5 -5
- package/lib/SelectorPicker/index.js +1 -1
- package/lib/SingleBox/component.json +151 -0
- package/lib/SingleBox/index.d.ts +2 -2
- package/lib/Slider/component.json +181 -0
- package/lib/SortBox/component.json +108 -0
- package/lib/Status/component.json +104 -0
- package/lib/Stepper/component.json +129 -0
- package/lib/Stepper/index.d.ts +2 -2
- package/lib/Switch/component.json +207 -0
- package/lib/Switch/index.css +1 -1
- package/lib/Switch/index.d.ts +3 -2
- package/lib/Switch/index.js +1 -1
- package/lib/Switch/style/index.css +1 -1
- package/lib/Table/component.json +547 -0
- package/lib/Table/index.d.ts +2 -2
- package/lib/Table/index.js +1 -1
- package/lib/Table/interface.d.ts +6 -0
- package/lib/Tabs/component.json +227 -0
- package/lib/Tag/component.json +221 -0
- package/lib/Tag/index.css +1 -1
- package/lib/Tag/index.d.ts +1 -1
- package/lib/Tag/index.js +1 -1
- package/lib/Tag/style/index.css +1 -1
- package/lib/TextEditor/component.json +186 -0
- package/lib/TextEditor/index.d.ts +5 -5
- package/lib/TextField/component.json +290 -0
- package/lib/TextField/index.d.ts +2 -2
- package/lib/TimePicker/component.json +176 -0
- package/lib/Timeline/component.json +110 -0
- package/lib/Title/component.json +156 -0
- package/lib/ToggleButton/component.json +153 -0
- package/lib/Tooltip/component.json +176 -0
- package/lib/Tooltip/index.js +1 -1
- package/lib/Tooltip/interface.d.ts +14 -1
- package/lib/Tooltip/utils.js +1 -1
- package/lib/Transfer/component.json +157 -0
- package/lib/Tree/component.json +512 -0
- package/lib/Upload/component.json +450 -0
- package/lib/Utils/type.d.ts +0 -2
- package/lib/index.d.ts +2 -0
- package/lib/index.js +1 -1
- package/lib/locale/en_US.d.ts +361 -0
- package/lib/locale/en_US.js +2 -0
- package/lib/locale/index.d.ts +1 -723
- package/lib/locale/index2.js +2 -0
- package/lib/locale/zh_CN.d.ts +361 -0
- package/lib/locale/zh_CN.js +2 -0
- package/package.json +9 -3
- /package/es/{Utils/Hooks → Hooks}/useResizeObserver.d.ts +0 -0
- /package/es/{Utils/Hooks → Hooks}/useResizeObserver.js +0 -0
- /package/lib/{Utils/Hooks → Hooks}/useResizeObserver.d.ts +0 -0
- /package/lib/{Utils/Hooks → Hooks}/useResizeObserver.js +0 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# Workflow 3: 复杂表单 + 异步验证 + 级联 Select + Upload
|
|
2
|
+
|
|
3
|
+
> **基于**:console 真实业务代码(User 模块 / Faas 模块)提炼
|
|
4
|
+
> **覆盖 baseline 失败任务**:Task 11(带验证表单)/ Task 12(级联 Select)/ Task 13(Upload 文件上传)/ Task 14(异步验证)/ Task 17(综合场景)
|
|
5
|
+
> **集成 typescriptPitfalls**:Form 5 条 / Select 5 条 / DatePicker 4 条 / Upload 4 条
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 何时使用
|
|
10
|
+
|
|
11
|
+
单张表单页面同时包含以下 3 项及以上:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
文本 / 数字输入 + Select 级联 + 文件上传 + 异步唯一性校验 + DatePicker + 条件显隐字段
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**典型业务**:新建订单 / 用户注册 / 资产登记 / 合同上传 / 工单创建
|
|
18
|
+
|
|
19
|
+
**不要用此模板的场景**:
|
|
20
|
+
- 只有文本输入(≤ 3 个字段)→ 用简单 Form
|
|
21
|
+
- 只读详情展示(无编辑)→ 用 Descriptions
|
|
22
|
+
- 动态多行录入 → 用 Workflow 4(DynamicMultiBox)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 关键模式(与脑补的区别)
|
|
27
|
+
|
|
28
|
+
| 错误模式(AI 常犯) | 正确模式 |
|
|
29
|
+
|------------------|--------|
|
|
30
|
+
| ❌ `rules: { validate: { maxLength: 10 } }`(驼峰 L) | ✅ `rules: { validate: { maxlength: 10 } }`(小写 l)— src 现状不一致 |
|
|
31
|
+
| ❌ `const formRef = useRef(null)` → `formRef.current.check()` 报 unknown | ✅ `useRef<FormRefObject>({} as FormRefObject)` |
|
|
32
|
+
| ❌ `InputType: 'text'` HTML 风格控件类型 | ✅ `InputType: 'default'`(Para UI 字符串输入是 `'default'`) |
|
|
33
|
+
| ❌ `list: [{ label: '选项A', name: 'a' }]` 用于 Select | ✅ Select 子项用 `value` 字段;radioGroup/checkGroup 用 `name` |
|
|
34
|
+
| ❌ `onChange={setLang}` 直接传 setter(签名不匹配) | ✅ `onChange={(val, _e) => setLang(val ?? '')}` 带第二参数 |
|
|
35
|
+
| ❌ `value={'2024-01-01'}` 传字符串给 DatePicker | ✅ `value={dayjs('2024-01-01')}` 必须传 Dayjs 对象 |
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 完整代码(自包含,可直接复制)
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import React, { FunctionComponent, useRef, useState, useCallback } from 'react';
|
|
43
|
+
import dayjs from 'dayjs';
|
|
44
|
+
import type { Dayjs } from 'dayjs';
|
|
45
|
+
import { Form, Button, DatePicker } from '@para-ui/core';
|
|
46
|
+
import { Message } from '@para-ui/core/Message';
|
|
47
|
+
import { FormRefObject, SelectOptionBase } from '@para-ui/core';
|
|
48
|
+
import type { UploadFile, configListProps } from '@para-ui/core';
|
|
49
|
+
import Select from '@para-ui/core/Select';
|
|
50
|
+
import Upload from '@para-ui/core/Upload';
|
|
51
|
+
|
|
52
|
+
// === 业务数据类型 ===
|
|
53
|
+
interface OrderForm {
|
|
54
|
+
title: string;
|
|
55
|
+
category: string;
|
|
56
|
+
subCategory: string;
|
|
57
|
+
assignee: string;
|
|
58
|
+
dueDate: Dayjs | null;
|
|
59
|
+
attachments: UploadFile[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// === 级联 Select 数据 ===
|
|
63
|
+
// ✅ SelectOptionBase 从 @para-ui/core 导入(不是 @para-ui/core/Select)
|
|
64
|
+
interface CategoryOpt extends SelectOptionBase {
|
|
65
|
+
catName: string;
|
|
66
|
+
catCode: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const CATEGORY_LIST: CategoryOpt[] = [
|
|
70
|
+
{ catName: '硬件', catCode: 'hw' },
|
|
71
|
+
{ catName: '软件', catCode: 'sw' },
|
|
72
|
+
{ catName: '服务', catCode: 'svc' }
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
const SUB_CATEGORY_MAP: Record<string, CategoryOpt[]> = {
|
|
76
|
+
hw: [{ catName: '服务器', catCode: 'hw-srv' }, { catName: '网络', catCode: 'hw-net' }],
|
|
77
|
+
sw: [{ catName: '操作系统', catCode: 'sw-os' }, { catName: '中间件', catCode: 'sw-mw' }],
|
|
78
|
+
svc: [{ catName: '咨询', catCode: 'svc-con' }, { catName: '培训', catCode: 'svc-trn' }]
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// === 异步唯一性校验(模拟,实际调 API) ===
|
|
82
|
+
const checkTitleUnique = async (title: string): Promise<boolean> => {
|
|
83
|
+
await new Promise(r => setTimeout(r, 300));
|
|
84
|
+
return title !== 'duplicate-title'; // 模拟:该标题已存在
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// === 主组件 ===
|
|
88
|
+
const OrderCreateForm: FunctionComponent = () => {
|
|
89
|
+
// ✅ FormRefObject 必须显式类型声明,否则 current 推断为 unknown
|
|
90
|
+
const formRef = useRef<FormRefObject>({} as FormRefObject);
|
|
91
|
+
|
|
92
|
+
const [category, setCategory] = useState<string>('');
|
|
93
|
+
const [subCategory, setSubCategory] = useState<string>('');
|
|
94
|
+
const [dueDate, setDueDate] = useState<Dayjs | null>(null);
|
|
95
|
+
const [attachments, setAttachments] = useState<UploadFile[]>([]);
|
|
96
|
+
const [submitting, setSubmitting] = useState<boolean>(false);
|
|
97
|
+
|
|
98
|
+
// 级联:切换父类时重置子类
|
|
99
|
+
const handleCategoryChange = (val: string | undefined, _e: React.SyntheticEvent): void => {
|
|
100
|
+
setCategory(val ?? '');
|
|
101
|
+
setSubCategory(''); // 级联清空子类
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const handleSubCategoryChange = (val: string | undefined, _e: React.SyntheticEvent): void => {
|
|
105
|
+
setSubCategory(val ?? '');
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// 提交:先 check,再异步校验标题唯一性,最后提交
|
|
109
|
+
const handleSubmit = useCallback(async (): Promise<void> => {
|
|
110
|
+
// ✅ check() 返回 false | object,不是 boolean 也不抛异常
|
|
111
|
+
const values = formRef.current.check?.();
|
|
112
|
+
if (!values) return; // false 表示校验失败
|
|
113
|
+
|
|
114
|
+
// 异步校验
|
|
115
|
+
const isUnique = await checkTitleUnique(values.title as string);
|
|
116
|
+
if (!isUnique) {
|
|
117
|
+
Message.error('工单标题已存在,请换一个');
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
setSubmitting(true);
|
|
122
|
+
try {
|
|
123
|
+
const orderData: OrderForm = {
|
|
124
|
+
title: values.title as string,
|
|
125
|
+
category,
|
|
126
|
+
subCategory,
|
|
127
|
+
assignee: values.assignee as string,
|
|
128
|
+
dueDate,
|
|
129
|
+
attachments
|
|
130
|
+
};
|
|
131
|
+
await mockApi.createOrder(orderData);
|
|
132
|
+
Message.success('工单已创建');
|
|
133
|
+
} finally {
|
|
134
|
+
setSubmitting(false);
|
|
135
|
+
}
|
|
136
|
+
}, [category, subCategory, dueDate, attachments]);
|
|
137
|
+
|
|
138
|
+
// ✅ 显式声明 configListProps 类型,避免 rules.message 可选字段与 index signature 冲突
|
|
139
|
+
const configList: configListProps = [
|
|
140
|
+
{
|
|
141
|
+
name: 'title',
|
|
142
|
+
label: '工单标题',
|
|
143
|
+
// ✅ 控件类型用 InputType(不是 type,type 是布局覆盖)
|
|
144
|
+
InputType: 'default',
|
|
145
|
+
rules: {
|
|
146
|
+
validate: {
|
|
147
|
+
required: true,
|
|
148
|
+
// ✅ maxlength 小写 L;minLength 驼峰 L(src 现状不一致)
|
|
149
|
+
maxlength: 100,
|
|
150
|
+
minLength: 2
|
|
151
|
+
},
|
|
152
|
+
message: {
|
|
153
|
+
required: '请输入工单标题',
|
|
154
|
+
maxlength: '标题不超过 100 字',
|
|
155
|
+
minLength: '标题至少 2 字'
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: 'assignee',
|
|
161
|
+
label: '经办人',
|
|
162
|
+
InputType: 'default',
|
|
163
|
+
rules: {
|
|
164
|
+
validate: { required: true },
|
|
165
|
+
message: { required: '请输入经办人' }
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
];
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<div style={{ maxWidth: 600 }}>
|
|
172
|
+
<Form
|
|
173
|
+
form={formRef}
|
|
174
|
+
configList={configList}
|
|
175
|
+
type="vertical"
|
|
176
|
+
/>
|
|
177
|
+
|
|
178
|
+
{/* 级联 Select:父类 */}
|
|
179
|
+
<div style={{ marginBottom: 16 }}>
|
|
180
|
+
<label>分类</label>
|
|
181
|
+
<Select<string>
|
|
182
|
+
list={CATEGORY_LIST}
|
|
183
|
+
value={category || undefined}
|
|
184
|
+
// ✅ 数据源字段名不是 label/value 时必须传 showName/showValue
|
|
185
|
+
showName="catName"
|
|
186
|
+
showValue="catCode"
|
|
187
|
+
allowClear
|
|
188
|
+
placeholder="请选择分类"
|
|
189
|
+
onChange={handleCategoryChange}
|
|
190
|
+
/>
|
|
191
|
+
</div>
|
|
192
|
+
|
|
193
|
+
{/* 级联 Select:子类(依赖父类) */}
|
|
194
|
+
<div style={{ marginBottom: 16 }}>
|
|
195
|
+
<label>子分类</label>
|
|
196
|
+
<Select<string>
|
|
197
|
+
list={category ? SUB_CATEGORY_MAP[category] ?? [] : []}
|
|
198
|
+
value={subCategory || undefined}
|
|
199
|
+
showName="catName"
|
|
200
|
+
showValue="catCode"
|
|
201
|
+
allowClear
|
|
202
|
+
placeholder={category ? '请选择子分类' : '请先选择分类'}
|
|
203
|
+
disabled={!category}
|
|
204
|
+
onChange={handleSubCategoryChange}
|
|
205
|
+
/>
|
|
206
|
+
</div>
|
|
207
|
+
|
|
208
|
+
{/* DatePicker:必须传 Dayjs 对象,不能传字符串 */}
|
|
209
|
+
<div style={{ marginBottom: 16 }}>
|
|
210
|
+
<label>截止日期</label>
|
|
211
|
+
<DatePicker
|
|
212
|
+
value={dueDate}
|
|
213
|
+
onChange={(date: Dayjs | null) => setDueDate(date)}
|
|
214
|
+
// ✅ disabledDate 参数是 Dayjs,用 Dayjs API 不用 Date 方法
|
|
215
|
+
disabledDate={(cur: Dayjs) => cur && cur.isBefore(dayjs().startOf('day'))}
|
|
216
|
+
/>
|
|
217
|
+
</div>
|
|
218
|
+
|
|
219
|
+
{/* Upload:onChange 签名是 (files: UploadFile[]) => void,不是 antd 的 {file,fileList} */}
|
|
220
|
+
<div style={{ marginBottom: 24 }}>
|
|
221
|
+
<label>附件</label>
|
|
222
|
+
<Upload
|
|
223
|
+
fileList={attachments}
|
|
224
|
+
onChange={(files: UploadFile[]) => setAttachments(files)}
|
|
225
|
+
multiple
|
|
226
|
+
accept=".pdf,.doc,.docx,.xlsx"
|
|
227
|
+
/>
|
|
228
|
+
</div>
|
|
229
|
+
|
|
230
|
+
<Button
|
|
231
|
+
variant="contained"
|
|
232
|
+
loading={submitting}
|
|
233
|
+
onClick={handleSubmit}
|
|
234
|
+
>
|
|
235
|
+
提交工单
|
|
236
|
+
</Button>
|
|
237
|
+
<Button
|
|
238
|
+
style={{ marginLeft: 8 }}
|
|
239
|
+
onClick={() => formRef.current.reset?.()}
|
|
240
|
+
>
|
|
241
|
+
重置
|
|
242
|
+
</Button>
|
|
243
|
+
</div>
|
|
244
|
+
);
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
export default OrderCreateForm;
|
|
248
|
+
|
|
249
|
+
// === 占位 Mock ===
|
|
250
|
+
const mockApi = {
|
|
251
|
+
createOrder: async (data: OrderForm): Promise<void> => { void data; }
|
|
252
|
+
};
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## 5 个真实陷阱(来自 M2/M3 修复实证)
|
|
258
|
+
|
|
259
|
+
### ❌ 陷阱 1:Form rules.validate 大小写不一致(src 现状)
|
|
260
|
+
```tsx
|
|
261
|
+
// 错(校验规则被忽略,不报 TS 错但校验不生效)
|
|
262
|
+
rules: { validate: { maxLength: 10, minlength: 2 } }
|
|
263
|
+
// ↑ 驼峰L ↑ 全小写
|
|
264
|
+
|
|
265
|
+
// 对(严格按 src/FormItem/index.tsx:54-60 字段名)
|
|
266
|
+
rules: { validate: { maxlength: 10, minLength: 2 } }
|
|
267
|
+
// ↑ 小写l ↑ 驼峰L
|
|
268
|
+
// 记忆口诀:max 小 / min 大(不一致是 src 历史问题,无法改变)
|
|
269
|
+
```
|
|
270
|
+
**实证来源**:Form component.json `typescriptPitfalls[2]`,Task 11/14 失败根因之一。
|
|
271
|
+
|
|
272
|
+
### ❌ 陷阱 2:FormRefObject 未显式类型声明
|
|
273
|
+
```tsx
|
|
274
|
+
// 错:useRef(null) → current 推断为 unknown → check() 报类型错
|
|
275
|
+
const formRef = useRef(null);
|
|
276
|
+
formRef.current.check?.(); // 报 TS 错:null 上不存在 check
|
|
277
|
+
|
|
278
|
+
// 对:显式声明 FormRefObject 类型
|
|
279
|
+
import { FormRefObject } from '@para-ui/core';
|
|
280
|
+
const formRef = useRef<FormRefObject>({} as FormRefObject);
|
|
281
|
+
// check() 返回 false(失败)或 object(成功)—— 不抛异常
|
|
282
|
+
const values = formRef.current.check?.();
|
|
283
|
+
if (!values) return; // false 表失败
|
|
284
|
+
```
|
|
285
|
+
**实证来源**:Form component.json `typescriptPitfalls[0]`,Task 11 失败根因。
|
|
286
|
+
|
|
287
|
+
### ❌ 陷阱 3:Select 数据源字段名忘传 showName/showValue
|
|
288
|
+
```tsx
|
|
289
|
+
// 错:自定义字段名不传 showName/showValue → 下拉无文字,onChange 返回 undefined
|
|
290
|
+
<Select list={[{ catName: '硬件', catCode: 'hw' }]} value={category} onChange={...} />
|
|
291
|
+
// 问题:Select 默认读 label/value 字段,catName/catCode 不被识别
|
|
292
|
+
|
|
293
|
+
// 对:非 label/value 字段名时必须声明
|
|
294
|
+
<Select
|
|
295
|
+
list={CATEGORY_LIST}
|
|
296
|
+
showName="catName" // ← 显示字段名
|
|
297
|
+
showValue="catCode" // ← 取值字段名
|
|
298
|
+
value={category || undefined}
|
|
299
|
+
onChange={(val, _e) => setCategory(val ?? '')}
|
|
300
|
+
/>
|
|
301
|
+
```
|
|
302
|
+
**实证来源**:Select component.json `commonMisconceptions[0]`,Task 12 失败根因。
|
|
303
|
+
|
|
304
|
+
### ❌ 陷阱 4:DatePicker value 传字符串而非 Dayjs 对象
|
|
305
|
+
```tsx
|
|
306
|
+
// 错:传字符串 → 组件内部格式化失败,日期显示异常
|
|
307
|
+
const [date, setDate] = useState('2024-01-01');
|
|
308
|
+
<DatePicker value={date} onChange={(d) => setDate(d)} />
|
|
309
|
+
// ↑ 字符串,不是 Dayjs
|
|
310
|
+
|
|
311
|
+
// 对:必须用 dayjs() 转换;清空用 null
|
|
312
|
+
const [date, setDate] = useState<Dayjs | null>(null);
|
|
313
|
+
<DatePicker
|
|
314
|
+
value={date}
|
|
315
|
+
onChange={(d: Dayjs | null) => setDate(d)}
|
|
316
|
+
// disabledDate 参数也是 Dayjs,用 Dayjs API
|
|
317
|
+
disabledDate={(cur: Dayjs) => cur.isBefore(dayjs().startOf('day'))}
|
|
318
|
+
/>
|
|
319
|
+
```
|
|
320
|
+
**实证来源**:DatePicker component.json `typescriptPitfalls[0]` + `typescriptPitfalls[3]`,Task 13 失败根因。
|
|
321
|
+
|
|
322
|
+
### ❌ 陷阱 5:Upload onChange 签名与 antd 不同
|
|
323
|
+
```tsx
|
|
324
|
+
// 错(antd 风格:解构对象)
|
|
325
|
+
<Upload onChange={({file, fileList}) => setList(fileList)} />
|
|
326
|
+
// 报 TS 类型错:实际传入的是数组 UploadFile[],不是对象
|
|
327
|
+
|
|
328
|
+
// 对:Para UI Upload onChange 直接接收 UploadFile[]
|
|
329
|
+
<Upload
|
|
330
|
+
fileList={attachments}
|
|
331
|
+
onChange={(files: UploadFile[]) => setAttachments(files)}
|
|
332
|
+
/>
|
|
333
|
+
// 注意:UploadFile.status 只有 'error' | 'done' | 'removed',没有 'uploading'
|
|
334
|
+
// 上传中状态用 showLoading/loading prop 控制 UI
|
|
335
|
+
```
|
|
336
|
+
**实证来源**:Upload component.json `typescriptPitfalls[0]` + `typescriptPitfalls[1]`,Task 13/17 失败根因。
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## 真实参考
|
|
341
|
+
|
|
342
|
+
| 关键模式 | 参考位置 |
|
|
343
|
+
|---------|--------|
|
|
344
|
+
| `FormRefObject` 声明 + `check()` 返回值 | Form/component.json typescriptPitfalls[0][3] |
|
|
345
|
+
| `maxlength`/`minLength` 大小写陷阱 | Form/component.json typescriptPitfalls[2] |
|
|
346
|
+
| `InputType` vs `type` 字段区分 | Form/component.json typescriptPitfalls[1] |
|
|
347
|
+
| Select `showName`/`showValue` 必传场景 | Select/component.json commonMisconceptions[0] |
|
|
348
|
+
| Select `onChange` 第二参数 `e` 签名 | Select/component.json typescriptPitfalls[0] |
|
|
349
|
+
| DatePicker value 必须是 Dayjs | DatePicker/component.json typescriptPitfalls[0] |
|
|
350
|
+
| Upload onChange 是数组而非 antd 对象 | Upload/component.json typescriptPitfalls[0] |
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
# Workflow 4: 数组字段表单 DynamicMultiBox
|
|
2
|
+
|
|
3
|
+
> **基于**:console 真实业务代码(Faas 模块 / 参数配置模块)提炼
|
|
4
|
+
> **覆盖 baseline 失败任务**:Task 15(动态多行表单 DynamicMultiBox)
|
|
5
|
+
> **集成 typescriptPitfalls**:M2 修复 DynamicMultiBox 6 条 typescriptPitfalls 全部集成
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 何时使用
|
|
10
|
+
|
|
11
|
+
表单中需要动态增减行数的多行录入场景:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
批量参数录入 / 联系人列表 / 规则条件配置 / 可排序步骤 / 字段自定义
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**典型业务**:订单明细 / 角色权限规则 / 资产联系人 / 工作流步骤
|
|
18
|
+
|
|
19
|
+
**不要用此模板的场景**:
|
|
20
|
+
- 固定字段表单(行数固定)→ 用 Form(Workflow 3)
|
|
21
|
+
- 只读数组展示 → 用 Table
|
|
22
|
+
- 树形结构(有嵌套子级)→ 用 Tree
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 关键模式(与脑补的区别)
|
|
27
|
+
|
|
28
|
+
| 错误模式(AI 常犯) | 正确模式 |
|
|
29
|
+
|------------------|--------|
|
|
30
|
+
| ❌ `onAdd={(list) => setValueList(list)}` 单参数 | ✅ `onAdd={(list, errs) => { setValueList(list); setErrors(errs); }}` 双参数 |
|
|
31
|
+
| ❌ `errRow[cfg.name] = ''`(IConfig.name 可能是 undefined) | ✅ `if (cfg.name) errRow[cfg.name] = ''` narrow 后再索引 |
|
|
32
|
+
| ❌ `rest as Contact`(unknown 索引签名直接 as) | ✅ `rest as unknown as Contact`(unknown 中转)|
|
|
33
|
+
| ❌ `{ inputType: 'text' }` HTML 小写风格 | ✅ `{ inputType: 'TextField' }` PascalCase(严格枚举) |
|
|
34
|
+
| ❌ 不传泛型 `<DynamicMultiBox>` | ✅ 传泛型 + interface 加 index signature `[key: string]: unknown` |
|
|
35
|
+
| ❌ `titleMode='single'` 误解为"只第一行有标题" | ✅ `single` = 整表 1 个合并标题;每列独立标题用 `all`(默认) |
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 完整代码(自包含,可直接复制)
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import React, { FC, useState, useMemo } from 'react';
|
|
43
|
+
import DynamicMultiBox from '@para-ui/core/DynamicMultiBox';
|
|
44
|
+
import type { IConfig, IErrors, IValueList } from '@para-ui/core/DynamicMultiBox/interface';
|
|
45
|
+
|
|
46
|
+
// === 业务数据类型 ===
|
|
47
|
+
// ✅ 泛型 T 必须满足 Record<string, unknown> 约束 → 加 index signature
|
|
48
|
+
interface ContactItem {
|
|
49
|
+
name: string;
|
|
50
|
+
phone: string;
|
|
51
|
+
email: string;
|
|
52
|
+
role: string;
|
|
53
|
+
[key: string]: unknown; // ← 必须加,否则 TS2344 不满足 DynamicMultiBox 泛型约束
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// === 工具:初始化 errors 空占位行 ===
|
|
57
|
+
// ✅ IConfig.name 是 string | undefined → narrow 后再索引(M1 TS2538 修复)
|
|
58
|
+
const buildEmptyErrors = (
|
|
59
|
+
valueList: IValueList[],
|
|
60
|
+
fieldConfig: IConfig[]
|
|
61
|
+
): IErrors[] =>
|
|
62
|
+
valueList.map(row => {
|
|
63
|
+
const errRow: IErrors = { id: row.id };
|
|
64
|
+
fieldConfig.forEach(cfg => {
|
|
65
|
+
if (cfg.name) errRow[cfg.name] = ''; // ← narrow,不是 errRow[cfg.name!] 也行
|
|
66
|
+
});
|
|
67
|
+
return errRow;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// === 业务类型转换 ===
|
|
71
|
+
// ✅ IValueList 解构后 rest 是 unknown 索引签名 → as unknown as 中转(M2 TS2352 修复)
|
|
72
|
+
const toContacts = (valueList: IValueList[]): ContactItem[] =>
|
|
73
|
+
valueList.map(({ id, ...rest }) => rest as unknown as ContactItem); // void id 不需要时
|
|
74
|
+
const toValueList = (contacts: ContactItem[]): IValueList[] =>
|
|
75
|
+
contacts.map((c, i) => ({ id: String(i + 1), ...c }));
|
|
76
|
+
|
|
77
|
+
// === 字段配置 ===
|
|
78
|
+
// ✅ inputType 必须 PascalCase('TextField' / 'Select' / 'Switch' 等),不是 HTML 小写
|
|
79
|
+
const FIELD_CONFIG: IConfig[] = [
|
|
80
|
+
{ name: 'name', label: '姓名', inputType: 'TextField', required: true },
|
|
81
|
+
{ name: 'phone', label: '电话', inputType: 'TextField' },
|
|
82
|
+
{ name: 'email', label: '邮箱', inputType: 'TextField' },
|
|
83
|
+
{
|
|
84
|
+
name: 'role',
|
|
85
|
+
label: '角色',
|
|
86
|
+
inputType: 'Select',
|
|
87
|
+
// ✅ Select 类型子项用 list 字段(component.json idealProps.config 说明)
|
|
88
|
+
list: [
|
|
89
|
+
{ label: '主联系人', value: 'primary' },
|
|
90
|
+
{ label: '抄送人', value: 'cc' },
|
|
91
|
+
{ label: '审批人', value: 'approver' }
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
// === 包装组件(对外以 ContactItem[] 受控)===
|
|
97
|
+
interface ContactsFormProps {
|
|
98
|
+
contacts: ContactItem[];
|
|
99
|
+
onChange: (contacts: ContactItem[]) => void;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const ContactsEntryForm: FC<ContactsFormProps> = ({ contacts, onChange }) => {
|
|
103
|
+
// ✅ 双 state:valueList + errors 都必须维护(wrapperPattern 核心)
|
|
104
|
+
const [valueList, setValueList] = useState<IValueList[]>(
|
|
105
|
+
() => toValueList(contacts)
|
|
106
|
+
);
|
|
107
|
+
const [errors, setErrors] = useState<IErrors[]>(
|
|
108
|
+
() => buildEmptyErrors(toValueList(contacts), FIELD_CONFIG)
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<DynamicMultiBox
|
|
113
|
+
config={FIELD_CONFIG}
|
|
114
|
+
valueList={valueList}
|
|
115
|
+
errors={errors}
|
|
116
|
+
// ✅ titleMode='all'(默认)= 每列独立 label;不要写 'single'(整表 1 个合并标题)
|
|
117
|
+
titleMode="all"
|
|
118
|
+
isSort
|
|
119
|
+
onChange={(next) => {
|
|
120
|
+
setValueList(next);
|
|
121
|
+
onChange(toContacts(next));
|
|
122
|
+
}}
|
|
123
|
+
// ✅ onAdd 必须接收双参数,errors 同步(M3 修复)
|
|
124
|
+
onAdd={(next, nextErrors) => {
|
|
125
|
+
setValueList(next);
|
|
126
|
+
setErrors(nextErrors);
|
|
127
|
+
onChange(toContacts(next));
|
|
128
|
+
}}
|
|
129
|
+
// ✅ onDelete 必须接收双参数(M3 修复)
|
|
130
|
+
onDelete={(next, nextErrors) => {
|
|
131
|
+
setValueList(next);
|
|
132
|
+
setErrors(nextErrors);
|
|
133
|
+
onChange(toContacts(next));
|
|
134
|
+
}}
|
|
135
|
+
onSort={(newList) => {
|
|
136
|
+
setValueList(newList);
|
|
137
|
+
onChange(toContacts(newList));
|
|
138
|
+
}}
|
|
139
|
+
/>
|
|
140
|
+
);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// === 页面使用示例 ===
|
|
144
|
+
const OrderContactsPage: FC = () => {
|
|
145
|
+
const [contacts, setContacts] = useState<ContactItem[]>([
|
|
146
|
+
{ name: '张三', phone: '13800000001', email: 'zhang@example.com', role: 'primary', [Symbol.iterator]: undefined }
|
|
147
|
+
]);
|
|
148
|
+
|
|
149
|
+
// useMemo 避免每次 render 都重建(contacts 作为依赖)
|
|
150
|
+
const initialContacts = useMemo<ContactItem[]>(() => [
|
|
151
|
+
{ name: '', phone: '', email: '', role: '' }
|
|
152
|
+
], []);
|
|
153
|
+
|
|
154
|
+
void initialContacts;
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
<div>
|
|
158
|
+
<h3>联系人配置</h3>
|
|
159
|
+
<ContactsEntryForm
|
|
160
|
+
contacts={contacts}
|
|
161
|
+
onChange={setContacts}
|
|
162
|
+
/>
|
|
163
|
+
<div style={{ marginTop: 16 }}>
|
|
164
|
+
当前联系人数:{contacts.length}
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
export default OrderContactsPage;
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 5 个真实陷阱(来自 M2 修复实证)
|
|
176
|
+
|
|
177
|
+
### ❌ 陷阱 1:onAdd / onDelete 只传单参数(errors 不同步)
|
|
178
|
+
```tsx
|
|
179
|
+
// 错(M2 DynamicMultiBox commonMisconceptions.M3 根因)
|
|
180
|
+
onAdd={(valueList) => setValueList(valueList)}
|
|
181
|
+
// 问题:errors state 与 valueList 行数不同步 → 新行渲染时查 errors 失败
|
|
182
|
+
// TS 不会报错(callback 参数可少传),但逻辑错误
|
|
183
|
+
|
|
184
|
+
// 对:必须双参数 + 双 setState
|
|
185
|
+
onAdd={(valueList, errors) => {
|
|
186
|
+
setValueList(valueList);
|
|
187
|
+
setErrors(errors); // ← errors 已含新行空占位,直接用
|
|
188
|
+
}}
|
|
189
|
+
onDelete={(valueList, errors) => {
|
|
190
|
+
setValueList(valueList);
|
|
191
|
+
setErrors(errors);
|
|
192
|
+
}}
|
|
193
|
+
```
|
|
194
|
+
**实证来源**:DynamicMultiBox/component.json `commonMisconceptions.M3`,Task 15 失败根因。
|
|
195
|
+
|
|
196
|
+
### ❌ 陷阱 2:`IConfig.name` 直接用作对象索引(TS2538)
|
|
197
|
+
```tsx
|
|
198
|
+
// 错(M2 DynamicMultiBox r23FailingScenarios.scenario_003 根因)
|
|
199
|
+
const buildEmptyErrors = (valueList: IValueList[], fieldConfig: IConfig[]) =>
|
|
200
|
+
valueList.map(row => {
|
|
201
|
+
const errRow: IErrors = { id: row.id };
|
|
202
|
+
fieldConfig.forEach((cfg) => {
|
|
203
|
+
errRow[cfg.name] = ''; // TS2538: 'undefined' cannot be used as an index type
|
|
204
|
+
}); // IConfig.name 是 string | undefined!
|
|
205
|
+
return errRow;
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// 对:narrow 后再索引
|
|
209
|
+
fieldConfig.forEach((cfg) => {
|
|
210
|
+
if (cfg.name) errRow[cfg.name] = ''; // narrow
|
|
211
|
+
// 或:errRow[cfg.name!] = ''; // 非空断言(已知 name 必有值时)
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
**实证来源**:DynamicMultiBox/component.json `typescriptPitfalls[0]`,R23 DynamicMultiBox-003 失败。
|
|
215
|
+
|
|
216
|
+
### ❌ 陷阱 3:IValueList 解构后直接 as 业务类型(TS2352)
|
|
217
|
+
```tsx
|
|
218
|
+
// 错(M2 DynamicMultiBox r23FailingScenarios.scenario_006 根因)
|
|
219
|
+
const toContact = (item: IValueList): Contact =>
|
|
220
|
+
(({ id, ...rest }) => rest as Contact)(item);
|
|
221
|
+
// TS2352: Conversion may be a mistake because neither type sufficiently overlaps
|
|
222
|
+
// rest 被推断为 { [x: string]: unknown },直接 as Contact 被 TS 5.x 拒绝
|
|
223
|
+
|
|
224
|
+
// 对:unknown 中转
|
|
225
|
+
const toContact = (item: IValueList): Contact =>
|
|
226
|
+
(({ id, ...rest }) => rest as unknown as Contact)(item); // 先转 unknown 再转目标
|
|
227
|
+
// 或显式字段映射(更安全):
|
|
228
|
+
const toContact = ({ name, phone, email }: IValueList): Contact => ({ name, phone, email } as Contact);
|
|
229
|
+
```
|
|
230
|
+
**实证来源**:DynamicMultiBox/component.json `typescriptPitfalls[1]`,R23 DynamicMultiBox-006 失败。
|
|
231
|
+
|
|
232
|
+
### ❌ 陷阱 4:inputType 用 HTML 小写风格
|
|
233
|
+
```tsx
|
|
234
|
+
// 错(运行时不渲染,TS 报类型错)
|
|
235
|
+
const config: IConfig[] = [
|
|
236
|
+
{ name: 'age', label: '年龄', inputType: 'number' }, // ← HTML 风格
|
|
237
|
+
{ name: 'memo', label: '备注', inputType: 'text' }, // ← HTML 风格
|
|
238
|
+
{ name: 'active', label: '激活', inputType: 'checkbox' } // ← HTML 风格
|
|
239
|
+
];
|
|
240
|
+
|
|
241
|
+
// 对:PascalCase 严格枚举(IInputType union)
|
|
242
|
+
const config: IConfig[] = [
|
|
243
|
+
{ name: 'age', label: '年龄', inputType: 'InputNumber' }, // ← PascalCase
|
|
244
|
+
{ name: 'memo', label: '备注', inputType: 'TextField' }, // ← 不是 'text'
|
|
245
|
+
{ name: 'active', label: '激活', inputType: 'Switch' } // ← 不是 'checkbox'
|
|
246
|
+
// 完整枚举:'TextField'|'Select'|'Switch'|'InputNumber'|'InputLang'|'ComboSelect'|'DatePicker'|'custom'
|
|
247
|
+
];
|
|
248
|
+
```
|
|
249
|
+
**实证来源**:DynamicMultiBox/component.json `idealProps.config.description`,Task 15 失败根因。
|
|
250
|
+
|
|
251
|
+
### ❌ 陷阱 5:泛型业务类型缺少 index signature(TS2344)
|
|
252
|
+
```tsx
|
|
253
|
+
// 错
|
|
254
|
+
interface Param { foo: string } // 没有 index signature
|
|
255
|
+
<DynamicMultiBox<Param> config={config} valueList={valueList} />
|
|
256
|
+
// TS2344: Type 'Param' does not satisfy the constraint 'Record<string, unknown>'.
|
|
257
|
+
// Index signature for type 'string' is missing in type 'Param'.
|
|
258
|
+
|
|
259
|
+
// 对:加 index signature
|
|
260
|
+
interface Param {
|
|
261
|
+
foo: string;
|
|
262
|
+
[key: string]: unknown; // ← 必须加,满足 T extends Record<string, unknown> 约束
|
|
263
|
+
}
|
|
264
|
+
// 或:type Param = { foo: string } & Record<string, unknown>
|
|
265
|
+
<DynamicMultiBox<Param> config={config} valueList={valueList} /> // 编译通过
|
|
266
|
+
```
|
|
267
|
+
**实证来源**:DynamicMultiBox/component.json `typescriptPitfalls[5]`,Task 15 高频错误。
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## 真实参考
|
|
272
|
+
|
|
273
|
+
| 关键模式 | 参考位置 |
|
|
274
|
+
|---------|--------|
|
|
275
|
+
| 双 state 联动(valueList + errors) | DynamicMultiBox/component.json `commonPatterns.wrapperPattern` |
|
|
276
|
+
| `onAdd`/`onDelete` 双参数签名 | DynamicMultiBox/component.json `commonMisconceptions.M3` |
|
|
277
|
+
| `IConfig.name` narrow 写法 | DynamicMultiBox/component.json `typescriptPitfalls[0]` |
|
|
278
|
+
| `as unknown as` 业务类型中转 | DynamicMultiBox/component.json `typescriptPitfalls[1]` |
|
|
279
|
+
| `inputType` PascalCase 枚举 | DynamicMultiBox/component.json `typescriptPitfalls[2]` |
|
|
280
|
+
| index signature 约束 | DynamicMultiBox/component.json `typescriptPitfalls[5]` |
|
|
281
|
+
| `titleMode` 语义 | DynamicMultiBox/component.json `titleModeBehavior` |
|