feat: 添加mv分类

This commit is contained in:
alger
2024-12-25 19:55:24 +08:00
parent d28adb61a4
commit b2c13121fd
6 changed files with 131 additions and 41 deletions

View File

@@ -2,7 +2,9 @@
<div class="app-container" :class="{ mobile: isMobile, noElectron: !isElectron }">
<n-config-provider :theme="darkTheme">
<n-dialog-provider>
<router-view></router-view>
<n-message-provider>
<router-view></router-view>
</n-message-provider>
</n-dialog-provider>
</n-config-provider>
</div>

View File

@@ -2,15 +2,27 @@ import { IData } from '@/type';
import { IMvItem, IMvUrlData } from '@/type/mv';
import request from '@/utils/request';
interface MvParams {
limit?: number;
offset?: number;
area?: string;
}
// 获取 mv 排行
export const getTopMv = (limit = 30, offset = 0) => {
export const getTopMv = (params: MvParams) => {
return request({
url: '/mv/all',
method: 'get',
params: {
limit,
offset,
},
params,
});
};
// 获取所有mv
export const getAllMv = (params: MvParams) => {
return request({
url: '/mv/all',
method: 'get',
params,
});
};

View File

@@ -23,6 +23,12 @@
<span class="text-sm text-gray-100">微信支付</span>
</div>
</div>
<div class="mt-4">
<p class="text-sm text-gray-100 text-center cursor-pointer hover:text-green-500" @click="copyQQ">
QQ群789288579
</p>
</div>
</div>
</n-popover>
</div>
@@ -31,6 +37,12 @@
<script setup>
import { NButton, NImage, NPopover } from 'naive-ui';
const message = useMessage();
const copyQQ = () => {
navigator.clipboard.writeText('789288579');
message.success('已复制到剪贴板');
};
defineProps({
alipayQR: {
type: String,

View File

@@ -10,17 +10,15 @@
<search-bar />
<!-- 主页面路由 -->
<div class="main-content" :native-scrollbar="false">
<n-message-provider>
<router-view
v-slot="{ Component }"
class="main-page"
:class="route.meta.noScroll && !isMobile ? 'pr-3' : ''"
>
<keep-alive :include="keepAliveInclude">
<component :is="Component" />
</keep-alive>
</router-view>
</n-message-provider>
<router-view
v-slot="{ Component }"
class="main-page"
:class="route.meta.noScroll && !isMobile ? 'pr-3' : ''"
>
<keep-alive :include="keepAliveInclude">
<component :is="Component" />
</keep-alive>
</router-view>
</div>
<play-bottom height="5rem" />
<app-menu v-if="isMobile" class="menu" :menus="menus" />

View File

@@ -3,6 +3,22 @@
<div class="mv-list-title">
<h2>推荐MV</h2>
</div>
<div class="play-list-type">
<n-scrollbar x-scrollable>
<div class="categories-wrapper">
<span
v-for="(category, index) in categories"
:key="category.value"
class="play-list-type-item"
:class="[setAnimationClass('animate__bounceIn'), { active: selectedCategory === category.value }]"
:style="getAnimationDelay(index)"
@click="selectedCategory = category.value"
>
{{ category.label }}
</span>
</div>
</n-scrollbar>
</div>
<n-scrollbar :size="100" @scroll="handleScroll">
<div v-loading="initLoading" class="mv-list-content" :class="setAnimationClass('animate__bounceInLeft')">
<div
@@ -10,7 +26,7 @@
:key="item.id"
class="mv-item"
:class="setAnimationClass('animate__bounceIn')"
:style="getItemAnimationDelay(index)"
:style="getAnimationDelay(index)"
>
<div class="mv-item-img" @click="handleShowMv(item, index)">
<n-image class="mv-item-img-img" :src="getImgUrl(item.cover, '320y180')" lazy preview-disabled />
@@ -38,10 +54,10 @@
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { computed, onMounted, ref, watch } from 'vue';
import { useStore } from 'vuex';
import { getTopMv } from '@/api/mv';
import { getAllMv, getTopMv } from '@/api/mv';
import MvPlayer from '@/components/MvPlayer.vue';
import { audioService } from '@/services/audioService';
import { IMvItem } from '@/type/mv';
@@ -62,10 +78,26 @@ const offset = ref(0);
const limit = ref(42);
const hasMore = ref(true);
const getItemAnimationDelay = (index: number) => {
const currentPageIndex = index % limit.value;
return setAnimationDelay(currentPageIndex, 30);
};
const categories = [
{ label: '全部', value: '全部' },
{ label: '内地', value: '内地' },
{ label: '港台', value: '港台' },
{ label: '欧美', value: '欧美' },
{ label: '日本', value: '日本' },
{ label: '韩国', value: '韩国' },
];
const selectedCategory = ref('全部');
watch(selectedCategory, async () => {
offset.value = 0;
mvList.value = [];
hasMore.value = true;
await loadMvList();
});
const getAnimationDelay = computed(() => {
return (index: number) => setAnimationDelay(index, 30);
});
onMounted(async () => {
await loadMvList();
@@ -116,26 +148,26 @@ const playNextMv = async (setLoading: (value: boolean) => void) => {
};
const loadMvList = async () => {
if (!hasMore.value || loadingMore.value) return;
if (offset.value === 0) {
initLoading.value = true;
} else {
loadingMore.value = true;
}
try {
const res = await getTopMv(limit.value, offset.value);
if (!hasMore.value || loadingMore.value) return;
if (offset.value === 0) {
mvList.value = res.data.data;
initLoading.value = true;
} else {
mvList.value.push(...res.data.data);
loadingMore.value = true;
}
hasMore.value = res.data.data.length === limit.value;
const params = {
limit: limit.value,
offset: offset.value,
area: selectedCategory.value === '全部' ? '' : selectedCategory.value,
};
const res = selectedCategory.value === '全部' ? await getTopMv(params) : await getAllMv(params);
const { data } = res.data;
mvList.value.push(...data);
hasMore.value = data.length === limit.value;
offset.value += limit.value;
} catch (error) {
console.error('加载MV失败:', error);
} finally {
initLoading.value = false;
loadingMore.value = false;
@@ -157,12 +189,37 @@ const isPrevDisabled = computed(() => currentIndex.value === 0);
<style scoped lang="scss">
.mv-list {
@apply relative h-full w-full;
@apply h-full flex-1 flex flex-col overflow-hidden;
&-title {
@apply text-xl font-bold pb-2;
}
// 添加歌单分类样式
.play-list-type {
.title {
@apply text-lg font-bold mb-4;
}
.categories-wrapper {
@apply flex items-center py-2 pb-4;
white-space: nowrap;
}
&-item {
@apply py-2 px-3 mr-3 inline-block border border-gray-700 rounded-xl cursor-pointer transition-all duration-300;
background-color: #1a1a1a;
&:hover {
@apply bg-green-600/50;
}
&.active {
@apply bg-green-600 border-green-500;
}
}
}
&-content {
@apply grid gap-4 pb-28 mt-2 pr-4;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));

View File

@@ -59,8 +59,12 @@
isElectron ? '保存并重启' : '保存'
}}</n-button>
</div>
<div class="p-6 bg-black rounded-lg shadow-lg mt-10">
<div class="mt-10">
<p class="text-sm text-gray-100 text-center cursor-pointer hover:text-green-500" @click="copyQQ">
QQ群789288579
</p>
</div>
<div class="p-6 bg-black rounded-lg shadow-lg">
<div class="text-gray-100 text-base text-center">支持作者</div>
<div class="flex gap-60">
<div class="flex flex-col items-center gap-2 cursor-none hover:scale-[2] transition-all z-10 bg-black">
@@ -90,6 +94,11 @@ import { setAnimationClass } from '@/utils';
defineOptions({
name: 'Setting',
});
const message = useMessage();
const copyQQ = () => {
navigator.clipboard.writeText('789288579');
message.success('已复制到剪贴板');
};
const isElectron = ref((window as any).electronAPI !== undefined);
const router = useRouter();