Commit e70744c5 by chenshu

fix:优化富文本编辑器

parent ecf1e707
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-07-17 15:49:11
* @Last Modified by: chenshu
* @Last Modified time: 2021-03-24 14:13:04
* @Last Modified time: 2021-04-06 16:43:23
* @Description: 大班互动-添加/编辑直播课
*/
......@@ -20,7 +20,6 @@ import AddLiveIntro from './components/AddLiveIntro';
import { randomString } from '@/domains/basic-domain/utils';
import Upload from '@/core/upload';
import PreviewCourseModal from './modal/PreviewCourseModal';
import SelectPrepareFileModal from '../prepare-lesson/modal/SelectPrepareFileModal';
import CourseService from "@/domains/course-domain/CourseService";
import moment from 'moment';
import User from '@/common/js/user';
......@@ -113,23 +112,6 @@ class AddLive extends React.Component {
if (type === 'edit') {
this.getCourseDetail();
}
this.initBus();
}
componentWillUnmount() {
this.removeBus();
}
initBus = () => {
Bus.bind('graphicsEditorImage', this.uploadImage)
}
removeBus = () => {
Bus.unbind('graphicsEditorImage', this.uploadImage)
}
uploadImage = () => {
this.setState({ showSelectImageModal: true })
}
getCourseDetail = () => {
......@@ -543,20 +525,6 @@ handleChangeBasicInfo = (field, value) => {
}
}
handleSelectImage = (file) => {
this.setState({
showSelectImageModal: false
})
const { ossUrl } = file;
const { addLiveIntroInfo } = this.state;
this.setState({
addLiveIntroInfo: {
...addLiveIntroInfo,
introduce: `${addLiveIntroInfo.introduce}<p><img style="max-width: 100%;" src="${ossUrl}" /><br/><p>`
}
});
}
render() {
const {
......@@ -567,9 +535,7 @@ handleChangeBasicInfo = (field, value) => {
addLiveIntroInfo,
isEdit,
loadintroduce,
showSelectImageModal,
} = this.state;
console.log(loadintroduce, addLiveIntroInfo, 888888)
return (
<div className="page add-live-page">
<Breadcrumbs
......@@ -617,22 +583,6 @@ handleChangeBasicInfo = (field, value) => {
<Button onClick={this.handleShowPreviewModal}>预览</Button>
<Button type="primary" onClick={_.debounce(() => this.handleSubmit(), 3000, true)}>保存</Button>
</div>
{showSelectImageModal &&
<SelectPrepareFileModal
key="basic"
operateType="select"
multiple={false}
accept="image/jpeg,image/png,image/jpg"
selectTypeList={['JPG', 'JPEG', 'PNG']}
tooltip='支持文件类型:jpg、jpeg、png'
isOpen={showSelectImageModal}
onClose={() => {
this.setState({ showSelectImageModal: false })
}}
onSelect={this.handleSelectImage}
/>
}
{ this.state.previewLiveCourseModal }
{ this.state.lackConsumeStudentModal }
</div>
......
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-07-16 11:05:17
* @Last Modified by: chenshu
* @Last Modified time: 2021-03-23 17:39:50
* @Last Modified time: 2021-04-06 16:40:24
* @Description: 添加直播-简介
*/
......@@ -83,61 +83,6 @@ class AddLiveIntro extends React.Component {
}
// 删除简介
handleDeleteIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data;
liveCourseMediaRequests.splice(index, 1);
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
// 上移简介
handleMoveUpIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data;
const prevItem = liveCourseMediaRequests[index];
const nextItem = liveCourseMediaRequests[index + 1];
liveCourseMediaRequests.splice(index, 2, nextItem, prevItem);
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
// 下移简介
handleMoveDownIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data;
const prevItem = liveCourseMediaRequests[index - 1];
const nextItem = liveCourseMediaRequests[index];
liveCourseMediaRequests.splice(index - 1, 2, nextItem, prevItem);
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
renderLittleIcon = (index) => {
const { liveCourseMediaRequests } = this.props.data;
return (
<div className="little-icon">
<span
className="icon iconfont close"
onClick={() => { this.handleDeleteIntro(index); }}
></span>
{
index > 0 &&
<span
className="icon iconfont"
onClick={() => { this.handleMoveDownIntro(index); }}
>&#xe6d1;</span>
}
{
index !== liveCourseMediaRequests.length - 1 &&
<span
className="icon iconfont"
onClick={() => { this.handleMoveUpIntro(index); }}
>&#xe6cf;</span>
}
</div>
)
}
changeIntro = (value) => {
this.props.onChange('introduce', value);
}
......@@ -149,9 +94,6 @@ class AddLiveIntro extends React.Component {
this.props.onChange('whetherVisitorsJoin','NO')
}
}
componentWillMount() {
}
render() {
const {liveType, isXiaomai, isEdit, data: { id, introduce, needRecord,whetherVisitorsJoin, loadintroduce, liveCourseWarmMedia = {} } } = this.props;
......
import { message } from 'antd';
import React from 'react';
import E from 'wangeditor';
import Bus from '../../../core/bus';
import SelectPrepareFileModal from '../../prepare-lesson/modal/SelectPrepareFileModal';
import './GraphicsEditor.less';
const { BtnMenu } = E;
class ImageMenu extends BtnMenu {
constructor(editor) {
// data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
const $elem = E.$(
`<div class="w-e-menu" data-title="图片">
<i class="w-e-icon-image"></i>
</div>`
)
super($elem, editor)
}
// 菜单点击事件
clickHandler() {
Bus.trigger('graphicsEditorImage')
}
tryChangeActive() {
}
}
class VideoMenu extends BtnMenu {
constructor(editor) {
// data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
const $elem = E.$(
`<div class="w-e-menu" data-title="视频">
<i class="w-e-icon-play"></i>
</div>`
)
super($elem, editor)
}
// 菜单点击事件
clickHandler() {
Bus.trigger('graphicsEditorVideo')
}
tryChangeActive() {
}
}
class GraphicsEditor extends React.Component {
constructor(props) {
super(props)
this.state = {
editorId: window.random_string(16),
textLength: 0,
showSelectImageModal: false,
showSelectVideoModal: false,
}
this.editorInt = null;
this.isContent = true;
}
componentDidMount() {
this.renderEditor()
this.resetIndex(true);
}
componentWillReceiveProps(nextProps) {
const { content } = this.props.detail;
const { content: nextContent } = nextProps.detail;
const videoCount = ((content || '').match(/<iframe/g) || []).length;
const nextVideoCount = ((nextContent || '').match(/<iframe/g) || []).length;
const imageCount = ((content || '').match(/<img/g) || []).length;
const nextImageCount = ((nextContent || '').match(/<img/g) || []).length;
if ((videoCount !== nextVideoCount) || (imageCount !== nextImageCount)) {
this.editorInt && this.editorInt.txt.html(nextProps.detail.content);
}
this.initBus();
this.bindClick();
}
componentWillUnmount() {
this.resetIndex();
this.removeBus();
this.removeClick();
}
bindClick = () => {
window.addEventListener('click', this.clickEditor)
}
removeClick = () => {
window.removeEventListener('click', this.clickEditor)
}
clickEditor = (e) => {
if (e && e.target.closest('.content-editor')) {
this.isContent = true
} else if (e && e.target.closest('.introduce-editor')) {
this.isContent = false
}
}
resetIndex = (bool) => {
......@@ -85,7 +58,47 @@ class GraphicsEditor extends React.Component {
renderEditor() {
const { editorId } = this.state;
const { detail, onChange, isIntro } = this.props;
const { detail, onChange, isIntro, maxLimit } = this.props;
class ImageMenu extends BtnMenu {
constructor(editor) {
// data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
const $elem = E.$(
`<div class="w-e-menu" data-title="图片">
<i class="w-e-icon-image"></i>
</div>`
)
super($elem, editor)
}
// 菜单点击事件
clickHandler() {
Bus.trigger(`graphicsEditorImage${isIntro ? '' : 'Content'}`)
}
tryChangeActive() {
}
}
class VideoMenu extends BtnMenu {
constructor(editor) {
// data-title属性表示当鼠标悬停在该按钮上时提示该按钮的功能简述
const $elem = E.$(
`<div class="w-e-menu" data-title="视频">
<i class="w-e-icon-play"></i>
</div>`
)
super($elem, editor)
}
// 菜单点击事件
clickHandler() {
Bus.trigger('graphicsEditorVideo')
}
tryChangeActive() {
}
}
this.editorInt = new E(`#editor${editorId}`);
this.editorInt.config.showFullScreen = !isIntro
this.editorInt.menus.extend('xmimage', ImageMenu);
......@@ -156,21 +169,96 @@ class GraphicsEditor extends React.Component {
const videoCount = ((html || '').match(/<iframe/g) || []).length;
const imageCount = ((html || '').match(/<img/g) || []).length;
const textLength = this.editorInt.txt.text().replace(/\&nbsp\;/ig, ' ').length + videoCount + imageCount;
console.log(html, 777777)
this.setState({ textLength }, () => {
if (textLength > maxLimit) {
message.warning('超过字数限定');
}
onChange(html, this.state.textLength);
})
}
this.editorInt.create();
this.editorInt.txt.html(detail.content);
}
// 选择图文
handleSelectVideo = (file) => {
this.setState({
showSelectVideoModal: false
})
const { ossUrl } = file;
const { detail } = this.props;
this.editorInt && this.editorInt.txt.html(`${detail.content}<p style="width: 100%;padding-top: 56.25%;position: relative;"><iframe style="position: absolute;width: 100%;height: 100%;top: 0;left: 0;" src="${ossUrl}"></iframe><br/></p><p><br/></p>`)
}
handleSelectImage = (file) => {
this.setState({
showSelectImageModal: false
})
const { ossUrl } = file;
const { detail } = this.props;
this.editorInt && this.editorInt.txt.html(`${detail.content}<p><img style="max-width: 100%;" src="${ossUrl}" /><br/><p>`)
}
initBus = () => {
const { isIntro } = this.props;
Bus.bind(`graphicsEditorImage${isIntro ? '' : 'Content'}`, this.uploadImage)
Bus.bind('graphicsEditorVideo', this.uploadVideo)
}
removeBus = () => {
const { isIntro } = this.props;
Bus.unbind(`graphicsEditorImage${isIntro ? '' : 'Content'}`, this.uploadImage)
Bus.unbind('graphicsEditorVideo', this.uploadVideo)
}
uploadImage = () => {
this.setState({ showSelectImageModal: true })
}
uploadVideo = () => {
this.setState({ showSelectVideoModal: true })
}
render() {
const { editorId, textLength } = this.state;
const { editorId, textLength, showSelectImageModal, showSelectVideoModal } = this.state;
const { limitLength = 1000, isIntro, maxLimit } = this.props;
return <div className={`graphics-editor-container${isIntro ? ' introduce' : ''}`}>
<div className="editor-box" id={`editor${editorId}`}></div>
<div className="editor-tips">({textLength}/{maxLimit || 100000})</div>
{showSelectVideoModal &&
<SelectPrepareFileModal
operateType="select"
selectTypeList={['MP4']}
accept="video/mp4"
confirm={{
title: '文件过大,无法上传',
content: '为保障学员的观看体验,上传的图文大小不能超过2G',
}}
tooltip={'格式支持mp4,大小不超过2G'}
isOpen={showSelectVideoModal}
diskList={diskList}
addVideo={true}
onClose={() => {
this.setState({ showSelectVideoModal: false })
}}
onSelect={this.handleSelectVideo}
/>
}
{showSelectImageModal &&
<SelectPrepareFileModal
key="basic"
operateType="select"
multiple={false}
accept="image/jpeg,image/png,image/jpg"
selectTypeList={['JPG', 'JPEG', 'PNG']}
tooltip='支持文件类型:jpg、jpeg、png'
isOpen={showSelectImageModal}
onClose={() => {
this.setState({ showSelectImageModal: false })
}}
onSelect={this.handleSelectImage}
/>
}
</div>
}
}
......
......@@ -15,7 +15,6 @@ import { DISK_MAP, FileTypeIcon, FileVerifyMap } from '@/common/constants/academ
import { ImgCutModalNew } from '@/components';
import ShowTips from "@/components/ShowTips";
import Breadcrumbs from "@/components/Breadcrumbs";
import Bus from '../../../core/bus'
import AddGraphicsIntro from './components/AddGraphicsIntro';
import SelectStudent from '../modal/select-student';
import SelectPrepareFileModal from '../../prepare-lesson/modal/SelectPrepareFileModal';
......@@ -70,10 +69,6 @@ class AddGraphicsCourse extends React.Component {
}
}
componentDidMount() {
this.initBus()
}
componentWillMount() {
const { id, pageType } = this.state;
this.getCourseCatalogList();
......@@ -82,10 +77,6 @@ class AddGraphicsCourse extends React.Component {
}
}
componentWillUnmount() {
this.removeBus();
}
initBus = () => {
Bus.bind('graphicsEditorImage', this.uploadImage)
Bus.bind('graphicsEditorVideo', this.uploadVideo)
......@@ -299,29 +290,6 @@ class AddGraphicsCourse extends React.Component {
this.setState({ previewGraphicsModal });
}
// 选择图文
handleSelectVideo = (file) => {
this.setState({
showSelectVideoModal: false
})
const { ossUrl } = file;
const { courseMedia } = this.state;
this.setState({
courseMedia: `${courseMedia}<p style="width: 100%;padding-top: 56.25%;position: relative;"><iframe style="position: absolute;width: 100%;height: 100%;top: 0;left: 0;" src="${ossUrl}"></iframe><br/></p><p><br/></p>`
});
}
handleSelectImage = (file) => {
this.setState({
showSelectImageModal: false
})
const { ossUrl } = file;
const { courseMedia, introduce, isContent } = this.state;
this.setState({
[isContent ? 'courseMedia' : 'introduce']: `${isContent ? courseMedia : introduce}<p><img style="max-width: 100%;" src="${ossUrl}" /><br/><p>`
});
}
handleSelectCover = (file)=> {
this.uploadCoverImage(file);
......@@ -538,8 +506,6 @@ class AddGraphicsCourse extends React.Component {
courseMedia,
introduce,
showCutModal,
showSelectVideoModal,
showSelectImageModal,
diskList,
imageFile,
videoType,
......@@ -632,41 +598,6 @@ class AddGraphicsCourse extends React.Component {
<Button type="primary" onClick={_.debounce(() => this.handleSubmit(), 3000, true)}>保存</Button>
</div>
{/* 选择备课文件弹窗 */}
{ showSelectVideoModal &&
<SelectPrepareFileModal
operateType="select"
selectTypeList={['MP4']}
accept="video/mp4"
confirm={{
title: '文件过大,无法上传',
content: '为保障学员的观看体验,上传的图文大小不能超过2G',
}}
tooltip={'格式支持mp4,大小不超过2G'}
isOpen={showSelectVideoModal}
diskList={diskList}
addVideo={true}
onClose={() => {
this.setState({ showSelectVideoModal: false })
}}
onSelect={this.handleSelectVideo}
/>
}
{showSelectImageModal &&
<SelectPrepareFileModal
key="basic"
operateType="select"
multiple={false}
accept="image/jpeg,image/png,image/jpg"
selectTypeList={['JPG', 'JPEG', 'PNG']}
tooltip='支持文件类型:jpg、jpeg、png'
isOpen={showSelectImageModal}
onClose={() => {
this.setState({ showSelectImageModal: false })
}}
onSelect={this.handleSelectImage}
/>
}
{showSelectCoverModal &&
<SelectPrepareFileModal
key="basic"
......
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-07-16 11:05:17
* @Last Modified by: chenshu
* @Last Modified time: 2021-03-25 11:25:02
* @Last Modified time: 2021-04-06 16:17:57
* @Description: 添加直播-简介
*/
......@@ -28,33 +28,6 @@ class AddGraphicsIntro extends React.Component {
diskList: [],
selectType: null,
}
this.isContent = true;
}
componentDidMount() {
this.bindClick();
}
componentWillUnmount() {
this.removeClick();
}
bindClick = () => {
window.addEventListener('click', this.clickEditor)
}
removeClick = () => {
window.removeEventListener('click', this.clickEditor)
}
clickEditor = (e) => {
if (e && e.target.closest('.content-editor')) {
this.isContent = true
console.log(11111111)
} else if (e && e.target.closest('.introduce-editor')) {
this.isContent = false
console.log(222222222)
}
}
// 上传封面图
......@@ -109,17 +82,11 @@ class AddGraphicsIntro extends React.Component {
}
changeDetail = (value) => {
this.props.onChange('isContent', !!this.isContent);
setTimeout(() => {
this.props.onChange('courseMedia', value);
}, 0)
this.props.onChange('courseMedia', value);
}
changeIntro = (value) => {
this.props.onChange('isContent', !!this.isContent);
setTimeout(() => {
this.props.onChange('introduce', value);
}, 0)
this.props.onChange('introduce', value);
}
whetherVisitorsJoinChange = ()=>{
......
......@@ -27,7 +27,6 @@ import _ from "underscore";
import Upload from '@/core/upload';
import { randomString } from '@/domains/basic-domain/utils';
import $ from 'jquery';
import Bus from '../../../core/bus'
// import PhotoClip from 'photoclip';
import './AddVideoCourse.less';
......@@ -90,19 +89,6 @@ class AddVideoCourse extends React.Component {
if (pageType === 'edit') {
this.handleFetchScheudleDetail(id);
}
this.initBus()
}
initBus = () => {
Bus.bind('graphicsEditorImage', this.uploadIntroImage)
}
removeBus = () => {
Bus.unbind('graphicsEditorImage', this.uploadIntroImage)
}
uploadIntroImage = () => {
this.setState({ showSelectImageModal: true })
}
//获取分类列表
......@@ -447,17 +433,6 @@ class AddVideoCourse extends React.Component {
handleSelectCover = (file)=> {
this.uploadImage(file);
}
handleSelectImage = (file) => {
this.setState({
showSelectImageModal: false
})
const { ossUrl } = file;
const { introduce } = this.state;
this.setState({
introduce: `${introduce}<p><img style="max-width: 100%;" src="${ossUrl}" /><br/><p>`
});
}
//上传图片
uploadImage = (imageFile) => {
......@@ -574,7 +549,6 @@ class AddVideoCourse extends React.Component {
introduce,
loadintroduce,
id,
showSelectImageModal,
} = this.state;
// 已选择的上课学员数量
......@@ -702,21 +676,6 @@ class AddVideoCourse extends React.Component {
onSelect={this.handleSelectVideo}
/>
}
{showSelectImageModal &&
<SelectPrepareFileModal
key="basic"
operateType="select"
multiple={false}
accept="image/jpeg,image/png,image/jpg"
selectTypeList={['JPG', 'JPEG', 'PNG']}
tooltip='支持文件类型:jpg、jpeg、png'
isOpen={showSelectImageModal}
onClose={() => {
this.setState({ showSelectImageModal: false })
}}
onSelect={this.handleSelectImage}
/>
}
{showSelectCoverModal &&
<SelectPrepareFileModal
key="basic"
......
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-07-16 11:05:17
* @Last Modified by: chenshu
* @Last Modified time: 2021-03-23 18:12:05
* @Last Modified time: 2021-04-06 16:44:09
* @Description: 添加直播-简介
*/
......@@ -82,84 +82,11 @@ class AddVideoIntro extends React.Component {
}
}
// 删除简介
handleDeleteIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data;
liveCourseMediaRequests.splice(index, 1);
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
// 上移简介
handleMoveUpIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data;
const prevItem = liveCourseMediaRequests[index];
const nextItem = liveCourseMediaRequests[index + 1];
liveCourseMediaRequests.splice(index, 2, nextItem, prevItem);
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
// 下移简介
handleMoveDownIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data;
const prevItem = liveCourseMediaRequests[index - 1];
const nextItem = liveCourseMediaRequests[index];
liveCourseMediaRequests.splice(index - 1, 2, nextItem, prevItem);
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
renderLittleIcon = (index) => {
const { liveCourseMediaRequests } = this.props.data;
return (
<div className="little-icon">
<span
className="icon iconfont close"
onClick={() => { this.handleDeleteIntro(index); }}
></span>
{
index > 0 &&
<span
className="icon iconfont"
onClick={() => { this.handleMoveDownIntro(index); }}
>&#xe6d1;</span>
}
{
index !== liveCourseMediaRequests.length - 1 &&
<span
className="icon iconfont"
onClick={() => { this.handleMoveUpIntro(index); }}
>&#xe6cf;</span>
}
</div>
)
}
handleChangeIntro = (index, value, length) => {
const { liveCourseMediaRequests } = this.props.data;
liveCourseMediaRequests[index].mediaContent = value;
liveCourseMediaRequests[index].mediaContentLength = length
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
changeIntro = (value) => {
this.props.onChange('introduce', value);
}
handleAddIntroText = () => {
const { liveCourseMediaRequests } = this.props.data;
liveCourseMediaRequests.push({
contentType:"INTRO",
mediaType: 'TEXT',
mediaContent: '',
key: Math.random()
});
this.props.onChange('liveCourseMediaRequests', liveCourseMediaRequests);
}
handleUpload = (Blob) => {
this.setState({
showSelectFileModal: true,
......@@ -180,9 +107,7 @@ class AddVideoIntro extends React.Component {
this.props.onChange('shelfState','NO')
}
}
componentWillMount() {
}
render() {
const {data: { whetherVisitorsJoin,liveCourseMediaRequests = [], shelfState, id, introduce, loadintroduce } } = this.props;
const {showSelectFileModal,selectType} = this.state
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment