Commit 23a0227a by wufan

feat:增加上课数据

parent 4ef073c8
......@@ -21,6 +21,7 @@ const Breadcrumbs = (props: BreadcrumbsProps) => {
const { goBack, navList, text } = props;
function _onClick(): any {
console.log("返回来")
goBack ? goBack() : window.RCHistory.goBack();
}
const isString = _.isString(navList);
......
......@@ -12,8 +12,8 @@ import $ from 'jquery';
import '@/libs/cropper/cropper.min.css';
import 'cropper';
import Upload from '../core/upload';
import baseImg from '@/common/images/xiaomai-IMG.png';
import './CropperModal.less';
const baseImg ='https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png'
interface CropperModalProps {
title?: string;
......
......@@ -32,6 +32,12 @@ interface ClassSearchSelectProps {
hasNoClass?: any;
onSelect?: (val1: any, val2?: any) => void;
teacherId?: any;
mode?: "multiple" | "tags" | undefined
}
interface ItemTypes {
name: string,
classId: string,
}
const ClassSearchSelect = (props: ClassSearchSelectProps) => {
......@@ -55,11 +61,11 @@ const ClassSearchSelect = (props: ClassSearchSelectProps) => {
const [isAll, setIsAll] = useState(false);
useEffect(() => {
Bus.bind('reset', handleQueryReset);
// Bus.bind('reset', handleQueryReset);
// fetchServerData();
return () => {
Bus.unbind('reset');
// Bus.unbind('reset');
clearTimeout(timer);
clearTimeout(scroll);
};
......@@ -72,7 +78,7 @@ const ClassSearchSelect = (props: ClassSearchSelectProps) => {
}, 300)
}, [props.courseId]);
const defprops = _.pick(props, 'open', 'getPopupContainer');
let defprops = _.pick(props, 'open', 'getPopupContainer');
if (multiple) {
defprops.mode = 'multiple';
}
......@@ -116,44 +122,44 @@ const ClassSearchSelect = (props: ClassSearchSelectProps) => {
const param = _.extend(queryTemp, props.query);
if (url == "public/homework/getTeacherClassPage") {
window.axios.Zeus(urlTemp, param).then((res: any) => {
const data = res.result.records;
_.map(data, (item: any) => {
item.name = item.className;
item.formatName = item.className;
});
let dataSetTemp = [];
if (current === 1) {
dataSetTemp = filter ? filter(data) : data;
if (hasNoneClass) {
dataSetTemp.unshift({ classId: "1", name: '未选班' });
}
} else {
dataSetTemp = dataSet.concat(filter ? filter(data) : data);
}
setDataSet(dataSetTemp);
setIsAll(!res.result.hasNext);
});
} else {
window.axios.Business(urlTemp, param).then((res: any) => {
const data = res.result.records;
_.map(data, (item: any) => {
item.formatName = item.name;
});
let dataSetTemp = [];
if (current === 1) {
dataSetTemp = filter ? filter(data) : data;
if (hasNoneClass) {
dataSetTemp.unshift({ classId: "1", name: '未选班' });
}
} else {
dataSetTemp = dataSet.concat(filter ? filter(data) : data);
}
setDataSet(dataSetTemp);
setIsAll(!res.result.hasNext);
});
}
// if (url == "public/homework/getTeacherClassPage") {
// window.axios.post(urlTemp, param).then((res: any) => {
// const data = res.result.records;
// _.map(data, (item: any) => {
// item.name = item.className;
// item.formatName = item.className;
// });
// let dataSetTemp = [];
// if (current === 1) {
// dataSetTemp = filter ? filter(data) : data;
// if (hasNoneClass) {
// dataSetTemp.unshift({ classId: "1", name: '未选班' });
// }
// } else {
// dataSetTemp = dataSet.concat(filter ? filter(data) : data);
// }
// setDataSet(dataSetTemp);
// setIsAll(!res.result.hasNext);
// });
// } else {
// window.axios.Business(urlTemp, param).then((res: any) => {
// const data = res.result.records;
// _.map(data, (item: any) => {
// item.formatName = item.name;
// });
// let dataSetTemp = [];
// if (current === 1) {
// dataSetTemp = filter ? filter(data) : data;
// if (hasNoneClass) {
// dataSetTemp.unshift({ classId: "1", name: '未选班' });
// }
// } else {
// dataSetTemp = dataSet.concat(filter ? filter(data) : data);
// }
// setDataSet(dataSetTemp);
// setIsAll(!res.result.hasNext);
// });
// }
}
function searchName() {
......@@ -194,16 +200,17 @@ const ClassSearchSelect = (props: ClassSearchSelectProps) => {
if (!multiple) {
if (needName) {
const items = _.filter(dataSet, (item: any) => {
const items:Array<ItemTypes> = _.filter(dataSet, (item: ItemTypes) => {
return item.classId === classId;
});
onSelect({ classId, formatName: !!items[0] && items[0].name });
const formatName = items[0] ? items[0].name ? items[0].name :"": "";
onSelect && onSelect({ classId, formatName });
return;
}
onSelect({ classId });
onSelect && onSelect({ classId });
return;
}
onSelect(classId);
onSelect && onSelect(classId);
}
return (
......
......@@ -5,11 +5,8 @@
* @Last Modified time: 2020-11-06 14:09:38
*/
import React from 'react';
import PropTypes from 'prop-types';
import { Menu, Dropdown, Icon, Checkbox, Button, Input, Spin, Select, Row, Col } from 'antd';
import { Spin, Select } from 'antd';
import Bus from '@/core/bus';
const Option = Select.Option;
const Search = Input.Search;
class CourseSelect extends React.Component {
......@@ -80,9 +77,6 @@ class CourseSelect extends React.Component {
// 排除一对一
param.status = 'ON';
}
// if (this.props.status) {
// param.status = this.props.status
// }
if (self.props.queryOneToOne) {
param.courseType = 'ONEVONE'
delete param.status;
......@@ -98,7 +92,6 @@ class CourseSelect extends React.Component {
})
window.axios.Business(url, param).then((res) => {
let data = res.result.records;
// this.parseServerData(data);
data.map(function (item, index) {
item.title = item.name;
item.desc = item.name;
......@@ -106,7 +99,6 @@ class CourseSelect extends React.Component {
if (current >1) {
data = this.state.dataSet.concat(data)
}
// res.totalCount = 200
this.setState({
dataSet: data,
totalCount: res.result.total,
......@@ -167,16 +159,14 @@ class CourseSelect extends React.Component {
return (
<div className={classNames("common-select staticSelect", { 'common-select-active': this.state.visible })} style={this.props.style}>
{
!!this.props.label && <div className='label'> {this.props.label}:</div>
!!this.props.label && <div className='label'>{ `${this.props.label}:`}</div>
}
<Select
id={this.props.id}
ref='course'
{...defprops}
showSearch
// style={{ width: '100%' }}
allowClear
// notFoundContent={this.state.fetching ? <Spin size="small" /> : null}
onSearch={(value) => {
const query = this.state.query;
query.courseNameLike = value
......@@ -184,8 +174,8 @@ class CourseSelect extends React.Component {
}}
onBlur={() => {
const query = this.state.query;
query.courseNameLike = null;
this.setState({ query }, this.searchName)
query.courseNameLike = null
this.setState({ query }, this.searchName)
}}
// open
onPopupScroll={(dom) => {
......
import React from 'react';
import PropTypes from 'prop-types';
import React from 'react';
import { DatePicker } from 'antd';
import moment from 'moment';
const { RangePicker } = DatePicker;
......
......@@ -3,12 +3,11 @@
* @Date: 2017-09-01 16:29:44
* @Last Modified by: 吴文洁
* @Last Modified time: 2019-12-09 15:03:40
*/
import React from 'react';
import { Menu, Icon, Checkbox, Button, Input, Spin, Select, Row } from 'antd';
import "./StaticSelect.less";
class StaticSelect extends React.Component{
class StaticSelect extends React.Component {
constructor(props) {
super(props);
this.state = {
......
......@@ -5,13 +5,12 @@
* @Last Modified time: 2020-03-20 10:43:55
*/
import React from 'react';
import { Tooltip, Dropdown, Icon, Checkbox, Button, Input, Spin, Select, Avatar, Row, Col } from 'antd';
import { Tooltip, Input, Spin, Select, Avatar, Row, Col } from 'antd';
import _ from 'underscore';
import "./CommonSelect.less";
import "./TeacherSearchSelect.less";
import _ from "underscore";
const Search = Input.Search;
const baseImg = require('@/common/images/xiaomai-IMG.png')
import classNames from 'classNames'
const baseImg ='https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png'
class TeacherSearchSelect extends React.Component {
......@@ -28,7 +27,7 @@ class TeacherSearchSelect extends React.Component {
status: 'ON',
CustomOrderType: 2,
courseId: props.courseId,
// instId: window.currentUserInstInfo.instId,
instId: window.currentUserInstInfo.instId,
},
dataSet: [],
visible: false,
......@@ -200,7 +199,7 @@ class TeacherSearchSelect extends React.Component {
let data = _.filter(this.state.dataSet, item => item.name);
data = _.uniq(data, item => item.teacherId);
return (
<div className={("common-select staticSelect teacher-search-select", { 'common-select-active': this.state.visible })} style={this.props.style}>
<div className={classNames("common-select staticSelect teacher-search-select", { 'common-select-active': this.state.visible })} style={this.props.style}>
{
!!this.props.label && <div className='label'> {this.props.label}:</div>
}
......
......@@ -10,7 +10,7 @@ import { Button, Icon, Upload, Avatar } from 'antd';
import './Upload.less';
import {CropperModal} from '@/components/';
const baseImg = require('@/common/images/xiaomai-IMG.png');
const baseImg ='https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png'
class UpLoad extends React.Component {
constructor(props) {
super(props);
......
import React from 'react';
import { withRouter } from "react-router-dom";
import { Tabs } from 'antd';
import Breadcrumbs from "@/components/Breadcrumbs";
import CourseData from './CourseData';
import PlaybackData from './PlaybackData';
import './DataList.less';
class DataList extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<div className="page data-list">
<Breadcrumbs
navList="上课数据"
goBack={() => {
console.log("准备返回");
RCHistory.goBack();
}}
/>
<div className="box">
<Tabs defaultActiveKey="courseData" >
<Tabs.TabPane tab="上课记录" key="courseData">
<CourseData></CourseData>
</Tabs.TabPane>
<Tabs.TabPane tab="回放记录" key="playbackData">
<PlaybackData></PlaybackData>
</Tabs.TabPane>
</Tabs>
</div>
</div>
)
}
}
export default withRouter(DataList);
\ No newline at end of file
.data-list {
.pop-table {
width: 300px;
}
.filter-wrap {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 16px;
.select-student {
span {
display: inline-block;
margin-right: 8px;
padding: 6px 10px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
background: #fc9c6b;
border-radius: 4px;
cursor: pointer;
}
}
.filter {
display: flex;
}
}
.handel-btn {
color: #ff7519;
cursor: pointer;
}
.split {
margin: 0 8px;
color: #ff7519;
}
.title {
font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
margin-bottom: 16px;
}
.select-course {
width: 300px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.iconfont {
color: #bfbfbf;
cursor: pointer;
}
}
.bulge {
color: #ff7519;
}
.ant-table-small > .ant-table-content .ant-table-header {
background-color: #fafafa !important;
}
.teacher-course-data {
width: 100%;
height: 90px;
background: #ffffff;
border: 1px solid #e8e8e8;
display: flex;
align-items: center;
margin-bottom: 32px;
.item-block {
width: 33%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
img {
width: 50px;
height: 50px;
margin-right: 16px;
}
.text {
height: 20px;
font-size: 14px;
color: #999999;
line-height: 20px;
}
&.avatar-name-phone {
justify-content: flex-start;
padding-left: 26px;
.name {
height: 22px;
font-size: 16px;
font-weight: 500;
color: #333;
line-height: 22px;
}
.phone {
height: 20px;
font-size: 14px;
color: #666;
line-height: 20px;
margin-top: 4px;
}
}
&.times {
flex-direction: column;
.times-num {
height: 37px;
font-size: 26px;
font-weight: 500;
color: #5289fa;
line-height: 37px;
cursor: pointer;
&.can-click {
cursor: pointer;
}
}
}
&.online-duration {
flex-direction: column;
.duration {
height: 37px;
font-size: 26px;
font-weight: 500;
color: #333333;
line-height: 37px;
}
}
}
}
import React from 'react';
import { withRouter } from "react-router-dom";
import { Table, Button, Modal } from 'antd';
import dealTimeDuration from '../utils/dealTimeDuration';
import { PageControl } from "@/components";
import Bus from '@/core/bus';
import './DataList.less';
const liveTypeMap = {
USER: "学生",
ANCHOR: "老师",
ADMIN: "助教",
};
class PlaybackData extends React.Component {
constructor(props) {
super(props);
this.state = {
playbackData: [],
current: 1,
size: 10,
total: 0
}
}
componentDidMount() {
this.fetchPlaybackList();
}
fetchPlaybackList = (page = 1) => {
const { size } = this.state
const params = {
liveCourseId: getParameterByName("id"),
current: page,
size: size
}
// window.axios
// .Apollo("public/businessLive/queryUserReplayRecordPage", params)
// .then((res) => {
// if (res.result) {
// const { records = [], current, size, total } = res.result;
// this.setState({
// playbackData: records,
// current,
// size,
// total
// });
// }
// });
};
getPlaybackColumns() {
const columns = [
{
title: "观看用户",
dataIndex: "userName",
},
{
title: "手机号",
dataIndex: "phone"
},
{
title: "观看者类型",
dataIndex: "liveRole",
render: (text) => <span>{liveTypeMap[text]}</span>,
},
{
title: "开始观看时间",
dataIndex: "entryTime",
render: (text) => (
<span>{text ? formatDate("YYYY-MM-DD H:i", parseInt(text)) : '-'}</span>
),
},
{
title: "观看时长",
dataIndex: "lookingDuration",
render: (text) => {
return <span>{text ? dealTimeDuration(text) : '-'}</span>;
},
},
];
return columns;
}
// 导出
handleplaybackExport() {
const type = getParameterByName("type");
const url = type === 'large' ? 'public/businessLive/exportLargeClassLiveAsync' : 'public/businessLive/exportClassInteractionLiveSync';
// window.axios.Apollo(url, {
// liveCourseId: getParameterByName("id"),
// exportLiveType: 0
// }).then((res) => {
// Bus.trigger('get_download_count');
// Modal.success({
// title: '导出任务提交成功',
// content: '请前往右上角的“' + window.NewVersion?'任务中心' : '导出中心' + '”进行下载',
// okText: <span id="I_know">我知道了</span>,
// });
// })
}
render() {
const { playbackData, total, current, size} = this.state
return (
<div>
<Button onClick={() => {this.handleplaybackExport()}}>导出</Button>
<Table
size="small"
columns={this.getPlaybackColumns()}
dataSource={playbackData}
pagination={false}
style={{ margin: '16px 0' }}>
</Table>
<PageControl
size="small"
current={current - 1}
pageSize={size}
total={total}
toPage={(page) => {
this.fetchPlaybackList(page + 1);
}}
/>
</div>
)
}
}
export default withRouter(PlaybackData);
\ No newline at end of file
......@@ -75,6 +75,12 @@ class LiveCourseList extends React.Component {
getDownloadVersion() {
}
// 前往上课数据页面
handleLinkToClassData = (item) => {
// TODOLIST 确定后端是否是根据liveCourseId 返回数据
window.RCHistory.push(`/live-course-data?type=large&id=${item.liveCourseId}`)
}
parseColumns = () => {
const menu = (item) => (
......@@ -152,6 +158,24 @@ class LiveCourseList extends React.Component {
},
},
{
title: '上课数据',
width: "9%",
key: "quota",
dataIndex: "quota",
render: (val, item) => {
return (
<span
className="operate-text"
onClick={() => {
this.handleLinkToClassData(item)
}}
>
{`${val}人`}
</span>
);
}
},
{
title: "上课状态",
width: "10%",
key: "courseState",
......
/*
* @Author: 吴文洁
* @Date: 2020-08-07 16:28:41
* @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-11 14:23:09
* @LastEditors: wufan
* @LastEditTime: 2020-12-11 15:29:27
* @Description: 选择学员-筛选组件
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
......@@ -11,6 +11,7 @@ import React from 'react';
import { Row, Col } from 'antd';
import Bus from '@/core/bus';
import _ from 'underscore';
import { SearchBar } from '@/components';
import ClassSearchSelect from '@/modules/common/ClassSearchSelect';
......
/*
* @Author: 吴文洁
* @Date: 2020-08-07 16:28:49
* @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-11 14:23:20
* @LastEditors: wufan
* @LastEditTime: 2020-12-11 17:47:33
* @Description: 选择学员-学员列表组件
* @Copyright: 杭州杰竞科技有限公司 版权所有
*/
import React from 'react';
import { Table, Tooltip, Menu, Dropdown } from 'antd';
import _ from 'underscore';
import Bus from '@/core/bus';
import { PageControl } from '@/components';
import _ from 'underscore';
......
export enum StudentStatus {
'NORMAL' = '在读',
'POTENTIAL' = '潜在',
'HISTORY' = '历史',
'ABANDON' = '废弃'
}
export enum TaskStatus {
'STARTING' = '未开始',
'DONE' = '已完成',
'OVERDUE' = '已逾期',
'CANCELED' = '已取消'
}
export enum StudentStatusForLinkToDetail {
'clue' = 'clue',
'clue_cycle' = 'clue_cycle',
'reading' = 'reading',
'history' = 'history'
}
export enum FollowStatus {
UN_DESIGN = '未分配',
WAIT_CLAIM = '待认领',
WAIT_FOLLOW = '待跟进',
FOLLOWING = '跟进中',
TRADED = '已成交',
INVALID = '已删除'
}
\ No newline at end of file
/*
* @Author: 吴文洁
* @Date: 2019-09-10 18:26:03
* @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-09 11:13:05
* @LastEditors: wufan
* @LastEditTime: 2020-12-11 14:01:06
* @Description:
*/
import React , { useContext, useState}from 'react';
......@@ -18,8 +18,8 @@ import { withRouter } from 'react-router-dom';
import User from '@/common/js/user';
import BaseService from "@/domains/basic-domain/baseService";
import { XMContext } from '@/store/context';
import baseImg from '@/common/images/xiaomai-IMG.png';
import logoImg from '@/common/images/logo.png';
const baseImg ='https://image.xiaomaiketang.com/xm/rJeQaZxtc7.png'
const { confirm } = Modal;
function Header(){
......
......@@ -5,7 +5,7 @@ function Main(){
const [menuType,setMenuType] = useState(1);
return (
<div
className={menuType ? `right-container has-nav}` : `right-container has-nav right-container-vertical}`}
className={menuType ? `right-container has-nav` : `right-container has-nav right-container-vertical`}
id="rightContainer"
>
<MainRoutes/>
......
/*
* @Author: 吴文洁
* @Date: 2020-04-29 10:26:32
* @LastEditors: zhangleyuan
* @LastEditTime: 2020-12-11 14:26:24
* @LastEditors: wufan
* @LastEditTime: 2020-12-11 17:48:07
* @Description: 内容线路由配置
*/
import EmployeesManagePage from '@/modules/store-manege/EmployeesManagePage';
......@@ -12,6 +12,8 @@ import StoreDecorationPage from '@/modules/store-manege/StoreDecorationPage';
import CourseCatalogPage from '@/modules/store-manege/CourseCatalogPage';
import LiveCoursePage from '@/modules/course-manage/LiveCoursePage';
import AddLivePage from '@/modules/course-manage/AddLive'
import DataList from '@/modules/course-manage/DataList/DataList';
import ClassBook from '@/modules/resource-disk';
const mainRoutes = [
......@@ -51,6 +53,11 @@ const mainRoutes = [
name: '创建直播课'
},
{
path: '/live-course-data',
component: DataList,
name: '上课数据'
},
{
path: '/resource-disk',
component:ClassBook,
name: '资料云盘'
......
export const menuList: any = [
// {
// groupName: "课程管理",
// groupCode: "CloudCourse",
// icon: '&#xe831;',
// children: [
// {
// groupName: "直播课",
// groupCode: "CourseLiveClass",
// link: '/CourseLiveClass'
// },
// {
// groupName: "视频课",
// groupCode: "CourseVideoClass",
// link: '/CourseVideoClass'
// }
// ]
// },
{
groupName: "课程管理",
groupCode: "CloudCourse",
icon: '&#xe831;',
children: [
{
groupName: "直播课",
groupCode: "CourseLiveClass",
link: '/live-course'
},
// {
// groupName: "视频课",
// groupCode: "CourseVideoClass",
// link: '/CourseVideoClass'
// }
{
groupName: "直播课-上课数据",
groupCode: "CourseData",
link: '/live-course-data'
},
]
},
{
groupName: "资料云盘",
groupCode: "CloudDisk",
......
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