【后台管理系统】—— Ant Design Pro结合插件(一)
一、富文本braft-editor
- 安装并引用
npm install braft-editor --save import BraftEditor from 'braft-editor'
import 'braft-editor/dist/index.css' state中初始内容
editorState: BraftEditor.createEditorState(),
表单中使用<BraftEditor/>
<FormItem label="教程正文" {...formLayout}>
{getFieldDecorator('content', {
validateTrigger: 'onBlur',
rules: [{
required: true,
validator: (_, value, callback) => {
if (value.isEmpty()) {
callback('请输入正文内容')
} else {
callback()
}
}
}],
// 内容必须通过BraftEditor.createEditorState()转化为可读的格式
initialValue: current && detail ? BraftEditor.createEditorState(defaultContent(detail.content)) : ''
})(
<BraftEditor
className="my-editor"
controls={controls} // 按需添加控件按钮
extendControls={extendControls} // 自定义控件按钮
placeholder="请输入正文内容"
media={{ // 媒体对象
uploadFn: handleUploadFn, // 上传七牛云服务器获取url
validateFn: handleValidateFn, // 上传文件的限制
accepts: { // 可上传格式
image: 'image/png, image/jpeg, image/jpg, image/gif, image/webp, image/apng, image/svg',
video: 'video/mp4',
audio: 'audio/mp3, audio/mp4, audio/ogg, audio/mpeg'
}
}}
onChange={this.handleContentChange} // 内容更改方法
/>
)}
</FormItem>
- 打开弹框时处理获取到的HTML格式的content,转化为插件可读格式,同时字符串切割替换转换后台传来的七牛云前缀与安卓ios视频图片需要的标签处理
showEditModal = item => {
const { dispatch } = this.props; let content = '';
if(item.content){
content = item.content;
let contentObj = JSON.parse(BraftEditor.createEditorState(content).toRAW());
let urlArr;
Object.keys(contentObj.entityMap).forEach((key) => {
if(contentObj.entityMap[key].data.url){
urlArr = contentObj.entityMap[key].data.url.split('/')
console.log('编辑时', urlArr)
if(urlArr.length == 2){ //ios视频前缀yihezo
urlArr.splice(0,1);
contentObj.entityMap[key].data.url = `${setFileHost()}`+ 'yihezo/' + urlArr.join('/');
} if(urlArr.length == 3){ //其它媒体文件前缀sys/tutorial
urlArr.splice(0,1);
contentObj.entityMap[key].data.url = `${setFileHost()}`+ 'sys/' + urlArr.join('/');
}
}
});
let contentRaw = JSON.stringify(contentObj);
item.content = contentRaw;
}; dispatch({
type: 'course/fetchDetail',
payload: {
id: item.id
},
callback: (res) => {
if(res){
let detail = res.data;
let HTML = detail.content;
HTML = HTML.substring(24).substring(0, HTML.length-6);
HTML = HTML.replace(/style='max-width:100%' /g, "").replace(/poster=['|"].*?['|"]/g, "").replace(/alt='picvision' /g, "");
detail.content = HTML; this.setState({
detail,
current: item,
addSubmit: false
}, () => {
this.setState({
visible: true
})
});
}
}
})
}; - 组件需要的参数和方法
// 自带的可按需选择的控件按钮
const controls = [ 'undo', 'redo', 'separator',
'font-size', 'line-height', 'letter-spacing', 'separator',
'text-color', 'bold', 'italic', 'underline', 'strike-through', 'separator',
'superscript', 'subscript', 'remove-styles', 'emoji', 'separator', 'text-indent', 'text-align', 'separator',
'headings', 'list-ul', 'list-ol', 'separator',
'link', 'separator', 'hr', 'separator',
'media', 'separator',
'clear'
]; // 上传七牛云服务器获取url
const handleUploadFn = (param) => {
const { file } = param; const fileTypeArr = file.type.split('/');
const fileType = fileTypeArr[0]; if(fileType == 'video'){
handleImageUpload(file, 'tutorialVideo').then(res => {
param.success({
url: `${setFileHost()+res}`,
meta: {
id: new Date().getTime(),
loop: false,
autoPlay: false,
controls: true
}
})
})
}else{
handleImageUpload(file, 'tutorial').then(res => {
param.success({
url: `${setFileHost()+res}`,
meta: {
id: new Date().getTime(),
loop: false,
autoPlay: false,
controls: true
}
})
})
}
} // 可上传文件的大小范围
const handleValidateFn = (file) => {
return file.size < 1024 * 1024 * 100
} // content内容存在时,处理为可编辑数据
const defaultContent = (content) => {
let contentObj = JSON.parse(BraftEditor.createEditorState(content).toRAW());
let urlArr;
Object.keys(contentObj.entityMap).forEach((key) => {
if(contentObj.entityMap[key].data.url){
urlArr = contentObj.entityMap[key].data.url.split('/')
console.log('默认内容', urlArr);
if(urlArr.length == 2){ //ios视频前缀yihezo
urlArr.splice(0,1);
contentObj.entityMap[key].data.url = `${setFileHost()}`+ 'yihezo/' + urlArr.join('/');
} if(urlArr.length == 3){ //其它媒体文件前缀sys/tutorail
urlArr.splice(0,1);
contentObj.entityMap[key].data.url = `${setFileHost()}`+ 'sys/' + urlArr.join('/');
}
}
});
let contentRaw = JSON.stringify(contentObj);
return contentRaw;
} // 自定义控件按钮
const extendControls = [
{
key: 'custom-button',
type: 'button',
text: '预览',
onClick: this.handleEditPreview
}
]; - react页面渲染HTML
<div dangerouslySetInnerHTML = {{__html:返回的html代码片段}} ></div>
原理:
1.dangerouslySetInnerHTMl 是React标签的一个属性,类似于angular的ng-bind;
2.有2个{{}},第一{}代表jsx语法开始,第二个是代表dangerouslySetInnerHTML接收的是一个对象键值对;
3.既可以插入DOM,又可以插入字符串;
二、图片裁剪
- 安装并引用
npm install react-cropper --save import Cropper from 'react-cropper'
import "cropperjs/dist/cropper.css" Modal弹框包裹<Cropper />组件
<Modal
title="上传轮播图"
visible={this.state.editImageModalVisible}
width={500}
bodyStyle={{height: 350, textAlign: 'center' }}
maskClosable={false}
onCancel={this.handleCancelImg}
okText="确认上传"
cancelText="取消"
onOk={this.handleSaveImg}
onCancel={this.handleCancelImg}
>
<Cropper
src={this.state.srcCropper} //图片路径,即是base64的值,在Upload上传的时候获取到的
ref="cropper"
viewMode={1} //定义cropper的视图模式
aspectRatio={1/1}
zoomable={false} //是否允许放大图像
movable={false}
guides={true} //显示在裁剪框上方的虚线
background={false} //是否显示背景的马赛克
rotatable={false} //是否旋转
style={{ maxWidth:500, maxHeight: 300 }}
cropBoxResizable={true} //是否可以拖拽
cropBoxMovable={true} //是否可以移动裁剪框
dragMode="move"
center={true}
/>
</Modal>beforeUpload方法中在获得file之后,判断this.refs.cropper,设置组件所需参数
beforeUpload = (file) => {
let type = file.type.split('/')[0];
let name = file.name.split('.')[0];
if(type == 'video') {
let imgArray = [...this.state.imgList];
imgArray.push(file); handleImageUpload(file, 'video', name).then(res => {
this.setState({
imgList: imgArray
});
this.handleFileThumb(res, file, imgArray)
})
}else{
//当打开同一张图片的时候清除上一次的缓存
if (this.refs.cropper) {
this.refs.cropper.reset();
} var reader = new FileReader();
const image = new Image();
//因为读取文件需要时间,所以要在回调函数中使用读取的结果
reader.readAsDataURL(file); //开始读取文件 reader.onload = (e) => {
image.src = reader.result;
image.onload = () => {
this.setState({
srcCropper: e.target.result, //cropper的图片路径
selectImgName: file.name, //文件名称
selectImgSize: (file.size / 1024 / 1024), //文件大小
selectImgSuffix: file.type.split("/")[1], //文件类型
editImageModalVisible: true, //打开控制裁剪弹窗的变量,为true即弹窗
})
if (this.refs.cropper) {
this.refs.cropper.replace(e.target.result);
}
}
}
return false;
}
}点击弹框中【确定/保存裁剪后的图片,上传七牛云获取url,在Upload组件中显示】,【取消/关闭弹框】
handleSaveImg = () => {
let imgArray = [...this.state.imgList];
let imgFile = this.dataURLtoFile(this.refs.cropper.getCroppedCanvas().toDataURL(), this.state.selectImgName)
imgArray.push(imgFile); // 上传七牛云方法 --- Upload组件使用中有js封装过程
handleImageUpload(imgFile, 'image').then(res => {
this.setState({
imgList: imgArray,
srcCropper: this.state.srcCropper, //cropper的图片路径
}, () => {
this.setState({
editImageModalVisible: false
})
})
this.handleFileThumb(res, imgFile, imgArray)
})
} handleCancelImg = () => {
this.setState({
editImageModalVisible: false,
});
}
三、统计图表
- 官网图例:https://bizcharts.net/products/bizCharts
- 安装和引用
npm install bizcharts --save import {ChartCard, Field, TimelineChart} from '@/components/Charts'; import {
G2,
Chart,
Geom,
Axis,
Tooltip,
Coord,
Label,
Legend,
View,
Guide,
Shape,
Facet,
Util
} from "bizcharts";官方折线图Mock数据示例:
class Curved extends React.Component {
render() {
const data = [
{
month: "Jan",
city: "Tokyo",
temperature: 7
},
{
month: "Jan",
city: "London",
temperature: 3.9
},
{
month: "Feb",
city: "Tokyo",
temperature: 6.9
},
{
month: "Feb",
city: "London",
temperature: 4.2
},
{
month: "Mar",
city: "Tokyo",
temperature: 9.5
},
{
month: "Mar",
city: "London",
temperature: 5.7
},
{
month: "Apr",
city: "Tokyo",
temperature: 14.5
},
{
month: "Apr",
city: "London",
temperature: 8.5
},
{
month: "May",
city: "Tokyo",
temperature: 18.4
},
{
month: "May",
city: "London",
temperature: 11.9
},
{
month: "Jun",
city: "Tokyo",
temperature: 21.5
},
{
month: "Jun",
city: "London",
temperature: 15.2
},
{
month: "Jul",
city: "Tokyo",
temperature: 25.2
},
{
month: "Jul",
city: "London",
temperature: 17
},
{
month: "Aug",
city: "Tokyo",
temperature: 26.5
},
{
month: "Aug",
city: "London",
temperature: 16.6
},
{
month: "Sep",
city: "Tokyo",
temperature: 23.3
},
{
month: "Sep",
city: "London",
temperature: 14.2
},
{
month: "Oct",
city: "Tokyo",
temperature: 18.3
},
{
month: "Oct",
city: "London",
temperature: 10.3
},
{
month: "Nov",
city: "Tokyo",
temperature: 13.9
},
{
month: "Nov",
city: "London",
temperature: 6.6
},
{
month: "Dec",
city: "Tokyo",
temperature: 9.6
},
{
month: "Dec",
city: "London",
temperature: 4.8
}
];
const cols = {
month: {
range: [0, 1]
}
};
return (
<div>
<Chart height={400} data={data} scale={cols} forceFit>
<Legend />
<Axis name="month" />
<Axis
name="temperature"
label={{
formatter: val => `${val}°C`
}}
/>
<Tooltip
crosshairs={{
type: "y"
}}
/>
<Geom
type="line"
position="month*temperature"
size={2}
color={"city"}
shape={"smooth"}
/>
<Geom
type="point"
position="month*temperature"
size={4}
shape={"circle"}
color={"city"}
style={{
stroke: "#fff",
lineWidth: 1
}}
/>
</Chart>
</div>
);
}
} ReactDOM.render(<Curved />, mountNode)
转载请注明出处
【后台管理系统】—— Ant Design Pro结合插件(一)的更多相关文章
- 【后台管理系统】—— Ant Design Pro入门学习&项目实践笔记(三)
前言:前一篇记录了[后台管理系统]目前进展开发中遇到的一些应用点,这一篇会梳理一些自己学习Ant Design Pro源码的功能点.附:Ant Design Pro 在线预览地址. Dashboard ...
- Ant Design Pro (中后台系统)教程
一.概念:https://pro.ant.design/docs/getting-started-cn(官方网站) 1.Ant Design Pro 是什么: https://www.cnblogs ...
- ant design pro(一)安装、目录结构、项目加载启动【原始、以及idea开发】
一.概述 1.1.脚手架概念 编程领域中的“脚手架(Scaffolding)”指的是能够快速搭建项目“骨架”的一类工具.例如大多数的React项目都有src,public,webpack配置文件等等, ...
- 使用ant design pro搭建项目
脚手架搭建 git clone --depth=1 https://github.com/ant-design/ant-design-pro.git my-project 然后 cd my-proje ...
- 轻松玩转Ant Design Pro一
ant design pro来源于ant design,其是一段自带样式的react组件,用于企业后台的漂亮的,可控的组件.ant design有很多组件和样式,不可能所有都记住,我们只要记住常用的, ...
- ant design pro 当中改变ant design 组件的样式和 数据管理
ant design pro 简介 官网简介 链接 https://pro.ant.design/docs/getting-started-cn 项目结构 https://github.com/ant ...
- Ant Design Pro 学习笔记:数据流向
在讲这个问题之前,有一个问题应当讲一下: Ant Design Pro / umi / dva 是什么关系? 首先是 umi / dva 的关系. umi 是一个基于路由的 react 开发框架. d ...
- 阿里开源项目之Ant Design Pro
本篇文章主要包含的内容有三个方面. 第一.Ant Design Pro简介; 第二.Ant Design Pro能做什么; 第三.初步使用; 我相信通过这三个方面的讲解能让你大概知道Ant Desig ...
- ant design pro (十一)advanced Mock 和联调
一.概述 原文地址:https://pro.ant.design/docs/mock-api-cn Mock 数据是前端开发过程中必不可少的一环,是分离前后端开发的关键链路.通过预先跟服务器端约定好的 ...
随机推荐
- ExpressionTree学习笔记
概述: 这段时间需要制定自定义查询条件,感觉有必要学习ExpressionTree. 学习参考资料:https://msdn.microsoft.com/en-us/library/mt654263. ...
- 【二】Django 视图和url配置
在新建的Django项目下,新建一个views的python文件,编辑如下代码 from django.http import HttpResponse def hello(request): ret ...
- django Paginator 让分页变得完美
参考大佬地址:https://www.zmrenwu.com/courses/django-blog-tutorial/materials/21/ 类视图 from django.contrib.au ...
- 通过web.xml监听器启动main方法
web.xml中添加要启动的类 <listener> <listener-class>server.NettyServer</listener-class> < ...
- 本地安装node.js模块
一.需求 单位电脑不让上网,但是需要用到一个node.js模块,elasticdump. 二.解决 1.自己电脑上下载模块: npm install elasticdump -g 注意:必须要加 -g ...
- python实现加密的方式总结
python实现加密的方式总结 原文地址 目录 基础知识扫盲 Base64 MD5 DES 3DES AES RSA 基础知识扫盲 对称加密 对称密钥加密 , 又叫私钥加密.即信息发送的方和接受方用一 ...
- Nginx 故障实例
linux vi 操作提示 Found a swap file by the name "/usr/local/nginx/conf/.nginx.conf.swp" 解决方法: ...
- 洛谷P5055 可持久化文艺平衡树 (可持久化treap)
题目链接 文艺平衡树的可持久化版,可以使用treap实现. 作为序列使用的treap相对splay的优点如下: 1.代码短 2.容易实现可持久化 3.边界处理方便(splay常常需要在左右两端加上保护 ...
- 【模板】Lucas定理
代码如下 #include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=1e5+10 ...
- java面向对象1-面向对象概念
面向对象概念-类与对象的关系 封装:指隐藏对象的属性和实现细节,仅对外提供公共访问方式,private-构造方法/构造器-this关键字-static关键字(javadoc制作工具类) -代码块 继承 ...