HTML定时表单提交双重问题:刷新计时异常与提交按钮失效
问题分析与解决方案
问题概述
需要实现的功能:
- 通过id为
send的表单将数组userchoice存入数据库 - 设置表单1分钟后自动提交,同时将数据库
answered字段设为true - 根据
answered字段向用户展示不同内容
当前遇到两个问题:
- 页面刷新时,表单自动提交,但计时未沿用数据库存储的数值,出现跳变
- 点击提交按钮时,
answered字段未立即设为true,需点击第二次才生效
问题根源与修复代码
问题1:刷新后计时跳变的原因
页面刷新时,原代码先查询旧数据,再处理POST提交更新数据库,但更新后未重新获取最新数据,仍使用更新前的timespnt计算计时;同时前端自动提交的setTimeout硬写为1分钟,未与后端剩余时间同步。
问题2:提交按钮点击后answered不生效的原因
原代码先查询旧数据,再执行更新操作,但更新后未重新获取最新的answered值,页面渲染仍使用更新前的状态,导致需要第二次点击才会显示提交完成。
修复后的完整代码
<html> <?php $time = 60; $questionid = 7; $answered = "false"; $servername = "***"; $dbusername = "***"; $dbpassword = "*****"; $dbname = "***"; $sub = "***"; $conn = mysqli_connect($servername, $dbusername, $dbpassword, $dbname); // 先处理POST请求,再查询最新数据 if (isset($_POST["submitButton"]) || isset($_POST["submitted"])) { $updata = $_POST["updata"] ?? ''; $timetosend = $_POST["timespnt"] ?? 0; $anstosend = $_POST["answered"] ?? 'false'; // 增加subject条件,避免误更新同questionid的其他数据 $upsql = "UPDATE question_data SET answered='$anstosend', ansstr='$updata', timespnt='$timetosend' WHERE questionid='$questionid' AND subject='$sub'"; $conn->execute_query($upsql); } // 处理完POST后,查询最新的数据 $mysql = "SELECT answered,ansstr,timespnt FROM question_data WHERE questionid='$questionid' and subject='$sub' limit 1"; $oldresult = $conn->execute_query($mysql); $value = $oldresult->fetch_object(); $answered = $value->answered ?? 'false'; $timetaken = $value->timespnt ?? 0; $remainingTime = 60 - $timetaken; // 防止剩余时间出现负数 if ($remainingTime < 0) { $remainingTime = 0; } ?> <head> </head> <body> <div id='timer'></div> <form method="POST" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']).'?questionid='.$questionid;?>" style='margin:auto;text-align:center' id="send" > <input type="hidden" name="submitted" value="" /> <input type="hidden" name="timespnt" value="<?php echo $timetaken;?>" /> <input type="hidden" name="updata" value="" /> <input type="hidden" name="answered" value="false" /> <?php if($answered != 'true'): ?> <input name="submitButton" type="submit" value="SUBMIT"> <?php endif; ?> </form> <script> var Timer; var TotalSeconds; const form = document.getElementById('send'); function CreateTimer(TimerID, Time) { Timer = document.getElementById(TimerID); TotalSeconds = Time; UpdateTimer(); // 使用箭头函数避免字符串解析问题 setTimeout(() => Tick(), 1000); } function Tick() { TotalSeconds -= 1; form.querySelector('[name=timespnt]').value = TotalSeconds; if(TotalSeconds <= 0){ form.querySelector('[name=answered]').value = "true"; form.submit(); } else{ UpdateTimer(); setTimeout(() => Tick(), 1000); } } function UpdateTimer() { Timer.innerHTML = TotalSeconds; } window.addEventListener('DOMContentLoaded', () => { let tId; form.addEventListener('submit', (e) => { clearTimeout(tId); form.querySelector('[name=submitted]').value = 'formsubmit'; form.querySelector('[name=updata]').value = userchoice.toString(); form.querySelector('[name=answered]').value = "true"; }); // 根据后端剩余时间设置自动提交延迟,而非固定1分钟 const remainingTime = <?php echo $remainingTime; ?> * 1000; if (remainingTime > 0) { tId = setTimeout(() => form.submit(), remainingTime); } else { // 剩余时间为0时直接提交 form.querySelector('[name=answered]').value = "true"; form.submit(); } }); var userchoice=['a','b','c']; <?php if($answered == 'false') { echo "window.onload = CreateTimer('timer', {$remainingTime});"; } else { echo "document.write('Submission Completed');"; } ?> </script> </body> </html>
关键修复点
- 调整代码执行顺序:先处理POST提交更新数据库,再查询最新数据,确保页面渲染使用更新后的状态和计时数值。
- 同步自动提交延迟:前端自动提交不再固定为1分钟,而是根据后端计算的剩余时间设置,避免刷新后计时跳变。
- 完善数据库更新条件:UPDATE语句增加
subject='$sub',防止误更新同questionid的其他数据。 - 处理异常计时:增加剩余时间负数判断,避免计时逻辑异常。
- 优化定时器调用:使用箭头函数替代字符串解析调用,减少潜在错误。
内容的提问来源于stack exchange,提问作者Kabir
相关产品推荐
相关产品推荐

