添加详情页的点赞计数,添加网站图标
This commit is contained in:
parent
5a5eba19e4
commit
f94ef73518
@ -87,11 +87,16 @@ async function readPostMem(context: BrowserContext, page: Page) {
|
|||||||
// return {aweme: { detail: {} } };
|
// return {aweme: { detail: {} } };
|
||||||
}).catch(() => null);
|
}).catch(() => null);
|
||||||
|
|
||||||
|
// await new Promise((res) => setTimeout(res, 1000000));
|
||||||
|
|
||||||
let aweme_mem = md?.aweme?.detail as DouyinImageAweme;
|
let aweme_mem = md?.aweme?.detail as DouyinImageAweme;
|
||||||
if (!aweme_mem) throw new Error('页面内存数据中未找到作品详情');
|
if (!aweme_mem) throw new Error('页面内存数据中未找到作品详情');
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
aweme_mem.author = aweme_mem.authorInfo
|
aweme_mem.author = aweme_mem.authorInfo
|
||||||
|
// @ts-ignore
|
||||||
|
aweme_mem.statistics = aweme_mem.stats
|
||||||
|
|
||||||
const comments = md.comment ? createCamelCompatibleProxy<DouyinCommentResponse>(md.comment) : null;
|
const comments = md.comment ? createCamelCompatibleProxy<DouyinCommentResponse>(md.comment) : null;
|
||||||
const aweme = createCamelCompatibleProxy(aweme_mem);
|
const aweme = createCamelCompatibleProxy(aweme_mem);
|
||||||
|
|
||||||
|
|||||||
@ -300,6 +300,7 @@ export default function AwemeDetailClient({ data, neighbors }: AwemeDetailClient
|
|||||||
<NavigationButtons
|
<NavigationButtons
|
||||||
neighbors={neighbors}
|
neighbors={neighbors}
|
||||||
commentsCount={data.commentsCount}
|
commentsCount={data.commentsCount}
|
||||||
|
likesCount={data.likesCount}
|
||||||
onNavigatePrev={() => neighbors.prev && router.push(`/aweme/${neighbors.prev.aweme_id}`)}
|
onNavigatePrev={() => neighbors.prev && router.push(`/aweme/${neighbors.prev.aweme_id}`)}
|
||||||
onNavigateNext={() => neighbors.next && router.push(`/aweme/${neighbors.next.aweme_id}`)}
|
onNavigateNext={() => neighbors.next && router.push(`/aweme/${neighbors.next.aweme_id}`)}
|
||||||
onToggleComments={() => commentState.setOpen((v) => !v)}
|
onToggleComments={() => commentState.setOpen((v) => !v)}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ export function ImageNavigationButtons({
|
|||||||
{/* 左侧按钮 */}
|
{/* 左侧按钮 */}
|
||||||
<button
|
<button
|
||||||
className={`
|
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
|
w-12 h-12 rounded-full
|
||||||
bg-black/40 backdrop-blur-sm border border-white/20
|
bg-black/40 backdrop-blur-sm border border-white/20
|
||||||
flex items-center justify-center
|
flex items-center justify-center
|
||||||
@ -38,7 +38,7 @@ export function ImageNavigationButtons({
|
|||||||
{/* 右侧按钮 */}
|
{/* 右侧按钮 */}
|
||||||
<button
|
<button
|
||||||
className={`
|
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
|
w-12 h-12 rounded-full
|
||||||
bg-black/40 backdrop-blur-sm border border-white/20
|
bg-black/40 backdrop-blur-sm border border-white/20
|
||||||
flex items-center justify-center
|
flex items-center justify-center
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import { ChevronDown, ChevronUp, MessageSquareText } from "lucide-react";
|
import { ChevronDown, ChevronUp, MessageSquareText, ThumbsUp } from "lucide-react";
|
||||||
import type { Neighbors } from "../types";
|
import type { Neighbors } from "../types";
|
||||||
|
|
||||||
interface NavigationButtonsProps {
|
interface NavigationButtonsProps {
|
||||||
neighbors: Neighbors;
|
neighbors: Neighbors;
|
||||||
commentsCount: number;
|
commentsCount: number;
|
||||||
|
likesCount: number;
|
||||||
onNavigatePrev: () => void;
|
onNavigatePrev: () => void;
|
||||||
onNavigateNext: () => void;
|
onNavigateNext: () => void;
|
||||||
onToggleComments: () => void;
|
onToggleComments: () => void;
|
||||||
@ -12,30 +13,44 @@ interface NavigationButtonsProps {
|
|||||||
export function NavigationButtons({
|
export function NavigationButtons({
|
||||||
neighbors,
|
neighbors,
|
||||||
commentsCount,
|
commentsCount,
|
||||||
|
likesCount,
|
||||||
onNavigatePrev,
|
onNavigatePrev,
|
||||||
onNavigateNext,
|
onNavigateNext,
|
||||||
onToggleComments,
|
onToggleComments,
|
||||||
}: NavigationButtonsProps) {
|
}: NavigationButtonsProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* 评论开关(右侧中部) */}
|
<div className="absolute right-4 top-8/14 flex flex-col items-center gap-8 z-10">
|
||||||
<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"
|
||||||
onClick={onToggleComments}
|
>
|
||||||
aria-label="切换评论"
|
<div className="grid place-items-center gap-1 drop-shadow-lg">
|
||||||
>
|
<ThumbsUp size={40} className="" />
|
||||||
<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> :
|
<span className="text-[16px] font-semibold text-white/90 drop-shadow">{likesCount}</span>
|
||||||
<span className="text-[12px] font-semibold text-white/90 drop-shadow">暂无评论</span>
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
{/* 评论开关(右侧中部) */}
|
||||||
|
<button
|
||||||
|
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-[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">
|
<div className="flex flex-col rounded-full bg-black/40 backdrop-blur-sm border border-white/20 overflow-hidden">
|
||||||
<button
|
<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"
|
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"
|
||||||
|
|||||||
@ -77,6 +77,7 @@ export default async function AwemeDetail({ params }: { params: Promise<{ awemeI
|
|||||||
height: video!.height ?? null,
|
height: video!.height ?? null,
|
||||||
author: { nickname: video!.author.nickname, avatar_url: video!.author.avatar_url },
|
author: { nickname: video!.author.nickname, avatar_url: video!.author.avatar_url },
|
||||||
commentsCount,
|
commentsCount,
|
||||||
|
likesCount: Number(video!.digg_count),
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
type: "image" as const,
|
type: "image" as const,
|
||||||
@ -87,6 +88,7 @@ export default async function AwemeDetail({ params }: { params: Promise<{ awemeI
|
|||||||
music_url: post!.music_url,
|
music_url: post!.music_url,
|
||||||
author: { nickname: post!.author.nickname, avatar_url: post!.author.avatar_url },
|
author: { nickname: post!.author.nickname, avatar_url: post!.author.avatar_url },
|
||||||
commentsCount,
|
commentsCount,
|
||||||
|
likesCount: Number(post!.digg_count),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Compute prev/next neighbors by created_at across videos and image posts
|
// Compute prev/next neighbors by created_at across videos and image posts
|
||||||
|
|||||||
@ -20,6 +20,7 @@ export type VideoData = {
|
|||||||
height?: number | null;
|
height?: number | null;
|
||||||
author: User;
|
author: User;
|
||||||
commentsCount: number;
|
commentsCount: number;
|
||||||
|
likesCount: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ImageData = {
|
export type ImageData = {
|
||||||
@ -31,6 +32,7 @@ export type ImageData = {
|
|||||||
music_url?: string | null;
|
music_url?: string | null;
|
||||||
author: User;
|
author: User;
|
||||||
commentsCount: number;
|
commentsCount: number;
|
||||||
|
likesCount: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AwemeData = VideoData | ImageData;
|
export type AwemeData = VideoData | ImageData;
|
||||||
|
|||||||
BIN
app/favicon.ico
BIN
app/favicon.ico
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB |
@ -18,6 +18,9 @@ export const metadata: Metadata = {
|
|||||||
template: "%s - 抖歪",
|
template: "%s - 抖歪",
|
||||||
},
|
},
|
||||||
description: "记录当下时代的精彩瞬间",
|
description: "记录当下时代的精彩瞬间",
|
||||||
|
icons: {
|
||||||
|
icon: "/favicon.png",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
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";
|
type TaskStatus = "pending" | "running" | "success" | "error";
|
||||||
|
|
||||||
@ -74,6 +74,21 @@ export default function TasksPage() {
|
|||||||
setInput("");
|
setInput("");
|
||||||
}, [input, addTasks]);
|
}, [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) => {
|
const startTask = useCallback(async (task: Task) => {
|
||||||
// 若已存在控制器,避免重复启动
|
// 若已存在控制器,避免重复启动
|
||||||
if (controllers.current.has(task.id)) return;
|
if (controllers.current.has(task.id)) return;
|
||||||
@ -199,10 +214,13 @@ export default function TasksPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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">
|
<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" /> 添加任务
|
<Plus className="h-4 w-4" /> 添加任务
|
||||||
</button>
|
</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">
|
<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" /> 清除已完成
|
<Trash2 className="h-4 w-4" /> 清除已完成
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
BIN
public/favicon.png
Normal file
BIN
public/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
Loading…
x
Reference in New Issue
Block a user