vue配置sql规则
vue配置sql规则
- 实现效果
- 组件完整代码
- 父组件
前端页面实现动态配置sql条件,将JSON结构给到后端,后端进行sql组装。
这里涉及的分组后端在组装时用括号将这块规则括起来就行,分组的sql连接符(并且/或者)取组里的第一个。
实现效果
组件完整代码
<!-- conditionGroup.vue -->
<template><div :class="{ marginClass: onlyOne }" v-if="reDraw"><div class="condition-header" v-if="onlyOne"><div class="group-button"><el-tooltip content="分组"><iclass="el-icon-folder-opened"icon-class="group":style="{width: groupBtnSize + 'px',height: groupBtnSize + 'px',color: '#1890ff',cursor: 'pointer',}"@click.stop="_addGroup"></i></el-tooltip></div></div><divv-for="(item, index) in conditionList":style="{ 'flex-direction': 'column' }"><div:style="{display: 'flex','flex-direction': 'row','align-items': 'center',}"v-if="!item.groups"><div:style="{display: 'flex','flex-direction': 'row','align-items': 'center',}"><iclass="el-icon-circle-plus-outline color-success font-title-large"style="cursor: pointer"@click="_addItem(item)"></i><iclass="el-icon-circle-close color-danger font-title-large"style="cursor: pointer; margin-left: 5px"@click="_delItem(item)"></i><el-checkboxstyle="padding: 0 10px 0 10px"v-model="item.checked"></el-checkbox><template v-if="floor > 1 && (!item.line || item.line.length == 0)"><div:style="{width: gradWidth + leftWidth * (floor - item.floor - 1) + 'px',height: '42px',}"></div></template><template v-else v-for="(n, li) in item.line"><div:style="{width:li == item.line.length - 1? gradWidth + leftWidth * (floor - item.floor) + 'px': leftWidth + 'px',height: '42px',background: getFloorColor(li + 1),}":class="{'group-left': n.l == 2,'group-top-left': n.l == 4,'group-bottom-left': n.l == 5,}"><el-tooltip :content="'点击取消所在分组'" v-if="n.l == 4"><iclass="el-icon-folder-opened"icon-class="group":style="{width: groupBtnSize + 'px',height: groupBtnSize + 'px',color: '#1890ff',cursor: 'pointer',}"@click="_delGroup(item, n.p)"></i></el-tooltip></div></template></div><div style="position: relative"><divv-if="item.header":style="{position: 'absolute',top: '-23px',left: '0px',display: 'flex','flex-direction': 'row',width: '100%',}"><div class="condition-header" style="margin-left: 20px">并且/或者</div></div><el-selectv-model="item.operate"style="width: 120px; padding: 5px 0 5px 1px"size="small":disabled="item.header"><el-optionv-for="ot in [{ key: '并且', val: 'and' },{ key: '或者', val: 'or' },]":key="ot.val":label="ot.key":value="ot.val"></el-option></el-select></div><div style="position: relative"><divv-if="item.header":style="{position: 'absolute',top: '-23px',left: '0px',display: 'flex','flex-direction': 'row',width: '100%',}"><div class="condition-header" style="margin-left: 20px">字段</div></div><el-selectv-model="item.field"style="width: 200px; margin-left: 10px; padding: 5px 0 5px 0px"size="small"@change="(item.value = ''), (item.condition = '')"><el-optionv-for="ot in keyList":key="ot.val":label="ot.key":value="ot.val"></el-option></el-select></div><div style="position: relative"><divv-if="item.header":style="{position: 'absolute',top: '-23px',left: '0px',display: 'flex','flex-direction': 'row',width: '100%',}"><div class="condition-header" style="margin-left: 20px">运算符</div></div><el-selectv-model="item.condition"v-if="conditionMap && conditionMap[item.field]"style="width: 120px; margin-left: 10px; padding: 5px 0 5px 0px"size="small"><el-optionv-for="ot in conditionMap[item.field]":key="ot.val":label="ot.key":value="ot.val"></el-option></el-select><el-selectv-model="item.condition"v-elsestyle="width: 120px; margin-left: 10px; padding: 5px 0 5px 0px"size="small"><el-optionv-for="ot in conditionSelect":key="ot.val":label="ot.key":value="ot.val"></el-option></el-select></div><div style="position: relative"><divv-if="item.header":style="{position: 'absolute',top: '-23px',left: '0px',display: 'flex','flex-direction': 'row',width: '100%',}"><div class="condition-header" style="margin-left: 20px">值</div></div><!-- 值类型:下拉选项、日期、时间、小数、整数、文本框 --><el-selectv-model="item.value"v-if="valList &&valList[item.field] &&valList[item.field].dom == 'select'"style="width: 400px; margin-left: 10px; padding: 5px 0 5px 0px"size="small"placeholder="请选择"><el-optionv-for="ot in valList[item.field].data":key="ot.dictValue":label="ot.dictLabel":value="ot.dictValue"></el-option></el-select><el-date-pickerv-else-if="valList &&valList[item.field] &&valList[item.field].dom == 'date'"size="small"v-model="item.value"type="date"placeholder="请选择日期"style="width: 400px;margin-left: 10px;cursor: pointer;padding: 5px 0 5px 0px;":editable="false"format="yyyy-MM-dd"value-format="yyyy-MM-dd"></el-date-picker><el-date-pickerv-else-if="valList &&valList[item.field] &&valList[item.field].dom == 'dateTime'"size="small"v-model="item.value"type="datetime"placeholder="请选择时间"style="width: 400px;margin-left: 10px;cursor: pointer;padding: 5px 0 5px 0px;":editable="false"format="yyyy-MM-dd HH:mm:ss"value-format="yyyy-MM-dd HH:mm:ss"></el-date-picker><el-inputv-else-if="valList &&valList[item.field] &&valList[item.field].dom == 'decimals'"v-model="item.value"style="width: 400px; margin-left: 10px; padding: 5px 0 5px 0px"placeholder="请输入(支持小数)"clearabletype="number"size="small"oninput="if(value < 0 || value == '' || value == null) value='';"/><!-- if(!/^\d+(\.\d{1,2})?$/.test(value)) value=value.match(/[\d]+(\.\d{0,2})?/)?.[0]; 两位 --><el-inputv-else-if="valList &&valList[item.field] &&valList[item.field].dom == 'integer'"v-model="item.value"style="width: 400px; margin-left: 10px; padding: 5px 0 5px 0px"placeholder="请输入(整数)"clearabletype="number":min="1"size="small"oninput="if(value.includes('.')) value=value.replace(/\./g, ''); if(value < 0 || value == '' || value == null) value=''; if(!/^\d+$/.test(value)) value=value.replace(/\D/g,'');"/><el-inputv-elsev-model="item.value"style="width: 400px; margin-left: 10px; padding: 5px 0 5px 0px"placeholder="请输入"clearablesize="small"/></div></div><conditionGroup:conditionList="item.groups"v-if="item.groups && item.groups.length > 0":only-one="false":parentData="parentData":floor="floor":borderColor="borderColor":key-list="keyList":val-list="valList":condition-map="conditionMap"></conditionGroup></div><!-- <el-buttonv-if="onlyOne"size="small"style="margin-top: 10px; cursor: pointer"@click="_addChild">添加规则</el-button> --></div>
</template><script>
const condition = {id: 1,index: 1,condition: "",operate: "and",field: "",value: "",checked: false,header: true,pid: -1,floor: 1,
};const gradWidth = 20;
const leftWidth = 20;
const groupBtnSize = 20;
const alpha = 0.2;const initData = [Object.assign({}, condition)];export default {name: "conditionGroup",components: {},props: {onlyOne: {type: Boolean,default: () => true,},floor: {type: Number,default: () => 1,},conditionList: {type: Array,default: () => initData,},keyList: {type: Array,default: () => [],},conditionMap: {type: Object,default: () => {},},valList: {type: Object,default: () => {},},parentData: {type: Object,default: () => {},},gradWidth: {type: Number,default: () => gradWidth,},leftWidth: {type: Number,default: () => leftWidth,},groupBtnSize: {type: Number,default: () => groupBtnSize,},borderColor: {type: Array,default: () => ["rgba(24, 124, 255, " + alpha + ")"],},},data() {return {plotList: [],loading: false,reDraw: true,addGroupIndex: 0,conditionSelect: [{ key: "等于", val: "eq" },{ key: "不等于", val: "notEq" },{ key: "大于", val: "gt" },{ key: "小于", val: "lt" },{ key: "大于等于", val: "gtq" },{ key: "小于等于", val: "ltq" },{ key: "包含", val: "like" },{ key: "不包含", val: "notLike" },// { key: "加", val: "add" },// { key: "减", val: "subtract" },// { key: "乘", val: "multiply" },// { key: "除", val: "divide" },],};},computed: {sidebar() {return this.$store.state.app.sidebar.opened;},},watch: {conditionList(val, oldVal) {this.$emit("input", val);while (this.borderColor.length < this.floor) {var _color = this.randomHexColor();while (this.borderColor.indexOf(_color) != -1) {_color = this.randomHexColor();}this.borderColor.push(_color);}this.reDraw = false;this.$nextTick(() => {this.reDraw = true;});},sidebar(val) {},},methods: {findChecked(list, arrParam) {var arr = arrParam || new Array();for (var i = 0; i < list.length; i++) {var o = list[i];if (o.groups && o.groups.length > 0) {this.findChecked(o.groups, arr);} else {if (o.checked) {arr.push(o);}}}return arr;},removeNode(list, targetList) {for (var i = 0; i < list.length; i++) {var o = list[i];for (var tid of targetList) {if (o.id == tid) {list.splice(i--, 1);}}}},findParentGroups(list, pid, retParam) {var ret = null || retParam;for (var i = 0; i < list.length; i++) {var o = list[i];if (o.groups && o.groups.length > 0) {if (o.id == pid) {ret = o;} else {ret = this.findParentGroups(o.groups, pid, ret);}}}return ret;},_addGroup() {this.addGroup(this.parentData.conditionList, this.parentData);},_delGroup(item, groupId) {this.delGroup(groupId, this.parentData.conditionList, this.parentData);},_addChild() {this.addChild(this.parentData.conditionList);},_delItem(item) {this.delItem(this.conditionList,item,this.parentData.conditionList,this.parentData);},_addItem(item) {this.addItem(this.conditionList,item.index,this.parentData.conditionList,this.parentData);},addItem(groups, index, conditionList, parentThis) {var newItem = Object.assign({}, condition, {id: new Date().getTime(),index: index + 1,floor: groups[0].floor,pid: groups[0].pid,});groups.splice(index, 0, newItem);parentThis.floor = this.refreshData(conditionList);},addChild(conditionList) {var newItem = Object.assign({}, condition, {id: new Date().getTime(),index: conditionList.length + 1,floor: 1,pid: -1,});newItem.header = false;conditionList.splice(conditionList.length, 0, newItem);},delItem(groups, item, conditionList, parentThis) {var sum = this.countItem(conditionList);if (sum <= 1) {return;}groups.splice(item.index - 1, 1);var currentGroups = this.findParentGroups(conditionList, groups[0].pid);if (currentGroups) {var parentGroups = this.findParentGroups(conditionList,currentGroups.pid);if (currentGroups.groups.length == 1) {var ag = JSON.parse(JSON.stringify(currentGroups.groups[0]));ag.index = currentGroups.index;ag.id = currentGroups.id;ag.pid = parentGroups ? parentGroups.id : -1;ag.floor = currentGroups.floor;if (ag.groups) {ag.groups.forEach((o, index) => {o.pid = ag.id;o.floor = ag.floor + 1;o.index = index + 1;});}if (parentGroups) {var _groups = this.findParentGroups(conditionList, parentGroups.id);_groups.groups.splice(currentGroups.index - 1, 1, ag);} else {conditionList.splice(currentGroups.index - 1, 1, ag);}}}if (conditionList.length == 1 && conditionList[0].groups) {var newList = JSON.parse(JSON.stringify(conditionList[0].groups));conditionList.splice(0, 1);for (var nl of newList) {nl.pid = -1;nl.floor = 1;conditionList.push(nl);}}parentThis.floor = this.refreshData(conditionList);},addGroup(conditionList, parentThis) {var checkedList = this.findChecked(conditionList);if (!checkedList || checkedList.length <= 1) {this.$message({message: "至少选择2个查询条目",type: "warning",duration: 1000,});return;}var checkNodes = [];for (var item of checkedList) {if (item.pid == -1) {this.uniquePush(checkNodes, item);} else {var pNode = this.getRealParent(conditionList, item, checkedList);if (pNode) {this.uniquePush(checkNodes, pNode);}}}var _tmpRoot = [];for (var ck of checkNodes) {var _tmp = this.findParentGroups(conditionList, ck.pid);if (_tmp) {this.uniquePush(_tmpRoot, _tmp);}}var allSelectCount = 0;var floorCount = [];for (var cn of checkNodes) {if (cn.groups) {allSelectCount += this.countItem(cn.groups);} else {allSelectCount++;}if (floorCount.indexOf(cn.floor) == -1) {floorCount.push(cn.floor);}}var rootGroup = this.findParentGroups(conditionList, checkNodes[0].pid);if (_tmpRoot.length > 1) {rootGroup = this.findParentGroups(conditionList, rootGroup.pid);allSelectCount = 0;for (var cn of _tmpRoot) {if (cn.groups) {allSelectCount += this.countItem(cn.groups);} else {allSelectCount++;}}}var rootArray = conditionList;if (rootGroup) {rootArray = rootGroup.groups;}var allCount = this.countItem(rootArray);var currentSelectCount = checkedList.length;if (allSelectCount != currentSelectCount || floorCount.length > 1) {this.$message({message: "不能交叉分组",type: "warning",duration: 1000,});return;}if (checkNodes.length == 1 || allCount == currentSelectCount) {this.$message({message: "无效分组",type: "warning",duration: 1000,});return;}var newCheckNode = JSON.parse(JSON.stringify(checkNodes));newCheckNode.sort(function (a, b) {return a.index - b.index;});var groupId = new Date().getTime();var newGroup = {groups: newCheckNode,id: groupId,index: newCheckNode[0].index,pid: newCheckNode[0].pid,floor: newCheckNode[0].floor,};var waitRemoveNode = [];for (var o of newCheckNode) {o.floor += 1;o.pid = groupId;if (!o.groups) {o.checked = false;}waitRemoveNode.push(o.id);}if (!rootGroup) {this.removeNode(conditionList, waitRemoveNode);conditionList.splice(newCheckNode[0].index - 1, 0, newGroup);} else {var _groups = this.findParentGroups(conditionList, rootGroup.id);this.removeNode(_groups.groups, waitRemoveNode);_groups.groups.splice(newCheckNode[0].index - 1, 0, newGroup);}parentThis.floor = this.refreshData(conditionList);},delGroup(groupId, conditionList, parentThis) {var parentGroups = this.findParentGroups(conditionList, groupId);var rootGroups = this.findParentGroups(conditionList, parentGroups.pid);var waitRemoveNode = [parentGroups.id];var newList = JSON.parse(JSON.stringify(parentGroups.groups));newList.forEach((o, index) => {o.pid = parentGroups.pid;o.floor = parentGroups.floor;o.checked = false;});if (!rootGroups) {this.removeNode(conditionList, waitRemoveNode);newList.forEach((o, index) => {conditionList.splice(parentGroups.index - 1 + index, 0, o);});} else {var _groups = this.findParentGroups(conditionList, rootGroups.id);this.removeNode(_groups.groups, waitRemoveNode);newList.forEach((o, index) => {_groups.groups.splice(parentGroups.index - 1 + index, 0, o);});}parentThis.floor = this.refreshData(conditionList);},getRealParent(allItems, item, checkedList) {var parentGroups = this.findParentGroups(allItems, item.pid);var ret = parentGroups;if (parentGroups) {var childCount = this.countItem(parentGroups.groups);var realChildCount = 0;for (var cl of checkedList) {if (cl.pid == parentGroups.id) {realChildCount++;} else {var pg = this.findParentGroups(allItems, cl.pid);if (pg) {if (pg.pid == parentGroups.id) {realChildCount++;} else {while (pg && pg.pid != parentGroups.id) {pg = this.findParentGroups(allItems, pg.pid);if (pg && pg.pid == parentGroups.id) {realChildCount++;}}}}}}if (childCount == realChildCount) {var _tmp = this.getRealParent(allItems, parentGroups, checkedList);if (_tmp) {ret = _tmp;}} else {ret = item;}}return ret;},reIndex(list, i, arr) {for (var index = 0; index < list.length; index++) {var o = list[index];if (arr.indexOf(i) == -1) {arr.push(i);}if (o.groups && o.groups.length > 0) {o.index = index + 1;o.floor = i;if (i == 1) {o.pid = -1;}this.reIndex(o.groups, i + 1, arr);} else {o.index = index + 1;o.floor = i;o.checked = false;if (i == 1) {o.pid = -1;}}}},drawLineGroup(list, currentFloor, retList) {for (var index = 0; index < list.length; index++) {var o = list[index];if (o.groups && o.groups.length > 0) {this.drawLineGroup(o.groups, currentFloor + 1, retList);} else {o.line = new Array(currentFloor - 1);if (retList.length == 0) {o.header = true;} else {o.header = false;}for (var _k = 0; _k < o.line.length; _k++) {o.line[_k] = { l: 2, p: -1 };}retList.push(o);}}},refreshData(list) {var floorCountArr = [];this.reIndex(list, 1, floorCountArr);var maxFloor = floorCountArr.length;var ret = new Array();this.drawLineGroup(list, 1, ret);for (var item of ret) {var parentGroup = this.findParentGroups(list, item.pid);if (item.pid != -1) {if (item.index == 1) {var node = { l: 4, p: parentGroup.id };item.line[item.line.length - 1] = node;} else if (item.index == parentGroup.groups.length) {var node = { l: 5, p: -1 };item.line[item.line.length - 1] = node;}}if (parentGroup) {var parentIndex = parentGroup.index;var parentLength = parentGroup.groups.length;var i = 2;var currentParentGroup = this.findParentGroups(list, parentGroup.pid);while (currentParentGroup) {if (i != 2) {parentGroup = JSON.parse(JSON.stringify(currentParentGroup));currentParentGroup = this.findParentGroups(list, parentGroup.pid);}if (currentParentGroup) {if (parentGroup.index == 1 &&item.index == 1 &&parentIndex == 1) {var node = { l: 4, p: currentParentGroup.id };item.line[item.line.length - i] = node;} else if (parentGroup.index == currentParentGroup.groups.length &&item.index == parentLength) {item.line[item.line.length - i] = { l: 5, p: -1 };} else {break;}i++;}}}}return maxFloor;},countItem(list, i) {var sum = i || 0;for (var index = 0; index < list.length; index++) {var o = list[index];if (o.groups && o.groups.length > 0) {sum += this.countItem(o.groups, i);} else {sum++;}}return sum;},uniquePush(arr, item) {var exist = false;for (var o of arr) {if (o.id == item.id) {exist = true;}}if (!exist) {arr.push(item);}},randomHexColor() {// return '#' + ('00000' + (Math.random() * 0x1000000 << 0).toString(16)).substr(-6);return this.randomColor(alpha);},randomColor(alpha) {alpha =alpha == undefined ? ((Math.random() * 10) / 10).toFixed(1) : alpha;alpha = Number(alpha);if (isNaN(alpha)) alpha = 1;var col = "rgba(";for (var i = 0; i < 3; i++) {col += parseInt(Math.random() * 256) + ",";}col += alpha + ")";return col;},getFloorColor(floor) {return this.borderColor[floor - 1];},},created() {if (typeof this.conditionList[0].field == "string" &&typeof this.conditionList[0].header == "undefined") {this.conditionList[0].header = true;}this.$nextTick(() => {});},
};
</script><style type="text/css">
/* :root 是CSS中的一个伪类选择器,它代表文档的根元素。在HTML中,根元素通常是<html>标签。使用:root选择器允许开发者为整个文档定义全局样式变量
--borderWidth:这是一个自定义的CSS变量
使用var(--variableName)语法进行引用 */:root {--borderWidth: 1px;--borderColor: rgba(158, 158, 158, 1);
}table {border-collapse: collapse;
}.marginClass {margin-bottom: 10px;
}.condition-header {font-weight: 600;display: flex;flex-direction: row;
}.group-button {margin-left: 47px;display: flex;flex-direction: row;align-items: center;
}.group-left {border-left: var(--borderWidth) solid var(--borderColor);
}
.group-top-left {border-top: var(--borderWidth) solid var(--borderColor);border-left: var(--borderWidth) solid var(--borderColor);
}
.group-bottom-left {border-bottom: var(--borderWidth) solid var(--borderColor);border-left: var(--borderWidth) solid var(--borderColor);
}
</style>
父组件
<template><!-- :parentData="this"传递父组件实例,子组件使用属性或方法时this.parentData.属性/方法名 -->
<conditionGroup:floor="floor":conditionList="conditionList":parentData="this":key-list="keyOptions":condition-map="conditionOptions":val-list="valueOptions"></conditionGroup>
</template><sctipt>
export default {data() {conditionList: [Object.assign({}, condition)], // 默认页面显示一条空规则floor: 1, // 树深度keyOptions: [], // 字段选项conditionOptions: {}, // 特殊运算符(像下拉框的只有 等于 运算符等)valueOptions: {}, //下拉框类型的数据},// 一些关键方法methods: {// 递归找结构深度getFloorth(groups) {let deepestFloor = 0;let deepestGroup = null;function searchGroup(group) {// 找到比当前deepestFloor值大,则重新赋值deepestFloor,并将当前对象记录if (group.floor > deepestFloor) {deepestFloor = group.floor;deepestGroup = group;}if (group.groups && group.groups.length > 0) {group.groups.forEach(searchGroup);}}groups.forEach(searchGroup);return deepestGroup ? deepestGroup.floor : 1;},// 提交时校验规则是否有未填/选项traverse(data) {for (let item of data) {// 这里需要判空的参数field、condition、value,如果有为空则提示,不可保存if (!item.groups &&(!item?.field || !item?.condition || !item?.value)) {this.$message.warning("请完善规则条件配置");// 当校验失败时抛出错误,`中断当前执行的代码块`,并被上层catch语句捕获throw new Error("字段验证失败"); } else if (item.groups) {this.traverse(item.groups);}}return true;},// 根据其他下拉框,查询动态字段项selectChange(obj) {let { name, val } = obj;if (name === "equipType") {this.keyOptions = [];this.valueOptions = {};this.conditionOptions = {};let keyOptionsDict = val + "_column"; // keyOptionsDict 为val和_column拼接的字典名称去过滤对应字典项let options = this.$options.filters["dictOption"]({dictName: keyOptionsDict,});// 有过滤到字段项,给字段项字段push数据(字段key和val)if (options.length) {options.forEach((item) => {// item.dictValue用#拼接的三个参数,如heat_status_code#select#heat_status(第一个为规则字段键、第二个为值类型、第三个为字典名)let parts = item.dictValue.split("#");this.keyOptions.push({key: item.dictLabel,val: parts[0],});if (parts[1] === "select") {// 如果是select下拉框,则拼接下拉框值数据项(我们这块都是匹配的字典查询,可拓展为接口查询)this.valueOptions[parts[0]] = {dom: parts[1],data: this.$options.filters["dictOption"]({dictName: parts[2],}),};// 若是下拉框,处理运算符this.conditionOptions[parts[0]] = [{ key: "等于", val: "eq" }];} else {// 其他字段直接给dom属性this.valueOptions[parts[0]] = { dom: parts[1] };}});} else {this.conditionList = [Object.assign({}, condition)];this.keyOptions = [];this.conditionOptions = {};}}},// 若需要前端组装给后端可使用下面方法(我这里是直接给的JSON,前端不进行组装)generateConditionString(conditionList) {let result = "";if (conditionList.length === 0) return result;const generateSubConditions = (conditions) => {return conditions.map((condition, index) => {if (condition.groups && condition.groups.length > 0) {let connectSym = condition.groups[0].operate;return index === 0? `(${generateSubConditions(condition.groups)})`: ` ${connectSym} (${generateSubConditions(condition.groups)})`;}let value = condition.value;if (typeof value === "string") {if (condition.condition === "like" ||condition.condition === "notLike") {value = `'%${value.replace(/'/g, "")}%'`;} else {value = `'${value.replace(/'/g, "''")}'`;}}if (!condition?.field ||!condition?.condition ||!condition?.value) {this.$message.warning("请完善规则条件配置");return result;}const conditionString = `${condition.field} ${this.operators[condition.condition]} ${value}`;const logicOperator = ` ${condition.operate} `;return `${index === 0 ? "" : logicOperator}${conditionString}`;}).join("");};result = generateSubConditions(conditionList);this.querystring = result;return result;},}
}
</script>
参考文章
相关文章:

vue配置sql规则
vue配置sql规则 实现效果组件完整代码父组件 前端页面实现动态配置sql条件,将JSON结构给到后端,后端进行sql组装。 这里涉及的分组后端在组装时用括号将这块规则括起来就行,分组的sql连接符(并且/或者)取组里的第一个。…...

面试官:Redis执行lua脚本能保证原子性吗?
核心问题 Redis执行lua脚本是否能确保原子性? 面试经历 面试者在面试中自信回答Redis执行lua脚本能保证原子性,但未能深入解释原因。 原子性概念 原子性:一个事务的所有命令要么全部执行成功,要么全部执行失败。 Redis官方说…...

基于Chrome扩展的浏览器可信事件与网页离线PDF导出
基于Chrome扩展的浏览器可信事件与网页离线PDF导出 Chrome扩展是一种可以在浏览器中添加新功能和修改浏览器行为的软件程序,我们可以基于Manifest规范的API实现对于浏览器和Web页面在一定程度上的修改,例如广告拦截、代理控制等。Chrome DevTools Proto…...

马拉松报名小程序的设计
管理员账户功能包括:系统首页,个人中心,用户管理,赛事信息管理,赛事报名管理,活动商城管理,留言板管理,系统管理 微信端账号功能包括:系统首页,赛事信息&…...

python使用pywebview集成vue3和element-plus开发桌面系统框架
随着web技术越来越成熟,就连QQ的windows客户端都用web技术来开发,所以在未来,web技术来开发windows桌面软件也会越来越多,所以在此发展驱动之下,将最近流程的python与web技术相结合,使用vue3和element-plus…...

C++线程的使用
C11之前,C语言没有对并发编程提供语言级别的支持,这使得我们在编写可移植的并发程序时,存在诸多的不便。现在C11中增加了线程以及线程相关的类,很方便地支持了并发编程,使得编写的多线程程序的可移植性得到了很大的提高…...

算法库应用--寻找最长麦穗
学习贺利坚老师算法库 数据结构例程——串的顺序存储应用_使用顺序串存储身份证号-CSDN博客 本人详细解析博客 串的顺序存储的应用实例二_串的顺序存储应用-CSDN博客 版本更新日志 V1.0: 在原有的基础上, 进行优化名字, 并且有了相应的算法库作为支撑, 我使用了for循环来代替老…...

ython 使用 cx_Freeze 打包,不想要打包文件中能直接看到依赖的代码,如何处理
背景:因为使用 cx_Freeze 打包时,添加需要依赖的文件 cx_Freeze 是一个用于将 Python 程序打包成独立可执行文件的工具,支持多个平台。当你需要打包包含多个 .py 文件的项目时,你可以通过编写一个 setup.py 文件来指定哪些模块应…...

某DingTalk企典 - Token
⚠️前言⚠️ 本文仅用于学术交流。 学习探讨逆向知识,欢迎私信共享学习心得。 如有侵权,联系博主删除。 请勿商用,否则后果自负。 网址 aHR0cHM6Ly9kaW5ndGFsay5jb20vcWlkaWFuLw 浅聊一下 没毛病,就这字段,有效期…...

手写一个类似@RequestParam的注解(用来接收请求体的参数)
一、本文解决的痛点 按照大众认为的开发规范,一般post类型的请求参数应该传在请求body里面。但是我们有些post接口只需要传入一个字段,我们接受这种参数就得像下面这样单独创建一个类,类中再添加要传入的基本类型字段,配合Reques…...

【遇坑笔记】Node.js 开发环境与配置 Visual Studio Code
【遇坑笔记】Node.js 开发环境与配置 Visual Studio Code 前言node.js开发环境配置解决pnpm 不是内部或外部命令的问题(pnpm安装教程)解决 pnpm : 无法加载文件 C:\Program Files\nodejs\pnpm.ps1,因为在此系统上禁止运行脚本。 vscode 插件开…...

【ajax实战07】文章筛选功能
本文章目标:根据筛选条件,获取匹配数据展示 本章**“查询参数对象”指的是,要“获取文章列表”功能**中服务器接口要求配置的对象 实现步骤如下: 一:设置频道列表数据 二:监听筛选条件改变,…...

promise.all和promise.race的区别
Promise.all和Promise.race是JavaScript中Promise API的两个重要方法,它们在处理多个Promise对象时表现出不同的行为。以下是它们之间的主要区别: 1. 功能和行为 Promise.all: 功能:接收一个包含多个Promise的数组&#x…...

Python爬取豆瓣电影+数据可视化,爬虫教程!
1. 爬取数据 1.1 导入以下模块 import os import re import time import requests from bs4 import BeautifulSoup from fake_useragent import UserAgent from openpyxl import Workbook, load_workbook1.2 获取每页电影链接 def getonepagelist(url,headers):try:r reque…...

初阶数据结构二叉树练习系列(1)
这个系列的文章将带大家一起刷题,并且总结思路 温馨提示:本篇文章里的练习题仅适合刚学完二叉树的小白使用 相同的树 思路 情况分析:第一种情况:两棵树都为空 → 返回true 第二种情况&am…...

【selenium 】操作元素
操作元素 元素操作鼠标操作键盘操作 元素操作 元素操作示例清空输入框clear()deiver.find_element_by_id(“username”).clear()输入文字send_keys()deiver.find_element_by_id(“username”).send_keys(‘zs’)元素点击 click()deiver.find_element_by_id(“login”).click()…...

【MySQL】事务实现原理
目录 事务 如何使用 ACID 原子性(Atomicity) 原子性实现原理 持久性(Durability) 持久性实现原理 隔离性 隔离级别 读未提交 读已提交 可重复读 串行化 隔离级别原理 锁 共享锁&独占锁 意向锁 索引记录锁 间隙锁 临键锁 插入意向锁 自增锁 MVCC 实现…...

面向物联网行业的异常监控追踪技术解决方案:技术革新与运维保障
在现代高度数字化和互联的环境中,物联网技术已经深入到我们生活的方方面面。特别是在家庭和工业环境中,物联网系列通讯作为连接各类设备的关键枢纽,其稳定性和可靠性显得尤为重要。本文将介绍一种创新的监控系统,旨在实时跟踪和分…...

守护厨房空气:全面排查与修复油烟净化器跳闸问题
我最近分析了餐饮市场的油烟净化器等产品报告,解决了餐饮业厨房油腻的难题,更加方便了在餐饮业和商业场所有需求的小伙伴们。 在繁忙的餐饮业厨房中,油烟净化器是确保空气清新和环境卫生的关键设备。然而,油烟净化器在长时间高强…...

【微服务网关——https与http2代理实现】
1.https与http2代理 1.1 重新认识https与http2 https是http安全版本http2是一种传输协议两者并没有本质联系 1.1.1 https与http的区别 HTTP(超文本传输协议)和 HTTPS(安全超文本传输协议)是用于在网络上交换数据的两种协议。H…...

mssql查询历史执行过的语句日志
SELECT deqs.creation_time,dest.text AS [SQL Text],deqs.execution_count,deqs.total_elapsed_time,deqs.total_worker_time FROM sys.dm_exec_query_stats AS deqs CROSS APPLY sys.dm_exec_sql_text(deqs.sql_handle) AS dest--where dest.text like %这个是我的条件&#…...

【LeetCode】每日一题:买卖股票的最佳时机 II
给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。 在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。 返回 你能获得的 最大 利润 。 AC代码 水…...

【TS】TypeScript 联合类型详解:解锁更灵活的类型系统
🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 💫个人格言: "如无必要,勿增实体" 文章目录 TypeScript 联合类型详解:解锁更灵活的类型系统一、联合类型的定义二…...

kali改回官方源后更新失败
官方源: deb http://http.kali.org/kali kali-rolling main non-free contrib deb-src http://http.kali.org/kali kali-rolling main non-free contrib在文件 /etc/cat/sources.list中将官方源修改为: deb http://http.kali.org/kali kali-rolling ma…...

Mysql 左关联(LEFT JOIN)
在左关联(LEFT JOIN)操作中,关于大表和小表的连接顺序,通常建议将小表放在前面,大表放在后面。这种安排方式有助于提高查询效率,原因如下: 扫描效率:在SQL查询中,尤其是…...

[笔记]小米CyberDog机器狗仿真调试记录
从官方github的所有源码库来看,所有的source命令只有两条,执行它以配置环境变量: source /opt/ros/galactic/setup.bash source /home/cyberdog_ws/install/setup.bash 如果运行脚本之后gazebo正常启动及机器狗模型在悬空状态,问…...

第十四届蓝桥杯省赛C++B组G题【子串简写】题解(AC)
题目大意 给定字符串 s s s,字符 a , b a, b a,b,问字符串 s s s 中有多少个 a a a 开头 b b b 结尾的子串。 解题思路 20pts 使用二重循环枚举左端点和右端点,判断是否为 a a a 开头 b b b 结尾的字符串,是则答案加一…...

实现Java Web应用的高性能负载均衡方案
实现Java Web应用的高性能负载均衡方案 大家好,我是微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 在高并发的网络环境中,负载均衡是确保Web应用程序高性能和可靠性的关键策略之一。本文将探讨如何…...

医学预测模型web APP的制作建议
医学预测模型web APP的制作建议 医学预测模型类web APP定义为承载预测模型而便利预测模型临床应用的可视化客户端。 医学预测模型类web APP的功能是衔接预测模型和临床实践,让用户正确地,方便地使用预测模型并恰当地理解预测模型的结果,在此…...

gitlab每日备份以及restore
gitlab服务有非常简洁的每日备份命令, 从production的gitlab的每日备份中restore到backup环境也非常方便。 一、Production gitlab每日备份 1. Production gitlab环境上编写脚本 cat /root/gitlab_bak.shgitlab-rake gitlab:backup:create > /var/opt/gitl…...