初始化功能优化

This commit is contained in:
tianfeng 2025-08-22 14:41:35 +08:00
parent 32730f9299
commit 42cee4913a
7 changed files with 553 additions and 419 deletions

View File

@ -94,15 +94,7 @@ export function connectApplication(renderFun) {
window.getIosAccessOriginParam = renderFun
try {
if (ios()) {
console.debug('ios access detected')
// iOS可能需要特殊处理这里先使用通用方法
if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.getAccessOrigin) {
window.webkit.messageHandlers.getAccessOrigin.postMessage({})
} else if (window.app && window.app.getAccessOrigin) {
renderFun(window.app.getAccessOrigin())
}
} else if (android()) {
if (android()) {
console.debug('Flutter Android WebView 检测')
console.debug('window.app 对象:', window.app)
@ -177,7 +169,19 @@ export function connectApplication(renderFun) {
}
checkApp()
}
} else {
}
/*else if (ios()) {
console.debug('ios access detected')
// iOS可能需要特殊处理这里先使用通用方法
if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.getAccessOrigin) {
window.webkit.messageHandlers.getAccessOrigin.postMessage({})
} else if (window.app && window.app.getAccessOrigin) {
renderFun(window.app.getAccessOrigin())
}
}*/
else {
console.debug('非移动设备环境')
// 非APP环境可能是浏览器调试
console.warn('Not in APP environment, using mock data for development')

82
src/utils/pageConfig.js Normal file
View File

@ -0,0 +1,82 @@
// src/config/pageConfigs.js
/**
* 各页面的初始化配置
* 统一管理不同页面对 usePageInitialization 的配置需求
*/
export const PageConfig = {
HOST_CENTER: {
needsBankBalance: true,
needsWorkStatistics: true,
needsRouteGuard: true,
title: 'Host Center',
userTag: '👑 Host'
},
COIN_SELLER: {
needsBankBalance: true,
needsWorkStatistics: false, // Coin Seller 不需要工作统计
needsRouteGuard: true,
title: 'Coin Seller',
userTag: '💰 Coin Seller'
},
AGENCY_CENTER: {
needsBankBalance: true,
needsWorkStatistics: true,
needsRouteGuard: true,
title: 'Agency Center',
userTag: '🏢 Agency'
},
BD_CENTER: {
needsBankBalance: true,
needsWorkStatistics: false, // BD 可能不需要日常工作统计
needsRouteGuard: true,
title: 'BD Center',
userTag: '📈 BD'
},
APPLY: {
needsBankBalance: false, // 申请页面不需要余额
needsWorkStatistics: false, // 申请页面不需要工作统计
needsRouteGuard: false, // 申请页面不需要身份检查
title: 'Apply',
userTag: null // 申请页面可能没有身份标签
}
}
/**
* 获取页面配置的工具函数
* @param {string} pageType 页面类型
* @returns {Object} 页面配置对象
*/
export function getPageConfig(pageType) {
const config = PageConfig[pageType]
if (!config) {
console.warn(`未找到页面配置: ${pageType}`)
return PageConfig.HOST_CENTER // 默认使用 HOST_CENTER 配置
}
return config
}
// ==========================================
import { usePageInitialization } from './usePageInitialization.js'
/**
* 使用预配置的页面初始化函数
* @param {string} pageType 页面类型 (HOST_CENTER, COIN_SELLER, etc.)
* @param {Object} customOptions 自定义选项会覆盖默认配置
* @returns {Object} usePageInitialization 的返回值
*/
export function usePageInitializationWithConfig(pageType, customOptions = {}) {
const pageConfig = getPageConfig(pageType)
// 合并默认配置和自定义选项
const options = {
...pageConfig,
...customOptions
}
return usePageInitialization(options)
}

View File

@ -6,7 +6,7 @@
// 用户身份类型
export const USER_ROLES = {
FREIGHT_AGENT: 'freightAgent',
AGENT: 'agent',
AGENT: 'agent',
BD: 'bd',
ANCHOR: 'anchor',
GUEST: 'guest'
@ -16,7 +16,7 @@ export const USER_ROLES = {
export const PAGES = {
COIN_SELLER: '/coin-seller',
AGENCY_CENTER: '/agency-center',
BD_CENTER: '/bd-center',
BD_CENTER: '/bd-center',
HOST_CENTER: '/host-center',
APPLY: '/apply',
MESSAGE: '/message',
@ -30,7 +30,7 @@ export const PAGE_PERMISSIONS = {
[PAGES.COIN_SELLER]: [USER_ROLES.FREIGHT_AGENT],
[PAGES.AGENCY_CENTER]: [USER_ROLES.AGENT],
[PAGES.BD_CENTER]: [USER_ROLES.BD],
[PAGES.HOST_CENTER]: [USER_ROLES.AGENT, USER_ROLES.ANCHOR],
[PAGES.HOST_CENTER]: [USER_ROLES.ANCHOR],
[PAGES.APPLY]: [USER_ROLES.GUEST],
[PAGES.MESSAGE]: [USER_ROLES.AGENT],
[PAGES.TRANSFER]: [USER_ROLES.AGENT, USER_ROLES.BD, USER_ROLES.ANCHOR],
@ -76,7 +76,7 @@ class PermissionManager {
this.primaryRole = this.calculatePrimaryRole(identity)
this.allowedPages = this.calculateAllowedPages(this.primaryRole)
this.isIdentityLoaded = true
console.debug('🔐 User identity updated:', {
identity: this.userIdentity,
primaryRole: this.primaryRole,
@ -97,7 +97,7 @@ class PermissionManager {
if (identity.agent) return USER_ROLES.AGENT
if (identity.bd) return USER_ROLES.BD
if (identity.anchor) return USER_ROLES.ANCHOR
return USER_ROLES.GUEST
}
@ -108,13 +108,13 @@ class PermissionManager {
*/
calculateAllowedPages(primaryRole) {
const allowedPages = []
Object.entries(PAGE_PERMISSIONS).forEach(([page, roles]) => {
if (roles.length === 0 || roles.includes(primaryRole)) {
allowedPages.push(page)
}
})
return allowedPages
}
@ -131,13 +131,13 @@ class PermissionManager {
// 检查是否在允许列表中
const hasPermission = this.allowedPages.includes(page)
console.debug('🔍 Permission check:', {
page,
primaryRole: this.primaryRole,
hasPermission
})
return hasPermission
}
@ -179,13 +179,13 @@ class PermissionManager {
*/
getAllRoles() {
if (!this.userIdentity) return [USER_ROLES.GUEST]
const roles = []
if (this.userIdentity.freightAgent) roles.push(USER_ROLES.FREIGHT_AGENT)
if (this.userIdentity.agent) roles.push(USER_ROLES.AGENT)
if (this.userIdentity.bd) roles.push(USER_ROLES.BD)
if (this.userIdentity.anchor) roles.push(USER_ROLES.ANCHOR)
return roles.length > 0 ? roles : [USER_ROLES.GUEST]
}

View File

@ -0,0 +1,392 @@
// src/composables/usePageInitialization.js
import { ref, reactive, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { getBankBalance, getTeamEntry, getTeamMemberWorkStatistics } 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 { getUserId, setUserInfo } 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,
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 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' // 固定值
taskInfo.minutesProgress = response.body.ownTime
taskInfo.giftTask = response.body.acceptGiftValue || 0 // acceptGiftValue
}
} catch (error) {
console.error('获取工作统计失败:', error)
}
}
/**
* 获取团队入口信息
*/
const fetchTeamEntry = async () => {
try {
const response = await getTeamEntry()
if (response && response.status && response.body) {
userProfile.value = response.body
// 缓存用户信息
if (response.body.memberProfile) {
setUserInfo(response.body.memberProfile, response.body.teamProfile)
// 更新用户信息显示
userInfo.userNickname = response.body.memberProfile.userNickname
userInfo.id = response.body.memberProfile.account
userInfo.userAvatar = response.body.memberProfile.userAvatar
}
return response.body.memberProfile?.id
}
} catch (error) {
console.error('获取团队信息失败:', error)
if (error.message && error.message.includes('401')) {
await router.push({
path: '/not_app',
query: { message: error.message }
})
return
}
}
return null
}
/**
* 数据初始化函数
*/
const initializePageData = async () => {
console.debug('📊 Starting data initialization...')
try {
// 获取团队信息
const teamEntryResult = await fetchTeamEntry()
if (teamEntryResult != null) {
// 并行获取银行余额和工作统计(提高性能)
const dataPromises = []
if (needsBankBalance) {
dataPromises.push(fetchBankBalance())
}
if (needsWorkStatistics) {
dataPromises.push(fetchWorkStatistics())
}
// 等待所有数据加载完成
await Promise.all(dataPromises)
// 使用路由守卫进行身份检查和重定向
if (needsRouteGuard) {
await checkAndRedirect(router, teamEntryResult)
}
// 触发数据加载完成回调
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,
fetchBankBalance,
fetchWorkStatistics,
fetchTeamEntry,
handleImageError,
getAvatarPlaceholder,
initializePage,
// 手动初始化方法(如果需要重新初始化)
reinitialize: initializePage
}
}

View File

@ -10,13 +10,13 @@
<img
v-if="userInfo.userAvatar"
:src="userInfo.userAvatar"
:alt="userInfo.name"
:alt="userInfo.userNickname"
@error="handleImageError"
/>
<span v-else class="avatar-placeholder">{{ getAvatarPlaceholder() }}</span>
</div>
<div class="user-details">
<h3>{{ userInfo.name }}</h3>
<h3>{{ userInfo.userNickname }}</h3>
<p>ID: {{ userInfo.id }}</p>
</div>
<button class="notification-btn" @click="goToNotification">
@ -157,20 +157,15 @@
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { ref, reactive } from 'vue'
import { useRouter } from 'vue-router'
import MobileHeader from '../components/MobileHeader.vue'
import { get } from '../utils/http.js'
import {getBankBalance, getTeamEntry} from "@/api/wallet.js";
import {getTeamId, setUserInfo} from "@/utils/userStore.js";
import {showError} from "@/utils/toast.js";
import {usePageInitializationWithConfig} from "@/utils/pageConfig.js";
import {getTeamId} from "@/utils/userStore.js";
import {getTeamMemberCount} from "@/api/teamBill.js";
const router = useRouter()
//
const currentIdentity = ref('agency')
//
const taskTab = ref('agency')
@ -178,27 +173,6 @@ const taskTab = ref('agency')
const teamMemberCount = ref(0)
const loadingMemberCount = ref(false)
//
const salaryInfo = reactive({
historySalary: 12345,
currentSalary: 12345
})
//
const userInfo = reactive({
userAvatar: '',
name: 'User1',
id: '1234567890'
})
//
const taskInfo = reactive({
anchorType: 'Chat',
minutesProgress: '120',
minutesTotal: '120',
giftTask: 0
})
// Team Bill
const teamBillInfo = reactive({
date: '2025.08',
@ -241,73 +215,35 @@ const goToPersonalSalary = () => {
const fetchTeamMemberCount = async () => {
try {
loadingMemberCount.value = true
// 使teamId使ID
const teamId = getTeamId()
const response = await getTeamMemberCount(teamId)
if (response.status && typeof response.body === 'number') {
teamMemberCount.value = response.body
} else {
teamMemberCount.value = 0
if (teamId) {
const response = await getTeamMemberCount(teamId)
if (response.status && typeof response.body === 'number') {
teamMemberCount.value = response.body
} else {
teamMemberCount.value = 0
}
}
} catch (error) {
console.error('Failed to fetch team member count:', error)
teamMemberCount.value = 0
teamMemberCount.value = 87 // 使
} finally {
loadingMemberCount.value = false
}
}
const fetchTeamEntry = async () => {
const response = await getTeamEntry()
const member = response.body.memberProfile
if (member) {
//
userInfo.name = member.userNickname
userInfo.id = member.account
userInfo.userAvatar = member.userAvatar
const {
userInfo,
salaryInfo,
taskInfo,
handleImageError,
getAvatarPlaceholder
} = usePageInitializationWithConfig('AGENCY_CENTER', {
onDataLoaded: (data) => {
fetchTeamMemberCount()
}
}
//
const fetchBankBalance = async () => {
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.')
}
}
//
const handleImageError = (event) => {
// userAvatar
userInfo.userAvatar = ''
}
//
const getAvatarPlaceholder = () => {
if (userInfo.name && userInfo.name.length > 0) {
return userInfo.name.charAt(0).toUpperCase()
}
return 'U' // 'U'
}
//
onMounted(() => {
fetchTeamEntry()
fetchTeamMemberCount()
fetchBankBalance()
})
</script>
@ -392,35 +328,6 @@ onMounted(() => {
cursor: pointer;
}
/* 身份切换标签 */
.identity-tabs {
display: flex;
gap: 8px;
margin: 12px 0;
}
.identity-tab {
padding: 6px 12px;
border: 1px solid #e5e7eb;
border-radius: 16px;
background-color: white;
color: #666;
font-size: 12px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
}
.identity-tab.active {
background-color: #8B5CF6;
color: white;
border-color: #8B5CF6;
}
.identity-tab:not(.active):hover {
border-color: #8B5CF6;
color: #8B5CF6;
}
.account-tags {
display: flex;
@ -439,11 +346,6 @@ onMounted(() => {
color: #1E40AF;
}
.salary-tag {
background-color: #FEF3C7;
color: #D97706;
}
/* Host Agency 标签页 */
.host-agency-tabs {
display: flex;
@ -665,14 +567,14 @@ onMounted(() => {
gap: 12px;
}
.team-bill-card {
/*.team-bill-card {
background-color: white;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
cursor: pointer;
transition: all 0.2s;
border: 2px solid #3B82F6;
}
}*/
.team-bill-card:active {
transform: scale(0.98);

View File

@ -5,7 +5,7 @@
<!-- 权限校验加载状态 -->
<div v-if="checkingAccess" class="loading-container">
<div class="loading-spinner"></div>
<p>正在校验权限...</p>
<p>Verifying permissions...</p>
</div>
<!-- 主要内容 -->
@ -25,10 +25,10 @@
</div>
<div class="user-details">
<h3>{{ userInfo.userNickname || userInfo.name }}</h3>
<p>ID: {{ userInfo.account || userInfo.id }}</p>
<p>ID: {{ userInfo.id || userInfo.id }}</p>
</div>
<button class="settings-btn" @click="goToSettings">
<span>📈</span>
<!-- <span>📈</span>-->
</button>
</div>
@ -78,7 +78,6 @@
placeholder="Please Enter The Amount Of Gold Coins To Transfer"
class="amount-input"
/>
<span class="currency-suffix">0/50</span>
</div>
<button
class="recharge-btn"
@ -93,24 +92,16 @@
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import { ref, computed } from 'vue'
import { useRouter } from 'vue-router'
import MobileHeader from '../components/MobileHeader.vue'
import { getSelectedUser, clearSelectedUser } from '../utils/coinSellerStore.js'
import { checkFreightDealer, getTeamEntry, getFreightBalance, searchFreightUser, freightRecharge } from '../api/wallet.js'
import { getSelectedUser } from '../utils/coinSellerStore.js'
import { checkFreightDealer, getTeamEntry, getFreightBalance, freightRecharge } from '../api/wallet.js'
import {showError} from "@/utils/toast.js";
import {usePageInitializationWithConfig} from "@/utils/pageConfig.js";
const router = useRouter()
//
const userInfo = ref({
name: 'User1',
id: '1234567890',
userNickname: 'User1',
account: '1234567890',
userAvatar: null
})
//
const dealerAccess = ref(false)
const checkingAccess = ref(true)
@ -136,13 +127,13 @@ const checkDealerAccess = async () => {
if (!dealerAccess.value) {
//
showError('您没有金币销售商权限')
showError('You do not have gold coin seller rights.')
router.go(-1)
return
}
}
} catch (error) {
console.error('权限校验失败:', error)
console.error('Permission verification failed:', error)
dealerAccess.value = false
router.go(-1)
} finally {
@ -266,18 +257,17 @@ const rechargeNow = async () => {
}
}
//
onMounted(async () => {
//
await checkDealerAccess()
//
if (dealerAccess.value) {
await fetchUserInfo()
await fetchFreightBalance()
initializeUser()
const {
userInfo
} = usePageInitializationWithConfig('COIN_SELLER', {
onDataLoaded: (data) => {
console.log('ddddddddddddddddddddddddd')
console.log(data)
checkDealerAccess()
fetchFreightBalance()
}
})
</script>
<style scoped>

View File

@ -125,200 +125,14 @@
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { reactive } from 'vue'
import { useRouter } from 'vue-router'
import MobileHeader from '../components/MobileHeader.vue'
import { getBankBalance, getTeamEntry, getTeamMemberWorkStatistics } 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 {getUserId, setUserInfo} from '../utils/userStore.js'
import {showError} from "@/utils/toast.js";
import {usePageInitializationWithConfig} from "@/utils/pageConfig.js";
import {isInApp} from "@/utils/appBridge.js";
const router = useRouter()
//
const loading = ref(false)
const appConnected = ref(false)
const headerInfo = ref({})
const userProfile = ref(null)
// APP
const connectToApp = async () => {
console.group('🔗 APP Connection Process (Optimized)')
console.debug('🚀 Starting optimized APP connection...')
// APP
if (!isInApp()) {
console.warn('⚠️ Not running in APP environment')
console.debug('🌐 Browser environment detected')
appConnected.value = true
console.debug('✅ Skipping APP connection, proceeding with team entry')
await fetchTeamEntry()
console.groupEnd()
return
}
//
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.debug('📊 Fetching data with existing connection...')
const teamEntryResult = await fetchTeamEntry()
if (teamEntryResult != null) {
await fetchBankBalance()
await fetchWorkStatistics()
// 使
await checkAndRedirect(router, teamEntryResult)
}
console.groupEnd()
return
}
//
if (appConnectionManager.isConnecting()) {
console.debug('⏳ Connection already in progress, waiting...')
try {
await appConnectionManager.getConnectionPromise()
appConnected.value = true
console.debug('✅ Connected via existing process')
console.groupEnd()
return
} catch (error) {
console.error('❌ Failed to wait for existing connection:', error)
}
}
console.debug('📱 APP environment detected, establishing new connection')
// Promise
const connectionPromise = new Promise((resolve, reject) => {
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')
//
console.debug('📊 Fetching team entry and bank balance...')
const teamEntryResult = await fetchTeamEntry()
if (teamEntryResult != null) {
await fetchBankBalance()
await fetchWorkStatistics()
// 使
await checkAndRedirect(router, teamEntryResult)
}
resolve()
} else {
console.error('❌ Failed to parse access origin:', result.error)
appConnectionManager.reset()
router.push({ path: '/not_app', query: { message: result.error }})
reject(new Error(result.error))
}
} catch (error) {
console.error('❌ Connection process failed:', error)
appConnectionManager.reset()
reject(error)
}
})
})
//
appConnectionManager.setConnecting(connectionPromise)
try {
await connectionPromise
console.debug('✅ Connection completed successfully')
} catch (error) {
console.error('❌ Connection failed:', error)
}
console.groupEnd()
}
//
const fetchBankBalance = async () => {
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 () => {
try {
const response = await getTeamMemberWorkStatistics('DAILY', getUserId())
if (response.status && response.body) {
//
taskInfo.anchorType = 'Chat' //
taskInfo.minutes = `${response.body.ownTime}/120` // ownTime/120
taskInfo.giftTask = response.body.acceptGiftValue || 0 // acceptGiftValue
}
} catch (error) {
console.error('获取工作统计失败:', error)
}
}
//
const userInfo = reactive({
name: 'User1',
id: '1234567890',
userAvatar: '',
userNickname: 'User1',
account: '1234567890'
})
//
const salaryInfo = reactive({
hostSalary: 120,
currentSalary: 0.00
})
//
const taskInfo = reactive({
anchorType: 'Chat',
minutes: '0/120',
giftTask: 0
})
//
const progressInfo = reactive({
@ -341,58 +155,6 @@ const goToNotification = () => {
router.push('/host-setting')
}
//
const fetchTeamEntry = async () => {
try {
const response = await getTeamEntry()
if (response && response.status && response.body) {
userProfile.value = response.body
//
if (response.body.memberProfile) {
setUserInfo(response.body.memberProfile, response.body.teamProfile)
//
userInfo.userNickname = response.body.memberProfile.userNickname
userInfo.account = response.body.memberProfile.account
userInfo.userAvatar = response.body.memberProfile.userAvatar
}
return response.body.memberProfile?.id
}
} catch (error) {
console.error('获取团队信息失败:', error)
// HTTP 406NOT_TEAM_MEMBER
if (error.message && error.message.includes('406')) {
await router.push('/apply')
return
}
if (error.message && error.message.includes('401')) {
await router.push({
path: '/not_app',
query: { message: error.message }
})
return
}
}
return null
}
//
const handleImageError = (event) => {
// userAvatar
userInfo.userAvatar = ''
}
//
const getAvatarPlaceholder = () => {
if (userInfo.name && userInfo.name.length > 0) {
return userInfo.name.charAt(0).toUpperCase()
}
return 'U' // 'U'
}
const exchangeGoldCoins = () => {
router.push('/exchange-gold-coins')
}
@ -401,13 +163,15 @@ const transfer = () => {
router.push('/transfer')
}
//
onMounted(async () => {
console.debug('📄 HostCenterView mounted')
const {
appConnected,
userInfo,
salaryInfo,
taskInfo,
handleImageError,
getAvatarPlaceholder
} = usePageInitializationWithConfig('HOST_CENTER')
// APP
await connectToApp()
})
</script>
<style scoped>