234 lines
6 KiB
JavaScript
234 lines
6 KiB
JavaScript
|
|
// 账号同步管理器 - 自动检查并处理手机号绑定和账号合并
|
|||
|
|
const apiClient = require('./api-client.js');
|
|||
|
|
const authManager = require('./auth.js');
|
|||
|
|
|
|||
|
|
class AccountSyncManager {
|
|||
|
|
constructor() {
|
|||
|
|
this.isChecking = false;
|
|||
|
|
this.hasChecked = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查用户是否需要绑定手机号
|
|||
|
|
async checkPhoneBinding() {
|
|||
|
|
try {
|
|||
|
|
// 确保用户已登录
|
|||
|
|
if (!authManager.isLoggedIn()) {
|
|||
|
|
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const userInfo = authManager.getUserDisplayInfo();
|
|||
|
|
if (!userInfo) {
|
|||
|
|
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查是否已绑定手机号(注意空字符串的处理)
|
|||
|
|
const hasPhone = !!(userInfo.phone && userInfo.phone.trim() !== '');
|
|||
|
|
|
|||
|
|
return !hasPhone; // 返回是否需要绑定
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('检查手机号绑定状态失败:', error);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 自动检查并引导用户绑定手机号
|
|||
|
|
async autoCheckAndBind() {
|
|||
|
|
if (this.isChecking || this.hasChecked) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.isChecking = true;
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
|
|||
|
|
const needsBinding = await this.checkPhoneBinding();
|
|||
|
|
|
|||
|
|
if (needsBinding) {
|
|||
|
|
|
|||
|
|
this.showPhoneBindingModal();
|
|||
|
|
} else {
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.hasChecked = true;
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('自动检查账号同步失败:', error);
|
|||
|
|
} finally {
|
|||
|
|
this.isChecking = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 显示手机号绑定弹窗
|
|||
|
|
showPhoneBindingModal() {
|
|||
|
|
|
|||
|
|
// 检查是否应该跳过
|
|||
|
|
if (this.shouldSkipBinding()) {
|
|||
|
|
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
wx.showModal({
|
|||
|
|
title: '完善账号信息',
|
|||
|
|
content: '为了更好的使用体验和账号安全,请绑定您的手机号',
|
|||
|
|
confirmText: '立即绑定',
|
|||
|
|
cancelText: '稍后再说',
|
|||
|
|
success: (res) => {
|
|||
|
|
if (res.confirm) {
|
|||
|
|
// 跳转到手机号绑定页面
|
|||
|
|
wx.navigateTo({
|
|||
|
|
url: '/subpackages/settings/phone-binding/phone-binding'
|
|||
|
|
});
|
|||
|
|
} else {
|
|||
|
|
// 用户选择稍后,记录状态避免频繁弹出
|
|||
|
|
this.setSkipBindingFlag();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 设置跳过绑定标记(24小时内不再提示)
|
|||
|
|
setSkipBindingFlag() {
|
|||
|
|
const skipUntil = Date.now() + 24 * 60 * 60 * 1000; // 24小时后
|
|||
|
|
wx.setStorageSync('skipPhoneBinding', skipUntil);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查是否应该跳过绑定提示
|
|||
|
|
shouldSkipBinding() {
|
|||
|
|
try {
|
|||
|
|
const skipUntil = wx.getStorageSync('skipPhoneBinding');
|
|||
|
|
if (skipUntil && Date.now() < skipUntil) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('检查跳过绑定标记失败:', error);
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 清除跳过绑定标记
|
|||
|
|
clearSkipBindingFlag() {
|
|||
|
|
try {
|
|||
|
|
wx.removeStorageSync('skipPhoneBinding');
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('清除跳过绑定标记失败:', error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 绑定手机号
|
|||
|
|
async bindPhone(phone, verifyCode, autoMerge = false) {
|
|||
|
|
try {
|
|||
|
|
|
|||
|
|
const response = await apiClient.bindPhone(phone, verifyCode, autoMerge);
|
|||
|
|
|
|||
|
|
if (response && response.code === 0) { // 修正成功码为0
|
|||
|
|
|
|||
|
|
// 清除跳过绑定标记
|
|||
|
|
this.clearSkipBindingFlag();
|
|||
|
|
|
|||
|
|
// 尝试刷新用户信息(失败不影响绑定结果)
|
|||
|
|
try {
|
|||
|
|
await this.refreshUserInfo();
|
|||
|
|
} catch (refreshError) {
|
|||
|
|
console.warn('刷新用户信息失败,但绑定操作已成功:', refreshError);
|
|||
|
|
// 不抛出错误,因为绑定本身是成功的
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 根据文档,返回完整的绑定结果
|
|||
|
|
return {
|
|||
|
|
success: response.data.success || true,
|
|||
|
|
hasMerged: response.data.hasMerged || false,
|
|||
|
|
mergeCount: response.data.mergeCount || 0,
|
|||
|
|
...response.data
|
|||
|
|
};
|
|||
|
|
} else {
|
|||
|
|
throw new Error(response?.message || '绑定失败');
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('绑定手机号失败:', error);
|
|||
|
|
|
|||
|
|
// 根据文档,处理特定的错误情况
|
|||
|
|
if (error.message && error.message.includes('已关联其他账号')) {
|
|||
|
|
// 重新抛出冲突错误,让上层处理
|
|||
|
|
throw new Error('该手机号已关联其他账号,请选择合并或使用其他手机号');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检测可合并账号
|
|||
|
|
async detectMerge(customId) {
|
|||
|
|
try {
|
|||
|
|
|
|||
|
|
const response = await apiClient.detectMerge(customId);
|
|||
|
|
|
|||
|
|
if (response && response.code === 0) { // 修正成功码为0
|
|||
|
|
|
|||
|
|
return response.data;
|
|||
|
|
} else {
|
|||
|
|
throw new Error(response?.message || '检测失败');
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('检测可合并账号失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 合并账号
|
|||
|
|
async mergeAccount(primaryCustomId, secondaryCustomId, mergeReason) {
|
|||
|
|
try {
|
|||
|
|
|
|||
|
|
const response = await apiClient.mergeAccount(primaryCustomId, secondaryCustomId, mergeReason);
|
|||
|
|
|
|||
|
|
if (response && response.code === 0) { // 修正成功码为0
|
|||
|
|
|
|||
|
|
// 刷新用户信息
|
|||
|
|
await this.refreshUserInfo();
|
|||
|
|
|
|||
|
|
return response.data;
|
|||
|
|
} else {
|
|||
|
|
throw new Error(response?.message || '合并失败');
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('合并账号失败:', error);
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 刷新用户信息
|
|||
|
|
async refreshUserInfo() {
|
|||
|
|
try {
|
|||
|
|
|
|||
|
|
const response = await apiClient.getUserInfo();
|
|||
|
|
if (response && response.code === 0) {
|
|||
|
|
// 更新全局用户信息
|
|||
|
|
const app = getApp();
|
|||
|
|
if (app && app.globalData.userInfo) {
|
|||
|
|
app.globalData.userInfo.user = response.data;
|
|||
|
|
|
|||
|
|
// 同步到本地存储
|
|||
|
|
wx.setStorageSync('userInfo', app.globalData.userInfo);
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('刷新用户信息失败:', error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 重置检查状态(用于测试或强制重新检查)
|
|||
|
|
resetCheckStatus() {
|
|||
|
|
this.hasChecked = false;
|
|||
|
|
this.isChecking = false;
|
|||
|
|
this.clearSkipBindingFlag();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 创建单例实例
|
|||
|
|
const accountSyncManager = new AccountSyncManager();
|
|||
|
|
|
|||
|
|
module.exports = accountSyncManager;
|
|||
|
|
|