import { useState } from "react"; import { useParams } from "react-router"; import Article from "~/components/common/article"; import LightBox, { useLightBox } from "~/components/biz/gallery/image-box"; import Comments from "~/components/shared/comment"; import { CupFill, ShareFill, ThumbUpFill } from "~/components/ui/icons"; import { useHydrated } from "~/hooks/use-hydrated"; import { siteTitle } from "~/utils"; import { getImageThumbUrl } from "~/utils/media"; import type { Route } from "./+types/note-detail"; const { APP_APIURL } = import.meta.env; export function meta({ loaderData }: Route.MetaArgs) { return [ { title: loaderData ? siteTitle(loaderData.data.title) : "404" }, { name: "description", content: loaderData?.data.except }, ]; } export async function loader({ params }: Route.LoaderArgs) { if (Number.isNaN(Number(params.year)) || Number.isNaN(Number(params.id))) { throw new Response("Not Found", { status: 404 }); } const note = (await fetch( `${APP_APIURL}/api/note/get?id=${params.id}&year=${params.year}`, ).then((res) => res.json())) as API.Response; if (note.status === "Failed") { throw new Response("Not Found", { status: 404 }); } return note; } export default function NoteDetail({ loaderData }: Route.ComponentProps) { const note = loaderData; const params = useParams(); const hydrated = useHydrated(); const { ref: mediaLightBoxRef, open: onShowMediaLightBox } = useLightBox(); const [likes, setLikes] = useState(note.data.likes); const mediaList = note.data.media?.length ? note.data.media.map((item) => ({ ...item, thumb_url: item.thumb_url || getImageThumbUrl(item.url), })) : []; const hasMedia = mediaList.length > 0; const commentRef = `note-${params.year}-${params.id}`; const onLike = () => { setLikes((prevLike) => prevLike + 1); }; const onShare = () => { const shareData = { title: note.data.title, text: note.data.except, url: `${location.protocol}//${location.host}${location.pathname}`, }; if ("share" in navigator) { navigator.share(shareData); } else { alert("当前操作系统尚未实现此 API"); } }; return (

{note.data.title}

{note.data.date}

{hasMedia && (
{mediaList.map((media, index) => { const isVideo = media.type === "mp4" || media.url.includes("mp4"); if (isVideo) { return (
)}
{hydrated && }
); }