authRedirect.js 9.2 KB
/*
 * @Date: 2025-01-25 10:00:00
 * @LastEditors: hookehuyr hookehuyr@gmail.com
 * @LastEditTime: 2025-09-12 10:52:09
 * @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) => {
  return new Promise((resolve, reject) => {
    // 检查是否已经授权
    if (!needAuth()) {
      // 已经授权,直接返回成功
      if (onSuccess) {
        onSuccess({ code: 1, msg: '已授权' })
      }
      resolve({ code: 1, msg: '已授权' })
      return
    }

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

    // 调用微信登录
    Taro.login({
      success: function (res) {
        if (res.code) {
          // 构建请求数据
          const requestData = {
            code: res.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';
          }

          // 发起授权请求 - 使用request.post保持与手动授权一致
          request.post('/srv/?a=openid', requestData)
            .then(response => {
              Taro.hideLoading()

              if (response.data.code) {
                const cookie = response.cookies && response.cookies[0]
                if (cookie) {
                  // 保存sessionid到本地存储
                  wx.setStorageSync("sessionid", cookie)

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

                  // 静默授权成功

                  // 执行成功回调
                  if (onSuccess) {
                    onSuccess(response.data)
                  }

                  resolve(response.data)
                } else {
                  console.error('授权响应中没有cookie信息')

                  if (onError) {
                    onError('授权失败:没有获取到有效的会话信息')
                  }

                  reject(new Error('授权失败:没有获取到有效的会话信息'))
                }
              } else {
                console.error('静默授权失败:', response.data.msg)

                if (onError) {
                  onError(response.data.msg || '授权失败')
                }

                reject(new Error(response.data.msg || '授权失败'))
              }
            })
            .catch(error => {
              console.error('静默授权请求失败:', error)
              Taro.hideLoading()

              if (onError) {
                onError('网络请求失败,请稍后重试')
              }

              reject(new Error('授权失败,请稍后重试'))
            })
        } else {
          console.error('微信登录失败:', res.errMsg)
          Taro.hideLoading()

          if (onError) {
            onError('微信登录失败:' + res.errMsg)
          }

          reject(new Error('微信登录失败:' + res.errMsg))
        }
      },
      fail: (error) => {
        console.error('调用微信登录失败:', error)
        Taro.hideLoading()

        if (onError) {
          onError('调用微信登录失败')
        }

        reject(error)
      }
    })
  })
}

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