@formily-design/formily-antd 1.0.0 → 1.0.2
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 +8 -8
- package/.umirc.js +0 -44
- package/copy.ts +0 -6
- package/playground/components/AsyncSelect/AsyncSelect.tsx +0 -38
- package/playground/components/AsyncSelect/index.tsx +0 -1
- package/playground/components/AsyncSelect/preview.tsx +0 -36
- package/playground/components/ClickEventSetter/ActionConfigModal.tsx +0 -173
- package/playground/components/ClickEventSetter/ActionList.tsx +0 -67
- package/playground/components/ClickEventSetter/DownloadPanel.tsx +0 -24
- package/playground/components/ClickEventSetter/NavigationPanel.tsx +0 -42
- package/playground/components/ClickEventSetter/RequestPanel.tsx +0 -190
- package/playground/components/ClickEventSetter/index.tsx +0 -90
- package/playground/components/ClickEventSetter/styles.less +0 -89
- package/playground/components/ClickEventSetter/types.ts +0 -43
- package/playground/components/FormButton/FormButton.tsx +0 -189
- package/playground/components/FormButton/hooks/useEventActionExecutor.ts +0 -65
- package/playground/components/FormButton/index.ts +0 -1
- package/playground/components/FormButton/preview.tsx +0 -60
- package/playground/components/FormButton/utils/actionExecutors.ts +0 -96
- package/playground/components/FormButtonGroup/FormButtonGroup.tsx +0 -21
- package/playground/components/FormButtonGroup/index.ts +0 -1
- package/playground/components/FormButtonGroup/preview.tsx +0 -66
- package/playground/components/FormList/FormList.tsx +0 -164
- package/playground/components/FormList/index.tsx +0 -1
- package/playground/components/FormList/preview.tsx +0 -429
- package/playground/components/LocationPicker/LocationModal.tsx +0 -328
- package/playground/components/LocationPicker/LocationPicker.tsx +0 -163
- package/playground/components/LocationPicker/SearchBox.tsx +0 -122
- package/playground/components/LocationPicker/api.ts +0 -77
- package/playground/components/LocationPicker/constants.ts +0 -2
- package/playground/components/LocationPicker/index.tsx +0 -44
- package/playground/components/LocationPicker/types.ts +0 -160
- package/playground/components/LocationPicker/utils.ts +0 -46
- package/playground/components/ResourceIcon/index.module.less +0 -10
- package/playground/components/ResourceIcon/index.tsx +0 -10
- package/playground/designerLocales/en-US.ts +0 -38
- package/playground/designerLocales/index.ts +0 -6
- package/playground/designerLocales/ko-KR.ts +0 -10
- package/playground/designerLocales/zh-CN.ts +0 -38
- package/playground/locales/FormButton.ts +0 -38
- package/playground/locales/FormButtonGroup.ts +0 -29
- package/playground/locales/LocationPicker.ts +0 -30
- package/playground/locales/all.ts +0 -3
- package/playground/locales/index.ts +0 -3
- package/playground/main.tsx +0 -222
- package/playground/react-app-env.d.ts +0 -4
- package/playground/request.ts +0 -123
- package/playground/schemas/FormButton.ts +0 -42
- package/playground/schemas/FormButtonGroup.ts +0 -24
- package/playground/schemas/LocationPicker.ts +0 -14
- package/playground/schemas/all.ts +0 -3
- package/playground/schemas/index.ts +0 -3
- package/playground/service/index.ts +0 -1
- package/playground/service/schema.ts +0 -22
- package/playground/template.ejs +0 -20
- package/playground/utils.ts +0 -744
- package/playground/webpack.base.ts +0 -123
- package/playground/webpack.dev.ts +0 -64
- package/playground/webpack.prod.ts +0 -46
- package/playground/widgets/ActionsWidget.tsx +0 -58
- package/playground/widgets/LogoWidget.tsx +0 -20
- package/playground/widgets/MarkupSchemaWidget.tsx +0 -164
- package/playground/widgets/PreviewWidget.tsx +0 -188
- package/playground/widgets/SchemaEditorWidget.tsx +0 -27
- package/playground/widgets/index.ts +0 -5
- package/tsconfig.build.json +0 -12
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import React, { Fragment, useState, useMemo } from 'react'
|
|
2
|
-
import { Modal, Button } from 'antd'
|
|
3
|
-
import { usePrefix, TextWidget } from '@formily-design/react'
|
|
4
|
-
import { IEventAction, IEventConfig } from './types'
|
|
5
|
-
import { ActionList } from './ActionList'
|
|
6
|
-
import { ActionConfigModal } from './ActionConfigModal'
|
|
7
|
-
import './styles.less'
|
|
8
|
-
|
|
9
|
-
export interface IClickEventSetterProps {
|
|
10
|
-
className?: string
|
|
11
|
-
style?: React.CSSProperties
|
|
12
|
-
onChange: (value: IEventConfig) => void
|
|
13
|
-
value?: IEventConfig
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const ClickEventSetter: React.FC<IClickEventSetterProps> = (props) => {
|
|
17
|
-
const { value, onChange } = props
|
|
18
|
-
const prefix = usePrefix('click-event-setter')
|
|
19
|
-
const [modalVisible, setModalVisible] = useState(false)
|
|
20
|
-
const [editingAction, setEditingAction] = useState<IEventAction | null>(null)
|
|
21
|
-
const [editingIndex, setEditingIndex] = useState<number>(-1)
|
|
22
|
-
|
|
23
|
-
const actions = useMemo(() => value?.actions || [], [value])
|
|
24
|
-
|
|
25
|
-
const openModal = () => setModalVisible(true)
|
|
26
|
-
const closeModal = () => {
|
|
27
|
-
setModalVisible(false)
|
|
28
|
-
setEditingAction(null)
|
|
29
|
-
setEditingIndex(-1)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const handleEditAction = (action: IEventAction, index: number) => {
|
|
33
|
-
setEditingAction(action)
|
|
34
|
-
setEditingIndex(index)
|
|
35
|
-
setModalVisible(true)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const handleDeleteAction = (index: number) => {
|
|
39
|
-
const newActions = [...actions]
|
|
40
|
-
newActions.splice(index, 1)
|
|
41
|
-
onChange({ actions: newActions })
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const handleSaveAction = (action: IEventAction) => {
|
|
45
|
-
const newActions = [...actions]
|
|
46
|
-
if (editingIndex >= 0) {
|
|
47
|
-
newActions[editingIndex] = action
|
|
48
|
-
} else {
|
|
49
|
-
newActions.push(action)
|
|
50
|
-
}
|
|
51
|
-
onChange({ actions: newActions })
|
|
52
|
-
closeModal()
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return (
|
|
56
|
-
<Fragment>
|
|
57
|
-
<div className={`${prefix}-container`}>
|
|
58
|
-
<Button block onClick={openModal} className={`${prefix}-trigger`}>
|
|
59
|
-
<TextWidget token="SettingComponents.ClickEventSetter.configureEvents" />
|
|
60
|
-
</Button>
|
|
61
|
-
{actions.length > 0 && (
|
|
62
|
-
<ActionList
|
|
63
|
-
actions={actions}
|
|
64
|
-
onEdit={handleEditAction}
|
|
65
|
-
onDelete={handleDeleteAction}
|
|
66
|
-
/>
|
|
67
|
-
)}
|
|
68
|
-
</div>
|
|
69
|
-
<Modal
|
|
70
|
-
title={
|
|
71
|
-
<TextWidget token="SettingComponents.ClickEventSetter.configureEvents" />
|
|
72
|
-
}
|
|
73
|
-
width={700}
|
|
74
|
-
styles={{ body: { padding: 10 } }}
|
|
75
|
-
transitionName=""
|
|
76
|
-
maskTransitionName=""
|
|
77
|
-
open={modalVisible}
|
|
78
|
-
onCancel={closeModal}
|
|
79
|
-
footer={null}
|
|
80
|
-
destroyOnClose
|
|
81
|
-
>
|
|
82
|
-
<ActionConfigModal
|
|
83
|
-
editingAction={editingAction}
|
|
84
|
-
onSave={handleSaveAction}
|
|
85
|
-
onCancel={closeModal}
|
|
86
|
-
/>
|
|
87
|
-
</Modal>
|
|
88
|
-
</Fragment>
|
|
89
|
-
)
|
|
90
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
// @click-event-setter-prefix: ~'click-event-setter';
|
|
2
|
-
@click-event-setter-prefix: 'dn-click-event-setter';
|
|
3
|
-
|
|
4
|
-
.dn-click-event-setter-container {
|
|
5
|
-
width: 100%;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
.dn-click-event-setter-trigger {
|
|
9
|
-
margin-bottom: 8px;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/* Action List Styles */
|
|
13
|
-
.click-event-action-list {
|
|
14
|
-
width: 100%;
|
|
15
|
-
border: 1px solid #e8e8e8;
|
|
16
|
-
border-radius: 4px;
|
|
17
|
-
|
|
18
|
-
.click-event-action-item {
|
|
19
|
-
padding: 4px;
|
|
20
|
-
border-bottom: 1px solid #f0f0f0;
|
|
21
|
-
word-break: break-all;
|
|
22
|
-
|
|
23
|
-
&:last-child {
|
|
24
|
-
border-bottom: none;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
.ant-list-item-action {
|
|
28
|
-
margin-inline-start: 0;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
.click-event-action-title {
|
|
32
|
-
display: flex;
|
|
33
|
-
align-items: center;
|
|
34
|
-
gap: 2px;
|
|
35
|
-
|
|
36
|
-
.click-event-action-description {
|
|
37
|
-
color: #666;
|
|
38
|
-
font-size: 12px;
|
|
39
|
-
overflow: hidden;
|
|
40
|
-
text-overflow: ellipsis;
|
|
41
|
-
white-space: nowrap;
|
|
42
|
-
max-width: 300px;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/* Action Config Modal Styles */
|
|
49
|
-
.action-config-modal {
|
|
50
|
-
.action-config-basic {
|
|
51
|
-
padding: 8px 0;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
.action-config-panel {
|
|
55
|
-
padding: 8px 0;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.action-config-footer {
|
|
59
|
-
display: flex;
|
|
60
|
-
justify-content: flex-end;
|
|
61
|
-
gap: 8px;
|
|
62
|
-
margin-top: 16px;
|
|
63
|
-
padding-top: 16px;
|
|
64
|
-
border-top: 1px solid #f0f0f0;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/* Request Panel Styles */
|
|
69
|
-
.request-panel {
|
|
70
|
-
&-section {
|
|
71
|
-
padding: 8px 0;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
&-row {
|
|
75
|
-
display: flex;
|
|
76
|
-
align-items: center;
|
|
77
|
-
margin-bottom: 8px;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/* Navigation Panel Styles */
|
|
82
|
-
.navigation-panel {
|
|
83
|
-
padding: 8px 0;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/* Download Panel Styles */
|
|
87
|
-
.download-panel {
|
|
88
|
-
padding: 8px 0;
|
|
89
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// 事件动作类型
|
|
2
|
-
export type EventActionType = 'navigation' | 'request' | 'download'
|
|
3
|
-
|
|
4
|
-
// 事件配置结构
|
|
5
|
-
export interface IEventConfig {
|
|
6
|
-
actions: IEventAction[]
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
// 单个事件动作基础接口
|
|
10
|
-
export interface IEventActionBase {
|
|
11
|
-
id: string
|
|
12
|
-
type: EventActionType
|
|
13
|
-
description?: string
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// 页面跳转动作
|
|
17
|
-
export interface INavigationAction extends IEventActionBase {
|
|
18
|
-
type: 'navigation'
|
|
19
|
-
url: string
|
|
20
|
-
target?: '_blank' | '_self'
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// 服务请求动作
|
|
24
|
-
export interface IRequestAction extends IEventActionBase {
|
|
25
|
-
type: 'request'
|
|
26
|
-
url: string
|
|
27
|
-
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
|
|
28
|
-
headers?: Record<string, string>
|
|
29
|
-
params?: Record<string, string>
|
|
30
|
-
beforeRequest?: string
|
|
31
|
-
dataHandler?: string
|
|
32
|
-
successMessage?: string
|
|
33
|
-
dataKey?: string
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// 下载文件动作
|
|
37
|
-
export interface IDownloadAction extends IEventActionBase {
|
|
38
|
-
type: 'download'
|
|
39
|
-
url: string
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// 联合类型
|
|
43
|
-
export type IEventAction = INavigationAction | IRequestAction | IDownloadAction
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { DnFC } from '@formily-design/react'
|
|
3
|
-
import { Button as AntButton, ButtonProps } from 'antd'
|
|
4
|
-
import { Reset, Submit } from '@formily/antd-v5'
|
|
5
|
-
import { useForm, observer, useExpressionScope } from '@formily/react'
|
|
6
|
-
import { IEventAction } from '../ClickEventSetter/types'
|
|
7
|
-
import {
|
|
8
|
-
useEventActionExecutor,
|
|
9
|
-
hasActionOfType,
|
|
10
|
-
} from './hooks/useEventActionExecutor'
|
|
11
|
-
|
|
12
|
-
interface IFormButtonSetterProps {
|
|
13
|
-
/** 是否禁用表单验证 */
|
|
14
|
-
noValidate?: boolean
|
|
15
|
-
/** 事件配置 */
|
|
16
|
-
onEvent?: {
|
|
17
|
-
/** 点击事件配置 */
|
|
18
|
-
click?: {
|
|
19
|
-
/** 点击事件动作列表 */
|
|
20
|
-
actions: IEventAction[]
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface IFormButtonProps extends IFormButtonSetterProps, ButtonProps {
|
|
26
|
-
onClick?: (e: React.MouseEvent<Element, MouseEvent>) => void
|
|
27
|
-
title?: string
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export const FormButton: DnFC<IFormButtonProps> = (props: IFormButtonProps) => {
|
|
31
|
-
const { htmlType } = props
|
|
32
|
-
|
|
33
|
-
if (htmlType === 'reset')
|
|
34
|
-
return <ResetButton {...props}>{props.title}</ResetButton>
|
|
35
|
-
if (htmlType === 'submit')
|
|
36
|
-
return <SubmitButton {...props}>{props.title}</SubmitButton>
|
|
37
|
-
return <Button {...props}>{props.title}</Button>
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* 获取点击事件动作列表
|
|
42
|
-
*/
|
|
43
|
-
function getClickActions(
|
|
44
|
-
onEvent?: IFormButtonSetterProps['onEvent']
|
|
45
|
-
): IEventAction[] | undefined {
|
|
46
|
-
return onEvent?.click?.actions
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* 重置
|
|
51
|
-
* 为什么使用 observer 包裹?
|
|
52
|
-
* 因为 useForm() 获取的 form 实例是响应式的,observer 可以确保组件在 form 状态变化时重新渲染。使用 connect 或 observer 都可以达到这个目的。
|
|
53
|
-
* https://react.formilyjs.org/zh-CN/api/shared/observer
|
|
54
|
-
*/
|
|
55
|
-
const ResetButton = observer(
|
|
56
|
-
({
|
|
57
|
-
children,
|
|
58
|
-
onEvent,
|
|
59
|
-
...props
|
|
60
|
-
}: React.ComponentProps<typeof Reset> & IFormButtonSetterProps) => {
|
|
61
|
-
const form = useForm()
|
|
62
|
-
const actions = getClickActions(onEvent)
|
|
63
|
-
const { execute: executeEvents, executing } = useEventActionExecutor(
|
|
64
|
-
actions,
|
|
65
|
-
form
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
const handleClick = async () => {
|
|
69
|
-
if (actions && actions.length > 0) {
|
|
70
|
-
await executeEvents()
|
|
71
|
-
}
|
|
72
|
-
// 执行表单重置
|
|
73
|
-
form.reset()
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return (
|
|
77
|
-
<Reset
|
|
78
|
-
{...props}
|
|
79
|
-
htmlType="button"
|
|
80
|
-
loading={executing}
|
|
81
|
-
onClick={handleClick}
|
|
82
|
-
>
|
|
83
|
-
{children}
|
|
84
|
-
</Reset>
|
|
85
|
-
)
|
|
86
|
-
}
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
/** 提交 */
|
|
90
|
-
const SubmitButton = observer(
|
|
91
|
-
({
|
|
92
|
-
children,
|
|
93
|
-
noValidate,
|
|
94
|
-
onEvent,
|
|
95
|
-
...props
|
|
96
|
-
}: React.ComponentProps<typeof Submit> & IFormButtonSetterProps) => {
|
|
97
|
-
const form = useForm()
|
|
98
|
-
const actions = getClickActions(onEvent)
|
|
99
|
-
const hasRequestAction = hasActionOfType(actions, 'request')
|
|
100
|
-
const { execute: executeEvents, executing } = useEventActionExecutor(
|
|
101
|
-
actions,
|
|
102
|
-
form
|
|
103
|
-
)
|
|
104
|
-
// useExpressionScope 读取表达式作用域,获取表单配置的提交 API submitFormApi
|
|
105
|
-
const { submitFormApi, apiParams } = useExpressionScope()
|
|
106
|
-
const handleClick = async () => {
|
|
107
|
-
if (noValidate) {
|
|
108
|
-
// 获取表单值
|
|
109
|
-
const values = form.values
|
|
110
|
-
// 手动更新表单状态为提交中
|
|
111
|
-
form.setSubmitting(true)
|
|
112
|
-
try {
|
|
113
|
-
if (hasRequestAction) {
|
|
114
|
-
// 有 request 动作时,仅执行事件动作,不执行表单提交
|
|
115
|
-
await executeEvents(values, apiParams)
|
|
116
|
-
} else if (actions && actions.length > 0) {
|
|
117
|
-
// 有事件但无 request 动作时,先执行事件再提交
|
|
118
|
-
await executeEvents(values, apiParams)
|
|
119
|
-
await doSubmit(values)
|
|
120
|
-
} else {
|
|
121
|
-
// 无事件配置时,直接提交
|
|
122
|
-
await doSubmit(values)
|
|
123
|
-
}
|
|
124
|
-
} finally {
|
|
125
|
-
form.setSubmitting(false)
|
|
126
|
-
}
|
|
127
|
-
} else {
|
|
128
|
-
form.submit(async (values) => {
|
|
129
|
-
if (hasRequestAction) {
|
|
130
|
-
// 有 request 动作时,仅执行事件动作,不执行表单提交
|
|
131
|
-
await executeEvents(values, apiParams)
|
|
132
|
-
} else if (actions && actions.length > 0) {
|
|
133
|
-
// 有事件但无 request 动作时,先执行事件再提交
|
|
134
|
-
await executeEvents(values, apiParams)
|
|
135
|
-
await doSubmit(values)
|
|
136
|
-
} else {
|
|
137
|
-
// 无事件配置时,直接提交
|
|
138
|
-
await doSubmit(values)
|
|
139
|
-
}
|
|
140
|
-
})
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/** 表单提交 - 执行 form 配置的 API */
|
|
145
|
-
const doSubmit = async (values: Record<string, any>) => {
|
|
146
|
-
await submitFormApi?.(values)
|
|
147
|
-
}
|
|
148
|
-
return (
|
|
149
|
-
<Submit
|
|
150
|
-
{...props}
|
|
151
|
-
htmlType="button"
|
|
152
|
-
loading={executing || form.submitting}
|
|
153
|
-
onClick={handleClick}
|
|
154
|
-
>
|
|
155
|
-
{children}
|
|
156
|
-
</Submit>
|
|
157
|
-
)
|
|
158
|
-
}
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
/** 按钮 */
|
|
162
|
-
const Button = observer(
|
|
163
|
-
({
|
|
164
|
-
children,
|
|
165
|
-
onEvent,
|
|
166
|
-
...props
|
|
167
|
-
}: React.ComponentProps<typeof AntButton> & IFormButtonSetterProps) => {
|
|
168
|
-
const form = useForm()
|
|
169
|
-
const actions = getClickActions(onEvent)
|
|
170
|
-
// useExpressionScope 读取表达式作用域
|
|
171
|
-
const { apiParams } = useExpressionScope()
|
|
172
|
-
const { execute: executeEvents, executing } = useEventActionExecutor(
|
|
173
|
-
actions,
|
|
174
|
-
form
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
const handleClick = async () => {
|
|
178
|
-
if (actions && actions.length > 0) {
|
|
179
|
-
await executeEvents(form.values, apiParams)
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
return (
|
|
184
|
-
<AntButton {...props} loading={executing} onClick={handleClick}>
|
|
185
|
-
{children}
|
|
186
|
-
</AntButton>
|
|
187
|
-
)
|
|
188
|
-
}
|
|
189
|
-
)
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { useState, useCallback } from 'react'
|
|
2
|
-
import { IEventAction } from '../../ClickEventSetter/types'
|
|
3
|
-
import { executeActions } from '../utils/actionExecutors'
|
|
4
|
-
import { Form } from '@formily/core'
|
|
5
|
-
|
|
6
|
-
interface UseEventActionExecutorOptions {
|
|
7
|
-
onComplete?: () => void
|
|
8
|
-
onError?: (error: Error) => void
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
interface UseEventActionExecutorReturn {
|
|
12
|
-
executing: boolean
|
|
13
|
-
execute: (
|
|
14
|
-
formValues?: Record<string, any>,
|
|
15
|
-
apiParams?: Record<string, any>
|
|
16
|
-
) => Promise<void>
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function useEventActionExecutor(
|
|
20
|
-
actions: IEventAction[] | undefined,
|
|
21
|
-
form: Form,
|
|
22
|
-
options?: UseEventActionExecutorOptions
|
|
23
|
-
): UseEventActionExecutorReturn {
|
|
24
|
-
const [executing, setExecuting] = useState(false)
|
|
25
|
-
|
|
26
|
-
const execute = useCallback(
|
|
27
|
-
async (
|
|
28
|
-
formValues?: Record<string, any>,
|
|
29
|
-
apiParams?: Record<string, any>
|
|
30
|
-
) => {
|
|
31
|
-
if (!actions || actions.length === 0) {
|
|
32
|
-
return
|
|
33
|
-
}
|
|
34
|
-
setExecuting(true)
|
|
35
|
-
try {
|
|
36
|
-
await executeActions(actions, formValues, apiParams, (error, index) => {
|
|
37
|
-
console.error(`动作 ${index + 1} 执行失败:`, error)
|
|
38
|
-
})
|
|
39
|
-
options?.onComplete?.()
|
|
40
|
-
} catch (error) {
|
|
41
|
-
const err = error instanceof Error ? error : new Error(String(error))
|
|
42
|
-
options?.onError?.(err)
|
|
43
|
-
} finally {
|
|
44
|
-
setExecuting(false)
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
[actions, form, options]
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
executing,
|
|
52
|
-
execute,
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* 检查动作配置中是否包含指定类型的动作
|
|
58
|
-
*/
|
|
59
|
-
export function hasActionOfType(
|
|
60
|
-
actions: IEventAction[] | undefined,
|
|
61
|
-
type: string
|
|
62
|
-
): boolean {
|
|
63
|
-
if (!actions) return false
|
|
64
|
-
return actions.some((action) => action.type === type)
|
|
65
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './preview'
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { createBehavior, createResource } from '@formily-design/core'
|
|
3
|
-
import { DnFC } from '@formily-design/react'
|
|
4
|
-
import { ClickEventSetter } from '../ClickEventSetter'
|
|
5
|
-
import { FormButton as FormButtonComponent } from './FormButton'
|
|
6
|
-
import { CustomSchemas } from '../../schemas'
|
|
7
|
-
import { CustomLocales } from '../../locales'
|
|
8
|
-
|
|
9
|
-
export const FormButton: DnFC<
|
|
10
|
-
React.ComponentProps<typeof FormButtonComponent>
|
|
11
|
-
> = FormButtonComponent
|
|
12
|
-
|
|
13
|
-
FormButton.Behavior = createBehavior({
|
|
14
|
-
name: 'FormButton',
|
|
15
|
-
extends: ['Field'],
|
|
16
|
-
selector: (node) => node.props['x-component'] === 'FormButton',
|
|
17
|
-
designerProps: {
|
|
18
|
-
droppable: false,
|
|
19
|
-
propsSchema: {
|
|
20
|
-
type: 'object',
|
|
21
|
-
properties: {
|
|
22
|
-
'component-group': {
|
|
23
|
-
type: 'void',
|
|
24
|
-
'x-component': 'CollapseItem',
|
|
25
|
-
properties: {
|
|
26
|
-
'x-component-props': CustomSchemas.FormButton,
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
'event-group': {
|
|
30
|
-
type: 'void',
|
|
31
|
-
'x-component': 'CollapseItem',
|
|
32
|
-
properties: {
|
|
33
|
-
'x-component-props.onEvent.click': {
|
|
34
|
-
type: 'object',
|
|
35
|
-
'x-component': ClickEventSetter,
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
designerLocales: CustomLocales.FormButton,
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
FormButton.Resource = createResource({
|
|
46
|
-
icon: 'SelectSource',
|
|
47
|
-
elements: [
|
|
48
|
-
{
|
|
49
|
-
componentName: 'Field',
|
|
50
|
-
props: {
|
|
51
|
-
type: 'void',
|
|
52
|
-
title: 'FormButton',
|
|
53
|
-
'x-component': 'FormButton',
|
|
54
|
-
'x-component-props': {
|
|
55
|
-
title: '按钮',
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
],
|
|
60
|
-
})
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { message } from 'antd'
|
|
2
|
-
import {
|
|
3
|
-
IEventAction,
|
|
4
|
-
INavigationAction,
|
|
5
|
-
IRequestAction,
|
|
6
|
-
IDownloadAction,
|
|
7
|
-
} from '../../ClickEventSetter/types'
|
|
8
|
-
import { executeFormApi } from '../../../utils'
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* 执行页面跳转动作
|
|
12
|
-
*/
|
|
13
|
-
export function executeNavigationAction(action: INavigationAction) {
|
|
14
|
-
const { url, target = '_self' } = action
|
|
15
|
-
if (target === '_blank') {
|
|
16
|
-
window.open(url, '_blank')
|
|
17
|
-
} else {
|
|
18
|
-
window.location.href = url
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* 执行服务请求动作
|
|
24
|
-
*/
|
|
25
|
-
export async function executeRequestAction(
|
|
26
|
-
action: IRequestAction,
|
|
27
|
-
formValues?: Record<string, any>,
|
|
28
|
-
apiParams?: Record<string, any>
|
|
29
|
-
): Promise<void> {
|
|
30
|
-
const { successMessage } = action
|
|
31
|
-
|
|
32
|
-
await executeFormApi(action, formValues, { apiParams })
|
|
33
|
-
|
|
34
|
-
if (successMessage) {
|
|
35
|
-
message.success(successMessage)
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* 执行下载文件动作
|
|
41
|
-
*/
|
|
42
|
-
export function executeDownloadAction(action: IDownloadAction) {
|
|
43
|
-
const { url } = action
|
|
44
|
-
const link = document.createElement('a')
|
|
45
|
-
link.href = url
|
|
46
|
-
link.download = ''
|
|
47
|
-
link.target = '_blank'
|
|
48
|
-
link.style.display = 'none'
|
|
49
|
-
document.body.appendChild(link)
|
|
50
|
-
link.click()
|
|
51
|
-
document.body.removeChild(link)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* 根据动作类型执行对应的动作
|
|
56
|
-
*/
|
|
57
|
-
export async function executeAction(
|
|
58
|
-
action: IEventAction,
|
|
59
|
-
formValues?: Record<string, any>,
|
|
60
|
-
apiParams?: Record<string, any>
|
|
61
|
-
): Promise<void> {
|
|
62
|
-
switch (action.type) {
|
|
63
|
-
case 'navigation':
|
|
64
|
-
return executeNavigationAction(action)
|
|
65
|
-
case 'request':
|
|
66
|
-
return executeRequestAction(action, formValues, apiParams)
|
|
67
|
-
case 'download':
|
|
68
|
-
return executeDownloadAction(action)
|
|
69
|
-
default:
|
|
70
|
-
console.warn(`未知的动作类型: ${(action as any).type}`)
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* 按顺序执行所有动作
|
|
76
|
-
*/
|
|
77
|
-
export async function executeActions(
|
|
78
|
-
actions: IEventAction[],
|
|
79
|
-
formValues?: Record<string, any>,
|
|
80
|
-
apiParams?: Record<string, any>,
|
|
81
|
-
onError?: (error: Error, index: number) => void
|
|
82
|
-
): Promise<void> {
|
|
83
|
-
for (let i = 0; i < actions.length; i++) {
|
|
84
|
-
try {
|
|
85
|
-
await executeAction(actions[i], formValues, apiParams)
|
|
86
|
-
} catch (error) {
|
|
87
|
-
const err = error instanceof Error ? error : new Error(String(error))
|
|
88
|
-
if (onError) {
|
|
89
|
-
onError(err, i)
|
|
90
|
-
} else {
|
|
91
|
-
console.error(`动作 ${i + 1} 执行失败:`, err)
|
|
92
|
-
}
|
|
93
|
-
// 继续执行后续动作
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { connect, mapProps } from '@formily/react'
|
|
2
|
-
import { FormButtonGroup as ButtonGroup } from '@formily/antd-v5'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* 表单按钮组
|
|
6
|
-
* 为了实现只读模式下不显示按钮,特殊处理一下 FormButtonGroup 组件
|
|
7
|
-
* 判断表单模式,如果是只读模式,不显示内部所有按钮
|
|
8
|
-
*/
|
|
9
|
-
export const FormButtonGroup = connect(
|
|
10
|
-
ButtonGroup,
|
|
11
|
-
mapProps((props, field) => {
|
|
12
|
-
return {
|
|
13
|
-
...props,
|
|
14
|
-
// 只读模式下不显示按钮
|
|
15
|
-
children:
|
|
16
|
-
field.form.pattern === 'readOnly' || field.form.pattern === 'readPretty'
|
|
17
|
-
? null
|
|
18
|
-
: props.children,
|
|
19
|
-
}
|
|
20
|
-
})
|
|
21
|
-
)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './preview'
|