2026-02-04 19:56:19 +08:00
|
|
|
<template>
|
|
|
|
|
<div class="flex h-screen w-screen overflow-hidden bg-white">
|
|
|
|
|
<!-- Left Navigation Sidebar -->
|
2026-02-11 18:30:45 +08:00
|
|
|
<div class="w-36 flex flex-col items-center py-4 bg-slate-900 border-r border-slate-800 z-50">
|
2026-02-04 19:56:19 +08:00
|
|
|
<div class="mb-6">
|
|
|
|
|
<!-- Logo or Brand -->
|
|
|
|
|
<div class="w-10 h-10 bg-blue-600 rounded-xl flex items-center justify-center shadow-lg shadow-blue-900/50">
|
|
|
|
|
<span class="material-icons-round text-white">grid_view</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-02-11 18:30:45 +08:00
|
|
|
<div class="flex-1 flex flex-col gap-3 w-full px-2">
|
2026-02-04 19:56:19 +08:00
|
|
|
|
|
|
|
|
<!-- TK Workbench Tab -->
|
|
|
|
|
<button @click="currentView = 'tk'"
|
2026-02-11 18:30:45 +08:00
|
|
|
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200"
|
2026-02-04 19:56:19 +08:00
|
|
|
:class="currentView === 'tk' ? 'bg-blue-600 text-white shadow-lg shadow-blue-900/30' : 'text-slate-400 hover:bg-slate-800 hover:text-white'">
|
2026-02-11 18:30:45 +08:00
|
|
|
<span class="material-icons-round text-xl">tiktok</span>
|
|
|
|
|
<span class="text-xs font-medium truncate">TK 工作台</span>
|
2026-02-04 19:56:19 +08:00
|
|
|
</button>
|
2026-02-11 18:30:45 +08:00
|
|
|
|
2026-02-04 19:56:19 +08:00
|
|
|
<!-- Hosts List Tab -->
|
|
|
|
|
<button @click="currentView = 'hosts'"
|
2026-02-11 18:30:45 +08:00
|
|
|
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200"
|
2026-02-04 19:56:19 +08:00
|
|
|
:class="currentView === 'hosts' ? 'bg-blue-600 text-white shadow-lg shadow-blue-900/30' : 'text-slate-400 hover:bg-slate-800 hover:text-white'">
|
2026-02-11 18:30:45 +08:00
|
|
|
<span class="material-icons-round text-xl">people</span>
|
|
|
|
|
<span class="text-xs font-medium truncate">主播列表</span>
|
2026-02-04 19:56:19 +08:00
|
|
|
</button>
|
2026-02-08 15:33:10 +08:00
|
|
|
|
2026-02-08 20:53:39 +08:00
|
|
|
<!-- Auto DM Workbench Tab -->
|
|
|
|
|
<button @click="currentView = 'auto_dm'"
|
2026-02-11 18:30:45 +08:00
|
|
|
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200"
|
2026-02-08 20:53:39 +08:00
|
|
|
:class="currentView === 'auto_dm' ? 'bg-blue-600 text-white shadow-lg shadow-blue-900/30' : 'text-slate-400 hover:bg-slate-800 hover:text-white'">
|
2026-02-11 18:30:45 +08:00
|
|
|
<span class="material-icons-round text-xl">chat</span>
|
|
|
|
|
<span class="text-xs font-medium truncate">自动私信</span>
|
2026-02-08 20:53:39 +08:00
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
<!-- Fan Workbench Tab -->
|
|
|
|
|
<button @click="currentView = 'FanWorkbench'"
|
2026-02-11 18:30:45 +08:00
|
|
|
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200"
|
2026-02-08 20:53:39 +08:00
|
|
|
:class="currentView === 'FanWorkbench' ? 'bg-blue-600 text-white shadow-lg shadow-blue-900/30' : 'text-slate-400 hover:bg-slate-800 hover:text-white'">
|
2026-02-11 18:30:45 +08:00
|
|
|
<span class="material-icons-round text-xl">supervised_user_circle</span>
|
|
|
|
|
<span class="text-xs font-medium truncate">大哥工作台</span>
|
2026-02-08 20:53:39 +08:00
|
|
|
</button>
|
|
|
|
|
|
2026-02-08 15:33:10 +08:00
|
|
|
<!-- PK 工作台 Tab -->
|
|
|
|
|
<button @click="currentView = 'pk_mini'"
|
2026-02-11 18:30:45 +08:00
|
|
|
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200"
|
2026-02-08 15:33:10 +08:00
|
|
|
:class="currentView === 'pk_mini' ? 'bg-blue-600 text-white shadow-lg shadow-blue-900/30' : 'text-slate-400 hover:bg-slate-800 hover:text-white'">
|
2026-02-11 18:30:45 +08:00
|
|
|
<span class="material-icons-round text-xl">sports_esports</span>
|
|
|
|
|
<span class="text-xs font-medium truncate">PK 工作台</span>
|
2026-02-08 15:33:10 +08:00
|
|
|
</button>
|
2026-02-12 13:03:52 +08:00
|
|
|
|
|
|
|
|
<!-- yolo商店 Tab -->
|
|
|
|
|
<button @click="currentView = 'shop'"
|
|
|
|
|
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200"
|
|
|
|
|
:class="currentView === 'shop' ? 'bg-blue-600 text-white shadow-lg shadow-blue-900/30' : 'text-slate-400 hover:bg-slate-800 hover:text-white'">
|
|
|
|
|
<span class="material-icons-round text-xl">admin_panel_settings</span>
|
|
|
|
|
<span class="text-xs font-medium truncate">YOLO商店</span>
|
|
|
|
|
</button>
|
2026-02-04 19:56:19 +08:00
|
|
|
</div>
|
|
|
|
|
|
2026-02-11 18:30:45 +08:00
|
|
|
<div class="mt-auto w-full px-2">
|
|
|
|
|
<!-- Logout -->
|
2026-02-04 19:56:19 +08:00
|
|
|
<button @click="$emit('logout')"
|
2026-02-11 18:30:45 +08:00
|
|
|
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 text-slate-400 hover:bg-slate-800 hover:text-red-400 transition-all">
|
|
|
|
|
<span class="material-icons-round text-xl">logout</span>
|
|
|
|
|
<span class="text-xs font-medium">退出登录</span>
|
2026-02-04 19:56:19 +08:00
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Main Content Area -->
|
|
|
|
|
<div class="flex-1 h-full relative">
|
|
|
|
|
|
2026-02-04 21:24:11 +08:00
|
|
|
<!-- Tab 1: Auto DM Workbench (Config + Browser) - webAi 权限 -->
|
2026-02-04 19:56:19 +08:00
|
|
|
<div v-show="currentView === 'auto_dm'" class="absolute inset-0 z-10 h-full w-full">
|
2026-02-04 21:24:11 +08:00
|
|
|
<PermissionMask
|
|
|
|
|
permission-key="webAi"
|
|
|
|
|
title="自动私信工作台未开通"
|
|
|
|
|
description="您当前没有使用自动私信功能的权限"
|
|
|
|
|
:placeholder-image="placeholderWebAi"
|
|
|
|
|
>
|
|
|
|
|
<div v-if="autoDmMode === 'config'" class="h-full w-full bg-slate-50 overflow-auto">
|
|
|
|
|
<ConfigPage
|
2026-02-04 19:56:19 +08:00
|
|
|
@go-to-browser="handleGoToBrowser"
|
|
|
|
|
@logout="$emit('logout')"
|
2026-02-04 21:24:11 +08:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-show="autoDmMode === 'browser'" class="h-full w-full">
|
2026-02-04 19:56:19 +08:00
|
|
|
<YoloBrowser
|
|
|
|
|
v-bind="$attrs"
|
|
|
|
|
@go-back="handleBackToConfig"
|
|
|
|
|
@stop-all="handleStopAll"
|
|
|
|
|
/>
|
2026-02-04 21:24:11 +08:00
|
|
|
</div>
|
|
|
|
|
</PermissionMask>
|
2026-02-04 19:56:19 +08:00
|
|
|
</div>
|
|
|
|
|
|
2026-02-04 21:24:11 +08:00
|
|
|
<!-- Tab 2: TK Workbench - crawl 权限 -->
|
2026-02-04 19:56:19 +08:00
|
|
|
<div v-show="currentView === 'tk'" class="absolute inset-0 z-20 bg-gray-50 h-full overflow-hidden">
|
2026-02-04 21:24:11 +08:00
|
|
|
<PermissionMask
|
|
|
|
|
permission-key="crawl"
|
|
|
|
|
title="TK工作台未开通"
|
|
|
|
|
description="您当前没有使用TK工作台功能的权限"
|
|
|
|
|
:placeholder-image="placeholderTk"
|
|
|
|
|
>
|
|
|
|
|
<TkWorkbenches />
|
|
|
|
|
</PermissionMask>
|
2026-02-04 19:56:19 +08:00
|
|
|
</div>
|
|
|
|
|
|
2026-02-04 21:24:11 +08:00
|
|
|
<!-- Tab 3: Hosts List - crawl 权限 -->
|
2026-02-04 19:56:19 +08:00
|
|
|
<div v-show="currentView === 'hosts'" class="absolute inset-0 z-20 bg-gray-50 h-full overflow-hidden p-4">
|
2026-02-04 21:24:11 +08:00
|
|
|
<PermissionMask
|
|
|
|
|
permission-key="crawl"
|
|
|
|
|
title="主播列表未开通"
|
|
|
|
|
description="您当前没有使用主播列表功能的权限"
|
|
|
|
|
:placeholder-image="placeholderHosts"
|
|
|
|
|
>
|
|
|
|
|
<HostsList />
|
|
|
|
|
</PermissionMask>
|
2026-02-04 19:56:19 +08:00
|
|
|
</div>
|
|
|
|
|
|
2026-02-04 21:24:11 +08:00
|
|
|
<!-- Tab 4: Fan Workbench - bigBrother 权限 -->
|
2026-02-04 19:56:19 +08:00
|
|
|
<div v-show="currentView === 'FanWorkbench'" class="absolute inset-0 z-20 bg-gray-50 h-full overflow-hidden p-4">
|
2026-02-08 15:33:10 +08:00
|
|
|
<PermissionMask
|
|
|
|
|
permission-key="bigBrother"
|
|
|
|
|
title="大哥工作台未开通"
|
2026-02-04 21:24:11 +08:00
|
|
|
description="您当前没有使用大哥工作台功能的权限"
|
|
|
|
|
:placeholder-image="placeholderBigBrother"
|
|
|
|
|
>
|
|
|
|
|
<FanWorkbench />
|
|
|
|
|
</PermissionMask>
|
2026-02-04 19:56:19 +08:00
|
|
|
</div>
|
2026-02-08 15:33:10 +08:00
|
|
|
|
|
|
|
|
<!-- Tab 5: PK Mini 工作台 - 无需权限控制 -->
|
|
|
|
|
<div v-show="currentView === 'pk_mini'" class="absolute inset-0 z-20 h-full overflow-hidden">
|
|
|
|
|
<PkMiniWorkbench />
|
|
|
|
|
</div>
|
2026-02-12 13:03:52 +08:00
|
|
|
|
|
|
|
|
<!-- Tab 6: yolo商店 - iframe 嵌入 -->
|
|
|
|
|
<div v-show="currentView === 'shop'" class="absolute inset-0 z-20 h-full overflow-hidden">
|
|
|
|
|
<iframe
|
|
|
|
|
v-if="adminLoaded"
|
2026-02-26 13:15:19 +08:00
|
|
|
:src="shopUrl"
|
2026-02-12 13:03:52 +08:00
|
|
|
class="w-full h-full border-0"
|
|
|
|
|
allow="clipboard-read; clipboard-write"
|
|
|
|
|
></iframe>
|
|
|
|
|
</div>
|
2026-02-04 19:56:19 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import { ref, watch } from 'vue'
|
|
|
|
|
import { isElectron } from '@/utils/electronBridge'
|
|
|
|
|
import YoloBrowser from '@/views/YoloBrowser.vue'
|
|
|
|
|
import TkWorkbenches from '@/views/tk/Workbenches.vue'
|
|
|
|
|
import HostsList from '@/views/tk/HostsList.vue'
|
|
|
|
|
import ConfigPage from '@/pages/ConfigPage.vue'
|
2026-02-04 21:24:11 +08:00
|
|
|
import FanWorkbench from '@/views/tk/FanWorkbench.vue'
|
2026-02-08 15:33:10 +08:00
|
|
|
import PkMiniWorkbench from '@/views/pk-mini/PkMiniWorkbench.vue'
|
2026-02-04 21:24:11 +08:00
|
|
|
import PermissionMask from '@/components/PermissionMask.vue'
|
2026-02-26 13:15:19 +08:00
|
|
|
import { ENV } from '@/config'
|
2026-02-04 21:24:11 +08:00
|
|
|
|
|
|
|
|
// 占位图片 - 无权限时显示的工作台截图
|
|
|
|
|
import placeholderTk from '@/assets/placeholder-tk.png'
|
|
|
|
|
import placeholderHosts from '@/assets/placeholder-hosts.png'
|
|
|
|
|
import placeholderWebAi from '@/assets/placeholder-webai.png'
|
|
|
|
|
import placeholderBigBrother from '@/assets/placeholder-bigbrother.png'
|
2026-02-04 19:56:19 +08:00
|
|
|
|
|
|
|
|
const emit = defineEmits(['logout', 'go-back', 'stop-all'])
|
|
|
|
|
|
2026-02-08 20:53:39 +08:00
|
|
|
const currentView = ref('tk') // Default Tab
|
2026-02-04 19:56:19 +08:00
|
|
|
const autoDmMode = ref('config') // Default Sub-state: 'config' or 'browser'
|
2026-02-12 13:03:52 +08:00
|
|
|
const adminLoaded = ref(false) // 懒加载:首次切换到管理后台时才加载 iframe
|
2026-02-26 13:15:19 +08:00
|
|
|
const shopUrl = ENV.SHOP_URL
|
2026-02-04 19:56:19 +08:00
|
|
|
|
|
|
|
|
const handleGoToBrowser = async () => {
|
|
|
|
|
autoDmMode.value = 'browser'
|
|
|
|
|
if (isElectron()) {
|
|
|
|
|
await window.electronAPI.showViews()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleBackToConfig = async () => {
|
|
|
|
|
autoDmMode.value = 'config'
|
|
|
|
|
if (isElectron()) {
|
|
|
|
|
await window.electronAPI.hideViews()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleStopAll = () => {
|
|
|
|
|
emit('stop-all')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Watch for view changes to manage native Electron BrowserViews
|
|
|
|
|
watch(currentView, async (newVal, oldVal) => {
|
2026-02-12 13:03:52 +08:00
|
|
|
// 懒加载管理后台 iframe
|
|
|
|
|
if (newVal === 'shop' && !adminLoaded.value) {
|
|
|
|
|
adminLoaded.value = true
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-04 19:56:19 +08:00
|
|
|
if (!isElectron()) return
|
|
|
|
|
|
|
|
|
|
if (newVal === 'auto_dm' && autoDmMode.value === 'browser') {
|
|
|
|
|
// Switching TO Auto DM tab AND we are in browser mode: Show views
|
|
|
|
|
try {
|
|
|
|
|
await window.electronAPI.showViews()
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('Failed to show views:', e)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Switching AWAY from Auto DM tab OR we are in config mode: Hide views
|
|
|
|
|
try {
|
|
|
|
|
await window.electronAPI.hideViews()
|
|
|
|
|
} catch (e) {
|
|
|
|
|
// console.error('Failed to hide views:', e)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Watch sub-mode changes
|
|
|
|
|
watch(autoDmMode, async (newVal) => {
|
|
|
|
|
if (currentView.value !== 'auto_dm') return
|
|
|
|
|
|
|
|
|
|
if (newVal === 'browser') {
|
|
|
|
|
if (isElectron()) await window.electronAPI.showViews()
|
|
|
|
|
} else {
|
|
|
|
|
if (isElectron()) await window.electronAPI.hideViews()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
/* Material Icons support - simplistic import, ideal to put in index.html or main.js */
|
|
|
|
|
@import url('https://fonts.googleapis.com/icon?family=Material+Icons+Round');
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|