diff --git a/public/locales/en/home.json b/public/locales/en/home.json
index 97a095a..65ed406 100644
--- a/public/locales/en/home.json
+++ b/public/locales/en/home.json
@@ -5,7 +5,7 @@
"bottom_text_nologin": "End of the page! Sign in to read more",
"nav": {
"all": "All",
- "newest": "Newest",
+ "newest": "Latest",
"monthly": "Monthly",
"yearly": "Yearly",
"featured": "Featured"
diff --git a/public/locales/en/periodical.json b/public/locales/en/periodical.json
index 2dae9a3..915c9fc 100644
--- a/public/locales/en/periodical.json
+++ b/public/locales/en/periodical.json
@@ -21,7 +21,10 @@
"page_next": "Next",
"category": {
"title": "HelloGitHub Monthly {{name}} Collection",
- "nav": "Category",
+ "nav": {
+ "active": "Active",
+ "last": "Default"
+ },
"p_text": "Here you can read past volumes of HelloGitHub Monthly by category. You are currently viewing the",
"p_text2": "collection."
},
diff --git a/public/locales/zh/periodical.json b/public/locales/zh/periodical.json
index 11ebafe..b8f3f96 100644
--- a/public/locales/zh/periodical.json
+++ b/public/locales/zh/periodical.json
@@ -21,7 +21,10 @@
"page_next": "下一页",
"category": {
"title": "《HelloGitHub 月刊》{{name}} 集合",
- "nav": "分类",
+ "nav": {
+ "active": "活跃",
+ "last": "默认"
+ },
"p_text": "这里是按照「分类」阅读往期的 HelloGitHub 月刊内容, 您目前在查看",
"p_text2": "集合。"
},
diff --git a/src/components/navbar/ArticleBar.tsx b/src/components/navbar/ArticleBar.tsx
index 7d10b2a..0806cbb 100644
--- a/src/components/navbar/ArticleBar.tsx
+++ b/src/components/navbar/ArticleBar.tsx
@@ -22,10 +22,10 @@ const ArticleNavbar = ({ t }: Props) => {
const linkClassName = (sortName: string) =>
classNames(
- 'flex items-center whitespace-nowrap rounded-lg px-2 py-1 text-xs hover:text-blue-500 dark:hover:bg-gray-700',
+ 'flex items-center whitespace-nowrap rounded-lg text-xs hover:text-blue-500',
{
- 'text-gray-500 dark:text-gray-200': sort_by !== sortName,
- 'dark:bg-gray-700 text-blue-500': sort_by === sortName,
+ 'text-gray-500 dark:text-gray-300': sort_by !== sortName,
+ 'text-blue-500': sort_by === sortName,
}
);
@@ -41,10 +41,11 @@ const ArticleNavbar = ({ t }: Props) => {
{t('nav.title')}
-
+
{t('nav.last')}
+
{t('nav.hot')}
diff --git a/src/components/navbar/CategoryBar.tsx b/src/components/navbar/CategoryBar.tsx
new file mode 100644
index 0000000..13ffacf
--- /dev/null
+++ b/src/components/navbar/CategoryBar.tsx
@@ -0,0 +1,70 @@
+import classNames from 'classnames';
+import { useRouter } from 'next/router';
+import { AiOutlineArrowLeft } from 'react-icons/ai';
+
+import { NoPrefetchLink } from '@/components/links/CustomLink';
+
+type Props = {
+ category: string;
+ middleText: string;
+ t: (key: string) => string;
+};
+
+const CategoryNavbar = ({ category, middleText, t }: Props) => {
+ const router = useRouter();
+ const { sort_by = 'last' } = router.query;
+
+ const goBack = () => {
+ if (window.history.length < 2) {
+ router.push('/');
+ } else {
+ router.back();
+ }
+ };
+
+ const linkClassName = (sortName: string) =>
+ classNames(
+ 'flex items-center whitespace-nowrap rounded-lg text-xs hover:text-blue-500',
+ {
+ 'text-gray-500 dark:text-gray-300': sort_by !== sortName,
+ 'text-blue-500': sort_by === sortName,
+ }
+ );
+
+ return (
+
+ );
+};
+
+export default CategoryNavbar;
diff --git a/src/components/periodical/item.tsx b/src/components/periodical/item.tsx
index 788598a..c510455 100644
--- a/src/components/periodical/item.tsx
+++ b/src/components/periodical/item.tsx
@@ -1,6 +1,6 @@
import { NextPage } from 'next';
import { useTranslation } from 'next-i18next';
-import { GoClock, GoRepoForked } from 'react-icons/go';
+import { GoCalendar, GoClock, GoRepoForked } from 'react-icons/go';
import { IoIosStarOutline } from 'react-icons/io';
import { CustomLink, NoPrefetchLink } from '@/components/links/CustomLink';
@@ -15,6 +15,35 @@ import { MDRender } from '../mdRender/MDRender';
import { PeriodicalItem, PeriodicalItemProps } from '@/types/periodical';
+const InfoItem = ({
+ icon: Icon,
+ text,
+ link,
+ className = '',
+}: {
+ icon: React.ElementType;
+ text: string | number;
+ link?: string;
+ className?: string;
+}) => {
+ const content = (
+
+
+ {text}
+
+ );
+
+ if (link) {
+ return (
+
+ {content}
+
+ );
+ }
+
+ return content;
+};
+
const PeriodItem: NextPage
= ({ item, index }) => {
const { t, i18n } = useTranslation('periodical');
@@ -31,7 +60,7 @@ const PeriodItem: NextPage = ({ item, index }) => {
onClickLink(item)}
- className='truncate text-ellipsis text-xl capitalize text-blue-500 hover:underline active:text-blue-500'
+ className='truncate text-ellipsis text-xl text-blue-500 hover:underline active:text-blue-500'
>
{item.name}
@@ -39,18 +68,26 @@ const PeriodItem: NextPage = ({ item, index }) => {
{/* stars forks watch */}
-
-
- Star {numFormat(item.stars, 1)}
-
-
-
- Fork {numFormat(item.forks, 1)}
-
-
-
- {fromNow(item.publish_at, i18n.language)}
-
+
+
+ {item.updated_at && (
+
+ )}
+
diff --git a/src/pages/periodical/category/[name].tsx b/src/pages/periodical/category/[name].tsx
index 419fd97..7aab5ca 100644
--- a/src/pages/periodical/category/[name].tsx
+++ b/src/pages/periodical/category/[name].tsx
@@ -4,7 +4,7 @@ import { Trans, useTranslation } from 'next-i18next';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { useMemo } from 'react';
-import Navbar from '@/components/navbar/Navbar';
+import CategoryNavbar from '@/components/navbar/CategoryBar';
import Pagination from '@/components/pagination/Pagination';
import PeriodItem from '@/components/periodical/item';
import Seo from '@/components/Seo';
@@ -12,6 +12,7 @@ import ToTop from '@/components/toTop/ToTop';
import { getCategory } from '@/services/category';
import { nameMap } from '@/utils/constants';
+import stringify from '@/utils/qs-stringify';
import { getClientIP } from '@/utils/util';
import {
@@ -20,7 +21,10 @@ import {
PeriodicalItem,
} from '@/types/periodical';
-const PeriodicalCategoryPage: NextPage
= ({ category }) => {
+const PeriodicalCategoryPage: NextPage = ({
+ category,
+ sortBy,
+}) => {
const { t, i18n } = useTranslation('periodical');
const router = useRouter();
@@ -45,9 +49,13 @@ const PeriodicalCategoryPage: NextPage = ({ category }) => {
const onPageChange = (page: number) => {
const name = category?.category_name;
- router.push(
- `/periodical/category/${encodeURIComponent(name)}?page=${page}`
- );
+ const nextURL = `/periodical/category/${encodeURIComponent(
+ name
+ )}?${stringify({
+ page: page,
+ sort_by: sortBy ? sortBy : null,
+ })}`;
+ router.push(nextURL);
};
if (router.isFallback) {
@@ -55,8 +63,7 @@ const PeriodicalCategoryPage: NextPage = ({ category }) => {
-
-
+
@@ -72,8 +79,11 @@ const PeriodicalCategoryPage: NextPage = ({ category }) => {
<>
-
-
+
@@ -122,10 +132,12 @@ export const getServerSideProps: GetServerSideProps = async ({
}) => {
const ip = getClientIP(req);
const name = query['name'] as string;
+ const sortBy = query['sort_by']?.toString() ?? null;
const data = await getCategory(
ip,
- encodeURIComponent(name),
- query['page'] as unknown as number
+ name,
+ query['page'] as unknown as number,
+ sortBy
);
if (!data.success) {
return {
@@ -135,6 +147,7 @@ export const getServerSideProps: GetServerSideProps = async ({
return {
props: {
category: data,
+ sortBy: sortBy,
...(await serverSideTranslations(locale as string, [
'common',
'periodical',
diff --git a/src/services/category.ts b/src/services/category.ts
index d8e996c..fe65611 100644
--- a/src/services/category.ts
+++ b/src/services/category.ts
@@ -7,18 +7,21 @@ import { Category } from '@/types/periodical';
export const getCategory = async (
ip: string,
name: string,
- page: number
+ page: number,
+ sortBy: string | null
): Promise => {
- const req: RequestInit = {};
- req.headers = { 'x-real-ip': ip, 'x-forwarded-for': ip };
+ const req: RequestInit = {
+ headers: {
+ 'x-real-ip': ip,
+ 'x-forwarded-for': ip,
+ },
+ };
try {
- let url;
- if (page > 1) {
- url = makeUrl(`/periodical/category/${name}?page=${page}`);
- } else {
- url = makeUrl(`/periodical/category/${name}`);
- }
+ const url = makeUrl(`/periodical/category/${encodeURIComponent(name)}`, {
+ page: page > 1 ? page : null, // 仅当 page > 1 时添加该参数
+ sort_by: sortBy ? sortBy : null,
+ });
const data = await fetcher(url, req);
return data;
} catch (error) {
diff --git a/src/types/periodical.tsx b/src/types/periodical.tsx
index c0d2be8..60564fd 100644
--- a/src/types/periodical.tsx
+++ b/src/types/periodical.tsx
@@ -30,7 +30,9 @@ export interface PeriodicalItem {
watch: number;
image_url: string | null;
vote_total: number;
+ volume_num: number;
publish_at: string;
+ updated_at: string;
}
export interface PeriodicalItemProps {
@@ -54,6 +56,7 @@ export type VolumeAll = {
export interface CategoryPageProps {
category: Category;
+ sortBy: string | null;
}
export interface Category {