初始化功能优化
This commit is contained in:
parent
32730f9299
commit
42cee4913a
@ -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
82
src/utils/pageConfig.js
Normal 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)
|
||||
}
|
||||
|
||||
@ -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]
|
||||
}
|
||||
|
||||
|
||||
392
src/utils/usePageInitialization.js
Normal file
392
src/utils/usePageInitialization.js
Normal 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
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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 406错误通常表示NOT_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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user