🆕 添加icon组件库 📦 添加package.json说明日志

This commit is contained in:
xujiang 2020-09-02 00:55:17 +08:00
parent f4f2a2ebaa
commit b89af1975b
9 changed files with 301 additions and 137 deletions

View File

@ -1,9 +1,22 @@
{
"name": "h5-Dooring",
"version": "1.2.0",
"name": "h5-dooring",
"version": "1.3.0",
"description": "H5-Dooring是一款功能强大开源免费的H5可视化页面配置解决方案致力于提供一套简单方便、专业可靠、无限可能的H5落地页最佳实践。技术栈以react为主 后台采用nodejs开发。",
"private": false,
"license": "MIT",
"author": {
"name": "徐小夕",
"email": "xujiang156@qq.com",
"url": "http://io.nainor.com/h5_visible"
},
"keywords": [
"h5 editor",
"h5",
"react",
"antd",
"react-dnd",
"web visible"
],
"contributors": ["yehuozhili <yehuozhili@outlook.com> (https://github.com/yehuozhili))"],
"scripts": {
"start": "umi dev",
"build": "umi build",
@ -23,6 +36,7 @@
"prettier --parser=typescript --write"
]
},
"homepage": "http://io.nainor.com/h5_visible",
"repository": {
"type": "git",
"url": "git+https://github.com/MrXujiang/h5-Dooring.git"
@ -58,5 +72,6 @@
"video-react": "^0.14.1",
"yorkie": "^2.0.0",
"zarm": "^2.5.1"
}
},
"license": "MIT"
}

View File

@ -0,0 +1,38 @@
import { useState, useEffect, memo } from 'react';
import classnames from 'classnames';
import Icon from '../Icon';
import styles from './index.less';
export default memo(props => {
const { type, icons, onChange } = props;
const [selected, setSelected] = useState(type);
const handlePicker = v => {
if (onChange) {
onChange(v);
return;
}
setSelected(v);
};
useEffect(() => {
setSelected(type);
}, [type]);
return (
<div className={styles.pickerWrap}>
{icons.map((item, i) => {
return (
<span
className={classnames(styles.picker, selected === item ? styles.selected : '')}
onClick={handlePicker.bind(this, item)}
key={i}
>
<Icon type={item} size={20} />
</span>
);
})}
</div>
);
});

View File

@ -0,0 +1,16 @@
.pickerWrap {
display: flex;
flex-wrap: wrap;
.picker {
display: inline-block;
padding: 10px;
border: 2px solid transparent;
cursor: pointer;
&:hover {
border-color: #4091f7;
}
&.selected {
border-color: #4091f7;
}
}
}

View File

@ -145,6 +145,8 @@ export default {
key: 'imgSize',
name: '图片大小',
type: 'Number',
isCrop: true,
cropRate: 1,
},
{
key: 'sourceData',
@ -271,6 +273,8 @@ export default {
key: 'qrcode',
name: '二维码',
type: 'Upload',
isCrop: true,
cropRate: 1,
},
{
key: 'text',
@ -364,6 +368,7 @@ export default {
key: 'imgUrl',
name: '上传',
type: 'Upload',
isCrop: false,
},
{
key: 'round',
@ -399,6 +404,8 @@ export default {
key: 'logo',
name: 'logo',
type: 'Upload',
isCrop: true,
cropRate: 1000 / 618,
},
{
key: 'logoText',
@ -519,6 +526,79 @@ export default {
color: 'rgba(153,153,153,1)',
},
},
Icon: {
editData: [
{
key: 'color',
name: '颜色',
type: 'Color',
},
{
key: 'size',
name: '大小',
type: 'Number',
},
{
key: 'spin',
name: '旋转动画',
type: 'Switch',
},
{
key: 'type',
name: '图标类型',
type: 'CardPicker',
icons: [
'AccountBookTwoTone',
'AlertTwoTone',
'ApiTwoTone',
'AppstoreTwoTone',
'AudioTwoTone',
'BankTwoTone',
'BellTwoTone',
'BookTwoTone',
'BugTwoTone',
'BuildTwoTone',
'BulbTwoTone',
'CalculatorTwoTone',
'CalendarTwoTone',
'CameraTwoTone',
'CarTwoTone',
'CarryOutTwoTone',
'CiCircleTwoTone',
'CloudTwoTone',
'CodeTwoTone',
'CrownTwoTone',
'CustomerServiceTwoTone',
'DollarCircleTwoTone',
'EnvironmentTwoTone',
'ExperimentTwoTone',
'FireTwoTone',
'GiftTwoTone',
'InsuranceTwoTone',
'LikeTwoTone',
'LockTwoTone',
'MailTwoTone',
'MessageTwoTone',
'PhoneTwoTone',
'PictureTwoTone',
'PlaySquareTwoTone',
'RedEnvelopeTwoTone',
'ShopTwoTone',
'TrademarkCircleTwoTone',
'StarTwoTone',
'SafetyCertificateTwoTone',
'SettingTwoTone',
'RocketTwoTone',
],
},
],
config: {
color: '',
size: 36,
spin: false,
type: 'CarTwoTone',
},
},
Video: {
editData: [
{

View File

@ -1,40 +1,44 @@
const template = [
{
type:'Text',
h: 20
{
type: 'Text',
h: 20,
},
{
type:'Carousel',
h: 82
{
type: 'Carousel',
h: 82,
},
{
type:'Tab',
h: 130
{
type: 'Tab',
h: 130,
},
{
type:'Notice',
h: 20
{
type: 'Notice',
h: 20,
},
{
type:'Qrcode',
h: 150
{
type: 'Qrcode',
h: 150,
},
{
type:'Footer',
h: 24
{
type: 'Icon',
h: 23,
},
{
type:'Image',
h: 188
{
type: 'Image',
h: 188,
},
{
type:'Header',
h: 28
{
type: 'Header',
h: 28,
},
{
type:'List',
h: 110
}
]
{
type: 'List',
h: 110,
},
{
type: 'Footer',
h: 24,
},
];
export default template
export default template;

View File

@ -1,17 +1,10 @@
import React, { memo, useState, useEffect } from 'react';
import {
Form,
Select,
InputNumber,
Input,
Switch,
Radio,
Button
} from 'antd';
import { Form, Select, InputNumber, Input, Switch, Radio, Button } from 'antd';
import Upload from '@/components/Upload';
import DataList from '@/components/DataList';
import MutiText from '@/components/MutiText';
import Color from '@/components/Color';
import CardPicker from '@/components/CardPicker';
// import styles from './index.less';
const normFile = e => {
@ -29,32 +22,24 @@ const formItemLayout = {
wrapperCol: { span: 16 },
};
const defaultConfig = [
{
"key": "tabs",
"name": "项目类别",
"type": "mutiText",
"defaultValue": ["类别一", "类别二"]
}
]
const FormEditor = props => {
const { config, defaultValue, onSave, onDel, uid } = props;
const FormEditor = (props) => {
const { config = defaultConfig, defaultValue, onSave, onDel, uid } = props
const onFinish = values => {
onSave && onSave(values)
}
onSave && onSave(values);
};
const handleDel = () => {
onDel && onDel(uid)
}
onDel && onDel(uid);
};
const [form] = Form.useForm()
const [form] = Form.useForm();
useEffect(() => {
return () => {
form.resetFields()
}
}, [defaultValue])
form.resetFields();
};
}, [defaultValue]);
return (
<Form
@ -64,83 +49,88 @@ const FormEditor = (props) => {
onFinish={onFinish}
initialValues={defaultValue}
>
{
config.map((item, i) => {
return <React.Fragment key={i}>
{
item.type === 'Number' &&
<Form.Item label={item.name} name={item.key}>
<InputNumber min={1} />
</Form.Item>
}
{
item.type === 'Text' &&
<Form.Item label={item.name} name={item.key}>
<Input />
</Form.Item>
}
{
item.type === 'DataList' &&
<Form.Item label={item.name} name={item.key}>
<DataList />
</Form.Item>
}
{
item.type === 'Color' &&
<Form.Item label={item.name} name={item.key}>
<Color />
</Form.Item>
}
{
item.type === 'MutiText' &&
<Form.Item label={item.name} name={item.key}>
<MutiText />
</Form.Item>
}
{
item.type === 'Select' &&
<Form.Item label={item.name} name={item.key}>
<Select placeholder="请选择">
{
item.range.map((v, i) => {
return <Option value={v.key} key={i}>{ v.text }</Option>
})
}
</Select>
</Form.Item>
}
{
item.type === 'Radio' &&
<Form.Item label={item.name} name={item.key}>
<Radio.Group>
{
item.range.map((v, i) => {
return <Radio value={v.key} key={i}>{ v.text }</Radio>
})
}
</Radio.Group>
</Form.Item>
}
{
item.type === 'Switch' &&
<Form.Item label={item.name} name={item.key} valuePropName="checked">
<Switch />
</Form.Item>
}
{
item.type === 'Upload' &&
<Form.Item label={item.name} name={item.key} valuePropName="fileList" getValueFromEvent={normFile}>
<Upload />
</Form.Item>
}
{config.map((item, i) => {
return (
<React.Fragment key={i}>
{item.type === 'Number' && (
<Form.Item label={item.name} name={item.key}>
<InputNumber min={1} max={item.range && item.range[1]} />
</Form.Item>
)}
{item.type === 'Text' && (
<Form.Item label={item.name} name={item.key}>
<Input />
</Form.Item>
)}
{item.type === 'DataList' && (
<Form.Item label={item.name} name={item.key}>
<DataList />
</Form.Item>
)}
{item.type === 'Color' && (
<Form.Item label={item.name} name={item.key}>
<Color />
</Form.Item>
)}
{item.type === 'MutiText' && (
<Form.Item label={item.name} name={item.key}>
<MutiText />
</Form.Item>
)}
{item.type === 'Select' && (
<Form.Item label={item.name} name={item.key}>
<Select placeholder="请选择">
{item.range.map((v, i) => {
return (
<Option value={v.key} key={i}>
{v.text}
</Option>
);
})}
</Select>
</Form.Item>
)}
{item.type === 'Radio' && (
<Form.Item label={item.name} name={item.key}>
<Radio.Group>
{item.range.map((v, i) => {
return (
<Radio value={v.key} key={i}>
{v.text}
</Radio>
);
})}
</Radio.Group>
</Form.Item>
)}
{item.type === 'Switch' && (
<Form.Item label={item.name} name={item.key} valuePropName="checked">
<Switch />
</Form.Item>
)}
{item.type === 'Upload' && (
<Form.Item
label={item.name}
name={item.key}
valuePropName="fileList"
getValueFromEvent={normFile}
>
<Upload cropRate={item.cropRate} isCrop={item.isCrop} />
</Form.Item>
)}
{item.type === 'CardPicker' && (
<Form.Item label={item.name} name={item.key} valuePropName="type">
<CardPicker icons={item.icons} />
</Form.Item>
)}
</React.Fragment>
})
}
);
})}
<Form.Item wrapperCol={{ span: 12, offset: 6 }}>
<Button type="primary" htmlType="submit">
保存
</Button>
<Button type="danger" style={{marginLeft: '20px'}} onClick={handleDel}>
<Button type="danger" style={{ marginLeft: '20px' }} onClick={handleDel}>
删除
</Button>
</Form.Item>
@ -148,4 +138,4 @@ const FormEditor = (props) => {
);
};
export default memo(FormEditor)
export default memo(FormEditor);

View File

@ -0,0 +1,20 @@
import { memo } from 'react';
import * as Icon from '@ant-design/icons';
import IconImg from 'assets/icon.png';
const XIcon = memo(props => {
const { color, size, type, spin, isTpl } = props;
const MyIcon = Icon[type];
return isTpl ? (
<div style={{ textAlign: 'center' }}>
<img style={{ verticalAlign: '-20px', width: '82px' }} src={IconImg} alt={type} />
图标
</div>
) : (
<MyIcon twoToneColor={color} style={{ fontSize: size }} spin={spin} />
);
});
export default XIcon;

View File

@ -20,7 +20,8 @@ const SourceBox = memo(props => {
pointEnd = monitor.getSourceClientOffset(),
y = pointEnd.y < top ? 0 : pointEnd.y - top,
col = 24, // 网格列数
cellHeight = 2;
cellHeight = 2,
w = item.type === 'Icon' ? 3 : col;
// 转换成网格规则的坐标和大小
let gridY = Math.ceil(y / cellHeight);
dispatch({
@ -28,7 +29,7 @@ const SourceBox = memo(props => {
payload: {
id: uuid(6, 10),
item,
point: { i: `x-${pointData.length}`, x: 0, y: gridY, w: col, h: item.h, isBounded: true },
point: { i: `x-${pointData.length}`, x: 0, y: gridY, w, h: item.h, isBounded: true },
},
});
},

View File

@ -6,7 +6,7 @@ import schema from 'components/DynamicEngine/schema';
import styles from './index.less';
const TargetBox = memo(props => {
const { item, dispatch, canvasId, pointData } = props;
const { item, dispatch, pointData } = props;
const [{ isDragging }, drag, preview] = useDrag({
item: {
type: item.type,