959 lines
23 KiB
Markdown
959 lines
23 KiB
Markdown
---
|
||
title: post 集合
|
||
icon: mdi:post-outline
|
||
createTime: 2025/10/05 17:10:57
|
||
permalink: /guide/collection/post/
|
||
---
|
||
|
||
## 概述
|
||
|
||
**post 集合**用于管理碎片化的多篇文章集合。这里的"碎片化"指文章间无强关联关系,或仅需扁平化展示的场景,典型应用包括:
|
||
|
||
- 博客系统
|
||
- 专题专栏
|
||
- 新闻资讯
|
||
- 随笔记录
|
||
|
||
该集合提供完整的文章管理功能:
|
||
|
||
- **文章列表页** - 支持置顶、封面图、摘要展示
|
||
- **文章分类页** - 基于目录结构自动生成分类
|
||
- **文章标签页** - 根据页面 `frontmatter.tags` 生成标签
|
||
- **文章归档页** - 基于 `frontmatter.createTime` 生成时间线归档
|
||
|
||
各页面均预留个人信息展示区域,支持个人简介或组织信息配置。
|
||
|
||
::: info 主题支持配置多个 post 集合
|
||
:::
|
||
|
||
## 创建 post 集合
|
||
|
||
通过三个简单步骤即可完成 post 集合创建:
|
||
|
||
:::: steps
|
||
|
||
- **创建文章目录**
|
||
|
||
::: file-tree
|
||
- docs
|
||
- ++ blog
|
||
- ++ post-1.md
|
||
- ++ post-2.md
|
||
- ++ …
|
||
:::
|
||
|
||
- **配置集合参数**
|
||
|
||
::: code-tabs#config
|
||
|
||
@tab .vuepress/config.ts
|
||
|
||
```ts twoslash
|
||
import { defineUserConfig } from 'vuepress'
|
||
import { plumeTheme } from 'vuepress-theme-plume'
|
||
|
||
export default defineUserConfig({
|
||
theme: plumeTheme({
|
||
collections: [ // [!code focus:3]
|
||
{ type: 'post', dir: 'blog', title: '博客' }
|
||
]
|
||
})
|
||
})
|
||
```
|
||
|
||
@tab .vuepress/plume.config.ts
|
||
|
||
```ts twoslash
|
||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||
|
||
export default defineThemeConfig({
|
||
collections: [ // [!code focus:3]
|
||
{ type: 'post', dir: 'blog', title: '博客' }
|
||
]
|
||
})
|
||
```
|
||
|
||
:::
|
||
|
||
- **完成**
|
||
|
||
::::
|
||
|
||
配置完成后,主题自动扫描 `docs/blog` 目录并生成以下页面:
|
||
|
||
- 文章列表页:`/blog/`
|
||
- 文章分类页:`/blog/categories/`
|
||
- 文章标签页:`/blog/tags/`
|
||
- 文章归档页:`/blog/archives/`
|
||
|
||
启用 `autoFrontmatter` 后,系统自动为 Markdown 文件生成永久链接:
|
||
|
||
```md title="docs/blog/post-1.md"
|
||
---
|
||
title: post-1
|
||
createTime: 2025/03/24 20:15:12
|
||
permalink: /blog/a1b2c3d4/
|
||
---
|
||
```
|
||
|
||
### 多语言支持
|
||
|
||
在主题多语言配置中定义不同语言的 post 集合:
|
||
|
||
::: code-tabs#config
|
||
|
||
@tab .vuepress/config.ts
|
||
|
||
```ts twoslash
|
||
import { defineUserConfig } from 'vuepress'
|
||
import { plumeTheme } from 'vuepress-theme-plume'
|
||
|
||
export default defineUserConfig({
|
||
theme: plumeTheme({
|
||
locales: {
|
||
'/': { // [!code focus:5]
|
||
collections: [
|
||
{ type: 'post', dir: 'blog', title: '博客' }
|
||
]
|
||
},
|
||
'/en/': { // [!code focus:5]
|
||
collections: [
|
||
{ type: 'post', dir: 'blog', title: 'Blog' }
|
||
]
|
||
}
|
||
}
|
||
})
|
||
})
|
||
```
|
||
|
||
@tab .vuepress/plume.config.ts
|
||
|
||
```ts twoslash
|
||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||
|
||
export default defineThemeConfig({
|
||
locales: {
|
||
'/': { // [!code focus:5]
|
||
collections: [
|
||
{ type: 'post', dir: 'blog', title: '博客' }
|
||
]
|
||
},
|
||
'/en/': { // [!code focus:5]
|
||
collections: [
|
||
{ type: 'post', dir: 'blog', title: 'Blog' }
|
||
]
|
||
}
|
||
}
|
||
})
|
||
```
|
||
|
||
:::
|
||
|
||
## 集合目录配置
|
||
|
||
`dir` 参数指定集合的源文件目录,支持绝对路径和相对路径(均相对于源目录):
|
||
|
||
```ts
|
||
dir: 'blog' // 指向 docs/blog
|
||
dir: '/blog/' // 等效写法
|
||
dir: './blog/' // 等效写法
|
||
dir: '/team/blog/' // 指向 docs/team/blog
|
||
```
|
||
|
||
::: info 在多语言下,则相对于多语言目录
|
||
:::
|
||
|
||
### 文件过滤
|
||
|
||
通过 `include` 和 `exclude` 配置过滤 Markdown 文件,
|
||
使用 [picomatch ::quill:search::](https://chat.baidu.com/search?word=picomatch+%E7%9A%84+glob+pattern+%E8%A7%84%E5%88%99){.no-icon} 模式匹配:
|
||
|
||
::: code-tabs#config
|
||
|
||
@tab .vuepress/config.ts
|
||
|
||
```ts twoslash
|
||
import { defineUserConfig } from 'vuepress'
|
||
import { plumeTheme } from 'vuepress-theme-plume'
|
||
|
||
export default defineUserConfig({
|
||
theme: plumeTheme({
|
||
collections: [
|
||
{
|
||
type: 'post',
|
||
dir: 'blog',
|
||
title: '博客',
|
||
// [!code hl:4]
|
||
include: ['**/*.md'], // 包含所有 .md 文件
|
||
exclude: ['**/*.snippet.md'] // 排除代码片段文件
|
||
}
|
||
]
|
||
})
|
||
})
|
||
```
|
||
|
||
@tab .vuepress/plume.config.ts
|
||
|
||
```ts twoslash
|
||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||
|
||
export default defineThemeConfig({
|
||
collections: [
|
||
{
|
||
type: 'post',
|
||
dir: 'blog',
|
||
title: '博客',
|
||
// [!code hl:4]
|
||
include: ['**/*.md'], // 包含所有 .md 文件
|
||
exclude: ['**/*.snippet.md'] // 排除代码片段文件
|
||
}
|
||
]
|
||
})
|
||
```
|
||
|
||
:::
|
||
|
||
## 页面生成配置
|
||
|
||
默认基于 `dir` 配置生成页面路径,支持完整自定义:
|
||
|
||
::: code-tabs#config
|
||
|
||
@tab .vuepress/config.ts
|
||
|
||
```ts twoslash
|
||
import { defineUserConfig } from 'vuepress'
|
||
import { plumeTheme } from 'vuepress-theme-plume'
|
||
|
||
export default defineUserConfig({
|
||
theme: plumeTheme({
|
||
collections: [
|
||
{
|
||
type: 'post',
|
||
dir: 'blog',
|
||
title: '博客',
|
||
// [!code hl:16]
|
||
postList: true, // 启用文章列表页
|
||
link: '/blog/', // 列表页链接
|
||
linkPrefix: '/blog/', // 文章链接前缀
|
||
tags: true, // 启用标签页
|
||
tagsLink: '/blog/tags/', // 标签页链接
|
||
tagsTheme: 'colored', // 标签主题 colored|gray|brand
|
||
tagsText: '标签', // 标签页标题
|
||
archives: true, // 启用归档页
|
||
archivesLink: '/blog/archives/', // 归档页链接
|
||
archivesText: '归档', // 归档页标题
|
||
categories: true, // 启用分类页
|
||
categoriesLink: '/blog/categories/', // 分类页链接
|
||
categoriesText: '分类', // 分类页标题
|
||
categoriesExpand: 'deep', // 分类展开层级 number|'deep'
|
||
categoriesTransform: categories => categories, // 分类转换函数
|
||
}
|
||
]
|
||
})
|
||
})
|
||
```
|
||
|
||
@tab .vuepress/plume.config.ts
|
||
|
||
```ts twoslash
|
||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||
|
||
export default defineThemeConfig({
|
||
collections: [
|
||
{
|
||
type: 'post',
|
||
dir: 'blog',
|
||
title: '博客',
|
||
// [!code hl:16]
|
||
postList: true, // 启用文章列表页
|
||
link: '/blog/', // 列表页链接
|
||
linkPrefix: '/blog/', // 文章链接前缀
|
||
tags: true, // 启用标签页
|
||
tagsLink: '/blog/tags/', // 标签页链接
|
||
tagsTheme: 'colored', // 标签主题 colored|gray|brand
|
||
tagsText: '标签', // 标签页标题
|
||
archives: true, // 启用归档页
|
||
archivesLink: '/blog/archives/', // 归档页链接
|
||
archivesText: '归档', // 归档页标题
|
||
categories: true, // 启用分类页
|
||
categoriesLink: '/blog/categories/', // 分类页链接
|
||
categoriesText: '分类', // 分类页标题
|
||
categoriesExpand: 'deep', // 分类展开层级 number|'deep'
|
||
categoriesTransform: categories => categories, // 分类转换函数
|
||
}
|
||
]
|
||
})
|
||
```
|
||
|
||
:::
|
||
|
||
## 自动 Frontmatter 生成
|
||
|
||
::: info 仅在执行 `vuepress dev` 或 `vuepress build` 后生效
|
||
:::
|
||
|
||
支持集合级别的 frontmatter 自动生成,可自定义转换逻辑:
|
||
|
||
::: code-tabs#config
|
||
|
||
@tab .vuepress/config.ts
|
||
|
||
```ts
|
||
import { defineUserConfig } from 'vuepress'
|
||
import { plumeTheme } from 'vuepress-theme-plume'
|
||
|
||
export default defineUserConfig({
|
||
theme: plumeTheme({
|
||
collections: [
|
||
{
|
||
type: 'post',
|
||
dir: 'blog',
|
||
title: '博客',
|
||
// [!code hl:10]
|
||
autoFrontmatter: {
|
||
title: true, // 自动生成标题
|
||
createTime: true, // 自动生成创建时间
|
||
permalink: true, // 自动生成永久链接
|
||
transform: (data, context, locale) => { // 自定义转换
|
||
data.foo ??= 'foo'
|
||
return data
|
||
}
|
||
}
|
||
}
|
||
]
|
||
})
|
||
})
|
||
```
|
||
|
||
@tab .vuepress/plume.config.ts
|
||
|
||
``` ts
|
||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||
|
||
export default defineThemeConfig({
|
||
collections: [
|
||
{
|
||
type: 'post',
|
||
dir: 'blog',
|
||
title: '博客',
|
||
// [!code hl:10]
|
||
autoFrontmatter: {
|
||
title: true, // 自动生成标题
|
||
createTime: true, // 自动生成创建时间
|
||
permalink: true, // 自动生成永久链接
|
||
transform: (data, context, locale) => { // 自定义转换
|
||
data.foo ??= 'foo'
|
||
return data
|
||
}
|
||
}
|
||
}
|
||
]
|
||
})
|
||
```
|
||
|
||
:::
|
||
|
||
生成示例:
|
||
|
||
```md title="docs/blog/post-1.md"
|
||
---
|
||
title: post-1
|
||
createTime: 2025/03/24 20:15:12
|
||
permalink: /blog/a1b2c3d4/
|
||
---
|
||
```
|
||
|
||
## 个人信息配置
|
||
|
||
每个 post 集合支持独立配置个人信息展示区域。未配置时继承[主题默认 profile 设置](../../config/theme.md#profile)。
|
||
|
||
::: code-tabs#config
|
||
|
||
@tab .vuepress/config.ts
|
||
|
||
```ts
|
||
import { defineUserConfig } from 'vuepress'
|
||
import { plumeTheme } from 'vuepress-theme-plume'
|
||
|
||
export default defineUserConfig({
|
||
theme: plumeTheme({
|
||
collections: [
|
||
{
|
||
type: 'post',
|
||
dir: 'blog',
|
||
title: '博客',
|
||
// [!code hl:10]
|
||
profile: {
|
||
avatar: '/avatar.jpg', // 头像路径
|
||
name: '张三', // 显示名称
|
||
description: '个人简介', // 简介文本
|
||
circle: true, // 圆形头像
|
||
location: '广州', // 所在地
|
||
organization: '组织名称', // 所属组织
|
||
layout: 'right', // 布局位置 left|right
|
||
}
|
||
}
|
||
]
|
||
})
|
||
})
|
||
```
|
||
|
||
@tab .vuepress/plume.config.ts
|
||
|
||
``` ts
|
||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||
|
||
export default defineThemeConfig({
|
||
collections: [
|
||
{
|
||
type: 'post',
|
||
dir: 'blog',
|
||
title: '博客',
|
||
// [!code hl:10]
|
||
profile: {
|
||
avatar: '/avatar.jpg', // 头像路径
|
||
name: '张三', // 显示名称
|
||
description: '个人简介', // 简介文本
|
||
circle: true, // 圆形头像
|
||
location: '广州', // 所在地
|
||
organization: '组织名称', // 所属组织
|
||
layout: 'right', // 布局位置 left|right
|
||
}
|
||
}
|
||
]
|
||
})
|
||
```
|
||
|
||
:::
|
||
|
||
## 社交链接
|
||
|
||
个人信息区域支持社交链接配置,未配置时继承 [主题默认 social 设置](../../config/theme.md#social)。
|
||
|
||
::: code-tabs#config
|
||
|
||
@tab .vuepress/config.ts
|
||
|
||
```ts
|
||
import { defineUserConfig } from 'vuepress'
|
||
import { plumeTheme } from 'vuepress-theme-plume'
|
||
|
||
export default defineUserConfig({
|
||
theme: plumeTheme({
|
||
collections: [
|
||
{
|
||
type: 'post',
|
||
dir: 'blog',
|
||
title: '博客',
|
||
// [!code hl:9]
|
||
social: [
|
||
// 使用 iconify name
|
||
{ icon: 'github', link: 'https://github.com/zhangsan' },
|
||
{
|
||
// 使用自定义图标
|
||
icon: { svg: '<svg>xxxxx</svg>', name: 'xxx' },
|
||
link: 'https://xxx.com'
|
||
},
|
||
],
|
||
}
|
||
]
|
||
})
|
||
})
|
||
```
|
||
|
||
@tab .vuepress/plume.config.ts
|
||
|
||
``` ts
|
||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||
|
||
export default defineThemeConfig({
|
||
collections: [
|
||
{
|
||
type: 'post',
|
||
dir: 'blog',
|
||
title: '博客',
|
||
// [!code hl:9]
|
||
social: [
|
||
// 使用 iconify name
|
||
{ icon: 'github', link: 'https://github.com/zhangsan' },
|
||
{
|
||
// 使用自定义图标
|
||
icon: { svg: '<svg>xxxxx</svg>', name: 'xxx' },
|
||
link: 'https://xxx.com'
|
||
},
|
||
],
|
||
}
|
||
]
|
||
})
|
||
```
|
||
|
||
:::
|
||
|
||
支持 [Iconify](https://icon-sets.iconify.design/) 任意图标,直接使用 iconify name 即可自动加载。
|
||
|
||
对于 `simple-icons` 集合下的图标,可以省略 `simple-icons:` 前缀,如 `simple-icons:github` 可以简写为 `github`
|
||
|
||
常见的社交图标示例:
|
||
|
||
::: flex
|
||
|
||
<div style="flex: 1">
|
||
|
||
- discord ::simple-icons:discord::
|
||
- telegram ::simple-icons:telegram::
|
||
- facebook ::simple-icons:facebook::
|
||
- github ::simple-icons:github::
|
||
- instagram ::simple-icons:instagram::
|
||
- linkedin ::simple-icons:linkedin::
|
||
- mastodon ::simple-icons:mastodon::
|
||
- npm ::simple-icons:npm::
|
||
- slack ::simple-icons:slack::
|
||
- twitter ::simple-icons:twitter::
|
||
- x ::simple-icons:x::
|
||
- youtube ::simple-icons:youtube::
|
||
- bluesky ::simple-icons:bluesky::
|
||
- tiktok ::simple-icons:tiktok::
|
||
|
||
</div><div style="flex: 1">
|
||
|
||
- qq ::simple-icons:qq::
|
||
- weibo ::simple-icons:sinaweibo::
|
||
- bilibili ::simple-icons:bilibili::
|
||
- gitlab ::simple-icons:gitlab::
|
||
- docker ::simple-icons:docker::
|
||
- juejin ::simple-icons:juejin::
|
||
- zhihu ::simple-icons:zhihu::
|
||
- douban ::simple-icons:douban::
|
||
- steam ::simple-icons:steam::
|
||
- stackoverflow ::simple-icons:stackoverflow::
|
||
- xbox ::simple-icons:xbox::
|
||
- kuaishou ::simple-icons:kuaishou::
|
||
- twitch ::simple-icons:twitch::
|
||
- xiaohongshu ::simple-icons:xiaohongshu::
|
||
|
||
</div>
|
||
|
||
:::
|
||
|
||
[你可以在这里查看 **simple-icons** 所有可用图标](https://icon-sets.iconify.design/simple-icons/){.readmore}
|
||
|
||
如果 **Iconify** 无法满足你的需求,可以传入 `{ svg: string, name?: string }`的格式,使用自定义图标,传入 svg 源码字符串。
|
||
|
||
## 文章封面配置
|
||
|
||
文章列表页支持封面图展示,提供多种布局和尺寸选项。
|
||
|
||
### 基础配置
|
||
|
||
在 frontmatter 中定义封面图路径:
|
||
|
||
```md{3}
|
||
---
|
||
title: 文章标题
|
||
cover: /images/cover.jpg
|
||
---
|
||
```
|
||
|
||
**路径规范**:仅支持绝对路径或远程 URL。本地图片需放置在 `.vuepress/public` 目录:
|
||
|
||
::: file-tree
|
||
|
||
- docs
|
||
- .vuepress
|
||
- public
|
||
- images
|
||
- cover.jpg
|
||
- config.ts
|
||
- article.md
|
||
:::
|
||
|
||
默认展示效果:
|
||
|
||
<div style="background-color: var(--vp-c-bg-alt); padding: 20px 24px;transition: var(--vp-t-color)">
|
||
<VPPostItem
|
||
:post="{ path: '/article/ecxnxxd0/', title: '文章标题',
|
||
categoryList: [{id:'65f30c',sort:4,name:'教程'}], createTime: '2024/09/18 09:19:36',
|
||
lang:'zh-CN', excerpt:'', cover: 'https://api.pengzhanbo.cn/wallpaper/bing' }"
|
||
:index="1"
|
||
/>
|
||
</div>
|
||
|
||
### 高级布局
|
||
|
||
调整封面图位置和尺寸:
|
||
|
||
```md{4-7}
|
||
---
|
||
title: 文章标题
|
||
cover: /images/cover.jpg
|
||
coverStyle:
|
||
layout: left
|
||
ratio: 16/9
|
||
width: 300
|
||
---
|
||
```
|
||
|
||
效果展示:
|
||
|
||
<div style="background-color: var(--vp-c-bg-alt); padding: 20px 24px;transition: var(--vp-t-color)">
|
||
<VPPostItem
|
||
:post="{ path: '/article/ecxnxxd0/', title: '文章标题',
|
||
categoryList: [{id:'65f30c',sort:4,name:'教程'}], createTime: '2024/09/18 09:19:36',
|
||
lang:'zh-CN', excerpt:'', cover: 'https://api.pengzhanbo.cn/wallpaper/bing', coverStyle: { layout: 'left', ratio: '16/9', width: 300 } }"
|
||
:index="1"
|
||
/>
|
||
</div>
|
||
|
||
### 紧凑模式
|
||
|
||
无摘要时启用紧凑布局:
|
||
|
||
```md{8}
|
||
---
|
||
title: 文章标题
|
||
cover: /images/cover.jpg
|
||
coverStyle:
|
||
layout: left
|
||
ratio: 16/9
|
||
width: 300
|
||
compact: true
|
||
---
|
||
```
|
||
|
||
效果展示:
|
||
|
||
<div style="background-color: var(--vp-c-bg-alt); padding: 20px 24px;transition: var(--vp-t-color)">
|
||
<VPPostItem
|
||
:post="{ path: '/article/ecxnxxd0/', title: '文章标题',
|
||
categoryList: [{id:'65f30c',sort:4,name:'教程'}], createTime: '2024/09/18 09:19:36',
|
||
lang:'zh-CN', excerpt:'', cover: 'https://api.pengzhanbo.cn/wallpaper/bing',
|
||
coverStyle: { layout: 'left', ratio: '16/9', width: 300, compact: true } }"
|
||
:index="1"
|
||
/>
|
||
</div>
|
||
|
||
::: warning `compact: true` 仅在无摘要时生效
|
||
:::
|
||
|
||
### 顶部大图布局
|
||
|
||
```md{5}
|
||
---
|
||
title: 文章标题
|
||
cover: /images/cover.jpg
|
||
coverStyle:
|
||
layout: top
|
||
ratio: 16/9
|
||
width: 300
|
||
---
|
||
```
|
||
|
||
效果展示:
|
||
|
||
<div style="background-color: var(--vp-c-bg-alt); padding: 20px 24px;transition: var(--vp-t-color)">
|
||
<VPPostItem
|
||
:post="{ path: '/article/ecxnxxd0/', title: '文章标题',
|
||
categoryList: [{id:'65f30c',sort:4,name:'教程'}], createTime: '2024/09/18 09:19:36',
|
||
lang:'zh-CN', excerpt:'', cover: 'https://api.pengzhanbo.cn/wallpaper/bing',
|
||
coverStyle: { layout: 'top', ratio: '16/9', width: 300 } }"
|
||
:index="1"
|
||
/>
|
||
</div>
|
||
|
||
### 预设配置
|
||
|
||
为保持视觉统一,支持集合级封面图预设:
|
||
|
||
```ts title=".vuepress/config.ts" twoslash
|
||
import { defineUserConfig } from 'vuepress'
|
||
import { plumeTheme } from 'vuepress-theme-plume'
|
||
|
||
export default defineUserConfig({
|
||
theme: plumeTheme({
|
||
collections: [
|
||
{
|
||
type: 'post',
|
||
dir: 'blog',
|
||
title: '博客',
|
||
postCover: {
|
||
layout: 'left',
|
||
ratio: '16/9',
|
||
width: 300,
|
||
compact: true
|
||
}
|
||
}
|
||
],
|
||
})
|
||
})
|
||
```
|
||
|
||
布局模式说明:
|
||
|
||
```ts
|
||
type PostCoverLayout = 'left' | 'right' | 'odd-left' | 'odd-right' | 'top'
|
||
|
||
interface PostCoverStyle {
|
||
layout?: PostCoverLayout // 布局位置
|
||
ratio?: number | `${number}/${number}` | `${number}:${number}` // 宽高比,默认 '4/3'
|
||
width?: number // 宽度(左右布局生效),默认 240
|
||
compact?: boolean // 紧凑模式,默认 false
|
||
}
|
||
```
|
||
|
||
:::warning 已知问题: `ratio` 在 markdown frontmatter 下解析问题
|
||
|
||
在 markdown frontmatter 中定义 `ratio` 时,使用 `:` 分隔符会导致解析错误,建议使用 `/` 分隔符。
|
||
|
||
如果您依然期望使用 `:` ,可以使用 `''` 包裹起来。示例:
|
||
|
||
```md /'16:9'/
|
||
---
|
||
coverStyle:
|
||
ratio: '16:9' # 而不是 ratio: 16:9
|
||
---
|
||
```
|
||
|
||
:::
|
||
|
||
特殊布局模式:
|
||
|
||
- `odd-left` - 奇数项居左,偶数项居右
|
||
- `odd-right` - 奇数项居右,偶数项居左
|
||
|
||
`odd-left` 布局效果:
|
||
|
||
<div style="background-color: var(--vp-c-bg-alt); padding: 20px 24px;display: flex;flex-direction: column;gap: 24px;transition: var(--vp-t-color)">
|
||
<VPPostItem
|
||
:post="{ path: '/article/ecxnxxd0/', title: '文章标题',
|
||
categoryList: [{id:'65f30c',sort:4,name:'教程'}], createTime: '2024/09/18 09:19:36',
|
||
lang:'zh-CN', excerpt:'', cover: 'https://api.pengzhanbo.cn/wallpaper/bing',
|
||
coverStyle: { layout: 'odd-left', ratio: '16/9', width: 300, compact: true } }"
|
||
:index="0"
|
||
/>
|
||
<VPPostItem
|
||
:post="{ path: '/article/ecxnxxd0/', title: '文章标题',
|
||
categoryList: [{id:'65f30c',sort:4,name:'教程'}], createTime: '2024/09/18 09:19:36',
|
||
lang:'zh-CN', excerpt:'', cover: 'https://api.pengzhanbo.cn/wallpaper/bing',
|
||
coverStyle: { layout: 'odd-left', ratio: '16/9', width: 300,compact: true } }"
|
||
:index="1"
|
||
/>
|
||
<VPPostItem
|
||
:post="{ path: '/article/ecxnxxd0/', title: '文章标题',
|
||
categoryList: [{id:'65f30c',sort:4,name:'教程'}], createTime: '2024/09/18 09:19:36',
|
||
lang:'zh-CN', excerpt:'', cover: 'https://api.pengzhanbo.cn/wallpaper/bing',
|
||
coverStyle: { layout: 'odd-left', ratio: '16/9', width: 300, compact: true } }"
|
||
:index="2"
|
||
/>
|
||
</div>
|
||
|
||
::: warning 移动端适配
|
||
窄屏设备上自动切换为 `top` 布局以确保显示效果
|
||
:::
|
||
|
||
## 文章元数据
|
||
|
||
在集合中通过 `meta` 选项,可以设置文章元数据的显示方式,
|
||
该设置将直接影响 **文章列表页** 和 **文章内容页** 的元数据显示:
|
||
|
||
::: code-tabs#config
|
||
|
||
@tab .vuepress/config.ts
|
||
|
||
```ts
|
||
import { defineUserConfig } from 'vuepress'
|
||
import { plumeTheme } from 'vuepress-theme-plume'
|
||
|
||
export default defineUserConfig({
|
||
theme: plumeTheme({
|
||
collections: [
|
||
{
|
||
type: 'post',
|
||
dir: 'blog',
|
||
title: '博客',
|
||
// [!code hl:11]
|
||
meta: {
|
||
tags: true, // 是否显示标签
|
||
/**
|
||
* 是否显示创建时间,或设置时间格式
|
||
* - 'short': 显示为 `2022-01-01`,默认
|
||
* - 'long': 显示为 `2022-01-01 00:00:00`
|
||
*/
|
||
createTime: true, // boolean | 'short' | 'long'
|
||
readingTime: true, // 是否显示阅读时间估算
|
||
wordCount: true, // 是否显示字数统计
|
||
}
|
||
}
|
||
]
|
||
})
|
||
})
|
||
```
|
||
|
||
@tab .vuepress/plume.config.ts
|
||
|
||
``` ts
|
||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||
|
||
export default defineThemeConfig({
|
||
collections: [
|
||
{
|
||
type: 'post',
|
||
dir: 'blog',
|
||
title: '博客',
|
||
// [!code hl:11]
|
||
meta: {
|
||
tags: true, // 是否显示标签
|
||
/**
|
||
* 是否显示创建时间,或设置时间格式
|
||
* - 'short': 显示为 `2022-01-01`,默认
|
||
* - 'long': 显示为 `2022-01-01 00:00:00`
|
||
*/
|
||
createTime: true, // boolean | 'short' | 'long'
|
||
readingTime: true, // 是否显示阅读时间估算
|
||
wordCount: true, // 是否显示字数统计
|
||
}
|
||
}
|
||
]
|
||
})
|
||
```
|
||
|
||
:::
|
||
|
||
在 markdown 中,通过 frontmatter 配置文章元数据:
|
||
|
||
```md
|
||
---
|
||
title: 文章标题
|
||
createTime: 2024/01/01 00:00:00
|
||
tags:
|
||
- tag1
|
||
- tag2
|
||
---
|
||
```
|
||
|
||
`title` 和 `createTime` 在文件创建时自动生成,支持手动修改。
|
||
|
||
### 可用属性
|
||
|
||
| 属性 | 类型 | 默认值 | 说明 |
|
||
| ---------- | ------------------- | -------- | -------------------------- |
|
||
| title | `string` | 文件名 | 文章标题 |
|
||
| createTime | `string` | 当前时间 | 创建时间 |
|
||
| tags | `string[]` | `[]` | 文章标签 |
|
||
| sticky | `boolean \| number` | false | 置顶标识,数字越大排序越前 |
|
||
| draft | `boolean` | false | 草稿模式,构建后隐藏 |
|
||
| cover | `string` | `''` | 封面图路径 |
|
||
| coverStyle | `PostCoverStyle` | `null` | 封面样式配置 |
|
||
| excerpt | `boolean \| string` | '' | 摘要内容,支持自动提取 |
|
||
|
||
同时支持[通用 frontmatter 配置](../../config/frontmatter/basic.md)中的所有字段。
|
||
|
||
## 文章摘要配置
|
||
|
||
### 自动提取
|
||
|
||
使用 `<!-- more -->` 标记摘要截断点:
|
||
|
||
```md
|
||
---
|
||
title: 标题
|
||
---
|
||
|
||
摘要内容区域
|
||
|
||
<!-- more -->
|
||
|
||
正文剩余部分
|
||
```
|
||
|
||
### 手动定义
|
||
|
||
通过 excerpt 字段自定义摘要:
|
||
|
||
```md
|
||
---
|
||
title: 标题
|
||
excerpt: 自定义摘要内容
|
||
---
|
||
```
|
||
|
||
**配置说明**:
|
||
|
||
- `excerpt: false` - 禁用摘要(忽略 `<!-- more -->`)
|
||
- `excerpt: string` - 自定义内容(忽略 `<!-- more -->`)
|
||
|
||
::: tip 推荐使用 <code><!-- more --></code> 注释定义摘要
|
||
:::
|
||
|
||
## 配置到站点首页
|
||
|
||
主题提供了两种方式来设置 post 集合 的文章列表页 到站点主页,满足不同的需求场景:
|
||
|
||
- **方式一:配置 主页的 `pageLayout` 属性为 `posts`**
|
||
|
||
```md title="docs/README.md"
|
||
---
|
||
pageLayout: posts
|
||
---
|
||
```
|
||
|
||
还可以通过 `collection` 配置项来指定读取哪个集合的文章列表页,默认读取第一个集合的文章列表页。
|
||
|
||
`collection` 需要与集合配置的 `dir` 的值相同。
|
||
|
||
```md title="docs/README.md"
|
||
---
|
||
pageLayout: posts
|
||
collection: blog
|
||
---
|
||
```
|
||
|
||
此配置会直接将页面应用 `posts` 布局,显示博客文章列表。
|
||
|
||
这是将主页修改为 博客页的 最简单的方式,但缺点是 缺少灵活性。
|
||
|
||
- **方式二:配置 主页的 `pageLayout` 属性为 `home`, 添加 `type: posts` 的首页区域类型**
|
||
|
||
```md title="docs/README.md"
|
||
---
|
||
pageLayout: home
|
||
config:
|
||
- type: posts
|
||
collection: blog
|
||
---
|
||
```
|
||
|
||
使用这种方式,你不仅可以在首页中添加 文章列表,还可以灵活的在页面的其他区域添加不同的内容。
|
||
|
||
比如,配置首屏为 `banner`,然后紧跟着 博客文章列表:
|
||
|
||
```md title="docs/README.md"
|
||
---
|
||
pageLayout: home
|
||
config:
|
||
- type: banner
|
||
- type: posts
|
||
---
|
||
```
|
||
|
||
更多自定义配置,请参考 [自定义首页](../custom/home.md)。
|
||
|
||
当使用以上两种方式 将首页配置为 文章列表页后,由于主题默认依然会生成 文章列表页,
|
||
这导致存在了重复功能的页面。为此,你可能需要在 集合配置中,
|
||
**关闭自动生成博客文章列表页**:
|
||
|
||
(还可以重新修改 分类页/标签页/归档页的链接地址)
|
||
|
||
```ts title=".vuepress/config.ts" twoslash
|
||
import { defineUserConfig } from 'vuepress'
|
||
import { plumeTheme } from 'vuepress-theme-plume'
|
||
|
||
export default defineUserConfig({
|
||
theme: plumeTheme({
|
||
collections: [
|
||
{ type: 'post', dir: 'blog', title: '博客', postList: false }
|
||
],
|
||
})
|
||
})
|
||
```
|