241 lines
5.0 KiB
Vue
241 lines
5.0 KiB
Vue
<template>
|
||
<view class="login-container">
|
||
<customNavbar opacity="0" :show-home="true" :show-back="false" :is-transparent="true" />
|
||
|
||
<view class="content">
|
||
<view class="title">登录</view>
|
||
|
||
<view class="illustration">
|
||
<image :src="staticHost + '/public/static/login/bg.png'" mode="aspectFit" />
|
||
</view>
|
||
|
||
<button class="login-btn" open-type="getPhoneNumber" @getphonenumber="onGetPhone">
|
||
手机号快捷登录
|
||
</button>
|
||
|
||
<!-- 恢复v-model,同时保留防错乱逻辑 -->
|
||
<view class="user-type">
|
||
<u-radio-group v-model="loginType" active-color="#EA414A" shape="square">
|
||
<u-radio name="0">个人</u-radio>
|
||
<u-radio name="1">企业</u-radio>
|
||
</u-radio-group>
|
||
</view>
|
||
|
||
<view class="agreement">
|
||
<u-checkbox v-model="agreeProtocol" shape="square" active-color="#EA414A">
|
||
<text class="agreement-text">
|
||
我已阅读并同意
|
||
<text class="link" @tap.stop="goPrivacy('user')">《用户协议》</text>
|
||
和
|
||
<text class="link" @tap.stop="goPrivacy('privacy')">《隐私政策》</text>
|
||
</text>
|
||
</u-checkbox>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
data() {
|
||
return {
|
||
loginType: "0", // 默认个人,恢复默认选中
|
||
agreeProtocol: false
|
||
};
|
||
},
|
||
computed: {
|
||
staticHost() {
|
||
return this.$config.staticUrl;
|
||
}
|
||
},
|
||
methods: {
|
||
async onGetPhone(e) {
|
||
if (e.detail.errMsg !== "getPhoneNumber:ok") {
|
||
this.$mytip.toast("已取消授权");
|
||
return;
|
||
}
|
||
|
||
if (!this.agreeProtocol) {
|
||
this.$mytip.toast("请先同意用户协议与隐私政策");
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const loginRes = await new Promise((resolve, reject) => {
|
||
uni.login({
|
||
provider: "weixin",
|
||
success: resolve,
|
||
fail: reject
|
||
});
|
||
});
|
||
|
||
// 🔥 关键:登录瞬间快照当前类型,防异步错乱
|
||
const currentType = this.loginType;
|
||
|
||
await this.doLogin({
|
||
phoneGetCode: e.detail.code,
|
||
loginCode: loginRes.code,
|
||
loginType: this.loginType
|
||
});
|
||
|
||
} catch (err) {
|
||
this.$mytip.toast("授权失败,请重试");
|
||
}
|
||
},
|
||
|
||
async doLogin(data) {
|
||
uni.showLoading({
|
||
title: "登录中...",
|
||
mask: true
|
||
});
|
||
|
||
try {
|
||
const authRes = await this.$u.post("/login/weChatLogin", data);
|
||
const token = authRes.data;
|
||
|
||
if (!token) {
|
||
uni.hideLoading();
|
||
this.$mytip.toast("登录失败");
|
||
return;
|
||
}
|
||
|
||
this.$u.vuex("vuex_token", token);
|
||
|
||
// 🔥 用快照的类型,不用this.loginType,防切换错乱
|
||
await this.getUserOtherInfo(data.loginType, token);
|
||
|
||
uni.hideLoading();
|
||
this.$mytip.toast("登录成功");
|
||
|
||
setTimeout(() => {
|
||
uni.switchTab({
|
||
url: "/pages/index/index",
|
||
success() {
|
||
const page = getCurrentPages().pop();
|
||
if (page) page.onLoad();
|
||
}
|
||
});
|
||
}, 500);
|
||
|
||
} catch (err) {
|
||
uni.hideLoading();
|
||
this.$mytip.toast("登录失败,请稍后重试");
|
||
}
|
||
},
|
||
|
||
getUserOtherInfo(loginType, token) {
|
||
return new Promise((resolve, reject) => {
|
||
this.$u.get("/login/userInfo", {}, {
|
||
"WT": token,
|
||
"USERTYPE": loginType
|
||
}).then(obj => {
|
||
if (obj?.flag) {
|
||
console.log("获取用户信息")
|
||
const userInfoData = {
|
||
userType: this.loginType,
|
||
oaAuth: obj.data.oaAuth,
|
||
cusNo: obj.data.cusNo,
|
||
userName: obj.data.userName,
|
||
openId: obj.data.openId,
|
||
subscribe: obj.data.subscribeMsg
|
||
}
|
||
uni.setStorageSync('userInfo',userInfoData )
|
||
}
|
||
resolve();
|
||
}).catch(() => {
|
||
resolve();
|
||
});
|
||
});
|
||
},
|
||
|
||
goBack() {
|
||
uni.navigateBack({
|
||
delta: 1
|
||
});
|
||
},
|
||
|
||
goPrivacy(type) {
|
||
const url = type === "user" ?
|
||
"/pages-biz/privacy/userAgreement" :
|
||
"/pages-biz/privacy/privacyPolicy";
|
||
uni.navigateTo({
|
||
url
|
||
});
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.login-container {
|
||
height: 100vh;
|
||
background: #fff;
|
||
padding-top: var(--status-bar-height);
|
||
}
|
||
|
||
.content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 0 40rpx;
|
||
margin-top: 200rpx;
|
||
}
|
||
|
||
.title {
|
||
font-size: 48rpx;
|
||
font-weight: 500;
|
||
color: #222;
|
||
margin-bottom: 60rpx;
|
||
}
|
||
|
||
.illustration {
|
||
width: 100%;
|
||
height: 400rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 60rpx;
|
||
|
||
image {
|
||
width: 80%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
.login-btn {
|
||
width: 100%;
|
||
height: 88rpx;
|
||
background: linear-gradient(90deg, #FF2F31 0%, #FF9379 100%);
|
||
border-radius: 49rpx;
|
||
font-size: 36rpx;
|
||
color: #fff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 40rpx;
|
||
border: none;
|
||
}
|
||
|
||
.user-type {
|
||
display: flex;
|
||
justify-content: center;
|
||
gap: 40rpx;
|
||
margin-bottom: 40rpx;
|
||
}
|
||
|
||
.agreement {
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.agreement-text {
|
||
font-size: 26rpx;
|
||
color: #cecece;
|
||
}
|
||
|
||
.link {
|
||
color: #334254;
|
||
}
|
||
</style> |