一、富文本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结合插件(一)的更多相关文章

  1. 【后台管理系统】—— Ant Design Pro入门学习&项目实践笔记(三)

    前言:前一篇记录了[后台管理系统]目前进展开发中遇到的一些应用点,这一篇会梳理一些自己学习Ant Design Pro源码的功能点.附:Ant Design Pro 在线预览地址. Dashboard ...

  2. Ant Design Pro (中后台系统)教程

    一.概念:https://pro.ant.design/docs/getting-started-cn(官方网站) 1.Ant Design Pro 是什么:  https://www.cnblogs ...

  3. ant design pro(一)安装、目录结构、项目加载启动【原始、以及idea开发】

    一.概述 1.1.脚手架概念 编程领域中的“脚手架(Scaffolding)”指的是能够快速搭建项目“骨架”的一类工具.例如大多数的React项目都有src,public,webpack配置文件等等, ...

  4. 使用ant design pro搭建项目

    脚手架搭建 git clone --depth=1 https://github.com/ant-design/ant-design-pro.git my-project 然后 cd my-proje ...

  5. 轻松玩转Ant Design Pro一

    ant design pro来源于ant design,其是一段自带样式的react组件,用于企业后台的漂亮的,可控的组件.ant design有很多组件和样式,不可能所有都记住,我们只要记住常用的, ...

  6. ant design pro 当中改变ant design 组件的样式和 数据管理

    ant design pro 简介 官网简介 链接 https://pro.ant.design/docs/getting-started-cn 项目结构 https://github.com/ant ...

  7. Ant Design Pro 学习笔记:数据流向

    在讲这个问题之前,有一个问题应当讲一下: Ant Design Pro / umi / dva 是什么关系? 首先是 umi / dva 的关系. umi 是一个基于路由的 react 开发框架. d ...

  8. 阿里开源项目之Ant Design Pro

    本篇文章主要包含的内容有三个方面. 第一.Ant Design Pro简介; 第二.Ant Design Pro能做什么; 第三.初步使用; 我相信通过这三个方面的讲解能让你大概知道Ant Desig ...

  9. ant design pro (十一)advanced Mock 和联调

    一.概述 原文地址:https://pro.ant.design/docs/mock-api-cn Mock 数据是前端开发过程中必不可少的一环,是分离前后端开发的关键链路.通过预先跟服务器端约定好的 ...

随机推荐

  1. ExpressionTree学习笔记

    概述: 这段时间需要制定自定义查询条件,感觉有必要学习ExpressionTree. 学习参考资料:https://msdn.microsoft.com/en-us/library/mt654263. ...

  2. 【二】Django 视图和url配置

    在新建的Django项目下,新建一个views的python文件,编辑如下代码 from django.http import HttpResponse def hello(request): ret ...

  3. django Paginator 让分页变得完美

    参考大佬地址:https://www.zmrenwu.com/courses/django-blog-tutorial/materials/21/ 类视图 from django.contrib.au ...

  4. 通过web.xml监听器启动main方法

    web.xml中添加要启动的类 <listener> <listener-class>server.NettyServer</listener-class> < ...

  5. 本地安装node.js模块

    一.需求 单位电脑不让上网,但是需要用到一个node.js模块,elasticdump. 二.解决 1.自己电脑上下载模块: npm install elasticdump -g 注意:必须要加 -g ...

  6. python实现加密的方式总结

    python实现加密的方式总结 原文地址 目录 基础知识扫盲 Base64 MD5 DES 3DES AES RSA 基础知识扫盲 对称加密 对称密钥加密 , 又叫私钥加密.即信息发送的方和接受方用一 ...

  7. Nginx 故障实例

    linux vi 操作提示 Found a swap file by the name "/usr/local/nginx/conf/.nginx.conf.swp" 解决方法: ...

  8. 洛谷P5055 可持久化文艺平衡树 (可持久化treap)

    题目链接 文艺平衡树的可持久化版,可以使用treap实现. 作为序列使用的treap相对splay的优点如下: 1.代码短 2.容易实现可持久化 3.边界处理方便(splay常常需要在左右两端加上保护 ...

  9. 【模板】Lucas定理

    代码如下 #include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=1e5+10 ...

  10. java面向对象1-面向对象概念

    面向对象概念-类与对象的关系 封装:指隐藏对象的属性和实现细节,仅对外提供公共访问方式,private-构造方法/构造器-this关键字-static关键字(javadoc制作工具类) -代码块 继承 ...