vue h5实现车牌号输入框

效果图:
在这里插入图片描述

用户移动端添加车牌号,于是我们手写了一个H5车牌号软键盘,已经封装成一个组件,调用即可。

功能如上图所示,支持 8位电车车牌和7位油车车牌。

第一位是 省份,用户点击就会弹出省份软键盘;

第二位是 字母,用户点击只能输入字母;

第三、四、五、六位是字母和数字,不包含O;

第七位是 数字、字母、或者学、警之类汉字;

第八位是 电车选项。

用户点击软键盘对应的按键时会高亮,这个是后期加的,所以上图中没有展示出来。

我用的移动端是rem布局,使用插件进行转换了(转换比是1rem=100px)

完整代码如下
主文件:

<template>
  <div>
    <button @click="addCare">添加车辆</button>
    <div>车牌:{{ carNo }}</div>

    <CarInput
      :addShow="showCarInput"
      @close="showCarInput = false"
      @submit="onCarInputSubmit"
    />
  </div>
</template>
<script>
import CarInput from "../components/CarPlateInput.vue";
export default {
  name: "test",
  components: {
    CarInput,
  },
  data() {
    return {
      carNo: "",
      showCarInput: false,
    };
  },
  methods: {
    addCare() {
      this.showCarInput = true;
    },
    // 车牌弹窗回填
    onCarInputSubmit(val) {
      this.carNo = val;
      this.showCarInput = false;
    },
  },
};
</script>

车牌录入组件:

<template>
  <div class="shade-layer" v-if="addShow" @click="keyboardShow = false">
    <div class="add-content">
      <div class="add-header">
        <p>车辆信息</p>
        <span @click="$emit('close')">关闭</span>
      </div>
      <div class="form-list">
        <p>车牌号:</p>
        <div class="car-num-input">
          <div
            v-for="(item, index) in carNumList"
            :key="index"
            @click.stop="selectCarNum(index)"
            :class="
              (carIndex == index ? 'active' : '') +
                ' ' +
                (item ? 'status-key' : '')
            "
          >
            {{
              index == 0 && !item
                ? '省'
                : index == carNumList.length - 1 && !item
                ? '新能源'
                : item
            }}
          </div>
        </div>
      </div>
      <button class="submit-btn" @click="carSubmitBtn()" v-points>
        提交
      </button>
    </div>
    <!-- 车牌键盘 -->
    <div class="keyboard-layer" v-if="keyboardShow" @click.stop="">
      <div class="keyboard-header">
        <span @click="keyboardShow = false">完成</span>
      </div>
      <!-- 省份键盘 -->
      <div class="province-layer" v-if="carIndex == '0'">
        <span
          v-for="(item, index) in provinceList"
          :key="index"
          @click="keyboardBtn(item)"
          :class="activeKey == item ? 'active-hover' : ''"
          >{{ item == 'del' ? '删除' : item }}</span
        >
      </div>
      <!-- 数字字母键盘 -->
      <div class="keyboard-item" v-if="carIndex != '0'">
        <div v-if="carIndex != '1'">
          <span
            v-for="(item, index) in keyboardList[0]"
            :key="index"
            @click="keyboardBtn(item)"
            :class="activeKey == item ? 'active-hover' : ''"
            >{{ item }}</span
          >
        </div>
        <div>
          <span
            v-for="(item, index) in keyboardList[1]"
            :key="index"
            @click="keyboardBtn(item)"
            :class="
              (item == 'O' && carIndex != '1' ? 'no-btn' : '') +
                ' ' +
                (activeKey == item ? 'active-hover' : '')
            "
            >{{ item }}</span
          >
        </div>
        <div>
          <span
            v-for="(item, index) in keyboardList[2]"
            :key="index"
            @click="keyboardBtn(item)"
            :class="activeKey == item ? 'active-hover' : ''"
            >{{ item }}</span
          >
        </div>
        <div>
          <span
            v-for="(item, index) in keyboardList[3]"
            :key="index"
            @click="keyboardBtn(item)"
            :class="activeKey == item ? 'active-hover' : ''"
            >{{ item == 'del' ? '删除' : item }}</span
          >
        </div>
        <div v-if="carIndex == carNumList.length - 2">
          <span
            v-for="(item, index) in keyboardList[4]"
            :key="index"
            @click="keyboardBtn(item)"
            :class="activeKey == item ? 'active-hover' : ''"
            >{{ item }}</span
          >
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'CarPlateInput',
  props: {
    addShow: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      formData: {
        carNumber: ''
      },
      carNumList: ['', '', '', '', '', '', '', ''],
      activeKey: '',
      timeoutId: null,
      carIndex: null,
      keyboardShow: false,
      provinceList: [
        '京', '津', '沪', '渝', '冀', '豫', '云', '辽', '黑', '湘', '皖', '鲁', '新', '苏', '浙', '赣', '鄂', '桂', '甘', '晋', '蒙', '陕', '吉', '闽', '贵', '粤', '青', '藏', '川', '宁', '琼', '使', '领', '学', '警', '挂', 'del'
      ],
      keyboardList: [
        ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
        ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'O', 'P'],
        ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
        ['Z', 'X', 'C', 'V', 'B', 'N', 'M', 'del'],
        ['学', '警', '港', '澳']
      ]
    }
  },
  watch: {
    addShow(val) {
      if (!val) {
        this.formData = { carNumber: '' }
        this.carIndex = ''
        this.carNumList = ['', '', '', '', '', '', '', '']
        this.keyboardShow = false
      }
    }
  },
  methods: {
    carSubmitBtn() {
      this.formData.carNumber = ''
      for (let i in this.carNumList) {
        if (this.carNumList[i] == '' && i != this.carNumList.length - 1) {
          this.$emit('incomplete')
          return
        }
        this.formData.carNumber += this.carNumList[i]
      }
      this.$emit('submit', this.formData.carNumber)
    },
    selectCarNum(inx) {
      this.carIndex = inx
      if (!this.keyboardShow) {
        this.keyboardShow = true
      }
    },
    keyboardBtn(val) {
      this.activeKey = val
      this.activeKeyBtn()
      this.carNumList[this.carIndex] = val == 'del' ? '' : val
      if (val == 'del' && this.carIndex > 0) {
        this.carIndex--
      }
      if (val != 'del' && this.carIndex < this.carNumList.length - 1) {
        this.carIndex++
      }
      this.$forceUpdate()
    },
    activeKeyBtn() {
      if (this.timeoutId) clearTimeout(this.timeoutId)
      this.timeoutId = setTimeout(() => {
        this.activeKey = ''
      }, 300)
    }
  }
}
</script>

<style scoped lang="less">
.shade-layer {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 5;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.4);
  padding: 16px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;

  .add-content {
    width: 100%;
    padding: 16px 16px 24px;
    box-sizing: border-box;
    border-radius: 16px;
    background: #fff;

    .add-header {
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding-bottom: 14px;
      box-sizing: border-box;

      p {
        color: #000;
        font-family: "PingFang SC";
        font-size: 16px;
        font-weight: 700;
        line-height: 22px;
      }

      span {
        color: #3faa73;
        font-family: "PingFang SC";
        font-size: 12px;
        font-weight: 700;
        line-height: 24px;
        cursor: pointer;
      }
    }

    .form-list {
      p {
        color: #6b7280;
        font-family: "PingFang SC";
        font-size: 14px;
        font-weight: 500;
        line-height: 20px;
      }

      input {
        display: block;
        font-size: 14px;
        line-height: 20px;
        width: 100%;
        border-radius: 8px;
        border: none;
        background: #f5f7fa;
        padding: 12px 16px;
        box-sizing: border-box;
      }

      .car-num-input {
        width: 100%;
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 4px 0;
        box-sizing: border-box;

        div {
          width: 30px;
          height: 36px;
          background: rgba(0, 0, 0, 0.05);
          border-radius: 4px;
          border: 1px solid transparent;
          box-sizing: border-box;
          display: flex;
          align-items: center;
          justify-content: center;
          color: #000;
          font-size: 14px;
          line-height: 18px;

          &:first-child {
            color: rgba(0, 0, 0, 0.5);
          }

          &:last-child {
            border: 1px dashed rgba(27, 171, 80, 0.8);
            color: rgba(0, 0, 0, 0.5);
            font-size: 8px;
          }
        }

        .active {
          border: 1px solid rgba(61, 172, 120) !important;
        }

        .status-key {
          color: #000 !important;
          font-size: 14px !important;
          line-height: 18px !important;
        }
      }
    }

    .submit-btn {
      display: block;
      width: 100%;
      border: none;
      padding: 6px 10px;
      box-sizing: border-box;
      border-radius: 52px;
      background: #3faa73;
      color: #fff;
      text-align: center;
      font-family: "PingFang SC";
      font-size: 16px;
      font-weight: 700;
      line-height: 24px;
      margin-top: 24px;
    }
  }

  .keyboard-layer {
    width: 100%;
    background: #d0d5dc;
    padding: 8px 4px 16px;
    box-sizing: border-box;
    position: absolute;
    bottom: 0;
    left: 0;

    .keyboard-header {
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: flex-end;
      padding: 0 8px 8px;
      box-sizing: border-box;

      span {
        color: #3faa73;
        font-family: "PingFang SC";
        font-size: 14px;
        font-weight: 700;
        line-height: 28px;
        cursor: pointer;
      }
    }

    .province-layer {
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-wrap: wrap;

      span {
        color: #000;
        font-size: 14px;
        line-height: 28px;
        background: #fff;
        border-radius: 6px;
        padding: 6px 8px;
        box-sizing: border-box;
        margin: 2px;
        box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.1);
      }
    }

    .keyboard-item {
      width: 100%;

      div {
        display: flex;
        align-items: center;
        justify-content: center;

        span {
          color: #000;
          font-size: 14px;
          line-height: 28px;
          background: #fff;
          border-radius: 6px;
          padding: 4px 10px;
          box-sizing: border-box;
          margin: 4px;
          box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.3);
        }
      }
    }

    .no-btn {
      color: rgba(0, 0, 0, 0.4) !important;
      pointer-events: none;
    }

    .active-hover {
      background: #b3bac7 !important;
    }
  }
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值