From 865477c37f6540e38eb195c80ddbc7fa729cada9 Mon Sep 17 00:00:00 2001 From: HIsheR Date: Mon, 26 Oct 2026 23:06:21 +0800 Subject: [PATCH] =?UTF-8?q?iter(g280):=20=E8=A1=A8=E5=8D=95=E9=A1=B9?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=9D=A1=E4=BB=B6=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .ua/index.json | 10 ++++++++-- llms-full.txt | 4 +++- packages/skin/ui/src/form.ts | 6 +++++- packages/skin/ui/src/types.ts | 1 + packages/skin/ui/ua.manifest.json | 8 +++++++- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/.ua/index.json b/.ua/index.json index 7e2df99..f4e6408 100644 --- a/.ua/index.json +++ b/.ua/index.json @@ -1,6 +1,6 @@ { "$schema": "ui-arch-registry-index/0.1", - "generatedAt": "2026-10-26T15:05:05.398Z", + "generatedAt": "2026-10-26T15:06:03.807Z", "repoRoot": ".", "packages": [ { @@ -1988,6 +1988,11 @@ "t": "number", "d": "多列表单里本字段占几列(如整宽的多行备注);单列布局或窄屏下自动退回整行" }, + { + "n": "(formItem)visible", + "t": "Signal", + "d": "条件显示信号:为假时整项隐藏且不参与校验(未显示的字段不该拦住提交)" + }, { "n": "onReset", "t": "() => void", @@ -2020,7 +2025,8 @@ "formItem 返回 { el, validate, validateAsync } 句柄:validate 只跑同步规则(供 blur/input 即时反馈),validateAsync 逐条 await 供 form 聚合提交", "需要给字段加格式说明就传 hint:平时显示在控件下方,校验失败时自动让位给错误文案,同一位置不堆两行", "字段多的编辑页传 columns: 2 或 3 走多列栅格:列间距与窄屏堆叠沿用 grid,按钮区始终整行;单列表单不要传(默认 1)", - "多列表单里想整宽就传 span:formItem({ span: 2 }, textarea(...)) 会占满两列,窄屏单列时自动忽略跨列(否则会撑出横向滚动)" + "多列表单里想整宽就传 span:formItem({ span: 2 }, textarea(...)) 会占满两列,窄屏单列时自动忽略跨列(否则会撑出横向滚动)", + "字段要按另一个字段的值决定是否出现(选了「其他」才出现输入框),给 formItem 传 visible 信号:隐藏项自动清掉错误态并退出校验,不用自己在 items 数组里增删" ] }, { diff --git a/llms-full.txt b/llms-full.txt index ed3d81a..894cdf8 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -1,6 +1,6 @@ # @ui-arch 组件库 Agent 文档(无图形版) -> 自动生成于 2026-10-26T15:05:05.398Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 +> 自动生成于 2026-10-26T15:06:03.807Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 ## 快速上手 @@ -976,6 +976,7 @@ const open = signal(false); drawer({ title: '详情', open, width: 360, onClose: - (formItem)validateOn(默认 blur):'input' | 'blur' | 'submit' —— 校验时机;缺省 blur(输入时自动清已报错误) - (formItem)hint:string —— 控件下方辅助说明(格式提示等);报错时让位给错误文案 - (formItem)span:number —— 多列表单里本字段占几列(如整宽的多行备注);单列布局或窄屏下自动退回整行 +- (formItem)visible:Signal —— 条件显示信号:为假时整项隐藏且不参与校验(未显示的字段不该拦住提交) - onReset:() => void —— 重置按钮点击回调;组件不自行清空字段,由调用方重置信号;不传 resetText 不渲染按钮 - onError(回调):(count: number) => void —— 校验不通过时的回调,参数为不通字段数(适合埋点或顶部提示) - errorSummary:boolean —— 是否在表单顶部显示「有 N 项需要修改」汇总条;缺省 true,自带错误 UI 时传 false @@ -1002,6 +1003,7 @@ const name = signal(''); const f = form({ onSubmit: submit }, [formItem({ label: 12. 需要给字段加格式说明就传 hint:平时显示在控件下方,校验失败时自动让位给错误文案,同一位置不堆两行 13. 字段多的编辑页传 columns: 2 或 3 走多列栅格:列间距与窄屏堆叠沿用 grid,按钮区始终整行;单列表单不要传(默认 1) 14. 多列表单里想整宽就传 span:formItem({ span: 2 }, textarea(...)) 会占满两列,窄屏单列时自动忽略跨列(否则会撑出横向滚动) +15. 字段要按另一个字段的值决定是否出现(选了「其他」才出现输入框),给 formItem 传 visible 信号:隐藏项自动清掉错误态并退出校验,不用自己在 items 数组里增删 现场演示:apps/docs/demo.html#sec-formlab diff --git a/packages/skin/ui/src/form.ts b/packages/skin/ui/src/form.ts index 7401f20..73d735e 100644 --- a/packages/skin/ui/src/form.ts +++ b/packages/skin/ui/src/form.ts @@ -1,4 +1,4 @@ -import { h } from '@ui-arch/frame'; +import { effect, h } from '@ui-arch/frame'; import { button } from './button.js'; import { grid } from './grid.js'; import type { FormItemHandle, FormItemProps, FormProps, FormRule } from './types.js'; @@ -40,6 +40,8 @@ export function formItem(props: FormItemProps, control: HTMLElement): FormItemHa const label = h('label', { class: 'ua-form-label' }, props.label, props.required ? h('i', { class: 'ua-form-req' }, '*') : null); const el = h('div', { class: 'ua-form-item' }, label, h('div', { class: 'ua-form-control' }, control, hint, error)); if (props.span) el.style.gridColumn = `span ${props.span}`; // 多列布局里跨列;单列容器下由 CSS 还原为整行 + // 条件显示:隐藏时顺带清掉错误态,否则「看不见的红框」会拦住提交 + if (props.visible) effect(() => { el.hidden = !props.visible?.(); if (el.hidden) paint(null); }); let seq = 0; // 校验轮次:异步结论回来时若已有更新的一轮,丢弃旧结果(防乱序覆盖) /*** 错误态落点:控件根 + 内部原生控件,保证 select / checkbox 这类包裹式控件也能标红 ***/ @@ -58,6 +60,7 @@ export function formItem(props: FormItemProps, control: HTMLElement): FormItemHa /*** 同步校验:异步规则不结论,保证 blur / input 路径不被 Promise 拖慢 ***/ const validate = (): string | null => { + if (el.hidden) return null; // 隐藏项不参与校验:没显示的字段不该拦住提交 const value = props.value(); let msg: string | null = null; for (const rule of rules) { @@ -70,6 +73,7 @@ export function formItem(props: FormItemProps, control: HTMLElement): FormItemHa /*** 异步校验:按序 await 每条规则,结论按轮次取舍,过期结果不动 UI ***/ const validateAsync = async (): Promise => { + if (el.hidden) return null; // 隐藏项不参与异步校验,与同步版同一口径 seq += 1; const mine = seq; // 本轮编号 const value = props.value(); diff --git a/packages/skin/ui/src/types.ts b/packages/skin/ui/src/types.ts index 509d883..9631852 100644 --- a/packages/skin/ui/src/types.ts +++ b/packages/skin/ui/src/types.ts @@ -462,6 +462,7 @@ export interface FormItemProps { validateOn?: 'input' | 'blur' | 'submit'; // 校验时机;缺省 blur hint?: string; // 控件下方辅助说明(格式提示等);报错时让位给错误文案 span?: number; // 多列表单里本字段占几列(如整宽的多行文本);单列布局下无效 + visible?: Signal; // 条件显示信号:为假时整项隐藏且不参与校验(未显示的字段不该拦住提交) } /*** 表单字段句柄:form 聚合校验用 ***/ diff --git a/packages/skin/ui/ua.manifest.json b/packages/skin/ui/ua.manifest.json index 1ddf8cf..0f743b7 100644 --- a/packages/skin/ui/ua.manifest.json +++ b/packages/skin/ui/ua.manifest.json @@ -1859,6 +1859,11 @@ "t": "number", "d": "多列表单里本字段占几列(如整宽的多行备注);单列布局或窄屏下自动退回整行" }, + { + "n": "(formItem)visible", + "t": "Signal", + "d": "条件显示信号:为假时整项隐藏且不参与校验(未显示的字段不该拦住提交)" + }, { "n": "onReset", "t": "() => void", @@ -1891,7 +1896,8 @@ "formItem 返回 { el, validate, validateAsync } 句柄:validate 只跑同步规则(供 blur/input 即时反馈),validateAsync 逐条 await 供 form 聚合提交", "需要给字段加格式说明就传 hint:平时显示在控件下方,校验失败时自动让位给错误文案,同一位置不堆两行", "字段多的编辑页传 columns: 2 或 3 走多列栅格:列间距与窄屏堆叠沿用 grid,按钮区始终整行;单列表单不要传(默认 1)", - "多列表单里想整宽就传 span:formItem({ span: 2 }, textarea(...)) 会占满两列,窄屏单列时自动忽略跨列(否则会撑出横向滚动)" + "多列表单里想整宽就传 span:formItem({ span: 2 }, textarea(...)) 会占满两列,窄屏单列时自动忽略跨列(否则会撑出横向滚动)", + "字段要按另一个字段的值决定是否出现(选了「其他」才出现输入框),给 formItem 传 visible 信号:隐藏项自动清掉错误态并退出校验,不用自己在 items 数组里增删" ] }, {