fix: 修复 inputTable 中自动计算值更新不正确的问题 Close:#8263 (#8436)

This commit is contained in:
liaoxuezhi 2023-10-24 14:05:55 +08:00 committed by GitHub
parent af806d553c
commit 1f4f491965
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 126 additions and 102 deletions

View File

@ -1340,108 +1340,119 @@ export default class FormTable extends React.Component<TableProps, TableState> {
diff: Array<object> | object,
rowIndexes: Array<string> | string
) {
const {perPage} = this.props;
const editIndex = this.state.editIndex;
const lastModifiedRow = this.state.lastModifiedRow;
if (~editIndex) {
const items = this.state.items.concat();
const origin = items[editIndex];
if (!origin) {
return;
}
const value: any = {
...rows
};
this.entries.set(value, this.entries.get(origin) || this.entityId++);
this.entries.delete(origin);
items.splice(editIndex, 1, value);
this.setState({
items,
/** 记录最近一次编辑记录,用于取消编辑数据回溯, */
...(lastModifiedRow?.index === editIndex
? {}
: {
lastModifiedRow: origin.__isPlaceholder
? undefined
: {index: editIndex, data: {...origin}}
})
});
return;
}
const page = this.state.page;
let items = this.state.items.concat();
if (Array.isArray(rows)) {
(rowIndexes as Array<string>).forEach((rowIndex, index) => {
const indexes = rowIndex.split('.').map(item => parseInt(item, 10));
if (page && page > 1 && typeof perPage === 'number') {
indexes[0] += (page - 1) * perPage;
}
const origin = getTree(items, indexes);
const data = merge({}, origin, (diff as Array<object>)[index]);
items = spliceTree(items, indexes, 1, data);
});
} else {
const indexes = (rowIndexes as string)
.split('.')
.map(item => parseInt(item, 10));
if (page && page > 1 && typeof perPage === 'number') {
indexes[0] += (page - 1) * perPage;
}
const origin = getTree(items, indexes);
const comboNames: Array<string> = [];
(this.props.$schema.columns ?? []).forEach((e: any) => {
if (e.type === 'combo' && !Array.isArray(diff)) {
comboNames.push(e.name);
}
});
const data = mergeWith(
{},
origin,
diff,
(
objValue: any,
srcValue: any,
key: string,
object: any,
source: any,
stack: any
) => {
// 只对第一层做处理如果不是combo并且是数组直接采用diff的值
if (
stack.size === 0 &&
comboNames.indexOf(key) === -1 &&
Array.isArray(objValue) &&
Array.isArray(srcValue)
) {
return srcValue;
}
// 直接return默认走的mergeWith自身的merge
return;
}
);
items = spliceTree(items, indexes, 1, data);
this.entries.set(data, this.entries.get(origin) || this.entityId++);
// this.entries.delete(origin); // 反正最后都会清理的,先不删了吧。
}
let callback: any;
// 这里有可能执行频率非常高,上次的变更还没结束就会再次进来,会拿不到最新的数据
// https://legacy.reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
this.setState(
{
items
(state, props) => {
const newState = {};
const {perPage} = props;
const editIndex = state.editIndex;
const lastModifiedRow = state.lastModifiedRow;
if (~editIndex) {
const items = state.items.concat();
const origin = items[editIndex];
if (!origin) {
return newState;
}
const value: any = {
...rows
};
this.entries.set(value, this.entries.get(origin) || this.entityId++);
this.entries.delete(origin);
items.splice(editIndex, 1, value);
Object.assign(newState, {
items,
/** 记录最近一次编辑记录,用于取消编辑数据回溯, */
...(lastModifiedRow?.index === editIndex
? {}
: {
lastModifiedRow: origin.__isPlaceholder
? undefined
: {index: editIndex, data: {...origin}}
})
});
return newState;
}
const page = state.page;
let items = state.items.concat();
if (Array.isArray(rows)) {
(rowIndexes as Array<string>).forEach((rowIndex, index) => {
const indexes = rowIndex.split('.').map(item => parseInt(item, 10));
if (page && page > 1 && typeof perPage === 'number') {
indexes[0] += (page - 1) * perPage;
}
const origin = getTree(items, indexes);
const data = merge({}, origin, (diff as Array<object>)[index]);
items = spliceTree(items, indexes, 1, data);
});
} else {
const indexes = (rowIndexes as string)
.split('.')
.map(item => parseInt(item, 10));
if (page && page > 1 && typeof perPage === 'number') {
indexes[0] += (page - 1) * perPage;
}
const origin = getTree(items, indexes);
const comboNames: Array<string> = [];
(props.$schema.columns ?? []).forEach((e: any) => {
if (e.type === 'combo' && !Array.isArray(diff)) {
comboNames.push(e.name);
}
});
const data = mergeWith(
{},
origin,
diff,
(
objValue: any,
srcValue: any,
key: string,
object: any,
source: any,
stack: any
) => {
// 只对第一层做处理如果不是combo并且是数组直接采用diff的值
if (
stack.size === 0 &&
comboNames.indexOf(key) === -1 &&
Array.isArray(objValue) &&
Array.isArray(srcValue)
) {
return srcValue;
}
// 直接return默认走的mergeWith自身的merge
return;
}
);
items = spliceTree(items, indexes, 1, data);
this.entries.set(data, this.entries.get(origin) || this.entityId++);
// this.entries.delete(origin); // 反正最后都会清理的,先不删了吧。
}
Object.assign(newState, {
items
});
callback = this.emitValue;
return newState;
},
this.emitValue
() => {
callback && callback();
}
);
}

View File

@ -339,11 +339,11 @@ export const HocQuickEdit =
onQuickChange(values, false, true);
}
handleChange(values: object) {
handleChange(values: object, diff?: any) {
const {onQuickChange, quickEdit} = this.props;
onQuickChange(
values,
diff, // 只变化差异部分,其他值有可能是旧的
(quickEdit as QuickEditConfig).saveImmediately,
false,
quickEdit as QuickEditConfig

View File

@ -1063,6 +1063,19 @@ export default class Table extends React.Component<TableProps, object> {
item.change(values, savePristine);
// 依然解决不了问题,所以先注释掉
// 预期是,这个表党项修改的时候,把其他还没运算公式的表单更新最新值
// 好让公式计算触发的值是最新的
// 但是事与愿违,应该是修改了 store.data 但是 props.data 还没变过来
// 即便如此,但是最终还是会算正确,只是会多触发几次 onChange :(
// const y = item.index;
// const str = `-${y}`;
// Object.keys(this.subForms).forEach(key => {
// if (key.endsWith(str)) {
// this.subForms[key].props.store.updateData(values);
// }
// });
// 值发生变化了,需要通过 onSelect 通知到外面,否则会出现数据不同步的问题
item.modified && this.syncSelected();