diff --git a/core/core-frontend/src/custom-component/v-query/Select.vue b/core/core-frontend/src/custom-component/v-query/Select.vue index 3a14d603a6..2353cb72a7 100644 --- a/core/core-frontend/src/custom-component/v-query/Select.vue +++ b/core/core-frontend/src/custom-component/v-query/Select.vue @@ -26,9 +26,11 @@ import colorFunctions from 'less/lib/less/functions/color.js' import colorTree from 'less/lib/less/tree/color.js' import { colorStringToHex } from '@/utils/color' import { isMobile } from '@/utils/utils' +import { ElMessage } from 'element-plus-secondary' interface SelectConfig { selectValue: any + required: false defaultMapValue: any mapValue: any displayFormat?: number @@ -70,6 +72,7 @@ const props = defineProps({ default: () => { return { selectValue: '', + required: false, displayFormat: 0, queryConditionWidth: 0, resultMode: 0, @@ -301,7 +304,20 @@ const handleFieldIdDefaultChange = (val: string[]) => { ? [...selectValue.value] : selectValue.value } - setEmptyData() + if (config.value?.required && config.value?.optionFilter?.length > 0) { + const isValid = selectValue.value?.some(value => + options.value?.some(option => option.value === value) + ) + if (!isValid) { + config.value.selectValue = null + ElMessage({ + message: `【${config.value?.name}】${t('v_query.before_querying')}`, + type: 'error', + duration: 3000 + }) + } + } + if (options.value) setEmptyData() }) } @@ -435,6 +451,19 @@ const handleFieldIdChange = (val: EnumValue) => { ? [...selectValue.value] : selectValue.value } + if (config.value?.required && config.value?.optionFilter?.length > 0) { + const isValid = selectValue.value?.some(value => + options.value?.some(option => option.value === value) + ) + if (!isValid) { + config.value.selectValue = null + ElMessage({ + message: `【${config.value?.name}】${t('v_query.before_querying')}`, + type: 'error', + duration: 3000 + }) + } + } setCascadeValueBack(config.value.mapValue) isFromRemote.value = false }) diff --git a/core/core-frontend/src/custom-component/v-query/Tree.vue b/core/core-frontend/src/custom-component/v-query/Tree.vue index 44d7cabda8..dcc080d738 100644 --- a/core/core-frontend/src/custom-component/v-query/Tree.vue +++ b/core/core-frontend/src/custom-component/v-query/Tree.vue @@ -18,9 +18,13 @@ import { getFieldTree } from '@/api/dataset' import colorFunctions from 'less/lib/less/functions/color.js' import colorTree from 'less/lib/less/tree/color.js' import { colorStringToHex } from '@/utils/color' +import { ElMessage } from 'element-plus-secondary' +import { useI18n } from '@/hooks/web/useI18n' +const { t } = useI18n() interface SelectConfig { selectValue: any + required: false defaultMapValue: any defaultValue: any queryConditionWidth: number @@ -51,6 +55,7 @@ const props = defineProps({ return { selectValue: '', defaultValue: '', + required: false, queryConditionWidth: 0, displayType: '', resultMode: 0, @@ -314,6 +319,39 @@ const dfsAuth = (tree, val) => { }) } +function containsNodeById(source, params) { + // 统一处理参数为数组 + const searchIds = Array.isArray(params) ? params : [params] + + // 递归搜索函数 + function searchById(node) { + // 检查当前节点的id是否在搜索列表中 + if (searchIds.includes(node.id)) { + return true + } + + // 递归搜索子节点 + if (node.children && node.children.length > 0) { + for (const child of node.children) { + if (searchById(child)) { + return true + } + } + } + + return false + } + + // 遍历所有根节点 + for (const node of source) { + if (searchById(node)) { + return true + } + } + + return false +} + const getTreeOption = debounce(() => { loading.value = true getFieldTree({ @@ -323,6 +361,18 @@ const getTreeOption = debounce(() => { }) .then(res => { treeOptionList.value = filterTree(dfs(res), config.value.optionFilter) + if (config.value?.required && config.value?.optionFilter?.length > 0) { + const isValid = containsNodeById(treeOptionList.value, config.value.selectValue) + if (!isValid) { + config.value.selectValue = null + ElMessage({ + message: `【${config.value?.name}】${t('v_query.before_querying')}`, + type: 'error', + duration: 3000 + }) + } + } + if (fromSelect) { fromTreeSelectConfirm.value = true if (multiple.value && Array.isArray(treeValue.value) && treeValue.value.length) { diff --git a/core/core-frontend/src/store/modules/data-visualization/dvMain.ts b/core/core-frontend/src/store/modules/data-visualization/dvMain.ts index ad91e8b1a1..deeb84115a 100644 --- a/core/core-frontend/src/store/modules/data-visualization/dvMain.ts +++ b/core/core-frontend/src/store/modules/data-visualization/dvMain.ts @@ -1289,6 +1289,7 @@ 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 => { @@ -1297,7 +1298,7 @@ export const dvMainStore = defineStore('dataVisualization', { } return option }) - const queryParams = paramValue + queryParams = paramValue // do filter filterItem['optionFilter'] = queryParams if (filterItem.defaultValueCheck) { @@ -1308,7 +1309,7 @@ export const dvMainStore = defineStore('dataVisualization', { if (result) { filterItem['selectValue'] = result filterItem['defaultValue'] = result - } else if (!filterItem.defaultValueFirstItem) { + } else if (!filterItem.defaultValueFirstItem && !filterItem.required) { filterItem.defaultValueCheck = false } }