web前端表单提交的时候需要记录有改变的字段,保存操作日志,表单含有子表以及嵌套对象,适用多层嵌套的表单
说明
项目上需要记录详细的用户操作日志,由于后台说系统日志可以记录每次操作的接口和入参出参,但是项目上要只展示给用户改变的字段,修改前和修改后的数据。
和后台讨论了很久,后台记录的话要在编辑前去查表对比,然后再更新表,比较麻烦。有些表单是很多表关联的,子表中的数据改变不太好记录,所以就由前端在提交编辑的时候进行对比数据,然后传给后台进行保存。本文主要记录一下筛选被修改的字段的方法。
废话不多说,直接上代码
getChangeFiled(newObj, oldObj, data) {
// 基于新旧数据不改变字段数据类型来判断,默认新旧数据都是对象,否则不执行
let type = typeof newObj;
let changeData = {};
if (data) {
changeData = data;
} else {
changeData = {
isChange: false,
changeData: [],
};
}
if (type == "object" && newObj && !Array.isArray(newObj)) {
// 数据为对象{}时才执行
let keysArr = Object.keys(newObj);
// 遍历对象
keysArr.forEach((key2, i) => {
let newData = newObj[key2];
let oldData = oldObj[key2];
let newFormat = typeof newData;
let oldFormat = typeof oldData;
if (newFormat == "object" && oldFormat == "object") {
// 判断数据是对象还是数组还是null,以新数据为准,不考虑新旧数据类型不同的情况
if (!newData) {
// 数据是null
if (newData!= oldData) {
changeData.isChange = true;
changeData.changeData.push({
oldData: oldData,
newData: newData,
key: key2,
});
}
} else if (Array.isArray(newData) && Array.isArray(oldData)) {
// 数据为数组
// 判断整个数组有无变化
if (JSON.stringify(newData) != JSON.stringify(oldData)) {
// 有变化,判断变化字段
changeData.isChange = true;
// 遍历新旧数组
let newIdArr = []; //新数据中所有的id
let oldIdArr = []; //旧数据中所有的id
newData.forEach((newItem, newIndex) => {
newIdArr = [newItem.id, ...newIdArr];
});
oldData.forEach((oldItem, newIndex) => {
oldIdArr = [oldItem.id, ...oldIdArr];
});
// 旧数据中有但是新数据中没有的id,被删除的id
let delIds = oldIdArr.filter((x) => {
return !newIdArr.includes(x);
});
// 遍历新数据
newData.forEach((newItem, newIndex) => {
if (!newItem.id) {
// 新增的数据,没有id
changeData.changeData.push({
oldData: "",
newData: newItem,
key: key2,
remarks: `新增1条数据`,
});
}
});
// 遍历旧数据
oldData.forEach((oldItem, newIndex) => {
delIds.forEach((delId) => {
// 被删除的数据
if (oldItem.id == delId) {
changeData.changeData.push({
oldData: oldItem,
newData: "",
key: key2,
remarks: `删除了1条id为${delId}的数据`,
});
}
});
});
// 找出被修改的数据,判断哪些字段做了修改
newData.forEach((newItem, newIndex) => {
oldData.forEach((oldItem, oldIndex) => {
if (oldItem.id == newItem.id) {
// 找出同一条数据,去做判断,编辑了哪些字段
this.getChangeFiled(newItem, oldItem, changeData);
}
});
});
}
} else {
// 数据为对象
this.getChangeFiled(newData, oldData, changeData);
}
} else if (newFormat !== "object" && oldFormat !== "object") {
// 不是对象的数据直接对比有没有变化
if (newFormat != "undefiend" || oldFormat != "undefiend") {
// 其他类型的直接对比即可
if (newData != oldData) {
// 有变化
changeData.isChange = true;
changeData.changeData.push({
oldData: oldData,
newData: newData,
key: key2,
});
}
}
}
});
console.log(changeData)
return changeData;
} else {
return false;
}
},
将上面的方法注入到全局,就可以愉快的在任何页面调用 了,调用的时候传前面两个参数,新数据和旧数据就可以了,会把被修改的字段返回。
let ChangeData = this.getChangeFiled(this.newData, this.oldData);
本人水平有限,有不足的地方欢迎指正。感谢阅读!