2025-05-22 16:37:43 +08:00
|
|
|
|
<template>
|
|
|
|
|
<view class="login-wrap">
|
|
|
|
|
<view class="top-wrap">
|
|
|
|
|
<view class="back-btn">
|
|
|
|
|
<u-icon v-if="formIndex==0" name="arrow-left" color="#333333" size="18" @click="handleBack()"></u-icon>
|
|
|
|
|
<u-icon v-if="formIndex==1" name="arrow-left" color="#333333" size="18"
|
|
|
|
|
@click="handleBackLogin"></u-icon>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="register" @click="handleRegister()" v-if="formIndex===0">{{$tt('register.registration')}}
|
|
|
|
|
</view>
|
2025-06-24 10:25:35 +08:00
|
|
|
|
<image class="img" src="https://iot-xcwl.cn/doc/photo/logo.jpg" mode="widthFix"></image>
|
2025-05-22 16:37:43 +08:00
|
|
|
|
</view>
|
|
|
|
|
<view class="main-wrap">
|
|
|
|
|
<view v-if="formIndex==0">
|
|
|
|
|
<text class="title">{{ $tt('login.account') }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="form" v-if="formIndex==0">
|
|
|
|
|
<u--form :model="loginForm" :rules="rules" ref="form" labelWidth="31">
|
|
|
|
|
<u-form-item prop="username">
|
|
|
|
|
<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">
|
|
|
|
|
<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" v-if="captchaOnOff">
|
|
|
|
|
<!-- 注意:由于兼容性差异,如果需要使用前后插槽,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="186rpx" height="68rpx" radius="12rpx"
|
|
|
|
|
@click="getCode"></u--image>
|
|
|
|
|
</template>
|
|
|
|
|
</uni-easyinput>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<!-- 记住密码 -->
|
|
|
|
|
<view prop="rememberMe" style="display: flex; justify-content: space-between; padding-top: 28rpx;">
|
|
|
|
|
<view>
|
|
|
|
|
<u-checkbox-group @change="handleRememberCheckbox" size="34rpx">
|
|
|
|
|
<label>
|
|
|
|
|
<u-checkbox :checked="loginForm.rememberMe" style="transform:scale(1)" />
|
|
|
|
|
</label>
|
|
|
|
|
<text style="font-size: 28rpx;">
|
|
|
|
|
{{$tt('login.remember')}}
|
|
|
|
|
</text>
|
|
|
|
|
</u-checkbox-group>
|
|
|
|
|
</view>
|
|
|
|
|
<!-- 忘记密码 -->
|
|
|
|
|
<view style="font-size: 28rpx; color: #486FF2;" @click="forgetPassword">
|
|
|
|
|
{{$tt('login.forgetPassword')}}
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<view style="margin-top: 60rpx;">
|
|
|
|
|
<button class="Login-button" @click="handleLogin()">{{$tt('login.login')}}</button>
|
|
|
|
|
</view>
|
|
|
|
|
</u--form>
|
|
|
|
|
</view>
|
|
|
|
|
<!-- 忘记密码 -->
|
|
|
|
|
<view class="forgetForm" v-if="formIndex==1">
|
|
|
|
|
<view style="margin-bottom: 40rpx;">
|
|
|
|
|
<text class="title">{{ $tt('login.forgetPassword') }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<u--form :model="fpForm" :rules="fpRules" ref="fpForm" labelWidth="31">
|
|
|
|
|
<u-form-item prop="phoneNumber" labelWidth="0">
|
|
|
|
|
<u-input v-model="fpForm.phoneNumber" clearable :inputBorder="false" border="none"
|
|
|
|
|
:maxlength="11" :placeholder="$tt('register.inputPhone')" prefixIcon="phone"
|
|
|
|
|
prefixIconStyle="font-size: 42rpx;color: rgb(192, 196, 204); margin-left:10rpx"
|
|
|
|
|
placeholderStyle="font-size: 22rpx;"
|
|
|
|
|
:customStyle="{padding:'20rpx 0',backgroundColor:' #fff', borderRradius:' 18rpx'}"></u-input>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<u-form-item prop="code" labelWidth="0">
|
|
|
|
|
<u-input :placeholder="$tt('register.inputCode')" v-model="fpForm.code" clearable border="none"
|
|
|
|
|
:customStyle="{padding:'20rpx 0',backgroundColor:' #fff', borderRradius:' 18rpx'}"
|
|
|
|
|
prefixIcon="integral-fill"
|
|
|
|
|
prefixIconStyle="font-size: 42rpx;color: rgb(192, 196, 204); margin-left:10rpx"
|
|
|
|
|
placeholderStyle="font-size: 22rpx;">
|
|
|
|
|
<template slot="suffix">
|
|
|
|
|
<view style="margin-right: 15rpx;">
|
|
|
|
|
<u-code ref="uCode" @change="codeChange" seconds="60"></u-code>
|
|
|
|
|
<u-button @click="getSmsCode" :text="tips" type="primary" size="small"
|
|
|
|
|
:disabled="fpForm.phoneNumber == ''" style="border:none;"></u-button>
|
|
|
|
|
</view>
|
|
|
|
|
</template>
|
|
|
|
|
</u-input>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<u-form-item prop="password" labelWidth="0">
|
|
|
|
|
<u-input v-model="fpForm.password" clearable :inputBorder="false" border="none"
|
|
|
|
|
prefixIcon="lock-fill" :placeholder="$tt('register.inputPassword')"
|
|
|
|
|
prefixIconStyle="font-size: 42rpx;color: rgb(192, 196, 204); margin-left:10rpx"
|
|
|
|
|
placeholderStyle="font-size: 22rpx;"
|
|
|
|
|
:customStyle="{padding:'20rpx 0',backgroundColor:' #fff', borderRradius:' 18rpx'}"></u-input>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<u-form-item prop="confirmPassword" labelWidth="0">
|
|
|
|
|
<u-input v-model="fpForm.confirmPassword" clearable :inputBorder="false" border="none"
|
|
|
|
|
prefixIcon="lock-fill" type="password" placeholder="确认密码"
|
|
|
|
|
prefixIconStyle="font-size: 42rpx;color: rgb(192, 196, 204); margin-left:10rpx"
|
|
|
|
|
placeholderStyle="font-size: 22rpx;"
|
|
|
|
|
:customStyle="{padding:'20rpx 0',backgroundColor:' #fff', borderRradius:' 18rpx'}"></u-input>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<view style="margin-top: 60rpx;">
|
|
|
|
|
<button class="Login-button" @click="handleForgetPsd()">确认</button>
|
|
|
|
|
</view>
|
|
|
|
|
</u--form>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="footer-wrap" v-if="formIndex===0">
|
|
|
|
|
<view class="tipbox">
|
|
|
|
|
<view class="divider-wrap">
|
|
|
|
|
<u-divider :text="$tt('login.thirdPartyLogin')" textColor="#999999"
|
|
|
|
|
lineColor="#D8D8D8"></u-divider>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="otherUser">
|
|
|
|
|
<!-- 短信登录,app和h5 -->
|
|
|
|
|
<!-- #ifdef APP-PLUS ||H5-->
|
|
|
|
|
<view class="item">
|
|
|
|
|
<uni-icons style="background-color: #E3EDFF; padding: 18rpx 20rpx; border-radius: 12rpx;"
|
|
|
|
|
type="chat-filled" size="24" color="#045FFA" @click="gotoSmsLogin()"></uni-icons>
|
|
|
|
|
<text class="text">{{$tt('login.smsLogin')}}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<!-- #endif -->
|
|
|
|
|
<!-- 微信登录 -->
|
|
|
|
|
<!-- #ifdef APP-PLUS -->
|
|
|
|
|
<view class="item">
|
|
|
|
|
<uni-icons style="background-color: #E3EDFF; padding: 18rpx 20rpx; border-radius: 12rpx;"
|
|
|
|
|
type="weixin" size="24" color="#045FFA" @click="handleWeChatLogin()"></uni-icons>
|
|
|
|
|
<text class="text">{{$tt('login.weChat')}}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<!-- #endif -->
|
|
|
|
|
<!-- 微信小程序,手机一键登录 -->
|
|
|
|
|
<!-- #ifdef MP-WEIXIN -->
|
|
|
|
|
<view class="item">
|
|
|
|
|
<uni-icons style="background-color: #E3EDFF; padding: 18rpx 20rpx; border-radius: 12rpx;"
|
|
|
|
|
type="phone-filled" size="24" color="#486FF2"
|
|
|
|
|
@click="handleWeChatOneClickLogin"></uni-icons>
|
|
|
|
|
<text class="text">{{$tt('login.mobileLogin')}}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<!-- #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="https://iot-xcwl.cn/app/fastbee1_blue.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,
|
|
|
|
|
getSmsCode,
|
|
|
|
|
smsLogin,
|
|
|
|
|
forgetPwdReset
|
|
|
|
|
} 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'
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
],
|
|
|
|
|
// 忘记密码
|
|
|
|
|
fpForm: {
|
|
|
|
|
phoneNumber: '',
|
|
|
|
|
code: '',
|
|
|
|
|
password: '',
|
|
|
|
|
confirmPassword: '',
|
|
|
|
|
},
|
|
|
|
|
captchaOnOff: true, //验证码开关
|
|
|
|
|
formIndex: 0,
|
|
|
|
|
value: 'English',
|
|
|
|
|
loginForm: {
|
|
|
|
|
username: '',
|
|
|
|
|
password: '',
|
|
|
|
|
rememberMe: false,
|
|
|
|
|
code: '',
|
|
|
|
|
uuid: '',
|
|
|
|
|
},
|
|
|
|
|
tips: '',
|
|
|
|
|
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,
|
|
|
|
|
fpRules: {
|
|
|
|
|
phoneNumber: [{
|
|
|
|
|
type: 'integer',
|
|
|
|
|
min: 11,
|
|
|
|
|
max: 11,
|
|
|
|
|
required: true,
|
|
|
|
|
message: this.$tt('register.inputPhone'),
|
|
|
|
|
trigger: ['blur', 'change']
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
validator: (rule, value, callback) => {
|
|
|
|
|
return uni.$u.test.mobile(value);
|
|
|
|
|
},
|
|
|
|
|
message: this.$tt('bindRegister.incorrectPhone'),
|
|
|
|
|
// 触发器可以同时用blur和change
|
|
|
|
|
trigger: ['change', 'blur']
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
code: {
|
|
|
|
|
type: 'string',
|
|
|
|
|
required: true,
|
|
|
|
|
min: 5,
|
|
|
|
|
max: 20,
|
|
|
|
|
message: this.$tt('login.inputCode'),
|
|
|
|
|
trigger: ['blur', 'change']
|
|
|
|
|
},
|
|
|
|
|
password: {
|
|
|
|
|
type: 'string',
|
|
|
|
|
required: true,
|
|
|
|
|
min: 6,
|
|
|
|
|
max: 20,
|
|
|
|
|
message: '请输入密码,长度在6-20个字符',
|
|
|
|
|
trigger: ['blur', 'change']
|
|
|
|
|
},
|
|
|
|
|
confirmPassword: [{
|
|
|
|
|
type: 'string',
|
|
|
|
|
required: true,
|
|
|
|
|
message: this.$tt('user.password7'),
|
|
|
|
|
trigger: ['blur', 'change']
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
validator: (rule, value, callback) => {
|
|
|
|
|
if (this.passwordForm.newPsd !== value) {
|
|
|
|
|
callback(new Error(this.$tt('user.password8')));
|
|
|
|
|
} else {
|
|
|
|
|
callback();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
message: this.$tt('user.password8'),
|
|
|
|
|
trigger: ['blur', 'change'],
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
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 = '简体中文';
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
//获取短信验证码
|
|
|
|
|
getSmsCode() {
|
|
|
|
|
if (this.$refs.uCode.canGetCode) {
|
|
|
|
|
if (this.validatePhoneNumber(this.fpForm.phoneNumber)) {
|
|
|
|
|
if (this.fpForm.phoneNumber) {
|
|
|
|
|
uni.showLoading({
|
|
|
|
|
title: this.$tt('smsLogin.obtainSmsCode')
|
|
|
|
|
});
|
|
|
|
|
getSmsCode(this.fpForm.phoneNumber).then(res => {
|
|
|
|
|
if (res.code == 200) {
|
|
|
|
|
uni.$u.toast(this.$tt('smsLogin.codeSent'));
|
|
|
|
|
// 通知验证码组件内部开始倒计时
|
|
|
|
|
this.$refs.uCode.start();
|
|
|
|
|
} else {
|
|
|
|
|
uni.$u.toast(res.msg);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(err => {
|
|
|
|
|
console.log("err catch", err);
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
uni.$u.toast(this.$tt('register.inputPhone'));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
uni.$u.toast(this.$tt('smsLogin.sending'));
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
//忘记密码
|
|
|
|
|
handleForgetPsd() {
|
|
|
|
|
this.$refs.fpForm.validate().then(res => {
|
|
|
|
|
this.fpLoading = true;
|
|
|
|
|
const {
|
|
|
|
|
confirmPassword,
|
|
|
|
|
...params
|
|
|
|
|
} = this.fpForm;
|
|
|
|
|
forgetPwdReset(params)
|
|
|
|
|
.then((res) => {
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
icon: "success",
|
|
|
|
|
title: res.msg,
|
|
|
|
|
});
|
|
|
|
|
this.formIndex = 0;
|
|
|
|
|
} else {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
icon: "none",
|
|
|
|
|
title: res.msg,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(() => {
|
|
|
|
|
this.fpLoading = false;
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
// 定义校验函数
|
|
|
|
|
validatePhoneNumber(phone) {
|
|
|
|
|
// 正则表达式规则:1开头的10位或者13、14、15、16、17、18、19开头的11位数字
|
|
|
|
|
const regExp =
|
|
|
|
|
/^((1[3-9]\d{9})|((\+?\d{2,3}-)?(13\d{9}|14[57]|15[0-35-9]|16[6]|17[0135678]|18[\d]{9}|\d{3}-\d{8})))$/;
|
|
|
|
|
return regExp.test(phone);
|
|
|
|
|
},
|
|
|
|
|
codeChange(text) {
|
|
|
|
|
this.tips = text;
|
|
|
|
|
text = this.$tt('smsLogin.obtainCode');
|
|
|
|
|
},
|
|
|
|
|
//返回
|
|
|
|
|
handleBack() {
|
|
|
|
|
uni.navigateBack();
|
|
|
|
|
},
|
|
|
|
|
handleBackLogin() {
|
|
|
|
|
this.formIndex = 0;
|
|
|
|
|
},
|
|
|
|
|
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) {},
|
|
|
|
|
handleLogin() {
|
|
|
|
|
this.$refs.form.validate().then(res => {
|
|
|
|
|
// 调用登录
|
|
|
|
|
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"
|
|
|
|
|
},
|
|
|
|
|
// 忘记密码
|
|
|
|
|
forgetPassword() {
|
|
|
|
|
this.formIndex = 1;
|
|
|
|
|
},
|
|
|
|
|
// 微信登录
|
|
|
|
|
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,
|
|
|
|
|
},
|
|
|
|
|
header: {
|
|
|
|
|
language: wx.getStorageSync('language') || 'zh-CN'
|
|
|
|
|
},
|
|
|
|
|
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.captchaOnOff = res.captchaEnabled;
|
|
|
|
|
if (this.captchaOnOff) {
|
|
|
|
|
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('用户授权成功');
|
|
|
|
|
//发起网络请求
|
|
|
|
|
if (projectConfig.baseUrl.endsWith('/')) {
|
|
|
|
|
// 如果以斜杠结尾,则移除它
|
|
|
|
|
projectConfig.baseUrl = projectConfig.baseUrl.slice(0, -1);
|
|
|
|
|
}
|
|
|
|
|
wx.request({
|
|
|
|
|
url: projectConfig.baseUrl + '/wechat/miniLogin',
|
|
|
|
|
data: {
|
|
|
|
|
code: res.code,
|
|
|
|
|
phoneCode: e.detail.code,
|
|
|
|
|
},
|
|
|
|
|
header: {
|
|
|
|
|
language: wx.getStorageSync('language') || 'zh-CN'
|
|
|
|
|
},
|
|
|
|
|
method: 'post',
|
|
|
|
|
success: async res => {
|
|
|
|
|
if (res.data.code == 200) {
|
|
|
|
|
// 存储token和账号
|
|
|
|
|
const token = res.data.data.token;
|
|
|
|
|
that.saveToken(token);
|
|
|
|
|
// 获取用户信息
|
|
|
|
|
let profile = await that.getProfile();
|
|
|
|
|
uni.$u.vuex('profile', profile);
|
|
|
|
|
// 跳转主页
|
|
|
|
|
uni.reLaunch({
|
|
|
|
|
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 {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
padding-top: var(--status-bar-height);
|
|
|
|
|
height: 100vh;
|
|
|
|
|
background-image: linear-gradient(45deg,
|
|
|
|
|
rgba(216, 216, 216, 0.3) 0,
|
|
|
|
|
rgba(225, 225, 225, 0) 100%);
|
|
|
|
|
|
|
|
|
|
.top-wrap {
|
|
|
|
|
position: relative;
|
|
|
|
|
display: flex;
|
|
|
|
|
|
|
|
|
|
.back-btn {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 70rpx;
|
|
|
|
|
left: 46rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.register {
|
|
|
|
|
position: absolute;
|
|
|
|
|
// #ifdef MP-WEIXIN
|
|
|
|
|
top: 140rpx;
|
|
|
|
|
// #endif
|
|
|
|
|
// #ifndef MP-WEIXIN
|
|
|
|
|
top: 70rpx;
|
|
|
|
|
// #endif
|
|
|
|
|
right: 46rpx;
|
|
|
|
|
line-height: 36rpx;
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.img {
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
width: 338rpx;
|
|
|
|
|
margin-top: 236rpx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.main-wrap {
|
|
|
|
|
flex: 1 auto;
|
|
|
|
|
padding-left: 80rpx;
|
|
|
|
|
padding-right: 80rpx;
|
|
|
|
|
margin-top: 142rpx;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
//display: grid;
|
|
|
|
|
|
|
|
|
|
.title {
|
|
|
|
|
font-size: 40rpx;
|
|
|
|
|
letter-spacing: 0.6rpx;
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.form {
|
|
|
|
|
margin-top: 46rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.forgetForm {
|
|
|
|
|
margin-top: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.Login-button {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
align-items: center;
|
|
|
|
|
height: 98rpx;
|
|
|
|
|
border-radius: 18rpx;
|
|
|
|
|
color: #fff;
|
|
|
|
|
background-color: #486FF2;
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
letter-spacing: 0.6rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.footer-wrap {
|
|
|
|
|
margin-top: auto;
|
|
|
|
|
margin-bottom: 38px;
|
|
|
|
|
|
|
|
|
|
.tipbox {
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
|
|
|
|
.divider-wrap {
|
|
|
|
|
margin-bottom: 38rpx;
|
|
|
|
|
padding: 0 112rpx;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.otherUser {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
|
|
|
|
.item {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: center;
|
|
|
|
|
width: 136rpx;
|
|
|
|
|
|
|
|
|
|
.text {
|
|
|
|
|
margin-top: 10rpx;
|
|
|
|
|
letter-spacing: 0.6rpx;
|
|
|
|
|
font-size: 20rpx;
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.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;
|
|
|
|
|
|
|
|
|
|
.service,
|
|
|
|
|
.privacy {
|
|
|
|
|
color: #486FF2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
::v-deep .uni-easyinput__content-input {
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
height: 88rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
::v-deep .uni-easyinput__content {
|
|
|
|
|
border-radius: 18rpx;
|
|
|
|
|
}
|
|
|
|
|
</style>
|