Vue实现动态查询规则生成组件

1. 动态查询规则

动态查询规则,大致如下图所示。是可以按照用户的自定义进行组织查询语句的一种复杂组件,大致可以实现SQL查询的where条件,下面是摘自mongodb的某一软件。

Vue实现动态查询规则生成组件

2.组件构建思路

按照规则组件的组织形式,可以把其视为一棵树,有树干和树叶,这样看起来就不难了。

2.1 组件属性 data: 是树结构的内容,我们定义为:

{
condition: \'AND\',
rules: [],
}

fieldList: 字段列表数组,可供选择的字段集合;

operatorList: 操作列表数组,可供选择的操作集合,定义如下:

{
     label: \'包含\',
          value: \'⊂\',
},

2.2 组件html

这里采用ElementUI构建,因此可以方便的组合各类ui控件来进行构建需要的界面。
当然该组件既然被看作树,因此其也是个递归组件,因此还涉及到自己调用自己。

<template>
    <div class=\"rules-group-container\">
        <div class=\"rules-group-header\">
            <el-radio-group v-model=\"data.condition\" size=\"mini\">
                <el-radio-button label=\"AND\"></el-radio-button>
                <el-radio-button label=\"OR\"></el-radio-button>
            </el-radio-group>
            <div>
                <el-button size=\"mini\" @click=\"addRule(data)\">添加规则</el-button>
                <el-button size=\"mini\" @click=\"addGroup(data)\">添加分组</el-button>
                <el-button v-if=\"parent\" size=\"mini\" @click=\"delGroup(data, parent)\">删除</el-button>
            </div>
        </div>
        <div class=\"rules-group-body\">
            <div class=\"rules-list\">
                <template v-for=\"(rule, index) in data.rules\">
                    <div :key=\"index\" v-if=\"!rule.condition\" class=\"rule-container\">                        
                        <!-- 字段 -->
                        <wt-dropdown
                            class=\"rule-item\"
                            v-model=\"rule.FilterField\"
                            :data=\"getFieldList(rule.FilterTable)\"
                            @change=\"handleFieldChange(rule)\"
                        ></wt-dropdown>
                        <!-- 操作符 -->
                        <wt-dropdown
                            class=\"rule-item\"
                            v-model=\"rule.Operator\"
                            :disabled=\"inputStatus && rule.FilterField === \'CommunityId\'\"
                            :data=\"getRule(rule.FilterTable, rule.FilterField)\"
                        ></wt-dropdown>
                        <!-- 值 -->
                        <wt-multi-dropdown
                            class=\"rule-item-long\"
                            v-if=\"rule.type === \'Dropdown\'\"
                            :disabled=\"inputStatus && rule.FilterField === \'CommunityId\'\"
                            v-model=\"rule.FilterValue\"
                            :data=\"getData(rule.FilterTable, rule.FilterField)\"
                        ></wt-multi-dropdown>
                        <wt-number
                            class=\"rule-item-long\"
                            :disabled=\"inputStatus && rule.FilterField === \'CommunityId\'\"
                            v-else-if=\"[\'DateTime\', \'Number\', \'Decimal\'].includes(rule.type)\"
                            v-model=\"rule.FilterValue\"
                        ></wt-number>
                        <wt-text class=\"rule-item-long\" v-else v-model=\"rule.FilterValue\" :disabled=\"inputStatus && rule.FilterField === \'CommunityId\'\"></wt-text>
                        <el-button size=\"mini\" @click=\"delRule(index)\">删除</el-button>
                    </div>
                    <CreateRule
                        :key=\"index\"
                        v-else
                        :data=\"rule\"
                        :parent=\"data\"
                        :fieldList=\"fieldList\"
                        :operatorList=\"operatorList\"
                    ></CreateRule>
                </template>
            </div>
        </div>
    </div>
</template>

2.3 对不同数据类型的字段定义不同的条件

const rules = {
    string: [
        {
            value: \'==\',
            label: \'等于\',
        },
        {
            value: \'<>\',
            label: \'不等于\',
        },
        {
            value: \'⊂\',
            label: \'包含\',
        },
        {
            value: \'⊄\',
            label: \'不包含\',
        },
        {
            value: \'in\',
            label: \'其中之一\',
        },
        {
            value: \'ni\',
            label: \'非其中之一\',
        },
        {
            value: \'mc\',
            label: \'多包含\',
        },
    ],
    number: [
        {
            value: \'==\',
            label: \'等于\',
        },
        {
            value: \'<>\',
            label: \'不等于\',
        },
        {
            value: \'≥\',
            label: \'大于等于\',
        },
        {
            value: \'≤\',
            label: \'小于等于\',
        },
    ],
    dict: [
        {
            value: \'in\',
            label: \'其中之一\',
        },
        {
            value: \'ni\',
            label: \'非其中之一\',
        },
    ],
    date: [
        {
            value: \'sdiff\',
            label: \'几天前\',
        },
        {
            value: \'ediff\',
            label: \'几天后\',
        },
    ],
}

2.4 定义方法操作组\\规则

主要的操作涉及到添加\\删除 规则

getRule(table, field) {
            let data = (rules && rules.string) || []
            let theField = this.getCurrentField(table, field)
            if (theField && theField.ControlType) {
                if ([\'Dropdown\'].includes(theField.ControlType)) {
                    return rules.dict
                } else if ([\'DateTime\'].includes(theField.ControlType)) {
                    return rules.date
                } else if ([\'Number\', \'Decimal\'].includes(theField.ControlType)) {
                    return rules.number
                } else {
                    return rules.string
                }
            }
            return data
        },
        // 添加规则
        addRule(data) {
            let rule = {
                type: \'Text\',
                FilterTable: this.firstTable,
                FilterField: this.firstField,
                Operator: \'==\',
                FilterValue: \'\',
            }
            data.rules.push(rule)
        },
        // 删除规则
        delRule(index) {
            this.data.rules.splice(index, 1)
        },
        // 添加分组
        addGroup(data) {
            let group = {
                condition: \'OR\',
                rules: [
                    {
                        type: \'Text\',
                        FilterTable: this.firstTable,
                        FilterField: \'\',
                        Operator: \'\',
                        FilterValue: \'\',
                    },
                ],
            }
            data.rules.push(group)
        },
        // 删除分组
        delGroup(data, parent) {
            let index = parent.rules.findIndex((item) => item === data)
            parent.rules.splice(index, 1)
        },

2.5 定义组件名

该组件命名为 CreateRule,定义代码很简单了。

export default {
    name: \'CreateRule\',
    props: {
        parent: {
            type: Object,
        },
        data: {
            type: Object,
        },
        fieldList: {
            type: Array,
            default() {
                return []
            },
        },
        operatorList: {
            type: Array,
            default() {
                return []
            },
        },
    },
  }

3.使用组件

vue中使用组件只需引用并增加到组件列表中即可。

import CreateRule from \'./CreateRule\'
export default {
    name: \'NewRuleForm\',
    components: {
        CreateRule,
    },
}

模板内增加引用

<template>
    <div class=\"new-rule-form\">
        <CreateRule
            v-if=\"!loading\"
            :data=\"data\"
            :fieldList=\"FilterTable\"
            :operatorList=\"operatorList\"
        ></CreateRule>
        <div v-if=\"!loading\" class=\"discription-wrap\" v-html=\"discription\"></div>
    </div>
</template>

4.效果展示

这是截取的实际效果.

Vue实现动态查询规则生成组件

在界面中,作为搜索条件或过滤条件效果均不错,可以做到非常灵活。

5.小结

在vue开发应用中,可以多参考下windows软件的某些界面,偶尔能给我们很大的灵感和启发的。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容