效果图
备注
新能源输入 车牌 输入规则 第三位必为 D 或 F ,第四位可以是字母也可以是数字 但最后四位必为数字,
在测车牌号校验时 总提示输入错误,最后才发现 上面的输入规则
代码
<template>
<view class="container">
<view class="form userform">
<view class="username">
<input style="width: 70%;" placeholder="请输入手机号" v-model="mobileNumber" />
<view class="get-code" :style="{'color':getCodeBtnColor}" @click.stop="getCode()">{{getCodeText}}
</view>
</view>
<view class="code">
<input placeholder="请输入验证码" v-model="code" />
</view>
<view class="car_number_input">
请输入车牌号
<view class="car_type" @click.stop="keyShow = !keyShow">
<view class="default_car">
<view class="" v-show="carNumber[0]">
{{carNumber[0]}}
</view>
<view class="line" v-show="!carNumber[0]">
__
</view>
</view>
<view class="default_car">
<view class="" v-show="carNumber[1]">
{{carNumber[1]}}
</view>
<view class="line" v-show="carNumber[0] && !carNumber[1]">
__
</view>
</view>
<view class="default_car">
<view class="" v-show="carNumber[2]">
{{carNumber[2]}}
</view>
<view class="line" v-show="carNumber[0] && carNumber[1] && !carNumber[2]">
__
</view>
</view>
<view class="default_car">
<view class="" v-show="carNumber[3]">
{{carNumber[3]}}
</view>
<view class="line" v-show="carNumber[0] && carNumber[1] && carNumber[2] && !carNumber[3]">
__
</view>
</view>
<view class="default_car">
<view class="" v-show="carNumber[4]">
{{carNumber[4]}}
</view>
<view class="line" v-show="carNumber[0] && carNumber[1] && carNumber[2] && carNumber[3] && !carNumber[4]">
__
</view>
</view>
<view class="default_car">
<view class="" v-show="carNumber[5]">
{{carNumber[5]}}
</view>
<view class="line"
v-show="carNumber[0] && carNumber[1] && carNumber[2] && carNumber[3] && carNumber[4] && !carNumber[5]">
__
</view>
</view>
<view class="default_car">
<view class="" v-show="carNumber[6]">
{{carNumber[6]}}
</view>
<view class="line"
v-show="carNumber[0] && carNumber[1] && carNumber[2] && carNumber[3] && carNumber[4] && carNumber[5] && !carNumber[6]">
__
</view>
</view>
<view class="default_car">
<view class="" v-show="carNumber[7]">
{{carNumber[7]}}
</view>
<view class="line"
v-show="carNumber[0] && carNumber[1] && carNumber[2] && carNumber[3] && carNumber[4] && carNumber[5] && carNumber[6] && !carNumber[7]">
__
</view>
</view>
</view>
</view>
<view class="tips">
注:请输入真实有效的车牌号
</view>
<view class="btn" @tap="pileBtn">请确认填入信息</view>
</view>
<!-- 键盘 -->
<view class="keyboard-content" v-show="keyShow">
<!-- 省份键盘 -->
<template v-if="provinceBoardShow">
<view class="province-keyboard flex">
<view class="td td-nor color-333" v-for="(item,index) in provincesKeyList" :key="index"
@click="provinceKeyClick(item,index)" hover-class="board-active" hover-start-time="0" hover-stay-time="80">
{{item}}
</view>
</view>
</template>
<!--数字键盘-->
<template v-if="!provinceBoardShow">
<view class="number-keyboard flex between">
<template>
<view class="td td-num color-333" :class="numberIsDis ? 'board-active' : ''"
v-for="(item,index) in numberKeyList" :key="index" @click="numberKeyClick(item,index)"
:hover-class="numberIsDis ? '' : 'board-active'" hover-start-time="0" hover-stay-time="80">
{{item}}
</view>
</template>
</view>
</template>
<!--字母键盘-->
<template v-if="!provinceBoardShow">
<view class="english-keyboard flex between">
<template>
<view class="td td-num color-333" :class="englishIsDis ? 'board-active' : ''"
v-for="(item,idx) in englishKeyOneList" :key="idx" @click="englishKeyClick(item,idx)"
:hover-class="englishIsDis ? '' : 'board-active'" hover-start-time="0" hover-stay-time="80">
{{item}}
</view>
</template>
</view>
<!-- 最后一行 -->
<view class="english-keyboard flex englishtTwo">
<template>
<view class="td td-num color-333" :class="englishIsDis ? 'board-active' : ''"
v-for="(item,index) in englishKeyTwoList" :key="index" @click="englishKeyClick(item,index)"
:hover-class="englishIsDis ? '' : 'board-active'" hover-start-time="0" hover-stay-time="80">
{{item}}
</view>
</template>
</view>
</template>
</view>
<!--清除按钮-->
<view @click.stop="backspace" class="delete flex" v-if="keyShow">清除</view>
<view @click.stop="sure" class="sure flex" v-if="keyShow">确定</view>
</view>
</template>
<script>
export default {
data() {
return {
// 手机号
mobileNumber: "",
// 验证码
code: '',
passwd: "",
getCodeText: '获取验证码',
getCodeBtnColor: "black",
getCodeisWaiting: false,
pileCode: '',
carClick: false,
keyShow: false, // 键盘是否显示
sureColor: false,
current: 0,
carNumber: [],
currentIndex: 0,
provincesKeyList: '京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼渝川贵云藏陕甘青宁新',
provinceBoardShow: true, // 省键盘
numberKeyList: '0123456789',
numberIsDis: true, // 输入键盘不可点击 true为不可点击
englishIsDis: false, // 字母键盘可点击
englishKeyOneList: 'ABCDEFGHJKLMNPQRSTUVWX',
};
},
onLoad() {},
onShow() {},
methods: {
// 确定桩号按钮
pileBtn() {
uni.hideKeyboard() //隐藏已经显示的软键盘,如果软键盘没有显示则不做任何操作。
//模板示例部分验证规则
if (!(/^1(3|4|5|6|7|8|9)\d{9}$/.test(this.mobileNumber))) { //校验手机号码
uni.showToast({
title: '请填写正确手机号码',
icon: "none"
});
return false;
}
//示例验证码,实际使用中应为请求服务器比对验证码是否正确。
if (this.code == '') {
uni.showToast({
title: '请输入验证码',
icon: "none"
});
return false;
}
let arr = this.carNumber.join('')
console.log(arr);
// this.keyShow = true
if (!this.checkPlateNumber(arr)) { // 校验桩号 this.passwd == ''
uni.showToast({
title: '请输入正确的车牌号',
icon: "none"
});
return false
}
uni.showLoading({
title: '提交中...'
})
this.bindingCarNo() // TODO 绑定车辆请求
},
// 绑定车牌号
async bindingCarNo() {
let arr = this.carNumber.join('')
console.log(arr);
let params = {
phoneNumber: this.mobileNumber,
verificationCode: this.code,
carNo: arr
}
const { data: { obj, resCode, msg } } = await uni.$http.post('/uniapp/member/memberBindingCarNo', params)
console.log('memberBindingCarNo 绑定车牌号发送请求 ', resCode, msg);
if ('00100000' !== resCode) return uni.showMsg(msg)
// 返回上一页
uni.navigateBack({
delta: 1
})
},
getCode() {
uni.hideKeyboard() //隐藏已经显示的软键盘,如果软键盘没有显示则不做任何操作。
if (this.getCodeisWaiting) {
return;
}
if (!(/^1(3|4|5|6|7|8|9)\d{9}$/.test(this.mobileNumber))) { //校验手机号码是否有误
uni.showToast({
title: '请填写正确手机号码',
icon: "none"
});
return false;
}
this.getCodeText = "发送中..." //发送验证码
this.verification()
this.getCodeisWaiting = true;
this.getCodeBtnColor = "black"
setTimeout(() => {
uni.showToast({
title: '验证码已发送',
icon: "none"
}); //弹出提示框
this.setTimer();
}, 1000)
},
// 获取验证码的方法
async verification() {
// console.log("手机号", this.mobileNumber)
const res = await uni.$http.post('/uniapp/member/sendSMS', {
mobileNumber: this.mobileNumber
})
console.log(res, '验证码信息');
},
setTimer() {
let holdTime = 60; //定义变量并赋值
this.getCodeText = "重新获取(60)"
this.Timer = setInterval(() => {
if (holdTime <= 0) {
this.getCodeisWaiting = false;
this.getCodeBtnColor = "#ffffff";
this.getCodeText = "获取验证码"
clearInterval(this.Timer); //清除该函数
return; //返回前面
}
this.getCodeText = "重新获取(" + holdTime + ")"
holdTime--;
}, 1000)
},
typeCurrent() {
this.carClick = true
this.carNumber = []
this.current = 0
console.log('点击哪个地方的', this.current);
this.provinceBoardShow = true
this.numberIsDis = true;
this.englishIsDis = true
},
// 省份键盘
provinceKeyClick(val, index) {
this.carNumber[0] = val
this.provinceBoardShow = false
this.numberIsDis = true;
this.englishIsDis = false
this.current++
console.log(this.current, '省份current')
},
// 数字键盘
numberKeyClick(val, idx) {
console.log(this.carNumber.length, 'this.carNumber.length00')
if (this.numberIsDis) return
if (this.carNumber.length >= 7) {
this.sureColor = true
}
if (this.carNumber.length >= 8) return
this.current++
this.carNumber[this.current - 1] = val;
// this.setTrailerKeyboardDis()
console.log(this.current, '数字键盘current')
},
// 字母键盘
englishKeyClick(val, idx) {
console.log(this.currentIndex, this.carNumber.length, 'this.carNumber.length')
if (this.englishIsDis) return
if (this.carNumber.length >= 7) {
this.sureColor = true
}
if (this.carNumber.length >= 8) {
console.log(this.carNumber);
this.keyShow = false
}
this.current++
this.carNumber[this.current - 1] = val;
if (this.current == 2) this.numberIsDis = false;
console.log(this.current, 'current')
},
sure() {
// console.log(this.carNumber);
let arr = this.carNumber.join('')
console.log(arr);
// this.keyShow = true
if (!this.checkPlateNumber(arr)) { // 校验桩号 this.passwd == ''
uni.showToast({
title: '请输入正确的车牌号',
icon: "none"
});
return false
}
this.keyShow = !this.keyShow
// let carString = this.carNumber.join(',')
console.log(this.carNumber);
},
backspace() {
console.log(this.current, 'current')
if (this.current <= 1) {
this.provinceBoardShow = true
this.numberIsDis = true
this.englishIsDis = true
}
if (this.current <= 0) return
this.current--
this.carNumber.pop()
// this.$forceUpdate()
},
addCar() {
if (this.sureColor == false) {
this.$u.toast('请输入有效的车牌号')
return false
}
this.keyShow = false
console.log(this.carNumber, 'carn')
},
checkPlateNumber(carNumber) {
// const re = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-Z0-9][0-9]{4}$))/
const re =
/^([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[a-zA-Z](([DF]((?![IO])[a-zA-Z0-9](?![IO]))[0-9]{4})|([0-9]{5}[DF]))|[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1})$/
const reg = new RegExp(re)
return reg.test(carNumber)
},
}
}
</script>
<style lang="scss" scoped>
@keyframes fade {
from {
opacity: 1.0;
}
50% {
opacity: 0;
}
to {
opacity: 1.0;
}
}
@-webkit-keyframes fade {
from {
opacity: 1.0;
}
50% {
opacity: 0;
}
to {
opacity: 1.0;
}
}
.flex {
display: flex;
}
.between {
justify-content: space-between;
}
.font-30 {
font-size: 30rpx;
}
.color-333 {
color: #333333;
}
.container {
padding: 20rpx;
color: black;
.car_number_input {
margin-top: 42rpx;
.car_type {
display: flex;
justify-content: start;
margin: 0 auto;
.default_car {
width: 98rpx;
height: 98rpx;
border: 1rpx solid #999999;
text-align: center;
line-height: 98rpx;
font-size: 40rpx;
font-family: PingFang SC;
font-weight: bold;
color: #333333;
.line {
color: #EA4070;
border-radius: 2px;
animation: fade 1500ms infinite;
-webkit-animation: fade 1500ms infinite;
}
}
.default_car:nth-child(1) {
border-right: none;
}
.default_car:nth-child(2) {
border-right: none;
color: #EA4070;
}
.default_car:nth-child(3) {
border-right: none;
color: #EA4070;
}
.default_car:nth-child(4) {
border-right: none;
color: #EA4070;
}
.default_car:nth-child(5) {
border-right: none;
color: #EA4070;
}
.default_car:nth-child(6) {
border-right: none;
color: #EA4070;
}
.default_car:nth-child(7) {
color: #EA4070;
}
.default_car:nth-child(8) {
border-left: none;
color: #EA4070;
}
}
}
.tips {
font-size: 28rpx;
font-family: PingFang SC;
font-weight: 500;
color: #999999;
margin-bottom: 27rpx;
// text-align: center;
}
.add_car_box {
float: left;
width: calc(100% - 64rpx);
height: 80rpx;
background: linear-gradient(180deg, #DF4270, #F299AB);
border-radius: 45upx;
margin: 0 auto;
.add_car {
height: 100%;
line-height: 80rpx;
font-size: 34rpx;
font-weight: 500;
color: #FFFFFF;
text-align: center;
}
.dis_car {
height: 100%;
line-height: 80rpx;
font-size: 34rpx;
font-weight: 500;
color: #FFFFFF;
background: #999999;
text-align: center;
border-radius: 40px;
}
}
.keyboard-content {
width: 100%;
height: 450rpx;
box-sizing: border-box;
position: fixed;
bottom: 0;
left: 0;
background-color: #D2D6D9;
.td {
font-family: "PingFangSC";
font-size: 34rpx;
color: #333333;
font-weight: 500;
margin: 12rpx 4rpx;
border: 1rpx solid #E0E0E0;
border-radius: 8rpx;
height: 84rpx;
line-height: 84rpx;
text-align: center;
background-color: #fff;
}
.province-keyboard {
margin: 0 5rpx;
flex-wrap: wrap;
.td-nor {
flex: 0 1 8%;
// margin-right: 3px;
}
}
.number-keyboard {
margin: 0 5rpx;
.td-num {
flex: 0 1 8%;
}
.board-active {
box-shadow: 0 0 0 #e5e5e5;
background: #e5e5e5;
}
}
.english-keyboard {
margin: 0 5rpx;
flex-wrap: wrap;
&.englishtTwo {
// margin-left: 80rpx;
.td-num {
margin-right: 5px;
flex: 0 1 8%;
}
}
.td-num {
flex: 0 1 8%;
}
.board-active {
box-shadow: 0 0 0 #e5e5e5;
background: #e5e5e5;
}
}
}
.delete {
width: 100rpx;
height: 84rpx;
text-align: center;
background-color: #AFB2BC;
border-radius: 8rpx;
position: absolute;
right: 120rpx;
bottom: 30rpx;
justify-content: center;
align-items: center;
}
.sure {
width: 100rpx;
height: 84rpx;
text-align: center;
background-color: #AFB2BC;
border-radius: 8rpx;
position: absolute;
right: 10rpx;
bottom: 30rpx;
justify-content: center;
align-items: center;
}
}
.form {
width: 86%;
padding: 0 7%;
font-size: 30upx;
.username,
.password,
.code {
width: calc(100% - 90upx);
height: 90upx;
display: flex;
align-items: center;
border-radius: 45upx;
background-color: rgba($color: black, $alpha: 0.1);
padding: 0 45upx;
margin-bottom: 26upx;
input {
width: 100%;
height: 50upx;
// color: rgba($color: #ffffff, $alpha: 0.8);
font-weight: 200;
}
}
.btn {
color: #f06c7a;
width: 100%;
height: 90upx;
display: flex;
justify-content: center;
align-items: center;
border-radius: 45upx;
// background-color: #fff;
font-size: 40upx;
}
.userform {
.username {
position: relative;
.get-code {
position: absolute;
height: 90upx;
display: flex;
align-items: center;
justify-content: center;
right: 0;
padding: 0 40upx;
z-index: 3;
&:after {
//点击以后,左边出现白色的线
content: " ";
width: 1upx; //宽度为1upx
height: 50upx; //高度为50upx
// background-color: #fff; //背景颜色为白色
position: absolute;
z-index: 3;
margin-right: 100%;
left: 0;
top: 20upx;
}
}
}
}
}
</style>
注意
我这边 绑定成功后 使用的是 navigateBack 返回上一页,那只能使用 navigateTo 跳转到注册页,
还有使用 navigateBack 返回上一页时 它不会自动刷新数据,因此 在 使用 navigateTo 方法的页面中 在 onShow 里发送请求 ,不要在onLoad 发送请求