This commit is contained in:
2025-12-25 08:26:09 +08:00
parent ab5c01bf5c
commit 964e4f9c33
72 changed files with 2474 additions and 1065 deletions

View File

@@ -1,113 +1,190 @@
<template>
<view class="login-page">
<!-- 背景视频 -->
<video
class="bg-video"
src="/static/login.mp4"
autoplay
loop
muted
object-fit="cover"
controls="false"
show-center-play-btn="false"
show-play-btn="false"
show-fullscreen-btn="false"
show-mute-btn="false"
show-status-bar="false"
enable-progress-gesture="false"
/>
<!-- 遮罩层增强可读性 -->
<view class="overlay"></view>
<!-- 背景图 -->
<!-- <image class="bg-img" :src="currentBg" :class="{ fade: isFading }" mode="aspectFill"></image> -->
<!-- 内容层 -->
<view class="login-content">
<view class="title u-font-36 u-m-b-40">
微信授权登录
</view>
<button
class="login-btn"
open-type="getPhoneNumber"
@getphonenumber="onGetPhone"
>
使用微信手机号授权登录
</button>
<view class="privacy-tip u-m-t-30 u-text-center">
登录即同意
<text class="link" @click="goPrivacy('user')">用户协议</text>
<text class="link" @click="goPrivacy('privacy')">隐私政策</text>
<view class="login-container">
<!-- 顶部状态栏 -->
<view class="status-bar">
<u-icon
:name="btn.icon"
:color="btn.color || '#333'"
:size="btn.size || 40"
></u-icon>
</view>
<!-- 主体内容区 -->
<view class="content">
<!-- 标题区域 -->
<view class="title">登录</view>
<!-- 登录插图区域 -->
<view class="illustration">
<image src="/static/login/bg.png" mode="aspectFit"></image>
</view>
<!-- 登录按钮 -->
<button class="login-btn" open-type="getPhoneNumber" @getphonenumber="onGetPhone">
使用微信授权登录
</button>
<!-- 用户类型选择 -->
<view class="user-type" shape="square">
<u-radio-group v-model="loginType" active-color="#EA414A" shape="square" >
<u-radio name="person" >个人</u-radio>
<u-radio name="company" >企业</u-radio>
</u-radio-group>
</view>
<!-- 协议提示 -->
<view class="agreement">
登录即同意
<text class="link">用户协议</text>
<text class="link">隐私政策</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
bgImages: [
'/static/loginbg1.jpg',
'/static/loginbg2.jpg'
],
currentIndex: 0,
currentBg: '/static/loginbg1.jpg',
timer: null
data() {
return {
designWidth: 750,
screenWidth: 0,
scale: 1,
bgImages: [
'/static/loginbg1.jpg',
'/static/loginbg2.jpg'
],
currentIndex: 0,
currentBg: '/static/login/bg.png',
isFading: false,
timer: null,
loginType:"person"
}
},
onLoad() {
// this.startBgTimer();
wx.getWindowInfo({
success: (res) => {
this.screenWidth = res.windowWidth
this.scale = this.screenWidth / this.designWidth
}
},
onLoad() {
this.startBgTimer();
},
onUnload() {
clearInterval(this.timer);
},
})
},
onUnload() {
clearInterval(this.timer);
},
computed: {
// title 样式
titleStyle() {
const s = this.scale;
return {
width: `${93 * s}rpx`,
height: `${45 * s}rpx`,
fontSize: `${48 * s}rpx`,
lineHeight: `${40 * s}rpx`,
fontWeight: 500,
color: '#222222',
fontFamily: 'Noto Sans S Chinese',
textAlign: 'center'
}
},
headerStyle() {
const s = this.scale;
return {
marginTop: `${214 * s}rpx`,
flex: 1,
display: 'flex',
flexDirection: 'column',
alignItems: 'center', // 水平居中
justifyContent: 'flex-start' // 从顶部开始
}
},
// cover 样式
coverStyle() {
const s = this.scale;
return {
width: `${428 * s}rpx`,
height: `${608 * s}rpx`
}
}
},
methods: {
startBgTimer() {
this.timer = setInterval(() => {
this.currentIndex = (this.currentIndex + 1) % this.bgImages.length;
this.currentBg = this.bgImages[this.currentIndex];
}, 2000); // 每 4 秒切换一次
},
/** 背景切换定时器 */
startBgTimer() {
this.timer = setInterval(() => {
this.isFading = true;
setTimeout(() => {
this.currentIndex = (this.currentIndex + 1) % this.bgImages.length;
this.currentBg = this.bgImages[this.currentIndex];
this.isFading = false;
}, 500);
}, 4000);
},
/** 微信手机号授权 */
onGetPhone(e) {
const { code } = e.detail;
if (!code) {
this.$mytip.toast("授权失败");
return;
}
this.doLogin(code);
},
async doLogin(code) {
/** 执行登录逻辑 */
async doLogin(phoneGetCode) {
uni.showLoading({ title: "登录中...", mask: true });
try {
const authRes = await this.$u.get(`/api/weChatAuth?code=${code}`);
if (!authRes.hasPhone) {
this.showPhoneSelector(authRes.phoneList, authRes.openid);
return;
}
await this.loginWithOpenId(authRes.openid);
// 微信登录
const loginRes = await new Promise((resolve, reject) => {
uni.login({
provider: 'weixin',
success: resolve,
fail: reject
});
});
// 调用后端登录接口
const authRes = await this.$u.post(`/login/weChatLogin`, {
phoneGetCode: phoneGetCode,
loginCode: loginRes.code
});
// 保存token
this.$u.vuex('vuex_token', authRes.data);
uni.hideLoading();
console.log(this.loginType)
uni.setStorageSync('indexParam', {
loginType: this.loginType
})
// 跳转首页
uni.switchTab({
url: '/pages/index/index'
});
} catch (err) {
uni.hideLoading();
this.$mytip.toast("登录失败");
uni.switchTab({ url: '/pages/index/index' });
console.error('Login failed:', err);
}
},
/** 触发手机号选择(子组件 → 父组件) */
showPhoneSelector(phoneList, openid) {
this.$emit("choosePhone", { phoneList, openid });
},
async loginWithOpenId(openid) {
const loginRes = await this.$u.post('/api/weChatLoginByOpenId', { openid });
this.$u.vuex('vuex_token', loginRes.token);
this.$u.vuex('vuex_user', loginRes.loginUser);
uni.hideLoading();
uni.switchTab({ url: '/pages/index/index' });
},
/** 查看协议 */
goPrivacy(type) {
const url = type === 'user'
? '/pages/privacy/userAgreement'
const url = type === 'user'
? '/pages/privacy/userAgreement'
: '/pages/privacy/privacyPolicy';
uni.navigateTo({ url });
}
}
@@ -115,95 +192,89 @@ export default {
</script>
<style lang="scss" scoped>
.login-page {
position: relative;
width: 100%;
.login-container {
height: 100vh;
background-color: #fff;
box-sizing: border-box;
overflow: hidden;
.bg-video {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: -1;
}
.status-bar {
margin-top: 7.56%;
height: var(--status-bar-height);
}
.overlay {
position: absolute;
top:0;
left:0;
width:100%;
height:100%;
background: rgba(0,0,0,0.3);
z-index:0;
}
.bg-img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
filter: brightness(0.7) blur(2px);
opacity: 1;
transition: opacity 0.5s ease;
}
.bg-img.fade {
opacity: 0;
}
.login-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 80%;
max-width: 400rpx;
.content {
display: flex;
flex-direction: column;
align-items: center;
z-index: 1;
animation: floatBtn 2s ease-in-out infinite alternate;
.title {
color: #fff;
font-weight: bold;
text-align: center;
}
.login-btn {
width: 100%;
height: 80rpx;
line-height: 80rpx;
font-size: 28rpx;
color: #fff;
border-radius: 40rpx;
background: linear-gradient(90deg, #4CAF50, #07c160);
box-shadow: 0 6rpx 12rpx rgba(0,0,0,0.25);
text-align: center;
margin-top: 20rpx;
}
.privacy-tip {
font-size: 24rpx;
color: #fff;
margin-top: 20rpx;
text-align: center;
.link {
color: #ffd700;
text-decoration: underline;
margin: 0 4rpx;
}
}
height: calc(100vh - var(--status-bar-height));
margin-top: 12.8%;
}
.title {
height: 45rpx;
font-family: Noto Sans S Chinese;
font-weight: 500;
font-size: 48rpx;
color: #222222;
line-height: 40rpx;
}
.illustration {
width: 100%;
height: 44.6%;
padding-left: 21.47%;
padding-right: 21.47%;
margin-bottom: 6%;
overflow: hidden;
}
.illustration image {
width: 100%;
height: 100%;
}
.login-btn {
width: 78.6%;
height: 7.12%;
background: linear-gradient(90deg, #FF2F31 0%, #FF9379 100%);
border-radius: 49rpx;
font-family: Noto Sans S Chinese;
font-weight: 400;
font-size: 36rpx;
color: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 40rpx;
}
.user-type {
display: flex;
justify-content: center;
gap: 40rpx;
margin-bottom: 20rpx;
}
.agreement {
font-family: Noto Sans S Chinese;
font-weight: 400;
font-size: 30rpx;
color: #CECECE;
align-items: center;
margin-top: 6.24%;
}
.link{
color: #334254;
}
}
@keyframes floatBtn {
0% { transform: translate(-50%, -50%) translateY(0); }
100% { transform: translate(-50%, -50%) translateY(-10rpx); }
/* 响应式适配 */
@media (max-width: 320rpx) {
.title { font-size: 42rpx; margin-bottom: 100rpx; }
.illustration { height: 360rpx; }
.login-btn { height: 80rpx; font-size: 30rpx; }
}
</style>