@wzyjs/uis 0.3.9 → 0.3.16
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/package.json +2 -2
- package/src/antd/form/FileUploader/index.tsx +163 -0
- package/src/antd/form/RadioButton/index.tsx +3 -1
- package/src/antd/form/index.ts +1 -0
- package/src/antd/index.ts +2 -0
- package/src/components/Crud/components/CardList/index.tsx +174 -0
- package/src/components/Crud/components/CreateUpdate/index.tsx +99 -0
- package/src/components/Crud/components/Provider/index.tsx +73 -0
- package/src/components/Crud/components/Remove/index.tsx +56 -0
- package/src/components/Crud/components/index.ts +4 -0
- package/src/components/Crud/hooks/index.ts +4 -0
- package/src/components/Crud/hooks/useColumns.tsx +169 -0
- package/src/components/Crud/hooks/useList.ts +54 -0
- package/src/components/Crud/hooks/useOrderable.tsx +107 -0
- package/src/components/Crud/hooks/useRequest.ts +41 -0
- package/src/components/Crud/index.tsx +91 -0
- package/src/components/Crud/types/index.ts +188 -0
- package/src/components/Crud/utils/index.ts +87 -0
- package/src/components/MindMap/context.tsx +29 -0
- package/src/components/MindMap/hooks/useAlignmentSnap.ts +220 -0
- package/src/components/MindMap/hooks/useCopyPaste.ts +272 -0
- package/src/components/MindMap/hooks/useDropToReparent.ts +288 -0
- package/src/components/MindMap/hooks/useExpandCollapse.ts +146 -0
- package/src/components/MindMap/hooks/useMoveDescendants.ts +136 -0
- package/src/components/MindMap/hooks/useUndoRedo.ts +232 -0
- package/src/components/MindMap/index.tsx +117 -0
- package/src/components/ProgressButton/index.module.scss +65 -0
- package/src/components/ProgressButton/index.tsx +96 -0
- package/src/components/TimelineBar/components/CurrentWeekHighlight/index.tsx +64 -0
- package/src/components/TimelineBar/components/Guides/index.tsx +61 -0
- package/src/components/TimelineBar/components/Ticks/index.tsx +56 -0
- package/src/components/TimelineBar/components/TodayIndicator/index.tsx +54 -0
- package/src/components/TimelineBar/components/index.ts +4 -0
- package/src/components/TimelineBar/const.ts +3 -0
- package/src/components/TimelineBar/hooks/index.ts +5 -0
- package/src/components/TimelineBar/hooks/useHighlightRange.ts +21 -0
- package/src/components/TimelineBar/hooks/useMonthGuides.ts +40 -0
- package/src/components/TimelineBar/hooks/useTickValues.ts +18 -0
- package/src/components/TimelineBar/hooks/useVisibleRange.ts +43 -0
- package/src/components/TimelineBar/hooks/useWeekGuides.ts +39 -0
- package/src/components/TimelineBar/index.tsx +63 -0
- package/src/components/TimelineBar/utils.ts +27 -0
- package/src/components/index.ts +4 -0
- package/src/rn.ts +1 -0
- package/src/rns/index.ts +0 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import React, { useMemo } from 'react'
|
|
2
|
+
|
|
3
|
+
import { Space } from 'antd'
|
|
4
|
+
import { CreateUpdate, Remove } from '../components'
|
|
5
|
+
|
|
6
|
+
import type { ProColumnsPro, CrudProps } from '../types'
|
|
7
|
+
|
|
8
|
+
interface UseColumnsParams {
|
|
9
|
+
columns: CrudProps['columns']
|
|
10
|
+
crud: CrudProps['crud']
|
|
11
|
+
update: CrudProps['update']
|
|
12
|
+
remove: CrudProps['remove']
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const normalizeCellDom = (dom: React.ReactNode): React.ReactNode => {
|
|
16
|
+
if (!dom || typeof dom !== 'object') {
|
|
17
|
+
return dom
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if ('children' in dom && 'props' in dom) {
|
|
21
|
+
return (dom as any).children
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return dom
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const normalizeRenderResult = (result: unknown) => {
|
|
28
|
+
if (!result || typeof result !== 'object') {
|
|
29
|
+
return result
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if ('children' in result && 'props' in result) {
|
|
33
|
+
return (result as any).children
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return result
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const useColumns = ({ columns, crud, update, remove }: UseColumnsParams) => {
|
|
40
|
+
// 检查是否需要显示操作列
|
|
41
|
+
const hasActions = update !== false || remove !== false
|
|
42
|
+
|
|
43
|
+
// 智能合并操作列
|
|
44
|
+
const finalColumns: ProColumnsPro[] = useMemo(() => {
|
|
45
|
+
// const proColumns = transformColumns(columns)
|
|
46
|
+
const proColumns: ProColumnsPro[] = columns.map((col: ProColumnsPro) => {
|
|
47
|
+
const isActionColumn: boolean = col.valueType === 'option'
|
|
48
|
+
|| col.key === 'option'
|
|
49
|
+
|| col.key === 'action'
|
|
50
|
+
|| col.title === '操作'
|
|
51
|
+
|
|
52
|
+
if (col.render) {
|
|
53
|
+
const originalRender = col.render
|
|
54
|
+
return {
|
|
55
|
+
...col,
|
|
56
|
+
render: (dom: any, record: any, index: any, action: any, schema: any) => {
|
|
57
|
+
return normalizeRenderResult(originalRender(dom, record, index, action, schema)) as any
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (isActionColumn) {
|
|
63
|
+
return col
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
...col,
|
|
68
|
+
// DragSortTable 需要包一层,不然有的字段不显示
|
|
69
|
+
render: (dom: React.ReactNode): React.ReactNode => normalizeCellDom(dom),
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
// 生成默认的操作按钮
|
|
74
|
+
const generateDefaultActions = (record: any) => {
|
|
75
|
+
const actions = []
|
|
76
|
+
|
|
77
|
+
if (update !== false) {
|
|
78
|
+
actions.push(
|
|
79
|
+
<CreateUpdate
|
|
80
|
+
key='update'
|
|
81
|
+
crud={crud}
|
|
82
|
+
columns={columns}
|
|
83
|
+
config={update || {}}
|
|
84
|
+
record={record}
|
|
85
|
+
/>,
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (remove !== false) {
|
|
90
|
+
actions.push(
|
|
91
|
+
<Remove
|
|
92
|
+
key='remove'
|
|
93
|
+
crud={crud}
|
|
94
|
+
config={remove || {}}
|
|
95
|
+
record={record}
|
|
96
|
+
/>,
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return actions
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// 查找是否已存在操作列
|
|
104
|
+
const existingActionColumnIndex = proColumns.findIndex(
|
|
105
|
+
col => col.key === 'option' || col.key === 'action' || col.title === '操作',
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
if (existingActionColumnIndex !== -1) {
|
|
109
|
+
// 如果已存在操作列,合并操作
|
|
110
|
+
const existingColumn = proColumns[existingActionColumnIndex]
|
|
111
|
+
if (!existingColumn) return proColumns
|
|
112
|
+
|
|
113
|
+
const originalRender = existingColumn.render
|
|
114
|
+
|
|
115
|
+
const mergedColumns = [...proColumns]
|
|
116
|
+
mergedColumns[existingActionColumnIndex] = {
|
|
117
|
+
...existingColumn,
|
|
118
|
+
render: (text: any, record: any, index: number, action: any, schema: any) => {
|
|
119
|
+
const defaultActions = hasActions ? generateDefaultActions(record) : []
|
|
120
|
+
|
|
121
|
+
// 如果用户定义了自定义渲染,调用它
|
|
122
|
+
if (originalRender) {
|
|
123
|
+
const customActions = originalRender(text, record, index, action, schema)
|
|
124
|
+
|
|
125
|
+
// 如果自定义渲染返回 ReactElement 或数组,合并操作
|
|
126
|
+
if (React.isValidElement(customActions) || Array.isArray(customActions)) {
|
|
127
|
+
return (
|
|
128
|
+
<Space>
|
|
129
|
+
{customActions}
|
|
130
|
+
{defaultActions}
|
|
131
|
+
</Space>
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 如果自定义渲染返回其他内容,直接使用
|
|
136
|
+
return customActions
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 没有自定义渲染时,只显示默认操作
|
|
140
|
+
return <Space>{defaultActions}</Space>
|
|
141
|
+
},
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return mergedColumns
|
|
145
|
+
} else {
|
|
146
|
+
// 如果不存在操作列且需要操作,添加新的操作列
|
|
147
|
+
return [
|
|
148
|
+
...proColumns,
|
|
149
|
+
...(hasActions ? [{
|
|
150
|
+
title: '操作',
|
|
151
|
+
dataIndex: 'action',
|
|
152
|
+
key: 'action',
|
|
153
|
+
fixed: 'right' as const,
|
|
154
|
+
width: 120,
|
|
155
|
+
search: false,
|
|
156
|
+
render: (_: any, record: any) => (
|
|
157
|
+
<Space>
|
|
158
|
+
{generateDefaultActions(record)}
|
|
159
|
+
</Space>
|
|
160
|
+
),
|
|
161
|
+
}] : []),
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
}, [columns, hasActions, update, remove, crud])
|
|
165
|
+
|
|
166
|
+
return {
|
|
167
|
+
finalColumns,
|
|
168
|
+
}
|
|
169
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useState, useEffect, useMemo } from 'react'
|
|
2
|
+
import type { CrudProps } from '../types'
|
|
3
|
+
|
|
4
|
+
interface UseTabsStateParams {
|
|
5
|
+
list: CrudProps['list']
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const useList = ({ list }: UseTabsStateParams) => {
|
|
9
|
+
// 初始化 activeTabKey 状态
|
|
10
|
+
const [activeTabKey, setTabActiveKey] = useState<string | undefined>(() => {
|
|
11
|
+
const tabs = list?.toolbar?.tabs as any
|
|
12
|
+
if (!tabs) {
|
|
13
|
+
return
|
|
14
|
+
}
|
|
15
|
+
return tabs.activeKey ?? tabs.items?.[0]?.key
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
// 当 Tab 变化时,将最新的类型通过 onChangeQuery 回传给父组件
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (activeTabKey !== undefined) {
|
|
21
|
+
list?.onChangeQuery?.({
|
|
22
|
+
where: { type: activeTabKey },
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
}, [activeTabKey])
|
|
26
|
+
|
|
27
|
+
// 构造最终传递给 ProTable 的 list 配置
|
|
28
|
+
const finalList = useMemo(() => {
|
|
29
|
+
if (!list?.toolbar?.tabs) return list ?? {}
|
|
30
|
+
|
|
31
|
+
const originalTabs: any = list.toolbar.tabs
|
|
32
|
+
|
|
33
|
+
const enhancedTabs = {
|
|
34
|
+
...originalTabs,
|
|
35
|
+
activeKey: activeTabKey,
|
|
36
|
+
onChange: setTabActiveKey,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
...list,
|
|
41
|
+
toolbar: {
|
|
42
|
+
...list.toolbar,
|
|
43
|
+
multipleLine: list.toolbar.multipleLine ?? !!list.toolbar.tabs.items?.length,
|
|
44
|
+
tabs: enhancedTabs,
|
|
45
|
+
},
|
|
46
|
+
}
|
|
47
|
+
}, [activeTabKey, list])
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
activeTabKey,
|
|
51
|
+
setTabActiveKey,
|
|
52
|
+
finalList,
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { useEffect, useMemo, useState } from 'react'
|
|
2
|
+
import type { CrudProps, ProColumnsPro } from '../types'
|
|
3
|
+
|
|
4
|
+
const dragSortKey = '__drag_sort__'
|
|
5
|
+
|
|
6
|
+
const getOrderableConfig = (
|
|
7
|
+
orderable: CrudProps['orderable'],
|
|
8
|
+
): Exclude<CrudProps['orderable'], boolean | undefined> => {
|
|
9
|
+
if (orderable && typeof orderable === 'object') {
|
|
10
|
+
return orderable
|
|
11
|
+
}
|
|
12
|
+
return {}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const sortByOrderField = <T extends Record<string, unknown>>(list: T[], orderField: string): T[] => {
|
|
16
|
+
const indexed = list.map((item, index) => ({ item, index }))
|
|
17
|
+
indexed.sort((a, b) => {
|
|
18
|
+
const av = a.item[orderField] as number | undefined
|
|
19
|
+
const bv = b.item[orderField] as number | undefined
|
|
20
|
+
|
|
21
|
+
const an = typeof av === 'number' && Number.isFinite(av) ? av : Number.POSITIVE_INFINITY
|
|
22
|
+
const bn = typeof bv === 'number' && Number.isFinite(bv) ? bv : Number.POSITIVE_INFINITY
|
|
23
|
+
|
|
24
|
+
return an - bn
|
|
25
|
+
})
|
|
26
|
+
return indexed.map(i => i.item)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const useOrderable = <T extends Record<string, unknown>>(params: {
|
|
30
|
+
orderable: CrudProps['orderable']
|
|
31
|
+
columns: ProColumnsPro<T>[]
|
|
32
|
+
crud: CrudProps['crud']
|
|
33
|
+
update: CrudProps['update']
|
|
34
|
+
readonly?: boolean
|
|
35
|
+
cardMode?: boolean
|
|
36
|
+
}) => {
|
|
37
|
+
const { orderable, columns, crud, update, readonly, cardMode } = params
|
|
38
|
+
|
|
39
|
+
const enabledFeature = !!orderable && !cardMode
|
|
40
|
+
const config = useMemo(() => getOrderableConfig(orderable), [orderable])
|
|
41
|
+
|
|
42
|
+
const orderField = config.orderField ?? 'sort'
|
|
43
|
+
const start = config.start ?? 0
|
|
44
|
+
|
|
45
|
+
const canUpdate = enabledFeature && !readonly && update !== false && !!crud.updateState?.mutateAsync
|
|
46
|
+
|
|
47
|
+
const [dataSource, setDataSource] = useState<T[]>([])
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (!enabledFeature) return
|
|
51
|
+
const list = (crud.listState.data as T[]) || []
|
|
52
|
+
setDataSource(sortByOrderField(list, orderField))
|
|
53
|
+
}, [enabledFeature, crud.listState.data, orderField])
|
|
54
|
+
|
|
55
|
+
const tableColumns = useMemo((): ProColumnsPro<T>[] => {
|
|
56
|
+
if (!enabledFeature) return columns
|
|
57
|
+
|
|
58
|
+
return [
|
|
59
|
+
{
|
|
60
|
+
title: '',
|
|
61
|
+
key: dragSortKey,
|
|
62
|
+
dataIndex: dragSortKey,
|
|
63
|
+
width: 48,
|
|
64
|
+
fixed: 'left',
|
|
65
|
+
hideInSearch: true,
|
|
66
|
+
hideInForm: true,
|
|
67
|
+
render: () => null,
|
|
68
|
+
} as ProColumnsPro<T>,
|
|
69
|
+
...columns,
|
|
70
|
+
]
|
|
71
|
+
}, [columns, enabledFeature])
|
|
72
|
+
|
|
73
|
+
const onDragSortEnd = async (
|
|
74
|
+
_beforeIndex: number,
|
|
75
|
+
_afterIndex: number,
|
|
76
|
+
newDataSource: T[],
|
|
77
|
+
) => {
|
|
78
|
+
const next = newDataSource.map((row, index) => ({
|
|
79
|
+
...row,
|
|
80
|
+
[orderField]: start + index,
|
|
81
|
+
})) as T[]
|
|
82
|
+
|
|
83
|
+
setDataSource(next)
|
|
84
|
+
|
|
85
|
+
if (!canUpdate) return
|
|
86
|
+
|
|
87
|
+
await Promise.allSettled(
|
|
88
|
+
next.map((row) => {
|
|
89
|
+
const id = row.id
|
|
90
|
+
if (typeof id !== 'string' || !id) {
|
|
91
|
+
return Promise.resolve()
|
|
92
|
+
}
|
|
93
|
+
return crud.updateState.mutateAsync(id, { [orderField]: row[orderField] })
|
|
94
|
+
}),
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
await crud.listState.refetch()
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
enabledFeature,
|
|
102
|
+
tableColumns,
|
|
103
|
+
dragSortKey: enabledFeature ? dragSortKey : undefined,
|
|
104
|
+
dataSource: enabledFeature ? dataSource : (crud.listState.data as T[] | undefined),
|
|
105
|
+
onDragSortEnd: enabledFeature ? onDragSortEnd : undefined,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { CrudProps, PaginationState } from '../types'
|
|
2
|
+
import { transformOrder, transformPagination, transformWhere } from '../utils'
|
|
3
|
+
|
|
4
|
+
interface UseRequest {
|
|
5
|
+
columns: CrudProps['columns']
|
|
6
|
+
list: CrudProps['list']
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const useRequest = ({ columns, list }: UseRequest) => {
|
|
10
|
+
const request = async (params: PaginationState, sort: any, filter: any) => {
|
|
11
|
+
const { current, pageSize, ...search } = params
|
|
12
|
+
|
|
13
|
+
// 转换分页参数
|
|
14
|
+
const pagination = transformPagination({ current, pageSize })
|
|
15
|
+
|
|
16
|
+
// 转换排序参数
|
|
17
|
+
const orderBy = transformOrder(sort)
|
|
18
|
+
|
|
19
|
+
// 转换过滤参数
|
|
20
|
+
const where = transformWhere(search, columns)
|
|
21
|
+
|
|
22
|
+
const query = {
|
|
23
|
+
...pagination,
|
|
24
|
+
...(orderBy && { orderBy }),
|
|
25
|
+
...(where && { where }),
|
|
26
|
+
}
|
|
27
|
+
console.log(666, 35, params, sort, search, filter, where, query)
|
|
28
|
+
|
|
29
|
+
list?.onChangeQuery?.(query)
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
data: [],
|
|
33
|
+
total: 0,
|
|
34
|
+
success: true,
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
request,
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { Space } from 'antd'
|
|
4
|
+
import { DragSortTable, ProTable } from '@ant-design/pro-components'
|
|
5
|
+
|
|
6
|
+
import { CardList, CreateUpdate, Provider } from './components'
|
|
7
|
+
|
|
8
|
+
import { useColumns, useList, useOrderable, useRequest } from './hooks'
|
|
9
|
+
|
|
10
|
+
export type { ProColumnsPro } from './types'
|
|
11
|
+
import type { CrudProps } from './types'
|
|
12
|
+
|
|
13
|
+
export const Crud = (props_: CrudProps) => {
|
|
14
|
+
const props = { ...props_ }
|
|
15
|
+
|
|
16
|
+
if (props.readonly) {
|
|
17
|
+
props.create = props.create ?? false
|
|
18
|
+
props.update = props.update ?? false
|
|
19
|
+
props.remove = props.remove ?? false
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const { crud, columns, list, create, update, remove, orderable } = props
|
|
23
|
+
|
|
24
|
+
const { tableColumns, dataSource, dragSortKey, onDragSortEnd } = useOrderable({
|
|
25
|
+
orderable,
|
|
26
|
+
columns,
|
|
27
|
+
crud,
|
|
28
|
+
update,
|
|
29
|
+
readonly: props.readonly,
|
|
30
|
+
cardMode: !!list?.cardConfig,
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const { finalColumns } = useColumns({ columns: tableColumns, crud, update, remove })
|
|
34
|
+
|
|
35
|
+
const { finalList } = useList({ list })
|
|
36
|
+
|
|
37
|
+
const { request } = useRequest({ list, columns })
|
|
38
|
+
|
|
39
|
+
const TableComponent = dragSortKey ? DragSortTable : ProTable
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Provider crud={crud}>
|
|
43
|
+
<TableComponent
|
|
44
|
+
rowKey='id'
|
|
45
|
+
loading={crud.listState.isLoading}
|
|
46
|
+
columns={finalColumns as any}
|
|
47
|
+
scroll={{ x: 'max-content' }}
|
|
48
|
+
search={{
|
|
49
|
+
labelWidth: 'auto',
|
|
50
|
+
}}
|
|
51
|
+
dataSource={dataSource}
|
|
52
|
+
request={request}
|
|
53
|
+
dragSortKey={dragSortKey}
|
|
54
|
+
onDragSortEnd={onDragSortEnd as any}
|
|
55
|
+
pagination={{
|
|
56
|
+
total: crud.countState.data,
|
|
57
|
+
showSizeChanger: true,
|
|
58
|
+
showQuickJumper: true,
|
|
59
|
+
defaultPageSize: 10,
|
|
60
|
+
pageSizeOptions: ['10', '15', '20', '30', '50'],
|
|
61
|
+
showTotal: (total, range) => `第 ${range[0]}-${range[1]} 条/总共 ${total} 条`,
|
|
62
|
+
}}
|
|
63
|
+
toolBarRender={() => [
|
|
64
|
+
create !== false ? (
|
|
65
|
+
<CreateUpdate
|
|
66
|
+
key='create'
|
|
67
|
+
crud={crud}
|
|
68
|
+
columns={tableColumns}
|
|
69
|
+
config={create || {}}
|
|
70
|
+
/>
|
|
71
|
+
) : null,
|
|
72
|
+
].filter(Boolean)}
|
|
73
|
+
tableRender={list?.cardConfig ? (props, dom, domList) => (
|
|
74
|
+
<Space style={{ width: '100%' }}>
|
|
75
|
+
{domList.toolbar}
|
|
76
|
+
<CardList
|
|
77
|
+
crud={crud}
|
|
78
|
+
columns={columns}
|
|
79
|
+
list={list}
|
|
80
|
+
create={create}
|
|
81
|
+
update={update}
|
|
82
|
+
remove={remove}
|
|
83
|
+
/>
|
|
84
|
+
</Space>
|
|
85
|
+
) : undefined}
|
|
86
|
+
{...finalList}
|
|
87
|
+
options={{ ...(finalList as CrudProps['list'])?.options, reload: () => (crud.countState.refetch(), crud.listState.refetch()) }}
|
|
88
|
+
/>
|
|
89
|
+
</Provider>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
2
|
+
import type { ButtonProps } from 'antd'
|
|
3
|
+
import type { ProTableProps, ProFormProps, ProColumns } from '@ant-design/pro-components'
|
|
4
|
+
|
|
5
|
+
// 扩展 ProColumns 类型,添加自定义的 valueType
|
|
6
|
+
export type ProColumnsPro<T = any> = Omit<ProColumns<T>, 'valueType'> & {
|
|
7
|
+
valueType?: ProColumns<T>['valueType'] | 'tags' | 'enabled'
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// 前端分页状态类型
|
|
11
|
+
export interface PaginationState {
|
|
12
|
+
current: number
|
|
13
|
+
pageSize: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// CRUD Hook 返回值类型(基于实际 tRPC hooks 的返回值)
|
|
17
|
+
export interface Crud {
|
|
18
|
+
listState: {
|
|
19
|
+
data?: any[]
|
|
20
|
+
isLoading?: boolean
|
|
21
|
+
error?: any
|
|
22
|
+
refetch: () => any
|
|
23
|
+
}
|
|
24
|
+
countState: {
|
|
25
|
+
data?: any
|
|
26
|
+
isLoading?: boolean
|
|
27
|
+
error?: any
|
|
28
|
+
refetch: () => any
|
|
29
|
+
}
|
|
30
|
+
createState: {
|
|
31
|
+
mutate: (data: any) => void
|
|
32
|
+
mutateAsync: (data: any) => Promise<any>
|
|
33
|
+
isLoading?: boolean
|
|
34
|
+
error?: any
|
|
35
|
+
}
|
|
36
|
+
updateState: {
|
|
37
|
+
mutate: (id: string, data: any) => void
|
|
38
|
+
mutateAsync: (id: string, data: any) => Promise<any>
|
|
39
|
+
isLoading?: boolean
|
|
40
|
+
error?: any
|
|
41
|
+
}
|
|
42
|
+
removeState: {
|
|
43
|
+
mutate: (id: string) => void
|
|
44
|
+
mutateAsync: (id: string) => Promise<any>
|
|
45
|
+
isLoading?: boolean
|
|
46
|
+
error?: any
|
|
47
|
+
}
|
|
48
|
+
deleteState: {
|
|
49
|
+
mutate: (id: string) => void
|
|
50
|
+
mutateAsync: (id: string) => Promise<any>
|
|
51
|
+
isLoading?: boolean
|
|
52
|
+
error?: any
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 卡片字段值类型:可以是字段名或自定义渲染内容
|
|
57
|
+
type CardFieldValue = string | ReactNode
|
|
58
|
+
|
|
59
|
+
// 卡片配置项
|
|
60
|
+
interface CardItem {
|
|
61
|
+
title?: CardFieldValue
|
|
62
|
+
extra?: CardFieldValue
|
|
63
|
+
content?: CardFieldValue
|
|
64
|
+
cover?: CardFieldValue
|
|
65
|
+
actions?: CardFieldValue[]
|
|
66
|
+
meta?: {
|
|
67
|
+
title?: CardFieldValue
|
|
68
|
+
description?: CardFieldValue
|
|
69
|
+
avatar?: CardFieldValue
|
|
70
|
+
}
|
|
71
|
+
props?: any // Card 组件的额外属性
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface CardConfig {
|
|
75
|
+
gutter?: [number, number] // 卡片间距
|
|
76
|
+
col?: {
|
|
77
|
+
xs?: number
|
|
78
|
+
sm?: number
|
|
79
|
+
md?: number
|
|
80
|
+
lg?: number
|
|
81
|
+
xl?: number
|
|
82
|
+
xxl?: number
|
|
83
|
+
} // 栅格配置
|
|
84
|
+
height?: string // 卡片列表容器高度
|
|
85
|
+
|
|
86
|
+
// 完全自定义渲染
|
|
87
|
+
render?: (record: any, index: number, defaultActions: ReactNode[]) => ReactNode
|
|
88
|
+
|
|
89
|
+
// 或者使用配置式渲染
|
|
90
|
+
card: CardItem | ((record: any, index: number) => CardItem)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 列表配置
|
|
94
|
+
export interface List extends Omit<ProTableProps<any, any>, 'columns' | 'dataSource' | 'loading'> {
|
|
95
|
+
onChangeQuery?: (query: any) => void // 用于更新查询参数
|
|
96
|
+
cardConfig?: CardConfig
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 创建配置
|
|
100
|
+
export interface Create {
|
|
101
|
+
mode?: 'modal' | 'drawer' // 创建模式,默认为 'drawer'
|
|
102
|
+
buttonProps?: ButtonProps // 创建按钮的属性
|
|
103
|
+
formProps?: ProFormProps // 创建表单的属性
|
|
104
|
+
transformData?: (values: Record<string, unknown>) => Record<string, unknown> | Promise<Record<string, unknown>> // 提交前转换 coverData?: (record: any) => Record<string, unknown> // 转换 record 用于表单回填
|
|
105
|
+
coverData?: (record: any) => Record<string, unknown> // 转换 record 用于表单回填
|
|
106
|
+
title?: string // 弹窗标题
|
|
107
|
+
width?: number | string // 弹窗宽度
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 更新配置
|
|
111
|
+
export interface Update {
|
|
112
|
+
mode?: 'modal' | 'drawer' // 更新模式,默认为 'drawer'
|
|
113
|
+
buttonProps?: ButtonProps // 更新按钮的属性
|
|
114
|
+
formProps?: ProFormProps // 更新表单的属性
|
|
115
|
+
transformData?: (values: Record<string, unknown>, record: any) => Record<string, unknown> | Promise<Record<string, unknown>> // 提交前转换
|
|
116
|
+
coverData?: (record: any) => Record<string, unknown> // 转换 record 用于表单回填
|
|
117
|
+
title?: string // 弹窗标题
|
|
118
|
+
width?: number | string // 弹窗宽度
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 删除配置
|
|
122
|
+
export interface Remove {
|
|
123
|
+
confirm?: boolean // 删除前是否需要确认,默认为 true
|
|
124
|
+
buttonProps?: ButtonProps // 删除按钮的属性
|
|
125
|
+
title?: string // 确认弹窗标题
|
|
126
|
+
content?: string // 确认弹窗内容
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface Orderable {
|
|
130
|
+
orderField?: string
|
|
131
|
+
start?: number
|
|
132
|
+
label?: string
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 主组件 Props
|
|
136
|
+
export interface CrudProps {
|
|
137
|
+
// 接口
|
|
138
|
+
crud: Crud // useHabitGroupCRUD() 的返回值
|
|
139
|
+
// 列表展示配置
|
|
140
|
+
columns: ProColumnsPro[]
|
|
141
|
+
// 列表配置
|
|
142
|
+
list?: List
|
|
143
|
+
// 创建配置
|
|
144
|
+
create?: false | Create // 为 false 时不显示创建按钮
|
|
145
|
+
// 更新配置
|
|
146
|
+
update?: false | Update // 为 false 时不显示更新按钮
|
|
147
|
+
// 删除配置
|
|
148
|
+
remove?: false | Remove // 为 false 时不显示删除按钮
|
|
149
|
+
// 排序配置
|
|
150
|
+
orderable?: boolean | Orderable
|
|
151
|
+
// 只读模式,开启后上述 create/update/remove 均等同于 false
|
|
152
|
+
readonly?: boolean
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export interface ListProps {
|
|
156
|
+
crud: Crud
|
|
157
|
+
columns: ProColumnsPro[]
|
|
158
|
+
list: List
|
|
159
|
+
create?: false | Create
|
|
160
|
+
update?: false | Update
|
|
161
|
+
remove?: false | Remove
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// export interface CreateProps {
|
|
165
|
+
// crud: Crud
|
|
166
|
+
// columns: ProColumnsPro[]
|
|
167
|
+
// config: Create
|
|
168
|
+
// }
|
|
169
|
+
//
|
|
170
|
+
// export interface UpdateProps {
|
|
171
|
+
// crud: Crud
|
|
172
|
+
// columns: ProColumnsPro[]
|
|
173
|
+
// config: Update
|
|
174
|
+
// record: any
|
|
175
|
+
// }
|
|
176
|
+
|
|
177
|
+
export interface RemoveProps {
|
|
178
|
+
crud: Crud
|
|
179
|
+
config: Remove
|
|
180
|
+
record: any
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export interface CreateUpdateProps {
|
|
184
|
+
crud: Crud
|
|
185
|
+
columns: ProColumnsPro[]
|
|
186
|
+
config: Create | Update
|
|
187
|
+
record?: any // 可选,有值时为编辑模式,无值时为创建模式
|
|
188
|
+
}
|