From e5c73b09506b008e9cf900bb4e758a1353ec6485 Mon Sep 17 00:00:00 2001 From: Imken Luo Date: Sun, 1 Oct 2023 21:36:41 +0800 Subject: [PATCH] feat(viewer): redirect/link to legacy site - Notice that it is hard encoded in the code. --- packages/viewer/src/app/[id]/[page]/page.tsx | 42 ++++++++------- packages/viewer/src/app/[id]/layout.tsx | 21 +++++++- packages/viewer/src/app/[id]/page.tsx | 9 +++- .../viewer/src/app/[id]/saved-in-legacy.json | 1 + .../viewer/src/app/r/[rid]/get-reply-raw.ts | 13 ++--- packages/viewer/src/app/r/[rid]/page.tsx | 53 ++++++++++++++++--- .../viewer/src/app/r/saved-in-legacy.json | 1 + .../viewer/src/components/replies/Content.tsx | 15 +++--- packages/viewer/src/lib/utils.ts | 37 +++++++++++++ 9 files changed, 147 insertions(+), 45 deletions(-) create mode 100644 packages/viewer/src/app/[id]/saved-in-legacy.json create mode 100644 packages/viewer/src/app/r/saved-in-legacy.json create mode 100644 packages/viewer/src/lib/utils.ts diff --git a/packages/viewer/src/app/[id]/[page]/page.tsx b/packages/viewer/src/app/[id]/[page]/page.tsx index ce20bef..8774493 100644 --- a/packages/viewer/src/app/[id]/[page]/page.tsx +++ b/packages/viewer/src/app/[id]/[page]/page.tsx @@ -1,11 +1,13 @@ -import { notFound } from "next/navigation"; +import { notFound, redirect } from "next/navigation"; import prisma from "@/lib/prisma"; import paginate from "@/lib/pagination"; import PageButtons from "@/components/replies/PageButtons"; -// import serializeReply from "@/lib/serialize-reply"; import Reply from "@/components/replies/Reply"; import { selectReply } from "@/lib/reply"; import { selectPost } from "@/lib/post"; +import { checkExists } from "@/lib/utils"; +import savedInLegacyList from "../saved-in-legacy.json"; +// import serializeReply from "@/lib/serialize-reply"; const REPLIES_PER_PAGE = parseInt(process.env.REPLIES_PER_PAGE ?? "10", 10); @@ -17,29 +19,31 @@ export default async function Page({ const id = parseInt(params.id, 10); const page = parseInt(params.page, 10); if (Number.isNaN(page)) notFound(); + const savedAtLegacy = checkExists(savedInLegacyList, id); const { snapshots, replies, _count: { replies: numReplies }, - } = await prisma.post - .findUnique({ - where: { id }, - select: { - ...selectPost.withLatestSnapshotMeta, - replies: { - select: { - ...selectReply.withBasic, - ...selectReply.withTakedown, - ...selectReply.withLatestContent, - }, - orderBy: { id: "asc" }, - skip: (page - 1) * REPLIES_PER_PAGE, - take: REPLIES_PER_PAGE, + } = (await prisma.post.findUnique({ + where: { id }, + select: { + ...selectPost.withLatestSnapshotMeta, + replies: { + select: { + ...selectReply.withBasic, + ...selectReply.withTakedown, + ...selectReply.withLatestContent, }, - _count: { select: { replies: true } }, + orderBy: { id: "asc" }, + skip: (page - 1) * REPLIES_PER_PAGE, + take: REPLIES_PER_PAGE, }, - }) - .then((post) => post ?? notFound()); + _count: { select: { replies: true } }, + }, + })) ?? + (savedAtLegacy + ? redirect(`https://legacy.lglg.top/${id}/${page}`) + : notFound()); const numPages = Math.ceil(numReplies / REPLIES_PER_PAGE); const { pagesLocalAttachedFront, pagesLocalAttachedBack, pagesLocal } = paginate(numPages, page); diff --git a/packages/viewer/src/app/[id]/layout.tsx b/packages/viewer/src/app/[id]/layout.tsx index 5013c79..26cdc4c 100644 --- a/packages/viewer/src/app/[id]/layout.tsx +++ b/packages/viewer/src/app/[id]/layout.tsx @@ -1,5 +1,5 @@ import type { Metadata } from "next"; -import { notFound } from "next/navigation"; +import { notFound, redirect } from "next/navigation"; import prisma from "@/lib/prisma"; import { getPostUrl, getForumUrl } from "@/lib/luogu"; import stringifyTime from "@/lib/time"; @@ -8,6 +8,8 @@ import "@/components/markdown.css"; import UpdateButton from "@/components/UpdateButton"; import Reply from "@/components/replies/Reply"; import { selectPost } from "@/lib/post"; +import { checkExists } from "@/lib/utils"; +import savedInLegacyList from "./saved-in-legacy.json"; export async function generateMetadata({ params, @@ -34,6 +36,7 @@ export default async function Page({ }: React.PropsWithChildren<{ params: { id: string } }>) { const id = parseInt(params.id, 10); if (Number.isNaN(id)) notFound(); + const savedAtLegacy = checkExists(savedInLegacyList, id); const { replyCount, time, @@ -48,7 +51,8 @@ export default async function Page({ ...selectPost.withTakedown, _count: { select: { replies: true } }, }, - })) ?? notFound(); + })) ?? + (savedAtLegacy ? redirect(`https://legacy.lglg.top/${id}`) : notFound()); if (takedown) return ( @@ -111,6 +115,19 @@ export default async function Page({ > 查看原帖 + {savedAtLegacy ? ( + + 前往旧站 + + ) : ( + "" + )} 更新帖子 diff --git a/packages/viewer/src/app/[id]/page.tsx b/packages/viewer/src/app/[id]/page.tsx index 7b64435..e770586 100644 --- a/packages/viewer/src/app/[id]/page.tsx +++ b/packages/viewer/src/app/[id]/page.tsx @@ -1,12 +1,16 @@ -import { notFound } from "next/navigation"; +import { notFound, redirect } from "next/navigation"; import prisma from "@/lib/prisma"; import paginate from "@/lib/pagination"; import InfiniteScrollReplies from "@/components/replies/InfiniteScrollReplies"; +import { checkExists } from "@/lib/utils"; +import savedInLegacyList from "./saved-in-legacy.json"; const REPLIES_PER_PAGE = parseInt(process.env.REPLIES_PER_PAGE ?? "10", 10); export default async function Page({ params }: { params: { id: string } }) { const id = parseInt(params.id, 10); + const savedAtLegacy = checkExists(savedInLegacyList, id); + const { snapshots: [{ authorId }], _count: { replies }, @@ -21,7 +25,8 @@ export default async function Page({ params }: { params: { id: string } }) { }, _count: { select: { replies: true } }, }, - })) ?? notFound(); + })) ?? + (savedAtLegacy ? redirect(`https://legacy.lglg.top/${id}`) : notFound()); const numPages = Math.ceil(replies / REPLIES_PER_PAGE); const { pagesLocalAttachedFront, pagesLocalAttachedBack, pagesLocal } = paginate(numPages, 1); diff --git a/packages/viewer/src/app/[id]/saved-in-legacy.json b/packages/viewer/src/app/[id]/saved-in-legacy.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/packages/viewer/src/app/[id]/saved-in-legacy.json @@ -0,0 +1 @@ +[] diff --git a/packages/viewer/src/app/r/[rid]/get-reply-raw.ts b/packages/viewer/src/app/r/[rid]/get-reply-raw.ts index 5cabf92..3ffe1fb 100644 --- a/packages/viewer/src/app/r/[rid]/get-reply-raw.ts +++ b/packages/viewer/src/app/r/[rid]/get-reply-raw.ts @@ -1,9 +1,9 @@ -import { notFound } from "next/navigation"; +import { selectPost } from "@/lib/post"; import prisma from "@/lib/prisma"; import { selectReply } from "@/lib/reply"; export default async (id: number) => - (await prisma.reply.findUnique({ + prisma.reply.findUnique({ select: { ...selectReply.withLatestContent, ...selectReply.withTakedown, @@ -12,13 +12,10 @@ export default async (id: number) => post: { select: { id: true, - snapshots: { - select: { title: true, authorId: true }, - orderBy: { time: "desc" }, - take: 1, - }, + ...selectPost.withLatestSnapshotMeta, + ...selectPost.withTakedown, }, }, }, where: { id }, - })) ?? notFound(); + }); diff --git a/packages/viewer/src/app/r/[rid]/page.tsx b/packages/viewer/src/app/r/[rid]/page.tsx index 7b67b86..804db78 100644 --- a/packages/viewer/src/app/r/[rid]/page.tsx +++ b/packages/viewer/src/app/r/[rid]/page.tsx @@ -1,31 +1,59 @@ -// eslint-disable -// Not impl yet -import { notFound } from "next/navigation"; +import "@/components/markdown.css"; +import { notFound, redirect } from "next/navigation"; +import { checkExists } from "@/lib/utils"; import Link from "next/link"; import prisma from "@/lib/prisma"; -import "@/components/markdown.css"; import Content from "@/components/replies/Content"; import UserInfo from "@/components/UserInfo"; import UserAvatar from "@/components/UserAvatar"; -// import serializeReply from "@/lib/serialize-reply"; import stringifyTime from "@/lib/time"; import getReplyRaw from "./get-reply-raw"; +import savedInLegacyList from "../saved-in-legacy.json"; + +// import serializeReply from "@/lib/serialize-reply"; export const metadata = { title: "金玉良言 - 洛谷帖子保存站" }; const REPLIES_PER_PAGE = parseInt(process.env.REPLIES_PER_PAGE ?? "10", 10); export default async function Page({ params }: { params: { rid: string } }) { - // return <>抱歉,本功能暂未完成 TAT; const id = parseInt(params.rid, 10); if (Number.isNaN(id)) notFound(); const reply = await getReplyRaw(id); + if (!reply) { + if (checkExists(savedInLegacyList, id)) + redirect(`https://legacy.lglg.top/r/${id}`); + else notFound(); + } const pages = Math.ceil( (await prisma.reply.count({ where: { id: { lte: id }, postId: reply.post.id }, })) / REPLIES_PER_PAGE, ); - // return redirect(`/${discussionId}/${pages}#${params.rid}`); + + if (reply.post.takedown) { + return ( + <> +

{reply.post.takedown.reason}

+

+ 由于回复的帖子由 {" "} + 申请删除,本回复无法查看。 +

+ + ); + } + + if (reply.takedown) { + return ( + <> +

{reply.takedown.reason}

+

+ 由 申请删除。 +

+ + ); + } + return (
@@ -57,6 +85,17 @@ export default async function Page({ params }: { params: { rid: string } }) { >
+ {reply.snapshots[0].author.id === + reply.post.snapshots[0].author.id ? ( + + 楼主 + + ) : ( + "" + )} - - {content} - + + {content} + +
{/* {usersMetioned.map((user) => (
{ diff --git a/packages/viewer/src/lib/utils.ts b/packages/viewer/src/lib/utils.ts new file mode 100644 index 0000000..7cb84de --- /dev/null +++ b/packages/viewer/src/lib/utils.ts @@ -0,0 +1,37 @@ +/** + * 检查元素是否出现在给定的数组中。 + * + * @param arr **单调递增**的数组 + * @param target 需要查找的目标 + * @returns 目标是否在 arr 中 + */ +export function checkExists(arr: number[], target: number) { + let left = 0; + let right = arr.length - 1; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + + if (arr[mid] === target) { + return true; // 找到了目标元素,返回true + } + if (arr[mid] < target) { + left = mid + 1; // 目标在右侧 + } else { + right = mid - 1; // 目标在左侧 + } + } + + return false; +} + +/** + * 检查元素是否未出现在给定的数组中。 + * + * @param arr **单调递增**的数组 + * @param target 需要查找的目标 + * @returns 目标是否没有出现在 arr 中 + */ +export function checkNonExists(arr: number[], target: number) { + return !checkExists(arr, target); +}