mirror of
https://github.com/snowykami/neo-blog.git
synced 2025-09-06 01:06:22 +00:00
⚡️ feat: refactor sorting parameters in post listing API and components
- Renamed `orderedBy` to `orderBy` and `reverse` to `desc` in ListPostsParams interface and related functions. - Updated all usages of the sorting parameters in the post listing logic to reflect the new naming convention. feat: add user-related API functions - Implemented `getLoginUser` and `getUserById` functions in the user API to fetch user details. - Enhanced user model to include `language` property. feat: integrate next-intl for internationalization - Added `next-intl` plugin to Next.js configuration for improved localization support. - Removed previous i18n implementation and replaced it with a new structure using JSON files for translations. - Created locale files for English, Japanese, and Chinese with basic translations. - Implemented a request configuration to handle user locales and messages dynamically. fix: clean up unused imports and code - Removed unused i18n utility functions and language settings from device context. - Cleaned up commented-out code in blog card component and sidebar. chore: update dependencies - Added `deepmerge` for merging locale messages. - Updated package.json and pnpm-lock.yaml to reflect new dependencies.
This commit is contained in:
@ -3,7 +3,7 @@ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle }
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { Calendar, Eye, Heart, MessageCircle, Lock } from "lucide-react";
|
||||
import { Calendar, Eye, Heart, MessageCircle, Lock } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import config from "@/config";
|
||||
|
||||
@ -23,27 +23,7 @@ export function BlogCard({ post, className }: BlogCardProps) {
|
||||
});
|
||||
};
|
||||
|
||||
// 计算阅读时间(估算)
|
||||
// const getReadingTime = (content: string) => {
|
||||
// const wordsPerMinute = 200;
|
||||
// const wordCount = content.length;
|
||||
// const minutes = Math.ceil(wordCount / wordsPerMinute);
|
||||
// return `${minutes} 分钟阅读`;
|
||||
// };
|
||||
|
||||
// // 根据内容类型获取图标
|
||||
// const getContentTypeIcon = (type: Post['type']) => {
|
||||
// switch (type) {
|
||||
// case 'markdown':
|
||||
// return '📝';
|
||||
// case 'html':
|
||||
// return '🌐';
|
||||
// case 'text':
|
||||
// return '📄';
|
||||
// default:
|
||||
// return '📝';
|
||||
// }
|
||||
// };
|
||||
// TODO: 阅读时间估计
|
||||
|
||||
return (
|
||||
<Card className={cn(
|
||||
@ -131,7 +111,7 @@ export function BlogCard({ post, className }: BlogCardProps) {
|
||||
<CardTitle className="line-clamp-2 group-hover:text-primary transition-colors text-lg leading-tight">
|
||||
{post.title}
|
||||
</CardTitle>
|
||||
|
||||
|
||||
</CardHeader>
|
||||
{/* Card Content - 主要内容 */}
|
||||
<CardContent className="flex-1">
|
||||
|
@ -5,8 +5,8 @@ import { Badge } from "@/components/ui/badge";
|
||||
import type { Label } from "@/models/label";
|
||||
import type { Post } from "@/models/post";
|
||||
import type configType from '@/config';
|
||||
import { t } from "i18next";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
// 侧边栏父组件,接收卡片组件列表
|
||||
export default function Sidebar({ cards }: { cards: React.ReactNode[] }) {
|
||||
@ -115,10 +115,11 @@ export function SidebarIframe(props?: { src?: string; scriptSrc?: string; title?
|
||||
title = "External Content",
|
||||
height = "400px",
|
||||
} = props || {};
|
||||
const t = useTranslations('HomePage');
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>{t(title)}</CardTitle>
|
||||
<CardTitle>{t("title")}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="p-0">
|
||||
<iframe
|
||||
|
@ -30,28 +30,28 @@ export default function BlogHome() {
|
||||
const fetchPosts = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
let orderedBy: string;
|
||||
let reverse: boolean;
|
||||
let orderBy: string;
|
||||
let desc: boolean;
|
||||
switch (sortType) {
|
||||
case 'latest':
|
||||
orderedBy = 'updated_at';
|
||||
reverse = false;
|
||||
orderBy = 'updated_at';
|
||||
desc = true;
|
||||
break;
|
||||
case 'popular':
|
||||
orderedBy = 'heat';
|
||||
reverse = false;
|
||||
orderBy = 'heat';
|
||||
desc = true;
|
||||
break;
|
||||
default:
|
||||
orderedBy = 'updated_at';
|
||||
reverse = false;
|
||||
orderBy = 'updated_at';
|
||||
desc = true;
|
||||
}
|
||||
// 处理关键词,空格分割转逗号
|
||||
const keywords = debouncedSearch.trim() ? debouncedSearch.trim().split(/\s+/).join(",") : undefined;
|
||||
const data = await listPosts({
|
||||
page: 1,
|
||||
size: 10,
|
||||
orderedBy,
|
||||
reverse,
|
||||
orderBy: orderBy,
|
||||
desc: desc,
|
||||
keywords
|
||||
});
|
||||
setPosts(data.data);
|
||||
|
0
web/src/components/sidebar.tsx
Normal file
0
web/src/components/sidebar.tsx
Normal file
Reference in New Issue
Block a user