login-custom.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <template>
  2. <view class="login-custom">
  3. <view class="container">
  4. <!-- logo -->
  5. <image class="logo" :src="staticUrl + 'logo2022525.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. methods: {
  92. // 获取用户信息
  93. async getUserProfile() {
  94. this.submitStatus = true
  95. if (!this.headImgUrl || !this.nickName) {
  96. try {
  97. const result = await getUserProfile()
  98. this.headImgUrl = result.avatarUrl
  99. this.nickName = result.nickName
  100. // return result
  101. console.log(result)
  102. } catch (e) {
  103. console.log(e)
  104. }
  105. }
  106. },
  107. // 短信验证码登录
  108. async mobileLogin() {
  109. const params = {
  110. openId: this.openId, //微信openId
  111. mobile: this.mobile, // 注册/绑定手机号
  112. headImgUrl: this.headImgUrl, //微信头像
  113. nickName: this.nickName, //微信昵称
  114. verificationCode: this.verificationCode, //短信验证码
  115. invitationCode: this.invitationCode // 推荐人邀请码
  116. }
  117. try {
  118. await this.$store.dispatch('user/register', params)
  119. // 登录成功处理
  120. uni.redirectTo({ url: '/pages/authorize/login-auth' })
  121. } catch (e) {
  122. this.submitStatus = false
  123. }
  124. },
  125. // 发送验证码
  126. async sendVerificationCode() {
  127. if (this.countDownStatus > 0) return
  128. if (!this.valide.mobile) {
  129. return this.$toast.error('请输入合法手机号')
  130. }
  131. try {
  132. await sendMobileVerification({ mobile: this.mobile })
  133. this.startCountDown()
  134. this.$toast.success('验证码已发送')
  135. } catch (e) {
  136. console.log('发送验证码失败')
  137. }
  138. },
  139. // 验证码倒计时
  140. startCountDown() {
  141. this.countDownStatus = 60
  142. if (this.timer) clearInterval(this.timer)
  143. // 开启定时器
  144. this.timer = setInterval(() => {
  145. this.countDownStatus--
  146. if (this.countDownStatus === 0) {
  147. clearInterval(this.timer)
  148. }
  149. }, 1000)
  150. },
  151. // 提交登录
  152. async submit() {
  153. await this.getUserProfile()
  154. const { mobile, verificationCode } = this.valide
  155. if (mobile && verificationCode) {
  156. this.mobileLogin()
  157. }
  158. }
  159. }
  160. }
  161. </script>
  162. <style lang="scss" scoped>
  163. .login-custom {
  164. @extend .cm-flex-center;
  165. align-items: flex-start;
  166. height: 100vh;
  167. background-color: #fff;
  168. .container {
  169. @extend .cm-flex-center;
  170. flex-direction: column;
  171. width: 600rpx;
  172. margin-top: 180rpx;
  173. .logo {
  174. width: 200rpx;
  175. height: 200rpx;
  176. }
  177. .login-form {
  178. width: 100%;
  179. margin: 80rpx 0 25rpx;
  180. .form-control {
  181. width: 100%;
  182. @extend .cm-flex-between;
  183. font-size: 26rpx;
  184. .input {
  185. flex: 1;
  186. }
  187. .validate-code {
  188. flex: 1;
  189. text-align: right;
  190. color: #666;
  191. }
  192. }
  193. .tip {
  194. font-size: 24rpx;
  195. color: #fc464c;
  196. text-align: left;
  197. }
  198. }
  199. }
  200. }
  201. </style>