|
|
import React, {Component} from "react";
|
|
|
import '../../signin/css/signincdi.css';
|
|
|
import {Pagination, Table, Menu, Dropdown,Spin} from 'antd';
|
|
|
import {getImageUrl, sortDirections,formatSeconds} from 'educoder';
|
|
|
import axios from 'axios';
|
|
|
import LoadingSpin from "../../../../common/LoadingSpin";
|
|
|
import NoneDatas from "../../signin/component/NoneDatas";
|
|
|
import moment from 'moment';
|
|
|
|
|
|
|
|
|
//条目
|
|
|
class Videostatisticscomtwo extends Component {
|
|
|
//条目组件
|
|
|
constructor(props) {
|
|
|
super(props);
|
|
|
|
|
|
this.state = {
|
|
|
data: [],
|
|
|
page: 1,
|
|
|
limit: 20,
|
|
|
members_count: 0,
|
|
|
columnsstu: [
|
|
|
{
|
|
|
title: '序号',
|
|
|
dataIndex: 'number',
|
|
|
key: 'number',
|
|
|
align: "center",
|
|
|
className: 'font-14',
|
|
|
width: '50px',
|
|
|
render: (text, record) => (
|
|
|
<div style={{width: '50px'}}>{record.number}</div>
|
|
|
),
|
|
|
},
|
|
|
{
|
|
|
title: '用户',
|
|
|
dataIndex: 'user_name',
|
|
|
key: 'user_name',
|
|
|
align: "center",
|
|
|
className: 'font-14 maxnamewidth100s',
|
|
|
width: '100px',
|
|
|
render: (text, record) => (
|
|
|
<div style={{width: "100px",wordWrap: 'break-word', wordBreak: 'break-word'}} className="maxnamewidth100s">
|
|
|
<script>
|
|
|
{
|
|
|
`
|
|
|
a{
|
|
|
text-decoration:none;
|
|
|
color:#333;
|
|
|
}
|
|
|
a:hover{
|
|
|
text-decoration:none;
|
|
|
color:#333;
|
|
|
}
|
|
|
`
|
|
|
}
|
|
|
</script>
|
|
|
<a className="maxnamewidth100s" style={{
|
|
|
color:"#333333"
|
|
|
}} title={record.user_name}>{record.user_name}</a>
|
|
|
|
|
|
</div>
|
|
|
),
|
|
|
},
|
|
|
{
|
|
|
title: '是否看完',
|
|
|
dataIndex: 'is_finished',
|
|
|
key: 'is_finished',
|
|
|
align: "center",
|
|
|
className: 'font-14 maxnamewidth90s',
|
|
|
width: '90px',
|
|
|
render: (text, record) => (
|
|
|
<div style={{width: '90px'}} className="maxnamewidth90s">{record.is_finished === true ?
|
|
|
<span style={{color: "#333333"}}>是</span> : <span style={{color: "#E02020"}}>否</span>}</div>
|
|
|
),
|
|
|
},
|
|
|
{
|
|
|
title: '观看时长',
|
|
|
dataIndex: 'total_duration',
|
|
|
key: 'total_duration',
|
|
|
align: "center",
|
|
|
className: 'font-14 maxnamewidth100s',
|
|
|
width: '100px',
|
|
|
sorter: true,
|
|
|
sortDirections: sortDirections,
|
|
|
render: (text, record) => (
|
|
|
<div style={{width: '100px'}} className="maxnamewidth100s">
|
|
|
<script>
|
|
|
{
|
|
|
`
|
|
|
a{
|
|
|
text-decoration:none;
|
|
|
color:#333;
|
|
|
}
|
|
|
a:hover{
|
|
|
text-decoration:none;
|
|
|
color:#333;
|
|
|
}
|
|
|
`
|
|
|
}
|
|
|
</script>
|
|
|
<a className="maxnamewidth100s" style={{
|
|
|
color:"#333333"
|
|
|
}} title={record.total_duration}>{record.total_duration}</a></div>
|
|
|
),
|
|
|
},
|
|
|
{
|
|
|
title: '观看次数',
|
|
|
dataIndex: 'feq',
|
|
|
key: 'feq',
|
|
|
align: "center",
|
|
|
className: 'font-14 maxnamewidth100s',
|
|
|
width: '100px',
|
|
|
sorter: true,
|
|
|
sortDirections: sortDirections,
|
|
|
render: (text, record) => (
|
|
|
<div style={{width: '100px'}} className="maxnamewidth100s">
|
|
|
<script>
|
|
|
{
|
|
|
`
|
|
|
a{
|
|
|
text-decoration:none;
|
|
|
color:#333;
|
|
|
}
|
|
|
a:hover{
|
|
|
text-decoration:none;
|
|
|
color:#333;
|
|
|
}
|
|
|
`
|
|
|
}
|
|
|
</script>
|
|
|
<a className="maxnamewidth100s" style={{
|
|
|
color:"#333333"
|
|
|
}} title={record.feq}>{record.feq}</a>
|
|
|
</div>
|
|
|
),
|
|
|
},
|
|
|
{
|
|
|
title: '最早观看时间',
|
|
|
dataIndex: 'start_at',
|
|
|
key: 'start_at',
|
|
|
align: "center",
|
|
|
className: 'font-14 ',
|
|
|
render: (text, record) => (
|
|
|
<div>
|
|
|
<script>
|
|
|
{
|
|
|
`
|
|
|
a{
|
|
|
text-decoration:none;
|
|
|
color:#333;
|
|
|
}
|
|
|
a:hover{
|
|
|
text-decoration:none;
|
|
|
color:#333;
|
|
|
}
|
|
|
`
|
|
|
}
|
|
|
</script>
|
|
|
{
|
|
|
record.start_at?
|
|
|
<a style={{
|
|
|
color:"#333333"
|
|
|
}} title={moment(record.start_at).format('YYYY-MM-DD HH:mm:ss')}>{moment(record.start_at).format('YYYY-MM-DD HH:mm:ss')}</a>
|
|
|
:
|
|
|
<span style={{color:"#333333"}}>--</span>
|
|
|
}
|
|
|
</div>
|
|
|
),
|
|
|
},
|
|
|
{
|
|
|
title: '最后观看时间',
|
|
|
dataIndex: 'end_at',
|
|
|
key: 'end_at',
|
|
|
align: "center",
|
|
|
className: 'font-14 ',
|
|
|
render: (text, record) => (
|
|
|
<div>
|
|
|
<script>
|
|
|
{
|
|
|
`
|
|
|
a{
|
|
|
text-decoration:none;
|
|
|
color:#333;
|
|
|
}
|
|
|
a:hover{
|
|
|
text-decoration:none;
|
|
|
color:#333;
|
|
|
}
|
|
|
`
|
|
|
}
|
|
|
</script>
|
|
|
{
|
|
|
record.end_at?
|
|
|
<a style={{
|
|
|
color:"#333333"
|
|
|
}} title={moment(record.end_at).format('YYYY-MM-DD HH:mm:ss')}>{moment(record.end_at).format('YYYY-MM-DD HH:mm:ss')}</a>
|
|
|
:
|
|
|
<span style={{color:"#333333"}}>--</span>
|
|
|
|
|
|
}
|
|
|
|
|
|
</div>
|
|
|
),
|
|
|
}
|
|
|
],
|
|
|
loading: false,
|
|
|
order: undefined,
|
|
|
course_groups: [],
|
|
|
fbbool: false,
|
|
|
groupsid: null,
|
|
|
none_group_member_count:0,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
componentDidMount() {
|
|
|
this.setState({
|
|
|
order: undefined
|
|
|
})
|
|
|
if (this.props.isAdmin()) {
|
|
|
//老师
|
|
|
const CourseId = this.props.match.params.coursesId;
|
|
|
|
|
|
var data = {
|
|
|
id: CourseId,
|
|
|
page: this.state.page,
|
|
|
}
|
|
|
this.getdatas(data);
|
|
|
|
|
|
} else {
|
|
|
//学生
|
|
|
var data = {
|
|
|
page: this.state.page,
|
|
|
}
|
|
|
this.getdatas(data);
|
|
|
}
|
|
|
this.fenbans();
|
|
|
}
|
|
|
|
|
|
componentDidUpdate = (prevProps) => {
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
//分班
|
|
|
fenbans = () => {
|
|
|
const CourseId = this.props.match.params.coursesId;
|
|
|
let url = `/courses/${CourseId}/course_groups.json`;
|
|
|
axios.get(url).then((response) => {
|
|
|
if (response) {
|
|
|
// console.log("分班");
|
|
|
// console.log("response");
|
|
|
// console.log(response);
|
|
|
this.setState({
|
|
|
course_groups: response.data.course_groups,
|
|
|
current_group_id: response.data.current_group_id,
|
|
|
none_group_member_count: response.data.none_group_member_count,
|
|
|
group_count: response.data.group_count,
|
|
|
})
|
|
|
}
|
|
|
|
|
|
}).catch((error) => {
|
|
|
|
|
|
});
|
|
|
}
|
|
|
|
|
|
//学生
|
|
|
getdatas = (data) => {
|
|
|
this.setState({
|
|
|
loading: true
|
|
|
})
|
|
|
const CourseId = this.props.match.params.coursesId;
|
|
|
let url = "";
|
|
|
if (this.props.isAdmin()) {
|
|
|
url = `/course_videos/${this.props.tisid}/watch_histories.json`;
|
|
|
} else {
|
|
|
url = `/courses/${CourseId}/own_watch_histories.json`;
|
|
|
}
|
|
|
axios.get(url, {params: data}).then((response) => {
|
|
|
if (response) {
|
|
|
if (response.data) {
|
|
|
if (response.data.data.length > 0) {
|
|
|
let datalists = [];
|
|
|
for (var i = 0; i < response.data.data.length; i++) {
|
|
|
datalists.push({
|
|
|
number: (parseInt(this.state.page) - 1) * parseInt(this.state.limit) + (i + 1),
|
|
|
user_name: response.data.data[i].user_name,
|
|
|
is_finished: response.data.data[i].is_finished,
|
|
|
total_duration: response.data.data[i].total_duration?formatSeconds(response.data.data[i].total_duration):0,
|
|
|
feq: response.data.data[i].feq,
|
|
|
start_at: response.data.data[i].start_at?response.data.data[i].start_at:null,
|
|
|
end_at: response.data.data[i].end_at?response.data.data[i].end_at:null,
|
|
|
title: response.data.data[i].title,
|
|
|
})
|
|
|
}
|
|
|
|
|
|
this.setState({
|
|
|
data: datalists,
|
|
|
members_count: response.data.count,
|
|
|
})
|
|
|
} else {
|
|
|
this.setState({
|
|
|
data: [],
|
|
|
members_count: response.data.count,
|
|
|
})
|
|
|
}
|
|
|
} else {
|
|
|
this.setState({
|
|
|
data: [],
|
|
|
members_count: response.data.count,
|
|
|
})
|
|
|
}
|
|
|
|
|
|
|
|
|
}
|
|
|
this.setState({
|
|
|
loading: false
|
|
|
})
|
|
|
}).catch((error) => {
|
|
|
this.setState({
|
|
|
loading: false
|
|
|
})
|
|
|
});
|
|
|
}
|
|
|
|
|
|
|
|
|
paginationonChange = (pageNumber) => {
|
|
|
this.setState({
|
|
|
page: pageNumber,
|
|
|
})
|
|
|
let data = {}
|
|
|
if (this.props.isAdmin()) {
|
|
|
//老师
|
|
|
const CourseId = this.props.match.params.coursesId;
|
|
|
data = {
|
|
|
id: CourseId,
|
|
|
page: pageNumber,
|
|
|
group_id: this.state.groupsid,
|
|
|
order: this.state.order,
|
|
|
}
|
|
|
} else {
|
|
|
//学生
|
|
|
data = {
|
|
|
page: pageNumber,
|
|
|
order: this.state.order,
|
|
|
}
|
|
|
}
|
|
|
this.getdatas(data);
|
|
|
}
|
|
|
fenbanone = () => {
|
|
|
if (this.state.fbbool === false) {
|
|
|
this.setState({
|
|
|
fbbool: true
|
|
|
})
|
|
|
} else {
|
|
|
this.setState({
|
|
|
fbbool: false
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
setcourse_groups = (id) => {
|
|
|
this.setState({
|
|
|
groupsid: id
|
|
|
})
|
|
|
//老师
|
|
|
const CourseId = this.props.match.params.coursesId;
|
|
|
|
|
|
var data = {};
|
|
|
if (id) {
|
|
|
data = {
|
|
|
id: CourseId,
|
|
|
page: this.state.page,
|
|
|
group_id: id
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
try {
|
|
|
if(id!==null&&id===0){
|
|
|
data = {
|
|
|
id: CourseId,
|
|
|
page: this.state.page,
|
|
|
group_id: id
|
|
|
}
|
|
|
}else{
|
|
|
data = {
|
|
|
id: CourseId,
|
|
|
page: this.state.page
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}catch (e) {
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
this.getdatas(data);
|
|
|
}
|
|
|
|
|
|
//实训作业tbale 列表塞选数据
|
|
|
table1handleChange = (pagination, filters, sorter) => {
|
|
|
if (JSON.stringify(sorter) === "{}") {
|
|
|
//没有选择
|
|
|
} else {
|
|
|
try {
|
|
|
//学生学号排序
|
|
|
if (sorter.columnKey === "total_duration" || sorter.columnKey === "feq") {
|
|
|
let mysorder = "";
|
|
|
if (sorter.order === "ascend") {
|
|
|
if (sorter.columnKey === "total_duration") {
|
|
|
mysorder = "total_duration-asc";
|
|
|
} else {
|
|
|
mysorder = "freq-asc";
|
|
|
|
|
|
}
|
|
|
//升序
|
|
|
let data = {}
|
|
|
if (this.props.isAdmin()) {
|
|
|
//老师
|
|
|
const CourseId = this.props.match.params.coursesId;
|
|
|
if (this.state.groupsid) {
|
|
|
data = {
|
|
|
id: CourseId,
|
|
|
page: this.state.page,
|
|
|
group_id: this.state.groupsid,
|
|
|
order: mysorder,
|
|
|
}
|
|
|
} else {
|
|
|
data = {
|
|
|
id: CourseId,
|
|
|
page: this.state.page,
|
|
|
order: mysorder,
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
//学生
|
|
|
data = {
|
|
|
page: this.state.page,
|
|
|
order: mysorder,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
this.getdatas(data);
|
|
|
this.setState({
|
|
|
order: mysorder,
|
|
|
})
|
|
|
} else if (sorter.order === "descend") {
|
|
|
if (sorter.columnKey === "total_duration") {
|
|
|
mysorder = "total_duration-desc";
|
|
|
|
|
|
} else {
|
|
|
mysorder = "freq-desc";
|
|
|
|
|
|
}
|
|
|
//降序
|
|
|
let data = {}
|
|
|
if (this.props.isAdmin()) {
|
|
|
//老师
|
|
|
const CourseId = this.props.match.params.coursesId;
|
|
|
if (this.state.groupsid) {
|
|
|
data = {
|
|
|
id: CourseId,
|
|
|
page: this.state.page,
|
|
|
group_id: this.state.groupsid,
|
|
|
order: mysorder,
|
|
|
}
|
|
|
} else {
|
|
|
data = {
|
|
|
id: CourseId,
|
|
|
page: this.state.page,
|
|
|
order: mysorder,
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
//学生
|
|
|
data = {
|
|
|
page: this.state.page,
|
|
|
order: mysorder,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
this.getdatas(data);
|
|
|
this.setState({
|
|
|
order: mysorder,
|
|
|
})
|
|
|
|
|
|
|
|
|
}
|
|
|
}
|
|
|
} catch (e) {
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
render() {
|
|
|
let {loading, data, page, limit, members_count, columnsstu, fbbool, course_groups} = this.state;
|
|
|
const isAdmin = this.props&& this.props.isAdmin();
|
|
|
|
|
|
const menu = (
|
|
|
<Menu>
|
|
|
<Menu.Item>
|
|
|
<a onClick={() => this.setcourse_groups(null)}>
|
|
|
<p className="maxnamewidth200yss">全部</p>
|
|
|
</a>
|
|
|
</Menu.Item>
|
|
|
{
|
|
|
course_groups && course_groups.length > 0 ?
|
|
|
(
|
|
|
course_groups.map((item, key) => {
|
|
|
return (
|
|
|
<Menu.Item>
|
|
|
<a onClick={() => this.setcourse_groups(item.id)} key={key}>
|
|
|
<p className="maxnamewidth200yss">{item.name}</p>
|
|
|
</a>
|
|
|
</Menu.Item>
|
|
|
)
|
|
|
})
|
|
|
)
|
|
|
:
|
|
|
""
|
|
|
}
|
|
|
{
|
|
|
this.state.none_group_member_count&&this.state.none_group_member_count>0?
|
|
|
<Menu.Item>
|
|
|
<a onClick={() => this.setcourse_groups(0)}>
|
|
|
<p className="maxnamewidth200yss">未分班</p>
|
|
|
</a>
|
|
|
</Menu.Item>
|
|
|
:
|
|
|
""
|
|
|
}
|
|
|
</Menu>
|
|
|
);
|
|
|
|
|
|
let mytitle="";
|
|
|
if(isAdmin){
|
|
|
mytitle=this.props&&this.props.mytitle;
|
|
|
|
|
|
}else{
|
|
|
if(this.state.data){
|
|
|
if(this.state.data.length>0){
|
|
|
try {
|
|
|
if(this.state.data[0].title){
|
|
|
mytitle=this.state.data[0].title;
|
|
|
}
|
|
|
}catch (e) {
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return (
|
|
|
<React.Fragment>
|
|
|
<div className="ws100s">
|
|
|
<script>
|
|
|
{
|
|
|
`
|
|
|
a{
|
|
|
text-decoration:none;
|
|
|
color:#333;
|
|
|
}
|
|
|
a:hover{
|
|
|
text-decoration:none;//鼠标放上面不显示下划线
|
|
|
color:#333;
|
|
|
}
|
|
|
`
|
|
|
}
|
|
|
</script>
|
|
|
<div className="ws100s teacherentrydivss edu-back-white ">
|
|
|
<div className="ws100s sortinxdirection">
|
|
|
<p className="sortinxdirection h40s" onClick={() => this.props.tisticsbools(false, null)} >
|
|
|
<i className="iconfont icon-zuojiantou1 font-14 posiivsiconmyss mr5 colorbluesigin xiaoshou h36s" style={{color:'#BBBBBB'}} ></i>
|
|
|
</p>
|
|
|
<div className="ws50s sptits font-18">
|
|
|
<div className="ml10">{mytitle}</div>
|
|
|
</div>
|
|
|
<div className="ws50s sptitss xaxisreverseorder font-14" style={{
|
|
|
color: "#5091FF",
|
|
|
lineHeight: "42px",
|
|
|
}}>
|
|
|
{/*{*/}
|
|
|
{/* isAdmin === true ?*/}
|
|
|
{/* <div className="xiaoshou ml32" onClick={() => this.props.tisticsbools(false, null)}>*/}
|
|
|
{/* <span className="mr5 xiaoshou">视频统计总览</span><i className="iconfont icon-fanhui font-13 xiaoshou"></i>*/}
|
|
|
{/* </div>*/}
|
|
|
{/* :""*/}
|
|
|
{/*}*/}
|
|
|
|
|
|
{
|
|
|
isAdmin === true ?
|
|
|
<div className="xiaoshou" onClick={() => this.fenbanone()}>
|
|
|
<Dropdown getPopupContainer={trigger => trigger.parentNode} overlay={menu}
|
|
|
placement="bottomLeft">
|
|
|
<span>
|
|
|
<span className="mr5 xiaoshou">分班</span>
|
|
|
{
|
|
|
fbbool === true ?
|
|
|
<i className="iconfont icon-sanjiaoxing-up font-13 xiaoshou"></i>
|
|
|
:
|
|
|
<i className="iconfont icon-sanjiaoxing-down font-13 xiaoshou"></i>
|
|
|
}
|
|
|
</span>
|
|
|
</Dropdown>
|
|
|
</div>
|
|
|
:
|
|
|
""
|
|
|
}
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
<style>
|
|
|
{
|
|
|
`
|
|
|
.ysltableo .ant-table-thead > tr > th, .ant-table-tbody > tr > td {
|
|
|
padding: 10px 5px;
|
|
|
}
|
|
|
`
|
|
|
}
|
|
|
</style>
|
|
|
|
|
|
<div className="ws100s ysltableo mt10" style={{ minHeight: "400px"}}>
|
|
|
{
|
|
|
data.length === 0 ?
|
|
|
<div style={{
|
|
|
minHeight: "400px",
|
|
|
}} className="ws100s">
|
|
|
<NoneDatas></NoneDatas>
|
|
|
</div>
|
|
|
:
|
|
|
<Spin spinning={loading}>
|
|
|
<Table
|
|
|
columns={columnsstu}
|
|
|
dataSource={data}
|
|
|
pagination={false}
|
|
|
onChange={this.table1handleChange}
|
|
|
/>
|
|
|
</Spin>
|
|
|
}
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div className="mb30 clearfix educontent mt40 intermediatecenter">
|
|
|
{
|
|
|
data && data.length > 0 ?
|
|
|
<Pagination showQuickJumper current={this.state.page} onChange={this.paginationonChange}
|
|
|
pageSize={this.state.limit}
|
|
|
total={this.state.members_count}></Pagination>
|
|
|
: ""
|
|
|
}
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
</React.Fragment>
|
|
|
)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
export default Videostatisticscomtwo;
|