From b37277efbcef9b56bafea2bf79a773b9dbb4ff06 Mon Sep 17 00:00:00 2001 From: Enok <416828041@qq.com> Date: Sun, 15 Mar 2020 18:17:45 +0800 Subject: [PATCH] filter topics --- src/common/base-page.ts | 5 ++++- src/common/data-provider/prefetch.ts | 5 +++-- src/common/format.ts | 10 ++++++++++ src/common/route-utli.ts | 17 +++++++++++++++-- src/entry/server.tsx | 10 +++++++--- src/pages/Detail/header.tsx | 4 ++-- src/pages/Index/index.tsx | 28 ++++++++++++---------------- src/pages/Index/topic.tsx | 7 ++++--- src/pages/User/index.tsx | 22 ++++++++++++---------- src/pages/detail/header.tsx | 4 ++-- src/pages/index/helper.ts | 15 +++++++++++++++ src/pages/index/index.tsx | 28 ++++++++++++---------------- src/pages/index/topic.tsx | 7 ++++--- src/pages/user/index.tsx | 22 ++++++++++++---------- 14 files changed, 114 insertions(+), 70 deletions(-) create mode 100644 src/pages/index/helper.ts diff --git a/src/common/base-page.ts b/src/common/base-page.ts index dd9d8a4..e47e751 100644 --- a/src/common/base-page.ts +++ b/src/common/base-page.ts @@ -3,5 +3,8 @@ import { match } from "react-router"; export interface BasePage { page: FunctionComponent; - prefetch?(match: match): Promise | undefined>; + prefetch?( + match: match, + search?: string + ): Promise | undefined>; } diff --git a/src/common/data-provider/prefetch.ts b/src/common/data-provider/prefetch.ts index 98238dd..5dc02ea 100644 --- a/src/common/data-provider/prefetch.ts +++ b/src/common/data-provider/prefetch.ts @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import { useRouteMatch } from "react-router"; +import { useRouteMatch, useLocation } from "react-router"; import { BasePage } from "../base-page"; let restore_state = (window as any)["__INIT_STATE__"]; @@ -10,12 +10,13 @@ export function setPrefetchState(state: any) { export function usePrefetchData(page: BasePage): Partial { const match = useRouteMatch(); + const location = useLocation(); const [data, setData] = useState | undefined>(restore_state); useEffect(() => { (async () => { if (!restore_state && page.prefetch) { - const state = await page.prefetch(match); + const state = await page.prefetch(match, location.search); setData(state); } else { restore_state = undefined; diff --git a/src/common/format.ts b/src/common/format.ts index 1bf1c26..f373c9b 100644 --- a/src/common/format.ts +++ b/src/common/format.ts @@ -1,4 +1,9 @@ import dayjs from "dayjs"; +import "dayjs/locale/zh-cn"; +import relativeTime from "dayjs/plugin/relativeTime"; + +dayjs.extend(relativeTime); +dayjs.locale("zh-cn"); const DATE_FORMAT = "YYYY-MM-DD HH:mm:ss"; @@ -6,3 +11,8 @@ export function formatDate(date?: string): string { if (!date) return ""; return dayjs(date).format(DATE_FORMAT); } + +export function formatFromNow(date?: string): string { + if (!date) return ""; + return dayjs(date).fromNow(); +} diff --git a/src/common/route-utli.ts b/src/common/route-utli.ts index dcd0a9c..28af826 100644 --- a/src/common/route-utli.ts +++ b/src/common/route-utli.ts @@ -14,14 +14,27 @@ export function findRoute(url: string): MatchRouteInfo | undefined { } } -export async function prefetch(routeInfo?: MatchRouteInfo): Promise { +export async function prefetch( + routeInfo?: MatchRouteInfo, + search?: string +): Promise { let state = {}; if (routeInfo) { const { route, match } = routeInfo; const prefetcher = route.page?.prefetch; if (prefetcher) { - state = (await prefetcher(match)) || {}; + state = (await prefetcher(match, search)) || {}; } } return state; } + +export function getAllSearchParams(search?: string): any { + if (!search) return {}; + const params = new URLSearchParams(search); + const paramsObject: any = {}; + for (const key of params.keys()) { + paramsObject[key] = params.get(key); + } + return paramsObject; +} diff --git a/src/entry/server.tsx b/src/entry/server.tsx index e624f11..a3c71c5 100644 --- a/src/entry/server.tsx +++ b/src/entry/server.tsx @@ -9,18 +9,22 @@ import { findRoute, prefetch } from "../common/route-utli"; globalThis.React = React; interface RenderProps { - url?: string; + params: { url?: string; search?: string }; api_base: string; data: Object; } export default async function render(props: RenderProps) { - const { url = "/", api_base = "", data } = props; + const { + params: { url = "/", search }, + api_base = "", + data + } = props; GlobalData.apiBase = api_base; let routeInfo = findRoute(url); - let state = { ...data, ...(await prefetch(routeInfo)) }; + let state = { ...data, ...(await prefetch(routeInfo, search)) }; setPrefetchState(state); diff --git a/src/pages/Detail/header.tsx b/src/pages/Detail/header.tsx index 6c7c368..a9561e5 100644 --- a/src/pages/Detail/header.tsx +++ b/src/pages/Detail/header.tsx @@ -9,7 +9,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import React from "react"; import { Link } from "react-router-dom"; import { useUserData } from "../../common/data-provider/user"; -import { formatDate } from "../../common/format"; +import { formatFromNow } from "../../common/format"; import Topic from "../../model/topic"; interface DetailHeaderProps { @@ -36,7 +36,7 @@ export default function DetailHeader(props: DetailHeaderProps) { {topic.is_good && 精华} - 发布于 {formatDate(topic.created_at)} + 发布于 {formatFromNow(topic.created_at)} diff --git a/src/pages/Index/index.tsx b/src/pages/Index/index.tsx index ba4ca42..8671704 100644 --- a/src/pages/Index/index.tsx +++ b/src/pages/Index/index.tsx @@ -1,8 +1,8 @@ import React from "react"; -import { Link, match, useHistory } from "react-router-dom"; +import { Link, useHistory } from "react-router-dom"; import { BasePage } from "../../common/base-page"; import { usePrefetchData } from "../../common/data-provider/prefetch"; -import GlobalData from "../../common/global"; +import { getAllSearchParams } from "../../common/route-utli"; import BasePanel from "../../components/base-panel"; import DefaultLayout from "../../components/layouts/DefaultLayout"; import Pagination from "../../components/pagination"; @@ -10,6 +10,7 @@ import FriendsLinkPanel from "../../components/panels/friends-link"; import LoginUserPanel from "../../components/panels/login-user"; import QQGroupPanel from "../../components/panels/qq-group"; import Topic from "../../model/topic"; +import { getTopics } from "./helper"; import "./index.less"; import TopicItem from "./topic"; @@ -30,18 +31,13 @@ interface IndexProps { } const Index: BasePage = { - async prefetch( - match: match<{ - type?: string; - page?: string; - pageSize?: string; - }> - ) { - const { type = "all", page = "0", pageSize = "10" } = match.params; - const { - data: { list: topics = [], total } - } = await fetch(`${GlobalData.apiBase}/api/topic/${type}`).then(res => - res.json() + async prefetch(_, search) { + const params = getAllSearchParams(search); + const { type = "all", page = "0", pageSize = "10" } = params; + const { topics, total } = await getTopics( + type, + parseInt(page), + parseInt(pageSize) ); return { @@ -79,14 +75,14 @@ const Index: BasePage = { header={
{types.map(item => ( - + {item.title} - + ))}
} diff --git a/src/pages/Index/topic.tsx b/src/pages/Index/topic.tsx index 1e4ff79..8aa9300 100644 --- a/src/pages/Index/topic.tsx +++ b/src/pages/Index/topic.tsx @@ -6,6 +6,7 @@ import { import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import React from "react"; import { Link } from "react-router-dom"; +import { formatFromNow } from "../../common/format"; import Topic from "../../model/topic"; interface TopicItemProps { @@ -46,13 +47,13 @@ export default function Topic(props: TopicItemProps) { ) : ( <> - - {/* {topic.user_nick_name} */} + + {topic.author?.nick_name} 发布于 - {topic.created_at} + {formatFromNow(topic.created_at)} )} diff --git a/src/pages/User/index.tsx b/src/pages/User/index.tsx index 2423898..c55cc1a 100644 --- a/src/pages/User/index.tsx +++ b/src/pages/User/index.tsx @@ -2,15 +2,17 @@ import dayjs from "dayjs"; import React from "react"; import { match } from "react-router"; import { BasePage } from "../../common/base-page"; +import { usePrefetchData } from "../../common/data-provider/prefetch"; import GlobalData from "../../common/global"; import BasePanel from "../../components/base-panel"; import DefaultLayout from "../../components/layouts/DefaultLayout"; import FriendsLinkPanel from "../../components/panels/friends-link"; import QQGroupPanel from "../../components/panels/qq-group"; +import UserModel from "../../model/user"; import "./index.less"; const User: BasePage<{ - user: any; + user: UserModel; }> = { async prefetch(match: match<{ id: string }>) { const id = match.params.id; @@ -19,8 +21,8 @@ const User: BasePage<{ ).then(res => res.json()); return { user: data }; }, - page(props) { - const { user = {} } = props; + page() { + const { user } = usePrefetchData(User); return (
注册于: - {dayjs(user.created_at).format("YYYY-MM-DD HH:mm:ss")} + {dayjs(user?.created_at).format("YYYY-MM-DD HH:mm:ss")}
- {user.name} + {user?.name}
- {user.nick_name} + {user?.nick_name} - {user.name} + {user?.name}
  • 积分
    - {user.score} + {user?.score}
  • 主题
    - {user.topic_count || 0} + {0}
diff --git a/src/pages/detail/header.tsx b/src/pages/detail/header.tsx index 6c7c368..a9561e5 100644 --- a/src/pages/detail/header.tsx +++ b/src/pages/detail/header.tsx @@ -9,7 +9,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import React from "react"; import { Link } from "react-router-dom"; import { useUserData } from "../../common/data-provider/user"; -import { formatDate } from "../../common/format"; +import { formatFromNow } from "../../common/format"; import Topic from "../../model/topic"; interface DetailHeaderProps { @@ -36,7 +36,7 @@ export default function DetailHeader(props: DetailHeaderProps) { {topic.is_good && 精华} - 发布于 {formatDate(topic.created_at)} + 发布于 {formatFromNow(topic.created_at)} diff --git a/src/pages/index/helper.ts b/src/pages/index/helper.ts new file mode 100644 index 0000000..b069c3d --- /dev/null +++ b/src/pages/index/helper.ts @@ -0,0 +1,15 @@ +import GlobalData from "../../common/global"; + +export async function getTopics( + type: string, + page: number = 1, + pageSize: number = 10 +) { + const { + data: { list: topics = [], total } + } = await fetch(`${GlobalData.apiBase}/api/topic/${type}`).then(res => + res.json() + ); + + return { topics, total, page, pageSize }; +} diff --git a/src/pages/index/index.tsx b/src/pages/index/index.tsx index ba4ca42..8671704 100644 --- a/src/pages/index/index.tsx +++ b/src/pages/index/index.tsx @@ -1,8 +1,8 @@ import React from "react"; -import { Link, match, useHistory } from "react-router-dom"; +import { Link, useHistory } from "react-router-dom"; import { BasePage } from "../../common/base-page"; import { usePrefetchData } from "../../common/data-provider/prefetch"; -import GlobalData from "../../common/global"; +import { getAllSearchParams } from "../../common/route-utli"; import BasePanel from "../../components/base-panel"; import DefaultLayout from "../../components/layouts/DefaultLayout"; import Pagination from "../../components/pagination"; @@ -10,6 +10,7 @@ import FriendsLinkPanel from "../../components/panels/friends-link"; import LoginUserPanel from "../../components/panels/login-user"; import QQGroupPanel from "../../components/panels/qq-group"; import Topic from "../../model/topic"; +import { getTopics } from "./helper"; import "./index.less"; import TopicItem from "./topic"; @@ -30,18 +31,13 @@ interface IndexProps { } const Index: BasePage = { - async prefetch( - match: match<{ - type?: string; - page?: string; - pageSize?: string; - }> - ) { - const { type = "all", page = "0", pageSize = "10" } = match.params; - const { - data: { list: topics = [], total } - } = await fetch(`${GlobalData.apiBase}/api/topic/${type}`).then(res => - res.json() + async prefetch(_, search) { + const params = getAllSearchParams(search); + const { type = "all", page = "0", pageSize = "10" } = params; + const { topics, total } = await getTopics( + type, + parseInt(page), + parseInt(pageSize) ); return { @@ -79,14 +75,14 @@ const Index: BasePage = { header={
{types.map(item => ( - + {item.title} - + ))}
} diff --git a/src/pages/index/topic.tsx b/src/pages/index/topic.tsx index 1e4ff79..8aa9300 100644 --- a/src/pages/index/topic.tsx +++ b/src/pages/index/topic.tsx @@ -6,6 +6,7 @@ import { import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import React from "react"; import { Link } from "react-router-dom"; +import { formatFromNow } from "../../common/format"; import Topic from "../../model/topic"; interface TopicItemProps { @@ -46,13 +47,13 @@ export default function Topic(props: TopicItemProps) { ) : ( <> - - {/* {topic.user_nick_name} */} + + {topic.author?.nick_name} 发布于 - {topic.created_at} + {formatFromNow(topic.created_at)} )} diff --git a/src/pages/user/index.tsx b/src/pages/user/index.tsx index 2423898..c55cc1a 100644 --- a/src/pages/user/index.tsx +++ b/src/pages/user/index.tsx @@ -2,15 +2,17 @@ import dayjs from "dayjs"; import React from "react"; import { match } from "react-router"; import { BasePage } from "../../common/base-page"; +import { usePrefetchData } from "../../common/data-provider/prefetch"; import GlobalData from "../../common/global"; import BasePanel from "../../components/base-panel"; import DefaultLayout from "../../components/layouts/DefaultLayout"; import FriendsLinkPanel from "../../components/panels/friends-link"; import QQGroupPanel from "../../components/panels/qq-group"; +import UserModel from "../../model/user"; import "./index.less"; const User: BasePage<{ - user: any; + user: UserModel; }> = { async prefetch(match: match<{ id: string }>) { const id = match.params.id; @@ -19,8 +21,8 @@ const User: BasePage<{ ).then(res => res.json()); return { user: data }; }, - page(props) { - const { user = {} } = props; + page() { + const { user } = usePrefetchData(User); return (
注册于: - {dayjs(user.created_at).format("YYYY-MM-DD HH:mm:ss")} + {dayjs(user?.created_at).format("YYYY-MM-DD HH:mm:ss")}
- {user.name} + {user?.name}
- {user.nick_name} + {user?.nick_name} - {user.name} + {user?.name}
  • 积分
    - {user.score} + {user?.score}
  • 主题
    - {user.topic_count || 0} + {0}