按照一下4个文件代码则可以渲染出车牌号键盘
效果图:
index.wxml
<!-- 输入框 -->
<view class="modal-content">
<view class="board-input">
<block wx:for="{{8}}" wx:key="index">
<view
wx:if="{{index!==7}}"
data-index="{{index}}"
class="input {{selectInputIndex===index?'activeInput':''}}"
bindtap='inputCarNum'
>
<text>{{carNumArr[index] || ''}}</text>
</view>
<block wx:if="{{index===7}}">
<view
wx:if="{{selectInputIndex===7||carNumArr[index]}}"
data-index="{{index}}"
class="input {{selectInputIndex===7?'activeInput':''}}"
bindtap='inputCarNum'
>
<text>{{carNumArr[index] || ''}}</text>
</view>
<view
wx:else
data-index="{{index}}"
class="input new"
bindtap='inputCarNum'
>
<text>新能源</text>
</view>
</block>
</block>
</view>
</view>
<view class="d-f jc-c c-333 fz-28 mt-64 mb-30" wx:if="{{lastCarNumber}}">
<view>
上次使用的车牌号:
</view>
<view class="fw-600">
{{lastCarNumber}}
</view>
<view class="c-ff6c1e ml-32" bind:tap="useLastTime">
使用
</view>
</view>
<!-- 提交 -->
<view class="{{lastCarNumber?'':'mt-136'}}">
<button class="giga-button bgc-FF6A1B c-fff fz-32 {{validationResults?'':'disabled'}}" bindtap="onOk">
{{btnText}}
</button>
</view>
<!-- 车牌 -->
<view class='keyboard'>
<!-- 省键盘 -->
<view class="provinces" hidden='{{hiddenPro}}'>
<view
class="provinces-row"
wx:for="{{provinceArr}}"
wx:key="index"
wx:for-item="subarray"
>
<view class="provinces-row-item" wx:for="{{subarray}}" wx:key="index">
<view
class="pro-li"
catchtap='proTap'
data-province="{{item}}"
wx:if="{{item}}"
>
{{item}}
</view>
</view>
</view>
</view>
<!-- 号码键盘 -->
<view class="keyNums" hidden='{{hiddenStr}}'>
<view class='kb-clear' catchtap='backSpace'>
清除
</view>
<view wx:if="{{selectInputIndex===1}}" class="row numRow">
<view class="row-item" wx:for="{{numArr}}" wx:key="index">
<view class="pro-li disabled" data-str="{{item}}">{{item}}
</view>
</view>
</view>
<view wx:else class="row numRow">
<view class="row-item" wx:for="{{numArr}}" wx:key="index">
<view class="pro-li" catchtap='strTap' data-str="{{item}}">{{item}}
</view>
</view>
</view>
<view class="strOne row">
<view class="row-item" wx:for="{{strArrOne}}" wx:key="index">
<view
class="pro-li {{(index===7&&selectInputIndex!==1)||(index===9&&selectInputIndex!==6)?'disabled':''}}"
catchtap='strTap'
data-str="{{item}}"
data-disabled="{{(index===7&&selectInputIndex!==1)||(index===9&&selectInputIndex!==6)}}"
>
{{item}}
</view>
</view>
</view>
<view class="strTwo row">
<view class="row-item" wx:for="{{strArrTwo}}" wx:key="index">
<view
class="pro-li {{(index===9&&selectInputIndex!==6)?'disabled':''}}"
catchtap='strTap'
data-str="{{item}}"
data-disabled="{{index===9&&selectInputIndex!==6}}"
>
{{item}}
</view>
</view>
</view>
<view class="strThree row">
<view class="row-item" wx:for="{{strArrThree}}" wx:key="index">
<view
class="pro-li {{(index===7&&selectInputIndex!==6)||(index===8&&selectInputIndex!==6)?'disabled':''}}"
catchtap='strTap'
data-str="{{item}}"
data-disabled="{{(index===7&&selectInputIndex!==6)||(index===8&&selectInputIndex!==6)}}"
>
{{item}}
</view>
</view>
<view class="row-item" />
</view>
</view>
</view>
index.js
const INPUT_NUM = 8; // 车牌号输入框个数
const EmptyArray = new Array(INPUT_NUM).fill(''); // ['','','','','','','','']
// 车牌输入框的下标
const INPUT_INDEX = {
FIRST : 0,
SECOND: 1,
};
function splitArr(ar, size = 1) {
let index = 0;
let res = [];
while (index < ar.length) {
const subarray = ar.slice(index, (index + size));
if (subarray.length < size) {
res.push([...subarray, ...new Array(size - subarray.length).fill('')]);
} else {
res.push(subarray);
}
index = index + size;
}
return res;
}
const provinceList = [
'京',
'沪',
'津',
'苏',
'粤',
'冀',
'晋',
'蒙',
'辽',
'吉',
'黑',
'浙',
'皖',
'闽',
'赣',
'鲁',
'豫',
'鄂',
'湘',
'桂',
'琼',
'渝',
'川',
'贵',
'云',
'藏',
'陕',
'甘',
'青',
'宁',
'新',
'使',
'无',
];
Component({
data: {
// 键
provinceArr: splitArr(provinceList, 9),
strArrOne : [
'Q',
'W',
'E',
'R',
'T',
'Y',
'U',
'O',
'P',
'港',
],
strArrTwo: [
'A',
'S',
'D',
'F',
'G',
'H',
'J',
'K',
'L',
'澳',
],
strArrThree: [
'Z',
'X',
'C',
'V',
'B',
'N',
'M',
'学',
'领',
],
numArr: [
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'0',
],
hiddenPro : false, // 隐藏省份键盘
hiddenStr : true, // 隐藏数字字母键盘
carNumArr : EmptyArray,
selectInputIndex : 0,
carNumber : '',
lastCarNumber : '',
// 车牌校验结果
validationResults: false,
},
// 组件的对外属性,是属性名到属性设置的映射表
properties: {
btnText: { // 属性名
type : String,
value: '添加',
},
},
pageLifetimes: {
// 组件所在页面的生命周期函数
show() {
// 获取最后一次提交车牌号
this.setData({
lastCarNumber: wx.getStorageSync(`last_car_number`),
});
},
},
// 使用数据监听器
observers: {
carNumArr: function(arr) {
// 只要有一框输入为空,且不是最后一位则禁止提交
const validationResults = !arr.some((el, i)=> !el && (i !== 7));
this.setData({
carNumber: arr.join(''),
validationResults,
});
},
},
methods: {
proTap(e) {
// 点击省份
let province = e.currentTarget.dataset.province;
const { carNumArr, selectInputIndex } = this.data;
this.setData({
hiddenPro: true,
hiddenStr: false,
});
carNumArr[selectInputIndex] = province;
// 选择车牌号时触发
this.setData({
carNumArr,
// 选中一个后,下一个输入框聚焦
// eslint-disable-next-line no-negated-condition
selectInputIndex: selectInputIndex !== carNumArr.length - 1 ? selectInputIndex + 1 : selectInputIndex,
});
},
strTap({ currentTarget:{ dataset }}) {
const { str, disabled } = dataset;
// 点击字母数字
const { carNumArr, selectInputIndex } = this.data;
if (!disabled) {
carNumArr[selectInputIndex] = str;
this.setData({
carNumArr,
// 选中一个后,下一个输入框聚焦
// eslint-disable-next-line no-negated-condition
selectInputIndex: selectInputIndex !== carNumArr.length - 1 ? selectInputIndex + 1 : selectInputIndex,
});
}
},
inputCarNum(e) {
const { index } = e.currentTarget.dataset;
this.setData({
showCarKeyboard : true,
selectInputIndex: index,
});
if (index === INPUT_INDEX.FIRST) {
// 第一个输入框展示省份键盘,第二个展示字母数字输入框(数字不可点),以后就是数字字母输入框(都可点)
this.setData({
hiddenPro: false,
hiddenStr: true,
});
} else if (index === INPUT_INDEX.SECOND) {
this.setData({
hiddenPro: true,
hiddenStr: false,
});
} else {
this.setData({
hiddenPro: true,
hiddenStr: false,
});
}
},
backSpace() {
// 删除
const { carNumArr, selectInputIndex } = this.data;
carNumArr[selectInputIndex] = '';
this.setData(
{
carNumArr,
// eslint-disable-next-line no-negated-condition
selectInputIndex: selectInputIndex !== INPUT_INDEX.FIRST ? selectInputIndex - 1 : selectInputIndex,
},
() => {
if (this.data.selectInputIndex === INPUT_INDEX.FIRST) {
// 这里必须要用this.data.selectInputIndex,用最新的
this.setData({
hiddenPro: false,
hiddenStr: true,
});
}
},
);
},
onOk() {
const { carNumber, validationResults } = this.data;
// this.setData({
// selectInputIndex: -1,
// });
if (validationResults) {
this.triggerEvent('onOk', carNumber);
wx.setStorageSync(`last_car_number`, carNumber);
}
},
useLastTime() {
const { lastCarNumber } = this.data;
this.setData(
{
carNumber: lastCarNumber,
carNumArr: [...lastCarNumber.split(''), ...new Array(INPUT_NUM - lastCarNumber?.length).fill('')],
}
);
},
},
});
index.wxss
/* 键盘 */
.giga-button {
width: 100% !important;
text-align: center;
}
.giga-button.disabled {
opacity: 0.5;
}
.keyboard {
position: fixed;
z-index: 1000;
bottom: 0;
left: 0;
width: 100%;
background-color: rgba(210, 213, 219, 90);
}
.fl {
float: left;
}
.carnum {
height: 88rpx;
text-align: center;
}
.tel {
height: 100rpx;
border-bottom: 2rpx solid #ddd;
line-height: 100rpx;
}
.provinces {
overflow: hidden;
padding: 32rpx 10rpx 60rpx;
box-shadow: 0px -2rpx 10rpx 0rpx rgba(0, 0, 0, 0.07);
}
.provinces-row {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
}
.provinces-row-item {
display: flex;
flex: 1;
justify-content: center;
}
.pro-li {
width: 62rpx;
height: 76rpx;
background-color: #fafafa;
border-radius: 5px;
box-shadow: 0px 1rpx 2rpx 0 #9a9a9a;
color: #353535;
font-size: 32rpx;
line-height: 76rpx;
text-align: center;
}
.keyNums .disabled {
background-color: #f7f7f7;
color: #ccc;
}
.keyNums {
display: flex;
overflow: hidden;
flex-direction: column;
padding: 32rpx 10rpx 60rpx;
box-shadow: 0px -2rpx 10rpx 0rpx rgba(0, 0, 0, 0.07);
}
.keyNums .row {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
}
.keyNums .row-item {
display: flex;
flex: 1;
justify-content: center;
}
.keyNums .numRow {
padding: 0;
}
.keyNums .strOne {
padding: 0;
}
.keyNums .strOne .strOneItem {
flex: 1;
}
.keyNums .strTwo {
padding: 0;
}
.keyNums .strOne .strTwoItem {
flex: 1;
}
.keyNums .strThree {
padding-right: 0;
padding-left: 0;
}
.keyNums .strOne .strThreeItem {
flex: 1;
}
.keyNums .strOne .strThreeItem:nth-child(7) {
margin-left: 100px;
}
.keyNums .pro-li:nth-child(16) {
color: red;
}
.keyNums .strThree .kb-del {
margin-left: 12rpx;
}
.keyNums .kb-clear {
margin-bottom: 32rpx;
color: #353535;
font-size: 32rpx;
text-align: right;
}
/* ipt样式 */
.board-input {
display: flex;
}
.board-input .input {
height: 80rpx;
box-sizing: border-box;
flex: 1;
margin-right: 4rpx;
background: #f2f2f2;
border-radius: 4rpx;
color: #333;
line-height: 80rpx;
text-align: center;
}
.board-input .input:nth-child(2) {
position: relative;
border-left-width: 0;
margin-right: 20rpx;
border-bottom-left-radius: 0;
border-top-left-radius: 0;
}
.board-input .new {
color: #fd7d28;
font-size: 20rpx;
outline: 1px dashed #fd7d28;
}
.board-input .activeInput {
z-index: 10;
border-radius: 4rpx !important;
outline: 1px solid #fd7d28 !important;
}
.board-input .text {
color: #c5c5c5;
font-size: 28rpx;
text-align: right;
}
.delete-icon {
width: 50rpx;
height: 45rpx;
margin-top: 18rpx;
}
index.json
{
"component": true,
"usingComponents": {}
}