之前写微信小程序时封装了车牌号输入键盘,记录在微信小程序组件中了,最近开发uniapp又重新开发了车牌号输入键盘组件,是在微信小程序开发的键盘组件的思想上做了一版优化,增加了挂车车牌号输入,及新能源车辆车牌号输入功能,功能如下:

uniapp的编程风格和H5非常相近,所以如果是H5需要车牌号输入键盘稍加改动同样可用

html

<template>
	<!--车牌号输入组件-->
	<view v-if="show" class="trailer-keyboard">
		<u-popup :show="show" :closeOnClickOverlay="false">
			<view class="keyBoard_content">
				<!-- header -->
				<view class="top-part flex">
					<view class="font-30 close" @click="closeKeyboard">x</view>
					<view class="message color-333">输入车牌号</view>
					<view 
						class="font-30 confirm"
						:class="{'confirm-active': confirmBtnFocus}"
						@click="confirmKeyboard">确定
					</view>
				</view>

				<!-- input checkbox -->
				<view class="input-and-checkbox">
					<!-- input -->
					<view class="license flex">
						<view 
							v-for="(item,index) in codeList" 
							:key="index"
							class="edit-text"
							:class="{'border-active': currentFocus === index,'space-left': index === 2}">
							<view>{{item.value}}</view>
						</view>
					</view>
					<!-- checkbox -->
					<view v-if="vehicleType === 'car' && checkboxShow" class="checkbox-box">
						<!--  -->
						<u-checkbox-group
							class="uCheckbox"
							v-model="checkboxList"
							@change="checkboxChange"
						>
							<u-checkbox
								:label="'新能源车'"
								:name="'新能源车'"
								shape="circle"
								activeColor="#27B57D"
								:checked="isNewEnergy"
							>
							</u-checkbox>
						</u-checkbox-group>
					</view>
				</view>
				

				<!-- 键盘 -->
				<view class="keyboard-content">
					<!-- 省份键盘 -->
					<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>
							
							<!-- 挂字键 -->
							<template v-if="vehicleType === 'trailer'">
								<view
									@click="trailerFiledClick('挂')"
									class="td td-num color-333"
									:class="trailerFiledIsDis ? 'board-active' : ''"
									:hover-class="trailerFiledIsDis ? '' : 'board-active'"
									hover-start-time="0" 
									hover-stay-time="80"
								>挂</view>
							</template>
						</view>
					</template>
					
					<!--清除按钮-->
					<view 
						@click="backspace" 
						class="delete flex" 
						hover-class="board-active" 
						hover-start-time="0"
						hover-stay-time="80">
						<image class="deleteImg" src="@/static/my/clear.png" />
					</view>
				</view>

			</view>
		</u-popup>
	</view>
</template>

js

<script>
	export default {
		name: 'trailerKeyboard',
		props: {
			// 组件显示
			show: {
				type: Boolean,
				default: false
			},
			// 初始传入车牌号
			vehicleNo: {
				type: String,
				default: ''
			},
			/**
			 * 车辆牌照类型 默认挂车
			 * trailer  挂车
			 * car      汽车
			 */
			vehicleType: {
				type: String,
				default: 'trailer'
			},
			// 是否展示新能源切换按钮
			checkboxShow: {
				type: Boolean,
				default: true,
			}
		},
		data() {
			return {
				/**
				 * currIndex 初始化为零  控制确定按钮高亮
				 * currentFocus 初始化为零 控制输入框高亮
				 */
				numberIsDis: true, // 输入键盘不可点击 true为不可点击
				englishIsDis: false, // 字母键盘可点击
				provinceBoardShow: true, // 省键盘
				isNewEnergy: false, // 是否新能源
				checkboxList: [],
				trailerFiledIsDis: true, // 挂字禁用
				provincesKeyList: '京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼渝川贵云藏陕甘青宁新',
				numberKeyList: '0123456789',
				englishKeyOneList: 'ABCDEFGHJKLMNPQRSTUV',
				englishKeyTwoList: 'WXYZ',
				currentFocus: 0,
				currIndex: 0,
				plateLimit: 7, // 车牌号位数
				codeList: [],
				// codeReset: []
			};
		},
		watch: {
			show: {
				handler(val) {
					this.initData()
				},
				immediate: true,
			}
		},
		computed: {
			confirmBtnFocus() {
				return this.currIndex === this.codeList.length
			}
		},
		methods: {
			// 省份键盘
			provinceKeyClick(val,index) {
				this.currentFocus++;
				this.currIndex++;
				this.codeList[0].value = val;
				this.provinceBoardShow = false;
				this.numberIsDis = true;
				this.englishIsDis = false;
			},

			// 数字键盘
			numberKeyClick(val,idx) {
				if(this.numberIsDis) return 
				if (this.currIndex >= this.codeList.length) return
				this.currIndex++;
				this.currentFocus = this.currIndex;
				this.codeList[this.currIndex - 1].value = val;
				if(this.vehicleType === 'trailer') {
					this.setTrailerKeyboardDis()
				}
			},

			// 字母键盘
			englishKeyClick(val,idx) {
				if(this.englishIsDis) return
				if (this.currIndex >= this.codeList.length) return
				this.currIndex++;
				this.currentFocus = this.currIndex;
				this.codeList[this.currIndex - 1].value = val;
				if(this.currIndex === 2) this.numberIsDis = false;
				if(this.vehicleType === 'trailer') {
					this.setTrailerKeyboardDis()
				}
			},
			
			// 挂字点击
			trailerFiledClick(val) {
				if(this.trailerFiledIsDis) return
				if (this.currIndex > this.codeList.length - 1) return
				this.currIndex++;
				this.currentFocus = this.currIndex + 1;
				this.codeList[this.currIndex - 1].value = val;
			},
			
			// 设置挂车键盘禁用(最后一个只能选择挂)
			setTrailerKeyboardDis() {
				if(this.currIndex + 1 === this.codeList.length) {
					this.numberIsDis = true;
					this.englishIsDis = true;
					this.trailerFiledIsDis = false;
				}
			},

			// 退格
			backspace() {
				if (!this.currIndex) return
				this.currIndex--;
				this.codeList[this.currIndex].value = '';
				this.currentFocus = this.currIndex;
				this.provinceBoardShow = this.currIndex === 0;
				if(this.currIndex === 1) this.numberIsDis = true;
				if(this.vehicleType === "trailer" && this.currIndex === this.codeList.length - 2) {	
					this.numberIsDis = false;
					this.englishIsDis = false;
					this.trailerFiledIsDis = true;
				}
			},

			// 关闭
			closeKeyboard(e) {
				this.$emit('update:show',false)
				this.$emit('close')
			},

			// 确定
			confirmKeyboard(e) {
				if (this.currIndex < this.codeList.length) return
				let plate = ''
				this.codeList.map(item => (plate += item.value))
				this.$emit('confirm', plate)
				this.closeKeyboard()
			},
			
			// 是否新能源车牌checkbox change
			checkboxChange(val) {
				console.log(val,'checkbox change');
				this.isNewEnergy = val.length ? true : false;
				
				if(val.length) {
					this.codeList.push({value: ''})
					// this.codeReset.push({value: ''})
				} else {
					this.codeList.splice(this.codeList.length - 1,1)
					// this.codeReset.splice(this.codeList.codeReset - 1,1)
					let vehicleNo = "";
					this.codeList.map(item => (vehicleNo += item.value))
					if(vehicleNo.length === this.codeList.length && this.currIndex > this.codeList.length) {
						this.currIndex--;
						this.currentFocus--
					}
				}
			},
			
			initData() {
				console.log('initData',this.isNewEnergy);
				console.log(this.checkboxList);
				let temp = []
				// let reset = []
				const vehicleNoTrim = this.vehicleNo.trim()
				const Leng = vehicleNoTrim ? vehicleNoTrim.length : 0;

				// 新能源checkbox回显
				this.isNewEnergy = Leng > 7 ? true : false;
				this.checkboxList = Leng > 7 ? ['新能源车'] : []

				if (Leng) {
					let arr = vehicleNoTrim.split('')
					arr.forEach(item => {
						temp.push({value: item})
						// reset.push({value: ''})
					})
				} else {
					// 初始化设置数据
					for (let index = 0; index < this.plateLimit; index++) {
						temp.push({value: ''})
						// reset.push({value: ''})
					}
				}

				// 解决车牌号回显位数不够问题
				if(Leng > 0 && Leng < 7) {
					let num = 7 - Leng;
					for(let i = 0; i < num; i++) {
						temp.push({value: ''})
					}
				}
				// 禁用设置
				this.isNewEnergy = Leng > 7 ? true : false;
				this.provinceBoardShow = Leng > 0 ? false : true;
				this.numberIsDis = Leng < 2 ? true : false;
				this.englishIsDis = false;
				if(this.vehicleType === 'trailer') {
					if(Leng >= 6) {
						this.numberIsDis = true;
						this.englishIsDis = true;
					}
					this.trailerFiledIsDis = Leng < 6 ? true: false;
				} 

				this.codeList = temp;
				// this.codeReset = reset;
				this.currentFocus = Leng;
				this.currIndex = vehicleNoTrim ? vehicleNoTrim.length : 0;
			}
		},
	}
</script>

css

<style lang="scss" scoped>
	.flex {
		display: flex;
	}

	.between {
		justify-content: space-between;
	}

	.font-30 {
		font-size: 30rpx;
	}

	.color-333 {
		color: #333333;
	}
	
	.trailer-keyboard {
		
	}

	.keyBoard_content {
		z-index: 9999;
		position: fixed;
		bottom: 0;
		left: 0;
		width: 100%;
		height: auto;
		background: #fff;
		
		.top-part {
			width: 100%;
			padding: 25rpx 40rpx;
			height: 92rpx;
			justify-content: center;
			align-items: center;
			box-sizing: border-box;
			border-bottom: 1rpx solid #EAEAEA;
			margin-bottom: 15rpx;
			text-align: center;
			
			.close {
				width: 10%;
				font-size: 47rpx;
				color: #A0A0A0;
			}
			
			.message {
				font-size: 15px;
				width: 80%;
				text-align: center;
				font-weight: Semibold;
			}
			
			.confirm {
				width: 10%;
				color: #A0A0A0;
				font-weight: Regular;
				
				&.confirm-active {
					color: #27B57D;
				}
			}
		}
		
		.input-and-checkbox {
			
			.license {
				box-sizing: border-box;
				justify-content: space-around;
				margin: 72rpx 86rpx 30rpx;
				
				.edit-text {
					height: 80rpx;
					line-height: 80rpx;
					width: 60rpx;
					border: 1rpx solid #A0A0A0;
					border-radius: 8rpx;
					text-align: center;
					font-size: 36rpx;
					
					&.space-left {
						// margin-left: 30rpx;
					}
					
					&.border-active {
						border: 1rpx solid #5BCA92;
					}
				}
			}
			
			.checkbox-box {
				margin: 25rpx 86rpx 28rpx;
				display: flex;
				justify-content: flex-end;
				
				.uCheckbox {
					
				}
			}
		}
		
		.keyboard-content {
			width: 100%;
			height: 450rpx;
			box-sizing: border-box;
			position: relative;
			
			.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;
			}
			
			.province-keyboard {
				margin: 0 50rpx;
				flex-wrap: wrap;
				
				.td-nor {
					flex: 0 1 9%;
					margin-right: 3px;
				}
			}
			
			.number-keyboard {
				margin: 0 5rpx;
				
				.td-num {
					flex: 0 1 8%;
				}
			}
			
			.english-keyboard {
				margin: 0 5rpx;
				flex-wrap: wrap;
				
				&.englishtTwo {
					margin-left: 80rpx;
					
					.td-num {
						margin-right: 5px;
						flex: 0 1 8.8%;
					}
				}
				
				.td-num {
					flex: 0 1 8%;
				}
			}
			
			.board-active {
				box-shadow: 0 0 0 #e5e5e5;
				background: #e5e5e5;
			}
			
			.delete {
				width: 140rpx;
				height: 84rpx;
				text-align: center;
				background-color: #D8D8D8;
				border-radius: 8rpx;
				position: absolute;
				right: 73rpx;
				bottom: 30rpx;
				justify-content: center;
				align-items: center;
				
				.deleteImg {
					width: 44rpx;
					height: 30rpx;
				}
			}
		}
		
	}
</style>

使用

<!-- vehicleType  车牌号组件类型 默认挂车trailer  普通车牌号为car -->
<TrailerKeyboard 
	:show.sync="trailerKeyboardShow" 
	:vehicleNo="trailerForm.trailerNo"
	@confirm="keyboardconfirm"
	vehicleType="car"
></TrailerKeyboard>
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐