思源笔记 v3.0.4 版本深度解析:闪卡复习体系增强、数据仓库健壮性与新增内核 API
导读
思源笔记(SiYuan)v3.0.4 是一次以「闪卡(Flashcard)复习体系」为核心的能力增强版本:本版为闪卡引入了到期时间设置与重置、复习计数优化、卡信息查看以及复习中删除当前卡等能力,并同步将底层调度算法升级为 FSRS-4.5;此外还围绕数据仓库可靠性、数据库(属性视图)与只读模式、网页剪藏、资源文件处理等方向做了大量修复与改进,并向开发者开放了 getBlocksIndexes、globalCopyFiles 两个内部内核 API。读者读完本文后,可完整掌握 v3.0.4 引入的闪卡复习操作细节、数据库与剪藏行为变化,以及两个新内核 API 的请求参数、权限要求与实现要点。本文以仓库内变更记录 v3.0.4_zh_CN.md 为主体骨架,并结合当前仓库中的 Go 内核源码进行印证与展开。
版本概述:闪卡系统是本版升级主线
官方概述将本版定位为「支持闪卡设置到期时间、重置和查看闪卡信息」。展开来看,本次改进全部围绕闪卡的完整生命周期展开:
- 调度控制:闪卡支持自定义到期时间(到期后才会再次进入待复习队列)与状态重置;
- 复习过程:支持复习时删除当前闪卡,改进复习计数显示,并修复了「某些情况下一直显示制卡动画」的问题;
- 信息透明:闪卡复习界面可查看卡片的复习次数、状态等信息;
- 入口一致性:
Alt+0闪卡复习入口不再返回卡包制作的闪卡; - 算法升级:底层间隔重复调度算法升级至 FSRS-4.5(见「开发重构」部分)。
从内核实现看,闪卡复习以「到期时间(due date)升序」作为排队依据。在 kernel/model/flashcard.go 的 getCardsBlocks 中,从卡包(deck)取出卡片后先按 fsrs.Card 的 Due 字段排序:due 为零值的卡片按卡片 ID 排序,否则到期时间更早的卡片排在前面,再经分页后映射为块(block)返回;单个块的卡信息由 getRiffCard(kernel/model/flashcard.go)从 FSRS 卡片对象构造,包含到期时间等字段。这些代码印证了 v3.0.4「到期时间」成为闪卡管理核心维度的产品设计。
闪卡增强细节
本节对应原变更记录「改进功能」中与闪卡相关的条目,逐项说明操作行为与底层含义。
设置到期时间与重置
此前闪卡到期时间由算法自动计算,用户难以干预。v3.0.4 起:
- 设置到期时间:可为指定闪卡手动指定下次到期时刻,用于「提前复习」或「推迟复习」等场景;
- 重置:将闪卡的复习历史(次数、间隔、状态)清空,使其回到类似新卡的状态重新开始调度。
结合 FSRS 调度模型理解:每张卡的状态与调度参数(Due、间隔、稳定性等)由 FSRS 算法在每次评分后更新,手动设置到期时间相当于直接改写调度中的 due,进而影响其进入待复习队列的时机;而重置则把卡片恢复到初始调度状态,之后再复习时会按新卡规则重新计算权重。
复习时删除当前闪卡
复习(review)过程中可直接移除当前正在复习的闪卡,适用于「这张卡不再需要复习」的场景。注意其与「删除卡片来源内容」是不同操作——这里操作对象是卡包中的闪卡调度条目本身。
复习计数与卡信息显示
- 改进闪卡复习计数显示:修正复习次数统计的展示口径,避免计数异常导致的误导;
- 查看闪卡信息:复习界面展示当前卡的复习次数、状态等调度信息(即
getRiffCard构造的 RiffCard 数据结构中的字段),帮助用户理解「为何这张卡此时出现、下次复习间隔如何」。
制卡动画与复习入口修复
- 修复了某些情况下一直显示闪卡制卡动画的问题,避免制卡动画阻塞后续操作;
Alt+0作为全局闪卡复习入口,不再返回卡包(deck)制作的闪卡,保证入口语义一致——避免从复习入口再次看到已经用卡包制卡的内容。
调度算法升级:FSRS-4.5
开发重构条目明确记录了升级 FSRS-4.5。从配置结构看,闪卡调度参数可在用户配置中调整:Flashcard 配置结构包含 requestRetention(期望记忆保持率)与 weights(FSRS 权重串),默认权重来自 FSRS 库的 fsrs.DefaultWeights(),见 kernel/conf/flashcard.go;内核在初始化配置时也会兜底写入默认权重,相关逻辑位于 kernel/model/conf.go。升级到 FSRS-4.5 意味着复习排期将使用更新版本的优化参数集进行预测与调度。
数据仓库健壮性:损坏后不再自动重置
改进条目「数据仓库损坏后不再自动重置」是本版一项重要的可靠性变化。此前若检测到数据仓库(data repo)损坏,内核可能自动执行重置,这会带来意外丢失历史记录的风险;v3.0.4 起改为不再自动重置,转而保留现场交由用户决策,从而避免自动重置造成的二次数据损失。该行为属于内核侧数据仓库(kernel/model/repository.go)启动自检逻辑的一部分。
数据库(属性视图)交互修正
围绕「数据库」(即块级属性视图,包括表/看板/画廊等视图布局)本版同时包含增强与缺陷修复:
添加到数据库不再自动填入筛选值:将块加入数据库时不再沿用上一次操作的筛选条件,避免新加入的行被已有筛选「隐藏」而误以为添加失败;- 只读模式下允许切换数据库视图:增强只读场景的可用性——只读仍禁止修改数据,但查看不同视图布局(表格/看板/画廊等)是被允许的;
- 修复只读模式下未完全禁止表格更新:堵住此前只读模式仍可更新表格数据的漏洞,完善只读语义的一致性;
- 修复无法筛选为空或不为空的关联值:此前针对关联(relation)字段的「为空 / 不为空」筛选条件失效,本版修复后可按关联值的有无进行过滤;
- 修复数据库多字段排序失效:多字段组合排序此前可能只按单字段生效,本版修复了排序键的组合处理。
数据库相关功能的底层实现在内核 av 模块(kernel/av)与 SQL 层的属性视图查询中,涉及筛选(kernel/av/filter.go)、排序(kernel/av/sort.go)与视图布局(kernel/av/layout.go)等模块。
网页剪藏与编辑器体验改进
网页剪藏(Web Clip)
- 4 个空格开头的文本不再解析为代码块:此前剪藏 HTML 时,以 4 个空格开头的段落可能被 Markdown 解析为缩进代码块,导致大量正文被错误地折叠进代码块中;本版起按块语义转换,不再触发缩进代码块规则;
- 改进代码块内容转换:修正剪藏时
<pre>/<code>等元素向代码块转换的细节(如首尾换行、语言推断、内联代码与块级代码的区分); - 粘贴为纯文本的 HTML 处理:改进剪藏或粘贴内容中含 HTML 标签时执行「粘贴为纯文本」的处理逻辑,避免标签残留或误转义。
这些转换逻辑依赖渲染内核 Lute 的 Markdown/HTML 解析,剪藏链路可在内核侧 kernel/model/md2html.go 与剪藏相关入口中继续追踪。
行内元素渲染
- 行级代码、键盘(kbd)与标签元素渲染优化:修复行级元素右侧重复渲染零宽空格(zero-width space)的问题,避免复制或对拍文本时出现隐形字符;
- 块引用自动完成:输入块引用(ref)时,空格不再终结自动完成弹窗,只有当选择确认时才结束补全,提高长引用标题下的补全可用性;
- 代码块语言切换改进:优化代码块语言(language)的切换交互与状态展示;
- 改进
Fn+Del删除标题元素:Fn+Del(向前删除整块)作用于标题块时的处理更符合预期,避免误删或删除不完整; - 修复表格后回车异常:表格块之后直接回车出现的异常行为得到修复。
资源文件、网络图片与媒体处理
- 网络图片转换本地时填充提示文本(alt):执行「网络图片转换本地」时,会为图片补充提示文本,作为替代
alt内容填充进资源文件说明,避免转换后图片缺失说明信息; 网络图片转换本地支持//开头的路径:协议相对 URL(以//开头,如//cdn.example.com/a.png)此前无法被识别,本版起可正常转换下载;- 资源文件元素右键菜单新增
新窗口打开与打开:图片、附件等资源文件块的右键菜单中,可直接使用系统默认程序打开资源,或在独立窗口打开; - 嵌入 B 站 iframe 块禁止自动播放:插入的 B 站视频 iframe 默认禁止自动播放,避免页面加载后视频自动出声干扰;
- 加载挂件(widget)时路径以
/结尾:挂件资源加载时的路径统一以/结尾,保证相对资源(子文件、图片)引用能正确解析。
工作空间、文件历史与移动端体验
- 默认打开最后关闭的工作空间:桌面端启动时默认恢复上次退出时使用的数据目录(工作空间),减少多工作空间用户每次手动选择的成本;
- 文件历史项目列表中显示操作类型:文件历史(File History)面板的版本列表会标注每个历史版本对应的操作类型(如更新、删除等),便于定位目标版本;
- 移动端自定义表情调整:移动端自定义表情(emoji)的调整交互得到改进;
- 改进块索引性能:块索引构建相关性能优化,可缩短数据索引与搜索就绪时间,缓解大库场景下的初始化等待。
文档改进:用户指南新增扩展开发章节
「改进文档」条目显示 v3.0.4 在用户指南中新增了**扩展开发(Extend Development)**章节,面向希望基于思源进行插件、挂件与 API 扩展的开发者提供指引。这与本版同期开放的内部内核 API(见下节)相互呼应,说明 v3.0.4 同时在为二次开发与生态扩展铺路。仓库内的产品内建引导文档位于 app/guide(.sy 格式),可作为扩展能力介绍的补充参考。
开发者:新增两个内部内核 API
v3.0.4 在内核中新增了两个「内部」API。所谓内部,指它们面向内核内部与授权扩展场景(挂件/插件经授权调用),而非面向普通第三方开放的全部能力,调用时需遵守内核的鉴权与只读约束。
/api/block/getBlocksIndexes:批量获取块索引
- 路由注册:
POST /api/block/getBlocksIndexes,挂载CheckAuth鉴权中间件,见 kernel/api/router.go; - 实现位置:kernel/api/block.go;
- 请求参数:JSON 对象
{ "ids": [...] },ids为字符串数组(块 ID 列表),缺失或类型错误时返回参数解析失败; - 返回内容:将
ids收集为字符串切片后调用model.GetBlocksIndexes(ids),一次性返回多个块的索引信息,ret.Data为索引结果。
与它对应的是同文件中既有的单块查询 getBlockIndex(kernel/api/block.go),接收单个 id 后调用 model.GetBlockIndex(id)。getBlocksIndexes 的价值在于批量:在需要一次渲染大量块索引(例如文档树、反链、大纲聚合)的场景下,将 N 次单块查询收敛为一次批处理调用,配合本版「改进块索引性能」的优化可显著减少往返与重复计算。
/api/file/globalCopyFiles:全局复制文件(批量、跨位置)
- 路由注册:
POST /api/file/globalCopyFiles,挂载了CheckAuth、CheckAdminRole与CheckReadonly三层约束,见 kernel/api/router.go——即需要登录、管理员角色,且在只读模式下被拒绝; - 实现位置:kernel/api/file.go;
- 请求参数:
srcs(必填):源文件绝对路径数组,数组元素必须是字符串;路径必须为绝对路径(非绝对路径直接返回错误Field [srcs]: each path must be absolute);destDir(必填):目标目录,语义为相对于工作空间(workspace)的路径,内核通过util.GetAbsPathInWorkspace解析为工作空间内的绝对路径。
逐项校验与安全策略(实现中对应不同的错误码):
- 每个源路径先经
filepath.Abs归一化; - 文件存在性:源文件必须真实存在(
filelock.IsExist),否则返回错误-1及对应提示; - 敏感路径拒绝:通过
util.IsSensitivePath检测,命中(如内核自身的数据文件等敏感路径)时返回-2,拒绝复制(refuse to copy sensitive file); - 加密笔记本限制:源或目标位于加密笔记本(
rejectEncryptedBoxPath)时返回-3,目标目录更是在创建目录(MkdirAll)之前即被拒绝,以避免在加密笔记本内部误创建明文目录(见代码注释「在 MkdirAll 前拒绝加密笔记本目录」)。
由此可见,globalCopyFiles 是一个「内核侧统一处理文件复制」的批处理原语:对外部扩展隐藏了路径校验、敏感文件防护、加密笔记本隔离与文件锁等细节,开发者只需以工作空间为参照系提供绝对源路径与相对目标目录即可完成跨目录批量复制,无需自行绕开内核的安全限制。
下载与升级说明
v3.0.4 为正式发布版本,官方同时提供桌面端、移动端与服务器(Docker)等发行形态。升级前建议先备份工作空间与数据目录;若使用 Docker 部署,可按镜像标签拉取 v3.0.4 对应的版本并保留数据卷挂载。本仓库内保留了该版本多语言变更记录的归档副本,除中文版 v3.0.4_zh_CN.md 外,另有英文版 v3.0.4.md 与繁体中文版(v3.0.4_zh_CHT.md,位于同一目录)可供对照。
小结:v3.0.4 的版本定位
综合来看,v3.0.4 是一次「复习体验 + 数据安全 + 剪藏质量 + 扩展接口」并行的稳健型迭代:
- 闪卡体系获得完整闭环能力——到期时间可控、状态可重置、信息可见、卡片可在复习中移除,配合 FSRS-4.5 的调度升级,是使用闪卡/记忆功能的用户值得立即升级的理由;
- 数据仓库「损坏不再自动重置」与只读模式下对表格更新的封堵,体现了数据安全优先的取向;
- 网页剪藏的两处解析修复(缩进代码块误判、代码块内容转换)直接提升剪藏忠实度;
getBlocksIndexes与globalCopyFiles两个内部 API 为后续「批量索引」与「跨位置文件复制」类扩展提供了内核级基座,配合用户指南新增的扩展开发章节,向生态开发者释放了明确的扩展信号。
如果你正在基于思源仓库研究闪卡调度、数据库筛选或内核 API 设计,可以分别从 kernel/model/flashcard.go、kernel/conf/flashcard.go、kernel/av 以及 kernel/api/block.go、kernel/api/file.go 继续深入阅读。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
video-shotcraftAI宣传片skill,使用 Remotion 制作电影级产品视频:提供106 张镜头配方卡和可复用的视频魔板。适用于 Claude Code 与 Codex以及所有其他智能体Markdown00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00