edL
(Ed Lepedus)
1
我想创建一个横幅区域,位于首页标题下方,展示一些经过美化的分类框。例如:
我了解到可以使用“below-site-header”出口,并参考 如何在您的首页上仅显示自定义内容 中的说明来输出我的标记。
理想情况下,我希望添加一个自定义设置枚举字段,用于选择在此处展示的分类。是否有可能创建一个允许搜索分类的自定义设置字段?
此外,我还希望为这些卡片设置自定义背景图像,而不仅仅是分类背景图像。是否可以在分类设置模态框的“图像”选项卡中添加另一个文件输入项?例如:
总体而言,这看起来可行吗?是否有任何潜在的陷阱或技巧我需要了解?
可以考虑先使用 TLP 插件。系统已有一个指向主题的“特色图片”功能,您可能可以复用其中的一些代码。
鉴于类别不太动态,采用更静态的方法可能更有意义:+1
我想你需要决定它是否要由数据驱动。
edL
(Ed Lepedus)
5
理想情况下,我希望它能成为“带主题的类别框”的精美版本,同时自动获取类别的徽标和背景图片,以及该类别中的最新主题。
不过,如果使用标准主题或插件扩展机制实现这一点并不直接,那么投入产出比可能不高。在这种情况下,我将选择静态实现,或者使用类别框的主页布局,并按需进行样式调整。
我认为有两个关键测试标准:
- 是否存在一种标准方法来呈现“选择类别”的配置项?
- 是否存在一种标准方法向类别设置模态框添加元数据字段?
或者,如果我只需在配置中使用类别 ID,但仍能通过编程方式获取数据,那也完全可以接受。
然而,如果无法以这种方式获取类别数据,我将采用其他方案之一。
您可以在插件中实现任何您想要的功能(尽管显然最好采用能最大限度降低插件在核心更新后失效风险的策略)。先勾勒出您的想法,参考现有插件和 Discourse 核心代码,然后从一个简单的版本开始,并逐步迭代完善。
我查看了 Kris 之前发布的帖子,并直接将其改编为你可以用作基础的版本。这里涵盖的大部分内容都是他在原始主题中阐述的。
https://meta.discourse.org/t/how-to-add-a-featured-topic-list-to-your-discourse-homepage/132949
所有代码都将添加到您主题的 <head> (head_tag.html) 部分。
第一部分将检查您所在的页面是否为“主页”。
然后,我们将使用类别类上的 Category.list() 方法获取站点的类别。
接着,我们将这些类别与您希望 featured 的类别进行比较。这些类别将位于下方代码中定义的 definedFeaturedCategories 数组中。您允许的类别将被设置为组件,并传递给模板进行渲染。
<script type="text/discourse-plugin" version="0.8">
const Category = require("discourse/models/category").default;
// 我们将使用 Category 模型来检索站点类别
api.registerConnectorClass('above-main-container', 'featured-categories', {
// above-main-container 是插件出口,
// featured-topics 是您自定义的组件名称
setupComponent(args, component) {
api.onPageChange((url, title) => {
console.log(url,title)
if ((url === "/") || (url === "/latest") ) {
// 页面切换时,检查 URL 是否匹配
// 如果您的主页不是 /latest,请将其更改为 /categories
$('html').addClass('custom-featured-categories');
// 为 HTML 标签添加一个类,以便轻松进行 CSS 定位
let definedFeaturedCategories = ["uncategorized","blog","two"]
// 您希望 featured 的类别数组
// 请务必将类别标题转换为小写
let featuredCategories = [];
categories = Category.list();
for (let cat of categories) {
if (definedFeaturedCategories.includes(cat.name.toLowerCase())) {
// 仅将您希望 featured 的类别推送到待渲染的数组中
featuredCategories.push(cat)
}
}
component.set('featuredCategories', featuredCategories)
} else {
// 如果页面不匹配上述 URL,则执行以下操作:
$('html').removeClass('custom-featured-categories');
// 移除我们的自定义类
component.set('categories',[])
// 将类别设置为空数组以禁用渲染
}
});
}
});
</script>
下一部分将上述创建的组件模板注入到插件出口 above-main-container 中。它将调用第三步中创建的自定义 categories-wrapper,并将 categories 定义为上面创建的 featuredCategories。
<script type="text/x-handlebars" data-template-name="/connectors/above-main-container/featured-categories">
<div class="custom-featured-categories-wrapper">
{{categories-wrapper categories=featuredCategories}}
<!-- 使用下方创建的 categories-wrapper 模板 -->
<!-- 将 categories 定义为上方脚本中创建的 featuredCategories -->
</div>
</script>
第三部分创建了自定义的 categories-wrapper Handlebars 模板,用于渲染 featured 类别。它是直接改编自 Discourse 的 categories-only.hbs 用于 Discourse 的类别页面。
<script type="text/x-handlebars" data-template-name="components/categories-wrapper">
<!-- 这将创建一个名为 'categories wrapper' 的组件模板 -->
<!-- 所有模板代码均改编自 Discourse 自身的类别页面模板
https://github.com/discourse/discourse/blob/acd1693dac1bff6ff50250d942134bc48a27ff14/app/assets/javascripts/discourse/templates/components/categories-only.hbs -->
<div class="top-categories-wrapper">
{{#each categories as |c|}}
<div class="top-category-column-one">
{{category-title-link category=c}}
{{#if c.escription}}
<div class="category-description">
{{dir-span c.description}}
</div>
{{/if}}
{{#if c.isGrandParent}}
<table class="category-list subcategories-with-subcategories">
<tbody>
{{#each c.subcategories as |subcategory|}}
<tr
data-category-id={{subcategory.id}}
data-notification-level={{subcategory.notificationLevelString
}}
class="{{if
subcategory.description_excerpt
"has-description"
"no-description"
}}
{{if subcategory.uploaded_logo.url "has-logo" "no-logo"}}"
>
<td
class="category"
style={{border-color subcategory.color}}
>
{{category-title-link tagName="h4" category=subcategory}}
{{#if subcategory.description_excerpt}}
<div
class="category-description subcategory-description"
>
{{{dir-span subcategory.description_excerpt}}}
</div>
{{/if}}
{{#if subcategory.subcategories}}
<div class="subcategories">
{{#each subcategory.subcategories as |subsubcategory|
}}
{{#unless subsubcategory.isMuted}}
<span class="subcategory">
{{category-title-before category=subsubcategory
}}
{{category-link subsubcategory hideParent="true"
}}
</span>
{{/unless}}
{{/each}}
</div>
{{else if subcategory.description_excerpt}}
<div
class="category-description subcategory-description"
>
{{{dir-span subcategory.description_excerpt}}}
</div>
{{/if}}
</td>
</tr>
{{/each}}
</tbody>
</table>
{{else if c.subcategories}}
<div class="subcategories">
{{#each c.subcategories as |subcategory|}}
{{#unless subcategory.isMuted}}
<span class="subcategory">
{{category-title-before category=subcategory}}
{{category-link subcategory hideParent="true"}}
{{category-unread category=subcategory}}
</span>
{{/unless}}
{{/each}}
</div>
{{/if}}
</div>
<div class="top-category-column-two">
<span class="topics-header">
主题
</span>
<span class="topics-count">
{{c.topic_count}}
</span>
{{category-unread category=c tagName="div" class="unread-new"}}
</div>
{{/each}}
</div>
</script>
这应该能帮助您开始实现您在原始帖子(OP)中请求的功能。
若要为每个类别框根据自定义定义的颜色进行样式设置,在第三部分中,您可以使用 # + c.color 硬编码样式以访问类别的颜色代码。
除此之外,样式设置可以在 common.scss 文件中完成。
edL
(Ed Lepedus)
9
哇!非常感谢你这么详细且极其有帮助的回复,@jordan.vidrine!我会试试看,然后告诉你进展如何 
edL
(Ed Lepedus)
10
这效果很好,@jordan.vidrine:
唯一奇怪的是,主题只有在访问 /categories 后才会加载,否则就像根本没有主题一样:
你知道这是怎么回事吗?