Compare commits

...

6 Commits
master ... 1.0

Author SHA1 Message Date
LiuJiaNan 2959b9e740 1.3.22 2026-06-24 14:40:53 +08:00
LiuJiaNan 4937d77709 feat(history): 支持自定义历史记录对象实现返回功能
- FormBuilder 组件新增 history 属性,允许注入自定义历史记录对象
- 优化 FormBuilder 的取消操作,优先调用 history.goBack 方法
- HeaderBack 组件修改返回点击事件,支持使用自定义 history 对象
- Page 组件返回按钮支持自定义历史记录回退行为
- README 更新,新增版本信息及 antd6 升级说明
2026-06-24 14:39:33 +08:00
LiuJiaNan 1befca1cac 1.3.21 2026-06-23 14:09:39 +08:00
LiuJiaNan 9527fec783 feat(FormBuilder): 支持Col和FormList行的样式及标题自定义
- 为FormItem增加colStyle属性,支持内联样式及函数动态计算
- 为FormItem增加colTitle属性,支持Col内部、Form.Item之间标题节点动态渲染
- 为FormList增加rowStyle属性,支持每行内联样式及基于字段动态计算
- 为FormList增加rowTitle属性,支持每行起始位置自定义标题节点及动态渲染
- FormItemsRenderer组件新增获取样式和标题的辅助函数,支持函数和静态配置
- 渲染时合并colStyle样式并插入colTitle标题节点
- FormList的每行Row增加rowStyle样式和rowTitle标题节点渲染
- 修正Select组件showSearch属性的写法,提升可用性
- 优化Form.Item内容器的flex样式,防止布局异常
2026-06-23 14:09:31 +08:00
LiuJiaNan fcfa539fc5 1.3.20 2026-06-22 10:52:40 +08:00
LiuJiaNan 43b36f1e26 fix(form): 修复表单项隐藏逻辑错误 2026-06-22 10:52:30 +08:00
7 changed files with 87 additions and 25 deletions

View File

@ -1,7 +1,7 @@
{
"name": "zy-react-library",
"private": false,
"version": "1.3.19",
"version": "1.3.22",
"type": "module",
"description": "",
"author": "LiuJiaNan",

View File

@ -44,6 +44,11 @@ export interface FormBuilderProps<Values = any> extends Omit<FormProps, "form" |
form: FormInstance<Values>;
/** 表单提交时的回调函数 */
onFinish?: (values: Values) => void;
/** 历史记录对象,用于返回上一页,默认使用 window.history.back */
history?: {
goBack?: () => void;
[key: string]: any;
};
}
/**

View File

@ -21,6 +21,7 @@ const FormBuilder = (props) => {
showCancelButton = true,
customActionButtons,
extraActionButtons,
history,
loading = false,
...restProps
} = props;
@ -51,7 +52,7 @@ const FormBuilder = (props) => {
}, [showActionButtons]);
const handleCancel = () => {
window.history.back();
history?.goBack ? history.goBack() : window.history.back();
};
return (

View File

@ -3,7 +3,7 @@ import type { FormItemProps, Rule } from "antd/es/form";
import type { FormListFieldData } from "antd/es/form/FormList";
import type { Gutter } from "antd/es/grid/row";
import type { NamePath } from "rc-field-form/lib/interface";
import type { ReactElement, ReactNode } from "react";
import type { CSSProperties, ReactElement, ReactNode } from "react";
import type { FORM_ITEM_RENDER_TYPE_MAP } from "../../enum/formItemRender";
import type { DeepPartial } from "./FormBuilder";
@ -131,6 +131,10 @@ export interface FormOptionBase<
dependencies?: FormOptionProperty<IsOnlyForLabel, IsCustomizeRender, Dependencies[]>;
/** 是否仅用于保存标签,不渲染到页面上,只在表单中保存数据,默认 false */
onlyForLabel?: IsOnlyForLabel;
/** Col 的内联样式,会合并到 Col 的 style 上,支持函数动态计算 */
colStyle?: FormOptionProperty<IsOnlyForLabel, IsCustomizeRender, CSSProperties | ((formValues: AllValues) => CSSProperties)>;
/** Col 内部、Form.Item 之前渲染的标题节点,支持函数动态计算 */
colTitle?: FormOptionProperty<IsOnlyForLabel, IsCustomizeRender, ReactNode | ((formValues: AllValues) => ReactNode)>;
}
/**
@ -157,6 +161,10 @@ export type FormOptionByRender<
checkboxCol?: FormOptionProperty<IsOnlyForLabel, IsCustomizeRender, RenderType extends "checkbox" ? number : never>;
/** Form.List 独有的属性 */
formListUniqueProps?: FormOptionProperty<IsOnlyForLabel, IsCustomizeRender, RenderType extends "formList" ? FormListUniqueProps | ((formValues: AllValues) => FormListUniqueProps) : never>;
/** FormList 每行的内联样式,仅 render 为 formList 时可用,支持函数按行计算 */
rowStyle?: FormOptionProperty<IsOnlyForLabel, IsCustomizeRender, RenderType extends "formList" ? CSSProperties | ((field: FormListFieldData, fieldIndex: number) => CSSProperties) : never>;
/** FormList 每行起始位置渲染的标题节点,仅 render 为 formList 时可用,支持函数按行计算 */
rowTitle?: FormOptionProperty<IsOnlyForLabel, IsCustomizeRender, RenderType extends "formList" ? ReactNode | ((field: FormListFieldData, fieldIndex: number) => ReactNode) : never>;
};
/**

View File

@ -84,12 +84,8 @@ const FormItemsRenderer = ({
};
};
// 获取传给formItem的属性
const getFormItemProps = (option) => {
const formItemProps = typeof option.formItemProps === "function"
? option.formItemProps(getFormValues())
: (option.formItemProps || {});
// 设置日期组件的属性
const setDateComponentProps = (option, formItemProps) => {
// 为日期组件添加特殊处理
if ([
FORM_ITEM_RENDER_ENUM.DATE,
@ -117,6 +113,15 @@ const FormItemsRenderer = ({
formItemProps.getValueFromEvent = (_, dateString) => dateString;
formItemProps.getValueProps = value => ({ value: Array.isArray(value) ? value.map(v => v ? dayjs(v) : undefined) : undefined });
}
};
// 获取传给 formItem 的属性
const getFormItemProps = (option) => {
const formItemProps = typeof option.formItemProps === "function"
? option.formItemProps(getFormValues())
: (option.formItemProps || {});
setDateComponentProps(option, formItemProps);
return formItemProps;
};
@ -218,6 +223,39 @@ const FormItemsRenderer = ({
return { span: itemSpan, labelCol: itemLabelCol, wrapperCol: itemWrapperCol };
};
// 获取 col 样式
const getColStyle = (option) => {
return typeof option.colStyle === "function"
? option.colStyle(getFormValues())
: option.colStyle;
};
// 获取 col 标题Col 内部、Form.Item 之后)
const getColTitle = (option) => {
return typeof option.colTitle === "function"
? option.colTitle(getFormValues())
: option.colTitle;
};
// 获取 row 样式FormList 的每一行)
const getRowStyle = (option, field, fieldIndex) => {
return typeof option.rowStyle === "function"
? option.rowStyle(field, fieldIndex)
: option.rowStyle;
};
// 获取 row 标题FormList 每行末尾)
const getRowTitle = (option, field, fieldIndex) => {
return typeof option.rowTitle === "function"
? option.rowTitle(field, fieldIndex)
: option.rowTitle;
};
// 获取是否动态表单项
const getIsDynamicFormItem = (option, formItemProps) => {
return (option.shouldUpdate ?? option.dependencies) || (formItemProps.shouldUpdate ?? formItemProps.dependencies);
};
// 获取 hidden
const getHidden = (hidden) => {
// 支持动态计算 hidden
@ -264,7 +302,7 @@ const FormItemsRenderer = ({
case FORM_ITEM_RENDER_ENUM.SELECT:
return (
<Select placeholder={placeholder} showSearch allowClear optionFilterProp="children" {...componentProps}>
<Select placeholder={placeholder} showSearch={{ optionFilterProp: "children" }} allowClear {...componentProps}>
{(option.items || []).map((item) => {
const { value, label, disabled } = getSelectableItemAttributes(item, itemsFieldKey);
return (
@ -420,8 +458,12 @@ const FormItemsRenderer = ({
delete formItemProps.dependencies;
delete formItemProps.shouldUpdate;
if (getHidden(option.hidden))
return null;
return (
<Col key={getKey(option) || index} span={col.span} style={style}>
<Col key={getKey(option) || index} span={col.span} style={{ ...style, ...getColStyle(option) }}>
{getColTitle(option)}
<Form.Item
name={option.name}
label={renderLabel(option)}
@ -503,18 +545,19 @@ const FormItemsRenderer = ({
const componentProps = getComponentProps(option);
return (
<Col key={getKey(option) || index} span={col.span} style={style}>
<Col key={getKey(option) || index} span={col.span} style={{ ...style, ...getColStyle(option) }}>
{getColTitle(option)}
<Form.List name={option.name} {...componentProps}>
{(fields, { add, remove, move }) => (
<>
{fields.map((field, fieldIndex) => {
const listOptions = getListOptions(formListUniqueProps.options, field, fieldIndex, add, remove, move);
const rowStyle = getRowStyle(option, field, fieldIndex);
const rowTitle = getRowTitle(option, field, fieldIndex);
return (
<Row gutter={gutter} key={field.key}>
<Row gutter={gutter} key={field.key} style={rowStyle}>
{rowTitle}
{listOptions.map((listOption, listIndex) => {
if (getHidden(listOption.hidden))
return null;
const col = getCol(listOption);
const formItemProps = getFormItemProps(listOption);
@ -532,7 +575,7 @@ const FormItemsRenderer = ({
if (listOption.render === FORM_ITEM_RENDER_ENUM.FORM_LIST)
return renderFormList(params);
if ((listOption.shouldUpdate ?? listOption.dependencies) || (formItemProps.shouldUpdate ?? formItemProps.dependencies))
if (getIsDynamicFormItem(listOption, formItemProps))
return renderDynamicFormItem(params);
// 判断一个项是否需要显示按钮(不是 onlyForLabel 且不是隐藏的)
@ -562,8 +605,10 @@ const FormItemsRenderer = ({
if (listIndex === lastShowIndex || isNextNestedFormList || isNextNoShow) {
delete formItemProps.dependencies;
delete formItemProps.shouldUpdate;
return (
<Col key={getKey(listOption) || listIndex} span={col.span} style={style}>
<Col key={getKey(listOption) || listIndex} span={col.span} style={{ ...style, ...getColStyle(listOption) }}>
{getColTitle(listOption)}
<Form.Item
label={renderLabel(listOption)}
labelCol={col.labelCol}
@ -574,7 +619,7 @@ const FormItemsRenderer = ({
{...formItemProps}
>
<div style={{ display: "flex", gap: 10, alignItems: "center", justifyContent: "space-between" }}>
<div style={{ flex: 1 }}>
<div style={{ flex: 1, minWidth: 0 }}>
<Form.Item
noStyle
rules={getRules(listOption)}
@ -632,9 +677,6 @@ const FormItemsRenderer = ({
return (
<>
{options.map((option, index) => {
if (getHidden(option.hidden))
return null;
const col = getCol(option);
const style = getStyle(index);
const formItemProps = getFormItemProps(option);
@ -657,7 +699,7 @@ const FormItemsRenderer = ({
return renderFormList(params);
// 如果配置了 shouldUpdate 或 dependencies使用 Form.Item 的联动机制
if ((option.shouldUpdate ?? option.dependencies) || (formItemProps.shouldUpdate ?? formItemProps.dependencies))
if (getIsDynamicFormItem(option, formItemProps))
return renderDynamicFormItem(params);
// 普通表单项(静态配置)

View File

@ -17,7 +17,9 @@ function HeaderBack(props) {
<>
<div
className="back"
onClick={() => history?.goBack?.() || window.history.back()}
onClick={() => {
history?.goBack ? history.goBack() : window.history.back();
}}
>
<ArrowLeftOutlined style={{ fontSize: 14 }} />
<span>返回</span>

View File

@ -61,7 +61,11 @@ function Page(props) {
{customActionButtons || (
<Space>
{extraActionButtons}
<Button onClick={() => history?.goBack?.() || window.history.back()}>
<Button
onClick={() => {
history?.goBack ? history.goBack() : window.history.back();
}}
>
{backButtonText}
</Button>
</Space>