From 0fb919893fb3a271fa89fa2988506499b739a86e Mon Sep 17 00:00:00 2001 From: HIsheR Date: Mon, 26 Oct 2026 19:55:38 +0800 Subject: [PATCH] =?UTF-8?q?iter(g215):=20=E6=96=B0=E5=A2=9E=E6=97=A5?= =?UTF-8?q?=E6=9C=9F=E5=8A=A0=E6=97=B6=E9=97=B4=E7=BB=84=E5=90=88=E9=85=8D?= =?UTF-8?q?=E6=96=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- llms-full.txt | 34 ++++++++++++++++++++++++++++++++++ packages/tools/cli/recipes.md | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/llms-full.txt b/llms-full.txt index c9bf4fb..6a7a401 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -2566,6 +2566,40 @@ document.body.append(cmdk.el); // 面板是 fixed + 遮罩,挂 body 最省事 - 一页只留一个实例用缺省 `hotkey`(⌘K / Ctrl+K),其余传 `hotkey: false` 自己绑,否则一次按键会同时开两个面板。 - 命令集随权限变化时**重建实例**(`items` 是创建时快照),不要往原数组里 push。 +## 配方 13:预约时点(日期 + 时间两段拼装) + +```ts +import { computed, signal } from '@ui-arch/frame'; +import { datePicker, form, formItem, timePicker, toast } from '@ui-arch/ui'; + +const day = signal(''); // 日期段:YYYY-MM-DD +const clock = signal('09:00'); // 时间段:HH:mm(给初值,用户只需要改自己想改的那半) +const at = computed(() => (day() ? `${day()} ${clock()}` : '')); // 拼装交给业务层:两个组件各管一段,互不知道对方 + +const dateField = formItem( + { label: '预约日期', value: day, required: true }, + datePicker({ value: day, min: new Date().toISOString().slice(0, 10) }), // 早于今天的日期直接置灰,比事后校验更省事 +); +const timeField = formItem( + { label: '预约时间', value: clock, required: true, hint: '每 15 分钟一档' }, + timePicker({ value: clock, minuteStep: 15 }), // 步长只影响分列,时列始终 24 档 +); + +form({ + layout: 'horizontal', + submitText: '确认预约', + items: [dateField, timeField], + onSubmit: () => toast.success(`已预约 ${at()}`), // 两段都非空才会走到这里:required 已经拦住半截状态 +}); +``` + +要点: +- **两段各管一段**:`datePicker` 只写 `YYYY-MM-DD`、`timePicker` 只写 `HH:mm`,拼成完整时点交给业务 `computed`——不要试图让某个组件同时产出日期与时间,否则一半值缺失时格式全靠猜。 +- **时间给初值**:`clock` 预置 `09:00` 这类合理默认,用户多数只想改小时;日期保持空值,避免「默认今天」被误提交。 +- **约束优先于校验**:日期上限下限用 `datePicker` 的 `min` / `max` 置灰,时间粒度用 `minuteStep` 收窄,`required` 只兜底空值——能点不出来的选项比报错文案更友好。 +- **半截状态别提交**:`form` 的 `required` 依赖各自 `value` 信号,日期没选时提交会被拦下并定位到该字段;不要自己写 `if (!day()) return` 之类的旁路判断。 +- 需要区间就用 `datePicker({ range: true })` + 两个 `timePicker`(起 / 止),拼装时各自独立,别指望一个信号同时表达两端。 + ## 通用约定 - 状态一律放信号(`signal` / `computed`),组件只读写信号,不持有业务数据副本。 diff --git a/packages/tools/cli/recipes.md b/packages/tools/cli/recipes.md index dbbc9ae..46062d0 100644 --- a/packages/tools/cli/recipes.md +++ b/packages/tools/cli/recipes.md @@ -259,6 +259,40 @@ document.body.append(cmdk.el); // 面板是 fixed + 遮罩,挂 body 最省事 - 一页只留一个实例用缺省 `hotkey`(⌘K / Ctrl+K),其余传 `hotkey: false` 自己绑,否则一次按键会同时开两个面板。 - 命令集随权限变化时**重建实例**(`items` 是创建时快照),不要往原数组里 push。 +## 配方 13:预约时点(日期 + 时间两段拼装) + +```ts +import { computed, signal } from '@ui-arch/frame'; +import { datePicker, form, formItem, timePicker, toast } from '@ui-arch/ui'; + +const day = signal(''); // 日期段:YYYY-MM-DD +const clock = signal('09:00'); // 时间段:HH:mm(给初值,用户只需要改自己想改的那半) +const at = computed(() => (day() ? `${day()} ${clock()}` : '')); // 拼装交给业务层:两个组件各管一段,互不知道对方 + +const dateField = formItem( + { label: '预约日期', value: day, required: true }, + datePicker({ value: day, min: new Date().toISOString().slice(0, 10) }), // 早于今天的日期直接置灰,比事后校验更省事 +); +const timeField = formItem( + { label: '预约时间', value: clock, required: true, hint: '每 15 分钟一档' }, + timePicker({ value: clock, minuteStep: 15 }), // 步长只影响分列,时列始终 24 档 +); + +form({ + layout: 'horizontal', + submitText: '确认预约', + items: [dateField, timeField], + onSubmit: () => toast.success(`已预约 ${at()}`), // 两段都非空才会走到这里:required 已经拦住半截状态 +}); +``` + +要点: +- **两段各管一段**:`datePicker` 只写 `YYYY-MM-DD`、`timePicker` 只写 `HH:mm`,拼成完整时点交给业务 `computed`——不要试图让某个组件同时产出日期与时间,否则一半值缺失时格式全靠猜。 +- **时间给初值**:`clock` 预置 `09:00` 这类合理默认,用户多数只想改小时;日期保持空值,避免「默认今天」被误提交。 +- **约束优先于校验**:日期上限下限用 `datePicker` 的 `min` / `max` 置灰,时间粒度用 `minuteStep` 收窄,`required` 只兜底空值——能点不出来的选项比报错文案更友好。 +- **半截状态别提交**:`form` 的 `required` 依赖各自 `value` 信号,日期没选时提交会被拦下并定位到该字段;不要自己写 `if (!day()) return` 之类的旁路判断。 +- 需要区间就用 `datePicker({ range: true })` + 两个 `timePicker`(起 / 止),拼装时各自独立,别指望一个信号同时表达两端。 + ## 通用约定 - 状态一律放信号(`signal` / `computed`),组件只读写信号,不持有业务数据副本。