在构建一个内容丰富的网站时,提供高效便捷的搜索功能是提升用户体验的关键一环。安企CMS(AnQiCMS)在设计之初就充分考虑了这一点,通过其灵活的模板引擎和内置标签,我们可以相对轻松地在网站前端实现搜索功能,并进一步优化,让搜索结果中的关键词醒目地高亮显示。

核心机制:理解 AnQiCMS 的搜索原理

安企CMS 网站前端搜索的核心在于 search/index.html 这个模板文件。当用户通过网站上的搜索表单提交一个关键词时,这个关键词会作为名为 q 的 URL 查询参数传递给预设的 /search 路径。例如,如果用户搜索“安企CMS”,URL 可能会是 http://yourdomain.com/search?q=安企CMS

search/index.html 模板中,系统内置的 archiveList 标签非常智能。它会自动识别并利用 URL 中存在的 q 参数来筛选相关的文档内容。这意味着,大部分的搜索逻辑都由 AnQiCMS 内部处理,我们只需关注前端的呈现。

构建搜索表单

实现搜索功能的第一步是提供一个直观的搜索表单。这个表单通常放置在网站的页头、侧边栏或专门的搜索页面上。一个基本的搜索表单会使用 GET 方法将用户输入的关键词发送到 /search 路径。

以下是一个简单的搜索表单示例:

<form method="get" action="/search">
    <div class="search-input-group">
        <input type="text" name="q" placeholder="请输入搜索关键词..." value="{{urlParams.q}}" class="search-field">
        <button type="submit" class="search-button">搜索</button>
    </div>
</form>

在这个表单中:

  • method="get" 确保关键词作为 URL 查询参数传递。
  • action="/search" 指定了搜索结果页的路径。
  • name="q" 是输入框的关键,AnQiCMS 的 archiveList 标签会识别这个 q 参数。
  • value="{{urlParams.q}}" 这是一个小技巧,它能让用户在搜索结果页看到自己之前输入的关键词,提升用户体验。urlParams.q 会自动获取当前 URL 中 q 参数的值。

展示搜索结果列表

当用户提交搜索请求后,AnQiCMS 会加载 search/index.html 模板。在这个模板中,我们使用 archiveList 标签来获取并展示搜索到的文档列表。

{% archiveList archives with type="page" limit="10" %}
    {% for item in archives %}
    <div class="search-result-item">
        <h3><a href="{{item.Link}}">{{item.Title}}</a></h3>
        <p class="description">{{item.Description}}</p>
        <div class="meta">
            <span>分类:{% categoryDetail with name="Title" id=item.CategoryId %}</span>
            <span>发布日期:{{stampToDate(item.CreatedTime, "2006-01-02")}}</span>
            <span>浏览量:{{item.Views}}</span>
        </div>
    </div>
    {% empty %}
    <div class="no-results">
        很抱歉,没有找到与“{{urlParams.q}}”相关的结果。
    </div>
    {% endfor %}

    <div class="pagination-area">
        {% pagination pages with show="5" %}
            {# 分页导航的代码,可参考官方文档 #}
            {% if pages.FirstPage %}
                <a class="{% if pages.FirstPage.IsCurrent %}active{% endif %}" href="{{pages.FirstPage.Link}}">首页</a>
            {% endif %}
            {% if pages.PrevPage %}
                <a href="{{pages.PrevPage.Link}}">上一页</a>
            {% endif %}
            {% for page in pages.Pages %}
                <a class="{% if page.IsCurrent %}active{% endif %}" href="{{page.Link}}">{{page.Name}}</a>
            {% endfor %}
            {% if pages.NextPage %}
                <a href="{{pages.NextPage.Link}}">下一页</a>
            {% endif %}
            {% if pages.LastPage %}
                <a class="{% if pages.LastPage.IsCurrent %}active{% endif %}" href="{{pages.LastPage.Link}}">末页</a>
            {% endif %}
        {% endpagination %}
    </div>
{% endarchiveList %}

在上述代码中:

  • archiveList archives with type="page" limit="10" 会自动获取与 q 参数匹配的文档,并按每页10条进行分页。
  • for item in archives 循环遍历每一条搜索结果。
  • item.Titleitem.Linkitem.Description 等是文档的常用字段,用于展示搜索结果摘要。
  • {% empty %} 块用于在没有搜索结果时显示友好提示。
  • {% pagination pages with show="5" %} 标签用于生成分页链接,确保在大量搜索结果时也能轻松浏览。

实现关键词高亮

为了让搜索结果中的关键词更加醒目,我们可以利用 AnQiCMS 模板引擎提供的过滤器来对标题和描述进行处理。核心思想是:获取用户输入的关键词,然后将标题和描述中所有匹配到的关键词用 <mark> 标签包裹起来。

AnQiCMS 提供了 replace 过滤器和 safe 过滤器,可以帮助我们轻松实现这一点。

  1. 获取搜索关键词:在 search/index.html 模板中,可以通过 {{urlParams.q}} 直接获取当前 URL 中的 q 参数值,即搜索关键词。
  2. 使用 replace 过滤器:将标题或描述中匹配到的关键词替换为带有 <mark> 标签的关键词。
  3. 使用 safe 过滤器:由于 replace 过滤器会在字符串中插入 HTML 标签(如 <mark>),为了让浏览器正确解析这些标签而不是将其作为纯文本显示,我们需要在输出时使用 safe 过滤器。

将上面的搜索结果展示代码稍作修改,加入关键词高亮:

”`twig {% set searchQuery = urlParams.q %} {# 获取搜索关键词 #}

{% archiveList archives with type=“page” limit=“10” %}

{% for item in archives %}
<div class="search-result-item">
    <h3>
        <a href="{{item.Link}}">
            {# 对标题进行高亮处理 #}
            {% if searchQuery %}
                {{ item.Title|replace:searchQuery,'<mark>'~searchQuery~'</mark>'|safe }}
            {% else %}
                {{ item.Title }}
            {% endif %}
        </a>
    </h3>
    <p class="description">
        {# 对描述进行高亮处理 #}
        {% if searchQuery %}
            {{ item.Description|replace:searchQuery,'<mark>'~searchQuery~'</mark>'|safe }}
        {% else %}
            {{ item.Description }}
        {% endif %}
    </p>
    <div class="meta">
        <span>分类:{% categoryDetail with name="Title" id=item.CategoryId %}</span>
        <span>发布日期:{{stampToDate(item.CreatedTime, "2006-01-02")}}</span>
        <span>浏览量:{{item.Views}}</span>
    </div>
</div>
{% empty %}
<div class="no-results">
    很抱歉,没有找到与“{{urlParams.q}}”相关的结果。
</div>
{% endfor %}

<div class="pagination-area">
    {# 分页导航的代码同上 #}
    {% pagination pages with show="5" %}
        {% if pages.FirstPage %}<a class="{% if pages.FirstPage.IsCurrent %}active{% endif %}" href="{{pages.FirstPage.Link}}">首页</a>{% endif %}
        {% if pages.PrevPage %}<a href