|
|
import React, { Component } from 'react';
|
|
|
import {getImageUrl,markdownToHTML} from 'educoder';
|
|
|
import DetailTop from './DetailTop.js';
|
|
|
import DetailCards from './DetailCards.js'
|
|
|
import AddCollaborators from "./addCollaborators.js";
|
|
|
import {Icon,Tooltip} from 'antd';
|
|
|
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
|
|
|
import { DragDropContext , Draggable, Droppable} from 'react-beautiful-dnd';
|
|
|
import '../../paths/ShixunPaths.css';
|
|
|
import "antd/dist/antd.css";
|
|
|
import Modals from '../../modals/Modals';
|
|
|
import axios from 'axios';
|
|
|
import TPMRightSection from "../../tpm/component/TPMRightSection";
|
|
|
import styled from "styled-components";
|
|
|
|
|
|
const getItemStyle = (isDragging, draggableStyle) => ({
|
|
|
// change background colour if dragging
|
|
|
background: isDragging ? '#dceeff' : '',
|
|
|
// styles we need to apply on draggables
|
|
|
...draggableStyle,
|
|
|
});
|
|
|
const getItems = count =>
|
|
|
Array.from({ length: count }, (v, k) => k).map(k => ({
|
|
|
id: `item-${k}`,
|
|
|
content: `item ${k}`
|
|
|
}));
|
|
|
|
|
|
// a little function to help us with reordering the result
|
|
|
const reorder = (list, startIndex, endIndex) => {
|
|
|
const result = Array.from(list);
|
|
|
const [removed] = result.splice(startIndex, 1);
|
|
|
result.splice(endIndex, 0, removed);
|
|
|
|
|
|
return result;
|
|
|
};
|
|
|
|
|
|
const List = styled.div`
|
|
|
background: lightgrey;
|
|
|
padding: 10px;
|
|
|
`;
|
|
|
|
|
|
const Item = styled.div`
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
padding: 10px;
|
|
|
margin-bottom: 10px;
|
|
|
border: 1px solid grey;
|
|
|
background: white;
|
|
|
&:hover {
|
|
|
background: lightgrey;
|
|
|
}
|
|
|
`;
|
|
|
|
|
|
const DragHandle = styled.div`
|
|
|
width: 15px;
|
|
|
height: 15px;
|
|
|
margin-right: 8px;
|
|
|
background: grey;
|
|
|
visibility: hidden;
|
|
|
&:hover {
|
|
|
background: black;
|
|
|
}
|
|
|
${Item}:hover & {
|
|
|
visibility: visible;
|
|
|
}
|
|
|
`;
|
|
|
const $ =window.$
|
|
|
class PathDetailIndex extends Component{
|
|
|
constructor(props){
|
|
|
super(props)
|
|
|
this.state={
|
|
|
detailInfoList:undefined,
|
|
|
clickdetailInfoListtype:false,
|
|
|
Modalstype:false,
|
|
|
Modalstopval:undefined,
|
|
|
Modalsbottomval:undefined,
|
|
|
cardsModalcancel:this.cardsModalcancel,
|
|
|
cardsModalsave:this.cardsModalsave,
|
|
|
user_id:undefined,
|
|
|
loadtype:false,
|
|
|
items: getItems(10)
|
|
|
}
|
|
|
this.onDragEnd = this.onDragEnd.bind(this);
|
|
|
|
|
|
}
|
|
|
onDragEnd(result) {
|
|
|
// dropped outside the list
|
|
|
if (!result.destination) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
|
|
|
}catch (e) {
|
|
|
|
|
|
}
|
|
|
const items = reorder(
|
|
|
this.state.detailInfoList.members,
|
|
|
result.source.index,
|
|
|
result.destination.index
|
|
|
);
|
|
|
this.state.detailInfoList.members=items;
|
|
|
this.setState({
|
|
|
detailInfoList:this.state.detailInfoList,
|
|
|
items
|
|
|
});
|
|
|
console.log(this.state.detailInfoList.members)
|
|
|
console.log("items 数组数组数组数组")
|
|
|
console.log(items)
|
|
|
}
|
|
|
cardsModalcancel=()=>{
|
|
|
this.setState({
|
|
|
Modalstype:false,
|
|
|
})
|
|
|
window.history.go(-1)
|
|
|
}
|
|
|
|
|
|
cardsModalsave=()=>{
|
|
|
this.setState({
|
|
|
Modalstype:false,
|
|
|
})
|
|
|
window.history.go(-1)
|
|
|
}
|
|
|
// 加载markdown
|
|
|
updatamakedown=(id)=>{
|
|
|
setTimeout(()=>{
|
|
|
var shixunDescr = window.editormd.markdownToHTML(id, {
|
|
|
htmlDecode: "style,script,iframe",
|
|
|
taskList: true,
|
|
|
tex: true,
|
|
|
flowChart: true,
|
|
|
sequenceDiagram: true
|
|
|
});
|
|
|
$("#"+id+" p:first").addClass("ReactMarkdown");
|
|
|
}, 200)
|
|
|
}
|
|
|
|
|
|
componentDidMount(){
|
|
|
let pathid=this.props.match.params.pathId;
|
|
|
let url="/paths/"+pathid+".json";
|
|
|
axios.get(url).then((result)=>{
|
|
|
if (result.data.status == 407 || result.data.status == 401) {
|
|
|
return;
|
|
|
}
|
|
|
if(result.data.allow_visit===true){
|
|
|
this.setState({
|
|
|
detailInfoList:result.data,
|
|
|
items: getItems(result.data.members.length),
|
|
|
})
|
|
|
}else{
|
|
|
window.location.href = "/403";
|
|
|
// this.setState({
|
|
|
// Modalstype:true,
|
|
|
// Modalstopval:'你没有权限访问,请联系对应课程管理人员开通',
|
|
|
// })
|
|
|
}
|
|
|
|
|
|
}).catch((error)=>{
|
|
|
console.log(error);
|
|
|
})
|
|
|
}
|
|
|
|
|
|
updatadetailInfoList=()=>{
|
|
|
let pathid=this.props.match.params.pathId;
|
|
|
let url="/paths/"+pathid+".json";
|
|
|
axios.get(url).then((result)=>{
|
|
|
// TODO 403 让后台返回status 403 比较好
|
|
|
if (result.data.status == 407 || result.data.status == 401) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if(result.data.allow_visit===true){
|
|
|
this.setState({
|
|
|
detailInfoList:result.data,
|
|
|
items: getItems(result.data.members.length),
|
|
|
user_id:undefined,
|
|
|
})
|
|
|
}else{
|
|
|
window.location.href = "/403";
|
|
|
// this.setState({
|
|
|
// Modalstype:true,
|
|
|
// Modalstopval:'你没有权限访问,请联系对应课程管理人员开通',
|
|
|
// })
|
|
|
}
|
|
|
}).catch((error)=>{
|
|
|
console.log(error);
|
|
|
})
|
|
|
}
|
|
|
clickNewsubscript=(val)=>{
|
|
|
if(val===0){
|
|
|
this.setState({
|
|
|
clickdetailInfoListtype:true
|
|
|
})
|
|
|
}else{
|
|
|
this.setState({
|
|
|
clickdetailInfoListtype:false
|
|
|
})
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
timeStamp=(value)=>{
|
|
|
var secondTime = parseInt(value);// 秒
|
|
|
var minuteTime = 0;// 分
|
|
|
var hourTime = 0;// 小时
|
|
|
if(secondTime > 60) {//如果秒数大于60,将秒数转换成整数
|
|
|
//获取分钟,除以60取整数,得到整数分钟
|
|
|
minuteTime = parseInt(secondTime / 60);
|
|
|
//获取秒数,秒数取佘,得到整数秒数
|
|
|
secondTime = parseInt(secondTime % 60);
|
|
|
//如果分钟大于60,将分钟转换成小时
|
|
|
if(minuteTime > 60) {
|
|
|
//获取小时,获取分钟除以60,得到整数小时
|
|
|
hourTime = parseInt(minuteTime / 60);
|
|
|
//获取小时后取佘的分,获取分钟除以60取佘的分
|
|
|
minuteTime = parseInt(minuteTime % 60);
|
|
|
}
|
|
|
}
|
|
|
var result = "" + parseInt(secondTime) + "秒";
|
|
|
|
|
|
if(minuteTime > 0) {
|
|
|
result = "" + parseInt(minuteTime) + "分" + result;
|
|
|
}
|
|
|
if(hourTime > 0) {
|
|
|
result = "" + parseInt(hourTime) + "小时" + result;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
|
|
|
shanchuallow=(id)=>{
|
|
|
this.setState({
|
|
|
user_id:id,
|
|
|
Modalstype:true,
|
|
|
Modalstopval:"你确定要删除该成员吗?",
|
|
|
cardsModalsave:this.delectshanchuallow,
|
|
|
loadtype:false
|
|
|
})
|
|
|
}
|
|
|
|
|
|
delectshanchuallow=()=>{
|
|
|
let{user_id}=this.state;
|
|
|
let pathid=this.props.match.params.pathId;
|
|
|
let url="/paths/"+pathid+"/delete_member.json";
|
|
|
let param={user_id:user_id};
|
|
|
axios.delete(url,{data:param}).then((response) => {
|
|
|
if(response.data.status===1){
|
|
|
this.setState({
|
|
|
Modalstype:true,
|
|
|
Modalstopval:response.data.message,
|
|
|
loadtype:true,
|
|
|
cardsModalsave:this.cardsModalsave,
|
|
|
})
|
|
|
this.updatadetailInfoList();
|
|
|
}
|
|
|
}).catch((error) => {
|
|
|
console.log(error)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
//上移
|
|
|
moveup=(data)=>{
|
|
|
// console.log(data);
|
|
|
let pathid=this.props.match.params.pathId;
|
|
|
let url=`/paths/${pathid}/up_member_position.json`;
|
|
|
axios.post(url,{
|
|
|
user_id:data.id
|
|
|
}).then((response) => {
|
|
|
if(response.status === 200){
|
|
|
console.log("上移");
|
|
|
// console.log(this.state.detailInfoList.members);
|
|
|
// console.log(response);
|
|
|
this.state.detailInfoList.members=response.data.members;
|
|
|
this.setState({
|
|
|
detailInfoList:this.state.detailInfoList,
|
|
|
});
|
|
|
// console.log(this.state.detailInfoList.members);
|
|
|
|
|
|
}
|
|
|
|
|
|
}).catch((error) => {
|
|
|
console.log(error)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
//下移
|
|
|
movedown =(data) => {
|
|
|
// console.log(data);
|
|
|
let pathid=this.props.match.params.pathId;
|
|
|
let url=`/paths/${pathid}/down_member_position.json`;
|
|
|
axios.post(url,{
|
|
|
user_id:data.id
|
|
|
}).then((response) => {
|
|
|
if( response.status === 200){
|
|
|
console.log("下移");
|
|
|
// console.log(this.state.detailInfoList.members);
|
|
|
// console.log(response);
|
|
|
this.state.detailInfoList.members=response.data.members;
|
|
|
this.setState({
|
|
|
detailInfoList:this.state.detailInfoList,
|
|
|
});
|
|
|
// console.log(this.state.detailInfoList.members);
|
|
|
}
|
|
|
|
|
|
}).catch((error) => {
|
|
|
console.log(error)
|
|
|
})
|
|
|
}
|
|
|
render(){
|
|
|
|
|
|
this.updatamakedown("shixuns_propaedeutics");
|
|
|
this.updatamakedown("subject_learning_notes");
|
|
|
let {detailInfoList,
|
|
|
clickdetailInfoListtype,
|
|
|
Modalstype,
|
|
|
Modalstopval,
|
|
|
Modalsbottomval,
|
|
|
cardsModalcancel,
|
|
|
cardsModalsave,
|
|
|
loadtype
|
|
|
} = this.state
|
|
|
|
|
|
|
|
|
return(
|
|
|
<div className="newContainer">
|
|
|
<Modals
|
|
|
modalsType={Modalstype}
|
|
|
modalsTopval={Modalstopval}
|
|
|
modalsBottomval={Modalsbottomval}
|
|
|
modalCancel={cardsModalcancel}
|
|
|
modalSave={cardsModalsave}
|
|
|
loadtype={loadtype}
|
|
|
>
|
|
|
</Modals>
|
|
|
<div className="newMain clearfix">
|
|
|
<DetailTop {...this.state} {...this.props}></DetailTop>
|
|
|
<div className="educontent clearfix mb80">
|
|
|
<div className="with65 fl">
|
|
|
<div className="produce-content mb10">
|
|
|
<p className="clearfix mb20">
|
|
|
<span className="fl font-18 font-bd">简介</span>
|
|
|
{detailInfoList===undefined?"":detailInfoList.allow_statistics===true?
|
|
|
<Link className="fr" to={"/paths/"+this.props.match.params.pathId+"/edit"}>
|
|
|
<i className="iconfont icon-bianjidaibeijing font-20 color-green"></i>
|
|
|
</Link>
|
|
|
:""
|
|
|
}
|
|
|
</p>
|
|
|
<div className="color-grey-6 clearfix">
|
|
|
<div id="shixuns_propaedeutics" className="new_li fl" style={{"padding":" 0px","textAlign": "justify;"}}>
|
|
|
{detailInfoList === undefined ? "" :detailInfoList.description===null?"":
|
|
|
<div className={"markdown-body"} dangerouslySetInnerHTML={{__html: markdownToHTML(detailInfoList.description).replace(/▁/g,"▁▁▁")}}></div>
|
|
|
}
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<DetailCards
|
|
|
{...this.props}
|
|
|
{...this.state}
|
|
|
updatadetailInfoLists={this.updatadetailInfoList}
|
|
|
></DetailCards>
|
|
|
</div>
|
|
|
<div className="with35 fr pl20">
|
|
|
<div className="edu-back-white mustlearn mb10">
|
|
|
<p className="clearfix mb30">
|
|
|
<span className="font-16">课程须知</span>
|
|
|
{detailInfoList===undefined?"":detailInfoList.allow_statistics===true?
|
|
|
<Link to={"/paths/"+this.props.match.params.pathId+"/edit"} className="fr mtf5">
|
|
|
<i className="iconfont icon-bianjidaibeijing font-20 color-green" data-tip-down="编辑"></i>
|
|
|
</Link>
|
|
|
:""
|
|
|
}
|
|
|
</p>
|
|
|
<div id="subject_learning_notes" className="color-grey-6 new_li markdown-body editormd-html-preview justify">
|
|
|
{detailInfoList === undefined ? "" :detailInfoList.learning_notes===null?"":
|
|
|
<textarea>{detailInfoList.learning_notes}</textarea>
|
|
|
}
|
|
|
</div>
|
|
|
</div>
|
|
|
{detailInfoList === undefined ? "" : detailInfoList.tags === null ? "":
|
|
|
<div className="edu-back-white padding40-20 mb10 relative">
|
|
|
<p className="font-16 mb20">技能标签 <span className="color-grey-c">{detailInfoList.tags.length}</span></p>
|
|
|
|
|
|
<div className={clickdetailInfoListtype===false?"newedbox newedboxheight":"newedbox newminheight"}>
|
|
|
<div className="clearfix" id="boxheight">
|
|
|
{
|
|
|
detailInfoList.tags && detailInfoList.tags.map((item,key)=>{
|
|
|
return(
|
|
|
<span value={key} className = {item.status == true ? "edu-filter-btn29BD8B fl" : "newedu-filter-btn fl"}>{item.tag_name}</span>
|
|
|
)
|
|
|
})
|
|
|
}
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div className={detailInfoList.tags.length>15&&clickdetailInfoListtype===false?"newsubscript mb9 color-grey-9 fr":"newsubscript mb9 color-grey-9 none"}
|
|
|
data-tip-down="显示全部"
|
|
|
onClick={()=>this.clickNewsubscript(0)}
|
|
|
><span className="mr8">...</span><Icon type="caret-down" />
|
|
|
</div>
|
|
|
|
|
|
<div className={clickdetailInfoListtype===false?"newsubscript mb9 color-grey-9 none":"newsubscript mb9 color-grey-9 fr"}
|
|
|
data-tip-down="收起"
|
|
|
onClick={()=>this.clickNewsubscript(1)}><Icon type="caret-up" />
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
}
|
|
|
{
|
|
|
detailInfoList === undefined ? "" : detailInfoList.progress === null ? "" :
|
|
|
<div className="edu-back-white myProgress padding40-20 mb10">
|
|
|
<p className="mb20">
|
|
|
<span className="font-16 mr10">我的进展</span>
|
|
|
<Tooltip placement="bottom" title="获得经验值/总经验值">
|
|
|
<span className="color-green" >{detailInfoList.progress.my_score} / {detailInfoList.progress.all_score}</span>
|
|
|
</Tooltip>
|
|
|
</p>
|
|
|
<p className="clearfix mb10">
|
|
|
<span className="fl color-green">已学 {detailInfoList.progress.learned}%</span>
|
|
|
<span className="fr color-grey-9" id="time-consuming">学习耗时{this.timeStamp(detailInfoList.progress.time)} </span>
|
|
|
</p>
|
|
|
<div className="myProgressNav"><div className="myProgressGreen" style={{"width":`${detailInfoList.progress.learned+"%"}`}}></div></div>
|
|
|
</div>
|
|
|
}
|
|
|
|
|
|
{
|
|
|
detailInfoList ===undefined ?"":detailInfoList.members === null ?"":
|
|
|
<div className="teacherTeam edu-back-white clearfix" id="subject_members">
|
|
|
<p className="font-16 clearfix">教学团队</p>
|
|
|
|
|
|
{ detailInfoList===undefined?
|
|
|
detailInfoList.members && detailInfoList.members.map((item,key)=>{
|
|
|
return(
|
|
|
<div className="teacherTeamItem clearfix df" key={key}>
|
|
|
<a href={item.user_url} target="_blank" className="fl">
|
|
|
<img alt="头像" className="radius" height="80" src={getImageUrl(`${"images/"+item.image_url}`)} width="80"/>
|
|
|
</a>
|
|
|
|
|
|
<div className="fl ml15 flex1">
|
|
|
<p className="mb10 mt5">{item.name}
|
|
|
{/*{*/}
|
|
|
{/* detailInfoList===undefined?"":detailInfoList.allow_add_member===true?*/}
|
|
|
{/* <a className="fr" onClick={()=>this.shanchuallow(item.id)}><i className="iconfont icon-shanchu color-grey-c font-14 font-n"></i></a>:""*/}
|
|
|
{/*}*/}
|
|
|
</p>
|
|
|
<div className="clearfix">
|
|
|
<p className="color-grey-9 font-12 fl"><span className="mr10">{item.school}</span><span>{item.identity}</span></p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
)
|
|
|
})
|
|
|
:detailInfoList.allow_add_member===true?
|
|
|
detailInfoList.members && detailInfoList.members.map((item,key)=>{
|
|
|
return(
|
|
|
<div className="teacherTeamItem clearfix df" key={key}>
|
|
|
<a href={item.user_url} target="_blank" className="fl">
|
|
|
<img alt="头像" className="radius" height="80" src={getImageUrl(`${"images/"+item.image_url}`)} width="80"/>
|
|
|
</a>
|
|
|
|
|
|
<div className="fl ml15 flex1">
|
|
|
<p className="mb10 mt5">{item.name}
|
|
|
{
|
|
|
detailInfoList===undefined?"":detailInfoList.allow_add_member===true?
|
|
|
<a className="fr" onClick={()=>this.shanchuallow(item.id)}><i className="iconfont icon-shanchu color-grey-c font-14 font-n"></i></a>:""
|
|
|
}
|
|
|
</p>
|
|
|
<div className="clearfix">
|
|
|
<p className="color-grey-9 font-12 fl"><span className="mr10">{item.school}</span><span>{item.identity}</span></p>
|
|
|
</div>
|
|
|
{
|
|
|
detailInfoList===undefined?"":detailInfoList.allow_add_member===true? <div>
|
|
|
<div className="fr ml15 flex1"><a onClick={()=>this.moveup(item)}><Tooltip title="上移"><i className="color-green font-18 iconfont icon-xiangshangyi"></i></Tooltip></a></div>
|
|
|
<div className="fr ml15 flex1 "><a onClick={()=>this.movedown(item)}><Tooltip title="下移"><i className="color-green font-18 iconfont icon-xiangxiayi"></i></Tooltip></a></div>
|
|
|
</div>
|
|
|
:""
|
|
|
}
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
)
|
|
|
})
|
|
|
: detailInfoList.members && detailInfoList.members.map((item,key)=>{
|
|
|
return(
|
|
|
<div className="teacherTeamItem clearfix df" key={key}>
|
|
|
<a href={item.user_url} target="_blank" className="fl">
|
|
|
<img alt="头像" className="radius" height="80" src={getImageUrl(`${"images/"+item.image_url}`)} width="80"/>
|
|
|
</a>
|
|
|
|
|
|
<div className="fl ml15 flex1">
|
|
|
<p className="mb10 mt5">{item.name}
|
|
|
{/*{*/}
|
|
|
{/* detailInfoList===undefined?"":detailInfoList.allow_add_member===true?*/}
|
|
|
{/* <a className="fr" onClick={()=>this.shanchuallow(item.id)}><i className="iconfont icon-shanchu color-grey-c font-14 font-n"></i></a>:""*/}
|
|
|
{/*}*/}
|
|
|
</p>
|
|
|
<div className="clearfix">
|
|
|
<p className="color-grey-9 font-12 fl"><span className="mr10">{item.school}</span><span>{item.identity}</span></p>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
)
|
|
|
})}
|
|
|
|
|
|
</div>
|
|
|
}
|
|
|
|
|
|
|
|
|
<AddCollaborators {...this.props} {...this.state} updatadetailInfoLists={this.updatadetailInfoList}></AddCollaborators>
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
)
|
|
|
}
|
|
|
}
|
|
|
export default PathDetailIndex; |