当前位置: 首页 > news >正文

封装一个高级查询组件

封装一个高级查询组件

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

背景

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

一,前端相关代码

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

[{"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"}}]}
]

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

<template><div><el-row :gutter="5"><!-- 弹窗, 高级搜索 --><el-dialogv-dialogDragtitle="高级搜索":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-optionv-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-optionv-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="请选择"multiplev-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-optionv-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)"clearablestyle="width: 100%;"><el-optionv-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-buttontype="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-optionv-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和条件的mapfieldConditionMap: new Map(),//field和控件相关的mapfieldElemenTypeChooseMap: 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.applicationShareFlagparam.roleShareFlag=this.roleShareFlagparam.configName=this.currentConfigNameparam.id=this.currentConfigIndexparam.roleCode=this.roleCodeparam.bizPageName=this.bizPageNamelet 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.searchConditionListthis.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.fieldTyperow.prompt=item.promptthis.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.configNamethis.currentConfigIndex=config.idthis.applicationShareFlag=config.applicationShareFlagthis.roleShareFlag=config.roleShareFlagthis.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=falsethis.roleShareFlag=falsethis.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 = trueif(item.fieldType==='VO_FIELD'){item.bracketShow=true}else{item.bracketShow=false}}else if(item.fieldType==='VO_FIELD'){//这种类型的字段不参与与或拼接item.relation= ""item.relationInputShow = trueitem.bracketShow=true}else{item.relationInputShow = falseitem.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>

二,后端相关代码

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

@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查询条件的方法如下

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类型输了多个值,也用替换成inif(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存在,还望读者不吝赐教。
作者:连

相关文章:

封装一个高级查询组件

封装一个高级查询组件 背景一&#xff0c;前端相关代码二&#xff0c;后端相关代码三&#xff0c;呈现效果总结 背景 业务有个按照自定义选择组合查询条件&#xff0c;保存下来每次查询的时候使用的需求。查了一下项目里的代码没有现成的组件可以用&#xff0c;于是封装了一个 …...

代码随想录第七章 栈与队列

1、leecode232 用栈实现队列 使用栈模拟队列的行为&#xff0c;仅使用一个栈是不行的&#xff0c;所以需要两个栈&#xff0c;一个是输入栈&#xff0c;一个是输出栈。 #include<iostream> #include<vector> #include<string> #include<stack> #incl…...

SQL Server对象类型(5)——4.5. 同义词(Synonym)

4.5. 同义词(Synonym) 4.5.1. 同义词概念 与Oracle中相同,SQL Server中的同义词是虚的、被定义的模式对象,其本身并不存储任何数据。其用途之一就是为其他类型基础对象提供一个别名;用途之二就是为应用提供一个抽象层,以方便后期应用相关的基础对象的更改和维护。用户可…...

IP风险查询:抵御DDoS攻击和CC攻击的关键一步

随着互联网的普及&#xff0c;网络攻击变得越来越普遍和复杂&#xff0c;对企业和个人的网络安全构成了重大威胁。其中&#xff0c;DDoS&#xff08;分布式拒绝服务&#xff09;攻击和CC&#xff08;网络连接&#xff09;攻击是两种常见且具有破坏性的攻击类型&#xff0c;它们…...

Tune-A-Video论文阅读

论文链接&#xff1a;Tune-A-Video: One-Shot Tuning of Image Diffusion Models for Text-to-Video Generation 文章目录 摘要引言相关工作文生图扩散模型文本到视频生成模型文本驱动的视频编辑从单个视频生成 方法前提DDPMsLDMs 网络膨胀微调和推理模型微调基于DDIM inversio…...

Dataset和DataLoader用法

Dataset和DataLoader用法 在d2l中有简洁的加载固定数据的方式&#xff0c;如下 d2l.load_data_fashion_mnist() # 源码 Signature: d2l.load_data_fashion_mnist(batch_size, resizeNone) Source: def load_data_fashion_mnist(batch_size, resizeNone):"""…...

【跟小嘉学习区块链】二、Hyperledger Fabric 架构详解

系列文章目录 【跟小嘉学习区块链】一、区块链基础知识与关键技术解析 【跟小嘉学习区块链】一、区块链基础知识与关键技术解析 文章目录 系列文章目录[TOC](文章目录) 前言一、Hyperledger 社区1.1、Hyperledger(面向企业的分布式账本)1.2、Hyperledger社区组织结构 二、Hype…...

springboot下spring方式实现Websocket并设置session时间

概述 springboot实现websocket有4种方式 servlet&#xff0c;spring&#xff0c;netty&#xff0c;stomp 使用下来spring方式是最简单的. springboot版本&#xff1a;3.1.2 jdk&#xff1a;17 当前依赖版本 <dependency><groupId>org.springframework.boot<…...

LeetCode算法二叉树—相同的树

目录 100. 相同的树 - 力扣&#xff08;LeetCode&#xff09; 代码&#xff1a; 运行结果&#xff1a; 给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是…...

搭建Flink集群、集群HA高可用以及配置历史服务器

Flink集群搭建 Flink集群搭建集群规划下载并解压安装包修改集群配置分发安装目录启动集群访问Web UI Flink集群HA高可用概述集群规划配置flink配置master、workers配置ZK分发安装目录启动HA集群测试 Flink参数配置配置历史服务器概述配置启动、停止历史服务器提交一个Job任务查…...

vscode终端中打不开conda虚拟包管理

今天&#xff0c;想着将之前鸽的Unet网络模型给实现一下&#xff0c;结果发现&#xff0c;在vscode中运行python脚本&#xff0c;显示没有这包&#xff0c;没有那包。但是在其他的ipynb中是有的&#xff0c;感觉很奇怪。我检查了一下python版本&#xff0c;发现不是我深度学习的…...

【音视频】MP4封装格式

基本概念 使用MP4box.js查看MP4内部组成结构 整体结构 数据索引&#xff08;moov&#xff09;数据流包&#xff08;mdat&#xff09; 各个包的位置&#xff0c;大小&#xff0c;信息&#xff0c;时间戳&#xff0c;编码方式等全在数据索引 数据流包只有纯二进制码流数据 数据…...

环境-使用vagrant快速创建linux虚拟机

1.下载软件 虚拟机 Oracle VM VirtualBox 镜像 Vagrant by HashiCorp (vagrantup.com) 如果下载慢&#xff0c;可以复制下载链接&#xff0c;使用迅雷下载 2.安装 根据提示点击下一步即可&#xff0c;建议安装到空间较大的非系统盘。 打开 window cmd 窗口&#xff0c;…...

10.1网站编写(Tomcat和servlet基础)

一.Tomcat: 1.Tomcat是java写的,运行时需要依赖jre,所以要装jdk. 2.建议配置好环境变量. 3.默认端口号8080(业务端口)可能会被占用,建议改一下(本人改成了9999). 4.另一个默认端口是8005(管理端口). 二Servlet基础(编写一个hello world代码): 整体分为7个步骤,分别是创建…...

10CQRS

本系列包含以下文章&#xff1a; DDD入门DDD概念大白话战略设计代码工程结构请求处理流程聚合根与资源库实体与值对象应用服务与领域服务领域事件CQRS&#xff08;本文&#xff09; 案例项目介绍 # 既然DDD是“领域”驱动&#xff0c;那么我们便不能抛开业务而只讲技术&…...

DAZ To UMA⭐一.DAZ简单使用教程

文章目录 &#x1f7e5; DAZ快捷键&#x1f7e7; DAZ界面介绍 &#x1f7e5; DAZ快捷键 移动物体:ctrlalt鼠标左键 旋转物体:ctrlalt鼠标右键 导入模型:双击左侧模型UI &#x1f7e7; DAZ界面介绍 Files:显示全部文件 Products:显示全部产品 Figures:安装的全部人物 Wardrobe…...

面试题 —— Java集合篇(23题)

文章目录 1.Java中常见集合有哪些 &#xff1f;2. 说说你对Java集合是怎么理解的&#xff1f;3.请你说一下List&#xff0c;Set&#xff0c;Map三者的特点是 &#xff1f;4.在实际开发过程中如何更好的选择集合 &#xff1f;5. ArrayList和Vector区别 &#xff1f;6. ArrayList…...

SpringBoot2.7.14整合Swagger3.0的详细步骤及容易踩坑的地方

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;啥技术都喜欢捣鼓捣鼓&#xff0c;喜欢分享技术、经验、生活。 &#x1f60e;人生感悟&#xff1a;尝尽人生百味&#xff0c;方知世间冷暖。 &#x1f4d6;所属专栏&#xff1a;Sp…...

题解:ABC321D - Set Menu

题解&#xff1a;ABC321D - Set Menu 题目 链接&#xff1a;Atcoder。 链接&#xff1a;洛谷。 难度 算法难度&#xff1a;B。 思维难度&#xff1a;C。 调码难度&#xff1a;B。 综合评价&#xff1a;见洛谷链接。 算法 枚举二分查找。 思路 先对b升序排序&#x…...

什么是Progressive Web App(PWA)?它们有哪些特点?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 渐进式Web App简介⭐ PWAs的主要特点⭐ 总结⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...

基于鸿蒙(HarmonyOS5)的打车小程序

1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...

从实验室到产业:IndexTTS 在六大核心场景的落地实践

一、内容创作&#xff1a;重构数字内容生产范式 在短视频创作领域&#xff0c;IndexTTS 的语音克隆技术彻底改变了配音流程。B 站 UP 主通过 5 秒参考音频即可克隆出郭老师音色&#xff0c;生成的 “各位吴彦祖们大家好” 语音相似度达 97%&#xff0c;单条视频播放量突破百万…...

2.2.2 ASPICE的需求分析

ASPICE的需求分析是汽车软件开发过程中至关重要的一环&#xff0c;它涉及到对需求进行详细分析、验证和确认&#xff0c;以确保软件产品能够满足客户和用户的需求。在ASPICE中&#xff0c;需求分析的关键步骤包括&#xff1a; 需求细化&#xff1a;将从需求收集阶段获得的高层需…...