561 lines
14 KiB
Vue
561 lines
14 KiB
Vue
<template>
|
||
<view class="login-wrap">
|
||
<view class="top-wrap">
|
||
<image src="../../static/538.png" mode="widthFix" style="width: 500rpx;"></image>
|
||
</view>
|
||
<view class="main-wrap">
|
||
<u--form :model="loginForm" :rules="rules" ref="form" labelWidth="31">
|
||
<u-form-item prop="username" borderBottom>
|
||
<uni-easyinput v-model="loginForm.username" clearable :inputBorder="false"
|
||
:placeholder="$tt('login.inputUserName')" prefixIcon="person"
|
||
prefixIconStyle="font-size: 44rpx; margin-right: 10rpx"></uni-easyinput>
|
||
</u-form-item>
|
||
<u-form-item prop="password" borderBottom>
|
||
<uni-easyinput prefixIcon="locked" prefixIconStyle="font-size: 44rpx; margin-right: 10rpx"
|
||
type="password" :inputBorder="false" v-model="loginForm.password"
|
||
:placeholder="$tt('login.inputPassword')"></uni-easyinput>
|
||
</u-form-item>
|
||
<u-form-item prop="code" borderBottom>
|
||
<!-- 注意:由于兼容性差异,如果需要使用前后插槽,nvue下需使用u--input,非nvue下需使用u-input -->
|
||
<!-- 验证码 -->
|
||
<uni-easyinput :placeholder="$tt('login.inputCode')" v-model="loginForm.code" :inputBorder="false"
|
||
prefixIcon="checkbox" prefixIconStyle="font-size: 44rpx; margin-right: 10rpx">
|
||
<template slot="right">
|
||
<u--image :src="codeUrl" width="240rpx" height="60rpx" @click="getCode"></u--image>
|
||
</template>
|
||
</uni-easyinput>
|
||
</u-form-item>
|
||
<!-- 记住密码 -->
|
||
<view prop="rememberMe" style="display: flex; justify-content:flex-end; padding: 20rpx;">
|
||
<view style="font-size: 13px;">
|
||
<u-checkbox-group @change="handleRememberCheckbox">
|
||
<label>
|
||
<u-checkbox :checked="loginForm.rememberMe" style="transform:scale(0.8)" />
|
||
</label>
|
||
<text>
|
||
{{$tt('login.remember')}}
|
||
</text>
|
||
</u-checkbox-group>
|
||
</view>
|
||
</view>
|
||
|
||
<view style="margin-top: 50rpx;">
|
||
<u-button style="height: 90rpx; width: 650rpx;" shape="circle" type="primary"
|
||
:text="$tt('login.login')" @click="handleLogin()"></u-button>
|
||
</view>
|
||
</u--form>
|
||
|
||
<view class="footer-wrap">
|
||
<view class="tipbox">
|
||
<!-- #ifdef APP-PLUS || MP-WEIXIN -->
|
||
<view class="txt">
|
||
—— {{$tt('login.other')}} ——
|
||
</view>
|
||
<!-- #endif -->
|
||
<view class="otherUser">
|
||
<!-- #ifdef APP-PLUS -->
|
||
<uni-icons style="background-color: #e7e7e7; padding: 10rpx; border-radius: 50%; margin: 20rpx;"
|
||
type="weixin" size="24" color="#3c9cff" @click="handleWeChatLogin()"></uni-icons>
|
||
<!-- #endif -->
|
||
<!-- #ifdef MP-WEIXIN -->
|
||
<uni-icons style="background-color: #e7e7e7; padding: 10rpx; border-radius: 50%; margin: 20rpx;"
|
||
type="phone-filled" size="24" color="#3c9cff"
|
||
@click="handleWeChatOneClickLogin"></uni-icons>
|
||
<!-- #endif -->
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="other-wrap">
|
||
<!-- 微信授权弹出框 -->
|
||
<!-- #ifdef MP-WEIXIN -->
|
||
<view class="one-click-login-pop-wrap">
|
||
<u-popup :show="isShowPop" mode="bottom" :round="10" closeable="true" @close="isShowPop = false">
|
||
<view class="content-wrap">
|
||
<u--image :showLoading="true" src="/static/logo_title.png" width="260rpx" height="90rpx"
|
||
customStyle="float:left"></u--image>
|
||
<text class="title">{{$tt("login.welcomeToLogin")}}</text>
|
||
<view class="btn-login">
|
||
<u-button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber"
|
||
@click="isShowPop = false;"
|
||
type="success">{{$tt("login.phoneAuthorization")}}</u-button>
|
||
</view>
|
||
</view>
|
||
</u-popup>
|
||
</view>
|
||
<!-- #endif -->
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { mapState, mapMutations } from 'vuex';
|
||
import projectConfig from '@/env.config.js';
|
||
import { getProfile } from '@/apis/modules/common.js'
|
||
import { encrypt, decrypt } from '@/utils/jsencrypt.js'
|
||
|
||
export default {
|
||
data () {
|
||
return {
|
||
token: '',
|
||
codeUrl: '',
|
||
isClause: false,
|
||
show: false,
|
||
systemLocale: '',
|
||
applicationLocale: '',
|
||
columns: [
|
||
[{
|
||
text: this.$tt('locale.en-US'),
|
||
code: 'en-US'
|
||
},
|
||
{
|
||
text: this.$tt('locale.zh-CN'),
|
||
code: 'zh-CN'
|
||
},
|
||
]
|
||
],
|
||
value: 'English',
|
||
loginForm: {
|
||
username: '',
|
||
password: '',
|
||
rememberMe: false,
|
||
code: '',
|
||
uuid: '',
|
||
},
|
||
rules: {
|
||
username: {
|
||
type: 'string',
|
||
min: 2,
|
||
max: 20,
|
||
required: true,
|
||
message: this.$tt('login.inputUserName'),
|
||
trigger: ['blur', 'change']
|
||
},
|
||
password: {
|
||
type: 'string',
|
||
required: true,
|
||
min: 5,
|
||
max: 20,
|
||
message: this.$tt('login.inputPassword'),
|
||
trigger: ['blur', 'change']
|
||
},
|
||
code: {
|
||
type: 'integer',
|
||
required: true,
|
||
message: this.$tt('login.inputCode'),
|
||
trigger: ['blur', 'change']
|
||
}
|
||
},
|
||
isShowPop: false,
|
||
};
|
||
},
|
||
onLoad () {
|
||
this.loadSelectedLanguage();
|
||
},
|
||
mounted () {
|
||
this.getToken();
|
||
if (this.token != '' && this.token != null) {
|
||
// 跳转主页
|
||
uni.switchTab({
|
||
url: '/pages/tabBar/home/index'
|
||
});
|
||
} else {
|
||
this.getCode();
|
||
this.getAccount();
|
||
}
|
||
},
|
||
methods: {
|
||
loadSelectedLanguage () {
|
||
// 获取之前保存的语言设置
|
||
const selectedLanguage = wx.getStorageSync('language');
|
||
// 如果获取到了,使用该语言设置
|
||
if (selectedLanguage === 'zh-CN') {
|
||
this.applicationLocale = 'zh-CN';
|
||
this.value = '简体中文';
|
||
} else if (selectedLanguage === 'en-US') {
|
||
this.applicationLocale = 'en-US';
|
||
this.value = 'English';
|
||
} else {
|
||
// 如果没有获取到,使用默认设置
|
||
this.applicationLocale = 'zh-CN'; // 默认设置为中文
|
||
this.$i18n.locale = this.applicationLocale;
|
||
this.value = '简体中文';
|
||
}
|
||
},
|
||
onLocaleChange () {
|
||
this.show = true;
|
||
},
|
||
close () {
|
||
this.show = false
|
||
},
|
||
cancel () {
|
||
this.show = false
|
||
},
|
||
confirm (e) {
|
||
this.show = false;
|
||
this.value = e.value[0].text;
|
||
this.$i18n.locale = e.value[0].code;
|
||
uni.setLocale(e.value[0].code);
|
||
wx.setStorageSync('language', e.value[0].code)
|
||
},
|
||
change (e) {
|
||
// console.log('change', e)
|
||
},
|
||
handleLogin () {
|
||
this.$refs.form.validate().then(res => {
|
||
// if (!this.isClause) {
|
||
// uni.showToast({
|
||
// icon: 'none',
|
||
// title: this.$tt('login.readAndCheckTheAgreement'),
|
||
// });
|
||
// return;
|
||
// }
|
||
// 调用登录
|
||
this.$api.common.login(this.loginForm).then(async res => {
|
||
if (res.code == 200) {
|
||
// 存储token和账号
|
||
this.saveToken(res.token);
|
||
this.saveAccount();
|
||
// 获取用户信息
|
||
let profile = await this.getProfile();
|
||
uni.$u.vuex('profile', profile);
|
||
// 跳转主页
|
||
uni.reLaunch({
|
||
url: '/pages/tabBar/home/index'
|
||
});
|
||
} else {
|
||
if (res.msg) {
|
||
uni.showToast({
|
||
icon: "none",
|
||
title: res.msg,
|
||
complete: (res) => {
|
||
setTimeout(() => {
|
||
this.getCode();
|
||
}, 1500);
|
||
}
|
||
})
|
||
}
|
||
}
|
||
})
|
||
}).catch(errors => {
|
||
uni.$u.toast(this.$tt('login.accontMsg'));
|
||
});
|
||
},
|
||
handletestLogin () {
|
||
this.loginForm.username = "fastbee"
|
||
this.loginForm.password = "123456"
|
||
},
|
||
// 微信登录
|
||
handleWeChatLogin () {
|
||
let that = this;
|
||
uni.login({
|
||
provider: 'weixin',
|
||
onlyAuthorize: false,
|
||
success: function (loginRes) {
|
||
if (loginRes) {
|
||
console.log('用户授权成功');
|
||
uni.request({
|
||
url: projectConfig.baseUrl + '/wechat/mobileLogin',
|
||
data: {
|
||
//业务服务器通过code + 仅保存在服务器的appsecret参数,向:微信开放平台接口发起网络请求
|
||
code: loginRes.code,
|
||
accessToken: loginRes.authResult.access_token,
|
||
expiresIn: loginRes.authResult.expires_in,
|
||
refreshToken: loginRes.authResult.refresh_token,
|
||
openId: loginRes.authResult.openid,
|
||
unionId: loginRes.authResult.unionid,
|
||
},
|
||
method: 'post',
|
||
success: async res => {
|
||
if (res.data.code == 200) {
|
||
if (res.data.data.token != null) {
|
||
that.saveToken(res.data.data.token);
|
||
// 获取用户信息
|
||
let profile = await that.getProfile();
|
||
uni.$u.vuex('profile', profile);
|
||
// 跳转主页面
|
||
wx.switchTab({
|
||
url: '/pages/tabBar/home/index'
|
||
})
|
||
} else {
|
||
//跳转绑定页面
|
||
uni.navigateTo({
|
||
url: '/pagesB/login/bindLogin?bindId=' +
|
||
res
|
||
.data.data.bindId,
|
||
})
|
||
}
|
||
} else {
|
||
uni.showToast({
|
||
icon: "none",
|
||
mask: true,
|
||
title: res.data.msg,
|
||
duration: 3000,
|
||
})
|
||
}
|
||
},
|
||
fail (err) {
|
||
console.log(err)
|
||
}
|
||
});
|
||
}
|
||
},
|
||
fail (err) {
|
||
console.log(err)
|
||
}
|
||
})
|
||
},
|
||
// 微信一键登录
|
||
handleWeChatOneClickLogin () {
|
||
this.isShowPop = true;
|
||
},
|
||
// 获取验证码
|
||
getCode () {
|
||
this.$api.common.captchaImage(true).then(res => {
|
||
this.codeUrl = 'data:image/gif;base64,' + res.img;
|
||
this.loginForm.uuid = res.uuid;
|
||
this.loginForm.code = '';
|
||
})
|
||
.catch(err => {
|
||
this.$u.toast(err.msg);
|
||
});
|
||
},
|
||
// 用户注册
|
||
handleRegister () {
|
||
uni.$u.route('/pagesB/login/register');
|
||
},
|
||
//短信登录
|
||
gotoSmsLogin () {
|
||
uni.$u.route('/pagesB/login/smsLogin');
|
||
},
|
||
// 获取用户信息
|
||
getProfile () {
|
||
return new Promise((resolve, reject) => {
|
||
getProfile().then(res => {
|
||
resolve(res.data);
|
||
}).catch(err => {
|
||
this.$u.toast(err.msg);
|
||
})
|
||
});
|
||
},
|
||
saveToken (token) {
|
||
// 本地缓存存储token
|
||
uni.setStorageSync('token', token);
|
||
// vuex存储token
|
||
uni.$u.vuex('vuex_token', token);
|
||
},
|
||
getToken () {
|
||
// 本地缓存获取token
|
||
this.token = uni.getStorageSync('token');
|
||
// vuex存储token
|
||
uni.$u.vuex('vuex_token', this.token);
|
||
},
|
||
// 本地缓存存储
|
||
saveAccount () {
|
||
if (this.loginForm.rememberMe) {
|
||
uni.setStorageSync('username', this.loginForm.username);
|
||
uni.setStorageSync('password', encrypt(this.loginForm.password));
|
||
uni.setStorageSync('rememberMe', this.loginForm.rememberMe)
|
||
} else {
|
||
uni.removeStorageSync('username');
|
||
uni.removeStorageSync('password');
|
||
uni.removeStorageSync('rememberMe');
|
||
}
|
||
},
|
||
// 本地缓存获取
|
||
getAccount () {
|
||
let username = uni.getStorageSync('username');
|
||
let password = uni.getStorageSync('password');
|
||
let rememberMe = uni.getStorageSync('rememberMe');
|
||
if (username && username != '') {
|
||
this.loginForm.username = username;
|
||
}
|
||
if (password && password != '') {
|
||
this.loginForm.password = decrypt(password);
|
||
}
|
||
if (rememberMe != '') {
|
||
this.loginForm.rememberMe = rememberMe;
|
||
}
|
||
},
|
||
//微信小程序登录获取手机号
|
||
getPhoneNumber (e) {
|
||
let that = this;
|
||
wx.login({
|
||
success (res) {
|
||
if (e.detail.code && res.code) {
|
||
console.log('用户授权成功');
|
||
//发起网络请求
|
||
wx.request({
|
||
url: projectConfig.baseUrl + '/wechat/miniLogin',
|
||
data: {
|
||
code: res.code,
|
||
phoneCode: e.detail.code,
|
||
},
|
||
method: 'post',
|
||
success: async res => {
|
||
if (res.data.code == 200) {
|
||
// 存储token和账号
|
||
const token = wx.setStorageSync('token', res.data.data.token)
|
||
that.saveToken(res.data.data.token);
|
||
// 获取用户信息
|
||
let profile = await that.getProfile();
|
||
uni.$u.vuex('profile', profile);
|
||
// 跳转主页
|
||
wx.switchTab({
|
||
url: '/pages/tabBar/home/index'
|
||
});
|
||
} else {
|
||
wx.showToast({
|
||
icon: "none",
|
||
mask: true,
|
||
title: res.data.msg,
|
||
duration: 3000,
|
||
})
|
||
}
|
||
},
|
||
})
|
||
} else {
|
||
console.log('用户拒绝授权');
|
||
}
|
||
}
|
||
})
|
||
},
|
||
// 服务协议
|
||
handleService () {
|
||
let title = this.$tt('login.serviceAgreement');
|
||
let url = projectConfig.officialWebUrl + 'service-agreement.html';
|
||
uni.navigateTo({
|
||
url: `/pages/common/webview/index?title=${title}&url=${url}`
|
||
});
|
||
},
|
||
// 隐私政策
|
||
handlePrivacy () {
|
||
let title = this.$tt('login.privacyPolicy');
|
||
let url = projectConfig.officialWebUrl + 'privacy-policy.html';
|
||
uni.navigateTo({
|
||
url: `/pages/common/webview/index?title=${title}&url=${url}`
|
||
});
|
||
},
|
||
//记住密码
|
||
handleRememberCheckbox (e) {
|
||
this.loginForm.rememberMe = !this.loginForm.rememberMe
|
||
},
|
||
// 勾选协议
|
||
handleClauseCheckbox (e) {
|
||
this.isClause = !this.isClause;
|
||
},
|
||
openhpLink () {
|
||
uni.navigateTo({
|
||
url: '/pages/common/webview/index?url=http://www.hpiot.cn/'
|
||
});
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
page {
|
||
height: 100%;
|
||
}
|
||
|
||
.copyright {
|
||
font-size: 16rpx;
|
||
margin-top: 20rpx;
|
||
}
|
||
|
||
.login-wrap {
|
||
height: 100%;
|
||
|
||
.top-wrap {
|
||
height: 510rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.main-wrap {
|
||
padding: 0 40rpx;
|
||
|
||
.register-wrap {
|
||
margin-top: 40rpx;
|
||
display: flex;
|
||
justify-content: center;
|
||
text-align: center;
|
||
|
||
.now-btn {
|
||
margin-left: 20rpx;
|
||
}
|
||
}
|
||
|
||
.footer-wrap {
|
||
position: fixed;
|
||
bottom: 60rpx;
|
||
left: 0;
|
||
right: 0;
|
||
|
||
.tipbox {
|
||
text-align: center;
|
||
}
|
||
|
||
.otherUser {
|
||
margin-top: 40rpx;
|
||
display: flex;
|
||
justify-content: center;
|
||
}
|
||
|
||
.txt {
|
||
font-size: 28rpx;
|
||
color: #cbcbcb;
|
||
}
|
||
|
||
.item-wrap {
|
||
background-color: #eaeaea;
|
||
width: 50px;
|
||
height: 50px;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin: 10rpx 20rpx;
|
||
}
|
||
|
||
.clause {
|
||
font-size: 28rpx;
|
||
display: inline-block;
|
||
vertical-align: middle;
|
||
|
||
.check_text {}
|
||
|
||
.service,
|
||
.privacy {
|
||
color: #3c9cff;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.other-wrap {
|
||
.one-click-login-pop-wrap {
|
||
.content-wrap {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
margin-top: 90rpx;
|
||
|
||
.title {
|
||
margin-top: 30rpx;
|
||
font-size: 36rpx;
|
||
}
|
||
|
||
.btn-login {
|
||
margin-top: 100rpx;
|
||
margin-bottom: 60rpx;
|
||
width: 320rpx;
|
||
border-radius: 20rpx
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style> |