forked from github/dataease
feat(查询组件): 支持文本搜索 #7715
This commit is contained in:
parent
464b2523f0
commit
b8c59be4ff
@ -171,6 +171,7 @@ const handleCheckAllChange = (val: boolean) => {
|
||||
isIndeterminate.value = false
|
||||
}
|
||||
const handleCheckedFieldsChange = (value: string[]) => {
|
||||
if (curComponent.value.displayType === '8') return
|
||||
handleDialogClick()
|
||||
const checkedCount = value.length
|
||||
checkAll.value = checkedCount === fields.value.length
|
||||
@ -369,6 +370,31 @@ const isInRange = (ele, startWindowTime, timeStamp) => {
|
||||
}
|
||||
}
|
||||
|
||||
const validateConditionType = ({
|
||||
defaultConditionValueF,
|
||||
defaultConditionValueS,
|
||||
conditionType
|
||||
}) => {
|
||||
if (conditionType === 0) {
|
||||
return defaultConditionValueF === ''
|
||||
} else {
|
||||
return defaultConditionValueF === '' || defaultConditionValueS === ''
|
||||
}
|
||||
}
|
||||
|
||||
const setParams = ele => {
|
||||
const {
|
||||
defaultConditionValueOperatorF,
|
||||
defaultConditionValueF,
|
||||
defaultConditionValueOperatorS,
|
||||
defaultConditionValueS
|
||||
} = ele
|
||||
ele.conditionValueOperatorF = defaultConditionValueOperatorF
|
||||
ele.conditionValueF = defaultConditionValueF
|
||||
ele.conditionValueOperatorS = defaultConditionValueOperatorS
|
||||
ele.conditionValueS = defaultConditionValueS
|
||||
}
|
||||
|
||||
const validate = () => {
|
||||
return conditions.value.some(ele => {
|
||||
if (ele.auto) return false
|
||||
@ -378,6 +404,15 @@ const validate = () => {
|
||||
}
|
||||
|
||||
if (ele.required) {
|
||||
if (ele.displayType === '8') {
|
||||
setParams(ele)
|
||||
const result = validateConditionType(ele)
|
||||
if (result) {
|
||||
ElMessage.error('查询条件为必填项,默认值不能为空')
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
if (!ele.defaultValueCheck) {
|
||||
ElMessage.error('查询条件为必填项,默认值不能为空')
|
||||
return true
|
||||
@ -392,6 +427,11 @@ const validate = () => {
|
||||
}
|
||||
}
|
||||
|
||||
if (ele.displayType === '8') {
|
||||
setParams(ele)
|
||||
return false
|
||||
}
|
||||
|
||||
if (+ele.displayType === 7) {
|
||||
if (!ele.defaultValueCheck) return false
|
||||
if (ele.timeType === 'fixed') {
|
||||
@ -633,6 +673,15 @@ const parameterCompletion = () => {
|
||||
timeType: 'fixed',
|
||||
required: false,
|
||||
parametersStart: null,
|
||||
conditionType: 0,
|
||||
conditionValueOperatorF: 'eq',
|
||||
conditionValueF: '',
|
||||
conditionValueOperatorS: 'like',
|
||||
conditionValueS: '',
|
||||
defaultConditionValueOperatorF: 'eq',
|
||||
defaultConditionValueF: '',
|
||||
defaultConditionValueOperatorS: 'like',
|
||||
defaultConditionValueS: '',
|
||||
parametersEnd: null,
|
||||
relativeToCurrent: 'custom',
|
||||
timeNum: 0,
|
||||
@ -645,6 +694,7 @@ const parameterCompletion = () => {
|
||||
arbitraryTimeRange: new Date(),
|
||||
setTimeRange: false,
|
||||
showEmpty: false,
|
||||
conditionType: 0,
|
||||
timeRange: {
|
||||
intervalType: 'none',
|
||||
dynamicWindow: false,
|
||||
@ -715,7 +765,7 @@ const showError = computed(() => {
|
||||
if (!checkedFields.length || !arr.length) {
|
||||
return true
|
||||
}
|
||||
if ([1, 7].includes(+displayType)) {
|
||||
if ([1, 7, 8].includes(+displayType)) {
|
||||
return false
|
||||
}
|
||||
return (optionValueSource === 1 && !field.id) || (optionValueSource === 2 && !valueSource.length)
|
||||
@ -723,6 +773,17 @@ const showError = computed(() => {
|
||||
const handleDialogClick = () => {
|
||||
visiblePopover.value = false
|
||||
}
|
||||
|
||||
const operators = [
|
||||
{
|
||||
label: '精准匹配',
|
||||
value: 'eq'
|
||||
},
|
||||
{
|
||||
label: '模糊匹配',
|
||||
value: 'like'
|
||||
}
|
||||
]
|
||||
const relativeToCurrentList = computed(() => {
|
||||
let list = []
|
||||
if (!curComponent.value) return list
|
||||
@ -1154,10 +1215,15 @@ defineExpose({
|
||||
v-model="curComponent.displayType"
|
||||
>
|
||||
<el-option
|
||||
:disabled="curComponent.displayType !== '0'"
|
||||
:disabled="!['0', '8'].includes(curComponent.displayType)"
|
||||
label="文本下拉"
|
||||
value="0"
|
||||
/>
|
||||
<el-option
|
||||
:disabled="!['0', '8'].includes(curComponent.displayType)"
|
||||
label="文本搜索"
|
||||
value="8"
|
||||
/>
|
||||
<el-option
|
||||
v-if="curComponent.displayType === '2'"
|
||||
:disabled="curComponent.displayType !== '2'"
|
||||
@ -1213,7 +1279,10 @@ defineExpose({
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-item top-item" v-if="!['1', '7'].includes(curComponent.displayType)">
|
||||
<div
|
||||
class="list-item top-item"
|
||||
v-if="!['1', '7', '8'].includes(curComponent.displayType)"
|
||||
>
|
||||
<div class="label">选项值来源</div>
|
||||
<div class="value">
|
||||
<div class="value">
|
||||
@ -1362,7 +1431,69 @@ defineExpose({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!['1', '7'].includes(curComponent.displayType)" class="list-item">
|
||||
<div class="list-item top-item" v-if="curComponent.displayType === '8'">
|
||||
<div class="label">条件类型</div>
|
||||
<div class="value">
|
||||
<div class="value">
|
||||
<el-radio-group class="larger-radio" v-model="curComponent.conditionType">
|
||||
<el-radio :label="0">单条件</el-radio>
|
||||
<el-radio :label="1">与条件</el-radio>
|
||||
<el-radio :label="2">或条件</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-item top-item" v-if="curComponent.displayType === '8'">
|
||||
<div class="label">设置默认值</div>
|
||||
<div class="value">
|
||||
<div class="condition-type">
|
||||
<el-select
|
||||
class="condition-value-select"
|
||||
popper-class="condition-value-select-popper"
|
||||
v-model="curComponent.defaultConditionValueOperatorF"
|
||||
>
|
||||
<el-option
|
||||
v-for="ele in operators"
|
||||
:key="ele.value"
|
||||
:label="ele.label"
|
||||
:value="ele.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-input
|
||||
class="condition-value-input"
|
||||
size="small"
|
||||
v-model="curComponent.defaultConditionValueF"
|
||||
/>
|
||||
<div class="bottom-line"></div>
|
||||
</div>
|
||||
<div class="condition-type" v-if="[1, 2].includes(curComponent.conditionType)">
|
||||
<sapn class="condition-type-tip">{{
|
||||
curComponent.conditionType === 1 ? '与' : '或'
|
||||
}}</sapn>
|
||||
<el-select
|
||||
class="condition-value-select"
|
||||
popper-class="condition-value-select-popper"
|
||||
v-model="curComponent.defaultConditionValueOperatorS"
|
||||
>
|
||||
<el-option
|
||||
v-for="ele in operators"
|
||||
:key="ele.value"
|
||||
:label="ele.label"
|
||||
:value="ele.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-input
|
||||
class="condition-value-input"
|
||||
size="small"
|
||||
v-model="curComponent.defaultConditionValueS"
|
||||
/>
|
||||
<div class="bottom-line next-line"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!['1', '7', '8'].includes(curComponent.displayType)" class="list-item">
|
||||
<div class="label">选项类型</div>
|
||||
<div class="value">
|
||||
<el-radio-group
|
||||
@ -1432,7 +1563,7 @@ defineExpose({
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-item">
|
||||
<div v-if="!['8'].includes(curComponent.displayType)" class="list-item">
|
||||
<div class="label">
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
@ -1518,7 +1649,7 @@ defineExpose({
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="list-item">
|
||||
<div v-if="!['8'].includes(curComponent.displayType)" class="list-item">
|
||||
<div class="label">
|
||||
<el-checkbox v-model="curComponent.defaultValueCheck" label="设置默认值" />
|
||||
</div>
|
||||
@ -1694,6 +1825,11 @@ defineExpose({
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
.condition-value-select-popper {
|
||||
.ed-select-dropdown__item.selected::after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.dataset-parameters {
|
||||
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
|
||||
font-style: normal;
|
||||
@ -1966,6 +2102,75 @@ defineExpose({
|
||||
}
|
||||
}
|
||||
|
||||
.value {
|
||||
width: 321px;
|
||||
.condition-type {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
.ed-input__wrapper {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
height: 26px;
|
||||
font-family: '阿里巴巴普惠体 3.0 55 Regular L3', Hiragino Sans GB, Microsoft YaHei,
|
||||
sans-serif;
|
||||
word-wrap: break-word;
|
||||
text-align: left;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
list-style: none;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
line-height: 26px;
|
||||
box-sizing: border-box;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.ed-select .ed-input.is-focus .ed-input__wrapper,
|
||||
.ed-select:hover:not(.ed-select--disabled) .ed-input__wrapper,
|
||||
.ed-select .ed-input__wrapper.is-focus {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.ed-select {
|
||||
width: 120px;
|
||||
.ed-input__wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.condition-type-tip {
|
||||
font-size: 12px;
|
||||
color: #646a73;
|
||||
line-height: 26px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.bottom-line {
|
||||
box-sizing: border-box;
|
||||
height: 1px;
|
||||
background-color: #000;
|
||||
opacity: 0.3;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
width: 220px;
|
||||
z-index: 10;
|
||||
|
||||
&.next-line {
|
||||
width: 206px;
|
||||
}
|
||||
}
|
||||
&:first-child {
|
||||
margin-top: -0.5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.parameters {
|
||||
margin-left: auto;
|
||||
margin-top: 8px;
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { provide, PropType } from 'vue'
|
||||
import Select from './Select.vue'
|
||||
import Time from './Time.vue'
|
||||
import TextSearch from './TextSearch.vue'
|
||||
|
||||
interface SelectConfig {
|
||||
selectValue: any
|
||||
@ -51,6 +52,9 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
const filterTypeCom = (displayType: string) => {
|
||||
if (displayType === '8') {
|
||||
return TextSearch
|
||||
}
|
||||
return ['1', '7'].includes(displayType) ? Time : Select
|
||||
}
|
||||
provide('$custom-style-filter', props.customStyle)
|
||||
|
163
core/core-frontend/src/custom-component/v-query/TextSearch.vue
Normal file
163
core/core-frontend/src/custom-component/v-query/TextSearch.vue
Normal file
@ -0,0 +1,163 @@
|
||||
<script lang="ts" setup>
|
||||
import { toRefs, onBeforeMount, type PropType } from 'vue'
|
||||
interface SelectConfig {
|
||||
conditionValueOperatorF: string
|
||||
conditionValueF: string
|
||||
conditionValueOperatorS: string
|
||||
conditionValueS: string
|
||||
defaultConditionValueOperatorF: string
|
||||
defaultConditionValueF: string
|
||||
defaultConditionValueOperatorS: string
|
||||
defaultConditionValueS: string
|
||||
conditionType: number
|
||||
}
|
||||
|
||||
const operators = [
|
||||
{
|
||||
label: '精准匹配',
|
||||
value: 'eq'
|
||||
},
|
||||
{
|
||||
label: '模糊匹配',
|
||||
value: 'like'
|
||||
}
|
||||
]
|
||||
|
||||
const props = defineProps({
|
||||
config: {
|
||||
type: Object as PropType<SelectConfig>,
|
||||
default: () => {
|
||||
return {
|
||||
conditionType: 0,
|
||||
conditionValueOperatorF: 'eq',
|
||||
conditionValueF: '',
|
||||
conditionValueOperatorS: 'like',
|
||||
conditionValueS: '',
|
||||
defaultConditionValueOperatorF: 'eq',
|
||||
defaultConditionValueF: '',
|
||||
defaultConditionValueOperatorS: 'like',
|
||||
defaultConditionValueS: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
const { config } = toRefs(props)
|
||||
const setParams = () => {
|
||||
const {
|
||||
defaultConditionValueOperatorF,
|
||||
defaultConditionValueF,
|
||||
defaultConditionValueOperatorS,
|
||||
defaultConditionValueS
|
||||
} = config.value
|
||||
config.value.conditionValueOperatorF = defaultConditionValueOperatorF
|
||||
config.value.conditionValueF = defaultConditionValueF
|
||||
config.value.conditionValueOperatorS = defaultConditionValueOperatorS
|
||||
config.value.conditionValueS = defaultConditionValueS
|
||||
}
|
||||
onBeforeMount(() => {
|
||||
setParams()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="text-search-select">
|
||||
<div class="condition-type">
|
||||
<el-select
|
||||
class="condition-value-select"
|
||||
popper-class="condition-value-select-popper"
|
||||
v-model="config.conditionValueOperatorF"
|
||||
>
|
||||
<el-option v-for="ele in operators" :key="ele.value" :label="ele.label" :value="ele.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-input class="condition-value-input" v-model="config.conditionValueF" />
|
||||
<div class="bottom-line"></div>
|
||||
</div>
|
||||
<div class="condition-type" v-if="[1, 2].includes(config.conditionType)">
|
||||
<sapn class="condition-type-tip">{{ config.conditionType === 1 ? '与' : '或' }}</sapn>
|
||||
<el-select
|
||||
class="condition-value-select"
|
||||
popper-class="condition-value-select-popper"
|
||||
v-model="config.conditionValueOperatorS"
|
||||
>
|
||||
<el-option v-for="ele in operators" :key="ele.value" :label="ele.label" :value="ele.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-input class="condition-value-input" v-model="config.conditionValueS" />
|
||||
<div class="bottom-line next-line"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.text-search-select {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.condition-type {
|
||||
display: flex;
|
||||
position: relative;
|
||||
:deep(.ed-input__wrapper) {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
box-shadow: none !important;
|
||||
height: 32px;
|
||||
word-wrap: break-word;
|
||||
text-align: left;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
list-style: none;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
line-height: 32px;
|
||||
box-sizing: border-box;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
:deep(.ed-select .ed-input.is-focus .ed-input__wrapper),
|
||||
:deep(.ed-select:hover:not(.ed-select--disabled) .ed-input__wrapper),
|
||||
:deep(.ed-select .ed-input__wrapper.is-focus) {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
:deep(.ed-select) {
|
||||
width: 120px;
|
||||
.ed-input__wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.condition-type-tip {
|
||||
font-size: 12px;
|
||||
color: #646a73;
|
||||
line-height: 32px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.bottom-line {
|
||||
box-sizing: border-box;
|
||||
height: 1px;
|
||||
background-color: #000;
|
||||
opacity: 0.3;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
width: 195px;
|
||||
z-index: 10;
|
||||
|
||||
&.next-line {
|
||||
width: 195px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="less">
|
||||
.condition-value-select-popper {
|
||||
.ed-select-dropdown__item.selected::after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -106,6 +106,56 @@ export const useFilter = (curComponentId: string, firstLoad = false) => {
|
||||
}
|
||||
}
|
||||
|
||||
const getResult = (
|
||||
conditionType,
|
||||
defaultConditionValueF,
|
||||
defaultConditionValueS,
|
||||
conditionValueF,
|
||||
conditionValueS,
|
||||
firstLoad
|
||||
) => {
|
||||
const valueF = firstLoad ? defaultConditionValueF : conditionValueF
|
||||
const valueS = firstLoad ? defaultConditionValueS : conditionValueS
|
||||
if (conditionType === 0) {
|
||||
return valueF === '' ? [] : valueF
|
||||
}
|
||||
return [valueF || '', valueS || ''].filter(ele => ele !== '')
|
||||
}
|
||||
|
||||
const getOperator = (
|
||||
displayType,
|
||||
multiple,
|
||||
conditionType,
|
||||
defaultConditionValueOperatorF,
|
||||
defaultConditionValueF,
|
||||
defaultConditionValueOperatorS,
|
||||
defaultConditionValueS,
|
||||
conditionValueOperatorF,
|
||||
conditionValueF,
|
||||
conditionValueOperatorS,
|
||||
conditionValueS,
|
||||
firstLoad
|
||||
) => {
|
||||
const valueF = firstLoad ? defaultConditionValueF : conditionValueF
|
||||
const valueS = firstLoad ? defaultConditionValueS : conditionValueS
|
||||
const operatorF = firstLoad ? defaultConditionValueOperatorF : conditionValueOperatorF
|
||||
const operatorS = firstLoad ? defaultConditionValueOperatorS : conditionValueOperatorS
|
||||
if (displayType === '8') {
|
||||
if (conditionType === 0) {
|
||||
return defaultConditionValueOperatorF
|
||||
}
|
||||
const operatorArr = [valueF === '' ? '' : operatorF, valueS === '' ? '' : operatorS].filter(
|
||||
ele => ele !== ''
|
||||
)
|
||||
if (operatorArr.length === 2) {
|
||||
return operatorArr.join(`-${conditionType === 1 ? 'and' : 'or'}-`)
|
||||
}
|
||||
return valueF === '' ? operatorS : operatorF
|
||||
}
|
||||
|
||||
return [1, 7].includes(+displayType) ? 'between' : multiple ? 'in' : 'eq'
|
||||
}
|
||||
|
||||
export const searchQuery = (queryComponentList, filter, curComponentId, firstLoad) => {
|
||||
queryComponentList.forEach(ele => {
|
||||
if (!!ele.propValue?.length) {
|
||||
@ -122,6 +172,15 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
|
||||
timeGranularityMultiple,
|
||||
parametersStart,
|
||||
parametersEnd,
|
||||
conditionType = 0,
|
||||
defaultConditionValueOperatorF = 'eq',
|
||||
defaultConditionValueF = '',
|
||||
defaultConditionValueOperatorS = 'like',
|
||||
defaultConditionValueS = '',
|
||||
conditionValueOperatorF = 'eq',
|
||||
conditionValueF = '',
|
||||
conditionValueOperatorS = 'like',
|
||||
conditionValueS = '',
|
||||
defaultValueCheck,
|
||||
timeType = 'fixed',
|
||||
defaultValue,
|
||||
@ -173,6 +232,15 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
|
||||
item.defaultValue = [startTime, endTime]
|
||||
item.selectValue = [startTime, endTime]
|
||||
}
|
||||
} else if (displayType === '8') {
|
||||
selectValue = getResult(
|
||||
conditionType,
|
||||
defaultConditionValueF,
|
||||
defaultConditionValueS,
|
||||
conditionValueF,
|
||||
conditionValueS,
|
||||
firstLoad
|
||||
)
|
||||
} else {
|
||||
selectValue = getValueByDefaultValueCheckOrFirstLoad(
|
||||
defaultValueCheck,
|
||||
@ -184,19 +252,34 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
|
||||
}
|
||||
if (
|
||||
!!selectValue?.length ||
|
||||
displayType === '8' ||
|
||||
Object.prototype.toString.call(selectValue) === '[object Date]'
|
||||
) {
|
||||
const values = forMatterValue(
|
||||
const result = forMatterValue(
|
||||
+displayType,
|
||||
selectValue,
|
||||
timeGranularity,
|
||||
timeGranularityMultiple
|
||||
)
|
||||
const operator = getOperator(
|
||||
displayType,
|
||||
multiple,
|
||||
conditionType,
|
||||
defaultConditionValueOperatorF,
|
||||
defaultConditionValueF,
|
||||
defaultConditionValueOperatorS,
|
||||
defaultConditionValueS,
|
||||
conditionValueOperatorF,
|
||||
conditionValueF,
|
||||
conditionValueOperatorS,
|
||||
conditionValueS,
|
||||
firstLoad
|
||||
)
|
||||
filter.push({
|
||||
componentId: ele.id,
|
||||
fieldId: item.checkedFieldsMap[curComponentId],
|
||||
operator: [1, 7].includes(+displayType) ? 'between' : multiple ? 'in' : 'eq',
|
||||
value: values,
|
||||
operator,
|
||||
value: result,
|
||||
parameters: parametersCheck
|
||||
? +displayType === 7
|
||||
? [
|
||||
|
Loading…
Reference in New Issue
Block a user