微信授权登录功能开发联调

This commit is contained in:
冯辉
2025-10-20 11:43:44 +08:00
parent ae91ded327
commit d9c1f83693
5 changed files with 784 additions and 41 deletions

View File

@@ -0,0 +1,386 @@
<template>
<uni-popup ref="popup" type="center" :mask-click="false">
<view class="auth-modal">
<view class="modal-content">
<!-- 关闭按钮 -->
<view class="close-btn" @click="close">
<uni-icons type="closeempty" size="24" color="#999"></uni-icons>
</view>
<!-- Logo和标题 -->
<view class="auth-header">
<image class="auth-logo" src="@/static/logo.png" mode="aspectFit"></image>
<view class="auth-title">欢迎使用就业服务</view>
<view class="auth-subtitle">需要您授权手机号登录</view>
</view>
<!-- 授权说明 -->
<view class="auth-tips">
<view class="tip-item">
<uni-icons type="checkmarkempty" size="16" color="#13C57C"></uni-icons>
<text>保护您的个人信息安全</text>
</view>
<view class="tip-item">
<uni-icons type="checkmarkempty" size="16" color="#13C57C"></uni-icons>
<text>为您推荐更合适的岗位</text>
</view>
<view class="tip-item">
<uni-icons type="checkmarkempty" size="16" color="#13C57C"></uni-icons>
<text>享受完整的就业服务</text>
</view>
</view>
<!-- 授权按钮 -->
<view class="auth-actions">
<!-- 微信小程序使用 open-type="getPhoneNumber" -->
<!-- #ifdef MP-WEIXIN -->
<button
class="auth-btn primary"
open-type="getPhoneNumber"
@getphonenumber="getPhoneNumber"
>
<uni-icons type="phone" size="20" color="#FFFFFF"></uni-icons>
<text>微信授权登录</text>
</button>
<!-- #endif -->
<!-- H5和App使用普通按钮 -->
<!-- #ifndef MP-WEIXIN -->
<button class="auth-btn primary" @click="wxLogin">
<uni-icons type="phone" size="20" color="#FFFFFF"></uni-icons>
<text>微信授权登录</text>
</button>
<!-- #endif -->
<!-- 测试登录按钮仅开发环境 -->
<!-- #ifdef APP-PLUS || H5 -->
<button class="auth-btn secondary" @click="testLogin">
<text>测试账号登录</text>
</button>
<!-- #endif -->
</view>
<!-- 用户协议 -->
<view class="auth-agreement">
<text>登录即表示同意</text>
<text class="link" @click="openAgreement('user')">用户协议</text>
<text></text>
<text class="link" @click="openAgreement('privacy')">隐私政策</text>
</view>
</view>
</view>
</uni-popup>
</template>
<script setup>
import { ref, inject } from 'vue';
import useUserStore from '@/stores/useUserStore';
const { $api } = inject('globalFunction');
const { loginSetToken } = useUserStore();
const popup = ref(null);
const emit = defineEmits(['success', 'cancel']);
// 打开弹窗
const open = () => {
popup.value?.open();
};
// 关闭弹窗
const close = () => {
popup.value?.close();
emit('cancel');
};
// 微信小程序获取手机号
const getPhoneNumber = (e) => {
console.log('获取手机号:', e);
if (e.detail.errMsg === 'getPhoneNumber:ok') {
const { code, encryptedData, iv } = e.detail;
// 调用后端接口进行登录
uni.showLoading({ title: '登录中...' });
$api.createRequest('/app/appLogin', {
code,
encryptedData,
iv
}, 'post').then((resData) => {
uni.hideLoading();
if (resData.token) {
// 登录成功存储token
loginSetToken(resData.token).then((resume) => {
$api.msg('登录成功');
close();
emit('success');
// 如果用户信息不完整,跳转到完善信息页面
if (!resume.data.jobTitleId) {
uni.navigateTo({
url: '/pages/login/login?step=1'
});
}
}).catch(() => {
$api.msg('获取用户信息失败');
});
} else {
$api.msg('登录失败,请重试');
}
}).catch((err) => {
uni.hideLoading();
$api.msg(err.msg || '登录失败,请重试');
});
} else if (e.detail.errMsg === 'getPhoneNumber:fail user deny') {
$api.msg('您取消了授权');
} else {
$api.msg('获取手机号失败');
}
};
// H5/App 微信登录
const wxLogin = () => {
// #ifdef H5
// H5网页微信登录逻辑
uni.showLoading({ title: '登录中...' });
// 获取微信授权code
uni.login({
provider: 'weixin',
success: (loginRes) => {
console.log('微信登录成功:', loginRes);
// 调用后端接口进行登录
$api.createRequest('/app/appLogin', {
code: loginRes.code
}, 'post').then((resData) => {
uni.hideLoading();
if (resData.token) {
loginSetToken(resData.token).then((resume) => {
$api.msg('登录成功');
close();
emit('success');
if (!resume.data.jobTitleId) {
uni.navigateTo({
url: '/pages/login/login?step=1'
});
}
});
} else {
$api.msg('登录失败,请重试');
}
}).catch((err) => {
uni.hideLoading();
$api.msg(err.msg || '登录失败,请重试');
});
},
fail: (err) => {
uni.hideLoading();
console.error('微信登录失败:', err);
$api.msg('微信登录失败');
}
});
// #endif
// #ifdef APP-PLUS
// App微信登录逻辑
uni.getProvider({
service: 'oauth',
success: (res) => {
if (~res.provider.indexOf('weixin')) {
uni.login({
provider: 'weixin',
success: (loginRes) => {
console.log('微信登录成功:', loginRes);
// 调用后端接口进行登录
$api.createRequest('/app/appLogin', {
code: loginRes.code
}, 'post').then((resData) => {
if (resData.token) {
loginSetToken(resData.token).then((resume) => {
$api.msg('登录成功');
close();
emit('success');
if (!resume.data.jobTitleId) {
uni.navigateTo({
url: '/pages/login/login?step=1'
});
}
});
}
});
},
fail: (err) => {
console.error('微信登录失败:', err);
$api.msg('微信登录失败');
}
});
}
}
});
// #endif
};
// 测试账号登录(仅开发环境)
const testLogin = () => {
uni.showLoading({ title: '登录中...' });
const params = {
username: 'test',
password: 'test',
};
$api.createRequest('/app/login', params, 'post').then((resData) => {
uni.hideLoading();
loginSetToken(resData.token).then((resume) => {
$api.msg('测试登录成功');
close();
emit('success');
if (!resume.data.jobTitleId) {
uni.navigateTo({
url: '/pages/login/login?step=1'
});
}
}).catch(() => {
$api.msg('获取用户信息失败');
});
}).catch((err) => {
uni.hideLoading();
$api.msg(err.msg || '登录失败');
});
};
// 打开用户协议
const openAgreement = (type) => {
const urls = {
user: '/pages/agreement/user',
privacy: '/pages/agreement/privacy'
};
if (urls[type]) {
uni.navigateTo({
url: urls[type]
});
}
};
// 暴露方法供父组件调用
defineExpose({
open,
close
});
</script>
<style lang="stylus" scoped>
.auth-modal
width: 620rpx
background: #FFFFFF
border-radius: 24rpx
overflow: hidden
.modal-content
padding: 60rpx 40rpx 40rpx
position: relative
.close-btn
position: absolute
right: 20rpx
top: 20rpx
width: 60rpx
height: 60rpx
display: flex
align-items: center
justify-content: center
z-index: 10
.auth-header
text-align: center
margin-bottom: 40rpx
.auth-logo
width: 120rpx
height: 120rpx
margin: 0 auto 24rpx
.auth-title
font-size: 36rpx
font-weight: 600
color: #333333
margin-bottom: 12rpx
.auth-subtitle
font-size: 28rpx
color: #666666
.auth-tips
background: #F7F8FA
border-radius: 16rpx
padding: 24rpx
margin-bottom: 40rpx
.tip-item
display: flex
align-items: center
margin-bottom: 16rpx
font-size: 26rpx
color: #666666
&:last-child
margin-bottom: 0
text
margin-left: 12rpx
.auth-actions
margin-bottom: 32rpx
.auth-btn
width: 100%
height: 88rpx
border-radius: 44rpx
display: flex
align-items: center
justify-content: center
font-size: 32rpx
font-weight: 500
border: none
margin-bottom: 20rpx
&:last-child
margin-bottom: 0
&.primary
background: linear-gradient(135deg, #13C57C 0%, #0FA368 100%)
color: #FFFFFF
box-shadow: 0 8rpx 20rpx rgba(19, 197, 124, 0.3)
&.secondary
background: #F7F8FA
color: #666666
text
margin-left: 12rpx
.auth-agreement
text-align: center
font-size: 24rpx
color: #999999
line-height: 1.6
.link
color: #256BFA
text-decoration: underline
// 按钮重置样式
button::after
border: none
</style>