This commit is contained in:
yehuozhili 2020-09-17 21:10:32 +08:00
parent 222f3b2108
commit 96e5d065ce
40 changed files with 15364 additions and 14767 deletions

View File

@ -1,9 +1,9 @@
import { CarouselConfigType } from '@/components/DynamicEngine/schema';
import React, { memo, PropsWithChildren } from 'react';
import { Carousel } from 'zarm';
import styles from './index.less';
import { ICarouselConfig } from './schema';
interface CarouselTypes extends CarouselConfigType {
interface CarouselTypes extends ICarouselConfig {
isTpl: boolean;
}

View File

@ -1,4 +1,31 @@
const Carousel = {
import {
IDataListConfigType,
IRadioConfigType,
ISwitchConfigType,
TDataListDefaultType,
TRadioDefaultType,
TSwitchDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type CarouselDirectionKeyType = 'down' | 'left';
export type TCarouselEditData = Array<
IRadioConfigType<CarouselDirectionKeyType> | ISwitchConfigType | IDataListConfigType
>;
export interface ICarouselConfig {
direction: TRadioDefaultType<CarouselDirectionKeyType>;
swipeable: TSwitchDefaultType;
autoPlay: TSwitchDefaultType;
imgList: TDataListDefaultType;
tplImg: string;
}
export interface ICarouselSchema {
editData: TCarouselEditData;
config: ICarouselConfig;
}
const Carousel: ICarouselSchema = {
editData: [
{
key: 'direction',

View File

@ -1,6 +1,6 @@
import { FooterConfigType } from '@/components/DynamicEngine/schema';
import React, { memo } from 'react';
const Footer = memo((props: FooterConfigType) => {
import { IFooterConfig } from './schema';
const Footer = memo((props: IFooterConfig) => {
const { bgColor, text, color, align, fontSize, height } = props;
return (
<footer

View File

@ -1,4 +1,34 @@
const Footer = {
import {
IColorConfigType,
INumberConfigType,
ISelectConfigType,
ITextConfigType,
TColorDefaultType,
TNumberDefaultType,
TSelectDefaultType,
TTextDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type TfooterSelectKeyType = 'left' | 'center' | 'right';
export type TFooterEditData = Array<
IColorConfigType | INumberConfigType | ITextConfigType | ISelectConfigType<TfooterSelectKeyType>
>;
export interface IFooterConfig {
bgColor: TColorDefaultType;
text: TTextDefaultType;
color: TColorDefaultType;
align: TSelectDefaultType<TfooterSelectKeyType>;
fontSize: TNumberDefaultType;
height: TNumberDefaultType;
}
export interface IFooterSchema {
editData: TFooterEditData;
config: IFooterConfig;
}
const Footer: IFooterSchema = {
editData: [
{
key: 'bgColor',

View File

@ -1,9 +1,23 @@
import { Input, Cell, DateSelect, Radio, Select } from 'zarm';
import styles from './baseForm.less';
import React from 'react';
import {
baseFormDateTpl,
baseFormMyRadioTpl,
baseFormMySelectTpl,
baseFormNumberTpl,
baseFormTextAreaTpl,
baseFormTextTpl,
baseFormUnionType,
} from '@/components/PanelComponents/FormEditor/types';
// 维护表单控件, 提高form渲染性能
const BaseForm = {
Text: props => {
type TBaseForm = {
[key in baseFormUnionType]: any;
};
const BaseForm: TBaseForm = {
Text: (props: baseFormTextTpl & { onChange: (v: string | undefined) => void }) => {
const { label, placeholder, onChange } = props;
return (
<Cell title={label}>
@ -11,7 +25,7 @@ const BaseForm = {
</Cell>
);
},
Textarea: props => {
Textarea: (props: baseFormTextAreaTpl & { onChange: (v: string | undefined) => void }) => {
const { label, placeholder, onChange } = props;
return (
<Cell title={label}>
@ -26,7 +40,7 @@ const BaseForm = {
</Cell>
);
},
Number: props => {
Number: (props: baseFormNumberTpl & { onChange: (v: string | undefined | number) => void }) => {
const { label, placeholder, onChange } = props;
return (
<Cell title={label}>
@ -34,7 +48,7 @@ const BaseForm = {
</Cell>
);
},
MyRadio: props => {
MyRadio: (props: baseFormMyRadioTpl & { onChange: (v: string | undefined | number) => void }) => {
const { label, options, onChange } = props;
return (
<div className={styles.radioWrap}>
@ -53,7 +67,7 @@ const BaseForm = {
</div>
);
},
Date: props => {
Date: (props: baseFormDateTpl & { onChange: (v: Date) => void }) => {
const { label, placeholder, onChange } = props;
return (
<Cell title={label}>
@ -67,7 +81,9 @@ const BaseForm = {
</Cell>
);
},
MySelect: props => {
MySelect: (
props: baseFormMySelectTpl & { onChange: ((v: Record<string, any>) => void) | undefined },
) => {
const { label, options, onChange } = props;
return (
<Cell title={label}>

View File

@ -1,20 +1,12 @@
import React, { memo, useState, useEffect, useMemo, useCallback } from 'react';
import React, { memo, useCallback } from 'react';
import { Button } from 'zarm';
import BaseForm from './BaseForm';
import req from 'utils/req';
import styles from './index.less';
import { IFormConfig } from './schema';
function unParams(params = '?a=1&b=2&c=3') {
let obj = {};
params &&
params.replace(/((\w*)=([\.a-z0-9A-Z]*)?)?/g, (m, a, b, c) => {
if (b || c) obj[b] = c;
});
return obj;
}
const FormComponent = props => {
const FormComponent = (props: IFormConfig) => {
const { title, bgColor, fontSize, titColor, btnColor, btnTextColor, api, formControls } = props;
const formData = {};
const formData: Record<string, any> = {};
const handleChange = useCallback(
(item, v) => {
if (item.options) {

View File

@ -1,4 +1,34 @@
const Form = {
import {
IColorConfigType,
IFormItemsConfigType,
INumberConfigType,
ITextConfigType,
TColorDefaultType,
TFormItemsDefaultType,
TNumberDefaultType,
TTextDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type TFormEditData = Array<
ITextConfigType | INumberConfigType | IColorConfigType | ITextConfigType | IFormItemsConfigType
>;
export interface IFormConfig {
title: TTextDefaultType;
fontSize: TNumberDefaultType;
titColor: TColorDefaultType;
bgColor: TColorDefaultType;
btnColor: TColorDefaultType;
btnTextColor: TColorDefaultType;
api: TTextDefaultType;
formControls: TFormItemsDefaultType;
}
export interface IFormSchema {
editData: TFormEditData;
config: IFormConfig;
}
const Form: IFormSchema = {
editData: [
{
key: 'title',

View File

@ -1,9 +1,9 @@
import { memo } from 'react';
import styles from './index.less';
import React from 'react';
import { HeaderConfigType } from '@/components/DynamicEngine/schema';
import { IHeaderConfig } from './schema';
const Header = memo((props: HeaderConfigType) => {
const Header = memo((props: IHeaderConfig) => {
const { bgColor, logo, logoText, fontSize, color } = props;
return (
<header className={styles.header} style={{ backgroundColor: bgColor }}>

View File

@ -1,4 +1,32 @@
const Header = {
import {
IColorConfigType,
INumberConfigType,
ITextConfigType,
IUploadConfigType,
TColorDefaultType,
TNumberDefaultType,
TTextDefaultType,
TUploadDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type THeaderEditData = Array<
IColorConfigType | INumberConfigType | IUploadConfigType | ITextConfigType
>;
export interface IHeaderConfig {
bgColor: TColorDefaultType;
logo: TUploadDefaultType;
logoText: TTextDefaultType;
fontSize: TNumberDefaultType;
color: TColorDefaultType;
height: TNumberDefaultType;
}
export interface IHeaderSchema {
editData: THeaderEditData;
config: IHeaderConfig;
}
const Header: IHeaderSchema = {
editData: [
{
key: 'bgColor',

View File

@ -2,13 +2,11 @@ import React, { memo } from 'react';
import * as Icon from '@ant-design/icons';
import IconImg from 'assets/icon.png';
import { AntdIconProps } from '@ant-design/icons/lib/components/AntdIcon';
import { IconConfigType } from '../../../DynamicEngine/schema';
import { AntdIconType } from './icon';
import { IIconConfig } from './schema';
interface IconType extends Omit<IconConfigType, 'spin' | 'color'> {
interface IconType extends IIconConfig {
isTpl?: boolean;
spin?: IconConfigType['spin'];
color?: IconConfigType['color'];
}
const XIcon = memo((props: IconType) => {
const { color, size, type, spin, isTpl } = props;

View File

@ -1,3 +1,29 @@
import {
ICardPickerConfigType,
IColorConfigType,
INumberConfigType,
ISwitchConfigType,
TCardPickerDefaultType,
TColorDefaultType,
TNumberDefaultType,
TSwitchDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type TIconEditData = Array<
IColorConfigType | INumberConfigType | ISwitchConfigType | ICardPickerConfigType<IconTypes>
>;
export interface IIconConfig {
color: TColorDefaultType;
size: TNumberDefaultType;
spin: TSwitchDefaultType;
type: TCardPickerDefaultType<IconTypes>;
}
export interface IIconSchema {
editData: TIconEditData;
config: IIconConfig;
}
export type IconTypes =
| 'AccountBookTwoTone'
| 'AlertTwoTone'
@ -41,7 +67,7 @@ export type IconTypes =
| 'SettingTwoTone'
| 'RocketTwoTone';
const Icon = {
const Icon: IIconSchema = {
editData: [
{
key: 'color',

View File

@ -1,6 +1,6 @@
import { ImageConfigType } from '@/components/DynamicEngine/schema';
import React, { memo } from 'react';
const Image = memo((props: ImageConfigType) => {
import { IImageConfig } from './schema';
const Image = memo((props: IImageConfig) => {
const { imgUrl, round = 0 } = props;
return (
<div style={{ borderRadius: round, width: '100%', textAlign: 'center', overflow: 'hidden' }}>

View File

@ -1,4 +1,22 @@
const Image = {
import {
INumberConfigType,
IUploadConfigType,
TNumberDefaultType,
TUploadDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type TImageEditData = Array<IUploadConfigType | INumberConfigType>;
export interface IImageConfig {
imgUrl: TUploadDefaultType;
round: TNumberDefaultType;
}
export interface IImageSchema {
editData: TImageEditData;
config: IImageConfig;
}
const Image: IImageSchema = {
editData: [
{
key: 'imgUrl',

View File

@ -1,7 +1,7 @@
import { ListConfigType } from '@/components/DynamicEngine/schema';
import React, { memo } from 'react';
import styles from './index.less';
const List = memo((props: ListConfigType) => {
import { IListConfig } from './schema';
const List = memo((props: IListConfig) => {
const { round, sourceData, imgSize, fontSize, color } = props;
return (
<div className={styles.list}>
@ -18,7 +18,7 @@ const List = memo((props: ListConfigType) => {
}
alt={item.desc}
style={{
width: imgSize,
width: parseFloat(imgSize),
height: imgSize,
objectFit: 'cover',
borderRadius: round,

View File

@ -1,4 +1,31 @@
const List = {
import {
IColorConfigType,
IDataListConfigType,
INumberConfigType,
ISelectConfigType,
TColorDefaultType,
TDataListDefaultType,
TNumberDefaultType,
TSelectDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type TListSelectKeyType = '60' | '80' | '100' | '120' | '150';
export type TListEditData = Array<
IColorConfigType | IDataListConfigType | INumberConfigType | ISelectConfigType<TListSelectKeyType>
>;
export interface IListConfig {
sourceData: TDataListDefaultType;
round: TNumberDefaultType;
imgSize: TSelectDefaultType<TListSelectKeyType>;
fontSize: TNumberDefaultType;
color: TColorDefaultType;
}
export interface IListSchema {
editData: TListEditData;
config: IListConfig;
}
const List: IListSchema = {
editData: [
{
key: 'sourceData',
@ -16,23 +43,23 @@ const List = {
type: 'Select',
range: [
{
key: 60,
key: '60',
text: '60 x 60',
},
{
key: 80,
key: '80',
text: '80 x 80',
},
{
key: 100,
key: '100',
text: '100 x 100',
},
{
key: 120,
key: '120',
text: '120 x 120',
},
{
key: 150,
key: '150',
text: '150 x 150',
},
],
@ -80,7 +107,7 @@ const List = {
},
],
round: 0,
imgSize: 80,
imgSize: '80',
fontSize: 16,
color: 'rgba(153,153,153,1)',
},

View File

@ -1,7 +1,7 @@
import { LongTextConfigType } from '@/components/DynamicEngine/schema';
import React, { memo } from 'react';
import styles from './index.less';
const LongText = memo((props: LongTextConfigType) => {
import { ILongTextConfig } from './schema';
const LongText = memo((props: ILongTextConfig) => {
const { text, fontSize, color, indent, lineHeight, textAlign } = props;
return (
<div

View File

@ -1,4 +1,36 @@
const LongText = {
import {
IColorConfigType,
INumberConfigType,
ISelectConfigType,
ITextAreaConfigType,
TColorDefaultType,
TNumberDefaultType,
TSelectDefaultType,
TTextAreaDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type TLongTextSelectKeyType = 'left' | 'center' | 'right';
export type TLongTextEditData = Array<
| ITextAreaConfigType
| IColorConfigType
| INumberConfigType
| ISelectConfigType<TLongTextSelectKeyType>
>;
export interface ILongTextConfig {
text: TTextAreaDefaultType;
color: TColorDefaultType;
fontSize: TNumberDefaultType;
indent: TNumberDefaultType;
lineHeight: TNumberDefaultType;
textAlign: TSelectDefaultType<TLongTextSelectKeyType>;
}
export interface ILongTextSchema {
editData: TLongTextEditData;
config: ILongTextConfig;
}
const LongText: ILongTextSchema = {
editData: [
{
key: 'text',

View File

@ -1,7 +1,7 @@
import { NoticeBar } from 'zarm';
import React, { memo } from 'react';
import { NoticeConfigType } from '@/components/DynamicEngine/schema';
const Notice = memo((props: NoticeConfigType) => {
import { INoticeConfig } from './schema';
const Notice = memo((props: INoticeConfig) => {
const { text, speed, theme, isClose = false } = props;
return (
<NoticeBar theme={theme === 'default' ? undefined : theme} closable={isClose} speed={speed}>

View File

@ -1,4 +1,31 @@
const Notice = {
import {
INumberConfigType,
ISelectConfigType,
ISwitchConfigType,
ITextConfigType,
TNumberDefaultType,
TSelectDefaultType,
TSwitchDefaultType,
TTextDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type TNoticeSelectKeyType = 'default' | 'warning' | 'primary' | 'success' | 'danger';
export type TNoticeEditData = Array<
ITextConfigType | INumberConfigType | ISelectConfigType<TNoticeSelectKeyType> | ISwitchConfigType
>;
export interface INoticeConfig {
text: TTextDefaultType;
speed: TNumberDefaultType;
theme: TSelectDefaultType<TNoticeSelectKeyType>;
isClose: TSwitchDefaultType;
}
export interface INoticeSchema {
editData: TNoticeEditData;
config: INoticeConfig;
}
const Notice: INoticeSchema = {
editData: [
{
key: 'text',
@ -45,7 +72,6 @@ const Notice = {
],
config: {
text: '通知栏: 趣谈前端上线啦',
link: '',
speed: 50,
theme: 'warning',
isClose: false,

View File

@ -1,7 +1,7 @@
import { QRCodeConfigType } from '@/components/DynamicEngine/schema';
import React, { memo } from 'react';
import { IQrcodeConfig } from './schema';
const Qrcode = memo((props: QRCodeConfigType) => {
const Qrcode = memo((props: IQrcodeConfig) => {
const { qrcode, text, color, fontSize = 14 } = props;
return (
<div style={{ width: '240px', margin: '16px auto' }}>

View File

@ -1,4 +1,30 @@
const Qrcode = {
import {
IColorConfigType,
INumberConfigType,
ITextConfigType,
IUploadConfigType,
TColorDefaultType,
TNumberDefaultType,
TTextDefaultType,
TUploadDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type TQrcodeEditData = Array<
IUploadConfigType | ITextConfigType | IColorConfigType | INumberConfigType
>;
export interface IQrcodeConfig {
qrcode: TUploadDefaultType;
text: TTextDefaultType;
color: TColorDefaultType;
fontSize: TNumberDefaultType;
}
export interface IQrcodeSchema {
editData: TQrcodeEditData;
config: IQrcodeConfig;
}
const Qrcode: IQrcodeSchema = {
editData: [
{
key: 'qrcode',

View File

@ -1,11 +1,11 @@
import { TabConfigType } from '@/components/DynamicEngine/schema';
import React, { useEffect, useRef } from 'react';
import { Tabs } from 'zarm';
import styles from './index.less';
import { ITabConfig } from './schema';
const { Panel } = Tabs;
const XTab = (props: TabConfigType) => {
const XTab = (props: ITabConfig) => {
const { tabs = ['分类一', '分类二'], activeColor, color, fontSize, sourceData } = props;
const tabWrapRef = useRef<HTMLDivElement>(null);

View File

@ -1,4 +1,32 @@
const Tab = {
import {
IColorConfigType,
IDataListConfigType,
IMutiTextConfigType,
INumberConfigType,
TColorDefaultType,
TDataListDefaultType,
TMutiTextDefaultType,
TNumberDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type TTabEditData = Array<
IMutiTextConfigType | IColorConfigType | INumberConfigType | IDataListConfigType
>;
export interface ITabConfig {
tabs: TMutiTextDefaultType;
color: TColorDefaultType;
activeColor: TColorDefaultType;
fontSize: TNumberDefaultType;
imgSize: TNumberDefaultType;
sourceData: TDataListDefaultType;
}
export interface ITabSchema {
editData: TTabEditData;
config: ITabConfig;
}
const Tab: ITabSchema = {
editData: [
{
key: 'tabs',

View File

@ -1,8 +1,8 @@
import { TextConfigType } from '@/components/DynamicEngine/schema';
import React, { memo } from 'react';
import styles from './index.less';
import { ITextConfig } from './schema';
const Text = memo((props: TextConfigType) => {
const Text = memo((props: ITextConfig) => {
const { align, text, fontSize, color, lineHeight } = props;
return (
<div className={styles.textWrap} style={{ color, textAlign: align, fontSize, lineHeight }}>

View File

@ -1,4 +1,31 @@
const Text = {
import {
IColorConfigType,
INumberConfigType,
ISelectConfigType,
ITextConfigType,
TColorDefaultType,
TNumberDefaultType,
TSelectDefaultType,
TTextDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type TTextSelectKeyType = 'left' | 'right' | 'center';
export type TTextEditData = Array<
ITextConfigType | IColorConfigType | INumberConfigType | ISelectConfigType<TTextSelectKeyType>
>;
export interface ITextConfig {
text: TTextDefaultType;
color: TColorDefaultType;
fontSize: TNumberDefaultType;
align: TSelectDefaultType<TTextSelectKeyType>;
lineHeight: TNumberDefaultType;
}
export interface ITextSchema {
editData: TTextEditData;
config: ITextConfig;
}
const Text: ITextSchema = {
editData: [
{
key: 'text',

View File

@ -1,9 +1,9 @@
import { VideoConfigType } from '@/components/DynamicEngine/schema';
import React, { memo } from 'react';
import { Player, BigPlayButton } from 'video-react';
import './index.css';
import { IVideoConfig } from './schema';
const VideoPlayer = memo((props: VideoConfigType) => {
const VideoPlayer = memo((props: IVideoConfig) => {
const { poster, url } = props;
return (
<div>

View File

@ -1,4 +1,22 @@
const Video = {
import {
ITextConfigType,
IUploadConfigType,
TTextDefaultType,
TUploadDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type TVideoEditData = Array<IUploadConfigType | ITextConfigType>;
export interface IVideoConfig {
poster: TUploadDefaultType;
url: TTextDefaultType;
}
export interface IVideoSchema {
editData: TVideoEditData;
config: IVideoConfig;
}
const Video: IVideoSchema = {
editData: [
{
key: 'poster',

View File

@ -1,25 +1,16 @@
import { Chart } from '@antv/f2';
import React, { memo, PropsWithChildren, useEffect, useRef } from 'react';
import React, { memo, useEffect, useRef } from 'react';
// import { uuid } from 'utils/tool';
import ChartImg from '@/assets/chart.png';
import styles from './index.less';
import { IChartConfig } from './schema';
type DataItem = {
name: string;
value: number;
};
interface XChartProps {
interface XChartProps extends IChartConfig {
isTpl: boolean;
title: string;
color: string;
size: number;
paddingTop: number;
data: Array<DataItem>;
}
const XChart = (props: PropsWithChildren<XChartProps>) => {
const XChart = (props: XChartProps) => {
const { isTpl, data, color, size, paddingTop, title } = props;
const chartRef = useRef(null);
useEffect(() => {
@ -44,7 +35,7 @@ const XChart = (props: PropsWithChildren<XChartProps>) => {
// Step 4: 渲染图表
chart.render();
}
}, []);
}, [data, isTpl]);
return (
<div className={styles.chartWrap}>
<div className={styles.chartTitle} style={{ color, fontSize: size, paddingTop }}>

View File

@ -1,4 +1,31 @@
const Chart = {
import {
IColorConfigType,
INumberConfigType,
ITableConfigType,
ITextConfigType,
TColorDefaultType,
TNumberDefaultType,
TTableDefaultType,
TTextDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type TChartEditData = Array<
ITextConfigType | INumberConfigType | IColorConfigType | ITableConfigType
>;
export interface IChartConfig {
title: TTextDefaultType;
size: TNumberDefaultType;
color: TColorDefaultType;
paddingTop: TNumberDefaultType;
data: TTableDefaultType;
}
export interface IChartSchema {
editData: TChartEditData;
config: IChartConfig;
}
const Chart: IChartSchema = {
editData: [
{
key: 'title',

View File

@ -1,9 +1,9 @@
import { XProgressConfigType } from '@/components/DynamicEngine/schema';
import React, { memo } from 'react';
import { Progress } from 'zarm';
import styles from './index.less';
import { IXProgressConfig } from './schema';
const XProgress = memo((props: XProgressConfigType) => {
const XProgress = memo((props: IXProgressConfig) => {
const { theme, size, shape, percent, strokeWidth } = props;
return (
<div className={styles.textWrap} style={{ textAlign: 'center' }}>

View File

@ -1,4 +1,32 @@
const XProgress = {
import {
INumberConfigType,
IRadioConfigType,
ISelectConfigType,
TNumberDefaultType,
TRadioDefaultType,
TSelectDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type TXProgressSelectKeyType = 'success' | 'warning' | 'danger';
export type TXProgressRadiotKeyType = 'circle' | 'line' | 'semi-circle';
export type TXProgressEditData = Array<
| ISelectConfigType<TXProgressSelectKeyType>
| IRadioConfigType<TXProgressRadiotKeyType>
| INumberConfigType
>;
export interface IXProgressConfig {
theme: TSelectDefaultType<TXProgressSelectKeyType>;
shape: TRadioDefaultType<TXProgressRadiotKeyType>;
size: TNumberDefaultType;
percent: TNumberDefaultType;
strokeWidth: TNumberDefaultType;
}
export interface IXProgressSchema {
editData: TXProgressEditData;
config: IXProgressConfig;
}
const XProgress: IXProgressSchema = {
editData: [
{
key: 'theme',

View File

@ -2,18 +2,17 @@ import { useState, useEffect, memo } from 'react';
import classnames from 'classnames';
import Icon from '../../BasicShop/BasicComponents/Icon';
import styles from './index.less';
import { IconTypes } from '../../DynamicEngine/schema';
import React from 'react';
import { IconTypes } from '@/components/BasicShop/BasicComponents/Icon/schema';
import { ICardPickerConfigType } from '../FormEditor/types';
interface CardPickerType {
type: IconTypes;
icons: Array<IconTypes>;
interface CardPickerType extends Omit<ICardPickerConfigType<IconTypes>, 'type' | 'key' | 'name'> {
onChange?: (v: string) => void;
type: IconTypes;
}
export default memo((props: CardPickerType) => {
const { type, icons, onChange } = props;
console.log(type);
const [selected, setSelected] = useState<IconTypes>(type);
const handlePicker = (v: IconTypes) => {
@ -37,7 +36,7 @@ export default memo((props: CardPickerType) => {
onClick={() => handlePicker(item)}
key={i}
>
<Icon type={item} size={20} />
<Icon type={item} size={20} color={'#4091f7'} spin={false} />
</span>
);
})}

View File

@ -1,13 +1,10 @@
import React, { memo, useEffect, FC } from 'react';
import { Form, Select, Input, Modal } from 'antd';
import Upload from '../Upload';
import { BasicDataSource } from '../../DynamicEngine/schema';
import { Store } from 'antd/lib/form/interface';
import { TDataListDefaultTypeItem } from '../FormEditor/types';
// import styles from './index.less';
const normFile = (e: any) => {
console.log('Upload event:', e);
console.log('ffffffffff'); //待修改?
if (Array.isArray(e)) {
return e;
}
@ -24,7 +21,7 @@ const formItemLayout = {
export type EditorModalProps = {
visible: boolean;
onCancel: ((e: React.MouseEvent<HTMLElement, MouseEvent>) => void) | undefined;
item?: BasicDataSource;
item?: TDataListDefaultTypeItem;
onSave: Function;
};

View File

@ -18,7 +18,7 @@ import { HTML5Backend } from 'react-dnd-html5-backend';
import EditorModal from './editorModal';
import { uuid } from '@/utils/tool';
import styles from './index.less';
import { BasicDataSource } from '../../DynamicEngine/schema';
import { TDataListDefaultType, TDataListDefaultTypeItem } from '../FormEditor/types';
type ListItemProps = DndItemProps & {
isDragging: boolean;
@ -66,7 +66,7 @@ function ListItem(props: ListItemProps) {
);
}
type DndItemProps = BasicDataSource & {
type DndItemProps = TDataListDefaultTypeItem & {
onDel: Function;
onEdit: Function;
key: number;
@ -127,8 +127,8 @@ const DndItem = DropTarget(
)(DragSource(type, dragSpec, dragCollect)(ListItem));
export type DataListMemo = {
onChange?: (v: BasicDataSource[]) => void;
value?: BasicDataSource[];
onChange?: (v: TDataListDefaultType) => void;
value?: TDataListDefaultType;
};
export type DataListType = DataListMemo & {
@ -139,7 +139,7 @@ const List = function(props: DataListType) {
const { onChange, value, connectDropTarget } = props;
const [list, setList] = useState(value);
const [visible, setVisible] = useState(false);
const [curItem, setCurItem] = useState<BasicDataSource>();
const [curItem, setCurItem] = useState<TDataListDefaultTypeItem>();
const handleDel = (id: string) => {
if (value && onChange) {
@ -172,13 +172,13 @@ const List = function(props: DataListType) {
setVisible(false);
}, []);
const handleEdit = useCallback((item: BasicDataSource) => {
const handleEdit = useCallback((item: TDataListDefaultTypeItem) => {
setVisible(true);
setCurItem(item);
}, []);
const handleSave = useCallback(
(item: BasicDataSource) => {
(item: TDataListDefaultTypeItem) => {
setVisible(false);
if (onChange) {
onChange(list!.map(p => (p.id === item.id ? item : p)));

View File

@ -1,4 +1,4 @@
import React, { memo, useState, useEffect } from 'react';
import React, { memo, useEffect } from 'react';
import { Form, Select, InputNumber, Input, Switch, Radio, Button } from 'antd';
import Upload from '../Upload';
import DataList from '../DataList';
@ -7,7 +7,6 @@ import Color from '../Color';
import CardPicker from '../CardPicker';
import Table from '../Table';
import { Store } from 'antd/lib/form/interface';
import { BasicRangeType, IconSchema } from '../../DynamicEngine/schema';
import FormItems from '../FormItems';
// import styles from './index.less';
const normFile = (e: any) => {
@ -37,6 +36,7 @@ interface FormEditorProps {
const FormEditor = (props: FormEditorProps) => {
const { config, defaultValue, onSave, onDel, uid } = props;
console.log(defaultValue, config);
const onFinish = (values: Store) => {
onSave && onSave(values);
};
@ -51,7 +51,7 @@ const FormEditor = (props: FormEditorProps) => {
return () => {
form.resetFields();
};
}, [defaultValue]);
}, [defaultValue, form]);
return (
<Form
form={form}
@ -96,7 +96,7 @@ const FormEditor = (props: FormEditorProps) => {
{item.type === 'Select' && (
<Form.Item label={item.name} name={item.key}>
<Select placeholder="请选择">
{item.range.map((v: BasicRangeType<string>, i: number) => {
{item.range.map((v: any, i: number) => {
return (
<Option value={v.key} key={i}>
{v.text}
@ -109,7 +109,7 @@ const FormEditor = (props: FormEditorProps) => {
{item.type === 'Radio' && (
<Form.Item label={item.name} name={item.key}>
<Radio.Group>
{item.range.map((v: BasicRangeType<string>, i: number) => {
{item.range.map((v: any, i: number) => {
return (
<Radio value={v.key} key={i}>
{v.text}
@ -136,10 +136,7 @@ const FormEditor = (props: FormEditorProps) => {
)}
{item.type === 'CardPicker' && (
<Form.Item label={item.name} name={item.key} valuePropName="type">
<CardPicker
icons={item.icons}
type={defaultValue['type'] as IconSchema['config']['type']}
/>
<CardPicker icons={item.icons} type={defaultValue['type']} />
</Form.Item>
)}
{item.type === 'Table' && (

View File

@ -1,14 +1,199 @@
export interface ItextAreaConfigType {
////////////////////
export interface IUploadConfigType {
key: string;
name: string;
type: 'Upload';
isCrop?: boolean;
cropRate?: number;
}
export type TUploadDefaultType = Array<{
uid: string;
name: string;
status: string;
url: string;
}>;
/////////////////
export interface ITextConfigType {
key: string;
name: string;
type: 'Text';
}
export type TTextDefaultType = string;
////////////////////////
export interface ITextAreaConfigType {
key: string;
name: string;
type: 'TextArea';
}
export type TtextAreaDefaultType = string;
export interface InumberConfigType {
export type TTextAreaDefaultType = string;
////////////////////////////
export interface INumberConfigType {
key: string;
name: string;
type: 'Number';
range?: [number, number];
step?: number;
}
export type TNumberDefaultType = number;
///////////////////
export interface IDataListConfigType {
key: string;
name: string;
type: 'DataList';
}
export type TDataListDefaultTypeItem = {
id: string;
title: string;
desc: string;
link: string;
type?: number;
imgUrl: TUploadDefaultType;
};
export type TDataListDefaultType = Array<TDataListDefaultTypeItem>;
////////////////////
export interface IColorConfigType {
key: string;
name: string;
type: 'Color';
}
export type TColorDefaultType = string;
export interface IMutiTextConfigType {
key: string;
name: string;
type: 'MutiText';
}
export type TMutiTextDefaultType = Array<string>;
/////////////////////////////////
export interface ISelectConfigType<KeyType> {
key: string;
name: string;
type: 'Select';
range: Array<{
key: KeyType;
text: string;
}>;
}
export type TSelectDefaultType<KeyType> = KeyType;
/////////////////////////
export interface IRadioConfigType<KeyType> {
key: string;
name: string;
type: 'Radio';
range: Array<{
key: KeyType;
text: string;
}>;
}
export type TRadioDefaultType<KeyType> = KeyType;
///////////////
export interface ISwitchConfigType {
key: string;
name: string;
type: 'Switch';
}
export type TSwitchDefaultType = boolean;
/////////////////////////////
export interface ICardPickerConfigType<T> {
key: string;
name: string;
type: 'CardPicker';
icons: Array<T>;
}
export type TCardPickerDefaultType<T> = T;
/////////////
export interface ITableConfigType {
key: string;
name: string;
type: 'Table';
}
export type TTableDefaultType = Array<{
name: string;
value: number;
}>;
//////////////////
export interface IFormItemsConfigType {
key: string;
name: string;
type: 'FormItems';
}
//0---------baseform
export type baseFormOptionsType = {
label: string;
value: string;
};
export type baseFormTextTpl = {
id: string;
type: 'Text';
label: string;
placeholder: string;
};
export type baseFormNumberTpl = {
id: string;
type: 'Number';
label: string;
placeholder: string;
};
export type baseFormTextAreaTpl = {
id: string;
type: 'Textarea';
label: string;
placeholder: string;
};
export type baseFormMyRadioTpl = {
id: string;
type: 'MyRadio';
label: string;
options: baseFormOptionsType[];
};
export type baseFormMySelectTpl = {
id: string;
type: 'MySelect';
label: string;
options: baseFormOptionsType[];
};
export type baseFormDateTpl = {
id: string;
type: 'Date';
label: string;
placeholder: string;
};
export type baseFormUnion =
| baseFormTextTpl
| baseFormNumberTpl
| baseFormTextAreaTpl
| baseFormMyRadioTpl
| baseFormMySelectTpl
| baseFormDateTpl;
export type baseFormUnionType =
| baseFormTextTpl['type']
| baseFormNumberTpl['type']
| baseFormTextAreaTpl['type']
| baseFormMyRadioTpl['type']
| baseFormMySelectTpl['type']
| baseFormDateTpl['type'];
export type TFormItemsDefaultType = Array<baseFormUnion>;

View File

@ -1,5 +1,7 @@
import React, { memo, useEffect } from 'react';
import React, { FC, memo, useEffect } from 'react';
import { Form, Select, Input, Modal } from 'antd';
import { baseFormOptionsType, baseFormUnion } from '../FormEditor/types';
import { Store } from 'antd/lib/form/interface';
const { Option } = Select;
@ -8,10 +10,17 @@ const formItemLayout = {
wrapperCol: { span: 14 },
};
const EditorModal = props => {
interface EditorModalProps {
item: any;
onSave: (data: any) => void;
visible: boolean;
onCancel: () => void;
}
const EditorModal: FC<EditorModalProps> = props => {
const { item, onSave, visible, onCancel } = props;
const onFinish = values => {
const onFinish = (values: any) => {
onSave && onSave(values);
};
@ -19,7 +28,6 @@ const EditorModal = props => {
form
.validateFields()
.then(values => {
console.log(values);
values.id = item.id;
onSave && onSave(values);
})
@ -34,70 +42,72 @@ const EditorModal = props => {
return () => {
form.resetFields();
};
}, [item]);
}, [form, item]);
return (
!!item && (
<Modal
title="编辑表单组件"
visible={visible}
onOk={handleOk}
onCancel={onCancel}
okText="确定"
cancelText="取消"
>
<Form
form={form}
name={`formItem_editor_modal`}
{...formItemLayout}
onFinish={onFinish}
initialValues={item}
<>
{!!item && (
<Modal
title="编辑表单组件"
visible={visible}
onOk={handleOk}
onCancel={onCancel}
okText="确定"
cancelText="取消"
>
{
<Form.Item label="类型" name="type" hidden>
<Input />
</Form.Item>
}
{!!item.label && (
<Form.Item
label="字段名"
name="label"
rules={[{ required: true, message: '请输入字段名!' }]}
>
<Input />
</Form.Item>
)}
{!!item.placeholder && (
<Form.Item label="提示文本" name="placeholder">
<Input placeholder="请输入提示文本" />
</Form.Item>
)}
{!!item.options && (
<Form.Item
label="选项源"
name="options"
rules={[{ required: true, message: '选项不能为空!' }]}
>
<Select
placeholder="请输入"
mode="tags"
labelInValue
maxTagCount={39}
maxTagTextLength={16}
<Form
form={form}
name={`formItem_editor_modal`}
{...formItemLayout}
onFinish={onFinish}
initialValues={item}
>
{
<Form.Item label="类型" name="type" hidden>
<Input />
</Form.Item>
}
{!!item.label && (
<Form.Item
label="字段名"
name="label"
rules={[{ required: true, message: '请输入字段名!' }]}
>
{item.options.map((v, i) => {
return (
<Option value={v.value} key={i}>
{v.label}
</Option>
);
})}
</Select>
</Form.Item>
)}
</Form>
</Modal>
)
<Input />
</Form.Item>
)}
{!!item.placeholder && (
<Form.Item label="提示文本" name="placeholder">
<Input placeholder="请输入提示文本" />
</Form.Item>
)}
{!!item.options && (
<Form.Item
label="选项源"
name="options"
rules={[{ required: true, message: '选项不能为空!' }]}
>
<Select
placeholder="请输入"
mode="tags"
labelInValue
maxTagCount={39}
maxTagTextLength={16}
>
{item.options.map((v: baseFormOptionsType, i: number) => {
return (
<Option value={v.value} key={i}>
{v.label}
</Option>
);
})}
</Select>
</Form.Item>
)}
</Form>
</Modal>
)}
</>
);
};

View File

@ -1,14 +1,13 @@
import React, { memo, useState, useEffect } from 'react';
import React, { memo, useState } from 'react';
import BaseForm from '../../BasicShop/BasicComponents/Form/BaseForm';
import EditorModal from './EditorModal';
import { EditOutlined, MinusCircleOutlined } from '@ant-design/icons';
import styles from './formItems.less';
import { baseFormUnion, TFormItemsDefaultType } from '../FormEditor/types';
// import { Popconfirm } from 'antd';
import styles from './formItems.less';
const formTpl = [
const formTpl: TFormItemsDefaultType = [
{
id: '1',
type: 'Text',
@ -50,29 +49,35 @@ const formTpl = [
id: '6',
type: 'Date',
label: '日期框',
placeholder: '',
},
];
const FormItems = props => {
const { formList, onChange } = props;
console.log(props);
const [formData, setFormData] = useState(formList || []);
const [visible, setVisible] = useState(false);
const [curItem, setCurItem] = useState();
interface FormItemsProps {
formList?: TFormItemsDefaultType;
onChange?: (v: TFormItemsDefaultType) => void;
data: any;
}
const handleAddItem = item => {
const FormItems = (props: FormItemsProps) => {
const { formList, onChange } = props;
const [formData, setFormData] = useState<TFormItemsDefaultType>(formList || []);
const [visible, setVisible] = useState(false);
const [curItem, setCurItem] = useState<baseFormUnion>();
const handleAddItem = (item: baseFormUnion) => {
let tpl = formTpl.find(v => v.type === item.type);
let newData = [...formData, tpl];
let newData = [...formData, tpl!];
setFormData(newData);
onChange && onChange(newData);
};
const handleEditItem = item => {
const handleEditItem = (item: baseFormUnion) => {
setVisible(true);
setCurItem(item);
};
const handleDelItem = item => {
const handleDelItem = (item: baseFormUnion) => {
let newData = formData.filter(v => v.type !== item.type);
setFormData(newData);
onChange && onChange(newData);
@ -82,7 +87,7 @@ const FormItems = props => {
setVisible(false);
};
const handleSaveItem = data => {
const handleSaveItem = (data: baseFormUnion) => {
let newData = formData.map(v => (v.type === data.type ? data : v));
setFormData(newData);
onChange && onChange(newData);
@ -91,7 +96,7 @@ const FormItems = props => {
return (
<div className={styles.formItemWrap}>
<div className={styles.editForm}>
{formData.map((item, i) => {
{formData.map((item: baseFormUnion, i: number) => {
let FormItem = BaseForm[item.type];
return (
<div className={styles.formItem} key={i}>

View File

@ -2,11 +2,11 @@ import React, { memo, useState, useEffect } from 'react';
import { Input, Button, Popconfirm } from 'antd';
import { MinusCircleOutlined } from '@ant-design/icons';
import styles from './index.less';
import { TabConfigType } from '../../DynamicEngine/schema';
import { TMutiTextDefaultType } from '../FormEditor/types';
type MultiTextProps = {
onChange?: (v: TabConfigType['tabs']) => void;
value?: TabConfigType['tabs'];
onChange?: (v: TMutiTextDefaultType) => void;
value?: TMutiTextDefaultType;
};
export default memo(function MutiText(props: MultiTextProps) {

29145
yarn.lock

File diff suppressed because it is too large Load Diff