Your Name 3 дней назад
Родитель
Сommit
38753c9e16

+ 0 - 1
---

@@ -1 +0,0 @@
-templates/base.html

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+.aider*

+ 0 - 2
</html>

@@ -1,2 +0,0 @@
-
-templates/post_template.html

+ 260 - 0
DESIGN.md

@@ -0,0 +1,260 @@
+# 基于 Flask 的个人博客系统设计文档
+
+## 1. 概述
+
+本系统是一个轻量级的个人博客内容管理方案,支持通过 Web 界面上传 Markdown 博文及关联图片。后端基于 Flask 完成 Markdown 到 HTML 的渲染(含 LaTeX 支持),生成静态页面并保存。不需要数据库,所有数据以文件系统方式组织。前端采用瀑布流布局展示文章列表,风格简洁美观,仿照朋友圈的卡片式设计。
+
+## 2. 技术架构
+
+- **后端框架**:Flask  
+- **Markdown 渲染**:`markdown` + 扩展(codehilite, fenced_code, tables 等)  
+- **LaTeX 渲染**:前端 MathJax 3(服务端保留 `$...$` / `$$...$$` 标记)  
+- **文件存储**:按文章 ID 分目录存储原始 Markdown、图片,另生成独立静态 HTML 文件  
+- **元数据管理**:单一 `posts_index.json` 文件存储所有文章索引(无数据库)  
+- **前端布局**:CSS Grid 实现瀑布流卡片,深色/浅色干净主题,响应式设计  
+
+## 3. 目录结构
+
+```
+.
+├── app.py                     # Flask 主程序,路由与核心逻辑
+├── config.py                  # 配置文件(上传限制、路径等)
+├── requirements.txt           # Python 依赖列表
+├── templates/                 # Jinja2 模板
+│   ├── base.html              # 全局基础模板(含 meta、MathJax、导航栏)
+│   ├── index.html             # 博客首页(瀑布流文章列表)
+│   ├── upload.html            # 上传表单页面
+│   └── admin.html             # 管理页面(展示所有文章,提供删除操作)
+├── static/                    # 静态资源(Flask 自动提供)
+│   ├── css/
+│   │   └── style.css          # 主样式表(瀑布流、卡片、暗色/亮色风格)
+│   ├── js/
+│   │   └── main.js            # 可选前端交互(如瀑布流优化、懒加载)
+│   └── uploads/               # 用户上传的图片存储目录
+│       └── posts/             # 每篇文章的图片子目录(详见下文)
+├── generated/                 # 生成的静态 HTML 文件
+│   └── <post_id>.html         # 每篇文章对应的独立页面
+├── posts_data/                # 原始数据存储
+│   └── <post_id>/             # 以文章 ID 命名的目录
+│       ├── content.md         # 原始 Markdown 文件
+│       └── images/            # 该文章用到的图片(软链接或实际存储)
+│           └── 图片文件...
+└── posts_index.json           # 全局索引文件,存储所有文章元数据
+```
+
+> **说明**:  
+> - 图片实际保存到 `static/uploads/posts/<post_id>/` 下,以便通过 `/static/uploads/posts/<post_id>/image.png` 直接访问。  
+> - `posts_data/<post_id>/images/` 可以是一个目录软链接,也可以在主程序中统一按 ID 查找图片路径。为简化,可以在上传时直接将图片保存到 `static/uploads/posts/<post_id>/`,而 `posts_data` 中只保留 Markdown 副本。两种方案均可,本设计采用统一保存到 `static/uploads/posts/<post_id>/`,在 `posts_data` 中不再重复存储图片。
+
+## 4. 需要创建的文件清单
+
+| 文件路径 | 作用 |
+|---------|------|
+| `app.py` | Flask 应用入口,定义所有路由(首页、上传、文章详情、管理、删除) |
+| `config.py` | 配置项:`UPLOAD_FOLDER`, `GENERATED_FOLDER`, `INDEX_FILE`, `ALLOWED_EXTENSIONS`, `MAX_CONTENT_LENGTH` 等 |
+| `requirements.txt` | 依赖列表(Flask, markdown, Pygments 等) |
+| `templates/base.html` | 全局模板,包含 HTML 骨架、导航栏、MathJax 脚本、基础 CSS/JS 引用 |
+| `templates/index.html` | 首页,继承 base.html,使用瀑布流卡片渲染文章列表 |
+| `templates/upload.html` | 上传表单,支持 Markdown 文件 + 多图片选择 |
+| `templates/admin.html` | 后台管理,以表格形式列出所有文章,提供删除按钮 |
+| `static/css/style.css` | 完整样式定义(瀑布流栅格、卡片样式、按钮、代码高亮等) |
+| `static/js/main.js` | 可选前端增强(如卡片悬停效果、动态瀑布流重排) |
+| `posts_index.json` | 运行时自动生成/更新,存储结构见下文 |
+
+## 5. 核心功能设计
+
+### 5.1 文章上传与处理流程
+
+1. **接收请求**:POST `/upload`,接收 `title`(字符串),`markdown_file`(文件),`images`(多文件列表)。  
+2. **创建文章 ID**:使用时间戳(如 `int(time.time()*1000)`)或 `uuid4` 生成唯一 `post_id`。  
+3. **创建目录**:  
+   - 图片保存目录:`static/uploads/posts/<post_id>/`  
+   - 原始 Markdown 保存目录:`posts_data/<post_id>/`
+4. **保存文件**:  
+   - 将 Markdown 文件保存为 `posts_data/<post_id>/content.md`。  
+   - 将每个图片保存到 `static/uploads/posts/<post_id>/` 下,保留原文件名(需过滤危险字符)。  
+5. **解析 Markdown**:  
+   - 读取 `content.md` 内容,提取 Front Matter(若存在,使用 `frontmatter` 库或正则),获得 `title`, `date`, `summary` 等。若 Front Matter 缺失,则使用表单中的 `title`,当前时间作为发布日期,摘要从正文前 200 字生成。  
+   - 处理图片 URL:扫描 Markdown 中所有 `![](filename)` 式的本地图片引用,将 `filename` 替换为 `/static/uploads/posts/<post_id>/filename`。若图片未上传,记录警告但继续渲染。  
+6. **渲染 HTML**:  
+   - 使用 `markdown.markdown()` 并将扩展启用:`extra`, `codehilite`, `tables`, `fenced_code`。  
+   - 若需 LaTeX 支持,在渲染结果中保留 `$...$` 和 `$$...$$`(不进行转义)。  
+7. **生成静态页面**:  
+   - 使用 Jinja2 模板(如 `post_template.html`,可从 `base.html` 继承)渲染完整 HTML,内容区为上述生成的 HTML,标题为文章标题。  
+   - 保存到 `generated/<post_id>.html`。  
+8. **更新索引**:  
+   - 读取 `posts_index.json`,新增一条记录:`{ "id": post_id, "title": title, "date": iso_date, "summary": summary, "thumbnail": 首张图片路径或空 }`。  
+   - 按日期倒序排序后写回文件。
+
+### 5.2 列表页渲染(瀑布流)
+
+- 路由 `/` 读取 `posts_index.json`,将文章列表按日期倒序传入模板。  
+- 前端使用 CSS Grid 布局实现瀑布流:  
+  ```css
+  .waterfall {
+    display: grid;
+    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+    gap: 1.5rem;
+  }
+  .card {
+    background: white;
+    border-radius: 20px;
+    box-shadow: 0 4px 12px rgba(0,0,0,0.05);
+    overflow: hidden;
+    transition: transform 0.2s;
+  }
+  .card:hover { transform: translateY(-4px); }
+  ```  
+- 每个卡片包含:文章标题、日期、摘要、若存在缩略图则显示在卡片顶部。缩略图可从索引的 `thumbnail` 字段获取。
+
+### 5.3 文章详情页
+
+- 路由 `/post/<post_id>` 使用 `send_from_directory` 返回 `generated` 目录下的 `<post_id>.html`。  
+- 若文件不存在,返回 404 页面(可自定义模板)。  
+- 生成的静态页面中已包含 MathJax 脚本,正文中的 LaTeX 会被自动渲染。
+
+### 5.4 管理功能
+
+- **管理页面**:`GET /admin`,读取索引展示所有文章,提供删除按钮(需注意 CSRF,可简单用 POST 表单)。  
+- **删除文章**:`POST /admin/delete/<post_id>`,执行以下操作:  
+  - 删除 `generated/<post_id>.html`  
+  - 删除 `posts_data/<post_id>/` 整个目录  
+  - 删除 `static/uploads/posts/<post_id>/` 整个目录  
+  - 从 `posts_index.json` 中移除该条目并保存  
+  - 重定向回 `/admin`
+
+## 6. 数据格式设计
+
+### 6.1 `posts_index.json` 结构
+
+```json
+[
+  {
+    "id": "1703123456789",
+    "title": "Python 中的装饰器",
+    "date": "2023-12-21T10:30:00",
+    "summary": "装饰器是 Python 一个强大的功能...",
+    "thumbnail": "/static/uploads/posts/1703123456789/code.png"
+  },
+  ...
+]
+```
+
+### 6.2 Markdown Front Matter 建议(可选)
+
+若用户希望在 Markdown 文件头部定义元数据,支持以下格式:
+
+```yaml
+---
+title: 文章标题
+date: 2024-01-01
+summary: 自定义摘要
+---
+```
+
+可使用 `python-frontmatter` 库解析,若未安装则回退到正则或忽略。在本设计中推荐使用,但非强制。
+
+## 7. 关键实现细节
+
+### 7.1 图片路径修正函数
+
+在渲染 Markdown 之前,预处理文本:
+
+```python
+def fix_image_paths(md_content: str, post_id: str) -> str:
+    pattern = r'!\[([^\]]*)\]\(([^)]+)\)'
+    def repl(match):
+        alt, src = match.groups()
+        # 仅当 src 不含 '/' 或 'http' 且扩展名为图片时视为本地文件
+        if not src.startswith(('http://', 'https://', '/', '#')) and '.' in src:
+            new_src = f"/static/uploads/posts/{post_id}/{src}"
+            return f'![{alt}]({new_src})'
+        return match.group(0)
+    return re.sub(pattern, repl, md_content)
+```
+
+### 7.2 Markdown 渲染配置
+
+```python
+import markdown
+md = markdown.Markdown(extensions=[
+    'extra',
+    'codehilite',
+    'tables',
+    'fenced_code'
+])
+html_body = md.convert(fixed_md)
+```
+
+### 7.3 摘要提取(无 Front Matter 时)
+
+```python
+from bs4 import BeautifulSoup
+soup = BeautifulSoup(html_body, 'html.parser')
+text = soup.get_text()
+summary = text[:200] + ('...' if len(text) > 200 else '')
+```
+
+### 7.4 缩略图提取
+
+优先使用 Front Matter 中指定的 `thumbnail`,否则取正文中第一张图片的 URL。
+
+## 8. 前端样式设计要点
+
+### 8.1 整体风格
+
+- 背景色:`#f8fafc`(浅灰色),卡片纯白 `#ffffff`,圆角大半径(20px)。  
+- 字体:系统默认无衬线(-apple-system, BlinkMacSystemFont, "Segoe UI")。  
+- 导航栏:半透明白色毛玻璃效果,包含 “博客”、“上传”、“管理” 链接。  
+- 响应式:移动端禁用悬停效果,栅格 `minmax(250px,1fr)`。
+
+### 8.2 卡片内容
+
+- 若缩略图存在:`<img>` 宽度 100%,高度 180px,object-fit: cover。  
+- 标题:粗体,大小 1.25rem,上下边距。  
+- 日期:小字,灰色。  
+- 摘要:浅灰色文字,行高 1.5。  
+- 底部可加 “阅读全文 →” 链接,指向 `/post/<id>`。
+
+### 8.3 代码高亮
+
+使用 Pygments 生成 CSS 类,在 `style.css` 中引入一个默认高亮主题(如 `monokai` 或 `friendly`)。需在 Markdown 渲染时启用 `codehilite` 扩展并生成对应 HTML。
+
+### 8.4 MathJax 配置
+
+在 `base.html` 中添加:
+
+```html
+<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js" id="MathJax-script" async></script>
+```
+
+并设置 `tex: { inlineMath: [['$', '$'], ['\\(', '\\)']] }`。
+
+## 9. 路由概览
+
+| 路径 | 方法 | 说明 |
+|------|------|------|
+| `/` | GET | 首页,瀑布流文章列表 |
+| `/upload` | GET | 显示上传表单 |
+| `/upload` | POST | 处理上传,保存文章并生成静态页 |
+| `/post/<post_id>` | GET | 查看静态文章详情 |
+| `/admin` | GET | 管理页面,列出所有文章 |
+| `/admin/delete/<post_id>` | POST | 删除文章及相关文件 |
+| `/static/<path:filename>` | GET | Flask 默认静态文件路由(用于 CSS、JS、图片) |
+
+## 10. 部署与运行说明
+
+1. 安装依赖:`pip install -r requirements.txt`  
+2. 运行:`python app.py`(默认监听 `0.0.0.0:5000`)  
+3. 使用生产服务器时,可将 `generated/` 目录通过 Nginx 直接托管提升性能,但 Flask 本身也可完成。
+
+## 11. 扩展建议
+
+- 支持 RSS 订阅:从索引生成 XML。  
+- 添加文章标签系统:在索引中增加 `tags` 列表,前端做筛选。  
+- 缓存优化:列表页可定期重新生成静态文件。  
+- 图片压缩/缩略图生成:使用 Pillow 在上传时生成不同尺寸。
+
+---
+
+> 本设计文档已覆盖完整架构、目录结构、核心代码逻辑及样式取向。请后续根据本设计实现具体代码。

BIN
__pycache__/config.cpython-314.pyc


+ 101 - 0
generated/1777727092010.html

@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>WyOJ 的未来设想 - 个人博客</title>
+    <link rel="stylesheet" href="/static/css/style.css" />
+    
+    <!-- MathJax 配置 -->
+    <script>
+        MathJax = {
+            tex: {
+                inlineMath: [['$', '$'], ['\\(', '\\)']]
+            },
+            svg: {
+                fontCache: 'global'
+            }
+        };
+    </script>
+    <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js" id="MathJax-script" async></script>
+</head>
+<body>
+    <nav class="navbar">
+        <div class="nav-container">
+            <a href="/" class="nav-brand">博客</a>
+            <ul class="nav-links">
+                <li><a href="/">首页</a></li>
+                <li><a href="/upload">上传</a></li>
+                <li><a href="/admin">管理</a></li>
+            </ul>
+        </div>
+    </nav>
+
+    <main class="main-content">
+        
+<article class="post-article">
+    <h1 class="post-title">WyOJ 的未来设想</h1>
+    <div class="post-content">
+        <p>WyOJ 面向的主要用户是谁?</p>
+<p>首先是 wfyz 的同学,WyOJ 的性质首先是校内的 OJ。</p>
+<p>其次,是水平高的,还是水平低的?</p>
+<p>目前为止 WyOJ 的主要用户是水平尚可的初二到高二同学,主要的用处是来打模拟赛。虽然说理论上也有补题的作用,但是补的人不是很多。</p>
+<p>高水平的同学会上类似 hba 或者现在的 LCA 那里去集训。所以 WyOJ 应该面向低到中等偏上水平的同学。</p>
+<p>这部分同学的特点是什么?大部分的算法已经学习完成,但是有缺陷,有短板。WyOJ 应该能给他们提供一个平台,让他们可以快速认清自己的短板,快速补齐。</p>
+<p>这需要什么?首先需要让他们知道自己有短板、短板在哪里。其次需要让他们知道怎么补,怎么做题,做哪些题。</p>
+<p>这其实很重要。我在役时间只有一年。前大半年我基本上都是在学算法,到第二年的四五月份左右,NOIP 级的算法我早就掌握完了,还学了一堆屁用没有的 ds。</p>
+<p>直到六七月模拟赛开始多起来,我才逐渐意识到我的比赛成绩与水平非常之低。七八月我去了 mx 集训,在那里我可以说打了一百万场模拟赛,但是回来之后似乎提升并没有想象的那么多。</p>
+<p>我观察到这似乎是一个非常共同的问题。</p>
+<p>总结一下这个问题是什么呢:</p>
+<ul>
+<li>
+<p>只接受过集训,针对性的训练比较少,害怕打模拟赛</p>
+</li>
+<li>
+<p>智力在线,算法点满了,但不均衡</p>
+</li>
+<li>
+<p>通过模拟赛意识到自己有大问题,但是靠自己不太清楚怎么补,或者是就算找到了题单,也做不下去</p>
+</li>
+</ul>
+<p>比如说,我早就认识到我的贪心是个大问题,我找了一堆贪心的题单,包括 CF 的 ABCD 这种难度的题目去训练。</p>
+<p>但是问题在哪里:做不出来的题目还是做不出来,能做出来的题目本来就能做出来。训练效果为零。</p>
+<p>最终我的 NOIP 在贪心上撞死了。我想,如果我在役时把贪心给补好,也许结果会很不一样。</p>
+<p>但我已经退役很久了。我希望能让以后的同学们不再受类似的问题困扰。</p>
+<p>所以说,怎么办?</p>
+<p>WyOJ 应该提供一个专题训练的功能。</p>
+<p>具体就是用大模型。</p>
+<p>互联网的优点就是大量的数据,这也是他的缺点,我们要做的就是选出我们要的那些数据来。</p>
+<p>我想要的数据是优质的、有中文题面、带题解的题目。我能想到的是洛谷爬的 Codeforces、AtCoder 的题目。理由如下:</p>
+<ul>
+<li>
+<p>有中文题面,好做</p>
+</li>
+<li>
+<p>质量有一定保证</p>
+</li>
+<li>
+<p>有题解,虽然数量参差不齐但是可以选择题解数量多的</p>
+</li>
+</ul>
+<p>CF 提供了一点 API,但是似乎没有提供读取题面的 API,看来他不怎么希望能让别人爬他的题面。At 的 API 似乎也差不多。</p>
+<p>用洛谷的好处是我已经会了,WyOJ Shojo 可以打个样。Shojo 这个名字太二了,换成 Maid 还好点儿。</p>
+<p>然后我们可以用大模型去阅读这些题解,得到对这个题的一个大概认识。</p>
+<p>我还没有认真学好深度学习,虽然整了本书,但只看到 CNN,离着 LLM 还远。</p>
+<p>然后通过一些类似 IOI 赛制的比赛来测试每个人的能力,再不断测试出每个人各项能力的大致分数区间,随后针对性推荐题目。</p>
+<p>这是个推荐网络,推荐网络里头似乎有很多有意思的算法,深度学习里头也有很多有意思的算法。</p>
+<p>这个草稿还相当简略,但是想法已经成型了。</p>
+<p>我非常期待这套系统能早日成功,帮助像曾经的我那样的同学们能够获得更好的分数。</p>
+    </div>
+</article>
+
+    </main>
+
+    <footer class="footer">
+        <p>&copy; 2026 个人博客系统</p>
+    </footer>
+
+    <script src="/static/js/main.js"></script>
+    
+</body>
+</html>

+ 70 - 0
posts_data/1777727092010/content.md

@@ -0,0 +1,70 @@
+WyOJ 面向的主要用户是谁?
+
+首先是 wfyz 的同学,WyOJ 的性质首先是校内的 OJ。
+
+其次,是水平高的,还是水平低的?
+
+目前为止 WyOJ 的主要用户是水平尚可的初二到高二同学,主要的用处是来打模拟赛。虽然说理论上也有补题的作用,但是补的人不是很多。
+
+高水平的同学会上类似 hba 或者现在的 LCA 那里去集训。所以 WyOJ 应该面向低到中等偏上水平的同学。
+
+这部分同学的特点是什么?大部分的算法已经学习完成,但是有缺陷,有短板。WyOJ 应该能给他们提供一个平台,让他们可以快速认清自己的短板,快速补齐。
+
+这需要什么?首先需要让他们知道自己有短板、短板在哪里。其次需要让他们知道怎么补,怎么做题,做哪些题。
+
+这其实很重要。我在役时间只有一年。前大半年我基本上都是在学算法,到第二年的四五月份左右,NOIP 级的算法我早就掌握完了,还学了一堆屁用没有的 ds。
+
+直到六七月模拟赛开始多起来,我才逐渐意识到我的比赛成绩与水平非常之低。七八月我去了 mx 集训,在那里我可以说打了一百万场模拟赛,但是回来之后似乎提升并没有想象的那么多。
+
+我观察到这似乎是一个非常共同的问题。
+
+总结一下这个问题是什么呢:
+
++ 只接受过集训,针对性的训练比较少,害怕打模拟赛
+
++ 智力在线,算法点满了,但不均衡
+
++ 通过模拟赛意识到自己有大问题,但是靠自己不太清楚怎么补,或者是就算找到了题单,也做不下去
+
+比如说,我早就认识到我的贪心是个大问题,我找了一堆贪心的题单,包括 CF 的 ABCD 这种难度的题目去训练。
+
+但是问题在哪里:做不出来的题目还是做不出来,能做出来的题目本来就能做出来。训练效果为零。
+
+最终我的 NOIP 在贪心上撞死了。我想,如果我在役时把贪心给补好,也许结果会很不一样。
+
+但我已经退役很久了。我希望能让以后的同学们不再受类似的问题困扰。
+
+所以说,怎么办?
+
+WyOJ 应该提供一个专题训练的功能。
+
+具体就是用大模型。
+
+互联网的优点就是大量的数据,这也是他的缺点,我们要做的就是选出我们要的那些数据来。
+
+我想要的数据是优质的、有中文题面、带题解的题目。我能想到的是洛谷爬的 Codeforces、AtCoder 的题目。理由如下:
+
++ 有中文题面,好做
+
++ 质量有一定保证
+
++ 有题解,虽然数量参差不齐但是可以选择题解数量多的
+
+CF 提供了一点 API,但是似乎没有提供读取题面的 API,看来他不怎么希望能让别人爬他的题面。At 的 API 似乎也差不多。
+
+用洛谷的好处是我已经会了,WyOJ Shojo 可以打个样。Shojo 这个名字太二了,换成 Maid 还好点儿。
+
+然后我们可以用大模型去阅读这些题解,得到对这个题的一个大概认识。
+
+我还没有认真学好深度学习,虽然整了本书,但只看到 CNN,离着 LLM 还远。
+
+然后通过一些类似 IOI 赛制的比赛来测试每个人的能力,再不断测试出每个人各项能力的大致分数区间,随后针对性推荐题目。
+
+这是个推荐网络,推荐网络里头似乎有很多有意思的算法,深度学习里头也有很多有意思的算法。
+
+这个草稿还相当简略,但是想法已经成型了。
+
+我非常期待这套系统能早日成功,帮助像曾经的我那样的同学们能够获得更好的分数。
+
+
+

+ 9 - 1
posts_index.json

@@ -1 +1,9 @@
-[]
+[
+  {
+    "id": "1777727092010",
+    "title": "WyOJ 的未来设想",
+    "date": "2026-05-02T13:04:52.026706+00:00",
+    "summary": "WyOJ 面向的主要用户是谁? 首先是 wfyz 的同学,WyOJ 的性质首先是校内的 OJ。 其次,是水平高的,还是水平低的? 目前为止 WyOJ 的主要用户是水平尚可的初二到高二同学,主要的用处是来打模拟赛。虽然说理论上也有补题的作用,但是补的人不是很多。 高水平的同学会上类似 hba 或者现在的 LCA 那里去集训。所以 WyOJ 应该面向低到中等偏上水平的同学。 这部分同学的特点是什么?大...",
+    "thumbnail": ""
+  }
+]

+ 0 - 2
{% endblock %}

@@ -1,2 +0,0 @@
-
-static/css/style.css


+ 0 - 0
现在我将提供 `SEARCH/REPLACE` 块。static/css/style.css