Files
web-fusion/src/App.vue

284 lines
8.9 KiB
Vue
Raw Normal View History

2026-02-04 19:56:19 +08:00
<template>
<!-- 强制更新检查 -->
<!-- <UpdateChecker v-if="false" @ready="updateReady = true" /> -->
<UpdateChecker v-if="!isDev && isElectronEnv && !updateReady" @ready="updateReady = true" />
<template v-else>
2026-02-11 14:49:18 +08:00
<!-- 滚动通知栏登录页和工作台都显示 -->
<NoticeBar />
2026-02-04 19:56:19 +08:00
<!-- 登录页面 -->
<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" />
2026-03-13 17:48:00 +08:00
<!-- 更新通知组件启动时已在 UpdateChecker 检查此处暂不显示 -->
<!-- <UpdateNotification /> -->
2026-02-04 19:56:19 +08:00
</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'
2026-02-11 14:49:18 +08:00
import NoticeBar from './components/NoticeBar.vue'
import { useNoticeStore } from './stores/noticeStore'
2026-02-04 19:56:19 +08:00
// 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'
2026-02-11 14:49:18 +08:00
// 公告通知
const noticeStore = useNoticeStore()
noticeStore.fetchNotices()
2026-02-04 19:56:19 +08:00
// 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)
2026-03-03 14:36:25 +08:00
// 隐藏所有 BrowserView 并停止自动化,防止视图悬浮在登录页上方
try {
await window.electronAPI.hideViews()
await handleStopAll()
} catch (e) {
console.warn('[App] 清理视图失败:', e)
}
2026-02-04 19:56:19 +08:00
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 () => {
2026-03-05 14:47:02 +08:00
stopHealthCheck()
2026-02-04 19:56:19 +08:00
currentPage.value = 'login'
2026-03-03 14:36:25 +08:00
localStorage.removeItem(USER_KEY)
2026-03-05 14:47:02 +08:00
if (isElectron()) {
try { await window.electronAPI.logout() } catch (e) { console.warn('[App] logout失败:', e) }
try {
await window.electronAPI.hideViews()
await handleStopAll()
} catch (e) {
console.warn('[App] 清理视图失败:', e)
}
}
2026-02-04 19:56:19 +08:00
}
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>