给博客添加Memos页面 作者:jinote 浏览:107 字数:5296 阅读:约 18 分钟 ##项目简介 [Memos](https://github.com/usememos/memos) 是一个开源的、自托管的备忘录工具,类似 Twitter 的时间线界面。本方案将其通过 **PHP 代理** + Typecho 独立页面的方式集成到博客中。 ###技术架构 ``` 用户访问 → Typecho 独立页面 → PHP 代理 (themeInit) → Memos API (Docker) ↓ 前端 JavaScript 渲染 ↓ 调用 /?action=memos-proxy 代理路径 ``` ###为什么使用 PHP 代理? 1. **完全兼容 Typecho 伪静态**:不需要担心 Nginx 配置冲突 2. **部署简单**:不需要修改 Nginx 配置文件 3. **灵活可控**:可以添加缓存、认证、日志等功能 4. **跨平台支持**:不依赖 Nginx,Apache 环境也可使用 --- ##部署 Memos ### 1. Docker 部署(推荐) ```bash # 创建数据目录 mkdir -p /opt/memos # 运行 Memos 容器 docker run -d \ --name memos \ --restart always \ -p 5230:5230 \ -v /opt/memos:/var/opt/memos \ neosmemo/memos:0.28.0 ``` ### 2. 验证部署 访问 `http://你的IP:5230`,首次访问会提示设置管理员账号。 --- ##Typecho 主题集成 ### 1. 添加 PHP 代理代码 在主题的 `functions.php` 文件中添加以下代码(通常在文件末尾,`?>` 之前): ```php /** * Memos API PHP 代理 * 解决 Nginx 反向代理冲突问题 * 通过查询参数方式调用:/?action=memos-proxy&creatorId=1&rowStatus=NORMAL&limit=10 */ function themeInit($archive) { // Memos API 代理请求 if (isset($_GET['action']) && $_GET['action'] === 'memos-proxy') { // 获取请求参数 $creatorId = isset($_GET['creatorId']) ? $_GET['creatorId'] : '1'; $rowStatus = isset($_GET['rowStatus']) ? $_GET['rowStatus'] : 'NORMAL'; $limit = isset($_GET['limit']) ? $_GET['limit'] : '10'; $pageToken = isset($_GET['pageToken']) ? $_GET['pageToken'] : ''; // Memos 服务器地址 $memosHost = 'http://127.0.0.1:5230'; // 构建 Memos API URL $apiUrl = $memosHost . '/api/v1/memos?creatorId=' . urlencode($creatorId) . '&rowStatus=' . urlencode($rowStatus) . '&limit=' . urlencode($limit); if (!empty($pageToken)) { $apiUrl .= '&pageToken=' . urlencode($pageToken); } // 使用 cURL 请求 Memos API $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $apiUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Accept: application/json', 'Content-Type: application/json' ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); curl_close($ch); // 设置响应头 header('Content-Type: application/json; charset=utf-8'); header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type, Authorization'); if ($error) { http_response_code(500); echo json_encode(['error' => 'Failed to connect to Memos API: ' . $error]); } else { http_response_code($httpCode); echo $response; } exit; } // Memos 文件代理请求 if (isset($_GET['action']) && $_GET['action'] === 'memos-file-proxy') { // 获取文件路径参数 $filePath = isset($_GET['path']) ? $_GET['path'] : ''; if (empty($filePath)) { http_response_code(400); echo json_encode(['error' => 'Missing file path parameter']); exit; } // Memos 服务器地址 $memosHost = 'http://127.0.0.1:5230'; // 构建 Memos 文件 URL $fileUrl = $memosHost . '/' . ltrim($filePath, '/'); // 使用 cURL 请求文件 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $fileUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE); curl_close($ch); // 设置响应头 if ($contentType) { header('Content-Type: ' . $contentType); } header('Cache-Control: public, max-age=2592000'); // 30天缓存 header('Access-Control-Allow-Origin: *'); if ($response === false) { http_response_code(404); echo 'File not found'; } else { http_response_code($httpCode); echo $response; } exit; } } ``` **注意**: - 确保你的服务器已启用 PHP cURL 扩展 - `themeInit()` 函数在 Typecho 主题初始化时自动执行 - 如果主题中已有 `themeInit()` 函数,请将上述代码合并进去 ### 2. 创建独立页面模板 在主题目录创建 `page-memos.php`: ```php need('header.php'); ?> need('footer.php'); ?> ``` **关键配置说明**: - `memos`: 通过 `/?action=memos-proxy&` 调用 PHP 代理 - `fileProxy`: 通过 `/?action=memos-file-proxy&path=` 调用文件代理 - `Helper::options()->index`: 自动获取网站根地址 ### 3. 前端渲染脚本 创建 `assets/js/memos.js`,负责数据获取、分页、图片处理、Markdown 渲染等功能。 **核心功能**: - ✅ 自动加载 Memos API 数据 - ✅ 分页加载("加载更多"按钮) - ✅ Markdown 渲染 - ✅ 图片网格布局(1张/2张/3-4张自适应) - ✅ 图片预览(ViewImage) - ✅ 时间格式化(Lately.js) - ✅ 标签提取和样式化 --- ##使用说明 ### 1. 创建独立页面 在 Typecho 后台: 1. 管理 → 独立页面 → 新增 2. 标题:说说 / 动态 / Memos(自定义) 3. 模板:选择 **"Memos 动态页面模板"** 4. 发布 ### 2. 修改配置 编辑 `page-memos.php` 中的配置: ```javascript var bbMemo = { username: "你的昵称", // 显示的昵称 useravatar: "你的头像URL", // 头像图片链接 limit: '10', // 每页加载数量 creatorId: '1', // Memos 用户ID } ``` ### 3. 查看你的 creatorId 在浏览器访问: ``` http://你的IP:5230/api/v1/memos?limit=1 ``` 返回的 JSON 中,第一条数据的 `creatorId` 就是你的用户 ID(通常是 `1`)。 ### 4. 自定义样式 如需调整样式,在主题 `style.css` 中添加自定义 CSS: ```css /* 修改容器宽度 */ #bber { max-width: 800px; } /* 修改图片大小 */ .datacont .img { max-width: 280px; } ``` --- ##常见问题 ### Q1: 页面显示"加载失败,请检查 Memos 地址是否正确" **原因**: - PHP cURL 扩展未启用 - Memos 服务未启动 - creatorId 配置错误 **解决**: 1. 检查 PHP 是否启用 cURL:创建 `phpinfo()` 页面查看 2. 访问 `http://你的IP:5230` 确认 Memos 服务正常 3. 确认 `creatorId` 配置正确(通常是 `1`) ### Q2: 返回空数据 `{"memos": [], "nextPageToken": ""}` **原因**: - Memos 动态设置为 Private(私有) - creatorId 不匹配 **解决**: 1. 在 Memos 后台将动态设置为 **Public(公开)** 2. 检查 creatorId 是否正确 ### Q3: 图片不显示 **原因**: - 文件代理路径配置错误 - Memos 动态中的图片未公开 **解决**: - 确保 `fileProxy` 配置正确 - 确认 Memos 动态已设置为 Public ### Q4: "$ is not defined" 错误 **原因**: - jQuery 未加载 - Lately.js 需要 jQuery 支持 **解决**: - 确保 jQuery CDN 在 memos.js 之前加载 - 检查 CDN 链接是否可访问 ### Q5: 如何修改 Memos 端口? 如果你的 Memos 运行在其他端口(如 `:5231`),修改 `functions.php` 中的: ```php $memosHost = 'http://127.0.0.1:5231'; ``` --- ##技术要点 ### API 路径说明 Memos 0.28.0 的 API 格式: ``` GET /api/v1/memos?creatorId=1&rowStatus=NORMAL&limit=10 ``` 通过 PHP 代理调用: ``` GET /?action=memos-proxy&creatorId=1&rowStatus=NORMAL&limit=10 ``` 返回数据结构: ```json { "memos": [ { "content": "动态内容", "createTime": "2024-01-01T12:00:00Z", "attachments": [ { "name": "attachments/xxx", "filename": "image.jpg", "type": "image/jpeg" } ] } ], "nextPageToken": "xxx" } ``` ### 图片路径处理 Memos 0.28.0 使用 `/file/{name}/{filename}` 格式访问图片: ```javascript // 原始路径 imgUrl = bbMemo.fileProxy + 'file/' + res.name + '/' + res.filename; // 代理后实际路径 // /?action=memos-file-proxy&path=file/attachments/xxx/image.jpg // → PHP 代理到 http://127.0.0.1:5230/file/attachments/xxx/image.jpg ``` --- ##致谢 本方案参考了 [veryjack.com](https://veryjack.com/technique/docker-memos-shuoshuo/) 的实现思路,感谢原作者的分享! - **Memos 项目**:https://github.com/usememos/memos - **ViewImage**:https://github.com/Tokinx/ViewImage - **Lately.js**:https://github.com/Tokinx/Lately --- **如果你在使用中遇到问题,欢迎在评论区留言交流!**
Responses