思源笔记 v3.0.4 变更解读:闪卡到期时间与重置、数据仓库容错与新内核 API
【免费下载链接】siyuanAn open-source, privacy-first, self-hosted knowledge workspace where humans and AI agents work together 开源、隐私优先、自托管的知识工作空间,让人与智能体在此协作项目地址: https://gitcode.com/GitHub_Trending/si/siyuan
导读
本文基于 v3.0.4 变更日志,深入拆解思源笔记(SiYuan)这一版本的核心改动。该版本围绕闪卡复习体验做了系统升级——支持为卡片设置到期时间、重置学习进度、删除当前卡片并展示卡片的复习次数与状态信息;同时改进了数据仓库损坏后的容错策略、资源文件操作和多个编辑器细节。读完本文,你将掌握 v3.0.4 闪卡相关功能的完整操作方式与底层实现原理,并能理解FSRS-4.5调度算法、/api/riff/*闪卡 API 以及新增内核 API 的调用形态。
版本概览
v3.0.4 是思源笔记 v3.0.x 系列的一个维护性版本,变更集中在以下几个方面:
- 闪卡功能:支持设定到期时间、重置卡片、复习时删除当前卡片、显示卡片复习信息,并将调度算法升级到 FSRS-4.5;
- 健壮性与安全性:数据仓库损坏后不再自动重置,网络图片转本地时填充
alt提示文字并支持//开头路径,载入挂件时路径以/结尾; - 编辑器与数据操作:改进
Fn+Del删除标题、粘贴为纯文本、代码块语言切换与剪藏转换,允许唯读模式下切换资料库检视,改进块索引效能; - 开发者能力:新增两个内部核心 API
/api/block/getBlocksIndexes与/api/file/globalCopyFiles,并在使用者指南中新增扩展开发章节。
闪卡:到期时间、重置与卡片信息
闪卡(Flashcard)是思源笔记基于内容块制卡、按间隔重复(spaced repetition)算法安排复习的功能。v3.0.4 中该模块的改进最多,也是本版本的「主角」。
支持设定到期时间与重置
此前用户无法主动干预一张卡片的复习时间,只能被动等待算法调度。v3.0.4 起,闪卡支持:
- 设定到期时间(due time):手动指定某张卡片下次复习的时间,适合「这张卡我今天想再复习一遍」「这张卡太简单了,过两周再看」这类诉求;
- 重置学习进度:将卡片恢复为未学习状态,重新开始调度,适合内容被修改、需要重新记忆的场景。
从源码看,这两个能力分别对应模型层的两个函数(kernel/model/flashcard.go):
SetFlashcardsDueTime(cardDues []*SetFlashcardDueTime)(L81-L114):批量设置卡片到期时间。请求体中的due字段采用20060102150405格式(即YYYYMMDDHHmmss),解析时使用本地时区time.ParseInLocation("20060102150405", cardDue.Due, time.Local),随后直接调用card.SetDue(due)写入卡包并持久化;ResetFlashcards(typ, id, deckID string, blockIDs []string)(L116-L181):支持两种粒度的重置——按blockIDs精确重置指定块,或按notebook(笔记本)、tree(文档)、deck(卡包)三种类型分页取回全部卡片后统一重置。若从全局管理入口进入而未指定deckID,会遍历所有卡包查找包含这些块的卡包再逐一重置。
重置并非简单地删除卡片,而是通过事务先removeFlashcards再addFlashcards(L183-L199),即把卡片从卡包中移除、移除块上的卡包属性,再以全新状态重新加入——这样卡片 ID 不变、但调度状态归零。
对应的 HTTP 接口注册在 kernel/api/router.go:
POST /api/riff/batchSetRiffCardsDueTime (设定到期时间) POST /api/riff/resetRiffCards (重置卡片)复习时删除当前卡片
在复习界面中,v3.0.4 支持直接删除当前正在复习的卡片。其实现路径是removeRiffCards接口(kernel/api/riff.go):接收deckID与blockIDs,构造一个removeFlashcards操作放入事务队列执行,最终由removeFlashcardsByBlockIDs完成卡包数据与块属性的清理(kernel/model/flashcard.go)。若指定了卡包,接口还会返回最新的deckData供前端刷新卡包状态;「全部」卡包则不返回数据。
复习计数与卡片信息展示
v3.0.4 改进了复习计数显示,并在复习界面展示卡片的复习次数、状态等完整信息。这些信息来自Flashcard结构体(kernel/model/flashcard.go):
| 字段 | 含义 |
|---|---|
deckID | 卡片所属卡包 ID |
cardID | 卡片 ID |
blockID | 卡片对应的内容块 ID |
lapses | 遗忘(lapse)次数,即「又忘了」的次数 |
reps | 复习总次数 |
state | 卡片状态(新卡 / 学习中 / 复习中 / 已掌握) |
lastReview | 上次复习时间(Unix 毫秒时间戳) |
nextDues | 按不同评分(riff.Rating)预测的「下次复习时间」人类可读文本 |
其中nextDues由newFlashcard遍历card.NextDues()生成,经过util.HumanizeDiffTime转换为「x 分钟后 / x 小时后 / x 天后」这类相对时间描述(L542-L558),让用户在评分前就能预览每个按钮对应的间隔预期。底层调度状态(Due、Reps、Lapses、State、LastReview)由getRiffCard直接从 FSRS 卡片对象映射而来(L448-L461)。
Alt+0 复习入口行为修正
此前按Alt+0打开复习入口后,会错误地回到「卡包制卡」所制作的闪卡。v3.0.4 修正了该行为,使Alt+0复习入口不再受卡包内容干扰,同时修复了「某些情况下一直显示制卡动画」的问题。
FSRS-4.5 调度算法升级
v3.0.4 将间隔重复调度核心升级为FSRS-4.5。FSRS(Free Spaced Repetition Scheduler)是一种基于算法的间隔重复调度方案,思源通过 Go 依赖github.com/open-spaced-repetition/go-fsrs/v3集成(kernel/go.mod,当前锁定 v3.3.1)。
FSRS 相关参数集中在 kernel/conf/flashcard.go 的Flashcard配置结构中:
| 配置项 | 默认值 | 说明 |
|---|---|---|
newCardLimit | 20 | 每轮复习的新卡上限 |
reviewCardLimit | 200 | 每轮复习的复习卡上限 |
mark | true | 是否启用标记制卡 |
list | true | 是否启用列表块制卡 |
superBlock | true | 是否启用超级块制卡 |
heading | true | 是否启用标题块制卡 |
deck | false | 是否启用卡包制卡 |
reviewMode | 0 | 复习模式:0 新旧混合、1 新卡优先、2 旧卡优先 |
requestRetention | 取自fsrs.DefaultParam() | 目标记忆保持率 |
maximumInterval | 同上 | 最大复习间隔(天) |
weights | fsrs.DefaultWeights() | FSRS 算法权重,共 17 个参数 |
值得说明的是,requestRetention、maximumInterval与weights这三个参数在思源中可由 FSRS 优化器基于用户真实的复习历史自动调优(源码注释中标注了 issue 9309),这也是 FSRS 区别于传统 SM-2 算法的重要特性:算法权重不是写死的,而是随个人记忆数据不断拟合。
调度相关的核心接口(注册于 kernel/api/router.go):
POST /api/riff/getRiffDueCards 获取卡包待复习卡片 POST /api/riff/getTreeRiffDueCards 获取文档待复习卡片 POST /api/riff/getNotebookRiffDueCards 获取笔记本待复习卡片 POST /api/riff/reviewRiffCard 提交复习评分 POST /api/riff/skipReviewRiffCard 跳过当前卡片 POST /api/riff/getRiffCards 获取卡包卡片 POST /api/riff/getTreeRiffCards 获取文档卡片 POST /api/riff/getNotebookRiffCards 获取笔记本卡片 POST /api/riff/getRiffCardsByBlockIDs 按块 ID 获取卡片复习动作的入口是ReviewFlashcard(kernel/model/flashcard.go):先通过reviewCardCache缓存卡片原始状态以支持「撤销评分后重新复习」,再调用deck.Review(cardID, rating)让 riff 层结合 FSRS 计算新的到期时间,随后依次保存卡包与复习日志。当卡包内无剩余待复习卡片时,会清空撤销与跳过缓存。
资料仓库:损坏后不再自动重置
v3.0.4 调整了数据仓库(data repo)的容错策略:损坏后不再自动重置。此前资料仓库在校验失败时可能直接重置,导致用户误以为数据丢失。现在仓库损坏后改为保留现场并提示用户,避免自动化操作掩盖真实的数据问题。这一改动与思源对数据安全「保守优先」的原则一致——宁可阻塞写操作,也不在未确认的情况下销毁任何既有数据。
资源文件与剪藏相关改进
本版本围绕资源文件(assets)与网页剪藏做了多项实用优化:
- 资源文件元素右键菜单新增「新视窗开启」与「开启」:可对图片、附件等资源文件直接在新窗口打开或在系统中打开(对应 kernel/api/asset.go 相关的资源文件操作);
- 网络图片转本地时填充提示文字(alt):转换后的本地图片会带上原图上下文生成的
alt描述; - 网络图片转本地支持
//开头的路径:协议相对地址(如//example.com/a.png)也能被正确识别和转换; - 载入挂件时路径以
/结尾:修正挂件目录路径的规范化,避免加载异常; - 网页剪藏改进:4 个空格开头的文字不再被误解析为代码块;代码块内容转换逻辑也得到增强;
- 嵌入 B 站 iframe 块禁止自动播放:默认不自动播放,避免页面加载即出声。
资料库(Attribute View)相关修复
v3.0.4 修复了资料库(数据库/属性视图)的几个缺陷,并允许在唯读模式下切换资料库检视:
- 唯读模式未完全禁止表格更新:此前唯读模式下表格仍可被部分更新,现已完全禁止(同时修复了「唯读模式下仍可更新表格」的遗漏路径);
- 资料库无法筛选为「空」或「不为空」的关联值:修复了关联字段的空值筛选逻辑;
- 资料库多字段排序失效:多个排序字段叠加时结果不正确的缺陷已修复。
编辑器与其他体验改进
Fn+Del删除标题元素:改进删除标题块时的处理逻辑,避免误删或残留;贴士为纯文字包含 HTML 标签时的处理:改进含 HTML 标签文本的纯文本粘贴转换;- 行内代码、键盘与标签元素渲染优化:改用等级(level)渲染,避免右侧重复渲染零宽空格;
- 块引用自动完成:空格不再终结自动补全,可继续输入以筛选候选;
- 代码块语言切换:改进切换语言时的处理;
- 文件历史项目清单显示操作类型:历史列表中标注每次变更的操作类型,便于回溯;
- 改进块索引效能:块索引性能优化(见下节);
- 行动装置自订表情调整:移动端自定义表情的调整支持。
新增内核 API:getBlocksIndexes 与 globalCopyFiles
/api/block/getBlocksIndexes
新增的内部核心 API,用于批量获取块在文档中的索引序号。接口注册于 kernel/api/router.go,请求格式:
POST /api/block/getBlocksIndexes { "ids": ["20230101000000-abcdefg", "20230101000000-hijklmn"] }服务端实现见 kernel/api/block.go:解析ids数组后调用model.GetBlocksIndexes。其核心逻辑在 kernel/model/blockinfo.go:以第一个块所在文档为基准加载整棵树,通过ast.Walk遍历,对文档的一级子块递增计数(idx++),同时为所有块记录其在遍历序中的位置,最后返回map[blockID]index。它可视为既有/api/block/getBlockIndex(单块版,kernel/api/block.go)的批量版本,用于一次性获取多个块的顺序位置,减少前端多次往返。
/api/file/globalCopyFiles
另一个新增的内部核心 API,用于将工作空间之外的绝对路径文件复制到工作空间内。接口注册于 kernel/api/router.go,并带有三重校验中间件:CheckAuth(需登录)、CheckAdminRole(需管理员角色)、CheckReadonly(唯读模式不可用)。
请求参数(kernel/api/file.go):
srcs(必填):源文件绝对路径数组,必须是绝对路径,相对路径会被拒绝;destDir(必填):目标目录,相对于工作空间的路径,最终经util.GetAbsPathInWorkspace解析。
实现上依次执行多重安全检查:
- 每个
src必须是绝对路径且文件存在; - 调用
util.IsSensitivePath拒绝复制敏感文件——kernel/util/path.go 的注释明确指出该检查正是为globalCopyFiles这类接受工作空间外绝对路径的接口收窄攻击面,覆盖常见凭据 dotfile(如.ssh、.aws等),防止内核用户越权读取敏感内容;对应拒绝逻辑有测试用例保障(kernel/util/path_test.go); - 拒绝复制加密笔记本相关的路径(
rejectEncryptedBoxPath)。
该 API 属于内部接口,主要供内核自身的扩展场景(如插件或内核模块需要从系统其他位置导入文件)使用,普通用户日常操作资源文件仍走常规导入流程即可。
文档与开发者向更新
- 使用者指南新增扩展开发章节:官方将扩展开发(自定义主题、插件等)的说明补入用户指南,便于开发者基于思源开发扩展;
- FSRS-4.5 升级:调度算法权重与计算升级,复习间隔预测更贴合个人记忆曲线;
- 新增上述两个内部核心 API,供内核与插件体系调用。
小结
v3.0.4 是一个「内外兼修」的版本:对外,闪卡复习体验显著增强——手动设定到期时间、重置进度、删除卡片、查看完整卡片信息,配合升级后的 FSRS-4.5 调度;对内,数据仓库容错更保守、块索引性能更优、资源文件操作更安全(globalCopyFiles的敏感路径防护),并为开发者新增了批量块索引查询能力。如果你正在使用闪卡进行间隔复习,这个版本值得立即升级。
【免费下载链接】siyuanAn open-source, privacy-first, self-hosted knowledge workspace where humans and AI agents work together 开源、隐私优先、自托管的知识工作空间,让人与智能体在此协作项目地址: https://gitcode.com/GitHub_Trending/si/siyuan
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考