杨树林 6 years ago
commit 2ad530e129

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because one or more lines are too long

@ -106,6 +106,7 @@
position: absolute;
top: -30px;
left: -30px;
left: -24px;
z-index: 999;
}

@ -484,7 +484,7 @@ class Comments extends Component {
const goldRewardInputErrorObj = goldRewardInputError ? {'error': 'error'} : {}
return (
<div className="fit -scroll">
<div className="fit -scroll" style={{ 'overflow-x': 'hidden'}}>
{ usingAntdModal ? <Modals

@ -0,0 +1,78 @@
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;
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: '' })
}
render(){
let { inputValue, visible } = 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>
{/* {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;

@ -3,13 +3,13 @@ import React,{ Component } from "react";
import {
Form, Input, InputNumber, Switch, Radio,
Slider, Button, Upload, Icon, Rate, Checkbox, message,
Row, Col, Select, Modal
Row, Col, Select, Modal, Divider
} 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';
@ -29,14 +29,14 @@ class BoardsNew extends Component{
boards: []
}
}
componentDidMount = () => {
const topicId = this.props.match.params.topicId
addSuccess = () => {
this.fetchBoards()
}
fetchBoards = () => {
const isEdit = this.isEdit
const boardId = this.props.match.params.boardId
const boardsUrl = `/courses/board_list.json?board_id=${boardId}`
const isEdit = !!topicId
const boardsUrl = `/courses/board_list.json?board_id=${boardId}`
axios.get(boardsUrl, { })
.then((response) => {
if (response.data.status == 0) {
@ -57,8 +57,17 @@ class BoardsNew extends Component{
.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, {
@ -260,6 +269,12 @@ class BoardsNew extends Component{
return(
<div className="newMain ">
<AddDirModal {...this.props}
title="添加目录"
label="目录名称"
ref="addDirModal"
addSuccess={this.addSuccess}
></AddDirModal>
<style>{`
.courseForm .ant-form {
}
@ -312,7 +327,17 @@ class BoardsNew extends Component{
{getFieldDecorator('select_board_id', {
// initialValue: '3779',
})(
<Select style={{ width: 230 }}>
<Select style={{ width: 230 }}
dropdownRender={menu => (
<div>
{menu}
<Divider style={{ margin: '4px 0' }} />
<div style={{ padding: '8px', cursor: 'pointer' }} onMouseDown={() => this.refs['addDirModal'].open()}>
<Icon type="plus" /> 添加目录
</div>
</div>
)}
>
{this.state.boards.map(item => {
return (
<Option value={item.id}>{item.name}</Option>

@ -71,9 +71,10 @@ function buildColumns(that, student_works) {
width: 90,
dataIndex: 'user_name',
key: 'user_name',
// width: '110px',
render: (text, record) => (
<div style={{
width: '110px',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'

@ -241,16 +241,18 @@ class CommonReply extends Component{
.course-message .commentInput {
padding-bottom: 56px !important;
}
.course-message .commentInput.mockInputWrapper {
padding-bottom: 30px !important;
.course-message .commentInput.mockInputWrapper {
padding-bottom: 20px !important;
}
.course-message .memoReplies {
border-top: 1px solid #EDEDED;
/* border-top: 1px solid #EDEDED; */
padding-bottom: 30px;
}
`}</style>
<MemoDetailMDEditor ref="editor" memo={memo} usingMockInput={true} placeholder="说点什么"
height={160} showError={true}
replyComment={this.replyComment}
commentsLength={comments ? comments.length : 0}
></MemoDetailMDEditor>
{/* bor-bottom-greyE */}
<div className="padding40 memoReplies commentsDelegateParent"

@ -7,6 +7,7 @@ import CoursesListType from '../coursesPublic/CoursesListType';
import Addcourses from '../coursesPublic/Addcourses';
import '../css/Courses.css';
import Modals from "../../modals/Modals";
import Guide from './CoursesGuide';
import AddStudentModal from '../members/modal/AddStudentModal'
import AddTeacherModal from '../members/modal/AddTeacherModal'
@ -43,6 +44,7 @@ class CoursesBanner extends Component {
modalsBottomval: "",
antIcon:false,
coursedata:undefined,
is_guide:false
}
}
componentDidMount() {
@ -323,13 +325,15 @@ class CoursesBanner extends Component {
postsettings=()=>{
window.location.href = "/courses/" + this.props.match.params.coursesId + "/settings";
}
render() {
let { Addcoursestypes, coursedata, modalsType, modalsTopval, loadtype,modalsBottomval,antIcon} = this.state;
let { Addcoursestypes, coursedata, modalsType, modalsTopval, loadtype,modalsBottomval,antIcon,is_guide} = this.state;
return (
<div>
{
is_guide && <Guide></Guide>
}
{
coursedata === undefined || coursedata.status===401? <div id="course_info_1309" className="courseHead" style={{height: '206px'}}></div>:<div id="course_info_1309" className="courseHead" style={{height: '206px'}}>

@ -0,0 +1,44 @@
import React, {Component} from 'react';
import '../css/Courses.css';
import {setImagesUrl} from 'educoder';
class CoursesGuide extends Component {
constructor(props) {
super(props)
this.state={
step:1
}
}
render(){
let {step} = this.state;
return(
<div className="guidePanel">
<style>{`
body{
overflow:hidden!important;
}
`}</style>
<div className="educontent">
{
step ==1 &&
<div>
<p className="clearfix"><img className="fr" src="/images/course/guide/1-1.png" width="175px" style={{margin:"205px 38px 0px 0px"}}/></p>
<p className="clearfix pr"><img src="/images/course/guide/1-2.png" className="fr mt20 guideFirstRight"/></p>
<p className="clearfix pr" style={{marginTop:"80px"}}>
<img src="/images/course/guide/1-4.png" className="fl guideFirstLeft"/>
<img src="/images/course/guide/1-3.png" className="fl" style={{marginLeft:"410px"}}/>
</p>
<p className="clearfix">
<img src="/images/course/guide/1-5.png" className="fl mt50"/>
<img src="/images/course/guide/1-6.png" className="fl mt40"/>
<a href="javascript:void(0)"><img src="/images/course/guide/1-7.png" className="fl mt80 ml100"/></a>
</p>
</div>
}
</div>
</div>
)
}
}
export default CoursesGuide;

@ -59,15 +59,18 @@ class Associationmodel extends Component{
goback=()=>{
debugger
this.setState({
Modalstype:false,
})
this.props.funlist()
this.props.Cancel()
this.props.funlist()
}
setSaves=()=>{
debugger
let {projectvalue}=this.state;
let taskid=this.props.taskid;
let url="/graduation_tasks/"+taskid+"/graduation_works/relate_project.json";
@ -76,19 +79,14 @@ class Associationmodel extends Component{
project_id: projectvalue
}).then((result)=>{
if(result.status===200){
if(result.data.status===0){
this.goback()
// this.setState({
// Modalstype:true,
// Modalstopval:result.data.message,
// ModalSave:this.goback,
// loadtype:true
// })
this.goback
}
}
}).catch((error)=>{
console.log(error)
@ -115,7 +113,7 @@ class Associationmodel extends Component{
project_id: projectvalue
}
}).then((result)=>{
if(result.status===200){
if(result.data.is_relate===false){
this.setSaves()
}else{
@ -126,7 +124,7 @@ class Associationmodel extends Component{
loadtype:true
})
}
}
}).catch((error)=>{
console.log(error)
})

@ -1,90 +1,91 @@
import React, { Component } from 'react';
import {Tooltip} from 'antd';
class CoursesListType extends Component {
constructor(props) {
super(props);
this.state={
// typelist:[],
// typesylename:"",
// tipval:""
}
}
componentDidMount() {
// let{typelist,typesylename,tipval}=this.props;
//
// this.setState({
// typelist:typelist,
// typesylename:typesylename,
// tipval:tipval
// })
// console.log("CoursesListType")
// console.log(typelist)
}
render() {
let {typelist,typesylename,tipval}=this.props;
return(
<span style={{display:'inline-block'}}>
{
typelist===undefined?"":typelist.map((item,key)=>{
return(
<Tooltip placement="bottom" title={tipval} getPopupContainer={()=>document.querySelector('.TabsWarp')}>
<span key={key}>
{item==="公开"?<span className={"edu-filter-btn edu-filter-btn-028d01 ml15 fl typestyle " + typesylename} >公开</span>:""}
{item==="已开启补交"?<span className={"edu-filter-btn edu-filter-btn-028d01 ml15 fl typestyle "+ typesylename} >已开启补交</span>:""}
{item==="未开启补交"?<span className={"edu-filter-btn edu-filter-btn-CC317C ml15 fl typestyle "+ typesylename} >未开启补交</span>:""}
{item==="匿名作品"?<span className={"edu-filter-btn edu-filter-btn-006B75 ml15 fl typestyle "+ typesylename} >匿名作品</span>:""}
{item==="已选择"?<span className={"edu-filter-btn edu-filter-btn-EDEDED ml15 fl typestyle color666666 "+ typesylename} >已选择</span>:""}
{item==="已结束"?<span className={"edu-filter-btn edu-filter-btn-EDEDED ml15 fl typestyle color666666 "+ typesylename} >已结束</span>:""}
{item==="提交中"?<span className={"edu-filter-btn edu-filter-btn-4CACFF ml15 fl typestyle "+ typesylename} >提交中</span>:""}
{item==="匿评中"?<span className={"edu-filter-btn edu-filter-btn-4CACFF ml15 fl typestyle "+ typesylename} >匿评中</span>:""}
{item==="申诉中"?<span className={"edu-filter-btn edu-filter-btn-4CACFF ml15 fl typestyle "+ typesylename} >申诉中</span>:""}
{item==="补交中"?<span className={"edu-filter-btn edu-filter-btn-4CACFF ml15 fl typestyle "+ typesylename} >补交中</span>:""}
{item==="评阅中"?<span className={"edu-filter-btn edu-filter-btn-4CACFF ml15 fl typestyle "+ typesylename} >评阅中</span>:""}
{item==="待选中"?<span className={"edu-filter-btn edu-filter-btn-4CACFF ml15 fl typestyle "+ typesylename} >待选中</span>:""}
{item==="交叉评阅中"?<span className={"edu-filter-btn edu-filter-btn-4CACFF ml15 fl typestyle "+ typesylename} >交叉评阅中</span>:""}
{item==="已开启交叉评阅"?<span className={"edu-filter-btn edu-filter-btn-E99695 ml15 fl typestyle "+ typesylename} >已开启交叉评阅</span>:""}
{item==="待确认"?<span className={"edu-filter-btn edu-filter-btn-5E5FB9 ml15 fl typestyle "+ typesylename} >待确认</span>:""}
{item==="待处理"?<span className={"edu-filter-btn edu-filter-btn-5E5FB9 ml15 fl typestyle mr10 "+ typesylename} >待处理</span>:""}
{item==="未发布"?<span className={"edu-filter-btn edu-filter-btn-84B6EB ml15 fl typestyle "+ typesylename} >未发布</span>:""}
{item==="私有"?<span className={"edu-filter-btn edu-filter-btn-84B6EB ml15 fl typestyle "+ typesylename} >私有</span>:""}
{item==="未提交"?<span className={"edu-filter-btn edu-filter-btn-84B6EB ml15 fl typestyle "+ typesylename} >未提交</span>:""}
{item==="已确认"?<span className={"edu-filter-btn edu-filter-btn-FC2B6A ml15 fl typestyle "+ typesylename} >已确认</span>:""}
{item==="已截止"?<span className={"edu-filter-btn edu-filter-btn-FC2B6A ml15 fl typestyle "+ typesylename} >已截止</span>:""}
</span>
</Tooltip>
)
})
}
</span>
)
}
}
export default CoursesListType;
// let typelist=["公开",
// "已开启补交",
// "未开启补交",
// "匿名作品",
// "已选择",
// "已结束",
// "提交中",
// "匿评中",
// "申诉中",
// "补交中",
// "评阅中",
// "待选中",
// "交叉评阅中",
// "已开启交叉评阅",
// "待确认",
// "待处理",
// "未发布",
// "私有",
// "未提交",
// "已确认",
// "已截止",
import React, { Component } from 'react';
import {Tooltip} from 'antd'
import '../css/Courses.css';
class CoursesListType extends Component {
constructor(props) {
super(props);
this.state={
// typelist:[],
// typesylename:"",
// tipval:""
}
}
componentDidMount() {
// let{typelist,typesylename,tipval}=this.props;
//
// this.setState({
// typelist:typelist,
// typesylename:typesylename,
// tipval:tipval
// })
// console.log("CoursesListType")
// console.log(typelist)
}
render() {
let {typelist,typesylename,tipval}=this.props;
return(
<span style={{display:'inline-block'}}>
{
typelist===undefined?"":typelist.map((item,key)=>{
return(
<Tooltip placement="bottom" title={tipval} getPopupContainer={()=>document.querySelector('.TabsWarp')}>
<span key={key}>
{item==="公开"?<span className={"edu-filter-btn edu-filter-btn-028d01 ml15 fl typestyle " + typesylename} >公开</span>:""}
{item==="已开启补交"?<span className={"edu-filter-btn edu-filter-btn-028d01 ml15 fl typestyle "+ typesylename} >已开启补交</span>:""}
{item==="未开启补交"?<span className={"edu-filter-btn edu-filter-btn-CC317C ml15 fl typestyle "+ typesylename} >未开启补交</span>:""}
{item==="匿名作品"?<span className={"edu-filter-btn edu-filter-btn-006B75 ml15 fl typestyle "+ typesylename} >匿名作品</span>:""}
{item==="已选择"?<span className={"edu-filter-btn edu-filter-btn-EDEDED ml15 fl typestyle color666666 "+ typesylename} >已选择</span>:""}
{item==="已结束"?<span className={"edu-filter-btn edu-filter-btn-EDEDED ml15 fl typestyle color666666 "+ typesylename} >已结束</span>:""}
{item==="提交中"?<span className={"edu-filter-btn edu-filter-btn-4CACFF ml15 fl typestyle "+ typesylename} >提交中</span>:""}
{item==="匿评中"?<span className={"edu-filter-btn edu-filter-btn-4CACFF ml15 fl typestyle "+ typesylename} >匿评中</span>:""}
{item==="申诉中"?<span className={"edu-filter-btn edu-filter-btn-4CACFF ml15 fl typestyle "+ typesylename} >申诉中</span>:""}
{item==="补交中"?<span className={"edu-filter-btn edu-filter-btn-4CACFF ml15 fl typestyle "+ typesylename} >补交中</span>:""}
{item==="评阅中"?<span className={"edu-filter-btn edu-filter-btn-4CACFF ml15 fl typestyle "+ typesylename} >评阅中</span>:""}
{item==="待选中"?<span className={"edu-filter-btn edu-filter-btn-4CACFF ml15 fl typestyle "+ typesylename} >待选中</span>:""}
{item==="交叉评阅中"?<span className={"edu-filter-btn edu-filter-btn-4CACFF ml15 fl typestyle "+ typesylename} >交叉评阅中</span>:""}
{item==="已开启交叉评阅"?<span className={"edu-filter-btn edu-filter-btn-E99695 ml15 fl typestyle "+ typesylename} >已开启交叉评阅</span>:""}
{item==="待确认"?<span className={"edu-filter-btn edu-filter-btn-5E5FB9 ml15 fl typestyle "+ typesylename} >待确认</span>:""}
{item==="待处理"?<span className={"edu-filter-btn edu-filter-btn-5E5FB9 ml15 fl typestyle mr10 "+ typesylename} >待处理</span>:""}
{item==="未发布"?<span className={"edu-filter-btn edu-filter-btn-84B6EB ml15 fl typestyle "+ typesylename} >未发布</span>:""}
{item==="私有"?<span className={"edu-filter-btn edu-filter-btn-84B6EB ml15 fl typestyle "+ typesylename} >私有</span>:""}
{item==="未提交"?<span className={"edu-filter-btn edu-filter-btn-84B6EB ml15 fl typestyle "+ typesylename} >未提交</span>:""}
{item==="已确认"?<span className={"edu-filter-btn edu-filter-btn-FC2B6A ml15 fl typestyle "+ typesylename} >已确认</span>:""}
{item==="已截止"?<span className={"edu-filter-btn edu-filter-btn-FC2B6A ml15 fl typestyle "+ typesylename} >已截止</span>:""}
</span>
</Tooltip>
)
})
}
</span>
)
}
}
export default CoursesListType;
// let typelist=["公开",
// "已开启补交",
// "未开启补交",
// "匿名作品",
// "已选择",
// "已结束",
// "提交中",
// "匿评中",
// "申诉中",
// "补交中",
// "评阅中",
// "待选中",
// "交叉评阅中",
// "已开启交叉评阅",
// "待确认",
// "待处理",
// "未发布",
// "私有",
// "未提交",
// "已确认",
// "已截止",
// ]

@ -613,7 +613,7 @@ class Selectsetting extends Component{
{item.name}
</span>
<span className="color656565 mt2 color-grey-6 font-12 mr8">
{item.response===undefined?"":isNaN(this.props.bytesToSize(item.response.filesize))?"":this.props.bytesToSize(item.response.filesize)}
{item.response===undefined?"":isNaN(this.props.bytesToSize(item.response.filesize))?"123":this.props.bytesToSize(item.response.filesize)}
</span>
<i className="font-14 iconfont icon-guanbi "
id={item.response===undefined?"":item.response.id}

@ -849,31 +849,31 @@ a.white-btn.use_scope-btn:hover{
.edu-filter-btn-028d01{
/*border: 1px solid #ff6800;*/
/*color: #ff6800!important;*/
background: #028d01;
background: #028d01 !important;
}
.edu-filter-btn-CC317C{
background:#CC317C;
background:#CC317C !important;
}
.edu-filter-btn-006B75{
background:#006B75;
background:#006B75 !important;
}
.edu-filter-btn-E99695{
background:#E99695;
background:#E99695 !important;
}
.edu-filter-btn-EDEDED{
background:#EDEDED;
background:#EDEDED !important;
}
.edu-filter-btn-4CACFF{
background:#4CACFF;
background:#4CACFF !important;
}
.edu-filter-btn-84B6EB{
background:#84B6EB;
background:#84B6EB !important;
}
.edu-filter-btn-5E5FB9{
background:#5E5FB9;
background:#5E5FB9 !important;
}
.edu-filter-btn-FC2B6A{
background:#FC2B6A;
background:#FC2B6A !important;
}
.color666666{
color:#666666 !important;
@ -1520,3 +1520,23 @@ input.ant-input-number-input:focus {
border-bottom: 1px solid transparent !important;
}
/* 指引 */
.guidePanel{
position: fixed;
top:0px;
left: 0px;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.7);
z-index: 10000;
}
.guideFirstRight{
position: absolute;
right: -90px;
}
.guideFirstLeft{
position: absolute;
left: -95px;
top:120px;
}

@ -98,7 +98,7 @@ class SingleEditor extends Component{
}
}
if(!answerArray || answerArray.length == 0) {
this.props.showNotification('请先点击本选择题的正确选项'); return;
this.props.showNotification('请先点击选择本选择题的正确选项'); return;
}
if(!question_title) {
this.props.showNotification('请先输入题目题干'); return;

@ -59,12 +59,12 @@ class GraduateTaskItem extends Component{
axios.get(url).then((result)=>{
if(result.data.status===0){
this.setState({
Modalstype:true,
Modalstopval:result.data.message,
cardsModalsavetype:this.cannerassocition,
loadtype:true
})
// this.setState({
// Modalstype:true,
// Modalstopval:result.data.message,
// cardsModalsavetype:this.cannerassocition,
// loadtype:true
// })
this.props.funlist()
}
@ -224,11 +224,11 @@ class GraduateTaskItem extends Component{
<span className="mr50">
{/* <a href="/users/innov" className="panel-name-small hide fl mr15 mr30 color-grey3">{discussMessage.author.name}</a> */}
{discussMessage.commit_count===undefined?"":<span className="mr15 color-grey9">{discussMessage.commit_count} 已交</span>}
{discussMessage.uncommit_count===undefined?"":<span className="mr15 color-grey9">{discussMessage.uncommit_count} 未交</span>}
{discussMessage.commit_count===undefined?"":<span className="mr15 color-grey9 font-14">{discussMessage.commit_count} 已交</span>}
{discussMessage.uncommit_count===undefined?"":<span className="mr15 color-grey9 font-14">{discussMessage.uncommit_count} 未交</span>}
{/*<span className="mr15 color-grey9">{discussMessage.replies_count} 3 未评</span>*/}
<Tooltip title={discussMessage.task_status===1?"提交剩余时间":discussMessage.task_status===2?"补交剩余时间":""} placement="bottom">
<span className="mr15 color-grey9">{discussMessage.status_time}</span>
<span className="mr15 color-grey9 font-14">{discussMessage.status_time}</span>
</Tooltip>
{/* { discussMessage.replies_count != 0 && <span className="mr15 color-grey9">{discussMessage.replies_count} </span> }

@ -2,7 +2,7 @@ import React,{Component} from "React";
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal,Spin,Tooltip} from "antd";
import {Link} from 'react-router-dom';
import TPMMDEditor from '../../../tpm/challengesnew/TPMMDEditor';
import { WordsBtn,getUrl } from 'educoder';
import { WordsBtn,getUrl ,bytesToSize} from 'educoder';
import axios from 'axios';
import Modals from '../../../modals/Modals';
const Search = Input.Search;
@ -577,7 +577,7 @@ class GraduationTasksSubmitedit extends Component{
{item.name}
</span>
<span className="color656565 mt2 color-grey-6 font-12 mr8">
{item.response===undefined?"":isNaN(this.props.bytesToSize(item.response.filesize))?"":this.props.bytesToSize(item.response.filesize)}
{item.response===undefined?"":bytesToSize(item.size)}
</span>
<i className="font-14 iconfont icon-guanbi "
id={item.response===undefined?"":item.response.id}

@ -2,7 +2,7 @@ import React,{Component} from "React";
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal,Tooltip,Spin} from "antd";
import {Link} from 'react-router-dom';
import TPMMDEditor from '../../../tpm/challengesnew/TPMMDEditor';
import { WordsBtn,getUrl,getImageUrl} from 'educoder';
import { WordsBtn,getUrl,getImageUrl,bytesToSize} from 'educoder';
import axios from 'axios';
import Modals from '../../../modals/Modals';
const Search = Input.Search;
@ -263,7 +263,7 @@ class GraduationTasksSubmitnew extends Component{
}
deleteAttachment = (file) => {
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
const url = `/attachments/${file}.json`
axios.delete(url, {
})
.then((response) => {
@ -446,7 +446,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,
@ -545,7 +545,39 @@ render(){
</Button>
<span className={"color-grey-9"}>(单个文件150M以内)</span>
</Upload>
</div>
<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>

@ -135,7 +135,7 @@ class GraduationTasksappraise extends Component{
let category_id=this.props.match.params.category_id;
let graduation_id=datalist===undefined?"":datalist.graduation_id;
let task_id=datalist===undefined?"":datalist.task_id;
console.log(datalist);
// console.log(datalist);
return(
<React.Fragment>
@ -197,7 +197,7 @@ class GraduationTasksappraise extends Component{
<div className="edu-back-white">
<div className={"stud-class-set edu-back-white padding20-30"}>
<div className={"stud-class-set edu-back-white padding20-30 bor-bottom-greyE"}>
<div className={"color-grey-6 h20 mb20"}>
内容
@ -249,8 +249,8 @@ class GraduationTasksappraise extends Component{
</div>
{firelistdata===undefined?"":firelistdata.length===0?"":firelistdata.revise_attachments.length===0?"":
<div className={"stud-class-set bor-top-greyE padding20-30 edu-back-white"}>
<div className={"color-grey-6 mb10 bor-top-greyE"}>
<div className={"stud-class-set bor-bottom-greyE padding20-30 edu-back-white"}>
<div className={"color-grey-6 mb10 "}>
补交附件
</div>
<div className={"ml20"}>
@ -258,7 +258,7 @@ class GraduationTasksappraise extends Component{
</div>
<div className="color-grey" key={key}>
<div className="color-grey">
{firelistdata===undefined?"":firelistdata.length===0?"":firelistdata.revise_attachments.map((item,key)=>{
return(
@ -291,7 +291,7 @@ class GraduationTasksappraise extends Component{
</div>}
{datalist&&datalist.project_info===undefined?"":
<div className={"stud-class-set edu-back-white padding20-30 bor-top-greyE"}>
<div className={"stud-class-set edu-back-white padding20-30 bor-bottom-greyE"}>
<div className={"color-grey-6 mb10"}>
关联项目
</div>
@ -301,7 +301,7 @@ class GraduationTasksappraise extends Component{
</div>}
{/*{*/}
{ datalist === undefined?"": datalist && datalist.task_type===undefined ?"" : datalist.task_type===1? "": datalist && datalist.work_members && datalist.work_members.length == 0 ?"":
<div className={"stud-class-set edu-back-white padding20-30 bor-top-greyE"} style={{height:"100%"}}>
<div className={"stud-class-set edu-back-white padding20-30 bor-bottom-greyE"} style={{height:"100%"}}>
<div className={"color-grey-6 mb10"}>
其他组员
</div>

@ -317,73 +317,59 @@ class GraduationTaskssettingapp extends Component{
}
funcrosscomment=(e)=>{
let {latetime,end_time}=this.state;
let {latetime,end_time,allowlate}=this.state;
let newtime;
if(latetime!=null&&end_time!=null){
if(e.target.checked===true){
if(moment(latetime)>moment(end_time)){
newtime=moment(latetime)+604800000;
newtime=new Date(newtime)
}else if(moment(latetime)<moment(end_time)){
newtime=moment(end_time)+604800000;
newtime=new Date(newtime)
}
if(e.target.checked===true){
if(allowlate===1||allowlate===true){
if(latetime===null||latetime===""){
let newlatetime=moment(new Date()).add(7, 'days').format("YYYY-MM-DD HH:mm");
let newcommenttime=moment(new Date()).format("YYYY-MM-DD HH:mm");
this.setState({
latetime:newlatetime,
crosscomment:e.target.checked,
commenttime:newcommenttime
})
}else{
let newlatetime=moment(latetime).add(7, 'days').format("YYYY-MM-DD HH:mm");
let newcommenttime=moment(latetime).format("YYYY-MM-DD HH:mm");
this.setState({
latetime:newlatetime,
crosscomment:e.target.checked,
commenttime:newcommenttime
})
}
}else{
if(end_time===null||end_time===""){
let newend_time=moment(new Date()).add(7, 'days').format("YYYY-MM-DD HH:mm");
let newcommenttime=moment(new Date()).add(8, 'days').format("YYYY-MM-DD HH:mm");
this.setState({
end_time:newend_time,
crosscomment:e.target.checked,
commenttime:newcommenttime
})
}else{
let newend_time=moment(end_time).add(7, 'days').format("YYYY-MM-DD HH:mm");
let newcommenttime=moment(end_time).add(8, 'days').format("YYYY-MM-DD HH:mm");
this.setState({
end_time:newend_time,
crosscomment:e.target.checked,
commenttime:newcommenttime
})
}
this.setState({
crosscomment:e.target.checked,
commenttime:moment(moment(newtime)).format("YYYY-MM-DD HH:mm"),
})
}
}else{
this.setState({
crosscomment:e.target.checked,
commenttime:undefined
})
}
}else if(latetime===null&&end_time!=null){
if(e.target.checked===true){
newtime=moment(end_time)+604800000;
newtime=new Date(newtime)
this.setState({
crosscomment:e.target.checked,
commenttime:newtime
})
}else{
this.setState({
crosscomment:e.target.checked,
commenttime:undefined
})
}
}else if(latetime!=null&&end_time===null){
if(e.target.checked===true){
newtime=moment(latetime)+604800000;
newtime=new Date(newtime)
this.setState({
crosscomment:e.target.checked,
commenttime:newtime
})
}else{
this.setState({
crosscomment:e.target.checked,
commenttime:undefined
})
}
}else if(latetime===null&&end_time===null){
if(e.target.checked===true){
newtime=moment(new Date())+604800000;
newtime=new Date(newtime)
this.setState({
crosscomment:e.target.checked,
commenttime:newtime
})
}else{
this.setState({
crosscomment:e.target.checked,
commenttime:undefined
})
}
}
}else{
this.setState({
crosscomment:e.target.checked,
commenttime:undefined
})
}
}
@ -588,7 +574,6 @@ class GraduationTaskssettingapp extends Component{
commenttimetype:false
})
}
debugger
if(moment(this.state.commenttime)<moment(publish_time)){
this.setState({
commenttimetype:true,

@ -544,12 +544,12 @@ class GraduationTaskssettinglist extends Component{
if(result.data.status===0){
this.searchValue()
this.setState({
Modalstype:true,
Modalstopval:result.data.message,
ModalSave:this.cannerassocition,
loadtype:true
})
// this.setState({
// Modalstype:true,
// Modalstopval:result.data.message,
// ModalSave:this.cannerassocition,
// loadtype:true
// })
}
}).catch((error)=>{

@ -550,7 +550,7 @@ class studentsList extends Component{
{
total_count > 0 ?
total_count > 0 || this.state.isSpin == true ?
<div className="mt20 edu-back-white padding20">
<div className="clearfix stu_head" style={{paddingLeft: '15px'}}>
{isAdmin && <Checkbox className="fl" onChange={this.onCheckAll} checked={checkAllValue} >已选 {checkBoxValues.length} </Checkbox>}

@ -33,6 +33,7 @@ function buildColumns(that) {
const { course_groups } = that.state
const columns = [{
title: '序号',
width: 28,
// dataIndex: 'name',
key: 'index',
render: (content, item, index) => {
@ -40,12 +41,13 @@ function buildColumns(that) {
}
},{
title: '用户ID',
width: 82,
dataIndex: 'login',
key: 'login'
}, {
title: '姓名',
dataIndex: 'name',
width: 160,
width: 140,
key: 'name',
render: (name, record) => {
return <a href={`/login/${record.login}`} target="_blank">{name}</a>
@ -57,7 +59,7 @@ function buildColumns(that) {
}]
that.state.course_groups && that.state.course_groups.length && columns.push({
title: <Tooltip title="仅能批阅指定分班的作品">管理权限</Tooltip>,
width: 230,
// width: 230,
key: 'course_groups',
dataIndex: 'course_groups',
// onClick={() => that.joinCourseGroup(item.id)}
@ -113,6 +115,7 @@ function buildColumns(that) {
if (hasGraduationModule) {
columns.push({
title: '答辩组',
width: 74,
key: 'graduation_group',
dataIndex: 'graduation_group',
render: text => (
@ -126,6 +129,7 @@ function buildColumns(that) {
columns.push({
title: '操作',
key: 'action',
width: 150,
align:'center',
render: (text, record) => {
if (record.application_id) {

@ -148,13 +148,13 @@ class MemoDetailMDEditor extends Component {
margin-right: 0px !important;
}
.commentInput {
border-bottom: 1px solid #EEEEEE;
}
.commentInput .editormd{
width:100%!important;
}
`}</style>
<div style={{ display: isInited ? 'none' : ''}} className="mockInputWrapper commentInput" >
<div style={{ display: isInited ? 'none' : '', borderBottom: `${this.props.commentsLength == 0 ? 'none' : '1px solid #EEEEEE'}`}}
className="mockInputWrapper commentInput" >
<input onClick={this.onMockInputClick} placeholder={placeholder || '我要回复'}></input>
<a href="javascript:void(0)"
onClick={this.onMockInputClick} className="commentsbtn task-btn task-btn-blue">

@ -7,7 +7,7 @@
width:237px!important;
height: 30px;
margin-bottom: 30px;
margin-right: 35px;
/*margin-right: 35px;*/
}
.search-newysl {
width:237px!important;

@ -33,7 +33,7 @@ class MainContent extends Component {
}
render() {
const { challenge, output_sets, onRunCodeTest, latest_output, record, st, readRepoTimeout,
onTestSetHeaderClick, loading, codeLoading, shixun} = this.props
onTestSetHeaderClick, loading, codeLoading, shixun, vnc_url} = this.props
// if (output_sets && output_sets.test_sets) {
// const test_sets_array = JSON.parse("[" + output_sets.test_sets + "]");
@ -86,9 +86,11 @@ class MainContent extends Component {
<div className="fl pr tip-right-con" id="update_game_tip"></div>
</div>*/}
{/* { showIframeContent && vnc_url ? <VNCDisplay
{ showIframeContent && vnc_url ? <VNCDisplay
vnc_url={vnc_url}
></VNCDisplay> */}
></VNCDisplay>
:
<React.Fragment>
<div className="-layout-v -flex">
<div className="-flex -relative">
@ -143,6 +145,9 @@ class MainContent extends Component {
<div id="actionView" className="-layout-h -center -bg-grey-90 -grey-20 -bg-darkblack" style={{height:'48px'}}>
<ActionView onRunCodeTest={onRunCodeTest} {...this.props}></ActionView>
</div>
</React.Fragment>
}
</div>
</div>
</div>

@ -1,154 +1,154 @@
// import React, { Component } from 'react';
import React, { Component } from 'react';
// import RFB from '@novnc/novnc/lib/rfb.js';
import RFB from '@novnc/novnc/lib/rfb.js';
// const $ = window.$;
// // const showIframeContent = window.location.search.indexOf('vnc=1') != -1;
// class VNCDisplay extends Component {
// componentDidMount() {
// console.log(RFB)
const $ = window.$;
// const showIframeContent = window.location.search.indexOf('vnc=1') != -1;
class VNCDisplay extends Component {
componentDidMount() {
console.log(RFB)
// let rfb;
// let desktopName;
// // When this function is called we have
// // successfully connected to a server
// function connectedToServer(e) {
// status("Connected to " + desktopName);
// }
// // This function is called when we are disconnected
// function disconnectedFromServer(e) {
// if (e.detail.clean) {
// status("Disconnected");
// } else {
// status("Something went wrong, connection is closed");
// }
// }
// // When this function is called, the server requires
// // credentials to authenticate
// function credentialsAreRequired(e) {
// const password = prompt("Password Required:");
// rfb.sendCredentials({ password: password });
// }
// // When this function is called we have received
// // a desktop name from the server
// function updateDesktopName(e) {
// desktopName = e.detail.name;
// }
// // Since most operating systems will catch Ctrl+Alt+Del
// // before they get a chance to be intercepted by the browser,
// // we provide a way to emulate this key sequence.
// function sendCtrlAltDel() {
// rfb.sendCtrlAltDel();
// return false;
// }
// // Show a status text in the top bar
// function status(text) {
// document.getElementById('status').textContent = text;
// }
// // This function extracts the value of one variable from the
// // query string. If the variable isn't defined in the URL
// // it returns the default value instead.
// function readQueryVariable(name, defaultValue) {
// // A URL with a query parameter can look like this:
// // https://www.example.com?myqueryparam=myvalue
// //
// // Note that we use location.href instead of location.search
// // because Firefox < 53 has a bug w.r.t location.search
// const re = new RegExp('.*[?&]' + name + '=([^&#]*)'),
// match = document.location.href.match(re);
// if (typeof defaultValue === 'undefined') { defaultValue = null; }
// if (match) {
// // We have to decode the URL since want the cleartext value
// return decodeURIComponent(match[1]);
// }
// return defaultValue;
// }
// document.getElementById('sendCtrlAltDelButton')
// .onclick = sendCtrlAltDel;
// // Read parameters specified in the URL query string
// // By default, use the host and port of server that served this file
let rfb;
let desktopName;
// When this function is called we have
// successfully connected to a server
function connectedToServer(e) {
status("Connected to " + desktopName);
}
// This function is called when we are disconnected
function disconnectedFromServer(e) {
if (e.detail.clean) {
status("Disconnected");
} else {
status("Something went wrong, connection is closed");
}
}
// When this function is called, the server requires
// credentials to authenticate
function credentialsAreRequired(e) {
const password = prompt("Password Required:");
rfb.sendCredentials({ password: password });
}
// When this function is called we have received
// a desktop name from the server
function updateDesktopName(e) {
desktopName = e.detail.name;
}
// Since most operating systems will catch Ctrl+Alt+Del
// before they get a chance to be intercepted by the browser,
// we provide a way to emulate this key sequence.
function sendCtrlAltDel() {
rfb.sendCtrlAltDel();
return false;
}
// Show a status text in the top bar
function status(text) {
document.getElementById('status').textContent = text;
}
// This function extracts the value of one variable from the
// query string. If the variable isn't defined in the URL
// it returns the default value instead.
function readQueryVariable(name, defaultValue) {
// A URL with a query parameter can look like this:
// https://www.example.com?myqueryparam=myvalue
//
// Note that we use location.href instead of location.search
// because Firefox < 53 has a bug w.r.t location.search
const re = new RegExp('.*[?&]' + name + '=([^&#]*)'),
match = document.location.href.match(re);
if (typeof defaultValue === 'undefined') { defaultValue = null; }
if (match) {
// We have to decode the URL since want the cleartext value
return decodeURIComponent(match[1]);
}
return defaultValue;
}
document.getElementById('sendCtrlAltDelButton')
.onclick = sendCtrlAltDel;
// Read parameters specified in the URL query string
// By default, use the host and port of server that served this file
// // const host = readQueryVariable('host', window.location.hostname);
// // let port = readQueryVariable('port', window.location.port);
// // const password = readQueryVariable('password', '');
// const host = readQueryVariable('host', window.location.hostname);
// let port = readQueryVariable('port', window.location.port);
// const password = readQueryVariable('password', '');
// const { vnc_url } = this.props;
// // http://117.50.12.63:43149/vnc_lite.html?password=headless
// let _ar1 = vnc_url.split('/');
// let ipAndPort = _ar1[2].split(':')
// let passwordAr = _ar1[3].split('password=')
// const host = ipAndPort[0]
// let port = ipAndPort[1]
// const password = passwordAr[1].split('&')[0]
const { vnc_url } = this.props;
// http://117.50.12.63:43149/vnc_lite.html?password=headless
let _ar1 = vnc_url.split('/');
let ipAndPort = _ar1[2].split(':')
let passwordAr = _ar1[3].split('password=')
const host = ipAndPort[0]
let port = ipAndPort[1]
const password = passwordAr[1].split('&')[0]
// const path = readQueryVariable('path', 'websockify');
// // | | | | | |
// // | | | Connect | | |
// // v v v v v v
// status("Connecting");
// // Build the websocket URL used to connect
// let url;
// if (vnc_url.indexOf("https:") != -1) {
// url = 'wss';
// } else {
// url = 'ws';
// }
// url += '://' + host;
// if(port) {
// url += ':' + port;
// }
// url += '/' + path;
// // Creating a new RFB object will start a new connection
// rfb = new RFB(document.getElementById('screen'), url,
// { credentials: { password: password } });
// // Add listeners to important events from the RFB module
// rfb.addEventListener("connect", connectedToServer);
// rfb.addEventListener("disconnect", disconnectedFromServer);
// rfb.addEventListener("credentialsrequired", credentialsAreRequired);
// rfb.addEventListener("desktopname", updateDesktopName);
// // Set parameters that can be changed on an active connection
// rfb.viewOnly = readQueryVariable('view_only', false);
// rfb.scaleViewport = readQueryVariable('scale', false);
// }
const path = readQueryVariable('path', 'websockify');
// | | | | | |
// | | | Connect | | |
// v v v v v v
status("Connecting");
// Build the websocket URL used to connect
let url;
if (vnc_url.indexOf("https:") != -1) {
url = 'wss';
} else {
url = 'ws';
}
url += '://' + host;
if(port) {
url += ':' + port;
}
url += '/' + path;
// Creating a new RFB object will start a new connection
rfb = new RFB(document.getElementById('screen'), url,
{ credentials: { password: password } });
// Add listeners to important events from the RFB module
rfb.addEventListener("connect", connectedToServer);
rfb.addEventListener("disconnect", disconnectedFromServer);
rfb.addEventListener("credentialsrequired", credentialsAreRequired);
rfb.addEventListener("desktopname", updateDesktopName);
// Set parameters that can be changed on an active connection
rfb.viewOnly = readQueryVariable('view_only', false);
rfb.scaleViewport = readQueryVariable('scale', false);
}
// render() {
// const { challenge, vnc_url } = this.props
render() {
const { challenge, vnc_url } = this.props
// return (
// <div className="">
// <style>{`
// #top_bar {
// background-color: #6e84a3;
// color: white;
// font: bold 12px Helvetica;
// padding: 6px 5px 4px 5px;
// border-bottom: 1px outset;
// }
// #status {
// text-align: center;
// }
// #sendCtrlAltDelButton {
// position: fixed;
// top: 0px;
// right: 0px;
// border: 1px outset;
// padding: 5px 5px 4px 5px;
// cursor: pointer;
// }
// #screen {
// flex: 1; /* fill remaining space */
// overflow: hidden;
// }
// `}</style>
// <div id="top_bar">
// <div id="status">Loading</div>
// <div id="sendCtrlAltDelButton">Send CtrlAltDel</div>
// </div>
// <div id="screen"></div>
// </div>
// );
// }
// }
return (
<div className="">
<style>{`
#top_bar {
background-color: #6e84a3;
color: white;
font: bold 12px Helvetica;
padding: 6px 5px 4px 5px;
border-bottom: 1px outset;
}
#status {
text-align: center;
}
#sendCtrlAltDelButton {
position: fixed;
top: 0px;
right: 0px;
border: 1px outset;
padding: 5px 5px 4px 5px;
cursor: pointer;
}
#screen {
flex: 1; /* fill remaining space */
overflow: hidden;
}
`}</style>
<div id="top_bar">
<div id="status">Loading</div>
<div id="sendCtrlAltDelButton">Send CtrlAltDel</div>
</div>
<div id="screen"></div>
</div>
);
}
}
// export default VNCDisplay;
export default VNCDisplay;

@ -192,16 +192,23 @@ class CodeEvaluateView extends Component {
<React.Fragment>
<div>{`已经过职业认证的教师可以免金币查看隐藏测试集。`}</div>
<div>{`解锁本关所有测试集需要扣除${challenge.score*5}金币,确定要解锁吗?`}</div>
<div onClick={()=>this.goToCertification()} style={{color: '#4CACFF', cursor: 'pointer', 'text-decoration': 'underline'
, 'margin-top': '12px'}}>立即认证</div>
</React.Fragment> :
`解锁本关所有测试集需要扣除${challenge.score*5}金币,确定要解锁吗?`
<React.Fragment>
<div>{`解锁本关所有测试集需要扣除${challenge.score*5}金币`}</div>
<div>{`确定要解锁吗?`}</div>
</React.Fragment>
const moreButtonsRender = () => {
return (power === 0 && user.is_teacher) ? (
<Button variant="raised" style={{ marginRight: '20px'}}
onClick={()=>this.goToCertification()} color="primary">
{ '立即认证' }
</Button>
) : ''
return ''
// ${this.props.classes.button}
// return (power === 0 && user.is_teacher) ? (
// <Button variant="raised" style={{ marginRight: '20px'}} className={``}
// onClick={()=>this.goToCertification()} color="primary">
// { '立即认证' }
// </Button>
// ) : ''
}
testSetsComponentArray.push(
<div className="-task-ces-box mb10 clearfix tabContent" key={index+'-1'}>

@ -229,6 +229,9 @@ body>div[role=dialog]>div {
/* padding-bottom: 10px; */
}
/* tpi 窗口宽度*/
#tpi-dialog>div[role=document] {
border-radius: 10px;
}
body>div[role=dialog] div[role=document] {
min-width: 400px;
}

@ -7,6 +7,7 @@ import {BrowserRouter as Router, Route, Link, Switch} from "react-router-dom";
// import "antd/dist/antd.css";
import { getImageUrl, toPath, getUrl } from 'educoder';
import '../../courses/css/Courses.css'
import axios from 'axios';

Loading…
Cancel
Save