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…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
