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…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
32单片机——基本定时器
STM32F103有众多的定时器,其中包括2个基本定时器(TIM6和TIM7)、4个通用定时器(TIM2~TIM5)、2个高级控制定时器(TIM1和TIM8),这些定时器彼此完全独立,不共享任何资源 1、定…...
[USACO23FEB] Bakery S
题目描述 Bessie 开了一家面包店! 在她的面包店里,Bessie 有一个烤箱,可以在 t C t_C tC 的时间内生产一块饼干或在 t M t_M tM 单位时间内生产一块松糕。 ( 1 ≤ t C , t M ≤ 10 9 ) (1 \le t_C,t_M \le 10^9) (1≤tC,tM≤109)。由于空间…...
