基于Django的博客系统之增加手机验证码登录(九)

需求文档

概述

实现基于Redis和第三方短信服务商的短信验证码登录功能。用户可以通过手机号码获取验证码,并使用验证码进行登录。

需求细节
  1. 用户请求验证码
    • 用户在登录页面输入手机号码并请求获取验证码。
    • 系统生成验证码并将其存储在Redis中,同时通过第三方短信服务商发送验证码到用户手机。
  2. 用户提交验证码
    • 用户在登录页面输入手机号码和验证码。
    • 系统验证手机号码和验证码的匹配情况,如果匹配成功,用户登录成功。
功能模块
  1. 短信验证码生成与存储
    • 生成一个随机的6位数字验证码。
    • 验证码和手机号码绑定存储在Redis中,设置验证码有效期(例如5分钟)。
  2. 验证码发送
    • 集成第三方短信服务商API,发送验证码到用户手机。
  3. 验证码验证
    • 校验用户提交的手机号码和验证码是否匹配。
    • 如果匹配成功,允许用户登录。
  4. 用户登录
    • 生成用户会话或JWT令牌,返回给前端。
安全考虑
  • 对于频繁请求验证码的行为进行限制(如一个手机号每分钟只能请求一次,每小时不超过5次)。
  • 验证码存储在Redis中设置合理的过期时间。
  • 确保与第三方短信服务商的API通信使用HTTPS协议。
流程图
  1. 用户请求验证码
    • 用户提交手机号 -> 系统生成验证码 -> 存储到Redis -> 发送验证码到用户手机
  2. 用户提交验证码
    • 用户提交手机号和验证码 -> 系统验证验证码 -> 如果成功,生成会话或JWT令牌 -> 返回登录成功信息

第三方短信服务商

基于aliyun的第三方短信服务商提供5次免费试用功能,开通后配置后台页面如下:

在这里插入图片描述

API地址

调用方式

import urllib, urllib2, sys
import sslhost = 'https://zwp.market.alicloudapi.com'
path = '/sms/sendv2'
method = 'GET'
appcode = '你自己的AppCode'
querys = 'mobile=1343994XXXX&content=%E3%80%90%E6%99%BA%E8%83%BD%E4%BA%91%E3%80%91%E6%82%A8%E7%9A%84%E9%AA%8C%E8%AF%81%E7%A0%81%E6%98%AF568126%E3%80%82%E5%A6%82%E9%9D%9E%E6%9C%AC%E4%BA%BA%E6%93%8D%E4%BD%9C%EF%BC%8C%E8%AF%B7%E5%BF%BD%E7%95%A5%E6%9C%AC%E7%9F%AD%E4%BF%A1'
bodys = {}
url = host + path + '?' + querysrequest = urllib2.Request(url)
request.add_header('Authorization', 'APPCODE ' + appcode)
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
response = urllib2.urlopen(request, context=ctx)
content = response.read()
if (content):print(content)

开启服务

云市场API商品的认证方式主要以下两种方式

  • 简单身份认证Appcode
  • 签名认证

目前先采用简单身份认证,购买4元套餐启动认证,否则请求调用返回403鉴权错误。

在这里插入图片描述

技术实现

技术栈

  • HTML5
  • CSS3
  • JavaScript (使用Vue.js)
  • Axios (用于HTTP请求)

架构概述

  1. 前端部分:使用 Vue.js 编写手机验证码登录页面。
  2. 后端部分:使用 Django 编写 API,处理手机号码和验证码的验证逻辑,并与 Redis 集成存储验证码。

Django + Vue

Django 和 Vue.js 可以很好的集成在一起。Django 处理后端逻辑和 API,而 Vue.js 可以处理前端交互和视图。通过 Django 提供的 API 接口,与 Vue.js 前端进行数据交互。

Vue
  1. 在项目目录下创建 Vue.js 项目
npm install -g @vue/cli
vue create frontend
cd frontend
  1. 创建登录组件

src/components/LoginWithSMS.vue 中:

<template><div class="login-container"><form@submit.prevent="submitLogin"><div class="input-group"><select id="country_code" v-model="countryCode"><!-- 添加其他国家的区号选项 --><option v-for="country in countryCodes" :key="country.code" :value="country.code">{{ country.name }} ({{country.code }})</option></select><input type="text" id="phone_number" v-model="phoneNumber" placeholder="请输入手机号" required></div><div class="input-group"><label for="verification_code" style="float: top;">验证码</label><input type="text" class="verification_code" id="verification_code"  v-model="verificationCode"style="width: calc(100%); float: top;" required><button type="button" class="verification_code_button"@click="requestVerificationCode" :disabled="isSendingCode" style="float: bottom;">{{ buttonText }}</button></div><button type="submit">登录</button></form><div v-if="message" class="message">{{ message }}</div>
</div></template><script>
import axios from 'axios';
import { countryCodes } from '../assets/countryCodes'; // 导入国家代码数据export default {data() {return {countryCodes: countryCodes, // 使用导入的国家代码数据countryCode: '+86',phoneNumber: '',verificationCode: '',isSendingCode: false,countdown: 60,message: '', // 添加 message 状态};},computed: {buttonText() {return this.isSendingCode ? `${this.countdown} 秒后重新获取` :'获取验证码'  ;}},methods: {async requestVerificationCode() {if (!this.phoneNumber) {this.message = '请填写手机号';return;}this.isSendingCode = true;try {const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;const response = await axios.post('/api/request_verification_code/', {country_code: this.countryCode,phone_number: this.phoneNumber,}, {headers: {'Content-Type': 'application/json', // 指定请求的数据格式为 JSON'X-CSRFToken': csrftoken}});if (response.data.success) {this.isSendingCode = true;this.message = '验证码已发送';// 开始倒计时this.startCountdown();} else {this.message = '发送验证码失败';this.isSendingCode = false;}} catch (error) {console.error(error);this.message = '发送验证码失败';this.isSendingCode = false;}},async submitLogin() {if (!this.phoneNumber || !this.verificationCode) {this.message = '请填写完整信息';this.isSendingCode = false;return;}try {const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;const response = await axios.post('http://localhost:8000/api/login_with_verification_code/', {country_code: this.countryCode,phone_number: this.phoneNumber,verification_code: this.verificationCode,}, {headers: {'Content-Type': 'application/json', // 指定请求的数据格式为 JSON'X-CSRFToken': csrftoken}});if (response.data.success) {this.message = '登录成功';// 可以根据需要进行重定向或其他登录成功操作} else {this.message = '验证码错误或登录失败';this.isSendingCode = false;}} catch (error) {console.error(error);this.message = '登录失败';this.isSendingCode = false;}},startCountdown() {const countdownInterval = setInterval(() => {if (this.countdown > 0) {this.countdown--;} else {clearInterval(countdownInterval);this.countdownTimer = null;this.isSendingCode = false;this.countdown = 60; // 重置倒计时时间}}, 1000);},},
};
</script><style scoped>
.login-container {background: white;padding: 20px;border-radius: 8px;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);width: 200px;text-align: center;
}.input-group {margin-bottom: 15px;
}label {display: block;margin-bottom: 5px;
}input[type="text"], select {padding: 8px;margin-right: 5px;border: 1px solid #ccc;border-radius: 4px;
}button {padding: 8px 15px;border: none;border-radius: 4px;background-color: #007bff;color: white;cursor: pointer;
}button:disabled {background-color: #ccc;cursor: not-allowed;
}
.message {margin-top: 15px;color: red; /* 可以根据需要更改消息的样式 */
}
</style>

配置setting如下:

import { createApp } from 'vue'
import App from './App.vue'
import LoginWithSMS from './components/LoginWithSMS.vue';createApp(App)
.component('LoginWithSMS', LoginWithSMS)
.mount('#app');
Django

在 Django 中设置 API 来处理手机号码和验证码的验证逻辑,并与 Redis 集成存储验证码。

  1. 创建 Django API 端点

myblog 应用中,创建 API 端点以处理验证码请求和登录验证。

from django.urls import path
from .views import request_verification_code, login_with_verification_codeurlpatterns = [path('api/request_verification_code/', request_verification_code, name='request_verification_code'),path('api/login_with_verification_code/', login_with_verification_code, name='login_with_verification_code'),
]
  1. 创建视图函数

blog/views.py 中:

import random
import redis
from django.conf import settings
from django.http import JsonResponse
from django.contrib.auth.models import User
from django.contrib.auth import login
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
import json# 连接Redis
redis_client = redis.StrictRedis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=0)@require_POST
def request_verification_code(request):data = json.loads(request.body)phone_number = data.get('phone_number')if not phone_number:return JsonResponse({'success': False, 'message': '手机号不能为空'}, status=400)code = str(random.randint(100000, 999999))redis_key = f"verification_code:{phone_number}"redis_client.set(redis_key, code, ex=300)  # 5分钟有效期# 这里调用第三方短信服务商API发送验证码# send_verification_code(phone_number, code)return JsonResponse({'success': True, 'message': '验证码已发送'})@require_POST
def login_with_verification_code(request):data = json.loads(request.body)phone_number = data.get('phone_number')verification_code = data.get('verification_code')if not phone_number or not verification_code:return JsonResponse({'success': False, 'message': '手机号和验证码不能为空'}, status=400)redis_key = f"verification_code:{phone_number}"stored_code = redis_client.get(redis_key)if stored_code and stored_code.decode('utf-8') == verification_code:redis_client.delete(redis_key)user, created = User.objects.get_or_create(username=phone_number)if created:user.set_unusable_password()user.save()login(request, user)return JsonResponse({'success': True, 'message': '登录成功'})return JsonResponse({'success': False, 'message': '验证码错误'}, status=400)
  1. 在 Django 模板中引入 Vue.js 应用

在 Django 的模板文件中login.html,引入 Vue.js 组件:

{% load static %}
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Login</title><link rel="stylesheet" href="{% static 'css/login.css' %}"><!-- 引入 Vue 3 的静态文件 --><script src="{% static 'js/app.85a93ec8.js' %}" defer></script><script src="{% static 'js/chunk-vendors.6b7a5a13.js' %}" defer></script><link rel="stylesheet" type="text/css" href="{% static 'css/app.438959e3.css' %}"><script src="https://code.jquery.com/jquery-3.6.0.min.js"></script><script>// 当点击验证码图片时,刷新验证码$('.captcha').click(function () {$.getJSON('/captcha/refresh/',function (result) {$('.captcha').attr('src',result['image_url']);$('#id_captcha_0').val(result['key']);});});</script><style>.focusable {padding: 10px;margin: 10px;border: 1px solid #ccc;outline: none;}.focusable:focus {border-color: #007BFF;background-color: #E9F7FF;}</style>
</head>
<body>
<div id="main-container"><div class="main"><div class="auth-content"><div class="auth-form"><div class="tabs"><input type="radio" id="tab1" name="tab-group" checked><label for="tab1">邮箱登录</label><div class="tab-content">{% if error_message %}<p>{{ error_message }}</p>{% endif %}<form method="post">{% csrf_token %}{{ form.as_p }}</form></div><input type="radio" id="tab2" name="tab-group"><label for="tab2">手机登录</label><div class="tab-content" id="app"><login-with-sms></login-with-sms></div><input type="radio" id="tab3" name="tab-group"><label for="tab3">扫码登录</label><div class="tab-content"><h2>Content 3</h2><p>This is the content of tab 3.</p></div><div class="clearfix shortcut-action"><span class="login"><button type="submit">登录</button></span><span class="forgot"><a href="{% url 'password_reset_request' %}">忘记密码</a></span></div></div></div></div></div>
</div>
</body></html>

效果如下:

在这里插入图片描述

运行 Django 和 Vue.js 项目
  1. 运行 Django 项目

确保你在虚拟环境中安装了 DjangoRedis

pip install django djangorestframework redis
python manage.py runserver
  1. 运行 Vue.js 项目
npm run serve

集成第三方调用短信API

集成上面的API调用,采用AppCode方式简单鉴权。

def send_verification_code(phone_number, code):host = 'http://zwp.market.alicloudapi.com'path = '/sms/sendv2'method = 'GET'appcode = settings.SEND_TEXT_APP_CODEcontent = f"【智能云】您的验证码是{code}。如非本人操作,请忽略本短信"querys = f'mobile={phone_number}&content={content}'print(f'querys, {querys}')bodys = {}api_url = host + path + '?' + querysprint(f'api_url, {api_url}')headers = {'Authorization': 'APPCODE ' + appcode,'Content-Type': 'application/json',}print(f'headers, {headers}')try:response = requests.get(api_url, headers=headers, verify=True)if response.status_code == 200:print('短信发送成功')return Trueelse:print(f'短信发送失败,错误代码: {response.status_code}, {response.text}')return Falseexcept requests.RequestException as e:print(f'短信发送失败: {str(e)}')return False

运行

确保 Vue.js 应用编译和打包正确

  • 确保你已经正确编译和打包了 Vue.js 应用。你可以通过以下命令进行打包:
npm run build

这将生成一个 dist 目录,其中包含所有静态文件。

将编译后的文件放到 Django 的静态文件目录

  • 确保将编译后的静态文件(通常在 dist 目录中)放置在 Django 项目的静态文件目录中。你可以将这些文件复制到 static 目录中:
cp -r frontend/dist/* path/to/django/static/

启动Django服务。效果如下:

输入手机号

在这里插入图片描述

点击获取验证码,启动1分钟倒计时禁止重复请求验证码功能。

在这里插入图片描述

同时,成功发送验证码到用户手机。

在这里插入图片描述

查询redis服务器能够看到对应的值。

在这里插入图片描述

输入验证码,点击登录。报错AxiosError: Network Error at u.onerror (http://127.0.0.1:8000/static/vue/js/chunk-vendors.6b7a5a13.js:18:56732) at nn.request (http://127.0.0.1:8000/static/vue/js/chunk-vendors.6b7a5a13.js:18:64167) at async Proxy.requestVerificationCode (http://127.0.0.1:8000/static/vue/js/app.8100d9be.js:1:2450)

Axios错误解决方法:

AxiosError: Network Error 表示 Axios 在尝试进行网络请求时遇到了问题。以下是一些可能的原因和解决方法:

1. 确保 Django 服务器正在运行

确保你的 Django 服务器正在运行,并且你可以通过浏览器访问 http://127.0.0.1:8000

python manage.py runserver

2. 检查 URL 和端口

确保在 Vue.js 中 Axios 请求的 URL 和端口是正确的。

const response = await axios.post('http://127.0.0.1:8000/api/request_verification_code/', {// 请求数据
});

3. 确保 CORS 配置正确

如果前端和后端在不同的端口上运行,请确保你已经正确配置了 CORS。

安装 django-cors-headers

如果还没有安装 django-cors-headers,请先安装它:

pip install django-cors-headers
配置 django-cors-headers

在你的 Django 项目的 settings.py 文件中进行以下配置:

INSTALLED_APPS = [...'corsheaders',...
]MIDDLEWARE = [...'corsheaders.middleware.CorsMiddleware','django.middleware.common.CommonMiddleware',...
]CORS_ALLOWED_ORIGINS = ["http://localhost:8080","http://127.0.0.1:8080",# 其他允许的源
]

4. 检查网络和代理设置

确保你的网络连接正常,并且没有任何代理服务器阻止网络请求。

5. 确保 CSRF Token 正确传递

在你的 Django 模板中添加 CSRF token:

<input type="hidden" id="csrf_token" name="csrfmiddlewaretoken" value="{% csrf_token %}">

在 Vue.js 中读取并传递 CSRF token:

async requestVerificationCode() {if (!this.phoneNumber) {this.message = '请填写手机号';return;}this.isSendingCode = true;try {const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;const response = await axios.post('http://127.0.0.1:8000/api/request_verification_code/', {country_code: this.countryCode,phone_number: this.phoneNumber,}, {headers: {'Content-Type': 'application/json','X-CSRFToken': csrftoken}});if (response.data.success) {this.message = '验证码已发送';this.startCountdown();} else {this.message = '发送验证码失败';this.isSendingCode = false;}} catch (error) {console.error(error);this.message = '发送验证码失败';this.isSendingCode = false;}
}

6. 检查浏览器控制台和网络请求日志

使用浏览器的开发者工具(通常按 F12 打开),查看 Network 面板,检查网络请求的详细信息。

7. 确保前后端运行在正确的端口

确保你的前端(Vue.js)和后端(Django)都在正确的端口上运行。

示例 Vue.js 代码

export default {data() {return {countryCodes: countryCodes, // 使用导入的国家代码数据countryCode: '+86',phoneNumber: '',verificationCode: '',isSendingCode: false,countdown: 0,countdownSeconds: 60,message: '',};},computed: {buttonText() {return this.isSendingCode ? `${this.countdown} 秒后重新获取` : '获取验证码';}},methods: {async requestVerificationCode() {if (!this.phoneNumber) {this.message = '请填写手机号';return;}this.isSendingCode = true;try {const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;const response = await axios.post('http://127.0.0.1:8000/api/request_verification_code/', {country_code: this.countryCode,phone_number: this.phoneNumber,}, {headers: {'Content-Type': 'application/json','X-CSRFToken': csrftoken}});if (response.data.success) {this.message = '验证码已发送';this.startCountdown();} else {this.message = '发送验证码失败';this.isSendingCode = false;}} catch (error) {console.error(error);this.message = '发送验证码失败';this.isSendingCode = false;}},async submitLogin() {if (!this.phoneNumber || !this.verificationCode) {this.message = '请填写完整信息';return;}try {const response = await axios.post('http://127.0.0.1:8000/api/login_with_verification_code/', {phone_number: this.countryCode + this.phoneNumber,verification_code: this.verificationCode,});if (response.data.success) {this.message = '登录成功';// 可以根据需要进行重定向或其他登录成功操作} else {this.message = '验证码错误或登录失败';}} catch (error) {console.error(error);this.message = '登录失败';}},startCountdown() {const countdownInterval = setInterval(() => {if (this.countdownSeconds > 0) {this.countdownSeconds--;} else {clearInterval(countdownInterval);this.countdownTimer = null;this.isSendingCode = false;this.countdownSeconds = 60; // 重置倒计时时间}}, 1000);},},
};

通过以上步骤,你应该能够解决 AxiosError: Network Error 问题。如果问题仍然存在,请提供更多详细信息以便进一步帮助。

再次点击登录,报错网络请求报错 302 found,分析原因在login_with_verification_code中调用了redirect('/post_list')

Redirect错误解决

在 Vue.js 中成功登录后,使用浏览器的原生 JavaScript 方法进行页面重定向。

submitLogin 方法中,当登录成功时,使用 window.location.hrefwindow.location.replace() 方法来实现页面的重定向。这些方法直接操作浏览器的地址栏,可以导航到任何 URL,包括 Django 中定义的页面 URL。

示例:

在django中处理rediect逻辑如下:

        if stored_code and stored_code.decode('utf-8') == verification_code:redis_client.delete(redis_key)user, created = CustomUser.objects.get_or_create(username=phone_number)print(f'user, {user}')if created:user.set_password(phone_number)user.email = f'{phone_number}@qq.com'user.save()login(request, user)redirect_url = '/post_list'  # 修改为实际的 post_list 页面 URLreturn JsonResponse({'success': True, 'redirect_url': redirect_url})return JsonResponse({'success': False, 'message': '验证码错误'}, status=400)

在urls.py中添加路由如下:

    path('post_list', views.post_list, name='post_list'),

在vue里面添加重定向路径:

 if (response.data.success) {this.message = '登录成功';if (response.data.redirect_url) {window.location.href = response.data.redirect_url;   // 页面重定向到 Django 中的 post_list 页面} else {this.message = '验证码错误或登录失败';this.isSendingCode = false;}

效果

再次点击登录,成功登录跳转
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/854201.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Android】安卓开发的前景

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

VMware虚拟机-Ubuntu设置共享文件夹(超详细)

目录 前言1. 其他教程2. 创建共享文件夹3. VMware 设置4. Ubuntu 设置4.1 创建 hgfs 目录:4.2 挂载共享目录4.3 验证是否挂载成功4.4 设置开机自动挂载创作不易,禁止转载抄袭!!!违者必究!!! 创作不易,禁止转载抄袭!!!违者必究!!! 创作不易,禁止转载抄袭!!!违…

韩顺平0基础学java——第24天

p484-508 System类 常见方法 System.arrycopy&#xff08;src&#xff0c;0&#xff0c;dest&#xff0c;1,2&#xff09;&#xff1b; 表示从scr的第0个位置拷贝2个&#xff0c;放到目标数组索引为1的地方。 BigInteger和BigDecimal类 保存大整数和高精度浮点数 BigInte…

Springboot 整合 Flowable(一):使用 flowable-UI 绘制流程图

目录 一、Flowable简介 二、Flowable 与 Activiti 的区别 三、流程图的绘制&#xff08;以员工请假流程图为例&#xff09; 1、下载 flowable 的压缩包&#xff1a; 2、启动包中的 tomcat 3、登录页面 4、绘制结束&#xff0c;导出 bpmn20.xml文件 一、Flowable简介 Fl…

老胡的周刊(第146期)

老胡的信息周刊[1]&#xff0c;记录这周我看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。 &#x1f3af; 项目 pingvin-share[2] Pingvin Share 是一个可自…

【机器学习】图神经网络:深度解析图神经网络的基本构成和原理以及关键技术

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 引言一、图数据及其应用场景1.1 图数据的定义和特征1.2 常见的图数据结构1.2.1 社交网络1.2.2 知识图谱1.2.3 分子结构1.2.4 交通网络 1.3 图数据在不同领域的应用实例1.3.1 社交网络中的推荐系统1.3.2 知识图谱中的信息检索…

StarRocks详解

什么是StarRocks&#xff1f; StarRocks是新一代极速全场景MPP数据库&#xff08;高并发数据库&#xff09;。 StarRocks充分吸收关系型OLAP数据库和分布式存储系统在大数据时代的优秀研究成果。 1.可以在Spark和Flink里面处理数据&#xff0c;然后将处理完的数据写到StarRo…

SQL 表连接(表关联)

目录 一、INNER JOIN&#xff08;内连接,等值连接&#xff09; 二、LEFT JOIN&#xff08;左连接&#xff09; 三、RIGHT JOIN&#xff08;右连接&#xff09;&#xff1a; 一、INNER JOIN&#xff08;内连接,等值连接&#xff09; 用途&#xff1a;获取两个表中字段能匹配上…

如何解决 Git 默认不区分文件名大小写和同名文件共存?

修改文件命名的大小写&#xff0c;不会有 git 记录 本文章的例子&#xff1a;将 demo.vue 文件命名改为 Demo.vue 1、在Git项目路径下执行该命令 git config core.ignorecase false &#xff08;1&#xff09;以上方法可以实现 git 区分 demo.vue 与 Demo.vue 文件&#xff0…

功能强大的多功能文档转换工具Neevia Document Converter Pro 7.5.0.241

Neevia Document Converter Pro是一款功能强大的Windows软件,旨在将文档转换为各种格式,包括PDF、TIFF、JPEG和许多其他格式。该程序专为在企业环境中使用而设计,提供文档转换和处理过程的自动化,这使其成为处理大量文档的组织的***工具。 Neevia Document Converter Pro的…

PHP7 数组的实现

前提 PHP版本&#xff1a;php7.0.29使用到的文件 php-src/Zend/zend_types.hphp-src/Zend/zend_hash.hphp-src/Zend/zend_hash.cphp-src/Zend/zend_string.h 本文 是《PHP7底层设计和源码实现》第5章 数组的实现&#xff0c;学习笔记 功能分析 整体结构 bucket 里面增加h字段…

欣九康诊疗系统助力诊所向数字化转型

数字化已经成为各行各业转型的重点方向&#xff0c;而为了不被时代所淘汰&#xff0c;医疗机构也势必要紧跟潮流&#xff0c;本人作为门诊部的负责人深知医疗机构要想实现数字化转型那么拥有一款便捷实用的医疗平台是必不可少的&#xff0c;近几年&#xff0c;随着国家大力支持…

动态 SQL

动态 SQL 是 MyBatis 的强大特性之一&#xff0c;能够完成不同条件下不同的 sql 拼接。也就是说执行的 SQL 语句并不是固定的&#xff0c;而是不同人的不同操作执行的语句会有所差异。MyBatis 通过使用 标签 的方式来实现这种灵活性的。 <if>标签 例如在有一些网站进行…

【可控图像生成系列论文(一)】MimicBrush 港大、阿里、蚂蚁集团合作论文解读

背景&#xff1a;考虑到用户的不同需求&#xff0c;图像编辑是一项实用而富有挑战性的任务&#xff0c;其中最困难的部分之一是准确描述编辑后的图像应该是什么样子。 创新点&#xff1a;在本文作者提出了一种新的编辑形式&#xff0c;称为模仿编辑&#xff0c;以帮助用户更方…

开放式耳机哪个品牌质量比较好?2024高性价比机型推荐!

随着音乐技术的不断进步&#xff0c;耳机也必不可少&#xff0c;开放式耳机成为一部分音乐发烧友们的选择。从最初的简单音质系统&#xff0c;到如今的高清解析&#xff0c;开放式耳机也在不断升级。音质也能够和入耳式一样纯净自然&#xff0c;佩戴舒适&#xff0c;无论是街头…

清华停招土木,新增地球科学引热议

早在今年2月26日&#xff0c;多个自媒体平台上有人发布消息称“清华大学停止土木工程等专业招生”&#xff0c;引发广泛关注。 在清华大学的官网可以看到下图的公告。 可以看到&#xff0c;清华大学停招土木工程等专业&#xff0c;新增地球系统科学等专业。这一举措引起全网热…

亚马逊测评沃尔玛下单砍单率、死号率高是什么原因?

很多卖家和服务商在进行自养号测评补单过程中会出现砍单率、封号率高的问题&#xff0c;其实造成这种的原因很多&#xff0c;一套稳定的测评系统并不是单解决IP的纯净度问题或者支付卡的卡头风控问题就可以解决的&#xff0c;亚马逊测评下单砍单率、死号率高的原因可以归纳为以…

Vue50-mixin混入

一、为什么要使用 mixin混入 两个组件共享一个配置。 二、使用 mixin混入 2-1、创建一个混合js文件 2-2、引入混合js文件 1、局部混合 在每个组件中都引入混合js文件 注意&#xff1a; 混合就是复用配置&#xff0c;vm实例中的所有的配置项&#xff0c;都能在混合.js文件中写…

elasticsearch过滤器filter:原理及使用

码到三十五 &#xff1a; 个人主页 目录 一、引言二、Elasticsearch的过滤器概述三、使用DSL进行过滤操作术语过滤范围过滤复合过滤 四、优化策略五、结语 一、引言 Elasticsearch是一个功能强大的开源搜索引擎&#xff0c;广泛应用于各种数据检索和处理场景。在Elasticsearch…

WPS如何合并多个word文档到一个文档中

将多个Word文档合并成一个 【插入】---》【附件】----》【文件中的文字】----》选择多个需要合并的word文档&#xff0c;点击确定即可。 用的工具是WPS。