Commit 510254f6 by guomingpang

feat:课程管理缺省图替换,导航栏收起高亮

parent f803fff4
import React from "react"; import User from '@/common/js/user';
import { withRouter } from "react-router-dom"; import college from '@/common/lottie/college';
import { Table, Popover, message, Button, Spin } from "antd"; import { PageControl, XMTable } from '@/components';
import dealTimeDuration from "../utils/dealTimeDuration"; import CourseService from '@/domains/course-domain/CourseService';
import { PageControl } from "@/components"; import { Button, message, Popover, Spin } from 'antd';
import CourseService from "@/domains/course-domain/CourseService"; import React from 'react';
import User from "@/common/js/user"; import { withRouter } from 'react-router-dom';
import "./DataList.less"; import dealTimeDuration from '../utils/dealTimeDuration';
import './DataList.less';
class DataList extends React.Component { class DataList extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
const courseId = getParameterByName("id"); // 课程ID const courseId = getParameterByName('id'); // 课程ID
const type = getParameterByName("type"); // 来源: 大班直播 large 互动班课 interactive const type = getParameterByName('type'); // 来源: 大班直播 large 互动班课 interactive
this.state = { this.state = {
type, type,
teacherData: [], // 老师上课数据 teacherData: [], // 老师上课数据
...@@ -68,34 +69,30 @@ class DataList extends React.Component { ...@@ -68,34 +69,30 @@ class DataList extends React.Component {
getVisiterColumns() { getVisiterColumns() {
const columns = [ const columns = [
{ {
title: "序号", title: '序号',
dataIndex: "index", dataIndex: 'index',
width: 50, width: 50,
render: (text, record, index) => { render: (text, record, index) => {
return <span>{index + 1}</span>; return <span>{index + 1}</span>;
}, },
}, },
{ {
title: "进入时间", title: '进入时间',
dataIndex: "entryTime", dataIndex: 'entryTime',
width: 150, width: 150,
render: (text) => ( render: (text) => <span>{formatDate('YYYY-MM-DD H:i', parseInt(text))}</span>,
<span>{formatDate("YYYY-MM-DD H:i", parseInt(text))}</span>
),
}, },
{ {
title: "离开时间", title: '离开时间',
dataIndex: "leaveTime", dataIndex: 'leaveTime',
width: 150, width: 150,
render: (text) => ( render: (text) => <span>{formatDate('YYYY-MM-DD H:i', parseInt(text))}</span>,
<span>{formatDate("YYYY-MM-DD H:i", parseInt(text))}</span>
),
}, },
{ {
title: "在线时长", title: '在线时长',
dataIndex: "lookingDuration", dataIndex: 'lookingDuration',
render: (text, record) => { render: (text, record) => {
return <span>{text ? dealTimeDuration(text) : "-"}</span>; return <span>{text ? dealTimeDuration(text) : '-'}</span>;
}, },
}, },
]; ];
...@@ -106,43 +103,44 @@ class DataList extends React.Component { ...@@ -106,43 +103,44 @@ class DataList extends React.Component {
getStudentColumns() { getStudentColumns() {
const columns = [ const columns = [
{ {
title: "学员姓名", title: '学员姓名',
dataIndex: "userName", dataIndex: 'userName',
}, },
{ {
title: "手机号", title: '手机号',
dataIndex: "phone", dataIndex: 'phone',
render: (text, record) => { render: (text, record) => {
const { phone = "", bindingWeChat } = record; const { phone = '', bindingWeChat } = record;
return <div>{phone}</div>; return <div>{phone}</div>;
}, },
}, },
{ {
title: "观看次数", title: '观看次数',
dataIndex: "entryNum", dataIndex: 'entryNum',
render: (text, record) => { render: (text, record) => {
if (text > 0) { if (text > 0) {
if ( if (record.visitorInfoVOList && record.visitorInfoVOList.length > 0) {
record.visitorInfoVOList &&
record.visitorInfoVOList.length > 0
) {
const table = ( const table = (
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
columns={this.getVisiterColumns()} columns={this.getVisiterColumns()}
dataSource={record.visitorInfoVOList} dataSource={record.visitorInfoVOList}
scroll={{ y: 75 }} scroll={{ y: 75 }}
size={"small"} size={'small'}
style={{ width: 450 }} style={{ width: 450 }}
pagination={false} pagination={false}
/> />
); );
return ( return (
<Popover content={table} trigger="click"> <Popover content={table} trigger='click'>
<span className="handel-btn">{text}</span> <span className='handel-btn'>{text}</span>
</Popover> </Popover>
); );
} else { } else {
return <div className="live-table--empty">暂无观看数据</div>; return <div className='live-table--empty'>暂无观看数据</div>;
} }
} else { } else {
return <span>{text}</span>; return <span>{text}</span>;
...@@ -150,13 +148,13 @@ class DataList extends React.Component { ...@@ -150,13 +148,13 @@ class DataList extends React.Component {
}, },
}, },
{ {
title: "累计在线时长", title: '累计在线时长',
dataIndex: "totalDuration", dataIndex: 'totalDuration',
sorter: (a, b) => a.totalDuration - b.totalDuration, sorter: (a, b) => a.totalDuration - b.totalDuration,
sortDirections: ["descend", "ascend"], sortDirections: ['descend', 'ascend'],
render: (text, record) => { render: (text, record) => {
//如无离开时间,就置空 //如无离开时间,就置空
return <span>{text ? dealTimeDuration(text) : "00:00:00"}</span>; return <span>{text ? dealTimeDuration(text) : '00:00:00'}</span>;
}, },
}, },
]; ];
...@@ -169,17 +167,17 @@ class DataList extends React.Component { ...@@ -169,17 +167,17 @@ class DataList extends React.Component {
CourseService.exportStudentCourseData({ CourseService.exportStudentCourseData({
liveCourseId: liveCourseId, liveCourseId: liveCourseId,
exportLiveType: "VISITOR", exportLiveType: 'VISITOR',
storeId, storeId,
}).then((res) => { }).then((res) => {
const link = res.result; const link = res.result;
this.setState({ this.setState({
link link,
}); });
document.getElementById("loadExcel").click(); document.getElementById('loadExcel').click();
if (res.success) { if (res.success) {
message.success("导出成功!"); message.success('导出成功!');
} }
}); });
}; };
...@@ -187,27 +185,28 @@ class DataList extends React.Component { ...@@ -187,27 +185,28 @@ class DataList extends React.Component {
handleCheckEnterTimes = () => { handleCheckEnterTimes = () => {
const { teacherData } = this.state; const { teacherData } = this.state;
if (teacherData.entryNum > 0) { if (teacherData.entryNum > 0) {
if ( if (teacherData.visitorInfoVOList && teacherData.visitorInfoVOList.length > 0) {
teacherData.visitorInfoVOList &&
teacherData.visitorInfoVOList.length > 0
) {
const table = ( const table = (
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
columns={this.getVisiterColumns()} columns={this.getVisiterColumns()}
dataSource={teacherData.visitorInfoVOList} dataSource={teacherData.visitorInfoVOList}
scroll={{ y: 75 }} scroll={{ y: 75 }}
size={"small"} size={'small'}
style={{ width: 450 }} style={{ width: 450 }}
pagination={false} pagination={false}
/> />
); );
return ( return (
<Popover content={table} trigger="click"> <Popover content={table} trigger='click'>
<span className="times-num">{teacherData.entryNum}</span> <span className='times-num'>{teacherData.entryNum}</span>
</Popover> </Popover>
); );
} else { } else {
return <div className="live-table--empty">暂无观看数据</div>; return <div className='live-table--empty'>暂无观看数据</div>;
} }
} else { } else {
return <span>{teacherData.entryNum}</span>; return <span>{teacherData.entryNum}</span>;
...@@ -216,130 +215,107 @@ class DataList extends React.Component { ...@@ -216,130 +215,107 @@ class DataList extends React.Component {
showTable = () => { showTable = () => {
return ( return (
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
columns={this.getVisiterColumns()} columns={this.getVisiterColumns()}
dataSource={this.state.teacherData.visitorInfoVOList} dataSource={this.state.teacherData.visitorInfoVOList}
scroll={{ y: 80 }} scroll={{ y: 80 }}
size={"small"} size={'small'}
style={{ width: 450 }} style={{ width: 450 }}
pagination={false} pagination={false}
className="visitor-num-table" className='visitor-num-table'
/> />
); );
}; };
onShowSizeChange = (current, size) => { onShowSizeChange = (current, size) => {
if (current == size) { if (current == size) {
return; return;
} }
this.setState({ size }, this.fetchUserData) this.setState({ size }, this.fetchUserData);
} };
render() { render() {
const { const { teacherData, studentData, current, size, total, loading, link } = this.state;
teacherData,
studentData,
current,
size,
total,
loading,
link
} = this.state;
return ( return (
<Spin spinning={loading}> <Spin spinning={loading}>
<a <a href={link} target='_blank' download id='loadExcel' style={{ position: 'absolute', left: '-10000px' }}>
href={link}
target="_blank"
download
id="loadExcel"
style={{ position: "absolute", left: "-10000px" }}
>
111 111
</a> </a>
{/* 讲师上课数据 */} {/* 讲师上课数据 */}
<div className="courseData-teacher"> <div className='courseData-teacher'>
<p className="title">讲师上课数据</p> <p className='title'>讲师上课数据</p>
<div className="teacher-course-data"> <div className='teacher-course-data'>
<div className="avatar-name-phone item-block"> <div className='avatar-name-phone item-block'>
<img <img src={teacherData.avatar || 'https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png'} alt='' className='avatar' />
src={ <div className='right'>
teacherData.avatar || <div className='name'>{teacherData.userName}</div>
"https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png" <div className='phone'>{teacherData.phone}</div>
}
alt=""
className="avatar"
/>
<div className="right">
<div className="name">{teacherData.userName}</div>
<div className="phone">
{teacherData.phone}
</div>
</div> </div>
</div> </div>
<div className="times item-block"> <div className='times item-block'>
<div <div className={`times-num ${Number(teacherData.entryNum) > 0 ? 'can-click' : ''}`}>
className={`times-num ${ {Number(teacherData.entryNum) > 0 ? (
Number(teacherData.entryNum) > 0 ? "can-click" : "" <Popover content={this.showTable()} trigger='click'>
}`} <span className='times-num'>{teacherData.entryNum || 0}</span>
>{ </Popover>
Number(teacherData.entryNum) > 0 ? ) : (
<Popover content={this.showTable()} trigger="click"> <span className='times-num'>{0}</span>
<span className="times-num">{teacherData.entryNum || 0}</span> )}
</Popover>:
<span className="times-num">{0}</span>
}
</div> </div>
<div className="text">进入直播间次数</div> <div className='text'>进入直播间次数</div>
</div> </div>
<div className="online-duration item-block"> <div className='online-duration item-block'>
<div className="duration"> <div className='duration'>{teacherData.totalDuration ? dealTimeDuration(teacherData.totalDuration) : '00:00:00'}</div>
{teacherData.totalDuration <div className='text'>累计在线时长</div>
? dealTimeDuration(teacherData.totalDuration)
: "00:00:00"}
</div>
<div className="text">累计在线时长</div>
</div> </div>
</div> </div>
</div> </div>
{/* 学员上课数据 */} {/* 学员上课数据 */}
<div className="courseData-student"> <div className='courseData-student'>
<p className="title">学员上课数据</p> <p className='title'>学员上课数据</p>
<div className="filter-wrap"> <div className='filter-wrap'>
<div className="filter"> <div className='filter'>
<Button <Button
style={{ height: 32}} style={{ height: 32 }}
onClick={_.debounce( onClick={_.debounce(
() => { () => {
if (!studentData.length) { if (!studentData.length) {
message.warning("暂无数据可导出"); message.warning('暂无数据可导出');
return; return;
} }
this.handleExportV5(); this.handleExportV5();
}, },
500, 500,
true true
)} )}>
>
导出 导出
</Button> </Button>
</div> </div>
</div> </div>
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
bordered bordered
size="small" size='small'
scroll={{ y: 600 }} scroll={{ y: 600 }}
columns={this.getStudentColumns()} columns={this.getStudentColumns()}
dataSource={studentData} dataSource={studentData}
pagination={false} pagination={false}
style={{ margin: "16px 0" }} style={{ margin: '16px 0' }}
/> />
{ total > 0 && {total > 0 && (
<PageControl <PageControl
size="small" size='small'
current={current - 1} current={current - 1}
pageSize={size} pageSize={size}
total={total} total={total}
...@@ -348,7 +324,7 @@ class DataList extends React.Component { ...@@ -348,7 +324,7 @@ class DataList extends React.Component {
this.fetchUserData(page + 1); this.fetchUserData(page + 1);
}} }}
/> />
} )}
</div> </div>
</Spin> </Spin>
); );
......
import User from '@/common/js/user';
import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components';
import CourseService from '@/domains/course-domain/CourseService';
import { Button, message } from 'antd';
import React from 'react'; import React from 'react';
import { withRouter } from "react-router-dom"; import { withRouter } from 'react-router-dom';
import { Table, Button, Modal, message } from 'antd';
import dealTimeDuration from '../utils/dealTimeDuration'; import dealTimeDuration from '../utils/dealTimeDuration';
import { PageControl } from "@/components";
import './DataList.less'; import './DataList.less';
import CourseService from "@/domains/course-domain/CourseService";
import User from '@/common/js/user';
const liveTypeMap = { const liveTypeMap = {
USER: "普通用户", USER: '普通用户',
ANCHOR: "讲师", ANCHOR: '讲师',
ADMIN: "管理员(助教)", ADMIN: '管理员(助教)',
GUEST: "游客" GUEST: '游客',
}; };
class PlaybackData extends React.Component { class PlaybackData extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
const courseId = getParameterByName("id"); // 课程ID const courseId = getParameterByName('id'); // 课程ID
this.state = { this.state = {
playbackData: [], playbackData: [],
...@@ -24,8 +25,8 @@ class PlaybackData extends React.Component { ...@@ -24,8 +25,8 @@ class PlaybackData extends React.Component {
size: 10, size: 10,
total: 0, total: 0,
liveCourseId: courseId, liveCourseId: courseId,
storeId: User.getStoreId() storeId: User.getStoreId(),
} };
} }
componentDidMount() { componentDidMount() {
...@@ -33,12 +34,12 @@ class PlaybackData extends React.Component { ...@@ -33,12 +34,12 @@ class PlaybackData extends React.Component {
} }
fetchPlaybackList = (page = 1) => { fetchPlaybackList = (page = 1) => {
const { size, liveCourseId } = this.state const { size, liveCourseId } = this.state;
const params = { const params = {
liveCourseId, liveCourseId,
current: page, current: page,
size size,
} };
CourseService.fetchPlaybackList(params).then((res) => { CourseService.fetchPlaybackList(params).then((res) => {
if (res.result) { if (res.result) {
...@@ -47,38 +48,35 @@ class PlaybackData extends React.Component { ...@@ -47,38 +48,35 @@ class PlaybackData extends React.Component {
playbackData: records, playbackData: records,
current, current,
size, size,
total total,
}); });
} }
}); });
}; };
getPlaybackColumns() { getPlaybackColumns() {
const columns = [ const columns = [
{ {
title: "观看学员", title: '观看学员',
dataIndex: "userName", dataIndex: 'userName',
}, },
{ {
title: "手机号", title: '手机号',
dataIndex: "phone" dataIndex: 'phone',
}, },
{ {
title: "观看者类型", title: '观看者类型',
dataIndex: "userRole", dataIndex: 'userRole',
render: (text) => <span>{liveTypeMap[text]}</span>, render: (text) => <span>{liveTypeMap[text]}</span>,
}, },
{ {
title: "开始观看时间", title: '开始观看时间',
dataIndex: "entryTime", dataIndex: 'entryTime',
render: (text) => ( render: (text) => <span>{text ? formatDate('YYYY-MM-DD H:i', parseInt(text)) : '-'}</span>,
<span>{text ? formatDate("YYYY-MM-DD H:i", parseInt(text)) : '-'}</span>
),
}, },
{ {
title: "观看时长", title: '观看时长',
dataIndex: "lookingDuration", dataIndex: 'lookingDuration',
render: (text) => { render: (text) => {
return <span>{text ? dealTimeDuration(text) : '-'}</span>; return <span>{text ? dealTimeDuration(text) : '-'}</span>;
}, },
...@@ -92,65 +90,67 @@ class PlaybackData extends React.Component { ...@@ -92,65 +90,67 @@ class PlaybackData extends React.Component {
CourseService.exportPlayBackCourseData({ CourseService.exportPlayBackCourseData({
liveCourseId, liveCourseId,
exportLiveType: "PLAY_BACK", exportLiveType: 'PLAY_BACK',
storeId storeId,
}).then((res) => { }).then((res) => {
const link = res.result; const link = res.result;
this.setState({ this.setState({
link link,
}); });
document.getElementById("load-play-back-excel").click(); document.getElementById('load-play-back-excel').click();
if(res.success){ if (res.success) {
message.success("导出成功!") message.success('导出成功!');
} }
}) });
} }
onShowSizeChange = (current, size) => { onShowSizeChange = (current, size) => {
if (current == size) { if (current == size) {
return; return;
} }
this.setState({ size }, this.fetchUserData) this.setState({ size }, this.fetchUserData);
} };
render() { render() {
const { playbackData, total, current, size, link} = this.state const { playbackData, total, current, size, link } = this.state;
return ( return (
<div> <div>
<a <a href={link} target='_blank' download id='load-play-back-excel' style={{ position: 'absolute', left: '-10000px' }}>
href={link}
target="_blank"
download
id="load-play-back-excel"
style={{ position: "absolute", left: "-10000px" }}
>
111 111
</a> </a>
<Button onClick={() => {this.handleplaybackExport()}}>导出</Button> <Button
<Table onClick={() => {
this.handleplaybackExport();
}}>
导出
</Button>
<XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
bordered bordered
size="small" size='small'
columns={this.getPlaybackColumns()} columns={this.getPlaybackColumns()}
dataSource={playbackData} dataSource={playbackData}
pagination={false} pagination={false}
style={{ margin: '16px 0' }}> style={{ margin: '16px 0' }}></XMTable>
</Table> {total > 0 && (
{ total > 0 && <PageControl
<PageControl size='small'
size="small" current={current - 1}
current={current - 1} pageSize={size}
pageSize={size} total={total}
total={total} onShowSizeChange={this.onShowSizeChange}
onShowSizeChange={this.onShowSizeChange} toPage={(page) => {
toPage={(page) => { this.fetchPlaybackList(page + 1);
this.fetchPlaybackList(page + 1); }}
}} />
/> )}
}
</div> </div>
) );
} }
} }
export default withRouter(PlaybackData); export default withRouter(PlaybackData);
\ No newline at end of file
/* /*
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-07-14 15:43:00 * @Date: 2020-07-14 15:43:00
* @Last Modified by: chenshu * @Last Modified by: chenshu
* @Last Modified time: 2021-03-16 17:37:23 * @Last Modified time: 2021-03-16 17:37:23
* @Description: 大班直播、互动班课的直播课列表 * @Description: 大班直播、互动班课的直播课列表
*/ */
import User from '@/common/js/user';
import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components';
import DownloadLiveModal from '@/components/DownloadLiveModal';
import BaseService from '@/domains/basic-domain/baseService';
import { appId, LIVE_SHARE } from '@/domains/course-domain/constants';
import CourseService from '@/domains/course-domain/CourseService';
import { QuestionCircleOutlined } from '@ant-design/icons';
import { Dropdown, message, Modal, Switch, Tooltip } from 'antd';
import React from 'react'; import React from 'react';
import { Table, Modal, message, Dropdown, Button,Switch,Tooltip} from 'antd';
import { Route, withRouter } from 'react-router-dom'; import { Route, withRouter } from 'react-router-dom';
import { PageControl } from "@/components"; import _ from 'underscore';
import DownloadLiveModal from '@/components/DownloadLiveModal'; import DataList from '../DataList/DataList';
import ManageCoursewareModal from '../modal/ManageCoursewareModal'; import ManageCoursewareModal from '../modal/ManageCoursewareModal';
import ShareLiveModal from '../modal/ShareLiveModal';
import RelatedPlanModal from '../modal/RelatedPlanModal'; import RelatedPlanModal from '../modal/RelatedPlanModal';
import ShareLiveModal from '../modal/ShareLiveModal';
import './LiveCourseList.less'; import './LiveCourseList.less';
import { QuestionCircleOutlined } from '@ant-design/icons';
import { appId, shareUrl, LIVE_SHARE,LIVE_REPLAY_MAP} from '@/domains/course-domain/constants';
import CourseService from "@/domains/course-domain/CourseService";
import BaseService from "@/domains/basic-domain/baseService";
import DataList from '../DataList/DataList';
import User from '@/common/js/user';
import _ from "underscore";
const { confirm } = Modal; const { confirm } = Modal;
const courseStateShow = { const courseStateShow = {
UN_START: { UN_START: {
code: 1, code: 1,
title: "待开课", title: '待开课',
color: "#FFB129", color: '#FFB129',
}, },
STARTING: { STARTING: {
code: 2, code: 2,
title: "上课中", title: '上课中',
color: "#238FFF", color: '#238FFF',
}, },
FINISH: { FINISH: {
code: 3, code: 3,
title: "已完成", title: '已完成',
color: "#3BBDAA", color: '#3BBDAA',
}, },
EXPIRED: { EXPIRED: {
code: 4, code: 4,
title: "未成功开课", title: '未成功开课',
color: "#999", color: '#999',
}, },
}; };
class LiveCourseList extends React.Component { class LiveCourseList extends React.Component {
...@@ -55,702 +52,744 @@ class LiveCourseList extends React.Component { ...@@ -55,702 +52,744 @@ class LiveCourseList extends React.Component {
super(props); super(props);
this.state = { this.state = {
columns: [], columns: [],
openDownloadModal:false, openDownloadModal: false,
url:'', url: '',
RelatedPlanModalVisible:false, RelatedPlanModalVisible: false,
selectPlanList:{} selectPlanList: {},
} };
} }
componentWillMount(){ componentWillMount() {
this.parseColumns(); this.parseColumns();
} }
componentDidMount() { componentDidMount() {
this.getDownloadVersion() this.getDownloadVersion();
} }
// 显示分享弹窗 // 显示分享弹窗
handleShowShareModal = (item, needStr = false) => { handleShowShareModal = (item, needStr = false) => {
const _appId = appId; const _appId = appId;
const { liveCourseId } = item; const { liveCourseId } = item;
const htmlUrl = `${LIVE_SHARE}live_detail/${liveCourseId}?id=${User.getStoreId()}`; const htmlUrl = `${LIVE_SHARE}live_detail/${liveCourseId}?id=${User.getStoreId()}`;
const longUrl = htmlUrl const longUrl = htmlUrl;
console.log('htmlUrl',htmlUrl,longUrl); console.log('htmlUrl', htmlUrl, longUrl);
const shareData = { ...item, longUrl }; const shareData = { ...item, longUrl };
const shareLiveModal = ( const shareLiveModal = (
<ShareLiveModal <ShareLiveModal
needStr={needStr} needStr={needStr}
data={shareData} data={shareData}
type="liveClass" type='liveClass'
title="直播课" title='直播课'
close={() => { close={() => {
this.setState({ this.setState({
shareLiveModal: null shareLiveModal: null,
}); });
localStorage.setItem('largeLiveCourseItem', ''); localStorage.setItem('largeLiveCourseItem', '');
}} }}
/> />
) );
this.setState({ shareLiveModal }) this.setState({ shareLiveModal });
} };
//改变上架状态 //改变上架状态
changeShelfState = (item) =>{ changeShelfState = (item) => {
let _shelfState = item.shelfState let _shelfState = item.shelfState;
if(_shelfState==='NO'){ if (_shelfState === 'NO') {
_shelfState = "YES"; _shelfState = 'YES';
item.shelfState = "YES" item.shelfState = 'YES';
}else{ } else {
_shelfState = "NO" _shelfState = 'NO';
item.shelfState = "NO" item.shelfState = 'NO';
}
const params={
"liveCourseId": item.liveCourseId,
"shelfState":_shelfState
} }
CourseService.turnOnOrOffLiveCloudCourse(params).then((res)=>{ const params = {
if(res.success){ liveCourseId: item.liveCourseId,
if(_shelfState === "YES"){ shelfState: _shelfState,
message.success("已开启展示"); };
}else{ CourseService.turnOnOrOffLiveCloudCourse(params).then((res) => {
message.success("已取消展示"); if (res.success) {
if (_shelfState === 'YES') {
message.success('已开启展示');
} else {
message.success('已取消展示');
} }
} }
}) });
} };
// 前往上课数据页面 // 前往上课数据页面
handleLinkToClassData = (item) => { handleLinkToClassData = (item) => {
const { match } = this.props; const { match } = this.props;
window.RCHistory.push({ window.RCHistory.push({
pathname: `${match.url}/live-course-data?type=large&id=${item.liveCourseId}` pathname: `${match.url}/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'>
<div> <div>上课记录</div>
上课记录
</div>
<div <div
onClick={() => { onClick={() => {
this.handleShowRepeatModal(item); this.handleShowRepeatModal(item);
}} }}>
>
回放记录 回放记录
</div> </div>
</div> </div>
); );
let columns let columns;
const userRole = User.getUserRole(); const userRole = User.getUserRole();
if(userRole !=="CloudLecturer"){ if (userRole !== 'CloudLecturer') {
columns = [ columns = [
{ {
title: "直播课", title: '直播课',
width: "23%", width: '23%',
key: "course", key: 'course',
dataIndex: "courseName", dataIndex: 'courseName',
render: (val, record) => { render: (val, record) => {
let hasCover = false; let hasCover = false;
return ( return (
<div className="record__item"> <div className='record__item'>
{ {record.courseMediaVOS.map((item, index) => {
record.courseMediaVOS.map((item,index)=>{ if (item.contentType === 'COVER') {
if( item.contentType === "COVER"){ hasCover = true;
hasCover = true; return <img className='course-cover' src={item.mediaUrl} />;
return <img className="course-cover" src={item.mediaUrl} /> }
} })}
}) {!hasCover && <img className='course-cover' src={'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png'} />}
}
{ !hasCover &&
<img className="course-cover" src={'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png'} />
}
<div> <div>
{ record.courseName.length > 17? {record.courseName.length > 17 ? (
<Tooltip title={record.courseName}> <Tooltip title={record.courseName}>
<div className="course-name">{record.courseName}</div> <div className='course-name'>{record.courseName}</div>
</Tooltip>
) : (
<div className='course-name'>{record.courseName}</div>
)}
<div>
<span className='course-time'>
{formatDate('YYYY-MM-DD H:i', parseInt(record.startTime))}~{formatDate('H:i', parseInt(record.endTime))}
</span>
<span
className='course-status'
style={{ color: courseStateShow[record.courseState].color, border: `1px solid ${courseStateShow[record.courseState].color}` }}>
{courseStateShow[record.courseState].title}
</span>
</div>
<div className='teacher-assistant'>
{record.teacherName.length > 4 ? (
<Tooltip title={record.teacherName}>
<span className='teacher'>讲师:{record.teacherName}</span>
</Tooltip> </Tooltip>
: ) : (
<div className="course-name">{record.courseName}</div> <span className='teacher'>讲师:{record.teacherName}</span>
} )}
<div>
<span className="course-time">{formatDate("YYYY-MM-DD H:i",parseInt(record.startTime))}~{formatDate("H:i", parseInt(record.endTime))}</span> {record.admins.length > 0 && (
<span className="course-status" style={{color:courseStateShow[record.courseState].color,border:`1px solid ${courseStateShow[record.courseState].color}`}}>{courseStateShow[record.courseState].title}</span> <>
</div> <span className='split'> | </span>
<div className="teacher-assistant"> {this.handleAdminName(record.admins).length > 4 ? (
{ record.teacherName.length > 4 ? <Tooltip title={this.handleAdminName(record.admins)}>
<Tooltip title={record.teacherName}> <span className='assistant'>
<span className="teacher">讲师:{record.teacherName}</span> 助教:
</Tooltip> {record.admins.map((item, index) => {
: return (
<span className="teacher">讲师:{record.teacherName}</span> <span>
} {item.adminName} {index < record.admins.length - 1 && <span></span>}{' '}
</span>
{ record.admins.length >0 && );
<> })}
<span className="split"> | </span> </span>
{ this.handleAdminName(record.admins).length > 4? </Tooltip>
<Tooltip title={this.handleAdminName(record.admins)}> ) : (
<span className="assistant">助教: <span className='assistant'>
{ record.admins.map((item,index)=>{ 助教:
return <span>{item.adminName} { (index < record.admins.length-1)&&(<span></span>)} </span> {record.admins.map((item, index) => {
}) return (
} <span>
{item.adminName} {index < record.admins.length - 1 && <span></span>}{' '}
</span> </span>
</Tooltip> );
: })}
<span className="assistant">助教: </span>
{ record.admins.map((item,index)=>{ )}
return <span>{item.adminName} { (index < record.admins.length-1)&&(<span></span>)} </span> </>
}) )}
} </div>
</span>
}
</>
}
</div>
</div> </div>
</div> </div>
) );
} },
}, },
{ {
title: "课程分类", title: '课程分类',
width: "10%", width: '10%',
key: "couseCatalog", key: 'couseCatalog',
dataIndex: "couseCatalog", dataIndex: 'couseCatalog',
render: (val, item) => { render: (val, item) => {
return ( return <div className='categoryName'>{item.categoryName}</div>;
<div className="categoryName">{item.categoryName}</div>
)
}, },
}, },
{ {
title: "课件管理", title: '课件管理',
width: "8%", width: '8%',
key: "courseware", key: 'courseware',
dataIndex: "courseware", dataIndex: 'courseware',
render: (val, item) => { render: (val, item) => {
return ( return (
<span className="courseware" <span
className='courseware'
onClick={() => { onClick={() => {
this.setState({ this.setState({
editData: item, editData: item,
openCoursewareModal: true, openCoursewareModal: true,
}); });
}}>{item.courseDocumentCount}</span> }}>
{item.courseDocumentCount}
</span>
); );
}, },
}, },
{ {
title: '上课数据', title: '上课数据',
width: "9%", width: '9%',
key: "quota", key: 'quota',
dataIndex: "quota", dataIndex: 'quota',
render: (val, item) => { render: (val, item) => {
return ( return (
<span className="iconfont icon quota-icon" onClick={() => { <span
this.handleLinkToClassData(item) className='iconfont icon quota-icon'
}}>&#xe7d6;</span> onClick={() => {
this.handleLinkToClassData(item);
}}>
&#xe7d6;
</span>
); );
}, },
}, },
{ {
title: <span> title: (
<span>学院展示</span> <span>
<Tooltip title={<div>开启后,学员可在学院内查看到此课程。若课程“未成功开课”,则系统会自动“关闭”学院展示。<br/>关闭后,学院内不再展示此课程,但学员仍可通过分享的海报/链接查看此课程。</div>}><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px',fontWeight:'normal'}}>&#xe61d;</i></Tooltip> <span>学院展示</span>
</span>, <Tooltip
width: "9%", title={
key: "shelfState", <div>
dataIndex: "shelfState", 开启后,学员可在学院内查看到此课程。若课程“未成功开课”,则系统会自动“关闭”学院展示。
<br />
关闭后,学院内不再展示此课程,但学员仍可通过分享的海报/链接查看此课程。
</div>
}>
<i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px', fontWeight: 'normal' }}>
&#xe61d;
</i>
</Tooltip>
</span>
),
width: '9%',
key: 'shelfState',
dataIndex: 'shelfState',
render: (val, item, index) => { render: (val, item, index) => {
return ( return <Switch defaultChecked={item.shelfState === 'YES' ? true : false} onChange={() => this.changeShelfState(item)} />;
<Switch defaultChecked={item.shelfState==="YES"?true:false} onChange={()=>this.changeShelfState(item)}/>
)
}, },
}, },
{ {
title: '创建时间', title: '创建时间',
width: "9%", width: '9%',
key: "created", key: 'created',
dataIndex: "created", dataIndex: 'created',
sorter: true, sorter: true,
render: (val, item) => { render: (val, item) => {
return ( return <span>{formatDate('YYYY-MM-DD H:i', val)}</span>;
<span>{formatDate('YYYY-MM-DD H:i', val)}</span>
);
}, },
}, },
{ {
title: '关联项', title: '关联项',
width: "15%", width: '15%',
key: "planList", key: 'planList',
dataIndex: "planList", dataIndex: 'planList',
render: (val, record) => { render: (val, record) => {
return ( return (
<div className="related-task"> <div className='related-task'>
{ record.relatedPlanList ? {record.relatedPlanList ? (
<Tooltip title={this.handlePlanName(record.relatedPlanList)} placement="top" arrowPointAtCenter> <Tooltip title={this.handlePlanName(record.relatedPlanList)} placement='top' arrowPointAtCenter>
{ record.relatedPlanList.map((item,index)=>{ {record.relatedPlanList.map((item, index) => {
return <span>{item.planName} { (index < record.relatedPlanList.length-1)&&(<span></span>)} </span> return (
}) <span>
} {item.planName} {index < record.relatedPlanList.length - 1 && <span></span>}{' '}
</Tooltip> </span>
: );
<span></span> })}
} </Tooltip>
) : (
<span></span>
)}
</div> </div>
) );
}, },
}, },
{ {
title: "操作", title: '操作',
width: "15%", width: '15%',
key: "operate", key: 'operate',
dataIndex: "operate", dataIndex: 'operate',
render: (val, item) => { render: (val, item) => {
return ( return (
<div className='operate'>
<div className="operate"> {(item.courseState === 'UN_START' || item.courseState === 'STARTING') &&
{ ((item.courseState==="UN_START" || item.courseState==="STARTING") && (item.teacherId === User.getUserId() || _.pluck(item.admins, "adminId").includes(User.getUserId()))) && (item.teacherId === User.getUserId() || _.pluck(item.admins, 'adminId').includes(User.getUserId())) && (
<>
<div
key="enter_live_room1"
className="operate__item"
onClick={() => { this.handleEnterLiveRoom(item) }}
>进入直播间
</div>
<span className="operate__item split" key="view_play_back_split"> | </span>
</>
}
{ (item.courseState==="FINISH" && item.haveRecord==="YES") &&
<> <>
<div <div
key="view_play_back" key='enter_live_room1'
className="operate__item" className='operate__item'
onClick={()=>{this.handleViewPlayBack(item)}} onClick={() => {
>查看回放</div> this.handleEnterLiveRoom(item);
<span className="operate__item split" key="view_play_back_split"> | </span> }}>
</> 进入直播间
}
{ item.courseState!=="EXPIRED" &&
<>
<div
key="share"
className="operate__item"
onClick={() => { this.handleShowShareModal(item); }}
>
分享
</div> </div>
<span className='operate__item split' key='view_play_back_split'>
{' '}
|{' '}
</span>
</> </>
} )}
{ item.courseState!=="EXPIRED" && {item.courseState === 'FINISH' && item.haveRecord === 'YES' && (
<>
<div
key='view_play_back'
className='operate__item'
onClick={() => {
this.handleViewPlayBack(item);
}}>
查看回放
</div>
<span className='operate__item split' key='view_play_back_split'>
{' '}
|{' '}
</span>
</>
)}
{item.courseState !== 'EXPIRED' && (
<>
<div
key='share'
className='operate__item'
onClick={() => {
this.handleShowShareModal(item);
}}>
分享
</div>
</>
)}
{item.courseState !== 'EXPIRED' && (
<> <>
<span key="split1" className="operate__item split"> | </span> <span key='split1' className='operate__item split'>
<div className="big-live"> {' '}
|{' '}
</span>
<div className='big-live'>
<Dropdown overlay={this.renderMoreOperate(item)}> <Dropdown overlay={this.renderMoreOperate(item)}>
<span className="more-operate"> <span className='more-operate'>
<span className="operate-text">更多</span> <span className='operate-text'>更多</span>
<span <span className='iconfont icon' style={{ color: '#2966FF' }}>
className="iconfont icon" &#xe824;
style={{ color: "#2966FF" }}
>
&#xe824;
</span> </span>
</span> </span>
</Dropdown> </Dropdown>
</div> </div>
</> </>
} )}
{ item.courseState==="EXPIRED" && {item.courseState === 'EXPIRED' && (
<div <div className='operate__item' onClick={() => this.handleDelete(item)}>
className="operate__item" 删除
onClick={()=>this.handleDelete(item)} </div>
>删除</div> )}
}
</div> </div>
) );
} },
} },
]; ];
}else{ } else {
columns = [ columns = [
{ {
title: "直播课", title: '直播课',
width: "25%", width: '25%',
key: "course", key: 'course',
dataIndex: "courseName", dataIndex: 'courseName',
render: (val, record) => { render: (val, record) => {
let hasCover = false; let hasCover = false;
return ( return (
<div className="record__item"> <div className='record__item'>
{ {record.courseMediaVOS.map((item, index) => {
record.courseMediaVOS.map((item,index)=>{ if (item.contentType === 'COVER') {
if( item.contentType === "COVER"){ hasCover = true;
hasCover = true; return <img className='course-cover' src={item.mediaUrl} />;
return <img className="course-cover" src={item.mediaUrl} /> }
} })}
}) {!hasCover && <img className='course-cover' src={'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png'} />}
}
{ !hasCover &&
<img className="course-cover" src={'https://image.xiaomaiketang.com/xm/Yip2YtFDwH.png'} />
}
<div> <div>
{ record.courseName.length > 17? {record.courseName.length > 17 ? (
<Tooltip title={record.courseName}> <Tooltip title={record.courseName}>
<div className="course-name">{record.courseName}</div> <div className='course-name'>{record.courseName}</div>
</Tooltip> </Tooltip>
: ) : (
<div className="course-name">{record.courseName}</div> <div className='course-name'>{record.courseName}</div>
} )}
<div> <div>
<span className="course-time">{formatDate("YYYY-MM-DD H:i",parseInt(record.startTime))}~{formatDate("H:i", parseInt(record.endTime))}</span> <span className='course-time'>
<span className="course-status" style={{color:courseStateShow[record.courseState].color,border:`1px solid ${courseStateShow[record.courseState].color}`}}>{courseStateShow[record.courseState].title}</span> {formatDate('YYYY-MM-DD H:i', parseInt(record.startTime))}~{formatDate('H:i', parseInt(record.endTime))}
</div> </span>
<div className="teacher-assistant"> <span
{ record.teacherName.length > 4 ? className='course-status'
style={{ color: courseStateShow[record.courseState].color, border: `1px solid ${courseStateShow[record.courseState].color}` }}>
{courseStateShow[record.courseState].title}
</span>
</div>
<div className='teacher-assistant'>
{record.teacherName.length > 4 ? (
<Tooltip title={record.teacherName}> <Tooltip title={record.teacherName}>
<span className="teacher">讲师:{record.teacherName}</span> <span className='teacher'>讲师:{record.teacherName}</span>
</Tooltip> </Tooltip>
: ) : (
<span className="teacher">讲师:{record.teacherName}</span> <span className='teacher'>讲师:{record.teacherName}</span>
} )}
{record.admins.length > 0 && (
{ record.admins.length >0 && <>
<> <span className='split'> | </span>
<span className="split"> | </span> {this.handleAdminName(record.admins).length > 4 ? (
{ this.handleAdminName(record.admins).length > 4? <Tooltip title={this.handleAdminName(record.admins)}>
<Tooltip title={this.handleAdminName(record.admins)}> <span className='assistant'>
<span className="assistant">助教: 助教:
{ record.admins.map((item,index)=>{ {record.admins.map((item, index) => {
return <span>{item.adminName} { (index < record.admins.length-1)&&(<span></span>)} </span> return (
}) <span>
} {item.adminName} {index < record.admins.length - 1 && <span></span>}{' '}
</span>
);
})}
</span>
</Tooltip>
) : (
<span className='assistant'>
助教:
{record.admins.map((item, index) => {
return (
<span>
{item.adminName} {index < record.admins.length - 1 && <span></span>}{' '}
</span> </span>
</Tooltip> );
: })}
<span className="assistant">助教: </span>
{ record.admins.map((item,index)=>{ )}
return <span>{item.adminName} { (index < record.admins.length-1)&&(<span></span>)} </span> </>
}) )}
} </div>
</span>
}
</>
}
</div>
</div> </div>
</div> </div>
) );
} },
}, },
{ {
title: "课程分类", title: '课程分类',
width: "10%", width: '10%',
key: "couseCatalog", key: 'couseCatalog',
dataIndex: "couseCatalog", dataIndex: 'couseCatalog',
render: (val, item) => { render: (val, item) => {
return ( return <div className='categoryName'>{item.categoryName}</div>;
<div className="categoryName">{item.categoryName}</div>
)
}, },
}, },
{ {
title: "课件管理", title: '课件管理',
width: "8%", width: '8%',
key: "courseware", key: 'courseware',
dataIndex: "courseware", dataIndex: 'courseware',
render: (val, item) => { render: (val, item) => {
return ( return (
<span className="courseware" <span
className='courseware'
onClick={() => { onClick={() => {
this.setState({ this.setState({
editData: item, editData: item,
openCoursewareModal: true, openCoursewareModal: true,
}); });
}}>{item.courseDocumentCount}</span> }}>
{item.courseDocumentCount}
</span>
); );
}, },
}, },
{ {
title: '上课数据', title: '上课数据',
width: "9%", width: '9%',
key: "quota", key: 'quota',
dataIndex: "quota", dataIndex: 'quota',
render: (val, item) => { render: (val, item) => {
return ( return (
<span className="iconfont icon quota-icon" onClick={() => { <span
this.handleLinkToClassData(item) className='iconfont icon quota-icon'
}}>&#xe7d6;</span> onClick={() => {
this.handleLinkToClassData(item);
}}>
&#xe7d6;
</span>
); );
}, },
}, },
{ {
title: '创建时间', title: '创建时间',
width: "9%", width: '9%',
key: "created", key: 'created',
dataIndex: "created", dataIndex: 'created',
sorter: true, sorter: true,
render: (val, item) => { render: (val, item) => {
return ( return <span>{formatDate('YYYY-MM-DD H:i', val)}</span>;
<span>{formatDate('YYYY-MM-DD H:i', val)}</span>
);
}, },
}, },
{ {
title: '关联项', title: '关联项',
width: "15%", width: '15%',
key: "planList", key: 'planList',
dataIndex: "planList", dataIndex: 'planList',
render: (val, record) => { render: (val, record) => {
return ( return (
<div className="related-task"> <div className='related-task'>
{ record.relatedPlanList ? {record.relatedPlanList ? (
<Tooltip title={this.handlePlanName(record.relatedPlanList)} placement="top" arrowPointAtCenter> <Tooltip title={this.handlePlanName(record.relatedPlanList)} placement='top' arrowPointAtCenter>
{ record.relatedPlanList.map((item,index)=>{ {record.relatedPlanList.map((item, index) => {
return <span>{item.planName} { (index < record.relatedPlanList.length-1)&&(<span></span>)} </span> return (
}) <span>
} {item.planName} {index < record.relatedPlanList.length - 1 && <span></span>}{' '}
</Tooltip> </span>
: );
<span></span> })}
} </Tooltip>
) : (
<span></span>
)}
</div> </div>
) );
}, },
}, },
]; ];
} }
this.setState({ columns }) this.setState({ columns });
} };
handleAdminName = (adminArray)=>{ handleAdminName = (adminArray) => {
let adminStr = ""; let adminStr = '';
adminArray.map((item,index)=>{ adminArray.map((item, index) => {
if(index < adminArray.length-1){ if (index < adminArray.length - 1) {
adminStr = adminStr + item.adminName + '、'; adminStr = adminStr + item.adminName + '、';
}else{ } else {
adminStr = adminStr + item.adminName adminStr = adminStr + item.adminName;
} }
}) });
return adminStr return adminStr;
} };
handlePlanName = (planArray)=>{ handlePlanName = (planArray) => {
let planStr = ""; let planStr = '';
planArray.map((item,index)=>{ planArray.map((item, index) => {
if(index < planArray.length-1){ if (index < planArray.length - 1) {
planStr = planStr + item.planName + '、'; planStr = planStr + item.planName + '、';
}else{ } else {
planStr = planStr + item.planName planStr = planStr + item.planName;
} }
}) });
return planStr return planStr;
} };
renderMoreOperate = (item) => { renderMoreOperate = (item) => {
return ( return (
<div className="live-course-more-menu"> <div className='live-course-more-menu'>
{ (User.getUserRole() === "CloudManager" || User.getUserRole() === "StoreManager") && {(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') && (
<div <div className='operate__item' onClick={() => this.handleRelatedModalShow(item)}>
className="operate__item" 关联培训计划
onClick={()=>this.handleRelatedModalShow(item)} </div>
>关联培训计划</div> )}
} <div className='operate__item' onClick={() => this.toEditCoursePage(item)}>
<div 编辑
className="operate__item" </div>
onClick={()=>this.toEditCoursePage(item)} {item.courseState !== 'STARTING' && (
>编辑</div> <div className='operate__item' onClick={() => this.handleDelete(item)}>
{ item.courseState !=="STARTING" && 删除
<div </div>
className="operate__item" )}
onClick={()=>this.handleDelete(item)}
>删除</div>
}
</div> </div>
) );
} };
handleDelete = (record)=>{ handleDelete = (record) => {
return confirm({ return confirm({
title: '你确定要删除直播课?', title: '你确定要删除直播课?',
content: '删除后,学员将不能观看直播课/回放', content: '删除后,学员将不能观看直播课/回放',
icon: <span className="icon iconfont default-confirm-icon">&#xe839; </span>, icon: <span className='icon iconfont default-confirm-icon'>&#xe839; </span>,
okText: '删除', okText: '删除',
okType: 'danger', okType: 'danger',
cancelText: '取消', cancelText: '取消',
width:440, width: 440,
height:188, height: 188,
onOk: () => { onOk: () => {
this.deleteConfirm(record); this.deleteConfirm(record);
} },
}) });
} };
deleteConfirm = (item)=>{ deleteConfirm = (item) => {
const params={ const params = {
"liveCourseId": item.liveCourseId, liveCourseId: item.liveCourseId,
} };
CourseService.delLiveCloudCourse(params).then((res)=>{ CourseService.delLiveCloudCourse(params).then((res) => {
if(res.success){ if (res.success) {
message.success("已删除"); message.success('已删除');
this.props.onChange(); this.props.onChange();
} }
}) });
} };
toEditCoursePage =(item)=>{ toEditCoursePage = (item) => {
window.RCHistory.push({ window.RCHistory.push({
pathname: `/create-live-course?type=edit&id=${item.liveCourseId}`, pathname: `/create-live-course?type=edit&id=${item.liveCourseId}`,
}) });
} };
refreshCourseList = ()=>{ refreshCourseList = () => {
this.props.onChange(this.props.query); this.props.onChange(this.props.query);
} };
//进入直播间 //进入直播间
handleEnterLiveRoom = (item) => { handleEnterLiveRoom = (item) => {
if (item.startTime - Date.now() > 1800000) { if (item.startTime - Date.now() > 1800000) {
Modal.warning({ Modal.warning({
title: "你来得太早了", title: '你来得太早了',
okText: '我知道了', okText: '我知道了',
content: "请于开始上课前30分钟来直播上课。", content: '请于开始上课前30分钟来直播上课。',
icon: ( icon: (
<span <span className='icon iconfont default-confirm-icon' style={{ color: '#FFBB54 !important' }}>
className="icon iconfont default-confirm-icon" &#xe834;
style={{ color: "#FFBB54 !important" }}
>
&#xe834;
</span> </span>
), ),
}); });
} else { } else {
CourseService.getLiveCloudCourseDetail({ CourseService.getLiveCloudCourseDetail({
liveCourseId: item.liveCourseId, liveCourseId: item.liveCourseId,
}) }).then((res) => {
.then((res) => { const url = `xmqx://liveCourseId=${item.liveCourseId}`;
const url = `xmqx://liveCourseId=${item.liveCourseId}`; if (res.result.courseState === 'FINISH') {
if (res.result.courseState === "FINISH") { Modal.warning({
Modal.warning({ title: '刷新页面',
title: "刷新页面", icon: <QuestionCircleOutlined />,
icon: <QuestionCircleOutlined />, content: '课次已结束,请刷新一下',
content: "课次已结束,请刷新一下", onOk: () => {
onOk: () => { this.refreshCourseList();
this.refreshCourseList(); },
} });
}); } else {
} else { this.setState({ url, openDownloadModal: true });
this.setState({ url, openDownloadModal: true }); }
} });
});
} }
} };
onShowSizeChange = (current, size) => { onShowSizeChange = (current, size) => {
if (current == size) { if (current == size) {
return return;
} }
let _query = this.props.query let _query = this.props.query;
_query.size = size; _query.size = size;
this.props.onChange(_query) this.props.onChange(_query);
} };
getDownloadVersion() { getDownloadVersion() {
const isMac = /macintosh|mac os x/i.test(navigator.userAgent); const isMac = /macintosh|mac os x/i.test(navigator.userAgent);
// 判断学员系统 // 判断学员系统
let platform; let platform;
if(!isMac){ if (!isMac) {
platform = 1 platform = 1;
}else{ } else {
platform = 4 platform = 4;
} }
BaseService BaseService.getLastedVersion({ model: 5, platform }).then((res) => {
.getLastedVersion({ model: 5, platform})
.then((res) => {
const { result = {} } = res; const { result = {} } = res;
this.setState({ downloadUrl: result.releaseUrl }); this.setState({ downloadUrl: result.releaseUrl });
}) });
} }
handleViewPlayBack = (item) => { handleViewPlayBack = (item) => {
let htmlUrl; let htmlUrl;
if(item.teacherId === User.getUserId()){ if (item.teacherId === User.getUserId()) {
htmlUrl = `${LIVE_SHARE}replay/${item.liveCourseId}?teacherId=${User.getUserId()}&id=${User.getStoreId()}`; htmlUrl = `${LIVE_SHARE}replay/${item.liveCourseId}?teacherId=${User.getUserId()}&id=${User.getStoreId()}`;
}else if(_.pluck(item.admins, "adminId").includes(User.getUserId())){ } else if (_.pluck(item.admins, 'adminId').includes(User.getUserId())) {
htmlUrl = `${LIVE_SHARE}replay/${item.liveCourseId}?userId=${User.getUserId()}&id=${User.getStoreId()}`; htmlUrl = `${LIVE_SHARE}replay/${item.liveCourseId}?userId=${User.getUserId()}&id=${User.getStoreId()}`;
}else{ } else {
htmlUrl = `${LIVE_SHARE}replay/${item.liveCourseId}?id=${User.getStoreId()}`; htmlUrl = `${LIVE_SHARE}replay/${item.liveCourseId}?id=${User.getStoreId()}`;
} }
window.open(htmlUrl); window.open(htmlUrl);
} };
handleRelatedModalShow = (item)=>{ handleRelatedModalShow = (item) => {
const selectPlanList = {}; const selectPlanList = {};
if(item.relatedPlanList){ if (item.relatedPlanList) {
item.relatedPlanList.map((item,index)=>{ item.relatedPlanList.map((item, index) => {
selectPlanList[item.planId] = {} selectPlanList[item.planId] = {};
selectPlanList[item.planId].planId = item.planId; selectPlanList[item.planId].planId = item.planId;
selectPlanList[item.planId].taskBaseVOList = [{taskId:item.taskId}]; selectPlanList[item.planId].taskBaseVOList = [{ taskId: item.taskId }];
return item return item;
}) });
} }
this.setState({ this.setState({
RelatedPlanModalVisible:true, RelatedPlanModalVisible: true,
selectCourseId:item.liveCourseId, selectCourseId: item.liveCourseId,
selectPlanList:selectPlanList selectPlanList: selectPlanList,
}) });
} };
closeRelatedPlanModalVisible = ()=>{ closeRelatedPlanModalVisible = () => {
this.setState({
RelatedPlanModalVisible:false
})
}
onChangeSelectPlanList = (selectPlanList)=>{
this.setState({ this.setState({
selectPlanList:selectPlanList RelatedPlanModalVisible: false,
}) });
} };
onConfirmSelectPlanList = ()=>{ onChangeSelectPlanList = (selectPlanList) => {
this.setState({ this.setState({
RelatedPlanModalVisible:false selectPlanList: selectPlanList,
},()=>{this.props.onChange();}) });
} };
onConfirmSelectPlanList = () => {
this.setState(
{
RelatedPlanModalVisible: false,
},
() => {
this.props.onChange();
}
);
};
handleChangeTable = (pagination, filters, sorter) => { handleChangeTable = (pagination, filters, sorter) => {
const { columnKey, order } = sorter; const { columnKey, order } = sorter;
const { query } = this.props; const { query } = this.props;
let _columnKey; let _columnKey;
let _order; let _order;
// 按创建时间升序排序 // 按创建时间升序排序
if (columnKey === 'created' && order === 'ascend') {_columnKey="CREATED"; _order = 'SORT_ASC'; } if (columnKey === 'created' && order === 'ascend') {
_columnKey = 'CREATED';
_order = 'SORT_ASC';
}
// 按创建时间降序排序 // 按创建时间降序排序
if (columnKey === 'created' && order === 'descend') { _columnKey="CREATED"; _order = 'SORT_DESC';} if (columnKey === 'created' && order === 'descend') {
_columnKey = 'CREATED';
_order = 'SORT_DESC';
}
const _query = { const _query = {
...query, ...query,
sortMap:{} sortMap: {},
}; };
_query.sortMap[_columnKey]=_order; _query.sortMap[_columnKey] = _order;
this.props.onChange(_query); this.props.onChange(_query);
} };
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 { openDownloadModal, downloadUrl, url, columns, openCoursewareModal, editData, RelatedPlanModalVisible, selectCourseId, selectPlanList } = this.state;
downloadUrl, url, columns,
openCoursewareModal,
editData,
RelatedPlanModalVisible,
selectCourseId,
selectPlanList
} = this.state;
const { match } = this.props; const { match } = this.props;
return ( return (
<div className="live-course-list"> <div className='live-course-list'>
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
bordered bordered
size="middle" size='middle'
pagination={false} pagination={false}
columns={columns} columns={columns}
loading={loading} loading={loading}
...@@ -758,21 +797,21 @@ class LiveCourseList extends React.Component { ...@@ -758,21 +797,21 @@ class LiveCourseList extends React.Component {
onChange={this.handleChangeTable} onChange={this.handleChangeTable}
rowKey={(row) => row.liveCourseId} rowKey={(row) => row.liveCourseId}
/> />
{ total>0 && {total > 0 && (
<div className="box-footer"> <div className='box-footer'>
<PageControl <PageControl
current={current - 1} current={current - 1}
pageSize={size} pageSize={size}
total={parseInt(total)} total={parseInt(total)}
toPage={(page) => { toPage={(page) => {
const _query = {...query, current: page + 1}; const _query = { ...query, current: page + 1 };
this.props.onChange(_query) this.props.onChange(_query);
}} }}
onShowSizeChange={this.onShowSizeChange} onShowSizeChange={this.onShowSizeChange}
/> />
</div> </div>
} )}
{ this.state.shareLiveModal } {this.state.shareLiveModal}
{openCoursewareModal && ( {openCoursewareModal && (
<ManageCoursewareModal <ManageCoursewareModal
data={editData} data={editData}
...@@ -789,13 +828,13 @@ class LiveCourseList extends React.Component { ...@@ -789,13 +828,13 @@ class LiveCourseList extends React.Component {
onCancel={() => { onCancel={() => {
this.setState({ this.setState({
url: '', url: '',
openDownloadModal: openDownloadModal: false,
false }); });
}} }}
/> />
)} )}
{ RelatedPlanModalVisible && {RelatedPlanModalVisible && (
<RelatedPlanModal <RelatedPlanModal
onClose={this.closeRelatedPlanModalVisible} onClose={this.closeRelatedPlanModalVisible}
visible={RelatedPlanModalVisible} visible={RelatedPlanModalVisible}
selectCourseId={selectCourseId} selectCourseId={selectCourseId}
...@@ -803,12 +842,12 @@ class LiveCourseList extends React.Component { ...@@ -803,12 +842,12 @@ class LiveCourseList extends React.Component {
onChange={this.onChangeSelectPlanList} onChange={this.onChangeSelectPlanList}
onConfirm={this.onConfirmSelectPlanList} onConfirm={this.onConfirmSelectPlanList}
/> />
} )}
<iframe src={url} style={{ display: "none" }} /> <iframe src={url} style={{ display: 'none' }} />
<Route path={`${match.url}/live-course-data`} component={DataList} /> <Route path={`${match.url}/live-course-data`} component={DataList} />
</div> </div>
) );
} }
} }
export default withRouter(LiveCourseList); export default withRouter(LiveCourseList);
\ No newline at end of file
...@@ -6,37 +6,29 @@ ...@@ -6,37 +6,29 @@
* @Description: 视频课-列表模块 * @Description: 视频课-列表模块
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
*/ */
import React from 'react'; import User from '@/common/js/user';
import { Table, Modal, message , Tooltip,Switch,Dropdown} from 'antd'; import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components';
import { PageControl } from "@/components"; import { appId, LIVE_SHARE } from '@/domains/course-domain/constants';
import { LIVE_SHARE_MAP } from '@/common/constants/academic/cloudClass'; import CourseService from '@/domains/course-domain/CourseService';
import { appId, shareUrl, LIVE_SHARE } from '@/domains/course-domain/constants';
import ShareLiveModal from '@/modules/course-manage/modal/ShareLiveModal'; import ShareLiveModal from '@/modules/course-manage/modal/ShareLiveModal';
import WatchDataModal from '../modal/WatchDataModal' import { Dropdown, message, Modal, Switch, Tooltip } from 'antd';
import CourseService from "@/domains/course-domain/CourseService"; import React from 'react';
import RelatedPlanModal from '../../modal/RelatedPlanModal'; import RelatedPlanModal from '../../modal/RelatedPlanModal';
import WatchDataModal from '../modal/WatchDataModal';
import User from '@/common/js/user'
import './GraphicsCourseList.less'; import './GraphicsCourseList.less';
const ENV = process.env.DEPLOY_ENV || 'dev';
const defaultCoverUrl = 'https://image.xiaomaiketang.com/xm/wFnpZtp2yB.png'; const defaultCoverUrl = 'https://image.xiaomaiketang.com/xm/wFnpZtp2yB.png';
class GraphicsCourseList extends React.Component { class GraphicsCourseList extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
id: '', // 视频课ID id: '', // 视频课ID
studentIds:[], studentIds: [],
RelatedPlanModalVisible:false, RelatedPlanModalVisible: false,
selectPlanList:{} selectPlanList: {},
} };
} }
componentDidMount() { componentDidMount() {
...@@ -46,7 +38,7 @@ class GraphicsCourseList extends React.Component { ...@@ -46,7 +38,7 @@ class GraphicsCourseList extends React.Component {
this.handleShowShareModal(_videoCourseItem, true); this.handleShowShareModal(_videoCourseItem, true);
} }
} }
// 观看数据弹窗 // 观看数据弹窗
handleShowWatchDataModal = (record) => { handleShowWatchDataModal = (record) => {
const watchDataModal = ( const watchDataModal = (
...@@ -55,25 +47,25 @@ class GraphicsCourseList extends React.Component { ...@@ -55,25 +47,25 @@ class GraphicsCourseList extends React.Component {
data={record} data={record}
close={() => { close={() => {
this.setState({ this.setState({
watchDataModal: null watchDataModal: null,
}); });
}} }}
/> />
); );
this.setState({ watchDataModal }); this.setState({ watchDataModal });
} };
handlePlanName = (planArray)=>{ handlePlanName = (planArray) => {
let planStr = ""; let planStr = '';
planArray.map((item,index)=>{ planArray.map((item, index) => {
if(index < planArray.length-1){ if (index < planArray.length - 1) {
planStr = planStr + item.planName + '、'; planStr = planStr + item.planName + '、';
}else{ } else {
planStr = planStr + item.planName planStr = planStr + item.planName;
} }
}) });
return planStr return planStr;
} };
// 请求表头 // 请求表头
parseColumns = () => { parseColumns = () => {
const columns = [ const columns = [
...@@ -81,24 +73,24 @@ class GraphicsCourseList extends React.Component { ...@@ -81,24 +73,24 @@ class GraphicsCourseList extends React.Component {
title: '图文课', title: '图文课',
key: 'scheduleName', key: 'scheduleName',
dataIndex: 'scheduleName', dataIndex: 'scheduleName',
width:321, width: 321,
fixed: 'left', fixed: 'left',
render: (val, record) => { render: (val, record) => {
const { coverUrl, scheduleVideoUrl } = record; const { coverUrl, scheduleVideoUrl } = record;
return ( return (
<div className="record__item"> <div className='record__item'>
{/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */} {/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */}
<img className="course-cover" src={coverUrl || defaultCoverUrl} /> <img className='course-cover' src={coverUrl || defaultCoverUrl} />
{ record.courseName.length > 25? {record.courseName.length > 25 ? (
<Tooltip title={record.courseName}> <Tooltip title={record.courseName}>
<div className="course-name">{record.courseName}</div> <div className='course-name'>{record.courseName}</div>
</Tooltip> </Tooltip>
: ) : (
<div className="course-name">{record.courseName}</div> <div className='course-name'>{record.courseName}</div>
} )}
</div> </div>
) );
} },
}, },
{ {
title: '课程分类', title: '课程分类',
...@@ -107,11 +99,12 @@ class GraphicsCourseList extends React.Component { ...@@ -107,11 +99,12 @@ class GraphicsCourseList extends React.Component {
width: 120, width: 120,
render: (val, record) => { render: (val, record) => {
return ( return (
<div className="record__item"> <div className='record__item'>
{record.categoryOneName}{ record.categoryTwoName?`-${record.categoryTwoName}`:''} {record.categoryOneName}
{record.categoryTwoName ? `-${record.categoryTwoName}` : ''}
</div> </div>
) );
} },
}, },
{ {
title: '创建人', title: '创建人',
...@@ -120,42 +113,47 @@ class GraphicsCourseList extends React.Component { ...@@ -120,42 +113,47 @@ class GraphicsCourseList extends React.Component {
width: 100, width: 100,
render: (val) => { render: (val) => {
return ( return (
<div> <div>
{ val && {val && (
<Tooltip title={val}> <Tooltip title={val}>
<div> <div>{val.length > 4 ? `${val.slice(0, 4)}...` : val}</div>
{val.length > 4 ? `${val.slice(0,4)}...` : val}
</div>
</Tooltip> </Tooltip>
} )}
</div> </div>
) );
} },
}, },
{ {
title: <span> title: (
<span>学院展示</span> <span>
<Tooltip title={<div>开启后,学员可在学院内查看到此课程。<br/>关闭后,学院内不再展示此课程,但学员仍可通过分享的海报/链接查看此课程。</div>}><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px',fontWeight:'normal'}}>&#xe61d;</i></Tooltip> <span>学院展示</span>
</span>, <Tooltip
title={
<div>
开启后,学员可在学院内查看到此课程。
<br />
关闭后,学院内不再展示此课程,但学员仍可通过分享的海报/链接查看此课程。
</div>
}>
<i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px', fontWeight: 'normal' }}>
&#xe61d;
</i>
</Tooltip>
</span>
),
width: 120, width: 120,
dataIndex: "courseware", dataIndex: 'courseware',
render: (val, item, index) => { render: (val, item, index) => {
return ( return <Switch defaultChecked={item.shelfState === 'YES' ? true : false} onChange={() => this.changeShelfState(item)} />;
<Switch defaultChecked={item.shelfState==="YES"?true:false} onChange={()=>this.changeShelfState(item)}/>
)
}, },
}, },
{ {
title: "观看学员数", title: '观看学员数',
width: 110, width: 110,
key: "watchUserCount", key: 'watchUserCount',
dataIndex: "watchUserCount", dataIndex: 'watchUserCount',
render: (val, item) => { render: (val, item) => {
return ( return <div className='watchUserCount'>{val}</div>;
<div className="watchUserCount">{val}</div>
)
}, },
}, },
{ {
...@@ -165,8 +163,8 @@ class GraphicsCourseList extends React.Component { ...@@ -165,8 +163,8 @@ class GraphicsCourseList extends React.Component {
dataIndex: 'created', dataIndex: 'created',
sorter: true, sorter: true,
render: (val) => { render: (val) => {
return formatDate('YYYY-MM-DD H:i', val) return formatDate('YYYY-MM-DD H:i', val);
} },
}, },
{ {
title: '最近修改时间', title: '最近修改时间',
...@@ -175,30 +173,33 @@ class GraphicsCourseList extends React.Component { ...@@ -175,30 +173,33 @@ class GraphicsCourseList extends React.Component {
dataIndex: 'updated', dataIndex: 'updated',
sorter: true, sorter: true,
render: (val) => { render: (val) => {
return formatDate('YYYY-MM-DD H:i', val) return formatDate('YYYY-MM-DD H:i', val);
} },
}, },
{ {
title: '关联项', title: '关联项',
width: 200, width: 200,
key: "planList", key: 'planList',
dataIndex: "planList", dataIndex: 'planList',
render: (val, record) => { render: (val, record) => {
return ( return (
<div className="related-task"> <div className='related-task'>
{ record.relatedPlanList ? {record.relatedPlanList ? (
<Tooltip title={this.handlePlanName(record.relatedPlanList)} placement="top" arrowPointAtCenter> <Tooltip title={this.handlePlanName(record.relatedPlanList)} placement='top' arrowPointAtCenter>
{ record.relatedPlanList.map((item,index)=>{ {record.relatedPlanList.map((item, index) => {
return <span>{item.planName} { (index < record.relatedPlanList.length-1)&&(<span></span>)} </span> return (
}) <span>
} {item.planName} {index < record.relatedPlanList.length - 1 && <span></span>}{' '}
</Tooltip> </span>
: );
<span></span> })}
} </Tooltip>
</div> ) : (
) <span></span>
} )}
</div>
);
},
}, },
{ {
title: '操作', title: '操作',
...@@ -208,148 +209,150 @@ class GraphicsCourseList extends React.Component { ...@@ -208,148 +209,150 @@ class GraphicsCourseList extends React.Component {
fixed: 'right', fixed: 'right',
render: (val, record) => { render: (val, record) => {
return ( return (
<div className="operate"> <div className='operate'>
<div className="operate__item" onClick={()=>this.handleShowWatchDataModal(record)}>观看数据</div> <div className='operate__item' onClick={() => this.handleShowWatchDataModal(record)}>
<span className="operate__item split"> | </span> 观看数据
<div className="operate__item" onClick={() => this.handleShowShareModal(record)}>分享</div> </div>
<span className="operate__item split"> | </span> <span className='operate__item split'> | </span>
<div className='operate__item' onClick={() => this.handleShowShareModal(record)}>
分享
</div>
<span className='operate__item split'> | </span>
<Dropdown overlay={this.renderMoreOperate(record)}> <Dropdown overlay={this.renderMoreOperate(record)}>
<span className="more-operate"> <span className='more-operate'>
<span className="operate-text">更多</span> <span className='operate-text'>更多</span>
<span <span className='iconfont icon' style={{ color: '#2966FF' }}>
className="iconfont icon"
style={{ color: "#2966FF" }}
>
&#xe824; &#xe824;
</span> </span>
</span> </span>
</Dropdown> </Dropdown>
</div> </div>
) );
} },
} },
]; ];
return columns; return columns;
} };
handleRelatedModalShow = (item) => { handleRelatedModalShow = (item) => {
const selectPlanList = {}; const selectPlanList = {};
if(item.relatedPlanList){ if (item.relatedPlanList) {
item.relatedPlanList.map((item, index) => { item.relatedPlanList.map((item, index) => {
selectPlanList[item.planId] = {} selectPlanList[item.planId] = {};
selectPlanList[item.planId].planId = item.planId; selectPlanList[item.planId].planId = item.planId;
selectPlanList[item.planId].taskBaseVOList = [{ taskId: item.taskId }]; selectPlanList[item.planId].taskBaseVOList = [{ taskId: item.taskId }];
return item return item;
}) });
} }
this.setState({ this.setState({
RelatedPlanModalVisible: true, RelatedPlanModalVisible: true,
selectCourseId: item.id, selectCourseId: item.id,
selectPlanList: selectPlanList, selectPlanList: selectPlanList,
}) });
} };
closeRelatedPlanModalVisible = ()=>{ closeRelatedPlanModalVisible = () => {
this.setState({ this.setState({
RelatedPlanModalVisible: false RelatedPlanModalVisible: false,
}) });
} };
onChangeSelectPlanList = (selectPlanList) => { onChangeSelectPlanList = (selectPlanList) => {
this.setState({ this.setState({
selectPlanList: selectPlanList selectPlanList: selectPlanList,
}) });
} };
onConfirmSelectPlanList = () => { onConfirmSelectPlanList = () => {
this.setState({ this.setState(
RelatedPlanModalVisible: false {
}, () => { this.props.onChange(); }); RelatedPlanModalVisible: false,
} },
() => {
this.props.onChange();
}
);
};
renderMoreOperate = (item) => { renderMoreOperate = (item) => {
return ( return (
<div className="live-course-more-menu"> <div className='live-course-more-menu'>
{(User.getUserRole() === "CloudManager" || User.getUserRole() === "StoreManager") && {(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') && (
<div <div
className="operate__item" className='operate__item'
key="plan" key='plan'
onClick={() => { onClick={() => {
this.handleRelatedModalShow(item); this.handleRelatedModalShow(item);
}} }}>
>关联培训计划</div> 关联培训计划
} </div>
)}
<div <div
className="operate__item" className='operate__item'
key="edit" key='edit'
onClick={() => { onClick={() => {
RCHistory.push(`/create-graphics-course?type=edit&id=${item.id}`); RCHistory.push(`/create-graphics-course?type=edit&id=${item.id}`);
}} }}>
>编辑</div> 编辑
<div </div>
className="operate__item" <div className='operate__item' key='delete' onClick={() => this.handleDeleteGraphicsCourse(item.id)}>
key="delete" 删除
onClick={() => this.handleDeleteGraphicsCourse(item.id)} </div>
>删除</div>
</div> </div>
) );
} };
//改变上架状态 //改变上架状态
changeShelfState = (item) =>{ changeShelfState = (item) => {
let _shelfState = item.shelfState let _shelfState = item.shelfState;
if(_shelfState==='NO'){ if (_shelfState === 'NO') {
_shelfState = "YES"; _shelfState = 'YES';
item.shelfState = "YES" item.shelfState = 'YES';
}else{ } else {
_shelfState = "NO" _shelfState = 'NO';
item.shelfState = "NO" item.shelfState = 'NO';
} }
const params={ const params = {
courseId: item.id, courseId: item.id,
shelfState:_shelfState shelfState: _shelfState,
} };
CourseService.changeVideoShelfState(params).then((res)=>{ CourseService.changeVideoShelfState(params).then((res) => {
if(res.success){ if (res.success) {
if(_shelfState === "YES"){ if (_shelfState === 'YES') {
message.success("已开启展示"); message.success('已开启展示');
}else{ } else {
message.success("已取消展示"); message.success('已取消展示');
} }
} }
}) });
} };
// 删除视频课 // 删除视频课
handleDeleteGraphicsCourse = (scheduleId) => { handleDeleteGraphicsCourse = (scheduleId) => {
Modal.confirm({ Modal.confirm({
title: '你确定要删除此视频课吗?', title: '你确定要删除此视频课吗?',
content: '删除后,学员将不能进行观看。', content: '删除后,学员将不能进行观看。',
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>, icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
okText: '确定', okText: '确定',
okType: 'danger', okType: 'danger',
cancelText: '取消', cancelText: '取消',
onOk: () => { onOk: () => {
const param ={ const param = {
courseId:scheduleId, courseId: scheduleId,
storeId:User.getStoreId() storeId: User.getStoreId(),
} };
CourseService.delVideoSchedule( CourseService.delVideoSchedule(param).then(() => {
param
).then(() => {
message.success('删除成功'); message.success('删除成功');
this.props.onChange(); this.props.onChange();
}) });
} },
}); });
} };
// 显示分享弹窗 // 显示分享弹窗
handleShowShareModal = (record, needStr = false) => { handleShowShareModal = (record, needStr = false) => {
const { id, scheduleVideoUrl } = record; const { id, scheduleVideoUrl } = record;
const _appId = appId; const _appId = appId;
const htmlUrl = `${LIVE_SHARE}graphics_detail/${id}?id=${User.getStoreId()}`; const htmlUrl = `${LIVE_SHARE}graphics_detail/${id}?id=${User.getStoreId()}`;
const longUrl = htmlUrl; const longUrl = htmlUrl;
const { coverUrl, courseName } = record; const { coverUrl, courseName } = record;
...@@ -364,11 +367,11 @@ class GraphicsCourseList extends React.Component { ...@@ -364,11 +367,11 @@ class GraphicsCourseList extends React.Component {
<ShareLiveModal <ShareLiveModal
needStr={needStr} needStr={needStr}
data={shareData} data={shareData}
type="graphicsClass" type='graphicsClass'
title="图文课" title='图文课'
close={() => { close={() => {
this.setState({ this.setState({
shareLiveModal: null shareLiveModal: null,
}); });
localStorage.setItem('videoCourseItem', ''); localStorage.setItem('videoCourseItem', '');
}} }}
...@@ -376,89 +379,106 @@ class GraphicsCourseList extends React.Component { ...@@ -376,89 +379,106 @@ class GraphicsCourseList extends React.Component {
); );
this.setState({ shareLiveModal }); this.setState({ shareLiveModal });
} };
handleChangeTable = (pagination, filters, sorter) => { handleChangeTable = (pagination, filters, sorter) => {
const { columnKey, order } = sorter; const { columnKey, order } = sorter;
const { query } = this.props; const { query } = this.props;
let { order: _order } =query; let { order: _order } = query;
// 按创建时间升序排序 // 按创建时间升序排序
if (columnKey === 'created' && order === 'ascend') { _order = 'CREATED_ASC'; } if (columnKey === 'created' && order === 'ascend') {
_order = 'CREATED_ASC';
}
// 按创建时间降序排序 // 按创建时间降序排序
if (columnKey === 'created' && order === 'descend') { _order = 'CREATED_DESC'; } if (columnKey === 'created' && order === 'descend') {
_order = 'CREATED_DESC';
}
// 按更新时间升序排序 // 按更新时间升序排序
if (columnKey === 'updated' && order === 'ascend') { _order = 'UPDATED_ASC'; } if (columnKey === 'updated' && order === 'ascend') {
_order = 'UPDATED_ASC';
}
// 按更新时间降序排序 // 按更新时间降序排序
if (columnKey === 'updated' && order === 'descend') { _order = 'UPDATED_DESC'; } if (columnKey === 'updated' && order === 'descend') {
_order = 'UPDATED_DESC';
}
const _query = { const _query = {
...query, ...query,
orderEnum: _order orderEnum: _order,
}; };
this.props.onChange(_query); this.props.onChange(_query);
} };
handleRelatedModalShow = (item)=>{ handleRelatedModalShow = (item) => {
const selectPlanList = {}; const selectPlanList = {};
if(item.relatedPlanList){ if (item.relatedPlanList) {
item.relatedPlanList.map((item,index)=>{ item.relatedPlanList.map((item, index) => {
selectPlanList[item.planId] = {} selectPlanList[item.planId] = {};
selectPlanList[item.planId].planId = item.planId; selectPlanList[item.planId].planId = item.planId;
selectPlanList[item.planId].taskBaseVOList = [{taskId:item.taskId}]; selectPlanList[item.planId].taskBaseVOList = [{ taskId: item.taskId }];
return item return item;
}) });
} }
this.setState({ this.setState({
RelatedPlanModalVisible:true, RelatedPlanModalVisible: true,
selectCourseId:item.id, selectCourseId: item.id,
selectPlanList:selectPlanList selectPlanList: selectPlanList,
}) });
} };
closeRelatedPlanModalVisible = ()=>{ closeRelatedPlanModalVisible = () => {
this.setState({
RelatedPlanModalVisible:false
})
}
onChangeSelectPlanList = (selectPlanList)=>{
this.setState({ this.setState({
selectPlanList:selectPlanList RelatedPlanModalVisible: false,
}) });
} };
onConfirmSelectPlanList = ()=>{ onChangeSelectPlanList = (selectPlanList) => {
this.setState({ this.setState({
RelatedPlanModalVisible:false selectPlanList: selectPlanList,
},()=>{this.props.onChange();}) });
} };
onConfirmSelectPlanList = () => {
this.setState(
{
RelatedPlanModalVisible: false,
},
() => {
this.props.onChange();
}
);
};
render() { render() {
const { RelatedPlanModalVisible, selectCourseId, selectPlanList } = this.state; const { RelatedPlanModalVisible, selectCourseId, selectPlanList } = this.state;
const { dataSource = [], totalCount, query } = this.props; const { dataSource = [], totalCount, query } = this.props;
const { current, size } = query; const { current, size } = query;
return ( return (
<div className="video-course-list"> <div className='video-course-list'>
<Table <XMTable
rowKey={record => record.id} renderEmpty={{
image: college,
description: '暂无数据',
}}
rowKey={(record) => record.id}
dataSource={dataSource} dataSource={dataSource}
columns={this.parseColumns()} columns={this.parseColumns()}
onChange={this.handleChangeTable} onChange={this.handleChangeTable}
pagination={false} pagination={false}
scroll={{ x: 1500}} scroll={{ x: 1500 }}
bordered bordered
className="video-list-table" className='video-list-table'
/> />
<div className="box-footer"> <div className='box-footer'>
<PageControl <PageControl
current={current - 1} current={current - 1}
pageSize={size} pageSize={size}
total={totalCount} total={totalCount}
toPage={(page) => { toPage={(page) => {
const _query = {...query, current: page + 1}; const _query = { ...query, current: page + 1 };
this.props.onChange(_query) this.props.onChange(_query);
}} }}
/> />
</div> </div>
{RelatedPlanModalVisible && {RelatedPlanModalVisible && (
<RelatedPlanModal <RelatedPlanModal
onClose={this.closeRelatedPlanModalVisible} onClose={this.closeRelatedPlanModalVisible}
visible={RelatedPlanModalVisible} visible={RelatedPlanModalVisible}
selectCourseId={selectCourseId} selectCourseId={selectCourseId}
...@@ -466,9 +486,9 @@ class GraphicsCourseList extends React.Component { ...@@ -466,9 +486,9 @@ class GraphicsCourseList extends React.Component {
onChange={this.onChangeSelectPlanList} onChange={this.onChangeSelectPlanList}
onConfirm={this.onConfirmSelectPlanList} onConfirm={this.onConfirmSelectPlanList}
/> />
} )}
{ RelatedPlanModalVisible && {RelatedPlanModalVisible && (
<RelatedPlanModal <RelatedPlanModal
onClose={this.closeRelatedPlanModalVisible} onClose={this.closeRelatedPlanModalVisible}
visible={RelatedPlanModalVisible} visible={RelatedPlanModalVisible}
selectCourseId={selectCourseId} selectCourseId={selectCourseId}
...@@ -476,11 +496,11 @@ class GraphicsCourseList extends React.Component { ...@@ -476,11 +496,11 @@ class GraphicsCourseList extends React.Component {
onChange={this.onChangeSelectPlanList} onChange={this.onChangeSelectPlanList}
onConfirm={this.onConfirmSelectPlanList} onConfirm={this.onConfirmSelectPlanList}
/> />
} )}
{ this.state.shareLiveModal } {this.state.shareLiveModal}
{ this.state.watchDataModal } {this.state.watchDataModal}
</div> </div>
) );
} }
} }
......
/* /*
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-05-19 11:01:31 * @Date: 2020-05-19 11:01:31
* @Last Modified by: chenshu * @Last Modified by: chenshu
* @Last Modified time: 2021-03-24 15:13:38 * @Last Modified time: 2021-03-24 15:13:38
* @Description 余额异常弹窗 * @Description 余额异常弹窗
*/ */
import React from 'react'; import React from 'react';
import {Table, Modal,Input} from 'antd'; import { Modal, Input } from 'antd';
import { PageControl } from "@/components"; import college from '@/common/lottie/college';
import Service from "@/common/js/service"; import { PageControl, XMTable } from '@/components';
import User from '@/common/js/user' import Service from '@/common/js/service';
import User from '@/common/js/user';
import './WatchDataModal.less'; import './WatchDataModal.less';
import dealTimeDuration from "../../utils/dealTimeDuration"; import dealTimeDuration from '../../utils/dealTimeDuration';
const { Search } = Input; const { Search } = Input;
class WatchDataModal extends React.Component { class WatchDataModal extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
visible:true, visible: true,
dataSource:[], dataSource: [],
size:10, size: 10,
query: { query: {
current: 1, current: 1,
}, },
totalCount:0 totalCount: 0,
}; };
} }
componentDidMount() { componentDidMount() {
this.handleFetchDataList(); this.handleFetchDataList();
} }
onClose = () =>{ onClose = () => {
this.props.close(); this.props.close();
} };
// 获取观看视频数据列表 // 获取观看视频数据列表
handleFetchDataList = () => { handleFetchDataList = () => {
const {query,size,totalCount} = this.state const { query, size, totalCount } = this.state;
const { id } = this.props.data; const { id } = this.props.data;
const params ={ const params = {
...query, ...query,
size, size,
courseId:id, courseId: id,
storeId:User.getStoreId() storeId: User.getStoreId(),
} };
Service.Hades('public/hades/mediaCourseWatchInfo', params).then((res) => { Service.Hades('public/hades/mediaCourseWatchInfo', params).then((res) => {
const { result = {} } = res ; const { result = {} } = res;
const { records = [], total = 0 } = result; const { records = [], total = 0 } = result;
this.setState({ this.setState({
dataSource: records, dataSource: records,
totalCount: Number(total) totalCount: Number(total),
}); });
}); });
} };
handleChangNickname = (value)=>{ handleChangNickname = (value) => {
const isPhone = (value || '').match(/^\d+$/); const isPhone = (value || '').match(/^\d+$/);
const { query } = this.state; const { query } = this.state;
if(isPhone){ if (isPhone) {
query.phone = value; query.phone = value;
query.nickName = null; query.nickName = null;
}else{ } else {
query.nickName = value; query.nickName = value;
query.phone = null; query.phone = null;
} }
query.current = 1; query.current = 1;
this.setState({ this.setState({
query query,
}) });
} };
onShowSizeChange = (current, size) => { onShowSizeChange = (current, size) => {
if (current == size) { if (current == size) {
return return;
} }
this.setState({ this.setState(
size {
},()=>{this.handleFetchDataList()}) size,
} },
() => {
this.handleFetchDataList();
}
);
};
// 请求表头 // 请求表头
parseColumns = () => { parseColumns = () => {
...@@ -86,92 +92,110 @@ class WatchDataModal extends React.Component { ...@@ -86,92 +92,110 @@ class WatchDataModal extends React.Component {
{ {
title: '观看学员', title: '观看学员',
key: 'name', key: 'name',
dataIndex: 'name' dataIndex: 'name',
}, },
{ {
title: '手机号', title: '手机号',
key: 'phone', key: 'phone',
dataIndex: 'phone' dataIndex: 'phone',
}, },
{ {
title: '观看者类型', title: '观看者类型',
key: 'userRole', key: 'userRole',
dataIndex: 'userRole' dataIndex: 'userRole',
}, },
{ {
title: '首次观看时间', title: '首次观看时间',
key: 'firstWatch', key: 'firstWatch',
dataIndex: 'firstWatch', dataIndex: 'firstWatch',
render: (val) => { render: (val) => {
return formatDate('YYYY-MM-DD H:i', val) return formatDate('YYYY-MM-DD H:i', val);
} },
}, },
{ {
title: '观看总时长', title: '观看总时长',
key: 'watchDuration', key: 'watchDuration',
dataIndex: 'watchDuration', dataIndex: 'watchDuration',
render: (val) => { render: (val) => {
return <span>{val ? dealTimeDuration(val) : "00:00:00" }</span> return <span>{val ? dealTimeDuration(val) : '00:00:00'}</span>;
} },
}, },
{ {
title: '学习进度', title: '学习进度',
key: 'progress', key: 'progress',
dataIndex: 'progress', dataIndex: 'progress',
render: (val) => { render: (val) => {
return <span>{val === 100 ? '已完成' : `${val || 0}%`}</span> return <span>{val === 100 ? '已完成' : `${val || 0}%`}</span>;
} },
} },
]; ];
return columns; return columns;
} };
render() { render() {
const { visible,size,dataSource,totalCount,query} = this.state; const { visible, size, dataSource, totalCount, query } = this.state;
return ( return (
<Modal <Modal
title="图文课观看数据" title='图文课观看数据'
visible={visible} visible={visible}
footer={null} footer={null}
onCancel={this.onClose} onCancel={this.onClose}
maskClosable={false} maskClosable={false}
className="watch-data-modal" className='watch-data-modal'
closable={true} closable={true}
width={800} width={800}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>} closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}>
> <div className='search-container'>
<div className="search-container"> <Search
<Search placeholder="搜索学员姓名/手机号" style={{ width: 200 }} onChange={(e) => { this.handleChangNickname(e.target.value)}} onSearch={ () => { this.handleFetchDataList()}} enterButton={<span className="icon iconfont">&#xe832;</span>}/> placeholder='搜索学员姓名/手机号'
</div> style={{ width: 200 }}
<div> onChange={(e) => {
<Table this.handleChangNickname(e.target.value);
rowKey={record => record.id} }}
dataSource={dataSource} onSearch={() => {
columns={this.parseColumns()} this.handleFetchDataList();
pagination={false} }}
bordered enterButton={<span className='icon iconfont'>&#xe832;</span>}
/> />
{dataSource.length >0 && </div>
<div className="box-footer"> <div>
<PageControl <XMTable
current={query.current - 1} renderEmpty={{
pageSize={size} image: college,
total={totalCount} description: '暂无数据',
size="small" }}
toPage={(page) => { rowKey={(record) => record.id}
const _query = {...query, current: page + 1}; dataSource={dataSource}
this.setState({ columns={this.parseColumns()}
query:_query pagination={false}
},()=>{ this.handleFetchDataList()}) bordered
}} />
onShowSizeChange={this.onShowSizeChange} {dataSource.length > 0 && (
/> <div className='box-footer'>
</div> <PageControl
} current={query.current - 1}
</div> pageSize={size}
</Modal> total={totalCount}
) size='small'
toPage={(page) => {
const _query = { ...query, current: page + 1 };
this.setState(
{
query: _query,
},
() => {
this.handleFetchDataList();
}
);
}}
onShowSizeChange={this.onShowSizeChange}
/>
</div>
)}
</div>
</Modal>
);
} }
} }
export default WatchDataModal; export default WatchDataModal;
\ No newline at end of file
import college from '@/common/lottie/college';
import { XMTable } from '@/components';
import { Modal } from 'antd';
import React from 'react'; import React from 'react';
import { Modal, Table } from "antd"; import './AccountChargeModal.less';
import ChargeArgeement from "./ChargeArgeement"; import ChargeArgeement from './ChargeArgeement';
import "./AccountChargeModal.less"; class AccountChargeRecords extends React.Component {
class AccountChargeRecords extends React.Component{
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
...@@ -15,14 +17,12 @@ class AccountChargeRecords extends React.Component{ ...@@ -15,14 +17,12 @@ class AccountChargeRecords extends React.Component{
getList = () => { getList = () => {
const { instId } = window.currentUserInstInfo; const { instId } = window.currentUserInstInfo;
axios axios.Business('public/liveAssets/rechargeProtocol', { instId }).then((res) => {
.Business("public/liveAssets/rechargeProtocol", { instId }) const list = res.result;
.then((res) => { this.setState({
const list = res.result; list,
this.setState({
list,
});
}); });
});
}; };
handleProtcol = (id) => { handleProtcol = (id) => {
const agreement = ( const agreement = (
...@@ -42,29 +42,28 @@ class AccountChargeRecords extends React.Component{ ...@@ -42,29 +42,28 @@ class AccountChargeRecords extends React.Component{
render() { render() {
const columns = [ const columns = [
{ {
title: "签订人", title: '签订人',
dataIndex: "operatorName", dataIndex: 'operatorName',
width: 140 width: 140,
}, },
{ title: "关联订单ID", dataIndex: "orderId" }, { title: '关联订单ID', dataIndex: 'orderId' },
{ {
title: "签订时间", title: '签订时间',
dataIndex: "createTime", dataIndex: 'createTime',
render: (text, record) => { render: (text, record) => {
return <span>{formatDate("YYYY-MM-DD H:i", parseInt(text))}</span>; return <span>{formatDate('YYYY-MM-DD H:i', parseInt(text))}</span>;
}, },
}, },
{ {
title: "签订协议", title: '签订协议',
dataIndex: "operate", dataIndex: 'operate',
render: (text, record) => { render: (text, record) => {
return ( return (
<div <div
style={{ cursor: "pointer", color: "#FC9C6B" }} style={{ cursor: 'pointer', color: '#FC9C6B' }}
onClick={() => { onClick={() => {
this.handleProtcol(record.protocolId); this.handleProtcol(record.protocolId);
}} }}>
>
《服务协议》 《服务协议》
</div> </div>
); );
...@@ -74,29 +73,31 @@ class AccountChargeRecords extends React.Component{ ...@@ -74,29 +73,31 @@ class AccountChargeRecords extends React.Component{
const { list } = this.state; const { list } = this.state;
return ( return (
<Modal <Modal
title="服务协议签订记录" title='服务协议签订记录'
visible={true} visible={true}
width={680} width={680}
footer={null} footer={null}
maskClosable={false} maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>} closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}
onCancel={() => { onCancel={() => {
this.props.close(); this.props.close();
}} }}>
>
<div> <div>
<div <div
style={{ style={{
fontSize: "14px", fontSize: '14px',
color: "#666666", color: '#666666',
lineHeight: "20px", lineHeight: '20px',
marginBottom: 16, marginBottom: 16,
}} }}>
>
以下是本校区自助充值时签订协议的记录 以下是本校区自助充值时签订协议的记录
</div> </div>
<Table <XMTable
size="middle" renderEmpty={{
image: college,
description: '暂无数据',
}}
size='middle'
columns={columns} columns={columns}
dataSource={list} dataSource={list}
pagination={false} pagination={false}
......
import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components';
import { Modal, Tooltip } from 'antd';
import React from 'react'; import React from 'react';
import { Modal, Table, Tooltip } from "antd"; import './AccountChargeModal.less';
import { ShowTips, PageControl } from "@/components";
import "./AccountChargeModal.less";
class ChargingDetailModal extends React.Component { class ChargingDetailModal extends React.Component {
constructor(props) { constructor(props) {
...@@ -25,22 +26,20 @@ class ChargingDetailModal extends React.Component { ...@@ -25,22 +26,20 @@ class ChargingDetailModal extends React.Component {
handleToPage = (page = 1) => { handleToPage = (page = 1) => {
const params = _.clone(this.state.query); const params = _.clone(this.state.query);
params.current = page; params.current = page;
axios axios.Apollo('public/businessLive/queryStudentVisitData', params).then((res) => {
.Apollo("public/businessLive/queryStudentVisitData", params) if (res.result) {
.then((res) => { const { records = [], total } = res.result;
if (res.result) { this.setState({
const { records = [], total } = res.result; list: records,
this.setState({ totalCount: total,
list: records, query: params,
totalCount: total, });
query: params, }
}); });
}
});
}; };
getTeacherData = () => { getTeacherData = () => {
window.axios window.axios
.Apollo("public/businessLive/queryTeacherVisitData", { .Apollo('public/businessLive/queryTeacherVisitData', {
liveCourseId: this.props.liveCourseId, liveCourseId: this.props.liveCourseId,
}) })
.then((res) => { .then((res) => {
...@@ -57,27 +56,27 @@ class ChargingDetailModal extends React.Component { ...@@ -57,27 +56,27 @@ class ChargingDetailModal extends React.Component {
let hours = Math.floor(time / 3600); let hours = Math.floor(time / 3600);
let mins = Math.floor(diff / 60); let mins = Math.floor(diff / 60);
let seconds = Math.floor(time % 60); let seconds = Math.floor(time % 60);
hours = hours < 10 ? "0" + hours : hours; hours = hours < 10 ? '0' + hours : hours;
mins = mins < 10 ? "0" + mins : mins; mins = mins < 10 ? '0' + mins : mins;
seconds = seconds < 10 ? "0" + seconds : seconds; seconds = seconds < 10 ? '0' + seconds : seconds;
return hours + ":" + mins + ":" + seconds; return hours + ':' + mins + ':' + seconds;
}; };
getColumns = (type) => { getColumns = (type) => {
const columns = [ const columns = [
{ {
title: type == "student" ? "学生姓名" : "老师姓名", title: type == 'student' ? '学生姓名' : '老师姓名',
dataIndex: "userName", dataIndex: 'userName',
}, },
{ {
title: "手机号", title: '手机号',
dataIndex: "phone", dataIndex: 'phone',
render: (text, record) => { render: (text, record) => {
return <p>{text}</p>; return <p>{text}</p>;
}, },
}, },
{ {
title: "累计在线时长", title: '累计在线时长',
dataIndex: "totalDuration", dataIndex: 'totalDuration',
render: (text, record) => { render: (text, record) => {
return <span>{text ? this.dealTimeDuration(text) : '-'}</span>; return <span>{text ? this.dealTimeDuration(text) : '-'}</span>;
}, },
...@@ -86,14 +85,14 @@ class ChargingDetailModal extends React.Component { ...@@ -86,14 +85,14 @@ class ChargingDetailModal extends React.Component {
title: ( title: (
<span> <span>
是否计费&nbsp; 是否计费&nbsp;
<Tooltip title="仅对累计在线时长≥10分钟的老师或学员计费"> <Tooltip title='仅对累计在线时长≥10分钟的老师或学员计费'>
<span className="icon iconfont">&#xe6f2;</span> <span className='icon iconfont'>&#xe6f2;</span>
</Tooltip> </Tooltip>
</span> </span>
), ),
dataIndex: "type", dataIndex: 'type',
render: (text, record) => { render: (text, record) => {
return <span>{record.totalDuration > 600 ? "计费" : "不计费"}</span>; //大于十分钟的计费 return <span>{record.totalDuration > 600 ? '计费' : '不计费'}</span>; //大于十分钟的计费
}, },
}, },
]; ];
...@@ -103,38 +102,45 @@ class ChargingDetailModal extends React.Component { ...@@ -103,38 +102,45 @@ class ChargingDetailModal extends React.Component {
const { list, query, totalCount, teacherList } = this.state; const { list, query, totalCount, teacherList } = this.state;
return ( return (
<Modal <Modal
title="计费人数详情" title='计费人数详情'
visible={true} visible={true}
width={680} width={680}
maskClosable={false} maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>} closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}
className="charging-detail-modal" className='charging-detail-modal'
footer={null} footer={null}
onCancel={() => { onCancel={() => {
this.props.close(); this.props.close();
}} }}>
>
<div> <div>
<div style={{ marginBottom: 16 }}> <div style={{ marginBottom: 16 }}>
<div className="detail-title">老师详情</div> <div className='detail-title'>老师详情</div>
<Table <XMTable
size="middle" renderEmpty={{
columns={this.getColumns("teacher")} image: college,
description: '暂无数据',
}}
size='middle'
columns={this.getColumns('teacher')}
dataSource={teacherList} dataSource={teacherList}
pagination={false} pagination={false}
bordered bordered
/> />
</div> </div>
<div className="detail-title">学生详情</div> <div className='detail-title'>学生详情</div>
<Table <XMTable
size="middle" renderEmpty={{
columns={this.getColumns("student")} image: college,
description: '暂无数据',
}}
size='middle'
columns={this.getColumns('student')}
dataSource={list} dataSource={list}
pagination={false} pagination={false}
bordered bordered
/> />
<PageControl <PageControl
size="small" size='small'
current={query.current - 1} current={query.current - 1}
pageSize={query.size} pageSize={query.size}
total={totalCount} total={totalCount}
......
...@@ -6,16 +6,14 @@ ...@@ -6,16 +6,14 @@
* @LastEditTime: 2021-02-01 14:00:19 * @LastEditTime: 2021-02-01 14:00:19
*/ */
import React, { useState, useEffect } from "react"; import college from '@/common/lottie/college';
import { Modal, Table, Input, Button, message, Checkbox, Tooltip } from "antd"; import { PageControl, XMTable } from '@/components';
import Bus from '@/core/bus'; import Bus from '@/core/bus';
import { PageControl } from "@/components"; import { Button, Checkbox, Input, message, Modal, Tooltip } from 'antd';
import React from 'react';
import hasExportPermission from '../utils/hasExportPermission';
import dealTimeDuration from '../utils/dealTimeDuration'; import dealTimeDuration from '../utils/dealTimeDuration';
import hasExportPermission from '../utils/hasExportPermission';
import "./ClassRecordModal.less"; import './ClassRecordModal.less';
const { Search } = Input; const { Search } = Input;
...@@ -28,7 +26,7 @@ class ClassRecordModal extends React.Component { ...@@ -28,7 +26,7 @@ class ClassRecordModal extends React.Component {
query: { query: {
current: 1, current: 1,
size: 10, size: 10,
nameOrPhone: "", nameOrPhone: '',
liveSignState: '', liveSignState: '',
durationSort: null, durationSort: null,
liveCourseId: props.liveItem.liveCourseId, liveCourseId: props.liveItem.liveCourseId,
...@@ -42,35 +40,31 @@ class ClassRecordModal extends React.Component { ...@@ -42,35 +40,31 @@ class ClassRecordModal extends React.Component {
fetchClassList = (page = 1) => { fetchClassList = (page = 1) => {
const params = _.clone(this.state.query); const params = _.clone(this.state.query);
if(!params.liveSignState) { if (!params.liveSignState) {
delete params.liveSignState; delete params.liveSignState;
} }
params.current = page; params.current = page;
window.axios window.axios.Apollo('public/businessLive/queryStudentVisitData', params).then((res) => {
.Apollo("public/businessLive/queryStudentVisitData", params) if (res.result) {
.then((res) => { const { records = [], total } = res.result;
if (res.result) { this.setState({
const { records = [], total } = res.result; classList: records,
this.setState({ total,
classList: records, query: params,
total, });
query: params, }
}); });
}
});
}; };
fetchTeacherData = () => { fetchTeacherData = () => {
const { liveCourseId } = this.props.liveItem; const { liveCourseId } = this.props.liveItem;
window.axios window.axios.Apollo('public/businessLive/queryTeacherVisitData', { liveCourseId }).then((res) => {
.Apollo("public/businessLive/queryTeacherVisitData", { liveCourseId }) if (res.result) {
.then((res) => { const teacherData = [res.result];
if (res.result) { this.setState({
const teacherData = [res.result]; teacherData,
this.setState({ });
teacherData, }
}); });
}
});
}; };
getColumns = (type) => { getColumns = (type) => {
...@@ -78,83 +72,85 @@ class ClassRecordModal extends React.Component { ...@@ -78,83 +72,85 @@ class ClassRecordModal extends React.Component {
const source = this.props.type; const source = this.props.type;
const columns = [ const columns = [
{ {
title: type == "student" ? "学生姓名" : "老师姓名", title: type == 'student' ? '学生姓名' : '老师姓名',
dataIndex: "userName", dataIndex: 'userName',
}, },
{ {
title: "手机号", title: '手机号',
dataIndex: "phone", dataIndex: 'phone',
render: (text, record) => { render: (text, record) => {
return ( return (
<p> <p>
{!( {!((!window.NewVersion && !window.currentUserInstInfo.teacherId) || (window.NewVersion && Permission.hasEduStudentPhone())) && type == 'student'
(!window.NewVersion && !window.currentUserInstInfo.teacherId) || ? (text || '').replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3')
(window.NewVersion && Permission.hasEduStudentPhone())
) && type == "student"
? (text || "").replace(/(\d{3})(\d{4})(\d{4})/, "$1****$3")
: text} : text}
</p> </p>
); );
}, },
}, },
{ {
title: type == "student" ? "观看直播次数" : "进入直播间次数", title: type == 'student' ? '观看直播次数' : '进入直播间次数',
dataIndex: "entryNum", dataIndex: 'entryNum',
align:'right' align: 'right',
}, },
{ {
title: "累计上课时长", title: '累计上课时长',
dataIndex: type == "student" ? "watchDuration" : "totalDuration", dataIndex: type == 'student' ? 'watchDuration' : 'totalDuration',
sorter: sorter: type == 'student' ? (a, b) => a.watchDuration - b.watchDuration : null,
type == "student" sortDirections: ['descend', 'ascend'],
? (a, b) => a.watchDuration - b.watchDuration
: null,
sortDirections: ["descend", "ascend"],
render: (text, record) => { render: (text, record) => {
//如无离开时间,就置空 //如无离开时间,就置空
return ( return <span>{text ? dealTimeDuration(text) : '00:00:00'}</span>;
<span>
{text ? dealTimeDuration(text) : '00:00:00'}
</span>
);
}, },
}, },
]; ];
if(type == "student") { if (type == 'student') {
columns.push({ columns.push({
title: <span>到课状态<Tooltip title={<div>学员累计上课时长达到<span className="bulge">{consumeClassTime}</span>分钟,即视为学员“到课”</div>}><span className="iconfont">&#xe6f2;</span></Tooltip></span>, title: (
<span>
到课状态
<Tooltip
title={
<div>
学员累计上课时长达到<span className='bulge'>{consumeClassTime}</span>分钟,即视为学员“到课”
</div>
}>
<span className='iconfont'>&#xe6f2;</span>
</Tooltip>
</span>
),
width: 100, width: 100,
dataIndex: "signState", dataIndex: 'signState',
render: (text) => { render: (text) => {
if(text) { if (text) {
return <span>{text === 'ABSENT' ? '未到' : '到课'}</span> return <span>{text === 'ABSENT' ? '未到' : '到课'}</span>;
} else { } else {
return <span>-</span> return <span>-</span>;
} }
} },
}) });
if(source) { if (source) {
columns.push({ columns.push({
title: "获得奖杯数", title: '获得奖杯数',
dataIndex: "trophyNum", dataIndex: 'trophyNum',
align:'right', align: 'right',
render: (text) => { render: (text) => {
return <span>{text ? text : 0}</span> return <span>{text ? text : 0}</span>;
} },
}) });
} }
} }
return columns; return columns;
}; };
handleTableChange = (pagination, filters, sorter) => { handleTableChange = (pagination, filters, sorter) => {
const query = this.state.query; const query = this.state.query;
if (!_.isEmpty(sorter)) { if (!_.isEmpty(sorter)) {
if (sorter.columnKey === "totalDuration") { if (sorter.columnKey === 'totalDuration') {
if (sorter.order === "ascend") { if (sorter.order === 'ascend') {
query.durationSort = "SORT_ASC"; query.durationSort = 'SORT_ASC';
} else if (sorter.order === "descend") { } else if (sorter.order === 'descend') {
query.durationSort = "SORT_DESC"; query.durationSort = 'SORT_DESC';
} }
this.setState({ query }, this.fetchClassList); this.setState({ query }, this.fetchClassList);
} }
...@@ -165,20 +161,22 @@ class ClassRecordModal extends React.Component { ...@@ -165,20 +161,22 @@ class ClassRecordModal extends React.Component {
handleExportV5 = () => { handleExportV5 = () => {
const { liveItem, type } = this.props; const { liveItem, type } = this.props;
const { liveCourseId } = liveItem; const { liveCourseId } = liveItem;
const url = !type ? 'public/businessLive/exportLargeClassLiveAsync' : 'public/businessLive/exportClassInteractionLiveSync' const url = !type ? 'public/businessLive/exportLargeClassLiveAsync' : 'public/businessLive/exportClassInteractionLiveSync';
window.axios.Apollo(url, { window.axios
liveCourseId, .Apollo(url, {
exportLiveType: 'VISITOR' liveCourseId,
}).then((res) => { exportLiveType: 'VISITOR',
Bus.trigger('get_download_count'); })
Modal.success({ .then((res) => {
title: '导出任务提交成功', Bus.trigger('get_download_count');
content: '请前往右上角的“任务中心”进行下载', Modal.success({
okText: '我知道了', title: '导出任务提交成功',
content: '请前往右上角的“任务中心”进行下载',
okText: '我知道了',
});
}); });
}) };
}
// 4.0导出 // 4.0导出
handleExport = () => { handleExport = () => {
...@@ -186,43 +184,41 @@ class ClassRecordModal extends React.Component { ...@@ -186,43 +184,41 @@ class ClassRecordModal extends React.Component {
const { liveCourseId } = liveItem; const { liveCourseId } = liveItem;
const url = !type ? 'api-b/b/lesson/exportLargeClassLiveAsync' : 'api-b/b/lesson/exportClassInteractionLiveSync'; const url = !type ? 'api-b/b/lesson/exportLargeClassLiveAsync' : 'api-b/b/lesson/exportClassInteractionLiveSync';
window.axios.post(url, { window.axios
liveCourseId, .post(url, {
exportLiveType: 1 liveCourseId,
}).then((res) => { exportLiveType: 1,
Bus.trigger('get_download_count'); })
Modal.success({ .then((res) => {
title: '导出任务提交成功', Bus.trigger('get_download_count');
content: '请前往右上角的“导出中心”进行下载', Modal.success({
okText: '我知道了', title: '导出任务提交成功',
content: '请前往右上角的“导出中心”进行下载',
okText: '我知道了',
});
}); });
}) };
}
render() { render() {
const { type } = this.props; const { type } = this.props;
const { query, total, teacherData, classList } = this.state; const { query, total, teacherData, classList } = this.state;
const expandedColumns = [ const expandedColumns = [
{ {
title: "进入时间", title: '进入时间',
dataIndex: "entryTime", dataIndex: 'entryTime',
key: "entryTime", key: 'entryTime',
render: (text) => ( render: (text) => <span>{formatDate('YYYY-MM-DD H:i', parseInt(text))}</span>,
<span>{formatDate("YYYY-MM-DD H:i", parseInt(text))}</span>
),
}, },
{ {
title: "离开时间", title: '离开时间',
dataIndex: "leaveTime", dataIndex: 'leaveTime',
key: "leaveTime", key: 'leaveTime',
render: (text) => ( render: (text) => <span>{formatDate('YYYY-MM-DD H:i', parseInt(text))}</span>,
<span>{formatDate("YYYY-MM-DD H:i", parseInt(text))}</span>
),
}, },
{ {
title: "上课时长", title: '上课时长',
dataIndex: "lookingDuration", dataIndex: 'lookingDuration',
key: "lookingDuration", key: 'lookingDuration',
render: (text, record) => { render: (text, record) => {
return <span>{text ? dealTimeDuration(text) : '-'}</span>; return <span>{text ? dealTimeDuration(text) : '-'}</span>;
}, },
...@@ -230,64 +226,73 @@ class ClassRecordModal extends React.Component { ...@@ -230,64 +226,73 @@ class ClassRecordModal extends React.Component {
]; ];
return ( return (
<Modal <Modal
title="上课记录" title='上课记录'
visible={true} visible={true}
footer={null} footer={null}
width={680} width={680}
maskClosable={false} maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>} closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}
className="class-record-modal" className='class-record-modal'
onCancel={() => { onCancel={() => {
this.props.close(); this.props.close();
}} }}>
>
<div> <div>
<p className="class-record-title" style={{ marginBottom: 18 }}> <p className='class-record-title' style={{ marginBottom: 18 }}>
老师上课数据 老师上课数据
</p> </p>
<Table <XMTable
size="small" renderEmpty={{
columns={this.getColumns("teacher")} image: college,
description: '暂无数据',
}}
size='small'
columns={this.getColumns('teacher')}
dataSource={teacherData} dataSource={teacherData}
pagination={false} pagination={false}
className="table-no-scrollbar" className='table-no-scrollbar'
expandedRowRender={(record) => { expandedRowRender={(record) => {
if ( if (record.visitorInfoVOList && record.visitorInfoVOList.length > 0) {
record.visitorInfoVOList &&
record.visitorInfoVOList.length > 0
) {
return ( return (
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
columns={expandedColumns} columns={expandedColumns}
dataSource={record.visitorInfoVOList} dataSource={record.visitorInfoVOList}
size={"small"} size={'small'}
className="no-scrollbar expanded-table" className='no-scrollbar expanded-table'
pagination={false} pagination={false}
></Table> />
); );
} else { } else {
return <div className="live-table--empty">暂无上课数据</div>; return <div className='live-table--empty'>暂无上课数据</div>;
} }
}} }}
></Table> />
<div className="student-wrapper"> <div className='student-wrapper'>
<section className="class-record-title">学员上课数据</section> <section className='class-record-title'>学员上课数据</section>
<section> <section>
<Checkbox <Checkbox
style={{lineHeight: '33px'}} style={{ lineHeight: '33px' }}
onChange={(e) => { onChange={(e) => {
const param = _.clone(this.state.query); const param = _.clone(this.state.query);
param.current = 1; param.current = 1;
param.liveSignState = e.target.checked ? 'SIGN' : ''; param.liveSignState = e.target.checked ? 'SIGN' : '';
this.setState({ this.setState(
query: param {
}, () => { query: param,
this.fetchClassList(); },
}) () => {
}}>只看“到课”学员</Checkbox> this.fetchClassList();
}
);
}}>
只看“到课”学员
</Checkbox>
<Search <Search
className="student-wrapper__search" className='student-wrapper__search'
placeholder="搜索学员姓名/手机号" placeholder='搜索学员姓名/手机号'
style={{ width: 200, marginBottom: 0 }} style={{ width: 200, marginBottom: 0 }}
onSearch={(value) => { onSearch={(value) => {
const param = _.clone(this.state.query); const param = _.clone(this.state.query);
...@@ -303,52 +308,62 @@ class ClassRecordModal extends React.Component { ...@@ -303,52 +308,62 @@ class ClassRecordModal extends React.Component {
); );
}} }}
/> />
{ {hasExportPermission(type) && (
hasExportPermission(type) && <Button
<Button onClick={_.debounce(() => { onClick={_.debounce(
if (!classList.length) { () => {
message.warning('暂无数据可导出'); if (!classList.length) {
return; message.warning('暂无数据可导出');
} return;
if (window.NewVersion) { }
this.handleExportV5(); if (window.NewVersion) {
} else { this.handleExportV5();
this.handleExport(); } else {
} this.handleExport();
}, 500, true)}>导出</Button> }
} },
500,
true
)}>
导出
</Button>
)}
</section> </section>
</div> </div>
<div> <div>
<Table <XMTable
size="small" renderEmpty={{
columns={this.getColumns("student")} image: college,
description: '暂无数据',
}}
size='small'
columns={this.getColumns('student')}
dataSource={classList} dataSource={classList}
pagination={false} pagination={false}
className="table-no-scrollbar" className='table-no-scrollbar'
onChange={this.handleTableChange} onChange={this.handleTableChange}
expandedRowRender={(record) => { expandedRowRender={(record) => {
if ( if (record.visitorInfoVOList && record.visitorInfoVOList.length > 0) {
record.visitorInfoVOList &&
record.visitorInfoVOList.length > 0
) {
return ( return (
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
columns={expandedColumns} columns={expandedColumns}
dataSource={record.visitorInfoVOList} dataSource={record.visitorInfoVOList}
size={"small"} size={'small'}
className="no-scrollbar expanded-table" className='no-scrollbar expanded-table'
pagination={false} pagination={false}
></Table> />
); );
} else { } else {
return <div className="live-table--empty">暂无上课数据</div>; return <div className='live-table--empty'>暂无上课数据</div>;
} }
}} }}
></Table> />
<PageControl <PageControl
size="small" size='small'
current={query.current - 1} current={query.current - 1}
pageSize={query.size} pageSize={query.size}
total={total} total={total}
......
...@@ -5,61 +5,49 @@ ...@@ -5,61 +5,49 @@
* @Last Modified time: 2020-07-22 16:25:30 * @Last Modified time: 2020-07-22 16:25:30
* 查看学员名单 * 查看学员名单
*/ */
import React from "react"; import college from '@/common/lottie/college';
import { import { PageControl, XMTable } from '@/components';
Modal, import { Button, Input, message, Modal, Popconfirm, Tooltip } from 'antd';
Button, import PropTypes from 'prop-types';
Input, import React from 'react';
Table, import './LiveStudentListModal.less';
Popconfirm, import SelectStudent from './select-student/index';
message,
Tooltip,
} from "antd";
import PropTypes from "prop-types";
import { PageControl } from "@/components";
import SelectStudent from "./select-student/index";
import "./LiveStudentListModal.less";
const { Search } = Input; const { Search } = Input;
const isTeacher = !!window.currentUserInstInfo.teacherId; const isTeacher = !!window.currentUserInstInfo.teacherId;
const liveTypeMap = { const liveTypeMap = {
LIVE: "直播", LIVE: '直播',
PLAYBACK: "回放", PLAYBACK: '回放',
}; };
const expandedColumns = [ const expandedColumns = [
{ {
title: "类型", title: '类型',
dataIndex: "liveType", dataIndex: 'liveType',
key: "liveType", key: 'liveType',
render: (text) => <span>{liveTypeMap[text]}</span>, render: (text) => <span>{liveTypeMap[text]}</span>,
}, },
{ {
title: "进入时间", title: '进入时间',
dataIndex: "entryTime", dataIndex: 'entryTime',
key: "entryTime", key: 'entryTime',
render: (text) => ( render: (text) => <span>{formatDate('YYYY-MM-DD H:i', parseInt(text))}</span>,
<span>{formatDate("YYYY-MM-DD H:i", parseInt(text))}</span>
),
}, },
{ {
title: "离开时间", title: '离开时间',
dataIndex: "leaveTime", dataIndex: 'leaveTime',
key: "leaveTime", key: 'leaveTime',
render: (text) => ( render: (text) => <span>{formatDate('YYYY-MM-DD H:i', parseInt(text))}</span>,
<span>{formatDate("YYYY-MM-DD H:i", parseInt(text))}</span>
),
}, },
{ title: "观看时长", dataIndex: "lookingTime", key: "lookingTime" }, { title: '观看时长', dataIndex: 'lookingTime', key: 'lookingTime' },
]; ];
const STATUS_ENUM = { const STATUS_ENUM = {
'NORMAL': '在读', NORMAL: '在读',
'POTENTIAL': '潜在', POTENTIAL: '潜在',
'HISTORY': '历史', HISTORY: '历史',
'ABANDON': '废弃', ABANDON: '废弃',
}; };
class LiveStudentListModal extends React.Component { class LiveStudentListModal extends React.Component {
...@@ -86,76 +74,72 @@ class LiveStudentListModal extends React.Component { ...@@ -86,76 +74,72 @@ class LiveStudentListModal extends React.Component {
fetchStudentList = (current = 1) => { fetchStudentList = (current = 1) => {
const query = _.clone(this.state.query); const query = _.clone(this.state.query);
query.current = current; query.current = current;
window.axios window.axios.Apollo('public/businessLive/getStudentList', query).then((res) => {
.Apollo("public/businessLive/getStudentList", query) const { records = [], total } = res.result;
.then((res) => {
const { records = [], total } = res.result;
this.setState({ this.setState({
studentList: records, studentList: records,
total, total,
query, query,
});
}); });
});
}; };
hanldSelect = () => { hanldSelect = () => {
const { query: { liveCourseId } } = this.state; const {
axios.Apollo('public/businessLive/getCourseDetail', { liveCourseId}) query: { liveCourseId },
.then((res) => { } = this.state;
const { result = {} } = res; axios.Apollo('public/businessLive/getCourseDetail', { liveCourseId }).then((res) => {
const { consumeStudentIds, studentIds } = result; const { result = {} } = res;
const studentList = []; const { consumeStudentIds, studentIds } = result;
const excludeStudentIds = studentIds; const studentList = [];
const excludeConsumeStudentIds = _.pluck(consumeStudentIds, 'studentId'); const excludeStudentIds = studentIds;
this.setState({ excludeStudentIds, excludeConsumeStudentIds}); const excludeConsumeStudentIds = _.pluck(consumeStudentIds, 'studentId');
this.setState({ excludeStudentIds, excludeConsumeStudentIds });
_.each(studentIds, (item) => { _.each(studentIds, (item) => {
studentList.push({ studentId: item }); studentList.push({ studentId: item });
}); });
const studentModal = (
<SelectStudent
liveCourseId={liveCourseId}
studentList={studentList}
excludeStudentIds={excludeStudentIds}
after={true}
close={() => { this.setState({ studentModal: null }); }}
onSelect={(studentIds) => {
this.handleSelectStudent(studentIds)
}}
/>
)
this.setState({ studentModal }); const studentModal = (
}) <SelectStudent
liveCourseId={liveCourseId}
studentList={studentList}
excludeStudentIds={excludeStudentIds}
after={true}
close={() => {
this.setState({ studentModal: null });
}}
onSelect={(studentIds) => {
this.handleSelectStudent(studentIds);
}}
/>
);
this.setState({ studentModal });
});
}; };
handleSelectStudent = (studentIds) => { handleSelectStudent = (studentIds) => {
const { const { liveType, liveCourseId, podium, quota } = this.props.liveItem;
liveType,
liveCourseId,
podium,
quota,
} = this.props.liveItem;
if (liveType !== "SMALL_CLASS_INTERACTION" && (studentIds.length) > 1000) { if (liveType !== 'SMALL_CLASS_INTERACTION' && studentIds.length > 1000) {
message.info(`最多选择1000人`); message.info(`最多选择1000人`);
return; return;
} else if (liveType == "SMALL_CLASS_INTERACTION" && (studentIds.length) > podium) { } else if (liveType == 'SMALL_CLASS_INTERACTION' && studentIds.length > podium) {
message.info(`最多选择${podium}人`); message.info(`最多选择${podium}人`);
return; return;
} else { } else {
const param = { const param = {
liveCourseId: liveCourseId, liveCourseId: liveCourseId,
studentIds: studentIds studentIds: studentIds,
}; };
axios.Apollo("public/businessLive/addCourseStu", param).then(res => { axios.Apollo('public/businessLive/addCourseStu', param).then((res) => {
if (res.success) { if (res.success) {
this.setState({ this.setState({
studentModal: null studentModal: null,
}); });
message.success("学员变更成功"); message.success('学员变更成功');
this.fetchStudentList(); this.fetchStudentList();
this.props.refresh(); this.props.refresh();
} }
...@@ -170,59 +154,51 @@ class LiveStudentListModal extends React.Component { ...@@ -170,59 +154,51 @@ class LiveStudentListModal extends React.Component {
liveCourseId, liveCourseId,
studentId, studentId,
}; };
window.axios window.axios.Apollo('public/businessLive/moveCourseStu', param).then((res) => {
.Apollo("public/businessLive/moveCourseStu", param) message.success('移除学员成功');
.then((res) => { this.fetchStudentList(1);
message.success("移除学员成功"); this.props.refresh();
this.fetchStudentList(1); });
this.props.refresh();
});
}; };
parseColumns = () => { parseColumns = () => {
const { type, liveItem } = this.props; const { type, liveItem } = this.props;
const columns = [ const columns = [
{ title: "姓名", dataIndex: "studentName", key: "studentName" }, { title: '姓名', dataIndex: 'studentName', key: 'studentName' },
{ {
title: "手机号", title: '手机号',
dataIndex: "phone", dataIndex: 'phone',
width: 150, width: 150,
key: "phone", key: 'phone',
render: (text, record) => { render: (text, record) => {
return ( return (
<p> <p>
{!( {!((!window.NewVersion && !window.currentUserInstInfo.teacherId) || (window.NewVersion && Permission.hasEduStudentPhone()))
(!window.NewVersion && !window.currentUserInstInfo.teacherId) || ? (text || '').replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3')
(window.NewVersion && Permission.hasEduStudentPhone())
)
? (text || "").replace(/(\d{3})(\d{4})(\d{4})/, "$1****$3")
: text} : text}
<Tooltip <Tooltip title={`${record.wechatStatus ? '已绑定微信' : '未绑定微信'}`}>
title={`${record.wechatStatus ? "已绑定微信" : "未绑定微信"}`}
>
<span <span
className="icon iconfont" className='icon iconfont'
style={ style={
record.wechatStatus record.wechatStatus
? { ? {
color: "#00D20D", color: '#00D20D',
fontSize: "16px", fontSize: '16px',
marginLeft: 6, marginLeft: 6,
} }
: { : {
color: "#BFBFBF", color: '#BFBFBF',
fontSize: "16px", fontSize: '16px',
marginLeft: 6, marginLeft: 6,
} }
} }>
>
&#xe68d; &#xe68d;
</span> </span>
</Tooltip> </Tooltip>
</p> </p>
); );
}, },
} },
]; ];
// 非互动班课类型增加学员类型 // 非互动班课类型增加学员类型
...@@ -233,100 +209,97 @@ class LiveStudentListModal extends React.Component { ...@@ -233,100 +209,97 @@ class LiveStudentListModal extends React.Component {
dataIndex: 'statusEnum', dataIndex: 'statusEnum',
render: (val) => { render: (val) => {
return STATUS_ENUM[val]; return STATUS_ENUM[val];
} },
}); });
} }
// 如果是非视频课, 显示操作的条件是课程未开始,且不是T端 // 如果是非视频课, 显示操作的条件是课程未开始,且不是T端
// 如果是视频课,那么只要满足不是T端就可以了 // 如果是视频课,那么只要满足不是T端就可以了
if ((liveItem.courseState === "UN_START" || type === 'videoCourse') && !isTeacher) { if ((liveItem.courseState === 'UN_START' || type === 'videoCourse') && !isTeacher) {
// 未开始 // 未开始
columns.push({ columns.push({
title: "操作", title: '操作',
dataIndex: "operate", dataIndex: 'operate',
key: "operate", key: 'operate',
align:'right', align: 'right',
render: (text, record) => { render: (text, record) => {
return ( return (
<Popconfirm <Popconfirm
title="你确定要移出这个学员吗?" title='你确定要移出这个学员吗?'
onConfirm={() => { onConfirm={() => {
// 如果是非视频课,且直播间类型是自研, 且晚于开课前30分钟, 不允许移出 // 如果是非视频课,且直播间类型是自研, 且晚于开课前30分钟, 不允许移出
if ( if (liveItem.channel == 'XIAOMAI' && liveItem.startTime - Date.now() < 1800000) {
liveItem.channel == "XIAOMAI" &&
liveItem.startTime - Date.now() < 1800000
) {
Modal.warning({ Modal.warning({
title: "不可移出", title: '不可移出',
icon: ( icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
<span className="icon iconfont default-confirm-icon"> content: '晚于开课前30分钟,不能移出学员',
&#xe6f4;
</span>
),
content: "晚于开课前30分钟,不能移出学员",
}); });
} else { } else {
this.removeStudent(record.studentId); this.removeStudent(record.studentId);
} }
}} }}>
> <span className='live-operate'>移出</span>
<span className="live-operate">移出</span>
</Popconfirm> </Popconfirm>
); );
}, },
}); });
} }
return columns; return columns;
} };
render() { render() {
const { studentList, query, total } = this.state; const { studentList, query, total } = this.state;
const { current, size } = query; const { current, size } = query;
return ( return (
<Modal <Modal
title="查看学员名单" title='查看学员名单'
visible={true} visible={true}
width={680} width={680}
footer={null} footer={null}
maskClosable={false} maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>} closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}
className="live-student-list-modal" className='live-student-list-modal'
onCancel={this.props.close} onCancel={this.props.close}>
>
{/* 任意状态都可以添加学员 */} {/* 任意状态都可以添加学员 */}
<div className="live-student-list-modal__operate"> <div className='live-student-list-modal__operate'>
{ {!isTeacher && (
!isTeacher && <Button type='primary' onClick={this.hanldSelect}>
<Button type="primary" onClick={this.hanldSelect}>
添加上课学员 添加上课学员
</Button> </Button>
} )}
<Search <Search
placeholder="搜索学员姓名/手机号" placeholder='搜索学员姓名/手机号'
style={{ width: 200 }} style={{ width: 200 }}
onSearch={(value) => { onSearch={(value) => {
this.setState({ this.setState(
query: { {
...this.state.query, query: {
nameOrPhone: value ...this.state.query,
nameOrPhone: value,
},
},
() => {
this.fetchStudentList(1);
} }
}, () => { );
this.fetchStudentList(1);
});
}} }}
className="search" className='search'
/> />
</div> </div>
<Table <XMTable
size="small" renderEmpty={{
image: college,
description: '暂无数据',
}}
size='small'
columns={this.parseColumns()} columns={this.parseColumns()}
dataSource={studentList} dataSource={studentList}
pagination={false} pagination={false}
scroll={{ y: 400 }} scroll={{ y: 400 }}
className="live-student-table table-no-scrollbar" className='live-student-table table-no-scrollbar'
/> />
<PageControl <PageControl
size="small" size='small'
current={current - 1} current={current - 1}
pageSize={size} pageSize={size}
total={Number(total)} total={Number(total)}
......
/* /*
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-06-22 14:26:37 * @Date: 2020-06-22 14:26:37
* @Last Modified by: chenshu * @Last Modified by: chenshu
* @Last Modified time: 2021-06-08 18:18:46 * @Last Modified time: 2021-06-08 18:18:46
*/ */
import React from 'react'; import { FileTypeIcon, FileVerifyMap } from '@/common/constants/academic/lessonEnum';
import { Modal, Button, Table, message, Tooltip, Spin, Popconfirm } from 'antd'; import { DEFAULT_SIZE_UNIT, suffixType } from '@/common/constants/academic/liveEnum';
import { QuestionCircleOutlined,LoadingOutlined} from "@ant-design/icons"; import Service from '@/common/js/service';
import _ from 'underscore';
import moment from 'moment';
import Lottie from "lottie-web";
import User from '@/common/js/user'; import User from '@/common/js/user';
import { suffixType, DEFAULT_SIZE_UNIT } from '@/common/constants/academic/liveEnum'; import college from '@/common/lottie/college';
import { FileVerifyMap, FileTypeIcon } from '@/common/constants/academic/lessonEnum'; import { XMTable } from '@/components';
import ScanFileModal from '@/modules/prepare-lesson/modal/ScanFileModal' import ScanFileModal from '@/modules/prepare-lesson/modal/ScanFileModal';
import SelectPrepareFileModal from '@/modules/prepare-lesson/modal/SelectPrepareFileModal'; import SelectPrepareFileModal from '@/modules/prepare-lesson/modal/SelectPrepareFileModal';
import Service from '@/common/js/service'; import { LoadingOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import { Button, message, Modal, Popconfirm, Spin, Tooltip } from 'antd';
import Lottie from 'lottie-web';
import moment from 'moment';
import React from 'react';
import _ from 'underscore';
import './ManageCoursewareModal.less'; import './ManageCoursewareModal.less';
class ManageCoursewareModal extends React.Component { class ManageCoursewareModal extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props);
this.state = { this.state = {
list: [], list: [],
uploadObject: {}, uploadObject: {},
...@@ -32,36 +31,34 @@ class ManageCoursewareModal extends React.Component { ...@@ -32,36 +31,34 @@ class ManageCoursewareModal extends React.Component {
editData: {}, editData: {},
scanFileModal: false, scanFileModal: false,
isLessonPermission: false, isLessonPermission: false,
diskList: [], // 机构可见的磁盘目录 diskList: [], // 机构可见的磁盘目录
selectedFileList: [] selectedFileList: [],
} };
} }
componentDidMount() { componentDidMount() {
this.getCoursewareList(); this.getCoursewareList();
var animation = Lottie.loadAnimation({ var animation = Lottie.loadAnimation({
path: "https://image.xiaomaiketang.com/xm/SDBkP7mbJX.json", path: 'https://image.xiaomaiketang.com/xm/SDBkP7mbJX.json',
name: "test", name: 'test',
renderer: "svg", renderer: 'svg',
loop: true, loop: true,
autoplay: true, autoplay: true,
container: document.getElementById("lottie-box") container: document.getElementById('lottie-box'),
}); });
} }
// 获取课件列表 // 获取课件列表
getCoursewareList(id) { getCoursewareList(id) {
const { liveCourseId } = this.props.data; const { liveCourseId } = this.props.data;
const params={ const params = {
liveCourseId, liveCourseId,
storeId:User.getStoreId() storeId: User.getStoreId(),
} };
Service.Hades('/anon/courseWare/getCourseWareDocList', params).then((res) => { Service.Hades('/anon/courseWare/getCourseWareDocList', params).then((res) => {
let newList = []; let newList = [];
const { list } = this.state; const { list } = this.state;
const data = _.find(res.result, item => item.docId == id); const data = _.find(res.result, (item) => item.docId == id);
if (id && !_.isEmpty(data)) { if (id && !_.isEmpty(data)) {
newList = list.map((item) => { newList = list.map((item) => {
if (item.id == id) { if (item.id == id) {
...@@ -80,7 +77,7 @@ class ManageCoursewareModal extends React.Component { ...@@ -80,7 +77,7 @@ class ManageCoursewareModal extends React.Component {
} else { } else {
return item; return item;
} }
}) });
} else { } else {
newList = res.result.map((item) => { newList = res.result.map((item) => {
item.id = item.docId; item.id = item.docId;
...@@ -98,47 +95,42 @@ class ManageCoursewareModal extends React.Component { ...@@ -98,47 +95,42 @@ class ManageCoursewareModal extends React.Component {
}); });
} }
this.setState({ list: newList }); this.setState({ list: newList });
}) });
} }
// 上传文件 // 上传文件
addFile() { addFile() {
// 判断是否早于开课前30分钟 // 判断是否早于开课前30分钟
const { startTime } = this.props.data; const { startTime } = this.props.data;
const currentTime = new Date().getTime(); const currentTime = new Date().getTime();
if (currentTime >= startTime - 30 * 60 * 1000) { if (currentTime >= startTime - 30 * 60 * 1000) {
Modal.info({ Modal.info({
title: "不能再上传课件了", title: '不能再上传课件了',
icon: ( icon: (
<span <span className='icon iconfont default-confirm-icon' style={{ color: '#FFBB54 !important' }}>
className="icon iconfont default-confirm-icon" &#xe834;
style={{ color: "#FFBB54 !important" }} </span>
> ),
&#xe834; content: '请在开课前30分钟前上传课件,开课后可在客户端中进行上传。',
</span> okText: '我知道了',
), });
content: "请在开课前30分钟前上传课件,开课后可在客户端中进行上传。", return;
okText: '我知道了' }
});
return;
}
const { list } = this.state; const { list } = this.state;
if (list.length >= 20) { if (list.length >= 20) {
message.warning('最多上传20个课件'); message.warning('最多上传20个课件');
return null; return null;
} }
this.setState({ this.setState({
selectedFileList: list, selectedFileList: list,
showSelectFileModal: true, // 选择文件弹窗 showSelectFileModal: true, // 选择文件弹窗
}) });
} }
handleAddFile = (addFolderIds) => { handleAddFile = (addFolderIds) => {
this.setState({ this.setState({
showSelectFileModal: false showSelectFileModal: false,
}); });
const { liveCourseId } = this.props.data; const { liveCourseId } = this.props.data;
...@@ -151,14 +143,14 @@ class ManageCoursewareModal extends React.Component { ...@@ -151,14 +143,14 @@ class ManageCoursewareModal extends React.Component {
Service.Hades('public/courseWare/uploadCourseWareFile', params).then((res) => { Service.Hades('public/courseWare/uploadCourseWareFile', params).then((res) => {
this.getCoursewareList(); this.getCoursewareList();
}); });
} };
// 删除文件 // 删除文件
deleteFile(item) { deleteFile(item) {
const { list } = this.state; const { list } = this.state;
Service.Hades('public/courseWare/delCourseDoc', { docId: item.id }).then(() => { Service.Hades('public/courseWare/delCourseDoc', { docId: item.id }).then(() => {
item.docId && message.success('删除成功') item.docId && message.success('删除成功');
}) });
const _list = _.reject(list, (data) => data.id == item.id); const _list = _.reject(list, (data) => data.id == item.id);
this.setState({ list: _list }); this.setState({ list: _list });
} }
...@@ -168,206 +160,192 @@ class ManageCoursewareModal extends React.Component { ...@@ -168,206 +160,192 @@ class ManageCoursewareModal extends React.Component {
if (!item.srcDocUrl) return null; if (!item.srcDocUrl) return null;
const suffix = _.last(item.fileName.split('.')).toLowerCase(); const suffix = _.last(item.fileName.split('.')).toLowerCase();
const type = suffixType[suffix] const type = suffixType[suffix];
const fileType = FileVerifyMap[type].type; const fileType = FileVerifyMap[type].type;
switch (fileType) { switch (fileType) {
case "PDF": case 'PDF':
window.open(item.srcDocUrl, "_blank"); window.open(item.srcDocUrl, '_blank');
break; break;
case "Excel": case 'Excel':
case "EXCEL": case 'EXCEL':
case "PPT": case 'PPT':
case "PPTX": case 'PPTX':
case "word": case 'word':
case "WORD": case 'WORD':
case "DOCX": case 'DOCX':
case "DOC": case 'DOC':
let size = parseFloat(item.fileSize.replace(/M$|KB$/g, '')); let size = parseFloat(item.fileSize.replace(/M$|KB$/g, ''));
if (item.fileSize.includes('KB')) { if (item.fileSize.includes('KB')) {
size = 0; size = 0;
} }
if (((fileType == 'word' || fileType == 'PPT') && size > 10) || ((fileType == 'Excel') && size > 5)) { if (((fileType == 'word' || fileType == 'PPT') && size > 10) || (fileType == 'Excel' && size > 5)) {
Modal.confirm({ Modal.confirm({
title: '抱歉,不能在线预览', title: '抱歉,不能在线预览',
content: '由于文件较大,不支持在线预览,请下载后再查看', content: '由于文件较大,不支持在线预览,请下载后再查看',
icon: <QuestionCircleOutlined />, icon: <QuestionCircleOutlined />,
okText:"下载", okText: '下载',
onOk:() => { onOk: () => {
const a = document.createElement('a'); const a = document.createElement('a');
a.href = item.srcDocUrl; a.href = item.srcDocUrl;
a.click(); a.click();
} },
}); });
} else { } else {
const scanUrl = "https://view.officeapps.live.com/op/view.aspx?src=" + encodeURIComponent(item.srcDocUrl); const scanUrl = 'https://view.officeapps.live.com/op/view.aspx?src=' + encodeURIComponent(item.srcDocUrl);
window.open(scanUrl, "_blank"); window.open(scanUrl, '_blank');
} }
break; break;
case "JPG": case 'JPG':
case "PNG": case 'PNG':
case "MP4": case 'MP4':
case "MP3": case 'MP3':
this.setState({ scanFileModal: true, editData: { fileType, ossAddress: item.srcDocUrl } }) this.setState({ scanFileModal: true, editData: { fileType, ossAddress: item.srcDocUrl } });
break; break;
default: default:
break; break;
} }
}; }
render() { render() {
const columns = [ const columns = [
{ {
title: "名称", title: '名称',
width: "25%", width: '25%',
dataIndex: "name", dataIndex: 'name',
render: (_value, item) => { render: (_value, item) => {
const suffix = _.last(item.fileName.split('.')).toLowerCase(); const suffix = _.last(item.fileName.split('.')).toLowerCase();
const fileType = suffixType[suffix] const fileType = suffixType[suffix];
const antIcon = <LoadingOutlined/>; const antIcon = <LoadingOutlined />;
const type = FileVerifyMap[fileType].type; const type = FileVerifyMap[fileType].type;
return <div className="courseware-name" onClick={() => this.handleScanFile(item)}> return (
<div className='courseware-name' onClick={() => this.handleScanFile(item)}>
<Choose> <Choose>
<When condition={(type === 'JPG' || type === 'PNG') && item.progress}> <When condition={(type === 'JPG' || type === 'PNG') && item.progress}>
<Spin indicator={antIcon} /> <Spin indicator={antIcon} />
</When> </When>
<Otherwise> <Otherwise>
<img <img src={FileTypeIcon[FileVerifyMap[fileType].type] || (item.docUrls[0] || {}).conversionFileUrl} alt='' className='item-img' />
src={FileTypeIcon[FileVerifyMap[fileType].type] || (item.docUrls[0] || {}).conversionFileUrl}
alt=""
className="item-img"
/>
</Otherwise> </Otherwise>
</Choose> </Choose>
<Tooltip title={item.fileName}><span className="name">{item.fileName}</span></Tooltip> <Tooltip title={item.fileName}>
</div> <span className='name'>{item.fileName}</span>
</Tooltip>
</div>
);
}, },
}, },
{ {
title: "创建人", title: '创建人',
width: "12%", width: '12%',
dataIndex: "adminName", dataIndex: 'adminName',
render: (_value, item) => { render: (_value, item) => {
return <span>{item.operatorName}</span> return <span>{item.operatorName}</span>;
}, },
}, },
{ {
title: "上传时间", title: '上传时间',
width: "20%", width: '20%',
dataIndex: "created", dataIndex: 'created',
render: (_value, item) => { render: (_value, item) => {
return item.failState ? '-' : <span>{moment(item.created).format('YYYY-MM-DD HH:mm')}</span> return item.failState ? '-' : <span>{moment(item.created).format('YYYY-MM-DD HH:mm')}</span>;
}, },
}, },
{ {
title: "大小", title: '大小',
width: "12%", width: '12%',
dataIndex: "size", dataIndex: 'size',
render: (_value, item) => { render: (_value, item) => {
return <span>{item.fileSize}</span> return <span>{item.fileSize}</span>;
}, },
}, },
{ {
title: "操作", title: '操作',
width: "16%", width: '16%',
dataIndex: "control", dataIndex: 'control',
render: (_value, item) => { render: (_value, item) => {
const { failObject } = this.state; const { failObject } = this.state;
const uploadFail = failObject[item.id]; const uploadFail = failObject[item.id];
// 上课前45分钟/上课中/已结束的情况下都不可操作 // 上课前45分钟/上课中/已结束的情况下都不可操作
if (this.props.data.startTime < Date.now() + 1800000 || item.progress || uploadFail) { if (this.props.data.startTime < Date.now() + 1800000 || item.progress || uploadFail) {
return <span>-</span> return <span>-</span>;
} }
return ( return (
<Popconfirm <Popconfirm title='你确定要删除这个课件吗?' onConfirm={() => this.deleteFile(item)} onCancel={() => {}}>
title="你确定要删除这个课件吗?" <span
onConfirm={() => this.deleteFile(item)} style={{
onCancel={() => { }} color: '#2966FF',
> cursor: 'pointer',
<span style={{ }}>
color: '#2966FF', 删除
cursor: 'pointer' </span>
}}>删除</span>
</Popconfirm> </Popconfirm>
) );
}, },
}, },
] ];
const { const { list, scanFileModal, editData, cancelObject, showSelectFileModal, selectedFileList, diskList } = this.state;
list, scanFileModal, editData, cancelObject,
showSelectFileModal, selectedFileList,
diskList
} = this.state;
const _list = _.reject(list, (item) => cancelObject[item.id]); const _list = _.reject(list, (item) => cancelObject[item.id]);
return ( return (
<Modal <Modal
visible={true} visible={true}
title="课件管理" title='课件管理'
footer={null} footer={null}
maskClosable={false} maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>} closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}
className="manage-courseware-modal" className='manage-courseware-modal'
width={_.isEmpty(_list) ? 680 : 800} width={_.isEmpty(_list) ? 680 : 800}
onCancel={() => { onCancel={() => {
this.props.onCancel() this.props.onCancel();
}} }}>
> {_.isEmpty(_list) ? (
{_.isEmpty(_list) ? <div className='empty-body'>
<div className="empty-body"> <div id='lottie-box' className='empty-image'></div>
<div id="lottie-box" className="empty-image"> <Button className='empty-button' type='primary' onClick={() => this.addFile()}>
</div> 上传课件
<Button </Button>
className="empty-button" <p className='empty-tip'>提前上传直播需要的课件和素材,直播将会变得更便捷!</p>
type="primary"
onClick={() => this.addFile()}
>上传课件</Button>
<p className="empty-tip">提前上传直播需要的课件和素材,直播将会变得更便捷!</p>
</div> </div>
: <div className="manage-body"> ) : (
<div id="lottie-box" className="empty-image" style={{display:'none'}}></div> <div className='manage-body'>
<div className="header"> <div id='lottie-box' className='empty-image' style={{ display: 'none' }}></div>
<Button <div className='header'>
className="header-button" <Button className='header-button' type='primary' onClick={() => this.addFile()}>
type="primary" 上传课件
onClick={() => this.addFile()} </Button>
>上传课件</Button>
</div> </div>
<Table <XMTable
size="small" renderEmpty={{
image: college,
description: '暂无数据',
}}
size='small'
pagination={false} pagination={false}
rowKey={record => record.id} rowKey={(record) => record.id}
dataSource={_list} dataSource={_list}
columns={columns} columns={columns}
bordered bordered
/> />
</div> </div>
} )}
{ {scanFileModal && <ScanFileModal item={editData} fileType={editData.fileType} close={() => this.setState({ scanFileModal: false })} />}
scanFileModal &&
<ScanFileModal
item={editData}
fileType={editData.fileType}
close={() => this.setState({ scanFileModal: false })}
/>
}
<SelectPrepareFileModal <SelectPrepareFileModal
multiple={true} multiple={true}
scene="liveCourse" scene='liveCourse'
operateType="select" operateType='select'
isOpen={showSelectFileModal} isOpen={showSelectFileModal}
diskList={diskList} diskList={diskList}
selectedFileList={selectedFileList} selectedFileList={selectedFileList}
onClose={() => { onClose={() => {
this.setState({ showSelectFileModal: false }) this.setState({ showSelectFileModal: false });
}} }}
onSelect={this.handleAddFile} onSelect={this.handleAddFile}
/> />
</Modal> </Modal>
) );
} }
} }
export default ManageCoursewareModal; export default ManageCoursewareModal;
\ No newline at end of file
...@@ -6,21 +6,19 @@ ...@@ -6,21 +6,19 @@
* @LastEditTime: 2021-02-01 14:00:36 * @LastEditTime: 2021-02-01 14:00:36
*/ */
import React, { useState, useEffect } from "react"; import college from '@/common/lottie/college';
import { Modal, Table, Button, message } from "antd"; import { PageControl, XMTable } from '@/components';
import Bus from '@/core/bus'; import Bus from '@/core/bus';
import { PageControl } from "@/components"; import { Button, message, Modal } from 'antd';
import React from 'react';
import hasExportPermission from '../utils/hasExportPermission';
import dealTimeDuration from '../utils/dealTimeDuration'; import dealTimeDuration from '../utils/dealTimeDuration';
import hasExportPermission from '../utils/hasExportPermission';
import "./ClassRecordModal.less"; import './ClassRecordModal.less';
const liveTypeMap = { const liveTypeMap = {
USER: "学生", USER: '学生',
ANCHOR: "老师", ANCHOR: '老师',
ADMIN: "助教", ADMIN: '助教',
}; };
class PlayBackRecordModal extends React.Component { class PlayBackRecordModal extends React.Component {
...@@ -38,7 +36,7 @@ class PlayBackRecordModal extends React.Component { ...@@ -38,7 +36,7 @@ class PlayBackRecordModal extends React.Component {
totalWatchNum: 0, totalWatchNum: 0,
}; };
} }
componentDidMount() { componentDidMount() {
this.fetchPlayBackList(); this.fetchPlayBackList();
} }
...@@ -46,22 +44,20 @@ class PlayBackRecordModal extends React.Component { ...@@ -46,22 +44,20 @@ class PlayBackRecordModal extends React.Component {
fetchPlayBackList = (page = 1) => { fetchPlayBackList = (page = 1) => {
const params = _.clone(this.state.query); const params = _.clone(this.state.query);
params.current = page; params.current = page;
window.axios window.axios.Apollo('public/businessLive/queryUserReplayRecordPage', params).then((res) => {
.Apollo("public/businessLive/queryUserReplayRecordPage", params) const { records = [], total } = res.result;
.then((res) => { this.setState({
const { records = [], total } = res.result; query: params,
this.setState({ total,
query: params, playBackList: records,
total,
playBackList: records,
});
}); });
});
}; };
fetchAllStatistics = () => { fetchAllStatistics = () => {
const { liveCourseId } = this.props.liveItem; const { liveCourseId } = this.props.liveItem;
window.axios window.axios
.Apollo("public/businessLive/queryReplayStatistics", { .Apollo('public/businessLive/queryReplayStatistics', {
liveCourseId, liveCourseId,
}) })
.then((res) => { .then((res) => {
...@@ -80,7 +76,7 @@ class PlayBackRecordModal extends React.Component { ...@@ -80,7 +76,7 @@ class PlayBackRecordModal extends React.Component {
const hours = Math.floor(time / 3600); const hours = Math.floor(time / 3600);
const mins = Math.floor(diff / 60); const mins = Math.floor(diff / 60);
const seconds = Math.floor(time % 60); const seconds = Math.floor(time % 60);
return hours + "小时" + mins + "分"; return hours + '小时' + mins + '分';
}; };
// 导出 // 导出
...@@ -88,126 +84,128 @@ class PlayBackRecordModal extends React.Component { ...@@ -88,126 +84,128 @@ class PlayBackRecordModal extends React.Component {
const { liveItem, type } = this.props; const { liveItem, type } = this.props;
const { liveCourseId } = liveItem; const { liveCourseId } = liveItem;
const url = !type ? 'api-b/b/lesson/exportLargeClassLiveAsync' : 'api-b/b/lesson/exportClassInteractionLiveSync'; const url = !type ? 'api-b/b/lesson/exportLargeClassLiveAsync' : 'api-b/b/lesson/exportClassInteractionLiveSync';
window.axios.post(url, { window.axios
liveCourseId, .post(url, {
exportLiveType: 0 liveCourseId,
}).then((res) => { exportLiveType: 0,
Bus.trigger('get_download_count'); })
Modal.success({ .then((res) => {
title: '导出任务提交成功', Bus.trigger('get_download_count');
content: '请前往右上角的“导出中心”进行下载', Modal.success({
okText: '我知道了', title: '导出任务提交成功',
content: '请前往右上角的“导出中心”进行下载',
okText: '我知道了',
});
}); });
}); };
}
handleExportV5 = () => { handleExportV5 = () => {
const { liveItem, type } = this.props; const { liveItem, type } = this.props;
const { liveCourseId } = liveItem; const { liveCourseId } = liveItem;
const url = !type ? 'public/businessLive/exportLargeClassLiveAsync' : 'public/businessLive/exportClassInteractionLiveSync'; const url = !type ? 'public/businessLive/exportLargeClassLiveAsync' : 'public/businessLive/exportClassInteractionLiveSync';
window.axios.Apollo(url, { window.axios
liveCourseId, .Apollo(url, {
exportLiveType: 'PLAY_BACK' liveCourseId,
}).then((res) => { exportLiveType: 'PLAY_BACK',
Bus.trigger('get_download_count'); })
Modal.success({ .then((res) => {
title: '导出任务提交成功', Bus.trigger('get_download_count');
content: '请前往右上角的“任务中心”进行下载', Modal.success({
okText: '我知道了', title: '导出任务提交成功',
content: '请前往右上角的“任务中心”进行下载',
okText: '我知道了',
});
}); });
}); };
}
render() { render() {
const columns = [ const columns = [
{ {
title: "观看者姓名", title: '观看者姓名',
dataIndex: "userName", dataIndex: 'userName',
}, },
{ {
title: "观看者手机号", title: '观看者手机号',
dataIndex: "phone", dataIndex: 'phone',
render: (text, record) => { render: (text, record) => {
return ( return (
<p> <p>
{!( {!((!window.NewVersion && !window.currentUserInstInfo.teacherId) || (window.NewVersion && Permission.hasEduStudentPhone()))
(!window.NewVersion && !window.currentUserInstInfo.teacherId) || ? (text || '').replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3')
(window.NewVersion && Permission.hasEduStudentPhone())
)
? (text || "").replace(/(\d{3})(\d{4})(\d{4})/, "$1****$3")
: text} : text}
</p> </p>
); );
}, },
}, },
{ {
title: "观看者类型", title: '观看者类型',
dataIndex: "liveRole", dataIndex: 'liveRole',
key: "liveRole", key: 'liveRole',
render: (text) => <span>{liveTypeMap[text]}</span>, render: (text) => <span>{liveTypeMap[text]}</span>,
}, },
{ {
title: "开始观看时间", title: '开始观看时间',
dataIndex: "entryTime", dataIndex: 'entryTime',
key: "entryTime", key: 'entryTime',
render: (text) => ( render: (text) => <span>{text ? formatDate('YYYY-MM-DD H:i', parseInt(text)) : '-'}</span>,
<span>{text ? formatDate("YYYY-MM-DD H:i", parseInt(text)) : '-'}</span>
),
}, },
{ {
title: "观看时长", title: '观看时长',
dataIndex: "lookingDuration", dataIndex: 'lookingDuration',
key: "lookingDuration", key: 'lookingDuration',
render: (text) => { render: (text) => {
return <span>{text ? dealTimeDuration(text) : '-'}</span>; return <span>{text ? dealTimeDuration(text) : '-'}</span>;
}, },
}, },
]; ];
const { const { query, total, playBackList, totalWatchNum, recordDuration } = this.state;
query,
total,
playBackList,
totalWatchNum,
recordDuration,
} = this.state;
const { type } = this.props; const { type } = this.props;
return ( return (
<Modal <Modal
title="回放记录" title='回放记录'
className="play-back-modal" className='play-back-modal'
width={680} width={680}
visible={true} visible={true}
maskClosable={false} maskClosable={false}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>} closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}
footer={null} footer={null}
onCancel={() => { onCancel={() => {
this.props.close(); this.props.close();
}} }}>
> {hasExportPermission(type) && (
{ <Button
hasExportPermission(type) && onClick={_.debounce(
<Button onClick={_.debounce(() => { () => {
if (!playBackList.length) { if (!playBackList.length) {
message.warning('暂无数据可导出'); message.warning('暂无数据可导出');
return; return;
} }
if (window.NewVersion) { if (window.NewVersion) {
this.handleExportV5(); this.handleExportV5();
} else { } else {
this.handleExport(); this.handleExport();
} }
}, 500, true)}>导出</Button> },
} 500,
<Table true
size="small" )}>
导出
</Button>
)}
<XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
size='small'
columns={columns} columns={columns}
dataSource={playBackList} dataSource={playBackList}
pagination={false} pagination={false}
className="table-no-scrollbar" className='table-no-scrollbar'
/> />
<PageControl <PageControl
size="small" size='small'
current={query.current - 1} current={query.current - 1}
pageSize={query.size} pageSize={query.size}
total={total} total={total}
......
import React from 'react' import User from '@/common/js/user';
import { Table, Modal, Input } from 'antd' import college from '@/common/lottie/college';
import { PageControl } from '@/components' import { PageControl, XMTable } from '@/components';
import CourseService from '@/domains/course-domain/CourseService' import CourseService from '@/domains/course-domain/CourseService';
import PlanService from '@/domains/plan-domain/planService' import PlanService from '@/domains/plan-domain/planService';
import User from '@/common/js/user' import { Input, Modal } from 'antd';
import './RelatedPlanModal.less' import React from 'react';
import _ from 'underscore' import _ from 'underscore';
const { Search } = Input import './RelatedPlanModal.less';
const { Search } = Input;
class RelatedPlanModal extends React.Component { class RelatedPlanModal extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props);
this.state = { this.state = {
dataSource: [], dataSource: [],
size: 10, size: 10,
query: { query: {
current: 1 current: 1,
}, },
totalCount: 0, totalCount: 0,
selectPlanList: {} selectPlanList: {},
} };
} }
componentDidMount() { componentDidMount() {
this.handleFetchDataList() this.handleFetchDataList();
} }
// 获取培训计划列表 // 获取培训计划列表
handleFetchDataList = () => { handleFetchDataList = () => {
const { query, size } = this.state const { query, size } = this.state;
const params = { const params = {
...query, ...query,
size, size,
storeId: User.getStoreId() storeId: User.getStoreId(),
} };
PlanService.getStorePlanAll(params).then((res) => { PlanService.getStorePlanAll(params).then((res) => {
const { result = {} } = res const { result = {} } = res;
const { records = [], total = 0 } = result const { records = [], total = 0 } = result;
this.setState({ this.setState({
dataSource: records, dataSource: records,
totalCount: Number(total) totalCount: Number(total),
}) });
}) });
} };
handleChangePlanName = (value) => { handleChangePlanName = (value) => {
const { query } = this.state const { query } = this.state;
query.planName = value query.planName = value;
query.current = 1 query.current = 1;
this.setState({ this.setState({
query query,
}) });
} };
onShowSizeChange = (current, size) => { onShowSizeChange = (current, size) => {
if (current == size) { if (current == size) {
return return;
} }
this.setState( this.setState(
{ {
size size,
}, },
() => { () => {
this.handleFetchDataList() this.handleFetchDataList();
} }
) );
} };
// 请求表头 // 请求表头
parsePlanColumns = () => { parsePlanColumns = () => {
...@@ -72,12 +73,12 @@ class RelatedPlanModal extends React.Component { ...@@ -72,12 +73,12 @@ class RelatedPlanModal extends React.Component {
key: 'planName', key: 'planName',
dataIndex: 'planName', dataIndex: 'planName',
render: (val, record) => { render: (val, record) => {
return <span>{val}</span> return <span>{val}</span>;
} },
} },
] ];
return columns return columns;
} };
parseTaskColumns = (parentIndex) => { parseTaskColumns = (parentIndex) => {
const columns = [ const columns = [
...@@ -86,76 +87,76 @@ class RelatedPlanModal extends React.Component { ...@@ -86,76 +87,76 @@ class RelatedPlanModal extends React.Component {
key: 'taskName', key: 'taskName',
dataIndex: 'taskName', dataIndex: 'taskName',
render: (val, record) => { render: (val, record) => {
return <span>{val}</span> return <span>{val}</span>;
} },
} },
] ];
return columns return columns;
} };
selectPlanList = (record, selected, planId) => { selectPlanList = (record, selected, planId) => {
const { selectPlanList } = this.props const { selectPlanList } = this.props;
let _selectPlanList = { ...selectPlanList } let _selectPlanList = { ...selectPlanList };
if (selected) { if (selected) {
if (!_selectPlanList[planId]) { if (!_selectPlanList[planId]) {
_selectPlanList[planId] = {} _selectPlanList[planId] = {};
} }
_selectPlanList[planId].taskBaseVOList = [] _selectPlanList[planId].taskBaseVOList = [];
_selectPlanList[planId].planId = planId _selectPlanList[planId].planId = planId;
_selectPlanList[planId].taskBaseVOList.push(record) _selectPlanList[planId].taskBaseVOList.push(record);
} else { } else {
if (!_selectPlanList[planId]) { if (!_selectPlanList[planId]) {
_selectPlanList[planId] = {} _selectPlanList[planId] = {};
} }
_selectPlanList[planId].taskBaseVOList = [] _selectPlanList[planId].taskBaseVOList = [];
_selectPlanList[planId].planId = planId _selectPlanList[planId].planId = planId;
} }
this.props.onChange(_selectPlanList) this.props.onChange(_selectPlanList);
// this.setState({selectPlanList:_selectPlanList}); // this.setState({selectPlanList:_selectPlanList});
} };
handleSelectPlanListData(selectPlanList) { handleSelectPlanListData(selectPlanList) {
let _selectPlanList = [] let _selectPlanList = [];
for (let key in selectPlanList) { for (let key in selectPlanList) {
let item = {} let item = {};
if (selectPlanList[key].taskBaseVOList) { if (selectPlanList[key].taskBaseVOList) {
item.planId = selectPlanList[key].planId item.planId = selectPlanList[key].planId;
if (selectPlanList[key].taskBaseVOList[0]) { if (selectPlanList[key].taskBaseVOList[0]) {
item.taskId = selectPlanList[key].taskBaseVOList[0].taskId item.taskId = selectPlanList[key].taskBaseVOList[0].taskId;
} }
} }
if (item.taskId) { if (item.taskId) {
_selectPlanList.push(item) _selectPlanList.push(item);
} }
} }
return _selectPlanList return _selectPlanList;
} }
confirmRelatedPlan = () => { confirmRelatedPlan = () => {
const { selectPlanList } = this.props const { selectPlanList } = this.props;
const params = { const params = {
courseId: this.props.selectCourseId, courseId: this.props.selectCourseId,
relatedPlanList: this.handleSelectPlanListData(selectPlanList), relatedPlanList: this.handleSelectPlanListData(selectPlanList),
storeId: User.getStoreId() storeId: User.getStoreId(),
} };
CourseService.relatedCourseToPlan(params).then((res) => { CourseService.relatedCourseToPlan(params).then((res) => {
this.props.onConfirm() this.props.onConfirm();
}) });
} };
getSelectLength = (selectList) => { getSelectLength = (selectList) => {
let num = 0 let num = 0;
for (let key in selectList) { for (let key in selectList) {
if (selectList[key].taskBaseVOList.length > 0) { if (selectList[key].taskBaseVOList.length > 0) {
num = num + 1 num = num + 1;
} }
} }
return num return num;
} };
clearSelect = () => { clearSelect = () => {
const _selectPlanList = {} const _selectPlanList = {};
this.props.onChange(_selectPlanList) this.props.onChange(_selectPlanList);
} };
render() { render() {
const { size, dataSource, totalCount, query } = this.state const { size, dataSource, totalCount, query } = this.state;
const { visible, selectPlanList } = this.props const { visible, selectPlanList } = this.props;
return ( return (
<Modal <Modal
title='关联培训计划' title='关联培训计划'
...@@ -172,10 +173,10 @@ class RelatedPlanModal extends React.Component { ...@@ -172,10 +173,10 @@ class RelatedPlanModal extends React.Component {
placeholder='搜索培训计划名称' placeholder='搜索培训计划名称'
style={{ width: 207 }} style={{ width: 207 }}
onChange={(e) => { onChange={(e) => {
this.handleChangePlanName(e.target.value) this.handleChangePlanName(e.target.value);
}} }}
onSearch={() => { onSearch={() => {
this.handleFetchDataList() this.handleFetchDataList();
}} }}
enterButton={<span className='icon iconfont'>&#xe832;</span>} enterButton={<span className='icon iconfont'>&#xe832;</span>}
/> />
...@@ -194,7 +195,11 @@ class RelatedPlanModal extends React.Component { ...@@ -194,7 +195,11 @@ class RelatedPlanModal extends React.Component {
</span> </span>
</div> </div>
<div> <div>
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
rowKey={(record) => record.planId} rowKey={(record) => record.planId}
className='plan-table' className='plan-table'
dataSource={dataSource} dataSource={dataSource}
...@@ -202,20 +207,24 @@ class RelatedPlanModal extends React.Component { ...@@ -202,20 +207,24 @@ class RelatedPlanModal extends React.Component {
pagination={false} pagination={false}
expandedRowRender={(_record, index) => { expandedRowRender={(_record, index) => {
if (!_record.taskBaseVOList) { if (!_record.taskBaseVOList) {
return return;
} }
if (_record.taskBaseVOList.length !== 0) { if (_record.taskBaseVOList.length !== 0) {
const selectPlan = selectPlanList[_record.planId] const selectPlan = selectPlanList[_record.planId];
let taskBaseVOList = [] let taskBaseVOList = [];
if (selectPlan) { if (selectPlan) {
taskBaseVOList = selectPlan.taskBaseVOList taskBaseVOList = selectPlan.taskBaseVOList;
} }
console.log('taskBaseVOList', taskBaseVOList) console.log('taskBaseVOList', taskBaseVOList);
return ( return (
<div> <div>
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
rowKey={(record) => record.taskId} rowKey={(record) => record.taskId}
pagination={false} pagination={false}
dataSource={_record.taskBaseVOList} dataSource={_record.taskBaseVOList}
...@@ -225,20 +234,20 @@ class RelatedPlanModal extends React.Component { ...@@ -225,20 +234,20 @@ class RelatedPlanModal extends React.Component {
type: 'checkbox', type: 'checkbox',
selectedRowKeys: _.pluck(taskBaseVOList, 'taskId'), selectedRowKeys: _.pluck(taskBaseVOList, 'taskId'),
onSelect: (record, selected) => { onSelect: (record, selected) => {
this.selectPlanList(record, selected, _record.planId) this.selectPlanList(record, selected, _record.planId);
}, },
onSelectAll: (selected, _selectedRows, changeRows) => {} onSelectAll: (selected, _selectedRows, changeRows) => {},
}} }}
/> />
</div> </div>
) );
} }
}} }}
rowClassName={(record, index) => { rowClassName={(record, index) => {
if (index % 2 === 0) { if (index % 2 === 0) {
return 'odd-row' return 'odd-row';
} else { } else {
return 'even-row' return 'even-row';
} }
}} }}
/> />
...@@ -250,15 +259,15 @@ class RelatedPlanModal extends React.Component { ...@@ -250,15 +259,15 @@ class RelatedPlanModal extends React.Component {
total={totalCount} total={totalCount}
size='small' size='small'
toPage={(page) => { toPage={(page) => {
const _query = { ...query, current: page + 1 } const _query = { ...query, current: page + 1 };
this.setState( this.setState(
{ {
query: _query query: _query,
}, },
() => { () => {
this.handleFetchDataList() this.handleFetchDataList();
} }
) );
}} }}
onShowSizeChange={this.onShowSizeChange} onShowSizeChange={this.onShowSizeChange}
/> />
...@@ -266,8 +275,8 @@ class RelatedPlanModal extends React.Component { ...@@ -266,8 +275,8 @@ class RelatedPlanModal extends React.Component {
)} )}
</div> </div>
</Modal> </Modal>
) );
} }
} }
export default RelatedPlanModal export default RelatedPlanModal;
...@@ -7,41 +7,43 @@ ...@@ -7,41 +7,43 @@
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
*/ */
import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components';
import { Dropdown, Menu, Tooltip } from 'antd';
import React from 'react'; import React from 'react';
import { Table, Tooltip, Menu, Dropdown } from 'antd';
import _ from 'underscore'; import _ from 'underscore';
import Bus from '@/core/bus';
import { PageControl } from '@/components';
let resourceData = {}; let resourceData = {};
_.map(window.RESOURCE, item => { _.map(window.RESOURCE, (item) => {
resourceData[item.code] = item.name resourceData[item.code] = item.name;
}); });
const isNewVersion = window.NewVersion; const isNewVersion = window.NewVersion;
class StudentList extends React.Component { class StudentList extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
showDegiest: false, showDegiest: false,
selectedRows: [], selectedRows: [],
prevSelectRows: props.savedSelectedRows || [], prevSelectRows: props.savedSelectedRows || [],
savedSelectedRows: props.savedSelectedRows || [] savedSelectedRows: props.savedSelectedRows || [],
} };
} }
parseColumns = () => { parseColumns = () => {
const { query: { status }, type, studentType } = this.props; const {
query: { status },
type,
studentType,
} = this.props;
// 是否是在读学员 // 是否是在读学员
const isNormal = (status === 'NORMAL' || status === 1); const isNormal = status === 'NORMAL' || status === 1;
// 是否是潜在学员 // 是否是潜在学员
const isPotential = (status === 'POTENTIAL' || status === 2); const isPotential = status === 'POTENTIAL' || status === 2;
// 是否是历史学员 // 是否是历史学员
const isHistory = (status === 'HISTORY' || status === 4); const isHistory = status === 'HISTORY' || status === 4;
const columns = [ const columns = [
{ {
title: '姓名', title: '姓名',
...@@ -50,7 +52,7 @@ class StudentList extends React.Component { ...@@ -50,7 +52,7 @@ class StudentList extends React.Component {
render: (text, record) => { render: (text, record) => {
const { studentBasicVO = {}, name } = record; const { studentBasicVO = {}, name } = record;
return studentBasicVO.name || name; return studentBasicVO.name || name;
} },
}, },
{ {
title: '手机号', title: '手机号',
...@@ -58,150 +60,150 @@ class StudentList extends React.Component { ...@@ -58,150 +60,150 @@ class StudentList extends React.Component {
render: (text, record) => { render: (text, record) => {
const { type } = this.props; const { type } = this.props;
const { studentBasicVO = {}, phone, weChatStatus, wechatStatus } = record; const { studentBasicVO = {}, phone, weChatStatus, wechatStatus } = record;
const { NewVersion, currentUserInstInfo: { teacherId } } = window; const {
NewVersion,
currentUserInstInfo: { teacherId },
} = window;
return ( return (
<div className="record__item"> <div className='record__item'>
{ {!((!NewVersion && !teacherId) || (NewVersion && Permission.hasEduStudentPhone()))
!((!NewVersion && !teacherId) || (NewVersion && Permission.hasEduStudentPhone())) ? ? (studentBasicVO.phone || phone).replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3')
(studentBasicVO.phone || phone).replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3') : : studentBasicVO.phone || phone}
studentBasicVO.phone || phone {type !== 'videoCourse' && (
} // 此处为了兼容4.0 和 5.0的扣课 不扣课学员的绑定微信
{ <Tooltip title={`${studentBasicVO.weChatStatus || weChatStatus || wechatStatus ? '已绑定微信' : '未绑定微信'}`}>
type !== 'videoCourse' &&
// 此处为了兼容4.0 和 5.0的扣课 不扣课学员的绑定微信
<Tooltip
title={`${(studentBasicVO.weChatStatus || weChatStatus || wechatStatus) ? '已绑定微信' : '未绑定微信'}`}
>
<span <span
className="iconfont icon" className='iconfont icon'
style={(studentBasicVO.weChatStatus || weChatStatus || wechatStatus) ? { style={
color: '#00D20D', studentBasicVO.weChatStatus || weChatStatus || wechatStatus
fontSize: '16px', ? {
marginLeft: 6 color: '#00D20D',
} : { fontSize: '16px',
fontSize: '16px', marginLeft: 6,
color:'#BFBFBF', }
marginLeft: 6 : {
}} fontSize: '16px',
>&#xe68d;</span> color: '#BFBFBF',
marginLeft: 6,
}
}>
&#xe68d;
</span>
</Tooltip> </Tooltip>
} )}
</div> </div>
) );
} },
} },
]; ];
// 扣课时学员显示消耗课程和剩余课时 // 扣课时学员显示消耗课程和剩余课时
if (studentType === 'DEDUCTION') { if (studentType === 'DEDUCTION') {
const { consumeStudentList } = this.props; const { consumeStudentList } = this.props;
columns.push({ columns.push(
title: ( {
<div className="consumption-course"> title: (
<span className="text">消耗课程</span> <div className='consumption-course'>
<Tooltip title="学员在这上课所消耗的课程"> <span className='text'>消耗课程</span>
<span className="icon iconfont">&#xe6f2;</span> <Tooltip title='学员在这上课所消耗的课程'>
</Tooltip> <span className='icon iconfont'>&#xe6f2;</span>
</div> </Tooltip>
), </div>
key: 'courseName', ),
dataIndex: 'courseName', key: 'courseName',
render: (val, record) => { dataIndex: 'courseName',
const { consumeStudentList } = this.props; render: (val, record) => {
const { digestHourVOS, studentId } = record; const { consumeStudentList } = this.props;
const { digestHourVOS, studentId } = record;
if (!digestHourVOS || !digestHourVOS.length) {
return <span className="digest-hour--empty">无可消耗课程</span> if (!digestHourVOS || !digestHourVOS.length) {
} else if (digestHourVOS.length === 1) { return <span className='digest-hour--empty'>无可消耗课程</span>;
return <span className="course-name">{digestHourVOS[0].courseName}</span> } else if (digestHourVOS.length === 1) {
} else { return <span className='course-name'>{digestHourVOS[0].courseName}</span>;
const { showDegiest, currentCourse } = this.state; } else {
// 默认显示第一个课程包的名称 const { showDegiest, currentCourse } = this.state;
let _currentCourse = digestHourVOS[0]; // 默认显示第一个课程包的名称
let _currentCourse = digestHourVOS[0];
// 判断学员是否被勾选了
const hasSelect = _.find(consumeStudentList, item => { // 判断学员是否被勾选了
return item.studentId === studentId; const hasSelect = _.find(consumeStudentList, (item) => {
}); return item.studentId === studentId;
// 如果被勾选了,再判断选中的课时包是哪个
if (hasSelect) {
const hasSelectCourse = _.find(digestHourVOS, item => {
return item.courseId === hasSelect.classHourId
}); });
if (hasSelectCourse) {
_currentCourse = hasSelectCourse // 如果被勾选了,再判断选中的课时包是哪个
if (hasSelect) {
const hasSelectCourse = _.find(digestHourVOS, (item) => {
return item.courseId === hasSelect.classHourId;
});
if (hasSelectCourse) {
_currentCourse = hasSelectCourse;
}
}
// 选择课时包之后, 根据学员ID判断选择的是哪个学员的课时包
if (currentCourse && currentCourse.studentId === studentId) {
_currentCourse = currentCourse;
}
if (this.isDisabledRow(record)) {
return <span className='course-name'>{_currentCourse.courseName}</span>;
} else {
return (
<Dropdown overlay={this.renderCourseMenu(digestHourVOS)} placement='bottomCenter' arrow>
<div
className='digest-hour'
onMouseEnter={() => {
this.setState({ showDegiest: true });
}}>
<span className='course-name'>{_currentCourse.courseName}</span>
{digestHourVOS.length > 1 && !this.isDisabledRow(record) && (
<span className={`icon iconfont ${showDegiest ? 'show' : 'hidden'}`}>&#xe6fa;</span>
)}
</div>
</Dropdown>
);
} }
} }
// 选择课时包之后, 根据学员ID判断选择的是哪个学员的课时包 },
if (currentCourse && currentCourse.studentId === studentId) { },
_currentCourse = currentCourse; {
} title: '剩余课时',
key: 'leftLessons',
dataIndex: 'leftLessons',
render: (val, record) => {
const { consumeStudentList } = this.props;
const { digestHourVOS, studentId } = record;
if (this.isDisabledRow(record)) { if (!digestHourVOS || !digestHourVOS.length) {
return <span className="course-name">{_currentCourse.courseName}</span> return '-';
} else if (digestHourVOS.length === 1) {
return digestHourVOS[0].leftLessons;
} else { } else {
return ( const { currentCourse } = this.state;
<Dropdown let _currentCourse = digestHourVOS[0];
overlay={this.renderCourseMenu(digestHourVOS)} // 判断学员是否被选中了
placement="bottomCenter" const hasSelect = _.find(consumeStudentList, (item) => {
arrow return item.studentId === studentId;
>
<div
className="digest-hour"
onMouseEnter={() => {
this.setState({ showDegiest: true });
}}
>
<span className="course-name">{_currentCourse.courseName}</span>
{
digestHourVOS.length > 1 && !this.isDisabledRow(record) &&
<span className={`icon iconfont ${showDegiest ? 'show' : 'hidden'}`}>&#xe6fa;</span>
}
</div>
</Dropdown>
)
}
}
}
}, {
title: '剩余课时',
key: 'leftLessons',
dataIndex: 'leftLessons',
render: (val, record) => {
const { consumeStudentList } = this.props;
const { digestHourVOS, studentId } = record;
if (!digestHourVOS || !digestHourVOS.length) {
return '-'
} else if (digestHourVOS.length === 1) {
return digestHourVOS[0].leftLessons;
} else {
const { currentCourse } = this.state;
let _currentCourse = digestHourVOS[0];
// 判断学员是否被选中了
const hasSelect = _.find(consumeStudentList, item => {
return item.studentId === studentId;
});
// 如果学员被勾选了,再判断该学员选择的课程包是哪个
if (hasSelect) {
const hasSelectCourse = _.find(digestHourVOS, item => {
return item.courseId === hasSelect.classHourId
}); });
if (hasSelectCourse) { // 如果学员被勾选了,再判断该学员选择的课程包是哪个
_currentCourse = hasSelectCourse if (hasSelect) {
const hasSelectCourse = _.find(digestHourVOS, (item) => {
return item.courseId === hasSelect.classHourId;
});
if (hasSelectCourse) {
_currentCourse = hasSelectCourse;
}
} }
// 选择课时包之后, 根据学员ID判断选择的是哪个学员的课时包
if (currentCourse && currentCourse.studentId === studentId) {
_currentCourse = currentCourse;
}
return _currentCourse.leftLessons;
} }
// 选择课时包之后, 根据学员ID判断选择的是哪个学员的课时包 },
if (currentCourse && currentCourse.studentId === studentId) {
_currentCourse = currentCourse;
}
return _currentCourse.leftLessons;
}
} }
}) );
} }
// 在读学员显示年级 // 在读学员显示年级
if (type === 'videoCourse' && isNormal) { if (type === 'videoCourse' && isNormal) {
...@@ -210,110 +212,120 @@ class StudentList extends React.Component { ...@@ -210,110 +212,120 @@ class StudentList extends React.Component {
dataIndex: 'gradeName', dataIndex: 'gradeName',
render: (text, record) => { render: (text, record) => {
const { studentBasicVO = {}, gradeName } = record; const { studentBasicVO = {}, gradeName } = record;
return studentBasicVO.gradeName || gradeName; return studentBasicVO.gradeName || gradeName;
} },
}) });
} }
// 潜在学员显示跟进人和学员来源 // 潜在学员显示跟进人和学员来源
if (isPotential) { if (isPotential) {
columns.push({ columns.push(
title: '跟进人', {
dataIndex: 'saleName', title: '跟进人',
render: (val, record) => { dataIndex: 'saleName',
const { studentSaleVO = {}, saleName } = record; render: (val, record) => {
return studentSaleVO.saleName || saleName; const { studentSaleVO = {}, saleName } = record;
} return studentSaleVO.saleName || saleName;
}, { },
title: '学员来源', },
dataIndex: 'resourceType', {
render: (val, record) => { title: '学员来源',
const { studentSaleVO = {}, resourceType } = record; dataIndex: 'resourceType',
return resourceData[studentSaleVO.resourceType || resourceType]; render: (val, record) => {
const { studentSaleVO = {}, resourceType } = record;
return resourceData[studentSaleVO.resourceType || resourceType];
},
} }
}); );
} }
// 历史学员显示结业时间和报读课程 // 历史学员显示结业时间和报读课程
if (isHistory) { if (isHistory) {
columns.push({ columns.push(
title: '结业时间', {
key: 'graduationTime', title: '结业时间',
dataIndex: 'graduationTime', key: 'graduationTime',
width: 200, dataIndex: 'graduationTime',
render: (val, record) => { width: 200,
const { studentHistoryVO = {}, graduationTime } = record; render: (val, record) => {
return formatDate('YYYY-MM-DD', (studentHistoryVO.graduationTime || graduationTime)) const { studentHistoryVO = {}, graduationTime } = record;
} return formatDate('YYYY-MM-DD', studentHistoryVO.graduationTime || graduationTime);
}, { },
title: '报读课程', },
key: 'lostCourseName', {
dataIndex: 'lostCourseName', title: '报读课程',
width: 150, key: 'lostCourseName',
render: (val, record) => { dataIndex: 'lostCourseName',
const { studentHistoryVO = {}, lostCourseName } = record; width: 150,
return studentHistoryVO.lostCourseName || lostCourseName render: (val, record) => {
const { studentHistoryVO = {}, lostCourseName } = record;
return studentHistoryVO.lostCourseName || lostCourseName;
},
} }
}); );
} }
return columns; return columns;
} };
// 课程下拉选项 // 课程下拉选项
renderCourseMenu = (courseList) => { renderCourseMenu = (courseList) => {
return ( return (
<Menu> <Menu>
{ {_.map(courseList, (item) => {
_.map(courseList, (item) => { return (
return ( <Menu.Item
<Menu.Item onClick={(e) => { this.handleSelectCourse(e, item)} }> onClick={(e) => {
{ item.courseName } this.handleSelectCourse(e, item);
</Menu.Item> }}>
) {item.courseName}
}) </Menu.Item>
} );
})}
</Menu> </Menu>
) );
} };
// 选择当前课程 // 选择当前课程
handleSelectCourse = (e, currentCourse) => { handleSelectCourse = (e, currentCourse) => {
e.domEvent.stopPropagation(); e.domEvent.stopPropagation();
this.setState({ this.setState(
currentCourse, {
showDegiest: false, currentCourse,
}, () => { showDegiest: false,
const { consumeStudentList = [], studentIds, excludeIds } = this.props; },
const { prevSelectRows } = this.state; () => {
const { studentId, courseId, leftLessons, name, phone } = currentCourse; const { consumeStudentList = [], studentIds, excludeIds } = this.props;
let _consumeStudentList = consumeStudentList; const { prevSelectRows } = this.state;
// 选完课时包之后,自动勾选当前学员 const { studentId, courseId, leftLessons, name, phone } = currentCourse;
const _studentIds = [...studentIds, studentId]; let _consumeStudentList = consumeStudentList;
// 选完课时包之后,自动勾选当前学员
const hasExist = _.find(consumeStudentList, item => { const _studentIds = [...studentIds, studentId];
return item.studentId === studentId
});
if (hasExist) { const hasExist = _.find(consumeStudentList, (item) => {
_consumeStudentList = _.map(consumeStudentList, item => { return item.studentId === studentId;
if (item.studentId === studentId) {
item.classHourId = courseId;
}
return item;
}); });
} else {
_consumeStudentList.push({
name,
phone,
studentId,
classHourId: courseId,
consumeHourNum: leftLessons
})
}
this.props.onSelect(_studentIds , _consumeStudentList, prevSelectRows); if (hasExist) {
}); _consumeStudentList = _.map(consumeStudentList, (item) => {
} if (item.studentId === studentId) {
item.classHourId = courseId;
}
return item;
});
} else {
_consumeStudentList.push({
name,
phone,
studentId,
classHourId: courseId,
consumeHourNum: leftLessons,
});
}
this.props.onSelect(_studentIds, _consumeStudentList, prevSelectRows);
}
);
};
handleSelect = (selectedRowKeys, selectedRows) => { handleSelect = (selectedRowKeys, selectedRows) => {
const { studentType, allstudentList, consumeStudentList } = this.props; const { studentType, allstudentList, consumeStudentList } = this.props;
...@@ -325,121 +337,113 @@ class StudentList extends React.Component { ...@@ -325,121 +337,113 @@ class StudentList extends React.Component {
let { currentCourse, prevSelectRows } = this.state; let { currentCourse, prevSelectRows } = this.state;
prevSelectRows = _.filter(prevSelectRows, (item) => { prevSelectRows = _.filter(prevSelectRows, (item) => {
return allStudentIds.indexOf(item.studentId) === -1 return allStudentIds.indexOf(item.studentId) === -1;
}); });
const savedSelectedRows = [...prevSelectRows, ...selectedRows]; const savedSelectedRows = [...prevSelectRows, ...selectedRows];
allSelectRows = savedSelectedRows.map((item) => { allSelectRows = savedSelectedRows.map((item) => {
const { studentId, digestHourVOS = [], name, phone } = item; const { studentId, digestHourVOS = [], name, phone } = item;
// 如果该学员已经被选择了 // 如果该学员已经被选择了
const hasSelectItem = _.find(consumeStudentList, _item => { const hasSelectItem = _.find(consumeStudentList, (_item) => {
return _item.studentId === item.studentId; return _item.studentId === item.studentId;
}); });
if (hasSelectItem) { if (hasSelectItem) {
return hasSelectItem; return hasSelectItem;
} }
return { return {
name, name,
phone, phone,
studentId, studentId,
classHourId: digestHourVOS[0].courseId, classHourId: digestHourVOS[0].courseId,
consumeHourNum: digestHourVOS[0].leftLessons consumeHourNum: digestHourVOS[0].leftLessons,
} };
}); });
this.setState({ this.setState(
selectedRows, {
savedSelectedRows selectedRows,
}, () => { savedSelectedRows,
this.props.onSelect(studentIds, allSelectRows, savedSelectedRows); },
}); () => {
this.props.onSelect(studentIds, allSelectRows, savedSelectedRows);
}
);
} else { } else {
this.props.onSelect(studentIds); this.props.onSelect(studentIds);
} }
} };
isDisabledRow = (record) => { isDisabledRow = (record) => {
// 扣课时的情况下, 无消耗课程的禁用 // 扣课时的情况下, 无消耗课程的禁用
const { const { after, excludeIds, studentType, studentList = [], consumeStudentList = [] } = this.props;
after,
excludeIds,
studentType,
studentList = [],
consumeStudentList = []
} = this.props;
const { digestHourVOS } = record; const { digestHourVOS } = record;
const hasDigestHours = digestHourVOS && digestHourVOS.length; const hasDigestHours = digestHourVOS && digestHourVOS.length;
// 已经入库的学员不可再选择 // 已经入库的学员不可再选择
const hasSelect = _.find(excludeIds, item => { const hasSelect = _.find(excludeIds, (item) => {
return item == record.studentId return item == record.studentId;
}); });
let disabled = false; let disabled = false;
// 扣课时学员课时为0的情况下禁止选择 // 扣课时学员课时为0的情况下禁止选择
if (studentType === 'DEDUCTION') { if (studentType === 'DEDUCTION') {
// 判断是否已经在不扣课时里 // 判断是否已经在不扣课时里
if (_.find(studentList, item => item.studentId === record.studentId)) { if (_.find(studentList, (item) => item.studentId === record.studentId)) {
disabled = true; disabled = true;
} else if (!hasDigestHours || (after && !!hasSelect)) { } else if (!hasDigestHours || (after && !!hasSelect)) {
disabled = true; disabled = true;
} }
} else { } else {
if (_.find(consumeStudentList, item => item.studentId === record.studentId)) { if (_.find(consumeStudentList, (item) => item.studentId === record.studentId)) {
disabled = true; disabled = true;
} else if (after && !!hasSelect) { } else if (after && !!hasSelect) {
disabled = true disabled = true;
} }
} }
return disabled return disabled;
} };
render() { render() {
const { const { after, query, totalCount, studentIds, allstudentList } = this.props;
after,
query,
totalCount,
studentIds,
allstudentList,
} = this.props;
const { prevSelectRows, selectedRows } = this.state; const { prevSelectRows, selectedRows } = this.state;
const { current, size, pageNo, pageSize, } = query; const { current, size, pageNo, pageSize } = query;
const rowSelection = { const rowSelection = {
selectedRowKeys: studentIds, selectedRowKeys: studentIds,
onChange: this.handleSelect, onChange: this.handleSelect,
getCheckboxProps: (record) => { getCheckboxProps: (record) => {
return { return {
disabled: this.isDisabledRow(record) disabled: this.isDisabledRow(record),
} };
} },
}; };
return ( return (
<div className="student-list"> <div className='student-list'>
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
bordered bordered
size={'small'} size={'small'}
rowKey={item => item.studentId} rowKey={(item) => item.studentId}
dataSource={allstudentList} dataSource={allstudentList}
columns={this.parseColumns()} columns={this.parseColumns()}
rowSelection={rowSelection} rowSelection={rowSelection}
onRow={record => ({ onRow={(record) => ({
onClick: e => { onClick: (e) => {
e.currentTarget e.currentTarget.getElementsByClassName('ant-checkbox-wrapper')[0].click();
.getElementsByClassName("ant-checkbox-wrapper")[0] },
.click();
}
})} })}
scroll={{ y: 350 }} scroll={{ y: 350 }}
pagination={false} pagination={false}
/> />
{ {isNewVersion ? (
isNewVersion ?
<PageControl <PageControl
size="small" size='small'
current={current - 1} current={current - 1}
pageSize={size} pageSize={size}
total={totalCount} total={totalCount}
...@@ -451,9 +455,10 @@ class StudentList extends React.Component { ...@@ -451,9 +455,10 @@ class StudentList extends React.Component {
onShowSizeChange={(current, size) => { onShowSizeChange={(current, size) => {
this.props.onChange('size', size); this.props.onChange('size', size);
}} }}
/> : />
) : (
<PageControl <PageControl
size="small" size='small'
current={pageNo} current={pageNo}
pageSize={pageSize} pageSize={pageSize}
total={totalCount} total={totalCount}
...@@ -464,10 +469,10 @@ class StudentList extends React.Component { ...@@ -464,10 +469,10 @@ class StudentList extends React.Component {
onShowSizeChange={(pageNo, pageSize) => { onShowSizeChange={(pageNo, pageSize) => {
this.props.onChange('pageNo', pageSize); this.props.onChange('pageNo', pageSize);
}} }}
/> />
} )}
</div> </div>
) );
} }
} }
......
import React from 'react'; import Service from '@/common/js/service';
import { Tooltip, Input, Radio, Table, Checkbox } from 'antd'; import User from '@/common/js/user';
import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components';
import Breadcrumbs from '@/components/Breadcrumbs';
import { Checkbox, Input, Tooltip } from 'antd';
import moment from 'moment'; import moment from 'moment';
import React from 'react';
import _ from 'underscore'; import _ from 'underscore';
import Breadcrumbs from "@/components/Breadcrumbs";
import PageControl from '@/components/PageControl';
import Service from "@/common/js/service";
import User from '@/common/js/user';
import './OfflineCourseData.less'; import './OfflineCourseData.less';
const { Search } = Input; const { Search } = Input;
...@@ -34,7 +35,7 @@ export default class OfflineCourseData extends React.Component { ...@@ -34,7 +35,7 @@ export default class OfflineCourseData extends React.Component {
joinInNum: 0, joinInNum: 0,
joinNum: 0, joinNum: 0,
joinOutNum: 0, joinOutNum: 0,
} };
} }
componentDidMount() { componentDidMount() {
...@@ -46,24 +47,27 @@ export default class OfflineCourseData extends React.Component { ...@@ -46,24 +47,27 @@ export default class OfflineCourseData extends React.Component {
Service.Hades('public/hades/getOfflineCourseJoinBase', { courseId }).then((res) => { Service.Hades('public/hades/getOfflineCourseJoinBase', { courseId }).then((res) => {
if (res.success) { if (res.success) {
const { result } = res; const { result } = res;
const group = _.groupBy(result.calendarTime, item => moment(item).format('YYYY-MM')); const group = _.groupBy(result.calendarTime, (item) => moment(item).format('YYYY-MM'));
const calendarTime = _.map(group, (value, key) => ({ key, value })); const calendarTime = _.map(group, (value, key) => ({ key, value }));
const currentDate = calendarTime[currentIndex].value[0]; const currentDate = calendarTime[currentIndex].value[0];
this.setState({ this.setState(
courseName: result.courseName, {
fullJoin: result.fullJoin || 0, courseName: result.courseName,
totalJoin: result.totalJoin || 0, fullJoin: result.fullJoin || 0,
calendarTime, totalJoin: result.totalJoin || 0,
currentDate, calendarTime,
offlineCourseType: result.offlineCourseType, currentDate,
whetherSetSignIn: result.whetherSetSignIn, offlineCourseType: result.offlineCourseType,
whetherSetSignOut: result.whetherSetSignOut, whetherSetSignIn: result.whetherSetSignIn,
whetherSetSignInOut: result.whetherSetSignInOut, whetherSetSignOut: result.whetherSetSignOut,
whetherSetApply: result.whetherSetApply, whetherSetSignInOut: result.whetherSetSignInOut,
}, () => this.getDateDetail()); whetherSetApply: result.whetherSetApply,
},
() => this.getDateDetail()
);
} }
}) });
} };
getDateDetail = (current = 1) => { getDateDetail = (current = 1) => {
const { query, currentDate, courseId } = this.state; const { query, currentDate, courseId } = this.state;
...@@ -75,9 +79,9 @@ export default class OfflineCourseData extends React.Component { ...@@ -75,9 +79,9 @@ export default class OfflineCourseData extends React.Component {
joinInNum: res.result.joinInNum || 0, joinInNum: res.result.joinInNum || 0,
joinNum: res.result.joinNum || 0, joinNum: res.result.joinNum || 0,
joinOutNum: res.result.joinOutNum || 0, joinOutNum: res.result.joinOutNum || 0,
}) });
} }
}) });
} }
query.current = current; query.current = current;
query.date = currentDate; query.date = currentDate;
...@@ -85,8 +89,8 @@ export default class OfflineCourseData extends React.Component { ...@@ -85,8 +89,8 @@ export default class OfflineCourseData extends React.Component {
if (res.success) { if (res.success) {
this.setState({ data: res.result.records, total: res.result.total }); this.setState({ data: res.result.records, total: res.result.total });
} }
}) });
} };
getColumns = () => { getColumns = () => {
const { whetherSetSignIn, whetherSetSignOut, whetherSetApply } = this.state; const { whetherSetSignIn, whetherSetSignOut, whetherSetApply } = this.state;
...@@ -96,50 +100,49 @@ export default class OfflineCourseData extends React.Component { ...@@ -96,50 +100,49 @@ export default class OfflineCourseData extends React.Component {
key: 'name', key: 'name',
dataIndex: 'name', dataIndex: 'name',
render: (val, record) => { render: (val, record) => {
return ( return <div>{record.name}</div>;
<div>{record.name}</div> },
)
}
}, },
{ {
title: "手机号", title: '手机号',
key: "phone", key: 'phone',
dataIndex: "phone", dataIndex: 'phone',
render: (val, item) => { render: (val, item) => {
return ( return <div>{item.phone || '-'}</div>;
<div>{item.phone || '-'}</div>
)
}, },
}, },
]; ];
whetherSetApply === 'YES' && columns.push({ whetherSetApply === 'YES' &&
title: '报名时间', columns.push({
key: 'joinTime', title: '报名时间',
dataIndex: 'joinTime', key: 'joinTime',
render: (val, item) => { dataIndex: 'joinTime',
return <div>{formatDate('YYYY-MM-DD H:i', item.joinTime)}</div> render: (val, item) => {
} return <div>{formatDate('YYYY-MM-DD H:i', item.joinTime)}</div>;
}); },
whetherSetSignIn === 'YES' && columns.push({ });
title: '签到时间', whetherSetSignIn === 'YES' &&
key: 'joinInTime', columns.push({
dataIndex: 'joinInTime', title: '签到时间',
sorter: true, key: 'joinInTime',
render: (val) => { dataIndex: 'joinInTime',
return val ? formatDate('YYYY-MM-DD H:i', val) : '-'; sorter: true,
} render: (val) => {
}) return val ? formatDate('YYYY-MM-DD H:i', val) : '-';
whetherSetSignOut === 'YES' && columns.push({ },
title: '签退时间', });
key: 'joinOutTime', whetherSetSignOut === 'YES' &&
dataIndex: 'joinOutTime', columns.push({
sorter: true, title: '签退时间',
render: (val) => { key: 'joinOutTime',
return val ? formatDate('YYYY-MM-DD H:i', val) : '-'; dataIndex: 'joinOutTime',
} sorter: true,
}) render: (val) => {
return val ? formatDate('YYYY-MM-DD H:i', val) : '-';
},
});
return columns; return columns;
} };
handleChangeTable = (pagination, filters, sorter) => { handleChangeTable = (pagination, filters, sorter) => {
const { columnKey, order } = sorter; const { columnKey, order } = sorter;
...@@ -161,8 +164,8 @@ export default class OfflineCourseData extends React.Component { ...@@ -161,8 +164,8 @@ export default class OfflineCourseData extends React.Component {
}; };
this.setState({ query: _query }, () => { this.setState({ query: _query }, () => {
this.getDateDetail(_query.current); this.getDateDetail(_query.current);
}) });
} };
render() { render() {
const { const {
...@@ -189,26 +192,32 @@ export default class OfflineCourseData extends React.Component { ...@@ -189,26 +192,32 @@ export default class OfflineCourseData extends React.Component {
const calendarLength = calendarTime.length; const calendarLength = calendarTime.length;
const dateList = (calendarTime[currentIndex] || {}).value || []; const dateList = (calendarTime[currentIndex] || {}).value || [];
return ( return (
<div className="page offline-course-data"> <div className='page offline-course-data'>
<Breadcrumbs <Breadcrumbs
navList="参与数据" navList='参与数据'
goBack={() => { goBack={() => {
window.RCHistory.goBack(); window.RCHistory.goBack();
}} }}
/> />
<div className="box"> <div className='box'>
<div className="offline-name">课程名称:{courseName}</div> <div className='offline-name'>课程名称:{courseName}</div>
{whetherSetApply === 'YES' && <div className="offline-application">报名总人数:{totalJoin}</div>} {whetherSetApply === 'YES' && <div className='offline-application'>报名总人数:{totalJoin}</div>}
{whetherSetSignInOut === 'YES' && <div className="offline-application"> {whetherSetSignInOut === 'YES' && (
完成考勤总人数<Tooltip title="根据上课日期,在规定时间内完成签到和签退的学员数"><span className="icon iconfont">&#xe7c4;</span></Tooltip>{fullJoin} <div className='offline-application'>
</div>} 完成考勤总人数
<Tooltip title='根据上课日期,在规定时间内完成签到和签退的学员数'>
<span className='icon iconfont'>&#xe7c4;</span>
</Tooltip>
{fullJoin}
</div>
)}
</div> </div>
<div className="box data-box"> <div className='box data-box'>
<div className="left-box"> <div className='left-box'>
<div className="left-title">上课日期</div> <div className='left-title'>上课日期</div>
<div className="left-calendar"> <div className='left-calendar'>
<div <div
className="icon-box" className='icon-box'
onClick={() => { onClick={() => {
const index = currentIndex - 1; const index = currentIndex - 1;
if (index >= 0 && index < calendarLength) { if (index >= 0 && index < calendarLength) {
...@@ -216,13 +225,12 @@ export default class OfflineCourseData extends React.Component { ...@@ -216,13 +225,12 @@ export default class OfflineCourseData extends React.Component {
this.getDateDetail(); this.getDateDetail();
}); });
} }
}} }}>
> <span className='icon iconfont'>&#xe79c;</span>
<span className="icon iconfont">&#xe79c;</span>
</div> </div>
<div className="calendar-text">{(calendarTime[currentIndex] || {}).key}</div> <div className='calendar-text'>{(calendarTime[currentIndex] || {}).key}</div>
<div <div
className="icon-box" className='icon-box'
onClick={() => { onClick={() => {
const index = currentIndex + 1; const index = currentIndex + 1;
if (index >= 0 && index < calendarLength) { if (index >= 0 && index < calendarLength) {
...@@ -230,112 +238,132 @@ export default class OfflineCourseData extends React.Component { ...@@ -230,112 +238,132 @@ export default class OfflineCourseData extends React.Component {
this.getDateDetail(); this.getDateDetail();
}); });
} }
}} }}>
> <span className='icon iconfont'>&#xe79b;</span>
<span className="icon iconfont">&#xe79b;</span>
</div> </div>
</div> </div>
<div className="date-list"> <div className='date-list'>
{dateList.map(item => ( {dateList.map((item) => (
<div <div
className={`date-item${item === currentDate ? ' selected' : ''}`} className={`date-item${item === currentDate ? ' selected' : ''}`}
key={item} key={item}
onClick={() => { onClick={() => {
this.setState({ currentDate: item }, () => { this.setState({ currentDate: item }, () => {
this.getDateDetail(); this.getDateDetail();
}) });
}} }}>
>{window.formatDate('MM月DD日(WW)', item)}</div> {window.formatDate('MM月DD日(WW)', item)}
</div>
))} ))}
</div> </div>
</div> </div>
<div className="right-box"> <div className='right-box'>
<div className="selected-date">{moment(currentDate).format('MM-DD')}</div> <div className='selected-date'>{moment(currentDate).format('MM-DD')}</div>
<div className="detail-data"> <div className='detail-data'>
{offlineCourseType !== 'ALL_DAY_OFFLINE' && whetherSetApply === 'YES' && <span className="icon iconfont">&#xe89f;</span>} {offlineCourseType !== 'ALL_DAY_OFFLINE' && whetherSetApply === 'YES' && <span className='icon iconfont'>&#xe89f;</span>}
{offlineCourseType !== 'ALL_DAY_OFFLINE' && whetherSetApply === 'YES' && <span className="data-text">报名人数:{joinNum}</span>} {offlineCourseType !== 'ALL_DAY_OFFLINE' && whetherSetApply === 'YES' && <span className='data-text'>报名人数:{joinNum}</span>}
{whetherSetSignInOut === 'YES' && <span className="icon iconfont">&#xe89e;</span>} {whetherSetSignInOut === 'YES' && <span className='icon iconfont'>&#xe89e;</span>}
{whetherSetSignInOut === 'YES' && <span className="data-text">完成考勤数<Tooltip title="当日在规定时间内完成签到和签退的学员数"><span className="icon iconfont">&#xe7c4;</span></Tooltip>{fullJoinNum}</span>} {whetherSetSignInOut === 'YES' && (
{whetherSetSignIn === 'YES' && <span className="icon iconfont">&#xe8a0;</span>} <span className='data-text'>
{whetherSetSignIn === 'YES' && <span className="data-text">签到人数:{joinInNum}</span>} 完成考勤数
{whetherSetSignOut === 'YES' && <span className="icon iconfont">&#xe89d;</span>} <Tooltip title='当日在规定时间内完成签到和签退的学员数'>
{whetherSetSignOut === 'YES' && <span className="data-text">签退人数:{joinOutNum}</span>} <span className='icon iconfont'>&#xe7c4;</span>
</Tooltip>
{fullJoinNum}
</span>
)}
{whetherSetSignIn === 'YES' && <span className='icon iconfont'>&#xe8a0;</span>}
{whetherSetSignIn === 'YES' && <span className='data-text'>签到人数:{joinInNum}</span>}
{whetherSetSignOut === 'YES' && <span className='icon iconfont'>&#xe89d;</span>}
{whetherSetSignOut === 'YES' && <span className='data-text'>签退人数:{joinOutNum}</span>}
</div> </div>
<div className="detail-filter"> <div className='detail-filter'>
<Search <Search
className="search-input" className='search-input'
placeholder="搜索学员姓名/手机号" placeholder='搜索学员姓名/手机号'
style={{ width: 200, marginRight: 24 }} style={{ width: 200, marginRight: 24 }}
enterButton={<span className="icon iconfont">&#xe832;</span>} enterButton={<span className='icon iconfont'>&#xe832;</span>}
onSearch={(value) => { onSearch={(value) => {
const _query = { ...query }; const _query = { ...query };
if (value) { if (value) {
const isPhone = (value || "").match(/^\d+$/); const isPhone = (value || '').match(/^\d+$/);
const name = isPhone ? "storeCustomerPhone" : "storeCustomerName"; const name = isPhone ? 'storeCustomerPhone' : 'storeCustomerName';
_query.storeCustomerName = ""; _query.storeCustomerName = '';
_query.storeCustomerPhone = ""; _query.storeCustomerPhone = '';
_query[name] = value; _query[name] = value;
} else { } else {
_query.storeCustomerName = ""; _query.storeCustomerName = '';
_query.storeCustomerPhone = ""; _query.storeCustomerPhone = '';
} }
this.setState({ query: _query }, () => this.getDateDetail()); this.setState({ query: _query }, () => this.getDateDetail());
}} }}
/> />
{whetherSetSignInOut === 'YES' && <div className="filter-box"> {whetherSetSignInOut === 'YES' && (
<span className="label">签到情况:</span> <div className='filter-box'>
<Checkbox <span className='label'>签到情况:</span>
checked={query.joinInState === 'YES'} <Checkbox
onChange={(e) => { checked={query.joinInState === 'YES'}
if (e.target.checked) { onChange={(e) => {
this.setState({ query: { ...query, joinInState: 'YES' } }, () => this.getDateDetail()); if (e.target.checked) {
} else { this.setState({ query: { ...query, joinInState: 'YES' } }, () => this.getDateDetail());
delete query.joinInState; } else {
this.setState({ query }, () => this.getDateDetail()) delete query.joinInState;
} this.setState({ query }, () => this.getDateDetail());
}} }
>已签到</Checkbox> }}>
<Checkbox 已签到
checked={query.joinInState === 'NO'} </Checkbox>
onChange={(e) => { <Checkbox
if (e.target.checked) { checked={query.joinInState === 'NO'}
this.setState({ query: { ...query, joinInState: 'NO' } }, () => this.getDateDetail()); onChange={(e) => {
} else { if (e.target.checked) {
delete query.joinInState; this.setState({ query: { ...query, joinInState: 'NO' } }, () => this.getDateDetail());
this.setState({ query }, () => this.getDateDetail()) } else {
} delete query.joinInState;
}} this.setState({ query }, () => this.getDateDetail());
>未签到</Checkbox> }
</div>} }}>
{whetherSetSignOut === 'YES' && <div className="filter-box"> 未签到
<span className="label">签退情况:</span> </Checkbox>
<Checkbox </div>
checked={query.joinOutState === 'YES'} )}
onChange={(e) => { {whetherSetSignOut === 'YES' && (
if (e.target.checked) { <div className='filter-box'>
this.setState({ query: { ...query, joinOutState: 'YES' } }, () => this.getDateDetail()); <span className='label'>签退情况:</span>
} else { <Checkbox
delete query.joinOutState; checked={query.joinOutState === 'YES'}
this.setState({ query }, () => this.getDateDetail()) onChange={(e) => {
} if (e.target.checked) {
}} this.setState({ query: { ...query, joinOutState: 'YES' } }, () => this.getDateDetail());
>已签退</Checkbox> } else {
<Checkbox delete query.joinOutState;
checked={query.joinOutState === 'NO'} this.setState({ query }, () => this.getDateDetail());
onChange={(e) => { }
if (e.target.checked) { }}>
this.setState({ query: { ...query, joinOutState: 'NO' } }, () => this.getDateDetail()); 已签退
} else { </Checkbox>
delete query.joinOutState; <Checkbox
this.setState({ query }, () => this.getDateDetail()) checked={query.joinOutState === 'NO'}
} onChange={(e) => {
}} if (e.target.checked) {
>未签退</Checkbox> this.setState({ query: { ...query, joinOutState: 'NO' } }, () => this.getDateDetail());
</div>} } else {
delete query.joinOutState;
this.setState({ query }, () => this.getDateDetail());
}
}}>
未签退
</Checkbox>
</div>
)}
</div> </div>
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
bordered bordered
size="middle" size='middle'
pagination={false} pagination={false}
columns={this.getColumns()} columns={this.getColumns()}
loading={loading} loading={loading}
...@@ -354,6 +382,6 @@ export default class OfflineCourseData extends React.Component { ...@@ -354,6 +382,6 @@ export default class OfflineCourseData extends React.Component {
</div> </div>
</div> </div>
</div> </div>
) );
} }
} }
\ No newline at end of file
...@@ -6,35 +6,32 @@ ...@@ -6,35 +6,32 @@
* @Description: 视频课-列表模块 * @Description: 视频课-列表模块
* @Copyright: 杭州杰竞科技有限公司 版权所有 * @Copyright: 杭州杰竞科技有限公司 版权所有
*/ */
import Service from '@/common/js/service';
import User from '@/common/js/user';
import college from '@/common/lottie/college';
import { PageControl, XMTable } from '@/components';
import { appId, LIVE_SHARE } from '@/domains/course-domain/constants';
import CourseService from '@/domains/course-domain/CourseService';
import ShareLiveModal from '@/modules/course-manage/modal/ShareLiveModal';
import OfflineCourseData from '@/modules/course-manage/offline-course/OfflineCourseData';
import { Dropdown, message, Modal, Switch, Tooltip } from 'antd';
import moment from 'moment';
import React from 'react'; import React from 'react';
import { Table, Modal, message , Tooltip,Switch,Dropdown} from 'antd';
import { Route, withRouter } from 'react-router-dom'; import { Route, withRouter } from 'react-router-dom';
import moment from 'moment'; import ENUM from '../../../knowledge-base/ENUM.js';
import $ from 'jquery';
import { PageControl } from "@/components";
import { appId, shareUrl, LIVE_SHARE } from '@/domains/course-domain/constants';
import OfflineCourseData from '@/modules/course-manage/offline-course/OfflineCourseData';
import ShareLiveModal from '@/modules/course-manage/modal/ShareLiveModal';
import Service from "@/common/js/service";
import CourseService from "@/domains/course-domain/CourseService";
import RelatedPlanModal from '../../modal/RelatedPlanModal';
import PreviewOfflineModal from '../modal/PreviewOfflineModal'; import PreviewOfflineModal from '../modal/PreviewOfflineModal';
import ENUM from "../../../knowledge-base/ENUM.js";
import User from '@/common/js/user'
import QRCodeModal from '../modal/QRCodeModal'; import QRCodeModal from '../modal/QRCodeModal';
import './OfflineCourseList.less'; import './OfflineCourseList.less';
const ENV = process.env.DEPLOY_ENV || 'dev';
const defaultCoverUrl = 'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png'; const defaultCoverUrl = 'https://image.xiaomaiketang.com/xm/pxbWKsYA87.png';
class OfflineCourseList extends React.Component { class OfflineCourseList extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
id: '', // 视频课ID id: '', // 视频课ID
studentIds: [], studentIds: [],
} };
} }
componentDidMount() { componentDidMount() {
...@@ -44,18 +41,18 @@ class OfflineCourseList extends React.Component { ...@@ -44,18 +41,18 @@ class OfflineCourseList extends React.Component {
this.handleShowShareModal(_videoCourseItem, true); this.handleShowShareModal(_videoCourseItem, true);
} }
} }
handlePlanName = (planArray)=>{ handlePlanName = (planArray) => {
let planStr = ""; let planStr = '';
planArray.map((item,index)=>{ planArray.map((item, index) => {
if(index < planArray.length-1){ if (index < planArray.length - 1) {
planStr = planStr + item.planName + '、'; planStr = planStr + item.planName + '、';
}else{ } else {
planStr = planStr + item.planName planStr = planStr + item.planName;
} }
}) });
return planStr return planStr;
} };
// 请求表头 // 请求表头
parseColumns = () => { parseColumns = () => {
const columns = [ const columns = [
...@@ -63,35 +60,39 @@ class OfflineCourseList extends React.Component { ...@@ -63,35 +60,39 @@ class OfflineCourseList extends React.Component {
title: '线下课', title: '线下课',
key: 'scheduleName', key: 'scheduleName',
dataIndex: 'scheduleName', dataIndex: 'scheduleName',
width:321, width: 321,
fixed: 'left', fixed: 'left',
render: (val, record) => { render: (val, record) => {
const { courseMediaVOS, courseName, offlinePlace, calendarTime, startTime, endTime } = record; const { courseMediaVOS, courseName, offlinePlace, calendarTime, startTime, endTime } = record;
const coverUrl = (_.find(courseMediaVOS, data => data.contentType === 'COVER') || {}).mediaUrl; const coverUrl = (_.find(courseMediaVOS, (data) => data.contentType === 'COVER') || {}).mediaUrl;
let isContinue = calendarTime.length > 1; let isContinue = calendarTime.length > 1;
_.reduce(calendarTime, (a, b) => { _.reduce(calendarTime, (a, b) => {
isContinue = isContinue && (b - a === 86400000); isContinue = isContinue && b - a === 86400000;
return b; return b;
}) });
const lastTime = _.last(calendarTime); const lastTime = _.last(calendarTime);
const time = `${!isContinue ? calendarTime.map(item => moment(item).format('MM-DD')).join('、') : `${moment(calendarTime[0]).format('MM-DD')}~${moment(lastTime).format('MM-DD')}`} ${moment(startTime).format('HH:mm')} ~ ${moment(endTime).format('HH:mm')}`; const time = `${
!isContinue
? calendarTime.map((item) => moment(item).format('MM-DD')).join('、')
: `${moment(calendarTime[0]).format('MM-DD')}~${moment(lastTime).format('MM-DD')}`
} ${moment(startTime).format('HH:mm')} ~ ${moment(endTime).format('HH:mm')}`;
return ( return (
<div className="record__item"> <div className='record__item'>
<img className="course-cover" src={coverUrl || defaultCoverUrl} /> <img className='course-cover' src={coverUrl || defaultCoverUrl} />
<div style={{ width: 175 }}> <div style={{ width: 175 }}>
<Tooltip title={courseName}> <Tooltip title={courseName}>
<div className="course-name">{courseName}</div> <div className='course-name'>{courseName}</div>
</Tooltip> </Tooltip>
<Tooltip title={`地点:${offlinePlace}`}> <Tooltip title={`地点:${offlinePlace}`}>
<div className="course-text">地点:{offlinePlace}</div> <div className='course-text'>地点:{offlinePlace}</div>
</Tooltip> </Tooltip>
<Tooltip title={time}> <Tooltip title={time}>
<div className="course-text">{time}</div> <div className='course-text'>{time}</div>
</Tooltip> </Tooltip>
</div> </div>
</div> </div>
) );
} },
}, },
{ {
title: '课程状态', title: '课程状态',
...@@ -100,12 +101,12 @@ class OfflineCourseList extends React.Component { ...@@ -100,12 +101,12 @@ class OfflineCourseList extends React.Component {
width: 120, width: 120,
render: (val, record) => { render: (val, record) => {
return ( return (
<div className="course-state"> <div className='course-state'>
<div style={{ width: 6, height: 6, borderRadius: '50%', background: ENUM.offlineStateShow[val].color, marginRight: 8 }}></div> <div style={{ width: 6, height: 6, borderRadius: '50%', background: ENUM.offlineStateShow[val].color, marginRight: 8 }}></div>
{ENUM.offlineStateShow[val].title} {ENUM.offlineStateShow[val].title}
</div> </div>
) );
} },
}, },
{ {
title: '课程分类', title: '课程分类',
...@@ -113,39 +114,40 @@ class OfflineCourseList extends React.Component { ...@@ -113,39 +114,40 @@ class OfflineCourseList extends React.Component {
dataIndex: 'categoryName', dataIndex: 'categoryName',
width: 120, width: 120,
render: (val, record) => { render: (val, record) => {
return ( return <div className='record__item'>{record.categorySonName}</div>;
<div className="record__item"> },
{record.categorySonName}
</div>
)
}
}, },
{ {
title: <span> title: (
<span>学院展示</span> <span>
<Tooltip title={<div>开启后,学员可在学院内查看到此课程。若课程“取消”,则系统会自动“关闭”学院展示。<br/>关闭后,学院内不再展示此课程,但学员仍可通过分享的海报/链接查看此课程。</div>}><i className="icon iconfont" style={{ marginLeft: '5px',cursor:'pointer',color:'#bfbfbf',fontSize:'14px',fontWeight:'normal'}}>&#xe61d;</i></Tooltip> <span>学院展示</span>
</span>, <Tooltip
title={
<div>
开启后,学员可在学院内查看到此课程。若课程“取消”,则系统会自动“关闭”学院展示。
<br />
关闭后,学院内不再展示此课程,但学员仍可通过分享的海报/链接查看此课程。
</div>
}>
<i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px', fontWeight: 'normal' }}>
&#xe61d;
</i>
</Tooltip>
</span>
),
width: 120, width: 120,
dataIndex: "courseware", dataIndex: 'courseware',
render: (val, item, index) => { render: (val, item, index) => {
return ( return <Switch disabled={item.courseState === 'EXPIRED'} checked={item.shelfState === 'YES'} onChange={() => this.changeShelfState(item)} />;
<Switch
disabled={item.courseState === 'EXPIRED'}
checked={item.shelfState === "YES"}
onChange={() => this.changeShelfState(item)}
/>
)
}, },
}, },
{ {
title: "讲师", title: '讲师',
width: 200, width: 200,
key: "teacher", key: 'teacher',
dataIndex: "teacher", dataIndex: 'teacher',
render: (val, item) => { render: (val, item) => {
return ( return <div>{item.teacherName}</div>;
<div>{item.teacherName}</div>
)
}, },
}, },
{ {
...@@ -155,22 +157,26 @@ class OfflineCourseList extends React.Component { ...@@ -155,22 +157,26 @@ class OfflineCourseList extends React.Component {
dataIndex: 'apply', dataIndex: 'apply',
sorter: true, sorter: true,
render: (val, item) => { render: (val, item) => {
return <div> return (
{item.startTimeApply ? `${formatDate('MM-DD H:i', item.startTimeApply)} ~ ${formatDate('MM-DD H:i', item.endTimeApply)}` : '-'} <div>
{item.whetherApplyFull === 'YES' && {item.startTimeApply ? `${formatDate('MM-DD H:i', item.startTimeApply)} ~ ${formatDate('MM-DD H:i', item.endTimeApply)}` : '-'}
<span {item.whetherApplyFull === 'YES' && (
style={{ <span
marginLeft: 4, style={{
color: '#FF4F4F', marginLeft: 4,
background: 'rgba(255, 79, 79, 0.1)', color: '#FF4F4F',
padding: '0 8px', background: 'rgba(255, 79, 79, 0.1)',
fontSize: '12px', padding: '0 8px',
height: '18px', fontSize: '12px',
lineHeight: '18px', height: '18px',
}}>已报满</span> lineHeight: '18px',
} }}>
</div> 已报满
} </span>
)}
</div>
);
},
}, },
{ {
title: '创建时间', title: '创建时间',
...@@ -179,8 +185,8 @@ class OfflineCourseList extends React.Component { ...@@ -179,8 +185,8 @@ class OfflineCourseList extends React.Component {
dataIndex: 'created', dataIndex: 'created',
sorter: true, sorter: true,
render: (val) => { render: (val) => {
return formatDate('YYYY-MM-DD H:i', val) return formatDate('YYYY-MM-DD H:i', val);
} },
}, },
{ {
title: '操作', title: '操作',
...@@ -190,30 +196,33 @@ class OfflineCourseList extends React.Component { ...@@ -190,30 +196,33 @@ class OfflineCourseList extends React.Component {
fixed: 'right', fixed: 'right',
render: (val, record) => { render: (val, record) => {
return ( return (
<div className="operate"> <div className='operate'>
<div className="operate__item" onClick={() => window.RCHistory.push(`/offline-course/data?id=${record.courseId}`)}>参与数据</div> <div className='operate__item' onClick={() => window.RCHistory.push(`/offline-course/data?id=${record.courseId}`)}>
{record.courseState !== 'EXPIRED' && <span className="operate__item split"> | </span>} 参与数据
{record.courseState !== 'EXPIRED' && <div className="operate__item" onClick={() => this.handleShowShareModal(record)}>分享</div>} </div>
<span className="operate__item split"> | </span> {record.courseState !== 'EXPIRED' && <span className='operate__item split'> | </span>}
{record.courseState !== 'EXPIRED' && (
<div className='operate__item' onClick={() => this.handleShowShareModal(record)}>
分享
</div>
)}
<span className='operate__item split'> | </span>
<Dropdown overlay={this.renderMoreOperate(record)}> <Dropdown overlay={this.renderMoreOperate(record)}>
<span className="more-operate"> <span className='more-operate'>
<span className="operate-text">更多</span> <span className='operate-text'>更多</span>
<span <span className='iconfont icon' style={{ color: '#2966FF' }}>
className="iconfont icon"
style={{ color: "#2966FF" }}
>
&#xe824; &#xe824;
</span> </span>
</span> </span>
</Dropdown> </Dropdown>
</div> </div>
) );
} },
} },
]; ];
return columns; return columns;
} };
// 显示预览弹窗 // 显示预览弹窗
handleShowPreviewModal = (courseId) => { handleShowPreviewModal = (courseId) => {
const previewOfflineModal = ( const previewOfflineModal = (
...@@ -221,133 +230,142 @@ class OfflineCourseList extends React.Component { ...@@ -221,133 +230,142 @@ class OfflineCourseList extends React.Component {
courseId={courseId} courseId={courseId}
close={() => { close={() => {
this.setState({ this.setState({
previewOfflineModal: null previewOfflineModal: null,
}) });
}} }}
/> />
); );
this.setState({ previewOfflineModal }); this.setState({ previewOfflineModal });
} };
renderMoreOperate = (item) => { renderMoreOperate = (item) => {
return ( return (
<div className="live-course-more-menu"> <div className='live-course-more-menu'>
{item.courseState !== 'EXPIRED' && (item.whetherSetSignIn === 'YES' || item.whetherSetSignOut === 'YES') && <div {item.courseState !== 'EXPIRED' && (item.whetherSetSignIn === 'YES' || item.whetherSetSignOut === 'YES') && (
className="operate__item" <div
key="qrcode" className='operate__item'
onClick={() => { key='qrcode'
this.setState({ openQRCodeModal: true, qrcodeData: item }) onClick={() => {
}} this.setState({ openQRCodeModal: true, qrcodeData: item });
>考勤二维码</div>} }}>
考勤二维码
</div>
)}
<div <div
className="operate__item" className='operate__item'
key="preview" key='preview'
onClick={() => { onClick={() => {
this.handleShowPreviewModal(item.courseId); this.handleShowPreviewModal(item.courseId);
}} }}>
>预览</div> 预览
{(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') && (item.courseState === 'UN_START' || item.courseState === 'STARTING') && <div </div>
className="operate__item" {(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') &&
key="cancel" (item.courseState === 'UN_START' || item.courseState === 'STARTING') && (
onClick={() => { <div
this.handleDeleteOfflineCourse(item.courseId); className='operate__item'
}} key='cancel'
>取消课程</div>} onClick={() => {
{item.courseState === 'UN_START' && window.ctx.xmState.storeUserPermissionList.includes('EditOfflineClass') && <div this.handleDeleteOfflineCourse(item.courseId);
className="operate__item" }}>
key="edit" 取消课程
onClick={() => { </div>
RCHistory.push(`/create-offline-course?type=edit&id=${item.courseId}`); )}
}} {item.courseState === 'UN_START' && window.ctx.xmState.storeUserPermissionList.includes('EditOfflineClass') && (
>编辑</div>} <div
{(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') && <div className='operate__item'
className="operate__item" key='edit'
key="delete" onClick={() => {
onClick={() => this.handleDeleteOfflineCourse(item.courseId, true)} RCHistory.push(`/create-offline-course?type=edit&id=${item.courseId}`);
>删除</div>} }}>
编辑
</div>
)}
{(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') && (
<div className='operate__item' key='delete' onClick={() => this.handleDeleteOfflineCourse(item.courseId, true)}>
删除
</div>
)}
</div> </div>
) );
} };
//改变上架状态 //改变上架状态
changeShelfState = (item) => { changeShelfState = (item) => {
if (!window.ctx.xmState.storeUserPermissionList.includes('EditOfflineClass')) { if (!window.ctx.xmState.storeUserPermissionList.includes('EditOfflineClass')) {
message.warning('无【编辑线下课】权限,请联系管理员') message.warning('无【编辑线下课】权限,请联系管理员');
return; return;
} }
let _shelfState = item.shelfState let _shelfState = item.shelfState;
if(_shelfState==='NO'){ if (_shelfState === 'NO') {
_shelfState = "YES"; _shelfState = 'YES';
item.shelfState = "YES" item.shelfState = 'YES';
}else{ } else {
_shelfState = "NO" _shelfState = 'NO';
item.shelfState = "NO" item.shelfState = 'NO';
} }
const params={ const params = {
courseId: item.courseId, courseId: item.courseId,
shelfState:_shelfState shelfState: _shelfState,
} };
CourseService.changeVideoShelfState(params).then((res)=>{ CourseService.changeVideoShelfState(params).then((res) => {
if(res.success){ if (res.success) {
if(_shelfState === "YES"){ if (_shelfState === 'YES') {
message.success("已开启展示"); message.success('已开启展示');
}else{ } else {
message.success("已取消展示"); message.success('已取消展示');
} }
this.props.onChange(); this.props.onChange();
} }
}) });
} };
// 删除视频课 // 删除视频课
handleDeleteOfflineCourse = (courseId, isDelete) => { handleDeleteOfflineCourse = (courseId, isDelete) => {
if (isDelete) { if (isDelete) {
Modal.confirm({ Modal.confirm({
title: '删除课程', title: '删除课程',
content: '确定删除该课程吗?删除后学员数据和课程数据将无法恢复。', content: '确定删除该课程吗?删除后学员数据和课程数据将无法恢复。',
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>, icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
okText: '确定', okText: '确定',
okType: 'danger', okType: 'danger',
cancelText: '取消', cancelText: '取消',
onOk: () => { onOk: () => {
const param ={ const param = {
courseId: courseId, courseId: courseId,
} };
Service.Hades('public/hades/delOfflineCourse', param).then(() => { Service.Hades('public/hades/delOfflineCourse', param).then(() => {
message.success('删除成功'); message.success('删除成功');
this.props.onChange(); this.props.onChange();
}) });
} },
}); });
} else { } else {
Modal.confirm({ Modal.confirm({
title: '取消课程', title: '取消课程',
content: '确定要取消该课程吗?取消后课程将失效,仅保留已有数据。', content: '确定要取消该课程吗?取消后课程将失效,仅保留已有数据。',
icon: <span className="icon iconfont default-confirm-icon">&#xe6f4;</span>, icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
okText: '确定', okText: '确定',
cancelText: '取消', cancelText: '取消',
onOk: () => { onOk: () => {
const param ={ const param = {
courseId: courseId, courseId: courseId,
} };
Service.Hades('public/hades/cancelOfflineCourse', param).then(() => { Service.Hades('public/hades/cancelOfflineCourse', param).then(() => {
message.success('取消成功'); message.success('取消成功');
this.props.onChange(); this.props.onChange();
}) });
} },
}); });
} }
} };
// 显示分享弹窗 // 显示分享弹窗
handleShowShareModal = (record, needStr = false) => { handleShowShareModal = (record, needStr = false) => {
const { courseId } = record; const { courseId } = record;
const _appId = appId; const _appId = appId;
const htmlUrl = `${LIVE_SHARE}offline_detail/${courseId}?id=${User.getStoreId()}`; const htmlUrl = `${LIVE_SHARE}offline_detail/${courseId}?id=${User.getStoreId()}`;
const longUrl = htmlUrl; const longUrl = htmlUrl;
const { courseName, courseMediaVOS } = record; const { courseName, courseMediaVOS } = record;
const coverUrl = (_.find(courseMediaVOS, data => data.contentType === 'COVER') || {}).mediaUrl; const coverUrl = (_.find(courseMediaVOS, (data) => data.contentType === 'COVER') || {}).mediaUrl;
const shareData = { const shareData = {
longUrl, longUrl,
coverUrl, coverUrl,
...@@ -358,11 +376,11 @@ class OfflineCourseList extends React.Component { ...@@ -358,11 +376,11 @@ class OfflineCourseList extends React.Component {
<ShareLiveModal <ShareLiveModal
needStr={needStr} needStr={needStr}
data={shareData} data={shareData}
type="offlineClass" type='offlineClass'
title="线下课" title='线下课'
close={() => { close={() => {
this.setState({ this.setState({
shareLiveModal: null shareLiveModal: null,
}); });
localStorage.setItem('videoCourseItem', ''); localStorage.setItem('videoCourseItem', '');
}} }}
...@@ -370,67 +388,83 @@ class OfflineCourseList extends React.Component { ...@@ -370,67 +388,83 @@ class OfflineCourseList extends React.Component {
); );
this.setState({ shareLiveModal }); this.setState({ shareLiveModal });
} };
handleChangeTable = (pagination, filters, sorter) => { handleChangeTable = (pagination, filters, sorter) => {
const { columnKey, order } = sorter; const { columnKey, order } = sorter;
const { query } = this.props; const { query } = this.props;
let _columnKey; let _columnKey;
let _order; let _order;
// 按创建时间升序排序 // 按创建时间升序排序
if (columnKey === 'apply' && order === 'ascend') {_columnKey="START_APPLY_DESC"; _order = 'SORT_ASC'; } if (columnKey === 'apply' && order === 'ascend') {
if (columnKey === 'created' && order === 'ascend') {_columnKey="CREATED"; _order = 'SORT_ASC'; } _columnKey = 'START_APPLY_DESC';
_order = 'SORT_ASC';
}
if (columnKey === 'created' && order === 'ascend') {
_columnKey = 'CREATED';
_order = 'SORT_ASC';
}
// 按创建时间降序排序 // 按创建时间降序排序
if (columnKey === 'apply' && order === 'descend') { _columnKey="START_APPLY_DESC"; _order = 'SORT_DESC';} if (columnKey === 'apply' && order === 'descend') {
if (columnKey === 'created' && order === 'descend') { _columnKey="CREATED"; _order = 'SORT_DESC';} _columnKey = 'START_APPLY_DESC';
_order = 'SORT_DESC';
}
if (columnKey === 'created' && order === 'descend') {
_columnKey = 'CREATED';
_order = 'SORT_DESC';
}
const _query = { const _query = {
...query, ...query,
sortMap:{} sortMap: {},
}; };
_query.sortMap[_columnKey]=_order; _query.sortMap[_columnKey] = _order;
this.props.onChange(_query); this.props.onChange(_query);
} };
render() { render() {
const { openQRCodeModal, qrcodeData } = this.state; const { openQRCodeModal, qrcodeData } = this.state;
const { dataSource = [], totalCount, query, match } = this.props; const { dataSource = [], totalCount, query, match } = this.props;
const { current, size } = query; const { current, size } = query;
return ( return (
<div className="offline-course-list"> <div className='offline-course-list'>
<Table <XMTable
rowKey={record => record.courseId} renderEmpty={{
image: college,
description: '暂无数据',
}}
rowKey={(record) => record.courseId}
dataSource={dataSource} dataSource={dataSource}
columns={this.parseColumns()} columns={this.parseColumns()}
onChange={this.handleChangeTable} onChange={this.handleChangeTable}
pagination={false} pagination={false}
scroll={{ x: 1500}} scroll={{ x: 1500 }}
bordered bordered
className="offline-list-table" className='offline-list-table'
/> />
<div className="box-footer"> <div className='box-footer'>
<PageControl <PageControl
current={current - 1} current={current - 1}
pageSize={size} pageSize={size}
total={totalCount} total={totalCount}
toPage={(page) => { toPage={(page) => {
const _query = {...query, current: page + 1}; const _query = { ...query, current: page + 1 };
this.props.onChange(_query) this.props.onChange(_query);
}} }}
/> />
</div> </div>
{this.state.shareLiveModal} {this.state.shareLiveModal}
{this.state.previewOfflineModal} {this.state.previewOfflineModal}
<QRCodeModal <QRCodeModal
visible={openQRCodeModal} visible={openQRCodeModal}
data={qrcodeData} data={qrcodeData}
onCancel={() => { onCancel={() => {
this.setState({ openQRCodeModal: false }) this.setState({ openQRCodeModal: false });
}} }}
/> />
<Route path={`${match.url}/data`} component={OfflineCourseData} /> <Route path={`${match.url}/data`} component={OfflineCourseData} />
</div> </div>
) );
} }
} }
......
import React from "react" import { Dropdown, message, Modal, Switch, Table, Tooltip } from 'antd';
import { Table, Modal, message, Tooltip, Switch, Dropdown } from "antd" import User from '@/common/js/user';
import _ from "underscore" import { PageControl } from '@/components';
import { PageControl } from "@/components" import { LIVE_SHARE } from '@/domains/course-domain/constants';
import { LIVE_SHARE } from "@/domains/course-domain/constants" import CourseService from '@/domains/course-domain/CourseService';
import ShareLiveModal from '@/modules/course-manage/modal/ShareLiveModal';
import ShareLiveModal from "@/modules/course-manage/modal/ShareLiveModal" import React from 'react';
import WatchDataModal from "../modal/WatchDataModal" import RelatedPlanModal from '../../modal/RelatedPlanModal';
import CourseService from "@/domains/course-domain/CourseService" import WatchDataModal from '../modal/WatchDataModal';
import RelatedPlanModal from "../../modal/RelatedPlanModal" import { XMTable } from '@/components';
import User from "@/common/js/user" import college from '@/common/lottie/college';
import './VideoCourseList.less';
import "./VideoCourseList.less"
class VideoCourseList extends React.Component { class VideoCourseList extends React.Component {
constructor(props) { constructor(props) {
super(props) super(props);
this.state = { this.state = {
id: "", // 视频课ID id: '', // 视频课ID
studentIds: [], studentIds: [],
RelatedPlanModalVisible: false, RelatedPlanModalVisible: false,
selectPlanList: {}, selectPlanList: {},
ShelfLoading: false ShelfLoading: false,
// dataSource: [], // dataSource: [],
} };
} }
componentDidMount() { componentDidMount() {
const videoCourseItem = localStorage.getItem("videoCourseItem") const videoCourseItem = localStorage.getItem('videoCourseItem');
if (videoCourseItem) { if (videoCourseItem) {
const _videoCourseItem = JSON.parse(videoCourseItem) const _videoCourseItem = JSON.parse(videoCourseItem);
this.handleShowShareModal(_videoCourseItem, true) this.handleShowShareModal(_videoCourseItem, true);
} }
} }
...@@ -41,27 +40,27 @@ class VideoCourseList extends React.Component { ...@@ -41,27 +40,27 @@ class VideoCourseList extends React.Component {
data={record} data={record}
close={() => { close={() => {
this.setState({ this.setState({
watchDataModal: null watchDataModal: null,
}) });
}} }}
/> />
) );
this.setState({ watchDataModal }) this.setState({ watchDataModal });
} };
// 请求表头 // 请求表头
parseColumns = () => { parseColumns = () => {
const { type } = this.props const { type } = this.props;
const { ShelfLoading } = this.state const { ShelfLoading } = this.state;
const columns = [ const columns = [
{ {
title: "视频课", title: '视频课',
key: "scheduleName", key: 'scheduleName',
dataIndex: "scheduleName", dataIndex: 'scheduleName',
width: 321, width: 321,
fixed: "left", fixed: 'left',
render: (val, record) => { render: (val, record) => {
const { coverUrl, scheduleVideoUrl } = record const { coverUrl, scheduleVideoUrl } = record;
return ( return (
<div className='record__item'> <div className='record__item'>
{/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */} {/* 上传了封面的话就用上传的封面, 没有的话就取视频的第一帧 */}
...@@ -69,7 +68,7 @@ class VideoCourseList extends React.Component { ...@@ -69,7 +68,7 @@ class VideoCourseList extends React.Component {
className='course-cover' className='course-cover'
src={ src={
coverUrl || coverUrl ||
(type === "internal" ? `${scheduleVideoUrl}?x-oss-process=video/snapshot,t_0,m_fast` : "https://image.xiaomaiketang.com/xm/mt3ZQRxGKB.png") (type === 'internal' ? `${scheduleVideoUrl}?x-oss-process=video/snapshot,t_0,m_fast` : 'https://image.xiaomaiketang.com/xm/mt3ZQRxGKB.png')
} }
alt='' alt=''
/> />
...@@ -84,45 +83,45 @@ class VideoCourseList extends React.Component { ...@@ -84,45 +83,45 @@ class VideoCourseList extends React.Component {
</Otherwise> </Otherwise>
</Choose> </Choose>
</div> </div>
) );
} },
}, },
{ {
title: ( title: (
<span> <span>
<span>课程分类</span> <span>课程分类</span>
<If condition={type !== "internal"}> <If condition={type !== 'internal'}>
<Tooltip title={<div>外部课程的分类由系统提供,不影响企业课程分类。</div>}> <Tooltip title={<div>外部课程的分类由系统提供,不影响企业课程分类。</div>}>
<i className='icon iconfont' style={{ marginLeft: "5px", cursor: "pointer", color: "#bfbfbf", fontSize: "14px", fontWeight: "normal" }}> <i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px', fontWeight: 'normal' }}>
&#xe61d; &#xe61d;
</i> </i>
</Tooltip> </Tooltip>
</If> </If>
</span> </span>
), ),
key: "categoryName", key: 'categoryName',
dataIndex: "categoryName", dataIndex: 'categoryName',
width: 200, width: 200,
render: (val, record) => { render: (val, record) => {
return ( return (
<Choose> <Choose>
<When condition={type === "internal"}> <When condition={type === 'internal'}>
<div className='record__item'> <div className='record__item'>
{record.categoryOneName} {record.categoryOneName}
{record.categoryTwoName ? `-${record.categoryTwoName}` : ""} {record.categoryTwoName ? `-${record.categoryTwoName}` : ''}
</div> </div>
</When> </When>
<Otherwise> <Otherwise>
<div className='record__item'>{record.categorySonName}</div> <div className='record__item'>{record.categorySonName}</div>
</Otherwise> </Otherwise>
</Choose> </Choose>
) );
} },
}, },
{ {
title: "创建人", title: '创建人',
key: "createName", key: 'createName',
dataIndex: "createName", dataIndex: 'createName',
width: 100, width: 100,
render: (val) => { render: (val) => {
return ( return (
...@@ -133,8 +132,8 @@ class VideoCourseList extends React.Component { ...@@ -133,8 +132,8 @@ class VideoCourseList extends React.Component {
</Tooltip> </Tooltip>
)} )}
</div> </div>
) );
} },
}, },
{ {
title: ( title: (
...@@ -148,62 +147,62 @@ class VideoCourseList extends React.Component { ...@@ -148,62 +147,62 @@ class VideoCourseList extends React.Component {
关闭后,学院内不再展示此课程,但学员仍可通过分享的海报/链接查看此课程。 关闭后,学院内不再展示此课程,但学员仍可通过分享的海报/链接查看此课程。
</div> </div>
}> }>
<i className='icon iconfont' style={{ marginLeft: "5px", cursor: "pointer", color: "#bfbfbf", fontSize: "14px" }}> <i className='icon iconfont' style={{ marginLeft: '5px', cursor: 'pointer', color: '#bfbfbf', fontSize: '14px' }}>
&#xe61d; &#xe61d;
</i> </i>
</Tooltip> </Tooltip>
</span> </span>
), ),
width: 120, width: 120,
key: "shelfState", key: 'shelfState',
dataIndex: "shelfState", dataIndex: 'shelfState',
render: (val, item, index) => { render: (val, item, index) => {
return ( return (
<Switch <Switch
loading={ShelfLoading} loading={ShelfLoading}
checked={item.shelfState === "YES"} checked={item.shelfState === 'YES'}
defaultChecked={item.shelfState} defaultChecked={item.shelfState}
onClick={(checked) => { onClick={(checked) => {
this.changeShelfState(checked, item, index) this.changeShelfState(checked, item, index);
}} }}
/> />
) );
} },
}, },
{ {
title: "观看学员数", title: '观看学员数',
width: 110, width: 110,
key: "watchUserCount", key: 'watchUserCount',
dataIndex: "watchUserCount", dataIndex: 'watchUserCount',
render: (val, item) => { render: (val, item) => {
return <div className='watchUserCount'>{val || 0}</div> return <div className='watchUserCount'>{val || 0}</div>;
} },
}, },
{ {
title: "创建时间", title: '创建时间',
width: 181, width: 181,
key: "created", key: 'created',
dataIndex: "created", dataIndex: 'created',
sorter: true, sorter: true,
render: (val) => { render: (val) => {
return formatDate("YYYY-MM-DD H:i", val) return formatDate('YYYY-MM-DD H:i', val);
} },
}, },
{ {
title: "更新时间", title: '更新时间',
width: 181, width: 181,
key: "updated", key: 'updated',
dataIndex: "updated", dataIndex: 'updated',
sorter: true, sorter: true,
render: (val) => { render: (val) => {
return formatDate("YYYY-MM-DD H:i", val) return formatDate('YYYY-MM-DD H:i', val);
} },
}, },
{ {
title: "关联项", title: '关联项',
width: 200, width: 200,
key: "planList", key: 'planList',
dataIndex: "planList", dataIndex: 'planList',
render: (val, record) => { render: (val, record) => {
return ( return (
<div className='related-task'> <div className='related-task'>
...@@ -215,7 +214,7 @@ class VideoCourseList extends React.Component { ...@@ -215,7 +214,7 @@ class VideoCourseList extends React.Component {
<span> <span>
{item.planName} {index < record.relatedPlanList.length - 1 && <span></span>} {item.planName} {index < record.relatedPlanList.length - 1 && <span></span>}
</span> </span>
) );
})} })}
</Tooltip> </Tooltip>
</When> </When>
...@@ -224,15 +223,15 @@ class VideoCourseList extends React.Component { ...@@ -224,15 +223,15 @@ class VideoCourseList extends React.Component {
</Otherwise> </Otherwise>
</Choose> </Choose>
</div> </div>
) );
} },
}, },
{ {
title: "操作", title: '操作',
key: "operate", key: 'operate',
dataIndex: "operate", dataIndex: 'operate',
width: 210, width: 210,
fixed: "right", fixed: 'right',
render: (val, record) => { render: (val, record) => {
return ( return (
<div className='operate'> <div className='operate'>
...@@ -240,7 +239,7 @@ class VideoCourseList extends React.Component { ...@@ -240,7 +239,7 @@ class VideoCourseList extends React.Component {
观看数据 观看数据
</div> </div>
<If condition={type === "internal"}> <If condition={type === 'internal'}>
<span className='operate__item split'> | </span> <span className='operate__item split'> | </span>
<div className='operate__item' onClick={() => this.handleShowShareModal(record)}> <div className='operate__item' onClick={() => this.handleShowShareModal(record)}>
分享 分享
...@@ -250,40 +249,40 @@ class VideoCourseList extends React.Component { ...@@ -250,40 +249,40 @@ class VideoCourseList extends React.Component {
<Dropdown overlay={this.renderMoreOperate(record)}> <Dropdown overlay={this.renderMoreOperate(record)}>
<span className='more-operate'> <span className='more-operate'>
<span className='operate-text'>更多</span> <span className='operate-text'>更多</span>
<span className='iconfont icon' style={{ color: "#2966FF" }}> <span className='iconfont icon' style={{ color: '#2966FF' }}>
&#xe824; &#xe824;
</span> </span>
</span> </span>
</Dropdown> </Dropdown>
</div> </div>
) );
} },
} },
] ];
type !== "internal" && columns.splice(2, 1) type !== 'internal' && columns.splice(2, 1);
return columns return columns;
} };
renderMoreOperate = (item) => { renderMoreOperate = (item) => {
const { type } = this.props const { type } = this.props;
return ( return (
<div className='live-course-more-menu'> <div className='live-course-more-menu'>
<If condition={type !== "internal"}> <If condition={type !== 'internal'}>
<div className='operate__item' onClick={() => this.handleShowShareModal(item)}> <div className='operate__item' onClick={() => this.handleShowShareModal(item)}>
分享 分享
</div> </div>
</If> </If>
{(User.getUserRole() === "CloudManager" || User.getUserRole() === "StoreManager") && ( {(User.getUserRole() === 'CloudManager' || User.getUserRole() === 'StoreManager') && (
<div className='operate__item' onClick={() => this.handleRelatedModalShow(item)}> <div className='operate__item' onClick={() => this.handleRelatedModalShow(item)}>
关联培训计划 关联培训计划
</div> </div>
)} )}
<If condition={type === "internal"}> <If condition={type === 'internal'}>
<div <div
className='operate__item' className='operate__item'
onClick={() => { onClick={() => {
window.RCHistory.push(`/create-video-course?type=edit&id=${item.id}`) window.RCHistory.push(`/create-video-course?type=edit&id=${item.id}`);
}}> }}>
编辑 编辑
</div> </div>
...@@ -292,77 +291,77 @@ class VideoCourseList extends React.Component { ...@@ -292,77 +291,77 @@ class VideoCourseList extends React.Component {
</div> </div>
</If> </If>
</div> </div>
) );
} };
handlePlanName = (planArray) => { handlePlanName = (planArray) => {
let planStr = "" let planStr = '';
planArray.map((item, index) => { planArray.map((item, index) => {
if (index < planArray.length - 1) { if (index < planArray.length - 1) {
planStr = planStr + item.planName + "、" planStr = planStr + item.planName + '、';
} else { } else {
planStr = planStr + item.planName planStr = planStr + item.planName;
} }
}) });
return planStr return planStr;
} };
//改变上架状态 //改变上架状态
changeShelfState = (checked, item, index) => { changeShelfState = (checked, item, index) => {
let _shelfState = checked ? "YES" : "NO" let _shelfState = checked ? 'YES' : 'NO';
if (checked) { if (checked) {
_shelfState = "YES" _shelfState = 'YES';
} else { } else {
_shelfState = "NO" _shelfState = 'NO';
} }
const params = { const params = {
courseId: item.id, courseId: item.id,
shelfState: _shelfState shelfState: _shelfState,
} };
CourseService.changeVideoShelfState(params).then(() => { CourseService.changeVideoShelfState(params).then(() => {
if (_shelfState === "YES") { if (_shelfState === 'YES') {
message.success("已开启展示") message.success('已开启展示');
} else { } else {
message.success("已取消展示") message.success('已取消展示');
} }
this.props.changeShelfState(index, _shelfState) this.props.changeShelfState(index, _shelfState);
}) });
} };
// 删除视频课 // 删除视频课
handleDeleteVideoCourse = (scheduleId) => { handleDeleteVideoCourse = (scheduleId) => {
Modal.confirm({ Modal.confirm({
title: "你确定要删除此视频课吗?", title: '你确定要删除此视频课吗?',
content: "删除后,学员将不能进行观看。", content: '删除后,学员将不能进行观看。',
icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>, icon: <span className='icon iconfont default-confirm-icon'>&#xe6f4;</span>,
okText: "确定", okText: '确定',
okType: "danger", okType: 'danger',
cancelText: "取消", cancelText: '取消',
onOk: () => { onOk: () => {
const param = { const param = {
courseId: scheduleId, courseId: scheduleId,
storeId: User.getStoreId() storeId: User.getStoreId(),
} };
CourseService.delVideoSchedule(param).then(() => { CourseService.delVideoSchedule(param).then(() => {
message.success("删除成功") message.success('删除成功');
this.props.onChange() this.props.onChange();
}) });
} },
}) });
} };
// 显示分享弹窗 // 显示分享弹窗
handleShowShareModal = (record, needStr = false) => { handleShowShareModal = (record, needStr = false) => {
const { type } = this.props const { type } = this.props;
const { id, scheduleVideoUrl } = record const { id, scheduleVideoUrl } = record;
const htmlUrl = `${LIVE_SHARE}video_detail/${id}?id=${User.getStoreId()}` const htmlUrl = `${LIVE_SHARE}video_detail/${id}?id=${User.getStoreId()}`;
const longUrl = htmlUrl const longUrl = htmlUrl;
const { coverUrl, courseName } = record const { coverUrl, courseName } = record;
const shareData = { const shareData = {
longUrl, longUrl,
coverUrl, coverUrl,
scheduleVideoUrl, scheduleVideoUrl,
courseName courseName,
} };
const shareLiveModal = ( const shareLiveModal = (
<ShareLiveModal <ShareLiveModal
...@@ -373,95 +372,109 @@ class VideoCourseList extends React.Component { ...@@ -373,95 +372,109 @@ class VideoCourseList extends React.Component {
title='视频课' title='视频课'
close={() => { close={() => {
this.setState({ this.setState({
shareLiveModal: null shareLiveModal: null,
}) });
localStorage.setItem("videoCourseItem", "") localStorage.setItem('videoCourseItem', '');
}} }}
/> />
) );
this.setState({ shareLiveModal }) this.setState({ shareLiveModal });
} };
handleChangeTable = (pagination, filters, sorter) => { handleChangeTable = (pagination, filters, sorter) => {
const { columnKey, order } = sorter const { columnKey, order } = sorter;
const { query } = this.props const { query } = this.props;
let { order: _order } = query let { order: _order } = query;
// 按创建时间升序排序 // 按创建时间升序排序
if (columnKey === "created" && order === "ascend") { if (columnKey === 'created' && order === 'ascend') {
_order = "CREATED_ASC" _order = 'CREATED_ASC';
} }
// 按创建时间降序排序 // 按创建时间降序排序
if (columnKey === "created" && order === "descend") { if (columnKey === 'created' && order === 'descend') {
_order = "CREATED_DESC" _order = 'CREATED_DESC';
} }
// 按更新时间升序排序 // 按更新时间升序排序
if (columnKey === "updated" && order === "ascend") { if (columnKey === 'updated' && order === 'ascend') {
_order = "UPDATED_ASC" _order = 'UPDATED_ASC';
} }
// 按更新时间降序排序 // 按更新时间降序排序
if (columnKey === "updated" && order === "descend") { if (columnKey === 'updated' && order === 'descend') {
_order = "UPDATED_DESC" _order = 'UPDATED_DESC';
} }
const _query = { const _query = {
...query, ...query,
orderEnum: _order orderEnum: _order,
} };
this.props.onChange(_query) this.props.onChange(_query);
} };
handleRelatedModalShow = (item) => { handleRelatedModalShow = (item) => {
const selectPlanList = {} const selectPlanList = {};
if (item.relatedPlanList) { if (item.relatedPlanList) {
item.relatedPlanList.map((item, index) => { item.relatedPlanList.map((item, index) => {
selectPlanList[item.planId] = {} selectPlanList[item.planId] = {};
selectPlanList[item.planId].planId = item.planId selectPlanList[item.planId].planId = item.planId;
selectPlanList[item.planId].taskBaseVOList = [{ taskId: item.taskId }] selectPlanList[item.planId].taskBaseVOList = [{ taskId: item.taskId }];
return item return item;
}) });
} }
this.setState({ this.setState({
RelatedPlanModalVisible: true, RelatedPlanModalVisible: true,
selectCourseId: item.id, selectCourseId: item.id,
selectPlanList: selectPlanList selectPlanList: selectPlanList,
}) });
} };
closeRelatedPlanModalVisible = () => { closeRelatedPlanModalVisible = () => {
this.setState({ this.setState({
RelatedPlanModalVisible: false RelatedPlanModalVisible: false,
}) });
} };
onChangeSelectPlanList = (selectPlanList) => { onChangeSelectPlanList = (selectPlanList) => {
this.setState({ this.setState({
selectPlanList: selectPlanList selectPlanList: selectPlanList,
}) });
} };
onConfirmSelectPlanList = () => { onConfirmSelectPlanList = () => {
this.setState( this.setState(
{ {
RelatedPlanModalVisible: false RelatedPlanModalVisible: false,
}, },
() => { () => {
this.props.onChange() this.props.onChange();
} }
) );
} };
render() { render() {
const { dataSource = [], totalCount, query, type } = this.props const { dataSource = [], totalCount, query, type } = this.props;
const { current, size } = query const { current, size } = query;
const { RelatedPlanModalVisible, selectPlanList, selectCourseId } = this.state const { RelatedPlanModalVisible, selectPlanList, selectCourseId } = this.state;
return ( return (
<div className={`video-course-list ${type !== "internal" ? "video-course-list-mt" : ""}`}> <div className={`video-course-list ${type !== 'internal' ? 'video-course-list-mt' : ''}`}>
<Table <XMTable
renderEmpty={{
image: college,
description: '暂无数据',
}}
rowKey={(record) => record.id} rowKey={(record) => record.id}
dataSource={dataSource} dataSource={dataSource}
columns={this.parseColumns()} columns={this.parseColumns()}
onChange={this.handleChangeTable} onChange={this.handleChangeTable}
pagination={false} pagination={false}
scroll={{ x: 1500 }}
bordered bordered
scroll={{ x: 1500 }}
className='video-list-table' className='video-list-table'
/> />
{/* <Table
rowKey={(record) => record.id}
dataSource={dataSource}
columns={this.parseColumns()}
onChange={this.handleChangeTable}
pagination={false}
scroll={{ x: 1500 }}
bordered
className='video-list-table'
/> */}
<div className='box-footer'> <div className='box-footer'>
<PageControl <PageControl
...@@ -469,8 +482,8 @@ class VideoCourseList extends React.Component { ...@@ -469,8 +482,8 @@ class VideoCourseList extends React.Component {
pageSize={size} pageSize={size}
total={totalCount} total={totalCount}
toPage={(page) => { toPage={(page) => {
const _query = { ...query, current: page + 1 } const _query = { ...query, current: page + 1 };
this.props.onChange(_query) this.props.onChange(_query);
}} }}
/> />
</div> </div>
...@@ -487,8 +500,8 @@ class VideoCourseList extends React.Component { ...@@ -487,8 +500,8 @@ class VideoCourseList extends React.Component {
{this.state.shareLiveModal} {this.state.shareLiveModal}
{this.state.watchDataModal} {this.state.watchDataModal}
</div> </div>
) );
} }
} }
export default VideoCourseList export default VideoCourseList;
/* /*
* @Author: 吴文洁 * @Author: 吴文洁
* @Date: 2020-05-19 11:01:31 * @Date: 2020-05-19 11:01:31
* @Last Modified by: 吴文洁 * @Last Modified by: 吴文洁
* @Last Modified time: 2020-05-25 16:50:47 * @Last Modified time: 2020-05-25 16:50:47
* @Description 余额异常弹窗 * @Description 余额异常弹窗
*/ */
import User from '@/common/js/user';
import { PageControl, XMTable } from '@/components';
import CourseService from '@/domains/course-domain/CourseService';
import { Input, Modal } from 'antd';
import college from '@/common/lottie/college';
import React from 'react'; import React from 'react';
import {Table, Modal,Input} from 'antd'; import dealTimeDuration from '../../utils/dealTimeDuration';
import { PageControl } from "@/components";
import CourseService from "@/domains/course-domain/CourseService";
import User from '@/common/js/user'
import './WatchDataModal.less'; import './WatchDataModal.less';
import dealTimeDuration from "../../utils/dealTimeDuration";
const { Search } = Input; const { Search } = Input;
class WatchDataModal extends React.Component { class WatchDataModal extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
visible:true, visible: true,
dataSource:[], dataSource: [],
size:10, size: 10,
query: { query: {
current: 1, current: 1,
}, },
totalCount:0 totalCount: 0,
}; };
} }
componentDidMount() { componentDidMount() {
this.handleFetchDataList(); this.handleFetchDataList();
} }
onClose = () =>{ onClose = () => {
this.props.close(); this.props.close();
} };
// 获取观看视频数据列表 // 获取观看视频数据列表
handleFetchDataList = () => { handleFetchDataList = () => {
const {query,size,totalCount} = this.state const { query, size, totalCount } = this.state;
const { id } = this.props.data; const { id } = this.props.data;
const params ={ const params = {
...query, ...query,
size, size,
courseId:id, courseId: id,
storeId:User.getStoreId() storeId: User.getStoreId(),
} };
CourseService.videoWatchInfo(params).then((res) => { CourseService.videoWatchInfo(params).then((res) => {
const { result = {} } = res ; const { result = {} } = res;
const { records = [], total = 0 } = result; const { records = [], total = 0 } = result;
this.setState({ this.setState({
dataSource: records, dataSource: records,
totalCount: Number(total) totalCount: Number(total),
}); });
}); });
} };
handleChangNickname = (value)=>{ handleChangNickname = (value) => {
const isPhone = (value || '').match(/^\d+$/); const isPhone = (value || '').match(/^\d+$/);
const { query } = this.state; const { query } = this.state;
if(isPhone){ if (isPhone) {
query.phone = value; query.phone = value;
query.nickName = null; query.nickName = null;
}else{ } else {
query.nickName = value; query.nickName = value;
query.phone = null; query.phone = null;
} }
query.current = 1; query.current = 1;
this.setState({ this.setState({
query query,
}) });
} };
onShowSizeChange = (current, size) => { onShowSizeChange = (current, size) => {
if (current == size) { if (current == size) {
return return;
} }
this.setState({ this.setState(
size {
},()=>{this.handleFetchDataList()}) size,
} },
() => {
this.handleFetchDataList();
}
);
};
// 请求表头 // 请求表头
parseColumns = () => { parseColumns = () => {
...@@ -86,84 +92,102 @@ class WatchDataModal extends React.Component { ...@@ -86,84 +92,102 @@ class WatchDataModal extends React.Component {
{ {
title: '观看学员', title: '观看学员',
key: 'name', key: 'name',
dataIndex: 'name' dataIndex: 'name',
}, },
{ {
title: '手机号', title: '手机号',
key: 'phone', key: 'phone',
dataIndex: 'phone' dataIndex: 'phone',
}, },
{ {
title: '观看者类型', title: '观看者类型',
key: 'userRole', key: 'userRole',
dataIndex: 'userRole' dataIndex: 'userRole',
}, },
{ {
title: '首次观看时间', title: '首次观看时间',
key: 'firstWatch', key: 'firstWatch',
dataIndex: 'firstWatch', dataIndex: 'firstWatch',
render: (val) => { render: (val) => {
return formatDate('YYYY-MM-DD H:i', val) return formatDate('YYYY-MM-DD H:i', val);
} },
}, },
{ {
title: '观看时长', title: '观看时长',
key: 'watchDuration', key: 'watchDuration',
dataIndex: 'watchDuration', dataIndex: 'watchDuration',
render: (val) => { render: (val) => {
return <span>{val ? dealTimeDuration(val) : "00:00:00" }</span> return <span>{val ? dealTimeDuration(val) : '00:00:00'}</span>;
} },
} },
]; ];
return columns; return columns;
} };
render() { render() {
const { visible,size,dataSource,totalCount,query} = this.state; const { visible, size, dataSource, totalCount, query } = this.state;
return ( return (
<Modal <Modal
title="视频课观看数据" title='视频课观看数据'
visible={visible} visible={visible}
footer={null} footer={null}
onCancel={this.onClose} onCancel={this.onClose}
maskClosable={false} maskClosable={false}
className="watch-data-modal" className='watch-data-modal'
closable={true} closable={true}
width={800} width={800}
closeIcon={<span className="icon iconfont modal-close-icon">&#xe6ef;</span>} closeIcon={<span className='icon iconfont modal-close-icon'>&#xe6ef;</span>}>
> <div className='search-container'>
<div className="search-container"> <Search
<Search placeholder="搜索学员姓名/手机号" style={{ width: 200 }} onChange={(e) => { this.handleChangNickname(e.target.value)}} onSearch={ () => { this.handleFetchDataList()}} enterButton={<span className="icon iconfont">&#xe832;</span>}/> placeholder='搜索学员姓名/手机号'
</div> style={{ width: 200 }}
<div> onChange={(e) => {
<Table this.handleChangNickname(e.target.value);
rowKey={record => record.id} }}
dataSource={dataSource} onSearch={() => {
columns={this.parseColumns()} this.handleFetchDataList();
pagination={false} }}
bordered enterButton={<span className='icon iconfont'>&#xe832;</span>}
/> />
{dataSource.length >0 && </div>
<div className="box-footer"> <div>
<PageControl <XMTable
current={query.current - 1} renderEmpty={{
pageSize={size} image: college,
total={totalCount} description: '暂无数据',
size="small" }}
toPage={(page) => { rowKey={(record) => record.id}
const _query = {...query, current: page + 1}; dataSource={dataSource}
this.setState({ columns={this.parseColumns()}
query:_query pagination={false}
},()=>{ this.handleFetchDataList()}) bordered
}} />
onShowSizeChange={this.onShowSizeChange} {dataSource.length > 0 && (
/> <div className='box-footer'>
</div> <PageControl
} current={query.current - 1}
</div> pageSize={size}
</Modal> total={totalCount}
) size='small'
toPage={(page) => {
const _query = { ...query, current: page + 1 };
this.setState(
{
query: _query,
},
() => {
this.handleFetchDataList();
}
);
}}
onShowSizeChange={this.onShowSizeChange}
/>
</div>
)}
</div>
</Modal>
);
} }
} }
export default WatchDataModal; export default WatchDataModal;
\ No newline at end of file
import React, { Key, useContext, useEffect, useRef, useState, useMemo } from 'react'; import User from '@/common/js/user';
import { import StoreService from '@/domains/store-domain/storeService';
withRouter,
} from 'react-router-dom';
import { Menu } from 'antd'; import { Menu } from 'antd';
import { menuList } from '../../routes//config/menuList' import React, { Key, useContext, useEffect, useMemo, useState } from 'react';
import { XMContext } from '../../store/context'; import { withRouter } from 'react-router-dom';
import Service from "@/common/js/service";
import StoreService from "@/domains/store-domain/storeService";
import User from "@/common/js/user";
import _ from 'underscore'; import _ from 'underscore';
import "./Menu.less"; import { menuList } from '../../routes//config/menuList';
import { XMContext } from '../../store/context';
import './Menu.less';
const { SubMenu } = Menu; const { SubMenu } = Menu;
function Aside(props: any) { function Aside(props: any) {
const { menuType, handleMenuType } = props const { menuType, handleMenuType } = props;
const ctx: any = useContext(XMContext); const ctx: any = useContext(XMContext);
const [selectKey, setSelectKey] = useState(); const [selectKey, setSelectKey] = useState();
const [selectKeyParent, setSelectKeyParent] = useState();
const [openKeys, setOpenKeys] = useState(['']); const [openKeys, setOpenKeys] = useState(['']);
const [topLogoUrl, setTopLogoUrl] = useState("") const [topLogoUrl, setTopLogoUrl] = useState('');
const [collapsed, setCollapsed] = useState(false) const [collapsed, setCollapsed] = useState(false);
const rootSubmenuKeys = _.pluck(menuList, 'groupCode'); const rootSubmenuKeys = _.pluck(menuList, 'groupCode');
useEffect(() => { useEffect(() => {
...@@ -26,44 +24,46 @@ function Aside(props: any) { ...@@ -26,44 +24,46 @@ function Aside(props: any) {
menuList.map((item: any, index: any) => { menuList.map((item: any, index: any) => {
if (link.indexOf(item.link) !== -1) { if (link.indexOf(item.link) !== -1) {
setSelectKey(item.groupCode); setSelectKey(item.groupCode);
setOpenKeys([]) setSelectKeyParent(item.groupCode);
setOpenKeys([]);
} else if (item.children) { } else if (item.children) {
item.children.map((_item: any, _index: any) => { item.children.map((_item: any, _index: any) => {
if (link.indexOf(_item.link) !== -1) { if (link.indexOf(_item.link) !== -1) {
setSelectKeyParent(item.groupCode);
setSelectKey(_item.groupCode + index + _index); setSelectKey(_item.groupCode + index + _index);
} }
}) });
} }
return item; return item;
}) });
}, [props.location.pathname]) }, [props.location.pathname]);
useEffect(() => { useEffect(() => {
getTopLeftLogo() getTopLeftLogo();
}, []) }, []);
function getTopLeftLogo() { function getTopLeftLogo() {
if (User.getToken()) { if (User.getToken()) {
StoreService.getStoreDetail({ storeId: User.getStoreId() }) StoreService.getStoreDetail({ storeId: User.getStoreId() }).then((res) => {
.then(res => { if (_.isEmpty(res.result.logo)) {
if (_.isEmpty(res.result.logo)) { setTopLogoUrl('https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png');
setTopLogoUrl("https://image.xiaomaiketang.com/xm/fe4NCjr7XF.png") } else {
} else { setTopLogoUrl(res.result.logo);
setTopLogoUrl(res.result.logo) }
} });
})
} }
} }
function toggleMenu(item: any) { function toggleMenu(item: any, selectKey: any) {
window.RCHistory.push(item.link) console.log('item', item, selectKey);
setSelectKeyParent(selectKey);
window.RCHistory.push(item.link);
if (!menuType) { if (!menuType) {
setOpenKeys([]) setOpenKeys([]);
} }
} }
function onOpenChange(key: Key[]) { function onOpenChange(key: Key[]) {
if (typeof key === "string") { if (typeof key === 'string') {
if (openKeys.includes(key)) { if (openKeys.includes(key)) {
setOpenKeys([]); setOpenKeys([]);
} else { } else {
...@@ -74,9 +74,9 @@ function Aside(props: any) { ...@@ -74,9 +74,9 @@ function Aside(props: any) {
function onOpenChangeForHover(key: Key[]) { function onOpenChangeForHover(key: Key[]) {
if (menuType) { if (menuType) {
return return;
} }
if (typeof key === "string") { if (typeof key === 'string') {
if (openKeys.includes(key)) { if (openKeys.includes(key)) {
setOpenKeys([]); setOpenKeys([]);
} else { } else {
...@@ -87,94 +87,78 @@ function Aside(props: any) { ...@@ -87,94 +87,78 @@ function Aside(props: any) {
function handleMenu() { function handleMenu() {
handleMenuType(); handleMenuType();
setCollapsed(!collapsed) setCollapsed(!collapsed);
} }
const openKeysConstrol = useMemo(() => { const openKeysConstrol = useMemo(() => {
return { return {
[menuType ? 'openKeys' : 'defaultOpenKeys']: openKeys [menuType ? 'openKeys' : 'defaultOpenKeys']: openKeys,
}; };
}, [menuType, openKeys]) }, [menuType, openKeys]);
return ( return (
<div <div id='left-container' className={menuType ? 'left-container' : 'left-container left-container-vertical'}>
id="left-container" <div className='top-ctrl'>
className={ <div className='topLogo'>{menuType && <img src={topLogoUrl} alt='' className='img1'></img>}</div>
menuType <div className='menu-type-icon' onClick={handleMenu}>
? "left-container" {menuType ? <span className='icon iconfont'>&#xe83d;</span> : <span className='icon iconfont'>&#xe615;</span>}
: "left-container left-container-vertical"
}
>
<div className="top-ctrl">
<div className="topLogo">
{menuType && <img src={topLogoUrl} alt="" className="img1"></img>}
</div>
<div className="menu-type-icon" onClick={handleMenu}>
{menuType ? (
<span
className="icon iconfont"
>
&#xe83d;
</span>
) : (
<span
className="icon iconfont"
>
&#xe615;
</span>
)}
</div> </div>
</div> </div>
<div className="left"> <div className='left'>
<div className="nav"> <div className='nav'>
<Menu <Menu
{...openKeysConstrol} {...openKeysConstrol}
style={menuType ? { minHeight: "100%", background: '#0E1935' } : { minHeight: "100%", background: '#0E1935', width: "56px" }} style={menuType ? { minHeight: '100%', background: '#0E1935' } : { minHeight: '100%', background: '#0E1935', width: '56px' }}
selectedKeys={selectKey} selectedKeys={selectKey}
onOpenChange={onOpenChange} onOpenChange={onOpenChange}
inlineCollapsed={collapsed} inlineCollapsed={collapsed}
mode={menuType ? "inline" : "vertical"} mode={menuType ? 'inline' : 'vertical'}>
> {menuList.map((item: any, index: any) => {
{ if (ctx.xmState.storeUserPermissionList.indexOf(item.groupCode) === -1) {
menuList.map((item: any, index: any) => { return null;
if (ctx.xmState.storeUserPermissionList.indexOf(item.groupCode) === -1) { }
return null; // console.log('selectKe===>', selectKey);
} // console.log('item===>', item);
if (item.children) {
return <SubMenu if (item.children) {
return (
<SubMenu
key={item.groupCode} key={item.groupCode}
style={{ marginTop: 0 }} style={{ marginTop: 0, backgroundColor: !menuType && item.groupCode === selectKeyParent ? '#2966FF' : '#fff' }}
icon={<img src={item.img} className="icon-img"></img>} icon={<img src={item.img} className='icon-img'></img>}
title={menuType ? <span>{item.groupName}</span> : ""} title={menuType ? <span>{item.groupName}</span> : ''}
onTitleClick={() => onOpenChange(item.groupCode)} onTitleClick={() => onOpenChange(item.groupCode)}>
> {item.children.map((_item: any, _index: any) => {
{ if (ctx.xmState.storeUserPermissionList.indexOf(_item.groupCode) === -1) {
item.children.map((_item: any, _index: any) => { return null;
if (ctx.xmState.storeUserPermissionList.indexOf(_item.groupCode) === -1) { }
return null; return (
} <Menu.Item
return <Menu.Item onClick={() => { toggleMenu(_item) }} style={{ marginTop: 0 }} key={_item.groupCode + index + _index} > onClick={() => {
<span className="name">{_item.groupName}</span> toggleMenu(_item, item.groupCode);
}}
style={{ marginTop: 0 }}
key={_item.groupCode + index + _index}>
<span className='name'>{_item.groupName}</span>
</Menu.Item> </Menu.Item>
);
}) })}
}
</SubMenu> </SubMenu>
} else { );
return <Menu.Item } else {
onClick={() => { toggleMenu(item) }} return (
<Menu.Item
onClick={() => {
toggleMenu(item, item.groupCode);
}}
key={item.groupCode} key={item.groupCode}
icon={<img src={selectKey === item.groupCode ? item.selectImg : item.img} className="icon-img"></img>} icon={<img src={selectKey === item.groupCode ? item.selectImg : item.img} className='icon-img'></img>}>
> {menuType ? item.groupName : ''}
{menuType ? item.groupName : ""}
</Menu.Item> </Menu.Item>
} );
}) }
} })}
</Menu> </Menu>
</div> </div>
</div> </div>
...@@ -182,4 +166,4 @@ function Aside(props: any) { ...@@ -182,4 +166,4 @@ function Aside(props: any) {
); );
} }
export default withRouter(Aside); export default withRouter(Aside);
\ No newline at end of file
...@@ -8,142 +8,142 @@ ...@@ -8,142 +8,142 @@
*/ */
export const menuList: any = [ export const menuList: any = [
{ {
groupName: "中心首页", groupName: '中心首页',
groupCode: "CloudPage", groupCode: 'CloudPage',
icon: '&#xe8a7;', icon: '&#xe8a7;',
link: '/home', link: '/home',
img:'https://image.xiaomaiketang.com/xm/ni3BFJDT3a.png', img: 'https://image.xiaomaiketang.com/xm/ni3BFJDT3a.png',
selectImg:'https://image.xiaomaiketang.com/xm/GRDztTAWaM.png' selectImg: 'https://image.xiaomaiketang.com/xm/GRDztTAWaM.png',
}, },
{ {
groupName: "课程管理", groupName: '课程管理',
groupCode: "CloudCourse", groupCode: 'CloudCourse',
icon: '&#xe8a5;', icon: '&#xe8a5;',
img:'https://image.xiaomaiketang.com/xm/jBGrGjM7HQ.png', img: 'https://image.xiaomaiketang.com/xm/jBGrGjM7HQ.png',
children: [ children: [
{ {
groupName: "直播课", groupName: '直播课',
groupCode: "CourseLiveClass", groupCode: 'CourseLiveClass',
link: '/live-course' link: '/live-course',
}, },
{ {
groupName: "视频课", groupName: '视频课',
groupCode: "CourseVideoClass", groupCode: 'CourseVideoClass',
link: '/video-course' link: '/video-course',
}, },
{ {
groupName: "图文课", groupName: '图文课',
groupCode: "GraphicLesson", groupCode: 'GraphicLesson',
link: '/graphics-course' link: '/graphics-course',
}, },
{ {
groupName: "线下课", groupName: '线下课',
groupCode: "OfflineClass", groupCode: 'OfflineClass',
link: '/offline-course' link: '/offline-course',
}, },
] ],
}, },
{ {
groupName: "培训管理", groupName: '培训管理',
groupCode: "TrainManage", groupCode: 'TrainManage',
icon: '&#xe8a6;', icon: '&#xe8a6;',
img:'https://image.xiaomaiketang.com/xm/Yy6pZ6G6kS.png', img: 'https://image.xiaomaiketang.com/xm/Yy6pZ6G6kS.png',
children: [ children: [
{ {
groupName: "培训计划", groupName: '培训计划',
groupCode: "TrainPlan", groupCode: 'TrainPlan',
link: '/plan' link: '/plan',
} },
], ],
}, },
{ {
groupName: "助学工具", groupName: '助学工具',
groupCode: "AidTool", groupCode: 'AidTool',
icon: '&#xe8a9;', icon: '&#xe8a9;',
img:'https://image.xiaomaiketang.com/xm/xsma4hx3b3.png', img: 'https://image.xiaomaiketang.com/xm/xsma4hx3b3.png',
children: [ children: [
{ {
groupName: "题库", groupName: '题库',
groupCode: "QuestionBank", groupCode: 'QuestionBank',
link: '/question-manage-index' link: '/question-manage-index',
}, },
{ {
groupName: "试卷", groupName: '试卷',
groupCode: "ExamPaper", groupCode: 'ExamPaper',
link: '/paper-manage-index' link: '/paper-manage-index',
}, },
{ {
groupName: "考试", groupName: '考试',
groupCode: "CloudExam", groupCode: 'CloudExam',
link: '/examination-manage-index' link: '/examination-manage-index',
}, },
] ],
}, },
{ {
groupName: "知识库", groupName: '知识库',
groupCode: "CloudKnowledge", groupCode: 'CloudKnowledge',
icon: '&#xe8a8;', icon: '&#xe8a8;',
link: '/knowledge-base', link: '/knowledge-base',
img:'https://image.xiaomaiketang.com/xm/8sbP5rGQWh.png', img: 'https://image.xiaomaiketang.com/xm/8sbP5rGQWh.png',
selectImg:'https://image.xiaomaiketang.com/xm/hJKCfibC22.png' selectImg: 'https://image.xiaomaiketang.com/xm/hJKCfibC22.png',
}, },
{ {
groupName: "资料云盘", groupName: '资料云盘',
groupCode: "CloudDisk", groupCode: 'CloudDisk',
icon: '&#xe8aa;', icon: '&#xe8aa;',
link: '/resource-disk', link: '/resource-disk',
img:'https://image.xiaomaiketang.com/xm/zGKbXJPzXx.png', img: 'https://image.xiaomaiketang.com/xm/zGKbXJPzXx.png',
selectImg:'https://image.xiaomaiketang.com/xm/5sN4MzjxYc.png', selectImg: 'https://image.xiaomaiketang.com/xm/5sN4MzjxYc.png',
}, },
{ {
groupName: "人员管理", groupName: '人员管理',
groupCode: "PersonManage", groupCode: 'PersonManage',
icon: '&#xe8a4;', icon: '&#xe8a4;',
img:'https://image.xiaomaiketang.com/xm/PRCnrt35y8.png', img: 'https://image.xiaomaiketang.com/xm/PRCnrt35y8.png',
children: [ children: [
{ {
groupName: "员工管理", groupName: '员工管理',
groupCode: "ShopStaff", groupCode: 'ShopStaff',
link: '/college-employee' link: '/college-employee',
}, },
{ {
groupName: "学员管理", groupName: '学员管理',
groupCode: "ShopUser", groupCode: 'ShopUser',
link: '/college-user' link: '/college-user',
} },
] ],
}, },
{ {
groupName: "学院管理", groupName: '学院管理',
groupCode: "CloudShop", groupCode: 'CloudShop',
icon: '&#xe8a4;', icon: '&#xe8a4;',
img:'https://image.xiaomaiketang.com/xm/Q8i5RSMKNc.png', img: 'https://image.xiaomaiketang.com/xm/Q8i5RSMKNc.png',
children: [ children: [
{ {
groupName: "学院信息", groupName: '学院信息',
groupCode: "ShopInfo", groupCode: 'ShopInfo',
link: '/college-info' link: '/college-info',
}, },
{ {
groupName: "学院装修", groupName: '学院装修',
groupCode: "ShopDecoration", groupCode: 'ShopDecoration',
link: '/store-decoration' link: '/store-decoration',
}, },
{ {
groupName: "分类管理", groupName: '分类管理',
groupCode: "CourseCategory", groupCode: 'CourseCategory',
link: '/course-category-manage' link: '/course-category-manage',
}, },
{ {
groupName: "H5学院", groupName: 'H5学院',
groupCode: "ShopDecorationH5", groupCode: 'ShopDecorationH5',
link: '/store-decoration/h5' link: '/store-decoration/h5',
}, },
{ {
groupName: "网页端学院", groupName: '网页端学院',
groupCode: "ShopDecorationWeb", groupCode: 'ShopDecorationWeb',
link: '/store-decoration/web' link: '/store-decoration/web',
} },
] ],
}, },
] ];
\ No newline at end of file
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