超詳細 anji-captcha滑塊驗證uniapp微信小程序前端組件

由于步驟太多,字數太多,廢話也太多,所以前后端分開講了,后端文章請看:

超詳細 anji-captcha滑塊驗證springboot+uniapp微信小程序前后端組合https://blog.csdn.net/new_public/article/details/149116742


anji-captcha開源項目地址:https://github.com/anji-plus/captcha

anji-captcha開源文檔地址:在線體驗暫時下線 !!! | AJ-Captcha


寫完后端代碼,開始寫前端,首選肯定又是一頓各種網上查資料搬磚,發現基本清一色用了anji-captcha開源文檔介紹的【Verify】組件,這組件是anji-captcha開源項目里面有的,在view文件夾下面,選擇自己對應的前端類型,里面有下面幾種類型。

比如:/view/vue/src/components/verifition/Verify?


?不過我沒去看,是自己寫了一個,畢竟只有自己寫的才是最適合自己的。


效果如下:


每次滑動有廣告語出現,比如視頻里的,【大怨種】【純牛馬】。

獲取次數和驗證次數超限,會顯示提示等。


組件代碼

<template><modal ref="$captchaModal" :width="modalWidth" :padding="modalPadding"><template #body><view class="captcha-modal-content" :style="{ height: 'calc(' + slideImageHeight + 'px + ' + slideBlockWidth + 'px + 12rpx)' }"><template v-if="sliderCaptchaBackBase64"><image class="captcha-back-image":style="{ width: slideImageWidth + 'px', height: slideImageHeight + 'px' }":src="sliderCaptchaBackBase64" /><image class="captcha-slider-image" :src="sliderCaptchaBlockBase64":style="{ width: slideBlockWidth + 'px', height: slideImageHeight + 'px', transform: 'translate3d(' + lastLeft + 'px,0,0)' }" /></template><image v-else src="/static/images/svg/null_data.svg" class="captcha-back-image" style="height: 300rpx;"/><view class="slide-parent" :style="{ width: slideImageWidth + 'px', height: slideBlockWidth + 'px',backgroundColor: sliderCaptchaBackBase64 ? 'rgb(233, 233, 233)' : 'transparent' }"><template  v-if="sliderCaptchaBackBase64"><view class="slide-tip tui-text-flashover">拖動滑塊驗證</view><view class="slide-cover" :style="{ width: lastLeft + 'px' }"><view class="slide-cover-content" :style="{ width: slideImageWidth + 'px' }">{{ slideCoverText }}</view></view><view class="slide-view" :style="{ width: slideBlockWidth + 'px', height: slideBlockWidth + 'px', transform: 'translate3d(' + lastLeft + 'px,0,0)' }"@touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"><tui-icon name="up" :size="19" style="transform: rotate(90deg);" /></view></template><view v-else class="tui-flex-center" style="height: 100%;":class="{ 'tui-underline': captChaGetRepCode !== '6201' }"@click="delayedGenerateSlideCaptchaImage">{{ errorMsg }}</view></view></view></template></modal>
</template>
<script>// 這里用到util是防抖動方法和四舍五入方法,自己寫一個吧,或者問api給一個import util from '@/utils/util'// npm i crypto-js -s 引入,這里用的是4.2.0版本import CryptoJS from 'crypto-js/crypto-js'export default {data () {return {// 滑塊寬高度 pxslideBlockWidth: 47,// 背景圖寬度 pxslideImageWidth: 310,// 背景圖高度 pxslideImageHeight: 155,// 彈窗占據屏幕 90%modalWidth: 90,// 彈窗內部左右邊距20pxmodalLRpadding: 20,// 縮放比率,不同屏幕的手機,必須適配scaleRatio: 0,// 滑動起始X位置 pxstartX: 0,// 滑動停止位置,也就是距離起始位置長度 pxlastLeft: 0,// 后端返回的驗證碼參數captchaOption: {},// 父頁面參數parentOption: {},// 獲取滑塊驗證碼返回的結果碼,用來顯示錯誤信息的captChaGetRepCode: void (0),// 廣告語,每次隨機取slideCoverTextList: ['大怨種', '純牛馬', '肝吧', '擠上牛馬傳送帶', '這就是命啊']}},created () {// 初始化背景圖和滑塊縮放this.handlerCaptchaScale()// 手動獲取滑塊驗證碼的方法,加上防抖動,350毫秒this.delayedGenerateSlideCaptchaImage = util.debounce(this.delayedGenerateSlideCaptchaImage, 350)},computed: {modalPadding () {return `40rpx ${this.modalLRpadding}px 20rpx ${this.modalLRpadding}px`},// 廣告語,隨機取,為了能隨機,故跟startX綁定上了slideCoverText () {const initIndex = Math.floor(Math.random() * this.slideCoverTextList.length)const startXStr = String(this.startX)const finalIndex = initIndex + (startXStr.length > 1 ? Number(startXStr.substring(startXStr.length - 1)) : this.startX)return this.slideCoverTextList[finalIndex > this.slideCoverTextList.length - 1 ? initIndex : finalIndex]},// 背景圖base64sliderCaptchaBackBase64 () {const { originalImageBase64 } = this.captchaOptionif (!originalImageBase64) {return ''}return 'data:image/png;base64,' + originalImageBase64},// 滑塊base64sliderCaptchaBlockBase64 () {const { jigsawImageBase64 } = this.captchaOptionif (!jigsawImageBase64) {return ''}return 'data:image/png;base64,' + jigsawImageBase64},errorMsg () {if (this.captChaGetRepCode === '6201') {return '獲取圖形驗證碼頻繁,請稍后再試'} else if (this.captChaGetRepCode !== '0000') {return '啊哦,加載失敗了,點擊這里刷新'}return ''}},methods: {// 顯示滑塊驗證碼彈窗,父頁面通過ref通用show (option = {}) {this.resetSlideCaptcha()this.parentOption = optionthis.generateSlideCaptchaImage().then(_ => {this.$nextTick(() => {// 調用彈窗組件方法,顯示彈窗this.$refs.$captchaModal.show({title: option.title || '驗證',maxHeight: 800,hideCancel: true,confirmText: '關閉',// 彈窗關閉按鈕點擊回調callback: _ => {// 如果父頁面有關閉回調,則這里調用this.parentOption.closeCallback && this.parentOption.closeCallback()}})})})},close () {this.resetSlideCaptcha()// 關閉彈窗this.$refs.$captchaModal.onClose()},// 初始化縮放比率,以及設置滑塊背景和滑塊寬高handlerCaptchaScale () {const { windowWidth } = uni.getSystemInfoSync()const modalWidthPx = windowWidth * (this.modalWidth / 100)const modalLRpaddingSum = this.modalLRpadding * 2const modalInternalWidth = modalWidthPx - modalLRpaddingSumconst onePercentagePx = windowWidth * 0.01if (modalInternalWidth > this.slideImageWidth) {// 如果屏幕寬度大于初始化滑塊背景圖寬度,則不縮放this.modalWidth = util.toFixed((this.slideImageWidth + modalLRpaddingSum) / onePercentagePx, 2)} else if (modalInternalWidth < this.slideImageWidth) {// 否則縮放滑塊背景圖和滑塊this.scaleRatio = modalInternalWidth / this.slideImageWidththis.slideImageWidth = modalInternalWidththis.slideImageHeight = this.slideImageHeight * this.scaleRatiothis.slideBlockWidth = this.slideBlockWidth * this.scaleRatio}},// 手動重新獲取delayedGenerateSlideCaptchaImage () {if (this.captChaGetRepCode === '6201') {return}this.generateSlideCaptchaImage()},// 獲取滑塊驗證碼generateSlideCaptchaImage () {return new Promise((resolve, reject) => {// request 基于uni.request封裝,總之就是調獲取驗證碼接口request('/captcha/get', 'POST', { 'captchaType' : 'blockPuzzle' }, true).then(({ repData = {}, repCode }) => {this.captChaGetRepCode = repCodethis.captchaOption = repData}).finally(() => {resolve()})})},// 按中滑塊,記錄起始位置touchstart (e) {const touch = e.touches[0] || e.changedTouches[0]this.startX = touch.clientX},// 開始滑動,計算當前滑動位置touchmove (e) {const touch = e.touches[0] || e.changedTouches[0]const pageX = touch.clientXconst width = this.slideImageWidth - this.slideBlockWidth - 1let left = pageX - this.startXleft = left < 0 ? 0 : (left >= width ? width : left)this.lastLeft = left},// 滑動結束(松手),驗證touchend () {/*** callback 父頁面驗證結果回調* verifyCaptchaCallback 整個驗證由父頁面處理* verifyApi 驗證后端接口* * callback 和 verifyCaptchaCallback 二選一* 選callback,verifyApi必傳,讓這個這個組件調用驗證接口*/const { callback, verifyCaptchaCallback, verifyApi } = this.parentOptionif (callback || verifyCaptchaCallback) {if (verifyCaptchaCallback) {verifyCaptchaCallback(this.captchaOption).then(flag => {if (flag) {this.close()} else {this.resetSlideCaptcha(true)}})} else {this.verifyCaptcha(verifyApi).then(res => {if (res) {// 驗證成功,記錄本次驗證碼的aes密匙,給后面后端二次驗證使用res.secretKey = this.captchaOption.secretKeythis.close()} else {// 驗證失敗重新獲取this.resetSlideCaptcha(true)}callback(res)})}} else {this.resetSlideCaptcha(true)}},// 重置resetSlideCaptcha (generateFlag) {this.lastLeft = 0this.startX = 0generateFlag && this.generateSlideCaptchaImage()},// 驗證滑動是否正確verifyCaptcha (verifyApi) {return new Promise((resolve, reject) => {const originalPointJson = this.generatePointJson()const param = {captchaType: 'blockPuzzle',token: this.captchaOption.token,pointJson: this.pointEncrypted(originalPointJson)}// request 基于uni.request封裝,總之就是調驗證接口request(verifyApi || '/captcha/check', 'POST', param, true).then(res => {const { repCode, repData = {}, repMsg } = resif (repCode === '0000' && repData.result) {resolve({ ...repData, originalPointJson })} else {// toast 等同 uni.showToast()toast(repMsg || '驗證失敗')resolve(false)}}).catch(_ => {resolve(false)})})},// 生成當前滑動完成的坐標點,加密的原文generatePointJson () {const x = this.scaleRatio > 0 ? ((this.lastLeft - 1) / this.scaleRatio) : this.lastLeft - 1return JSON.stringify({x,y:0})},// aes加密坐標點pointEncrypted (originalPointJson) {const key = CryptoJS.enc.Utf8.parse(this.captchaOption.secretKey)const encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(originalPointJson),key,{mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7})return encrypted.toString()},// 生成后端二次驗證的密文captchaVerificationEncrypted ({ originalPointJson, token, secretKey }) {const key = CryptoJS.enc.Utf8.parse(secretKey)const dataToEncrypt = token + '---' + originalPointJsonconst encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(dataToEncrypt),key,{mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7})return encrypted.toString()}}}
</script>
<style scoped lang="scss">.captcha-modal-content {position: relative;.captcha-back-image {width: 100%;border-radius: 10rpx;}.captcha-slider-image {position: absolute;left: 0;top: 0;z-index: 1;}.slide-parent {width: 100%;background-color: rgb(233, 233, 233);position: relative;padding: 1px 0;.slide-tip {position: absolute;top: 0;left: 0;right: 0;bottom: 0;color: #616161;font-size: 30rpx;display: flex;align-items: center;justify-content: center;}.slide-cover {width: 0;height: 100%;position: absolute;left: 0;top: 0;z-index: 1;display: flex;align-items: center;justify-content: center;overflow: hidden;.slide-cover-content {height: 100%;color: #FFF;background-color: #0081ff;font-size: 30rpx;display: flex;align-items: center;justify-content: center;position: absolute;left: 0;top: 0;}}.slide-view {position: absolute;left: 1px;z-index: 2;background: #FFF;display: flex;align-items: center;justify-content: center;}}}.tui-text-flashover {background: -webkit-gradient(linear, left top, right top, color-stop(0, #444), color-stop(.4, #444), color-stop(.5, white), color-stop(.6, #444), color-stop(1, #444));-webkit-background-clip: text !important;-webkit-text-fill-color: transparent !important;-webkit-animation: animate 1.8s infinite;}.tui-flex-center {display: flex;align-items: center;justify-content: center;}.tui-underline {text-decoration: underline;}@-webkit-keyframes animate {from {background-position: -90rpx;}to {background-position: 90rpx;}}@keyframes animate {from {background-position: -90rpx;}to {background-position: 90rpx;}}
</style>

注意:組件代碼不可直接復制使用,里面使用了一些我項目的封裝代碼(下面這些)。

  • toast方法,是輸出提示。
  • request方法,是調后端接口。
  • <modal>是我封裝的一個彈窗組件,彈窗組件UI庫大把,自己套一個。參數width是百分比,我的modal組件接收的是Number,所以這里初始90,代表占屏幕90%寬度。然后再根據屏幕大小決定彈窗大小的。
  • 兩個import上面有注釋說明。

最好看一遍代碼的里面的注釋,上面說的幾個地方需要自己改一下


使用流程

功能引入此組件并定義ref,通過ref調用組件的show方法即可,傳入參數,例如:

this.$refs.$sliderCaptcha.show({// 驗證接口verifyApi: '/xxx/yyy',callback: res => {if (res) {// 驗證成功,生成后端二次驗證密文(也就是二次驗證的redisKey)(不是必須,看自己業務,如有需要的話)const captchaVerification = this.$refs.$sliderCaptcha.captchaVerificationEncrypted(res)}}
})

其他羅里吧嗦

1:滑塊滑動到缺口后,取哪里的x值?

正確缺口的開始位置,這個開始位置x值是正確的,對應后端緩存,基本大差不差。

2:怎么取?

觸摸滑塊時,touchstart方法記錄觸摸位置,滑動觸發touchmove方法,獲取當前滑動x值,然后減去起始觸摸位置,就是正確的x值。


代碼里面那個null_data.svg

我直接把源碼粘貼出來,復制到文本文件里面,然后后綴改成svg就可以用了

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="122px" height="104px" viewBox="0 0 122 104" version="1.1"><!-- Generator: Sketch 55 (78076) - https://sketchapp.com --><title>暫無相關搜索</title><desc>Created with Sketch.</desc><g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="空白頁" transform="translate(-40.000000, -508.000000)"><g id="暫無相關搜索" transform="translate(40.000000, 508.000000)"><g id="分組"><g id="背景/線" fill="#C3CBD6"><g id="-"><g id="編組" transform="translate(14.200000, 9.200000)" fill-rule="nonzero"><path d="M0.8,73.1 C0.3581722,73.1 -5.68434189e-14,72.7418278 -5.68434189e-14,72.3 C-5.68434189e-14,71.8581722 0.3581722,71.5 0.8,71.5 L70.8,71.5 C71.2418278,71.5 71.6,71.8581722 71.6,72.3 C71.6,72.7418278 71.2418278,73.1 70.8,73.1 L0.8,73.1 Z M74.8,73.1 C74.3581722,73.1 74,72.7418278 74,72.3 C74,71.8581722 74.3581722,71.5 74.8,71.5 L77.3,71.5 C77.7418278,71.5 78.1,71.8581722 78.1,72.3 C78.1,72.7418278 77.7418278,73.1 77.3,73.1 L74.8,73.1 Z M83.8,73.1 C83.3581722,73.1 83,72.7418278 83,72.3 C83,71.8581722 83.3581722,71.5 83.8,71.5 L92.8,71.5 C93.2418278,71.5 93.6,71.8581722 93.6,72.3 C93.6,72.7418278 93.2418278,73.1 92.8,73.1 L83.8,73.1 Z M23.8,80.6 C23.3581722,80.6 23,80.2418278 23,79.8 C23,79.3581722 23.3581722,79 23.8,79 L30.8,79 C31.2418278,79 31.6,79.3581722 31.6,79.8 C31.6,80.2418278 31.2418278,80.6 30.8,80.6 L23.8,80.6 Z M35.3,80.6 C34.8581722,80.6 34.5,80.2418278 34.5,79.8 C34.5,79.3581722 34.8581722,79 35.3,79 L65.8,79 C66.2418278,79 66.6,79.3581722 66.6,79.8 C66.6,80.2418278 66.2418278,80.6 65.8,80.6 L35.3,80.6 Z M80,52.8 C80,51.7333333 81.6,51.7333333 81.6,52.8 L81.6,55.8 C81.6,56.2418278 81.2418278,56.6 80.8,56.6 L77.8,56.6 C76.7333333,56.6 76.7333333,55 77.8,55 L80,55 L80,52.8 Z M81.6,58.8 C81.6,59.8666667 80,59.8666667 80,58.8 L80,55.8 C80,55.3581722 80.3581722,55 80.8,55 L83.8,55 C84.8666667,55 84.8666667,56.6 83.8,56.6 L81.6,56.6 L81.6,58.8 Z M4,28.8 C4,27.7333333 5.6,27.7333333 5.6,28.8 L5.6,31.8 C5.6,32.2418278 5.2418278,32.6 4.8,32.6 L1.8,32.6 C0.733333333,32.6 0.733333333,31 1.8,31 L4,31 L4,28.8 Z M78.1,3.5 L80.8,3.5 C81.8666667,3.5 81.8666667,5.1 80.8,5.1 L78.1,5.1 L78.1,7.8 C78.1,8.86666667 76.5,8.86666667 76.5,7.8 L76.5,5.1 L73.8,5.1 C72.7333333,5.1 72.7333333,3.5 73.8,3.5 L76.5,3.5 L76.5,0.8 C76.5,-0.266666667 78.1,-0.266666667 78.1,0.8 L78.1,3.5 Z M5.6,34.8 C5.6,35.8666667 4,35.8666667 4,34.8 L4,31.8 C4,31.3581722 4.3581722,31 4.8,31 L7.8,31 C8.86666667,31 8.86666667,32.6 7.8,32.6 L5.6,32.6 L5.6,34.8 Z" id="Path-2"></path><path d="M14.0928932,61.1431458 C14.5642977,60.6717412 15.2714045,61.378848 14.8,61.8502525 L13.7393398,62.9109127 C13.5440777,63.1061748 13.2274952,63.1061748 13.032233,62.9109127 L11.9715729,61.8502525 C11.5001684,61.378848 12.2072751,60.6717412 12.6786797,61.1431458 L13.3857864,61.8502525 L14.0928932,61.1431458 Z M12.6786797,63.9715729 C12.2072751,64.4429774 11.5001684,63.7358706 11.9715729,63.2644661 L13.032233,62.2038059 C13.2274952,62.0085438 13.5440777,62.0085438 13.7393398,62.2038059 L14.8,63.2644661 C15.2714045,63.7358706 14.5642977,64.4429774 14.0928932,63.9715729 L13.3857864,63.2644661 L12.6786797,63.9715729 Z M22.9213203,8.8 C23.3927249,8.32859548 24.0998316,9.03570226 23.6284271,9.50710678 L22.567767,10.567767 C22.3725048,10.7630291 22.0559223,10.7630291 21.8606602,10.567767 L20.8,9.50710678 C20.3285955,9.03570226 21.0357023,8.32859548 21.5071068,8.8 L22.2142136,9.50710678 L22.9213203,8.8 Z M21.5071068,11.6284271 C21.0357023,12.0998316 20.3285955,11.3927249 20.8,10.9213203 L21.8606602,9.86066017 C22.0559223,9.66539803 22.3725048,9.66539803 22.567767,9.86066017 L23.6284271,10.9213203 C24.0998316,11.3927249 23.3927249,12.0998316 22.9213203,11.6284271 L22.2142136,10.9213203 L21.5071068,11.6284271 Z" id="Path復制"></path></g></g></g><g id="Group-6" transform="translate(37.000000, 29.000000)"><g id="分組" stroke="#C3CBD6"><path d="M3,-1.0658141e-14 L35,-1.0658141e-14 C36.6568542,-1.09625002e-14 38,1.34314575 38,3 L38,42 C38,43.6568542 36.6568542,45 35,45 L3,45 C1.34314575,45 2.02906125e-16,43.6568542 0,42 L0,3 C-2.02906125e-16,1.34314575 1.34314575,-1.03537818e-14 3,-1.0658141e-14 Z" id="矩形" stroke-width="1.6" fill="#FFFFFF"></path><path d="M7.8,26.8 L12.8,26.8 L7.8,26.8 Z M7.8,19.8 L11.8,19.8 L7.8,19.8 Z M7.8,12.8 L13.8,12.8 L7.8,12.8 Z" id="Stroke-16" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"></path></g><g id="分組-2" transform="translate(15.000000, 4.000000)"><path d="M26.8450231,25.0101574 L32.8450231,25.0101574 L32.8370236,35.9124666 C32.8358076,37.5696764 31.4920325,38.9124658 29.8348223,38.9124658 L29.8348223,38.9124658 C28.1791833,38.9124658 26.8370228,37.5703052 26.8370228,35.9146662 C26.8370228,35.913933 26.837023,35.9131998 26.8370236,35.9124666 L26.8450231,25.0101574 Z" id="矩形" stroke="#C3CBD6" stroke-width="1.6" fill="#F5F7F9" transform="translate(29.839923, 31.961312) rotate(-42.000000) translate(-29.839923, -31.961312) "></path><circle id="橢圓形" stroke="#C3CBD6" stroke-width="1.6" fill="#F5F7F9" cx="16.5" cy="16.5" r="16.5"></circle><circle id="橢圓形-copy" stroke="#C3CBD6" stroke-width="1.6" fill="#FFFFFF" cx="16.5" cy="16.5" r="12.5"></circle><path d="M17.6131592,19.685 C17.3091168,19.7925464 15.7049189,19.8010303 15.4349189,19.685 C15.1649189,19.5689697 15.1349189,19.43 15.1349189,18.995 C15.1349189,17.96 15.3149189,17.36 15.7949189,16.775 C16.1549189,16.355 16.2749189,16.265 17.3399189,15.62 C18.0749189,15.185 18.3149189,14.87 18.3149189,14.375 C18.3149189,13.67 17.7899189,13.25 16.8899189,13.25 C16.2149189,13.25 15.7199189,13.49 15.4349189,13.955 C15.2849189,14.195 15.1949189,14.2841284 15.1649189,14.87 C15.1349189,15.4558716 11.9819336,15.62 12.0749189,14.585 C12.1679042,13.55 12.4649189,12.92 13.0349189,12.29 C13.9049189,11.3 15.2399189,10.79 16.9649189,10.79 C19.7249189,10.79 21.4499189,12.095 21.4499189,14.165 C21.4499189,15.08 21.1499189,15.785 20.5199189,16.37 C20.1599189,16.7 20.0099189,16.805 18.7049189,17.615 C18.0749189,18.02 17.8499189,18.41 17.8499189,19.1 C17.8499189,19.28 17.9172016,19.5774536 17.6131592,19.685 Z M16.4174189,20.705 L16.5974189,20.705 C17.3802825,20.705 18.0149189,21.3396364 18.0149189,22.1225 L18.0149189,22.1225 C18.0149189,22.9053636 17.3802825,23.54 16.5974189,23.54 L16.4174189,23.54 C15.6345553,23.54 14.9999189,22.9053636 14.9999189,22.1225 L14.9999189,22.1225 C14.9999189,21.3396364 15.6345553,20.705 16.4174189,20.705 Z" id="?" fill="#C3CBD6" fill-rule="nonzero"></path></g></g></g></g></g></g>
</svg>


碼字不易,于你有利,勿忘點贊

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/89388.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/89388.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/89388.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

面向對象編程篇

文章目錄一、思維導圖二、詳細內容第 6 章&#xff1a;面向對象編程基礎6.1 面向對象編程的概念和優勢6.2 類和對象的定義與創建6.3 類的屬性和方法6.4 構造函數&#xff08;__init__&#xff09;和析構函數&#xff08;__del__&#xff09;6.5 封裝、繼承和多態的實現第 7 章&…

虛擬商品自動化實踐:閑魚訂單防漏發與模板化管理的技術解析

最近阿燦發現了一款閑魚虛擬商品賣家必備神器&#xff01;告別手動發貨&#xff0c;訂單自動處理&#xff0c;防錯防漏&#xff0c;支持課程、激活碼、電子書等多種商品&#xff0c;預設模板更省心。文末獲取工具&#xff01;最厲害的是&#xff0c;你完全不用一直開著電腦。以…

【Zephyr開發實踐系列】08_NVS文件系統調試記錄

文章目錄前言一、NVS原理介紹&#xff1a;二、BUG-NO1&#xff1a;將NVS運用在NAND-Flash類大容量存儲設備2.1 情況描述&#xff1a;2.2 BUG復現&#xff1a;文件系統設備樹構建測試應用編寫&#xff08;導致錯誤部分&#xff09;&#xff1a;問題呈現&#xff1a;2.3 問題簡述…

網絡安全第二次作業

靶場闖關1~8 1. 在url后的name后輸入payload ?name<script>alert(1)</script> 2. 嘗試在框中輸入上一關的payload,發現并沒有通過&#xff0c;此時我們可以點開頁面的源代碼看看我們輸入的值被送到什么地方去了 從圖中可以看到&#xff0c;我們輸入的值被送到i…

LangChain 源碼剖析(七)RunnableBindingBase 深度剖析:給 Runnable“穿衣服“ 的裝飾器架構

每一篇文章都短小精悍&#xff0c;不啰嗦。一、功能定位&#xff1a;Runnable 的 "增強包裝器"RunnableBindingBase 是 LangChain 中實現裝飾器模式的核心組件。它就像給原有 Runnable 套上一件 "功能外套"—— 不改變原有 Runnable 的核心邏輯&#xff0c…

為 Git branch 命令添加描述功能

寫在最前面的使用方式 查看 所有分支的備注 git branch.notes創建分支并為分支添加備注 git co -b feat/oauth -m 第三方用戶登錄對分支描述的添加與清除 添加 git branch.note --add 清除 git branch.note --clear &#x1f4dd; 為 Git branch 命令添加描述功能 &#x…

LeetCode|Day18|20. 有效的括號|Python刷題筆記

LeetCode&#xff5c;Day18&#xff5c;20. 有效的括號&#xff5c;Python刷題筆記 &#x1f5d3;? 本文屬于【LeetCode 簡單題百日計劃】系列 &#x1f449; 點擊查看系列總目錄 >> &#x1f4cc; 題目簡介 題號&#xff1a;20. 有效的括號 難度&#xff1a;簡單 題目…

使?Pytorch構建?個神經?絡

關于torch.nn:使?Pytorch來構建神經?絡, 主要的?具都在torch.nn包中.nn依賴于autograd來定義模型, 并對其?動求導.構建神經?絡的典型流程:定義?個擁有可學習參數的神經?絡遍歷訓練數據集處理輸?數據使其流經神經?絡計算損失值將?絡參數的梯度進?反向傳播以?定的規則…

網絡爬蟲的詳細知識點

基本介紹 什么是網絡爬蟲 網絡爬蟲&#xff08;Web Crawler&#xff09;是一種自動化程序&#xff0c;用于從互聯網上抓取、解析和存儲網頁數據。其核心功能是模擬人類瀏覽行為&#xff0c;通過HTTP/HTTPS協議訪問目標網站&#xff0c;提取文本、鏈接、圖片或其他結構化信息&…

AndroidX中ComponentActivity與原生 Activity 的區別

一、AndroidX 與原生 Activity 的區別 1. 概念與背景 原生 Activity&#xff1a;指 Android 早期&#xff08;API 1 起&#xff09;就存在于 android.app 包下的 Activity 類&#xff08;如 android.app.Activity&#xff09;&#xff0c;是 Android 最初的 Activity 實現&…

Spring AI 使用 Elasticsearch 作為向量數據庫

前言 嗨&#xff0c;大家好&#xff0c;我是雪荷&#xff0c;最近在公司開發 AI 知識庫&#xff0c;同時學到了一些 AI 開發相關的技術&#xff0c;這期先與大家分享一下如何用 ES 當做向量數據庫。 安裝ES 第一步我們先安裝 Elasticsearch&#xff0c;這里建議 Elasticsear…

TypeScript 配置全解析:tsconfig.json、tsconfig.app.json 與 tsconfig.node.json 的深度指南

前言在現代前端和后端開發中&#xff0c;TypeScript 已經成為許多開發者的首選語言。然而&#xff0c;TypeScript 的配置文件&#xff08;特別是多個配置文件協同工作時&#xff09;常常讓開發者感到困惑。本文將深入探討 tsconfig.json、tsconfig.app.json 和 tsconfig.node.j…

讀書筆記(學會說話)

1、一個人只有會說話&#xff0c;才會有好人緣&#xff0c;做事才會順利。會說話的人容易成功。善于說話的人易成功&#xff0c;而不善說話的人往往寸步難行。我們要把話說得好聽&#xff0c;同時更要把事做得漂亮。或許一句話&#xff0c;一件事&#xff0c;就可能使人生的旅途…

私有服務器AI智能體搭建-大模型選擇優缺點、擴展性、可開發

以下是主流 AI 框架與模型的對比分析&#xff0c;涵蓋其優缺點、擴展性、可開發性等方面。 文章目錄一、AI 框架對比二、主流大模型對比三、擴展性對比總結四、可開發性對比總結五、選擇建議&#xff08;按場景&#xff09;六、未來趨勢一、AI 框架對比 框架優點缺點擴展性可開…

OpenCV直線段檢測算法類cv::line_descriptor::LSDDetector

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 該類用于實現 LSD (Line Segment Detector) 直線段檢測算法。LSD 是一種快速、準確的直線檢測方法&#xff0c;能夠在不依賴邊緣檢測的前提下直接從…

Go語言流程控制(if / for)

分支結構package mainimport ("fmt""strconv" )/* 1.順序結構 2.分支結構 3.循環結構 *//* if 條件1 {// 條件1為真時執行的代碼 } else if 條件2 {// 條件1為假但條件2為真時執行的代碼 } else {// 所有條件均為假時執行的代碼 }一種特殊的條件分支結構if…

wx小程序設置沉浸式導航文字高度問題

第一步&#xff1a;在app.json中設置"navigationStyle": "custom"第二步驟&#xff1a;文件的home.js中// pages/test/test.js Page({/*** 頁面的初始數據*/data: {statusBarHeight: 0,navBarHeight: 44 // 自定義導航內容區高度(單位px)},/*** 生命周期函…

C++算法競賽篇:DevC++ 如何進行debug調試

C算法競賽篇&#xff1a;DevC 如何進行debug調試前言一、準備工作&#xff1a;編譯生成可執行程序二、核心步驟&#xff1a;設置斷點與啟動調試1. 設置斷點2. 啟動調試模式三、調試操作&#xff1a;逐步執行與變量監控1. 逐步執行代碼2. 監控變量值變化四、調試結束前言 在算法…

語音大模型速覽(三)- cosyvoice2

CosyVoice 2: Scalable Streaming Speech Synthesis with Large Language Models 論文鏈接&#xff1a;https://arxiv.org/pdf/2412.10117代碼鏈接&#xff1a;https://github.com/FunAudioLLM/CosyVoice 一句話總結 CosyVoice 2 是一款改進的流式語音合成模型&#xff0c;其…

-lstdc++與-static-libstdc++的用法和差異

CMakeLists.txt 里寫了&#xff1a; target_link_libraries(${PROJECT_NAME} PRIVATEgccstdc ) target_link_options(${PROJECT_NAME} PRIVATE -static-libstdc)看起來像是“鏈接了兩次 C 標準庫”&#xff0c;其實它們的作用完全不同&#xff1a;1. target_link_libraries(...…