This commit is contained in:
@ -30,7 +30,7 @@ const { title = '小帕的小窝', withGap = false } = Astro.props
|
|||||||
<a href="/">小帕的小窝</a>
|
<a href="/">小帕的小窝</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/blogs"><Icon name="mdi:invoice-text-outline" />文章</a>
|
<a href="/blog"><Icon name="mdi:invoice-text-outline" />文章</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/about"
|
<a href="/about"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { legacyClient } from '../clients'
|
import { legacyClient } from '../clients'
|
||||||
|
|
||||||
export type ListBlogItemType = {
|
export type LegacyListBlogItemType = {
|
||||||
id: number
|
id: number
|
||||||
title: string
|
title: string
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ export type ListBlogItemType = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BlogContentType = ListBlogItemType & {
|
export type LegacyBlogContentType = LegacyListBlogItemType & {
|
||||||
content: string
|
content: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,12 +57,12 @@ export const listBlogs = async ({
|
|||||||
_blog.updated_at = new Date(_blog.updated_at)
|
_blog.updated_at = new Date(_blog.updated_at)
|
||||||
|
|
||||||
return _blog
|
return _blog
|
||||||
}) as ListBlogItemType[]
|
}) as LegacyListBlogItemType[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getBlog: (
|
export const getBlog: (
|
||||||
blog_id: number,
|
blog_id: number,
|
||||||
) => Promise<null | BlogContentType> = async (blog_id: number) => {
|
) => Promise<null | LegacyBlogContentType> = async (blog_id: number) => {
|
||||||
const resp = await legacyClient.get(`/v1/blog/${blog_id}`, {
|
const resp = await legacyClient.get(`/v1/blog/${blog_id}`, {
|
||||||
validateStatus: (status) => status == 200 || status == 404,
|
validateStatus: (status) => status == 200 || status == 404,
|
||||||
})
|
})
|
||||||
|
|||||||
27
src/lib/apis/legacy/user.ts
Normal file
27
src/lib/apis/legacy/user.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { legacyClient } from '../clients'
|
||||||
|
|
||||||
|
export type LegacyUserType = {
|
||||||
|
id: number
|
||||||
|
created_at: Date
|
||||||
|
username: string
|
||||||
|
nickname: string
|
||||||
|
permission: number
|
||||||
|
introduction: string
|
||||||
|
avatar: {
|
||||||
|
image_url: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getUserInfo = async ({ username }: { username: string }) => {
|
||||||
|
const resp = await legacyClient.get(`/v1/user/${username}/info`)
|
||||||
|
if (resp.status != 200) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...resp.data,
|
||||||
|
created_at: new Date(resp.data.created_at),
|
||||||
|
avatar: {
|
||||||
|
image_url: 'https://legacy.passthem.top' + resp.data.avatar.image_url,
|
||||||
|
},
|
||||||
|
} as LegacyUserType
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
import FullLayoutV1 from '../layout/FullLayoutV1.astro'
|
import FullLayoutV1 from '../layout/FullLayoutV1.astro'
|
||||||
import { listBlogs, type ListBlogItemType } from '../lib/apis/legacy/blog'
|
import { listBlogs, type LegacyListBlogItemType } from '../lib/apis/legacy/blog'
|
||||||
import BlogCard from '../components/BlogCard.astro'
|
import BlogCard from '../components/BlogCard.astro'
|
||||||
import BlogHeaderImage from '../assets/blogs-header.webp'
|
import BlogHeaderImage from '../assets/blogs-header.webp'
|
||||||
import { Image } from 'astro:assets'
|
import { Image } from 'astro:assets'
|
||||||
@ -10,7 +10,7 @@ export const prerender = false
|
|||||||
const _page = parseInt(Astro.url.searchParams.get('page') || '1')
|
const _page = parseInt(Astro.url.searchParams.get('page') || '1')
|
||||||
const page = isNaN(_page) ? 1 : Math.max(1, _page)
|
const page = isNaN(_page) ? 1 : Math.max(1, _page)
|
||||||
|
|
||||||
let blogs: ListBlogItemType[] = []
|
let blogs: LegacyListBlogItemType[] = []
|
||||||
|
|
||||||
try {
|
try {
|
||||||
blogs = await listBlogs({ page, limit: 100 })
|
blogs = await listBlogs({ page, limit: 100 })
|
||||||
@ -45,7 +45,7 @@ try {
|
|||||||
blogs.map((blog) => (
|
blogs.map((blog) => (
|
||||||
<BlogCard
|
<BlogCard
|
||||||
title={blog.title}
|
title={blog.title}
|
||||||
link={`/blogs/${blog.id}`}
|
link={`/blog/${blog.id}`}
|
||||||
featureImage={blog.featured_image?.image_url}
|
featureImage={blog.featured_image?.image_url}
|
||||||
author={{
|
author={{
|
||||||
name: blog.author.nickname,
|
name: blog.author.nickname,
|
||||||
@ -54,10 +54,7 @@ const formatDate = (date: Date) =>
|
|||||||
{
|
{
|
||||||
blogData.author && (
|
blogData.author && (
|
||||||
<div class="blog-info">
|
<div class="blog-info">
|
||||||
<a
|
<a class="author" href={`/user/${blogData.author.username}`}>
|
||||||
class="author"
|
|
||||||
href={`https://legacy.passthem.top/user/${blogData.author.username}`}
|
|
||||||
>
|
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
<Image
|
<Image
|
||||||
class="image"
|
class="image"
|
||||||
@ -3,7 +3,7 @@ import type { APIRoute } from 'astro'
|
|||||||
import {
|
import {
|
||||||
getBlog,
|
getBlog,
|
||||||
listBlogs,
|
listBlogs,
|
||||||
type ListBlogItemType,
|
type LegacyListBlogItemType,
|
||||||
} from '../lib/apis/legacy/blog'
|
} from '../lib/apis/legacy/blog'
|
||||||
import { ensureShikiEngine } from '../lib/markdown'
|
import { ensureShikiEngine } from '../lib/markdown'
|
||||||
// import { toMarkdocTree } from '../lib/markdoc'
|
// import { toMarkdocTree } from '../lib/markdoc'
|
||||||
@ -50,7 +50,7 @@ const _getBlog = async (blogId: number) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const GET = (async (context) => {
|
export const GET = (async (context) => {
|
||||||
let blogs: ListBlogItemType[] = []
|
let blogs: LegacyListBlogItemType[] = []
|
||||||
let pid = 0
|
let pid = 0
|
||||||
|
|
||||||
let newBlogs = []
|
let newBlogs = []
|
||||||
@ -76,7 +76,7 @@ export const GET = (async (context) => {
|
|||||||
const rssItem: RSSFeedItem = {
|
const rssItem: RSSFeedItem = {
|
||||||
title: blog.title,
|
title: blog.title,
|
||||||
description: `一篇由 ${blog.author.nickname} 写的博客`,
|
description: `一篇由 ${blog.author.nickname} 写的博客`,
|
||||||
link: `${site}/blogs/${blog.id}`,
|
link: `${site}/blog/${blog.id}`,
|
||||||
pubDate: new Date(blog.created_at),
|
pubDate: new Date(blog.created_at),
|
||||||
content: await _render(blogContent),
|
content: await _render(blogContent),
|
||||||
author: blog.author.nickname,
|
author: blog.author.nickname,
|
||||||
|
|||||||
89
src/pages/user/[user_id].astro
Normal file
89
src/pages/user/[user_id].astro
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
---
|
||||||
|
import FullLayoutV1 from '../../layout/FullLayoutV1.astro'
|
||||||
|
import { getUserInfo, type LegacyUserType } from '../../lib/apis/legacy/user'
|
||||||
|
import { Image } from 'astro:assets'
|
||||||
|
|
||||||
|
const { user_id = '' } = Astro.params
|
||||||
|
var user_data: LegacyUserType
|
||||||
|
|
||||||
|
try {
|
||||||
|
const _user_data = await getUserInfo({ username: user_id })
|
||||||
|
if (_user_data === null) {
|
||||||
|
return Astro.redirect('/404')
|
||||||
|
}
|
||||||
|
user_data = _user_data
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('访问了不存在的用户', user_id)
|
||||||
|
console.warn(e)
|
||||||
|
return Astro.redirect('/404')
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
<FullLayoutV1>
|
||||||
|
<div class="container">
|
||||||
|
<div class="user-card">
|
||||||
|
<div class="avatar">
|
||||||
|
<Image
|
||||||
|
src={user_data.avatar.image_url}
|
||||||
|
densities={[1.5, 2]}
|
||||||
|
width={150}
|
||||||
|
height={150}
|
||||||
|
alt=`用户 ${user_data.username} 的头像`
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="user-info">
|
||||||
|
<h1 class="name">
|
||||||
|
<span class="nickname">{user_data.nickname}</span><span
|
||||||
|
class="username">{user_data.username}</span
|
||||||
|
>
|
||||||
|
</h1>
|
||||||
|
<h2 class="introduction">{user_data.introduction}</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</FullLayoutV1>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100dvh;
|
||||||
|
|
||||||
|
.user-card {
|
||||||
|
background-color: var(--color-bg-n);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 4rem;
|
||||||
|
gap: 1rem;
|
||||||
|
border-radius: 1rem;
|
||||||
|
|
||||||
|
@media (width >= 768px) {
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info {
|
||||||
|
.name {
|
||||||
|
display: flex;
|
||||||
|
font-weight: 600;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-block-end: 0.25rem;
|
||||||
|
align-items: center;
|
||||||
|
font-size: larger;
|
||||||
|
|
||||||
|
.username {
|
||||||
|
opacity: 0.3;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.9em;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '@';
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user