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

鸿蒙OSUniApp 实现的表单验证与提交功能#三方框架 #Uniapp

UniApp 实现的表单验证与提交功能

前言

在移动端应用开发中,表单是用户与应用交互的重要媒介。一个好的表单不仅布局合理、使用方便,还应该具备完善的验证与提交功能,以确保用户输入的数据准确无误。本文将分享如何在 UniApp 中实现表单验证与提交功能,帮助你构建更加健壮的表单系统。

作为一个经常与表单打交道的开发者,我发现很多初学者往往忽视了表单验证的重要性,或者实现方式不够优雅。通过本文,希望能为你提供一些关于 UniApp 表单处理的实用技巧和最佳实践。

为什么需要表单验证?

想象一下,如果没有表单验证,用户可能会提交不完整或格式错误的数据:

  • 手机号码少输一位或输入了字母
  • 密码太简单,不符合安全要求
  • 重要字段被遗漏
  • 日期格式错误
  • 上传的图片尺寸过大或格式不支持

这些问题不仅会导致后端数据处理错误,还会影响用户体验。因此,前端表单验证显得尤为重要。

UniApp 表单验证的实现方式

在 UniApp 中,有多种方式可以实现表单验证:

  1. 使用原生方法自行实现
  2. 使用第三方验证库(如 async-validator)
  3. 结合 uView 等 UI 框架使用内置验证功能

下面我们主要讨论前两种方式的实现。

方式一:自行实现表单验证

自行实现的优点是灵活、无需引入额外依赖,但需要自己编写各种验证规则和处理逻辑。

基本思路:
  1. 定义表单数据模型
  2. 编写验证规则函数
  3. 在提交前调用验证函数
  4. 根据验证结果决定是否提交

让我们看一个简单的注册表单验证示例:

export default {data() {return {// 表单数据form: {username: '',password: '',confirmPassword: '',mobile: '',email: '',agree: false},// 错误信息errors: {username: '',password: '',confirmPassword: '',mobile: '',email: '',agree: ''}}},methods: {// 验证用户名validateUsername() {if (!this.form.username) {this.errors.username = '用户名不能为空';return false;}if (this.form.username.length < 3 || this.form.username.length > 20) {this.errors.username = '用户名长度应为3-20个字符';return false;}this.errors.username = '';return true;},// 验证密码validatePassword() {if (!this.form.password) {this.errors.password = '密码不能为空';return false;}if (this.form.password.length < 6) {this.errors.password = '密码长度不能少于6个字符';return false;}// 包含数字和字母的正则表达式const passwordPattern = /^(?=.*[0-9])(?=.*[a-zA-Z]).{6,}$/;if (!passwordPattern.test(this.form.password)) {this.errors.password = '密码必须包含数字和字母';return false;}this.errors.password = '';return true;},// 验证确认密码validateConfirmPassword() {if (!this.form.confirmPassword) {this.errors.confirmPassword = '请确认密码';return false;}if (this.form.confirmPassword !== this.form.password) {this.errors.confirmPassword = '两次输入的密码不一致';return false;}this.errors.confirmPassword = '';return true;},// 验证手机号validateMobile() {if (!this.form.mobile) {this.errors.mobile = '手机号不能为空';return false;}// 中国大陆手机号正则表达式const mobilePattern = /^1[3-9]\d{9}$/;if (!mobilePattern.test(this.form.mobile)) {this.errors.mobile = '请输入有效的手机号码';return false;}this.errors.mobile = '';return true;},// 验证邮箱validateEmail() {if (!this.form.email) {this.errors.email = '邮箱不能为空';return false;}// 邮箱正则表达式const emailPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;if (!emailPattern.test(this.form.email)) {this.errors.email = '请输入有效的邮箱地址';return false;}this.errors.email = '';return true;},// 验证用户协议validateAgree() {if (!this.form.agree) {this.errors.agree = '请同意用户协议';return false;}this.errors.agree = '';return true;},// 验证所有字段validateForm() {const usernameValid = this.validateUsername();const passwordValid = this.validatePassword();const confirmPasswordValid = this.validateConfirmPassword();const mobileValid = this.validateMobile();const emailValid = this.validateEmail();const agreeValid = this.validateAgree();return usernameValid && passwordValid && confirmPasswordValid && mobileValid && emailValid && agreeValid;},// 提交表单submitForm() {// 先清空所有错误信息for (let key in this.errors) {this.errors[key] = '';}// 验证表单if (!this.validateForm()) {uni.showToast({title: '请正确填写表单信息',icon: 'none'});return;}// 验证通过,可以进行提交操作uni.showLoading({title: '提交中...'});// 模拟提交请求setTimeout(() => {uni.hideLoading();uni.showToast({title: '注册成功',icon: 'success'});// 重置表单或跳转页面// this.resetForm();// uni.navigateTo({ url: '/pages/login/login' });}, 1500);},// 重置表单resetForm() {this.form = {username: '',password: '',confirmPassword: '',mobile: '',email: '',agree: false};for (let key in this.errors) {this.errors[key] = '';}}}
}

对应的模板部分可以这样编写:

<template><view class="register-form"><view class="form-item"><text class="label">用户名</text><input class="input" v-model="form.username" placeholder="请输入用户名" @blur="validateUsername" /><text v-if="errors.username" class="error-tip">{{ errors.username }}</text></view><view class="form-item"><text class="label">密码</text><input class="input" v-model="form.password" type="password" placeholder="请输入密码" @blur="validatePassword" /><text v-if="errors.password" class="error-tip">{{ errors.password }}</text></view><view class="form-item"><text class="label">确认密码</text><input class="input" v-model="form.confirmPassword" type="password" placeholder="请再次输入密码" @blur="validateConfirmPassword" /><text v-if="errors.confirmPassword" class="error-tip">{{ errors.confirmPassword }}</text></view><view class="form-item"><text class="label">手机号</text><input class="input" v-model="form.mobile" type="number" placeholder="请输入手机号" @blur="validateMobile" /><text v-if="errors.mobile" class="error-tip">{{ errors.mobile }}</text></view><view class="form-item"><text class="label">邮箱</text><input class="input" v-model="form.email" placeholder="请输入邮箱" @blur="validateEmail" /><text v-if="errors.email" class="error-tip">{{ errors.email }}</text></view><view class="form-item checkbox-item"><checkbox v-model="form.agree" /><text class="agreement-text" @click="form.agree = !form.agree">我已阅读并同意《用户协议》</text><text v-if="errors.agree" class="error-tip">{{ errors.agree }}</text></view><button class="submit-btn" type="primary" @click="submitForm">立即注册</button></view>
</template>

并添加一些基本样式:

<style scoped>
.register-form {padding: 30rpx;
}.form-item {margin-bottom: 40rpx;position: relative;
}.label {display: block;margin-bottom: 10rpx;font-size: 28rpx;color: #333;
}.input {width: 100%;height: 80rpx;border: 1rpx solid #dcdfe6;border-radius: 8rpx;padding: 0 20rpx;box-sizing: border-box;font-size: 28rpx;
}.error-tip {position: absolute;left: 0;bottom: -36rpx;font-size: 24rpx;color: #f56c6c;
}.checkbox-item {display: flex;align-items: center;
}.agreement-text {font-size: 26rpx;margin-left: 10rpx;
}.submit-btn {margin-top: 60rpx;
}
</style>

方式二:使用 async-validator 库

对于复杂的验证需求,使用成熟的验证库会更加便捷。async-validator 是一个流行的表单验证库,支持丰富的验证规则和自定义验证功能。

首先,安装依赖:

npm install async-validator --save

然后,在组件中使用:

import Schema from 'async-validator';export default {data() {return {// 表单数据form: {username: '',password: '',confirmPassword: '',mobile: '',email: '',agree: false},// 错误信息errors: {}}},computed: {// 定义验证规则rules() {return {username: [{ required: true, message: '用户名不能为空' },{ min: 3, max: 20, message: '用户名长度应为3-20个字符' }],password: [{ required: true, message: '密码不能为空' },{ min: 6, message: '密码长度不能少于6个字符' },{ pattern: /^(?=.*[0-9])(?=.*[a-zA-Z]).{6,}$/, message: '密码必须包含数字和字母' }],confirmPassword: [{ required: true, message: '请确认密码' },{ validator: (rule, value, callback) => {if (value !== this.form.password) {callback(new Error('两次输入的密码不一致'));} else {callback();}} }],mobile: [{ required: true, message: '手机号不能为空' },{ pattern: /^1[3-9]\d{9}$/, message: '请输入有效的手机号码' }],email: [{ required: true, message: '邮箱不能为空' },{ type: 'email', message: '请输入有效的邮箱地址' }],agree: [{ validator: (rule, value, callback) => {if (!value) {callback(new Error('请同意用户协议'));} else {callback();}} }]};}},methods: {// 验证单个字段validateField(field) {const descriptor = {};descriptor[field] = this.rules[field];const validator = new Schema(descriptor);const source = {};source[field] = this.form[field];validator.validate(source, (errors) => {if (errors) {// 有错误this.$set(this.errors, field, errors[0].message);} else {// 没有错误this.$set(this.errors, field, '');}});},// 验证所有字段validateForm() {return new Promise((resolve, reject) => {const validator = new Schema(this.rules);validator.validate(this.form, (errors) => {if (errors) {// 有错误const errorObj = {};errors.forEach(error => {errorObj[error.field] = error.message;});this.errors = errorObj;resolve(false);} else {// 验证通过this.errors = {};resolve(true);}});});},// 提交表单async submitForm() {const valid = await this.validateForm();if (!valid) {uni.showToast({title: '请正确填写表单信息',icon: 'none'});return;}// 验证通过,可以进行提交操作uni.showLoading({title: '提交中...'});// 模拟提交请求setTimeout(() => {uni.hideLoading();uni.showToast({title: '注册成功',icon: 'success'});// 重置表单或跳转页面// this.resetForm();// uni.navigateTo({ url: '/pages/login/login' });}, 1500);},// 重置表单resetForm() {this.form = {username: '',password: '',confirmPassword: '',mobile: '',email: '',agree: false};this.errors = {};}}
}

模板部分可以与前面的例子类似,只需要修改验证方法的调用:

<input class="input" v-model="form.username" placeholder="请输入用户名" @blur="validateField('username')" />

表单提交功能的实现

表单验证通过后,我们需要将数据提交到服务器。在 UniApp 中,可以使用 uni.request() 方法发送网络请求。

下面是一个完整的表单提交示例:

// 提交表单
async submitForm() {const valid = await this.validateForm();if (!valid) {uni.showToast({title: '请正确填写表单信息',icon: 'none'});return;}// 显示加载提示uni.showLoading({title: '提交中...'});try {// 发送请求const res = await uni.request({url: 'https://api.example.com/register',method: 'POST',data: this.form,header: {'content-type': 'application/json'}});// 请求成功if (res.statusCode === 200 && res.data.code === 0) {uni.hideLoading();uni.showToast({title: '注册成功',icon: 'success'});// 存储登录信息uni.setStorageSync('token', res.data.data.token);uni.setStorageSync('userInfo', res.data.data.userInfo);// 跳转到首页setTimeout(() => {uni.switchTab({url: '/pages/index/index'});}, 1500);} else {throw new Error(res.data.message || '注册失败');}} catch (error) {uni.hideLoading();uni.showToast({title: error.message || '网络错误,请稍后重试',icon: 'none'});}
}

实战案例:会员信息编辑表单

下面是一个完整的会员信息编辑表单案例,综合了表单验证和提交功能:

<template><view class="profile-form"><view class="form-header"><view class="avatar-wrapper"><image class="avatar" :src="form.avatar || '/static/default-avatar.png'" @click="chooseAvatar"></image><text class="edit-hint">点击修改头像</text></view></view><view class="form-content"><view class="form-item"><text class="label">姓名</text><input class="input" v-model="form.name" placeholder="请输入您的姓名" @blur="validateField('name')" /><text v-if="errors.name" class="error-tip">{{ errors.name }}</text></view><view class="form-item"><text class="label">性别</text><view class="radio-group"><view class="radio-item" @click="form.gender = 1"><view class="radio-box" :class="{ 'checked': form.gender === 1 }"></view><text class="radio-label">男</text></view><view class="radio-item" @click="form.gender = 2"><view class="radio-box" :class="{ 'checked': form.gender === 2 }"></view><text class="radio-label">女</text></view></view></view><view class="form-item"><text class="label">手机号</text><input class="input" v-model="form.mobile" type="number" placeholder="请输入手机号" @blur="validateField('mobile')" /><text v-if="errors.mobile" class="error-tip">{{ errors.mobile }}</text></view><view class="form-item"><text class="label">邮箱</text><input class="input" v-model="form.email" placeholder="请输入邮箱" @blur="validateField('email')" /><text v-if="errors.email" class="error-tip">{{ errors.email }}</text></view><view class="form-item"><text class="label">生日</text><picker mode="date" :value="form.birthday" @change="onBirthdayChange"><view class="picker-box"><text class="picker-text">{{ form.birthday || '请选择出生日期' }}</text><text class="picker-arrow">></text></view></picker></view><view class="form-item"><text class="label">地址</text><textarea class="textarea" v-model="form.address" placeholder="请输入您的详细地址" @blur="validateField('address')" /><text v-if="errors.address" class="error-tip">{{ errors.address }}</text></view><view class="form-item"><text class="label">个人简介</text><textarea class="textarea" v-model="form.bio" placeholder="介绍一下自己吧(选填)" /></view></view><button class="submit-btn" type="primary" @click="submitForm">保存修改</button></view>
</template><script>
import Schema from 'async-validator';export default {data() {return {// 表单数据form: {avatar: '',name: '',gender: 1, // 1-男,2-女mobile: '',email: '',birthday: '',address: '',bio: ''},// 错误信息errors: {}}},computed: {// 定义验证规则rules() {return {name: [{ required: true, message: '姓名不能为空' },{ max: 20, message: '姓名长度不能超过20个字符' }],mobile: [{ required: true, message: '手机号不能为空' },{ pattern: /^1[3-9]\d{9}$/, message: '请输入有效的手机号码' }],email: [{ required: true, message: '邮箱不能为空' },{ type: 'email', message: '请输入有效的邮箱地址' }],address: [{ required: true, message: '地址不能为空' },{ max: 100, message: '地址长度不能超过100个字符' }]};}},onLoad() {// 获取用户信息(示例数据)const userInfo = {avatar: '/static/avatar.png',name: '张三',gender: 1,mobile: '13800138000',email: 'zhangsan@example.com',birthday: '1990-01-01',address: '北京市朝阳区某某街道某某小区',bio: '热爱生活,热爱编程。'};// 填充表单this.form = { ...userInfo };},methods: {// 选择头像chooseAvatar() {uni.chooseImage({count: 1,sizeType: ['compressed'],sourceType: ['album', 'camera'],success: (res) => {const tempFilePaths = res.tempFilePaths;this.form.avatar = tempFilePaths[0];// 实际场景中应该先上传图片,再获取图片的URLthis.uploadAvatar(tempFilePaths[0]);}});},// 上传头像uploadAvatar(filePath) {uni.showLoading({title: '上传中...'});// 模拟上传setTimeout(() => {uni.hideLoading();uni.showToast({title: '头像上传成功',icon: 'success'});// 实际场景中,这里应该返回服务器的图片URL// this.form.avatar = res.data.url;}, 1500);},// 生日改变onBirthdayChange(e) {this.form.birthday = e.detail.value;},// 验证单个字段validateField(field) {if (!this.rules[field]) return;const descriptor = {};descriptor[field] = this.rules[field];const validator = new Schema(descriptor);const source = {};source[field] = this.form[field];validator.validate(source, (errors) => {if (errors) {// 有错误this.$set(this.errors, field, errors[0].message);} else {// 没有错误this.$set(this.errors, field, '');}});},// 验证所有字段validateForm() {return new Promise((resolve, reject) => {const validator = new Schema(this.rules);validator.validate(this.form, (errors) => {if (errors) {// 有错误const errorObj = {};errors.forEach(error => {errorObj[error.field] = error.message;});this.errors = errorObj;resolve(false);} else {// 验证通过this.errors = {};resolve(true);}});});},// 提交表单async submitForm() {const valid = await this.validateForm();if (!valid) {uni.showToast({title: '请正确填写表单信息',icon: 'none'});return;}// 显示加载提示uni.showLoading({title: '保存中...'});// 模拟提交请求setTimeout(() => {uni.hideLoading();uni.showToast({title: '保存成功',icon: 'success'});// 返回上一页setTimeout(() => {uni.navigateBack();}, 1500);}, 1500);/* 实际场景中的提交代码try {const res = await uni.request({url: 'https://api.example.com/update-profile',method: 'POST',data: this.form,header: {'content-type': 'application/json','Authorization': `Bearer ${uni.getStorageSync('token')}`}});if (res.statusCode === 200 && res.data.code === 0) {uni.hideLoading();uni.showToast({title: '保存成功',icon: 'success'});// 更新本地存储的用户信息uni.setStorageSync('userInfo', res.data.data.userInfo);// 返回上一页setTimeout(() => {uni.navigateBack();}, 1500);} else {throw new Error(res.data.message || '保存失败');}} catch (error) {uni.hideLoading();uni.showToast({title: error.message || '网络错误,请稍后重试',icon: 'none'});}*/}}
}
</script><style scoped>
.profile-form {padding: 30rpx;
}.form-header {display: flex;justify-content: center;margin-bottom: 50rpx;
}.avatar-wrapper {display: flex;flex-direction: column;align-items: center;
}.avatar {width: 150rpx;height: 150rpx;border-radius: 50%;margin-bottom: 10rpx;
}.edit-hint {font-size: 24rpx;color: #666;
}.form-content {margin-bottom: 40rpx;
}.form-item {margin-bottom: 40rpx;position: relative;
}.label {display: block;margin-bottom: 10rpx;font-size: 28rpx;color: #333;
}.input, .textarea, .picker-box {width: 100%;border: 1rpx solid #dcdfe6;border-radius: 8rpx;padding: 0 20rpx;box-sizing: border-box;font-size: 28rpx;
}.input, .picker-box {height: 80rpx;line-height: 80rpx;
}.textarea {height: 160rpx;padding: 20rpx;line-height: 1.5;
}.picker-box {display: flex;justify-content: space-between;align-items: center;
}.picker-text {color: #333;
}.picker-arrow {color: #999;transform: rotate(90deg);
}.radio-group {display: flex;margin-top: 10rpx;
}.radio-item {display: flex;align-items: center;margin-right: 50rpx;
}.radio-box {width: 40rpx;height: 40rpx;border: 2rpx solid #dcdfe6;border-radius: 50%;display: flex;justify-content: center;align-items: center;box-sizing: border-box;position: relative;
}.radio-box.checked {border-color: #2979ff;
}.radio-box.checked:after {content: '';width: 20rpx;height: 20rpx;border-radius: 50%;background-color: #2979ff;position: absolute;
}.radio-label {margin-left: 10rpx;font-size: 28rpx;
}.error-tip {position: absolute;left: 0;bottom: -36rpx;font-size: 24rpx;color: #f56c6c;
}.submit-btn {margin-top: 60rpx;
}
</style>

表单验证的最佳实践

  1. 实时验证与提交验证结合:在输入框失去焦点时进行单个字段验证,在表单提交时进行全表单验证
  2. 友好的错误提示:错误信息应该清晰明了,位置合适
  3. 良好的用户体验:添加适当的过渡效果,不要让错误提示突兀出现
  4. 避免重复验证:已验证过且符合要求的字段无需重复验证
  5. 表单防抖:防止用户频繁点击提交按钮
  6. 状态保持:表单提交失败后不要清空用户输入
  7. 进度提示:使用加载提示,让用户知道表单正在提交

总结

本文介绍了在 UniApp 中实现表单验证与提交功能的多种方式,包括自定义验证和使用第三方库验证。我们通过实例详细讲解了各种验证规则的编写,以及表单提交的完整流程。

表单验证看似简单,但实际上涉及众多细节,一个设计良好的表单验证系统能极大提升用户体验。希望本文对你在 UniApp 中开发表单功能有所帮助。

在实际项目中,你可能需要根据业务需求进行更多定制化的开发,例如添加更复杂的验证规则、优化表单的交互效果、处理更多的表单场景等。不论如何变化,本文提供的基本思路和方法都是适用的。

进一步思考

  • 如何处理更复杂的表单依赖验证?(例如,当选择A选项时,B字段必填)
  • 如何处理文件上传类型的表单字段?
  • 如何优化大型复杂表单的性能?
  • 如何实现多步骤表单?

这些都是表单开发中的进阶话题,欢迎在实践中探索更多解决方案。

相关文章:

鸿蒙OSUniApp 实现的表单验证与提交功能#三方框架 #Uniapp

UniApp 实现的表单验证与提交功能 前言 在移动端应用开发中&#xff0c;表单是用户与应用交互的重要媒介。一个好的表单不仅布局合理、使用方便&#xff0c;还应该具备完善的验证与提交功能&#xff0c;以确保用户输入的数据准确无误。本文将分享如何在 UniApp 中实现表单验证…...

开源的跨语言GUI元素理解8B大模型:AgentCPM-GUI

一、模型概述 AgentCPM-GUI 是由清华大学自然语言处理实验室 (THUNLP) 和 ModelBest 联合开发的开源大模型。该模型基于 MiniCPM-V 架构&#xff0c;拥有 80 亿参数规模&#xff0c;是一个能够直接在终端设备上运行的轻量化智能体。它创新性地将多模态输入与 GUI 操作相结合&a…...

Function Calling

在介绍Function Calling之前我们先了解一个概念,接口。 接口 两种常见接口: 人机交互接口,User Interface,简称 UI应用程序编程接口,Application Programming Interface,简称 API接口能「通」的关键,是两边都要遵守约定。 人要按照 UI 的设计来操作。UI 的设计要符合人…...

星巴克中国要卖在高点

9%能否救70%的急&#xff1f; 作者|古廿 编辑|文昌龙 星巴克中国刚刚回暖&#xff0c;总部出售的计划再次提上日程。 5月15日&#xff0c;外媒又适时放出消息&#xff1a;星巴克将开始出售其在中国的股份。消息人士称&#xff0c;星巴克本周通过一位财务顾问向几位潜在投资…...

Docker实现MySQL数据库主从复制

一、拉取数据库镜像 docker pull mysql:5.7二、创建两个数据库(一主一从模式) mysql01&#xff08;主&#xff09; 1.docker run -d -p 3310:3306 -v /root/mysql/node-1/init:/docker-entrypoinit-initdb.d -v /root/mysql/node-1/config:/etc/mysql/conf.d -v /root/mysq…...

【物联网】基于树莓派的物联网开发【4】——WIFI+SSH远程登录树莓派

使用背景 没有有线网络&#xff0c;无屏幕如何远程登录&#xff1f;程序猫教大家如何通过电脑wifi热点的方式连接树莓派&#xff0c;ssh连接访问树莓派&#xff0c;包括putty开源远程工具进行连接&#xff0c;VNC远程桌面显示。 注&#xff1a;新手建议买一个树莓派配置的显示…...

CentOS7 OpenSSL升级1.1.1w

1.安装依赖 # openssl-3.4.0需要perl-IPC-Cmd perl-Data-Dumper yum -y install gcc* yum -y install perl-IPC-Cmd perl-Data-Dumper 2.备份、卸载旧OpenSSL 查找安装目录并备份 # whereis openssl openssl: /usr/bin/openssl /usr/lib64/openssl /usr/share/man/man1/op…...

高精度降压稳压技术在现代工业自动化中的应用

一、引言 在现代工业自动化的浪潮中&#xff0c;电源管理技术犹如隐藏在精密机械背后的智囊&#xff0c;虽不直接参与生产流程的逻辑决策&#xff0c;却是保障各类自动化设备稳定、高效运行的基石。高精度降压稳压技术&#xff0c;作为电源管理领域的核心分支&#xff0c;聚焦…...

鸿蒙OSUniApp制作动态筛选功能的列表组件(鸿蒙系统适配版)#三方框架 #Uniapp

使用UniApp制作动态筛选功能的列表组件&#xff08;鸿蒙系统适配版&#xff09; 前言 随着移动应用的普及&#xff0c;用户对应用内容检索和筛选的需求也越来越高。在开发跨平台应用时&#xff0c;动态筛选功能已成为提升用户体验的重要组成部分。本文将详细介绍如何使用UniA…...

Qt中控件的Viewport作用

在Qt中&#xff0c;viewport是控件中用于显示内容的一个概念区域&#xff0c;它在可滚动控件中尤为重要。以下是viewport的主要作用和特点&#xff1a; 主要作用 内容显示区域&#xff1a;viewport定义了控件中实际可见的部分&#xff0c;所有内容都在这个区域内显示。 滚动机…...

论文学习_Precise and Accurate Patch Presence Test for Binaries

摘要&#xff1a;打补丁是应对软件漏洞的主要手段&#xff0c;及时将补丁应用到所有受影响的软件上至关重要&#xff0c;然而这一点在实际中常常难以做到&#xff0c;研究背景。因此&#xff0c;准确检测安全补丁是否已被集成进软件发行版本的能力&#xff0c;对于防御者和攻击…...

ubuntu服务器版启动卡在start job is running for wait for...to be Configured

目录 前言 一、原因分析 二、解决方法 总结 前言 当 Ubuntu 服务器启动时&#xff0c;系统会显示类似 “start job is running for wait for Network to be Configured” 或 “start job is running for wait for Plymouth Boot Screen Service” 等提示信息&#xff0c;并且…...

国产数据库工具突围:SQLynx如何解决Navicat的三大痛点?深度体验报告

引言&#xff1a;Navicat的"中国困境" 当开发者面对达梦数据库的存储过程调试&#xff0c;或是在人大金仓中处理复杂查询时&#xff0c;Navicat突然变得力不从心——这不是个例。 真实痛点&#xff1a;某政务系统迁移至OceanBase后&#xff0c;开发团队发现Navicat无…...

牛客网NC21994:分钟计算

牛客网NC21994&#xff1a;分钟计算 &#x1f4dd; 题目描述 输入格式 输入两行&#xff0c;每行包含两个整数&#xff0c;分别表示小时和分钟第一行表示起始时间&#xff0c;第二行表示结束时间 输出格式 输出一个整数&#xff0c;表示两个时间点之间的分钟数 示例 输入…...

全球宠物经济新周期下的亚马逊跨境采购策略革新——宠物用品赛道成本优化三维路径

在全球"孤独经济"与"银发经济"双轮驱动下&#xff0c;宠物用品市场正经历结构性增长。Euromonitor数据显示&#xff0c;2023年全球市场规模突破1520亿美元&#xff0c;其中中国供应链贡献度达38%&#xff0c;跨境电商出口增速连续三年超25%。在亚马逊流量红…...

Tomcat多应用部署与静态资源路径问题全解指南

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家、CSDN平台优质创作者&#xff0c;高级开发工程师&#xff0c;数学专业&#xff0c;10年以上C/C, C#, Java等多种编程语言开发经验&#xff0c;拥有高级工程师证书&#xff1b;擅长C/C、C#等开发语言&#xff0c;熟悉Java常用开…...

128.在 Vue 3 中使用 OpenLayers 实现绘制矩形截图并保存地图区域

&#x1f4cc; 本文将介绍如何在 Vue 3 中使用 OpenLayers 实现&#xff1a; 1&#xff09;用户可在地图上绘制矩形&#xff1b; 2&#xff09;自动截取该区域地图为图片&#xff1b; 3&#xff09;一键保存为本地 PNG 图片。 ✨效果如下图所示 &#x1f9e0;一、前言 在地图类…...

使用 163 邮箱实现 Spring Boot 邮箱验证码登录

使用 163 邮箱实现 Spring Boot 邮箱验证码登录 本文将详细介绍如何使用网易 163 邮箱作为 SMTP 邮件服务器&#xff0c;实现 Spring Boot 项目中的邮件验证码发送功能&#xff0c;并解决常见配置报错问题。 一、为什么需要邮箱授权码&#xff1f; 出于安全考虑&#xff0c;大…...

python处理异常,JSON

异常处理 #异常处理 # 在连接MySQL数据库的过程中&#xff0c;如果不能有效地处理异常&#xff0c;则异常信息过于复杂&#xff0c;对用户不友好&#xff0c;暴露过多的敏感信息 # 所以&#xff0c;在真实的生产环境中&#xff0c; 程序必须有效地处理和控制异常&#xff0c;按…...

原生微信小程序 textarea组件placeholder无法换行的问题解决办法

【问题描述】 微信小程序原生代码&#xff0c;使用文本域&#xff0c;placeholder使用\n 没有效果&#xff0c;网上找了一堆方案说使用 也没有效果 最后在一个前端大佬博客&#xff0c;找到解决办法&#xff0c;CSS设置word-wrap: break-word; white-space: pre-line; 【解决办…...

毕设设计 | 管理系统图例

文章目录 环素1. 登录、注册2. 菜单管理 环素 1. 登录、注册 2. 菜单管理 公告通知 订单管理 会员管理 奖品管理 新增、编辑模块...

激光雷达视觉定位是3D视觉定位吗?

激光雷达视觉定位通常被归类为3D视觉定位&#xff0c;但具体来说&#xff0c;它是融合了激光雷达&#xff08;LiDAR&#xff09;数据和视觉&#xff08;图像&#xff09;数据的多模态3D定位方法。我们可以从几个角度来理解这点&#xff1a; 为什么说它属于3D视觉定位&#xff…...

每周靶点:NY-ESO-1、GPC3、IL27分享

本期精选了《自身免疫性癌抗原NY-ESO-1》《肝细胞癌标记物GPC3》《白细胞介素IL27》三篇文章。以下为各研究内容的概述&#xff1a; 自身免疫性癌抗原NY-ESO-1 NY-ESO-1是一种自身免疫性癌抗原&#xff0c;也称为CTA1B&#xff08;CTAG1B&#xff09;&#xff0c;由主要组织相…...

Maven 插件参数注入与Mojo开发详解

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…...

Java详解RabbitMQ工作模式之发布订阅模式

目录 一、发布订阅模式简介二、发布订阅模式的工作原理2.1 核心组件2.2 工作流程 三、代码示例3.1 生产者代码3.2 消费者代码 四、实际应用场景五、注意事项六、总结 在分布式系统中&#xff0c;消息队列作为异步通信的桥梁&#xff0c;扮演着至关重要的角色。而 RabbitMQ&…...

UR5e机器人Matlab仿真

在 MATLAB 中使用 UR5e 机器人模型进行仿真和控制&#xff0c;通常需要结合机器人系统工具箱&#xff08;Robotics System Toolbox&#xff09; UR5e loadrobot("universalUR5e","DataFormat","column"); UR5e.Gravity [0 0 -9.81]; % 保存机器…...

[ctfshow web入门] web75

信息收集 scandir被禁用了 解题 cforeach(new DirectoryIterator("glob:///*") as $a){echo($a->__toString(). ); } ob_flush();cif ( $a opendir("glob:///*") ) {while ( ($file readdir($a)) ! false ) {echo $file."<br>";}c…...

论文中表格跨页该怎么整(如何给跨页表格添加标题和表头)

标题&#xff1a;光标移动到第一行表格&#xff0c;然后快捷键;ctrl shirft enter&#xff0c;就会发现第二页多了一行&#xff0c;再把标题复制张贴过来即可 表头&#xff1a; 光标移动到第一行表格&#xff0c;鼠标右键 选择插入 再选择在上方插入行&#xff0c;然后手动添加…...

day26 Python 自定义函数

目录 一、函数的基本定义 示例 1&#xff1a;不带参数的函数 示例 2&#xff1a;查看文档字符串 二、带参数的函数 示例 3&#xff1a;带一个参数的函数 示例 4&#xff1a;带多个参数的函数 三、带返回值的函数 示例 5&#xff1a;计算两个数的和并返回结果 示例 6&am…...

洛谷P4907题解

题目传送门 题意&#xff1a; 扑克牌的部分牌被移除&#xff0c;需从剩牌中选 4 个区间&#xff0c;每个区间的牌都是同一花色且点数连续。如果不可选&#xff0c;输出最少需添加几张牌才能满足要求。 思路&#xff1a; 暴力和剪枝。 暴力&#xff1a;按照题意模拟&#xff…...

【MyBatis插件】PageHelper 分页

前言 在开发 Web 应用时&#xff0c;我们经常需要处理海量数据的展示问题。例如&#xff0c;在一个电商平台上&#xff0c;商品列表可能有成千上万条数据。如果我们一次性将所有数据返回给前端&#xff0c;不仅会导致页面加载缓慢&#xff0c;还会对数据库造成巨大压力。为了解…...

AI数字人融合VR全景:从技术突破到可信场景落地

摘要 本文深度解析AI数字人与VR全景技术融合的技术架构&#xff0c;结合故宫博物院、西门子、强生等真实行业案例&#xff0c;揭示技术落地的关键路径与量化价值。通过具体技术参数、实施细节及权威机构数据&#xff0c;构建可信的技术应用图景&#xff0c;为开发者提供可复用…...

机器学习——朴素贝叶斯练习题

一、 使用鸢尾花数据训练多项式朴素贝叶斯模型&#xff0c;并评估模型 代码展示&#xff1a; from sklearn.datasets import load_iris from sklearn.metrics import accuracy_score from sklearn.model_selection import train_test_split from sklearn.naive_bayes impor…...

【爬虫】DrissionPage-3

安装&#xff1a;4.1最新版本 pip install drissionpage --upgrade 官方文档&#xff1a;&#x1f6f0;️ 连接浏览器 | DrissionPage官网 1 Chromium对象 Chromium对象用于连接和管理浏览器。标签页的开关和获取、整体运行参数配置、浏览器信息获取等都由它进行。 1.1 默认…...

网络爬虫学习之httpx的使用

开篇 本文整理自《Python3 网络爬虫实战》&#xff0c;主要是httpx的使用。 笔记整理 使用urllib库requests库的使用&#xff0c;已经可以爬取绝大多数网站的数据&#xff0c;但对于某些网站依然无能为力。 这是因为这些网站强制使用HTTP/2.0协议访问&#xff0c;这时urllib和r…...

TASK02【Datawhale 组队学习】使用 LLM API 开发应用

文章目录 system prompt 和 user prompt高效prompt&#xff1a;用清晰、详尽的语言表达 Prompt原则一&#xff1a;清晰&#xff0c;具体的指令分隔符寻求结构化的输出要求模型检查是否满足条件提供少量示例 "Few-shot" prompting 原则二&#xff0c;给模型时间去思考…...

黑马k8s(七)

1.Pod介绍 查看版本&#xff1a; 查看类型,这里加s跟不加s没啥区别&#xff0c;可加可不加 2.Pod基本配置 3.镜像拉去策略 本地没有这个镜像&#xff0c;策略是Never&#xff0c;启动失败 查看拉去策略&#xff1a; 更改拉去策略&#xff1a; 4.启动命令 运行的是nginx、busv…...

【FMC216】基于 VITA57.1 的 2 路 TLK2711 发送、2 路 TLK2711 接收 FMC 子卡模块

产品概述 FMC216 是一款基于 VITA57.1 标准规范的 2 路 TLK2711 接收、2 路 TLK2711 发送 FMC 子卡模块。该板卡支持 2 路 TLK2711 数据的收发&#xff0c;支持线速率 1.6Gbps&#xff0c;经过 TLK2711 高速串行收发器&#xff0c;可以将 1.6Gbps 的高速串行数据解串为 16 位并…...

如何在Edge浏览器里-安装梦精灵AI提示词管理工具

方案一&#xff08;应用中心安装-推荐&#xff09;&#xff1a; 梦精灵 跨平台AI提示词管理工具 - Microsoft Edge AddonsMake Microsoft Edge your own with extensions that help you personalize the browser and be more productive.https://microsoftedge.microsoft.com…...

Ubuntu shell指定conda的python环境启动脚本

Ubuntu shell指定conda的python环境启动脚本。 通过指令&#xff0c;获取目前系统的conda虚拟python环境 conda info -e 如下图所示&#xff0c;为我自己电脑的python环境 # conda environments: # base * /home/ubuntu/miniconda3 kitti …...

深入理解无监督学习与K-means聚类算法:原理与实践

一、无监督学习概述 无监督学习(Unsupervised Learning)是机器学习的重要分支之一&#xff0c;与有监督学习不同&#xff0c;它不需要预先标记的训练数据。在无监督学习中&#xff0c;计算机仅根据样本的特征或样本间的相关性&#xff0c;从数据中自动发现隐藏的模式或结构。 …...

单片机-STM32部分:16、Git工具使用

Docshttps://x509p6c8to.feishu.cn/wiki/Pftrw3Z6niRlewkurnyctyw1nQx 使用Git管理本地仓库的好处是&#xff0c;可以知道自己每次修改了哪些内容&#xff0c;随时进行版本切换。 待完善。...

扬州卓韵酒店用品:优质洗浴用品,提升酒店满意度与品牌形象

在酒店提供的服务里&#xff0c;沐浴用品占据了非常重要的地位&#xff0c;其质量与种类直接关系到客人洗澡时的感受。好的沐浴用品能让客人洗澡时感到舒心和快乐&#xff0c;反之&#xff0c;质量不好的用品可能会影响客人整个住宿期间的愉悦心情。挑选恰当的洗浴用品不仅能够…...

Coze 实战教程 | 10 分钟打造你的AI 助手

> 文章中的 xxx 自行替换&#xff0c;文章被屏蔽了。 &#x1f4f1; 想让你的xxx具备 AI 对话能力&#xff1f;本篇将手把手教你&#xff0c;如何用 Coze 平台快速构建一个能与用户自然交流、自动回复提问的 xxx助手&#xff0c;零代码、超高效&#xff01; &#x1f4cc;…...

使用 frp 实现内网穿透:从基础到进阶

在日常开发中&#xff0c;我们经常会遇到需要将本地服务暴露给外部用户的情况&#xff0c;比如测试同学需要临时测试一个本地开发的 Web 服务&#xff0c;或者希望在出差时远程访问家里的 NAS。这些需求的核心问题都是如何实现内网穿透。 一、为什么选择 frp&#xff1f; 经过…...

redis中key的过期和淘汰

一、过期&#xff08;redis主动删除&#xff09; 设置了ttl过期时间的key&#xff0c;在ttl时间到的时候redis会删除过期的key。但是redis是惰性过期。惰性过期&#xff1a;redis并不会立即删除过期的key&#xff0c;而是会在获取key的时候判断key是否过期&#xff0c;如果发现…...

鸿蒙OSUniApp制作多选框与单选框组件#三方框架 #Uniapp

使用UniApp制作多选框与单选框组件 前言 在移动端应用开发中&#xff0c;表单元素是用户交互的重要组成部分。尤其是多选框&#xff08;Checkbox&#xff09;和单选框&#xff08;Radio&#xff09;&#xff0c;它们几乎存在于每一个需要用户做出选择的场景中。虽然UniApp提供…...

和为target问题汇总

文章目录 习题题型1377.组合总和 IV 题型2494.目标和 和为target的问题&#xff0c;可以有很多种问题的形式的考察&#xff0c;当然&#xff0c;及时的总结与回顾有利于我们熟练掌握这些知识&#xff01; 题型1 爬楼梯问题&#xff0c;是对于转移步伐有规定&#xff0c;在不同…...

Ubuntu使用Docker搭建SonarQube企业版(含破解方法)

目录 Ubuntu使用Docker搭建SonarQube企业版&#xff08;含破解方法&#xff09;SonarQube介绍安装Docker安装PostgreSQL容器Docker安装SonarQube容器SonarQube汉化插件安装 破解生成license配置agent 使用 Ubuntu使用Docker搭建SonarQube企业版&#xff08;含破解方法&#xff…...

牛客网 NC22167: 多组数据a+b

牛客网 NC22167: 多组数据ab 题目分析 这道题目来自牛客网&#xff08;题号&#xff1a;NC22167&#xff09;&#xff0c;要求我们计算两个整数a和b的和。乍看简单&#xff0c;但有以下特殊点需要注意&#xff1a; 输入包含多组测试数据每组输入两个整数当两个整数都为0时表示…...