@wordrhyme/auto-crud 0.2.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/LICENSE +21 -0
- package/README.md +724 -0
- package/dist/index.cjs +6065 -0
- package/dist/index.d.cts +1165 -0
- package/dist/index.d.ts +1165 -0
- package/dist/index.js +5985 -0
- package/package.json +104 -0
package/README.md
ADDED
|
@@ -0,0 +1,724 @@
|
|
|
1
|
+
# @wordrhyme/auto-crud
|
|
2
|
+
|
|
3
|
+
> Schema-first CRUD components with auto-generated tables and forms
|
|
4
|
+
|
|
5
|
+
基于 Zod Schema 自动生成完整 CRUD 界面的低代码 React 组件库。
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@wordrhyme/auto-crud)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## ✨ 特性
|
|
13
|
+
|
|
14
|
+
- 🚀 **零配置 CRUD**: 从 Zod Schema 自动生成表格和表单
|
|
15
|
+
- 🎨 **高级数据表格**: 基于 TanStack Table,支持排序、过滤、分页
|
|
16
|
+
- 📝 **智能表单**: 集成 Formily,支持复杂表单联动
|
|
17
|
+
- 🔌 **灵活集成**: 支持 tRPC、REST API 或内存数据源
|
|
18
|
+
- 🎯 **类型安全**: 完整的 TypeScript 类型推断
|
|
19
|
+
- 🌐 **URL 状态同步**: 使用 nuqs 实现 URL 状态管理
|
|
20
|
+
- 🎭 **三种过滤模式**: Simple / Advanced / Command
|
|
21
|
+
- 🔄 **批量操作**: 支持批量更新和删除
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 📦 安装
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# pnpm
|
|
29
|
+
pnpm add @wordrhyme/auto-crud zod
|
|
30
|
+
|
|
31
|
+
# npm
|
|
32
|
+
npm install @wordrhyme/auto-crud zod
|
|
33
|
+
|
|
34
|
+
# yarn
|
|
35
|
+
yarn add @wordrhyme/auto-crud zod
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Peer Dependencies
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
43
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
44
|
+
"zod": "^3.0.0 || ^4.0.0"
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 🚀 快速开始
|
|
51
|
+
|
|
52
|
+
### 基础示例
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { AutoCrudTable, useAutoCrudResource, createMemoryDataSource } from "@wordrhyme/auto-crud";
|
|
56
|
+
import { z } from "zod";
|
|
57
|
+
|
|
58
|
+
// 1. 定义 Zod Schema
|
|
59
|
+
const taskSchema = z.object({
|
|
60
|
+
id: z.string(),
|
|
61
|
+
title: z.string(),
|
|
62
|
+
status: z.enum(["todo", "in-progress", "done"]),
|
|
63
|
+
priority: z.enum(["low", "medium", "high"]),
|
|
64
|
+
createdAt: z.date(),
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
type Task = z.infer<typeof taskSchema>;
|
|
68
|
+
|
|
69
|
+
// 2. 创建数据源
|
|
70
|
+
const dataSource = createMemoryDataSource<Task>({
|
|
71
|
+
data: [
|
|
72
|
+
{ id: "1", title: "Task 1", status: "todo", priority: "high", createdAt: new Date() },
|
|
73
|
+
{ id: "2", title: "Task 2", status: "done", priority: "low", createdAt: new Date() },
|
|
74
|
+
],
|
|
75
|
+
onCreate: async (data) => { /* 创建逻辑 */ },
|
|
76
|
+
onUpdate: async (id, data) => { /* 更新逻辑 */ },
|
|
77
|
+
onDelete: async (id) => { /* 删除逻辑 */ },
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// 3. 使用组件
|
|
81
|
+
function TasksPage() {
|
|
82
|
+
const resource = useAutoCrudResource({
|
|
83
|
+
dataSource,
|
|
84
|
+
schema: taskSchema,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<AutoCrudTable
|
|
89
|
+
title="任务管理"
|
|
90
|
+
schema={taskSchema}
|
|
91
|
+
resource={resource}
|
|
92
|
+
/>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 与 tRPC 集成
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import { AutoCrudTable, useAutoCrudResource, createTRPCDataSource } from "@wordrhyme/auto-crud";
|
|
101
|
+
import { trpc } from "@/lib/trpc/client";
|
|
102
|
+
import { createSelectSchema } from "drizzle-zod";
|
|
103
|
+
import { tasks } from "@/db/schema";
|
|
104
|
+
|
|
105
|
+
const taskSchema = createSelectSchema(tasks);
|
|
106
|
+
|
|
107
|
+
function TasksPage() {
|
|
108
|
+
// URL 状态管理
|
|
109
|
+
const [queryParams] = useQueryStates({
|
|
110
|
+
page: parseAsInteger.withDefault(1),
|
|
111
|
+
perPage: parseAsInteger.withDefault(10),
|
|
112
|
+
sort: getSortingStateParser().withDefault([]),
|
|
113
|
+
filters: getFiltersStateParser().withDefault([]),
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// 创建 tRPC 数据源
|
|
117
|
+
const dataSource = createTRPCDataSource({
|
|
118
|
+
router: trpc.tasks,
|
|
119
|
+
queryInput: queryParams,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const resource = useAutoCrudResource({
|
|
123
|
+
dataSource,
|
|
124
|
+
schema: taskSchema,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<AutoCrudTable
|
|
129
|
+
title="任务管理"
|
|
130
|
+
schema={taskSchema}
|
|
131
|
+
resource={resource}
|
|
132
|
+
fieldOverrides={{
|
|
133
|
+
id: { hidden: true },
|
|
134
|
+
status: { label: "状态" },
|
|
135
|
+
priority: { label: "优先级" },
|
|
136
|
+
}}
|
|
137
|
+
tableProps={{
|
|
138
|
+
filterMode: ["simple", "advanced", "command"],
|
|
139
|
+
batchUpdateFields: ["status", "priority"],
|
|
140
|
+
}}
|
|
141
|
+
/>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 📖 核心概念
|
|
149
|
+
|
|
150
|
+
### Schema First 理念
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
Zod Schema → 自动推断字段类型 → 生成表格列 + 表单字段
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**优势**:
|
|
157
|
+
- ✅ 单一数据源(SSOT)
|
|
158
|
+
- ✅ 类型安全
|
|
159
|
+
- ✅ 零手动配置
|
|
160
|
+
- ✅ Schema 变更自动同步
|
|
161
|
+
|
|
162
|
+
### 数据源(Data Source)
|
|
163
|
+
|
|
164
|
+
`@wordrhyme/auto-crud` 支持三种数据源:
|
|
165
|
+
|
|
166
|
+
#### 1. 内存数据源(Memory Data Source)
|
|
167
|
+
|
|
168
|
+
适合:原型开发、演示、测试
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { createMemoryDataSource } from "@wordrhyme/auto-crud";
|
|
172
|
+
|
|
173
|
+
const dataSource = createMemoryDataSource({
|
|
174
|
+
data: initialData,
|
|
175
|
+
onCreate: async (data) => { /* ... */ },
|
|
176
|
+
onUpdate: async (id, data) => { /* ... */ },
|
|
177
|
+
onDelete: async (id) => { /* ... */ },
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### 2. tRPC 数据源(tRPC Data Source)
|
|
182
|
+
|
|
183
|
+
适合:全栈 TypeScript 项目
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import { createTRPCDataSource } from "@wordrhyme/auto-crud";
|
|
187
|
+
|
|
188
|
+
const dataSource = createTRPCDataSource({
|
|
189
|
+
router: trpc.tasks,
|
|
190
|
+
queryInput: { page: 1, perPage: 10 },
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**要求**:后端需要使用 `@wordrhyme/auto-crud-server` 创建 CRUD 路由。
|
|
195
|
+
|
|
196
|
+
#### 3. 自定义数据源(Custom Data Source)
|
|
197
|
+
|
|
198
|
+
适合:REST API、GraphQL 等
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
const dataSource: DataSource<Task> = {
|
|
202
|
+
list: async (params) => {
|
|
203
|
+
const response = await fetch(`/api/tasks?${new URLSearchParams(params)}`);
|
|
204
|
+
return response.json();
|
|
205
|
+
},
|
|
206
|
+
get: async (id) => {
|
|
207
|
+
const response = await fetch(`/api/tasks/${id}`);
|
|
208
|
+
return response.json();
|
|
209
|
+
},
|
|
210
|
+
create: async (data) => {
|
|
211
|
+
const response = await fetch("/api/tasks", {
|
|
212
|
+
method: "POST",
|
|
213
|
+
body: JSON.stringify(data),
|
|
214
|
+
});
|
|
215
|
+
return response.json();
|
|
216
|
+
},
|
|
217
|
+
update: async (id, data) => {
|
|
218
|
+
const response = await fetch(`/api/tasks/${id}`, {
|
|
219
|
+
method: "PATCH",
|
|
220
|
+
body: JSON.stringify(data),
|
|
221
|
+
});
|
|
222
|
+
return response.json();
|
|
223
|
+
},
|
|
224
|
+
delete: async (id) => {
|
|
225
|
+
await fetch(`/api/tasks/${id}`, { method: "DELETE" });
|
|
226
|
+
},
|
|
227
|
+
deleteMany: async (ids) => {
|
|
228
|
+
await fetch("/api/tasks/batch", {
|
|
229
|
+
method: "DELETE",
|
|
230
|
+
body: JSON.stringify({ ids }),
|
|
231
|
+
});
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## 🎨 组件 API
|
|
239
|
+
|
|
240
|
+
### `<AutoCrudTable />`
|
|
241
|
+
|
|
242
|
+
完整的 CRUD 表格组件。
|
|
243
|
+
|
|
244
|
+
#### Props
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
interface AutoCrudTableProps<TData> {
|
|
248
|
+
// 必需
|
|
249
|
+
title: string; // 表格标题
|
|
250
|
+
schema: z.ZodType<TData>; // Zod Schema
|
|
251
|
+
resource: AutoCrudResource<TData>; // useAutoCrudResource 返回值
|
|
252
|
+
|
|
253
|
+
// 可选
|
|
254
|
+
fieldOverrides?: FieldOverrides<TData>; // 字段配置
|
|
255
|
+
tableProps?: {
|
|
256
|
+
filterMode?: FilterMode | FilterMode[]; // 过滤模式
|
|
257
|
+
batchUpdateFields?: (keyof TData)[]; // 批量更新字段
|
|
258
|
+
};
|
|
259
|
+
slots?: {
|
|
260
|
+
toolbarEnd?: React.ReactNode; // 工具栏右侧插槽
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
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
|
+
### `useAutoCrudResource()`
|
|
296
|
+
|
|
297
|
+
连接数据源到组件的 Hook。
|
|
298
|
+
|
|
299
|
+
#### 参数
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
interface UseAutoCrudResourceConfig<TData> {
|
|
303
|
+
dataSource: DataSource<TData>; // 数据源
|
|
304
|
+
schema: z.ZodType<TData>; // Zod Schema
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
#### 返回值
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
interface AutoCrudResource<TData> {
|
|
312
|
+
// 数据
|
|
313
|
+
data: TData[];
|
|
314
|
+
total: number;
|
|
315
|
+
isLoading: boolean;
|
|
316
|
+
|
|
317
|
+
// 模态框状态
|
|
318
|
+
modal: {
|
|
319
|
+
variant: "dialog" | "sheet";
|
|
320
|
+
isOpen: boolean;
|
|
321
|
+
mode: "create" | "edit";
|
|
322
|
+
editingItem: TData | null;
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
// 操作方法
|
|
326
|
+
handlers: {
|
|
327
|
+
setVariant: (variant: "dialog" | "sheet") => void;
|
|
328
|
+
openCreate: () => void;
|
|
329
|
+
openEdit: (item: TData) => void;
|
|
330
|
+
closeModal: () => void;
|
|
331
|
+
handleCreate: (data: Partial<TData>) => Promise<void>;
|
|
332
|
+
handleUpdate: (id: string, data: Partial<TData>) => Promise<void>;
|
|
333
|
+
handleDelete: (id: string) => Promise<void>;
|
|
334
|
+
handleDeleteMany: (ids: string[]) => Promise<void>;
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## 🔧 字段配置
|
|
342
|
+
|
|
343
|
+
### 基础配置
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
fieldOverrides={{
|
|
347
|
+
fieldName: {
|
|
348
|
+
label: "显示名称", // 表格和表单共用
|
|
349
|
+
hidden: true, // 表格和表单都隐藏
|
|
350
|
+
},
|
|
351
|
+
}}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### 表格特定配置
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
fieldOverrides={{
|
|
358
|
+
amount: {
|
|
359
|
+
label: "金额",
|
|
360
|
+
table: {
|
|
361
|
+
meta: {
|
|
362
|
+
unit: "¥", // 单位显示
|
|
363
|
+
variant: "number", // 筛选器类型
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
status: {
|
|
368
|
+
label: "状态",
|
|
369
|
+
table: {
|
|
370
|
+
meta: {
|
|
371
|
+
variant: "select",
|
|
372
|
+
options: [
|
|
373
|
+
{ label: "待处理", value: "pending" },
|
|
374
|
+
{ label: "已完成", value: "completed" },
|
|
375
|
+
],
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
}}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### 表单特定配置
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
fieldOverrides={{
|
|
386
|
+
description: {
|
|
387
|
+
label: "描述",
|
|
388
|
+
form: {
|
|
389
|
+
"x-component": "Textarea",
|
|
390
|
+
"x-component-props": { rows: 5 },
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
createdAt: {
|
|
394
|
+
label: "创建时间",
|
|
395
|
+
form: {
|
|
396
|
+
"x-hidden": true, // 仅表单隐藏
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
}}
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### 字段联动
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
fieldOverrides={{
|
|
406
|
+
endDate: {
|
|
407
|
+
label: "结束日期",
|
|
408
|
+
form: {
|
|
409
|
+
"x-reactions": {
|
|
410
|
+
dependencies: ["startDate"],
|
|
411
|
+
when: "{{$deps[0] !== undefined}}",
|
|
412
|
+
fulfill: {
|
|
413
|
+
state: {
|
|
414
|
+
visible: true,
|
|
415
|
+
disabled: false,
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
}}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## 🎯 过滤模式
|
|
427
|
+
|
|
428
|
+
### Simple 模式(简单筛选)
|
|
429
|
+
|
|
430
|
+
- 适合:快速筛选常用字段
|
|
431
|
+
- 特点:下拉选择框,一键清除
|
|
432
|
+
- 示例:状态筛选、优先级筛选
|
|
433
|
+
|
|
434
|
+
```typescript
|
|
435
|
+
tableProps={{
|
|
436
|
+
filterMode: "simple",
|
|
437
|
+
}}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### Advanced 模式(高级筛选)
|
|
441
|
+
|
|
442
|
+
- 适合:复杂多条件查询
|
|
443
|
+
- 特点:Notion 风格,支持 AND/OR 逻辑
|
|
444
|
+
- 示例:`status = "done" AND priority = "high"`
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
tableProps={{
|
|
448
|
+
filterMode: "advanced",
|
|
449
|
+
}}
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### Command 模式(命令面板)
|
|
453
|
+
|
|
454
|
+
- 适合:键盘流用户
|
|
455
|
+
- 特点:Linear 风格,快捷键 `Cmd+K`
|
|
456
|
+
- 示例:快速搜索并添加筛选条件
|
|
457
|
+
|
|
458
|
+
```typescript
|
|
459
|
+
tableProps={{
|
|
460
|
+
filterMode: "command",
|
|
461
|
+
}}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### 多模式切换
|
|
465
|
+
|
|
466
|
+
```typescript
|
|
467
|
+
tableProps={{
|
|
468
|
+
filterMode: ["simple", "advanced", "command"], // 第一个为默认模式
|
|
469
|
+
}}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
## 🔄 批量操作
|
|
475
|
+
|
|
476
|
+
### 批量更新
|
|
477
|
+
|
|
478
|
+
```typescript
|
|
479
|
+
<AutoCrudTable
|
|
480
|
+
schema={taskSchema}
|
|
481
|
+
resource={resource}
|
|
482
|
+
tableProps={{
|
|
483
|
+
batchUpdateFields: ["status", "priority"],
|
|
484
|
+
}}
|
|
485
|
+
/>
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
**功能**:
|
|
489
|
+
- 选择多行
|
|
490
|
+
- 点击批量更新按钮
|
|
491
|
+
- 选择字段和新值
|
|
492
|
+
- 一键更新所有选中行
|
|
493
|
+
|
|
494
|
+
### 批量删除
|
|
495
|
+
|
|
496
|
+
```typescript
|
|
497
|
+
// 自动启用,无需配置
|
|
498
|
+
<AutoCrudTable schema={taskSchema} resource={resource} />
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
**功能**:
|
|
502
|
+
- 选择多行
|
|
503
|
+
- 点击批量删除按钮
|
|
504
|
+
- 确认删除
|
|
505
|
+
- 一次性删除所有选中行
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
509
|
+
## 🎨 自定义样式
|
|
510
|
+
|
|
511
|
+
### 使用 Tailwind CSS
|
|
512
|
+
|
|
513
|
+
```typescript
|
|
514
|
+
<AutoCrudTable
|
|
515
|
+
schema={taskSchema}
|
|
516
|
+
resource={resource}
|
|
517
|
+
className="custom-table"
|
|
518
|
+
/>
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### 自定义工具栏
|
|
522
|
+
|
|
523
|
+
```typescript
|
|
524
|
+
<AutoCrudTable
|
|
525
|
+
schema={taskSchema}
|
|
526
|
+
resource={resource}
|
|
527
|
+
slots={{
|
|
528
|
+
toolbarEnd: (
|
|
529
|
+
<div className="flex gap-2">
|
|
530
|
+
<Button onClick={handleExport}>导出</Button>
|
|
531
|
+
<Button onClick={handleImport}>导入</Button>
|
|
532
|
+
</div>
|
|
533
|
+
),
|
|
534
|
+
}}
|
|
535
|
+
/>
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
---
|
|
539
|
+
|
|
540
|
+
## 📚 高级用法
|
|
541
|
+
|
|
542
|
+
### 自定义列渲染
|
|
543
|
+
|
|
544
|
+
```typescript
|
|
545
|
+
import { createColumns } from "@wordrhyme/auto-crud";
|
|
546
|
+
|
|
547
|
+
const columns = createColumns(taskSchema, {
|
|
548
|
+
overrides: {
|
|
549
|
+
status: {
|
|
550
|
+
cell: ({ row }) => (
|
|
551
|
+
<Badge variant={row.original.status === "done" ? "success" : "default"}>
|
|
552
|
+
{row.original.status}
|
|
553
|
+
</Badge>
|
|
554
|
+
),
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
});
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### 自定义表单组件
|
|
561
|
+
|
|
562
|
+
```typescript
|
|
563
|
+
fieldOverrides={{
|
|
564
|
+
tags: {
|
|
565
|
+
label: "标签",
|
|
566
|
+
form: {
|
|
567
|
+
"x-component": "TagsInput",
|
|
568
|
+
"x-component-props": {
|
|
569
|
+
placeholder: "输入标签",
|
|
570
|
+
maxTags: 5,
|
|
571
|
+
},
|
|
572
|
+
},
|
|
573
|
+
},
|
|
574
|
+
}}
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
### 服务端分页
|
|
578
|
+
|
|
579
|
+
```typescript
|
|
580
|
+
const [queryParams] = useQueryStates({
|
|
581
|
+
page: parseAsInteger.withDefault(1),
|
|
582
|
+
perPage: parseAsInteger.withDefault(10),
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
const dataSource = createTRPCDataSource({
|
|
586
|
+
router: trpc.tasks,
|
|
587
|
+
queryInput: queryParams,
|
|
588
|
+
});
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
---
|
|
592
|
+
|
|
593
|
+
## 🔌 与其他库集成
|
|
594
|
+
|
|
595
|
+
### 与 Drizzle ORM 集成
|
|
596
|
+
|
|
597
|
+
```typescript
|
|
598
|
+
import { createSelectSchema } from "drizzle-zod";
|
|
599
|
+
import { tasks } from "@/db/schema";
|
|
600
|
+
|
|
601
|
+
const taskSchema = createSelectSchema(tasks);
|
|
602
|
+
|
|
603
|
+
<AutoCrudTable schema={taskSchema} resource={resource} />
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
### 与 React Hook Form 集成
|
|
607
|
+
|
|
608
|
+
```typescript
|
|
609
|
+
import { zodResolver } from "@hookform/resolvers/zod";
|
|
610
|
+
import { useForm } from "react-hook-form";
|
|
611
|
+
|
|
612
|
+
const form = useForm({
|
|
613
|
+
resolver: zodResolver(taskSchema),
|
|
614
|
+
});
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
### 与 Next.js 集成
|
|
618
|
+
|
|
619
|
+
```typescript
|
|
620
|
+
// app/tasks/page.tsx
|
|
621
|
+
"use client";
|
|
622
|
+
|
|
623
|
+
import { AutoCrudTable } from "@wordrhyme/auto-crud";
|
|
624
|
+
|
|
625
|
+
export default function TasksPage() {
|
|
626
|
+
return <AutoCrudTable schema={taskSchema} resource={resource} />;
|
|
627
|
+
}
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
---
|
|
631
|
+
|
|
632
|
+
## 🛠️ 工具函数
|
|
633
|
+
|
|
634
|
+
### `createColumns()`
|
|
635
|
+
|
|
636
|
+
从 Zod Schema 自动生成表格列。
|
|
637
|
+
|
|
638
|
+
```typescript
|
|
639
|
+
import { createColumns } from "@wordrhyme/auto-crud";
|
|
640
|
+
|
|
641
|
+
const columns = createColumns(taskSchema, {
|
|
642
|
+
exclude: ["id", "createdAt"],
|
|
643
|
+
overrides: {
|
|
644
|
+
status: {
|
|
645
|
+
meta: {
|
|
646
|
+
label: "状态",
|
|
647
|
+
variant: "select",
|
|
648
|
+
},
|
|
649
|
+
},
|
|
650
|
+
},
|
|
651
|
+
});
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
### `createFormSchema()`
|
|
655
|
+
|
|
656
|
+
从 Zod Schema 自动生成 Formily 表单 Schema。
|
|
657
|
+
|
|
658
|
+
```typescript
|
|
659
|
+
import { createFormSchema } from "@wordrhyme/auto-crud";
|
|
660
|
+
|
|
661
|
+
const formSchema = createFormSchema(taskSchema, {
|
|
662
|
+
exclude: ["id", "createdAt"],
|
|
663
|
+
layout: "vertical",
|
|
664
|
+
});
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
---
|
|
668
|
+
|
|
669
|
+
## 📦 导出的类型
|
|
670
|
+
|
|
671
|
+
```typescript
|
|
672
|
+
// 组件
|
|
673
|
+
export { AutoCrudTable } from "./components/auto-crud/auto-crud-table";
|
|
674
|
+
export { AutoForm } from "./components/auto-crud/auto-form";
|
|
675
|
+
export { AutoTable } from "./components/auto-crud/auto-table";
|
|
676
|
+
|
|
677
|
+
// Hooks
|
|
678
|
+
export { useAutoCrudResource } from "./hooks/use-auto-crud-resource";
|
|
679
|
+
export { useDataTable } from "./hooks/use-data-table";
|
|
680
|
+
|
|
681
|
+
// 数据源
|
|
682
|
+
export { createTRPCDataSource, createMemoryDataSource } from "./lib/data-source";
|
|
683
|
+
export type { DataSource, ListParams, ListResult } from "./lib/data-source";
|
|
684
|
+
|
|
685
|
+
// 工具函数
|
|
686
|
+
export { createColumns, createFormSchema } from "./lib/schema-bridge";
|
|
687
|
+
export type {
|
|
688
|
+
FieldOverrides,
|
|
689
|
+
FieldOverride,
|
|
690
|
+
CreateColumnsOptions,
|
|
691
|
+
CreateFormSchemaOptions,
|
|
692
|
+
} from "./lib/schema-bridge";
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
---
|
|
696
|
+
|
|
697
|
+
## 🤝 贡献
|
|
698
|
+
|
|
699
|
+
欢迎贡献代码!请查看 [CONTRIBUTING.md](./CONTRIBUTING.md)。
|
|
700
|
+
|
|
701
|
+
---
|
|
702
|
+
|
|
703
|
+
## 📄 许可证
|
|
704
|
+
|
|
705
|
+
MIT © [wordrhyme](https://github.com/pixpilot/shadcn-components)
|
|
706
|
+
|
|
707
|
+
---
|
|
708
|
+
|
|
709
|
+
## 🔗 相关链接
|
|
710
|
+
|
|
711
|
+
- [GitHub](https://github.com/pixpilot/shadcn-components)
|
|
712
|
+
- [文档](https://github.com/pixpilot/shadcn-components/tree/main/packages/auto-crud)
|
|
713
|
+
- [示例](https://github.com/pixpilot/shadcn-components/tree/main/examples)
|
|
714
|
+
- [Changelog](./CHANGELOG.md)
|
|
715
|
+
|
|
716
|
+
---
|
|
717
|
+
|
|
718
|
+
## 💡 灵感来源
|
|
719
|
+
|
|
720
|
+
- [TanStack Table](https://tanstack.com/table) - 强大的表格库
|
|
721
|
+
- [Formily](https://formilyjs.org/) - 灵活的表单解决方案
|
|
722
|
+
- [Shadcn UI](https://ui.shadcn.com/) - 优雅的 UI 组件
|
|
723
|
+
- [Notion](https://notion.so) - 高级筛选器设计
|
|
724
|
+
- [Linear](https://linear.app) - 命令面板设计
|