mirror of
https://github.com/dataease/dataease.git
synced 2026-05-15 05:22:13 +08:00
refactor: 外部参数使用过滤选项时,支持关联过滤组件的图表使用过滤选项过滤结果 (#17846)
This commit is contained in:
@@ -396,35 +396,93 @@ const tagColor = computed(() => {
|
||||
.toRGB()
|
||||
})
|
||||
|
||||
const filterTree = (treeData, filterIds) => {
|
||||
function filterTree(treeData, filterIds) {
|
||||
if (!filterIds || filterIds.length === 0) {
|
||||
return treeData
|
||||
}
|
||||
const filterIdSet = new Set(filterIds)
|
||||
// 递归处理每个节点
|
||||
const recursionFilter = node => {
|
||||
const newNode = { ...node }
|
||||
const filterSet = new Set(filterIds)
|
||||
|
||||
// 2. 处理子节点:有子节点才过滤,无子节点直接返回当前节点
|
||||
if (newNode.children && Array.isArray(newNode.children) && newNode.children.length > 0) {
|
||||
// 筛选出当前节点的子节点中,id在过滤清单里的「命中子节点」
|
||||
const hitChildren = newNode.children.filter(child => filterIdSet.has(child.id))
|
||||
// 用于存储最终保留的所有节点ID
|
||||
const keepIds = new Set()
|
||||
|
||||
if (hitChildren.length > 0) {
|
||||
// 规则1:当前层级有命中的子节点 → 只保留命中的,递归过滤其子节点
|
||||
newNode.children = hitChildren.map(child => recursionFilter(child))
|
||||
} else {
|
||||
// 规则2:当前层级无命中的子节点 → 完整保留所有子节点,子节点也不做过滤
|
||||
newNode.children = [...newNode.children]
|
||||
// 用于查找节点的Map
|
||||
const nodeMap = new Map()
|
||||
// 用于构建节点关系的Map(子节点到父节点)
|
||||
const parentMap = new Map()
|
||||
|
||||
// 遍历所有节点,构建Map和父子关系
|
||||
function traverse(nodes, parentId = null) {
|
||||
for (const node of nodes) {
|
||||
nodeMap.set(node.id, node)
|
||||
if (parentId) {
|
||||
parentMap.set(node.id, parentId)
|
||||
}
|
||||
|
||||
// 递归处理子节点
|
||||
if (node.children && node.children.length > 0) {
|
||||
traverse(node.children, node.id)
|
||||
}
|
||||
}
|
||||
return newNode
|
||||
}
|
||||
|
||||
// 根节点过滤:只保留根节点id在过滤清单中的节点,再递归处理子节点
|
||||
return treeData
|
||||
.filter(rootNode => filterIdSet.has(rootNode.id))
|
||||
.map(node => recursionFilter(node))
|
||||
// 收集所有匹配的节点及其祖先和后代
|
||||
function collectRelatedNodes(nodeId) {
|
||||
if (keepIds.has(nodeId)) return
|
||||
|
||||
keepIds.add(nodeId)
|
||||
const node = nodeMap.get(nodeId)
|
||||
|
||||
// 1. 收集所有祖先节点
|
||||
let currentId = nodeId
|
||||
while (parentMap.has(currentId)) {
|
||||
const parentId = parentMap.get(currentId)
|
||||
keepIds.add(parentId)
|
||||
currentId = parentId
|
||||
}
|
||||
|
||||
// 2. 收集所有后代节点(递归)
|
||||
function collectDescendants(node) {
|
||||
if (node.children && node.children.length > 0) {
|
||||
for (const child of node.children) {
|
||||
keepIds.add(child.id)
|
||||
collectDescendants(child)
|
||||
}
|
||||
}
|
||||
}
|
||||
collectDescendants(node)
|
||||
}
|
||||
|
||||
// 第二步:递归构建过滤后的树
|
||||
function buildFilteredTree(nodes) {
|
||||
const result = []
|
||||
|
||||
for (const node of nodes) {
|
||||
// 如果节点ID在保留集合中,则保留该节点
|
||||
if (keepIds.has(node.id)) {
|
||||
const newNode = { ...node }
|
||||
|
||||
// 递归处理子节点
|
||||
if (newNode.children && newNode.children.length > 0) {
|
||||
newNode.children = buildFilteredTree(newNode.children)
|
||||
}
|
||||
|
||||
result.push(newNode)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// 执行遍历和构建
|
||||
traverse(treeData)
|
||||
|
||||
for (const filterId of filterIds) {
|
||||
if (nodeMap.has(filterId)) {
|
||||
collectRelatedNodes(filterId)
|
||||
}
|
||||
}
|
||||
|
||||
return buildFilteredTree(treeData)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -369,12 +369,25 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
|
||||
|
||||
const isTree = +displayType === 9
|
||||
if (optionFilter) {
|
||||
let fieldIdOption = item.checkedFieldsMap[curComponentId]
|
||||
const optionFilterValue = isTree
|
||||
? optionFilter.map(itemOption => itemOption.replace(/-de-/g, ','))
|
||||
: optionFilter
|
||||
if (isTree) {
|
||||
const [i, r] = getFieldId(
|
||||
treeFieldList,
|
||||
optionFilterValue,
|
||||
relationshipChartIndex,
|
||||
ids
|
||||
)
|
||||
fieldIdOption = i
|
||||
}
|
||||
filter.push({
|
||||
filterId: id,
|
||||
componentId: ele.id,
|
||||
fieldId: item.checkedFieldsMap[curComponentId],
|
||||
fieldId: fieldIdOption,
|
||||
operator: 'in',
|
||||
value: optionFilter,
|
||||
value: optionFilterValue,
|
||||
parameters: [],
|
||||
isTree
|
||||
})
|
||||
|
||||
@@ -1289,9 +1289,15 @@ export const dvMainStore = defineStore('dataVisualization', {
|
||||
if (element.component === 'VQuery') {
|
||||
element.propValue?.forEach(filterItem => {
|
||||
if (filterItem.id === targetViewId) {
|
||||
let queryParams = paramValue
|
||||
const targetMatchMode = targetInfoArray[2] // 目标匹配模式
|
||||
if (targetMatchMode === 'filter') {
|
||||
paramValue = paramValue.map(option => {
|
||||
if (typeof option === 'string' && option.includes(',')) {
|
||||
return option.replace(/,/g, '-de-')
|
||||
}
|
||||
return option
|
||||
})
|
||||
const queryParams = paramValue
|
||||
// do filter
|
||||
filterItem['optionFilter'] = queryParams
|
||||
if (filterItem.defaultValueCheck) {
|
||||
|
||||
Reference in New Issue
Block a user