杨树明 5 years ago
commit 8ebf969251

@ -42,8 +42,6 @@
"immutability-helper": "^2.6.6",
"install": "^0.12.2",
"jest": "20.0.4",
"js-base64": "^2.5.1",
"js-file-download": "^0.4.7",
"lodash": "^4.17.5",
"loglevel": "^1.6.1",
"material-ui": "^1.0.0-beta.40",
@ -165,7 +163,6 @@
"babel-plugin-import": "^1.11.0",
"concat": "^1.0.3",
"happypack": "^5.0.1",
"videojs-for-react": "^0.0.3",
"webpack-bundle-analyzer": "^3.0.3",
"webpack-parallel-uglify-plugin": "^1.1.0"
}

@ -0,0 +1,103 @@
function Base64() {
// private property
_keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
// public method for encoding
this.encode = function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = _utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
_keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
_keyStr.charAt(enc3) + _keyStr.charAt(enc4);
}
return output;
}
// public method for decoding
this.decode = function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = _keyStr.indexOf(input.charAt(i++));
enc2 = _keyStr.indexOf(input.charAt(i++));
enc3 = _keyStr.indexOf(input.charAt(i++));
enc4 = _keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = _utf8_decode(output);
return output;
}
// private method for UTF-8 encoding
_utf8_encode = function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
}
// private method for UTF-8 decoding
_utf8_decode = function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
} else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
} else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
}

@ -211,20 +211,35 @@ $(function(){
var FF = !(window.mozInnerScreenX == null);
var websshLineHeight = FF ? 19 : 18
function throttle(method, delay, duration){
var timer = null, begin = new Date();
return function(){
var context = this, args = arguments, current = new Date();
clearTimeout(timer);
if(current-begin >= duration){
method.apply(context, args);
begin = current;
} else {
timer = setTimeout(function(){
method.apply(context, args);
}, delay);
}
}
}
doc.live('mousemove touchmove',function(e){
$(".-brother").show();// 代码行的遮罩显示
if(dragging) {
clickX = e.pageX || e.originalEvent.touches[0].pageX;;
if(clickX > leftOffset+0&&clickX<leftOffset+1600) {
console.log('resize')
//console.log(1);
lab.css('left', clickX - 7 - leftOffset + 'px');
$("#game_left_contents").width( clickX-leftOffset + 'px');
nextW2 = clickX-leftOffset;
$("#game_right_contents").width( wrapWidth - nextW2 + 'px');
//console.log(lab.next().width());
refresh_editor_monaco()
throttle(refresh_editor_monaco, 100, 200)()
} else {
lab.css('left', '0px');
}
@ -246,7 +261,8 @@ $(function(){
var w = $("#games_repository_contents").width();
$(".game_webssh").css("min-height", m);
$(".game_webssh").css("max-height", m);
refresh_editor_monaco(m)
throttle(refresh_editor_monaco, 100, 200)(m)
// refresh_editor_monaco(m)
// 火狐下行高为19
// CodeRepositoryView.js有同样的计算逻辑用来初始化ssh
var rows = Math.round(m / websshLineHeight);
@ -1187,6 +1203,8 @@ $(function(){ // 这里重新加一次事件监听,不在原有事件的基
dragging = true;
dragDom = lab;
$('#htmlIframe').css('pointer-events', 'none')
$('#can-drag').show()
lab.hide()
return false;
}
);
@ -1206,8 +1224,11 @@ $(function(){ // 这里重新加一次事件监听,不在原有事件的基
})
doc.live("mouseup", function(e) {
lab.show()
// 在大窗口将下边测试集滚动条拖上去后,将窗口缩小,再拖下来就有这种情况 https://www.trustie.net/issues/16326
if (dragging === true) {
$('#can-drag').hide()
window.editor_CodeMirror && window.editor_CodeMirror.refresh()
// 使得iframe可以继续捕获事件

@ -60,7 +60,7 @@ class DMDEditor extends Component{
<style>{`
`}</style>
<div id="content_editorMd_show" className="new_li content_editorMd_show"
<div id="content_editorMd_show" className="new_li content_editorMd_show markdown-body"
style={_style}
dangerouslySetInnerHTML={{__html: initValue ? markdownToHTML(initValue):this.props.placeholder}}
onClick={this.toMDMode}

@ -6,7 +6,6 @@ import {getImageUrl} from 'educoder';
import axios from 'axios'
import {getUrl} from 'educoder';
import moment from 'moment'
import { Base64 } from 'js-base64';
import CoursesListType from '../coursesPublic/CoursesListType';
import Showoldfiles from "../coursesPublic/Showoldfiles";
import Modals from '../../modals/Modals';

@ -186,7 +186,7 @@ class Exercisestatisticalresult extends Component {
<span className="CACFF">{item.ques_position+"."}{item.ques_type===0?"单选":item.ques_type===1?"多选":item.ques_type===2?"判断":item.ques_type===3?"填空":item.ques_type===4?"主观":item.ques_type===5?"实训":""}</span>
<div>
{/*Q{item.ques_position}*/}
<div dangerouslySetInnerHTML={{__html: markdownToHTML(item.ques_title).replace(/▁/g,"▁▁▁")}}></div>
<div className={"markdown-body"} dangerouslySetInnerHTML={{__html: markdownToHTML(item.ques_title).replace(/▁/g,"▁▁▁")}}></div>
{/*<span className="markdown-body" dangerouslySetInnerHTML={createMarkup(item.ques_title)}></span>*/}
</div>

@ -293,7 +293,20 @@ class GraduationTasksSubmitedit extends Component{
funtaskstatus=(checkedValues)=>{
let{memberslist,selectobjct}=this.state;
let{memberslist,selectobjct,workslist}=this.state;
if(selectobjct.length>workslist.max_num){
this.setState({
minvalue:workslist.max_num,
setvalue:"大于",
minmaxtype:true
})
return
}else{
this.setState({
minmaxtype:false
})
}
let newlist =memberslist;
let newcheckedValues=checkedValues;
let selects=[];
@ -309,6 +322,7 @@ class GraduationTasksSubmitedit extends Component{
}
}
this.setState({
task_status:checkedValues,
selectmemberslist:selects
@ -347,12 +361,7 @@ class GraduationTasksSubmitedit extends Component{
handleSubmit=(e) => {
let {fileList,selectmemberslist,workslist}=this.state;
if(fileList.length===0){
this.setState({
shixunsreplace:true,
})
return
}
this.Commoninterface(fileList,selectmemberslist,workslist);
// setTimeout(function () {
@ -361,6 +370,7 @@ class GraduationTasksSubmitedit extends Component{
}
Commoninterface =(fileList,selectmemberslist,workslist)=>{
let userids=[];
for(var list of selectmemberslist){
@ -386,17 +396,16 @@ class GraduationTasksSubmitedit extends Component{
return
}
if(workslist.task_type===2){
if(userids.length<2){
if(userids.length<workslist.min_num){
this.setState({
minvalue:2,
minvalue:workslist.min_num,
setvalue:"小于",
minmaxtype:true
})
return
}else if(userids.length>5){
}else if(userids.length>workslist.max_num){
this.setState({
minvalue:5,
minvalue:workslist.max_num,
setvalue:"大于",
minmaxtype:true
})
@ -409,6 +418,13 @@ class GraduationTasksSubmitedit extends Component{
})
let workId=this.props.match.params.work_Id;
if(fileList.length===0){
this.setState({
shixunsreplace:true,
})
return
}
let url="/graduation_works/"+workId+".json";
axios.put(url, {
description:values.description,
@ -474,7 +490,7 @@ class GraduationTasksSubmitedit extends Component{
multiple: true,
// https://github.com/ant-design/ant-design/issues/15505
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
showUploadList: false,
// showUploadList: false,
action: `${getUrl()}/api/attachments.json`,
onChange: this.handleChange,
onRemove: this.onAttachmentRemove,
@ -628,37 +644,37 @@ class GraduationTasksSubmitedit extends Component{
)
})}
<style>
{
`
.maxwidth500{
max-width:500px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: #05101a;
}
`
}
</style>
{this.state.fileList.length===0?"":this.state.fileList.map((item,key)=>{
return(
<p className="color-grey mt10" key={key} >
<a className="color-grey fl">
<i className="font-14 color-green iconfont icon-fujian mr8" aria-hidden="true"></i>
</a>
<span className="mr12 color9B9B maxwidth500 fl" length="58">
{item.name}
</span>
<span className="color656565 mt2 color-grey-6 font-12 mr8">
{item.response===undefined?"":bytesToSize(item.size)}
</span>
<i className="font-14 iconfont icon-guanbi "
id={item.response===undefined?"":item.response.id}
aria-hidden="true" onClick={()=>this.onAttachmentRemove(item.response===undefined?"":item.response.id&&item.response.id)}></i>
</p>
)
})}
{/*<style>*/}
{/*{*/}
{/*`*/}
{/*.maxwidth500{*/}
{/*max-width:500px;*/}
{/*overflow: hidden;*/}
{/*text-overflow: ellipsis;*/}
{/*white-space: nowrap;*/}
{/*color: #05101a;*/}
{/*}*/}
{/*`*/}
{/*}*/}
{/*</style>*/}
{/*{this.state.fileList.length===0?"":this.state.fileList.map((item,key)=>{*/}
{/*return(*/}
{/*<p className="color-grey mt10" key={key} >*/}
{/*<a className="color-grey fl">*/}
{/*<i className="font-14 color-green iconfont icon-fujian mr8" aria-hidden="true"></i>*/}
{/*</a>*/}
{/*<span className="mr12 color9B9B maxwidth500 fl" length="58">*/}
{/*{item.name}*/}
{/*</span>*/}
{/*<span className="color656565 mt2 color-grey-6 font-12 mr8">*/}
{/*{item.response===undefined?"":bytesToSize(item.size)}*/}
{/*</span>*/}
{/*<i className="font-14 iconfont icon-guanbi "*/}
{/*id={item.response===undefined?"":item.response.id}*/}
{/*aria-hidden="true" onClick={()=>this.onAttachmentRemove(item.response===undefined?"":item.response.id&&item.response.id)}></i>*/}
{/*</p>*/}
{/*)*/}
{/*})}*/}
@ -675,7 +691,7 @@ class GraduationTasksSubmitedit extends Component{
>
<div>
<div className={"fl ml20"}>成员要求25</div>
<div className={"fl ml20"}>成员要求{workslist&&workslist.min_num}{workslist&&workslist.max_num}</div>
<Search
className={"fl mt5 ml20"}
style={{width:"270px"}}
@ -724,7 +740,7 @@ class GraduationTasksSubmitedit extends Component{
</div>:memberslist&&memberslist.map((item,key)=>{
return(
<div key={key} style={{
width: '375px',
width: '400px',
height: '30px'
}}>
<Checkbox value={item.user_id}
@ -735,8 +751,8 @@ class GraduationTasksSubmitedit extends Component{
}
disabled={item.commit_status===true?true:false} className="fl "></Checkbox>
<div className={"fl ml5 fonthidden width100"} style={{width: '70px'}} title={item.user_name}>{item.user_name}</div>
<div className={"fl ml5 fonthidden width100 color-grey-9"} style={{width: '70px'}}>{item.group_name}</div>
<div className={"fl ml5 color-grey-9 fonthidden width100"} style={{width: '70px'}}>{item.student_id}</div>
<div className={"fl ml5 fonthidden width100 color-grey-9"}>{item.group_name}</div>
<div className={"fl ml5 color-grey-9 fonthidden width100"}>{item.student_id}</div>
<div className={"fl ml20"}>{item.commit_status===false?<span className={"color-orange"}>已提交</span> :""}</div>
</div>
)
@ -760,7 +776,7 @@ class GraduationTasksSubmitedit extends Component{
height: '30px',
display: item.user_name === undefined ? "none" : ""
}}>
<div className={"fl ml5 fonthidden width100"} style={{width: '50px'}}
<div className={"fl ml5 fonthidden width100"}
title={item.user_name}>{item.user_name}</div>
<div className={"fl ml5 fonthidden width100 color-grey-9"}>{item.group_name}</div>
<div className={"fl ml5 color-grey-9 fonthidden width100"}>{item.student_id}</div>
@ -769,6 +785,7 @@ class GraduationTasksSubmitedit extends Component{
style={{marginTop: '-4px'}}
onClick={() => this.delecttask_status(item.user_id)}></i>
</div> : ""}
<div className={"both"}></div>
</div>
)
}

@ -85,15 +85,9 @@ class GraduationTasksSubmitnew extends Component{
}
handleSubmit=(e) => {
console.log("86");
let {fileList,selectmemberslist,workslist}=this.state;
if(fileList.length === 0){
this.setState({
shixunsreplace:true,
})
return
}
this.Commoninterface(fileList,selectmemberslist,workslist);
}
@ -280,7 +274,19 @@ class GraduationTasksSubmitnew extends Component{
funtaskstatus=(checkedValues)=>{
let{memberslist,selectobjct}=this.state;
let{memberslist,selectobjct,workslist}=this.state;
if(selectobjct.length>workslist.max_num){
this.setState({
minvalue:workslist.max_num,
setvalue:"大于",
minmaxtype:true
})
return
}else{
this.setState({
minmaxtype:false
})
}
let newlist =memberslist;
let newcheckedValues=checkedValues;
let selects=[];
@ -382,17 +388,17 @@ class GraduationTasksSubmitnew extends Component{
}
if(workslist&&workslist.task_type===2){
if(userids!=undefined){
if(userids.length<2){
if(userids.length<workslist.min_num){
this.setState({
minvalue:2,
minvalue:workslist.min_num,
setvalue:"小于",
minmaxtype:true
})
return
}else if(userids.length>5){
}else if(userids.length>workslist.max_num){
this.setState({
minvalue:5,
minvalue:workslist.max_num,
setvalue:"大于",
minmaxtype:true
})
@ -405,8 +411,16 @@ class GraduationTasksSubmitnew extends Component{
spinnings:true
})
let id=this.props.match.params.task_Id;
if(fileList.length === 0){
this.setState({
shixunsreplace:true,
})
return
}
debugger
let url="/graduation_tasks/"+id+"/graduation_works.json";
axios.post(url, {
description:values.description,
@ -471,7 +485,7 @@ render(){
multiple: true,
// https://github.com/ant-design/ant-design/issues/15505
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
showUploadList: false,
// showUploadList: false,
action: `${getUrl()}/api/attachments.json`,
onChange: this.handleChange,
onRemove: this.onAttachmentRemove,
@ -593,37 +607,37 @@ render(){
</Button>
<span className={"color-grey-9"}>(单个文件150M以内)</span>
</Upload>
<style>
{
`
.maxwidth500{
max-width:500px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: #05101a;
}
`
}
</style>
{this.state.fileList.length===0?"":this.state.fileList.map((item,key)=>{
return(
<p className="color-grey mt10" key={key} >
<a className="color-grey fl">
<i className="font-14 color-green iconfont icon-fujian mr8" aria-hidden="true"></i>
</a>
<span className="mr12 color9B9B maxwidth500 fl" length="58">
{item.name}
</span>
<span className="color656565 mt2 color-grey-6 font-12 mr8">
{item.response===undefined?"":bytesToSize(item.size)}
</span>
<i className="font-14 iconfont icon-guanbi "
id={item.response===undefined?"":item.response.id}
aria-hidden="true" onClick={()=>this.onAttachmentRemove(item.response===undefined?"":item.response.id&&item.response.id)}></i>
</p>
)
})}
{/*<style>*/}
{/*{*/}
{/*`*/}
{/*.maxwidth500{*/}
{/*max-width:500px;*/}
{/*overflow: hidden;*/}
{/*text-overflow: ellipsis;*/}
{/*white-space: nowrap;*/}
{/*color: #05101a;*/}
{/*}*/}
{/*`*/}
{/*}*/}
{/*</style>*/}
{/*{this.state.fileList.length===0?"":this.state.fileList.map((item,key)=>{*/}
{/*return(*/}
{/*<p className="color-grey mt10" key={key} >*/}
{/*<a className="color-grey fl">*/}
{/*<i className="font-14 color-green iconfont icon-fujian mr8" aria-hidden="true"></i>*/}
{/*</a>*/}
{/*<span className="mr12 color9B9B maxwidth500 fl" length="58">*/}
{/*{item.name}*/}
{/*</span>*/}
{/*<span className="color656565 mt2 color-grey-6 font-12 mr8">*/}
{/*{item.response===undefined?"":bytesToSize(item.size)}*/}
{/*</span>*/}
{/*<i className="font-14 iconfont icon-guanbi "*/}
{/*id={item.response===undefined?"":item.response.id}*/}
{/*aria-hidden="true" onClick={()=>this.onAttachmentRemove(item.response===undefined?"":item.response.id&&item.response.id)}></i>*/}
{/*</p>*/}
{/*)*/}
{/*})}*/}
</div>
@ -638,7 +652,7 @@ render(){
>
<div>
<div className={"fl ml20"}>成员要求25</div>
<div className={"fl ml20"}>成员要求{workslist&&workslist.min_num}{workslist&&workslist.max_num}</div>
<input type="text" style={{width:"0px",height:"0px",display:"none"}} onKeyUp={(e) => this.onSearchKeywordKeyUp(e)}
onkeydown={(e)=>this.onSearchKeywordKeyUps(e)}/>

@ -7,15 +7,9 @@ import axios from 'axios';
import Modals from '../../../modals/Modals';
import DownloadMessage from '../../../modals/DownloadMessage';
import CoursesListType from '../../coursesPublic/CoursesListType';
import PublishModals from "../../coursesPublic/PublishModals";
import HomeworkModal from "../../coursesPublic/HomeworkModal";
import moment from 'moment';
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 range(start, end) {

@ -376,7 +376,7 @@ class GraduationTasksquestions extends Component{
width: '100%',
border: '1px solid transparent'
}}>
<div dangerouslySetInnerHTML={{__html: markdownToHTML(questionslist.description).replace(/▁/g,"▁▁▁")}}></div>
<div className={"markdown-body"} dangerouslySetInnerHTML={{__html: markdownToHTML(questionslist.description).replace(/▁/g,"▁▁▁")}}></div>
</div>:""
}

@ -0,0 +1,80 @@
import React, { useState, useEffect } from 'react'
import { trigger } from 'educoder'
import { Input, Checkbox } from "antd";
function CourseGroupChooser({ course_groups, isAdminOrCreator, item, index, arg_course_groups, checkAllValue
, coursesids, onCheckAllChange, joinCourseGroup }) {
const [state, setState] = useState({counter: 0})
const [search, setSearch] = useState('')
// useEffect(() => {
// console.log(' cdm')
// return () => {
// console.log(' cwum')
// };
// // , [state.counter] 加了这个后onClick就消失了 加错位置了?
// }, [state.counter] )
// TODO 为什么每次onClick都会执行 cwum
// const add1ToCounter = () => {
// const newCounterValue = state.counter + 1
// setState({ counter: newCounterValue })
// }
/**
that.state.groupSearchValue
that.setState({groupSearchValue: e.target.value})
that.onCheckAllChange(e, item, index) - onCheckAllChange(e, item, index)
that.joinCourseGroup(checkedValues, item, index) - joinCourseGroup(checkedValues, item, index)
that.state.checkAllArray[index] - checkAllValue
*/
return (
<ul className="drop_down_menu" style={{"lef":"tunset", minWidth: '262px'}}>
{
course_groups && course_groups.length > 10?
(<p className="drop_down_search">
<Input placeholder="搜索" value={search} onChange={(e) => {setSearch(e.target.value)}} allowClear/>
</p>):
''
}
<Checkbox.Group onChange={(checkedValues) => joinCourseGroup(checkedValues, item, index)}
value={arg_course_groups.map(item => item.id)}
disabled={!isAdminOrCreator} className="mainGroup"
>
{course_groups && course_groups.length > 1 && <li key={'_all' + index} >
{/* 防止被外面group包裹 */}
<Checkbox.Group>
<Checkbox
checked={checkAllValue}
style={{ marginRight: '6px' }} onClick={(e) => onCheckAllChange(e, item, index)} onChange={() => {}}
>全选</Checkbox>
</Checkbox.Group>
</li>}
{
course_groups && course_groups.filter((item) => {
return (!search || item.name.indexOf(search) != -1)
}).map((item,key)=>{
return(
<li key={item.id} value={item.id} >
<Checkbox value={item.id}
style={{ marginRight: '6px' }}
></Checkbox>
{item.name}
</li>
)
})
}
</Checkbox.Group>
<p className="drop_down_btn">
<a href="javascript:void(0)" className="color-grey-6"
onClick={() => trigger('groupAdd', coursesids)}
>添加分班...</a>
</p>
</ul>
)
}
export default CourseGroupChooser

@ -1,5 +1,5 @@
import React,{ Component } from "react";
import { Input,Checkbox,Table, Divider, Tooltip,Spin } from "antd";
import { Input,Checkbox,Table, Divider, Tooltip,Spin, Menu } from "antd";
import CourseLayoutcomponent from '../common/CourseLayoutComponent'
@ -21,24 +21,29 @@ import { from } from "array-flatten";
import AddGraduationGroupModal from './modal/AddGraduationGroupModal'
import AddAdminModal from './modal/AddAdminModal'
import { ROLE_TEACHER_NUM, ROLE_ASSISTANT_NUM } from './common'
import CourseGroupChooser from './CourseGroupChooser'
const Search = Input.Search;
const ROLE_ADMIN = "管理员"
const ROLE_TEACHER = "教师"
const ROLE_TEACHER_ASSISTANT = "助教"
const pageSize = 20;
function buildColumns(that) {
let sortedInfo = that.state.sortedInfo || {}
const isAdmin = that.props.isAdmin()
const isAdminOrCreator = that.props.isAdminOrCreator();
const isAdminOrTeacher = that.props.isAdminOrTeacher()
const { course_groups } = that.state
const { course_groups, filterKey } = that.state
const showSorter = filterKey == '1'
const columns = [{
title: '序号',
dataIndex: 'name',
key: 'index',
render: (content, item, index) => {
return item.isApply == true ? '' : <a href="javascript:;">{(that.state.page - 1) * 20 + index + 1
- (that.state.application_list ? that.state.application_list.length : 0)} </a>
return index + 1
// return item.isApply == true ? '' : <a href="javascript:;">{(that.state.page - 1) * 20 + index + 1
// - (that.state.application_list ? that.state.application_list.length : 0)} </a>
}
}
// ,{
@ -55,6 +60,8 @@ function buildColumns(that) {
dataIndex: 'name',
width: 120,
key: 'name',
sorter: showSorter,
sortOrder: sortedInfo.columnKey === 'name' && sortedInfo.order,
render: (name, record) => {
return <a href={`/login/${record.login}`} target="_blank" className="overflowHidden1" style={{ maxWidth: '110px'}}
title={`${name.length > 4 ? name : ''}`}>{name}</a>
@ -63,6 +70,11 @@ function buildColumns(that) {
title: '角色',
dataIndex: 'role',
key: 'role',
sorter: showSorter,
// 'ascend' | 'descend'
defaultSortOrder: 'ascend',
sortOrder: sortedInfo.columnKey === 'role' && sortedInfo.order,
}]
that.state.course_groups && that.state.course_groups.length && columns.push({
title: <Tooltip title="仅能批阅指定分班的作品">管理权限</Tooltip>,
@ -84,49 +96,13 @@ function buildColumns(that) {
{ isAdmin &&
<React.Fragment>
<i className="iconfont icon-xiajiantou font-12 ml2"></i>
{!noGroups && <ul className="drop_down_menu" style={{"lef":"tunset", minWidth: '262px'}}>
{
course_groups && course_groups.length > 10?
(<p className="drop_down_search">
<Input placeholder="搜索" value={that.state.groupSearchValue} onChange={(e) => {that.setState({groupSearchValue: e.target.value})}} allowClear/>
</p>):
''
}
{course_groups && course_groups.length > 1 && <li key={'_all' + index} >
{/* 防止被外面group包裹 */}
<Checkbox.Group>
<Checkbox
checked={that.state.checkAllArray[index]}
style={{ marginRight: '6px' }} onClick={(e) => that.onCheckAllChange(e, item, index)} onChange={() => {}}
>全选</Checkbox>
</Checkbox.Group>
</li>}
<Checkbox.Group onChange={(checkedValues) => that.joinCourseGroup(checkedValues, item, index)}
value={arg_course_groups.map(item => item.id)}
disabled={!isAdminOrCreator}
>
{
course_groups && course_groups.filter((item) => {
return (!that.state.groupSearchValue || item.name.indexOf(that.state.groupSearchValue) != -1)
}).map((item,key)=>{
return(
<li key={key} value={item.id} >
<Checkbox value={item.id}
style={{ marginRight: '6px' }}
></Checkbox>
{item.name}
</li>
)
})
}
<p className="drop_down_btn">
<a href="javascript:void(0)" className="color-grey-6"
onClick={() => trigger('groupAdd', that.props.coursesids)}
>添加分班...</a>
</p>
</Checkbox.Group>
</ul>}
{!noGroups && <CourseGroupChooser
{...{course_groups, isAdminOrCreator, item, index, arg_course_groups,
checkAllValue: that.state.checkAllArray[index],
joinCourseGroup: that.joinCourseGroup,
onCheckAllChange: that.onCheckAllChange,
coursesids: that.props.coursesids }}
></CourseGroupChooser>}
</React.Fragment> }
</span>
</ConditionToolTip>)
@ -138,8 +114,11 @@ function buildColumns(that) {
columns.push({
title: '答辩组',
// width: 90,
sorter: showSorter,
key: 'graduation_group',
dataIndex: 'graduation_group',
sortOrder: sortedInfo.columnKey === 'graduation_group' && sortedInfo.order,
render: text => (
<span>
{text}
@ -200,6 +179,7 @@ class studentsList extends Component{
this.state={
headIndex:"1",
page:1,
sortedInfo: { columnKey: 'role', order: 'ascend'},
totalPage:undefined,
searchValue:"",
order: ORDER_BY_DATE,
@ -209,7 +189,8 @@ class studentsList extends Component{
checkBoxValues: [],
isSpin:false,
application_list: [],
checkAllArray: []
checkAllArray: [],
filterKey: 1, // 1 已审批 2 待审批
}
}
onCheckAllChange = (e, item, index) => {
@ -312,7 +293,7 @@ class studentsList extends Component{
});
}
joinCourseGroup = (ids, item, index) => {
console.log('join ', ids, item)
// console.log('join ', ids, item)
const courseId = this.props.match.params.coursesId
@ -339,7 +320,7 @@ class studentsList extends Component{
console.log(error);
});
}
fetchAll=(argPage)=>{
fetchAll = async (argPage) => {
this.setState({
isSpin:true
})
@ -347,28 +328,57 @@ class studentsList extends Component{
if (argPage) {
this.setState({ page: argPage })
}
const sortedInfo = this.state.sortedInfo;
let page = argPage || this.state.page
let { order, searchValue }=this.state
let url=`/courses/${id}/teachers.json?order=${order}&page=${page}`;
let { searchValue, filterKey }=this.state
let order = 1;
if (sortedInfo.columnKey == 'role') {
order = 1;
} else if (sortedInfo.columnKey == 'name') {
order = 2;
} else if (sortedInfo.columnKey == 'graduation_group') {
order = 3;
}
let sort = 'desc'
if (sortedInfo.order == 'ascend') {
sort = 'asc'
}
let url=`/courses/${id}/teachers.json?order=${order}&page=${page}&sort=${sort}`;
if (filterKey == '1') {
} else if (filterKey == '2') {
url = `/courses/${id}/apply_teachers.json?_a=1`
}
if(searchValue!=""){
url+='&search='+searchValue;
}
axios.get((url)).then((result)=>{
const result = await axios.get(url)
// axios.get((url)).then((result)=>{
if (result.data.teacher_list) {
this.setState({
teachers: result.data.teacher_list,
total_count: result.data.teacher_list_size,
application_list: result.data.application_list,
application_list: result.data.application_list || [],
is_admin: result.data.is_admin,
apply_size: result.data.apply_size,
isSpin:false
})
} else if (result.data.application_list) {
this.setState({
total_count: result.data.teacher_list_size,
application_list: result.data.application_list || [],
is_admin: result.data.is_admin,
apply_size: result.data.apply_size,
isSpin:false
})
}
}).catch((error)=>{
console.log(error);
this.setState({
isSpin:false
})
})
// }).catch((error)=>{
// console.log(error);
// this.setState({
// isSpin:false
// })
// })
}
getGroupList(){
let id = this.props.match.params.coursesId
@ -529,13 +539,33 @@ class studentsList extends Component{
})
return result && result.length > 0
}
onTableChange = (pagination, filters, sorter) => {
console.log('Various parameters', pagination, filters, sorter);
this.setState({
sortedInfo: sorter,
}, () => {
this.fetchAll()
});
};
clearSelection = () => {
this.setState({ checkBoxValues: [] })
}
selectedStatus=(e)=>{
this.clearSelection()
this.setState({
filterKey: e.key,
page:1,
isSpin:true
}, () => {
this.fetchAll();
})
}
render(){
const isAdmin = this.props.isAdmin()
const columns = buildColumns(this)
let {
searchValue, checkBoxValues, checkAllValue,
groupList, total_count, teachers, order, page
groupList, total_count, teachers, order, page, apply_size, filterKey
}=this.state
let currentOrderName = '加入时间排序'
@ -544,12 +574,13 @@ class studentsList extends Component{
} else if (order == ORDER_BY_GRADUATION_GROUP) {
currentOrderName = '答辩组排序'
}
const combineArray = teachers.slice(0)
if (page == 1) {
this.state.application_list && this.state.application_list.slice(0).reverse().forEach(item => {
item.isApply = true
combineArray.unshift(item)
})
let combineArray = teachers.slice(0)
if (page == 1 && filterKey == '2') {
// this.state.application_list && this.state.application_list.slice(0).reverse().forEach(item => {
// item.isApply = true
// combineArray.unshift(item)
// })
combineArray = this.state.application_list
}
const isAdminOrTeacher = this.props.isAdminOrTeacher()
const hasGraduationModule = this.hasGraduationModule()
@ -585,21 +616,39 @@ class studentsList extends Component{
</React.Fragment>
}
secondRowLeft={
total_count ? <ColorCountText count={total_count} name="个教师"></ColorCountText> : ''
isAdminOrTeacher ? <div className="fl mt6 task_menu_ul ">
<Menu mode="horizontal" defaultSelectedKeys="1" onClick={this.selectedStatus}>
<Menu.Item key="1">已审批({total_count})</Menu.Item>
<Menu.Item key="2">待审批({apply_size})</Menu.Item>
</Menu>
</div> :
(total_count ? <ColorCountText count={total_count} name="个教师"></ColorCountText> : '')
}
onPressEnter={this.onPressEnter}
></Titlesearchsection>
<style>{`
/* CourseGroupChooser */
.drop_down_menu .mainGroup.ant-checkbox-group {
max-height: 380px;
overflow-y: auto;
}
.task_menu_ul .ant-menu-item, .task_menu_ul .ant-menu-submenu-title{
padding:0px;
margin-right: 30px;
line-height: 68px;
font-size: 16px;
}
.teacherList .ant-table-pagination.ant-pagination {
float: none;
text-align: center;
}
`}</style>
<div className="mt20 edu-back-white padding20 teacherList">
<div className="clearfix stu_head" style={{paddingLeft: '15px'}}>
{filterKey == '1' && <div className="clearfix stu_head" style={{paddingLeft: '15px'}}>
{ isAdminOrTeacher && hasGraduationModule && <Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue} >已选 {checkBoxValues.length} </Checkbox> }
{ <div className="studentList_operation_ul">
{ filterKey == '1' && <div className="studentList_operation_ul">
{ hasGraduationModule && isAdminOrTeacher && <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", minWidth: '222px'}}>
@ -627,22 +676,23 @@ class studentsList extends Component{
</p>
</ul>
</li> }
<li className="drop_down">
{/* <li className="drop_down">
{currentOrderName} <i className="iconfont icon-xiajiantou font-12 ml2"></i>
<ul className="drop_down_normal">
<li onClick={() => this.onSortTypeChange(ORDER_BY_NAME)} >姓名排序</li>
<li onClick={() => this.onSortTypeChange(ORDER_BY_DATE)} style={{width: '125px'}}>加入时间排序</li>
{this.hasGraduationModule() && <li onClick={() => this.onSortTypeChange(ORDER_BY_GRADUATION_GROUP)} >答辩组排序</li>}
</ul>
</li>
</li> */}
</div> }
</div>
</div>}
<Spin size="large" spinning={this.state.isSpin}>
<div className="clearfix stu_table">
<Checkbox.Group style={{ width: '100%' }} onChange={this.onCheckBoxChange} value={checkBoxValues}>
{/* pagination={{ current: page, total: total_count, pageSize:20, onChange: this.onPageChange }} */}
<Table columns={columns} dataSource={combineArray}
pagination={total_count > 20 ? { //分页
onChange={this.onTableChange}
pagination={total_count > 20 && filterKey == '1' ? { //分页
total: page == 1 && this.state.application_list.length ? total_count + total_count / Math.floor(this.state.application_list.length + 20) : total_count , //数据总数量
pageSize: page == 1 && this.state.application_list.length ? this.state.application_list.length + 20 : 20, //显示几条一页
current: page,

File diff suppressed because it is too large Load Diff

@ -340,3 +340,6 @@ textarea:read-only{
line-height: 40px;
text-align: center;
}
.myyslwidth {
min-width:1200px
}

@ -160,7 +160,7 @@ class CommitSummary extends Component{
max: 5000, message: '最大限制为5000个字符',
}],
})(
<TPMMDEditor ref={this.mdRef} placeholder={'请在此输入帖子详情,最大限制为5000个字符'}
<TPMMDEditor ref={this.mdRef} placeholder={'请在此输入总结内容,最多5000个字符'}
mdID={'courseMessageMD'} initValue={this.state.description} className="courseMessageMD"></TPMMDEditor>
)}
</div>

@ -337,13 +337,6 @@ class Listofworks extends Component {
render: (text, record) => (
record.submitstate === "未提交" ? <span style={{ color: '#9A9A9A'}}>--</span> :
<span>
<Tooltip placement="bottom" title={<div>
<div>直接调整最终成绩的分数</div>
<div>其它评分全部作废</div>
</div>}>
<a style={this.props.isNotMember() === true ? this.state.mystyles : this.state.mystyle}
onClick={() => this.Viewstudenttraininginformations(record)}>调分</a>
</Tooltip>
<a style={{"text-align": "center"}} className="color-blue"
onClick={() => this.Viewstudenttraininginformation(record)}>{record.operating}</a>
</span>
@ -590,13 +583,6 @@ class Listofworks extends Component {
render: (text, record) => (
record.submitstate === "未提交" ? <span style={{ color: '#9A9A9A'}}>--</span> :
<span>
<Tooltip placement="bottom" title={<div>
<div>直接调整最终成绩的分数</div>
<div>其它评分全部作废</div>
</div>}>
<a style={this.props.isNotMember() === true ? this.state.mystyles : this.state.mystyle}
onClick={() => this.Viewstudenttraininginformations(record)}>调分</a>
</Tooltip>
<a style={{"text-align": "center"}} className="color-blue"
onClick={() => this.Viewstudenttraininginformation(record)}>{record.operating}</a>
</span>

@ -33,7 +33,6 @@ import '../css/Courses.css'
import './style.css'
import moment from 'moment';
import 'moment/locale/zh-cn';
import {Base64} from 'js-base64';
const Search = Input.Search;
const CheckboxGroup = Checkbox.Group;
@ -752,7 +751,7 @@ class ShixunStudentWork extends Component {
</style>
{data&&data?
<div>
<div style={{display:duplicatechecking===false?"":"none"}}>
<ul className="clearfix" style={{padding: '20px 16px 10px'}}>
<li className="clearfix ">

@ -1,5 +1,5 @@
import React, {Component} from "react";
import {WordsBtn} from 'educoder';
import {WordsBtn,markdownToHTML} from 'educoder';
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal, Table, Divider,InputNumber, Tag,DatePicker,Radio,Tooltip,Spin} from "antd";
import {Link,Switch,Route,Redirect} from 'react-router-dom';
import axios from 'axios';
@ -13,14 +13,11 @@ import 'codemirror/mode/cmake/cmake';
import 'codemirror/mode/xml/xml';
import 'codemirror/mode/javascript/javascript';
import 'codemirror/mode/clike/clike';
import '../css/members.css';
import "../common/formCommon.css";
import '../css/Courses.css';
import './style.css';
import moment from 'moment';
import 'moment/locale/zh-cn';
import {Base64} from 'js-base64';
class ShixunWorkReport extends Component {
@ -173,7 +170,6 @@ class ShixunWorkReport extends Component {
<style>
{`
.personalsummary{
height:115px;
border:1px solid rgba(235,235,235,1);
border-radius:2px;
}
@ -195,7 +191,9 @@ class ShixunWorkReport extends Component {
</style>
<div className={"pad040"}>
<div className={"personalsummary"}>
{data&&data.work_description}
<div className={"markdown-body"}
dangerouslySetInnerHTML={{__html: markdownToHTML(data&&data.work_description).replace(/▁/g, "▁▁▁")}}></div>
</div>
</div>
</div>

@ -184,10 +184,10 @@ class ShixunWorkModal extends Component{
if (response.data.status === 0) {
this.props.updatas()
this.props.issCancel()
notification.open({
message:"提示",
description: response.data.message
});
// notification.open({
// message:"提示",
// description: response.data.message
// });
this.props.history.replace(`/courses/${this.props.match.params.coursesId}/shixun_homeworks/${this.props.match.params.homeworkid}/student_work`);
}else if(response.data.status === -1){
notification.open({

@ -4,7 +4,6 @@ import HomeworkModal from "../coursesPublic/HomeworkModal";
import {WordsBtn, ActionBtn, handleDateString} from 'educoder';
import PollDetailTabForthRules from '../poll/PollDetailTabForthRules';
import ShixunWorkModal from './Shixunworkdetails/ShixunWorkModal';
import {Base64} from 'js-base64';
import {
Button,
Checkbox,

@ -23,7 +23,6 @@ import {
import {Link, Switch, Route, Redirect} from 'react-router-dom';
import moment from 'moment';
import 'moment/locale/zh-cn';
import {Base64} from 'js-base64';
import axios from 'axios';
import '../css/members.css'
import "../common/formCommon.css"
@ -510,7 +509,7 @@ class Workquestionandanswer extends Component {
}
</style>
<div className={"font-16 color-dark fl pl20 "}>
<div
<div className={"markdown-body"}
dangerouslySetInnerHTML={{__html: markdownToHTML(jobsettingsdata.data.description).replace(/▁/g, "▁▁▁")}}></div>
{/* /!*{}}></div>
{/* /!*{jobsettingsdata.data.description}*!/*/}
@ -560,7 +559,7 @@ class Workquestionandanswer extends Component {
<div className="pl20 markdown-body" style={{"padding": "10px 10px 10px 20px"}}>
{jobsettingsdata === undefined ? "无" : jobsettingsdata === null ? "无" : jobsettingsdata === "null" ? "无" :
jobsettingsdata.data.explanation === undefined ? "无" : jobsettingsdata.data.explanation === null ? "无" :
<div
<div className={"markdown-body"}
dangerouslySetInnerHTML={{__html: markdownToHTML(jobsettingsdata.data.explanation).replace(/▁/g, "▁▁▁")}}></div>
}

@ -58,6 +58,14 @@ class MainContent extends Component {
font-family: 微软雅黑,宋体 !important;
overflow: hidden !important;
}
.can-drag {
width: 100%;
height: 100%;
z-index: 100;
position: fixed;
cursor: col-resize;
top: 0px;
}
`}</style>
<div className="-layout -stretch -fit labelN" id="game_show_content">
<div className="split-panel--first -layout -vertical -flex -relative -flex-basic40"
@ -67,7 +75,7 @@ class MainContent extends Component {
{/* 左侧任务说明等功能的区域 */}
<LeftViewContainer {...newProps}></LeftViewContainer>
</div>
<div id="can-drag" className="can-drag" style={{display: 'none'}}></div>
<div className="b-label -layout" style={{left: '687px'}}>
<div className="resize-helper ">
<Button variant="fab" aria-label="Swap" mini onClick={this.onResizeButtonClick}>

@ -18,7 +18,7 @@ export function ImageLayerOfCommentHOC(options = {}) {
const imageSrc = event.target.src || event.target.getAttribute('src') || event.target.getAttribute('href')
// 判断imageSrc是否是图片
const fileName = event.target.innerHTML.trim()
if (isImageExtension(imageSrc.trim()) || isImageExtension(fileName)) {
if (isImageExtension(imageSrc.trim()) || isImageExtension(fileName) || event.target.tagName == 'IMG') {
// 非回复里的头像图片; 非emoticons
if (imageSrc.indexOf('/images/avatars/User') === -1 &&
imageSrc.indexOf('kindeditor/plugins/emoticons') === -1 ) {

@ -41,9 +41,10 @@
align-items: center;
display: -webkit-flex;
height: 100%;
text-align: center;
}
.passImg{
max-width: 100%;
max-width: 86%;
max-height: 100%;
}
/* ImageLayer ----------------- End */

@ -159,7 +159,7 @@ class CodeEvaluateView extends Component {
let headIconClass = '';
let _headLockIconClass = '';
if (item.is_public === 0) {
if (item.is_public == 0) {
if (game.test_sets_view === true || power === 1){
_headLockIconClass = 'fas fa-unlock-alt'
} else {
@ -175,7 +175,7 @@ class CodeEvaluateView extends Component {
testSetsComponentArray.push(
<div className="-task-ces-top clearfix" onClick={ this.onTestSetHeaderClick.bind(this, index) }
style={{cursor:'pointer'}} key={index+'-0'}>
style={{cursor:'pointer', 'margin-top':index == 0 ? '4px' : ''}} key={index+'-0'}>
<p className="clearfix">
<i className={`fa ${ 'fa-caret-right'} mr8 font-16`}
style={isExpanded ? {transform: 'rotate(90deg)'} : {}}></i>

@ -283,6 +283,9 @@ class LeftView extends Component {
color: #CDCDCD;
flex: 0 0 45px;
}
.markdown-body ol, .markdown-body ul {
padding-left: 2.5em;
}
`}</style>
<div className="multiLevelAnswer">
@ -293,7 +296,7 @@ class LeftView extends Component {
<div className="name">{item.name}</div>
<div className="status">已解锁</div>
</div>
<div className="contents" dangerouslySetInnerHTML={{__html: markdownToHTML(item.contents)}}>
<div className="contents markdown-body" dangerouslySetInnerHTML={{__html: markdownToHTML(item.contents)}}>
</div>
</div>
})}

@ -342,7 +342,7 @@ class PathDetailIndex extends Component{
<div className="color-grey-6 clearfix">
<div id="shixuns_propaedeutics" className="new_li fl" style={{"padding":" 0px","textAlign": "justify;"}}>
{detailInfoList === undefined ? "" :detailInfoList.description===null?"":
<div dangerouslySetInnerHTML={{__html: markdownToHTML(detailInfoList.description).replace(/▁/g,"▁▁▁")}}></div>
<div className={"markdown-body"} dangerouslySetInnerHTML={{__html: markdownToHTML(detailInfoList.description).replace(/▁/g,"▁▁▁")}}></div>
}
</div>
</div>

@ -304,7 +304,7 @@ class Challenges extends Component {
id="challenge_editorMd_description">
<p id="ReactMarkdown" style={{overflow:'hidden'}}>
{ChallengesDataList === undefined ? "" :ChallengesDataList&&ChallengesDataList.description===null?"":
<div dangerouslySetInnerHTML={{__html: markdownToHTML(ChallengesDataList.description).replace(/▁/g,"▁▁▁")}}></div>
<div className={"markdown-body"} dangerouslySetInnerHTML={{__html: markdownToHTML(ChallengesDataList.description).replace(/▁/g,"▁▁▁")}}></div>
}
</p>

Loading…
Cancel
Save