11<script lang="ts" setup>
2- import { onMounted , computed } from ' vue'
2+ import { onMounted , onUnmounted , computed } from ' vue'
33import Menu from ' ./components/Menu.vue'
4+ import GlobalAudioPlayer from ' ./components/GlobalAudioPlayer.vue'
45import { ElConfigProvider } from ' element-plus'
56import ' element-plus/es/components/message/style/css'
67import zhCn from ' element-plus/dist/locale/zh-cn.mjs'
78import { themeStore } from ' ./stores/theme'
9+ import { playerStore } from ' ./stores/player'
10+ import { AudioDetailAlias } from ' ../wailsjs/go/backend/App'
811
912// 初始化主题
1013const store = themeStore ()
1114onMounted (() => {
1215 store .initTheme ()
1316})
1417
18+ const pStore = playerStore ()
19+ const odobCache = new Map <string , { src: string ; poster? : string }>()
20+ const odobPending = new Map <string , Promise <{ src: string ; poster? : string }>>()
21+
22+ const globalPlayerHeight = computed (() => {
23+ if (! pStore .hasTrack ) return 0
24+ const h = Number (pStore .barHeight ) || 0
25+ if (h > 0 ) return h
26+ return pStore .collapsed ? 76 : 120
27+ })
28+
29+ const mainStyle = computed (() => {
30+ return { ' --global-player-height' : ` ${globalPlayerHeight .value }px ` } as any
31+ })
32+
33+ const resolveOdobSrc = async (aliasId : string ) => {
34+ const key = String (aliasId || ' ' ).trim ()
35+ if (! key ) return { src: ' ' }
36+ const cached = odobCache .get (key )
37+ if (cached ) return cached
38+ const pending = odobPending .get (key )
39+ if (pending ) return pending
40+ const p = AudioDetailAlias (key )
41+ .then ((detail ) => {
42+ const src = String (detail ?.mp3_play_url ?? ' ' ).trim ()
43+ const poster = String (detail ?.icon ?? ' ' ).trim () || undefined
44+ const val = { src , poster }
45+ if (src ) odobCache .set (key , val )
46+ return val
47+ })
48+ .finally (() => {
49+ odobPending .delete (key )
50+ })
51+ odobPending .set (key , p )
52+ return p
53+ }
54+
55+ const onResolveTrack = async (ev : any ) => {
56+ const detail = ev ?.detail || {}
57+ const contextKey = String (detail ?.contextKey ?? ' ' )
58+ if (contextKey !== ' odob:study' ) return
59+ const trackId = String (detail ?.trackId ?? ' ' )
60+ if (! trackId ) return
61+ const aliasId = trackId .startsWith (' odob:' ) ? trackId .slice (5 ) : trackId
62+ if (! aliasId ) return
63+ try {
64+ const { src, poster } = await resolveOdobSrc (aliasId )
65+ if (! src ) return
66+ pStore .updateTrackSource (trackId , src , poster )
67+ } catch {
68+ }
69+ }
70+
71+ onMounted (() => {
72+ window .addEventListener (' player:resolveTrack' , onResolveTrack as any )
73+ })
74+
75+ onUnmounted (() => {
76+ window .removeEventListener (' player:resolveTrack' , onResolveTrack as any )
77+ })
78+
1579// Element Plus 主题配置
1680const elementTheme = computed (() => store .isDark ? ' dark' : ' light' )
1781 </script >
@@ -22,9 +86,10 @@ const elementTheme = computed(() => store.isDark ? 'dark' : 'light')
2286 <el-header >
2387 <Menu />
2488 </el-header >
25- <el-main >
89+ <el-main :style = " mainStyle " >
2690 <router-view ></router-view >
2791 </el-main >
92+ <GlobalAudioPlayer />
2893 <!-- <el-footer>Footer</el-footer> -->
2994 </el-container >
3095 </el-config-provider >
@@ -110,6 +175,7 @@ body {
110175 color : var (--text-color-secondary );
111176 width : 100% ;
112177 height : 100% ;
178+ padding-bottom : calc (var (--global-player-height , 0px ) + 10px );
113179 background-color : var (--bg-color );
114180 transition : background-color 0.3s ease , color 0.3s ease ;
115181
@@ -131,4 +197,4 @@ body {
131197
132198
133199}
134- </style >
200+ </style >
0 commit comments