phoneLogin.vue 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <template>
  2. <view class="wrap">
  3. <view class="content">
  4. <view class="title">手机号登录</view>
  5. <input class="u-border-bottom" type="number" maxlength="11" v-model="tel" placeholder="请输入手机号" />
  6. <view class="u-text-center u-type-error u-m-t-20" v-if="telError">手机号输入错误</view>
  7. <button @tap="submit" :style="[inputStyle]" class="getCaptcha">获取短信验证码</button>
  8. <u-message-input
  9. v-if="show"
  10. :focus="true"
  11. :value="messageCode"
  12. @change="change"
  13. @finish="finish"
  14. mode="bottomLine"
  15. :maxlength="codelength"
  16. ></u-message-input>
  17. </view>
  18. <view class="captcha">
  19. <text v-if="messageShow">{{ second }}秒后可重新获取验证码</text>
  20. </view>
  21. <view class="buttom">
  22. <view class="hint u-text-center">
  23. 登录代表同意
  24. <text class="link" @tap="jumpToPage(1)">《用户服务条款》</text>和
  25. <text class="link" @tap="jumpToPage(2)">《隐私政策》</text>
  26. 并授权使用您的账号信息(如昵称、头像、收货地址)以便您统一管理
  27. </view>
  28. </view>
  29. <u-toast ref="uToast" />
  30. </view>
  31. </template>
  32. <script>
  33. import getUrlParams from './../../../utils/getUrlParams.js';
  34. export default {
  35. data() {
  36. return {
  37. tel: '',
  38. messageCode: '',
  39. messageShow: false,
  40. messageDisable: false,
  41. codelength: 4,
  42. show: false,
  43. second: 60,
  44. toastMsg: '',
  45. toastUrl: '',
  46. toastType: '',
  47. accessToken: '',
  48. userId: '',
  49. telError: false,
  50. openId: ''
  51. };
  52. },
  53. onLoad(page) {
  54. this.openId = this.vuex_wxinfo?.openId;
  55. const backUrl = location.href;
  56. if (!this.openId) {
  57. // 判断浏览器
  58. const ua = window.navigator.userAgent.toLowerCase();
  59. if (ua.match(/MicroMessenger/i) == 'micromessenger') {
  60. // 微信中打开
  61. this.$u.route('pages/wechatLogin/wechatLogin', {
  62. backUrl
  63. });
  64. }
  65. }
  66. const pages = getCurrentPages();
  67. if (pages.length >= 2) {
  68. uni.setStorageSync('last_page', pages[pages.length - 2].route);
  69. if (pages[pages.length - 2].options) {
  70. uni.setStorageSync('last_page_options', pages[pages.length - 2].options);
  71. }
  72. }
  73. },
  74. computed: {
  75. inputStyle() {
  76. let style = {};
  77. if (this.tel.length == 11 && this.messageDisable == false && this.$u.test.mobile(this.tel)) {
  78. style.color = '#fff';
  79. style.backgroundColor = '#5295F5';
  80. this.telError = false;
  81. } else if (this.tel.length == 11 && !this.$u.test.mobile(this.tel)) {
  82. this.telError = true;
  83. }
  84. return style;
  85. }
  86. },
  87. methods: {
  88. showToast() {
  89. this.$refs.uToast.show({
  90. title: this.toastMsg,
  91. type: this.toastType,
  92. url: this.toastUrl
  93. });
  94. },
  95. submit() {
  96. if (this.$u.test.mobile(this.tel) && this.messageDisable == false) {
  97. let that = this;
  98. this.$u.api.userLoginApi.sendSmsCodeApi({ mobile: this.tel }).then((res) => {
  99. this.messageDisable = true;
  100. this.messageShow = true;
  101. this.show = true;
  102. let interval = setInterval(() => {
  103. that.second--;
  104. if (that.second <= 0) {
  105. that.messageDisable = false;
  106. that.messageShow = false;
  107. clearInterval(interval);
  108. that.second = 60;
  109. }
  110. }, 1000);
  111. this.accessToken = res?.data?.accessToken;
  112. this.userId = res?.data?.userId;
  113. });
  114. }
  115. },
  116. // change事件侦听
  117. change(value) {
  118. // console.log('change', value);
  119. },
  120. // 输入完验证码最后一位执行
  121. finish(value) {
  122. let params = {
  123. loginType: 1,
  124. nickName: this.vuex_wxinfo?.nickname,
  125. code: value,
  126. openId: this.vuex_wxinfo?.openId,
  127. mobile: this.tel,
  128. avatar: this.vuex_wxinfo?.headImgUrl
  129. };
  130. this.$u.api.userLoginApi
  131. .mobileLoginApi(params)
  132. .then((res) => {
  133. if (res.code == '200') {
  134. this.$u.vuex('vuex_token', res.data.accessToken);
  135. this.$u.vuex('vuex_user', res.data);
  136. this.$u.vuex('vuex_hasLogin', true);
  137. setTimeout(() => {
  138. this.jumpIndex();
  139. }, 500);
  140. } else {
  141. this.$refs.uToast.show({
  142. title: res.msg,
  143. type: 'error'
  144. });
  145. }
  146. })
  147. .catch((err) => {
  148. this.toastMsg = err.msg;
  149. this.showToast();
  150. });
  151. },
  152. // 微信已登录则跳转到首页
  153. jumpIndex() {
  154. let ret = localStorage.getItem('backUrl');
  155. ret = decodeURIComponent(ret);
  156. if ((ret && ret.indexOf('wechatLogin') > -1) || (ret && ret.indexOf('phoneLogin') < 0)) {
  157. // 截取url
  158. const pagesIndex = ret.indexOf('pages');
  159. if (pagesIndex > -1) {
  160. const pageUrl = ret.slice(pagesIndex);
  161. const tabbarUrl = ['pages/center/index', 'pages/parkingLists/parkingLists', 'page/index/index'];
  162. if (tabbarUrl.indexOf(pageUrl) > -1) {
  163. setTimeout(() => {
  164. uni.switchTab({
  165. url: '../../index/index'
  166. });
  167. }, 100);
  168. } else {
  169. setTimeout(() => {
  170. uni.redirectTo({
  171. url: '/' + pageUrl
  172. });
  173. }, 100);
  174. }
  175. } else {
  176. uni.switchTab({
  177. url: '../../index/index'
  178. });
  179. }
  180. } else {
  181. uni.switchTab({
  182. url: '/pages/index/index'
  183. });
  184. }
  185. },
  186. /**
  187. * 跳转页面
  188. * */
  189. jumpToPage(flag) {
  190. uni.navigateTo({
  191. url: '/pages/privacyPolicy/privacyPolicy?termsType=' + flag
  192. });
  193. }
  194. }
  195. };
  196. </script>
  197. <style lang="scss" scoped>
  198. .hide {
  199. display: none !important;
  200. }
  201. .wrap {
  202. font-size: 28rpx;
  203. .content {
  204. width: 600rpx;
  205. margin: 80rpx auto 0;
  206. .title {
  207. text-align: left;
  208. font-size: 60rpx;
  209. font-weight: 500;
  210. margin-bottom: 100rpx;
  211. }
  212. input {
  213. text-align: left;
  214. margin-bottom: 10rpx;
  215. padding-bottom: 20rpx;
  216. border-bottom: 1px solid #ddd;
  217. }
  218. .getCaptcha {
  219. margin: 45rpx auto 130rpx;
  220. background-color: #a8c6f1;
  221. color: $u-tips-color;
  222. border: none;
  223. font-size: 30rpx;
  224. padding: 12rpx 0;
  225. &::after {
  226. border: none;
  227. }
  228. }
  229. }
  230. .buttom {
  231. .hint {
  232. padding: 20rpx 40rpx;
  233. font-size: 20rpx;
  234. color: $u-tips-color;
  235. .link {
  236. color: $u-type-warning;
  237. }
  238. }
  239. }
  240. .captcha {
  241. color: $u-type-warning;
  242. font-size: 30rpx;
  243. margin-top: 40rpx;
  244. text-align: center;
  245. }
  246. }
  247. </style>