improve: SSR in database page, fix some UI bugs
extract: component SongCard used in database pages adjust (UI): now lyrics container won't show scrollbar
This commit is contained in:
parent
73ad9036c2
commit
aef964aa35
@ -8,7 +8,7 @@ AquaVox 是一个为中文虚拟歌手爱好者献上的产品。
|
|||||||
|
|
||||||
## 使用
|
## 使用
|
||||||
|
|
||||||
当前 AquaVox 的公开预览版位于[aquavox.a2x.pub](https://aquavox.a2x.pub)上。
|
当前 AquaVox 的公开预览版位于 [aquavox.app](https://aquavox.app) 上。
|
||||||
|
|
||||||
[](https://wakatime.com/badge/user/018f0628-909b-47e4-bcfd-0153235426d9/project/b67c03ef-ee0b-45f2-85ec-d9c60269cc55)
|
[](https://wakatime.com/badge/user/018f0628-909b-47e4-bcfd-0153235426d9/project/b67c03ef-ee0b-45f2-85ec-d9c60269cc55)
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "aquavox",
|
"name": "aquavox",
|
||||||
"version": "1.12.6",
|
"version": "1.12.8",
|
||||||
"private": false,
|
"private": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
|
62
src/lib/components/database/songCard.svelte
Normal file
62
src/lib/components/database/songCard.svelte
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import formatDuration from "$lib/formatDuration";
|
||||||
|
import { formatViews } from "$lib/formatViews";
|
||||||
|
|
||||||
|
export let songData: MusicMetadata;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="relative w-56 h-56 bg-zinc-300 dark:bg-zinc-600 rounded-lg overflow-hidden
|
||||||
|
shadow-lg cursor-pointer justify-self-center"
|
||||||
|
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="absolute top-0 left-0 w-full h-full duration-100
|
||||||
|
z-10 opacity-0 hover:opacity-100 bg-[rgba(0,0,0,0.15)]"
|
||||||
|
>
|
||||||
|
<a href={songData.url} class="absolute z-10 h-full w-full">
|
||||||
|
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
class="brightness-125 absolute top-2 right-2 w-8 h-8 rounded-full
|
||||||
|
bg-[rgba(49,49,49,0.7)] backdrop-blur-lg z-30 hover:bg-red-500"
|
||||||
|
href={`/database/edit/${songData.id}`}
|
||||||
|
>
|
||||||
|
<img class="relative w-4 h-4 top-2 left-2 scale-90" src="/edit.svg" alt="编辑" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<img src={songData.coverURL[0]} class="w-56 h-56" alt="" />
|
||||||
|
<div
|
||||||
|
class="absolute bottom-0 w-full h-28 backdrop-blur-xl"
|
||||||
|
style="mask-image: linear-gradient(to top, black 50%, transparent);"
|
||||||
|
>
|
||||||
|
<div class="absolute bottom-0 w-full h-16 pl-2">
|
||||||
|
<span
|
||||||
|
class="font-semibold text-2xl text-white"
|
||||||
|
style="text-shadow: 0px 0px 4px rgba(65, 65, 65, .6);">{songData.name}</span
|
||||||
|
>
|
||||||
|
<br />
|
||||||
|
<span
|
||||||
|
class="relative inline-block whitespace-nowrap text-white w-28
|
||||||
|
overflow-hidden text-ellipsis"
|
||||||
|
style="text-shadow: 0px 0px 4px rgba(65, 65, 65, .6);"
|
||||||
|
>
|
||||||
|
{songData.producer}
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
class="absolute right-2 bottom-2 text-right text-white"
|
||||||
|
style="text-shadow: 0px 0px 4px rgba(65, 65, 65, .6);"
|
||||||
|
>
|
||||||
|
{#if songData.duration}
|
||||||
|
<span>{formatDuration(songData.duration)}</span>
|
||||||
|
{/if}
|
||||||
|
<br />
|
||||||
|
{#if songData.views}
|
||||||
|
<span>{formatViews(songData.views)}播放</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -68,7 +68,7 @@
|
|||||||
|
|
||||||
for (let i = 0; i < scripts.length; i++) {
|
for (let i = 0; i < scripts.length; i++) {
|
||||||
const offset = Math.abs(i - currentPositionIndex);
|
const offset = Math.abs(i - currentPositionIndex);
|
||||||
const blurRadius = Math.min(offset * 1.5, 16);
|
const blurRadius = Math.min(offset * 1, 16);
|
||||||
if (refs[i]) {
|
if (refs[i]) {
|
||||||
refs[i].style.filter = `blur(${blurRadius}px)`;
|
refs[i].style.filter = `blur(${blurRadius}px)`;
|
||||||
}
|
}
|
||||||
@ -278,10 +278,10 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
.no-scrollbar {
|
.no-scrollbar {
|
||||||
scrollbar-width: 10px;
|
scrollbar-width: none;
|
||||||
}
|
}
|
||||||
.no-scrollbar::-webkit-scrollbar {
|
.no-scrollbar::-webkit-scrollbar {
|
||||||
width: 10px;
|
width: 0px;
|
||||||
}
|
}
|
||||||
.current-lyric {
|
.current-lyric {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
17
src/routes/database/+page.server.ts
Normal file
17
src/routes/database/+page.server.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { songData } from '$lib/server/cache.js';
|
||||||
|
import { loadData } from '$lib/server/database/loadData.js';
|
||||||
|
import type { PageServerLoad } from './$types';
|
||||||
|
|
||||||
|
export const load: PageServerLoad = () => {
|
||||||
|
loadData();
|
||||||
|
const songIDList = songData.keys().slice(0, 20);
|
||||||
|
const songDataList = [];
|
||||||
|
for (const songID of songIDList) {
|
||||||
|
songDataList.push(songData.get(songID)!);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
songDataList: songDataList
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ssr = true;
|
@ -1,20 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import formatDuration from '$lib/formatDuration';
|
import SongCard from '$lib/components/database/songCard.svelte';
|
||||||
import { formatViews } from '$lib/formatViews';
|
import type { PageServerData } from './$types';
|
||||||
import { onMount } from 'svelte';
|
export let data: PageServerData;
|
||||||
let songList: MusicMetadata[] = [];
|
let songList: MusicMetadata[] = data.songDataList;
|
||||||
|
|
||||||
onMount(async () => {
|
|
||||||
fetch('/api/database/songs')
|
|
||||||
.then((response) => response.json())
|
|
||||||
.then((data) => {
|
|
||||||
songList = data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
return [];
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@ -33,57 +21,14 @@
|
|||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid mb-32" style="grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
|
<div
|
||||||
|
class="relative grid mb-32"
|
||||||
|
style="grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
gap: 2rem 1rem;">
|
gap: 2rem 1rem;"
|
||||||
|
>
|
||||||
{#each songList as song}
|
{#each songList as song}
|
||||||
<a
|
<SongCard songData={song}/>
|
||||||
class="relative w-56 h-56 bg-zinc-300 dark:bg-zinc-600 rounded-lg overflow-hidden
|
|
||||||
shadow-lg cursor-pointer justify-self-center"
|
|
||||||
href={song.url}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="absolute top-0 left-0 w-full h-full duration-100
|
|
||||||
z-10 opacity-0 hover:opacity-100 bg-[rgba(0,0,0,0.15)]"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
class="brightness-125 absolute top-2 right-2 w-8 h-8 rounded-full
|
|
||||||
bg-[rgba(49,49,49,0.7)] backdrop-blur-lg z-10 hover:bg-red-500"
|
|
||||||
href={`/database/edit/${song.id}`}
|
|
||||||
>
|
|
||||||
<img class="relative w-4 h-4 top-2 left-2 scale-90" src="/edit.svg" alt="编辑" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<img src={song.coverURL[0]} class="w-56 h-56" alt="" />
|
|
||||||
<div
|
|
||||||
class="absolute bottom-0 w-full h-28 backdrop-blur-xl"
|
|
||||||
style="mask-image: linear-gradient(to top, black 50%, transparent);"
|
|
||||||
>
|
|
||||||
<div class="absolute bottom-0 w-full h-16 pl-2">
|
|
||||||
<span
|
|
||||||
class="font-semibold text-2xl text-white"
|
|
||||||
style="text-shadow: 0px 0px 4px rgba(65, 65, 65, .6);">{song.name}</span
|
|
||||||
>
|
|
||||||
<br />
|
|
||||||
<span
|
|
||||||
class="relative inline-block whitespace-nowrap text-white w-28
|
|
||||||
overflow-hidden text-ellipsis"
|
|
||||||
style="text-shadow: 0px 0px 4px rgba(65, 65, 65, .6);"
|
|
||||||
>
|
|
||||||
{song.producer}
|
|
||||||
</span>
|
|
||||||
<div class="absolute right-2 bottom-2 text-right text-white" style="text-shadow: 0px 0px 4px rgba(65, 65, 65, .6);">
|
|
||||||
{#if song.duration}
|
|
||||||
<span>{formatDuration(song.duration)}</span>
|
|
||||||
{/if}
|
|
||||||
<br />
|
|
||||||
{#if song.views}
|
|
||||||
<span>{formatViews(song.views)}播放</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
18
src/routes/database/page/[id]/+page.server.ts
Normal file
18
src/routes/database/page/[id]/+page.server.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { songData } from '$lib/server/cache.js';
|
||||||
|
import { loadData } from '$lib/server/database/loadData.js';
|
||||||
|
import type { PageServerLoad } from './$types';
|
||||||
|
|
||||||
|
export const load: PageServerLoad = ({ params }) => {
|
||||||
|
const offset = (parseInt(params.id) - 1) * 20;
|
||||||
|
loadData();
|
||||||
|
const songIDList = songData.keys().slice(offset, offset + 20);
|
||||||
|
const songDataList = [];
|
||||||
|
for (const songID of songIDList) {
|
||||||
|
songDataList.push(songData.get(songID)!);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
songDataList: songDataList
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ssr = true;
|
34
src/routes/database/page/[id]/+page.svelte
Normal file
34
src/routes/database/page/[id]/+page.svelte
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import SongCard from '$lib/components/database/songCard.svelte';
|
||||||
|
import type { PageServerData } from './$types';
|
||||||
|
export let data: PageServerData;
|
||||||
|
let songList: MusicMetadata[] = data.songDataList;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<title>AquaVox 音乐数据库</title>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<h1 class="text-3xl text-red-500"><a href="/">AquaVox</a></h1>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="flex justify-between items-center h-20 mb-8">
|
||||||
|
<h1>AquaVox 音乐数据库</h1>
|
||||||
|
<a
|
||||||
|
href="/database/submit"
|
||||||
|
class="h-12 w-24 border-black dark:border-white border-2 flex items-center justify-center rounded-lg"
|
||||||
|
>提交新曲</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="relative grid mb-32"
|
||||||
|
style="grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 2rem 1rem;"
|
||||||
|
>
|
||||||
|
{#each songList as song}
|
||||||
|
<SongCard songData={song}/>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Reference in New Issue
Block a user