@wordrhyme/auto-crud 1.0.9 → 1.1.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 +243 -154
- package/dist/index.cjs +141 -42
- package/dist/index.d.cts +81 -31
- package/dist/index.d.ts +65 -15
- package/dist/index.js +141 -42
- package/package.json +13 -13
package/README.md
CHANGED
|
@@ -155,6 +155,7 @@ Zod Schema → 自动推断字段类型 → 生成表格列 + 表单字段
|
|
|
155
155
|
```
|
|
156
156
|
|
|
157
157
|
**优势**:
|
|
158
|
+
|
|
158
159
|
- ✅ 单一数据源(SSOT)
|
|
159
160
|
- ✅ 类型安全
|
|
160
161
|
- ✅ 零手动配置
|
|
@@ -169,13 +170,19 @@ Zod Schema → 自动推断字段类型 → 生成表格列 + 表单字段
|
|
|
169
170
|
适合:原型开发、演示、测试
|
|
170
171
|
|
|
171
172
|
```typescript
|
|
172
|
-
import { createMemoryDataSource } from
|
|
173
|
+
import { createMemoryDataSource } from '@wordrhyme/auto-crud';
|
|
173
174
|
|
|
174
175
|
const dataSource = createMemoryDataSource({
|
|
175
176
|
data: initialData,
|
|
176
|
-
onCreate: async (data) => {
|
|
177
|
-
|
|
178
|
-
|
|
177
|
+
onCreate: async (data) => {
|
|
178
|
+
/* ... */
|
|
179
|
+
},
|
|
180
|
+
onUpdate: async (id, data) => {
|
|
181
|
+
/* ... */
|
|
182
|
+
},
|
|
183
|
+
onDelete: async (id) => {
|
|
184
|
+
/* ... */
|
|
185
|
+
},
|
|
179
186
|
});
|
|
180
187
|
```
|
|
181
188
|
|
|
@@ -184,7 +191,7 @@ const dataSource = createMemoryDataSource({
|
|
|
184
191
|
适合:全栈 TypeScript 项目
|
|
185
192
|
|
|
186
193
|
```typescript
|
|
187
|
-
import { createTRPCDataSource } from
|
|
194
|
+
import { createTRPCDataSource } from '@wordrhyme/auto-crud';
|
|
188
195
|
|
|
189
196
|
const dataSource = createTRPCDataSource({
|
|
190
197
|
router: trpc.tasks,
|
|
@@ -209,25 +216,25 @@ const dataSource: DataSource<Task> = {
|
|
|
209
216
|
return response.json();
|
|
210
217
|
},
|
|
211
218
|
create: async (data) => {
|
|
212
|
-
const response = await fetch(
|
|
213
|
-
method:
|
|
219
|
+
const response = await fetch('/api/tasks', {
|
|
220
|
+
method: 'POST',
|
|
214
221
|
body: JSON.stringify(data),
|
|
215
222
|
});
|
|
216
223
|
return response.json();
|
|
217
224
|
},
|
|
218
225
|
update: async (id, data) => {
|
|
219
226
|
const response = await fetch(`/api/tasks/${id}`, {
|
|
220
|
-
method:
|
|
227
|
+
method: 'PATCH',
|
|
221
228
|
body: JSON.stringify(data),
|
|
222
229
|
});
|
|
223
230
|
return response.json();
|
|
224
231
|
},
|
|
225
232
|
delete: async (id) => {
|
|
226
|
-
await fetch(`/api/tasks/${id}`, { method:
|
|
233
|
+
await fetch(`/api/tasks/${id}`, { method: 'DELETE' });
|
|
227
234
|
},
|
|
228
235
|
deleteMany: async (ids) => {
|
|
229
|
-
await fetch(
|
|
230
|
-
method:
|
|
236
|
+
await fetch('/api/tasks/batch', {
|
|
237
|
+
method: 'DELETE',
|
|
231
238
|
body: JSON.stringify({ ids }),
|
|
232
239
|
});
|
|
233
240
|
},
|
|
@@ -247,23 +254,23 @@ const dataSource: DataSource<Task> = {
|
|
|
247
254
|
```typescript
|
|
248
255
|
interface AutoCrudTableProps<TSchema> {
|
|
249
256
|
// 必需
|
|
250
|
-
schema: TSchema;
|
|
257
|
+
schema: TSchema; // Zod Schema
|
|
251
258
|
resource: UseAutoCrudResourceReturn<TSchema>; // useAutoCrudResource 返回值
|
|
252
259
|
|
|
253
260
|
// 可选
|
|
254
261
|
title?: string;
|
|
255
262
|
description?: string;
|
|
256
|
-
fields?: Fields;
|
|
263
|
+
fields?: Fields; // 统一字段配置
|
|
257
264
|
table?: {
|
|
258
|
-
hidden?: string[];
|
|
259
|
-
overrides?: Record<string, any>;
|
|
260
|
-
filterModes?: FilterMode | FilterMode[];
|
|
265
|
+
hidden?: string[]; // 隐藏的列
|
|
266
|
+
overrides?: Record<string, any>; // 列覆盖配置
|
|
267
|
+
filterModes?: FilterMode | FilterMode[]; // 过滤模式
|
|
261
268
|
batchFields?: (string | BatchUpdateField)[]; // 批量更新字段
|
|
262
|
-
defaultSort?: any[];
|
|
269
|
+
defaultSort?: any[]; // 默认排序
|
|
263
270
|
};
|
|
264
271
|
form?: {
|
|
265
|
-
overrides?: Record<string, any>;
|
|
266
|
-
columns?: number;
|
|
272
|
+
overrides?: Record<string, any>; // 表单覆盖配置
|
|
273
|
+
columns?: number; // 表单列数
|
|
267
274
|
};
|
|
268
275
|
/**
|
|
269
276
|
* 工具栏右侧操作配置
|
|
@@ -288,8 +295,8 @@ interface AutoCrudTableProps<TSchema> {
|
|
|
288
295
|
|
|
289
296
|
```typescript
|
|
290
297
|
interface UseAutoCrudResourceConfig<TData> {
|
|
291
|
-
dataSource: DataSource<TData>;
|
|
292
|
-
schema: z.ZodType<TData>;
|
|
298
|
+
dataSource: DataSource<TData>; // 数据源
|
|
299
|
+
schema: z.ZodType<TData>; // Zod Schema
|
|
293
300
|
}
|
|
294
301
|
```
|
|
295
302
|
|
|
@@ -305,7 +312,7 @@ interface UseAutoCrudResourceReturn<TSchema, TData> {
|
|
|
305
312
|
|
|
306
313
|
// 模态框状态
|
|
307
314
|
modal: {
|
|
308
|
-
variant:
|
|
315
|
+
variant: 'dialog' | 'sheet';
|
|
309
316
|
createOpen: boolean;
|
|
310
317
|
editOpen: boolean;
|
|
311
318
|
viewOpen: boolean;
|
|
@@ -352,16 +359,16 @@ interface Field {
|
|
|
352
359
|
hidden?: boolean;
|
|
353
360
|
/** 表格特定配置 */
|
|
354
361
|
table?: {
|
|
355
|
-
hidden?: boolean;
|
|
356
|
-
meta?: Record<string, unknown>;
|
|
362
|
+
hidden?: boolean; // 仅表格隐藏
|
|
363
|
+
meta?: Record<string, unknown>; // 筛选器配置
|
|
357
364
|
[key: string]: unknown;
|
|
358
365
|
};
|
|
359
366
|
/** 表单特定配置 */
|
|
360
367
|
form?: {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
368
|
+
'x-hidden'?: boolean; // 仅表单隐藏
|
|
369
|
+
'x-component'?: string; // 组件类型
|
|
370
|
+
'x-component-props'?: Record<string, unknown>; // 组件属性
|
|
371
|
+
'x-reactions'?: object; // 字段联动
|
|
365
372
|
[key: string]: unknown;
|
|
366
373
|
};
|
|
367
374
|
}
|
|
@@ -533,8 +540,12 @@ table={{
|
|
|
533
540
|
```tsx
|
|
534
541
|
<AutoCrudTable
|
|
535
542
|
toolbarActions={[
|
|
536
|
-
{
|
|
537
|
-
|
|
543
|
+
{
|
|
544
|
+
type: 'custom',
|
|
545
|
+
component: <Button variant="outline">分类管理</Button>,
|
|
546
|
+
position: 'start',
|
|
547
|
+
},
|
|
548
|
+
{ type: 'custom', component: <Button variant="outline">批量标签</Button> }, // 默认 position: "end"
|
|
538
549
|
]}
|
|
539
550
|
/>
|
|
540
551
|
// 渲染顺序: 分类管理 · [导入] · [导出] · [新建] · 批量标签
|
|
@@ -547,8 +558,8 @@ table={{
|
|
|
547
558
|
```tsx
|
|
548
559
|
<AutoCrudTable
|
|
549
560
|
toolbarActions={[
|
|
550
|
-
{ type:
|
|
551
|
-
{ type:
|
|
561
|
+
{ type: 'create' }, // 新建移到最前
|
|
562
|
+
{ type: 'export', label: '导出 CSV' }, // 覆盖文案
|
|
552
563
|
// import 未列出 → 隐藏
|
|
553
564
|
]}
|
|
554
565
|
/>
|
|
@@ -560,12 +571,12 @@ table={{
|
|
|
560
571
|
```tsx
|
|
561
572
|
<AutoCrudTable
|
|
562
573
|
toolbarActions={[
|
|
563
|
-
{ type:
|
|
564
|
-
{ type:
|
|
565
|
-
{
|
|
566
|
-
type:
|
|
567
|
-
label:
|
|
568
|
-
onClick: () => router.push('/products/new'),
|
|
574
|
+
{ type: 'import' },
|
|
575
|
+
{ type: 'export' },
|
|
576
|
+
{
|
|
577
|
+
type: 'create',
|
|
578
|
+
label: '发布商品',
|
|
579
|
+
onClick: () => router.push('/products/new'), // 跳转详情页而非弹窗
|
|
569
580
|
},
|
|
570
581
|
]}
|
|
571
582
|
/>
|
|
@@ -576,13 +587,17 @@ table={{
|
|
|
576
587
|
```tsx
|
|
577
588
|
<AutoCrudTable
|
|
578
589
|
toolbarActions={[
|
|
579
|
-
{ type:
|
|
580
|
-
{
|
|
581
|
-
type:
|
|
582
|
-
|
|
590
|
+
{ type: 'export' },
|
|
591
|
+
{
|
|
592
|
+
type: 'create',
|
|
593
|
+
// 整个按钮替换
|
|
594
|
+
component: (
|
|
583
595
|
<DropdownMenu>
|
|
584
596
|
<DropdownMenuTrigger asChild>
|
|
585
|
-
<Button
|
|
597
|
+
<Button>
|
|
598
|
+
<Plus className="mr-2 h-4 w-4" />
|
|
599
|
+
新建
|
|
600
|
+
</Button>
|
|
586
601
|
</DropdownMenuTrigger>
|
|
587
602
|
<DropdownMenuContent>
|
|
588
603
|
<DropdownMenuItem onClick={() => create('simple')}>简易商品</DropdownMenuItem>
|
|
@@ -600,9 +615,9 @@ table={{
|
|
|
600
615
|
```tsx
|
|
601
616
|
<AutoCrudTable
|
|
602
617
|
toolbarActions={[
|
|
603
|
-
{ type:
|
|
604
|
-
{ type:
|
|
605
|
-
{ type:
|
|
618
|
+
{ type: 'custom', component: <CategoryFilter onChange={setCategory} /> },
|
|
619
|
+
{ type: 'export' },
|
|
620
|
+
{ type: 'create', label: '发布', onClick: () => router.push('/products/new') },
|
|
606
621
|
]}
|
|
607
622
|
/>
|
|
608
623
|
// 渲染顺序: 分类筛选 · 导出 · 发布(导入隐藏)
|
|
@@ -623,11 +638,11 @@ table={{
|
|
|
623
638
|
can: { create: isAdmin, export: true, delete: isAdmin },
|
|
624
639
|
}}
|
|
625
640
|
toolbarActions={[
|
|
626
|
-
{ type:
|
|
627
|
-
{ type:
|
|
628
|
-
{
|
|
629
|
-
type:
|
|
630
|
-
component: isEditor ? <Button>审核</Button> : null,
|
|
641
|
+
{ type: 'export' }, // ✅ 始终渲染
|
|
642
|
+
{ type: 'create', label: '发布商品' }, // 🔒 仅 isAdmin 时渲染
|
|
643
|
+
{
|
|
644
|
+
type: 'custom', // ✅ 不受 permissions 影响
|
|
645
|
+
component: isEditor ? <Button>审核</Button> : null, // 业务方自行守卫
|
|
631
646
|
},
|
|
632
647
|
]}
|
|
633
648
|
/>
|
|
@@ -640,11 +655,13 @@ table={{
|
|
|
640
655
|
```tsx
|
|
641
656
|
<AutoCrudTable
|
|
642
657
|
// defaults 即内置三个按钮的信息,在此数组里你可以随意 map、过滤或插值
|
|
643
|
-
toolbarActions={(defaults) =>
|
|
644
|
-
btn
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
658
|
+
toolbarActions={(defaults) =>
|
|
659
|
+
defaults.map((btn) =>
|
|
660
|
+
btn.type === 'create'
|
|
661
|
+
? { ...btn, label: '发布商品', onClick: () => router.push('/products/new') }
|
|
662
|
+
: btn,
|
|
663
|
+
)
|
|
664
|
+
}
|
|
648
665
|
/>
|
|
649
666
|
// 非常适合“只盖头不换面”的场景,不会导致内置按钮丢失或顺序打乱
|
|
650
667
|
```
|
|
@@ -655,16 +672,16 @@ table={{
|
|
|
655
672
|
type ToolbarActionItem = ToolbarBuiltinActionItem | ToolbarCustomActionItem;
|
|
656
673
|
|
|
657
674
|
type ToolbarBuiltinActionItem = {
|
|
658
|
-
type:
|
|
659
|
-
onClick?: () => void;
|
|
660
|
-
label?: string;
|
|
661
|
-
component?: React.ReactNode;
|
|
675
|
+
type: 'create' | 'import' | 'export';
|
|
676
|
+
onClick?: () => void; // 覆盖默认行为
|
|
677
|
+
label?: string; // 覆盖默认文案
|
|
678
|
+
component?: React.ReactNode; // 完全替换按钮渲染
|
|
662
679
|
};
|
|
663
680
|
|
|
664
681
|
type ToolbarCustomActionItem = {
|
|
665
|
-
type:
|
|
666
|
-
component: React.ReactNode;
|
|
667
|
-
position?:
|
|
682
|
+
type: 'custom';
|
|
683
|
+
component: React.ReactNode; // 自定义渲染内容
|
|
684
|
+
position?: 'start' | 'end'; // 仅在无内置项时生效,默认 "end"
|
|
668
685
|
};
|
|
669
686
|
```
|
|
670
687
|
|
|
@@ -679,8 +696,8 @@ type ToolbarCustomActionItem = {
|
|
|
679
696
|
```tsx
|
|
680
697
|
<AutoCrudTable
|
|
681
698
|
actions={[
|
|
682
|
-
{ type:
|
|
683
|
-
{ type:
|
|
699
|
+
{ type: 'custom', label: '分配', onClick: (row) => assign(row.id) },
|
|
700
|
+
{ type: 'custom', label: '预览', onClick: (row) => preview(row), position: 'start' },
|
|
684
701
|
]}
|
|
685
702
|
/>
|
|
686
703
|
// 渲染顺序: 预览 · 查看 · 编辑 · 复制 · 删除 · 分配
|
|
@@ -693,9 +710,9 @@ type ToolbarCustomActionItem = {
|
|
|
693
710
|
```tsx
|
|
694
711
|
<AutoCrudTable
|
|
695
712
|
actions={[
|
|
696
|
-
{ type:
|
|
697
|
-
{ type:
|
|
698
|
-
{ type:
|
|
713
|
+
{ type: 'view', onClick: (row) => router.push(`/tasks/${row.id}`) }, // 覆盖跳转
|
|
714
|
+
{ type: 'custom', label: '分配', onClick: (row) => assign(row.id) },
|
|
715
|
+
{ type: 'edit' }, // 默认行为
|
|
699
716
|
// copy / delete 未列出 → 隐藏
|
|
700
717
|
]}
|
|
701
718
|
/>
|
|
@@ -706,10 +723,10 @@ type ToolbarCustomActionItem = {
|
|
|
706
723
|
```tsx
|
|
707
724
|
<AutoCrudTable
|
|
708
725
|
actions={[
|
|
709
|
-
{ type:
|
|
710
|
-
{ type:
|
|
711
|
-
{ type:
|
|
712
|
-
{ type:
|
|
726
|
+
{ type: 'edit' },
|
|
727
|
+
{ type: 'copy' },
|
|
728
|
+
{ type: 'custom', label: '归档', onClick: archive, separator: true },
|
|
729
|
+
{ type: 'delete', separator: true },
|
|
713
730
|
]}
|
|
714
731
|
/>
|
|
715
732
|
```
|
|
@@ -720,11 +737,13 @@ type ToolbarCustomActionItem = {
|
|
|
720
737
|
|
|
721
738
|
```tsx
|
|
722
739
|
<AutoCrudTable
|
|
723
|
-
actions={(defaults) =>
|
|
724
|
-
action
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
740
|
+
actions={(defaults) =>
|
|
741
|
+
defaults.map((action) =>
|
|
742
|
+
action.type === 'delete'
|
|
743
|
+
? { ...action, label: '下架', variant: 'default' }
|
|
744
|
+
: action,
|
|
745
|
+
)
|
|
746
|
+
}
|
|
728
747
|
/>
|
|
729
748
|
```
|
|
730
749
|
|
|
@@ -733,18 +752,18 @@ type ToolbarCustomActionItem = {
|
|
|
733
752
|
```typescript
|
|
734
753
|
type ActionItem<T> =
|
|
735
754
|
| {
|
|
736
|
-
type:
|
|
737
|
-
onClick?: (row: T) => void;
|
|
738
|
-
label?: string;
|
|
739
|
-
separator?: boolean;
|
|
755
|
+
type: 'view' | 'edit' | 'copy' | 'delete';
|
|
756
|
+
onClick?: (row: T) => void; // 不传则使用默认行为
|
|
757
|
+
label?: string; // 不传则使用默认文案
|
|
758
|
+
separator?: boolean; // 此项前加分隔线
|
|
740
759
|
}
|
|
741
760
|
| {
|
|
742
|
-
type:
|
|
761
|
+
type: 'custom';
|
|
743
762
|
label: string;
|
|
744
763
|
onClick: (row: T) => void;
|
|
745
|
-
position?:
|
|
764
|
+
position?: 'start' | 'end'; // 仅无内置项时生效,默认 end
|
|
746
765
|
separator?: boolean;
|
|
747
|
-
variant?:
|
|
766
|
+
variant?: 'default' | 'destructive';
|
|
748
767
|
};
|
|
749
768
|
```
|
|
750
769
|
|
|
@@ -763,11 +782,59 @@ type ActionItem<T> =
|
|
|
763
782
|
```
|
|
764
783
|
|
|
765
784
|
**功能**:
|
|
785
|
+
|
|
766
786
|
- 选择多行
|
|
767
787
|
- 点击批量更新按钮
|
|
768
788
|
- 选择字段和新值
|
|
769
789
|
- 一键更新所有选中行
|
|
770
790
|
|
|
791
|
+
### 批量悬浮栏操作顺序
|
|
792
|
+
|
|
793
|
+
`table.batchActions` 控制多选后悬浮操作栏,设计思路对齐行操作 `actions` 和顶部 `toolbarActions`。
|
|
794
|
+
|
|
795
|
+
内置操作类型:`batchUpdate`(批量更新字段下拉)、`export`(导出选中行)、`delete`(删除选中行)。
|
|
796
|
+
|
|
797
|
+
只传 `type: "custom"` 项时,默认批量操作保持原样;包含任意内置 `type` 时,将完全接管顺序,未列出的内置操作不渲染。
|
|
798
|
+
|
|
799
|
+
`AutoCrudTable` 默认不在悬浮栏重复显示导出按钮;需要悬浮栏导出时,在 `batchActions` 中显式列出 `{ type: 'export' }`。
|
|
800
|
+
|
|
801
|
+
```tsx
|
|
802
|
+
<AutoCrudTable
|
|
803
|
+
schema={taskSchema}
|
|
804
|
+
resource={resource}
|
|
805
|
+
table={{
|
|
806
|
+
batchFields: ['status', 'priority'],
|
|
807
|
+
batchActions: [
|
|
808
|
+
{ type: 'batchUpdate' },
|
|
809
|
+
{
|
|
810
|
+
type: 'custom',
|
|
811
|
+
label: '同步选中项',
|
|
812
|
+
onClick: (rows) => syncSelected(rows),
|
|
813
|
+
},
|
|
814
|
+
{ type: 'export' },
|
|
815
|
+
{ type: 'delete' },
|
|
816
|
+
],
|
|
817
|
+
}}
|
|
818
|
+
/>
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
也可以用函数式写法基于默认顺序插入业务操作:
|
|
822
|
+
|
|
823
|
+
```tsx
|
|
824
|
+
<AutoCrudTable
|
|
825
|
+
table={{
|
|
826
|
+
batchActions: (defaults) => [
|
|
827
|
+
defaults[0], // batchUpdate
|
|
828
|
+
{
|
|
829
|
+
type: 'custom',
|
|
830
|
+
component: ({ rows }) => <Button size="sm">同步 {rows.length} 项</Button>,
|
|
831
|
+
},
|
|
832
|
+
defaults[2], // delete
|
|
833
|
+
],
|
|
834
|
+
}}
|
|
835
|
+
/>
|
|
836
|
+
```
|
|
837
|
+
|
|
771
838
|
### 批量删除
|
|
772
839
|
|
|
773
840
|
```typescript
|
|
@@ -776,6 +843,7 @@ type ActionItem<T> =
|
|
|
776
843
|
```
|
|
777
844
|
|
|
778
845
|
**功能**:
|
|
846
|
+
|
|
779
847
|
- 选择多行
|
|
780
848
|
- 点击批量删除按钮
|
|
781
849
|
- 确认删除
|
|
@@ -817,13 +885,13 @@ export default function TasksPage() {
|
|
|
817
885
|
|
|
818
886
|
```typescript
|
|
819
887
|
import {
|
|
820
|
-
parseZodField,
|
|
821
|
-
createTableSchema,
|
|
822
|
-
createSelectColumn,
|
|
823
|
-
createActionsColumn,
|
|
824
|
-
createFormSchema,
|
|
888
|
+
parseZodField, // 解析 Zod 字段类型
|
|
889
|
+
createTableSchema, // Zod Schema → TanStack Table 列定义
|
|
890
|
+
createSelectColumn, // 创建选择列
|
|
891
|
+
createActionsColumn, // 创建操作列
|
|
892
|
+
createFormSchema, // Zod Schema → Formily Schema
|
|
825
893
|
createEditFormSchema, // 创建编辑表单 Schema(排除 id, createdAt, updatedAt)
|
|
826
|
-
} from
|
|
894
|
+
} from '@wordrhyme/auto-crud';
|
|
827
895
|
```
|
|
828
896
|
|
|
829
897
|
### 自定义列渲染
|
|
@@ -864,31 +932,31 @@ const columns = createTableSchema(taskSchema, {
|
|
|
864
932
|
使用 `createFormSchema` 的 `overrides` 参数自定义表单组件:
|
|
865
933
|
|
|
866
934
|
```typescript
|
|
867
|
-
import { createFormSchema } from
|
|
935
|
+
import { createFormSchema } from '@wordrhyme/auto-crud';
|
|
868
936
|
|
|
869
937
|
const formSchema = createFormSchema(taskSchema, {
|
|
870
938
|
overrides: {
|
|
871
939
|
description: {
|
|
872
|
-
|
|
873
|
-
|
|
940
|
+
'x-component': 'Textarea',
|
|
941
|
+
'x-component-props': { rows: 5 },
|
|
874
942
|
},
|
|
875
943
|
status: {
|
|
876
|
-
|
|
877
|
-
|
|
944
|
+
'x-component': 'Select',
|
|
945
|
+
'x-component-props': {
|
|
878
946
|
options: [
|
|
879
|
-
{ label:
|
|
880
|
-
{ label:
|
|
947
|
+
{ label: '待办', value: 'todo' },
|
|
948
|
+
{ label: '完成', value: 'done' },
|
|
881
949
|
],
|
|
882
950
|
},
|
|
883
951
|
},
|
|
884
952
|
dueDate: {
|
|
885
|
-
|
|
886
|
-
|
|
953
|
+
'x-component': 'DatePicker',
|
|
954
|
+
'x-component-props': { format: 'YYYY-MM-DD' },
|
|
887
955
|
},
|
|
888
956
|
},
|
|
889
|
-
layout:
|
|
957
|
+
layout: 'grid',
|
|
890
958
|
gridColumns: 2,
|
|
891
|
-
exclude: [
|
|
959
|
+
exclude: ['id', 'createdAt'],
|
|
892
960
|
});
|
|
893
961
|
```
|
|
894
962
|
|
|
@@ -901,13 +969,13 @@ const formSchema = createFormSchema(taskSchema, {
|
|
|
901
969
|
### 1. Zod Schema(推荐)
|
|
902
970
|
|
|
903
971
|
```typescript
|
|
904
|
-
import { z } from
|
|
972
|
+
import { z } from 'zod';
|
|
905
973
|
|
|
906
974
|
const taskSchema = z.object({
|
|
907
975
|
id: z.string(),
|
|
908
976
|
title: z.string(),
|
|
909
|
-
status: z.enum([
|
|
910
|
-
priority: z.enum([
|
|
977
|
+
status: z.enum(['todo', 'in-progress', 'done']),
|
|
978
|
+
priority: z.enum(['low', 'medium', 'high']),
|
|
911
979
|
createdAt: z.date(),
|
|
912
980
|
});
|
|
913
981
|
```
|
|
@@ -915,49 +983,49 @@ const taskSchema = z.object({
|
|
|
915
983
|
### 2. JSON Schema
|
|
916
984
|
|
|
917
985
|
```typescript
|
|
918
|
-
import type { JSONSchema } from
|
|
986
|
+
import type { JSONSchema } from '@wordrhyme/auto-crud';
|
|
919
987
|
|
|
920
988
|
const taskSchema: JSONSchema = {
|
|
921
|
-
type:
|
|
989
|
+
type: 'object',
|
|
922
990
|
properties: {
|
|
923
|
-
id: { type:
|
|
924
|
-
title: { type:
|
|
991
|
+
id: { type: 'string' },
|
|
992
|
+
title: { type: 'string', title: '标题' },
|
|
925
993
|
status: {
|
|
926
|
-
type:
|
|
927
|
-
enum: [
|
|
928
|
-
title:
|
|
994
|
+
type: 'string',
|
|
995
|
+
enum: ['todo', 'in-progress', 'done'],
|
|
996
|
+
title: '状态',
|
|
929
997
|
},
|
|
930
|
-
createdAt: { type:
|
|
998
|
+
createdAt: { type: 'string', format: 'date-time' },
|
|
931
999
|
},
|
|
932
|
-
required: [
|
|
1000
|
+
required: ['id', 'title'],
|
|
933
1001
|
};
|
|
934
1002
|
```
|
|
935
1003
|
|
|
936
1004
|
### 3. 简化配置(Simple Config)
|
|
937
1005
|
|
|
938
1006
|
```typescript
|
|
939
|
-
import type { SimpleFieldsConfig } from
|
|
1007
|
+
import type { SimpleFieldsConfig } from '@wordrhyme/auto-crud';
|
|
940
1008
|
|
|
941
1009
|
const taskSchema: SimpleFieldsConfig = {
|
|
942
|
-
id: { type:
|
|
943
|
-
title: { type:
|
|
1010
|
+
id: { type: 'string', required: true },
|
|
1011
|
+
title: { type: 'string', label: '标题', required: true },
|
|
944
1012
|
status: {
|
|
945
|
-
type:
|
|
946
|
-
label:
|
|
947
|
-
options: [
|
|
1013
|
+
type: 'select',
|
|
1014
|
+
label: '状态',
|
|
1015
|
+
options: ['todo', 'in-progress', 'done'],
|
|
948
1016
|
},
|
|
949
|
-
description: { type:
|
|
950
|
-
createdAt: { type:
|
|
1017
|
+
description: { type: 'textarea', label: '描述' },
|
|
1018
|
+
createdAt: { type: 'datetime' },
|
|
951
1019
|
};
|
|
952
1020
|
```
|
|
953
1021
|
|
|
954
1022
|
### SchemaAdapter 使用
|
|
955
1023
|
|
|
956
1024
|
```typescript
|
|
957
|
-
import { SchemaAdapter } from
|
|
1025
|
+
import { SchemaAdapter } from '@wordrhyme/auto-crud';
|
|
958
1026
|
|
|
959
1027
|
// 自动检测 Schema 类型
|
|
960
|
-
const type = SchemaAdapter.detectType(schema);
|
|
1028
|
+
const type = SchemaAdapter.detectType(schema); // "zod" | "json" | "simple"
|
|
961
1029
|
|
|
962
1030
|
// 转换为统一的字段定义
|
|
963
1031
|
const fields = SchemaAdapter.toUnified(schema);
|
|
@@ -1119,48 +1187,69 @@ function CustomCrudPage() {
|
|
|
1119
1187
|
|
|
1120
1188
|
```typescript
|
|
1121
1189
|
// Auto-CRUD 组件
|
|
1122
|
-
export { AutoCrudTable } from
|
|
1123
|
-
export type {
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
export {
|
|
1190
|
+
export { AutoCrudTable } from './components/auto-crud/auto-crud-table';
|
|
1191
|
+
export type {
|
|
1192
|
+
Field,
|
|
1193
|
+
Fields,
|
|
1194
|
+
AutoCrudTableProps,
|
|
1195
|
+
} from './components/auto-crud/auto-crud-table';
|
|
1196
|
+
export { AutoForm } from './components/auto-crud/auto-form';
|
|
1197
|
+
export { AutoTable } from './components/auto-crud/auto-table';
|
|
1198
|
+
export { AutoTableActionBar } from './components/auto-crud/auto-table-action-bar';
|
|
1199
|
+
export { AutoTableSimpleFilters } from './components/auto-crud/auto-table-simple-filters';
|
|
1200
|
+
export { CrudFormModal } from './components/auto-crud/crud-form-modal';
|
|
1129
1201
|
|
|
1130
1202
|
// 数据表格组件
|
|
1131
|
-
export { DataTable } from
|
|
1132
|
-
export { DataTableAdvancedToolbar } from
|
|
1133
|
-
export { DataTableColumnHeader } from
|
|
1134
|
-
export { DataTableFacetedFilter } from
|
|
1135
|
-
export { DataTablePagination } from
|
|
1136
|
-
export { DataTableToolbar } from
|
|
1137
|
-
export { DataTableViewOptions } from
|
|
1203
|
+
export { DataTable } from './components/data-table/data-table';
|
|
1204
|
+
export { DataTableAdvancedToolbar } from './components/data-table/data-table-advanced-toolbar';
|
|
1205
|
+
export { DataTableColumnHeader } from './components/data-table/data-table-column-header';
|
|
1206
|
+
export { DataTableFacetedFilter } from './components/data-table/data-table-faceted-filter';
|
|
1207
|
+
export { DataTablePagination } from './components/data-table/data-table-pagination';
|
|
1208
|
+
export { DataTableToolbar } from './components/data-table/data-table-toolbar';
|
|
1209
|
+
export { DataTableViewOptions } from './components/data-table/data-table-view-options';
|
|
1138
1210
|
|
|
1139
1211
|
// Hooks
|
|
1140
|
-
export { useAutoCrudResource, noopToastAdapter } from
|
|
1141
|
-
export type {
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1212
|
+
export { useAutoCrudResource, noopToastAdapter } from './hooks/use-auto-crud-resource';
|
|
1213
|
+
export type {
|
|
1214
|
+
ToastAdapter,
|
|
1215
|
+
CrudHooks,
|
|
1216
|
+
UseAutoCrudResourceOptions,
|
|
1217
|
+
} from './hooks/use-auto-crud-resource';
|
|
1218
|
+
export { useDataTable } from './hooks/use-data-table';
|
|
1219
|
+
export { useReadableFilters } from './hooks/use-readable-filters';
|
|
1220
|
+
export { useUrlState, useQueryState, useQueryStates } from './hooks/use-url-state';
|
|
1145
1221
|
|
|
1146
1222
|
// Schema Bridge - 核心工具
|
|
1147
|
-
export {
|
|
1148
|
-
|
|
1149
|
-
|
|
1223
|
+
export {
|
|
1224
|
+
parseZodField,
|
|
1225
|
+
createTableSchema,
|
|
1226
|
+
createSelectColumn,
|
|
1227
|
+
createActionsColumn,
|
|
1228
|
+
} from './lib/schema-bridge/zod-to-columns';
|
|
1229
|
+
export {
|
|
1230
|
+
createFormSchema,
|
|
1231
|
+
createEditFormSchema,
|
|
1232
|
+
} from './lib/schema-bridge/zod-to-formily';
|
|
1233
|
+
export { SchemaAdapter } from './lib/schema-bridge/schema-adapter';
|
|
1150
1234
|
export type {
|
|
1151
|
-
ColumnOverrides,
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1235
|
+
ColumnOverrides,
|
|
1236
|
+
FormSchemaOverrides,
|
|
1237
|
+
CreateTableSchemaOptions,
|
|
1238
|
+
CreateFormSchemaOptions,
|
|
1239
|
+
UnifiedSchema,
|
|
1240
|
+
JSONSchema,
|
|
1241
|
+
SimpleFieldsConfig,
|
|
1242
|
+
UnifiedField,
|
|
1243
|
+
} from './lib/schema-bridge';
|
|
1155
1244
|
|
|
1156
1245
|
// 数据源
|
|
1157
|
-
export { createTRPCDataSource, createMemoryDataSource } from
|
|
1158
|
-
export type { DataSource, ListParams, ListResult } from
|
|
1246
|
+
export { createTRPCDataSource, createMemoryDataSource } from './lib/data-source';
|
|
1247
|
+
export type { DataSource, ListParams, ListResult } from './lib/data-source';
|
|
1159
1248
|
|
|
1160
1249
|
// 工具函数
|
|
1161
|
-
export { cn } from
|
|
1162
|
-
export { formatDate } from
|
|
1163
|
-
export { humanize } from
|
|
1250
|
+
export { cn } from './lib/utils';
|
|
1251
|
+
export { formatDate } from './lib/format';
|
|
1252
|
+
export { humanize } from './lib/humanize';
|
|
1164
1253
|
```
|
|
1165
1254
|
|
|
1166
1255
|
---
|