miniprogramme/app.js
2025-09-12 16:08:17 +08:00

507 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// app.js
const config = require('./config/config.js');
const authManager = require('./utils/auth.js');
const apiClient = require('./utils/api-client.js');
const accountSyncManager = require('./utils/account-sync.js');
const animationManager = require('./utils/animation-manager.js');
App({
globalData: {
userInfo: null,
isLoggedIn: false,
appConfig: {
name: config.appName,
version: config.appVersion
},
systemInfo: null,
networkStatus: 'unknown'
},
// 小程序启动
onLaunch: async function () {
console.log('=== FindMe小程序启动 ===');
console.log('版本:', config.appVersion);
console.log('环境:', config.debug?.enabled ? '开发' : '生产');
try {
// 1. 初始化系统信息
await this.initSystemInfo();
// 2. 监听网络状态
this.initNetworkMonitoring();
// 3. 初始化认证管理器
await this.initAuth();
// 4. 静默登录检查
await this.checkSilentLogin();
console.log('=== 小程序启动完成 ===');
} catch (error) {
console.error('小程序启动过程中发生错误:', error);
// 即使出错也要继续启动,不能阻塞用户使用
}
},
// 小程序显示
onShow: function () {
console.log('小程序显示');
// 检查网络状态
this.checkNetworkStatus();
// 如果用户已登录检查token是否需要刷新
if (this.globalData.isLoggedIn) {
this.refreshTokenIfNeeded();
// 🔥 自动检查账号同步状态(延迟执行,避免阻塞主流程)
setTimeout(() => {
this.checkAccountSync();
}, 2000);
}
},
// 小程序隐藏
onHide: function () {
console.log('小程序隐藏');
},
// 小程序错误处理
onError: function (error) {
console.error('小程序全局错误:', error);
// 这里可以集成错误上报服务
// 例如errorReporter.report(error);
},
// 页面未找到
onPageNotFound: function (res) {
console.error('页面未找到:', res);
// 重定向到首页
wx.reLaunch({
url: '/pages/map/map'
});
},
// 未处理的Promise拒绝
onUnhandledRejection: function (res) {
console.error('未处理的Promise拒绝:', res);
},
// 初始化系统信息
async initSystemInfo() {
try {
// 使用新的API替代废弃的wx.getSystemInfoSync
const [windowInfo, deviceInfo, appBaseInfo] = await Promise.all([
this.getWindowInfo(),
this.getDeviceInfo(),
this.getAppBaseInfo()
]);
// 合并系统信息
const systemInfo = {
...windowInfo,
...deviceInfo,
...appBaseInfo
};
this.globalData.systemInfo = systemInfo;
console.log('系统信息初始化成功:', {
platform: systemInfo.platform,
version: systemInfo.version,
model: systemInfo.model,
language: systemInfo.language
});
} catch (error) {
console.error('获取系统信息失败,使用兜底方案:', error);
// 兜底使用统一的系统信息工具
try {
const { getSystemInfoSync } = require('./utils/system-info-helper.js');
const systemInfo = getSystemInfoSync();
this.globalData.systemInfo = systemInfo;
} catch (fallbackError) {
console.error('兜底方案也失败:', fallbackError);
}
}
},
// 获取窗口信息
getWindowInfo() {
return new Promise((resolve) => {
try {
const windowInfo = wx.getWindowInfo();
resolve(windowInfo);
} catch (error) {
console.warn('获取窗口信息失败:', error);
resolve({});
}
});
},
// 获取设备信息
getDeviceInfo() {
return new Promise((resolve) => {
try {
const deviceInfo = wx.getDeviceInfo();
resolve(deviceInfo);
} catch (error) {
console.warn('获取设备信息失败:', error);
resolve({});
}
});
},
// 获取应用基础信息
getAppBaseInfo() {
return new Promise((resolve) => {
try {
const appBaseInfo = wx.getAppBaseInfo();
resolve(appBaseInfo);
} catch (error) {
console.warn('获取应用信息失败:', error);
resolve({});
}
});
},
// 初始化网络监听
initNetworkMonitoring() {
// 获取当前网络状态
wx.getNetworkType({
success: (res) => {
this.globalData.networkStatus = res.networkType;
console.log('当前网络类型:', res.networkType);
}
});
// 监听网络状态变化
wx.onNetworkStatusChange((res) => {
this.globalData.networkStatus = res.networkType;
console.log('网络状态变化:', res);
if (res.isConnected) {
console.log('网络连接恢复');
// 网络恢复时,重新检查登录状态
if (this.globalData.isLoggedIn) {
this.refreshTokenIfNeeded();
}
} else {
console.log('网络连接断开');
}
});
},
// 初始化认证管理器
async initAuth() {
try {
console.log('初始化认证管理器...');
await authManager.init();
console.log('认证管理器初始化完成');
} catch (error) {
console.error('认证管理器初始化失败:', error);
}
},
// 静默登录检查
async checkSilentLogin() {
try {
console.log('🔍 开始静默登录检查...');
// 🔥 先检查本地存储的token
const storedUserInfo = wx.getStorageSync('userInfo');
const directToken = wx.getStorageSync('token');
console.log('🔍 本地token检查:', {
hasStoredUserInfo: !!storedUserInfo,
hasUserInfoToken: !!(storedUserInfo?.token),
hasDirectToken: !!directToken,
userInfoTokenLength: storedUserInfo?.token?.length || 0,
directTokenLength: directToken?.length || 0
});
// 如果没有任何token直接返回false
if (!storedUserInfo?.token && !directToken) {
console.log('❌ 没有找到任何token用户需要登录');
this.globalData.isLoggedIn = false;
this.globalData.userInfo = null;
return;
}
const isAuthenticated = await authManager.silentLogin();
if (isAuthenticated) {
console.log('✅ 静默登录成功,用户已登录');
this.globalData.isLoggedIn = true;
// 🔥 再次验证token的有效性
const finalUserInfo = wx.getStorageSync('userInfo');
if (finalUserInfo && finalUserInfo.token && finalUserInfo.token.length > 0) {
this.globalData.userInfo = finalUserInfo;
console.log('✅ 已恢复完整用户信息token长度:', finalUserInfo.token.length);
} else {
console.error('❌ 静默登录成功但无法获取有效token');
this.globalData.isLoggedIn = false;
this.globalData.userInfo = null;
}
} else {
console.log('❌ 静默登录失败,用户需要手动登录');
this.globalData.isLoggedIn = false;
this.globalData.userInfo = null;
// 🔥 清理无效的存储数据
wx.removeStorageSync('userInfo');
wx.removeStorageSync('token');
}
} catch (error) {
console.error('❌ 静默登录检查失败:', error);
this.globalData.isLoggedIn = false;
this.globalData.userInfo = null;
// 🔥 出错时清理存储数据
wx.removeStorageSync('userInfo');
wx.removeStorageSync('token');
}
},
// 检查网络状态
checkNetworkStatus() {
wx.getNetworkType({
success: (res) => {
const oldStatus = this.globalData.networkStatus;
this.globalData.networkStatus = res.networkType;
if (oldStatus !== res.networkType) {
console.log('网络类型变化:', oldStatus, '->', res.networkType);
}
},
fail: (error) => {
console.error('获取网络类型失败:', error);
}
});
},
// 刷新token如果需要
async refreshTokenIfNeeded() {
try {
if (!this.globalData.userInfo) {
return;
}
const isValid = authManager.isTokenValid(this.globalData.userInfo);
if (!isValid) {
console.log('Token即将过期尝试刷新');
const refreshed = await authManager.refreshTokenIfNeeded(this.globalData.userInfo);
if (refreshed) {
console.log('Token刷新成功');
// 🔥 修复:获取完整的认证信息
const storedUserInfo = wx.getStorageSync('userInfo');
if (storedUserInfo && storedUserInfo.token) {
this.globalData.userInfo = storedUserInfo;
console.log('Token刷新后已更新完整用户信息');
}
} else {
console.log('Token刷新失败需要重新登录');
this.handleAuthExpired();
}
}
} catch (error) {
console.error('Token刷新检查失败:', error);
}
},
// 处理认证过期
handleAuthExpired() {
console.log('认证已过期,清除登录状态');
authManager.clearAuthData();
this.globalData.isLoggedIn = false;
this.globalData.userInfo = null;
// 显示提示
wx.showToast({
title: '登录已过期,请重新登录',
icon: 'none',
duration: 2000
});
// 跳转到登录页
setTimeout(() => {
wx.reLaunch({
url: '/pages/login/login'
});
}, 2000);
},
// 手动登录方法(供页面调用)
async login(loginData) {
try {
console.log('执行登录,保存用户信息');
// 使用认证管理器保存登录信息
const success = await authManager.saveAuthData(loginData);
if (success) {
// 🔥 修复:获取完整的认证信息
const storedUserInfo = wx.getStorageSync('userInfo');
if (storedUserInfo && storedUserInfo.token) {
this.globalData.userInfo = storedUserInfo;
this.globalData.isLoggedIn = true;
console.log('登录信息保存成功包含token');
return true;
} else {
console.error('登录信息保存失败:无法获取完整用户信息');
return false;
}
} else {
console.error('登录信息保存失败');
return false;
}
} catch (error) {
console.error('登录处理失败:', error);
return false;
}
},
// 登出方法(供页面调用)
async logout() {
try {
console.log('执行登出');
const success = await authManager.logout();
// 无论服务端登出是否成功,都要清除本地状态
this.globalData.isLoggedIn = false;
this.globalData.userInfo = null;
console.log('登出完成');
return success;
} catch (error) {
console.error('登出失败:', error);
return false;
}
},
// 检查是否需要登录(供页面调用)
requireAuth() {
return authManager.requireAuth();
},
// 获取用户显示信息(供页面调用)
getUserDisplayInfo() {
return authManager.getUserDisplayInfo();
},
// 检查用户权限(供页面调用)
hasPermission(permission) {
return authManager.hasPermission(permission);
},
// 获取当前token供页面调用
getCurrentToken() {
return authManager.getCurrentToken();
},
// 等待认证初始化完成(供页面调用)
async waitForAuth() {
await authManager.waitForInitialization();
return this.globalData.isLoggedIn;
},
// 检查网络连接
isNetworkAvailable() {
return this.globalData.networkStatus !== 'none';
},
// 显示网络错误提示
showNetworkError() {
if (!this.isNetworkAvailable()) {
wx.showToast({
title: '网络连接不可用',
icon: 'none',
duration: 2000
});
return true;
}
return false;
},
// 全局错误处理工具
handleError(error, context = '') {
console.error(`${context} 错误:`, error);
// 根据错误类型显示不同提示
let message = '操作失败,请重试';
if (error.message) {
message = error.message;
} else if (error.errMsg) {
if (error.errMsg.includes('timeout')) {
message = '请求超时,请检查网络连接';
} else if (error.errMsg.includes('fail')) {
message = '网络连接失败';
}
}
wx.showToast({
title: message,
icon: 'none',
duration: 2000
});
},
// 显示加载状态
showLoading(title = '加载中...') {
wx.showLoading({
title: title,
mask: true
});
},
// 隐藏加载状态
hideLoading() {
wx.hideLoading();
},
// 兼容性方法 - 检查登录状态
isLoggedIn() {
return this.globalData.isLoggedIn;
},
// 兼容性方法 - 获取用户信息
getUserInfo() {
return this.globalData.userInfo;
},
// 兼容性方法 - 获取token
getToken() {
return authManager.getCurrentToken();
},
// 🔥 账号同步检查
async checkAccountSync() {
try {
console.log('开始检查账号同步状态...');
// 检查是否应该跳过绑定提示
if (accountSyncManager.shouldSkipBinding()) {
console.log('用户选择跳过绑定24小时内不再提示');
return;
}
// 自动检查并引导用户绑定手机号
await accountSyncManager.autoCheckAndBind();
} catch (error) {
console.error('账号同步检查失败:', error);
// 不影响主要功能,静默处理错误
}
}
})