织梦表单防止重复提交设置

织梦自定义表单上线后,最让人头疼的不是没数据,而是数据重复——同一个访客连点几下"提交"按钮,数据库里就冒出几条完全相同的记录,既干扰后续筛选,也拉低线索的真实性。本文围绕织梦表单防止重复提交设置,从前端、后端、数据库三个层面给出可落地的方案。

一、重复提交是怎么产生的

重复提交通常有两类来源:一是真实用户在网络卡顿时多次点击提交按钮;二是脚本机器人对同一表单 URL 的批量请求。无论哪种,根本原因都在于服务端没有对"同一份内容是否已入库"做判断,导致每次 POST 都被当作新数据处理。

二、前端方案:禁用按钮 + 防抖

最简单的做法是在表单提交后立刻禁用按钮,避免用户连点。可以在表单的 <form> 标签上加 onsubmit 事件:

<form action="/diy.php" method="post" onsubmit="return checkForm(this)">
  <input type="submit" id="btnSubmit" value="提交" class="btn" />
</form>
<script>
function checkForm(form){
  var btn=document.getElementById('btnSubmit');
  if(btn.dataset.locked==='1'){ return false; }
  btn.dataset.locked='1';
  btn.value='提交中...';
  btn.disabled=true;
  return true;
}
</script>

前端方案只能拦截真实用户的误操作,对机器人无效,必须配合后端限制使用。

三、后端方案:session 时间间隔限制

diy.php 入库逻辑前,用 session 记录上次提交时间,限定最小间隔。打开网站根目录下的 diy.php,找到处理提交的位置,在写入数据前加入:

session_start();
$lockKey='diy_form_' . $diyid . '_last';
$interval=30; // 30秒内不允许重复提交
if(isset($_SESSION[$lockKey]) && (time() - $_SESSION[$lockKey]) < $interval){
    ShowMsg('提交过于频繁,请稍后再试', '-1');
    exit();
}
$_SESSION[$lockKey]=time();

该方案对同一会话内的快速重复提交非常有效,是织梦表单防刷最常用的手段。

四、数据库方案:唯一索引兜底

对于要求强一致性的表单(如报名、预约),建议在数据表上建立唯一索引,从根上杜绝重复。例如以手机号作为唯一键:

ALTER TABLE dede_diyform1 ADD UNIQUE KEY uk_tel (tel);

同时在 diy.php 中捕获重复键异常:

$rs=$dsql->ExecuteNoneQuery($query);
if(!$rs && $dsql->GetErrorNo()==1062){
    ShowMsg('您已提交过,请勿重复提交', '-1');
    exit();
}

数据库方案对集群部署、CDN 加速场景同样有效,是最稳妥的兜底手段。

五、注意事项

session 方案依赖 cookie,若用户清缓存或换设备仍可绕过,应配合 IP 限制或数据库唯一键使用。
加唯一索引前务必先清理历史重复数据,否则索引创建会失败。
前端禁用按钮后,若 ajax 提交失败需及时恢复按钮可点击状态,否则用户无法再次提交。

六、后续优化方向

完成织梦表单防止重复提交设置后,建议把"提交频次"纳入运营监控,定期统计同一来源 IP、同一手机号的提交分布,识别异常峰值并动态调整间隔阈值。对于关键业务表单,可以把"是否重复"作为线索评分的一个维度,让销售团队优先处理首次提交的高质量线索,从而把防重复设置从单纯的技术防护,升级为对转化效率的实际提升。