Skip to content

Commit 855e4d5

Browse files
committed
feat: list
1 parent a2a8914 commit 855e4d5

File tree

10 files changed

+75
-508
lines changed

10 files changed

+75
-508
lines changed

markdown/index.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
{
33
"path": "yyblog.md",
44
"title": "yyblog",
5-
"tag": "技术/react"
5+
"tag": "技术/react",
6+
"coverImage": "yyblog-cover.jpg"
67
},
78
{
89
"path": "react19.md",
910
"title": "react19",
10-
"tag": "随笔/生活"
11+
"tag": "随笔/生活",
12+
"coverImage": "yyblog-cover.jpg"
1113
}
1214
]

next.config.mjs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
/** @type {import('next').NextConfig} */
22
import NextBundleAnalyzer from '@next/bundle-analyzer';
3-
import { type } from 'os';
43

54
let nextConfig = {
65
images: {
7-
domains: ['innei.in', 'images.unsplash.com', 'assets.aceternity.com'],
86
remotePatterns: [
97
{
108
protocol: 'https',
@@ -16,10 +14,11 @@ let nextConfig = {
1614
},
1715
],
1816
},
17+
// type: 'asset/source' 会让 Webpack 将文件内容直接作为字符串导出,而不是生成特定的资源文件路径。这种方式特别适用于将 Markdown、SVG、文本文件等直接导入为字符串内容的场景。
1918
webpack(config) {
2019
config.module.rules.push({
2120
test: /\.md$/,
22-
use: 'raw-loader',
21+
// use: 'raw-loader',
2322
type: 'asset/source',
2423
});
2524

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@
2929
"clsx": "^2.1.1",
3030
"colorjs.io": "^0.5.2",
3131
"daisyui": "^4.12.13",
32+
"dayjs": "^1.11.13",
3233
"framer-motion": "11.11.1",
3334
"markdown-to-jsx": "npm:@innei/[email protected]",
3435
"next": "14.2.15",
3536
"next-themes": "^0.3.0",
3637
"pngjs": "^7.0.0",
3738
"postcss-js": "^4.0.1",
3839
"prettier": "3.3.2",
39-
"raw-loader": "^4.0.2",
4040
"react": "^18",
4141
"react-dom": "^18",
4242
"shiki": "^1.22.2",

pnpm-lock.yaml

Lines changed: 8 additions & 470 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/(app)/list/AnimatedPostItem.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@ import React from 'react';
55
import { m } from 'framer-motion';
66

77
import { PostItem } from '@/components/modules/list/PostItem';
8+
import type { PostItem as PostItemType } from '@/core';
89

910
interface AnimatedPostItemProps {
10-
item: {
11-
id: number;
12-
title: string;
13-
content: string;
14-
};
11+
item: PostItemType;
1512
index: number;
1613
}
1714

@@ -29,7 +26,7 @@ const AnimatedPostItem: React.FC<AnimatedPostItemProps> = ({ item, index }) => {
2926
stiffness: 100,
3027
},
3128
}}
32-
key={item.id}
29+
key={item.path}
3330
>
3431
<PostItem data={item} />
3532
</m.li>

src/app/(app)/list/page.tsx

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,14 @@ import AnimatedPostItem from './AnimatedPostItem';
55
import { NormalContainer } from '@/components/layout/container/Normal';
66
import { buildPostData } from '@/core';
77

8-
// 假数据
9-
const mockData = [
10-
{ id: 1, title: '文章标题 1', content: '这是文章内容 1' },
11-
{ id: 2, title: '文章标题 2', content: '这是文章内容 2' },
12-
{ id: 3, title: '文章标题 3', content: '这是文章内容 3' },
13-
{ id: 12, title: '文章标题 1', content: '这是文章内容 1' },
14-
{ id: 22, title: '文章标题 2', content: '这是文章内容 2' },
15-
{ id: 32, title: '文章标题 3', content: '这是文章内容 3' },
16-
// 更多假数据
17-
];
18-
198
const ArticleList: React.FC = () => {
20-
console.log(buildPostData());
9+
const { postDataList } = buildPostData();
2110

2211
return (
2312
<NormalContainer>
2413
<ul>
25-
{mockData.map((item, index) => (
26-
<AnimatedPostItem key={item.id} item={item} index={index} />
14+
{postDataList.map((item, index) => (
15+
<AnimatedPostItem key={item.path} item={item} index={index} />
2716
))}
2817
</ul>
2918
</NormalContainer>

src/components/modules/list/PostItem.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,28 @@ import { memo } from 'react';
33

44
import { PostItemHoverOverlay } from './PostItemHoverOverlay';
55

6+
import dayjs from '@/lib/dayjs';
67
import { MdiClockOutline } from '@/components/icons/clock';
78
import { FeHash } from '@/components/icons/fa-hash';
9+
import type { PostItem as PostItemType } from '@/core';
810

9-
export const PostItem = memo<{ data: any }>(function PostItem({ data }) {
10-
const categorySlug = data.category?.slug;
11-
const postLink = `/posts/${categorySlug}/${data.slug}`;
11+
export const PostItem = memo<{ data: PostItemType }>(function PostItem({ data }) {
12+
const postLink = `/notes/${data.path}`;
1213

1314
return (
14-
<Link href={postLink} className="relative flex flex-col py-8 focus-visible:!shadow-none">
15+
<Link href={postLink} className="relative flex flex-col py-8 focus-visible:!shadow-none gap-2">
1516
<PostItemHoverOverlay />
1617
<h2 className="relative text-balance break-words text-2xl font-medium">{data.title}</h2>
1718

1819
<div className="post-meta-bar mt-2 flex select-none flex-wrap items-center justify-start gap-8 text-base-content/60">
1920
<span className=" flex min-w-0 items-center space-x-1 text-sm">
2021
<MdiClockOutline />
21-
<p>2024 年 6 月 4 日 星期二</p>
22+
{data.createdAt ? dayjs(data.createdAt).format('YYYY 年 M 月 D 日') : '1999 年 9 月 9 日'}
23+
{data.updatedAt && <>&nbsp;&nbsp;(已编辑)</>}
2224
</span>
2325
<span className="flex min-w-0 items-center space-x-1 text-sm">
2426
<FeHash className="translate-y-[0.5px]" />
25-
<p>技术/react</p>
27+
<p>{data.tag}</p>
2628
</span>
2729
</div>
2830
</Link>

src/core/index.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import jsonData from '@md/index.json';
22
import { join } from 'node:path';
33

44
import { symbolsTime, symbolsCount } from '@/lib/count';
5-
import { getLastGitUpdateTime } from '@/lib/git';
5+
import { getFirstGitCommitTime, getLastGitUpdateTime } from '@/lib/git';
66

77
export type PostItem = {
88
path: string;
@@ -13,12 +13,16 @@ export type PostItem = {
1313
title: string;
1414
tag: string;
1515
updatedAt: Date | null;
16+
createdAt: Date | null;
17+
modified: boolean;
18+
coverImage: string;
1619
};
1720

1821
export type PostJsonType = {
1922
path: string;
2023
title: string;
2124
tag: string;
25+
coverImage: string;
2226
};
2327
export type PostMap = Record<string, PostItem>;
2428

@@ -40,12 +44,21 @@ export function buildPostData() {
4044
itemInfo.tag = item.tag;
4145
itemInfo.path = item.path.replace('.md', '');
4246
itemInfo.rawFilePath = `./${item.path}`;
47+
itemInfo.coverImage = item.coverImage.startsWith('http')
48+
? item.coverImage
49+
: `/postCoverImage/${item.coverImage}`;
4350

4451
itemInfo.text = file;
4552
itemInfo.count = symbolsCount(file);
4653
itemInfo.readingTime = symbolsTime(file, 0, 200);
4754
itemInfo.updatedAt = getLastGitUpdateTime(join('markdown/', item.path));
48-
console.log(itemInfo);
55+
itemInfo.createdAt = getFirstGitCommitTime(join('markdown/', item.path));
56+
57+
itemInfo.modified =
58+
itemInfo.updatedAt && itemInfo.createdAt
59+
? itemInfo.updatedAt.getTime() !== itemInfo.createdAt.getTime()
60+
: false;
61+
4962
postDataMap[itemInfo.path] = itemInfo;
5063
postDataList.push(itemInfo);
5164
}
@@ -54,5 +67,13 @@ export function buildPostData() {
5467
processPostItem(postJsonItem);
5568
});
5669

70+
postDataList.sort((a, b) => {
71+
if (a.createdAt && b.createdAt) {
72+
return b.createdAt.getTime() - a.createdAt.getTime();
73+
}
74+
75+
return 0;
76+
});
77+
5778
return { postDataMap, postDataList };
5879
}

src/lib/dayjs.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import dayjs from 'dayjs';
2+
import 'dayjs/locale/zh-cn';
3+
4+
dayjs.locale('zh-cn');
5+
6+
export default dayjs;

src/lib/git.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,34 @@ import { execSync } from 'node:child_process';
22

33
export function getLastGitUpdateTime(filePath: string): Date | null {
44
try {
5-
// 执行 git log 命令获取最后一次提交的日期
65
const command = `git log -1 --format="%ai" -- "${filePath}"`;
76
const stdout = execSync(command).toString().trim();
8-
// 如果没有获取到日期,则返回 null
97

108
if (!stdout) {
119
return null;
1210
}
13-
// 将获取到的日期字符串转换为 Date 对象
1411

1512
return new Date(stdout);
1613
} catch (error) {
17-
// 如果执行命令时出错(例如,文件未被跟踪或路径无效),返回 null
1814
console.error('Error fetching git commit time:', error);
1915

2016
return null;
2117
}
2218
}
19+
20+
export function getFirstGitCommitTime(filePath: string): Date | null {
21+
try {
22+
const command = `git log --reverse -1 --format="%ai" -- "${filePath}"`;
23+
const stdout = execSync(command).toString().trim();
24+
25+
if (!stdout) {
26+
return null;
27+
}
28+
29+
return new Date(stdout);
30+
} catch (error) {
31+
console.error('Error fetching git first commit time:', error);
32+
33+
return null;
34+
}
35+
}

0 commit comments

Comments
 (0)