在安企CMS中管理网站留言是日常运营中常见的需求,特别是当我们需要收集特定信息时,一个能够灵活定制的留言表单就显得尤为重要。安企CMS充分考虑了这一需求,提供了强大的guestbook标签,让我们可以轻松动态生成包含自定义字段的留言表单,并适配多种输入类型。

留言表单标签(guestbook)的力量

核心在于guestbook标签。它允许我们通过模板动态获取后台定义的留言表单字段。当在模板中使用{% guestbook fields %}...{% endguestbook %}时,fields变量将承载一个包含所有自定义留言字段定义的数组。这意味着我们不需要硬编码每一个表单项,而是由系统根据后台设置自动提供这些字段的结构信息,极大地提高了模板的复用性和灵活性。

动态生成表单字段的秘密

fields数组中的每一个元素(通常命名为item)都代表一个独立的留言字段,它包含了生成表单项所需的关键信息:

  • Name: 字段的显示名称,如“您的姓名”、“联系电话”等。
  • FieldName: 字段的唯一标识,用于表单提交时后端接收数据。例如,如果后台定义了一个名为“兴趣爱好”的字段,其FieldName可能是hobbies
  • Type: 这是实现不同输入类型的关键。安企CMS支持多种字段类型,如text(单行文本)、number(数字)、textarea(多行文本)、radio(单选)、checkbox(多选)和select(下拉选择)。
  • Required: 一个布尔值,指示该字段是否为必填项。在前端可以根据此属性添加HTML5的required属性或自定义验证。
  • Content: 字段的默认值,通常用于placeholder提示。
  • Items: 当字段类型为radiocheckboxselect时,Items会包含一个数组,列出所有可供选择的选项。

有了这些信息,我们就可以在模板中利用for循环遍历fields数组,并结合if/elif逻辑判断item.Type,从而为每个字段渲染出适配的HTML表单元素。

下面是一个完整的示例代码,展示了如何动态生成一个包含不同输入类型的留言表单:

<form method="post" action="/guestbook.html">
    {% guestbook fields %}
        {% for item in fields %}
        <div>
            <label>{{item.Name}}</label>
            <div>
                {% if item.Type == "text" or item.Type == "number" %}
                <input type="{{item.Type}}" name="{{item.FieldName}}" {% if item.Required %}required lay-verify="required"{% endif %} placeholder="{{item.Content}}" autocomplete="off">
                {% elif item.Type == "textarea" %}
                <textarea name="{{item.FieldName}}" {% if item.Required %}required lay-verify="required"{% endif %} placeholder="{{item.Content}}" rows="5"></textarea>
                {% elif item.Type == "radio" %}
                    {%- for val in item.Items %}
                    <input type="{{item.Type}}" name="{{item.FieldName}}" value="{{val}}" title="{{val}}"> {{val}}
                    {%- endfor %}
                {% elif item.Type == "checkbox" %}
                    {%- for val in item.Items %}
                    <input type="{{item.Type}}" name="{{item.FieldName}}[]" value="{{val}}" title="{{val}}"> {{val}}
                    {%- endfor %}
                {% elif item.Type == "select" %}
                <select name="{{item.FieldName}}">
                    {%- for val in item.Items %}
                    <option value="{{val}}">{{val}}</option>
                    {%- endfor %}
                </select>
                {% endif %}
            </div>
        </div>
        {% endfor %}

        {# 验证码字段,如果后台开启了验证码功能 #}
        <div style="display: flex; clear: both; margin-top: 15px;">
          <input type="hidden" name="captcha_id" id="captcha_id">
          <input type="text" name="captcha" required placeholder="请填写验证码" style="flex: 1; border: 1px solid #e6e6e6; padding: 0 10px; height: 38px; line-height: 38px; box-sizing: border-box;">
          <img src="" id="get-captcha" style="width: 120px;height: 38px;cursor: pointer; margin-left: 5px; border: 1px solid #e6e6e6;" />
          <script>
            document.addEventListener('DOMContentLoaded', function() {
              var captchaImg = document.getElementById('get-captcha');
              if (captchaImg) {
                captchaImg.addEventListener("click", function () {
                  fetch('/api/captcha')
                          .then(response => response.json())
                          .then(res => {
                            document.getElementById('captcha_id').setAttribute("value", res.data.captcha_id);
                            captchaImg.setAttribute("src", res.data.captcha);
                          }).catch(err => console.error('获取验证码失败:', err));
                });
                // Initial load
                captchaImg.click();
              }
            });
          </script>
        </div>

        <div style="margin-top: 20px;">
            <button type="submit" style="padding: 10px 20px; background-color: #007bff; color: white; border: none; cursor: pointer;">提交留言</button>
            <button type="reset" style="padding: 10px 20px; background-color: #6c757d; color: white; border: none; cursor: pointer; margin-left: 10px;">重置</button>
        </div>
    {% endguestbook %}
</form>

在上面的代码中,我们为每种字段类型渲染了对应的HTML标签:

  • textnumber类型生成<input type="text"><input type="number">
  • textarea类型生成<textarea>
  • radiocheckboxselect类型则会遍历item.Items数组,生成各自的选项。需要注意的是,checkboxname属性末尾通常会添加[],以便后端能以数组形式接收多个选中值。
  • required属性的添加,可以利用浏览器自带的HTML5表单验证,提升用户体验。

提交留言:后端交互与验证码集成

表单的提交地址固定为/guestbook.html,提交方式为POST。除了动态生成的自定义字段外,安企CMS也要求一些核心字段如user_name(留言者姓名)、contact(联系方式)和content(留言内容)必须在表单中存在并被提交。这些字段可以在后台留言设置中进行管理,并根据需要设置为必填项。

为了增强安全性,防止垃圾留言,安企CMS还支持集成验证码。当后台开启留言验证码功能后,我们需要在表单中加入验证码的输入框及图片显示逻辑。上述代码中已经包含了验证码的JS生成和显示逻辑,用户点击图片即可刷新验证码,输入后随表单一同提交。

总结

安企CMS的guestbook标签为网站留言表单的定制提供了极大的便利。通过简单地在后台定义字段,我们便可以在前端模板中动态生成功能丰富的表单,适配各种信息收集场景。这种设计不仅提升了开发效率,也为网站运营带来了更多的可能性,让网站能够更灵活地与用户互动,收集所需数据。