Merge pull request #13381 from dataease/pr@dev-v2_st

feat(查询组件): 下拉查询组件支持自定义排序 #12387
This commit is contained in:
xuwei-fit2cloud 2024-11-18 14:17:59 +08:00 committed by GitHub
commit facf7a1477
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 163 additions and 25 deletions

View File

@ -0,0 +1,104 @@
<template>
<el-dialog
destroy-on-close
append-to-body
:title="$t('v_query.custom_sort')"
v-model="dialogShow"
class="custom-sort_filter"
width="300px"
>
<div>
<draggable :list="sortList" animation="300" class="drag-list">
<template #item="{ element }">
<span :key="element.name" class="item-dimension" :title="element">
<el-icon size="20px">
<Icon name="drag"><drag class="svg-icon" /></Icon>
</el-icon>
<span class="item-span">
{{ element }}
</span>
</span>
</template>
</draggable>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeDialog">{{ $t('common.cancel') }}</el-button>
<el-button type="primary" @click="save">{{ $t('chart.confirm') }}</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import drag from '@/assets/svg/drag.svg'
import draggable from 'vuedraggable'
import { ref, unref } from 'vue'
import { cloneDeep } from 'lodash-es'
const sortList = ref([])
const dialogShow = ref(false)
const sortInit = list => {
init(list)
dialogShow.value = true
}
const init = list => {
sortList.value = cloneDeep(list)
}
const emits = defineEmits(['save'])
const closeDialog = () => {
dialogShow.value = false
}
const save = () => {
emits('save', unref(sortList))
closeDialog()
}
defineExpose({
sortInit
})
</script>
<style lang="less">
.custom-sort_filter {
.drag-list {
overflow: auto;
max-height: 800px;
.item-dimension {
padding: 2px;
margin: 2px;
border: solid 1px #eee;
text-align: left;
color: #606266;
background-color: white;
display: flex;
align-items: center;
}
.item-icon {
cursor: move;
margin: 0 2px;
}
.item-span {
display: inline-block;
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.item-dimension + .item-dimension {
margin-top: 6px;
}
.item-dimension:hover {
color: #1890ff;
background: #e8f4ff;
border-color: #a3d3ff;
cursor: pointer;
}
}
}
</style>

View File

@ -23,6 +23,8 @@ import {
unref
} from 'vue'
import { storeToRefs } from 'pinia'
import { enumValueObj } from '@/api/dataset'
import CustomSortFilter from './CustomSortFilter.vue'
import { addQueryCriteriaConfig } from './options'
import { getCustomTime } from './time-format'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
@ -1755,6 +1757,35 @@ const getOptions = (id, component) => {
})
}
const handleSortChange = () => {
handleFieldChange()
curComponent.value.sortList = []
resetSort()
}
const resetSort = () => {
if (sortComputed.value) {
curComponent.value.sort = ''
}
}
const customSortFilterRef = ref()
const sortSave = list => {
curComponent.value.sortList = cloneDeep(list)
}
const handleCustomClick = async () => {
if (sortComputed.value || curComponent.value.sort !== 'customSort') return
const list = await enumValueObj({ queryId: curComponent.value.sortId, searchText: '' })
customSortFilterRef.value.sortInit([...new Set(list.map(ele => ele[curComponent.value.sortId]))])
}
const sortComputed = computed(() => {
const { sortId, displayId } = curComponent.value
return sortId && displayId && sortId !== displayId
})
const treeDialog = ref()
const startTreeDesign = () => {
const [comId] = curComponent.value.checkedFields
@ -2804,6 +2835,7 @@ defineExpose({
:placeholder="t('v_query.display_field')"
class="search-field"
v-model="curComponent.displayId"
@change="resetSort"
>
<template v-if="curComponent.displayId" #prefix>
<el-icon>
@ -2865,7 +2897,7 @@ defineExpose({
:placeholder="t('v_query.the_sorting_field')"
v-model="curComponent.sortId"
class="sort-field"
@change="handleFieldChange"
@change="handleSortChange"
>
<template v-if="curComponent.sortId" #prefix>
<el-icon>
@ -2919,6 +2951,13 @@ defineExpose({
>
<el-option :label="t('chart.asc')" value="asc" />
<el-option :label="t('chart.desc')" value="desc" />
<el-option
@click="handleCustomClick"
:title="sortComputed ? $t('v_query.display_sort') : ''"
:disabled="sortComputed"
:label="t('v_query.custom_sort')"
value="customSort"
/>
</el-select>
</div>
</template>
@ -3081,6 +3120,7 @@ defineExpose({
<el-button type="primary" @click="numTypeChange">{{ t('dataset.confirm') }}</el-button>
</template>
</el-dialog>
<customSortFilter ref="customSortFilterRef" @save="sortSave"></customSortFilter>
<CascadeDialog @saveCascade="saveCascade" ref="cascadeDialog"></CascadeDialog>
</template>

View File

@ -26,6 +26,7 @@ interface SelectConfig {
displayType: string
showEmpty: boolean
id: string
sortList?: string[]
queryConditionWidth: number
placeholder: string
resultMode: number
@ -287,6 +288,14 @@ const setOldMapValue = arr => {
return defaultValue
}
const customSort = () => {
if (config.value.sortList?.length && config.value.sort === 'customSort') {
options.value.sort(
(a, b) => config.value.sortList.indexOf(a.value) - config.value.sortList.indexOf(b.value)
)
}
}
const handleFieldIdChange = (val: EnumValue) => {
loading.value = true
enumValueObj(val)
@ -313,6 +322,7 @@ const handleFieldIdChange = (val: EnumValue) => {
checked: oldArr.includes(ele)
}
})
customSort()
})
.finally(() => {
loading.value = false
@ -348,16 +358,6 @@ const handleFieldIdChange = (val: EnumValue) => {
}
const visible = ref(false)
const visibleChange = (val: boolean) => {
setTimeout(() => {
visible.value = !val
if (!val) {
isFromRemote.value = false
searchText.value = ''
remoteMethod('')
}
}, 50)
}
watch(
() => config.value.showEmpty,
@ -449,6 +449,11 @@ watch(
}
)
watch([() => config.value.sortList], val => {
if (!val?.length || config.value.sort !== 'customSort') return
customSort()
})
watch(
() => config.value.optionValueSource,
(valNew, newOld) => {
@ -474,16 +479,6 @@ watch(
const searchText = ref('')
const isFromRemote = ref(false)
const clear = () => {
remoteMethod('')
}
const remoteMethod = (query: string) => {
if (config.value.optionValueSource !== 1) return
isFromRemote.value = true
searchText.value = query
debounceOptions(1)
}
watch(
() => config.value.valueSource,
@ -520,7 +515,7 @@ const setOptions = (num: number) => {
handleFieldIdChange({
queryId: field.id,
displayId: displayId || field.id,
sort,
sort: sort === 'customSort' ? '' : sort,
sortId,
resultMode: config.value.resultMode || 0,
searchText: searchText.value,
@ -612,7 +607,6 @@ defineExpose({
v-loading="loading"
filterable
@change="handleValueChange"
@visible-change="visibleChange"
:popper-class="
visible ? 'load-select filter-select-popper_class' : 'filter-select-popper_class'
"
@ -635,9 +629,7 @@ defineExpose({
ref="single"
:style="selectStyle"
filterable
@clear="clear"
radio
@visible-change="visibleChange"
:popper-class="
visible ? 'load-select filter-select-popper_class' : 'filter-select-popper_class'
"

View File

@ -2564,6 +2564,8 @@ export default {
variable_mgm: '参数设置'
},
v_query: {
display_sort: '显示字段和排序字段不一致无法进行自定义排序',
custom_sort: '自定义排序',
msg_center: '消息中心',
to_be_filled: '待填报',
the_minimum_value: '数值区间最大值必须大于最小值',