Merge branch 'dev_aliyun' of http://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun

dev_admin
cxt 6 years ago
commit e4a28dd0ce

@ -59,4 +59,6 @@ export function toPath(path) {
}
// export default queryString
export function getTaskUrlById(id) {
return `/tasks/${id}`
}

@ -3,7 +3,8 @@ import { from } from '_array-flatten@2.1.2@array-flatten';
// export { default as OrderStateUtil } from '../routes/Order/components/OrderStateUtil';
export { getImageUrl as getImageUrl, getUrl as getUrl, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
, getUploadActionUrl as getUploadActionUrl, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth } from './UrlTool';
, getUploadActionUrl as getUploadActionUrl, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth
, getTaskUrlById as getTaskUrlById } from './UrlTool';
export { default as queryString } from './UrlTool2';
export { SnackbarHOC as SnackbarHOC } from './SnackbarHOC';

@ -604,6 +604,7 @@ class studentsList extends Component{
}
const isAdminOrTeacher = this.props.isAdminOrTeacher()
const hasGraduationModule = this.hasGraduationModule()
const coursesId = this.props.match.params.coursesId
return(
<React.Fragment>
@ -624,7 +625,10 @@ class studentsList extends Component{
></AddAdminModal>
<Titlesearchsection
title={"教师列表"}
title={<React.Fragment>
<span>教师列表</span>
{coursesId == '1309' && <span style={{color: '#848484', fontSize: '14px', marginLeft: '10px'}}>(示例课堂部分成员不可见)</span>}
</React.Fragment>}
searchValue={ searchValue }
onInputSearchChange={this.onInputSearchChange}
showSearchInput={total_count >= 10}
@ -641,6 +645,7 @@ class studentsList extends Component{
<Menu.Item key="1">已审批({total_count})</Menu.Item>
<Menu.Item key="2">待审批({apply_size})</Menu.Item>
</Menu>
{/* */}
</div> :
(!!total_count ? <ColorCountText count={total_count} name="个教师"></ColorCountText> : '')
}

@ -1,6 +1,6 @@
import React,{ Component } from "react";
import CoursesListType from '../coursesPublic/CoursesListType';
import { WordsBtn } from 'educoder';
import { WordsBtn, getTaskUrlById } from 'educoder';
import {Tooltip,message,Modal} from 'antd';
import {Link} from 'react-router-dom';
import axios from 'axios';
@ -56,7 +56,7 @@ class ShixunhomeWorkItem extends Component{
startbtn:true,
})
let url= list+".json";
const w=window.open('about:blank');
// const w=window.open('about:blank');
axios.get(url).then((response) => {
if(response.status===200){
@ -66,7 +66,7 @@ class ShixunhomeWorkItem extends Component{
shixunsreplace:true,
hidestartshixunsreplacevalue:response.data.message+".json"
})
w.close()
// w.close()
}else if(response.data.status===-1){
console.log(response)
}else if(response.data.status===-3){
@ -75,11 +75,15 @@ class ShixunhomeWorkItem extends Component{
startshixunCombattype:true,
startbtn:false
})
w.close()
// w.close()
}else{
if(response.data.status!=401&&response.data.status!=403){
w.location.href= "/tasks/"+response.data.game_identifier
}
this.setState({
startbtn:false
})
// if(response.data.status!=401&&response.data.status!=403){
// w.location.href= "/tasks/"+response.data.game_identifier
// }
window.location.href = "/tasks/"+response.data.game_identifier
}
}
@ -87,7 +91,7 @@ class ShixunhomeWorkItem extends Component{
this.setState({
startbtn:false
})
w.close()
// w.close()
});
@ -389,9 +393,15 @@ class ShixunhomeWorkItem extends Component{
{this.props.isStudent===true?this.props.course_identity===5?
<WordsBtn style="blue" className="colorblue font-16 mr20 fr mt10">
{startbtn===false?<a className="btn colorblue" onClick={()=>this.taskoperationId(discussMessage.task_operation[1])}>
{discussMessage.task_operation[0]}
</a>:<a className="btn colorblue" ></a>}
{startbtn===false?
(discussMessage.task_operation[0] == '继续挑战' || discussMessage.task_operation[0] == '查看实战' ?
<a className="btn colorblue" href={getTaskUrlById(discussMessage.task_operation[1])}>
{discussMessage.task_operation[0]}
</a>
:
<a className="btn colorblue" onClick={()=>this.taskoperationId(discussMessage.task_operation[1])}>
{discussMessage.task_operation[0]}
</a>):<a className="btn colorblue" ></a>}
</WordsBtn>:"":""
}

@ -42,6 +42,7 @@ import './ForumsIndex.css'
import './RightSection.css'
import { SnackbarHOC, getUrl } from 'educoder'
import { CNotificationHOC } from '../courses/common/CNotificationHOC'
let _url_origin = getUrl()
@ -248,7 +249,7 @@ class ForumsIndex extends Component {
}
}
export default SnackbarHOC() ( TPMIndexHOC ( ForumsIndex ) );
export default CNotificationHOC() (SnackbarHOC() ( TPMIndexHOC ( ForumsIndex ) ));
/*
:

@ -65,7 +65,7 @@ class MemoDetail extends Component {
const memo = response.data.memo
if (response.data.status === -1) {
setTimeout(() => {
this.props.showSnackbar('帖子不存在!')
this.props.showNotification('帖子不存在!')
}, 300)
this.props.history.push(`/forums`)
return;
@ -127,11 +127,11 @@ class MemoDetail extends Component {
const status = response.data.status
if (status === 0) {
this.props.showSnackbar('删除成功');
this.props.showNotification('删除成功');
this.props.history.push(`/forums`)
} else if (status === -1) {
this.props.showSnackbar('帖子已被删除');
this.props.showNotification('帖子已被删除');
this.props.history.push(`/forums`)
}
}).catch((error) => {
@ -180,18 +180,16 @@ class MemoDetail extends Component {
})
}
renderAttachment() {
const { memo } = this.props;
const { memo, attachments_list } = this.props;
const attachments = []
memo.attachment_url.forEach((item, index) => {
attachments_list.forEach((item, index) => {
const ar = item.url.split('/')
const fileName = item.filename || ar[ar.length - 1]
let filesize = 0
if (item.filesize) {
filesize = bytesToSize(item.filesize)
}
const fileName = item.title
let filesize = item.filesize
attachments.push(
<p className="clearfix" key={index} >
<a href={item.url} className="color-green clearfix notefileDownload">
<a href={item.url} className="color-green clearfix notefileDownload" target="_blank">
<i className="iconfont icon-xiazai color-green ml5 fl"></i><span className="fl">{fileName}{filesize? ` ${filesize}` : ''}</span>
</a>
</p>
@ -215,9 +213,9 @@ class MemoDetail extends Component {
}
}
replyComment = (commentContent, id, editor) => {
const { showSnackbar } = this.props;
const { showNotification } = this.props;
if (!commentContent || commentContent.length === 0) {
showSnackbar('必须填写内容!')
showNotification('必须填写内容!')
return;
}
@ -377,7 +375,7 @@ class MemoDetail extends Component {
})
}
rewardCode = (parrentComment, childComment, amount) => {
const { showSnackbar } = this.props;
const { showNotification } = this.props;
const { comments } = this.state;
let handleComment = parrentComment
if (childComment) {
@ -421,12 +419,12 @@ class MemoDetail extends Component {
}
}).catch((error) => {
console.log(error)
showSnackbar('奖励失败,请联系系统管理员!')
showNotification('奖励失败,请联系系统管理员!')
})
}
hiddenComment = (item, childCommentId) => {
const id = item.id
const { showSnackbar } = this.props;
const { showNotification } = this.props;
const user = this._getUser();
const url = `/memos/${id}/hidden.json`
const { comments } = this.state;
@ -441,7 +439,7 @@ class MemoDetail extends Component {
}
).then((response) => {
if (response.data.status === -1) {
showSnackbar(response.data.message)
showNotification(response.data.message)
return;
}
if (response.data.status === 0) {
@ -600,7 +598,7 @@ class MemoDetail extends Component {
.then((response) => {
const status = response.data.status
if (status === 0) {
this.props.showSnackbar( memo.sticky ? '取消置顶成功' : '置顶成功');
this.props.showNotification( memo.sticky ? '取消置顶成功' : '置顶成功');
memo.sticky = memo.sticky ? false : true
this.setState({
memo: Object.assign({}, memo)
@ -635,9 +633,9 @@ class MemoDetail extends Component {
this.props.initForumState({
memo: newMemo
})
this.props.showSnackbar( '奖励成功' );
this.props.showNotification( '奖励成功' );
} else {
this.props.showSnackbar( '奖励失败,请联系系统管理员!' );
this.props.showNotification( '奖励失败,请联系系统管理员!' );
}
}).catch((error) => {
console.log(error)
@ -777,7 +775,7 @@ class MemoDetail extends Component {
</p>
</div>
{ memo.attachment_url && !!memo.attachment_url.length &&
{ this.props.attachments_list &&
<div>
{this.renderAttachment()}
</div>

@ -7,17 +7,17 @@ import PropTypes from 'prop-types';
import classNames from 'classnames'
import { Select,Icon } from 'antd';
import { Select,Icon, Upload, Button } from 'antd';
// demo http://react-component.github.io/upload/examples/simple.html
import Upload from 'rc-upload';
// import Upload from 'rc-upload';
import axios from 'axios'
import 'antd/lib/select/style/index.css'
import TPMMDEditor from '../tpm/challengesnew/TPMMDEditor'
import { getUrl } from 'educoder'
import { getUrl, getUploadActionUrl, appendFileSizeToUploadFileAll, appendFileSizeToUploadFile } from 'educoder'
const Option = Select.Option;
const $ = window.$;
@ -169,14 +169,16 @@ class MemoNew extends Component {
repertoires: [],
currentSelectRepertoiresIndex: -1,
repertoiresTagMap: {}
repertoiresTagMap: {},
fileList: []
}
}
onCommit() {
const { memoSubject, memoRepertoire, memoLanguage, currentMemoId, memoType } = this.state;
const { showSnackbar } = this.props;
const { showNotification } = this.props;
if (!memoSubject) {
showSnackbar('请先输入话题名称')
showNotification('请先输入话题名称')
return
}
let mdVal;
@ -184,17 +186,17 @@ class MemoNew extends Component {
mdVal = this.mdRef.current.getValue()
} catch (e) {
showSnackbar('编辑器还未加载完毕,请稍后')
showNotification('编辑器还未加载完毕,请稍后')
return
}
if (!mdVal) {
showSnackbar('请先输入话题内容')
showNotification('请先输入话题内容')
return
}
// !memoRepertoire ||
if (memoType === 5 && ( !memoLanguage || memoLanguage.length === 0 )) {
showSnackbar('请先选择技术标签')
showNotification('请先选择技术标签')
return
}
/*
@ -207,19 +209,21 @@ class MemoNew extends Component {
// collect attachments
const $ = window.$;
const attachmentsMap = {};
const attachmentIds = []
$('#attachments_fields .attachment').each(( index, item ) => {
const filename = $(item).find('.upload_filename').val();
// $($('#attachments_fields .attachment')[0]).find('input:nth-child(6)').val()
const token = $(item).find('input:nth-child(7)').val()
const attachment_id = parseInt($(item).children().last().val())
attachmentsMap[index] = {
filename,
token,
attachment_id
}
attachmentIds.push(attachment_id)
const attachmentIds = this.state.fileList.map(item => {
return item.response ? item.response.id : item.id
})
// $('#attachments_fields .attachment').each(( index, item ) => {
// const filename = $(item).find('.upload_filename').val();
// // $($('#attachments_fields .attachment')[0]).find('input:nth-child(6)').val()
// const token = $(item).find('input:nth-child(7)').val()
// const attachment_id = parseInt($(item).children().last().val())
// attachmentsMap[index] = {
// filename,
// token,
// attachment_id
// }
// attachmentIds.push(attachment_id)
// })
if (currentMemoId) {
@ -253,7 +257,7 @@ class MemoNew extends Component {
// language: memoLanguage.join(languageSeparator),
//
// },
attachments: attachmentsMap
attachment_ids: attachmentsMap
}, {
// withCredentials: true,
})
@ -263,7 +267,7 @@ class MemoNew extends Component {
window.$("html,body").animate({"scrollTop":0})
this.props.history.push(`/forums/${currentMemoId}`)
} else {
this.props.showSnackbar(message)
this.props.showNotification(message)
}
}).catch((error) => {
console.log(error)
@ -283,7 +287,7 @@ class MemoNew extends Component {
// repertoire_name: memoRepertoire,
// },
attachments: attachmentsMap
attachment_ids: attachmentsMap
}, {
// withCredentials: true,
})
@ -293,7 +297,7 @@ class MemoNew extends Component {
window.$("html,body").animate({"scrollTop":0})
this.props.history.push(`/forums/${memo_id}`)
} else {
this.props.showSnackbar(message)
this.props.showNotification(message)
}
}).catch((error) => {
console.log(error)
@ -349,7 +353,7 @@ class MemoNew extends Component {
if (tag_list) {
// this.setState({...response.data})
const { content, forum_id, id, repertoire_name, subject,
current_user, tag_list, attachments_url, memo_tags } = response.data;
current_user, tag_list, attachments_url, memo_tags, attachments } = response.data;
this.initMD(content);
// this.onRepertoiresChange(repertoire_name)
// tag -> memo_tags
@ -360,7 +364,18 @@ class MemoNew extends Component {
return item.id + ""
})
}
const fileList = attachments.map(item => {
return {
id: item.id,
uid: item.id,
name: appendFileSizeToUploadFile(item),
url: item.url,
filesize: item.filesize,
status: 'done'
}
})
this.setState({
fileList,
currentMemoId: memoId,
memoSubject: subject,
memoType: forum_id,
@ -466,7 +481,7 @@ class MemoNew extends Component {
onTagChange(value) {
if (value && value.length > 3) {
this.props.showSnackbar(`最多选择3个技术标签`)
this.props.showNotification(`最多选择3个技术标签`)
return;
}
@ -531,6 +546,55 @@ class MemoNew extends Component {
)
})
return attachments;
}
handleChange = (info) => {
let fileList = info.fileList;
this.setState({
fileList: appendFileSizeToUploadFileAll(fileList)
});
}
onAttachmentRemove = (file) => {
this.props.confirm({
// title: '确定要删除这个附件吗?',
content: '是否确认删除?',
okText: '确定',
cancelText: '取消',
// content: 'Some descriptions',
onOk: () => {
this.deleteAttachment(file)
},
onCancel() {
console.log('Cancel');
},
});
return false;
}
deleteAttachment = (file) => {
// 初次上传不能直接取uid
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
axios.delete(url, {
})
.then((response) => {
if (response.data) {
const { status } = response.data;
if (status == 0) {
console.log('--- success')
this.setState((state) => {
const index = state.fileList.indexOf(file);
const newFileList = state.fileList.slice();
newFileList.splice(index, 1);
return {
fileList: newFileList,
};
});
}
}
})
.catch(function (error) {
console.log(error);
});
}
render() {
const { match, history } = this.props
@ -538,8 +602,28 @@ class MemoNew extends Component {
// repertoires, repertoiresTagMap, currentSelectRepertoiresIndex, memoRepertoire,
tag_list,
memoSubject, memoType,
memoLanguage, attachments_url } = this.state;
memoLanguage, attachments_url, fileList } = this.state;
const memoId = match.params.memoId;
const uploadProps = {
width: 600,
fileList,
multiple: true,
// https://github.com/ant-design/ant-design/issues/15505
// showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。
// showUploadList: false,
action: `${getUploadActionUrl()}`,
onChange: this.handleChange,
onRemove: this.onAttachmentRemove,
beforeUpload: (file) => {
console.log('beforeUpload', file.name);
const isLt150M = file.size / 1024 / 1024 < 150;
if (!isLt150M) {
// message.error('文件大小必须小于150MB!');
}
return isLt150M;
},
};
return (
<div >
<div className="pt20 pl20 pr20 pb20 bor-bottom-greyE clearfix" style={{background: '#fff'}}>
@ -592,13 +676,13 @@ class MemoNew extends Component {
<form className="newForm">
{/* <form className="newForm">
<span id={`attachments_fields`} className="attachments_fields"
xmlns="http://www.w3.org/1999/html">
{ attachments_url && !!attachments_url.length &&
this.renderAttachment()
}
</span>
</span>
<span className="add_attachment">
<input className="file_selector" data-are-you-sure="您确定要删除吗?"
data-delete-all-files="您确定要删除所有文件吗" data-description-placeholder="可选的描述"
@ -610,19 +694,39 @@ class MemoNew extends Component {
onChange={()=>{debugger;window.addInputFiles( window.$('.file_selector')[0] ) }}
style={{'display':'none'}} type="file">
</input>
</span>
</form>
</span>
</form>*/}
<style>{`
.memo_upload.upload_1 {
margin-left: 36px;
}
.memo_upload.upload_1 .ant-upload-list {
margin-left: 30px;
}
.memo_upload.upload_1 .ant-upload-list-item-info .anticon-paper-clip {
top: 4px;
}
`}</style>
{/*<Upload {...this.uploaderProps} ref="inner"><a>开始上传</a></Upload>*/}
<Upload {...uploadProps} className="upload_1 memo_upload" >
<Button className="uploadBtn">
<Icon type="upload" /> 上传附件
</Button>
(单个文件150M以内)
</Upload>
{/* 请求status 422 */}
<div className="df uploadBtn">
{/* <Icon type="upload" ></Icon> */}
{/* <div className="df uploadBtn">
<a href="javascript:void(0);" className="fl" onClick={()=>window.$('#_file').click()}
data-tip-down="请选择文件上传">
<i className="fa fa-upload mr5 color-blue"></i>
<span className="color-blue"> <Icon type="upload" > 上传附件</Icon></span><span style={{color: '#CDCDCD', fontSize: "14px"}}>(50M)</span>
<span className="color-blue"> 上传附件
</span><span style={{color: '#CDCDCD', fontSize: "14px"}}>(50M)</span>
</a>
</div>
</div> */}
</div>
</div>
{/* TODOTODO 这里重复的html代码太多如果有其他页面有类似需求需要封装*/}

@ -276,7 +276,7 @@ return function wrap(WrappedComponent) {
const status = response.data.status
if (status === 0) {
this.props.showSnackbar('删除成功');
this.props.showNotification('删除成功');
// 刷新列表
this.fetchMemos();
}

@ -1313,7 +1313,7 @@ export default class TPMsettings extends Component {
</div>
<div className="task-popup-submit clearfix">
<a onClick={this.hideoperateshixuns} className="task-btn fl">取消</a>
{delType===2?<a className="task-btn task-btn-orange fr" onClick={this.shixunsdel}>确定</a>:<a className="task-btn task-btn-orange fr" onClick={this.shixunsclose}></a>}
{delType===1?<a className="task-btn task-btn-orange fr" onClick={this.shixunsdel}>确定</a>:<a className="task-btn task-btn-orange fr" onClick={this.shixunsclose}></a>}
</div>
</Modal>

@ -164,11 +164,14 @@ class InfosPath extends Component{
<a href="javascript:void(0)" className="square-img"><img alt="Subject12" src={getImageUrl(`${item.image_url}`)}/></a>
<div className="square-main">
<p className="task-hide">
<a href="javascript:void(0)" className="justify color-grey-name">{item.name}</a>
<a href="javascript:void(0)" className="justify color-grey-name "
>{item.name}</a>
</p>
<div className="mt10">
<p className="color-grey-6 clearfix">
<a href="javascript:void(0)" className="fl color-grey-9">{item.owner_name}</a>
<a href="javascript:void(0)" className="fl color-grey-9 overflowHidden1"
title={item.owner_name.length > 12 ? item.owner_name : ''} style={{ maxWidth: '198px'}}
>{item.owner_name}</a>
<span className="fr squareIconSpan">
<Tooltip placement='bottom' title="访问量">
<i className="iconfont icon-liulanyan fl mr5"></i>

Loading…
Cancel
Save