uni-id-pages-sms-form.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. <template>
  2. <view>
  3. <uni-captcha :focus="focusCaptchaInput" ref="captcha" scene="send-sms-code" v-model="captcha" />
  4. <view class="box">
  5. <uni-easyinput :focus="focusSmsCodeInput" @blur="focusSmsCodeInput = false" type="number" class="input-box" :inputBorder="false" v-model="modelValue" maxlength="6"
  6. placeholder="请输入短信验证码">
  7. </uni-easyinput>
  8. <view class="short-code-btn" hover-class="hover" @click="start">
  9. <text class="inner-text" :class="reverseNumber==0?'inner-text-active':''">{{innerText}}</text>
  10. </view>
  11. </view>
  12. </view>
  13. </template>
  14. <script>
  15. function debounce(func, wait) {
  16. let timer;
  17. wait = wait || 500;
  18. return function() {
  19. let context = this;
  20. let args = arguments;
  21. if (timer) clearTimeout(timer);
  22. let callNow = !timer;
  23. timer = setTimeout(() => {
  24. timer = null;
  25. }, wait)
  26. if (callNow) func.apply(context, args);
  27. }
  28. }
  29. /**
  30. * sms-form
  31. * @description 获取短信验证码组件
  32. * @tutorial https://ext.dcloud.net.cn/plugin?id=
  33. * @property {Number} count 倒计时时长 s
  34. * @property {String} phone 手机号码
  35. * @property {String} type = [login-by-sms|reset-pwd-by-sms|bind-mobile] 验证码类型,用于防止不同功能的验证码混用,目前支持的类型login登录、register注册、bind绑定手机、unbind解绑手机
  36. * @property {false} focusCaptchaInput = [true|false] 验证码输入框是否默认获取焦点
  37. */
  38. export default {
  39. name: "uni-sms-form",
  40. model: {
  41. prop: 'modelValue',
  42. event: 'update:modelValue'
  43. },
  44. props: {
  45. event: ['update:modelValue'],
  46. /**
  47. * 倒计时时长 s
  48. */
  49. count: {
  50. type: [String, Number],
  51. default: 60
  52. },
  53. /**
  54. * 手机号码
  55. */
  56. phone: {
  57. type: [String, Number],
  58. default: ''
  59. },
  60. /*
  61. 验证码类型,用于防止不同功能的验证码混用,目前支持的类型login登录、register注册、bind绑定手机、unbind解绑手机
  62. */
  63. type: {
  64. type: String,
  65. default () {
  66. return 'login'
  67. }
  68. },
  69. /*
  70. 验证码输入框是否默认获取焦点
  71. */
  72. focusCaptchaInput: {
  73. type: Boolean,
  74. default () {
  75. return false
  76. }
  77. },
  78. },
  79. data() {
  80. return {
  81. captcha: "",
  82. reverseNumber: 0,
  83. reverseTimer: null,
  84. modelValue: "",
  85. focusSmsCodeInput:false
  86. };
  87. },
  88. watch: {
  89. captcha(value, oldValue) {
  90. if (value.length == 4 && oldValue.length != 4) {
  91. this.start()
  92. }
  93. },
  94. modelValue(value) {
  95. // TODO 兼容 vue2
  96. this.$emit('input', value);
  97. // TODO 兼容 vue3
  98. this.$emit('update:modelValue', value)
  99. }
  100. },
  101. computed: {
  102. innerText() {
  103. if (this.reverseNumber == 0) return "获取短信验证码";
  104. return "重新发送" + '(' + this.reverseNumber + 's)';
  105. }
  106. },
  107. created() {
  108. this.initClick();
  109. },
  110. methods: {
  111. getImageCaptcha(focus) {
  112. this.$refs.captcha.getImageCaptcha(focus)
  113. },
  114. initClick() {
  115. this.start = debounce(() => {
  116. if (this.reverseNumber != 0) return;
  117. this.sendMsg();
  118. })
  119. },
  120. sendMsg() {
  121. if (this.captcha.length != 4) {
  122. this.$refs.captcha.focusCaptchaInput = true
  123. return uni.showToast({
  124. title: '请先输入图形验证码',
  125. icon: 'none'
  126. });
  127. }
  128. let reg_phone = /^1\d{10}$/;
  129. if (!reg_phone.test(this.phone)) return uni.showToast({
  130. title: "手机号格式错误",
  131. icon: 'none'
  132. });
  133. const uniIdCo = uniCloud.importObject("uni-id-co", {
  134. customUI: true
  135. })
  136. console.log('sendSmsCode',{
  137. "mobile": this.phone,
  138. "scene": this.type,
  139. "captcha": this.captcha
  140. });
  141. uniIdCo.sendSmsCode({
  142. "mobile": this.phone,
  143. "scene": this.type,
  144. "captcha": this.captcha
  145. }).then(result => {
  146. console.log(result.code);
  147. uni.showToast({
  148. title: "短信验证码发送成功",
  149. icon: 'none'
  150. });
  151. this.reverseNumber = Number(this.count);
  152. this.getCode();
  153. }).catch(e => {
  154. console.log(JSON.stringify(e));
  155. if (e.code == "uni-id-invalid-sms-template-id") {
  156. this.modelValue = "123456"
  157. uni.showToast({
  158. title: '已启动测试模式,详情【控制台信息】',
  159. icon: 'none',
  160. duration: 3000
  161. });
  162. console.warn(e.message);
  163. } else {
  164. this.getImageCaptcha()
  165. this.captcha = ""
  166. uni.showToast({
  167. title: e.message,
  168. icon: 'none'
  169. });
  170. }
  171. })
  172. },
  173. getCode() {
  174. if (this.reverseNumber == 0) {
  175. clearTimeout(this.reverseTimer);
  176. this.reverseTimer = null;
  177. return;
  178. }
  179. this.reverseNumber--;
  180. this.reverseTimer = setTimeout(() => {
  181. this.getCode();
  182. }, 1000)
  183. }
  184. }
  185. }
  186. </script>
  187. <style lang="scss" scoped>
  188. .box {
  189. position: relative;
  190. margin-top: 10px;
  191. }
  192. .short-code-btn {
  193. padding: 0;
  194. position: absolute;
  195. top: 0;
  196. right: 8px;
  197. width: 260rpx;
  198. max-width: 100px;
  199. height: 44px;
  200. /* #ifndef APP-NVUE */
  201. display: flex;
  202. /* #endif */
  203. justify-content: center;
  204. align-items: center;
  205. }
  206. .inner-text {
  207. font-size: 14px;
  208. color: #AAAAAA;
  209. }
  210. .inner-text-active {
  211. color: #04498c;
  212. }
  213. .captcha {
  214. width: 350rpx;
  215. }
  216. .input-box {
  217. margin: 0;
  218. padding: 4px;
  219. background-color: #F8F8F8;
  220. font-size: 14px;
  221. }
  222. .box ::v-deep .content-clear-icon {
  223. margin-right: 110px;
  224. }
  225. .box {
  226. /* #ifndef APP-NVUE */
  227. display: flex;
  228. /* #endif */
  229. flex-direction: row;
  230. }
  231. </style>