树形结构数据,判断重复规则
- 同一层级不能出现重复,不同层级可重复
- 非空判断
逻辑判断
// 只平铺一层数组
flattenTreeLevelFn(tree) {
let result = []
for (let i = 0; i < tree.length; i++) {
const node = tree[i]
result.push({ ...node })
}
return result
},
// 判断平铺数组中是否有重复数据
handleDuplicate(flatData) {
const queue = [...flatData]
while (queue.length > 0) {
const label = this.unPackType[this.type].label
// 当前层级节点数
const levelSize = queue.length
// 当前层级的path集合
const paths = new Set()
// 当前层级的key集合
const keys = new Set()
for (let i = 0; i < levelSize; i++) {
// 获取当前节点
const node = queue.shift(),
path = node['attributePath'],
key = node['freemarkerKey']
// 判断path集合中是否已经存在该path值
if (paths.has(path)) {
this.$message.error(`${label}中:字段路径【${path}】数据重复`)
throw new Error('存在重复数据')
} else if (keys.has(key)) {
this.$message.error(`${label}中:字段key值【${key}】数据重复`)
throw new Error('存在重复数据')
}
// 空数据也会判断重复,所有去除非空值再判断
if (path) paths.add(path)
if (key) keys.add(key)
}
}
},
// 遍历数组平铺每一层级判断是否有重复数据
processNodeLevelFn(tree) {
if (tree.length === 0) return false
const flatData = this.flattenTreeLevelFn(tree)
this.handleDuplicate(flatData)
for (let i = 0; i < tree.length; i++) {
const node = tree[i]
if (node.children && node.children.length > 0) {
this.processNodeLevelFn(node.children)
}
}
},
// 判断是否有重复数据:同一层级不能出现重复,不同层级可重复
isHasDuplicateLevelFn() {
// return 只能跳出当前函数,对于嵌套函数可以使用throw抛出错误,使用try...catch捕获错误
try {
this.processNodeLevelFn(this.treeData)
return false
} catch (error) {
return true
}
},
isHasEmptyLevelFn() {
let allValid = true
const traverseNodes = (nodes) => {
nodes?.forEach((node) => {
node.pathValid = node?.attributePath ? false : true
node.keyValid = node.disabled ? false : node.freemarkerKey ? false : true
if (node.pathValid || node.keyValid || node.typeValid) {
allValid = false
}
if (node.children && node.children.length > 0) {
traverseNodes(node.children)
}
})
return allValid
}
traverseNodes(this.treeData)
if (!allValid) {
this.$message.error(`${this.unPackType[this.type].label}中表单未填写完整`)
}
return allValid
},
handleValidate() {
this.handleFormSubmit()
},
// 确定按钮-先校验-后保存
handleFormSubmit(type = 'save') {
// return 只能跳出当前函数,对于嵌套函数可以使用标志变量flag
let flag = false
if (!this.isHasEmptyLevelFn()) {
console.log('error submit!-空值')
flag = false
} else if (this.isHasDuplicateLevelFn()) {
console.log('error submit!-重复值')
flag = false
} else {
if (type !== 'look') this.saveData()
flag = true
}
return flag
},
saveData() {
console.log(this.treeData, 'this.treeData')
},
示例图
treeData数据
treeData: [
{
key: '1',
packType: '2',
filePath: 'Head',
fileKey: '',
pathValid: false,
keyValid: false,
typeValid: false,
children: [
{
key: '1-1',
packType: '1',
children: [],
filePath: 'SvcScnAA',
fileKey: 'SvcScnAA_1',
pathValid: false,
keyValid: false,
isEdit: 1,
status: 'append',
typeValid: false,
disabled: false,
},
{
key: '1-2',
packType: '2',
children: [
{
key: '1-2-1',
packType: '1',
children: [],
filePath: 'SvcScn',
fileKey: '',
pathValid: false,
keyValid: false,
isEdit: 1,
status: 'append',
typeValid: false,
disabled: true,
},
],
filePath: 'SvcScnObj',
fileKey: '',
pathValid: false,
keyValid: false,
isEdit: 1,
status: 'append',
typeValid: false,
disabled: true,
freemarkerKey: '',
},
{
key: '1-3',
packType: '3',
children: [],
filePath: 'SvcScnList',
fileKey: 'SvcScnList_1',
pathValid: false,
keyValid: false,
isEdit: 1,
status: 'append',
typeValid: false,
disabled: false,
freemarkerKey: '',
},
],
isEdit: 1,
status: 'append',
disabled: true,
freemarkerKey: '',
},
{
key: '2',
packType: '2',
filePath: 'Body',
fileKey: '',
pathValid: false,
keyValid: false,
typeValid: false,
children: [
{
key: '2-3',
packType: '2',
children: [
{
key: '2-3-1',
packType: '1',
children: [],
filePath: '44',
fileKey: '',
pathValid: false,
keyValid: false,
isEdit: 1,
status: 'append',
typeValid: false,
disabled: true,
},
],
filePath: '3',
fileKey: '',
pathValid: false,
keyValid: false,
isEdit: 1,
status: 'append',
typeValid: false,
disabled: true,
freemarkerKey: '',
},
],
isEdit: 1,
status: 'append',
disabled: true,
freemarkerKey: '',
},
],