weifuwu 0.64.0 → 0.64.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/docs/components-map.md +153 -0
- package/docs/components.md +345 -1
- package/docs/environment.md +32 -8
- package/docs/frontend.md +50 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ npm install weifuwu # 一个依赖,完整应用栈
|
|
|
44
44
|
| 认证 / 消息 / 队列 | **随包内置、互相咬合** | 自选 + 自缝 | 自选 + 自缝 |
|
|
45
45
|
| 部署 | 一个 Node 进程 + PG + Redis | 各组件自理 | 平台绑定 |
|
|
46
46
|
|
|
47
|
-
> 定位不是「替代某个框架」,而是**包换包**:用 weifuwu 一个依赖替换你原本要缝合的整套栈。心智模型有借鉴(两阶段组件接近 React、中间件接近 Express),但每一层都是自研的确定性实现——组件模型见[核心概念](#核心概念),与 antd/Element Plus/shadcn 的对应见
|
|
47
|
+
> 定位不是「替代某个框架」,而是**包换包**:用 weifuwu 一个依赖替换你原本要缝合的整套栈。心智模型有借鉴(两阶段组件接近 React、中间件接近 Express),但每一层都是自研的确定性实现——组件模型见[核心概念](#核心概念),与 antd/Element Plus/shadcn 的对应见 [docs/components-map.md](docs/components-map.md)。
|
|
48
48
|
|
|
49
49
|
### 从这里开始
|
|
50
50
|
|
|
@@ -495,6 +495,7 @@ README 只保留入门内容(设计理念 / 快速开始 / 核心概念 / 模
|
|
|
495
495
|
| [docs/examples.md](docs/examples.md) | 组合场景示例:登录表单 / 数据列表 + 搜索 / 消息提示 |
|
|
496
496
|
| [docs/environment.md](docs/environment.md) | 环境变量与开发命令 |
|
|
497
497
|
| [docs/mobile.md](docs/mobile.md) | 移动端开发指南:断点 / 44px 命中区 / usePopup / 手势 / safe-area |
|
|
498
|
+
| [docs/components-map.md](docs/components-map.md) | 组件速查:weifuwu ↔ antd / Element Plus / shadcn 对应 + 迁移路径 |
|
|
498
499
|
| [design/](design/) | 设计与计划文档(组件地图 / AI 协议契约 / 移动端指南 / 数据库客户端计划 / 设计系统 / 各阶段计划) |
|
|
499
500
|
|
|
500
501
|
> `docs/` 用户文档随 npm 包发布(`files: ['dist/', 'README.md', 'docs/']`)——`node_modules/weifuwu/docs` 可离线查阅;`design/` 设计/计划文档仅仓库内。
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# weifuwu/components 组件速查(对应 antd / Element Plus / shadcn-ui)
|
|
2
|
+
|
|
3
|
+
> **开发者迁移速查**:从 antd / Element Plus / shadcn-ui 迁到 weifuwu,按功能找到对应组件。
|
|
4
|
+
> 左侧是 **weifuwu 组件**(已提供),右侧是对应的三库组件 + 差异备注。
|
|
5
|
+
> 真实未实现清单(仅 4 项):见文末「weifuwu 尚未实现」。
|
|
6
|
+
|
|
7
|
+
## 通用基础
|
|
8
|
+
|
|
9
|
+
| 功能 | weifuwu | antd | Element Plus | shadcn-ui | 差异说明 |
|
|
10
|
+
|------|---------|------|-------------|-----------|---------|
|
|
11
|
+
| 按钮 | `<Button variant size loading block>` | Button | Button | Button | 命名基本一致;weifuwu `variant`=primary/secondary/ghost/danger |
|
|
12
|
+
| 图标 | `<Icon name>`(自研 30+ stroke SVG) | Icon | Icon | lucide-react | weifuwu 零依赖、currentColor、1em 随字号;组件内部统一走 Icon |
|
|
13
|
+
| 文本排版 | `<Title/Text/Paragraph>` | Typography | Typography | — | 语义标签 + 语义色 `-text` 变体 + mark/code/删除线 |
|
|
14
|
+
| 分割线 | `<Divider>`(horizontal/vertical/带文字) | Divider | Divider | Separator | 等价 |
|
|
15
|
+
| 头像 | `<Avatar name src color size>` | Avatar | Avatar | Avatar | weifuwu 支持名字哈希色 + 指定色 |
|
|
16
|
+
| 头像组 | `<AvatarGroup items max size>` | Avatar.Group | 手动组合 | 手动组合 | weifuwu 独立组件,`max` 溢出显示 +N |
|
|
17
|
+
| 标签/标签组 | `<Label>`(required 星号)/ `<TagsInput>`(回车/逗号/去重) | Form.Item 标签 / Select tags | — | Label | Label 独立组件 |
|
|
18
|
+
|
|
19
|
+
## 导航
|
|
20
|
+
|
|
21
|
+
| 功能 | weifuwu | antd | Element Plus | shadcn-ui | 差异说明 |
|
|
22
|
+
|------|---------|------|-------------|-----------|---------|
|
|
23
|
+
| 菜单/侧栏 | `<Menu items group activeKey onSelect>`(方向键导航) | Menu | Menu | NavigationMenu / Sidebar | 分组 group 已支持;**子菜单/折叠未实现** |
|
|
24
|
+
| 面包屑 | `<Breadcrumb items>` | Breadcrumb | Breadcrumb | Breadcrumb | 等价 |
|
|
25
|
+
| 标签页 | `<Tabs items active onChange>`(方向键 + 移动端横向滚动) | Tabs | Tabs | Tabs | 等价 |
|
|
26
|
+
| 分页 | `<Pagination total page onChange>`(页码折叠 + 移动端 44px) | Pagination | Pagination | Pagination | 等价 |
|
|
27
|
+
| 步骤条 | `<Steps items current>` | Steps | Steps | — | 等价 |
|
|
28
|
+
| 下拉菜单 | `<Dropdown items>`(danger variant) | Dropdown | Dropdown | DropdownMenu | 等价(usePopup:外部点击/Escape 关闭) |
|
|
29
|
+
| 水平菜单栏 | `<Menubar menus>`(←→↓ 键盘 + 触屏) | Menu 水平 | Menu | Menubar | 等价 |
|
|
30
|
+
| 页面标题 | `<PageHeader title sub>` | PageHeader(v5 移除) | PageHeader | — | weifuwu 保留独立组件 |
|
|
31
|
+
| 回到顶部 | `<BackTop threshold>` | FloatButton / BackTop | Backtop | — | 滚动超阈值显示 |
|
|
32
|
+
| 固定定位 | `<Affix offsetTop>` | Affix | Affix | — | useScrollPosition 实现 |
|
|
33
|
+
| 锚点 | 未实现 | Anchor | Anchor | — | 待补 |
|
|
34
|
+
|
|
35
|
+
## 表单
|
|
36
|
+
|
|
37
|
+
| 功能 | weifuwu | antd | Element Plus | shadcn-ui | 差异说明 |
|
|
38
|
+
|------|---------|------|-------------|-----------|---------|
|
|
39
|
+
| 输入框 | `<Input label error hint variant>` | Input | Input | Input | weifuwu 自带 label/error/hint 包装(antd 需 Form.Item);`variant="borderless"` 内联编辑 |
|
|
40
|
+
| 文本域 | `<Textarea rows showCount maxLength>` | Input.TextArea | Input textarea | Textarea | weifuwu 独立组件 + 字数统计 |
|
|
41
|
+
| 选择器 | `<Select options searchable multiple>` | Select | Select | Select / Combobox | **searchable + 键盘 ↑↓ + multiple 已实现**(近 Combobox) |
|
|
42
|
+
| 复选框 | `<Checkbox checked label>` | Checkbox | Checkbox | Checkbox | 等价 |
|
|
43
|
+
| 复选组 | `<CheckboxGroup options value>` | Checkbox.Group | Checkbox 组 | — | 数组受控 + 栅格列数 |
|
|
44
|
+
| 单选 | `<RadioGroup options value>` | Radio.Group | Radio | RadioGroup | 等价 |
|
|
45
|
+
| 开关 | `<Switch checked>` | Switch | Switch | Switch | 等价 |
|
|
46
|
+
| 滑块 | `<Slider min max step>` | Slider | Slider | Slider | 等价 |
|
|
47
|
+
| 数字输入 | `<InputNumber min max step precision>`(增减按钮+clamp) | InputNumber | InputNumber | — | 等价 |
|
|
48
|
+
| 密码输入 | `<PasswordInput>`(眼睛切换) | Input.Password | Input show-password | — | weifuwu 独立组件 |
|
|
49
|
+
| 日期选择 | `<DatePicker mode="date\|datetime\|time\|range">`(四合一) | DatePicker / TimePicker / RangePicker | DatePicker / DateTimePicker / TimePicker | Calendar + DatePicker 组合 | **一个组件覆盖三库四个**;移动端 range 自动堆叠 |
|
|
50
|
+
| 评分 | `<Rate value>`(键盘方向键) | Rate | Rate | — | allowClear/readOnly |
|
|
51
|
+
| 验证码 | `<PinInput length>`(粘贴/回退/自动聚焦) | — | — | InputOTP | 等价 |
|
|
52
|
+
| 颜色选择 | `<ColorPicker value>`(预设色板 + hex) | ColorPicker | ColorPicker | — | Popover 弹层 |
|
|
53
|
+
| 标签输入 | `<TagsInput value onChange>`(回车/逗号/去重) | Select mode="tags" | 手动组合 | — | weifuwu 独立组件 |
|
|
54
|
+
| 搜索框 | `<SearchInput>` | Input.Search | Input search | — | weifuwu 独立组件 |
|
|
55
|
+
| 分段控件 | `<SegmentedControl options value>` | Segmented | — | ToggleGroup 近似 | weifuwu 独立组件 |
|
|
56
|
+
| 切换按钮 | `<Toggle>/<ToggleGroup>`(single/multiple) | — | — | ToggleGroup | shadcn 对齐 |
|
|
57
|
+
| 表单 | `<Form>` + `<Field label error>`(校验规则) | Form + Form.Item | Form + Form.Item | Form | weifuwu Field 轻量(无 Provider 样板) |
|
|
58
|
+
| 文件上传 | `<FileUpload drag multiple accept maxSize>` | Upload | Upload | — | 拖拽已支持;文件列表/预览/进度待增强 |
|
|
59
|
+
|
|
60
|
+
## 数据展示
|
|
61
|
+
|
|
62
|
+
| 功能 | weifuwu | antd | Element Plus | shadcn-ui | 差异说明 |
|
|
63
|
+
|------|---------|------|-------------|-----------|---------|
|
|
64
|
+
| 表格 | `<Table columns data sortable onSort>` | Table | Table | Table | 列排序 + **行选择/筛选/列宽已实现**;虚拟表格待补 |
|
|
65
|
+
| 卡片 | `<Card clickable hover padding>` | Card | Card | Card | clickable/hover 抬升/active 选中态 |
|
|
66
|
+
| 标签 | `<Tag variant closable>` | Tag | Tag | Badge(variant) | closable 已支持 |
|
|
67
|
+
| 徽标 | `<Badge variant dot>`(8px 状态点) | Badge | Badge | Badge | `dot` = 状态点 |
|
|
68
|
+
| 列表 | `<List items renderItem empty>` | List | 手动 v-for | — | 通用列表 |
|
|
69
|
+
| 时间线 | `<Timeline items status>` | Timeline | Timeline | — | 节点状态色 + 图标 |
|
|
70
|
+
| 描述列表 | `<Descriptions items column bordered>`(dl/dt/dd 语义) | Descriptions | Descriptions | — | 等价 |
|
|
71
|
+
| 统计卡片 | `<StatCard label value trend animate>` | Statistic | Statistic | — | 卡片形态 + 点击 + 动画 |
|
|
72
|
+
| 图片 | `<Img src fallback lazy preview>` | Image | Image | — | **preview 点击放大已实现** |
|
|
73
|
+
| 图表 | `<Chart type data>`(自研零依赖) | — | — | Chart(recharts 包装) | 自研 line/bar/pie,无运行时依赖 |
|
|
74
|
+
| 骨架屏 | `<Skeleton variant count>` | Skeleton | Skeleton | Skeleton | 等价 |
|
|
75
|
+
| 空状态 | `<EmptyState icon text hint>` | Empty | Empty | — | icon 用 emoji/Icon + 操作区 |
|
|
76
|
+
| 结果页 | `<Result status title desc extra>` | Result | Result | — | 等价(success/error/warning/info) |
|
|
77
|
+
| 搜索高亮 | `<Highlight text query>`(`<mark>` 分词) | — | — | — | weifuwu 独有(配 SearchInput/Table) |
|
|
78
|
+
| 树 | `<Tree data checkable checkedKeys>` | Tree | Tree | — | 勾选父子联动 + indeterminate |
|
|
79
|
+
| 级联 | `<Cascader options value>` | Cascader | Cascader | — | 多列面板逐级推进 |
|
|
80
|
+
| 穿梭框 | `<Transfer data targetKeys>` | Transfer | Transfer | — | 双列表 + 移动;移动端自动堆叠 |
|
|
81
|
+
| 月历 | `<Calendar month year events>` | Calendar | Calendar | — | 事件点 + 月切换 |
|
|
82
|
+
| 虚拟列表 | `<VirtualList height itemHeight>` | — | — | — | spacer + 可见窗口,200 条只渲染 ~12 |
|
|
83
|
+
|
|
84
|
+
## 反馈
|
|
85
|
+
|
|
86
|
+
| 功能 | weifuwu | antd | Element Plus | shadcn-ui | 差异说明 |
|
|
87
|
+
|------|---------|------|-------------|-----------|---------|
|
|
88
|
+
| 提示条 | `<Alert variant closable>` | Alert | Alert | Alert | 等价 |
|
|
89
|
+
| 模态框 | `<Modal open title onClose width>` | Modal | Dialog | Dialog | `open/onClose`(antd v5 同);焦点 trap + 归还;移动端 bottom-sheet |
|
|
90
|
+
| 确认框 | `<Confirm>` + `await confirm()` 命令式 | Popconfirm / Modal.confirm | Popconfirm / MessageBox | AlertDialog | 声明式 + 命令式双模式 |
|
|
91
|
+
| 抽屉 | `<Drawer position="left\|right\|top\|bottom">` | Drawer | Drawer | Sheet / Drawer | **四方向覆盖 shadcn Sheet + Drawer**;移动端全宽 |
|
|
92
|
+
| 气泡 | `<Popover position>`(视口夹紧) | Popover | Popover | Popover | 等价(usePopup:外部点击/Escape/tap 降级) |
|
|
93
|
+
| 悬浮提示 | `<Tooltip content position>`(string) | Tooltip | Tooltip | Tooltip | usePopup:桌面 hover / 触屏 tap |
|
|
94
|
+
| 悬停卡 | `<HoverCard content>`(富内容 + 延迟) | — | — | HoverCard | shadcn 对齐;触屏 tap |
|
|
95
|
+
| 右键菜单 | `<ContextMenu items>` | Dropdown context | — | ContextMenu | 桌面右键 + **触屏长按**双通道 |
|
|
96
|
+
| 消息 | `<Toast>` + `toast()` 命令式 | message | Message | Sonner | 命令式 `toast('已保存','success')` |
|
|
97
|
+
| 通知 | `<Notification>` + `notification.success()` | notification | Notification | — | 队列式通知 |
|
|
98
|
+
| 加载 | `<Loading>` | Spin | Loading | — | 等价 |
|
|
99
|
+
| 进度条 | `<ProgressBar value>` | Progress | Progress | Progress | 等价(线性) |
|
|
100
|
+
| 折叠 | `<Collapse items active>`(异步 loading + extra) | Collapse | Collapse | Collapse | 行内折叠(区别于 Accordion) |
|
|
101
|
+
| 手风琴 | `<Accordion items>` | Collapse accordion | Collapse accordion | Accordion | 单开折叠 |
|
|
102
|
+
| 复制按钮 | `<CopyButton value>`(clipboard + 降级 + 成功态) | — | — | — | Chat/CodeBlock 证据驱动 |
|
|
103
|
+
| 水印 | `<Watermark text>`(canvas 平铺 + overlay) | Watermark | — | — | 自研 |
|
|
104
|
+
| 二维码 | `<QRCode value>`(Reed-Solomon + 8 掩码) | QRCode | QRCode | — | **自研编码零依赖** |
|
|
105
|
+
| 轮播 | `<Carousel autoplay>`(箭头/圆点/循环 + 触摸) | Carousel | Carousel | — | 触摸滑动 + 触屏命中区 |
|
|
106
|
+
| 分割面板 | `<Resizable defaultSize>`(拖拽 + 键盘 + clamp) | Splitter | — | Resizable | 指针 + 方向键 |
|
|
107
|
+
| 回到顶部按钮 | `<BackTop>` | FloatButton.BackTop | Backtop | — | 滚动监听 |
|
|
108
|
+
|
|
109
|
+
## AI / 特色(三库无,weifuwu 独有)
|
|
110
|
+
|
|
111
|
+
| 组件 | 说明 |
|
|
112
|
+
|------|------|
|
|
113
|
+
| `<AiChat>` | 完整 AI 对话界面(流式 token/工具卡/审批卡/自动滚动),配 `ctx.ui.useChat()`;移动端 `raiseOnKeyboard` |
|
|
114
|
+
| `<Markdown content>` | 零依赖安全子集 parser(无 raw HTML 注入,VNode 渲染天然转义) |
|
|
115
|
+
| `<CodeBlock code lang>` | 代码块 + 语言标签 + 复制按钮 |
|
|
116
|
+
| `<MessageBubble role status>` | 聊天气泡(独立复用,AiChat 抽取) |
|
|
117
|
+
| `<ToolCallCard>` | AI 工具调用状态机(running/ok/error) |
|
|
118
|
+
| `<ApprovalCard>` | HITL 人工审批卡片(pending/approved/rejected/timeout) |
|
|
119
|
+
| `<Editor>` | 富文本编辑器(contentEditable + 工具栏/表格/图片,零依赖) |
|
|
120
|
+
| `<ThemeSwitch>` | 明暗主题切换(CSS 变量驱动,配 `data-theme`) |
|
|
121
|
+
| `<InView>` | 交叉观察(进入视口触发,可做无限滚动) |
|
|
122
|
+
| `<AspectRatio>` | 宽高比容器(内容填满) |
|
|
123
|
+
| `<CopyButton>` | 复制(clipboard + execCommand 降级 + 成功状态机) |
|
|
124
|
+
|
|
125
|
+
## 快速迁移路径(三库 → weifuwu)
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
// antd / shadcn 开发者
|
|
129
|
+
<Modal open={show} onClose={f}>…</Modal> // antd v5 同命名,直接迁移
|
|
130
|
+
<Select options={opts} value={v} onChange={f} /> // 同命名
|
|
131
|
+
<Button variant="primary">保存</Button> // antd type="primary" → variant
|
|
132
|
+
|
|
133
|
+
// Element Plus 开发者(v-model 模板语法 → value/onChange)
|
|
134
|
+
<Input :value="v" @input="f" /> // → <Input value={v} onInput={f} />
|
|
135
|
+
<ElDialog :visible="s" @close="f" /> // → <Modal open={s} onClose={f} />
|
|
136
|
+
<ElMessage>成功</ElMessage> // → toast('成功','success')
|
|
137
|
+
|
|
138
|
+
// shadcn 开发者(原子组合 → 成品)
|
|
139
|
+
<Dialog><DialogTrigger/>…</Dialog> // → <Modal open onClose> 一体组件
|
|
140
|
+
<Sheet><SheetTrigger/>…</Sheet> // → <Drawer position="bottom">
|
|
141
|
+
<Badge variant="secondary">x</Badge> // → <Tag variant="secondary">x</Tag>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## weifuwu 尚未实现(三库有)→ 待补清单
|
|
145
|
+
|
|
146
|
+
仅 4 项:
|
|
147
|
+
|
|
148
|
+
- **Anchor**(锚点导航,三库均有)
|
|
149
|
+
- **Menu 子菜单/折叠**(分组 group 已支持,子级/折叠待补)
|
|
150
|
+
- **FileUpload 增强**(拖拽已支持;文件列表/预览/进度待补)
|
|
151
|
+
- **VirtualTable**(VirtualList 已有,表格虚拟化待补)
|
|
152
|
+
|
|
153
|
+
> 难度阶梯(L1-L6)与验证的 client 能力点:见 `design/components-cdd.md`;三库 → weifuwu 覆盖矩阵:见 `design/components-migration.md`。
|
package/docs/components.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
92 个 HTML 原语组件。每个是 `(_init, ctx) => (props) => VNode`(两阶段组件,与前端框架同一模型),引用 `--wf-*` CSS 变量做主题。另含 `confirm()` / `toast()` 命令式中间件。
|
|
6
6
|
|
|
7
|
-
> **组件速查(weifuwu 组件 ↔ antd / Element Plus / shadcn-ui 对应 + 迁移示例)**:见 [`
|
|
7
|
+
> **组件速查(weifuwu 组件 ↔ antd / Element Plus / shadcn-ui 对应 + 迁移示例)**:见 [`docs/components-map.md`](components-map.md)——从其他组件库迁来的开发者按功能直接找对应组件。
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
10
|
import { Button, Input, Table, Modal, Toast } from 'weifuwu/components'
|
|
@@ -163,6 +163,350 @@ props 变化 ──────────────────────
|
|
|
163
163
|
| `局部刷新` | `ctx.ui.render()` 或 `$.x = val` |
|
|
164
164
|
| `跨组件刷新` | `ctx.ui.selfId('name')` + `render(['name'])` |
|
|
165
165
|
|
|
166
|
+
## 通用约定(所有组件一致)
|
|
167
|
+
|
|
168
|
+
### 受控模式
|
|
169
|
+
|
|
170
|
+
| 组件类型 | 受控 prop | 必须配回调 |
|
|
171
|
+
|----------|-----------|-----------|
|
|
172
|
+
| 开关/勾选(Checkbox/Switch/RadioGroup) | `checked` | `onChange` |
|
|
173
|
+
| 输入(Input/Select/DatePicker/Textarea) | `value` | `onChange` / `onInput` |
|
|
174
|
+
| 标签页/折叠(Tabs/Collapse) | `active` | `onChange` |
|
|
175
|
+
| 弹层(Modal/Drawer/Dropdown/Popover) | `open` | `onClose` / `onOpenChange` |
|
|
176
|
+
| 树/级联/穿梭(Tree/Cascader/Transfer) | `checkedKeys`/`value`/`targetKeys` | `onChange` |
|
|
177
|
+
| 月历(Calendar) | `month`/`year` | `onMonthChange` |
|
|
178
|
+
|
|
179
|
+
**规则**:传受控 props 而不传回调时,交互**静默失效**——组件 `console.warn` 明确提示(Collapse/Tree/Calendar/Cascader/Dropdown 已有防护)。非受控(不传受控 props)即可直接点击。
|
|
180
|
+
|
|
181
|
+
### size 变体
|
|
182
|
+
|
|
183
|
+
- `sm` / `md` / `lg`(Button/Avatar/Input 族)。未提供 size 的组件使用默认尺寸(CSS `--wf-control-pad-*` 驱动)。
|
|
184
|
+
- 触屏(coarse pointer)自动 44px 命中区,不受 size 影响。
|
|
185
|
+
|
|
186
|
+
### 事件命名
|
|
187
|
+
|
|
188
|
+
| 语义 | 命名 |
|
|
189
|
+
|------|------|
|
|
190
|
+
| 值变化(受控) | `onChange` |
|
|
191
|
+
| 原生输入 | `onInput` |
|
|
192
|
+
| 列表选中 | `onSelect` |
|
|
193
|
+
| 弹层开关 | `onOpenChange`(弹层)/ `onClose`(对话框) |
|
|
194
|
+
| 表格排序 | `onSort` |
|
|
195
|
+
|
|
196
|
+
### 命令式 API(无需组件)
|
|
197
|
+
|
|
198
|
+
`confirm()` / `toast()` / `notification.success()`——组件内 `ctx.confirm?.('确定?')` 直接可用(中间件注入)。
|
|
199
|
+
|
|
200
|
+
## 关键组件 Props 参考
|
|
201
|
+
> 从组件 TS 类型自动提取(`src/components/*/*.ts` 的 `interface XxxProps`)。
|
|
202
|
+
> 完整 props 以 TS 类型为准——`tsc` 编译期校验;此处为速查。受控约定:传受控 props 必须配回调(缺回调运行期 warn)。
|
|
203
|
+
|
|
204
|
+
### Button(表单/通用)
|
|
205
|
+
| Prop | 类型 | 说明 |
|
|
206
|
+
|------|------|------|
|
|
207
|
+
| `variant` | `'primary' \| 'secondary' \| 'ghost' \| 'danger'` | — |
|
|
208
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | — |
|
|
209
|
+
| `block` | `boolean` | — |
|
|
210
|
+
| `loading` | `boolean` | — |
|
|
211
|
+
| `disabled` | `boolean` | — |
|
|
212
|
+
| `type` | `'button' \| 'submit'` | — |
|
|
213
|
+
| `title` | `string` | — |
|
|
214
|
+
| `class` | `string` | 透传原生 class(覆盖默认 wf-btn 组合) |
|
|
215
|
+
| `onClick` | `(e: MouseEvent) => void` | — |
|
|
216
|
+
| `children` | `any` | — |
|
|
217
|
+
|
|
218
|
+
### Input(表单核心)
|
|
219
|
+
| Prop | 类型 | 说明 |
|
|
220
|
+
|------|------|------|
|
|
221
|
+
| `label` | `string` | — |
|
|
222
|
+
| `name` | `string` | — |
|
|
223
|
+
| `type` | `'text' \| 'email' \| 'password' \| 'number' \| 'url' \| 'date' \| 'tel' \| 'time' \| 'color'` | — |
|
|
224
|
+
| `value` | `string` | — |
|
|
225
|
+
| `placeholder` | `string` | — |
|
|
226
|
+
| `required` | `boolean` | — |
|
|
227
|
+
| `disabled` | `boolean` | — |
|
|
228
|
+
| `error` | `string` | — |
|
|
229
|
+
| `hint` | `string` | — |
|
|
230
|
+
| `variant` | `'default' \| 'borderless'` | 边框变体:borderless 用于可编辑标题/内联编辑(hover/focus 才显边框) |
|
|
231
|
+
| `onInput` | `(e: Event) => void` | — |
|
|
232
|
+
| `onChange` | `(e: Event) => void` | — |
|
|
233
|
+
| `min` | `string \| number` | 原生 input 属性透传(type=number 时 min/max/step 等) |
|
|
234
|
+
| `max` | `string \| number` | — |
|
|
235
|
+
| `step` | `string \| number` | — |
|
|
236
|
+
| `key` | `string]: any` | — |
|
|
237
|
+
|
|
238
|
+
### Textarea(表单核心)
|
|
239
|
+
| Prop | 类型 | 说明 |
|
|
240
|
+
|------|------|------|
|
|
241
|
+
| `label` | `string` | — |
|
|
242
|
+
| `value` | `string` | — |
|
|
243
|
+
| `placeholder` | `string` | — |
|
|
244
|
+
| `required` | `boolean` | — |
|
|
245
|
+
| `disabled` | `boolean` | — |
|
|
246
|
+
| `error` | `string` | — |
|
|
247
|
+
| `hint` | `string` | — |
|
|
248
|
+
| `rows` | `number` | — |
|
|
249
|
+
| `maxLength` | `number` | 最大字符数(同时限制输入) |
|
|
250
|
+
| `showCount` | `boolean` | 显示字数统计(右下角;配合受控 value 实时更新) |
|
|
251
|
+
| `onInput` | `(e: Event) => void` | — |
|
|
252
|
+
|
|
253
|
+
### Select(表单选择)
|
|
254
|
+
| Prop | 类型 | 说明 |
|
|
255
|
+
|------|------|------|
|
|
256
|
+
| `label` | `string` | — |
|
|
257
|
+
| `value` | `string \| string[]` | — |
|
|
258
|
+
| `options` | `SelectOption[]` | — |
|
|
259
|
+
| `placeholder` | `string` | — |
|
|
260
|
+
| `required` | `boolean` | — |
|
|
261
|
+
| `disabled` | `boolean` | — |
|
|
262
|
+
| `error` | `string` | — |
|
|
263
|
+
| `onChange` | `(value: string \| string[]) => void` | — |
|
|
264
|
+
| `children` | `any` | — |
|
|
265
|
+
| `searchable` | `boolean` | 启用搜索过滤 |
|
|
266
|
+
| `multiple` | `boolean` | 多选模式(searchable 下生效;value/onChange 为数组) |
|
|
267
|
+
| `onSearch` | `(keyword: string) => SelectOption[] \| Promise<SelectOption[]>` | 异步搜索回调,返回值作为新选项列表 |
|
|
268
|
+
|
|
269
|
+
### Checkbox(表单选择)
|
|
270
|
+
| Prop | 类型 | 说明 |
|
|
271
|
+
|------|------|------|
|
|
272
|
+
| `label` | `string` | — |
|
|
273
|
+
| `checked` | `boolean` | — |
|
|
274
|
+
| `disabled` | `boolean` | — |
|
|
275
|
+
| `onChange` | `(checked: boolean) => void` | — |
|
|
276
|
+
|
|
277
|
+
### Switch(表单选择)
|
|
278
|
+
| Prop | 类型 | 说明 |
|
|
279
|
+
|------|------|------|
|
|
280
|
+
| `label` | `string` | — |
|
|
281
|
+
| `checked` | `boolean` | — |
|
|
282
|
+
| `disabled` | `boolean` | — |
|
|
283
|
+
| `onChange` | `(checked: boolean) => void` | — |
|
|
284
|
+
|
|
285
|
+
### RadioGroup(表单选择)
|
|
286
|
+
| Prop | 类型 | 说明 |
|
|
287
|
+
|------|------|------|
|
|
288
|
+
| `name` | `string` | — |
|
|
289
|
+
| `value` | `string` | — |
|
|
290
|
+
| `options` | `RadioOption[]` | — |
|
|
291
|
+
| `inline` | `boolean` | — |
|
|
292
|
+
| `onChange` | `(value: string) => void` | — |
|
|
293
|
+
|
|
294
|
+
### DatePicker(表单选择)
|
|
295
|
+
| Prop | 类型 | 说明 |
|
|
296
|
+
|------|------|------|
|
|
297
|
+
| `mode` | `DatePickerMode` | — |
|
|
298
|
+
| `value` | `string` | — |
|
|
299
|
+
| `onChange` | `(value: string) => void` | — |
|
|
300
|
+
| `placeholder` | `string` | — |
|
|
301
|
+
| `disabled` | `boolean` | — |
|
|
302
|
+
|
|
303
|
+
### Form(表单增强)
|
|
304
|
+
| Prop | 类型 | 说明 |
|
|
305
|
+
|------|------|------|
|
|
306
|
+
| `onSubmit` | `(values: Record<string, any>) => void \| Promise<void>` | 提交回调,接收字段名→值的对象 |
|
|
307
|
+
| `validation` | `Record<string, ValidationRule[]>` | 验证规则:字段名 → 规则数组 |
|
|
308
|
+
| `onError` | `(errors: Record<string, string>) => void` | 验证失败时回调,接收字段名→错误消息的对象 |
|
|
309
|
+
| `children` | `any` | — |
|
|
310
|
+
|
|
311
|
+
### Field(表单增强)
|
|
312
|
+
| Prop | 类型 | 说明 |
|
|
313
|
+
|------|------|------|
|
|
314
|
+
| `label` | `string` | — |
|
|
315
|
+
| `required` | `boolean` | — |
|
|
316
|
+
| `error` | `string` | — |
|
|
317
|
+
| `hint` | `string` | — |
|
|
318
|
+
| `children` | `any` | — |
|
|
319
|
+
|
|
320
|
+
### Table(数据展示)
|
|
321
|
+
| Prop | 类型 | 说明 |
|
|
322
|
+
|------|------|------|
|
|
323
|
+
| `data` | `any[]` | — |
|
|
324
|
+
| `columns` | `TableColumn[]` | — |
|
|
325
|
+
| `onRowClick` | `(row: any, index: number) => void` | — |
|
|
326
|
+
| `sortKey` | `string` | 当前排序列的 key |
|
|
327
|
+
| `sortOrder` | `'asc' \| 'desc'` | 当前排序方向 |
|
|
328
|
+
| `onSort` | `(key: string, order: 'asc' \| 'desc') => void` | 排序变化回调 |
|
|
329
|
+
| `rowSelection` | `TableRowSelection` | 行选择(受控) |
|
|
330
|
+
| `emptyText` | `string` | 数据为空时显示的文本 |
|
|
331
|
+
| `minWidth` | `string` | 表格最小宽度(窄屏横向滚动,如 '720px') |
|
|
332
|
+
| `loading` | `boolean` | 加载中:保留表头,渲染骨架行 |
|
|
333
|
+
| `loadingRows` | `number` | 骨架行数,默认 3 |
|
|
334
|
+
|
|
335
|
+
### Modal(数据反馈)
|
|
336
|
+
| Prop | 类型 | 说明 |
|
|
337
|
+
|------|------|------|
|
|
338
|
+
| `open` | `boolean` | — |
|
|
339
|
+
| `title` | `string` | — |
|
|
340
|
+
| `onClose` | `() => void` | — |
|
|
341
|
+
| `children` | `any` | — |
|
|
342
|
+
| `footer` | `any` | — |
|
|
343
|
+
| `width` | `string` | 自定义宽度,如 '500px'、'80%',默认 400px |
|
|
344
|
+
| `closable` | `boolean` | 是否显示关闭按钮,默认 true |
|
|
345
|
+
| `maskClosable` | `boolean` | 点击遮罩是否关闭,默认 true(危险确认应设 false) |
|
|
346
|
+
|
|
347
|
+
### Drawer(数据反馈)
|
|
348
|
+
| Prop | 类型 | 说明 |
|
|
349
|
+
|------|------|------|
|
|
350
|
+
| `open` | `boolean` | — |
|
|
351
|
+
| `title` | `string` | — |
|
|
352
|
+
| `position` | `DrawerPosition` | — |
|
|
353
|
+
| `onClose` | `() => void` | — |
|
|
354
|
+
| `children` | `any` | — |
|
|
355
|
+
| `footer` | `any` | — |
|
|
356
|
+
|
|
357
|
+
### Confirm(数据反馈)
|
|
358
|
+
| Prop | 类型 | 说明 |
|
|
359
|
+
|------|------|------|
|
|
360
|
+
| `open` | `boolean` | — |
|
|
361
|
+
| `title` | `string` | — |
|
|
362
|
+
| `message` | `any` | 提示内容(文本或任意 VNode) |
|
|
363
|
+
| `confirmText` | `string` | — |
|
|
364
|
+
| `cancelText` | `string` | — |
|
|
365
|
+
| `variant` | `'primary' \| 'danger'` | — |
|
|
366
|
+
| `width` | `string` | 对话框宽度,如 '500px'、'80%',默认 Modal 的 400px |
|
|
367
|
+
| `maskClosable` | `boolean` | 遮罩点击是否取消(默认 false:危险操作防误触;显式传 true 可恢复) |
|
|
368
|
+
| `onConfirm` | `() => void` | — |
|
|
369
|
+
| `onCancel` | `() => void` | — |
|
|
370
|
+
|
|
371
|
+
### Toast(数据反馈)
|
|
372
|
+
| Prop | 类型 | 说明 |
|
|
373
|
+
|------|------|------|
|
|
374
|
+
| `toasts` | `ToastItem[]` | — |
|
|
375
|
+
| `onRemove` | `(id: string) => void` | — |
|
|
376
|
+
| `position` | `ToastPosition` | 容器位置,默认 top-right |
|
|
377
|
+
| `duration` | `number` | 全局默认自动消失时间(ms),0 = 不自动消失,默认 0 |
|
|
378
|
+
| `max` | `number` | 最大显示条数,超出时移除最早条目,默认 0 = 不限制 |
|
|
379
|
+
|
|
380
|
+
### Tooltip(数据反馈)
|
|
381
|
+
| Prop | 类型 | 说明 |
|
|
382
|
+
|------|------|------|
|
|
383
|
+
| `content` | `string` | — |
|
|
384
|
+
| `position` | `TooltipPosition` | — |
|
|
385
|
+
| `children` | `any` | — |
|
|
386
|
+
| `disabled` | `boolean` | — |
|
|
387
|
+
|
|
388
|
+
### Popover(数据反馈)
|
|
389
|
+
| Prop | 类型 | 说明 |
|
|
390
|
+
|------|------|------|
|
|
391
|
+
| `content` | `any` | — |
|
|
392
|
+
| `trigger` | `'click' \| 'hover'` | — |
|
|
393
|
+
| `position` | `PopoverPosition` | — |
|
|
394
|
+
| `open` | `boolean` | — |
|
|
395
|
+
| `onOpenChange` | `(open: boolean) => void` | — |
|
|
396
|
+
| `disabled` | `boolean` | — |
|
|
397
|
+
| `children` | `any` | — |
|
|
398
|
+
|
|
399
|
+
### Dropdown(导航组件)
|
|
400
|
+
| Prop | 类型 | 说明 |
|
|
401
|
+
|------|------|------|
|
|
402
|
+
| `trigger` | `any` | — |
|
|
403
|
+
| `items` | `DropdownItem[]` | — |
|
|
404
|
+
| `open` | `boolean` | — |
|
|
405
|
+
| `onOpenChange` | `(open: boolean) => void` | 关闭回调(面板内 Escape / 外部点击) |
|
|
406
|
+
|
|
407
|
+
### Tabs(导航组件)
|
|
408
|
+
| Prop | 类型 | 说明 |
|
|
409
|
+
|------|------|------|
|
|
410
|
+
| `items` | `TabItem[]` | — |
|
|
411
|
+
| `active` | `string` | — |
|
|
412
|
+
| `onChange` | `(key: string) => void` | — |
|
|
413
|
+
|
|
414
|
+
### Pagination(导航组件)
|
|
415
|
+
| Prop | 类型 | 说明 |
|
|
416
|
+
|------|------|------|
|
|
417
|
+
| `total` | `number` | — |
|
|
418
|
+
| `page` | `number` | — |
|
|
419
|
+
| `pageSize` | `number` | — |
|
|
420
|
+
| `onChange` | `(page: number) => void` | — |
|
|
421
|
+
|
|
422
|
+
### Tree(新增批次)
|
|
423
|
+
| Prop | 类型 | 说明 |
|
|
424
|
+
|------|------|------|
|
|
425
|
+
| `data` | `TreeNode[]` | — |
|
|
426
|
+
| `selectedKeys` | `string[]` | 受控选中 keys |
|
|
427
|
+
| `onSelect` | `(keys: string[]) => void` | — |
|
|
428
|
+
| `expandedKeys` | `string[]` | 受控展开 keys |
|
|
429
|
+
| `onExpand` | `(keys: string[]) => void` | — |
|
|
430
|
+
| `checkable` | `boolean` | 勾选模式(父子联动,antd 非 strict 语义) |
|
|
431
|
+
| `checkedKeys` | `string[]` | — |
|
|
432
|
+
| `onCheck` | `(keys: string[]) => void` | — |
|
|
433
|
+
| `className` | `string` | — |
|
|
434
|
+
|
|
435
|
+
### Cascader(新增批次)
|
|
436
|
+
| Prop | 类型 | 说明 |
|
|
437
|
+
|------|------|------|
|
|
438
|
+
| `options` | `CascaderOption[]` | — |
|
|
439
|
+
| `value` | `string[]` | 选中路径(数组,如 ['zj','hz','xh']) |
|
|
440
|
+
| `onChange` | `(value: string[]) => void` | — |
|
|
441
|
+
| `placeholder` | `string` | — |
|
|
442
|
+
| `disabled` | `boolean` | — |
|
|
443
|
+
| `error` | `string` | — |
|
|
444
|
+
| `label` | `string` | — |
|
|
445
|
+
|
|
446
|
+
### Transfer(新增批次)
|
|
447
|
+
| Prop | 类型 | 说明 |
|
|
448
|
+
|------|------|------|
|
|
449
|
+
| `data` | `TransferItem[]` | — |
|
|
450
|
+
| `targetKeys` | `string[]` | 目标侧已选 keys |
|
|
451
|
+
| `onChange` | `(targetKeys: string[]) => void` | — |
|
|
452
|
+
| `titles` | `[string, string]` | — |
|
|
453
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | — |
|
|
454
|
+
| `disabled` | `boolean` | — |
|
|
455
|
+
|
|
456
|
+
### Carousel(新增批次)
|
|
457
|
+
| Prop | 类型 | 说明 |
|
|
458
|
+
|------|------|------|
|
|
459
|
+
| `children` | `any[]` | — |
|
|
460
|
+
| `autoplay` | `boolean` | 自动播放 |
|
|
461
|
+
| `interval` | `number` | 自动播放间隔(ms),默认 3000 |
|
|
462
|
+
| `showArrows` | `boolean` | — |
|
|
463
|
+
| `showDots` | `boolean` | — |
|
|
464
|
+
| `loop` | `boolean` | 循环播放(尾 → 头),默认 true |
|
|
465
|
+
| `className` | `string` | — |
|
|
466
|
+
|
|
467
|
+
### Calendar(新增批次)
|
|
468
|
+
| Prop | 类型 | 说明 |
|
|
469
|
+
|------|------|------|
|
|
470
|
+
| `events` | `CalendarEvent[]` | — |
|
|
471
|
+
| `month` | `number` | 受控年月:month 0-11,year 四位数 |
|
|
472
|
+
| `year` | `number` | — |
|
|
473
|
+
| `onMonthChange` | `(month: number, year: number) => void` | — |
|
|
474
|
+
| `onSelectDate` | `(date: string) => void` | — |
|
|
475
|
+
| `selectedDate` | `string` | — |
|
|
476
|
+
|
|
477
|
+
### AiChat(AI 交互)
|
|
478
|
+
| Prop | 类型 | 说明 |
|
|
479
|
+
|------|------|------|
|
|
480
|
+
| `chat` | `UseChatHandle` | ctx.ui.useChat() 返回的会话 handle(同一 $,状态变化自动重渲染) |
|
|
481
|
+
| `maxHeight` | `string` | 消息列表最大高度(默认 '70vh') |
|
|
482
|
+
| `labels` | `Partial<AiChatLabels>` | 界面文案覆盖 |
|
|
483
|
+
| `renderMessage` | `(msg: UiMessage) => any` | 自定义气泡渲染逃生舱(默认纯文本) |
|
|
484
|
+
| `renderToolArgs` | `(args: Record<string, unknown>) => any` | 工具参数渲染(透传 ToolCallCard) |
|
|
485
|
+
| `raiseOnKeyboard` | `boolean` | 键盘弹起时输入区 fixed 抬升(全屏 chat 布局用;内联卡片默认 false——原生聚焦滚动已够) |
|
|
486
|
+
|
|
487
|
+
### FileUpload(表单增强)
|
|
488
|
+
| Prop | 类型 | 说明 |
|
|
489
|
+
|------|------|------|
|
|
490
|
+
| `accept` | `string` | — |
|
|
491
|
+
| `multiple` | `boolean` | — |
|
|
492
|
+
| `maxSize` | `number` | — |
|
|
493
|
+
| `disabled` | `boolean` | — |
|
|
494
|
+
| `error` | `string` | — |
|
|
495
|
+
| `hint` | `string` | — |
|
|
496
|
+
| `value` | `File[]` | — |
|
|
497
|
+
| `onChange` | `(files: File[]) => void` | — |
|
|
498
|
+
| `children` | `any` | — |
|
|
499
|
+
|
|
500
|
+
### Slider(表单选择)
|
|
501
|
+
| Prop | 类型 | 说明 |
|
|
502
|
+
|------|------|------|
|
|
503
|
+
| `label` | `string` | — |
|
|
504
|
+
| `value` | `number \| string` | — |
|
|
505
|
+
| `min` | `number` | — |
|
|
506
|
+
| `max` | `number` | — |
|
|
507
|
+
| `step` | `number` | — |
|
|
508
|
+
| `onChange` | `(value: number) => void` | — |
|
|
509
|
+
|
|
166
510
|
## 组件列表
|
|
167
511
|
|
|
168
512
|
### 表单核心
|
package/docs/environment.md
CHANGED
|
@@ -2,26 +2,50 @@
|
|
|
2
2
|
|
|
3
3
|
> 本页为 weifuwu 官方文档拆分页 · [返回 README](../README.md)
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
|
8
|
-
|
|
5
|
+
## 环境变量
|
|
6
|
+
|
|
7
|
+
| 变量 | 用途 | 模块 | 默认 |
|
|
8
|
+
|------|------|------|------|
|
|
9
|
+
| `DATABASE_URL` | PostgreSQL 连接字符串 | `postgres()` | —(必填) |
|
|
10
|
+
| `REDIS_URL` | Redis 连接字符串 | `redis()` | `redis://localhost:6379` |
|
|
11
|
+
| `AUTH_SECRET` | userSystem HMAC 签名密钥(≥16 字符) | `userSystem()` | 可传 `options.secret` |
|
|
12
|
+
| `DEEPSEEK_API_KEY` | LLM 对话 provider API key | `ai()` | — |
|
|
13
|
+
| `DEEPSEEK_BASE_URL` | LLM 对话 provider 端点 | `ai()` | `https://api.deepseek.com/v1` |
|
|
14
|
+
| `DEEPSEEK_MODEL` | 默认对话模型 | `ai()` | `deepseek-v4-flash` |
|
|
15
|
+
| `DASHSCOPE_API_KEY` | embedding 向量化 provider key | `ai({ embedding })` | — |
|
|
16
|
+
| `DASHSCOPE_BASE_URL` | embedding provider 端点 | `ai({ embedding })` | — |
|
|
17
|
+
| `DASHSCOPE_EMBEDDING_MODEL` | embedding 模型名 | `ai({ embedding })` | — |
|
|
18
|
+
| `RESEND_API_KEY` | 邮件 adapter `resend` | `email()` | 可用 `options.resend` |
|
|
19
|
+
| `SMTP_HOST` | 邮件 adapter `smtp` | `email()` | `localhost` |
|
|
20
|
+
| `SMTP_PORT` | SMTP 端口 | `email()` | `3025` |
|
|
21
|
+
|
|
22
|
+
> 均可通过中间件 options 显式传入(`postgres({ url })` / `userSystem({ secret })` / `ai({ provider })`),环境变量为默认来源。
|
|
9
23
|
|
|
10
24
|
---
|
|
11
25
|
|
|
12
|
-
|
|
26
|
+
## 开发命令
|
|
13
27
|
|
|
14
28
|
```bash
|
|
15
29
|
npm run build # 构建 dist/
|
|
16
30
|
npm run typecheck # TypeScript 类型检查
|
|
17
|
-
npm test # 运行 node --test
|
|
18
|
-
node scripts/release.mjs <version> # 发布
|
|
31
|
+
npm test # 运行 node --test(含 docker 真库测试)
|
|
32
|
+
node scripts/release.mjs <version> # 构建 + 发布 + git tag
|
|
19
33
|
```
|
|
20
34
|
|
|
21
35
|
```bash
|
|
22
|
-
#
|
|
36
|
+
# 测试前启动依赖服务(postgres / redis / smtp)
|
|
23
37
|
docker compose up -d
|
|
24
38
|
```
|
|
25
39
|
|
|
26
40
|
---
|
|
27
41
|
|
|
42
|
+
## 应用示例启动
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# 组件 cheatsheet(零依赖)
|
|
46
|
+
cd apps/components-demo && node server.ts
|
|
47
|
+
|
|
48
|
+
# 全栈 SaaS 示例(多租户 AI 平台)
|
|
49
|
+
cd apps/agent-platform && npm run seed && npm run dev
|
|
50
|
+
# 凭据:admin@demo.com / admin123
|
|
51
|
+
```
|
package/docs/frontend.md
CHANGED
|
@@ -153,6 +153,8 @@ ctx.ui.render(['name'])
|
|
|
153
153
|
| `render()` | `render(ids?: string[])` | 同步强制渲染;无参 = 当前组件,传参 = 指定组件列表 |
|
|
154
154
|
| `dirty()` | `dirty(ids?: string[])` | 异步渲染(微任务批处理合并);`$` 内部就是调它 |
|
|
155
155
|
| `selfId()` | `selfId(name: string)` | 注册组件自定义 ID,配合 `render(['id'])` 跨组件精准刷新 |
|
|
156
|
+
| `useChat()` | `useChat({ url, approveUrl?, body? })` | AI 对话会话:消息/流式/工具/审批,与 `$` 同容器(AiChat 配套) |
|
|
157
|
+
| `useAsync()` | `useAsync(fetcher)` | 异步取数:`data/loading/error` 响应式 + `reload()` |
|
|
156
158
|
| `useMedia()` | `useMedia(query, cb)` | 响应式媒体查询,断点变化时自动回调 |
|
|
157
159
|
| `useBreakpoint()` | `useBreakpoint(cb \| bps, cb?)` | 命名断点 mobile/tablet/desktop |
|
|
158
160
|
| `usePopupPosition()` | `usePopupPosition(opts)` | 弹层坐标跟随:scroll/resize 时自动重算 fixed 坐标 |
|
|
@@ -412,6 +414,54 @@ ctx.ui.render(['stats']) // 同步刷新
|
|
|
412
414
|
- **同名冲突直接抛错**,每个自定义 ID 必须全局唯一
|
|
413
415
|
- 配合 `selfId` 注册的组件在跨组件场景下无需把刷新逻辑层层传 props
|
|
414
416
|
|
|
417
|
+
#### `ctx.ui.useChat(options)` — AI 对话会话(AiChat 配套)
|
|
418
|
+
|
|
419
|
+
会话语义的流式 AI 状态容器:消息累积 / 工具调用内嵌 / HITL 审批 / stop / retry,协议对页面完全透明(wf: 协议见 `design/ai-contract.md`)。返回的 handle 与 `ctx.ui.$()` **同一个 $**(页面状态与会话状态共处一容器):
|
|
420
|
+
|
|
421
|
+
```tsx
|
|
422
|
+
// mount 阶段(服务端 `ai()` 中间件 + `AiChat` 组件配套)
|
|
423
|
+
const $ = ctx.ui.useChat({
|
|
424
|
+
url: '/api/chat', // POST 端点(返回 wf: SSE 流)
|
|
425
|
+
approveUrl: '/api/approve', // HITL 审批上行(缺省时 approve() 只清卡片)
|
|
426
|
+
body: (messages) => ({ messages, mode: 'agent' }), // 定制请求体
|
|
427
|
+
onEvent: (name, data) => { console.log('x:' + name, data) }, // x:* 透传
|
|
428
|
+
})
|
|
429
|
+
|
|
430
|
+
return (props) =>
|
|
431
|
+
h('div', {},
|
|
432
|
+
h(AiChat, { chat: $ }), // 标准对话界面:流式 token/工具卡/审批卡/自动滚动
|
|
433
|
+
$.streaming ? '生成中…' : '', // 会话状态与页面状态同容器
|
|
434
|
+
)
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
**状态(`$` 上)**:
|
|
438
|
+
|
|
439
|
+
| 字段 | 类型 | 说明 |
|
|
440
|
+
|------|------|------|
|
|
441
|
+
| `$.messages` | `UiMessage[]` | 消息列表(`{ id, role, content, status, toolCalls?, approval?, usage?, error? }`) |
|
|
442
|
+
| `$.input` | `string` | 输入框值(双向绑定) |
|
|
443
|
+
| `$.streaming` | `boolean` | 是否正在流式生成 |
|
|
444
|
+
| `$.error` | `WfError \| null` | 最近错误(code + message) |
|
|
445
|
+
| `$.usage` | `WfUsage \| null` | token 用量(prompt/completion/total) |
|
|
446
|
+
| `$.step` | `WfStep \| null` | 最近 agent 步骤指示(思考/工具),done/error 时清空 |
|
|
447
|
+
|
|
448
|
+
**操作(`$` 上的方法)**:`$.send()`(发送当前输入)/ `$.stop()`(中止)/ `$.retry()`(截断到最后一条 user 重生成)/ `$.clear()`(清空)/ `$.approve(decision, note?)`(响应审批)/ `$.dispose()`(卸载时释放流)。
|
|
449
|
+
|
|
450
|
+
**共享 $ 的子组件**(如 `<AiChat chat={$}>`):父组件 dirty 不驱动子组件(三态 skip),子组件 mount 阶段 `chat.__watch?.(() => ctx.ui.dirty())` 自订阅(AiChat 已内置)。
|
|
451
|
+
|
|
452
|
+
#### `ctx.ui.useAsync(fetcher)` — 异步取数
|
|
453
|
+
|
|
454
|
+
`data/loading/error` 响应式 + `reload()` 重跑;数据就绪自动渲染当前组件。
|
|
455
|
+
|
|
456
|
+
```tsx
|
|
457
|
+
const list = ctx.ui.useAsync(() => ctx.api.get<User[]>('/users'))
|
|
458
|
+
|
|
459
|
+
return () => list.loading ? h(Loading) : list.data?.map(u => h('div', {}, u.name))
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
- `list.data` / `list.loading` / `list.error` 赋值自动 dirty 当前组件
|
|
463
|
+
- `list.reload()` 重跑;组件卸载后旧 Promise resolve 不再触发渲染(idRegistry 查无此组件,安全忽略)
|
|
464
|
+
|
|
415
465
|
#### CSS 层响应式(不碰 JS)
|
|
416
466
|
|
|
417
467
|
配合 `weifuwu/layout` 的断点变体,纯 CSS 实现布局方向切换:
|