You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
331 lines
6.9 KiB
331 lines
6.9 KiB
<template>
|
|
<view class="container">
|
|
<!-- 顶部导航 -->
|
|
<view class="nav-bar">
|
|
<view class="nav-title">微信账号绑定</view>
|
|
<view class="nav-close" @click="closePage">
|
|
<fui-icon name="close" :size="40" color="#333"></fui-icon>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 微信授权webview -->
|
|
<web-view
|
|
v-if="authUrl"
|
|
:src="authUrl"
|
|
@message="handleWebviewMessage"
|
|
@error="handleWebviewError">
|
|
</web-view>
|
|
|
|
<!-- 绑定表单 -->
|
|
<view class="bind-form" v-if="showBindForm">
|
|
<view class="form-title">完成账号绑定</view>
|
|
<view class="form-subtitle">请输入手机号和验证码完成绑定</view>
|
|
|
|
<view class="form-item">
|
|
<fui-input
|
|
placeholder="请输入手机号"
|
|
v-model="phone"
|
|
type="number"
|
|
backgroundColor="#f8f8f8">
|
|
</fui-input>
|
|
</view>
|
|
|
|
<view class="form-item">
|
|
<fui-input
|
|
placeholder="请输入验证码"
|
|
v-model="smsCode"
|
|
backgroundColor="#f8f8f8">
|
|
<fui-button
|
|
:background="canSendSms ? '#00be8c' : '#ccc'"
|
|
:disabled="!canSendSms"
|
|
width="200rpx"
|
|
height="60rpx"
|
|
:size="24"
|
|
@click="sendSmsCode">
|
|
{{ smsButtonText }}
|
|
</fui-button>
|
|
</fui-input>
|
|
</view>
|
|
|
|
<view class="form-item">
|
|
<fui-button
|
|
background="#00be8c"
|
|
radius="5rpx"
|
|
@click="submitBind"
|
|
:disabled="!canSubmit">
|
|
确认绑定
|
|
</fui-button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import apiRoute from '@/api/apiRoute.js';
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
authUrl: '',
|
|
miniOpenid: '',
|
|
wechatOpenid: '',
|
|
phone: '',
|
|
smsCode: '',
|
|
showBindForm: false,
|
|
smsCountdown: 0,
|
|
smsTimer: null
|
|
}
|
|
},
|
|
computed: {
|
|
canSendSms() {
|
|
return this.phone.length === 11 && this.smsCountdown === 0;
|
|
},
|
|
canSubmit() {
|
|
return this.phone.length === 11 && this.smsCode.length > 0 && this.wechatOpenid;
|
|
},
|
|
smsButtonText() {
|
|
return this.smsCountdown > 0 ? `${this.smsCountdown}s` : '获取验证码';
|
|
}
|
|
},
|
|
onLoad(options) {
|
|
this.authUrl = decodeURIComponent(options.auth_url || '');
|
|
this.miniOpenid = options.mini_openid || '';
|
|
|
|
if (!this.authUrl || !this.miniOpenid) {
|
|
uni.showToast({
|
|
title: '参数错误',
|
|
icon: 'none'
|
|
});
|
|
setTimeout(() => {
|
|
this.closePage();
|
|
}, 1500);
|
|
return;
|
|
}
|
|
|
|
// 监听URL变化,检测是否完成授权
|
|
this.checkAuthCallback();
|
|
},
|
|
onShow() {
|
|
// 页面显示时检查是否有授权回调参数
|
|
this.checkUrlParams();
|
|
},
|
|
onUnload() {
|
|
if (this.smsTimer) {
|
|
clearInterval(this.smsTimer);
|
|
}
|
|
},
|
|
methods: {
|
|
// 检查授权回调
|
|
checkAuthCallback() {
|
|
// 定时检查URL变化,模拟检测授权完成
|
|
setTimeout(() => {
|
|
// 模拟授权完成,显示绑定表单
|
|
// 实际项目中这里应该通过webview的URL变化或消息来判断
|
|
this.showBindFormWithDelay();
|
|
}, 3000); // 3秒后显示绑定表单,给用户足够时间完成微信授权
|
|
},
|
|
|
|
// 检查URL参数
|
|
checkUrlParams() {
|
|
// 这里可以检查页面参数,判断是否从微信授权回调返回
|
|
const pages = getCurrentPages();
|
|
const currentPage = pages[pages.length - 1];
|
|
if (currentPage && currentPage.options) {
|
|
const { code, state } = currentPage.options;
|
|
if (code && state) {
|
|
// 有授权回调参数,处理授权结果
|
|
this.handleAuthCallback(code, state);
|
|
}
|
|
}
|
|
},
|
|
|
|
// 延迟显示绑定表单
|
|
showBindFormWithDelay() {
|
|
// 模拟获取到微信公众号openid
|
|
this.wechatOpenid = 'mock_wechat_openid_' + Date.now();
|
|
this.showBindForm = true;
|
|
|
|
uni.showToast({
|
|
title: '微信授权成功,请完成绑定',
|
|
icon: 'success'
|
|
});
|
|
},
|
|
|
|
// 处理授权回调
|
|
async handleAuthCallback(code, state) {
|
|
try {
|
|
// 这里应该调用后端接口处理授权回调
|
|
// 暂时模拟处理
|
|
this.wechatOpenid = 'wechat_openid_from_callback';
|
|
this.showBindForm = true;
|
|
} catch (error) {
|
|
console.error('处理授权回调失败:', error);
|
|
uni.showToast({
|
|
title: '授权失败',
|
|
icon: 'none'
|
|
});
|
|
}
|
|
},
|
|
|
|
// 处理webview消息
|
|
handleWebviewMessage(event) {
|
|
console.log('收到webview消息:', event);
|
|
// 这里可以处理来自webview的消息
|
|
},
|
|
|
|
// 处理webview错误
|
|
handleWebviewError(event) {
|
|
console.error('webview错误:', event);
|
|
uni.showToast({
|
|
title: '授权页面加载失败',
|
|
icon: 'none'
|
|
});
|
|
},
|
|
|
|
// 发送短信验证码
|
|
async sendSmsCode() {
|
|
if (!this.canSendSms) return;
|
|
|
|
try {
|
|
const res = await apiRoute.common_forgetPassword({
|
|
phone: this.phone,
|
|
type: 'bind' // 绑定类型
|
|
});
|
|
|
|
if (res && res.code === 1) {
|
|
uni.showToast({
|
|
title: '验证码已发送',
|
|
icon: 'success'
|
|
});
|
|
this.startCountdown();
|
|
} else {
|
|
uni.showToast({
|
|
title: res.msg || '发送失败',
|
|
icon: 'none'
|
|
});
|
|
}
|
|
} catch (error) {
|
|
console.error('发送验证码失败:', error);
|
|
uni.showToast({
|
|
title: '发送失败,请重试',
|
|
icon: 'none'
|
|
});
|
|
}
|
|
},
|
|
|
|
// 开始倒计时
|
|
startCountdown() {
|
|
this.smsCountdown = 60;
|
|
this.smsTimer = setInterval(() => {
|
|
this.smsCountdown--;
|
|
if (this.smsCountdown <= 0) {
|
|
clearInterval(this.smsTimer);
|
|
this.smsTimer = null;
|
|
}
|
|
}, 1000);
|
|
},
|
|
|
|
// 提交绑定
|
|
async submitBind() {
|
|
if (!this.canSubmit) return;
|
|
|
|
try {
|
|
uni.showLoading({
|
|
title: '绑定中...'
|
|
});
|
|
|
|
const params = {
|
|
mini_openid: this.miniOpenid,
|
|
wechat_openid: this.wechatOpenid,
|
|
phone: this.phone,
|
|
code: this.smsCode
|
|
};
|
|
|
|
const res = await apiRoute.wechatBind(params);
|
|
uni.hideLoading();
|
|
|
|
if (res && res.code === 1) {
|
|
uni.showToast({
|
|
title: '绑定成功',
|
|
icon: 'success'
|
|
});
|
|
|
|
setTimeout(() => {
|
|
// 绑定成功后返回登录页面并自动登录
|
|
uni.navigateBack();
|
|
// 通知登录页面绑定成功
|
|
uni.$emit('wechatBindSuccess');
|
|
}, 1500);
|
|
} else {
|
|
uni.showToast({
|
|
title: res.msg || '绑定失败',
|
|
icon: 'none'
|
|
});
|
|
}
|
|
} catch (error) {
|
|
uni.hideLoading();
|
|
console.error('绑定失败:', error);
|
|
uni.showToast({
|
|
title: '绑定失败,请重试',
|
|
icon: 'none'
|
|
});
|
|
}
|
|
},
|
|
|
|
// 关闭页面
|
|
closePage() {
|
|
uni.navigateBack();
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.container {
|
|
height: 100vh;
|
|
background-color: #fff;
|
|
}
|
|
|
|
.nav-bar {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 20rpx 30rpx;
|
|
border-bottom: 1rpx solid #eee;
|
|
position: relative;
|
|
z-index: 999;
|
|
}
|
|
|
|
.nav-title {
|
|
font-size: 36rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
}
|
|
|
|
.nav-close {
|
|
padding: 10rpx;
|
|
}
|
|
|
|
.bind-form {
|
|
padding: 60rpx 30rpx;
|
|
}
|
|
|
|
.form-title {
|
|
font-size: 48rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
text-align: center;
|
|
margin-bottom: 20rpx;
|
|
}
|
|
|
|
.form-subtitle {
|
|
font-size: 28rpx;
|
|
color: #666;
|
|
text-align: center;
|
|
margin-bottom: 60rpx;
|
|
}
|
|
|
|
.form-item {
|
|
margin-bottom: 40rpx;
|
|
}
|
|
</style>
|
|
|