-
JS 求助,在右上角添加「PgUp PgDn 」上下翻页按钮
2025-10-09 22:390.0.6 版
改进无论是自读滚动还是模拟拖动滚动条效果,均 alt 暂停/继续,esc 退出滚动

模拟拖动滚动条效果
自滚动效果(实际不会抖动,录制失帧问题看起来抖动)
原 0.0.5 版
-
JS 求助,在右上角添加「PgUp PgDn 」上下翻页按钮
2025-10-09 21:470.0.5 已更新
- 增加自滚动功能;
- 调整提示信息根据参数开关显示隐藏

所有功能均在 3.3.4 Mac 和 Windows 上测试通过(如有问题,请在新空间测试试试,并查看控制台是否有本代码相关的报错信息)。
参数如下
// 是否开启自滚动功能 true 开启 false 不开启
const isAutoScroll = true;// 滚动速度,每次滚动距离,默认 1 像素,支持小数,越小速度越慢,尽量用小数点级别去调
const autoScrollSpeed = 1; -
JS 求助,在右上角添加「PgUp PgDn 」上下翻页按钮
2025-10-09 19:130.0.4 更新内容如下
- 调整快捷键;
- 增加 alt+ 点击下方向键 模拟鼠标按住滚动条拖动,再次按 alt 关闭模拟滚动;
- 增加按 shift/shift+ctrl 时箭头翻转效果;
- 增加详细提示文本;
- 删除向上按钮
所有功能都可以通过开关开启和关闭。

2 模拟滚动哪个,系统出于安全考虑是无法捕获拖动的,这里通过 js 算法模拟实现,如果有问题可以通过开关关闭。
-
JS 求助,在右上角添加「PgUp PgDn 」上下翻页按钮
2025-10-09 15:080.0.3 更新内容
1 新增 alt+ 点击下方向键 向下滚动指定行
2 alt+shift+ 点击下方向键,向上滚动指定行
3 向上或向下滚动时,会保留一定的重叠区域,方便浏览时衔接(alt+ 点击除外)
参数
// alt+ 点击 滚动高度,这里用行高 * 3 表示,由于每个人的行高不一样,这里可自行修改
const altClickScrollHeight = 34 * 3;// 重叠高度,当上下滚动时,有一部分重叠区域不滚动(并非完全滚动整个视窗),方便上下文衔接,可根据自己需要修改
const overlap = 40;有其他问题再说吧
-
[js] 文档加密
2025-10-09 14:08注意:getRealPw 函数是计算真实密码的函数,由于明文很容易被看出算法。为了增加安全性,可用以下函数替换该函数,以达到简单混淆的目的。
但,再次提醒,前端加密并不能做到安全,且还可以通过网络抓取 api 调用获取真实数据。
以下函数由 Qwen 提供(仅供参考)。
function getRealPw(_0x3aef2d) { if (!_0x3aef2d) return ''; const _0x5f4e = [83, 84, 65, 84, 73][0] - 78; const _0x1c2b = '_0x3aef2d'['length'] - 4; const _0x9a3c = (1 << 2) + 1; if (_0x3aef2d['length'] <= _0x5f4e + _0x1c2b + _0x9a3c) return ''; let _0x7d1e = _0x3aef2d['slice'](_0x5f4e); _0x7d1e = _0x7d1e['slice'](0, -_0x1c2b); const _0x2f8a = Math['floor'](_0x7d1e['length'] / 2); return _0x7d1e['slice'](0, _0x2f8a - 2) + _0x7d1e['slice'](_0x2f8a + 3); }还有以下两种思路供参考,给人以疑惑感。
function getRealPw(pw) { if (!pw) return ''; // "NQ==" 是 "5" 的 Base64 const config = atob("NQ==") + atob("NQ==") + atob("NQ=="); // "555" const [p, l, m] = config.split('').map(Number); // [5,5,5] if (pw.length <= p + l + m) return ''; let s = pw.slice(p); s = s.slice(0, -l); const mid = Math.floor(s.length / 2); return s.slice(0, mid - Math.floor(m / 2)) + s.slice(mid + Math.ceil(m / 2)); }function getRealPw(pw) { if (!pw) return ''; const steps = [ () => pw.length, () => '\u0035\u0035\u0035\u0035\u0035'.length, // '55555'.length = 5 () => '\u0035'.charCodeAt() - 48, // 53 - 48 = 5 () => [,,,].length + 2, // 3 + 2 = 5 (len, p, l, m) => len > p + l + m, (str, p) => str.slice(p), (str, l) => str.slice(0, -l), (str) => Math.floor(str.length / 2), (s, mid, m) => s.slice(0, mid - Math.floor(m / 2)) + s.slice(mid + Math.ceil(m / 2)) ]; const len = steps[0](); const p = steps[1](); const l = steps[2](); const m = steps[3](); if (!steps[4](len, p, l, m)) return ''; let s = steps[5](pw, p); s = steps[6](s, l); const mid = steps[7](s); return steps[8](s, mid, m); } -
JS 求助,在右上角添加「PgUp PgDn 」上下翻页按钮
2025-10-09 13:35已更新到 0.0.2
- 修复滚动算法错误(之前的视窗计算有误差);
- 增加按住 ctrl 键 + 点击向下方向键,实现向上翻页功能
- 取消平滑滚动(即滚动动画效果)
- 向上翻页按钮可选,当
isShowPageUpBtn设为 true 是同时显示,默认只显示向下翻页按钮
然后编辑上翻页按钮显示与否,下翻页按钮
↓会多出来一个,重启会消失,是不是有缓存什么的。js 代码编辑后,最好重启或刷新下页面,不然内存会存在两份及多份代码,可能相互干扰影响。
-
JS 求助,在右上角添加「PgUp PgDn 」上下翻页按钮
2025-10-09 11:38不知是否你想要的,有问题再告知
// 右上角按钮实现上下翻新页 // see https://ld246.com/article/1759977992135 // vesion 0.0.3 // 0.0.3 新增alt+点击下方向键 向下滚动指定行,alt+shift+点击下方向键,向上滚动指定行;向下按钮和alt+点击向下按钮滚动时,会保留一定的重叠区域,方便浏览时衔接 // 0.0.2 修复滚动算法错误(之前的视窗计算有误差);增加ctrl+点击向下方向键,实现向上翻页功能 (async ()=>{ // 是否显示向上翻页按钮 true 显示 false 不显示 const isShowPageUpBtn = false; // alt+点击 滚动高度,这里用行高 * 3 表示,由于每个人的行高不一样,这里可自行修改 const altClickScrollHeight = 34 * 3; // 重叠高度,当上下滚动时,有一部分重叠区域不滚动(并非完全滚动整个视窗),方便上下文衔接,可根据自己需要修改 const overlap = 40; // 不支持手机版 if(isMobile()) return; // 添加toolbar按钮 whenElementExist('#toolbar .fn__ellipsis').then((el)=>{ if(!el) return; const pageDownBtnHtml = `<div data-menu="true" id="pageDownBtn" class="toolbar__item ariaLabel" aria-label="点击向下翻页" data-location="right"><svg style=""><use xlink:href="#iconArrowDown"></use></svg></div>`; el.insertAdjacentHTML('afterend', pageDownBtnHtml); const pageDownBtn = el.nextElementSibling; pageDownBtn.addEventListener('click', (event) => { const protyleEl = getProtyleEl(); const scrollEl = protyleEl?.querySelector('.protyle-content'); const isCtrlPressed = (event.ctrlKey || event.metaKey) && !event.shiftKey && !event.altKey; const isAltPressed = event.altKey && !event.shiftKey && !event.ctrlKey && !event.metaKey; const isAltShiftPressed = event.altKey && event.shiftKey && !event.ctrlKey && !event.metaKey; // ctrl+点击向下方向键按钮 if(isCtrlPressed) scrollPage(scrollEl, true); // alt+点击向下方向键按钮 else if(isAltPressed) scrollPage(scrollEl, false, altClickScrollHeight); // alt+shift+点击向下方向键按钮 else if(isAltShiftPressed) scrollPage(scrollEl, true, altClickScrollHeight); // 直接点击向下方向键按钮 else scrollPage(scrollEl, false); }); if(isShowPageUpBtn) { const pageUpBtnHtml = `<div data-menu="true" id="pageUpBtn" class="toolbar__item ariaLabel" aria-label="点击向上翻页" data-location="right"><svg style="transform: scaleY(-1);"><use xlink:href="#iconArrowDown"></use></svg></div>`; el.insertAdjacentHTML('afterend', pageUpBtnHtml); const pageUpBtn = el.nextElementSibling; pageUpBtn.addEventListener('click', (event) => { const protyleEl = getProtyleEl(); const scrollEl = protyleEl?.querySelector('.protyle-content'); scrollPage(scrollEl, true); }); } }); function scrollPage(element, isPageUp = true, amount = 0) { const scroller = element || window; const pageHeight = scroller === window ? window.innerHeight : scroller.clientHeight; const scrollOptions = { top: isPageUp ? (amount?-amount:(-pageHeight+overlap)) : (amount?amount:(pageHeight-overlap)), // behavior: 'smooth' // 按需开启 }; if (scroller === window) { window.scrollBy(scrollOptions); } else { scroller.scrollBy(scrollOptions); } } function getProtyleEl() { return document.querySelector('#editor') || document.querySelector(`.protyle[data-id="${[...document.querySelectorAll('.layout-tab-bar [data-type="tab-header"]')] .reduce((max, tab) => Number(tab?.dataset?.activetime) > Number(max?.dataset?.activetime || -1) ? tab : max, null)?.dataset?.id}"]`); } function whenElementExist(selector, node = document, timeout = 5000) { return new Promise((resolve, reject) => { const start = Date.now(); function check() { let el; try { el = typeof selector === 'function' ? selector() : node.querySelector(selector); } catch (err) { return resolve(null); } if (el) { resolve(el); } else if (Date.now() - start >= timeout) { resolve(null); } else { requestAnimationFrame(check); } } check(); }); } function isMobile() { return !!document.getElementById("sidebar"); } })(); -
台式机(WIN11)集市打不开
2025-10-09 10:04我也有时遇到过这个问题,感觉问题很复杂。
有时外出,不同的网络环境下,有的可以访问有些不可以。
即使同一个网络环境,也会出现有时不可以,有时又可以的情况。
如果有时需要安装某个插件,但不能访问时,可以采用手动安装方式,参考 https://www.siyuan-note.club/6991951m0
不过,奇怪的是,ob 插件市场,只要 github 能访问,就比较稳定,没有出现像思源这样的情况。因此,感觉思源的集市服务器还是有问题的,但不清楚可能是哪方面的问题。
-
求助自动编号自动换行该怎么解决
2025-10-08 13:09 -
请问有没有办法能在笔记里插入地图地址?最好能 ai 编辑城市路线
2025-10-08 11:37可以参考这两个,让 ai 帮你改改地图
请问能否实现在思源笔记做一个中国地图,然后点击各个省份可以跳转新建的页面 - wilsons 的回帖
通过属性制作 chart 足迹地图 - wilsons 的回帖
让 ai 改了下,支持世界地图

但,由于世界地图数据太大,因此未精确到省或州,不过可通过坐标简单自定义地点,如上图。
如果想更精确和详细,建议使用高德地图等 api 实现。
-
求问,笔记本关闭后,在发布服务中不能打开,以此控制笔记内容可访问与不可访问安全吗?
2025-10-05 23:50关闭后是安全的。
关闭了,任何人都无法访问了,自然是安全的。
不过,要注意,你可能哪天不小心打开,刚好别又此时访问,建议如果不想公开了就修改发布服务访问密码或直接关闭发布服务,这样是更好的做法。
-
分享如何白嫖上亿 token?我见过的 AI 平台最大的福利!
2025-10-05 19:18感谢大佬支持!
七牛还有额外奖励,这个还挺给力的,以前在其他平台,也推广了很多,但达不到这么多。
10 人还是很容易达到了,1 亿 +token 值得分享一波。

不过,有时间限制,从领取日期起,最多 2 年,领取时间截止到 2026.7.1,也即是最多到 2028.7.1
-
思源笔记移动端导出 PDF 的技术讨论
2025-10-04 11:30有道理。
不过,目前第三方现在还没有完善的插件,大部分都是部分支持。
关于审核,我觉得如果以前确实麻烦,不过现在,可以对发布的文章用 ai 扫一遍,基本没啥大问题,且发现严重违规的,给予永久封号惩罚,这样应该可以避免风险。
不过,如果是视频和图片审核可能较耗资源,所以,这个如果不收费确实不划算。
不过,以上仅仅个人想法,实际情况能否足够有效未知,得试过才知道,如果不想承担风险,还是不提供的好吧。
-
思源笔记移动端导出 PDF 的技术讨论
2025-10-04 10:57@88250 其实我到希望思源有类似 obsidian 那样的发布服务,可以把本地的文档发布到官方平台,方便分享,免得用户购买服务器,搭建发布服务等,当然也不是免费的。
-
思源笔记移动端导出 PDF 的技术讨论
2025-10-04 10:45并不是一刀切,只 web 实现,我意思本地是支持的,和现在一样,爱折腾的用户可以本地实现,懒得折腾的可以使用 web 服务,另外移动端本地也不好支持。
导出功能等之所以收费,是因为如果走 web 的会比较耗资源,现在很多在线转码,ocr 也是收费的,免费的有限。
-
思源笔记移动端导出 PDF 的技术讨论
2025-10-04 10:34官方可以搞个 web 服务,用户不想折腾,想多端支持的,就直接走 web 服务,不过嘛,收费或作为 VIP 功能,既满足了用户,还增加了收入,岂不是一举两得。
-
思源笔记移动端导出 PDF 的技术讨论
2025-10-04 09:35这个不错
题外话,我记得之前有个小伙伴有转码需求,这个 ffmpeg 转码用 wasm 实现的也不错 https://github.com/ffmpegwasm/ffmpeg.wasm








