Files
RentWeAppFront/pages-biz/login/login.vue
2026-05-20 14:57:38 +08:00

239 lines
5.1 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>
<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 {
// 1. 先拿微信登录 code
const loginRes = await new Promise((resolve, reject) => {
uni.login({
provider: "weixin",
success: resolve,
fail: reject
});
});
// 2. 传给后端登录
await this.doLogin({
loginCode: loginRes.code,
encryptedData: e.detail.encryptedData,
iv: e.detail.iv,
loginType: this.loginType
});
} catch (err) {
this.$mytip.toast("授权失败,请重试");
}
},
// 登录接口(修复:用户信息 + 全局刷新)
async doLogin(data) {
uni.showLoading({ title: "登录中...", mask: true });
try {
// 1. 登录拿 token
const authRes = await this.$u.post("/login/weChatLogin", data);
const token = authRes.data;
if (!token) {
uni.hideLoading();
this.$mytip.toast("登录失败");
return;
}
// 2. 保存 token全局
this.$u.vuex("vuex_token", token);
// 3. 获取并保存用户信息(修复:必须 await 等它完成)
await this.getUserOtherInfo(this.loginType, token);
// 4. 登录成功 → 强制刷新全局状态 + 跳首页
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("登录失败,请稍后重试");
}
},
// 获取用户信息(修复:必须返回 Promise
getUserOtherInfo(loginType, token) {
return new Promise((resolve, reject) => {
this.$u.get("/login/userInfo", {}, {
"WT": token,
"USERTYPE": loginType
}).then(obj => {
if (obj?.flag) {
// 🔥 保存用户信息到缓存
uni.setStorageSync('userInfo', obj.data);
// 🔥 同时存入 vuex 全局状态(首页就能实时刷新)
this.$u.vuex('vuex_userInfo', obj.data);
}
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>