Files
BYW-VoiceHub/app/components/Admin/ScheduleItemPrint.vue
T
Henry_Du 9fc5e3e607
构建并部署 BYW VoiceHub / 构建并推送容器镜像 (push) Canceled after 0s
构建并部署 BYW VoiceHub / 部署到生产服务器 (push) Canceled after 0s
构建并部署 BYW VoiceHub / Preflight 语法与构建检查 (push) Canceled after 1m27s
fix(ui): 批量替换所有组件中残留的硬编码深色值以彻底支持浅色主题
2026-09-12 15:56:10 +08:00

329 lines
6.9 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>
<div class="schedule-item-print">
<div class="item-content">
<!-- 序号 -->
<div v-if="settings.showSequence" class="sequence-number">
{{ schedule.sequence || 1 }}
</div>
<!-- 歌曲封面 -->
<div v-if="settings.showCover" class="cover-section aspect-square">
<img
v-if="schedule.song.cover"
:alt="schedule.song.title"
:src="convertToHttps(schedule.song.cover)"
class="song-cover object-cover"
referrerpolicy="no-referrer"
@error="handleImageError"
>
<div class="cover-placeholder object-contain" :class="{ 'show': !schedule.song.cover }">
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="3" />
<path d="M12 1v6m0 6v6" />
<path d="m21 12-6-3-6 3-6-3" />
</svg>
</div>
</div>
<!-- 歌曲信息 -->
<div class="song-info">
<div v-if="settings.showTitle" class="song-title">
{{ schedule.song.title }}
<!-- 重播标识 -->
<span v-if="schedule.song.replayRequestCount > 0" class="replay-badge-print"> 重播 </span>
</div>
<div v-if="settings.showArtist" class="song-artist">
{{ schedule.song.artist }}
</div>
</div>
<!-- 投稿人信息(重播歌曲不显示申请人,只显示原投稿人) -->
<div v-if="settings.showRequester" class="requester-info">
<span class="label">投稿人:</span>
<span class="value">
{{ schedule.song.requester }}
<span v-if="schedule.song.collaborators && schedule.song.collaborators.length > 0">
& {{ schedule.song.collaborators.map((c) => c.displayName || c.name).join(' & ') }}
</span>
</span>
</div>
<!-- 人数信息 -->
<div v-if="settings.showVotes" class="votes-info">
<span v-if="schedule.song.replayRequestCount > 0" class="label">申请重播:</span>
<span v-else class="label">热度:</span>
<span class="value">{{
schedule.song.replayRequestCount > 0
? schedule.song.replayRequestCount + '人'
: schedule.song.voteCount || 0
}}</span>
</div>
</div>
</div>
</template>
<script setup>
import { defineProps } from 'vue'
import { convertToHttps } from '~/utils/url'
// 定义props
defineProps({
schedule: {
type: Object,
required: true
},
settings: {
type: Object,
required: true
}
})
// 处理图片加载错误
const handleImageError = (event) => {
event.target.style.display = 'none'
event.target.nextElementSibling?.classList.add('show')
}
</script>
<style scoped>
.schedule-item-print {
display: flex;
align-items: center;
padding: 8px 0;
border-bottom: 1px solid #e5e5e5;
page-break-inside: avoid;
}
.item-content {
display: flex;
align-items: center;
width: 100%;
gap: 12px;
}
.sequence-number {
width: 30px;
height: 30px;
background: #f0f0f0;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 14px;
color: var(--text-quaternary, #333333);
flex-shrink: 0;
}
.cover-section {
width: 40px;
height: 40px;
aspect-ratio: 1 / 1;
flex-shrink: 0;
}
.song-cover {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.cover-placeholder {
width: 100%;
height: 100%;
aspect-ratio: 1 / 1;
object-fit: contain;
background: #f5f5f5;
border-radius: 4px;
display: none;
align-items: center;
justify-content: center;
color: var(--text-tertiary, #999999);
}
.cover-placeholder.show {
display: flex;
}
.cover-placeholder svg {
width: 20px;
height: 20px;
}
.song-info {
flex: 1;
min-width: 0;
}
.song-title {
font-weight: bold;
font-size: 16px;
color: var(--text-quaternary, #333333);
margin-bottom: 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: flex;
align-items: center;
gap: 4px;
}
/* 打印用重播标识 */
.replay-badge-print {
display: inline-block;
padding: 1px 4px;
background: #e3f2fd;
border: 1px solid var(--border-secondary, #2196f3);
border-radius: 3px;
color: #1976d2;
font-size: 10px;
font-weight: bold;
flex-shrink: 0;
}
.song-artist {
font-size: 14px;
color: var(--text-quaternary, #666666);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.requester-info,
.votes-info {
display: flex;
align-items: center;
font-size: 12px;
color: var(--text-quaternary, #666666);
white-space: nowrap;
}
.label {
font-weight: 500;
margin-right: 4px;
}
.value {
color: var(--text-quaternary, #333333);
}
/* 打印样式 */
@media print {
.schedule-item-print {
color: var(--text-primary, #000) !important;
background: var(--card-bg, #fff) !important;
width: 100% !important;
max-width: none !important;
box-sizing: border-box !important;
}
.item-content {
display: flex !important;
flex-direction: row !important;
align-items: center !important;
width: 100% !important;
gap: 12px !important;
}
.sequence-number {
background: #f0f0f0 !important;
color: var(--text-primary, #000) !important;
width: 30px !important;
height: 30px !important;
flex-shrink: 0 !important;
}
.cover-section {
width: 48px !important;
height: 48px !important;
aspect-ratio: 1 / 1 !important;
flex-shrink: 0 !important;
}
.song-cover {
width: 100% !important;
height: 100% !important;
object-fit: contain !important;
border-radius: 0 !important;
box-shadow: none !important;
}
.cover-placeholder {
width: 100% !important;
height: 100% !important;
object-fit: contain !important;
border-radius: 0 !important;
}
.song-info {
flex: 1 !important;
min-width: 0 !important;
}
.song-title {
color: var(--text-primary, #000) !important;
font-size: 16px !important;
white-space: nowrap !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
}
.song-artist,
.label,
.value {
color: var(--text-quaternary, #333333) !important;
}
.time-range {
color: var(--text-quaternary, #666666) !important;
}
.requester-info,
.votes-info,
.playtime-info {
display: flex !important;
align-items: center !important;
font-size: 12px !important;
white-space: nowrap !important;
flex-shrink: 0 !important;
}
}
/* 紧凑模式 */
.compact .schedule-item-print {
padding: 4px 0;
}
.compact .item-content {
gap: 8px;
}
.compact .sequence-number {
width: 24px;
height: 24px;
font-size: 12px;
}
.compact .cover-section {
width: 32px;
height: 32px;
}
.compact .song-title {
font-size: 14px;
}
.compact .song-artist {
font-size: 12px;
}
.compact .requester-info,
.compact .votes-info,
.compact .playtime-info {
font-size: 11px;
}
</style>