|
@@ -1,423 +1,144 @@
|
|
|
<template>
|
|
|
- <view class="content">
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- <view style="margin-top: 300rpx;">
|
|
|
- <view class="input-group">
|
|
|
- <view class="input-row">
|
|
|
- <text class="title"><tui-icon name="mobile" :size="22"></tui-icon></text>
|
|
|
- <m-input class="m-input" type="text" clearable focus v-model="mobile" placeholder="请输入手机号码"></m-input>
|
|
|
- </view>
|
|
|
- <view class="input-row" style="margin-top: 10px;">
|
|
|
- <text class="title"><tui-icon name="shield" :size="22"></tui-icon></text>
|
|
|
- <m-input type="text" v-model="code" placeholder="请输入验证码"></m-input>
|
|
|
- <tui-button type="black" disabled margin="15rpx 15rpx 15rpx 15rpx" plain shape="rightAngle" width="130rpx" height="50rpx" :size="24" @click="sendSmsCode">{{codeDuration ? codeDuration + 's' : '发送验证码' }}</tui-button>
|
|
|
- </view>
|
|
|
- </view>
|
|
|
- <view class="btn-row">
|
|
|
- <tui-button type="warning" @tap="bindLogin">登录</tui-button>
|
|
|
- </view>
|
|
|
-
|
|
|
- <view class="oauth-row" v-if="hasProvider" v-bind:style="{top: positionTop + 'px'}">
|
|
|
- <view class="oauth-image" v-for="provider in providerList" :key="provider.value">
|
|
|
- <image :src="provider.image" @tap="oauth(provider.value)"></image>
|
|
|
- <!-- #ifdef MP-WEIXIN -->
|
|
|
- <button v-if="!isDevtools" open-type="getUserInfo" @getuserinfo="getUserInfo"></button>
|
|
|
- <!-- #endif -->
|
|
|
- </view>
|
|
|
- </view>
|
|
|
+ <view>
|
|
|
+ <view class="login">
|
|
|
+ <image src="../../static/images/logo.jpg" class="logo"></image>
|
|
|
+ <view class="item">
|
|
|
+ <text class="icon"></text>
|
|
|
+ <input type="number" placeholder="输入手机号" v-model="item.mobile" />
|
|
|
+ </view>
|
|
|
+ <view class="item">
|
|
|
+ <text class="icon"></text>
|
|
|
+ <input type="number" placeholder="输入短信验证码" v-model="item.captcha" />
|
|
|
+ <text class="code" @click="captchaSend()">{{ msg }}</text>
|
|
|
+ </view>
|
|
|
+ <button type="warn" @click="login()">登陆</button>
|
|
|
+ <view class="divider"><view>第三方登陆</view></view>
|
|
|
+ <view class="third">
|
|
|
+ <view class="weixin"><text class="icon"></text></view>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
-
|
|
|
-
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
- import service from '@/service.js';
|
|
|
- import tuiIcon from "@/components/thorui/tui-icon/tui-icon"
|
|
|
- import tuiButton from "@/components/thorui/tui-button/tui-button"
|
|
|
-
|
|
|
- import {
|
|
|
- mapState,
|
|
|
- mapMutations
|
|
|
- } from 'vuex'
|
|
|
- import mInput from '@/components/m-input.vue'
|
|
|
-
|
|
|
- export default {
|
|
|
- components: {
|
|
|
- mInput,
|
|
|
- tuiButton,
|
|
|
- tuiIcon
|
|
|
- },
|
|
|
- data() {
|
|
|
- return {
|
|
|
- loginType: 0,
|
|
|
- loginTypeList: ['密码登录', '免密登录'],
|
|
|
- mobile: '',
|
|
|
- code: '',
|
|
|
- providerList: [],
|
|
|
- hasProvider: false,
|
|
|
- username: '',
|
|
|
- password: '',
|
|
|
- positionTop: 0,
|
|
|
- isDevtools: false,
|
|
|
- codeDuration: 0
|
|
|
+export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ item: {},
|
|
|
+ msg: '获取短信',
|
|
|
+ flag: true,
|
|
|
+ time: 60
|
|
|
+ };
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ //发送验证码
|
|
|
+ captchaSend() {
|
|
|
+ if (!this.flag) {
|
|
|
+ return;
|
|
|
}
|
|
|
- },
|
|
|
- computed: mapState(['forcedLogin']),
|
|
|
- methods: {
|
|
|
- ...mapMutations(['login']),
|
|
|
- initProvider() {
|
|
|
- const filters = ['weixin', 'qq', 'sinaweibo'];
|
|
|
- uni.getProvider({
|
|
|
- service: 'oauth',
|
|
|
- success: (res) => {
|
|
|
- if (res.provider && res.provider.length) {
|
|
|
- for (let i = 0; i < res.provider.length; i++) {
|
|
|
- if (~filters.indexOf(res.provider[i])) {
|
|
|
- this.providerList.push({
|
|
|
- value: res.provider[i],
|
|
|
- image: '../../static/img/' + res.provider[i] + '.png'
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- this.hasProvider = true;
|
|
|
- }
|
|
|
- },
|
|
|
- fail: (err) => {
|
|
|
- console.error('获取服务供应商失败:' + JSON.stringify(err));
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
- initPosition() {
|
|
|
- /**
|
|
|
- * 使用 absolute 定位,并且设置 bottom 值进行定位。软键盘弹出时,底部会因为窗口变化而被顶上来。
|
|
|
- * 反向使用 top 进行定位,可以避免此问题。
|
|
|
- */
|
|
|
- this.positionTop = uni.getSystemInfoSync().windowHeight - 100;
|
|
|
- },
|
|
|
- sendSmsCode() {
|
|
|
- if(this.codeDuration) {
|
|
|
- uni.showModal({
|
|
|
- content: `请在${this.codeDuration}秒后重试`,
|
|
|
- showCancel: false
|
|
|
- })
|
|
|
- }
|
|
|
- if (!/^1\d{10}$/.test(this.mobile)) {
|
|
|
- uni.showModal({
|
|
|
- content: '手机号码填写错误',
|
|
|
- showCancel: false
|
|
|
- })
|
|
|
- return
|
|
|
- }
|
|
|
- uniCloud.callFunction({
|
|
|
- name: 'user-center',
|
|
|
- data: {
|
|
|
- action: 'sendSmsCode',
|
|
|
- params: {
|
|
|
- mobile: this.mobile
|
|
|
- }
|
|
|
- },
|
|
|
- success: (e) => {
|
|
|
- if (e.result.code == 0) {
|
|
|
- uni.showModal({
|
|
|
- content: '验证码发送成功,请注意查收',
|
|
|
- showCancel: false
|
|
|
- })
|
|
|
- this.codeDuration = 60
|
|
|
- this.codeInterVal = setInterval(() => {
|
|
|
- this.codeDuration--
|
|
|
- if (this.codeDuration === 0) {
|
|
|
- if (this.codeInterVal) {
|
|
|
- clearInterval(this.codeInterVal)
|
|
|
- this.codeInterVal = null
|
|
|
- }
|
|
|
- }
|
|
|
- }, 1000)
|
|
|
- } else {
|
|
|
- uni.showModal({
|
|
|
- content: '验证码发送失败:' + e.result.msg,
|
|
|
- showCancel: false
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- },
|
|
|
- fail(e) {
|
|
|
- uni.showModal({
|
|
|
- content: '验证码发送失败',
|
|
|
- showCancel: false
|
|
|
- })
|
|
|
- }
|
|
|
- })
|
|
|
- },
|
|
|
- loginByPwd() {
|
|
|
- /**
|
|
|
- * 客户端对账号信息进行一些必要的校验。
|
|
|
- * 实际开发中,根据业务需要进行处理,这里仅做示例。
|
|
|
- */
|
|
|
- if (this.username.length < 3) {
|
|
|
- uni.showToast({
|
|
|
- icon: 'none',
|
|
|
- title: '账号最短为 3 个字符'
|
|
|
- });
|
|
|
- return;
|
|
|
- }
|
|
|
- if (this.password.length < 6) {
|
|
|
- uni.showToast({
|
|
|
- icon: 'none',
|
|
|
- title: '密码最短为 6 个字符'
|
|
|
- });
|
|
|
- return;
|
|
|
- }
|
|
|
- const data = {
|
|
|
- username: this.username,
|
|
|
- password: this.password
|
|
|
- };
|
|
|
- let _self = this;
|
|
|
-
|
|
|
- uniCloud.callFunction({
|
|
|
- name: 'user-center',
|
|
|
- data: {
|
|
|
- action: 'login',
|
|
|
- params: data
|
|
|
- },
|
|
|
- success: (e) => {
|
|
|
-
|
|
|
- console.log('login success', e);
|
|
|
-
|
|
|
- if (e.result.code == 0) {
|
|
|
- uni.setStorageSync('uniIdToken', e.result.token)
|
|
|
- uni.setStorageSync('username', e.result.username)
|
|
|
- uni.setStorageSync('login_type', 'online')
|
|
|
- _self.toMain(_self.username);
|
|
|
- } else {
|
|
|
- uni.showModal({
|
|
|
- content: e.result.msg,
|
|
|
- showCancel: false
|
|
|
- })
|
|
|
- console.log('登录失败', e);
|
|
|
- }
|
|
|
-
|
|
|
- },
|
|
|
- fail(e) {
|
|
|
- uni.showModal({
|
|
|
- content: JSON.stringify(e),
|
|
|
- showCancel: false
|
|
|
- })
|
|
|
- }
|
|
|
- })
|
|
|
- },
|
|
|
- loginBySms() {
|
|
|
- if (!/^1\d{10}$/.test(this.mobile)) {
|
|
|
- uni.showModal({
|
|
|
- content: '手机号码填写错误',
|
|
|
- showCancel: false
|
|
|
- })
|
|
|
- return
|
|
|
- }
|
|
|
- if (!/^\d{6}$/.test(this.code)) {
|
|
|
- uni.showModal({
|
|
|
- title: '验证码为6位纯数字',
|
|
|
- showCancel: false
|
|
|
- });
|
|
|
- return;
|
|
|
- }
|
|
|
- let _self = this;
|
|
|
-
|
|
|
- uniCloud.callFunction({
|
|
|
- name: 'user-center',
|
|
|
- data: {
|
|
|
- action: 'loginBySms',
|
|
|
- params: {
|
|
|
- mobile: this.mobile,
|
|
|
- code: this.code
|
|
|
- }
|
|
|
- },
|
|
|
- success: (e) => {
|
|
|
-
|
|
|
- console.log('login success', e);
|
|
|
-
|
|
|
- if (e.result.code == 0) {
|
|
|
- const username = e.result.username || '新用户'
|
|
|
- uni.setStorageSync('uniIdToken', e.result.token)
|
|
|
- uni.setStorageSync('username', username)
|
|
|
- uni.setStorageSync('login_type', 'online')
|
|
|
- _self.toMain(username);
|
|
|
+ this.$http.request({
|
|
|
+ url: this.$http.urls.captchaSend,
|
|
|
+ data: { mobile: this.item.mobile, type: 2 },
|
|
|
+ success: res => {
|
|
|
+ uni.showToast({ title: '发送成功' });
|
|
|
+ //一分钟倒计时
|
|
|
+ var countdown = setInterval(() => {
|
|
|
+ this.time--;
|
|
|
+ if (this.time == 0) {
|
|
|
+ this.flag = true;
|
|
|
+ this.msg = '获取短信';
|
|
|
+ this.time = 60;
|
|
|
+ clearInterval(countdown);
|
|
|
} else {
|
|
|
- uni.showModal({
|
|
|
- content: e.result.msg,
|
|
|
- showCancel: false
|
|
|
- })
|
|
|
- console.log('登录失败', e);
|
|
|
+ this.flag = false;
|
|
|
+ this.msg = '重新获取(' + this.time + ')';
|
|
|
}
|
|
|
-
|
|
|
- },
|
|
|
- fail(e) {
|
|
|
- uni.showModal({
|
|
|
- content: JSON.stringify(e),
|
|
|
- showCancel: false
|
|
|
- })
|
|
|
- }
|
|
|
- })
|
|
|
- },
|
|
|
- bindLogin() {
|
|
|
- switch (this.loginType) {
|
|
|
- case 0:
|
|
|
- this.loginByPwd()
|
|
|
- break;
|
|
|
- case 1:
|
|
|
- this.loginBySms()
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
+ }, 1000);
|
|
|
}
|
|
|
- },
|
|
|
- oauth(value) {
|
|
|
- console.log('三方登录只演示登录api能力,暂未关联云端数据');
|
|
|
- uni.login({
|
|
|
- provider: value,
|
|
|
- success: (res) => {
|
|
|
- uni.getUserInfo({
|
|
|
- provider: value,
|
|
|
- success: (infoRes) => {
|
|
|
- /**
|
|
|
- * 实际开发中,获取用户信息后,需要将信息上报至服务端。
|
|
|
- * 服务端可以用 userInfo.openId 作为用户的唯一标识新增或绑定用户信息。
|
|
|
- */
|
|
|
- this.loginLocal(infoRes.userInfo.nickName);
|
|
|
- },
|
|
|
- fail() {
|
|
|
- uni.showToast({
|
|
|
- icon: 'none',
|
|
|
- title: '登陆失败'
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
- fail: (err) => {
|
|
|
- console.error('授权登录失败:' + JSON.stringify(err));
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
- getUserInfo({
|
|
|
- detail
|
|
|
- }) {
|
|
|
- console.log('三方登录只演示登录api能力,暂未关联云端数据');
|
|
|
- if (detail.userInfo) {
|
|
|
- this.loginLocal(detail.userInfo.nickName);
|
|
|
- } else {
|
|
|
- uni.showToast({
|
|
|
- icon: 'none',
|
|
|
- title: '登陆失败'
|
|
|
- });
|
|
|
- }
|
|
|
- },
|
|
|
- loginLocal(nickName) {
|
|
|
- uni.setStorageSync('login_type', 'local')
|
|
|
- uni.setStorageSync('username', nickName)
|
|
|
- this.toMain(nickName);
|
|
|
- },
|
|
|
- toMain(userName) {
|
|
|
- this.login(userName);
|
|
|
- /**
|
|
|
- * 强制登录时使用reLaunch方式跳转过来
|
|
|
- * 返回首页也使用reLaunch方式
|
|
|
- */
|
|
|
- if (this.forcedLogin) {
|
|
|
- uni.reLaunch({
|
|
|
- url: '../main/main',
|
|
|
- });
|
|
|
- } else {
|
|
|
+ });
|
|
|
+ },
|
|
|
+ //登陆
|
|
|
+ login() {
|
|
|
+ //数据校验
|
|
|
+ let rule = [{ name: 'mobile', checkType: 'phoneno', errorMsg: '请输入正确的手机号' }, { name: 'captcha', checkType: 'notnull', errorMsg: '输入短信验证码' }];
|
|
|
+ let checkRes = this.$verify.check(this.item, rule);
|
|
|
+ if (!checkRes) {
|
|
|
+ uni.showToast({ title: this.$verify.error, icon: 'none' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.$http.request({
|
|
|
+ url: this.$http.urls.login,
|
|
|
+ data:this.item,
|
|
|
+ success: res => {
|
|
|
+ uni.showToast({ title: '登陆成功' });
|
|
|
+ uni.setStorageSync('user', res.data.data.user);
|
|
|
+ uni.$emit('update');
|
|
|
uni.navigateBack();
|
|
|
}
|
|
|
-
|
|
|
- }
|
|
|
- },
|
|
|
- onReady() {
|
|
|
- this.initPosition();
|
|
|
- this.initProvider();
|
|
|
- // #ifdef MP-WEIXIN
|
|
|
- this.isDevtools = uni.getSystemInfoSync().platform === 'devtools';
|
|
|
- // #endif
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
+};
|
|
|
</script>
|
|
|
|
|
|
-<style>
|
|
|
- .content {
|
|
|
- background-color: #C74547;
|
|
|
- }
|
|
|
- .login-type {
|
|
|
- display: flex;
|
|
|
- justify-content: center;
|
|
|
- }
|
|
|
-
|
|
|
- .login-type-btn {
|
|
|
- line-height: 30px;
|
|
|
- margin: 0px 15px;
|
|
|
- }
|
|
|
-
|
|
|
- .login-type-btn.act {
|
|
|
- color: #C74547;
|
|
|
- border-bottom: solid 1px #C74547;
|
|
|
- }
|
|
|
-
|
|
|
- .input-row .title {
|
|
|
- width: auto;
|
|
|
- padding-left: 30rpx;
|
|
|
- }
|
|
|
-
|
|
|
- .send-code-btn {
|
|
|
- text-align: center;
|
|
|
- color: #a3a3a3;
|
|
|
- font-size: 20rpx;
|
|
|
- border: solid 1px #a3a3a3;
|
|
|
- }
|
|
|
-
|
|
|
- .action-row {
|
|
|
- display: flex;
|
|
|
- flex-direction: row;
|
|
|
- justify-content: center;
|
|
|
+<style lang="scss">
|
|
|
+page {
|
|
|
+ background-color: $theme-color;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+.login {
|
|
|
+ padding: 15px;
|
|
|
+ .logo {
|
|
|
+ width: 150px;
|
|
|
+ height: 150px;
|
|
|
}
|
|
|
-
|
|
|
- .action-row navigator {
|
|
|
- color: #C74547;
|
|
|
- padding: 0 10px;
|
|
|
- }
|
|
|
-
|
|
|
- .oauth-row {
|
|
|
- display: flex;
|
|
|
- flex-direction: row;
|
|
|
- justify-content: center;
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- width: 100%;
|
|
|
+ .item {
|
|
|
+ background-color: white;
|
|
|
+ padding: 15px;
|
|
|
+ margin-top: 15px;
|
|
|
+ border-radius: 3px;
|
|
|
+ overflow: hidden;
|
|
|
+ text-align: left;
|
|
|
+ font-size: 14px;
|
|
|
+ .icon {
|
|
|
+ float: left;
|
|
|
+ font-size: 24px;
|
|
|
+ }
|
|
|
+ input {
|
|
|
+ float: left;
|
|
|
+ padding-left: 10px;
|
|
|
+ width: 50%;
|
|
|
+ }
|
|
|
+ .code {
|
|
|
+ float: right;
|
|
|
+ color: #565656;
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- .oauth-image {
|
|
|
- position: relative;
|
|
|
- width: 50px;
|
|
|
- height: 50px;
|
|
|
- border: 1px solid #dddddd;
|
|
|
- border-radius: 50px;
|
|
|
- margin: 0 20px;
|
|
|
- background-color: #ffffff;
|
|
|
+ button {
|
|
|
+ margin-top: 36px;
|
|
|
+ width: 85%;
|
|
|
+ background-color: #ebb827;
|
|
|
+ color: white;
|
|
|
}
|
|
|
-
|
|
|
- .oauth-image image {
|
|
|
- width: 30px;
|
|
|
- height: 30px;
|
|
|
- margin: 10px;
|
|
|
+ .divider {
|
|
|
+ color: white;
|
|
|
+ font-size: 13px;
|
|
|
+ margin-top: 76px;
|
|
|
}
|
|
|
-
|
|
|
- .oauth-image button {
|
|
|
- position: absolute;
|
|
|
- left: 0;
|
|
|
- top: 0;
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- opacity: 0;
|
|
|
+ .third {
|
|
|
+ margin-top: 20px;
|
|
|
+ .weixin {
|
|
|
+ width: 50px;
|
|
|
+ height: 50px;
|
|
|
+ margin: 0 auto;
|
|
|
+ border: 1px solid white;
|
|
|
+ border-radius: 50%;
|
|
|
+ color: white;
|
|
|
+ .icon {
|
|
|
+ font-size: 33px;
|
|
|
+ line-height: 50px;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+}
|
|
|
</style>
|