mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-14 06:30:49 +08:00
✨ feat: 修改 捐赠支持 添加留言显示 可隐藏列表
This commit is contained in:
@@ -1,8 +1,16 @@
|
||||
<template>
|
||||
<div class="donation-container">
|
||||
<div class="donation-grid">
|
||||
<div class="refresh-container">
|
||||
<n-button secondary round size="small" :loading="isLoading" @click="fetchDonors">
|
||||
<template #icon>
|
||||
<i class="ri-refresh-line"></i>
|
||||
</template>
|
||||
刷新列表
|
||||
</n-button>
|
||||
</div>
|
||||
<div class="donation-grid" :class="{ 'grid-expanded': isExpanded }">
|
||||
<div
|
||||
v-for="(donor, index) in sortedDonors"
|
||||
v-for="(donor, index) in displayDonors"
|
||||
:key="donor.id"
|
||||
class="donation-card animate__animated"
|
||||
:class="getAnimationClass(index)"
|
||||
@@ -38,9 +46,20 @@
|
||||
<span class="donation-date">{{ donor.date }}</span>
|
||||
</div>
|
||||
<div v-if="donor.message" class="donation-message">
|
||||
<i class="ri-double-quotes-l quote-icon"></i>
|
||||
{{ donor.message }}
|
||||
<i class="ri-double-quotes-r quote-icon"></i>
|
||||
<n-popover trigger="hover" placement="bottom">
|
||||
<template #trigger>
|
||||
<div class="message-content">
|
||||
<i class="ri-double-quotes-l quote-icon"></i>
|
||||
<div class="message-text">{{ donor.message }}</div>
|
||||
<i class="ri-double-quotes-r quote-icon"></i>
|
||||
</div>
|
||||
</template>
|
||||
<div class="message-popup">
|
||||
<i class="ri-double-quotes-l quote-icon"></i>
|
||||
{{ donor.message }}
|
||||
<i class="ri-double-quotes-r quote-icon"></i>
|
||||
</div>
|
||||
</n-popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -48,6 +67,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="sortedDonors.length > 8" class="expand-button">
|
||||
<n-button text @click="toggleExpand">
|
||||
<template #icon>
|
||||
<i :class="isExpanded ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line'"></i>
|
||||
</template>
|
||||
{{ isExpanded ? '收起' : '展开更多' }}
|
||||
</n-button>
|
||||
</div>
|
||||
|
||||
<div class="p-6 rounded-lg shadow-lg bg-light dark:bg-gray-800">
|
||||
<div class="flex justify-between">
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
@@ -77,7 +105,7 @@
|
||||
import 'animate.css';
|
||||
|
||||
import axios from 'axios';
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, onActivated, onMounted, ref } from 'vue';
|
||||
|
||||
import alipay from '@/assets/alipay.png';
|
||||
import wechat from '@/assets/wechat.png';
|
||||
@@ -97,69 +125,34 @@ interface Donor {
|
||||
badgeColor: string;
|
||||
}
|
||||
|
||||
const donors = ref<Donor[]>([
|
||||
{
|
||||
id: 6,
|
||||
name: '*桤',
|
||||
amount: 5,
|
||||
date: '2025-01-01',
|
||||
badge: '开源赞助',
|
||||
badgeColor: '#FF69B4'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '*木',
|
||||
amount: 1,
|
||||
date: '2024-12-26',
|
||||
badge: '开源赞助',
|
||||
badgeColor: '#FF69B4'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '**兴',
|
||||
amount: 5,
|
||||
date: '2024-12-25',
|
||||
badge: '开源赞助',
|
||||
badgeColor: '#FF69B4'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 's*r',
|
||||
amount: 1.68,
|
||||
date: '2024-12-25',
|
||||
badge: '开源赞助',
|
||||
badgeColor: '#FF69B4'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'G*Y',
|
||||
amount: 1.99,
|
||||
date: '2024-12-18',
|
||||
badge: '开源赞助',
|
||||
badgeColor: '#FF69B4'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: '*辉',
|
||||
amount: 1,
|
||||
date: '2024-12-15',
|
||||
badge: '开源赞助',
|
||||
badgeColor: '#FF69B4'
|
||||
}
|
||||
]);
|
||||
const donors = ref<Donor[]>([]);
|
||||
|
||||
onMounted(async () => {
|
||||
const isLoading = ref(false);
|
||||
|
||||
const fetchDonors = async () => {
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const response = await axios.get(
|
||||
'https://www.ghproxy.cn/https://raw.githubusercontent.com/algerkong/data/main/donors.json'
|
||||
);
|
||||
donors.value = response.data.map((donor: Donor, index: number) => ({
|
||||
...donor,
|
||||
avatar: `https://api.dicebear.com/7.x/micah/svg?seed=${index}`
|
||||
avatar: `https://api.dicebear.com/7.x/micah/svg?seed=${index}`,
|
||||
message: donor.message || '没有留言'
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch donors:', error);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
fetchDonors();
|
||||
});
|
||||
|
||||
onActivated(() => {
|
||||
fetchDonors();
|
||||
});
|
||||
|
||||
// 动画类名列表
|
||||
@@ -192,8 +185,8 @@ const getBadgeClass = (badge: string): string => {
|
||||
// 鼠标悬停效果
|
||||
const handleMouseEnter = (event: MouseEvent) => {
|
||||
const card = event.currentTarget as HTMLElement;
|
||||
card.style.transform = 'translateY(-5px) scale(1.02)';
|
||||
card.style.boxShadow = '0 8px 30px rgba(0, 0, 0, 0.12)';
|
||||
card.style.transform = 'translateY(-2px)';
|
||||
card.style.boxShadow = '0 8px 20px rgba(0, 0, 0, 0.12)';
|
||||
|
||||
// 添加金额标签动画
|
||||
const amountTag = card.querySelector('.donation-amount');
|
||||
@@ -204,8 +197,8 @@ const handleMouseEnter = (event: MouseEvent) => {
|
||||
|
||||
const handleMouseLeave = (event: MouseEvent) => {
|
||||
const card = event.currentTarget as HTMLElement;
|
||||
card.style.transform = 'translateY(0) scale(1)';
|
||||
card.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)';
|
||||
card.style.transform = 'translateY(0)';
|
||||
card.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.08)';
|
||||
|
||||
// 移除金额标签动画
|
||||
const amountTag = card.querySelector('.donation-amount');
|
||||
@@ -225,6 +218,19 @@ const sortedDonors = computed(() => {
|
||||
return new Date(b.date).getTime() - new Date(a.date).getTime();
|
||||
});
|
||||
});
|
||||
|
||||
const isExpanded = ref(false);
|
||||
|
||||
const displayDonors = computed(() => {
|
||||
if (isExpanded.value) {
|
||||
return sortedDonors.value;
|
||||
}
|
||||
return sortedDonors.value.slice(0, 8);
|
||||
});
|
||||
|
||||
const toggleExpand = () => {
|
||||
isExpanded.value = !isExpanded.value;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -233,122 +239,145 @@ const sortedDonors = computed(() => {
|
||||
}
|
||||
|
||||
.donation-grid {
|
||||
@apply grid gap-3 px-2 py-3;
|
||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||
@apply grid gap-3 px-2 py-3 transition-all duration-300 overflow-hidden;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
max-height: 280px;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
|
||||
&.grid-expanded {
|
||||
@apply max-h-none;
|
||||
}
|
||||
}
|
||||
|
||||
.donation-card {
|
||||
@apply relative overflow-hidden rounded-lg p-3;
|
||||
background: linear-gradient(145deg, rgba(255, 255, 255, 0.03), rgba(255, 255, 255, 0.08));
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
animation-duration: 0.8s;
|
||||
@apply relative rounded-lg p-3 min-w-0 w-full transition-all duration-500 shadow-md backdrop-blur-md;
|
||||
@apply bg-gradient-to-br from-white/[0.03] to-white/[0.08] border border-white/[0.08];
|
||||
@apply hover:shadow-lg;
|
||||
|
||||
.card-content {
|
||||
@apply relative z-10 flex items-start gap-3;
|
||||
}
|
||||
|
||||
.donor-avatar {
|
||||
@apply relative flex-shrink-0 w-10 h-9 transition-transform duration-300;
|
||||
|
||||
.avatar-img {
|
||||
@apply border border-white/20 dark:border-gray-800/50 shadow-sm;
|
||||
@apply w-10 h-9;
|
||||
}
|
||||
}
|
||||
|
||||
.donor-badge {
|
||||
@apply absolute -bottom-2 -right-1 px-1.5 py-0.5 text-xs font-medium text-white/90 rounded-full whitespace-nowrap;
|
||||
@apply bg-gradient-to-r from-pink-400 to-pink-500 shadow-sm opacity-90 scale-90;
|
||||
@apply transition-all duration-300;
|
||||
}
|
||||
|
||||
.donor-info {
|
||||
@apply flex-1 min-w-0;
|
||||
|
||||
.donor-name {
|
||||
@apply text-sm font-medium mb-0.5 truncate;
|
||||
}
|
||||
|
||||
.donation-meta {
|
||||
@apply flex items-center gap-2 mb-1;
|
||||
|
||||
.donation-date {
|
||||
@apply text-xs text-gray-400/80 dark:text-gray-500/80;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.donation-message {
|
||||
@apply text-sm text-gray-600 dark:text-gray-300 leading-relaxed mt-2;
|
||||
|
||||
.message-content {
|
||||
@apply relative p-2 rounded-lg transition-all duration-300 cursor-pointer;
|
||||
@apply bg-white/[0.02] hover:bg-[var(--n-color)];
|
||||
|
||||
.message-text {
|
||||
@apply px-6 italic line-clamp-2;
|
||||
}
|
||||
|
||||
.quote-icon {
|
||||
@apply absolute text-gray-400/60 dark:text-gray-500/60 text-sm;
|
||||
|
||||
&:first-child {
|
||||
@apply left-0.5 top-2;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
@apply right-0.5 bottom-2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.card-sparkles {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.donor-avatar {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-content {
|
||||
@apply relative z-10 flex items-start gap-3;
|
||||
}
|
||||
|
||||
.donor-avatar {
|
||||
@apply relative flex-shrink-0;
|
||||
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
|
||||
.avatar-img {
|
||||
@apply border border-white/20 dark:border-gray-800/50;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
|
||||
width: 40px !important;
|
||||
height: 36px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.donor-badge {
|
||||
@apply absolute -bottom-0.5 -right-0.5 px-1 py-0.5 text-xs font-medium text-white/90 rounded-full;
|
||||
font-size: 0.5rem;
|
||||
transform: scale(0.8);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
|
||||
line-height: 1;
|
||||
background: linear-gradient(45deg, #ff69b4, #ff1493);
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.donor-info {
|
||||
@apply flex-1 min-w-0;
|
||||
}
|
||||
|
||||
.donor-name {
|
||||
@apply text-sm font-medium mb-0.5 truncate;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.donation-meta {
|
||||
@apply flex items-center gap-2 mb-1;
|
||||
}
|
||||
|
||||
.donation-amount {
|
||||
@apply text-xs font-medium;
|
||||
}
|
||||
|
||||
.donation-date {
|
||||
@apply text-xs text-gray-400/80 dark:text-gray-500/80;
|
||||
}
|
||||
|
||||
.donation-message {
|
||||
@apply text-sm text-gray-600 dark:text-gray-300 leading-relaxed;
|
||||
@apply relative pl-4 pr-4;
|
||||
font-style: italic;
|
||||
|
||||
.quote-icon {
|
||||
@apply text-gray-400 dark:text-gray-500 absolute;
|
||||
font-size: 0.8rem;
|
||||
|
||||
&:first-child {
|
||||
left: 0;
|
||||
top: 0;
|
||||
@apply scale-105 rotate-3;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
.donor-badge {
|
||||
@apply scale-95 -translate-y-0.5;
|
||||
}
|
||||
|
||||
.card-sparkles {
|
||||
@apply opacity-60 scale-110;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-sparkles {
|
||||
@apply absolute inset-0 pointer-events-none opacity-0;
|
||||
background-image: radial-gradient(
|
||||
1.5px 1.5px at 20px 30px,
|
||||
rgba(255, 255, 255, 0.95),
|
||||
rgba(0, 0, 0, 0)
|
||||
),
|
||||
radial-gradient(1.5px 1.5px at 40px 70px, rgba(255, 255, 255, 0.95), rgba(0, 0, 0, 0)),
|
||||
radial-gradient(2px 2px at 50px 160px, rgba(255, 255, 255, 0.95), rgba(0, 0, 0, 0)),
|
||||
radial-gradient(1.5px 1.5px at 90px 40px, rgba(255, 255, 255, 0.95), rgba(0, 0, 0, 0)),
|
||||
radial-gradient(2px 2px at 130px 80px, rgba(255, 255, 255, 0.95), rgba(0, 0, 0, 0));
|
||||
@apply absolute inset-0 pointer-events-none opacity-0 transition-all duration-500;
|
||||
background-image: radial-gradient(2px 2px at 20px 30px, rgba(255, 255, 255, 0.95), transparent),
|
||||
radial-gradient(2px 2px at 40px 70px, rgba(255, 255, 255, 0.95), transparent),
|
||||
radial-gradient(2.5px 2.5px at 50px 160px, rgba(255, 255, 255, 0.95), transparent),
|
||||
radial-gradient(2px 2px at 90px 40px, rgba(255, 255, 255, 0.95), transparent),
|
||||
radial-gradient(2.5px 2.5px at 130px 80px, rgba(255, 255, 255, 0.95), transparent);
|
||||
background-size: 200% 200%;
|
||||
animation: sparkle 5s ease infinite;
|
||||
transition: opacity 0.5s ease;
|
||||
animation: sparkle 8s ease infinite;
|
||||
}
|
||||
|
||||
@keyframes sparkle {
|
||||
0%,
|
||||
100% {
|
||||
background-position: 0% 0%;
|
||||
opacity: 0.4;
|
||||
@apply bg-[0%_0%] opacity-40 scale-100;
|
||||
}
|
||||
50% {
|
||||
background-position: 100% 100%;
|
||||
opacity: 0.8;
|
||||
@apply bg-[100%_100%] opacity-80 scale-110;
|
||||
}
|
||||
}
|
||||
|
||||
.refresh-container {
|
||||
@apply flex justify-end px-2 py-2;
|
||||
}
|
||||
|
||||
.expand-button {
|
||||
@apply flex justify-center items-center py-2;
|
||||
|
||||
:deep(.n-button) {
|
||||
@apply transition-all duration-300 hover:-translate-y-0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.message-popup {
|
||||
@apply relative px-4 py-2 text-sm;
|
||||
max-width: 300px;
|
||||
line-height: 1.6;
|
||||
font-style: italic;
|
||||
|
||||
.quote-icon {
|
||||
@apply text-gray-400/60 dark:text-gray-500/60;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -196,11 +196,19 @@
|
||||
<div
|
||||
class="p-4 bg-light dark:bg-dark rounded-lg mb-4 border border-gray-200 dark:border-gray-700 rounded-lg"
|
||||
>
|
||||
<div>
|
||||
<div class="set-item-title">捐赠支持</div>
|
||||
<div class="set-item-content">感谢您的支持,让我有动力能够持续改进</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
<div class="set-item-title">捐赠支持</div>
|
||||
<div class="set-item-content">感谢您的支持,让我有动力能够持续改进</div>
|
||||
</div>
|
||||
<n-button text @click="toggleDonationList">
|
||||
<template #icon>
|
||||
<i :class="isDonationListVisible ? 'ri-eye-line' : 'ri-eye-off-line'" />
|
||||
</template>
|
||||
{{ isDonationListVisible ? '隐藏列表' : '显示列表' }}
|
||||
</n-button>
|
||||
</div>
|
||||
<donation-list />
|
||||
<donation-list v-if="isDonationListVisible" />
|
||||
</div>
|
||||
</div>
|
||||
<play-bottom />
|
||||
@@ -476,6 +484,13 @@ watch(
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const isDonationListVisible = ref(localStorage.getItem('donationListVisible') !== 'false');
|
||||
|
||||
const toggleDonationList = () => {
|
||||
isDonationListVisible.value = !isDonationListVisible.value;
|
||||
localStorage.setItem('donationListVisible', isDonationListVisible.value.toString());
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
Reference in New Issue
Block a user