aslan-h5/src/utils/usePageInitialization.js
2025-08-26 11:59:56 +08:00

430 lines
12 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.

import { ref, reactive, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import {
getBankBalance,
getMemberProfile,
getTeamMemberWorkStatistics,
getTeamEntry
} from '../api/wallet.js'
import { connectApplication, parseAccessOrigin, parseHeader, setHttpHeaders, isInApp } from '../utils/appBridge.js'
import { appConnectionManager, isAppConnected, getAppHeaderInfo } from '../utils/appConnectionManager.js'
import { checkAndRedirect } from '../utils/routeGuard.js'
import {getTeamInfo, getUserId, getUserProfile, setTeamInfo} from '../utils/userStore.js'
import { showError } from '../utils/toast.js'
/**
* 页面初始化公共组合式函数
* 适用于: HOST_CENTER, COIN_SELLER, AGENCY_CENTER, BD_CENTER, APPLY 等页面
*
* @param {Object} options 配置选项
* @param {boolean} options.needsBankBalance 是否需要获取银行余额 (默认: true)
* @param {boolean} options.needsWorkStatistics 是否需要获取工作统计 (默认: true)
* @param {boolean} options.needsRouteGuard 是否需要路由守卫检查 (默认: true)
* @param {Function} options.onDataLoaded 数据加载完成后的回调函数
* @param {Function} options.onConnectionSuccess APP连接成功后的回调函数
* @param {Function} options.onConnectionFailed APP连接失败后的回调函数
*/
export function usePageInitialization(options = {}) {
const {
needsBankBalance = true,
needsWorkStatistics = true,
needsTeamInfo = false,
needsRouteGuard = true,
onDataLoaded,
onConnectionSuccess,
onConnectionFailed
} = options
const router = useRouter()
// 响应式状态
const loading = ref(false)
const appConnected = ref(false)
const headerInfo = ref({})
const userProfile = ref(null)
// 用户信息
const userInfo = reactive({
name: 'user',
id: '1001',
userAvatar: '',
userNickname: 'user',
account: '1234567890'
})
// 收入信息
const salaryInfo = reactive({
hostSalary: 0.00,
currentSalary: 0.00
})
// 任务信息
const taskInfo = reactive({
anchorType: 'Chat',
minutesProgress: 0,
minutesTotal: 120,
giftTask: 0
})
/**
* 连接APP并获取认证信息优化版 - 仅专注连接)
*/
const connectToApp = async () => {
console.group('🔗 APP Connection Process')
console.debug('🚀 Starting APP connection...')
try {
// 检查是否在APP环境中
if (!isInApp()) {
console.debug('🌐 Browser environment detected')
appConnected.value = true
console.groupEnd()
// 触发连接成功回调
if (onConnectionSuccess) {
onConnectionSuccess({ environment: 'browser' })
}
return { success: true, environment: 'browser' }
}
// 检查是否已经连接且未过期
if (isAppConnected()) {
console.debug('✅ APP already connected and valid')
appConnected.value = true
// 使用缓存的头部信息
const cachedHeaderInfo = getAppHeaderInfo()
if (cachedHeaderInfo) {
headerInfo.value = cachedHeaderInfo
console.debug('🔧 Using cached HTTP headers')
}
console.groupEnd()
// 触发连接成功回调
if (onConnectionSuccess) {
onConnectionSuccess({ environment: 'app', fromCache: true })
}
return { success: true, environment: 'app', fromCache: true }
}
// 检查是否有正在进行的连接
if (appConnectionManager.isConnecting()) {
console.debug('⏳ Connection already in progress, waiting...')
await appConnectionManager.getConnectionPromise()
appConnected.value = true
console.debug('✅ Connected via existing process')
console.groupEnd()
// 触发连接成功回调
if (onConnectionSuccess) {
onConnectionSuccess({ environment: 'app', fromCache: true })
}
return { success: true, environment: 'app', fromCache: true }
}
// 建立新的APP连接
console.debug('📱 Establishing new APP connection...')
const connectionResult = await new Promise((resolve, reject) => {
const connectionPromise = new Promise((connectResolve, connectReject) => {
connectApplication(async (access) => {
try {
const result = parseAccessOrigin(access)
if (result.success) {
// 解析头部信息
headerInfo.value = parseHeader(result.data)
// 设置HTTP请求头
console.debug('🔧 Setting HTTP headers...')
await setHttpHeaders(headerInfo.value)
// 标记连接成功
appConnected.value = true
appConnectionManager.setConnected(headerInfo.value)
console.debug('🎉 APP connection established successfully')
connectResolve({ success: true, environment: 'app', fromCache: false })
} else {
console.error('❌ Failed to parse access origin:', result.error)
appConnectionManager.reset()
connectReject(new Error(result.error))
}
} catch (error) {
console.error('❌ Connection process failed:', error)
appConnectionManager.reset()
connectReject(error)
}
})
})
// 设置连接状态
appConnectionManager.setConnecting(connectionPromise)
connectionPromise
.then(resolve)
.catch(reject)
})
console.debug('✅ Connection completed successfully')
console.groupEnd()
// 触发连接成功回调
if (onConnectionSuccess) {
onConnectionSuccess(connectionResult)
}
return connectionResult
} catch (error) {
console.error('❌ Connection failed:', error)
appConnected.value = false
console.groupEnd()
// 触发连接失败回调
if (onConnectionFailed) {
onConnectionFailed(error)
}
// 连接失败的特殊处理
if (error.message && error.message.includes('parse access')) {
router.push({ path: '/not_app', query: { message: error.message }})
}
return { success: false, error: error.message }
}
}
const fetchUserInfo = async () => {
const userProfile = getUserProfile();
if (!userProfile) {
const res = await getMemberProfile()
if (res.status && res.body) {
userInfo.id = res.body.account
userInfo.userNickname = res.body.userNickname
userInfo.userAvatar = res.body.userAvatar
}
} else {
userInfo.id = userProfile.account
userInfo.userNickname = userProfile.userNickname
userInfo.userAvatar = userProfile.userAvatar
}
}
/**
* 获取团队信息
*/
const fetchTeamInfo = async () => {
if (!needsTeamInfo) return
const teamInfo = getTeamInfo()
if (teamInfo) return teamInfo
try {
console.debug('🏢 Fetching team information...')
const response = await getTeamEntry()
if (response && response.status && response.body) {
console.debug('✅ Team information retrieved successfully')
// 缓存团队信息
setTeamInfo(response.body.teamProfile || response.body)
} else {
console.warn('⚠️ Team entry response invalid or empty')
setTeamInfo(null)
}
} catch (error) {
console.debug('🔴 Team info fetch error:', error)
// 处理特定错误码
if (error.response && error.response.body && error.response.body.errorCode) {
const errorCode = error.response.body.errorCode
switch (errorCode) {
case 6025:
console.debug('🚫 User is not a team member (6025)')
break
case 6010:
console.debug('🚫 Team not found or disbanded (6010)')
break
default:
console.debug('❌ Other team error:', errorCode, error.response.body.message)
}
}
// 静默处理错误,不向上抛出
setTeamInfo(null)
}
}
/**
* 获取银行余额
*/
const fetchBankBalance = async () => {
if (!needsBankBalance) return
loading.value = true
try {
const response = await getBankBalance()
if (response.status && typeof response.body === 'number') {
// 格式化余额显示保留2位小数
salaryInfo.currentSalary = response.body.toFixed(2)
} else {
salaryInfo.currentSalary = 0.00
}
} catch (error) {
console.error('Failed to fetch bank balance:', error)
salaryInfo.currentSalary = 0.00
// 可以显示错误提示
showError('Failed to load balance. Please try again.')
} finally {
loading.value = false
}
}
/**
* 获取工作统计数据
*/
const fetchWorkStatistics = async () => {
if (!needsWorkStatistics) return
try {
const response = await getTeamMemberWorkStatistics('DAILY', getUserId())
if (response.status && response.body) {
// 更新任务信息
taskInfo.anchorType = 'Chat' // 固定值
const ownTime = Number(response.body.ownTime) || 0
const otherTime = Number(response.body.otherTime) || 0
const totalTime = ownTime + otherTime
taskInfo.minutesProgress = totalTime >= taskInfo.minutesTotal ? taskInfo.minutesTotal : totalTime
taskInfo.giftTask = response.body.acceptGiftValue || 0 // acceptGiftValue
}
} catch (error) {
console.error('获取工作统计失败:', error)
}
}
/**
* 数据初始化函数
*/
const initializePageData = async () => {
console.debug('📊 Starting data initialization...')
try {
const dataPromises = []
dataPromises.push(fetchUserInfo())
if (needsTeamInfo) {
dataPromises.push(fetchTeamInfo())
}
if (needsBankBalance) {
dataPromises.push(fetchBankBalance())
}
if (needsWorkStatistics) {
dataPromises.push(fetchWorkStatistics())
}
// 等待所有数据加载完成
await Promise.all(dataPromises)
// 使用路由守卫进行身份检查和重定向
if (needsRouteGuard) {
await checkAndRedirect(router, getUserId())
}
// 触发数据加载完成回调
if (onDataLoaded) {
onDataLoaded({
userProfile: userProfile.value,
userInfo: userInfo,
salaryInfo: salaryInfo,
taskInfo: taskInfo
})
}
console.debug('✅ Data initialization completed')
} catch (error) {
console.error('❌ Data initialization failed:', error)
}
}
/**
* 处理头像图片加载失败
*/
const handleImageError = () => {
// 图片加载失败时清空userAvatar显示占位符
userInfo.userAvatar = ''
}
/**
* 获取头像占位符(用户名首字母)
*/
const getAvatarPlaceholder = () => {
if (userInfo.name && userInfo.name.length > 0) {
return userInfo.name.charAt(0).toUpperCase()
}
return 'U' // 默认显示 'U'
}
/**
* 页面挂载时的初始化逻辑
*/
const initializePage = async () => {
console.debug('📄 Page initialization started')
try {
// 第一步仅进行APP连接
const connectionResult = await connectToApp()
// 第二步:根据连接结果决定是否初始化数据
if (connectionResult.success) {
console.debug('🔗 Connection successful, initializing data...')
await initializePageData()
} else {
console.warn('⚠️ Connection failed, skipping data initialization')
}
} catch (error) {
console.error('❌ Page initialization failed:', error)
}
}
// 自动在 onMounted 时初始化
onMounted(initializePage)
// 返回所有需要的状态和方法
return {
// 状态
loading,
appConnected,
headerInfo,
userProfile,
userInfo,
salaryInfo,
taskInfo,
// 方法
connectToApp,
initializePageData,
fetchUserInfo,
fetchTeamInfo,
fetchBankBalance,
fetchWorkStatistics,
handleImageError,
getAvatarPlaceholder,
initializePage,
// 手动初始化方法(如果需要重新初始化)
reinitialize: initializePage
}
}