695 lines
13 KiB
Vue
695 lines
13 KiB
Vue
<template>
|
|
<div
|
|
class="flip-card"
|
|
:class="{ 'is-flipped': isFlipped }"
|
|
@mouseenter="handleCardHover"
|
|
@mouseleave="handleCardLeave"
|
|
>
|
|
<div class="flip-card-inner">
|
|
<!-- 卡片背面 (左邊的樣式) -->
|
|
<div class="flip-card-back">
|
|
<div class="back-content">
|
|
<h3 class="back-title">{{ streamer.name }}</h3>
|
|
<p class="greeting">{{ streamer.greeting }}</p>
|
|
<p class="status">{{ streamer.status }}</p>
|
|
<p class="availability">{{ streamer.availability }}</p>
|
|
<p class="personality">{{ streamer.personality }}</p>
|
|
<p class="promise">{{ streamer.promise }}</p>
|
|
|
|
<!-- 主播主頁按鈕 -->
|
|
<button
|
|
class="profile-button"
|
|
@click="handleProfileClick"
|
|
>
|
|
去這個主播主頁
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 卡片正面 - 簡潔設計 -->
|
|
<div class="flip-card-front">
|
|
<div class="photo-container">
|
|
<img
|
|
:src="streamer.photo"
|
|
:alt="streamer.name"
|
|
class="streamer-photo"
|
|
/>
|
|
|
|
<!-- 簡潔的覆蓋層 -->
|
|
<div class="photo-overlay">
|
|
<!-- 右上角徽章組 -->
|
|
<div class="badges-container">
|
|
<StreamerBadge
|
|
v-for="(badgeCode, index) in streamer.badges.slice(0, 3)"
|
|
:key="`${streamer.id}-badge-${index}`"
|
|
:code="badgeCode"
|
|
size="small"
|
|
class="streamer-badge"
|
|
/>
|
|
</div>
|
|
|
|
<!-- 底部資訊條 -->
|
|
<div class="info-bar">
|
|
<div class="streamer-info">
|
|
<h3 class="streamer-name">{{ streamer.name }}</h3>
|
|
<p class="streamer-description">{{ streamer.description }}</p>
|
|
</div>
|
|
|
|
<!-- 性別和生日資訊 -->
|
|
<div class="personal-info">
|
|
<div class="gender-badge" :class="streamer.gender">
|
|
<span class="gender-icon">{{ streamer.gender === 'female' ? '♀' : '♂' }}</span>
|
|
<span class="gender-text">{{ streamer.gender === 'female' ? '女' : '男' }}</span>
|
|
</div>
|
|
<div class="birthday-info">
|
|
<span class="birthday-icon">🎂</span>
|
|
<span class="birthday-text">{{ formatBirthday(streamer.birthday) }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="stats-row">
|
|
<div class="stat-item">
|
|
<span class="stat-number">{{ streamer.fans }}</span>
|
|
<span class="stat-label">粉絲</span>
|
|
</div>
|
|
<div class="stat-item">
|
|
<span class="stat-number">{{ streamer.orders }}</span>
|
|
<span class="stat-label">接單</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref } from 'vue';
|
|
import StreamerBadge from './StreamerBadge.vue';
|
|
|
|
interface Streamer {
|
|
id: number;
|
|
name: string;
|
|
photo: string;
|
|
description: string;
|
|
rank: string;
|
|
fans: number;
|
|
orders: number;
|
|
badges: string[];
|
|
greeting: string;
|
|
status: string;
|
|
availability: string;
|
|
personality: string;
|
|
promise: string;
|
|
gender: 'male' | 'female';
|
|
birthday: string;
|
|
}
|
|
|
|
interface Props {
|
|
streamer: Streamer;
|
|
}
|
|
|
|
const props = defineProps<Props>();
|
|
const emit = defineEmits<{
|
|
click: [streamer: Streamer];
|
|
more: [streamer: Streamer];
|
|
profile: [streamer: Streamer];
|
|
}>();
|
|
|
|
const isFlipped = ref(false);
|
|
|
|
const handleCardHover = () => {
|
|
isFlipped.value = true;
|
|
console.log('Card hovered, showing back');
|
|
};
|
|
|
|
const handleCardLeave = () => {
|
|
isFlipped.value = false;
|
|
console.log('Card left, showing front');
|
|
};
|
|
|
|
const handleMoreClick = (event: Event) => {
|
|
event.stopPropagation();
|
|
emit('more', props.streamer);
|
|
};
|
|
|
|
const handleStreamerClick = (event: Event) => {
|
|
event.stopPropagation();
|
|
emit('click', props.streamer);
|
|
};
|
|
|
|
const handleProfileClick = (event: Event) => {
|
|
event.stopPropagation();
|
|
emit('profile', props.streamer);
|
|
};
|
|
|
|
// 格式化生日顯示
|
|
const formatBirthday = (birthday: string): string => {
|
|
const date = new Date(birthday);
|
|
return `${date.getMonth() + 1}/${date.getDate()}`;
|
|
};
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* 翻轉卡片容器 */
|
|
.flip-card {
|
|
width: 100%;
|
|
height: 320px;
|
|
min-height: 320px;
|
|
max-height: 320px;
|
|
perspective: 1000px;
|
|
cursor: pointer;
|
|
position: relative;
|
|
z-index: 1;
|
|
transition: z-index 0.3s ease;
|
|
}
|
|
|
|
.flip-card:hover {
|
|
z-index: 10;
|
|
}
|
|
|
|
.flip-card.is-flipped {
|
|
z-index: 5;
|
|
}
|
|
|
|
.flip-card-inner {
|
|
position: relative;
|
|
width: 100%;
|
|
height: 100%;
|
|
text-align: center;
|
|
transition: transform 0.6s;
|
|
transform-style: preserve-3d;
|
|
min-height: 320px;
|
|
max-height: 320px;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.flip-card-back,
|
|
.flip-card-front {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
z-index: 1;
|
|
/* 確保正面和背面尺寸完全一致 */
|
|
min-height: 320px;
|
|
max-height: 320px;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
/* 卡片背面樣式 (左邊) */
|
|
.flip-card-back {
|
|
background: linear-gradient(135deg, rgba(255, 107, 157, 0.8) 0%, rgba(255, 167, 38, 0.8) 100%);
|
|
color: white;
|
|
display: none;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
padding: 20px;
|
|
position: relative;
|
|
overflow: hidden;
|
|
/* 移除框框效果 */
|
|
border: none;
|
|
box-shadow: none;
|
|
border-radius: 12px;
|
|
}
|
|
|
|
.flip-card-back::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: -50%;
|
|
right: -50%;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: radial-gradient(circle, rgba(255, 255, 255, 0.05) 0%, transparent 70%);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.back-content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100%;
|
|
justify-content: center;
|
|
align-items: center;
|
|
text-align: center;
|
|
position: relative;
|
|
z-index: 1;
|
|
padding: 50px 25px;
|
|
box-sizing: border-box;
|
|
gap: 10px;
|
|
}
|
|
|
|
.back-title {
|
|
font-size: 20px;
|
|
font-weight: bold;
|
|
margin: 0 0 16px 0;
|
|
color: white;
|
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
.back-content p {
|
|
margin: 0;
|
|
font-size: 13px;
|
|
line-height: 1.4;
|
|
color: white;
|
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
.greeting {
|
|
font-weight: 600;
|
|
color: #fff3e0;
|
|
font-size: 15px;
|
|
}
|
|
|
|
.status {
|
|
color: #ffe0b2;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.availability {
|
|
color: #ffccbc;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.personality {
|
|
color: #f8bbd9;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.promise {
|
|
color: #e1bee7;
|
|
font-size: 12px;
|
|
margin: 0;
|
|
opacity: 0.9;
|
|
}
|
|
|
|
/* 主播主頁按鈕 */
|
|
.profile-button {
|
|
background: rgba(255, 255, 255, 0.2);
|
|
border: 2px solid rgba(255, 255, 255, 0.4);
|
|
color: white;
|
|
padding: 10px 20px;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
margin-top: 20px;
|
|
border-radius: 25px;
|
|
backdrop-filter: blur(8px);
|
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
|
|
min-width: 140px;
|
|
}
|
|
|
|
.profile-button:hover {
|
|
background: rgba(255, 255, 255, 0.3);
|
|
border-color: rgba(255, 255, 255, 0.6);
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
.profile-button:active {
|
|
transform: translateY(0);
|
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
|
|
/* 卡片正面樣式 - 簡潔設計 */
|
|
.flip-card-front {
|
|
background: white;
|
|
display: flex;
|
|
flex-direction: column;
|
|
position: relative;
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.photo-container {
|
|
width: 100%;
|
|
height: 100%;
|
|
position: relative;
|
|
border-radius: 12px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.streamer-photo {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
object-position: center;
|
|
}
|
|
|
|
.photo-overlay {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
padding: 16px;
|
|
background: linear-gradient(
|
|
to bottom,
|
|
rgba(0, 0, 0, 0.1) 0%,
|
|
transparent 30%,
|
|
transparent 70%,
|
|
rgba(0, 0, 0, 0.7) 100%
|
|
);
|
|
}
|
|
|
|
/* 徽章容器 */
|
|
.badges-container {
|
|
position: absolute;
|
|
top: 16px;
|
|
right: 16px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
max-width: 120px;
|
|
align-items: flex-end;
|
|
}
|
|
|
|
.streamer-badge {
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* 底部資訊條 */
|
|
.info-bar {
|
|
background: transparent;
|
|
backdrop-filter: none;
|
|
border-radius: 12px;
|
|
padding: 12px;
|
|
margin-top: auto;
|
|
}
|
|
|
|
.streamer-info {
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.streamer-name {
|
|
font-size: 18px;
|
|
font-weight: 700;
|
|
color: white;
|
|
margin: 0 0 4px 0;
|
|
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.8);
|
|
}
|
|
|
|
.streamer-description {
|
|
font-size: 12px;
|
|
color: white;
|
|
margin: 0;
|
|
line-height: 1.3;
|
|
text-shadow: 0 1px 4px rgba(0, 0, 0, 0.8);
|
|
}
|
|
|
|
/* 個人資訊區域 */
|
|
.personal-info {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 10px;
|
|
gap: 8px;
|
|
}
|
|
|
|
/* 性別徽章 */
|
|
.gender-badge {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
padding: 4px 8px;
|
|
border-radius: 12px;
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
backdrop-filter: blur(4px);
|
|
}
|
|
|
|
.gender-badge.female {
|
|
background: rgba(255, 182, 193, 0.8);
|
|
color: #d63384;
|
|
border: 1px solid rgba(214, 51, 132, 0.3);
|
|
}
|
|
|
|
.gender-badge.male {
|
|
background: rgba(173, 216, 230, 0.8);
|
|
color: #0d6efd;
|
|
border: 1px solid rgba(13, 110, 253, 0.3);
|
|
}
|
|
|
|
.gender-icon {
|
|
font-size: 12px;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.gender-text {
|
|
font-size: 10px;
|
|
}
|
|
|
|
/* 生日資訊 */
|
|
.birthday-info {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
padding: 4px 8px;
|
|
background: rgba(255, 255, 255, 0.15);
|
|
border-radius: 12px;
|
|
font-size: 10px;
|
|
font-weight: 500;
|
|
backdrop-filter: blur(4px);
|
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
}
|
|
|
|
.birthday-icon {
|
|
font-size: 10px;
|
|
}
|
|
|
|
.birthday-text {
|
|
font-size: 10px;
|
|
opacity: 0.9;
|
|
}
|
|
|
|
/* 統計行 */
|
|
.stats-row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
|
|
.stat-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
flex: 1;
|
|
}
|
|
|
|
.stat-number {
|
|
font-size: 16px;
|
|
font-weight: 700;
|
|
color: white;
|
|
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.8);
|
|
line-height: 1;
|
|
}
|
|
|
|
.stat-label {
|
|
font-size: 10px;
|
|
color: white;
|
|
margin-top: 2px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
text-shadow: 0 1px 4px rgba(0, 0, 0, 0.8);
|
|
}
|
|
|
|
/* 翻轉狀態樣式 - 懸停時顯示背面(粉橙漸變) */
|
|
.flip-card.is-flipped .flip-card-back {
|
|
display: flex;
|
|
}
|
|
|
|
.flip-card.is-flipped .flip-card-front {
|
|
display: none;
|
|
}
|
|
|
|
/* 響應式設計 */
|
|
@media (max-width: 768px) {
|
|
.flip-card {
|
|
height: 300px;
|
|
min-height: 300px;
|
|
max-height: 300px;
|
|
}
|
|
|
|
.flip-card-inner {
|
|
min-height: 300px;
|
|
max-height: 300px;
|
|
}
|
|
|
|
.flip-card-back,
|
|
.flip-card-front {
|
|
min-height: 300px;
|
|
max-height: 300px;
|
|
}
|
|
|
|
.back-content {
|
|
padding: 45px 22px;
|
|
gap: 12px;
|
|
}
|
|
|
|
.back-title {
|
|
font-size: 20px;
|
|
margin-bottom: 14px;
|
|
}
|
|
|
|
.back-content p {
|
|
font-size: 13px;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.profile-button {
|
|
padding: 8px 16px;
|
|
font-size: 13px;
|
|
margin-top: 16px;
|
|
min-width: 120px;
|
|
}
|
|
|
|
/* 正面卡片響應式 */
|
|
.streamer-name {
|
|
font-size: 16px;
|
|
}
|
|
|
|
.streamer-description {
|
|
font-size: 12px;
|
|
}
|
|
|
|
.personal-info {
|
|
margin-bottom: 8px;
|
|
gap: 6px;
|
|
}
|
|
|
|
.gender-badge {
|
|
padding: 3px 6px;
|
|
font-size: 10px;
|
|
}
|
|
|
|
.birthday-info {
|
|
padding: 3px 6px;
|
|
font-size: 9px;
|
|
}
|
|
|
|
.stat-number {
|
|
font-size: 14px;
|
|
}
|
|
|
|
.stat-label {
|
|
font-size: 10px;
|
|
}
|
|
|
|
/* 徽章響應式 */
|
|
.badges-container {
|
|
top: 12px;
|
|
right: 12px;
|
|
max-width: 100px;
|
|
gap: 4px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
.flip-card {
|
|
height: 280px;
|
|
min-height: 280px;
|
|
max-height: 280px;
|
|
}
|
|
|
|
.flip-card-inner {
|
|
min-height: 280px;
|
|
max-height: 280px;
|
|
}
|
|
|
|
.flip-card-back,
|
|
.flip-card-front {
|
|
min-height: 280px;
|
|
max-height: 280px;
|
|
}
|
|
|
|
.back-content {
|
|
padding: 35px 18px;
|
|
gap: 10px;
|
|
}
|
|
|
|
.back-title {
|
|
font-size: 18px;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.back-content p {
|
|
font-size: 12px;
|
|
line-height: 1.3;
|
|
}
|
|
|
|
.profile-button {
|
|
padding: 6px 12px;
|
|
font-size: 12px;
|
|
margin-top: 14px;
|
|
min-width: 100px;
|
|
}
|
|
|
|
/* 正面卡片響應式 */
|
|
.streamer-name {
|
|
font-size: 15px;
|
|
}
|
|
|
|
.streamer-description {
|
|
font-size: 11px;
|
|
}
|
|
|
|
.personal-info {
|
|
margin-bottom: 6px;
|
|
gap: 4px;
|
|
}
|
|
|
|
.gender-badge {
|
|
padding: 2px 5px;
|
|
font-size: 9px;
|
|
}
|
|
|
|
.birthday-info {
|
|
padding: 2px 5px;
|
|
font-size: 8px;
|
|
}
|
|
|
|
.stat-number {
|
|
font-size: 13px;
|
|
}
|
|
|
|
.stat-label {
|
|
font-size: 9px;
|
|
}
|
|
|
|
/* 徽章響應式 */
|
|
.badges-container {
|
|
top: 10px;
|
|
right: 10px;
|
|
max-width: 90px;
|
|
gap: 3px;
|
|
}
|
|
}
|
|
|
|
/* 深色主題適配 */
|
|
.theme-dark .flip-card-front {
|
|
background: var(--window-background);
|
|
color: var(--content-text-color);
|
|
}
|
|
|
|
.theme-dark .streamer-name {
|
|
color: var(--content-text-color);
|
|
}
|
|
|
|
.theme-dark .streamer-description {
|
|
color: var(--content-text-color);
|
|
opacity: 0.8;
|
|
}
|
|
</style>
|