我在侧边栏的“类别”部分使用了表情符号,但我也有一个公开的自定义部分。我想在那个部分使用相同的彩色图标,这样它就不会像“类别”部分那样“平淡无奇”。
这可能吗?
在 ChatGPT 和 Claude 的帮助下,我得以实现了一个高度可定制化的功能:
如果您想实现此功能,请创建一个新组件,并将以下内容添加到 CSS 选项卡:
.sidebar-section-link-prefix .emoji.prefix-emoji {
width: 1rem !important;
height: 1rem !important;
}
在我的特定情况下,
1rem工作得很好。请根据您的论坛/社区进行调整。
然后,在 JS 选项卡中添加以下代码:
import { apiInitializer } from "discourse/lib/api";
import { emojiUrlFor } from "discourse/lib/text";
export default apiInitializer("0.11.1", (api) => {
// 将部分名称映射到 ID
const sectionIds = {
"community": 1,
"tiago": 2,
"personal-section": 3,
// 在此处添加更多部分
};
// [sectionId, itemName] 到 emoji 名称的映射
const iconReplacements = {
// 社区部分 (ID: 1)
"1,admin": "wrench",
"1,review": "triangular_flag_on_post",
"1,everything": "books",
"1,my-posts": "writing_hand",
"1,my-messages": "envelope_with_arrow",
// Tiago 部分 (ID: 2)
"2,Journal": "notebook_with_decorative_cover",
"2,Music": "musical_note",
"2,About": "bust_in_silhouette",
// 个人部分 (ID: 3)
"3,Backups": "floppy_disk",
"3,Scheduled": "clock3",
"3,Staff": "lock",
"3,Components": "electric_plug",
};
function replaceIcons() {
Object.entries(sectionIds).forEach(([sectionName, sectionId]) => {
Object.entries(iconReplacements).forEach(([key, emojiName]) => {
const [keyId, itemName] = key.split(',');
// 仅处理当前部分的替换项
if (parseInt(keyId) === sectionId) {
const url = emojiUrlFor(emojiName);
// 尝试多个选择器以捕获汉堡菜单和固定侧边栏
const selectors = [
// 固定侧边栏选择器
`div[data-section-name="${sectionName}"] li[data-list-item-name="${itemName}"] .sidebar-section-link-prefix.icon`,
// 汉堡菜单选择器 (更具体)
`.menu-panel div[data-section-name="${sectionName}"] li[data-list-item-name="${itemName}"] .sidebar-section-link-prefix.icon`,
// 通用回退
`[data-section-name="${sectionName}"] [data-list-item-name="${itemName}"] .sidebar-section-link-prefix.icon`
];
for (const selector of selectors) {
const prefix = document.querySelector(selector);
if (prefix && url) {
// 检查是否已替换,以避免不必要的 DOM 操作
if (!prefix.querySelector('.prefix-emoji')) {
prefix.innerHTML = `
<img src="${url}"
title="${emojiName}"
alt="${emojiName}"
class="emoji prefix-emoji">
`;
}
break; // 找到并替换图标后退出循环
}
}
}
});
});
}
// 页面更改时运行
api.onPageChange(replaceIcons);
// 也延迟运行以捕获动态加载的内容
api.onPageChange(() => {
setTimeout(replaceIcons, 100);
setTimeout(replaceIcons, 500);
});
// 增强的 MutationObserver 以捕获侧边栏更改
const observer = new MutationObserver((mutations) => {
let shouldReplace = false;
mutations.forEach((mutation) => {
// 监视添加的节点 (原始功能)
mutation.addedNodes.forEach((node) => {
if (node.nodeType === Node.ELEMENT_NODE) {
if (node.classList?.contains('menu-panel') ||
node.querySelector?.('.sidebar-sections') ||
node.classList?.contains('sidebar-sections') ||
node.querySelector?.('[data-section-name]')) {
shouldReplace = true;
}
}
});
// 监视侧边栏部分上的属性更改 (折叠/展开)
if (mutation.type === 'attributes' && mutation.target.nodeType === Node.ELEMENT_NODE) {
const target = mutation.target;
if (target.matches('[data-section-name]') ||
target.closest('[data-section-name]') ||
target.matches('.sidebar-section') ||
target.closest('.sidebar-section')) {
shouldReplace = true;
}
}
// 监视侧边栏部分中的 childList 更改
if (mutation.type === 'childList' && mutation.target.nodeType === Node.ELEMENT_NODE) {
const target = mutation.target;
if (target.matches('[data-section-name]') ||
target.closest('[data-section-name]') ||
target.querySelector('[data-section-name]')) {
shouldReplace = true;
}
}
});
if (shouldReplace) {
setTimeout(replaceIcons, 50);
}
});
// 使用增强的选项开始观察
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true, // 监视属性更改
attributeFilter: ['class', 'style', 'aria-expanded'], // 折叠/展开时常见的更改属性
});
// 额外的事件监听器,用于常见的侧边栏交互
document.addEventListener('click', (event) => {
// 检查点击是否发生在侧边栏部分标题或切换按钮上
if (event.target.closest('.sidebar-section-header') ||
event.target.closest('[data-section-name]') ||
event.target.matches('.sidebar-section-toggle')) {
setTimeout(replaceIcons, 100);
}
});
});
我将其设计为可以通过名称轻松添加新的自定义部分,为其分配一个 id,然后创建每个部分的映射。
这样做的原因是,我可能有 2 个标题为“Journal”的部分,但我可能希望为每个部分使用不同的表情符号。
我敢肯定会有人说有现成的组件或插件可以做到这一点
但与 ChatGPT 和 Claude 来回调试直到一切如我所愿仍然很有趣。
希望这对其他用户有所帮助。
如果您发现任何可以调整/改进的地方,请分享
我刚更新了 JS 代码,因为我注意到它在移动设备上仍然显示默认图标。所有功能在移动设备和桌面设备上都按预期工作。
又一个编辑:当我折叠和展开该部分时,表情符号会消失,并被替换为原始图标。现在可以正常工作了,我再次更新了 JS 代码。
很高兴你找到了实现这一功能的方法——我认为这对于核心功能来说是一个非常自然的选择,因为我们现在已经支持分类的 emoji 了。
我同意。希望这最终能成为一个原生功能。在此之前,这个自定义组件正在发挥它的作用 ![]()
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.