mirror of
https://github.com/dataease/dataease.git
synced 2025-02-24 11:32:57 +08:00
Merge pull request #13381 from dataease/pr@dev-v2_st
feat(查询组件): 下拉查询组件支持自定义排序 #12387
This commit is contained in:
commit
facf7a1477
@ -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>
|
@ -23,6 +23,8 @@ import {
|
|||||||
unref
|
unref
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
|
import { enumValueObj } from '@/api/dataset'
|
||||||
|
import CustomSortFilter from './CustomSortFilter.vue'
|
||||||
import { addQueryCriteriaConfig } from './options'
|
import { addQueryCriteriaConfig } from './options'
|
||||||
import { getCustomTime } from './time-format'
|
import { getCustomTime } from './time-format'
|
||||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
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 treeDialog = ref()
|
||||||
const startTreeDesign = () => {
|
const startTreeDesign = () => {
|
||||||
const [comId] = curComponent.value.checkedFields
|
const [comId] = curComponent.value.checkedFields
|
||||||
@ -2804,6 +2835,7 @@ defineExpose({
|
|||||||
:placeholder="t('v_query.display_field')"
|
:placeholder="t('v_query.display_field')"
|
||||||
class="search-field"
|
class="search-field"
|
||||||
v-model="curComponent.displayId"
|
v-model="curComponent.displayId"
|
||||||
|
@change="resetSort"
|
||||||
>
|
>
|
||||||
<template v-if="curComponent.displayId" #prefix>
|
<template v-if="curComponent.displayId" #prefix>
|
||||||
<el-icon>
|
<el-icon>
|
||||||
@ -2865,7 +2897,7 @@ defineExpose({
|
|||||||
:placeholder="t('v_query.the_sorting_field')"
|
:placeholder="t('v_query.the_sorting_field')"
|
||||||
v-model="curComponent.sortId"
|
v-model="curComponent.sortId"
|
||||||
class="sort-field"
|
class="sort-field"
|
||||||
@change="handleFieldChange"
|
@change="handleSortChange"
|
||||||
>
|
>
|
||||||
<template v-if="curComponent.sortId" #prefix>
|
<template v-if="curComponent.sortId" #prefix>
|
||||||
<el-icon>
|
<el-icon>
|
||||||
@ -2919,6 +2951,13 @@ defineExpose({
|
|||||||
>
|
>
|
||||||
<el-option :label="t('chart.asc')" value="asc" />
|
<el-option :label="t('chart.asc')" value="asc" />
|
||||||
<el-option :label="t('chart.desc')" value="desc" />
|
<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>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -3081,6 +3120,7 @@ defineExpose({
|
|||||||
<el-button type="primary" @click="numTypeChange">{{ t('dataset.confirm') }}</el-button>
|
<el-button type="primary" @click="numTypeChange">{{ t('dataset.confirm') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<customSortFilter ref="customSortFilterRef" @save="sortSave"></customSortFilter>
|
||||||
<CascadeDialog @saveCascade="saveCascade" ref="cascadeDialog"></CascadeDialog>
|
<CascadeDialog @saveCascade="saveCascade" ref="cascadeDialog"></CascadeDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ interface SelectConfig {
|
|||||||
displayType: string
|
displayType: string
|
||||||
showEmpty: boolean
|
showEmpty: boolean
|
||||||
id: string
|
id: string
|
||||||
|
sortList?: string[]
|
||||||
queryConditionWidth: number
|
queryConditionWidth: number
|
||||||
placeholder: string
|
placeholder: string
|
||||||
resultMode: number
|
resultMode: number
|
||||||
@ -287,6 +288,14 @@ const setOldMapValue = arr => {
|
|||||||
return defaultValue
|
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) => {
|
const handleFieldIdChange = (val: EnumValue) => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
enumValueObj(val)
|
enumValueObj(val)
|
||||||
@ -313,6 +322,7 @@ const handleFieldIdChange = (val: EnumValue) => {
|
|||||||
checked: oldArr.includes(ele)
|
checked: oldArr.includes(ele)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
customSort()
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
@ -348,16 +358,6 @@ const handleFieldIdChange = (val: EnumValue) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const visible = ref(false)
|
const visible = ref(false)
|
||||||
const visibleChange = (val: boolean) => {
|
|
||||||
setTimeout(() => {
|
|
||||||
visible.value = !val
|
|
||||||
if (!val) {
|
|
||||||
isFromRemote.value = false
|
|
||||||
searchText.value = ''
|
|
||||||
remoteMethod('')
|
|
||||||
}
|
|
||||||
}, 50)
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => config.value.showEmpty,
|
() => config.value.showEmpty,
|
||||||
@ -449,6 +449,11 @@ watch(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
watch([() => config.value.sortList], val => {
|
||||||
|
if (!val?.length || config.value.sort !== 'customSort') return
|
||||||
|
customSort()
|
||||||
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => config.value.optionValueSource,
|
() => config.value.optionValueSource,
|
||||||
(valNew, newOld) => {
|
(valNew, newOld) => {
|
||||||
@ -474,16 +479,6 @@ watch(
|
|||||||
|
|
||||||
const searchText = ref('')
|
const searchText = ref('')
|
||||||
const isFromRemote = ref(false)
|
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(
|
watch(
|
||||||
() => config.value.valueSource,
|
() => config.value.valueSource,
|
||||||
@ -520,7 +515,7 @@ const setOptions = (num: number) => {
|
|||||||
handleFieldIdChange({
|
handleFieldIdChange({
|
||||||
queryId: field.id,
|
queryId: field.id,
|
||||||
displayId: displayId || field.id,
|
displayId: displayId || field.id,
|
||||||
sort,
|
sort: sort === 'customSort' ? '' : sort,
|
||||||
sortId,
|
sortId,
|
||||||
resultMode: config.value.resultMode || 0,
|
resultMode: config.value.resultMode || 0,
|
||||||
searchText: searchText.value,
|
searchText: searchText.value,
|
||||||
@ -612,7 +607,6 @@ defineExpose({
|
|||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
filterable
|
filterable
|
||||||
@change="handleValueChange"
|
@change="handleValueChange"
|
||||||
@visible-change="visibleChange"
|
|
||||||
:popper-class="
|
:popper-class="
|
||||||
visible ? 'load-select filter-select-popper_class' : 'filter-select-popper_class'
|
visible ? 'load-select filter-select-popper_class' : 'filter-select-popper_class'
|
||||||
"
|
"
|
||||||
@ -635,9 +629,7 @@ defineExpose({
|
|||||||
ref="single"
|
ref="single"
|
||||||
:style="selectStyle"
|
:style="selectStyle"
|
||||||
filterable
|
filterable
|
||||||
@clear="clear"
|
|
||||||
radio
|
radio
|
||||||
@visible-change="visibleChange"
|
|
||||||
:popper-class="
|
:popper-class="
|
||||||
visible ? 'load-select filter-select-popper_class' : 'filter-select-popper_class'
|
visible ? 'load-select filter-select-popper_class' : 'filter-select-popper_class'
|
||||||
"
|
"
|
||||||
|
@ -2564,6 +2564,8 @@ export default {
|
|||||||
variable_mgm: '参数设置'
|
variable_mgm: '参数设置'
|
||||||
},
|
},
|
||||||
v_query: {
|
v_query: {
|
||||||
|
display_sort: '显示字段和排序字段不一致,无法进行自定义排序',
|
||||||
|
custom_sort: '自定义排序',
|
||||||
msg_center: '消息中心',
|
msg_center: '消息中心',
|
||||||
to_be_filled: '待填报',
|
to_be_filled: '待填报',
|
||||||
the_minimum_value: '数值区间最大值必须大于最小值',
|
the_minimum_value: '数值区间最大值必须大于最小值',
|
||||||
|
Loading…
Reference in New Issue
Block a user