iter(g36): 新增 result 结果页组件

This commit is contained in:
HIsheR
2026-10-26 11:47:48 +08:00
parent f1703b3e68
commit 8ac71c4efd
13 changed files with 195 additions and 9 deletions
+8
View File
@@ -644,6 +644,14 @@
"acceptance": "notification({ title, description, variant, duration, closable, action }) 右下角堆叠(与 toast 分区)、超出 3 条挤掉最早、返回 { el, close }、duration 0 常驻;组件数 42→43 三处计数同步;npm run check 全绿", "acceptance": "notification({ title, description, variant, duration, closable, action }) 右下角堆叠(与 toast 分区)、超出 3 条挤掉最早、返回 { el, close }、duration 0 常驻;组件数 42→43 三处计数同步;npm run check 全绿",
"status": "done", "status": "done",
"notes": "自补:组件补充;与 toast 分区避免视觉冲突" "notes": "自补:组件补充;与 toast 分区避免视觉冲突"
},
{
"id": "g36",
"title": "新增 result 结果页组件",
"motivation": "提交成功/校验失败/权限不足这类终态页每次手写图标+标题+按钮,语义色和留白都不统一",
"acceptance": "result({ status, title, description, extra }) 四档语义色 + 居中终态布局 + role=\"status\";组件数 43→44 三处计数同步;npm run check 全绿",
"status": "open",
"notes": "自补:组件补充"
} }
] ]
} }
+38 -2
View File
@@ -1,6 +1,6 @@
{ {
"$schema": "ui-arch-registry-index/0.1", "$schema": "ui-arch-registry-index/0.1",
"generatedAt": "2026-10-26T03:46:32.583Z", "generatedAt": "2026-10-26T03:47:28.088Z",
"repoRoot": ".", "repoRoot": ".",
"packages": [ "packages": [
{ {
@@ -186,7 +186,8 @@
"carousel(props):轮播,items 横排位移,指示点/箭头/←→ 键切换,autoplay 毫秒自动前进且悬停暂停,index 信号可外部受控", "carousel(props):轮播,items 横排位移,指示点/箭头/←→ 键切换,autoplay 毫秒自动前进且悬停暂停,index 信号可外部受控",
"tree(props):树形,递归节点 + 箭头展开/收起 + 点选节点,键盘 Enter 选中、→ 展开、← 收起,禁用节点不响应", "tree(props):树形,递归节点 + 箭头展开/收起 + 点选节点,键盘 Enter 选中、→ 展开、← 收起,禁用节点不响应",
"upload(props):文件选择,点击或拖拽入列,清单可逐个移除,onChange 回传文件数组(不内置上传请求)", "upload(props):文件选择,点击或拖拽入列,清单可逐个移除,onChange 回传文件数组(不内置上传请求)",
"notification(props):右下角通知卡片(标题 + 描述 + 操作区),返回 { el, close } 句柄,缺省常驻需手动关闭" "notification(props):右下角通知卡片(标题 + 描述 + 操作区),返回 { el, close } 句柄,缺省常驻需手动关闭",
"result(props):结果页,status 四档语义色 + 标题 + 说明 + 操作区,用于提交完成/校验失败等终态"
], ],
"keyTypes": [ "keyTypes": [
"ButtonProps", "ButtonProps",
@@ -1993,6 +1994,41 @@
"action 放操作区(常见为按钮);variant 决定左侧条与圆点语义色", "action 放操作区(常见为按钮);variant 决定左侧条与圆点语义色",
"与 toast 的分工:toast 右上角轻量瞬时,notification 右下角可长读、可操作" "与 toast 的分工:toast 右上角轻量瞬时,notification 右下角可长读、可操作"
] ]
},
{
"id": "result",
"title": "结果页 Result",
"demo": "sec-result",
"props": [
{
"n": "status",
"t": "'success' | 'warning' | 'danger' | 'info'",
"d": "终态语义色(图标底色);缺省 info"
},
{
"n": "title",
"t": "string",
"r": 1,
"d": "主标题"
},
{
"n": "description",
"t": "string",
"d": "补充说明;缺省不渲染"
},
{
"n": "extra",
"t": "unknown",
"d": "操作区内容(常见为主次按钮);缺省不渲染"
}
],
"example": "result({ status: 'success', title: '提交成功', description: '工单 #2049 已受理', extra: button({ label: '查看工单', variant: 'primary', onClick: () => go() }) })",
"steps": [
"status 决定图标底色(success 绿 / warning 黄 / danger 红 / info 蓝),整体居中排布",
"title 必填;description 用于说明原因或下一步,超过一行自动居中换行",
"extra 放操作区,常见为主按钮 + 幽灵按钮;不传则不渲染",
"组件自带 role=\"status\",插入页面后读屏会播报终态文案"
]
} }
] ]
}, },
+1 -1
View File
@@ -21,7 +21,7 @@
- `packages/core/table-core`(@ui-arch/table-core):Headless 表格逻辑内核 - `packages/core/table-core`(@ui-arch/table-core):Headless 表格逻辑内核
- `packages/core/frame`(@ui-arch/frame):signal + hyperscript 微框架 - `packages/core/frame`(@ui-arch/frame):signal + hyperscript 微框架
- `packages/skin/ui`(@ui-arch/ui):43 个 DOM 组件(表单 / 反馈 / 浮层 / 导航 / 表格),样式只消费令牌 - `packages/skin/ui`(@ui-arch/ui):44 个 DOM 组件(表单 / 反馈 / 浮层 / 导航 / 表格),样式只消费令牌
- `packages/design/tokens`(@ui-arch/tokens):设计令牌 - `packages/design/tokens`(@ui-arch/tokens):设计令牌
- `packages/tools/cli`(@ui-arch/cli):`ua` 命令行 + MCP 注册表服务(private) - `packages/tools/cli`(@ui-arch/cli):`ua` 命令行 + MCP 注册表服务(private)
- `apps/demo`(@ui-arch/demo):交互演示,产物 apps/demo/dist/demo.html - `apps/demo`(@ui-arch/demo):交互演示,产物 apps/demo/dist/demo.html
+1 -1
View File
@@ -34,7 +34,7 @@ ui-arch-mvp/
│ │ ├── table-core/ # 表格状态内核 │ │ ├── table-core/ # 表格状态内核
│ │ └── frame/ # 信号 + hyperscript 微框架 │ │ └── frame/ # 信号 + hyperscript 微框架
│ ├── skin/ # 皮肤层(DOM 组件,可发布) │ ├── skin/ # 皮肤层(DOM 组件,可发布)
│ │ └── ui/ # 43 个组件 + ui.css │ │ └── ui/ # 44 个组件 + ui.css
│ ├── design/ # 资产层(可发布) │ ├── design/ # 资产层(可发布)
│ │ └── tokens/ # --ua-* 设计令牌 │ │ └── tokens/ # --ua-* 设计令牌
│ └── tools/ # 工程层(private,不发布) │ └── tools/ # 工程层(private,不发布)
+3 -3
View File
@@ -11,10 +11,10 @@ npm run demo # 打开演示:apps/demo/dist/demo.html
npm run docs # 生成人类文档站 apps/docs/index.html + Agent 全量文档 llms-full.txt npm run docs # 生成人类文档站 apps/docs/index.html + Agent 全量文档 llms-full.txt
``` ```
## 组件(共 43 个) ## 组件(共 44 个)
<!-- ua:components --> <!-- ua:components -->
accordion · alert · avatar · badge · breadcrumb · button · carousel · card · checkbox · dataTable · descriptions · divider · drawer · empty · form · image · inputNumber · list · menu · modal · notification · pagination · popover · progress · radioGroup · rate · segmented · select · skeleton · slider · spinner · statistic · stepper · switchButton · tabs · tag · textField · textarea · timeline · toast · tooltip · tree · upload accordion · alert · avatar · badge · breadcrumb · button · carousel · card · checkbox · dataTable · descriptions · divider · drawer · empty · form · image · inputNumber · list · menu · modal · notification · pagination · popover · progress · radioGroup · rate · result · segmented · select · skeleton · slider · spinner · statistic · stepper · switchButton · tabs · tag · textField · textarea · timeline · toast · tooltip · tree · upload
<!-- /ua:components --> <!-- /ua:components -->
分组:表单(button / textField / inputNumber / textarea / checkbox / switchButton / select / radioGroup / slider / rate / segmented / form / formItem)、反馈(alert / toast / spinner / progress / skeleton / badge / empty / statistic)、浮层(tooltip / popover / modal / drawer / menu)、导航(tabs / breadcrumb / pagination / accordion / stepper)、数据(dataTable / descriptions / tag / avatar / card)、其他(divider / timeline)。 分组:表单(button / textField / inputNumber / textarea / checkbox / switchButton / select / radioGroup / slider / rate / segmented / form / formItem)、反馈(alert / toast / spinner / progress / skeleton / badge / empty / statistic)、浮层(tooltip / popover / modal / drawer / menu)、导航(tabs / breadcrumb / pagination / accordion / stepper)、数据(dataTable / descriptions / tag / avatar / card)、其他(divider / timeline)。
@@ -25,7 +25,7 @@ accordion · alert · avatar · badge · breadcrumb · button · carousel · car
|---|---| |---|---|
| `packages/core/frame` | @ui-arch/frame:signal / computed / effect + hyperscript(无虚拟 DOM) | | `packages/core/frame` | @ui-arch/frame:signal / computed / effect + hyperscript(无虚拟 DOM) |
| `packages/core/table-core` | @ui-arch/table-core:headless 表格(filter → sort → paginate 派生管线) | | `packages/core/table-core` | @ui-arch/table-core:headless 表格(filter → sort → paginate 派生管线) |
| `packages/skin/ui` | @ui-arch/ui:43 个 DOM 组件 + ui.css(只消费 `--ua-*` 令牌) | | `packages/skin/ui` | @ui-arch/ui:44 个 DOM 组件 + ui.css(只消费 `--ua-*` 令牌) |
| `packages/design/tokens` | @ui-arch/tokens:设计令牌(暗色只换值不换名) | | `packages/design/tokens` | @ui-arch/tokens:设计令牌(暗色只换值不换名) |
| `packages/tools/cli` | @ui-arch/cli:`ua` 命令行与 stdio MCP server | | `packages/tools/cli` | @ui-arch/cli:`ua` 命令行与 stdio MCP server |
| `apps/demo` | 交互演示(esbuild 打包成单文件) | | `apps/demo` | 交互演示(esbuild 打包成单文件) |
+12
View File
@@ -29,6 +29,7 @@ import {
carousel, carousel,
tree, tree,
notification, notification,
result,
upload, upload,
menu, menu,
modal, modal,
@@ -671,6 +672,17 @@ const content = h(
button({ label: '错误(可关)', variant: 'danger', onClick: () => notification({ title: '保存失败', description: '服务端返回 500,请稍后重试', variant: 'danger' }) }), button({ label: '错误(可关)', variant: 'danger', onClick: () => notification({ title: '保存失败', description: '服务端返回 500,请稍后重试', variant: 'danger' }) }),
), ),
), ),
section(
'sec-result',
'结果页',
'result:终态页(成功 / 警告 / 失败 / 中性),状态符号 + 标题 + 说明 + 操作区,适合提交完成、权限不足等场景。',
h(
'div',
{ class: 'row' },
result({ status: 'success', title: '提交成功', description: '报销单 RB-2049 已进入财务复核,预计 2 个工作日内出结果。', extra: h('div', { class: 'row' }, button({ label: '查看单据', variant: 'primary', onClick: () => toast.success('打开单据') }), button({ label: '继续提交', variant: 'ghost', onClick: () => toast.info('已新建草稿') })) }),
result({ status: 'danger', title: '校验未通过', description: '发票金额与报销金额不一致,请核对后重新提交。' }),
),
),
section( section(
'sec-menu', 'sec-menu',
'下拉菜单', '下拉菜单',
+26 -1
View File
@@ -1,6 +1,6 @@
# @ui-arch 组件库 Agent 文档(无图形版) # @ui-arch 组件库 Agent 文档(无图形版)
> 自动生成于 2026-10-26T03:46:32.583Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 自动生成于 2026-10-26T03:47:28.088Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。
> 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。
## 快速上手 ## 快速上手
@@ -1142,6 +1142,30 @@ const { close } = notification({ title: '导出完成', description: 'report.csv
现场演示:apps/docs/demo.html#sec-notification 现场演示:apps/docs/demo.html#sec-notification
### result — 结果页 Result
参数:
- status:'success' | 'warning' | 'danger' | 'info' —— 终态语义色(图标底色);缺省 info
- title(必填):string —— 主标题
- description:string —— 补充说明;缺省不渲染
- extra:unknown —— 操作区内容(常见为主次按钮);缺省不渲染
示例:
```
result({ status: 'success', title: '提交成功', description: '工单 #2049 已受理', extra: button({ label: '查看工单', variant: 'primary', onClick: () => go() }) })
```
手把手:
1. status 决定图标底色(success 绿 / warning 黄 / danger 红 / info 蓝),整体居中排布
2. title 必填;description 用于说明原因或下一步,超过一行自动居中换行
3. extra 放操作区,常见为主按钮 + 幽灵按钮;不传则不渲染
4. 组件自带 role="status",插入页面后读屏会播报终态文案
现场演示:apps/docs/demo.html#sec-result
API 速览: API 速览:
- button(props):按钮,variant = primary | ghost | danger,disabled 支持布尔或信号禁用 - button(props):按钮,variant = primary | ghost | danger,disabled 支持布尔或信号禁用
@@ -1189,6 +1213,7 @@ API 速览:
- tree(props):树形,递归节点 + 箭头展开/收起 + 点选节点,键盘 Enter 选中、→ 展开、← 收起,禁用节点不响应 - tree(props):树形,递归节点 + 箭头展开/收起 + 点选节点,键盘 Enter 选中、→ 展开、← 收起,禁用节点不响应
- upload(props):文件选择,点击或拖拽入列,清单可逐个移除,onChange 回传文件数组(不内置上传请求) - upload(props):文件选择,点击或拖拽入列,清单可逐个移除,onChange 回传文件数组(不内置上传请求)
- notification(props):右下角通知卡片(标题 + 描述 + 操作区),返回 { el, close } 句柄,缺省常驻需手动关闭 - notification(props):右下角通知卡片(标题 + 描述 + 操作区),返回 { el, close } 句柄,缺省常驻需手动关闭
- result(props):结果页,status 四档语义色 + 标题 + 说明 + 操作区,用于提交完成/校验失败等终态
一行用法: 一行用法:
+1
View File
@@ -92,6 +92,7 @@
- tree(props):树形,递归节点 + 箭头展开/收起 + 点选节点,键盘 Enter 选中、→ 展开、← 收起,禁用节点不响应 - tree(props):树形,递归节点 + 箭头展开/收起 + 点选节点,键盘 Enter 选中、→ 展开、← 收起,禁用节点不响应
- upload(props):文件选择,点击或拖拽入列,清单可逐个移除,onChange 回传文件数组(不内置上传请求) - upload(props):文件选择,点击或拖拽入列,清单可逐个移除,onChange 回传文件数组(不内置上传请求)
- notification(props):右下角通知卡片(标题 + 描述 + 操作区),返回 { el, close } 句柄,缺省常驻需手动关闭 - notification(props):右下角通知卡片(标题 + 描述 + 操作区),返回 { el, close } 句柄,缺省常驻需手动关闭
- result(props):结果页,status 四档语义色 + 标题 + 说明 + 操作区,用于提交完成/校验失败等终态
- 用法: `const checked = signal(false); checkbox({ label: '同意', checked }); const open = signal(false); modal({ title: '确认', open }, '内容')` - 用法: `const checked = signal(false); checkbox({ label: '同意', checked }); const open = signal(false); modal({ title: '确认', open }, '内容')`
- 约定: 皮肤不持有业务状态,一律委托 headless 内核或调用方信号 - 约定: 皮肤不持有业务状态,一律委托 headless 内核或调用方信号
- 约定: 表单类组件统一约定:*Props.value/checked/active 为 Signal 双向绑定,onChange/onInput 为回调 - 约定: 表单类组件统一约定:*Props.value/checked/active 为 Signal 双向绑定,onChange/onInput 为回调
+1
View File
@@ -31,6 +31,7 @@ export { segmented } from './segmented.js';
export { stepper } from './stepper.js'; export { stepper } from './stepper.js';
export { rate } from './rate.js'; export { rate } from './rate.js';
export { empty } from './empty.js'; export { empty } from './empty.js';
export { result } from './result.js';
export { divider } from './divider.js'; export { divider } from './divider.js';
export { list } from './list.js'; export { list } from './list.js';
export { carousel } from './carousel.js'; export { carousel } from './carousel.js';
+18
View File
@@ -0,0 +1,18 @@
import { h } from '@ui-arch/frame';
import type { ResultProps } from './types.js';
// 语义状态对应的符号(纯装饰,读屏跳过)
const GLYPH: Record<string, string> = { success: '✓', warning: '!', danger: '×', info: 'i' };
/*** 结果页:状态符号 + 标题 + 说明 + 操作区,用于提交完成 / 校验失败 / 无权限等终态页面 ***/
export function result(props: ResultProps): HTMLElement {
const status = props.status ?? 'info'; // 缺省中性信息
return h(
'div',
{ class: `ua-result ua-result-${status}`, role: 'status' }, // role=status 由读屏播报终态
h('div', { class: 'ua-result-icon', 'aria-hidden': 'true' }, GLYPH[status] ?? 'i'),
h('div', { class: 'ua-result-title' }, props.title),
props.description ? h('div', { class: 'ua-result-desc' }, props.description) : null,
props.extra ? h('div', { class: 'ua-result-extra' }, props.extra) : null, // 操作区:常见为主次按钮
) as HTMLElement;
}
+8
View File
@@ -420,6 +420,14 @@ export interface ListProps {
onItemClick?: (item: ListItem, index: number) => void; // 条目点击回调;提供后条目可点击并带 hover 反馈 onItemClick?: (item: ListItem, index: number) => void; // 条目点击回调;提供后条目可点击并带 hover 反馈
} }
/*** 结果页入参 ***/
export interface ResultProps {
status?: 'success' | 'warning' | 'danger' | 'info'; // 终态语义色;缺省 info
title: string; // 主标题(必填)
description?: string; // 补充说明;缺省不渲染
extra?: unknown; // 操作区内容(常见为主次按钮);缺省不渲染
}
/*** 通知入参 ***/ /*** 通知入参 ***/
export interface NotificationProps { export interface NotificationProps {
title: string; // 通知标题(必填) title: string; // 通知标题(必填)
+37 -1
View File
@@ -57,7 +57,8 @@
"carousel(props):轮播,items 横排位移,指示点/箭头/←→ 键切换,autoplay 毫秒自动前进且悬停暂停,index 信号可外部受控", "carousel(props):轮播,items 横排位移,指示点/箭头/←→ 键切换,autoplay 毫秒自动前进且悬停暂停,index 信号可外部受控",
"tree(props):树形,递归节点 + 箭头展开/收起 + 点选节点,键盘 Enter 选中、→ 展开、← 收起,禁用节点不响应", "tree(props):树形,递归节点 + 箭头展开/收起 + 点选节点,键盘 Enter 选中、→ 展开、← 收起,禁用节点不响应",
"upload(props):文件选择,点击或拖拽入列,清单可逐个移除,onChange 回传文件数组(不内置上传请求)", "upload(props):文件选择,点击或拖拽入列,清单可逐个移除,onChange 回传文件数组(不内置上传请求)",
"notification(props):右下角通知卡片(标题 + 描述 + 操作区),返回 { el, close } 句柄,缺省常驻需手动关闭" "notification(props):右下角通知卡片(标题 + 描述 + 操作区),返回 { el, close } 句柄,缺省常驻需手动关闭",
"result(props):结果页,status 四档语义色 + 标题 + 说明 + 操作区,用于提交完成/校验失败等终态"
], ],
"keyTypes": [ "keyTypes": [
"ButtonProps", "ButtonProps",
@@ -1864,6 +1865,41 @@
"action 放操作区(常见为按钮);variant 决定左侧条与圆点语义色", "action 放操作区(常见为按钮);variant 决定左侧条与圆点语义色",
"与 toast 的分工:toast 右上角轻量瞬时,notification 右下角可长读、可操作" "与 toast 的分工:toast 右上角轻量瞬时,notification 右下角可长读、可操作"
] ]
},
{
"id": "result",
"title": "结果页 Result",
"demo": "sec-result",
"props": [
{
"n": "status",
"t": "'success' | 'warning' | 'danger' | 'info'",
"d": "终态语义色(图标底色);缺省 info"
},
{
"n": "title",
"t": "string",
"r": 1,
"d": "主标题"
},
{
"n": "description",
"t": "string",
"d": "补充说明;缺省不渲染"
},
{
"n": "extra",
"t": "unknown",
"d": "操作区内容(常见为主次按钮);缺省不渲染"
}
],
"example": "result({ status: 'success', title: '提交成功', description: '工单 #2049 已受理', extra: button({ label: '查看工单', variant: 'primary', onClick: () => go() }) })",
"steps": [
"status 决定图标底色(success 绿 / warning 黄 / danger 红 / info 蓝),整体居中排布",
"title 必填;description 用于说明原因或下一步,超过一行自动居中换行",
"extra 放操作区,常见为主按钮 + 幽灵按钮;不传则不渲染",
"组件自带 role=\"status\",插入页面后读屏会播报终态文案"
]
} }
] ]
} }
+41
View File
@@ -2363,3 +2363,44 @@ button.ua-step-dot:hover {
transition: none; transition: none;
} }
} }
/* —— 结果页 —— */
.ua-result {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
gap: var(--ua-space-2);
padding: var(--ua-space-4) var(--ua-space-3);
min-height: 180px;
justify-content: center;
}
.ua-result-icon {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
border-radius: 50%;
font-size: var(--ua-font-size-lg);
font-weight: 700;
color: var(--ua-color-accent-contrast);
background: var(--ua-color-accent);
}
.ua-result-success .ua-result-icon { background: var(--ua-color-success); }
.ua-result-warning .ua-result-icon { background: var(--ua-color-warning); }
.ua-result-danger .ua-result-icon { background: var(--ua-color-danger); }
.ua-result-title {
font-size: var(--ua-font-size-lg);
font-weight: 600;
color: var(--ua-color-text);
}
.ua-result-desc {
max-width: 380px;
font-size: var(--ua-font-size-sm);
color: var(--ua-color-text-muted);
line-height: 1.6;
}
.ua-result-extra {
margin-top: var(--ua-space-1);
}