filter-tree.vue 6.5 KB
Newer Older
JunZai's avatar
JunZai committed
1
<template>
JunZai's avatar
JunZai committed
2
    <el-tree class="filter-tree" :data="treeItems" :expand-on-click-node="false" default-expand-all>
JunZai's avatar
JunZai committed
3
        <template slot-scope="{ node, data }">
JunZai's avatar
JunZai committed
4
            <template v-if="Object.is(data.label, '$and') || Object.is(data.label, '$or')">
JunZai's avatar
JunZai committed
5
                <div class="filter-tree-item">
JunZai's avatar
JunZai committed
6
                    <el-select size="small" v-model="data.label" :disabled="data.isroot">
JunZai's avatar
JunZai committed
7
                        <el-option v-for="mode in relationModes" :key="mode.value" :label="getLabel(mode)" :value="mode.value"></el-option>
JunZai's avatar
JunZai committed
8 9
                    </el-select>
                    <div class="filter-tree-action">
10 11
                        <i-button :title="$t('components.filterTree.title1')" @click="onAddItem(data)"><i class="fa fa-plus" aria-hidden="true"></i> {{$t('components.filterTree.title1')}}</i-button>
                        <i-button :title="$t('components.filterTree.title2')" @click="onAddGroup(data)"><i class="fa fa-plus" aria-hidden="true"></i> {{$t('components.filterTree.title2')}}</i-button>
JunZai's avatar
JunZai committed
12
                        <icon v-if="!data.isroot" type="md-close"  @click="onRemoveItem(node, data)"/>
JunZai's avatar
JunZai committed
13 14 15 16 17
                    </div>
                </div>
            </template>
            <template v-else>
                <div class="filter-tree-item">
JunZai's avatar
JunZai committed
18
                    <el-select size="small" class="filter-item-field" v-model="data.field" clearable :placeholder="$t('components.filterTree.placeholder')">
JunZai's avatar
JunZai committed
19
                        <el-option
JunZai's avatar
JunZai committed
20 21
                            v-for="item in fieldItems"
                            :key="item.value"
JunZai's avatar
JunZai committed
22
                            :label="item.label"
JunZai's avatar
JunZai committed
23
                            :value="item.value">
JunZai's avatar
JunZai committed
24 25
                        </el-option>
                    </el-select>
JunZai's avatar
JunZai committed
26
                    <filter-mode class="filter-item-mode" v-model="data.mode" :modes="getModes(data.field)" @on-change="onModeChange($event, data)"></filter-mode>
JunZai's avatar
JunZai committed
27
                    <div class="filter-item-value">
JunZai's avatar
JunZai committed
28
                        <i-input v-if="!data.editor"></i-input>
JunZai's avatar
JunZai committed
29 30 31
                        <div v-else :key="data.editor">
                            <slot :data="data"></slot>
                        </div>
JunZai's avatar
JunZai committed
32 33
                    </div>
                    <div class="filter-tree-action">
JunZai's avatar
JunZai committed
34
                        <icon type="md-close"  @click="onRemoveItem(node, data)"/>
JunZai's avatar
JunZai committed
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
                    </div>
                </div>
            </template>
        </template>
    </el-tree>
</template>

<script lang="ts"> 
import {Vue, Component, Prop} from 'vue-property-decorator';
import FilterMode from './filter-mode.vue';

@Component({
    components: {
        FilterMode
    }
})
export default class FilterTree extends Vue {

JunZai's avatar
JunZai committed
53 54 55 56 57 58
    /**
     * 数据集
     *
     * @type {*}
     * @memberof FilterTree
     */
JunZai's avatar
JunZai committed
59 60
    @Prop() datas: any;

JunZai's avatar
JunZai committed
61 62 63 64 65 66
    /**
     * 过滤项集合
     *
     * @type {*}
     * @memberof FilterTree
     */
JunZai's avatar
JunZai committed
67 68
    @Prop() fields: any;

JunZai's avatar
JunZai committed
69 70 71 72 73 74 75 76
    /**
     * 属性项集合
     *
     * @type {*}
     * @memberof FilterTree
     */
    protected fieldItems: any[] = [];

JunZai's avatar
JunZai committed
77 78 79 80 81 82
    /**
     * 组条件集合
     *
     * @type {*}
     * @memberof FilterTree
     */
JunZai's avatar
JunZai committed
83
    protected relationModes: any[] = [
JunZai's avatar
JunZai committed
84 85
        { 'zh-CN': '并且', 'en-US': 'AND', value: '$and' },
        { 'zh-CN': '或', 'en-US': 'OR', value: '$or' }
JunZai's avatar
JunZai committed
86 87
    ];

JunZai's avatar
JunZai committed
88 89 90 91 92 93
    /**
     * 树数据集合
     *
     * @type {*}
     * @memberof FilterTree
     */
JunZai's avatar
JunZai committed
94 95
    get treeItems() {
        let root: any = {
JunZai's avatar
JunZai committed
96 97 98
            label: '$and',
            isroot: true,
            children: this.datas
JunZai's avatar
JunZai committed
99 100 101 102 103 104 105
        };
        if(this.datas.length == 0) {
            this.onAddItem(root);
        }
        return [root];
    }

JunZai's avatar
JunZai committed
106

JunZai's avatar
JunZai committed
107
    /**
JunZai's avatar
JunZai committed
108
     * 生命周期
JunZai's avatar
JunZai committed
109
     *
JunZai's avatar
JunZai committed
110
     * @return {void}
JunZai's avatar
JunZai committed
111 112
     * @memberof FilterTree
     */
JunZai's avatar
JunZai committed
113 114 115
    public created() {
        if(!this.fields) {
            return;
JunZai's avatar
JunZai committed
116
        }
JunZai's avatar
JunZai committed
117 118 119 120 121 122 123 124 125 126
        this.fields.forEach((field: any) => {
            let index: number = this.fieldItems.findIndex((item: any) => Object.is(item.value, field.prop));
            if(index < 0) {
                this.fieldItems.push({
                    label: field.label,
                    value: field.prop,
                    modes: this.getFieldModes(field.prop)
                })
            } 
        });
JunZai's avatar
JunZai committed
127 128
    }

JunZai's avatar
JunZai committed
129
    /**
JunZai's avatar
JunZai committed
130
     * 获取逻辑模式集合
JunZai's avatar
JunZai committed
131
     *
JunZai's avatar
JunZai committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
     * @return {void}
     * @memberof FilterTree
     */
    public getModes(field: string) {
        if(this.fieldItems.length > 0) {
            let item: any = this.fieldItems.find((item: any) => Object.is(item.value, field));
            if(item) {
                return item.modes;
            }
        }
        return [];
    }

    /**
     * 获取属性逻辑模式集合
     *
     * @return {void}
JunZai's avatar
JunZai committed
149 150
     * @memberof FilterTree
     */
JunZai's avatar
JunZai committed
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
    public getFieldModes(name: string) {
        let modes: any[] = [];
        for(let i = 0; i < this.fields.length; i++) {
            let field: any = this.fields[i];
            if(!Object.is(field.prop, name)) {
                continue;
            }
            modes.push({
                name: field.name,
                mode: field.mode ? field.mode : 'all'
            })
        }
        return modes;
    }

    /**
     * 获取语言文本
     *
     * @return {string}
     * @memberof FilterTree
     */
    getLabel(mode: any): string {
        if(this.$i18n.locale) {
            return mode[this.$i18n.locale];
JunZai's avatar
JunZai committed
175
        }
JunZai's avatar
JunZai committed
176
        return mode['zh-CN'];
JunZai's avatar
JunZai committed
177 178
    }

JunZai's avatar
JunZai committed
179 180 181 182 183 184
    /**
     * 添加条件
     *
     * @return {*}
     * @memberof FilterTree
     */
JunZai's avatar
JunZai committed
185
    public onAddItem(data: any) {
JunZai's avatar
JunZai committed
186 187
        if(data && data.children) {
            data.children.push({
JunZai's avatar
JunZai committed
188
                field: null,
JunZai's avatar
JunZai committed
189 190
                mode: null,
                editor: null
JunZai's avatar
JunZai committed
191 192 193 194
            });
        }
    }

JunZai's avatar
JunZai committed
195 196 197 198 199 200
    /**
     * 添加组
     *
     * @return {*}
     * @memberof FilterTree
     */
JunZai's avatar
JunZai committed
201
    public onAddGroup(data: any) {
JunZai's avatar
JunZai committed
202 203 204 205
        if(data && data.children) {
            data.children.push({
                label: '$and',
                children: []
JunZai's avatar
JunZai committed
206 207 208 209
            })
        }
    }

JunZai's avatar
JunZai committed
210 211 212 213 214 215
    /**
     * 删除条件/组
     *
     * @return {*}
     * @memberof FilterTree
     */
JunZai's avatar
JunZai committed
216 217 218
    public onRemoveItem(node: any, data: any) {
        if(node && node.parent) {
            let pData: any = node.parent.data;
JunZai's avatar
JunZai committed
219 220
            if(pData.children.indexOf(data) >= 0) {
                pData.children.splice(pData.children.indexOf(data), 1)
JunZai's avatar
JunZai committed
221 222 223
            }
        }
    }
JunZai's avatar
JunZai committed
224 225 226 227 228 229 230 231 232 233 234 235

    /**
     * 条件逻辑变化
     *
     * @return {*}
     * @memberof FilterTree
     */
    public onModeChange(mode: any, data: any) {
        if(mode && data) {
            data.editor = mode.name;
        } 
    }
JunZai's avatar
JunZai committed
236 237 238
}
</script>

239 240
<style lang="scss">
@import './filter-tree.scss';
JunZai's avatar
JunZai committed
241
</style>