小程序-车牌号键盘

此代码展示了如何在微信小程序中创建一个车牌号输入键盘,包括省份选择和字母数字输入,支持新能源车牌,并提供了输入验证和历史车牌复用功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

按照一下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": {}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值