Initial commit

This commit is contained in:
sjk
2025-11-17 13:32:54 +08:00
commit e788eab6eb
1659 changed files with 171560 additions and 0 deletions

View File

@@ -0,0 +1,182 @@
// pages/user/phone-verify/index.js
const weChatAuthService = require('../../../services/auth/wechat');
Page({
data: {
phoneNumber: '',
verifyCode: '',
canSendCode: false,
canConfirm: false,
sendCodeText: '发送验证码',
countdown: 0,
loading: false
},
onLoad(options) {
// weChatAuthService 已经是一个实例,直接使用
this.countdownTimer = null;
},
onUnload() {
if (this.countdownTimer) {
clearInterval(this.countdownTimer);
}
},
// 手机号输入
onPhoneInput(e) {
const phoneNumber = e.detail.value;
this.setData({
phoneNumber
});
this.checkCanSendCode();
this.checkCanConfirm();
},
// 验证码输入
onVerifyCodeInput(e) {
const verifyCode = e.detail.value;
this.setData({
verifyCode
});
this.checkCanConfirm();
},
// 检查是否可以发送验证码
checkCanSendCode() {
const { phoneNumber, countdown } = this.data;
const phoneRegex = /^1[3-9]\d{9}$/;
const canSendCode = phoneRegex.test(phoneNumber) && countdown === 0;
this.setData({
canSendCode
});
},
// 检查是否可以确认绑定
checkCanConfirm() {
const { phoneNumber } = this.data;
const phoneRegex = /^1[3-9]\d{9}$/;
const canConfirm = phoneRegex.test(phoneNumber);
this.setData({
canConfirm
});
},
// 发送验证码
async sendVerifyCode() {
if (!this.data.canSendCode) return;
try {
this.setData({ loading: true });
// 这里应该调用后端API发送验证码
// 暂时模拟发送成功
await this.simulateSendCode();
wx.showToast({
title: '验证码已发送',
icon: 'success'
});
// 开始倒计时
this.startCountdown();
} catch (error) {
console.error('发送验证码失败:', error);
wx.showToast({
title: '发送失败,请重试',
icon: 'none'
});
} finally {
this.setData({ loading: false });
}
},
// 模拟发送验证码实际项目中应该调用真实API
simulateSendCode() {
return new Promise((resolve) => {
setTimeout(resolve, 1000);
});
},
// 开始倒计时
startCountdown() {
let countdown = 60;
this.setData({
countdown,
sendCodeText: `${countdown}s后重发`,
canSendCode: false
});
this.countdownTimer = setInterval(() => {
countdown--;
if (countdown > 0) {
this.setData({
countdown,
sendCodeText: `${countdown}s后重发`
});
} else {
this.setData({
countdown: 0,
sendCodeText: '重新发送'
});
this.checkCanSendCode();
clearInterval(this.countdownTimer);
}
}, 1000);
},
// 确认绑定
async confirmBind() {
if (!this.data.canConfirm) return;
try {
this.setData({ loading: true });
const { phoneNumber } = this.data;
// 直接更新用户信息,不验证验证码
await this.updateUserPhone(phoneNumber);
wx.showToast({
title: '绑定成功',
icon: 'success'
});
// 延迟返回上一页
setTimeout(() => {
wx.navigateBack();
}, 1500);
} catch (error) {
console.error('绑定手机号失败:', error);
wx.showToast({
title: error.message || '绑定失败,请重试',
icon: 'none'
});
} finally {
this.setData({ loading: false });
}
},
// 更新用户手机号
async updateUserPhone(phoneNumber) {
try {
// 调用微信授权服务更新用户信息
await weChatAuthService.updateUserProfile({
phoneNumber: phoneNumber
});
// 更新本地存储的用户信息
const userInfo = wx.getStorageSync('userInfo') || {};
userInfo.phoneNumber = phoneNumber;
wx.setStorageSync('userInfo', userInfo);
} catch (error) {
console.error('更新用户手机号失败:', error);
throw error;
}
}
});

View File

@@ -0,0 +1,9 @@
{
"navigationBarTitleText": "绑定手机号",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"backgroundColor": "#f5f5f5",
"usingComponents": {
"t-loading": "tdesign-miniprogram/loading/loading"
}
}

View File

@@ -0,0 +1,65 @@
<!--pages/user/phone-verify/index.wxml-->
<view class="phone-verify">
<view class="header">
<view class="title">绑定手机号</view>
<view class="subtitle">绑定手机号后,可以更好地保护您的账户安全</view>
</view>
<view class="form-container">
<!-- 手机号输入 -->
<view class="input-group">
<view class="input-label">手机号</view>
<input
class="phone-input"
type="number"
placeholder="请输入手机号"
value="{{phoneNumber}}"
bindinput="onPhoneInput"
maxlength="11"
/>
</view>
<!-- 验证码输入 -->
<view class="input-group">
<view class="input-label">验证码</view>
<view class="verify-code-container">
<input
class="verify-input"
type="number"
placeholder="请输入验证码"
value="{{verifyCode}}"
bindinput="onVerifyCodeInput"
maxlength="6"
/>
<button
class="send-code-btn {{canSendCode ? '' : 'disabled'}}"
bindtap="sendVerifyCode"
disabled="{{!canSendCode}}"
>
{{sendCodeText}}
</button>
</view>
</view>
</view>
<!-- 操作按钮 -->
<view class="button-container">
<button
class="confirm-btn {{canConfirm ? 'active' : ''}}"
bindtap="confirmBind"
disabled="{{!canConfirm}}"
>
确认绑定
</button>
</view>
<!-- 提示信息 -->
<view class="tips">
<view class="tip-item">• 验证码将发送至您的手机</view>
<view class="tip-item">• 请确保手机号码正确无误</view>
<view class="tip-item">• 如有问题,请联系客服</view>
</view>
</view>
<!-- 加载提示 -->
<t-loading wx:if="{{loading}}" theme="circular" size="40rpx" text="处理中..." />

View File

@@ -0,0 +1,196 @@
/* pages/user/phone-verify/index.wxss */
.phone-verify {
min-height: 100vh;
background-color: #f5f5f5;
padding: 40rpx 32rpx;
}
/* 头部区域 */
.header {
text-align: center;
margin-bottom: 80rpx;
}
.title {
font-size: 48rpx;
font-weight: 600;
color: #333;
margin-bottom: 16rpx;
}
.subtitle {
font-size: 28rpx;
color: #666;
line-height: 1.5;
}
/* 表单容器 */
.form-container {
background: #fff;
border-radius: 16rpx;
padding: 40rpx 32rpx;
margin-bottom: 40rpx;
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.08);
}
/* 输入组 */
.input-group {
margin-bottom: 40rpx;
}
.input-group:last-child {
margin-bottom: 0;
}
.input-label {
font-size: 28rpx;
color: #333;
margin-bottom: 16rpx;
font-weight: 500;
}
/* 手机号输入框 */
.phone-input {
width: 100%;
height: 88rpx;
padding: 0 24rpx;
border: 2rpx solid #e0e0e0;
border-radius: 12rpx;
font-size: 32rpx;
color: #333;
background: #fff;
transition: border-color 0.3s ease;
}
.phone-input:focus {
border-color: #0052d9;
}
/* 验证码容器 */
.verify-code-container {
display: flex;
align-items: center;
gap: 16rpx;
}
.verify-input {
flex: 1;
height: 88rpx;
padding: 0 24rpx;
border: 2rpx solid #e0e0e0;
border-radius: 12rpx;
font-size: 32rpx;
color: #333;
background: #fff;
transition: border-color 0.3s ease;
}
.verify-input:focus {
border-color: #0052d9;
}
/* 发送验证码按钮 */
.send-code-btn {
width: 200rpx;
height: 88rpx;
background: #0052d9;
color: #fff;
border: none;
border-radius: 12rpx;
font-size: 28rpx;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.send-code-btn.disabled {
background: #ccc;
color: #999;
}
.send-code-btn::after {
border: none;
}
/* 按钮容器 */
.button-container {
margin-bottom: 40rpx;
}
/* 确认按钮 */
.confirm-btn {
width: 100%;
height: 96rpx;
background: #ccc;
color: #999;
border: none;
border-radius: 12rpx;
font-size: 32rpx;
font-weight: 500;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.confirm-btn.active {
background: #0052d9;
color: #fff;
}
.confirm-btn::after {
border: none;
}
/* 提示信息 */
.tips {
background: #fff;
border-radius: 16rpx;
padding: 32rpx;
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.08);
}
.tip-item {
font-size: 26rpx;
color: #666;
line-height: 1.6;
margin-bottom: 12rpx;
}
.tip-item:last-child {
margin-bottom: 0;
}
/* 加载状态 */
.t-loading {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 9999;
}
/* 响应式设计 */
@media (max-width: 375px) {
.phone-verify {
padding: 32rpx 24rpx;
}
.title {
font-size: 44rpx;
}
.subtitle {
font-size: 26rpx;
}
.form-container {
padding: 32rpx 24rpx;
}
.send-code-btn {
width: 180rpx;
font-size: 26rpx;
}
}