Files
RentWeAppFront/pages-biz/login/login.vue
2026-06-02 16:23:56 +08:00

241 lines
5.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>