fix: 修复 inputFile 的initAutoFill false 功能 Close: #7087 (#7191)

* chore: tpl 初始用同步模版渲染后更新异步模版 Close: #7099

* fix: 修复 inputFile 的initAutoFill false 功能 Close: #7087
This commit is contained in:
liaoxuezhi 2023-06-16 17:49:02 +08:00 committed by GitHub
parent a97dfe234d
commit 132761fcf1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 55 deletions

View File

@ -223,14 +223,18 @@ export function wrapControl<
if (propValue !== undefined && propValue !== null) { if (propValue !== undefined && propValue !== null) {
// 同步 value: 优先使用 props 中的 value // 同步 value: 优先使用 props 中的 value
model.changeTmpValue(propValue); model.changeTmpValue(propValue, 'controlled');
} else { } else {
// 备注: 此处的 value 是 schema 中的 value和props.defaultValue相同 // 备注: 此处的 value 是 schema 中的 value和props.defaultValue相同
const curTmpValue = isExpression(value) const isExp = isExpression(value);
const curTmpValue = isExp
? FormulaExec['formula'](value, data) // 对组件默认值进行运算 ? FormulaExec['formula'](value, data) // 对组件默认值进行运算
: store?.getValueByName(model.name) ?? replaceExpression(value); // 优先使用公式表达式 : store?.getValueByName(model.name) ?? replaceExpression(value); // 优先使用公式表达式
// 同步 value // 同步 value
model.changeTmpValue(curTmpValue); model.changeTmpValue(
curTmpValue,
isExp ? 'formulaChanged' : 'defaultValue'
);
} }
if ( if (
@ -354,7 +358,7 @@ export function wrapControl<
!isEqual(props.value, model.tmpValue) !isEqual(props.value, model.tmpValue)
) { ) {
// 外部直接传入的 value 无需执行运算器 // 外部直接传入的 value 无需执行运算器
model.changeTmpValue(props.value); model.changeTmpValue(props.value, 'controlled');
} }
} else if ( } else if (
model && model &&
@ -386,46 +390,39 @@ export function wrapControl<
!isEqual(curResult, model.tmpValue) !isEqual(curResult, model.tmpValue)
) { ) {
// 识别上下文变动、自身数值变动、公式运算结果变动 // 识别上下文变动、自身数值变动、公式运算结果变动
model.changeTmpValue(curResult); model.changeTmpValue(curResult, 'formulaChanged');
props.onChange?.(curResult, model.name, false); props.onChange?.(curResult, model.name, false);
} else if (nowFormulaChecked) { } else if (nowFormulaChecked) {
const nowData = props.data[model.name]; const nowData = props.data[model.name];
// now 表达式,计算后的值永远相同 // now 表达式,计算后的值永远相同
model.changeTmpValue(nowData); model.changeTmpValue(nowData, 'formulaChanged');
props.onChange?.(nowData, model.name, false); props.onChange?.(nowData, model.name, false);
} }
} }
} else if (model) { } else if (model) {
const valueByName = getVariable(props.data, model.name); const valueByName = getVariable(props.data, model.name);
if (isEqual(props.defaultValue, prevProps.defaultValue)) { // value 非公式表达式时name 值优先,若 defaultValue 主动变动时,则使用 defaultValue
// value 非公式表达式时name 值优先,若 defaultValue 主动变动时,则使用 defaultValue if (
if ( // 然后才是查看关联的 name 属性值是否变化
// 然后才是查看关联的 name 属性值是否变化 props.data !== prevProps.data &&
props.data !== prevProps.data && (!model.emitedValue ||
(!model.emitedValue || isEqual(model.emitedValue, model.tmpValue))
isEqual(model.emitedValue, model.tmpValue))
) {
model.changeEmitedValue(undefined);
const prevValueByName = getVariable(props.data, model.name);
if (
(!isEqual(valueByName, prevValueByName) ||
getVariable(props.data, model.name, false) !==
getVariable(prevProps.data, model.name, false)) &&
!isEqual(valueByName, model.tmpValue)
) {
model.changeTmpValue(valueByName);
}
}
} else if (
!isEqual(props.defaultValue, prevProps.defaultValue) &&
!isEqual(props.defaultValue, model.tmpValue)
) { ) {
// 组件默认值非公式 model.changeEmitedValue(undefined);
const curValue = replaceExpression(props.defaultValue); const prevValueByName = getVariable(props.data, model.name);
model.changeTmpValue(curValue); if (
if (props.onChange) { (!isEqual(valueByName, prevValueByName) ||
props.onChange(curValue, model.name, false); getVariable(props.data, model.name, false) !==
getVariable(prevProps.data, model.name, false)) &&
!isEqual(valueByName, model.tmpValue)
) {
model.changeTmpValue(
valueByName,
props.formInited && !prevProps.formInited
? 'formInited'
: 'dataChanged'
);
} }
} }
} }
@ -589,7 +586,7 @@ export function wrapControl<
value = pipeOut(value, oldValue, data); value = pipeOut(value, oldValue, data);
} }
this.model.changeTmpValue(value); this.model.changeTmpValue(value, 'input');
if (changeImmediately || conrolChangeImmediately || !formInited) { if (changeImmediately || conrolChangeImmediately || !formInited) {
this.emitChange(submitOnChange); this.emitChange(submitOnChange);
@ -762,6 +759,7 @@ export function wrapControl<
ref: this.controlRef, ref: this.controlRef,
data: data || store?.data, data: data || store?.data,
value, value,
changeMotivation: model?.changeMotivation,
defaultValue: control.value, defaultValue: control.value,
formItemValue: value, // 为了兼容老版本的自定义组件 formItemValue: value, // 为了兼容老版本的自定义组件
onChange: this.handleChange, onChange: this.handleChange,

View File

@ -61,6 +61,7 @@ export const FormItemStore = StoreNode.named('FormItemStore')
isValueSchemaExp: types.optional(types.boolean, false), isValueSchemaExp: types.optional(types.boolean, false),
tmpValue: types.frozen(), tmpValue: types.frozen(),
emitedValue: types.frozen(), emitedValue: types.frozen(),
changeMotivation: 'input',
rules: types.optional(types.frozen(), {}), rules: types.optional(types.frozen(), {}),
messages: types.optional(types.frozen(), {}), messages: types.optional(types.frozen(), {}),
errorData: types.optional(types.array(ErrorDetail), []), errorData: types.optional(types.array(ErrorDetail), []),
@ -1232,8 +1233,20 @@ export const FormItemStore = StoreNode.named('FormItemStore')
} }
} }
function changeTmpValue(value: any) { function changeTmpValue(
value: any,
changeReason?:
| 'formInited' // 表单初始化
| 'dataChanged' // 表单数据变化
| 'formulaChanged' // 公式运算结果变化
| 'controlled' // 受控
| 'input' // 用户交互改变
| 'defaultValue' // 默认值
) {
self.tmpValue = value; self.tmpValue = value;
if (changeReason) {
self.changeMotivation = changeReason;
}
} }
function changeEmitedValue(value: any) { function changeEmitedValue(value: any) {

View File

@ -208,7 +208,7 @@ export class ItemPlugin extends BasePlugin {
const context = event.context; const context = event.context;
if ( if (
/\$/.test(context.info.renderer.name!) && context.info.renderer.isFormItem &&
context.diff?.some(change => change.path?.join('.') === 'value') context.diff?.some(change => change.path?.join('.') === 'value')
) { ) {
const change: any = find( const change: any = find(

View File

@ -348,7 +348,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
file: any; file: any;
executor: () => void; executor: () => void;
}> = []; }> = [];
initAutoFill: boolean; initedFilled = false;
static valueToFile( static valueToFile(
value: string | FileValue, value: string | FileValue,
@ -398,7 +398,6 @@ export default class FileControl extends React.Component<FileProps, FileState> {
const joinValues = props.joinValues; const joinValues = props.joinValues;
const delimiter = props.delimiter as string; const delimiter = props.delimiter as string;
let files: Array<FileValue> = []; let files: Array<FileValue> = [];
this.initAutoFill = !!props.initAutoFill;
if (value && value instanceof Blob) { if (value && value instanceof Blob) {
files = [value as any]; files = [value as any];
@ -438,11 +437,16 @@ export default class FileControl extends React.Component<FileProps, FileState> {
} }
componentDidMount() { componentDidMount() {
if (this.initAutoFill) { const {formInited, addHook} = this.props;
const {formInited, addHook} = this.props;
formInited || !addHook if (formInited || !addHook) {
? this.syncAutoFill() this.initedFilled = true;
: addHook(this.syncAutoFill, 'init'); this.props.initAutoFill && this.syncAutoFill();
} else if (addHook) {
addHook(() => {
this.initedFilled = true;
this.props.initAutoFill && this.syncAutoFill();
}, 'init');
} }
} }
@ -494,7 +498,9 @@ export default class FileControl extends React.Component<FileProps, FileState> {
{ {
files: files files: files
}, },
props.formInited !== false ? this.syncAutoFill : undefined props.changeMotivation !== 'formInited' && this.initedFilled
? this.syncAutoFill
: undefined
); );
} }
} }
@ -1486,7 +1492,8 @@ export default class FileControl extends React.Component<FileProps, FileState> {
{files.map((file, index) => { {files.map((file, index) => {
const filename = const filename =
file[nameField as keyof typeof file] || file[nameField as keyof typeof file] ||
(file as FileValue).filename; (file as FileValue).filename ||
file.name;
return ( return (
<li key={file.id}> <li key={file.id}>

View File

@ -373,7 +373,8 @@ export default class ImageControl extends React.Component<
delimiter: ',', delimiter: ',',
autoUpload: true, autoUpload: true,
multiple: false, multiple: false,
dropCrop: true dropCrop: true,
initAutoFill: true
}; };
static valueToFile( static valueToFile(
@ -428,7 +429,7 @@ export default class ImageControl extends React.Component<
resolve?: (value?: any) => void; resolve?: (value?: any) => void;
emitValue: any; emitValue: any;
unmounted = false; unmounted = false;
initAutoFill: boolean; initedFilled = false;
// 文件重新上传的位置标记,用以定位替换 // 文件重新上传的位置标记,用以定位替换
reuploadIndex: undefined | number = undefined; reuploadIndex: undefined | number = undefined;
@ -439,7 +440,6 @@ export default class ImageControl extends React.Component<
const joinValues = props.joinValues; const joinValues = props.joinValues;
const delimiter = props.delimiter as string; const delimiter = props.delimiter as string;
let files: Array<FileValue> = []; let files: Array<FileValue> = [];
this.initAutoFill = !!(props.initAutoFill ?? true);
if (value) { if (value) {
// files = (multiple && Array.isArray(value) ? value : joinValues ? (value as string).split(delimiter) : [value]) // files = (multiple && Array.isArray(value) ? value : joinValues ? (value as string).split(delimiter) : [value])
@ -488,11 +488,16 @@ export default class ImageControl extends React.Component<
} }
componentDidMount() { componentDidMount() {
if (this.initAutoFill) { const {formInited, addHook} = this.props;
const {formInited, addHook} = this.props;
formInited || !addHook if (formInited || !addHook) {
? this.syncAutoFill() this.initedFilled = true;
: addHook(this.syncAutoFill, 'init'); this.props.initAutoFill && this.syncAutoFill();
} else if (addHook) {
addHook(() => {
this.initedFilled = true;
this.props.initAutoFill && this.syncAutoFill();
}, 'init');
} }
if (this.props.initCrop && this.files.length) { if (this.props.initCrop && this.files.length) {
@ -545,7 +550,9 @@ export default class ImageControl extends React.Component<
{ {
files: (this.files = files) files: (this.files = files)
}, },
this.initAutoFill ? this.syncAutoFill : () => {} props.changeMotivation !== 'formInited' && this.initedFilled
? this.syncAutoFill
: undefined
); );
} }
@ -1380,7 +1387,7 @@ export default class ImageControl extends React.Component<
}, },
() => { () => {
if (!needUploading) { if (!needUploading) {
this.onChange(false, true, this.initAutoFill); this.onChange(false, true, this.props.initAutoFill);
} }
} }
); );