🆕 添加富文本组件 💄 优化首页样式

This commit is contained in:
xujiang 2020-11-27 00:49:55 +08:00
parent 17ba811b3c
commit c86501388a
15 changed files with 324 additions and 21 deletions

View File

@ -62,6 +62,7 @@
"antd": "^4.7.0",
"antd-img-crop": "^3.10.0",
"axios": "^0.19.2",
"braft-editor": "^2.3.9",
"chatbot-antd": "^0.6.0",
"codemirror": "^5.57.0",
"dom-to-image": "^2.6.0",

BIN
src/assets/richText.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1,17 @@
.richTextWrap {
:global(p) {
margin-bottom: 0;
}
:global(img) {
max-width: 100%;
text-align: center;
}
:global(blockquote) {
margin: 0 0 10px;
padding: 12px 20px;
background-color: #f1f2f3;
border-left: 5px solid #ccc;
color: #666;
font-style: italic;
}
}

View File

@ -0,0 +1,30 @@
import React, { memo, useState } from 'react';
import styles from './index.less';
import { IButtonConfig } from './schema';
import logo from '@/assets/richText.png';
interface IProps extends IButtonConfig {
isTpl: boolean;
}
const XButton = memo((props: IProps) => {
const { isTpl, borderColor, borderWidth, round, padding, content } = props;
return isTpl ? (
<div>
<img style={{ width: '100%' }} src={logo} alt=""></img>
</div>
) : (
<div
className={styles.richTextWrap}
style={{
border: `${borderWidth}px solid ${borderColor}`,
borderRadius: round + 'px',
padding: padding + 'px',
}}
>
<div dangerouslySetInnerHTML={{ __html: content }}></div>
</div>
);
});
export default XButton;

View File

@ -0,0 +1,64 @@
import {
IColorConfigType,
INumberConfigType,
ITextConfigType,
TColorDefaultType,
TNumberDefaultType,
TTextDefaultType,
IRichTextConfigType,
TRichTextDefaultType,
} from '@/components/PanelComponents/FormEditor/types';
export type TButtonEditData = Array<
ITextConfigType | IColorConfigType | INumberConfigType | IRichTextConfigType
>;
export interface IButtonConfig {
round: TNumberDefaultType;
borderWidth: TNumberDefaultType;
padding: TNumberDefaultType;
borderColor: TColorDefaultType;
content: TRichTextDefaultType;
}
export interface IButtonSchema {
editData: TButtonEditData;
config: IButtonConfig;
}
const Button: IButtonSchema = {
editData: [
{
key: 'round',
name: '边框圆角',
type: 'Number',
},
{
key: 'borderWidth',
name: '边框宽度',
type: 'Number',
},
{
key: 'borderColor',
name: '边框颜色',
type: 'Color',
},
{
key: 'padding',
name: '内边距',
type: 'Number',
},
{
key: 'content',
name: '内容',
type: 'RichText',
},
],
config: {
round: 0,
borderWidth: 0,
borderColor: 'rgba(255,255,255,1)',
padding: 0,
content: '',
},
};
export default Button;

View File

@ -0,0 +1,6 @@
const template = {
type: 'RichText',
h: 120,
displayName: '富文本组件',
};
export default template;

View File

@ -11,6 +11,7 @@ import Notice from './Notice/schema';
import Qrcode from './Qrcode/schema';
import Tab from './Tab/schema';
import Text from './Text/schema';
import RichText from './RichText/schema';
const basicSchema = {
Carousel,
@ -26,5 +27,6 @@ const basicSchema = {
Qrcode,
Tab,
Text,
RichText,
};
export default basicSchema;

View File

@ -11,6 +11,7 @@ import Qrcode from './Qrcode/template';
import Tab from './Tab/template';
import Text from './Text/template';
import WhiteTpl from './WhiteTpl/template';
import RichText from './RichText/template';
const basicTemplate = [
Carousel,
@ -26,6 +27,7 @@ const basicTemplate = [
Tab,
Text,
WhiteTpl,
RichText,
];
const BasicTemplate = basicTemplate.map(v => {
return { ...v, category: 'base' };

View File

@ -8,6 +8,7 @@ import CardPicker from '../CardPicker';
import Table from '../Table';
import Pos from '../Pos';
import { Store } from 'antd/lib/form/interface';
import RichText from '../XEditor';
import FormItems from '../FormItems';
// import styles from './index.less';
const normFile = (e: any) => {
@ -158,6 +159,11 @@ const FormEditor = (props: FormEditorProps) => {
<FormItems data={item.data} rightPannelRef={rightPannelRef} />
</Form.Item>
)}
{item.type === 'RichText' && (
<Form.Item label={item.name} name={item.key} noStyle={true}>
<RichText />
</Form.Item>
)}
</React.Fragment>
);
})}

View File

@ -0,0 +1,4 @@
.avatarUploader > :global(.ant-upload) {
width: 128px;
height: 128px;
}

View File

@ -0,0 +1,94 @@
import React, { useState, useEffect, memo } from 'react';
import req from '@/utils/req';
import BraftEditor from 'braft-editor';
import 'braft-editor/dist/index.css';
import styles from './index.less';
const controls = [
{
key: 'bold',
text: <b></b>,
},
'undo',
'redo',
'emoji',
'list-ul',
'list-ol',
'blockquote',
'text-align',
'font-size',
'line-height',
'letter-spacing',
'text-color',
'italic',
'underline',
'link',
'media',
];
export default memo(function XEditor(props: any) {
const [editorState, setEditorState] = useState(BraftEditor.createEditorState());
const { value, onChange } = props;
const myUploadFn = param => {
const fd = new FormData();
fd.append('file', param.file);
req
.post('xxxx', fd, {
headers: {
'Content-Type': 'multipart/form-data',
},
onUploadProgress: function(event) {
// 上传进度发生变化时调用param.progress
console.log((event.loaded / event.total) * 100);
param.progress((event.loaded / event.total) * 100);
},
})
.then(res => {
console.log(res);
// 上传成功后调用param.success并传入上传后的文件地址
param.success({
url: res.url,
meta: {
id: Date.now(),
title: res.filename,
alt: '趣谈前端',
},
});
})
.catch(err => {
param.error({
msg: '上传失败.',
});
});
};
const submitContent = () => {
const htmlContent = editorState.toHTML();
onChange && onChange(htmlContent);
};
const handleEditorChange = editorState => {
setEditorState(editorState);
if (onChange) {
const htmlContent = editorState.toHTML();
onChange(htmlContent);
}
};
useEffect(() => {
const htmlContent = value || '';
setEditorState(BraftEditor.createEditorState(htmlContent));
}, []);
return (
<BraftEditor
value={editorState}
controls={controls}
onChange={handleEditorChange}
onSave={submitContent}
media={{ uploadFn: myUploadFn }}
/>
);
});

View File

@ -5,7 +5,7 @@ import styles from './index.less';
///这组件写的有问题 popover会重定位
const content = (
<div className={styles.imgWrap}>
<img src="http://io.nainor.com/uploads/WechatIMG2_1742b586c3d.jpeg" alt="sponsorship" />
<img src="http://49.234.61.19/uploads/WechatIMG2_1742b586c3d.jpeg" alt="sponsorship" />
</div>
);

View File

@ -53,7 +53,7 @@
.footer {
margin-top: 50px;
text-align: center;
font-size: 50px;
font-size: 15px;
p {
font-size: 16px;
}

View File

@ -1,13 +1,13 @@
import React from 'react';
import { Tabs, message, Button } from 'antd';
import { Tabs, message } from 'antd';
import { history } from 'umi';
import {
MobileOutlined,
ConsoleSqlOutlined,
GithubOutlined,
CodeOutlined,
IdcardOutlined,
} from '@ant-design/icons';
import Zan from '@/components/Zan';
import styles from './index.less';
const { TabPane } = Tabs;
@ -90,21 +90,30 @@ const Home = () => {
</div>
</div>
<footer className={styles.footer}>
<div>
<a href="https://github.com/MrXujiang/h5-Dooring">
<GithubOutlined />
</a>
<p>
Welcome to H5-Dooring
<span role="img" aria-label="welcome">
👋
</span>
</p>
<p>
<Button type="primary">
<a href="https://www.oschina.net/p/h5-dooring">dooring投票</a>
</Button>
</p>
<div style={{ display: 'flex', justifyContent: 'center' }}>
<div style={{ marginTop: '30px' }}>
<Zan />
</div>
<div style={{ width: '160px', marginLeft: '60px', marginTop: '32px' }}>
<a
href="http://49.234.61.19/h5?tid=B73349B8&isTpl=1"
style={{ marginRight: '24px' }}
target="_blank"
>
</a>
<a href="http://49.234.61.19/h5?tid=7B4008F7&isTpl=1" target="_blank">
</a>
</div>
</div>
<div style={{ display: 'flex', justifyContent: 'center' }}>
<div style={{ width: '360px', marginLeft: '60px', marginTop: '32px' }}>
<span style={{ marginRight: '24px' }}>: </span>
<a href="http://49.234.61.19/qt" style={{ marginRight: '24px' }} target="_blank">
-线gif动图制作平台
</a>
</div>
</div>
</footer>
</div>

View File

@ -3978,6 +3978,39 @@ braces@^3.0.1, braces@~3.0.2:
dependencies:
fill-range "^7.0.1"
braft-convert@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/braft-convert/-/braft-convert-2.3.0.tgz#27d5905136c334903d083b7a2352a72045627888"
integrity sha512-5km+dLHk8iYDv2iEYDrDQ2ld/ZoUx66QLql0qdm5PqZEcNXc8dBHGLORfzeu3iMw1jLeAiHxtdY5+ypuIhczVg==
dependencies:
draft-convert "^2.0.0"
draft-js "^0.10.3"
braft-editor@^2.3.9:
version "2.3.9"
resolved "https://registry.yarnpkg.com/braft-editor/-/braft-editor-2.3.9.tgz#fd2b8e23ea71191016579a1ed8231d16ad8f5b4a"
integrity sha512-mqdPk/zI2dhFK8tW/A4Qj/AkkARLh5L/niNw+iif5wFqb6zh15rMlrShgz1nWO/QXyAKr8XtDgxiBbR0zWwtRg==
dependencies:
"@babel/runtime" "^7.0.0"
braft-convert "^2.3.0"
braft-finder "^0.0.19"
braft-utils "^3.0.8"
draft-convert "^2.0.0"
draft-js "^0.10.3"
draft-js-multidecorators "^1.0.0"
draftjs-utils "^0.9.4"
immutable "~3.7.4"
braft-finder@^0.0.19:
version "0.0.19"
resolved "https://registry.yarnpkg.com/braft-finder/-/braft-finder-0.0.19.tgz#c324d82526ed3476a93de86cc9b407f4e188bc8d"
integrity sha512-0kzI6/KbomJJhYX1hpjn4edCKhblyUyWdUrsgBmOrwy0vrj+pPkm69+Uf8Uj6KGAULM6LF0ooC++p7fqUGgFHw==
braft-utils@^3.0.8:
version "3.0.12"
resolved "https://registry.yarnpkg.com/braft-utils/-/braft-utils-3.0.12.tgz#2b755ce1d8397d96b627b6767f74d07f25729d85"
integrity sha512-O2cKysURNC4HSEMKgNmQ2RluwcrxvYrztlEmyPN5SzktiNX3vaLFQoo0Ez3PlIhvjaGrIBSIT2Oyh2N6mn6TFg==
brorand@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
@ -5618,6 +5651,36 @@ dotenv@8.2.0:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a"
integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==
draft-convert@^2.0.0:
version "2.1.10"
resolved "https://registry.yarnpkg.com/draft-convert/-/draft-convert-2.1.10.tgz#07552f0aadff7ac01c8619d769210d4ea8fcab77"
integrity sha512-PRdcjBqFUfEb2jlPM+bOyyCNlTzGaHdyhvKsw5nur6Dj1YclmuAiTwJ8yTsEa95YI9kwzbO5ccZ/+tYj/LlS0A==
dependencies:
"@babel/runtime" "^7.5.5"
immutable "~3.7.4"
invariant "^2.2.1"
draft-js-multidecorators@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/draft-js-multidecorators/-/draft-js-multidecorators-1.0.0.tgz#6c4be8d7b78dd2b966ee51ee6cc179b9b535e612"
integrity sha1-bEvo17eN0rlm7lHubMF5ubU15hI=
dependencies:
immutable "*"
draft-js@^0.10.3:
version "0.10.5"
resolved "https://registry.yarnpkg.com/draft-js/-/draft-js-0.10.5.tgz#bfa9beb018fe0533dbb08d6675c371a6b08fa742"
integrity sha512-LE6jSCV9nkPhfVX2ggcRLA4FKs6zWq9ceuO/88BpXdNCS7mjRTgs0NsV6piUCJX9YxMsB9An33wnkMmU2sD2Zg==
dependencies:
fbjs "^0.8.15"
immutable "~3.7.4"
object-assign "^4.1.0"
draftjs-utils@^0.9.4:
version "0.9.4"
resolved "https://registry.yarnpkg.com/draftjs-utils/-/draftjs-utils-0.9.4.tgz#976c61aa133dbbbfedd65ae1dd6627d7b98c6f08"
integrity sha512-KYjABSbGpJrwrwmxVj5UhfV37MF/p0QRxKIyL+/+QOaJ8J9z1FBKxkblThbpR0nJi9lxPQWGg+gh+v0dAsSCCg==
duplexer3@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
@ -6486,7 +6549,7 @@ fb-watchman@^2.0.0:
dependencies:
bser "2.1.1"
fbjs@^0.8.0, fbjs@^0.8.3, fbjs@^0.8.9:
fbjs@^0.8.0, fbjs@^0.8.15, fbjs@^0.8.3, fbjs@^0.8.9:
version "0.8.17"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=
@ -7415,11 +7478,16 @@ immer@^7.0.5:
resolved "https://registry.yarnpkg.com/immer/-/immer-7.0.9.tgz#28e7552c21d39dd76feccd2b800b7bc86ee4a62e"
integrity sha512-Vs/gxoM4DqNAYR7pugIxi0Xc8XAun/uy7AQu4fLLqaTBHxjOP9pJ266Q9MWA/ly4z6rAFZbvViOtihxUZ7O28A==
immutable@^3.8.1:
immutable@*, immutable@^3.8.1:
version "3.8.2"
resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3"
integrity sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=
immutable@~3.7.4:
version "3.7.6"
resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.7.6.tgz#13b4d3cb12befa15482a26fe1b2ebae640071e4b"
integrity sha1-E7TTyxK++hVIKib+Gy665kAHHks=
import-cwd@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9"