表单提交前须双重校验身份证号(15/18位,末位X)和手机号(11位、限定号段),用pattern正则+JavaScript;科室医生联动采用data-*预加载JSON;时间控件改用三联select并动态禁用时段;提交按钮需JS锁定状态防重提。

表单提交前必须校验身份证号和手机号格式
浏览器原生 required 和 type="email" 对挂号场景完全不够用——身份证号要区分15位/18位、末位可能是X;手机号得限定11位且匹配号段。光靠 HTML5 属性会漏掉 13000000000 这种无效号,或放行 12345678901 这类非运营商号段。
实操建议:
- 用
pattern配合正则:身份证用pattern="[0-9]{17}[0-9Xx]|[0-9]{15}",手机号用pattern="1[3-9][0-9]{9}" - 必须加 JavaScript 双重校验,因为 pattern 在 Safari 旧版和部分安卓 WebView 中不触发
- 在
input失去焦点(blur)时实时提示,别等点提交才弹 alert
select 医生科室联动必须用 data-* 属性预存数据
用户先选「内科」,再选「呼吸科」,最后选医生——如果每次选完都发请求查后端,页面会卡顿且易出竞态问题。实际开发中更稳的做法是:把所有科室-医生关系一次性加载进页面,用 data-doctors 存 JSON 字符串。
示例结构:
立即学习“前端免费学习笔记(深入)”;
<select id="dept">
<option value="neike">内科</option>
<option value="waike">外科</option>
</select>
<p><select id="doctor"></select></p><p><script>
const deptMap = {
"neike": '[{"id":"d001","name":"张医生","time":"8:00-12:00"}]',
"waike": '[{"id":"d002","name":"李医生","time":"14:00-17:00"}]'
};
</script>这样切换科室时,直接 JSON.parse(deptMap[value]) 渲染医生下拉,无网络延迟,也避免重复请求。
时间选择控件不能只用 type="datetime-local"
这个原生控件在 iOS Safari 和部分国产安卓浏览器里根本不可用,点开没反应,或者日期格式错乱(比如显示成 2024-05-20T08:00 却无法编辑)。挂号系统对时间精度要求高——必须精确到“上午/下午/夜诊”+具体时段,且要禁用已约满的时间点。
实操建议:
- 放弃
datetime-local,改用三个独立select:日期(未来7天)、班次(上午/下午/夜间)、时段(每30分钟一档) - 每个时段选项加
data-status="full"或data-status="available",前端根据返回的预约状态动态禁用disabled - 提交时拼接成 ISO 格式字符串传给后端,例如
"2024-05-22T08:30"
提交按钮点击后必须立即置灰并改文字
挂号接口响应慢是常态,用户狂点“确认预约”会导致重复提交——后端没做幂等处理的话,可能一个号挂出三张号条。单纯 CSS disabled 不够,得配合 JS 锁定状态。
关键代码逻辑:
const btn = document.querySelector('#submit-btn');
btn.addEventListener('click', function(e) {
if (btn.dataset.sending === 'true') return;
btn.dataset.sending = 'true';
btn.textContent = '提交中...';
btn.disabled = true;
// 发起 fetch 后,无论成功失败都要恢复
});注意:别只在 finally 里恢复,fetch 被 abort 或网络异常时可能不进 finally,要在 then 和 catch 里都写恢复逻辑。
真实场景里,时间控件的禁用状态、医生列表的加载中动画、表单字段的只读锁定,这些细节没对齐,用户就会觉得系统“卡”或“没反应”。最麻烦的是跨端一致性——iOS 微信内置浏览器对 inputmode 和 autocomplete 的支持差异,会让键盘类型错乱,这点容易被忽略。


















