diff --git a/Vocal-rank.code-workspace b/Vocal-rank.code-workspace new file mode 100644 index 0000000..876a149 --- /dev/null +++ b/Vocal-rank.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": {} +} \ No newline at end of file diff --git a/components/uploader-search.tsx b/components/uploader-search.tsx index c2e8e71..28fd28d 100644 --- a/components/uploader-search.tsx +++ b/components/uploader-search.tsx @@ -29,7 +29,7 @@ export default function UploaderSearch() { return } - // 检查是否为禁止的 UP 主 ID + // tsy 过滤器 if (blockedUploaderIds.includes(uid)) { router.push("/blocked") return diff --git a/components/video-search.tsx b/components/video-search.tsx index 13e06d1..2372e72 100644 --- a/components/video-search.tsx +++ b/components/video-search.tsx @@ -1,131 +1,275 @@ -"use client" +"use client"; -import { useState } from "react" -import { useRouter } from "next/navigation" -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" -import { Input } from "@/components/ui/input" -import { Button } from "@/components/ui/button" -import { Loader2 } from "lucide-react" -import { blockedVideoIds } from "@/config/blocked-ids" +import { useState } from "react"; +import { useRouter } from "next/navigation"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Loader2 } from "lucide-react"; +import { blockedVideoIds } from "@/config/blocked-ids"; interface Video { video_stat: { - view: number - like: number - coin: number - favorite: number - reply: number - share: number - danmaku: number - } + view: number; + like: number; + coin: number; + favorite: number; + reply: number; + share: number; + danmaku: number; + }; video_info: { - uploader_mid: string - uploader_name: string - title: string - pic: string - pages: number - timestamp: number - } + uploader_mid: string; + uploader_name: string; + title: string; + pic: string; + pages: number; + timestamp: number; + }; video_id: { - avid: string - bvid: string - } + avid: string; + bvid: string; + }; vrank_info: { - vrank_score: number - rank: string - rank_code: number - progress_percentage: number - } + vrank_score: number; + rank: string; + rank_code: number; + progress_percentage: number; + }; video_increase: { - view: number - like: number - coin: number - favorite: number - reply: number - share: number - danmaku: number - } - score_rank: number + view: number; + like: number; + coin: number; + favorite: number; + reply: number; + share: number; + danmaku: number; + }; + score_rank: number; } function getAchievement(views: number) { - if (views >= 10000000) return { name: "神话曲", next: null, progress: 100 } - if (views >= 1000000) + const safeViews = Math.max(0, Number(views) || 0); + if (safeViews >= 10000000) + return { name: "神话曲", next: null, progress: 100 }; + if (safeViews >= 1000000) return { name: "传说曲", next: "神话曲", - progress: (views / 10000000) * 100, - } - if (views >= 100000) + progress: (safeViews / 10000000) * 100, + }; + if (safeViews >= 100000) return { name: "殿堂曲", next: "传说曲", - progress: (views / 1000000) * 100, - } - return { name: "未达成", next: "殿堂曲", progress: (views / 100000) * 100 } + progress: (safeViews / 1000000) * 100, + }; + return { + name: "未达成", + next: "殿堂曲", + progress: (safeViews / 100000) * 100, + }; } +const VideoInfo = ({ video }: { video: Video }) => { + const achievement = getAchievement(video.video_stat.view); + + return ( +
+ UP主: {video.video_info.uploader_name} (UID:{" "} + {video.video_info.uploader_mid}) +
+BV号: {video.video_id.bvid}
+AV号: {video.video_id.avid}
++ 播放量: {video.video_stat.view.toLocaleString()} +
++ 点赞数: {video.video_stat.like.toLocaleString()} +
++ 投币: {video.video_stat.coin.toLocaleString()} +
++ 收藏: {video.video_stat.favorite.toLocaleString()} +
++ 评论: {video.video_stat.reply.toLocaleString()} +
++ 分享: {video.video_stat.share.toLocaleString()} +
++ 弹幕数: {video.video_stat.danmaku.toLocaleString()} +
++ 周刊得分: {video.vrank_info.vrank_score.toFixed(2)} +
++ 周刊排名: {video.score_rank} +
+ > + ) : ( +暂无周刊数据
+ )} + {video.video_increase && ( + <> ++ 播放增长: {video.video_increase.view.toLocaleString()} +
++ 点赞增长: {video.video_increase.like.toLocaleString()} +
++ 投币增长: {video.video_increase.coin.toLocaleString()} +
++ 收藏增长: {video.video_increase.favorite.toLocaleString()} +
++ 评论增长: {video.video_increase.reply.toLocaleString()} +
++ 分享增长: {video.video_increase.share.toLocaleString()} +
++ 弹幕增长: {video.video_increase.danmaku.toLocaleString()} +
++ 数据更新时间:{" "} + {new Date(video.video_info.timestamp * 1000).toLocaleString( + "zh-CN" + )} +
+成就: {achievement.name}
+ {achievement.next && ( ++ 距离 {achievement.next} 还需{" "} + {(achievement.next === "殿堂曲" + ? 100000 + : achievement.next === "传说曲" + ? 1000000 + : 10000000) - video.video_stat.view}{" "} + 播放 +
+