Commit 2532f05d authored by baixian's avatar baixian

直播功能完成

parents 0d525a6b fe966ef6
bww-develop
bww-new
bww-newui
bww-register
bww-router1
* bww-v1
bww-v2
develop
master
wxl-develop
zs-develop
remotes/origin/HEAD -> origin/master
remotes/origin/bww-chooseclass
remotes/origin/bww-develop
remotes/origin/bww-new
remotes/origin/bww-newui
remotes/origin/bww-register
remotes/origin/bww-router1
remotes/origin/bww-v1
remotes/origin/bww-v2
remotes/origin/develop
remotes/origin/develop-copy
remotes/origin/dianping
remotes/origin/draw-develop
remotes/origin/editor-develop
remotes/origin/master
remotes/origin/sj-dev-v1
remotes/origin/webpack-change
remotes/origin/wxl-develop
remotes/origin/wxl-guide
remotes/origin/zs-develop
......@@ -18,5 +18,5 @@
</head>
<body>
<div id="root"></div>
<script type="text/javascript" src="https://cdn.img.shangjiadao.cn/qingxiao/biz/dist/main.09567f.js"></script></body>
<script type="text/javascript" src="https://cdn.img.shangjiadao.cn/qingxiao/biz/dist/main.ea8103.js"></script></body>
</html>
\ No newline at end of file
This diff is collapsed.
......@@ -58,6 +58,9 @@
"react-dom": "^16.2.0",
"react-slick": "^0.25.2",
"video-react": "^0.14.1",
"video.js": "^7.6.6",
"videojs-playlist": "^4.3.1",
"videojs-playlist-ui": "^3.7.0",
"xlsx": "^0.15.0"
},
"devDependencies": {
......
......@@ -243,4 +243,10 @@ export default {
subjectDelete: `${dakaapi}member/website/subject/destroy`,
subjectSort: `${dakaapi}member/website/subject/subject_sort`,
},
liveClass: {
lives: `${dakaapi}member/lives`,
livesStatus: `${dakaapi}member/live/status`,
livesUrl: `${dakaapi}member/live/url`,
livesEnd: `${dakaapi}member/live/end`,
},
};
......@@ -210,5 +210,19 @@ export default {
},
],
},
{
id: '70',
name: '直播课堂',
key: 70,
isFather: false,
style: {
width: '20px',
height: '20px',
},
activeurl: `${__IMGCDN__}menu/live.png?v=1`,
notactiveurl: `${__IMGCDN__}menu/liveactive.png`,
path: '/sjd/liveClass',
relativePath: ['/sjd/liveClass', '/sjd/addLive', '/sjd/editLive/:id'],
},
],
};
......@@ -93,13 +93,13 @@ class MaterialModalForm extends React.Component {
{item.type === 1 &&
<div className={`${pageStyle.mediaBox} ${pageStyle.imgBox}`} title={JSON.parse(item.content).name}>
<img className={pageStyle.img} src={imagify(item.src)} alt="" />
<img className={pageStyle.imageicon} src={`${__IMGCDN__}/course/photo_icon.png`} alt="" />
<img className={pageStyle.imageicon} src={`${__IMGCDN__}course/photo_icon.png`} alt="" />
</div>
}
{item.type === 2 &&
<div className={`${pageStyle.mediaBox} ${pageStyle.videoBox}`} title={JSON.parse(item.content).name}>
<img className={pageStyle.img} src={`${videoPoster(item.src)}`} alt="" />
<img className={pageStyle.videoicon} src={`${__IMGCDN__}/course/video_icon.png`} alt="" />
<img className={pageStyle.videoicon} src={`${__IMGCDN__}course/video_icon.png`} alt="" />
<div className={pageStyle.videoplay}>
<img className={pageStyle.videoplayicon} src={`${__IMGCDN__}smallplayicon.png`} alt="" />
</div>
......
......@@ -56,6 +56,7 @@ import addcrm from './addcrm';
import crmdetail from './crmdetail';
import holidays from './holidays';
import officialtheme from './officialtheme';
import liveclass from './liveclass';
export default {
loginModel,
indexstaicModel,
......@@ -106,4 +107,5 @@ export default {
crmdetail,
holidays,
officialtheme,
liveclass,
};
This diff is collapsed.
......@@ -106,10 +106,11 @@ export default {
const { code, data } = permissionData;
if (code == 200) {
const userPermission = data.list.map(ele => Number(ele.menu_id));
userPermission.push(70);
yield put({
type: 'webapp/updateState',
payload: {
userPermission,
userPermission: [...userPermission],
},
});
const matchMenu = menuConfig.menus.find(ele => userPermission.indexOf(ele.key) != -1);
......
......@@ -1298,6 +1298,64 @@ export default {
},
});
}
if (pathname === '/sjd/liveClass') {
dispatch({
type: 'liveclass/queryinfo',
});
dispatch({
type: 'updateState',
payload: {
breadcrumbList: [{
path: pathname,
name: '直播课堂',
}],
},
});
}
if (pathname === '/sjd/addLive') {
dispatch({
type: 'liveclass/pageInit',
});
dispatch({
type: 'updateState',
payload: {
breadcrumbList: [
{
path: 'sjd/liveClass',
name: '直播课堂',
},
{
path: pathname,
name: '添加直播',
},
],
},
});
}
const editLiveclass = pathToRegexp('/sjd/editLive/:id').exec(pathname);
if (editLiveclass) {
dispatch({
type: 'liveclass/queryDetail',
payload: {
id: editLiveclass[1],
},
});
dispatch({
type: 'updateState',
payload: {
breadcrumbList: [
{
path: 'sjd/liveClass',
name: '直播课堂',
},
{
path: pathname,
name: '编辑直播',
},
],
},
});
}
if (pathname === '/sjd/record') {
dispatch({
type: 'classrecord/queryinfo',
......@@ -1376,11 +1434,13 @@ export default {
perPage: 200,
});
const { code, data } = permissionData;
const newArray = data.list.map(ele => Number(ele.menu_id));
newArray.push(70);
if (code == 200) {
yield put({
type: 'updateState',
payload: {
userPermission: data.list.map(ele => Number(ele.menu_id)),
userPermission: [...newArray],
},
});
} else {
......@@ -1504,15 +1564,15 @@ export default {
yield put({
type: 'onlineclasses/pageInit',
});
} if (locationPathname == '/sjd/coursegather') {
} else if (locationPathname == '/sjd/coursegather') {
yield put({
type: 'coursegatherindex/pageInit',
});
} if (pathToRegexp('/sjd/gatherdetail/:id').exec(locationPathname)) {
} else if (pathToRegexp('/sjd/gatherdetail/:id').exec(locationPathname)) {
yield put({
type: 'coursegatherdetail/pageInit',
});
} if (locationPathname == '/sjd/coursemateria') {
} else if (locationPathname == '/sjd/coursemateria') {
yield put({
type: 'coursemateria/pageInit',
});
......@@ -1572,6 +1632,18 @@ export default {
yield put({
type: 'createtheme/pageInit',
});
} else if (pathToRegexp('/sjd/liveClass').exec(locationPathname)) {
yield put({
type: 'liveclass/pageInit',
});
} else if (pathToRegexp('/sjd/addLive').exec(locationPathname)) {
yield put({
type: 'liveclass/pageInit',
});
} else if (pathToRegexp('/sjd/editLive/:id').exec(locationPathname)) {
yield put({
type: 'liveclass/pageInit',
});
}
// yield put({
// type: 'joinschooladd/pageInit',
......
This diff is collapsed.
@import '../../less/variables.less';
.container {
background-color: #fff;
border-radius: 2px;
padding:20px;
padding-bottom: 50px;
}
.topTip {
font-size:14px;
font-family:PingFang SC;
font-weight:400;
color:rgba(33,148,255,1);
padding-bottom: 20px;
display: block;
}
.headerWrap {
.commonTitle {
font-size:16px;
font-family:PingFangSC-Medium,PingFang SC;
font-weight:600;
line-height: 24px;
color:rgba(0,0,0,0.85);
margin-bottom: 20px;
.line {
width: 4px;
height: 20px;
background-color: #1890FF;
display: inline-block;
vertical-align: -10%;
margin-right: 6px;
border-radius: 2px;
}
}
:global {
.ant-form-item {
margin-bottom: 25px;
}
}
}
.addMobile {
font-size:13px;
font-family:PingFangSC-Regular,PingFang SC;
font-weight:400;
color:rgba(24,144,255,1);
line-height:18px;
cursor: pointer;
display: inline-block;
margin-left: 10px;
}
.mobileTip {
font-size:12px;
font-weight:400;
color:rgba(153,153,153,1);
line-height:17px;
margin-bottom: 0;
}
.imgWrap {
display: flex;
.imgLeft {
width: 200px;
height: 150px;
margin-right: 20px;
.coverimg {
width: 100%;
height: 100%;
}
.imgBox {
width: 200px;
height: 150px;
background-color: #F7F8F9;
border: 1px solid #E6E6E6;
border-radius: 6px;
text-align: center;
line-height: 150px;
.defaultImg {
width: 32px;
height: 28px;
}
}
}
.imgRight {
.uploadImg {
position: relative;
width: 100px;
height: 40px;
cursor: pointer;
.uploadInput {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
opacity: 0;
z-index: 5;
}
}
.imgTip {
font-size:14px;
font-family:PingFang SC;
font-weight:400;
color:rgba(143,143,143,1);
width: 270px;
line-height: 1.8;
margin-top: 40px;
.imgCase {
position: relative;
display: inline-block;
&>span {
font-size:14px;
font-family:PingFang SC;
font-weight:400;
color:rgba(24,144,255,1);
cursor: pointer;
}
&:hover .caseWrap{
opacity: 1;
z-index: 111;
}
.caseWrap {
position: absolute;
top: -300px;
right: -80px;
opacity: 1;
width: 200px;
height: 297px;
box-shadow: 0px 6px 12px 0px rgba(0, 0, 0, 0.05), 0px 2px 4px 0px rgba(0, 0, 0, 0.05);
border-radius: 2px;
z-index: -1;
padding: 14px 10px;
background-color: #fff;
&>img {
width: 100%;
height: 100%;
}
}
}
}
}
}
.radioWrap {
width: 100%;
:global {
.ant-form-item-children {
width: 100%;
}
.ant-radio-wrapper {
width: 100%;
display: flex;
align-items: center;
}
.ant-form-item {
margin-bottom: 0px;
}
}
.radioList {
display: flex;
align-items: center;
}
.radioName {
font-size:14px;
font-family:PingFang SC;
font-weight:400;
color:rgba(51,51,51,1);
display: inline-block;
margin-right: 20px;
}
.radioTip {
font-size:14px;
font-family:PingFang SC;
font-weight:400;
color:rgba(143,143,143,1);
}
}
.footerBox {
position: fixed;
bottom: 0;
background-color: #fff;
padding: 20px 20px 14px 20px;
width: 100%;
box-shadow:1px -6px 6px 0px rgba(0, 0, 0, 0.04);
transition: 0.2s left;
transition: 0.1s width;
z-index: 20;
text-align: left;
}
.exampleSize {
font-size: 14px;
font-family: PingFang SC;
font-weight: 400;
color: #1890ff;
cursor: pointer;
}
.example {
font-size: 16px;
display: flex;
position: fixed;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
-webkit-justify-content: center;
justify-content: center;
z-index: 9999;
top: 0;
left: 0;
.exampleImg {
position: absolute;
width: 379px;
height: 95%;
top: 5%;
overflow-y: scroll;
&>img {
max-width: 100%;
min-width: 100%;
}
}
.exampleClose {
position: absolute;
top: 5%;
width: 550px;
text-align: right;
.closeBtn {
width: 76px;
height: 32px;
border-radius: 4px;
color: white;
font-size: 14px;
background:#8D8D8D;
line-height: 32px;
border:1px solid rgba(255,255,255,1);
}
}
}
::-webkit-scrollbar {
width: 8px;
height: 10px;
background-color: rgba(0,0,0,0);
}
::-webkit-scrollbar-thumb {
border-radius: 6px;
background-color: rgba(0,0,0,.2);
transition: all .4s ease;
-moz-transition: all .4s ease;
-webkit-transition: all .4s ease;
-o-transition: all .4s ease;
}
import { connect } from 'dva';
import React from 'react';
import PropTypes from 'prop-types';
import { message, Row, Col, Input, Select, Modal, Form, InputNumber, Checkbox, Radio, Tabs } from 'antd';
import ClipboardJS from 'clipboard';
import { imagify, pageIn } from '../../utils/index';
import pageStyle from './DownloadModal.less';
const FormItem = Form.Item;
const { TabPane } = Tabs;
class DownloadModal extends React.Component {
componentWillMount() {
}
componentDidUpdate() {
}
componentWillUpdate() {
}
componentDidMount() { // 挂载
pageIn('直播课堂');
message.config({
maxCount: 1,
});
this.clipboard1 = new ClipboardJS('#btnCopyLink1'); // 点击按钮复制到粘贴板
this.clipboard2 = new ClipboardJS('#btnCopyLink2');
this.clipboard3 = new ClipboardJS('#btnCopyLink3');
this.clipboard1.on('success', () => {
message.success('复制成功', 0.3);
});
this.clipboard2.on('success', () => {
message.success('复制成功', 0.3);
});
this.clipboard3.on('success', () => {
message.success('复制成功', 0.3);
});
}
componentWillUnmount() { // 卸载
}
close = () => {
const { form, close } = this.props;
close();
}
downLoadApp = (type) => {
const a = document.createElement('a'); // 生成一个a元素
const event = new MouseEvent('click'); // 创建一个单击事件
const url = (type == 'windows' ? 'https://cdn.s.shangjiadao.cn/clock/software/OBS-Studio-23.0.1-Full-Installer-x86.exe' : 'https://cdn.s.shangjiadao.cn/clock/software/obs-mac-23.2.1-installer.pkg');
a.href = url; // 将生成的URL设置为a.href属性
a.dispatchEvent(event); // 触发a的单击事件
}
render() {
const {
visible,
form: { getFieldDecorator, getFieldValue },
liveUrlData,
} = this.props;
return (
<Modal
className={pageStyle.modalWrap}
visible={visible}
onCancel={this.close}
maskClosable={false}
zIndex={110}
width={740}
bodyStyle={{ borderRadius: 8 }}
footer={
<div className={pageStyle.footerTip}>
*若上述下载失败或要下载最新版请到OBS软件官网进行下载:https://obsproject.com/
</div>
}
>
<div className={pageStyle.wrap}>
<div className={pageStyle.title}>直播间创建成功,快去OBS直播客户端开始学员讲课吧</div>
{/* eslint-disable-next-line react/jsx-no-target-blank */}
<div className={pageStyle.titleTip}>说明:OBS是讲师进行直播推流使用的第三方软件,助教可以配合网页/h5进行直播评论互动,详情操作 查看 <a className={pageStyle.dowTip} href="https://w.url.cn/s/APP4rb7" target="_blank">OBS直播使用教程</a></div>
<div className={pageStyle.stepOne}>
<span>1</span>OBS推
</div>
<div className={pageStyle.stepWrap}>
<div className={pageStyle.stepText}>(1) OBS推流工具下载</div>
<div className={pageStyle.downloadType}>
<div className={pageStyle.downloadItem}>
<img className={pageStyle.macImg} src={`${__IMGCDN__}liveclass/mac.png`} alt="" />
<div className={pageStyle.downloadItemRight}>
<span>Mac</span>
<span className={pageStyle.dowloadSize} onClick={() => this.downLoadApp('mac')}>下载</span>
</div>
</div>
<div className={pageStyle.downloadItem}>
<img className={pageStyle.windowsImg} src={`${__IMGCDN__}liveclass/windows.png`} alt="" />
<div className={pageStyle.downloadItemRight}>
<span>Windows</span>
<span className={pageStyle.dowloadSize} onClick={() => this.downLoadApp('windows')}>下载</span>
</div>
</div>
</div>
<div className={pageStyle.stepText}>(2) 推流信息 <span>OBS软件中输入以下URL与流名称,根据桌面共享直播使用教程配置开启直播</span></div>
<div className={pageStyle.copyWrap}>
<div className={pageStyle.copyRight}>URL</div>
<div className={pageStyle.copyBox} id="copy1">{liveUrlData.stream_url}</div>
<div className={pageStyle.copyButton} data-clipboard-target="#copy1" id="btnCopyLink1">复制</div>
</div>
<div className={pageStyle.copyWrap}>
<div className={pageStyle.copyRight}>流名称</div>
<div className={pageStyle.copyBox} id="copy2">{liveUrlData.stream_name}</div>
<div className={pageStyle.copyButton} data-clipboard-target="#copy2" id="btnCopyLink2">复制</div>
</div>
</div>
<div className={pageStyle.stepOne} style={{ marginTop: 16 }}>
<span>2</span>网页端地
<div className={pageStyle.copyWrap} style={{ marginTop: 0, marginLeft: 47 }}>
<div className={pageStyle.copyBox} id="copy3">{ENVIRONMENT == 'pro' ? `https://h5.qingxiao.online/livecoursedesc/${liveUrlData.id}` : `https://clock-h5.wp53.cn/livecoursedesc/${liveUrlData.id}`}</div>
<div className={pageStyle.copyButton} data-clipboard-target="#copy3" id="btnCopyLink3">复制</div>
</div>
</div>
<p className={pageStyle.webTip}>复制链接在网页直接打开</p>
</div>
</Modal>
);
}
}
const Download = Form.create()(DownloadModal);
export default Download;
.wrap {
.title {
font-size:16px;
font-family:PingFang SC;
font-weight:bold;
color:rgba(0,0,0,1);
position: relative;
text-align: center;
&:after {
position: absolute;
content: '';
display: block;
width: 34px;
height: 4px;
background-color: #1890FF;
border-radius: 2px;
left: 50%;
bottom: -10px;
}
}
.titleTip {
margin: 30px 0;
font-size: 14px;
color: #888;
&>span {
font-size:14px;
font-family:PingFang SC;
font-weight:400;
color:rgba(128,128,128,1);
text-align: center;
}
.dowTip {
color: #2A75ED;
cursor: pointer;
}
}
}
.stepOne {
font-size:14px;
font-family:PingFang SC;
font-weight:400;
color:rgba(0,0,0,1);
display: flex;
align-items: center;
&>span {
width: 19px;
height: 19px;
border-radius: 50%;
background-color: #3699FF;
display: inline-block;
line-height: 19px;
text-align: center;
color: #fff;
margin-right: 13px;
}
}
.stepWrap {
margin-left: 35px;
.stepText {
font-size:14px;
font-family:PingFang SC;
font-weight:400;
color:rgba(0,0,0,1);
line-height:26px;
margin: 18px 0 20px;
&>span {
font-size:14px;
font-family:PingFang SC;
font-weight:400;
color:rgba(128,128,128,1);
}
}
.downloadType {
display: flex;
justify-content: center;
align-items: center;
.downloadItem {
display: flex;
&:first-child {
margin-right: 80px;
}
.macImg {
width: 47px;
height: 57px;
}
.windowsImg {
width: 52px;
height: 50px;
}
.downloadItemRight {
margin-left: 25px;
&>span {
display: block;
margin-bottom: 10px;
font-size:14px;
font-family:PingFang SC;
font-weight:400;
color:rgba(0,0,0,1);
}
.dowloadSize {
width: 41px;
height: 23px;
margin-bottom: 22px;
border: 1px solid #BFBFBF;
text-align: center;
line-height: 23px;
cursor: pointer;
}
}
}
}
}
.copyWrap {
margin-top: 16px;
margin-left: 52px;
display: -webkit-flex;
display: flex;
-webkit-align-items: center;
align-items: center;
.copyRight {
width: 42px;
margin-right: 20px;
height: 17px;
font-family: PingFangSC-Regular;
font-weight: 400;
color: #353535;
line-height: 17px;
}
.copyBox {
padding: 0 8px;
width: 388px;
background: #f5f7fa;
border-radius: 4px 0 0 4px;
border: 1px solid #9EAABA;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
height: 36px;
font-size: 14px;
font-weight: 400;
color: #808080;
line-height: 34px;
}
.copyButton {
font-size: 14px;
width: 64px;
height: 36px;
background: #3699FF;
border-radius: 0px 4px 4px 0px;
color: white;
display: -webkit-flex;
display: flex;
-webkit-justify-content: center;
justify-content: center;
-webkit-align-items: center;
align-items: center;
cursor: pointer;
}
}
.modalWrap {
:global {
.ant-modal-footer {
padding: 0;
}
}
}
.footerTip {
background-color: #EFEFEF;
font-size:12px;
font-family:PingFang SC;
font-weight:400;
color:rgba(128,128,128,1);
line-height:35px;
height: 35px;
text-align: center;
}
.webTip {
margin-left: 150px;
margin-top: 15px;
}
import { connect } from 'dva';
import React from 'react';
import { Icon, Divider, Tabs, Select, Form, Upload, Row, Col, Input, Radio, Modal, message } from 'antd';
import pageStyle from './Editor.less';
import api from '../../../common/api';
import { pageIn, hasBtnPower, LocalStorage, imagify, ossVideofy, audioorigin } from '../../../utils/index';
const upImg = `${__IMGCDN__}subjectUp.png`;
const { TabPane } = Tabs;
const { TextArea } = Input;
class Editor extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
clearHtml = () => {
if (this.uEditor) {
this.uEditor.execCommand('cleardoc');
}
}
componentWillUnmount() {
if (this.uEditor) {
this.uEditor.destroy();
}
clearTimeout(this.timeout2);
clearTimeout(this.setTimeout3);
}
componentDidMount() { // 挂载
this.renderEditor();
}
renderEditor = () => {
const { sid, commentParams } = this.props;
const that = this;
if (UE && document.getElementById('editor_id')) {
that.uEditor = UE.getEditor('editor_id', {
autoHeightEnabled: false,
zIndex: 10,
allowDivTransToP: false,
// UEDITOR_HOME_URL: '../../js/ueeditor/',
materiaImgUrl: api.courseMateria.index,
materiaImgParams: {
school_id: LocalStorage.getItem('sid') || 0,
type: 1,
// page: 1
// perPage: 12
trans_status: 2,
},
elementPathEnabled: false,
requestUser: LocalStorage.getItem('user') || {},
serverUrl: api.editorUpload,
imageFieldName: 'file',
initialFrameHeight: 300,
removeFormatAttributes: 'class,style,lang,width,height,align,hspace,valign',
toolbars: [
[
'source', // 源代码
'undo', // 撤销
'redo', // 重做
'fontsize', // 字号
'forecolor', // 字体颜色
'bold', // 加粗
'italic', // 斜体
'underline', // 下划线
// 'strikethrough', // 删除线
// 'subscript', // 下标
// 'superscript', // 上标
// 'blockquote', // 引用
// 'pasteplain', // 纯文本粘贴模式
// 'horizontal', // 分隔线
// 'removeformat', // 清除格式
// 'unlink', // 取消链接
'inserttitle', // 插入标题
'simpleupload', // 单图上传
'insertimage', // 多图上传
// 'link', // 超链接
'emotion', // 表情
'spechars', // 特殊字符
'searchreplace', // 查询替换
// 'map', // Baidu地图
// 'insertvideo', // 视频
'justifyleft', // 居左对齐
'justifyright', // 居右对齐
'justifycenter', // 居中对齐
'justifyjustify', // 两端对齐
// 'fullscreen', // 全屏
'imagecenter', // 居中
'edittip ', // 编辑提示
// 'customstyle', // 自定义标题
// 'background', // 背景
// 'scrawl', // 涂鸦
// 'music', // 音乐
// 'inserttable', // 插入表格
// 'drafts', // 从草稿箱加载
// 'charts', // 图表
// 'fontfamily', // 字体
// 'insertcode', // 代码语言
'insertorderedlist', // 有序列表
// 'insertunorderedlist', // 无序列表
'lineheight', // 行间距
'rowspacingtop', // 段前距
'rowspacingbottom', // 段后距
'backcolor', // 背景色
// 'preview', // 预览
],
],
});
that.timeout2 = setTimeout(() => {
if (document.getElementById('editor_id')) {
const { sid, commentParams } = that.props;
if (commentParams.content && commentParams.content.length == 1) {
if (commentParams.content[0].type == 'editor' && commentParams.content[0].value != '') {
that.uEditor.ready(() => {
that.uEditor.setContent(commentParams.content[0].value);
});
}
}
}
that.uEditor.ready(() => {
that.uEditor.setHeight(600);
that.uEditor.addListener('contentChange', () => {
that.props.uEditorChange(this.uEditor.getContent());
});
});
}, 800);
} else {
that.setTimeout3 = setTimeout(() => {
that.renderEditor();
}, 200);
}
}
render() {
const {
commentParams,
} = this.props;
return (
<div className={pageStyle.container}>
<div className="clearfix">
<div className={pageStyle.editorwrap} style={{ float: 'left' }}>
{/* eslint-disable-next-line array-callback-return,consistent-return */}
{commentParams.content.map((item, index) => {
// eslint-disable-next-line default-case
switch (item.type) {
case 'editor':
return (
<div key={index} className={pageStyle.editorwrap}>
<textarea id="editor_id" name="content" style={{ width: '700px', height: '300px' }}>
</textarea>
<div className={pageStyle.extraoperatebox}>
<div className={pageStyle.extraoperateitem} onClick={this.clearHtml}>
<img alt="" className={pageStyle.del} src={`${__IMGCDN__}coursetemplate/del.png`} />
<span>清空内容</span>
</div>
{/* <div className={pageStyle.extraoperateitem} onClick={this.reviewHtml}> */}
{/* <img alt="" className={pageStyle.mobile} src={`${__IMGCDN__}coursetemplate/mobile.png`} /> */}
{/* <span>手机预览</span> */}
{/* </div> */}
</div>
</div>
);
}
},
)}
</div>
</div>
</div>
);
}
}
Editor.propTypes = {
};
export default connect()(Editor);
.textWrap {
height: auto;
position: relative;
margin-bottom:10px;
:global {
.ant-input {
padding: 6px 15px 20px;
}
}
.sizeNumber {
position: absolute;
bottom: 8px;
right: 10px;
}
}
.templatesbox {
line-height: initial;
width: 282px;
border:1px solid rgba(0,0,0,0.15);
.templatesheader {
background-color: #D9D9D9;
line-height: 37px;
color: #616161;
font-size: 16px;
text-align: center;
}
.templatesbody {
padding: 9px;
max-height: 550px;
overflow-y: scroll;
.templatesitem {
margin-bottom: 12px;
.imgbox {
width: 100%;
height: 135px;
border-radius: 6px;
overflow: hidden;
position: relative;
img {
height: 135px;
display: block;
width: 100%;
}
&:hover .templateoperate {
display: flex;
}
.templateoperate {
display: none;
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
left: 0;
top: 0;
z-index: 1;
// display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
.operateitem {
letter-spacing: 1px;
line-height: 40px;
color: #FFFFFF;
font-size: 14px;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
.operateicon {
margin-right: 4px;
}
&.preview {
.operateicon {
width: 16px;
height: 12px;
}
}
&.use {
.operateicon {
width: 16px;
height: 16px;
}
}
cursor: pointer;
&:hover {
background-color: rgba(0,0,0,0.5);
}
}
}
}
.templatename {
color: #616161;
font-size: 12px;
text-align: center;
margin-top: 4px;
}
}
}
}
.editorwrap {
// width: 424px;
// margin-top: 15px;
position: relative;
.extraoperatebox {
line-height: initial;
position: absolute;
top: 0;
width: 105px;
right: -105px;
z-index: 5;
.extraoperateitem {
background: #404040;
-webkit-border-radius: 3px;
border-radius: 3px;
color: #fff;
padding: 6px 19px;
margin-bottom: 14px;
cursor: pointer;
font-size: 12px;
margin-bottom: 10px;
display: flex;
align-items: center;
.del {
width: 14px;
height: 16px;
display: block;
margin-right: 3px;
}
.mobile {
width: 10px;
height: 14px;
display: block;
margin-left: 2px;
margin-right: 5px;
}
}
}
.videowrap {
width: 100%;
height: 200px;
position: relative;
margin-bottom: 10px;
.videoPoster {
width: 100%;
height: 100%;
}
}
.videowrap:hover {
cursor: pointer;
.videohide {
opacity: 1;
background-color: rgba(0,0,0,0.5);
transition: all .3s;
z-index: 1;
color: #fff;
}
}
.videohide {
position: absolute;
width: 100%;
height: 100%;
bottom: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
color: #fff;
z-index: -1;
a {
color: #fff;
}
}
.uploadimgbox {
display: flex;
align-items: flex-end;
margin-bottom: 18px;
flex-wrap: wrap;
.imgwrap {
width: 100%;
// height: 120px;
border-radius: 4px;
// margin-right: 6px;
position: relative;
.uploadimgwrap {
width: 100%;
// height: 120px;
overflow: hidden;
}
}
.imgwrap:hover {
cursor: pointer;
.imghide {
opacity: 1;
background-color: rgba(0,0,0,0.5);
transition: all .3s;
z-index: 1;
color: #fff;
}
}
.imghide {
position: absolute;
width: 100%;
height: 100%;
bottom: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
opacity: 0;
color: #fff;
z-index: -1;
a {
color: #fff;
}
}
.teacheruploadimg {
object-fit: contain;
border-radius: 4px;
width: 100%;
}
.teacheruploadimg:nth-child(4n){
margin-right: 0;
}
}
}
.uploadflex {
display: flex;
align-items: center;
.uploadimg {
cursor: pointer;
width: 106px;
height: 32px;
line-height: 32px;
text-align: center;
border: 1px solid #D9D9D9;
border-radius: 4px;
color: rgba(0,0,0,0.65);
position: relative;
margin-right: 30px;
.fileuploadinput {
cursor: pointer;
position: absolute;
width: 100%;
height: 100%;
z-index: 1;
opacity: 0;
left: 0;
top: 0;
}
}
}
.toolList {
position: absolute;
right: -30px;
top: 0;
width: 30px;
height: 90px;
display: flex;
flex-direction: column;
background-color: #D3D3D3;
opacity: 0;
border-radius: 2px;
z-index: -1;
div {
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 14px;
cursor: pointer;
}
div>img {
width: 14px;
height: 14px;
}
.up:hover {
background-color: #1890FF;
}
.down,.nodown {
transform: rotate(180deg);
}
.nodown,.noup {
cursor: not-allowed;
}
.down:hover {
background-color: #1890FF;
}
.delete:hover {
background-color: #FF6060;
}
}
.textWrap:hover,.imgwrap:hover,.videowrap:hover {
.toolList {
opacity: 1;
z-index: 1;
}
}
import React from 'react';
import { Modal, Icon, message } from 'antd';
import QRCode from 'qrcode.react';
import ClipboardJS from 'clipboard';
import { imagify } from '../../../utils/index';
import pageStyle from './QrcodeShow.less';
class QrcodeShow extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
componentDidMount() { // 挂载
this.clipboard = new ClipboardJS('#btnCopyLink'); // 点击按钮复制到粘贴板
this.clipboard.on('success', () => {
message.success('复制成功', 0.3);
});
}
componentWillUnmount() { // 卸载
}
download = () => {
const Qr = document.getElementById('qrid');
const image = new Image();
image.src = Qr.toDataURL('image/png');
image.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
const context = canvas.getContext('2d');
context.drawImage(image, 0, 0, image.width, image.height);
const url = canvas.toDataURL('image/png'); // 得到图片的base64编码数据
const a = document.createElement('a'); // 生成一个a元素
const event = new MouseEvent('click'); // 创建一个单击事件
a.download = '二维码'; // 设置图片名称
a.href = url; // 将生成的URL设置为a.href属性
a.dispatchEvent(event); // 触发a的单击事件
};
}
render() {
const {
previewQrcodeShow,
previewQrcode,
closeQrcodeShow,
title,
} = this.props;
return (
<div className={pageStyle.container} style={{ display: previewQrcodeShow ? 'flex' : 'none' }}>
<div className={pageStyle.mask}></div>
<div className={pageStyle.qrcodeBox}>
<Icon type="close-circle" className={pageStyle.closeIcon} onClick={closeQrcodeShow} />
<div className={pageStyle.boxHeader}>
<div className={pageStyle.headerTitle}>{title}</div>
</div>
<div className={pageStyle.qrCode}>
{
previewQrcode && <QRCode className={pageStyle.qrCodeImage} id="qrid" value={previewQrcode} />
}
<div className={pageStyle.download} onClick={this.download}>保存图片至桌面</div>
<div className={pageStyle.copyWrap}>
<div className={pageStyle.copyBox} id="copy">{previewQrcode}</div>
<div className={pageStyle.copyButton} data-clipboard-target="#copy" id="btnCopyLink">复制</div>
</div>
</div>
</div>
</div>
);
}
}
QrcodeShow.propTypes = {
};
export default QrcodeShow;
@import '../../../less/variables.less';
@keyframes qrCodefadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.container {
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: 200;
display: flex;
align-items: center;
justify-content: center;
}
.mask {
position: absolute;
z-index: 1;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
}
.qrcodeBox {
min-height: 320px;
border-radius: 10px;
background-color: #fff;
position: relative;
z-index: 2;
animation: qrCodefadeIn 0.1s linear 1 forwards;
// overflow: hidden;
max-width: 520px;
width: calc(100% - 10px);
padding-bottom: 20px;
}
.boxHeader {
height: 150px;
background-image: url('@{imagesroot}qrboxheader.png');
background-size: 100% 100%;
}
.headerTitle {
color: #fff;
text-align: center;
font-size: 18px;
line-height: 1;
padding-top: 34px;
}
.closeIcon {
position: absolute;
font-size: 30px;
color: rgba(255, 255, 255 ,0.7);
// right: 0;
// top: 0;
right: -15px;
z-index: 2;
top: -15px;
cursor: pointer;
&:hover {
transition: 0.2s;
color: rgba(255, 255, 255 ,1);
}
}
.qrCode {
text-align: center;
}
.qrCodeImage {
width: 160px;
height: 160px;
display: block;
margin: -10px auto 0;
}
.download {
font-size: 16px;
color: #1890FF;
text-align: center;
padding: 20px 0;
cursor: pointer;
width: 190px;
margin: 0 auto;
}
.copyWrap {
display: -webkit-flex;
display: flex;
-webkit-align-items: center;
align-items: center;
justify-content: center;
.copyRight {
width: 42px;
margin-right: 20px;
height: 17px;
font-family: PingFangSC-Regular;
font-weight: 400;
color: #353535;
line-height: 17px;
}
.copyBox {
padding: 0 8px;
width: 388px;
background: #F5F7FA;
border-radius: 4px 0 0 4px;
border: 1px solid #eeeeee;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
height: 36px;
font-size: 14px;
font-weight: 400;
color: #808080;
line-height: 34px;
}
.copyButton {
font-size: 14px;
width: 64px;
height: 36px;
background: #3699FF;
border-radius: 0px 4px 4px 0px;
color: white;
display: -webkit-flex;
display: flex;
-webkit-justify-content: center;
justify-content: center;
-webkit-align-items: center;
align-items: center;
cursor: pointer;
}
}
import React from 'react';
import { Icon, Button } from 'antd';
import videojs from 'video.js';
import playlist from 'videojs-playlist';
import playlistUi from 'videojs-playlist-ui';
import componentStyle from './VideoListPlay.less';
import { imagify, ossVideofy } from '../../../utils/index';
let myVideo;
let curr = 0;
class VideoListPlay extends React.Component {
constructor(props) {
super(props);
this.state = {
};
videojs.addLanguage('zh-CN', {
Play: '播放',
Pause: '暂停',
'Current Time': '当前时间',
Duration: '时长',
'Remaining Time': '剩余时间',
'Stream Type': '媒体流类型',
LIVE: '直播',
Loaded: '加载完毕',
Progress: '进度',
Fullscreen: '全屏',
'Non-Fullscreen': '退出全屏',
Mute: '静音',
Unmute: '取消静音',
'Playback Rate': '播放速度',
Subtitles: '字幕',
'subtitles off': '关闭字幕',
Captions: '内嵌字幕',
'captions off': '关闭内嵌字幕',
Chapters: '节目段落',
'Close Modal Dialog': '关闭弹窗',
Descriptions: '描述',
'descriptions off': '关闭描述',
'Audio Track': '音轨',
'You aborted the media playback': '视频播放被终止',
'A network error caused the media download to fail part-way.': '网络错误导致视频下载中途失败。',
'The media could not be loaded, either because the server or network failed or because the format is not supported.': '视频因格式不支持或者服务器或网络的问题无法加载。',
'The media playback was aborted due to a corruption problem or because the media used features your browser did not support.': '由于视频文件损坏或是该视频使用了你的浏览器不支持的功能,播放终止。',
'No compatible source was found for this media.': '无法找到此视频兼容的源。',
'The media is encrypted and we do not have the keys to decrypt it.': '视频已加密,无法解密。',
'Play Video': '播放视频',
Close: '关闭',
'Modal Window': '弹窗',
'This is a modal window': '这是一个弹窗',
'This modal can be closed by pressing the Escape key or activating the close button.': '可以按ESC按键或启用关闭按钮来关闭此弹窗。',
', opens captions settings dialog': ', 开启标题设置弹窗',
', opens subtitles settings dialog': ', 开启字幕设置弹窗',
', opens descriptions settings dialog': ', 开启描述设置弹窗',
', selected': ', 选择',
'captions settings': '字幕设定',
'Audio Player': '音频播放器',
'Video Player': '视频播放器',
Replay: '重播',
'Progress Bar': '进度条',
'Volume Level': '音量',
'subtitles settings': '字幕设定',
'descriptions settings': '描述设定',
Text: '文字',
White: '白',
Black: '黑',
Red: '红',
Green: '绿',
Blue: '蓝',
Yellow: '黄',
Magenta: '紫红',
Cyan: '青',
Background: '背景',
Window: '视窗',
Transparent: '透明',
'Semi-Transparent': '半透明',
Opaque: '不透明',
'Font Size': '字体尺寸',
'Text Edge Style': '字体边缘样式',
None: '无',
Raised: '浮雕',
Depressed: '压低',
Uniform: '均匀',
Dropshadow: '下阴影',
'Font Family': '字体库',
'Proportional Sans-Serif': '比例无细体',
'Monospace Sans-Serif': '单间隔无细体',
'Proportional Serif': '比例细体',
'Monospace Serif': '单间隔细体',
Casual: '舒适',
Script: '手写体',
'Small Caps': '小型大写字体',
Reset: '重置',
'restore all settings to the default values': '恢复全部设定至预设值',
Done: '完成',
'Caption Settings Dialog': '字幕设定视窗',
'Beginning of dialog window. Escape will cancel and close the window.': '开始对话视窗。离开会取消及关闭视窗',
'End of dialog window.': '结束对话视窗',
'Now Playing': '正在播放',
'Up Next': '下一个播放',
'Untitled Video': '无标题视频',
});
}
componentDidMount() {
const { videoList, poster } = this.props;
const options = {
playbackRates: [0.5, 1, 1.5, 2, 4, 8, 16],
poster: imagify(poster),
language: 'zh-CN',
}; //
const source = document.getElementById('source');
// 视频列表播放 列表格式 [{name:'111',sources:[{src:'', type: 'video/mp4',}]}]
if (videoList.length > 0) {
source.setAttribute('src', videoList[0].sources[0].src);
myVideo = videojs('myVideo', options, (onPlayerReady) => {
myVideo.play();
myVideo.on('ended', () => {
if (curr >= videoList.length) {
curr = 0;
}
myVideo.src(videoList[curr].sources[0].src);
myVideo.load();
myVideo.play();
curr++;
});
});
curr++;
myVideo.playlist(videoList);
myVideo.playlistUi();
}
}
componentWillUnmount() {
curr = 0;
myVideo.dispose(); // 销毁videojs 不然下次打开是原生的Video
}
render() {
const { lookVideoPoster, closeVideoPlay } = this.props;
return (
<div className={`${componentStyle.VideoPlayBox} VideoPlayBox`}>
<Icon type="close-circle" className={componentStyle.closeIcon} onClick={closeVideoPlay} />
<div className={componentStyle.videoitem}>
<video
id="myVideo"
controls
preload="metadata"
className="video-js"
style={{
width: '100%',
height: '90%',
}}
>
<source id="source" />
</video>
<div id="playList" className="vjs-playlist"></div>
</div>
</div>
);
}
}
export default VideoListPlay;
This diff is collapsed.
import React from 'react';
import { Icon } from 'antd';
import videojs from 'video.js';
import componentStyle from './VideoPlay.less';
import { imagify } from '../../../utils';
let myVideo;
class VideoPlay extends React.Component {
constructor(props) {
super(props);
this.state = {
};
videojs.addLanguage('zh-CN', {
Play: '播放',
Pause: '暂停',
'Current Time': '当前时间',
Duration: '时长',
'Remaining Time': '剩余时间',
'Stream Type': '媒体流类型',
LIVE: '直播',
Loaded: '加载完毕',
Progress: '进度',
Fullscreen: '全屏',
'Non-Fullscreen': '退出全屏',
Mute: '静音',
Unmute: '取消静音',
'Playback Rate': '播放速度',
Subtitles: '字幕',
'subtitles off': '关闭字幕',
Captions: '内嵌字幕',
'captions off': '关闭内嵌字幕',
Chapters: '节目段落',
'Close Modal Dialog': '关闭弹窗',
Descriptions: '描述',
'descriptions off': '关闭描述',
'Audio Track': '音轨',
'You aborted the media playback': '视频播放被终止',
'A network error caused the media download to fail part-way.': '网络错误导致视频下载中途失败。',
'The media could not be loaded, either because the server or network failed or because the format is not supported.': '视频因格式不支持或者服务器或网络的问题无法加载。',
'The media playback was aborted due to a corruption problem or because the media used features your browser did not support.': '由于视频文件损坏或是该视频使用了你的浏览器不支持的功能,播放终止。',
'No compatible source was found for this media.': '无法找到此视频兼容的源。',
'The media is encrypted and we do not have the keys to decrypt it.': '视频已加密,无法解密。',
'Play Video': '播放视频',
Close: '关闭',
'Modal Window': '弹窗',
'This is a modal window': '这是一个弹窗',
'This modal can be closed by pressing the Escape key or activating the close button.': '可以按ESC按键或启用关闭按钮来关闭此弹窗。',
', opens captions settings dialog': ', 开启标题设置弹窗',
', opens subtitles settings dialog': ', 开启字幕设置弹窗',
', opens descriptions settings dialog': ', 开启描述设置弹窗',
', selected': ', 选择',
'captions settings': '字幕设定',
'Audio Player': '音频播放器',
'Video Player': '视频播放器',
Replay: '重播',
'Progress Bar': '进度条',
'Volume Level': '音量',
'subtitles settings': '字幕设定',
'descriptions settings': '描述设定',
Text: '文字',
White: '白',
Black: '黑',
Red: '红',
Green: '绿',
Blue: '蓝',
Yellow: '黄',
Magenta: '紫红',
Cyan: '青',
Background: '背景',
Window: '视窗',
Transparent: '透明',
'Semi-Transparent': '半透明',
Opaque: '不透明',
'Font Size': '字体尺寸',
'Text Edge Style': '字体边缘样式',
None: '无',
Raised: '浮雕',
Depressed: '压低',
Uniform: '均匀',
Dropshadow: '下阴影',
'Font Family': '字体库',
'Proportional Sans-Serif': '比例无细体',
'Monospace Sans-Serif': '单间隔无细体',
'Proportional Serif': '比例细体',
'Monospace Serif': '单间隔细体',
Casual: '舒适',
Script: '手写体',
'Small Caps': '小型大写字体',
Reset: '重置',
'restore all settings to the default values': '恢复全部设定至预设值',
Done: '完成',
'Caption Settings Dialog': '字幕设定视窗',
'Beginning of dialog window. Escape will cancel and close the window.': '开始对话视窗。离开会取消及关闭视窗',
'End of dialog window.': '结束对话视窗',
'Now Playing': '正在播放',
'Up Next': '下一个播放',
'Untitled Video': '无标题视频',
});
}
componentDidMount() {
const { src, poster } = this.props;
const options = {
playbackRates: [0.5, 1, 1.5, 2, 4, 8, 16],
poster: imagify(poster),
language: 'zh-CN',
};
myVideo = videojs('myVideo', options, (onPlayerReady) => {
myVideo.src(src);
myVideo.load();
});
}
componentWillUnmount() {
myVideo.dispose(); // 销毁videojs 不然下次打开是原生的Video
}
render() {
const { src, closeVideoPlay } = this.props;
return (
<div className={`${componentStyle.VideoPlayBox} VideoPlayBox`}>
<Icon type="close-circle" className={componentStyle.closeIcon} onClick={closeVideoPlay} />
<div className={componentStyle.videoitem}>
<video
id="myVideo"
controls
preload="metadata"
className="video-js"
style={{
width: '100%',
height: '90%',
}}
>
</video>
</div>
</div>
);
}
}
export default VideoPlay;
This diff is collapsed.
This diff is collapsed.
@import '../../less/variables.less';
.container {
background-color: #fff;
border-radius: 2px;
padding: 20px;
}
.headerbox{
background-color: #fff;
.headerbtn {
color: #2194FF;
font-size: 14px;
cursor: pointer;
}
padding-bottom: 18px;
}
.searchrow {
.formitem {
display: flex;
align-items: center;
margin-bottom: 16px;
.formitemlabel {
color: #000000;
font-size: 14px;
line-height: 1;
min-width: 70px;
white-space: nowrap;
}
}
}
.selectitem {
display: block;
}
.searchbtnbox {
height: 54px;
display: flex;
align-items: flex-end;
}
.resetbtn {
margin-right: 16px;
}
.tablebox {
background: #fff;
:global {
.ant-table-fixed {
border-bottom: 1px solid #E8E8E8 !important;
}
.ant-table tbody tr:nth-child(2n) {
background-color: #FBFBFB;
}
.ant-table-thead > tr > th, .ant-table-tbody > tr > td {
padding: 11px 10px;
}
.ant-table-bordered .ant-table-tbody tr td {
border-bottom: none;
border-right: none!important;
}
.ant-table-bordered .ant-table-thead tr th {
border-bottom: none;
border-right: none!important;
}
.ant-table-bordered .ant-table-thead tr th:last-child {
border-right: 1px solid #e8e8e8!important;
}
.ant-table-bordered .ant-table-tbody tr td:last-child {
border-right: 1px solid #e8e8e8!important;
}
.ant-table-bordered .ant-table-tbody tr:last-child {
border-bottom: 1px solid #e8e8e8!important;
}
}
}
.divideline {
color: #E9E9E9;
padding: 0 8px;
}
.alink {
color: #1890FF;
}
.classNamebox {
max-width: 250px;
word-break: break-all;
color: #1890FF;
cursor: pointer;
}
.tableoperatebox {
min-width: 160px;
line-height: 30px;
}
.endsearchcol {
margin-bottom: 18px;
}
.endclassfooter {
display: flex;
align-items: center;
justify-content: space-between;
}
.classroomitem {
margin-bottom: 5px;
.classroom {
color:rgba(0,0,0,0.85);
}
.aLink {
color: #1890FF;
padding-left: 21px;
}
}
.rightList {
display: flex;
align-items: center;
height: 32px;
.resetIcon {
width: 14px;
height: 14px;
cursor: pointer;
margin-right: 15px;
}
.expend {
font-size:13px;
font-family:PingFangSC-Regular,PingFang SC;
font-weight:400;
color:rgba(102,102,102,1);
display: inline-block;
cursor: pointer;
}
}
.tablefooterbox {
color: rgba(0,0,0,0.6);
font-size: 16px;
line-height: 50px;
display: flex;
background-color: #fff;
align-items: center;
justify-content: space-between;
padding-left: 14px;
padding-right: 14px;
margin-top: 10px;
.tablefooterstatic {
color:rgba(0,0,0,0.65);
font-size: 14px;
}
}
.typeColor {
.point {
width: 6px;
height: 6px;
border-radius: 50%;
display: inline-block;
margin-right: 5px;
}
.typeColor1 {
color: #FEC02A;
display: flex;
align-items: center;
.point {
background-color: #FEC02A;
}
}
.typeColor2 {
display: flex;
align-items: center;
color: #3ADD60;
.point {
background-color: #3ADD60;
}
}
.typeColor3 {
display: flex;
align-items: center;
color: #F96500;
.point {
background-color: #F96500;
}
}
.typeColor4 {
color: #818181;
display: flex;
align-items: center;
.point {
background-color: #818181;
}
}
}
.tableImg {
display: flex;
&>img {
width: 80px;
height: 60px;
border-radius: 2px;
margin-right: 12px;
}
.tableText {
width: 200px;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
word-break: break-all;
text-overflow: ellipsis;
}
}
......@@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
import {
message, Row, Col, Input, Select, Modal, Form, InputNumber, Checkbox, Radio, Tabs,
Icon, Pagination,
Empty,
} from 'antd';
import { imagify, pageIn } from '../../../utils/index';
import pageStyle from './AddThemeClassModal.less';
......@@ -194,7 +195,7 @@ class AddThemeClassModal extends React.Component {
<div>课程类型</div>
</div>
{
themeList.length > 0 && themeList.map((item, index) =>
themeList.length > 0 ? themeList.map((item, index) =>
(
<div className={pageStyle.radioItem} onClick={() => this.handleCheck(item)}>
<div className={pageStyle.radioLeft}>
......@@ -209,7 +210,7 @@ class AddThemeClassModal extends React.Component {
<div>{this.getSubjectType(item.subject_type)}</div>
</div>
),
)
) : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
}
</div>
<Pagination
......
......@@ -281,6 +281,16 @@ const ThemeClass = props => (
{ ThemeClass => (<ThemeClass {...props} />) }
</Bundle>
);
const LiveClass = props => (
<Bundle load={() => import(/* webpackChunkName:"LiveClass" */'./pages/liveclass/index')}>
{ LiveClass => (<LiveClass {...props} />) }
</Bundle>
);
const AddLive = props => (
<Bundle load={() => import(/* webpackChunkName:"AddLive" */'./pages/liveclass/AddLive')}>
{ AddLive => (<AddLive {...props} />) }
</Bundle>
);
function RouterConfig({ history }) {
return (
<ConfigProvider locale={zhCN}>
......@@ -334,6 +344,9 @@ function RouterConfig({ history }) {
<Route path="/sjd/addCustomsContent/:id" exact component={UnclockDetail} />
<Route path="/sjd/addStoreCount/:id" exact component={AddStoreCount} />
<Route path="/sjd/themeClass" exact component={ThemeClass} />
<Route path="/sjd/liveClass" exact component={LiveClass} />
<Route path="/sjd/addLive" exact component={AddLive} />
<Route path="/sjd/editLive/:id" exact component={AddLive} />
<Route component={Errorpage} />
</Switch>
</SjdIndex>
......@@ -357,6 +370,7 @@ function RouterConfig({ history }) {
render={() => (
<OuterPage>
<Switch>
<Route path="/erp/deploySchool/:id" exact component={DeploySchool} />
<Route path="/erp/joinschooladd" exact component={JoinSchoolAdd} />
<Route path="/erp/schoollist" exact component={SchoolList} />
<Route path="/erp/schooladd" exact component={SchoolAdd} />
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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