diff --git a/llms-full.txt b/llms-full.txt index fbbb482..5b91107 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -3018,6 +3018,61 @@ pagination({ page, total: () => rows().length, pageSize: size() }); // 独立分 - **改页大小要回到第 1 页**:`pageSize` 变化时表格内部按内核语义回第 1 页,外部只需把 `size` 改掉,别在业务层再手动 `page(1)`(顺序错了会出现「先跳到 25 条的第 3 页再被推回第 1 页」的闪动)。 - **越界页码由内核收敛**:数据缩水后 `state` 里的页码会被回写成实际生效页,数据恢复也不会突然跳回旧页码——所以外部依赖这个信号做联动时不需要自己钳制。 - **每页条数下拉要给名字**:无可见 label 的场合(分页条、工具栏)传 `ariaLabel`,否则读屏只念出一句「10 条/页」而没有主语。 +## 配方 16:后台页骨架 + +```ts +layout( + { + header: h('div', { class: 'row' }, breadcrumb({ items: [{ label: '订单' }, { label: '列表' }] })), + sider: menu({ items: [{ key: 'overview', label: '概览' }, { key: 'orders', label: '订单' }] }), + footer: '© 2026 内部系统', + collapsible: true, // 页头左侧出现折叠开关 + sticky: true, // 长内容页让页头吸顶 + }, + card({ title: '本月订单' }, dataTable({ data: rows, columns })), +) +``` + +要点: +- 页头给 `breadcrumb`、侧栏给 `menu`、主体给 `card`:`layout` 只负责四区位置与页头吸顶,导航与内容各归其组件,别在 `layout` 上塞交互。 +- 折叠态想接到别处(例如只显示图标栏)就传 `collapsed` 信号读值;不给信号则内部自管,不必自己再 `signal(false)`。 +- 内容区自带滚动与统一细条,不要再套一层 `overflow: auto`——两层滚动容器会让吸顶与滚动条重复出现。 + +## 配方 17:表格刷新遮罩 + +```ts +const busy = signal(false); +const table = dataTable({ data: rows, columns, page, selectable: true }); + +const refresh = async () => { + busy(true); + try { await reload(); } finally { busy(false); } // 遮罩只跟 busy 走,异常也要收 +}; + +loading({ active: busy, text: '正在刷新订单', minHeight: 240 }, table); +``` + +要点: +- 遮罩包住表格而不是整页:用户看得见「哪一块在等」,其余区域仍可操作。 +- `loading` 默认延迟 120ms 出场——接口快于此不闪;别为了「一定看见」传 `delay: 0`,那会让每次快请求都闪一下。 +- 刷新期间不要把 `data` 换成空数组占位:`loading` 已负责等待感,清空数据会让页码与选中态无谓地收敛一次。 + +## 配方 18:变更审阅面板 + +```ts +const panel = h('div', { class: 'review' }, + tag({ label: '待审阅', variant: 'warning' }), + codeBlock({ code: before, title: '旧版本', lang: 'ts', maxHeight: 220 }), + diffView({ before, after }), + copyButton({ text: after, label: '复制新版本' }), +); +``` + +要点: +- 三段各司其职:`codeBlock` 看全文(带行号与复制)、`diffView` 只看变化、`copyButton` 把新版本带走——不要用 `diffView` 代替全文展示。 +- `codeBlock` 的行号不参与复制,`copyButton` 直接读原文,所以「复制出来的代码」永远干净。 +- 差异行多了给 `diffView` 外层限定高度(或放进抽屉),否则长差异会把审阅按钮挤出视口。 + ## 通用约定 - 状态一律放信号(`signal` / `computed`),组件只读写信号,不持有业务数据副本。 diff --git a/llms.txt b/llms.txt index 529f302..839a35f 100644 --- a/llms.txt +++ b/llms.txt @@ -179,3 +179,6 @@ - 配方 13:预约时点(日期 + 时间两段拼装)(5 条要点) - 配方 14:标签筛选条 → 表格联动(5 条要点) - 配方 15:表格分页与独立分页器联动(每页条数 + 受控页码)(4 条要点) +- 配方 16:后台页骨架(3 条要点) +- 配方 17:表格刷新遮罩(3 条要点) +- 配方 18:变更审阅面板(3 条要点) diff --git a/packages/tools/cli/recipes.md b/packages/tools/cli/recipes.md index 5b9fbc6..065e64e 100644 --- a/packages/tools/cli/recipes.md +++ b/packages/tools/cli/recipes.md @@ -352,6 +352,61 @@ pagination({ page, total: () => rows().length, pageSize: size() }); // 独立分 - **改页大小要回到第 1 页**:`pageSize` 变化时表格内部按内核语义回第 1 页,外部只需把 `size` 改掉,别在业务层再手动 `page(1)`(顺序错了会出现「先跳到 25 条的第 3 页再被推回第 1 页」的闪动)。 - **越界页码由内核收敛**:数据缩水后 `state` 里的页码会被回写成实际生效页,数据恢复也不会突然跳回旧页码——所以外部依赖这个信号做联动时不需要自己钳制。 - **每页条数下拉要给名字**:无可见 label 的场合(分页条、工具栏)传 `ariaLabel`,否则读屏只念出一句「10 条/页」而没有主语。 +## 配方 16:后台页骨架 + +```ts +layout( + { + header: h('div', { class: 'row' }, breadcrumb({ items: [{ label: '订单' }, { label: '列表' }] })), + sider: menu({ items: [{ key: 'overview', label: '概览' }, { key: 'orders', label: '订单' }] }), + footer: '© 2026 内部系统', + collapsible: true, // 页头左侧出现折叠开关 + sticky: true, // 长内容页让页头吸顶 + }, + card({ title: '本月订单' }, dataTable({ data: rows, columns })), +) +``` + +要点: +- 页头给 `breadcrumb`、侧栏给 `menu`、主体给 `card`:`layout` 只负责四区位置与页头吸顶,导航与内容各归其组件,别在 `layout` 上塞交互。 +- 折叠态想接到别处(例如只显示图标栏)就传 `collapsed` 信号读值;不给信号则内部自管,不必自己再 `signal(false)`。 +- 内容区自带滚动与统一细条,不要再套一层 `overflow: auto`——两层滚动容器会让吸顶与滚动条重复出现。 + +## 配方 17:表格刷新遮罩 + +```ts +const busy = signal(false); +const table = dataTable({ data: rows, columns, page, selectable: true }); + +const refresh = async () => { + busy(true); + try { await reload(); } finally { busy(false); } // 遮罩只跟 busy 走,异常也要收 +}; + +loading({ active: busy, text: '正在刷新订单', minHeight: 240 }, table); +``` + +要点: +- 遮罩包住表格而不是整页:用户看得见「哪一块在等」,其余区域仍可操作。 +- `loading` 默认延迟 120ms 出场——接口快于此不闪;别为了「一定看见」传 `delay: 0`,那会让每次快请求都闪一下。 +- 刷新期间不要把 `data` 换成空数组占位:`loading` 已负责等待感,清空数据会让页码与选中态无谓地收敛一次。 + +## 配方 18:变更审阅面板 + +```ts +const panel = h('div', { class: 'review' }, + tag({ label: '待审阅', variant: 'warning' }), + codeBlock({ code: before, title: '旧版本', lang: 'ts', maxHeight: 220 }), + diffView({ before, after }), + copyButton({ text: after, label: '复制新版本' }), +); +``` + +要点: +- 三段各司其职:`codeBlock` 看全文(带行号与复制)、`diffView` 只看变化、`copyButton` 把新版本带走——不要用 `diffView` 代替全文展示。 +- `codeBlock` 的行号不参与复制,`copyButton` 直接读原文,所以「复制出来的代码」永远干净。 +- 差异行多了给 `diffView` 外层限定高度(或放进抽屉),否则长差异会把审阅按钮挤出视口。 + ## 通用约定 - 状态一律放信号(`signal` / `computed`),组件只读写信号,不持有业务数据副本。