vitepresss生成静态知识库


网站https://vitepress.dev/zh/guide/getting-started

npm add -D vitepress@next
npx vitepress init 脚手架创建一个初始化项目,需要回答一些问题:

bash
Where should VitePress initialize the config?
./docs

Where should VitePress look for your markdown files?
./docs

Site title:
网站标题

Site description:
网站介绍

Theme:
默认主题就行

#...后面全部yes或默认

修改运行端口

修改package.json:
"docs:dev": "vitepress dev docs --host --port 5176"
其中--host允许所有主机访问,--port 5176指定端口

运行:npm run docs:dev
构建:npm run docs:build
构建后文件在docs\.vitepress\dist 目录中

主页自动跳转到文档快速开始页(不需要主页)

docs\index.md:

md
<!-- docs/index.md -->
<meta http-equiv="refresh" content="0; url=/quickstart.html" />
# 正在跳转...
如果没有自动跳转,请点击 [进入文档](/quickstart)。

自定义简易主页

docs\index.md:

md
---
title: CrowdPulse 文档 
outline: deep # 控制右侧大纲层级(可选:deep / 2 / [2,6] 等)               
---

# CrowdPulse 文档
欢迎使用CrowdPulse。你可以从以下章节开始:

## 快速开始
- [注册用户](./login.md)
- [创建推广](./quickstart.md)

## 基础知识   
- [用户面板](./user.md)    
- [角色说明](./kol.md)
- [计费标准](./price.md) 

网站配置:

假设选择的路径为docs目录,则配置文件应该在docs.vitepress\config.mts:

ts
import { defineConfig } from 'vitepress'

export default defineConfig({
  title: "CrowdPulse文档", // 网站标题
  description: "CrowdPulse文档", // 网站描述
  lang: 'zh-CN', // 网站语言影响<html lang="zh-CN">标签
  lastUpdated: true,  // 根据 git 提交自动显示“最近更新”
  // cleanUrls: true,    // 生成干净URL,不带.html后缀
  // 网站配置
  themeConfig: {
    nav: [ 
      { text: '快速开始', link: '/quickstart' } // 导航栏
    ],
    // 侧边栏
    sidebar: [
      {
        text: '基础知识',  // 一级标题
        collapsed: false, // 手风琴菜单,传递了就自动变为手风琴菜单,false为默认展开,true为默认折叠
        items: [ // 二级标题+路由
          { text: '成为用户', link: '/login' },
          { text: '用户面板', link: '/user' },
          { text: '角色说明', link: '/kol' },
        ]
      },
      {
        text: '推广操作',  // 一级标题
        collapsed: false, // 手风琴菜单
        items: [ // 二级标题+路由
          { text: '创建推广', link: '/quickstart' },
          { text: '计费标准', link: '/price' },
        ]
      },
    ],
    // 启用内置搜索,可选
    search: {
      provider: 'local',              // 启用内置本地搜索
      options: {
        // (可选)把搜索 UI 文案改成中文
        locales: {
          root: {
            translations: {
              button: {
                buttonText: '搜索文档',      // 按钮文案
                buttonAriaLabel: '搜索文档'  // 无障碍文案
              },
              modal: {
                noResultsText: '没有找到结果',
                resetButtonTitle: '清除查询条件',
                displayDetails: '显示详细信息',
                backButtonTitle: '返回',
                footer: {
                  selectText: '选择',
                  navigateText: '切换',
                  closeText: '关闭'
                }
              }
            }
          }
        }
      }
    },
    // 下面是菜单中文化(选填)
    // 右侧“On this page”下拉的标题
    outline: {
      label: '本页目录'               // 原 "On this page"
    },
    // 回到顶部按钮
    returnToTopLabel: '返回顶部',       // 原 "Return to top"
    // (可选)其它内置文案
    sidebarMenuLabel: '目录',
    docFooter: { prev: '上一页', next: '下一页' },
    darkModeSwitchLabel: '外观',
    lightModeSwitchTitle: '切换到浅色',
    darkModeSwitchTitle: '切换到深色',
  },
  // 可选,生成网站地图
  sitemap: {
    hostname: 'https://docs.cp.5210010.xyz/docs/'
  },
})

静态文件

创建static静态文件目录要在docs目录中(和md文件同级),然后在md中使用![alt text](./static/login.png)的引用

页面加载时获取数据

例如创建一个获取价格的ts文件,docs\price.data.ts:

ts
// 平台价格接口定义
export interface PlatformPrice {
  post: string | null      // 发帖价格
  reply: string | null     // 回复价格
  retweet: string | null   // 转发价格
  like: string | null      // 点赞价格
  quote: string | null     // 引用价格
  follow: string | null    // 关注价格
  day: string | null       // 日常价格
}

// 价格数据接口定义
export interface PriceData {
  facebook: PlatformPrice
  telegram: PlatformPrice
  x: PlatformPrice
  instagram: PlatformPrice
  whatsapp: PlatformPrice
}

// 声明导出的数据
declare const data: PriceData
export { data }

export default {
  /**
   * 异步加载价格数据
   * @returns {Promise<PriceData>} 返回各平台的价格信息
   */
  async load(): Promise<PriceData> {
    try {
      // 从 API 获取价格数据
      const response = await fetch('http://127.0.0.1:8000/api/price/price_list')
      const priceData = await response.json()
      return priceData
    } catch (error) {
      console.error('获取价格数据失败:', error)
      // 返回默认数据或空数据
      return {
        facebook: { post: null, reply: null, retweet: null, like: null, quote: null, follow: null, day: null },
        telegram: { post: null, reply: null, retweet: null, like: null, quote: null, follow: null, day: null },
        x: { post: null, reply: null, retweet: null, like: null, quote: null, follow: null, day: null },
        instagram: { post: null, reply: null, retweet: null, like: null, quote: null, follow: null, day: null },
        whatsapp: { post: null, reply: null, retweet: null, like: null, quote: null, follow: null, day: null }
      }
    }
  }
}

然后创建docs\price.md:

md
# 计费标准
当前各平台操作费用(单位:元)

<script setup>
import { data } from './price.data'

// 平台名称映射
const platformNames = {
  facebook: 'Facebook',
  telegram: 'Telegram',
  x: 'X',
  instagram: 'Instagram',
  whatsapp: 'WhatsApp'
}

// 操作类型映射
const actionNames = {
  post: '发帖',
  reply: '评论',
  retweet: '转发',
  like: '点赞',
  quote: '引用',
  follow: '关注',
  day: 'KOL占用每天',
}

// 获取所有平台
const platforms = Object.keys(data)
// 获取所有操作类型
const actions = Object.keys(actionNames)
</script>

<div class="price-container">
  <table class="price-table">
    <thead>
      <tr>
        <th class="action-column">操作类型</th>
        <th v-for="platform in platforms" :key="platform">
          {{ platformNames[platform] }}
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="action in actions" :key="action">
        <td class="action-column">{{ actionNames[action] }}</td>
        <td v-for="platform in platforms" :key="platform" class="price-cell">
          <span v-if="data[platform][action] !== null" class="price">
            ${{ data[platform][action] }}
          </span>
          <span v-else class="not-available">-</span>
        </td>
      </tr>
    </tbody>
  </table>
</div>

<style scoped>
/* 这里写样式 */
</style>

这里的md中写html可能会让编辑器显示错乱,但是没报错就行

nginx配置静态网站

假设容器中的/usr/share/nginx路径与/home/nginx_ser/nginx做了映射

ini
server {
  listen 80;
  server_name docs.cp.5210010.xyz;
  root /usr/share/nginx/docs;          # 静态根目录映射到容器内 /usr/share/nginx/docs
  
  location = / {
    try_files /index.html =404;
  }
  
  # 根路由:先找真实文件/目录,最后才会 404
  location / {
    try_files $uri $uri/ =404;         # 先尝试 /path 或 /path/,都不存在才 404
  }

  # /assets 静态目录:修正 alias 路径,指向 /usr/share/nginx/docs/assets/
  location ^~ /assets/ {
    alias /usr/share/nginx/docs/assets/;  # 注意是 docs 不是 doc,并以 / 结尾
    access_log off;
    expires 7d;
    add_header Cache-Control "public";
    try_files $uri =404;                   # 以 URI 为基准进行匹配,找不到则 404
  }
}

不作为独立站部署

docs.vitepress\config.mts:

ts
base: '/docs/', //代表在docs路由下,这样生成的html也会是/docs/下

nginx配置:

ini
location = /docs {
    try_files /docs/index.html =404;
  }
  location = /docs/ {
    try_files /docs/index.html =404;
  }
  location /docs {
    try_files $uri $uri/ =404;
  }
  location ^~ /docs/assets/ {
    alias /usr/share/nginx/html/docs/assets/;  # 注意是 docs 不是 doc,并以 / 结尾
    access_log off;
    expires 7d;
    add_header Cache-Control "public";
    try_files $uri =404;                   # 以 URI 为基准进行匹配,找不到则 404
  }