@wzyjs/uis 0.3.27 → 0.3.29
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 -3
- package/src/antd/pro/FoldCard/index.tsx +131 -0
- package/src/antd/pro/{Input/components/Range.tsx → RangeInput/index.tsx} +2 -2
- package/src/antd/pro/Tabs/index.tsx +135 -0
- package/src/antd/pro/buttons/ButtonGroup.tsx +26 -0
- package/src/antd/pro/{Button/components/Confirm.tsx → buttons/ConfirmButton.tsx} +2 -2
- package/src/antd/pro/{Button/components/Copy.tsx → buttons/CopyButton.tsx} +2 -2
- package/src/antd/pro/{Button/components/Drawer.tsx → buttons/DrawerButton.tsx} +2 -2
- package/src/antd/pro/buttons/index.tsx +4 -0
- package/src/antd/pro/index.ts +4 -9
- package/src/components/Crud/components/CreateUpdate/index.tsx +122 -42
- package/src/components/Crud/components/Provider/index.tsx +53 -43
- package/src/components/DynamicSelect/index.tsx +2 -0
- package/src/components/DynamicSelect/types.ts +8 -0
- package/src/components/DynamicSelect/utils.ts +2 -0
- package/src/components/index.ts +0 -1
- package/src/antd/pro/Alert/index.tsx +0 -24
- package/src/antd/pro/Button/components/Group.tsx +0 -26
- package/src/antd/pro/Button/index.tsx +0 -11
- package/src/antd/pro/Card/index.tsx +0 -92
- package/src/antd/pro/Collapse/components/Item.tsx +0 -30
- package/src/antd/pro/Collapse/index.tsx +0 -27
- package/src/antd/pro/Image/index.tsx +0 -17
- package/src/antd/pro/Input/index.tsx +0 -61
- package/src/antd/pro/Popconfirm/index.tsx +0 -16
- package/src/antd/pro/Radio/components/Cancel.tsx +0 -30
- package/src/antd/pro/Radio/index.tsx +0 -7
- package/src/antd/pro/Space/index.tsx +0 -15
- package/src/components/Fold/index.tsx +0 -52
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wzyjs/uis",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.29",
|
|
4
4
|
"description": "description",
|
|
5
5
|
"author": "wzy",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -39,7 +39,6 @@
|
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@wzyjs/hooks": "^0.2.37",
|
|
42
|
-
"@wzyjs/types": "^0.2.37",
|
|
43
42
|
"@wzyjs/utils": "^0.2.37",
|
|
44
43
|
"antd": "^6.0.0"
|
|
45
44
|
},
|
|
@@ -47,7 +46,7 @@
|
|
|
47
46
|
"@types/js-beautify": "^1.14.3",
|
|
48
47
|
"@types/react-grid-layout": "1.3.5"
|
|
49
48
|
},
|
|
50
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "a78702bb9367a10779eaa376ed70834d8b42b5a8",
|
|
51
50
|
"publishConfig": {
|
|
52
51
|
"access": "public"
|
|
53
52
|
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import React, { useState, useRef, useEffect, forwardRef, CSSProperties } from 'react'
|
|
4
|
+
import { Card, Button, CardProps } from 'antd'
|
|
5
|
+
import { DownOutlined, UpOutlined } from '@ant-design/icons'
|
|
6
|
+
|
|
7
|
+
export interface FoldCardProps extends CardProps {
|
|
8
|
+
max?: number; // 默认折叠高度,可根据需要调整
|
|
9
|
+
buttonStyle?: CSSProperties;
|
|
10
|
+
defaultCollapsed?: boolean;
|
|
11
|
+
showButtonOnHover?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const FoldCard = forwardRef((props: FoldCardProps, ref: any) => {
|
|
15
|
+
const {
|
|
16
|
+
max,
|
|
17
|
+
buttonStyle,
|
|
18
|
+
defaultCollapsed = true,
|
|
19
|
+
showButtonOnHover = true,
|
|
20
|
+
children,
|
|
21
|
+
style,
|
|
22
|
+
onMouseEnter,
|
|
23
|
+
onMouseLeave,
|
|
24
|
+
...rest
|
|
25
|
+
} = props
|
|
26
|
+
|
|
27
|
+
const maxHeight = max ?? 300
|
|
28
|
+
|
|
29
|
+
const [collapsed, setCollapsed] = useState(defaultCollapsed)
|
|
30
|
+
const [hovered, setHovered] = useState(false)
|
|
31
|
+
const [isOverflow, setIsOverflow] = useState(false)
|
|
32
|
+
const contentRef = useRef<HTMLDivElement>(null)
|
|
33
|
+
|
|
34
|
+
const measureOverflow = () => {
|
|
35
|
+
const contentEl = contentRef.current
|
|
36
|
+
if (!contentEl) {
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
setIsOverflow(contentEl.scrollHeight > maxHeight)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const toggleCollapse = (ev: React.MouseEvent<HTMLElement>) => {
|
|
44
|
+
ev.stopPropagation()
|
|
45
|
+
setCollapsed(value => !value)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
measureOverflow()
|
|
50
|
+
|
|
51
|
+
const contentEl = contentRef.current
|
|
52
|
+
if (!contentEl || typeof ResizeObserver === 'undefined') {
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const observer = new ResizeObserver(measureOverflow)
|
|
57
|
+
observer.observe(contentEl)
|
|
58
|
+
return () => observer.disconnect()
|
|
59
|
+
}, [children, maxHeight])
|
|
60
|
+
|
|
61
|
+
const contentStyle: CSSProperties = {
|
|
62
|
+
maxHeight: collapsed ? maxHeight : undefined,
|
|
63
|
+
transition: 'max-height 0.3s ease',
|
|
64
|
+
overflow: collapsed ? 'hidden' : 'visible',
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const hoverButtonContainerStyle: CSSProperties = {
|
|
68
|
+
position: 'absolute',
|
|
69
|
+
bottom: hovered ? 10 : -40,
|
|
70
|
+
left: '50%',
|
|
71
|
+
transform: 'translateX(-50%)',
|
|
72
|
+
transition: 'bottom 0.3s ease, opacity 0.3s ease',
|
|
73
|
+
display: 'flex',
|
|
74
|
+
justifyContent: 'center',
|
|
75
|
+
width: '100%',
|
|
76
|
+
pointerEvents: 'none',
|
|
77
|
+
opacity: hovered && isOverflow ? 1 : 0,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const inlineButtonContainerStyle: CSSProperties = {
|
|
81
|
+
textAlign: 'center',
|
|
82
|
+
marginTop: 8,
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const finalButtonStyle: CSSProperties = {
|
|
86
|
+
pointerEvents: 'auto',
|
|
87
|
+
border: 'none',
|
|
88
|
+
boxShadow: showButtonOnHover ? '0 2px 8px rgba(0, 0, 0, 0.15)' : undefined,
|
|
89
|
+
...buttonStyle,
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const button = (
|
|
93
|
+
<Button
|
|
94
|
+
size='small'
|
|
95
|
+
icon={collapsed ? <DownOutlined /> : <UpOutlined />}
|
|
96
|
+
onClick={toggleCollapse}
|
|
97
|
+
style={finalButtonStyle}
|
|
98
|
+
/>
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<Card
|
|
103
|
+
ref={ref}
|
|
104
|
+
style={{ position: 'relative', overflow: 'hidden', ...style }}
|
|
105
|
+
onMouseEnter={(ev) => {
|
|
106
|
+
setHovered(true)
|
|
107
|
+
onMouseEnter?.(ev)
|
|
108
|
+
}}
|
|
109
|
+
onMouseLeave={(ev) => {
|
|
110
|
+
setHovered(false)
|
|
111
|
+
onMouseLeave?.(ev)
|
|
112
|
+
}}
|
|
113
|
+
{...rest}
|
|
114
|
+
>
|
|
115
|
+
<div style={contentStyle} ref={contentRef}>
|
|
116
|
+
{children}
|
|
117
|
+
</div>
|
|
118
|
+
{isOverflow && (
|
|
119
|
+
showButtonOnHover ? (
|
|
120
|
+
<div style={hoverButtonContainerStyle}>
|
|
121
|
+
{button}
|
|
122
|
+
</div>
|
|
123
|
+
) : (
|
|
124
|
+
<div style={inlineButtonContainerStyle}>
|
|
125
|
+
{button}
|
|
126
|
+
</div>
|
|
127
|
+
)
|
|
128
|
+
)}
|
|
129
|
+
</Card>
|
|
130
|
+
)
|
|
131
|
+
})
|
|
@@ -4,7 +4,7 @@ import React from 'react'
|
|
|
4
4
|
import { InputNumber, InputNumberProps, Space } from 'antd'
|
|
5
5
|
import { _ } from '@wzyjs/utils/web'
|
|
6
6
|
|
|
7
|
-
export interface
|
|
7
|
+
export interface RangeInputProps extends Omit<InputNumberProps, 'value' | 'onChange'> {
|
|
8
8
|
value?: number[];
|
|
9
9
|
min?: number;
|
|
10
10
|
max?: number;
|
|
@@ -12,7 +12,7 @@ export interface RangeProps extends Omit<InputNumberProps, 'value' | 'onChange'>
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
// 最小值 最大值 的输入框
|
|
15
|
-
export const
|
|
15
|
+
export const RangeInput = (props: RangeInputProps) => {
|
|
16
16
|
const { value = [], min, max, onChange } = props
|
|
17
17
|
|
|
18
18
|
const onNumberChange = (index: 0 | 1, v: number | null) => {
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { Tabs, type TabsProps } from 'antd'
|
|
5
|
+
|
|
6
|
+
type SyncMode = 'replace' | 'push'
|
|
7
|
+
|
|
8
|
+
export interface TabsProProps extends TabsProps {
|
|
9
|
+
syncToUrl?: boolean
|
|
10
|
+
queryKey?: string
|
|
11
|
+
historyMode?: SyncMode
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const getItemKeys = (items?: TabsProps['items']): string[] => {
|
|
15
|
+
return (items || [])
|
|
16
|
+
.map(item => item?.key)
|
|
17
|
+
.filter((key): key is string => typeof key === 'string' && !!key)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const getUrlTabKey = (queryKey: string): string | undefined => {
|
|
21
|
+
if (typeof window === 'undefined') {
|
|
22
|
+
return undefined
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const value = new URLSearchParams(window.location.search).get(queryKey)
|
|
26
|
+
return value || undefined
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const updateUrlTabKey = (queryKey: string, key: string, mode: SyncMode) => {
|
|
30
|
+
if (typeof window === 'undefined') {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const url = new URL(window.location.href)
|
|
35
|
+
url.searchParams.set(queryKey, key)
|
|
36
|
+
|
|
37
|
+
const nextUrl = `${url.pathname}${url.search}${url.hash}`
|
|
38
|
+
if (mode === 'push') {
|
|
39
|
+
window.history.pushState(window.history.state, '', nextUrl)
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
window.history.replaceState(window.history.state, '', nextUrl)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const TabsPro = (props: TabsProProps) => {
|
|
47
|
+
const {
|
|
48
|
+
syncToUrl = false,
|
|
49
|
+
queryKey = 'tab',
|
|
50
|
+
historyMode = 'replace',
|
|
51
|
+
activeKey,
|
|
52
|
+
defaultActiveKey,
|
|
53
|
+
items,
|
|
54
|
+
onChange,
|
|
55
|
+
...rest
|
|
56
|
+
} = props
|
|
57
|
+
|
|
58
|
+
const itemKeys = React.useMemo(() => getItemKeys(items), [items])
|
|
59
|
+
|
|
60
|
+
const initialKey = React.useMemo(() => {
|
|
61
|
+
const urlKey = syncToUrl ? getUrlTabKey(queryKey) : undefined
|
|
62
|
+
if (urlKey && itemKeys.includes(urlKey)) {
|
|
63
|
+
return urlKey
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (typeof defaultActiveKey === 'string' && itemKeys.includes(defaultActiveKey)) {
|
|
67
|
+
return defaultActiveKey
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return itemKeys[0]
|
|
71
|
+
}, [defaultActiveKey, itemKeys, queryKey, syncToUrl])
|
|
72
|
+
|
|
73
|
+
const [innerActiveKey, setInnerActiveKey] = React.useState<string | undefined>(initialKey)
|
|
74
|
+
|
|
75
|
+
const mergedActiveKey = typeof activeKey === 'string' ? activeKey : innerActiveKey
|
|
76
|
+
|
|
77
|
+
React.useEffect(() => {
|
|
78
|
+
if (typeof activeKey === 'string') {
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
setInnerActiveKey(prev => {
|
|
83
|
+
if (prev && itemKeys.includes(prev)) {
|
|
84
|
+
return prev
|
|
85
|
+
}
|
|
86
|
+
return initialKey
|
|
87
|
+
})
|
|
88
|
+
}, [activeKey, initialKey, itemKeys])
|
|
89
|
+
|
|
90
|
+
React.useEffect(() => {
|
|
91
|
+
if (!syncToUrl || !mergedActiveKey) {
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
updateUrlTabKey(queryKey, mergedActiveKey, historyMode)
|
|
96
|
+
}, [historyMode, mergedActiveKey, queryKey, syncToUrl])
|
|
97
|
+
|
|
98
|
+
React.useEffect(() => {
|
|
99
|
+
if (!syncToUrl) {
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const onPopState = () => {
|
|
104
|
+
const urlKey = getUrlTabKey(queryKey)
|
|
105
|
+
if (!urlKey || !itemKeys.includes(urlKey)) {
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (typeof activeKey !== 'string') {
|
|
110
|
+
setInnerActiveKey(urlKey)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
onChange?.(urlKey)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
window.addEventListener('popstate', onPopState)
|
|
117
|
+
return () => {
|
|
118
|
+
window.removeEventListener('popstate', onPopState)
|
|
119
|
+
}
|
|
120
|
+
}, [activeKey, itemKeys, onChange, queryKey, syncToUrl])
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<Tabs
|
|
124
|
+
{...rest}
|
|
125
|
+
items={items}
|
|
126
|
+
activeKey={mergedActiveKey}
|
|
127
|
+
onChange={key => {
|
|
128
|
+
if (typeof activeKey !== 'string') {
|
|
129
|
+
setInnerActiveKey(key)
|
|
130
|
+
}
|
|
131
|
+
onChange?.(key)
|
|
132
|
+
}}
|
|
133
|
+
/>
|
|
134
|
+
)
|
|
135
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { Space } from 'antd'
|
|
5
|
+
import { ConfirmButton, ConfirmButtonProps } from './ConfirmButton'
|
|
6
|
+
|
|
7
|
+
export interface ButtonGroupProps {
|
|
8
|
+
list?: (ConfirmButtonProps & { visible?: boolean, title?: string })[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// 1. 按钮组
|
|
12
|
+
export const ButtonGroup = (props: ButtonGroupProps) => {
|
|
13
|
+
const { list = [] } = props
|
|
14
|
+
|
|
15
|
+
if (!list?.length) {
|
|
16
|
+
return null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Space.Compact>
|
|
21
|
+
{list.filter(item => item.visible).map((item, index) => (
|
|
22
|
+
<ConfirmButton key={index} {...item}>{item.title}</ConfirmButton>
|
|
23
|
+
))}
|
|
24
|
+
</Space.Compact>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
@@ -4,12 +4,12 @@ import React from 'react'
|
|
|
4
4
|
import { _ } from '@wzyjs/utils/web'
|
|
5
5
|
import { Button, Popconfirm, PopconfirmProps, ButtonProps } from 'antd'
|
|
6
6
|
|
|
7
|
-
export interface
|
|
7
|
+
export interface ConfirmButtonProps extends PopconfirmProps {
|
|
8
8
|
btnProps?: ButtonProps
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
// 1. 给按钮增加了确认功能
|
|
12
|
-
export const
|
|
12
|
+
export const ConfirmButton = (props: ConfirmButtonProps) => {
|
|
13
13
|
const { children, btnProps } = props
|
|
14
14
|
|
|
15
15
|
return (
|
|
@@ -8,12 +8,12 @@ import { CheckOutlined } from '@ant-design/icons'
|
|
|
8
8
|
import { copy, readClipboard } from '@wzyjs/utils/web'
|
|
9
9
|
import { useControllableValue } from '@wzyjs/hooks/web'
|
|
10
10
|
|
|
11
|
-
export interface
|
|
11
|
+
export interface CopyButtonProps extends ButtonProps {
|
|
12
12
|
value?: string,
|
|
13
13
|
canPaste?: boolean,
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export const
|
|
16
|
+
export const CopyButton = (props: CopyButtonProps) => {
|
|
17
17
|
const [icon, setIcon] = useState<ReactNode>(null)
|
|
18
18
|
const { message } = App.useApp()
|
|
19
19
|
|
|
@@ -4,12 +4,12 @@ import React, { useState } from 'react'
|
|
|
4
4
|
import { _ } from '@wzyjs/utils/web'
|
|
5
5
|
import { Button, Drawer as AntdDrawer, DrawerProps as AntdDrawerProps, ButtonProps } from 'antd'
|
|
6
6
|
|
|
7
|
-
export interface
|
|
7
|
+
export interface DrawerButtonProps extends AntdDrawerProps {
|
|
8
8
|
btnProps?: ButtonProps
|
|
9
9
|
defaultOpen?: boolean
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export const
|
|
12
|
+
export const DrawerButton = (props: DrawerButtonProps) => {
|
|
13
13
|
const { children, defaultOpen, btnProps } = props
|
|
14
14
|
const [open, setOpen] = useState<boolean>(defaultOpen ?? false)
|
|
15
15
|
|
package/src/antd/pro/index.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './Image'
|
|
6
|
-
export * from './Input'
|
|
7
|
-
export * from './Radio'
|
|
8
|
-
export * from './Space'
|
|
1
|
+
export * from './buttons'
|
|
2
|
+
export * from './FoldCard'
|
|
3
|
+
export * from './RangeInput'
|
|
4
|
+
export * from './Tabs'
|
|
9
5
|
export * from './Typography'
|
|
10
|
-
export * from './Popconfirm'
|
|
@@ -1,13 +1,50 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useMemo, useState } from 'react'
|
|
1
4
|
import { Button, type DrawerProps, type ModalProps } from 'antd'
|
|
2
5
|
import { PlusOutlined, EditOutlined } from '@ant-design/icons'
|
|
3
6
|
import { BetaSchemaForm } from '@ant-design/pro-components'
|
|
4
7
|
|
|
5
|
-
import type { CreateUpdateProps } from '../../types'
|
|
8
|
+
import type { CreateUpdateProps, ProColumnsPro } from '../../types'
|
|
9
|
+
|
|
10
|
+
const isActionColumn = (column: ProColumnsPro) => (
|
|
11
|
+
column.valueType === 'option'
|
|
12
|
+
|| column.key === 'option'
|
|
13
|
+
|| column.key === 'action'
|
|
14
|
+
|| column.title === '操作'
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
const getFormColumns = (columns: ProColumnsPro[]) => {
|
|
18
|
+
return columns
|
|
19
|
+
.filter(column => !column.hideInForm && !isActionColumn(column) && column.key !== '__drag_sort__')
|
|
20
|
+
.map((column) => {
|
|
21
|
+
const {
|
|
22
|
+
fixed,
|
|
23
|
+
sorter,
|
|
24
|
+
sortOrder,
|
|
25
|
+
defaultSortOrder,
|
|
26
|
+
filters,
|
|
27
|
+
onFilter,
|
|
28
|
+
onCell,
|
|
29
|
+
onHeaderCell,
|
|
30
|
+
ellipsis,
|
|
31
|
+
copyable,
|
|
32
|
+
render,
|
|
33
|
+
renderText,
|
|
34
|
+
width,
|
|
35
|
+
...formColumn
|
|
36
|
+
} = column as ProColumnsPro & Record<string, unknown>
|
|
37
|
+
|
|
38
|
+
return formColumn as ProColumnsPro
|
|
39
|
+
})
|
|
40
|
+
}
|
|
6
41
|
|
|
7
42
|
export const CreateUpdate = (props: CreateUpdateProps) => {
|
|
8
43
|
const { crud, columns, config, record } = props
|
|
9
44
|
|
|
10
45
|
const isEdit = !!record
|
|
46
|
+
const [open, setOpen] = useState(false)
|
|
47
|
+
const [formRendered, setFormRendered] = useState(false)
|
|
11
48
|
|
|
12
49
|
const {
|
|
13
50
|
mode = 'drawer',
|
|
@@ -19,20 +56,49 @@ export const CreateUpdate = (props: CreateUpdateProps) => {
|
|
|
19
56
|
width,
|
|
20
57
|
} = config
|
|
21
58
|
|
|
22
|
-
const {
|
|
59
|
+
const {
|
|
60
|
+
drawerProps,
|
|
61
|
+
modalProps,
|
|
62
|
+
initialValues,
|
|
63
|
+
onOpenChange,
|
|
64
|
+
onVisibleChange,
|
|
65
|
+
open: _open,
|
|
66
|
+
visible: _visible,
|
|
67
|
+
...formSafeProps
|
|
68
|
+
} = formProps as unknown as {
|
|
69
|
+
drawerProps?: DrawerProps
|
|
70
|
+
modalProps?: ModalProps
|
|
71
|
+
initialValues?: Record<string, unknown>
|
|
72
|
+
onOpenChange?: (open: boolean) => void
|
|
73
|
+
onVisibleChange?: (open: boolean) => void
|
|
74
|
+
open?: boolean
|
|
75
|
+
visible?: boolean
|
|
76
|
+
} & Record<string, unknown>
|
|
23
77
|
|
|
24
78
|
const layoutType = mode === 'modal' ? 'ModalForm' : 'DrawerForm'
|
|
25
79
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
80
|
+
const formColumns = useMemo(() => getFormColumns(columns), [columns])
|
|
81
|
+
|
|
82
|
+
const handleOpenChange = (nextOpen: boolean) => {
|
|
83
|
+
setOpen(nextOpen)
|
|
84
|
+
if (nextOpen) {
|
|
85
|
+
setFormRendered(true)
|
|
86
|
+
}
|
|
87
|
+
onOpenChange?.(nextOpen)
|
|
88
|
+
onVisibleChange?.(nextOpen)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const openForm = (event: any) => {
|
|
92
|
+
buttonProps.onClick?.(event)
|
|
93
|
+
if (event.defaultPrevented) {
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
setFormRendered(true)
|
|
97
|
+
setOpen(true)
|
|
98
|
+
}
|
|
33
99
|
|
|
34
100
|
const onFinish = async (values: Record<string, unknown>) => {
|
|
35
|
-
const finalValues = transformData ? transformData(values, record) : values
|
|
101
|
+
const finalValues = transformData ? await transformData(values, record) : values
|
|
36
102
|
|
|
37
103
|
if (isEdit) {
|
|
38
104
|
await crud.updateState.mutateAsync(record.id, finalValues)
|
|
@@ -47,7 +113,6 @@ export const CreateUpdate = (props: CreateUpdateProps) => {
|
|
|
47
113
|
return record.id
|
|
48
114
|
}
|
|
49
115
|
|
|
50
|
-
const initialValues: unknown = (formSafeProps as { initialValues?: unknown }).initialValues
|
|
51
116
|
if (!initialValues) {
|
|
52
117
|
return 'create'
|
|
53
118
|
}
|
|
@@ -63,37 +128,52 @@ export const CreateUpdate = (props: CreateUpdateProps) => {
|
|
|
63
128
|
}
|
|
64
129
|
})()
|
|
65
130
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}}
|
|
80
|
-
{...(drawerProps ? { drawerProps } : {})}
|
|
81
|
-
{...(modalProps ? { modalProps } : {})}
|
|
82
|
-
trigger={
|
|
83
|
-
isEdit ? (
|
|
84
|
-
<Button
|
|
85
|
-
type='link'
|
|
86
|
-
size='small'
|
|
87
|
-
icon={<EditOutlined />}
|
|
88
|
-
{...buttonProps}
|
|
89
|
-
/>
|
|
90
|
-
) : (
|
|
91
|
-
<Button type='primary' icon={<PlusOutlined />} {...buttonProps}>
|
|
92
|
-
新建
|
|
93
|
-
</Button>
|
|
94
|
-
)
|
|
95
|
-
}
|
|
96
|
-
{...formSafeProps}
|
|
131
|
+
const finalInitialValues = {
|
|
132
|
+
...(record ?? {}),
|
|
133
|
+
...(initialValues ?? {}),
|
|
134
|
+
...(coverData ? coverData(record) : {}),
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const trigger = isEdit ? (
|
|
138
|
+
<Button
|
|
139
|
+
type='link'
|
|
140
|
+
size='small'
|
|
141
|
+
icon={<EditOutlined />}
|
|
142
|
+
{...buttonProps}
|
|
143
|
+
onClick={openForm}
|
|
97
144
|
/>
|
|
145
|
+
) : (
|
|
146
|
+
<Button
|
|
147
|
+
type='primary'
|
|
148
|
+
icon={<PlusOutlined />}
|
|
149
|
+
{...buttonProps}
|
|
150
|
+
onClick={openForm}
|
|
151
|
+
>
|
|
152
|
+
新建
|
|
153
|
+
</Button>
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
<>
|
|
158
|
+
{trigger}
|
|
159
|
+
{formRendered ? (
|
|
160
|
+
<BetaSchemaForm
|
|
161
|
+
key={formKey}
|
|
162
|
+
layoutType={layoutType as any}
|
|
163
|
+
title={title}
|
|
164
|
+
width={width}
|
|
165
|
+
columns={formColumns as any}
|
|
166
|
+
onFinish={onFinish}
|
|
167
|
+
layout='horizontal'
|
|
168
|
+
labelCol={{ span: 4 }}
|
|
169
|
+
initialValues={finalInitialValues}
|
|
170
|
+
open={open}
|
|
171
|
+
onOpenChange={handleOpenChange}
|
|
172
|
+
{...(drawerProps ? { drawerProps } : {})}
|
|
173
|
+
{...(modalProps ? { modalProps } : {})}
|
|
174
|
+
{...formSafeProps}
|
|
175
|
+
/>
|
|
176
|
+
) : null}
|
|
177
|
+
</>
|
|
98
178
|
)
|
|
99
179
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { type PropsWithChildren, useContext, useMemo } from 'react'
|
|
2
4
|
import { Tag, Switch } from 'antd'
|
|
3
5
|
import { ProProvider, ProFormSelect } from '@ant-design/pro-components'
|
|
6
|
+
import type { ProRenderFieldPropsType } from '@ant-design/pro-provider'
|
|
4
7
|
|
|
5
8
|
import type { Crud } from '../../types'
|
|
6
9
|
|
|
@@ -19,52 +22,59 @@ export const Provider = (props: ProviderProps) => {
|
|
|
19
22
|
}
|
|
20
23
|
}
|
|
21
24
|
|
|
25
|
+
const valueTypeMap = useMemo<Record<string, ProRenderFieldPropsType>>(() => ({
|
|
26
|
+
...defaultContext.valueTypeMap,
|
|
27
|
+
tags: {
|
|
28
|
+
renderFormItem: (_: unknown, props: any) => {
|
|
29
|
+
const { options, ...restFieldProps } = props.fieldProps || {}
|
|
30
|
+
|
|
31
|
+
let processedOptions = options
|
|
32
|
+
|
|
33
|
+
if (Array.isArray(options) && options.length > 0 && typeof options[0] === 'string') {
|
|
34
|
+
processedOptions = options.map((item: string) => ({
|
|
35
|
+
label: item,
|
|
36
|
+
value: item,
|
|
37
|
+
}))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<ProFormSelect
|
|
42
|
+
placeholder='请输入标签'
|
|
43
|
+
mode='tags'
|
|
44
|
+
options={processedOptions}
|
|
45
|
+
{...restFieldProps}
|
|
46
|
+
/>
|
|
47
|
+
)
|
|
48
|
+
},
|
|
49
|
+
render: (tags: string[]) => {
|
|
50
|
+
return (
|
|
51
|
+
<>
|
|
52
|
+
{tags?.map((tag: string) => (
|
|
53
|
+
<Tag key={tag}>{tag}</Tag>
|
|
54
|
+
))}
|
|
55
|
+
</>
|
|
56
|
+
)
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
enabled: {
|
|
60
|
+
render: (enabled: boolean, props: any) => {
|
|
61
|
+
return (
|
|
62
|
+
<Switch
|
|
63
|
+
loading={crud?.updateState.isLoading}
|
|
64
|
+
checked={enabled}
|
|
65
|
+
onChange={enabled => onSwitchChange(props.record?.id, enabled)}
|
|
66
|
+
disabled={!crud?.updateState}
|
|
67
|
+
/>
|
|
68
|
+
)
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
}), [crud?.updateState, defaultContext.valueTypeMap])
|
|
72
|
+
|
|
22
73
|
return (
|
|
23
74
|
<ProProvider.Provider
|
|
24
75
|
value={{
|
|
25
76
|
...defaultContext,
|
|
26
|
-
valueTypeMap
|
|
27
|
-
tags: {
|
|
28
|
-
renderFormItem: (_: unknown, props) => {
|
|
29
|
-
const { options, ...restFieldProps } = props.fieldProps || {}
|
|
30
|
-
|
|
31
|
-
let processedOptions = options
|
|
32
|
-
|
|
33
|
-
if (Array.isArray(options) && options.length > 0 && typeof options[0] === 'string') {
|
|
34
|
-
processedOptions = options.map((item: string) => ({
|
|
35
|
-
label: item,
|
|
36
|
-
value: item,
|
|
37
|
-
}))
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return (
|
|
41
|
-
<ProFormSelect
|
|
42
|
-
placeholder='请输入标签'
|
|
43
|
-
mode='tags'
|
|
44
|
-
options={processedOptions}
|
|
45
|
-
{...restFieldProps}
|
|
46
|
-
/>
|
|
47
|
-
)
|
|
48
|
-
},
|
|
49
|
-
render: (tags: string[]) => {
|
|
50
|
-
return tags?.map((tag: string) => (
|
|
51
|
-
<Tag key={tag}>{tag}</Tag>
|
|
52
|
-
))
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
enabled: {
|
|
56
|
-
render: (enabled: boolean, props: any) => {
|
|
57
|
-
return (
|
|
58
|
-
<Switch
|
|
59
|
-
loading={crud?.updateState.isLoading}
|
|
60
|
-
checked={enabled}
|
|
61
|
-
onChange={enabled => onSwitchChange(props.record?.id, enabled)}
|
|
62
|
-
disabled={!crud?.updateState}
|
|
63
|
-
/>
|
|
64
|
-
)
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
},
|
|
77
|
+
valueTypeMap,
|
|
68
78
|
}}
|
|
69
79
|
>
|
|
70
80
|
{children}
|
package/src/components/index.ts
CHANGED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import React, { ReactNode } from 'react'
|
|
4
|
-
import { Alert, AlertProps, Space } from 'antd'
|
|
5
|
-
|
|
6
|
-
export interface AlertProProps extends AlertProps {
|
|
7
|
-
children?: ReactNode,
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
// 1. 支持 children 作为 description 显示
|
|
11
|
-
export const AlertPro = (props: AlertProProps) => {
|
|
12
|
-
const { children, description = children } = props
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
<Alert
|
|
16
|
-
{...props}
|
|
17
|
-
description={(
|
|
18
|
-
<Space style={{ width: '100%' }} orientation='vertical'>
|
|
19
|
-
{description}
|
|
20
|
-
</Space>
|
|
21
|
-
)}
|
|
22
|
-
/>
|
|
23
|
-
)
|
|
24
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import React from 'react'
|
|
4
|
-
import { Button } from 'antd'
|
|
5
|
-
import { Confirm, ConfirmProps } from './Confirm'
|
|
6
|
-
|
|
7
|
-
export interface GroupProps {
|
|
8
|
-
list?: (ConfirmProps & { visible?: boolean, title?: string })[]
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// 1. 按钮组
|
|
12
|
-
export const Group = (props: GroupProps) => {
|
|
13
|
-
const { list = [] } = props
|
|
14
|
-
|
|
15
|
-
if (!list?.length) {
|
|
16
|
-
return null
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<Button.Group>
|
|
21
|
-
{list.filter(item => item.visible).map((item, index) => (
|
|
22
|
-
<Confirm key={index} {...item}>{item.title}</Confirm>
|
|
23
|
-
))}
|
|
24
|
-
</Button.Group>
|
|
25
|
-
)
|
|
26
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import React, { useState, useRef, useEffect, forwardRef } from 'react'
|
|
4
|
-
import { Card, Button, CardProps } from 'antd'
|
|
5
|
-
import { DownOutlined, UpOutlined } from '@ant-design/icons'
|
|
6
|
-
|
|
7
|
-
interface CardProProps extends CardProps {
|
|
8
|
-
collapsedHeight?: number; // 默认折叠高度,可根据需要调整
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const CardPro = forwardRef((props: CardProProps, ref: any) => {
|
|
12
|
-
const { collapsedHeight = 300, children, ...rest } = props
|
|
13
|
-
|
|
14
|
-
const [collapsed, setCollapsed] = useState(true)
|
|
15
|
-
const [hovered, setHovered] = useState(false)
|
|
16
|
-
const [isOverflow, setIsOverflow] = useState(false)
|
|
17
|
-
const contentRef = useRef<HTMLSpanElement>(null)
|
|
18
|
-
|
|
19
|
-
const toggleCollapse = (ev: any) => {
|
|
20
|
-
ev.stopPropagation()
|
|
21
|
-
setCollapsed(!collapsed)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
const contentEl = contentRef.current
|
|
26
|
-
if (contentEl) {
|
|
27
|
-
// 获取内容的实际高度
|
|
28
|
-
const actualHeight = contentEl.scrollHeight
|
|
29
|
-
if (actualHeight > collapsedHeight) {
|
|
30
|
-
setIsOverflow(true)
|
|
31
|
-
} else {
|
|
32
|
-
setIsOverflow(false)
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}, [children, collapsedHeight])
|
|
36
|
-
|
|
37
|
-
const cardStyle: React.CSSProperties = {
|
|
38
|
-
position: 'relative',
|
|
39
|
-
overflow: 'hidden',
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const contentStyle: React.CSSProperties = {
|
|
43
|
-
maxHeight: collapsed ? `${collapsedHeight}px` : 'none',
|
|
44
|
-
overflowY: collapsed ? 'auto' : 'visible',
|
|
45
|
-
transition: 'max-height 0.3s ease',
|
|
46
|
-
display: 'block',
|
|
47
|
-
textOverflow: 'ellipsis',
|
|
48
|
-
overflow: 'hidden',
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const buttonContainerStyle: React.CSSProperties = {
|
|
52
|
-
position: 'absolute',
|
|
53
|
-
bottom: hovered ? '10px' : '-40px', // 增加隐藏时的负值,确保按钮完全隐藏
|
|
54
|
-
left: '50%',
|
|
55
|
-
transform: 'translateX(-50%)',
|
|
56
|
-
transition: 'bottom 0.3s ease, opacity 0.3s ease',
|
|
57
|
-
display: 'flex',
|
|
58
|
-
justifyContent: 'center',
|
|
59
|
-
width: '100%',
|
|
60
|
-
pointerEvents: 'none', // 默认情况下,禁止点击
|
|
61
|
-
opacity: hovered && isOverflow ? 1 : 0, // 控制按钮的透明度
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const buttonStyle: React.CSSProperties = {
|
|
65
|
-
pointerEvents: 'auto', // 允许按钮在悬停时可点击
|
|
66
|
-
border: 'none',
|
|
67
|
-
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return (
|
|
71
|
-
<Card
|
|
72
|
-
ref={ref}
|
|
73
|
-
style={cardStyle}
|
|
74
|
-
onMouseEnter={() => setHovered(true)}
|
|
75
|
-
onMouseLeave={() => setHovered(false)}
|
|
76
|
-
{...rest}
|
|
77
|
-
>
|
|
78
|
-
<span style={contentStyle} ref={contentRef}>
|
|
79
|
-
{children}
|
|
80
|
-
</span>
|
|
81
|
-
{isOverflow && (
|
|
82
|
-
<div style={buttonContainerStyle}>
|
|
83
|
-
<Button
|
|
84
|
-
icon={collapsed ? <DownOutlined /> : <UpOutlined />}
|
|
85
|
-
onClick={toggleCollapse}
|
|
86
|
-
style={buttonStyle}
|
|
87
|
-
/>
|
|
88
|
-
</div>
|
|
89
|
-
)}
|
|
90
|
-
</Card>
|
|
91
|
-
)
|
|
92
|
-
})
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import React from 'react'
|
|
4
|
-
import { Collapse, CollapsePanelProps, Space } from 'antd'
|
|
5
|
-
|
|
6
|
-
export interface CollapseItemProps extends Omit<CollapsePanelProps, 'key'> {
|
|
7
|
-
step?: boolean; // 为true自动给标题添加 `第{index}步:`
|
|
8
|
-
index?: number; // step为true时才需要
|
|
9
|
-
space?: boolean; // 子元素是否有间距
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export const Item = (props: CollapseItemProps) => {
|
|
13
|
-
const { step = true, header, index, space } = props
|
|
14
|
-
|
|
15
|
-
return (
|
|
16
|
-
<Collapse.Panel
|
|
17
|
-
key={String(header)}
|
|
18
|
-
{...props}
|
|
19
|
-
header={step ? `第${index}步: ${header}` : header}
|
|
20
|
-
>
|
|
21
|
-
{space ? (
|
|
22
|
-
<Space orientation='vertical' size='small' style={{ width: '100%' }}>
|
|
23
|
-
{props.children}
|
|
24
|
-
</Space>
|
|
25
|
-
) : (
|
|
26
|
-
props.children
|
|
27
|
-
)}
|
|
28
|
-
</Collapse.Panel>
|
|
29
|
-
)
|
|
30
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import React from 'react'
|
|
4
|
-
import { Collapse, CollapseProps } from 'antd'
|
|
5
|
-
import { Item, CollapseItemProps } from './components/Item'
|
|
6
|
-
|
|
7
|
-
export interface CollapseProProps extends CollapseProps {
|
|
8
|
-
list?: CollapseItemProps[],
|
|
9
|
-
step?: boolean; // 为true自动给标题添加 `第{index}步:`
|
|
10
|
-
space?: boolean; // 子元素是否有间距
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const CollapsePro = (props: CollapseProProps) => {
|
|
14
|
-
const { list = [], step = false, space = true, accordion = true } = props
|
|
15
|
-
|
|
16
|
-
if (!props.children && list.length) {
|
|
17
|
-
props.children = list.map((item, index) => (
|
|
18
|
-
<Item key={index} step={step} space={space} index={index + 1} {...item} />
|
|
19
|
-
))
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<Collapse accordion={accordion} {...props} />
|
|
24
|
-
)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
CollapsePro.Pane = Item
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import React from 'react'
|
|
4
|
-
import { Image, ImageProps } from 'antd'
|
|
5
|
-
|
|
6
|
-
export type ImageProProps = ImageProps
|
|
7
|
-
|
|
8
|
-
export const ImagePro = (props: ImageProProps) => {
|
|
9
|
-
const { preview = false } = props
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<Image
|
|
13
|
-
{...props}
|
|
14
|
-
preview={preview}
|
|
15
|
-
/>
|
|
16
|
-
)
|
|
17
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import React, { useState, useEffect, useMemo } from 'react'
|
|
4
|
-
import { Input, InputProps } from 'antd'
|
|
5
|
-
import { getStrLength } from '@wzyjs/utils/web'
|
|
6
|
-
import { Range } from './components/Range'
|
|
7
|
-
|
|
8
|
-
export interface InputProProps extends Omit<InputProps, 'onChange'> {
|
|
9
|
-
maxLengthChinese?: boolean; // 限制长度:中文算2个字符
|
|
10
|
-
onChange?: (value: string) => void
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// 1. 增加对中文字符串的长度限制 (Input的maxLength会认为汉字为1个长度)
|
|
14
|
-
export const InputPro = (props: InputProProps) => {
|
|
15
|
-
const {
|
|
16
|
-
value: _value,
|
|
17
|
-
onChange: _onChange,
|
|
18
|
-
addonAfter: _addonAfter,
|
|
19
|
-
maxLength,
|
|
20
|
-
maxLengthChinese,
|
|
21
|
-
...rest
|
|
22
|
-
} = props
|
|
23
|
-
|
|
24
|
-
const [value, setValue] = useState<string>('')
|
|
25
|
-
|
|
26
|
-
const addonAfter = useMemo(() => {
|
|
27
|
-
if (!maxLengthChinese) {
|
|
28
|
-
return _addonAfter
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<>
|
|
33
|
-
{_addonAfter}
|
|
34
|
-
{maxLength ? `${getStrLength(value)} / ${maxLength}` : null}
|
|
35
|
-
</>
|
|
36
|
-
)
|
|
37
|
-
}, [_addonAfter, value, maxLength])
|
|
38
|
-
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
_onChange?.(value)
|
|
41
|
-
}, [value])
|
|
42
|
-
|
|
43
|
-
const onChange = (ev: React.ChangeEvent<HTMLInputElement>) => {
|
|
44
|
-
if (maxLengthChinese && maxLength && getStrLength(ev.target.value) > maxLength) {
|
|
45
|
-
return
|
|
46
|
-
}
|
|
47
|
-
setValue(ev.target.value)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return (
|
|
51
|
-
<Input
|
|
52
|
-
value={value}
|
|
53
|
-
onChange={onChange}
|
|
54
|
-
addonAfter={addonAfter}
|
|
55
|
-
maxLength={maxLength}
|
|
56
|
-
{...rest}
|
|
57
|
-
/>
|
|
58
|
-
)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
InputPro.Range = Range
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import React from 'react'
|
|
4
|
-
import { Popconfirm, PopconfirmProps } from 'antd'
|
|
5
|
-
|
|
6
|
-
export type PopconfirmProProps = PopconfirmProps
|
|
7
|
-
|
|
8
|
-
export const PopconfirmPro = (props: PopconfirmProProps) => {
|
|
9
|
-
return (
|
|
10
|
-
<Popconfirm
|
|
11
|
-
okText="确定"
|
|
12
|
-
cancelText="取消"
|
|
13
|
-
{...props}
|
|
14
|
-
/>
|
|
15
|
-
)
|
|
16
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import React from 'react'
|
|
4
|
-
import { Checkbox, CheckboxProps, CheckboxOptionType } from 'antd'
|
|
5
|
-
|
|
6
|
-
export interface CancelProps {
|
|
7
|
-
value: CheckboxProps['value'];
|
|
8
|
-
options: CheckboxOptionType[];
|
|
9
|
-
onChange?: CheckboxProps['onChange'];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// 给Radio组件增加取消选择的功能,是用Checkbox组件实现的
|
|
13
|
-
export const Cancel = (props: CancelProps) => {
|
|
14
|
-
const { value, options, onChange } = props
|
|
15
|
-
|
|
16
|
-
const evs = {
|
|
17
|
-
onChange: (checkedValue: CheckboxProps['value'][]) => {
|
|
18
|
-
onChange?.(checkedValue.find(i => i !== value) || '')
|
|
19
|
-
},
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<Checkbox.Group
|
|
24
|
-
value={[value]}
|
|
25
|
-
prefixCls='ant-radio'
|
|
26
|
-
options={options}
|
|
27
|
-
onChange={evs.onChange}
|
|
28
|
-
/>
|
|
29
|
-
)
|
|
30
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import React from 'react'
|
|
4
|
-
import { Space, SpaceProps } from 'antd'
|
|
5
|
-
|
|
6
|
-
export type SpaceProProps = SpaceProps
|
|
7
|
-
|
|
8
|
-
export const SpacePro = (props: SpaceProProps) => {
|
|
9
|
-
return (
|
|
10
|
-
<Space
|
|
11
|
-
style={{ width: '100%' }}
|
|
12
|
-
{...props}
|
|
13
|
-
/>
|
|
14
|
-
)
|
|
15
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import React, { useState } from 'react'
|
|
4
|
-
import { Button } from 'antd'
|
|
5
|
-
import { DownOutlined, UpOutlined } from '@ant-design/icons'
|
|
6
|
-
|
|
7
|
-
interface FoldProps {
|
|
8
|
-
max: number
|
|
9
|
-
children?: React.ReactNode
|
|
10
|
-
btnStyle?: React.CSSProperties
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const Fold = (props: FoldProps) => {
|
|
14
|
-
const { max, children, btnStyle = {} } = props
|
|
15
|
-
|
|
16
|
-
const [collapsed, setCollapsed] = useState<boolean | undefined>(undefined)
|
|
17
|
-
|
|
18
|
-
const divRef = React.useRef<HTMLDivElement>(null)
|
|
19
|
-
|
|
20
|
-
React.useEffect(() => {
|
|
21
|
-
if (divRef.current) {
|
|
22
|
-
const { clientHeight } = divRef.current
|
|
23
|
-
if (clientHeight > max) {
|
|
24
|
-
setCollapsed(true)
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}, [divRef.current])
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<div ref={divRef} style={{ overflow: 'hidden' }}>
|
|
31
|
-
<div style={{ maxHeight: collapsed ? max : undefined }}>
|
|
32
|
-
{children}
|
|
33
|
-
</div>
|
|
34
|
-
|
|
35
|
-
<div style={{ textAlign: 'center', ...btnStyle }}>
|
|
36
|
-
{collapsed === undefined ? null : collapsed ? (
|
|
37
|
-
<Button
|
|
38
|
-
size='small'
|
|
39
|
-
icon={<DownOutlined />}
|
|
40
|
-
onClick={() => setCollapsed(false)}
|
|
41
|
-
/>
|
|
42
|
-
) : (
|
|
43
|
-
<Button
|
|
44
|
-
size='small'
|
|
45
|
-
icon={<UpOutlined />}
|
|
46
|
-
onClick={() => setCollapsed(true)}
|
|
47
|
-
/>
|
|
48
|
-
)}
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
)
|
|
52
|
-
}
|