封装一个高级查询组件

news/2024/7/9 23:58:18 标签: java, vue

封装一个高级查询组件

  • 背景
    • 一,前端相关代码
    • 二,后端相关代码
    • 三,呈现效果
    • 总结

背景

业务有个按照自定义选择组合查询条件,保存下来每次查询的时候使用的需求。查了一下项目里的代码没有现成的组件可以用,于是封装了一个

一,前端相关代码

总体的设计的设想上,需要一个弹出式的对话框,可以点击增加条件,并且整体能比较容易的嵌入到界面的查询中。根据需求的查询条件需要支持常见的如输入框,下拉,时间等控件。因为使用场景不多,目前的需求范围暂时只支持三层括号。为了通用性应该做成每个界面按需配置的,譬如一个页面可以有多少个可供选择的查询条件,因此需要有个简单的协议通过配置渲染查询条件。安全起见,查询条件在后端拼成sql传给数据库中。
另外,对于有些本身在界面的增删改查的条件本身是组合的条件或者涉及到sql语句的一些逻辑的,这里使用的方法是通过反射给本来的查询vo里设值,而这些"VO_FIELD"的选项不参与界面的与或以及括号的组合,这涉及到一些特殊的修改
配置的demo如下

javascript">[
	{
		"field": "对应后端表字段1",
		"name": "输入框查询条件",
		"fieldType": "STRING",
		"conditions": [
			{
				"value": "=",
				"label": "等于=",
				"element": {
					"type": "input",
					"placeholder": "请输入查询条件1"
				}
			}
		]
	},
	{
		"field": "对应后端表字段2",
		"name": "下拉查询条件",
		"fieldType": "STRING",
		"conditions": [
			{
				"value": "in",
				"label": "在范围内in",
				"element": {
					"type": "select",
					"placeholder": "请选择下拉查询条件",
					"options": [
						{
							"value": 1,
							"label": "下拉查询条件1"
						},
						{
							"value": 2,
							"label": "下拉查询条件2"
						}
					]
				}
			}
		]
	},
	{
		"field": "对应后端表字段3",
		"name": "日期查询条件",
		"fieldType": "DATE",
		"conditions": [
			{
				"value": "between",
				"label": "介于between",
				"element": {
					"type": "datePickerRange"
				}
			},
			{
				"value": "=",
				"label": "等于=",
				"element": {
					"type": "datePicker"
				}
			}
		]
	}
]

这是组件的前端代码,删除一些业务相关的信息,以及查询接口的信息

javascript"><template>
    <div>
       <el-row :gutter="5">
         <!-- 弹窗, 高级搜索 -->
             <el-dialog
             v-dialogDrag
             title="高级搜索"
             :visible.sync="dialogFormVisible"
             @close="onClose()"
             @open="onOpen()"
             width="60%"
             >
             <el-form :model="form">
                 <!-- 操作按钮 -->
                 <el-row>
                 <el-col :span="24" class="pb15 pt5">
                     <el-button
                     @click="searchAdd()"
                     type="danger"
                     size="mini"
                     style="margin-left: 10px"
                     plain
                     >新增</el-button
                     >
                 </el-col>
                 </el-row>
                 <el-table :data="searchConditionList" style="width: 100%">

                 <el-table-column prop="relation" label="关联">
                     <template slot-scope="scope">
                     <el-select v-model="scope.row.relation" placeholder="请选择"  :disabled="scope.row.relationInputShow">
                         <el-option label="且" value="and"></el-option>
                         <el-option label="或" value="or"></el-option>
                     </el-select>
                     </template>
                 </el-table-column>

                 <el-table-column prop="leftBracket" label="括号"   width="70">
                     <template slot-scope="scope">
                     <el-select v-model="scope.row.leftBracket"  placeholder="" :disabled="scope.row.bracketShow"  clearable>
                         <el-option label="(" value="("></el-option>
                         <el-option label="((" value="(("></el-option>
                         <el-option label="(((" value="((("></el-option>
                     </el-select>
                     </template>
                 </el-table-column>

                 <el-table-column prop="field" label="栏位" width="180">
                     <template slot-scope="scope">
                     <el-select v-model="scope.row.field"
                     @change="fieldChange(scope.row,scope.row.field)"
                     placeholder="请选择">
                         <el-option
                         v-for="item in queryConditionsConfig"
                         :key="item.field"
                         :label="item.name"
                         :value="item.field"
                         >
                         </el-option>
                     </el-select>
                     </template>
                 </el-table-column>

                 
                 <el-table-column   width="25">
                     <template slot-scope="scope">
                     <span v-if="scope.row.prompt!=null&&scope.row.prompt!=''">
                        <el-tooltip placement="top">
                            <div style="white-space: pre-wrap;" slot="content">
                                {{scope.row.prompt}}
                            </div>
                            <i class="el-icon-question" />
                        </el-tooltip>
                     </span>
                     </template>
                 </el-table-column>

                 <el-table-column prop="condition" label="条件" width="180">
                     <template slot-scope="scope">
                     <el-select v-model="scope.row.condition" placeholder="请选择"
                     @change="conditionChange(scope.row.field,scope.row.condition)">
                         <el-option
                         v-for="item in fieldConditionMap.get(scope.row.field)"
                         :key="item.value"
                         :label="item.label"
                         :value="item.value"
                         >
                         </el-option>
                     </el-select>
                     </template>
                 </el-table-column>

                 <el-table-column prop="searchValue" label="搜索值" width="350">
                     <template slot-scope="scope" >
                        <!-- 输入框 -->
                     <el-input  v-if="inputChoosed(scope.row.field,scope.row.condition)"
                         v-model="scope.row.searchValue"
                         :placeholder="inputPlaceholder(scope.row.field,scope.row.condition)"
                     ></el-input>
                     <!-- 下拉多选框 -->
                     <el-select v-model="scope.row.tempSelectOptions" placeholder="请选择"
                         multiple
                     v-if="selectChoosed(scope.row.field,scope.row.condition)"
                     :placeholder="inputPlaceholder(scope.row.field,scope.row.condition)"
                     @change="combineSelectOptions(scope.row,scope.row.tempSelectOptions);(val) => this.$forceUpdate()"
                     style="width: 100%;"
                     >
                         <el-option
                         v-for="item in fieldElementOptionsMap.get(scope.row.field+scope.row.condition)"
                         :key="item.value"
                         :label="item.label"
                         :value="item.value"
                         >
                         </el-option>
                     </el-select>
                         <!-- 下拉单选框 -->
                     <el-select v-model="scope.row.searchValue" placeholder="请选择"
                     v-if="singleSelectChoosed(scope.row.field,scope.row.condition)"
                     :placeholder="inputPlaceholder(scope.row.field,scope.row.condition)"
                     clearable
                     style="width: 100%;"
                     >
                         <el-option
                         v-for="item in fieldElementOptionsMap.get(scope.row.field+scope.row.condition)"
                         :key="item.value"
                         :label="item.label"
                         :value="item.value"
                         >
                         </el-option>
                     </el-select>
                       <!-- 日期范围 -->
                     <el-date-picker v-if="datePickerRangeChoosed(scope.row.field,scope.row.condition)"
                         v-model="scope.row.tempDateRange"
                         type="daterange"
                         :default-time="['00:00:00', '23:59:59']"
                         value-format="yyyy-MM-dd"
                         range-separator="至"
                         start-placeholder="开始日期"
                         end-placeholder="结束日期"
                         size="mini" style="padding-top: 0px;padding-bottom:0px;line-height:24px;width: 100%;"
                         @change="combineDateRange(scope.row,scope.row.tempDateRange);(val) => this.$forceUpdate()"
                         >
                     </el-date-picker>
                     <!-- 日期 -->
                     <el-date-picker  v-if="datePickerChoosed(scope.row.field,scope.row.condition)"
                         v-model="scope.row.searchValue"
                         type="date"
                         value-format="yyyy-MM-dd"
                         placeholder="请输入日期"
                         size="mini" style="padding-top: 0px;padding-bottom:0px;line-height:24px;width: 100%;"
                         >
                     </el-date-picker>
                     </template>
                 </el-table-column>

                 <el-table-column prop="rightBracket" label="括号"  width="70">
                     <template slot-scope="scope" >
                     <el-select v-model="scope.row.rightBracket"  placeholder="" :disabled="scope.row.bracketShow" clearable>
                         <el-option label=")" value=")"></el-option>
                         <el-option label="))" value="))"></el-option>
                         <el-option label=")))" value=")))"></el-option>
                     </el-select>
                     </template>
                 </el-table-column>

                 <el-table-column align="center" label="操作">
                     <template slot-scope="scope">
                     <el-button
                         type="text"
                         size="small"
                         @click="deleteData(scope.row.id, scope.$index)"
                         >删除</el-button
                     >
                     </template>
                 </el-table-column>
                 </el-table>
                 <template>
                     <el-col :span="24">
                         <el-col :md="12" :lg="16" class="margin-bottom-5">
                         <div class="el-input el-input--mini el-input-group">
                             <div >收藏夹
                             <el-select v-model="currentConfigIndex" placeholder="请选择"
                             @change="changeConfig"
                             @clear="clearConfig"
                             clearable
                             >
                                 <el-option
                                 v-for="item in existQueryConfigs"
                                 :key="item.id"
                                 :label="item.configName"
                                 :value="item.id"
                                 >
                                 </el-option>
                             </el-select>
                         </div>
                         </div>
                         </el-col>
                         <el-col :span="8" class="margin-bottom-5">
                             <el-checkbox v-model="applicationShareFlag" style="display:block;">是否共享至应用层(所有人)</el-checkbox>
                             <el-checkbox v-model="roleShareFlag" style="display:block;">是否共享至角色层(当前角色)</el-checkbox>
                             <el-input  v-model="currentConfigName" placeholder="输入保存名称" style="width:300px" ></el-input>
                         </el-col>
                     </el-col>
                 </template>
             </el-form>
             <div slot="footer" class="dialog-footer">
                 <el-button plain @click="onClose()">取 消</el-button>
                 <el-button type="info" @click="saveCondition">保存到收藏夹</el-button>
                 <el-button type="info" @click="searchByConditions">搜索</el-button>
             </div>
             </el-dialog>
         </el-row>
     </div>

   </template>
   <style >
   </style>
   <script>

   import advanceQuery from './advance-query'
     import { mixin } from '@/mixin/mixin'
     import {cloneDeep} from 'lodash'

  export default {
    name: "advance-query",
    mixins: [mixin],
    components: {},
    props: {
           //查询条件整体配置
      queryConditionsConfig: {
        type: Object,
        default: {},
        required: true
      },
      queryDataFunc:  Function,
      //查主界面列表的条件
      condition:{
        type: Object,
        default: {}
      },
      //对话框显示
      dialogFormVisible: {
        type: Boolean,
        default: true
      },
       //页面名称
      bizPageName: {
        type: String,
        default: ""
      },
      dataList:{
        type: Object,
        default: {}
      },
      total:{
        type: Number,
        default: {}
      },
      //搜索条件,用于回传
      searchConditionList:{
        type: Object,
        default: {}
      },
    },
    data() {
      return {
        //当前选中的字段
        currentField:{},
        //field和条件的map
        fieldConditionMap: new Map(),
        //field和控件相关的map
        fieldElemenTypeChooseMap: new Map(),
        fieldElementPlaceholderMap: new Map(),
        fieldElementOptionsMap: new Map(),
        currentField:'',
        currentCondition:'',

        existQueryConfigs:[],
        applicationShareFlag:false,
        roleShareFlag:false,
        currentConfigName:"",
        currentConfigIndex:"",
        roleCode:""

      };
    },
    async created() {
        await this.getCurrentRoleCodes()
        this.getConfigs()
    },
    methods: {
    // 高级搜索-新增
    searchAdd() {
        let newsearchObject = {
            field: "", //栏位
            fieldType:"",//字段类型
            condition: "", //条件
            searchValue: "", //搜索值
            relation: "and", //关联
            relationInputShow:true,//控制关联不可选择
            bracketShow:false//控制括号不可选择
        };
        this.searchConditionList.push(newsearchObject);
        this.modifyRelationAndBracket()
        },
        //高级搜索-删除
        deleteData(id, index) {
            this.searchConditionList.splice(index, 1);
            this.modifyRelationAndBracket()
        },
        // 高级搜索-保存
        saveCondition() {
            let param={}
            param.applicationShareFlag=this.applicationShareFlag
            param.roleShareFlag=this.roleShareFlag
            param.configName=this.currentConfigName
            param.id=this.currentConfigIndex
            param.roleCode=this.roleCode
            param.bizPageName=this.bizPageName
            let tempConditionTable=[]
            tempConditionTable = cloneDeep(this.searchConditionList)
            //干掉两个临时变量
            tempConditionTable.forEach(item=>{
                if(item.tempDateRange!=null){
                    item.tempDateRange=null
                }
                if(item.tempSelectOptions!=null){
                    item.tempSelectOptions=null
                }
            })
            param.configJson=JSON.stringify(tempConditionTable)
            if(param.configName==''){
                this.$message.warning('配置名称不可以为空!');
                return
            }
            apAdvanceQuery.saveConfig(param).then( data => {
                if( data.data.status==0){
                    this.$message.success('保存成功')
                    this.getConfigs()
                }else{
                    this.$message.error('保存失败')
                }
            });
        },
        // 获取数据列表
        searchByConditions() {
        //   console.log("打印查询参数:",JSON.stringify(this.condition))
          let param = Object.assign({},this.condition)
          param.start= this.condition.limit * (this.condition.page - 1),
          param.length= this.condition.limit,
          param.searchConditionList=this.searchConditionList
          this.queryDataFunc(param).then( data => {
            if (data.data.status === 0) {
                this.$emit('update:dataList', data.data.data)
                this.$emit('update:total', data.data.count)
                this.$emit('update:searchConditionList', this.searchConditionList)
                this.$emit('changeAdvanceConfigName',this.currentConfigName==""&&this.searchConditionList.length>=1?"新建":this.currentConfigName)
            } else {
                this.$message.error(data.data.msg);
            }
          });
        },
        //切换栏目
        fieldChange(row,field){
            this.queryConditionsConfig.forEach(item=>{
                if(item.field===field){
                    row.fieldType=item.fieldType
                    row.prompt=item.prompt
                    this.fieldConditionMap.set(item.field,item.conditions)
                }
            })
            this.modifyRelationAndBracket()
        },
        //切换条件
        conditionChange(field,condition){
            this.currentField=field,
            this.currentCondition=condition,
            this.fieldConditionMap.get(field).forEach(item=>{
                if(item.value===condition){
                    this.fieldElementPlaceholderMap.set(field+condition,item.element.placeholder)
                    this.fieldElementOptionsMap.set(field+condition,item.element.options)
                    this.fieldElemenTypeChooseMap.set(field+condition,item.element.type)
                }
            })
        },
        inputChoosed:function(field,condition){
            return this.fieldElemenTypeChooseMap.get(field+condition)==='input';
        },
        selectChoosed:function(field,condition){
            return this.fieldElemenTypeChooseMap.get(field+condition)==='select';
        },
        singleSelectChoosed:function(field,condition){
            return this.fieldElemenTypeChooseMap.get(field+condition)==='singleSelect';
        },
        datePickerRangeChoosed:function(field,condition){
            return this.fieldElemenTypeChooseMap.get(field+condition)==='datePickerRange';
        },
        datePickerChoosed:function(field,condition){
            return this.fieldElemenTypeChooseMap.get(field+condition)==='datePicker';
        },
        //切换配置
        changeConfig(value){
            this.existQueryConfigs.forEach(config=>{
                if(config.id===value){
                    this.currentConfigName=config.configName
                    this.currentConfigIndex=config.id
                    this.applicationShareFlag=config.applicationShareFlag
                    this.roleShareFlag=config.roleShareFlag
                    this.searchConditionList=[]
                    config.searchObjects.forEach(item=>{
                        let newsearchObject={}
                        Object.assign(newsearchObject, item);
                        this.fieldChange(newsearchObject,newsearchObject.field)
                        this.conditionChange(newsearchObject.field,newsearchObject.condition)
                        this.searchConditionList.push(newsearchObject);
                        }
                    )
                }
            })
        },
        //清除选中的配置
        clearConfig(){
            this.currentConfigName=""
            this.currentConfigIndex=""
            this.applicationShareFlag=false
            this.roleShareFlag=false
            this.searchConditionList=[]
        },
        getCurrentRoleCodes(){
    		//获取当前角色信息
        },
        getConfigs(){
       //获取已经保存的查询配置
        },
        combineDateRange(row,value){
            if(value!=null&&value!=[]){
                row.searchValue=value[0]+','+value[1]
            }else{
                row.searchValue=null
            }
        },
        combineSelectOptions(row,value){
            if(value!=null){
                row.searchValue=value.reduce((prev, curr) => {
                    return prev+','+curr
                }, '')
                row.searchValue=row.searchValue.slice(1)
            }
        },
        //关联关系和括号修改
        modifyRelationAndBracket(){
            this.searchConditionList.forEach((item,index)=>{
                if(index == 0){
                    item.relation= "and"
                    item.relationInputShow = true
                    if(item.fieldType==='VO_FIELD'){
                        item.bracketShow=true
                    }else{
                        item.bracketShow=false
                    }
                }else if(item.fieldType==='VO_FIELD'){//这种类型的字段不参与与或拼接
                    item.relation= ""
                    item.relationInputShow = true
                    item.bracketShow=true
                }else{
                    item.relationInputShow = false
                    item.bracketShow=false
                }
            })
        },
        //调用父组件实现关闭事件
        onClose() {
            this.$emit('update:dialogFormVisible', false)
        },
        //打开时候先初始化一下配置的显示
        onOpen(){
            this.changeConfig(this.currentConfigIndex);
        }
    },computed:{
        inputPlaceholder(){
            return function(field,value){
               return this.fieldElementPlaceholderMap.get(field+value)
            }
        }
      },
  };
  </script>

二,后端相关代码

后端相关的代码主要是参与解析条件生成配置的
配置的实体类如下

java">@Data
public class AdvanceSearchCondition {
    /**
     * 栏位
     */
    private String field;

    /**
     * 条件
     */
    private String  condition;

    /**
     * 搜寻值
     */
    private String searchValue;

    /**
     * 关联
     */
    private  String relation;

    /**
     * 字段类型
     */
    private  String fieldType;

    /**
     * 左括号
     */
    private String leftBracket;

    /**
     * 右括号
     */
    private String rightBracket;

}

主要的生成sql查询条件的方法如下

java">public class AdvancedSearchBizService {
    /**
     * 返回生成的sql查询条件,同时部分无法拼接成sql的字段修饰到查询vo里
     * @param searchConditionList
     * @param queryVo
     * @return
     */
    public static String genarateConditionSql(List<AdvanceSearchCondition> searchConditionList,Object queryVo) {
        if(CollectionUtils.isEmpty(searchConditionList)){
            return StringUtils.EMPTY;
        }
        List<AdvanceSearchCondition> validList = searchConditionList.stream().filter(AdvancedSearchBizService::validate).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(validList)){
            return StringUtils.EMPTY;
        }
        //有些字段不能用拼sql的方式处理,因此直接作用到查询vo上
        List<AdvanceSearchCondition> decorateQueryVoList = validList.stream().filter(x-> conditionFieldTypeEnum.VO_FIELD.name().equalsIgnoreCase(x.getFieldType())).collect(Collectors.toList());
        validList.removeAll(decorateQueryVoList);
        decorateQueryVo(queryVo,decorateQueryVoList);
        //select *  from table where 1=1 拼上 条件(关联符号在前)
        StringBuilder searchParamer = new StringBuilder();
        String space = " ";
        for (AdvanceSearchCondition searchCondition : validList ) {
            String field = searchCondition.getField().toLowerCase();
            String value = searchCondition.getSearchValue();
            String searchVal =AdvanceSearchUtils.convertValue(searchCondition);
            String condition = searchCondition.getCondition();
            String relation = searchCondition.getRelation();
            String leftBracket=StringUtils.isNotBlank(searchCondition.getLeftBracket())?searchCondition.getLeftBracket():space;
            String rightBracket=StringUtils.isNotBlank(searchCondition.getRightBracket())?searchCondition.getRightBracket():space;

            // = 拼接的情况
            if (condition.equals(SearchConditionEnum.EQUALS.chs())) {
                //转一下,如果是string类型输了多个值,也用替换成in
                if(searchVal.contains(",")) {
                    searchParamer.append(space).append(relation)
                            .append(space)
                            .append(leftBracket)
                            .append(space).append(field)
                            .append(space).append(SearchConditionEnum.IN.chs())
                            .append(space).append("(")
                            .append(space).append(searchVal)
                            .append(space).append(") ")
                            .append(space).append(rightBracket)
                            .append(space);
                }else {
                    searchParamer.append(space).append(relation)
                            .append(space)
                            .append(leftBracket)
                            .append(space).append(field)
                            .append(space).append(condition)
                            .append(space).append(searchVal)
                            .append(space).append(rightBracket)
                            .append(space);
                }
            }
            // <> 拼接的情况
            if (condition.equals(SearchConditionEnum.NOT_EQUALS.chs())) {
                searchParamer.append(space).append(relation)
                        .append(space)
                        .append(leftBracket)
                        .append(space).append(field)
                        .append(space).append(condition)
                        .append(space).append(searchVal)
                        .append(space).append(rightBracket).append(space);
            }
            //  > 拼接的情况
            if (condition.equals(SearchConditionEnum.GREATER_THAN.chs())) {
                searchParamer.append(space).append(relation)
                        .append(space)
                        .append(leftBracket)
                        .append(space).append(field)
                        .append(space).append(condition)
                        .append(space).append(searchVal)
                        .append(space).append(rightBracket).append(space);
            }
            // < 拼接的情况
            if (condition.equals(SearchConditionEnum.LESS_THAN.chs())) {
                searchParamer.append(space).append(relation)
                        .append(space)
                        .append(leftBracket)
                        .append(space).append(field)
                        .append(space).append(condition)
                        .append(space).append(searchVal)
                        .append(space).append(rightBracket).
                        append(space);
            }
            // >= 拼接的情况
            if (condition.equals(SearchConditionEnum.GREATER_EQUALS.chs())) {
                searchParamer.append(space).append(relation)
                        .append(space)
                        .append(leftBracket)
                        .append(space).append(field)
                        .append(space).append(condition)
                        .append(space).append(searchVal)
                        .append(space).append(rightBracket).
                        append(space);
            }
            // <= 拼接的情况
            if (condition.equals(SearchConditionEnum.LESS_EQUALS.chs())) {
                searchParamer.append(space).append(relation)
                        .append(space)
                        .append(leftBracket)
                        .append(space).append(field)
                        .append(space).append(condition)
                        .append(space).append(searchVal)
                        .append(space).append(rightBracket).
                        append(space);
            }
            // in 拼接的情况
            if (condition.equals(SearchConditionEnum.IN.chs())) {
                searchParamer.append(space).append(relation)
                        .append(space)
                        .append(leftBracket)
                        .append(space).append(field)
                        .append(space).append(condition)
                        .append(space).append("(")
                        .append(space).append(searchVal)
                        .append(space).append(") ")
                        .append(space).append(rightBracket)
                        .append(space);
            }
            // not in  拼接的情况
            if (condition.equals(SearchConditionEnum.NOT_IN.chs())) {
                searchParamer.append(space).append(relation)
                        .append(space)
                        .append(leftBracket)
                        .append(space).append(field)
                        .append(space).append(condition)
                        .append(space).append("(")
                        .append(space).append(searchVal)
                        .append(space).append(") ")
                        .append(space).append(rightBracket)
                        .append(space);
            }
            // like 拼接的情况
            if (condition.equals(SearchConditionEnum.LIKE.chs())) {
                searchParamer.append(space).append(relation)
                        .append(space)
                        .append(leftBracket)
                        .append(space).append(field)
                        .append(space).append(condition)
                        .append(space).append("'%").append(searchVal.replace("'","")).append("%'")
                        .append(space).append(rightBracket).
                        append(space);
            }
            // not like  拼接的情况
            if (condition.equals(SearchConditionEnum.NOT_LIKE.chs())) {
                searchParamer.append(space).append(relation)
                        .append(space)
                        .append(leftBracket)
                        .append(space).append(field)
                        .append(space).append(condition)
                        .append(space).append("'%").append(searchVal).append("%'")
                        .append(space).append(rightBracket).
                        append(space);
            }
            // between 拼接的情况  between... and...
            // not between  拼接的情况
            if (condition.equals(SearchConditionEnum.BETWEEN.chs())) {
                String[] contentUnits = value.split(",");
                if (contentUnits.length != 2) {
                    throw new BizException("搜索值栏位必须输入两个参数且用“,”隔开");
                }
                String leftContentUnit = contentUnits[0];
                String rightContentUnit = contentUnits[1];
                if(!AdvanceSearchUtils.isNumber(leftContentUnit)){
                    searchParamer.append(space).append(relation)
                            .append(space)
                            .append(leftBracket)
                            .append(space).append(field)
                            .append(space).append(condition).append(space)
                            .append("'").append(leftContentUnit).append("'")
                            .append(space).append("and").append(space)
                            .append("'").append(rightContentUnit).append("' ")
                            .append(space).append(rightBracket).
                            append(space);
                }else {
                    searchParamer.append(space).append(relation)
                            .append(space)
                            .append(leftBracket)
                            .append(space).append(field)
                            .append(space).append(condition)
                            .append(space).append(leftContentUnit)
                            .append(space).append("and")
                            .append(space).append(rightContentUnit)
                            .append(space).append(rightBracket).
                            append(space);
                }
            }
            if (condition.equals(SearchConditionEnum.NOT_BETWEEN.chs())) {
                String[] contentUnits = value.split(",");
                if (contentUnits.length != 2) {
                    throw new RuntimeException("搜索值栏位必须输入两个参数且用“,”隔开");
                }
                String leftContentUnit = contentUnits[0];
                String rightContentUnit = contentUnits[1];
                if(!AdvanceSearchUtils.isNumber(leftContentUnit)){
                    searchParamer.append(space).append(relation)
                            .append(space)
                            .append(leftBracket)
                            .append(space).append(field)
                            .append(space).append(condition).append(space)
                            .append("'").append(leftContentUnit).append("'")
                            .append(space).append("and").append(space)
                            .append("'").append(rightContentUnit).append("' ")
                            .append(space).append(rightBracket)
                            .append(space);
                }else {
                    searchParamer.append(space).append(relation)
                            .append(space)
                            .append(leftBracket)
                            .append(space).append(field)
                            .append(space).append(condition)
                            .append(space).append(leftContentUnit)
                            .append(space).append("and")
                            .append(space).append(rightContentUnit)
                            .append(space).append(rightBracket).
                            append(space);
                }
            }
        }
        if(!CollectionUtils.isEmpty(searchConditionList) && StringUtils.isNotBlank(searchParamer)) {
            searchParamer.insert(4, "(");
            searchParamer.append(")");
        }
        String sqlCondition=searchParamer.toString();
        checkBracketMatch(sqlCondition);
        return sqlCondition;
    }

    private static void checkBracketMatch(String sqlCondition) {
        Deque<Character> stringStack = new LinkedList<>();
        char tempChar;
        for (int i = 0; i < sqlCondition.length(); i++) {
            tempChar = sqlCondition.charAt(i);
            switch (tempChar) {
                case '(': {
                    stringStack.push(tempChar);
                    break;
                }
                case ')':
                    if(stringStack.isEmpty()){
                        throw new BizException("括号不匹配,请检查");
                    }
                    if (stringStack.pop() != '(') {
                        throw new BizException("括号不匹配,请检查");
                    }
                    break;
                default:
            }
        }
        if (!stringStack.isEmpty()) {
            throw new BizException("括号不匹配,请检查");
        }
    }

    /**
     * 把参数设置进vo里
     * @param queryVo
     * @param decorateQueryVoList
     */
    private static void decorateQueryVo(Object queryVo, List<AdvanceSearchCondition> decorateQueryVoList) {
        if(CollectionUtils.isEmpty(decorateQueryVoList)){
            return;
        }
        try {
            for (AdvanceSearchCondition one : decorateQueryVoList) {
                Field field = ReflectionUtil.getField(queryVo.getClass(), one.getField());
                Type type = field.getGenericType();
                Set<Object> supportValues = new HashSet<>();
                if (type instanceof ParameterizedType) {
                    Class<?> clazz = (Class<?>) ((ParameterizedType) type).getActualTypeArguments()[0];
                    for (String val : Arrays.asList(one.getSearchValue().split(","))) {
                        switch (clazz.getTypeName()) {
                            case "java.lang.String":
                                supportValues.add(val);
                                break;
                            default:
                                supportValues.add(clazz.getMethod("valueOf", String.class).invoke(null, val));
                                break;
                        }
                    }
                    ReflectionUtil.setFieldValue(queryVo, one.getField(), supportValues);
                }else{
                    ReflectionUtil.setFieldValue(queryVo, one.getField(), one.getSearchValue());
                }
            }
        }catch (Exception e){
            Log.error("高级查询设置vo参数失败"+e.getMessage(),e);
        }
    }

    private static boolean validate(AdvanceSearchCondition condition){
        if(!condition.getFieldType().equalsIgnoreCase(conditionFieldTypeEnum.VO_FIELD.name())) {
            return StringUtils.isNotBlank(condition.getField())
                    && StringUtils.isNotBlank(condition.getFieldType())
                    && StringUtils.isNotBlank(condition.getCondition())
                    && StringUtils.isNotBlank(condition.getSearchValue())
                    && StringUtils.isNotBlank(condition.getRelation())
                    ;
        }else{
            return StringUtils.isNotBlank(condition.getField())
                    && StringUtils.isNotBlank(condition.getFieldType())
                    && StringUtils.isNotBlank(condition.getCondition())
                    && StringUtils.isNotBlank(condition.getSearchValue())
                    ;
        }
    }

}

这里生成的sql片段就可以当成一个简单的查询条件追加到原来的sql上面
在这里插入图片描述

三,呈现效果

最终效果如下
在这里插入图片描述

总结

接触前端也有两年了,从一开始只想着调用别人的组件慢慢的也喜欢自己封装一些组件简化业务开发过程。不过由于对前端的一些高级的写法不太熟悉可能写出来的代码啰嗦了一些,并且时间仓促落地的场景不多可能也有比较多的隐含的bug存在,还望读者不吝赐教。
作者:连


http://www.niftyadmin.cn/n/5047555.html

相关文章

线性dp,毫哥和巨佬的故事

Contest (nefu.edu.cn) Problem:E Time Limit:10000ms Memory Limit:262144K Description 众所周知&#xff0c;毫哥和巨佬是好朋友&#xff0c;他们各有所好&#xff0c;毫哥喜欢数字&#xff0c;巨佬喜欢取余&#xff0c;有一天他们决定来玩一个游戏来决定谁的能力更高。…

Nature Communications | 张阳课题组:端到端深度学习实现高精度RNA结构预测

RNA分子是基因转录的主要执行者&#xff0c;也是细胞运作的隐形功臣。它们在基因表达调控、支架构建以及催化活性等多个生命过程中都扮演着关键角色。虽然RNA如此重要&#xff0c;但由于实验数据的缺乏&#xff0c;准确预测RNA 的三维空间结构仍然是目前计算生物学面临的重大挑…

rust泛型

泛型&#xff0c;英文是generic。 泛型是一种参数化多态。就是把类型作为参数&#xff0c;使用时才指定具体类型。 这样一套代码可以应用于多种类型。比如Vec<T>&#xff0c;可以是整型向量Vec<i32>&#xff0c;也可以是浮点型向量Vec<f64>。 Rust中的泛型属…

闲话Python编程-初入小门

Python语言号称是最简单最容易学习的编程语言&#xff0c;有口号&#xff1a;人生苦短&#xff0c;我用Python&#xff01;常常Python又被称为脚本语言&#xff0c;给人感觉都是很容易的&#xff0c;相对于C和Java&#xff0c;这个观点是真实不虚的。 但是过犹不及&#xff0c;…

【数据结构】链表和LinkedList的理解和使用

目录 1.前言 2.链表 2.1链表的概念以及结构 2.2链表的实现 3.LinkedList的使用 3.1什么是LinkedList 3.2LinkedList的使用 2.常用的方法介绍 4. ArrayList和LinkedList的区别 1.前言 在上一篇文章中我们介绍了顺序表&#xff0c;ArrayList的底层原理和具体的使用&#x…

二、怎么简单使用vuex

目录 前提步骤&#xff1a;正式开始vuex的相关操作&#xff1a;一、安装vuex&#xff1a;二、项目配置VUEX&#xff1a;三、创建相关文件&#xff1a;1、state2、getters3、mutations4、actions5、modules 前提步骤&#xff1a; 1、 搭建一个vue2项目 2、 修改App.vue文件&…

Java中的继承是什么?

在Java中&#xff0c;继承是一种面向对象编程的概念&#xff0c;它允许一个类&#xff08;称为子类或派生类&#xff09;继承另一个类&#xff08;称为父类或基类&#xff09;的属性和方法。通过继承&#xff0c;子类可以获得父类的属性和方法&#xff0c;并且可以添加自己的特…

HTTP 协议的定义,工作原理,Fiddler的原理和使用,请求的内容

文章目录 一. HTTP协议是什么?1.HTTP工作原理2.HTTP协议格式2.1抓包工具的原理2.2抓包工具的使用2.3 HTTP协议的内容请求首行请求头(header)空行正文(body) 一. HTTP协议是什么? HTTP (全称为 “超文本传输协议”) 是一种应用非常广泛的 应用层协议. "超文本"是指…