纯html+少量css仅能展示静态课表,实现“选课—占位—防重复提交”必须引入javascript;小规模固定课表推荐布局,语义正确、屏幕阅读器友好、行列对齐稳定;动态或响应式需求则用+css grid更灵活。

直接用纯 HTML + 少量 CSS 就能做出可用的健身房团课预约页面,但真要支持“选课—占位—防重复提交”,必须引入 JavaScript;纯静态页面只能展示课表,无法处理预约逻辑。
课表结构用 <table> 还是 <code><div> 布局?
<p>小规模固定课表(比如 7 天 × 6 节课)用 <code><table> 更直观、语义正确、屏幕阅读器友好,且 CSS 控制行列对齐更稳;但若需横向滚动、动态增删时段或响应式折叠(比如手机端改竖排时间轴),<code><div> + CSS Grid 更灵活。
<p>实操建议:</p>
<ul><li>先用 <code><table> 搭骨架,列是日期(<code><th>),行是时段(<code><th>),单元格放课程名 + 剩余名额 + <code><button></button>
<button></button> 加 data-course-id 和 data-slot 属性,方便 JS 绑定事件<td> 里嵌套多层 <code><div>,否则打印课表或爬虫解析易出错
<h3>
<code>fetch() 提交预约时为什么总被 403 或 CORS 拦截?
因为浏览器默认禁止跨域请求,而你的 HTML 文件双击打开是 file:// 协议,连本地 localhost:3000 的 API 都会被拦。不是后端没配,是你根本没走 HTTP 协议。
常见错误现象:
- 控制台报
Access to fetch at 'http://localhost:3000/book' from origin 'null' has been blocked - 点按钮没反应,Network 面板里看不到请求发出
解决办法只有两个:
- 用轻量服务器启动页面:VS Code 装 Live Server 插件,右键 → “Open with Live Server”,地址变成
http://127.0.0.1:5500/ - 或者把前端代码部署到真实 HTTP 环境(如 GitHub Pages + 后端允许该域名跨域)
别试 --disable-web-security 启动 Chrome——开发可以,但不解决实质问题,上线必挂。
怎么防止用户狂点“预约”按钮导致重复提交?
光禁用按钮还不够。用户可能刷新页面重来、或开多个标签页同时点,得靠服务端幂等性 + 前端状态锁双重保障。
实操建议:
- 点击后立即将按钮设为
disabled并改文字为“提交中…”(用button.disabled = true) - 同时给按钮加临时 class(如
is-submitting),CSS 隐藏 hover 效果,避免视觉误导 - 成功后不要只弹 alert,而是更新对应单元格的文案:从“剩余 8 人”变成“已预约”,并移除按钮
- 失败时恢复按钮,并提示具体错误(如
“名额已满”或“请先登录”),而不是笼统的“提交失败”
真正难的不是画出课表,而是让每个 <button></button> 点下去都有确定的响应、可回溯的状态、以及和后端一致的并发控制。静态页面看着像,一交互就露馅——尤其在多人同时抢热门课时,前端乐观更新很容易和实际库存对不上。











