iter(g296): 修正表单校验失败仍提交

This commit is contained in:
HIsheR
2026-10-26 23:37:15 +08:00
parent 8dd31bde4b
commit 2c0a760f18
6 changed files with 25 additions and 7 deletions
+8 -2
View File
@@ -30,6 +30,10 @@ async function checkRuleAsync(value: string, rule: FormRule): Promise<string | n
return r === true ? null : typeof r === 'string' ? r : rule.message ?? '校验未通过';
}
/*** 字段容器里的焦点落点:自绘控件(非搜索式下拉、评分、开关)没有原生 input,只查 input 会拿到 null,退到按钮 / 带 tabindex 的节点 ***/
const focusableOf = (box: HTMLElement): HTMLElement | null =>
box.querySelector<HTMLElement>('input:not([type="hidden"]), textarea, select, button, [tabindex]:not([tabindex="-1"])');
/*** 表单字段:label + 控件插槽 + 错误区;返回句柄(同步 / 异步两种校验)供 form 聚合 ***/
export function formItem(props: FormItemProps, control: HTMLElement): FormItemHandle {
// —— 状态集中声明 ——
@@ -120,13 +124,15 @@ export function form(props: FormProps, items: FormItemHandle[]): HTMLElement {
if (!msg) continue; // 卫语句:本项通过
bad += 1;
if (firstBad) continue; // 只把首个错误控件留作焦点目标
firstBad = item.el.querySelector('input, textarea, select') as HTMLElement | null;
const target = focusableOf(item.el);
if (!target) item.el.tabIndex = -1; // 整块无可聚焦控件时把字段容器本身设为焦点落点(-1 不进 Tab 序,只接受程序聚焦)
firstBad = target ?? item.el;
}
submitBtn.disabled = false;
running = false;
summary.hidden = bad === 0;
summary.textContent = bad ? `有 ${bad} 项需要修改,已定位到第一处` : '';
if (firstBad) { firstBad.focus(); props.onError?.(bad); return; } // 卫语句:有错误不提交
if (bad > 0) { firstBad?.focus(); props.onError?.(bad); return; } // 有错即中止:判据用错误数而非焦点目标,否则自绘控件字段会漏过去直接提交
props.onSubmit?.();
};