Commit bbd20dcd by zhangleyuan

feat:直播课创建和编辑页处理

parent 55a028ed
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
"@testing-library/jest-dom": "^4.2.4", "@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2", "@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2", "@testing-library/user-event": "^7.1.2",
"@types/ali-oss": "^6.0.5",
"@types/qs": "^6.9.5", "@types/qs": "^6.9.5",
"@types/react": "^16.9.46", "@types/react": "^16.9.46",
"@types/react-dom": "^16.9.8", "@types/react-dom": "^16.9.8",
...@@ -18,7 +19,6 @@ ...@@ -18,7 +19,6 @@
"@types/underscore": "^1.10.22", "@types/underscore": "^1.10.22",
"@typescript-eslint/eslint-plugin": "^2.10.0", "@typescript-eslint/eslint-plugin": "^2.10.0",
"@typescript-eslint/parser": "^2.10.0", "@typescript-eslint/parser": "^2.10.0",
"@types/ali-oss": "^6.0.5",
"ali-oss": "^6.12.0", "ali-oss": "^6.12.0",
"antd": "^4.8.5", "antd": "^4.8.5",
"axios": "^0.20.0", "axios": "^0.20.0",
......
.xm-show-tip { .xm-show-tip {
position: relative; position: relative;
min-height:32px; min-height:32px;
background:#FFF0E7; background:#FFF4DD;
border-radius:4px; border-radius:4px;
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
padding: 0 12px; padding: 0 12px;
span.icon { span.icon {
color:#FF8534; color:#FF9D14;
line-height: 20px; line-height: 20px;
} }
p { p {
......
@font-face { @font-face {
font-family: 'iconfont'; /* project id 2223403 */ font-family: 'iconfont'; /* project id 2223403 */
src: url('//at.alicdn.com/t/font_2223403_yeyjxe4w6a.eot'); src: url('//at.alicdn.com/t/font_2223403_uo63ciaamd.eot');
src: url('//at.alicdn.com/t/font_2223403_yeyjxe4w6a.eot?#iefix') format('embedded-opentype'), src: url('//at.alicdn.com/t/font_2223403_uo63ciaamd.eot?#iefix') format('embedded-opentype'),
url('//at.alicdn.com/t/font_2223403_yeyjxe4w6a.woff2') format('woff2'), url('//at.alicdn.com/t/font_2223403_uo63ciaamd.woff2') format('woff2'),
url('//at.alicdn.com/t/font_2223403_yeyjxe4w6a.woff') format('woff'), url('//at.alicdn.com/t/font_2223403_uo63ciaamd.woff') format('woff'),
url('//at.alicdn.com/t/font_2223403_yeyjxe4w6a.ttf') format('truetype'), url('//at.alicdn.com/t/font_2223403_uo63ciaamd.ttf') format('truetype'),
url('//at.alicdn.com/t/font_2223403_yeyjxe4w6a.svg#iconfont') format('svg'); url('//at.alicdn.com/t/font_2223403_uo63ciaamd.svg#iconfont') format('svg');
} }
.iconfont{ .iconfont{
font-family:"iconfont" !important; font-family:"iconfont" !important;
......
import React from 'react'
import { Modal, Button } from "antd";
import "./DownloadLiveModal.less"
class DownloadLiveModal extends React.Component {
constructor(props) {
super(props);
this.state = {
image: 'https://image.xiaomaiketang.com/xm/K2sJJHG3pa.png',
tip: '直播上课需要使用客户端,请先下载并安装。',
text: '安装直播客户端',
type: 'pre',
}
}
downloadLiveClient(){
if (type === 'pre') {
const isMac = /macintosh|mac os x/i.test(navigator.userAgent);
if(isMac){
Modal.info({
title: "抱歉,暂不支持Mac版",
content: "Mac版正在开发中,敬请期待",
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>,
okText: '我知道了'
});
return;
}
url && window.open(url);
this.setState({
image: 'https://image.xiaomaiketang.com/xm/wPwRdaa7MM.png',
tip: '安装完成后,再次打开即可开始直播。',
text: '我知道了',
type: 'finish',
})
} else {
this.props.onCancel();
}
}
render() {
const { url } = this.props;
const { image, tip, text, type } = this.state;
return <Modal
visible={true}
title="下载客户端"
className="download-live-modal"
footer={null}
onCancel={() => {
this.props.onCancel();
}}
>
<img className="download-image" src={image} alt="" />
<p className="download-tip">{tip}</p>
<Button
type="primary"
className="download-button"
onClick={() => {
}}
>{text}</Button>
</Modal>
}
}
export default DownloadLiveModal;
\ No newline at end of file
.download-live-modal {
.ant-modal-body {
padding: 20px 24px 48px !important;
.download-image {
display: block;
width: 80px;
margin: 0 auto 8px;
}
.download-tip {
color: #666;
text-align: center;
margin-bottom: 32px;
}
.download-button {
display: block;
margin: 0 auto;
}
}
}
\ No newline at end of file
...@@ -177,15 +177,15 @@ class ImgCutModalNew extends React.Component { ...@@ -177,15 +177,15 @@ class ImgCutModalNew extends React.Component {
} }
} }
// ImgCutModalNew.propTypes = { ImgCutModalNew.propTypes = {
// visible: PropTypes.bool, visible: PropTypes.bool,
// needReUpload: PropTypes.bool, // 是否需要重新上传 needReUpload: PropTypes.bool, // 是否需要重新上传
// title: PropTypes.string, title: PropTypes.string,
// width: PropTypes.number, width: PropTypes.number,
// cutWidth: PropTypes.number, cutWidth: PropTypes.number,
// cutHeight: PropTypes.number, cutHeight: PropTypes.number,
// imageFile: PropTypes.File // imageFile: PropTypes.File
// }; };
ImgCutModalNew.defaultProps = { ImgCutModalNew.defaultProps = {
width: 550, width: 550,
cutWidth: 502, cutWidth: 502,
......
/**
* 多选日历
* Created by Gentean
* Mail: 4083189@qq.com
* Date: 2016/12/30
* Time: 下午2:32
*/
import React from 'react'
import { message } from "antd";
import moment from 'moment';
require("./MultipleDatePicker.less");
class MultipleDatePicker extends React.Component {
constructor(props) {
super(props);
this.state = {
calendar: "",
calendarDate: props.type ? moment(props.startTime):moment(),
detailList: [],
waitNoticeNumber: 0,
totalCount: 0,
selectDateList: props.selectDateList || [],
endTime: props.endTime || null,
startTime: props.startTime || null,
homeworkProcessEnum: props.homeworkProcessEnum || ''
};
}
componentWillReceiveProps(nextProps) {
this.setState({endTime : nextProps.endTime, startTime: nextProps.startTime, selectDateList: nextProps.selectDateList, homeworkProcessEnum:nextProps.homeworkProcessEnum},() => {
this.handleQuery();
});
}
componentDidMount() {
this.handleQuery();
}
handleQuery() {
var self = this;
self.setState({
calendar: self.renderCalendar(),
});
}
renderCalendar() {
var start = moment(this.state.calendarDate).startOf("month"),
startDay = start.dates(),
// 每月的第一天是星期几 [0-6] 6:日
startWeekOf = start.weekday();
var end = moment(this.state.calendarDate).endOf("month"),
endDay = end.dates(),
endWeekOf = end.weekday();
var dateElms = [];
// 上月余留的天
var prevMonthDays = moment(start).subtract("month", 1).endOf("month"),
prevMonthDaysNumber = prevMonthDays.dates();
for (
var j = prevMonthDaysNumber - startWeekOf + 1, i = 0;
i < startWeekOf;
i++, j++
) {
var time = moment(prevMonthDays).subtract("days", startWeekOf - 1 - i);
dateElms.push(
<li className={"disabled"} key={"before" + i}>
<span>{j}</span>
</li>
);
}
// 本月
for (var i = startDay; i <= endDay; i++) {
var time = moment(start).add("days", i - 1);
var className = "";
if(!this.props.canSelectTodayBefore && time.valueOf() < moment().valueOf() && time.format("YYYY-MM-DD") != moment().format("YYYY-MM-DD")) {
className = 'before-disabled'
}
// 今日待跟进
if (time.format("YYYY-MM-DD") == moment().format("YYYY-MM-DD")) {
className += " today";
}
if (this.state.selectDateList.indexOf(time.valueOf()) > -1) {
className += " active";
const today = moment().startOf('day').valueOf();
if(this.props.type && this.props.type == 'CALENDAR_CLOCK' && (time.valueOf() < today) && this.state.homeworkProcessEnum == 'ONGOING') {
className += " past";
}
}
if(this.state.startTime && this.state.endTime && (time.valueOf() > this.state.endTime.valueOf() || time.valueOf() < this.state.startTime.valueOf())) {
className += " disabled"
}
dateElms.push(
<li
className={className}
key={"curr" + i}
onClick={this.handleShowDetail.bind(this, time, className)}
>
<span>{i}</span>
</li>
);
}
// 下月预来的天
for (var j = 1, i = endWeekOf; i < 6; i++, j++) {
var time = moment(end).add("days", i);
dateElms.push(
<li className={"disabled"} key={"after" + i}>
<span>{j}</span>
</li>
);
}
return dateElms;
}
handleShowDetail(time, className) {
if(!this.props.canSelectTodayBefore && className === 'before-disabled') {
return
}
let date = time.valueOf();
const today = moment().startOf('day').valueOf();
if(this.props.type && this.props.type == 'CALENDAR_CLOCK' && (date < today)) {
return;
}
if(this.state.homeworkProcessEnum == 'ONGOING' && date == today) {
return;
}
if(this.props.type && this.props.type == 'CALENDAR_CLOCK' && this.state.startTime && this.state.endTime && (date > this.state.endTime.valueOf() || date < this.state.startTime.valueOf())) {
return;
}
let tempArr = this.state.selectDateList;
if (tempArr.indexOf(date) > -1) {
let index = tempArr.indexOf(date);
tempArr.splice(index, 1);
} else {
if (tempArr.length > 29 && !this.props.type) {
message.warning("最多选择30天");
return;
} else {
tempArr.push(date);
}
}
this.props.onSelect(tempArr);
this.setState(
{
selectDateList: tempArr,
},
() => {
this.handleQuery();
}
);
}
render() {
const self = this;
const {calendarDate, endTime,startTime } = this.state;
const { type} = this.props;
const prevMonth = startTime && calendarDate.subtract("month", 1).endOf('month').valueOf() < startTime.valueOf();
const nextMonth = !(endTime && calendarDate.add("month", 1).valueOf() < endTime.valueOf());
return (
<div
className={`multiple-calendar ${
type == "CALENDAR_CLOCK" ? "punch-calender" : ""
}`}
>
{type == "CALENDAR_CLOCK" ? (
<div className="punch-control">
<div className="punch-main">
<div
onClick={function () {
if(prevMonth){return}
this.state.calendarDate = this.state.calendarDate.subtract(
"month",
1
);
self.handleQuery();
}.bind(this)}
className={`prev-icon ${prevMonth?'disbled-icon':''}`}
>
<span className="icon iconfont">&#xe65f;</span>
</div>
<span className="month">{this.state.calendarDate.format("YYYY年MM月")}</span>
<div
className={`next-icon ${nextMonth?'disbled-icon':''}`}
onClick={function () {
if(nextMonth){return}
this.state.calendarDate = this.state.calendarDate.add(
"month",
1
);
self.handleQuery();
}.bind(this)}
>
<span className="icon iconfont">&#xe65e;</span>
</div>
</div>
<div
className="self"
onClick={function () {
this.state.calendarDate = moment(startTime);
self.handleQuery();
}.bind(this)}
>
回到起始月
</div>
</div>
) : (
<div className="t-control">
<div
className="prev"
onClick={function () {
this.state.calendarDate = this.state.calendarDate.subtract(
"month",
1
);
self.handleQuery();
}.bind(this)}
>
上月
</div>
<div className="loc">
{this.state.calendarDate.format("YYYY年MM月")}
</div>
<div
className="self"
onClick={function () {
this.state.calendarDate = moment();
self.handleQuery();
}.bind(this)}
>
本月
</div>
<div
className="next"
onClick={function () {
this.state.calendarDate = this.state.calendarDate.add('month', 1);
self.handleQuery()
}.bind(this)}
>
下月
</div>
</div>
)}
<ul className="week">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<ul className="calendar" id="multiCalendar">
{this.state.calendar}
</ul>
</div>
);
}
}
MultipleDatePicker.propTypes = {};
MultipleDatePicker.defaultProps = {
reEditUrl: "",
close: function () {},
canSelectTodayBefore: true // 支持选择今天之前的日期
};
export default MultipleDatePicker;
@import '@/core/variables.less';
.multiple-calendar {
width: 295px;
border: 1px solid #e8e8e8;
border-radius: 4px;
ul {
list-style: none;
}
.t-control {
display: flex;
> div {
padding: 2px 0;
text-align: center;
cursor: pointer;
&:hover {
background: #ececec;
}
}
.loc {
flex: 1;
cursor: default;
&:hover {
background: #FFFFFF;
border-radius: 4px;
}
}
.self {
width: 50px;
}
.prev, .next {
width: 50px;
}
}
.week {
font-size: 12px;
li {
display: inline-block;
width: 41px;
text-align: center;
cursor: pointer;
}
}
.calendar {
padding-bottom: 10px;
li {
display: inline-block;
width: 31px;
margin: 0 5px;
text-align: center;
height: 30px;
line-height: 30px;
cursor: pointer;
vertical-align: top;
&:hover {
background: #e8e8e8;
}
&.before-disabled {
color: #e8e8e8;
cursor: default;
&:hover {
background: none!important;
span{
color: #e8e8e8!important;
}
}
}
&.disabled{
color: #e8e8e8;
cursor: default;
&:hover {
background: none!important;
span{
color: #e8e8e8!important;
}
}
}
&.active {
background: @xm-color-primary;
color: #fff;
border-radius: 4px;
}
&.today {
border: 1px solid @xm-color-primary;
border-radius: 5px;
}
}
}
&.punch-calender {
width: 400px;
margin-top: 12px;
.punch-control {
border-bottom: 1px solid rgba(0,0,0,0.06);
position: relative;
.punch-main {
margin: 0 133px;
display: flex;
justify-content: space-between;
align-items: center;
.prev-icon,
.next-icon {
cursor: pointer;
}
.month {
color: #333333;
}
.icon {
color: rgba(0,0,0,0.45);
}
.disbled-icon {
cursor: not-allowed;
.icon {
color: #e8e8e8;
}
}
}
.self {
position: absolute;
right: 8px;
top: 0;
color: #FF7519;
cursor: pointer;
}
}
.week {
li {
width: 56px;
}
}
.calendar li {
width: 56px;
margin: 0 !important;
span {
width: 30px;
height: 30px;
}
&:hover {
background: transparent;
span {
background: transparent;
color: #FF7519;
}
}
&.active {
background: transparent;
color: #fff;
border-radius: none;
span {
background: @xm-color-primary;
border-radius: 4px;
}
&:hover {
span {
color: #fff;
}
}
}
&.today {
border: none;
border-radius: none;
span {
border: 1px solid @xm-color-primary;
border-radius: 5px;
}
}
&.past {
span {
background:rgba(255,133,52,0.1);
border-radius: 4px;
color:rgba(0,0,0,0.25);
}
}
}
}
}
import React from 'react' import React from 'react'
import './ShowTips.less' import './ShowTips.less'
import {InfoCircleOutlined} from '@ant-design/icons';
function ShowTips(props) { function ShowTips(props) {
return ( return (
<div className={`xm-show-tip xm-type-${props.type || 'defulat'}`} > <div className={`xm-show-tip xm-type-${props.type || 'defulat'}`} >
<span className="icon iconfont">&#xe6f2;</span> <InfoCircleOutlined className="icon"/>
<p>{props.message}</p> <p>{props.message}</p>
</div> </div>
) )
......
.xm-show-tip { .xm-show-tip {
position: relative; position: relative;
min-height:32px; min-height:32px;
background:#FFF0E7; background:#FFF4DD;
border-radius:4px; border-radius:4px;
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
padding: 0 12px; padding: 0 12px;
span.icon { .icon {
color:#FF8534; color:#FF9D14;
line-height: 20px; line-height: 24px;
height: 20px;
} }
p { p {
color:#666666; color:#666666;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-08-24 12:20:57 * @Date: 2020-08-24 12:20:57
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-11 17:44:15 * @LastEditTime: 2020-12-12 16:55:50
* @Description: * @Description:
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
--> -->
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
--> -->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_yeyjxe4w6a.css"> <link rel="stylesheet" href="//at.alicdn.com/t/font_2223403_uo63ciaamd.css">
<!-- <!--
Notice the use of %PUBLIC_URL% in the tags above. Notice the use of %PUBLIC_URL% in the tags above.
......
...@@ -79,7 +79,29 @@ class AddLive extends React.Component { ...@@ -79,7 +79,29 @@ class AddLive extends React.Component {
addLiveBasicInfo: { addLiveBasicInfo: {
courseName: null, // 课程名称 courseName: null, // 课程名称
coverId: null, coverId: null,
coverUrl: defaultCover coverUrl: defaultCover,
courseCatalogOption:[
{
value: 'zhejiang',
label: 'Zhejiang',
children: [
{
value: 'hangzhou',
label: 'Hangzhou',
},
],
},
{
value: 'jiangsu',
label: 'Jiangsu',
children: [
{
value: 'nanjing',
label: 'Nanjing',
}
],
},
]
}, },
// 直播课上课信息 // 直播课上课信息
...@@ -632,13 +654,10 @@ class AddLive extends React.Component { ...@@ -632,13 +654,10 @@ class AddLive extends React.Component {
navList={type == "add" ? "新建直播课" : "编辑直播课"} navList={type == "add" ? "新建直播课" : "编辑直播课"}
goBack={this.handleGoBack} goBack={this.handleGoBack}
/> />
<div className="box"> <div className="box">
<div className="show-tips"> <div className="show-tips">
<ShowTips message="请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦助教保有依据国家规定及平台规则进行处理的权利" /> <ShowTips message="请遵守国家相关规定,切勿上传低俗色情、暴力恐怖、谣言诈骗、侵权盗版等相关内容,小麦助教保有依据国家规定及平台规则进行处理的权利" />
</div> </div>
<div className="add-live-page__form"> <div className="add-live-page__form">
<div className="basic-info__wrap"> <div className="basic-info__wrap">
<div className="title">基本信息</div> <div className="title">基本信息</div>
......
.add-live-page { .add-live-page {
.box { .box {
margin-bottom: 66px; margin-bottom: 66px !important;
} }
.add-live-page__form { .add-live-page__form {
margin-top: 16px; margin-top: 16px;
...@@ -13,7 +12,7 @@ ...@@ -13,7 +12,7 @@
line-height: 22px; line-height: 22px;
} }
.add-live__class-info { .add-live__class-info {
margin-left: 24px; margin-left: 14px;
.student { .student {
margin-bottom: 16px; margin-bottom: 16px;
} }
......
...@@ -21,7 +21,7 @@ class LiveCoursePage extends React.Component { ...@@ -21,7 +21,7 @@ class LiveCoursePage extends React.Component {
} }
} }
componentWillMount() { componentWillMount() {
this.handleFetchLiveList(); this.handleFetchLiveList(this.state.query);
} }
// // 获取直播课列表 // // 获取直播课列表
// handleFetchLiveList = (_query) => { // handleFetchLiveList = (_query) => {
...@@ -47,7 +47,7 @@ class LiveCoursePage extends React.Component { ...@@ -47,7 +47,7 @@ class LiveCoursePage extends React.Component {
// this.setState({ loading: false }); // this.setState({ loading: false });
// }); // });
// } // }
handleFetchLiveList() { handleFetchLiveList= (_query) => {
const _courseList=[ const _courseList=[
{ {
applyMode: "ANYONE", applyMode: "ANYONE",
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
*/ */
import React from 'react'; import React from 'react';
import { Input, Button, message } from 'antd'; import { Input, Button, message ,Cascader } from 'antd';
import UploadOss from "@/core/upload"; import UploadOss from "@/core/upload";
import { ImgCutModalNew } from '@/components'; import { ImgCutModalNew } from '@/components';
...@@ -55,10 +55,8 @@ class AddLiveBasic extends React.Component { ...@@ -55,10 +55,8 @@ class AddLiveBasic extends React.Component {
render() { render() {
const { showCutModal, imageFile } = this.state; const { showCutModal, imageFile } = this.state;
const { data, liveScene } = this.props; const { data, liveScene } = this.props;
const { courseName, coverUrl } = data; const { courseName, coverUrl , courseCatalogOption} = data;
const fileName = ''; const fileName = '';
// 是否是互动班课,互动班课不显示封面图
const isInteractive = liveScene === 'interactive';
// 当前是否使用的是默认图片 // 当前是否使用的是默认图片
const isDefaultCover = coverUrl === defaultCover; const isDefaultCover = coverUrl === defaultCover;
...@@ -75,9 +73,6 @@ class AddLiveBasic extends React.Component { ...@@ -75,9 +73,6 @@ class AddLiveBasic extends React.Component {
onChange={(e) => { this.props.onChange('courseName', e.target.value)}} onChange={(e) => { this.props.onChange('courseName', e.target.value)}}
/> />
</div> </div>
{
!isInteractive &&
<div className="course-cover"> <div className="course-cover">
<span className="label">封面图:</span> <span className="label">封面图:</span>
...@@ -111,10 +106,12 @@ class AddLiveBasic extends React.Component { ...@@ -111,10 +106,12 @@ class AddLiveBasic extends React.Component {
>使用默认图</span> >使用默认图</span>
<div className="tips">建议尺寸690*398像素,图片支持jpg、jpeg、png格式。</div> <div className="tips">建议尺寸690*398像素,图片支持jpg、jpeg、png格式。</div>
</div> </div>
</div> </div>
</div> </div>
} <div className="course-catalog">
<span className="label"><span className="require">*</span>课程分类:</span>
<Cascader options={courseCatalogOption} style={{ width: 240 }} placeholder="请选择课程分类" />
</div>
<ImgCutModalNew <ImgCutModalNew
title="裁剪" title="裁剪"
width={550} width={550}
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
.label { .label {
width: 100px; width: 100px;
text-align: right; text-align: right;
display:inline-block;
.require { .require {
color: #EC4B35; color: #EC4B35;
} }
...@@ -69,6 +69,9 @@ ...@@ -69,6 +69,9 @@
color: #999; color: #999;
} }
} }
.course-catalog{
margin:20px 0 0 14px;
}
} }
#imgCutModalNew { #imgCutModalNew {
......
...@@ -7,31 +7,23 @@ ...@@ -7,31 +7,23 @@
*/ */
import React from 'react'; import React from 'react';
import { import {TimePicker, Select, Spin, Tooltip } from 'antd';
Radio, Slider, Row, Input, InputNumber, import {InfoCircleFilled} from '@ant-design/icons';
DatePicker, TimePicker, Select, Button,
message, Spin, Tooltip
} from 'antd';
// import TeacherSelectV5 from "@/modules/classManage_V5/classDetail/TeacherSelectV5"; // import TeacherSelectV5 from "@/modules/classManage_V5/classDetail/TeacherSelectV5";
import ChargeExplainModal from '../modal/ChargeExplainModal'; import ChargeExplainModal from '../modal/ChargeExplainModal';
import SelectStudent from '../modal/select-student/index'; import SelectStudent from '../modal/select-student/index';
// import MultipleDatePicker from '@/modules/class/MultipleDatePicker'; import MultipleDatePicker from '@/components/MultipleDatePicker';
import moment from 'moment'; import moment from 'moment';
import './AddLiveClass.less'; import './AddLiveClass.less';
const defaultQuery = { const defaultQuery = {
// instId,
size: 10, size: 10,
current: 1, current: 1,
adminName: null
} }
// const { instId } = window.currentUserInstInfo;
class AddLiveClass extends React.Component { class AddLiveClass extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
...@@ -46,37 +38,8 @@ class AddLiveClass extends React.Component { ...@@ -46,37 +38,8 @@ class AddLiveClass extends React.Component {
} }
componentWillMount() { componentWillMount() {
const { liveScene } = this.props;
// 如果是互动班课,则请求用户是否是旗舰版
if (liveScene === 'interactive') {
this.handleFetchPermission();
}
this.getAssistantList(); this.getAssistantList();
} }
componentWillReceiveProps(nextProps) {
if(nextProps.data.assistant.sort().toString() !== this.props.data.assistant.sort().toString()) {
// 获取助教老师列表
this.getAssistantList(1, nextProps.data.assistant);
}
}
// 获取用户是否是旗舰版的权限
handleFetchPermission = () => {
// const { instId } = window.currentUserInstInfo;
this.setState({ loading: true });
axios.Business('public/inst/checkInstProduct', {
// instId: instId || LS.get("instId"),
productCodeList: ['ULTIMATESELL', 'PIP_TO_ULTIMATE', 'HIGH_TO_ULTIMATE']
}).then((res) => {
const { result } = res;
this.setState({
loading: false,
isUltimateEdition: result,
// 旗舰版用户没有大班直播模式,所以默认是大班互动模式
addLiveType: result ? 'LARGE_CLASS_INTERACTION' : 'LARGE_CLASS_LIVE'
})
});
}
// 获取助教老师列表 // 获取助教老师列表
getAssistantList = (current = 1, selectList) => { getAssistantList = (current = 1, selectList) => {
// const { query, assistantList } = this.state; // const { query, assistantList } = this.state;
...@@ -106,8 +69,6 @@ class AddLiveClass extends React.Component { ...@@ -106,8 +69,6 @@ class AddLiveClass extends React.Component {
// assistantList: list, // assistantList: list,
// _assistantList: _assistantList // _assistantList: _assistantList
// }) // })
// }); // });
} }
...@@ -119,19 +80,7 @@ class AddLiveClass extends React.Component { ...@@ -119,19 +80,7 @@ class AddLiveClass extends React.Component {
this.props.onChange('liveType', e.target.value); this.props.onChange('liveType', e.target.value);
}; };
//查看计费说明
handleLookExplain = () => {
const explainModal = (
<ChargeExplainModal
close={() => {
this.setState({
explainModal: null,
});
}}
/>
);
this.setState({ explainModal });
};
// 滑动加载更多 // 滑动加载更多
handleScroll = (e) => { handleScroll = (e) => {
...@@ -145,101 +94,6 @@ class AddLiveClass extends React.Component { ...@@ -145,101 +94,6 @@ class AddLiveClass extends React.Component {
} }
} }
// 选择学员数量
handleShowSelectStuModal = (studentType) => {
const {
after,
liveScene,
data: {
id,
studentList,
consumeStudentList,
excludeStudentIds,
excludeConsumeStudentIds,
}
} = this.props;
const { savedSelectedRows } = this.state;
const studentModal = (
<SelectStudent
savedSelectedRows={savedSelectedRows}
studentType={studentType}
liveScene={liveScene}
after={after} //表明是不是上课后的状态
excludeStudentIds={excludeStudentIds}
excludeConsumeStudentIds={excludeConsumeStudentIds}
studentList={studentList}
consumeStudentList={consumeStudentList}
close={() => {
this.setState({
studentModal: null,
});
}}
onSelect={(studentIds, selectedStudents, savedSelectedRows) => {
this.setState({ savedSelectedRows })
this.handleSelectStudent(studentIds, selectedStudents, studentType)
}}
/>
)
this.setState({ studentModal });
}
handleSelectStudent = (studentIds, selectedStudents = [], studentType) => {
let studentList = [];
if (studentType === 'DEDUCTION') {
studentList = selectedStudents
} else {
_.each(studentIds, (item) => {
studentList.push({ studentId: item });
});
}
const {
liveScene,
liveType,
endTime,
startTime,
id,
podium,
excludeStudentIds,
excludeConsumeStudentIds
} = this.props.data;
const { addLiveType } = this.state;
// 当前选择的学员
const currentSelectStuIds = studentType === 'DEDUCTION' ? _.pluck(selectedStudents, 'studentId') : studentIds;
// 如果当前选择的是扣课时学员,那么总的已选学员人数 = 扣课时 + 之前选择不扣课时的
// 如果当前选择的是不扣课时学员,那么总的已选学员人数 = 不扣课时 + 之前选择的扣课时的
const prevSelectStutIds = studentType === 'DEDUCTION' ? excludeStudentIds : excludeConsumeStudentIds;
const studentLen = [...currentSelectStuIds, ...prevSelectStutIds].length;
// 如果是互动班课,模式为大班直播,学员人数超过1000人,提示最多选择1000人
// 如果是大班直播(大班直播没有模式,只要考虑学员人数是否超过了1000个人即可)
if ((liveScene === 'interactive' &&
addLiveType !== "SMALL_CLASS_INTERACTION" &&
studentLen > 1000) || (studentLen > 1000)
) {
message.info(`最多选择1000人`);
return;
// 如果是互动班课,模式为大班互动,学员人数超过课上台人数,提示最多选择上台人数
} else if (liveScene === 'interactive' &&
addLiveType === "SMALL_CLASS_INTERACTION" &&
studentLen > podium
) {
message.info(`最多选择${podium}人`);
return;
}
this.setState({ studentModal: null });
if (studentType === 'DEDUCTION') {
this.props.onChange('consumeStudentList', studentList);
} else {
this.props.onChange('studentList', studentList);
}
}
disabledDate = (current) => { disabledDate = (current) => {
return current.valueOf() < moment().subtract(1, "days") return current.valueOf() < moment().subtract(1, "days")
}; };
...@@ -252,33 +106,19 @@ class AddLiveClass extends React.Component { ...@@ -252,33 +106,19 @@ class AddLiveClass extends React.Component {
render() { render() {
const { const {
loading, loading,
assistantList,
addLiveType,
isUltimateEdition,
query,
_assistantList
} = this.state; } = this.state;
// pageType: 页面类型:add->新建、edit->编辑 // pageType: 页面类型:add->新建、edit->编辑
// liveScene: 直播场景: interactive -> 互动班课 large -> 大班直播 // liveScene: 直播场景: interactive -> 互动班课 large -> 大班直播
// data:表单数据 // data:表单数据
// selectedAssistant: 已经选择的助教 // selectedAssistant: 已经选择的助教
const { pageType, liveScene, data, selectedAssistant, isXiaomai, isEdit, after } = this.props; const { pageType, liveScene, data, selectedAssistant, isXiaomai, isEdit, after } = this.props;
const { const {
podium,
endTime, endTime,
liveType,
liveDate,
assistant,
startTime, startTime,
teacherId,
studentList, studentList,
teacherName,
timeHorizonEnd,
consumeHourNum,
consumeClassTime,
timeHorizonStart,
consumeStudentList, consumeStudentList,
applyMode,
calendarTime calendarTime
} = data; } = data;
// 已选择的上课学员数量(不扣课时) // 已选择的上课学员数量(不扣课时)
...@@ -290,128 +130,6 @@ class AddLiveClass extends React.Component { ...@@ -290,128 +130,6 @@ class AddLiveClass extends React.Component {
return ( return (
<Spin spinning={loading}> <Spin spinning={loading}>
<div className="add-live__class-info"> <div className="add-live__class-info">
{
liveScene === 'interactive' &&
<div className="live-mode">
<span className="label">直播模式:</span>
{
pageType === 'add' ?
<Radio.Group
className="uncommon-wrapper"
onChange={this.handleChangeLiveType}
value={addLiveType}
>
{
// 旗舰版不显示大班互动
!isUltimateEdition &&
<Radio
value={"LARGE_CLASS_LIVE"}
>
<p className="title">
{ window.ENUM.liveType["LARGE_CLASS_LIVE"].name }
</p>
<p className="info">
{ window.ENUM.liveType["LARGE_CLASS_LIVE"].info }
</p>
</Radio>
}
<Radio
value={"LARGE_CLASS_INTERACTION"}
>
<p className="title">
{ window.ENUM.liveType["LARGE_CLASS_INTERACTION"].name }
</p>
<p className="info">
{ window.ENUM.liveType["LARGE_CLASS_INTERACTION"].info }
</p>
</Radio>
<Radio
value={"SMALL_CLASS_INTERACTION"}
>
<p className="title">
{ window.ENUM.liveType["SMALL_CLASS_INTERACTION"].name }
</p>
<p className="info">
{ window.ENUM.liveType["SMALL_CLASS_INTERACTION"].info }
</p>
</Radio>
</Radio.Group> :
<div className="edit-info">
<p className="name">
{window.ENUM.liveType[liveType].name}
</p>
<p className="info">
{window.ENUM.liveType[liveType].info}
</p>
</div>
}
</div>
}
{
liveScene === 'interactive' &&
addLiveType !== "LARGE_CLASS_LIVE" &&
pageType === 'add' &&
<div className="stage-num">
<div className="content">
<span className="label">上台人数:</span>
<Row type="flex">
<Slider
min={1}
max={12}
style={{ width: 160 }}
className="add-live-slider"
onChange={(value) => {
this.props.onChange('podium', Number(value));
}}
value={typeof podium === "number" ? podium : 1}
/>
<Input
style={{ margin: "0 16px", width: 90 }}
value={podium}
onChange={(e) => {
const { value } = e.target;
this.props.onChange('podium', parseInt(value));
}}
onBlur={(e) => {
let value = e.target.value;
if (value < 1) {
value = 1;
} else if (value > 12) {
value = 12;
}
value = value ? parseInt(value) : value;
this.props.onChange('podium', value);
}}
/>
</Row>
</div>
<div className="tips">
请按需选择同时上台的最多人数,人数越多价格越贵,设置后不可修改。
<span
className="look-explain"
onClick={this.handleLookExplain}
>
查看计费规则
</span>
</div>
</div>
}
{
liveScene === 'interactive' &&
addLiveType !== "LARGE_CLASS_LIVE" &&
pageType === "edit" &&
<div className="podium-max-num">
<span className="label">上台人数:</span>
<span>最多可同时上台{podium}</span>
</div>
}
{
window.NewVersion && pageType === 'add' &&
<div className="course"> <div className="course">
<div className="day"> <div className="day">
<span className="label"> <span className="label">
...@@ -420,23 +138,23 @@ class AddLiveClass extends React.Component { ...@@ -420,23 +138,23 @@ class AddLiveClass extends React.Component {
<Tooltip <Tooltip
overlayStyle={{maxWidth: 300, zIndex: '9999'}} overlayStyle={{maxWidth: 300, zIndex: '9999'}}
title={<div style={{width: '266px'}}>支持按上课日期批量创建直播课,创建后按“课程名称_日期”命名,例如:<br/>张三的语文课_9月18日<br/>张三的语文课_9月19日......</div>}> title={<div style={{width: '266px'}}>支持按上课日期批量创建直播课,创建后按“课程名称_日期”命名,例如:<br/>张三的语文课_9月18日<br/>张三的语文课_9月19日......</div>}>
<span className="iconfont">&#xe6f2;</span> <InfoCircleFilled className="tip-icon"/>
</Tooltip> </Tooltip>
</span> </span>
<div> <div>
<div className='select-day'> <div className='select-day'>
已选 已选
<span class="mark-day"> <span className="mark-day">
{isLongArr(calendarTime) {isLongArr(calendarTime)
? calendarTime.length : 0 ? calendarTime.length : 0
} }
</span> </span>
</div> </div>
{/* <MultipleDatePicker <MultipleDatePicker
selectDateList={calendarTime} selectDateList={calendarTime}
onSelect={this.selectMultiDate} onSelect={this.selectMultiDate}
canSelectTodayBefore={false} canSelectTodayBefore={false}
/> */} />
</div> </div>
</div> </div>
...@@ -463,224 +181,31 @@ class AddLiveClass extends React.Component { ...@@ -463,224 +181,31 @@ class AddLiveClass extends React.Component {
/> />
</div> </div>
</div> </div>
}
{
(window.NewVersion && pageType !== 'add' || !window.NewVersion) &&
<div className="time" id="time">
<div className="content">
<span className="label"><span className="require">*</span>上课时间:</span>
<DatePicker
disabled={liveScene === 'large' && !isEdit}
format="YYYY-MM-DD"
value={liveDate ? moment(Number(liveDate)) : null}
style={{ width: 160, minWidth: 130, marginRight: 10 }}
placeholder="上课日期"
getCalendarContainer={() =>
document.getElementById("time")
}
disabledDate={this.disabledDate}
onChange={(date) => { this.props.onChange('liveDate', date) }}
/>
<TimePicker
disabled={liveScene === 'large' && !isEdit}
format="HH:mm"
value={timeHorizonStart ? moment(Number(timeHorizonStart)) : null}
defaultOpenValue={moment(new Date().setHours(0,0,0,0))}
placeholder="开始时间"
style={{ width: 100, minWidth: 100, marginRight: 10 }}
getPopupContainer={() =>
document.getElementById("time")
}
onChange={(time) => { this.props.onChange('timeHorizonStart', time) }}
/>
<TimePicker
disabled={liveScene === 'large' && !isEdit}
format="HH:mm"
value={timeHorizonEnd ? moment(Number(timeHorizonEnd)) : null}
defaultOpenValue={moment(new Date().setHours(0,0,0,0))}
placeholder="结束时间"
style={{ width: 100, minWidth: 100 }}
getPopupContainer={() =>
document.getElementById("time")
}
onChange={(time) => { this.props.onChange('timeHorizonEnd', time) }}
/>
</div>
</div>
}
{
liveScene === 'interactive' &&
<div className="tips">
上课老师可以在 直播时 主动结束直播
</div>
}
<div className="teacher"> <div className="teacher">
<span className="label"><span className="require">* </span>上课老师:</span> <span className="label"><span className="require">* </span>讲师:</span>
{/* <TeacherSelectV5 <Select
disabled={liveScene === 'large' && !isEdit} placeholder="请选择讲师"
ref="TeacherSelect"
showSearch={true}
allowClear={true}
onSelect={(teacherId, dataSet) => { this.props.onChange('teacherId', teacherId, dataSet) }}
placeholder="请选择上课老师"
defaultValue={teacherId}
style={{ width: 240, marginTop: 6 }} style={{ width: 240, marginTop: 6 }}
/> */} filterOption={(input, option) => option}
</div> onSearch={(value) => {
{ }}
isXiaomai && onBlur={() => {
}}
></Select>
</div>
<div className="assistant-teacher"> <div className="assistant-teacher">
<span className="label">助教老师</span> <span className="label">助教</span>
<Select <Select
id="assistant" id="assistant"
disabled={liveScene === 'large' && !isEdit}
mode="multiple" mode="multiple"
value={assistant}
placeholder="请选择助教老师" placeholder="请选择助教老师"
style={{ width: 240, marginTop: 6 }} style={{ width: 240, marginTop: 6 }}
filterOption={(input, option) => option} filterOption={(input, option) => option}
onPopupScroll={this.handleScroll}
onChange={(value) => {
this.props.onChange('assistant', value)
}}
onSearch={(value) => {
query.adminName = value
this.setState({
query
}, () => {
this.getAssistantList()
})
}}
onBlur={() => {
query.adminName = ''
this.setState({
query
}, () => {
this.getAssistantList()
})
}}
> >
{_.map(_assistantList, (item, index) => {
return (
<Select.Option value={item.id} key={item.id}>{item.adminName}</Select.Option>
);
})}
</Select> </Select>
</div> </div>
}
{
liveScene === 'large' &&
<div className="watch-setting">
<span className="label"><span className="require">* </span>分享设置:</span>
<div className="content">
<Radio.Group
onChange={(e) => this.props.onChange('applyMode', e.target.value)}
value={applyMode}
>
<Radio value={'ANYONE'}>
<div className="radio-item">
<div className="text mr16">允许任何学员通过直播课链接加入学习</div>
<div className="sub-text">加入后,在读学员可通过家长端、“每课学堂”app、直播课网页端、直播课链接观看,非在读学员仅可通过直播课链接观看</div>
</div>
</Radio>
<Radio value={'ONLY_READ'}>
<div className="radio-item">
<div className="text mr16">仅在读学员可通过直播课链接加入学习</div>
<div className="sub-text">加入后,在读学员可通过家长端、“每课学堂”app、直播课网页端、直播课链接观看</div>
</div>
</Radio>
<Radio value={'ASSIGN'}>
<div className="radio-item mb0">
<div className="text mr16">仅指定学员可通过直播课链接加入学习</div>
<div className="sub-text">加入后,在读学员可通过家长端、“每课学堂”app、直播课网页端、直播课链接观看</div>
</div>
</Radio>
</Radio.Group>
</div>
</div>
}
{
window.NewVersion && isXiaomai ?
<div className="class-student">
<span className="label">上课学员:</span>
<div className="class-student-content">
<div className="deduction-student">
<span className="label">扣课时学员:</span>
<div className="content">
<div className="has-selected">
已选择 <span style={{ color: "#FF8534" }}>{hasSelectedDeductionStu}</span>名学员
<Button onClick={() => this.handleShowSelectStuModal('DEDUCTION')}>选择学员</Button>
</div>
</div>
</div>
<div className="deduction-student-tips">
学员“到课”后,系统自动扣
<InputNumber
disabled={liveScene === 'large' && !isEdit}
min={0.1}
max={10}
precision={1}
value={consumeHourNum}
onChange={(value) => {
this.props.onChange('consumeHourNum', value)
}}
onBlur={(e) => {
this.props.onChange('consumeHourNum', e.target.value || 1)
}}
/>课时
</div>
<div className="no-deduction-student">
<span className="label">不扣课时学员:</span>
<div className="content">
<div className="has-selected">
已选择 <span style={{ color: "#FF8534" }}>{hasSelectedStu}</span>名学员
</div>
<Button onClick={this.handleShowSelectStuModal}>选择学员</Button>
</div>
</div>
</div>
</div> :
<div className="student">
<span className="label">上课学员:</span>
<div className="content">
<div className="has-selected">
已选择 <span style={{ color: "#FF8534" }}>{hasSelectedStu}</span>名学员
</div>
<Button onClick={this.handleShowSelectStuModal}>选择学员</Button>
</div>
</div>
}
{
isXiaomai &&
<div className="arrive-rule">
<span className="label"><span className="require">* </span>到课规则:</span>
学员累计在线时长达到
<InputNumber
className="arrive-rule-input"
disabled={liveScene === 'large' && !isEdit}
min={0}
max={999}
precision={0}
value={consumeClassTime}
onChange={(value) => {
this.props.onChange('consumeClassTime', value)
}}
onBlur={(e) => {
this.props.onChange('consumeClassTime', e.target.value || 30)
}}
/>
分钟,则视为学员”到课“
</div>
}
{ this.state.studentModal }
{ this.state.explainModal }
</div> </div>
</Spin> </Spin>
) )
......
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
.label { .label {
width: 100px; width: 100px;
text-align: right; text-align: right;
display:inline-block;
.require { .require {
color: #EC4B35; color: #EC4B35;
} }
...@@ -154,7 +154,6 @@ ...@@ -154,7 +154,6 @@
} }
} }
.teacher,
.student, .student,
.deduction-student, .deduction-student,
.no-deduction-student { .no-deduction-student {
...@@ -191,6 +190,9 @@ ...@@ -191,6 +190,9 @@
} }
} }
} }
.tip-icon{
color:#BFBFBF;
}
} }
.iconfont { .iconfont {
......
...@@ -69,6 +69,7 @@ class AddLiveIntro extends React.Component { ...@@ -69,6 +69,7 @@ class AddLiveIntro extends React.Component {
// this.setState({ diskList }); // this.setState({ diskList });
// }); // });
} }
// 删除简介 // 删除简介
handleDeleteIntro = (index) => { handleDeleteIntro = (index) => {
const { liveCourseMediaRequests } = this.props.data; const { liveCourseMediaRequests } = this.props.data;
...@@ -208,15 +209,12 @@ class AddLiveIntro extends React.Component { ...@@ -208,15 +209,12 @@ class AddLiveIntro extends React.Component {
render() { render() {
const { liveScene, liveType, isXiaomai, isEdit, data: { introduction, needRecord, whetherRecord, liveCourseMediaRequests = [], liveCourseWarmMedia = {}, isAutoSendReport } } = this.props; const { liveScene, liveType, isXiaomai, isEdit, data: { introduction, needRecord, whetherRecord, liveCourseMediaRequests = [], liveCourseWarmMedia = {}, isAutoSendReport } } = this.props;
const { showCutModal, warmUrl, showSelectFileModal, diskList, imageFile } = this.state const { showCutModal, warmUrl, showSelectFileModal, diskList, imageFile } = this.state
// 是否是互动班课
const isInteractive = liveScene === 'interactive';
return ( return (
<div className="add-live__intro-info"> <div className="add-live__intro-info">
{(liveScene === 'large' || (liveScene === 'interactive' && liveType === 'LARGE_CLASS_LIVE')) && isXiaomai &&
<div className="playback"> <div className="playback">
<span className="label">直播回放:</span> <span className="label">直播回放:</span>
<div className="content"> <div className="content">
<Radio.Group disabled={liveScene === 'large' && !isEdit} value={needRecord} onChange={(e) => { this.props.onChange('needRecord', e.target.value) }}> <Radio.Group>
<Row style={{ marginBottom: '5px' }}> <Row style={{ marginBottom: '5px' }}>
<Col span={8}> <Col span={8}>
<Radio value="YES"> <Radio value="YES">
...@@ -234,59 +232,29 @@ class AddLiveIntro extends React.Component { ...@@ -234,59 +232,29 @@ class AddLiveIntro extends React.Component {
</Radio> </Radio>
</Col> </Col>
<Col span={16}> <Col span={16}>
<span className="playback__text">师手动选择何时开始录制</span> <span className="playback__text">师手动选择何时开始录制</span>
</Col> </Col>
</Row> </Row>
</Radio.Group> </Radio.Group>
</div> </div>
</div> </div>
} <div className="allow-tourist-join">
{ <span className="label">允许游客加入:</span>
(liveScene === 'interactive' && liveType !== 'LARGE_CLASS_LIVE' && isXiaomai) &&
<div className="interactive-playback">
<span className="label">直播回放:</span>
<div className="content"> <div className="content">
<Radio.Group disabled={liveScene === 'large' && !isEdit} value={whetherRecord} onChange={(e) => { this.props.onChange('whetherRecord', e.target.value) }}> <Row>
<Radio value="YES"> <Col span={3}>
自动录制 <Switch />
</Radio> </Col>
<Radio value="NO"> <Col span={21}>
不录制 <div>开启:用户可直接进入直播间观看直播</div>
</Radio> <div>关闭:用户需先填写手机号并短信验证,通过后才可进入直播间观看直播</div>
</Radio.Group> </Col>
<Popover content={ </Row>
<div className="record-rule-wrap">
<p>录制费 = 录课单价 x 回放视频时长</p>
<ul>
<li>录课单价:2元/小时</li>
<li>回放视频时长:0.5小时起收,不足0.5小时的按0.5小时结算</li>
</ul>
<p className="text">示例:生成了49分26秒的回放视频,不足1小时按1小时计算,录制费就是2元</p>
</div>
}>
<span className="check-record-rule">查看录制费规则</span>
</Popover>
</div>
</div> </div>
}
{
((liveScene === 'large' || liveScene === 'interactive') && isXiaomai && window.currentUserInstInfo.saaSVersionEnum === 'V_50') &&
<div className="auto-send-class-report">
<span className="label">自动发送报告:</span>
<Switch
checked={isAutoSendReport}
onChange={(checked) => this.props.onChange("isAutoSendReport",checked)}></Switch>
<div className="open-text">开启:课程结束后,公众号将自动发送课堂报告给上课学员(仅已绑定微信号的学员)</div>
<div className="close-text">关闭:不自动发送,但学员仍可通过课次详情页查看课堂报告</div>
</div> </div>
}
{ ((liveScene === 'large' || liveScene === 'interactive') && isXiaomai) &&
<div className="warmup"> <div className="warmup">
<span className="label">直播暖场图:</span> <span className="label">直播暖场图:</span>
<div className="course-cover__wrap"> <div className="course-cover__wrap">
<div className="img-content" style={ liveCourseWarmMedia.mediaUrl ? {background: '#000'} : {} }> <div className="img-content" style={ liveCourseWarmMedia.mediaUrl ? {background: '#000'} : {} }>
<img src={liveCourseWarmMedia.mediaType === 'VIDEO' ? `${liveCourseWarmMedia.mediaUrl}?x-oss-process=video/snapshot,t_0,m_fast` : (liveCourseWarmMedia.mediaUrl ? liveCourseWarmMedia.mediaUrl : defaultCover )} /> <img src={liveCourseWarmMedia.mediaType === 'VIDEO' ? `${liveCourseWarmMedia.mediaUrl}?x-oss-process=video/snapshot,t_0,m_fast` : (liveCourseWarmMedia.mediaUrl ? liveCourseWarmMedia.mediaUrl : defaultCover )} />
{ {
...@@ -297,7 +265,6 @@ class AddLiveIntro extends React.Component { ...@@ -297,7 +265,6 @@ class AddLiveIntro extends React.Component {
}}/> }}/>
</div> </div>
} }
</div> </div>
<div className="opt-btns"> <div className="opt-btns">
<Button <Button
...@@ -323,24 +290,11 @@ class AddLiveIntro extends React.Component { ...@@ -323,24 +290,11 @@ class AddLiveIntro extends React.Component {
</div> </div>
</div> </div>
}
<div className="introduce"> <div className="introduce">
<span className="label">直播简介:</span> <span className="label">直播简介:</span>
<div className="content"> <div className="content">
{
isInteractive &&
<TextArea
value={introduction}
placeholder="简单介绍下这次课吧"
maxLength={200}
style={{ width: 480 }}
onChange={(e) => { this.props.onChange('introduction', e.target.value) }}
/>
}
{
!isInteractive &&
[
<div className="intro-list"> <div className="intro-list">
{ {
liveCourseMediaRequests.map((item, index) => { liveCourseMediaRequests.map((item, index) => {
...@@ -370,10 +324,10 @@ class AddLiveIntro extends React.Component { ...@@ -370,10 +324,10 @@ class AddLiveIntro extends React.Component {
} }
}) })
} }
</div>, </div>
<div className="operate"> <div className="operate">
<div className="operate__item" onClick={this.handleAddIntroText}> <div className="operate__item" onClick={this.handleAddIntroText}>
<span className="icon iconfont">&#xe760;</span> <span className="icon iconfont">&#xe639;</span>
<span className="text">文字</span> <span className="text">文字</span>
</div> </div>
...@@ -386,16 +340,15 @@ class AddLiveIntro extends React.Component { ...@@ -386,16 +340,15 @@ class AddLiveIntro extends React.Component {
}} }}
> >
<div className="operate__item"> <div className="operate__item">
<span className="icon iconfont">&#xe74a;</span> <span className="icon iconfont">&#xe63b;</span>
<span className="text">图片</span> <span className="text">图片</span>
</div> </div>
</Upload> </Upload>
</div>, </div>
<div className="tips"> <div className="tips">
• 图片支持jpeg、jpg、png、gif格式 • 图片支持jpeg、jpg、png、gif格式
</div> </div>
]
}
</div> </div>
</div> </div>
{/* 选择暖场图文件弹窗 */} {/* 选择暖场图文件弹窗 */}
......
...@@ -13,7 +13,9 @@ ...@@ -13,7 +13,9 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
} }
.allow-tourist-join{
display:flex;
}
.radio { .radio {
display: block; display: block;
height: 30px; height: 30px;
......
...@@ -13,7 +13,8 @@ import { Table, Modal, Tooltip, Badge, message, Dropdown, Button,Switch} from 'a ...@@ -13,7 +13,8 @@ import { Table, Modal, Tooltip, Badge, message, Dropdown, Button,Switch} from 'a
// import User from "@/core/user"; // import User from "@/core/user";
// import User_t from "@/teacher/core/user"; // import User_t from "@/teacher/core/user";
import { PageControl } from "@/components"; import { PageControl } from "@/components";
// import DownloadLiveModal from '@/components/DownloadLiveModal'; // import { LIVE_SHARE_MAP } from '@/common/constants/academic/cloudClass';
import DownloadLiveModal from '@/components/DownloadLiveModal';
// import LiveStudentListModal from '../modal/LiveStudentListModal'; // import LiveStudentListModal from '../modal/LiveStudentListModal';
// import CheckBalanceModal from '../modal/CheckBalanceModal'; // import CheckBalanceModal from '../modal/CheckBalanceModal';
...@@ -56,6 +57,8 @@ class LiveCourseList extends React.Component { ...@@ -56,6 +57,8 @@ class LiveCourseList extends React.Component {
super(props); super(props);
this.state = { this.state = {
columns: [], columns: [],
openDownloadModal:false,
url:''
} }
} }
componentWillMount(){ componentWillMount(){
...@@ -110,7 +113,6 @@ class LiveCourseList extends React.Component { ...@@ -110,7 +113,6 @@ class LiveCourseList extends React.Component {
// TODOLIST 确定后端是否是根据liveCourseId 返回数据 // TODOLIST 确定后端是否是根据liveCourseId 返回数据
window.RCHistory.push(`/live-course-data?type=large&id=${item.liveCourseId}`) window.RCHistory.push(`/live-course-data?type=large&id=${item.liveCourseId}`)
} }
parseColumns = () => { parseColumns = () => {
const menu = (item) => ( const menu = (item) => (
<div className="live-course-more-menu"> <div className="live-course-more-menu">
...@@ -208,6 +210,7 @@ class LiveCourseList extends React.Component { ...@@ -208,6 +210,7 @@ class LiveCourseList extends React.Component {
<div <div
key="enter_live_room1" key="enter_live_room1"
className="operate__item" className="operate__item"
onClick={() => { this.handleEnterLiveRoom(item) }}
>进入直播间 >进入直播间
</div> </div>
<span className="operate__item split" key="enter_live_room1_split"> | </span> <span className="operate__item split" key="enter_live_room1_split"> | </span>
...@@ -280,11 +283,55 @@ class LiveCourseList extends React.Component { ...@@ -280,11 +283,55 @@ class LiveCourseList extends React.Component {
// pathname: '/create-live-course?type=edit', // pathname: '/create-live-course?type=edit',
// }) // })
} }
refreshCourseList = ()=>{
this.props.onChange(this.props.query);
}
//进入直播间
handleEnterLiveRoom = (item) => {
if (item.startTime - Date.now() > 1800000) {
Modal.warning({
title: "你来得太早了",
okText: '我知道了',
content: "请于开始上课前30分钟来直播上课。",
icon: (
<span
className="icon iconfont default-confirm-icon"
style={{ color: "#FFBB54 !important" }}
>
&#xe6f1;
</span>
),
});
} else {
// axios
// .Apollo("public/businessLive/getCourseDetail", {
// liveCourseId: item.liveCourseId,
// })
// .then((res) => {
// const url = `xiaomai5://instId=${instId}&courseId=${item.liveCourseId}&teacherId=${item.teacherId}&uid=${ teacherId ? User_t.uid() : User.uid()}&aid=${teacherId ? "" : User.aid()}&tid=${teacherId || ""}&identity=${identity}&classType=${item.liveType}&xmVersion=${window.NewVersion ? '5.0' : '4.0'}`;
// if (res.result.courseState === "FINISH") {
// Modal.warning({
// title: "刷新页面",
// icon: <QuestionCircleOutlined />,
// content: "课次已结束,请刷新一下",
// onOk: () => {
// this.refreshCourseList();
// }
// });
// } else {
this.setState({ url:'', openDownloadModal: true });
// }
// });
}
}
render() { render() {
const { total, query, courseList, loading} = this.props; const { total, query, courseList, loading} = this.props;
const { current, size } = query; const { current, size } = query;
const { openDownloadModal,
const { columns} = this.state; downloadUrl, url, columns,
} = this.state;
return ( return (
<div className="live-course-list"> <div className="live-course-list">
<Table <Table
...@@ -309,6 +356,18 @@ class LiveCourseList extends React.Component { ...@@ -309,6 +356,18 @@ class LiveCourseList extends React.Component {
/> />
</div> </div>
{ this.state.shareLiveModal } { this.state.shareLiveModal }
{openDownloadModal && (
<DownloadLiveModal
url={downloadUrl}
onCancel={() => {
this.setState({
url: '',
openDownloadModal:
false });
}}
/>
)}
<iframe src={url} style={{ display: "none" }} />
</div> </div>
) )
} }
......
...@@ -18,6 +18,29 @@ class LiveCourseOpt extends React.Component { ...@@ -18,6 +18,29 @@ class LiveCourseOpt extends React.Component {
pathname: '/create-live-course?type=add', pathname: '/create-live-course?type=add',
}) })
} }
// 下载直播客户端
handleDownloadClient = () => {
const isMac = /macintosh|mac os x/i.test(navigator.userAgent);
// 判断用户系统
if(!isMac) {
// axios
// .Apollo("anon/version/getLastedVersion", { model: 1, platform: 1 })
// .then((res) => {
// const a = document.createElement("a");
// document.body.appendChild(a);
// a.href = res.result.releaseUrl;
// a.click();
// document.body.removeChild(a);
// })
}else {
Modal.info({
title: "抱歉,暂不支持Mac版",
content: "Mac版正在开发中,敬请期待",
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>,
okText: '我知道了'
});
}
}
render() { render() {
return ( return (
<div className="live-course-opt"> <div className="live-course-opt">
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* @Author: zhangleyuan * @Author: zhangleyuan
* @Date: 2020-11-27 15:06:31 * @Date: 2020-11-27 15:06:31
* @LastEditors: zhangleyuan * @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-09 11:23:52 * @LastEditTime: 2020-12-12 14:49:13
* @Description: 描述一下 * @Description: 描述一下
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
......
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