添加详情页的点赞计数,添加网站图标

This commit is contained in:
feie9456 2025-10-23 14:22:12 +08:00
parent 5a5eba19e4
commit f94ef73518
10 changed files with 65 additions and 19 deletions

View File

@ -87,11 +87,16 @@ async function readPostMem(context: BrowserContext, page: Page) {
// return {aweme: { detail: {} } };
}).catch(() => null);
// await new Promise((res) => setTimeout(res, 1000000));
let aweme_mem = md?.aweme?.detail as DouyinImageAweme;
if (!aweme_mem) throw new Error('页面内存数据中未找到作品详情');
// @ts-ignore
aweme_mem.author = aweme_mem.authorInfo
// @ts-ignore
aweme_mem.statistics = aweme_mem.stats
const comments = md.comment ? createCamelCompatibleProxy<DouyinCommentResponse>(md.comment) : null;
const aweme = createCamelCompatibleProxy(aweme_mem);

View File

@ -300,6 +300,7 @@ export default function AwemeDetailClient({ data, neighbors }: AwemeDetailClient
<NavigationButtons
neighbors={neighbors}
commentsCount={data.commentsCount}
likesCount={data.likesCount}
onNavigatePrev={() => neighbors.prev && router.push(`/aweme/${neighbors.prev.aweme_id}`)}
onNavigateNext={() => neighbors.next && router.push(`/aweme/${neighbors.next.aweme_id}`)}
onToggleComments={() => commentState.setOpen((v) => !v)}

View File

@ -21,7 +21,7 @@ export function ImageNavigationButtons({
{/* 左侧按钮 */}
<button
className={`
absolute left-4 top-7/16 -translate-y-1/2 z-20
absolute left-4 top-6/17 -translate-y-1/2 z-20
w-12 h-12 rounded-full
bg-black/40 backdrop-blur-sm border border-white/20
flex items-center justify-center
@ -38,7 +38,7 @@ export function ImageNavigationButtons({
{/* 右侧按钮 */}
<button
className={`
absolute right-4 top-7/16 -translate-y-1/2 z-20
absolute right-4 top-6/17 -translate-y-1/2 z-20
w-12 h-12 rounded-full
bg-black/40 backdrop-blur-sm border border-white/20
flex items-center justify-center

View File

@ -1,9 +1,10 @@
import { ChevronDown, ChevronUp, MessageSquareText } from "lucide-react";
import { ChevronDown, ChevronUp, MessageSquareText, ThumbsUp } from "lucide-react";
import type { Neighbors } from "../types";
interface NavigationButtonsProps {
neighbors: Neighbors;
commentsCount: number;
likesCount: number;
onNavigatePrev: () => void;
onNavigateNext: () => void;
onToggleComments: () => void;
@ -12,30 +13,44 @@ interface NavigationButtonsProps {
export function NavigationButtons({
neighbors,
commentsCount,
likesCount,
onNavigatePrev,
onNavigateNext,
onToggleComments,
}: NavigationButtonsProps) {
return (
<>
<div className="absolute right-4 top-8/14 flex flex-col items-center gap-8 z-10">
<button
className="grid place-items-center w-[54px] h-[54px] rounded-full -translate-y-1/2"
>
<div className="grid place-items-center gap-1 drop-shadow-lg">
<ThumbsUp size={40} className="" />
<span className="text-[16px] font-semibold text-white/90 drop-shadow">{likesCount}</span>
</div>
</button>
{/* 评论开关(右侧中部) */}
<button
className="z-10 grid place-items-center w-[54px] h-[54px] rounded-full absolute right-4 top-2/3 -translate-y-1/2 cursor-pointer"
className="grid place-items-center w-[54px] h-[54px] rounded-full -translate-y-1/2 cursor-pointer"
onClick={onToggleComments}
aria-label="切换评论"
>
<div className="grid place-items-center gap-1 drop-shadow-lg">
<MessageSquareText size={40} className="" />
{commentsCount > 0 ? <span className="text-[18px] font-semibold text-white/90 drop-shadow">{commentsCount}</span> :
{commentsCount > 0 ? <span className="text-[16px] font-semibold text-white/90 drop-shadow">{commentsCount}</span> :
<span className="text-[12px] font-semibold text-white/90 drop-shadow"></span>
}
</div>
</button>
</div>
{/* 上下切换按钮(右侧胶囊形状) */}
<div className="absolute right-4 top-6/11 -translate-y-1/2 z-10">
<div className="absolute right-4 top-5/11 -translate-y-1/2 z-10">
<div className="flex flex-col rounded-full bg-black/40 backdrop-blur-sm border border-white/20 overflow-hidden">
<button
className="w-[44px] h-[44px] inline-flex items-center justify-center text-white disabled:opacity-40 cursor-pointer disabled:cursor-not-allowed hover:bg-white/10 transition-colors"

View File

@ -77,6 +77,7 @@ export default async function AwemeDetail({ params }: { params: Promise<{ awemeI
height: video!.height ?? null,
author: { nickname: video!.author.nickname, avatar_url: video!.author.avatar_url },
commentsCount,
likesCount: Number(video!.digg_count),
}
: {
type: "image" as const,
@ -87,6 +88,7 @@ export default async function AwemeDetail({ params }: { params: Promise<{ awemeI
music_url: post!.music_url,
author: { nickname: post!.author.nickname, avatar_url: post!.author.avatar_url },
commentsCount,
likesCount: Number(post!.digg_count),
};
// Compute prev/next neighbors by created_at across videos and image posts

View File

@ -20,6 +20,7 @@ export type VideoData = {
height?: number | null;
author: User;
commentsCount: number;
likesCount: number;
};
export type ImageData = {
@ -31,6 +32,7 @@ export type ImageData = {
music_url?: string | null;
author: User;
commentsCount: number;
likesCount: number;
};
export type AwemeData = VideoData | ImageData;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@ -18,6 +18,9 @@ export const metadata: Metadata = {
template: "%s - 抖歪",
},
description: "记录当下时代的精彩瞬间",
icons: {
icon: "/favicon.png",
},
};
export default function RootLayout({

View File

@ -1,7 +1,7 @@
"use client";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { AlertTriangle, CheckCircle2, Clock, ExternalLink, Link2, Loader2, PlayCircle, Plus, Square, Trash2, X } from "lucide-react";
import { AlertTriangle, CheckCircle2, Clipboard, Clock, ExternalLink, Link2, Loader2, PlayCircle, Plus, Square, Trash2, X } from "lucide-react";
type TaskStatus = "pending" | "running" | "success" | "error";
@ -74,6 +74,21 @@ export default function TasksPage() {
setInput("");
}, [input, addTasks]);
const handlePasteAndAdd = useCallback(async () => {
try {
const text = await navigator.clipboard.readText();
const urls = extractDouyinLinks(text);
if (!urls.length) {
alert("剪贴板中未检测到 Douyin 短链,请复制包含 https://v.douyin.com/... 的文本");
return;
}
addTasks(urls);
} catch (err) {
alert("无法读取剪贴板内容,请检查浏览器权限设置");
console.error("Clipboard read error:", err);
}
}, [addTasks]);
const startTask = useCallback(async (task: Task) => {
// 若已存在控制器,避免重复启动
if (controllers.current.has(task.id)) return;
@ -199,10 +214,13 @@ export default function TasksPage() {
</div>
</div>
</div>
<div className="mt-4 flex items-center gap-3">
<div className="mt-4 flex flex-wrap items-center gap-3">
<button type="submit" className="inline-flex items-center gap-2 rounded-md bg-indigo-600/90 px-3 py-2 text-sm font-medium text-white transition-colors hover:bg-indigo-600 focus:outline-none focus:ring-2 focus:ring-indigo-400/40">
<Plus className="h-4 w-4" />
</button>
<button type="button" onClick={handlePasteAndAdd} className="inline-flex items-center gap-2 rounded-md bg-emerald-600/90 px-3 py-2 text-sm font-medium text-white transition-colors hover:bg-emerald-600 focus:outline-none focus:ring-2 focus:ring-emerald-400/40">
<Clipboard className="h-4 w-4" />
</button>
<button type="button" onClick={clearFinished} className="inline-flex items-center gap-2 rounded-md bg-neutral-800 px-3 py-2 text-sm text-neutral-200 transition-colors hover:bg-neutral-700 focus:outline-none focus:ring-2 focus:ring-white/10">
<Trash2 className="h-4 w-4" />
</button>

BIN
public/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB