From 23873355481616c8bdeb144742359583de55f345 Mon Sep 17 00:00:00 2001 From: HIsheR Date: Mon, 26 Oct 2026 15:44:44 +0800 Subject: [PATCH] =?UTF-8?q?iter(g147):=20=E8=A1=A5=E4=B8=89=E6=9D=A1?= =?UTF-8?q?=E7=BB=84=E5=90=88=E9=85=8D=E6=96=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .ua/backlog.json | 8 +++++ llms-full.txt | 58 +++++++++++++++++++++++++++++++++++ packages/tools/cli/recipes.md | 58 +++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) diff --git a/.ua/backlog.json b/.ua/backlog.json index 5213468..c8c5888 100644 --- a/.ua/backlog.json +++ b/.ua/backlog.json @@ -1532,6 +1532,14 @@ "acceptance": "progress 新增 type=line|circle,环形走 createElementNS 的 SVG 双圆 + dashoffset,中间显示百分比、aria-label 拼名称与数值,variant 换弧色;linear 行为不变;文档与演示同步;npm run check 全绿", "notes": "自补:既有组件可用性细节(坑:h() 用 createElement 造不出可渲染 SVG,必须 createElementNS)", "status": "done" + }, + { + "id": "g147", + "title": "补三条组合配方(筛选栏/评论/详情页)", + "motivation": "本轮新增的 treeSelect、datePicker range、mentions、avatarGroup、typography、grid 只有参数表,Agent 拿到组件却不知道该怎么拼;recipes.md 还停在 6 条", + "acceptance": "recipes.md 补配方 7-9(筛选栏、评论输入、详情页排版),只消费对外 API,随 npm run docs 进入 llms-full.txt;npm run check 全绿", + "notes": "自补:Agent 文档完善", + "status": "open" } ] } diff --git a/llms-full.txt b/llms-full.txt index fa87d43..c41a577 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -2229,6 +2229,64 @@ affix({ position: 'bottom', offset: 0 }, h('div', { class: 'row' }, - 提交期间用同一个 `saving` 信号锁三处:按钮 `disabled`、开关 `loading`(转圈 + aria-busy)、业务请求出口,防重复提交与中途改状态。 - 长度约束一处写够:`textField` 的 `maxCount` 设原生上限并实时计数,`formItem` 的 `rules: [{ max }]` 只做提交兜底,两处数字保持一致。 +## 配方 7:筛选栏(层级归属 + 日期区间) + +```ts +const dept = signal(''); +const from = signal(''); +const to = signal(''); +space({ size: 'sm', wrap: true }, + treeSelect({ nodes: orgTree, value: dept, searchable: true, placeholder: '归属部门' }), + datePicker({ range: true, value: from, end: to, onRangeChange: (a, b) => reload(a, b) }), + button({ label: '重置', variant: 'ghost', onClick: () => { dept(''); from(''); to(''); } }), +); +``` + +要点: +- 层级用 `treeSelect`(允许选中间节点、可搜索),只有「必须逐级选到叶子」时才用 `cascader`。 +- 日期区间传 `range: true`:组件内部保证先后顺序(用户点早了会自动交换),`onRangeChange` 拿到的就是排好序的两端。 +- 重置把三个信号清空即可:组件都是受控的,值一变界面自己回到占位态。 + +## 配方 8:评论输入(@ 提及 + 参与人头像组) + +```ts +const text = signal(''); +const members = [{ name: 'zhangsan', label: '张三', description: '前端', keywords: ['zs'] }]; +card({ title: '评审讨论', extra: avatarGroup({ items: members, max: 4 }) }, + mentions({ items: members, value: text, placeholder: '输入 @ 叫人评审…', onSelect: (m) => toast.info(`已提及 ${m.label}`) }), + space({ size: 'sm', justify: 'end', block: true }, + button({ label: '发送', onClick: () => { toast.success('已发送'); text(''); } })), +); +``` + +要点: +- 参与人头像用 `avatarGroup`:超出 `max` 自动折叠成 `+N`,整组 `title` 列出全部姓名,比并排 `avatar` 省一半横向空间。 +- `mentions` 的 `value` 是受控信号:发送后 `text('')` 即清空,不要在组件外部再改 textarea。 +- 候选人来源由调用方决定(`items` 可随 `onInput` 远程拉取后重建),组件不做远程搜索。 + +## 配方 9:详情页排版(栅格 + 排版文本 + 描述列表) + +```ts +grid({ columns: 2, gutter: 'lg' }, + card({ title: '基本信息' }, + typography({ variant: 'title', level: 4, content: '订单 RB-2048' }), + descriptions({ column: 2, items: [ + { label: '金额', value: '¥1,280.00' }, + { label: '状态', value: tag({ label: '待发货', variant: 'warning' }) }, + ] }), + ), + card({ title: '备注' }, + typography({ variant: 'paragraph', ellipsis: 3, content: longNote }), + typography({ content: 'RB-2048-0917', code: true, copyable: true }), + ), +); +``` + +要点: +- 页面骨架用 `grid`(`columns` 固定列 / `min` 走 auto-fit),窄屏自动单列,不要在调用方写媒体查询。 +- 标题一律 `typography({ variant: 'title', level })` 出语义 `h1-h5`;正文长文本用 `ellipsis` 截断并自动挂 `title` 看全文。 +- 只读字段用 `descriptions`(不要用 `form`):`form` 承载输入与校验,`descriptions` 只负责 label:value 对齐。 + ## 通用约定 - 状态一律放信号(`signal` / `computed`),组件只读写信号,不持有业务数据副本。 diff --git a/packages/tools/cli/recipes.md b/packages/tools/cli/recipes.md index 09d6fd3..d92af50 100644 --- a/packages/tools/cli/recipes.md +++ b/packages/tools/cli/recipes.md @@ -126,6 +126,64 @@ affix({ position: 'bottom', offset: 0 }, h('div', { class: 'row' }, - 提交期间用同一个 `saving` 信号锁三处:按钮 `disabled`、开关 `loading`(转圈 + aria-busy)、业务请求出口,防重复提交与中途改状态。 - 长度约束一处写够:`textField` 的 `maxCount` 设原生上限并实时计数,`formItem` 的 `rules: [{ max }]` 只做提交兜底,两处数字保持一致。 +## 配方 7:筛选栏(层级归属 + 日期区间) + +```ts +const dept = signal(''); +const from = signal(''); +const to = signal(''); +space({ size: 'sm', wrap: true }, + treeSelect({ nodes: orgTree, value: dept, searchable: true, placeholder: '归属部门' }), + datePicker({ range: true, value: from, end: to, onRangeChange: (a, b) => reload(a, b) }), + button({ label: '重置', variant: 'ghost', onClick: () => { dept(''); from(''); to(''); } }), +); +``` + +要点: +- 层级用 `treeSelect`(允许选中间节点、可搜索),只有「必须逐级选到叶子」时才用 `cascader`。 +- 日期区间传 `range: true`:组件内部保证先后顺序(用户点早了会自动交换),`onRangeChange` 拿到的就是排好序的两端。 +- 重置把三个信号清空即可:组件都是受控的,值一变界面自己回到占位态。 + +## 配方 8:评论输入(@ 提及 + 参与人头像组) + +```ts +const text = signal(''); +const members = [{ name: 'zhangsan', label: '张三', description: '前端', keywords: ['zs'] }]; +card({ title: '评审讨论', extra: avatarGroup({ items: members, max: 4 }) }, + mentions({ items: members, value: text, placeholder: '输入 @ 叫人评审…', onSelect: (m) => toast.info(`已提及 ${m.label}`) }), + space({ size: 'sm', justify: 'end', block: true }, + button({ label: '发送', onClick: () => { toast.success('已发送'); text(''); } })), +); +``` + +要点: +- 参与人头像用 `avatarGroup`:超出 `max` 自动折叠成 `+N`,整组 `title` 列出全部姓名,比并排 `avatar` 省一半横向空间。 +- `mentions` 的 `value` 是受控信号:发送后 `text('')` 即清空,不要在组件外部再改 textarea。 +- 候选人来源由调用方决定(`items` 可随 `onInput` 远程拉取后重建),组件不做远程搜索。 + +## 配方 9:详情页排版(栅格 + 排版文本 + 描述列表) + +```ts +grid({ columns: 2, gutter: 'lg' }, + card({ title: '基本信息' }, + typography({ variant: 'title', level: 4, content: '订单 RB-2048' }), + descriptions({ column: 2, items: [ + { label: '金额', value: '¥1,280.00' }, + { label: '状态', value: tag({ label: '待发货', variant: 'warning' }) }, + ] }), + ), + card({ title: '备注' }, + typography({ variant: 'paragraph', ellipsis: 3, content: longNote }), + typography({ content: 'RB-2048-0917', code: true, copyable: true }), + ), +); +``` + +要点: +- 页面骨架用 `grid`(`columns` 固定列 / `min` 走 auto-fit),窄屏自动单列,不要在调用方写媒体查询。 +- 标题一律 `typography({ variant: 'title', level })` 出语义 `h1-h5`;正文长文本用 `ellipsis` 截断并自动挂 `title` 看全文。 +- 只读字段用 `descriptions`(不要用 `form`):`form` 承载输入与校验,`descriptions` 只负责 label:value 对齐。 + ## 通用约定 - 状态一律放信号(`signal` / `computed`),组件只读写信号,不持有业务数据副本。