import Taro from "@tarojs/taro"; import httpService, { ApiResponse } from "./httpService"; import tokenManager from "../utils/tokenManager"; import { useUser } from "@/store/userStore"; // 微信用户信息接口 export interface WechatUserInfo { id: string; nickname: string; avatar: string; gender: number; city: string; province: string; country: string; } // 登录响应接口 export interface LoginResponse { success: boolean; message: string; token?: string; user_info?: WechatUserInfo; phone_update_status?: string; existing_phone?: string; } // 发送短信响应接口 export interface SmsResponse { success: boolean; message: string; } // 验证验证码响应接口 export interface VerifyCodeResponse { success: boolean; message: string; token?: string; user_info?: WechatUserInfo; } // 用户详细信息 export interface UserStats { followers_count: number; following_count: number; hosted_games_count: number; participated_games_count: number; } // 手机号验证码登录接口参数 export interface PhoneLoginParams { phone: string; verification_code: string; user_code: string; } export interface UserInfoType { subscribe_time: string; last_login_time: string; create_time: string; last_modify_time: string; id: number; openid: string; user_code: string | null; unionid: string; session_key: string; nickname: string; ntrp_level: string; occupation: string | null; avatar_url: string; gender: string; country: string; province: string; city: string; language: string; phone: string; personal_profile: string | null; is_subscribed: string; // 如果只会是 "0" | "1",也可以写成字面量联合类型 latitude: number; longitude: number; stats: UserStats; } // 微信授权登录 // phone_code: 可选参数,如果提供则绑定手机号,否则只进行微信授权 export const wechat_auth_login = async ( phone_code?: string ): Promise => { try { // 先进行微信登录获取code const login_result = await Taro.login(); if (!login_result.code) { return { success: false, message: "微信登录失败", }; } // 构建请求参数 const requestData: any = { code: login_result.code, }; // 只有在提供 phone_code 时才添加到请求参数中 if (phone_code) { requestData.phone_code = phone_code; } // 使用 httpService 调用微信授权接口 const auth_response = await httpService.post("user/wx_auth", requestData); if (auth_response.code === 0) { return { success: true, message: "微信登录成功", token: auth_response.data?.token || "", user_info: auth_response.data?.userInfo, }; } else { return { success: false, message: auth_response.message || "微信授权失败", }; } } catch (error) { console.error("微信授权登录失败:", error); return { success: false, message: "微信授权失败,请重试", }; } }; // 手机号验证码登录接口参数 export interface PhoneLoginParams { phone: string; verification_code: string; user_code: string; } // 更新手机号接口参数 export interface ChangePhoneParams { phone: string; } // 手机号验证码登录 export const phone_auth_login = async ( params: PhoneLoginParams ): Promise => { try { // 使用 httpService 调用验证验证码接口 const verify_response = await httpService.post("user/sms/verify", { phone: params.phone, code: params.verification_code, user_code: params.user_code, }); if (verify_response.code === 0) { // 登录成功后,更新用户信息到 store try { await useUser.getState().fetchUserInfo(); await useUser.getState().checkNicknameChangeStatus(); } catch (error) { console.error("更新用户信息到 store 失败:", error); } return { success: true, message: "登录成功", token: verify_response.data?.token, user_info: verify_response.data?.userInfo, phone_update_status: verify_response.data?.phone_update_status, existing_phone: verify_response.data?.existing_phone, }; } else { return { success: false, message: verify_response.message || "验证码错误", }; } } catch (error) { console.error("手机号登录失败:", error); return { success: false, message: error.message, }; } }; // 发送短信验证码 export const send_sms_code = async (phone: string): Promise => { try { const response = await httpService.post("user/sms/send", { phone: phone, }); // 修复响应检查逻辑:检查 code === 0 或 success === true if (response.code === 0 || response.success === true) { return { success: true, message: "验证码发送成功", }; } else { return { success: false, message: response.message || "验证码发送失败", }; } } catch (error) { console.error("发送短信失败:", error); return { success: false, message: error.message, }; } }; // 验证短信验证码 export const verify_sms_code = async ( phone: string, code: string ): Promise => { try { const response = await httpService.post("user/sms/verify", { phone: phone, code: code, }); return { success: response.success, message: response.message || "验证失败", token: response.data?.token, user_info: response.data?.userInfo, }; } catch (error) { console.error("验证验证码失败:", error); return { success: false, message: error.message, }; } }; // 保存用户登录状态 export const save_login_state = (token: string, user_info: WechatUserInfo) => { try { // 使用 tokenManager 保存令牌信息,设置24小时过期 const expires_at = Date.now() + 24 * 60 * 60 * 1000; // 24小时后过期 tokenManager.setToken({ accessToken: token, expiresAt: expires_at, }); // 保存用户信息 Taro.setStorageSync("user_info", JSON.stringify(user_info)); Taro.setStorageSync("is_logged_in", true); Taro.setStorageSync("login_time", Date.now()); } catch (error) { console.error("保存登录状态失败:", error); } }; // 清除登录状态 export const clear_login_state = () => { try { // 使用 tokenManager 清除令牌 // tokenManager.clearTokens(); // 清除其他登录状态 Taro.removeStorageSync("user_info"); Taro.removeStorageSync("is_logged_in"); Taro.removeStorageSync("login_time"); } catch (error) { console.error("清除登录状态失败:", error); } }; // 检查是否已登录 export const check_login_status = (): boolean => { try { // 使用 tokenManager 检查令牌有效性 if (!tokenManager.hasValidToken()) { clear_login_state(); return false; } const is_logged_in = Taro.getStorageSync("is_logged_in"); return !!is_logged_in; } catch (error) { return false; } }; // 检查令牌是否需要刷新(剩余时间少于1小时时) export const should_refresh_token = (): boolean => { try { const remaining_time = tokenManager.getTokenRemainingTime(); const one_hour = 60 * 60 * 1000; // 1小时 return remaining_time > 0 && remaining_time < one_hour; } catch (error) { return false; } }; // 获取令牌状态信息 export const get_token_status = () => { try { const is_valid = tokenManager.hasValidToken(); const remaining_time = tokenManager.getTokenRemainingTime(); const is_expired = tokenManager.isTokenExpired(); return { is_valid, remaining_time, is_expired, expires_in_minutes: Math.floor(remaining_time / (60 * 1000)), }; } catch (error) { return { is_valid: false, remaining_time: 0, is_expired: true, expires_in_minutes: 0, }; } }; // 获取用户信息 export const get_user_info = (): WechatUserInfo | null => { try { let userinfo = Taro.getStorageSync("user_info"); if (userinfo) { return JSON.parse(userinfo); } return null; } catch (error) { return null; } }; // 获取用户token export const get_user_token = (): string | null => { try { // 使用 tokenManager 获取令牌 return tokenManager.getAccessToken(); } catch (error) { return null; } }; // 检查微信登录状态 export const check_wechat_login = async (): Promise => { try { const check_result = await Taro.checkSession(); // Taro.checkSession 返回的是 { errMsg: string } return check_result.errMsg === "checkSession:ok"; } catch (error) { return false; } }; // 刷新登录状态 export const refresh_login_status = async (): Promise => { try { // 检查微信登录状态 const is_valid = await check_wechat_login(); if (!is_valid) { // 微信登录已过期,需要重新登录 clear_login_state(); return false; } // 检查本地存储的登录状态 return check_login_status(); } catch (error) { console.error("刷新登录状态失败:", error); return false; } }; // 更新用户手机号 export const updateUserPhone = async (payload: ChangePhoneParams) => { try { const response = await httpService.post("/user/update_phone", payload); return response; } catch (error) { console.error("更新用户手机号失败:", error); throw error; } }; // 获取指定用户信息 export const getUserInfoById = async (id) => { try { const response = await httpService.post( "/user/detail_by_id", { id }, { showLoading: false, showToast: false, // 不显示错误弹窗 } ); return response; } catch (error) { console.error("获取用户信息失败:", error); throw error; } }; // 关注用户 export const followUser = async (following_id) => { try { const response = await httpService.post("/wch_users/follow", { following_id, }); return response; } catch (error) { console.error("关注失败:", error); throw error; } }; // 取消关注用户 export const unFollowUser = async (following_id) => { try { const response = await httpService.post("/wch_users/unfollow", { following_id, }); return response; } catch (error) { console.error("取消关注失败:", error); throw error; } }; // 静默登录锁,防止并发调用 let silentLoginPromise: Promise | null = null; // 静默登录:只获取用户ID和token,不需要手机号 export const silentLogin = async (): Promise => { // 如果已经有正在进行的静默登录,直接返回该 Promise if (silentLoginPromise) { console.log("静默登录正在进行中,等待结果..."); return silentLoginPromise; } // 先检查是否已经登录 if (check_login_status()) { console.log("已登录,跳过静默登录"); return { success: true, message: "已登录", token: get_user_token() || undefined, user_info: get_user_info() || undefined, }; } // 创建静默登录 Promise silentLoginPromise = (async (): Promise => { try { console.log("开始执行静默登录..."); // 调用微信登录获取code const login_result = await Taro.login(); console.log("微信登录结果:", login_result); if (!login_result.code) { console.error("微信登录失败:未获取到code"); return { success: false, message: "微信登录失败", }; } // 调用微信授权接口,不传 phone_code(静默登录) console.log("调用后端接口进行静默登录..."); const auth_response = await httpService.post( "user/wx_auth", { code: login_result.code, // 不传 phone_code,实现静默登录 }, { showLoading: false, // 静默登录不显示loading } ); console.log("后端接口响应:", auth_response); if (auth_response.code === 0) { const token = auth_response.data?.token || ""; const user_info = auth_response.data?.userInfo; // 保存登录状态 if (token && user_info) { console.log("保存登录状态..."); save_login_state(token, user_info); console.log("静默登录成功,已保存登录状态"); } else { console.warn("静默登录成功,但token或user_info为空"); } return { success: true, message: "静默登录成功", token, user_info, }; } else { console.error("静默登录失败:", auth_response.message); return { success: false, message: auth_response.message || "静默登录失败", }; } } catch (error) { console.error("静默登录异常:", error); return { success: false, message: "静默登录失败,请重试", }; } finally { // 清除锁,允许下次调用 silentLoginPromise = null; } })(); return silentLoginPromise; };