login-custom.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. <template>
  2. <view class="login-custom">
  3. <view class="container">
  4. <!-- logo -->
  5. <image class="logo" :src="staticUrl + 'icon-logo@2x.png'" mode="widthFix"></image>
  6. <!-- 登录表单 -->
  7. <view class="login-form">
  8. <view class="form-control">
  9. <input class="input" type="number" placeholder="请输入手机号" v-model="mobile" maxlength="11" />
  10. </view>
  11. <tui-divider :height="dividerHeight"></tui-divider>
  12. <view class="form-control">
  13. <input
  14. class="input"
  15. type="number"
  16. v-model="verificationCode"
  17. placeholder="请输入短信验证码"
  18. maxlength="6"
  19. />
  20. <view class="validate-code" @click="sendVerificationCode">
  21. <text v-if="!countDownStatus">获取验证码</text>
  22. <text v-else v-text="countDownTip"></text>
  23. </view>
  24. </view>
  25. <tui-divider :height="dividerHeight"></tui-divider>
  26. <view class="tip" v-text="tipMessage"></view>
  27. </view>
  28. <tui-button
  29. type="base"
  30. width="600rpx"
  31. height="90rpx"
  32. shape="circle"
  33. @click="submit"
  34. :disabled="disabled || submitStatus"
  35. :loading="submitStatus"
  36. >
  37. 登录
  38. </tui-button>
  39. </view>
  40. </view>
  41. </template>
  42. <script>
  43. import { getUserProfile } from '@/common/auth.js'
  44. import { validMobile } from '@/common/validation.js'
  45. import { sendMobileVerification } from '@/services/api/common.js'
  46. import { mapGetters } from 'vuex'
  47. export default {
  48. data() {
  49. return {
  50. dividerHeight: 50,
  51. tipMsg: '',
  52. countDownStatus: 0,
  53. // 用户注册登录信息
  54. mobile: '', // 注册/绑定手机号
  55. headImgUrl: '', //微信头像
  56. nickName: '', //微信昵称
  57. verificationCode: '', //短信验证码
  58. invitationCode: '', // 推荐人邀请码
  59. // 数据校验
  60. valide: {
  61. mobile: false,
  62. verificationCode: false
  63. },
  64. submitStatus: false
  65. }
  66. },
  67. watch: {
  68. mobile(value) {
  69. const valide = validMobile(value)
  70. this.valide.mobile = valide
  71. this.tipMsg = valide ? '' : '请输入合法的手机号'
  72. },
  73. verificationCode(value) {
  74. const valide = value.toString().length === 6
  75. this.valide.verificationCode = valide
  76. this.tipMsg = valide ? '' : '请输入6位邀请码'
  77. }
  78. },
  79. computed: {
  80. ...mapGetters(['openId']),
  81. tipMessage() {
  82. return this.tipMsg || '未注册的手机号验证后自动创建颜选美学账户'
  83. },
  84. disabled() {
  85. return !this.valide.mobile || !this.valide.verificationCode
  86. },
  87. countDownTip() {
  88. return `重新获取(${this.countDownStatus}s)`
  89. }
  90. },
  91. beforeDestroy() {
  92. uni.removeStorageSync('LOGIN_REDIRECT_URL')
  93. },
  94. methods: {
  95. // 获取用户信息
  96. async getUserProfile() {
  97. this.submitStatus = true
  98. if (!this.headImgUrl || !this.nickName) {
  99. try {
  100. const result = await getUserProfile()
  101. this.headImgUrl = result.avatarUrl
  102. this.nickName = result.nickName
  103. // return result
  104. console.log(result)
  105. } catch (e) {
  106. console.log(e)
  107. }
  108. }
  109. },
  110. // 短信验证码登录
  111. async mobileLogin() {
  112. const params = {
  113. openId: this.openId, //微信openId
  114. mobile: this.mobile, // 注册/绑定手机号
  115. headImgUrl: this.headImgUrl, //微信头像
  116. nickName: this.nickName, //微信昵称
  117. verificationCode: this.verificationCode, //短信验证码
  118. invitationCode: this.invitationCode // 推荐人邀请码
  119. }
  120. try {
  121. await this.$store.dispatch('user/register', params)
  122. // 登录成功处理
  123. uni.redirectTo({ url: '/pages/authorize/login-auth' })
  124. } catch (e) {
  125. this.submitStatus = false
  126. }
  127. },
  128. // 发送验证码
  129. async sendVerificationCode() {
  130. if (this.countDownStatus > 0) return
  131. if (!this.valide.mobile) {
  132. return this.$toast.error('请输入合法手机号')
  133. }
  134. try {
  135. await sendMobileVerification({ mobile: this.mobile })
  136. this.startCountDown()
  137. this.$toast.success('验证码已发送')
  138. } catch (e) {
  139. console.log('发送验证码失败')
  140. }
  141. },
  142. // 验证码倒计时
  143. startCountDown() {
  144. this.countDownStatus = 30
  145. if (this.timer) clearInterval(this.timer)
  146. // 开启定时器
  147. this.timer = setInterval(() => {
  148. this.countDownStatus--
  149. if (this.countDownStatus === 0) {
  150. clearInterval(this.timer)
  151. }
  152. }, 1000)
  153. },
  154. // 提交登录
  155. async submit() {
  156. await this.getUserProfile()
  157. const { mobile, verificationCode } = this.valide
  158. if (mobile && verificationCode) {
  159. this.mobileLogin()
  160. }
  161. }
  162. }
  163. }
  164. </script>
  165. <style lang="scss" scoped>
  166. .login-custom {
  167. @extend .cm-flex-center;
  168. align-items: flex-start;
  169. height: 100vh;
  170. background-color: #fff;
  171. .container {
  172. @extend .cm-flex-center;
  173. flex-direction: column;
  174. width: 600rpx;
  175. margin-top: 180rpx;
  176. .logo {
  177. width: 200rpx;
  178. height: 200rpx;
  179. }
  180. .login-form {
  181. width: 100%;
  182. margin: 80rpx 0 25rpx;
  183. .form-control {
  184. width: 100%;
  185. @extend .cm-flex-between;
  186. font-size: 26rpx;
  187. .input {
  188. flex: 1;
  189. }
  190. .validate-code {
  191. flex: 1;
  192. text-align: right;
  193. color: #666;
  194. }
  195. }
  196. .tip {
  197. font-size: 24rpx;
  198. color: #fc464c;
  199. text-align: left;
  200. }
  201. }
  202. }
  203. }
  204. </style>