前言我记笔记的方式比较懒散：想到什么写什么，写完了再想着整理。但整理这件事本身很费脑子，尤其是两件事让我特别烦。一是我用 Obsidian 配合 Typecho 写博客，每篇文章前面都要填 frontmatter：aliases、分类、tags、概述 这些字段。每次发文前我都得自己盯着空字段想：这篇文章该归到哪一类？tags 怎么取才合适？概述一句话怎么说清楚？填一次还好，文章多了之后，每次都要重新动脑，真的很累。二是看视频学习的时候，我习惯把字幕或者逐字稿复制下来，再整理成笔记。但网上常见的提示词模板大多是通用型的，不是偏重知识类就是偏重新闻类，跟我实际看的视频类型对不上。每次都要改提示词、删不需要的模块、调整输出格式，最后整理出来的笔记还是不尽人意。所以我干脆做了两个 Skill：一个叫 fill-frontmatter，一个叫 video-note。fill-frontmatter：让 frontmatter 自己长出来这个 Skill 的想法很简单：我把文章丢给它，它帮我分析全文主题，然后把空的元数据字段填上。它不会乱填。执行的时候，它会先扫描文章的所有小节标题，给每个小节提取几个关键词，再把这些关键词汇总成主题清单。然后根据主题清单去匹配或生成 aliases、分类、tags、概述。如果某个字段本来已经有值，它就不会覆盖。我比较喜欢它的一点是，它会优先参考我已经在 Typecho 里建好的分类和标签，不会每次都给我造一套新的体系。这样我的笔记库和博客站点的分类标签能保持一致，后面找东西也方便。另外，像 banner、slug、保护密码 这种需要人工判断或包含敏感信息的字段，它会主动跳过，不会自作主张。video-note：把视频文案变成能看的笔记video-note 解决的是另一个问题：视频内容太杂，通用提示词不够用。我在设计它的时候，把视频内容分成了五种类型：知识类、资讯类、故事类、技能/教程类、观点/评论类。每种类型对应一套不同的笔记生成策略。比如知识类会梳理概念、补充术语解释；教程类会拆解步骤、标注注意事项；观点类会提炼论点、梳理论据和反方视角。如果视频同时包含几种类型，它也能处理：先判断主类型，再把次要类型里的一两个核心模块融合进来，并在笔记开头标注这是混合类型。输出格式我也固定下来了：最前面是折叠起来的完整原文，后面才是整理好的笔记正文。这样我既能快速看到重点，又保留了原始素材，以后想回看原文也不会丢。怎么使用这两个 Skill 都是围绕我的 Obsidian 工作流来用的，但用法略有不同。fill-frontmatter 需要先运行一个辅助脚本 get-metas.mjs，从 Typecho 站点拉取已有的分类和标签列表。然后在 Obsidian 里打开要发布的文章，调用 Skill，它会把分析结果填充到 frontmatter 里。填完之后我会快速扫一遍，确认分类和 tags 没问题就完事。video-note 更偏提示词。我在 Obsidian 里新建一个笔记，把视频文案贴进去，然后调用对应的提示词。它会先判断视频类型，再按类型输出结构化的笔记，最后直接写回当前文件。两个都不需要我去记复杂的操作流程，核心目标都是一致的：减少重复思考，让我把精力放在内容本身。最后做这两个 Skill 是觉得笔记工作流里有些步骤本来就不该消耗那么多注意力。填 frontmatter、整理视频笔记这些事情，交给一个稳定的规则去做，比每次自己临时想一遍要轻松得多。如果你也有类似的烦恼，也许可以试试看。不是照搬我的做法，而是想想自己笔记流程里有哪些步骤是重复、机械、却又不得不做的，把它们固化成规则，后面会省很多事。
自动化将Obsidian的笔记同步到typecho的方案开发
从「找到合适的发布插件」到「干脆自己改一个」，记录如何让 Obsidian 里的笔记在保存时自动同步到 Typecho 博客，并在这个过程中把通信协议、字段映射、自动推送和图片上传逐一重构。起点：为什么想要一套笔记到博客的同步方案我的笔记和博客长期分属两个系统。Obsidian 负责日常记录、整理和输出，Typecho 负责把成稿发布出去。理想状态下，写完一篇笔记后，应该只需点一下按钮或者保存文件，文章就出现在博客上。如果后续修改，博客上的版本也应该跟着更新，而不需要再登录后台复制粘贴。这个需求听起来并不复杂，但要把体验做得顺畅，涉及几个问题：发布动作要简单、更新要自动、图片等附件要正确上传、Frontmatter 元数据要能控制文章的标题、分类、标签、状态等字段。再加上一些个人偏好，比如用文件名做标题、用中文命令触发、保存后自动推送，现成的方案很难一次性满足。于是我开始在 GitHub 上找相关项目，最终锁定了两个基础仓库作为二次开发的起点。对现有的Obsidian同步到typecho插件的对比可以看这篇文章：三款 Obsidian-Typecho 同步插件横向对比分析两个原项目obsidian-typecho-publisher：已有的 Obsidian 发布插件skyue/obsidian-typecho-publisher 是一个相对成熟的 Obsidian 插件，功能架构很清晰：通过 XML-RPC 协议与 Typecho 通信，支持读取 Frontmatter、上传图片、转换 Wiki-Link、截断内容，并把文章发布或更新到博客上。插件内部有 PublishService、XmlRpcClient、设置面板、i18n 等模块，整体结构对我非常有参考价值。它的核心流程大致如下：flowchart TB A[Obsidian 笔记文件] --> B[解析 Frontmatter] B --> C[图片上传] C --> D[Wiki-Link 转换] D --> E[内容截断] E --> F[剥离 Frontmatter] F --> G[XML-RPC 发布/更新] G --> H[回写 typecho_postid]但在实际测试中，我发现两个关键问题：一是每次更新文章都会新建一篇，无法实现真正的「更新」；这个问题排查了很久，但都找不到为什么，怀疑是 Typecho 服务端 XML-RPC 的实现存在问题。既然服务端肯定要动，那不如把通信协议一并换掉，从 XML-RPC 迁移到 RESTful API。typecho-plugin-Restful：Typecho 的 RESTful 插件Chen2226/typecho-plugin-Restful 提供了一个 Typecho 的 REST API 扩展，包含文章、页面、分类、标签、评论、文件等端点。它正好可以作为新的服务端基础，让我不用再从零写 API 路由和鉴权。不过原版的端点和字段设计比较通用，并没有针对 Obsidian 发布场景做专门优化。例如文章发布接口只支持 title、text、slug、mid 等少量字段，匹配策略是「slug 优先、title 回退」，没有 cid 精确匹配，也没有状态、密码、评论开关、封面图、摘要等字段。因此服务端也需要做比较大的改动，才能配合新的 Obsidian 插件工作。需求梳理与方案取舍在开始写代码之前，我把需求分成三层：必须有的基础功能、希望优化的体验、未来可能做的扩展。基础功能对 Obsidian 中的单篇笔记执行发布，自动推送到 Typecho。保存文件后自动检测变化并同步更新。本地图片和附件上传到博客，博客正文中的相对路径替换为远程 URL。体验优化用文件名作为文章标题，而不是从 Frontmatter 的别名字段读取。评论开关用 Frontmatter 中的布尔值控制。支持封面图、文章摘要、slug 自动回填、公开状态修改、访问密码、分类与标签自动创建等。标题不一致时二次提醒，避免意外覆盖其他文章。扩展想法通过 AI 快速生成标签元数据。（后面打算通过编写一个skill来实现）从头图或图库中自动选择封面图，不用每次手动去复制图片链接。娱乐影音阅读管理类的特殊页面同步。关于附件管理，我一开始想联动自托管的 obsidian-fast-note-sync 服务，让图片由同步服务管理，博客只引用链接。但这两个服务本身没有为这种场景设计，不修改源码很难打通。权衡之后，还是选择最稳妥的方案：图片随文章一起上传到 Typecho 作为附件。二次开发的整体思路最终方案是「保留 obsidian-typecho-publisher 的交互流程和业务逻辑，把底层通信协议从 XML-RPC 换成 RESTful，再补齐两端缺失的字段和能力」。也就是说，Obsidian 端的用户操作、设置面板、发布流程基本沿用原有设计，但 XmlRpcClient 被完全替换为新的 RestfulClient；Typecho 端则在 Restful 插件基础上扩展发布接口、上传接口和后台配置。flowchart LR subgraph Obsidian O1[main.ts] --> O2[PublishService] O2 --> O3[RestfulClient] end subgraph Typecho T1[Plugin.php] --> T2[Action.php] T2 --> T3[postArticle] T2 --> T4[upload] T2 --> T5[fileList] T2 --> T6[deleteFile] end O3 -.->|JSON REST API| T1下面分别记录服务端和客户端的具体改动。服务端改造：typecho-plugin-Restful服务端基于 Chen2226 的 Restful 插件，版本号升级到 1.3.0。最大的改动是 postArticle 接口的重构，其次是上传接口和后台配置面板。文章发布接口的三级匹配策略原版接口用 slug 或 title 匹配文章，在高频修改场景下容易出错。我把它改成三级回退：如果请求里带了 cid 且大于 0，优先按 cid 精确查询并更新。cid 未命中时，按 authorId + slug 查询。都未命中则新建文章。这样只要 Obsidian 端在 Frontmatter 中保留了 cid，后续更新就不会因为标题或 slug 的变化而错改到其他文章。新增和扩展的字段发布接口从只支持少量字段，扩展为支持完整的文章元数据：字段说明cid文章 ID，0 或未匹配到文章时新建；正整数时优先按 cid 匹配，未命中可回退 slug 匹配created自定义发布时间，Unix 时间戳banner封面图 URL，写入自定义字段 thumbdescription文章摘要 / SEO 描述statuspublish / hidden / password / private / waitingpassword访问密码，仅在 status=password 时生效allowComments0 关闭评论，1 允许评论mid分类 / 标签 ID返回值也做了语义化，例如 {"cid": 45, "type": "add", "slug": "my-post"}，让 Obsidian 端能明确知道是新增还是更新，并回写 slug。上传接口的多格式兼容为了让 Obsidian 插件能以不同方式上传图片，上传接口通过新增的 Util.php 支持三种格式：标准的 multipart/form-data 文件上传。JSON 中的 Uint8Array 字节数组，通过 pack('C*', ...$bytes) 还原为文件。Base64 字符串，包括 data:*;base64,xxx 和纯 base64 两种形式。新增文件管理接口除了上传，还增加了 /api/deleteFile 删除附件、/api/fileList 分页获取附件列表，以及 /api/upgrade 插件自更新接口，方便在后台一键检查并拉取最新代码。CORS 与鉴权调整原版 CORS 要求 Origin 在白名单内，否则不返回 Access-Control-Allow-Origin。但 Obsidian 插件作为非浏览器客户端，通常不会携带 Origin 头。我改成：无 Origin 头时自动允许 *，有 Origin 头时再按白名单校验。这样既保留浏览器的安全限制，又让 Obsidian 客户端能直接调用。鉴权方面，高敏接口默认通过 apiToken 校验，并允许关闭登录校验，让纯 Token 认证场景更易用。后台配置面板的小调整服务端插件的配置面板原本已经比较完整，包含 API 状态开关、CORS 域名、字段隐私过滤、设置项白名单、CSRF 盐值、API Token、高敏接口登录校验以及一键升级按钮。每个 API 开关的说明来自代码注释的中文翻译，并会显示对应的端点路径，例如 GET /api/posts。我主要在这个基础上增加了一个 Butterfly 主题检测提示：检测到 Butterfly 时显示绿色提示，未检测到时显示黄色提示并说明摘要会通过 方式实现。这样用户在配置时就能直观知道 description 字段会如何存储。客户端改造：obsidian-typecho-publisherObsidian 端基于 skyue 的插件，版本号升级到 2.0.0。核心变化是通信协议替换、字段映射调整和自动推送机制的增加。通信协议：XML-RPC → RESTful我删除了 xmlrpc-client.ts，新增 restful-client.ts。新的客户端通过 JSON 与 Typecho 通信，主要调用以下端点：端点用途POST /api/postArticle发表或更新文章POST /api/upload上传图片，使用 base64 JSONGET /api/categories获取分类列表GET /api/tags获取标签列表POST /api/addMetas自动创建缺失的分类或标签GET /api/userList获取用户列表，自动填充 authorIdGET /api/post获取文章详情，用于标题比对POST /api/deleteFile删除附件连接配置与字段映射设置面板删除了 xmlrpcUrl、username、password，改为 apiUrl、apiToken、authorId。authorId 旁边加了「获取用户」按钮，可以自动填充。Frontmatter 字段名也做了统一：原版的 typecho_postid 改为 cid，更符合 Typecho 本身的命名习惯。发布成功后，cid 和 slug 会自动回写到 Frontmatter。标题取值与标题不一致提醒新增 useFilenameAsTitle 选项，开启后文章标题直接取文件名，忽略 Frontmatter 中的 title 和正文第一个 # 标题。关闭时则按「Frontmatter → 正文第一个标题 → 文件名」的优先级取值。另一个安全机制是「标题不一致提醒」：当 cid > 0 且手动推送时，插件会先获取云端文章标题与本地比对，如果不一致会弹窗确认，避免 cid 被意外修改后覆盖到别的文章。自动保存推送这是本次改动里最实用的功能之一。文件保存后，插件会在 3 秒防抖后自动推送。为了避免无意义的重复发布，我加了几个保护：基于 DJB2 哈希对比文件内容，内容没有实质变化时跳过。记录 cid 变化，如果发现 Frontmatter 中的 cid 被改成本地不存在的值，停止自动推送并通知用户。用 autoPublishRunning Set 做并发保护，同一文件不会同时被推送多次。因回写 cid/slug 触发的保存会被识别并跳过。图片上传重构图片上传从 XML-RPC 的 newMediaObject 改为 POST /api/upload。缓存策略从「基于 Vault 相对路径」改为「基于文件内容哈希」，相同内容的图片不会重复上传。上传失败时不会阻断整篇文章的发布，而是弹出单张图片的失败通知并继续处理其余图片。同时也保留了 Cloudflare R2 图床的支持，通过 AWS Signature V4 计算签名，适合想把图片放到独立存储的场景。内容截断重写原版内容截断只能匹配 1-3 级标题，且逻辑比较粗糙。我重写了 markdown-utils.ts 中的截断函数，支持 1-6 级所有标题，并只移除匹配标题及其子内容，后续内容保留。这样可以在发布时去掉某些仅在本地使用的章节，而不影响正文其余部分。Wiki-Link 转换与 i18nWiki-Link 转换现在会排除图片链接 !...，只对普通双链 [[...]] 做替换。其实wikilink转换最好是在Obsidian笔记库里面本身完成统一，而不是上传的时候让插件来转换，目前我的笔记库中的所有链接统一使用markdown格式。设置面板、命令面板、右键菜单等处的触发文字统一改为中文「推送到 Typecho」。i18n 字符串表也做了相应更新，移除 XML-RPC 相关文案，增加 RESTful、自动推送、封面图、摘要、状态、密码、评论开关等新文案。摘要与 SEO 描述字段的透传如果 Frontmatter 中填写了 description 字段，插件会把它同时作为文章摘要和 SEO 描述发送给服务端；如果没有填写，则传空值，不会根据正文自动生成摘要。这个功能只是把用户已经写好的描述同步到博客上，而不是替用户生成。服务端会根据是否安装 Butterfly 主题 做不同处理：检测到 Butterfly 时，把 description 写入 summaryContent 和 desc 等独立字段；未检测到时，则把描述包在一个隐藏 div 中，并在正文开头插入 标记，让普通主题也能通过 Typecho 摘要机制展示概述。具体应该会在文章的正文开头显示概述内容，实际效果未经过测试。修复的两个关键 Bug在改造过程中，顺手修复了原版中比较影响体验的问题。标题截断不生效且只支持 1-3 级标题原版的标题取值逻辑和长标题处理在某些 Frontmatter 配置下会异常，导致截断功能失效。新版本通过 useFilenameAsTitle 和更鲁棒的标题解析解决了这个问题，并把截断范围扩展到 1-6 级标题。同步后的文章无法被解析为 Markdown这个问题与服务端有关。Typecho 在保存正文时，如果没有 标记，可能会把 Markdown 当纯文本处理。我在 postArticle 中自动为正文章 prepend 该标记，确保同步后的文章能被正确渲染为 Markdown。原插件这个问题应该是要在typecho的设置中开启对应的XML的解析 markdown 才行，不过我这边反正不走这个就无所谓了目前的效果完成改造后，日常使用流程大致是这样的：在 Obsidian 中写完一篇笔记，点击 Ribbon 按钮或右键选择「推送到 Typecho」，文章就会发布到博客上，并自动在 Frontmatter 中写入 cid 和 slug。之后只要修改笔记并保存，3 秒后博客上的文章会自动更新。flowchart LR A[Obsidian 保存笔记] --> B{已有 cid?} B -->|是| C[自动更新文章] B -->|否| D[弹窗确认新建] D --> E[发布并回写 cid/slug] C --> F[完成] E --> F现在已支持的功能包括：手动推送与保存后自动推送。用文件名作为标题，或按优先级自动提取标题。Frontmatter 控制分类、标签、状态、密码、评论开关、封面图、摘要。本地图片自动上传并替换 URL，支持内容哈希缓存避免重复上传。Wiki-Link 自动转换为博客链接。标题不一致时二次确认，防止误覆盖。Frontmatter 中的 description 同时作为文章摘要与 SEO 描述透传到博客；Butterfly 主题写入独立字段，其他主题通过 实现摘要。尚未完成的主要是娱乐影音阅读管理类的特殊页面同步，这部分需要更独立的界面和模板处理，计划后续单独实现。一些还可以继续做的事这个方案已经能覆盖我 90% 以上的发布需求，但还有一些想法没做进去：发布时自动获取当前笔记的头图链接，或从图库中随机/手动选择封面图，并回写到 Frontmatter。娱乐影音阅读管理页的文章同步，可能需要隐藏首页显示并做成独立入口。这些暂时列在待办里，等实际使用一段时间后再决定优先级。总结这次二次开发本质上是一次「协议替换 + 字段补齐 + 体验优化」的组合改造。obsidian-typecho-publisher 提供了很好的发布流程骨架，typecho-plugin-Restful 提供了 REST API 基础，我把两者对接起来，并针对自己的使用习惯做了一些调整。项目主要使用AI进行的vibe coding，确实好用，主体部分大概只花了一天就开发完成了。两个二开后的仓库地址如下，如果有类似需求可以参考：Obsidian 插件：bluemoon23333/obsidian-typecho-publisherTypecho 服务端插件：bluemoon23333/typecho-plugin-Restful参考链接skyue/obsidian-typecho-publisher — 原版 Obsidian 发布插件Chen2226/typecho-plugin-Restful — 原版 Typecho RESTful 插件bluemoon23333/obsidian-typecho-publisher — 二开后的 Obsidian 插件bluemoon23333/typecho-plugin-Restful — 二开后的 Typecho 服务端插件haierkeys/obsidian-fast-note-sync — 自托管笔记同步服务
AI生成标注此文章由AI生成，不保证正确性，请注意甄别1. 项目概览对比维度obsidian-typechoobsidian-typecho-publishertypecho-xmlrpc-publisher插件 IDtypechotypecho-publishertypecho-xmlrpc-publisher版本0.1.51.0.41.3.0作者ChenSKYueHans J. Han编程语言TypeScriptTypeScriptJavaScript (纯 JS)代码行数~1200+ (9个文件)~1600+ (7个文件)~535 (单文件)文件数量20 (含配置和资源)16 (含配置和资源)2构建工具esbuildesbuild无 (直接分发)运行时依赖i18next无无最低 Obsidian0.15.01.12.01.5.02. 通信协议对比维度obsidian-typechoobsidian-typecho-publishertypecho-xmlrpc-publisher通信协议RESTful API (自定义)XML-RPC (MetaWeblog API)XML-RPC (MetaWeblog + Blogger API)服务端要求需安装配套插件 Typecho Restful仅需 Typecho 原生 XML-RPC仅需 Typecho 原生 XML-RPC鉴权方式Token (Bearer 风格)用户名+密码用户名+密码JSON vs XMLJSON 请求/响应XML 请求/响应XML 请求/响应API 封装层HttpUtils 类 (get/post)XmlRpcClient 类 (call/newPost/editPost/uploadMedia)XmlRpc 静态工具类 (buildCall/parseResponse)开箱即用❌ 需要额外安装服务端插件✅ 原生 XML-RPC 即可✅ 原生 XML-RPC 即可3. 功能特性对比3.1 核心发布功能功能obsidian-typechoobsidian-typecho-publishertypecho-xmlrpc-publisher新建文章✅✅✅更新已有文章❌ (每次都是新建)✅ (通过 typecho_postid)✅ (通过 cid)Frontmatter 自动读取❌✅ (9个字段可映射)✅ (7个字段可映射)Frontmatter 回写✅ (slug/title/tags等)✅ (typecho_postid)✅ (cid/slug/dateCreated等)发布时间处理由服务端决定✅ (从 Frontmatter 读取)✅ (可配置偏移 + 当前时间)Slug 回退策略Hash 自动生成✅ 日期格式模板❌ 留空让 Typecho 生成内容预览✅ (文章摘要 HTML)❌❌发布进度弹窗✅ (Notice)✅ (自定义 Modal + 链接)✅ (Notice)3.2 图片与文件处理功能obsidian-typechoobsidian-typecho-publishertypecho-xmlrpc-publisher粘贴图片自动上传✅ (核心特色)❌❌图片上传到图床上传到 RESTful API 服务端✅ R2 (AWS SigV4) + Typecho 附件❌图片上传缓存❌✅ (path→URL 缓存)❌文件管理✅ (上传/删除/复制URL/预览)❌❌批量文件上传✅ (进度条+取消)❌❌Wiki-Link 转换❌✅ (双链 → 博客 URL)❌3.3 文章管理功能功能obsidian-typechoobsidian-typecho-publishertypecho-xmlrpc-publisher浏览文章列表✅ (分页+筛选)❌✅ (getRecentPosts)删除文章❌❌✅导入文章到 Obsidian✅ (htmlToMarkdown)❌✅ (含 YAML frontmatter)同步发布时间❌❌✅文章预览✅ (HTML 渲染)❌❌分类/标签树形浏览✅ (层级展开)❌❌管理分类/标签✅ (添加)❌❌3.4 高级特性功能obsidian-typechoobsidian-typecho-publishertypecho-xmlrpc-publisherFrontmatter 类型校验❌✅ (严格校验)❌内容截断❌✅ (按标题)❌ 校验❌✅ (可选)❌多种发布状态❌✅ (publish/draft/pending/private/future)✅ (草稿开关)自定义文章类型❌✅ (post/page)❌国际化✅ i18next✅ 内置双语❌ (仅中文)插件图标✅ (自定义 SVG)✅ (send 图标)❌右侧面板集成✅ (ItemView)❌❌4. 代码质量与架构对比维度obsidian-typechoobsidian-typecho-publishertypecho-xmlrpc-publisher类型安全✅ TypeScript✅ TypeScript❌ JavaScript模块化✅ 9个模块文件✅ 7个模块文件❌ 单文件 (内聚但耦合)设计模式基础分层依赖注入 + 策略模式直接过程式可测试性中等高 (依赖注入)低 (全局状态)代码可维护性中等高中低 (单文件但逻辑清晰)ESLint✅❌❌构建复杂度中等 (esbuild + tsc)中等 (esbuild + tsc)无构建PHP 错误处理N/A (RESTful)✅ (自动清理)❌ (未处理)5. 用户体验对比维度obsidian-typechoobsidian-typecho-publishertypecho-xmlrpc-publisher发布触发方式1种 (Ribbon)4种 (Ribbon/Command/FileMenu/EditorMenu)3种 (3个 Command)是否弹窗编辑✅ (界面丰富)❌ (一键发布)✅ (弹窗编辑)新建/编辑确认❌✅ (弹窗确认)❌ (cid 自动判断)发布后反馈Notice 文字Modal (含链接+统计)Notice 文字学习曲线中等 (配置多)较高 (字段映射+图床)低 (配置简单)安装复杂度高 (需服务端插件)低 (原生 XML-RPC)极低 (2个文件)中文文档✅ (README 中英)✅ (README 中英)❌ (仅 manifest 描述)6. 优劣分析6.1 obsidian-typecho — 优势功能最丰富: 不仅支持发布，还有右侧面板、文件管理、图片粘贴上传、文章预览等 IDE 级功能图片粘贴上传: 独有的"粘贴即上传"功能，是内容创作者最需要的工作流优化RESTful API: JSON 格式更现代，调试更友好，可扩展性更强树形分类/标签: 直观的层级结构展示Slug 映射缓存: 自动化 Slug 管理文件管理: 内置文件上传/删除/复制URL/图片预览功能6.2 obsidian-typecho — 劣势需要服务端插件: 最大门槛 — 必须安装额外的 Typecho 插件，限制了用户群体不支持更新: 每次发布都是新建文章，无法更新已有文章版本较低 (0.1.5): 功能可能不够稳定配置项较多: Host + Token + User 三个配置项，相比另两者更复杂不支持 Frontmatter 自动读取: 需要手动在弹窗中填写元数据无发布状态管理: 无法控制草稿/发布/定时等状态6.3 obsidian-typecho-publisher — 优势功能最完善的 XML-RPC 发布器: 一键发布 + 图片处理 + 双链转换 + 内容截断 + 类型校验开箱即用: 无服务端插件依赖，配置 XML-RPC 即可使用严格的类型校验: 确保 Frontmatter 数据类型正确，避免发布失败Cloudflare R2 图床: 支持专业的外部图床，带有 AWS Signature V4 签名和上传缓存Wiki-Link 转换: 独有的 双链 → 博客 URL 功能，连接 Obsidian 知识图谱与博客内容截断: 可以隐藏草稿、变更日志等私密段落依赖注入架构: 代码质量高，易于测试和扩展丰富的发布入口: Ribbon + Command + FileMenu + EditorMenu进度弹窗: 带成功/失败反馈和可点击的文章链接自动新建/编辑: 通过 typecho_postid 自动区分6.4 obsidian-typecho-publisher — 劣势学习曲线较高: 字段映射、URL 模板、截断标题等配置项较多R2 配置复杂: Cloudflare R2 需要 Account ID/Access Key/Secret Key 等多项凭证无文章管理功能: 无法浏览/删除/导入服务器上的文章无文件管理: 不支持文件上传管理6.5 typecho-xmlrpc-publisher — 优势极简部署: 仅 2 个文件，无需构建，即拷即用纯 JavaScript: 不需要 npm/TypeScript 知识即可修改功能最均衡: 同时支持发布、更新、删除、导入、同步发布时间可配置的 Frontmatter 键: 允许用户自定义所有键名时间偏移: 发布和同步两个独立的时区调整文章管理: 支持删除和导入（含完整 YAML frontmatter）版本最高 (1.3.0): 可能迭代次数最多，相对成熟分类必填校验: 防止无分类的"孤儿"文章6.6 typecho-xmlrpc-publisher — 劣势无类型安全: JavaScript 代码存在运行时类型错误风险代码耦合度高: 单文件包含所有逻辑，可维护性相对较低无图片处理: 不支持图床上传或图片处理无国际化: 仅中文界面无内容转换: 不支持 Wiki-Link 转换、内容截断等高级功能XML 解析脆弱性: PHP 8.x 下可能遇到弃用警告打乱 XML7. 技术栈雷达图式对比 obsidian-typecho obsidian-typecho-publisher typecho-xmlrpc-publisher 功能丰富度 ████████████ ██████████ ██████ 开箱即用度 ██ ████████ ██████████ 代码工程质量 ████████ ████████████ ██████ 类型安全 ████████ ████████████ ██ 部署简易度 ████ ██████ ██████████ 图片处理能力 ██████████ ██████████ ██ 文章管理能力 ██████████ ██ ████████ 发布体验 ██████ ██████████ ████████8. 适用场景推荐选择 obsidian-typecho 如果你:愿意安装服务端插件需要图片粘贴自动上传（文字创作者的核心需求）需要在 Obsidian 内管理 Typecho 文件（上传/删除/预览）需要树形分类/标签浏览偏爱 RESTful API 胜过 XML-RPC需要富功能面板体验选择 obsidian-typecho-publisher 如果你:追求一键发布的极致效率使用 Cloudflare R2 作为图床需要 Wiki-Link → 博客链接 转换需要 Frontmatter 类型严格校验需要内容截断隐藏私密段落重视代码质量和可维护性需要多入口发布 (命令/右键/Ribbon)选择 typecho-xmlrpc-publisher 如果你:追求极简部署（2个文件即用）需要发布 + 更新 + 删除 + 导入全套文章管理需要同步发布时间到本地喜欢在发布前弹窗编辑（标题/标签/分类/发布时间）使用纯 JavaScript 项目，不想引入构建工具需要可配置的 Frontmatter 键名9. 综合评分评分维度obsidian-typechoobsidian-typecho-publishertypecho-xmlrpc-publisher功能完整性⭐⭐⭐⭐⭐ (5/5)⭐⭐⭐⭐ (4/5)⭐⭐⭐ (3/5)易用性⭐⭐⭐ (3/5)⭐⭐⭐⭐ (4/5)⭐⭐⭐⭐⭐ (5/5)代码质量⭐⭐⭐⭐ (4/5)⭐⭐⭐⭐⭐ (5/5)⭐⭐⭐ (3/5)部署难度⭐⭐ (2/5)⭐⭐⭐⭐ (4/5)⭐⭐⭐⭐⭐ (5/5)发布体验⭐⭐⭐ (3/5)⭐⭐⭐⭐⭐ (5/5)⭐⭐⭐⭐ (4/5)服务端兼容⭐⭐ (需要插件)⭐⭐⭐⭐⭐ (原生)⭐⭐⭐⭐⭐ (原生)图片处理⭐⭐⭐⭐ (4/5)⭐⭐⭐⭐⭐ (5/5)⭐ (1/5)可扩展性⭐⭐⭐⭐ (4/5)⭐⭐⭐⭐⭐ (5/5)⭐⭐ (2/5)10. 总结这三款插件代表了三种不同的设计哲学：obsidian-typecho 走的是 "平台化" 路线 — 把 Obsidian 变成一个 Typecho 的管理客户端，功能最丰富但代价是需要服务端插件和更多配置。obsidian-typecho-publisher 走的是 "专业发布" 路线 — 专精于发布链路，在图片处理、双链转换、内容截断等方面做到极致，是三个中发布体验最好的。typecho-xmlrpc-publisher 走的是 "极简实用" 路线 — 用最少的代码实现最核心的功能（发布+管理），部署成本最低，学习曲线最平缓。如果只选一个作为长期使用，obsidian-typecho-publisher 是最均衡的选择。它在功能深度和易用性之间取得了最佳平衡，同时代码质量最高，架构最清晰。但如果你的核心需求是"粘贴图片自动上传"或"文章管理面板"，那么 obsidian-typecho 更适合你。
引言在Unity3D中实现3D角色移动与跳跃有多种实现方式，以下是三种基础的主要实现方式的对比分析和推荐方案：一、组件对比分析1. Transform组件特点：直接修改坐标位置，无物理模拟优点：完全可控的位移，适合简单机制缺点：需要手动处理碰撞，无法与物理系统互动适用场景：2D游戏或不需要物理交互的简单移动2. Rigidbody组件特点：基于物理引擎的刚体模拟优点：自动处理碰撞和重力支持力和速度控制（AddForce）可实现真实的物理效果（如斜坡滑落）缺点：需要调节质量/阻力参数可能出现"滑冰感"适用场景：需要物理交互的3D游戏（如被爆炸冲击波影响）3. Character Controller特点：专为角色设计的非物理移动组件优点：内置斜坡/台阶处理精确控制移动（Move方法）自带碰撞检测（isGrounded）缺点：需要手动处理重力与跳跃逻辑适用场景：平台跳跃类游戏或需要精细控制角色的场景二、推荐方案通常来讲，对于无需玩家操控的物体使用Rigidbody，对于要配合动画进行玩家操作的角色，推荐组合使用 Character Controller1. 移动控制选择// 使用Character Controller示例代码 public class PlayerController : MonoBehaviour { private CharacterController controller; private float verticalVelocity; private bool isJumping; void Start() { controller = GetComponent<CharacterController>(); } void Update() { // 水平移动 Vector3 moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); moveDirection = transform.TransformDirection(moveDirection); moveDirection *= moveSpeed; // 跳跃逻辑 if (controller.isGrounded) { verticalVelocity = -1f; // 微小向下的力保证接地检测 if (Input.GetButtonDown("Jump")) { verticalVelocity = jumpForce; isJumping = true; animator.SetTrigger("Jump"); // 触发跳跃动画 } } else { verticalVelocity -= gravity * Time.deltaTime; isJumping = false; } moveDirection.y = verticalVelocity; controller.Move(moveDirection * Time.deltaTime); } }2. 动画系统实现Animator Controller设置：创建状态机包含：Idle/Run/Jump/Fall等状态使用混合树(Blend Tree)处理不同移动速度的动画过渡添加参数：Speed（Float）、IsGrounded（Bool）、Jump（Trigger）动画参数更新：// 在Update中更新动画参数 animator.SetFloat("Speed", controller.velocity.magnitude); animator.SetBool("IsGrounded", controller.isGrounded);3. 扩展性设计模块化设计：将移动、跳跃、动画控制拆分为独立脚本动作扩展：// 后续可添加新动作（如翻滚） public void PlayRollAnimation() { animator.SetTrigger("Roll"); // 添加位移逻辑... }使用动画层：通过Animator Layer实现不同身体部位的独立动画（如上半身持枪，下半身奔跑）三、Rigidbody与Character Controller最好只择其一一、为什么建议「二选一」？底层冲突机制：CharacterController 通过Move()方法直接修改坐标Rigidbody 通过物理引擎计算位置同时使用会导致两套系统争夺控制权（例如角色卡顿、穿墙）典型冲突表现：// 错误用法示例：同时操作两种组件 void Update() { controller.Move(moveDir); // 直接修改坐标 rigidbody.AddForce(force); // 物理引擎修改坐标 }可能出现：角色移动抽搐/碰撞失效/重力异常官方文档建议："CharacterController does not require a Rigidbody. In fact, having both may cause undefined behavior."—— Unity官方文档二、是否完全不能组合使用？在特定需求下可以有限组合，但需要遵循以下原则：方案1：Rigidbody作为物理接收器// 组件配置： - CharacterController (主移动) - Rigidbody (IsKinematic = true) // 关闭物理位置计算 // 脚本示例： void OnCollisionEnter(Collision other) { if (other.gameObject.CompareTag("Explosion")) { Vector3 force = CalculateExplosionForce(); rigidbody.isKinematic = false; // 临时启用物理 rigidbody.AddForce(force, ForceMode.Impulse); StartCoroutine(ResetKinematic()); } } IEnumerator ResetKinematic() { yield return new WaitForSeconds(1f); rigidbody.isKinematic = true; // 恢复控制器主导 }适用场景：需要临时受外力影响的剧情事件方案2：物理驱动为主// 组件配置： - Rigidbody (约束Rotation) - CustomMovementScript // 通过AddForce实现移动 void FixedUpdate() { if (isGrounded) { rigidbody.AddForce(moveDir * acceleration); } rigidbody.velocity = Vector3.ClampMagnitude(rigidbody.velocity, maxSpeed); }优势：可实现真实的物理交互（如被车撞飞）代价：需要处理惯性带来的"滑冰感"三、CharacterController如何实现重力？完全不需要Rigidbody，通过手动计算实现：public class GravityHandler : MonoBehaviour { private float verticalSpeed; private const float GRAVITY = 9.81f; void Update() { if (controller.isGrounded) { verticalSpeed = -0.5f; // 微小向下力维持接地状态 } else { verticalSpeed -= GRAVITY * Time.deltaTime; } Vector3 move = new Vector3(0, verticalSpeed, 0); controller.Move(move * Time.deltaTime); } }关键点：接地检测依赖controller.isGrounded重力加速度需手动模拟（建议值：2倍真实重力）四、方案选型决策树graph TD A[是否需要与物理对象互动?] --> |是| B[是否要求精确控制?] A --> |否| C[使用纯CharacterController] B --> |是| D[CharacterController + 事件触发物理] B --> |否| E[纯Rigidbody方案] D --> F[如爆炸时临时启用Rigidbody] E --> G[处理惯性/摩擦力参数]五、最佳实践建议基础移动架构：CharacterControllerAnimatorCustomMovementScript (无Rigidbody)// 移动逻辑：void Update() { HandleMovement(); // 使用Move() HandleGravity(); // 手动重力 HandleJump(); // 自定义跳跃}物理交互实现技巧：方案A：通过CharacterController.Move()模拟受力// 受击退效果示例 public void ApplyKnockback(Vector3 force) { StartCoroutine(KnockbackRoutine(force)); } IEnumerator KnockbackRoutine(Vector3 force) { float duration = 0.5f; while (duration > 0) { controller.Move(force * Time.deltaTime); force = Vector3.Lerp(force, Vector3.zero, 0.1f); duration -= Time.deltaTime; yield return null; } }方案B：临时切换物理控制器private bool isPhysicsActive; void Update() { if (!isPhysicsActive) { // 正常CharacterController移动 } } void ActivatePhysics(Vector3 force) { isPhysicsActive = true; controller.enabled = false; rigidbody.isKinematic = false; rigidbody.AddForce(force); }动画融合技巧：// 在Animator中混合物理动画 animator.SetFloat("FallSpeed", verticalSpeed); // 使用动画遮罩层实现上半身不受物理影响 animator.SetLayerWeight(1, 1.0f); // 第1层控制上半身六、各方案性能对比|指标|纯CharacterController|纯Rigidbody|混合方案||-|-|-|-||CPU占用|低（无物理计算）|中高|中||内存占用|低|中|中||物理交互复杂度|需手动实现|自动|按需切换||移动精度|高|中|高||适合场景|平台跳跃/ACT|沙盒/物理游戏|动作RPG|总结你的原始脚本不需要Rigidbody：之前的重力实现完全可以通过手动计算完成，添加Rigidbody是画蛇添足物理需求的正确实现路径：90%的基础功能：纯CharacterController10%的特殊物理需求：通过协程/临时启用Rigidbody实现扩展建议：使用State Pattern管理不同移动状态（行走/跳跃/受击），每个状态独立处理物理需求四、开发细节分离输入与物理响应，详细可以查看后面新出的文档物理参数调节：重力建议值：根据需求调整，太小可能会很飘跳跃力建议值：4-8（根据角色尺寸调整）移动速度建议值：2-6 m/s动画衔接优化：在动画状态过渡中设置合理的Exit Time和Transition Duration使用动画事件触发脚步声/跳跃音效碰撞检测增强：// 添加底部射线检测提高接地判断精度 if (Physics.Raycast(transform.position + Vector3.up * 0.1f, Vector3.down, 0.2f)) { // 接地处理... }输入优化：// 使用Input System Package实现多设备输入支持 PlayerInput playerInput = GetComponent<PlayerInput>(); Vector2 input = playerInput.actions["Move"].ReadValue<Vector2>();
引言对于网站相关的技术，我并不算了解。大学期间就学过一个 webapp 的制作课程项目，基本上仅限于了解。所以所有的搭建都是基于可视化，低代码的形式实现的。搭建过程在搭建博客时考虑了几种选择，主要为现在最常见的一些选择：WordPress，Halo，Solo，hexo，typecho，poezite主要参考的教程博客Poezit号称最美博客，确实很好看，但是推荐的服务器性能需求在 1H1G最后考虑到我的学习成本，时间成本都不富裕，选择性能较好，搭建方便，有后端的typecho整体搭建非常方便：使用宝塔面板安装常规环境 Nginx1.21 + PHP7.4 + Mysql5.7再直接部署typecho系统+butterfly主题最后进行简单的设置就部署完成辣头像设置引用博客主题头像需要设置两处：显示在首页的左侧边栏中：主题外观设置——初级设置——头像设置，填写图片地址，请确保这个图片地址是没有防盗链的，最简单方式就是在文章编辑页面右侧附件上传图片可以获得图片地址显示在时光机、评论、右上角顶部的头像处：gravatar（全球通用头像），打开后台——控制台——个人设置，点击左侧的头像，去该网站使用你在个人设置里填写的电子邮箱地址注册账号，并上传头像，typecho的头像会自动更新或者打开var/Typecho/Common.php，找到下面的代码，大概在939行，使用本地图片进行替换博客图片来源要想搭建出好看的博客，合适的文章头图是不可缺少的。个人倾向于使用一些acg相关的动画图片，于是选择去各个图库网址寻找个人使用的二次元图库来源：比较精选，类别也不少https://wallpaper.ur1.fun高清精选，可能质量会过高https://www.someacg.top/各种插画，质量还行https://anime-pictures.net/偏向二游相关，质量挺高的，但是预览有水印次元小镇 – 动漫爱好者分享社区ヽ(✿゜▽゜)ノ二次搭建过程此前的服务器到期了，有段时间没有把网站搭上耽误了一段时间，总算是又把网站搭上了新的服务器和域名因为都放在国内，所有还得走备案流程，只能说备案还是比较麻烦的，没什么经营需求的，其实完全可以放在国外服务器上二次搭建使用1panel面板，php8.1恢复备份的时候出了点问题，数据上似乎有点不兼容，相关的附件文件啥的也全都丢失了应该是因为使用1.3版本的typecho，和之前使用的差了一个版本的原因以后恢复备份的时候最好还是保证使用的环境一样比较好，或者干脆进行整个服务器的备份迁移，单独备份博客的数据再恢复还是比较折腾的