获取分支和标签接口

This commit is contained in:
caishi 2020-06-04 18:27:19 +08:00
parent 52f559a384
commit 2007033db6
62 changed files with 5844 additions and 13016 deletions

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,13 @@
"css_prefix_text": "icon-", "css_prefix_text": "icon-",
"description": "", "description": "",
"glyphs": [ "glyphs": [
{
"icon_id": "15115208",
"name": "镜像",
"font_class": "jingxiang",
"unicode": "e773",
"unicode_decimal": 59251
},
{ {
"icon_id": "15097291", "icon_id": "15097291",
"name": "新建", "name": "新建",

View File

@ -20,6 +20,9 @@ Created by iconfont
/> />
<missing-glyph /> <missing-glyph />
<glyph glyph-name="jingxiang" unicode="&#59251;" d="M776.084211 1.347368H258.694737c-75.452632 0-134.736842 59.284211-134.736842 134.736843V734.315789C123.957895 809.768421 183.242105 869.052632 258.694737 869.052632h517.389474c75.452632 0 134.736842-59.284211 134.736842-134.736843v-598.231578c0-75.452632-59.284211-134.736842-134.736842-134.736843zM258.694737 815.157895c-43.115789 0-80.842105-37.726316-80.842105-80.842106v-598.231578c0-43.115789 37.726316-80.842105 80.842105-80.842106h517.389474c43.115789 0 80.842105 37.726316 80.842105 80.842106V734.315789c0 43.115789-37.726316 80.842105-80.842105 80.842106H258.694737zM334.147368 146.863158h194.021053v-264.084211l-97.010526 70.063158-97.010527-70.063158zM420.378947 772.042105h107.789474v-107.789473h-107.789474zM420.378947 637.305263h107.789474v-107.789474h-107.789474zM420.378947 507.957895h107.789474v-107.789474h-107.789474zM420.378947 378.610526h107.789474v-107.789473h-107.789474zM123.957895 286.989474h776.08421v-53.894737H123.957895zM274.863158 847.494737h53.894737v-609.010526h-53.894737z" horiz-adv-x="1024" />
<glyph glyph-name="xinjian1" unicode="&#59250;" d="M614.4-97.882353H301.176471c-156.611765 0-289.129412 126.494118-289.129412 289.129412V877.929412h764.988235c156.611765 0 289.129412-126.494118 289.129412-289.129412v-246.964706h-90.352941V444.235294H108.423529v-252.988235C108.423529 82.823529 192.752941-7.529412 301.176471-7.529412h313.223529v-90.352941zM108.423529 534.588235h867.388236V594.823529c0 108.423529-90.352941 192.752941-192.752941 192.752942H108.423529V534.588235z m758.964706-590.305882h-90.352941v150.588235h-144.564706v90.352941H783.058824V329.788235h90.352941v-150.588235H1024v-90.352941h-150.588235v-144.564706z" horiz-adv-x="1084" /> <glyph glyph-name="xinjian1" unicode="&#59250;" d="M614.4-97.882353H301.176471c-156.611765 0-289.129412 126.494118-289.129412 289.129412V877.929412h764.988235c156.611765 0 289.129412-126.494118 289.129412-289.129412v-246.964706h-90.352941V444.235294H108.423529v-252.988235C108.423529 82.823529 192.752941-7.529412 301.176471-7.529412h313.223529v-90.352941zM108.423529 534.588235h867.388236V594.823529c0 108.423529-90.352941 192.752941-192.752941 192.752942H108.423529V534.588235z m758.964706-590.305882h-90.352941v150.588235h-144.564706v90.352941H783.058824V329.788235h90.352941v-150.588235H1024v-90.352941h-150.588235v-144.564706z" horiz-adv-x="1084" />

Before

Width:  |  Height:  |  Size: 466 KiB

After

Width:  |  Height:  |  Size: 467 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -76,6 +76,11 @@ const InfosIndex = Loadable({
loader: () => import('./forge/users/Infos'), loader: () => import('./forge/users/Infos'),
loading: Loading, loading: Loading,
}) })
// 组织
const OrganizeIndex = Loadable({
loader: () => import('./forge/Team/Index'),
loading: Loading,
})
class App extends Component { class App extends Component {
constructor(props) { constructor(props) {
@ -247,7 +252,14 @@ class App extends Component {
<Route path="/403" component={Shixunauthority} /> <Route path="/403" component={Shixunauthority} />
<Route path="/500" component={http500} /> <Route path="/500" component={http500} />
<Route
path={"/organize"}
render={
(props) => {
return (<OrganizeIndex {...this.props} {...props} {...this.state} />)
}
}>
</Route>
{/*404*/} {/*404*/}
<Route path="/nopage" component={Shixunnopage} /> <Route path="/nopage" component={Shixunnopage} />
{/* 个人主页 */} {/* 个人主页 */}

View File

@ -100,7 +100,7 @@ export function initAxiosInterceptors(props) {
// TODO 读取到package.json中的配置 // TODO 读取到package.json中的配置
var proxy = "http://localhost:3000" var proxy = "http://localhost:3000"
// proxy = "https://pre-newweb.educoder.net" // proxy = "https://pre-newweb.educoder.net"
// proxy = "https://testforgeplus.trustie.net/" proxy = "https://testforgeplus.trustie.net/"
// 在这里使用requestMap控制避免用户通过双击等操作发出重复的请求 // 在这里使用requestMap控制避免用户通过双击等操作发出重复的请求
// 如果需要支持重复的请求考虑config里面自定义一个allowRepeat参考来控制 // 如果需要支持重复的请求考虑config里面自定义一个allowRepeat参考来控制

110
src/forge/Branch/Select.jsx Normal file
View File

@ -0,0 +1,110 @@
import React , { useState , useEffect } from 'react';
import { Popover , Input , Spin } from 'antd';
import './branch.css';
import { getBranch , getTag } from '../GetData/getData';
export default (({ projectsId , repo_id , changeBranch , branch })=>{
const [ showValue , setShowValue ] = useState(branch);
const [ inputValue , setInputValue] = useState(undefined);
const [ nav , setNav ] = useState(0);
const [ isSpin , setIsSpin ] = useState(true);
const [ flag , setFlag ] = useState(false);
const [ data , setData ] = useState(undefined);
const [ datas , setDatas ] = useState(undefined);
useEffect(()=>{
setShowValue(branch);
},[branch])
useEffect(()=>{
document.body.addEventListener('click', e => {
let name = e.target.className;
let turn = name == "ant-input OptionsInput" || name == "navli active"|| name == "navli" || name == "padding10 bor-bottom-greyE";
if(turn){
return;
}else{
setFlag(false);
}
})
})
useEffect(()=>{
getBranchs(projectsId);
},[projectsId])
async function getBranchs(id){
let result = await getBranch(id);
setData(result);
setDatas(result);
setIsSpin(false);
}
async function getTags(id){
let result = await getTag(id);
setData(result);
setDatas(result);
setIsSpin(false);
}
function changeInputValue(e){
setInputValue(e.target.value);
let filter = e.target.value ? data && data.length>0 && data.filter(item=>item.name.indexOf(e.target.value)>-1) : data;
setDatas(filter);
}
function changeNav(nav){
setNav(nav);
setIsSpin(true);
if(nav === 0){
getBranchs(projectsId);
}else{
getTags(repo_id);
}
}
function chooseitem(value){
setShowValue(value);
changeBranch(value);
}
const menu = (
<div>
<div className="padding10 bor-bottom-greyE">
<Input
placeholder="请输入分支或标签名称搜索"
autocomplete="off" className="OptionsInput" value={inputValue}
onChange={changeInputValue} style={{width:"220px"}}
/>
<ul className="navUl">
<li className={nav==0?"navli active":"navli"} onClick={()=>changeNav(0)}><i className="iconfont icon-fenzhi1 font-14 mr3"></i>分支列表</li>
<li className={nav==1?"navli active":"navli"} onClick={()=>changeNav(1)}><i className="iconfont icon-biaoqian3 font-14 mr3"></i>标签列表</li>
</ul>
</div>
<Spin spinning={isSpin}>
<ul className="OptionsUl" id="ul-btn">
{
datas && datas.length>0 ?
datas.map((item,key)=>{
return(
<li key={key} onClick={()=>chooseitem(item.name)}><a className="task-hide ulALink">{item.name}</a></li>
)
}):
<p className="listTips">暂无{inputValue}{nav === 0 ?"分支":"标签"}~</p>
}
</ul>
</Spin>
</div>
);
return(
<Popover placement="bottom" visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
<div className="branch-tagBox">
<span className="color-grey-9 mr3 ml8">{nav === 0 ?"分支":"标签"}:</span>
<a className="ant-dropdown-link">
{showValue}
</a>
<i className="showtag iconfont icon-xiajiantou font-14 color-grey-9 mr8" />
</div>
</Popover>
)
})

View File

@ -1,6 +1,6 @@
import React , { Component } from 'react'; import React , { Component } from 'react';
import { Dropdown , Icon , Input } from 'antd'; import { Dropdown , Icon , Input } from 'antd';
import { getBranch } from '../GetData/getData';
import "./branch.css" import "./branch.css"
import axios from 'axios'; import axios from 'axios';
const $ = window.$; const $ = window.$;
@ -11,7 +11,9 @@ class SelectBranch extends Component{
visible:false, visible:false,
value:undefined, value:undefined,
search:"branch", search:"branch",
tags:undefined tags:undefined,
branchsFilter:undefined,
data:undefined
} }
} }
componentDidMount() { componentDidMount() {
@ -28,6 +30,9 @@ class SelectBranch extends Component{
visible:!v, visible:!v,
value:undefined value:undefined
}) })
if(!v){
this.getBranchs();
}
return; return;
}else if (classF) { }else if (classF) {
return; return;
@ -44,6 +49,22 @@ class SelectBranch extends Component{
this.getTagList(); this.getTagList();
} }
} }
// 获取分支
getBranchs=()=>{
debugger;
const { projectsId } = this.props;
let result = getBranch(projectsId);
if(result){
this.setState({
data:result.data
})
if(result.data && result.data.length>0){
this.setState({
search:"branch"
})
}
}
}
getTagList=()=>{ getTagList=()=>{
const { repo_id } = this.props; const { repo_id } = this.props;
if(repo_id){ if(repo_id){
@ -73,6 +94,16 @@ class SelectBranch extends Component{
this.setState({ this.setState({
value:e.target.value value:e.target.value
}) })
let { branchs } = this.props;
const { tags } = this.state;
let array = branchs;
if(search === "tag" && tags.length>0){
array = tags;
}
let branchsFilter = e.target.value ? (array && array.length>0 && array.filter(item=>item.name.indexOf(e.target.value)>-1)) : array;
this.setState({
branchsFilter
})
} }
// 选择分支 // 选择分支
@ -94,15 +125,11 @@ class SelectBranch extends Component{
} }
render(){ render(){
const { visible , value , search , tags } = this.state; const { visible , value , search , tags , branchsFilter , data } = this.state;
const { branchs , branch } = this.props; const { branchs , branch } = this.props;
let array = branchs;
if(search === "tag" && tags.length>0){ console.log(data);
array = tags;
}
let branchsFilter = value ? (array && array.length>0 && array.filter(item=>item.name.indexOf(value)>-1)) : array;
const menu = ( const menu = (
<div className="branchOptions" id="m-btn" onClick={this.stopPropagations}> <div className="branchOptions" id="m-btn" onClick={this.stopPropagations}>
<div className="downobject padding10 bor-bottom-greyE"> <div className="downobject padding10 bor-bottom-greyE">
@ -114,11 +141,13 @@ class SelectBranch extends Component{
</div> </div>
<ul className="OptionsUl" id="ul-btn"> <ul className="OptionsUl" id="ul-btn">
{ {
branchsFilter && branchsFilter.map((item,key)=>{ data && data.length> 0 ? data.map((item,key)=>{
return( return(
<li key={key}><a className="task-hide ulALink" onClick={(e)=>this.changeBranchs(e,`${item.name}`)}>{item.name}</a></li> <li key={key}><a className="task-hide ulALink" onClick={(e)=>this.changeBranchs(e,`${item.name}`)}>{item.name}</a></li>
) )
}) })
:
<p className="listTips">暂无{value}{search === "tag" ?"标签":"分支"}~</p>
} }
</ul> </ul>
</div> </div>

View File

@ -44,6 +44,28 @@
line-height: 32px; line-height: 32px;
width: 100%; width: 100%;
} }
.branch-tagBox{
border:1px solid #eee;
border-radius: 3px;
height: 40px;
display: flex;
align-items: center;
cursor: pointer;
width: 240px;
}
.branch-tagBox-list .ant-popover-arrow{
display: none;
}
.branch-tagBox-list.ant-popover.ant-popover-placement-bottom{
padding-top:0px;
}
.branch-tagBox .ant-dropdown-link{
display: block;
flex:1;
}
.branch-tagBox-list .ant-popover-inner-content{
padding:0px;
}
.navUl{ .navUl{
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -55,4 +77,8 @@
} }
.navUl li.active{ .navUl li.active{
color:#5091FF; color:#5091FF;
}
.listTips{
padding:20px 0px;
text-align: center;
} }

View File

@ -0,0 +1,9 @@
import axios from 'axios';
export const getBranch = async (id)=>{
return (await axios.get(`/projects/${id}/branches.json`)).data;
}
export const getTag = async (id)=>{
return (await axios.get(`/repositories/${id}/tags.json`)).data;
}

View File

@ -1,74 +1,75 @@
import React , { Component } from 'react'; import React , { useState, useEffect } from 'react';
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { Dropdown , Menu , Icon , Tooltip } from 'antd'; import { Dropdown , Menu , Icon , Tooltip } from 'antd';
import { truncateCommitId } from '../common/util'; import { truncateCommitId } from '../common/util';
import { getBranch } from '../GetData/getData';
import './list.css' import './list.css';
import Top from './DetailTop';
class CoderRootBranch extends Component { export default ((props)=>{
constructor(porps){ const [ data , setData ] =useState(undefined);
super(porps); const { projectsId } = props.match.params;
this.state={
data:undefined useEffect(()=>{
} getBranchs(projectsId);
},[projectsId])
async function getBranchs(id){
let result = await getBranch(id);
setData(result);
} }
render(){ const list =()=>{
const { branchList } = this.props; if(data && data.length>0){
const { projectsId } = this.props.match.params; return(
const list =()=>{ <React.Fragment>
if(branchList && branchList.length>0){ <ul className="branchUl">
return( {
<React.Fragment> data.map((item,key)=>{
<ul className="branchUl"> return(
{ <li key={key}>
branchList.map((item,key)=>{ <div>
return( <Link to={`/projects/${projectsId}/coders?branch=${item.name}`} className="color-blue font-15" style={{"maxWidth":"100px"}}>{item.name}</Link>
<li key={key}> <p className="f-wrap-alignCenter mt15">
<div> <span className="mr5 commitKey" style={{marginLeft:0}}>{item.last_commit && truncateCommitId(item.last_commit.sha)}</span>
<Link to={`/projects/${projectsId}/coders?branch=${item.name}`} className="color-blue font-15" style={{"maxWidth":"100px"}}>{item.name}</Link> <span className="color-grey-3 hide-1 messages leftPoint">{item.last_commit && item.last_commit.message}</span>
<p className="f-wrap-alignCenter mt15"> <span className="color-grey-8 ml30">最后更新于{item.last_commit && item.last_commit.time_from_now}</span>
<span className="mr5 commitKey" style={{marginLeft:0}}>{item.last_commit && truncateCommitId(item.last_commit.id)}</span> </p>
<span className="color-grey-3 hide-1 messages leftPoint">{item.last_commit && item.last_commit.message}</span> </div>
<span className="color-grey-8 ml30">最后更新于{item.last_commit && item.last_commit.time_from_now}</span> <span>
</p> <Link to={`/projects/${projectsId}/merge/new`} className="mr20 color-blue mr30">创建合并请求</Link>
</div> <Dropdown overlay={menu(item.zip_url,item.tar_url)} trigger={['click']} placement="bottomRight" className="color-green-file">
<span> <a className="ant-dropdown-link">
<Link to={`/projects/${projectsId}/merge/new`} className="mr20 color-blue mr30">创建合并请求</Link> <Tooltip title={`下载分支${item.name}`}><Icon type="cloud-download" className="font-18"/></Tooltip>
<Dropdown overlay={menu(item.zip_url,item.tar_url)} trigger={['click']} placement="bottomRight" className="color-green-file"> </a>
<a className="ant-dropdown-link"> </Dropdown>
<Tooltip title={`下载分支${item.name}`}><Icon type="cloud-download" className="font-18"/></Tooltip> </span>
</a> </li>
</Dropdown> )
</span> })
</li> }
) </ul>
}) </React.Fragment>
} )
</ul>
</React.Fragment>
)
}
} }
const menu =(zip_url,tar_url)=> ( }
<Menu> const menu =(zip_url,tar_url)=> (
<Menu.Item key={'0'}><a href={zip_url}>ZIP</a></Menu.Item> <Menu>
<Menu.Item key={'1'}><a href={tar_url}>TAR.GZ</a></Menu.Item> <Menu.Item key={'0'}><a href={zip_url}>ZIP</a></Menu.Item>
</Menu> <Menu.Item key={'1'}><a href={tar_url}>TAR.GZ</a></Menu.Item>
) </Menu>
return( )
<React.Fragment> return(
<div className="main"> <React.Fragment>
<div className="branchTable"> <div className="main">
<p className="branchTitle bor-bottom-greyE">分支列表</p> <div className="branchTable">
{list()} <p className="branchTitle bor-bottom-greyE">分支列表</p>
</div> {list()}
</div> </div>
</React.Fragment> </div>
) </React.Fragment>
} )
})
}
export default CoderRootBranch;

View File

@ -2,7 +2,7 @@ import React , { Component } from 'react';
import { Spin } from 'antd'; import { Spin } from 'antd';
import { getImageUrl } from 'educoder'; import { getImageUrl } from 'educoder';
import { truncateCommitId } from '../common/util' import { truncateCommitId } from '../common/util'
import SelectBranch from '../Branch/SelectBranch'; import SelectBranch from '../Branch/Select';
import axios from 'axios'; import axios from 'axios';
import {Link} from "react-router-dom"; import {Link} from "react-router-dom";
@ -77,6 +77,7 @@ class CoderRootCommit extends Component{
render(){ render(){
const { branch , data , dataCount , limit , page , isSpin } = this.state; const { branch , data , dataCount , limit , page , isSpin } = this.state;
const { branchs , projectDetail } = this.props; const { branchs , projectDetail } = this.props;
const { projectsId } = this.props.match.params;
const title =()=>{ const title =()=>{
return( return(
<div className="f-wrap-between" style={{alignItems:"center"}}> <div className="f-wrap-between" style={{alignItems:"center"}}>
@ -98,7 +99,12 @@ class CoderRootCommit extends Component{
<React.Fragment> <React.Fragment>
<div className="main"> <div className="main">
<div className="f-wrap-between"> <div className="f-wrap-between">
<SelectBranch repo_id={projectDetail && projectDetail.repo_id} branch={branch} branchs={branchs} changeBranch={this.changeBranch}></SelectBranch> <SelectBranch
repo_id={projectDetail && projectDetail.repo_id}
projectsId={projectsId}
branch={branch}
changeBranch={this.changeBranch}
></SelectBranch>
</div> </div>
<Spin spinning={isSpin}> <Spin spinning={isSpin}>
<div className="commonBox"> <div className="commonBox">
@ -117,8 +123,8 @@ class CoderRootCommit extends Component{
</p> </p>
<p className="f-wrap-alignCenter mt15"> <p className="f-wrap-alignCenter mt15">
<Link to={`/users/${item.login}/projects`} className="show-user-link"> <Link to={`/users/${item.login}/projects`} className="show-user-link">
<img src={getImageUrl(`images/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/> {item.image_url?<img src={getImageUrl(`images/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
<label className="font-14 color-grey-6" style={{'verticalAlign':'middle'}}>{item.name}:提交于 {item.time_from_now}</label> <label className="font-14 color-grey-6" style={{'verticalAlign':'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
</Link> </Link>
</p> </p>
</div> </div>

View File

@ -4,7 +4,7 @@ import { getImageUrl } from 'educoder';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import './list.css'; import './list.css';
import SelectBranch from '../Branch/SelectBranch'; import SelectBranch from '../Branch/Select';
import CloneAddress from '../Branch/CloneAddress'; import CloneAddress from '../Branch/CloneAddress';
import RootTable from './RootTable'; import RootTable from './RootTable';
import CoderRootFileDetail from './CoderRootFileDetail'; import CoderRootFileDetail from './CoderRootFileDetail';
@ -41,7 +41,8 @@ class CoderRootDirectory extends Component{
rootList:undefined, rootList:undefined,
readOnly: true, readOnly: true,
zip_url:undefined, zip_url:undefined,
tar_url:undefined tar_url:undefined,
chooseType:undefined
} }
} }
changeAddress=(address)=>{ changeAddress=(address)=>{
@ -179,9 +180,10 @@ class CoderRootDirectory extends Component{
} }
}).then((result)=>{ }).then((result)=>{
let entries = result.data && result.data.entries let entries = result.data && result.data.entries
if(entries && entries.length > 0){ if( entries && entries.length > 0){
let { chooseType } = this.state;
// 当前返回的子目录只有一条数据,且这条数据返回的是文件类型 // 当前返回的子目录只有一条数据,且这条数据返回的是文件类型
if(entries.length === 1 && entries[0].type === "file"){ if(entries.length === 1 && entries[0].type === "file" && chooseType ==="file"){
this.setState({ this.setState({
fileDetail:entries, fileDetail:entries,
rootList:undefined, rootList:undefined,
@ -227,7 +229,10 @@ class CoderRootDirectory extends Component{
} }
// 点击跳转到子目录 // 点击跳转到子目录
goToSubRoot=(path)=>{ goToSubRoot=(path,type)=>{
this.setState({
chooseType:type
})
const { projectsId } = this.props.match.params; const { projectsId } = this.props.match.params;
this.props.history.push(`/projects/${projectsId}/coders?url=${path}`); this.props.history.push(`/projects/${projectsId}/coders?url=${path}`);
} }
@ -278,6 +283,14 @@ class CoderRootDirectory extends Component{
this.getProjectRoot( value ); this.getProjectRoot( value );
} }
} }
returnUlr=(url)=>{
this.setState({
chooseType:"dir"
})
const { projectsId } = this.props.match.params;
this.props.history.push(`/projects/${projectsId}/coders?url=${url}`);
}
render(){ render(){
const { branchLastCommit , lastCommitAuthor , rootList , branch ,filePath , fileDetail , subFileType , readMeContent, isSpin , zip_url , tar_url} = this.state; const { branchLastCommit , lastCommitAuthor , rootList , branch ,filePath , fileDetail , subFileType , readMeContent, isSpin , zip_url , tar_url} = this.state;
const { isManager , isDeveloper , projectDetail } = this.props; const { isManager , isDeveloper , projectDetail } = this.props;
@ -288,7 +301,7 @@ class CoderRootDirectory extends Component{
dataIndex: 'name', dataIndex: 'name',
width:"30%", width:"30%",
render: (text,item) => ( render: (text,item) => (
<a onClick={()=>this.goToSubRoot(item.path)} className="ml12"> <a onClick={()=>this.goToSubRoot(item.path,item.type)} className="ml12">
<i className={ item.type === "file" ? "iconfont icon-wenjia font-15 color-green-file mr5":"iconfont icon-wenjianjia1 color-green-file font-15 mr5"}></i>{text} <i className={ item.type === "file" ? "iconfont icon-wenjia font-15 color-green-file mr5":"iconfont icon-wenjianjia1 color-green-file font-15 mr5"}></i>{text}
</a> </a>
), ),
@ -350,7 +363,12 @@ class CoderRootDirectory extends Component{
<div className="main"> <div className="main">
<div className="f-wrap-between mb20"> <div className="f-wrap-between mb20">
<div className="f-wrap-alignCenter"> <div className="f-wrap-alignCenter">
<SelectBranch repo_id={projectDetail && projectDetail.repo_id} branch={branch} changeBranch={this.changeBranch} {...this.props} {...this.state}></SelectBranch> <SelectBranch
repo_id={projectDetail && projectDetail.repo_id}
projectsId={projectsId}
branch={branch}
changeBranch={this.changeBranch}
></SelectBranch>
{ {
filePath && filePath &&
@ -364,10 +382,7 @@ class CoderRootDirectory extends Component{
key === array.length-1 ? key === array.length-1 ?
<span className="color-grey-6 subFileName" key={key}>{item}</span> <span className="color-grey-6 subFileName" key={key}>{item}</span>
: :
key === 0? <a onClick={()=>this.returnUlr(`${key === 0 ? `${item}` :`${array[key-1]}/${item}`}`)} className="color-blue subFileName">{item}</a>
<Link to={`/projects/${projectsId}/coders?url=${item}`} className="color-blue subFileName" key={key}>{item}</Link>
:
<Link to={`/projects/${projectsId}/coders?url=${array[key-1]}/${item}`} className="color-blue subFileName" key={key}>{item}</Link>
} }
</React.Fragment> </React.Fragment>
) )

View File

@ -121,7 +121,7 @@ class Detail extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
isSpin: false, isSpin: true,
projectDetail: undefined, projectDetail: undefined,
isManager: false, isManager: false,
isReporter: false, isReporter: false,
@ -147,13 +147,6 @@ class Detail extends Component {
if ((prevState.match.params.projectsId !== this.props.match.params.projectsId)) { if ((prevState.match.params.projectsId !== this.props.match.params.projectsId)) {
this.getDetail(); this.getDetail();
} }
const { search } = this.props.location;
const search_c = prevState.location && prevState.location.search;
if (search && search !== search_c) {
const { projectsId } = this.props.match.params;
this.getBranch(projectsId);
}
} }
@ -177,9 +170,6 @@ class Detail extends Component {
forked_count: result.data.forked_count, forked_count: result.data.forked_count,
isSpin:false isSpin:false
}) })
if (result.data.project_id) {
this.getBranch(result.data.project_id);
}
} }
}).catch((error) => { }) }).catch((error) => { })
} }
@ -325,6 +315,13 @@ class Detail extends Component {
<Link to={`/projects/${projectDetail.forked_from_project_id}/coders`} className="color-grey-ccc">{projectDetail.fork_info.fork_form_name}</Link> <Link to={`/projects/${projectDetail.forked_from_project_id}/coders`} className="color-grey-ccc">{projectDetail.fork_info.fork_form_name}</Link>
</React.Fragment> : "" </React.Fragment> : ""
); );
const mirror = (
<React.Fragment>
<span>镜像自 </span>
<a href={projectDetail && projectDetail.mirror_url} target="_blank" style={{color:"#fff"}}>{projectDetail && projectDetail.mirror_url}</a>
</React.Fragment>
)
const common ={ const common ={
getDetail:this.getDetail getDetail:this.getDetail
} }
@ -352,12 +349,18 @@ class Detail extends Component {
</Link> </Link>
</Tooltip> : "" </Tooltip> : ""
} }
{
projectDetail && projectDetail.type && projectDetail.type === 2 ?
<Tooltip placement={'right'} title={mirror}>
<i className="iconfont icon-jingxiang font-18 fl mt6 ml10" style={{ color: "#8D90E3" }}></i>
</Tooltip>:""
}
</span> </span>
</p> </p>
<span className="df mt25"> <span className="df mt25">
{ {
projectDetail && projectDetail.type && projectDetail.type === 2 && projectDetail && projectDetail.type && projectDetail.type === 2 ?
<a className="synchronism ml30" onClick={this.synchronismMirror}>同步镜像</a> <a className="synchronism ml30" onClick={this.synchronismMirror}>同步镜像</a>:""
} }
<span className="detail_tag_btn"> <span className="detail_tag_btn">
<a className="detail_tag_btn_name" onClick={() => this.focusFunc(watched)}> <a className="detail_tag_btn_name" onClick={() => this.focusFunc(watched)}>

View File

@ -1,43 +1,42 @@
import React , { Component } from 'react'; import React , { useEffect , useState } from 'react';
import { Input , Select } from 'antd'; import { Input , Select } from 'antd';
import { getBranch } from '../GetData/getData';
const { Option } = Select; const { Option } = Select;
class Branch extends Component{ export default ((props)=>{
constructor(props){ const [ branchList , setBranchList] = useState(undefined);
super(props); const { projectsId } = props.match.params;
this.state={
userDataSource:undefined useEffect(()=>{
} getBranchs(projectsId);
},[projectsId])
async function getBranchs(id){
let result = await getBranch(id);
setBranchList(result);
} }
// 更新仓库设置
resetSetting=()=>{
}
render(){ const branchListRender = (
const { branchList } = this.props; branchList && branchList.map((item,key)=>{
const branchListRender = ( return(
branchList && branchList.map((item,key)=>{ <Option value={item.name}>{item.name}</Option>
return( )
<Option value={item.name}>{item.name}</Option> })
) )
}) return(
) <div className="normalBox">
return( <div className="normalBox-title font-16">
<div className="normalBox"> 分支列表
<div className="normalBox-title font-16">
分支列表
</div>
<p className="pl15 pt15">请选择一个默认的分支用于合并请求和提交</p>
<div className="addPanel">
<Select className="branchSelect">
{branchListRender}
</Select>
<a className="small_submitBtn ml20" onClick={this.resetSetting}>更新仓库设置</a>
</div>
</div> </div>
) <p className="pl15 pt15">请选择一个默认的分支用于合并请求和提交</p>
} <div className="addPanel">
} <Select className="branchSelect">
export default Branch; {branchListRender}
</Select>
<a className="small_submitBtn ml20" onClick={this.resetSetting}>更新仓库设置</a>
</div>
</div>
)
})

31
src/forge/Team/Index.jsx Normal file
View File

@ -0,0 +1,31 @@
import React from 'react';
import { Route, Switch } from "react-router-dom";
import { SnackbarHOC } from "educoder";
import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC";
import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC";
import Loadable from "react-loadable";
import Loading from "../../Loading";
import '../css/index.css';
const New = Loadable({
loader: () => import("./New"),
loading: Loading,
});
export default CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(
((props)=>{
return (
<Switch {...props}>
<Route
path="/organize/new"
render={(props) => {
return <New {...props} />;
}}
></Route>
</Switch>
)
})
)))

31
src/forge/Team/Index.scss Normal file
View File

@ -0,0 +1,31 @@
.teamBox{
margin:10px 0px;
border:1px solid #eee;
border-radius: 2px;
.teamBox-title{
border-bottom: 1px solid #eee;
background-color: #F1F8FF;
height: 50px;
line-height: 50px;
text-align: center;
color: #333;
font-size: 18px;
}
.teamBox-form{
padding:24px 40px;
}
.lables{
position: relative;
color:#333;
margin-bottom: 5px;
display: block;
}
.lables.must::before{
content: "*";
color: #F73030;
font-size: 18px;
position: absolute;
left: -15px;
height: 100%;
}
}

57
src/forge/Team/New.jsx Normal file
View File

@ -0,0 +1,57 @@
import React,{ forwardRef , useCallback } from 'react';
import './Index.scss';
import { Form , Input , Cascader } from "antd";
import { locData } from "../Utils/locData";
export default Form.create()(
forwardRef(({form})=>{
const { getFieldDecorator, validateFields, setFieldsValue } = form;
const helper = useCallback(
(label, name, rules, widget, isRequired = true) => (
<React.Fragment>
<span className={isRequired?"lables must":"lables"}>{label}</span>
<Form.Item>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
</Form.Item>
</React.Fragment>
),
[]
);
return(
<div className="newMain">
<div className="main">
<div className="teamBox">
<p className="teamBox-title">新建组织</p>
<Form className="teamBox-form">
{helper(
<span>组织名称<span className="color-grey-8">(组织名称应该简单明了)</span></span>,
"name",
[{ required: true, message: "请输入组织名称" }],
<Input
placeholder="请输入组织名称"
/>
)}
{helper(
'组织描述',
"desc",
[{ required: true, message: "请输入组织描述" }],
<Input.TextArea
autoSize={{ minRows: 3, maxRows: 5 }}
placeholder="请输入组织描述"
/>
)}
{helper(
'所在地区',
"area",
[],
<Cascader placeholder="请选择城市" options={locData}/>
)}
</Form>
</div>
</div>
</div>
)
})
)

5332
src/forge/Utils/locData.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -8,13 +8,14 @@ import Attachments from "../Upload/attachment";
import axios from "axios"; import axios from "axios";
import "./version.css"; import "./version.css";
import UploadImg from "../Images/upload.png"; import UploadImg from "../Images/upload.png";
import { getBranch } from '../GetData/getData';
const { Option } = AutoComplete; const { Option } = AutoComplete;
export default Form.create()( export default Form.create()(
forwardRef( forwardRef(
( (
{ form, projectDetail, branchs, match, showNotification, history }, { form, projectDetail , match, showNotification, history },
ref ref
) => { ) => {
const { getFieldDecorator, validateFields, setFieldsValue } = form; const { getFieldDecorator, validateFields, setFieldsValue } = form;
@ -25,6 +26,15 @@ export default Form.create()(
const [attachment, setAttachment] = useState(undefined); const [attachment, setAttachment] = useState(undefined);
const [options , setOptions] = useState(undefined); const [options , setOptions] = useState(undefined);
useEffect(()=>{
getBranchs(projectsId);
},[projectsId])
async function getBranchs(id){
let result = await getBranch(id);
setBranchList(result);
}
const Span = styled.span` const Span = styled.span`
margin: 0px 15px; margin: 0px 15px;
color: #bbb; color: #bbb;
@ -34,11 +44,6 @@ export default Form.create()(
const repo_id = projectDetail && projectDetail.repo_id; const repo_id = projectDetail && projectDetail.repo_id;
const { projectsId, versionId } = match.params; const { projectsId, versionId } = match.params;
useEffect(() => {
if (branchs) {
setBranchList(branchs);
}
}, [branchs]);
useEffect(() => { useEffect(() => {
if (versionId) { if (versionId) {
@ -86,6 +91,7 @@ export default Form.create()(
} }
function submit() { function submit() {
validateFields((err, value) => { validateFields((err, value) => {
if(err)return;
if (versionId) { if (versionId) {
let url = `/projects/${projectsId}/version_releases/${versionId}.json`; let url = `/projects/${projectsId}/version_releases/${versionId}.json`;
axios axios
@ -102,18 +108,17 @@ export default Form.create()(
}); });
} else { } else {
let url = `/projects/${projectsId}/version_releases.json`; let url = `/projects/${projectsId}/version_releases.json`;
axios axios.post(url, {
.post(url, { ...value,
...value, body: desc,
body: desc, attachment_ids: fileList
attachment_ids: fileList })
}) .then(result => {
.then(result => { if (result) {
if (result) { showNotification("版本发布成功!");
showNotification("版本发布成功!"); history.push(`/projects/${projectsId}/coders/version`);
history.push(`/projects/${projectsId}/coders/version`); }
} });
});
} }
}); });
} }

View File

@ -1,209 +0,0 @@
import React, { Component } from "react";
import { Form, Input, Select, Divider, Button, Checkbox, Dropdown, Menu, Spin } from 'antd';
import '../Order/order.css';
import './version.css';
import axios from 'axios';
const Option = Select.Option;
const TextArea = Input.TextArea;
class NewVersion extends Component {
constructor(props) {
super(props);
this.state = {
branch_name: "",
issue_tag_ids: "",
fixed_version_id: "",
issue_chosen: undefined,
fileList: undefined,
ischeck: undefined,
branches: undefined,
pull: undefined,
tag_name: '',
isSpin: false
}
}
componentDidMount = () => {
this.InitData();
this.getSelectList();
}
InitData = () => {
this.props.form.setFieldsValue({
...this.state
});
}
getSelectList = () => {
const { projectsId } = this.props.match.params;
const url = `/projects/${projectsId}/version_releases/new.json`;
axios.get(url).then((result) => {
if (result) {
this.setState({
branches: result.data.branches,
pull: result.data.branches[0]
})
}
}).catch((error) => {
console.log(error);
})
}
renderSelect = (list) => {
if (list && list.length > 0) {
return (
list.map((item, key) => {
return (
<Option key={key + 1} value={item.id + ""}>{item.name}</Option>
)
})
)
}
}
// 创建
handleSubmit = (draft) => {
this.setState({
isSpin: true
})
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
const { projectsId } = this.props.match.params;
const { pull, tag_name, ischeck } = this.state;
const url = `/projects/${projectsId}/version_releases.json`;
// if(values.issue_type==="普通"){
// values.issue_type="1"
// }
axios.post(url, {
...values,
tag_name: tag_name,
draft: draft,
prerelease: ischeck,
target_commitish: pull,
}).then(result => {
if (result) {
this.setState({
isSpin: false
})
this.props.history.push(`/projects/${projectsId}/version`);
}
}).catch(error => {
console.log(error);
})
} else {
this.setState({
isSpin: false
})
}
})
}
// 获取上传后的文件id数组
UploadFunc = (fileList) => {
this.setState({
fileList
})
}
RedieonChange = (e) => {
this.setState({
ischeck: e.target.checked
})
}
Preservation = () => {
alert(this.state.ischeck)
}
renderMenu = (array, id) => {
return (
<Menu>
{
array && array.length > 0 && array.map((item, key) => {
return (
<Menu.Item key={item} onClick={() => this.getOption(item)}>{item}</Menu.Item>
)
})
}
</Menu>
)
}
getOption = (name) => {
this.setState({
pull: name
})
}
changmodelname = (e) => {
this.setState({
tag_name: e.target.value
})
}
render() {
const { getFieldDecorator } = this.props.form;
const { branches, pull, tag_name, isSpin } = this.state;
return (
<div className="main">
<Form>
<h1 style={{ marginLeft: 15, marginTop: 20 }}>发布新版</h1>
<h5 style={{ marginLeft: 15 }}>发布一个特定的打包好的项目版本</h5>
<Divider />
<div style={{ display: 'flex' }}>
<Input placeholder="标签名称" style={{ width: 180, marginLeft: 15 }} value={tag_name} onChange={this.changmodelname} />
<div style={{ marginLeft: 20, marginRight: 20, lineHeight: '32px' }}>@ </div>
<Dropdown overlay={this.renderMenu(branches && branches, 'pull')} trigger={['click']} placement="bottomCenter">
<Button style={{ width: 180 }}>{pull}</Button>
</Dropdown>
</div>
<div style={{ display: 'flex' }}>
<div className="versionmilepostleft">
<h1>标题</h1>
<div>
<Form.Item>
{getFieldDecorator('name', {
rules: [{
required: true, message: '请输入标题'
}],
})(
<Input placeholder="标题" maxLength="32" />
)}
</Form.Item>
</div>
<h1>内容</h1>
<Form.Item>
{getFieldDecorator('body', {
rules: [{
required: true, message: '请输入描述内容'
}],
})(
<TextArea placeholder="添加描述内容..." style={{ 'min-height': "150px" }} />
)}
</Form.Item>
{/* <UploadComponent load={this.UploadFunc} style={{width:80,marginLeft:15}}></UploadComponent> */}
</div>
</div>
<Divider />
<div className="fr mb15">
<Checkbox onChange={this.RedieonChange}>标记为预行版<span className="ml15 color-grey-9 font-13">(此版本不适合生产使用)</span></Checkbox>
</div>
<div className="clearfix mt15" style={{ marginTop: 5 }} >
<Spin spinning={isSpin}>
<a className='topWrapper_btn_close fr' onClick={() => this.handleSubmit(true)} style={{ marginLeft: 15 }} >保存草稿</a>
<a className='topWrapper_btn fr' onClick={() => this.handleSubmit(false)} style={{ marginRight: 15 }}>发布版本</a>
</Spin>
</div>
</Form>
</div>
)
}
}
const WrappedNewVersionForm = Form.create({ name: 'NewVersionForm' })(NewVersion);
export default WrappedNewVersionForm;

View File

@ -1,207 +0,0 @@
import React , { Component } from "react";
import { Form , Input , Select,Divider,Button,Checkbox,Dropdown,Menu, Spin} from 'antd';
import {Link} from 'react-router-dom';
import UploadComponent from '../Upload/Index';
import '../Order/order.css';
import './version.css';
import axios from 'axios';
const Option = Select.Option;
const TextArea = Input.TextArea;
class NewVersion extends Component{
constructor(props){
super(props);
this.state={
branch_name:"",
issue_tag_ids:"",
fixed_version_id:"",
issue_chosen:undefined,
fileList:undefined,
ischeck:undefined,
pull:undefined,
tag_name:'',
data:undefined,
isSpin: false
}
}
componentDidMount=()=>{
this.getSelectList();
}
getSelectList=()=>{
const { projectsId,versionId} = this.props.match.params;
const url = `/projects/${projectsId}/version_releases/${versionId}/edit.json`;
axios.get(url).then((result)=>{
if(result){
this.setState({
data:result.data,
pull:result.data.target_commitish
})
}
}).catch((error)=>{
console.log(error);
})
}
//delete
deleteversion=()=>{
const { projectsId , versionId } = this.props.match.params;
this.setState({isSpin: true})
const url = `/projects/${projectsId}/version_releases/${versionId}.json`;
axios.delete(url,{ data: {
project_id: projectsId,
id:versionId
}
}).then((result)=>{
if(result){
this.setState({isSpin: false})
this.props.history.push(`/projects/${projectsId}/version`);
}
}).catch((error)=>{
console.log(error);
})
}
// 创建
handleSubmit=()=>{
this.setState({
isSpin: true
})
this.props.form.validateFieldsAndScroll((err, values) => {
if(!err){
const { projectsId , versionId } = this.props.match.params;
const { pull,ischeck } = this.state;
const url = `/projects/${projectsId}/version_releases/${versionId}.json`;
// if(values.issue_type==="普通"){
// values.issue_type="1"
// }
axios.put(url,{
...values,
tag_name:this.state.data&&this.state.data.tag_name,
draft:false,
prerelease:ischeck,
target_commitish:pull
}).then(result=>{
if(result){
this.setState({
isSpin: false
})
this.props.history.push(`/projects/${projectsId}/version`);
}
}).catch(error=>{
console.log(error);
})
}else{
this.setState({
isSpin: false
})
}
})
}
RedieonChange=(e)=>{
this.setState({
ischeck:e.target.checked
})
}
Preservation=()=>{
alert(this.state.data.tag_name)
}
renderMenu =(array,id)=>{
return(
<Menu>
{
array && array.length > 0 && array.map((item,key)=>{
return(
<Menu.Item key={item} onClick={()=>this.getOption(item)}>{item}</Menu.Item>
)
})
}
</Menu>
)
}
getOption=(name)=>{
this.setState({
pull:name
})
}
changmodelname=(e)=>{
this.setState({
tag_name:e.target.value
})
}
render(){
const { getFieldDecorator } = this.props.form;
const { projectsId } = this.props.match.params;
const {isSpin} = this.state;
return(
<div className="main">
<Form>
<h1 style={{marginLeft:15,marginTop:20}}>编辑版本</h1>
<h5 style={{marginLeft:15}}>编辑这个特定的打包好的项目版本</h5>
<Divider/>
<div style={{display:'flex',marginLeft:15}}>
{this.state.data&&this.state.data.tag_name}@{this.state.data&&this.state.data.target_commitish}
</div>
<div style={{display:'flex'}}>
<div className="versionmilepostleft">
<h1>标题</h1>
<div>
<Form.Item>
{getFieldDecorator('name', {
rules: [{
required: true, message: '请输入标题'
}],
initialValue:this.state.data&&this.state.data.name
})(
<Input placeholder="标题" maxLength="32"/>
)}
</Form.Item>
</div>
<h1>内容</h1>
<Form.Item>
{getFieldDecorator('body', {
rules: [{
required: true, message: '请输入描述内容'
}],
initialValue:this.state.data&&this.state.data.body
})(
<TextArea placeholder="添加描述内容..." style={{'min-height':"150px"}}/>
)}
</Form.Item>
{/* <UploadComponent load={this.UploadFunc} style={{width:80,marginLeft:15}}></UploadComponent> */}
</div>
</div>
<Divider/>
<div style={{textAlign:"right"}}>
<Checkbox onChange={this.RedieonChange}>标记为预行版<span className="ml15 color-grey-9 font-13">(此版本不适合生产使用)</span></Checkbox>
</div>
<div className="clearfix mt15" style={{marginTop:5}} >
<Spin spinning={isSpin}>
<a className='topWrapper_btn_delete fr' onClick={()=>this.deleteversion()} style={{marginLeft:15}}>删除发布</a>
<a className='topWrapper_btn fr' onClick={()=>this.handleSubmit()} style={{marginRight:15}}>发布版本</a>
<Link to={`/projects/${projectsId}/version`} style={{marginRight:30}} className='topWrapper_btn fr'>取消</Link>
</Spin>
</div>
</Form>
</div>
)
}
}
const WrappedNewVersionForm = Form.create({ name: 'NewVersionForm' })(NewVersion);
export default WrappedNewVersionForm;

View File

@ -1,113 +0,0 @@
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;

View File

@ -1,355 +0,0 @@
import '../katex.css';
import '../css/Courses.css';
import React, { Component } from "react";
import { ImageLayer2 } from 'educoder';
import { Button, Row, Col } from "antd";
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 RenderHtml from '../../../components/render-html';
class CommonWorkAppraise extends Component {
constructor(props) {
super(props)
this.state = {
course_name: "",
homework_name: "",
search: '',
get_next_work: undefined,
attachments: [],
revise_attachments: [],
get_next_worktype: false
}
}
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)
})
}
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()
}
get_next_works = (id) => {
let workId = this.props.match.params.workId;
let url
if (id) {
url = `/homework_commons/${workId}/get_next_work.json?work_id=${id}`;
} else {
url = `/homework_commons/${workId}/get_next_work.json?work_id=${this.props.match.params.studentWorkId}`;
}
axios.get(url).then((result) => {
this.setState({
get_next_work: result.data,
get_next_worktype: true
})
}).catch((error) => {
console.log(error)
})
}
gotoget_next_work = (id) => {
if (this.props.match.path === `/classrooms/:coursesId/common_homework/:workId/:studentWorkId/appraise`) {
this.props.history.replace(`/classrooms/${this.props.match.params.coursesId}/common_homeworks/${this.props.match.params.workId}/${id}/appraise`);
}
if (this.props.match.path === `/classrooms/:coursesId/group_homework/:workId/:studentWorkId/appraise`) {
this.props.history.replace(`/classrooms/${this.props.match.params.coursesId}/group_homework/${this.props.match.params.workId}/${id}/appraise`);
}
if (this.props.match.path === `/classrooms/:coursesId/common_homeworks/:workId/:studentWorkId/appraise`) {
this.props.history.replace(`/classrooms/${this.props.match.params.coursesId}/common_homeworks/${this.props.match.params.workId}/${id}/appraise`);
}
if (this.props.match.path === `/classrooms/:coursesId/group_homeworks/:workId/:studentWorkId/appraise`) {
this.props.history.replace(`/classrooms/${this.props.match.params.coursesId}/group_homeworks/${this.props.match.params.workId}/${id}/appraise`);
}
this.setState({
get_next_worktype: false
})
}
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() {
let { course_name, get_next_work, get_next_worktype,
attachments, project_info, work_members, is_evaluation,
description, update_user_name, commit_user_name, update_time, commit_time, author_name,
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 (
<div>
<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>
<RenderHtml className="markdown-body ml20" value={description} />
{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'}`}
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 }}
get_next_works={() => this.get_next_works()}
></CommonWorkAppraiseReply>
</div>
</WorkDetailPageHeader>
{isAdmin === true && get_next_worktype === true ? <style>
{
`
.newFooter{
display:none !important;
}
.-task-sidebar{
display:none !important;
}
.educontent{
margin-bottom: 0px !important;
}
`
}
</style> : ""}
{isAdmin === true && get_next_worktype === true ? <div className="clearfix bor-bottom-greyE edu-back-white orderingbox newshixunbottombtn">
<div className={"educontent mt5"}>
<div>
<Row>
<Col span={12} className={"mt13"}>
{get_next_work && get_next_work.work_id === null ?
<Row type="flex" justify="start">
<Col span={8}><div style={{ color: "#333333" }}>已全部评阅完</div></Col>
</Row> : <Row type="flex" justify="start">
<Col><div style={{ color: "#333333" }}>{get_next_work && get_next_work ? `下一位待评阅人员:${get_next_work && get_next_work.user_name}` : ""}</div></Col>
<Col span={4}><a className={"ml10 color-blue font-15"} onClick={() => this.get_next_works(get_next_work && get_next_work.work_id)}>跳过</a></Col>
</Row>}
</Col>
{get_next_work && get_next_work.work_id === null ? "" : <Col span={12} className={"mt8"}>
<Row type="flex" justify="end">
<Col span={4}>
<Button className={"newshixunmode"} type="primary"
onClick={() => this.gotoget_next_work(get_next_work && get_next_work.work_id)}
// loading={this.state.hometypepvisible}
>评阅</Button>
</Col>
</Row>
</Col>}
</Row>
</div>
</div>
</div> : ""}
</div>
)
}
}
export default CommonWorkAppraise;

View File

@ -1,52 +0,0 @@
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;

View File

@ -1,536 +0,0 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Route, Switch } from 'react-router-dom';
import Loadable from 'react-loadable';
import Loading from '../../../Loading';
import { WordsBtn, 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;
let category = this.state.category;
let secondName = "";
if (window.location.pathname.indexOf('group_homework') > -1) {
secondName = category.main === 1 ? 'group_homeworks' : "group_homework";
this.props.toListPage(this.props.match.params, category_id, secondName);
}
if (window.location.pathname.indexOf('common_homework') > -1) {
secondName = category.main === 1 ? 'common_homeworks' : "common_homework";
this.props.toListPage(this.props.match.params, category_id, secondName);
}
} 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;
console.log(category_id)
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 && current_user.first_category_url, name: course_name },
{ to: `/classrooms/${courseId}/${moduleEngName}/${category_id}`, name: category_name },
window.location.pathname.indexOf('appraise') == -1 ? {} : { to: `/classrooms/${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={`/classrooms/${courseId}/${moduleEngName}/${workId}/list`}>作品列表</Link>
<Link
onClick={() => this.setState({ moduleName: '作业描述' })}
className={`${childModuleName == '作业描述' ? 'active' : ''} `}
to={`/classrooms/${courseId}/${moduleEngName}/${workId}/question`}>作业描述</Link>
{view_answer == true && <Link
onClick={() => this.setState({ moduleName: '参考答案' })}
className={`${childModuleName == '参考答案' ? 'active' : ''} `}
to={`/classrooms/${courseId}/${moduleEngName}/${workId}/answer`}>参考答案</Link>}
<Link
onClick={() => this.setState({ moduleName: '设置' })}
className={`${childModuleName == '设置' ? 'active' : ''} `}
style={{ paddingLeft: this.props.isAdmin() ? '38px' : '20px' }}
to={`/classrooms/${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/classrooms/1309/homework/9300/setting */}
<Route exact path="/classrooms/:coursesId/common_homeworks/:workId/setting"
render={
(props) => (<CommonWorkSetting {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/common_homework/:workId/setting"
render={
(props) => (<CommonWorkSetting {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
{/* 作品列表 */}
<Route exact path="/classrooms/:coursesId/common_homeworks/:workId/list"
render={
(props) => (<CommonWorkList ref="commonWorkList" triggerRef={this.bindRef} {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
{/* 作品列表 */}
<Route exact path="/classrooms/:coursesId/common_homework/:workId/list"
render={
(props) => (<CommonWorkList ref="commonWorkList" triggerRef={this.bindRef} {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
{/* 作业问答 */}
<Route exact path="/classrooms/:coursesId/common_homeworks/:workId/question"
render={
(props) => (<CommonWorkQuestion {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/common_homework/:workId/question"
render={
(props) => (<CommonWorkQuestion {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/common_homeworks/:workId/answer"
render={
(props) => (<CommonWorkAnswer {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/common_homework/:workId/answer"
render={
(props) => (<CommonWorkAnswer {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homeworks/:workId/setting"
render={
(props) => (<CommonWorkSetting {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homework/:workId/setting"
render={
(props) => (<CommonWorkSetting {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
{/* 作品列表 */}
<Route exact path="/classrooms/:coursesId/group_homeworks/:workId/list"
render={
(props) => (<CommonWorkList triggerRef={this.bindRef} {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homework/:workId/list"
render={
(props) => (<CommonWorkList triggerRef={this.bindRef} {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
{/* 作业问答 */}
<Route exact path="/classrooms/:coursesId/group_homeworks/:workId/question"
render={
(props) => (<CommonWorkQuestion {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homework/:workId/question"
render={
(props) => (<CommonWorkQuestion {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homeworks/:workId/answer"
render={
(props) => (<CommonWorkAnswer {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homework/:workId/answer"
render={
(props) => (<CommonWorkAnswer {...this.props} {...props} {...this.state} {...commonHandler} />)
}
></Route>
</Switch>
</div>
</div>
</div>
)
}
}
export default (CommonWorkDetailIndex);

View File

@ -1,307 +0,0 @@
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">
{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>
{
item && item.upper_category_name &&
// <ConditionToolTip title={discussMessage.upper_category_name} condition={ discussMessage.upper_category_name.length > 22 }>
<div className="color-grey9 task-hide mt5" title={item.upper_category_name}>所属目录{item.upper_category_name}</div>
// </ConditionToolTip>
}
<p className="color-grey-9 clearfix mt10">
{ 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.uncomment_count===undefined?"":<span className="mr20 fl">{item.uncomment_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={`/classrooms/${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;

View File

@ -1,968 +0,0 @@
import React,{Component} from "react";
import { Form, Table,Tooltip,Spin, Pagination} from "antd";
import { 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.$;
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_comment) {
/**
开启了匿评的才显示此列
*/
columns.push({
width: 84,
title: <div style={{color: 'rgba(0,0,0,.85)'}}>已评数</div>,
key: 'user_comment_count',
dataIndex: 'user_comment_count',
render: (user_comment_count, record) => (
<span style={{color:'#989898', cursor: 'default'}}>
<Tooltip title={"在匿评期间评阅的作品数量"}>
{record.user_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>*/}
<div>
<a style={{color: '#4CACFF'}} id={"asdasdasdasd"}
className="font-14"
onMouseDown={(e) => that.props.toWorkDetailPage2(e, courseId, workId, record.id)}
// onClick={() => that.props.toWorkDetailPage(courseId, workId, record.id)}
>{isAdmin ? record.has_comment===true?"已评阅":'评阅':"查看"}</a>
</div>
<div>
{ isAdmin && <Tooltip placement="bottom" title={<pre>调整学生当前成绩<br/>其它历史评分将全部失效</pre>}>
<a style={{color: "#32C090"}}
className="font-14"
onClick={() => that.showModulationModal(record)}
>调分</a>
</Tooltip> }
</div>
{/* toWorkDetailPage */}
{/* /classrooms/"+courseId+"/common_homeworks/"+workId+ '/' + record.id +"/appraise */}
</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/classrooms/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,
comwbool:false
}
}
onTablePagination = (page) => {
const { search } = this.state;
this.setState({ page: page }, () => {
this.fetchList(page,search);
})
}
onSearchValue = (val) => {
this.setState({
search:val,
searchtypes:true,
loadingstate:true,
page:1
})
this.fetchList(1,val);
}
onSearchValueInput = (e) => {
this.setState({search: e.target.value})
}
componentDidMount() {
console.log("CommonWorkList 分班list 开始加载");
const { page , search } = this.state;
this.fetchList(page,search);
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 = () => {
const { page,search } = this.state;
this.fetchList(page,search);
}
// arg_teacher_comment
_getRequestParams(pages,search) {
let { arg_work_status, arg_teacher_comment, arg_course_group, order, page, arg_member_work, b_order} = this.state
page=pages?pages:page;
return {
page,
search,
work_status: arg_work_status, // [0]
course_group: arg_course_group,
teacher_comment: arg_teacher_comment.length === 0 || arg_teacher_comment.length > 1 ? '' : arg_teacher_comment[0],
order,
limit: PAGE_SIZE,
b_order: b_order,
group_id:arg_course_group,
member_work: arg_member_work
}
}
fetchData = () => {
const { page , search } = this.state;
this.fetchList(page , search );
}
fetchList = (page,search) => {
if(this.state.comwbool===true){
console.log('arg_course_group2');
console.log(this.state.arg_course_group);
return
}
this.setState({
comwbool:true,
})
//分班
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(page,search);
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: '作品列表'
}))
}
setTimeout(() => {
this.setState({
comwbool:false,
})
}, 1000)
}).catch((error)=>{
console.log(error)
this.setState({
isSpin:false,
loadingstate:false
})
setTimeout(() => {
this.setState({
comwbool:false,
})
}, 1000)
})
}
teacherCommentOptionChange = (values, isAllChecked) => {
const { search } = this.state;
this.setState({arg_teacher_comment: isAllChecked ? [] : values, page: 1}, () => {
this.fetchList(1,search)
})
}
statusOptionChange = (values, isAllChecked) => {
const { search } = this.state;
this.setState({arg_work_status: isAllChecked ? [] : values, page: 1}, () => {
this.fetchList(1,search)
})
}
courseGroupOptionChange = (values, isAllChecked) => {
const { search } = this.state;
this.setState({arg_course_group: isAllChecked ? [] : values, page: 1}, () => {
this.fetchList(1,search);
})
}
memberWorkChange = (values, isAllChecked) => {
const { search } = this.state;
this.setState({arg_member_work: isAllChecked ? '' : values[0], page: 1}, () => {
this.fetchList(1,search);
})
}
funorder = (order, b_order) => {
const { page , search } = this.state;
this.setState({
order: order
,
b_order: b_order
}, () => {
this.fetchList(page,search);
})
}
doWhenSuccess = () => {
const { page , search } = this.state;
this.fetchList(page,search);
}
// --------------调分
showModulationModal = (item) => {
this.modulationItem = item;
this.setState({ modulationModalVisible: true })
}
cancelModulationModel = () => {
this.setState({ modulationModalVisible: false })
}
saveModulationModal = (value, num) => {
const item = this.modulationItem
const { page , search } = this.state;
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(page,search);
}
})
.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,has_comment,
late_penalty, absence_penalty, appeal_penalty,user_comment_count
, 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,user_comment_count,
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 comwbool={this.state.comwbool} options={options_teacher_comment} label={'你的评阅:'} onChange={this.teacherCommentOptionChange}></CheckAllGroup>
<CheckAllGroup comwbool={this.state.comwbool} options={options_status} label={'作品状态:'} onChange={this.statusOptionChange}></CheckAllGroup>
{isGroup && <CheckAllGroup comwbool={this.state.comwbool} options={options_member_work} label={'组内角色:'} onChange={this.memberWorkChange}></CheckAllGroup>}
{options_course_group.length > 1 && <CheckAllGroup comwbool={this.state.comwbool} 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;

View File

@ -1,135 +0,0 @@
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/classrooms/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={"/classrooms/"+courseId} className="color-grey-6">{course_name}</Link></WordsBtn>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<WordsBtn style="grey" className="fl"> <Link to={"/classrooms/"+courseId+"/graduation"} className="color-grey-6">毕设任务</Link></WordsBtn>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<span>任务详情</span>
</p>
<div style={{ width:'100%',height:'75px'}} >
<p className=" fl color-black mt25 summaryname">
<Link to={"/classrooms/"+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={"/classrooms/"+courseId+"/graduation/graduation_tasks/"+category_id+"/"+task_Id+"/list"}>作品列表</Link>
<Link to={"/classrooms/"+courseId+"/graduation/graduation_tasks/"+category_id+"/"+task_Id+"/questions"}>作业描述</Link>
<Link to={"/classrooms/"+courseId+"/graduation/graduation_tasks/"+category_id+"/"+task_Id+"/questions"}>参考答案</Link>
<Link
style={{paddingLeft:'38px'}}
to={"/classrooms/"+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={"/classrooms/"+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;

View File

@ -1,775 +0,0 @@
import React, { Component } from "react";
import { Form, Input, Button, Checkbox, Upload, Icon, 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 = "classrooms/" + 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(`/classrooms/${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(`/classrooms/${coursesId}/${moduleName}/${workId}/${response.data.work_id}/appraise`)
}
}
}).catch((error) => {
console.log(error)
})
}
}
handleSelectChange = (value) => {
console.log(value);
this.props.form.setFieldsValue({
note: `Hi, ${value === 'male' ? 'man' : 'lady'}!`,
});
}
goback = () => {
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) => {
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: '是否确认删除?',
ModalSave: "",
ModalCancel: ""
})
}
deleteAttachment = (file) => {
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
axios.delete(url, {
})
.then((response) => {
if (response.data) {
if (response.data.status === 0) {
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 workId = this.props.match.params.workId;
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])
}
this.setState({
task_status: checkedValues,
selectmemberslist: _selectmemberslist
})
}
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
action: `${getUploadActionUrl()}`,
onChange: this.handleChange,
onRemove: this.onAttachmentRemove,
beforeUpload: (file) => {
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;
},
};
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">&gt;</span>
<WordsBtn style="grey" className="fl"> <Link to={`/classrooms/${courseId}/${moduleName}/${workId}`} className="color-grey-6">{moduleCHName}</Link></WordsBtn>
<span className="color-grey-9 fl ml3 mr3">&gt;</span>
<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={{ 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;

View File

@ -1,110 +0,0 @@
import React, { Component } from "react";
import { on, off } from 'educoder';
import axios from 'axios';
import '../css/Courses.css'
import CommonReply from '../common/comments/CommonReply.js'
import RenderHtml from "../../../components/render-html";
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() {
let { description
, homework_id, attachments, group_info = {}
} = this.state;
let courseId = this.props.match.params.coursesId;
const isGroup = this.props.isGroup()
return (
<React.Fragment>
{/* 内容区 */}
<div className="padding40 memoContent new_li">
<RenderHtml value={description} className="mb10" />
{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;

File diff suppressed because it is too large Load Diff

View File

@ -1,186 +0,0 @@
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", "overflowY": "auto", "overflowX": '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;

View File

@ -1,199 +0,0 @@
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/classrooms/1309/homework/9300/setting */}
<Route exact path="/classrooms/:coursesId/common_homeworks/:workId/setting"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/common_homework/:workId/setting"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 作品列表 */}
<Route exact path="/classrooms/:coursesId/common_homeworks/:workId/list"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 作品列表 */}
<Route exact path="/classrooms/:coursesId/common_homework/:workId/list"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 作业问答 */}
<Route exact path="/classrooms/:coursesId/common_homeworks/:workId/question"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/common_homework/:workId/question"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/common_homeworks/:workId/answer"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/common_homework/:workId/answer"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 评阅 */}
<Route exact path="/classrooms/:coursesId/common_homeworks/:workId/:studentWorkId/appraise"
render={
(props) => (<CommonWorkAppraise {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/common_homework/:workId/:studentWorkId/appraise"
render={
(props) => (<CommonWorkAppraise {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 提交作品 */}
<Route exact path="/classrooms/:coursesId/common_homeworks/:workId/post"
render={
(props) => (<CommonWorkPost {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/common_homework/:workId/post"
render={
(props) => (<CommonWorkPost {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/common_homeworks/:workId/:studentWorkId/post_edit"
render={
(props) => (<CommonWorkPost {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/common_homework/:workId/:studentWorkId/post_edit"
render={
(props) => (<CommonWorkPost {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 新建 */}
{/* http://localhost:3007/classrooms/1309/common_homeworks/9299/edit/1 */}
<Route exact path="/classrooms/:coursesId/common_homeworks/:workId/:pageType"
render={
(props) => (<NewWork {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/common_homework/:workId/:pageType"
render={
(props) => (<NewWork {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/common_homeworks/:categroy_id/new"
render={
(props) => (<NewWork {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/common_homework/:categroy_id/new"
render={
(props) => (<NewWork {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 作业列表 */}
<Route path="/classrooms/:coursesId/common_homeworks"
render={
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/classrooms/:coursesId/common_homework"
render={
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
}
></Route>
{/* --------------------------------------------------------------------- */}
</Switch>
</div>
)
}
}
export default RouteHOC() (CNotificationHOC() (SnackbarHOC() ( CoursesWorkIndex) ));

View File

@ -1,191 +0,0 @@
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="/classrooms/:coursesId/group_homeworks/:workId/setting"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homework/:workId/setting"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 作品列表 */}
<Route exact path="/classrooms/:coursesId/group_homeworks/:workId/list"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homework/:workId/list"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 作业问答 */}
<Route exact path="/classrooms/:coursesId/group_homeworks/:workId/question"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homework/:workId/question"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 参考答案 */}
<Route exact path="/classrooms/:coursesId/group_homeworks/:workId/answer"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homework/:workId/answer"
render={
(props) => (<CommonWorkDetailIndex {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 评阅 */}
<Route exact path="/classrooms/:coursesId/group_homeworks/:workId/:studentWorkId/appraise"
render={
(props) => (<CommonWorkAppraise {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homework/:workId/:studentWorkId/appraise"
render={
(props) => (<CommonWorkAppraise {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homeworks/:workId/post"
render={
(props) => (<CommonWorkPost {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homework/:workId/post"
render={
(props) => (<CommonWorkPost {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homeworks/:workId/:studentWorkId/post_edit"
render={
(props) => (<CommonWorkPost {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homework/:workId/:studentWorkId/post_edit"
render={
(props) => (<CommonWorkPost {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 新建 */}
{/* http://localhost:3007/classrooms/1309/group_homeworks/9299/edit/1 */}
<Route exact path="/classrooms/:coursesId/group_homeworks/:workId/:pageType"
render={
(props) => (<NewWork {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homework/:workId/:pageType"
render={
(props) => (<NewWork {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homeworks/:categroy_id/new"
render={
(props) => (<NewWork {...this.props} {...props} {...this.state} />)
}
></Route>
<Route exact path="/classrooms/:coursesId/group_homework/:categroy_id/new"
render={
(props) => (<NewWork {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 作业列表 */}
<Route path="/classrooms/:coursesId/group_homeworks"
render={
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
}
></Route>
{/* 作业列表 */}
<Route path="/classrooms/:coursesId/group_homework"
render={
(props) => (<ListPageIndex {...this.props} {...props} {...this.state} />)
}
></Route>
</Switch>
</div>
)
}
}
export default RouteHOC() (CNotificationHOC() (SnackbarHOC() ( CoursesWorkIndex) ));

View File

@ -1,233 +0,0 @@
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) => {
let newcategory = undefined;
if (this.props.match.path === "/classrooms/:coursesId/common_homework/:workId/:pageType" || this.props.match.path === "/classrooms/:coursesId/group_homework/:workId/:pageType") {
newcategory = this.props.match.params.workId
}
const isGroup = this.props.isGroup()
let url = ""
if (newcategory) {
url = `/courses/${courseId}/homework_commons/new.json?type=${isGroup ? 3 : 1}&category=${newcategory}`;
} else {
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) => {
let newcategory = undefined;
if (this.props.match.path === "/classrooms/:coursesId/common_homework/:workId/:pageType" || this.props.match.path === "/classrooms/:coursesId/group_homework/:workId/:pageType") {
newcategory = this.props.match.params.workId
}
let url = ""
if (newcategory) {
url = `/homework_commons/${workId}/edit.json?category=${newcategory}`;
} else {
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`
if (this.props.match.path === "/classrooms/:coursesId/common_homework/:workId/:pageType" || this.props.match.path === "/classrooms/:coursesId/group_homework/:workId/:pageType") {
params.category = this.props.match.params.workId
}
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: `/classrooms/${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 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;

View File

@ -1,555 +0,0 @@
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;

View File

@ -1,280 +0,0 @@
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,
modallate_time: undefined,
immediatelyopen: false,
starttimeslate_time: 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",
immediatelyopen: true,
modallate_time: showdatatypes ? this.state.starttimeslate_time : undefined,
})
}
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,
modallate_time: undefined,
immediatelyopen: false
})
}
homeworkstartend = (arg_group_ids, endtime) => {
if (this.usingCheckBeforePost && this.props.checkBeforePost) {
const goOn = this.props.checkBeforePost();
if (!goOn) {
this.homeworkhide();
return;
}
}
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
})
}
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.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,
starttimeslate_time: response.data.late_time === undefined || response.data.late_time === null || response.data.late_time === "" ? undefined : response.data.late_time,
})
this.showDialog(response.data.course_groups)
})
.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}
immediatelyopen={this.state.immediatelyopen}
modallate_time={this.state.starttimeslate_time}
/> : ""}
{showActionButton && <a className="color-grey-9" onClick={this.homeworkstart}>{showdatatypes ? "立即发布" : "立即截止"}</a>}
</div>
)
}
}
export default PublishRightnow;

View File

@ -1,26 +0,0 @@
// 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

View File

@ -1,393 +0,0 @@
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 = () => {
const { checkBoxValues } = this.state;
const { object_type,category_id } = 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,
"category":category_id
}
)
.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;

View File

@ -1,236 +0,0 @@
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||window.location.pathname.indexOf('group_homework') != -1
}
getModuleName = (isChinese) => {
const isGroup = this.isGroup()
if (isChinese) {
let chName = isGroup ? '分组作业' : '普通作业'
return chName;
}
if(window.location.pathname.indexOf('group_homeworks') != -1){
const secondName ='group_homeworks';
return secondName;
}
if(window.location.pathname.indexOf('group_homework') != -1){
const secondName ='group_homework';
return secondName;
}
if(window.location.pathname.indexOf('common_homeworks') != -1){
const secondName ='common_homeworks';
return secondName;
}
if(window.location.pathname.indexOf('common_homework') != -1){
const secondName ='common_homework';
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(`/classrooms/${courseId}/boards/${workId}/messages/${topicId}`)
} else {
this.props.history.push(`/classrooms/${_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(`/classrooms/${courseId}/${secondName}/${_workId || workId}/edit`)
} else {
this.props.history.push(`/classrooms/${_courseId}/${secondName}/${_workId}/edit`)
}
}
toWorkDetailPage = (_courseId, _workId, _studentWorkId) => {
let secondName;
//= this.getModuleName()
if(window.location.pathname.indexOf('group_homeworks') != -1||window.location.pathname.indexOf('group_homework') != -1){
secondName ='group_homeworks';
}
if(window.location.pathname.indexOf('common_homeworks') != -1||window.location.pathname.indexOf('common_homework') != -1){
secondName ='common_homeworks';
}
if (typeof _courseId == "object") {
const workId = _courseId.workId
const courseId = _courseId.coursesId
const studentWorkId = _courseId.studentWorkId
window.open(`/classrooms/${courseId}/${secondName}/${_workId || workId}/${_studentWorkId || studentWorkId}/appraise`);
} else {
window.open(`/classrooms/${_courseId}/${secondName}/${_workId}/${_studentWorkId}/appraise`);
}
}
toWorkDetailPage2 = (e, _courseId, _workId, _studentWorkId) => {
console.log("鼠标中键点击了")
console.log(_studentWorkId)
let secondName;
//= this.getModuleName()
if(window.location.pathname.indexOf('group_homeworks') != -1||window.location.pathname.indexOf('group_homework') != -1){
secondName ='group_homeworks';
}
if(window.location.pathname.indexOf('common_homeworks') != -1||window.location.pathname.indexOf('common_homework') != -1){
secondName ='common_homeworks';
}
if (typeof _courseId == "object") {
const workId = _courseId.workId
const courseId = _courseId.coursesId
const studentWorkId = _courseId.studentWorkId
window.open(`/classrooms/${courseId}/${secondName}/${_workId || workId}/${_studentWorkId || studentWorkId}/appraise`);
} else {
window.open(`/classrooms/${_courseId}/${secondName}/${_workId}/${_studentWorkId}/appraise`);
}
}
toNewPage = (courseId) => {
const secondName = this.getModuleName()
this.props.history.push(`/classrooms/${courseId.coursesId}/${secondName}/${courseId.category_id}/new`)
}
toListPage = (_courseId, _workId,_subName) => {
// _subName仅分组和普通作业会传值因为category_id是主目录还是子目录需要根据接口传的category.main判断
const secondName = this.getModuleName();
if (typeof _courseId == "object") {
const workId = _courseId.workId
const courseId = _courseId.coursesId
this.props.history.push(`/classrooms/${courseId}/${_subName || secondName}/${_workId || workId}`)
} else {
this.props.history.push(`/classrooms/${_courseId}/${_subName || 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(`/classrooms/${courseId}/${secondName}/${_workId || workId}/${isEdit? `${_studentWorkId || studentWorkId}/post_edit` : 'post'}`)
} else {
this.props.history.push(`/classrooms/${_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(`/classrooms/${courseId}/${secondName}/${_workId || workId}/list`)
} else {
this.props.history.push(`/classrooms/${_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(`/classrooms/${courseId}/${secondName}/${workId}/answer`)
} else {
this.props.history.push(`/classrooms/${_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(`/classrooms/${courseId}/${secondName}/${workId}/question`)
} else {
this.props.history.push(`/classrooms/${_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(`/classrooms/${courseId}/${secondName}/${_workId || workId}/setting`)
} else {
this.props.history.push(`/classrooms/${_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>
)
}
}
}
}

View File

@ -1,22 +0,0 @@
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
}

View File

@ -1,197 +0,0 @@
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;

View File

@ -1,172 +0,0 @@
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&&current_user.first_category_url, name: course_name},
{ to: `/classrooms/${courseId}/${moduleEngName}/${category_id}`, name: category_name },
window.location.pathname.indexOf('appraise') == -1 ? { } : { to: `/classrooms/${courseId}/${moduleEngName}/${workId}/list`, name: '作业详情' },
// 1. 与上一条联动当匿评他人作品时TA人作品的作者真实姓名切换为“匿名”
window.location.pathname.indexOf('appraise') == -1 ? { name: '作业详情' } : { name: author_name },
// window.location.pathname.indexOf('appraise') == -1 ? { } : { to: `/classrooms/${courseId}/${moduleEngName}/${workId}/list`, name: '作品列表' },
// { name: childModuleName }
]}></CBreadcrumb>
<div className="clearfix mt20 mb20" >
<span className=" fl color-black summaryname">
{homework_name}
{/* <Link to={"/classrooms/"+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={`/classrooms/${courseId}/${moduleEngName}/${workId}/list`}>作品列表</Link>
<Link
className={`${childModuleName == '作业描述' ? 'active' : '' } `}
to={`/classrooms/${courseId}/${moduleEngName}/${workId}/question`}>作业描述</Link>
{view_answer == true && <Link
className={`${childModuleName == '参考答案' ? 'active' : '' } `}
to={`/classrooms/${courseId}/${moduleEngName}/${workId}/answer`}>参考答案</Link>}
<Link
className={`${childModuleName == '设置' ? 'active' : '' } `}
style={{paddingLeft:this.props.isAdmin()?'38px':'20px'}}
to={`/classrooms/${courseId}/${moduleEngName}/${workId}/setting`}>{this.props.isAdmin()?"设置":"得分规则"}</Link>
{ this.props.tabRightComponents }
</div>
</div> }
{/* 内容区 */}
{this.props.children}
</div>
</div>
</div>
</React.Fragment>
)
}
}
export default WorkDetailPageHeader;

View File

@ -1,646 +0,0 @@
import React, { Component } from "react";
import { Input, Checkbox, Menu, Pagination, Spin } from "antd";
import UseBank from './UseBank'
import '../css/members.css'
import '../css/busyWork.css'
import CommonWorkItem from './CommonWorkItem'
import PublishRightnow from './PublishRightnow'
import ConnectProject from './ConnectProject'
import { WordsBtn, on, off, trigger } from 'educoder'
import Modals from '../../modals/Modals'
import NoneData from "../coursesPublic/NoneData"
import Titlesearchsection from '../common/titleSearch/TitleSearchSection';
import { RouteHOC } from './common'
import axios from 'axios';
import _ from 'lodash'
// const Search = Input.Search;
// const map={1:"普通作业",2:"",3:"分组作业"}
// const COMMON_WORK = 1
// const COMMON_WORK = 2
class commonWork extends Component {
constructor(props) {
super(props);
this.state = {
modalsType: "",
modalsTopval: "",
modalsBottomval: "",
modalCancel: "",
mainList: undefined,
selectedKeys: 'all',
order: "",
page: 1,
search: "",
totalCount: 0,
checkAll: false,
checkBoxValues: [],
isSpin: false,
category_id: undefined,
course_module: []
}
}
//输入搜索条件
inputStudent = (e) => {
this.setState({
search: e.target.value,
})
}
//搜索查询
searchStudent = () => {
let { category_id, search, order } = this.state;
this.getList(1, search, order, category_id);
}
openConnectionProject = (work) => {
this.refs['connectProject'].openConnectionProject(work)
}
// 新建
createCommonWork = (type) => {
this.props.toNewPage(this.props.match.params)
}
cancelDelClasses = () => {
this.setState({
modalsType: false,
modalsTopval: "",
modalsBottomval: "",
modalCancel: false
})
}
sureDelClasses() {
}
componentDidUpdate(prevProps, prevState) {
if (prevProps.coursesidtype != this.props.coursesidtype || prevProps.match.params.category_id != this.props.match.params.category_id) {
this.setState({
page: 1
})
if (this.props.match.path === "/classrooms/:coursesId/common_homeworks/:category_id" || this.props.match.path === "/classrooms/:coursesId/common_homework/:category_id" ||
this.props.match.path === "/classrooms/:coursesId/group_homeworks/:category_id" || this.props.match.path === "/classrooms/:coursesId/group_homework/:category_id"
) {
if (this.props.coursesidtype === "node" && this.props.match.path === "/classrooms/:coursesId/common_homeworks/:category_id" ||
this.props.coursesidtype === "node" && this.props.match.path === "/classrooms/:coursesId/group_homeworks/:category_id"
) {
this.clearSelection()
this.setState({ selectedKeys: 'all', order: '' }, () => {
this._getList()
})
}
if (this.props.coursesidtype === "child" && this.props.match.path === "/classrooms/:coursesId/common_homework/:category_id" ||
this.props.coursesidtype === "child" && this.props.match.path === "/classrooms/:coursesId/group_homework/:category_id"
) {
this.clearSelection()
this.setState({ selectedKeys: 'all', order: '' }, () => {
this._getList(this.props.match.params.category_id)
})
}
}
}
}
_getList = (id) => {
this.setState({
isSpin: true,
category_id: id
})
let { page, search, order } = this.state;
this.getList(page, search, order, id);
}
componentDidMount() {
if (this.props.match.path === "/classrooms/:coursesId/common_homeworks/:category_id" || this.props.match.path === "/classrooms/:coursesId/group_homeworks/:category_id") {
this._getList()
}
if (this.props.match.path === "/classrooms/:coursesId/common_homework/:category_id" || this.props.match.path === "/classrooms/:coursesId/group_homework/:category_id") {
this._getList(this.props.match.params.category_id)
}
on('updateNavSuccess', this.updateNavSuccess)
}
componentWillUnmount() {
off('updateNavSuccess', this.updateNavSuccess)
}
updateNavSuccess = () => {
if (this.props.match.path === "/classrooms/:coursesId/common_homeworks/:category_id" || this.props.match.path === "/classrooms/:coursesId/group_homeworks/:category_id") {
this._getList()
}
if (this.props.match.path === "/classrooms/:coursesId/common_homework/:category_id" || this.props.match.path === "/classrooms/:coursesId/group_homework/:category_id") {
this._getList(this.props.match.params.category_id)
}
}
useBankSuccess = (checkBoxValues, newWorkIdArray) => {
this.setState({
page: 1,
checkBoxValues: newWorkIdArray
}, () => {
this.refs['publishModalRef'].open()
})
let { search, order, category_id } = this.state;
this.getList(1, search, order, category_id);
}
getList = (page, search, order, category_id) => {
this.setState({
isSpin: true
})
let id = this.props.match.params.coursesId;
let workType = this.props.getModuleType()
let url = "/courses/" + id + "/homework_commons.json?type=" + workType + "&page=" + page;
if (order != "") {
url += "&order=" + order;
}
if (search != "") {
url += "&search=" + search;
}
if (category_id) {
url += "&category=" + category_id;
}
axios.get(encodeURI(url)).then((result) => {
if (result.status == 200) {
this.setState({
mainList: result.data,
totalCount: result.data.task_count,
isSpin: false,
page: page,
...result.data
})
this.getdatas(result.data.main_category_id)
}
}).catch((error) => {
this.setState({
isSpin: false
})
})
}
getdatas = (main_category_id) => {
let newcourse_module = []
let urls = `/course_modules/${main_category_id}.json`
axios.get(encodeURI(urls)).then((result) => {
if (result.status == 200) {
newcourse_module.push({ name: result.data.course_module.module_name, id: result.data.course_module.id })
if (result.data.course_module.course_second_categories.length > 0) {
result.data.course_module.course_second_categories.map((item, key) => {
newcourse_module.push(item)
})
}
this.setState({
course_module: newcourse_module
})
}
}).catch((error) => {
this.setState({
isSpin: false
})
})
}
//筛选条件
selectedStatus = (e) => {
this.clearSelection()
this.setState({
order: e.key === "all" ? "" : e.key,
selectedKeys: e.key,
page: 1,
isSpin: true,
checkBoxValues: [],
checkAll: false
})
let { search, category_id } = this.state;
this.getList(1, search, e.key === "all" ? "" : e.key, category_id);
}
onPageChange = (pageNumber) => {
let { search, order, category_id, checkAll } = this.state;
if (checkAll === true) {
this.setState({
page: pageNumber,
checkBoxValues: [],
checkAll: false
})
} else {
this.setState({
page: pageNumber,
checkBoxValues: []
})
}
this.getList(pageNumber, search, order, category_id);
}
// 全选和反选
changeAll = (e) => {
this.setState({
checkAll: e.target.checked
})
const valueId = this.state.mainList.homeworks.map(item => {
return item.homework_id
})
if (e.target.checked) {
const concated = this.state.checkBoxValues.concat(valueId);
const sortedUniqed = _.uniq(concated)
this.setState({
checkBoxValues: sortedUniqed
})
} else {
this.setState({
checkBoxValues: _.difference(this.state.checkBoxValues, valueId)
})
}
}
onChangeSelect = (checkedValues) => {
this.setState({
checkBoxValues: checkedValues,
checkAll: checkedValues.length == this.state.mainList.homeworks.length
})
}
onWorkDelete = () => {
const { checkBoxValues, category_id } = this.state;
const len = checkBoxValues.length;
if (len == 0) {
this.props.showNotification('请先选择要删除的作业')
return;
}
this.props.confirm({
// content: `确认要删除所选的${len}个作业吗?`,
content: <div>
<div>已提交作品将全部被删除不可恢复</div>
<div>是否确认删除?</div>
</div>,
onOk: () => {
let coursesId = this.props.match.params.coursesId;
const url = `/courses/${coursesId}/homework_commons/multi_destroy.json`
axios.post(url, {
homework_ids: checkBoxValues,
all_check: 0,
// category:category_id
// group_ids
}).then((response) => {
if (response.data.status == 0) {
this.props.showNotification('删除成功')
this.clearSelection()
let { search, order } = this.state;
this.getList(1, search, order, category_id);
this.props.updataleftNavfun()
}
}).catch((error) => {
console.log(error)
})
}
})
}
clearSelection = () => {
this.setState({ checkBoxValues: [], checkAll: false })
}
//
onSetPublic = () => {
const { checkBoxValues, category_id } = this.state;
const len = checkBoxValues.length;
if (len == 0) {
this.props.showNotification('请先选择要公开的作业')
return;
}
this.props.confirm({
content: <div>
<div>设为公开后非课堂成员也可以访问查看</div>
<div>是否确认设为公开</div>
</div>,
onOk: () => {
let coursesId = this.props.match.params.coursesId;
const url = `/courses/${coursesId}/homework_commons/set_public.json`
axios.post(url, {
homework_ids: checkBoxValues,
all_check: 0
}).then((response) => {
if (response.data.status == 0) {
this.props.showNotification('设为公开操作成功')
let { search, order, page } = this.state;
this.getList(page, search, order, category_id);
}
}).catch((error) => {
console.log(error)
})
}
})
}
doWhenSuccess = () => {
let { search, order, page, category_id } = this.state;
this.getList(page, search, order, category_id);
this.setState({
checkBoxValues: []
})
}
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.onChangeSelect(checkBoxValues)
}
addToBank = () => {
const { checkBoxValues, category_id } = this.state;
const len = checkBoxValues.length;
if (len == 0) {
this.props.showNotification('请先选择要加入题库的作业')
return;
}
const coursesId = this.props.match.params.coursesId
const url = `/courses/${coursesId}/homework_commons/add_to_homework_bank.json`
axios.post(url, {
homework_ids: checkBoxValues,
all_check: 0
}).then((response) => {
if (response.data.status == 0) {
this.props.showNotification('加入成功')
let { search, order } = this.state;
this.getList(1, search, order, category_id);
}
}).catch((error) => {
console.log(error)
})
}
connectSuccess = () => {
let { page, search, order, category_id } = this.state;
this.getList(page, search, order, category_id);
}
cancelConnectionProject = (work) => {
let workId = this.props.match.params.workId;
let courseId = this.props.match.params.coursesId;
let { page, search, order, category_id } = this.state;
const url = `/homework_commons/${work.homework_id}/student_works/cancel_relate_project.json`
axios.get(url).then((response) => {
if (response.data.status == 0) {
this.getList(page, search, order, category_id);
this.props.showNotification('取消关联成功')
}
}).catch((error) => {
console.log(error)
})
}
addDir = (id) => {
if (!id) {
trigger('addcommon_homeworks', parseInt(this.props.match.params.category_id))
} else {
let data = { id: parseInt(id), name: this.state.category_name }
trigger('editcommon_homeworks', data)
}
}
newaddDir = () => {
trigger('addcommon_homeworks', parseInt(this.state.main_category_id))
}
moveTo = (item) => {
const len = this.state.checkBoxValues.length
if (len == 0) {
this.props.showNotification('请先在列表中选择要移动的作业')
return;
}
const checkBoxValues = this.state.checkBoxValues;
const coursesId = this.props.match.params.coursesId;
const category_id = this.state.category_id;
const url = `/courses/${coursesId}/homework_commons/move_to_category.json`
axios.post(url, {
homework_ids: checkBoxValues,
new_category_id: item.id,
category_id: !category_id ? undefined : category_id
})
.then((response) => {
if (response.data.status == 0) {
console.log('--- 成功')
this.props.showNotification('作业移动成功')
this.props.updataleftNavfun()
this.setState({
checkBoxValues: []
})
this.updateNavSuccess()
}
})
.catch(function (error) {
console.log(error);
});
}
render() {
let {
search,
page,
modalsType,
modalsTopval,
modalsBottomval,
mainList,
totalCount,
checkAll,
checkBoxValues,
course_module,
task_count,
published_count,
unpublished_count,
main_category_name,
category_name,
category_id
} = this.state;
const { coursedata } = this.props;
if (!coursedata) {
return ''
}
let workType = this.props.getModuleType()
const moduleChineseName = this.props.getModuleName(true)
const { course_public } = coursedata;
const isGroup = this.props.isGroup()
const isAdmin = this.props.isAdmin()
const bid = this.props.match.params.category_id
return (
<div>
{/* <div className="edu-back-white">
<p className="clearfix padding30 bor-bottom-greyE">
<span className="font-18 fl color-dark-21">{moduleChineseName}</span>
</p>
<div className="clearfix pl30 pr30">
<div className="fl mt6 task_menu_ul">
<Menu mode="horizontal" defaultSelectedKeys="all" onClick={this.selectedStatus}>
<Menu.Item key="all">全部</Menu.Item>
{isAdmin && <Menu.Item key="0">未发布</Menu.Item>}
<Menu.Item key="1">提交中</Menu.Item>
<Menu.Item key="2">补交中</Menu.Item>
<Menu.Item key="3">匿评中</Menu.Item>
<Menu.Item key="4">申诉中</Menu.Item>
<Menu.Item key="5">评阅中</Menu.Item>
</Menu>
</div>
<div className="fr mt16 mb16 searchView">
<Search
value={search}
placeholder="请输入姓名进行搜索"
onInput={this.inputStudent}
onSearch={this.searchStudent}
></Search>
</div>
</div>
</div> */}
<ConnectProject ref="connectProject" {...this.props} connectSuccess={this.connectSuccess}></ConnectProject>
<Titlesearchsection
title={!category_id ? main_category_name : category_name}
searchValue={search}
// searchtype={this.props.isAdmin||this.props.isStudent ?true:false}
onInputSearchChange={this.inputStudent}
onPressEnter={this.searchStudent}
allowClearonChange={this.inputStudent}
firstRowRight={
<React.Fragment>
{isAdmin && <WordsBtn style="blue" className="fr" onClick={() => this.createCommonWork(1)}>新建</WordsBtn>}
{isAdmin && <li className="fr">
<UseBank {...this.props} {...this.state} object_type={isGroup ? "group" : "normal"} useBankSuccess={this.useBankSuccess}></UseBank>
</li>}
{isAdmin && <li className="fr mr30">
<WordsBtn style="blue" className="fr" onClick={() => this.addDir(category_id)}>{!category_id ? "新建目录" : "目录重命名"}</WordsBtn>
</li>}
</React.Fragment>
}
secondRowBotton={
<div className="fl mt6 task_menu_ul">
<Menu mode="horizontal" selectedKeys={this.state.selectedKeys} onClick={this.selectedStatus}>
<Menu.Item key="all">全部</Menu.Item>
{isAdmin && <Menu.Item key="0">未发布</Menu.Item>}
<Menu.Item key="1">提交中</Menu.Item>
<Menu.Item key="2">补交中</Menu.Item>
<Menu.Item key="3">匿评中</Menu.Item>
<Menu.Item key="4">申诉中</Menu.Item>
<Menu.Item key="5">已截止</Menu.Item>
</Menu>
</div>
}
secondRowLeft={
<div style={{ "display": "inline-block", "marginTop": "22px" }}>
<span> {mainList && mainList.all_count} {moduleChineseName}</span>
<span style={{ "marginLeft": "16px" }}>已发布{published_count}</span>
{/* {this.props.isAdmin()?:""} */}
<span style={{ "marginLeft": "16px" }}>未发布{unpublished_count}</span>
</div>
}
searchPlaceholder={"请输入名称进行搜索"}
showSearchInput={true}
></Titlesearchsection>
<PublishRightnow ref="publishModalRef" showActionButton={true} {...this.props} checkBoxValues={checkBoxValues}
showActionButton={false}
isPublish={true}
islist={true}
isPublishtype={1}
doWhenSuccess={this.doWhenSuccess} fromListPage={true}></PublishRightnow>
{
mainList && mainList.course_identity < 5 && mainList.homeworks.length > 0 &&
<div className="mt20 edu-back-white padding20-30">
<div className="clearfix" >
<Checkbox className="fl" onChange={this.changeAll} checked={checkAll}>已选 {checkBoxValues.length} 不支持跨页勾选</Checkbox>
<div className="studentList_operation_ul">
<li className="li_line">
<a className="color-grey-9"
onClick={this.onWorkDelete}>删除</a>
</li>
<li className="li_line">
<a className="color-grey-9" onClick={() => this.refs['publishModalRef'].homeworkstart()}>{"立即发布"}</a>
</li>
<li className="li_line">
<PublishRightnow showActionButton={true} {...this.props} checkBoxValues={checkBoxValues}
isPublish={false} doWhenSuccess={this.doWhenSuccess} fromListPage={true}></PublishRightnow>
</li>
{!!course_public && <li className="li_line"><a onClick={this.onSetPublic} className="color-grey-9">设为公开</a></li>}
{this.props.user && this.props.user.main_site === true ? <li className="li_line"><a className="color-grey-9"
onClick={this.addToBank}
>加入题库</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' }}>
{course_module && course_module.length > 10 && <p className="drop_down_search">
<Input placeholder="搜索" value={this.state.dirSearchValue} onChange={(e) => { this.setState({ dirSearchValue: e.target.value }) }} />
</p>}
{
course_module && course_module.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 &&
<p className="drop_down_btn">
<a className="color-grey-6"
onClick={() => this.newaddDir()}
>新建目录...</a>
</p>
}
{/* <p className="drop_down_btn"><a className="color-grey-6">添加分班...</a></p> */}
</ul>
</li>
</div>
{/* 设为公开 */}
<Modals
modalsType={modalsType}
modalsTopval={modalsTopval}
modalsBottomval={modalsBottomval}
modalCancel={this.cancelDelClasses}
modalSave={this.sureDelClasses}
>
</Modals>
</div>
</div>
}
<Spin size="large" spinning={this.state.isSpin}>
<Checkbox.Group style={{ "width": "100%" }} onChange={this.onChangeSelect} value={checkBoxValues}>
<CommonWorkItem mainList={mainList} {...this.props} workType={workType} onItemClick={this.onItemClick}
openConnectionProject={this.openConnectionProject}
cancelConnectionProject={this.cancelConnectionProject}
></CommonWorkItem>
</Checkbox.Group>
</Spin>
{
mainList && mainList.homeworks && mainList.homeworks.length == 0 && <NoneData></NoneData>
}
{
!!totalCount && totalCount > 15 &&
<div className="edu-txt-center pt30 pb10 clearfix">
<Pagination current={page} showQuickJumper pageSize={15} total={totalCount} onChange={this.onPageChange}></Pagination>
</div>
}
</div>
)
}
}
export default RouteHOC()(commonWork);

View File

@ -1,316 +0,0 @@
import React,{ Component } from "react";
import { Pagination } from "antd";
import update from 'immutability-helper';
import axios from 'axios';
import moment from 'moment';
import _ from 'lodash';
import {ImageLayerOfCommentHOC} from '../../../page/layers/ImageLayerOfCommentHOC';
import GraduationTasksappraiseMainEditor from '../../graduation/tasks/GraduationTasksappraiseMainEditor';
import CCommentItem from '../../common/comments/CCommentItem';
import '../../../comment/Comment.css';
import '../../common/courseMessage.css';
import '../../graduation/tasks/GraduationTasksappraiseReply.css';
import './CommonWorkAppraiseReply.css';
import ModulationModal from "../../coursesPublic/ModulationModal";
import Modals from '../../../modals/Modals';
const REPLY_PAGE_COUNT = 10
const $ = window.$;
/*
*/
class CommonWorkAppraiseReply extends Component{
constructor(props){
super(props);
this.editorRef = React.createRef();
this.state={
total_count: 0,
comment_scores: [],
}
}
fetchAllComments = () => {
let category_id= this.props.match.params.category_id;
// const url = `/graduation_works/${category_id}/comment_list.json`
const task_id = this.props.task_id
const url = `/student_works/${task_id}/comment_list.json`
axios.get(url).then((result)=>{
if(result.data.comment_scores){
const comment_scores = result.data.comment_scores.map(item => {
return this.transformReply(item)
})
this.setState({
...result.data,
comment_scores
})
}
}).catch((error)=>{
console.log(error)
})
}
replySuccess = () => {
this.fetchAllComments()
}
componentDidMount(){
this.fetchAllComments()
}
addSuccess = () => {
this.fetchAllComments()
}
transformReply = (reply, children = []) => {
const isAdmin = this.props.isAdmin()
const isSuperAdmin = this.props.isSuperAdmin()
if (reply.appeal_info && reply.appeal_info.time) {
reply.appeal_info.user_info = {
"user_name": reply.appeal_info.user_name,
"user_login": reply.appeal_info.user_login,
"user_image_url": reply.appeal_info.user_image_url
}
reply.appeal_info.is_appeal_info = true
reply.appeal_info.appeal_status = reply.appeal_status
reply.appeal_info.score_id = reply.score_id
reply.journals.push(reply.appeal_info)
reply.journals = _.orderBy(reply.journals, 'time', 'asc')
}
return {
isSuperAdmin: isSuperAdmin,
admin: isAdmin, //
journals: reply.journals,
appeal_status: reply.appeal_status,
attachments: reply.attachments,
can_appeal: reply.can_appeal,
can_reply: reply.can_reply,
child_message_count: reply.child_message_count,
id: reply.comment_id,
// time: moment(reply.comment_time).fromNow(),
time: moment(reply.comment_time).format('YYYY-MM-DD HH:mm'),
image_url: reply.user_image_url,
user_id: reply.user_id,
user_login: reply.user_login,
username: reply.user_name,
content: reply.content,
score: reply.score,
delete: reply.delete,
is_invalid: reply.is_invalid,
comment_role: reply.comment_role
}
}
onDelete = (item) => {
this.props.confirm({
content: '确定要删除这个评阅吗?',
okText: '确定',
cancelText: '取消',
onOk: () => {
let category_id= this.props.match.params.category_id;
const task_id = this.props.task_id
// 作业是使用 task_id
const url = `/student_works/${task_id}/destroy_score.json`
axios.delete(url, { data: {
score_id: item.id
}
}).then((result)=>{
if(result.data.status == 0){
this.props.showNotification('删除成功')
this.fetchAllComments()
}
}).catch((error)=>{
console.log(error)
})
},
onCancel() {
console.log('Cancel');
},
});
}
showModulationtype=(id)=>{
// console.log(id)
this.setState({
Modulationtype:true,
operationId:id
})
}
cancelmodel=()=>{
this.setState({
Modalstype:false,
Loadtype:false,
visible:false,
Modulationtype:false,
Allocationtype:false,
Modalstopval:"",
ModalCancel:"",
ModalSave:"",
})
}
saveModulationModal=(value,num)=>{
let {operationId}=this.state;
let studentWorkId =this.props.match.params.studentWorkId;
let url ="/student_works/"+studentWorkId+"/adjust_score.json";
axios.post(url,{
score:num,
comment:value
}).then((result)=>{
if(result.data.status===0){
this.cancelmodel()
this.props.showNotification('调分成功')
this.props.onReplySuccess && this.props.onReplySuccess()
this.fetchAllComments();
}
}).catch((error)=>{
console.log(error)
})
}
onReply = (params) => {
const { task_id } = this.props;
const replyUrl = `/student_works/${task_id}/add_score.json`
axios.post(replyUrl, params).then((response)=>{
if(response.data.status == 0) {
this.editorRef.current.clearInputs()
this.fetchAllComments();
this.props.onReplySuccess && this.props.onReplySuccess()
}
}).catch((error)=>{
console.log(error)
})
}
render(){
let { total_count, comments, pageCount, comment_scores, allow_score } = this.state
const { current_user, memo, homework_status } = this.props
const isAdmin = this.props.isAdmin()
const isNiPing = homework_status && homework_status.indexOf('匿评中') != -1
const isGroup = this.props.isGroup()
/**
isAdmin || 评阅入口超级管理员老师和助教显示 - 改成admin也不显示
匿评人匿评期间显示
*/
// && isNiPing
const needNiPingEditor = (allow_score );
if (!needNiPingEditor && comment_scores.length == 0) {
return ''
}
return(
<React.Fragment>
<div className="edu-back-white padding10-10" style={{marginTop: '16px'}}>
<div className={"stud-class-set edu-back-white mb10"} style={{height:"100%"}}>
<Modals
modalsType={this.state.Modalstype}
modalsTopval={this.state.Modalstopval}
modalCancel={this.state.ModalCancel}
modalSave={this.state.ModalSave}
closable={false}
footer={null}
destroyOnClose={true}
centered={true}
/>
{this.state.Modulationtype===true?<ModulationModal
modalname={"调分"}
visible={this.state.Modulationtype}
Cancelname={"取消"}
Savesname={"保存"}
Cancel={this.cancelmodel}
Saves={(value,num)=>this.saveModulationModal(value,num)}
closable={false}
footer={null}
destroyOnClose={true}
centered={true}
/>:""}
{/*<div style={{ width:'100%',height:'75px'}} >*/}
{/*<p className=" fl color-black mt25 summaryname">{datalist&&datalist.task_name}</p>*/}
{/*<a className="color-grey-6 fr font-16 mt10 mr20" onClick={this.goback}>返回</a>*/}
{/*{this.props.isStudent()?<a className={"fr color-blue font-16 mt10 mr20"} onClick={this.addAccessory}>补交附件</a>:""}*/}
{/*</div>*/}
{/* {
(!!comment_scores.length &&
<div className={"color-grey-6 mb10"}>
<span className="labal">全部评阅</span>
<span className="count">{comment_scores.length}</span>
</div>)} */}
<div className={`padding20-30 ${comment_scores.length ? 'bor-bottom-greyE' : ''}`}>
{!!comment_scores.length && <div className={"color-grey-6 font-16"}>
全部评阅<span className="count">{comment_scores.length===0?"":`(${comment_scores.length})`}</span>
{/* <div style={{ width:'100%',height:'75px'}} ></div> */}
{/* true: 老师身份显示“调分”入口false: 不显示调分入口 */}
{isAdmin && !allow_score &&
<a className={"fr color-blue font-16"} onClick={()=>this.showModulationtype(this.props.task_id)}>调分</a>
}
</div> }
{needNiPingEditor && <GraduationTasksappraiseMainEditor {...this.props}
title={'评语'}
showModulationtype={this.showModulationtype}
addSuccess={this.addSuccess} ref={this.editorRef} totalCount={comment_scores.length}
onReply={this.onReply} placeholder={"请在此输入对本作品的评语最大限制2000个字符"}
showSameScore={isGroup && isAdmin}
get_next_works={()=>this.props.get_next_works()}
></GraduationTasksappraiseMainEditor> }
</div>
{/* ${!!comment_scores.length ? 'bor-bottom-greyE' : ''} */}
<div className={`padding20 memoReplies commentsDelegateParent course-message`}
style={{ paddingTop: '0px', paddingBottom: '0px' }}
>
{/*
.course-message .panel-comment_item {
margin-top: ${needNiPingEditor ? 56 : 28}px;
}
*/}
<style>{`
.course-message .panel-comment_item .comment_orig_content {
width: 1040px;
}
.course-message .childrenCommentsView .comment_orig_content {
width: 1000px;
}
.comment_item_cont:last-child {
border-bottom: none;
}
`}</style>
{!!comment_scores.length && <div className="panel-comment_item">
{ comment_scores.map((item, index) => {
return <CCommentItem item={item} onDelete={this.onDelete} {...this.props} commentIndex={index} replySuccess={this.replySuccess}></CCommentItem>
}) }
</div>}
</div>
</div>
</div>
</React.Fragment>
)
}
}
export default ImageLayerOfCommentHOC() (CommonWorkAppraiseReply);

View File

@ -1,415 +0,0 @@
import React,{ Component } from "react";
import { Input,Checkbox,Table, Pagination, Modal,Menu, Tooltip,Spin,Button,Form,Icon,message,Progress,notification} from "antd";
import { WordsBtn,on, off, trigger,markdownToHTML,getImageUrl} from 'educoder';
import './myelearning.css'
import axios from 'axios';
import YslDetailCards from "./YslDetailCards.js";
import Jointheclass from '../../modals/Jointheclass';
import LoginDialog from "../../login/LoginDialog";
import NoneData from '../../../modules/courses/coursesPublic/NoneData'
//在线学习
class Elearning extends Component{
constructor(props){
super(props);
this.state={
description:"", //简介
isSpin:true,
start_learning:undefined, //是否要开始学习 没开始学习 点击第一个是开始学习 就是学习下面的从第一个开始
learned:0, //学习进度
last_shixun:"", //上次学习的实训
stages:[], //实践课程的章节
yslJointhe:false,
shixunsreplace:false,
hidestartshixunsreplacevalue:"",
shixunsmessage:"",
startshixunCombattype:false,
isSpins:false,
userlogin:"",
isRender:false,
subject_id:0,
myupdataleftNavs:this.myupdataleftNav
}
}
componentDidMount() {
// 记得删除退出课堂
// console.log("在线学习");
// console.log("获取到数据");
// console.log(this.props);
this.getdata();
}
getdata=()=>{
console.log("更新了数据了");
let url = `/courses/${this.props.match.params.coursesId}/online_learning.json`;
// //
axios.get(url).then((response) => {
if(response){
if(response.data){
// console.log("获取到到数据");
// console.log(response);
this.setState({
description: response.data.description,
start_learning:response.data.start_learning,
learned:response.data.learned,
last_shixun:response.data.last_shixun,
stages:response.data.stages,
subject_id:response.data.subject_id,
});
}
}
this.setState({
isSpin:false,
})
}).catch((error) => {
console.log(error);
this.setState({
isSpin:false,
})
});
try {
if(this.props.current_user!==undefined){
this.setState({
userlogin :this.props.current_user.login,
})
}
}catch (e) {
console.log("12312312312")
console.log(e);
}
}
componentDidUpdate = (prevProps) => {
console.log("componentDidUpdate");
// console.log(prevProps);
// console.log(this.props);
if(prevProps.current_user!=this.props.current_user){
if(this.props.current_user!==undefined){
// console.log(this.props.current_user.login);
// console.log(prevProps.current_user.login);
this.setState({
userlogin :this.props.current_user.login,
})
}
}
if(prevProps.yslElearning===this.props.yslElearning) {
if(prevProps.yslElearning===true && this.props.yslElearning===true){
// console.log("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
// console.log(prevProps.yslElearning);
// console.log(this.props.yslElearning);
this.getdata();
this.props.comyslElearning(false);
}
}
}
//开始学习
Startlearning=()=>{
let {userlogin} = this.state;
console.log("userlogin");
console.log(userlogin);
if (userlogin === undefined) {
this.setState({
isRender: true
})
return
}
if (userlogin === "") {
this.setState({
isRender: true
})
return;
}
if(this.props.isNotMember()===true){
this.setState({
yslJointhe:true
})
}else {
let {stages}=this.state;
if(stages.length>0){
var stagesdatas=[];
for(var i=0;i<stages.length;i++){
for(var ki=0;ki<stages[i].shixuns_list.length;ki++){
if(stages[i].shixuns_list[ki].shixun_status !=="暂未公开"){
var id=stages[i].shixuns_list[ki].identifier;
console.log(id);
stagesdatas.push(id);
}
}
}
console.log(stagesdatas[0]);
if(stagesdatas.length>0){
this.kaishishixun(stagesdatas[0]);
}else {
notification.open({
message:"提示",
description: "实训暂未公开!"
});
}
console.log("这是"+i);
}
}
};
kaishishixun=(id)=>{
let url = "/shixuns/" + id + "/shixun_exec.json";
axios.get(url).then((response) => {
console.log("精品课堂开发学习");
console.log(response);
// console.log(JSON.stringify(response));
if (response.data.status === -2) {
this.setState({
shixunsreplaces:true,
hidestartshixunsreplacevalues:response.data.message+".json"
})
} else if (response.data.status === -1) {
console.log(response)
}else if(response.data.status===-3){
this.setState({
shixunsmessages:response.data.message,
startshixunCombattypes:true,
})
} else {
console.log("开始学习了");
window.open("/tasks/" + response.data.game_identifier,'_blank');
//这个是传过来 调用刷新
this.Myreload();
// window.location.href = path
// let path="/tasks/"+response.data.game_identifier;
// this.props.history.push(path);
}
}).catch((error) => {
});
}
Startlearningtwo=()=>{
this.setState({
yslJointhe:true
})
};
ysljoinmodalCancel=()=>{
this.setState({
yslJointhe:false
})
};
ysljoinmodalCanceltwo=()=>{
this.setState({
yslJointhe:false
})
window.location.reload();
};
Myreload = ()=>{
window.location.reload();
};
hidestartshixunsreplace=(url)=>{
this.setState({
isSpins:true,
})
axios.get(url).then((response) => {
if(response.status===200){
// let path="/shixuns/"+response.data.shixun_identifier+"/challenges";
// this.props.history.push(path);
message.success('重置成功,正在进入实训!');
this.startgameid(response.data.shixun_identifier);
this.setState({
shixunsreplaces:false,
isSpins:false,
})
}}
).catch((error) => {
this.setState({
isSpins:false,
shixunsreplaces:false,
})
});
};
startgameid=(id)=>{
if(this.props.isNotMember()===true){
//这个是外部传过来的
this.Startlearningtwo();
return
}
let url = "/shixuns/" + id + "/shixun_exec.json";
axios.get(url).then((response) => {
if (response.data.status === -2) {
this.setState({
shixunsreplaces:true,
hidestartshixunsreplacevalues:response.data.message+".json"
})
} else if (response.data.status === -1) {
console.log(response)
}else if(response.data.status===-3){
this.setState({
shixunsmessages:response.data.message,
startshixunCombattypes:true,
})
} else {
console.log("开始学习了");
window.open("/tasks/" + response.data.game_identifier,'_blank');
//这个是传过来 调用刷新
this.Myreload();
// window.location.href = path
// let path="/tasks/"+response.data.game_identifier;
// this.props.history.push(path);
}
}).catch((error) => {
});
};
hidestartshixunCombattype=()=>{
this.setState({
startshixunCombattypes:false
})
};
Modifyloginvalue=()=>{
this.setState({
isRender:false,
})
};
Tojoinclass=()=> {
this.setState({
isRender: true
})
};
myupdataleftNav=()=>{
this.props.updataleftNavfun();
}
render(){
console.log("Elearning++++++++");
// console.log(this.props.Chapterupdate);
let{description,whethertoedit,isSpin,start_learning,hidestartshixunsreplacevalues,learned,last_shixun,stages,isRender} =this.state;
const isNotMembers=this.props.isNotMember();//非课堂成员
const antIcon = <Icon type="loading" style={{ fontSize: 24 }} spin />;
return(
<React.Fragment >
<div id={"zhudiv"}>
{isRender===true?<LoginDialog
Modifyloginvalue={()=>this.Modifyloginvalue()}
{...this.props}
{...this.state}
/>:""}
<Jointheclass {...this.props} {...this.state} ysljoinmodalCancel={()=>this.ysljoinmodalCancel()} ysljoinmodalCanceltwo={()=>this.ysljoinmodalCanceltwo()}></Jointheclass>
<Modal
keyboard={false}
title="提示"
visible={this.state.startshixunCombattypes}
closable={false}
footer={null}
>
<div className="task-popup-content">
<p className="task-popup-text-center font-16 pb20">目前该实训项目尚在内测中将于{this.state.shixunsmessages}之后开放谢谢</p>
</div>
<div className="task-popup-submit clearfix">
{/*<a onClick={this.hidestartshixunCombattype} className="task-btn fl">取消</a>*/}
<a className="task-btn task-btn-orange fr"
style={{marginRight:'51px'}}
onClick={this.hidestartshixunCombattype}>知道了</a>
</div>
{/*<p className="inviteTipbtn with100 fl">*/}
{/*<a onClick={this.hidestartshixunCombattype}>知道了</a>*/}
{/*</p>*/}
</Modal>
<Modal
keyboard={false}
title="提示"
visible={this.state.shixunsreplaces}
closable={false}
footer={null}
>
<Spin indicator={antIcon} spinning={this.state.isSpins}>
<div className="task-popup-content">
<p className="task-popup-text-center font-16 pb20">实训已经更新了正在为您重置!</p>
</div>
<div className="task-popup-submit clearfix">
<a className="task-btn task-btn-orange fr"
style={{marginRight:'51px'}}
onClick={() => this.hidestartshixunsreplace(hidestartshixunsreplacevalues)}>知道了</a>
</div>
</Spin>
</Modal>
<div className="edu-back-white">
{
this.props.isAdmin()===true?"":
<div>
{
start_learning===undefined?"":start_learning===false?
<div className="clearfix padding30 bor-bottom-greyE" style={{textAlign: "center"}}>
<div style={{height: '40px',textAlign: "center"}}>
<span className=" fl color-dark-21 " style={{height: '40px', textAlign: "center",fontSize:"19px"}}>还未开始学习</span>
<Button className="ant-btn defalutSubmitbtn ant-btn-primary colorblue font-16 fr" onClick={()=>this.Startlearning()}>
<span>开始学习</span></Button>
</div>
</div>
:
<div className="clearfix padding30 bor-bottom-greyE" style={{textAlign: "center"}}>
<div style={{height: '40px',textAlign: "left"}}>
<span className=" color-dark-21 " style={{height: '40px', textAlign: "center",fontSize:"19px",color:"#05101A"}}>已学{learned}%</span>
</div>
<div style={{marginTop:"7px",width:"401px"}}>
<Progress percent={learned} showInfo={false} />
</div>
<div style={{marginTop:"7px",textAlign: "left"}}>
<span className="font-16">上次学习内容</span><span style={{color:"#4CADFF",marginLeft:"25px"}}>{last_shixun}</span>
</div>
</div>
}
</div>
}
{/*简介*/}
{/*<div className="clearfix pl30 pr30" style={{paddingBottom:"22px"}}>*/}
{/* <div style={{textAlign: "left",marginTop:"10px",paddingBottom: "10px"}}>*/}
{/* <span className=" color-dark-21 " style={{textAlign: "center",fontSize:"19px"}}>简介</span>*/}
{/* </div>*/}
{/* <div className="edu-back-white new_li editormd-html-preview " >*/}
{/* <p className="markdown-body fonttext " dangerouslySetInnerHTML={{__html: markdownToHTML(description).replace(/▁/g,"▁▁▁")}}>*/}
{/* </p>*/}
{/* </div>*/}
{/*</div>*/}
</div>
<Spin size="large" spinning={isSpin} id={"cdiv"}>
<div className=" clearfix" style={this.props.isAdmin()===true?{marginTop:"0px"}:{marginTop:"20px"}}>
<div>
{/*开始学习*/}
<YslDetailCards {...this.state} {...this.props} Startlearningtwo={()=>this.Startlearningtwo()} Myreload={()=>this.Myreload()} Tojoinclass={()=>this.Tojoinclass()} getPathCardsList={()=>this.getdata()} ></YslDetailCards>
</div>
</div>
</Spin>
</div>
</React.Fragment>
)
}
}
const Elearningss = Form.create({ name: 'elearning' })(Elearning);
export default Elearningss;

View File

@ -1,566 +0,0 @@
import React, { Component } from 'react';
import {getImageUrl} from 'educoder';
import { Tooltip,Modal,Icon,Spin,message} from 'antd';
import '../../paths/ShixunPaths.css';
import axios from 'axios';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import DetailCardsEditAndEdit from '../../paths/PathDetail/DetailCardsEditAndEdit';
import DetailCardsEditAndAdd from "../../paths/PathDetail/DetailCardsEditAndAdd";
import Modals from "../../modals/Modals";
import NoneData from "../coursesPublic/NoneData";
class YslDetailCards extends Component{
constructor(props){
super(props)
this.state={
showparagraph:false,
showparagraphkey:"",
showparagraphindex:"",
shixunsreplace:false,
hidestartshixunsreplacevalue:"",
shixunsmessage:"",
startshixunCombattype:false,
isSpin:false,
idsum:undefined,
pathCardsedittype:false,
pathid:undefined,
editbuttomtype:false,
editbuttomtypeadd:false,
pathlistedit:undefined,
delecttype:false,
Modalstype:false,
Modalstopval:'',
Modalsbottomval:'',
}
//idsum 是否点击这个
//pathCardsedittype 是否是在编辑模式
//editbuttomtypeadd 是否已经是编辑模式
//pathid课堂id
//pathlistedit 编辑返回的数据
}
showparagraph =(key,index)=>{
this.setState({
showparagraph:true,
showparagraphkey:key,
showparagraphindex:index
})
};
hideparagraph=()=>{
this.setState({
showparagraph:false,
showparagraphkey:null,
showparagraphindex:null
})
};
startgameid=(id)=>{
// 上面传过来的方法是用来没登入弹出弹框的
try {
let {userlogin} = this.props;
if (userlogin === undefined) {
this.props.Tojoinclass();
return
}
if (userlogin === "") {
this.props.Tojoinclass();
return;
}
}catch (e) {
}
try {
if(this.props.isNotMember()===true){
//这个是外部传过来的
this.props.Startlearningtwo();
return
}
}catch (e) {
}
let url = "/shixuns/" + id + "/shixun_exec.json";
axios.get(url).then((response) => {
if (response.data.status === -2) {
this.setState({
shixunsreplace:true,
hidestartshixunsreplacevalue:response.data.message+".json"
})
} else if (response.data.status === -1) {
console.log(response)
}else if(response.data.status===-3){
this.setState({
shixunsmessage:response.data.message,
startshixunCombattype:true,
})
} else {
// console.log("开始学习了");
window.open("/tasks/" + response.data.game_identifier,'_blank');
//这个是传过来 调用刷新
this.props.getPathCardsList();
// window.location.href = path
// let path="/tasks/"+response.data.game_identifier;
// this.props.history.push(path);
}
}).catch((error) => {
});
};
componentDidMount(){
// console.log("YslDetailCards start");
let pathid=this.props.match.params.coursesId;
this.setState({
pathid:pathid
})
}
Pathlisteditundefined=()=>{
this.setState({
pathlistedit:undefined
})
};
hidestartshixunsreplace=(url)=>{
this.setState({
isSpin:true,
})
axios.get(url).then((response) => {
if(response.status===200){
message.success('重置成功,正在进入实训!');
this.startgameid(response.data.shixun_identifier);
this.setState({
shixunsreplace:false,
isSpin:false,
startbtn:false,
})
}}
).catch((error) => {
this.setState({
isSpin:false,
shixunsreplace:false,
})
});
}
hidestartshixunCombattype=()=>{
this.setState({
startshixunCombattype:false
})
};
// 关卡的上移下移操作
operations = (url) => {
let newurl = url+".json"
axios.get(newurl).then((response) => {
if(response.data.status===1){
this.props.getPathCardsList();
}
}).catch((error) => {
console.log(error);
})
};
//章节下移
chapterdown=(id)=>{
let url=`/course_stages/${id}/down_position.json`;
axios.post(url).then((response) => {
if(response){
if(response.data){
if(response.data.status===0){
this.props.showNotification(`下移成功`);
this.props.getPathCardsList();
}else{
this.props.showNotification(`下移失败`);
}
}else{
this.props.showNotification(`下移失败`);
}
}else {
this.props.showNotification(`下移失败`);
}
}).catch((error) => {
console.log(error)
});
};
//章节上移
chapterup=(id)=>{
let url=`/course_stages/${id}/up_position.json`;
axios.post(url).then((response) => {
if(response){
if(response.data){
if(response.data.status===0){
this.props.showNotification(`上移成功`);
this.props.getPathCardsList();
}else{
this.props.showNotification(`上移失败`);
}
}else{
this.props.showNotification(`上移失败`);
}
}else{
this.props.showNotification(`上移失败`);
}
}).catch((error) => {
console.log(error)
});
};
//确认的
updatapathCardsedit=()=>{
this.setState({
idsum:undefined,
pathCardsedittype:false,
editbuttomtype:false,
editbuttomtypeadd:false
})
this.props.getPathCardsList();
this.props.myupdataleftNavs();
// this.props.updatadetailInfoLists();
};
//取消的
editeditbuttomtypecanle=()=>{
this.setState({
editbuttomtype:true,
editbuttomtypeadd:false
})
}
//编辑用
pathCardsedit=(key,pathid)=>{
let url=`/course_stages/${pathid}/edit.json`;
axios.get(url).then((result)=>{
if(result){
if(result.status===200){
this.setState({
idsum:key,
pathCardsedittype:true,
pathlistedit:result.data,
editbuttomtype:true,
editbuttomtypeadd:true
})
}
}
}).catch((error)=>{
console.log(error);
})
};
//删除用的
delectpathCardsedit=(id)=>{
this.setState({
Modalstype:true,
Modalstopval:'是否删除该章节?',
Modalsbottomval:'',
editdelectid:id,
delecttype:true,
})
}
cardsModalcancel=()=>{
this.setState({
Modalstype:false,
Modalstopval:'',
Modalsbottomval:'',
editdelectid:undefined
})
}
cardsModalsave=()=>{
this.setState({
Modalstype:false,
Modalstopval:'',
Modalsbottomval:'',
editdelectid:undefined
})
}
delectpathCardseditfun=()=>{
let {delecttype,editdelectid}=this.state;
let id=editdelectid;
if(delecttype===true){
let url =`/course_stages/${id}.json`
axios.delete(url).then((response) => {
if(response){
if(response.data){
if(response.data.status===0){
this.setState({
idsum:undefined,
pathCardsedittype:false,
Modalstype:false,
Modalstopval:'',
Modalsbottomval:'',
delecttype:false,
editdelectid:undefined
})
this.updatapathCardsedit()
this.props.showNotification(`删除成功`);
this.props.myupdataleftNavs();
}else {
this.props.showNotification(`删除失败`);
}
}else{
this.props.showNotification(`删除失败`);
}
}else {
this.props.showNotification(`删除失败`);
}
}).catch((error) => {
console.log(error)
})
}
}
render(){
let{showparagraph,showparagraphkey,showparagraphindex,hidestartshixunsreplacevalue,idsum,pathCardsedittype,pathid,Modalstype,Modalstopval,Modalsbottomval,delecttype,pathlistedit,editbuttomtypeadd,editbuttomtype} =this.state;
let { stages ,subject_id}=this.props;
const antIcon = <Icon type="loading" style={{ fontSize: 24 }} spin />;
// console.log("pathCardsedittype");
// console.log(pathCardsedittype);
// console.log(editbuttomtype);
// console.log("this.props.isAdmin");
// console.log(this.props.isAdmin());
// console.log(this.state.delecttype);
return(
<div>
{
stages===undefined||stages===JSON.stringify("[]")||stages.length===0?
""
:
<div className="lesson-saved-list">
<Modal
keyboard={false}
title="提示"
visible={this.state.startshixunCombattype}
closable={false}
footer={null}
>
<div className="task-popup-content">
<p className="task-popup-text-center font-16 pb20">目前该实训项目尚在内测中将于{this.state.shixunsmessage}之后开放谢谢</p>
</div>
<div className="task-popup-submit clearfix">
{/*<a onClick={this.hidestartshixunCombattype} className="task-btn fl">取消</a>*/}
<a className="task-btn task-btn-orange fr"
style={{marginRight:'51px'}}
onClick={this.hidestartshixunCombattype}>知道了</a>
</div>
{/*<p className="inviteTipbtn with100 fl">*/}
{/*<a onClick={this.hidestartshixunCombattype}>知道了</a>*/}
{/*</p>*/}
</Modal>
<Modal
keyboard={false}
title="提示"
visible={this.state.shixunsreplace}
closable={false}
footer={null}
>
<Spin indicator={antIcon} spinning={this.state.isSpin}>
<div className="task-popup-content">
<p className="task-popup-text-center font-16 pb20">实训已经更新了正在为您重置!</p>
</div>
<div className="task-popup-submit clearfix">
<a className="task-btn task-btn-orange fr"
style={{marginRight:'51px'}}
onClick={() => this.hidestartshixunsreplace(hidestartshixunsreplacevalue)}>知道了</a>
</div>
</Spin>
</Modal>
<Modals
modalsType={Modalstype}
modalsTopval={Modalstopval}
modalsBottomval={Modalsbottomval}
modalCancel={this.cardsModalcancel}
modalSave={delecttype===true?this.delectpathCardseditfun:this.cardsModalsave}
>
</Modals>
<style>{
`
.lesson-saved-list-item {
border-bottom: none!important;
margin-bottom: 20px;
background-color: #fff;
}
.lessonvalue{
max-width: 556px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
}
`
}</style>
{
this.props.isStudent()===true&&(stages===undefined||stages===JSON.stringify("[]")||stages.length===0)?
<NoneData></NoneData>
:
""
}
{
stages && stages.map((item,key)=>{
return(
<div className={"lesson-saved-list-item"} key={key} id={"stage_div_"+key} >
<p className="clearfix title-line">
<a className="fl ring-blue mr10 mt2">
<img src={getImageUrl("images/educoder/icon/charpter-white.svg")} className="fl ml3 mt3"/>
</a>
<span className="font-18 font-bd lessonvalue" title={item.stage_name}>{item.stage_name}</span>
{
idsum===key&&pathCardsedittype===true?'':
this.props.isAdmin()==true?
<a>
<a className="fr mtf3">
{ editbuttomtype===true?'':
<Tooltip placement="bottom" title="编辑"
onClick={() => this.pathCardsedit(key, item.stage_id)}>
<i className="iconfont icon-bianjidaibeijing font-22 color-green"></i>
</Tooltip>
}
</a>
{
stages.length=== key+1?"":<a className="fr ring-op-green mr20" onClick={()=>this.chapterdown(item.stage_id)}>
<Tooltip placement="bottom" title="向下移动">
<img src={getImageUrl("images/educoder/icon/movedown.svg")} className="fl mt2 ml4"/>
</Tooltip>
</a>
}
{key===0?"":
<a className="fr ring-op-green mr20" onClick={()=>this.chapterup(item.stage_id)}>
<Tooltip placement="bottom" title="向上移动">
<img src={getImageUrl("images/educoder/icon/moveup.svg")} className="fl mt2 ml4"/>
</Tooltip>
</a>}
</a>:""
}
{
idsum === key && pathCardsedittype === true ?
this.props.isAdmin()===true?
<a className="fr" onClick={()=>this.delectpathCardsedit(item.stage_id)}>
<Tooltip placement="bottom" title="删除">
<i className="iconfont icon-shanchu color-grey-c font-14 font-n"></i>
</Tooltip>
</a>:""
: ''
}
</p>
{
idsum===key&&pathCardsedittype===true?'':
<div className="detail_for_paragraph clearfix" id={"detail_for_paragraph_"+key}>
<p className="color-dark-grey mt20 mb25 ml20 mr20 pl28 justify font-15">{item.stage_description}</p>
<div>
{
item.shixuns_list && item.shixuns_list.map((line,index)=>{
return(
<div className="clearfix paragraph lineh-30" key={index} onMouseEnter={()=>this.showparagraph(key,index)} onMouseLeave={this.hideparagraph}>
<li className="fl li-width63">
<span className="progressRing mr10">
{
line.complete_status === 1 ?<i className="iconfont icon-wancheng progressRing-over font-18 mt10"></i>
:<i className="iconfont icon-bofang progressRing-part font-18 mt10"></i>
}
</span>
<span className={line.allow_visit===false&&line.shixun_status==="暂未公开"?"paragraph_name color204":"paragraph_name color-grey3"}>
<span className="subject_stage_shixun_index">{key+1}</span>-{index+1}&nbsp;&nbsp;{line.shixun_name}
</span>
</li>
{
line.allow_visit===false&&line.shixun_status==="暂未公开"?
<li className="fr status_li"><span className="fr color204">暂未公开</span></li>
:
<li className={showparagraph===false?"none":"fr status_li"}>
{
showparagraphkey===key&&showparagraphindex===index?<div>
<Link to={'/shixuns/'+line.identifier+'/challenges'} className="mr30 color-blue_4C shixun_detail pointer fl" target="_blank">查看详情</Link>
{line.shixun_status==="暂未公开"?"":<a onClick={()=>this.startgameid(line.identifier)} className="btn_auto user_bluebg_btn fl" id="shixun_operation" >开始学习</a>}
</div>:""
}
</li>
}
{line.allow_visit===false&&line.shixun_status==="暂未公开"?"": <li className={showparagraph===false?"fr status_li":"fr status_li"}>
{
showparagraphkey === key && showparagraphindex === index ? "" :
<span className="fr color204">实验任务 <span
className={"color000"}>{line.challenges_count}</span></span>
}
</li>}
</div>)
})
}
</div>
</div>
}
{
this.props.isAdmin()===true?
<DetailCardsEditAndEdit
{...this.props}
idsum={idsum}
keys={key}
pathCardsedittype={pathCardsedittype}
updatapathCardsedits={this.updatapathCardsedit}
pathlisteditlist={pathlistedit}
stageid={item.stage_id}
ysldetailcards={"ysldetailcards"}
pathid={subject_id}
coursesId={pathid}
Pathlisteditundefined={this.Pathlisteditundefined}
></DetailCardsEditAndEdit>
:""
}
</div>
)
})
}
</div>
}
{ editbuttomtypeadd===true?'':this.props.isAdmin()===true?
<DetailCardsEditAndAdd
{...this.props}
sum={stages && stages.length+1}
pathid={subject_id}
coursesId={pathid}
detailInfoList={this.props.detailInfoList}
getPathCardsLists={this.updatapathCardsedit}
editeditbuttomtypes={this.editeditbuttomtypecanle}
ysldetailcards={"ysldetailcards"}
></DetailCardsEditAndAdd>
:""
}
</div>
)
}
}
export default YslDetailCards;
// detailInfoList以前实训课堂做权限判断的作用 this.props.subject_id

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,109 +0,0 @@
.color4CACFF{
color: #4CACFF !important;
}
.orderingbox{
width:1200px;
height:80px;
background:rgba(255,255,255,1);
box-shadow:3px 3px 3px rgba(237,237,237,1);
opacity:1;
border-radius:2px 2px 0px 0px;
padding: 24px;
box-sizing: border-box;
line-height: 34px;
}
.orderingbtnright{
width: 90px;
height: 38px;
background: rgba(255,255,255,1);
border: 1px solid rgba(228,228,228,1);
box-shadow: 0px 1px 1px rgba(0,0,0,0.16);
opacity: 1;
border-radius: 4px;
}
.orderingbtnleft{
width: 90px;
height: 38px;
background: rgba(76,172,255,1);
box-shadow: 0px 1px 1px rgba(0,0,0,0.16);
opacity: 1;
border-radius: 4px;
}
.pd1323s{
padding: 10px 6px 25px 40px;
cursor: pointer;
}
.orderSection{
height: 80px;
padding-top: 16px;
}
.ordermidbox{
width: 960px;
height: 120px;
background: rgba(255,255,255,1);
/* border: 1px solid rgba(205,205,205,1); */
opacity: 1;
margin-left:120px;
}
.orderfonttop{
font-size: 16px !important;
font-family: Microsoft YaHei;
font-weight: bold;
line-height: 28px;
color: rgba(5,16,26,1);
opacity: 1;
}
.orderfontbom{
font-size:14px;
font-family:Microsoft YaHei;
font-weight:400;
line-height:25px;
color:rgba(153,153,153,1);
opacity:1;
}
.ordermidbox:hover {
box-shadow: 0px 2px 6px rgba(51,51,51,0.09);
opacity: 1;
}
.mb200{
margin-bottom: 200px;
}
.maxwidth865s{
max-width: 865px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.maxwidth795 {
max-width:795px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
}
.ordermidbox:active{
background:rgba(248,247,255,1);
border:1px solid rgba(76,172,255,1);
}
.ordermidbox:focus{
background:rgba(248,247,255,1);
border:1px solid rgba(76,172,255,1);
}
.ordermiddiv{
min-height: 500px;
}

View File

@ -1,296 +0,0 @@
import React,{ Component } from "react";
import { Input,Checkbox,Table, Pagination, Modal,Menu, Tooltip,Spin,Breadcrumb,Button } from "antd";
import { WordsBtn,on, off, trigger } from 'educoder';
import { DragDropContext,Draggable, Droppable} from 'react-beautiful-dnd';
import axios from'axios';
import Modals from '../../modals/Modals';
import '../css/members.css';
import '../css/busyWork.css';
import './Ordering.css';
import NoneData from "../coursesPublic/NoneData";
const reorder = (list, startIndex, endIndex) => {
const result = Array.from(list);
const [removed] = result.splice(startIndex, 1);
result.splice(endIndex, 0, removed);
return result;
};
class Ordering extends Component{
constructor(props){
super(props);
this.state={
isSpin:false,
antIcon:false,
datas:undefined,
windowsscrollTop:false,
newtask_ids:[]
}
}
componentDidMount() {
this.setState({
isSpin:true
})
let coursesId=this.props.match.params.coursesId;
let ordering_type=this.props.match.params.ordering_type;
let url=`/courses/${coursesId}/tasks_list.json`;
axios.get((url),{params:{
container_type:ordering_type
}}).then((result)=>{
if(result){
this.setState({
datas:result.data.tasks,
isSpin:false
})
}
}).catch((error)=>{
console.log(error);
this.setState({
isSpin:false
})
})
window.addEventListener('scroll', this.handleScroll.bind(this)) //监听滚动
// window.addEventListener('resize', this.handleResize.bind(this)) //监听窗口大小改变
}
// componentWillUnmount() { //一定要最后移除监听器以防多个组件之间导致this的指向紊乱
// window.removeEventListener('scroll', this.handleScroll.bind(this))
// window.removeEventListener('resize', this.handleResize.bind(this))
// }
handleScroll=(e)=>{
// console.log(
// '浏览器滚动事件',
// e.srcElement.scrollingElement.scrollTop,
// e.srcElement.scrollingElement.scrollHeight
// )
//e.srcElement.scrollingElement.scrollTop为距离滚动条顶部高度
// e.srcElement.scrollingElement.scrollHeight为整个文档高度
if(e.srcElement.scrollingElement.scrollTop>60){
this.setState({
windowsscrollTop:true,
})
}
if(e.srcElement.scrollingElement.scrollTop===0){
this.setState({
windowsscrollTop:false
})
}
}
//
// handleResize = e => {
// console.log('浏览器窗口大小改变事件', e.target.innerWidth)
// }
onDragEnd=(result)=>{
if(result.destination!=null&&result.destination!=undefined){
let {datas}=this.state;
if (!result.destination) {
console.log('dropped outside the list')
return;
}
if (result.destination.index === result.source.index) {
console.log('the same')
return;
}
const shixuns_list = reorder(
datas,
result.source.index,
result.destination.index
);
let newtask_ids=[]
shixuns_list.map((item,key)=>{
newtask_ids.push(item.task_id)
})
this.setState({
datas:shixuns_list,
newtask_ids:newtask_ids
})
}
}
updatalist=()=>{
let {datas,newtask_ids,isSpin}=this.state;
if(newtask_ids.length===0){
this.props.showNotification("请先移动需要排序的实训作业任务");
return
}
if(isSpin===true){
return
}
this.setState({
isSpin:true
})
let coursesId=this.props.match.params.coursesId;
let ordering_type=this.props.match.params.ordering_type;
let url=`/courses/${coursesId}/update_task_position.json`;
axios.post(url,{
container_type:ordering_type,
task_ids:newtask_ids
}).then((result)=>{
if(result.data.status===0){
this.props.showNotification(result.data.message);
this.setState({
isSpin:false,
datas:datas,
newtask_ids:[]
});
this.goback()
}else{
this.setState({
isSpin:false,
});
}
}).catch((error)=>{
this.setState({
isSpin:false,
});
})
}
goback=()=>{
window.location.href=`/classrooms/${this.props.match.params.coursesId}/shixun_homeworks/${this.props.match.params.main_id}`
}
render(){
let {
datas,
Modalstype,
windowsscrollTop,
}=this.state;
let main_id=this.props.match.params.main_id;
let category_id=this.props.match.params.category_id;
let positiontype=null;
if(windowsscrollTop===true){
positiontype={position:'fixed',zIndex:'1000',top: '0px'}
}else{
positiontype={}
}
return(
<div className={"mb200"}>
{/*提示*/}
{Modalstype&&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}
antIcon={this.state.antIcon}
/>:""}
<div className="educontent clearfix">
{windowsscrollTop===false?<div className={"mt20 mb20"}>
<Breadcrumb separator=">">
<Breadcrumb.Item href={this.props.current_user&&this.props.current_user.first_category_url}>{this.props.current_user&&this.props.current_user.course_name}</Breadcrumb.Item>
<Breadcrumb.Item href={`/classrooms/${this.props.match.params.coursesId}/shixun_homeworks/${this.props.match.params.main_id}`}>实训作业</Breadcrumb.Item>
<Breadcrumb.Item>调整排序</Breadcrumb.Item>
</Breadcrumb>
</div>:""}
<p className="clearfix bor-bottom-greyE edu-back-white orderingbox"
style={positiontype}
>
<span>温馨提示请在列表中长按鼠标左键进行拖放排序完成排序后请点击保存</span>
<Button className="fr orderingbtnleft" type="primary" onClick={()=>this.updatalist()}>保存</Button>
<Button className="fr mr30 orderingbtnright" onClick={()=>this.goback()}>取消</Button>
</p>
</div>
<Spin size="large" spinning={this.state.isSpin} >
<DragDropContext onDragEnd={this.onDragEnd} >
<Droppable droppableId={this.props.match.params.ordering_type}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.droppableProps}
className={"educontent mb50 mt40 droppableul ordermiddiv"}
onScroll={this.contentViewScrolledit}
>
{datas===undefined?"":
datas.map((item, index) => {
return (
<Draggable
key={item.task_id}
draggableId={item.task_id}
index={index}
className={"TabsWarps"}
>
{(provided, snapshot) => (
<div className={"mt30 edu-back-white pd1323s relativef ordermidbox"}
key={index}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<div className={"clearfix"}>
<div className={"item-body"}>
<div className={"clearfix ds pr orderSection"}>
<p title={item.task_name} className="font-16 color-dark maxwidth865s orderfonttop"
href={`/classrooms/${this.props.match.params.coursesId}/shixun_homeworks/${item.task_id}/list?tab=0`}>{item.task_name}</p>
<p className={"color-grey panel-lightgrey mt16 "}>
<span className="topicswidth400">
<span className="topsics100 color-grey9 orderfontbom mr20 maxwidth795">{item.user_name}</span>
<span className="mr50 color-grey9 orderfontbom maxwidth795">{item.category}</span>
</span>
</p>
</div>
</div>
</div>
</div>
)}
</Draggable>
)
})
}
</div>
)}
</Droppable>
</DragDropContext>
{
datas===undefined?"":datas.length===0? <NoneData></NoneData>:""
}
</Spin>
</div>
)
}
}
export default Ordering;

View File

@ -1,53 +0,0 @@
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 { TPMIndexHOC } from '../../tpm/TPMIndexHOC';
import "../css/Courses.css"
//引入对应跳转的组件
// {/*提交总结*/}
// const CommitSummary = Loadable({
// loader: () => import('../shixunHomework/CommitSummary'),
// loading:Loading,
// })
//
//
// //实训设置
//
// const StudentHomework = Loadable({
// loader: () => import('./StudentHomework'),
// loading:Loading,
// })
//
class CommitSummaryIndex extends Component{
constructor(props) {
super(props)
}
render() {
return (
<div>
<Switch {...this.props}>
{/*/!*提交总结*!/*/}
{/*<Route path="/student_work/:StudentId/commit_summary" component={CommitSummary} {...this.props} {...this.state}></Route>*/}
{/*/!*实训设置*!/*/}
{/*<Route path={"/student_work/homework"} component={StudentHomework} {...this.props} {...this.state}></Route>*/}
{/*/!*提交总结*!/*/}
{/*<Route exact path="/student_work" component={CommitSummary} {...this.props} {...this.state}></Route>*/}
</Switch>
</div>
)
}
}
export default SnackbarHOC() ( TPMIndexHOC(CommitSummaryIndex) );

View File

@ -1,246 +0,0 @@
import React,{Component} from "react";
import { Form, Select, Input, Button,Checkbox,DatePicker} from "antd";
import locale from 'antd/lib/date-picker/locale/zh_CN';
import "../css/Courses.css";
import CoursesListType from '../coursesPublic/CoursesListType';
const { Option } = Select;
const CheckboxGroup = Checkbox.Group;
class StudentHomework extends Component{
constructor(props){
super(props)
this.state={
}
}
componentDidMount(){
}
handleSubmit = (e) => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
}
});
}
handleSelectChange = (value) => {
console.log(value);
this.props.form.setFieldsValue({
note: `Hi, ${value === 'male' ? 'man' : 'lady'}!`,
});
}
render(){
const { getFieldDecorator } = this.props.form;
const dateFormat = 'YYYY-MM-DD HH:mm:ss';
return(
<React.Fragment>
<div>
<div className="newMain clearfix">
<div className={"educontent mb20"}>
<div style={{ width:'100%',height:'70px'}} >
<p className="ml15 fl color-black mt30 summaryname">Java语言之控制语句</p>
<CoursesListType
typelist={["已开启补交"]}
typesylename={"mt28"}
/>
<a onClick={()=>this.props.history.goBack()} className="color-grey-6 fr font-16 ml20 mt18 mr20">返回</a>
<a href="/student_work?homework=16737" className="color-grey-6 fr font-16 ml30 mt18 " target={"_blank"}>实训详情</a>
</div>
<div className="stud-class-set bor-bottom-greyE">
<div className="mt10 clearfix edu-back-white poll_list pl20">
<a className="active">作业列表</a>
<a>作业描述</a>
<a>配置</a>
<a className={"fr color-blue font-16"}>立即发布</a>
<a className={"fr color-blue font-16"}>导出成绩</a>
</div>
</div>
<Form onSubmit={this.handleSubmit} className={"edu-back-white newcourses exercise"}>
{/*内容*/}
<div className="stud-class-set bor-bottom-greyE pd20 exerciselist">
<Form.Item label="发布设置" hasFeedback>
{getFieldDecorator("TestingProfile")(
<Checkbox id="TestingProfile" value={""} className="fl ml40">统一设置</Checkbox>
)}
<span className={"coursesselect"}>选中则所有分班使用相同的发布设置否则各个分班单独设置</span>
<div className={"clearfix"}>
<span className="color-grey-6 mt5 fl ml40" style={{minWidth: '70px'}}>发布时间</span>
<span className="fl mt5">
{getFieldDecorator("startTime")(
<DatePicker
showToday={false}
showTime
locale={locale}
format={dateFormat}
placeholder="请选择发布时间"
id={"startTime"}
width={"210px"}
// value={opening_time===null||opening_time===""?"":moment(opening_time, dateFormat)}
// onChange={this.onChangeTimePicker}
/>
)}
<span className={"exerciseselect"}>发布之前学生不会收到问卷</span>
</span>
</div>
<div className={"clearfix"}>
<span className="color-grey-6 mt5 fl ml40" style={{minWidth: '70px'}}>截止时间</span>
<span className="fl mt5">
{getFieldDecorator("endTime")(
<DatePicker
showToday={false}
showTime
locale={locale}
format={dateFormat}
placeholder="请选择截止时间"
id={"endTime"}
width={"210px"}
// value={opening_time===null||opening_time===""?"":moment(opening_time, dateFormat)}
// onChange={this.onChangeTimePicker}
/>
)}
<span className={"exerciseselect"}>截止时间点系统将自动提交所有学生的答题学生将不能继续答题</span>
</span>
</div>
</Form.Item>
</div>
<div className="stud-class-set bor-bottom-greyE pd20 exercisetime">
<Form.Item label="补交设置" hasFeedback>
<div className={"clearfix"}>
<span className="color-grey-6 mt5 fl ml40 font-16" style={{minWidth: '70px'}}>答题时长</span>
{getFieldDecorator("TestingProfile"
, {
rules: [{
pattern: /^[1-9]\d*$/,
message: '答题时长必须为正整数',
}],
})(
<Input id="TestingProfile" className={"greyInput mt10 mr10"} style={{width:'108px',marginLeft:'0px'}} />
)}
<span className={"mr10"}>分钟</span>
<span className={"coursesselect"}>选中则所有分班使用相同的发布设置否则各个分班单独设置</span>
</div>
</Form.Item>
<Form.Item hasFeedback>
<div className={"clearfix pd60"}>
{getFieldDecorator("subject", {
valuePropName: 'checked',
})(
<Checkbox id="subject" className="fl">题目顺序随机打乱</Checkbox>
)}
<span className={"coursesselect"}>选中则学生答题时题目顺序按照题型随机显示</span>
</div>
<div className={"clearfix pd60"}>
{getFieldDecorator("options", {
valuePropName: 'checked',
})(
<Checkbox id="options" className="fl">选项顺序随机打乱</Checkbox>
)}
<span className={"coursesselect"}>选中则学生答题时选项顺序随机显示</span>
</div>
</Form.Item>
</div>
<div className="stud-class-set pd20 coursenavbox">
<Form.Item
label="公开设置"
hasFeedback
>
<div className={"clearfix pd28"}>
{getFieldDecorator("opergrdee", {
valuePropName: 'checked',
})(
<Checkbox id="opergrdee" className="fl">公开成绩</Checkbox>
)}
<span className={"coursesselect"}>选中则在截止时间之后对提交答题的课堂成员公开所有成绩否则不公开</span>
</div>
<div className={"clearfix pd28"}>
{getFieldDecorator("openanswer", {
valuePropName: 'checked',
})(
<Checkbox id="openanswer" className="fl">公开答案</Checkbox>
)}
<span className={"coursesselect"}>选中则在截止时间之后对提交答题的课堂成员公开试卷题目的答案否则不公开</span>
</div>
<div className={"clearfix pd28"}>
{getFieldDecorator("openstatisticss", {
valuePropName: 'checked',
})(
<Checkbox id="openstatisticss" className="fl">公开统计</Checkbox>
)}
<span className={"coursesselect"}>选中则在截止时间之后对提交答题的课堂成员公开答题统计否则不公开</span>
</div>
</Form.Item>
</div>
<Form.Item wrapperCol={{ span: 12, offset: 5 }} >
<div className="clearfix mt30 mb30">
<Button type="primary" htmlType="submit" className="defalutSubmitbtn fl mr20">
提交
</Button>
{/*<a className="defalutSubmitbtn fl mr20">提交</a>*/}
<a className="defalutCancelbtn fl">取消</a>
</div>
</Form.Item>
</Form>
</div>
</div>
</div>
</React.Fragment>
)
}
}
const StudentHomeworkApp = Form.create({ name: 'coursesNew' })(StudentHomework);
export default StudentHomeworkApp;

View File

@ -5321,7 +5321,6 @@ for (const code in data) {
city2province.set(cn,pn); city2province.set(cn,pn);
} }
} }
export const locData = Array.from(province.keys()).map(p=>({ export const locData = Array.from(province.keys()).map(p=>({
value:p, value:p,
label:p, label:p,