You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
educoder/public/react/src/modules/paths/PathDetail/PathDetailIndex.js

545 lines
20 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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,
})
// TODO 这个是临时处理,还需要优化,这里要看怎么区分处理
if (this.state.Modalstopval == '你确定要删除该成员吗?') {
return;
}
this.props.history.goBack()
}
cardsModalsave=()=>{
this.setState({
Modalstype:false,
})
this.props.history.goBack()
}
// 加载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) {
debugger
return;
}
if (result.data.status === 403) {
debugger
// window.location.href = "/403";
return;
}
if(result.data.allow_visit===true){
this.setState({
detailInfoList:result.data,
items: getItems(result.data.members.length),
})
}
}).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) {
debugger
return;
}
if (result.data.status === 403 ) {
debugger
// window.location.href = "/403";
return;
}
if(result.data.allow_visit===true){
this.setState({
detailInfoList:result.data,
items: getItems(result.data.members.length),
user_id:undefined,
})
}
}).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.props.showNotification(response.data.message)
this.setState({
Modalstype:false,
// Modalstopval:response.data.message,
loadtype:false,
// 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">
<style>
{
`
.head-right{
line-height: 30px;
}
`
}
</style>
<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?
<Tooltip placement="bottom" title={"编辑"}>
<Link className="fr" to={"/paths/"+this.props.match.params.pathId+"/edit"}>
<i className="iconfont icon-bianjidaibeijing font-20 color-green"></i>
</Link>
</Tooltip>
:""
}
</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?
<Tooltip placement="bottom" title={"编辑"}>
<Link to={"/paths/"+this.props.match.params.pathId+"/edit#learning_notes"} className="fr mtf5">
<i className="iconfont icon-bianjidaibeijing font-20 color-green"></i>
</Link>
</Tooltip>
:""
}
</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>
<Tooltip placement="bottom" title={"显示全部"}>
<div className={detailInfoList.tags.length>15&&clickdetailInfoListtype===false?"newsubscript mb9 color-grey-9 fr":"newsubscript mb9 color-grey-9 none"}
onClick={()=>this.clickNewsubscript(0)}
><span className="mr8">...</span><Icon type="caret-down" />
</div>
</Tooltip>
<Tooltip placement="bottom" title={"收起"}>
<div className={clickdetailInfoListtype===false?"newsubscript mb9 color-grey-9 none":"newsubscript mb9 color-grey-9 fr"}
onClick={()=>this.clickNewsubscript(1)}><Icon type="caret-up" />
</div>
</Tooltip>
</div>
}
{
this.props.checkIfLogin()===false?"":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}
{/* 新增role 判断是否能删除 1 管理员 2 合作者 */}
{
detailInfoList===undefined?"":detailInfoList.allow_add_member===true && item.role == 2?
<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;