@wordrhyme/auto-crud 0.2.0 → 0.4.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 +459 -223
- package/dist/index.cjs +24 -16
- package/dist/index.d.cts +92 -24
- package/dist/index.d.ts +78 -10
- package/dist/index.js +24 -16
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
28
|
# pnpm
|
|
29
|
-
pnpm add @wordrhyme/auto-crud zod
|
|
29
|
+
pnpm add @wordrhyme/auto-crud zod sonner
|
|
30
30
|
|
|
31
31
|
# npm
|
|
32
|
-
npm install @wordrhyme/auto-crud zod
|
|
32
|
+
npm install @wordrhyme/auto-crud zod sonner
|
|
33
33
|
|
|
34
34
|
# yarn
|
|
35
|
-
yarn add @wordrhyme/auto-crud zod
|
|
35
|
+
yarn add @wordrhyme/auto-crud zod sonner
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
### Peer Dependencies
|
|
@@ -41,6 +41,7 @@ yarn add @wordrhyme/auto-crud zod
|
|
|
41
41
|
{
|
|
42
42
|
"react": "^18.0.0 || ^19.0.0",
|
|
43
43
|
"react-dom": "^18.0.0 || ^19.0.0",
|
|
44
|
+
"sonner": "^2.0.0",
|
|
44
45
|
"zod": "^3.0.0 || ^4.0.0"
|
|
45
46
|
}
|
|
46
47
|
```
|
|
@@ -129,14 +130,14 @@ function TasksPage() {
|
|
|
129
130
|
title="任务管理"
|
|
130
131
|
schema={taskSchema}
|
|
131
132
|
resource={resource}
|
|
132
|
-
|
|
133
|
+
fields={{
|
|
133
134
|
id: { hidden: true },
|
|
134
135
|
status: { label: "状态" },
|
|
135
136
|
priority: { label: "优先级" },
|
|
136
137
|
}}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
table={{
|
|
139
|
+
filterModes: ["simple", "advanced", "command"],
|
|
140
|
+
batchFields: ["status", "priority"],
|
|
140
141
|
}}
|
|
141
142
|
/>
|
|
142
143
|
);
|
|
@@ -244,54 +245,34 @@ const dataSource: DataSource<Task> = {
|
|
|
244
245
|
#### Props
|
|
245
246
|
|
|
246
247
|
```typescript
|
|
247
|
-
interface AutoCrudTableProps<
|
|
248
|
+
interface AutoCrudTableProps<TSchema> {
|
|
248
249
|
// 必需
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
resource: AutoCrudResource<TData>; // useAutoCrudResource 返回值
|
|
250
|
+
schema: TSchema; // Zod Schema
|
|
251
|
+
resource: UseAutoCrudResourceReturn<TSchema>; // useAutoCrudResource 返回值
|
|
252
252
|
|
|
253
253
|
// 可选
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
254
|
+
title?: string;
|
|
255
|
+
description?: string;
|
|
256
|
+
fields?: Fields; // 统一字段配置
|
|
257
|
+
table?: {
|
|
258
|
+
hidden?: string[]; // 隐藏的列
|
|
259
|
+
overrides?: Record<string, any>; // 列覆盖配置
|
|
260
|
+
filterModes?: FilterMode | FilterMode[]; // 过滤模式
|
|
261
|
+
batchFields?: (string | BatchUpdateField)[]; // 批量更新字段
|
|
262
|
+
defaultSort?: any[]; // 默认排序
|
|
263
|
+
};
|
|
264
|
+
form?: {
|
|
265
|
+
overrides?: Record<string, any>; // 表单覆盖配置
|
|
266
|
+
columns?: number; // 表单列数
|
|
258
267
|
};
|
|
259
268
|
slots?: {
|
|
260
|
-
|
|
269
|
+
toolbarStart?: React.ReactNode; // 工具栏左侧插槽
|
|
270
|
+
toolbarEnd?: React.ReactNode; // 工具栏右侧插槽
|
|
271
|
+
rowActions?: (row) => Array<{ label: string; onClick: () => void }>;
|
|
261
272
|
};
|
|
262
273
|
}
|
|
263
274
|
```
|
|
264
275
|
|
|
265
|
-
#### 示例
|
|
266
|
-
|
|
267
|
-
```typescript
|
|
268
|
-
<AutoCrudTable
|
|
269
|
-
title="用户管理"
|
|
270
|
-
schema={userSchema}
|
|
271
|
-
resource={resource}
|
|
272
|
-
fieldOverrides={{
|
|
273
|
-
id: { hidden: true },
|
|
274
|
-
email: { label: "邮箱" },
|
|
275
|
-
role: {
|
|
276
|
-
label: "角色",
|
|
277
|
-
table: {
|
|
278
|
-
meta: {
|
|
279
|
-
variant: "select",
|
|
280
|
-
options: [
|
|
281
|
-
{ label: "管理员", value: "admin" },
|
|
282
|
-
{ label: "用户", value: "user" },
|
|
283
|
-
],
|
|
284
|
-
},
|
|
285
|
-
},
|
|
286
|
-
},
|
|
287
|
-
}}
|
|
288
|
-
tableProps={{
|
|
289
|
-
filterMode: ["simple", "advanced"],
|
|
290
|
-
batchUpdateFields: ["role", "status"],
|
|
291
|
-
}}
|
|
292
|
-
/>
|
|
293
|
-
```
|
|
294
|
-
|
|
295
276
|
### `useAutoCrudResource()`
|
|
296
277
|
|
|
297
278
|
连接数据源到组件的 Hook。
|
|
@@ -308,30 +289,44 @@ interface UseAutoCrudResourceConfig<TData> {
|
|
|
308
289
|
#### 返回值
|
|
309
290
|
|
|
310
291
|
```typescript
|
|
311
|
-
interface
|
|
312
|
-
//
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
292
|
+
interface UseAutoCrudResourceReturn<TSchema, TData> {
|
|
293
|
+
// 表格数据
|
|
294
|
+
tableData: {
|
|
295
|
+
data: TData[];
|
|
296
|
+
pageCount: number;
|
|
297
|
+
};
|
|
316
298
|
|
|
317
299
|
// 模态框状态
|
|
318
300
|
modal: {
|
|
319
301
|
variant: "dialog" | "sheet";
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
302
|
+
createOpen: boolean;
|
|
303
|
+
editOpen: boolean;
|
|
304
|
+
viewOpen: boolean;
|
|
305
|
+
deleteOpen: boolean;
|
|
306
|
+
selected: TData | null;
|
|
307
|
+
copySource: TData | null;
|
|
323
308
|
};
|
|
324
309
|
|
|
325
310
|
// 操作方法
|
|
326
311
|
handlers: {
|
|
327
|
-
setVariant: (variant: "dialog" | "sheet") => void;
|
|
328
312
|
openCreate: () => void;
|
|
329
313
|
openEdit: (item: TData) => void;
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
314
|
+
openView: (item: TData) => void;
|
|
315
|
+
openDelete: (item: TData) => void;
|
|
316
|
+
copyRow: (item: TData) => void;
|
|
317
|
+
closeModals: () => void;
|
|
318
|
+
submitCreate: (data: TData) => Promise<void>;
|
|
319
|
+
submitUpdate: (data: TData) => Promise<void>;
|
|
320
|
+
confirmDelete: () => Promise<void>;
|
|
321
|
+
deleteMany: (rows: TData[]) => Promise<void>;
|
|
322
|
+
updateMany: (rows: TData[], data: Record<string, unknown>) => Promise<void>;
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
// 加载状态
|
|
326
|
+
mutations: {
|
|
327
|
+
isCreating: boolean;
|
|
328
|
+
isUpdating: boolean;
|
|
329
|
+
isDeleting: boolean;
|
|
335
330
|
};
|
|
336
331
|
}
|
|
337
332
|
```
|
|
@@ -340,100 +335,147 @@ interface AutoCrudResource<TData> {
|
|
|
340
335
|
|
|
341
336
|
## 🔧 字段配置
|
|
342
337
|
|
|
338
|
+
### Field 类型
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
interface Field {
|
|
342
|
+
/** 字段标签(表格和表单共用) */
|
|
343
|
+
label?: string;
|
|
344
|
+
/** 是否隐藏(表格和表单都隐藏) */
|
|
345
|
+
hidden?: boolean;
|
|
346
|
+
/** 表格特定配置 */
|
|
347
|
+
table?: {
|
|
348
|
+
hidden?: boolean; // 仅表格隐藏
|
|
349
|
+
meta?: Record<string, unknown>; // 筛选器配置
|
|
350
|
+
[key: string]: unknown;
|
|
351
|
+
};
|
|
352
|
+
/** 表单特定配置 */
|
|
353
|
+
form?: {
|
|
354
|
+
"x-hidden"?: boolean; // 仅表单隐藏
|
|
355
|
+
"x-component"?: string; // 组件类型
|
|
356
|
+
"x-component-props"?: Record<string, unknown>; // 组件属性
|
|
357
|
+
"x-reactions"?: object; // 字段联动
|
|
358
|
+
[key: string]: unknown;
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
type Fields = Record<string, Field>;
|
|
363
|
+
```
|
|
364
|
+
|
|
343
365
|
### 基础配置
|
|
344
366
|
|
|
345
367
|
```typescript
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
}
|
|
368
|
+
<AutoCrudTable
|
|
369
|
+
schema={taskSchema}
|
|
370
|
+
resource={resource}
|
|
371
|
+
fields={{
|
|
372
|
+
id: { hidden: true }, // 表格和表单都隐藏
|
|
373
|
+
title: { label: "标题" }, // 自定义标签
|
|
374
|
+
createdAt: {
|
|
375
|
+
label: "创建时间",
|
|
376
|
+
form: { "x-hidden": true }, // 仅表单隐藏
|
|
377
|
+
},
|
|
378
|
+
}}
|
|
379
|
+
/>
|
|
352
380
|
```
|
|
353
381
|
|
|
354
|
-
###
|
|
382
|
+
### 表格筛选器配置
|
|
355
383
|
|
|
356
384
|
```typescript
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
385
|
+
<AutoCrudTable
|
|
386
|
+
schema={taskSchema}
|
|
387
|
+
resource={resource}
|
|
388
|
+
fields={{
|
|
389
|
+
status: {
|
|
390
|
+
label: "状态",
|
|
391
|
+
table: {
|
|
392
|
+
meta: {
|
|
393
|
+
variant: "select", // "text" | "select" | "multiSelect" | "date" | "dateRange" | "range"
|
|
394
|
+
options: [
|
|
395
|
+
{ label: "待处理", value: "pending" },
|
|
396
|
+
{ label: "已完成", value: "completed" },
|
|
397
|
+
],
|
|
398
|
+
},
|
|
364
399
|
},
|
|
365
400
|
},
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
{ label: "已完成", value: "completed" },
|
|
375
|
-
],
|
|
401
|
+
amount: {
|
|
402
|
+
label: "金额",
|
|
403
|
+
table: {
|
|
404
|
+
meta: {
|
|
405
|
+
variant: "range",
|
|
406
|
+
range: [0, 10000],
|
|
407
|
+
unit: "¥",
|
|
408
|
+
},
|
|
376
409
|
},
|
|
377
410
|
},
|
|
378
|
-
}
|
|
379
|
-
|
|
411
|
+
}}
|
|
412
|
+
/>
|
|
380
413
|
```
|
|
381
414
|
|
|
382
|
-
###
|
|
415
|
+
### 表单组件配置
|
|
383
416
|
|
|
384
417
|
```typescript
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
"
|
|
418
|
+
<AutoCrudTable
|
|
419
|
+
schema={taskSchema}
|
|
420
|
+
resource={resource}
|
|
421
|
+
fields={{
|
|
422
|
+
description: {
|
|
423
|
+
label: "描述",
|
|
424
|
+
form: {
|
|
425
|
+
"x-component": "Textarea",
|
|
426
|
+
"x-component-props": { rows: 5 },
|
|
427
|
+
},
|
|
391
428
|
},
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
429
|
+
assignee: {
|
|
430
|
+
label: "负责人",
|
|
431
|
+
form: {
|
|
432
|
+
"x-component": "Combobox",
|
|
433
|
+
"x-component-props": { placeholder: "选择负责人" },
|
|
434
|
+
},
|
|
397
435
|
},
|
|
398
|
-
}
|
|
399
|
-
|
|
436
|
+
}}
|
|
437
|
+
/>
|
|
400
438
|
```
|
|
401
439
|
|
|
402
440
|
### 字段联动
|
|
403
441
|
|
|
404
442
|
```typescript
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
443
|
+
<AutoCrudTable
|
|
444
|
+
schema={taskSchema}
|
|
445
|
+
resource={resource}
|
|
446
|
+
fields={{
|
|
447
|
+
endDate: {
|
|
448
|
+
label: "结束日期",
|
|
449
|
+
form: {
|
|
450
|
+
"x-reactions": {
|
|
451
|
+
dependencies: ["startDate"],
|
|
452
|
+
when: "{{$deps[0] !== undefined}}",
|
|
453
|
+
fulfill: {
|
|
454
|
+
state: {
|
|
455
|
+
visible: true,
|
|
456
|
+
disabled: false,
|
|
457
|
+
},
|
|
416
458
|
},
|
|
417
459
|
},
|
|
418
460
|
},
|
|
419
461
|
},
|
|
420
|
-
}
|
|
421
|
-
|
|
462
|
+
}}
|
|
463
|
+
/>
|
|
422
464
|
```
|
|
423
465
|
|
|
424
466
|
---
|
|
425
467
|
|
|
426
468
|
## 🎯 过滤模式
|
|
427
469
|
|
|
428
|
-
### Simple
|
|
470
|
+
### Simple 模式(默认)
|
|
429
471
|
|
|
430
472
|
- 适合:快速筛选常用字段
|
|
431
473
|
- 特点:下拉选择框,一键清除
|
|
432
474
|
- 示例:状态筛选、优先级筛选
|
|
433
475
|
|
|
434
476
|
```typescript
|
|
435
|
-
|
|
436
|
-
|
|
477
|
+
table={{
|
|
478
|
+
filterModes: "simple",
|
|
437
479
|
}}
|
|
438
480
|
```
|
|
439
481
|
|
|
@@ -444,8 +486,8 @@ tableProps={{
|
|
|
444
486
|
- 示例:`status = "done" AND priority = "high"`
|
|
445
487
|
|
|
446
488
|
```typescript
|
|
447
|
-
|
|
448
|
-
|
|
489
|
+
table={{
|
|
490
|
+
filterModes: "advanced",
|
|
449
491
|
}}
|
|
450
492
|
```
|
|
451
493
|
|
|
@@ -456,16 +498,16 @@ tableProps={{
|
|
|
456
498
|
- 示例:快速搜索并添加筛选条件
|
|
457
499
|
|
|
458
500
|
```typescript
|
|
459
|
-
|
|
460
|
-
|
|
501
|
+
table={{
|
|
502
|
+
filterModes: "command",
|
|
461
503
|
}}
|
|
462
504
|
```
|
|
463
505
|
|
|
464
506
|
### 多模式切换
|
|
465
507
|
|
|
466
508
|
```typescript
|
|
467
|
-
|
|
468
|
-
|
|
509
|
+
table={{
|
|
510
|
+
filterModes: ["simple", "advanced", "command"], // 第一个为默认模式
|
|
469
511
|
}}
|
|
470
512
|
```
|
|
471
513
|
|
|
@@ -479,8 +521,8 @@ tableProps={{
|
|
|
479
521
|
<AutoCrudTable
|
|
480
522
|
schema={taskSchema}
|
|
481
523
|
resource={resource}
|
|
482
|
-
|
|
483
|
-
|
|
524
|
+
table={{
|
|
525
|
+
batchFields: ["status", "priority"],
|
|
484
526
|
}}
|
|
485
527
|
/>
|
|
486
528
|
```
|
|
@@ -506,162 +548,334 @@ tableProps={{
|
|
|
506
548
|
|
|
507
549
|
---
|
|
508
550
|
|
|
509
|
-
##
|
|
551
|
+
## 🔌 与其他库集成
|
|
510
552
|
|
|
511
|
-
###
|
|
553
|
+
### 与 Drizzle ORM 集成
|
|
512
554
|
|
|
513
555
|
```typescript
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
556
|
+
import { createSelectSchema } from "drizzle-zod";
|
|
557
|
+
import { tasks } from "@/db/schema";
|
|
558
|
+
|
|
559
|
+
const taskSchema = createSelectSchema(tasks);
|
|
560
|
+
|
|
561
|
+
<AutoCrudTable schema={taskSchema} resource={resource} />
|
|
519
562
|
```
|
|
520
563
|
|
|
521
|
-
###
|
|
564
|
+
### 与 Next.js 集成
|
|
522
565
|
|
|
523
566
|
```typescript
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
</div>
|
|
533
|
-
),
|
|
534
|
-
}}
|
|
535
|
-
/>
|
|
567
|
+
// app/tasks/page.tsx
|
|
568
|
+
"use client";
|
|
569
|
+
|
|
570
|
+
import { AutoCrudTable } from "@wordrhyme/auto-crud";
|
|
571
|
+
|
|
572
|
+
export default function TasksPage() {
|
|
573
|
+
return <AutoCrudTable schema={taskSchema} resource={resource} />;
|
|
574
|
+
}
|
|
536
575
|
```
|
|
537
576
|
|
|
538
577
|
---
|
|
539
578
|
|
|
540
|
-
##
|
|
579
|
+
## 🧰 工具函数
|
|
580
|
+
|
|
581
|
+
### Schema Bridge - 核心转换函数
|
|
582
|
+
|
|
583
|
+
```typescript
|
|
584
|
+
import {
|
|
585
|
+
parseZodField, // 解析 Zod 字段类型
|
|
586
|
+
createTableSchema, // Zod Schema → TanStack Table 列定义
|
|
587
|
+
createSelectColumn, // 创建选择列
|
|
588
|
+
createActionsColumn, // 创建操作列
|
|
589
|
+
createFormSchema, // Zod Schema → Formily Schema
|
|
590
|
+
createEditFormSchema, // 创建编辑表单 Schema(排除 id, createdAt, updatedAt)
|
|
591
|
+
} from "@wordrhyme/auto-crud";
|
|
592
|
+
```
|
|
541
593
|
|
|
542
594
|
### 自定义列渲染
|
|
543
595
|
|
|
596
|
+
使用 `createTableSchema` 的 `overrides` 参数自定义列渲染:
|
|
597
|
+
|
|
544
598
|
```typescript
|
|
545
|
-
import {
|
|
599
|
+
import { createTableSchema } from "@wordrhyme/auto-crud";
|
|
600
|
+
import { Badge } from "@shadcn/ui";
|
|
546
601
|
|
|
547
|
-
const columns =
|
|
602
|
+
const columns = createTableSchema(taskSchema, {
|
|
548
603
|
overrides: {
|
|
549
604
|
status: {
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
605
|
+
label: "状态",
|
|
606
|
+
// 自定义 cell 渲染
|
|
607
|
+
cell: ({ row }) => {
|
|
608
|
+
const status = row.getValue("status");
|
|
609
|
+
return (
|
|
610
|
+
<Badge variant={status === "done" ? "success" : "secondary"}>
|
|
611
|
+
{status}
|
|
612
|
+
</Badge>
|
|
613
|
+
);
|
|
614
|
+
},
|
|
615
|
+
},
|
|
616
|
+
priority: {
|
|
617
|
+
label: "优先级",
|
|
618
|
+
// 自定义列配置
|
|
619
|
+
size: 100,
|
|
620
|
+
enableSorting: false,
|
|
555
621
|
},
|
|
556
622
|
},
|
|
623
|
+
exclude: ["id", "createdAt"], // 排除字段
|
|
557
624
|
});
|
|
558
625
|
```
|
|
559
626
|
|
|
560
|
-
###
|
|
627
|
+
### 自定义表单渲染
|
|
628
|
+
|
|
629
|
+
使用 `createFormSchema` 的 `overrides` 参数自定义表单组件:
|
|
561
630
|
|
|
562
631
|
```typescript
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
632
|
+
import { createFormSchema } from "@wordrhyme/auto-crud";
|
|
633
|
+
|
|
634
|
+
const formSchema = createFormSchema(taskSchema, {
|
|
635
|
+
overrides: {
|
|
636
|
+
description: {
|
|
637
|
+
"x-component": "Textarea",
|
|
638
|
+
"x-component-props": { rows: 5 },
|
|
639
|
+
},
|
|
640
|
+
status: {
|
|
641
|
+
"x-component": "Select",
|
|
568
642
|
"x-component-props": {
|
|
569
|
-
|
|
570
|
-
|
|
643
|
+
options: [
|
|
644
|
+
{ label: "待办", value: "todo" },
|
|
645
|
+
{ label: "完成", value: "done" },
|
|
646
|
+
],
|
|
571
647
|
},
|
|
572
648
|
},
|
|
649
|
+
dueDate: {
|
|
650
|
+
"x-component": "DatePicker",
|
|
651
|
+
"x-component-props": { format: "YYYY-MM-DD" },
|
|
652
|
+
},
|
|
573
653
|
},
|
|
574
|
-
|
|
654
|
+
layout: "grid",
|
|
655
|
+
gridColumns: 2,
|
|
656
|
+
exclude: ["id", "createdAt"],
|
|
657
|
+
});
|
|
575
658
|
```
|
|
576
659
|
|
|
577
|
-
|
|
660
|
+
---
|
|
661
|
+
|
|
662
|
+
## 🔀 三种 Schema 类型
|
|
663
|
+
|
|
664
|
+
`@wordrhyme/auto-crud` 支持三种 Schema 输入格式,通过 `SchemaAdapter` 统一处理:
|
|
665
|
+
|
|
666
|
+
### 1. Zod Schema(推荐)
|
|
578
667
|
|
|
579
668
|
```typescript
|
|
580
|
-
|
|
581
|
-
page: parseAsInteger.withDefault(1),
|
|
582
|
-
perPage: parseAsInteger.withDefault(10),
|
|
583
|
-
});
|
|
669
|
+
import { z } from "zod";
|
|
584
670
|
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
|
|
671
|
+
const taskSchema = z.object({
|
|
672
|
+
id: z.string(),
|
|
673
|
+
title: z.string(),
|
|
674
|
+
status: z.enum(["todo", "in-progress", "done"]),
|
|
675
|
+
priority: z.enum(["low", "medium", "high"]),
|
|
676
|
+
createdAt: z.date(),
|
|
588
677
|
});
|
|
589
678
|
```
|
|
590
679
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
## 🔌 与其他库集成
|
|
594
|
-
|
|
595
|
-
### 与 Drizzle ORM 集成
|
|
680
|
+
### 2. JSON Schema
|
|
596
681
|
|
|
597
682
|
```typescript
|
|
598
|
-
import {
|
|
599
|
-
import { tasks } from "@/db/schema";
|
|
683
|
+
import type { JSONSchema } from "@wordrhyme/auto-crud";
|
|
600
684
|
|
|
601
|
-
const taskSchema =
|
|
602
|
-
|
|
603
|
-
|
|
685
|
+
const taskSchema: JSONSchema = {
|
|
686
|
+
type: "object",
|
|
687
|
+
properties: {
|
|
688
|
+
id: { type: "string" },
|
|
689
|
+
title: { type: "string", title: "标题" },
|
|
690
|
+
status: {
|
|
691
|
+
type: "string",
|
|
692
|
+
enum: ["todo", "in-progress", "done"],
|
|
693
|
+
title: "状态",
|
|
694
|
+
},
|
|
695
|
+
createdAt: { type: "string", format: "date-time" },
|
|
696
|
+
},
|
|
697
|
+
required: ["id", "title"],
|
|
698
|
+
};
|
|
604
699
|
```
|
|
605
700
|
|
|
606
|
-
###
|
|
701
|
+
### 3. 简化配置(Simple Config)
|
|
607
702
|
|
|
608
703
|
```typescript
|
|
609
|
-
import {
|
|
610
|
-
import { useForm } from "react-hook-form";
|
|
704
|
+
import type { SimpleFieldsConfig } from "@wordrhyme/auto-crud";
|
|
611
705
|
|
|
612
|
-
const
|
|
613
|
-
|
|
614
|
-
}
|
|
706
|
+
const taskSchema: SimpleFieldsConfig = {
|
|
707
|
+
id: { type: "string", required: true },
|
|
708
|
+
title: { type: "string", label: "标题", required: true },
|
|
709
|
+
status: {
|
|
710
|
+
type: "select",
|
|
711
|
+
label: "状态",
|
|
712
|
+
options: ["todo", "in-progress", "done"],
|
|
713
|
+
},
|
|
714
|
+
description: { type: "textarea", label: "描述" },
|
|
715
|
+
createdAt: { type: "datetime" },
|
|
716
|
+
};
|
|
615
717
|
```
|
|
616
718
|
|
|
617
|
-
###
|
|
719
|
+
### SchemaAdapter 使用
|
|
618
720
|
|
|
619
721
|
```typescript
|
|
620
|
-
|
|
621
|
-
"use client";
|
|
722
|
+
import { SchemaAdapter } from "@wordrhyme/auto-crud";
|
|
622
723
|
|
|
623
|
-
|
|
724
|
+
// 自动检测 Schema 类型
|
|
725
|
+
const type = SchemaAdapter.detectType(schema); // "zod" | "json" | "simple"
|
|
624
726
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
727
|
+
// 转换为统一的字段定义
|
|
728
|
+
const fields = SchemaAdapter.toUnified(schema);
|
|
729
|
+
|
|
730
|
+
// 转换为 Formily Schema
|
|
731
|
+
const formilySchema = SchemaAdapter.toFormily(fields);
|
|
628
732
|
```
|
|
629
733
|
|
|
630
734
|
---
|
|
631
735
|
|
|
632
|
-
##
|
|
736
|
+
## 🧩 基础组件(自定义组合)
|
|
737
|
+
|
|
738
|
+
如果 `AutoCrudTable` 不能满足需求,可以使用基础组件自行组合:
|
|
633
739
|
|
|
634
|
-
###
|
|
740
|
+
### 组件层级
|
|
741
|
+
|
|
742
|
+
```
|
|
743
|
+
AutoCrudTable ← 高级封装,一站式 CRUD
|
|
744
|
+
├── AutoTable ← 表格 + 工具栏 + 筛选器
|
|
745
|
+
│ ├── DataTable ← 纯表格组件(TanStack Table)
|
|
746
|
+
│ ├── AutoTableActionBar ← 批量操作栏
|
|
747
|
+
│ └── AutoTableSimpleFilters ← 简单筛选器
|
|
748
|
+
├── AutoForm ← 表单组件(Formily)
|
|
749
|
+
└── CrudFormModal ← 表单弹窗(创建/编辑/查看)
|
|
750
|
+
```
|
|
635
751
|
|
|
636
|
-
|
|
752
|
+
### 使用 DataTable 组件
|
|
637
753
|
|
|
638
754
|
```typescript
|
|
639
|
-
import {
|
|
755
|
+
import { DataTable, createTableSchema, createSelectColumn, createActionsColumn } from "@wordrhyme/auto-crud";
|
|
756
|
+
|
|
757
|
+
function CustomTable({ data }) {
|
|
758
|
+
const columns = [
|
|
759
|
+
createSelectColumn(),
|
|
760
|
+
...createTableSchema(taskSchema, { exclude: ["id"] }),
|
|
761
|
+
createActionsColumn({
|
|
762
|
+
onEdit: (row) => console.log("Edit", row),
|
|
763
|
+
onDelete: (row) => console.log("Delete", row),
|
|
764
|
+
onView: (row) => console.log("View", row),
|
|
765
|
+
onCopy: (row) => console.log("Copy", row),
|
|
766
|
+
}),
|
|
767
|
+
];
|
|
640
768
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
769
|
+
return (
|
|
770
|
+
<DataTable
|
|
771
|
+
columns={columns}
|
|
772
|
+
data={data}
|
|
773
|
+
pageCount={10}
|
|
774
|
+
/>
|
|
775
|
+
);
|
|
776
|
+
}
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
### 使用 AutoForm 组件
|
|
780
|
+
|
|
781
|
+
```typescript
|
|
782
|
+
import { AutoForm, createFormSchema } from "@wordrhyme/auto-crud";
|
|
783
|
+
import { createForm } from "@formily/core";
|
|
784
|
+
|
|
785
|
+
function CustomForm() {
|
|
786
|
+
const form = createForm();
|
|
787
|
+
const formSchema = createFormSchema(taskSchema, {
|
|
788
|
+
exclude: ["id", "createdAt"],
|
|
789
|
+
layout: "grid",
|
|
790
|
+
gridColumns: 2,
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
return (
|
|
794
|
+
<AutoForm
|
|
795
|
+
form={form}
|
|
796
|
+
schema={formSchema}
|
|
797
|
+
onSubmit={(values) => console.log(values)}
|
|
798
|
+
/>
|
|
799
|
+
);
|
|
800
|
+
}
|
|
652
801
|
```
|
|
653
802
|
|
|
654
|
-
###
|
|
803
|
+
### 使用 useDataTable Hook
|
|
804
|
+
|
|
805
|
+
```typescript
|
|
806
|
+
import { useDataTable, DataTable, DataTablePagination } from "@wordrhyme/auto-crud";
|
|
807
|
+
|
|
808
|
+
function CustomDataTable({ data, pageCount }) {
|
|
809
|
+
const { table } = useDataTable({
|
|
810
|
+
data,
|
|
811
|
+
columns,
|
|
812
|
+
pageCount,
|
|
813
|
+
initialState: {
|
|
814
|
+
pagination: { pageIndex: 0, pageSize: 10 },
|
|
815
|
+
sorting: [{ id: "createdAt", desc: true }],
|
|
816
|
+
},
|
|
817
|
+
});
|
|
818
|
+
|
|
819
|
+
return (
|
|
820
|
+
<div>
|
|
821
|
+
<DataTable table={table} />
|
|
822
|
+
<DataTablePagination table={table} />
|
|
823
|
+
</div>
|
|
824
|
+
);
|
|
825
|
+
}
|
|
826
|
+
```
|
|
655
827
|
|
|
656
|
-
|
|
828
|
+
### 组件组合示例
|
|
657
829
|
|
|
658
830
|
```typescript
|
|
659
|
-
import {
|
|
831
|
+
import {
|
|
832
|
+
AutoTable,
|
|
833
|
+
AutoForm,
|
|
834
|
+
CrudFormModal,
|
|
835
|
+
useAutoCrudResource,
|
|
836
|
+
createTableSchema,
|
|
837
|
+
createFormSchema,
|
|
838
|
+
} from "@wordrhyme/auto-crud";
|
|
839
|
+
|
|
840
|
+
function CustomCrudPage() {
|
|
841
|
+
const resource = useAutoCrudResource({ dataSource, schema: taskSchema });
|
|
842
|
+
|
|
843
|
+
const columns = createTableSchema(taskSchema, {
|
|
844
|
+
overrides: {
|
|
845
|
+
status: {
|
|
846
|
+
cell: ({ row }) => <StatusBadge status={row.getValue("status")} />,
|
|
847
|
+
},
|
|
848
|
+
},
|
|
849
|
+
});
|
|
660
850
|
|
|
661
|
-
const formSchema = createFormSchema(taskSchema, {
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
851
|
+
const formSchema = createFormSchema(taskSchema, {
|
|
852
|
+
exclude: ["id", "createdAt", "updatedAt"],
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
return (
|
|
856
|
+
<div>
|
|
857
|
+
{/* 自定义表格 */}
|
|
858
|
+
<AutoTable
|
|
859
|
+
columns={columns}
|
|
860
|
+
data={resource.tableData.data}
|
|
861
|
+
pageCount={resource.tableData.pageCount}
|
|
862
|
+
filterMode="simple"
|
|
863
|
+
/>
|
|
864
|
+
|
|
865
|
+
{/* 自定义表单弹窗 */}
|
|
866
|
+
<CrudFormModal
|
|
867
|
+
mode={resource.modal.editOpen ? "edit" : "create"}
|
|
868
|
+
open={resource.modal.createOpen || resource.modal.editOpen}
|
|
869
|
+
onClose={resource.handlers.closeModals}
|
|
870
|
+
schema={formSchema}
|
|
871
|
+
initialValues={resource.modal.selected}
|
|
872
|
+
onSubmit={resource.modal.editOpen
|
|
873
|
+
? resource.handlers.submitUpdate
|
|
874
|
+
: resource.handlers.submitCreate}
|
|
875
|
+
/>
|
|
876
|
+
</div>
|
|
877
|
+
);
|
|
878
|
+
}
|
|
665
879
|
```
|
|
666
880
|
|
|
667
881
|
---
|
|
@@ -669,27 +883,49 @@ const formSchema = createFormSchema(taskSchema, {
|
|
|
669
883
|
## 📦 导出的类型
|
|
670
884
|
|
|
671
885
|
```typescript
|
|
672
|
-
// 组件
|
|
886
|
+
// Auto-CRUD 组件
|
|
673
887
|
export { AutoCrudTable } from "./components/auto-crud/auto-crud-table";
|
|
888
|
+
export type { Field, Fields, AutoCrudTableProps } from "./components/auto-crud/auto-crud-table";
|
|
674
889
|
export { AutoForm } from "./components/auto-crud/auto-form";
|
|
675
890
|
export { AutoTable } from "./components/auto-crud/auto-table";
|
|
891
|
+
export { AutoTableActionBar } from "./components/auto-crud/auto-table-action-bar";
|
|
892
|
+
export { AutoTableSimpleFilters } from "./components/auto-crud/auto-table-simple-filters";
|
|
893
|
+
export { CrudFormModal } from "./components/auto-crud/crud-form-modal";
|
|
894
|
+
|
|
895
|
+
// 数据表格组件
|
|
896
|
+
export { DataTable } from "./components/data-table/data-table";
|
|
897
|
+
export { DataTableAdvancedToolbar } from "./components/data-table/data-table-advanced-toolbar";
|
|
898
|
+
export { DataTableColumnHeader } from "./components/data-table/data-table-column-header";
|
|
899
|
+
export { DataTableFacetedFilter } from "./components/data-table/data-table-faceted-filter";
|
|
900
|
+
export { DataTablePagination } from "./components/data-table/data-table-pagination";
|
|
901
|
+
export { DataTableToolbar } from "./components/data-table/data-table-toolbar";
|
|
902
|
+
export { DataTableViewOptions } from "./components/data-table/data-table-view-options";
|
|
676
903
|
|
|
677
904
|
// Hooks
|
|
678
|
-
export { useAutoCrudResource } from "./hooks/use-auto-crud-resource";
|
|
905
|
+
export { useAutoCrudResource, noopToastAdapter } from "./hooks/use-auto-crud-resource";
|
|
906
|
+
export type { ToastAdapter, CrudHooks, UseAutoCrudResourceOptions } from "./hooks/use-auto-crud-resource";
|
|
679
907
|
export { useDataTable } from "./hooks/use-data-table";
|
|
908
|
+
export { useReadableFilters } from "./hooks/use-readable-filters";
|
|
909
|
+
export { useUrlState, useQueryState, useQueryStates } from "./hooks/use-url-state";
|
|
910
|
+
|
|
911
|
+
// Schema Bridge - 核心工具
|
|
912
|
+
export { parseZodField, createTableSchema, createSelectColumn, createActionsColumn } from "./lib/schema-bridge/zod-to-columns";
|
|
913
|
+
export { createFormSchema, createEditFormSchema } from "./lib/schema-bridge/zod-to-formily";
|
|
914
|
+
export { SchemaAdapter } from "./lib/schema-bridge/schema-adapter";
|
|
915
|
+
export type {
|
|
916
|
+
ColumnOverrides, FormSchemaOverrides,
|
|
917
|
+
CreateTableSchemaOptions, CreateFormSchemaOptions,
|
|
918
|
+
UnifiedSchema, JSONSchema, SimpleFieldsConfig, UnifiedField,
|
|
919
|
+
} from "./lib/schema-bridge";
|
|
680
920
|
|
|
681
921
|
// 数据源
|
|
682
922
|
export { createTRPCDataSource, createMemoryDataSource } from "./lib/data-source";
|
|
683
923
|
export type { DataSource, ListParams, ListResult } from "./lib/data-source";
|
|
684
924
|
|
|
685
925
|
// 工具函数
|
|
686
|
-
export {
|
|
687
|
-
export
|
|
688
|
-
|
|
689
|
-
FieldOverride,
|
|
690
|
-
CreateColumnsOptions,
|
|
691
|
-
CreateFormSchemaOptions,
|
|
692
|
-
} from "./lib/schema-bridge";
|
|
926
|
+
export { cn } from "./lib/utils";
|
|
927
|
+
export { formatDate } from "./lib/format";
|
|
928
|
+
export { humanize } from "./lib/humanize";
|
|
693
929
|
```
|
|
694
930
|
|
|
695
931
|
---
|