SiYuan v3.6.1 版本详解:细节体验改进、安全修复与主题内核 API 深度解析
v3.6.1 是思源笔记(SiYuan)在 v3.6.x 系列中的一次面向细节的稳定版本更新。该版本以"改进一些细节"为总基调,围绕编辑器撤销、数据库字段与预览图、块链接导出、插件停靠栏、发布服务安全、桌面端启动加载、退出同步等十余处体验细节进行打磨,同时为开发者新增了两个主题相关内核 API 和一个全量表情预览页面。本文将基于官方变更记录,逐条还原该版本的改进内容与底层实现,并结合仓库源码讲解 setTheme、reloadTheme 两个新增 API 的参数规范与调用链路,帮助用户理解升级收益、帮助插件与主题开发者快速上手新接口。
一、版本概况与定位
v3.6.1 延续了思源"高频迭代、持续打磨细节"的发布节奏,从 变更记录 与中文版 v3.6.1_zh_CN.md 可见,本次变更共分为三大类:
| 类别 | 数量 | 核心主题 |
|---|---|---|
| 改进功能(Enhancement) | 10 项 | 编辑器、数据库、导出、插件、发布、桌面端、同步等细节体验 |
| 修复缺陷(Bugfix) | 1 项 | 修复若干安全漏洞 |
| 开发者(Development) | 3 项 | 新增 2 个内核 API + 1 个表情 HTML 页面 |
从变更条目对应的 issue/PR 编号(16134~17237)可以推断,这些改动横跨了约两个月的用户反馈与社区贡献积累,属于典型的"多入口汇总、细节导向"的小版本。对于普通用户而言,该版本最直接的感知点是:制卡撤销更可靠、导出块链接更完整、启动更快、退出不丢数据;对于开发者而言,则是主题切换与重载开始拥有官方内核 API。
二、改进功能逐项详解
1. 改进"快速制卡"后的撤销逻辑
快速制卡(Quick make card)是思源将任意块快速转换为卡片(用于闪卡复习)的高频操作。此前在制卡之后执行撤销,可能无法正确回退到制卡前的状态。本版本针对该场景重构了撤销栈的记录时机。
在源码层面,"制卡"入口分布在多处 UI 中,例如 navigation.ts、openTitleMenu.ts 与 gutter/index.ts,最终汇聚到 makeCard.ts 执行块转换。改进的核心思路是让制卡操作与其前后的编辑操作在历史记录(undo)中形成清晰、可回退的边界,确保一次撤销即可完整还原转换动作,而不是只回退部分属性改动。
2. 改进数据库关联字段的默认图标
思源数据库(属性视图)的"关联"(relation)字段用于建立文档、块之间的引用关系。此前新建关联字段时使用的默认图标辨识度不足,本版本优化了该默认图标,使其在数据库工具栏与字段设置中更容易与其他字段类型(文本、数字、日期、单选、多选、文件等)区分。
3. 改进关闭用户指南笔记本的体验
思源在首次安装后会内置"用户指南"笔记本,用于引导新手了解块编辑、数据库、发布等功能(对应 app/guide 目录下的 .sy 文档树)。此前用户手动关闭该笔记本时,界面反馈不够清晰,甚至可能造成困惑。本版本优化了关闭流程的交互,让"关闭"与"重新打开/恢复"的入口更明确,避免误操作导致指南丢失。
4. 改进块链接的导出
块链接((()) 语法)是思源跨文档引用的基础。此前将含块链接的文档导出为 Markdown 时,块链接可能退化为普通文本或丢失目标锚点。本版本改进了导出流程中块链接的解析与渲染,确保导出结果保留可识别的引用形式,便于在其他笔记工具或静态站点中继续使用。
5. 改进插件启用/禁用时停靠栏图标的持久性
思源插件可以注册自定义停靠栏(Dock)图标。此前在启用或禁用插件后,停靠栏布局可能出现图标残留或缺失,需要手动调整。本版本修复了停靠栏配置在插件生命周期变更时的持久化逻辑,使插件的停靠栏条目随插件状态正确增删,且不会影响其他插件与内置面板的布局。
6. 改进发布服务的安全性
发布(Publish)功能允许将笔记本以网页形式对外分享(对应 publish_access.go 等内核模块)。本版本针对发布服务做了安全加固,重点收紧访问控制与请求校验,降低公开站点被异常访问或注入的风险。对于自托管部署的用户,建议升级后复查发布站点的访问授权设置。
7. RTL 不再应用于行级公式
思源支持从右到左(RTL)的文本方向设置,用于阿拉伯语、希伯来语等场景。但此前 RTL 属性会错误地作用于行级数学公式(行内公式),导致公式渲染顺序错乱。本版本将行内公式从 RTL 作用域中排除,保证公式始终按数学规范从左到右渲染,这是对多语言排版与公式编辑并存场景的精细修复。
8. 改进桌面端主窗口的加载
桌面端(Electron)主窗口的启动加载速度与稳定性是影响体感的关键。本版本针对主窗口加载流程做了优化(相关实现位于 electron/main.js 与 electron/window.js),减少启动阶段的阻塞与闪烁,使窗口更快进入可用状态,尤其对大型工作空间(大量笔记本与文档)的启动体验有明显帮助。
9. 改进退出时的数据同步
退出应用是数据安全的关键节点。本版本加强了退出流程中的数据同步保障:在退出前确保待写入的文档、索引与数据库变更完整落盘,避免因快速关闭窗口导致"最后几分钟的编辑未保存"。这一改进与内核的存储与仓库层(storage.go、repository.go)的同步逻辑直接相关。
10. 改进数据库预览图片加载
数据库的"预览"模式(如图库画廊视图)会展示附件图片的缩略图。本版本优化了预览图片的加载策略与缓存处理,减少滚动浏览大量图片时的卡顿与重复加载。从文件结构看,这与资产(asset)管理与 assets.go 的引用解析机制相关。
三、安全修复:修复若干安全漏洞
v3.6.1 修复了若干安全漏洞(对应 issue #17209)。思源作为可自托管的本地优先知识库,其安全边界主要包括:内核 API 的鉴权、工作空间文件的访问控制、发布服务的对外暴露面等。该版本对上述攻击面进行了漏洞修复,建议所有部署了公开访问(发布、云端同步)的用户优先升级。内核侧的通用防护可见 router.go 中统一挂载的 CheckAuth、CheckAdminRole、CheckReadonly 中间件链路。
四、开发者更新:新增主题内核 API 与表情预览页
本次版本对开发者最重要的变化是新增了两个主题相关内核 API,以及一个全量表情 HTML 页面。下面结合源码逐一讲解。
1. 内核 API /api/setting/setTheme
该 API 用于以编程方式切换主题及外观模式,是主题开发者和自动化脚本期待已久的官方入口。其核心实现位于 setting.go:
func setTheme(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret)
if !ok {
return
}
var theme, appearanceMode string
var modesRaw []any
if !util.ParseJsonArgs(arg, ret,
util.BindJsonArg("theme", &theme, false, false),
util.BindJsonArg("modes", &modesRaw, false, false),
util.BindJsonArg("appearanceMode", &appearanceMode, false, false),
) {
return
}
theme, appearanceMode = strings.TrimSpace(theme), strings.TrimSpace(appearanceMode)
modes := make([]int, 0, 2)
if theme != "" {
for _, m := range modesRaw {
mf, ok := m.(float64)
if !ok {
break
}
mi := int(mf)
if mi != 0 && mi != 1 {
break
}
modes = append(modes, mi)
}
if len(modes) == 0 {
ret.Code = -1
ret.Msg = "[modes] is required ([0] for light, [1] for dark, [0,1] for both)"
return
}
}
if err := model.SetTheme(theme, modes, appearanceMode); err != nil {
ret.Code = -1
ret.Msg = err.Error()
return
}
model.InitAppearance()
util.BroadcastByType("main", "setAppearance", 0, "", model.Conf.Appearance)
}
请求参数说明(JSON Body):
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
theme |
string | 否 | 主题名称(如 daylight、midnight),为空时静默忽略 modes |
modes |
int 数组 | 条件必填 | 主题模式集合,[0] 表示仅浅色,[1] 表示仅深色,[0,1] 表示同时支持浅色与深色 |
appearanceMode |
string | 否 | 外观模式,用于指定当前启用的浅色/深色状态 |
几个值得注意的实现细节:
- 参数校验严谨:
modes中的元素仅接受0或1,其余值会中断解析;当theme非空但modes为空数组时,接口会返回错误"[modes] is required ([0] for light, [1] for dark, [0,1] for both)",避免传入无效主题模式。 - 空主题静默:当
theme为空字符串时,modes与appearanceMode会被忽略,便于调用方只更新外观模式而不切换主题。 - 完成后广播:设置成功后调用
model.InitAppearance()重新初始化外观,并通过util.BroadcastByType("main", "setAppearance", ...)向所有主窗口广播外观变更事件,前端据此实时刷新主题样式,无需重启。
从 router.go 可以看到该 API 的路由注册方式,且与其他设置类 API 一样经过三层中间件保护:
ginServer.Handle("POST", "/api/setting/setTheme", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, setTheme)
即:必须登录(CheckAuth)、必须为管理员角色(CheckAdminRole)、且当前工作空间非只读(CheckReadonly)。调用方式为 POST,请求体为 JSON。
调用示例(切换为主题 daylight,同时支持浅色与深色两种模式):
POST /api/setting/setTheme
Authorization: Token <API Token>
{
"theme": "daylight",
"modes": [0, 1],
"appearanceMode": "light"
}
2. 内核 API /api/ui/reloadTheme
该 API 用于在主题文件发生变更后强制重新加载主题,是主题开发调试流程的核心工具。实现位于 ui.go:
func reloadTheme(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
model.LoadThemes()
util.BroadcastByType("main", "setAppearance", 0, "", model.Conf.Appearance)
}
其逻辑非常简洁:调用 model.LoadThemes() 从 appearance/themes 目录重新加载主题配置与样式(思源内置主题见 themes/daylight 与 themes/midnight),然后同样通过 setAppearance 广播通知所有窗口刷新。这意味着主题开发者修改主题文件后,可以通过一次 API 调用即时看到效果,而无需重启内核。其路由注册同样位于 router.go,并挂载了与 setTheme 一致的三层中间件。
3. 新增全量表情 HTML 页面
版本同时新增了一个展示所有表情符号的 HTML 页面。思源的表情数据与配置位于 appearance/emojis(含 conf.json 与 index.html),该页面将内置的表情集合以可视化方式集中呈现,便于用户浏览、挑选表情,也方便表情包开发者核对符号与快捷键的映射关系。
五、升级与获取
v3.6.1 属于 v3.6.x 系列的小版本更新,升级方式与思源常规版本一致:
- 桌面端/移动端:在应用内检查更新,或前往官方下载页获取对应平台安装包;
- 自托管 Docker:拉取最新镜像并重建容器,启动时内核会自动完成数据迁移,无需手动干预;
- 内核 API 兼容性:新增的
/api/setting/setTheme与/api/ui/reloadTheme均为增量接口,不影响既有 API,插件与脚本可直接按本文参数规范接入。
六、小结
v3.6.1 虽然体量不大,但覆盖了编辑器撤销、数据库交互、导出、插件生态、发布安全、桌面端启动与退出同步等多个高频场景,属于"升级无感、但细节体验有明显提升"的版本。对于普通用户,建议关注快速制卡撤销、退出数据同步与主窗口加载三项改进;对于插件与主题开发者,则强烈建议将主题切换迁移到新的 setTheme / reloadTheme 内核 API 上,以获得参数校验、管理员鉴权与全端广播的官方保障。若需进一步了解相关源码,可参考 setting.go、ui.go 与 router.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