Bootstrap不提供报销申请表单业务组件,需用form-group+row布局分三区、JS实现费用明细动态列表、input事件监听文件上传、is-invalid语义化校验及审批状态回显。

Bootstrap 本身不提供“报销申请表单”这种业务组件,它只提供可组合的表单控件、栅格和样式工具;直接套用官方示例容易漏掉报销场景的关键字段(如发票上传、费用明细列表、审批流标记),也容易在响应式和校验逻辑上翻车。
用 form-group + row 布局报销核心字段
报销表单不是线性堆砌,得区分「申请人信息」「费用明细」「附件与备注」三块。别用单列 form-control 拉到底,移动端会挤成窄条且难操作。
- 用
row包裹每组横向字段,比如「日期」和「报销类型」并排:两个col-md-6就够,col-sm-12保底小屏独占一行 - 「费用明细」必须用动态列表——Bootstrap 不管增删行,得自己用 JS 控制
tbody或div容器,每行带删除按钮和独立的amount、description输入框 - 金额输入框强制加
type="number"和step="0.01",避免用户输「100.」或「100,50」导致后端解析失败
custom-file 上传发票时绕开默认样式缺陷
Bootstrap 4+ 的 custom-file 在 Safari 和部分安卓 WebView 里无法触发 change 事件,且不支持多图预览。别信文档里“开箱即用”的说法。
- 保留
<input type="file" class="custom-file-input">,但用 JS 监听input事件而非change(input在文件选择后立即触发) - 预览发票缩略图?别依赖
custom-file-label,自己在旁边加<div id="preview-area"></div>,用URL.createObjectURL()渲染,否则 iOS 会白屏 - 后端接收时注意:
enctype="multipart/form-data"必须写在form标签上,漏掉就变成纯文本提交,发票字段为空
用 is-invalid + invalid-feedback 做语义化校验
报销表单的校验不是“必填”就够了。比如「交通费」需关联「出发地/目的地」,「住宿费」要检查「天数 × 单价 ≤ 总额」,这些得前端初步拦截,再交由后端终审。
- 手动给出错字段加
is-invalid类,并确保对应<div class="invalid-feedback"> 紧跟其后(DOM 顺序错乱会导致提示不显示) <li>服务端返回的错误结构最好统一为 <code>{ "field": "total_amount", "message": "总额不能低于明细合计" },前端按field值定位元素,避免硬编码 ID - 别用
required属性做金额校验——它只认空值,对「0」或「-100」无感;得用pattern或 JScheckValidity()配合自定义setCustomValidity()
最常被忽略的是「审批状态回显」:提交后页面不该清空,而要禁用所有输入框、显示「已提交,等待财务审核」,同时保留原始数据供用户查证。这要求表单初始渲染逻辑和提交成功后的 DOM 更新逻辑保持一致,而不是靠 location.reload() 简单粗暴解决。


















