闪卡 | 同级列表项一键制卡 / 移除制卡

要不是群聊被问到,我是真没想到竟然还有其他人会也有这样的需求。

前提条件:
使用方法效果展示:

将光标放到对应同级的列表项块中,然后使用复制 id-快捷键去复制(段落)块 id。

注意:不能通过块菜单复制。这里的制卡适配的是最底层的段落块 id,递增到同级列表项块制卡。而思源的列表块是列表块、列表项块、段落块嵌套。段落块块标被隐藏,无法通过鼠标选中对应的块菜单。

代码(放入嵌入块中)
//!js
const query = async () => {
    let dv = Query.DataView(protyle, item, top);
    const docId = dv.useState('docId', '');
    const searchResult = dv.useState('search-result', []);
  
    dv.addmd(`**同级列表项快速制卡操作**`);
  
    // 文档ID输入框(3行高度)
    const idInput = document.createElement('textarea');
    idInput.className = "fn__block b3-text-field";
    idInput.placeholder = "输入块ID (如:20250424104910-q34fpnf)";
    idInput.rows = 3;  // 改为3行高度
    idInput.style.fontSize = '22px';
    idInput.style.marginBottom = '8px';
    idInput.value = docId.value;
    dv.addele(idInput);

    // 按钮容器(网格布局)
    const btnGrid = document.createElement('div');
    btnGrid.style.display = 'grid';
    btnGrid.style.gridTemplateColumns = 'repeat(2, 1fr)';
    btnGrid.style.gap = '8px';
    btnGrid.style.marginBottom = '8px';
  
    // 创建按钮(只保留添加、移除和刷新)
    const addButton = createButton("添加闪卡");
    const removeButton = createButton("移除闪卡");
    const refreshButton = createButton("刷新结果");
  
    // 添加到网格
    btnGrid.appendChild(addButton);
    btnGrid.appendChild(removeButton);
    btnGrid.appendChild(refreshButton);
  
    dv.addele(btnGrid);
  
    // 结果容器
    const resultContainer = document.createElement('div');
    dv.addele(resultContainer);
  
    // 初始渲染结果
    updateResults();

    // 按钮事件处理
    const handleButtonClick = async (action) => {
        const blocks = await executeQuery();
        if (!blocks) return;
  
        switch(action) {
            case 'add':
                await tomato_zZmqus5PtYRi.siyuan.addRiffCards(blocks.map(b => b.id));
                break;
            case 'remove':
                await tomato_zZmqus5PtYRi.siyuan.removeRiffCards(blocks.map(b => b.id));
                break;
            // 移除批量推迟、分散推迟和调整优先级的case分支
        }
  
        updateResults();
        dv.repaint();
    }
  
    refreshButton.onclick = async () => {
        await executeQuery();
        updateResults();
        dv.repaint();
    }
  
    // 按钮绑定
    addButton.onclick = () => handleButtonClick('add');
    removeButton.onclick = () => handleButtonClick('remove');
  
    // 辅助函数:创建按钮
    function createButton(text) {
        const btn = document.createElement('button');
        btn.className = "b3-button";
        btn.textContent = text;
        btn.style.width = '100%';
        btn.style.padding = '8px 0';
        return btn;
    }
  
    // 辅助函数:执行查询
    async function executeQuery() {
        const id = idInput.value.trim();
        if (!id) {
            searchResult([]);
            return null;
        }
  
        const finalSql = `SELECT * FROM blocks 
WHERE parent_id = (
    SELECT parent_id FROM blocks 
    WHERE id = (
        SELECT parent_id FROM blocks 
        WHERE id = '${id}'
    )
) AND type = 'i'`;
  
        try {
            const blocks = await tomato_zZmqus5PtYRi.siyuan.sql(finalSql);
            docId.value = id;
            searchResult(blocks);
            return blocks;
        } catch (error) {
            console.error("SQL执行失败:", error);
            return null;
        }
    }
  
    // 辅助函数:获取卡片(保留,但不再用于移除的功能)
    async function getCards(blocks) {
        const cardMap = await tomato_zZmqus5PtYRi.siyuan.getRiffCardsByBlockIDs(blocks.map(b => b.id));
        return [...cardMap.values()].flat();
    }
  
    // 辅助函数:更新结果视图
    function updateResults() {
        resultContainer.innerHTML = '';
        if (searchResult().length > 0) {
            dv.addlist(searchResult(), {
                fullwidth: true,
                cols: null
            }, resultContainer);
        } else {
            const emptyMsg = document.createElement('div');
            emptyMsg.className = "b3-label";
            emptyMsg.textContent = "无查询结果";
            emptyMsg.style.textAlign = 'center';
            emptyMsg.style.padding = '20px';
            emptyMsg.style.opacity = '0.6';
            resultContainer.appendChild(emptyMsg);
        }
    }
  
    dv.render();
}

return query();
致谢

@Frostime 佬提供 querw&view 插件、思源 sql 的入门教程及 sql 小助手提示词。

@player 番茄佬书写并提供制卡/取消制卡的代码。

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...