init project
@@ -0,0 +1,37 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
|
||||
|
||||
import Loading from '../../Loading';
|
||||
|
||||
import Loadable from 'react-loadable';
|
||||
|
||||
import { TPMIndexHOC } from '../tpm/TPMIndexHOC';
|
||||
|
||||
import { SnackbarHOC,getImageUrl } from 'educoder';
|
||||
|
||||
class Shixunauthority extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="newMain clearfix">
|
||||
<div className=" edu-txt-center mt60 mb60">
|
||||
{/*mt100 mb100*/}
|
||||
<img src={getImageUrl("images/warn/pic_403.jpg")} />
|
||||
<p className="font-18 mt40">
|
||||
您可以稍后尝试 <a href="/"
|
||||
className="color-blue">返回首页</a>
|
||||
,或者
|
||||
<a target="_blank"
|
||||
href="//shang.qq.com/wpa/qunwpa?idkey=2f2043d88c1bd61d182b98bf1e061c6185e23055bec832c07d8148fe11c5a6cd"
|
||||
className="color-blue">QQ反馈>></a>
|
||||
</p>
|
||||
</div>
|
||||
{/*<div style="clear:both;"></div>*/}
|
||||
{/*<div id="ajax-indicator" style="display:none;"><span>载入中...</span></div>*/}
|
||||
{/*<div id="ajax-modal" style="display:none;"></div>*/}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SnackbarHOC() (TPMIndexHOC ( Shixunauthority ));
|
||||
@@ -0,0 +1,37 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
|
||||
|
||||
import Loading from '../../Loading';
|
||||
|
||||
import Loadable from 'react-loadable';
|
||||
|
||||
import { TPMIndexHOC } from '../tpm/TPMIndexHOC';
|
||||
|
||||
import { SnackbarHOC,getImageUrl } from 'educoder';
|
||||
|
||||
class http500 extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="newMain clearfix">
|
||||
<div className=" edu-txt-center mt60 mb60">
|
||||
{/*mt100 mb100*/}
|
||||
<img src={getImageUrl("images/warn/pic_404.jpg")} />
|
||||
<p className="font-18 mt40">
|
||||
您可以稍后尝试 <a href="/"
|
||||
className="color-blue">返回首页</a>
|
||||
,或者
|
||||
<a target="_blank"
|
||||
href="//shang.qq.com/wpa/qunwpa?idkey=2f2043d88c1bd61d182b98bf1e061c6185e23055bec832c07d8148fe11c5a6cd"
|
||||
className="color-blue">QQ反馈>></a>
|
||||
</p>
|
||||
</div>
|
||||
{/*<div style="clear:both;"></div>*/}
|
||||
{/*<div id="ajax-indicator" style="display:none;"><span>载入中...</span></div>*/}
|
||||
{/*<div id="ajax-modal" style="display:none;"></div>*/}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SnackbarHOC() (TPMIndexHOC ( http500 ));
|
||||
@@ -0,0 +1,37 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
|
||||
|
||||
import Loading from '../../Loading';
|
||||
|
||||
import Loadable from 'react-loadable';
|
||||
|
||||
import { TPMIndexHOC } from '../tpm/TPMIndexHOC';
|
||||
|
||||
import { SnackbarHOC,getImageUrl } from 'educoder';
|
||||
|
||||
class Shixunnopage extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="newMain clearfix">
|
||||
<div className=" edu-txt-center mt60 mb60">
|
||||
{/*mt100 mb100*/}
|
||||
<img src={getImageUrl("images/warn/pic_500.jpg")} />
|
||||
<p className="font-18 mt40">
|
||||
您可以稍后尝试 <a href="/"
|
||||
className="color-blue">返回首页</a>
|
||||
,或者
|
||||
<a target="_blank"
|
||||
href="//shang.qq.com/wpa/qunwpa?idkey=2f2043d88c1bd61d182b98bf1e061c6185e23055bec832c07d8148fe11c5a6cd"
|
||||
className="color-blue">QQ反馈>></a>
|
||||
</p>
|
||||
</div>
|
||||
{/*<div style="clear:both;"></div>*/}
|
||||
{/*<div id="ajax-indicator" style="display:none;"><span>载入中...</span></div>*/}
|
||||
{/*<div id="ajax-modal" style="display:none;"></div>*/}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SnackbarHOC() (TPMIndexHOC ( Shixunnopage ));
|
||||
@@ -0,0 +1,261 @@
|
||||
|
||||
.greytab-inner {
|
||||
/*overflow-y: scroll;*/
|
||||
}
|
||||
/*评论列表*/
|
||||
.panel-comment_item .t_area {
|
||||
font-size: 12px;
|
||||
color: #CCCCCC;
|
||||
}
|
||||
.panel-comment_item .orig_reply i {
|
||||
font-size: 14px !important;
|
||||
margin-left: 12px;
|
||||
}
|
||||
/* ke style 代码块*/
|
||||
.panel-comment_item ol.linenums {
|
||||
overflow: auto;
|
||||
}
|
||||
.panel-comment_item .rewarded {
|
||||
color: #FF7500!important
|
||||
}
|
||||
.panel-comment_item .rewarded.normalUser {
|
||||
cursor: inherit;
|
||||
}
|
||||
#tab_con_4 .-layout-v {
|
||||
overflow-y: auto;
|
||||
}
|
||||
#tab_con_4 .rc-pagination {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.rc-pagination {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.comment_content img {
|
||||
max-width: 23% !important;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------- CommentInput START */
|
||||
|
||||
/*收起的时候radius变化*/
|
||||
#mini_comment_section .df .ke-container {
|
||||
border-radius: 15px;
|
||||
|
||||
}
|
||||
#mini_comment_section .df .buttons {
|
||||
width: 70px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
#mini_comment_section .buttons i {
|
||||
font-size: 18px;
|
||||
color: #656565;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
#mini_comment_section i.newReplyIcon {
|
||||
color: #4DACFF;
|
||||
cursor: pointer;
|
||||
}
|
||||
#mini_comment_section .buttons {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#mini_comment_section .buttons>p {
|
||||
margin-top: 4px;
|
||||
display: none;
|
||||
}
|
||||
#mini_comment_section .df .buttons>p {
|
||||
margin-top: 14px;
|
||||
display: block;
|
||||
}
|
||||
#mini_comment_section {
|
||||
height: auto;
|
||||
background-color: #FFF;
|
||||
/*border-top: 1px solid #f0f1fe;*/
|
||||
display: flex;
|
||||
box-shadow: 0px -3px 5px 0px rgba(76, 172, 255, 0.2);
|
||||
z-index: 99;
|
||||
}
|
||||
#mini_comment_section #editor_panel {
|
||||
margin-bottom: 9px
|
||||
}
|
||||
/* commentInput 上传图片的图标挪动到左下*/
|
||||
#mini_comment_section #editor_panel>div:nth-child(1) {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
right: 88px;
|
||||
}
|
||||
#mini_comment_section .ke-toolbar-icon-url {
|
||||
background-image: url('../../images/tpi/upload-image.png');
|
||||
background-position: 0px 0px;
|
||||
background-size: 30px 30px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
#mini_comment_section .ke-outline {
|
||||
height: 30px;
|
||||
margin-bottom: -11px;
|
||||
width: 30px;
|
||||
margin-right: -5px;
|
||||
border: none;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
/* ie上传图片看不见的问题 */
|
||||
position: absolute;
|
||||
top: -30px;
|
||||
left: -30px;
|
||||
left: -24px;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
#mini_comment_section i.replyIcon {
|
||||
font-size: 20px;
|
||||
}
|
||||
#shixun_comment_block .dot {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
border-radius: 2px;
|
||||
background-color: #4CACFF;
|
||||
width: 4px;
|
||||
position: relative;
|
||||
bottom: 30px;
|
||||
left: 18px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#mini_comment_section .ke-container {
|
||||
border-radius: 6px;
|
||||
border-color: #EAEAEA;
|
||||
/*max-height: 400px; */
|
||||
/*解决上传图片后看不到评论按钮的问题*/
|
||||
}
|
||||
.commentTxt{
|
||||
width: 100%;
|
||||
height: 95px;
|
||||
border:1px solid #EAEAEA;
|
||||
border-radius: 10px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
#game_praise_tread {
|
||||
cursor: pointer;
|
||||
}
|
||||
.commentsbtn {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
#shixun_comment_block {
|
||||
margin: 0px 10px;
|
||||
margin-bottom: -2px;
|
||||
}
|
||||
|
||||
.panel-comment_item a.task-btn-orange {
|
||||
background: #4CACFF;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------- CommentInput END */
|
||||
.childrenCommentsView {
|
||||
background: #F4F4F4;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 6px;
|
||||
position: relative;
|
||||
margin-top: 6px;
|
||||
}
|
||||
.childrenCommentsView .trangle{
|
||||
position: absolute;
|
||||
border-color: black;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
border-bottom: 5px solid #F4F4F4;
|
||||
left: 13px;
|
||||
top: -9px;
|
||||
border-bottom: 10px solid #F4F4F4;
|
||||
}
|
||||
.childComment {
|
||||
padding: 2px 8px;
|
||||
}
|
||||
.childComment .iconfont.icon-jiangli {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
|
||||
.childComment:hover {
|
||||
background: #EBEBEB;
|
||||
}
|
||||
.childComment .iconfont {
|
||||
display: none;
|
||||
}
|
||||
.childComment p.orig_reply {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.childComment:hover .iconfont{
|
||||
display: inline;
|
||||
}
|
||||
.noCommentTitle {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.blink {
|
||||
animation: blink-animation 3s steps(5, start) infinite;
|
||||
-webkit-animation: blink-animation 3s steps(5, start) infinite;
|
||||
}
|
||||
@keyframes blink-animation {
|
||||
to {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes blink-animation {
|
||||
to {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*md 编辑器 emoji */
|
||||
.J_Comment_Reply img.emoji {
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.noCommentTitle {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
font-size: 16px;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
}
|
||||
|
||||
.break_word_comments{
|
||||
/* 这个样式影响到了行高 */
|
||||
/* white-space: pre-wrap!important; */
|
||||
word-break: break-word;
|
||||
/* 影响了 ul li的样式: https://testeduplus2.educoder.net/courses/1748/common_homeworks/12131/740898/appraise */
|
||||
/* line-height: 14px; */
|
||||
width: 100%;
|
||||
word-wrap: break-word;
|
||||
margin-bottom: 4px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.childComment .break_word_comments{
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
form.df .tips {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.loadMoreChildComments {
|
||||
text-align: center;
|
||||
height: 24px;
|
||||
background: #F1F1F1;
|
||||
cursor: pointer;
|
||||
|
||||
}
|
||||
.loadMoreChildComments i.icon-xiajiantou {
|
||||
position: relative;
|
||||
bottom: 5px;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import Comments from './Comments'
|
||||
import CommentInput from './CommentInput'
|
||||
|
||||
class CommentContainer extends Component {
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
|
||||
<Comments
|
||||
{...this.props}
|
||||
showHiddenButton={true}
|
||||
>
|
||||
|
||||
</Comments>
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default CommentContainer;
|
||||
@@ -0,0 +1,131 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import Tooltip from 'material-ui/Tooltip';
|
||||
|
||||
import './Comment.css'
|
||||
|
||||
import messageImg from '../../images/tpi/message.svg'
|
||||
|
||||
import messagegreyImg from '../../images/tpi/messagegrey.svg'
|
||||
|
||||
const $ = window.$;
|
||||
function pasteListener(event) {
|
||||
if (event.clipboardData.types[0] === 'Files' ) {
|
||||
event.preventDefault();
|
||||
// event.stopPropagation();
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
*/
|
||||
class CommentInput extends Component {
|
||||
|
||||
componentDidMount() {
|
||||
const { challenge } = this.props;
|
||||
|
||||
}
|
||||
|
||||
componentWillReceiveProps(newProps, newContext) {
|
||||
// TODO 暂没有切实训的场景
|
||||
if (newProps.challenge && newProps.challenge.shixun_id
|
||||
&& (!this.props.challenge.shixun_id || newProps.challenge.shixun_id != this.props.challenge.shixun_id)) {
|
||||
setTimeout(()=>{
|
||||
window.sd_create_editor_from_shixun_data(newProps.challenge.shixun_id, null, "100%", "Shixun");
|
||||
if ( $.browser.mozilla ) {
|
||||
setTimeout(() => {
|
||||
const _body = $('.ke-edit-iframe')[0].contentWindow.document.body;
|
||||
_body.removeEventListener('paste', pasteListener)
|
||||
_body.addEventListener('paste', pasteListener)
|
||||
}, 4200)
|
||||
}
|
||||
}, 100)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
const { createNewComment, editedComment, commentOnChange, challenge, shixun, loading, praisePlus, gotNewReply, showNewReply} = this.props;
|
||||
|
||||
/*
|
||||
onclick="game_praise('<%= @game_challenge.id %>', '<%= @game_challenge.class %>')"
|
||||
|
||||
onclick="game_tread('<%= @game_challenge.id %>')"
|
||||
|
||||
style={{display: 'none'}}
|
||||
*/
|
||||
return (
|
||||
<li className="comment-input fl" id="shixun_comment_block">
|
||||
{ !challenge.shixun_id ? '' :
|
||||
<div nhname={`new_message_${challenge.shixun_id}`} className="fr" style={{ width: '99%'}}>
|
||||
<form acceptCharset="UTF-8" action="/discusses?challenge_id=118&dis_id=61&dis_type=Shixun" className="df" data-remote="true" id="new_comment_form" method="post">
|
||||
<div className="fl" style={{flex: 1,marginTop:'7px'}} id="editor_panel">
|
||||
<div nhname={`toolbar_container_${challenge.shixun_id}`}></div>
|
||||
{/*有问题或有建议,请直接给我留言吧!*/}
|
||||
<textarea id={`comment_news_${challenge.shixun_id}`}
|
||||
nhname={`new_message_textarea_${challenge.shixun_id}`} name="content"
|
||||
value={ editedComment } onChange={ commentOnChange } className="none">
|
||||
</textarea>
|
||||
</div>
|
||||
<div className="tips"
|
||||
style={{ 'float': 'left', 'marginTop': '6px', 'fontSize': '12px', 'color': '#ff6800'}}>
|
||||
请勿粘贴答案,否则将造成账号禁用等后果!
|
||||
</div>
|
||||
<div className="fr buttons" style={{ minWidth:'25px', height: '32px' }}>
|
||||
<a id={`new_message_submit_btn_${challenge.shixun_id}`} href="javascript:void(0)"
|
||||
style={{display: 'none'}} onClick={ createNewComment } className="commentsbtn task-btn task-btn-blue fr">
|
||||
发送
|
||||
</a>
|
||||
<p className="fr ml10" style={{minWidth:'25px'}} >
|
||||
<Tooltip title={ challenge.user_praise ? "取消点赞" : "点赞"}>
|
||||
<span id="game_praise_tread" className="color-grey mr20" onClick={praisePlus}>
|
||||
<i className={`mr3 ${ challenge.user_praise ? "iconfont icon-dianzan color-orange03" : "iconfont icon-dianzan-xian" } `} alt="赞" ></i>
|
||||
{ challenge.praise_count ?
|
||||
<span className="font-16" id="game_praise_count">{challenge.praise_count}</span> : ''}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</p>
|
||||
<p className="fr ml10" style={{minWidth:'25px'}} >
|
||||
{ gotNewReply ?
|
||||
<React.Fragment>
|
||||
<i className={`replyIcon newReplyIcon iconfont icon-tpixiaoxitixing`} onClick={showNewReply}></i>
|
||||
<span className="dot blink"></span>
|
||||
</React.Fragment>
|
||||
:
|
||||
<Tooltip title={ "暂无新消息" }>
|
||||
<i className={`replyIcon iconfont icon-tpixiaoxitixing`}></i>
|
||||
</Tooltip>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
}
|
||||
</li>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
<img src={messagegreyImg}/>
|
||||
|
||||
<span data-tip-top={ tread ? "踩" : "取消踩" } id="game_tread" className="color-grey" style={{paddingTop:'7px'}}>
|
||||
<i className={`fa fa-thumbs-down font-20 mr3 ${ tread ? "" : "color-orange03" } `} ></i>
|
||||
<span className="font-12 font-bd" id="game_tread_count">{tread_count}</span>
|
||||
</span>
|
||||
|
||||
<div className="clearfix with100">
|
||||
<textarea className="commentTxt"></textarea>
|
||||
<p className="clearfix">
|
||||
<a href="javascript:void(0)" className="fl uploadImg mt2">
|
||||
<img src="/images/sendimg.svg" className="fl mr3 mt6"/><span className="up">上传图片</span>
|
||||
</a>
|
||||
<a href="javascript:void(0)" className="commentsbtn task-btn task-btn-blue fr">评论</a>
|
||||
<span className="fr mr15 mt3"><i className="fa fa-thumbs-up color-dark-grey mr3 font-18"></i>20</span>
|
||||
|
||||
<img src="/images/message.svg" className="fr mr15 mt8"/>
|
||||
</p>
|
||||
</div>
|
||||
*/
|
||||
export default CommentInput;
|
||||
@@ -0,0 +1,72 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Redirect } from 'react-router';
|
||||
|
||||
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import classNames from 'classnames'
|
||||
|
||||
const $ = window.$;
|
||||
const _origin = window.location.origin;
|
||||
|
||||
class CommentItemKEEditor extends Component {
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { item, currentReplyComment } = this.props;
|
||||
if ( prevProps.showReplyEditorFlag != this.props.showReplyEditorFlag &&
|
||||
currentReplyComment && currentReplyComment.id == item.id ) {
|
||||
this.showOrHideEditor(currentReplyComment)
|
||||
}
|
||||
}
|
||||
// 如果未初始化,会先初始化
|
||||
showOrHideEditor = (comment) => {
|
||||
const { user } = this.props;
|
||||
console.log('initReply ', comment)
|
||||
|
||||
const $ = window.$;
|
||||
var id = comment.id
|
||||
var reply_message_el = `#reply_message_${id}`
|
||||
var reply_iconup_el = `#reply_iconup_${id}`
|
||||
if($(reply_message_el).html() == "") {
|
||||
$(".reply_to_message").html("");
|
||||
$(reply_message_el).html(`<div className=\"orig_reply_box borderBottomNone reply_to_message\" id=\"reply_to_message_${id}\">\n <div class=\"homepagePostReplyPortrait mr15 imageFuzzy fl\" id=\"reply_image_${id}\"><a href=\"${user.user_url}\" target=\"_blank\" alt=\"用户头像\"><img alt=\"0?1442652658\" height=\"33\" src=\"${_origin}/images/${user.image_url}\" width=\"33\" /><\/a><\/div>\n <div class=\"orig_textarea fl\" style=\"margin-bottom: 0px\">\n <div nhname=\'new_message_${id}\'>\n <form accept-charset=\"UTF-8\" action=\"/discusses?challenge_id=118&dis_id=61&dis_type=Shixun\" data-remote=\"true\" id=\"new_comment_form\" method=\"post\"><div style=\"margin:0;padding:0;display:inline\"><input name=\"utf8\" type=\"hidden\" value=\"✓\" /><input name=\"authenticity_token\" type=\"hidden\" value=\"HJTbMpfI8LKUpwghfkvgB2SaMmcIVyVdAezyKmzJ7FU=\" /><\/div>\n <input type=\"hidden\" id=\"dis_reply_id\" name=\"reply_id\" value=\"${id}\">\n <div nhname=\'toolbar_container_${id}\'><\/div>\n <textarea placeholder=\"有问题或有建议,请直接给我留言吧!\" id=\"comment_news_${id}\" style=\"display: none\" nhname=\'new_message_textarea_${id}\' name=\"content\"><\/textarea>\n <a id=\"new_message_submit_btn_${id}\" href=\"javascript:void(0)\" onclick=\"this.style.display=\'none\'\" class=\"mt10 task-btn task-btn-orange fr\">发送<\/a>\n <div class=\"cl\"><\/div>\n <p nhname=\'contentmsg_${id}\'><\/p>\n<\/form> <\/div>\n <div class=\"cl\"><\/div>\n <\/div>\n <div class=\"cl\"><\/div>\n<\/div>\n`); //" ide语法识别
|
||||
$(reply_iconup_el).show();
|
||||
$(function(){
|
||||
window.sd_create_editor_from_data(id ,null,"100%", "Discuss");
|
||||
});
|
||||
|
||||
}else {
|
||||
if ($(reply_message_el).is(':visible')) {
|
||||
$(reply_message_el).hide();
|
||||
} else {
|
||||
$(reply_message_el).show();
|
||||
}
|
||||
// $(reply_message_el).html("");
|
||||
|
||||
// $(reply_iconup_el).hide();
|
||||
}
|
||||
// 自动focus
|
||||
setTimeout(()=>{
|
||||
var iframe =$(`#reply_to_message_${id}`).find('iframe')[0]
|
||||
iframe && iframe.contentDocument.body.focus()
|
||||
}, 200)
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
const { match, history, item, user } = this.props
|
||||
if (!item) {
|
||||
return <div></div>
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="cl"></div>
|
||||
<div id={`reply_message_${item.id}`} className="reply_to_message"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ( CommentItemKEEditor );
|
||||
@@ -0,0 +1,58 @@
|
||||
/*md编辑器 将toolbar高度变小变袖珍*/
|
||||
.reply_to_message .editorMD .editormd-toolbar li {
|
||||
padding: 0;
|
||||
}
|
||||
.reply_to_message .editorMD .editormd-toolbar {
|
||||
min-height: 28px;
|
||||
|
||||
}
|
||||
.reply_to_message .editorMD .editormd-toolbar .editormd-toolbar-container {
|
||||
min-height: 28px;
|
||||
}
|
||||
.reply_to_message .editorMD .editormd-toolbar i {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
|
||||
.reply_to_message .editorMD .editormd-preview {
|
||||
top: 30px;
|
||||
}
|
||||
.reply_to_message .editorMD .CodeMirror {
|
||||
margin-top: 30px;
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
.panel-comment_item .editor__resize {
|
||||
transform: translateX(-2%);
|
||||
|
||||
position: absolute;
|
||||
width: 120px;
|
||||
height: 4px;
|
||||
left: 54%;
|
||||
transform: translateX(-50%);
|
||||
margin-top: 2px;
|
||||
border-top: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ccc;
|
||||
cursor: row-resize;
|
||||
text-indent: 110%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-transform: capitalize;
|
||||
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/*帖子回復按鈕*/
|
||||
a.commentsbtn.task-btn-blue {
|
||||
background: #4CACFF !important;
|
||||
}
|
||||
|
||||
.commentTab a.commentsbtn.task-btn-blue {
|
||||
margin-right: 22px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
|
||||
.editormd-grid-table-row a.editormd-emoji-btn.selected {
|
||||
border-bottom: 2px solid #4CACFF!important;
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Redirect } from 'react-router';
|
||||
|
||||
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import classNames from 'classnames'
|
||||
import { getImageUrl, toPath, getUrl,getUploadActionUrl } from 'educoder';
|
||||
import './CommentItemMDEditor.css'
|
||||
|
||||
const $ = window.$;
|
||||
const _origin = window.location.origin;
|
||||
|
||||
class CommentItemMDEditor extends Component {
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { item, currentReplyComment } = this.props;
|
||||
if ( prevProps.showReplyEditorFlag != this.props.showReplyEditorFlag &&
|
||||
currentReplyComment && currentReplyComment.id == item.id ) {
|
||||
this.showOrHideEditor(currentReplyComment)
|
||||
}
|
||||
}
|
||||
// 如果未初始化,会先初始化
|
||||
showOrHideEditor = (comment) => {
|
||||
const { user } = this.props;
|
||||
console.log('initReply ', comment)
|
||||
|
||||
const $ = window.$;
|
||||
var commentId = comment.id
|
||||
var reply_message_el = `#reply_message_${commentId}`
|
||||
|
||||
const initMD_ID = `reply_message_editorMd_${commentId}`
|
||||
const view_selector = `.commentItemMDEditorView_${commentId}`
|
||||
const commitBtnSelector = `#commitBtn_${commentId}`
|
||||
if( $(`#${initMD_ID} textarea`).length === 1 ) { // 没有初始化
|
||||
const placeholder = '我要回复...'
|
||||
// const imageUrl = `/upload_with_markdown?container_id=${commentId}&container_type=Memo`;
|
||||
const imageUrl = `${getUploadActionUrl()}`;
|
||||
|
||||
const otherOptions = {
|
||||
watch: false,
|
||||
htmlDecode: "style,script,iframe", // you can filter tags decode
|
||||
// taskList: true,
|
||||
|
||||
mode: 'markdown',
|
||||
toolbar: true,
|
||||
markdown: '',
|
||||
readOnly: false,
|
||||
// preview: false,
|
||||
|
||||
tex: true, // 数学公式
|
||||
flowChart: false, // 默认不解析
|
||||
sequenceDiagram: false, // 默认不解析
|
||||
dialogLockScreen: false,
|
||||
}
|
||||
const commentMDEditor = window.create_editorMD_4comment(`${initMD_ID}`, '', 120, placeholder, imageUrl, () => {
|
||||
// onload callback
|
||||
commentMDEditor.cm.focus()
|
||||
|
||||
window.initMDEditorDragResize(".editor__resize", commentMDEditor, {
|
||||
initHeight: 120
|
||||
})
|
||||
|
||||
}, otherOptions);
|
||||
commentMDEditor.state.preview = false;
|
||||
this.commentMDEditor = commentMDEditor;
|
||||
|
||||
$('.commentItemMDEditorView').hide();
|
||||
$(view_selector).show();
|
||||
|
||||
}else { // 初始化了,显示隐藏切换
|
||||
if ($(reply_message_el).is(':visible')) {
|
||||
$( view_selector ).hide()
|
||||
|
||||
} else {
|
||||
$('.commentItemMDEditorView').hide();
|
||||
|
||||
$(view_selector).show();
|
||||
|
||||
window._currentChildcommentMDEditor && window._currentChildcommentMDEditor.resize()
|
||||
// 自动focus
|
||||
setTimeout(()=>{
|
||||
this.commentMDEditor && this.commentMDEditor.cm && this.commentMDEditor.cm.focus()
|
||||
this.commentMDEditor.resize() // 解决切换显示、隐藏多次后出现的样式错乱的问题
|
||||
}, 200)
|
||||
}
|
||||
}
|
||||
window._currentChildcommentMDEditor = this.commentMDEditor; // tpi resize 的时候需要做调用editor.resize
|
||||
|
||||
}
|
||||
|
||||
onCommit = () => {
|
||||
window.$(document).trigger("onReply", { commentContent: this.commentMDEditor.getValue()
|
||||
, id: this.props.item.id, editor: this.commentMDEditor } );
|
||||
}
|
||||
|
||||
render() {
|
||||
const { match, history, item, user, buttonText } = this.props
|
||||
if (!item) {
|
||||
return <div></div>
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`commentItemMDEditorView commentItemMDEditorView_${item.id}`} style={{display:'none'}}>
|
||||
<div className="homepagePostReplyPortrait mr15 fl imageFuzzy" id="reply_image_3097"
|
||||
style={{ marginTop: '2px', marginRight: '-20px' }} >
|
||||
<a href={`${user.user_url}`} target="_blank" alt="用户头像">
|
||||
{/* 'https://testeduplus2.educoder.net/images/avatars/User/50571'|| */}
|
||||
<img alt="0?1442652658" height="33" src={`/images/${user.image_url}`} width="33"></img>
|
||||
</a>
|
||||
</div>
|
||||
<div id={`reply_message_${item.id}`} className="reply_to_message commentItemMDEditor editormd-image-click-expand"
|
||||
style={{ paddingTop: '0px', paddingBottom: '0px', marginTop: '36px' }}
|
||||
>
|
||||
<div id={`reply_message_editorMd_${item.id}`} className="editorMD" style={{ marginBottom: '0px'}}>
|
||||
<textarea style={{'display': 'none'}}>
|
||||
</textarea>
|
||||
</div>
|
||||
<div className="editor__resize" href="javascript:void(0);" style={{display: ''}}>调整高度</div>
|
||||
|
||||
<div class="clearfix">
|
||||
<a id={`commitBtn_${item.id}`} href="javascript:void(0)"
|
||||
onClick={this.onCommit} style={{ marginRight: '44px' }}
|
||||
className="commentsbtn task-btn task-btn-blue fr " style={{display: ''}}>
|
||||
{ buttonText || '发送'}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ( CommentItemMDEditor );
|
||||
|
||||
// style={{ margin: '10px 44px', marginBottom: '0px'}}
|
||||
@@ -0,0 +1,616 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import Dialog, {
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
DialogTitle,
|
||||
} from 'material-ui/Dialog';
|
||||
import Button from 'material-ui/Button';
|
||||
import Tooltip from 'material-ui/Tooltip';
|
||||
|
||||
import Pagination from 'rc-pagination';
|
||||
import 'rc-pagination/assets/index.css';
|
||||
|
||||
import { getImageUrl, toPath } from 'educoder';
|
||||
|
||||
import Input, { InputLabel } from 'material-ui/Input';
|
||||
|
||||
import { FormControl, FormHelperText } from 'material-ui/Form';
|
||||
|
||||
import CommentItemKEEditor from './CommentItemKEEditor';
|
||||
import CommentItemMDEditor from './CommentItemMDEditor';
|
||||
|
||||
import './Comment.css'
|
||||
import Modals from '../modals/Modals'
|
||||
import { InputNumber } from 'antd'
|
||||
|
||||
/*
|
||||
-------------------------- 样式相关
|
||||
class 改成 className
|
||||
style 需要传入json对象 style="margin:0px"> -> style={{ margin:"0px" }}>
|
||||
margin-top -> marginTop
|
||||
onclick -> onClick 驼峰
|
||||
|
||||
-------------------------- 模板语法相关
|
||||
页面都在前端组装、渲染
|
||||
rails模板的 if等逻辑改成js实现
|
||||
客户端需要能判断 User.current.manager_of_shixun?(comment.dis_id)
|
||||
|
||||
-------------------------- 现有ui控件的使用方式
|
||||
方案1: 换成对应的react组件,然后再调用(控件简单时推荐)
|
||||
方案2: 在react环境中使用若干jquery插件(控件复杂,又无react环境下的替代方案时考虑使用)
|
||||
|
||||
--------------------------
|
||||
需要服务端提供对应的rest api
|
||||
|
||||
|
||||
*/
|
||||
|
||||
const _origin = window.location.origin;
|
||||
|
||||
|
||||
/*
|
||||
tpi讨论、交流问答帖子详情讨论、课堂讨论的公用模块:
|
||||
https://www.educoder.net/tasks/n2ejvaowk6l9
|
||||
https://www.educoder.net/forums/2629
|
||||
注意不同模块使用时的参数的不同 usingAntdModal onlySuperAdminCouldHide isChildCommentPagination等等
|
||||
|
||||
用到的props:
|
||||
user user_url image_url
|
||||
|
||||
loadingComments--
|
||||
comment_count_without_reply
|
||||
currentPage
|
||||
comments
|
||||
|
||||
buttonText 发送按钮 显示文本
|
||||
|
||||
showRewardButton 是否显示奖励按钮
|
||||
showHiddenButton 是否显示隐藏按钮
|
||||
|
||||
onlySuperAdminCouldHide 只有超级管理员才显示隐藏、取消隐藏
|
||||
isChildCommentPagination 是否子回复分页
|
||||
loadMoreChildComments function 加载所有子回复
|
||||
|
||||
usingAntdModal 是否使用antd的弹框
|
||||
|
||||
接口
|
||||
deleteComment 删除
|
||||
onPaginationChange 翻页变化
|
||||
commentPraise 点赞
|
||||
hiddenComment 隐藏
|
||||
rewardCode 奖励
|
||||
|
||||
*/
|
||||
class Comments extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.handleDialogClose = this.handleDialogClose.bind(this)
|
||||
this.handleGoldRewardDialogClose = this.handleGoldRewardDialogClose.bind(this)
|
||||
|
||||
this.state = {
|
||||
dialogOpen: false,
|
||||
goldRewardDialogOpen: false,
|
||||
goldRewardInput: '',
|
||||
|
||||
showReplyEditorFlag: false, // false->true or true->false时切换editor显示或隐藏
|
||||
currentReplyComment: null
|
||||
}
|
||||
}
|
||||
componentWillUnmount() {
|
||||
const $ = window.$;
|
||||
$(document).off("onReply");
|
||||
}
|
||||
componentDidMount() {
|
||||
setTimeout(()=>{
|
||||
const $ = window.$;
|
||||
// 绑定后会自动off? 加timeout试试
|
||||
$(document).on("onReply", (e, args)=>{
|
||||
const { commentContent, id, editor } = args;
|
||||
|
||||
this.props.replyComment(commentContent, id, editor)
|
||||
});
|
||||
}, 1000)
|
||||
|
||||
}
|
||||
initReply(comment) {
|
||||
this.props.initReply && this.props.initReply(comment)
|
||||
// 如果配置的使用kindEditor
|
||||
if (window.__useKindEditor === true) {
|
||||
const { user } = this.props;
|
||||
console.log('initReply ', comment)
|
||||
|
||||
const $ = window.$;
|
||||
var id = comment.id
|
||||
var reply_message_el = `#reply_message_${id}`
|
||||
var reply_iconup_el = `#reply_iconup_${id}`
|
||||
if($(reply_message_el).html() == "") {
|
||||
$(".reply_to_message").html("");
|
||||
$(reply_message_el).html(`<div className=\"orig_reply_box borderBottomNone reply_to_message\" id=\"reply_to_message_${id}\">\n <div class=\"homepagePostReplyPortrait mr15 imageFuzzy fl\" id=\"reply_image_${id}\"><a href=\"${user.user_url}\" target=\"_blank\" alt=\"用户头像\"><img alt=\"0?1442652658\" height=\"33\" src=\"${_origin}/images/${user.image_url}\" width=\"33\" /><\/a><\/div>\n <div class=\"orig_textarea fl\" style=\"margin-bottom: 0px\">\n <div nhname=\'new_message_${id}\'>\n <form accept-charset=\"UTF-8\" action=\"/discusses?challenge_id=118&dis_id=61&dis_type=Shixun\" data-remote=\"true\" id=\"new_comment_form\" method=\"post\"><div style=\"margin:0;padding:0;display:inline\"><input name=\"utf8\" type=\"hidden\" value=\"✓\" /><input name=\"authenticity_token\" type=\"hidden\" value=\"HJTbMpfI8LKUpwghfkvgB2SaMmcIVyVdAezyKmzJ7FU=\" /><\/div>\n <input type=\"hidden\" id=\"dis_reply_id\" name=\"reply_id\" value=\"${id}\">\n <div nhname=\'toolbar_container_${id}\'><\/div>\n <textarea placeholder=\"有问题或有建议,请直接给我留言吧!\" id=\"comment_news_${id}\" style=\"display: none\" nhname=\'new_message_textarea_${id}\' name=\"content\"><\/textarea>\n <a id=\"new_message_submit_btn_${id}\" href=\"javascript:void(0)\" onclick=\"this.style.display=\'none\'\" class=\"mt10 task-btn task-btn-orange fr\">${this.props.buttonText || '发送'}<\/a>\n <div class=\"cl\"><\/div>\n <p nhname=\'contentmsg_${id}\'><\/p>\n<\/form> <\/div>\n <div class=\"cl\"><\/div>\n <\/div>\n <div class=\"cl\"><\/div>\n<\/div>\n`); //" ide语法识别
|
||||
$(reply_iconup_el).show();
|
||||
$(function(){
|
||||
window.sd_create_editor_from_data(id ,null,"100%", "Discuss");
|
||||
});
|
||||
|
||||
}else {
|
||||
if ($(reply_message_el).is(':visible')) {
|
||||
$(reply_message_el).hide();
|
||||
} else {
|
||||
$(reply_message_el).show();
|
||||
}
|
||||
// $(reply_message_el).html("");
|
||||
|
||||
// $(reply_iconup_el).hide();
|
||||
}
|
||||
} else { // MD
|
||||
this.setState({
|
||||
currentReplyComment: comment,
|
||||
showReplyEditorFlag: !this.state.showReplyEditorFlag
|
||||
})
|
||||
}
|
||||
}
|
||||
// enableReplyTo
|
||||
// onClick={() => this.replyTo(item.user_id)}
|
||||
replyTo = (toUserId) => {
|
||||
|
||||
}
|
||||
renderChildenComments(comment) {
|
||||
if (!comment.children || comment.children.length === 0) {
|
||||
return ''
|
||||
}
|
||||
const { user } = this.props;
|
||||
let childCommentsElement = comment.children.map((item, index) =>{
|
||||
let _content = this.parseCommentContent(item.content);
|
||||
|
||||
return (
|
||||
<div key={index} className="childComment" >
|
||||
<div className="J_Comment_Info clearfix mt3">
|
||||
<div className="t_info fl">
|
||||
<a href={`${_origin}/users/${item.user_login}`} className="content-username hide fl">
|
||||
{item.username}
|
||||
</a>
|
||||
<span className="t_area fl">{item.time}</span>
|
||||
{/* { item.position ? <span className="fl color-light-green font-14 ml15">[第{item.position}关]</span> : ""} */}
|
||||
{
|
||||
item.reward ?
|
||||
<Tooltip title={ `已奖励金币${item.reward}` } disableFocusListener={true}>
|
||||
<a href="javascript:void(0);" style={{ marginLeft: '20px', cursor: 'default'}}
|
||||
className={`rewarded color-grey-8 font-12 fl ${ item.admin === true ? '': 'normalUser'}`}
|
||||
>
|
||||
<i className="iconfont icon-gift mr5 color-orange fl" style={{display: 'inline'}}></i><span className="fl">{item.reward}</span>
|
||||
</a>
|
||||
</Tooltip> : ''
|
||||
}
|
||||
</div>
|
||||
|
||||
<p className="fr orig_reply lineh-20">
|
||||
<span id="hidden_discuss_btn_952">
|
||||
</span>
|
||||
|
||||
{this.props.showRewardButton != false && comment.admin === true ?
|
||||
<a href="javascript:void(0);" className="color-grey-8" onClick={() => this.showGoldRewardDialog(comment, item) }>
|
||||
<Tooltip title={ "给TA奖励金币" } disableFocusListener={true}>
|
||||
<i className="iconfont icon-jiangli fl"></i>
|
||||
</Tooltip>
|
||||
</a>
|
||||
:""}
|
||||
|
||||
{/*子回复还没hidden字段*/}
|
||||
{false && comment.admin === true ?
|
||||
<Tooltip title={ item.hidden ? "取消隐藏" : "隐藏评论" }>
|
||||
<a href="javascript:void(0);" className="color-grey-8" onClick={() => this.onCommentBtnClick(comment, item, item.hidden ? 'hiddenCancel' : 'hidden') }>
|
||||
<i className={`fa ${item.hidden ? 'fa-eye' : 'fa-eye-slash'} mr5`}></i>
|
||||
</a>
|
||||
</Tooltip>
|
||||
:""}
|
||||
|
||||
{/* 新版user_id不准,获取方式不对 */}
|
||||
{ comment.admin === true || item.can_delete || item.user_id === user.user_id || item.user_login == user.login ?
|
||||
<a href="javascript:void(0);" className="color-grey-8" id="delete_reply_118_952" onClick={() => this.onCommentBtnClick(comment, item, 'delete') }>
|
||||
<Tooltip title={ "删除" } disableFocusListener={true}>
|
||||
<i className="iconfont icon-shanchu mr5"></i>
|
||||
</Tooltip>
|
||||
</a>
|
||||
: ''}
|
||||
|
||||
{/*
|
||||
<span className="ml5 mr5 color-grey-8">|</span>
|
||||
|
||||
<span className="reply_praise_count_952">
|
||||
<a href="/praise_tread/praise_plus?obj_id=952&obj_type=Discuss&type=reply&user_activity_id=952" data-remote="true" className="fr mr5 color-grey-8" data-tip-down="点赞">
|
||||
<i className="fa fa-thumbs-up mr5"></i>赞
|
||||
|
||||
<span className="ml5 fr"></span>
|
||||
</a>
|
||||
|
||||
</span>*/}
|
||||
</p>
|
||||
|
||||
{/* currentUser.id == item.creator_user.id && (
|
||||
<p className="fr mr10 orig_repll">
|
||||
<span id={`hidden_discuss_btn_${item.id}`}>
|
||||
<a href="javascript:void(0);" className="color-grey-8" onClick={ this.onCommentBtnClick(comment, item, 'delete') } >
|
||||
<i className="far fa-trash-alt mr5"></i>删除
|
||||
</a>
|
||||
<span className="ml5 mr5 color-grey-8">|</span>
|
||||
</span>
|
||||
</p>
|
||||
)*/}
|
||||
</div>
|
||||
|
||||
<div className="comment_content clearfix" id={`reply_content_${item.id}`}>
|
||||
<div className="color-grey-3" id={`reply_content_${item.id}`}>
|
||||
<div className={"break_word_comments markdown-body"} dangerouslySetInnerHTML={{__html: _content}}></div>
|
||||
<div className="cl"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)
|
||||
})
|
||||
return childCommentsElement
|
||||
}
|
||||
parseCommentContent = (oldContent) => {
|
||||
if (oldContent && oldContent.startsWith('<') && oldContent.endsWith('>')) {
|
||||
} else if (window.$('#md_div').length) { // 有这个临时处理md内容的dom
|
||||
window.$('#md_div').html('')
|
||||
// markdown to html
|
||||
try {
|
||||
var markdwonParser = window.editormd.markdownToHTML("md_div", {
|
||||
markdown: oldContent,
|
||||
emoji: true,
|
||||
htmlDecode: "style,script,iframe", // you can filter tags decode
|
||||
taskList: true,
|
||||
tex: true, // 默认不解析
|
||||
flowChart: true, // 默认不解析
|
||||
sequenceDiagram: true // 默认不解析
|
||||
});
|
||||
oldContent = window.$('#md_div').html()
|
||||
} catch (e) {
|
||||
// TODO 可能公式parse时报错了
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
return oldContent;
|
||||
}
|
||||
renderComments() {
|
||||
let { comments, currentUser, deleteComment, commentPraise, hiddenComment, user } = this.props;
|
||||
const { showReplyEditorFlag, currentReplyComment } = this.state;
|
||||
if (!comments || comments.length === 0) {
|
||||
return;
|
||||
}
|
||||
// "https://www.educoder.net/users/m02945638"
|
||||
let commentsElement = comments.map((item, index) => {
|
||||
let _content
|
||||
|
||||
_content = this.parseCommentContent(item.content);
|
||||
|
||||
return (
|
||||
<div className="comment_item_cont df clearfix" key={index}>
|
||||
<div className="J_Comment_Face fl">
|
||||
<a href={`${_origin}/users/${item.user_login}`} target="_blank">
|
||||
<img alt="用户头像" height="50" src={getImageUrl(`images/${item.image_url}`)} width="50"/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className="t_content fl">
|
||||
<div className="J_Comment_Reply">
|
||||
<div className="comment_orig_content" style={{ margin:"0px" }}>
|
||||
|
||||
|
||||
<div className="J_Comment_Info clearfix mt3">
|
||||
<div className="t_info fl">
|
||||
<a href={`${_origin}/users/${item.user_login}`} className="content-username hide fl">
|
||||
{item.username}
|
||||
</a>
|
||||
<span className="t_area fl">{item.time}</span>
|
||||
{ item.position && <span className="fl color-light-green font-14 ml15">[第{item.position}关]</span> }
|
||||
{ item.game_url ?
|
||||
<Tooltip title={ `点击查看TA的代码页面` } disableFocusListener={true}>
|
||||
<a href={item.game_url} target="_blank" className="fl font-14 ml15"
|
||||
style={{ color: "#4CACFF", cursor: "pointer" }}
|
||||
>查看</a>
|
||||
</Tooltip> : ""}
|
||||
|
||||
{
|
||||
item.reward ?
|
||||
<Tooltip title={ `已奖励金币${item.reward}` } disableFocusListener={true}>
|
||||
<a href="javascript:void(0);" style={{ marginLeft: '20px', cursor: 'default'}}
|
||||
className={`rewarded color-grey-8 font-12 fl ${ item.admin === true ? '': 'normalUser'}`}
|
||||
>
|
||||
<i className="iconfont icon-gift mr5 color-orange fl"></i><span className="fl">{item.reward}</span>
|
||||
</a>
|
||||
</Tooltip> : ''
|
||||
}
|
||||
</div>
|
||||
|
||||
{/* currentUser.id == item.creator_user.id && (
|
||||
<p className="fr mr10 orig_repll">
|
||||
<span id={`hidden_discuss_btn_${item.id}`}>
|
||||
<a href="javascript:void(0);" className="color-grey-8" onClick={ deleteComment.bind(this, item, index) } >
|
||||
<i className="far fa-trash-alt mr5"></i>删除
|
||||
</a>
|
||||
<span className="ml5 mr5 color-grey-8">|</span>
|
||||
</span>
|
||||
</p>
|
||||
)*/}
|
||||
</div>
|
||||
|
||||
<div className="comment_content clearfix" id={`reply_content_${item.id}`}>
|
||||
<div className="color-grey-3" id={`reply_content_${item.id}`}>
|
||||
{/* 改成后端返回了的,都是要显示的,不管hidden的值是true还是false */}
|
||||
|
||||
{/* { item.hidden && ((this.props.onlySuperAdminCouldHide && !item.isSuperAdmin)
|
||||
|| !this.props.onlySuperAdminCouldHide && item.admin === false && (item.manager === false || item.manager == undefined))
|
||||
? <p className="color-orange font-16">违规评论已被屏蔽!</p>
|
||||
: */}
|
||||
<div className={"break_word_comments markdown-body"} dangerouslySetInnerHTML={{__html: _content}}></div>
|
||||
{/* } */}
|
||||
<div className="cl"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="childrenCommentsView">
|
||||
{(item && item.children && item.children.length) ? <div className="trangle"></div>: ''}
|
||||
{this.renderChildenComments(item)}
|
||||
{ item.isAllChildrenLoaded != true && item.children && this.props.isChildCommentPagination == true && item.child_message_count > 5?
|
||||
<Tooltip title={ "点击查看更多回复" } disableFocusListener={true}>
|
||||
<div className="loadMoreChildComments" onClick={() => {this.props.loadMoreChildComments && this.props.loadMoreChildComments(item)}}>
|
||||
<i className="iconfont icon-xiajiantou"></i>
|
||||
</div>
|
||||
</Tooltip>
|
||||
: ''}
|
||||
</div>
|
||||
{/*mr10 */}
|
||||
<p className="fr orig_reply">
|
||||
<span id="hidden_discuss_btn_952">
|
||||
</span>
|
||||
|
||||
{/* && !item.reward */}
|
||||
{this.props.showRewardButton != false && item.admin === true ?
|
||||
<a href="javascript:void(0);" className="color-grey-8 fl mt2" onClick={() => this.showGoldRewardDialog(item) }>
|
||||
<Tooltip title={ "给TA奖励金币" } disableFocusListener={true}>
|
||||
<i className="iconfont icon-jiangli mr5 fl"></i>
|
||||
</Tooltip>
|
||||
</a>
|
||||
:""}
|
||||
|
||||
{ this.props.showHiddenButton == true
|
||||
&& (this.props.onlySuperAdminCouldHide && item.isSuperAdmin || !this.props.onlySuperAdminCouldHide && item.admin === true) ?
|
||||
<Tooltip title={ item.hidden ? "取消隐藏" : "隐藏评论" } disableFocusListener={true}>
|
||||
<a href="javascript:void(0);" className="color-grey-8 fl mt1" onClick={() => this.onCommentBtnClick(item, '', item.hidden ? 'hiddenCancel' : 'hidden') }>
|
||||
<i className={` ${item.hidden ? 'iconfont icon-yincangbiyan' : 'fa fa-eye'} mr5`}></i>
|
||||
</a>
|
||||
</Tooltip>
|
||||
:""}
|
||||
|
||||
|
||||
|
||||
{ item.admin && ( !item.children || item.children.length === 0 )?
|
||||
<a href="javascript:void(0);" className="color-grey-8" onClick={() => this.onCommentBtnClick(item, '', 'delete') }>
|
||||
<Tooltip title={ "删除" } disableFocusListener={true}>
|
||||
<i className="iconfont icon-shanchu mr5"></i>
|
||||
</Tooltip>
|
||||
</a> : '' }
|
||||
|
||||
{/* <span className="ml5 mr5 color-grey-8">|</span>*/}
|
||||
|
||||
{(this.props.showReply == undefined || this.props.showReply == true) && <a href={`javascript:void(0)`} className="color-grey-8"
|
||||
onClick={() => this.initReply(item) } >
|
||||
<Tooltip title={ "回复" }>
|
||||
<i className="iconfont icon-huifu1 mr5"></i>
|
||||
</Tooltip>
|
||||
</a>}
|
||||
|
||||
|
||||
{/* <span className="ml5 mr5 color-grey-8">|</span>*/}
|
||||
<span className="reply_praise_count_952">
|
||||
<Tooltip title={ item.user_praise ? "取消点赞" : "点赞" }>
|
||||
<a href={`javascript:void(0)`} className={`fr mr5 ${item.user_praise ? 'color-orange03' : 'color-grey-8'}`} onClick={()=>commentPraise(item.id)}>
|
||||
<i className={ item.user_praise ? "iconfont icon-dianzan mr3" : "iconfont icon-dianzan-xian mr3" }></i>
|
||||
|
||||
<span className="fr font-14" style={{ marginTop: '1px'}}>{item.praise_count?item.praise_count:''}</span>
|
||||
</a>
|
||||
</Tooltip>
|
||||
</span>
|
||||
</p>
|
||||
{/* __useKindEditor暂时没用到了,TODO 可以去掉 */}
|
||||
{ window.__useKindEditor ? <CommentItemKEEditor showReplyEditorFlag={showReplyEditorFlag}
|
||||
currentReplyComment={currentReplyComment}
|
||||
item={item}
|
||||
user={user}
|
||||
>
|
||||
</CommentItemKEEditor>
|
||||
:
|
||||
<CommentItemMDEditor showReplyEditorFlag={showReplyEditorFlag}
|
||||
currentReplyComment={currentReplyComment}
|
||||
item={item}
|
||||
user={user}
|
||||
buttonText={this.props.buttonText}
|
||||
>
|
||||
</CommentItemMDEditor>
|
||||
}
|
||||
{/* <div id={`reply_message_${item.id}`} className="reply_to_message"></div> */}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
/*
|
||||
/users/reply_to?reply_id=${item.id}&type=Challenge&user_activity_id=118
|
||||
*/
|
||||
/*
|
||||
onclick="delete_confirm_box_2('<%= discuss_path(comment, :challenge_id => @game_challenge) %>', '确定要删除该条回复吗?')"
|
||||
delete按钮
|
||||
id=`delete_reply_<%=@game_challenge.id %>_<%=comment.id %>`
|
||||
|
||||
*/
|
||||
return commentsElement;
|
||||
}
|
||||
|
||||
onCommentBtnClick(comment, childComment, dialogType) {
|
||||
this.comment = comment;
|
||||
this.childComment = childComment;
|
||||
this.setState({dialogOpen: true, dialogType: dialogType})
|
||||
}
|
||||
handleDialogClose() {
|
||||
this.setState({
|
||||
dialogOpen: false
|
||||
})
|
||||
}
|
||||
onDialogOkBtnClick = () => {
|
||||
|
||||
const { deleteComment, hiddenComment } = this.props;
|
||||
const { dialogType } = this.state;
|
||||
if (dialogType === 'delete') {
|
||||
deleteComment(this.comment, this.childComment ? this.childComment.id : '')
|
||||
} else if (dialogType === 'hidden' || dialogType === 'hiddenCancel' ) {
|
||||
hiddenComment(this.comment, this.childComment ? this.childComment.id : '')
|
||||
}
|
||||
|
||||
this.setState({dialogOpen: false})
|
||||
}
|
||||
|
||||
showGoldRewardDialog(comment, childComment) {
|
||||
if (comment.admin === true) {
|
||||
this.comment = comment;
|
||||
this.childComment = childComment;
|
||||
this.setState({goldRewardDialogOpen: true})
|
||||
}
|
||||
}
|
||||
handleGoldRewardDialogClose() {
|
||||
this.setState({
|
||||
goldRewardDialogOpen: false
|
||||
})
|
||||
}
|
||||
onGoldRewardDialogOkBtnClick() {
|
||||
console.log('onGoldRewardDialogOkBtnClick')
|
||||
const { goldRewardInput } = this.state;
|
||||
// || goldRewardInput.indexOf('-') !== -1
|
||||
if (!goldRewardInput || goldRewardInput === '0' ) {
|
||||
this.setState({ goldRewardInputError: true})
|
||||
return;
|
||||
} else {
|
||||
this.setState({goldRewardDialogOpen: false})
|
||||
this.props.rewardCode(this.comment, this.childComment, goldRewardInput)
|
||||
}
|
||||
}
|
||||
onGoldRewardInputChange(value) {
|
||||
// e.target.value
|
||||
const number = parseInt(value || 0, 10);
|
||||
if (Number.isNaN(number)) {
|
||||
return;
|
||||
}
|
||||
this.setState({ goldRewardInput: number, goldRewardInputError: false });
|
||||
}
|
||||
render() {
|
||||
const { deleteComment, onPaginationChange, comment_count_without_reply, currentPage, comments, usingAntdModal } = this.props;
|
||||
const { dialogOpen, goldRewardDialogOpen, dialogType, goldRewardInputError } = this.state;
|
||||
|
||||
const goldRewardInputErrorObj = goldRewardInputError ? {'error': 'error'} : {}
|
||||
|
||||
return (
|
||||
<div className="fit -scroll" style={{ 'overflow-x': 'hidden'}}>
|
||||
|
||||
|
||||
{ usingAntdModal ? <Modals
|
||||
modalsType={dialogOpen}
|
||||
modalsTopval={
|
||||
dialogType === 'delete' ? '确定要删除该条回复吗?'
|
||||
: dialogType === 'hidden' ? '确定要隐藏该条回复吗?'
|
||||
: dialogType === 'hiddenCancel' ? '确定要取消隐藏该条回复吗?' : ''
|
||||
}
|
||||
modalsBottomval={""}
|
||||
modalCancel={this.handleDialogClose}
|
||||
modalSave={this.onDialogOkBtnClick}
|
||||
>
|
||||
</Modals> :
|
||||
<Dialog
|
||||
open={dialogOpen}
|
||||
disableEscapeKeyDown={true}
|
||||
onClose={this.handleDialogClose}
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">{"提示"}</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText id="alert-dialog-description" style={{textAlign: 'center'}}>
|
||||
{
|
||||
dialogType === 'delete' ? '确定要删除该条回复吗?'
|
||||
: dialogType === 'hidden' ? '确定要隐藏该条回复吗?'
|
||||
: dialogType === 'hiddenCancel' ? '确定要取消隐藏该条回复吗?' : ''
|
||||
}
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={this.handleDialogClose} color="primary">
|
||||
取消
|
||||
</Button>
|
||||
<Button variant="raised"
|
||||
onClick={() => this.onDialogOkBtnClick() } color="primary" autoFocus>
|
||||
确定
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
}
|
||||
|
||||
<Dialog
|
||||
open={goldRewardDialogOpen}
|
||||
disableEscapeKeyDown={true}
|
||||
onClose={this.handleGoldRewardDialogClose}
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">{"奖励设置"}</DialogTitle>
|
||||
<DialogContent>
|
||||
|
||||
<InputNumber placeholder="请输入奖励的金币数量" id="goldReward" type="number" value={this.state.goldRewardInput}
|
||||
onChange={(e) => this.onGoldRewardInputChange(e)} width={228} style={{ width: '228px'}} />
|
||||
|
||||
{/* <FormControl { ...goldRewardInputErrorObj } aria-describedby="name-error-text">
|
||||
<InputLabel htmlFor="goldReward">请输入奖励的金币数量</InputLabel>
|
||||
<Input id="goldReward" type="number" value={this.state.goldRewardInput} onChange={(e) => this.onGoldRewardInputChange(e)} />
|
||||
{ goldRewardInputError ? <FormHelperText id="name-error-text">奖励金币不能为空或负数</FormHelperText> : ''}
|
||||
</FormControl> */}
|
||||
|
||||
{/*<DialogContentText id="alert-dialog-description" style={{textAlign: 'center'}}> </DialogContentText>*/}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={this.handleGoldRewardDialogClose} color="primary">
|
||||
取消
|
||||
</Button>
|
||||
<Button variant="raised"
|
||||
onClick={() => this.onGoldRewardDialogOkBtnClick() } color="primary" autoFocus>
|
||||
确定
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
|
||||
<div className="-layout-v -fit">
|
||||
<div className="panel-comment_item" >
|
||||
|
||||
{this.renderComments()}
|
||||
|
||||
</div>
|
||||
{ (comment_count_without_reply > 10 ) ?
|
||||
<div className="paginationSection">
|
||||
<Pagination showQuickJumper onChange={onPaginationChange} current={currentPage} total={comment_count_without_reply} />
|
||||
</div>
|
||||
: '' }
|
||||
{ (comment_count_without_reply == 0) ? <div>
|
||||
|
||||
<div className="edu-tab-con-box clearfix edu-txt-center">
|
||||
<img className="edu-nodata-img mb20"
|
||||
src={getImageUrl("images/educoder/nodata.png")} />
|
||||
<p className="edu-nodata-p mb20">暂时还没有相关数据哦!</p>
|
||||
</div>
|
||||
</div>
|
||||
: '' }
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Comments;
|
||||
@@ -0,0 +1,625 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import axios from 'axios'
|
||||
import { notification } from 'antd'
|
||||
import update from 'immutability-helper'
|
||||
|
||||
import ImageLayer from '../page/layers/ImageLayer'
|
||||
|
||||
const $ = window.$
|
||||
/* 需要的props:
|
||||
shixun
|
||||
id
|
||||
myshixun
|
||||
id
|
||||
challenge
|
||||
id
|
||||
user
|
||||
"image_url": user.image_url,
|
||||
"username": user.username,
|
||||
showSnackbar
|
||||
|
||||
*/
|
||||
/*
|
||||
这里提供props给WrappedComponent,用于封装特定的state和功能(评论列表)
|
||||
不要直接使用this.xxx调用WrappedComponent内的方法,尽量避免互相依赖,封装好后供不同场景使用(tpi、tpm)
|
||||
*/
|
||||
export function commentHOC(WrappedComponent) {
|
||||
// 这里如果extends WrappedComponent 会出现 WrappedComponent mount twice的问题
|
||||
return class II extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
// ------------------------------------
|
||||
this.createNewComment = this.createNewComment.bind(this)
|
||||
this.fetchCommentIfNotFetched = this.fetchCommentIfNotFetched.bind(this)
|
||||
this.replyComment = this.replyComment.bind(this)
|
||||
this.deleteComment = this.deleteComment.bind(this)
|
||||
this.commentPraise = this.commentPraise.bind(this)
|
||||
this.hiddenComment = this.hiddenComment.bind(this)
|
||||
this.rewardCode = this.rewardCode.bind(this)
|
||||
this.showNewReply = this.showNewReply.bind(this)
|
||||
this.newMessage = this.newMessage.bind(this)
|
||||
// ------------------------------------
|
||||
|
||||
this.onPaginationChange = this.onPaginationChange.bind(this)
|
||||
|
||||
this.state = {
|
||||
// 评论
|
||||
comments: [],
|
||||
comment_count_without_reply: 0,
|
||||
// 默认pageSize为10
|
||||
currentPage: 1,
|
||||
loadingComments: true,
|
||||
|
||||
// 图片最大化
|
||||
showImage: false,
|
||||
imageSrc: '',
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------评论 Start
|
||||
|
||||
// ----------------------------------------------------------------------------------------------评论 Start
|
||||
onPaginationChange(page) {
|
||||
this.fetchComment(page)
|
||||
this.setState({
|
||||
currentPage: page,
|
||||
});
|
||||
}
|
||||
/*
|
||||
email: "1843820944@qq.com"
|
||||
grade: 2138
|
||||
image_url: "avatar/User/36497"
|
||||
login: "p24891375"
|
||||
name: "杨俊男"
|
||||
user_url: "/users/p24891375"
|
||||
*/
|
||||
handleComments(comments, responseData) {
|
||||
comments.forEach(element => {
|
||||
if (element.children) {
|
||||
this.handleComments(element.children, responseData)
|
||||
}
|
||||
element.admin = responseData.all
|
||||
element.manager = element.manage
|
||||
|
||||
element.username = element.author.name
|
||||
element.user_login = element.author.login
|
||||
element.image_url = element.author.image_url
|
||||
element.user_id = element.author.user_id
|
||||
|
||||
});
|
||||
}
|
||||
responseDataParse(response) {
|
||||
const comments = response.data.comments
|
||||
this.handleComments(comments, response.data)
|
||||
}
|
||||
fetchComment(page = 1) {
|
||||
const { challenge, shixun, match } = this.props;
|
||||
// const url = `/api/v1/shixuns/${shixun.id}/shixun_discusses?page=${page-1}&container_type=Shixun`
|
||||
const url =
|
||||
`/discusses.json?page=${page-1}&container_identifier=${shixun && shixun.identifier ?
|
||||
shixun.identifier : match.params.shixunId}&container_type=Shixun`
|
||||
|
||||
this.setState({
|
||||
loadingComments: true,
|
||||
});
|
||||
|
||||
// test
|
||||
// if (true) {
|
||||
if (false) {
|
||||
var data = {"children_list":[{"id":1165,"content":"\u7535\u8111\u6ca1\u6709pi\u554a","time":"4\u5929\u524d","position":2,"user_id":31542,"reward":null,"image_url":"avatars/User/b","username":"\u8d75\u94f6\u7fd4","user_login":"p81572036","shixun_id":61,"hidden":false,"manager":false,"praise_count":0,"user_praise":false,"admin":false,"children":null},{"id":1142,"content":"\u6700\u540e\u4e00\u9898\u4e09\u5929\u6253\u9c7c\uff0c\u4e24\u5929\u6652\u7f51\uff0c\u4e0d\u5e94\u8be5\u662f1.01*1.01*1.01*0.99*0.99\uff0c\u800c\u4e0d\u662f\u52a0\u5417\uff1f","time":"4\u5929\u524d","position":1,"user_id":33714,"reward":null,"image_url":"avatars/User/b","username":"\u843d\u5c18","user_login":"p52769048","shixun_id":61,"hidden":false,"manager":false,"praise_count":0,"user_praise":false,"admin":false,"children":[{"content":"\u672c\u5173\u5e76\u6ca1\u6709\u5199\u5230\u201c<span style=\"color:#333333;font-family:"background-color:#FFFFFF;\">1.01*1.01*1.01*0.99*0.99</span>\u201d\uff0c\u4e0d\u77e5\u9053\u4f55\u6765\u6b64\u95ee\uff1f","time":"4\u5929\u524d","position":1,"reward":null,"image_url":"avatars/User/1","username":"Coder","user_id":1,"user_login":"innov","can_delete":false,"id":1144}]},{"id":1112,"content":"\u8fd9\u4e2a\u5b9e\u8bad\u5f88\u8d5e\uff01","time":"10\u5929\u524d","position":2,"user_id":12,"reward":null,"image_url":"avatars/User/12","username":"\u9ec4\u4e95\u6cc9","user_login":"Hjqreturn","shixun_id":61,"hidden":false,"manager":false,"praise_count":1,"user_praise":false,"admin":false,"children":null},{"id":1057,"content":"\u4e0d\u9519","time":"20\u5929\u524d","position":2,"user_id":30403,"reward":null,"image_url":"avatars/User/b","username":"Jimmy","user_login":"p69243850","shixun_id":61,"hidden":false,"manager":false,"praise_count":1,"user_praise":false,"admin":false,"children":null},{"id":975,"content":"q","time":"1\u4e2a\u6708\u524d","position":2,"user_id":30403,"reward":null,"image_url":"avatars/User/b","username":"Jimmy","user_login":"p69243850","shixun_id":61,"hidden":false,"manager":false,"praise_count":1,"user_praise":false,"admin":false,"children":[{"content":"\u4e0b\u6b21\u518d\u53d1\u65e0\u610f\u4e49\u7684\u5185\u5bb9\uff0c\u5c06\u88ab\u6263\u91d1\u5e01\u54e6","time":"1\u4e2a\u6708\u524d","position":2,"reward":null,"image_url":"avatars/User/1","username":"Coder","user_id":1,"user_login":"innov","can_delete":false,"id":980}]},{"id":974,"content":"k","time":"1\u4e2a\u6708\u524d","position":2,"user_id":30403,"reward":null,"image_url":"avatars/User/b","username":"Jimmy","user_login":"p69243850","shixun_id":61,"hidden":false,"manager":false,"praise_count":0,"user_praise":false,"admin":false,"children":[{"content":"\u4e0b\u6b21\u518d\u53d1\u65e0\u610f\u4e49\u7684\u5185\u5bb9\uff0c\u5c06\u88ab\u6263\u91d1\u5e01\u54e6","time":"1\u4e2a\u6708\u524d","position":2,"reward":null,"image_url":"avatars/User/1","username":"Coder","user_id":1,"user_login":"innov","can_delete":false,"id":981}]},{"id":859,"content":"\u5f88\u68d2\uff01\uff01\uff01","time":"1\u4e2a\u6708\u524d","position":4,"user_id":1,"reward":null,"image_url":"avatars/User/1","username":"Coder","user_login":"innov","shixun_id":61,"hidden":false,"manager":false,"praise_count":0,"user_praise":false,"admin":false,"children":null},{"id":802,"content":"\u4e0d\u9519\uff01","time":"2\u4e2a\u6708\u524d","position":1,"user_id":30403,"reward":null,"image_url":"avatars/User/b","username":"Jimmy","user_login":"p69243850","shixun_id":61,"hidden":false,"manager":false,"praise_count":1,"user_praise":false,"admin":false,"children":null},{"id":619,"content":"\u770b\u6765\u8001\u5e08\u5bf9\u9f50\u7528\u7684\u90fd\u662f\u7a7a\u683c","time":"5\u4e2a\u6708\u524d","position":3,"user_id":29145,"reward":null,"image_url":"avatars/User/b","username":"yang","user_login":"m02945638","shixun_id":61,"hidden":false,"manager":false,"praise_count":1,"user_praise":false,"admin":false,"children":null},{"id":553,"content":"<p>\r\n\t666\r\n</p>\r\n<p>\r\n\t<br />\r\n</p>","time":"6\u4e2a\u6708\u524d","position":4,"user_id":26838,"reward":null,"image_url":"avatars/User/b","username":"\u5189\u529b","user_login":"m54013296","shixun_id":61,"hidden":false,"manager":false,"praise_count":0,"user_praise":false,"admin":false,"children":null}],"disscuss_count":183}
|
||||
|
||||
this.setState({
|
||||
comments: data.children_list,
|
||||
comment_count_without_reply: data.disscuss_count,
|
||||
|
||||
currentPage: page,
|
||||
loadingComments: false,
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
axios.get(url,
|
||||
{
|
||||
// withCredentials: true
|
||||
}
|
||||
).then((response) => {
|
||||
// test
|
||||
|
||||
if (response.data) {
|
||||
this.responseDataParse(response)
|
||||
this.setState({
|
||||
comments: response.data.comments,
|
||||
comment_count_without_reply: response.data.disscuss_count,
|
||||
|
||||
currentPage: page,
|
||||
loadingComments: false,
|
||||
}, ()=>{
|
||||
// keditor代码美化
|
||||
window.prettyPrint()
|
||||
})
|
||||
}
|
||||
// console.log(response)
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
// 切换关卡时,清空state
|
||||
clearCommentsInState = () => {
|
||||
this.setState({ comments: [] })
|
||||
}
|
||||
fetchCommentIfNotFetched() {
|
||||
if (this.state.comments && this.state.comments.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// http://localhost:3000/api/v1/shixuns/cz7yw3en/shixun_discusses?page=0
|
||||
|
||||
this.fetchComment();
|
||||
}
|
||||
// 新增父级评论
|
||||
createNewComment() {
|
||||
console.log('createNewComment...')
|
||||
|
||||
const { challenge, shixun, showSnackbar } = this.props;
|
||||
let content = window._commentInput.html();
|
||||
if (!content || content.length === 0) {
|
||||
showSnackbar('必须填写内容!')
|
||||
return;
|
||||
}
|
||||
|
||||
// const url = `/api/v1/discusses`
|
||||
const url = `/discusses.json`
|
||||
|
||||
if(content != undefined){
|
||||
var beforeImage = content.split("<img");
|
||||
var afterImage = content.split("/>");
|
||||
if(beforeImage[0] == "" && afterImage[1] == ""){
|
||||
window.notice_box('不支持纯图片评论<br/>请在评论中增加文字信息');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$("#new_message_submit_btn_" + this.props.challenge.shixun_id).hide();
|
||||
|
||||
if (content) { // 去掉尾部的回车换行
|
||||
content = content.replace(/(\n<p>\n\t<br \/>\n<\/p>)*$/g,'');
|
||||
}
|
||||
|
||||
axios.post(url, {
|
||||
container_type: "Shixun",
|
||||
container_id: shixun.id,
|
||||
challenge_id: challenge.id,
|
||||
content,
|
||||
position: challenge.position
|
||||
},
|
||||
{
|
||||
// withCredentials: true
|
||||
}
|
||||
).then((response) => {
|
||||
if (response.data.discuss) {
|
||||
|
||||
window._commentInput.html('');
|
||||
window._commentInput.afterBlur()
|
||||
// this.setState({
|
||||
// runTesting: false,
|
||||
// })
|
||||
this.fetchComment()
|
||||
}
|
||||
console.log(response)
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
return true;
|
||||
}
|
||||
_findCommentById(id, arg_comments) {
|
||||
let comments;
|
||||
if (!arg_comments) {
|
||||
comments = this.state.comments;
|
||||
} else {
|
||||
comments = arg_comments;
|
||||
}
|
||||
for(let i = 0; i < comments.length; i++) {
|
||||
if (id === comments[i].id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
replyComment(commentContent, id, editor) {
|
||||
// http://localhost:3000/api/v1/discusses/812/reply
|
||||
const { challenge, shixun, user, showSnackbar, match } = this.props;
|
||||
|
||||
if (!commentContent || commentContent.length === 0) {
|
||||
showSnackbar('必须填写内容!')
|
||||
return;
|
||||
}
|
||||
// const url = `/api/v1/discusses/${id}/reply`
|
||||
const url = `/discusses/${id}/reply.json`
|
||||
if (commentContent) {
|
||||
commentContent = commentContent.replace(/(\n<p>\n\t<br \/>\n<\/p>)*$/g,'');
|
||||
}
|
||||
if (!user.login && user.user_url) {
|
||||
const loginAr = user.user_url.split('/')
|
||||
user.login = loginAr[loginAr.length - 1]
|
||||
}
|
||||
axios.post(url, {
|
||||
content: commentContent,
|
||||
// TODO
|
||||
"container_id": match.params.shixunId,
|
||||
"container_type": "Shixun",
|
||||
},
|
||||
{
|
||||
// withCredentials: true
|
||||
}
|
||||
).then((response) => {
|
||||
if (response.data.discuss) {
|
||||
let newDiscuss = response.data.discuss;
|
||||
let { comments } = this.state;
|
||||
var commentIndex = this._findCommentById(id);
|
||||
let comment = comments[commentIndex]
|
||||
comment = Object.assign({}, comment)
|
||||
if (!comment.children ) {
|
||||
comment.children = []
|
||||
} else {
|
||||
comment.children = comment.children.slice(0);
|
||||
}
|
||||
// TODO userName iamge_url
|
||||
comment.children.push( {
|
||||
"can_delete": true,
|
||||
"content": commentContent,
|
||||
|
||||
"image_url": user.image_url,
|
||||
"username": user.username,
|
||||
"user_login": user.login,
|
||||
"id": newDiscuss.id,
|
||||
"position": newDiscuss.position,
|
||||
"time": "1分钟前",
|
||||
"praise_count": newDiscuss.praise_count,
|
||||
|
||||
"user_id": newDiscuss.user_id,
|
||||
|
||||
})
|
||||
|
||||
comments = comments.slice(0)
|
||||
comments[commentIndex] = comment
|
||||
|
||||
// ke
|
||||
editor.html && editor.html('')
|
||||
// md
|
||||
if (editor.setValue) {
|
||||
editor.setValue('')
|
||||
const $ = window.$
|
||||
var view_selector = `.commentItemMDEditorView_${id}`
|
||||
$(view_selector).hide();
|
||||
}
|
||||
|
||||
|
||||
this.setState({
|
||||
// runTesting: false,
|
||||
comments: comments
|
||||
}, ()=>{
|
||||
// keditor代码美化
|
||||
editor.html && window.prettyPrint()
|
||||
})
|
||||
}
|
||||
console.log(response)
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
hiddenComment(item, childCommentId) {
|
||||
const id = item.id
|
||||
const { challenge, shixun, user, showSnackbar, match } = this.props;
|
||||
// const url = `/api/v1/discusses/${id}/hidden`
|
||||
const url = `/discusses/${id}/hidden.json`
|
||||
|
||||
const commentIndex = this._findCommentById(id);
|
||||
const { comments } = this.state;
|
||||
const comment = Object.assign({}, comments[commentIndex]);
|
||||
axios.post(url, {
|
||||
hidden: !comment.hidden ? "1" : "0",
|
||||
container_identifier: match.params.shixunId || shixun.identifier
|
||||
},
|
||||
{
|
||||
// withCredentials: true
|
||||
}
|
||||
).then((response) => {
|
||||
if (response.data.status === -1) {
|
||||
showSnackbar(response.data.message)
|
||||
return;
|
||||
}
|
||||
if (response.data.status === 1) {
|
||||
|
||||
if (!childCommentId) {
|
||||
comment.hidden = !comment.hidden;
|
||||
const commentsCopy = this.state.comments.slice(0)
|
||||
commentsCopy[commentIndex] = comment
|
||||
this.setState({
|
||||
comments: commentsCopy
|
||||
})
|
||||
} else { // TODO 目前子回复没hidden字段
|
||||
let childCommentIndex = this._findCommentById(childCommentId, comments[commentIndex].children);
|
||||
const childComment = comments[commentIndex].children[childCommentIndex]
|
||||
childComment.hidden = !childComment.hidden;
|
||||
this.setState({ comments })
|
||||
}
|
||||
|
||||
}
|
||||
// {"message":"Couldn't find Discuss with id=911","status":-1}
|
||||
console.log(response)
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
deleteComment(parrentComment, childCommentId) {
|
||||
const { challenge, shixun } = this.props;
|
||||
let deleteCommentId = parrentComment.id
|
||||
if (childCommentId) {
|
||||
deleteCommentId = childCommentId;
|
||||
}
|
||||
// const url = `/api/v1/discusses/${deleteCommentId}`
|
||||
const url = `/discusses/${deleteCommentId}.json`
|
||||
|
||||
axios.delete(url,
|
||||
{
|
||||
// withCredentials: true
|
||||
}
|
||||
).then((response) => {
|
||||
// TODO 删除成功或失败
|
||||
if (response.data && response.data.status === 1) {
|
||||
const commentIndex = this._findCommentById(parrentComment.id);
|
||||
|
||||
// https://stackoverflow.com/questions/29527385/removing-element-from-array-in-component-state
|
||||
if (!childCommentId) {
|
||||
this.setState((prevState) => ({
|
||||
comments: update(prevState.comments, {$splice: [[commentIndex, 1]]})
|
||||
}))
|
||||
|
||||
if (this.state.comments.length <= 5) {
|
||||
this.fetchComment()
|
||||
}
|
||||
} else {
|
||||
let comments = this.state.comments;
|
||||
let newComments = Object.assign({}, comments)
|
||||
let childCommentIndex = this._findCommentById(childCommentId, newComments[commentIndex].children);
|
||||
newComments[commentIndex].children = update(newComments[commentIndex].children, {$splice: [[childCommentIndex, 1]]})
|
||||
this.setState({ newComments })
|
||||
}
|
||||
}
|
||||
console.log(response)
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
rewardCode(parrentComment, childComment, amount) {
|
||||
const { challenge, shixun, showSnackbar } = this.props;
|
||||
let handleComment = parrentComment
|
||||
if (childComment) {
|
||||
handleComment = childComment;
|
||||
}
|
||||
let handleCommentId = handleComment.id;
|
||||
// const url = `/api/v1/discusses/${handleCommentId}/reward_code`
|
||||
const url = `/discusses/${handleCommentId}/reward_code.json`
|
||||
|
||||
axios.post(url, {
|
||||
// id: handleCommentId,
|
||||
|
||||
// container_id: shixun.id,
|
||||
container_type: 'Discusses',
|
||||
score: amount,
|
||||
user_id: handleComment.user_id
|
||||
},
|
||||
{
|
||||
// withCredentials: true
|
||||
}
|
||||
).then((response) => {
|
||||
if (response.data && response.data.code) {
|
||||
const commentIndex = this._findCommentById(parrentComment.id);
|
||||
let { comments } = this.state;
|
||||
const newComments = comments.slice(0)
|
||||
|
||||
if (childComment) {
|
||||
const childCommentIndex = this._findCommentById(handleComment.id, parrentComment.children);
|
||||
const newChildComment = Object.assign({}, childComment);
|
||||
newChildComment.reward = response.data.code
|
||||
parrentComment = Object.assign({}, parrentComment)
|
||||
parrentComment.children = parrentComment.children.slice(0)
|
||||
parrentComment.children[childCommentIndex] = newChildComment
|
||||
|
||||
newComments[commentIndex] = parrentComment;
|
||||
|
||||
|
||||
} else {
|
||||
const newComment = Object.assign({}, newComments[commentIndex]);
|
||||
newComment.reward = response.data.code;
|
||||
newComments[commentIndex] = newComment;
|
||||
}
|
||||
this.setState({
|
||||
comments: newComments
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
showSnackbar('奖励失败,请联系系统管理员!')
|
||||
})
|
||||
}
|
||||
|
||||
// 评论点赞
|
||||
commentPraise(discussId) {
|
||||
const commentIndex = this._findCommentById(discussId);
|
||||
const { comments } = this.state;
|
||||
|
||||
const { challenge } = this.props;
|
||||
// const url = `/api/v1/discusses/${discussId}/plus`
|
||||
const url = `/discusses/${discussId}/plus.json`
|
||||
axios.post(url, {
|
||||
// id: discussId,
|
||||
// container_id: challenge.id,
|
||||
container_type: 'Discuss', //Discuss
|
||||
type: comments[commentIndex].user_praise === true ? 0 : 1, // "踩0;赞1"
|
||||
},
|
||||
{
|
||||
// withCredentials: true
|
||||
}
|
||||
).then((response) => {
|
||||
if (response.data.praise_count === 0 || response.data.praise_count) {
|
||||
const newComments = comments.slice(0)
|
||||
const comment = Object.assign({}, newComments[commentIndex])
|
||||
comment.user_praise = !comment.user_praise;
|
||||
comment.praise_count = response.data.praise_count;
|
||||
newComments[commentIndex] = comment;
|
||||
this.setState({
|
||||
comments: newComments
|
||||
})
|
||||
}
|
||||
console.log(response)
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
newMessage() {
|
||||
return; // newMessage 暂时不用了
|
||||
const { shixun, myshixun } = this.props;
|
||||
const url = `/api/v1/shixuns/${shixun.id}/new_message?container_type=Shixun&myshixun_id=${myshixun.id}`
|
||||
// this.setState({
|
||||
// gotNewReply: true
|
||||
// })
|
||||
axios.get(url,
|
||||
{
|
||||
// withCredentials: true
|
||||
}
|
||||
).then((response) => {
|
||||
const new_message = response.data.new_message;
|
||||
if (response.data.new_message) {
|
||||
this.setState({
|
||||
gotNewReply: new_message
|
||||
})
|
||||
}
|
||||
// console.log(response)
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
showNewReply() {
|
||||
const { shixun, myshixun } = this.props;
|
||||
const commentId = 929 // TODO
|
||||
const url = `/api/v1/shixuns/${shixun.id}/anchor?container_type=Shixun&myshixun_id=${myshixun.id}&discuss_id=${commentId}`
|
||||
|
||||
this.setState({
|
||||
loadingComments: true,
|
||||
gotNewReply: false,
|
||||
|
||||
});
|
||||
axios.get(url,
|
||||
{
|
||||
// withCredentials: true
|
||||
}
|
||||
).then((response) => {
|
||||
const data = response.data;
|
||||
const new_message = data.new_message;
|
||||
|
||||
this.setState({
|
||||
comments: data.children_list,
|
||||
comment_count_without_reply: data.disscuss_count,
|
||||
|
||||
currentPage: data.page,
|
||||
loadingComments: false,
|
||||
|
||||
}, () => {
|
||||
if (response.data.find_status) { // 没找到评论的话,默认会返回第一页的评论
|
||||
const comment_J = window.$(`#reply_content_${commentId}`);
|
||||
if (comment_J.length) {
|
||||
comment_J[0].scrollIntoView()
|
||||
comment_J.parents('.comment_item_cont').css('border', '1px solid #4CACFF')
|
||||
}
|
||||
}
|
||||
})
|
||||
console.log(response)
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------------评论 End
|
||||
|
||||
// ----------------------------------------------------------------------------------------------评论 End
|
||||
|
||||
componentDidMount() {
|
||||
// commentsDelegateParent #game_left_contents #tab_con_4
|
||||
$(".commentsDelegateParent")
|
||||
.delegate(".J_Comment_Reply .comment_content img, .J_Comment_Reply .childrenCommentsView img","click", (event) => {
|
||||
|
||||
const imageSrc = event.target.src
|
||||
// 非回复里的头像图片; 非emoticons
|
||||
if (imageSrc.indexOf('/images/avatars/User') === -1 &&
|
||||
imageSrc.indexOf('kindeditor/plugins/emoticons') === -1 ) {
|
||||
this.setState({
|
||||
showImage: true,
|
||||
imageSrc,
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
onImageLayerClose = () => {
|
||||
this.setState({
|
||||
showImage: false,
|
||||
imageSrc: '',
|
||||
})
|
||||
}
|
||||
|
||||
showNotification = (description, message = "提示", icon) => {
|
||||
const data = {
|
||||
message,
|
||||
description
|
||||
}
|
||||
if (icon) {
|
||||
data.icon = icon;
|
||||
}
|
||||
notification.open(data);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<ImageLayer {...this.state} onImageLayerClose={this.onImageLayerClose}></ImageLayer>
|
||||
|
||||
<WrappedComponent {...this.props} {...this.state}
|
||||
createNewComment={this.createNewComment}
|
||||
fetchCommentIfNotFetched={this.fetchCommentIfNotFetched}
|
||||
clearCommentsInState={this.clearCommentsInState}
|
||||
replyComment={this.replyComment}
|
||||
deleteComment={this.deleteComment}
|
||||
commentPraise={this.commentPraise}
|
||||
hiddenComment={this.hiddenComment}
|
||||
rewardCode={this.rewardCode}
|
||||
onPaginationChange={this.onPaginationChange}
|
||||
showNotification= { this.showNotification }
|
||||
newMessage={this.newMessage}
|
||||
showNewReply={this.showNewReply}
|
||||
></WrappedComponent>
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
<div>
|
||||
<h2>
|
||||
HOC Debugger Component
|
||||
</h2>
|
||||
<p>
|
||||
Props
|
||||
</p>
|
||||
<pre>{stringify(this.props)}</pre>
|
||||
<p>
|
||||
State
|
||||
</p>
|
||||
<pre>{stringify(this.state)}</pre>
|
||||
{super.render()}
|
||||
</div>
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,202 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import ieImg from './imgs/internet-explorer@2x.png'
|
||||
import chromeImg from './imgs/google-chrome@2x.png'
|
||||
import ffImg from './imgs/firefox_icon.png'
|
||||
|
||||
import bannerImg from './imgs/icon@2x.png'
|
||||
|
||||
|
||||
import { TPMIndexHOC } from '..//tpm/TPMIndexHOC';
|
||||
|
||||
class CompatibilityPage extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
onGoldRewardInputChange(event) {
|
||||
this.setState({ goldRewardInput: event.target.value, goldRewardInputError: false });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { goldRewardDialogOpen } = this.props;
|
||||
const { goldRewardInputError } = this.state;
|
||||
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<style>{`
|
||||
.Header {
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 3px 4px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.Header-inner {
|
||||
width: 1008px;
|
||||
margin: 0 auto;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.Header-logo {
|
||||
width: 64px;
|
||||
height: 30px;
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.Header-logo img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.Compatibility {
|
||||
margin-top: 60px;
|
||||
background: #fff;
|
||||
width: 1008px;
|
||||
margin: 0 auto;
|
||||
padding: 16px;
|
||||
margin-bottom: 220px;
|
||||
}
|
||||
|
||||
.Compatibility-icon {
|
||||
width: 112px;
|
||||
height: 83px;
|
||||
margin: 64px auto;
|
||||
}
|
||||
|
||||
.Compatibility-icon img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.Compatibility-tip {
|
||||
font-size: 24px;
|
||||
@mixin bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.CompatibilityBrowsers {
|
||||
overflow: hidden;
|
||||
margin-top: 64px;
|
||||
}
|
||||
|
||||
.CompatibilityBrowsers-item {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 33%;
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
a.CompatibilityBrowsers-item {
|
||||
text-decoration: none;
|
||||
color: #3e7ac2;
|
||||
}
|
||||
|
||||
.CompatibilityBrowsers-divider {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 24px;
|
||||
height: 64px;
|
||||
border-right: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.CompatibilityBrowsers-icon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.CompatibilityBrowsers-icon img {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.CompatibilityBrowsers-ieIcon img {
|
||||
width: 88px;
|
||||
height: 81px;
|
||||
margin-left: -8px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.CompatibilityBrowsers-chromeIcon img {
|
||||
width: 83px;
|
||||
height: 83px;
|
||||
margin: -1.5px;
|
||||
}
|
||||
|
||||
.CompatibilityBrowsers-text {
|
||||
margin-top: 32px;
|
||||
text-align: center;
|
||||
}
|
||||
`}</style>
|
||||
|
||||
{/* <div className="Header">
|
||||
<div className="Header-inner">
|
||||
<div className="Header-logo">
|
||||
<img src="https://testeduplus2.educoder.net/images/educoder/headNavLogo.png?1526520218"
|
||||
></img>
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
<div className="Compatibility">
|
||||
|
||||
<div className="Compatibility-icon">
|
||||
<img src={ bannerImg }
|
||||
></img>
|
||||
</div>
|
||||
<div className="Compatibility-tip">你正在使用的浏览器版本过低,将不能正常浏览和使用Educoder。</div>
|
||||
<div className="CompatibilityBrowsers">
|
||||
|
||||
{/* https://www.google.cn/intl/zh-CN/chrome/ */}
|
||||
{/* <a href="http://www.google.com/chrome/" className="CompatibilityBrowsers-item">
|
||||
|
||||
srcset="/compatibility/images/internet-explorer.png 1x, /compatibility/images/internet-explorer@2x.png 2x, /compatibility/images/internet-explorer@3x.png 3x"
|
||||
srcset="/compatibility/images/google-chrome.png 1x, /compatibility/images/google-chrome@2x.png 2x, /compatibility/images/google-chrome@3x.png 3x"
|
||||
*/}
|
||||
<a href="https://www.google.cn/intl/zh-CN/chrome/" className="CompatibilityBrowsers-item"
|
||||
target="_blank">
|
||||
<div className="CompatibilityBrowsers-icon CompatibilityBrowsers-chromeIcon">
|
||||
<img src={ chromeImg }
|
||||
>
|
||||
</img>
|
||||
</div>
|
||||
<div className="CompatibilityBrowsers-text">使用 Google Chrome 浏览器</div>
|
||||
<div className="CompatibilityBrowsers-divider"></div>
|
||||
</a>
|
||||
|
||||
<a href="http://www.firefox.com.cn/" className="CompatibilityBrowsers-item"
|
||||
target="_blank">
|
||||
<div className="CompatibilityBrowsers-icon CompatibilityBrowsers-ieIcon">
|
||||
<img src={ ffImg }
|
||||
|
||||
>
|
||||
</img>
|
||||
</div>
|
||||
<div className="CompatibilityBrowsers-text">使用 Firefox 浏览器</div>
|
||||
<div className="CompatibilityBrowsers-divider"></div>
|
||||
</a>
|
||||
|
||||
<a href="https://www.microsoft.com/zh-cn/download/internet-explorer.aspx" className="CompatibilityBrowsers-item"
|
||||
target="_blank">
|
||||
<div className="CompatibilityBrowsers-icon CompatibilityBrowsers-ieIcon">
|
||||
<img src={ ieImg }
|
||||
|
||||
>
|
||||
</img>
|
||||
</div>
|
||||
<div className="CompatibilityBrowsers-text">升级 IE 浏览器</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TPMIndexHOC ( CompatibilityPage );
|
||||
@@ -0,0 +1,105 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import Dialog, {
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
DialogTitle,
|
||||
} from 'material-ui/Dialog';
|
||||
import Button from 'material-ui/Button';
|
||||
import { FormControl, FormHelperText } from 'material-ui/Form';
|
||||
import Input, { InputLabel } from 'material-ui/Input';
|
||||
import { InputNumber } from 'antd'
|
||||
|
||||
|
||||
|
||||
class RewardDialog extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.handleGoldRewardDialogClose = this.handleGoldRewardDialogClose.bind(this)
|
||||
|
||||
this.state = {
|
||||
// goldRewardDialogOpen: false,
|
||||
goldRewardInput: '',
|
||||
}
|
||||
}
|
||||
|
||||
showGoldRewardDialog(comment, childComment) {
|
||||
if (comment.admin === true) {
|
||||
this.comment = comment;
|
||||
this.childComment = childComment;
|
||||
this.setState({goldRewardDialogOpen: true})
|
||||
}
|
||||
}
|
||||
|
||||
handleGoldRewardDialogClose() {
|
||||
this.props.setRewardDialogVisible(false)
|
||||
}
|
||||
onGoldRewardDialogOkBtnClick() {
|
||||
console.log('onGoldRewardDialogOkBtnClick')
|
||||
const { goldRewardInput } = this.state;
|
||||
if (!goldRewardInput || goldRewardInput === '0' || goldRewardInput < 0) {
|
||||
this.props.showNotification('奖励金币不能为空或负数')
|
||||
// this.setState({ goldRewardInputError: true})
|
||||
return;
|
||||
} else {
|
||||
this.props.setRewardDialogVisible( false )
|
||||
this.props.rewardCode(goldRewardInput)
|
||||
}
|
||||
}
|
||||
onGoldRewardInputChange(value) {
|
||||
// || event.target.value
|
||||
const number = parseInt(value || 0, 10);
|
||||
if (Number.isNaN(number)) {
|
||||
return;
|
||||
}
|
||||
this.setState({ goldRewardInput: number , goldRewardInputError: false });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { goldRewardDialogOpen } = this.props;
|
||||
const { goldRewardInputError } = this.state;
|
||||
const goldRewardInputErrorObj = goldRewardInputError ? {'error': 'error'} : {}
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={goldRewardDialogOpen}
|
||||
disableEscapeKeyDown={true}
|
||||
onClose={this.handleGoldRewardDialogClose}
|
||||
className={'rewardDialog'}
|
||||
>
|
||||
<style>{`
|
||||
.rewardDialog>div:last-child {
|
||||
width: 280px;
|
||||
}
|
||||
`}</style>
|
||||
<DialogTitle id="alert-dialog-title">{"奖励设置"}</DialogTitle>
|
||||
<DialogContent>
|
||||
|
||||
{/* <FormControl { ...goldRewardInputErrorObj } aria-describedby="name-error-text"> */}
|
||||
{/* <InputLabel htmlFor="goldReward">请输入奖励的金币数量</InputLabel>
|
||||
<Input id="goldReward" type="number" value={this.state.goldRewardInput} onChange={(e) => this.onGoldRewardInputChange(e)} />
|
||||
{ goldRewardInputError ? <FormHelperText id="name-error-text">奖励金币不能为空或负数</FormHelperText> : ''} */}
|
||||
|
||||
<InputNumber placeholder="请输入奖励的金币数量" id="goldReward" type="number" value={this.state.goldRewardInput}
|
||||
onChange={(e) => this.onGoldRewardInputChange(e)} width={228} style={{ width: '228px'}} />
|
||||
{/* </FormControl> */}
|
||||
|
||||
{/*<DialogContentText id="alert-dialog-description" style={{textAlign: 'center'}}> </DialogContentText>*/}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={this.handleGoldRewardDialogClose} color="primary">
|
||||
取消
|
||||
</Button>
|
||||
<Button variant="raised"
|
||||
onClick={() => this.onGoldRewardDialogOkBtnClick() } color="primary" autoFocus>
|
||||
确定
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default RewardDialog;
|
||||
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 22 KiB |
@@ -0,0 +1,163 @@
|
||||
import React, {Component} from 'react';
|
||||
import competition from './comcss/competition.css';
|
||||
import {getImageUrl} from 'educoder';
|
||||
// 团队竞赛报名大图
|
||||
class CompetitionMaxImg extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
GetenrollmentAPI: undefined
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
}
|
||||
|
||||
componentDidUpdate = (prevProps) => {
|
||||
if (prevProps.GetenrollmentAPI != this.props.GetenrollmentAPI) {
|
||||
this.setState({
|
||||
GetenrollmentAPI: this.props.GetenrollmentAPI,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let {type, pint} = this.props;
|
||||
return (
|
||||
<div>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
|
||||
`
|
||||
}
|
||||
</style>
|
||||
{
|
||||
type === 1 || type === 2 ?
|
||||
<div className="registrationback"
|
||||
style={{"background": `url(${getImageUrl(`images/educoder/competitions/tipregistit.jpg`)})`}}
|
||||
>
|
||||
<p className="registrationbackp1">在线竞赛平台</p>
|
||||
<p className="registrationbackp2">在线竞赛平台是一个面向计算机类的互联网IT教育和实战平台,</p>
|
||||
<p className="registrationbackp3">提供企业级工程实训,以实现工程化专业教学的自动化和智能化。</p>
|
||||
<div className="registrationbackp2button">
|
||||
<div className="registbut1">
|
||||
<p onClick={() => this.props.Jointheteam()}>加入战队</p>
|
||||
</div>
|
||||
<div className="registbut2">
|
||||
<p onClick={() => this.props.Createateam()}>创建战队</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
type === 3 ?
|
||||
|
||||
<div className="registrationback"
|
||||
style={{"background": `url(${getImageUrl(`images/educoder/competitions/tipregistit.jpg`)})`}}
|
||||
>
|
||||
<p className="registrationbackp1">在线竞赛平台</p>
|
||||
<p className="registrationbackp2">在线竞赛平台是一个面向计算机类的互联网IT教育和实战平台,</p>
|
||||
<p className="registrationbackp3">提供企业级工程实训,以实现工程化专业教学的自动化和智能化。</p>
|
||||
<div className="registrationbackp2button">
|
||||
<div className="registbut1">
|
||||
<p onClick={() => this.props.Jointheteam()}>加入战队</p>
|
||||
</div>
|
||||
<div className="registbut2">
|
||||
<p onClick={() => this.props.Createateam()}>创建战队</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
type === 4 || type === 5 ?
|
||||
|
||||
<div className="registrationback"
|
||||
style={{"background": `url(${getImageUrl(`images/educoder/competitions/tipregistit.jpg`)})`}}
|
||||
>
|
||||
<p className="registrationbackp1">在线竞赛平台</p>
|
||||
<p className="registrationbackp2">在线竞赛平台是一个面向计算机类的互联网IT教育和实战平台,</p>
|
||||
<p className="registrationbackp3">提供企业级工程实训,以实现工程化专业教学的自动化和智能化。</p>
|
||||
<div className="registrationbackp2button">
|
||||
<div className="registbut1">
|
||||
<p onClick={() => this.props.Jointheteam()}>加入战队</p>
|
||||
</div>
|
||||
<div className="registbut2">
|
||||
<p onClick={() => this.props.Createateam()}>创建战队</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
: type === 6 ?
|
||||
<div className="registrationback"
|
||||
style={{"background": `url(${getImageUrl(`images/educoder/competitions/tipregistit.jpg`)})`}}>
|
||||
<p className="registrationbackp1">在线竞赛平台</p>
|
||||
<p className="registrationbackp2">在线竞赛平台是一个面向计算机类的互联网IT教育和实战平台,</p>
|
||||
<p className="registrationbackp3">提供企业级工程实训,以实现工程化专业教学的自动化和智能化。</p>
|
||||
<div className="registrationbackp2button">
|
||||
{
|
||||
pint === 1 ?
|
||||
<div className="registbut1" onClick={() => this.props.Personalregistration()}>
|
||||
<p onClick={() => this.props.Personalregistration()}>立即报名</p>
|
||||
</div>
|
||||
: pint === 2 ?
|
||||
<div className="personreg1">
|
||||
<p>已报名</p>
|
||||
</div>
|
||||
:
|
||||
<div className="personreg1">
|
||||
<p>报名已截止</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<div className="registrationback"
|
||||
style={{"background": `url(${getImageUrl(`images/educoder/competitions/tipregistit.jpg`)})`}}>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CompetitionMaxImg;
|
||||
|
||||
// // type3
|
||||
// /*<div className="registrationback"*/
|
||||
// /* style={{"background": `url(${getImageUrl(`images/educoder/competitions/tipregistit.jpg`)})`}}>*/
|
||||
// /* <p className="registrationbackp1">Educoder竞赛平台</p>*/
|
||||
// /* <p className="registrationbackp4">高校智能课堂与综合实训平台</p>*/
|
||||
// /* <div className="registrationbackp2button2">*/
|
||||
// /* <div className="registbut11">*/
|
||||
// /* <p onClick={() => this.props.Jointheteam()}>加入战队</p>*/
|
||||
// /* </div>*/
|
||||
// /* <div className="registbut22">*/
|
||||
// /* <p onClick={() => this.props.Createateam()}>创建战队</p>*/
|
||||
// /* </div>*/
|
||||
//
|
||||
// /* </div>*/
|
||||
// /*</div>*/
|
||||
//
|
||||
//
|
||||
// // type === 4 || type === 5
|
||||
// // <div className="registrationback1"
|
||||
// // style={{"background": `url(${getImageUrl(`images/educoder/competitions/tipregistit.jpg`)})`}}>
|
||||
// // <p className="registrationbackp11">Educoder竞赛平台</p>
|
||||
// // <p className="registrationbackp22">高校智能课堂与综合实训平台</p>
|
||||
// // <div className="registrationbackp2button3">
|
||||
// // <div className="registbut111">
|
||||
// // <p onClick={() => this.props.Jointheteam()}>加入战队</p>
|
||||
// // </div>
|
||||
// // <div className="registbut222">
|
||||
// // <p onClick={() => this.props.Createateam()}>创建战队</p>
|
||||
// // </div>
|
||||
// //
|
||||
// // </div>
|
||||
// // </div>
|
||||
@@ -0,0 +1,50 @@
|
||||
import React, {Component} from 'react';
|
||||
import {
|
||||
BrowserRouter as Router,
|
||||
Route,
|
||||
Switch
|
||||
} from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
import moment from 'moment';
|
||||
import competition from './comcss/competition.css';
|
||||
import {Checkbox, Table, Pagination, Menu, Icon} from "antd";
|
||||
import {getImageUrl} from 'educoder';
|
||||
// 团队竞赛报名无报名子组件团队 在线竞赛 > 全国高校计算机大赛-项目挑战>
|
||||
class RegisListview extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="reglistviewdivs">
|
||||
<div className="reglistviewdivss " style={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: " space-around",
|
||||
alignItems: "center",
|
||||
background: `url(${getImageUrl(`images/educoder/competitions/Rectanglex.png`)})`,
|
||||
height: "50px",
|
||||
backgroundPosition: "center",
|
||||
backgroundSize: "110% 100%",
|
||||
}}>
|
||||
<p className=" "
|
||||
style={{fontSize: "16px", color: "#05101A", width: "79px", textAlign: "center"}}>创建者</p>
|
||||
<p className=" "
|
||||
style={{fontSize: "16px", color: "#05101A", width: "160px", textAlign: "center"}}>战队名称</p>
|
||||
<p className=" "
|
||||
style={{fontSize: "16px", color: "#05101A", width: "487px", textAlign: "center"}}>战队成员</p>
|
||||
<p className=" "
|
||||
style={{fontSize: "16px", color: "#05101A", width: "134px", textAlign: "center"}}>学校</p>
|
||||
<p className=" "
|
||||
style={{fontSize: "16px", color: "#05101A", width: "151px", textAlign: "center"}}>时间</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RegisListview;
|
||||
@@ -0,0 +1,170 @@
|
||||
import React, {Component} from 'react';
|
||||
import {
|
||||
BrowserRouter as Router,
|
||||
Route,
|
||||
Switch
|
||||
} from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
import moment from 'moment';
|
||||
import {SnackbarHOC, WordsBtn, getImageUrl} from 'educoder';
|
||||
import {TPMIndexHOC} from '../tpm/TPMIndexHOC';
|
||||
import competition from './comcss/competition.css';
|
||||
import {Button} from 'antd';
|
||||
|
||||
// 团队竞赛报名无报名子组件团队 竞赛报名-已创建战队
|
||||
class RegisListviewdata extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
item: undefined
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
////console.log("RegisListviewdata");
|
||||
////console.log(this.props.item)
|
||||
this.setState({
|
||||
item: this.props.item
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
getotiku = (url) => {
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
|
||||
render() {
|
||||
const {item} = this.props;
|
||||
return (
|
||||
|
||||
<div>
|
||||
{
|
||||
item !== undefined ?
|
||||
<div className={"yslborderbottom"}>
|
||||
<div className="regitem22">
|
||||
|
||||
<div className="regitemimg1 ">
|
||||
<img className="regitemimg2" src={getImageUrl("images/" + item.creator.image_url)}>
|
||||
|
||||
</img>
|
||||
<a className="maxnamewidth78" title={item.creator.name} style={{
|
||||
color: "#999999", fontSize: "14px",
|
||||
width: "78px",
|
||||
textAlign: "center"
|
||||
}}>{item.creator.name}</a>
|
||||
</div>
|
||||
<div style={{
|
||||
marginTop: "29px",
|
||||
marginLeft: "37px",
|
||||
width: "160px",
|
||||
textAlign: "center",
|
||||
}} className="textsize maxnamewidth160">
|
||||
{
|
||||
this.props.admin?
|
||||
this.props.admin===true?
|
||||
<a className="maxnamewidth160" title={item.name} style={{
|
||||
fontSize: "16px",
|
||||
width: "160px",
|
||||
textAlign: "center",
|
||||
cursor:"pointer"
|
||||
}}
|
||||
onClick={()=>this.getotiku(`/competitions/${this.props.match.params.identifier}/competition_teams/${item.id}`)}
|
||||
>{item.name}</a>
|
||||
: <p className="maxnamewidth160" style={{
|
||||
color: "#05101A",
|
||||
fontSize: "16px",
|
||||
width: "160px",
|
||||
textAlign: "center"
|
||||
}}>{item.name}</p>
|
||||
: <p className="maxnamewidth160" style={{
|
||||
color: "#05101A",
|
||||
fontSize: "16px",
|
||||
width: "160px",
|
||||
textAlign: "center"
|
||||
}}>{item.name}</p>
|
||||
}
|
||||
</div>
|
||||
<div style={{
|
||||
marginLeft: "37px",
|
||||
display: "flex",
|
||||
flexDirection: "initial",
|
||||
width: "487px"
|
||||
}}>
|
||||
|
||||
{
|
||||
item && item.team_members.map((item, index) => {
|
||||
return (
|
||||
|
||||
index === 0 ?
|
||||
<img className="regitemimgs" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 1 ?
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 2 ?
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 3 ?
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 4 ?
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 5 ?
|
||||
<div>
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
<img className="regitemimgs22"
|
||||
src={getImageUrl(`images/educoder/competitions/pexjiazai.png`)}>
|
||||
</img>
|
||||
</div>
|
||||
: ""
|
||||
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
<div style={{
|
||||
marginLeft: "41px",
|
||||
width: "134px",
|
||||
marginTop: "29px",
|
||||
textAlign: "center",
|
||||
}} className="maxnamewidth134">
|
||||
<a className="maxnamewidth134" title={item.school_name} style={{
|
||||
color: "#05101A",
|
||||
fontSize: "16px",
|
||||
textAlign: "center"
|
||||
}}>{item.school_name}</a>
|
||||
</div>
|
||||
<div style={{
|
||||
marginLeft: "37px",
|
||||
width: "151px",
|
||||
marginTop: "29px",
|
||||
|
||||
}}>
|
||||
<p style={{
|
||||
color: "#999999",
|
||||
fontSize: "16px",
|
||||
textAlign: "center"
|
||||
}}>{item.created_at}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RegisListviewdata;
|
||||
@@ -0,0 +1,34 @@
|
||||
import React, {Component} from 'react';
|
||||
import competition from './comcss/competition.css';
|
||||
import {getImageUrl} from 'educoder';
|
||||
// 团队竞赛报名无报名子组件
|
||||
class RegisNodata extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="bootom">
|
||||
<div className="bootomimg" style={{
|
||||
height: "80px",
|
||||
width: "125px",
|
||||
marginTop: "107px",
|
||||
background: `url(${getImageUrl(`images/educoder/competitions/Noentry.jpg`)})`,
|
||||
backgroundPosition: "center",
|
||||
backgroundSize: "110% 100%",
|
||||
}}>
|
||||
|
||||
</div>
|
||||
<p className="bootomtext">暂无战队参与报名哦,赶紧来成为第一个挑战的吧~</p>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RegisNodata;
|
||||
@@ -0,0 +1,75 @@
|
||||
import React, {Component} from 'react';
|
||||
import {
|
||||
BrowserRouter as Router,
|
||||
Route,
|
||||
Switch
|
||||
} from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
import moment from 'moment';
|
||||
import competition from './comcss/competition.css';
|
||||
import {Checkbox, Input, Table, Pagination, Menu, Icon} from "antd";
|
||||
|
||||
const Search = Input.Search;
|
||||
|
||||
// 团队竞赛报名无报名子组件团队 在线竞赛 > 全国高校计算机大赛-项目挑战>
|
||||
class RegistrationSearch extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
keywords: ""
|
||||
}
|
||||
}
|
||||
|
||||
setdatafunsval = (e) => {
|
||||
this.setState({
|
||||
keywords: e.target.value
|
||||
})
|
||||
|
||||
};
|
||||
setdatafuns = (value) => {
|
||||
//console.log("setdatafuns点击了搜索");
|
||||
//console.log(value);
|
||||
this.setState({
|
||||
keywords: value
|
||||
})
|
||||
this.props.RegistrationSearchvalue(value);
|
||||
};
|
||||
|
||||
myonPressEnter = (e) => {
|
||||
//console.log("点击了回车setdatafunsval点击了搜索");
|
||||
//console.log(e.target.value);
|
||||
this.props.RegistrationSearchvalue(e.target.value);
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div className="searchhead">
|
||||
|
||||
<Search
|
||||
className="packinputs"
|
||||
value={this.state.keywords}
|
||||
enterButton={<span>搜索</span>}
|
||||
onInput={(e) => this.setdatafunsval(e)}
|
||||
onSearch={(value) => this.setdatafuns(value)}
|
||||
onPressEnter={(e) => this.myonPressEnter(e)}
|
||||
/>
|
||||
|
||||
<p style={{
|
||||
width: "583px",
|
||||
color: "#07140E",
|
||||
fontSize: '16px',
|
||||
marginTop: " 7px",
|
||||
marginLeft: "300px",
|
||||
textAlign: "right",
|
||||
lineHeight: " 24px"
|
||||
}}>战队总数:<span
|
||||
style={{color: "#459BE5", fontSize: "16px"}}>{this.props.count}</span><span
|
||||
style={{marginLeft: "5px", marginRight: "15px",}}>个</span> 参赛总人数:<span
|
||||
style={{color: "#459BE5"}}>{this.props.members_count}</span><span
|
||||
style={{marginLeft: "5px"}}>人</span></p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RegistrationSearch;
|
||||
@@ -0,0 +1,84 @@
|
||||
import React, {Component} from 'react';
|
||||
import {
|
||||
BrowserRouter as Router,
|
||||
Route,
|
||||
Switch
|
||||
} from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
import moment from 'moment';
|
||||
import {SnackbarHOC, WordsBtn, getImageUrl} from 'educoder';
|
||||
import {TPMIndexHOC} from '../tpm/TPMIndexHOC';
|
||||
import competition from './comcss/competition.css';
|
||||
import {Button} from 'antd';
|
||||
import RegisListviewdata from "./RegisListviewdata";
|
||||
|
||||
// 团队竞赛报名无报名子组件团队 竞赛报名-已创建战队
|
||||
class Registrationitem extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
let {item} = this.props;
|
||||
return (
|
||||
<div className="yslborderbottom">
|
||||
{
|
||||
item !== undefined ?
|
||||
<div className="regitem2">
|
||||
<div className="perregitemimg1 ">
|
||||
<img className="personregitemimg" src={getImageUrl("images/" + item.creator.image_url)}>
|
||||
|
||||
</img>
|
||||
</div>
|
||||
<div className="" style={{
|
||||
marginTop: "19px",
|
||||
marginLeft: "54px",
|
||||
display: "flex",
|
||||
flexDirection: "initial",
|
||||
}}>
|
||||
<p className="" style={{
|
||||
color: "#05101A",
|
||||
fontSize: "16px",
|
||||
width: "160px",
|
||||
textAlign: "center"
|
||||
}}>{item.creator.name}</p>
|
||||
{
|
||||
item.manage_permission === true ?
|
||||
<p className="" style={{
|
||||
color: "#459BE5",
|
||||
fontSize: "16px",
|
||||
textAlign: "center",
|
||||
marginLeft: "25px",
|
||||
}}>已报名</p>
|
||||
:
|
||||
""
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
<div className="" style={{
|
||||
marginLeft: "632px",
|
||||
width: "151px",
|
||||
marginTop: "19px",
|
||||
marginRight: "35px",
|
||||
}}>
|
||||
<p style={{
|
||||
color: "#999999",
|
||||
fontSize: "16px",
|
||||
textAlign: "center",
|
||||
}}>{item.created_at}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Registrationitem;
|
||||
@@ -0,0 +1,900 @@
|
||||
/*All*/
|
||||
.borders {
|
||||
border: 0.5px solid;
|
||||
}
|
||||
|
||||
.borders2 {
|
||||
border: 1px solid #D9D9D9;
|
||||
}
|
||||
|
||||
.newMainybot {
|
||||
padding-bottom: 0px !important;
|
||||
}
|
||||
/*All*/
|
||||
/*Registration.js*/
|
||||
/*.registrationback {*/
|
||||
/* height: 368px;*/
|
||||
/* width: 1200px;*/
|
||||
/* border: 0.5px solid;*/
|
||||
/* display: flex;*/
|
||||
/* display: -webkit-flex;*/
|
||||
/* flex-direction: column;*/
|
||||
/* align-items: center;*/
|
||||
/* background:url(../../../../../images/regis/tipregistit.jpg)*/
|
||||
|
||||
/*}*/
|
||||
|
||||
.registrationbackcenter {
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/*.registrationback1 {*/
|
||||
/* height: 368px;*/
|
||||
/* width: 1200px;*/
|
||||
/* border: 0.5px solid;*/
|
||||
/* display: flex;*/
|
||||
/* flex-direction: column;*/
|
||||
/* background:url(../../../../../images/regis/tipregistit.jpg)*/
|
||||
/*}*/
|
||||
|
||||
.registrationbackp1 {
|
||||
color: #ffffff;
|
||||
font-size: 42px;
|
||||
margin-top: 80px;
|
||||
line-height: 42px;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.registrationbackp11 {
|
||||
color: #ffffff;
|
||||
font-size: 48px;
|
||||
margin-top: 71px;
|
||||
line-height: 48px;
|
||||
font-weight: bold;
|
||||
margin-left: 251px;
|
||||
|
||||
}
|
||||
|
||||
.registrationbackp2 {
|
||||
color: #ffffff;
|
||||
font-size: 18px;
|
||||
margin-top: 16px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.registrationbackp22 {
|
||||
margin-left: 251px;
|
||||
color: #ffffff;
|
||||
font-size: 36px;
|
||||
margin-top: 25px;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.registrationbackp3 {
|
||||
color: #ffffff;
|
||||
font-size: 18px;
|
||||
line-height: 20px;
|
||||
margin-top: 7px;
|
||||
}
|
||||
|
||||
.registrationbackp4 {
|
||||
color: #ffffff;
|
||||
font-size: 26px;
|
||||
margin-top: 25px;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.registrationbackp5 {
|
||||
color: #ffffff;
|
||||
font-size: 26px;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
|
||||
.registrationbackp2button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 36px;
|
||||
}
|
||||
|
||||
.registrationbackp2button2 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.registrationbackp2button3 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 44px;
|
||||
margin-left: 251px;
|
||||
|
||||
}
|
||||
|
||||
.registbut1 {
|
||||
margin-right: 46px;
|
||||
text-align: center;
|
||||
background: #0BDEE6;
|
||||
border-radius: 10px;
|
||||
height: 54px;
|
||||
width: 156px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer
|
||||
|
||||
}
|
||||
|
||||
.personreg1 {
|
||||
margin-right: 46px;
|
||||
text-align: center;
|
||||
background: #C3C1C1;
|
||||
height: 54px;
|
||||
width: 156px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
.registbut11 {
|
||||
margin-right: 46px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
color: #ffffff;
|
||||
height: 48px;
|
||||
width: 156px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
border: 1px;
|
||||
border-style: solid;
|
||||
border-color: #ffffff;
|
||||
|
||||
}
|
||||
|
||||
.registbut111 {
|
||||
margin-right: 46px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
height: 41px;
|
||||
width: 146px;
|
||||
font-size: 16px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
border: 2px;
|
||||
border-style: solid;
|
||||
border-color: #ffffff;
|
||||
|
||||
}
|
||||
|
||||
.registbut1 p {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #ffffff;
|
||||
line-height: 54px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
.registbut11 p {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
line-height: 48px;
|
||||
|
||||
}
|
||||
|
||||
.registbut22 p {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
line-height: 48px;
|
||||
}
|
||||
|
||||
.registbut2 p {
|
||||
line-height: 54px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #ffffff;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
cursor: pointer
|
||||
|
||||
}
|
||||
|
||||
.personreg1 p {
|
||||
color: #ffffff;
|
||||
font-size: 20px;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.registbut111 p {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
line-height: 38px;
|
||||
}
|
||||
|
||||
.registbut222 p {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
line-height: 38px;
|
||||
|
||||
}
|
||||
|
||||
.registbut2 {
|
||||
text-align: center;
|
||||
color: #05101A;
|
||||
font-size: 20px;
|
||||
background: #F8EC25;
|
||||
height: 54px;
|
||||
width: 156px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
.registbut22 {
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
height: 48px;
|
||||
width: 156px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
border: 1px;
|
||||
border-style: solid;
|
||||
border-color: #ffffff;
|
||||
}
|
||||
|
||||
.registbut222 {
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
height: 41px;
|
||||
width: 146px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
border: 2px;
|
||||
border-style: solid;
|
||||
border-color: #ffffff;
|
||||
}
|
||||
|
||||
.bootom {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.bootomimg {
|
||||
height: 80px;
|
||||
width: 125px;
|
||||
margin-top: 107px;
|
||||
|
||||
}
|
||||
|
||||
.bootomtext {
|
||||
color: #999999;
|
||||
font-size: 16px;
|
||||
margin-top: 33px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*Registration.js*/
|
||||
|
||||
/*Registrationitem.js*/
|
||||
/*横向*/
|
||||
.regitem {
|
||||
display: flex;
|
||||
flex-direction: initial;
|
||||
margin-top: 44px;
|
||||
}
|
||||
|
||||
.myregitem11 {
|
||||
display: flex;
|
||||
flex-direction: initial;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
|
||||
.regitem22 {
|
||||
display: flex;
|
||||
flex-direction: initial;
|
||||
margin-top: 27px;
|
||||
margin-bottom: 19px;
|
||||
}
|
||||
|
||||
.yslborderbottom {
|
||||
border-bottom: 1px solid #EDEDED;
|
||||
}
|
||||
|
||||
.registrationback {
|
||||
height: 368px;
|
||||
width: 1200px;
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.registrationback1 {
|
||||
height: 368px;
|
||||
width: 1200px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.regitem2 {
|
||||
display: flex;
|
||||
flex-direction: initial;
|
||||
padding-bottom: 18px;
|
||||
margin-top: 19px;
|
||||
|
||||
}
|
||||
|
||||
/*垂直*/
|
||||
.regitemimg1 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 17px;
|
||||
}
|
||||
|
||||
.perregitemimg1 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 26px;
|
||||
|
||||
}
|
||||
|
||||
.regitemimg2 {
|
||||
height: 78px;
|
||||
width: 78px;
|
||||
background-color: transparent;
|
||||
margin-bottom: 9px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.personregitemimg {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
|
||||
.regitemimg2 p {
|
||||
border: 0.5px solid;
|
||||
color: #999999;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.regitemimgs {
|
||||
width: 69px;
|
||||
height: 69px;
|
||||
margin-top: 3px;
|
||||
background-color: transparent;
|
||||
border-radius: 50%;
|
||||
|
||||
}
|
||||
|
||||
.regitemimgs2 {
|
||||
margin-top: 16px;
|
||||
width: 49px;
|
||||
height: 51px;
|
||||
margin-left: 25px;
|
||||
border-radius: 50%;
|
||||
|
||||
}
|
||||
|
||||
.regitemimgs22 {
|
||||
margin-top: 27px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
margin-left: 20px;
|
||||
border-radius: 50%;
|
||||
|
||||
}
|
||||
|
||||
.regitemimgs222 {
|
||||
margin-top: 12px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
margin-left: 20px;
|
||||
border-radius: 50%;
|
||||
|
||||
}
|
||||
|
||||
.regitemimgs3 {
|
||||
/* border: 0.5px solid; */
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
font-size: 21px !important;
|
||||
margin-top: 19px;
|
||||
color: #1C91E8;
|
||||
}
|
||||
|
||||
.regitemimgs4 {
|
||||
width: 156px;
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
.regitemimgs444 {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
margin-top: 18px;
|
||||
}
|
||||
.regitemimgs5 {
|
||||
margin-left: 10px;
|
||||
text-align: center;
|
||||
background: #ffffff;
|
||||
height: 40px;
|
||||
width: 72px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px;
|
||||
border-style: solid;
|
||||
border-color: #459BE5;
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
.regitemimgs555 {
|
||||
margin-left: 33px;
|
||||
text-align: center;
|
||||
background: #ffffff;
|
||||
height: 40px;
|
||||
width: 72px;
|
||||
color: #459be5;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px;
|
||||
border-style: solid;
|
||||
border-color: #459BE5;
|
||||
cursor: pointer
|
||||
}
|
||||
|
||||
.regitemimgs555 p {
|
||||
line-height: 39px;
|
||||
color: #459be5;
|
||||
}
|
||||
.regitemimgs6 {
|
||||
|
||||
text-align: center;
|
||||
background: #ffffff;
|
||||
height: 40px;
|
||||
width: 72px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px;
|
||||
cursor: pointer;
|
||||
border-style: solid;
|
||||
border-color: #459BE5;
|
||||
}
|
||||
|
||||
.regitemimgs5 p {
|
||||
color: #459BE5;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
line-height: 39px;
|
||||
}
|
||||
|
||||
.regitemimgs6 p {
|
||||
color: #459BE5;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
line-height: 39px;
|
||||
|
||||
}
|
||||
|
||||
/*Registrationitem.js*/
|
||||
|
||||
/*RegistrationSearch.js*/
|
||||
.searchhead {
|
||||
display: flex;
|
||||
flex-direction: initial;
|
||||
margin-top: 24px;
|
||||
|
||||
}
|
||||
|
||||
.packinputs button {
|
||||
background: #459BE5;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.packinputs {
|
||||
width: 317px;
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
|
||||
/*RegistrationSearch.js*/
|
||||
.reglistviewdiv {
|
||||
display: flex;
|
||||
flex-direction: initial;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
/*RegisListview.js*/
|
||||
.reglistviewdivs {
|
||||
margin-top: 25px;
|
||||
|
||||
}
|
||||
|
||||
.reglistviewdivss {
|
||||
display: flex;
|
||||
flex-direction: initial;
|
||||
|
||||
}
|
||||
|
||||
.reglistviewdivss2 {
|
||||
display: flex;
|
||||
flex-direction: initial;
|
||||
|
||||
}
|
||||
|
||||
.reglistviewdivss2c {
|
||||
display: flex;
|
||||
flex-direction: initial;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.reglistviewdivss2p {
|
||||
width: 90px;
|
||||
font-size: 12px;
|
||||
color: #666666;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
|
||||
.reglistviewdivss4p {
|
||||
width: 90px;
|
||||
font-size: 12px;
|
||||
color: #666666;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
|
||||
.reglistviewdivss5p {
|
||||
width: 110px;
|
||||
font-size: 12px;
|
||||
color: #666666;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
|
||||
.reglistviewdivss33p {
|
||||
width: 25px;
|
||||
font-size: 12px;
|
||||
color: #666666;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
|
||||
.reglistviewdivss333p {
|
||||
width: 31px;
|
||||
font-size: 12px;
|
||||
color: #666666;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
.reglistviewdivss3p {
|
||||
width: 31px;
|
||||
font-size: 12px;
|
||||
color: #666666;
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
|
||||
reglistviewdivs2 {
|
||||
margin-top: 27px;
|
||||
|
||||
}
|
||||
|
||||
/*RegisListview.js*/
|
||||
|
||||
|
||||
/*RegisListviewdata.js*/
|
||||
.reglistimg1 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
}
|
||||
|
||||
.reglistimg2 {
|
||||
border: 0.5px solid;
|
||||
height: 78px;
|
||||
width: 78px;
|
||||
}
|
||||
|
||||
/*RegisListviewdata.js*/
|
||||
|
||||
|
||||
/*PersonModal.js*/
|
||||
.yslanswerList {
|
||||
|
||||
}
|
||||
|
||||
.yslanswerList li {
|
||||
|
||||
}
|
||||
|
||||
.yslanswerList li:hover {
|
||||
background-color: #F6F4F4;
|
||||
}
|
||||
.permaindiv {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
.demo-loading-container {
|
||||
position: absolute;
|
||||
bottom: 40px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.demo-infinite-container {
|
||||
border-radius: 2px;
|
||||
overflow: auto;
|
||||
height: 215px;
|
||||
width: 485px;
|
||||
|
||||
}
|
||||
|
||||
.demo-infinite-containerdiv {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.demo-infinite-containerdiv2 {
|
||||
margin-top: 24px;
|
||||
|
||||
}
|
||||
|
||||
.backgroundspersondiv {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.cpersondiv1 {
|
||||
height: 161px;
|
||||
width: 410px;
|
||||
}
|
||||
|
||||
.demo-infinite-container2 {
|
||||
border-radius: 2px;
|
||||
overflow: auto;
|
||||
height: 161px;
|
||||
width: 410px;
|
||||
|
||||
}
|
||||
|
||||
.demo-infinite-container33 {
|
||||
border-radius: 2px;
|
||||
height: 161px;
|
||||
width: 410px;
|
||||
|
||||
}
|
||||
.cpersondiv1Items {
|
||||
color: #05101A;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.personbut1 {
|
||||
background: #F2F2F2;
|
||||
border-color: #F2F2F2;
|
||||
margin-right: 26px;
|
||||
width: 120px;
|
||||
height: 38px;
|
||||
color: #4A4A4A;
|
||||
font-size: 16px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.personbut1 p {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
color: #4A4A4A;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.personbut2 {
|
||||
background: #459BE5;
|
||||
border-color: #459BE5;
|
||||
margin-right: 26px;
|
||||
width: 120px;
|
||||
height: 38px;
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.personbut2 p {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/*PersonModal.js*/
|
||||
|
||||
|
||||
/*PersonalModalteam.js*/
|
||||
.personaldiv {
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.personaldivbutt1 {
|
||||
|
||||
background: #F2F2F2;
|
||||
border-color: #F2F2F2;
|
||||
margin-right: 23px;
|
||||
width: 100px;
|
||||
height: 38px;
|
||||
color: #4A4A4A;
|
||||
font-size: 16px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.personaldivbutt1 p {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
color: #666666;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.personaldivbutt2 {
|
||||
background: #459BE5;
|
||||
border-color: #459BE5;
|
||||
width: 100px;
|
||||
height: 38px;
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.personaldivbutt2 p {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.task-btn-orange {
|
||||
background: #4CACFF !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.task-btn {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
border: none;
|
||||
padding: 0 12px;
|
||||
letter-spacing: 1px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
/*PersonalModalteam.js*/
|
||||
|
||||
|
||||
/*文字长度限制*/
|
||||
.maxnamewidth100 {
|
||||
max-width: 100px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.maxnamewidth78 {
|
||||
width: 78px !important;
|
||||
max-width: 78px !important;
|
||||
min-width: 78px !important;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
}
|
||||
.maxnamewidth85 {
|
||||
max-width: 85px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.maxnamewidth90 {
|
||||
max-width: 90px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.maxnamewidth110 {
|
||||
max-width: 110px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
|
||||
.maxnamewidth160 {
|
||||
width: 160px !important;
|
||||
min-width:160px !important;
|
||||
max-width: 160px !important;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.maxnamewidth134 {
|
||||
max-width: 134px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/*文字长度限制?*/
|
||||
|
||||
|
||||
.textsize{
|
||||
width: 160px !important;
|
||||
min-width: 160px !important;
|
||||
max-width: 160px !important;
|
||||
text-align: center;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import React, {Component} from 'react';
|
||||
import {getImageUrl} from 'educoder';
|
||||
import {Modal, Input, Spin, Tooltip, Icon, Dropdown, Button} from 'antd';
|
||||
import axios from 'axios';
|
||||
import competition from '../comcss/competition.css';
|
||||
import Registrationitem from "../Registrationitem";
|
||||
import InfiniteScroll from 'react-infinite-scroller';
|
||||
// import PersonModaltion from "./PersonModaltion";
|
||||
const {Search} = Input;
|
||||
|
||||
//退出战队
|
||||
class ExittheteamModel extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {}
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const {
|
||||
addonAfter, test, test3, Numberofteammentors, Thecurrentnumber, person1, person2
|
||||
} = this.state;
|
||||
//Modal
|
||||
//keyboard是否支持键盘 esc 关闭
|
||||
//closable 是否显示右上角的关闭按钮
|
||||
//底部内容,当不需要默认底部按钮时,可以设为 footer={null}
|
||||
//destroyOnClose 关闭时销毁 Modal 里的子元素
|
||||
//centered 垂直居中展示 Modal
|
||||
//visible 弹出框是否显示
|
||||
|
||||
return (
|
||||
|
||||
<Modal
|
||||
keyboard={false}
|
||||
closable={false}
|
||||
footer={null}
|
||||
destroyOnClose={true}
|
||||
title={this.props.messageexit}
|
||||
centered={true}
|
||||
visible={this.props.messageexitol === undefined ? false : this.props.messageexitol}
|
||||
width="480px"
|
||||
>
|
||||
|
||||
<div className="task-popup-content">
|
||||
<div className="task-popup-text-center font-14">{this.props.exitintpermessages}</div>
|
||||
</div>
|
||||
<div className="task-popup-submit clearfix">
|
||||
<a className="pop_close task-btn mb10 mr40 colorFFF"
|
||||
onClick={() => this.props.Exittheteam(false)}>取消</a>
|
||||
<a className="task-btn task-btn-orange fr" onClick={() => this.props.Exittheteam(true)}>确定</a>
|
||||
</div>
|
||||
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default ExittheteamModel;
|
||||
@@ -0,0 +1,63 @@
|
||||
import React, {Component} from 'react';
|
||||
import {getImageUrl} from 'educoder';
|
||||
import {Modal, Input, Spin, Tooltip, Icon, Dropdown, Button} from 'antd';
|
||||
import axios from 'axios';
|
||||
import competition from '../comcss/competition.css';
|
||||
import Registrationitem from "../Registrationitem";
|
||||
import InfiniteScroll from 'react-infinite-scroller';
|
||||
// import PersonModaltion from "./PersonModaltion";
|
||||
const {Search} = Input;
|
||||
|
||||
class MessagePersonModal extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {}
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const {
|
||||
addonAfter, test, test3, Numberofteammentors, Thecurrentnumber, person1, person2
|
||||
} = this.state;
|
||||
//Modal
|
||||
//keyboard是否支持键盘 esc 关闭
|
||||
//closable 是否显示右上角的关闭按钮
|
||||
//底部内容,当不需要默认底部按钮时,可以设为 footer={null}
|
||||
//destroyOnClose 关闭时销毁 Modal 里的子元素
|
||||
//centered 垂直居中展示 Modal
|
||||
//visible 弹出框是否显示
|
||||
|
||||
return (
|
||||
|
||||
<Modal
|
||||
keyboard={false}
|
||||
closable={false}
|
||||
footer={null}
|
||||
destroyOnClose={true}
|
||||
title={this.props.messagePer}
|
||||
centered={true}
|
||||
visible={this.props.messagePerbool === undefined ? false : this.props.messagePerbool}
|
||||
width="480px"
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<div style={{width: "100%", textAlign: "center"}}
|
||||
className="task-popup-text-center font-16 ">{this.props.intpermessages}</div>
|
||||
<div style={{textAlign: "center", marginTop: "30px"}}
|
||||
className="task-popup-text-center task-btn task-btn-orange"
|
||||
onClick={() => this.props.messagePerboolbuton()}>确认
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default MessagePersonModal;
|
||||
@@ -0,0 +1,50 @@
|
||||
import React, {Component} from 'react';
|
||||
import {
|
||||
BrowserRouter as Router,
|
||||
Route,
|
||||
Switch
|
||||
} from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
import moment from 'moment';
|
||||
import competition from './comcss/competition.css';
|
||||
import {Checkbox, Table, Pagination, Menu, Icon} from "antd";
|
||||
// 团队竞赛报名无报名子组件团队 在线竞赛 > 全国高校计算机大赛-项目挑战>
|
||||
|
||||
class PersonModaltion extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="reglistviewdivs">
|
||||
<div className="reglistviewdivss " style={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: " space-around",
|
||||
alignItems: "center",
|
||||
height: "50px",
|
||||
backgroundPosition: "center",
|
||||
backgroundSize: "110% 100%",
|
||||
backgroundColor: "#E0E0E0",
|
||||
}}>
|
||||
<p className="borders"
|
||||
style={{fontSize: "16px", color: "#05101A", textAlign: "center"}}>姓名</p>
|
||||
<p className="borders"
|
||||
style={{fontSize: "16px", color: "#05101A", textAlign: "center"}}>角色</p>
|
||||
<p className="borders"
|
||||
style={{fontSize: "16px", color: "#05101A", textAlign: "center"}}>单位</p>
|
||||
<p className="borders"
|
||||
style={{fontSize: "16px", color: "#05101A", textAlign: "center"}}>其他</p>
|
||||
<p className="borders"
|
||||
style={{fontSize: "16px", color: "#05101A", textAlign: "center"}}>操作</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PersonModaltion;
|
||||
@@ -0,0 +1,146 @@
|
||||
import React, {Component} from 'react';
|
||||
import {getImageUrl} from 'educoder';
|
||||
import {Modal, Input, Spin, Tooltip, Icon, Dropdown, Button} from 'antd';
|
||||
import axios from 'axios';
|
||||
import competition from '../comcss/competition.css';
|
||||
import Registrationitem from "../Registrationitem";
|
||||
import InfiniteScroll from 'react-infinite-scroller';
|
||||
// import PersonModaltion from "./PersonModaltion";
|
||||
const {Search} = Input;
|
||||
|
||||
//立即申请试用
|
||||
class PersonalModalteam extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
yslzxueshiskmcdm1: "",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Tmoconfirmto = () => {
|
||||
try {
|
||||
if (this.state.yslzxueshiskmcdm1) {
|
||||
if (this.state.yslzxueshiskmcdm1.length === 0) {
|
||||
this.props.showNotification(`请输入您的邀请码`);
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
let url = `/competitions/${this.props.match.params.identifier}/competition_teams/join.json`;
|
||||
axios.post(url, {
|
||||
invite_code: this.state.yslzxueshiskmcdm1
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
if (result.data) {
|
||||
try {
|
||||
if (result.data.status === 0) {
|
||||
this.props.showNotification(`报名成功,预祝您夺得桂冠`);
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
this.props.Tmoconfirm(true)
|
||||
}
|
||||
}
|
||||
}).catch((error) => {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
studentsonChange = (e) => {
|
||||
this.setState({
|
||||
yslzxueshiskmcdm1: e.target.value,
|
||||
});
|
||||
|
||||
}
|
||||
render() {
|
||||
const {
|
||||
addonAfter, test, test3, Numberofteammentors, Thecurrentnumber, person1, person2
|
||||
} = this.state;
|
||||
//Modal
|
||||
//keyboard是否支持键盘 esc 关闭
|
||||
//closable 是否显示右上角的关闭按钮
|
||||
//底部内容,当不需要默认底部按钮时,可以设为 footer={null}
|
||||
//destroyOnClose 关闭时销毁 Modal 里的子元素
|
||||
//centered 垂直居中展示 Modal
|
||||
//visible 弹出框是否显示
|
||||
|
||||
return (
|
||||
|
||||
<Modal
|
||||
keyboard={false}
|
||||
closable={false}
|
||||
footer={null}
|
||||
destroyOnClose={true}
|
||||
title="加入战队"
|
||||
centered={true}
|
||||
visible={this.props.tmodalsTypes === undefined ? false : this.props.tmodalsTypes}
|
||||
width="600px"
|
||||
>
|
||||
|
||||
<div className="personaldiv">
|
||||
<div style={{
|
||||
display: "flex",
|
||||
flexDirection: "initial",
|
||||
marginTop: "10px",
|
||||
}}>
|
||||
<p style={{
|
||||
width: "67px",
|
||||
fontSize: "16px",
|
||||
color: '#05101A',
|
||||
height: "40px",
|
||||
lineHeight: "40px",
|
||||
}}>
|
||||
邀请码:
|
||||
</p>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.yslzxueshiskmcdm1 {
|
||||
height: 40px !important;
|
||||
width: 329px !important;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
<Input className={"yslzxueshiskmcdm1"} value={this.state.yslzxueshiskmcdm1}
|
||||
onChange={(e) => this.studentsonChange(e)} placeholder="请输入您的邀请码"/>
|
||||
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
marginTop: "48px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
paddingBottom: "12px",
|
||||
|
||||
}}>
|
||||
<div style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
width: "100%"
|
||||
}}>
|
||||
<div className="personaldivbutt1">
|
||||
<p onClick={() => this.props.Tmoconfirm(false)}>取消</p>
|
||||
</div>
|
||||
<div className="personaldivbutt2">
|
||||
<p onClick={() => this.Tmoconfirmto()}>确定</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default PersonalModalteam;
|
||||
@@ -0,0 +1,97 @@
|
||||
import React, {Component} from 'react';
|
||||
import {SnackbarHOC, WordsBtn} from 'educoder';
|
||||
import {TPMIndexHOC} from '../../tpm/TPMIndexHOC';
|
||||
import competition from '../comcss/competition.css';
|
||||
import {Button, Pagination,} from 'antd';
|
||||
import CompetitionMaxImg from '../CompetitionMaxImg';
|
||||
import Registrationitem from '../Registrationitem';
|
||||
|
||||
// 团队竞赛报名无报名
|
||||
class PersonalCompetit extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
loadingstate: false,
|
||||
page: 1,
|
||||
limit: 20,
|
||||
type: 6,
|
||||
pint: 1,
|
||||
test: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
paginationonChangestwo = (pageNumber) => {
|
||||
this.setState({
|
||||
page: pageNumber,
|
||||
loadingstate: true,
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const {test, page, limit, type, pint} = this.state;
|
||||
const listItems = test.map((item, index) =>
|
||||
<Registrationitem></Registrationitem>
|
||||
);
|
||||
return (
|
||||
<div className="newMain clearfix ">
|
||||
<div className={"educontent mb20"} style={{width: "1200px", marginTop: "26px"}}>
|
||||
<div className="educontent mb20 ">
|
||||
<p className="clearfix mb20 mt10">
|
||||
<a className="btn colorgrey fl hovercolorblue ">在线竞赛</a>
|
||||
<span className="color-grey-9 fl ml3 mr3">></span>
|
||||
<a
|
||||
className=" btn colorgrey fl hovercolorblue ">全国高校计算机大赛-项目挑战</a>
|
||||
<span className="color-grey-9 fl ml3 mr3">></span>
|
||||
<WordsBtn className="fl">报名</WordsBtn>
|
||||
</p>
|
||||
</div>
|
||||
{/*大图*/}
|
||||
{
|
||||
type === 6 ?
|
||||
<CompetitionMaxImg type={type} pint={pint}></CompetitionMaxImg>
|
||||
:
|
||||
""
|
||||
}
|
||||
{
|
||||
pint === 1 || pint === 3 ?
|
||||
<div style={{
|
||||
marginTop: "22px"
|
||||
}}>
|
||||
<p>参赛总人数:<span style={{color: "#459BE5"}}>132</span><span style={{marginLeft: "5px"}}>人</span></p>
|
||||
</div>
|
||||
: ""}
|
||||
|
||||
{/*列表*/}
|
||||
{
|
||||
pint === 1 || pint === 3 ?
|
||||
<div
|
||||
style={{
|
||||
marginTop: "31px"
|
||||
}}
|
||||
>
|
||||
{
|
||||
listItems
|
||||
}
|
||||
|
||||
</div>
|
||||
: ""}
|
||||
{
|
||||
pint === 1 || pint === 3 ?
|
||||
<div className="edu-txt-center ysyslxh mt56 " style={{marginBottom: "192px",}}>
|
||||
<Pagination showQuickJumper current={page}
|
||||
onChange={this.paginationonChangestwo} pageSize={limit}
|
||||
total={30}></Pagination>
|
||||
</div>
|
||||
: ""
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default SnackbarHOC()(TPMIndexHOC(PersonalCompetit));
|
||||
@@ -0,0 +1,445 @@
|
||||
import React, {Component} from 'react';
|
||||
import {
|
||||
BrowserRouter as Router,
|
||||
Route,
|
||||
Switch
|
||||
} from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
import moment from 'moment';
|
||||
import {SnackbarHOC, WordsBtn, getImageUrl} from 'educoder';
|
||||
import {TPMIndexHOC} from '../../tpm/TPMIndexHOC';
|
||||
import competition from '../comcss/competition.css';
|
||||
import {Button, message, Tooltip} from 'antd';
|
||||
// 点击按钮复制功能
|
||||
function jsCopy(s) {
|
||||
var e = document.getElementById(s);
|
||||
e.select();
|
||||
document.execCommand("Copy");
|
||||
codesuccess()
|
||||
// const range=document.createRange();
|
||||
// window.getSelection().removeAllRanges();
|
||||
// range.selectNode(e.target);
|
||||
// window.getSelection().addRange(range);
|
||||
// const successful =document.execCommand('copy');
|
||||
// if(successful){
|
||||
// codesuccess()
|
||||
// }
|
||||
}
|
||||
|
||||
function codesuccess() {
|
||||
message.success('复制成功');
|
||||
};
|
||||
// 团队竞赛报名无报名子组件团队 竞赛报名-已创建战队
|
||||
class PersonalCompetititem extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// // ////console.log(this.props.data)
|
||||
|
||||
|
||||
}
|
||||
|
||||
componentDidUpdate = (prevProps) => {
|
||||
//
|
||||
// if (prevProps.data != this.props.data) {
|
||||
//
|
||||
// }
|
||||
}
|
||||
|
||||
render() {
|
||||
const {key, item, type, mode} = this.props;
|
||||
// ////console.log("PersonalCompetititem");
|
||||
// ////console.log(data);
|
||||
// ////console.log(data[0]);
|
||||
// ////console.log(data&&data[0].creator.image_url);
|
||||
// const listItems = mydatas.map((item, index) =>
|
||||
//
|
||||
// );
|
||||
// console.log("PersonalCompetititem");
|
||||
// console.log(data);
|
||||
// console.log("PersonalCompetititem");
|
||||
// console.log(type);
|
||||
// console.log("sdasjdhahsdas");
|
||||
// console.log(this.props);
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
item !== undefined || item !== null ? <div className={"yslborderbottom"}>
|
||||
<div
|
||||
className={this.props.index === undefined || this.props.index === null ? "myregitem11" : this.props.index === 0 ? "regitem" : "myregitem11"}
|
||||
style={{
|
||||
marginBottom: "19px",
|
||||
}}>
|
||||
<div className="regitemimg1 ">
|
||||
<img className="regitemimg2" src={getImageUrl("images/" + item.creator.image_url)}>
|
||||
|
||||
</img>
|
||||
<a className="maxnamewidth78" title={item.creator.name} style={{
|
||||
color: "#999999",
|
||||
fontSize: "14px",
|
||||
width: "78px",
|
||||
textAlign: "center"
|
||||
|
||||
}}>{item.creator.name}</a>
|
||||
</div>
|
||||
<div className=" maxnamewidth160" style={{
|
||||
marginTop: "29px",
|
||||
marginLeft: "37px",
|
||||
width: "160px",
|
||||
textAlign: "center"
|
||||
}} >
|
||||
<a className="maxnamewidth160" title={item.name} style={{
|
||||
|
||||
color: "#05101A",
|
||||
fontSize: "16px",
|
||||
width: "160px",
|
||||
textAlign: "center"
|
||||
}}>{item.name}</a>
|
||||
</div>
|
||||
{this.props.type === 5 || this.props.type === 2 ?
|
||||
(this.props.mode === 3 ?
|
||||
<div style={{
|
||||
marginLeft: "37px",
|
||||
display: "flex",
|
||||
flexDirection: "initial",
|
||||
width: "340px"
|
||||
}}>
|
||||
{
|
||||
item && item.team_members.map((item, index) => {
|
||||
return (
|
||||
|
||||
index === 0 ?
|
||||
<img className="regitemimgs" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 1 ?
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 2 ?
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 3 ?
|
||||
<div>
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
|
||||
<img className="regitemimgs222"
|
||||
src={getImageUrl(`images/educoder/competitions/pexjiazai.png`)}>
|
||||
|
||||
</img>
|
||||
</div>
|
||||
: ""
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
:
|
||||
<div className=" " style={{
|
||||
marginLeft: "37px",
|
||||
display: "flex",
|
||||
flexDirection: "initial",
|
||||
width: "487px"
|
||||
}}>
|
||||
{
|
||||
item && item.team_members.map((item, index) => {
|
||||
return (
|
||||
|
||||
index === 0 ?
|
||||
<img className="regitemimgs" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 1 ?
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 2 ?
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 3 ?
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 4 ?
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 5 ?
|
||||
<div>
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
|
||||
<img className="regitemimgs222"
|
||||
src={getImageUrl(`images/educoder/competitions/pexjiazai.png`)}>
|
||||
|
||||
</img>
|
||||
</div>
|
||||
: ""
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
</div>
|
||||
)
|
||||
:
|
||||
<div className=" " style={{
|
||||
marginLeft: "37px",
|
||||
display: "flex",
|
||||
flexDirection: "initial",
|
||||
width: "487px"
|
||||
}}>
|
||||
{
|
||||
item && item.team_members.map((item, index) => {
|
||||
return (
|
||||
|
||||
index === 0 ?
|
||||
<img className="regitemimgs" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 1 ?
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 2 ?
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 3 ?
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 4 ?
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
: index === 5 ?
|
||||
<div>
|
||||
<img className="regitemimgs2" src={getImageUrl("images/" + item.image_url)}>
|
||||
|
||||
</img>
|
||||
|
||||
<img className="regitemimgs222"
|
||||
src={getImageUrl(`images/educoder/competitions/pexjiazai.png`)}>
|
||||
|
||||
</img>
|
||||
</div>
|
||||
: ""
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
</div>
|
||||
}
|
||||
<div style={this.props.type === 5 || this.props.type === 2 ?
|
||||
(this.props.mode === 3 ?
|
||||
|
||||
{
|
||||
marginLeft: "37px",
|
||||
}
|
||||
:
|
||||
{
|
||||
marginLeft: "18px",
|
||||
}
|
||||
)
|
||||
: {
|
||||
marginLeft: "16px",
|
||||
}}>
|
||||
<div style={{marginTop: "23px", width: '140px'}}>
|
||||
<span style={{
|
||||
color: "#05101A",
|
||||
fontSize: "16px",
|
||||
}}>邀请码:</span>
|
||||
<span
|
||||
style={{
|
||||
|
||||
color: "#05101A",
|
||||
fontSize: "16px",
|
||||
}}>{item.invite_code === null || item.invite_code === undefined ? "" : item.invite_code}</span>
|
||||
</div>
|
||||
<div style={{
|
||||
overflow: 'hidden',
|
||||
height: "1px",
|
||||
width: "1px"
|
||||
}}>
|
||||
<input id={"copy_invite_code" + this.props.index}
|
||||
value={item.invite_code === null || item.invite_code === undefined ? "" : item.invite_code}/>
|
||||
</div>
|
||||
</div>
|
||||
{item.invite_code === null || item.invite_code === undefined ?
|
||||
<i className="regitemimgs3 iconfont icon-fuzhi1 font-14 font-n"
|
||||
style={{
|
||||
marginLeft: "18px",
|
||||
}}
|
||||
>
|
||||
</i>
|
||||
:
|
||||
<Tooltip placement="bottom" title={"复制邀请码"}>
|
||||
<i className="regitemimgs3 iconfont icon-fuzhi1 font-14 font-n"
|
||||
style={{
|
||||
marginLeft: "18px",
|
||||
}}
|
||||
onClick={() => {
|
||||
jsCopy("copy_invite_code" + this.props.index)
|
||||
}}
|
||||
>
|
||||
</i>
|
||||
</Tooltip>
|
||||
}
|
||||
|
||||
{
|
||||
this.props.type === 5 ?
|
||||
(this.props.mode === 3 ?
|
||||
<div className="regitemimgs444"
|
||||
style={{
|
||||
marginLeft: "32px",
|
||||
}}
|
||||
>
|
||||
<div className="regitemimgs555">
|
||||
<a
|
||||
href={`/competitions/${this.props.match.params.identifier}/competition_teams/${item.id}`}
|
||||
style={{
|
||||
color: "#459be5",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
lineHeight: "39px",
|
||||
}}>战队详情</a>
|
||||
</div>
|
||||
<div className="regitemimgs555"
|
||||
style={item.manage_permission === true ? {display: "block"} : {display: "none"}}
|
||||
onClick={() => this.props.Exittheteamshow(item.id, true)}>
|
||||
<p onClick={() => this.props.Exittheteamshow(item.id, true)}>删除战队</p>
|
||||
</div>
|
||||
<div className="regitemimgs6"
|
||||
style={item.manage_permission === true ? {display: "block"} : {display: "none"}}
|
||||
onClick={() => this.props.Createateamedit(item)}>
|
||||
<p onClick={() => this.props.Createateamedit(item)}>编辑战队</p>
|
||||
</div>
|
||||
<div className="regitemimgs6"
|
||||
style={item.manage_permission === true ? {display: "none"} : {display: "block"}}
|
||||
onClick={() => this.props.Exittheteamshow(item.id, false)}>
|
||||
<p onClick={() => this.props.Exittheteamshow(item.id, false)}>退出战队</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
:
|
||||
<div className="regitemimgs444"
|
||||
style={{
|
||||
marginLeft: "32px",
|
||||
}}
|
||||
>
|
||||
|
||||
<div className="regitemimgs5"
|
||||
style={item.manage_permission === true ? {display: "block"} : {display: "none"}}
|
||||
onClick={() => this.props.Exittheteamshow(item.id, true)}>
|
||||
<p onClick={() => this.props.Exittheteamshow(item.id, true)}>删除战队</p>
|
||||
</div>
|
||||
<div className="regitemimgs6"
|
||||
style={item.manage_permission === true ? {display: "block"} : {display: "none"}}
|
||||
onClick={() => this.props.Createateamedit(item)}>
|
||||
<p onClick={() => this.props.Createateamedit(item)}>编辑战队</p>
|
||||
</div>
|
||||
<div className="regitemimgs6"
|
||||
style={item.manage_permission === true ? {display: "none"} : {display: "block"}}
|
||||
onClick={() => this.props.Exittheteamshow(item.id, false)}>
|
||||
<p onClick={() => this.props.Exittheteamshow(item.id, false)}>退出战队</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
)
|
||||
: this.props.type === 2 ?
|
||||
(this.props.mode === 3 ?
|
||||
<div className="regitemimgs444 "
|
||||
style={{
|
||||
marginLeft: "32px",
|
||||
}}
|
||||
>
|
||||
<div className="regitemimgs555">
|
||||
<a
|
||||
href={`/competitions/${this.props.match.params.identifier}/competition_teams/${item.id}`}
|
||||
style={{
|
||||
color: "#459be5",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
lineHeight: "39px",
|
||||
}}>战队详情</a>
|
||||
</div>
|
||||
<div className="regitemimgs555"
|
||||
style={item.manage_permission === true ? {display: "block"} : {display: "none"}}
|
||||
onClick={() => this.props.Exittheteamshow(item.id, true)}>
|
||||
<p onClick={() => this.props.Exittheteamshow(item.id, true)}>删除战队</p>
|
||||
</div>
|
||||
<div className="regitemimgs6"
|
||||
style={item.manage_permission === true ? {display: "block"} : {display: "none"}}
|
||||
onClick={() => this.props.Createateamedit(item)}>
|
||||
<p onClick={() => this.props.Createateamedit(item)}>编辑战队</p>
|
||||
</div>
|
||||
<div className="regitemimgs6"
|
||||
style={item.manage_permission === true ? {display: "none"} : {display: "block"}}
|
||||
onClick={() => this.props.Exittheteamshow(item.id, false)}>
|
||||
<p onClick={() => this.props.Exittheteamshow(item.id, false)}>退出战队</p>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<div className="regitemimgs444 "
|
||||
style={{
|
||||
marginLeft: "32px",
|
||||
}}
|
||||
>
|
||||
<div className="regitemimgs5"
|
||||
style={item.manage_permission === true ? {display: "block"} : {display: "none"}}
|
||||
onClick={() => this.props.Exittheteamshow(item.id, true)}>
|
||||
<p onClick={() => this.props.Exittheteamshow(item.id, true)}>删除战队</p>
|
||||
</div>
|
||||
<div className="regitemimgs6"
|
||||
style={item.manage_permission === true ? {display: "block"} : {display: "none"}}
|
||||
onClick={() => this.props.Createateamedit(item)}>
|
||||
<p onClick={() => this.props.Createateamedit(item)}>编辑战队</p>
|
||||
</div>
|
||||
<div className="regitemimgs6"
|
||||
style={item.manage_permission === true ? {display: "none"} : {display: "block"}}
|
||||
onClick={() => this.props.Exittheteamshow(item.id, false)}>
|
||||
<p onClick={() => this.props.Exittheteamshow(item.id, false)}>退出战队</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
:
|
||||
this.props.type === 3 ?
|
||||
<div className="regitemimgs4"
|
||||
style={{
|
||||
marginLeft: "32px",
|
||||
}}
|
||||
>
|
||||
|
||||
<div className="regitemimgs6" onClick={() => this.props.Exittheteamshow(item.id, false)}>
|
||||
<p onClick={() => this.props.Exittheteamshow(item.id, false)}>退出战队</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
:
|
||||
""
|
||||
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PersonalCompetititem;
|
||||
@@ -0,0 +1,225 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Menu, Icon, List, Avatar,Row, Col,Tag,Pagination,Alert} from 'antd';
|
||||
import {getImageUrl} from 'educoder';
|
||||
import axios from 'axios';
|
||||
import './Competitionsindex.css';
|
||||
import NoneData from "../../courses/coursesPublic/NoneData";
|
||||
import LoadingSpin from '../../../common/LoadingSpin';
|
||||
|
||||
class CompetitionsIndex extends Component{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state={
|
||||
current: 'all',
|
||||
datas:undefined,
|
||||
page:1,
|
||||
category:undefined
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
window.document.title = '竞赛';
|
||||
let{category,page}=this.state;
|
||||
this.getdata(category,page)
|
||||
}
|
||||
|
||||
getdata=(category,page)=>{
|
||||
const Url =`/competitions.json`;
|
||||
axios.get(Url,{params:{
|
||||
category:category,
|
||||
page:page,
|
||||
per_page:15,
|
||||
}
|
||||
}).then((response) => {
|
||||
if(response.status===200){
|
||||
this.setState({
|
||||
datas:response.data.competitions,
|
||||
count:response.data.count,
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
handleClick = e => {
|
||||
this.setState({
|
||||
current: e.key,
|
||||
datas:undefined
|
||||
});
|
||||
let{category,page}=this.state;
|
||||
this.getdata(e.key,page)
|
||||
};
|
||||
|
||||
PaginationCourse=(pageNumber)=>{
|
||||
let {category}=this.state;
|
||||
this.setState({
|
||||
page: pageNumber,
|
||||
})
|
||||
this.getdata(category,pageNumber);
|
||||
}
|
||||
|
||||
render() {
|
||||
let {datas,page,count}=this.state;
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="clearfix">
|
||||
<div>
|
||||
<div className="clearfix">
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.courses-head{
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
background-image: url(${getImageUrl(this.props.mygetHelmetapi && this.props.mygetHelmetapi.competition_banner_url === null ?`images/educoder/competitions/courses.jpg`:this.props.mygetHelmetapi&&this.props.mygetHelmetapi.competition_banner_url)});
|
||||
background-color: #081C4B;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
`
|
||||
}
|
||||
</style>
|
||||
<div className="courses-head pr Competitionshead ">
|
||||
<div className="edu-txt-center pathNavLine">
|
||||
<div className="inline path-nav"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="competitionstitle mb20">
|
||||
<div className="competitionstitle2">
|
||||
<Menu onClick={this.handleClick} selectedKeys={[this.state.current]} mode="horizontal">
|
||||
<Menu.Item key="all" className={"competitionmr50"}>
|
||||
<span className={"competitionsvalue"}>全部</span>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="nearly_published" className={"competitionmr50"}>
|
||||
<span className={"competitionsvalue"}>即将发布</span>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="progressing" className={"competitionmr50"}>
|
||||
<span className={"competitionsvalue"}>进行中</span>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="ended" className={"competitionmr50"}>
|
||||
<span className={"competitionsvalue"}>往期比赛</span>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={"educontent clearfix mtf10 CompetitionsIndex mb20"}>
|
||||
|
||||
{datas===undefined?"":datas.length===0?"":<List
|
||||
itemLayout="vertical"
|
||||
size="large"
|
||||
dataSource={datas&&datas}
|
||||
renderItem={(item,key) => (
|
||||
<a target="_blank" href={item.competition_status==="ended"?`/competitions/${item.identifier}`:item.competition_status==="nearly_published"?item.permission.editable==true?`/competitions/${item.identifier}`:null:item.competition_status==="progressing"?`/competitions/${item.identifier}`:null}
|
||||
className={item.competition_status==="ended"?"competitionstitlesshou":item.competition_status==="nearly_published"?
|
||||
item.permission.editable==true?"competitionstitlesshou":"endedfont":"competitionstitlesshou"}
|
||||
>
|
||||
|
||||
<div className={"CompetitionsList"} >
|
||||
{item.competition_status==="nearly_published"?
|
||||
item.permission.editable==true?"":<div className={"CompetitionsListzhezhao"}>即将发布 敬请期待</div>:""}
|
||||
{/*<div className={"CompetitionsListzhezhao"}>即将发布 敬请期待</div>*/}
|
||||
{/*{item.description===null||item.description===undefined||item.description===""?<style>*/}
|
||||
{/*{*/}
|
||||
{/*`*/}
|
||||
{/*// .CompetitionsIndex .ant-list-vertical .ant-list-item-action{*/}
|
||||
{/*// margin-top:50px;*/}
|
||||
{/*// }*/}
|
||||
{/*`*/}
|
||||
{/*}*/}
|
||||
{/*</style>:""}*/}
|
||||
<img className={"competitonimg"}
|
||||
src={item.competition_status==="ended"?getImageUrl(`images/educoder/competitions/groups1.png`):item.competition_status==="nearly_published"?getImageUrl(`images/educoder/competitions/groups2.png`):item.competition_status==="progressing"?getImageUrl(`images/educoder/competitions/groups3.png`):""} />
|
||||
<List.Item
|
||||
key={key}
|
||||
actions={[
|
||||
<span>竞赛时间: {item.start_time}~{item.end_time}</span>,
|
||||
<span>报名截止时间:{item.enroll_end_time}</span>,
|
||||
]}
|
||||
extra={
|
||||
<div className={"pt50"} style={{"width":'314px'}}>
|
||||
|
||||
<Row gutter={16}>
|
||||
<Col className="gutter-row" span={6}>
|
||||
<div className="gutter-box CompetitionsIndexdadels">奖金</div>
|
||||
</Col>
|
||||
<Col className="gutter-row" span={6}>
|
||||
<div className="gutter-box CompetitionsIndexdadels">浏览数</div>
|
||||
</Col>
|
||||
<Col className="gutter-row" span={6}>
|
||||
<div className="gutter-box CompetitionsIndexdadels">报名数</div>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={16}>
|
||||
<Col className="gutter-row" span={6}>
|
||||
<div className="gutter-box CompetitionsIndexbottomvalue">¥{item.bonus}</div>
|
||||
</Col>
|
||||
<Col className="gutter-row" span={6}>
|
||||
<div className="gutter-box CompetitionsIndexbottomvalue">{item.competition_status==="nearly_published"?"--":item.visits_count}</div>
|
||||
</Col>
|
||||
<Col className="gutter-row" span={6}>
|
||||
<div className="gutter-box CompetitionsIndexbottomvalue">{item.competition_status==="nearly_published"?"--":item.member_count}</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<List.Item.Meta
|
||||
title={<a className={item.competition_status==="ended"?"competitionstitlesshou":item.competition_status==="nearly_published"?
|
||||
item.permission.editable==true?"competitionstitlesshou":"endedfont":"competitionstitlesshou"}>
|
||||
<a target="_blank" className={"competitionstitles"}
|
||||
href={item.competition_status==="ended"?`/competitions/${item.identifier}`:item.competition_status==="nearly_published"? item.permission.editable==true?`/competitions/${item.identifier}`:null:item.competition_status==="progressing"?`/competitions/${item.identifier}`:null}
|
||||
>{item.name}{item.sub_title===null?"":`——${item.sub_title}`}</a>
|
||||
{/*<span>{item.sub_title===null?"":*/}
|
||||
{/*<Tag className="competitionsrelative" color="#87d068">{item.sub_title}</Tag>}*/}
|
||||
{/*</span>*/}
|
||||
</a>}
|
||||
/>
|
||||
<span className={"span666"}>{item.description}</span>
|
||||
</List.Item>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
)
|
||||
|
||||
}
|
||||
/>}
|
||||
|
||||
{datas===undefined?"":count===undefined?"":count >15 ?<div className="mb40 edu-txt-center padding20-30"
|
||||
>
|
||||
|
||||
<Pagination
|
||||
showQuickJumper
|
||||
defaultCurrent={1}
|
||||
pageSize={15}
|
||||
total={count===undefined?"":count}
|
||||
current={page}
|
||||
onChange={this.PaginationCourse}
|
||||
/>
|
||||
|
||||
</div>:""}
|
||||
|
||||
{
|
||||
datas===undefined?<LoadingSpin/>:datas && datas.length===0? <NoneData></NoneData>:""
|
||||
}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default CompetitionsIndex;
|
||||
@@ -0,0 +1,163 @@
|
||||
.teamsLayout{background: transparent !important;}
|
||||
|
||||
.competitionstitle{
|
||||
height:50px !important;
|
||||
border-radius: 6px;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.competitionstitle2{
|
||||
height:50px !important;
|
||||
margin-left: 30px !important;
|
||||
background: #fff;
|
||||
width: 1200px;
|
||||
}
|
||||
.CompetitionsList{
|
||||
position: relative;
|
||||
/*max-height: 210px;*/
|
||||
}
|
||||
.competitonimg{
|
||||
position: absolute;
|
||||
right: -5px;
|
||||
width: 80px;
|
||||
top: 20px;
|
||||
}
|
||||
|
||||
.ant-menu-horizontal {
|
||||
border-bottom:none !important;
|
||||
}
|
||||
|
||||
|
||||
.competitionsvalue{
|
||||
font-size: 16px;
|
||||
font-family: PingFangSC-Medium,PingFangSC;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.competitionmr50 {
|
||||
margin-right: 50px !important;
|
||||
}
|
||||
|
||||
.CompetitionsIndex .ant-list-item{
|
||||
background: #fff !important;
|
||||
margin-top: 20px;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.CompetitionsIndex .ant-list-item{
|
||||
padding:25px;
|
||||
}
|
||||
|
||||
.CompetitionsIndex .ant-list-item-meta-title{
|
||||
height:28px;
|
||||
font-size:28px;
|
||||
font-family:PingFangSC-Regular,PingFangSC;
|
||||
font-weight:400;
|
||||
color:rgba(5,16,26,1);
|
||||
line-height:28px;
|
||||
}
|
||||
|
||||
.CompetitionsIndex .ant-list-vertical .ant-list-item-meta{
|
||||
margin-bottom: 20px !important;
|
||||
}
|
||||
|
||||
.CompetitionsIndex .ant-list-vertical .ant-list-item-action {
|
||||
margin-top: 20px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.CompetitionsIndex .ant-list-item-action-split{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.CompetitionsIndexdadels{
|
||||
font-family: PingFangSC-Regular,PingFangSC;
|
||||
font-weight: 400;
|
||||
color: #777777;
|
||||
margin-bottom: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.CompetitionsIndexbottomvalue{
|
||||
font-size: 24px;
|
||||
font-family: ArialMT;
|
||||
color: rgba(5,16,26,1);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.CompetitionsIndex .gutter-row{
|
||||
/*margin-right:20px;*/
|
||||
width: 33%;
|
||||
}
|
||||
|
||||
.pt50{
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
.competitionstitles{
|
||||
max-width: 789px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
margin-right: 15px;
|
||||
color:#000 !important;
|
||||
}
|
||||
|
||||
.competitionsrelative{
|
||||
position: absolute;
|
||||
top: 28px;
|
||||
}
|
||||
|
||||
.CompetitionsList:hover{
|
||||
/*box-shadow: 0 2px 6px rgba(51,51,51,.09);*/
|
||||
box-shadow:3px 4px 10px 2px rgba(229,229,229,0.5);
|
||||
opacity: 1;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.endedfont{
|
||||
color:#000 !important;
|
||||
}
|
||||
.CompetitionsListzhezhao{
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 1206px;
|
||||
height: 100%;
|
||||
z-index: 10000;
|
||||
display: none;
|
||||
background: rgba(0,0,0,0.33);
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 22px;
|
||||
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
flex-direction: column;
|
||||
}
|
||||
.CompetitionsList:hover .CompetitionsListzhezhao{
|
||||
display: block;
|
||||
display: flex;
|
||||
}
|
||||
.competitionstitlesshou:hover a{
|
||||
cursor: pointer;
|
||||
color: #1c91e8 !important;
|
||||
}
|
||||
|
||||
.competitionstitlesshou{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
.Competitionshead{
|
||||
background-color: #2d28ba !important;
|
||||
background-position: center !important;
|
||||
background-position: 50% !important;
|
||||
background-repeat: no-repeat !important;
|
||||
}
|
||||
|
||||
.span666{
|
||||
color:#666666 !important;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
.teamsLayout{background: transparent !important;}
|
||||
.teamsLayout .teamsLayoutitle{
|
||||
font-size:18px;
|
||||
font-family:PingFangSC-Semibold,PingFang SC;
|
||||
font-weight:600;
|
||||
color:rgba(5,16,26,1);
|
||||
line-height:25px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.teamsLayoutTable .ant-table-bordered .ant-table-thead > tr > th, .ant-table-bordered .ant-table-tbody > tr > td {
|
||||
border-right: 1px solid transparent !important;
|
||||
}
|
||||
|
||||
.teamsLayoutTable .ant-table-body .ant-table-thead > tr> th:nth-last-child(1){
|
||||
border-right: 1px solid #e8e8e8 !important;
|
||||
}
|
||||
|
||||
.teamsLayoutTable .ant-table-body .ant-table-tbody > tr> td:nth-last-child(1){
|
||||
border-right: 1px solid #e8e8e8 !important;
|
||||
}
|
||||
|
||||
.teamsLayoutTable .ant-table-bordered .ant-table-thead > tr > th{
|
||||
background:#EEEEEE;
|
||||
font-size: 14px;
|
||||
font-family: PingFangSC-Regular,PingFang SC;
|
||||
font-weight: 400;
|
||||
color: rgba(102,102,102,1);
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.teamsLayoutTable .ant-table-bordered .ant-table-tbody > tr > th{
|
||||
background:#EEEEEE;
|
||||
font-size:14px;
|
||||
font-family:PingFangSC-Regular,PingFang SC;
|
||||
font-weight:400;
|
||||
color:rgba(5,16,26,1);
|
||||
line-height:20px;
|
||||
}
|
||||
|
||||
.teamsLayout .mt40{
|
||||
margin-top: 40px !important;
|
||||
}
|
||||
|
||||
.teamsLayoutheji{
|
||||
color: #878787;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.teamsLayoucolor-orange {
|
||||
color: #ff6800!important;
|
||||
font-size: 16px;
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Breadcrumb,Layout,Table, Divider, Tag,Badge,Tooltip} from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
|
||||
|
||||
import './Competitionteams.css';
|
||||
const { Content } = Layout;
|
||||
|
||||
class Competitionteams extends Component{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state={
|
||||
shixundata: undefined,
|
||||
coursedata:undefined,
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
window.document.title = '竞赛';
|
||||
if(this.props.match.params.identifier!=null){
|
||||
let url=`/competitions/${this.props.match.params.identifier}/common_header.json`;
|
||||
axios.get(url).then((response) => {
|
||||
if(response.status===200){
|
||||
this.setState({
|
||||
data:response.data,
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
this.getshixundata();
|
||||
this.getcoursedata();
|
||||
}
|
||||
|
||||
getshixundata=()=>{
|
||||
|
||||
const Url =`/competitions/${this.props.match.params.identifier}/competition_teams/${this.props.match.params.competition_team_id}/shixun_detail.json`;
|
||||
axios.get(Url).then((response) => {
|
||||
if(response.status===200){
|
||||
// let data={
|
||||
// shixuns: [
|
||||
// {
|
||||
// creator: "黄井泉", // 创建者
|
||||
// shixun_name: "单链表的学习与应用(I)", // 实训名称
|
||||
// shixun_identifier: "mnf6b7z3",
|
||||
// forked: false, // false:原创
|
||||
// myshixuns_count: 179, // 学习人数
|
||||
// forked_myshixun_count: 0, // 被fork发布的学习人数
|
||||
// valid_count: 82, // 有效作品数
|
||||
// score: 1320 // 应用值
|
||||
// }
|
||||
// ],
|
||||
// shixun_count: 1, // 实训总计
|
||||
// total_myshixun_count: 179, // 学习人数总计
|
||||
// total_forked_myshixun_count: 0, // 被fork发布的学习人数总计
|
||||
// total_valid_count: 82, // 有效作品数总计
|
||||
// total_shixun_score: 1320 // 应用值总计
|
||||
// }
|
||||
let data=response.data;
|
||||
|
||||
let newarr=data.shixuns;
|
||||
|
||||
let newobj={
|
||||
creator:"合计:",
|
||||
shixun_name:data.shixun_count,
|
||||
myshixuns_count:data.total_myshixun_count,
|
||||
forked_myshixun_count:data.total_forked_myshixun_count,
|
||||
valid_count:data.total_valid_count,
|
||||
score:data.total_shixun_score
|
||||
}
|
||||
newarr.push(newobj)
|
||||
|
||||
this.setState({
|
||||
shixundata:newarr
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
getcoursedata=()=>{
|
||||
const Url =`/competitions/${this.props.match.params.identifier}/competition_teams/${this.props.match.params.competition_team_id}/course_detail.json`;
|
||||
|
||||
axios.get(Url).then((response) => {
|
||||
if(response.status===200){
|
||||
// let data={
|
||||
// courses: [
|
||||
// {
|
||||
// creator: "周海芳", // 创建者
|
||||
// creator_login: "Nancy", // login
|
||||
// course_name: "大学计算机基础2018年秋季",
|
||||
// course_id: 1502,
|
||||
// students_count: 122, // 学生数量
|
||||
// shixun_homework_count: 8, // 发布的实训作业数量
|
||||
// valid_count: 977, // 有效作品数
|
||||
// score: 29810 // 应用值
|
||||
// }
|
||||
// ],
|
||||
// total_course_count: 1, // 课堂总计
|
||||
// total_students_count: 122, // 学生数总计
|
||||
// total_shixun_homework_count: 8, // 实训作业数总计
|
||||
// total_valid_count: 977, // 有效作品数总计
|
||||
// total_course_score: 29810 // 应用值总计
|
||||
// }
|
||||
|
||||
let data=response.data;
|
||||
|
||||
let newarr=data.courses;
|
||||
|
||||
let newobj={
|
||||
creator:"合计:",
|
||||
course_name:data.total_course_count,
|
||||
students_count:data.total_students_count,
|
||||
shixun_homework_count:data.total_shixun_homework_count,
|
||||
valid_count:data.total_valid_count,
|
||||
score:data.total_course_score
|
||||
}
|
||||
newarr.push(newobj)
|
||||
|
||||
this.setState({
|
||||
coursedata:newarr
|
||||
})
|
||||
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
let {data}=this.state;
|
||||
const shixuncolumns = [
|
||||
{
|
||||
title: '创建者',
|
||||
dataIndex: 'creator',
|
||||
key: 'creator',
|
||||
render: (text, record) => <div className={record.creator==="合计:"?"teamsLayoutheji":""}>{text}</div>,
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'shixun_name',
|
||||
key: 'shixun_name',
|
||||
render: (text, record) =>
|
||||
<div className={record.creator==="合计:"?"teamsLayoucolor-orange":""}>{text}{record.forked===true?<Badge count={"原创"} style={{ backgroundColor: '#459BE5' }} />:""}</div>,
|
||||
},
|
||||
{
|
||||
title: '学习人数',
|
||||
dataIndex: 'myshixuns_count',
|
||||
key: 'myshixuns_count',
|
||||
render: (text, record) => <div className={record.creator==="合计:"?"teamsLayoucolor-orange":""}>{text}</div>,
|
||||
},
|
||||
{
|
||||
title: '被fork发布的学习人数',
|
||||
dataIndex: 'forked_myshixun_count',
|
||||
key: 'forked_myshixun_count',
|
||||
render: (text, record) =>
|
||||
<Tooltip placement="bottom" title={"fork该实训产生的新实训,学习总人数"}>
|
||||
<div className={record.creator==="合计:"?"teamsLayoucolor-orange":""}>{text}</div>
|
||||
</Tooltip>,
|
||||
},
|
||||
{
|
||||
title: '有效作品数',
|
||||
dataIndex: 'valid_count',
|
||||
key: 'valid_count',
|
||||
render: (text, record) =>
|
||||
<Tooltip placement="bottom" title={"至少完成了1个关卡"}>
|
||||
<div className={record.creator==="合计:"?"teamsLayoucolor-orange":""}>{text}</div>
|
||||
</Tooltip>,
|
||||
},
|
||||
{
|
||||
title: '应用值',
|
||||
dataIndex: 'score',
|
||||
key: 'score',
|
||||
render: (text, record) => <div className={record.creator==="合计:"?"teamsLayoucolor-orange":""}>{text}</div>,
|
||||
},
|
||||
];
|
||||
|
||||
const coursecolumns = [
|
||||
{
|
||||
title: '创建者',
|
||||
dataIndex: 'creator',
|
||||
key: 'creator',
|
||||
render: (text, record) => <div className={record.creator==="合计:"?"teamsLayoutheji":""}>{text}</div>,
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'course_name',
|
||||
key: 'course_name',
|
||||
render: (text, record) => <div className={record.creator==="合计:"?"teamsLayoucolor-orange":""}>{text}</div>,
|
||||
},
|
||||
{
|
||||
title: '学生数量',
|
||||
dataIndex: 'students_count',
|
||||
key: 'students_count',
|
||||
render: (text, record) => <div className={record.creator==="合计:"?"teamsLayoucolor-orange":""}>{text}</div>,
|
||||
},
|
||||
{
|
||||
title: '发布的实训作业数量',
|
||||
dataIndex: 'shixun_homework_count',
|
||||
key: 'shixun_homework_count',
|
||||
render: (text, record) =>
|
||||
<div className={record.creator==="合计:"?"teamsLayoucolor-orange":""}>{text}</div>
|
||||
,
|
||||
},
|
||||
{
|
||||
title: '有效作品数',
|
||||
dataIndex: 'valid_count',
|
||||
key: 'valid_count',
|
||||
render: (text, record) =>
|
||||
<Tooltip placement="bottom" title={"至少完成了1个关卡"}>
|
||||
<div className={record.creator==="合计:"?"teamsLayoucolor-orange":""}>{text}</div>
|
||||
</Tooltip>,
|
||||
},
|
||||
{
|
||||
title: '应用值',
|
||||
dataIndex: 'score',
|
||||
key: 'score',
|
||||
render: (text, record) => <div className={record.creator==="合计:"?"teamsLayoucolor-orange":""}>{text}</div>,
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
// console.log(this.state.shixundata)
|
||||
return (
|
||||
|
||||
<div className={"educontent clearfix mt20 "}>
|
||||
<Breadcrumb separator=">">
|
||||
<Breadcrumb.Item><Link to={"/competitions"}>{data&&data.name}</Link></Breadcrumb.Item>
|
||||
<Breadcrumb.Item><Link to={`/competitions/${this.props.match.params.identifier}/enroll`}>报名</Link></Breadcrumb.Item>
|
||||
<Breadcrumb.Item>战队详情</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
|
||||
<Layout className={"teamsLayout"}>
|
||||
|
||||
<Content className={"teamsLayoutitle"}>实训项目</Content>
|
||||
<Content className={"teamsLayoutContent"}>
|
||||
<Table className="teamsLayoutTable" columns={shixuncolumns} dataSource={this.state.shixundata} bordered pagination={false}/>
|
||||
</Content>
|
||||
<Content className={"teamsLayoutitle mt40"}>翻转课堂</Content>
|
||||
<Content className={"teamsLayoutContents"}>
|
||||
<Table className="teamsLayoutTable" columns={coursecolumns} dataSource={this.state.coursedata} bordered pagination={false}/>
|
||||
</Content>
|
||||
|
||||
</Layout>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
export default Competitionteams;
|
||||
@@ -0,0 +1,438 @@
|
||||
.teamsLayout{background: transparent !important;}
|
||||
|
||||
.teamsLayout .ant-layout-sider{
|
||||
background: transparent !important;
|
||||
flex: 0 0 180px !important;
|
||||
max-width: 180px !important;
|
||||
min-width: 180px !important;
|
||||
width: 180px !important;
|
||||
}
|
||||
.teamsLayout .teamsLayoutitle{
|
||||
font-size:18px;
|
||||
font-family:PingFangSC-Semibold,PingFang SC;
|
||||
font-weight:600;
|
||||
color:rgba(5,16,26,1);
|
||||
line-height:25px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.teamsLayoutTable .ant-table-bordered .ant-table-thead > tr > th, .ant-table-bordered .ant-table-tbody > tr > td {
|
||||
border-right: 1px solid transparent !important;
|
||||
}
|
||||
|
||||
.teamsLayoutTable .ant-table-body .ant-table-thead > tr> th:nth-last-child(1){
|
||||
border-right: 1px solid #e8e8e8 !important;
|
||||
}
|
||||
|
||||
.teamsLayoutTable .ant-table-body .ant-table-tbody > tr> td:nth-last-child(1){
|
||||
border-right: 1px solid #e8e8e8 !important;
|
||||
}
|
||||
|
||||
.teamsLayoutTable .ant-table-bordered .ant-table-thead > tr > th{
|
||||
background:#EEEEEE;
|
||||
font-size: 14px;
|
||||
font-family: PingFangSC-Regular,PingFang SC;
|
||||
font-weight: 400;
|
||||
color: rgba(102,102,102,1);
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.teamsLayoutTable .ant-table-bordered .ant-table-tbody > tr > th{
|
||||
background:#EEEEEE;
|
||||
font-size:14px;
|
||||
font-family:PingFangSC-Regular,PingFang SC;
|
||||
font-weight:400;
|
||||
color:rgba(5,16,26,1);
|
||||
line-height:20px;
|
||||
}
|
||||
|
||||
.teamsLayout .mt40{
|
||||
margin-top: 40px !important;
|
||||
}
|
||||
|
||||
.teamsLayoutheji{
|
||||
color: #878787;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.teamsLayoucolor-orange {
|
||||
color: #ff6800 !important;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.CompetitionCommonbanner{
|
||||
padding: 20px;
|
||||
background:rgba(255,255,255,1);
|
||||
box-shadow:3px 2px 12px 2px rgba(0,0,0,0.05);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.CompetitionCommonbannerfont{
|
||||
height:100%;
|
||||
width: 365px !important;
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
.CompetitionCommonbannerfont .competitionbannerdiv:nth-child(1){
|
||||
max-height:100px;
|
||||
font-size:25px;
|
||||
font-weight:400;
|
||||
color:rgba(5,16,26,1);
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.CompetitionCommonbannerfont .competitionbannerdiv:nth-child(2){
|
||||
max-height: 70px;
|
||||
font-size:16px;
|
||||
font-weight:400;
|
||||
/*color:rgba(155,155,155,1);*/
|
||||
color:#05101A;
|
||||
}
|
||||
|
||||
.CompetitionCommonbannerfont .competitionbannerdiv:nth-child(3){
|
||||
max-height: 70px;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
/*color: rgba(155,155,155,1);*/
|
||||
color:#05101A;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.Competitioncolor9b{
|
||||
color: #9B9B9B;
|
||||
}
|
||||
|
||||
.Competitioncolor77{
|
||||
color: #777777;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.Competitioncolor516{
|
||||
font-size:24px;
|
||||
color:rgba(5,16,26,1);
|
||||
}
|
||||
|
||||
.Competitionfontsize22{
|
||||
font-size:22px;
|
||||
font-weight:500;
|
||||
color:rgba(255,255,255,1);
|
||||
}
|
||||
|
||||
.Competitionfontsize16{
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: rgba(102,102,102,1);
|
||||
}
|
||||
|
||||
.ant-layout-sider {
|
||||
position: relative;
|
||||
min-width: 0;
|
||||
background: #001529;
|
||||
-webkit-transition: all 0.2s;
|
||||
-o-transition: all 0.2s;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.CompetitionMenu .ant-menu-item::after {
|
||||
left: 0px !important;
|
||||
right: auto;
|
||||
border-right: 5px solid #4CACFF;
|
||||
}
|
||||
|
||||
.CompetitionMenu .ant-menu-item{
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
background:none;
|
||||
color:#666;
|
||||
}
|
||||
|
||||
.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.CompetitionMenu .ant-menu-item:not(:last-child){
|
||||
margin-bottom: 40px;
|
||||
background: transparent;
|
||||
color:#666;
|
||||
}
|
||||
|
||||
.CompetitionMenu .ant-menu-item{
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.CompetitionMenu .ant-menu-item-selected {
|
||||
color: rgba(76,172,255,1) !important;
|
||||
}
|
||||
|
||||
.CompetitionMenu{
|
||||
width: 145px;
|
||||
background: #fff;
|
||||
border: 1px solid rgba(239,239,239,1);
|
||||
padding-top: 20px;
|
||||
padding-bottom: 40px !important;
|
||||
}
|
||||
|
||||
.teamsLayoutleft{
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.Competitioncharts{
|
||||
font-size: 24px;
|
||||
color: rgba(5,16,26,1);
|
||||
}
|
||||
.Competitionfirst{
|
||||
width:233px;
|
||||
height:298px;
|
||||
background:rgba(250,250,250,1);
|
||||
box-shadow:0px 2px 8px 2px rgba(255,134,34,0.5);
|
||||
border-radius:5px;
|
||||
}
|
||||
.Competitionsecondary{
|
||||
width:234px;
|
||||
height:298px;
|
||||
background:rgba(250,250,250,1);
|
||||
box-shadow:0px 3px 5px 0px rgba(254,190,154,1);
|
||||
border-radius:5px;
|
||||
}
|
||||
|
||||
.Competitionthird{
|
||||
width: 234px;
|
||||
height: 298px;
|
||||
background: rgba(250,250,250,1);
|
||||
box-shadow: 0px 4px 5px 0px rgba(200,200,202,1);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.Competition399{
|
||||
height:399px;
|
||||
}
|
||||
|
||||
.Competitiontransparent table{
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.Commonimg{
|
||||
position: absolute;
|
||||
right: -5px;
|
||||
width:93px;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
.Competitionthirdbox{
|
||||
width:234px;
|
||||
height:167px;
|
||||
background:rgba(223,223,225,1);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.Competitionfirstbox{
|
||||
width:233px;
|
||||
height:167px;
|
||||
background:rgba(255,231,160,1);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.Competitionsecondarybox{
|
||||
width:234px;
|
||||
height:167px;
|
||||
background:rgba(253,230,217,1);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.rankingimg{
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50% !important;
|
||||
box-shadow: 0px 0px 12px rgba(0,0,0,0.2);
|
||||
border: 2px solid #459BE5;
|
||||
}
|
||||
|
||||
.Competitioncenter{
|
||||
text-align: center;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
|
||||
.jinshaifont{
|
||||
font-size: 16px;
|
||||
color: rgba(5,16,26,1);
|
||||
margin-top: 13px !important;
|
||||
}
|
||||
|
||||
.Competitionthird .ant-card-body {
|
||||
padding: 12px;
|
||||
zoom: 1;
|
||||
}
|
||||
|
||||
/*.Competitionthird .ant-card-meta-title{*/
|
||||
/*margin-bottom: 0px !important;*/
|
||||
/*}*/
|
||||
|
||||
.Competitionfirst .ant-card-body {
|
||||
padding: 12px;
|
||||
zoom: 1;
|
||||
}
|
||||
|
||||
.Competitionsecondary .ant-card-body {
|
||||
padding: 12px;
|
||||
zoom: 1;
|
||||
}
|
||||
|
||||
.center{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.rankfonttop{
|
||||
font-size:14px;
|
||||
color:rgba(102,102,102,1);
|
||||
}
|
||||
|
||||
.rankfontmid{
|
||||
font-size:18px;
|
||||
color:rgba(102,102,102,1);
|
||||
}
|
||||
|
||||
.rankfontbottom{
|
||||
font-size:26px;
|
||||
color:rgba(165,91,41,1);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.rankfontbottoms{
|
||||
font-size:28px;
|
||||
color:rgba(165,91,41,1);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.Competitionuserimg{
|
||||
width: 64px;
|
||||
height: 63px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid #459BE5;
|
||||
}
|
||||
|
||||
.CompetitionsListzhezhao{
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 1206px;
|
||||
height: 100%;
|
||||
z-index: 10000;
|
||||
display: none;
|
||||
background: rgba(0,0,0,0.33);
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 22px;
|
||||
|
||||
}
|
||||
|
||||
.relative{position: relative;}
|
||||
|
||||
.relative:hover .CompetitionsListzhezhao{
|
||||
display: block;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.image_urlbox{
|
||||
width: 790px;
|
||||
height: 340px;
|
||||
}
|
||||
|
||||
.CompetitionContents{
|
||||
background: #fff !important;
|
||||
padding: 40px;
|
||||
box-shadow: 3px 2px 12px 2px rgba(0,0,0,0.05);
|
||||
border: 1px solid rgba(239,239,239,1);
|
||||
}
|
||||
|
||||
.rankbeicenter{
|
||||
text-align: center;
|
||||
}
|
||||
.rankbei{
|
||||
font-size: 16px;
|
||||
color: rgba(119,119,119,1);
|
||||
|
||||
}
|
||||
|
||||
.youranklist{
|
||||
background: rgba(226,241,255,1);
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.ranknames{
|
||||
font-size: 16px;
|
||||
color: rgba(62,62,62,1);
|
||||
}
|
||||
|
||||
.ranknameslast{
|
||||
font-size:16px;
|
||||
color:rgba(12,158,254,1);
|
||||
}
|
||||
|
||||
.textleft{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.textright{
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.userranksclass{
|
||||
text-align: left;
|
||||
width: 18%;
|
||||
padding-left: 12px;
|
||||
margin-right: 28px;
|
||||
}
|
||||
|
||||
.Commonimgbox{
|
||||
width: 800px !important;
|
||||
}
|
||||
|
||||
.CompetitionCommonbannerfont{
|
||||
width: 350px !important;
|
||||
margin-left:10px;
|
||||
}
|
||||
|
||||
.color000{
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.cursorpointer{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.rankfonttop{
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space:nowrap
|
||||
}
|
||||
|
||||
.usernamebox{
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
max-width: 100px;
|
||||
display: inherit;
|
||||
}
|
||||
|
||||
.competimgabsolute{
|
||||
position: absolute;
|
||||
left: 72px;
|
||||
bottom: -10px;
|
||||
}
|
||||
.competimgabsolute .ant-badge-count{
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.competimgabsoluteijmg{
|
||||
position: absolute;
|
||||
left: -11px;
|
||||
bottom: 0px;
|
||||
}
|
||||
@@ -0,0 +1,548 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Breadcrumb,Layout,Table, Divider, Tag,Badge,Row, Col,Button, Menu, Icon} from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
import {markdownToHTML,getImageUrl} from 'educoder';
|
||||
import CompetitionContents from './CompetitionCommonChild/CompetitionContents';
|
||||
import CompetitionContentsChart from './CompetitionCommonChild/CompetitionContentsChart';
|
||||
import CompetitionContentsMd from './CompetitionCommonChild/CompetitionContentsMd';
|
||||
import CompetitionContentspdf from './CompetitionCommonChild/CompetitionContentspdf';
|
||||
|
||||
import './CompetitionCommon.css';
|
||||
|
||||
const {Sider } = Layout;
|
||||
|
||||
class CompetitionCommon extends Component{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state={
|
||||
data: undefined,
|
||||
bannerdata: undefined,
|
||||
module_type: undefined,
|
||||
mdContentdata: undefined,
|
||||
chart_rules: undefined,
|
||||
Competitionedittype: false,
|
||||
chartdata: undefined,
|
||||
has_url: false,
|
||||
signupdata: undefined
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
window.document.title = '竞赛';
|
||||
if(this.props.match.params.identifier!=null){
|
||||
this.getbannerdata();
|
||||
// this.setState({
|
||||
// thiskeys:this.props.location.search.replace('?menu=', '')
|
||||
// })
|
||||
// let url=`/competitions/${this.props.match.params.identifier}.json`;
|
||||
// axios.get(url).then((response) => {
|
||||
// if(response.status===200){
|
||||
// this.setState({
|
||||
// bannerdata:response.data
|
||||
// })
|
||||
// }
|
||||
// }).catch((error) => {
|
||||
// //console.log(error)
|
||||
// })
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate = (prevProps) => {
|
||||
if (prevProps.user != this.props.user) {
|
||||
|
||||
//console.log("componentDidUpdatess");
|
||||
//console.log(this.props.user);
|
||||
if (this.props.user && this.props.user.login != "") {
|
||||
const zul = `/competitions/${this.props.match.params.identifier}/competition_staff.json`;
|
||||
axios.get((zul)).then((result) => {
|
||||
if (result) {
|
||||
if (result.data) {
|
||||
this.setState({
|
||||
signupdata: result.data
|
||||
})
|
||||
}
|
||||
}
|
||||
}).catch((error) => {
|
||||
////console.log(error);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//获取头部信息
|
||||
getbannerdata=()=>{
|
||||
// let menuid=this.props.location.search.replace('?menu=', '');
|
||||
let query=this.props.location&&this.props.location.search;
|
||||
const types = query.split('&')
|
||||
const menuid = types[0].split('?menu=')
|
||||
let url=`/competitions/${this.props.match.params.identifier}/common_header.json`;
|
||||
axios.get(url).then((response) => {
|
||||
if(response.status===200){
|
||||
this.setState({
|
||||
data: response.data,
|
||||
thiskeys: menuid[1] === undefined || menuid[1] === "" ? response.data.competition_modules[0].id : menuid[1],
|
||||
mode: response.data.mode
|
||||
})
|
||||
if(menuid[1]===undefined||menuid[1]===""){
|
||||
this.getrightdata(
|
||||
response.data.competition_modules[0].id,
|
||||
response.data.competition_modules[0].module_type,
|
||||
response.data.competition_modules[0].module_url,
|
||||
response.data.competition_modules[0].has_url
|
||||
)
|
||||
}else{
|
||||
let newlist=response.data.competition_modules;
|
||||
newlist.map((item,key)=>{
|
||||
if(`${item.id}`===`${menuid[1]}`){
|
||||
this.getrightdata(
|
||||
item.id,
|
||||
item.module_type,
|
||||
item.module_url,
|
||||
item.has_url
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}).catch((error) => {
|
||||
//console.log(error)
|
||||
})
|
||||
|
||||
//this.props.user 有可能为空
|
||||
|
||||
if (this.props.user && this.props.user.login != "") {
|
||||
const zul = `/competitions/${this.props.match.params.identifier}/competition_staff.json`;
|
||||
axios.get((zul)).then((result) => {
|
||||
if (result) {
|
||||
if (result.data) {
|
||||
this.setState({
|
||||
signupdata: result.data
|
||||
})
|
||||
}
|
||||
}
|
||||
}).catch((error) => {
|
||||
////console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
getrightdatas=(e)=>{
|
||||
let keys = parseInt(e.key);
|
||||
this.getlistdata(keys)
|
||||
this.props.history.replace(`?menu=${keys}`);
|
||||
}
|
||||
|
||||
getlistdata=(keys,listkey)=>{
|
||||
|
||||
let{data}=this.state;
|
||||
this.setState({
|
||||
thiskeys:keys
|
||||
})
|
||||
data&&data.competition_modules.map((item,key)=>{
|
||||
if(item.module_type!="enroll") {
|
||||
if (keys === item.id) {
|
||||
this.getrightdata(item.id, item.module_type, item.module_url, item.has_url, listkey)
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getnewchartdata=(typeid,tabkey)=>{
|
||||
if(typeid==="chart"){
|
||||
let url=`/competitions/${this.props.match.params.identifier}/chart_rules.json`;
|
||||
axios.get(url)
|
||||
.then((response) => {
|
||||
if(response.status===200){
|
||||
this.setState({
|
||||
chart_rules:response.data,
|
||||
tabkey: tabkey === undefined ? response.data.stages[0].id === null ? "0" : `${response.data.stages[0].id}` : tabkey
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
}).catch((error) => {
|
||||
//console.log(error)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
getrightdata=(id,typeid,module_url,has_url,listkey)=>{
|
||||
|
||||
// if(typeid==="enroll"){
|
||||
// this.props.history.replace(`/competitions/${this.props.match.params.identifier}/enroll`);
|
||||
// return
|
||||
// }
|
||||
|
||||
this.getnewchartdata(typeid, listkey)
|
||||
|
||||
if(has_url===false){
|
||||
let url=`${module_url}`;
|
||||
axios.get(url).then((response) => {
|
||||
if(response.status===200){
|
||||
|
||||
if(typeid==="chart"){
|
||||
this.setState({
|
||||
chartdata:response.data
|
||||
})
|
||||
}else{
|
||||
this.setState({
|
||||
mdContentdata:response.data
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}).catch((error) => {
|
||||
//console.log(error)
|
||||
})
|
||||
}else{
|
||||
if (module_url.substring(0, 7) == 'http://' || module_url.substring(0, 8) == 'https://') {
|
||||
// window.location.href= module_url
|
||||
window.open(module_url)
|
||||
}else{
|
||||
window.open(`https://${module_url}`)
|
||||
// window.location.href=;
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
this.setState({
|
||||
module_id:id,
|
||||
module_type:typeid,
|
||||
has_url:has_url
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
Competitionedit=()=>{
|
||||
this.setState({
|
||||
Competitionedittype: true
|
||||
})
|
||||
}
|
||||
|
||||
hideCompetitionedit=()=>{
|
||||
this.setState({
|
||||
Competitionedittype:false
|
||||
})
|
||||
|
||||
}
|
||||
newgotocourse=(url)=>{
|
||||
if(this.props.checkIfLogin()===false){
|
||||
this.props.showLoginDialog()
|
||||
return
|
||||
}
|
||||
if(this.props.checkIfProfileCompleted()===false){
|
||||
this.props.showProfileCompleteDialog()
|
||||
return
|
||||
}
|
||||
window.open(url);
|
||||
|
||||
}
|
||||
|
||||
gotocourse=(url)=>{
|
||||
if(this.props.checkIfLogin()===false){
|
||||
this.props.showLoginDialog()
|
||||
return
|
||||
}
|
||||
if(this.props.checkIfProfileCompleted()===false){
|
||||
this.props.showProfileCompleteDialog()
|
||||
return
|
||||
}
|
||||
|
||||
if(url===undefined){
|
||||
let {data,signupdata}=this.state;
|
||||
// if(signupdata.enrolled===true){
|
||||
// this.props.history.replace(`/courses/${data.course_id}`);
|
||||
// }else{ }
|
||||
|
||||
if (data.member_of_course === true) {
|
||||
// this.props.history.replace(`/courses/${data.course_id}`);
|
||||
window.open(`/courses/${data.course_id}`)
|
||||
} else {
|
||||
// 以学生身份调用加入课堂 进入课堂首页
|
||||
let url = "/courses/apply_to_join_course.json"
|
||||
axios.post(url, {
|
||||
invite_code: data.invite_code,
|
||||
student: 1
|
||||
}
|
||||
).then((response) => {
|
||||
if (response.data.status === 0) {
|
||||
// this.props.history.replace();
|
||||
this.getbannerdata()
|
||||
window.open(`/courses/${data.course_id}`);
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}else{
|
||||
|
||||
if (url === "personal") {
|
||||
let urls = `/competitions/${this.props.match.params.identifier}/enroll`;
|
||||
this.Personalregistration(urls)
|
||||
} else {
|
||||
window.open(url);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Personalregistration = (urls) => {
|
||||
|
||||
let {signupdata} = this.state;
|
||||
|
||||
if (signupdata.enroll_ended === true) {
|
||||
//已截止
|
||||
this.props.showNotification(`报名已截止`);
|
||||
return;
|
||||
}
|
||||
if (signupdata.enrolled === true) {
|
||||
this.props.showNotification(`你已经报名,不能重复报名!`);
|
||||
return;
|
||||
}
|
||||
const url = `/competitions/${this.props.match.params.identifier}/competition_teams.json`;
|
||||
axios.post(url).then((response) => {
|
||||
if (response) {
|
||||
if (response.data) {
|
||||
this.props.showNotification(`报名成功,预祝您夺得桂冠!`);
|
||||
// this.props.history.replace(urls);
|
||||
this.getbannerdata()
|
||||
window.open(urls)
|
||||
}
|
||||
}
|
||||
}).catch((error) => {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Competitioncallback=(key)=>{
|
||||
this.setState({
|
||||
tabkey:key
|
||||
})
|
||||
let url=`/competitions/${this.props.match.params.identifier}/charts.json`;
|
||||
axios.get(url,{params:{
|
||||
stage_id:key===0||key===null?undefined:key
|
||||
}}).then((response) => {
|
||||
if(response.status===200){
|
||||
this.setState({
|
||||
chartdata:response.data
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
//console.log(error)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
let {data, module_type, Competitionedittype, signupdata} = this.state;
|
||||
|
||||
return (
|
||||
data===undefined?"":<div className={"educontent clearfix mt20 "}>
|
||||
|
||||
<Breadcrumb separator=">">
|
||||
<Breadcrumb.Item><Link to={"/competitions"}>在线竞赛</Link></Breadcrumb.Item>
|
||||
<Breadcrumb.Item>{data && data.name}</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
|
||||
<div className={"mt10 relative"}>
|
||||
|
||||
<Row className={"CompetitionCommonbanner"}>
|
||||
{data.competition_status === "nearly_published" ?
|
||||
data && data.permission.editable === true ? "" :
|
||||
<div className={"CompetitionsListzhezhao"}>即将发布 敬请期待</div> : ""}
|
||||
<img className={"Commonimg"}
|
||||
src={data.competition_status === "ended" ? getImageUrl(`images/educoder/competitions/groups1.png`) : data.competition_status === "nearly_published" ? getImageUrl(`images/educoder/competitions/groups2.png`) : data.competition_status === "progressing" ? getImageUrl(`images/educoder/competitions/groups3.png`) : ""}/>
|
||||
<Col span={15} className={"Commonimgbox"}>
|
||||
<img className={"image_urlbox"}
|
||||
src={data === undefined ? getImageUrl(`images/educoder/competitions/mainbanner.jpg`) : data.avatar_url === null ? getImageUrl(`images/educoder/competitions/mainbanner.jpg`) : getImageUrl(data.avatar_url)}/>
|
||||
</Col>
|
||||
<Col className={"CompetitionCommonbannerfont"} span={9}>
|
||||
|
||||
<Col
|
||||
className={data && data.name.length > 15 ? "competitionbannerdiv mt30" : "competitionbannerdiv mt30"}>{data && data.name}</Col>
|
||||
|
||||
<Col className={"competitionbannerdiv mt10"}>
|
||||
<Col className={"Competitioncolor9b"}>竞赛时间:<span
|
||||
className={"color000"}>{data && data.start_time}~{data && data.end_time}</span></Col>
|
||||
{/*<Col></Col>*/}
|
||||
</Col>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.ant-col-6{
|
||||
width: 30%;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
<Col className={"competitionbannerdiv mt10"}>
|
||||
<Row gutter={16}>
|
||||
<Col className="gutter-row" span={6}>
|
||||
<div className="gutter-box CompetitionsIndexdadels Competitioncolor77">奖金</div>
|
||||
</Col>
|
||||
<Col className="gutter-row ml20 rankbeicenter" span={6}>
|
||||
<div className="gutter-box CompetitionsIndexdadels Competitioncolor77">浏览数</div>
|
||||
</Col>
|
||||
<Col className="gutter-row rankbeicenter" span={6}>
|
||||
<div className="gutter-box CompetitionsIndexdadels Competitioncolor77">报名数</div>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={16}>
|
||||
<Col className="gutter-row" span={6}>
|
||||
<div
|
||||
className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516">¥{data && data.bonus}</div>
|
||||
</Col>
|
||||
<Col className="gutter-row ml20 rankbeicenter" span={6}>
|
||||
<div
|
||||
className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516">{data.competition_status === "nearly_published" ? "--" : data && data.visits_count}</div>
|
||||
</Col>
|
||||
<Col className="gutter-row rankbeicenter" span={6}>
|
||||
|
||||
{data.competition_status === "ended" ?
|
||||
<div className={data.mode === 2 ?data.member_of_course==true?"gutter-box CompetitionsIndexbottomvalue Competitioncolor516 cursorpointer":"gutter-box CompetitionsIndexbottomvalue Competitioncolor516":"gutter-box CompetitionsIndexbottomvalue Competitioncolor516 cursorpointer"}
|
||||
// 已结束onClick={data.competition_status === "nearly_published" ? "" : () => this.gotocourse(`/competitions/${this.props.match.params.identifier}/enroll`)}
|
||||
onClick={ data.mode === 2 ?data.member_of_course==true?() => this.newgotocourse(`/courses/${data.course_id}`):"":() => this.newgotocourse(`/competitions/${this.props.match.params.identifier}/enroll`)}
|
||||
>{data && data.member_count}</div>
|
||||
:data.competition_status === "nearly_published" ?
|
||||
<div className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516"
|
||||
// onClick={data.competition_status === "nearly_published" ? "" : () => this.gotocourse(`/competitions/${this.props.match.params.identifier}/enroll`)}
|
||||
>{"--"}</div> :
|
||||
data.competition_status === "progressing" ?
|
||||
data.mode === 2 ?
|
||||
<div className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516 cursorpointer" onClick={() => this.gotocourse()}>{data && data.member_count}</div> : signupdata && signupdata.personal === true ?
|
||||
<div className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516 cursorpointer" onClick={() => this.gotocourse("personal")}>{data && data.member_count}</div> : <div
|
||||
className="gutter-box CompetitionsIndexbottomvalue Competitioncolor516 cursorpointer"
|
||||
onClick={() => this.gotocourse(`/competitions/${this.props.match.params.identifier}/enroll`)}>{data && data.member_count}</div>
|
||||
:""}
|
||||
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
|
||||
{data.competition_status === "ended" ? <style>
|
||||
{
|
||||
`
|
||||
.Competitionfontsize22{
|
||||
height: 50px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style> : <style>
|
||||
{
|
||||
`
|
||||
.Competitionfontsize22{
|
||||
height: 50px;
|
||||
background: rgba(76,172,255,1);
|
||||
border-radius: 4px;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>}
|
||||
<Col className={"competitionbannerdiv mt20"}>
|
||||
{data.competition_status === "ended" ?
|
||||
<Button type="primary" block className={"Competitionfontsize22"} disabled={true}>
|
||||
已结束
|
||||
</Button> : data.enroll_end === true ?
|
||||
<Button type="primary" block className={"Competitionfontsize22"} disabled={true}>
|
||||
{data.competition_status === "nearly_published" ? "未发布" : "报名截止"}
|
||||
</Button> :
|
||||
data.competition_status === "progressing" ?
|
||||
<Button type="primary" block className={"Competitionfontsize22"}>
|
||||
{data.mode === 2 ?
|
||||
<a onClick={() => this.gotocourse()}>立即报名</a> : signupdata && signupdata.personal === true ?
|
||||
<a onClick={() => this.gotocourse("personal")}>立即报名</a> : <a
|
||||
onClick={() => this.gotocourse(`/competitions/${this.props.match.params.identifier}/enroll`)}>立即报名</a>}
|
||||
</Button>:""}
|
||||
</Col>
|
||||
<Col
|
||||
className={"mt10 Competitionfontsize16"}>{data && data.enroll_end_time === null ? "" : `报名截止时间:${data && data.enroll_end_time}`}</Col>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.CompetitionMenu .ant-menu-item a{
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space:nowrap
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
<Layout className={'teamsLayout mt40'}>
|
||||
<Sider>
|
||||
<Menu mode="inline" className="CompetitionMenu" selectedKeys={[`${this.state.thiskeys}`]}
|
||||
onClick={(e) => this.getrightdatas(e)}>
|
||||
{data && data.competition_modules.map((item, key) => {
|
||||
if (item.module_type != "enroll") {
|
||||
return (
|
||||
<Menu.Item key={item.id}>
|
||||
{/*{item.has_url===false?<span*/}
|
||||
{/*// onClick={()=>this.getrightdata(item.id,item.module_type,item.module_url,item.has_url)}*/}
|
||||
{/*>{item.name}</span>:<a*/}
|
||||
{/*// target="_blank"*/}
|
||||
{/*href={item.module_url}*/}
|
||||
{/*// onClick={()=>this.getrightdata(item.id,item.module_type)}*/}
|
||||
{/*>{item.name}</a>}*/}
|
||||
<a title={item.name}>{item.name}</a>
|
||||
</Menu.Item>
|
||||
)
|
||||
}
|
||||
})}
|
||||
</Menu>
|
||||
|
||||
{/*<Menu mode="inline" className="CompetitionMenu" onClick={(e)=>this.isdownloadpdf(e)}>*/}
|
||||
{/*<Menu.Item>*/}
|
||||
{/*<a>证书下载</a>*/}
|
||||
{/*</Menu.Item>*/}
|
||||
{/*</Menu>*/}
|
||||
</Sider>
|
||||
|
||||
{module_type === "certificate" ? "" : <Layout className={"teamsLayoutleft CompetitionContents mb30"}>
|
||||
{this.state.module_type === "chart" ? Competitionedittype === false ? <CompetitionContentsChart
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
Competitionedit={() => this.Competitionedit()}
|
||||
Competitioncallback={(e) => this.Competitioncallback(e)}
|
||||
/> : "" : Competitionedittype === false ? <CompetitionContents
|
||||
Competitionedit={() => this.Competitionedit()}
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
/> : ""}
|
||||
{/*<CompetitionContentsChart*/}
|
||||
{/*{...this.props}*/}
|
||||
{/*{...this.state}*/}
|
||||
{/*/>*/}
|
||||
{Competitionedittype === true ? <CompetitionContentsMd
|
||||
hideCompetitionedit={() => this.hideCompetitionedit()}
|
||||
getlistdata={(keys, listkey) => this.getlistdata(keys, listkey)}
|
||||
Competitioncallback={(e) => this.Competitioncallback(e)}
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
/> : ""}
|
||||
</Layout>}
|
||||
|
||||
{module_type === "certificate" ? <Layout className={"teamsLayoutleft CompetitionContents mb30"}>
|
||||
<CompetitionContentspdf
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
/>
|
||||
</Layout> : ""}
|
||||
</Layout>
|
||||
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
export default CompetitionCommon;
|
||||
@@ -0,0 +1,45 @@
|
||||
import React, { Component } from 'react';
|
||||
import {Button,Layout} from 'antd';
|
||||
import axios from 'axios';
|
||||
import {markdownToHTML,getImageUrl,AttachmentList} from 'educoder';
|
||||
|
||||
|
||||
const { Header, Footer, Sider, Content } = Layout;
|
||||
class CompetitionContents extends Component{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state={
|
||||
hash:undefined
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
window.document.title = '竞赛';
|
||||
this.props.MdifHasAnchorJustScorll();
|
||||
}
|
||||
|
||||
render() {
|
||||
let {mdContentdata, data} = this.props;
|
||||
//mdhash滚动
|
||||
this.props.MdifHasAnchorJustScorll();
|
||||
return (
|
||||
|
||||
<div className={"fr"}>
|
||||
{data && data.permission.editable === true ? this.props.Competitionedittype === false ? this.props.has_url === false ?
|
||||
<Button className={"fr"} type="primary" ghost onClick={() => this.props.Competitionedit()}>
|
||||
编辑
|
||||
</Button>:"":"":""}
|
||||
<div className={this.props.current_user&&this.props.current_user.admin===true||this.props.current_user&&this.props.current_user.business===true?"mt50 mb100 ":"mb100 "}>
|
||||
<Content className={"markdown-body"} dangerouslySetInnerHTML={{__html: markdownToHTML(mdContentdata===undefined?"":mdContentdata.md_content===undefined||mdContentdata.md_content===null?"":mdContentdata.md_content).replace(/▁/g, "▁▁▁")}}>
|
||||
</Content>
|
||||
|
||||
<div className={"mt30"}>
|
||||
<AttachmentList {...this.props} {...this.state} attachments={mdContentdata===undefined?[]:mdContentdata.attachments===undefined?[]:mdContentdata.attachments}></AttachmentList>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
export default CompetitionContents;
|
||||
@@ -0,0 +1,423 @@
|
||||
import React, { Component } from 'react';
|
||||
import {Button,Layout,Tabs,Icon, Card, Avatar, Row, Col ,Table,Badge} from 'antd';
|
||||
import {markdownToHTML,getImageUrl,getRandomNumber} from 'educoder';
|
||||
import axios from 'axios';
|
||||
|
||||
const { Content } = Layout;
|
||||
const { TabPane } = Tabs;
|
||||
const { Meta } = Card;
|
||||
|
||||
class CompetitionContents extends Component{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state={
|
||||
personal:undefined
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
window.document.title = '竞赛';
|
||||
let url=`/competitions/${this.props.match.params.identifier}/competition_staff.json`;
|
||||
axios.get(url)
|
||||
.then((response) => {
|
||||
if(response.status===200){
|
||||
console.log(response)
|
||||
this.setState({
|
||||
personal:response.data.personal
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
this.props.MdifHasAnchorJustScorll();
|
||||
}
|
||||
|
||||
derivefun=(url)=>{
|
||||
axios.get(url).then((response)=>{
|
||||
if(response === undefined){
|
||||
return
|
||||
}
|
||||
if(response.data.status&&response.data.status===-1){
|
||||
this.props.showNotification(response.data.message);
|
||||
}else if(response.data.status&&response.data.status===-2){
|
||||
// if(response.data.message === "100"){
|
||||
// // 已超出文件导出的上限数量(100 ),建议:
|
||||
//
|
||||
// this.setState({
|
||||
// DownloadType:true,
|
||||
// DownloadMessageval:100
|
||||
// })
|
||||
// }else {
|
||||
// //因附件资料超过500M
|
||||
// this.setState({
|
||||
// DownloadType:true,
|
||||
// DownloadMessageval:500
|
||||
// })
|
||||
// }
|
||||
this.props.showNotification(response.data.message);
|
||||
}else {
|
||||
// this.props.showNotification(`正在下载中`);
|
||||
// window.open("/api"+url, '_blank');
|
||||
this.props.slowDownload(url);
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
});
|
||||
}
|
||||
render() {
|
||||
this.props.MdifHasAnchorJustScorll();
|
||||
const operations = <div>
|
||||
<Button className={"fr"} type="primary" ghost onClick={()=>this.props.Competitionedit()}>编辑</Button>
|
||||
<Button className={"fr mr20"} type="primary" ghost>
|
||||
<a onClick={()=>this.derivefun(`/competitions/${this.props.match.params.identifier}/charts.xlsx?${getRandomNumber(true)}`)}>导出</a>
|
||||
</Button>
|
||||
</div>
|
||||
const columns = [
|
||||
{
|
||||
title: 'usersum',
|
||||
dataIndex: 'usersum',
|
||||
key: 'name',
|
||||
render: text => <span className={"color-blue"}>{text}</span>,
|
||||
},
|
||||
{
|
||||
title: 'userimg',
|
||||
dataIndex: 'userimg',
|
||||
key: 'userimg',
|
||||
render: (text, record) =>(
|
||||
<a href={`/users/${record.user_login}`} target={"_blank"} className="color-dark">
|
||||
<div className={"relativef"}>
|
||||
<img className={"Competitionuserimg mb10"} src={getImageUrl(`images/${record.userimg===null?`avatars/User/0?1442652658`:record.userimg}`)}/>
|
||||
<div className={"competimgabsoluteijmg"}><Badge count={record.competition_prize} style={{ backgroundColor: '#459BE5' }} title={record.competition_prize}/></div>
|
||||
</div>
|
||||
</a>),
|
||||
},
|
||||
{
|
||||
title: 'username',
|
||||
dataIndex: 'username',
|
||||
key: 'username',
|
||||
render: text => <span title={text} title={text}>{text}</span>,
|
||||
},
|
||||
{
|
||||
title: 'school',
|
||||
dataIndex: 'school',
|
||||
key: 'school',
|
||||
render: text => <span title={text} title={text}>{text}</span>,
|
||||
},
|
||||
{
|
||||
title: 'spendtime',
|
||||
dataIndex: 'spendtime',
|
||||
key: 'spendtime',
|
||||
render: text => <span>{text}</span>,
|
||||
},
|
||||
{
|
||||
title: 'score',
|
||||
dataIndex: 'score',
|
||||
key: 'score',
|
||||
render: text => <span className={"color-blue"}>{text}</span>,
|
||||
},
|
||||
];
|
||||
|
||||
const datas = [];
|
||||
let {chart_rules, chartdata, data} = this.props;
|
||||
let {personal}=this.state;
|
||||
|
||||
if(this.props&&this.props.mode!=1){
|
||||
|
||||
columns.some((item,key)=> {
|
||||
if (item.title === "spendtime") {
|
||||
columns.splice(key, 1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
{chartdata===undefined?"":chartdata.teams.length===0?"":chartdata.teams.map((item,key)=>{
|
||||
let list={
|
||||
usersum:key+1,
|
||||
userimg:item.user_image,
|
||||
username:personal===undefined||personal===null?item.record_user_name:personal===true?item.record_user_name:item.team_name,
|
||||
school:item.school_name,
|
||||
spendtime:item.spend_time,
|
||||
score:item.score<50?"< 50 分":item.score,
|
||||
user_login:item.user_login,
|
||||
competition_prize:item.competition_prize
|
||||
}
|
||||
datas.push(list)
|
||||
})}
|
||||
|
||||
// console.log(this.props&&this.props.mode)
|
||||
// console.log(columns)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.ant-tabs-nav .ant-tabs-tab{
|
||||
font-size: 20px;
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
.ant-badge{
|
||||
width:90px;
|
||||
}
|
||||
.ant-badge sup{
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
{chart_rules === undefined ? "" :
|
||||
<Tabs onChange={(e) => this.props.Competitioncallback(e)} activeKey={this.props.tabkey}
|
||||
tabBarExtraContent={data && data.permission.editable === true ? this.props.Competitionedittype === false ? this.props.has_url === false ? operations : "" : "" : ""}>
|
||||
{chart_rules.stages.map((item,key)=>{
|
||||
return(
|
||||
<TabPane tab={item.name} key={item.id===null?0:item.id}>
|
||||
{chart_rules.rule_contents.map((items,keys)=>{
|
||||
if(item.id===items.competition_stage_id){
|
||||
return(
|
||||
<Content key={keys} className={"markdown-body "} dangerouslySetInnerHTML={{__html: markdownToHTML(items.content===undefined||items.content===null?"":items.content).replace(/▁/g, "▁▁▁")}}></Content>
|
||||
)
|
||||
}else if(item.id===null&&items.competition_stage_id===0){
|
||||
return(
|
||||
<Content key={keys} className={"markdown-body "} dangerouslySetInnerHTML={{__html: markdownToHTML(items.content===undefined||items.content===null?"":items.content).replace(/▁/g, "▁▁▁")}}></Content>
|
||||
)
|
||||
}
|
||||
})}
|
||||
</TabPane>
|
||||
)
|
||||
})}
|
||||
</Tabs>}
|
||||
|
||||
|
||||
<Col className="gutter-row Competitioncharts mt30 mb30">总排名</Col>
|
||||
{chartdata===undefined?"":chartdata.teams.length===0?<Col className="gutter-row Competitioncharts mt30 mb30 rankbeicenter">
|
||||
<img src={getImageUrl(`images/educoder/competitions/trophy.png`)}/>
|
||||
<div className={"rankbei mt10"}>要抓住一切机会,向所有人证明你自己,证明你能够迎接荣耀</div>
|
||||
</Col>:""}
|
||||
<Row calssName={"Competition399"}>
|
||||
{chartdata===undefined?"":chartdata.teams.length===0?"":chartdata.teams.map((item,key)=>{
|
||||
|
||||
|
||||
if(key===1){
|
||||
return(
|
||||
<Col className="mt40" xs={{ span: 5, offset: 1 }} lg={{ span: 6, offset: 2 }}>
|
||||
<Card
|
||||
className={"Competitionthird"}
|
||||
cover={
|
||||
<div className={"Competitionthirdbox center"}>
|
||||
<li className="pr Competitioncenter">
|
||||
<img src={getImageUrl("images/educoder/huangguan-two.png")}/>
|
||||
<div className={"mt10"}>
|
||||
<a href={`/users/${item.user_login}`} target={"_blank"} className="color-dark ">
|
||||
<div className={"relativef"}>
|
||||
<img className={"rankingimg"} src={getImageUrl(`images/${item.user_image===null?`avatars/User/0?1442652658`:item.user_image}`)} />
|
||||
<div className={"competimgabsolute"}><Badge count={item.competition_prize} style={{ backgroundColor: '#459BE5' }} title={item.competition_prize}/></div>
|
||||
</div>
|
||||
<p className="task-hide rankName mt5 jinshaifont">{personal===undefined||personal===null?item.record_user_name:personal===true?item.record_user_name:item.team_name}</p>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Meta
|
||||
title={<div className={"center"}>
|
||||
<div className={"rankfonttop"} title={item.school_name}>{item.school_name}</div>
|
||||
{this.props&&this.props.mode===1?<div className={"rankfontmid"}>{item.spend_time}</div>:""}
|
||||
</div>}
|
||||
description={
|
||||
<div className={"rankfontbottom"}>{item.score<50?"< 50 分":item.score}分</div>
|
||||
}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
})}
|
||||
{chartdata===undefined?"":chartdata.teams.length===0?"":chartdata.teams.map((item,key)=>{
|
||||
if(key===0){
|
||||
return(
|
||||
<Col xs={{ span: 11, offset: 1 }} lg={{ span: 6, offset: 1 }}>
|
||||
<Card
|
||||
className={"Competitionfirst"}
|
||||
cover={
|
||||
<div className={"Competitionfirstbox center"}>
|
||||
<li className="pr Competitioncenter">
|
||||
<img src={getImageUrl("images/educoder/huangguan.png")}/>
|
||||
<div className={"mt10"}>
|
||||
<a href={`/users/${item.user_login}`} target={"_blank"} className="color-dark">
|
||||
<div className={"relativef"}>
|
||||
<img className={"rankingimg"} src={getImageUrl(`images/${item.user_image===null?`avatars/User/0?1442652658`:item.user_image}`)} />
|
||||
<div className={"competimgabsolute"}><Badge count={item.competition_prize} style={{ backgroundColor: '#459BE5' }} title={item.competition_prize}/></div>
|
||||
</div>
|
||||
<p className="task-hide rankName mt5 jinshaifont">{personal===undefined||personal===null?item.record_user_name:personal===true?item.record_user_name:item.team_name}</p>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Meta
|
||||
title={<div className={"center"}>
|
||||
<div className={"rankfonttop"} title={item.school_name}>{item.school_name}</div>
|
||||
{this.props&&this.props.mode===1?<div className={"rankfontmid"}>{item.spend_time}</div>:""}
|
||||
</div>}
|
||||
description={
|
||||
<div className={"rankfontbottoms"}>{item.score<50?"< 50 分":item.score}分</div>
|
||||
}
|
||||
|
||||
/>
|
||||
</Card>
|
||||
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
})}
|
||||
{chartdata===undefined?"":chartdata.teams.length===0?"":chartdata.teams.map((item,key)=>{
|
||||
if(key===2){
|
||||
return(
|
||||
<Col className="mt30" xs={{ span: 5, offset: 1 }} lg={{ span: 6, offset: 1 }}>
|
||||
<Card
|
||||
className={"Competitionsecondary "}
|
||||
cover={
|
||||
<div className={"Competitionsecondarybox center"}>
|
||||
<li className=" pr Competitioncenter ">
|
||||
<img src={getImageUrl("images/educoder/huangguan-three.png")}/>
|
||||
<div className={"mt10"}>
|
||||
<a href={`/users/${item.user_login}`} target={"_blank"} className="color-dark">
|
||||
<div className={"relativef"}>
|
||||
<img className={"rankingimg"} src={getImageUrl(`images/${item.user_image===null?`avatars/User/0?1442652658`:item.user_image}`)} />
|
||||
<div className={"competimgabsolute"}><Badge count={item.competition_prize} style={{ backgroundColor: '#459BE5' }} title={item.competition_prize}/></div>
|
||||
</div>
|
||||
<p className="task-hide rankName mt5 jinshaifont">{personal===undefined||personal===null?item.record_user_name:personal===true?item.record_user_name:item.team_name}</p>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Meta
|
||||
title={<div className={"center"}>
|
||||
<div className={"rankfonttop"} title={item.school_name}>{item.school_name}</div>
|
||||
{this.props&&this.props.mode===1?<div className={"rankfontmid"}>{item.spend_time}</div>:""}
|
||||
</div>}
|
||||
description={
|
||||
<div className={"rankfontbottom"}>{item.score<50?"< 50 分":item.score}分</div>
|
||||
}
|
||||
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
})}
|
||||
|
||||
</Row>
|
||||
{chartdata===undefined?"":chartdata.user_ranks.length===0?"":<div className={"youranklist mt50"}>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.ant-col-9 {
|
||||
width: 35.5%;
|
||||
}
|
||||
.col13{
|
||||
width:13%;
|
||||
text-align:left;
|
||||
}
|
||||
.col24{
|
||||
width: 24%;
|
||||
text-align: left;
|
||||
padding-left: 33px;
|
||||
}
|
||||
.col15{
|
||||
width: 14%;
|
||||
text-align: right;
|
||||
}
|
||||
.col12{
|
||||
width: 12%;
|
||||
text-align: right;
|
||||
}
|
||||
.col10{
|
||||
width: 10%;
|
||||
}
|
||||
.col6{
|
||||
width: 6%;
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
</style>
|
||||
{chartdata.user_ranks.map((item,key)=>{
|
||||
|
||||
return(
|
||||
<Row type="flex" key={key}>
|
||||
<Col span={4} order={1} className={"col13"}>
|
||||
<span className={"ranknames"}>您当前排名:{item.rank}</span>
|
||||
</Col>
|
||||
<Col className="userranksclass" span={3} order={2} className={"col24"}>
|
||||
{personal===undefined||personal===null?item.record_user_name:personal===true?item.user_name:item.team_name}
|
||||
</Col>
|
||||
<Col className="textleft" span={9} order={3}>
|
||||
{/*{item.team_name}*/}
|
||||
</Col>
|
||||
{item.cost_time=== "--"?<Col span={3} order={4} className={"col6"}>
|
||||
{this.props&&this.props.mode===1?item.cost_time:""}
|
||||
</Col>:<Col span={3} order={4} className={"col10"}>
|
||||
{this.props&&this.props.mode===1?item.cost_time:""}
|
||||
</Col>}
|
||||
{item.cost_time=== "--"?<Col className="textright" span={3} order={5} className={"col15"}>
|
||||
<span className={"ranknameslast"}>{item.score<50?"< 50 分":item.score}</span>
|
||||
</Col>:<Col className="textright" span={3} order={5} className={"col12"}>
|
||||
<span className={"ranknameslast"}>{item.score<50?"< 50 分":item.score}</span>
|
||||
</Col>}
|
||||
</Row>
|
||||
)
|
||||
})}
|
||||
</div>}
|
||||
<Row className={"mt20 mb80"}>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.ant-table-tbody > tr > td:nth-last-child(4){
|
||||
overflow: hidden;
|
||||
max-width: 100px;
|
||||
-o-text-overflow: ellipsis;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
}
|
||||
.ant-table-tbody > tr > td:nth-last-child(3){
|
||||
overflow: hidden;
|
||||
max-width: 200px;
|
||||
-o-text-overflow: ellipsis;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
}
|
||||
.ant-table-tbody>tr>td, .ant-table-thead>tr>th {
|
||||
padding: 5px;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
{chartdata === undefined ? "" : chartdata.teams.length === 0 ? "" :
|
||||
<Table className="Competitiontransparent" columns={columns} dataSource={datas} showHeader={false}
|
||||
pagination={false}/>}
|
||||
</Row>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
export default CompetitionContents;
|
||||
@@ -0,0 +1,232 @@
|
||||
import React, { Component } from 'react';
|
||||
import {Button, Card, Row, Col ,Upload,Icon,message,Tabs} from 'antd';
|
||||
import axios from 'axios';
|
||||
import {getUploadActionUrl,getUrl,appendFileSizeToUploadFileAll,appendFileSizeToUploadFile} from 'educoder';
|
||||
import TPMMDEditor from '../../../tpm/challengesnew/TPMMDEditor';
|
||||
const { TabPane } = Tabs;
|
||||
class CompetitionContentsMd extends Component{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.contentMdRef = React.createRef();
|
||||
this.state={
|
||||
contentFileList:[],
|
||||
chartmodule_id:undefined
|
||||
}
|
||||
}
|
||||
componentDidUpdate =(prevState)=>{
|
||||
if(prevState!=this.props){
|
||||
this.getchartdata();
|
||||
}
|
||||
}
|
||||
componentDidMount(){
|
||||
window.document.title = '竞赛';
|
||||
|
||||
this.getchartdata()
|
||||
}
|
||||
|
||||
getchartdata=()=>{
|
||||
let {mdContentdata,chart_rules}=this.props;
|
||||
|
||||
// is_pdf: false
|
||||
if(this.props.module_type==="chart"){
|
||||
let type=true;
|
||||
if(chart_rules===undefined){
|
||||
|
||||
}else{
|
||||
chart_rules.rule_contents.map((items,keys)=>{
|
||||
debugger
|
||||
if(parseInt(this.props.tabkey)===items.competition_stage_id){
|
||||
console.log(items)
|
||||
this.contentMdRef.current.setValue(items.content);
|
||||
this.setState({
|
||||
contentFileList:undefined,
|
||||
chartmodule_id:items.id
|
||||
})
|
||||
type=false;
|
||||
}
|
||||
})
|
||||
|
||||
if(type===true){
|
||||
this.contentMdRef.current.setValue("");
|
||||
this.setState({
|
||||
contentFileList:undefined,
|
||||
chartmodule_id:undefined
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}else{
|
||||
let contentFileList = mdContentdata===undefined?[]:mdContentdata.attachments===undefined?[]:mdContentdata.attachments.map((item) => {
|
||||
return {
|
||||
id: item.id,
|
||||
uid: item.id,
|
||||
name: appendFileSizeToUploadFile(item),
|
||||
url: item.url,
|
||||
filesize: item.filesize,
|
||||
status: 'done',
|
||||
response:{id: item.id}
|
||||
}
|
||||
})
|
||||
this.setState({
|
||||
contentFileList:contentFileList
|
||||
})
|
||||
this.contentMdRef.current.setValue(mdContentdata===undefined?"":mdContentdata.md_content===undefined?"":mdContentdata.md_content || '')
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
handleContentUploadChange = (info) => {
|
||||
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
|
||||
let contentFileList = info.fileList;
|
||||
this.setState({ contentFileList: appendFileSizeToUploadFileAll(contentFileList) });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
onAttachmentRemove = (file, stateName) => {
|
||||
if(file.response!=undefined){
|
||||
this.props.confirm({
|
||||
content: '是否确认删除?',
|
||||
|
||||
onOk: () => {
|
||||
this.deleteAttachment(file, stateName)
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
deleteAttachment = (file, stateName) => {
|
||||
// 初次上传不能直接取uid
|
||||
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
|
||||
axios.delete(url, {
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data) {
|
||||
const { status } = response.data;
|
||||
if (status == 0) {
|
||||
console.log('--- success')
|
||||
this.props.showNotification(response.data.message);
|
||||
this.setState((state) => {
|
||||
const index = state[stateName].indexOf(file);
|
||||
const newFileList = state[stateName].slice();
|
||||
newFileList.splice(index, 1);
|
||||
return {
|
||||
[stateName]: newFileList,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
handleSubmit = () => {
|
||||
let {contentFileList}=this.state;
|
||||
const mdContnet = this.contentMdRef.current.getValue().trim();
|
||||
// if(mdContnet.length>10000){
|
||||
// this.props.showNotification("内容超过10000个字");
|
||||
// return
|
||||
// }
|
||||
let attachment_ids=undefined
|
||||
if(contentFileList!=undefined){
|
||||
attachment_ids= contentFileList.map(item => {
|
||||
return item.response ? item.response.id : item.id
|
||||
})
|
||||
}
|
||||
|
||||
let newstage_id=parseInt(this.props.tabkey)===0||null?undefined:parseInt(this.props.tabkey)
|
||||
let data={}
|
||||
if(this.props.module_type==="chart"){
|
||||
data={
|
||||
md_content_id:this.state.chartmodule_id,
|
||||
competition_module_id:this.props.module_id,
|
||||
stage_id:newstage_id,
|
||||
content:mdContnet,
|
||||
}
|
||||
}else{
|
||||
data={
|
||||
md_content_id:this.props.mdContentdata.md_id,
|
||||
competition_module_id:this.props.mdContentdata.id,
|
||||
content:mdContnet,
|
||||
attachment_ids:attachment_ids
|
||||
}
|
||||
}
|
||||
|
||||
let url=`/competitions/${this.props.match.params.identifier}/update_md_content.json`;
|
||||
axios.post(url,data
|
||||
).then((response) => {
|
||||
if(response.data.status===0){
|
||||
this.props.showNotification(response.data.message);
|
||||
this.props.getlistdata(this.props.thiskeys,this.props.tabkey);
|
||||
this.props.hideCompetitionedit();
|
||||
}else{
|
||||
this.props.showNotification(response.data.message);
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
}
|
||||
render() {
|
||||
let {contentFileList}=this.state;
|
||||
let {chart_rules}=this.props;
|
||||
const uploadProps = {
|
||||
width: 600,
|
||||
fileList: contentFileList,
|
||||
multiple: true,
|
||||
// https://github.com/ant-design/ant-design/issues/15505
|
||||
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
|
||||
// showUploadList: false,
|
||||
action: `${getUploadActionUrl()}`,
|
||||
onChange: this.handleContentUploadChange,
|
||||
onRemove: (file) => this.onAttachmentRemove(file, 'contentFileList'),
|
||||
beforeUpload: (file) => {
|
||||
console.log('beforeUpload', file.name);
|
||||
const isLt150M = file.size / 1024 / 1024 < 150;
|
||||
if (!isLt150M) {
|
||||
this.props.showNotification("文件大小必须小于150MB");
|
||||
}
|
||||
return isLt150M;
|
||||
},
|
||||
};
|
||||
// console.log(this.props.tabkey)
|
||||
// console.log(chart_rules)
|
||||
console.log(this.props.mdContentdata)
|
||||
return (
|
||||
<div>
|
||||
{chart_rules===undefined?"":this.props.module_type==="chart"?<Tabs activeKey={this.props.tabkey} onChange={(e)=>this.props.Competitioncallback(e)}>
|
||||
|
||||
{chart_rules.stages.map((item,key)=>{
|
||||
return(
|
||||
<TabPane tab={item.name} key={item.id===null?0:item.id}></TabPane>
|
||||
)
|
||||
})}
|
||||
|
||||
</Tabs>:""}
|
||||
<TPMMDEditor ref={this.contentMdRef} placeholder="请输入内容说明" mdID={'courseContentMD'} refreshTimeout={1500}
|
||||
className="courseMessageMD" initValue={this.state.description}></TPMMDEditor>
|
||||
{this.props.module_type==="chart"?"":<Upload {...uploadProps} className="upload_1 newWorkUpload">
|
||||
<Button className="uploadBtn">
|
||||
<Icon type="upload" /> 上传附件
|
||||
</Button>
|
||||
(单个文件150M以内)
|
||||
</Upload>}
|
||||
|
||||
<div className="clearfix mt30 mb30">
|
||||
{/* htmlType="submit" */}
|
||||
<Button type="primary" onClick={this.handleSubmit} className="defalutSubmitbtn fl mr20">提交</Button>
|
||||
<a className="defalutCancelbtn fl" onClick={() => this.props.hideCompetitionedit()}>取消</ a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
export default CompetitionContentsMd;
|
||||
@@ -0,0 +1,64 @@
|
||||
import React, { Component } from 'react';
|
||||
import {Tabs} from 'antd';
|
||||
import axios from 'axios';
|
||||
import {markdownToHTML,getImageUrl,AttachmentList} from 'educoder';
|
||||
import CompetitionContentspdfdownload from './CompetitionContentspdfChild/CompetitionContentspdfdownload';
|
||||
import CompetitionContentspdfpeopledata from './CompetitionContentspdfChild/CompetitionContentspdfpeopledata';
|
||||
// import NoneData from "../../../courses/shixunHomework/shixunHomework";
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
class CompetitionContentspdf extends Component{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state={
|
||||
Tabskey:"1"
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
window.document.title = '竞赛';
|
||||
let query=this.props.location&&this.props.location.search;
|
||||
const types = query.split('user_id=')
|
||||
if(types[1]===undefined){
|
||||
}else{
|
||||
this.setState({
|
||||
Tabskey:"2"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Competitioncallback=(key)=>{
|
||||
this.setState({
|
||||
Tabskey:key
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
|
||||
return (
|
||||
|
||||
<div className={"fr"}>
|
||||
<div className={"mb100 "}>
|
||||
<Tabs defaultActiveKey="1" onChange={(e) => this.Competitioncallback(e)} activeKey={this.state.Tabskey}>
|
||||
<TabPane tab="获奖证书下载" key="1" >
|
||||
{this.state.Tabskey==="1"?<CompetitionContentspdfdownload
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
Competitioncallback={(e)=>this.Competitioncallback(e)}
|
||||
/>:""}
|
||||
</TabPane>
|
||||
<TabPane tab="完善个人信息" key="2">
|
||||
{this.state.Tabskey==="2"?<CompetitionContentspdfpeopledata
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
/>:""}
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
export default CompetitionContentspdf;
|
||||
@@ -0,0 +1,292 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Button, Layout, Input, Form} from 'antd';
|
||||
import axios from 'axios';
|
||||
import {getImageUrl} from 'educoder';
|
||||
import mycompetotionchild from './mycompetotionchild.css';
|
||||
import {getHiddenName} from "../../../../user/account/AccountBasicEdit";
|
||||
import '../../../../courses/css/Courses.css'
|
||||
|
||||
export const identityMap = {"teacher": "教师", "student": "学生", "professional": "专业人士"}
|
||||
|
||||
class Bankcardnumberverification extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
basicInfo: {},
|
||||
updating: '',
|
||||
secondsFlag: false,
|
||||
seconds: 60,
|
||||
phonebool: false,
|
||||
emailbool: false,
|
||||
formationdata: [],
|
||||
bank_account_editable: false,
|
||||
leader: false,
|
||||
bank_account: undefined,
|
||||
certification: 1
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.document.title = '竞赛';
|
||||
// console.log("3获取用户信息");
|
||||
// console.log(this.props)
|
||||
try {
|
||||
this.props.triggerRef(this);
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
console.log(this.props.bank_account);
|
||||
|
||||
//初始化值
|
||||
if (this.props.bank_account) {
|
||||
this.props.form.setFieldsValue({
|
||||
openingbank: this.props.bank_account.bank,
|
||||
subbranch: this.props.bank_account.second_bank,
|
||||
subbranchs: this.props.bank_account.card_no,
|
||||
})
|
||||
this.setState({
|
||||
openingbank: this.props.bank_account.bank,
|
||||
subbranch: this.props.bank_account.second_bank,
|
||||
subbranchs: this.props.bank_account.card_no,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setdata(bank,second_bank,card_no){
|
||||
this.props.form.setFieldsValue({
|
||||
openingbank: bank,
|
||||
subbranch: second_bank,
|
||||
subbranchs:card_no,
|
||||
})
|
||||
}
|
||||
componentDidUpdate = (prevProps) => {
|
||||
if (prevProps.bank_account != this.props.bank_account) {
|
||||
console.log("componentDidUpdate");
|
||||
console.log(this.props);//是新数据
|
||||
console.log(prevProps);//是老数据
|
||||
////console.log("Registration");
|
||||
////console.log("componentDidUpdate");
|
||||
////console.log(this.props.user.admin);
|
||||
try {
|
||||
if(this.props.bank_account){
|
||||
this.props.form.setFieldsValue({
|
||||
openingbank: this.props.bank_account.bank,
|
||||
subbranch: this.props.bank_account.second_bank,
|
||||
subbranchs: this.props.bank_account.card_no,
|
||||
})
|
||||
}
|
||||
this.setState({
|
||||
openingbank: this.props.bank_account.bank,
|
||||
subbranch: this.props.bank_account.second_bank,
|
||||
subbranchs: this.props.bank_account.card_no,
|
||||
})
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
yhBankstrue = () => {
|
||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
let url = `/competitions/${this.props.match.params.identifier}/prize_leader_account.json`;
|
||||
axios.patch(url, {
|
||||
user_id:this.props.userdata.id,
|
||||
bank: values.openingbank,
|
||||
second_bank: values.subbranch ,
|
||||
card_no: values.subbranchs
|
||||
})
|
||||
.then((result) => {
|
||||
try {
|
||||
if (result.data.status === 0) {
|
||||
try {
|
||||
// console.log(values.openingbank);
|
||||
// console.log(values.subbranch);
|
||||
// console.log(values.subbranchs);
|
||||
this.props.form.setFieldsValue({
|
||||
openingbank: values.openingbank,
|
||||
subbranch: values.subbranch,
|
||||
subbranchs: values.subbranchs,
|
||||
});
|
||||
this.setState({
|
||||
openingbank: values.openingbank,
|
||||
subbranch: values.subbranch,
|
||||
subbranchs: values.subbranchs,
|
||||
})
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
this.props.showNotification(`提交成功,等待审核!`);
|
||||
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
try {
|
||||
this.props.getdata(this.props.userdata.id);
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
try {
|
||||
this.props.GetawardinformationAPI();
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
const {getFieldDecorator} = this.props.form;
|
||||
const {updating, seconds, secondsFlag, basicInfo, phonebool, emailbool, certification, formationdata, bank_account_editable, leader, bank_account} = this.state
|
||||
return (
|
||||
<div>
|
||||
<div className="flexdirections mt36">
|
||||
<p className="fontcolorsyslhei font-16">签/领/开户行及银行卡号</p>
|
||||
<p className="fontcolorsyslhui font-14 ml11">为保障奖金的及时发放,请队长如实填写你名下的银行卡信息</p>
|
||||
</div>
|
||||
<div className="ml38">
|
||||
<style>{`
|
||||
|
||||
.flexRow {
|
||||
padding: 20px 0;
|
||||
}
|
||||
.flexRow .name {
|
||||
margin-left: 12px;
|
||||
color: #666666;
|
||||
|
||||
text-align: center;
|
||||
flex: 0 0 100px;
|
||||
}
|
||||
.flexRow .description {
|
||||
margin-left: 10px;
|
||||
flex: 1;
|
||||
color: #CDCDCD;
|
||||
}
|
||||
.description span {
|
||||
margin-right: 20px;
|
||||
color: #05101A;
|
||||
}
|
||||
.flexRow .status {
|
||||
width: 100px;
|
||||
color: #28AC7F;
|
||||
text-align: right;
|
||||
}
|
||||
.flexTable .flexTable {
|
||||
border-bottom: 1px solid #EBEBEB;
|
||||
}
|
||||
|
||||
.settingFormsy label{
|
||||
color: #666666;
|
||||
font-size: 14px !important ;
|
||||
|
||||
}
|
||||
.settingFormsy input {
|
||||
width: 340px;
|
||||
height: 40px;
|
||||
}
|
||||
.settingFormsy input.validateInput {
|
||||
width: 220px;
|
||||
}
|
||||
.settingFormsy .formItemInline button {
|
||||
width: 110px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.settingFormsy .ant-form-item-label {
|
||||
width: 60px;
|
||||
text-align: left;
|
||||
}
|
||||
.formItemInline .ant-form-explain{
|
||||
position:absolute;
|
||||
bottom:-22px;
|
||||
left:0px;
|
||||
width:100%;
|
||||
}
|
||||
.yslzxueshi .ant-input{
|
||||
height: 40px !important;
|
||||
width: 276px !important
|
||||
}
|
||||
|
||||
// class="ant-col ant-form-item-label"
|
||||
`}</style>
|
||||
<div className="settingFormsy">
|
||||
<React.Fragment>
|
||||
<Form>
|
||||
<Form.Item
|
||||
label="开户行:"
|
||||
className="formItemInline hideRequireTag mb20 mt20"
|
||||
>
|
||||
{getFieldDecorator('openingbank', {
|
||||
rules: [{
|
||||
initialValue:this.state.openingbank,
|
||||
required: true,
|
||||
message: '请输入开户行',
|
||||
}],
|
||||
})(
|
||||
<Input placeholder={`例如:中国工商银行`}></Input>
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="支行:"
|
||||
className="formItemInline hideRequireTag mb20 mt20"
|
||||
>
|
||||
{getFieldDecorator('subbranch', {
|
||||
rules: [{
|
||||
initialValue: this.state.subbranch,
|
||||
required: true,
|
||||
message: '请输入支行',
|
||||
}],
|
||||
})(
|
||||
<Input placeholder={`例如:长沙天河支行`}></Input>
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="账号:"
|
||||
className="formItemInline hideRequireTag mb20 mt20"
|
||||
>
|
||||
{getFieldDecorator('subbranchs', {
|
||||
rules: [{
|
||||
initialValue: this.state.subbranchs,
|
||||
required: true,
|
||||
message: '请输入账号',
|
||||
}],
|
||||
})(
|
||||
<Input placeholder={`请填写银行卡账号`}></Input>
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
<div className="flexdirections yslzxueshi ml38 mt34">
|
||||
<p className="fontcolorsyslhui1 font-14 w300 myysllineheight myyslminwidth"></p>
|
||||
<div className="myyslminwidth276 flexdirections">
|
||||
{/*<div className="buttongo mycompitcursor" onClick={()=>this.yhBanksfalse()}><p className="fontwenzi mycompitcursor" >取消</p></div>*/}
|
||||
<Button type="primary" onClick={() => this.yhBankstrue()}>确定</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</Form>
|
||||
</React.Fragment>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const Bankcardnumberverifications = Form.create({name: 'Bankcardnumberverification'})(Bankcardnumberverification);
|
||||
|
||||
export default Bankcardnumberverifications;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
.pdfdownload {
|
||||
max-width: 791px;
|
||||
height: 40px;
|
||||
background: rgba(249, 249, 249, 1);
|
||||
line-height: 40px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.pdfpicture {
|
||||
font-size: 16px;
|
||||
color: rgba(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
.pdfdownloadfont4CACFF {
|
||||
color: #4CACFF !important;
|
||||
}
|
||||
|
||||
.pdfdownloadfont00CC5F {
|
||||
color: #00CC5F;
|
||||
}
|
||||
|
||||
.pdfdownloadfontFF6602 {
|
||||
color: #FF6602;
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
import React, { Component } from 'react';
|
||||
import {Button,Layout,Row, Col,Divider,Table} from 'antd';
|
||||
import axios from 'axios';
|
||||
import {getImageUrl,getRandomcode} from 'educoder';
|
||||
import './CompetitionContentspdfdownload.css';
|
||||
// import NoneData from "../../../courses/shixunHomework/shixunHomework";
|
||||
|
||||
|
||||
class CompetitionContentspdfdownload extends Component{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state={
|
||||
data:undefined,
|
||||
teams:undefined
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
window.document.title = '竞赛';
|
||||
let url=`/competitions/${this.props.match.params.identifier}/prize.json`;
|
||||
let query=this.props.location&&this.props.location.search;
|
||||
const types = query.split('user_id=')
|
||||
let userid;
|
||||
if(types[1]===undefined){
|
||||
userid=this.props.user&&this.props.user.user_id;
|
||||
}else{
|
||||
userid=types[1];
|
||||
}
|
||||
axios.get(url,{params:{
|
||||
user_id:userid,
|
||||
}
|
||||
}).then((response) => {
|
||||
if(response.status===200){
|
||||
|
||||
let datas=response.data.teams;
|
||||
if(datas.length>0){
|
||||
datas.map((item,key)=>{
|
||||
let lista=item.team_members;
|
||||
if(lista.length>0){
|
||||
console.log(lista)
|
||||
lista.map((i,k)=>{
|
||||
i["bank_account"]=item.bank_account;
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
this.setState({
|
||||
data:response.data,
|
||||
teams:datas,
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
|
||||
|
||||
let {data,teams}=this.state;
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '角色',
|
||||
dataIndex: 'type',
|
||||
key: 'type',
|
||||
render: (text, record) => (
|
||||
<span>
|
||||
{record.role}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
render: (text, record) => (
|
||||
<span>
|
||||
{record.name}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '实名认证',
|
||||
dataIndex: 'namecertify',
|
||||
key: 'namecertify',
|
||||
render: (text, record) => (
|
||||
<span>
|
||||
{record.real_name_auth==="authed"?<span className={"pdfdownloadfont00CC5F"}>已认证</span>:record.real_name_auth==="authing"?<span className={"pdfdownloadfontFF6602"}>待审核</span>:record.real_name_auth==="not_authed"?<span className={"color-red"}>未认证</span>:""}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '职业认证',
|
||||
key: 'certify',
|
||||
dataIndex: 'certify',
|
||||
render: (text, record) => (
|
||||
<span>
|
||||
{record.professional_auth==="authed"?<span className={"pdfdownloadfont00CC5F"}>已认证</span>:record.professional_auth==="authing"?<span className={"pdfdownloadfontFF6602"}>待审核</span>:record.professional_auth==="not_authed"?<span className={"color-red"}>未认证</span>:""}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '手机绑定',
|
||||
key: 'mobile',
|
||||
dataIndex: 'mobile',
|
||||
render: (text, record) => (
|
||||
<span>
|
||||
{record.phone_binded===true?<span className={"pdfdownloadfont00CC5F"}>已绑定</span>:<span className={"color-red"}>未绑定</span>}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '邮箱绑定',
|
||||
key: 'mail',
|
||||
dataIndex: 'mail',
|
||||
render: (text, record) => (
|
||||
<span>
|
||||
{record.email_binded===true?<span className={"pdfdownloadfont00CC5F"}>已绑定</span>:<span className={"color-red"}>未绑定</span>}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '开户行及银行卡号信息(队长填写)',
|
||||
key: 'idcard',
|
||||
dataIndex: 'idcard',
|
||||
render: (value, record, index) => {
|
||||
if (index === 0&&record.bank_account!=null) {
|
||||
return {
|
||||
children: <span>{record.bank_account.bank + record.bank_account.second_bank + record.bank_account.card_no}</span>,
|
||||
};
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
let people=[ { url: '/api/competitions/xxxxx/certificates/1/personal' },
|
||||
{ url: '/api/competitions/xxxxx/certificates/2/personal' },]
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Row>
|
||||
<Col className={"pdfdownload"}>温馨提示:填写的个人信息经审批后,将提供个人获奖证书下载;团队队员信息全部审批后,将提供团队获奖证书下载。</Col>
|
||||
</Row>
|
||||
|
||||
<Row className={"mt30"}>
|
||||
<Col className={"pdfpicture"}>证书情况</Col>
|
||||
</Row>
|
||||
|
||||
<Row className={"mt30"}>
|
||||
<Col>个人证书:{data&&data.personal_certifications.length===0&&data&&data.all_certified===false?
|
||||
<span><span className={"pdfpicture font-14"}>暂未生成</span> <span className={"ml20"}>原因:<span className={"pdfpicture font-14"}>还未认证个人信息,</span><a className={"pdfdownloadfont4CACFF"} onClick={()=>this.props.Competitioncallback("2")}>立即认证</a></span></span>:
|
||||
data&&data.personal_certifications.length===0&&data&&data.all_certified===true?
|
||||
<span><span className={"pdfpicture font-14"}>暂未生成</span> <span className={"ml20"}>原因:<span className={"pdfpicture font-14"}>组委会未完成证书审批,请稍后</span></span></span>:
|
||||
data&&data.personal_certifications.map((item,key)=>{
|
||||
return(
|
||||
<span className={"mr10"} key={key}>
|
||||
<img src={ getImageUrl(`images/educoder/pdfs.png`)} />
|
||||
<a className={"pdfdownloadfont4CACFF ml10"} href={getRandomcode(item.url)} download=""
|
||||
title="下载" mce_href="#">立即下载</a>
|
||||
</span>
|
||||
)
|
||||
})}</Col>
|
||||
</Row>
|
||||
|
||||
<Row className={"mt30"}>
|
||||
<Col>团队证书:
|
||||
{data&&data.team_certifications.length===0?<span className={"pdfpicture font-14"}>暂未生成</span>
|
||||
:data&&data.team_certifications.map((item,key)=>{
|
||||
return(
|
||||
<span className={"mr10"} key={key}>
|
||||
<img src={ getImageUrl(`images/educoder/pdfs.png`)} />
|
||||
<a className={"pdfdownloadfont4CACFF ml10"} href={getRandomcode(item.url)} download=""
|
||||
title="下载" mce_href="#">立即下载</a>
|
||||
</span>
|
||||
)
|
||||
})}
|
||||
</Col>
|
||||
</Row>
|
||||
<Divider />
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.pdfdownloadTable .ant-table-column-title{
|
||||
color:#000;
|
||||
}
|
||||
.pdfdownloadTable .ant-table-tbody > tr > td{
|
||||
color:#666666;
|
||||
border-bottom: 1px solid transparent;
|
||||
}
|
||||
.pdfdownloadTable .ant-table-thead > tr > th, .ant-table-tbody > tr > td{
|
||||
text-align: center;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
{teams&&teams.map((item,key)=>{
|
||||
return(
|
||||
<Row className={"mt30"} key={key}>
|
||||
<Col className={"pdfpicture mb20"}>{item.name}战队信息填报概况</Col>
|
||||
|
||||
<Table columns={columns} dataSource={item.team_members} className={"pdfdownloadTable"} pagination={false}/>
|
||||
</Row>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default CompetitionContentspdfdownload;
|
||||
@@ -0,0 +1,597 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Button, Layout, Input, Form} from 'antd';
|
||||
import axios from 'axios';
|
||||
import {setmiyah} from 'educoder';
|
||||
import mycompetotionchild from './mycompetotionchild.css';
|
||||
import {getHiddenName} from "../../../../user/account/AccountBasicEdit";
|
||||
import '../../../../courses/css/Courses.css'
|
||||
import RealNameCertificationModal from "../../../../user/modal/RealNameCertificationModal";
|
||||
import Phonenumberverifications from './Phonenumberverification';
|
||||
import Mailboxvalidations from './Mailboxvalidation'
|
||||
import Bankcardnumberverifications from './Bankcardnumberverification'
|
||||
export const identityMap = {"teacher": "教师", "student": "学生", "professional": "专业人士"}
|
||||
|
||||
class CompetitionContentspdfpeopledata extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
basicInfo: {},
|
||||
updating: '',
|
||||
secondsFlag: false,
|
||||
seconds: 60,
|
||||
phonebool: false,
|
||||
emailbool: false,
|
||||
formationdata: [],
|
||||
bank_account_editable: false,
|
||||
leader: false,
|
||||
bank_account: undefined,
|
||||
certification: 1,
|
||||
userdata:undefined
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.document.title = '竞赛';
|
||||
console.log("获取用户信息");
|
||||
console.log(this.props);
|
||||
|
||||
this.GetawardinformationAPI();
|
||||
let query=this.props.location&&this.props.location.search;
|
||||
const types = query.split('user_id=')
|
||||
let userid;
|
||||
if(types[1]===undefined){
|
||||
userid=this.props.user&&this.props.user.user_id;
|
||||
}else{
|
||||
userid=types[1];
|
||||
}
|
||||
this.getdata(userid);
|
||||
this.GetuseridApi(userid);
|
||||
|
||||
}
|
||||
|
||||
GetuseridApi=(id)=>{
|
||||
//个人信息API 获取个人信息
|
||||
let url = `/users/accounts/${id}.json`;
|
||||
axios.get(url).then((result) => {
|
||||
if (result.data) {
|
||||
console.log("GetuseridApi");
|
||||
console.log(result.data);
|
||||
this.setState({
|
||||
userdata:result.data
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
GetawardinformationAPI = () => {
|
||||
let url = `/competitions/${this.props.match.params.identifier}/prize.json`;
|
||||
let query=this.props.location&&this.props.location.search;
|
||||
const types = query.split('user_id=')
|
||||
let userid;
|
||||
if(types[1]===undefined){
|
||||
userid=this.props.user&&this.props.user.user_id;
|
||||
}else{
|
||||
userid=types[1];
|
||||
}
|
||||
axios.get(url,{params:{
|
||||
user_id:userid,
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result.data) {
|
||||
this.setState({
|
||||
formationdata: result.data.formationdata,
|
||||
bank_account_editable: result.data.bank_account_editable, //队长是否可以编辑
|
||||
leader: result.data.leader, //是否是队长
|
||||
bank_account: result.data.bank_account, //队长银行卡号信息
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
getdata = (id) => {
|
||||
this.setState({
|
||||
certification: 3
|
||||
})
|
||||
this.GetuseridApi(id);
|
||||
};
|
||||
// 绑定手机
|
||||
onPhoneSubmit = () => {
|
||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
let {id} =this.state.userdata;
|
||||
let reg = /^1\d{10}$/;
|
||||
if (reg.test(values.phone)) {
|
||||
let url = `/users/accounts/${id}/phone_bind.json`
|
||||
axios.post((url), {
|
||||
phone: values.phone,
|
||||
code: values.phoneValidateCode
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
this.props.showNotification("手机号码绑定成功!");
|
||||
this.setState({
|
||||
phonebool: false
|
||||
})
|
||||
this.getdata(this.state.userdata.id);
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
} else {
|
||||
this.props.showNotification("请输入有效的11位手机号码");
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// 绑定邮箱
|
||||
onEmailSubmit = () => {
|
||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
let {id} =this.state.userdata;
|
||||
let reg = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
|
||||
if (reg.test(values.email)) {
|
||||
let url = `/users/accounts/${id}/email_bind.json`
|
||||
axios.post((url), {
|
||||
email: values.email,
|
||||
code: values.emailValidateCode
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
this.props.showNotification("邮箱地址绑定成功!");
|
||||
this.setState({
|
||||
emailbool: false
|
||||
})
|
||||
this.getdata(this.state.userdata.id);
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
} else {
|
||||
this.props.showNotification("请输入正确的邮箱地址");
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
//取消编辑
|
||||
hideUpdating = (i) => {
|
||||
if (i === 1) {
|
||||
this.setState({
|
||||
phonebool: false
|
||||
})
|
||||
} else if (i === 2) {
|
||||
this.setState({
|
||||
emailbool: false
|
||||
})
|
||||
|
||||
} else if (i === 3) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
getCode = (index) => {
|
||||
let url = `/accounts/get_verification_code.json`
|
||||
let login = '';
|
||||
let values = this.props.form.getFieldsValue();
|
||||
if (index == 3) {
|
||||
//绑定手机号码
|
||||
login = values.phone;
|
||||
let reg = /^1\d{10}$/;
|
||||
if (reg.test(login) == false) {
|
||||
this.props.showNotification(`请先输入正确的手机号码`);
|
||||
return;
|
||||
}
|
||||
} else if (index == 4) {
|
||||
// 绑定邮箱
|
||||
login = values.email;
|
||||
let reg = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
|
||||
if (reg.test(login) == false) {
|
||||
this.props.showNotification(`请先输入正确的邮箱地址`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
let type = index;
|
||||
if (!login) {
|
||||
this.props.showNotification(`请先输入${index == 3 ? "手机号码" : "邮箱地址"}`);
|
||||
return;
|
||||
}
|
||||
let smscode=setmiyah(login)
|
||||
axios.get((url), {
|
||||
params: {
|
||||
login, type,smscode
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
// 倒计时
|
||||
this.setState({
|
||||
secondsFlag: true
|
||||
})
|
||||
this.remainTime();
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
// 获取验证码倒计时
|
||||
remainTime = () => {
|
||||
this.setState({
|
||||
seconds: 60
|
||||
})
|
||||
this.timer = setInterval(() => {
|
||||
let {seconds} = this.state;
|
||||
let s = parseInt(seconds) - 1;
|
||||
if (s > -1) {
|
||||
this.setState({
|
||||
seconds: s
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
secondsFlag: false
|
||||
})
|
||||
clearInterval(this.timer);
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
phonebools = () => {
|
||||
this.setState({
|
||||
phonebool: true
|
||||
})
|
||||
}
|
||||
|
||||
emailbools = () => {
|
||||
console.log("点击了邮箱");
|
||||
this.setState({
|
||||
emailbool: true
|
||||
})
|
||||
}
|
||||
|
||||
//立即认证
|
||||
checkBasicInfo = (index) => {
|
||||
if (this.state.userdata.base_info_completed == true) {
|
||||
this.showRealNameCertificationModal(index)
|
||||
} else {
|
||||
try {
|
||||
this.props.confirm({
|
||||
okText: `立即完善`,
|
||||
content: `请先完善基本信息`,
|
||||
onOk: () => {
|
||||
this.props.history.push('/account/profile/edit')
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
this.props.history.push(`/account/profile/edit`);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
showRealNameCertificationModal = (index) => {
|
||||
this.setState({
|
||||
certification: index,
|
||||
}, () => {
|
||||
if (index == 1) {
|
||||
this.realNameCertificationModal1.setVisible(true)
|
||||
} else if (index == 2) {
|
||||
this.realNameCertificationModal2.setVisible(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
//绑定银行确认
|
||||
yhBankstrue = () => {
|
||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
let url = `/competitions/${this.props.match.params.identifier}/prize_leader_account.json`;
|
||||
axios.patch(url, {
|
||||
user_id:this.state.userdata.id,
|
||||
bank: values.openingbank,
|
||||
second_bank: values.subbranchs,
|
||||
card_no: values.subbranch
|
||||
})
|
||||
.then((result) => {
|
||||
try {
|
||||
if (result.data.status == 0) {
|
||||
// console.log(JSON.stringify(result));
|
||||
this.props.showNotification(`提交成功`);
|
||||
this.getdata(this.state.userdata.id);
|
||||
this.GetawardinformationAPI();
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
//取消认证弹框
|
||||
onCancel = () => {
|
||||
this.getdata(this.state.userdata.id);
|
||||
|
||||
}
|
||||
|
||||
bindRef = ref => { this.child = ref }
|
||||
//撤销认证
|
||||
Cancellationofapplication = (index) => {
|
||||
let userid;
|
||||
let query=this.props.location&&this.props.location.search;
|
||||
const types = query.split('user_id=')
|
||||
if(types[1]===undefined){
|
||||
userid=this.props.user&&this.props.user.user_id;
|
||||
}else{
|
||||
userid=types[1];
|
||||
}
|
||||
let url = ""
|
||||
if (index === 1) {
|
||||
url = `/users/accounts/${userid}/authentication_apply.json`;
|
||||
} else if (index === 2) {
|
||||
url = `/users/accounts/${userid}/professional_auth_apply.json`;
|
||||
}
|
||||
axios.delete(url)
|
||||
.then((response) => {
|
||||
try {
|
||||
if (response.data.status == 0) {
|
||||
if (index === 1) {
|
||||
this.props.showNotification('撤销实名认证成功')
|
||||
} else if (index === 2) {
|
||||
this.props.showNotification('撤销职业认证成功')
|
||||
}
|
||||
try {
|
||||
this.getdata(this.state.userdata.id);
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const admins=this.props.user.admin;
|
||||
if(admins===undefined||admins===null) {
|
||||
admins === false;
|
||||
}
|
||||
const {updating, seconds, secondsFlag,userdata, basicInfo, phonebool, emailbool, certification, formationdata, bank_account_editable, leader, bank_account} = this.state
|
||||
return (
|
||||
<div className="flexdidirectionss mt17">
|
||||
{this.state.certification === 1 &&userdata?
|
||||
|
||||
<RealNameCertificationModal {...this.props} {...this.state} basicInfo={userdata}
|
||||
wrappedComponentRef={(form) => this.realNameCertificationModal1 = form}
|
||||
certification={certification}
|
||||
Getdata={(id) => this.getdata(id)}
|
||||
onCancel={() => this.onCancel()}
|
||||
></RealNameCertificationModal>
|
||||
|
||||
|
||||
: ""}
|
||||
|
||||
{this.state.certification === 2 &&userdata ?
|
||||
<RealNameCertificationModal {...this.props} {...this.state} basicInfo={userdata}
|
||||
wrappedComponentRef={(form) => this.realNameCertificationModal2 = form}
|
||||
certification={certification}
|
||||
Getdata={(id) => this.getdata(id)}
|
||||
onCancel={() => this.onCancel()}
|
||||
|
||||
></RealNameCertificationModal> : ""}
|
||||
<div className="flexdirections ">
|
||||
<p className="fontcolorsyslhei font-16 w98"><span className="fontcolorsysl font-16">*</span><span>实名信息</span>
|
||||
</p>
|
||||
{userdata && userdata.authentication == "uncertified" ?
|
||||
<p className="fontcolorsyslhui font-14 w200">通过实名认证后才能获得证书</p> : ""
|
||||
}
|
||||
{userdata && userdata.authentication == "uncertified" ?
|
||||
<p className="fontcolorsysllan font-14 ml3 mycompitcursor"
|
||||
onClick={() => this.checkBasicInfo(1)}>立即认证</p> : ""
|
||||
}
|
||||
|
||||
</div>
|
||||
<div className="flexdirections ml38 mt23">
|
||||
<p className="fontcolorsyslhui1">姓名:</p>
|
||||
<p className="fontcolorsyslhei flexdirections">{userdata && userdata.name}
|
||||
|
||||
{
|
||||
userdata && userdata.authentication == "uncertified" ? "" :
|
||||
userdata && userdata.authentication == "applying" ?
|
||||
<p className="flexdirections"><p className="iconfont icon-tishi colorgreenorg font-14 ml20"></p><p
|
||||
className="colorgreenorg font-14 ml6">待审核!</p><p
|
||||
className="fontcolorsysllan borcolors font-12 w64 mycompitcursor"
|
||||
onClick={() => this.Cancellationofapplication(1)}>撤销认证</p></p>
|
||||
:
|
||||
<p className="flexdirections">
|
||||
<p className="iconfont icon-wancheng colorgreenlight font-14 ml20"></p><p
|
||||
className="colorgreenlight font-14 ml6">已认证</p>
|
||||
</p>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flexdirections ml38 mt19">
|
||||
<p className="fontcolorsyslhui1">性别:</p>
|
||||
<p className="fontcolorsyslhei"> {userdata && userdata.gender == 0 ? "男" : "女"}</p>
|
||||
</div>
|
||||
|
||||
<div className="flexdirections mt36 ">
|
||||
<p className="fontcolorsyslhei font-16 w98"><span className="fontcolorsysl font-16">*</span><span>职业信息</span>
|
||||
</p>
|
||||
{
|
||||
userdata && userdata.professional_certification == "uncertified" ?
|
||||
<p className="fontcolorsyslhui font-14 w200">通过职业认证后才能获得证书</p>
|
||||
|
||||
: ""}
|
||||
{
|
||||
userdata && userdata.professional_certification == "uncertified" ?
|
||||
<p className="fontcolorsysllan font-14 ml3 mycompitcursor" onClick={() => this.checkBasicInfo(2)}>立即认证</p>
|
||||
|
||||
: ""}
|
||||
</div>
|
||||
|
||||
<div className="flexdirections ml38 mt23">
|
||||
<p className="fontcolorsyslhui1">职业:</p>
|
||||
<p
|
||||
className="fontcolorsyslhei flexdirections">{userdata && userdata.identity && identityMap[userdata.identity]}
|
||||
{
|
||||
userdata && userdata.professional_certification == "uncertified" ?
|
||||
"" :
|
||||
userdata && userdata.professional_certification == "applying" ?
|
||||
<p className="flexdirections">
|
||||
<p className="iconfont icon-tishi colorgreenorg font-14 ml20"></p><p
|
||||
className="colorgreenorg font-14 ml6">待审核!</p><p
|
||||
className="fontcolorsysllan borcolors font-12 w64 mycompitcursor ml6"
|
||||
onClick={() => this.Cancellationofapplication(2)}>撤销认证</p>
|
||||
</p>
|
||||
:
|
||||
<p className="flexdirections">
|
||||
<p className="iconfont icon-wancheng colorgreenlight font-14 ml20"></p><p
|
||||
className="colorgreenlight font-14 ml6">已认证</p>
|
||||
<p className="fontcolorsysllan borcolors font-12 w64 mycompitcursor ml6"
|
||||
onClick={() => this.checkBasicInfo(2)}>重新认证</p>
|
||||
|
||||
</p>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flexdirections ml38 mt19">
|
||||
<p
|
||||
className="fontcolorsyslhui1">{userdata && userdata.technical_title ? "职称:" : ""}{userdata && userdata.student_id ? "学号:" : ""}</p>
|
||||
<p className="fontcolorsyslhei">{userdata && (userdata.technical_title || userdata.student_id)}</p>
|
||||
</div>
|
||||
<div className="flexdirections ml38 mt19">
|
||||
<p className="fontcolorsyslhui1">学校:</p>
|
||||
<p className="fontcolorsyslhei">{userdata && userdata.school_name}</p>
|
||||
</div>
|
||||
<div className="flexdirections ml38 mt19">
|
||||
<p className="fontcolorsyslhui1">院系:</p>
|
||||
<p className="fontcolorsyslhei"> {userdata && userdata.department_name}</p>
|
||||
</div>
|
||||
<div className="flexdirections mt36 ">
|
||||
<p className="fontcolorsyslhei font-16 w98"><span className="fontcolorsysl font-16">*</span><span>联系方式</span>
|
||||
</p>
|
||||
</div>
|
||||
<div className="flexdirections ml38 mt23">
|
||||
<p className="fontcolorsyslhui1 w60 ">手机号:</p>
|
||||
{
|
||||
userdata && userdata.phone ?
|
||||
<p className="fontcolorsyslhei w200 ">{userdata && userdata.phone}</p>
|
||||
:
|
||||
<p className="fontcolorsysljin w200 ">未绑定</p>
|
||||
}
|
||||
<p className="fontcolorsysllan mycompitcursor"
|
||||
onClick={() => this.phonebools()}>{userdata && userdata.phone ? (phonebool === false ? "更换" : "") : (phonebool === false ? "立即绑定" : "")}</p>
|
||||
</div>
|
||||
{/*手机号绑定*/}
|
||||
{
|
||||
phonebool === true &&userdata ?
|
||||
<Phonenumberverifications {...this.props} {...this.state} basicInfo={userdata}
|
||||
hideUpdating={(i) => this.hideUpdating(i)}
|
||||
getdata={(id) => this.getdata(id)}></Phonenumberverifications>
|
||||
: ""
|
||||
}
|
||||
|
||||
|
||||
<div className="flexdirections ml38 mt19">
|
||||
<p className="fontcolorsyslhui1 w60">Email:</p>
|
||||
<p className="fontcolorsyslhei w200">{userdata && userdata.mail}</p>
|
||||
<p className="fontcolorsysllan mycompitcursor"
|
||||
onClick={() => this.emailbools()}>{userdata && userdata.mail ? (emailbool === false ? "更换" : "") : (emailbool === false ? "立即绑定" : "")}</p>
|
||||
</div>
|
||||
{
|
||||
emailbool === false ? "" :
|
||||
(
|
||||
userdata?
|
||||
<Mailboxvalidations {...this.props} {...this.state} basicInfo={userdata}
|
||||
hideUpdating={(i) => this.hideUpdating(i)}
|
||||
getdata={(id) => this.getdata(id)}></Mailboxvalidations>
|
||||
:""
|
||||
)
|
||||
}
|
||||
{
|
||||
leader === true ?
|
||||
<div>
|
||||
{
|
||||
bank_account_editable === true ?
|
||||
<Bankcardnumberverifications triggerRef={this.bindRef} {...this.props} {...this.state} basicInfo={userdata}
|
||||
hideUpdating={(i) => this.hideUpdating(i)}
|
||||
getdata={(id) => this.getdata(id)}
|
||||
GetawardinformationAPI={() => this.GetawardinformationAPI()}
|
||||
bank_account={this.state.bank_account}
|
||||
></Bankcardnumberverifications>
|
||||
:
|
||||
admins===true?
|
||||
<Bankcardnumberverifications triggerRef={this.bindRef} {...this.props} {...this.state} basicInfo={userdata}
|
||||
hideUpdating={(i) => this.hideUpdating(i)}
|
||||
getdata={(id) => this.getdata(id)}
|
||||
GetawardinformationAPI={() => this.GetawardinformationAPI()}
|
||||
bank_account={this.state.bank_account}
|
||||
></Bankcardnumberverifications>
|
||||
:
|
||||
<div>
|
||||
<div className="flexdirections mt36">
|
||||
<p className="fontcolorsyslhei font-16">签/领/开户行及银行卡号</p>
|
||||
<p className="fontcolorsyslhui font-14 ml11">为保障奖金的及时发放,请队长如实填写你名下的银行卡信息</p>
|
||||
</div>
|
||||
{
|
||||
bank_account && bank_account ?
|
||||
<div>
|
||||
<div className="flexdirections ml38 mt19">
|
||||
<p className="fontcolorsyslhui1 w56">开户行:</p>
|
||||
<p className="fontcolorsyslhei">{bank_account && bank_account.bank}</p>
|
||||
</div>
|
||||
<div className="flexdirections ml38 mt19">
|
||||
<p className="fontcolorsyslhui1 w56" style={{textAlign: "right"}}>支行:</p>
|
||||
<p className="fontcolorsyslhei">{bank_account && bank_account.second_bank}</p>
|
||||
</div>
|
||||
<div className="flexdirections ml38 mt19">
|
||||
<p className="fontcolorsyslhui1 w56" style={{textAlign: "right"}}>账号:</p>
|
||||
<p className="fontcolorsyslhei"> {bank_account && bank_account.card_no}</p>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
""
|
||||
}
|
||||
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
{
|
||||
admins===true?
|
||||
<Bankcardnumberverifications triggerRef={this.bindRef} {...this.props} {...this.state} basicInfo={userdata}
|
||||
hideUpdating={(i) => this.hideUpdating(i)}
|
||||
getdata={(id) => this.getdata(id)}
|
||||
GetawardinformationAPI={() => this.GetawardinformationAPI()}
|
||||
bank_account={this.state.bank_account}
|
||||
></Bankcardnumberverifications>
|
||||
:""
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default CompetitionContentspdfpeopledata;
|
||||
|
||||
@@ -0,0 +1,278 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Button, Layout, Input, Form} from 'antd';
|
||||
import axios from 'axios';
|
||||
import {setmiyah} from 'educoder';
|
||||
import mycompetotionchild from './mycompetotionchild.css';
|
||||
import {getHiddenName} from "../../../../user/account/AccountBasicEdit";
|
||||
import '../../../../courses/css/Courses.css'
|
||||
|
||||
export const identityMap = {"teacher": "教师", "student": "学生", "professional": "专业人士"}
|
||||
|
||||
class Mailboxvalidation extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
basicInfo: {},
|
||||
updating: '',
|
||||
secondsFlag: false,
|
||||
seconds: 60,
|
||||
phonebool: false,
|
||||
emailbool: false,
|
||||
formationdata: [],
|
||||
bank_account_editable: false,
|
||||
leader: false,
|
||||
bank_account: undefined,
|
||||
certification: 1
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.document.title = '竞赛';
|
||||
// console.log("3获取用户信息");
|
||||
// console.log(this.props);
|
||||
}
|
||||
|
||||
|
||||
// 绑定邮箱
|
||||
onEmailSubmit = () => {
|
||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
let {id} = this.props.userdata;
|
||||
let reg = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
|
||||
if (reg.test(values.email)) {
|
||||
let url = `/users/accounts/${id}/email_bind.json`
|
||||
axios.post((url), {
|
||||
email: values.email,
|
||||
code: values.emailValidateCode
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
this.props.showNotification("邮箱地址绑定成功!");
|
||||
this.hideUpdating(2);
|
||||
this.props.getdata(id);
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
} else {
|
||||
this.props.showNotification("请输入正确的邮箱地址");
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
//取消编辑
|
||||
hideUpdating = (i) => {
|
||||
if (i === 1) {
|
||||
this.props.hideUpdating(1);
|
||||
} else if (i === 2) {
|
||||
this.props.hideUpdating(2);
|
||||
|
||||
|
||||
} else if (i === 3) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
getCode = (index) => {
|
||||
let url = `/accounts/get_verification_code.json`
|
||||
let login = '';
|
||||
let values = this.props.form.getFieldsValue();
|
||||
|
||||
if (index == 3) {
|
||||
//绑定手机号码
|
||||
login = values.phone;
|
||||
let reg = /^1\d{10}$/;
|
||||
if (reg.test(login) == false) {
|
||||
this.props.showNotification(`请先输入正确的手机号码`);
|
||||
return;
|
||||
}
|
||||
} else if (index == 4) {
|
||||
// 绑定邮箱
|
||||
login = values.email;
|
||||
let reg = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
|
||||
if (reg.test(login) == false) {
|
||||
this.props.showNotification(`请先输入正确的邮箱地址`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
let type = index;
|
||||
if (!login) {
|
||||
this.props.showNotification(`请先输入${index == 3 ? "手机号码" : "邮箱地址"}`);
|
||||
return;
|
||||
}
|
||||
let smscode=setmiyah(login)
|
||||
axios.get((url), {
|
||||
params: {
|
||||
login, type,smscode
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
// 倒计时
|
||||
if(result.data.status===1){
|
||||
this.props.showNotification("验证码已发送,请注意查收");
|
||||
}else if(result.data.status===-2){
|
||||
this.props.showNotification(result.data.message);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
secondsFlag: true
|
||||
})
|
||||
this.remainTime();
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
// 获取验证码倒计时
|
||||
remainTime = () => {
|
||||
this.setState({
|
||||
seconds: 60
|
||||
})
|
||||
this.timer = setInterval(() => {
|
||||
let {seconds} = this.state;
|
||||
let s = parseInt(seconds) - 1;
|
||||
if (s > -1) {
|
||||
this.setState({
|
||||
seconds: s
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
secondsFlag: false
|
||||
})
|
||||
clearInterval(this.timer);
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
phonebools = () => {
|
||||
this.setState({
|
||||
phonebool: true
|
||||
})
|
||||
}
|
||||
|
||||
emailbools = () => {
|
||||
console.log("点击了邮箱");
|
||||
this.setState({
|
||||
emailbool: true
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const {getFieldDecorator} = this.props.form;
|
||||
const {updating, seconds, secondsFlag, basicInfo, phonebool, emailbool, certification, formationdata, bank_account_editable, leader, bank_account} = this.state
|
||||
console.log(emailbool);
|
||||
return (
|
||||
<div>
|
||||
<style>{`
|
||||
|
||||
.flexRow {
|
||||
padding: 20px 0;
|
||||
}
|
||||
.flexRow .name {
|
||||
margin-left: 12px;
|
||||
color: #666666;
|
||||
|
||||
text-align: center;
|
||||
flex: 0 0 100px;
|
||||
}
|
||||
.flexRow .description {
|
||||
margin-left: 10px;
|
||||
flex: 1;
|
||||
color: #CDCDCD;
|
||||
}
|
||||
.description span {
|
||||
margin-right: 20px;
|
||||
color: #05101A;
|
||||
}
|
||||
.flexRow .status {
|
||||
width: 100px;
|
||||
color: #28AC7F;
|
||||
text-align: right;
|
||||
}
|
||||
.flexTable .flexTable {
|
||||
border-bottom: 1px solid #EBEBEB;
|
||||
}
|
||||
|
||||
.settingForm label{
|
||||
color: #666666;
|
||||
font-size: 14px !important ;
|
||||
}
|
||||
.settingForm input {
|
||||
width: 340px;
|
||||
height: 40px;
|
||||
}
|
||||
.settingForm input.validateInput {
|
||||
width: 220px;
|
||||
}
|
||||
.settingForm .formItemInline button {
|
||||
width: 110px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.settingForm .ant-form-item-label {
|
||||
text-align: left;
|
||||
width: 84px;
|
||||
}
|
||||
|
||||
|
||||
.formItemInline .ant-form-explain{
|
||||
position:absolute;
|
||||
bottom:-22px;
|
||||
left:0px;
|
||||
width:100%;
|
||||
}
|
||||
`}</style>
|
||||
<div className="settingForm ml38">
|
||||
<React.Fragment>
|
||||
<Form>
|
||||
<Form.Item
|
||||
label="邮箱地址"
|
||||
className="formItemInline hideRequireTag mb20 mt20"
|
||||
>
|
||||
{getFieldDecorator('email', {
|
||||
rules: [{
|
||||
// initialValue: this.state.cityDefaultValue,
|
||||
required: true,
|
||||
message: basicInfo && basicInfo.mail ? '请输入要更换的新邮箱地址' : '请输入邮箱地址',
|
||||
}],
|
||||
})(
|
||||
<Input placeholder={`${basicInfo && basicInfo.mail ? '请输入要更换的新邮箱地址' : '请输入邮箱地址'}`}></Input>
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="邮箱验证码"
|
||||
className="mb20 formItemInline hideRequireTag"
|
||||
>
|
||||
{getFieldDecorator('emailValidateCode', {
|
||||
rules: [{
|
||||
// initialValue: this.state.cityDefaultValue,
|
||||
required: true,
|
||||
message: '请输入邮箱收到的验证码',
|
||||
}],
|
||||
})(
|
||||
<Input placeholder="请输入邮箱收到的验证码" className="validateInput"></Input>
|
||||
)}
|
||||
<Button type="primary" disabled={secondsFlag} onClick={() => this.getCode(4)}>
|
||||
{!secondsFlag ? "获取验证码" : `重新发送${seconds}s`}</Button>
|
||||
</Form.Item>
|
||||
|
||||
<div className="mb20" style={{marginLeft: '204px'}}>
|
||||
<Button type="primary" onClick={() => this.onEmailSubmit()}>确定</Button>
|
||||
<Button type="primary grayBtn" style={{marginLeft: '20px'}}
|
||||
onClick={() => this.hideUpdating(2)}>取消</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</React.Fragment>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const Mailboxvalidations = Form.create({name: 'Mailboxvalidation'})(Mailboxvalidation);
|
||||
|
||||
export default Mailboxvalidations;
|
||||
|
||||
@@ -0,0 +1,269 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Button, Layout, Input, Form} from 'antd';
|
||||
import axios from 'axios';
|
||||
import {setmiyah} from 'educoder';
|
||||
import mycompetotionchild from './mycompetotionchild.css';
|
||||
import {getHiddenName} from "../../../../user/account/AccountBasicEdit";
|
||||
import '../../../../courses/css/Courses.css'
|
||||
import RealNameCertificationModal from "../../../../user/modal/RealNameCertificationModal";
|
||||
|
||||
export const identityMap = {"teacher": "教师", "student": "学生", "professional": "专业人士"}
|
||||
|
||||
class Phonenumberverification extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
updating: '',
|
||||
secondsFlag: false,
|
||||
seconds: 60,
|
||||
phonebool: false,
|
||||
emailbool: false,
|
||||
formationdata: [],
|
||||
bank_account_editable: false,
|
||||
leader: false,
|
||||
bank_account: undefined,
|
||||
certification: 1
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.document.title = '竞赛';
|
||||
// console.log("获取用户信息");
|
||||
// console.log(this.props);
|
||||
}
|
||||
|
||||
|
||||
// 绑定手机
|
||||
onPhoneSubmit = () => {
|
||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
let {id} = this.props.userdata;
|
||||
let reg = /^1\d{10}$/;
|
||||
if (reg.test(values.phone)) {
|
||||
let url = `/users/accounts/${id}/phone_bind.json`
|
||||
axios.post((url), {
|
||||
phone: values.phone,
|
||||
code: values.phoneValidateCode
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
this.props.showNotification("手机号码绑定成功!");
|
||||
this.props.hideUpdating(1)
|
||||
this.props.getdata(id);
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
} else {
|
||||
this.props.showNotification("请输入有效的11位手机号码");
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
//取消编辑
|
||||
hideUpdating = (i) => {
|
||||
if (i === 1) {
|
||||
this.props.hideUpdating(1);
|
||||
} else if (i === 2) {
|
||||
this.props.hideUpdating(2);
|
||||
|
||||
} else if (i === 3) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
getCode = (index) => {
|
||||
let url = `/accounts/get_verification_code.json`
|
||||
let login = '';
|
||||
let values = this.props.form.getFieldsValue();
|
||||
|
||||
if (index == 3) {
|
||||
//绑定手机号码
|
||||
login = values.phone;
|
||||
let reg = /^1\d{10}$/;
|
||||
if (reg.test(login) == false) {
|
||||
this.props.showNotification(`请先输入正确的手机号码`);
|
||||
return;
|
||||
}
|
||||
} else if (index == 4) {
|
||||
// 绑定邮箱
|
||||
login = values.email;
|
||||
let reg = /^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
|
||||
if (reg.test(login) == false) {
|
||||
this.props.showNotification(`请先输入正确的邮箱地址`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
let type = index;
|
||||
if (!login) {
|
||||
this.props.showNotification(`请先输入${index == 3 ? "手机号码" : "邮箱地址"}`);
|
||||
return;
|
||||
}
|
||||
let smscode=setmiyah(login)
|
||||
axios.get((url), {
|
||||
params: {
|
||||
login, type,smscode
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
// 倒计时
|
||||
if(result.data.status===1){
|
||||
this.props.showNotification("验证码已发送,请注意查收");
|
||||
}else if(result.data.status===-2){
|
||||
this.props.showNotification(result.data.message);
|
||||
}
|
||||
this.setState({
|
||||
secondsFlag: true
|
||||
})
|
||||
this.remainTime();
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
// 获取验证码倒计时
|
||||
remainTime = () => {
|
||||
this.setState({
|
||||
seconds: 60
|
||||
})
|
||||
this.timer = setInterval(() => {
|
||||
let {seconds} = this.state;
|
||||
let s = parseInt(seconds) - 1;
|
||||
if (s > -1) {
|
||||
this.setState({
|
||||
seconds: s
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
secondsFlag: false
|
||||
})
|
||||
clearInterval(this.timer);
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
phonebools = () => {
|
||||
this.setState({
|
||||
phonebool: true
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const {getFieldDecorator} = this.props.form;
|
||||
const {updating, seconds, secondsFlag, phonebool, emailbool, certification, formationdata, bank_account_editable, leader, bank_account} = this.state
|
||||
const {basicInfo} = this.props
|
||||
console.log(emailbool);
|
||||
return (
|
||||
<div>
|
||||
<style>{`
|
||||
|
||||
.flexRow {
|
||||
padding: 20px 0;
|
||||
}
|
||||
.flexRow .name {
|
||||
margin-left: 12px;
|
||||
color: #666666;
|
||||
|
||||
text-align: center;
|
||||
flex: 0 0 100px;
|
||||
}
|
||||
.flexRow .description {
|
||||
margin-left: 10px;
|
||||
flex: 1;
|
||||
color: #CDCDCD;
|
||||
}
|
||||
.description span {
|
||||
margin-right: 20px;
|
||||
color: #05101A;
|
||||
}
|
||||
.flexRow .status {
|
||||
width: 100px;
|
||||
color: #28AC7F;
|
||||
text-align: right;
|
||||
}
|
||||
.flexTable .flexTable {
|
||||
border-bottom: 1px solid #EBEBEB;
|
||||
}
|
||||
|
||||
.settingForm label{
|
||||
color: #666666;
|
||||
font-size: 14px !important ;
|
||||
}
|
||||
.settingForm input {
|
||||
width: 340px;
|
||||
height: 40px;
|
||||
}
|
||||
.settingForm input.validateInput {
|
||||
width: 220px;
|
||||
}
|
||||
.settingForm .formItemInline button {
|
||||
width: 110px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.settingForm .ant-form-item-label {
|
||||
text-align: left;
|
||||
width: 84px;
|
||||
}
|
||||
.formItemInline .ant-form-explain{
|
||||
position:absolute;
|
||||
bottom:-22px;
|
||||
left:0px;
|
||||
width:100%;
|
||||
}
|
||||
`}</style>
|
||||
<div className="settingForm ml38">
|
||||
<React.Fragment>
|
||||
<Form>
|
||||
<Form.Item
|
||||
label="你的手机号"
|
||||
className="formItemInline hideRequireTag mb20 mt20"
|
||||
>
|
||||
{getFieldDecorator('phone', {
|
||||
rules: [{
|
||||
// initialValue: this.state.cityDefaultValue,
|
||||
required: true,
|
||||
message: `请输入要${basicInfo.phone ? '更换' : '绑定'}的手机号码`,
|
||||
}],
|
||||
})(
|
||||
<Input placeholder={`请输入要${basicInfo.phone ? '更换' : '绑定'}的手机号码`}></Input>
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="手机验证码"
|
||||
className="mb20 formItemInline hideRequireTag"
|
||||
>
|
||||
{getFieldDecorator('phoneValidateCode', {
|
||||
rules: [{
|
||||
// initialValue: this.state.cityDefaultValue,
|
||||
required: true,
|
||||
message: '请输入手机获取的验证码',
|
||||
}],
|
||||
})(
|
||||
<Input placeholder="请输入手机获取的验证码" className="validateInput"></Input>
|
||||
)}
|
||||
<Button type="primary" disabled={secondsFlag} onClick={() => this.getCode(3)}>
|
||||
{!secondsFlag ? "获取验证码" : `重新发送${seconds}s`}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
|
||||
<div className="mb20" style={{marginLeft: '204px'}}>
|
||||
<Button type="primary" onClick={() => this.onPhoneSubmit()}>确定</Button>
|
||||
<Button type="primary grayBtn" style={{marginLeft: '20px'}}
|
||||
onClick={() => this.hideUpdating(1)}>取消</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</React.Fragment>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const Phonenumberverifications = Form.create({name: 'Phonenumberverification'})(Phonenumberverification);
|
||||
|
||||
export default Phonenumberverifications;
|
||||
|
||||
@@ -0,0 +1,314 @@
|
||||
/*垂直布局
|
||||
|
||||
一
|
||||
二
|
||||
三
|
||||
*/
|
||||
.flexdirectionjust {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
|
||||
.directstwebkitflex {
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.diredisplayitflex {
|
||||
display: flex;
|
||||
display: -webkit-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/*垂直布局*/
|
||||
/*靠左侧
|
||||
一 二 三 四 五 六 七 八
|
||||
*/
|
||||
.flexdirection {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.flexdirections {
|
||||
display: flex;
|
||||
flex-direction: initial;
|
||||
}
|
||||
|
||||
/*靠左侧
|
||||
*/
|
||||
|
||||
|
||||
/*靠右侧八 七 六 五 四 三 二 一*/
|
||||
.flexdirectionss {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
|
||||
/*垂直布局
|
||||
一
|
||||
二
|
||||
三
|
||||
四
|
||||
*/
|
||||
.flexdidirectionss {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/*垂直布局
|
||||
四
|
||||
三
|
||||
二
|
||||
一
|
||||
*/
|
||||
.flexdidireverses {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
.fontcolorsysl {
|
||||
color: #FF0000
|
||||
}
|
||||
|
||||
.fontcolorsyslhei {
|
||||
color: #000000
|
||||
}
|
||||
|
||||
.fontcolorsyslhui {
|
||||
color: #888888
|
||||
}
|
||||
|
||||
.fontcolorsyslhui1 {
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.fontcolorsysllan {
|
||||
color: #4CACFF
|
||||
}
|
||||
|
||||
.fontcolorsysljin {
|
||||
color: #DD7600
|
||||
}
|
||||
|
||||
.w200 {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.w64 {
|
||||
width: 64px;
|
||||
}
|
||||
|
||||
.w60 {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.w98 {
|
||||
width: 98px;
|
||||
}
|
||||
|
||||
.myysllineheight {
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.myyslminwidth {
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.myyslminwidth276 {
|
||||
width: 276px;
|
||||
}
|
||||
|
||||
.buttongo {
|
||||
background: #E7E7E7;
|
||||
border: 1px solid #E7E7E7;
|
||||
width: 60px;
|
||||
height: 30px;
|
||||
border-radius: 4px;
|
||||
color: #999999;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.buttongo2 {
|
||||
background: #4CACFF;
|
||||
border: 1px solid #4CACFF;
|
||||
width: 64px;
|
||||
height: 32px;
|
||||
border-radius: 4px;
|
||||
color: #FFFFFF;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.fontwenzi {
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.mt17 {
|
||||
margin-top: 17px;
|
||||
}
|
||||
|
||||
.mt36 {
|
||||
margin-top: 36px;
|
||||
}
|
||||
|
||||
.mt23 {
|
||||
margin-top: 23px;
|
||||
}
|
||||
|
||||
.mt19 {
|
||||
margin-top: 19px;
|
||||
}
|
||||
|
||||
.mt23 {
|
||||
margin-top: 23px;
|
||||
}
|
||||
|
||||
.mt34 {
|
||||
margin-top: 34px;
|
||||
}
|
||||
|
||||
.ml11 {
|
||||
margin-left: 11px;
|
||||
}
|
||||
|
||||
.ml38 {
|
||||
margin-left: 38px;
|
||||
}
|
||||
|
||||
.ml7 {
|
||||
margin-left: 7px;
|
||||
}
|
||||
|
||||
.colorgreenlight {
|
||||
color: #6EC76E
|
||||
}
|
||||
|
||||
.colorgreenorg {
|
||||
color: #FF7300;
|
||||
}
|
||||
|
||||
.borcolors {
|
||||
border: 1px solid #4CACFF;
|
||||
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mycompitcursor {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.basicForm {
|
||||
background: #fff;
|
||||
padding: 30px;
|
||||
margin-bottom: 10px;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
min-height: 390px;
|
||||
}
|
||||
|
||||
.basicForm .title {
|
||||
font-size: 16px;
|
||||
padding-left: 30px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.flexTable {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.flexRow {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.mb15 {
|
||||
margin-bottom: 15px !important;
|
||||
}
|
||||
|
||||
/* BUTTOn */
|
||||
.ant-btn {
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
button.ant-btn.ant-btn-primary.grayBtn {
|
||||
background: #CBCBCB;
|
||||
border-color: #CBCBCB;
|
||||
}
|
||||
|
||||
.borderBottom {
|
||||
border-bottom: 1px solid #4CACFF;
|
||||
}
|
||||
|
||||
/* form ---------------- START */
|
||||
.formItemInline {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.formItemInline .ant-form-item-control-wrapper {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.hideRequireTag .ant-form-item-required:before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/* .basicForm .ant-form-item-label {
|
||||
width: 100px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.basicForm .ant-form-item-label label {
|
||||
color: #979797
|
||||
} */
|
||||
|
||||
|
||||
.courseNormalForm .ant-select-show-search {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.courseNormalForm .ant-select-auto-complete.ant-select .ant-input {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.courseNormalForm .ant-select-search__field__mirror {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.courseNormalForm .ant-input-lg {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.courseNormalForm .ant-select-selection--single {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.courseNormalForm .ant-select-auto-complete.ant-select .ant-select-selection--single {
|
||||
height: 40px
|
||||
}
|
||||
|
||||
.courseNormalForm .ant-input-affix-wrapper {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
/* 职业 */
|
||||
.courseNormalForm .ant-select-selection-selected-value {
|
||||
line-height: 38px
|
||||
}
|
||||
|
||||
.courseNormalForm input {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.w300 {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.w56 {
|
||||
width: 56px;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import { Redirect } from 'react-router';
|
||||
|
||||
import { Route, Link, Switch } from "react-router-dom";
|
||||
|
||||
import Loading from '../../Loading';
|
||||
|
||||
import Loadable from 'react-loadable';
|
||||
import { TPMIndexHOC } from '../tpm/TPMIndexHOC';
|
||||
import { CNotificationHOC } from '../courses/common/CNotificationHOC';
|
||||
|
||||
//新版竞赛首页
|
||||
const CompetitionsIndex = Loadable({
|
||||
loader: () => import('./Competitimain/CompetitionsIndex'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//竞赛详情页
|
||||
const CompetitionCommon=Loadable({
|
||||
loader: () => import('./Competitioncommon/CompetitionCommon'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
|
||||
//战队详情
|
||||
const CompetitionTeams = Loadable({
|
||||
loader: () => import('./Competition_teams/Competitionteams'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//团队竞赛报名
|
||||
const Registration = Loadable({
|
||||
loader: () => import('../competition/Registration'),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
class Competitions extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
|
||||
window.document.title = '竞赛';
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div className="newMain clearfix">
|
||||
|
||||
<Switch>
|
||||
|
||||
{/*新版竞赛战队详情*/}
|
||||
<Route path="/competitions/:identifier/competition_teams/:competition_team_id"
|
||||
render={
|
||||
(props) => (<CompetitionTeams {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
{/*新版竞赛报名*/}
|
||||
<Route
|
||||
path="/competitions/:identifier/enroll"
|
||||
render={
|
||||
(props) => (<Registration {...this.props} {...props} {...this.state}/>)
|
||||
}
|
||||
/>
|
||||
|
||||
{/*新版竞赛详情页面*/}
|
||||
<Route path="/competitions/:identifier"
|
||||
render={
|
||||
(props) => (<CompetitionCommon {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/*新版竞赛首页*/}
|
||||
<Route path="/competitions"
|
||||
render={
|
||||
(props) => (<CompetitionsIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
</Switch>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default CNotificationHOC() (TPMIndexHOC (Competitions)) ;
|
||||
@@ -0,0 +1,100 @@
|
||||
import React, { Component } from 'react';
|
||||
import { SnackbarHOC } from 'educoder';
|
||||
import {BrowserRouter as Router,Route,Switch} from 'react-router-dom';
|
||||
import Loadable from 'react-loadable';
|
||||
import Loading from '../../Loading';
|
||||
import axios from 'axios';
|
||||
// import { TPMIndexHOC } from '../tpm/TPMIndexHOC';
|
||||
import { CNotificationHOC } from './common/CNotificationHOC'
|
||||
import "./css/Courses.css"
|
||||
//引入对应跳转的组件
|
||||
const ListPageIndex = Loadable({
|
||||
loader: () => import('./ListPageIndex'),
|
||||
loading:Loading,
|
||||
})
|
||||
// 讨论
|
||||
const BoardsNew= Loadable({
|
||||
loader: () => import('./boards/BoardsNew'),
|
||||
loading: Loading,
|
||||
})
|
||||
const TopicDetail= Loadable({
|
||||
loader: () => import('./boards/TopicDetail'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
// 讨论
|
||||
const Boards= Loadable({
|
||||
loader: () => import('./boards'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
|
||||
class CoursesIndex extends Component{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state={
|
||||
// coursedata:undefined
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
|
||||
}
|
||||
render() {
|
||||
const common = {
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
<Switch {...this.props}>
|
||||
|
||||
{/*课堂讨论*/}
|
||||
{/* /board/5464/messages/new */}
|
||||
{/* <Route exact path="/courses/:coursesId/board/:boardId/messages/:topicId/edit"
|
||||
render={
|
||||
(props) => (<BoardsNew {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route exact path="/courses/:coursesId/board/:boardId/messages/new" component={BoardsNew}
|
||||
render={
|
||||
(props) => (<BoardsNew {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route> */}
|
||||
|
||||
|
||||
|
||||
|
||||
{/*课堂讨论*/}
|
||||
<Route exact path="/courses/:coursesId/boards/:boardId/messages/:topicId/edit"
|
||||
render={
|
||||
(props) => (<BoardsNew {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
<Route exact path="/courses/:coursesId/boards/:boardId/messages/new"
|
||||
render={
|
||||
(props) => (<BoardsNew {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
<Route exact path="/courses/:coursesId/boards/:boardId/messages/:topicId"
|
||||
render={
|
||||
(props) => (<TopicDetail {...this.props} {...this.state} {...props} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
<Route exact path="/courses/:coursesId/boards/:boardId/messages/:topicId"
|
||||
render={
|
||||
(props) => (<TopicDetail {...this.props} {...this.state} {...props} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
<Route exact path="/courses/:coursesId/boards/:boardId"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
</Switch>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default CNotificationHOC() ( SnackbarHOC() ( (CoursesIndex) ));
|
||||
@@ -0,0 +1,963 @@
|
||||
import React, { Component } from 'react';
|
||||
import { SnackbarHOC } from 'educoder';
|
||||
import {BrowserRouter as Router,Route,Switch} from 'react-router-dom';
|
||||
import { withRouter } from 'react-router'
|
||||
import Loadable from 'react-loadable';
|
||||
import Loading from '../../Loading';
|
||||
import axios from 'axios';
|
||||
import { TPMIndexHOC } from '../tpm/TPMIndexHOC';
|
||||
import { CNotificationHOC } from './common/CNotificationHOC'
|
||||
import {ImageLayerOfCommentHOC} from '../page/layers/ImageLayerOfCommentHOC'
|
||||
import "./css/Courses.css"
|
||||
//引入对应跳转的组件
|
||||
|
||||
const ListPageIndex = Loadable({
|
||||
loader: () => import('./ListPageIndex'),
|
||||
loading:Loading,
|
||||
})
|
||||
|
||||
//课堂首页
|
||||
const CoursesHome = Loadable({
|
||||
loader: () => import('./coursesHome/CoursesHome'),
|
||||
loading:Loading,
|
||||
})
|
||||
|
||||
//课堂详情页
|
||||
const CoursesDetail= Loadable({
|
||||
loader: () => import('./coursesDetail/CoursesDetail'),
|
||||
loading:Loading,
|
||||
})
|
||||
|
||||
|
||||
|
||||
// 课堂讨论
|
||||
const BoardIndex = Loadable({
|
||||
loader: () => import('./BoardIndex'),
|
||||
loading:Loading,
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
const GraduationTopics= Loadable({
|
||||
loader: () => import('./graduation/topics'),
|
||||
loading: Loading,
|
||||
})
|
||||
const GraduationTopicsDetail= Loadable({
|
||||
loader: () => import('./graduation/topics/GraduateTopicDetail'),
|
||||
loading: Loading,
|
||||
})
|
||||
const GraduateTopicPostWorksNew= Loadable({
|
||||
loader: () => import('./graduation/topics/GraduateTopicPostWorksNew'),
|
||||
loading: Loading,
|
||||
})
|
||||
const GraduateTopicNew= Loadable({
|
||||
loader: () => import('./graduation/topics/GraduateTopicNew'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
const GraduationTasks= Loadable({
|
||||
loader: () => import('./graduation/tasks'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
// 资源
|
||||
const Resourcelist= Loadable({
|
||||
loader: () => import('./Resource/index'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//新建实训
|
||||
const WrappedCoursesNewApp= Loadable({
|
||||
loader: () => import('./new/CoursesNew'),
|
||||
loading: Loading,
|
||||
})
|
||||
//新建精品课堂
|
||||
const WrappedCoursesNewAppGoldclass= Loadable({
|
||||
loader: () => import('./new/Goldsubject'),
|
||||
loading: Loading,
|
||||
})
|
||||
const ShixunHomeworkPage =Loadable({
|
||||
loader: () => import('./shixunHomework/ShixunHomeworkPage'),
|
||||
loading: Loading,
|
||||
})
|
||||
//实训作业
|
||||
const ShixunHomework= Loadable({
|
||||
loader: () => import('./shixunHomework/shixunHomework'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//实训作业设置
|
||||
const Trainingjobsetting= Loadable({
|
||||
loader: () => import('./shixunHomework/Trainingjobsetting'),
|
||||
loading: Loading,
|
||||
})
|
||||
//实训作业列表教师
|
||||
|
||||
// //实训作业列表学生未完成的
|
||||
// const Studentnotcompleted= Loadable({
|
||||
// loader: () => import('./shixunHomework/Listofworksstudentone'),
|
||||
// loading: Loading,
|
||||
// })
|
||||
//实训作业列表完成的
|
||||
const Studenthascompleted= Loadable({
|
||||
loader: () => import('./shixunHomework/Listofworksstudentone'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
|
||||
//实训作业提交总结
|
||||
const CommitSummary = Loadable({
|
||||
loader: () => import('./shixunHomework/CommitSummary'),
|
||||
loading: Loading,
|
||||
})
|
||||
//实训作业设置
|
||||
const Workquestionandanswer= Loadable({
|
||||
loader: () => import('./shixunHomework/Workquestionandanswer'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
|
||||
//实训报告
|
||||
const ShixunWorkReport= Loadable({
|
||||
loader: () => import('./shixunHomework/ShixunWorkReport'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//实训查重
|
||||
const ShixunStudentWork= Loadable({
|
||||
loader: () => import('./shixunHomework/ShixunStudentWork'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//实训查重详情
|
||||
const ShixunWorkDetails= Loadable({
|
||||
loader: () => import('./shixunHomework/ShixunWorkDetails'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//问卷
|
||||
const Poll= Loadable({
|
||||
loader: () => import('./poll/Poll'),
|
||||
loading: Loading,
|
||||
})
|
||||
//问卷新建
|
||||
const PollNew= Loadable({
|
||||
loader: () => import('./poll/PollNew'),
|
||||
loading: Loading,
|
||||
})
|
||||
//问卷答题
|
||||
const PollInfo= Loadable({
|
||||
loader: () => import('./poll/PollInfo'),
|
||||
loading: Loading,
|
||||
})
|
||||
//问卷详情
|
||||
const PollDetail= Loadable({
|
||||
loader: () => import('./poll/PollDetailIndex'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
|
||||
//试卷
|
||||
const Exercise= Loadable({
|
||||
loader: () => import('./exercise/Exercise'),
|
||||
loading: Loading,
|
||||
})
|
||||
const Testpapersettinghomepage =Loadable({
|
||||
loader: () => import('./exercise/Testpapersettinghomepage'),
|
||||
loading: Loading,
|
||||
})
|
||||
const ExerciseNew =Loadable({
|
||||
loader: () => import('./exercise/ExerciseNew'),
|
||||
loading: Loading,
|
||||
})
|
||||
const ExerciseReviewAndAnswer=Loadable({
|
||||
loader:() => import('./exercise/ExerciseReviewAndAnswer'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//学生列表
|
||||
const Studentshavecompletedthelist = Loadable({
|
||||
loader: () => import('./exercise/Studentshavecompletedthelist'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//教师列表
|
||||
const TeacherList= Loadable({
|
||||
loader: () => import('./members/teacherList'),
|
||||
loading: Loading,
|
||||
})
|
||||
//学生列表
|
||||
const StudentsList= Loadable({
|
||||
loader: () => import('./members/studentsList'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
|
||||
//普通作业
|
||||
const CommonWork= Loadable({
|
||||
loader: () => import('./busyWork/Index'),
|
||||
loading: Loading,
|
||||
})
|
||||
const GroupWork= Loadable({
|
||||
loader: () => import('./busyWork/IndexGroup'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//
|
||||
// //分组作业
|
||||
// const GroupWork= Loadable({
|
||||
// loader: () => import('./busyWork/GroupWork'),
|
||||
// loading: Loading,
|
||||
// })
|
||||
|
||||
//毕设任务列表新建
|
||||
const GraduationTaskseditApp= Loadable({
|
||||
loader: () => import('./graduation/tasks/GraduationTasksedit'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//毕设任务列表编辑
|
||||
const GraduationTasksnewApp= Loadable({
|
||||
loader: () => import('./graduation/tasks/GraduationTasksnew'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//毕设任务列表设置
|
||||
const GraduationTasksquestions= Loadable({
|
||||
loader: () => import('./graduation/tasks/GraduationTaskssettingquestions'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//毕设任务列表
|
||||
|
||||
const GraduationTaskssettinglist= Loadable({
|
||||
loader: () => import('./graduation/tasks/GraduationTaskDetail'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//毕业任务设置
|
||||
|
||||
const GraduationTaskssetting=Loadable({
|
||||
loader: () => import('./graduation/tasks/GraduationTaskssetting'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
// 评阅列表
|
||||
|
||||
const GraduationTasksappraise=Loadable({
|
||||
loader: () => import('./graduation/tasks/GraduationTasksappraise'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
|
||||
//创建作品
|
||||
|
||||
const GraduationTasksSubmitnewApp=Loadable({
|
||||
loader: () => import('./graduation/tasks/GraduationTasksSubmitnew'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//修改作品
|
||||
|
||||
const GraduationTasksSubmiteditApp=Loadable({
|
||||
loader: () => import('./graduation/tasks/GraduationTasksSubmitedit'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//排序
|
||||
const Ordering=Loadable({
|
||||
loader: () => import('../../modules/courses/ordering/Ordering'),
|
||||
loading: Loading,
|
||||
});
|
||||
class CoursesIndex extends Component{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state={
|
||||
coursesids: undefined,
|
||||
coursesidsfun:this.coursesidsfun,
|
||||
updataleftNavfun:this.updataleftNav,
|
||||
course_modules:undefined,
|
||||
hidden_modules:[],
|
||||
is_teacher:false,
|
||||
isaloadtype:true,
|
||||
coursesidtype:undefined,
|
||||
locationNavfun:this.locationNav,
|
||||
unlocationNavfun:this.unlocationNavfun
|
||||
}
|
||||
}
|
||||
|
||||
coursesidsfun=(id,type)=>{
|
||||
this.setState({
|
||||
coursesids:id,
|
||||
coursesidtype:type
|
||||
})
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
// this.updataleftNav()
|
||||
this.historyArray = [window.location.pathname];
|
||||
|
||||
this.props.history.listen( location => {
|
||||
this.historyArray.unshift(window.location.pathname);
|
||||
this.historyArray.length = 2;
|
||||
//Do your stuff here
|
||||
});
|
||||
}
|
||||
//更新左边课堂导航
|
||||
updataleftNav=()=>{
|
||||
let query=this.props.location.pathname
|
||||
let {isaloadtype}=this.state;
|
||||
let types=isaloadtype===false?true:false
|
||||
const type = query.split('/');
|
||||
let id=parseInt(type[2])
|
||||
if(isNaN(id)){
|
||||
return
|
||||
}
|
||||
|
||||
const querys = this.props.location.search;
|
||||
var dataqueryss={}
|
||||
try {
|
||||
var foqus=this.foo(querys);
|
||||
if(JSON.stringify(foqus) ==="{}"){
|
||||
this.setState({
|
||||
dataquerys:{},
|
||||
});
|
||||
}else{
|
||||
this.setState({
|
||||
dataquerys:foqus,
|
||||
});
|
||||
dataqueryss=foqus;
|
||||
}
|
||||
}catch (e) {
|
||||
this.setState({
|
||||
dataquerys:{},
|
||||
})
|
||||
}
|
||||
// let id=this.props.match.params.coursesId;
|
||||
let url ="/courses/"+id+"/left_banner.json"
|
||||
axios.get(url,
|
||||
{params:
|
||||
dataqueryss
|
||||
}
|
||||
).then((response) => {
|
||||
if(response!=undefined){
|
||||
if(response.data&&response.data){
|
||||
this.setState({
|
||||
course_modules:response.data.course_modules,
|
||||
hidden_modules:response.data.hidden_modules,
|
||||
is_teacher:response.data.is_teacher,
|
||||
isaloadtype:types
|
||||
})
|
||||
this.locationNav(response.data.course_modules)
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
foo=(url)=> {
|
||||
var json = {};
|
||||
var regExp = /[\?\&](\w+)(=?)(\w*)/g;
|
||||
var arr;
|
||||
do {
|
||||
arr = regExp.exec(url);
|
||||
// console.log(arr); // arr = [完整的字符串, key, 等号或'', value或'']
|
||||
|
||||
if (arr) {
|
||||
var key = arr[1];
|
||||
var value = arr[3];
|
||||
// arr[2] === ''时, value = undefined
|
||||
if (!arr[2])
|
||||
value = undefined;
|
||||
|
||||
json[key] = value;
|
||||
}
|
||||
} while (arr);
|
||||
|
||||
return json;
|
||||
};
|
||||
|
||||
locationNav=(list)=>{
|
||||
if(list){
|
||||
let url=this.props.location.pathname;
|
||||
const type = url.split('/');
|
||||
let filesId=parseInt(type[4]);
|
||||
// let urls=this.props.match.url
|
||||
|
||||
var lists=list;
|
||||
|
||||
lists.forEach((item,index)=>{
|
||||
|
||||
if(url===item.category_url){
|
||||
this.setState({
|
||||
indexs:index,
|
||||
mainurl:item.category_url
|
||||
})
|
||||
this.coursesidsfun(item.id,"node")
|
||||
}else{
|
||||
if(item.second_category!=undefined&&item.second_category.length!=0){
|
||||
item.second_category.forEach((iem,key)=>{
|
||||
if(url===iem.second_category_url){
|
||||
|
||||
if( parseInt(filesId)===iem.category_id||parseInt(filesId)===item.id){
|
||||
this.setState({
|
||||
indexs:index,
|
||||
url:url,
|
||||
mainurl:item.category_url
|
||||
})
|
||||
}
|
||||
this.coursesidsfun(item.id,"child")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
unlocationNavfun=(val)=>{
|
||||
this.setState({
|
||||
indexs:val,
|
||||
})
|
||||
}
|
||||
// // 老师、管理员等
|
||||
// isAdmin = () => {
|
||||
// return this.state.coursedata && this.state.coursedata.course_identity < 4
|
||||
// }
|
||||
// // 学生
|
||||
// isStudent = () => {
|
||||
// return this.state.coursedata && this.state.coursedata.course_identity === 4
|
||||
// }
|
||||
// isAdminOrStudent = () => {
|
||||
// return this.state.coursedata && this.state.coursedata.course_identity <= 4
|
||||
// }
|
||||
// // 非课堂成员
|
||||
// isNotMember = () => {
|
||||
// return this.state.coursedata && this.state.coursedata.course_identity === 5
|
||||
// }
|
||||
|
||||
|
||||
// isCourseidentity = () => {
|
||||
//
|
||||
// if(this.state.coursedata&&this.state.coursedata.course_identity < 4){
|
||||
// return "isAdmin"
|
||||
// // 老师、管理员等
|
||||
// }else if(this.state.coursedata&&this.state.coursedata.course_identity === 4){
|
||||
// return "isStudent"
|
||||
// // 学生
|
||||
// }else if(this.state.coursedata&&this.state.coursedata.course_identity === 5){
|
||||
// return "isNotMember"
|
||||
// // 非课堂成员
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
// componentDidMount(){
|
||||
// // console.log(this.props.location.pathname)
|
||||
// let query=this.props.location.pathname;
|
||||
// const type = query.split('/');
|
||||
// if (!type[2]) {
|
||||
// return;
|
||||
// }
|
||||
// let id=parseInt(type[2])
|
||||
//
|
||||
// let url="/courses/"+id+"/top_banner.json"
|
||||
// axios.get(url).then((result)=>{
|
||||
// if(result.status===200){
|
||||
// let data=result.data;
|
||||
// this.setState({
|
||||
// coursedata:data
|
||||
// })
|
||||
//
|
||||
// // console.log(data)
|
||||
// }
|
||||
// }).catch((error)=>{
|
||||
// console.log(error);
|
||||
// })
|
||||
|
||||
// }
|
||||
|
||||
render() {
|
||||
const common = {
|
||||
previousPathName: this.historyArray && this.historyArray[1]
|
||||
// isAdmin: this.isAdmin,
|
||||
// isStudent: this.isStudent,
|
||||
// isAdminOrStudent: this.isAdminOrStudent,
|
||||
|
||||
// isNotMember: this.isNotMember,
|
||||
// isCourseidentity:this.isCourseidentity
|
||||
}
|
||||
// const commons = {
|
||||
// admind: this.props.user,
|
||||
// // isAdminOrStudent: this.isAdminOrStudent,
|
||||
//
|
||||
// // isNotMember: this.isNotMember,
|
||||
// // isCourseidentity:this.isCourseidentity
|
||||
// }
|
||||
// console.log("commonscommons")
|
||||
// console.log(commons)
|
||||
return (
|
||||
<Switch {...this.props}>
|
||||
{/*排序*/}
|
||||
<Route path="/courses/:coursesId/ordering/:ordering_type/:main_id"
|
||||
render={
|
||||
(props) => (<Ordering {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/*视频列表*/}
|
||||
|
||||
<Route path="/courses/:coursesId/course_videos"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 资源列表页 */}
|
||||
<Route path="/courses/:coursesId/file/:Id" exact
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/courses/:coursesId/files/:main_id"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
<Route exact path="/courses/:coursesId/boards/:boardId"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
{/*课堂讨论*/}
|
||||
<Route path="/courses/:coursesId/boards/:boardId"
|
||||
render={
|
||||
(props) => (<BoardIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 毕业设计 */}
|
||||
{/* 毕设问答 */}
|
||||
<Route path="/courses/:coursesId/graduation_topics/postwork/new"
|
||||
render={
|
||||
(props) => (<GraduateTopicPostWorksNew {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 毕设选题新建页 */}
|
||||
<Route path="/courses/:coursesId/graduation_topics/new"
|
||||
render={
|
||||
(props) => (<GraduateTopicNew {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}></Route>
|
||||
{/* 毕设选题编辑页*/}
|
||||
<Route path="/courses/:coursesId/graduation_topics/:topicId/edit"
|
||||
render={
|
||||
(props) => (<GraduateTopicNew {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}></Route>
|
||||
|
||||
{/* 毕设选题详情页 */}
|
||||
<Route path="/courses/:course_id/graduation_topics/:graduation_topic_id/detail"
|
||||
render={
|
||||
(props)=>(<GraduationTopicsDetail {...this.props} {...props} {...this.state}></GraduationTopicsDetail>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 毕设选题列表 */}
|
||||
<Route path="/courses/:coursesId/graduation_topics/:Id" exact
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}></Route>
|
||||
|
||||
|
||||
{/*————————————————————————————————————————————————————————————————————————————————————*/}
|
||||
{/* 作品评阅 https://www.trustie.net/issues/19981 */}
|
||||
<Route path="/courses/:coursesId/graduation_tasks/:category_id/appraise"
|
||||
render={
|
||||
(props) => (<GraduationTasksappraise {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 新建作品 */}
|
||||
<Route path="/courses/:coursesId/graduation_tasks/:category_id/works/:task_Id/new"
|
||||
render={
|
||||
(props) => (<GraduationTasksSubmitnewApp {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 修改作品 */}
|
||||
<Route path="/courses/:coursesId/graduation_tasks/:category_id/works/:work_Id/edit"
|
||||
render={
|
||||
(props) => (<GraduationTasksSubmiteditApp {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 设置毕设任务 https://www.trustie.net/issues/19981 */}
|
||||
|
||||
{/* <Route path="/courses/:coursesId/graduation_tasks/:category_id/:task_Id/setting"
|
||||
render={
|
||||
(props) => (<GraduationTaskssetting {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
<Route path="/courses/:coursesId/graduation_tasks/:category_id/:task_Id/questions"
|
||||
render={
|
||||
(props) => (<GraduationTasksquestions {...this.props} {...props} {...this.state} />)
|
||||
}></Route> */}
|
||||
|
||||
|
||||
<Route path="/courses/:coursesId/graduation_tasks/:category_id/detail/:task_Id"
|
||||
render={
|
||||
(props) => (<GraduationTaskssettinglist {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
{/* 修改毕设任务 https://www.trustie.net/issues/19981 */}
|
||||
<Route path="/courses/:coursesId/graduation_tasks/:category_id/edit"
|
||||
render={
|
||||
(props) => (<GraduationTaskseditApp {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
{/* 新建毕设任务 https://www.trustie.net/issues/19981 */}
|
||||
<Route path="/courses/:coursesId/graduation_tasks/:category_id/new"
|
||||
render={
|
||||
(props) => (<GraduationTasksnewApp {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
{/* 毕设任务列表 https://www.trustie.net/issues/19981 */}
|
||||
<Route path="/courses/:coursesId/graduation_tasks/:Id" exact
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/*/!* 毕业设计主 https://www.trustie.net/issues/19981 *!/*/}
|
||||
{/*<Route path="/courses/:coursesId/graduation"*/}
|
||||
{/*render={*/}
|
||||
{/*(props) => (<GraduationTopics {...this.props} {...props} {...this.state} {...common}/>)*/}
|
||||
{/*}*/}
|
||||
{/*></Route>*/}
|
||||
|
||||
{/*/!* 资源子目录 https://www.trustie.net/issues/19917 *!/*/}
|
||||
{/*<Route path="/courses/:coursesId/attachment/attachment/:attachmentId"*/}
|
||||
{/*render={*/}
|
||||
{/*(props) => (<Files {...this.props} {...props} {...this.state} {...common}/>)*/}
|
||||
{/*}*/}
|
||||
{/*></Route>*/}
|
||||
{/* 教师列表*/}
|
||||
<Route path="/courses/:coursesId/teachers"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
{/* 学生列表*/}
|
||||
<Route path="/courses/:coursesId/students"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
{/* 分班列表 */}
|
||||
<Route path="/courses/:coursesId/course_groups/:course_group_id"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/courses/:coursesId/course_groups"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 普通作业 */}
|
||||
<Route path="/courses/:coursesId/common_homeworks/:category_id" exact
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
{/* 分组作业 */}
|
||||
<Route path="/courses/:coursesId/group_homeworks/:category_id" exact
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 普通作业 */}
|
||||
<Route path="/courses/:coursesId/common_homeworks/" strict
|
||||
render={
|
||||
(props) => (<CommonWork {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 分组作业 */}
|
||||
<Route path="/courses/:coursesId/group_homeworks/" strict
|
||||
render={
|
||||
(props) => (<GroupWork {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 问卷答题 */}
|
||||
<Route path="/courses/:coursesId/polls/:pollId/users/:login"
|
||||
render={
|
||||
(props) => (<PollInfo {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 问卷详情 */}
|
||||
<Route path="/courses/:coursesId/polls/:pollId/detail"
|
||||
render={
|
||||
(props) => (<PollDetail {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 问卷新建 */}
|
||||
<Route path="/courses/:coursesId/polls/:pollid/:news"
|
||||
render={
|
||||
(props) => (<PollNew {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
{/*/!* 问卷编辑 *!/*/}
|
||||
{/*<Route path="/courses/:coursesId/polls/:pollid/:news"*/}
|
||||
{/*render={*/}
|
||||
{/*(props) => (<PollNew {...this.props} {...props} {...this.state} {...common} />)*/}
|
||||
{/*}*/}
|
||||
{/*></Route>*/}
|
||||
{/* 问卷 */}
|
||||
<Route path="/courses/:coursesId/polls/:Id"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
{/* 试卷查看/评阅 */}
|
||||
<Route exact path="/courses/:coursesId/exercises/:Id/users/:userId"
|
||||
render={
|
||||
(props)=>(<ExerciseReviewAndAnswer {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/*试卷新建 */}
|
||||
<Route exact path="/courses/:coursesId/exercises/new"
|
||||
render={
|
||||
(props) => (<ExerciseNew {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
{/*试卷新建 */}
|
||||
<Route exact path="/courses/:coursesId/exercises/:Id/edit"
|
||||
render={
|
||||
(props) => (<ExerciseNew {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/*试卷设置主页*/}
|
||||
|
||||
<Route path="/courses/:coursesId/exercises/:Id/student_exercise_list"
|
||||
render={
|
||||
(props) => (<Testpapersettinghomepage {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
{/*学生完成列表*/}
|
||||
<Route
|
||||
path="/courses/:coursesId/exercises/:Id/Studentshavecompletedthelist"
|
||||
render={
|
||||
(props) => (<Studentshavecompletedthelist {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
>
|
||||
</Route>
|
||||
{/* 试卷 */}
|
||||
<Route path="/courses/:coursesId/exercises/:Id"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
{/*实训查重详情*/}
|
||||
<Route path="/courses/:coursesId/shixun_homeworks/:homeworkid/review_detail/:userid"
|
||||
render={
|
||||
(props) => (<ShixunWorkDetails {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/courses/:coursesId/shixun_homework/:homeworkid/review_detail/:userid"
|
||||
render={
|
||||
(props) => (<ShixunWorkDetails {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/*实训查重列表*/}
|
||||
<Route path="/courses/:coursesId/shixun_homeworks/:homeworkid/student_work"
|
||||
render={
|
||||
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/courses/:coursesId/shixun_homework/:homeworkid/student_work"
|
||||
render={
|
||||
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/*实训报告*/}
|
||||
<Route path="/courses/:coursesId/shixun_homeworks/:homeworkid/shixun_work_report"
|
||||
render={
|
||||
(props) => (<ShixunWorkReport {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/courses/:coursesId/shixun_homework/:homeworkid/shixun_work_report"
|
||||
render={
|
||||
(props) => (<ShixunWorkReport {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/*教师列表*/}
|
||||
<Route path="/courses/:coursesId/shixun_homeworks/:homeworkid/list"
|
||||
render={
|
||||
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/courses/:coursesId/shixun_homework/:homeworkid/list"
|
||||
render={
|
||||
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
{/*实训作业page*/}
|
||||
<Route path="/courses/:coursesId/shixun_homeworks/:homeworkid/Page"
|
||||
render={
|
||||
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
{/*实训作业设置*/}
|
||||
<Route path="/courses/:coursesId/shixun_homeworks/:homeworkid/settings"
|
||||
render={
|
||||
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/courses/:coursesId/shixun_homework/:homeworkid/settings"
|
||||
render={
|
||||
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
{/*/!*实训作品列表教师*!/*/}
|
||||
{/*提交总结*/}
|
||||
<Route path="/courses/:coursesId/shixun_homeworks/:id/commitsummary/:homeworkid"
|
||||
render={
|
||||
(props) => (<CommitSummary {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/courses/:coursesId/shixun_homework/:id/commitsummary/:homeworkid"
|
||||
render={
|
||||
(props) => (<CommitSummary {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/*实训作品列表学生未公布*/}
|
||||
{/*<Route path="/courses/:coursesId/shixun_homeworks/:homeworkid/noopenlist"*/}
|
||||
{/* render={*/}
|
||||
{/* (props) => (<Studentnotcompleted {...this.props} {...props} {...this.state} />)*/}
|
||||
{/* }*/}
|
||||
{/*></Route>*/}
|
||||
{/*实训学生作品列表已公布*/}
|
||||
{/* <Route path="/courses/:coursesId/shixun_homeworks/:homeworkid/list"*/}
|
||||
{/* render={*/}
|
||||
{/* (props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} />)*/}
|
||||
{/* }*/}
|
||||
{/* ></Route>*/}
|
||||
{/*/!*实训学生作品列表已公布*!/*/}
|
||||
{/*<Route path="/courses/:coursesId/shixun_homework/:homeworkid/list"*/}
|
||||
{/* render={*/}
|
||||
{/* (props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} />)*/}
|
||||
{/* }*/}
|
||||
{/*></Route>*/}
|
||||
|
||||
|
||||
|
||||
{/*实训作业问答主目录*/}
|
||||
<Route path="/courses/:coursesId/shixun_homeworks/:homeworkid/questions"
|
||||
render={
|
||||
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/*实训作业问答子目录*/}
|
||||
<Route path="/courses/:coursesId/shixun_homework/:homeworkid/questions"
|
||||
render={
|
||||
(props) => (<ShixunHomeworkPage {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/*新建课堂*/}
|
||||
<Route path="/courses/new"
|
||||
render={
|
||||
(props) => (<WrappedCoursesNewApp {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
{/*新建精品课堂*/}
|
||||
{/*coursesId 课堂id */}
|
||||
{/*id 是否是私有或者公有*/}
|
||||
<Route path="/courses/news/:subjectid/newgold/:id"
|
||||
render={
|
||||
(props) => (<WrappedCoursesNewAppGoldclass {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
{/*修改精品课堂*/}
|
||||
<Route path="/courses/:coursesId/newgolds/settings"
|
||||
render={
|
||||
(props) => (<WrappedCoursesNewAppGoldclass {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
{/*修改课堂*/}
|
||||
<Route path="/courses/:coursesId/settings"
|
||||
render={
|
||||
(props) => (<WrappedCoursesNewApp {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 实训作业子页面*/}
|
||||
<Route path="/courses/:coursesId/shixun_homework/:category_id"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 实训作业页面*/}
|
||||
<Route path="/courses/:coursesId/shixun_homeworks/:main_id"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/*课堂统计列表2019.10.29 */}
|
||||
|
||||
<Route path="/courses/:coursesId/statistics"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/*/!*实训作业and课堂详情页*!/*/}
|
||||
<Route path="/courses/:coursesId"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/*课堂首页*/}
|
||||
<Route path="/courses"
|
||||
render={
|
||||
(props) => (<CoursesHome {...this.props} {...props} {...this.state} {...common}/>)
|
||||
}
|
||||
></Route>
|
||||
{/*<Route exact path="/courses" component={CoursesHome} {...this.props} {...props} {...this.state} ></Route>*/}
|
||||
|
||||
</Switch>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(ImageLayerOfCommentHOC({imgSelector: '.imageLayerParent img, .imageLayerParent .imageTarget', parentSelector: '.newMain'}) (CNotificationHOC() ( SnackbarHOC() ( TPMIndexHOC(CoursesIndex) ))));
|
||||
@@ -0,0 +1,371 @@
|
||||
import React, { Component } from 'react';
|
||||
import {BrowserRouter as Router,Route,Switch} from 'react-router-dom';
|
||||
|
||||
import {Input,Pagination,Tooltip} from 'antd';
|
||||
import Loadable from 'react-loadable';
|
||||
import Loading from '../../Loading';
|
||||
import Guide from "../../modules/courses/shixunHomework/Guide";
|
||||
//业务组件
|
||||
import CoursesBanner from "./coursesDetail/CoursesBanner";
|
||||
import Coursesleftnav from "./coursesDetail/CoursesLeftNav";
|
||||
|
||||
//普通作业
|
||||
const CommonWork = Loadable({
|
||||
loader: () => import('./busyWork/commonWork'),
|
||||
loading:Loading,
|
||||
})
|
||||
const GroupWork= Loadable({
|
||||
loader: () => import('./busyWork/commonWork'),
|
||||
loading: Loading,
|
||||
})
|
||||
// 讨论
|
||||
const Boards= Loadable({
|
||||
loader: () => import('./boards'),
|
||||
loading: Loading,
|
||||
})
|
||||
//教师列表
|
||||
const TeacherList= Loadable({
|
||||
loader: () => import('./members/teacherList'),
|
||||
loading: Loading,
|
||||
})
|
||||
//学生列表
|
||||
const StudentsList= Loadable({
|
||||
loader: () => import('./members/studentsList'),
|
||||
loading: Loading,
|
||||
});
|
||||
//分班列表
|
||||
const CourseGroupList= Loadable({
|
||||
loader: () => import('./members/CourseGroupList'),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const Eduinforms= Loadable({
|
||||
loader: () => import('./gradinforms/Eduinforms'),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
//2019.10.29 统计
|
||||
const Statistics=Loadable({
|
||||
loader: () => import('./statistics/Statistics'),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const Elearning= Loadable({
|
||||
loader: () => import('./elearning/Elearning'),
|
||||
loading: Loading,
|
||||
});
|
||||
//
|
||||
const Exercise= Loadable({
|
||||
loader: () => import('./exercise/Exercise'),
|
||||
loading: Loading,
|
||||
})
|
||||
//
|
||||
const Poll= Loadable({
|
||||
loader: () => import('./poll/Poll'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
// 资源
|
||||
const Resourcelist= Loadable({
|
||||
loader: () => import('./Resource/index'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
// 视频
|
||||
const CourseVideo = Loadable({
|
||||
loader: () => import('./Video/VideoIndex'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
//实训作业
|
||||
const ShixunHomework= Loadable({
|
||||
loader: () => import('./shixunHomework/shixunHomework'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
const GraduationTopics= Loadable({
|
||||
loader: () => import('./graduation/topics'),
|
||||
loading: Loading,
|
||||
})
|
||||
const GraduationTasks= Loadable({
|
||||
loader: () => import('./graduation/tasks'),
|
||||
loading: Loading,
|
||||
})
|
||||
class ListPageIndex extends Component{
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state={
|
||||
yslGuideone:undefined,
|
||||
yslElearning:false,
|
||||
isexcellent:false
|
||||
}
|
||||
}
|
||||
comyslElearning(bool){
|
||||
if(bool===true){
|
||||
this.setState({
|
||||
yslElearning:true,
|
||||
})
|
||||
}else {
|
||||
this.setState({
|
||||
yslElearning:false,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
componentDidMount(){
|
||||
// console.log("77");
|
||||
var yslGuideone = window.localStorage.getItem('yslGuideone');
|
||||
// console.log("78");
|
||||
// console.log(yslGuideone);
|
||||
try {
|
||||
if (yslGuideone === "true") {
|
||||
// console.log("true 字符串");
|
||||
this.setState({
|
||||
yslGuideone:true,
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
yslGuideone:false,
|
||||
});
|
||||
// console.log("false 字符串");
|
||||
}
|
||||
}catch (e) {
|
||||
console.log(e);
|
||||
this.setState({
|
||||
yslGuideone:false,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//
|
||||
// getleftNavid=(navid,newselectnavid)=>{
|
||||
// console.log(navid,newselectnavid)
|
||||
// this.setState({
|
||||
// navkey:navid,
|
||||
// navttype:newselectnavid
|
||||
// })
|
||||
// }
|
||||
componentWillUnmount(){
|
||||
// window.localStorage.setItem('yslGuideone', "false");
|
||||
}
|
||||
setwindowlocal=(bool)=>{
|
||||
window.localStorage.setItem('yslGuideone', bool);
|
||||
try {
|
||||
if (bool === "true") {
|
||||
|
||||
this.setState({
|
||||
yslGuideone:true,
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
yslGuideone:false,
|
||||
});
|
||||
|
||||
}
|
||||
}catch (e) {
|
||||
// console.log(e);
|
||||
this.setState({
|
||||
yslGuideone:false,
|
||||
});
|
||||
}
|
||||
}
|
||||
ispostexcellenttype=(excellent)=>{
|
||||
this.setState({
|
||||
isexcellent:excellent
|
||||
})
|
||||
}
|
||||
render() {
|
||||
let {yslGuideone} =this.state;
|
||||
// console.log("98");
|
||||
// console.log(yslGuideone);
|
||||
// console.log(this.props.isAdmin());
|
||||
// // var yslGuideones = window.sessionStorage.getItem('yslGuideone');
|
||||
// console.log(this.props);
|
||||
// console.log(this.props.location.search);
|
||||
return (
|
||||
<div>
|
||||
<div className="newMain clearfix">
|
||||
{/*头部banner*/}
|
||||
<CoursesBanner {...this.props} ispostexcellenttype={(excellent)=>this.ispostexcellenttype(excellent)}></CoursesBanner>
|
||||
{/*下面是指引哦*/}
|
||||
{/*{yslGuideone!==undefined?*/}
|
||||
{/*(*/}
|
||||
{/* yslGuideone===true?*/}
|
||||
{/* <Guide*/}
|
||||
{/* setwindowlocal={(b)=>this.setwindowlocal(b)}*/}
|
||||
{/* >*/}
|
||||
{/* </Guide>*/}
|
||||
{/* :""*/}
|
||||
{/* )*/}
|
||||
{/* :""*/}
|
||||
{/*}*/}
|
||||
<div className="educontent clearfix" style={{flex: "1 0 auto"}}>
|
||||
|
||||
<div className="stud-class-set">
|
||||
<div className="news">
|
||||
<div className="edu-class-inner container clearfix">
|
||||
<div className="member for-content-0 for-content">
|
||||
<div className="people clearfix mb60">
|
||||
|
||||
{/*left_nav*/}
|
||||
<div className={"with22 fl setleft"} style={{width:'264px',minHeight:'500px'}}>
|
||||
<Coursesleftnav {...this.props} {...this.state} comyslElearning={(i)=>this.comyslElearning(i)}/>
|
||||
</div>
|
||||
|
||||
{/*right_concent*/}
|
||||
<div className="with78 fl">
|
||||
<div className={"ml20 clearfix"}>
|
||||
<Switch {...this.props}>
|
||||
{/* --------------------------------------------------------------------- */}
|
||||
|
||||
{/* 作业设置 */}
|
||||
{/* http://localhost:3007/courses/1309/homework/9300/setting */}
|
||||
{/* 普通作业 */}
|
||||
<Route path="/courses/:coursesId/common_homeworks/:category_id"
|
||||
render={
|
||||
(props) => (<CommonWork {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 作品列表 */}
|
||||
<Route path="/courses/:coursesId/group_homeworks/:category_id"
|
||||
render={
|
||||
(props) => (<CommonWork {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route exact path="/courses/:coursesId/boards/:boardId"
|
||||
render={
|
||||
(props) => (<Boards {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/*视频列表*/}
|
||||
|
||||
<Route path="/courses/:coursesId/course_videos"
|
||||
render={
|
||||
(props) => (<CourseVideo {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/courses/:coursesId/teachers"
|
||||
render={
|
||||
(props) => (<TeacherList {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 学生列表*/}
|
||||
<Route path="/courses/:coursesId/students"
|
||||
render={
|
||||
(props) => (<StudentsList {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/courses/:coursesId/course_groups/:course_group_id"
|
||||
render={
|
||||
(props) => (<StudentsList {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/courses/:coursesId/course_groups"
|
||||
render={
|
||||
(props) => (<CourseGroupList {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route path="/courses/:coursesId/exercises/:Id"
|
||||
render={
|
||||
(props) => (<Exercise {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route path="/courses/:coursesId/polls/:Id"
|
||||
render={
|
||||
(props) => (<Poll {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* <Route path="/courses/:coursesId/file/:Id"
|
||||
render={
|
||||
(props) => (<Resourcelist {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route> */}
|
||||
|
||||
{/* 实训作业子页面*/}
|
||||
<Route path="/courses/:coursesId/shixun_homework/:category_id"
|
||||
render={
|
||||
(props) => (<ShixunHomework {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/*课堂统计列表2019.10.29 */}
|
||||
|
||||
<Route path="/courses/:coursesId/statistics"
|
||||
render={
|
||||
(props) => (<Statistics {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
{/*公告栏列表*/}
|
||||
|
||||
<Route path="/courses/:coursesId/informs"
|
||||
render={
|
||||
(props) => (<Eduinforms {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/*在线学习*/}
|
||||
<Route
|
||||
path="/courses/:coursesId/online_learning"
|
||||
render={
|
||||
(props) => (<Elearning {...this.props} {...props} {...this.state} comyslElearning={(i)=>this.comyslElearning(i)} />)
|
||||
}
|
||||
>
|
||||
</Route>
|
||||
{/* 实训作业页面*/}
|
||||
<Route path="/courses/:coursesId/shixun_homeworks/:main_id"
|
||||
render={
|
||||
(props) => (<ShixunHomework {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
<Route path="/courses/:coursesId/files/:main_id"
|
||||
render={
|
||||
(props) => (<Resourcelist {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/courses/:coursesId/file/:Id"
|
||||
render={
|
||||
(props) => (<Resourcelist {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
<Route path="/courses/:coursesId/graduation_topics/:Id"
|
||||
render={
|
||||
(props) => (<GraduationTopics {...this.props} {...props} {...this.state} />)
|
||||
}></Route>
|
||||
<Route path="/courses/:coursesId/graduation_tasks/:Id"
|
||||
render={
|
||||
(props) => (<GraduationTasks {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 默认 */}
|
||||
<Route path="/courses/:coursesId"
|
||||
render={
|
||||
(props) => (<StudentsList {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default ListPageIndex;
|
||||
@@ -0,0 +1,368 @@
|
||||
import React,{ Component } from "react";
|
||||
import { WordsBtn } from 'educoder';
|
||||
import {Tooltip,message} from 'antd';
|
||||
import {Link} from 'react-router-dom';
|
||||
import {getImageUrl} from 'educoder';
|
||||
import axios from 'axios'
|
||||
import {getUrl} from 'educoder';
|
||||
import moment from 'moment'
|
||||
import CoursesListType from '../coursesPublic/CoursesListType';
|
||||
import Showoldfiles from "../coursesPublic/Showoldfiles";
|
||||
import Modals from '../../modals/Modals';
|
||||
|
||||
class Fileslistitem extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state = {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
settingList=()=>{
|
||||
let {discussMessage}=this.props
|
||||
|
||||
this.setState({
|
||||
discussMessageid:discussMessage.id
|
||||
})
|
||||
this.props.Settingtypes(discussMessage.id)
|
||||
}
|
||||
|
||||
showfiles=(list)=>{
|
||||
if(this.props.checkIfLogin()===false){
|
||||
this.props.showLoginDialog()
|
||||
return
|
||||
}
|
||||
// if(this.props.checkIfProfileCompleted()===false){
|
||||
// this.setState({
|
||||
// AccountProfiletype:true
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
// if(this.props.checkIfProfessionalCertification()===false){
|
||||
// this.props.showProfileCompleteDialog()
|
||||
// return
|
||||
// }
|
||||
|
||||
if(list.is_history_file===false){
|
||||
// this.props.DownloadFileA(list.title,list.url)
|
||||
//window.location.href=list.url;
|
||||
window.open(list.url, '_blank');
|
||||
}else{
|
||||
let {discussMessage,coursesId}=this.props
|
||||
let file_id=discussMessage.id
|
||||
let url="/files/"+file_id+"/histories.json"
|
||||
axios.get(url,{
|
||||
params:{
|
||||
course_id:coursesId
|
||||
},
|
||||
}).then((result)=>{
|
||||
|
||||
if(result.data.attachment_histories.length===0){
|
||||
// if(result.data.is_pdf===true){
|
||||
// this.props.ShowOnlinePdf(result.data.url)
|
||||
// //预览pdf
|
||||
// }else{
|
||||
//
|
||||
// }
|
||||
// this.props.DownloadFileA(result.data.title,result.data.url)
|
||||
window.open(list.url, '_blank');
|
||||
}else{
|
||||
this.setState({
|
||||
Showoldfiles:true,
|
||||
allfiles:result.data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}).catch((error)=>{
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
closaoldfilesprops=()=>{
|
||||
this.setState({
|
||||
Showoldfiles:false,
|
||||
})
|
||||
}
|
||||
|
||||
onDelete = (id) => {
|
||||
|
||||
this.setState({
|
||||
Modalstype:true,
|
||||
Modalstopval:"是否确认删除?",
|
||||
ModalCancel:this.cancelmodel,
|
||||
ModalSave:()=>this.savedelete(id),
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
cancelmodel=()=>{
|
||||
|
||||
this.setState({
|
||||
Modalstype:false,
|
||||
Loadtype:false,
|
||||
Modalstopval:"",
|
||||
ModalCancel:"",
|
||||
ModalSave:"",
|
||||
checkBoxValues:[],
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
savedelete=(id)=>{
|
||||
|
||||
this.setState({
|
||||
Modalstype:false,
|
||||
})
|
||||
|
||||
|
||||
const cid = this.props.match.params.coursesId
|
||||
const url = `/files/bulk_delete.json`;
|
||||
axios.delete(url, { data: {
|
||||
course_id:cid,
|
||||
ids: [id],
|
||||
}})
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
//Modalstopval:response.data.message,
|
||||
|
||||
this.props.updatafiledfun()
|
||||
this.setState({
|
||||
// Modalstype:true,
|
||||
// Modalstopval:"删除成功",
|
||||
ModalsBottomval:"",
|
||||
// ModalSave:this.cancelmodel,
|
||||
// Loadtype:true,
|
||||
checkBoxValues:[],
|
||||
checkAllValue:false
|
||||
})
|
||||
|
||||
this.props.showNotification("删除成功");
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
eventStop = (event) =>{
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
render(){
|
||||
|
||||
const { checkBox,
|
||||
discussMessage,index
|
||||
} = this.props;
|
||||
|
||||
return(
|
||||
<div className="graduateTopicList boardsList">
|
||||
|
||||
{/*提示*/}
|
||||
{this.state.Modalstype&&this.state.Modalstype===true?<Modals
|
||||
modalsType={this.state.Modalstype}
|
||||
modalsTopval={this.state.Modalstopval}
|
||||
modalCancel={this.state.ModalCancel}
|
||||
modalSave={this.state.ModalSave}
|
||||
modalsBottomval={this.state.ModalsBottomval}
|
||||
loadtype={this.state.Loadtype}
|
||||
/>:""}
|
||||
<Showoldfiles
|
||||
{...this.props}
|
||||
visible={this.state.Showoldfiles}
|
||||
allfiles={this.state.allfiles}
|
||||
closaoldfilesprops={this.closaoldfilesprops}
|
||||
/>
|
||||
<style>{`
|
||||
.graduateTopicList .ant-checkbox-input {
|
||||
margin-right: 15px;
|
||||
}
|
||||
.graduateTopicList .ant-checkbox-wrapper {
|
||||
margin-top: 0px;
|
||||
}
|
||||
`}</style>
|
||||
|
||||
|
||||
<style>{`
|
||||
.boardsList .panel-list-img {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
`}</style>
|
||||
{/*<a href={"/users/"+this.props.user.login} alt="用户"*/}
|
||||
{/*style={{"width": "50px", "height": "50px", "display": "block", margin: "0 10px"}}>*/}
|
||||
{/*<img*/}
|
||||
{/*alt="1?1529221779" className="panel-list-img mr15" height="50"*/}
|
||||
{/*src={getImageUrl("images/"+discussMessage.author.image_url)} width="50"*/}
|
||||
{/*></img>*/}
|
||||
{/*</a>*/}
|
||||
|
||||
<style>{`
|
||||
.boardsList .contentSection{
|
||||
margin-left:0px;
|
||||
}
|
||||
.maxwidth580{
|
||||
max-width: 580px;
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space:nowrap
|
||||
}
|
||||
.mt2{
|
||||
margin-top:2px;
|
||||
}
|
||||
`}</style>
|
||||
<div className="clearfix ds pr contentSection" style={{cursor : this.props.isAdmin ? "pointer" : "default"}} onClick={() => window.$(`.sourceitem${index} input`).click() }>
|
||||
<h6 onClick={(event)=>this.eventStop(event)}>
|
||||
<span className={`sourceitem${index} fl mr12 mt3`}>
|
||||
{checkBox}
|
||||
</span>
|
||||
{
|
||||
this.props.isAdmin ? <a
|
||||
// href={"/courses/" + coursesId + "/graduation/graduation_tasks/" + categoryid + "/" + taskid + "/list"}
|
||||
onClick={()=>this.showfiles(discussMessage)}
|
||||
title={discussMessage.title}
|
||||
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a> : ""
|
||||
}
|
||||
{
|
||||
this.props.isStudent? <a
|
||||
onClick={()=>this.showfiles(discussMessage)}
|
||||
title={discussMessage.title}
|
||||
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a> :""
|
||||
}
|
||||
|
||||
{
|
||||
this.props.isNotMember===true?
|
||||
discussMessage.is_lock === true ?
|
||||
<span className="fl mt3 font-16 font-bd color-dark maxwidth580 pointer" title={"私有属性,非课堂成员不能访问"}>{discussMessage.title}</span>
|
||||
:<a
|
||||
onClick={()=>this.showfiles(discussMessage)}
|
||||
title={discussMessage.title}
|
||||
className="fl mt3 font-16 font-bd color-dark maxwidth580">{discussMessage.title}</a>:""
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
discussMessage.is_lock === true ?
|
||||
<Tooltip title={"私有属性,非课堂成员不能访问"} placement="bottom">
|
||||
<i className="iconfont icon-guansuo color-grey-c ml10 font-16 fl mt4"></i>
|
||||
</Tooltip>
|
||||
:""
|
||||
}
|
||||
{discussMessage.is_publish===false?<CoursesListType typelist={["未发布"]} typesylename={""}/>:""}
|
||||
|
||||
{this.props.isAdmin?
|
||||
<span className={"fr mt2"} onClick={(event)=>this.eventStop(event)}>
|
||||
<WordsBtn style="blue" className="colorblue font-16 ml20 fr">
|
||||
<a className="btn colorblue fontweight400"
|
||||
onClick={()=>this.settingList()}>设置</a>
|
||||
</WordsBtn>
|
||||
</span>:""}
|
||||
|
||||
{this.props.isStudent===true&&this.props.current_user.login===discussMessage.author.login?
|
||||
<span className={"fr mt2"} onClick={(event)=>this.eventStop(event)}>
|
||||
|
||||
<WordsBtn style="blue" className="colorblue font-16 ml20 fr">
|
||||
<a className="btn colorblue fontweight400"
|
||||
onClick={()=>this.settingList()}>设置</a>
|
||||
</WordsBtn>
|
||||
|
||||
<WordsBtn style="blue" className="colorblue font-16 ml20 fr">
|
||||
<a className="btn colorblue fontweight400"
|
||||
onClick={()=>this.onDelete(discussMessage.id)}>删除</a>
|
||||
</WordsBtn>
|
||||
|
||||
</span>:""}
|
||||
</h6>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.sttingbox{
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 20px;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.lightgreybox{
|
||||
min-width: 260px;
|
||||
}
|
||||
.mrf2{
|
||||
margin-top: -2px;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
{/*资源分班*/}
|
||||
{/*{discussMessage.course_groups.length===0?"":*/}
|
||||
{/*<p className="color-grey panel-lightgrey mt8 fl lightgreybox ml30" style={{width:'100%'}}>*/}
|
||||
{/*{discussMessage.course_groups.map((item,key)=>{*/}
|
||||
{/*return(*/}
|
||||
{/*<div className="mr50">*/}
|
||||
{/*<span className="mr15 color-dark">{item.course_group_name}</span>*/}
|
||||
{/*<span className="mr15 color-grey9 ">将发布于 { moment(item.course_group_publish_time).format('YYYY-MM-DD HH:mm')}</span>*/}
|
||||
{/*</div>*/}
|
||||
{/*)*/}
|
||||
{/*})}*/}
|
||||
|
||||
{/*</p>}*/}
|
||||
|
||||
<p className={this.props.isAdmin===true?"color-grey panel-lightgrey mt8 fl ml30":"color-grey panel-lightgrey mt8 fl ml13"} style={{width:'100%'}}>
|
||||
<span className="mr50">
|
||||
<span className="mr15 color-dark">{discussMessage.author.name}</span>
|
||||
<span className="mr15 color-grey9">大小 {discussMessage.filesize}</span>
|
||||
<span className="mr15 color-grey9">下载 {discussMessage.downloads_count}</span>
|
||||
{/*<span className="mr15 color-grey9">引用 {discussMessage.quotes}</span>*/}
|
||||
<span className="mr15 color-grey-c">
|
||||
{/*{moment(discussMessage.publish_time).format('YYYY-MM-DD HH:mm:ss')}*/}
|
||||
{/*{moment(discussMessage.publish_time).fromNow()}*/}
|
||||
{ discussMessage.publish_time===null?"":
|
||||
discussMessage.is_publish===true?"":"发布于"}
|
||||
{ discussMessage.publish_time===null?"":discussMessage.is_publish===true?moment(discussMessage.publish_time).fromNow():moment(discussMessage.publish_time).format('YYYY-MM-DD HH:mm')}
|
||||
</span>
|
||||
</span>
|
||||
{discussMessage&&discussMessage.category_name===null?"":this.props.child===false?<div className="color-grey9 task-hide fr mr30" title={discussMessage&&discussMessage.category_name}
|
||||
style={{"max-width":"268px"}}>所属目录:{discussMessage&&discussMessage.category_name}
|
||||
</div>:""}
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<p className={this.props.isAdmin===true?"color-grey panel-lightgrey mt8 fl ml30":"color-grey panel-lightgrey mt8 fl ml13"} style={{width:'94%'}}>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.isspans{
|
||||
text-align: left;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
<span className="color-dark isspans">资源描述 :{discussMessage.description===null?"暂无描述":discussMessage.description}</span>
|
||||
{/*<span className="mr50">*/}
|
||||
{/*/!*<span className="mr15 color-dark"></span>*!/*/}
|
||||
{/*<span className="mr15 color-dark">*/}
|
||||
|
||||
{/*</span>*/}
|
||||
{/*/!*{this.props.isAdmin ?<span><i className="iconfont icon-bianjidaibeijing font-22 color-green" onClick={()=>this.settingList()}></i></span>:""}*!/*/}
|
||||
{/*</span>*/}
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default Fileslistitem;
|
||||
@@ -0,0 +1,82 @@
|
||||
import React,{ Component } from "react";
|
||||
import { Pagination } from 'antd';
|
||||
// import { NoneData } from 'educoder';
|
||||
|
||||
import LiveItem from './LiveItem';
|
||||
import './video.css';
|
||||
|
||||
import bilibili from './images/bilibili.png';
|
||||
import tencent from './images/tencent.png';
|
||||
import WeiBaiTong from './images/WeiBaiTong.png';
|
||||
import douyu from './images/douyu.jpg';
|
||||
class Live extends Component{
|
||||
|
||||
render(){
|
||||
const { liveData , lives , successFunc , pageSize , changePage , page } = this.props;
|
||||
|
||||
return(
|
||||
<div className="livePanel">
|
||||
<p className="mt30 mb10 color-grey-9 pl10">EduCoder支持所有第三方直播平台,特别推荐:</p>
|
||||
<ul className="platform">
|
||||
<li>
|
||||
<a href="https://ke.qq.com/act/speed_pc/index.html?from=800021837" target="_blank"><img alt="" src={tencent} className="mr8" width="28px"/>
|
||||
<label className="color-grey-3 pointer">腾讯课堂</label>
|
||||
</a>
|
||||
<a href="https://pub.idqqimg.com/pc/misc/files/20200204/2e4cb765bef54f0c919c0ab8ab79d969.pdf" target="_blank" className="color-blue ml20">(简明手册)</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://live.bilibili.com/liveHime?visit_id=a81rbm7v2kk0" target="_blank"><img alt="" src={bilibili} className="mr8" width="52px"/>
|
||||
<label className="color-grey-3 pointer">哔哩哔哩</label>
|
||||
</a>
|
||||
<a href="https://www.bilibili.com/blackboard/live/broadcast-intro.html#/" target="_blank" className="color-blue ml20">(简明手册)</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.douyu.com/" target="_blank"><img alt="" src={douyu} className="mr8" width="28px"/>
|
||||
<label className="color-grey-3 pointer">斗鱼</label>
|
||||
</a>
|
||||
<a href="https://www.douyu.com/special/guide/anchor" target="_blank" className="color-blue ml20">(简明手册)</a>
|
||||
</li>
|
||||
<li>
|
||||
<div><img alt="" src={WeiBaiTong} className="mr8" width="28px"/>
|
||||
<label className="color-grey-3">威佰通</label>
|
||||
</div>
|
||||
<a href="https://www.educoder.net/forums/3734" target="_blank" className="color-blue ml20">(简明手册)</a>
|
||||
</li>
|
||||
</ul>
|
||||
{
|
||||
lives && lives.length > 0 ?
|
||||
<React.Fragment>
|
||||
<p className="font-grey-9 mt20 mb20 pl10">共 <span className="color-orange">{liveData && liveData.total_count}</span> 个视频</p>
|
||||
<div className="liveContent">
|
||||
{
|
||||
lives.map((item,key)=>{
|
||||
return(
|
||||
<LiveItem
|
||||
key={key}
|
||||
item={item}
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
successFunc={()=>successFunc()}
|
||||
></LiveItem>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
{
|
||||
liveData && liveData.total_count > pageSize &&
|
||||
<div className="mt30 mb50 edu-txt-center">
|
||||
<Pagination showQuickJumper total={liveData.total_count} pageSize={pageSize} current={page} onChange={(page)=>changePage(page,'live')}></Pagination>
|
||||
</div>
|
||||
}
|
||||
</React.Fragment>
|
||||
:
|
||||
""
|
||||
// <div className="edu-back-white">
|
||||
// <NoneData style={{width: '100%'}}></NoneData>
|
||||
// </div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default Live;
|
||||
@@ -0,0 +1,177 @@
|
||||
import React,{ Component } from "react";
|
||||
import { getImageUrl } from 'educoder';
|
||||
import { Modal } from 'antd';
|
||||
import { WordsBtn } from 'educoder';
|
||||
|
||||
import axios from 'axios';
|
||||
// 点击按钮复制功能
|
||||
function jsCopy(props){
|
||||
var e = document.getElementById("copy_meet_content");
|
||||
e.select();
|
||||
document.execCommand("Copy");
|
||||
props.showNotification("复制成功!");
|
||||
}
|
||||
const $ = window.$;
|
||||
|
||||
function getRight(){
|
||||
var right = parseInt($(".-task-sidebar").css("right"));
|
||||
return right===0?0:right;
|
||||
}
|
||||
class LiveItem extends Component{
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
visible:false
|
||||
}
|
||||
}
|
||||
|
||||
deleteLive=(id)=>{
|
||||
this.props.confirm({
|
||||
content: '是否确认删除?',
|
||||
|
||||
onOk: () => {
|
||||
const url = `/live_links/${id}.json`;
|
||||
axios.delete(url).then(result=>{
|
||||
if(result){
|
||||
this.props.showNotification(`删除成功!`);
|
||||
const { successFunc } = this.props;
|
||||
successFunc && successFunc(1);
|
||||
}
|
||||
}).catch(error=>{
|
||||
console.log(error);
|
||||
})
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
alertInfo=()=>{
|
||||
this.setState({
|
||||
visible:true
|
||||
})
|
||||
getRight();
|
||||
}
|
||||
onDialogOkBtnClick=()=>{
|
||||
this.setState({
|
||||
visible:false,
|
||||
})
|
||||
}
|
||||
render(){
|
||||
const { key, item , setLiveId } = this.props;
|
||||
const { visible } = this.state;
|
||||
|
||||
const wei_flag = item.platform && (item.platform === "威佰通");
|
||||
console.log(wei_flag && item.url);
|
||||
return(
|
||||
<div className="liveItem" key={key}>
|
||||
<Modal
|
||||
title="提示"
|
||||
visible={visible}
|
||||
closable={false}
|
||||
footer={null}
|
||||
keyboard={false}
|
||||
centered={true}
|
||||
>
|
||||
{
|
||||
wei_flag && item.url ?
|
||||
<React.Fragment>
|
||||
<div className="task-popup-content edu-txt-center">
|
||||
<p className="font-16">打开威佰通客户端,输入会议号即可进入直播</p>
|
||||
<div className="wei_meet">
|
||||
<p className="wei_meet_info">
|
||||
<span>会议号:</span>
|
||||
<input value={item.url} className="showNumber" readOnly id="copy_meet_content"/>
|
||||
<a className="color-blue ml50" onClick={()=>jsCopy(this.props)}>复制会议号</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="task-popup-submit clearfix edu-txt-center">
|
||||
<a className="task-btn fl" onClick={this.onDialogOkBtnClick}>取消</a >
|
||||
<a className="task-btn task-btn-orange fr" onClick={this.onDialogOkBtnClick}>完成</a >
|
||||
</div>
|
||||
</React.Fragment>
|
||||
:
|
||||
<React.Fragment>
|
||||
<div className="task-popup-content">
|
||||
<p className="task-popup-text-center font-16 pb20">{wei_flag ? "当前直播无会议号":"直播链接失效"}</p >
|
||||
</div>
|
||||
<div className="task-popup-submit clearfix edu-txt-center">
|
||||
<a className="task-btn task-btn-orange mr51" onClick={this.onDialogOkBtnClick}>知道了</a >
|
||||
</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
</Modal>
|
||||
{
|
||||
visible ?
|
||||
<style>{
|
||||
`
|
||||
body{
|
||||
width: calc(100% - 7px)!important;
|
||||
overflow: hidden!important;
|
||||
}
|
||||
.-task-sidebar{
|
||||
right:${getRight()+7}px!important;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
:
|
||||
""
|
||||
}
|
||||
<div className="lineMiddle livesMain">
|
||||
<span className="lineMiddle">
|
||||
<span className="font-18 task-hide" style={{maxWidth:"759px"}}>{item.course_name}</span>
|
||||
<span className={item.on_status?"labels living":"labels lived"}>{item.on_status?'已开播':'未开播'}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="lineMiddle mt15">
|
||||
<div className="liveDesc">
|
||||
<p><span className="task-hide-2 break_word">{item.description}</span></p>
|
||||
</div>
|
||||
{
|
||||
item.on_status ?
|
||||
<React.Fragment>
|
||||
{
|
||||
item.url ?
|
||||
<React.Fragment>
|
||||
{
|
||||
wei_flag ?
|
||||
<a className="btns going" onClick={this.alertInfo}>进入</a>
|
||||
:
|
||||
<a className="btns going" target="_blank" href={`${item.url}`}>进入</a>
|
||||
}
|
||||
</React.Fragment>
|
||||
:
|
||||
<a className="btns going" onClick={this.alertInfo}>进入</a>
|
||||
}
|
||||
</React.Fragment>
|
||||
:
|
||||
<span className="btns ect">进入</span>
|
||||
}
|
||||
</div>
|
||||
<p className="lineMiddle livesMain mt15 font-12">
|
||||
<span className="lineMiddle color-grey-9">
|
||||
<img alt={`${item.author_name}`} className="liveAuthor" src={getImageUrl(`images/${item.author_img}`)}/>
|
||||
<label className="mr50">{item.author_name}</label>
|
||||
{ item.platform && <span className="mr50">直播平台:{item.platform}</span> }
|
||||
{ item.live_time && <span className="mr50">开播时间:{item.live_time}</span>}
|
||||
{ item.duration && <span className="mr50">直播预计时长:{item.duration}分钟</span> }
|
||||
</span>
|
||||
<span>
|
||||
{
|
||||
item.op_auth ?
|
||||
<WordsBtn style="grey" onClick={()=>setLiveId(item.id)}>编辑</WordsBtn>:""
|
||||
}
|
||||
{
|
||||
item.delete_auth ?
|
||||
<WordsBtn style="grey" className="ml30" onClick={()=>this.deleteLive(item.id)}>删除</WordsBtn>
|
||||
:""
|
||||
}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default LiveItem;
|
||||
@@ -0,0 +1,292 @@
|
||||
import React,{ Component } from "react";
|
||||
import { Modal , Form , Input , Spin , Select , AutoComplete , DatePicker , InputNumber } from 'antd';
|
||||
import locale from 'antd/lib/date-picker/locale/zh_CN';
|
||||
import moment from 'moment';
|
||||
import { handleDateString } from 'educoder';
|
||||
|
||||
import './video.css';
|
||||
import axios from 'axios';
|
||||
|
||||
const { TextArea } = Input;
|
||||
const { Option } = Select;
|
||||
const array=['腾讯课堂','B站','斗鱼','威佰通'];
|
||||
|
||||
function range(start, end) {
|
||||
const result = [];
|
||||
for (let i = start; i < end; i++) {
|
||||
result.push(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function disabledDateTime() {
|
||||
return {
|
||||
disabledMinutes: () => range(1, 30).concat(range(31, 60)),
|
||||
};
|
||||
}
|
||||
function disabledDate(current) {
|
||||
return current && current < moment().endOf('day').subtract(1, 'days');
|
||||
}
|
||||
|
||||
|
||||
class LiveNew extends Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
isSpining:false,
|
||||
beginTime:undefined,
|
||||
wei_flag:undefined
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount=()=>{
|
||||
this.checkType();
|
||||
}
|
||||
|
||||
componentDidUpdate=(prevState)=>{
|
||||
if(prevState && prevState.liveId !== this.props.liveId){
|
||||
this.setState({
|
||||
isSpining:true
|
||||
})
|
||||
this.checkType();
|
||||
}
|
||||
}
|
||||
|
||||
checkType=()=>{
|
||||
const { liveId } = this.props;
|
||||
this.clearAll();
|
||||
if(liveId){
|
||||
const url =`/live_links/${liveId}/edit.json`;
|
||||
axios.get(url).then(result=>{
|
||||
if(result){
|
||||
this.props.form.setFieldsValue({
|
||||
url:result.data.url,
|
||||
description:result.data.description,
|
||||
platform:result.data.platform || "腾讯课堂",
|
||||
duration:result.data.duration,
|
||||
course_name:result.data.course_name
|
||||
})
|
||||
this.setState({
|
||||
beginTime:result.data.live_time && moment(result.data.live_time,"YYYY-MM-DD HH:mm"),
|
||||
wei_flag:result.data.platform && result.data.platform === "威佰通"
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
this.setState({
|
||||
isSpining:false
|
||||
})
|
||||
}
|
||||
|
||||
handleSubmit=()=>{
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if(!err){
|
||||
this.setState({
|
||||
isSpining:true
|
||||
})
|
||||
const { liveId } = this.props;
|
||||
if(liveId){
|
||||
// 修改
|
||||
this.updateFunc(liveId,values);
|
||||
}else{
|
||||
this.creatFunc(values);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// 修改
|
||||
updateFunc=(id,values)=>{
|
||||
const url = `/live_links/${id}.json`;
|
||||
const { beginTime } = this.state;
|
||||
axios.put(url,{
|
||||
...values,
|
||||
live_time:beginTime
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
this.props.showNotification("修改成功!");
|
||||
const { setliveVisibel } = this.props;
|
||||
setliveVisibel && setliveVisibel(false,true);
|
||||
}
|
||||
this.setState({
|
||||
isSpining:false
|
||||
})
|
||||
}).catch(error=>{
|
||||
this.setState({
|
||||
isSpining:false
|
||||
})
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
// 新增
|
||||
creatFunc=(values)=>{
|
||||
const CourseId=this.props.match.params.coursesId;
|
||||
const url = `/courses/${CourseId}/live_links.json`;
|
||||
const { beginTime } = this.state;
|
||||
axios.post(url,{
|
||||
...values,
|
||||
live_time:beginTime
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
this.props.showNotification("添加成功!");
|
||||
const { setliveVisibel } = this.props;
|
||||
setliveVisibel && setliveVisibel(false,true);
|
||||
}
|
||||
this.setState({
|
||||
isSpining:false
|
||||
})
|
||||
}).catch(error=>{
|
||||
this.setState({
|
||||
isSpining:false
|
||||
})
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
validateDesc= (rule, value, callback) => {
|
||||
if(!value){
|
||||
callback();
|
||||
}
|
||||
if (value.length > 100) {
|
||||
callback("直播说明不能超过100个字!");
|
||||
}else{
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
cancelNew=()=>{
|
||||
const { setliveVisibel } = this.props;
|
||||
this.clearAll();
|
||||
setliveVisibel && setliveVisibel(false);
|
||||
}
|
||||
|
||||
clearAll=()=>{
|
||||
this.props.form.setFieldsValue({
|
||||
course_name:undefined,
|
||||
platform:"腾讯课堂",
|
||||
url:undefined,
|
||||
description:undefined,
|
||||
duration:undefined
|
||||
})
|
||||
this.setState({
|
||||
beginTime:undefined,
|
||||
wei_flag:false
|
||||
})
|
||||
}
|
||||
|
||||
onChangeTime=(data,dateString)=>{
|
||||
this.setState({
|
||||
beginTime:handleDateString(dateString)
|
||||
})
|
||||
}
|
||||
|
||||
ChangePlatform=(e)=>{
|
||||
if(e === "威佰通"){
|
||||
this.setState({
|
||||
wei_flag:true
|
||||
})
|
||||
}else{
|
||||
this.setState({
|
||||
wei_flag:false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
render(){
|
||||
const { isSpining , beginTime , wei_flag } = this.state;
|
||||
const {getFieldDecorator} = this.props.form;
|
||||
const { visible } = this.props;
|
||||
|
||||
const dataSource = array.map((item,key)=>{
|
||||
return(
|
||||
<Option value={item}>{item}</Option>
|
||||
)
|
||||
})
|
||||
return(
|
||||
<Modal
|
||||
visible={visible}
|
||||
width="560px"
|
||||
title={'添加直播'}
|
||||
footer={null}
|
||||
closable={false}
|
||||
className="liveModal"
|
||||
>
|
||||
<Spin spinning={isSpining}>
|
||||
<div className="task-popup-content">
|
||||
<Form onSubmit={this.handleSubmit}>
|
||||
<Form.Item label={`直播课程`}>
|
||||
{getFieldDecorator('course_name', {
|
||||
rules: [{required: true, message: "请输入课程名称"}],
|
||||
})(
|
||||
<Input placeholder="请输入课程名称" />
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label={`直播平台`}>
|
||||
{getFieldDecorator('platform', {
|
||||
rules: [{required: true, message: "请选择直播平台"}],
|
||||
})(
|
||||
<AutoComplete
|
||||
placeholder="请选择或输入直播平台名称"
|
||||
onChange={this.ChangePlatform}
|
||||
dataSource={dataSource}
|
||||
>
|
||||
</AutoComplete>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label={wei_flag?`会议号`:`直播链接`}>
|
||||
{getFieldDecorator('url', {
|
||||
rules: [],
|
||||
})(
|
||||
<Input placeholder={wei_flag?`请输入会议号`:"请输入第三方直播链接,如:腾讯课堂播放链接等。"} />
|
||||
)}
|
||||
</Form.Item>
|
||||
<div className="flex-bottom">
|
||||
<div className="flex1">
|
||||
<p className="ant-col ant-form-item-label color-grey-3 font-16 setStyle">开播时间</p>
|
||||
<DatePicker
|
||||
dropdownClassName="hideDisable"
|
||||
className="timeStyle mb20"
|
||||
placeholder="如:2020/02/02 12:00"
|
||||
style={{width:"220px"}}
|
||||
showTime={{ format: 'HH:mm' }}
|
||||
locale={locale}
|
||||
format="YYYY-MM-DD HH:mm"
|
||||
showToday={false}
|
||||
disabledTime={disabledDateTime}
|
||||
disabledDate={disabledDate}
|
||||
value={beginTime && moment(beginTime,"YYYY-MM-DD HH:mm")}
|
||||
onChange={this.onChangeTime}
|
||||
></DatePicker>
|
||||
</div>
|
||||
<Form.Item label={`直播预计时长`}>
|
||||
{getFieldDecorator('duration', {
|
||||
rules: [],
|
||||
})(
|
||||
<InputNumber placeholder="请输入直播时长" style={{width:"220px"}}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<span className="mb20 ml5">分钟</span>
|
||||
</div>
|
||||
<Form.Item label={`直播说明`}>
|
||||
{getFieldDecorator('description', {
|
||||
rules: [{
|
||||
validator: this.validateDesc,
|
||||
}],
|
||||
})(
|
||||
<TextArea rows={4} placeholder="可在此介绍开播具体事项,如开播时间安排等。" />
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
</Form>
|
||||
<div className="clearfix mt30 edu-txt-center">
|
||||
<a onClick={this.cancelNew} className="task-btn mr30">取消</a>
|
||||
<a type="submit" onClick={this.handleSubmit} className="task-btn task-btn-orange">确定</a>
|
||||
</div>
|
||||
</div>
|
||||
</Spin>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
}
|
||||
const WrappedLiveNew = Form.create({name: 'LiveNew'})(LiveNew);
|
||||
export default WrappedLiveNew;
|
||||
@@ -0,0 +1,254 @@
|
||||
import React,{ Component } from "react";
|
||||
import { Input , Pagination } from 'antd';
|
||||
import { NoneData ,ActionBtn } from 'educoder';
|
||||
|
||||
import VideoUploadList from '../../user/usersInfo/video/VideoUploadList';
|
||||
import VideoInReviewItem from '../../user/usersInfo/video/VideoInReviewItem';
|
||||
import HeadlessModal from '../../user/usersInfo/common/HeadlessModal';
|
||||
import EditVideoModal from '../../user/usersInfo/video/EditVideoModal'
|
||||
import ClipboardJS from 'clipboard'
|
||||
|
||||
import './video.css';
|
||||
import '../../user/usersInfo/video/InfosVideo.css'
|
||||
import axios from 'axios';
|
||||
|
||||
const DEFAULT_VIDEO_WIDTH_IN_MD = "90%" // 400
|
||||
const DEFAULT_VIDEO_HEIGHT_IN_MD = "55%" // 400
|
||||
|
||||
const videoEl = null;
|
||||
let _clipboard = null;
|
||||
|
||||
class Video extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
videos:undefined,
|
||||
count:0,
|
||||
page:1,
|
||||
|
||||
videoId:undefined,
|
||||
videoVisible:false,
|
||||
visible:false
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑的弹框visible
|
||||
setVisible=(flag)=>{
|
||||
this.setState({
|
||||
visible:flag
|
||||
})
|
||||
}
|
||||
|
||||
setVideoVisible=(flag)=>{
|
||||
|
||||
this.setState({
|
||||
videoVisible:flag
|
||||
})
|
||||
if (flag === false) {
|
||||
if (_clipboard) {
|
||||
this.setState({
|
||||
videoId:undefined
|
||||
})
|
||||
_clipboard.listener.destroy();
|
||||
_clipboard = null;
|
||||
}
|
||||
} else {
|
||||
// videoEl.current && videoEl.current.play()
|
||||
|
||||
setTimeout(() => {
|
||||
if (!_clipboard) {
|
||||
_clipboard = new ClipboardJS('.copybtn');
|
||||
_clipboard.on('success', (e) => {
|
||||
this.props.showNotification('复制成功');
|
||||
});
|
||||
}
|
||||
}, 200)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 编辑成功后回调的方法
|
||||
editSuccess=()=>{
|
||||
this.props.showNotification("视频名称修改成功!");
|
||||
const { listFunc , page } = this.props;
|
||||
listFunc && listFunc(page);
|
||||
}
|
||||
|
||||
onEditVideo=(item)=>{
|
||||
let videoId = {
|
||||
videoId: item.id,
|
||||
title: item.title
|
||||
}
|
||||
this.setState({
|
||||
videoId,
|
||||
})
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
onMaskClick=(item)=> {
|
||||
let videoId = {
|
||||
videoId: item.id,
|
||||
title: item.title,
|
||||
file_url: item.file_url,
|
||||
cover_url: item.cover_url
|
||||
}
|
||||
this.setState({
|
||||
videoId
|
||||
})
|
||||
this.setVideoVisible(true);
|
||||
}
|
||||
|
||||
|
||||
setVideoVisible=(flag)=>{
|
||||
|
||||
this.setState({
|
||||
videoVisible:flag
|
||||
})
|
||||
if (flag === false) {
|
||||
if (_clipboard) {
|
||||
this.setState({
|
||||
videoId:undefined
|
||||
})
|
||||
_clipboard.listener.destroy();
|
||||
_clipboard = null;
|
||||
}
|
||||
} else {
|
||||
// videoEl.current && videoEl.current.play()
|
||||
|
||||
setTimeout(() => {
|
||||
if (!_clipboard) {
|
||||
_clipboard = new ClipboardJS('.copybtn');
|
||||
_clipboard.on('success', (e) => {
|
||||
this.props.showNotification('复制成功');
|
||||
});
|
||||
}
|
||||
}, 200)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
getCopyText = (file_url, cover_url)=>{
|
||||
return `<video src="${file_url}" controls="true" controlslist="nodownload" width="${DEFAULT_VIDEO_WIDTH_IN_MD}" height="${DEFAULT_VIDEO_HEIGHT_IN_MD}" poster="${cover_url}">您的浏览器不支持 video 标签。</video>`
|
||||
}
|
||||
|
||||
// 删除事件
|
||||
deleteVideo=(item)=>{
|
||||
this.props.confirm({
|
||||
content: '该视频将被删除,不可恢复',
|
||||
subContent:'是否确认删除?',
|
||||
|
||||
onOk: () => {
|
||||
const CourseId=this.props.match.params.coursesId;
|
||||
const url = `/courses/${CourseId}/delete_course_video.json`;
|
||||
axios.delete(url,{
|
||||
params:{
|
||||
video_id:item.id
|
||||
}
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
this.props.showNotification(`删除成功!`);
|
||||
this.props.updataleftNavfun();
|
||||
const { listFunc , page } = this.props;
|
||||
listFunc && listFunc(page);
|
||||
}
|
||||
}).catch(error=>{
|
||||
console.log(error);
|
||||
})
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
const { visible , videoVisible , videoId } = this.state;
|
||||
const CourseId=this.props.match.params.coursesId;
|
||||
const login=this.props.user&&this.props.user.login;
|
||||
const _inputValue = videoId && this.getCopyText(videoId.file_url, videoId.cover_url);
|
||||
|
||||
const { admin , is_teacher ,business , user_id} = this.props.user;
|
||||
|
||||
const { videos , upload , uploadVideo , videoData , changePage ,pageSize ,page } = this.props;
|
||||
|
||||
const operation = admin || business || (is_teacher && this.props.checkIfProfessionalCertification())
|
||||
return(
|
||||
<div>
|
||||
<EditVideoModal {...this.props} visible={visible} setVisible={this.setVisible}
|
||||
editSuccess={this.editSuccess}
|
||||
{...videoId} CourseUser={login}
|
||||
></EditVideoModal>
|
||||
<HeadlessModal
|
||||
visible={videoVisible}
|
||||
setVisible={this.setVideoVisible}
|
||||
className="showVideoModal"
|
||||
width={800 - 1}
|
||||
>
|
||||
{
|
||||
videoId &&
|
||||
<video
|
||||
autoplay="true"
|
||||
ref={videoEl}
|
||||
src={videoId.file_url} controls="true" controlslist="nodownload">
|
||||
您的浏览器不支持 video 标签。
|
||||
</video>
|
||||
}
|
||||
|
||||
<div className="df copyLine">
|
||||
<Input value={_inputValue}
|
||||
className="dark"
|
||||
></Input>
|
||||
<ActionBtn className="copybtn" data-clipboard-text={_inputValue}>复制视频地址</ActionBtn>
|
||||
</div>
|
||||
</HeadlessModal>
|
||||
<div className="videoPanel">
|
||||
{
|
||||
upload ?
|
||||
<VideoUploadList {...this.props} flag={true} CourseId={CourseId} CourseUser={login} successFunc={()=>uploadVideo()}></VideoUploadList>
|
||||
:
|
||||
<React.Fragment>
|
||||
{
|
||||
videos && videos.length > 0 ?
|
||||
<React.Fragment>
|
||||
<p className="font-grey-9 mt20 mb20 pl5">共 <span className="color-orange">{videoData && videoData.count}</span> 个视频</p>
|
||||
<div className="videoContent">
|
||||
{
|
||||
videos.map((item,key)=>{
|
||||
return(
|
||||
<VideoInReviewItem
|
||||
{...this.props}
|
||||
|
||||
{...item}
|
||||
key={item.id}
|
||||
onEditVideo={this.onEditVideo}
|
||||
onMaskClick={this.onMaskClick}
|
||||
getCopyText={this.getCopyText}
|
||||
operation={operation}
|
||||
deleteVideo={(admin || item.user_id === user_id) ? this.deleteVideo : undefined}
|
||||
>
|
||||
</VideoInReviewItem>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</React.Fragment>
|
||||
:
|
||||
<div className="edu-back-white">
|
||||
<NoneData style={{width: '100%'}}></NoneData>
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
videoData && videoData.count > pageSize &&
|
||||
<div className="mt30 mb50 edu-txt-center">
|
||||
<Pagination showQuickJumper total={videoData.count} current={page} pageSize={pageSize} onChange={(page)=>changePage(page,'video')}></Pagination>
|
||||
</div>
|
||||
}
|
||||
</React.Fragment>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default Video;
|
||||
@@ -0,0 +1,297 @@
|
||||
import React,{ Component } from "react";
|
||||
|
||||
import { Menu, Spin } from 'antd';
|
||||
|
||||
import { WordsBtn } from 'educoder';
|
||||
import axios from 'axios';
|
||||
import Videos from './Video';
|
||||
import Lives from './Live';
|
||||
import LivesNew from './LiveNew';
|
||||
|
||||
|
||||
import './video.css';
|
||||
import '../css/Courses.css';
|
||||
import '../publicNav/nav.css';
|
||||
const PAGE_SIZE = 15;
|
||||
const LIVE_PAGE_SIZE = 10;
|
||||
const $ = window.$;
|
||||
|
||||
function getRight(){
|
||||
var right = parseInt($(".-task-sidebar").css("right"));
|
||||
return right===0?0:right;
|
||||
}
|
||||
class VideoIndex extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
page:1,
|
||||
upload:false,
|
||||
videos:undefined,
|
||||
videoData:undefined,
|
||||
type:"video",
|
||||
isSpining:false,
|
||||
|
||||
lives:undefined,
|
||||
liveData:undefined,
|
||||
|
||||
liveId:undefined,
|
||||
|
||||
liveVisible:false
|
||||
}
|
||||
}
|
||||
|
||||
checkType=(type,page)=>{
|
||||
this.setState({
|
||||
type,
|
||||
isSpining:true
|
||||
})
|
||||
if(type === "video"){
|
||||
this.getList(page);
|
||||
}else{
|
||||
this.getLiveList(page);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount=()=>{
|
||||
const { search } = this.props.location;
|
||||
const { page } = this.state;
|
||||
if(search && search === "?open=live"){
|
||||
this.setState({
|
||||
type:"live"
|
||||
})
|
||||
this.checkType("live",page);
|
||||
}else{
|
||||
if(search === "?open=new"){
|
||||
this.setState({
|
||||
upload:true
|
||||
})
|
||||
}
|
||||
this.checkType("video",page);
|
||||
}
|
||||
}
|
||||
// 获取直播列表
|
||||
getLiveList=(page)=>{
|
||||
const CourseId=this.props.match.params.coursesId;
|
||||
const url = `/courses/${CourseId}/live_links.json`;
|
||||
axios.get(url,{
|
||||
params:{
|
||||
page,
|
||||
limit:LIVE_PAGE_SIZE
|
||||
}
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
this.setState({
|
||||
liveData:result.data,
|
||||
lives:result.data.lives,
|
||||
isSpining:false,
|
||||
})
|
||||
}
|
||||
}).catch(error=>{
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
// 获取视频列表
|
||||
getList=(page)=>{
|
||||
const CourseId=this.props.match.params.coursesId;
|
||||
const fetchUrl = `/courses/${CourseId}/course_videos.json`;
|
||||
axios.get(fetchUrl, {
|
||||
params: {
|
||||
page,
|
||||
limit: PAGE_SIZE,
|
||||
}
|
||||
})
|
||||
.then((response) => {
|
||||
if(response){
|
||||
this.setState({
|
||||
videos:response.data.videos,
|
||||
videoData:response.data,
|
||||
isSpining:false
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
changeType=(e)=>{
|
||||
this.setState({
|
||||
type:e.key,
|
||||
upload:false,
|
||||
page:1
|
||||
})
|
||||
this.checkType(e.key,1);
|
||||
}
|
||||
|
||||
changePage=(page,type)=>{
|
||||
this.setState({
|
||||
page
|
||||
})
|
||||
this.checkType(type,page);
|
||||
}
|
||||
|
||||
onEditVideo=(item)=>{
|
||||
let videoId = {
|
||||
videoId: item.id,
|
||||
title: item.title
|
||||
}
|
||||
this.setState({
|
||||
videoId,
|
||||
})
|
||||
this.setVisible(true);
|
||||
}
|
||||
uploadVideo=(upload)=>{
|
||||
this.setState({
|
||||
upload,
|
||||
isSpining:true
|
||||
})
|
||||
const { page } = this.state;
|
||||
setTimeout(()=>{
|
||||
this.getList(page);
|
||||
},500)
|
||||
}
|
||||
|
||||
toUpload =()=> {
|
||||
const { admin , is_teacher,business} = this.props.user;
|
||||
if (admin || business || (is_teacher && this.props.checkIfProfessionalCertification())) {
|
||||
this.setState({
|
||||
type:"video",
|
||||
upload:true,
|
||||
page:1
|
||||
})
|
||||
} else {
|
||||
this.props.showProfessionalCertificationDialog();
|
||||
}
|
||||
}
|
||||
|
||||
// 直播设置后回调的方法
|
||||
// successFunc=()=>{
|
||||
// this.setState({
|
||||
// type:"live",
|
||||
// page:1
|
||||
// })
|
||||
// this.checkType("live",1);
|
||||
// }
|
||||
// 直播设置
|
||||
liveSetting=()=>{
|
||||
this.setState({
|
||||
liveId:undefined
|
||||
})
|
||||
this.setliveVisibel(true);
|
||||
}
|
||||
//直播设置弹框
|
||||
setliveVisibel=(flag,changetypeFlag)=>{
|
||||
this.setState({
|
||||
liveVisible:flag
|
||||
})
|
||||
if(flag === false){
|
||||
this.setState({
|
||||
liveId:undefined
|
||||
})
|
||||
}
|
||||
if(changetypeFlag){
|
||||
this.checkType("live",1);
|
||||
}
|
||||
}
|
||||
// 列表-编辑(修改传到编辑的id)
|
||||
setLiveId=(id)=>{
|
||||
this.setState({
|
||||
liveId:id
|
||||
})
|
||||
this.setliveVisibel(true);
|
||||
}
|
||||
render(){
|
||||
const { videos , upload , videoData , type , liveData , lives , page , liveVisible , isSpining , liveId } = this.state;
|
||||
const { admin , is_teacher , business } = this.props.user;
|
||||
// console.log("p",this.props);
|
||||
return(
|
||||
<React.Fragment>
|
||||
<LivesNew
|
||||
visible={liveVisible}
|
||||
liveId={liveId}
|
||||
setliveVisibel={this.setliveVisibel}
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
></LivesNew>
|
||||
{
|
||||
liveVisible ?
|
||||
<style>{
|
||||
`
|
||||
body{
|
||||
width: calc(100% - 7px)!important;
|
||||
overflow: hidden!important;
|
||||
}
|
||||
.-task-sidebar{
|
||||
right:${getRight()+7}px!important;
|
||||
}
|
||||
`}</style>:
|
||||
<style>{
|
||||
`
|
||||
body{
|
||||
width: 100%!important;
|
||||
}
|
||||
`}</style>
|
||||
}
|
||||
<div className="edu-back-white" style={{marginBottom:"1px"}}>
|
||||
|
||||
<div className="clearfix pl30 pr30 menuDiv">
|
||||
<div className="task_menu_ul fl">
|
||||
<Menu mode="horizontal" selectedKeys={[type]} onClick={this.changeType}>
|
||||
<Menu.Item key="video">视频</Menu.Item>
|
||||
<Menu.Item key="live">直播</Menu.Item>
|
||||
</Menu>
|
||||
</div>
|
||||
{
|
||||
(admin || is_teacher || business) &&
|
||||
<li className="fr mt18">
|
||||
{
|
||||
type === "video" ?
|
||||
<React.Fragment>
|
||||
{
|
||||
upload ?
|
||||
<WordsBtn style="grey" className="font-16" onClick={()=>this.uploadVideo(false)}>取消</WordsBtn>
|
||||
:
|
||||
<WordsBtn style="blue" className="font-16" onClick={this.toUpload}>上传视频</WordsBtn>
|
||||
}
|
||||
</React.Fragment>
|
||||
:
|
||||
<WordsBtn style="blue" className="font-16 ml30" onClick={this.liveSetting}>添加直播</WordsBtn>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<Spin spinning={isSpining}>
|
||||
{
|
||||
type === "video" ?
|
||||
<Videos
|
||||
upload={upload}
|
||||
videos={videos}
|
||||
page={page}
|
||||
data={videoData}
|
||||
pageSize={PAGE_SIZE}
|
||||
uploadVideo={this.uploadVideo}
|
||||
listFunc={this.getList}
|
||||
changePage={this.changePage}
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
></Videos>
|
||||
:
|
||||
<Lives
|
||||
lives={lives}
|
||||
liveData={liveData}
|
||||
page={page}
|
||||
pageSize={LIVE_PAGE_SIZE}
|
||||
successFunc={this.getLiveList}
|
||||
changePage={this.changePage}
|
||||
setLiveId={this.setLiveId}
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
></Lives>
|
||||
}
|
||||
</Spin>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default VideoIndex;
|
||||
@@ -0,0 +1,11 @@
|
||||
import React,{ Component } from "react";
|
||||
|
||||
|
||||
class VideoNew extends Component{
|
||||
render(){
|
||||
return(
|
||||
<div></div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default VideoNew;
|
||||
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 350 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,179 @@
|
||||
.videoContent{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.videoContent > div{
|
||||
width: 285px;
|
||||
margin-bottom: 20px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
margin-right: 30px;
|
||||
}
|
||||
.videoContent > div:nth-child(3n+0){
|
||||
margin-right: 0px!important;
|
||||
}
|
||||
.videoContent > div.videoItem:nth-child(4n+0){
|
||||
margin-right: 30px;
|
||||
}
|
||||
.videoItem:nth-child(4n+0) {
|
||||
margin-right: 30px;
|
||||
}
|
||||
.videoContent > div .cover{
|
||||
border-radius: 12px 12px 0px 0px;
|
||||
height: 158px;
|
||||
width: 100%;
|
||||
}
|
||||
.videoInfo{
|
||||
padding:15px;
|
||||
}
|
||||
.videoInfo .title{
|
||||
line-height: 24px;
|
||||
}
|
||||
.videoInfo .time{
|
||||
line-height: 15px;
|
||||
margin-bottom: 10px;
|
||||
color: #C0C4CC;
|
||||
font-size: 14px;
|
||||
}
|
||||
.flex-middle{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 25px;
|
||||
}
|
||||
.flex-bottom{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
}
|
||||
.square-main .buttonRow i {
|
||||
vertical-align: top;
|
||||
font-size: 16px;
|
||||
color: #4CACFF !important;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.leftMenu{
|
||||
float: left;
|
||||
border:none;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.liveItem{
|
||||
padding: 30px 30px 15px 30px;
|
||||
background: #fff;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.livesMain{
|
||||
justify-content: space-between;
|
||||
}
|
||||
.lineMiddle{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.liveAuthor{
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.labels{
|
||||
display: block;
|
||||
padding: 0px 16px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
font-size: 12px;
|
||||
margin-left: 20px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
.labels.living{
|
||||
border:1px solid #25C03B;
|
||||
color: #25C03B;
|
||||
}
|
||||
.labels.lived{
|
||||
border:1px solid #999999;
|
||||
color: #999999;
|
||||
}
|
||||
.btns
|
||||
{
|
||||
display: block;
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
padding: 0px 26px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.btns.going{
|
||||
background: #5091FF;
|
||||
color: #fff;
|
||||
}
|
||||
.btns.ect{
|
||||
background: #CCCCCC;
|
||||
color: #fff;
|
||||
}
|
||||
.liveDesc{
|
||||
flex:1;
|
||||
margin-right: 30px;
|
||||
text-overflow: -o-ellipsis-lastline;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
.timeStyle{
|
||||
transition: 0.5s;
|
||||
}
|
||||
.borderRed{
|
||||
border:1px solid #f5222d;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.setStyle{
|
||||
margin-bottom: 5px!important;
|
||||
}
|
||||
.switchStyle.ant-switch-checked{
|
||||
background-color: #25C03B;
|
||||
}
|
||||
.liveModal .ant-modal-body{
|
||||
padding:20px;
|
||||
}
|
||||
.liveModal .ant-modal-body .task-popup-content{
|
||||
padding:0px;
|
||||
}
|
||||
.liveModal .ant-row.ant-form-item{
|
||||
position: relative;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.liveModal .ant-form-explain{
|
||||
position: absolute;
|
||||
bottom: -18px;
|
||||
left: 0px;
|
||||
}
|
||||
.liveModal .ant-col.ant-form-item-label{
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
}
|
||||
.platform{
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding:20px 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.platform > li{
|
||||
margin-right: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.showNumber{
|
||||
border:none;
|
||||
}
|
||||
.wei_meet{
|
||||
display: flex;
|
||||
margin:20px auto;
|
||||
align-items: center;
|
||||
}
|
||||
.wei_meet_info{
|
||||
margin:0px auto;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
import React,{ Component } from "react";
|
||||
import {Tooltip, Modal, Input } from 'antd'
|
||||
import moment from 'moment'
|
||||
import { getUrl, WordsBtn } from 'educoder'
|
||||
import axios from 'axios'
|
||||
class AddDirModal extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state = {
|
||||
|
||||
}
|
||||
}
|
||||
onInput = (e) => {
|
||||
this.setState({
|
||||
inputValue: e.target.value
|
||||
})
|
||||
}
|
||||
open = () => {
|
||||
this.setState({ visible: true, inputValue: '' })
|
||||
}
|
||||
onSave = () => {
|
||||
let coursesId = this.props.match.params.coursesId;
|
||||
const url = `/courses/${coursesId}/boards.json`
|
||||
let { inputValue } = this.state;
|
||||
if (!inputValue) {
|
||||
this.setState({ errorMsg: '名称不能为空'})
|
||||
return;
|
||||
}
|
||||
if (inputValue.length > 20) {
|
||||
this.setState({ errorMsg: '名称不能超过20个字'})
|
||||
return;
|
||||
}
|
||||
this.setState({ errorMsg: ''})
|
||||
|
||||
axios.post(url,{
|
||||
name: inputValue
|
||||
}).then((response)=>{
|
||||
if (response.data.status == 0) {
|
||||
this.onCancel()
|
||||
this.props.showNotification('添加成功')
|
||||
this.props.addSuccess && this.props.addSuccess()
|
||||
}
|
||||
}).catch((error)=>{
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
onCancel = () => {
|
||||
this.setState({ visible: false, inputValue: '', errorMsg: '' })
|
||||
}
|
||||
render(){
|
||||
let { inputValue, visible, errorMsg } = this.state;
|
||||
const { title } = this.props;
|
||||
return(
|
||||
<Modal
|
||||
keyboard={false}
|
||||
title={title}
|
||||
visible={visible}
|
||||
className={"Navmodal"}
|
||||
closable={false}
|
||||
footer={null}
|
||||
destroyOnClose={true}
|
||||
centered={true}
|
||||
>
|
||||
<div className="df">
|
||||
<div className={"fl mt5"}>{this.props.label}:</div>
|
||||
<Input placeholder={this.props.inputPlaceholder || '示例:讨论小组A'}
|
||||
className={"input-flex-35 greyInput fl"}
|
||||
maxLength="60"
|
||||
value={inputValue}
|
||||
onInput={this.onInput}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{errorMsg && <span style={{color: 'red', marginTop: '2px', display: 'inline-block' }}>{errorMsg}</span>}
|
||||
|
||||
{/* {this.state.NavmodalValuetype===true?<span className={"color-red"}>
|
||||
{this.state.NavmodalValues}
|
||||
</span>:""} */}
|
||||
|
||||
{/* this.state.NavmodalValuetype===true?"clearfix mt20 edu-txt-center": */}
|
||||
<div className={"clearfix mt50 edu-txt-center"}>
|
||||
<a className="task-btn mr30" onClick={this.onCancel}>取消</a>
|
||||
<a className="task-btn task-btn-orange" onClick={this.onSave}>确定</a>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default AddDirModal;
|
||||
@@ -0,0 +1,146 @@
|
||||
import React,{ Component } from "react";
|
||||
import {Tooltip} from 'antd'
|
||||
import moment from 'moment'
|
||||
import { getUrl, WordsBtn, ConditionToolTip } from 'educoder'
|
||||
import './boardsListItem.css';
|
||||
class BoardsListItem extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state = {
|
||||
|
||||
}
|
||||
}
|
||||
onTitleClick = (discussMessage) => {
|
||||
if(this.props.checkIfLogin()===false){
|
||||
this.props.showLoginDialog()
|
||||
return
|
||||
}
|
||||
// if(this.props.checkIfProfileCompleted()===false){
|
||||
// this.setState({
|
||||
// AccountProfiletype:true
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
// if(this.props.checkIfProfessionalCertification()===false){
|
||||
// this.props.showProfileCompleteDialog()
|
||||
// return
|
||||
// }
|
||||
|
||||
const isAdminOrStudent = this.props.isAdminOrStudent();
|
||||
if (!isAdminOrStudent && discussMessage.is_public == false) {
|
||||
// 没有权限访问
|
||||
return;
|
||||
}
|
||||
const cid = this.props.match.params.coursesId
|
||||
const board_id = this.props.match.params.boardId
|
||||
this.props.toDetailPage(cid, board_id, discussMessage.id)
|
||||
}
|
||||
render(){
|
||||
let { addGroup } = this.state;
|
||||
const isAdmin = this.props.isAdmin()
|
||||
const isAdminOrStudent = this.props.isAdminOrStudent()
|
||||
const { checkBox, discussMessage, onSticky, onItemClick, current_user } = this.props;
|
||||
if (!discussMessage || !discussMessage.author) {
|
||||
return '';
|
||||
}
|
||||
let canNotLink = !isAdminOrStudent && discussMessage.is_public == false
|
||||
|
||||
return(
|
||||
<div className="panel-inner-fourm boardsList">
|
||||
<style>{`
|
||||
.boardsList .panel-list-img {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
`}</style>
|
||||
{ checkBox }
|
||||
<a href={`/users/${discussMessage.author.login}`} alt="用户" style={{"width":"50px","height":"50px","display":"block", margin: "0 10px"}}>
|
||||
{/* /images/avatars/User/1?1529221779 */}
|
||||
<img
|
||||
alt="1?1529221779" className="panel-list-img mr15" height="50"
|
||||
src={`${getUrl()}/images/${discussMessage.author.image_url}`} width="50"
|
||||
></img>
|
||||
</a>
|
||||
<div className="clearfix ds pr pt5 contentSection" onClick={() => onItemClick(discussMessage)}>
|
||||
<h6>
|
||||
{canNotLink?<span className="fl mt3 font-16 font-bd color-dark maxwidth580 pointer" title={canNotLink?"私有属性,非课堂成员不能访问":`${discussMessage.subject}`}>{discussMessage.subject}</span>:<a className="panel-list-title hide fl mt5 color-dark font-bd pointer"
|
||||
style={{ fontWeight: 'bold', maxWidth: '700px' }}
|
||||
title={discussMessage.subject}
|
||||
onClick={canNotLink ? () => {} : () => this.onTitleClick(discussMessage)}
|
||||
>{discussMessage.subject}</a>}
|
||||
{ !!discussMessage.sticky && <span className="btn-cir btn-cir-red fl mt5 ml5">置顶</span> }
|
||||
{
|
||||
|
||||
discussMessage.is_public == false ? (<Tooltip title={'私有属性,非课堂成员不能访问'} placement="bottom">
|
||||
<i className="iconfont icon-guansuo color-grey-c ml10 font-16 fl mt4"></i>
|
||||
</Tooltip>) : ""
|
||||
}
|
||||
|
||||
</h6>
|
||||
|
||||
<div className="fr">
|
||||
|
||||
{(isAdmin || discussMessage.author.login == current_user.login) &&
|
||||
<WordsBtn style="blue" className="fr font-16 ml28"
|
||||
onClick={(e) => { this.props.toEditPage(this.props.match.params.coursesId, this.props.match.params.boardId, discussMessage.id )} }>编辑</WordsBtn> }
|
||||
|
||||
{ isAdmin && <WordsBtn style="blue" className="fr font-16 ml28"
|
||||
onClick={(e) => { debugger; onSticky(discussMessage); e.cancelBubble = true; e.stopPropagation();}}>
|
||||
{ discussMessage.sticky ? '取消置顶' : '置顶' }</WordsBtn> }
|
||||
|
||||
{canNotLink?"":<WordsBtn style="blue" className="font-16 fr " onClick={canNotLink ? () => {} : () => this.onTitleClick(discussMessage)}>查看详情</WordsBtn>}
|
||||
|
||||
</div>
|
||||
|
||||
<div className="cl"></div>
|
||||
<p className="color-grey panel-lightgrey mt18 fl">
|
||||
<span className="mr50">
|
||||
<a href={`/users/${discussMessage.author.login}`} className="panel-name-small hide fl mr15 mr30 color-grey3 font-14">{discussMessage.author.name}</a>
|
||||
|
||||
{ discussMessage.total_replies_count != 0 && <span className="mr15 color-grey9 font-14">{discussMessage.total_replies_count} 回复</span> }
|
||||
{ discussMessage.praises_count != 0 && <span className="mr15 color-grey9 font-14">{discussMessage.praises_count} 点赞</span> }
|
||||
{ discussMessage.visits != 0 && <span className="mr15 color-grey9 font-14">{discussMessage.visits} 浏览</span> }
|
||||
|
||||
<span className="mr15 color-light-grey-C font-14">{moment(discussMessage.created_on).fromNow()} </span>
|
||||
</span>
|
||||
</p>
|
||||
{
|
||||
discussMessage.category_name &&
|
||||
<div className={'directory_style'}>
|
||||
<ConditionToolTip title={discussMessage.category_name} condition={discussMessage.category_name}>
|
||||
{ <div className=" color-grey9 task-hide fr"
|
||||
style={{"maxWidth":"216px"}}
|
||||
title={discussMessage.category_name}>
|
||||
所属目录:{discussMessage.category_name}
|
||||
</div>
|
||||
}
|
||||
</ConditionToolTip>
|
||||
</div>
|
||||
}
|
||||
|
||||
{/* { (isAdmin || discussMessage.author.login == current_user.login) &&
|
||||
<div className="homepagePostSetting" style={{"right":"4px","top":"5px","display":"block"}}>
|
||||
<ul>
|
||||
<li className="edu-position edu-position-hidebox">
|
||||
<i className="fa fa-bars color-grey-b"></i>
|
||||
<ul className="edu-position-hide undis">
|
||||
{(isAdmin || discussMessage.author.login == current_user.login) && <li><a href="javascript:void(0)" onClick={(e) => {
|
||||
this.props.toEditPage(this.props.match.params.coursesId, this.props.match.params.boardId, discussMessage.id )} } >编辑</a></li>
|
||||
}
|
||||
{isAdmin && <li><a href="javascript:void(0)" onClick={(e) => { debugger; onSticky(discussMessage); e.cancelBubble = true; e.stopPropagation();} }>
|
||||
{ discussMessage.sticky ? '取消置顶' : '置顶' }
|
||||
</a></li>
|
||||
}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
} */}
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default BoardsListItem;
|
||||
@@ -0,0 +1,497 @@
|
||||
import React,{ Component } from "react";
|
||||
|
||||
import {
|
||||
Form, Input, InputNumber, Switch, Radio,
|
||||
Slider, Button, Upload, Icon, Rate, Checkbox, message,
|
||||
Row, Col, Select, Modal, Divider,Tooltip
|
||||
} from 'antd';
|
||||
import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
|
||||
import axios from 'axios'
|
||||
import './board.css'
|
||||
import "../common/formCommon.css"
|
||||
import AddDirModal from './AddDirModal'
|
||||
import { RouteHOC } from './common.js'
|
||||
import CBreadcrumb from '../common/CBreadcrumb'
|
||||
import {getUploadActionUrl, bytesToSize, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll} from 'educoder';
|
||||
|
||||
const confirm = Modal.confirm;
|
||||
const $ = window.$
|
||||
const { Option } = Select;
|
||||
const MAX_TITLE_LENGTH = 60
|
||||
// https://lanhuapp.com/web/#/item/project/board/detail?pid=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&project_id=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&image_id=71072679-b925-4824-aceb-4649535e3652
|
||||
class BoardsNew extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.mdRef = React.createRef();
|
||||
|
||||
this.state = {
|
||||
fileList: [],
|
||||
boards: [],
|
||||
title_num: 0,
|
||||
email_notify:false,
|
||||
isemail_notify:false,
|
||||
isemail_notifys:false
|
||||
}
|
||||
}
|
||||
addSuccess = () => {
|
||||
this.fetchBoards()
|
||||
}
|
||||
fetchBoards = () => {
|
||||
const isEdit = this.isEdit
|
||||
const boardId = this.props.match.params.boardId
|
||||
|
||||
const boardsUrl = `/courses/board_list.json?board_id=${boardId}`
|
||||
axios.get(boardsUrl, { })
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.setState({
|
||||
boards: response.data.data.boards || [],
|
||||
boardsdata:response.data.data,
|
||||
course_id: response.data.data.course_id
|
||||
})
|
||||
if (!isEdit) {
|
||||
response.data.data.boards.forEach( board => {
|
||||
if (board.id == boardId) {
|
||||
this.setState({ board_name: board.name })
|
||||
}
|
||||
})
|
||||
// board_name
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
componentDidMount = () => {
|
||||
|
||||
const topicId = this.props.match.params.topicId
|
||||
const isEdit = !!topicId
|
||||
this.isEdit = isEdit
|
||||
|
||||
const boardId = this.props.match.params.boardId
|
||||
|
||||
this.fetchBoards()
|
||||
|
||||
if (isEdit) {
|
||||
const url = `/messages/${topicId}.json`
|
||||
axios.get(url, {
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
const { id, data } = response.data;
|
||||
if (data) {
|
||||
this.editTopic = data;
|
||||
this.props.form.setFieldsValue({
|
||||
sticky: !!data.sticky,
|
||||
content: data.content,
|
||||
subject: data.subject,
|
||||
select_board_id: data.board_id // TODO 没返回给前端
|
||||
});
|
||||
this.mdRef.current.setValue(data.content)
|
||||
const _fileList = data.attachments.map(item => {
|
||||
return {
|
||||
id: item.id,
|
||||
uid: item.id,
|
||||
name: appendFileSizeToUploadFile(item),
|
||||
url: item.url,
|
||||
status: 'done'
|
||||
}
|
||||
})
|
||||
|
||||
this.setState({ fileList: _fileList, board_name: data.board_name, title_num: parseInt(data.subject.length) ,isemail_notifys:response.data.data.email_notify})
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
} else {
|
||||
const boardId = this.props.match.params.boardId
|
||||
|
||||
this.props.form.setFieldsValue({
|
||||
select_board_id: parseInt(boardId)
|
||||
});
|
||||
}
|
||||
}
|
||||
handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
const cid = this.state.course_id
|
||||
const boardId = this.props.match.params.boardId
|
||||
|
||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
console.log('Received values of form: ', values);
|
||||
if (this.isEdit == true) {
|
||||
const editTopic = this.editTopic
|
||||
const editUrl = `/messages/${editTopic.id}.json`
|
||||
|
||||
let attachment_ids = undefined
|
||||
if (this.state.fileList) {
|
||||
attachment_ids = this.state.fileList.map(item => {
|
||||
return item.response ? item.response.id : item.id
|
||||
})
|
||||
}
|
||||
axios.put(editUrl, {
|
||||
subject: values.subject,
|
||||
select_board_id: values.select_board_id,
|
||||
content: values.content,
|
||||
sticky: values.sticky,
|
||||
email_notify:this.state.isemail_notify,
|
||||
attachment_ids,
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
const { id } = response.data;
|
||||
console.log('--- success')
|
||||
|
||||
this.props.toDetailPage(cid, values.select_board_id, editTopic.id)
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
} else {
|
||||
const url = `/boards/${boardId}/messages.json`
|
||||
let attachment_ids = undefined
|
||||
if (this.state.fileList) {
|
||||
attachment_ids = this.state.fileList.map(item => {
|
||||
return item.response.id
|
||||
})
|
||||
}
|
||||
|
||||
axios.post(url, {
|
||||
...values,
|
||||
email_notify:this.state.isemail_notify,
|
||||
course_id: cid,
|
||||
attachment_ids,
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.data && response.data.status == 0) {
|
||||
const { id } = response.data.data;
|
||||
if (id) {
|
||||
console.log('--- success')
|
||||
this.props.toDetailPage(cid, values.select_board_id, id)
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
$("html").animate({ scrollTop: $('html').scrollTop() - 100 })
|
||||
}
|
||||
});
|
||||
}
|
||||
// 附件相关 START
|
||||
handleChange = (info) => {
|
||||
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
|
||||
let fileList = info.fileList;
|
||||
this.setState({ fileList: appendFileSizeToUploadFileAll(fileList) });
|
||||
}
|
||||
}
|
||||
onAttachmentRemove = (file) => {
|
||||
if(!file.percent || file.percent == 100){
|
||||
this.props.confirm({
|
||||
// title: '确定要删除这个附件吗?',
|
||||
content: '是否确认删除?',
|
||||
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
// content: 'Some descriptions',
|
||||
onOk: () => {
|
||||
this.deleteAttachment(file)
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
deleteAttachment = (file) => {
|
||||
// 初次上传不能直接取uid
|
||||
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
|
||||
axios.delete(url, {
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data) {
|
||||
const { status } = response.data;
|
||||
if (status == 0) {
|
||||
console.log('--- success')
|
||||
|
||||
this.setState((state) => {
|
||||
const index = state.fileList.indexOf(file);
|
||||
const newFileList = state.fileList.slice();
|
||||
newFileList.splice(index, 1);
|
||||
return {
|
||||
fileList: newFileList,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
// 附件相关 ------------ END
|
||||
changeTitle=(e)=>{
|
||||
console.log(e.target.value.length);
|
||||
this.setState({
|
||||
title_num: parseInt(e.target.value.length)
|
||||
})
|
||||
}
|
||||
goBack = () => {
|
||||
// this.props.history.goBack()
|
||||
const courseId=this.props.match.params.coursesId;
|
||||
const boardId = this.props.match.params.boardId
|
||||
this.props.toListPage(courseId, boardId)
|
||||
}
|
||||
|
||||
setemailchange=(e)=>{
|
||||
this.setState({
|
||||
isemail_notify:e.target.checked
|
||||
})
|
||||
}
|
||||
render() {
|
||||
let { addGroup, fileList, course_id, title_num } = this.state;
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const { current_user } = this.props
|
||||
|
||||
const formItemLayout = {
|
||||
labelCol: {
|
||||
xs: { span: 24 },
|
||||
// sm: { span: 8 },
|
||||
sm: { span: 24 },
|
||||
},
|
||||
wrapperCol: {
|
||||
xs: { span: 24 },
|
||||
// sm: { span: 16 },
|
||||
sm: { span: 24 },
|
||||
},
|
||||
};
|
||||
|
||||
const uploadProps = {
|
||||
width: 600,
|
||||
fileList,
|
||||
multiple: true,
|
||||
// https://github.com/ant-design/ant-design/issues/15505
|
||||
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
|
||||
// showUploadList: false,
|
||||
action: `${getUploadActionUrl()}`,
|
||||
onChange: this.handleChange,
|
||||
onRemove: this.onAttachmentRemove,
|
||||
beforeUpload: (file) => {
|
||||
console.log('beforeUpload', file.name);
|
||||
const isLt150M = file.size / 1024 / 1024 < 150;
|
||||
if (!isLt150M) {
|
||||
this.props.showNotification('文件大小必须小于150MB!');
|
||||
}
|
||||
return isLt150M;
|
||||
},
|
||||
};
|
||||
const isAdmin = this.props.isAdmin()
|
||||
const courseId=this.props.match.params.coursesId;
|
||||
const boardId = this.props.match.params.boardId
|
||||
const isCourseEnd = this.props.isCourseEnd();
|
||||
document.title=this.props.coursedata&&this.props.coursedata.name;
|
||||
|
||||
// console.log(this.state)
|
||||
return(
|
||||
<div className="newMain ">
|
||||
<AddDirModal {...this.props}
|
||||
title="新建目录"
|
||||
label="目录名称"
|
||||
ref="addDirModal"
|
||||
addSuccess={this.addSuccess}
|
||||
></AddDirModal>
|
||||
<style>{`
|
||||
.courseForm .ant-form {
|
||||
}
|
||||
.courseForm .formBlock {
|
||||
padding: 20px 30px 30px 30px;
|
||||
border-bottom: 1px solid #EDEDED;
|
||||
margin-bottom: 0px;
|
||||
background: #fff;
|
||||
}
|
||||
.courseForm .noBorder {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
`}</style>
|
||||
<div className="edu-class-container edu-position courseForm">
|
||||
<CBreadcrumb items={[
|
||||
{ to: current_user&¤t_user.first_category_url, name: this.props.coursedata ? this.props.coursedata.name : ''},
|
||||
{ to: `/courses/${courseId}/boards/${boardId}`, name: this.state.board_name },
|
||||
{ name: this.isEdit ? '帖子编辑' : '帖子新建'}
|
||||
]}></CBreadcrumb>
|
||||
|
||||
<p className="clearfix mt20 mb20">
|
||||
<span className="fl font-24 color-grey-3">{this.isEdit ? "编辑" : "新建"}帖子</span>
|
||||
<a href="javascript:void(0)" className="color-grey-6 fr font-16 mr2"
|
||||
onClick={this.goBack}>
|
||||
返回
|
||||
</a>
|
||||
</p>
|
||||
{/* notRequired */}
|
||||
<Form {...formItemLayout} onSubmit={this.handleSubmit}>
|
||||
<div className="formBlock" style={{paddingBottom: '0px', position: 'relative'}}>
|
||||
{this.state.boardsdata&&this.state.boardsdata.email_notify===true?this.props.isAdminOrTeacher()===true?<Tooltip placement="bottom" title={this.state.isemail_notifys===true?"邮件只能发送一次":""}><span className={"setemail fr mr70 setemailposition"}>
|
||||
<Checkbox onChange={this.setemailchange} checked={this.state.isemail_notifys===true?this.state.isemail_notifys:this.state.isemail_notify} disabled={this.state.isemail_notifys}>发送邮件提醒</Checkbox>
|
||||
</span></Tooltip>:"":""}
|
||||
|
||||
{ isAdmin &&
|
||||
<React.Fragment>
|
||||
{getFieldDecorator('sticky', {
|
||||
valuePropName: 'checked',
|
||||
})(
|
||||
isAdmin && <Checkbox style={{ right: '22px',
|
||||
top: '17px',
|
||||
position: 'absolute'
|
||||
}}>置顶</Checkbox>
|
||||
)}
|
||||
{/* checkbox 有个边距样式 .ant-checkbox-wrapper + span, */}
|
||||
<span style={{ "padding-left": 0, "padding-right": 0 }}></span>
|
||||
</React.Fragment>
|
||||
}
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.yslboardsnewinputaddonAfter .ant-input{
|
||||
border-right: none !important;
|
||||
height: 40px !important;
|
||||
}
|
||||
|
||||
`
|
||||
}
|
||||
</style>
|
||||
<Form.Item
|
||||
label="标题"
|
||||
className="topicTitle "
|
||||
>
|
||||
|
||||
{getFieldDecorator('subject', {
|
||||
rules: [{
|
||||
required: true, message: '请输入标题',
|
||||
}, {
|
||||
max: MAX_TITLE_LENGTH, message: `最大限制为${MAX_TITLE_LENGTH}个字符`,
|
||||
}],
|
||||
})(
|
||||
<Input placeholder={`请输入帖子标题,最大限制${MAX_TITLE_LENGTH}个字符 `}className="searchViewAfter yslboardsnewinputaddonAfter" maxLength={MAX_TITLE_LENGTH}
|
||||
onInput={this.changeTitle} addonAfter={`${title_num}/${MAX_TITLE_LENGTH}`} />
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label=""
|
||||
style={{ display: 'inline-block' }}
|
||||
>
|
||||
{getFieldDecorator('select_board_id', {
|
||||
// initialValue: '3779',
|
||||
})(
|
||||
<Select style={{ width: 230 }}
|
||||
dropdownRender={menu => (
|
||||
<div>
|
||||
{menu}
|
||||
{
|
||||
isAdmin && !isCourseEnd &&
|
||||
<React.Fragment>
|
||||
<Divider style={{ margin: '4px 0' }} />
|
||||
<div style={{ padding: '8px', cursor: 'pointer' }} onMouseDown={() => this.refs['addDirModal'].open()}>
|
||||
<Icon type="plus" /> 新建目录
|
||||
</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
{this.state.boards.map(item => {
|
||||
return (
|
||||
<Option value={item.id}>{item.name}</Option>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
|
||||
|
||||
{/* { isAdmin && <Form.Item
|
||||
label=""
|
||||
style={{ display: 'inline-block', marginLeft: "14px" }}
|
||||
>
|
||||
{getFieldDecorator('sticky', {
|
||||
})(
|
||||
<Checkbox>置顶</Checkbox>
|
||||
)}
|
||||
</Form.Item> } */}
|
||||
</div>
|
||||
|
||||
<style>{`
|
||||
.courseMessageMD {
|
||||
width: 1140px;
|
||||
}
|
||||
|
||||
.uploadBtn.ant-btn {
|
||||
border: none;
|
||||
color: #4CACFF;
|
||||
box-shadow: none;
|
||||
background: transparent;
|
||||
padding: 0 6px;
|
||||
}
|
||||
.upload_1 .ant-upload-list {
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
`}</style>
|
||||
|
||||
<div className="formBlock noBorder">
|
||||
|
||||
<Form.Item
|
||||
label="内容"
|
||||
className="mdInForm"
|
||||
>
|
||||
{getFieldDecorator('content', {
|
||||
rules: [{
|
||||
required: true, message: '请输入帖子内容',
|
||||
}, {
|
||||
max: 10000, message: '最大限制为10000个字符',
|
||||
}],
|
||||
})(
|
||||
<TPMMDEditor ref={this.mdRef} placeholder={'请在此输入帖子详情,最大限制为10000个字符'}
|
||||
mdID={'courseMessageMD'} initValue={this.editTopic ? this.editTopic.content : ''} className="courseMessageMD"></TPMMDEditor>
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
<Upload {...uploadProps} className="upload_1">
|
||||
<Button className="uploadBtn">
|
||||
<Icon type="upload" /> 上传附件
|
||||
</Button>
|
||||
(单个文件150M以内)
|
||||
</Upload>
|
||||
</div>
|
||||
|
||||
<Form.Item>
|
||||
<div className="clearfix mt30 mb30">
|
||||
<Button type="primary" htmlType="submit" className="defalutSubmitbtn fl mr20">提交</Button>
|
||||
<a className="defalutCancelbtn fl"
|
||||
onClick={() => this.isEdit ?
|
||||
this.props.toDetailPage(Object.assign({}, this.props.match.params, {'coursesId': course_id})) :
|
||||
this.props.toListPage(Object.assign({}, this.props.match.params, {'coursesId': course_id})) }>取消</ a>
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const WrappedBoardsNew = Form.create({ name: 'boardsNew' })(BoardsNew);
|
||||
export default RouteHOC()(WrappedBoardsNew);
|
||||
@@ -0,0 +1,202 @@
|
||||
import React,{ Component } from "react";
|
||||
|
||||
import {
|
||||
Form, Input, InputNumber, Switch, Radio,
|
||||
Slider, Button, Upload, Icon, Rate, Checkbox,
|
||||
Row, Col, Select
|
||||
} from 'antd';
|
||||
const $ = window.$
|
||||
const { Option } = Select;
|
||||
|
||||
// 红点在输入框前面的版本
|
||||
// https://lanhuapp.com/web/#/item/project/board/detail?pid=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&project_id=a3bcd4b1-99ce-4e43-8ead-5b8b0a410807&image_id=71072679-b925-4824-aceb-4649535e3652
|
||||
class BoardsNew extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state = {
|
||||
|
||||
}
|
||||
}
|
||||
compareToFirstPassword = (rule, value, callback) => {
|
||||
const form = this.props.form;
|
||||
if (value && value !== form.getFieldValue('password')) {
|
||||
callback('Two passwords that you enter is inconsistent!');
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
validateToNextPassword = (rule, value, callback) => {
|
||||
const form = this.props.form;
|
||||
if (value && this.state.confirmDirty) {
|
||||
form.validateFields(['confirm'], { force: true });
|
||||
}
|
||||
callback();
|
||||
}
|
||||
handleConfirmBlur = (e) => {
|
||||
const value = e.target.value;
|
||||
this.setState({ confirmDirty: this.state.confirmDirty || !!value });
|
||||
}
|
||||
handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
console.log('Received values of form: ', values);
|
||||
} else {
|
||||
$("html").animate({ scrollTop: $('html').scrollTop() - 100 })
|
||||
}
|
||||
});
|
||||
}
|
||||
render() {
|
||||
let { addGroup } = this.state;
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
|
||||
const formItemLayout = {
|
||||
labelCol: {
|
||||
xs: { span: 24 },
|
||||
// sm: { span: 8 },
|
||||
sm: { span: 24 },
|
||||
},
|
||||
wrapperCol: {
|
||||
xs: { span: 24 },
|
||||
// sm: { span: 16 },
|
||||
sm: { span: 24 },
|
||||
},
|
||||
};
|
||||
|
||||
const tailFormItemLayout = {
|
||||
wrapperCol: {
|
||||
xs: {
|
||||
span: 24,
|
||||
offset: 0,
|
||||
},
|
||||
sm: {
|
||||
span: 16,
|
||||
offset: 8,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
return(
|
||||
<div className="newMain ">
|
||||
<style>{`
|
||||
.edu-class-container {
|
||||
width: 1200px;
|
||||
margin: 10px auto 20px;
|
||||
}
|
||||
|
||||
/* form 样式 --------------------------------------------- */
|
||||
/* 不知道被哪个样式影响,这里需要重置 */
|
||||
.ant-input:focus {
|
||||
border-color: #40a9ff;
|
||||
}
|
||||
@media (min-width: 576px) {
|
||||
.ant-col-sm-24 {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
.ant-form-item-control-wrapper.ant-col-xs-24.ant-col-sm-24 {
|
||||
margin-left: 2px;
|
||||
}
|
||||
/*必填*/
|
||||
.ant-form-item-required::before {
|
||||
display: none;
|
||||
}
|
||||
.ant-form-item-control-wrapper.ant-col-xs-24.ant-col-sm-24::before {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
color: #f5222d;
|
||||
font-size: 14px;
|
||||
font-family: SimSun, sans-serif;
|
||||
line-height: 1;
|
||||
content: '*';
|
||||
}
|
||||
.ant-form-item-control {
|
||||
display: inline-block;
|
||||
}
|
||||
/* form 样式 --------------------------------------------- */
|
||||
|
||||
|
||||
.topicTitle.ant-form-item {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* errorInline ----------- */
|
||||
/* 这里需要指定form组件的宽度 style={{ width: 270 }} */
|
||||
.errorInline .ant-form-item-children input {
|
||||
width: auto
|
||||
}
|
||||
.errorInline .ant-form-explain {
|
||||
display: inline;
|
||||
margin-left: 10px;
|
||||
}
|
||||
/* errorInline ----------- */
|
||||
`}</style>
|
||||
<div className="edu-class-container edu-position">
|
||||
<Form {...formItemLayout} onSubmit={this.handleSubmit}>
|
||||
<Form.Item
|
||||
label="E-mail"
|
||||
className="topicTitle errorInline"
|
||||
>
|
||||
{getFieldDecorator('email', {
|
||||
rules: [{
|
||||
type: 'email', message: 'The input is not valid E-mail!',
|
||||
}, {
|
||||
required: true, message: 'Please input your E-mail!',
|
||||
}],
|
||||
})(
|
||||
<Input style={{ width: 270 }} />
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label=""
|
||||
>
|
||||
{getFieldDecorator('prefix', {
|
||||
initialValue: '86',
|
||||
})(
|
||||
<Select style={{ width: 270 }}>
|
||||
<Option value="86">+86</Option>
|
||||
<Option value="87">+87</Option>
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Password"
|
||||
>
|
||||
{getFieldDecorator('password', {
|
||||
rules: [{
|
||||
required: true, message: 'Please input your password!',
|
||||
}, {
|
||||
validator: this.validateToNextPassword,
|
||||
}],
|
||||
})(
|
||||
<Input type="password" />
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="Confirm Password"
|
||||
>
|
||||
{getFieldDecorator('confirm', {
|
||||
rules: [{
|
||||
required: true, message: 'Please confirm your password!',
|
||||
}, {
|
||||
validator: this.compareToFirstPassword,
|
||||
}],
|
||||
})(
|
||||
<Input type="password" onBlur={this.handleConfirmBlur} />
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item {...tailFormItemLayout}>
|
||||
<Button type="primary" htmlType="submit">Register</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
const WrappedBoardsNew = Form.create({ name: 'boardsNew' })(BoardsNew);
|
||||
export default WrappedBoardsNew;
|
||||
@@ -0,0 +1,15 @@
|
||||
.edu-class-container {
|
||||
width: 1200px;
|
||||
margin: 10px auto 20px;
|
||||
}
|
||||
#forum_index_list {
|
||||
margin-top: 90px;
|
||||
margin-bottom: 320px;
|
||||
}
|
||||
#yslforum_index_list {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 320px;
|
||||
}
|
||||
.uploadBtn {
|
||||
margin-left: 0px;
|
||||
}
|
||||
@@ -0,0 +1,748 @@
|
||||
import React, { Component } from 'react';
|
||||
import axios from 'axios'
|
||||
import moment from 'moment'
|
||||
import Comments from '../../comment/Comments'
|
||||
import {ImageLayerOfCommentHOC} from '../../page/layers/ImageLayerOfCommentHOC'
|
||||
import MemoDetailMDEditor from '../../forums/MemoDetailMDEditor'
|
||||
import { RouteHOC } from './common.js'
|
||||
import '../../forums/Post.css'
|
||||
import '../../forums/RightSection.css'
|
||||
import './TopicDetail.css'
|
||||
import '../common/courseMessage.css'
|
||||
import { Pagination, Tooltip,Button } from 'antd'
|
||||
import { bytesToSize, ConditionToolTip, markdownToHTML, MarkdownToHtml , setImagesUrl } from 'educoder'
|
||||
import SendToCourseModal from '../coursesPublic/modal/SendToCourseModal'
|
||||
import CBreadcrumb from '../common/CBreadcrumb'
|
||||
import { generateComments, generateChildComments, _findById, handleContentBeforeCreateNew, addNewComment
|
||||
, addSecondLevelComment, NEED_TO_WRITE_CONTENT, handleContentBeforeCreateSecondLevelComment
|
||||
, handleDeleteComment, handleCommentPraise, handleHiddenComment } from '../common/CommentsHelper'
|
||||
|
||||
const $ = window.$
|
||||
const REPLY_PAGE_COUNT = 10;
|
||||
let setTime;
|
||||
function urlStringify(params) {
|
||||
let noParams = true;
|
||||
let paramsUrl = '';
|
||||
for (let key in params) {
|
||||
noParams = false;
|
||||
paramsUrl += `${key}=${params[key]}&`
|
||||
}
|
||||
if (noParams) {
|
||||
return '';
|
||||
}
|
||||
paramsUrl = paramsUrl.substring(0, paramsUrl.length - 1);
|
||||
return paramsUrl;
|
||||
}
|
||||
class TopicDetail extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
memo: {},
|
||||
memoLoading: true,
|
||||
hasMoreComments: false,
|
||||
pageCount: 1,
|
||||
comments: [],
|
||||
goldRewardDialogOpen: false,
|
||||
author:undefined,
|
||||
commentstype:false
|
||||
}
|
||||
}
|
||||
componentDidMount() {
|
||||
window.$("html,body").animate({"scrollTop":0})
|
||||
|
||||
const topicId = this.props.match.params.topicId
|
||||
const bid = this.props.match.params.boardId
|
||||
|
||||
const memoUrl = `/messages/${topicId}.json`;
|
||||
this.setState({
|
||||
memoLoading: true
|
||||
})
|
||||
axios.get(memoUrl,{
|
||||
})
|
||||
.then((response) => {
|
||||
|
||||
if (response.data.status === -1) {
|
||||
setTimeout(() => {
|
||||
this.props.showNotification('帖子不存在!')
|
||||
}, 300)
|
||||
// this.props.toListPage(response.data.data.course_id, bid)
|
||||
return;
|
||||
} else {
|
||||
|
||||
this.setState({
|
||||
memo: Object.assign({}, {
|
||||
...response.data.data,
|
||||
replies_count: response.data.data.total_replies_count
|
||||
}, {...this.state.memo}),
|
||||
author:response.data.data.author
|
||||
}, () => {
|
||||
})
|
||||
|
||||
// const { memo_replies, memo } = response.data;
|
||||
// let hasMoreComments = false;
|
||||
// if (memo_replies && memo_replies.length === 10 && memo.total_replies_count > 10) {
|
||||
// // 遍历一遍,计算下是否还有评论未加载
|
||||
// let totalCount = 10;
|
||||
// memo_replies.forEach(item=>{
|
||||
// totalCount += item.children.length
|
||||
// })
|
||||
// if (totalCount < memo.total_replies_count) {
|
||||
// hasMoreComments = true;
|
||||
// }
|
||||
// }
|
||||
// this.setState({
|
||||
// hasMoreComments,
|
||||
// pageCount: 1,
|
||||
// comments: memo_replies
|
||||
// })
|
||||
// delete response.data.memo_replies;
|
||||
// this.setState(response.data)
|
||||
// const user = response.data.current_user;
|
||||
// user.tidding_count = response.data.tidding_count;
|
||||
// this.props.initCommonState(user)
|
||||
}
|
||||
this.setState({
|
||||
memoLoading: false
|
||||
})
|
||||
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
this.fetchReplies()
|
||||
|
||||
$('body>#root').on('onMemoDelete', (event) => {
|
||||
// const val = $('body>#root').data('onMemoDelete')
|
||||
const val = window.onMemoDelete ;
|
||||
this.onMemoDelete( JSON.parse(decodeURIComponent(val)) )
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
onPaginationChange = (pageCount) => {
|
||||
this.setState({ pageCount }, () => {
|
||||
this.fetchReplies()
|
||||
})
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
$('body>#root').off('onMemoDelete')
|
||||
}
|
||||
onMemoDelete(memo) {
|
||||
const deleteUrl = `/commons/delete.json`;
|
||||
// 获取memo list
|
||||
axios.delete(deleteUrl, { data: {
|
||||
object_id: memo.id,
|
||||
object_type: 'message'
|
||||
}
|
||||
})
|
||||
.then((response) => {
|
||||
const status = response.data.status
|
||||
if (status === 0) {
|
||||
|
||||
this.props.showNotification('删除成功');
|
||||
const props = Object.assign({}, this.props, {})
|
||||
this.props.toListPage( Object.assign({}, this.props.match.params, {'coursesId': this.state.memo.course_id} ) )
|
||||
|
||||
} else if (status === -1) {
|
||||
this.props.showNotification('帖子已被删除');
|
||||
this.props.history.push(`/forums`)
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
// if (this.state.memo && this.state.memo.content
|
||||
// && (!prevProps.memo || prevProps.memo.content != this.state.memo.content) ) {
|
||||
if (this.state.memo && this.state.memo.content && prevState.memoLoading === true && this.state.memoLoading === false) {
|
||||
// md渲染content,等xhr执行完(即memoLoading变化),memo.content更新后初始化md
|
||||
|
||||
setTimeout(()=>{
|
||||
// var shixunDescr = window.editormd.markdownToHTML("memo_content_editorMd", {
|
||||
// htmlDecode: "style,script,iframe", // you can filter tags decode
|
||||
// taskList: true,
|
||||
// tex: true, // 默认不解析
|
||||
// flowChart: true, // 默认不解析
|
||||
// sequenceDiagram: true // 默认不解析
|
||||
// });
|
||||
}, 200)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
clickPraise(){
|
||||
const { memo } = this.state;
|
||||
// const url = `/api/v1/discusses/${memo.id}/plus`;
|
||||
const url = memo.user_praise ? '/praise_tread/unlike.json' : `/praise_tread/like.json`;
|
||||
const _method = memo.user_praise ? axios.delete : axios.post
|
||||
let _data = {
|
||||
object_id: memo.id,
|
||||
object_type: 'message', //Discuss
|
||||
}
|
||||
if (memo.user_praise) {
|
||||
_data = {
|
||||
data: _data
|
||||
}
|
||||
}
|
||||
_method(url, {
|
||||
..._data
|
||||
},
|
||||
{
|
||||
|
||||
}
|
||||
).then((response) => {
|
||||
|
||||
const newMemo = Object.assign({}, this.state.memo)
|
||||
newMemo.praises_count = newMemo.user_praise ? newMemo.praises_count - 1 : newMemo.praises_count + 1
|
||||
newMemo.total_praises_count = newMemo.user_praise ? newMemo.total_praises_count - 1 : newMemo.total_praises_count + 1
|
||||
newMemo.user_praise = !newMemo.user_praise
|
||||
this.setState({memo : newMemo })
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
renderAttachment() {
|
||||
const { memo } = this.state;
|
||||
const attachments = []
|
||||
memo.attachments.forEach((item, index) => {
|
||||
const ar = item.url.split('/')
|
||||
const fileName = item.title || ar[ar.length - 1]
|
||||
let filesize = 0
|
||||
if (item.filesize) {
|
||||
filesize = item.filesize
|
||||
// filesize = bytesToSize(item.filesize)
|
||||
}
|
||||
attachments.push(
|
||||
// <p className="clearfix" key={index} >
|
||||
// <a href={item.url} className="color-green clearfix notefileDownload">
|
||||
// <i className="iconfont icon-fujian color-green ml5 fl"></i>
|
||||
// {fileName && <ConditionToolTip title={fileName} condition={fileName.length > 30 }>
|
||||
// <span className="fl task-hide upload_item" style={{ color: '#333'}}>{fileName}</span>
|
||||
// </ConditionToolTip>}
|
||||
// <span className="fl" style={{ color: '#999', marginLeft: '6px'}}>{filesize? ` ${filesize.replace(' ', '')}` : ''}</span>
|
||||
// </a>
|
||||
// </p>
|
||||
|
||||
<div className="color-grey df" key={index}>
|
||||
<a className="color-grey ">
|
||||
<i className="font-14 color-green iconfont icon-fujian mr8" aria-hidden="true"></i>
|
||||
</a>
|
||||
{/* {fileName && <ConditionToolTip title={fileName} condition={fileName.length > 30 }> </ConditionToolTip>} */}
|
||||
<a href={item.url} title={fileName.length > 30 ? fileName : ''}
|
||||
className="mr12 color9B9B overflowHidden1" length="58" style={{maxWidth: '480px'}}>
|
||||
{fileName}
|
||||
</a>
|
||||
|
||||
|
||||
<span className="color656565 mt2 color-grey-6 font-12 mr8">{item.filesize}</span>
|
||||
|
||||
</div>
|
||||
)
|
||||
})
|
||||
return attachments;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------- comments START
|
||||
// ------------------------------------------------------------------------------------------- comments START
|
||||
transformReply = (reply, children = []) => {
|
||||
const isAdmin = this.props.isAdmin()
|
||||
const isSuperAdmin = this.props.isSuperAdmin()
|
||||
return {
|
||||
isSuperAdmin: isSuperAdmin,
|
||||
admin: isAdmin, //
|
||||
permission: true, //
|
||||
children: children,
|
||||
child_message_count: reply.total_count,
|
||||
hidden: reply.is_hidden,
|
||||
id: reply.id,
|
||||
image_url: reply.author.image_url,
|
||||
reward: null, //
|
||||
time: moment(reply.created_on).fromNow(),
|
||||
user_id: reply.author.id,
|
||||
user_login: reply.author.login,
|
||||
user_praise: reply.liked,
|
||||
username: reply.author.name,
|
||||
content: reply.content,
|
||||
praise_count: reply.praises_count
|
||||
}
|
||||
}
|
||||
|
||||
fetchReplies = () => {
|
||||
const topicId = this.props.match.params.topicId
|
||||
const url = `/messages/${topicId}/reply_list.json?page=${this.state.pageCount}&page_size=${REPLY_PAGE_COUNT}`
|
||||
axios.get(url,{
|
||||
})
|
||||
.then((response) => {
|
||||
const { replies, liked, total_replies_count, total_count } = response.data.data
|
||||
|
||||
const memo = Object.assign({}, this.state.memo)
|
||||
memo.user_praise = liked
|
||||
memo.total_replies_count = total_replies_count;
|
||||
this.setState({
|
||||
memo,
|
||||
comments: generateComments(replies, this.transformReply, 'replies'),
|
||||
// : this.state.comments.concat(comments),
|
||||
total_count: total_count
|
||||
})
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
_getUser() {
|
||||
const { current_user } = this.props;
|
||||
current_user.user_url = `/users/${current_user.login}`;
|
||||
return current_user;
|
||||
}
|
||||
_findById = _findById
|
||||
replyComment = (commentContent, id, editor) => {
|
||||
const { showNotification } = this.props;
|
||||
// if (!commentContent || commentContent.length === 0) {
|
||||
// showNotification(NEED_TO_WRITE_CONTENT)
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (this.state.memo.id === id ) { // 回复帖子
|
||||
this.createNewComment(commentContent, id, editor);
|
||||
return;
|
||||
}
|
||||
const url = `/messages/${id}/reply.json`;
|
||||
|
||||
const { comments } = this.state;
|
||||
const user = this._getUser();
|
||||
/*
|
||||
移除末尾的空行
|
||||
.replace(/(\n<p>\n\t<br \/>\n<\/p>)*$/g,'');
|
||||
|
||||
*/
|
||||
|
||||
commentContent = handleContentBeforeCreateSecondLevelComment(commentContent)
|
||||
if (!commentContent) {
|
||||
this.props.showNotification('不能为空')
|
||||
return;
|
||||
}
|
||||
axios.post(url, {
|
||||
content: commentContent
|
||||
},
|
||||
{
|
||||
}
|
||||
).then((response) => {
|
||||
if (response.data.data.id) {
|
||||
let newId = response.data.data.id;
|
||||
const commentIndex = this._findById(id, comments);
|
||||
const parentComment = comments[commentIndex]
|
||||
|
||||
this.setState({
|
||||
// runTesting: false,
|
||||
comments: addSecondLevelComment(comments, parentComment, commentIndex, newId, commentContent, user, editor)
|
||||
}, ()=>{
|
||||
// keditor代码美化
|
||||
editor.html && window.prettyPrint()
|
||||
})
|
||||
|
||||
const newMemo2 = Object.assign({}, this.state.memo);
|
||||
newMemo2.total_replies_count = newMemo2.total_replies_count + 1;
|
||||
this.setState({
|
||||
memo: newMemo2
|
||||
})
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
// 公共接口 --- 删除回复
|
||||
deleteComment = (parrentComment, childCommentId) => {
|
||||
handleDeleteComment(this, parrentComment, childCommentId, 'message')
|
||||
|
||||
}
|
||||
// 公共接口 --- 回复点赞
|
||||
commentPraise = (discussId) => {
|
||||
handleCommentPraise(this, discussId, 'message', (old_user_praise) => {
|
||||
const newMemo2 = Object.assign({}, this.state.memo);
|
||||
|
||||
newMemo2.total_praises_count = old_user_praise
|
||||
? newMemo2.total_praises_count - 1 : newMemo2.total_praises_count + 1;
|
||||
this.setState({
|
||||
memo: newMemo2
|
||||
})
|
||||
})
|
||||
}
|
||||
// 公共接口 --- 隐藏回复
|
||||
hiddenComment = (item, childCommentId) => {
|
||||
handleHiddenComment(this, item, childCommentId, 'message')
|
||||
}
|
||||
createNewComment = (commentContent, id, editor) => {
|
||||
let content = handleContentBeforeCreateNew(commentContent);
|
||||
const { memo } = this.props;
|
||||
|
||||
const url = `/messages/${id}/reply.json`;
|
||||
|
||||
// const url = `/api/v1/memos/${memo.id}/reply`;
|
||||
let { comments } = this.state;
|
||||
axios.post(url, {
|
||||
content: content
|
||||
},
|
||||
{
|
||||
}
|
||||
).then((response) => {
|
||||
if (response.data.status === -1) {
|
||||
console.error('服务端异常')
|
||||
return;
|
||||
}
|
||||
// this.props.showNotification('帖子发表成功')
|
||||
|
||||
if (response.data) {
|
||||
const _id = response.data.data.id;
|
||||
// ke
|
||||
editor.html && editor.html('');
|
||||
editor.afterBlur && editor.afterBlur()
|
||||
// md
|
||||
editor.setValue && editor.setValue('')
|
||||
|
||||
|
||||
const user = this._getUser();
|
||||
this.setState({
|
||||
comments: addNewComment(comments, _id, content, user, this.props.isSuperAdmin(), this)
|
||||
})
|
||||
const newMemo2 = Object.assign({}, this.state.memo);
|
||||
newMemo2.total_replies_count = newMemo2.total_replies_count + 1;
|
||||
this.setState({
|
||||
memo: newMemo2
|
||||
})
|
||||
this.refs.editor.showEditor();
|
||||
this.refs.editor.close();
|
||||
|
||||
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* parent.isAllChildrenLoaded 为 true的时候,表示已经没有更多子回复了
|
||||
*/
|
||||
loadMoreChildComments = (parent) => {
|
||||
const url = `/messages/${parent.id}/reply_list.json?page=1&page_size=500`
|
||||
axios.get(url,{
|
||||
})
|
||||
.then((response) => {
|
||||
const { replies, liked, total_replies_count } = response.data.data
|
||||
|
||||
// const memo = Object.assign({}, this.state.memo)
|
||||
// memo.total_replies_count = total_replies_count;
|
||||
this.setState({
|
||||
// memo,
|
||||
comments: generateChildComments(replies, this.state.comments, parent, this.transformReply)
|
||||
})
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------- comments END
|
||||
// ------------------------------------------------------------------------------------------- comments END
|
||||
// 置顶
|
||||
setTop(memo) {
|
||||
// const params = {
|
||||
// sticky: memo.sticky ? 0 : 1,
|
||||
// }
|
||||
// if (this.state.p_s_order) {
|
||||
// params.order = this.state.p_s_order;
|
||||
// }
|
||||
// if (this.state.p_forum_id) {
|
||||
// params.forum_id = this.state.p_forum_id;
|
||||
// }
|
||||
// let paramsUrl = urlStringify(params)
|
||||
const set_top_or_down_Url = `/messages/${memo.id}/sticky_top.json`;
|
||||
// 获取memo list
|
||||
axios.put(set_top_or_down_Url, {
|
||||
|
||||
})
|
||||
.then((response) => {
|
||||
const status = response.data.status
|
||||
if (status === 0) {
|
||||
this.props.showNotification( memo.sticky ? '取消置顶成功' : '置顶成功');
|
||||
memo.sticky = memo.sticky ? false : true
|
||||
this.setState({
|
||||
memo: Object.assign({}, memo)
|
||||
})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
setRewardDialogVisible = (visible) => {
|
||||
this.setState({
|
||||
goldRewardDialogOpen: visible
|
||||
})
|
||||
}
|
||||
showRewardDialog = () => {
|
||||
this.setState({
|
||||
goldRewardDialogOpen: true
|
||||
})
|
||||
}
|
||||
// --------------------------------------------------------------------------------------------帖子獎勵 END
|
||||
showCommentInput = () => {
|
||||
if (window.__useKindEditor === true) {
|
||||
this.refs.editor.showEditor();
|
||||
} else {
|
||||
this.refs.editor.showEditor();
|
||||
}
|
||||
}
|
||||
initReply = (parent) => {
|
||||
if (!parent.isAllChildrenLoaded) {
|
||||
this.loadMoreChildComments(parent)
|
||||
}
|
||||
}
|
||||
|
||||
startcomments=()=>{
|
||||
setTime = setInterval( ()=> {
|
||||
this.fetchReplies()
|
||||
}, 5000);
|
||||
this.setState({
|
||||
commentstype:true
|
||||
})
|
||||
}
|
||||
|
||||
clearcomments=()=>{
|
||||
clearInterval(setTime);
|
||||
this.setState({
|
||||
commentstype:false
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const { match, history } = this.props
|
||||
const { recommend_shixun, current_user,author_info } = this.props;
|
||||
const { memo, comments, hasMoreComments, commentstype, pageCount, total_count , author } = this.state;
|
||||
const messageId = match.params.topicId
|
||||
if (this.state.memoLoading || !current_user) {
|
||||
return <div className="edu-back-white" id="forum_index_list"></div>
|
||||
}
|
||||
current_user.user_url = `/users/${current_user.login}`;
|
||||
const isCurrentUserTheAuthor = current_user.login == memo.author.login
|
||||
const isAdmin = this.props.isAdmin()
|
||||
// TODO 图片上传地址
|
||||
const courseId=this.props.match.params.coursesId;
|
||||
const boardId = this.props.match.params.boardId;
|
||||
const isCourseEnd = this.props.isCourseEnd();
|
||||
|
||||
document.title=this.props.coursedata&&this.props.coursedata.name;
|
||||
return (
|
||||
<div className="edu-back-white edu-class-container edu-position course-message topicDetail" id="yslforum_index_list"> {/* fl with100 */}
|
||||
<style>{`
|
||||
.topicDetail #forum_list .return_btn.no_mr {
|
||||
margin-right: 1px;
|
||||
}
|
||||
/* 有内容时,编辑器下方的边框*/
|
||||
.topicDetail .borderBottom.commentInputs {
|
||||
border-bottom: 1px solid rgb(238, 238, 238);
|
||||
}
|
||||
.independent {
|
||||
background: rgb(250, 250, 250);
|
||||
padding-bottom: 20px;
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
|
||||
.course-message.topicDetail .panel-comment_item .comment_orig_content {
|
||||
width: 1072px;
|
||||
}
|
||||
`}</style>
|
||||
<CBreadcrumb className={'independent'} items={[
|
||||
{ to: current_user&¤t_user.first_category_url, name: this.props.coursedata.name},
|
||||
{ to: `/courses/${courseId}/boards/${boardId}`, name: memo.board_name },
|
||||
{ name: '帖子详情'}
|
||||
]}></CBreadcrumb>
|
||||
|
||||
<SendToCourseModal
|
||||
ref="sendToCourseModal"
|
||||
{...this.props}
|
||||
moduleName="帖子"
|
||||
seletedMessageIds={[messageId]}
|
||||
></SendToCourseModal>
|
||||
<div className="clearfix">
|
||||
<div id="forum_list" className="forum_table mh650">
|
||||
<div className="padding30 bor-bottom-greyE" style={{paddingBottom: '20px'}}>
|
||||
<div className="font-16 cdefault clearfix pr pr35">
|
||||
<span className="noteDetailTitle">{memo.subject}</span>
|
||||
{ !!memo.sticky && <span className="btn-cir btn-cir-red ml10"
|
||||
style={{position: 'relative', bottom: '4px'}}>置顶</span>}
|
||||
{ !!memo.reward && <span className="color-orange font-14 ml15"
|
||||
data-tip-down={`获得平台奖励金币:${memo.reward}`} >
|
||||
<i className="iconfont icon-gift mr5"></i>{memo.reward}
|
||||
</span> }
|
||||
{/* || current_user.user_id === author_info.user_id */}
|
||||
{ current_user && (isAdmin || isCurrentUserTheAuthor) &&
|
||||
<div className="edu-position-hidebox" style={{position: 'absolute', right: '2px',top:'4px'}}>
|
||||
<a href="javascript:void(0);"><i className="fa fa-bars font-16"></i></a>
|
||||
<ul className="edu-position-hide undis">
|
||||
|
||||
{ ( isCurrentUserTheAuthor || isAdmin ) &&
|
||||
<li><a
|
||||
onClick={() => this.props.toEditPage( Object.assign({}, this.props.match.params, {'coursesId': this.state.memo.course_id}) ) }
|
||||
>编 辑</a></li>}
|
||||
{ isAdmin &&
|
||||
( memo.sticky == true ?
|
||||
<li><a href="javascript:void(0);" onClick={() => this.setTop(memo)}>取消置顶</a></li>
|
||||
:
|
||||
<li><a href="javascript:void(0);" onClick={() => this.setTop(memo)}>置 顶</a></li> )
|
||||
}
|
||||
{ isAdmin &&
|
||||
<li><a href="javascript:void(0);" onClick={() => this.refs.sendToCourseModal.setVisible(true)}>发 送</a></li>
|
||||
}
|
||||
{ ( isCurrentUserTheAuthor || isAdmin ) && <li>
|
||||
<a href="javascript:void(0)" onClick={() =>
|
||||
window.delete_confirm_box_2_react(`onMemoDelete`, '您确定要删除吗?' , memo)}>
|
||||
|
||||
删 除</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
<div className="df mt20">
|
||||
<img src={setImagesUrl(`/images/${author && author.image_url}`)} className="radius mr10 mt2" width="40px" height="40px"/>
|
||||
<div className="flex1">
|
||||
<div className="color-grey-9 lineh-20">
|
||||
<span class="color-grey-3 mr20 fl" style={{"fontWeight":"400"}}>{author && author.name}</span>
|
||||
<span className="fl">{moment(memo.created_on).fromNow()} 发布</span>
|
||||
</div>
|
||||
|
||||
<div className="color-grey-9 clearfix">
|
||||
<span className="fl" style={{marginTop: '4px'}}>
|
||||
{/* { current_user.admin && <Tooltip title={ "帖子奖励" }>
|
||||
<span className="noteDetailNum rightline cdefault" style={{padding: '0 4px', cursor: 'pointer'}}>
|
||||
<i className="iconfont icon-jiangli mr5" onClick={this.showRewardDialog}></i>
|
||||
</span>
|
||||
</Tooltip> } */}
|
||||
<Tooltip title={"浏览数"}>
|
||||
<span className={`noteDetailNum `} style={{paddingLeft: '0px'}}>
|
||||
<i className="iconfont icon-liulanyan mr5"></i>
|
||||
<span style={{ top: "1px", position: "relative" }}>{memo.visits || '1'}</span>
|
||||
</span>
|
||||
</Tooltip>
|
||||
{ !!memo.total_replies_count &&
|
||||
<Tooltip title={"回复数"}>
|
||||
<a href="javascript:void(0)" className="noteDetailNum">
|
||||
<i className="iconfont icon-huifu1 mr5" onClick={this.showCommentInput}></i>
|
||||
<span style={{ top: "2px", position: "relative" }}>{ memo.total_replies_count }</span>
|
||||
</a>
|
||||
</Tooltip>
|
||||
}
|
||||
{!!memo.total_praises_count &&
|
||||
<Tooltip title={"点赞数"}>
|
||||
<span className={`noteDetailNum `} style={{}}>
|
||||
<i className="iconfont icon-dianzan-xian mr5"></i>
|
||||
<span style={{ top: "2px", position: "relative" }}>{ memo.total_praises_count }</span>
|
||||
</span>
|
||||
</Tooltip>
|
||||
}
|
||||
</span>
|
||||
<div className="fr">
|
||||
{/* || current_user.user_id === author_info.user_id */}
|
||||
<a className={`task-hide fr return_btn color-grey-6 ${ current_user && (isAdmin
|
||||
) ? '': 'no_mr'} `} onClick={() => this.props.toListPage(Object.assign({}, this.props.match.params, {'coursesId': this.state.memo.course_id})) } >
|
||||
返回
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="padding30 memoContent new_li" style={{ paddingBottom: '10px'}}>
|
||||
{/* <MarkdownToHtml content={memo.content}></MarkdownToHtml> */}
|
||||
{memo.is_md == true ?
|
||||
<MarkdownToHtml content={memo.content}></MarkdownToHtml>
|
||||
:
|
||||
<div dangerouslySetInnerHTML={{ __html: memo.content }}></div>
|
||||
}
|
||||
</div>
|
||||
<div className="padding30 bor-bottom-greyE" style={{paddingTop: '2px'}}>
|
||||
<div className="mt10 mb20">
|
||||
{/* ${memo.user_praise ? '' : ''} */}
|
||||
<Tooltip title={`${memo.liked ? '取消点赞' : '点赞'}`}>
|
||||
<p className={`noteDetailPoint ${memo.user_praise ? 'Pointed' : ''}`} onClick={()=>{this.clickPraise()}} >
|
||||
<i className="iconfont icon-dianzan"></i><br/>
|
||||
<span>{memo.praises_count}</span>
|
||||
</p>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
{ memo.attachments && !!memo.attachments.length &&
|
||||
<div>
|
||||
{this.renderAttachment()}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
{!isCourseEnd && <MemoDetailMDEditor ref="editor" memo={memo} usingMockInput={true} placeholder="说点什么"
|
||||
{...this.props}
|
||||
height={160} showError={true} buttonText={'发表'} className={comments && comments.length && 'borderBottom'}></MemoDetailMDEditor>}
|
||||
|
||||
{/* onClick={ this.createNewComment }
|
||||
enableReplyTo={true}
|
||||
*/}
|
||||
<div className="padding20 memoReplies commentsDelegateParent comments_hideSecondReplyUserHeader"
|
||||
style={{ display: (comments && !!comments.length) ? 'block' : 'none', paddingBottom: '0px' }}>
|
||||
<div className="replies_count commentstypetop">
|
||||
{this.props.isAdmin()===true? <span className="commentstypebutton font-16 ">
|
||||
{this.state.commentstype===false?<Button type="primary" onClick={()=>this.startcomments()}>开启刷新评论</Button>
|
||||
:<Button type="danger" onClick={()=>this.clearcomments()}>停止刷新</Button>}
|
||||
</span>:""}
|
||||
|
||||
<span className="labal font-16">全部回复</span>
|
||||
<span className="count font-16">({memo.total_replies_count})</span>
|
||||
|
||||
</div>
|
||||
|
||||
<Comments comments={comments} user={current_user}
|
||||
replyComment={this.replyComment}
|
||||
deleteComment={this.deleteComment}
|
||||
commentPraise={this.commentPraise}
|
||||
rewardCode={this.rewardCode}
|
||||
hiddenComment={this.hiddenComment}
|
||||
buttonText={'发表'}
|
||||
|
||||
usingAntdModal={true}
|
||||
isChildCommentPagination={true}
|
||||
loadMoreChildComments={this.loadMoreChildComments}
|
||||
initReply={this.initReply}
|
||||
showRewardButton={false}
|
||||
showReply={!isCourseEnd}
|
||||
|
||||
onlySuperAdminCouldHide={true}
|
||||
></Comments>
|
||||
|
||||
|
||||
{/* { true ? :
|
||||
<div className="memoMore">
|
||||
<div className="writeCommentBtn" onClick={this.showCommentInput}>写评论</div>
|
||||
</div>} */}
|
||||
</div>
|
||||
|
||||
|
||||
<div className="memoMore" style={{'margin-top': '20px'}}>
|
||||
{ total_count > REPLY_PAGE_COUNT &&
|
||||
<Pagination showQuickJumper onChange={this.onPaginationChange} current={pageCount} total={total_count} pageSize={10}/>
|
||||
}
|
||||
{!isCourseEnd && <div className="writeCommentBtn" onClick={this.showCommentInput}>写评论</div>}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ImageLayerOfCommentHOC() ( RouteHOC()(TopicDetail) );
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
|
||||
|
||||
|
||||
/*必填*/
|
||||
/*
|
||||
.ant-form-item-required::before {
|
||||
display: none;
|
||||
}
|
||||
.ant-form-item-control-wrapper.ant-col-xs-24.ant-col-sm-24::before {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
color: #f5222d;
|
||||
font-size: 14px;
|
||||
font-family: SimSun, sans-serif;
|
||||
line-height: 1;
|
||||
content: '*';
|
||||
}*/
|
||||
/*
|
||||
.ant-form-item-control {
|
||||
display: inline-block;
|
||||
}*/
|
||||
/* form 样式 --------------------------------------------- */
|
||||
|
||||
|
||||
|
||||
.topicTitle {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.topicTitle .ant-form-item-control-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.ant-pagination.coursePagination {
|
||||
text-align: center;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.setemail{
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.setemail .ant-checkbox-wrapper{
|
||||
margin-top: 8px;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
.directory_style {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
maxSize: 20px;
|
||||
overflow: hidden;
|
||||
whiteSpace: nowrap;
|
||||
textOverflow: ellipsis
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export function RouteHOC(options = {}) {
|
||||
return function wrap(WrappedComponent) {
|
||||
return class Wrapper extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
|
||||
}
|
||||
}
|
||||
toDetailPage = (_courseId, boardId, topicId) => {
|
||||
if (typeof _courseId == "object") {
|
||||
const topicId = _courseId.topicId
|
||||
const boardId = _courseId.boardId
|
||||
const courseId = _courseId.coursesId
|
||||
this.props.history.push(`/courses/${courseId}/boards/${boardId}/messages/${topicId}`)
|
||||
} else {
|
||||
this.props.history.push(`/courses/${_courseId}/boards/${boardId}/messages/${topicId}`)
|
||||
}
|
||||
|
||||
}
|
||||
toEditPage = (_courseId, boardId, topicId) => {
|
||||
if (typeof _courseId == "object") {
|
||||
const topicId = _courseId.topicId
|
||||
const boardId = _courseId.boardId
|
||||
const courseId = _courseId.coursesId
|
||||
this.props.history.push(`/courses/${courseId}/boards/${boardId}/messages/${topicId}/edit`)
|
||||
} else {
|
||||
this.props.history.push(`/courses/${_courseId}/boards/${boardId}/messages/${topicId}/edit`)
|
||||
}
|
||||
}
|
||||
toNewPage = (courseId, boardId) => {
|
||||
this.props.history.push(`/courses/${courseId}/boards/${boardId}/messages/new`)
|
||||
}
|
||||
toListPage = (_courseId, boardId) => {
|
||||
if (typeof _courseId == "object") {
|
||||
const boardId = _courseId.boardId
|
||||
const courseId = _courseId.coursesId
|
||||
this.props.history.push(`/courses/${courseId}/boards/${boardId}`)
|
||||
} else {
|
||||
this.props.history.push(`/courses/${_courseId}/boards${boardId ? '/' + boardId : ''}`)
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { snackbarOpen} = this.state;
|
||||
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<WrappedComponent {...this.props}
|
||||
toDetailPage={this.toDetailPage}
|
||||
toEditPage={this.toEditPage}
|
||||
toNewPage={this.toNewPage}
|
||||
toListPage={this.toListPage}
|
||||
>
|
||||
|
||||
</WrappedComponent>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,466 @@
|
||||
import React,{ Component } from "react";
|
||||
import { Input, Checkbox, Table, Tooltip, Pagination,Spin } from "antd";
|
||||
|
||||
import CourseLayoutcomponent from '../common/CourseLayoutComponent'
|
||||
import BoardsListItem from './BoardsListItem'
|
||||
|
||||
import Titlesearchsection from '../common/titleSearch/TitleSearchSection'
|
||||
import ColorCountText from '../common/titleSearch/ColorCountText'
|
||||
import SendToCourseModal from '../coursesPublic/modal/SendToCourseModal'
|
||||
import NoneData from "../coursesPublic/NoneData"
|
||||
|
||||
import axios from 'axios'
|
||||
|
||||
import _ from 'lodash'
|
||||
import './board.css'
|
||||
import '../css/members.css'
|
||||
import { RouteHOC } from './common.js'
|
||||
import { on, off, trigger, WordsBtn } from 'educoder'
|
||||
|
||||
class Boards extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state = {
|
||||
searchValue: '',
|
||||
checkAllValue: false,
|
||||
checkBoxValues: [],
|
||||
pagination: {
|
||||
page: 1,
|
||||
page_size: 15,
|
||||
total_count: 0
|
||||
},
|
||||
messages: [
|
||||
],
|
||||
sort_type: 'time',
|
||||
boardid:undefined,
|
||||
isSpin:false
|
||||
}
|
||||
}
|
||||
fetchAll = (searchText, page) => {
|
||||
this.setState({
|
||||
isSpin:true
|
||||
})
|
||||
const _serachText = searchText || this.state.searchValue
|
||||
const _page = page || this.state.pagination.page
|
||||
|
||||
|
||||
const cid = this.props.match.params.coursesId
|
||||
const bid = this.props.match.params.boardId
|
||||
//
|
||||
// hot
|
||||
const sort_type = this.state.sort_type
|
||||
// page_size
|
||||
const url = `/boards/${bid}/messages.json?page_size=15&search=${_serachText || ''}&page=${_page}&sort=0&sort_type=${sort_type}`
|
||||
axios.get(encodeURI(url)).then((response) => {
|
||||
if (response.data.status == 0 && response.data.data) {
|
||||
let _newBoards = response.data.data.messages
|
||||
// if (_page > 1) {
|
||||
// _newBoards = this.state.boards.slice().concat(_newBoards)
|
||||
// }
|
||||
this.setState({
|
||||
messages: _newBoards,
|
||||
boardName: response.data.data.name,
|
||||
boardid:response.data.data.id,
|
||||
parent_id: response.data.data.parent_id,
|
||||
pagination: response.data.pagination || Object.assign({}, this.state.pagination
|
||||
, { page: _page, total_count: response.data.data.total_count }),
|
||||
isSpin:false
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
isSpin:false
|
||||
})
|
||||
});
|
||||
}
|
||||
fetchBoards = () => {
|
||||
const boardId = this.props.match.params.boardId
|
||||
const boardsUrl = `/courses/board_list.json?board_id=${boardId}`
|
||||
axios.get(boardsUrl, { })
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.setState({
|
||||
boards: response.data.data.boards,
|
||||
course_id: response.data.data.course_id
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
componentDidMount = () => {
|
||||
this.setState({
|
||||
isSpin:true
|
||||
})
|
||||
this.fetchBoards()
|
||||
this.fetchAll()
|
||||
|
||||
on('updateNavSuccess', this.updateNavSuccess)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
off('updateNavSuccess', this.updateNavSuccess)
|
||||
}
|
||||
updateNavSuccess = () => {
|
||||
this.fetchBoards()
|
||||
if (this.props.match.params.boardId == this.state.boardid) {
|
||||
this.fetchAll()
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate = (prevProps) => {
|
||||
if ( prevProps.match.params.boardId != this.props.match.params.boardId ) {
|
||||
this.setState({
|
||||
isSpin:true
|
||||
})
|
||||
this.clearAllCheck()
|
||||
this.fetchAll(null, 1)
|
||||
}
|
||||
}
|
||||
moveTo = (board) => {
|
||||
const len = this.state.checkBoxValues.length
|
||||
if (len == 0) {
|
||||
this.props.showNotification('请先在列表中选择要移动的帖子')
|
||||
return;
|
||||
}
|
||||
|
||||
const bid = this.props.match.params.boardId
|
||||
|
||||
const checkBoxValues = this.state.checkBoxValues
|
||||
const url = `/boards/${bid}/messages/bulk_move.json`
|
||||
axios.put(url, {
|
||||
ids: checkBoxValues,
|
||||
to_board_id: board.id
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
console.log('--- 成功')
|
||||
this.props.showNotification('帖子移动成功')
|
||||
this.props.updataleftNavfun()
|
||||
// TODO 停留在当前board 或 目标board
|
||||
this.clearAllCheck()
|
||||
this.fetchAll()
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
onDelete = () => {
|
||||
const len = this.state.checkBoxValues.length
|
||||
if (len == 0) {
|
||||
this.props.showNotification('请先选择要删除的帖子')
|
||||
return;
|
||||
}
|
||||
this.props.confirm({
|
||||
// content: `确认要删除所选的${len}个帖子吗?`,
|
||||
content: `是否确认删除?`,
|
||||
onOk: () => {
|
||||
// const cid = this.props.match.params.coursesId
|
||||
const bid = this.props.match.params.boardId
|
||||
|
||||
const url = `/boards/${bid}/messages/bulk_delete.json`
|
||||
const board_id = 5897
|
||||
axios.delete(url, { data: {
|
||||
// course_id: cid,
|
||||
ids: this.state.checkBoxValues
|
||||
}})
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
// {"status":1,"message":"删除成功"}
|
||||
console.log('--- 删除成功')
|
||||
this.clearAllCheck()
|
||||
this.fetchAll(null, 1)
|
||||
this.props.updataleftNavfun()
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
onSticky = (message) => {
|
||||
const cid = this.props.match.params.coursesId
|
||||
const url = `/messages/${message.id}/sticky_top.json`
|
||||
axios.put(url, {
|
||||
course_id: cid,
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
console.log('--- 置顶/取消置顶成功')
|
||||
// const boards = this.state.boards;
|
||||
// for (let _i = 0; _i < boards.length; _i++) {
|
||||
// boards[]
|
||||
// }
|
||||
this.fetchAll()
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
onItemClick = (item) => {
|
||||
const checkBoxValues = this.state.checkBoxValues.slice(0);
|
||||
const index = checkBoxValues.indexOf(item.id);
|
||||
if (index != -1) {
|
||||
_.remove(checkBoxValues, (listItem)=> listItem === item.id)
|
||||
} else {
|
||||
checkBoxValues.push(item.id)
|
||||
}
|
||||
this.onCheckBoxChange(checkBoxValues)
|
||||
}
|
||||
|
||||
onPressEnter = (e) => {
|
||||
clearTimeout(this.timeoutHandler)
|
||||
this.timeoutHandler = null;
|
||||
|
||||
this.fetchAll(this.state.searchValue, 1)
|
||||
}
|
||||
onInputSearchChange = (e) => {
|
||||
this.setState({
|
||||
searchValue:e.target.value
|
||||
})
|
||||
|
||||
if (this.timeoutHandler) {
|
||||
clearTimeout(this.timeoutHandler)
|
||||
this.timeoutHandler = null;
|
||||
}
|
||||
this.timeoutHandler = setTimeout(() => {
|
||||
this.fetchAll(this.state.searchValue, 1)
|
||||
}, 1200)
|
||||
}
|
||||
addDir = () => {
|
||||
let {boardid}=this.state;
|
||||
trigger('boardAdd', parseInt(boardid))
|
||||
}
|
||||
renameDir = () => {
|
||||
const boardId = this.props.match.params.boardId
|
||||
trigger('boardRename', { category_id: parseInt(boardId), category_name: this.state.boardName})
|
||||
}
|
||||
onToBoardsNew = () => {
|
||||
const courseId = this.state.course_id
|
||||
const boardId = this.props.match.params.boardId
|
||||
|
||||
this.props.toNewPage(courseId, boardId)
|
||||
}
|
||||
onCheckAll = (e) => {
|
||||
this.setState({
|
||||
checkAllValue: e.target.checked
|
||||
})
|
||||
const values = this.state.messages.map(item => {
|
||||
return item.id
|
||||
})
|
||||
if (e.target.checked) {
|
||||
const concated = this.state.checkBoxValues.concat(values);
|
||||
const sortedUniqed = _.uniq(concated)
|
||||
this.setState({
|
||||
checkBoxValues: sortedUniqed
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
checkBoxValues: _.difference(this.state.checkBoxValues, values)
|
||||
})
|
||||
}
|
||||
}
|
||||
clearAllCheck = () => {
|
||||
this.setState({
|
||||
checkBoxValues: [],
|
||||
checkAllValue: false
|
||||
})
|
||||
}
|
||||
onCheckBoxChange = (checkedValues) => {
|
||||
this.setState({
|
||||
checkBoxValues: checkedValues,
|
||||
checkAllValue: checkedValues.length == this.state.messages.length
|
||||
})
|
||||
console.log('checked = ', checkedValues);
|
||||
}
|
||||
onPageChange = (pageNumber) => {
|
||||
this.setState({
|
||||
checkBoxValues:[]
|
||||
})
|
||||
this.fetchAll(null, pageNumber)
|
||||
}
|
||||
|
||||
onSendToOtherCourse = () => {
|
||||
const len = this.state.checkBoxValues.length
|
||||
if (len == 0) {
|
||||
this.props.showNotification('请先在列表中选择要发送的帖子')
|
||||
return;
|
||||
}
|
||||
this.refs.sendToCourseModal.setVisible(true)
|
||||
}
|
||||
onSetToOpen = () => {
|
||||
const { checkBoxValues } = this.state;
|
||||
if (checkBoxValues.length == 0) {
|
||||
this.props.showNotification('请先在列表中选择要公开的帖子')
|
||||
return;
|
||||
}
|
||||
const boardId = this.props.match.params.boardId
|
||||
const url = `/boards/${boardId}/messages/bulk_public.json`
|
||||
axios.put(url, {
|
||||
ids: checkBoxValues
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.props.showNotification('操作成功')
|
||||
this.fetchAll()
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
}
|
||||
onSortTypeChange = (sort_type) => {
|
||||
this.setState({ sort_type }, () => {
|
||||
this.fetchAll()
|
||||
})
|
||||
|
||||
}
|
||||
render(){
|
||||
const isAdmin = this.props.isAdmin()
|
||||
const isCourseEnd = this.props.isCourseEnd()
|
||||
const isAdminOrStudent = this.props.isAdminOrStudent()
|
||||
let { boardName, searchValue, boards, messages, checkBoxValues,
|
||||
checkAllValue, pagination, sort_type, parent_id } = this.state;
|
||||
const { coursedata } = this.props;
|
||||
|
||||
const bid = this.props.match.params.boardId
|
||||
const haveMore = pagination.total_count - pagination.page_size * pagination.page > 0
|
||||
return(
|
||||
<React.Fragment >
|
||||
<SendToCourseModal
|
||||
ref="sendToCourseModal"
|
||||
{...this.props}
|
||||
moduleName="帖子"
|
||||
selectedMessageIds={checkBoxValues}
|
||||
></SendToCourseModal>
|
||||
<Titlesearchsection
|
||||
title={boardName || "帖子列表"}
|
||||
searchValue={ searchValue }
|
||||
onInputSearchChange={this.onInputSearchChange}
|
||||
allowClearonChange={this.onInputSearchChange}
|
||||
showSearchInput={messages.length >= 10}
|
||||
searchPlaceholder={ '请输入帖子名称进行搜索' }
|
||||
firstRowRight={
|
||||
<React.Fragment>
|
||||
{ !isCourseEnd && isAdmin && !parent_id && <WordsBtn style="blue" className="mr30" onClick={()=>this.addDir()}>新建目录</WordsBtn> }
|
||||
{ isAdmin && !!parent_id && <WordsBtn style="blue" className="mr30" onClick={()=>this.renameDir()}>目录重命名</WordsBtn> }
|
||||
{ !isCourseEnd && isAdminOrStudent && <WordsBtn style="blue" className="" onClick={()=>this.onToBoardsNew()}>我要发贴</WordsBtn> }
|
||||
</React.Fragment>
|
||||
}
|
||||
secondRowLeft={
|
||||
pagination ? <ColorCountText count={pagination.total_count} name="个帖子"></ColorCountText> : ''
|
||||
}
|
||||
onPressEnter={this.onPressEnter}
|
||||
></Titlesearchsection>
|
||||
|
||||
|
||||
{/* <BoardsListItem></BoardsListItem>
|
||||
|
||||
<FilesListItem></FilesListItem> */}
|
||||
|
||||
{messages&&messages.length == 0?"": isAdmin && <div className="mt20 edu-back-white padding20-30">
|
||||
<div className="clearfix">
|
||||
{isAdmin&&<Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue}>已选 {checkBoxValues.length} 个 (不支持跨页勾选)</Checkbox>}
|
||||
<div className="studentList_operation_ul">
|
||||
{ !!isAdmin &&
|
||||
<React.Fragment>
|
||||
<li className="li_line"><a href="javascript:void(0)" className="color-grey-9" onClick={this.onDelete}>删除</a></li>
|
||||
<li className="li_line"><a href="javascript:void(0)" className="color-grey-9" onClick={this.onSendToOtherCourse}>发送</a></li>
|
||||
{ coursedata && !!coursedata.course_public && <li className="li_line"><a href="javascript:void(0)" className="color-grey-9" onClick={this.onSetToOpen}>设为公开</a></li> }
|
||||
|
||||
<li className="li_line drop_down">
|
||||
移动到...<i className="iconfont icon-xiajiantou font-12 ml2"></i>
|
||||
<ul className="drop_down_menu"
|
||||
style={{"right":"0px","left":"unset", maxHeight: '318px', overflowY: 'auto', minWidth: '200px'}}>
|
||||
{ boards && boards.length > 10 && <p className="drop_down_search">
|
||||
<Input placeholder="搜索" value={this.state.dirSearchValue} onChange={(e) => {this.setState({dirSearchValue: e.target.value})}}/>
|
||||
</p> }
|
||||
{
|
||||
boards && boards.filter((item)=> {
|
||||
return item.id != bid && (!this.state.dirSearchValue || item.name.indexOf(this.state.dirSearchValue) != -1)
|
||||
}).map( (item, index) => {
|
||||
return <li key={`i_${index}`} onClick={() => this.moveTo(item)} title={item.name}>{item.name}</li>
|
||||
})
|
||||
}
|
||||
{ isAdmin && !isCourseEnd &&
|
||||
<p className="drop_down_btn">
|
||||
<a href="javascript:void(0)" className="color-grey-6"
|
||||
onClick={()=>this.addDir()}
|
||||
>新建目录...</a>
|
||||
</p>
|
||||
}
|
||||
{/* <p className="drop_down_btn"><a href="javascript:void(0)" className="color-grey-6">添加分班...</a></p> */}
|
||||
</ul>
|
||||
</li>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
<li className="drop_down">
|
||||
{sort_type == 'time' ? '时间排序' : '热度排序'}<i className="iconfont icon-xiajiantou font-12 ml2"></i>
|
||||
<ul className="drop_down_normal">
|
||||
<li onClick={() => this.onSortTypeChange('time')}>时间排序</li>
|
||||
<li onClick={() => this.onSortTypeChange('hot')}>热度排序</li>
|
||||
</ul>
|
||||
</li>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<style>{`
|
||||
.panel-inner-fourm {
|
||||
border-bottom: none;
|
||||
}
|
||||
.panel-inner-fourm:hover {
|
||||
background: #fff;
|
||||
}
|
||||
`}</style>
|
||||
<Spin size="large" spinning={this.state.isSpin}>
|
||||
<div className="clearfix stu_table">
|
||||
<Checkbox.Group style={{ width: '100%' }} onChange={this.onCheckBoxChange} value={checkBoxValues}>
|
||||
{ messages.map((item, index) => {
|
||||
return (
|
||||
<div className="mt20 edu-back-white padding02010" key={`d_${index}`}>
|
||||
<BoardsListItem
|
||||
{...this.props}
|
||||
discussMessage={item}
|
||||
checkBox={ isAdmin ? <Checkbox value={item.id} key={item.id}></Checkbox> : ''}
|
||||
onItemClick={this.onItemClick}
|
||||
onSticky={this.onSticky}
|
||||
></BoardsListItem>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</Checkbox.Group>
|
||||
</div>
|
||||
</Spin>
|
||||
{
|
||||
( !this.state.isSpin && (!messages || messages.length == 0) ) && <NoneData></NoneData>
|
||||
}
|
||||
|
||||
{/* { haveMore && <p className="edu-txt-center pt30 pb10 clearfix">
|
||||
<a className={"clickmorebox"} onClick={() => this.fetchAll(null, parseInt(pagination.page) + 1)}>
|
||||
<Tooltip title="点击查看更多" placement="bottom" arrowPointAtCenter={true}
|
||||
>
|
||||
<i className="iconfont icon-xiajiantou color-grey-9 font-16"></i>
|
||||
</Tooltip>
|
||||
</a>
|
||||
</p> } */}
|
||||
{pagination.total_count > 15 && <Pagination className="coursePagination"
|
||||
current={pagination.page}
|
||||
showQuickJumper pageSize={15} total={pagination.total_count} onChange={this.onPageChange} />}
|
||||
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default RouteHOC()(Boards);
|
||||
@@ -0,0 +1,113 @@
|
||||
import React,{Component} from "react";
|
||||
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal, Table, Divider, Tag,DatePicker,Radio,Tooltip} from "antd";
|
||||
import {Link} from 'react-router-dom';
|
||||
import locale from 'antd/lib/date-picker/locale/zh_CN';
|
||||
import { WordsBtn, MarkdownToHtml, on, off } from 'educoder';
|
||||
import axios from 'axios';
|
||||
import Modals from '../../modals/Modals';
|
||||
import CoursesListType from '../coursesPublic/CoursesListType';
|
||||
import HomeworkModal from "../coursesPublic/HomeworkModal";
|
||||
import CheckAllGroup from '../common/button/CheckAllGroup'
|
||||
import moment from 'moment';
|
||||
import CheckCodeModal from '../coursesPublic/modal/CheckCodeModal'
|
||||
import NoneData from '../coursesPublic/NoneData'
|
||||
|
||||
import '../css/Courses.css'
|
||||
import WorkDetailPageHeader from './common/WorkDetailPageHeader'
|
||||
import TabRightComponents from './common/TabRightComponents'
|
||||
|
||||
const { Option} = Select;
|
||||
const CheckboxGroup = Checkbox.Group;
|
||||
const confirm = Modal.confirm;
|
||||
let GraduationTasksnewtype=true;
|
||||
const $ = window.$;
|
||||
const Search = Input.Search;
|
||||
const RadioGroup = Radio.Group;
|
||||
|
||||
class CommonWorkAnswer extends Component{
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.state={
|
||||
course_name:"",
|
||||
homework_name:"",
|
||||
search: ''
|
||||
}
|
||||
}
|
||||
fetchData = () => {
|
||||
let workId=this.props.match.params.workId;
|
||||
const url = `/homework_commons/${workId}/reference_answer.json`
|
||||
|
||||
axios.get(url).then((result)=> {
|
||||
if (result.data.course_id) {
|
||||
|
||||
this.setState({
|
||||
...result.data
|
||||
}, () => {
|
||||
})
|
||||
this.props.initWorkDetailCommonState && this.props.initWorkDetailCommonState( Object.assign({...result.data}, {
|
||||
moduleName: '参考答案'
|
||||
}))
|
||||
}
|
||||
|
||||
}).catch((error)=>{
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
componentDidMount() {
|
||||
this.fetchData()
|
||||
try {
|
||||
this.props.triggerRef(this);
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
on('commonwork_fetch_all', this.fetchAllListener)
|
||||
}
|
||||
componentWillUnmount() {
|
||||
off('commonwork_fetch_all', this.fetchAllListener)
|
||||
}
|
||||
fetchAllListener = () => {
|
||||
this.fetchData()
|
||||
}
|
||||
|
||||
|
||||
render(){
|
||||
const dateFormat = 'YYYY-MM-DD HH:mm';
|
||||
|
||||
let {course_name, homework_name, search, page, loadingstate, homework_status, reference_answer,
|
||||
attachments
|
||||
} =this.state;
|
||||
|
||||
let courseId=this.props.match.params.coursesId;
|
||||
let category_id=this.props.match.params.category_id;
|
||||
let workId=this.props.match.params.workId;
|
||||
|
||||
const exportResultUrl = `/api/homework_commons/${workId}/works_list.xlsx`
|
||||
|
||||
return(
|
||||
<React.Fragment
|
||||
>
|
||||
{/* 内容区 */}
|
||||
<div className="padding40 memoContent new_li">
|
||||
{reference_answer ? <MarkdownToHtml content={reference_answer || "还未设置答案。"}></MarkdownToHtml> :
|
||||
reference_answer === undefined ? '' : ((!attachments || attachments.length == 0) && <NoneData></NoneData>)}
|
||||
|
||||
{ attachments && attachments.map((item) => {
|
||||
return ( <div className="color-grey">
|
||||
<a className="color-grey">
|
||||
<i className="font-14 color-green iconfont icon-fujian mr8" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a href={item.url} className="mr12" length="58">{item.title}</a>
|
||||
<span className="color-grey mt2 color-grey-6 font-12">{item.filesize}</span>
|
||||
</div> )
|
||||
}) }
|
||||
|
||||
</div>
|
||||
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default CommonWorkAnswer;
|
||||
@@ -0,0 +1,284 @@
|
||||
import '../katex.css';
|
||||
import '../css/Courses.css';
|
||||
import React,{Component} from "react";
|
||||
import {markdownToHTML, ImageLayer2 } from 'educoder';
|
||||
import axios from 'axios';
|
||||
import Modals from '../../modals/Modals';
|
||||
import moment from 'moment';
|
||||
import WorkDetailPageHeader from './common/WorkDetailPageHeader'
|
||||
import CommonWorkAppraiseReply from './reply/CommonWorkAppraiseReply'
|
||||
import CommonWorkAppraiseReviseAttachments from './CommonWorkAppraiseReviseAttachments'
|
||||
import LeaderIcon from './common/LeaderIcon';
|
||||
import showdown from 'showdown'
|
||||
import showdownKatex from 'showdown-katex'
|
||||
class CommonWorkAppraise extends Component{
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.state={
|
||||
course_name:"",
|
||||
homework_name:"",
|
||||
search: '',
|
||||
|
||||
|
||||
attachments: [],
|
||||
revise_attachments: [],
|
||||
}
|
||||
}
|
||||
getWork = () => {
|
||||
let workId =this.props.match.params.workId;
|
||||
let studentWorkId =this.props.match.params.studentWorkId;
|
||||
|
||||
// https://www.showdoc.cc/127895880302646?page_id=1957586480118445
|
||||
const url = `/student_works/${studentWorkId}.json`
|
||||
|
||||
axios.get(url).then((result)=> {
|
||||
if (result.data.course_id) {
|
||||
|
||||
this.setState({
|
||||
...result.data
|
||||
})
|
||||
}
|
||||
}).catch((error)=>{
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
exportMdtoHtml=(md)=> {
|
||||
let newmd=md;
|
||||
const converter = new showdown.Converter({
|
||||
extensions: [
|
||||
showdownKatex({
|
||||
// maybe you want katex to throwOnError
|
||||
throwOnError: true,
|
||||
// disable displayMode
|
||||
displayMode: false,
|
||||
// change errorColor to blue
|
||||
errorColor: '#1500ff',
|
||||
}),
|
||||
],
|
||||
});
|
||||
return converter.makeHtml(newmd);
|
||||
}
|
||||
getReviseAttachments = () => {
|
||||
let studentWorkId =this.props.match.params.studentWorkId;
|
||||
const url = `/student_works/${studentWorkId}/supply_attachments.json`;
|
||||
axios.get(url).then((result)=> {
|
||||
if (result.data.revise_attachments) {
|
||||
|
||||
this.setState({
|
||||
...result.data
|
||||
})
|
||||
}
|
||||
|
||||
}).catch((error)=>{
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (this.props.match.params.studentWorkId != prevProps.match.params.studentWorkId) {
|
||||
this.getWork();
|
||||
this.getReviseAttachments()
|
||||
this.commonWorkAppraiseReply && this.commonWorkAppraiseReply.fetchAllComments()
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getWork();
|
||||
this.getReviseAttachments()
|
||||
}
|
||||
|
||||
onAttachmentRemove = (id) => {
|
||||
this.setState({
|
||||
Modalstype:true,
|
||||
// Modalstopval:'确定要删除这个附件吗?',
|
||||
Modalstopval: '是否确认删除?',
|
||||
|
||||
ModalSave: ()=>this.deleteAttachment(id),
|
||||
ModalCancel:this.cancelAttachment
|
||||
})
|
||||
}
|
||||
deleteAttachment = (id) => {
|
||||
const url = `/attachments/${id}.json`
|
||||
axios.delete(url, {
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data) {
|
||||
const { status } = response.data;
|
||||
if (status == 0) {
|
||||
this.getWork()
|
||||
this.getReviseAttachments();
|
||||
this.cancelAttachment();
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
cancelAttachment=()=>{
|
||||
this.setState({
|
||||
Modalstype:false,
|
||||
Modalstopval:'',
|
||||
ModalSave:"",
|
||||
ModalCancel:""
|
||||
})
|
||||
}
|
||||
onReplySuccess = () => {
|
||||
this.getReviseAttachments();
|
||||
}
|
||||
|
||||
render(){
|
||||
const dateFormat = 'YYYY-MM-DD HH:mm';
|
||||
|
||||
let {course_name, homework_name, search, page, loadingstate, homework_status, reference_answer,
|
||||
attachments, homework_id, project_info, work_members, is_evaluation,
|
||||
description, update_user_name, commit_user_name, update_time, commit_time, author_name,
|
||||
revise_attachments, revise_reason, atta_update_user, atta_update_time, atta_update_user_login,
|
||||
Modalstype,Modalstopval,ModalCancel,ModalSave,loadtype, is_leader_work
|
||||
} =this.state;
|
||||
|
||||
let courseId=this.props.match.params.coursesId;
|
||||
let category_id=this.props.match.params.category_id;
|
||||
let studentWorkId=this.props.match.params.studentWorkId;
|
||||
const isAdmin = this.props.isAdmin()
|
||||
|
||||
document.title=course_name&&course_name;
|
||||
return(
|
||||
<WorkDetailPageHeader
|
||||
{...this.props} {...this.state}
|
||||
noTab={true}
|
||||
moduleName={'作业详情'}
|
||||
getReviseAttachments={this.getReviseAttachments}
|
||||
>
|
||||
{/*提示*/}
|
||||
<Modals
|
||||
modalsType={Modalstype}
|
||||
modalsTopval={Modalstopval}
|
||||
modalCancel={ModalCancel}
|
||||
modalSave={ModalSave}
|
||||
loadtype={loadtype}
|
||||
/>
|
||||
{/* 内容区 */}
|
||||
{/* <div className="padding40 memoContent new_li">
|
||||
</div> */}
|
||||
|
||||
<div className={"appraise imageLayerParent "} style={{}}>
|
||||
|
||||
<style>{`
|
||||
.workAppraise>div:last-child {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
`}</style>
|
||||
<ImageLayer2 parentSel=".workAppraise" childSel="a.imageTarget"></ImageLayer2>
|
||||
<div className={"workAppraise"}>
|
||||
{(description || (attachments && attachments.length != 0)) && <div className={"stud-class-set edu-back-white padding20-30"}>
|
||||
<div className={"color-grey-6 mb15 font-16"}>
|
||||
内容
|
||||
</div>
|
||||
<div className="markdown-body ml20" dangerouslySetInnerHTML={{__html: markdownToHTML(description)}}>
|
||||
</div>
|
||||
|
||||
{attachments.map((item,key)=>{
|
||||
return(
|
||||
<div className="color-grey" key={key}>
|
||||
<a className="color-grey ml20">
|
||||
<i className="font-14 color-green iconfont icon-fujian mr8" aria-hidden="true"></i>
|
||||
</a>
|
||||
|
||||
<a href={item.url}
|
||||
className="mr12 color9B9B imageTarget" length="58" title={`${item.title && item.title.length > 40 ? item.title : ''}`}>
|
||||
{item.title}
|
||||
</a>
|
||||
<span className="color656565 mt2 color-grey-6 font-12 mr8">{item.filesize}</span>
|
||||
{/*{item.delete===true?<i className="font-14 iconfont icon-guanbi " id={item.id} aria-hidden="true" onClick={()=>this.onAttachmentRemove(item.id)}></i>:""}*/}
|
||||
{item.delete===true?<i className="font-14 iconfont icon-guanbi " id={item.id} aria-hidden="true" onClick={()=>this.onAttachmentRemove(item.id)}></i>:""}
|
||||
{/* style={{display: 'none'}} */}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
|
||||
<div className={"color-grey-6 h20 ml20"}>
|
||||
{ update_time &&
|
||||
<React.Fragment>
|
||||
<span className={"color9B9B fr"}>更新</span>
|
||||
<span className={"fr font-14 mr10 ml10"}>{update_user_name}</span>
|
||||
<span className={"color9B9B fr"}>
|
||||
{moment(update_time).format('YYYY-MM-DD HH:mm')==="Invalid date"?"":moment(update_time).format('YYYY-MM-DD HH:mm')}
|
||||
</span>
|
||||
</React.Fragment> }
|
||||
|
||||
{ commit_time &&
|
||||
<React.Fragment>
|
||||
<span className={"color9B9B fr mr30"}>提交</span>
|
||||
<span className={"fr font-14 mr10 ml10"}>{commit_user_name}</span>
|
||||
<span className={" color9B9B fr"}>
|
||||
{moment(commit_time).format('YYYY-MM-DD HH:mm')==="Invalid date"?"":moment(commit_time).format('YYYY-MM-DD HH:mm')}
|
||||
</span>
|
||||
</React.Fragment> }
|
||||
</div>
|
||||
|
||||
</div> }
|
||||
|
||||
<CommonWorkAppraiseReviseAttachments {...this.state}
|
||||
onAttachmentRemove={this.onAttachmentRemove}
|
||||
></CommonWorkAppraiseReviseAttachments>
|
||||
|
||||
{is_evaluation != true && project_info && project_info.name && <div className={"stud-class-set bor-top-greyE edu-back-white padding20-30"}>
|
||||
<div className={"color-grey-6 mb10"}>
|
||||
关联项目
|
||||
</div>
|
||||
<div className={"ml20"}>
|
||||
<a className="color-blue" href={`/projects/${project_info.id}`}>{project_info.name}</a>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
{is_evaluation != true && work_members && !!work_members.length && <div className={"stud-class-set bor-top-greyE edu-back-white padding20-30"}>
|
||||
<div className={"color-grey-6 mb10"}>
|
||||
全部组员
|
||||
</div>
|
||||
<div className={"ml20 color-grey-6"}>
|
||||
<div className="">
|
||||
当前组员:{author_name} {is_leader_work && <LeaderIcon small={true} ></LeaderIcon>}
|
||||
</div>
|
||||
<div>
|
||||
其他组员:
|
||||
{work_members.map((item, index) => {
|
||||
return <React.Fragment>
|
||||
{isAdmin ?
|
||||
<a className={`color-blue ${index == 0 ? '' : 'ml12'}`} href="javascript:void(0)"
|
||||
onClick={() => this.props.toWorkDetailPage(this.props.match.params, null, item.work_id)}
|
||||
>
|
||||
{item.user_name}
|
||||
</a> : <span className={`${index == 0 ? '' : 'ml12'}`} >{item.user_name}</span>}
|
||||
{item.is_leader && <LeaderIcon small={true} ></LeaderIcon>}
|
||||
</React.Fragment>
|
||||
})}
|
||||
</div>
|
||||
{isAdmin && <div className="font-12 color-grey-9">
|
||||
<span >温馨提示:</span>
|
||||
点击其他组员的姓名,可以快速评阅TA的作品
|
||||
</div>}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
{/* task_type={datalist&&datalist.task_type} */}
|
||||
<CommonWorkAppraiseReply {...this.props} task_id={studentWorkId}
|
||||
onReplySuccess={this.onReplySuccess} {...this.state}
|
||||
wrappedComponentRef={(ref) => {this.commonWorkAppraiseReply = ref}}
|
||||
></CommonWorkAppraiseReply>
|
||||
|
||||
</div>
|
||||
|
||||
</WorkDetailPageHeader>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default CommonWorkAppraise;
|
||||
@@ -0,0 +1,52 @@
|
||||
import React, { useState } from 'react'
|
||||
import moment from 'moment'
|
||||
// import Example from './TestHooks'
|
||||
function CommonWorkAppraiseReviseAttachments(props) {
|
||||
const { revise_attachments, revise_reason, atta_update_time, atta_update_user} = props
|
||||
if (!revise_attachments) return ''
|
||||
return (
|
||||
<React.Fragment>
|
||||
{/* {Example()} */}
|
||||
{revise_attachments.length===0?"":<div className={"stud-class-set bor-top-greyE padding20-30 edu-back-white"}>
|
||||
<style>{`
|
||||
.color-grey:hover i {
|
||||
display: inline !important;
|
||||
}
|
||||
`}</style>
|
||||
<div className={"color-grey-6 mb10 font-16"}>
|
||||
补交附件
|
||||
</div>
|
||||
|
||||
{/* {age} */}
|
||||
|
||||
<div className={"ml20"}>
|
||||
{revise_reason}
|
||||
</div>
|
||||
{revise_attachments.map((item,key)=>{
|
||||
return(
|
||||
<div className="color-grey" key={key}>
|
||||
<a className="color-grey ml20">
|
||||
<i className="font-14 color-green iconfont icon-fujian mr8" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a href={item.url}
|
||||
className="mr12 color9B9B imageTarget" length="58">
|
||||
{item.title}
|
||||
</a>
|
||||
<span className="color656565 mt2 color-grey-6 font-12 mr8">{item.filesize}</span>
|
||||
{item.delete===true?<i className="font-14 iconfont icon-guanbi " style={{display: 'none'}} id={item.id} aria-hidden="true" onClick={()=>props.onAttachmentRemove(item.id)}></i>:""}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<div className={"color-grey-6 clearfix lineh-25 ml20"}>
|
||||
<span className={"color9B9B fr"}>更新</span>
|
||||
<span className={"fr font-13 mr10 ml10"}>{atta_update_user}</span>
|
||||
<span className={"color9B9B fr"}>
|
||||
{moment(atta_update_time).format('YYYY-MM-DD HH:mm')==="Invalid date"?"":moment(atta_update_time).format('YYYY-MM-DD HH:mm')}
|
||||
</span>
|
||||
</div>
|
||||
</div>}
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
}
|
||||
export default CommonWorkAppraiseReviseAttachments;
|
||||
@@ -0,0 +1,482 @@
|
||||
import React, { Component } from 'react';
|
||||
import { getRandomNumber } from 'educoder';
|
||||
import {Link} from 'react-router-dom';
|
||||
import {BrowserRouter as Router,Route,Switch} from 'react-router-dom';
|
||||
import Loadable from 'react-loadable';
|
||||
import Loading from '../../../Loading';
|
||||
import { WordsBtn, MarkdownToHtml, trigger, queryString, getRandomcode } from 'educoder';
|
||||
import axios from 'axios';
|
||||
import CoursesListType from '../coursesPublic/CoursesListType';
|
||||
import AccessoryModal from "../coursesPublic/AccessoryModal";
|
||||
import PublishRightnow from './PublishRightnow'
|
||||
import '../css/Courses.css'
|
||||
import CBreadcrumb from '../common/CBreadcrumb'
|
||||
import DownloadMessageysl from "../../modals/DownloadMessageysl";
|
||||
import ConnectProject from './ConnectProject'
|
||||
import { Spin } from 'antd'
|
||||
|
||||
//引入对应跳转的组件
|
||||
|
||||
//新建分组/普通作业
|
||||
const NewWork = Loadable({
|
||||
loader: () => import('./NewWork'),
|
||||
loading:Loading,
|
||||
})
|
||||
|
||||
const CommonWorkSetting = Loadable({
|
||||
loader: () => import('./CommonWorkSetting'),
|
||||
loading:Loading,
|
||||
})
|
||||
//普通作业列表
|
||||
const CommonWorkList = Loadable({
|
||||
loader: () => import('./CommonWorkList'),
|
||||
loading:Loading,
|
||||
})
|
||||
const CommonWorkQuestion = Loadable({
|
||||
loader: () => import('./CommonWorkQuestion'),
|
||||
loading:Loading,
|
||||
})
|
||||
const CommonWorkAnswer = Loadable({
|
||||
loader: () => import('./CommonWorkAnswer'),
|
||||
loading:Loading,
|
||||
})
|
||||
const CommonWorkAppraise = Loadable({
|
||||
loader: () => import('./CommonWorkAppraise'),
|
||||
loading:Loading,
|
||||
})
|
||||
|
||||
const CommonWorkPost = Loadable({
|
||||
loader: () => import('./CommonWorkPost'),
|
||||
loading:Loading,
|
||||
})
|
||||
|
||||
const CommonWork = Loadable({
|
||||
loader: () => import('./commonWork'),
|
||||
loading:Loading,
|
||||
})
|
||||
class CommonWorkDetailIndex extends Component{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.publishModal = React.createRef();
|
||||
this.endModal = React.createRef();
|
||||
this.state = {
|
||||
DownloadType:false,
|
||||
DownloadMessageval:undefined,
|
||||
donwloading:false,
|
||||
}
|
||||
}
|
||||
initWorkDetailCommonState = (data) => {
|
||||
this.setState({
|
||||
...data
|
||||
})
|
||||
}
|
||||
goback = () => {
|
||||
let workId=this.props.match.params.workId;
|
||||
//
|
||||
if ( window.location.pathname.indexOf('appraise') == -1) {
|
||||
let category_id= this.state.category.category_id;
|
||||
this.props.toListPage(this.props.match.params, category_id)
|
||||
} else {
|
||||
this.props.toWorkListPage(this.props.match.params, workId)
|
||||
}
|
||||
// this.props.history.goBack()
|
||||
}
|
||||
|
||||
// 补交附件
|
||||
Cancelvisible=()=>{
|
||||
this.setState({
|
||||
accessoryVisible:false
|
||||
})
|
||||
}
|
||||
|
||||
addAccessory=()=>{
|
||||
this.setState({
|
||||
accessoryVisible:true
|
||||
})
|
||||
}
|
||||
setupdate = () => {
|
||||
|
||||
}
|
||||
doWhenSuccess = () => {
|
||||
trigger('commonwork_fetch_all')
|
||||
}
|
||||
|
||||
/// 确认是否下载
|
||||
confirmysl(url){
|
||||
axios.get(url+ '&export=true').then((response) => {
|
||||
if(response===undefined){
|
||||
return
|
||||
}
|
||||
if(response.data.status&&response.data.status===-1){
|
||||
|
||||
}else if(response.data.status&&response.data.status===-2){
|
||||
if(response.data.message === "100"){
|
||||
// 已超出文件导出的上限数量(100 ),建议:
|
||||
|
||||
this.setState({
|
||||
DownloadType:true,
|
||||
DownloadMessageval:100
|
||||
})
|
||||
}else {
|
||||
//因附件资料超过500M
|
||||
this.setState({
|
||||
DownloadType:true,
|
||||
DownloadMessageval:500
|
||||
})
|
||||
}
|
||||
}else {
|
||||
this.props.slowDownload(getRandomcode(url))
|
||||
|
||||
// this.props.showNotification(`正在下载中`);
|
||||
// this.setState({ donwloading: true })
|
||||
// downloadFile({
|
||||
// url: url,
|
||||
// successCallback: (url) => {
|
||||
// this.setState({ donwloading: false })
|
||||
// console.log('successCallback')
|
||||
// },
|
||||
// failCallback: (responseHtml, url) => {
|
||||
// this.setState({ donwloading: false })
|
||||
// console.log('failCallback')
|
||||
// }
|
||||
// })
|
||||
// window.open("/api"+url, '_blank');
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
});
|
||||
}
|
||||
|
||||
Downloadcal=()=>{
|
||||
this.setState({
|
||||
DownloadType:false,
|
||||
DownloadMessageval:undefined
|
||||
})
|
||||
}
|
||||
bindRef = ref => { this.child = ref };
|
||||
|
||||
// 关联项目
|
||||
openConnectionProject = (work) => {
|
||||
this.refs['connectProject'].openConnectionProject(work)
|
||||
}
|
||||
connectSuccess = () => {
|
||||
this.child.fetchData && this.child.fetchData()
|
||||
}
|
||||
|
||||
cancelConnectionProject = (work) => {
|
||||
let workId=this.props.match.params.workId;
|
||||
let courseId=this.props.match.params.coursesId;
|
||||
|
||||
const url = `/homework_commons/${work.homework_id}/student_works/cancel_relate_project.json`
|
||||
axios.get(url).then((response)=> {
|
||||
if (response.data.status == 0) {
|
||||
this.child.fetchData && this.child.fetchData()
|
||||
|
||||
this.props.showNotification('取消关联成功')
|
||||
}
|
||||
}).catch((error)=>{
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
// 关联项目 END
|
||||
|
||||
render() {
|
||||
let {course_name, homework_name, homework_status, noTab
|
||||
, view_answer, author_name, category, work_id
|
||||
|
||||
, end_immediately, publish_immediately, work_statuses, accessoryVisible
|
||||
} =this.state;
|
||||
const { current_user } = this.props
|
||||
|
||||
let courseId=this.props.match.params.coursesId;
|
||||
let category_id= category && category.category_id;
|
||||
let category_name= category && category.category_name;
|
||||
|
||||
let workId=this.props.match.params.workId;
|
||||
const studentWorkId = this.props.match.params.studentWorkId
|
||||
|
||||
const isGroup = this.props.isGroup()
|
||||
const moduleName = !isGroup? "普通作业":"分组作业";
|
||||
const moduleEngName = this.props.getModuleName()
|
||||
|
||||
const childModuleName = this.state.moduleName
|
||||
const commonHandler = {
|
||||
initWorkDetailCommonState: this.initWorkDetailCommonState,
|
||||
triggerRef: this.bindRef
|
||||
}
|
||||
const isAdmin = this.props.isAdmin()
|
||||
|
||||
|
||||
let exportParams = {}
|
||||
const isListModule = childModuleName == '作品列表';
|
||||
// 是列表页
|
||||
let params = {}
|
||||
if (isListModule) {
|
||||
// TODO
|
||||
if(this.child && this.child._getRequestParams) {
|
||||
params = this.child._getRequestParams() !== undefined ? this.child._getRequestParams() : {};
|
||||
}
|
||||
}
|
||||
// console.log("普通作业176176176");
|
||||
// console.log(params);
|
||||
let exportUrl = `/homework_commons/${workId}/works_list.zip?${queryString.stringify(params)}`
|
||||
let exportResultUrl = `/homework_commons/${workId}/works_list.xlsx?${queryString.stringify(params)}`
|
||||
document.title=course_name === undefined ? "" : course_name;
|
||||
return (
|
||||
<div>
|
||||
<PublishRightnow ref={this.publishModal} showActionButton={false} {...this.props} checkBoxValues={[workId]}
|
||||
isPublish={true} doWhenSuccess={this.doWhenSuccess} checkBeforePost={this.saveWorkSetting}
|
||||
onToPublishClick={this.onToPublishClick}
|
||||
></PublishRightnow>
|
||||
<DownloadMessageysl
|
||||
{...this.props}
|
||||
value={this.state.DownloadMessageval}
|
||||
modalCancel={this.Downloadcal}
|
||||
modalsType={this.state.DownloadType}
|
||||
/>
|
||||
<PublishRightnow ref={this.endModal} showActionButton={false} {...this.props} checkBoxValues={[workId]}
|
||||
isPublish={false} doWhenSuccess={this.doWhenSuccess}></PublishRightnow>
|
||||
|
||||
|
||||
<div className="newMain clearfix worklist1">
|
||||
<div className={"educontent mt20"}>
|
||||
<style>{`
|
||||
.memoContent {
|
||||
background: #fff;
|
||||
}
|
||||
`}</style>
|
||||
{current_user && <CBreadcrumb items={[
|
||||
{ to: current_user&¤t_user.first_category_url , name: course_name},
|
||||
{ to: `/courses/${courseId}/${moduleEngName}/${category_id}`, name: category_name },
|
||||
window.location.pathname.indexOf('appraise') == -1 ? { } : { to: `/courses/${courseId}/${moduleEngName}/${workId}/list`, name: '作业详情' },
|
||||
// 1. 与上一条联动,当匿评他人作品时,TA人作品的作者真实姓名切换为“匿名”
|
||||
window.location.pathname.indexOf('appraise') == -1 ? { name: '作业详情' } : { name: author_name },
|
||||
// window.location.pathname.indexOf('appraise') == -1 ? { } : { to: `/courses/${courseId}/${moduleEngName}/${workId}/list`, name: '作品列表' },
|
||||
// { name: childModuleName }
|
||||
]}></CBreadcrumb>}
|
||||
|
||||
<div style={{ width:'100%',height:'52px'}} >
|
||||
<span className=" fl color-black summaryname" title={`${homework_name && homework_name.length > 36 ? homework_name : ''}`}
|
||||
style={{height: 'auto'}}
|
||||
>
|
||||
{homework_name}
|
||||
{/* <Link to={"/courses/"+courseId+"/graduation"+"/graduation_tasks/"}>{homework_name}</Link> */}
|
||||
</span>
|
||||
<CoursesListType
|
||||
typelist={homework_status}
|
||||
typesylename={"mt12"}
|
||||
/>
|
||||
|
||||
|
||||
{category && <a className="color-grey-6 fr font-16 ml30 mt5 mr20" onClick={this.goback} style={{ marginRight: '26px'}}>返回</a>}
|
||||
|
||||
{this.state.update_atta &&
|
||||
<React.Fragment>
|
||||
{this.state.accessoryVisible===true? <AccessoryModal
|
||||
{...this.props}
|
||||
modalname={"补交附件"}
|
||||
visible={this.state.accessoryVisible}
|
||||
Cancelname={"取消"}
|
||||
Savesname={"确认"}
|
||||
Cancel={this.Cancelvisible}
|
||||
setupdate={this.setupdate}
|
||||
seeworks={undefined}
|
||||
reviseAttachmentUrl={`/student_works/${work_id || studentWorkId}/revise_attachment.json`}
|
||||
/>:""}
|
||||
<a className={"fr color-blue font-16 "} href={"javascript:void(0)"}
|
||||
onClick={this.addAccessory} style={{ 'marginTop': '-4px' }}
|
||||
>补交附件</a>
|
||||
</React.Fragment>
|
||||
|
||||
}
|
||||
</div>
|
||||
|
||||
{ noTab !== true && <div className="stud-class-set bor-bottom-greyE floatSpinParent">
|
||||
<div className="mt10 clearfix edu-back-white poll_list pl5">
|
||||
<Link
|
||||
onClick={() => this.setState({moduleName: '作品列表'})}
|
||||
className={`${isListModule ? 'active' : '' } `}
|
||||
to={`/courses/${courseId}/${moduleEngName}/${workId}/list`}>作品列表</Link>
|
||||
<Link
|
||||
onClick={() => this.setState({moduleName: '作业描述'})}
|
||||
className={`${childModuleName == '作业描述' ? 'active' : '' } `}
|
||||
to={`/courses/${courseId}/${moduleEngName}/${workId}/question`}>作业描述</Link>
|
||||
{view_answer == true && <Link
|
||||
onClick={() => this.setState({moduleName: '参考答案'})}
|
||||
className={`${childModuleName == '参考答案' ? 'active' : '' } `}
|
||||
to={`/courses/${courseId}/${moduleEngName}/${workId}/answer`}>参考答案</Link>}
|
||||
<Link
|
||||
onClick={() => this.setState({moduleName: '设置'})}
|
||||
className={`${childModuleName == '设置' ? 'active' : '' } `}
|
||||
style={{paddingLeft:this.props.isAdmin()?'38px':'20px'}}
|
||||
to={`/courses/${courseId}/${moduleEngName}/${workId}/setting`}>{this.props.isAdmin()?"设置":"得分规则"}</Link>
|
||||
|
||||
|
||||
{/* { this.props.tabRightComponents } */}
|
||||
<React.Fragment>
|
||||
<style>{`
|
||||
.drop_down_menu li a {
|
||||
padding: 0px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.drop_down_menu {
|
||||
width: 121px;
|
||||
}
|
||||
.drop_down_menu li {
|
||||
overflow: visible;
|
||||
width: 121px;
|
||||
}
|
||||
.drop_down_menu, .drop_down_normal {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.floatSpinParent .ant-spin-nested-loading {
|
||||
float: right;
|
||||
}
|
||||
`}</style>
|
||||
{this.props.isAdmin()? <Spin spinning={this.state.donwloading} style={{ }}>
|
||||
<li className="li_line drop_down fr color-blue font-16 mt20" style={{"padding":"0 20px"}}>
|
||||
导出<i className="iconfont icon-xiajiantou font-12 ml2"></i>
|
||||
<ul className="drop_down_menu" style={{"right":"-34px","left":"unset","height":"auto"}}>
|
||||
<li>
|
||||
|
||||
<a href={"javascript:void(0)"} className="color-dark"
|
||||
onClick={() => this.confirmysl(exportResultUrl)}
|
||||
>导出成绩</a>
|
||||
|
||||
</li>
|
||||
<li>
|
||||
<a href={"javascript:void(0)"} className="color-dark"
|
||||
onClick={() => this.confirmysl(exportUrl)}
|
||||
>导出作品附件</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</Spin>:""}
|
||||
|
||||
{/* {isAdmin && <a className={"fr color-blue font-16"} href={exportUrl}>导出作品附件</a>}
|
||||
{isAdmin && <a className={"fr color-blue font-16"} href={exportResultUrl}>导出成绩</a>} */}
|
||||
{/*<a className={"fr color-blue font-16"}>导出</a>*/}
|
||||
{end_immediately && <a className={"fr color-blue font-16"} onClick={() => { this.endModal.current.open() } }>立即截止</a>}
|
||||
{publish_immediately && <a className={"fr color-blue font-16"} onClick={() => { this.publishModal.current.open() } } >立即发布</a>}
|
||||
|
||||
{/*<a className={"fr color-blue font-16"}>项目在线质量检测</a>*/}
|
||||
{isAdmin && <a className={"fr color-blue font-16"} onClick={() => this.props.toEditPage(this.props.match.params, workId)}>编辑作业</a>}
|
||||
|
||||
{ //
|
||||
work_statuses && work_statuses.indexOf('关联项目') != -1 &&
|
||||
<React.Fragment>
|
||||
<ConnectProject ref="connectProject" {...this.props} connectSuccess={this.connectSuccess}></ConnectProject>
|
||||
<WordsBtn style="blue" className={` font-16 fr`} onClick={() => this.openConnectionProject({ homework_id: workId })}>关联项目</WordsBtn>
|
||||
<WordsBtn style="blue" className={` font-16 fr`} onClick={() => this.props.toCreateProject()}>创建项目</WordsBtn>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
{ //
|
||||
work_statuses && work_statuses.indexOf('取消关联') != -1 &&
|
||||
<WordsBtn style="blue" className={` font-16 fr`} onClick={() => this.cancelConnectionProject( {homework_id: workId} )}>取消关联</WordsBtn>
|
||||
}
|
||||
|
||||
{work_statuses && work_statuses.indexOf('提交作品') != -1 && <a className={"fr color-blue font-16"} href={"javascript:void(0)"}
|
||||
onClick={() => { this.props.toWorkPostPage(this.props.match.params)}}
|
||||
>提交作品</a>}
|
||||
|
||||
{ work_statuses && work_statuses.indexOf('补交作品') != -1 &&
|
||||
<a className={"fr color-blue font-16"} href={"javascript:void(0)"}
|
||||
onClick={() => { this.props.toWorkPostPage(this.props.match.params)}}>
|
||||
补交作品</a> }
|
||||
|
||||
{work_statuses && work_statuses.indexOf('修改作品') != -1 && <a className={"fr color-blue font-16"} href={"javascript:void(0)"}
|
||||
onClick={() => { this.props.toWorkPostPage(this.props.match.params, null, true, work_id)}}
|
||||
>修改作品</a>}
|
||||
{work_statuses && work_statuses.indexOf('补交附件') != -1 &&
|
||||
<React.Fragment>
|
||||
<AccessoryModal
|
||||
{...this.props}
|
||||
modalname={"补交附件"}
|
||||
visible={accessoryVisible}
|
||||
Cancelname={"取消"}
|
||||
Savesname={"确认"}
|
||||
Cancel={this.Cancelvisible}
|
||||
setupdate={this.setupdate}
|
||||
reviseAttachmentUrl={`/student_works/${work_id}/revise_attachment.json`}
|
||||
/>
|
||||
<a className={"fr color-blue font-16"} href={"javascript:void(0)"}
|
||||
onClick={this.addAccessory}
|
||||
>补交附件</a>
|
||||
</React.Fragment>
|
||||
|
||||
}
|
||||
</React.Fragment>
|
||||
|
||||
</div>
|
||||
</div> }
|
||||
|
||||
{/* 内容区 */}
|
||||
<Switch {...this.props}>
|
||||
|
||||
{/* --------------------------------------------------------------------- */}
|
||||
|
||||
{/* 作业设置 */}
|
||||
{/* http://localhost:3007/courses/1309/homework/9300/setting */}
|
||||
<Route exact path="/courses/:coursesId/common_homeworks/:workId/setting"
|
||||
render={
|
||||
(props) => (<CommonWorkSetting {...this.props} {...props} {...this.state} {...commonHandler}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 作品列表 */}
|
||||
<Route exact path="/courses/:coursesId/common_homeworks/:workId/list"
|
||||
render={
|
||||
(props) => (<CommonWorkList ref="commonWorkList" triggerRef={this.bindRef} {...this.props} {...props} {...this.state} {...commonHandler}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 作业问答 */}
|
||||
<Route exact path="/courses/:coursesId/common_homeworks/:workId/question"
|
||||
render={
|
||||
(props) => (<CommonWorkQuestion {...this.props} {...props} {...this.state} {...commonHandler}/>)
|
||||
}
|
||||
></Route>
|
||||
<Route exact path="/courses/:coursesId/common_homeworks/:workId/answer"
|
||||
render={
|
||||
(props) => (<CommonWorkAnswer {...this.props} {...props} {...this.state} {...commonHandler}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
<Route exact path="/courses/:coursesId/group_homeworks/:workId/setting"
|
||||
render={
|
||||
(props) => (<CommonWorkSetting {...this.props} {...props} {...this.state} {...commonHandler}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 作品列表 */}
|
||||
<Route exact path="/courses/:coursesId/group_homeworks/:workId/list"
|
||||
render={
|
||||
(props) => (<CommonWorkList triggerRef={this.bindRef} {...this.props} {...props} {...this.state} {...commonHandler}/>)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 作业问答 */}
|
||||
<Route exact path="/courses/:coursesId/group_homeworks/:workId/question"
|
||||
render={
|
||||
(props) => (<CommonWorkQuestion {...this.props} {...props} {...this.state} {...commonHandler}/>)
|
||||
}
|
||||
></Route>
|
||||
<Route exact path="/courses/:coursesId/group_homeworks/:workId/answer"
|
||||
render={
|
||||
(props) => (<CommonWorkAnswer {...this.props} {...props} {...this.state} {...commonHandler}/>)
|
||||
}
|
||||
></Route>
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default ( CommonWorkDetailIndex) ;
|
||||
@@ -0,0 +1,299 @@
|
||||
import React,{ Component } from "react";
|
||||
import { Input,Checkbox, Modal,Menu, Tooltip, Pagination } from "antd";
|
||||
|
||||
import '../css/members.css'
|
||||
import '../css/busyWork.css'
|
||||
import CoursesListType from '../coursesPublic/CoursesListType'
|
||||
import { WordsBtn } from 'educoder'
|
||||
import AccessoryModal2 from '../coursesPublic/AccessoryModal2'
|
||||
import AccessoryModal from '../coursesPublic/AccessoryModal'
|
||||
import axios from 'axios'
|
||||
class CommonWorkItem extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state = {
|
||||
aModalVisible: false
|
||||
}
|
||||
}
|
||||
onItemClick = (item) => {
|
||||
|
||||
if(this.props.checkIfLogin()===false){
|
||||
this.props.showLoginDialog()
|
||||
return
|
||||
}
|
||||
// if(this.props.checkIfProfileCompleted()===false){
|
||||
// this.setState({
|
||||
// AccountProfiletype:true
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
// if(this.props.checkIfProfessionalCertification()===false){
|
||||
// this.props.showProfileCompleteDialog()
|
||||
// return
|
||||
// }
|
||||
|
||||
const isStudent = this.props.isStudent()
|
||||
if (isStudent) {
|
||||
this.props.toWorkQuestionPage(this.props.match.params, item.homework_id)
|
||||
} else {
|
||||
this.props.toWorkListPage(this.props.match.params, item.homework_id)
|
||||
}
|
||||
}
|
||||
sendMoreAttachment = (item) => {
|
||||
this.handleItem = item;
|
||||
const url = `/student_works/${item.work_id}/supply_attachments.json`
|
||||
axios.get(url, {
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.revise_attachments) {
|
||||
// response.data.revise_attachments = [
|
||||
// {
|
||||
// "id": 8686,
|
||||
// "title": "lasdl",
|
||||
// "filesize": 12323,
|
||||
// "description": "1原因3",
|
||||
// "url": "/attachments/:id/download",
|
||||
// "delete": true
|
||||
// }
|
||||
// ]
|
||||
// response.data.revise_reason = 'qweqweqweqe';
|
||||
|
||||
// revise_reason revise_attachments 传给modal
|
||||
// attach to fileList
|
||||
const fileList = response.data.revise_attachments.map(item => {
|
||||
return {
|
||||
id: item.id,
|
||||
uid: item.id,
|
||||
name: item.title,
|
||||
url: item.url,
|
||||
status: 'done',
|
||||
|
||||
description: item.description,
|
||||
delete: item.delete,
|
||||
filesize: item.filesize,
|
||||
}
|
||||
})
|
||||
|
||||
this.setState({ aModalVisible: true, fileList, revise_reason: response.data.revise_reason })
|
||||
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
toProductPage = (item) => {
|
||||
|
||||
}
|
||||
// Cancelvisible = () => {
|
||||
// this.setState({ aModalVisible: false })
|
||||
// }
|
||||
onAccessoryModalSaves = (newfileList, description) => {
|
||||
const url = `/student_works/${this.handleItem.work_id}/revise_attachment.json`
|
||||
axios.post(url, {
|
||||
"description": description,
|
||||
"attachment_ids": newfileList
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.props.showNotification('提交成功')
|
||||
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
// 补交附件
|
||||
Cancelvisible=()=>{
|
||||
this.setState({
|
||||
accessoryVisible:false
|
||||
})
|
||||
}
|
||||
addAccessory=()=>{
|
||||
this.setState({
|
||||
accessoryVisible:true
|
||||
})
|
||||
}
|
||||
setupdate = () => {
|
||||
}
|
||||
|
||||
render(){
|
||||
let { mainList,workType }=this.props;
|
||||
const { aModalVisible, fileList, revise_reason } = this.state
|
||||
let coursesId = this.props.match.params.coursesId;
|
||||
|
||||
const isStudent = this.props.isStudent()
|
||||
const isAdmin = this.props.isAdmin()
|
||||
const isAdminOrStudent = this.props.isAdminOrStudent()
|
||||
return(
|
||||
<div className="workList">
|
||||
{/* <AccessoryModal2
|
||||
visible={aModalVisible}
|
||||
Cancel={this.Cancelvisible}
|
||||
Saves={this.onAccessoryModalSaves}
|
||||
fileList={fileList}
|
||||
description={revise_reason}
|
||||
></AccessoryModal2> */}
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.comnonwidth580{
|
||||
max-width: 580px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
a:hover{
|
||||
color: #4cacff;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>
|
||||
{
|
||||
mainList && mainList.homeworks && mainList.homeworks.length>0 && mainList.homeworks.map((item,index)=>{
|
||||
let canNotLink = !isAdminOrStudent && item.private_icon == true
|
||||
return(
|
||||
<div className="mt20 edu-back-white padding02010" key={index} >
|
||||
<div className="clearfix">
|
||||
<div className="workList_Item">
|
||||
{
|
||||
mainList && isAdmin &&
|
||||
<span className="fl mr12"><Checkbox value={item.homework_id} key={item.homework_id}></Checkbox></span>
|
||||
}
|
||||
|
||||
<div className="flex1" onClick={() => this.props.onItemClick(Object.assign({}, item, {id: item.homework_id})) }>
|
||||
<p className="clearfix mb20">
|
||||
{canNotLink?<span className={"fl font-16 font-bd mt2 comnonwidth580 pointer color-grey-name"}
|
||||
title={ canNotLink ? "私有属性,非课堂成员不能访问" : item.name}
|
||||
>
|
||||
{item.name}
|
||||
</span>:<a className={"fl font-16 font-bd mt2 comnonwidth580 pointer"}
|
||||
onClick={ canNotLink ? () => {} : () => this.onItemClick(item)}
|
||||
title={item.name}
|
||||
>{item.name}</a>}
|
||||
{/* 只有非课堂成员且作业是私有的情况下才会为true */}
|
||||
{
|
||||
item.private_icon===true ?
|
||||
(<Tooltip title={"私有属性,非课堂成员不能访问"} placement="bottom" >
|
||||
<i className="iconfont icon-guansuo color-grey-c ml10 font-16 fl"></i>
|
||||
</Tooltip>) : ""
|
||||
}
|
||||
|
||||
<span className="fl">
|
||||
<CoursesListType typelist={item.status} />
|
||||
</span>
|
||||
{/* {
|
||||
mainList && isAdmin &&
|
||||
<li className="fr drop_down">
|
||||
<i className="iconfont icon-caidan font-16 color-grey-c"></i>
|
||||
<ul className="drop_down_normal" style={{ textAlign: 'center'}}>
|
||||
<li onClick={ () => { this.props.toEditPage(this.props.match.params, item.homework_id) }}>
|
||||
<a href={`javascript:void(0)`} >编辑</a>
|
||||
</li>
|
||||
<li onClick={ () => { this.props.toWorkSettingPage(this.props.match.params, item.homework_id) }}>
|
||||
<a href={`javascript:void(0)`}
|
||||
>设置</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
} */}
|
||||
</p>
|
||||
<p className="color-grey-9 clearfix">
|
||||
{ item.author && <span className="mr20 fl">{item.author}</span> }
|
||||
{item.commit_count===undefined?"":<span className="mr20 fl">{item.commit_count} 已交</span>}
|
||||
{item.uncommit_count===undefined?"":<span className="mr20 fl">{item.uncommit_count} 未交</span>}
|
||||
{
|
||||
item.status_time!="" &&
|
||||
|
||||
<span className="mr20 fl">{item.status_time}</span>
|
||||
|
||||
}
|
||||
{/*<Tooltip placement="bottom" title={ item.status.indexOf('提交中') != -1 ? '提交剩余时间' :*/}
|
||||
{/* item.status.indexOf('补交中') != -1 ? '补交剩余时间' :*/}
|
||||
{/* item.status.indexOf('申诉中') != -1 ? '申诉剩余时间' :*/}
|
||||
{/* item.status.indexOf('匿评中') != -1 ? '匿评剩余时间' :*/}
|
||||
{/* item.status.indexOf('匿评申诉中') != -1 ? '匿评申诉剩余时间' : ''}>*/}
|
||||
{/*</Tooltip>*/}
|
||||
{isAdmin && <div className="fr">
|
||||
<WordsBtn style="blue" className={"fl font-16 ml28"}
|
||||
onClick={ canNotLink ? () => {} : () => this.onItemClick(item)}
|
||||
>查看详情</WordsBtn>
|
||||
<WordsBtn style="blue" className="fl font-16 ml28" onClick={ () => { this.props.toEditPage(this.props.match.params, item.homework_id) }}>编辑</WordsBtn>
|
||||
<WordsBtn style="blue" className="fl font-16 ml28" onClick={ () => { this.props.toWorkSettingPage(this.props.match.params, item.homework_id) }}>设置</WordsBtn>
|
||||
</div>}
|
||||
|
||||
{
|
||||
//
|
||||
isStudent &&
|
||||
<li className="fr">
|
||||
<WordsBtn style="blue" className={"fl font-16"}
|
||||
onClick={ canNotLink ? () => {} : () => this.onItemClick(item)}
|
||||
>查看详情</WordsBtn>
|
||||
|
||||
{ //
|
||||
item.work_status && item.work_status.indexOf('关联项目') != -1 &&
|
||||
<React.Fragment>
|
||||
<WordsBtn style="blue" className={` font-16 fl ml28`} onClick={() => this.props.toCreateProject(item)}>创建项目</WordsBtn>
|
||||
<WordsBtn style="blue" className={` font-16 fl ml28`} onClick={() => this.props.openConnectionProject(item)}>关联项目</WordsBtn>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
{ //
|
||||
item.work_status && item.work_status.indexOf('取消关联') != -1 &&
|
||||
<WordsBtn style="blue" className={` font-16 fl ml28`} onClick={() => this.props.cancelConnectionProject(item)}>取消关联</WordsBtn>
|
||||
}
|
||||
{ //
|
||||
item.work_status && item.work_status.indexOf('提交作品') != -1 &&
|
||||
<WordsBtn style="blue" className="fl font-16 ml28" onClick={() => this.props.toWorkPostPage(this.props.match.params, item.homework_id)}>提交作品</WordsBtn>
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
//
|
||||
item.work_status && item.work_status.indexOf('补交作品') != -1 &&
|
||||
<WordsBtn style="blue" className="fl font-16 ml28" onClick={() => this.props.toWorkPostPage(this.props.match.params, item.homework_id)}>补交作品</WordsBtn> }
|
||||
|
||||
{ //
|
||||
item.work_status && item.work_status.indexOf('修改作品') != -1 &&
|
||||
<WordsBtn style="blue" className="fl font-16 ml28" onClick={() => this.props.toWorkPostPage(this.props.match.params, item.homework_id, true, item.work_id)}>修改作品</WordsBtn>
|
||||
}
|
||||
{ //
|
||||
item.work_status && item.work_status.indexOf('补交附件') != -1 &&
|
||||
<React.Fragment>
|
||||
<AccessoryModal
|
||||
{...this.props}
|
||||
modalname={"补交附件"}
|
||||
visible={this.state.accessoryVisible}
|
||||
Cancelname={"取消"}
|
||||
Savesname={"确认"}
|
||||
Cancel={this.Cancelvisible}
|
||||
setupdate={this.setupdate}
|
||||
reviseAttachmentUrl={`/student_works/${item.work_id}/revise_attachment.json`}
|
||||
seeworks={`/courses/${this.props.match.params.coursesId}/common_homeworks/${item.homework_id}/${item.work_id}/appraise`}
|
||||
/>
|
||||
<WordsBtn style="blue" className="fl font-16 ml28" onClick={() => this.addAccessory(item)}>补交附件</WordsBtn>
|
||||
</React.Fragment>
|
||||
|
||||
}
|
||||
{
|
||||
//
|
||||
item.work_status && item.work_status.indexOf('查看作品') != -1 &&
|
||||
<WordsBtn style="blue" className="fl font-16 ml28" onClick={() => this.props.toWorkDetailPage(this.props.match.params, item.homework_id, item.work_id)}>查看作品</WordsBtn> }
|
||||
|
||||
|
||||
</li>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default CommonWorkItem;
|
||||
@@ -0,0 +1,913 @@
|
||||
import React,{Component} from "react";
|
||||
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal, Table, Divider, Tag,DatePicker,Radio,Tooltip,Spin, Pagination} from "antd";
|
||||
import {WordsBtn, ConditionToolTip, queryString, publicSearchs, on, off, NoneData, sortDirections} from 'educoder';
|
||||
import axios from 'axios';
|
||||
import CheckAllGroup from '../common/button/CheckAllGroup'
|
||||
import moment from 'moment';
|
||||
import CheckCodeModal from '../coursesPublic/modal/CheckCodeModal'
|
||||
import '../css/Courses.css';
|
||||
import PublishRightnow from './PublishRightnow'
|
||||
import ModulationModal from "../coursesPublic/ModulationModal";
|
||||
import AccessoryModal from "../coursesPublic/AccessoryModal";
|
||||
import LeaderIcon from './common/LeaderIcon'
|
||||
const $ = window.$;
|
||||
const Search = Input.Search;
|
||||
|
||||
function renderScore(score, content) {
|
||||
let color = '#747A7F'
|
||||
if (score >= 90) {
|
||||
color = '#DD1717'
|
||||
} else if (score >= 60) {
|
||||
color = '#FF6800'
|
||||
}
|
||||
return <a href="javascript:;" style={{ color, cursor: 'default', minWidth: '30px', display: 'inline-block', textAlign: 'center' }}>
|
||||
{score == null || score == undefined || score == '--' ? '--': (content || score)}
|
||||
</a>
|
||||
}
|
||||
function getScoreTip(score, dom) {
|
||||
return score == '--' ? '未评分' : score == '**' ? '未公开' : dom
|
||||
}
|
||||
function buildColumns(that, student_works, studentData) {
|
||||
let gotWorkGroup = false;
|
||||
let gotProjectInfo = false;
|
||||
if (student_works && student_works.length) {
|
||||
student_works.forEach(item => {
|
||||
if (item.work_group) {
|
||||
gotWorkGroup = true
|
||||
}
|
||||
if (item.project_info && item.project_info.name) {
|
||||
gotProjectInfo = true;
|
||||
}
|
||||
})
|
||||
} else if (studentData && studentData[0]) {
|
||||
if (studentData[0].work_group) {
|
||||
gotWorkGroup = true
|
||||
}
|
||||
if (studentData[0].project_info) {
|
||||
gotProjectInfo = true;
|
||||
}
|
||||
}
|
||||
let courseId= that.props.match.params.coursesId;
|
||||
let workId= that.props.match.params.workId;
|
||||
const { course_group_count, homework_status } = that.state;
|
||||
const isAdmin = that.props.isAdmin()
|
||||
const isAdminOrStudent = that.props.isAdminOrStudent()
|
||||
const isStudent = that.props.isStudent()
|
||||
const isNiPing = homework_status && homework_status.indexOf('匿评中') != -1
|
||||
const isAppeal = homework_status && homework_status.indexOf('申诉中') != -1
|
||||
// https://www.trustie.net/issues/21450 分组作业作品列表 学时视角,匿评阶段的列表显示信息不正确
|
||||
const niPingAndIsStudent = isStudent && (isNiPing || isAppeal)
|
||||
|
||||
let columns = [{
|
||||
width: 60,
|
||||
title: '序号',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<span style={{ minWidth: '50px', display: 'inline-block', textAlign: 'center' }} >
|
||||
{record.isMine == true && (student_works && student_works.length) ? '我' : (that.state.page - 1) * PAGE_SIZE + index + 1}
|
||||
</span>
|
||||
)},
|
||||
}, {
|
||||
title: '姓名',
|
||||
width: 90,
|
||||
dataIndex: 'user_name',
|
||||
key: 'user_name',
|
||||
// width: '110px',
|
||||
render: (text, record) => (
|
||||
<div style={{
|
||||
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
width: '74px',
|
||||
margin: '0 auto'
|
||||
}} title={text && text.length > 5 ? text : ''}>
|
||||
{/* <Tooltip placement="bottom" title={text}>
|
||||
</Tooltip> */}
|
||||
{record.is_leader ?
|
||||
<div style={{ display: 'flex', 'flex-direction': 'column', 'align-items': 'center'}}>
|
||||
<div >{text}</div>
|
||||
<LeaderIcon></LeaderIcon>
|
||||
</div>
|
||||
: <React.Fragment>{text}</React.Fragment>}
|
||||
</div>
|
||||
),
|
||||
}]
|
||||
if (!niPingAndIsStudent && isAdminOrStudent) {
|
||||
columns.push({
|
||||
width: isStudent ? undefined : 88,
|
||||
title: '学号',
|
||||
dataIndex: 'student_id',
|
||||
key: 'student_id',
|
||||
sorter: true,
|
||||
sortDirections: sortDirections,
|
||||
render: (text, record) => (
|
||||
<span>
|
||||
<a href="javascript:;"
|
||||
title={text && text.length > 12 ? text : ''}
|
||||
style={{
|
||||
color: '#9A9A9A',
|
||||
'text-overflow': 'ellipsis',
|
||||
'white-space': 'nowrap',
|
||||
'width': '98px',
|
||||
display: 'block',
|
||||
overflow: 'hidden'
|
||||
, margin: '0 auto', cursor: 'default'}}
|
||||
>{record.student_id}</a>
|
||||
</span>
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
// TODO 只有有分班时才显示分班列
|
||||
if (course_group_count != 0 && !niPingAndIsStudent) {
|
||||
columns.push( {
|
||||
title: '分班',
|
||||
key: 'group_name',
|
||||
dataIndex: 'group_name',
|
||||
render: (text, record) => (
|
||||
<span>
|
||||
<a href="javascript:;" style={{color:'#9A9A9A', cursor: 'default'}}>{record.group_name}</a>
|
||||
</span>
|
||||
),
|
||||
} )
|
||||
}
|
||||
if (gotWorkGroup && !niPingAndIsStudent) {
|
||||
columns.push({
|
||||
width: 72,
|
||||
title: '分组',
|
||||
dataIndex: 'work_group',
|
||||
key: 'work_group',
|
||||
|
||||
render: (text, record) => (
|
||||
<span>
|
||||
<a href="javascript:void(0);" style={{color:'#4CACFF'}}>{record.work_group}</a>
|
||||
</span>
|
||||
),
|
||||
})
|
||||
}
|
||||
if (gotProjectInfo) {
|
||||
columns.push({
|
||||
width: 72,
|
||||
title: '关联项目',
|
||||
dataIndex: 'project_info',
|
||||
key: 'project_info',
|
||||
|
||||
render: (project_info, record) => (
|
||||
<span>
|
||||
{project_info && project_info.name &&
|
||||
<a href={project_info.id == -1 ? 'javascript:void(0)' : `/projects/${project_info.id}`}
|
||||
target={project_info.id == -1 ? '' : "_blank"}
|
||||
className="overflowHidden1" style={{
|
||||
color: '#4CACFF',
|
||||
width: that.state.anonymous_comment ? '80px' : '130px',
|
||||
margin: '0 auto',
|
||||
display: 'block'
|
||||
}} title={project_info.name}
|
||||
>{project_info.name}</a>}
|
||||
</span>
|
||||
),
|
||||
})
|
||||
}
|
||||
columns = columns.concat([{
|
||||
width: 88,
|
||||
title: '作品状态',
|
||||
dataIndex: 'work_status',
|
||||
key: 'work_status',
|
||||
|
||||
render: (status, record) => {
|
||||
let color;
|
||||
let text
|
||||
if (status === 2) {
|
||||
color = '#DD1717'
|
||||
text = '延时提交'
|
||||
} else if (status === 0 ) {
|
||||
color = '#747A7F'
|
||||
text = '未提交'
|
||||
} else {
|
||||
color = '#29BD8B'
|
||||
text = '按时提交'
|
||||
}
|
||||
return (
|
||||
<span>
|
||||
<a href="javascript:;" style={{color: color, cursor: 'default'}}>
|
||||
{status === 0 ? "未提交" : status === 1 ? "按时提交" : status === 2 ? "延时提交" : ""}
|
||||
</a>
|
||||
</span>
|
||||
)},
|
||||
}, {
|
||||
width: 106, // isStudent ? undefined : 106 , // 匿评中 只有这几列: 序号 姓名 提交状态 更新时间 匿评评分 操作
|
||||
title: '更新时间',
|
||||
dataIndex: 'update_time',
|
||||
key: 'update_time',
|
||||
sorter: true,
|
||||
defaultSortOrder: 'descend',
|
||||
sortDirections: sortDirections,
|
||||
render: (update_time, record) => (
|
||||
<span>
|
||||
<a href="javascript:;" style={{color:'#989898', cursor: 'default'}}>{update_time ? moment(update_time).format('YYYY-MM-DD HH:mm') : '--'}</a>
|
||||
</span>
|
||||
),
|
||||
}])
|
||||
if (!niPingAndIsStudent) {
|
||||
columns.push({
|
||||
width: 70,
|
||||
title: '教师评分',
|
||||
key: 'teacher_score',
|
||||
dataIndex: 'teacher_score',
|
||||
|
||||
render: (teacher_score, record) => (
|
||||
|
||||
<Tooltip title={ getScoreTip(teacher_score, teacher_score) }>
|
||||
<span>
|
||||
{ renderScore(teacher_score) }
|
||||
</span>
|
||||
</Tooltip>
|
||||
),
|
||||
})
|
||||
|
||||
columns.push({
|
||||
width: 70,
|
||||
title: '助教评分',
|
||||
key: 'teaching_asistant_score',
|
||||
dataIndex: 'teaching_asistant_score',
|
||||
/**
|
||||
* 2名助教进行了评分
|
||||
平均分:85.0分
|
||||
*
|
||||
*/
|
||||
render: (teaching_asistant_score, record) => (
|
||||
<span>
|
||||
{ <Tooltip placement="bottom" title={
|
||||
getScoreTip(teaching_asistant_score,
|
||||
<div>
|
||||
<div>{record.ta_comment_count}名助教进行了评分</div>
|
||||
<div>{that.state.ta_mode == 1 ? '平均分': '复审分'}:{teaching_asistant_score}分</div>
|
||||
</div>) }
|
||||
>
|
||||
|
||||
{renderScore(teaching_asistant_score) }
|
||||
</Tooltip> }
|
||||
</span>
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
if (that.state.anonymous_comment) {
|
||||
/**
|
||||
开启了匿评的才显示此列,悬浮TIP示例:
|
||||
3名学生进行了匿评
|
||||
有效平均分:80.0分
|
||||
*/
|
||||
columns.push({
|
||||
width: 84,
|
||||
// title: <div style={{color: 'rgba(0,0,0,.85)'}}><div style={{color: 'rgba(0,0,0,.85)'}}>匿评</div>评分</div>,
|
||||
title: <div style={{color: 'rgba(0,0,0,.85)'}}>匿评评分</div>,
|
||||
key: 'student_score',
|
||||
dataIndex: 'student_score',
|
||||
|
||||
render: (student_score, record) => (
|
||||
<span>
|
||||
<Tooltip title={
|
||||
getScoreTip(student_score,
|
||||
that.state.is_evaluation ? `你的评阅分数:${record.student_score}分` : <div>
|
||||
{record.student_comment_count && <div>{`${record.student_comment_count}名学生进行了匿评`}</div>}
|
||||
<div>有效平均分:{record.student_score}分</div>
|
||||
</div>
|
||||
)
|
||||
}>
|
||||
{ renderScore(student_score, `${student_score}${record.student_comment_count ? ` (${record.student_comment_count})` : ''}`) }
|
||||
</Tooltip>
|
||||
</span>
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
if (that.state.anonymous_appeal) {
|
||||
columns.push({
|
||||
width: 70,
|
||||
title: '匿评申诉',
|
||||
key: 'appeal_all_count',
|
||||
dataIndex: 'appeal_all_count',
|
||||
|
||||
render: (appeal_all_count, record) => (
|
||||
<span>
|
||||
{!!appeal_all_count &&
|
||||
<Tooltip placement="bottom" title={`共有${appeal_all_count}条匿评申诉,${record.appeal_deal_count}条待处理`}>
|
||||
<span style={{ minWidth: '30px', display: 'inline-block', textAlign: 'center' }}>
|
||||
{`${record.appeal_deal_count}/${appeal_all_count}`}
|
||||
</span>
|
||||
</Tooltip> }
|
||||
{ !appeal_all_count && <span style={{ color: '#747A7F' }}>-/-</span>}
|
||||
</span>
|
||||
),
|
||||
})
|
||||
}
|
||||
if (!niPingAndIsStudent) {
|
||||
columns.push({
|
||||
width: '113px',
|
||||
title: '当前成绩',
|
||||
key: 'work_score',
|
||||
dataIndex: 'work_score',
|
||||
sorter: true,
|
||||
sortDirections: sortDirections,
|
||||
render: (work_score, record) => {
|
||||
return (
|
||||
<span>
|
||||
<Tooltip title={
|
||||
getScoreTip(work_score,
|
||||
<div>
|
||||
<div>{`${record.user_name}(${record.user_login})`}</div>
|
||||
{record.ultimate_score ?
|
||||
<div>最终调整成绩:{record.work_score}分</div> :
|
||||
<div>
|
||||
{ record.final_score && <div>作业评分:{record.final_score}分</div> }
|
||||
{ record.late_penalty >= 0 && <div>迟交扣分:{record.late_penalty}分</div>}
|
||||
{ record.absence_penalty >= 0 && <div>缺评扣分:{record.absence_penalty}分</div>}
|
||||
{ record.appeal_penalty >= 0 && <div>违规匿评扣分:{record.appeal_penalty}分</div>}
|
||||
<div>最终成绩:{record.work_score}分</div>
|
||||
</div> }
|
||||
</div>)
|
||||
}>
|
||||
{ renderScore(work_score) }
|
||||
</Tooltip>
|
||||
</span>
|
||||
)
|
||||
},
|
||||
})
|
||||
}
|
||||
if (isAdminOrStudent || that.props.work_public == true) {
|
||||
columns.push({
|
||||
width: 72,
|
||||
title: '操作',
|
||||
key: 'operation',
|
||||
dataIndex: 'operation',
|
||||
render: (operation, record) => (
|
||||
record.work_status === 0 && !isAdmin ? <span style={{ color: '#747A7F' }}>--</span>:
|
||||
<div>
|
||||
{/* 0 未提交 */}
|
||||
{/*<React.Fragment>*/}
|
||||
{/*</React.Fragment>*/}
|
||||
{ isAdmin && <Tooltip placement="bottom" title={<pre>调整学生当前成绩<br/>其它历史评分将全部失效</pre>}>
|
||||
<a style={{color: "#4CACFF"}}
|
||||
onClick={() => that.showModulationModal(record)}
|
||||
>调分</a>
|
||||
</Tooltip> }
|
||||
{/* toWorkDetailPage */}
|
||||
{/* /courses/"+courseId+"/common_homeworks/"+workId+ '/' + record.id +"/appraise */}
|
||||
<a style={{color: '#4CACFF', marginLeft: '4px'}} id={"asdasdasdasd"}
|
||||
onMouseDown={(e) => that.props.toWorkDetailPage2(e, courseId, workId, record.id)}
|
||||
onClick={() => that.props.toWorkDetailPage(courseId, workId, record.id)}>{isAdmin ? '评阅' : '查看'}</a>
|
||||
|
||||
</div>
|
||||
|
||||
),
|
||||
});
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
// update_time,最终成绩:work_score,学号:student_id
|
||||
// desc:倒序 , asc:顺序
|
||||
const orderMap = {
|
||||
update_time: 'desc',
|
||||
work_score: 'asc',
|
||||
student_id: 'asc',
|
||||
}
|
||||
const PAGE_SIZE = 20
|
||||
// 类似页面 http://localhost:3007/courses/1309/graduation/graduation_tasks/48/76/setting
|
||||
class CommonWorkList extends Component{
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
|
||||
this.publishModal = React.createRef();
|
||||
this.endModal = React.createRef();
|
||||
|
||||
this.state={
|
||||
course_name:"",
|
||||
homework_name:"",
|
||||
search: '',
|
||||
task_status: [],
|
||||
teacher_comment: [],
|
||||
course_group_info: [],
|
||||
arg_work_status: [],
|
||||
arg_teacher_comment: [],
|
||||
arg_course_group: [],
|
||||
order: 'update_time',
|
||||
page: 1,
|
||||
isSpin:true,
|
||||
left_time: {},
|
||||
category: {},
|
||||
b_order: 'desc',
|
||||
searchtypes:false,
|
||||
loadingstate:false
|
||||
}
|
||||
}
|
||||
onTablePagination = (page) => {
|
||||
this.setState({ page: page }, () => {
|
||||
this.fetchList()
|
||||
})
|
||||
|
||||
}
|
||||
onSearchValue = (val) => {
|
||||
if (val === ""||val===undefined) {
|
||||
this.setState({
|
||||
search: undefined,
|
||||
searchtypes:false
|
||||
})
|
||||
}else{
|
||||
this.setState({
|
||||
searchtypes:true,
|
||||
loadingstate:true
|
||||
})
|
||||
}
|
||||
|
||||
this.fetchList()
|
||||
}
|
||||
onSearchValueInput = (e) => {
|
||||
if (e.target.value === ""||e.target.value===undefined) {
|
||||
this.setState({
|
||||
search: undefined,
|
||||
})
|
||||
} else {
|
||||
this.setState({search: e.target.value})
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
console.log("CommonWorkList 分班list 开始加载");
|
||||
this.fetchList()
|
||||
on('commonwork_fetch_all', this.fetchAllListener)
|
||||
$("html").animate({ scrollTop: $('html').scrollTop() - 100 });
|
||||
try {
|
||||
this.props.triggerRef(this);
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
componentWillUnmount() {
|
||||
off('commonwork_fetch_all', this.fetchAllListener)
|
||||
}
|
||||
fetchAllListener = () => {
|
||||
this.fetchList()
|
||||
}
|
||||
|
||||
_getRequestParams() {
|
||||
const {search, arg_work_status, arg_teacher_comment, arg_course_group, order, page, arg_member_work, b_order} = this.state
|
||||
return {
|
||||
page,
|
||||
search,
|
||||
work_status: arg_work_status, // [0]
|
||||
course_group: arg_course_group,
|
||||
teacher_comment: arg_teacher_comment.length == 0 ? '' : arg_teacher_comment[0],
|
||||
order,
|
||||
limit: PAGE_SIZE,
|
||||
b_order: b_order,
|
||||
group_id:arg_course_group,
|
||||
member_work: arg_member_work
|
||||
}
|
||||
}
|
||||
fetchData = () => {
|
||||
this.fetchList()
|
||||
}
|
||||
fetchList = () => {
|
||||
let workId=this.props.match.params.workId;
|
||||
let courseId=this.props.match.params.coursesId;
|
||||
|
||||
const url = `/homework_commons/${workId}/works_list.json`
|
||||
let params = this._getRequestParams()
|
||||
axios.post(url, params).then((response)=> {
|
||||
if (response.data) {
|
||||
this.setState({
|
||||
...response.data,
|
||||
isSpin:false,
|
||||
loadingstate:false
|
||||
})
|
||||
|
||||
this.props.initWorkDetailCommonState && this.props.initWorkDetailCommonState( Object.assign({...response.data}, {
|
||||
moduleName: '作品列表'
|
||||
}))
|
||||
}
|
||||
}).catch((error)=>{
|
||||
console.log(error)
|
||||
this.setState({
|
||||
isSpin:false,
|
||||
loadingstate:false
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
teacherCommentOptionChange = (values, isAllChecked) => {
|
||||
this.setState({arg_teacher_comment: isAllChecked ? [] : values, page: 1}, () => {
|
||||
this.fetchList()
|
||||
})
|
||||
}
|
||||
statusOptionChange = (values, isAllChecked) => {
|
||||
this.setState({arg_work_status: isAllChecked ? [] : values, page: 1}, () => {
|
||||
this.fetchList()
|
||||
})
|
||||
}
|
||||
courseGroupOptionChange = (values, isAllChecked) => {
|
||||
this.setState({arg_course_group: isAllChecked ? [] : values, page: 1}, () => {
|
||||
this.fetchList()
|
||||
})
|
||||
}
|
||||
memberWorkChange = (values, isAllChecked) => {
|
||||
this.setState({arg_member_work: isAllChecked ? '' : values[0], page: 1}, () => {
|
||||
this.fetchList()
|
||||
})
|
||||
}
|
||||
funorder = (order, b_order) => {
|
||||
this.setState({
|
||||
order: order
|
||||
,
|
||||
b_order: b_order
|
||||
}, () => {
|
||||
this.fetchList()
|
||||
})
|
||||
}
|
||||
doWhenSuccess = () => {
|
||||
this.fetchList()
|
||||
}
|
||||
|
||||
// --------------调分
|
||||
showModulationModal = (item) => {
|
||||
this.modulationItem = item;
|
||||
this.setState({ modulationModalVisible: true })
|
||||
}
|
||||
cancelModulationModel = () => {
|
||||
this.setState({ modulationModalVisible: false })
|
||||
}
|
||||
saveModulationModal = (value, num) => {
|
||||
const item = this.modulationItem
|
||||
const url = `/student_works/${item.id}/adjust_score.json`
|
||||
axios.post(url, {
|
||||
score: num,
|
||||
comment: value
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.status == '0') {
|
||||
this.setState({ modulationModalVisible: false })
|
||||
this.props.showNotification('调分成功')
|
||||
this.fetchList()
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
// --------------调分 END
|
||||
|
||||
// 补交附件
|
||||
Cancelvisible=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
addAccessory=()=>{
|
||||
this.setState({
|
||||
visible:true
|
||||
})
|
||||
}
|
||||
setupdate = () => {
|
||||
|
||||
}
|
||||
|
||||
//普通作业tbale 列表塞选数据
|
||||
table1handleChange = (pagination, filters, sorter) => {
|
||||
//"ascend" 升序
|
||||
//"descend" 降序
|
||||
if (JSON.stringify(sorter) === "{}") {
|
||||
//没有选择
|
||||
} else {
|
||||
// 时间
|
||||
try {
|
||||
if (sorter.columnKey === "update_time") {
|
||||
let myyslorder = "";
|
||||
if (sorter.order === "ascend") {
|
||||
myyslorder = "asc";
|
||||
} else if (sorter.order === "descend") {
|
||||
myyslorder = "desc";
|
||||
}
|
||||
this.funorder("update_time", myyslorder);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
//成绩
|
||||
try {
|
||||
if (sorter.columnKey === "work_score") {
|
||||
let myyslorder = "";
|
||||
if (sorter.order === "ascend") {
|
||||
myyslorder = "asc";
|
||||
} else if (sorter.order === "descend") {
|
||||
myyslorder = "desc";
|
||||
}
|
||||
this.funorder("work_score", myyslorder)
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
//学号
|
||||
try {
|
||||
if (sorter.columnKey === "student_id") {
|
||||
let myyslorder = "";
|
||||
if (sorter.order === "ascend") {
|
||||
myyslorder = "asc";
|
||||
} else if (sorter.order === "descend") {
|
||||
myyslorder = "desc";
|
||||
}
|
||||
this.funorder("student_id", myyslorder)
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
render(){
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const dateFormat = 'YYYY-MM-DD HH:mm';
|
||||
|
||||
let {course_name, homework_name, search, page, loadingstate, student_works, work_count,
|
||||
all_member_count, time_status,
|
||||
// 老师显示的三个过滤条件
|
||||
task_status, teacher_comment, course_group_info, order,
|
||||
commit_count, uncommit_count, left_time,
|
||||
modulationModalVisible, work_statuses,
|
||||
|
||||
id, user_name, user_login, student_id, group_name, work_status, update_time, teacher_score, teaching_asistant_score, student_score,
|
||||
ultimate_score, work_score, student_comment_count, appeal_all_count, appeal_deal_count,
|
||||
late_penalty, absence_penalty, appeal_penalty
|
||||
|
||||
, end_immediately, publish_immediately
|
||||
, homework_id, visible, work_group, project_info, is_leader
|
||||
} =this.state;
|
||||
|
||||
|
||||
let courseId=this.props.match.params.coursesId;
|
||||
let category_id=this.props.match.params.category_id;
|
||||
let workId=this.props.match.params.workId;
|
||||
const radioStyle = {
|
||||
display: 'block',
|
||||
height: '30px',
|
||||
lineHeight: '30px',
|
||||
};
|
||||
|
||||
const options_status = task_status.map((item) => {
|
||||
return { label: `${item.name}(${item.count})`, value: item.id }
|
||||
})
|
||||
|
||||
const options_course_group = course_group_info.map((item) => {
|
||||
return { label: `${item.group_group_name}(${item.count})`, value: item.course_group_id }
|
||||
})
|
||||
const options_teacher_comment = teacher_comment.map((item) => {
|
||||
return { label: `${item.name}(${item.count})`, value: item.id }
|
||||
})
|
||||
|
||||
// 1:组长, 0:组员,“” 不限
|
||||
const member_works = [{
|
||||
name: '组长', id: 1
|
||||
}, {
|
||||
name: '组员', id: 0
|
||||
}]
|
||||
const options_member_work = member_works.map((item) => {
|
||||
return { label: `${item.name}`, value: item.id }
|
||||
})
|
||||
|
||||
|
||||
const isAdmin = this.props.isAdmin()
|
||||
const isStudent = this.props.isStudent()
|
||||
const isAdminOrStudent = this.props.isAdminOrStudent()
|
||||
const isGroup = this.props.isGroup();
|
||||
// work_group
|
||||
let StudentData;
|
||||
|
||||
if(id===undefined){
|
||||
StudentData=undefined
|
||||
}else{
|
||||
StudentData=isStudent ? [{ id, user_name, user_login, student_id, group_name, work_status, update_time, teacher_score, teaching_asistant_score, student_score,
|
||||
ultimate_score, work_score, student_comment_count, appeal_all_count, appeal_deal_count,
|
||||
late_penalty, absence_penalty, appeal_penalty, project_info, is_leader,
|
||||
work_group, isMine: true }] : []
|
||||
}
|
||||
const columns = buildColumns(this, student_works, StudentData)
|
||||
|
||||
let params = this._getRequestParams()
|
||||
let exportUrl = `/api/homework_commons/${workId}/works_list.zip?${queryString.stringify(params)}`;
|
||||
const exportResultUrl = `/api/homework_commons/${workId}/works_list.xlsx`;
|
||||
let appraisetype=false;
|
||||
let appraiselist=this.state.homework_status;
|
||||
|
||||
appraiselist&&appraiselist.map((item,key)=>{
|
||||
if(item==="评阅中"){
|
||||
appraisetype=true
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
// time_status int 时间对应的状态: 0:未发布,1:提交中,2:补交中,3:匿评中,4:申诉中,5:评阅中,6:已结束
|
||||
|
||||
let timeMsg = '提交剩余时间'
|
||||
if (time_status === 1) {
|
||||
|
||||
} else if (time_status === 2) {
|
||||
timeMsg = '补交剩余时间'
|
||||
} else if (time_status === 3) {
|
||||
timeMsg = '匿评剩余时间'
|
||||
} else if (time_status === 4) {
|
||||
timeMsg = '申诉剩余时间'
|
||||
}
|
||||
|
||||
const hasData = this.state.homework_status && this.state.homework_status.indexOf("未发布") == -1 // student_works && !!student_works.length && page == 1 &&
|
||||
|
||||
// console.log(StudentData)
|
||||
// console.log(student_works)
|
||||
return(
|
||||
<React.Fragment>
|
||||
<CheckCodeModal
|
||||
ref="checkCodeModal"
|
||||
{...this.props}
|
||||
></CheckCodeModal>
|
||||
|
||||
<AccessoryModal
|
||||
{...this.props}
|
||||
modalname={"补交附件"}
|
||||
visible={visible}
|
||||
Cancelname={"取消"}
|
||||
Savesname={"确认"}
|
||||
Cancel={this.Cancelvisible}
|
||||
categoryid={category_id}
|
||||
setupdate={this.setupdate}
|
||||
reviseAttachmentUrl={`/student_works/${id}/revise_attachment.json`}
|
||||
/>
|
||||
|
||||
<PublishRightnow ref={this.publishModal} showActionButton={false} {...this.props} checkBoxValues={[workId]}
|
||||
isPublish={true} doWhenSuccess={this.doWhenSuccess}></PublishRightnow>
|
||||
<PublishRightnow ref={this.endModal} showActionButton={false} {...this.props} checkBoxValues={[workId]}
|
||||
isPublish={false} doWhenSuccess={this.doWhenSuccess}></PublishRightnow>
|
||||
|
||||
{
|
||||
modulationModalVisible === true ?
|
||||
<ModulationModal
|
||||
visible={modulationModalVisible}
|
||||
Cancel={this.cancelModulationModel}
|
||||
Saves={(value, num) => this.saveModulationModal(value, num)}
|
||||
/>
|
||||
: ""
|
||||
}
|
||||
|
||||
|
||||
|
||||
{/* 内容区 */}
|
||||
<style>{`
|
||||
.ant-table-thead > tr > th, .ant-table-tbody > tr > td {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.worklist1 .search-new {
|
||||
margin-bottom: -30px !important;
|
||||
top: 22px;
|
||||
position: absolute;
|
||||
right: 18px;
|
||||
}
|
||||
|
||||
.workListContent .ant-table-thead > tr > th, .workListContent .ant-table-tbody > tr > td {
|
||||
padding: 10px 1px;
|
||||
}
|
||||
`}</style>
|
||||
<div style={{ background: '#fff'}} className="workListContent">
|
||||
{ isAdmin && hasData && <ul className="clearfix" style={{padding: "20px 40px 10px", position: 'relative', paddingLeft: '24px'}}>
|
||||
|
||||
<CheckAllGroup options={options_teacher_comment} label={'你的评阅:'} onChange={this.teacherCommentOptionChange}></CheckAllGroup>
|
||||
<CheckAllGroup options={options_status} label={'作品状态:'} onChange={this.statusOptionChange}></CheckAllGroup>
|
||||
{isGroup && <CheckAllGroup options={options_member_work} label={'组内角色:'} onChange={this.memberWorkChange}></CheckAllGroup>}
|
||||
{options_course_group.length > 1 && <CheckAllGroup options={options_course_group} label={'分班情况:'} onChange={this.courseGroupOptionChange} checkboxGroupStyle={{width: '980px'}}></CheckAllGroup>}
|
||||
|
||||
|
||||
{/* value={search} */}
|
||||
<div className="fr search-new mr8" style={{marginBottom:'1px'}}>
|
||||
{/*<Search*/}
|
||||
{/* placeholder="请输入姓名或学号搜索1"*/}
|
||||
{/* id="subject_search_input"*/}
|
||||
{/* onInput={this.onSearchValueInput}*/}
|
||||
{/* onSearch={this.onSearchValue}*/}
|
||||
{/* autoComplete="off"*/}
|
||||
{/*></Search>*/}
|
||||
{publicSearchs("请输入姓名或学号搜索",this.onSearchValue,this.onSearchValueInput,this.onSearchValueInput)}
|
||||
</div>
|
||||
</ul> }
|
||||
|
||||
{ <div id="graduation_work_list" style={{padding: isStudent ? '10px 24px 10px 24px' : '0px 24px 10px 24px'}}>
|
||||
<div className="clearfix">
|
||||
{hasData && <span className="fl color-grey-6 font-12">
|
||||
{ isAdmin ?
|
||||
(!!all_member_count) && <React.Fragment>
|
||||
<span className="color-orange-tip">{work_count || '0'}</span>个检索结果({all_member_count} 学生)
|
||||
</React.Fragment> :
|
||||
(!!commit_count || !!uncommit_count) &&
|
||||
<React.Fragment>
|
||||
<span className="color-orange-tip">{commit_count}</span>已交 {uncommit_count}未交
|
||||
{timeMsg || ''}
|
||||
<span className="color-orange-tip">{left_time.time}</span>
|
||||
</React.Fragment>
|
||||
}
|
||||
</span>}
|
||||
|
||||
|
||||
</div>
|
||||
</div> }
|
||||
|
||||
|
||||
<style>{`
|
||||
.workListContent .ant-table-thead > tr > th {
|
||||
border-bottom: none;
|
||||
}
|
||||
.studentTable .ant-table-tbody { background: '#F1F9FF' }
|
||||
.studentTable table, .stageTable table{
|
||||
font-size: 13px !important;
|
||||
}
|
||||
`}</style>
|
||||
{ isStudent &&StudentData===undefined?"":StudentData===undefined?"":
|
||||
<Table
|
||||
className="studentTable"
|
||||
dataSource={StudentData}
|
||||
onChange={this.table1handleChange}
|
||||
columns={columns}
|
||||
pagination={false}
|
||||
showHeader={ !student_works || student_works.length == 0}
|
||||
/>
|
||||
}
|
||||
|
||||
|
||||
<div className={"justify break_full_word new_li edu-back-white course_table_wrap"} style={{minHeight:"480px", marginBottom: '30px'}}>
|
||||
<style>{`
|
||||
// .ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
|
||||
// top: 72%;}
|
||||
// }
|
||||
.singleLine tr.ant-table-row {
|
||||
background: #f1f9ff;
|
||||
}
|
||||
.course_table_wrap .ant-pagination.ant-table-pagination {
|
||||
float: none;
|
||||
text-align: center;
|
||||
}
|
||||
`}</style>
|
||||
{isStudent && student_works && student_works.length == 0 || !isStudent && student_works===undefined?"":JSON.stringify(student_works) === "[]" ||student_works===undefined?
|
||||
<Spin size="large" spinning={this.state.isSpin}>
|
||||
<div id="forum_list" className="forum_table">
|
||||
<div className="mh650 edu-back-white">
|
||||
|
||||
<NoneData
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
></NoneData>
|
||||
</div>
|
||||
</div>
|
||||
</Spin>
|
||||
:
|
||||
<React.Fragment>
|
||||
<Spin tip="正在加载..." spinning={loadingstate}>
|
||||
<Table
|
||||
className="stageTable"
|
||||
dataSource={student_works}
|
||||
columns={columns}
|
||||
showQuickJumper
|
||||
pagination={false}
|
||||
onChange={this.table1handleChange}
|
||||
// loading={loadingstate}
|
||||
/>
|
||||
</Spin>
|
||||
</React.Fragment>
|
||||
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{work_count > PAGE_SIZE && <Pagination
|
||||
style={{ textAlign: 'center', marginBottom: '20px' }}
|
||||
showQuickJumper pageSize={PAGE_SIZE} onChange={this.onTablePagination} current={page} total={work_count} />}
|
||||
|
||||
|
||||
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const CommonWorkListForm = Form.create({ name: 'commonworkListForm' })(CommonWorkList);
|
||||
export default CommonWorkListForm;
|
||||
@@ -0,0 +1,135 @@
|
||||
import React,{Component} from "react";
|
||||
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal, Table, Divider, Tag,DatePicker,Radio,Tooltip} from "antd";
|
||||
import {Link} from 'react-router-dom';
|
||||
import locale from 'antd/lib/date-picker/locale/zh_CN';
|
||||
import { WordsBtn } from 'educoder';
|
||||
import axios from 'axios';
|
||||
import Modals from '../../modals/Modals';
|
||||
import CoursesListType from '../coursesPublic/CoursesListType';
|
||||
import HomeworkModal from "../coursesPublic/HomeworkModal";
|
||||
import moment from 'moment';
|
||||
import '../css/Courses.css'
|
||||
const { Option} = Select;
|
||||
const CheckboxGroup = Checkbox.Group;
|
||||
const confirm = Modal.confirm;
|
||||
let GraduationTasksnewtype=true;
|
||||
const $ = window.$;
|
||||
const Search = Input.Search;
|
||||
const RadioGroup = Radio.Group;
|
||||
|
||||
function scrollTo(className) {
|
||||
$("html").animate({ scrollTop: $(`${className}`).offset().top - 400 })
|
||||
}
|
||||
|
||||
|
||||
function range(start, end) {
|
||||
const result = [];
|
||||
for (let i = start; i < end; i++) {
|
||||
result.push(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function disabledDateTime() {
|
||||
return {
|
||||
// disabledHours: () => range(0, 24).splice(4, 20),
|
||||
disabledMinutes: () => range(1, 30).concat(range(31, 60)),
|
||||
// disabledSeconds: () => [55, 56],
|
||||
};
|
||||
}
|
||||
function handleDateString (dateString) {
|
||||
if (!dateString) return dateString;
|
||||
const ar = dateString.split(':')
|
||||
if (ar[1] != '00' && ar[1] != '30') {
|
||||
return [ar[0], '00'].join(':')
|
||||
}
|
||||
return dateString
|
||||
}
|
||||
// 类似页面 http://localhost:3007/courses/1309/graduation/graduation_tasks/48/76/setting
|
||||
class CommonWorkSetting extends Component{
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.state={
|
||||
course_name:"",
|
||||
homework_name:"",
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render(){
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const dateFormat = 'YYYY-MM-DD HH:mm';
|
||||
|
||||
let {course_name, homework_name
|
||||
} =this.state;
|
||||
|
||||
let courseId=this.props.match.params.coursesId;
|
||||
let category_id=this.props.match.params.category_id;
|
||||
let task_Id=this.props.match.params.task_Id;
|
||||
const radioStyle = {
|
||||
display: 'block',
|
||||
height: '30px',
|
||||
lineHeight: '30px',
|
||||
};
|
||||
|
||||
|
||||
return(
|
||||
<React.Fragment>
|
||||
{ <div>
|
||||
|
||||
<div className="newMain clearfix">
|
||||
<div className={"educontent mb20"}>
|
||||
|
||||
<p className="clearfix mt10">
|
||||
<WordsBtn style="grey" className="fl"> <Link to={"/courses/"+courseId} className="color-grey-6">{course_name}</Link></WordsBtn>
|
||||
<span className="color-grey-9 fl ml3 mr3">></span>
|
||||
<WordsBtn style="grey" className="fl"> <Link to={"/courses/"+courseId+"/graduation"} className="color-grey-6">毕设任务</Link></WordsBtn>
|
||||
<span className="color-grey-9 fl ml3 mr3">></span>
|
||||
<span>任务详情</span>
|
||||
</p>
|
||||
|
||||
<div style={{ width:'100%',height:'75px'}} >
|
||||
<p className=" fl color-black mt25 summaryname">
|
||||
<Link to={"/courses/"+courseId+"/graduation"+"/graduation_tasks/"}>{homework_name}</Link>
|
||||
</p>
|
||||
<CoursesListType
|
||||
typelist={["已开启补交"]}
|
||||
typesylename={"mt22"}
|
||||
/>
|
||||
<a className="color-grey-6 fr font-16 ml30 mt10 mr20" onClick={this.goback}>返回</a>
|
||||
</div>
|
||||
|
||||
<div className="stud-class-set bor-bottom-greyE">
|
||||
<div className="mt10 clearfix edu-back-white poll_list pl20">
|
||||
<Link
|
||||
className="active"
|
||||
to={"/courses/"+courseId+"/graduation/graduation_tasks/"+category_id+"/"+task_Id+"/list"}>作品列表</Link>
|
||||
<Link to={"/courses/"+courseId+"/graduation/graduation_tasks/"+category_id+"/"+task_Id+"/questions"}>作业描述</Link>
|
||||
<Link to={"/courses/"+courseId+"/graduation/graduation_tasks/"+category_id+"/"+task_Id+"/questions"}>参考答案</Link>
|
||||
<Link
|
||||
style={{paddingLeft:'38px'}}
|
||||
to={"/courses/"+courseId+"/graduation/graduation_tasks/"+category_id+"/"+task_Id+"/setting"}>设置</Link>
|
||||
|
||||
<a className={"fr color-blue font-16"} onClick={() => { this.end()} }>立即截止</a>
|
||||
<a className={"fr color-blue font-16"} onClick={() => { this.publish()} }>立即发布</a>
|
||||
|
||||
<a className={"fr color-blue font-16"} href={"/courses/"+courseId+"/graduation/graduation_tasks/"+task_Id+"/edit"}>编辑作业</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>}
|
||||
|
||||
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const CommonWorkSettingForm = Form.create({ name: 'commonworkSettingForm' })(CommonWorkSetting);
|
||||
export default CommonWorkSettingForm;
|
||||
@@ -0,0 +1,851 @@
|
||||
import React,{Component} from "react";
|
||||
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal,Tooltip} from "antd";
|
||||
import {Link} from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
import _ from 'lodash'
|
||||
|
||||
import { WordsBtn, getUploadActionUrl, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll, ConditionToolTip } from 'educoder';
|
||||
import Modals from '../../modals/Modals';
|
||||
import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
|
||||
import LeaderIcon from './common/LeaderIcon'
|
||||
|
||||
const Search = Input.Search;
|
||||
const CheckboxGroup = Checkbox.Group;
|
||||
|
||||
class CommonWorkPost extends Component{
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.mdRef = React.createRef();
|
||||
this.state={
|
||||
coursename:"",
|
||||
coursesearch:"",
|
||||
title_num:20,
|
||||
title_value:"",
|
||||
fileList: [],
|
||||
contents: [{val:"",id:1}],
|
||||
type:true,
|
||||
workslist:undefined,
|
||||
search:"",
|
||||
task_status:[],
|
||||
members: [],
|
||||
selectmemberslist:[],
|
||||
minvalue:"",
|
||||
setvalue:"",
|
||||
minmaxtype:false,
|
||||
selectobjct:undefined,
|
||||
Loadtype:false,
|
||||
|
||||
|
||||
limit:20,
|
||||
memberNumMin: 2,
|
||||
memberNumMax: 5,
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
const studentWorkId = this.props.match.params.studentWorkId
|
||||
this.isEdit = !!studentWorkId
|
||||
window.location.pathname.indexOf('post_edit') != -1
|
||||
let coursesId=this.props.match.params.coursesId;
|
||||
let workId=this.props.match.params.workId;
|
||||
let url = `/homework_commons/${workId}/student_works/new.json`
|
||||
const isGroup = this.props.isGroup()
|
||||
if (isGroup) {
|
||||
this.searchList('',1, this.state.limit)
|
||||
}
|
||||
|
||||
if (this.isEdit) {
|
||||
url = `/student_works/${studentWorkId}/edit.json`
|
||||
axios.get(url).then((response)=>{
|
||||
if(response.data.course_id){
|
||||
|
||||
// TODO
|
||||
// response.data.attachments
|
||||
const _fileList = response.data.attachments.map(item => {
|
||||
return {
|
||||
id: item.id,
|
||||
uid: item.id,
|
||||
name: appendFileSizeToUploadFile(item),
|
||||
url: item.url,
|
||||
delete: item.delete,
|
||||
status: 'done'
|
||||
}
|
||||
})
|
||||
const _memebers = response.data.members ? response.data.members.slice(0) : [];
|
||||
this._edit_init_memebers = _memebers
|
||||
delete response.data.members;
|
||||
this.setState({
|
||||
...response.data,
|
||||
selectmemberslist: _memebers || [],
|
||||
// members: [],
|
||||
task_status: [], //_memebers ? _memebers.map(item => item.user_id) : [],
|
||||
fileList: _fileList,
|
||||
memberNumMin: response.data.min_num,
|
||||
memberNumMax: response.data.max_num,
|
||||
})
|
||||
this.mine = _memebers.length ? _memebers[0] : null
|
||||
// 分组
|
||||
// this.setState({
|
||||
// task_status:checkedValues,
|
||||
// selectmemberslist:selects
|
||||
// })
|
||||
this.props.form.setFieldsValue({
|
||||
description: response.data.description,
|
||||
}, () => {});
|
||||
this.mdRef.current.setValue(response.data.description)
|
||||
}
|
||||
}).catch((error)=>{
|
||||
console.log(error)
|
||||
})
|
||||
} else {
|
||||
axios.get(url).then((response)=>{
|
||||
if(response.data.course_id){
|
||||
const mine = {
|
||||
user_id: response.data.user_id,
|
||||
user_name: response.data.user_name,
|
||||
student_id: response.data.user_student_id,
|
||||
group_name: response.data.group_name,
|
||||
|
||||
}
|
||||
this.mine = mine
|
||||
// const _memebers = response.data.members.slice(0);
|
||||
if (response.data.members) {
|
||||
delete response.data.members;
|
||||
}
|
||||
this.setState({
|
||||
...response.data,
|
||||
selectmemberslist: [mine],
|
||||
memberNumMin: response.data.min_num,
|
||||
memberNumMax: response.data.max_num,
|
||||
})
|
||||
}
|
||||
}).catch((error)=>{
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setedit=(workId)=>{
|
||||
|
||||
let coursesId=this.props.match.params.coursesId;
|
||||
window.location.href="courses/"+coursesId+"/graduation_tasks/"+workId+"/appraise";
|
||||
|
||||
}
|
||||
|
||||
handleSubmit=(e) => {
|
||||
|
||||
let {fileList,selectmemberslist,workslist, memberNumMin, memberNumMax}=this.state;
|
||||
|
||||
let userids=[];
|
||||
if(selectmemberslist!=undefined&&selectmemberslist.length>0) {
|
||||
for (var list of selectmemberslist) {
|
||||
|
||||
if (list.user_id != undefined && list.user_id != null) {
|
||||
userids.push(list.user_id)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
const isGroup = this.props.isGroup()
|
||||
if(!isGroup){
|
||||
userids=undefined
|
||||
}
|
||||
|
||||
let listid=[];
|
||||
if(fileList!=undefined&&fileList.length>0) {
|
||||
for (var list of fileList) {
|
||||
listid.push(list.id || list.response.id)
|
||||
}
|
||||
}
|
||||
e.preventDefault();
|
||||
if( true ){
|
||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
console.log(values.description);
|
||||
// console.log(fileList);
|
||||
if(values.description===undefined||values.description===""){
|
||||
|
||||
return
|
||||
}
|
||||
if(isGroup){
|
||||
if(userids!=undefined){
|
||||
if(userids.length < memberNumMin){
|
||||
this.setState({
|
||||
minvalue: memberNumMin,
|
||||
setvalue:"小于",
|
||||
minmaxtype:true
|
||||
})
|
||||
|
||||
return
|
||||
}else if(userids.length > memberNumMax){
|
||||
this.setState({
|
||||
minvalue: memberNumMax,
|
||||
setvalue:"大于",
|
||||
minmaxtype:true
|
||||
})
|
||||
return
|
||||
} else {
|
||||
this.setState({
|
||||
minmaxtype: false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!listid || listid.length == 0) {
|
||||
this.props.confirm({
|
||||
content: <div>
|
||||
<div>还未上传附件</div>
|
||||
<div>是否确认提交作品?</div>
|
||||
</div>,
|
||||
onOk: () => {
|
||||
this.doCommit(values, listid, userids)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.doCommit(values, listid, userids)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
doCommit = (values, listid, userids) => {
|
||||
let workId=this.props.match.params.workId;
|
||||
let studentWorkId=this.props.match.params.studentWorkId;
|
||||
let coursesId=this.props.match.params.coursesId;
|
||||
|
||||
// let url="/graduation_tasks/"+id+"/graduation_works.json";
|
||||
let url = `/homework_commons/${workId}/student_works.json`
|
||||
const moduleName = this.props.getModuleName()
|
||||
if (this.isEdit) {
|
||||
url = `/student_works/${studentWorkId}.json`
|
||||
axios.put(url, {
|
||||
description:values.description,
|
||||
attachment_ids:listid,
|
||||
user_ids:userids
|
||||
}
|
||||
).then((response) => {
|
||||
if(response.status===200) {
|
||||
if(response.data.status===0){
|
||||
// this.props.showNotification('保存成功')
|
||||
}else{
|
||||
}
|
||||
this.props.history.push(`/courses/${coursesId}/${moduleName}/${workId}/${studentWorkId}/appraise`)
|
||||
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
} else {
|
||||
axios.post(url, {
|
||||
description:values.description,
|
||||
attachment_ids:listid,
|
||||
user_ids:userids
|
||||
}
|
||||
).then((response) => {
|
||||
if(response.status===200) {
|
||||
if(response.data.status===0){
|
||||
this.props.history.push(`/courses/${coursesId}/${moduleName}/${workId}/${response.data.work_id}/appraise`)
|
||||
// this.props.showNotification('保存成功')
|
||||
// this.setState({
|
||||
// Modalstype:true,
|
||||
// Modalstopval:response.data.message,
|
||||
// ModalSave:()=>this.setedit(response.data.work_id),
|
||||
// Loadtype:true
|
||||
// })
|
||||
}else{
|
||||
}
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
handleSelectChange = (value) => {
|
||||
console.log(value);
|
||||
this.props.form.setFieldsValue({
|
||||
note: `Hi, ${value === 'male' ? 'man' : 'lady'}!`,
|
||||
});
|
||||
}
|
||||
|
||||
goback=()=>{
|
||||
// this.props.toListPage(this.props.match.params, this.state.category ? this.state.category.category_id : '')
|
||||
this.props.history.goBack()
|
||||
}
|
||||
|
||||
|
||||
// 输入title
|
||||
changeTitle=(e)=>{
|
||||
|
||||
this.setState({
|
||||
title_num:20-parseInt(e.target.value.length),
|
||||
title_value:e.target.value
|
||||
})
|
||||
|
||||
}
|
||||
// 附件相关 START
|
||||
handleChange = (info) => {
|
||||
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
|
||||
let fileList = info.fileList;
|
||||
|
||||
this.setState({ fileList: appendFileSizeToUploadFileAll(fileList) });
|
||||
}
|
||||
}
|
||||
|
||||
onAttachmentRemove = (file) => {
|
||||
// confirm({
|
||||
// title: '确定要删除这个附件吗?',
|
||||
// okText: '确定',
|
||||
// cancelText: '取消',
|
||||
// // content: 'Some descriptions',
|
||||
// onOk: () => {
|
||||
// this.deleteAttachment(file)
|
||||
// },
|
||||
// onCancel() {
|
||||
// console.log('Cancel');
|
||||
// },
|
||||
// });
|
||||
// return false;
|
||||
|
||||
// this.setState({
|
||||
// Modalstype:true,
|
||||
// // Modalstopval:'确定要删除这个附件吗?',
|
||||
// Modalstopval:'是否确认删除?',
|
||||
// ModalSave: ()=>this.deleteAttachment(file),
|
||||
// ModalCancel:this.cancelAttachment
|
||||
// })
|
||||
if (file.delete === false) {
|
||||
this.props.showNotification(`该作品已被评阅,不能删除该附件`);
|
||||
return false
|
||||
} else {
|
||||
if (!file.percent || file.percent == 100) {
|
||||
this.props.confirm({
|
||||
content: '是否确认删除?',
|
||||
onOk: () => {
|
||||
this.deleteAttachment(file)
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cancelAttachment=()=>{
|
||||
this.setState({
|
||||
Modalstype:false,
|
||||
// Modalstopval:'确定要删除这个附件吗?',
|
||||
Modalstopval:'是否确认删除?',
|
||||
ModalSave:"",
|
||||
ModalCancel:""
|
||||
})
|
||||
}
|
||||
|
||||
deleteAttachment = (file) => {
|
||||
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
|
||||
axios.delete(url, {
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data) {
|
||||
// const { status } = response.data;
|
||||
if (response.data.status === 0) {
|
||||
|
||||
console.log('--- success')
|
||||
// this.setState({
|
||||
// Modalstype:true,
|
||||
// Modalstopval:response.data.message,
|
||||
// ModalSave:this.cancelAttachment,
|
||||
// Loadtype:true,
|
||||
// })
|
||||
|
||||
this.setState((state) => {
|
||||
const index = state.fileList.indexOf(file);
|
||||
const newFileList = state.fileList.slice();
|
||||
newFileList.splice(index, 1);
|
||||
return {
|
||||
fileList: newFileList,
|
||||
};
|
||||
});
|
||||
|
||||
this.cancelAttachment()
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
inputSearchValue=(e)=>{
|
||||
|
||||
if(e.target.value===""){
|
||||
this.setState({
|
||||
search:null
|
||||
})
|
||||
}else{
|
||||
this.setState({
|
||||
search:e.target.value
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
searchValue=()=>{
|
||||
|
||||
let {search, limit} = this.state;
|
||||
|
||||
this.searchList(search,1, limit)
|
||||
|
||||
}
|
||||
|
||||
searchList=(search,page,limit)=>{
|
||||
|
||||
let id=this.props.match.params.workId;
|
||||
let workId=this.props.match.params.workId;
|
||||
// let url="/graduation_tasks/"+id+"/graduation_works/search_member_list.json";
|
||||
let url = `/homework_commons/${workId}/student_works/search_member_list.json`
|
||||
axios.get(url,{
|
||||
params: {
|
||||
search: search,
|
||||
page: page,
|
||||
limit: limit
|
||||
}
|
||||
}).then((result)=>{
|
||||
|
||||
if(result){
|
||||
this.setState({
|
||||
page: result.data.members.length == 0 ? page - 1 : page,
|
||||
members: page != 1 && search == this.state.lastSearch ? this.state.members.concat(result.data.members) : result.data.members,
|
||||
search: search,
|
||||
lastSearch: search,
|
||||
})
|
||||
}
|
||||
|
||||
}).catch((error)=>{
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
contentViewScroll=(e)=>{
|
||||
//滑动到底判断
|
||||
let newscrollTop=parseInt(e.currentTarget.scrollTop);
|
||||
let allclientHeight=e.currentTarget.clientHeight+newscrollTop;
|
||||
|
||||
if(e.currentTarget.scrollHeight-allclientHeight===0||e.currentTarget.scrollHeight-allclientHeight===1||e.currentTarget.scrollHeight-allclientHeight===-1){
|
||||
// console.log("到达底部");
|
||||
|
||||
let{ search,page,limit }=this.state;
|
||||
|
||||
let newpage=page+1
|
||||
|
||||
this.searchList(search,newpage,limit)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
funtaskstatus=(checkedValues)=>{
|
||||
/**
|
||||
比较 checkedValues 和 this.state.selectmemberslist
|
||||
checkedValues length > this.state.task_status.length 是新增; 反之是删除
|
||||
比较找到不同的id
|
||||
去除重复的,checkedValues留下的是新增,task_status留下的是删除
|
||||
*/
|
||||
|
||||
const _checkedValues = checkedValues.slice(0)
|
||||
const _task_status = this.state.task_status.slice(0);
|
||||
checkedValues.forEach(item => {
|
||||
this.state.task_status.forEach(_item => {
|
||||
if (item == _item) {
|
||||
_.remove(_checkedValues, (item)=> item == _item)
|
||||
_.remove(_task_status, (item)=> item == _item)
|
||||
}
|
||||
})
|
||||
})
|
||||
let _selectmemberslist = this.state.selectmemberslist.slice(0)
|
||||
if (_checkedValues.length) { // 新增
|
||||
_selectmemberslist.push( this.state.members.filter(item => item.user_id == _checkedValues[0])[0])
|
||||
} else if (_task_status.length) { // 删除
|
||||
_.remove(_selectmemberslist, (item)=> item.user_id == _task_status[0])
|
||||
}
|
||||
|
||||
|
||||
// let{members}=this.state;
|
||||
// let newlist =members.concat(this.state.selectmemberslist);
|
||||
// let newcheckedValues=checkedValues;
|
||||
// let selects= this.mine ? [this.mine] : [];
|
||||
// // const selectobjct = this._findByUserId(check)
|
||||
// // selects.push(selectobjct)
|
||||
// for(var z=0; z<newcheckedValues.length; z++){
|
||||
// for(var i=0; i<newlist.length; i++){
|
||||
// if(newlist[i].user_id===newcheckedValues[z]){
|
||||
// selects.push(newlist[i])
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
this.setState({
|
||||
task_status:checkedValues,
|
||||
selectmemberslist: _selectmemberslist
|
||||
// selectmemberslist:checkedValues
|
||||
})
|
||||
|
||||
}
|
||||
doDelete = (id) => {
|
||||
let{selectmemberslist,task_status}=this.state;
|
||||
let newlist=task_status.slice(0);
|
||||
let selects=selectmemberslist;
|
||||
|
||||
for(var i=0; i<newlist.length; i++){
|
||||
if(newlist[i]===id){
|
||||
newlist.splice(i,1)
|
||||
}
|
||||
}
|
||||
|
||||
for(var z=0; z<selects.length; z++){
|
||||
if(selects[z].user_id===id){
|
||||
selects.splice(z,1)
|
||||
}
|
||||
}
|
||||
this.setState({
|
||||
task_status:newlist,
|
||||
selectmemberslist:selects
|
||||
})
|
||||
}
|
||||
delecttask_status=(id)=>{
|
||||
if (this.isEdit) {
|
||||
let deleteOldMemberIndex = -1;
|
||||
|
||||
if (this._edit_init_memebers && this._edit_init_memebers.length) {
|
||||
this._edit_init_memebers.some((item, index) => {
|
||||
if (item.user_id == id) {
|
||||
deleteOldMemberIndex = index;
|
||||
return true
|
||||
}
|
||||
})
|
||||
if (deleteOldMemberIndex == -1) {
|
||||
this.doDelete(id)
|
||||
return;
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.props.confirm({
|
||||
content: <div>
|
||||
<div>TA的作品将被删除</div>
|
||||
<div>是否确认删除?</div>
|
||||
</div>,
|
||||
onOk: () => {
|
||||
let workId=this.props.match.params.workId;
|
||||
const url = `/homework_commons/${workId}/student_works/delete_work.json`;
|
||||
axios.delete(url, { data: {
|
||||
user_id: id
|
||||
}})
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.searchValue()
|
||||
this.doDelete(id)
|
||||
deleteOldMemberIndex != -1 && this._edit_init_memebers.splice(deleteOldMemberIndex, 1)
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.doDelete(id)
|
||||
}
|
||||
}
|
||||
|
||||
gocannel=()=>{
|
||||
this.props.history.goBack()
|
||||
}
|
||||
|
||||
render(){
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const isEdit = this.isEdit
|
||||
let {search,fileList, workslist,setvalue,minvalue,minmaxtype,Loadtype,
|
||||
Modalstype,Modalstopval,ModalCancel,ModalSave,task_status,selectmemberslist,members,
|
||||
category,
|
||||
course_name, homework_name,
|
||||
memberNumMax, memberNumMin
|
||||
} =this.state;
|
||||
const { current_user } = this.props
|
||||
|
||||
let courseId=this.props.match.params.coursesId;
|
||||
let workId=this.props.match.params.workId;
|
||||
const uploadProps = {
|
||||
width: 600,
|
||||
fileList,
|
||||
multiple: true,
|
||||
// https://github.com/ant-design/ant-design/issues/15505
|
||||
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
|
||||
// showUploadList: false,
|
||||
action: `${getUploadActionUrl()}`,
|
||||
onChange: this.handleChange,
|
||||
onRemove: this.onAttachmentRemove,
|
||||
beforeUpload: (file) => {
|
||||
// TODO 文件存在则提示并退出
|
||||
let gotSameFile = false;
|
||||
this.state.fileList && this.state.fileList.some((item) => {
|
||||
if (item.name && item.name.startsWith(file.name)) {
|
||||
gotSameFile = true;
|
||||
return true
|
||||
}
|
||||
})
|
||||
if (gotSameFile) {
|
||||
this.props.showNotification("该附件已被上传!")
|
||||
return false
|
||||
}
|
||||
console.log('beforeUpload', file.name);
|
||||
const isLt150M = file.size / 1024 / 1024 < 150;
|
||||
if (!isLt150M) {
|
||||
this.props.showNotification('文件大小必须小于150MB!');
|
||||
}
|
||||
return isLt150M;
|
||||
},
|
||||
};
|
||||
|
||||
// console.log(workslist&&workslist)
|
||||
|
||||
// console.log(selectmemberslist&&selectmemberslist)
|
||||
const moduleName = this.props.getModuleName()
|
||||
const moduleCHName = this.props.getModuleName(true)
|
||||
const isGroup = this.props.isGroup()
|
||||
|
||||
return(
|
||||
<React.Fragment>
|
||||
|
||||
<div>
|
||||
{/*提示*/}
|
||||
<Modals
|
||||
modalsType={Modalstype}
|
||||
modalsTopval={Modalstopval}
|
||||
modalCancel={ModalCancel}
|
||||
modalSave={ModalSave}
|
||||
loadtype={Loadtype}
|
||||
/>
|
||||
<div className="newMain clearfix">
|
||||
<div className={"educontent mb20"}>
|
||||
|
||||
<p className="clearfix mt10">
|
||||
<WordsBtn style="grey" className="fl"> <Link to={ current_user && current_user.first_category_url} className="color-grey-6">{course_name}</Link></WordsBtn>
|
||||
<span className="color-grey-9 fl ml3 mr3">></span>
|
||||
<WordsBtn style="grey" className="fl"> <Link to={`/courses/${courseId}/${moduleName}/${workId}`} className="color-grey-6">{moduleCHName}</Link></WordsBtn>
|
||||
<span className="color-grey-9 fl ml3 mr3">></span>
|
||||
{/*<WordsBtn style="grey" className="fl">*/}
|
||||
{/*<Link to={"/courses/"+courseId+"/graduation/graduation_tasks/"+category_id} className="color-grey-6">{workslist&&workslist.task_name}</Link>*/}
|
||||
{/*<span className="color-grey-9 ml3 mr3">></span>*/}
|
||||
{/*</WordsBtn>*/}
|
||||
|
||||
<span>{`${current_user ? current_user.real_name : ''} ${ this.isEdit ? '编辑' : '提交'}作品` }</span>
|
||||
</p>
|
||||
|
||||
<div style={{ width:'100%',height:'75px'}} >
|
||||
<p className=" fl color-black mt25 summaryname" title={homework_name}>{homework_name}</p>
|
||||
<a className="color-grey-6 fr font-16 ml30 mt10 mr20" onClick={this.goback}>返回</a>
|
||||
</div>
|
||||
|
||||
{/* */}
|
||||
<Form >
|
||||
<div className="stud-class-set pd20 coursenavbox edu-back-white">
|
||||
<style>{`
|
||||
.uploadBtn.ant-btn {
|
||||
border: none;
|
||||
color: #4CACFF;
|
||||
box-shadow: none;
|
||||
background: transparent;
|
||||
padding: 0 6px;
|
||||
}
|
||||
.ant-upload-list-item:hover .ant-upload-list-item-info{
|
||||
background-color:#fff;
|
||||
}
|
||||
|
||||
.upload_1 .ant-upload-list {
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
`}</style>
|
||||
<Form.Item
|
||||
label="内容"
|
||||
style={{marginBottom: '4px'}}
|
||||
className="mdInForm"
|
||||
|
||||
>
|
||||
{getFieldDecorator('description', {
|
||||
rules: [{
|
||||
required: true, message: '请输入作品内容',
|
||||
}, {
|
||||
max: 5000, message: '最大限制为5000个字符',
|
||||
}],
|
||||
})(
|
||||
<TPMMDEditor ref={this.mdRef} placeholder={'请在此输入作业内容或作业附件的简要描述,最大限制为5000个字符'} maxLent={"5000"}
|
||||
mdID={'courseMessageMD'} initValue={this.editTopic ? this.editTopic.content : ''} className="courseMessageMD"></TPMMDEditor>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Upload {...uploadProps} className="upload_1 upload_under_markdown_editor">
|
||||
<Button className="uploadBtn">
|
||||
<Icon type="upload" /> 上传附件
|
||||
</Button>
|
||||
<span className={"color-grey-9"}>(单个文件150M以内)</span>
|
||||
</Upload>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{!isGroup?"":
|
||||
<div className="stud-class-set pd20 coursenavbox edu-back-white" style={{borderTop: '1px solid #EAEAEA'}}>
|
||||
<Form.Item
|
||||
label="小组成员"
|
||||
|
||||
>
|
||||
<div>
|
||||
<div className={"fl ml20"}>成员要求:{memberNumMin}~{memberNumMax}人</div>
|
||||
<Search
|
||||
className={"fl mt5 ml20"}
|
||||
style={{width:"20%"}}
|
||||
placeholder="请输入姓名或学号搜索"
|
||||
id="subject_search_input"
|
||||
value={search}
|
||||
onInput={this.inputSearchValue}
|
||||
onSearch={this.searchValue}
|
||||
autoComplete="off"
|
||||
></Search>
|
||||
</div>
|
||||
|
||||
|
||||
</Form.Item>
|
||||
|
||||
<style>{`
|
||||
.fonthidden{
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space:nowrap
|
||||
}
|
||||
.members.fl {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
`}</style>
|
||||
|
||||
<div className={"ml20"} style={{width:"100%"}}>
|
||||
|
||||
<div className={"members workPost fl"}
|
||||
onScroll={this.contentViewScroll}>
|
||||
<CheckboxGroup value={task_status} onChange={this.funtaskstatus} style={{ paddingTop: '4px'}}>
|
||||
{members.map((item,key)=>{
|
||||
return(
|
||||
<div key={key} style={{
|
||||
// width: '375px',
|
||||
height: '30px'
|
||||
}}>
|
||||
<Checkbox value={item.user_id} key={item.user_id} checked={parseInt(task_status[key])===item.user_id?true:false}
|
||||
disabled={item.commit_status || item.user_id == this.props.current_user.user_id ===true?true:false} className="fl "
|
||||
></Checkbox>
|
||||
<Tooltip placement="bottom" title={item.user_nam}><div className={"fl ml5 fonthidden"} style={{width: '70px'}}>{item.user_name}</div></Tooltip>
|
||||
<div className={"fl ml20 color-grey-9 overflowHidden1"} style={{ maxWidth: '147px' }}
|
||||
title={item.group_name && item.group_name.length > 9 ? item.group_name : ''}
|
||||
>{item.group_name}</div>
|
||||
<div className={"fl ml20 color-grey-9 overflowHidden1"} style={{ maxWidth: '99px' }}
|
||||
title={item.student_id && item.student_id.length > 12 ? item.student_id : ''}
|
||||
>{item.student_id}</div>
|
||||
<div className={"fl ml20"}>{item.commit_status===true?<span className={"color-orange"}>已提交</span> :""}</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</CheckboxGroup>
|
||||
</div>
|
||||
|
||||
<div className={"youjiangboxs"}>
|
||||
<i className={"iconfont icon-youjiang fl ml20 mr20"}></i>
|
||||
</div>
|
||||
<style>{`
|
||||
.fonthidden{
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space:nowrap
|
||||
}
|
||||
.members .leaderIcon {
|
||||
}
|
||||
.workPost.members {
|
||||
width: 452px;
|
||||
}
|
||||
`}</style>
|
||||
<div className={"members workPost fl"}>
|
||||
|
||||
{selectmemberslist&&selectmemberslist.map((item,key)=>{
|
||||
const _is_leader = (item.is_leader || !this.isEdit && key==0)
|
||||
return(
|
||||
<div key={key} style={{
|
||||
// width: '375px',
|
||||
height: '30px',
|
||||
display:item.user_name===undefined?"none":""
|
||||
}}>
|
||||
<ConditionToolTip placement="bottom" title={'组长'} condition={_is_leader && item.user_name.length > 5}>
|
||||
<div className={"fl ml5 fonthidden"} style={{width: '98px', color: `${item.user_name.length > 5 && _is_leader ? '#4CACFF' : 'inherit'}`}}>
|
||||
{item.user_name}{ item.user_name.length <= 5 && _is_leader && <LeaderIcon className="leaderIcon" small={true}></LeaderIcon>}
|
||||
</div>
|
||||
</ConditionToolTip>
|
||||
|
||||
<div className={"fl ml20 color-grey-9 overflowHidden1"} style={{ maxWidth: '147px' }}
|
||||
title={item.group_name && item.group_name.length > 9 ? item.group_name : ''}
|
||||
>{item.group_name}</div>
|
||||
<div className={"fl ml20 color-grey-9 overflowHidden1"} style={{ maxWidth: '99px' }}
|
||||
title={item.student_id && item.student_id.length > 12 ? item.student_id : ''}
|
||||
>{item.student_id}</div>
|
||||
{item.user_id != this.props.current_user.user_id ?
|
||||
<div className={"fr"}><i className={"iconfont icon-shanchudiao fl "}
|
||||
style={{marginTop:'-4px'}} onClick={()=>this.delecttask_status(item.user_id)}></i></div>:""}
|
||||
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
|
||||
<div className={"both"}>
|
||||
|
||||
</div>
|
||||
|
||||
{minmaxtype===true?<span className={"color-red mt20"}>
|
||||
人数不能{setvalue+minvalue}个人
|
||||
</span>:""}
|
||||
|
||||
</div>
|
||||
</div>}
|
||||
|
||||
|
||||
|
||||
|
||||
<Form.Item>
|
||||
<div className="clearfix mt30 mb30">
|
||||
<Button type="primary" onClick={this.handleSubmit} className="defalutSubmitbtn fl mr20">提交</Button>
|
||||
<a onClick={this.gocannel} className="defalutCancelbtn fl">取消</a>
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
const CommonWorkPostApp = Form.create({ name: 'coursesNew' })(CommonWorkPost);
|
||||
export default CommonWorkPostApp;
|
||||
@@ -0,0 +1,130 @@
|
||||
import React,{Component} from "react";
|
||||
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal, Table, Divider, Tag,DatePicker,Radio,Tooltip} from "antd";
|
||||
import {Link} from 'react-router-dom';
|
||||
import locale from 'antd/lib/date-picker/locale/zh_CN';
|
||||
import { WordsBtn, MarkdownToHtml, on, off } from 'educoder';
|
||||
import axios from 'axios';
|
||||
import Modals from '../../modals/Modals';
|
||||
import CoursesListType from '../coursesPublic/CoursesListType';
|
||||
import HomeworkModal from "../coursesPublic/HomeworkModal";
|
||||
import CheckAllGroup from '../common/button/CheckAllGroup'
|
||||
import moment from 'moment';
|
||||
import CheckCodeModal from '../coursesPublic/modal/CheckCodeModal'
|
||||
import '../css/Courses.css'
|
||||
import WorkDetailPageHeader from './common/WorkDetailPageHeader'
|
||||
import CommonReply from '../common/comments/CommonReply.js'
|
||||
import TabRightComponents from './common/TabRightComponents'
|
||||
const { Option} = Select;
|
||||
const CheckboxGroup = Checkbox.Group;
|
||||
const confirm = Modal.confirm;
|
||||
let GraduationTasksnewtype=true;
|
||||
const $ = window.$;
|
||||
const Search = Input.Search;
|
||||
const RadioGroup = Radio.Group;
|
||||
|
||||
class CommonWorkQuestion extends Component{
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
|
||||
this.state={
|
||||
course_name:"",
|
||||
homework_name:"",
|
||||
search: ''
|
||||
}
|
||||
}
|
||||
fetchData = () => {
|
||||
let workId=this.props.match.params.workId;
|
||||
const url = `/homework_commons/${workId}.json`
|
||||
|
||||
axios.get(url).then((result)=> {
|
||||
if (result.data.course_id) {
|
||||
|
||||
this.setState({
|
||||
...result.data
|
||||
}, () => {
|
||||
})
|
||||
this.props.initWorkDetailCommonState && this.props.initWorkDetailCommonState( Object.assign({...result.data}, {
|
||||
moduleName: '作业描述'
|
||||
}))
|
||||
}
|
||||
|
||||
}).catch((error)=>{
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
componentDidMount() {
|
||||
this.fetchData()
|
||||
try {
|
||||
this.props.triggerRef(this);
|
||||
}catch (e) {
|
||||
|
||||
}
|
||||
on('commonwork_fetch_all', this.fetchAllListener)
|
||||
}
|
||||
componentWillUnmount() {
|
||||
off('commonwork_fetch_all', this.fetchAllListener)
|
||||
}
|
||||
fetchAllListener = () => {
|
||||
this.fetchData()
|
||||
}
|
||||
|
||||
|
||||
render(){
|
||||
const dateFormat = 'YYYY-MM-DD HH:mm';
|
||||
|
||||
let {course_name, homework_name, search, page, loadingstate, homework_status, description
|
||||
, homework_id, homework_user_id, attachments, group_info = {}
|
||||
} =this.state;
|
||||
|
||||
let courseId=this.props.match.params.coursesId;
|
||||
let category_id=this.props.match.params.category_id;
|
||||
let task_Id=this.props.match.params.task_Id;
|
||||
const isGroup = this.props.isGroup()
|
||||
|
||||
return(
|
||||
<React.Fragment>
|
||||
|
||||
{/* 内容区 */}
|
||||
<div className="padding40 memoContent new_li">
|
||||
<MarkdownToHtml content={description} selector="work_content" className="mb10"></MarkdownToHtml>
|
||||
|
||||
{ attachments && attachments.map((item) => {
|
||||
return ( <div className="color-grey">
|
||||
<a className="color-grey">
|
||||
<i className="font-14 color-green iconfont icon-fujian mr8" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a href={item.url} className="mr12" length="58">{item.title}</a>
|
||||
<span className="color-grey mt2 color-grey-6 font-12">{item.filesize}</span>
|
||||
</div> )
|
||||
}) }
|
||||
|
||||
{isGroup && <div className="df mt10">
|
||||
<div style={{flex: '0 0 160px'}}>
|
||||
<div>分组要求: {group_info.min_num} ~ {group_info.max_num}人</div>
|
||||
<div>{group_info.base_on_project ? '基于项目实施' : '不基于项目'}:</div>
|
||||
</div>
|
||||
<div style={{color: '#9B9B9B'}}>
|
||||
<div>(学生提交作品时需要关联同组成员,组内成员作品共享)</div>
|
||||
<div>({group_info.base_on_project ? '学生必须在本平台创建项目,项目管理员可以提交作品' : '无需在平台创建项目,任意小组成员均可以提交作品'})</div>
|
||||
{/* <div>(各小组必须在educoder平台创建项目)</div> */}
|
||||
</div>
|
||||
</div>}
|
||||
|
||||
</div>
|
||||
|
||||
{ homework_id && <CommonReply
|
||||
memo={{
|
||||
id: homework_id,
|
||||
}}
|
||||
course_id={courseId} {...this.props}
|
||||
apiRouteName={'homework_commons'}
|
||||
jour_type={'HomeworkCommon'}
|
||||
></CommonReply> }
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default CommonWorkQuestion;
|
||||
@@ -0,0 +1,186 @@
|
||||
import React,{ Component } from "react";
|
||||
import {Radio,Input ,Modal} from "antd";
|
||||
|
||||
import '../css/members.css'
|
||||
import { WordsBtn } from 'educoder'
|
||||
import axios from 'axios'
|
||||
import InfiniteScroll from 'react-infinite-scroller';
|
||||
import NoneData from "../coursesPublic/NoneData"
|
||||
|
||||
const Search =Input.Search;
|
||||
const LIMIT = 15
|
||||
class ConnectProject extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
project_flag:false,
|
||||
page: 1,
|
||||
loading: false,
|
||||
hasMore: true,
|
||||
keyword: ''
|
||||
}
|
||||
}
|
||||
componentDidMount() {
|
||||
|
||||
}
|
||||
onSubmit = () => {
|
||||
const { radioValue, projects } = this.state;
|
||||
if (projects.length === 0) {
|
||||
this.closeConnectionProject()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!radioValue) {
|
||||
this.props.showNotification('请先在下面的列表中选择项目')
|
||||
return;
|
||||
}
|
||||
this.connectProject(radioValue)
|
||||
}
|
||||
connectProject = (project_id) => {
|
||||
let workId=this.work.homework_id;
|
||||
const url = `/homework_commons/${workId}/student_works/relate_project.json`
|
||||
axios.post(url, {
|
||||
project_id: project_id
|
||||
}).then((result)=>{
|
||||
if(result.data.status==0){
|
||||
this.closeConnectionProject()
|
||||
this.props.connectSuccess()
|
||||
this.props.showNotification('关联成功')
|
||||
}
|
||||
}).catch((error)=>{
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
onSearchValue = () => {
|
||||
this.fetchData(1)
|
||||
}
|
||||
fetchData = (page = 1) => {
|
||||
// https://www.showdoc.cc/127895880302646?page_id=2032696709966819
|
||||
|
||||
// https://www.showdoc.cc/page/edit/127895880302646/2228554041379772
|
||||
// /${this.props.current_user.user_id}
|
||||
const url = `/users/projects/search.json`
|
||||
this.setState({ loading: true })
|
||||
const { keyword } = this.state;
|
||||
axios.get(url, {
|
||||
params: {
|
||||
page: page,
|
||||
per_page: LIMIT,
|
||||
keyword: keyword
|
||||
}
|
||||
}).then((result)=>{
|
||||
if(result.status==200){
|
||||
this.setState({
|
||||
count: result.data.count,
|
||||
projects: page == 1 ? result.data.projects : this.state.projects.concat(result.data.projects),
|
||||
page: page,
|
||||
loading: false,
|
||||
hasMore: result.data.projects.length != 0
|
||||
})
|
||||
if (page == 1) {
|
||||
this.setState({ haveProjects: result.data.projects.length > 0 })
|
||||
}
|
||||
}
|
||||
}).catch((error)=>{
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
//关联项目
|
||||
openConnectionProject=(work)=>{
|
||||
this.work = work;
|
||||
this.fetchData()
|
||||
this.setState({
|
||||
project_flag:true
|
||||
})
|
||||
}
|
||||
closeConnectionProject=()=>{
|
||||
this.setState({
|
||||
project_flag:false
|
||||
})
|
||||
}
|
||||
onChange = (e) => {
|
||||
this.setState({ radioValue: e.target.value })
|
||||
}
|
||||
|
||||
render(){
|
||||
let {project_flag, projects, loading, hasMore, haveProjects }=this.state;
|
||||
return(
|
||||
<React.Fragment>
|
||||
<Modal
|
||||
visible={project_flag}
|
||||
title="关联项目"
|
||||
centered={true}
|
||||
closable={false}
|
||||
keyboard={false}
|
||||
width="600px"
|
||||
footer={null}
|
||||
destroyOnClose={true}
|
||||
>
|
||||
<style>{`
|
||||
.connectProject .ant-radio {
|
||||
float: left;
|
||||
line-height: 18px;
|
||||
}
|
||||
.connectProject .ant-radio-wrapper .name {
|
||||
max-width: 480px;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.connectProject .ant-radio-wrapper>span:last-child {
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
`}</style>
|
||||
<div className="newupload_conbox clearfix connectProject">
|
||||
{
|
||||
(projects && !!projects.length || this.state.keyword) &&
|
||||
<div>
|
||||
<Search placeholder="请输入项目名称进行搜索" className="with100"
|
||||
value={this.state.keyword} onInput={(e) => {this.setState({keyword: e.target.value})}}
|
||||
onSearch={this.onSearchValue}
|
||||
></Search>
|
||||
<Radio.Group onChange={this.onChange} value={this.state.radioValue} className={"with100"}>
|
||||
<div className="mt15" style={{"maxHeight":"228px","overflow-y":"auto", "overflow-x": 'hidden'}}>
|
||||
<InfiniteScroll
|
||||
threshold={20}
|
||||
initialLoad={false}
|
||||
pageStart={0}
|
||||
loadMore={() => this.fetchData(this.state.page + 1)}
|
||||
hasMore={!loading && hasMore}
|
||||
useWindow={false}
|
||||
>
|
||||
{ projects.map(item => {
|
||||
return <p className="mb7" key={item.id}><Radio value={item.id}>
|
||||
<span title={item.name.length > 12 ? item.name : ''} className="name">{item.name}</span>
|
||||
</Radio></p>
|
||||
})}
|
||||
</InfiniteScroll>
|
||||
</div>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
haveProjects && projects.length == 0 &&
|
||||
<NoneData></NoneData>
|
||||
}
|
||||
{
|
||||
(!haveProjects) &&
|
||||
<div className="edu-txt-center">
|
||||
您当前尚未管理任何项目,请先<WordsBtn style="blue" className="" onClick={this.props.toCreateProject}>创建项目</WordsBtn>再关联
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
<div className="mt30 marginauto clearfix edu-txt-center">
|
||||
<a onClick={this.closeConnectionProject} className="pop_close task-btn mr30">取消</a>
|
||||
<a className="task-btn task-btn-orange" onClick={this.onSubmit}>确定</a>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default ConnectProject;
|
||||
@@ -0,0 +1,142 @@
|
||||
import React, { Component } from 'react';
|
||||
import { SnackbarHOC } from 'educoder';
|
||||
import {BrowserRouter as Router,Route,Switch} from 'react-router-dom';
|
||||
import Loadable from 'react-loadable';
|
||||
import Loading from '../../../Loading';
|
||||
import { CNotificationHOC } from '../common/CNotificationHOC'
|
||||
import { RouteHOC } from './common'
|
||||
import "../css/busyWork.css"
|
||||
//引入对应跳转的组件
|
||||
const ListPageIndex = Loadable({
|
||||
loader: () => import('../ListPageIndex'),
|
||||
loading:Loading,
|
||||
})
|
||||
//新建分组/普通作业
|
||||
const NewWork = Loadable({
|
||||
loader: () => import('./NewWork'),
|
||||
loading:Loading,
|
||||
})
|
||||
const CommonWorkDetailIndex = Loadable({
|
||||
loader: () => import('./CommonWorkDetailIndex'),
|
||||
loading:Loading,
|
||||
})
|
||||
const CommonWorkSetting = Loadable({
|
||||
loader: () => import('./CommonWorkSetting'),
|
||||
loading:Loading,
|
||||
})
|
||||
const CommonWorkList = Loadable({
|
||||
loader: () => import('./CommonWorkList'),
|
||||
loading:Loading,
|
||||
})
|
||||
const CommonWorkQuestion = Loadable({
|
||||
loader: () => import('./CommonWorkQuestion'),
|
||||
loading:Loading,
|
||||
})
|
||||
const CommonWorkAnswer = Loadable({
|
||||
loader: () => import('./CommonWorkAnswer'),
|
||||
loading:Loading,
|
||||
})
|
||||
const CommonWorkAppraise = Loadable({
|
||||
loader: () => import('./CommonWorkAppraise'),
|
||||
loading:Loading,
|
||||
})
|
||||
|
||||
const CommonWorkPost = Loadable({
|
||||
loader: () => import('./CommonWorkPost'),
|
||||
loading:Loading,
|
||||
})
|
||||
|
||||
const CommonWork = Loadable({
|
||||
loader: () => import('./commonWork'),
|
||||
loading:Loading,
|
||||
})
|
||||
class CoursesWorkIndex extends Component{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Switch {...this.props}>
|
||||
|
||||
{/* --------------------------------------------------------------------- */}
|
||||
|
||||
{/* 作业设置 */}
|
||||
{/* http://localhost:3007/courses/1309/homework/9300/setting */}
|
||||
<Route exact path="/courses/:coursesId/common_homeworks/:workId/setting"
|
||||
render={
|
||||
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 作品列表 */}
|
||||
<Route exact path="/courses/:coursesId/common_homeworks/:workId/list"
|
||||
render={
|
||||
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 作业问答 */}
|
||||
<Route exact path="/courses/:coursesId/common_homeworks/:workId/question"
|
||||
render={
|
||||
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route exact path="/courses/:coursesId/common_homeworks/:workId/answer"
|
||||
render={
|
||||
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 评阅 */}
|
||||
<Route exact path="/courses/:coursesId/common_homeworks/:workId/:studentWorkId/appraise"
|
||||
render={
|
||||
(props) => (<CommonWorkAppraise {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 提交作品 */}
|
||||
<Route exact path="/courses/:coursesId/common_homeworks/:workId/post"
|
||||
render={
|
||||
(props) => (<CommonWorkPost {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route exact path="/courses/:coursesId/common_homeworks/:workId/:studentWorkId/post_edit"
|
||||
render={
|
||||
(props) => (<CommonWorkPost {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
{/* 新建 */}
|
||||
{/* http://localhost:3007/courses/1309/common_homeworks/9299/edit/1 */}
|
||||
<Route exact path="/courses/:coursesId/common_homeworks/:workId/:pageType"
|
||||
render={
|
||||
(props) => (<NewWork {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route exact path="/courses/:coursesId/common_homeworks/:categroy_id/new"
|
||||
render={
|
||||
(props) => (<NewWork {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
|
||||
{/* 作业列表 */}
|
||||
<Route path="/courses/:coursesId/common_homeworks"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* --------------------------------------------------------------------- */}
|
||||
|
||||
|
||||
|
||||
</Switch>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default RouteHOC() (CNotificationHOC() (SnackbarHOC() ( CoursesWorkIndex) ));
|
||||
@@ -0,0 +1,140 @@
|
||||
import React, { Component } from 'react';
|
||||
import { SnackbarHOC } from 'educoder';
|
||||
import {BrowserRouter as Router,Route,Switch} from 'react-router-dom';
|
||||
import Loadable from 'react-loadable';
|
||||
import Loading from '../../../Loading';
|
||||
import { CNotificationHOC } from '../common/CNotificationHOC'
|
||||
import { RouteHOC } from './common'
|
||||
import "../css/busyWork.css"
|
||||
//引入对应跳转的组件
|
||||
const ListPageIndex = Loadable({
|
||||
loader: () => import('../ListPageIndex'),
|
||||
loading:Loading,
|
||||
})
|
||||
//新建分组/普通作业
|
||||
const NewWork = Loadable({
|
||||
loader: () => import('./NewWork'),
|
||||
loading:Loading,
|
||||
})
|
||||
const CommonWorkPost = Loadable({
|
||||
loader: () => import('./CommonWorkPost'),
|
||||
loading:Loading,
|
||||
})
|
||||
const CommonWorkSetting = Loadable({
|
||||
loader: () => import('./CommonWorkSetting'),
|
||||
loading:Loading,
|
||||
})
|
||||
const CommonWorkList = Loadable({
|
||||
loader: () => import('./CommonWorkList'),
|
||||
loading:Loading,
|
||||
})
|
||||
const CommonWorkQuestion = Loadable({
|
||||
loader: () => import('./CommonWorkQuestion'),
|
||||
loading:Loading,
|
||||
})
|
||||
const CommonWorkAnswer = Loadable({
|
||||
loader: () => import('./CommonWorkAnswer'),
|
||||
loading:Loading,
|
||||
})
|
||||
const CommonWorkAppraise = Loadable({
|
||||
loader: () => import('./CommonWorkAppraise'),
|
||||
loading:Loading,
|
||||
})
|
||||
|
||||
|
||||
const CommonWork = Loadable({
|
||||
loader: () => import('./commonWork'),
|
||||
loading:Loading,
|
||||
})
|
||||
|
||||
const CommonWorkDetailIndex = Loadable({
|
||||
loader: () => import('./CommonWorkDetailIndex'),
|
||||
loading:Loading,
|
||||
})
|
||||
class CoursesWorkIndex extends Component{
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Switch {...this.props}>
|
||||
|
||||
|
||||
{/* --------------------------------------------------------------------- */}
|
||||
|
||||
{/* --------------------------------------------------------------------- */}
|
||||
|
||||
{/* 作业设置 */}
|
||||
<Route exact path="/courses/:coursesId/group_homeworks/:workId/setting"
|
||||
render={
|
||||
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 作品列表 */}
|
||||
<Route exact path="/courses/:coursesId/group_homeworks/:workId/list"
|
||||
render={
|
||||
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 作业问答 */}
|
||||
<Route exact path="/courses/:coursesId/group_homeworks/:workId/question"
|
||||
render={
|
||||
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 参考答案 */}
|
||||
<Route exact path="/courses/:coursesId/group_homeworks/:workId/answer"
|
||||
render={
|
||||
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 评阅 */}
|
||||
<Route exact path="/courses/:coursesId/group_homeworks/:workId/:studentWorkId/appraise"
|
||||
render={
|
||||
(props) => (<CommonWorkAppraise {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
<Route exact path="/courses/:coursesId/group_homeworks/:workId/post"
|
||||
render={
|
||||
(props) => (<CommonWorkPost {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route exact path="/courses/:coursesId/group_homeworks/:workId/:studentWorkId/post_edit"
|
||||
render={
|
||||
(props) => (<CommonWorkPost {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 新建 */}
|
||||
{/* http://localhost:3007/courses/1309/group_homeworks/9299/edit/1 */}
|
||||
<Route exact path="/courses/:coursesId/group_homeworks/:workId/:pageType"
|
||||
render={
|
||||
(props) => (<NewWork {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route exact path="/courses/:coursesId/group_homeworks/:categroy_id/new"
|
||||
render={
|
||||
(props) => (<NewWork {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 作业列表 */}
|
||||
<Route path="/courses/:coursesId/group_homeworks"
|
||||
render={
|
||||
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
</Switch>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default RouteHOC() (CNotificationHOC() (SnackbarHOC() ( CoursesWorkIndex) ));
|
||||
@@ -0,0 +1,207 @@
|
||||
import React,{ Component } from "react";
|
||||
import { Input, InputNumber, Form, Button, Checkbox, Upload, Icon, message, Modal } from "antd";
|
||||
import axios from 'axios'
|
||||
import '../css/busyWork.css'
|
||||
import '../css/Courses.css'
|
||||
import { WordsBtn, getUrl, ConditionToolTip, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll
|
||||
, getUploadActionUrl } from 'educoder'
|
||||
import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
|
||||
import CBreadcrumb from '../common/CBreadcrumb'
|
||||
import NewWorkForm from './NewWorkForm'
|
||||
|
||||
const confirm = Modal.confirm;
|
||||
const $ = window.$
|
||||
const MAX_TITLE_LENGTH = 60;
|
||||
class NewWork extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.contentMdRef = React.createRef();
|
||||
this.answerMdRef = React.createRef();
|
||||
|
||||
this.state={
|
||||
category: {},
|
||||
course_name: ''
|
||||
}
|
||||
}
|
||||
componentDidMount () {
|
||||
let {typeId, coursesId, pageType, workId}=this.props.match.params;
|
||||
const isEdit = pageType === "edit"
|
||||
this.isEdit = isEdit;
|
||||
if (isEdit) {
|
||||
this.fetchWork(workId)
|
||||
} else {
|
||||
this.fetchCourseData(coursesId)
|
||||
}
|
||||
}
|
||||
fetchCourseData = (courseId) => {
|
||||
const isGroup = this.props.isGroup()
|
||||
const url = `/courses/${courseId}/homework_commons/new.json?type=${isGroup ? 3 : 1}`
|
||||
axios.get(url, {
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.course_name) {
|
||||
const data = response.data;
|
||||
this.setState({
|
||||
course_id: data.course_id,
|
||||
course_name: data.course_name,
|
||||
category: data.category,
|
||||
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
fetchWork = (workId) => {
|
||||
const url = `/homework_commons/${workId}/edit.json`
|
||||
axios.get(url, {
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data.name) {
|
||||
const data = response.data;
|
||||
data.isEdit = this.isEdit
|
||||
this.setState({
|
||||
course_id: data.course_id,
|
||||
course_name: data.course_name,
|
||||
category: data.category,
|
||||
})
|
||||
this.newWorkFormRef.initValue(response.data)
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
onCancel = () => {
|
||||
this.props.toListPage(this.props.match.params, this.state.category.category_id)
|
||||
}
|
||||
|
||||
doEdit = (params) => {
|
||||
const workId = this.props.match.params.workId
|
||||
const newUrl = `/homework_commons/${workId}.json`
|
||||
|
||||
axios.put(newUrl, params)
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.props.showNotification('保存成功')
|
||||
this.props.toWorkListPage(this.props.match.params, workId)
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
doNew = (params) => {
|
||||
const coursesId = this.props.match.params.coursesId
|
||||
const newUrl = `/courses/${coursesId}/homework_commons.json`
|
||||
|
||||
axios.post(newUrl, params)
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.props.showNotification('保存成功')
|
||||
this.props.toWorkListPage(this.props.match.params, response.data.homework_id)
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
handleContentUploadChange = (info) => {
|
||||
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
|
||||
let contentFileList = info.fileList;
|
||||
this.setState({ contentFileList: appendFileSizeToUploadFileAll(contentFileList) });
|
||||
}
|
||||
}
|
||||
handleAnswerUploadChange = (info) => {
|
||||
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
|
||||
let answerFileList = info.fileList;
|
||||
this.setState({ answerFileList: appendFileSizeToUploadFileAll(answerFileList) });
|
||||
}
|
||||
}
|
||||
|
||||
onAttachmentRemove = (file, stateName) => {
|
||||
if(!file.percent || file.percent == 100){
|
||||
this.props.confirm({
|
||||
content: '是否确认删除?',
|
||||
|
||||
onOk: () => {
|
||||
this.deleteAttachment(file, stateName)
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
render(){
|
||||
let {typeId,coursesId,pageType}=this.props.match.params;
|
||||
|
||||
const isGroup = this.props.isGroup()
|
||||
const moduleName = !isGroup? "普通作业":"分组作业";
|
||||
const moduleEngName = this.props.getModuleName()
|
||||
let{
|
||||
course_name, category
|
||||
}=this.state
|
||||
const { current_user } = this.props
|
||||
|
||||
const courseId = this.state.course_id || coursesId ;
|
||||
const isEdit = this.isEdit;
|
||||
|
||||
const common = {
|
||||
onCancel:this.onCancel,
|
||||
isGroup: this.props.isGroup,
|
||||
doNew: this.doNew,
|
||||
doEdit: this.doEdit,
|
||||
}
|
||||
document.title=this.state.course_name && this.state.course_name
|
||||
return(
|
||||
<div className="newMain">
|
||||
<div className="educontent mt20 mb50">
|
||||
<CBreadcrumb items={[
|
||||
{ to: current_user && current_user.first_category_url, name: this.state.course_name},
|
||||
{ to: `/courses/${courseId}/${moduleEngName}/${category && category.category_id ? category.category_id : ''}`
|
||||
, name: category && category.category_name },
|
||||
{ name: `${ this.isEdit ? '编辑' : '新建'}` }
|
||||
]}></CBreadcrumb>
|
||||
|
||||
<p className="clearfix mt20 mb20">
|
||||
<span className="fl font-24 color-grey-3">{this.isEdit ?"编辑":"新建"}{ moduleName }</span>
|
||||
<a href="javascript:void(0)" className="color-grey-6 fr font-16 mr2"
|
||||
onClick={() => this.props.history.goBack()}>
|
||||
返回
|
||||
</a>
|
||||
</p>
|
||||
<div>
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.yslnewworkinputaddonAfter .ant-input{
|
||||
border-right: none !important;
|
||||
height: 40px !important;
|
||||
}
|
||||
|
||||
`
|
||||
}
|
||||
</style>
|
||||
<NewWorkForm
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
{...common}
|
||||
wrappedComponentRef={(ref) => {this.newWorkFormRef = ref}}
|
||||
></NewWorkForm>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default NewWork;
|
||||
@@ -0,0 +1,555 @@
|
||||
import React,{ Component } from "react";
|
||||
import { Input, InputNumber, Form, Button, Checkbox, Upload, Icon, message, Modal } from "antd";
|
||||
import axios from 'axios'
|
||||
import '../css/busyWork.css'
|
||||
import '../css/Courses.css'
|
||||
import {getUploadActionUrl, ConditionToolTip, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll } from 'educoder'
|
||||
import TPMMDEditor from '../../tpm/challengesnew/TPMMDEditor';
|
||||
import CBreadcrumb from '../common/CBreadcrumb'
|
||||
|
||||
const confirm = Modal.confirm;
|
||||
const $ = window.$
|
||||
const MAX_TITLE_LENGTH = 60;
|
||||
|
||||
/**
|
||||
需要注意的props
|
||||
isGroup
|
||||
*/
|
||||
class NewWorkForm extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.contentMdRef = React.createRef();
|
||||
this.answerMdRef = React.createRef();
|
||||
|
||||
this.state={
|
||||
title_value:"",
|
||||
title_num: 0,
|
||||
contentFileList: [],
|
||||
answerFileList: [],
|
||||
workLoaded: false,
|
||||
base_on_project: true,
|
||||
category: {},
|
||||
min_num: 2,
|
||||
max_num: 10,
|
||||
}
|
||||
}
|
||||
initValue = (data) => {
|
||||
if (data.isEdit) {
|
||||
const contentFileList = data.attachments.map(item => {
|
||||
return {
|
||||
id: item.id,
|
||||
uid: item.id,
|
||||
name: appendFileSizeToUploadFile(item),
|
||||
url: item.url,
|
||||
filesize: item.filesize,
|
||||
status: 'done'
|
||||
}
|
||||
})
|
||||
const answerFileList = data.ref_attachments.map(item => {
|
||||
return {
|
||||
id: item.id,
|
||||
uid: item.id,
|
||||
name: appendFileSizeToUploadFile(item),
|
||||
url: item.url,
|
||||
filesize: item.filesize,
|
||||
status: 'done'
|
||||
}
|
||||
})
|
||||
|
||||
this.setState({
|
||||
...data,
|
||||
// course_id: data.course_id,
|
||||
// course_name: data.course_name,
|
||||
// category: data.category,
|
||||
title_num: parseInt(data.name.length),
|
||||
workLoaded: true,
|
||||
init_min_num: data.min_num,
|
||||
init_max_num: data.max_num,
|
||||
// description: data.description,
|
||||
reference_answer: data.reference_answer,
|
||||
contentFileList,
|
||||
answerFileList,
|
||||
}, () => {
|
||||
// setTimeout(() => {
|
||||
// this._scrollToTop()
|
||||
// 阻止setValue的滚动
|
||||
// $(window).scroll( function() {
|
||||
// $("html").scrollTop(0)
|
||||
// $(window).unbind("scroll");
|
||||
// });
|
||||
/**
|
||||
setValue会调用到 codemirror的 o.scrollIntoView(i), 会导致滚动条跳动
|
||||
*/
|
||||
// $('.editormd').parent().css('position', 'fixed').css('left', '-1000px')
|
||||
// this.contentMdRef.current.setValue(data.description || '')
|
||||
// this.answerMdRef.current.setValue(data.reference_answer || '')
|
||||
// setTimeout(() => {
|
||||
// $('.editormd').parent().css('position', '').css('left', 'auto')
|
||||
// }, 100);
|
||||
// }, 500)
|
||||
|
||||
this.props.form.setFieldsValue({
|
||||
title: data.name,
|
||||
description: data.description || '',
|
||||
reference_answer: data.reference_answer || '',
|
||||
});
|
||||
|
||||
})
|
||||
} else { // new
|
||||
|
||||
}
|
||||
// this._scrollToTop()
|
||||
}
|
||||
_scrollToTop = () => {
|
||||
// setTimeout(() => {
|
||||
$("html").scrollTop(0)
|
||||
// $("html").animate({ scrollTop: 0 })
|
||||
// }, 1000)
|
||||
}
|
||||
|
||||
// 输入title
|
||||
changeTitle=(e)=>{
|
||||
|
||||
this.setState({
|
||||
title_num: parseInt(e.target.value.length)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
handleSubmit = () => {
|
||||
const courseId = this.state.course_id || this.props.match.params.coursesId ;
|
||||
|
||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||
if(err && err.personNum) delete err.personNum;
|
||||
|
||||
const mdContnet = this.contentMdRef.current.getValue().trim();
|
||||
|
||||
values.description = mdContnet;
|
||||
// return;
|
||||
|
||||
{/* max={has_commit ? init_min_num : null } */}
|
||||
{/* min={has_commit ? init_max_num : (min_num == undefined ? 2 : min_num + 1) } */}
|
||||
// 已有提交作品,人数范围只能扩大
|
||||
const { has_commit, max_num, init_max_num, min_num, init_min_num } = this.state;
|
||||
const isGroup = this.props.isGroup()
|
||||
if (isGroup) {
|
||||
if (!min_num) {
|
||||
this.props.showNotification('最小人数不能为空');
|
||||
this.props.scrollToAnchor("numberofgroups");
|
||||
return;
|
||||
} else if (min_num < 1) {
|
||||
this.props.showNotification('最小人数不能小于1');
|
||||
this.props.scrollToAnchor("numberofgroups");
|
||||
return;
|
||||
} else if (!max_num) {
|
||||
this.props.showNotification('最大人数不能为空');
|
||||
this.props.scrollToAnchor("numberofgroups");
|
||||
return;
|
||||
} else if (max_num < min_num) {
|
||||
this.props.showNotification('最大人数不能小于最小人数');
|
||||
this.props.scrollToAnchor("numberofgroups");
|
||||
return;
|
||||
}
|
||||
|
||||
if (has_commit) {
|
||||
if (max_num < init_max_num || min_num > init_min_num) {
|
||||
this.props.showNotification(`已有提交作品,人数范围只能扩大(原设置为:${init_min_num} - ${init_max_num})`)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// const errKeys = Object.keys(err); // || errKeys.length == 1 && errKeys[0] == 'content' && mdContnet
|
||||
if (!err || Object.keys(err).length == 0) {
|
||||
if (this.state.isEdit) {
|
||||
this.doEdit(courseId, values)
|
||||
} else {
|
||||
this.doNew(courseId, values)
|
||||
}
|
||||
|
||||
} else {
|
||||
$("html").animate({ scrollTop: $('html').scrollTop() - 100 })
|
||||
}
|
||||
})
|
||||
}
|
||||
doEdit = (courseId, values) => {
|
||||
let attachment_ids = this.state.contentFileList.map(item => {
|
||||
return item.response ? item.response.id : item.id
|
||||
})
|
||||
let reference_attachment_ids = this.state.answerFileList.map(item => {
|
||||
return item.response ? item.response.id : item.id
|
||||
})
|
||||
|
||||
const { min_num, max_num, base_on_project, category } = this.state
|
||||
const isGroup = this.props.isGroup()
|
||||
|
||||
const params = {
|
||||
type: isGroup ? 3 : 1,
|
||||
name: values.title,
|
||||
description: values.description,
|
||||
reference_answer: values.reference_answer,
|
||||
attachment_ids,
|
||||
reference_attachment_ids,
|
||||
|
||||
min_num,
|
||||
max_num,
|
||||
base_on_project
|
||||
}
|
||||
this.props.doEdit && this.props.doEdit(params)
|
||||
}
|
||||
doNew = (courseId, values) => {
|
||||
let attachment_ids = this.state.contentFileList.map(item => {
|
||||
return item.response ? item.response.id : item.id
|
||||
})
|
||||
let reference_attachment_ids = this.state.answerFileList.map(item => {
|
||||
return item.response ? item.response.id : item.id
|
||||
})
|
||||
const isGroup = this.props.isGroup()
|
||||
const { min_num, max_num, base_on_project, category } = this.state
|
||||
|
||||
const params = {
|
||||
type: isGroup ? 3 : 1,
|
||||
name: values.title,
|
||||
description: values.description,
|
||||
reference_answer: values.reference_answer,
|
||||
attachment_ids,
|
||||
reference_attachment_ids,
|
||||
|
||||
min_num,
|
||||
max_num,
|
||||
base_on_project
|
||||
}
|
||||
this.props.doNew && this.props.doNew(params)
|
||||
|
||||
}
|
||||
|
||||
handleContentUploadChange = (info) => {
|
||||
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
|
||||
let contentFileList = info.fileList;
|
||||
this.setState({ contentFileList: appendFileSizeToUploadFileAll(contentFileList) });
|
||||
}
|
||||
}
|
||||
handleAnswerUploadChange = (info) => {
|
||||
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
|
||||
let answerFileList = info.fileList;
|
||||
this.setState({ answerFileList: appendFileSizeToUploadFileAll(answerFileList) });
|
||||
}
|
||||
}
|
||||
|
||||
onAttachmentRemove = (file, stateName) => {
|
||||
if(!file.percent || file.percent == 100){
|
||||
this.props.confirm({
|
||||
content: '是否确认删除?',
|
||||
|
||||
onOk: () => {
|
||||
this.deleteAttachment(file, stateName)
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
deleteAttachment = (file, stateName) => {
|
||||
// 初次上传不能直接取uid
|
||||
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
|
||||
axios.delete(url, {
|
||||
})
|
||||
.then((response) => {
|
||||
if (response.data) {
|
||||
const { status } = response.data;
|
||||
if (status == 0) {
|
||||
|
||||
|
||||
this.setState((state) => {
|
||||
const index = state[stateName].indexOf(file);
|
||||
const newFileList = state[stateName].slice();
|
||||
newFileList.splice(index, 1);
|
||||
return {
|
||||
[stateName]: newFileList,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
max_num_change = (val) => {
|
||||
// if (val < 2) {
|
||||
// // this.setState({
|
||||
// // max_num: 2,
|
||||
// // })
|
||||
// return;
|
||||
// }
|
||||
const { min_num } = this.state;
|
||||
this.setState({
|
||||
max_num: val,
|
||||
// min_num: val <= min_num ? val - 1 : min_num
|
||||
})
|
||||
}
|
||||
personNumValidator = (rule, value, callback) => {
|
||||
const { min_num, max_num } = this.state;
|
||||
const form = this.props.form;
|
||||
if (!min_num) {
|
||||
callback('最小人数不能为空');
|
||||
} else if (min_num < 1) {
|
||||
callback('最小人数不能小于1');
|
||||
} else if (!max_num) {
|
||||
callback('最大人数不能为空');
|
||||
} else if (max_num < min_num) {
|
||||
callback('最大人数不能小于最小人数');
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
min_num_change = (val) => {
|
||||
this.setState({ min_num: val })
|
||||
}
|
||||
base_on_project_change = () => {
|
||||
this.setState({ base_on_project: !this.state.base_on_project })
|
||||
}
|
||||
componentDidMount() {
|
||||
window.$('.groupSetting .ant-form-item-label > label').addClass('ant-form-item-required')
|
||||
this._scrollToTop()
|
||||
}
|
||||
|
||||
render(){
|
||||
let {typeId,coursesId,pageType}=this.props.match.params;
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const isGroup = this.props.isGroup()
|
||||
let{
|
||||
title_value, contentFileList, answerFileList, max_num, min_num, base_on_project,
|
||||
init_max_num, init_min_num,
|
||||
title_num, course_name, category, has_commit, has_project
|
||||
}=this.state
|
||||
const { current_user } = this.props
|
||||
|
||||
const courseId = this.state.course_id || this.props.match.params.coursesId ;
|
||||
this.isEdit = this.isEdit || this.props.match.url.indexOf('/edit') != -1
|
||||
if ((this.isEdit) && !this.state.description && this.state.description != '') {
|
||||
return ''
|
||||
}
|
||||
const uploadProps = {
|
||||
width: 600,
|
||||
fileList: contentFileList,
|
||||
multiple: true,
|
||||
// https://github.com/ant-design/ant-design/issues/15505
|
||||
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
|
||||
// showUploadList: false,
|
||||
action: `${getUploadActionUrl()}`,
|
||||
onChange: this.handleContentUploadChange,
|
||||
onRemove: (file) => this.onAttachmentRemove(file, 'contentFileList'),
|
||||
beforeUpload: (file) => {
|
||||
|
||||
const isLt150M = file.size / 1024 / 1024 < 150;
|
||||
if (!isLt150M) {
|
||||
this.props.showNotification('文件大小必须小于150MB!');
|
||||
}
|
||||
return isLt150M;
|
||||
},
|
||||
};
|
||||
const answerUploadProps = {
|
||||
width: 600,
|
||||
fileList: answerFileList,
|
||||
multiple: true,
|
||||
// https://github.com/ant-design/ant-design/issues/15505
|
||||
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
|
||||
// showUploadList: false,
|
||||
action: `${getUploadActionUrl()}`,
|
||||
onChange: this.handleAnswerUploadChange,
|
||||
onRemove: (file) => this.onAttachmentRemove(file, 'answerFileList'),
|
||||
beforeUpload: (file) => {
|
||||
|
||||
const isLt150M = file.size / 1024 / 1024 < 150;
|
||||
if (!isLt150M) {
|
||||
this.props.showNotification('文件大小必须小于150MB!');
|
||||
}
|
||||
return isLt150M;
|
||||
},
|
||||
};
|
||||
|
||||
return(
|
||||
<React.Fragment>
|
||||
|
||||
<style>
|
||||
{
|
||||
`
|
||||
.yslnewworkinputaddonAfter .ant-input{
|
||||
border-right: none !important;
|
||||
height: 40px !important;
|
||||
}
|
||||
|
||||
`
|
||||
}
|
||||
</style>
|
||||
<Form className="courseForm">
|
||||
<Form.Item
|
||||
label="标题"
|
||||
className="AboutInputForm"
|
||||
>
|
||||
{getFieldDecorator('title', {
|
||||
rules: [{
|
||||
required: true, message: '请输入标题'
|
||||
}],
|
||||
})(
|
||||
<Input placeholder="请输入作业标题,最大限制60个字符" onInput={this.changeTitle} className="searchView yslnewworkinputaddonAfter searchViewAfter" style={{"width":"100%"}} maxLength={MAX_TITLE_LENGTH} addonAfter={`${String(title_num)}/${MAX_TITLE_LENGTH}`}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<style>{`
|
||||
.uploadBtn.ant-btn {
|
||||
border: none;
|
||||
color: #4CACFF;
|
||||
box-shadow: none;
|
||||
background: transparent;
|
||||
padding: 0 6px;
|
||||
}
|
||||
.ant-upload-list-item:hover .ant-upload-list-item-info{
|
||||
background-color:#fff;
|
||||
}
|
||||
.upload_1 .ant-upload-list {
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
.ant-input-number {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.workContent.AboutInputForm.ant-form-item {
|
||||
border-bottom: none;
|
||||
padding-bottom: 0px !important;
|
||||
}
|
||||
.newWorkUpload {
|
||||
padding: 0px 30px 30px 30px!important;
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
border-bottom: 1px solid #EDEDED;
|
||||
}
|
||||
.courseForm .AboutInputForm.clearPaddingBottom{
|
||||
padding-bottom:0px!important;
|
||||
}
|
||||
.clearPaddingBottom .ant-form-explain{
|
||||
position:absolute;
|
||||
bottom:0px;
|
||||
left:0px
|
||||
}
|
||||
|
||||
.resetNewWorkUpload{
|
||||
border-bottom:none!important;
|
||||
}
|
||||
|
||||
`}</style>
|
||||
|
||||
|
||||
{ <Form.Item
|
||||
label="内容"
|
||||
className="AboutInputForm workContent mdInForm"
|
||||
>
|
||||
{getFieldDecorator('description', {
|
||||
rules: [{
|
||||
required: true, message: '请输入作业内容和要求',
|
||||
},{
|
||||
max: 5000 , message:'最大限制5000个字符'
|
||||
}],
|
||||
})(
|
||||
<TPMMDEditor ref={this.contentMdRef} placeholder="请在此输入作业内容和要求,最大限制5000个字符" mdID={'courseContentMD'} refreshTimeout={1500}
|
||||
initValue={this.state.description} noSetValueOnInit={!!this.isEdit}
|
||||
className="courseMessageMD" ></TPMMDEditor>
|
||||
)}
|
||||
</Form.Item> }
|
||||
<Upload {...uploadProps} className="upload_1 newWorkUpload">
|
||||
<Button className="uploadBtn">
|
||||
<Icon type="upload" /> 上传附件
|
||||
</Button>
|
||||
(单个文件150M以内)
|
||||
</Upload>
|
||||
<span id={"numberofgroups"}></span>
|
||||
|
||||
{ isGroup &&
|
||||
<Form.Item
|
||||
label="分组设置"
|
||||
className="AboutInputForm groupSetting"
|
||||
>
|
||||
{getFieldDecorator('personNum', {
|
||||
validateTrigger: 'onNone',
|
||||
// rules: [{
|
||||
// required: true,
|
||||
// message: '人数不能为空'
|
||||
// validator: this.personNumValidator
|
||||
// required: true, message: '请输入最小人数和最大人数'
|
||||
// }],
|
||||
})(
|
||||
<div >
|
||||
<p className="clearfix">
|
||||
<ConditionToolTip condition={has_commit} title={'已有提交作品,人数范围只能扩大'}>
|
||||
{/* max={has_commit ? init_min_num : null } */}
|
||||
<InputNumber placeholder="请填写每组最小人数" min={1} className="winput-240-40" value={min_num}
|
||||
|
||||
onChange={this.min_num_change} style={{width:'180px'}} />
|
||||
</ConditionToolTip>
|
||||
|
||||
<span className="ml15 mr15">~</span>
|
||||
{/* min={has_commit ? init_max_num : (min_num == undefined ? 2 : min_num + 1) } */}
|
||||
<ConditionToolTip condition={has_commit} title={'已有提交作品,人数范围只能扩大'}>
|
||||
<InputNumber className="winput-240-40" placeholder="请填写每组最大人数" value={max_num} max={10}
|
||||
onChange={this.max_num_change} style={{width:'180px'}} />
|
||||
</ConditionToolTip>
|
||||
<label className="color-grey-9 ml20 font-14">(学生提交作品时需要关联同组成员,组内成员作品共享)</label>
|
||||
</p>
|
||||
<p className="mt20">
|
||||
<ConditionToolTip condition={has_commit || has_project} title={'已有关联项目或作品,不能修改'}>
|
||||
<Checkbox checked={base_on_project} onChange={this.base_on_project_change}
|
||||
disabled={has_project || has_commit}
|
||||
>基于项目实施</Checkbox>
|
||||
</ConditionToolTip>
|
||||
|
||||
<label className="color-grey-9 ml12 font-14">(选中,则必须在本平台创建项目,项目管理员可以提交作品;不选中,无需在平台创建项目,任意小组成员均可以提交作品)</label>
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</Form.Item>
|
||||
}
|
||||
|
||||
<div className="edu-back-white">
|
||||
<Form.Item
|
||||
label="参考答案"
|
||||
className="AboutInputForm clearPaddingBottom pr"
|
||||
style={{"borderBottom":"none"}}
|
||||
>
|
||||
{getFieldDecorator('reference_answer', {
|
||||
rules: [{
|
||||
max: 5000 , message:'最大限制5000个字符'
|
||||
}],
|
||||
})(
|
||||
<TPMMDEditor ref={this.answerMdRef} placeholder="请在此输入作业的参考答案,最大限制5000个字符" mdID={'workAnswerMD'}
|
||||
initValue={this.state.reference_answer || ''} noSetValueOnInit={!!this.isEdit}
|
||||
className="courseMessageMD" refreshTimeout={1500} ></TPMMDEditor>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Upload {...answerUploadProps} className="upload_1 newWorkUpload resetNewWorkUpload">
|
||||
<Button className="uploadBtn">
|
||||
<Icon type="upload" /> 上传附件
|
||||
</Button>
|
||||
(单个文件150M以内)
|
||||
</Upload>
|
||||
</div>
|
||||
<Form.Item>
|
||||
<div className="clearfix mt30 mb30">
|
||||
{/* htmlType="submit" */}
|
||||
<Button type="primary" onClick={this.handleSubmit} className="defalutSubmitbtn fl mr20">提交</Button>
|
||||
<a className="defalutCancelbtn fl" onClick={() => this.props.onCancel()}>取消</ a>
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
const WrappedWorkForm = Form.create({ name: 'NewWorkForm' })(NewWorkForm);
|
||||
export default WrappedWorkForm;
|
||||
@@ -0,0 +1,269 @@
|
||||
import React,{ Component } from "react";
|
||||
import { Input,Checkbox,Menu,Pagination } from "antd";
|
||||
|
||||
import HomeworkModal from '../coursesPublic/HomeworkModal';
|
||||
import OneSelfOrderModal from "../coursesPublic/OneSelfOrderModal";
|
||||
import axios from 'axios'
|
||||
import moment from 'moment'
|
||||
import { getNextHalfHourOfMoment } from 'educoder'
|
||||
class PublishRightnow extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
course_groups: [],
|
||||
modalname:undefined,
|
||||
modaltype:undefined,
|
||||
visible:false,
|
||||
Topval:undefined,
|
||||
Botvalleft:undefined,
|
||||
Botval:undefined,
|
||||
starttime:undefined,
|
||||
endtime:undefined,
|
||||
Cancelname:undefined,
|
||||
Savesname:undefined,
|
||||
Cancel:undefined,
|
||||
Saves:undefined,
|
||||
Topvalright:undefined
|
||||
}
|
||||
}
|
||||
open = (usingCheckBeforePost) => {
|
||||
this.usingCheckBeforePost = usingCheckBeforePost == true
|
||||
this.homeworkstart()
|
||||
}
|
||||
|
||||
homeworkstart=()=>{
|
||||
const isPublish = this.props.isPublish;
|
||||
const isPublishtype = this.props.isPublishtype;
|
||||
let showdatatypes=isPublish===true||isPublishtype===1;
|
||||
|
||||
if (!this.props.checkBoxValues || this.props.checkBoxValues.length == 0) {
|
||||
this.props.showNotification(`请先选择要立即${showdatatypes? "发布" : "截止"}的作业`)
|
||||
return;
|
||||
}
|
||||
|
||||
this.fetchCourseGroups();
|
||||
|
||||
|
||||
}
|
||||
showDialog = (course_groups) => {
|
||||
const isPublish = this.props.isPublish;
|
||||
const isPublishtype = this.props.isPublishtype;
|
||||
const dateFormat = 'YYYY-MM-DD HH:mm';
|
||||
let showdatatype=isPublish===true&&isPublishtype===undefined;
|
||||
let showdatatypes=isPublish===true||isPublishtype===1;
|
||||
// getNextHalfHourOfMoment
|
||||
const startMoment = (moment());
|
||||
this.setState({
|
||||
modalname: showdatatypes ? "立即发布" : "立即截止",
|
||||
modaltype:course_groups.length> 0 ? 1 : 2,
|
||||
visible:showdatatype?false:true,
|
||||
OneSelftype:showdatatype?true:false,
|
||||
Topval:showdatatypes ? "学生将立即收到作业" : "学生将不能再提交作品",
|
||||
// Botvalleft: isPublish ? "暂不发布" : "暂不截止",
|
||||
Botval: this.props.fromListPage ? (showdatatypes ? "本操作只对“未发布”的作业有效" : "本操作只对“提交中”的作业有效") : '',
|
||||
starttime: showdatatypes? `发布时间:${startMoment.format(dateFormat)}` : '',
|
||||
starttimes:showdatatypes? `${startMoment.format(dateFormat)}` : '',
|
||||
endtime:showdatatypes ? `截止时间:${startMoment.add(1, 'months').add(1, 'hours').minutes(0).format(dateFormat)}` : '',
|
||||
Cancelname:showdatatypes ? "暂不发布" : "暂不截止",
|
||||
Savesname:showdatatypes ? "立即发布" : "立即截止",
|
||||
Cancel:this.homeworkhide,
|
||||
Saves:this.homeworkstartend,
|
||||
typs:showdatatypes ? "start" : "end",
|
||||
})
|
||||
}
|
||||
homeworkhide=()=>{
|
||||
this.setState({
|
||||
modalname:undefined,
|
||||
modaltype:undefined,
|
||||
visible:false,
|
||||
OneSelftype:false,
|
||||
Topval:undefined,
|
||||
Topvalright:undefined,
|
||||
Botvalleft:undefined,
|
||||
Botval:undefined,
|
||||
starttime:undefined,
|
||||
endtime:undefined,
|
||||
Cancelname:undefined,
|
||||
Savesname:undefined,
|
||||
Cancel:undefined,
|
||||
Saves:undefined,
|
||||
StudentList_value:undefined,
|
||||
addname:undefined,
|
||||
addnametype:false,
|
||||
addnametab:undefined
|
||||
})
|
||||
}
|
||||
|
||||
homeworkstartend=(arg_group_ids,endtime)=>{
|
||||
debugger
|
||||
if (this.usingCheckBeforePost && this.props.checkBeforePost) {
|
||||
const goOn = this.props.checkBeforePost();
|
||||
if (!goOn) {
|
||||
this.homeworkhide();
|
||||
return;
|
||||
}
|
||||
}
|
||||
debugger
|
||||
const isPublish = this.props.isPublish;
|
||||
let group_ids = arg_group_ids
|
||||
if (this.usingCheckBeforePost) {
|
||||
group_ids = this.state.course_groups.map((item) => {
|
||||
return item.id
|
||||
})
|
||||
}
|
||||
debugger
|
||||
if(this.state.course_groups.length>0){
|
||||
if (this.state.course_groups.length && (!group_ids || group_ids&&group_ids.length == 0)) {
|
||||
this.props.showNotification('请至少选择一个分班');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let data={}
|
||||
if(arg_group_ids&&arg_group_ids.length===0){
|
||||
data = {
|
||||
homework_ids: this.props.checkBoxValues,
|
||||
end_time: endtime==="Invalid date"?undefined:endtime,
|
||||
}
|
||||
}else if(this.props.islist===true){
|
||||
data={
|
||||
homework_ids: this.props.checkBoxValues,
|
||||
group_ids: group_ids,
|
||||
end_time:endtime,
|
||||
}
|
||||
}else{
|
||||
data={
|
||||
homework_ids: this.props.checkBoxValues,
|
||||
group_ids: group_ids,
|
||||
group_end_times:endtime,
|
||||
detail:true
|
||||
}
|
||||
}
|
||||
const isPublishtype = this.props.isPublishtype;
|
||||
let showdatatypes=isPublish===true||isPublishtype===1;
|
||||
let coursesId=this.props.match.params.coursesId;
|
||||
const url = `/courses/${coursesId}/homework_commons/${showdatatypes ? "publish_homework" : "end_homework"}.json`
|
||||
axios.post(url, data)
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.homeworkhide()
|
||||
this.props.showNotification(showdatatypes ? "立即发布成功" : "立即截止成功")
|
||||
this.props.doWhenSuccess && this.props.doWhenSuccess()
|
||||
this.setState({ visible : false })
|
||||
this.props.action && this.props.action()
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
// componentDidUpdate = (prevProps) => {
|
||||
// if ( prevProps.match.params.boardId != this.props.match.params.boardId ) {
|
||||
// this.fetchAll(null, 1)
|
||||
// }
|
||||
// }
|
||||
fetchCourseGroups = () => {
|
||||
const isPublish = this.props.isPublish;
|
||||
const isPublishtype = this.props.isPublishtype;
|
||||
let showdatatypes=isPublish===true||isPublishtype===1;
|
||||
let coursesId=this.props.match.params.coursesId;
|
||||
// TODO 这里要改成单选作业,接口使用这个 https://www.showdoc.cc/127895880302646?page_id=2035541497546668
|
||||
// /homework_commons/:id/publish_groups.json
|
||||
let url = `/courses/${coursesId}/all_course_groups.json`
|
||||
if (this.props.checkBoxValues.length == 1) {
|
||||
const isPublish = this.props.isPublish;
|
||||
url = `/homework_commons/${this.props.checkBoxValues[0]}/${ showdatatypes ? 'publish_groups' : 'end_groups'}.json`
|
||||
}
|
||||
|
||||
axios.get(url, {
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response || response.data.status == -1) {
|
||||
this.setState({ visible : false })
|
||||
return;
|
||||
}
|
||||
this.showDialog(response.data.course_groups)
|
||||
this.setState({
|
||||
course_groups: response.data.course_groups,
|
||||
starttimesend:response.data.end_time===undefined||response.data.end_time===null||response.data.end_time===""?undefined:response.data.end_time,
|
||||
})
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
const isPublish = this.props.isPublish;
|
||||
const isPublishtype = this.props.isPublishtype;
|
||||
let showdatatypes=isPublish===true||isPublishtype===1;
|
||||
|
||||
let{
|
||||
Topvalright,
|
||||
modalname,
|
||||
modaltype,
|
||||
visible,
|
||||
Topval,
|
||||
Botvalleft,
|
||||
Botval,
|
||||
starttime,
|
||||
starttimes,
|
||||
endtime,
|
||||
Cancelname,
|
||||
Savesname,
|
||||
Cancel,
|
||||
Saves,
|
||||
course_groups
|
||||
}=this.state
|
||||
|
||||
const { showActionButton } = this.props
|
||||
return(
|
||||
<div>
|
||||
{/*立即截止*/}
|
||||
{visible===true?<HomeworkModal
|
||||
modaltype={modaltype}
|
||||
modalname={modalname}
|
||||
visible={visible}
|
||||
Topval={Topval}
|
||||
Topvalright={Topvalright}
|
||||
Botvalleft={Botvalleft}
|
||||
Botval={Botval}
|
||||
starttime={starttime}
|
||||
starttimes={starttimes}
|
||||
endtime={endtime}
|
||||
Cancelname={Cancelname}
|
||||
Savesname={Savesname}
|
||||
Cancel={Cancel}
|
||||
Saves={Saves}
|
||||
course_groups={course_groups}
|
||||
usingCheckBeforePost= {this.usingCheckBeforePost}
|
||||
onToPublishClick={this.props.onToPublishClick}
|
||||
typs={this.state.typs}
|
||||
/>:""}
|
||||
{/*立即发布*/}
|
||||
{this.state.OneSelftype===true?<OneSelfOrderModal
|
||||
modaltype={this.state.modaltype}
|
||||
modalname={this.state.modalname}
|
||||
OneSelftype={this.state.OneSelftype}
|
||||
Topval={this.state.Topval}
|
||||
Topvalright={this.state.Topvalright}
|
||||
Botvalleft={this.state.Botvalleft}
|
||||
Botval={this.state.Botval}
|
||||
starttime={this.state.starttime}
|
||||
endtime={this.state.endtime}
|
||||
Cancelname={this.state.Cancelname}
|
||||
Savesname={this.state.Savesname}
|
||||
Cancel={this.state.Cancel}
|
||||
Saves={this.state.Saves}
|
||||
course_groups={this.state.course_groups}
|
||||
starttimes={this.state.starttimes}
|
||||
starttimesend={this.state.starttimesend}
|
||||
typs={this.state.typs}
|
||||
/>:""}
|
||||
{ showActionButton && <a href="javascript:void(0)" className="color-grey-9" onClick={this.homeworkstart}>{ showdatatypes ? "立即发布" : "立即截止" }</a> }
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default PublishRightnow;
|
||||
@@ -0,0 +1,26 @@
|
||||
// import React, { useState, useEffect } from 'react'
|
||||
|
||||
|
||||
// function Example() {
|
||||
// const [state, setState] = useState({counter: 0})
|
||||
// useEffect(() => {
|
||||
// console.log(' cdm')
|
||||
|
||||
// return () => {
|
||||
// console.log(' cwum')
|
||||
// };
|
||||
// })
|
||||
// const add1ToCounter = () => {
|
||||
// const newCounterValue = state.counter + 1
|
||||
// setState({ counter: newCounterValue })
|
||||
// }
|
||||
// return (
|
||||
// <div>
|
||||
// <p>{state.counter}</p>
|
||||
// <button onClick={add1ToCounter}>
|
||||
// Click me
|
||||
// </button>
|
||||
// </div>
|
||||
// )
|
||||
// }
|
||||
// export default Example
|
||||
@@ -0,0 +1,392 @@
|
||||
import React,{ Component } from "react";
|
||||
import { Modal,Input, Checkbox,Icon,Spin} from "antd";
|
||||
|
||||
import '../css/members.css'
|
||||
import '../css/busyWork.css'
|
||||
import { WordsBtn, ConditionToolTip } from 'educoder'
|
||||
import axios from 'axios'
|
||||
import InfiniteScroll from 'react-infinite-scroller';
|
||||
|
||||
import NoneData from '../coursesPublic/NoneData'
|
||||
|
||||
const Search=Input.Search;
|
||||
const pageCount = 20
|
||||
// "poll", #normal 普通作业题库; group 分组作业题库; poll问卷题库; exercise试卷题库; gtask 毕设选题题库;gtopic 毕设任务
|
||||
const engNameMap = {
|
||||
poll: '问卷',
|
||||
normal: '普通作业',
|
||||
group: '分组作业',
|
||||
exercise: '试卷',
|
||||
gtask: '毕设任务',
|
||||
gtopic: '毕设选题',
|
||||
}
|
||||
class UseBank extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
flag:false,
|
||||
nav_my: 'myself',
|
||||
search: '',
|
||||
page: 1,
|
||||
checkBoxValues: [],
|
||||
isChecked:'',
|
||||
is_teacher:undefined,
|
||||
hometypepvisible:false
|
||||
}
|
||||
}
|
||||
componentDidMount() {
|
||||
// console.log("UseBank");
|
||||
// console.log(this.props);
|
||||
|
||||
}
|
||||
onCheckBoxChange = (checkBoxValues) => {
|
||||
this.setState({
|
||||
checkBoxValues: checkBoxValues
|
||||
})
|
||||
if(checkBoxValues.length!=0){
|
||||
this.setState({
|
||||
isChecked:""
|
||||
})
|
||||
}
|
||||
}
|
||||
fetchAll = (arg_page) => {
|
||||
console.log('fetchAll')
|
||||
const courseId = this.props.match.params.coursesId
|
||||
const page = arg_page || this.state.page;
|
||||
const { nav_my, search } = this.state
|
||||
/**
|
||||
normal 普通作业题库; group 分组作业题库; poll问卷题库; exercise试卷题库; gtask 毕设选题题库;gtopic 毕设任务
|
||||
filter string public公共题库 2, myself我的题库 1
|
||||
*/
|
||||
const object_type = this.props.object_type
|
||||
let url = `/question_banks/bank_list.json?page=${page}&limit=${pageCount}&object_type=${object_type || ''}&search=${search || ''}&filter=${nav_my}`
|
||||
this.setState({ loading: true })
|
||||
axios.get(url
|
||||
// , {
|
||||
// params: {
|
||||
|
||||
// }
|
||||
// }
|
||||
)
|
||||
.then((response) => {
|
||||
if(response.data){
|
||||
this.setState({
|
||||
is_teacher:response.data.is_teacher
|
||||
})
|
||||
}
|
||||
if (!response.data.object_list || response.data.object_list.length == 0) {
|
||||
this.setState({
|
||||
object_list: page == 1 ? [] : this.state.object_list,
|
||||
page,
|
||||
loading: false,
|
||||
hasMore: false,
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
object_list: page == 1 ? response.data.object_list : this.state.object_list.concat(response.data.object_list),
|
||||
page,
|
||||
loading: false,
|
||||
hasMore: response.data.object_list.length == pageCount
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
openSelectBank=()=>{
|
||||
this.setState({
|
||||
search: '',
|
||||
flag:true
|
||||
}, () => {
|
||||
this.fetchAll()
|
||||
})
|
||||
}
|
||||
closeSelectBank=()=>{
|
||||
this.setState({
|
||||
flag:false,
|
||||
nav_my: 'myself',
|
||||
search: '',
|
||||
page: 1,
|
||||
checkBoxValues: [],
|
||||
isChecked:'',
|
||||
is_teacher:undefined,
|
||||
hometypepvisible:false
|
||||
})
|
||||
}
|
||||
|
||||
//切换tab
|
||||
changeNav=(index)=>{
|
||||
this.setState({
|
||||
nav_my:index
|
||||
}, () => {
|
||||
this.fetchAll(1)
|
||||
})
|
||||
}
|
||||
onSearchChange = (e) => {
|
||||
this.setState({
|
||||
search: e.target.value
|
||||
})
|
||||
}
|
||||
onSave = () => {
|
||||
debugger
|
||||
const { checkBoxValues } = this.state;
|
||||
const { object_type } = this.props
|
||||
if(checkBoxValues.length==0){
|
||||
this.setState({
|
||||
isChecked:"请先选择"+engNameMap[object_type]
|
||||
})
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
hometypepvisible:true
|
||||
})
|
||||
const courseId = this.props.match.params.coursesId
|
||||
let url = `/question_banks/save_banks.json`
|
||||
this.setState({ loading: true })
|
||||
axios.post(url
|
||||
, {
|
||||
"object_type": object_type,
|
||||
"bank_id": checkBoxValues,
|
||||
"course_id": courseId
|
||||
}
|
||||
)
|
||||
.then((response) => {
|
||||
if (response.data.status == 0) {
|
||||
this.props.useBankSuccess && this.props.useBankSuccess(checkBoxValues,response.data.object_ids);
|
||||
this.props.showNotification('题库选用成功')
|
||||
this.closeSelectBank();
|
||||
this.props.updataleftNavfun()
|
||||
this.setState({
|
||||
hometypepvisible:false,
|
||||
checkBoxValues:[]
|
||||
})
|
||||
} else {
|
||||
this.setState({
|
||||
hometypepvisible:false,
|
||||
checkBoxValues:[]
|
||||
})
|
||||
this.props.showNotification(response.data.message)
|
||||
}
|
||||
})
|
||||
.catch( (error) =>{
|
||||
console.log(error);
|
||||
this.setState({
|
||||
hometypepvisible:false,
|
||||
checkBoxValues:[]
|
||||
})
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
getotiku = (url) => {
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
|
||||
|
||||
|
||||
render(){
|
||||
let { flag, nav_my, loading, hasMore, object_list, search, checkBoxValues,isChecked,page,is_teacher }=this.state
|
||||
let { object_type }=this.props;
|
||||
const antIcon = <Icon type="loading" style={{ fontSize: 24 }} spin />;
|
||||
// console.log("题库选用2222");
|
||||
// console.log("UseBank");
|
||||
// console.log(this.props);
|
||||
return(
|
||||
<a>
|
||||
<style>{`
|
||||
.bankModal .task-hide {
|
||||
max-width: 290px;
|
||||
}
|
||||
.d_middle{
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
display: -webkit-flex;
|
||||
}
|
||||
.setImgW .edu-nodata-img{
|
||||
width: 170px !important;
|
||||
}
|
||||
.bankwidth{
|
||||
width:32% !important;
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space:nowrap
|
||||
}
|
||||
.bankwidth76{
|
||||
width:76px !important;
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space:nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
.bankwidth2{
|
||||
width:24% !important;
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
white-space:nowrap
|
||||
}
|
||||
.with58{
|
||||
width:58% !important;
|
||||
Margin-left:15px
|
||||
}
|
||||
.with63{
|
||||
width: 60% !important;
|
||||
box-sizing: border-box;
|
||||
margin-left: 15px;
|
||||
}
|
||||
`}</style>
|
||||
|
||||
|
||||
{
|
||||
flag===true?<style>
|
||||
{
|
||||
`
|
||||
body {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
`
|
||||
}
|
||||
</style>:""
|
||||
}
|
||||
|
||||
{this.props.user&&this.props.user.main_site===true?<WordsBtn style="blue" className="mr30 font-16" onClick={()=>this.openSelectBank()}>{engNameMap[object_type]=="问卷"?"问卷选用":engNameMap[object_type]=="试卷"?"试卷选用":"题库选用"}</WordsBtn>:""}
|
||||
{flag===true?<Modal
|
||||
title="题库选用"
|
||||
visible={flag}
|
||||
closable={false}
|
||||
width="800px"
|
||||
footer={null}
|
||||
keyboard={false}
|
||||
destroyOnClose={true}
|
||||
centered={true}
|
||||
>
|
||||
|
||||
<div className="newupload_conbox clearfix bankModal">
|
||||
<Spin indicator={antIcon} spinning={this.state.hometypepvisible} className="newnext-loading" color='#4AC7FF' size="large">
|
||||
<div className="clearfix mb30">
|
||||
<ul className="fl mt2 bankNav">
|
||||
<li className={nav_my==='myself'?"active":""} onClick={()=>this.changeNav('myself')}><a>我的题库</a></li>
|
||||
<li className={nav_my==='myself'?"":"active"} onClick={()=>this.changeNav('public')}><a>公共题库</a></li>
|
||||
</ul>
|
||||
<Search placeholder="输入标题、适用课程进行搜索" className="searchView fr" style={{"width":"268px","height":"30px"}}
|
||||
onSearch={() => this.fetchAll(1)} onChange={this.onSearchChange} value={search}
|
||||
></Search>
|
||||
</div>
|
||||
{
|
||||
object_list && object_list.length == 0 && page == 1 ? "" : nav_my === 'myself' ?
|
||||
<p className="color-grey-6 mb25 edu-txt-center">选用对象:你在课堂{engNameMap[object_type]}列表中已<span className="color-orange-tip">“加入题库”</span>的{engNameMap[object_type]}</p>
|
||||
:
|
||||
<p className="color-grey-6 mb25 edu-txt-center">选用对象:题库中已设置成公共属性的所有{engNameMap[object_type]}</p>
|
||||
}
|
||||
|
||||
{
|
||||
nav_my != 'myself' && is_teacher == false ?
|
||||
<div style={{"height":"230px"}} className="d_middle edu-txt-center">
|
||||
<div>
|
||||
<p className="font-16 mb20 color-grey-3">通过职业认证的教师才能访问公共题库</p>
|
||||
<a className="white-btn edu-orangeback-btn" target="_blank" href="/account/certification">立即认证</a>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
object_list && object_list.length == 0 && page == 1 ?
|
||||
<div className="setImgW"><NoneData></NoneData></div>
|
||||
:
|
||||
<div className="edu-back-skyblue padding20" style={{"height":"230px", "overflowY": 'auto'}}>
|
||||
<InfiniteScroll
|
||||
threshold={10}
|
||||
initialLoad={false}
|
||||
pageStart={0}
|
||||
loadMore={() => this.fetchAll(this.state.page + 1)}
|
||||
hasMore={!loading && hasMore}
|
||||
useWindow={false}
|
||||
>
|
||||
<Checkbox.Group style={{ width: '100%' }} onChange={this.onCheckBoxChange} value={checkBoxValues}>
|
||||
{ object_list && object_list.map( item => {
|
||||
/**
|
||||
course_list_name: "C++程序设计"
|
||||
id: 3889
|
||||
name: "作业3:第四章 控制结构 "
|
||||
username: "Coder"
|
||||
*/
|
||||
return (
|
||||
<p className="clearfix mb7" key={item.id}>
|
||||
<Checkbox className="fl" value={item.id} key={item.id}></Checkbox>
|
||||
<span className={nav_my === 'myself' ? "fl with58" : "fl with63"}>
|
||||
<label className="task-hide fl" title={item.name && item.name.length > 30 ? item.name : ""}
|
||||
style={{"maxWidth": "100%"}}>
|
||||
<a title={item.name}>{item.name}</a>
|
||||
</label>
|
||||
</span>
|
||||
<span title={item.course_list_name && item.course_list_name.length > 10 && item.course_list_name}
|
||||
className={nav_my === 'myself' ? "fl with30 color-grey-6 task-hide pl5 bankwidth" : "fl with30 color-grey-6 task-hide pl5 bankwidth2"}
|
||||
|
||||
><a title={item.course_list_name}>{item.course_list_name}</a></span>
|
||||
{
|
||||
nav_my === 'public' &&
|
||||
<span className="fl with16 color-grey-6 task-hide pl10 bankwidth76"><a
|
||||
title={item.username} style={{
|
||||
width: "76px"
|
||||
}}>{item.username}</a></span>
|
||||
}
|
||||
{nav_my === "myself" ?
|
||||
(this.props.object_type && this.props.object_type === "normal" ?
|
||||
<a style={{textAlign: "center"}} key={item.id} className="color-blue font-14 pl5"
|
||||
onClick={() => this.getotiku(`/banks/normal/${item.id}/edit/personal?tab=0`)}
|
||||
>编辑</a>
|
||||
: this.props.object_type && this.props.object_type === "group" ?
|
||||
<a style={{textAlign: "center"}} key={item.id} className="color-blue font-14 pl5"
|
||||
onClick={() => this.getotiku(`/banks/group/${item.id}/edit/publicly?tab=0`)}
|
||||
>编辑</a>
|
||||
: this.props.object_type && this.props.object_type === "exercise" ?
|
||||
<a style={{textAlign: "center"}} key={item.id} className="color-blue font-14 pl5"
|
||||
onClick={() => this.getotiku(`/banks/exercise/${item.id}/edit/personal`)}
|
||||
>编辑</a>
|
||||
: this.props.object_type && this.props.object_type === "poll" ?
|
||||
<a style={{textAlign: "center"}} key={item.id} className="color-blue font-14 pl5"
|
||||
onClick={() => this.getotiku(`/banks/poll/${item.id}/edit/personal`)}
|
||||
>编辑</a>
|
||||
: "")
|
||||
: ""
|
||||
}
|
||||
</p>
|
||||
)
|
||||
})}
|
||||
</Checkbox.Group>
|
||||
{/* <p className="clearfix mb7">
|
||||
<Checkbox className="fl"></Checkbox>
|
||||
<span className="fl with45"><label className="task-hide fl" style={{"maxWidth":"208px;"}}>毕业设计2018开题报告题报</label></span>
|
||||
<span className={nav_my===1?"fl with50 color-grey-6 task-hide pl5":"fl with30 color-grey-6 task-hide pl5"}>数据库原理数据库原理</span>
|
||||
{
|
||||
nav_my===2 &&
|
||||
<span className="fl with16 color-grey-6 task-hide pl10">胡莎莎胡莎莎</span>
|
||||
}
|
||||
</p> */}
|
||||
</InfiniteScroll>
|
||||
</div>
|
||||
}
|
||||
|
||||
<p style={{height: "20px", lineHeight: "20px;", marginTop: '4px'}}>
|
||||
{
|
||||
isChecked !="" ? <span className="color-red">{isChecked}</span>:""
|
||||
}
|
||||
</p>
|
||||
<div className="mt10 marginauto clearfix edu-txt-center">
|
||||
<a onClick={this.closeSelectBank} className="pop_close task-btn mr30">取消</a>
|
||||
|
||||
{object_list && object_list.length == 0 && page == 1 ?
|
||||
nav_my !='myself' && is_teacher == false ?
|
||||
<a onClick={this.closeSelectBank} className="task-btn task-btn-orange">确定</a>
|
||||
: <a onClick={this.closeSelectBank} className="task-btn task-btn-orange">确定</a>
|
||||
:<a className="task-btn task-btn-orange" id="submit_send_shixun" onClick={this.onSave}>确定</a>
|
||||
}
|
||||
{/*<a className="task-btn task-btn-orange" id="submit_send_shixun" onClick={this.onSave}>确定</a>*/}
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
</Modal>:""}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default UseBank;
|
||||
@@ -0,0 +1,196 @@
|
||||
import React, { Component } from 'react';
|
||||
export const STATUS_UN_PUBLISH = "未发布"
|
||||
// homework_status: ["提交中", "未开启补交"]
|
||||
export const STATUS_SUBMIT = "提交中"
|
||||
// export const STATUS_UN_PUBLISH = "未发布"
|
||||
|
||||
// homework_status: ["提交中"] 未发布 未开启补交
|
||||
|
||||
|
||||
export function RouteHOC(options = {}) {
|
||||
return function wrap(WrappedComponent) {
|
||||
return class Wrapper extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
|
||||
}
|
||||
}
|
||||
toCreateProject = () => {
|
||||
let url = '/projects/new'
|
||||
if (window.location.port == 3007) {
|
||||
// window.location.href
|
||||
url = '/testbdweb.educoder.net/projects/new'
|
||||
}
|
||||
window.open(
|
||||
url,
|
||||
'_blank' // <- This is what makes it open in a new window.
|
||||
);
|
||||
}
|
||||
// common_homework group_homework
|
||||
// 是否是分组作业
|
||||
isGroup = () => {
|
||||
return window.location.pathname.indexOf('group_homeworks') != -1
|
||||
}
|
||||
getModuleName = (isChinese) => {
|
||||
const isGroup = this.isGroup()
|
||||
if (isChinese) {
|
||||
let chName = isGroup ? '分组作业' : '普通作业'
|
||||
return chName;
|
||||
}
|
||||
const secondName = isGroup ? 'group_homeworks' : 'common_homeworks'
|
||||
return secondName;
|
||||
}
|
||||
getModuleType = () => {
|
||||
const isGroup = this.isGroup()
|
||||
return isGroup ? 3 : 1
|
||||
}
|
||||
toDetailPage = (_courseId, workId, topicId) => {
|
||||
if (typeof _courseId == "object") {
|
||||
const topicId = _courseId.topicId
|
||||
const workId = _courseId.workId
|
||||
const courseId = _courseId.coursesId
|
||||
this.props.history.push(`/courses/${courseId}/boards/${workId}/messages/${topicId}`)
|
||||
} else {
|
||||
this.props.history.push(`/courses/${_courseId}/boards/${workId}/messages/${topicId}`)
|
||||
}
|
||||
|
||||
}
|
||||
toEditPage = (_courseId, _workId) => {
|
||||
const secondName = this.getModuleName()
|
||||
if (typeof _courseId == "object") {
|
||||
const workId = _courseId.workId
|
||||
const courseId = _courseId.coursesId
|
||||
this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}/edit`)
|
||||
} else {
|
||||
this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/edit`)
|
||||
}
|
||||
}
|
||||
toWorkDetailPage = (_courseId, _workId, _studentWorkId) => {
|
||||
const secondName = this.getModuleName()
|
||||
if (typeof _courseId == "object") {
|
||||
const workId = _courseId.workId
|
||||
const courseId = _courseId.coursesId
|
||||
const studentWorkId = _courseId.studentWorkId
|
||||
window.open(`/courses/${courseId}/${secondName}/${_workId || workId}/${_studentWorkId || studentWorkId}/appraise`);
|
||||
} else {
|
||||
window.open(`/courses/${_courseId}/${secondName}/${_workId}/${_studentWorkId}/appraise`);
|
||||
}
|
||||
}
|
||||
toWorkDetailPage2 = (e, _courseId, _workId, _studentWorkId) => {
|
||||
console.log("鼠标中键点击了")
|
||||
console.log(_studentWorkId)
|
||||
const secondName = this.getModuleName()
|
||||
if (typeof _courseId == "object") {
|
||||
const workId = _courseId.workId
|
||||
const courseId = _courseId.coursesId
|
||||
const studentWorkId = _courseId.studentWorkId
|
||||
window.open(`/courses/${courseId}/${secondName}/${_workId || workId}/${_studentWorkId || studentWorkId}/appraise`);
|
||||
} else {
|
||||
window.open(`/courses/${_courseId}/${secondName}/${_workId}/${_studentWorkId}/appraise`);
|
||||
}
|
||||
}
|
||||
toNewPage = (courseId) => {
|
||||
const secondName = this.getModuleName()
|
||||
this.props.history.push(`/courses/${courseId.coursesId}/${secondName}/${courseId.category_id}/new`)
|
||||
}
|
||||
toListPage = (_courseId, _workId) => {
|
||||
const secondName = this.getModuleName()
|
||||
if (typeof _courseId == "object") {
|
||||
const workId = _courseId.workId
|
||||
const courseId = _courseId.coursesId
|
||||
this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}`)
|
||||
} else {
|
||||
this.props.history.push(`/courses/${_courseId}/${secondName}${_workId ? '/' + _workId : ''}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
toWorkPostPage = (_courseId, _workId, isEdit, _studentWorkId) => {
|
||||
const secondName = this.getModuleName()
|
||||
if (typeof _courseId == "object") {
|
||||
const workId = _courseId.workId
|
||||
const courseId = _courseId.coursesId
|
||||
const studentWorkId = _courseId.studentWorkId
|
||||
this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}/${isEdit? `${_studentWorkId || studentWorkId}/post_edit` : 'post'}`)
|
||||
} else {
|
||||
this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/${isEdit? `${_studentWorkId}/post_edit` : 'post'}`)
|
||||
}
|
||||
}
|
||||
toWorkListPage = (_courseId, _workId) => {
|
||||
const secondName = this.getModuleName()
|
||||
if (typeof _courseId == "object") {
|
||||
const workId = _courseId.workId
|
||||
const courseId = _courseId.coursesId
|
||||
this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}/list`)
|
||||
} else {
|
||||
this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/list`)
|
||||
}
|
||||
}
|
||||
toWorkAnswerPage = (_courseId, _workId) => {
|
||||
const secondName = this.getModuleName()
|
||||
if (typeof _courseId == "object") {
|
||||
const workId = _courseId.workId
|
||||
const courseId = _courseId.coursesId
|
||||
this.props.history.push(`/courses/${courseId}/${secondName}/${workId}/answer`)
|
||||
} else {
|
||||
this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/answer`)
|
||||
}
|
||||
}
|
||||
|
||||
toWorkQuestionPage = (_courseId, _workId) => {
|
||||
const secondName = this.getModuleName()
|
||||
if (typeof _courseId == "object") {
|
||||
const workId = _workId || _courseId.workId
|
||||
const courseId = _courseId.coursesId
|
||||
this.props.history.push(`/courses/${courseId}/${secondName}/${workId}/question`)
|
||||
} else {
|
||||
this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/question`)
|
||||
}
|
||||
}
|
||||
|
||||
toWorkSettingPage = (_courseId, _workId) => {
|
||||
const secondName = this.getModuleName()
|
||||
if (typeof _courseId == "object") {
|
||||
const workId = _courseId.workId
|
||||
const courseId = _courseId.coursesId
|
||||
this.props.history.push(`/courses/${courseId}/${secondName}/${_workId || workId}/setting`)
|
||||
} else {
|
||||
this.props.history.push(`/courses/${_courseId}/${secondName}/${_workId}/setting`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const { snackbarOpen} = this.state;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<WrappedComponent {...this.props}
|
||||
toDetailPage={this.toDetailPage}
|
||||
toEditPage={this.toEditPage}
|
||||
toNewPage={this.toNewPage}
|
||||
toListPage={this.toListPage}
|
||||
toWorkDetailPage={this.toWorkDetailPage}
|
||||
toWorkDetailPage2={this.toWorkDetailPage2}
|
||||
toWorkPostPage={this.toWorkPostPage}
|
||||
toWorkListPage={this.toWorkListPage}
|
||||
toWorkAnswerPage={this.toWorkAnswerPage}
|
||||
toWorkQuestionPage={this.toWorkQuestionPage}
|
||||
toWorkSettingPage={this.toWorkSettingPage}
|
||||
|
||||
toCreateProject={this.toCreateProject}
|
||||
|
||||
isGroup={this.isGroup}
|
||||
getModuleName={this.getModuleName}
|
||||
getModuleType={this.getModuleType}
|
||||
|
||||
>
|
||||
|
||||
</WrappedComponent>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import React,{Component} from "react";
|
||||
|
||||
export default function LeaderIcon(props = {}) {
|
||||
let icon = null;
|
||||
const { className, style } = props;
|
||||
const _className = `font-8 blueFull Actionbtn ${className}`
|
||||
if (props.small) {
|
||||
icon = <div className={_className} style={{
|
||||
height: '14px',
|
||||
'line-height': '14px',
|
||||
// width: '24px',
|
||||
transform: 'scale(0.833)',
|
||||
padding: '0px 5px',
|
||||
'margin-top': '-2px',
|
||||
'margin-left': '2px',
|
||||
'vertical-align': 'middle', }}>组长</div>
|
||||
} else {
|
||||
icon = <div className={_className} style={{ height: '16px', 'line-height': '16px', transform: 'scale(0.833)'}}>组长</div>
|
||||
|
||||
}
|
||||
return icon
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
import React,{Component} from "react";
|
||||
import { Form, Select, Input, Button,Checkbox,Icon,message,Modal, Table, Divider, Tag,DatePicker,Radio,Tooltip} from "antd";
|
||||
import {Link} from 'react-router-dom';
|
||||
import { WordsBtn, getRandomcode } from 'educoder';
|
||||
import axios from 'axios';
|
||||
import PublishRightnow from '../PublishRightnow'
|
||||
import AccessoryModal from "../../coursesPublic/AccessoryModal";
|
||||
import DownloadMessageysl from "../../../modals/DownloadMessageysl";
|
||||
|
||||
const { Option} = Select;
|
||||
const CheckboxGroup = Checkbox.Group;
|
||||
const confirm = Modal.confirm;
|
||||
let GraduationTasksnewtype=true;
|
||||
const $ = window.$;
|
||||
const Search = Input.Search;
|
||||
const RadioGroup = Radio.Group;
|
||||
|
||||
class TabRightComponents extends Component{
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
|
||||
this.publishModal = React.createRef();
|
||||
this.endModal = React.createRef();
|
||||
|
||||
this.state={
|
||||
accessoryVisible: false,
|
||||
DownloadType:false,
|
||||
DownloadMessageval:undefined,
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
}
|
||||
|
||||
onToPublishClick = () => {
|
||||
|
||||
}
|
||||
// 补交附件
|
||||
Cancelvisible=()=>{
|
||||
this.setState({
|
||||
accessoryVisible:false
|
||||
})
|
||||
}
|
||||
/// 确认是否下载
|
||||
confirmysl(url){
|
||||
axios.get(url + '&export=true' ).then((response) => {
|
||||
if(response.data.status&&response.data.status===-1){
|
||||
|
||||
}else if(response.data.status&&response.data.status===-2){
|
||||
if(response.data.message === "100"){
|
||||
// 已超出文件导出的上限数量(100 ),建议:
|
||||
|
||||
this.setState({
|
||||
DownloadType:true,
|
||||
DownloadMessageval:100
|
||||
})
|
||||
}else {
|
||||
//因附件资料超过500M
|
||||
this.setState({
|
||||
DownloadType:true,
|
||||
DownloadMessageval:500
|
||||
})
|
||||
}
|
||||
}else {
|
||||
this.props.slowDownload(getRandomcode(url));
|
||||
// this.props.showNotification(`正在下载中`);
|
||||
// window.open("/api"+url, '_blank');
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
});
|
||||
}
|
||||
|
||||
Downloadcal=()=>{
|
||||
this.setState({
|
||||
DownloadType:false,
|
||||
DownloadMessageval:undefined
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
addAccessory=()=>{
|
||||
this.setState({
|
||||
accessoryVisible:true
|
||||
})
|
||||
}
|
||||
setupdate = () => {
|
||||
|
||||
}
|
||||
render(){
|
||||
const dateFormat = 'YYYY-MM-DD HH:mm';
|
||||
const { accessoryVisible } = this.state
|
||||
let { work_statuses, publish_immediately, work_id
|
||||
, end_immediately
|
||||
} =this.props;
|
||||
|
||||
let courseId=this.props.match.params.coursesId;
|
||||
let category_id=this.props.match.params.category_id;
|
||||
let workId=this.props.match.params.workId;
|
||||
|
||||
const isGroup = this.props.isGroup()
|
||||
const moduleName = !isGroup? "普通作业":"分组作业";
|
||||
const moduleEngName = this.props.getModuleName()
|
||||
|
||||
const childModuleName = this.props.moduleName
|
||||
|
||||
const isAdmin = this.props.isAdmin()
|
||||
const isSuperAdmin = this.props.isSuperAdmin()
|
||||
|
||||
let exportUrls = `/api/homework_commons/${workId}/works_list.zip`
|
||||
const exportResultUrls = `/api/homework_commons/${workId}/works_list.xlsx`
|
||||
return(
|
||||
<React.Fragment>
|
||||
{isAdmin ?
|
||||
<React.Fragment>
|
||||
<div style={{display: 'inline', float: 'right'}}>
|
||||
<PublishRightnow ref={this.publishModal} showActionButton={false} {...this.props} checkBoxValues={[workId]}
|
||||
isPublish={true} doWhenSuccess={this.props.doWhenSuccess} checkBeforePost={this.props.saveWorkSetting}
|
||||
onToPublishClick={this.onToPublishClick}
|
||||
></PublishRightnow>
|
||||
<PublishRightnow ref={this.endModal} showActionButton={false} {...this.props} checkBoxValues={[workId]}
|
||||
isPublish={false} doWhenSuccess={this.props.doWhenSuccess}></PublishRightnow>
|
||||
</div>
|
||||
<DownloadMessageysl
|
||||
{...this.props}
|
||||
value={this.state.DownloadMessageval}
|
||||
modalCancel={this.Downloadcal}
|
||||
modalsType={this.state.DownloadType}
|
||||
/>
|
||||
<style>{`
|
||||
.drop_down_menu li a {
|
||||
padding: 0px;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
.drop_down_menu {
|
||||
width: 121px;
|
||||
}
|
||||
.drop_down_menu li {
|
||||
overflow: visible;
|
||||
width: 121px;
|
||||
}
|
||||
.drop_down_menu, .drop_down_normal {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
`}</style>
|
||||
{this.props.isAdmin()? <li className="li_line drop_down fr color-blue font-16 mt20" style={{"padding":"0 20px"}}>
|
||||
导出<i className="iconfont icon-xiajiantou font-12 ml2"></i>
|
||||
<ul className="drop_down_menu" style={{"right":"-34px","left":"unset","height":"auto"}}>
|
||||
<li><a onClick={(url)=>this.confirmysl(exportResultUrls)} className="color-dark">导出成绩</a></li>
|
||||
<li><a onClick={(url)=>this.confirmysl(exportUrls)} className="color-dark">导出作品附件</a></li>
|
||||
</ul>
|
||||
</li>:""}
|
||||
|
||||
{/* <a className={"fr color-blue font-16"} href={exportUrl}>导出作品附件</a>
|
||||
<a className={"fr color-blue font-16"} href={exportResultUrl}>导出成绩</a> */}
|
||||
{/*<a className={"fr color-blue font-16"}>导出</a>*/}
|
||||
{end_immediately && <a className={"fr color-blue font-16"} onClick={() => { this.endModal.current.open() } }>立即截止</a>}
|
||||
{publish_immediately && <a className={"fr color-blue font-16"} onClick={() => { this.publishModal.current.open() } } >立即发布</a>}
|
||||
|
||||
{/*<a className={"fr color-blue font-16"}>项目在线质量检测</a>*/}
|
||||
{isAdmin && <a className={"fr color-blue font-16"} onClick={() => this.props.toEditPage(this.props.match.params, workId)}>编辑作业</a>}
|
||||
</React.Fragment> :
|
||||
<React.Fragment>
|
||||
{work_statuses && work_statuses.indexOf('提交作品') != -1 && <a className={"fr color-blue font-16"} href={"javascript:void(0)"}
|
||||
onClick={() => { this.props.toWorkPostPage(this.props.match.params)}}
|
||||
>提交作品</a>}
|
||||
{work_statuses && work_statuses.indexOf('修改作品') != -1 && <a className={"fr color-blue font-16"} href={"javascript:void(0)"}
|
||||
onClick={() => { this.props.toWorkPostPage(this.props.match.params, null, true, work_id)}}
|
||||
>修改作品</a>}
|
||||
{work_statuses && work_statuses.indexOf('补交附件') != -1 &&
|
||||
<React.Fragment>
|
||||
<AccessoryModal
|
||||
{...this.props}
|
||||
modalname={"补交附件"}
|
||||
visible={accessoryVisible}
|
||||
Cancelname={"取消"}
|
||||
Savesname={"确认"}
|
||||
Cancel={this.Cancelvisible}
|
||||
setupdate={this.setupdate}
|
||||
reviseAttachmentUrl={`/student_works/${work_id}/revise_attachment.json`}
|
||||
/>
|
||||
<a className={"fr color-blue font-16"} href={"javascript:void(0)"}
|
||||
onClick={this.addAccessory}
|
||||
>补交附件</a>
|
||||
</React.Fragment>
|
||||
}
|
||||
</React.Fragment> }
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default TabRightComponents;
|
||||
@@ -0,0 +1,172 @@
|
||||
import React,{Component} from "react";
|
||||
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal, Table, Divider, Tag,DatePicker,Radio,Tooltip} from "antd";
|
||||
import {Link} from 'react-router-dom';
|
||||
import locale from 'antd/lib/date-picker/locale/zh_CN';
|
||||
import { WordsBtn, MarkdownToHtml } from 'educoder';
|
||||
import axios from 'axios';
|
||||
import Modals from '../../../modals/Modals';
|
||||
import CoursesListType from '../../coursesPublic/CoursesListType';
|
||||
import AccessoryModal from "../../coursesPublic/AccessoryModal";
|
||||
|
||||
import '../../css/Courses.css'
|
||||
import CBreadcrumb from '../../common/CBreadcrumb'
|
||||
|
||||
const { Option} = Select;
|
||||
const CheckboxGroup = Checkbox.Group;
|
||||
const confirm = Modal.confirm;
|
||||
let GraduationTasksnewtype=true;
|
||||
const $ = window.$;
|
||||
const Search = Input.Search;
|
||||
const RadioGroup = Radio.Group;
|
||||
|
||||
class WorkDetailPageHeader extends Component{
|
||||
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.state={
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
}
|
||||
|
||||
goback = () => {
|
||||
let workId=this.props.match.params.workId;
|
||||
|
||||
if ( window.location.pathname.indexOf('appraise') == -1) {
|
||||
let category_id= this.props.category.category_id;
|
||||
this.props.toListPage(this.props.match.params, category_id)
|
||||
} else {
|
||||
this.props.toWorkListPage(this.props.match.params, workId)
|
||||
// this.props.match.params.category_id
|
||||
}
|
||||
// this.props.history.goBack()
|
||||
}
|
||||
// 补交附件
|
||||
Cancelvisible=()=>{
|
||||
this.setState({
|
||||
accessoryVisible:false
|
||||
})
|
||||
}
|
||||
addAccessory=()=>{
|
||||
this.setState({
|
||||
accessoryVisible:true
|
||||
})
|
||||
}
|
||||
setupdate = () => {
|
||||
this.props.getReviseAttachments && this.props.getReviseAttachments()
|
||||
}
|
||||
|
||||
render(){
|
||||
const dateFormat = 'YYYY-MM-DD HH:mm';
|
||||
|
||||
let {course_name, homework_name, search, page, loadingstate, homework_status, description, noTab
|
||||
, view_answer, author_name, category, work_id, current_user
|
||||
} =this.props;
|
||||
|
||||
let courseId=this.props.match.params.coursesId;
|
||||
let category_id= category && category.category_id;
|
||||
let category_name= category && category.category_name;
|
||||
|
||||
let workId=this.props.match.params.workId;
|
||||
const studentWorkId = this.props.match.params.studentWorkId
|
||||
|
||||
const isGroup = this.props.isGroup()
|
||||
const moduleName = !isGroup? "普通作业":"分组作业";
|
||||
const moduleEngName = this.props.getModuleName()
|
||||
|
||||
const childModuleName = this.props.moduleName
|
||||
return(
|
||||
<React.Fragment>
|
||||
<div>
|
||||
<div className="newMain clearfix worklist1 workDetailPageHeader">
|
||||
<div className={"educontent mt20"}>
|
||||
<style>{`
|
||||
.memoContent {
|
||||
background: #fff;
|
||||
}
|
||||
.workDetailPageHeader .summaryname {
|
||||
line-height:28px
|
||||
}
|
||||
`}</style>
|
||||
<CBreadcrumb items={[
|
||||
{ to: current_user&¤t_user.first_category_url, name: course_name},
|
||||
{ to: `/courses/${courseId}/${moduleEngName}/${category_id}`, name: category_name },
|
||||
window.location.pathname.indexOf('appraise') == -1 ? { } : { to: `/courses/${courseId}/${moduleEngName}/${workId}/list`, name: '作业详情' },
|
||||
// 1. 与上一条联动,当匿评他人作品时,TA人作品的作者真实姓名切换为“匿名”
|
||||
window.location.pathname.indexOf('appraise') == -1 ? { name: '作业详情' } : { name: author_name },
|
||||
// window.location.pathname.indexOf('appraise') == -1 ? { } : { to: `/courses/${courseId}/${moduleEngName}/${workId}/list`, name: '作品列表' },
|
||||
// { name: childModuleName }
|
||||
]}></CBreadcrumb>
|
||||
|
||||
<div className="clearfix mt20 mb20" >
|
||||
<span className=" fl color-black summaryname">
|
||||
{homework_name}
|
||||
{/* <Link to={"/courses/"+courseId+"/graduation"+"/graduation_tasks/"}>{homework_name}</Link> */}
|
||||
</span>
|
||||
<CoursesListType
|
||||
typelist={homework_status}
|
||||
typesylename={"mt3"}
|
||||
/>
|
||||
|
||||
|
||||
{category && <a className="color-grey-6 fr font-16 ml30 mr30 lineh-25" onClick={this.goback}>返回</a>}
|
||||
|
||||
{this.props.update_atta &&
|
||||
<React.Fragment>
|
||||
{this.state.accessoryVisible===true? <AccessoryModal
|
||||
{...this.props}
|
||||
modalname={"补交附件"}
|
||||
visible={this.state.accessoryVisible}
|
||||
Cancelname={"取消"}
|
||||
Savesname={"确认"}
|
||||
Cancel={this.Cancelvisible}
|
||||
setupdate={this.setupdate}
|
||||
seeworks={undefined}
|
||||
reviseAttachmentUrl={`/student_works/${work_id || studentWorkId}/revise_attachment.json`}
|
||||
/>:""}
|
||||
<a className={"fr color-blue font-16 "} href={"javascript:void(0)"}
|
||||
onClick={this.addAccessory} style={{ 'marginTop': '-4px' }}
|
||||
>补交附件</a>
|
||||
</React.Fragment>
|
||||
|
||||
}
|
||||
</div>
|
||||
|
||||
{ noTab !== true && <div className="stud-class-set bor-bottom-greyE">
|
||||
<div className="mt10 clearfix edu-back-white poll_list pl5">
|
||||
<Link
|
||||
className={`${childModuleName == '作品列表' ? 'active' : '' } `}
|
||||
to={`/courses/${courseId}/${moduleEngName}/${workId}/list`}>作品列表</Link>
|
||||
<Link
|
||||
className={`${childModuleName == '作业描述' ? 'active' : '' } `}
|
||||
to={`/courses/${courseId}/${moduleEngName}/${workId}/question`}>作业描述</Link>
|
||||
{view_answer == true && <Link
|
||||
className={`${childModuleName == '参考答案' ? 'active' : '' } `}
|
||||
to={`/courses/${courseId}/${moduleEngName}/${workId}/answer`}>参考答案</Link>}
|
||||
|
||||
<Link
|
||||
className={`${childModuleName == '设置' ? 'active' : '' } `}
|
||||
style={{paddingLeft:this.props.isAdmin()?'38px':'20px'}}
|
||||
to={`/courses/${courseId}/${moduleEngName}/${workId}/setting`}>{this.props.isAdmin()?"设置":"得分规则"}</Link>
|
||||
|
||||
|
||||
{ this.props.tabRightComponents }
|
||||
|
||||
</div>
|
||||
</div> }
|
||||
|
||||
{/* 内容区 */}
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default WorkDetailPageHeader;
|
||||