Files
web-fusion/src/App.vue

259 lines
8.0 KiB
Vue
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.
<template>
<!-- 强制更新检查 -->
<!-- <UpdateChecker v-if="false" @ready="updateReady = true" /> -->
<UpdateChecker v-if="!isDev && isElectronEnv && !updateReady" @ready="updateReady = true" />
<template v-else>
<!-- 登录页面 -->
<LoginPage v-if="currentPage === 'login'" @login-success="currentPage = 'browser'" class="animate-fadeIn" />
<template v-else>
<!-- 配置页面 - 使用 v-show 保持状态 -->
<div class="h-full w-full animate-fadeIn" v-show="currentPage === 'config'">
<ConfigPage @go-to-browser="handleGoToBrowser" @logout="handleLogout" />
<UpdateNotification />
</div>
<!-- 浏览器页面 -->
<div class="h-full w-full animate-fadeIn" v-show="currentPage === 'browser'">
<WorkbenchLayout
:account-groups="accountGroups"
:rotation-status="rotationStatus"
:greeting-stats="greetingStats"
:automation-logs="automationLogs"
@go-back="handleGoToConfig"
@stop-all="handleStopAll"
@logout="handleLogout"
/>
</div>
</template>
</template>
</template>
<script setup>
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import { isElectron, getAppVersion } from './utils/electronBridge'
import LoginPage from './pages/LoginPage.vue'
import ConfigPage from './pages/ConfigPage.vue'
import UpdateChecker from './pages/UpdateChecker.vue'
import WorkbenchLayout from './layout/WorkbenchLayout.vue'
import UpdateNotification from './components/UpdateNotification.vue'
// Constants
const USER_KEY = 'user_data'
const CONFIG_KEY = 'autoDm_runConfig'
// State
const updateReady = ref(false)
const currentPage = ref('login')
const isLoading = ref(false)
const automationStatus = ref({})
const accountGroups = ref([])
const viewAccountMap = ref({})
const rotationStatus = ref(null)
const greetingStats = ref({ greetingCount: 0, inviteCount: 0 })
const automationLogs = ref([])
const isElectronEnv = isElectron()
const isDev = window.location.port === '5173'
// Lifecycle
onMounted(() => {
// Set Title
getAppVersion().then(version => {
document.title = `YoloAI助手Web版v${version}`
}).catch(() => {
document.title = 'YoloAI助手Web版'
})
console.log('[App]',!isDev , isElectronEnv , !updateReady.value)
// Check Login
try {
const userData = localStorage.getItem(USER_KEY)
if (userData) {
const user = JSON.parse(userData)
if (user && user.tokenValue) {
currentPage.value = 'browser'
}
}
} catch { } // eslint-disable-line no-empty
// Listeners
if (isElectronEnv) {
window.electronAPI.onRequestClearLogin(() => {
console.log('[App] 收到清除登录状态请求')
localStorage.removeItem(USER_KEY)
})
// Rotation Status
window.electronAPI.getRotationStatus().then(status => {
rotationStatus.value = status
}).catch(console.error)
window.electronAPI.onRotationStatusChanged(status => {
rotationStatus.value = status
console.log('[App] 收到轮换状态变化123:', status)
// Auto switch tab if group changes
if (status && status.currentActiveGroup && status.enabled) {
console.log('[App] 收到轮换状态变化456:', status)
const targetTab = tabs.value.find(t => t.label === status.currentActiveGroup || t.id === status.currentActiveGroup)
if (targetTab && targetTab.id !== currentTab.value) {
console.log('[App] 自动切换到轮换组789:', targetTab.id)
handleTabSwitch(targetTab.id)
}
}
})
// Stats
window.electronAPI.getGreetingStats().then(stats => {
greetingStats.value = stats
}).catch(console.error)
window.electronAPI.onGreetingStatsChanged(stats => {
greetingStats.value = stats
})
// Logs
window.electronAPI.onAutomationLog(log => {
automationLogs.value = [...automationLogs.value.slice(-99), { ...log, timestamp: Date.now() }]
})
}
window.addEventListener('beforeunload', handleBeforeUnload)
window.addEventListener('storage', handleStorageChange)
loadConfig()
// Health Check
startHealthCheck()
})
onUnmounted(() => {
window.removeEventListener('beforeunload', handleBeforeUnload)
window.removeEventListener('storage', handleStorageChange)
stopHealthCheck()
})
// Handlers
const handleBeforeUnload = () => {
localStorage.removeItem(USER_KEY)
}
const handleStorageChange = (e) => {
if (e.key === CONFIG_KEY) {
loadConfig()
}
}
let healthCheckInterval = null
const startHealthCheck = () => {
const check = async () => {
if (currentPage.value === 'login' || !isElectron()) return
try {
const result = await window.electronAPI.checkHealth()
if (result.success && result.code === 40400) {
alert('当前账号已在其他地方登录,请重新登录')
localStorage.removeItem(USER_KEY)
currentPage.value = 'login'
}
} catch (error) {
console.error('[App] 健康检查失败:', error)
}
}
check()
healthCheckInterval = setInterval(check, 5000)
}
const stopHealthCheck = () => {
if (healthCheckInterval) clearInterval(healthCheckInterval)
}
const loadConfig = () => {
try {
const savedConfig = localStorage.getItem(CONFIG_KEY)
if (savedConfig) {
const config = JSON.parse(savedConfig)
accountGroups.value = config.accountGroups || []
const map = {}
config.accountGroups.forEach((group, groupIndex) => {
const viewsPerGroup = 3
group.accounts.forEach((account, accIndex) => {
const viewId = groupIndex * viewsPerGroup + accIndex + 1
if (viewId <= 9 && account.email && account.pwd) {
map[viewId] = { ...account, group: group.name }
}
})
})
viewAccountMap.value = map
}
} catch { } // eslint-disable-line no-empty
}
watch(currentPage, (newVal) => {
if (newVal === 'browser') {
loadConfig()
}
})
// Actions
const handleGoToBrowser = async () => {
if (isElectron()) {
await window.electronAPI.showViews()
}
currentPage.value = 'browser'
}
const handleGoToConfig = async () => {
if (isElectron()) {
await window.electronAPI.hideViews()
}
currentPage.value = 'config'
}
const handleLogout = async () => {
if (isElectron()) {
await window.electronAPI.logout()
}
localStorage.removeItem(USER_KEY)
currentPage.value = 'login'
}
const handleStopAll = async () => {
if (!isElectron()) return
console.log('[App] 开始并行停止所有任务...')
await Promise.allSettled(
Array.from({ length: 9 }, (_, i) => i + 1).map(viewId =>
window.electronAPI.stopTikTokAutomation(viewId).catch((e) => {
console.warn(`[App] 停止视图 ${viewId} 失败:`, e)
})
)
)
try {
await window.electronAPI.updateAutomationConfig({
rotationEnabled: false
})
} catch (e) {
console.warn('[App] 停止轮换服务失败:', e)
}
automationStatus.value = {}
rotationStatus.value = null
try {
console.log('[App] 正在清空缓存...')
if (window.electronAPI.clearAllCache) await window.electronAPI.clearAllCache()
console.log('[App] 缓存清空完成')
} catch (e) {
console.warn('[App] 清空缓存失败:', e)
}
console.log('[App] 已并行停止所有任务并清空缓存')
}
</script>