weifuwu 0.63.0 → 0.64.0
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 +124 -2956
- package/dist/ai/client.d.ts +1 -1
- package/dist/ai/sse.d.ts +1 -1
- package/dist/ai/types.d.ts +2 -2
- package/dist/client/ai.d.ts +1 -1
- package/dist/client/index.js +3 -3
- package/dist/client/types.d.ts +108 -0
- package/dist/client/use-chat.d.ts +1 -1
- package/dist/components/AiChat/AiChat.d.ts +2 -0
- package/dist/components/ContextMenu/ContextMenu.d.ts +1 -1
- package/dist/components/Dropdown/Dropdown.d.ts +4 -1
- package/dist/components/HoverCard/HoverCard.d.ts +7 -1
- package/dist/components/Popover/Popover.d.ts +3 -0
- package/dist/components/Tooltip/Tooltip.d.ts +3 -0
- package/dist/components/index.js +13 -13
- package/dist/components/style.css +164 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/layout/weifuwu-layout.css +22 -0
- package/docs/components.md +314 -0
- package/docs/data.md +240 -0
- package/docs/environment.md +27 -0
- package/docs/examples.md +127 -0
- package/docs/frontend-middleware.md +435 -0
- package/docs/frontend.md +697 -0
- package/docs/layout.md +203 -0
- package/docs/mobile.md +109 -0
- package/docs/realtime.md +291 -0
- package/docs/saas.md +246 -0
- package/docs/server.md +356 -0
- package/docs/styling.md +130 -0
- package/package.json +4 -3
|
@@ -702,6 +702,28 @@ code {
|
|
|
702
702
|
}
|
|
703
703
|
}
|
|
704
704
|
|
|
705
|
+
@layer layout {
|
|
706
|
+
/* popup — 浮层基类(usePopup.portal 自动附加;Modal/Drawer 等手动浮层可选用)
|
|
707
|
+
*
|
|
708
|
+
* 宽度视口 clamp:任何浮层默认不横向溢出(375px 屏也能完整操作)。
|
|
709
|
+
* usePopup 已内联 maxWidth;本类兜底组件手动引用场景(audit 规则的目标选择器)。
|
|
710
|
+
*/
|
|
711
|
+
.wf-popup {
|
|
712
|
+
max-width: min(var(--wf-popup-max, 480px), calc(100vw - 32px));
|
|
713
|
+
box-sizing: border-box;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
@layer layout {
|
|
718
|
+
/* safe-area — iOS 刘海屏/Home 条安全区工具(env() 未生效环境自动为 0) */
|
|
719
|
+
.wf-safe-bottom {
|
|
720
|
+
padding-bottom: env(safe-area-inset-bottom);
|
|
721
|
+
}
|
|
722
|
+
.wf-safe-top {
|
|
723
|
+
padding-top: env(safe-area-inset-top);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
705
727
|
@layer layout {
|
|
706
728
|
/* anchor — 定位锚点容器 */
|
|
707
729
|
.wf-anchor {
|
|
@@ -2049,6 +2071,14 @@ code {
|
|
|
2049
2071
|
color: var(--wf-color-text-tertiary);
|
|
2050
2072
|
}
|
|
2051
2073
|
|
|
2074
|
+
/* 触屏(coarse):月份切换按钮 44px 命中区 */
|
|
2075
|
+
@media (pointer: coarse) {
|
|
2076
|
+
.wf-calendar-nav-btn {
|
|
2077
|
+
min-height: 44px;
|
|
2078
|
+
min-width: 44px;
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2052
2082
|
/* weifuwu/components — Card */
|
|
2053
2083
|
|
|
2054
2084
|
.wf-card {
|
|
@@ -2187,6 +2217,25 @@ code {
|
|
|
2187
2217
|
transform: scale(1.25);
|
|
2188
2218
|
}
|
|
2189
2219
|
|
|
2220
|
+
/* 触屏(coarse):箭头 44px;圆点保持视觉 8px,用 ::after 扩展命中区(视觉不变) */
|
|
2221
|
+
@media (pointer: coarse) {
|
|
2222
|
+
.wf-carousel-arrow {
|
|
2223
|
+
width: 44px;
|
|
2224
|
+
height: 44px;
|
|
2225
|
+
min-width: 44px;
|
|
2226
|
+
min-height: 44px;
|
|
2227
|
+
}
|
|
2228
|
+
.wf-carousel-dot {
|
|
2229
|
+
position: relative;
|
|
2230
|
+
}
|
|
2231
|
+
.wf-carousel-dot::after {
|
|
2232
|
+
content: '';
|
|
2233
|
+
position: absolute;
|
|
2234
|
+
inset: -14px;
|
|
2235
|
+
border-radius: 50%;
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
|
|
2190
2239
|
/* weifuwu/components — Cascader */
|
|
2191
2240
|
|
|
2192
2241
|
.wf-cascader-wrap {
|
|
@@ -3240,6 +3289,34 @@ code {
|
|
|
3240
3289
|
padding: 0 2px;
|
|
3241
3290
|
}
|
|
3242
3291
|
|
|
3292
|
+
/* ── 移动端适配(P0):面板宽度视口 clamp + range 窄屏纵向堆叠 ── */
|
|
3293
|
+
|
|
3294
|
+
.wf-datepicker-dropdown {
|
|
3295
|
+
max-width: calc(100vw - 32px);
|
|
3296
|
+
}
|
|
3297
|
+
|
|
3298
|
+
.wf-time-picker {
|
|
3299
|
+
max-width: calc(100vw - 32px);
|
|
3300
|
+
}
|
|
3301
|
+
|
|
3302
|
+
.wf-datepicker-range-wrap {
|
|
3303
|
+
max-width: calc(100vw - 32px);
|
|
3304
|
+
}
|
|
3305
|
+
|
|
3306
|
+
/* range 双面板(240px×2 ≈ 500px)在 375px 屏溢出 → 窄屏纵向堆叠 */
|
|
3307
|
+
@media (max-width: 639px) {
|
|
3308
|
+
.wf-datepicker-range-wrap {
|
|
3309
|
+
flex-direction: column;
|
|
3310
|
+
max-height: 80vh;
|
|
3311
|
+
overflow-y: auto;
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
|
|
3315
|
+
/* 时间选择列(时/分/秒)窄屏横向滚动 */
|
|
3316
|
+
.wf-time-body {
|
|
3317
|
+
overflow-x: auto;
|
|
3318
|
+
}
|
|
3319
|
+
|
|
3243
3320
|
/* weifuwu/components — Descriptions */
|
|
3244
3321
|
|
|
3245
3322
|
.wf-descriptions {
|
|
@@ -3477,6 +3554,14 @@ code {
|
|
|
3477
3554
|
border-top: var(--wf-border-width, 1px) solid var(--wf-color-border);
|
|
3478
3555
|
}
|
|
3479
3556
|
|
|
3557
|
+
/* 移动端适配(P2):小屏抽屉全宽(底部安全区) */
|
|
3558
|
+
@media (max-width: 639px) {
|
|
3559
|
+
.wf-drawer-panel {
|
|
3560
|
+
width: 100vw;
|
|
3561
|
+
max-width: 100vw;
|
|
3562
|
+
}
|
|
3563
|
+
}
|
|
3564
|
+
|
|
3480
3565
|
/* weifuwu/components — Dropdown */
|
|
3481
3566
|
|
|
3482
3567
|
.wf-dropdown {
|
|
@@ -3843,6 +3928,14 @@ code {
|
|
|
3843
3928
|
border-top: 1px solid var(--wf-color-border);
|
|
3844
3929
|
}
|
|
3845
3930
|
|
|
3931
|
+
/* 触屏(coarse):工具栏按钮 44px 命中区 */
|
|
3932
|
+
@media (pointer: coarse) {
|
|
3933
|
+
.wf-editor-toolbar button {
|
|
3934
|
+
min-height: 44px;
|
|
3935
|
+
min-width: 44px;
|
|
3936
|
+
}
|
|
3937
|
+
}
|
|
3938
|
+
|
|
3846
3939
|
/* weifuwu/components — EmptyState */
|
|
3847
3940
|
|
|
3848
3941
|
.wf-empty {
|
|
@@ -4915,6 +5008,25 @@ code {
|
|
|
4915
5008
|
border-top: var(--wf-border-width) solid var(--wf-color-border);
|
|
4916
5009
|
}
|
|
4917
5010
|
|
|
5011
|
+
/* ── 移动端适配(P2):min-width 视口 clamp(修 375px 屏 400px 溢出)+ 小屏 bottom-sheet ── */
|
|
5012
|
+
|
|
5013
|
+
.wf-modal-content {
|
|
5014
|
+
min-width: min(var(--wf-modal-width, 400px), calc(100vw - 32px));
|
|
5015
|
+
}
|
|
5016
|
+
|
|
5017
|
+
@media (max-width: 639px) {
|
|
5018
|
+
.wf-modal {
|
|
5019
|
+
align-items: flex-end; /* bottom-sheet 形态 */
|
|
5020
|
+
}
|
|
5021
|
+
.wf-modal-content {
|
|
5022
|
+
width: 100%;
|
|
5023
|
+
max-width: 100vw;
|
|
5024
|
+
max-height: 85vh;
|
|
5025
|
+
border-radius: var(--wf-radius-lg) var(--wf-radius-lg) 0 0;
|
|
5026
|
+
padding-bottom: env(safe-area-inset-bottom);
|
|
5027
|
+
}
|
|
5028
|
+
}
|
|
5029
|
+
|
|
4918
5030
|
/* weifuwu/components — Notification */
|
|
4919
5031
|
|
|
4920
5032
|
.wf-notification-container {
|
|
@@ -5111,6 +5223,23 @@ code {
|
|
|
5111
5223
|
color: var(--wf-color-text-tertiary);
|
|
5112
5224
|
}
|
|
5113
5225
|
|
|
5226
|
+
/* 触屏(coarse):页码 44px 命中区(覆盖全局 button min-height) */
|
|
5227
|
+
@media (pointer: coarse) {
|
|
5228
|
+
.wf-pagination-item {
|
|
5229
|
+
min-height: 44px;
|
|
5230
|
+
min-width: 44px;
|
|
5231
|
+
}
|
|
5232
|
+
}
|
|
5233
|
+
|
|
5234
|
+
/* 移动端适配(P2):窄屏页码横向滚动兜底(44px 命中区 + 折叠后仍可能溢出) */
|
|
5235
|
+
.wf-pagination {
|
|
5236
|
+
overflow-x: auto;
|
|
5237
|
+
scrollbar-width: none;
|
|
5238
|
+
}
|
|
5239
|
+
.wf-pagination::-webkit-scrollbar {
|
|
5240
|
+
display: none;
|
|
5241
|
+
}
|
|
5242
|
+
|
|
5114
5243
|
/* weifuwu/components — PasswordInput(复用 Input 基础类) */
|
|
5115
5244
|
|
|
5116
5245
|
.wf-password {
|
|
@@ -5816,6 +5945,15 @@ code {
|
|
|
5816
5945
|
border-radius: var(--wf-radius-sm);
|
|
5817
5946
|
}
|
|
5818
5947
|
|
|
5948
|
+
/* 触屏(coarse):搜索选项行 44px 命中区(非 button 元素,需显式覆盖) */
|
|
5949
|
+
@media (pointer: coarse) {
|
|
5950
|
+
.wf-select-search-opt {
|
|
5951
|
+
min-height: 44px;
|
|
5952
|
+
display: flex;
|
|
5953
|
+
align-items: center;
|
|
5954
|
+
}
|
|
5955
|
+
}
|
|
5956
|
+
|
|
5819
5957
|
/* weifuwu/components — Skeleton */
|
|
5820
5958
|
|
|
5821
5959
|
.wf-skeleton {
|
|
@@ -6277,6 +6415,15 @@ code {
|
|
|
6277
6415
|
padding-top: var(--wf-space-md);
|
|
6278
6416
|
}
|
|
6279
6417
|
|
|
6418
|
+
/* 移动端适配(P2):窄屏标签横向滚动(隐藏滚动条) */
|
|
6419
|
+
.wf-tab-list {
|
|
6420
|
+
overflow-x: auto;
|
|
6421
|
+
scrollbar-width: none;
|
|
6422
|
+
}
|
|
6423
|
+
.wf-tab-list::-webkit-scrollbar {
|
|
6424
|
+
display: none;
|
|
6425
|
+
}
|
|
6426
|
+
|
|
6280
6427
|
/* weifuwu/components — Tag */
|
|
6281
6428
|
|
|
6282
6429
|
.wf-tag {
|
|
@@ -7065,6 +7212,23 @@ code {
|
|
|
7065
7212
|
cursor: not-allowed;
|
|
7066
7213
|
}
|
|
7067
7214
|
|
|
7215
|
+
/* 触屏(coarse):移动按钮 44px 命中区 */
|
|
7216
|
+
@media (pointer: coarse) {
|
|
7217
|
+
.wf-transfer-btn {
|
|
7218
|
+
width: 44px;
|
|
7219
|
+
height: 44px;
|
|
7220
|
+
min-width: 44px;
|
|
7221
|
+
min-height: 44px;
|
|
7222
|
+
}
|
|
7223
|
+
}
|
|
7224
|
+
|
|
7225
|
+
/* 移动端适配(P2):窄屏双栏纵向堆叠(操作钮居中) */
|
|
7226
|
+
@media (max-width: 767px) {
|
|
7227
|
+
.wf-transfer {
|
|
7228
|
+
flex-direction: column;
|
|
7229
|
+
}
|
|
7230
|
+
}
|
|
7231
|
+
|
|
7068
7232
|
/* weifuwu/components — Tree */
|
|
7069
7233
|
|
|
7070
7234
|
.wf-tree {
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export type { EmailOptions, EmailMessage, EmailResult, EmailAdapter, EmailInject
|
|
|
18
18
|
export { sendSmtp } from './email/smtp.ts';
|
|
19
19
|
export type { SmtpConfig } from './email/smtp.ts';
|
|
20
20
|
export { userSystem } from './user/index.ts';
|
|
21
|
+
export { hashPassword, verifyPassword } from './user/password.ts';
|
|
21
22
|
export { messager } from './messager/index.ts';
|
|
22
23
|
export type { UserSystemOptions, UserInjected, AuthApi, RegisterInput } from './user/index.ts';
|
|
23
24
|
export type { MessagerOptions, MessagerInjected, MessagerClient, MessagerSystem, Message, Conversation } from './messager/index.ts';
|
package/dist/index.js
CHANGED
|
@@ -6035,6 +6035,7 @@ export {
|
|
|
6035
6035
|
created,
|
|
6036
6036
|
email,
|
|
6037
6037
|
forbidden,
|
|
6038
|
+
hashPassword,
|
|
6038
6039
|
messager,
|
|
6039
6040
|
noContent,
|
|
6040
6041
|
notFound,
|
|
@@ -6055,5 +6056,6 @@ export {
|
|
|
6055
6056
|
uiSsr,
|
|
6056
6057
|
unauthorized,
|
|
6057
6058
|
unprocessable,
|
|
6058
|
-
userSystem
|
|
6059
|
+
userSystem,
|
|
6060
|
+
verifyPassword
|
|
6059
6061
|
};
|
|
@@ -702,6 +702,28 @@ code {
|
|
|
702
702
|
}
|
|
703
703
|
}
|
|
704
704
|
|
|
705
|
+
@layer layout {
|
|
706
|
+
/* popup — 浮层基类(usePopup.portal 自动附加;Modal/Drawer 等手动浮层可选用)
|
|
707
|
+
*
|
|
708
|
+
* 宽度视口 clamp:任何浮层默认不横向溢出(375px 屏也能完整操作)。
|
|
709
|
+
* usePopup 已内联 maxWidth;本类兜底组件手动引用场景(audit 规则的目标选择器)。
|
|
710
|
+
*/
|
|
711
|
+
.wf-popup {
|
|
712
|
+
max-width: min(var(--wf-popup-max, 480px), calc(100vw - 32px));
|
|
713
|
+
box-sizing: border-box;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
@layer layout {
|
|
718
|
+
/* safe-area — iOS 刘海屏/Home 条安全区工具(env() 未生效环境自动为 0) */
|
|
719
|
+
.wf-safe-bottom {
|
|
720
|
+
padding-bottom: env(safe-area-inset-bottom);
|
|
721
|
+
}
|
|
722
|
+
.wf-safe-top {
|
|
723
|
+
padding-top: env(safe-area-inset-top);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
705
727
|
@layer layout {
|
|
706
728
|
/* anchor — 定位锚点容器 */
|
|
707
729
|
.wf-anchor {
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
# 组件库(weifuwu/components)
|
|
2
|
+
|
|
3
|
+
> 本页为 weifuwu 官方文档拆分页 · [返回 README](../README.md)
|
|
4
|
+
|
|
5
|
+
92 个 HTML 原语组件。每个是 `(_init, ctx) => (props) => VNode`(两阶段组件,与前端框架同一模型),引用 `--wf-*` CSS 变量做主题。另含 `confirm()` / `toast()` 命令式中间件。
|
|
6
|
+
|
|
7
|
+
> **组件速查(weifuwu 组件 ↔ antd / Element Plus / shadcn-ui 对应 + 迁移示例)**:见 [`design/components-map.md`](../design/components-map.md)——从其他组件库迁来的开发者按功能直接找对应组件。
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { Button, Input, Table, Modal, Toast } from 'weifuwu/components'
|
|
11
|
+
import 'weifuwu/components/style.css' // 包含 Token + 67 布局原语 + 组件样式,一次性引入
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### 使用示例
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
// ├─ 按钮
|
|
18
|
+
<Button variant="primary" onClick={() => alert('提交')}>提交</Button>
|
|
19
|
+
<Button variant="ghost" loading>加载中</Button>
|
|
20
|
+
<Button variant="danger" size="lg" block>删除</Button>
|
|
21
|
+
|
|
22
|
+
// ├─ 输入框
|
|
23
|
+
<Input placeholder="请输入邮箱" />
|
|
24
|
+
<Input label="用户名" name="username" required error="必填" />
|
|
25
|
+
<Input type="password" hint="至少6位" />
|
|
26
|
+
<Input name="email" type="email" disabled placeholder="name@example.com" />
|
|
27
|
+
|
|
28
|
+
// ├─ 选择器
|
|
29
|
+
<Select options={[{ value: 'a', label: '选项A' }]} placeholder="请选择" />
|
|
30
|
+
<Select searchable options={options} onChange={v => setVal(v)} />
|
|
31
|
+
|
|
32
|
+
// ├─ 复选框 / 开关 / 单选
|
|
33
|
+
<Checkbox checked={agree} onChange={setAgree} label="同意协议" />
|
|
34
|
+
<Switch checked={enabled} onChange={setEnabled} />
|
|
35
|
+
<RadioGroup options={[{ value: '1', label: '男' }, { value: '2', label: '女' }]} value={gender} />
|
|
36
|
+
|
|
37
|
+
// ├─ 表格
|
|
38
|
+
<Table columns={[{ key: 'id', label: 'ID', sortable: true }, { key: 'name', label: '名称' }]}
|
|
39
|
+
data={rows} sortKey="id" sortOrder="asc" onSort={(k, o) => setSort(k, o)} />
|
|
40
|
+
|
|
41
|
+
// ├─ 模态框 / 确认框 / 抽屉
|
|
42
|
+
<Modal open={show} title="提示" onClose={() => setShow(false)} width="500px" closable>
|
|
43
|
+
<p>确认删除?</p>
|
|
44
|
+
</Modal>
|
|
45
|
+
<Confirm open={confirming} message="确定删除?" variant="danger" onConfirm={doDelete} onCancel={() => setConfirming(false)} />
|
|
46
|
+
// 命令式:await ctx.confirm?.('确定删除?') —— 组件里直接调用
|
|
47
|
+
<Drawer open={open} title="详情" onClose={() => setOpen(false)} position="right">内容</Drawer>
|
|
48
|
+
|
|
49
|
+
// ├─ 消息提示
|
|
50
|
+
<Toast toasts={items} position="top-right" max={5} onRemove={id => remove(id)} />
|
|
51
|
+
<Alert variant="warning" closable>注意:磁盘空间不足</Alert>
|
|
52
|
+
|
|
53
|
+
// ├─ 标签 / 徽标 / 头像
|
|
54
|
+
<Badge variant="primary">消息</Badge>
|
|
55
|
+
<Badge variant="success" dot>通过</Badge>
|
|
56
|
+
<Tag variant="primary" closable onClose={() => {}}>标签</Tag>
|
|
57
|
+
<Avatar name="张三" size="lg" />
|
|
58
|
+
|
|
59
|
+
// ├─ 卡片 / 统计卡片
|
|
60
|
+
<Card variant="outlined" padding="md">卡片内容</Card>
|
|
61
|
+
<StatCard label="总用户" value="1,234" trend="up" trendLabel="12%" />
|
|
62
|
+
|
|
63
|
+
// ├─ 标签页 / 下拉菜单
|
|
64
|
+
<Tabs items={[{ key: 'a', label: '标签A' }, { key: 'b', label: '标签B' }]} active="a" onChange={setTab} />
|
|
65
|
+
<Dropdown items={[{ label: '编辑', onClick: () => {} }, { label: '删除', variant: 'danger' }]}>操作</Dropdown>
|
|
66
|
+
|
|
67
|
+
// ├─ 分页 / 步骤条
|
|
68
|
+
<Pagination total={100} page={1} pageSize={10} onChange={setPage} />
|
|
69
|
+
<Steps items={[{ key: 's1', label: '第一步' }, { key: 's2', label: '第二步' }]} current={1} />
|
|
70
|
+
|
|
71
|
+
// ├─ 滑块 / 进度条
|
|
72
|
+
<Slider min={0} max={100} value={50} onChange={setValue} />
|
|
73
|
+
<ProgressBar value={75} label="75%" />
|
|
74
|
+
|
|
75
|
+
// ├─ 面包屑 / 分割线
|
|
76
|
+
<Breadcrumb items={[{ label: '首页' }, { label: '用户管理' }]} />
|
|
77
|
+
<Divider />
|
|
78
|
+
<Divider>分割文字</Divider>
|
|
79
|
+
|
|
80
|
+
// ├─ 加载 / 空状态 / 骨架屏
|
|
81
|
+
<Loading text="加载中..." />
|
|
82
|
+
<EmptyState text="暂无数据" hint="请先创建一条记录"><Button>新建</Button></EmptyState>
|
|
83
|
+
<Skeleton variant="text" lines={3} />
|
|
84
|
+
<Skeleton variant="table" lines={5} cols={4} />
|
|
85
|
+
<Skeleton variant="avatar" />
|
|
86
|
+
<Skeleton variant="image" />
|
|
87
|
+
|
|
88
|
+
// ├─ 表单验证
|
|
89
|
+
<Form validation={{ email: [{ required: true, message: '请输入邮箱' }] }}
|
|
90
|
+
onSubmit={values => ctx.api?.post('/login', values)} // ctx.api 由中间件注入
|
|
91
|
+
onError={errors => setErrors(errors)}>
|
|
92
|
+
<Field label="邮箱" error={errors.email}>
|
|
93
|
+
<Input name="email" />
|
|
94
|
+
</Field>
|
|
95
|
+
<Button type="submit">登录</Button>
|
|
96
|
+
</Form>
|
|
97
|
+
|
|
98
|
+
// ├─ 新增批次组件(全量实现)
|
|
99
|
+
<Rate value={3} onChange={setRate} /> // 评分
|
|
100
|
+
<ToggleGroup type="single" options={toolbar} value={fmt} /> // 工具栏切换
|
|
101
|
+
<CheckboxGroup options={members} value={selected} onChange={setSelected} /> // 多选列表
|
|
102
|
+
<PinInput length={6} value={code} onChange={setCode} /> // 验证码
|
|
103
|
+
<CopyButton value="https://weifuwu.dev" label="复制" /> // 复制
|
|
104
|
+
<ColorPicker value={color} showInput onChange={setColor} /> // 颜色
|
|
105
|
+
<Notification /> + notification.success({ title, description }) // 队列通知
|
|
106
|
+
<Collapse items={docs} active={open} /> // 行内折叠
|
|
107
|
+
<Tree data={orgTree} checkable checkedKeys={keys} /> // 树形(父子联动)
|
|
108
|
+
<Cascader options={regions} value={['zj','hz']} /> // 级联选择
|
|
109
|
+
<Transfer data={members} targetKeys={selected} /> // 穿梭框
|
|
110
|
+
<Command items={commands} open={open} onOpenChange={setOpen} /> // ⌘K 命令面板
|
|
111
|
+
<Carousel autoplay>{slides}</Carousel> // 轮播
|
|
112
|
+
<Resizable defaultSize={180}>…</Resizable> // 拖拽分割
|
|
113
|
+
<Calendar month={5} year={2025} events={events} /> // 月历
|
|
114
|
+
<Watermark text="内部资料">…</Watermark> // 水印
|
|
115
|
+
<VirtualList height={400} itemHeight={36} items={rows} renderItem={render} /> // 虚拟列表
|
|
116
|
+
<QRCode value="https://weifuwu.dev" size={128} /> // 二维码(自研编码)
|
|
117
|
+
<Img src="photo.png" preview /> // 图片点击放大
|
|
118
|
+
<BackTop /> <Affix offsetTop={64}>…</Affix> // 回顶 / 固定
|
|
119
|
+
<HoverCard content={<UserCard />}>…</HoverCard> // 悬停富内容
|
|
120
|
+
<Mentions options={users} value={text} /> // @提及
|
|
121
|
+
<ContextMenu items={actions}>…</ContextMenu> // 右键菜单
|
|
122
|
+
<Menubar menus={menus} /> // 水平菜单
|
|
123
|
+
<InfiniteScroll hasMore onLoadMore>…</InfiniteScroll> // 无限滚动
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
> 所有组件引用 `--wf-*` CSS 变量做主题,详见下文的「样式定制指南」。
|
|
127
|
+
|
|
128
|
+
### 生命周期映射
|
|
129
|
+
|
|
130
|
+
组件没有生命周期函数。每个阶段对应到代码的明确位置:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
mount ──────────────────────────────────────────
|
|
134
|
+
const Counter = (_init, ctx) => { ← mount(只一次)
|
|
135
|
+
let count = 0 ← 初始化状态
|
|
136
|
+
return (props) => { ← render 函数
|
|
137
|
+
// ... ← 每次 dirty/props 变化执行
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
ref ────────────────────────────────────────────
|
|
142
|
+
h('div', {
|
|
143
|
+
ref: (el) => {
|
|
144
|
+
if (el) { /* 元素已创建 */ } ← 相当于 onmounted
|
|
145
|
+
else { /* 元素已移除 */ } ← 相当于 onunmount
|
|
146
|
+
}
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
props 变化 ─────────────────────────────────────
|
|
150
|
+
return (props) => {
|
|
151
|
+
// 每次 render 都收到最新 props ← 相当于 onupdate
|
|
152
|
+
if (props.value !== prevValue) { ... }
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
| 旧概念 | 新写法 |
|
|
157
|
+
|--------|--------|
|
|
158
|
+
| `onmount` | mount 外层函数直接写 |
|
|
159
|
+
| `onmounted` | `ref` 的 `if (el)` 分支 |
|
|
160
|
+
| `onunmount` | `ref` 的 `else` 分支 |
|
|
161
|
+
| `onupdate` | render 内层函数收新 props 自行比较 |
|
|
162
|
+
| `全局刷新` | `ctx.ui.render(['_wf_root'])` |
|
|
163
|
+
| `局部刷新` | `ctx.ui.render()` 或 `$.x = val` |
|
|
164
|
+
| `跨组件刷新` | `ctx.ui.selfId('name')` + `render(['name'])` |
|
|
165
|
+
|
|
166
|
+
## 组件列表
|
|
167
|
+
|
|
168
|
+
### 表单核心
|
|
169
|
+
|
|
170
|
+
| 组件 | 导入名 | 关键 Props | 说明 |
|
|
171
|
+
|-----|--------|-----------|------|
|
|
172
|
+
| Button | `Button` | `variant`, `size`, `loading`, `disabled`, `block`, `type` | 按钮 |
|
|
173
|
+
| Input | `Input` | `label`, `name`, `type`, `value`, `placeholder`, `required`, `disabled`, `error`, `hint`, `onInput`, `onChange` | 输入框 |
|
|
174
|
+
| Textarea | `Textarea` | `rows`, `maxLength`, `showCount`, `error` | 文本域 |
|
|
175
|
+
| Select | `Select` | `options: SelectOption[]`, `placeholder`, `searchable` | 下拉选择 |
|
|
176
|
+
|
|
177
|
+
### 表单选择
|
|
178
|
+
|
|
179
|
+
| 组件 | 导入名 | 关键 Props | 说明 |
|
|
180
|
+
|-----|--------|-----------|------|
|
|
181
|
+
| Checkbox | `Checkbox` | `checked`, `label`, `onChange` | 复选框 |
|
|
182
|
+
| Switch | `Switch` | `checked`, `label`, `onChange` | 开关 |
|
|
183
|
+
| RadioGroup | `RadioGroup` | `options: RadioOption[]`, `value`, `name` | 单选组 |
|
|
184
|
+
| Slider | `Slider` | `min`, `max`, `step`, `value`, `onChange` | 滑块 |
|
|
185
|
+
|
|
186
|
+
### 表单增强
|
|
187
|
+
|
|
188
|
+
| 组件 | 导入名 | 关键 Props | 说明 |
|
|
189
|
+
|-----|--------|-----------|------|
|
|
190
|
+
| Form | `Form` | `onSubmit`, `validation` | 表单容器 |
|
|
191
|
+
| Field | `Field` | `label`, `error`, `required`, `hint` | 字段包装 |
|
|
192
|
+
| FileUpload | `FileUpload` | `accept`, `multiple`, `maxSize`, `onChange` | 文件上传 |
|
|
193
|
+
| SearchInput | `SearchInput` | `value`, `placeholder`, `onInput`, `onClear` | 搜索框 |
|
|
194
|
+
| SegmentedControl | `SegmentedControl` | `options: SegmentedOption[]`, `value`, `onChange`, `size` | 分段选择器 |
|
|
195
|
+
| ProgressBar | `ProgressBar` | `value`, `max`, `label`, `showValue` | 进度条 |
|
|
196
|
+
| InputNumber | `InputNumber` | `value`, `min`, `max`, `step`, `precision`, `onChange` | 数字输入(增减按钮) |
|
|
197
|
+
| PasswordInput | `PasswordInput` | `value`, `onInput`, `autoComplete` | 密码输入(可见性切换) |
|
|
198
|
+
| TagsInput | `TagsInput` | `value: string[]`, `maxTags`, `allowDuplicates` | 标签输入(中文输入法感知) |
|
|
199
|
+
|
|
200
|
+
### 数据展示
|
|
201
|
+
|
|
202
|
+
| 组件 | 导入名 | 关键 Props | 说明 |
|
|
203
|
+
|-----|--------|-----------|------|
|
|
204
|
+
| Table | `Table` | `columns: TableColumn[]`, `data`, `loading`, `sortKey`, `sortOrder`, `onSort`, `onRowClick` | 表格 |
|
|
205
|
+
| Card | `Card` | `variant`, `outlined`, `padding`, `clickable`, `hover`, `active`, `onClick` | 卡片 |
|
|
206
|
+
| Badge | `Badge` | `variant: BadgeVariant`, `dot` | 徽标 |
|
|
207
|
+
| Tag | `Tag` | `variant: 'default'\|'primary'\|'success'\|'danger'`, `closable`, `onClose` | 标签 |
|
|
208
|
+
| Avatar | `Avatar` | `src`, `name`, `size`, `color` | 头像 |
|
|
209
|
+
| AvatarGroup | `AvatarGroup` | `items`, `max`, `size` | 头像组(堆叠 + 溢出 +N) |
|
|
210
|
+
| Timeline | `Timeline` | `items: TimelineItem[]`, `mode`, `reverse` | 时间线(执行日志/历史) |
|
|
211
|
+
| Descriptions | `Descriptions` | `items: DescriptionItem[]`, `column`, `bordered` | 描述列表(详情页字段) |
|
|
212
|
+
| Markdown | `Markdown` | `content` | AI 回复渲染(安全子集 parser) |
|
|
213
|
+
| CodeBlock | `CodeBlock` | `code`, `lang`, `title` | 代码块(语言标签 + 复制) |
|
|
214
|
+
| Highlight | `Highlight` | `text`, `query: string \| string[]` | 搜索词高亮(mark) |
|
|
215
|
+
| List | `List` | `items`, `renderItem`, `divided`, `header/footer/empty` | 通用列表 |
|
|
216
|
+
| Result | `Result` | `status`, `title`, `desc`, `extra` | 结果页(成功/失败/警告/信息) |
|
|
217
|
+
| Icon | `Icon` | `name: IconName`, `size` | 图标(内置 25 个 stroke 图标,currentColor 随字号) |
|
|
218
|
+
| StatCard | `StatCard` | `label`, `value`, `trend: 'up'\|'down'`, `trendLabel`, `icon`, `animate` | 统计卡片 |
|
|
219
|
+
| PageHeader | `PageHeader` | `title`, `sub`, `display` | 页面标题(actions 放 children) |
|
|
220
|
+
| Img | `Img` | `src`, `alt`, `fallback`, `loading`, `width`, `height` | 图片(含 fallback) |
|
|
221
|
+
| InView | `InView` | `once`, `threshold`, `rootMargin`, `placeholder`, `onEnter` | 进入视窗后懒加载内容 |
|
|
222
|
+
|
|
223
|
+
### 数据反馈
|
|
224
|
+
|
|
225
|
+
| 组件 | 导入名 | 关键 Props | 说明 |
|
|
226
|
+
|-----|--------|-----------|------|
|
|
227
|
+
| Modal | `Modal` | `open`, `title`, `onClose`, `width`, `footer`, `closable` | 模态框 |
|
|
228
|
+
| Confirm | `Confirm` | `open`, `message`, `confirmText`, `cancelText`, `variant`, `onConfirm`, `onCancel` | 确认对话框(同 `ctx.confirm()` 命令式) |
|
|
229
|
+
| Drawer | `Drawer` | `open`, `title`, `position: DrawerPosition`, `onClose`, `footer` | 抽屉 |
|
|
230
|
+
| Tooltip | `Tooltip` | `content`, `position: TooltipPosition`, `disabled` | 工具提示(hover/focus 触发) |
|
|
231
|
+
| Popover | `Popover` | `content`, `position: PopoverPosition`, `trigger`, `open`, `onOpenChange`, `disabled` | 弹出层 |
|
|
232
|
+
| Toast | `Toast` | `toasts: ToastItem[]`, `position`, `max`, `onRemove` | 消息提示 |
|
|
233
|
+
| Alert | `Alert` | `variant: AlertVariant`, `closable`, `onClose` | 警告提示(内容放 children) |
|
|
234
|
+
| Loading | `Loading` | `text` | 加载中 |
|
|
235
|
+
| EmptyState | `EmptyState` | `icon`, `text`, `hint` | 空状态(操作放 children) |
|
|
236
|
+
| Skeleton | `Skeleton` | `variant: SkeletonVariant`, `lines`, `cols`, `width`, `height` | 骨架屏 |
|
|
237
|
+
|
|
238
|
+
### 导航组件
|
|
239
|
+
|
|
240
|
+
| 组件 | 导入名 | 关键 Props | 说明 |
|
|
241
|
+
|-----|--------|-----------|------|
|
|
242
|
+
| Breadcrumb | `Breadcrumb` | `items: BreadcrumbItem[]` | 面包屑 |
|
|
243
|
+
| Menu | `Menu` | `items: MenuItem[]`, `activeKey`, `onSelect` | 侧栏导航(分组 + 图标 + 方向键) |
|
|
244
|
+
| Tabs | `Tabs` | `items: TabItem[]`, `active`, `onChange` | 标签页 |
|
|
245
|
+
| Dropdown | `Dropdown` | `trigger`, `items: DropdownItem[]`, `open`, `onOpenChange` | 下拉菜单 |
|
|
246
|
+
| Pagination | `Pagination` | `total`, `page`, `pageSize`, `onChange` | 分页 |
|
|
247
|
+
| Steps | `Steps` | `items: StepItem[]`(`{ key, label }`), `current`, `active` | 步骤条 |
|
|
248
|
+
| Accordion | `Accordion` | `items: AccordionItem[]`, `multiple` | 手风琴 |
|
|
249
|
+
|
|
250
|
+
### 新增批次(全量 92 组件)
|
|
251
|
+
|
|
252
|
+
| 组件 | 导入名 | 关键 Props | 说明 |
|
|
253
|
+
|-----|--------|-----------|------|
|
|
254
|
+
| Rate | `Rate` | `value`, `count`, `onChange`, `allowClear`, `readOnly`, `size` | 评分(键盘方向键/Home/End) |
|
|
255
|
+
| Typography | `Title` `Text` `Paragraph` | `Title: level 1-5`;`Text: type/strong/underline/strike/mark/code`;`Paragraph: ellipsis` | 语义排版(Title/Text/Paragraph 三组件) |
|
|
256
|
+
| Label | `Label` | `htmlFor`, `required` | 独立标签(必填星号) |
|
|
257
|
+
| AspectRatio | `AspectRatio` | `ratio` | 宽高比容器(内容填满) |
|
|
258
|
+
| Toggle | `Toggle` | `pressed`, `onPressedChange`, `variant`, `size` | 切换按钮(shadcn 对齐) |
|
|
259
|
+
| ToggleGroup | `ToggleGroup` | `type: 'single'\|'multiple'`, `options`, `value`, `onChange` | 切换组 |
|
|
260
|
+
| CheckboxGroup | `CheckboxGroup` | `options`, `value: string[]`, `onChange`, `cols` | 复选框组(栅格列数) |
|
|
261
|
+
| PinInput | `PinInput` | `length`, `value`, `onChange`, `type` | 验证码输入(自动聚焦/粘贴分派/回退) |
|
|
262
|
+
| CopyButton | `CopyButton` | `value`, `label`, `onCopy` | 复制按钮(clipboard + execCommand 降级) |
|
|
263
|
+
| ColorPicker | `ColorPicker` | `value`, `onChange`, `showInput`, `preset` | 颜色选择(预设色板 + hex 输入) |
|
|
264
|
+
| HoverCard | `HoverCard` | `content`, `position`, `openDelay`, `closeDelay` | 悬停富内容卡(shadcn) |
|
|
265
|
+
| Notification | `Notification` | 命令式 `notification.success/error/warning/open` | 队列式通知(antd 对齐) |
|
|
266
|
+
| BackTop | `BackTop` | `visibilityHeight`, `target`, `smooth` | 回到顶部(滚动超阈值显示) |
|
|
267
|
+
| Affix | `Affix` | `offsetTop`, `target` | 固定定位(滚动超阈值钉住) |
|
|
268
|
+
| ContextMenu | `ContextMenu` | `items: ContextMenuItem[]`(`{ label, onClick, variant: 'danger' }`) | 右键菜单(光标定位 + 方向键) |
|
|
269
|
+
| Mentions | `Mentions` | `options: { value, label }[]`, `value`, `onChange`, `prefix` | @提及(composition 抑制) |
|
|
270
|
+
| Collapse | `Collapse` | `items: CollapseItem[]`(`{ key, title, content, loading }`), `active`, `multiple` | 行内折叠(异步 loading) |
|
|
271
|
+
| Tree | `Tree` | `data: TreeNode[]`, `expandedKeys`, `checkedKeys`, `checkable`, `selectedKeys`, `onCheck/onExpand/onSelect` | 树(递归 + 勾选父子联动 + 半选传播) |
|
|
272
|
+
| Cascader | `Cascader` | `options: CascaderOption[]`, `value: string[]`, `onChange` | 级联选择(多列推进) |
|
|
273
|
+
| Transfer | `Transfer` | `data: { key, label }[]`, `targetKeys`, `onChange`, `titles` | 穿梭框(选中 + 批量移动) |
|
|
274
|
+
| Command | `Command` | `items: CommandItem[]`, `open`, `onOpenChange`, `shortcut` | 命令面板(⌘K 全局 + 键盘流) |
|
|
275
|
+
| Menubar | `Menubar` | `menus: { key, label, items }[]` | 水平菜单栏(←→ 切换 + ↓ 展开) |
|
|
276
|
+
| Carousel | `Carousel` | `children`, `autoplay`, `interval`, `loop`, `showArrows/Dots` | 轮播(箭头/圆点/循环/自动播放) |
|
|
277
|
+
| Resizable | `Resizable` | `direction`, `defaultSize`, `min/maxSize` | 拖拽分割面板(pointer + 键盘方向键) |
|
|
278
|
+
| Calendar | `Calendar` | `month`, `year`, `events`, `selectedDate`, `onMonthChange/onSelectDate` | 月历(事件点 + 月切换 + 选日) |
|
|
279
|
+
| Watermark | `Watermark` | `text`, `fontSize`, `rotate`, `zIndex` | 水印(canvas 平铺) |
|
|
280
|
+
| VirtualList | `VirtualList` | `items`, `height`, `itemHeight`, `renderItem`, `overscan` | 虚拟列表(spacer + 可见窗口,1000+ 条) |
|
|
281
|
+
| InfiniteScroll | `InfiniteScroll` | `hasMore`, `loadMore`, `children`, `loader` | 触底加载(IntersectionObserver) |
|
|
282
|
+
| QRCode | `QRCode` | `value`, `ecLevel`, `size`, `color`, `bgColor` | 二维码(自研 Reed-Solomon,版本 1-6) |
|
|
283
|
+
|
|
284
|
+
### 图表
|
|
285
|
+
|
|
286
|
+
| 组件 | 导入名 | 关键 Props | 说明 |
|
|
287
|
+
|-----|--------|-----------|------|
|
|
288
|
+
| Chart | `Chart` | `type: ChartType`, `data`, `options`, `title`, `area` | SVG 图表(line/bar/pie)|
|
|
289
|
+
| DatePicker | `DatePicker` | `mode: DatePickerMode`, `value`, `onChange`, `placeholder`, `disabled` | 日期选择器(date/datetime/time/range)|
|
|
290
|
+
| Editor | `Editor` | `value`, `onChange`, `toolbar`, `placeholder`, `disabled` | 富文本编辑器,零依赖 |
|
|
291
|
+
|
|
292
|
+
### 布局
|
|
293
|
+
|
|
294
|
+
| 组件 | 导入名 | 关键 Props | 说明 |
|
|
295
|
+
|-----|--------|-----------|------|
|
|
296
|
+
| Divider | `Divider` | `vertical` | 分割线(水平带文字放 children,`vertical` 垂直) |
|
|
297
|
+
|
|
298
|
+
### AI 交互原语(wf: 协议配套)
|
|
299
|
+
|
|
300
|
+
| 组件 | 导入名 | 关键 Props | 说明 |
|
|
301
|
+
|-----|--------|-----------|------|
|
|
302
|
+
| AiChat | `AiChat` | `chat`, `maxHeight?`, `labels?`, `renderMessage?`, `renderToolArgs?` | 标准 AI 对话界面:气泡 + 工具卡 + 审批卡 + 自动滚动 + 错误重试(接收 `ctx.ui.useChat()` handle) |
|
|
303
|
+
| MessageBubble | `MessageBubble` | `content`, `role`, `status`, `actions` | 独立消息气泡(业务聊天页复用) |
|
|
304
|
+
| ToolCallCard | `ToolCallCard` | `call`, `progress?`, `result?`, `renderArgs?` | 工具调用卡片:running(进度条)/ ok / error 三态(协议 §4) |
|
|
305
|
+
| ApprovalCard | `ApprovalCard` | `request`, `status?`, `onApprove`, `onReject` | 人工审批卡片:待批(允许/拒绝+备注)/ 已批 / 已拒 / 超时(协议 §4.5) |
|
|
306
|
+
|
|
307
|
+
### 全局工具
|
|
308
|
+
|
|
309
|
+
| 组件 | 导入名 | 关键 Props | 说明 |
|
|
310
|
+
|-----|--------|-----------|------|
|
|
311
|
+
| ThemeSwitch | `ThemeSwitch` | `mode: 'auto'\|'light'\|'dark'`, `onChange`, `storageKey` | 主题切换(auto/light/dark,localStorage 持久化);另有 `applyTheme()` / `getTheme()` 命令式工具 |
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|