283 lines
9.1 KiB
Markdown
283 lines
9.1 KiB
Markdown
# 个人主页 — 需求文档
|
||
|
||
## 1. 项目范围
|
||
|
||
本项目是一个**公开静态站点 + 构建时数据同步层**。
|
||
|
||
站点运行时仍然是纯静态页面,但在构建阶段由本项目主动向 Gitea / Seafile 拉取所需数据,清洗后生成本地只读数据文件,再交给 Astro 渲染。
|
||
|
||
也就是说:
|
||
|
||
- **运行时**:纯静态站点,对外公开访问
|
||
- **构建时**:服务端脚本拉取远程数据、生成内容文件
|
||
|
||
AstrBot、定时任务、手动脚本等都可以作为“触发构建”的外部入口,但**同步逻辑本身属于这个仓库的一部分**。
|
||
|
||
- 域名:`sepcomet.xyz`(备案中)
|
||
- 部署:自有服务器 Docker 环境
|
||
- 访问:完全公开,求职时可直接给链接
|
||
- 用户背景:Unity 客户端开发,Web 经验不多,怎么方便怎么来
|
||
|
||
---
|
||
|
||
## 2. 页面与功能
|
||
|
||
### 2.1 首页
|
||
|
||
- **Hero 区**:头像、名字、一句话简介、社交链接(GitHub/Gitea/Blog 等)
|
||
- **开发日志摘要**:最新 3-5 条日志的卡片列表
|
||
- **精选项目**:featured 项目的卡片展示
|
||
- **Gitea 活动概览**:贡献热力图(可选)
|
||
|
||
### 2.2 开发日志(/logs)
|
||
|
||
- 按时间倒序的日志列表
|
||
- 每条日志卡片:标题、日期、标签、摘要
|
||
- 点击进入日志详情页(/logs/[slug])
|
||
- 日志详情:Markdown 全文渲染,关联的仓库名和 commit 链接
|
||
- 内容来自 `src/content/logs/` 下的 `.md` 文件
|
||
- 首版允许日志继续由手动维护或外部系统写入;日志生成逻辑不要求在本项目内实现
|
||
|
||
### 2.3 项目展示(/projects)
|
||
|
||
- 项目卡片网格布局
|
||
- 每个项目卡片:名称、描述、封面图、标签
|
||
- 点击可展开/跳转详情:演示视频(如有)、Gitea 仓库链接、Seafile 下载链接(如有)
|
||
- 数据来源:构建时从 Gitea / Seafile 拉取并生成的结构化数据文件
|
||
- 页面层只读取最终生成数据,不直接处理上游 API 响应
|
||
|
||
### 2.4 Gitea 统计(可嵌入首页或独立页)
|
||
|
||
- 贡献热力图
|
||
- 最近活动列表
|
||
- 仓库简要信息(名称、描述、更新时间、链接等)
|
||
- 数据由构建脚本从 Gitea 拉取并清洗
|
||
- 运行时不依赖浏览器直接访问带 token 的私有 API
|
||
|
||
### 2.5 Seafile 分享(/shares 或首页侧栏)
|
||
|
||
- 文件分享链接列表,每条含:文件名、描述、链接、时间
|
||
- 数据来源:构建时从 Seafile 拉取并生成的结构化数据文件
|
||
- 支持展示特定目录或特定文件(如项目打包产物)
|
||
- 首版优先展示文件元数据与下载链接;如确有需要,可在后续增加“构建时镜像文件到站点静态目录”的能力
|
||
|
||
---
|
||
|
||
## 3. 功能优先级
|
||
|
||
**P0(必须有):**
|
||
- 首页 Hero 区(个人简介 + 链接)
|
||
- 日志列表 + 详情页(Markdown 渲染)
|
||
- 项目展示卡片
|
||
- 构建时 Gitea / Seafile 数据同步入口
|
||
|
||
**P1(很重要):**
|
||
- Gitea 贡献热力图(基于构建期抓取的数据渲染)
|
||
- 仓库摘要信息同步
|
||
- Seafile 分享列表同步
|
||
- 响应式布局
|
||
|
||
**P2(锦上添花):**
|
||
- 日志按标签/时间筛选
|
||
- 项目演示视频嵌入
|
||
- 构建时镜像特定 Seafile 文件到站点静态目录
|
||
- 深色模式
|
||
|
||
---
|
||
|
||
## 4. 技术选型
|
||
|
||
| 层 | 选型 | 理由 |
|
||
|----|------|------|
|
||
| **框架** | [Astro](https://astro.build) | 静态站点生成,原生 `.md` 支持,零 JS 默认 + 可选交互岛 |
|
||
| **样式** | CSS(当前) / Tailwind CSS(可选) | 首版以简单直接、低心智负担为主,是否接 Tailwind 以后续实现成本决定 |
|
||
| **交互组件** | Astro 原生 + 按需引入 React | 默认静态渲染;只有热力图等确需交互时再引入前端组件 |
|
||
| **内容存储** | 文件系统(`.md` + `.json`) | 构建脚本先把远程数据清洗为本地文件,再统一消费 |
|
||
| **数据同步** | Node.js 构建脚本 | 服务端拉取 Gitea / Seafile 数据,避免浏览器暴露 token |
|
||
| **部署** | Nginx + Docker | 静态文件服务,单容器 |
|
||
| **构建触发** | 手动 / 定时任务 / AstrBot | `npm run content:sync` → `npm run build` → 部署静态产物 |
|
||
|
||
---
|
||
|
||
## 5. 数据模型
|
||
|
||
### 日志 frontmatter(src/content/logs/*.md)
|
||
|
||
```yaml
|
||
---
|
||
title: "personal-homepage 项目初始化"
|
||
date: 2026-05-03
|
||
repo: "sepcomet/personal-homepage"
|
||
tags: [astro, init, setup]
|
||
summary: "搭建 Astro 项目骨架,确定目录结构与部署方案"
|
||
---
|
||
正文内容(Markdown) — 客观 diff 分析 + 主观动机,由 AstrBot 生成后写入
|
||
```
|
||
|
||
### 项目数据(示例:`src/data/generated/projects.json`)
|
||
|
||
```json
|
||
[
|
||
{
|
||
"name": "personal-homepage",
|
||
"description": "个人主页 Dashboard",
|
||
"gitea_repo": "sepcomet/personal-homepage",
|
||
"repo_url": "https://gitea.sepcomet.xyz/sepcomet/personal-homepage",
|
||
"cover_image": "/images/projects/homepage.png",
|
||
"demo_video": "https://...",
|
||
"download_link": "https://seafile.sepcomet.xyz/...",
|
||
"tags": ["astro", "web"],
|
||
"featured": true,
|
||
"updated_at": "2026-05-05T00:00:00Z",
|
||
"source": "gitea+seafile"
|
||
}
|
||
]
|
||
```
|
||
|
||
### Gitea 活动数据(示例:`src/data/generated/gitea-activity.json`)
|
||
|
||
```json
|
||
{
|
||
"updatedAt": "2026-05-05T00:00:00Z",
|
||
"days": [
|
||
{ "date": "2026-05-01", "count": 3 },
|
||
{ "date": "2026-05-02", "count": 0 }
|
||
],
|
||
"recent": [
|
||
{
|
||
"type": "push",
|
||
"repo": "sepcomet/personal-homepage",
|
||
"message": "更新首页模块结构",
|
||
"url": "https://gitea.sepcomet.xyz/...",
|
||
"time": "2026-05-05T00:00:00Z"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 分享 / 下载数据(示例:`src/data/generated/shares.json`)
|
||
|
||
```json
|
||
[
|
||
{
|
||
"name": "personal-homepage-demo.zip",
|
||
"description": "项目打包产物",
|
||
"url": "https://seafile.sepcomet.xyz/...",
|
||
"time": "2026-05-05T00:00:00Z",
|
||
"size": 12345678,
|
||
"source": "seafile"
|
||
}
|
||
]
|
||
```
|
||
|
||
### 站点配置(src/config.ts)
|
||
|
||
```ts
|
||
export const site = {
|
||
name: "SepComet",
|
||
title: "个人主页",
|
||
tagline: "Unity 开发者",
|
||
avatar: "/images/avatar.png",
|
||
gitea: {
|
||
url: "https://gitea.sepcomet.xyz",
|
||
username: "sepcomet"
|
||
},
|
||
links: [
|
||
{ name: "Gitea", url: "https://gitea.sepcomet.xyz" },
|
||
{ name: "GitHub", url: "https://github.com/sepcomet" }
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 6. 目录结构
|
||
|
||
```
|
||
personal-homepage/
|
||
├── src/
|
||
│ ├── pages/
|
||
│ │ ├── index.astro # 首页
|
||
│ │ ├── logs/
|
||
│ │ │ ├── index.astro # 日志列表
|
||
│ │ │ └── [slug].astro # 日志详情
|
||
│ │ ├── projects/
|
||
│ │ │ └── index.astro # 项目展示
|
||
│ │ └── shares.astro # Seafile 分享
|
||
│ ├── components/
|
||
│ │ ├── Header.astro
|
||
│ │ ├── Footer.astro
|
||
│ │ ├── Hero.astro
|
||
│ │ ├── LogCard.astro
|
||
│ │ ├── ProjectCard.astro
|
||
│ │ └── GiteaHeatmap.jsx # React Island
|
||
│ ├── content/
|
||
│ │ └── logs/ # *.md 日志内容
|
||
│ ├── data/
|
||
│ │ └── generated/ # 构建时同步生成的 JSON
|
||
│ │ ├── gitea-activity.json
|
||
│ │ ├── projects.json
|
||
│ │ └── shares.json
|
||
│ ├── config.ts
|
||
│ └── styles/
|
||
│ └── global.css
|
||
├── scripts/
|
||
│ ├── fetch-gitea.ts
|
||
│ ├── fetch-seafile.ts
|
||
│ └── sync-content.ts
|
||
├── public/
|
||
│ ├── images/
|
||
│ │ └── avatar.png
|
||
│ └── downloads/ # 可选:构建时镜像的下载文件
|
||
│ └── favicon.svg
|
||
├── astro.config.mjs
|
||
├── Dockerfile
|
||
├── docker-compose.yml
|
||
└── package.json
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 部署
|
||
|
||
```yaml
|
||
# docker-compose.yml
|
||
services:
|
||
homepage:
|
||
build: .
|
||
ports:
|
||
- "8080:80"
|
||
volumes:
|
||
- ./src/content:/app/src/content # 日志/项目内容热更新
|
||
- ./public/images:/app/public/images
|
||
restart: unless-stopped
|
||
```
|
||
|
||
- Docker 构建阶段:`npm run build` 生成静态文件
|
||
- Docker 构建阶段:先执行 `npm run content:sync`,再执行 `npm run build`
|
||
- 运行阶段:Nginx 托管 `dist/` 目录
|
||
- 日常更新:定时任务 / AstrBot 触发同步与重建
|
||
- Gitea / Seafile token 只存在于构建环境,不进入前端产物
|
||
|
||
---
|
||
|
||
## 8. 实施计划
|
||
|
||
| Phase | 内容 | 产出 |
|
||
|-------|------|------|
|
||
| **1** | Astro 项目初始化 + 首页/日志/项目/分享骨架 | 可访问的骨架页面 |
|
||
| **2** | 日志系统:列表页 + 详情页 + frontmatter 解析 + 示例内容 | 日志模块 |
|
||
| **3** | 数据同步层:Gitea / Seafile 拉取脚本、环境变量、生成文件 | 构建期数据链路 |
|
||
| **4** | 页面改读生成数据 + Gitea 活动真实化 + 仓库摘要接入 | 统计与项目模块 |
|
||
| **5** | Docker、定时重建、响应式打磨、深色模式、SEO | 收尾 |
|
||
|
||
---
|
||
|
||
## 9. 不在此项目范围内
|
||
|
||
- AstrBot 插件开发(独立项目)
|
||
- 日志 markdown 文件的生成逻辑(可由 AstrBot 或其他系统负责)
|
||
- 自动化部署流程(CI/CD,可后续补充)
|
||
|
||
本项目负责:**构建时拉取远程数据 / 读取本地日志 → 生成站点数据文件 → 渲染为 HTML → 静态托管**。
|