销售名片
This commit is contained in:
@@ -1,71 +1,77 @@
|
||||
<template>
|
||||
<div class="flex h-screen w-screen overflow-hidden bg-white">
|
||||
<!-- Left Navigation Sidebar -->
|
||||
<div class="w-36 flex flex-col items-center py-4 bg-slate-900 border-r border-slate-800 z-50">
|
||||
<div class="mb-6">
|
||||
<div ref="sidebarRef" class="flex flex-col items-center py-4 border-r z-50" style="flex: 0 0 calc(100vw * 2 / 19); min-width: 96px; max-width: 400px; background-color: #F8F9FA;">
|
||||
<div class="mb-6" style="border-bottom: 1px solid #A0AEC023; padding: 10%;">
|
||||
<!-- 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 class="" >
|
||||
<img :src="yoloIcon" class="yolo-logo" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 flex flex-col gap-3 w-full px-2">
|
||||
<div class="flex-1 flex flex-col w-full px-2" style="gap: 2vh;">
|
||||
|
||||
<!-- TK Workbench Tab -->
|
||||
<button @click="currentView = 'tk'"
|
||||
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200"
|
||||
:class="currentView === 'tk' ? '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">tiktok</span>
|
||||
<span class="text-xs font-medium truncate">TK 工作台</span>
|
||||
style="height: 6vh;"
|
||||
:class="currentView === 'tk' ? 'bg-white text-blue-600 shadow shadow-blue-900/20' : 'text-slate-400 hover:bg-[rgba(21,96,250,0.06)]'">
|
||||
<img :src="currentView === 'tk' ? nav11 : nav1" class="w-9 h-9 object-contain flex-shrink-0" />
|
||||
<span class="text-base font-medium truncate">TK 工作台</span>
|
||||
</button>
|
||||
|
||||
<!-- Hosts List Tab -->
|
||||
<button @click="currentView = 'hosts'"
|
||||
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200"
|
||||
:class="currentView === 'hosts' ? '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">people</span>
|
||||
<span class="text-xs font-medium truncate">主播列表</span>
|
||||
style="height: 6vh;"
|
||||
:class="currentView === 'hosts' ? 'bg-white text-blue-600 shadow shadow-blue-900/20' : 'text-slate-400 hover:bg-[rgba(21,96,250,0.06)]'">
|
||||
<img :src="currentView === 'hosts' ? nav22 : nav2" class="w-9 h-9 object-contain flex-shrink-0" />
|
||||
<span class="text-base font-medium truncate">主播列表</span>
|
||||
</button>
|
||||
|
||||
<!-- Auto DM Workbench Tab -->
|
||||
<button @click="currentView = 'auto_dm'"
|
||||
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200"
|
||||
: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'">
|
||||
<span class="material-icons-round text-xl">chat</span>
|
||||
<span class="text-xs font-medium truncate">自动私信</span>
|
||||
style="height: 6vh;"
|
||||
:class="currentView === 'auto_dm' ? 'bg-white text-blue-600 shadow shadow-blue-900/20' : 'text-slate-400 hover:bg-[rgba(21,96,250,0.06)]'">
|
||||
<img :src="currentView === 'auto_dm' ? nav33 : nav3" class="w-9 h-9 object-contain flex-shrink-0" />
|
||||
<span class="text-base font-medium truncate">自动私信</span>
|
||||
</button>
|
||||
|
||||
<!-- Fan Workbench Tab -->
|
||||
<button @click="currentView = 'FanWorkbench'"
|
||||
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200"
|
||||
:class="currentView === 'FanWorkbench' ? '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">supervised_user_circle</span>
|
||||
<span class="text-xs font-medium truncate">大哥工作台</span>
|
||||
style="height: 6vh;"
|
||||
:class="currentView === 'FanWorkbench' ? 'bg-white text-blue-600 shadow shadow-blue-900/20' : 'text-slate-400 hover:bg-[rgba(21,96,250,0.06)]'">
|
||||
<img :src="currentView === 'FanWorkbench' ? nav44 : nav4" class="w-9 h-9 object-contain flex-shrink-0" />
|
||||
<span class="text-base font-medium truncate">大哥工作台</span>
|
||||
</button>
|
||||
|
||||
<!-- PK 工作台 Tab -->
|
||||
<button @click="currentView = 'pk_mini'"
|
||||
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 transition-all duration-200"
|
||||
: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'">
|
||||
<span class="material-icons-round text-xl">sports_esports</span>
|
||||
<span class="text-xs font-medium truncate">PK 工作台</span>
|
||||
style="height: 6vh;"
|
||||
:class="currentView === 'pk_mini' ? 'bg-white text-blue-600 shadow shadow-blue-900/20' : 'text-slate-400 hover:bg-[rgba(21,96,250,0.06)]'">
|
||||
<img :src="currentView === 'pk_mini' ? nav55 : nav5" class="w-9 h-9 object-contain flex-shrink-0" />
|
||||
<span class="text-base font-medium truncate">PK 工作台</span>
|
||||
</button>
|
||||
|
||||
<!-- 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>
|
||||
style="height: 6vh;"
|
||||
:class="currentView === 'shop' ? 'bg-white text-blue-600 shadow shadow-blue-900/20' : 'text-slate-400 hover:bg-[rgba(21,96,250,0.06)]'">
|
||||
<img :src="currentView === 'shop' ? nav66 : nav6" class="w-9 h-9 object-contain flex-shrink-0" />
|
||||
<span class="text-base font-medium truncate">TK商店</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mt-auto w-full px-2">
|
||||
<!-- Logout -->
|
||||
<button @click="$emit('logout')"
|
||||
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>
|
||||
class="w-full rounded-xl flex items-center gap-2 px-3 py-2.5 text-slate-400 bg-white shadow shadow-blue-900/20 transition-all">
|
||||
<img :src="backIcon" class="w-9 h-9 object-contain flex-shrink-0" />
|
||||
<span class="text-base font-medium" style="color: #ED4949;">退出登录</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -75,11 +81,12 @@
|
||||
|
||||
<!-- Tab 1: Auto DM Workbench (Config + Browser) - webAi 权限 -->
|
||||
<div v-show="currentView === 'auto_dm'" class="absolute inset-0 z-10 h-full w-full">
|
||||
<PermissionMask
|
||||
permission-key="webAi"
|
||||
title="自动私信工作台未开通"
|
||||
<PermissionMask
|
||||
permission-key="webAi"
|
||||
title="自动私信工作台未开通"
|
||||
description="您当前没有使用自动私信功能的权限"
|
||||
:placeholder-image="placeholderWebAi"
|
||||
:contacts="serviceContacts"
|
||||
>
|
||||
<div v-if="autoDmMode === 'config'" class="h-full w-full bg-slate-50 overflow-auto">
|
||||
<ConfigPage
|
||||
@@ -88,10 +95,11 @@
|
||||
/>
|
||||
</div>
|
||||
<div v-show="autoDmMode === 'browser'" class="h-full w-full">
|
||||
<YoloBrowser
|
||||
v-bind="$attrs"
|
||||
@go-back="handleBackToConfig"
|
||||
@stop-all="handleStopAll"
|
||||
<YoloBrowser
|
||||
v-bind="$attrs"
|
||||
:nav-sidebar-width="navSidebarWidth"
|
||||
@go-back="handleBackToConfig"
|
||||
@stop-all="handleStopAll"
|
||||
/>
|
||||
</div>
|
||||
</PermissionMask>
|
||||
@@ -99,11 +107,12 @@
|
||||
|
||||
<!-- Tab 2: TK Workbench - crawl 权限 -->
|
||||
<div v-show="currentView === 'tk'" class="absolute inset-0 z-20 bg-gray-50 h-full overflow-hidden">
|
||||
<PermissionMask
|
||||
permission-key="crawl"
|
||||
title="TK工作台未开通"
|
||||
<PermissionMask
|
||||
permission-key="crawl"
|
||||
title="TK工作台未开通"
|
||||
description="您当前没有使用TK工作台功能的权限"
|
||||
:placeholder-image="placeholderTk"
|
||||
:contacts="serviceContacts"
|
||||
>
|
||||
<TkWorkbenches />
|
||||
</PermissionMask>
|
||||
@@ -111,11 +120,12 @@
|
||||
|
||||
<!-- Tab 3: Hosts List - crawl 权限 -->
|
||||
<div v-show="currentView === 'hosts'" class="absolute inset-0 z-20 bg-gray-50 h-full overflow-hidden p-4">
|
||||
<PermissionMask
|
||||
permission-key="crawl"
|
||||
title="主播列表未开通"
|
||||
<PermissionMask
|
||||
permission-key="crawl"
|
||||
title="主播列表未开通"
|
||||
description="您当前没有使用主播列表功能的权限"
|
||||
:placeholder-image="placeholderHosts"
|
||||
:contacts="serviceContacts"
|
||||
>
|
||||
<HostsList />
|
||||
</PermissionMask>
|
||||
@@ -128,6 +138,7 @@
|
||||
title="大哥工作台未开通"
|
||||
description="您当前没有使用大哥工作台功能的权限"
|
||||
:placeholder-image="placeholderBigBrother"
|
||||
:contacts="serviceContacts"
|
||||
>
|
||||
<FanWorkbench />
|
||||
</PermissionMask>
|
||||
@@ -140,7 +151,7 @@
|
||||
|
||||
<!-- Tab 6: yolo商店 - Electron 用 BrowserView,Web 用 iframe 兜底 -->
|
||||
<div v-show="currentView === 'shop'" class="absolute inset-0 z-20 h-full overflow-hidden">
|
||||
<div v-if="isElectron()" class="w-full h-full flex items-center justify-center text-sm text-slate-500 bg-white">
|
||||
<div v-if="isElectron()" class="w-full h-full flex items-center justify-center text-base text-slate-500 bg-white">
|
||||
正在进入商店...
|
||||
</div>
|
||||
<iframe
|
||||
@@ -156,7 +167,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { ref, watch, onMounted, onUnmounted, useTemplateRef } from 'vue'
|
||||
import { isElectron } from '@/utils/electronBridge'
|
||||
import YoloBrowser from '@/views/YoloBrowser.vue'
|
||||
import TkWorkbenches from '@/views/tk/Workbenches.vue'
|
||||
@@ -166,6 +177,23 @@ import FanWorkbench from '@/views/tk/FanWorkbench.vue'
|
||||
import PkMiniWorkbench from '@/views/pk-mini/PkMiniWorkbench.vue'
|
||||
import PermissionMask from '@/components/PermissionMask.vue'
|
||||
import { ENV } from '@/config'
|
||||
import { getCustomServiceInfo } from '@/api/account'
|
||||
|
||||
// 导航图标
|
||||
import yoloIcon from '@/assets/nav/yolo.png'
|
||||
import nav1 from '@/assets/nav/nav1.png'
|
||||
import nav11 from '@/assets/nav/nav11.png'
|
||||
import nav2 from '@/assets/nav/nav2.png'
|
||||
import nav22 from '@/assets/nav/nav22.png'
|
||||
import nav3 from '@/assets/nav/nav3.png'
|
||||
import nav33 from '@/assets/nav/nav33.png'
|
||||
import nav4 from '@/assets/nav/nav4.png'
|
||||
import nav44 from '@/assets/nav/nav44.png'
|
||||
import nav5 from '@/assets/nav/nav5.png'
|
||||
import nav55 from '@/assets/nav/nav55.png'
|
||||
import nav6 from '@/assets/nav/nav6.png'
|
||||
import nav66 from '@/assets/nav/nav66.png'
|
||||
import backIcon from '@/assets/nav/back.png'
|
||||
|
||||
// 占位图片 - 无权限时显示的工作台截图
|
||||
import placeholderTk from '@/assets/placeholder-tk.png'
|
||||
@@ -180,6 +208,53 @@ const autoDmMode = ref('config') // Default Sub-state: 'config' or 'browser'
|
||||
const adminLoaded = ref(false) // Web iframe 懒加载(仅非 Electron)
|
||||
const shopOpened = ref(false) // Electron 只首开加载一次
|
||||
const shopUrl = ENV.SHOP_URL
|
||||
const sidebarRef = useTemplateRef('sidebarRef')
|
||||
const navSidebarWidth = ref(200) // 左侧导航菜单的实际宽度(px),传给 YoloBrowser/Sidebar 使用
|
||||
|
||||
// 客服名片
|
||||
const serviceContacts = ref([])
|
||||
const loadServiceContacts = async () => {
|
||||
try {
|
||||
const res = await getCustomServiceInfo()
|
||||
console.log("获取名片",res)
|
||||
if (res) {
|
||||
serviceContacts.value = res.map(item => ({
|
||||
avatar: item.avater,
|
||||
name: item.name,
|
||||
desc: item.description,
|
||||
qrcode: item.concat,
|
||||
phone: item.phone
|
||||
}))
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取客服名片失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
// 监听菜单栏实际宽度,通知后端更新 BrowserView 定位
|
||||
let resizeObserver = null
|
||||
const notifySidebarWidth = (width) => {
|
||||
navSidebarWidth.value = Math.round(width)
|
||||
if (isElectron()) {
|
||||
window.electronAPI.setSidebarWidth(Math.round(width)).catch(() => {})
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
loadServiceContacts()
|
||||
if (!isElectron()) return
|
||||
resizeObserver = new ResizeObserver((entries) => {
|
||||
const width = entries[0]?.contentRect.width
|
||||
if (width) notifySidebarWidth(width)
|
||||
})
|
||||
if (sidebarRef.value) {
|
||||
resizeObserver.observe(sidebarRef.value)
|
||||
// 立即上报初始宽度
|
||||
notifySidebarWidth(sidebarRef.value.getBoundingClientRect().width)
|
||||
}
|
||||
})
|
||||
onUnmounted(() => {
|
||||
resizeObserver?.disconnect()
|
||||
})
|
||||
|
||||
const handleGoToBrowser = async () => {
|
||||
autoDmMode.value = 'browser'
|
||||
@@ -263,6 +338,10 @@ watch(autoDmMode, async (newVal) => {
|
||||
<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');
|
||||
|
||||
.yolo-logo{
|
||||
width: 70%;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user