Commit ba77125c authored by baixian's avatar baixian

youhua

parents 53d6cd7b 850e1a4a
......@@ -13,10 +13,10 @@
<script charset="utf-8" src="https://map.qq.com/api/js?v=2.exp&key=XSZBZ-5LHCV-5I2P7-UQHPW-6456F-JBB3B"></script>
<script src="/js/ueeditor/ueditor.config.js?20200107" charset="utf-8"></script><script src="/js/ueeditor/ueditor.all.js?20200107" charset="utf-8"></script>
<script src="https://cdn.img.shangjiadao.cn/qingxiao/biz/js/console-polyfill.js?20200107" charset="utf-8"></script><script src="https://cdn.img.shangjiadao.cn/qingxiao/biz/js/es6-shim.min.js?20200107" charset="utf-8"></script><script src="https://cdn.img.shangjiadao.cn/qingxiao/biz/js/es5-shim.js?20200107" charset="utf-8"></script><script src="https://cdn.img.shangjiadao.cn/qingxiao/biz/js/es5-sham.min.js?20200107" charset="utf-8"></script><script src="https://cdn.img.shangjiadao.cn/qingxiao/biz/js/json3.min.js?20200107" charset="utf-8"></script><script src="https://cdn.img.shangjiadao.cn/qingxiao/biz/js/html5shiv.min.js?20200107" charset="utf-8"></script><script src="https://cdn.img.shangjiadao.cn/qingxiao/biz/js/polyfill.js?20200107" charset="utf-8"></script><script src="https://cdn.img.shangjiadao.cn/qingxiao/biz/lib/vendor.dll.js?20200107" charset="utf-8"></script>
<script src="js/console-polyfill.js?20200107" charset="utf-8"></script><script src="js/es6-shim.min.js?20200107" charset="utf-8"></script><script src="js/es5-shim.js?20200107" charset="utf-8"></script><script src="js/es5-sham.min.js?20200107" charset="utf-8"></script><script src="js/json3.min.js?20200107" charset="utf-8"></script><script src="js/html5shiv.min.js?20200107" charset="utf-8"></script><script src="js/polyfill.js?20200107" charset="utf-8"></script><script src="lib/vendor.dll.js?20200107" charset="utf-8"></script>
</head>
</head>
<body>
<div id="root"></div>
<script type="text/javascript" src="https://cdn.img.shangjiadao.cn/qingxiao/biz/dist/main.1a6a46.js"></script></body>
<script type="text/javascript" src="/dist/main.80d239.js"></script></body>
</html>
\ No newline at end of file
This diff is collapsed.
......@@ -58,6 +58,7 @@
"react-dom": "^16.2.0",
"react-slick": "^0.25.2",
"video-react": "^0.14.1",
"video.js": "^7.6.6",
"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/crmactive.png`,
notactiveurl: `${__IMGCDN__}menu/crm.png`,
path: '/sjd/liveClass',
relativePath: ['/sjd/liveClass', '/sjd/addLive', '/sjd/editLive/:id'],
},
],
};
......@@ -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.
......@@ -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',
......@@ -1504,15 +1562,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 +1630,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;
}
.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: 3px;
height: 19px;
background-color: #1890FF;
display: inline-block;
vertical-align: -10%;
margin-right: 6px;
}
}
:global {
.ant-form-item {
margin-bottom: 20px;
}
}
}
.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;
}
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://xiaoetong-1252524126.file.myqcloud.com/obs-download/OBS-Studio-23.0.1-Full-Installer-x86.exe' : 'https://xiaoetong-1252524126.file.myqcloud.com/obs-download/OBS-Studio-23.0.1-Full-Installer-x86.exe');
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={800}
bodyStyle={{ borderRadius: 8 }}
footer={
<div className={pageStyle.footerTip}>
*若上述下载失败或要下载最新版请到OBS软件官网进行下载:https://obsproject.com/
</div>
}
>
<div className={pageStyle.wrap}>
<div className={pageStyle.title}>直播间创建成功,快去OBS直播客户端开始学员讲课吧</div>
<div className={pageStyle.titleTip}>说明:OBS是讲师进行直播推流使用的第三方软件,助教可以配合网页/h5进行直播评论互动,详情操作 查看 <span>OBS直播使用教程</span></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">https://www.baidu.com/</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;
}
}
}
.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 } from 'antd';
import QRCode from 'qrcode.react';
import { imagify } from '../../../utils/index';
import pageStyle from './QrcodeShow.less';
class QrcodeShow extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
componentDidMount() { // 挂载
}
componentWillUnmount() { // 卸载
}
download = () => {
const { previewQrcode, downloadTitle } = this.props;
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>
</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);
}
.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;
}
import React from 'react';
import { Icon, Button } from 'antd';
import Videojs from 'video.js';
import componentStyle from './VideoPlay.less';
import { imagify, ossVideofy } from '../../../utils/index';
let myVideo;
class VideoPlay extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
componentDidMount() {
const { videoList, poster } = this.props;
const options = {
playbackRates: [0.5, 1, 1.5, 2, 4, 8, 16],
poster: imagify(poster),
}; //
let curr = 0;
const source = document.getElementById('source');
if (videoList.length > 0) {
source.setAttribute('src', videoList[0]);
myVideo = Videojs('myVideo', options, (onPlayerReady) => {
myVideo.play();
// eslint-disable-next-line func-names
myVideo.on('ended', () => {
if (curr >= videoList.length) {
curr = 0;
}
myVideo.src(videoList[curr]);
myVideo.load();
curr++;
});
});
curr++;
}
}
componentWillUnmount() {
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="auto"
className="video-js"
style={{
width: '100%',
height: 330,
}}
>
<source id="source" />
</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>
......
import qs from 'qs';
import request from '../utils/request';
import api from '../common/api';
export function liveList(params) {
const data = qs.stringify(params);
return request({
url: `${api.liveClass.lives}?${data}`,
method: 'GET',
});
}
export function addLive(params) {
const data = qs.stringify(params);
return request({
url: `${api.liveClass.lives}`,
method: 'POST',
data,
});
}
export function editLive(params) {
const data = qs.stringify(params);
return request({
url: `${api.liveClass.lives}/${params.id}`,
method: 'PUT',
data,
});
}
export function liveDetail(params) {
const data = qs.stringify(params);
return request({
url: `${api.liveClass.lives}/${params.id}`,
method: 'GET',
data,
});
}
export function deleteLive(parmas) {
const data = qs.stringify(parmas);
return request({
url: `${api.liveClass.lives}/${parmas.id}`,
method: 'DELETE',
data,
});
}
export function changeStatus(params) {
const data = qs.stringify(params);
return request({
url: `${api.liveClass.livesStatus}`,
method: 'POST',
data,
});
}
export function liveUrl(params) {
const data = qs.stringify(params);
return request({
url: `${api.liveClass.livesUrl}?${data}`,
method: 'GET',
});
}
export function closeLive(params) {
const data = qs.stringify(params);
return request({
url: `${api.liveClass.livesEnd}`,
method: 'POST',
data,
});
}
......@@ -157,7 +157,6 @@ function isOnline(expiredate) {
return false;
}
function formatDate(date) {
console.log(date, 'date');
const time = Number(date);
if (time === undefined || time === '' || time <= 0) {
......
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