authRedirect.js 8.87 KB
/*
 * @Date: 2025-01-25 10:00:00
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2025-09-12 12:24:03
 * @FilePath: /lls_program/src/utils/authRedirect.js
 * @Description: 授权重定向处理工具函数
 */
import Taro from '@tarojs/taro'
import { routerStore } from '@/stores/router'
import request from '@/utils/request'
import { getMyFamiliesAPI } from '@/api/family'

/**
 * 获取当前页面完整路径(包含参数)
 * @returns {string} 完整的页面路径
 */
export const getCurrentPageFullPath = () => {
  const pages = getCurrentPages()
  if (pages.length === 0) return ''

  const currentPage = pages[pages.length - 1]
  const route = currentPage.route
  const options = currentPage.options

  // 构建查询参数字符串
  const queryParams = Object.keys(options)
    .map(key => `${key}=${encodeURIComponent(options[key])}`)
    .join('&')

  return queryParams ? `${route}?${queryParams}` : route
}

/**
 * 保存当前页面路径到路由存储
 * @param {string} customPath - 自定义路径,如果不提供则使用当前页面路径
 */
export const saveCurrentPagePath = (customPath) => {
  const router = routerStore()
  const path = customPath || getCurrentPageFullPath()
  router.add(path)
}

/**
 * 跳转到授权页面
 * @param {string} returnPath - 授权完成后要返回的页面路径
 */
export const navigateToAuth = (returnPath) => {
  // 保存返回路径
  if (returnPath) {
    saveCurrentPagePath(returnPath)
  } else {
    saveCurrentPagePath()
  }

  // 跳转到授权页面
  Taro.navigateTo({
    url: '/pages/auth/index'
  })
}

/**
 * 授权完成后返回原页面
 * @param {string} defaultPath - 默认返回路径,如果没有保存的路径则使用此路径
 */
/**
 * 检查用户是否已加入家庭
 * @returns {Promise<boolean>} 返回是否已加入家庭
 */
export const checkUserHasFamily = async () => {
  try {
    const { code, data } = await getMyFamiliesAPI()
    if (code && data && data.length > 0) {
      return true
    }
    return false
  } catch (error) {
    console.error('检查用户家庭状态失败:', error)
    return false
  }
}

/**
 * 返回到原始页面,优化版本避免重复跳转
 * @param {string} defaultPath - 默认跳转路径
 */
export const returnToOriginalPage = async (defaultPath = '/pages/Dashboard/index') => {
  const router = routerStore()
  const savedPath = router.url

  try {
    // 清除保存的路径
    router.remove()

    // 获取当前页面栈
    const pages = Taro.getCurrentPages()
    const currentPage = pages[pages.length - 1]
    const currentRoute = currentPage?.route

    // 确定目标路径
    let targetPath = defaultPath
    if (savedPath && savedPath !== '') {
      targetPath = savedPath.startsWith('/') ? savedPath : `/${savedPath}`
    }

    // 检查用户是否已加入家庭
    const hasFamily = await checkUserHasFamily()

    // 如果用户没有加入家庭,跳转到欢迎页面
    if (!hasFamily) {
      await Taro.reLaunch({
        url: '/pages/Welcome/index'
      })
      return
    }

    // 提取目标页面路由(去掉参数)
    const targetRoute = targetPath.split('?')[0].replace(/^\//, '')

    // 如果当前页面就是目标页面,不需要跳转
    if (currentRoute === targetRoute) {
      return
    }

    // 如果目标是首页,使用 reLaunch
    if (targetRoute === 'pages/Dashboard/index') {
      await Taro.reLaunch({
        url: '/pages/Dashboard/index'
      })
    } else {
      // 其他页面使用 redirectTo
      await Taro.redirectTo({
        url: targetPath
      })
    }
  } catch (error) {
    console.error('returnToOriginalPage 执行出错:', error)
    // 错误处理:检查是否有家庭,决定跳转到哪里
    try {
      const hasFamily = await checkUserHasFamily()
      if (hasFamily) {
        await Taro.reLaunch({
          url: '/pages/Dashboard/index'
        })
      } else {
        await Taro.reLaunch({
          url: '/pages/Welcome/index'
        })
      }
    } catch (finalError) {
      console.error('最终降级方案也失败了:', finalError)
    }
  }
}

/**
 * 检查页面是否来自分享
 * @param {Object} options - 页面参数
 * @returns {boolean} 是否来自分享
 */
export const isFromShare = (options) => {
  // 检查是否有分享相关的参数或标识
  return options && (options.from_share === '1' || options.scene)
}

/**
 * 处理分享页面的授权逻辑
 * @param {Object} options - 页面参数
 * @param {Function} callback - 授权成功后的回调函数
 */
export const handleSharePageAuth = async (options, callback) => {
  const sessionid = wx.getStorageSync('sessionid')

  if (!sessionid) {
    // 没有授权,需要先授权
    if (isFromShare(options)) {
      // 来自分享,保存当前页面路径用于授权后返回
      saveCurrentPagePath()
    }

    // 跳转到授权页面
    Taro.navigateTo({
      url: '/pages/auth/index'
    })
    return false
  }

  // 已授权,执行回调
  if (callback && typeof callback === 'function') {
    callback()
  }
  return true
}

/**
 * 为分享链接添加分享标识参数
 * @param {string} path - 原始路径
 * @returns {string} 添加分享标识后的路径
 */
export const addShareFlag = (path) => {
  const separator = path.includes('?') ? '&' : '?'
  return `${path}${separator}from_share=1`
}

/**
 * 静默授权处理函数
 * 在后台处理授权,不跳转页面,避免用户感知
 * @param {Function} onSuccess - 授权成功回调
 * @param {Function} onError - 授权失败回调
 * @returns {Promise} 授权结果
 */
export const silentAuth = async (onSuccess, onError) => {
  try {
    // 检查是否已经授权
    if (!needAuth()) {
      // 已经授权,直接返回成功
      if (onSuccess) {
        onSuccess({ code: 1, msg: '已授权' })
      }
      return { code: 1, msg: '已授权' }
    }

    // 显示loading提示
    Taro.showLoading({
      title: '加载中...',
      mask: true
    })

    // 调用微信登录
    const loginResult = await new Promise((resolve, reject) => {
      Taro.login({
        success: resolve,
        fail: reject
      })
    })

    if (!loginResult.code) {
      throw new Error('获取微信登录code失败')
    }

    // 构建请求数据
    const requestData = {
      code: loginResult.code,
    }

    // 测试环境下传递openid,正式环境不传递
    if (process.env.NODE_ENV === 'development') {
      requestData.openid = 'h-008';
      // requestData.openid = 'h-009';
      // requestData.openid = 'h-010';
      // requestData.openid = 'h-011';
      // requestData.openid = 'h-012';
      // requestData.openid = 'h-013';
      // requestData.openid = 'oWbdFvkD5VtloC50wSNR9IWiU2q8';
      // requestData.openid = 'oex8h5QZnZJto3ttvO6swSvylAQo';
    }

    // 发起授权请求
    const response = await request.post('/srv/?a=openid', requestData)
    Taro.hideLoading()

    if (!response.data.code) {
      const errorMsg = response.data.msg || '授权失败'
      console.error('静默授权失败:', errorMsg)
      if (onError) {
        onError(errorMsg)
      }
      throw new Error(errorMsg)
    }

    const cookie = response.cookies && response.cookies[0]
    if (!cookie) {
      const errorMsg = '授权失败:没有获取到有效的会话信息'
      console.error(errorMsg)
      if (onError) {
        onError(errorMsg)
      }
      throw new Error(errorMsg)
    }

    // 保存sessionid到本地存储
    wx.setStorageSync("sessionid", cookie)

    // 更新request默认headers
    request.defaults.headers.cookie = cookie

    // 静默授权成功,检查用户是否已加入家庭
    try {
      const hasFamily = await checkUserHasFamily()

      // 如果用户没有加入家庭,跳转到欢迎页面
      if (!hasFamily) {
        await Taro.reLaunch({
          url: '/pages/Welcome/index'
        })

        const result = { ...response.data, redirected: true }
        if (onSuccess) {
          onSuccess(result)
        }
        return result
      }

      // 用户已有家庭,执行成功回调
      if (onSuccess) {
        onSuccess(response.data)
      }
      return response.data

    } catch (familyCheckError) {
      console.error('检查家庭状态失败:', familyCheckError)

      // 家庭检查失败,仍然执行成功回调,让页面正常显示
      if (onSuccess) {
        onSuccess(response.data)
      }
      return response.data
    }

  } catch (error) {
    console.error('静默授权过程失败:', error)
    Taro.hideLoading()

    const errorMsg = error.message || '授权失败,请稍后重试'
    if (onError) {
      onError(errorMsg)
    }
    throw error
  }
}

/**
 * 检查是否需要授权
 * @returns {boolean} 是否需要授权
 */
export const needAuth = () => {
  try {
    const sessionid = wx.getStorageSync("sessionid")
    return !sessionid || sessionid === ''
  } catch (error) {
    console.error('检查授权状态失败:', error)
    return true
  }
}