将一份Discourse主题列表嵌入到外部网站上

:bookmark: 本指南将介绍如何使用 JavaScript 在外部网站上嵌入和显示 Discourse 主题列表,从而在博客、网站或外部内容平台上展示论坛内容,例如讨论或公告。

:person_raising_hand: 所需用户级别:管理员

摘要

在外部网站上嵌入 Discourse 主题,可以让你直接在其他网站上显示 Discourse 论坛的主题列表。这种集成有助于为你的论坛带来流量,并让你的受众与你的社区内容保持互动。嵌入的主题将显示为 JavaScript 小部件,可与你网站的 DOM 结构集成,从而更易于通过 CSS 进行自定义。

启用主题嵌入

要在外部网站上设置主题嵌入:

  1. 导航到你的 Discourse 管理仪表板,然后点击 site_settings。搜索并启用 embed_topics_list 站点设置。

  2. 将嵌入脚本添加到外部网站的 HTML <head> 部分:

    <script src="https://discourse.example.com/javascripts/embed-topics.js"></script>
    

    discourse.example.com 替换为你实际的 Discourse 论坛 URL。

  3. 将主题列表元素放置在你想要显示主题的位置(例如,在博客文章或单个网站页面中):

    <d-topics-list discourse-url="https://discourse.example.com" category="1234" per-page="5"></d-topics-list>
    
  4. 如果你要在与 Discourse 站点不同的域上嵌入主题,请将外部网站的域添加到 Admin > Advanced > Embedding > Hosts

    例如,如果你的 Discourse 站点位于 yourdiscourseforum.com,而你想在 yourexternalsite.com 上嵌入主题,则需要将 yourexternalsite.com 添加到你的允许主机列表中。

:warning: 你无法嵌入来自私有、需要登录的 Discourse 站点的帖子。

配置参数

d-topics-list 元素支持以下属性来自定义你的主题显示:

  • discourse-url - 你的 Discourse 站点的 URL(必需)
  • template - 显示样式选项:
    • basic(默认)- 显示最少的主题信息
    • complete - 显示标题、用户名、头像、创建日期和缩略图
  • per-page - 要显示的主题数量
  • category - 要从特定类别过滤主题的类别 ID
  • tags - 按特定标签过滤主题
  • allow-create - 设置为 true 时,显示“新主题”按钮
  • top_period - 显示特定时间段内的热门主题:
    • all
    • yearly
    • quarterly
    • monthly
    • weekly
    • daily

你可以组合多个参数来优化你的主题列表显示。例如:

<d-topics-list
  discourse-url="https://discourse.example.com"
  category="5"
  tags="announcements"
  per-page="10"
  template="complete">
</d-topics-list>

自定义外观

你可以使用 Admin > Customize > Themes 面板中的自定义 SCSS 来设置嵌入式主题的样式。点击你当前或默认的主题,然后点击 Edit Code。然后,你可以选择 Show_advanced 并选择 Embedded CSS 来添加你的自定义代码:

以下是用于创建网格布局的 SCSS 示例:

.topics-list {
  display: grid;
  grid-template-columns: repeat(2, 1fr);

  .topic-list-item {
    .main-link {
      border: 1px dotted gray;
      padding: 0;
    }

    .topic-column-wrapper {
      flex-direction: column-reverse;

      .topic-column.details-column {
        width: 100%;
      }

      .topic-column.featured-image-column .topic-featured-image img {
        max-width: initial;
        max-height: initial;
        width: 100%;
      }
    }
  }
}

最佳实践

  • 使用有意义的类别和标签过滤器来显示与你的受众相关的内容
  • 设置适当的 per-page 值,避免让访问者不知所措
  • 在不同的屏幕尺寸上测试你嵌入的主题,以确保响应式设计
  • 当空间允许时,考虑使用 complete 模板以获得更好的视觉效果
  • 定期查看你的允许主机列表,以确保只有授权的域可以嵌入你的主题

常见问题及解决方案

主题未在外部域上显示

问题:嵌入式主题在外部域上查看时显示为空白或灰色框。

解决方案:将外部域添加到 Discourse 站点的 Admin > Customize > Embedding > Allowed Hosts。确保包含正确的子域(例如,如果你的站点使用 www.example.com,请添加 www.example.com 而不是仅 example.com)。

脚本加载错误

问题:嵌入脚本未能加载或返回连接错误。

解决方案

  • 验证脚本源中的 Discourse URL 是否正确且可访问
  • 检查 embed_topics_list 站点设置是否已启用
  • 确保你的 Discourse 站点不要求登录才能访问公开主题

SameSite 上下文行为

在嵌入站点和论坛共享父域的 SameSite 上下文中,Discourse 会尊重登录状态并相应地显示结果。已登录用户可能会看到来自安全类别的、匿名用户无法访问的内容。

常见问题解答

问:我可以在私有 Discourse 站点上嵌入主题吗?
答:不可以,主题嵌入仅适用于公开的 Discourse 站点。无法嵌入私有、需要登录的站点。

问:我可以在同一页面上嵌入多个主题列表吗?
答:是的,你可以在同一页面上包含多个 <d-topics-list> 元素,并使用不同的参数来显示不同的主题集合。

问:如何嵌入带有特色图片的主题?
答:在 <d-topics-list> 元素中使用 template="complete" 参数来显示带有缩略图和特色图片的主题。

问:我可以更改主题链接的打开方式吗?
答:默认情况下,主题链接会在父窗口中打开。你可以通过 CSS 或 JavaScript 自定义来修改此行为。

附加资源

9 个赞

这是否适用于 Discourse 订阅?我尝试实现它,但它却将我的整个论坛框起来,而不是主题?

1 个赞

是的,这应该可以与Discourse Subscriptions插件一起正常工作。

嵌入依赖于配置特定参数来控制显示哪些主题,例如通过网站HTML中的d-topics-list标签来设置categorytagsper-page。如果您的嵌入最终框定了您的整个论坛,您可能需要确保Discourse URL和d-topics-list标签中的任何参数都已正确设置,以反映您打算显示的主题。

4 个赞

你好,非常好!谢谢!

我想将 topic-list-item a 元素的 target 值更改为 “_blank”(默认是 “_parent”,存在跨域问题,也不是我想要的),

我该怎么做?

您好,我正尝试将这些内容显示在两个不同的网站上。

我的 Discourse URL 是 https://learn.getupearlier.com

我已将此脚本嵌入在此处,并且可以正常工作:

我已将相同的脚本嵌入在此处,但无法正常工作:

这是放在标头中的内容:

<script src="https://learn.getupearlier.com/javascripts/embed-topics.js"></script>

这是放在页面中的内容:

<d-topics-list discourse-url="https://learn.getupearlier.com" category="5" per-page="10"></d-topics-list>

任何帮助都将不胜感激!

2 个赞

您好 Michael,

您在这里遇到的问题很可能与使用不同于您的 Discourse 域的域来嵌入主题有关。

您的脚本在 getupearlier.com 上可以工作,因为这与您的 Discourse 站点 learn.getupearlier.com 位于同一域上,而 michaelbakerdigital.com 位于不同的域上。

我已将此部分添加到指南中,其中解释了如何解决这种情况。

因此,在您的情况下,将 michaelbakerdigital.com 添加到您的 Discourse 站点的“嵌入”→“允许的主机”应该可以使您在该域上正确嵌入主题。

6 个赞

您好,我允许了我下面显示的这个 URL:

这是测试 URL:
https://www.michaelbakerdigital.com/discourse-test/

我只得到一个空白的灰色错误框

这是 michaelbakerdigital.com 里面的代码

<div id='discourse-comments'></div>
<meta name='discourse-username' content='MikeB'>

<script type="text/javascript">
  DiscourseEmbed = {
    discourseUrl: 'https://learn.getupearlier.com/',
    discourseEmbedUrl: 'michaelbakerdigital.com',
    // className: 'CLASS_NAME',
  };

  (function() {
    var d = document.createElement('script'); d.type = 'text/javascript'; d.async = true;
    d.src = DiscourseEmbed.discourseUrl + 'javascripts/embed.js';
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(d);
  })();
</script>

或者这个:

<d-topics-list discourse-url="https://learn.getupearlier.com" category="5" per-page="5"></d-topics-list>

非常感谢您的帮助,我一直被这个问题困扰,一直想解决它。

你好,这里的解决方案是我的域名在嵌入部分添加了 www。

就是这样!花了这么多时间来处理这 4 个字符,但最终在 Discourse 和 WP Engine 支持的帮助下解决了。

是否有示例代码可用于将特色图片输出到外部网站?

非常感谢

需要帮助:在 Next.js 网站上嵌入 Discourse 主题列表

大家好,

我正尝试在我用 Next.js 框架和 Node.js 构建、并通过 Vercel 部署的网站 (example.io) 上嵌入 Discourse 主题列表。为此,我在 test-discourse.app 上创建了一个测试副本。

以下是我目前所做的:

  1. 在 Discourse 的嵌入设置中添加了主机。
  2. 在环境中启用了 CORS,并将主机添加到了 CORS 源。
  3. 关闭了 CSP (内容安全策略)。

尽管遵循了这些步骤并添加了必要的脚本,我仍然无法在我的网站上看到主题列表。

这是我正在使用的代码:

在 head 部分:

<script src="my-website/javascripts/embed-topics.js"></script>

在 body 部分:

<d-topics-list discourse-url="my-website" tags="example"></d-topics-list>

也尝试了帖子中所示的分类嵌入。

有人能指出我可能遗漏或做错的地方吗?任何关于让主题列表出现在我网站上的建议都将不胜感激。

提前感谢您的帮助!

我有一个 Discourse 实例运行在 VPS 上
我还有另一个网站运行在不同的 VPS 上
两者都有相同的根域名,例如

community.mydomain.com
mydomain.com

我已成功使用此方法将论坛服务器 (Discourse) 的主题列表嵌入到另一个网站中。这对于从我的网站吸引流量到论坛非常有用。

我使用右侧边栏块组件来列出 discourse-calendar 插件日历中的“即将举行的活动”

我想在我的其他网站上复制“即将举行的活动”。我可以使用此主题中描述的方法来获取日历类别中的所有主题,但它们的排序方式是按最近发布的时间。

右侧边栏块组件按活动日期对它们进行排序
示例

有办法做到这一点吗?我对两个网站都有管理控制权。
是否有其他方法可以从我的 Discourse 服务器提取数据,例如 API?API 是默认安装在所有 Discourse 实例上的,还是我必须安装它?

1 个赞

既然我没有得到任何提示,我想我会为那些查看的人回答我自己的几个问题。

仅供参考,是的,自托管的 官方安装 包括 REST API。

API 示例线程 获取提示,了解如何从终端发出 cURL 调用。一旦 cURL 命令起作用,我就使用这个网站将命令行版本转换为 PHP

我的另一个服务器运行 PHP 作为后端,我从网页向服务器上的函数发出 ajax 调用。Discourse 输出它构建用于解码的 json 和 javascript。按需样式化……汤
注意这可能只起作用,因为

并且我使用 API 密钥和用户,如 此处 所示。
希望这对某人有帮助 :+1:

1 个赞

我们似乎也可以像这样在论坛帖子中使用嵌入链接:

<iframe> width="500" height="400" src="https://meta.discourse.org/embed/topics?tags=release-notes" frameborder="0" scrolling="no"></iframe>

(在这里它不起作用,因为他们尚未在其 iframe 管理设置中启用自己的网站)

但是,scrolling="no" 无效……显然,标准机构在 HTML5 中已弃用 scrolling,并用……什么都没有替换它。iframe 每年都在变得更好,对吧?

在我测试时,如果我将 iframe 中的 <body> 更改为 overflow: hidden,水平滚动条就会消失。我还没有找到一种方法来消除垂直滚动条。从我的插件来看,我是否有办法修改嵌入页面以设置 overflow: hidden

嵌入主题列表时,如果我想从所有嵌入的主题创建一个带有水平滚动的轮播,哪种方式“最好”?

有没有办法将每个主题链接更改为在新标签页/窗口中打开?