uni-id-pages-email-form.vue 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <template>
  2. <view>
  3. <uni-captcha :focus="focusCaptchaInput" ref="captcha" scene="send-email-code" v-model="captcha" />
  4. <view class="box">
  5. <uni-easyinput :focus="focusEmailCodeInput" @blur="focusEmailCodeInput = 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. * email-code-form
  31. * @description 获取邮箱验证码组件
  32. * @tutorial https://ext.dcloud.net.cn/plugin?id=
  33. * @property {Number} count 倒计时时长 s
  34. * @property {String} email 邮箱
  35. * @property {String} type = [login-by-email-code|reset-pwd-by-email-code|bind-email] 验证码类型,用于防止不同功能的验证码混用,目前支持的类型login登录、register注册、bind绑定邮箱、unbind解绑邮箱
  36. * @property {false} focusCaptchaInput = [true|false] 验证码输入框是否默认获取焦点
  37. */
  38. export default {
  39. name: "uni-email-code-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. email: {
  57. type: [String],
  58. default: ''
  59. },
  60. /*
  61. 验证码类型,用于防止不同功能的验证码混用,目前支持的类型login登录、register注册、bind绑定邮箱、unbind解绑邮箱
  62. */
  63. type: {
  64. type: String,
  65. default () {
  66. return 'register'
  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. focusEmailCodeInput: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. duration: 3000
  127. });
  128. }
  129. if(!this.email) return uni.showToast({
  130. title: "请输入邮箱",
  131. icon: 'none',
  132. duration: 3000
  133. });
  134. let reg_email = /@/;
  135. if (!reg_email.test(this.email)) return uni.showToast({
  136. title: "邮箱格式错误",
  137. icon: 'none',
  138. duration: 3000
  139. });
  140. const uniIdCo = uniCloud.importObject("uni-id-co", {
  141. customUI: true
  142. })
  143. console.log('sendEmailCode',{
  144. "email": this.email,
  145. "scene": this.type,
  146. "captcha": this.captcha
  147. });
  148. uniIdCo.sendEmailCode({
  149. "email": this.email,
  150. "scene": this.type,
  151. "captcha": this.captcha
  152. }).then(result => {
  153. uni.showToast({
  154. title: "邮箱验证码发送成功",
  155. icon: 'none',
  156. duration: 3000
  157. });
  158. this.reverseNumber = Number(this.count);
  159. this.getCode();
  160. }).catch(e => {
  161. if (e.code == "uni-id-invalid-mail-template") {
  162. this.modelValue = "123456"
  163. uni.showToast({
  164. title: '已启动测试模式,详情【控制台信息】',
  165. icon: 'none',
  166. duration: 3000
  167. });
  168. console.warn(e.message);
  169. } else {
  170. this.getImageCaptcha()
  171. this.captcha = ""
  172. uni.showToast({
  173. title: e.message,
  174. icon: 'none',
  175. duration: 3000
  176. });
  177. }
  178. })
  179. },
  180. getCode() {
  181. if (this.reverseNumber == 0) {
  182. clearTimeout(this.reverseTimer);
  183. this.reverseTimer = null;
  184. return;
  185. }
  186. this.reverseNumber--;
  187. this.reverseTimer = setTimeout(() => {
  188. this.getCode();
  189. }, 1000)
  190. }
  191. }
  192. }
  193. </script>
  194. <style lang="scss" scoped>
  195. .box {
  196. position: relative;
  197. margin-top: 10px;
  198. }
  199. .short-code-btn {
  200. padding: 0;
  201. position: absolute;
  202. top: 0;
  203. right: 8px;
  204. width: 260rpx;
  205. max-width: 130px;
  206. height: 44px;
  207. /* #ifndef APP-NVUE */
  208. display: flex;
  209. /* #endif */
  210. justify-content: center;
  211. align-items: center;
  212. }
  213. .inner-text {
  214. font-size: 14px;
  215. color: #AAAAAA;
  216. }
  217. .inner-text-active {
  218. color: #04498c;
  219. }
  220. .captcha {
  221. width: 350rpx;
  222. }
  223. .input-box {
  224. margin: 0;
  225. padding: 4px;
  226. background-color: #F8F8F8;
  227. font-size: 14px;
  228. }
  229. .box ::v-deep .content-clear-icon {
  230. margin-right: 100px;
  231. }
  232. .box {
  233. /* #ifndef APP-NVUE */
  234. display: flex;
  235. /* #endif */
  236. flex-direction: row;
  237. }
  238. </style>