Merge branch 'dev_hjm' into dev_aliyun

# Conflicts:
#	public/react/src/App.js
#	public/react/src/modules/forums/UserSection.js
dev_cs_new
hjm 6 years ago
commit 96126fd7dd

@ -351,8 +351,13 @@ class App extends Component {
{/*课堂*/} {/*课堂*/}
<Route path="/courses" component={CoursesIndex} {...this.props}></Route> <Route path="/courses" component={CoursesIndex} {...this.props}></Route>
{/* <Route path="/forums" component={ForumsIndexComponent}>
</Route> */} <Route path="/forums"
render={
(props)=>(<ForumsIndexComponent {...this.props} {...props} {...this.state}></ForumsIndexComponent>)
}
>
</Route>
<Route path="/comment" component={CommentComponent}/> <Route path="/comment" component={CommentComponent}/>
<Route path="/testMaterial" component={TestMaterialDesignComponent}/> <Route path="/testMaterial" component={TestMaterialDesignComponent}/>

@ -57,7 +57,7 @@ class SchoolSelect extends Component{
const { value, onChange } = this.props; const { value, onChange } = this.props;
return ( return (
<AutoComplete allowClear placeholder="请输入单位名称" value={value} <AutoComplete allowClear placeholder="请输入单位名称" value={value}
style={{ width: '200px'}} style={{ width: '221px'}}
onSearch={this.onOrgNameSearch} onSearch={this.onOrgNameSearch}
onSelect={onChange} onSelect={onChange}
onChange={onChange} onChange={onChange}

@ -195,7 +195,7 @@ class AddStudentModal extends Component{
<div className="df"> <div className="df">
<span className="mr10">姓名:</span> <span className="mr10">姓名:</span>
<Input allowClear placeholder="请输入真实姓名" value={name} onChange={(e) => {this.setState({name: e.target.value})}} <Input allowClear placeholder="请输入真实姓名" value={name} onChange={(e) => {this.setState({name: e.target.value})}}
style={{ width: '242px'}} style={{ width: '221px'}}
></Input> ></Input>
<span className="label" style={{ minWidth: '36px' }}>单位:</span> <span className="label" style={{ minWidth: '36px' }}>单位:</span>
{/* <Input allowClear placeholder="" value={school_name} onChange={(e) => {this.setState({school_name: e.target.value})}} {/* <Input allowClear placeholder="" value={school_name} onChange={(e) => {this.setState({school_name: e.target.value})}}
@ -210,14 +210,7 @@ class AddStudentModal extends Component{
>搜索</a> >搜索</a>
</div> </div>
{/* <Divider /> */} {/* <Divider /> */}
{course_groups && course_groups.length && <div className="df" style={{ marginTop: '24px' }} >
<span className="mr10">分班:</span>
<Select style={{ width:500 }} onChange={this.handleCourseGroupChange} value={courseGroup}>
{ course_groups.map((item) => {
return <Option value={item.id}>{item.name}</Option>
})}
</Select>
</div>}
<p className="clearfix mb2" style={{ margin: '0px 15px 6px' }}> <p className="clearfix mb2" style={{ margin: '0px 15px 6px' }}>
<Checkbox className="fl" style={{ visibility: 'hidden' }} ></Checkbox> <Checkbox className="fl" style={{ visibility: 'hidden' }} ></Checkbox>
@ -247,7 +240,12 @@ class AddStudentModal extends Component{
<Checkbox className="fl" value={candidate.id} disabled={candidate.added}></Checkbox> <Checkbox className="fl" value={candidate.id} disabled={candidate.added}></Checkbox>
<span className="fl with25"> <span className="fl with25">
<ConditionToolTip title={candidate.name} condition={candidate.name && candidate.name.length > 12 }> <ConditionToolTip title={candidate.name} condition={candidate.name && candidate.name.length > 12 }>
<label className="task-hide fl" style={{"maxWidth":"208px;"}}>{candidate.name || ' '}</label> <label className="task-hide fl" style={{"maxWidth":"208px;"}}>
{ candidate.name ?
<a href={`/users/${candidate.login}`} target="_blank">
{ candidate.name }
</a> : <span> </span> }
</label>
</ConditionToolTip> </ConditionToolTip>
</span> </span>
<span className="fl with25"> <span className="fl with25">
@ -271,6 +269,14 @@ class AddStudentModal extends Component{
</InfiniteScroll> </InfiniteScroll>
</div> </div>
{course_groups && course_groups.length && <div className="df" style={{ marginTop: '12px' }} >
<span className="mr10" style={{ width: '148px' }}>所选学生分班至(选填):</span>
<Select style={{ width: 236 }} onChange={this.handleCourseGroupChange} value={courseGroup}>
{ course_groups.map((item) => {
return <Option value={item.id}>{item.name}</Option>
})}
</Select>
</div>}
</div> : <NoneData></NoneData> } </div> : <NoneData></NoneData> }
</Spin> </Spin>
</ModalWrapper> </ModalWrapper>

@ -5,6 +5,9 @@
.discuss-tab { .discuss-tab {
height: 90px; height: 90px;
} }
.discuss-tab ._forum_tab a.navItem {
line-height: 2;
}
.discuss-tab ._forum_tab a.navItem:hover { .discuss-tab ._forum_tab a.navItem:hover {
color: #4CACFF !important; color: #4CACFF !important;
border-bottom: none !important; border-bottom: none !important;

@ -44,7 +44,7 @@ class MemoDetail extends Component {
this.state = { this.state = {
memoLoading: true, memoLoading: true,
hasMoreComments: false, hasMoreComments: false,
pageCount: 1, pageCount: 2,
goldRewardDialogOpen: false goldRewardDialogOpen: false
} }
@ -54,12 +54,12 @@ class MemoDetail extends Component {
const { match } = this.props const { match } = this.props
const memoUrl = `/api/v1/memos/${match.params.memoId}`; const memoUrl = `/memos/${match.params.memoId}.json`;
this.setState({ this.setState({
memoLoading: true memoLoading: true
}) })
axios.get(memoUrl,{ axios.get(memoUrl,{
withCredentials: true, // withCredentials: true,
}) })
.then((response) => { .then((response) => {
const memo = response.data.memo const memo = response.data.memo
@ -86,14 +86,16 @@ class MemoDetail extends Component {
} }
this.setState({ this.setState({
hasMoreComments, hasMoreComments,
pageCount: 1, pageCount: 2,
comments: memo_replies comments: memo_replies
}) })
delete response.data.memo_replies; delete response.data.memo_replies;
// reset
response.data.memo.praise_count = response.data.memo.memo_praise_count
this.props.initForumState(response.data) this.props.initForumState(response.data)
const user = response.data.current_user; // const user = response.data.current_user;
user.tidding_count = response.data.tidding_count; // user.tidding_count = response.data.tidding_count;
this.props.initCommonState(user) // this.props.initCommonState(user)
} }
this.setState({ this.setState({
memoLoading: false memoLoading: false
@ -116,10 +118,10 @@ class MemoDetail extends Component {
$('body>#root').off('onMemoDelete') $('body>#root').off('onMemoDelete')
} }
onMemoDelete(memo) { onMemoDelete(memo) {
const deleteUrl = `/api/v1/memos/${memo.id}`; const deleteUrl = `/memos/${memo.id}.json`;
// 获取memo list // 获取memo list
axios.delete(deleteUrl, { axios.delete(deleteUrl, {
withCredentials: true, // withCredentials: true,
}) })
.then((response) => { .then((response) => {
const status = response.data.status const status = response.data.status
@ -158,14 +160,14 @@ class MemoDetail extends Component {
clickPraise(){ clickPraise(){
const { memo } = this.props; const { memo } = this.props;
const url = `/api/v1/discusses/${memo.id}/plus`; const url = `/discusses/${memo.id}/plus.json`;
console.log(url) console.log(url)
axios.post(url, { axios.post(url, {
container_type: 'Memo', container_type: 'Memo',
type: 1 // "踩0赞1" type: 1 // "踩0赞1"
}, },
{ {
withCredentials: true // withCredentials: true
} }
).then((response) => { ).then((response) => {
console.log(response); console.log(response);
@ -223,7 +225,8 @@ class MemoDetail extends Component {
this.createNewComment(commentContent, id, editor); this.createNewComment(commentContent, id, editor);
return; return;
} }
const url = `/api/v1/memos/${id}/reply`; // /${id}
const url = `/memos/reply.json`;
const { comments } = this.state; const { comments } = this.state;
const user = this._getUser(); const user = this._getUser();
/* /*
@ -235,12 +238,14 @@ class MemoDetail extends Component {
commentContent = commentContent.replace(/(\n<p>\n\t<br \/>\n<\/p>)*$/g,''); commentContent = commentContent.replace(/(\n<p>\n\t<br \/>\n<\/p>)*$/g,'');
} }
axios.post(url, { axios.post(url, {
parent_id: id,
content: commentContent content: commentContent
}, },
{ {
withCredentials: true // withCredentials: true
} }
).then((response) => { ).then((response) => {
response.data.memo = response.data
if (response.data.memo) { if (response.data.memo) {
let newDiscuss = response.data.memo; let newDiscuss = response.data.memo;
@ -303,12 +308,12 @@ class MemoDetail extends Component {
if (childCommentId) { if (childCommentId) {
deleteCommentId = childCommentId; deleteCommentId = childCommentId;
} }
const url = `/api/v1/memos/${deleteCommentId}` const url = `/memos/${deleteCommentId}.json`
let comments = this.state.comments; let comments = this.state.comments;
axios.delete(url, axios.delete(url,
{ {
withCredentials: true // withCredentials: true
} }
).then((response) => { ).then((response) => {
// TODO 删除成功或失败 // TODO 删除成功或失败
@ -346,7 +351,7 @@ class MemoDetail extends Component {
const { comments } = this.state; const { comments } = this.state;
const commentIndex = this._findById(discussId, comments); const commentIndex = this._findById(discussId, comments);
const url = `/api/v1/discusses/${discussId}/plus` const url = `/discusses/${discussId}/plus.json`
axios.post(url, { axios.post(url, {
// id: discussId, // id: discussId,
// container_id: challenge.id, // container_id: challenge.id,
@ -354,7 +359,7 @@ class MemoDetail extends Component {
type: comments[commentIndex].user_praise === true ? 0 : 1, // "踩0赞1" type: comments[commentIndex].user_praise === true ? 0 : 1, // "踩0赞1"
}, },
{ {
withCredentials: true // withCredentials: true
} }
).then((response) => { ).then((response) => {
if (response.data.praise_count === 0 || response.data.praise_count) { if (response.data.praise_count === 0 || response.data.praise_count) {
@ -379,7 +384,7 @@ class MemoDetail extends Component {
handleComment = childComment; handleComment = childComment;
} }
let handleCommentId = handleComment.id; let handleCommentId = handleComment.id;
const url = `/api/v1/discusses/${handleCommentId}/reward_code` const url = `/discusses/${handleCommentId}/reward_code.json`
axios.post(url, { axios.post(url, {
id: handleCommentId, id: handleCommentId,
@ -389,7 +394,7 @@ class MemoDetail extends Component {
user_id: handleComment.user_id user_id: handleComment.user_id
}, },
{ {
withCredentials: true // withCredentials: true
} }
).then((response) => { ).then((response) => {
if (response.data && response.data.code) { if (response.data && response.data.code) {
@ -423,7 +428,7 @@ class MemoDetail extends Component {
const id = item.id const id = item.id
const { showSnackbar } = this.props; const { showSnackbar } = this.props;
const user = this._getUser(); const user = this._getUser();
const url = `/api/v1/memos/${id}/hidden` const url = `/memos/${id}/hidden.json`
const { comments } = this.state; const { comments } = this.state;
const commentIndex = this._findById(id, comments); const commentIndex = this._findById(id, comments);
@ -432,14 +437,14 @@ class MemoDetail extends Component {
hidden: !comment.hidden ? "1" : "0" hidden: !comment.hidden ? "1" : "0"
}, },
{ {
withCredentials: true // withCredentials: true
} }
).then((response) => { ).then((response) => {
if (response.data.status === -1) { if (response.data.status === -1) {
showSnackbar(response.data.message) showSnackbar(response.data.message)
return; return;
} }
if (response.data.status === 1) { if (response.data.status === 0) {
if (!childCommentId) { if (!childCommentId) {
comment.hidden = !comment.hidden; comment.hidden = !comment.hidden;
@ -473,14 +478,16 @@ class MemoDetail extends Component {
return; return;
} }
} }
const url = `/api/v1/memos/${memo.id}/reply`; // /${memo.id}
const url = `/memos/reply.json`;
let { comments } = this.state; let { comments } = this.state;
const user = this._getUser(); const user = this._getUser();
axios.post(url, { axios.post(url, {
parent_id: memo.id,
content: content content: content
}, },
{ {
withCredentials: true // withCredentials: true
} }
).then((response) => { ).then((response) => {
if (response.data.status === -1) { if (response.data.status === -1) {
@ -488,6 +495,7 @@ class MemoDetail extends Component {
return; return;
} }
if (response.data) { if (response.data) {
response.data.memo = response.data
const newMemo = response.data.memo; const newMemo = response.data.memo;
// ke // ke
editor.html && editor.html(''); editor.html && editor.html('');
@ -536,12 +544,12 @@ class MemoDetail extends Component {
let { comments, pageCount } = this.state; let { comments, pageCount } = this.state;
let { memo } = this.props; let { memo } = this.props;
const user = this._getUser(); const user = this._getUser();
const url = `/api/v1/memos/${memo.id}/more_reply?page=${pageCount}`; const url = `/memos/${memo.id}/more_reply.json?page=${pageCount}`;
axios.get(url, { axios.get(url, {
}, },
{ {
withCredentials: true // withCredentials: true
} }
).then((response) => { ).then((response) => {
if (response.data.status === -1) { if (response.data.status === -1) {
@ -584,10 +592,10 @@ class MemoDetail extends Component {
params.forum_id = this.state.p_forum_id; params.forum_id = this.state.p_forum_id;
} }
let paramsUrl = urlStringify(params) let paramsUrl = urlStringify(params)
const set_top_or_down_Url = `/api/v1/memos/${memo.id}/set-top-or-down?${paramsUrl}`; const set_top_or_down_Url = `/memos/${memo.id}/sticky_or_cancel.json?${paramsUrl}`;
// 获取memo list // 获取memo list
axios.get(set_top_or_down_Url, { axios.post(set_top_or_down_Url, {
withCredentials: true, // withCredentials: true,
}) })
.then((response) => { .then((response) => {
const status = response.data.status const status = response.data.status
@ -608,9 +616,8 @@ class MemoDetail extends Component {
const { memo, author_info } = this.props; const { memo, author_info } = this.props;
const newMemo = Object.assign({}, memo); const newMemo = Object.assign({}, memo);
const _reward = parseInt(inputVal) const _reward = parseInt(inputVal)
const newMemoUrl = `/api/v1/memos/${memo.id}/update`
const url = `/api/v1/discusses/${memo.id}/reward_code` const url = `/discusses/${memo.id}/reward_code.json`
axios.post(url, { axios.post(url, {
id: memo.id, id: memo.id,
@ -619,7 +626,7 @@ class MemoDetail extends Component {
score: _reward, score: _reward,
user_id: author_info.user_id user_id: author_info.user_id
}, { }, {
withCredentials: true, // withCredentials: true,
}) })
.then((response) => { .then((response) => {
const { code } = response.data; const { code } = response.data;
@ -659,14 +666,24 @@ class MemoDetail extends Component {
const { memo, recommend_shixun, current_user,author_info } = this.props; const { memo, recommend_shixun, current_user,author_info } = this.props;
const { comments, hasMoreComments, goldRewardDialogOpen } = this.state; const { comments, hasMoreComments, goldRewardDialogOpen } = this.state;
if (this.state.memoLoading) { if (!memo || this.state.memoLoading) {
return <div className="edu-back-white" id="forum_index_list"></div> return <div className="edu-back-white" id="forum_index_list"></div>
} }
current_user.user_url = `/users/${current_user.login}`; let _current_user = {}
if (current_user) {
_current_user = current_user
}
(_current_user.user_url = `/users/${_current_user.login}`);
memo.isDetailPage = true; memo.isDetailPage = true;
// TODO 图片上传地址 // TODO 图片上传地址
return ( return (
<div className="edu-back-white" id="forum_index_list"> {/* fl with100 */} <div className="edu-back-white memoDetail" id="forum_index_list"> {/* fl with100 */}
<style>{`
.memoDetail .commentsbtn {
margin-top: 6px;
}
`}</style>
<RewardDialog goldRewardDialogOpen={goldRewardDialogOpen} <RewardDialog goldRewardDialogOpen={goldRewardDialogOpen}
setRewardDialogVisible={this.setRewardDialogVisible} setRewardDialogVisible={this.setRewardDialogVisible}
rewardCode={this.rewardCodeMemo} rewardCode={this.rewardCodeMemo}
@ -681,11 +698,11 @@ class MemoDetail extends Component {
data-tip-down={`获得平台奖励金币:${memo.reward}`} > data-tip-down={`获得平台奖励金币:${memo.reward}`} >
<i className="iconfont icon-gift mr5"></i>{memo.reward} <i className="iconfont icon-gift mr5"></i>{memo.reward}
</span> } </span> }
{ current_user && (current_user.admin === true || current_user.user_id === author_info.user_id) && { _current_user && (_current_user.admin === true || _current_user.user_id === author_info.user_id) &&
<div className="edu-position-hidebox" style={{position: 'absolute', right: '18px',top:'4px'}}> <div className="edu-position-hidebox" style={{position: 'absolute', right: '12px',top:'4px'}}>
<a href="javascript:void(0);"><i className="fa fa-bars font-16"></i></a> <a href="javascript:void(0);"><i className="fa fa-bars font-16"></i></a>
<ul className="edu-position-hide undis"> <ul className="edu-position-hide undis">
{ current_user.admin === true && { _current_user.admin === true &&
( memo.sticky === true ? ( memo.sticky === true ?
<li><a href="javascript:void(0);" onClick={() => this.setTop(memo)}>取消置顶</a></li> <li><a href="javascript:void(0);" onClick={() => this.setTop(memo)}>取消置顶</a></li>
: :
@ -701,15 +718,22 @@ class MemoDetail extends Component {
</ul> </ul>
</div> </div>
} }
<Link className={`task-hide fr return_btn color-grey-6 mt2 ${ current_user && (current_user.admin === true <Link className={`task-hide fr return_btn color-grey-6 mt2 ${ _current_user && (_current_user.admin === true
|| current_user.user_id === author_info.user_id) ? '': 'no_mr'} `} to="/forums" > || _current_user.user_id === author_info.user_id) ? '': 'no_mr'} `} to="/forums"
style={{ marginRight: '10px'}}
>
返回 返回
</Link> </Link>
</div> </div>
<div className="color-grey-9 clearfix"> <div className="color-grey-9 clearfix">
<span className="fl">{moment(memo.time).fromNow()} 发布</span> <span className="fl">{moment(memo.time).fromNow()} 发布</span>
<div className="fr"> <div className="fr detailIcons">
{ current_user.admin && <Tooltip title={ "帖子奖励" }> <style>{`
.detailIcons i{
vertical-align: sub;
}
`}</style>
{ _current_user.admin && <Tooltip title={ "帖子奖励" }>
<span className="noteDetailNum rightline cdefault" style={{padding: '0 4px', cursor: 'pointer'}}> <span className="noteDetailNum rightline cdefault" style={{padding: '0 4px', cursor: 'pointer'}}>
<i className="iconfont icon-jiangli mr5" onClick={this.showRewardDialog}></i> <i className="iconfont icon-jiangli mr5" onClick={this.showRewardDialog}></i>
</span> </span>
@ -770,7 +794,7 @@ class MemoDetail extends Component {
<span className="count">{memo.replies_count}</span> <span className="count">{memo.replies_count}</span>
</div> </div>
<Comments comments={comments} user={current_user} <Comments comments={comments} user={_current_user}
replyComment={this.replyComment} replyComment={this.replyComment}
deleteComment={this.deleteComment} deleteComment={this.deleteComment}
commentPraise={this.commentPraise} commentPraise={this.commentPraise}

@ -42,7 +42,7 @@ class MemoDetailMDEditor extends Component {
window.__tt = 400; window.__tt = 400;
setTimeout(() => { setTimeout(() => {
var commentMDEditor = window.create_editorMD_4comment("memo_comment_editorMd", '', this.props.height || 240, placeholder, imageUrl, () => { var commentMDEditor = window.create_editorMD_4comment("memo_comment_editorMd", '', this.props.height || 240, placeholder, imageUrl, () => {
commentMDEditor.focus() // commentMDEditor.focus()
this.isMDInited = true this.isMDInited = true
this.initDrag() this.initDrag()

@ -15,6 +15,7 @@ import Upload from 'rc-upload';
import axios from 'axios' import axios from 'axios'
import 'antd/lib/select/style/index.css' import 'antd/lib/select/style/index.css'
import TPMMDEditor from '../tpm/challengesnew/TPMMDEditor'
import { getUrl } from 'educoder' import { getUrl } from 'educoder'
const Option = Select.Option; const Option = Select.Option;
@ -130,6 +131,7 @@ const languageSeparator = '/'
class MemoNew extends Component { class MemoNew extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.mdRef = React.createRef();
// https://testbdweb.trustie.net/uploads.js?attachment_id=1&filename=jqui.js // https://testbdweb.trustie.net/uploads.js?attachment_id=1&filename=jqui.js
// https://ant.design/components/upload-cn/ // https://ant.design/components/upload-cn/
@ -179,7 +181,7 @@ class MemoNew extends Component {
} }
let mdVal; let mdVal;
try { try {
mdVal = this.taskpass_editormd.getValue() mdVal = this.mdRef.current.getValue()
} catch (e) { } catch (e) {
showSnackbar('编辑器还未加载完毕,请稍后') showSnackbar('编辑器还未加载完毕,请稍后')
@ -205,6 +207,7 @@ class MemoNew extends Component {
// collect attachments // collect attachments
const $ = window.$; const $ = window.$;
const attachmentsMap = {}; const attachmentsMap = {};
const attachmentIds = []
$('#attachments_fields .attachment').each(( index, item ) => { $('#attachments_fields .attachment').each(( index, item ) => {
const filename = $(item).find('.upload_filename').val(); const filename = $(item).find('.upload_filename').val();
// $($('#attachments_fields .attachment')[0]).find('input:nth-child(6)').val() // $($('#attachments_fields .attachment')[0]).find('input:nth-child(6)').val()
@ -215,13 +218,14 @@ class MemoNew extends Component {
token, token,
attachment_id attachment_id
} }
attachmentIds.push(attachment_id)
}) })
if (currentMemoId) { if (currentMemoId) {
this.updateMemo(attachmentsMap) this.updateMemo(attachmentIds)
} else { } else {
this.newMemo(attachmentsMap) this.newMemo(attachmentIds)
} }
} }
onCancel() { onCancel() {
@ -235,23 +239,23 @@ class MemoNew extends Component {
} }
updateMemo(attachmentsMap) { updateMemo(attachmentsMap) {
const { memoSubject, memoRepertoire, memoLanguage, memoType, currentMemoId, content } = this.state; const { memoSubject, memoRepertoire, memoLanguage, memoType, currentMemoId, content } = this.state;
const mdVal = this.taskpass_editormd.getValue() const mdVal = this.mdRef.current.getValue()
console.log('isContentEdit: ', mdVal === content); console.log('isContentEdit: ', mdVal === content);
const newMemoUrl = `/api/v1/memos/${currentMemoId}/update` const newMemoUrl = `/memos/${currentMemoId}.json`
axios.post(newMemoUrl, { axios.put(newMemoUrl, {
content_changed: this.contentChanged, content_changed: this.contentChanged,
tags: memoLanguage, tags: memoLanguage,
memo:{ // memo:{
subject: memoSubject , subject: memoSubject ,
content: mdVal, content: mdVal,
forum_id: memoType, forum_id: memoType,
repertoire_name: memoRepertoire, repertoire_name: memoRepertoire,
// language: memoLanguage.join(languageSeparator), // language: memoLanguage.join(languageSeparator),
// //
}, // },
attachments: attachmentsMap attachments: attachmentsMap
}, { }, {
withCredentials: true, // withCredentials: true,
}) })
.then((response) => { .then((response) => {
const { status, message, memo_id } = response.data; const { status, message, memo_id } = response.data;
@ -267,21 +271,21 @@ class MemoNew extends Component {
} }
newMemo(attachmentsMap) { newMemo(attachmentsMap) {
const { memoSubject, memoRepertoire, memoLanguage, memoType } = this.state; const { memoSubject, memoRepertoire, memoLanguage, memoType } = this.state;
const mdVal = this.taskpass_editormd.getValue() const mdVal = this.mdRef.current.getValue()
const newMemoUrl = `/api/v1/memos/create` const newMemoUrl = `/memos.json`
axios.post(newMemoUrl, { axios.post(newMemoUrl, {
tags: memoLanguage, tags: memoLanguage,
memo:{ // memo:{
subject: memoSubject , subject: memoSubject ,
content: mdVal, content: mdVal,
forum_id: memoType, forum_id: memoType,
repertoire_name: memoRepertoire, // repertoire_name: memoRepertoire,
}, // },
attachments: attachmentsMap attachments: attachmentsMap
}, { }, {
withCredentials: true, // withCredentials: true,
}) })
.then((response) => { .then((response) => {
const { status, message, memo_id } = response.data; const { status, message, memo_id } = response.data;
@ -296,9 +300,9 @@ class MemoNew extends Component {
}) })
} }
componentDidMount() { componentDidMount() {
const newMemoUrl = `/api/v1/memos/new` const newMemoUrl = `/memos/new.json`
axios.get(newMemoUrl,{ axios.get(newMemoUrl,{
withCredentials: true, // withCredentials: true,
}) })
.then((response) => { .then((response) => {
const data = response.data; const data = response.data;
@ -319,9 +323,9 @@ class MemoNew extends Component {
// repertoiresTagMap // repertoiresTagMap
}) })
const user = response.data.current_user; // const user = response.data.current_user;
user.tidding_count = response.data.tidding_count; // user.tidding_count = response.data.tidding_count;
this.props.initCommonState(user) // this.props.initCommonState(user)
// 初始化 csrf meta // 初始化 csrf meta
const $ = window.$ const $ = window.$
@ -336,18 +340,20 @@ class MemoNew extends Component {
const { match } = this.props const { match } = this.props
const memoId = match.params.memoId; const memoId = match.params.memoId;
if (memoId) { if (memoId) {
const memoUrl = `/api/v1/memos/${match.params.memoId}/edit`; const memoUrl = `/memos/${match.params.memoId}/edit.json`;
axios.get(memoUrl,{ axios.get(memoUrl,{
withCredentials: true, // withCredentials: true,
}) })
.then((response) => { .then((response) => {
const tag_list = response.data.tag_list const tag_list = response.data.tag_list
if (tag_list) { if (tag_list) {
// this.setState({...response.data}) // this.setState({...response.data})
const { content, forum_id, id, tag, repertoire_name, subject, const { content, forum_id, id, repertoire_name, subject,
current_user, tag_list, attachments_url } = response.data; current_user, tag_list, attachments_url, memo_tags } = response.data;
this.initMD(content); this.initMD(content);
// this.onRepertoiresChange(repertoire_name) // this.onRepertoiresChange(repertoire_name)
// tag -> memo_tags
const tag = memo_tags;
let memoLanguage = [] let memoLanguage = []
if (tag) { if (tag) {
memoLanguage = tag.map((item, index) => { memoLanguage = tag.map((item, index) => {
@ -355,7 +361,7 @@ class MemoNew extends Component {
}) })
} }
this.setState({ this.setState({
currentMemoId: id, currentMemoId: memoId,
memoSubject: subject, memoSubject: subject,
memoType: forum_id, memoType: forum_id,
memoRepertoire: repertoire_name, memoRepertoire: repertoire_name,
@ -377,7 +383,7 @@ class MemoNew extends Component {
window.$("html,body").animate({"scrollTop":0}) window.$("html,body").animate({"scrollTop":0})
this.props.initForumState({ this.props.initForumState({
current_user, // current_user,
tag_list tag_list
}) })
} }
@ -394,6 +400,8 @@ class MemoNew extends Component {
} }
initMD(initValue) { initMD(initValue) {
return;
this.contentChanged = false; this.contentChanged = false;
const placeholder = ""; const placeholder = "";
// amp; // amp;
@ -566,9 +574,12 @@ class MemoNew extends Component {
<div className="df"> <div className="df">
<span className="mr30 color-orange pt10">*</span> <span className="mr30 color-orange pt10">*</span>
<div className="flex1 mr20"> <div className="flex1 mr20">
<div className="flex1 break_word show_content_grey new_li" id="memoMD"> <TPMMDEditor ref={this.mdRef} placeholder={''} watch={false}
mdID={'memoMD'} initValue={this.state.content} className="memoMD">
</TPMMDEditor>
{/* <div className="flex1 break_word show_content_grey new_li" id="memoMD">
<textarea style={{'display':'none'}}></textarea> <textarea style={{'display':'none'}}></textarea>
</div> </div> */}
<p id="e_tip_memoNew" className="edu-txt-right color-grey-cd font-12"></p> <p id="e_tip_memoNew" className="edu-txt-right color-grey-cd font-12"></p>
<p id="e_tips_memoNew" className="edu-txt-right color-grey-cd font-12"></p> <p id="e_tips_memoNew" className="edu-txt-right color-grey-cd font-12"></p>
</div> </div>

@ -8,6 +8,9 @@
min-height: 400px; min-height: 400px;
position: relative; position: relative;
} }
#forum_index_list .forum_table .forum_table_item {
background: #fff;
}
.noMemosTip { .noMemosTip {
position: absolute; position: absolute;
right: 10px; right: 10px;

@ -29,7 +29,7 @@ class PostItem extends Component {
<img alt="用户头像" className="bor-radius-all mt3" height="50" src={getImageUrl(`images/`+memo.image_url)} width="50" /> <img alt="用户头像" className="bor-radius-all mt3" height="50" src={getImageUrl(`images/`+memo.image_url)} width="50" />
</a> </a>
<div className="fl pr" style={{flex: 1}}> <div className="fl pr" style={{flex: 1}}>
<p className="font-16 clearfix" > <p className="font-16 clearfix" style={{ lineHeight: 2 }}>
{/* target="_blank" */} {/* target="_blank" */}
<a href={`/forums/${memo.id}`} target="_blank" title={memo.subject} <a href={`/forums/${memo.id}`} target="_blank" title={memo.subject}
className="clearfix task-hide item_name fl" style={{maxWidth: '750px'}} > className="clearfix task-hide item_name fl" style={{maxWidth: '750px'}} >
@ -46,16 +46,16 @@ class PostItem extends Component {
</p> </p>
<div className="clearfix mt5 color-grey-9"> <div className="clearfix mt5 color-grey-9">
<span className="fl">{memo.username}</span> <span className="fl">{memo.user_name}</span>
{/*todo{memo.username} {/*todo{memo.username}
memo.language && memo.language != 'other' && <span className="fl language-cir-orange mr10 mt3 ml6">{memo.language}</span> memo.language && memo.language != 'other' && <span className="fl language-cir-orange mr10 mt3 ml6">{memo.language}</span>
*/} */}
<span className="fl ml50">{moment(memo.updated_at).fromNow()}</span> {/* <span className="fl ml50">{moment(memo.updated_at).fromNow()}</span> */}
{memo.tag && memo.tag.length ? <span className="fl ml50">来自 {memo.tag.join('/')}</span> : ''} {memo.tag && memo.tag.length ? <span className="fl ml50">来自 {memo.tag.join('/')}</span> : ''}
{/*<span className="fl language-cir-orange mr10 mt3">C++</span>*/} {/*<span className="fl language-cir-orange mr10 mt3">C++</span>*/}
<p className="font-12 fr mr8 color-grey-6"> <p className="font-12 fr mr8 color-grey-6" style={{ marginTop: '4px' }}>
{/* data-tip-down="回复数" <i className="fa fa-comments-o mr5"></i>{memo.replies_count} {/* data-tip-down="回复数" <i className="fa fa-comments-o mr5"></i>{memo.replies_count}
<i className="fa fa-thumbs-o-up mr5"></i>{memo.praise_count}*/} <i className="fa fa-thumbs-o-up mr5"></i>{memo.praise_count}*/}
{memo.replies_count ? {memo.replies_count ?

@ -165,7 +165,7 @@ return function wrap(WrappedComponent) {
let paramsUrl = queryString.stringify(params) let paramsUrl = queryString.stringify(params)
const memosUrl = '/api/v1/memos?' + paramsUrl // /${challenge.identifier}/star const memosUrl = '/memos.json?' + paramsUrl // /${challenge.identifier}/star
this.setState({ this.setState({
currentPage, currentPage,
@ -174,7 +174,7 @@ return function wrap(WrappedComponent) {
}) })
// 获取memo list // 获取memo list
axios.get(memosUrl,{ axios.get(memosUrl,{
withCredentials: true, // withCredentials: true,
}) })
.then((response) => { .then((response) => {
const memo_count = response.data.memo_count const memo_count = response.data.memo_count
@ -186,9 +186,9 @@ return function wrap(WrappedComponent) {
this.fetchMemos(maxPage); this.fetchMemos(maxPage);
return; return;
} }
const user = response.data.current_user; // const user = response.data.current_user;
user.tidding_count = response.data.tidding_count; // user.tidding_count = response.data.tidding_count;
this.props.initCommonState(user) // this.props.initCommonState(user)
this.props.initForumState(response.data) this.props.initForumState(response.data)
this.setState({ this.setState({
p_forum_id: params.forum, p_forum_id: params.forum,
@ -242,16 +242,18 @@ return function wrap(WrappedComponent) {
params.forum_id = this.state.p_forum_id; params.forum_id = this.state.p_forum_id;
} }
let paramsUrl = urlStringify(params) let paramsUrl = urlStringify(params)
const set_top_or_down_Url = `/api/v1/memos/${memo.id}/set-top-or-down?${paramsUrl}`; const set_top_or_down_Url = `/memos/${memo.id}/sticky_or_cancel.json?${paramsUrl}`;
// 获取memo list // 获取memo list
axios.get(set_top_or_down_Url, { axios.post(set_top_or_down_Url, {
withCredentials: true, // withCredentials: true,
}) })
.then((response) => { .then((response) => {
const status = response.data.status const status = response.data.status
if (status === 0) { if (status === 0) {
const { memo_list } = response.data; this.fetchMemos(1, '')
this.props.initForumState({ memo_list })
// const { memo_list } = response.data;
// this.props.initForumState({ memo_list })
// 刷新列表 // 刷新列表
// TODO 服务端直接返回第一页列表 // TODO 服务端直接返回第一页列表
// this.props.history.replace('/') // this.props.history.replace('/')
@ -268,7 +270,7 @@ return function wrap(WrappedComponent) {
const deleteUrl = `/api/v1/memos/${memo.id}`; const deleteUrl = `/api/v1/memos/${memo.id}`;
// 获取memo list // 获取memo list
axios.delete(deleteUrl, { axios.delete(deleteUrl, {
withCredentials: true, // withCredentials: true,
}) })
.then((response) => { .then((response) => {
const status = response.data.status const status = response.data.status

@ -33,7 +33,7 @@ class RecommendShixun extends Component {
</a> </a>
<div className="ml10 flex1"> <div className="ml10 flex1">
<a href={`/shixuns/${_shixun.identifier}/challenges`} target="_blank" data-tip-down={_shixun.name} <a href={`/shixuns/${_shixun.identifier}/challenges`} target="_blank" data-tip-down={_shixun.name}
className="color-grey-6 task-hide mb12 recomment-name" style={{maxWidth:'147px'}}> className="color-grey-6 task-hide mb10 recomment-name" style={{maxWidth:'147px'}}>
{_shixun.name} {_shixun.name}
</a> </a>
<p className="color-grey-9">{_shixun.myshixuns_count} 人学习</p> <p className="color-grey-9">{_shixun.myshixuns_count} 人学习</p>
@ -50,7 +50,7 @@ class RecommendShixun extends Component {
// 参考 TPMShixunDiscuss.js 推荐实训, 页面路径http://localhost:3007/shixuns/uznmbg54/shixun_discuss // 参考 TPMShixunDiscuss.js 推荐实训, 页面路径http://localhost:3007/shixuns/uznmbg54/shixun_discuss
return ( return (
<div className="padding10"> <div className="padding10">
<p className="mb20 font-16 clearfix">推荐实训</p> <p className="mb20 font-16 clearfix" style={{ lineHeight: 2 }}>推荐实训</p>
<div className="recommend-list"> <div className="recommend-list">
{this.showRecommandShixun()} {this.showRecommandShixun()}
</div> </div>

@ -21,27 +21,52 @@ class UserSection extends Component {
const { author_info } = this.props const { author_info } = this.props
/*http://localhost:3000/api/v1/users/155/watch?object_id=156&object_type=user*/ /*http://localhost:3000/api/v1/users/155/watch?object_id=156&object_type=user*/
const focusUrl = `/api/v1/users/${author_info.user_id}/${this.props.author_info.watched ? 'unwatch' : 'watch'}?object_id=${author_info.user_id}&object_type=user` // const focusUrl = `/api/v1/users/${author_info.user_id}/${this.props.author_info.watched ? 'unwatch' : 'watch'}?object_id=${author_info.user_id}&object_type=user`
axios.get(focusUrl,{ // axios.get(focusUrl,{
}) // })
.then((response) => { // .then((response) => {
const status = response.data.status; // const status = response.data.status;
console.log(status); // console.log(status);
if(status == 1){ // if(status == 1){
// const new_author_info = Object.assign({}, this.props.author_info)
// new_author_info.watched = !new_author_info.watched
// this.props.initForumState({author_info: new_author_info})
// }
// }).catch((error) => {
// console.log(error)
// })
let url=`/users/${author_info.user_id}/watch.json`;
// 取消关注
if(author_info.watched){
axios.delete(url).then((result)=>{
if(result){
const new_author_info = Object.assign({}, this.props.author_info) const new_author_info = Object.assign({}, this.props.author_info)
new_author_info.watched = !new_author_info.watched new_author_info.watched = !new_author_info.watched
this.props.initForumState({author_info: new_author_info}) this.props.initForumState({author_info: new_author_info})
} }
}).catch((error) => { }).catch((error)=>{
console.log(error) console.log(error)
}) })
}else{
// 关注
axios.post(url).then((result)=>{
if(result){
const new_author_info = Object.assign({}, this.props.author_info)
new_author_info.watched = !new_author_info.watched
this.props.initForumState({author_info: new_author_info})
}
}).catch((error)=>{
console.log(error);
})
}
} }
render() { render() {
const { match, history, author_info , current_user } = this.props const { match, history, author_info , current_user } = this.props
if (!author_info) { if (!author_info || !current_user) {
return <div className="edu-back-white" id="forum_index_list"></div> return <div className="edu-back-white" id="forum_index_list"></div>
} }
return ( return (
@ -52,7 +77,7 @@ class UserSection extends Component {
{ author_info.user_id !== current_user.user_id && { author_info.user_id !== current_user.user_id &&
<p className="clearfix mt30"> <p className="clearfix mt30">
<a href="javascript:void(0)" className="fl font-16 mr10 user_default_btn edu-blueback-btn" onClick={()=>{this.AboutFocus()}}>{ author_info.watched == true ? "取消关注" : "关注" }</a> <a href="javascript:void(0)" className="fl font-16 mr10 user_default_btn edu-blueback-btn" onClick={()=>{this.AboutFocus()}}>{ author_info.watched == true ? "取消关注" : "关注" }</a>
<a href={`/message/${current_user.login}/message_detail?target_ids=${author_info.user_id}`} className="fr font-16 user_default_btn user_private_btn" target="_blank">私信</a> <a href={`/users/${current_user.login}/message_detail?user_id=${author_info.user_id}`} className="fr font-16 user_default_btn user_private_btn" target="_blank">私信</a>
</p> } </p> }
</div> </div>
); );

@ -11,7 +11,7 @@
height:48px; height:48px;
width: 48px; width: 48px;
float: left; float: left;
margin-top: 7px; margin-top: 4px;
} }
.shixunReply{ .shixunReply{
max-width: 604px; max-width: 604px;

@ -83,7 +83,7 @@ class MemoShixun extends Component {
} }
const stringifid = queryString.stringify(paramsObject); const stringifid = queryString.stringify(paramsObject);
const url = `/api/v1/discusses?${stringifid}` // /${challenge.identifier}/star const url = `/discusses/forum_discusses.json?${stringifid}` // /${challenge.identifier}/star
// 获取memo list // 获取memo list
this.setState({ this.setState({
@ -91,13 +91,13 @@ class MemoShixun extends Component {
loadingMemos: true loadingMemos: true
}) })
axios.get(url,{ axios.get(url,{
withCredentials: true, // withCredentials: true,
}) })
.then((response) => { .then((response) => {
if (response.data) { if (response.data) {
const user = response.data.current_user; // const user = response.data.current_user;
user.tidding_count = response.data.tidding_count; // user.tidding_count = response.data.tidding_count;
this.props.initCommonState(user) // this.props.initCommonState(user)
this.props.initForumState(response.data) this.props.initForumState(response.data)
// const { hot_tags } = response.data; // const { hot_tags } = response.data;

@ -39,7 +39,7 @@ class ShiXunPostItem extends Component
width="48px" height="48px" className="radius"/> width="48px" height="48px" className="radius"/>
</a> </a>
<div className="flex1 ml10 pr20"> <div className="flex1 ml10 pr20">
<div className="clearfix"> <div className="clearfix" style={{ height: '32px' }}>
<p className="shixunReply task-hide font-16 fl"> <p className="shixunReply task-hide font-16 fl">
<Link to={`${memo.tpm_url}`} title={memo.subject} target="_blank">{memo.subject}</Link> <Link to={`${memo.tpm_url}`} title={memo.subject} target="_blank">{memo.subject}</Link>
</p> </p>

Loading…
Cancel
Save