年(不)久失修,让 AI 改了下,能跑了。原帖见:[js] 闪卡 JS 分享(方便在数据库上制作闪卡) - 链滴
(() => {
// 块菜单配置
const menus = [
{
name: "快速制卡",
operation: "add",
},
{
name: "取消制卡",
operation: "remove",
}
];
// 监听块右键菜单
whenElementExist('#commonMenu .b3-menu__items').then((menuItems) => {
const menusReverse = menus.reverse();
observeBlockMenu(menuItems, async (isTargetMenu) => {
if (menuItems.querySelector('.operate-my-card')) return;
const addAv = menuItems.querySelector('button[data-id="addToDatabase"]');
if (!addAv) return;
if (menus.length === 0) return;
// 生成块菜单
menusReverse.forEach((menu, index) => {
const menuText = menu.name;
const menuIcon = '#iconRiffCard';
const menuClass = `operate-my-card-${menu.operation}-${menus.length - index - 1}`;
const menuButtonHtml = `<button class="b3-menu__item ${menuClass}"><svg class="b3-menu__icon " style=""><use xlink:href="${menuIcon}"></use></svg><span class="b3-menu__label">${menuText}</span></button>`;
addAv.insertAdjacentHTML('afterend', menuButtonHtml);
const menuBtn = menuItems.querySelector('.' + menuClass);
// 块菜单点击事件
menuBtn.onclick = async () => {
window.siyuan.menus.menu.remove();
await menuItemClick(menu.operation);
};
});
});
});
// 菜单点击事件
async function menuItemClick(operation) {
let blocks = [];
const selectedRows = document.querySelectorAll('.av__row.av__row--select');
console.log('选中的行数:', selectedRows.length); // 调试日志
// 遍历每个选中的行
selectedRows.forEach((row, index) => {
// 修复:使用正确的选择器
const blockRefNodes = row.querySelectorAll('[data-type="block-ref"]');
console.log(`第${index}行块引用数量:`, blockRefNodes.length); // 调试日志
// 遍历这些元素,提取 data-id
blockRefNodes.forEach(node => {
const dataId = node.dataset.id;
console.log('找到块引用:', dataId); // 调试日志
if (dataId) {
blocks.push(dataId);
}
});
});
console.log('最终收集的块ID:', blocks); // 调试日志
if (blocks.length === 0) {
showMessage('未找到任何块引用,请确保选中了包含块引用的行');
return;
}
if (operation === 'remove') {
await removeFlashcard(blocks);
} else {
await addFlashcard(blocks);
}
}
// 快速制卡
async function addFlashcard(blockIds) {
console.log('开始添加闪卡:', blockIds); // 调试日志
blockIds = typeof blockIds === 'string' ? [blockIds] : blockIds;
try {
const result = await requestApi("/api/riff/addRiffCards", {
"blockIDs": blockIds,
"deckID": "20230218211946-2kw8jgx"
});
console.log('添加闪卡结果:', result); // 调试日志
if (result && result.code === 0) {
showMessage(`成功添加 ${blockIds.length} 个闪卡`);
} else {
showMessage('添加闪卡失败: ' + (result?.msg || '未知错误'));
console.error('添加闪卡失败:', result);
}
} catch (error) {
showMessage('添加闪卡请求失败: ' + error.message);
console.error('添加闪卡请求失败:', error);
}
}
async function removeFlashcard(blockIds) {
console.log('开始移除闪卡:', blockIds); // 调试日志
blockIds = typeof blockIds === 'string' ? [blockIds] : blockIds;
try {
const result = await requestApi("/api/riff/removeRiffCards", {
"blockIDs": blockIds,
"deckID": "20230218211946-2kw8jgx"
});
console.log('移除闪卡结果:', result); // 调试日志
if (result && result.code === 0) {
showMessage(`成功移除 ${blockIds.length} 个闪卡`);
} else {
showMessage('移除闪卡失败: ' + (result?.msg || '未知错误'));
console.error('移除闪卡失败:', result);
}
} catch (error) {
showMessage('移除闪卡请求失败: ' + error.message);
console.error('移除闪卡请求失败:', error);
}
}
async function requestApi(url, data, method = 'POST') {
const response = await fetch(url, {
method: method,
body: JSON.stringify(data || {})
});
return await response.json();
}
// 显示消息
function showMessage(message) {
window.siyuan.showMessage(message, 3000);
}
/**
* 监控 body 直接子元素中 #commonMenu 的添加
*/
function observeBlockMenu(selector, callback) {
let isTargetMenu = false;
const observer = new MutationObserver((mutationsList) => {
for (const mutation of mutationsList) {
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
mutation.addedNodes.forEach((node) => {
if (isTargetMenu) return;
if (node.nodeType === 1 && node.closest('[data-id="fields"]')) {
isTargetMenu = true;
}
if (isTargetMenu) {
callback(isTargetMenu);
setTimeout(() => {
isTargetMenu = false;
}, 200);
}
});
}
}
});
observer.observe(selector || document.body, {
childList: true,
subtree: false,
});
return observer;
}
// 等待元素出现
function whenElementExist(selector, node) {
return new Promise(resolve => {
const check = () => {
const el = typeof selector === 'function' ? selector() : (node || document).querySelector(selector);
if (el) resolve(el); else requestAnimationFrame(check);
};
check();
});
}
})();
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于