add example
This commit is contained in:
		
							
								
								
									
										20
									
								
								packages/dooringx-example/src/plugin/commanderModules.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								packages/dooringx-example/src/plugin/commanderModules.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| /* | ||||
|  * @Author: yehuozhili | ||||
|  * @Date: 2021-07-07 14:27:01 | ||||
|  * @LastEditors: yehuozhili | ||||
|  * @LastEditTime: 2021-07-07 14:27:38 | ||||
|  * @FilePath: \visual-editor\src\plugin\commanderModules.ts | ||||
|  */ | ||||
|  | ||||
| import { CommanderItem } from 'dooringx-lib/dist/core/command/commanderType'; | ||||
|  | ||||
| const modulesFiles = (require as any).context('./commands', true, /\.(js|ts)$/); | ||||
| const commandModules: CommanderItem[] = modulesFiles | ||||
| 	.keys() | ||||
| 	.reduce((modules: any, modulePath: any) => { | ||||
| 		const value = modulesFiles(modulePath); | ||||
| 		modules.push(value.default); | ||||
| 		return modules; | ||||
| 	}, []); | ||||
|  | ||||
| export default commandModules; | ||||
							
								
								
									
										18
									
								
								packages/dooringx-example/src/plugin/commands/redo.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								packages/dooringx-example/src/plugin/commands/redo.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| /* | ||||
|  * @Author: yehuozhili | ||||
|  * @Date: 2021-07-07 14:28:20 | ||||
|  * @LastEditors: yehuozhili | ||||
|  * @LastEditTime: 2021-07-07 14:28:28 | ||||
|  * @FilePath: \visual-editor\src\plugin\commands\redo.ts | ||||
|  */ | ||||
| import { CommanderItemFactory } from 'dooringx-lib'; | ||||
| const undo = new CommanderItemFactory( | ||||
| 	'redo', | ||||
| 	'Control+Shift+z', | ||||
| 	(store) => { | ||||
| 		store.redo(); | ||||
| 	}, | ||||
| 	'重做' | ||||
| ); | ||||
|  | ||||
| export default undo; | ||||
							
								
								
									
										19
									
								
								packages/dooringx-example/src/plugin/commands/undo.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								packages/dooringx-example/src/plugin/commands/undo.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| /* | ||||
|  * @Author: yehuozhili | ||||
|  * @Date: 2021-07-07 14:28:00 | ||||
|  * @LastEditors: yehuozhili | ||||
|  * @LastEditTime: 2021-07-07 14:28:08 | ||||
|  * @FilePath: \visual-editor\src\plugin\commands\undo.ts | ||||
|  */ | ||||
| import { CommanderItemFactory } from 'dooringx-lib'; | ||||
|  | ||||
| const undo = new CommanderItemFactory( | ||||
| 	'undo', | ||||
| 	'Control+z', | ||||
| 	(store) => { | ||||
| 		store.undo(); | ||||
| 	}, | ||||
| 	'撤销' | ||||
| ); | ||||
|  | ||||
| export default undo; | ||||
							
								
								
									
										21
									
								
								packages/dooringx-example/src/plugin/formComponentModules.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								packages/dooringx-example/src/plugin/formComponentModules.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| /* | ||||
|  * @Author: yehuozhili | ||||
|  * @Date: 2021-07-07 14:29:38 | ||||
|  * @LastEditors: yehuozhili | ||||
|  * @LastEditTime: 2021-07-09 13:51:32 | ||||
|  * @FilePath: \dooringx\packages\dooringx-example\src\plugin\registFormComponents.ts | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| import { ComponentClass } from 'react'; | ||||
| import { FunctionComponent } from 'react'; | ||||
|  | ||||
| const modulesFiles = (require as any).context('./formComponents', true, /\.(js|tsx)$/); | ||||
| export const Formmodules: Record<string, FunctionComponent<any> | ComponentClass<any, any>> = | ||||
| 	modulesFiles.keys().reduce((modules: any, modulePath: any) => { | ||||
| 		const tmp = modulePath.split('.'); | ||||
| 		const name = tmp[tmp.length - 2].slice(1); | ||||
| 		const value = modulesFiles(modulePath); | ||||
| 		modules[name] = value.default; | ||||
| 		return modules; | ||||
| 	}, []); | ||||
| @@ -0,0 +1,515 @@ | ||||
| /* | ||||
|  * @Author: yehuozhili | ||||
|  * @Date: 2021-07-07 14:46:01 | ||||
|  * @LastEditors: yehuozhili | ||||
|  * @LastEditTime: 2021-07-10 18:33:35 | ||||
|  * @FilePath: \dooringx\packages\dooringx-example\src\plugin\formComponents\actionButton.tsx | ||||
|  */ | ||||
|  | ||||
| import { Button, Col, Input, message, Modal, Row, Select } from 'antd'; | ||||
| import { memo, useMemo, useState } from 'react'; | ||||
| import React from 'react'; | ||||
| import { UserConfig, createUid, deepCopy } from 'dooringx-lib'; | ||||
| import { unstable_batchedUpdates } from 'react-dom'; | ||||
| import { FormMap } from '../formTypes'; | ||||
| import { CreateOptionsRes } from 'dooringx-lib/dist/core/components/formTypes'; | ||||
| import { IBlockType, IStoreData } from 'dooringx-lib/dist/core/store/storetype'; | ||||
| import { FunctionConfigType } from 'dooringx-lib/dist/core/functionCenter/config'; | ||||
| import { EventCenterUserSelect } from 'dooringx-lib/dist/core/eventCenter'; | ||||
|  | ||||
| const { Option } = Select; | ||||
|  | ||||
| interface ActionButtonProps { | ||||
| 	data: CreateOptionsRes<FormMap, 'actionButton'>; | ||||
| 	current: IBlockType; | ||||
| 	config: UserConfig; | ||||
| } | ||||
|  | ||||
| function ActionButton(props: ActionButtonProps) { | ||||
| 	const [visible, setVisible] = useState(false); | ||||
| 	const [cur, setCur] = useState(''); | ||||
|  | ||||
| 	const eventMap = props.config.getEventCenter().getEventMap(); | ||||
| 	const currentOption = useMemo(() => { | ||||
| 		return Object.keys(eventMap).filter((v) => v.indexOf(props.current.id) >= 0); | ||||
| 	}, [eventMap, props.current.id]); | ||||
|  | ||||
| 	const [search, setSearch] = useState<EventCenterUserSelect[]>([]); | ||||
| 	const functionCenter = props.config.getEventCenter().getFunctionCenter(); | ||||
| 	const functionConfig = functionCenter.getConfigMap(); | ||||
| 	const functionMap = functionCenter.getFunctionMap(); | ||||
| 	const isEdit = props.config.getStoreChanger().isEdit(); | ||||
| 	const dataMap = props.config.getDataCenter().getDataMap(); | ||||
| 	let modalMap: Record<string, IStoreData>; | ||||
| 	if (isEdit) { | ||||
| 		modalMap = props.config.getStoreChanger().getOrigin()?.now.modalMap || {}; | ||||
| 	} else { | ||||
| 		modalMap = props.config.getStore().getData().modalMap; | ||||
| 	} | ||||
|  | ||||
| 	const handleInputDataSource = ( | ||||
| 		w: { | ||||
| 			uid: string; | ||||
| 			value: string; | ||||
| 			detail: Record<string, any>; | ||||
| 		}, | ||||
| 		c: any, | ||||
| 		name = 'dataSource' | ||||
| 	) => { | ||||
| 		return ( | ||||
| 			<div> | ||||
| 				<div | ||||
| 					style={{ | ||||
| 						textAlign: 'right', | ||||
| 						margin: '10px 0', | ||||
| 					}} | ||||
| 				> | ||||
| 					<Button | ||||
| 						type="primary" | ||||
| 						onClick={() => { | ||||
| 							setSearch((pre) => { | ||||
| 								pre.forEach((v) => { | ||||
| 									if (v.uid === w.uid) { | ||||
| 										let sign = true; | ||||
| 										if (!v.detail[name][c.name]) { | ||||
| 											v.detail[name][c.name] = []; | ||||
| 										} | ||||
| 										if (!c.options.multi) { | ||||
| 											if (v.detail[name][c.name].length >= 1) { | ||||
| 												sign = false; | ||||
| 												message.error('该函数最多只能添加1个'); | ||||
| 											} | ||||
| 										} | ||||
| 										if (sign) { | ||||
| 											v.detail[name][c.name].push(''); | ||||
| 										} | ||||
| 									} | ||||
| 								}); | ||||
| 								return [...pre]; | ||||
| 							}); | ||||
| 						}} | ||||
| 					> | ||||
| 						添加 | ||||
| 					</Button> | ||||
| 				</div> | ||||
| 				<div> | ||||
| 					{w.detail[name] && | ||||
| 						w.detail[name][c.name] && | ||||
| 						w.detail[name][c.name].map((vvv: string, x: number) => { | ||||
| 							return ( | ||||
| 								<Row key={x}> | ||||
| 									<Col span={19}> | ||||
| 										<Select | ||||
| 											style={{ width: '100%' }} | ||||
| 											value={vvv} | ||||
| 											onChange={(e) => { | ||||
| 												const value = e; | ||||
| 												setSearch((pre) => { | ||||
| 													pre.forEach((v) => { | ||||
| 														v.uid === w.uid ? (v.detail[name][c.name][x] = value || '') : ''; | ||||
| 													}); | ||||
| 													return [...pre]; | ||||
| 												}); | ||||
| 											}} | ||||
| 										> | ||||
| 											{Object.keys(dataMap).map((n) => { | ||||
| 												return ( | ||||
| 													<Option key={n} value={n}> | ||||
| 														{n} | ||||
| 													</Option> | ||||
| 												); | ||||
| 											})} | ||||
| 										</Select> | ||||
| 									</Col> | ||||
| 									<Col span={5} style={{ textAlign: 'right' }}> | ||||
| 										<Button | ||||
| 											danger | ||||
| 											onClick={() => { | ||||
| 												setSearch((pre) => { | ||||
| 													pre.forEach((v) => { | ||||
| 														v.uid === w.uid ? v.detail[name][c.name].splice(x, 1) : ''; | ||||
| 													}); | ||||
| 													return [...pre]; | ||||
| 												}); | ||||
| 											}} | ||||
| 										> | ||||
| 											删除 | ||||
| 										</Button> | ||||
| 									</Col> | ||||
| 								</Row> | ||||
| 							); | ||||
| 						})} | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		); | ||||
| 	}; | ||||
|  | ||||
| 	const handleInput = ( | ||||
| 		w: { | ||||
| 			uid: string; | ||||
| 			value: string; | ||||
| 			detail: Record<string, any>; | ||||
| 		}, | ||||
| 		c: any, | ||||
| 		name = 'ctx' | ||||
| 	) => { | ||||
| 		return ( | ||||
| 			<div> | ||||
| 				<div | ||||
| 					style={{ | ||||
| 						textAlign: 'right', | ||||
| 						margin: '10px 0', | ||||
| 					}} | ||||
| 				> | ||||
| 					<Button | ||||
| 						type="primary" | ||||
| 						onClick={() => { | ||||
| 							setSearch((pre) => { | ||||
| 								pre.forEach((v) => { | ||||
| 									if (v.uid === w.uid) { | ||||
| 										if (!v.detail[name][c.name]) { | ||||
| 											v.detail[name][c.name] = []; | ||||
| 										} | ||||
| 										let sign = true; | ||||
| 										if (!c.options.multi) { | ||||
| 											if (v.detail[name][c.name].length >= 1) { | ||||
| 												sign = false; | ||||
| 												message.error('该函数最多只能添加1个'); | ||||
| 											} | ||||
| 										} | ||||
| 										if (sign) { | ||||
| 											v.detail[name][c.name].push(''); | ||||
| 										} | ||||
| 									} | ||||
| 								}); | ||||
| 								return [...pre]; | ||||
| 							}); | ||||
| 						}} | ||||
| 					> | ||||
| 						添加输入框 | ||||
| 					</Button> | ||||
| 				</div> | ||||
| 				<div> | ||||
| 					{w.detail[name] && | ||||
| 						w.detail[name][c.name] && | ||||
| 						w.detail[name][c.name].map((vvv: string, x: number) => { | ||||
| 							return ( | ||||
| 								<Row key={x}> | ||||
| 									<Col span={19}> | ||||
| 										<Input | ||||
| 											value={vvv} | ||||
| 											onChange={(e) => { | ||||
| 												const value = e.target.value; | ||||
| 												setSearch((pre) => { | ||||
| 													pre.forEach((v) => { | ||||
| 														v.uid === w.uid ? (v.detail[name][c.name][x] = value || '') : ''; | ||||
| 													}); | ||||
| 													return [...pre]; | ||||
| 												}); | ||||
| 											}} | ||||
| 										></Input> | ||||
| 									</Col> | ||||
| 									<Col span={5} style={{ textAlign: 'right' }}> | ||||
| 										<Button | ||||
| 											danger | ||||
| 											onClick={() => { | ||||
| 												setSearch((pre) => { | ||||
| 													pre.forEach((v) => { | ||||
| 														v.uid === w.uid ? v.detail[name][c.name].splice(x, 1) : ''; | ||||
| 													}); | ||||
| 													return [...pre]; | ||||
| 												}); | ||||
| 											}} | ||||
| 										> | ||||
| 											删除 | ||||
| 										</Button> | ||||
| 									</Col> | ||||
| 								</Row> | ||||
| 							); | ||||
| 						})} | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		); | ||||
| 	}; | ||||
|  | ||||
| 	return ( | ||||
| 		<div style={{ padding: '10px 20px' }}> | ||||
| 			<Row | ||||
| 				style={{ | ||||
| 					padding: 20, | ||||
| 					justifyContent: 'space-between', | ||||
| 					alignItems: 'center', | ||||
| 				}} | ||||
| 			> | ||||
| 				<Col span={8}>标识ID</Col> | ||||
| 				<Col span={16}>{props.current.id}</Col> | ||||
| 			</Row> | ||||
| 			{currentOption.map((j, i) => { | ||||
| 				return ( | ||||
| 					<Row | ||||
| 						key={i} | ||||
| 						style={{ | ||||
| 							padding: 20, | ||||
| 							justifyContent: 'space-between', | ||||
| 							alignItems: 'center', | ||||
| 						}} | ||||
| 					> | ||||
| 						<div>{eventMap[j].displayName}</div> | ||||
| 						<Button | ||||
| 							onClick={() => { | ||||
| 								unstable_batchedUpdates(() => { | ||||
| 									setVisible(true); | ||||
| 									setCur((pre) => { | ||||
| 										if (pre !== j) { | ||||
| 											//查找该cur的选项 | ||||
| 											const store = props.config.getStore().getData(); | ||||
| 											let init: EventCenterUserSelect[] = []; | ||||
| 											store.block.forEach((v) => { | ||||
| 												if (v.id === props.current.id) { | ||||
| 													init = v.eventMap[j]?.userSelect || []; | ||||
| 												} | ||||
| 											}); | ||||
| 											setSearch(init); | ||||
| 										} | ||||
| 										return j; | ||||
| 									}); | ||||
| 								}); | ||||
| 							}} | ||||
| 						> | ||||
| 							配置 | ||||
| 						</Button> | ||||
| 					</Row> | ||||
| 				); | ||||
| 			})} | ||||
| 			<Modal | ||||
| 				width={800} | ||||
| 				title={'事件编辑' + `-${(eventMap[cur] && eventMap[cur].displayName) || ''}`} | ||||
| 				forceRender | ||||
| 				onOk={() => { | ||||
| 					// 更新store中的eventMap | ||||
| 					const store = props.config.getStore(); | ||||
| 					const cloneData: IStoreData = deepCopy(store.getData()); | ||||
| 					const arr = search.map((v) => { | ||||
| 						//   name: string; // 函数名 | ||||
| 						// args: Record<string, any>; // 输入参数都会变成对象传来, | ||||
| 						//  data: Record<string, FunctionDataType>; // 用户选的种类 键是每个配置项名 | ||||
| 						const name = v.value; //函数名 | ||||
| 						const options: FunctionConfigType = functionConfig[name]; | ||||
| 						const dataMap = v.detail['data']; | ||||
| 						const combine = options.map((jkk) => { | ||||
| 							const select: string = dataMap[jkk.name]; // datasource / input / modal | ||||
| 							let val = {}; | ||||
| 							if (select) { | ||||
| 								const value = v.detail[select]; //{name:array<>} | ||||
| 								const receive = jkk.options.receive; | ||||
| 								val = { [receive]: value[jkk.name] }; //这里不能换算,否则修改data后值不会更新 | ||||
| 							} | ||||
|  | ||||
| 							const choose = { [jkk.name]: select }; | ||||
| 							return { | ||||
| 								...v, | ||||
| 								choose, | ||||
| 								val, | ||||
| 							}; | ||||
| 						}); | ||||
| 						const combineVal = combine.reduce((prev, next) => { | ||||
| 							return Object.assign(prev, next.val); | ||||
| 						}, {}); | ||||
| 						const combineChoose = combine.reduce((prev, next) => { | ||||
| 							return Object.assign(prev, next.choose); | ||||
| 						}, {}); | ||||
|  | ||||
| 						return { | ||||
| 							name: name, | ||||
| 							data: combineChoose, | ||||
| 							args: combineVal, | ||||
| 						}; | ||||
| 					}); | ||||
| 					let displayName = ''; | ||||
| 					cloneData.block.forEach((v) => { | ||||
| 						if (v.id === props.current.id) { | ||||
| 							v.eventMap[cur].userSelect = search; | ||||
| 							v.eventMap[cur].arr = arr; | ||||
| 							displayName = v.eventMap[cur].displayName; | ||||
| 						} | ||||
| 					}); | ||||
| 					const eventCenter = props.config.getEventCenter(); | ||||
| 					eventCenter.manualUpdateMap(cur, displayName, arr); | ||||
| 					store.setData(cloneData); | ||||
| 					setVisible(false); | ||||
| 				}} | ||||
| 				onCancel={() => { | ||||
| 					setVisible(false); | ||||
| 				}} | ||||
| 				visible={visible} | ||||
| 			> | ||||
| 				<div> | ||||
| 					<Row align="middle"> | ||||
| 						<Col span={6}>触发事件ID:</Col> | ||||
| 						<Col span={18}>{cur}</Col> | ||||
| 					</Row> | ||||
| 					<Row justify="space-between" style={{ justifyContent: 'flex-end', margin: '20px 0' }}> | ||||
| 						<Button | ||||
| 							type="primary" | ||||
| 							onClick={() => { | ||||
| 								setSearch((pre) => { | ||||
| 									pre.push({ | ||||
| 										uid: createUid(), | ||||
| 										value: '', | ||||
| 										detail: { | ||||
| 											input: {}, | ||||
| 											ctx: {}, | ||||
| 											dataSource: {}, | ||||
| 											data: {}, | ||||
| 											modal: {}, | ||||
| 										}, | ||||
| 									}); | ||||
| 									return [...pre]; | ||||
| 								}); | ||||
| 							}} | ||||
| 						> | ||||
| 							添加事件 | ||||
| 						</Button> | ||||
| 					</Row> | ||||
| 					<div> | ||||
| 						{search.map((w, i) => { | ||||
| 							const current = search.find((v) => v.uid === w.uid); | ||||
| 							const options: FunctionConfigType | undefined = functionConfig[current?.value || '']; | ||||
| 							return ( | ||||
| 								<div key={w.uid}> | ||||
| 									<Row align="middle"> | ||||
| 										<Col span={6}>选择函数:</Col> | ||||
| 										<Col span={14}> | ||||
| 											<Select | ||||
| 												value={current?.value || ''} | ||||
| 												style={{ width: '100%' }} | ||||
| 												optionFilterProp="children" | ||||
| 												filterOption={(input, option) => | ||||
| 													option!.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 | ||||
| 												} | ||||
| 												onChange={(e) => { | ||||
| 													setSearch((pre) => { | ||||
| 														pre.forEach((v) => { | ||||
| 															// 切换选择要把下一级制空 | ||||
| 															if (v.uid === w.uid) { | ||||
| 																v.value = e as string; | ||||
| 																v.detail['data'] = {}; | ||||
| 															} | ||||
| 														}); | ||||
| 														return [...pre]; | ||||
| 													}); | ||||
| 												}} | ||||
| 											> | ||||
| 												{Object.keys(functionMap).map((v) => { | ||||
| 													return ( | ||||
| 														<Option key={v} value={v}> | ||||
| 															{v} | ||||
| 														</Option> | ||||
| 													); | ||||
| 												})} | ||||
| 											</Select> | ||||
| 										</Col> | ||||
| 										<Col span={4} style={{ textAlign: 'right' }}> | ||||
| 											<Button | ||||
| 												danger | ||||
| 												onClick={() => { | ||||
| 													setSearch((pre) => { | ||||
| 														pre.splice(i, 1); | ||||
| 														return [...pre]; | ||||
| 													}); | ||||
| 												}} | ||||
| 											> | ||||
| 												删除 | ||||
| 											</Button> | ||||
| 										</Col> | ||||
| 									</Row> | ||||
| 									<div | ||||
| 									//[{data: "" | ||||
| 									///   name: "改变文本数据源" | ||||
| 									//options: {receive: "_changeval"}}] | ||||
| 									> | ||||
| 										{options && | ||||
| 											options.map((c) => { | ||||
| 												return ( | ||||
| 													<Row key={c.name} style={{ margin: '10px 0' }}> | ||||
| 														<Col span={6}>{c.name}:</Col> | ||||
| 														<Col span={18}> | ||||
| 															{ | ||||
| 																<Select | ||||
| 																	value={current?.detail?.data?.[c.name] || ''} | ||||
| 																	style={{ width: '100%' }} | ||||
| 																	onChange={(e) => { | ||||
| 																		setSearch((pre) => { | ||||
| 																			pre.forEach((v) => { | ||||
| 																				v.uid === w.uid | ||||
| 																					? (v.detail['data'][c.name] = (e as string) || '') | ||||
| 																					: ''; | ||||
| 																			}); | ||||
| 																			return [...pre]; | ||||
| 																		}); | ||||
| 																	}} | ||||
| 																> | ||||
| 																	{c.data.includes('dataSource') && ( | ||||
| 																		<Option value="dataSource">数据源</Option> | ||||
| 																	)} | ||||
| 																	{c.data.includes('ctx') && <Option value="ctx">上下文</Option>} | ||||
| 																	{c.data.includes('input') && ( | ||||
| 																		<Option value="input">输入框</Option> | ||||
| 																	)} | ||||
| 																	{c.data.includes('modal') && ( | ||||
| 																		<Option value="modal">弹窗选择</Option> | ||||
| 																	)} | ||||
| 																</Select> | ||||
| 															} | ||||
|  | ||||
| 															{w.detail['data'] && w.detail['data'][c.name] === 'dataSource' && ( | ||||
| 																<div>{handleInputDataSource(w, c)}</div> | ||||
| 															)} | ||||
| 															{w.detail['data'] && w.detail['data'][c.name] === 'ctx' && ( | ||||
| 																<div>{handleInput(w, c, 'ctx')}</div> | ||||
| 															)} | ||||
| 															{w.detail['data'] && w.detail['data'][c.name] === 'input' && ( | ||||
| 																<div>{handleInput(w, c, 'input')}</div> | ||||
| 															)} | ||||
| 															{w.detail['data'] && w.detail['data'][c.name] === 'modal' && ( | ||||
| 																<div> | ||||
| 																	<Select | ||||
| 																		value={w.detail['modal'][c.name] || ''} | ||||
| 																		onChange={(e) => { | ||||
| 																			setSearch((pre) => { | ||||
| 																				pre.forEach((v) => { | ||||
| 																					v.uid === w.uid | ||||
| 																						? (v.detail['modal'][c.name] = (e as string) || '') | ||||
| 																						: ''; | ||||
| 																				}); | ||||
| 																				return [...pre]; | ||||
| 																			}); | ||||
| 																		}} | ||||
| 																		style={{ width: '100%' }} | ||||
| 																	> | ||||
| 																		{Object.keys(modalMap).map((v) => { | ||||
| 																			return ( | ||||
| 																				<Option key={v} value={v}> | ||||
| 																					{v} | ||||
| 																				</Option> | ||||
| 																			); | ||||
| 																		})} | ||||
| 																	</Select> | ||||
| 																</div> | ||||
| 															)} | ||||
| 														</Col> | ||||
| 													</Row> | ||||
| 												); | ||||
| 											})} | ||||
| 									</div> | ||||
| 								</div> | ||||
| 							); | ||||
| 						})} | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</Modal> | ||||
| 		</div> | ||||
| 	); | ||||
| } | ||||
|  | ||||
| export default memo(ActionButton); | ||||
| @@ -0,0 +1,309 @@ | ||||
| import React, { useMemo, useState } from 'react'; | ||||
| import { UserConfig, deepCopy } from 'dooringx-lib'; | ||||
| import { Col, Row, Select, InputNumber } from 'antd'; | ||||
| import { FormMap, FormBaseType } from '../formTypes'; | ||||
| import { CreateOptionsRes } from 'dooringx-lib/dist/core/components/formTypes'; | ||||
| import { IBlockType } from 'dooringx-lib/dist/core/store/storetype'; | ||||
|  | ||||
| export interface FormAnimateControlType extends FormBaseType {} | ||||
|  | ||||
| interface AnimateControlProps { | ||||
| 	data: CreateOptionsRes<FormMap, 'animateControl'>; | ||||
| 	current: IBlockType; | ||||
| 	config: UserConfig; | ||||
| } | ||||
|  | ||||
| //类型待修改 | ||||
| const animateCategory: Record<string, string> = { | ||||
| 	'': '无', | ||||
| 	animate__bounce: 'bounce', | ||||
| 	animate__flash: 'flash', | ||||
| 	animate__pulse: 'pulse', | ||||
| 	animate__rubberBand: 'rubberBand', | ||||
| 	animate__shakeX: 'shakeX', | ||||
| 	animate__shakeY: 'shakeY', | ||||
| 	animate__headShake: 'headShake', | ||||
| 	animate__swing: 'swing', | ||||
| 	animate__tada: 'tada', | ||||
| 	animate__wobble: 'wobble', | ||||
| 	animate__jello: 'jello', | ||||
| 	animate__heartBeat: 'heartBeat', | ||||
| 	animate__backInDown: 'backInDown', | ||||
| 	animate__backInLeft: 'backInLeft', | ||||
| 	animate__backInRight: 'backInRight', | ||||
| 	animate__backInUp: 'backInUp', | ||||
| 	animate__backOutDown: 'backOutDown', | ||||
| 	animate__backOutLeft: 'backOutLeft', | ||||
| 	animate__backOutRight: 'backOutRight', | ||||
| 	animate__backOutUp: 'backOutUp', | ||||
| 	animate__bounceIn: 'bounceIn', | ||||
| 	animate__bounceInDown: 'bounceInDown', | ||||
| 	animate__bounceInLeft: 'bounceInLeft', | ||||
| 	animate__bounceInRight: 'bounceInRight', | ||||
| 	animate__bounceInUp: 'bounceInUp', | ||||
| 	animate__bounceOut: 'bounceOut', | ||||
| 	animate__bounceOutDown: 'bounceOutDown', | ||||
| 	animate__bounceOutLeft: 'bounceOutLeft', | ||||
| 	animate__bounceOutRight: 'bounceOutRight', | ||||
| 	animate__bounceOutUp: 'bounceOutUp', | ||||
| 	animate__fadeIn: 'fadeIn', | ||||
| 	animate__fadeInDown: 'fadeInDown', | ||||
| 	animate__fadeInDownBig: 'fadeInDownBig', | ||||
| 	animate__fadeInLeft: 'fadeInLeft', | ||||
| 	animate__fadeInLeftBig: 'fadeInLeftBig', | ||||
| 	animate__fadeInRight: 'fadeInRight', | ||||
| 	animate__fadeInRightBig: 'fadeInRightBig', | ||||
| 	animate__fadeInUp: 'fadeInUp', | ||||
| 	animate__fadeInUpBig: 'fadeInUpBig', | ||||
| 	animate__fadeInTopLeft: 'fadeInTopLeft', | ||||
| 	animate__fadeInTopRight: 'fadeInTopRight', | ||||
| 	animate__fadeInBottomLeft: 'fadeInBottomLeft', | ||||
| 	animate__fadeInBottomRight: 'fadeInBottomRight', | ||||
| 	animate__fadeOut: 'fadeOut', | ||||
| 	animate__fadeOutDown: 'fadeOutDown', | ||||
| 	animate__fadeOutDownBig: 'fadeOutDownBig', | ||||
| 	animate__fadeOutLeft: 'fadeOutLeft', | ||||
| 	animate__fadeOutLeftBig: 'fadeOutLeftBig', | ||||
| 	animate__fadeOutRight: 'fadeOutRight', | ||||
| 	animate__fadeOutRightBig: 'fadeOutRightBig', | ||||
| 	animate__fadeOutUp: 'fadeOutUp', | ||||
| 	animate__fadeOutUpBig: 'fadeOutUpBig', | ||||
| 	animate__fadeOutTopLeft: 'fadeOutTopLeft', | ||||
| 	animate__fadeOutTopRight: 'fadeOutTopRight', | ||||
| 	animate__fadeOutBottomRight: 'fadeOutBottomRight', | ||||
| 	animate__fadeOutBottomLeft: 'fadeOutBottomLeft', | ||||
| 	animate__flip: 'flip', | ||||
| 	animate__flipInX: 'flipInX', | ||||
| 	animate__flipInY: 'flipInY', | ||||
| 	animate__flipOutX: 'flipOutX', | ||||
| 	animate__flipOutY: 'flipOutY', | ||||
| 	animate__lightSpeedInRight: 'lightSpeedInRight', | ||||
| 	animate__lightSpeedInLeft: 'lightSpeedInLeft', | ||||
| 	animate__lightSpeedOutRight: 'lightSpeedOutRight', | ||||
| 	animate__lightSpeedOutLeft: 'lightSpeedOutLeft', | ||||
| 	animate__rotateIn: 'rotateIn', | ||||
| 	animate__rotateInDownLeft: 'rotateInDownLeft', | ||||
| 	animate__rotateInDownRight: 'rotateInDownRight', | ||||
| 	animate__rotateInUpLeft: 'rotateInUpLeft', | ||||
| 	animate__rotateInUpRight: 'rotateInUpRight', | ||||
| 	animate__rotateOut: 'rotateOut', | ||||
| 	animate__rotateOutDownLeft: 'rotateOutDownLeft', | ||||
| 	animate__rotateOutDownRight: 'rotateOutDownRight', | ||||
| 	animate__rotateOutUpLeft: 'rotateOutUpLeft', | ||||
| 	animate__rotateOutUpRight: 'rotateOutUpRight', | ||||
| 	animate__hinge: 'hinge', | ||||
| 	animate__jackInTheBox: 'jackInTheBox', | ||||
| 	animate__rollIn: 'rollIn', | ||||
| 	animate__rollOut: 'rollOut', | ||||
| 	animate__zoomIn: 'zoomIn', | ||||
| 	animate__zoomInDown: 'zoomInDown', | ||||
| 	animate__zoomInLeft: 'zoomInLeft', | ||||
| 	animate__zoomInRight: 'zoomInRight', | ||||
| 	animate__zoomInUp: 'zoomInUp', | ||||
| 	animate__zoomOut: 'zoomOut', | ||||
| 	animate__zoomOutDown: 'zoomOutDown', | ||||
| 	animate__zoomOutLeft: 'zoomOutLeft', | ||||
| 	animate__zoomOutRight: 'zoomOutRight', | ||||
| 	animate__zoomOutUp: 'zoomOutUp', | ||||
| 	animate__slideInDown: 'slideInDown', | ||||
| 	animate__slideInLeft: 'slideInLeft', | ||||
| 	animate__slideInRight: 'slideInRight', | ||||
| 	animate__slideInUp: 'slideInUp', | ||||
| 	animate__slideOutDown: 'slideOutDown', | ||||
| 	animate__slideOutLeft: 'slideOutLeft', | ||||
| 	animate__slideOutRight: 'slideOutRight', | ||||
| 	animate__slideOutUp: 'slideOutUp', | ||||
| }; | ||||
|  | ||||
| const animateRepeat: Record<string, string> = { | ||||
| 	'': '无', | ||||
| 	'1': '1次', | ||||
| 	'2': '2次', | ||||
| 	'3': '3次', | ||||
| 	'4': '4次', | ||||
| 	infinite: '无限', | ||||
| }; | ||||
|  | ||||
| const animateSpeed: Record<string, string> = { | ||||
| 	'': '普通', | ||||
| 	animate__slow: '特慢', | ||||
| 	animate__slower: '慢速', | ||||
| 	animate__fast: '快速', | ||||
| 	animate__faster: '特快', | ||||
| }; | ||||
|  | ||||
| let lastAnimate = ''; | ||||
| /** | ||||
|  * | ||||
|  * 这个控制组件配置项写死,只可能出现或者不出现 | ||||
|  * @return {*} | ||||
|  */ | ||||
| function AnimateControl(props: AnimateControlProps) { | ||||
| 	const [count, setCount] = useState<number | null>(null); | ||||
| 	const [sign, setSign] = useState(false); | ||||
| 	const v1 = useMemo(() => { | ||||
| 		if (sign) { | ||||
| 			return lastAnimate; | ||||
| 		} else { | ||||
| 			const val = props.current.animate.animate | ||||
| 				? animateCategory[props.current.animate.animate] | ||||
| 				: ''; | ||||
| 			lastAnimate = val; | ||||
| 			return val; | ||||
| 		} | ||||
| 	}, [props.current.animate.animate, sign]); | ||||
|  | ||||
| 	const v2 = useMemo(() => { | ||||
| 		if (typeof props.current.animate.animationIterationCount === 'number') { | ||||
| 			setCount(props.current.animate.animationIterationCount); | ||||
| 			return ''; | ||||
| 		} else { | ||||
| 			setCount(null); | ||||
| 			return props.current.animate.animationIterationCount | ||||
| 				? animateRepeat[props.current.animate.animationIterationCount] | ||||
| 				: ''; | ||||
| 		} | ||||
| 	}, [props.current.animate.animationIterationCount]); | ||||
|  | ||||
| 	const v3 = useMemo(() => { | ||||
| 		return animateSpeed[props.current.animate.speed ?? '']; | ||||
| 	}, [props.current.animate.speed]); | ||||
|  | ||||
| 	const changeAnimation = ( | ||||
| 		e: any, | ||||
| 		props: AnimateControlProps, | ||||
| 		type: 'animate' | 'animationIterationCount' | 'speed' | ||||
| 	) => { | ||||
| 		if (type === 'animationIterationCount') { | ||||
| 			setCount(null); | ||||
| 		} | ||||
|  | ||||
| 		const clonedata = deepCopy(props.config.getStore().getData()); | ||||
| 		const newblock = clonedata.block.map((v: IBlockType) => { | ||||
| 			if (v.id === props.current.id) { | ||||
| 				if (type === 'animationIterationCount') { | ||||
| 					v.animate[type] = Number(e); | ||||
| 				} | ||||
| 				v.animate[type] = e; | ||||
| 			} | ||||
| 			return v; | ||||
| 		}); | ||||
| 		const [item] = clonedata.block.filter((item: IBlockType) => item.id === props.current.id); | ||||
| 		if (item?.animate?.animate) { | ||||
| 			const cloneNewBlock = deepCopy(newblock); | ||||
| 			const temporaryBlock = cloneNewBlock.map((item: IBlockType) => { | ||||
| 				if (item.id === props.current.id) { | ||||
| 					delete item.animate.animate; | ||||
| 				} | ||||
| 				return item; | ||||
| 			}); | ||||
| 			setSign(true); | ||||
| 			// 若有动画属性则删除动画属性再将动画属性添加 | ||||
| 			props.config.getStore().setData({ ...clonedata, block: [...temporaryBlock] }); | ||||
| 		} | ||||
| 		setTimeout(() => { | ||||
| 			props.config.getStore().setData({ ...clonedata, block: [...newblock] }); | ||||
| 			setSign(false); | ||||
| 		}); | ||||
| 	}; | ||||
| 	return ( | ||||
| 		<> | ||||
| 			<Row style={{ padding: '20px' }}> | ||||
| 				<Col span={6} style={{ lineHeight: '30px' }}> | ||||
| 					动画种类 | ||||
| 				</Col> | ||||
| 				<Col span={18}> | ||||
| 					<Select | ||||
| 						value={v1} | ||||
| 						onChange={(e) => changeAnimation(e, props, 'animate')} | ||||
| 						style={{ width: '100%' }} | ||||
| 					> | ||||
| 						{Object.keys(animateCategory).map((v) => { | ||||
| 							return ( | ||||
| 								<Select.Option value={v} key={v}> | ||||
| 									{animateCategory[v]} | ||||
| 								</Select.Option> | ||||
| 							); | ||||
| 						})} | ||||
| 					</Select> | ||||
| 				</Col> | ||||
| 			</Row> | ||||
| 			<Row style={{ padding: '20px' }}> | ||||
| 				<Col span={6} style={{ lineHeight: '30px' }}> | ||||
| 					频率 | ||||
| 				</Col> | ||||
| 				<Col span={18} style={{ display: 'flex', justifyContent: 'space-between' }}> | ||||
| 					<InputNumber | ||||
| 						min={1} | ||||
| 						value={count as number} | ||||
| 						onChange={(value) => { | ||||
| 							setCount(value); | ||||
| 							const clonedata = deepCopy(props.config.getStore().getData()); | ||||
| 							const newblock = clonedata.block.map((v: IBlockType) => { | ||||
| 								if (v.id === props.current.id) { | ||||
| 									v.animate.animationIterationCount = value; | ||||
| 								} | ||||
| 								return v; | ||||
| 							}); | ||||
|  | ||||
| 							const [item] = clonedata.block.filter( | ||||
| 								(item: IBlockType) => item.id === props.current.id | ||||
| 							); | ||||
|  | ||||
| 							if (item?.animate?.animate) { | ||||
| 								const cloneNewBlock = deepCopy(newblock); | ||||
| 								const temporaryBlock = cloneNewBlock.map((item: IBlockType) => { | ||||
| 									if (item.id === props.current.id) { | ||||
| 										delete item.animate.animate; | ||||
| 									} | ||||
| 									return item; | ||||
| 								}); | ||||
| 								setSign(true); | ||||
| 								props.config.getStore().setData({ ...clonedata, block: [...temporaryBlock] }); | ||||
| 							} | ||||
| 							setTimeout(() => { | ||||
| 								props.config.getStore().setData({ ...clonedata, block: [...newblock] }); | ||||
| 								setSign(false); | ||||
| 							}); | ||||
| 						}} | ||||
| 					></InputNumber> | ||||
| 					<Select | ||||
| 						value={v2} | ||||
| 						onChange={(e) => changeAnimation(e, props, 'animationIterationCount')} | ||||
| 						style={{ width: '60%' }} | ||||
| 					> | ||||
| 						{Object.keys(animateRepeat).map((v) => { | ||||
| 							return ( | ||||
| 								<Select.Option value={v} key={v}> | ||||
| 									{animateRepeat[v]} | ||||
| 								</Select.Option> | ||||
| 							); | ||||
| 						})} | ||||
| 					</Select> | ||||
| 				</Col> | ||||
| 			</Row> | ||||
| 			<Row style={{ padding: '20px' }}> | ||||
| 				<Col span={6} style={{ lineHeight: '30px' }}> | ||||
| 					动画速度 | ||||
| 				</Col> | ||||
| 				<Col span={18}> | ||||
| 					<Select | ||||
| 						value={v3} | ||||
| 						onChange={(e: any) => changeAnimation(e, props, 'speed')} | ||||
| 						style={{ width: '100%' }} | ||||
| 					> | ||||
| 						{Object.keys(animateSpeed).map((v) => { | ||||
| 							return ( | ||||
| 								<Select.Option value={v} key={v}> | ||||
| 									{animateSpeed[v]} | ||||
| 								</Select.Option> | ||||
| 							); | ||||
| 						})} | ||||
| 					</Select> | ||||
| 				</Col> | ||||
| 			</Row> | ||||
| 		</> | ||||
| 	); | ||||
| } | ||||
|  | ||||
| export default AnimateControl; | ||||
| @@ -0,0 +1,51 @@ | ||||
| /* | ||||
|  * @Author: yehuozhili | ||||
|  * @Date: 2021-07-07 14:32:55 | ||||
|  * @LastEditors: yehuozhili | ||||
|  * @LastEditTime: 2021-07-07 14:33:06 | ||||
|  * @FilePath: \visual-editor\src\plugin\formComponents\input.tsx | ||||
|  */ | ||||
| import { deepCopy } from 'dooringx-lib'; | ||||
| import { store } from 'dooringx-lib'; | ||||
| import { Col, Input, Row } from 'antd'; | ||||
| import { memo, useMemo } from 'react'; | ||||
| import React from 'react'; | ||||
| import { FormMap } from '../formTypes'; | ||||
| import { CreateOptionsRes } from 'dooringx-lib/dist/core/components/formTypes'; | ||||
| import { IBlockType } from 'dooringx-lib/dist/core/store/storetype'; | ||||
|  | ||||
| interface MInputProps { | ||||
| 	data: CreateOptionsRes<FormMap, 'input'>; | ||||
| 	current: IBlockType; | ||||
| } | ||||
|  | ||||
| function MInput(props: MInputProps) { | ||||
| 	const option = useMemo(() => { | ||||
| 		return props.data?.option || {}; | ||||
| 	}, [props.data]); | ||||
| 	return ( | ||||
| 		<Row style={{ padding: '10px 20px' }}> | ||||
| 			<Col span={6} style={{ lineHeight: '30px' }}> | ||||
| 				{(option as any)?.label || '文字'}: | ||||
| 			</Col> | ||||
| 			<Col span={18}> | ||||
| 				<Input | ||||
| 					value={props.current.props[(option as any).receive] || ''} | ||||
| 					onChange={(e) => { | ||||
| 						const receive = (option as any).receive; | ||||
| 						const clonedata = deepCopy(store.getData()); | ||||
| 						const newblock = clonedata.block.map((v: IBlockType) => { | ||||
| 							if (v.id === props.current.id) { | ||||
| 								v.props[receive] = e.target.value; | ||||
| 							} | ||||
| 							return v; | ||||
| 						}); | ||||
| 						store.setData({ ...clonedata, block: [...newblock] }); | ||||
| 					}} | ||||
| 				></Input> | ||||
| 			</Col> | ||||
| 		</Row> | ||||
| 	); | ||||
| } | ||||
|  | ||||
| export default memo(MInput); | ||||
							
								
								
									
										21
									
								
								packages/dooringx-example/src/plugin/formTypes.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								packages/dooringx-example/src/plugin/formTypes.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| /* | ||||
|  * @Author: yehuozhili | ||||
|  * @Date: 2021-07-07 14:31:20 | ||||
|  * @LastEditors: yehuozhili | ||||
|  * @LastEditTime: 2021-07-10 17:21:04 | ||||
|  * @FilePath: \dooringx\packages\dooringx-example\src\plugin\formTypes.ts | ||||
|  */ | ||||
| export interface FormBaseType { | ||||
| 	receive?: string; | ||||
| } | ||||
| export interface FormInputType extends FormBaseType { | ||||
| 	label: string; | ||||
| 	text: string; | ||||
| } | ||||
| export interface FormActionButtonType {} | ||||
| export interface FormAnimateControlType {} | ||||
| export interface FormMap { | ||||
| 	input: FormInputType; | ||||
| 	actionButton: FormActionButtonType; | ||||
| 	animateControl: FormAnimateControlType; | ||||
| } | ||||
							
								
								
									
										10
									
								
								packages/dooringx-example/src/plugin/functionMap/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								packages/dooringx-example/src/plugin/functionMap/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| /* | ||||
|  * @Author: yehuozhili | ||||
|  * @Date: 2021-07-07 14:22:51 | ||||
|  * @LastEditors: yehuozhili | ||||
|  * @LastEditTime: 2021-07-09 13:52:51 | ||||
|  * @FilePath: \dooringx\packages\dooringx-example\src\plugin\functionMap\index.ts | ||||
|  */ | ||||
| import { FunctionCenterType } from 'dooringx-lib/dist/core/functionCenter'; | ||||
|  | ||||
| export const functionMap: FunctionCenterType = {}; | ||||
							
								
								
									
										83
									
								
								packages/dooringx-example/src/plugin/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								packages/dooringx-example/src/plugin/index.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| /* | ||||
|  * @Author: yehuozhili | ||||
|  * @Date: 2021-02-27 21:33:36 | ||||
|  * @LastEditors: yehuozhili | ||||
|  * @LastEditTime: 2021-07-10 19:32:16 | ||||
|  * @FilePath: \dooringx\packages\dooringx-example\src\plugin\index.tsx | ||||
|  */ | ||||
|  | ||||
| import { InitConfig } from 'dooringx-lib'; | ||||
| import { LeftRegistComponentMapItem } from 'dooringx-lib/dist/core/crossDrag'; | ||||
| import { ContainerOutlined, HighlightOutlined } from '@ant-design/icons'; | ||||
| import commandModules from './commanderModules'; | ||||
| import { functionMap } from './functionMap'; | ||||
| import { Formmodules } from './formComponentModules'; | ||||
|  | ||||
| const LeftRegistMap: LeftRegistComponentMapItem[] = [ | ||||
| 	// build 时如果用代码分割会生成多个文件,这样就不能生成多类型文件。 | ||||
| 	// 建议基础包全部不分割。后面插件包可以用webpack的特性,所以插件包用新脚手架制作 | ||||
| 	// 基础包不独立出去的原因是部分左侧分类起始值最好规定住 | ||||
| 	// { | ||||
| 	//   type: 'xxa', | ||||
| 	//   component: 'asyncCo', | ||||
| 	//   img: '', | ||||
| 	//   urlFn: () => import('./registComponents/asyncCo'), | ||||
| 	//  displayName:'xxx' | ||||
| 	// }, | ||||
| 	{ | ||||
| 		type: 'basic', | ||||
| 		component: 'button', | ||||
| 		img: 'icon-anniu', | ||||
| 		displayName: '按钮', | ||||
| 		urlFn: () => import('./registComponents/button'), | ||||
| 	}, | ||||
| ]; | ||||
|  | ||||
| export const defaultConfig: Partial<InitConfig> = { | ||||
| 	leftAllRegistMap: LeftRegistMap, | ||||
| 	leftRenderListCategory: [ | ||||
| 		{ | ||||
| 			type: 'basic', | ||||
| 			icon: <HighlightOutlined />, | ||||
| 			displayName: '基础组件', | ||||
| 		}, | ||||
| 		{ | ||||
| 			type: 'xxc', | ||||
| 			icon: <ContainerOutlined />, | ||||
| 			custom: true, | ||||
| 			customRender: <div>我是自定义渲染</div>, | ||||
| 		}, | ||||
| 	], | ||||
| 	initComponentCache: {}, | ||||
| 	rightRenderListCategory: [ | ||||
| 		{ | ||||
| 			type: 'style', | ||||
| 			icon: ( | ||||
| 				<div className="right-tab-item" style={{ width: 50, textAlign: 'center' }}> | ||||
| 					外观 | ||||
| 				</div> | ||||
| 			), | ||||
| 		}, | ||||
| 		{ | ||||
| 			type: 'animate', | ||||
| 			icon: ( | ||||
| 				<div className="right-tab-item" style={{ width: 50, textAlign: 'center' }}> | ||||
| 					动画 | ||||
| 				</div> | ||||
| 			), | ||||
| 		}, | ||||
| 		{ | ||||
| 			type: 'actions', | ||||
| 			icon: ( | ||||
| 				<div className="right-tab-item" style={{ width: 50, textAlign: 'center' }}> | ||||
| 					事件 | ||||
| 				</div> | ||||
| 			), | ||||
| 		}, | ||||
| 	], | ||||
| 	initFunctionMap: functionMap, | ||||
| 	initCommandModule: commandModules, | ||||
| 	initFormComponents: Formmodules, | ||||
| }; | ||||
|  | ||||
| export default defaultConfig; | ||||
							
								
								
									
										138
									
								
								packages/dooringx-example/src/plugin/registComponents/button.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								packages/dooringx-example/src/plugin/registComponents/button.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,138 @@ | ||||
| /* | ||||
|  * @Author: yehuozhili | ||||
|  * @Date: 2021-07-07 14:35:38 | ||||
|  * @LastEditors: yehuozhili | ||||
|  * @LastEditTime: 2021-07-10 19:04:05 | ||||
|  * @FilePath: \dooringx\packages\dooringx-example\src\plugin\registComponents\button.tsx | ||||
|  */ | ||||
|  | ||||
| import { Button } from 'antd'; | ||||
| import React, { useEffect, useMemo, useState } from 'react'; | ||||
| import { | ||||
| 	changeUserValue, | ||||
| 	ComponentItemFactory, | ||||
| 	createPannelOptions, | ||||
| 	useDynamicAddEventCenter, | ||||
| } from 'dooringx-lib'; | ||||
| import { FormMap } from '../formTypes'; | ||||
| import { ComponentRenderConfigProps } from 'dooringx-lib/dist/core/components/componentItem'; | ||||
|  | ||||
| function ButtonTemp(pr: ComponentRenderConfigProps) { | ||||
| 	const props = pr.data.props; | ||||
| 	const eventCenter = useMemo(() => { | ||||
| 		return pr.config.getEventCenter(); | ||||
| 	}, [pr.config]); | ||||
|  | ||||
| 	useDynamicAddEventCenter(pr, `${pr.data.id}-init`, '初始渲染时机'); //注册名必须带id 约定! | ||||
| 	useDynamicAddEventCenter(pr, `${pr.data.id}-click`, '点击执行时机'); | ||||
|  | ||||
| 	useEffect(() => { | ||||
| 		// 模拟抛出事件 | ||||
| 		if (pr.context === 'preview') { | ||||
| 			eventCenter.runEventQueue(`${pr.data.id}-init`, pr.config); | ||||
| 		} | ||||
| 	}, [eventCenter, pr.config, pr.context, pr.data.id]); | ||||
|  | ||||
| 	const [text, setText] = useState(''); | ||||
| 	useEffect(() => { | ||||
| 		//模拟改变文本 | ||||
| 		const functionCenter = eventCenter.getFunctionCenter(); | ||||
| 		const unregist = functionCenter.register( | ||||
| 			`${pr.data.id}+改变文本函数`, | ||||
| 			async (ctx, next, config, args: any, _eventList, iname) => { | ||||
| 				const userSelect = iname.data; | ||||
| 				const ctxVal = changeUserValue( | ||||
| 					userSelect['改变文本数据源'], | ||||
| 					args, | ||||
| 					'_changeval', | ||||
| 					config, | ||||
| 					ctx | ||||
| 				); | ||||
| 				const text = ctxVal[0]; | ||||
| 				setText(text); | ||||
| 				next(); | ||||
| 			}, | ||||
| 			[ | ||||
| 				{ | ||||
| 					name: '改变文本数据源', | ||||
| 					data: ['ctx', 'input', 'dataSource'], | ||||
| 					options: { | ||||
| 						receive: '_changeval', | ||||
| 						multi: false, | ||||
| 					}, | ||||
| 				}, | ||||
| 			] | ||||
| 		); | ||||
| 		return () => { | ||||
| 			unregist(); | ||||
| 		}; | ||||
| 	}, []); | ||||
|  | ||||
| 	return ( | ||||
| 		<Button | ||||
| 			style={{ | ||||
| 				width: pr.data.width ? pr.data.width : props.sizeData[0], | ||||
| 				height: pr.data.height ? pr.data.height : props.sizeData[1], | ||||
| 				borderRadius: props.borderRadius + 'px', | ||||
| 				border: `${props.borderData.borderWidth}px ${props.borderData.borderStyle} ${props.borderData.borderColor}`, | ||||
| 				backgroundColor: props.backgroundColor, | ||||
| 				color: props.fontData.color, | ||||
| 				fontSize: props.fontData.fontSize, | ||||
| 				fontWeight: props.fontData.fontWeight, | ||||
| 				fontStyle: props.fontData.fontStyle, | ||||
| 				textDecoration: props.fontData.textDecoration, | ||||
| 				lineHeight: props.lineHeight, | ||||
| 			}} | ||||
| 			onClick={() => { | ||||
| 				eventCenter.runEventQueue(`${pr.data.id}-click`, pr.config); | ||||
| 			}} | ||||
| 			// type={props.type} | ||||
| 			// size={props.size} | ||||
| 		> | ||||
| 			{text ? text : props.text} | ||||
| 		</Button> | ||||
| 	); | ||||
| } | ||||
|  | ||||
| const MButton = new ComponentItemFactory( | ||||
| 	'button', | ||||
| 	'按钮', | ||||
| 	{ | ||||
| 		style: [ | ||||
| 			createPannelOptions<FormMap, 'input'>('input', { | ||||
| 				receive: 'text', //用于发送回的props,必传 ,跨组件传递需要指定额外字段 | ||||
| 				label: '文字', | ||||
| 				text: 'yehuozhili', | ||||
| 			}), | ||||
| 		], | ||||
| 		animate: [createPannelOptions<FormMap, 'animateControl'>('animateControl', {})], | ||||
| 		actions: [createPannelOptions<FormMap, 'actionButton'>('actionButton', {})], | ||||
| 	}, | ||||
| 	{ | ||||
| 		props: { | ||||
| 			text: 'yehuozhili', | ||||
| 			sizeData: [100, 30], | ||||
| 			backgroundColor: 'rgba(0,132,255,1)', | ||||
| 			lineHeight: 1, | ||||
| 			borderRadius: 0, | ||||
| 			borderData: { | ||||
| 				borderWidth: 0, | ||||
| 				borderColor: 'rgba(0,0,0,1)', | ||||
| 				borderStyle: 'solid', | ||||
| 			}, | ||||
| 			fontData: { | ||||
| 				fontSize: 14, | ||||
| 				textDecoration: 'none', | ||||
| 				fontStyle: 'normal', | ||||
| 				color: 'rgba(255,255,255,1)', | ||||
| 				fontWeight: 'normal', | ||||
| 			}, | ||||
| 		}, | ||||
| 	}, | ||||
| 	(data, context, store, config) => { | ||||
| 		return <ButtonTemp data={data} store={store} context={context} config={config}></ButtonTemp>; | ||||
| 	}, | ||||
| 	true | ||||
| ); | ||||
|  | ||||
| export default MButton; | ||||
		Reference in New Issue
	
	Block a user
	 hufeixiong
					hufeixiong