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

基于Vue的验证码实现

一、验证码核心实现

        创建slide-verify.vue,代码如下:

<template><divclass="slide-verify":style="{ width: w + 'px' }"id="slideVerify"onselectstart="return false;"><!-- 图片加载遮蔽罩 --><div :class="{ 'slider-verify-loading': loadBlock }"></div><canvas :width="w" :height="h" ref="canvas"></canvas><div v-if="show" @click="refresh" class="slide-verify-refresh-icon"></div><canvas:width="w":height="h"ref="block"class="slide-verify-block"></canvas><!-- container --><divclass="slide-verify-slider":class="{'container-active': containerActive,'container-success': containerSuccess,'container-fail': containerFail}"><div class="slide-verify-slider-mask" :style="{ width: sliderMaskWidth }"><!-- slider --><div@mousedown="sliderDown"@touchstart="touchStartEvent"@touchmove="handleMoveEvent($event, 'touch')"@touchend="handleMoveEndEvent($event, 'touch')"class="slide-verify-slider-mask-item":style="{ left: sliderLeft }"><div class="slide-verify-slider-mask-item-icon"></div></div></div><span class="slide-verify-slider-text">{{ sliderText }}</span></div></div>
</template>
<script>
const PI = Math.PI;function sum(x, y) {return x + y;
}function square(x) {return x * x;
}
export default {name: "SlideVerify",props: {// block lengthl: {type: Number,default: 42},// block radiusr: {type: Number,default: 10},// canvas widthw: {type: Number,default: 310},// canvas heighth: {type: Number,default: 155},sliderText: {type: String,default: "Slide filled right"},accuracy: {type: Number,default: 5 // 若为 -1 则不进行机器判断},show: {type: Boolean,default: true},imgs: {type: Array,default: () => []}},data() {return {containerActive: false, // container active classcontainerSuccess: false, // container success classcontainerFail: false, // container fail classcanvasCtx: null,blockCtx: null,block: null,block_x: undefined, // container random positionblock_y: undefined,L: this.l + this.r * 2 + 3, // block real lengthimg: undefined,originX: undefined,originY: undefined,isMouseDown: false,trail: [],sliderLeft: 0, // block right offsetsliderMaskWidth: 0, // mask width,success: false, // Bug Fixes 修复了验证成功后还能滑动loadBlock: true, // Features 图片加载提示,防止图片没加载完就开始验证timestamp: null};},mounted() {this.init();},methods: {init() {this.initDom();this.initImg();this.bindEvents();},initDom() {this.block = this.$refs.block;this.canvasCtx = this.$refs.canvas.getContext("2d");this.blockCtx = this.block.getContext("2d");},initImg() {const img = this.createImg(() => {// 图片加载完关闭遮蔽罩this.loadBlock = false;this.drawBlock();this.canvasCtx.drawImage(img, 0, 0, this.w, this.h);this.blockCtx.drawImage(img, 0, 0, this.w, this.h);let { block_x: x, block_y: y, r, L } = this;let _y = y - r * 2 - 1;let ImageData = this.blockCtx.getImageData(x, _y, L, L);this.block.width = L;this.blockCtx.putImageData(ImageData, 0, _y);});this.img = img;},drawBlock() {this.block_x = this.getRandomNumberByRange(this.L + 10,this.w - (this.L + 10));this.block_y = this.getRandomNumberByRange(10 + this.r * 2,this.h - (this.L + 10));this.draw(this.canvasCtx, this.block_x, this.block_y, "fill");this.draw(this.blockCtx, this.block_x, this.block_y, "clip");},draw(ctx, x, y, operation) {let { l, r } = this;ctx.beginPath();ctx.moveTo(x, y);ctx.arc(x + l / 2, y - r + 2, r, 0.72 * PI, 2.26 * PI);ctx.lineTo(x + l, y);ctx.arc(x + l + r - 2, y + l / 2, r, 1.21 * PI, 2.78 * PI);ctx.lineTo(x + l, y + l);ctx.lineTo(x, y + l);ctx.arc(x + r - 2, y + l / 2, r + 0.4, 2.76 * PI, 1.24 * PI, true);ctx.lineTo(x, y);ctx.lineWidth = 2;ctx.fillStyle = "rgba(255, 255, 255, 0.7)";ctx.strokeStyle = "rgba(255, 255, 255, 0.7)";ctx.stroke();ctx[operation]();// Bug Fixes 修复了火狐和ie显示问题ctx.globalCompositeOperation = "destination-over";},createImg(onload) {const img = document.createElement("img");img.crossOrigin = "Anonymous";img.onload = onload;img.onerror = () => {img.src = this.getRandomImg();};img.src = this.getRandomImg();return img;},// 随机生成img srcgetRandomImg() {// return require('../assets/img.jpg')const len = this.imgs.length;return len > 0? this.imgs[this.getRandomNumberByRange(0, len - 1)]: // "https://bing.ioliu.cn/v1/rand?w=300&h=150";"https://source.unsplash.com/300x150/?book,library";// "https://api.dujin.org/pic/fengjing";},getRandomNumberByRange(start, end) {return Math.round(Math.random() * (end - start) + start);},refresh() {this.reset();this.$emit("refresh");},sliderDown(event) {if (this.success) return;this.originX = event.clientX;this.originY = event.clientY;this.isMouseDown = true;this.timestamp = +new Date();},touchStartEvent(e) {if (this.success) return;e.preventDefault();this.originX = e.changedTouches[0].pageX;this.originY = e.changedTouches[0].pageY;this.isMouseDown = true;this.timestamp = +new Date();},bindEvents() {document.addEventListener("mousemove", this.handleMoveEvent);document.addEventListener("mouseup", this.handleMoveEndEvent);},// 处理函数抽离handleMoveEvent: throttle(function(e, type = "mouse") {if (!this.isMouseDown) return false;const moveX =type === "mouse"? e.clientX - this.originX: e.changedTouches[0].pageX - this.originX;const moveY =type === "mouse"? e.clientY - this.originY: e.changedTouches[0].pageY - this.originY;if (moveX < 0 || moveX + 38 >= this.w) return false;this.sliderLeft = moveX + "px";let blockLeft = ((this.w - 40 - 20) / (this.w - 40)) * moveX;this.block.style.left = blockLeft + "px";this.containerActive = true; // add activethis.sliderMaskWidth = moveX + "px";this.trail.push(moveY);}),handleMoveEndEvent(e, type = "mouse") {if (!this.isMouseDown) return false;this.isMouseDown = false;if ((type === "mouse" && e.clientX === this.originX) ||(type === "touch" && e.changedTouches[0].pageX === this.originX))return false;this.containerActive = false; // remove activethis.timestamp = +new Date() - this.timestamp;const { spliced, TuringTest } = this.verify();if (spliced) {if (this.accuracy === -1) {this.containerSuccess = true;this.success = true;this.$emit("success", this.timestamp);return;}if (TuringTest) {// succthis.containerSuccess = true;this.success = true;this.$emit("success", this.timestamp);} else {this.containerFail = true;this.$emit("again");}} else {this.containerFail = true;this.$emit("fail");setTimeout(() => {this.reset();}, 1000);}},verify() {const arr = this.trail; // drag y move distanceconst average = arr.reduce(sum) / arr.length; // averageconst deviations = arr.map(x => x - average); // deviation arrayconst stddev = Math.sqrt(deviations.map(square).reduce(sum) / arr.length); // standard deviationconst left = parseInt(this.block.style.left);const accuracy =this.accuracy <= 1 ? 1 : this.accuracy > 10 ? 10 : this.accuracy;return {spliced: Math.abs(left - this.block_x) <= accuracy,TuringTest: average !== stddev // equal => not person operate};},reset() {this.success = false;this.containerActive = false;this.containerSuccess = false;this.containerFail = false;this.sliderLeft = 0;this.block.style.left = 0;this.sliderMaskWidth = 0;// canvaslet { w, h } = this;this.canvasCtx.clearRect(0, 0, w, h);this.blockCtx.clearRect(0, 0, w, h);this.block.width = w;// generate imgthis.img.src = this.getRandomImg();this.$emit("fulfilled");}},destroyed() {document.removeEventListener("mousemove", this.handleMoveEvent);document.removeEventListener("mouseup", this.handleMoveEndEvent);}
};function throttle(fn,interval = 50,options = { leading: true, trailing: true }
) {const { leading, trailing, resultCallback } = options;let lastTime = 0;let timer = null;const _throttle = function(...args) {return new Promise((resolve, reject) => {const nowTime = new Date().getTime();if (!lastTime && !leading) lastTime = nowTime;const remainTime = interval - (nowTime - lastTime);if (remainTime <= 0) {if (timer) {clearTimeout(timer);timer = null;}const result = fn.apply(this, args);if (resultCallback) resultCallback(result);resolve(result);lastTime = nowTime;return;}if (trailing && !timer) {timer = setTimeout(() => {timer = null;lastTime = !leading ? 0 : new Date().getTime();const result = fn.apply(this, args);if (resultCallback) resultCallback(result);resolve(result);}, remainTime);}});};_throttle.cancel = function() {if (timer) clearTimeout(timer);timer = null;lastTime = 0;};return _throttle;
}
</script>
<style scoped>
.slide-verify {position: relative;
}/* 图片加载样式 */
.slider-verify-loading {position: absolute;top: 0;right: 0;left: 0;bottom: 0;background: rgba(255, 255, 255, 0.9);z-index: 999;animation: loading 1.5s infinite;
}@keyframes loading {0% {opacity: 0.7;}100% {opacity: 9;}
}.slide-verify-block {position: absolute;left: 0;top: 0;
}.slide-verify-refresh-icon {position: absolute;right: 0;top: 0;width: 34px;height: 34px;cursor: pointer;background: url("../assets/icon_light.png") 0 -437px;background-size: 34px 471px;
}.slide-verify-slider {position: relative;text-align: center;width: 100%;height: 40px;line-height: 40px;margin-top: 15px;background: #f7f9fa;color: #45494c;border: 1px solid #e4e7eb;
}.slide-verify-slider-mask {position: absolute;left: 0;top: 0;height: 40px;border: 0 solid #1991fa;background: #d1e9fe;
}.slide-verify-slider-mask-item {position: absolute;top: 0;left: 0;width: 40px;height: 40px;background: #fff;box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);cursor: pointer;transition: background 0.2s linear;
}.slide-verify-slider-mask-item:hover {background: #1991fa;
}.slide-verify-slider-mask-item:hover .slide-verify-slider-mask-item-icon {background-position: 0 -13px;
}.slide-verify-slider-mask-item-icon {position: absolute;top: 15px;left: 13px;width: 14px;height: 12px;background: url("../assets/icon_light.png") 0 -26px;background-size: 34px 471px;
}
.container-active .slide-verify-slider-mask-item {height: 38px;top: -1px;border: 1px solid #1991fa;
}.container-active .slide-verify-slider-mask {height: 38px;border-width: 1px;
}.container-success .slide-verify-slider-mask-item {height: 38px;top: -1px;border: 1px solid #52ccba;background-color: #52ccba !important;
}.container-success .slide-verify-slider-mask {height: 38px;border: 1px solid #52ccba;background-color: #d2f4ef;
}.container-success .slide-verify-slider-mask-item-icon {background-position: 0 0 !important;
}.container-fail .slide-verify-slider-mask-item {height: 38px;top: -1px;border: 1px solid #f57a7a;background-color: #f57a7a !important;
}.container-fail .slide-verify-slider-mask {height: 38px;border: 1px solid #f57a7a;background-color: #fce1e1;
}.container-fail .slide-verify-slider-mask-item-icon {top: 14px;background-position: 0 -82px !important;
}.container-active .slide-verify-slider-text,
.container-success .slide-verify-slider-text,
.container-fail .slide-verify-slider-text {display: none;
}
</style>

        基于slide-verify.vue创建组件,index.js代码如下:

import SlideVerify from './slide-verify.vue'const plugins = {install(Vue) {Vue.component(SlideVerify.name, SlideVerify)}
}if (typeof window !== 'undefined' && window.Vue) {window.Vue.use(SlideVerify)
}export default plugins

二、在项目中使用验证码

        在main.js中应用:

import { createApp } from 'vue'
import App from './App.vue'
// 导入验证码
import SlideVerify from './xxx/index'const vue = createApp(App)
vue.use(SlideVerify) // 在vue中使用
vue.mount('#app')

        准备验证码图片:

         其中icon_light.png图标图片如下,其他img.jpg图片可以是任意图片。

        在vue中使用验证码,App.vue代码如下:

<template><div id="app"><slide-verify ref="slideBlock" @success="onSuccess" @again="onAgain" @fulfilled="onFulfilled" @fail="onFail"@refresh="onRefresh" :slider-text="text" :imgs="imgs" :accuracy="accuracy"></slide-verify><div>{{ msg }}</div><button class="btn" @click="handleClick">在父组件点击刷新</button></div>
</template><script setup>
import img0 from './assets/img.jpg';
import img1 from './assets/img1.jpg';
import img2 from './assets/img2.jpg';
import img3 from './assets/img3.jpg';
import img4 from './assets/img4.jpg';
import img5 from './assets/img5.jpg';
import {ref} from "vue";const slideBlock = ref();
const msg = ref('');
const text = ref('向右滑动->');
const imgs = ref([img0,img1,img2,img3,img4,img5,
]);
const accuracy = ref(1); // 精确度小,可允许的误差范围小;为1时,则表示滑块要与凹槽完全重叠,才能验证成功。默认值为5const onSuccess = (times) => {console.log('验证通过');msg.value = `login success, 耗时${(times / 1000).toFixed(1)}s`;
};
const onFail = () => {console.log('验证不通过');msg.value = ''
};
const onRefresh = () => {console.log('点击了刷新小图标');msg.value = ''
};
const onFulfilled = () => {console.log('刷新成功啦!');
};
const onAgain = () => {console.log('检测到非人为操作的哦!');msg.value = 'try again';// 刷新handleClick();
};
const handleClick = () => {slideBlock.value.reset();msg.value = ''
}</script><style scoped>
#app {font-family: 'Avenir', Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;color: #2c3e50;margin-top: 60px;
}.btn {margin-top: 20px;outline: 0;border: none;padding: 8px 15px;border-radius: 5px;color: #fff;background-color: #1890ff;cursor: pointer;
}.btn:active {box-shadow: 1px 5px 0 rgba(0, 0, 0, 0.1) inset;
}
</style>

        运行项目查看:

相关文章:

基于Vue的验证码实现

一、验证码核心实现 创建slide-verify.vue&#xff0c;代码如下&#xff1a; <template><divclass"slide-verify":style"{ width: w px }"id"slideVerify"onselectstart"return false;"><!-- 图片加载遮蔽罩 -->&…...

P4【力扣217,389,496】【数据结构】【哈希表】C++版

【217】存在重复元素 给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 &#xff0c;返回 true &#xff1b;如果数组中每个元素互不相同&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3,1] 输出&#xff1a;true 示例 2&#xff1a;…...

PE文件(六)新增节-添加代码作业

一.手动新增节添加代码 1.当预备条件都满足&#xff0c;节表结尾没有相关数据时&#xff1a; 现在我们将ipmsg.exe用winhex打开&#xff0c;在节的最后新增一个节用于存放我们要增加的数据 注意&#xff1a;飞鸽的文件对齐和内存对齐是一致的 先判断节表末尾到第一个节之间…...

ICRA 2024: NVIDIA 联合多伦多大学、加州大学伯克利分校、苏黎世联邦理工学院等研究人员开发了精细操作的手术机器人

英伟达&#xff08;NVIDIA&#xff09;正与学术研究人员合作&#xff0c;研究手术机器人。 NVIDIA 联合多伦多大学、加州大学伯克利分校、苏黎世联邦理工学院和佐治亚理工学院的研究人员开发了 ORBIT-Surgical&#xff0c;一个训练机器人的模拟框架&#xff0c;可以提高手术团…...

探索Go语言的原子操作秘籍:sync/atomic.Value全解析

引言 ​ 在并发编程的世界里&#xff0c;数据的一致性和线程安全是永恒的话题。Go语言以其独特的并发模型——goroutine和channel&#xff0c;简化了并发编程的复杂性。然而&#xff0c;在某些场景下&#xff0c;我们仍然需要一种机制来保证操作的原子性。这就是sync/atomic.V…...

【java深入学习第3章】利用 Spring Boot 和 Screw 快速生成数据库设计文档

免费多模型AI网站,支持豆包、GPT-4o、谷歌Gemini等AI模型&#xff0c;无限制使用&#xff0c;快去白嫖&#x1f449;海鲸AI&#x1f525;&#x1f525;&#x1f525; 在开发过程中&#xff0c;数据库设计文档是非常重要的&#xff0c;它可以帮助开发者理解数据库结构&#xff0…...

继“三级淋巴结”之后,再看看“单细胞”如何与AI结合【医学AI|顶刊速递|05-25】

小罗碎碎念 24-05-25文献速递 今天想和大家分享的是肿瘤治疗领域的另一个热点——单细胞技术&#xff0c;我们一起来看看&#xff0c;最新出炉的顶刊&#xff0c;是如何把AI与单细胞结合起来的。 另外&#xff0c;今天是周末&#xff0c;所以会有两篇文章——一篇文献速递&…...

[图解]产品经理创新之阿布思考法

0 00:00:00,000 --> 00:00:01,900 那刚才我们讲到了 1 00:00:02,730 --> 00:00:03,746 业务序列图 2 00:00:03,746 --> 00:00:04,560 然后怎么 3 00:00:05,530 --> 00:00:06,963 画现状&#xff0c;怎么改进 4 00:00:06,963 --> 00:00:09,012 然后改进的模式…...

Proteus仿真小技巧(隔空连线)

用了好几天Proteus了.总结一下使用的小技巧. 目录 一.隔空连线 1.打开添加网络标号 2.输入网络标号 二.常用元件 三.运行仿真 四.总结 一.隔空连线 引出一条线,并在末尾点一下. 1.打开添加网络标号 选择添加网络标号, 也可以先点击按钮,再去选择线(注意不要点端口) 2.…...

抖音极速版:抖音轻量精简版本,新人享大福利

和快手一样&#xff0c;抖音也有自己的极速版&#xff0c;可视作抖音的轻量精简版&#xff0c;更专注于刷视频看广告赚钱&#xff0c;收益比抖音要高&#xff0c;可玩性更佳。 抖音极速版简介 抖音极速版是一个提供短视频创业和收益任务的平台&#xff0c;用户可以通过观看广…...

leetCode-hot100-数组专题之双指针

数组双指针专题 1.同向双指针1.1例题26.删除有序数组中的重复项27.移除元素80.删除有序数组中的重复项 Ⅱ 2.相向双指针2.1例题11.盛最多水的容器42.接雨水581.最短无序连续子数组 双指针在算法题中很常见&#xff0c;下面总结双指针在数组中的一些应用&#xff0c;主要分为两类…...

完成商品SPU管理页面

文章目录 1.引入前端界面1.将前端界面放到commodity下2.创建菜单3.进入前端项目&#xff0c;使用npm添加依赖1.根目录下输入2.报错 chromedriver2.27.2的问题3.点击链接下载压缩包&#xff0c;然后使用下面的命令安装4.再次安装 pubsub-js 成功5.在main.js中引入这个组件 4.修改…...

Ansible实战YAML语言完成apache的部署,配置,启动全过程

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f3dd;️Ansible专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年5月24日15点59分 目录 &#x1f4af;趣站推荐&#x1f4af; &#x1f38a;前言 ✨️YAML语言回顾 &#x1f386;1.编写YAML文…...

深入探索微软Edge:新一代浏览器的演进与创新

在数字时代的浪潮中&#xff0c;浏览器已不再只是简单的网页访问工具&#xff0c;而是成为了连接信息、服务与用户之间的重要桥梁。微软Edge作为微软公司推出的一款全新的浏览器&#xff0c;不仅承载着微软在互联网领域的最新愿景&#xff0c;还融合了多项前沿技术&#xff0c;…...

k8s使用Volcano调度gpu

k8s部署 https://www.yangxingzhen.com/9817.html cri-dockerd安装 https://zhuanlan.zhihu.com/p/632861515 安装nvidia-container-runtime https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html 安装k8s-device-plugin https://…...

x的平方根-力扣

本题想到使用二分法不断逼近一个区间&#xff0c;直到最后趋近于x&#xff0c;从而求得解。注意的点&#xff0c;一开始使用 if(mid * mid < x) 进行判断时&#xff0c;会出现越界&#xff0c;原因是输入一个很大的数是&#xff0c;超过int表示的范围&#xff0c;继而修改为…...

hot100 -- 回溯(上)

目录 &#x1f35e;科普 &#x1f33c;全排列 AC DFS &#x1f6a9;子集 AC DFS &#x1f382;电话号码的字母组合 AC DFS &#x1f33c;组合总和 AC DFS &#x1f35e;科普 忘记 dfs 的&#xff0c;先看看这个&#x1f447; DFS&#xff08;深度优先搜索&#xf…...

5.24数据库作业

考虑如下关系模式R(A,B.C.D,E,F)上的函数依赖集F: {A→BCD&#xff0c;BC→DE&#xff0c;B→D&#xff0c;D→A} 1、计算B的闭包。 2、(使用Armstrong公理)证明AF是超码。 3、计算上述函数依赖集F的正则覆盖&#xff1b;给出你的推导的步骤并解释。 4、基于正则覆盖&#xff0…...

go-zero 实战(5)

引入Prometheus 用 Prometheus 监控应用 1. 用 docker 启动 Prometheus 编辑配置位置&#xff0c;我将 prometheus.yaml 和 targets.json 文件放在了 /opt/prometheus/conf目录下 prometheus.yaml global:scrape_interval: 15s # 抓取间隔evaluation_interval: 15s # 评估…...

Python异常处理:打造你的代码防弹衣!

Hi&#xff0c;我是阿佑&#xff0c;上文咱们讲到——揭秘Python的魔法&#xff1a;装饰器的超能力大揭秘 ‍♂️✨&#xff0c;阿佑将带领大家通过精准捕获异常、使用with语句和上下文管理器、以及异常链等高级技巧来增强代码的健壮性。就像为代码穿上防弹衣&#xff0c;保护它…...

STM32外设问题总结

SPI&#xff1a; ①&#xff0e;软件SPI和硬件SPI有什么不一样&#xff1f; 答&#xff1a;软件SPI需要在代码中进行配置相关代码&#xff0c;如配置引脚等&#xff0c;而硬件SPI的话是它已经在硬件上已经配置好SPI了&#xff0c;已经可以直接实现&#xff0c;所以可以直接使…...

【k8s】k8s集群搭建

k8s集群搭建 一、环境准备1.1 集群类型1.2 安装方式1.3 主机规划1.4 环境配置1.4.1 说明1.4.2 初始化1.4.3 关闭防火墙和禁止防火墙开机启动1.4.4 设置主机名1.4.5 主机名解析1.4.6 时间同步1.4.7 关闭selinux1.4.8 关闭swap分区1.4.9 将桥接的IPv4流量传递到iptables的链1.4.1…...

爆炸仿真的学习日志

今天学习了一下【Workbench LS-DYNA中炸药在空气中爆炸的案例-哔哩哔哩】 https://b23.tv/kmXlN29 一开始 如果你的 ANSYS Workbench 工具箱&#xff08;Toolbox&#xff09;里 只有 SPEOS&#xff0c;即使尝试了 右键刷新、重置视图、显示全部 等方法仍然没有其他分析系统&a…...

Neovim - 常用插件,提升体验(三)

文章目录 nvim-treelualineindent-blanklinetelescopegrug-far nvim-tree 官方文档&#xff1a;https://github.com/nvim-tree/nvim-tree.lua 以前我们都是通过 :e 的方式打开一个 buffer&#xff0c;但是这种方式需要记忆文件路径&#xff0c;因此这里可以通过 nvim-tree 插…...

OpenLayers 地图定位

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图定位功能很常见&#xff0c;在移动端和PC端都需要经常用到&#xff0c;像百度、高德、谷歌都提供了方便快捷的定位功能。OpenLayers中也提供了定位的…...

【数据结构】_排序

【本节目标】 排序的概念及其运用常见排序算法的实现排序算法复杂度及稳定性分析 1.排序的概念及其运用 1.1排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 1.2特性…...

96. 2017年蓝桥杯省赛 - Excel地址(困难)- 进制转换

96. Excel地址&#xff08;进制转换&#xff09; 1. 2017年蓝桥杯省赛 - Excel地址&#xff08;困难&#xff09; 标签&#xff1a;2017 省赛 1.1 题目描述 Excel 单元格的地址表示很有趣&#xff0c;它使用字母来表示列号。 比如&#xff0c; A 表示第 1 列&#xff0c;…...

Nginx + Tomcat负载均衡群集

目录 一、案例环境 二、部署 Tomcat&#xff08;102/103&#xff09; 1、准备环境 &#xff08;1&#xff09;关闭firewalld 防火墙 &#xff08;2&#xff09;安装JDK 2、安装配置 Tomcat &#xff08;1&#xff09;Tomcat 的安装和配置 &#xff08;2&#xff09;移动…...

高效绘制业务流程图!专业模板免费下载

在复杂的业务流程管理中&#xff0c;可视化工具已成为提升效能的核心基础设施。为助力开发者、项目经理及业务架构师高效落地流程标准化&#xff0c;本文将为你精选5套开箱即用的专业流程图模板。这些模板覆盖跨部门协作、电商订单、客户服务等高频场景&#xff0c;具备以下核心…...

Zookeeper 和 Kafka 版本与 JDK 要求

Apache Zookeeper 和 Apache Kafka 在不同版本中对 JDK 的要求如下表所示(基于官方文档和历史版本记录整理): 1. Zookeeper 版本与 JDK 要求 Zookeeper 版本要求的最低 JDK 版本说明3.4.x 系列JDK 6生产环境建议用 JDK 8(旧版兼容性强)。3.5.x 系列(3.5.5+)JDK 83.5.0 …...