add example
This commit is contained in:
@@ -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);
|
Reference in New Issue
Block a user