From e94fae7ca410b0bf097c6dff895395d82e70daa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E9=98=B3?= Date: Sat, 13 Sep 2025 20:14:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=85=B3=E4=BA=8E=E6=88=91?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E7=9A=84=E6=8A=80=E6=9C=AF=E6=A0=88=E5=AE=B9?= =?UTF-8?q?=E5=99=A8=EF=BC=8C=E9=87=8D=E5=91=BD=E5=90=8D=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E6=95=B0=E6=8D=AE=E7=9A=84=20API=20=E4=B8=BA?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E4=BD=9C=E8=80=85=E6=95=B0=E6=8D=AE=EF=BC=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=9C=8B=E5=8F=8B=E5=9C=88=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E7=9A=84=E7=BB=84=E4=BB=B6=E7=BB=93=E6=9E=84=EF=BC=8C=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84=20API=20=E8=B0=83?= =?UTF-8?q?=E7=94=A8=EF=BC=8C=E7=AE=80=E5=8C=96=E8=AE=B0=E5=BD=95=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E7=9A=84=E6=B8=B2=E6=9F=93=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E5=9B=BE=E7=89=87=E5=88=97=E8=A1=A8=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E4=B8=BA=E8=AE=B0=E5=BD=95=E5=8D=A1=E7=89=87=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=EF=BC=8C=E5=B9=B6=E6=9B=B4=E6=96=B0=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=B3=A8=E5=85=A5=E9=80=BB=E8=BE=91=E4=BB=A5=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E4=BD=9C=E8=80=85=E4=BF=A1=E6=81=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/user.ts | 2 +- .../article/components/Copyright/index.tsx | 11 ++- src/app/friend/index.tsx | 97 +++++++++++++++++++ src/app/friend/page.tsx | 94 +----------------- src/app/record/components/ImageList/index.tsx | 24 ++--- src/app/record/components/RecordCard.tsx | 44 +++++++++ src/app/record/page.tsx | 42 +++----- src/components/Footer/index.tsx | 4 +- src/components/InjectData/index.tsx | 13 ++- src/components/Sidebar/Author/index.tsx | 4 +- src/components/Slide/index.tsx | 14 ++- src/stores/index.ts | 3 +- src/stores/modules/author.ts | 13 +++ 更新日志.md | 7 -- 14 files changed, 211 insertions(+), 161 deletions(-) create mode 100644 src/app/friend/index.tsx create mode 100644 src/app/record/components/RecordCard.tsx create mode 100644 src/stores/modules/author.ts delete mode 100644 更新日志.md diff --git a/src/api/user.ts b/src/api/user.ts index 2536057..18a738f 100755 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -2,6 +2,6 @@ import { User } from '@/types/app/user' import Request from '@/utils/request' // 获取作者信息 -export const getUserDataAPI = async () => { +export const getAuthorDataAPI = async () => { return await Request('GET', '/user/author') } \ No newline at end of file diff --git a/src/app/article/components/Copyright/index.tsx b/src/app/article/components/Copyright/index.tsx index 4c14970..0f94ab3 100755 --- a/src/app/article/components/Copyright/index.tsx +++ b/src/app/article/components/Copyright/index.tsx @@ -1,13 +1,14 @@ -import { getUserDataAPI } from '@/api/user'; -import { User } from '@/types/app/user'; +'use client'; + +import { useAuthorStore } from '@/stores'; const Copyright = async () => { - const { data } = (await getUserDataAPI()) || { data: {} as User }; + const author = useAuthorStore((state) => state.author); return (
-

作者:{data?.name}

-

版权:此文章版权归 {data?.name} 所有,如有转载,请注明出处!

+

作者:{author?.name}

+

版权:此文章版权归 {author?.name} 所有,如有转载,请注明出处!

); }; diff --git a/src/app/friend/index.tsx b/src/app/friend/index.tsx new file mode 100644 index 0000000..b7e6676 --- /dev/null +++ b/src/app/friend/index.tsx @@ -0,0 +1,97 @@ +'use client'; + +import Link from 'next/link'; + +import { ToastContainer } from 'react-toastify'; + +import Slide from '@/components/Slide'; +import Starry from '@/components/Starry'; +import ApplyForAdd from './components/ApplyForAdd'; +import CopyableText from './components/CopyableText'; + +import { Web } from '@/types/app/web'; + +import { useConfigStore, useAuthorStore } from '@/stores'; + +export default ({ data }: { data: { [string: string]: { order: number; list: Web[] } } }) => { + const web = useConfigStore((state) => state.web); + const author = useAuthorStore((state) => state.author); + + return ( + <> + + {/* 星空背景组件 */} + + +
+
一个人的寂寞,一群人的狂欢!
+
+ +
+
+
+ +
+
+
+

本站信息

+ +
+

+ 站点名称:{web?.title} +

+

+ 站点介绍:{web?.description} +

+

+ 站点图标:{author?.avatar} +

+

+ 站点地址:{web?.url} +

+

+ Rss地址:{web?.url + '/api/rss'} +

+
+
+ + {Object.keys(data)?.map((type, index) => ( +
+

{type}

+ +
+ {type === '全站置顶' && ( + +
+ 项目作者 + +
+

宇阳

+

ThriveX 博客管理系统作者

+
+
+ + )} + + {data[type].list?.map((item: Web) => ( + +
+ {item.title} + +
+

{item.title}

+

{item.description}

+
+
+ + ))} +
+
+ ))} +
+
+ + + + ); +}; diff --git a/src/app/friend/page.tsx b/src/app/friend/page.tsx index 01978a3..3469539 100755 --- a/src/app/friend/page.tsx +++ b/src/app/friend/page.tsx @@ -1,19 +1,9 @@ -import Link from 'next/link'; import { Metadata } from 'next'; -import { getWebConfigDataAPI } from '@/api/config'; import { getWebListAPI, getWebTypeListAPI } from '@/api/web'; import { Web as WebLink, WebType } from '@/types/app/web'; -import Slide from '@/components/Slide'; -import Starry from '@/components/Starry'; -import ApplyForAdd from './components/ApplyForAdd'; -import CopyableText from './components/CopyableText'; - -import { ToastContainer } from 'react-toastify'; -import { getUserDataAPI } from '@/api/user'; -import { User } from '@/types/app/user'; -import { Web } from '@/types/app/config'; +import Friend from './index'; export const metadata: Metadata = { title: '😇 朋友圈', @@ -21,10 +11,6 @@ export const metadata: Metadata = { }; export default async () => { - const { data: user } = (await getUserDataAPI()) || { data: {} as User }; - const { - data: { value: web }, - } = (await getWebConfigDataAPI<{ value: Web }>('web')) || { data: { value: {} as Web } }; const { data: linkList } = (await getWebListAPI()) || { data: [] as WebLink[] }; const { data: typeList } = (await getWebTypeListAPI()) || { data: [] as WebType[] }; @@ -49,81 +35,5 @@ export default async () => { dataTemp.sort((a, b) => a[1].order - b[1].order); data = Object.fromEntries(dataTemp); - return ( - <> - - {/* 星空背景组件 */} - - -
-
一个人的寂寞,一群人的狂欢!
-
- -
-
-
- -
-
-
-

本站信息

- -
-

- 站点名称:{web?.title} -

-

- 站点介绍:{web?.description} -

-

- 站点图标:{user?.avatar} -

-

- 站点地址:{web?.url} -

-

- Rss地址:{web?.url + '/api/rss'} -

-
-
- - {Object.keys(data)?.map((type, index) => ( -
-

{type}

- -
- {type === '全站置顶' && ( - -
- 项目作者 - -
-

宇阳

-

ThriveX 博客管理系统作者

-
-
- - )} - - {data[type].list?.map((item: WebLink) => ( - -
- {item.title} - -
-

{item.title}

-

{item.description}

-
-
- - ))} -
-
- ))} -
-
- - - - ); + return ; }; diff --git a/src/app/record/components/ImageList/index.tsx b/src/app/record/components/ImageList/index.tsx index cf500b2..a21337f 100755 --- a/src/app/record/components/ImageList/index.tsx +++ b/src/app/record/components/ImageList/index.tsx @@ -10,17 +10,19 @@ interface Props { export default ({ list }: Props) => { return ( <> -
- 800} easing={(type) => (type === 2 ? 'cubic-bezier(0.36, 0, 0.66, -0.56)' : 'cubic-bezier(0.34, 1.56, 0.64, 1)')}> -
- {list?.map((url, index) => ( - - 闪念图片 - - ))} -
-
-
+ {!!list?.length && ( +
+ 800} easing={(type) => (type === 2 ? 'cubic-bezier(0.36, 0, 0.66, -0.56)' : 'cubic-bezier(0.34, 1.56, 0.64, 1)')}> +
+ {list.map((url, index) => ( + + 闪念图片 + + ))} +
+
+
+ )} ); }; diff --git a/src/app/record/components/RecordCard.tsx b/src/app/record/components/RecordCard.tsx new file mode 100644 index 0000000..bd5e69c --- /dev/null +++ b/src/app/record/components/RecordCard.tsx @@ -0,0 +1,44 @@ +import ImageList from './ImageList'; +import Editor from './Editor'; +import { dayFormat } from '@/utils'; +import { User } from '@/types/app/user'; + +interface RecordItemProps { + id: number | string; + content: string; + images: string | string[] | null; + createTime?: string | number | Date; + user: Pick | null; +} + +export default function RecordCard({ id, content, images, createTime, user }: RecordItemProps) { + const imageList: string[] = Array.isArray(images) ? images : JSON.parse((images as string) || '[]'); + + return ( +
+ 作者头像 + +
+ 作者头像 + +
+

{user?.name}

+ {dayFormat(createTime as any)} +
+
+ +
+
+

{user?.name}

+ {dayFormat(createTime as any)} +
+ +
+ + + +
+
+
+ ); +} diff --git a/src/app/record/page.tsx b/src/app/record/page.tsx index 48bff48..8592bdb 100755 --- a/src/app/record/page.tsx +++ b/src/app/record/page.tsx @@ -1,15 +1,13 @@ -import ImageList from './components/ImageList'; +import RecordCard from './components/RecordCard'; import { getRecordPagingAPI } from '@/api/record'; -import { getUserDataAPI } from '@/api/user'; +import { getAuthorDataAPI } from '@/api/user'; import { Record } from '@/types/app/record'; import { User } from '@/types/app/user'; -import { dayFormat } from '@/utils'; import Pagination from '@/components/Pagination'; import Empty from '@/components/Empty'; import Show from '@/components/Show'; import { getWebConfigDataAPI } from '@/api/config'; import { Theme } from '@/types/app/config'; -import Editor from './components/Editor'; interface Props { searchParams: Promise<{ page: number }>; @@ -19,7 +17,7 @@ export default async (props: Props) => { const searchParams = await props.searchParams; const page = searchParams.page || 1; - const { data: user } = (await getUserDataAPI()) || { data: {} as User }; + const { data: user } = (await getAuthorDataAPI()) || { data: {} as User }; const { data: record } = (await getRecordPagingAPI({ pagination: { page, size: 8 } })) || { data: {} as Paginate }; const { data: { value: theme }, @@ -41,32 +39,14 @@ export default async (props: Props) => {
{!!record?.result?.length && record?.result.map((item) => ( -
- 作者头像 - -
- 作者头像 - -
-

{user?.name}

- {dayFormat(item?.createTime)} -
-
- -
-
-

{user?.name}

- {dayFormat(item?.createTime)} -
- -
- - - - {/* */} -
-
-
+ ))} diff --git a/src/components/Footer/index.tsx b/src/components/Footer/index.tsx index 43636ea..58b1423 100755 --- a/src/components/Footer/index.tsx +++ b/src/components/Footer/index.tsx @@ -1,7 +1,7 @@ import Link from 'next/link'; import Image from 'next/image'; import { getWebConfigDataAPI } from '@/api/config'; -import { getUserDataAPI } from '@/api/user'; +import { getAuthorDataAPI } from '@/api/user'; import { User } from '@/types/app/user'; import { Web } from '@/types/app/config'; import Tooltip from './components/Tooltip'; @@ -10,7 +10,7 @@ import animals from './images/animals.webp'; import ICP from './images/ICP.png'; export default async () => { - const { data: user } = (await getUserDataAPI()) || { data: {} as User }; + const { data: user } = (await getAuthorDataAPI()) || { data: {} as User }; const { data: { value: web }, } = (await getWebConfigDataAPI<{ value: Web }>('web')) || { data: { value: {} as Web } }; diff --git a/src/components/InjectData/index.tsx b/src/components/InjectData/index.tsx index 80cf070..c80a770 100644 --- a/src/components/InjectData/index.tsx +++ b/src/components/InjectData/index.tsx @@ -3,10 +3,20 @@ import { useEffect } from 'react'; import { getWebConfigDataAPI } from '@/api/config'; -import { useConfigStore } from '@/stores'; +import { useAuthorStore, useConfigStore } from '@/stores'; import { Web, Theme, Other } from '@/types/app/config'; +import { getAuthorDataAPI } from '@/api/user'; +import { User } from '@/types/app/user'; export default () => { + const setAuthor = useAuthorStore((state) => state.setAuthor); + + // 获取作者信息 + const getAuthorData = async () => { + const { data: user } = (await getAuthorDataAPI()) || { data: {} as User }; + setAuthor(user); + }; + const { setWeb, setTheme, setOther } = useConfigStore(); // 获取项目配置 @@ -28,6 +38,7 @@ export default () => { }; useEffect(() => { + getAuthorData(); getConfigData(); }, []); diff --git a/src/components/Sidebar/Author/index.tsx b/src/components/Sidebar/Author/index.tsx index ea8781e..f807831 100755 --- a/src/components/Sidebar/Author/index.tsx +++ b/src/components/Sidebar/Author/index.tsx @@ -9,13 +9,13 @@ import Juejin from '@/assets/svg/socializing/Juejin.svg'; import QQ from '@/assets/svg/socializing/QQ.svg'; import Weixin from '@/assets/svg/socializing/Weixin.svg'; -import { getUserDataAPI } from '@/api/user'; +import { getAuthorDataAPI } from '@/api/user'; import { getWebConfigDataAPI } from '@/api/config'; import { User } from '@/types/app/user'; import { Social, Theme } from '@/types/app/config'; const Author = async () => { - const { data: user } = (await getUserDataAPI()) || { data: {} as User }; + const { data: user } = (await getAuthorDataAPI()) || { data: {} as User }; const { data: { value: theme }, } = (await getWebConfigDataAPI<{ value: Theme }>('theme')) || { data: { value: {} as Theme } }; diff --git a/src/components/Slide/index.tsx b/src/components/Slide/index.tsx index 8d079dd..1e8d84a 100755 --- a/src/components/Slide/index.tsx +++ b/src/components/Slide/index.tsx @@ -1,8 +1,9 @@ +'use client'; + import { ReactNode } from 'react'; import Ripple from '@/components/Ripple'; import { getRandom } from '@/utils'; -import { getWebConfigDataAPI } from '@/api/config'; -import { Theme } from '@/types/app/config'; +import { useConfigStore } from '@/stores'; interface Props { src?: string; // 图片列表 @@ -10,12 +11,9 @@ interface Props { children?: ReactNode; } -export default async ({ src, isRipple = true, children }: Props) => { - const { - data: { value: data }, - } = (await getWebConfigDataAPI<{ value: Theme }>('theme')) || { data: { value: {} as Theme } }; - - const covers = data.covers || []; +export default ({ src, isRipple = true, children }: Props) => { + const theme = useConfigStore((state) => state.theme); + const covers = theme.covers || []; const sty = { backgroundImage: `url(${src ? src : covers[getRandom(0, covers.length - 1)]})`, diff --git a/src/stores/index.ts b/src/stores/index.ts index febb4bb..5f54847 100755 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -1,3 +1,4 @@ import useConfigStore from './modules/config' +import useAuthorStore from './modules/author' -export { useConfigStore } \ No newline at end of file +export { useConfigStore, useAuthorStore }; \ No newline at end of file diff --git a/src/stores/modules/author.ts b/src/stores/modules/author.ts new file mode 100644 index 0000000..1a1f615 --- /dev/null +++ b/src/stores/modules/author.ts @@ -0,0 +1,13 @@ +import { create } from 'zustand'; +import { User } from '@/types/app/user'; + +interface AuthorState { + // 作者信息 + author: User; + setAuthor: (data: User) => void; +} + +export default create((set) => ({ + author: {} as User, + setAuthor: (data: User) => set(() => ({ author: data })), +})); diff --git a/更新日志.md b/更新日志.md deleted file mode 100644 index 6ce2d87..0000000 --- a/更新日志.md +++ /dev/null @@ -1,7 +0,0 @@ -一、调整关于我页面技术栈容器宽度 - -二、调整我的履历页面 项目描述、亮点和难点的渲染逻辑,确保在有内容时才显示相关信息。 - -三、解决移动端点击导航跳转到分类 BUG - -四、放行所有图片来源,不用再手动配置 \ No newline at end of file