iptv-app/ui/src/components/Layout/BottomPanel.vue
2026-02-24 22:57:47 +08:00

212 lines
4.1 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>
<Transition name="slide-up">
<div
v-show="bottomPanelVisible"
class="bottom-panel"
@mouseenter="showBottomPanel"
@mousemove="showBottomPanel"
>
<!-- 左侧频道信息 -->
<div class="panel-left">
<div class="channel-logo">
{{ getChannelLogo(channel?.name) }}
</div>
<div class="channel-info">
<div class="channel-name-row">
<span class="name">{{ channel?.name || "未选择频道" }}</span>
<span class="source-tag"
>线路 {{ currentSourceIndex + 1 }}/{{
channel?.urls?.length || 0
}}</span
>
</div>
<div class="program-info">
<span class="live-dot"></span>
<span class="program-title">{{
currentProgram || "精彩节目"
}}</span>
</div>
<div class="progress-bar">
<div class="progress-fill" :style="{ width: progress + '%' }"></div>
<span class="time-label">{{ currentTime }} / {{ totalTime }}</span>
</div>
</div>
</div>
<!-- 右侧操作按钮 -->
<div class="panel-right">
<button
class="action-btn"
:class="{ active: isFavorite }"
@click="handleFavorite"
@mouseenter="showBottomPanel"
>
<span class="icon"></span>
<span>{{ isFavorite ? "已收藏" : "收藏" }}</span>
</button>
<button
class="action-btn"
@click="handleSwitchSource"
@mouseenter="showBottomPanel"
>
<span class="icon"></span>
<span>切换线路</span>
</button>
</div>
</div>
</Transition>
</template>
<script setup>
import { useKeyEvent } from "../../composables/useEvent.js";
useKeyEvent("Escape", showBottomPanel);
</script>
<style scoped>
.bottom-panel {
position: fixed;
left: 0;
right: 0;
bottom: 0;
height: 80px;
background: rgba(0, 0, 0, 0.85);
backdrop-filter: blur(10px);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
z-index: 50;
}
/* 左侧信息 */
.panel-left {
display: flex;
align-items: center;
gap: 12px;
flex: 1;
min-width: 0;
}
.channel-logo {
width: 48px;
height: 48px;
background: rgba(255, 255, 255, 0.1);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: bold;
color: rgba(255, 255, 255, 0.8);
flex-shrink: 0;
}
.channel-info {
flex: 1;
min-width: 0;
}
.channel-name-row {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 4px;
}
.channel-name-row .name {
font-size: 16px;
font-weight: 500;
color: #fff;
}
.source-tag {
font-size: 11px;
color: rgba(255, 255, 255, 0.6);
background: rgba(255, 255, 255, 0.1);
padding: 2px 8px;
border-radius: 4px;
}
.program-info {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
color: rgba(255, 255, 255, 0.7);
margin-bottom: 6px;
}
.live-dot {
color: #ff4444;
font-size: 10px;
}
.progress-bar {
height: 3px;
background: rgba(255, 255, 255, 0.1);
border-radius: 2px;
position: relative;
}
.progress-fill {
height: 100%;
background: #fff;
border-radius: 2px;
transition: width 0.3s;
}
.time-label {
position: absolute;
right: 0;
top: -16px;
font-size: 11px;
color: rgba(255, 255, 255, 0.5);
}
/* 右侧按钮 */
.panel-right {
display: flex;
gap: 8px;
}
.action-btn {
display: flex;
align-items: center;
gap: 6px;
padding: 8px 16px;
background: transparent;
border: none;
color: rgba(255, 255, 255, 0.7);
font-size: 13px;
cursor: pointer;
border-radius: 6px;
transition: all 0.2s;
}
.action-btn:hover {
background: rgba(255, 255, 255, 0.1);
color: #fff;
}
.action-btn.active {
color: #ffd700;
}
.action-btn .icon {
font-size: 14px;
}
/* 滑入动画 */
.slide-up-enter-active,
.slide-up-leave-active {
transition: transform 0.3s ease;
}
.slide-up-enter-from,
.slide-up-leave-to {
transform: translateY(100%);
}
</style>