feat(查询组件): 支持文本搜索 #7715

This commit is contained in:
dataeaseShu 2024-04-10 16:21:32 +08:00
parent 464b2523f0
commit b8c59be4ff
4 changed files with 464 additions and 9 deletions

View File

@ -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;

View File

@ -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)

View 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>

View File

@ -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
? [