forked from github/dataease
Merge pull request #335 from dataease/pr@dev@feat_过滤组件下拉列表
feat: 增加过滤组件下拉列表
This commit is contained in:
commit
43f038ab65
@ -1448,7 +1448,7 @@ export default {
|
||||
},
|
||||
// 记录当前样式
|
||||
recordCurStyle() {
|
||||
debugger
|
||||
// debugger
|
||||
const style = {
|
||||
...this.defaultStyle
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
<div ref="deContentContainer" class="condition-content" :class="element.options.attrs.title ? '' : 'condition-content-default'">
|
||||
<div class="condition-content-container">
|
||||
<div class="first-element">
|
||||
<div class="first-element-contaner">
|
||||
<div :class="element.component === 'de-select-grid' ? 'first-element-grid-contaner': ''" class="first-element-contaner">
|
||||
<component
|
||||
:is="element.component"
|
||||
v-if="element.type==='custom'"
|
||||
@ -151,6 +151,8 @@ export default {
|
||||
}
|
||||
.first-element-contaner {
|
||||
width: calc(100% - 10px);
|
||||
background: #fff;
|
||||
border: 1px solid #d7dae2;
|
||||
position:absolute;
|
||||
bottom: 5px;
|
||||
margin: 0 4px;
|
||||
@ -158,6 +160,9 @@ export default {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.first-element-grid-contaner {
|
||||
top: 5px;
|
||||
}
|
||||
.condition-main-line {
|
||||
height: 40px !important;
|
||||
}
|
||||
|
199
frontend/src/components/widget/DeWidget/DeSelectGrid.vue
Normal file
199
frontend/src/components/widget/DeWidget/DeSelectGrid.vue
Normal file
@ -0,0 +1,199 @@
|
||||
<template>
|
||||
|
||||
<div v-if="options!== null && options.attrs!==null" class="de-select-grid-class">
|
||||
<div class="de-select-grid-search">
|
||||
<el-input v-model="keyWord" :placeholder="$t('deinputsearch.placeholder')" size="mini" prefix-icon="el-icon-search" clearable />
|
||||
</div>
|
||||
<div>
|
||||
<el-tree
|
||||
v-if="options!== null && options.attrs!==null"
|
||||
ref="deSelectGrid"
|
||||
:data="options.attrs.datas"
|
||||
:props="defaultProp"
|
||||
:indent="0"
|
||||
:filter-node-method="filterNode"
|
||||
class="de-filter-tree"
|
||||
default-expand-all
|
||||
>
|
||||
<span slot-scope="{ node, data }" class="custom-tree-node-list father">
|
||||
<span style="display: flex;flex: 1;width: 0;">
|
||||
<el-radio v-if="!options.attrs.multiple" v-model="options.value" :label="data.id" @change="changeRadioBox"><span> {{ node.label }} </span></el-radio>
|
||||
<el-checkbox v-if="options.attrs.multiple" v-model="data.checked" :label="data.id" @change="changeCheckBox(data)"><span> {{ node.label }} </span></el-checkbox>
|
||||
</span>
|
||||
<span v-if="!options.attrs.multiple && options.value && options.value === data.id" class="child">
|
||||
<span style="margin-left: 12px;" @click.stop>
|
||||
<span class="el-dropdown-link">
|
||||
<el-button
|
||||
icon="el-icon-circle-close"
|
||||
type="text"
|
||||
size="small"
|
||||
@click="cancelRadio(data)"
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</el-tree>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
|
||||
props: {
|
||||
element: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
inDraw: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
inScreen: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: null,
|
||||
// value: null,
|
||||
checked: null,
|
||||
defaultProp: {
|
||||
id: 'id',
|
||||
label: 'text',
|
||||
children: 'children'
|
||||
},
|
||||
keyWord: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
operator() {
|
||||
return this.options.attrs.multiple ? 'in' : 'eq'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'options.attrs.multiple': function(value) {
|
||||
const datas = JSON.parse(JSON.stringify(this.options.attrs.datas))
|
||||
this.options.attrs.datas = []
|
||||
this.options.attrs.datas = datas
|
||||
const sourceValue = this.options.value
|
||||
const sourceValid = !!sourceValue && Object.keys(sourceValue).length > 0
|
||||
if (value) {
|
||||
!sourceValid && (this.options.value = [])
|
||||
sourceValid && !Array.isArray(sourceValue) && (this.options.value = sourceValue.split(','))
|
||||
!this.inDraw && (this.options.value = [])
|
||||
this.setMutiBox()
|
||||
} else {
|
||||
!sourceValid && (this.options.value = null)
|
||||
sourceValid && Array.isArray(sourceValue) && (this.options.value = sourceValue[0])
|
||||
!this.inDraw && (this.options.value = null)
|
||||
}
|
||||
},
|
||||
keyWord(val) {
|
||||
this.$refs.deSelectGrid.filter(val)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.options = this.element.options
|
||||
this.setMutiBox()
|
||||
this.setRadioBox()
|
||||
// this.setCondition()
|
||||
},
|
||||
mounted() {
|
||||
// this.$nextTick(() => {
|
||||
// this.options && this.options.value && this.changeValue(this.options.value)
|
||||
// })
|
||||
this.options && this.options.value && Object.keys(this.options.value).length > 0 && this.initValue(this.options.value)
|
||||
},
|
||||
methods: {
|
||||
initValue(value) {
|
||||
// this.options.value = [value]
|
||||
this.setCondition()
|
||||
},
|
||||
setMutiBox() {
|
||||
if (this.options && this.options.attrs.multiple) {
|
||||
this.options.attrs.datas.forEach(data => {
|
||||
data.checked = (this.options.value && this.options.value.includes(data.id))
|
||||
})
|
||||
}
|
||||
},
|
||||
setRadioBox() {
|
||||
if (this.options && !this.options.attrs.multiple) {
|
||||
if (Array.isArray(this.options.value) && this.options.value.length > 0) {
|
||||
// this.value = this.options.value.length[0]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
setCondition() {
|
||||
const param = {
|
||||
component: this.element,
|
||||
value: Array.isArray(this.options.value) ? this.options.value : [this.options.value],
|
||||
operator: this.operator
|
||||
}
|
||||
this.inDraw && this.$store.commit('addViewFilter', param)
|
||||
},
|
||||
changeCheckBox(data) {
|
||||
const values = Array.isArray(this.options.value) ? this.options.value : this.options.value ? [this.options.value] : []
|
||||
const index = values.indexOf(data.id)
|
||||
if (index < 0 && data.checked) {
|
||||
values.push(data.id)
|
||||
}
|
||||
if (index >= 0 && !data.checked) {
|
||||
values.splice(index, 1)
|
||||
}
|
||||
|
||||
this.options.value = values
|
||||
this.setCondition()
|
||||
},
|
||||
changeRadioBox(value) {
|
||||
// this.options.value = []
|
||||
// if (this.value) this.options.value = [this.value]
|
||||
this.setCondition()
|
||||
},
|
||||
cancelRadio(data) {
|
||||
this.options.value = null
|
||||
this.changeRadioBox()
|
||||
},
|
||||
filterNode(value, data) {
|
||||
if (!value) return true
|
||||
return data[this.defaultProp.label].indexOf(value) !== -1
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.custom-tree-node-list {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
padding:0 8px;
|
||||
}
|
||||
.father .child {
|
||||
display: none;
|
||||
}
|
||||
.father:hover .child {
|
||||
display: inline;
|
||||
}
|
||||
.de-filter-tree {
|
||||
>>>span.is-leaf {
|
||||
width: 5px !important;
|
||||
padding: 6px 0 !important;
|
||||
}
|
||||
}
|
||||
.de-select-grid-search {
|
||||
>>>input {
|
||||
border-radius: 0px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -3,7 +3,7 @@ import { WidgetService } from '../service/WidgetService'
|
||||
const leftPanel = {
|
||||
icon: 'iconfont icon-zuoce-qujian',
|
||||
label: 'denumberrange.label',
|
||||
defaultClass: 'text-filter'
|
||||
defaultClass: 'tree-filter'
|
||||
}
|
||||
|
||||
const dialogPanel = {
|
||||
@ -15,7 +15,7 @@ const dialogPanel = {
|
||||
},
|
||||
value: ''
|
||||
},
|
||||
defaultClass: 'text-filter',
|
||||
defaultClass: 'tree-filter',
|
||||
component: 'de-number-range'
|
||||
}
|
||||
const drawPanel = {
|
||||
|
@ -0,0 +1,81 @@
|
||||
|
||||
import { WidgetService } from '../service/WidgetService'
|
||||
|
||||
const leftPanel = {
|
||||
icon: 'iconfont icon-xialakuang',
|
||||
label: 'denumbergridselect.label',
|
||||
defaultClass: 'tree-filter'
|
||||
}
|
||||
|
||||
const dialogPanel = {
|
||||
options: {
|
||||
attrs: {
|
||||
multiple: false,
|
||||
placeholder: 'denumbergridselect.placeholder',
|
||||
viewIds: [],
|
||||
datas: [],
|
||||
key: 'id',
|
||||
label: 'text',
|
||||
value: 'id'
|
||||
},
|
||||
value: ''
|
||||
},
|
||||
defaultClass: 'tree-filter',
|
||||
component: 'de-select-grid'
|
||||
}
|
||||
const drawPanel = {
|
||||
type: 'custom',
|
||||
style: {
|
||||
width: 300,
|
||||
height: 300,
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
lineHeight: '',
|
||||
letterSpacing: 0,
|
||||
textAlign: '',
|
||||
color: ''
|
||||
},
|
||||
component: 'de-select-grid'
|
||||
}
|
||||
|
||||
class NumberSelectGridServiceImpl extends WidgetService {
|
||||
constructor(options = {}) {
|
||||
Object.assign(options, { name: 'numberSelectGridWidget' })
|
||||
super(options)
|
||||
this.filterDialog = true
|
||||
this.showSwitch = true
|
||||
}
|
||||
|
||||
initLeftPanel() {
|
||||
const value = JSON.parse(JSON.stringify(leftPanel))
|
||||
return value
|
||||
}
|
||||
|
||||
initFilterDialog() {
|
||||
const value = JSON.parse(JSON.stringify(dialogPanel))
|
||||
return value
|
||||
}
|
||||
|
||||
initDrawPanel() {
|
||||
const value = JSON.parse(JSON.stringify(drawPanel))
|
||||
return value
|
||||
}
|
||||
|
||||
filterFieldMethod(fields) {
|
||||
return fields.filter(field => {
|
||||
return field['deType'] === 2
|
||||
})
|
||||
}
|
||||
|
||||
optionDatas(datas) {
|
||||
if (!datas) return null
|
||||
return datas.filter(item => !!item).map(item => {
|
||||
return {
|
||||
id: item,
|
||||
text: item
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
const numberSelectGridServiceImpl = new NumberSelectGridServiceImpl()
|
||||
export default numberSelectGridServiceImpl
|
@ -4,7 +4,7 @@ import { WidgetService } from '../service/WidgetService'
|
||||
const leftPanel = {
|
||||
icon: 'iconfont icon-xialakuang',
|
||||
label: 'denumberselect.label',
|
||||
defaultClass: 'text-filter'
|
||||
defaultClass: 'tree-filter'
|
||||
}
|
||||
|
||||
const dialogPanel = {
|
||||
@ -19,7 +19,7 @@ const dialogPanel = {
|
||||
},
|
||||
value: ''
|
||||
},
|
||||
defaultClass: 'text-filter',
|
||||
defaultClass: 'tree-filter',
|
||||
component: 'de-select'
|
||||
}
|
||||
const drawPanel = {
|
||||
|
@ -0,0 +1,81 @@
|
||||
|
||||
import { WidgetService } from '../service/WidgetService'
|
||||
|
||||
const leftPanel = {
|
||||
icon: 'iconfont icon-xialakuang',
|
||||
label: 'detextgridselect.label',
|
||||
defaultClass: 'text-filter'
|
||||
}
|
||||
|
||||
const dialogPanel = {
|
||||
options: {
|
||||
attrs: {
|
||||
multiple: false,
|
||||
placeholder: 'detextgridselect.placeholder',
|
||||
viewIds: [],
|
||||
datas: [],
|
||||
key: 'id',
|
||||
label: 'text',
|
||||
value: 'id'
|
||||
},
|
||||
value: ''
|
||||
},
|
||||
defaultClass: 'text-filter',
|
||||
component: 'de-select-grid'
|
||||
}
|
||||
const drawPanel = {
|
||||
type: 'custom',
|
||||
style: {
|
||||
width: 300,
|
||||
height: 300,
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
lineHeight: '',
|
||||
letterSpacing: 0,
|
||||
textAlign: '',
|
||||
color: ''
|
||||
},
|
||||
component: 'de-select-grid'
|
||||
}
|
||||
|
||||
class TextSelectGridServiceImpl extends WidgetService {
|
||||
constructor(options = {}) {
|
||||
Object.assign(options, { name: 'textSelectGridWidget' })
|
||||
super(options)
|
||||
this.filterDialog = true
|
||||
this.showSwitch = true
|
||||
}
|
||||
|
||||
initLeftPanel() {
|
||||
const value = JSON.parse(JSON.stringify(leftPanel))
|
||||
return value
|
||||
}
|
||||
|
||||
initFilterDialog() {
|
||||
const value = JSON.parse(JSON.stringify(dialogPanel))
|
||||
return value
|
||||
}
|
||||
|
||||
initDrawPanel() {
|
||||
const value = JSON.parse(JSON.stringify(drawPanel))
|
||||
return value
|
||||
}
|
||||
|
||||
filterFieldMethod(fields) {
|
||||
return fields.filter(field => {
|
||||
return field['deType'] === 0
|
||||
})
|
||||
}
|
||||
|
||||
optionDatas(datas) {
|
||||
if (!datas) return null
|
||||
return datas.filter(item => !!item).map(item => {
|
||||
return {
|
||||
id: item,
|
||||
text: item
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
const textSelectGridServiceImpl = new TextSelectGridServiceImpl()
|
||||
export default textSelectGridServiceImpl
|
@ -1314,6 +1314,14 @@ export default {
|
||||
label: 'Text selector',
|
||||
placeholder: 'Please select'
|
||||
},
|
||||
detextgridselect: {
|
||||
label: 'Text list',
|
||||
placeholder: 'Please select'
|
||||
},
|
||||
denumbergridselect: {
|
||||
label: 'Number list',
|
||||
placeholder: 'Please select'
|
||||
},
|
||||
dedaterange: {
|
||||
label: 'Date range',
|
||||
to_placeholder: 'End date',
|
||||
|
@ -1314,6 +1314,14 @@ export default {
|
||||
label: '文本下拉',
|
||||
placeholder: '請選擇'
|
||||
},
|
||||
detextgridselect: {
|
||||
label: '文本列表',
|
||||
placeholder: '請選擇'
|
||||
},
|
||||
denumbergridselect: {
|
||||
label: '數字列表',
|
||||
placeholder: '請選擇'
|
||||
},
|
||||
dedaterange: {
|
||||
label: '日期範圍',
|
||||
to_placeholder: '結束日期',
|
||||
|
@ -1316,6 +1316,14 @@ export default {
|
||||
label: '文本下拉',
|
||||
placeholder: '请选择'
|
||||
},
|
||||
detextgridselect: {
|
||||
label: '文本列表',
|
||||
placeholder: '请选择'
|
||||
},
|
||||
denumbergridselect: {
|
||||
label: '数字列表',
|
||||
placeholder: '请选择'
|
||||
},
|
||||
dedaterange: {
|
||||
label: '日期范围',
|
||||
to_placeholder: '结束日期',
|
||||
|
@ -51,10 +51,12 @@ export default {
|
||||
],
|
||||
'文本过滤组件': [
|
||||
'textSelectWidget',
|
||||
'textSelectGridWidget',
|
||||
'textInputWidget'
|
||||
],
|
||||
'数字过滤组件': [
|
||||
'numberSelectWidget',
|
||||
'numberSelectGridWidget',
|
||||
'numberRangeWidget'
|
||||
]
|
||||
// '按钮': [
|
||||
@ -202,7 +204,8 @@ export default {
|
||||
.tree-filter:hover {
|
||||
background-color: #37b4aa;
|
||||
.filter-widget-icon {
|
||||
color: #37b4aa;
|
||||
background-color: #37b4aa;
|
||||
color: #fff;
|
||||
}
|
||||
.filter-widget-text {
|
||||
color: #fff;
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<layout-content v-loading="$store.getters.loadingMap[$store.getters.currentPath]">
|
||||
|
||||
<el-row style="height: 100%;overflow-y: hidden;width: 100%;">
|
||||
<el-row style="height: 100%;width: 100%;">
|
||||
<el-tabs v-model="tabActive" @tab-click="changeTab">
|
||||
<el-tab-pane :label="$t('dataset.task.list')" name="DatasetTaskList">
|
||||
<dataset-task-list v-if="tabActive=='DatasetTaskList'" :param="task" @jumpTaskRecord="jumpTaskRecord" />
|
||||
|
Loading…
Reference in New Issue
Block a user