wilsons
关注
142093 号成员,2024-05-12 13:24:23 加入
4.7k
个人主页 浏览
2.7k
帖子 + 回帖 + 评论
正式入驻知乎了,以后新贴主要在这里。 欢迎大家订阅关注! 你的关注对我是莫大鼓励,也能让我持续产出优质内容,我们一起成长 🙏 点这里立即关注:https://www.zhihu.com/people/wilsonses
  • 如何能隐藏页签和面包屑?将 QYL 主题的功能单独提取出来

    2025-08-13 23:50

    改好了,看看是否你要的效果。

  • 如何能隐藏页签和面包屑?将 QYL 主题的功能单独提取出来

    2025-08-13 20:40

    image.png

    1 我说的页签是黄色标记的地方,先确认下我们俩说的页签是否指同一个东西?

    2 其他代码与对页面元素对应关系如图

    3 如果还有问题,请检查下是否其他样式影响到了,先新空间测试看看以排除干扰项

  • [js] 粘贴为网络图片和本地图片(支持粘贴 gif 保持动画不失效,可拦截思源默认 gif 粘贴)

    2025-08-13 19:57

    1 看看控制台是否有报错

    2 断点调试下

    比如,在 fetchImageAsBinary 函数里断点,看看是否正确获取数据,还是因报错而降级为 png 了。

    3 网络问题,比如直接用 fetch 获取看看是否报错

    image.png

    4 我这里暂时无法重现,如果还不行,可以关注下此文,只有等哪位朋友再次遇到同样问题反馈后再说了(不同的角度去反馈很可能找到关键点,以前碰到过)。

  • [js] 粘贴为网络图片和本地图片(支持粘贴 gif 保持动画不失效,可拦截思源默认 gif 粘贴)

    2025-08-13 17:51

    这就不造了,我这边无法重现

    这个参数,设置为 true 了吗

    // 是否监听思源默认的粘贴 true监听 false 不监听
    const isListenSiyuanPaste = true;
    
  • [js] 粘贴为网络图片和本地图片(支持粘贴 gif 保持动画不失效,可拦截思源默认 gif 粘贴)

    2025-08-13 16:04

    这就不知道了,我这边是好的。

    r172.gif

    可能是图片的问题,可否把图片发来看看?

    比如,防盗链,识别不了等,这时候会降级到思源默认粘贴。

  • [js] 粘贴为网络图片和本地图片(支持粘贴 gif 保持动画不失效,可拦截思源默认 gif 粘贴)

    2025-08-13 15:13

    你的代码是 version 0.0.6 版吗?

    先更新到最新版,新空间测试看看。

  • 如何能隐藏页签和面包屑?将 QYL 主题的功能单独提取出来

    2025-08-13 13:38
    /* 隐藏面包屑和右侧工具栏 */
    /*.protyle .protyle-breadcrumb{
        display: none;
    }*/
    /* 仅隐藏面包屑 */
    .protyle .protyle-breadcrumb__bar {
        display: none;
    }
    /* 隐藏页签 */
    [data-type="wnd"] > div.fn__flex:has(.layout-tab-bar) {
        display:none;
    }
    /* 隐藏头图 */
    /*.protyle .protyle-background{
        display: none;
    }*/
    
  • 思源笔记有内容修改的日志功能吗?

    2025-08-13 10:35

    可以用书签 + 插件实现,以下代码仅供参考

    显示今日更新或创建

    SELECT *
    FROM blocks
    WHERE type IN ('b', 'h', 'p', 't', 'm')
      AND (
        -- 判断 updated 在今天范围内(本地时间 00:00:00 到 23:59:59)
        (updated >= strftime('%Y%m%d%H%M%S', 'now', 'localtime', 'start of day')
         AND updated < strftime('%Y%m%d%H%M%S', 'now', 'localtime', 'start of day', '+1 day'))
        OR
        -- 判断 created 在今天范围内
        (created >= strftime('%Y%m%d%H%M%S', 'now', 'localtime', 'start of day')
         AND created < strftime('%Y%m%d%H%M%S', 'now', 'localtime', 'start of day', '+1 day'))
      )
      AND TRIM(content) != ''
    ORDER BY updated desc
    LIMIT 500;
    

    显示本次更新或创建

    async function main() {
      // 初始化 startTime(仅在首次运行时设置)
      if (!localStorage.getItem('__startTime')) {
       localStorage.setItem('__startTime', new Date().toLocaleString('zh-CN', {
          year: 'numeric',
          month: '2-digit',
          day: '2-digit',
          hour: '2-digit',
          minute: '2-digit',
          second: '2-digit',
          hour12: false
        }).replace(/[/\s:]+/g, ''));
      }
    
      // 查询最近更新或创建的 blocks
      const startTime = localStorage.getItem('__startTime');
      const blocks = await kit.sql(`
        SELECT * FROM blocks
        WHERE type IN ('b', 'h', 'p', 't', 'm')
          AND (
            (updated >= '${startTime}'
              AND updated < strftime('%Y%m%d%H%M%S', date('now', 'localtime'), 'start of day', '+1 day'))
            OR
            (created >= '${startTime}'
              AND created < strftime('%Y%m%d%H%M%S', date('now', 'localtime'), 'start of day', '+1 day'))
          )
        AND trim(content) != ''
        ORDER BY updated desc
        LIMIT 500;
      `);
    
      return blocks;
    }
    
    return main();
    

    如果包括新建的空文档,可以把 WHERE type IN ('b', 'h', 'p', 't', 'm') 中加上'd'

  • [js] 折叠代码块

    2025-08-13 10:11

    本来就是一起滚动

    r171.gif

  • HTML 制作的文本框是不能在思源填写吗?一填一个数字就跳不能填了

    2025-08-13 03:05

    第一步 设置允许 HTML 脚本

    image.png

    第二步 添加事件

    每个 input 加上属性 oninput="event.stopPropagation()"

    第三步 实时保存输入结果

    可参考 HTML 块脚本可以调用 JS 片段中的函数吗 - wilsons 的回帖


    完整示例如下:

    r170.gif

    html 代码

    <div>
    <!-- 尺寸部分 -->
    <div class="title">尺寸:</div>
    <div class="form-row">
        <div class="input-group">
            <span class="form-label">胸围:</span>
            <input type="text" class="form-input" placeholder="" oninput="inputHandle(event, this)" value="">
            <span class="unit">(cm)</span>
        </div>
        <div class="input-group">
            <span class="form-label">衣长:</span>
            <input type="text" class="form-input" placeholder="" oninput="inputHandle(event, this)" value="">
            <span class="unit">(cm)</span>
        </div>
    </div>
    <div class="form-row">
        <div class="input-group">
            <span class="form-label">腰围:</span>
            <input type="text" class="form-input" placeholder="" oninput="inputHandle(event, this)" value="">
            <span class="unit">(cm)</span>
        </div>
        <div class="input-group">
            <span class="form-label">放量:</span>
            <input type="text" class="form-input temp-inputting" placeholder="" oninput="inputHandle(event, this)" value="">
            <span class="unit">(cm)</span>
        </div>
    </div>
    </div>
    

    js 代码(放到 js 代码片段中)

    // HTML块,input实时输入并保存
    async function inputHandle(event, input, isComposing = true) {
        // 阻止冒泡
        event.stopPropagation();
        // 输入法事件
        if(!input.compositionend) {
            input.compositionend = true;
            input.addEventListener("compositionend", () => {
                inputHandle(event, input, false);
            });
        }
        if (event.isComposing && isComposing) return;
        // 保存光标位置
        const selectionStart = input.selectionStart;
        const selectionEnd = input.selectionEnd;
        // 修改input的value
        input.setAttribute('value', input.value);
        // 保存修改后的HTML代码块(核心代码)
        const host = input.getRootNode().host;
        const htmlBlock = host.closest('[data-node-id][data-type]');
        const blockId = htmlBlock.dataset.nodeId;
        const protyle = htmlBlock.closest('.protyle');
        const div = host.shadowRoot.querySelector('div');
        div.querySelectorAll('.temp-inputting').forEach(item=>item.classList.remove('temp-inputting'));
        input.classList.add('temp-inputting');
        host.setAttribute('data-content', Lute.EscapeHTMLStr(div.outerHTML));
      
        // 更新块
        await updateBlock(host);
    
        // 再次聚焦
        const newInput = protyle?.querySelector(`.protyle-wysiwyg [data-node-id="${blockId}"] protyle-html`)?.shadowRoot?.querySelector('input.temp-inputting');
        if(newInput) {
            newInput.focus();
            newInput.setSelectionRange(selectionStart, selectionEnd); // 恢复光标位置
            newInput.classList.remove('temp-inputting');
        }
    }
    
    // 此函数同之前的updateBlock完全一样
    async function updateBlock(node) {
        if(!node.matches('[data-node-id][data-type]')) {
            node = node.closest('[data-node-id][data-type]');
        }
        await requestApi('/api/block/updateBlock', {
            "dataType": "dom",
            "data": node.outerHTML,
            "id": node.dataset.nodeId
        });
        async function requestApi(url, data, method = 'POST') {
            return await (await fetch(url, {method: method, body: JSON.stringify(data||{})})).json();
        }
    }
    
  • [js] 一键查看引用块:点击反链即可跳转

    2025-08-12 15:44

    @HugZephyr 这里判断下 data.length 是否等于 1,等于 1 的时候直接 openBlock(data[0].id)即可

    IMG20250812153524.jpg

    空了改,纯手机打代码太累了 😳

    这个代码比原悬浮窗好的地方是支持手机,思源自带悬浮窗不支持手机

  • [js] 顶栏融合 - 参考 qyl 主题的顶栏融合

    2025-08-12 07:44

    建议顶部栏和 tab 不要用固定高度,用户可自定义,用户可能不是用思源默认的高度,比如我。

    我自定义高度后(减小默认高度)tab 就有一部分隐藏到顶部了。

    image.png

  • 链滴无法签到,标签停留页面过一会就要真人验证

    2025-08-12 00:37

    r1691gif.gif

    liuyun.io 验证也有问题,一直验证不通过。

  • [js] 一键查看引用块:点击反链即可跳转

    2025-08-12 00:32

    反馈一个问题: ALt 几乎得同时和单击一起按才正常显示候选窗, 如果持续按住 Alt 不松开单击鼠标 , 候选窗会打开然后瞬间关闭

    我这边不存在先按住 alt,再单击引用数,菜单会关闭的情况。

    如果持续按住 alt 点引用数没问题

    r1692gif.gif

    如果持续按住 alt 点菜单项,会关闭菜单,这和是否按住 alt 无关,点击菜单项后就会关闭菜

  • 链滴无法签到

    2025-08-11 18:51

    我的浏览器也一样,不知为何。

    可以用无痕模式或手机浏览器试试。

    参考帖子 链滴无法签到,标签停留页面过一会就要真人验证

  • [js] 好玩:模仿 obsidian 自滚动菜单,丝滑!

    2025-08-11 18:16

    仅支持思源自带的菜单,插件自己实现的菜单不好支持。

  • 准备用思源写日记,能否对日记文件夹设置密码?

    2025-08-11 14:05

    思源为什么不实现加密?

    参考 是否提供文档级“加密”以保护隐私?(含投票) - 88250 的回帖

    也可自行在链滴或思源 github 搜索

  • [js] 文档树文档置顶和设置颜色 [0.0.8 完美版]

    2025-08-11 12:06

    没有,这种情况应该是你存储的代码片段和思源页面的编码不一致导致的。

    如果你把代码片段存储到单纯的文件中,检查下文件的编码是否 utf-8

  • 请问如何修改样式才能在导出 PDF 时保持修改后所见的样式

    2025-08-07 16:44

    不是,就思源自带的颜色,你自定义配置放到哪了,如果插件里可能不行。如果放到 css 代码片段应该没问题。

    我用你给的代码放 css 片段没问题,我测试的代码都随便写的,没有参考价值,比如 body 改颜色等。

  • 请问如何修改样式才能在导出 PDF 时保持修改后所见的样式

    2025-08-07 16:22

    我通过工具栏和 css 代码片段添加的都能正常导出。

  • 思源布局功能是否可以定期自动保存?

    2025-08-07 16:10

    好吧,可以把源码和帮助文档,思源源码给 ai,然后让 ai 来实现试试。

    报错或许是因为不熟悉 js 思源 openAny 的运行规律吧,等熟悉了就能掌控报错或不报错了。

    下面是针对已有布局自动保存的,你试试,默认 5 分钟更新一次,可自行修改保存时间。

    setInterval(async ()=>{
        const layoutName=''; // 👈 这里填写布局名称,必填
        const saveTime = 5; // 多久保存一次,单位:分钟,默认5分钟
        await openAny.click('#barWorkspace');
        const selector = '#commonMenu [data-id="layout"] .b3-menu__item--custom';
        await openAny.el(selector);
        const layouts = document.querySelectorAll(selector);
        const edit = [...layouts].find(item=>item.firstChild.firstChild.textContent.trim()===layoutName.trim());
        if(!edit) {window.siyuan.menus.menu.remove();return}
        await openAny.click('svg', edit);
        const style = document.createElement('style');
        style.textContent = `[data-key="dialog-saveworkspace"]{display:none}`;
        document.head.appendChild(style);
        await openAny.click('[data-key="dialog-saveworkspace"] .b3-dialog__action > :last-child');
        setTimeout(()=>style.remove(), 500);
    }, saveTime * 60000);
    
  • 思源布局功能是否可以定期自动保存?

    2025-08-07 09:22

    [js] 连续点击 openAny,小代码,大作用,让一切触手可达 一行代码即可

    setInterval(()=>openAny.clicks('#barWorkspace', '#commonMenu [data-id="save"]'), 300000); // 每5分钟保存一次
    

    如果是更新布局,稍微麻烦一步,先打开编辑旧布局对话框,然后模拟点击更新布局即可,请自行研究。

  • [js] 好玩:模仿 obsidian 自滚动菜单,丝滑!

    2025-08-05 21:24

    试试还能 🆙 否?

  • [js] 粘贴为网络图片和本地图片(支持粘贴 gif 保持动画不失效,可拦截思源默认 gif 粘贴)

    2025-08-05 21:10

    感谢反馈,为了不影响思源原有功能,不会直接改为默认,后续看看怎样通过参数开启默认和关闭。

  • [js] 思源屏保,酷炫防偷窥

    2025-08-05 10:48

    哈哈 zxkmn 原贴是手机防烧屏所以都支持了。

    如果不想支持手机,可以在代码开头,即 (sync ()=>{ 下面添加下面的代码即可

    if(!!document.getElementById("sidebar")) return;

  • [js] 思源屏保,酷炫防偷窥

    2025-08-04 23:00

    👍 感谢大佬的科普,学习到了。

    我也不是很懂,刚才请教了下 ai,ai 说移动像素是最好的办法。

    传统屏保做到以下也是有效的

    如果满足以下条件,是有效的

    条件 说明
    ✅ 位置完全随机且均匀分布 覆盖全屏所有区域,不能集中在中部
    ✅ 内容简单、低亮度 使用灰阶、低对比度图案,避免高亮白块
    ✅ 图案不包含固定元素 比如不要每次都是同一个“雪花”图标
    ✅ 显示时间合理 5 秒不算长,但配合频繁切换也可接受
    ✅ 不干扰用户 用户回来时能立即消失

    👉 这种机制本质上就是一种伪随机像素负载均衡系统,类似于“动态壁纸 + 位移”。

    📌 结论
    如果你的“屏保”是一个全屏、低亮度、随机分布、频繁切换、无固定图案的系统,
    那么它可以作为一种辅助防烧手段,甚至接近专业级的“像素抖动”技术。

    所以,如果想纯粹防烧屏,还是老老实实用大佬的 思源笔记防烧屏插件震 (hu) 撼(nao)发布 插件吧

    如果你主要为了酷炫或防偷窥,可以用这个代码,防烧上也基本符合了 ai 所说的功能,能起到一定的防烧屏作用。


    给 ai 看了代码,给出的结论如下:

    和专业防烧插件的区别

    对比项 你的代码 ZXKMM 大佬的插件
    目标 屏保 + 防偷窥 + 酷炫 专为防烧屏设计
    触发时机 空闲 10 分钟后启动 持续运行,实时微移
    移动对象 屏保文字(局部) 整个思源界面元素(全局)
    移动频率 每 7 秒一次(可调) 定期轻微位移(无感)
    是否需要激活 是(空闲后才开始) 否(一直生效)
    防烧效率 辅助级(有一定作用) 专业级(核心防护)

    📌 所以说:

    你的代码不能替代专业防烧插件,但可以作为“补充手段”或“个性化方案中的意外之喜”

    另外,ai 还给出了一定的优化措施,为了美观,就先不改了。

  • 你应当有个免费的 webdav(一场由浏览器升级引发的“数据灾难”)

    2025-08-04 22:20

    👍 有道理!

    自动备份的好处是当你来不及备份时,它在默默地帮你做好了一切

    比如,这个案例中,浏览器突然升级旧版插件无法开启。要么删除,要么更新,但无论哪种操作,数据都会丢失。

    这是 chrome 插件的机制问题,当然也是插件本身的问题。

    所以说,二者是相辅相成的。

    但,我目前的方案是自动备份 + 小备份

    什么意思?

    自动备份就是上面说的啦。

    小备份,是针对小功能,及时备份。比如,这个案例中,我每完成一个脚本的编写,对这个脚本做单独备份,比如有个脚本库,或者干脆外链本地文件。

    这种小备份针对任何操作或事件。

    比如,我以前在公司,每次离职时,要检查电脑,备份自己的文件,通常需要花很久时间。

    现在养成习惯,用到的东西,当时就备份到云盘了。

    自己用的东西都在一个总目录里,当然这么目录的重要文件也是按小备份备份过的。

    这样离职时拷贝这一个文件,然后系统重置就好了。

    最后的拷贝只不过是兜底罢了。

    小备份还有个好处,就是大备份(这种短时间内大量拷贝),可能会有数据丢失等情况发生。

    我曾经遇到过,目录、文件都在,以为备份完成,系统也显示完成,回去一看,很多空文件或损坏的文件。