关于JavaScript返回指定HTML内容的Discourse Widget技术咨询
Discourse自定义Admin菜单Widget实现指定HTML输出方案
我帮你完善并修改这段代码,让它能正确返回你需要的HTML内容,同时补全缺失的触发按钮逻辑:
const currentUsername = Discourse.User.currentProp('username'); // 仅对指定用户创建Admin菜单Widget if (currentUsername === "crazy-geek") { api.createWidget('admin-menu', { tagName: 'div.admin-panel', // 这里返回你需要的指定HTML内容,用this.h()构建安全的DOM元素 panelContents() { // 示例HTML内容:包含问候语、后台链接和操作列表 return this.h('div.admin-menu-content', [ this.h('p', `Hello *${currentUsername}*`), this.h('a.admin-link', { href: '/admin' }, 'Go to Admin Dashboard'), this.h('ul.admin-actions', [ this.h('li', this.h('a', { href: '/admin/users' }, 'Manage Users')), this.h('li', this.h('a', { href: '/admin/settings' }, 'Site Settings')) ]) ]); }, html() { return this.attach('menu-panel', { contents: () => this.panelContents(), // 可选:给菜单面板添加自定义样式类 class: 'custom-admin-menu-panel' }); }, clickOutside() { this.sendWidgetAction('toggleAdmin'); } }); // 在头部图标区域后添加触发菜单的按钮 api.decorateWidget('header-icons:after', helper => { return helper.attach('button', { className: 'icon-btn admin-menu-trigger', icon: 'wrench', action: 'toggleAdmin', title: 'Open Admin Menu' }); }); // 新增Widget动作,控制菜单的显示/隐藏 api.attachWidgetAction('header', 'toggleAdmin', function() { const adminMenu = this.widgets.find(w => w.name === 'admin-menu'); if (adminMenu) { adminMenu.toggle(); } else { this.attach('admin-menu', { target: this }); } }); }
关键修改说明
- 返回指定HTML内容:
推荐用Discourse Widget内置的this.h()方法构建DOM元素,这是官方认可的安全方式,能避免XSS风险。如果你需要直接插入原始HTML字符串,可以改用this.raw()方法,示例如下:
注意:使用panelContents() { return this.raw('<div class="admin-menu-content"><p>Hello <strong>crazy-geek</strong></p><a href="/admin">Go to Admin Dashboard</a></div>'); }raw()时要确保内容完全可信,避免注入恶意代码。 - 补全触发逻辑:完善了
header-icons:after装饰器,添加了 wrench 图标按钮,点击后触发菜单的显示/隐藏操作。 - 外部点击关闭:保留了
clickOutside()方法,点击菜单外部区域会自动关闭菜单。
可选样式优化
如果需要美化菜单样式,可以添加自定义CSS:
.admin-panel { position: absolute; top: 50px; right: 10px; background: white; border: 1px solid #ddd; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); padding: 15px; min-width: 200px; } .admin-menu-content p { margin: 0 0 10px 0; font-weight: bold; } .admin-link { display: block; margin-bottom: 10px; color: #39739d; } .admin-actions { list-style: none; padding: 0; margin: 0; } .admin-actions li { margin-bottom: 5px; }
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

