您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

verification-code-input.vue 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. <template>
  2. <view class="code-box">
  3. <view class="flex-box">
  4. <input
  5. type="number"
  6. focus="true"
  7. :maxlength="maxlength"
  8. class="hide-input"
  9. v-model="inputData.code"
  10. @input="getVal"
  11. />
  12. <view v-for="(item, index) in maxlength" :key="item">
  13. <view
  14. :class="[
  15. 'item',
  16. {
  17. active: codeIndex === item,
  18. middle: type === 'middle',
  19. bottom: type === 'bottom',
  20. box: type === 'box',
  21. },
  22. ]"
  23. >
  24. <view class="line" v-if="type !== 'middle'" />
  25. <view
  26. v-if="type === 'middle' && codeIndex <= item"
  27. class="bottom-line"
  28. />
  29. <view v-if="isPwd && inputData.codeArr.length >= item">
  30. <text class="dot">*</text>
  31. </view>
  32. <view v-else>
  33. {{ inputData.codeArr[index] ? inputData.codeArr[index] : "" }}
  34. </view>
  35. </view>
  36. </view>
  37. </view>
  38. </view>
  39. </template>
  40. <script setup lang="ts">
  41. import { reactive, ref } from "vue";
  42. const props = defineProps({
  43. maxlength: {
  44. type: Number,
  45. default: 6,
  46. },
  47. isPwd: {
  48. type: Boolean,
  49. default: false,
  50. },
  51. // middle-middle line, bottom-bottom line, box-square box
  52. type: {
  53. type: String,
  54. default: "bottom",
  55. },
  56. modelValue: {
  57. type: Number,
  58. },
  59. });
  60. const emit = defineEmits(["update:modelValue"]);
  61. const flexWidth = 80 / props.maxlength + "%";
  62. const inputData = reactive({
  63. codeArr: [] as Array<number>,
  64. code: null,
  65. });
  66. const codeIndex = ref(1);
  67. const getVal = (e) => {
  68. let { value } = e.detail;
  69. let arr: Array<number> = value.split("");
  70. codeIndex.value = arr.length + 1;
  71. inputData.codeArr = arr;
  72. if (codeIndex.value > Number(props.maxlength)) {
  73. emit("update:modelValue", inputData.code);
  74. }
  75. };
  76. </script>
  77. <style lang="scss" scoped>
  78. @keyframes twinkling {
  79. 0% {
  80. opacity: 0.2;
  81. }
  82. 50% {
  83. opacity: 0.5;
  84. }
  85. 100% {
  86. opacity: 0.2;
  87. }
  88. }
  89. .code-box {
  90. text-align: center;
  91. }
  92. .flex-box {
  93. display: flex;
  94. justify-content: space-evenly;
  95. flex-wrap: wrap;
  96. position: relative;
  97. }
  98. .flex-box .hide-input {
  99. position: absolute;
  100. top: 0;
  101. left: -100%;
  102. width: 200%;
  103. height: 100%;
  104. text-align: left;
  105. z-index: 9;
  106. opacity: 1;
  107. }
  108. .flex-box .item {
  109. position: relative;
  110. width: 106rpx;
  111. height: 100rpx;
  112. font-size: 46rpx;
  113. color: #333333;
  114. line-height: 100rpx;
  115. }
  116. .flex-box .item:last-child {
  117. margin-right: 0rpx;
  118. }
  119. .flex-box .middle {
  120. border: none;
  121. }
  122. .flex-box .box {
  123. box-sizing: border-box;
  124. border: 2rpx solid #dcdcdc;
  125. border-radius: 6rpx;
  126. }
  127. .flex-box .bottom {
  128. box-sizing: border-box;
  129. border-bottom: 1rpx solid #dcdcdc;
  130. }
  131. .flex-box .active {
  132. border-color: #00b38b;
  133. }
  134. .flex-box .active .line {
  135. display: block;
  136. }
  137. .flex-box .line {
  138. display: none;
  139. position: absolute;
  140. left: 50%;
  141. top: 50%;
  142. transform: translate(-50%, -50%);
  143. width: 2rpx;
  144. height: 50rpx;
  145. background: #333333;
  146. animation: twinkling 1s infinite ease;
  147. }
  148. .flex-box .dot {
  149. font-size: 80rpx;
  150. line-height: 40rpx;
  151. }
  152. .flex-box .bottom-line {
  153. height: 1rpx;
  154. background: #dcdcdc;
  155. width: 80%;
  156. position: absolute;
  157. border-radius: 2px;
  158. top: 50%;
  159. left: 50%;
  160. transform: translate(-50%, -50%);
  161. }
  162. </style>