fragment.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. <template>
  2. <view class="input-component" @click.self="onFocus" :class="{'active':withFocus}">
  3. <view class="bubbleTip" v-show="haserror && withFocus">
  4. <view>
  5. <bubble-tip msg="输入了错误的值"></bubble-tip>
  6. </view>
  7. </view>
  8. <view class="text-container" :style="{'font-size':fontSize,'height':fontSize}">
  9. <view class="text-sequence">
  10. <text v-for="(item, key) in sequence" :key="key">{{item}}</text>
  11. <view v-if="withFocus" class="fiction-cursor"></view>
  12. </view>
  13. </view>
  14. </view>
  15. </template>
  16. <script>
  17. import bubbleTip from "./bubble-tip.vue"
  18. export default {
  19. components: {
  20. "bubble-tip": bubbleTip
  21. },
  22. props: {
  23. "fontSize": {
  24. type: String,
  25. default: "1rem"
  26. },
  27. "value": {
  28. type: String,
  29. default: ""
  30. },
  31. "focus": {
  32. type: Boolean,
  33. default: false
  34. },
  35. "maxLength": {
  36. type: Number,
  37. default: null
  38. },
  39. "type": {
  40. type: String
  41. },
  42. "validate": {
  43. type: Function
  44. }
  45. },
  46. // #ifdef VUE3
  47. emits: {
  48. "complete": null,
  49. "updateValue": null,
  50. "returned": null,
  51. "error": null,
  52. "onFocus": null
  53. },
  54. // #endif
  55. data() {
  56. return {
  57. sequence: this.value.split(""),
  58. withFocus: this.focus,
  59. haserror: false
  60. };
  61. },
  62. methods: {
  63. onFocus() {
  64. this.withFocus = true;
  65. this.$emit("onFocus", true)
  66. },
  67. onComplete() {
  68. this.$emit("onFocus", false);
  69. this.$emit("complete");
  70. },
  71. inPut(character) {
  72. //console.log(character, this);
  73. let ins = this;
  74. let arr = JSON.parse(JSON.stringify(ins.sequence));
  75. if (character === "delete") {
  76. if (arr.length > 0) {
  77. arr.pop();
  78. } else {
  79. this.$emit("returned");
  80. }
  81. } else if (character !== "delete") {
  82. if (ins.maxLength) {
  83. if (ins.maxLength > arr.length) {
  84. arr.push(character);
  85. if (arr.length === ins.maxLength) {
  86. this.checkStr(arr.join("")) && ins.onComplete();
  87. }
  88. } else {
  89. this.checkStr(arr.join("")) && ins.onComplete();
  90. }
  91. } else {
  92. arr.push(character);
  93. }
  94. }
  95. if (this.checkStr(arr.join(""))) {
  96. ins.sequence = arr;
  97. ins.$emit("updateValue", arr.join(""));
  98. }
  99. },
  100. checkStr(str) {
  101. //console.log(this.validate);
  102. this.haserror = false;
  103. if (this.validate) {
  104. let r = this.validate(str);
  105. if (r === false) {
  106. this.haserror = true;
  107. uni.vibrateLong({
  108. success: function() {}
  109. });
  110. this.$nextTick(function() {
  111. setTimeout(() => {
  112. this.haserror = false;
  113. }, 1000)
  114. })
  115. this.$emit("error");
  116. }
  117. return r;
  118. }
  119. return true;
  120. }
  121. },
  122. watch: {
  123. "focus": {
  124. handler(n, o) {
  125. //console.log("watch focus",n,o)
  126. this.checkStr(this.sequence.join(""))
  127. this.withFocus = n;
  128. }
  129. }
  130. }
  131. }
  132. </script>
  133. <style scoped lang="scss">
  134. .bubbleTip {
  135. position: absolute;
  136. top: 0px;
  137. left: 50%;
  138. transform: translate(-50%, -105%);
  139. }
  140. .input-component {
  141. width: 100%;
  142. background-color: #FFFFFF;
  143. padding-top: 20rpx;
  144. padding-bottom: 20rpx;
  145. position: relative;
  146. border-radius: 6px;
  147. box-sizing: border-box;
  148. }
  149. .active {
  150. border: 1px solid #0080fb;
  151. }
  152. .text-container {
  153. display: flex;
  154. align-items: center;
  155. justify-content: space-around;
  156. .text-sequence {
  157. display: flex;
  158. height: 100%;
  159. align-items: center;
  160. }
  161. }
  162. .fiction-cursor {
  163. width: 2rpx;
  164. height: 100%;
  165. background-color: #666;
  166. animation: flashing 0.9s infinite;
  167. }
  168. @keyframes flashing {
  169. 0% {
  170. background-color: rgba(0, 0, 0, 0);
  171. }
  172. 100% {
  173. background-color: #666;
  174. }
  175. }
  176. </style>