Merge remote-tracking branch 'origin/dev_aliyun' into dev_aliyun

# Conflicts:
#	public/react/src/modules/forums/UserSection.js
dev_cs_new
杨树明 6 years ago
commit d84fd9654b

@ -911,6 +911,7 @@ class CoursesController < ApplicationController
CourseAddStudentCreateWorksJob.perform_later(course.id, [current_user.id])
StudentJoinCourseNotifyJob.perform_later(current_user.id, course.id)
end
student_role = 1
end
# 创建教师身份
@ -928,19 +929,21 @@ class CoursesController < ApplicationController
course_message.save!
role = course_message.content == 2 ? '7' : '9' # 7:助教 9:教师
role = course_message.content == 2 ? '9' : '7' # 7:助教 9:教师
ApplyTeacherRoleJoinCourseNotifyJob.perform_later(current_user.id, course.id, role)
message = "#{course_message.content == 2 ? '教' : ''}申请已提交,请等待审核"
message = "#{course_message.content == 2 ? '' : '教'}申请已提交,请等待审核"
else
message = "#{existing_course_message.content == 2 ? '教' : ''}申请已提交,请等待审核"
message = "#{existing_course_message.content == 2 ? '' : '教'}申请已提交,请等待审核"
end
else
message = "您已是课堂成员"
end
teacher_role = 1
end
if teacher_role && current_user.student_of_course?(course)
if teacher_role && student_role
render json: { status: 0, message: message, course_id: course.id}
elsif current_user.student_of_course?(course)
elsif student_role
render json: { status: 0, message: "加入成功", course_id: course.id}
else
normal_status(message)

@ -38,6 +38,7 @@ class Shixun < ApplicationRecord
belongs_to :user
# 实训服务配置
has_many :shixun_service_configs, :dependent => :destroy
has_many :tidings, as: :container, dependent: :destroy
scope :search_by_name, ->(keyword) { where("name like ? or description like ? ",
"%#{keyword}%", "%#{keyword}%") }
@ -62,6 +63,8 @@ class Shixun < ApplicationRecord
scope :field_for_recommend, lambda{ select([:id, :name, :identifier, :myshixuns_count]) }
scope :find_by_ids,lambda{|k| where(id:k)}
after_create :send_tiding
# REDO: 
def propaedeutics
shixun_info.try(:propaedeutics)
@ -242,4 +245,11 @@ class Shixun < ApplicationRecord
def finished_challenges_count(user)
Game.joins(:myshixun).where(user_id: user.id, status: 2, myshixuns: { shixun_id: id }).count
end
private
def send_tiding
self.tidings << Tiding.new(:user_id => user_id, :trigger_user_id => 1, :belong_container_id => id, :belong_container_type =>'Shixun', :tiding_type => "System", :viewed => 0)
end
end

@ -234,7 +234,7 @@ class User < ApplicationRecord
# 课堂的老师(创建者、老师、助教),不用考虑当前身份
def teacher_of_course_non_active?(course)
course.course_members.exists?(user_id: id, role: [1,2,3]) || admin? || business?
course.course_members.exists?(user_id: id, role: [1,2,3])
end
# 是否是教师,课堂管理员或者超级管理员

@ -11,6 +11,6 @@ if message.m_parent_id
json.can_delete message.can_delete(identity)
else
json.praise_count message.praise_treads.select{|pt| pt.praise_or_tread == 1}.count
json.user_praise message.praise_treads.select{|pt| pt.praise_or_tread == 1 && user_id == current_user.id}.count
json.user_praise message.praise_treads.select{|pt| pt.praise_or_tread == 1 && pt.user_id == current_user.id}.count
json.child_message_count message.m_reply_count
end

Binary file not shown.

@ -351,9 +351,14 @@ class App extends Component {
{/*课堂*/}
<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="/testMaterial" component={TestMaterialDesignComponent}/>
<Route path="/test" component={TestIndex}/>

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

@ -195,7 +195,7 @@ class AddStudentModal extends Component{
<div className="df">
<span className="mr10">姓名:</span>
<Input allowClear placeholder="请输入真实姓名" value={name} onChange={(e) => {this.setState({name: e.target.value})}}
style={{ width: '242px'}}
style={{ width: '221px'}}
></Input>
<span className="label" style={{ minWidth: '36px' }}>单位:</span>
{/* <Input allowClear placeholder="" value={school_name} onChange={(e) => {this.setState({school_name: e.target.value})}}
@ -210,14 +210,7 @@ class AddStudentModal extends Component{
>搜索</a>
</div>
{/* <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' }}>
<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>
<span className="fl with25">
<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>
</span>
<span className="fl with25">
@ -271,6 +269,14 @@ class AddStudentModal extends Component{
</InfiniteScroll>
</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> }
</Spin>
</ModalWrapper>

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

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

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

@ -15,6 +15,7 @@ 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'
const Option = Select.Option;
@ -130,6 +131,7 @@ const languageSeparator = '/'
class MemoNew extends Component {
constructor(props) {
super(props)
this.mdRef = React.createRef();
// https://testbdweb.trustie.net/uploads.js?attachment_id=1&filename=jqui.js
// https://ant.design/components/upload-cn/
@ -179,7 +181,7 @@ class MemoNew extends Component {
}
let mdVal;
try {
mdVal = this.taskpass_editormd.getValue()
mdVal = this.mdRef.current.getValue()
} catch (e) {
showSnackbar('编辑器还未加载完毕,请稍后')
@ -205,6 +207,7 @@ 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()
@ -215,13 +218,14 @@ class MemoNew extends Component {
token,
attachment_id
}
attachmentIds.push(attachment_id)
})
if (currentMemoId) {
this.updateMemo(attachmentsMap)
this.updateMemo(attachmentIds)
} else {
this.newMemo(attachmentsMap)
this.newMemo(attachmentIds)
}
}
onCancel() {
@ -235,23 +239,23 @@ class MemoNew extends Component {
}
updateMemo(attachmentsMap) {
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);
const newMemoUrl = `/api/v1/memos/${currentMemoId}/update`
axios.post(newMemoUrl, {
const newMemoUrl = `/memos/${currentMemoId}.json`
axios.put(newMemoUrl, {
content_changed: this.contentChanged,
tags: memoLanguage,
memo:{
// memo:{
subject: memoSubject ,
content: mdVal,
forum_id: memoType,
repertoire_name: memoRepertoire,
// language: memoLanguage.join(languageSeparator),
//
},
// },
attachments: attachmentsMap
}, {
withCredentials: true,
// withCredentials: true,
})
.then((response) => {
const { status, message, memo_id } = response.data;
@ -267,21 +271,21 @@ class MemoNew extends Component {
}
newMemo(attachmentsMap) {
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, {
tags: memoLanguage,
memo:{
// memo:{
subject: memoSubject ,
content: mdVal,
forum_id: memoType,
repertoire_name: memoRepertoire,
// repertoire_name: memoRepertoire,
},
// },
attachments: attachmentsMap
}, {
withCredentials: true,
// withCredentials: true,
})
.then((response) => {
const { status, message, memo_id } = response.data;
@ -296,9 +300,9 @@ class MemoNew extends Component {
})
}
componentDidMount() {
const newMemoUrl = `/api/v1/memos/new`
const newMemoUrl = `/memos/new.json`
axios.get(newMemoUrl,{
withCredentials: true,
// withCredentials: true,
})
.then((response) => {
const data = response.data;
@ -319,9 +323,9 @@ class MemoNew extends Component {
// repertoiresTagMap
})
const user = response.data.current_user;
user.tidding_count = response.data.tidding_count;
this.props.initCommonState(user)
// const user = response.data.current_user;
// user.tidding_count = response.data.tidding_count;
// this.props.initCommonState(user)
// 初始化 csrf meta
const $ = window.$
@ -336,18 +340,20 @@ class MemoNew extends Component {
const { match } = this.props
const memoId = match.params.memoId;
if (memoId) {
const memoUrl = `/api/v1/memos/${match.params.memoId}/edit`;
const memoUrl = `/memos/${match.params.memoId}/edit.json`;
axios.get(memoUrl,{
withCredentials: true,
// withCredentials: true,
})
.then((response) => {
const tag_list = response.data.tag_list
if (tag_list) {
// this.setState({...response.data})
const { content, forum_id, id, tag, repertoire_name, subject,
current_user, tag_list, attachments_url } = response.data;
const { content, forum_id, id, repertoire_name, subject,
current_user, tag_list, attachments_url, memo_tags } = response.data;
this.initMD(content);
// this.onRepertoiresChange(repertoire_name)
// tag -> memo_tags
const tag = memo_tags;
let memoLanguage = []
if (tag) {
memoLanguage = tag.map((item, index) => {
@ -355,7 +361,7 @@ class MemoNew extends Component {
})
}
this.setState({
currentMemoId: id,
currentMemoId: memoId,
memoSubject: subject,
memoType: forum_id,
memoRepertoire: repertoire_name,
@ -377,7 +383,7 @@ class MemoNew extends Component {
window.$("html,body").animate({"scrollTop":0})
this.props.initForumState({
current_user,
// current_user,
tag_list
})
}
@ -394,6 +400,8 @@ class MemoNew extends Component {
}
initMD(initValue) {
return;
this.contentChanged = false;
const placeholder = "";
// amp;
@ -566,9 +574,12 @@ class MemoNew extends Component {
<div className="df">
<span className="mr30 color-orange pt10">*</span>
<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>
</div>
</div> */}
<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>
</div>

@ -8,6 +8,9 @@
min-height: 400px;
position: relative;
}
#forum_index_list .forum_table .forum_table_item {
background: #fff;
}
.noMemosTip {
position: absolute;
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" />
</a>
<div className="fl pr" style={{flex: 1}}>
<p className="font-16 clearfix" >
<p className="font-16 clearfix" style={{ lineHeight: 2 }}>
{/* target="_blank" */}
<a href={`/forums/${memo.id}`} target="_blank" title={memo.subject}
className="clearfix task-hide item_name fl" style={{maxWidth: '750px'}} >
@ -46,16 +46,16 @@ class PostItem extends Component {
</p>
<div className="clearfix mt5 color-grey-9">
<span className="fl">{memo.username}</span>
<span className="fl">{memo.user_name}</span>
{/*todo{memo.username}
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> : ''}
{/*<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}
<i className="fa fa-thumbs-o-up mr5"></i>{memo.praise_count}*/}
{memo.replies_count ?

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

@ -33,7 +33,7 @@ class RecommendShixun extends Component {
</a>
<div className="ml10 flex1">
<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}
</a>
<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
return (
<div className="padding10">
<p className="mb20 font-16 clearfix">推荐实训</p>
<p className="mb20 font-16 clearfix" style={{ lineHeight: 2 }}>推荐实训</p>
<div className="recommend-list">
{this.showRecommandShixun()}
</div>

@ -21,27 +21,52 @@ class UserSection extends Component {
const { author_info } = this.props
/*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`
axios.get(focusUrl,{
})
.then((response) => {
const status = response.data.status;
console.log(status);
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)
})
// 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,{
// })
// .then((response) => {
// const status = response.data.status;
// console.log(status);
// 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)
new_author_info.watched = !new_author_info.watched
this.props.initForumState({author_info: new_author_info})
}
}).catch((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() {
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 (

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

@ -83,7 +83,7 @@ class MemoShixun extends Component {
}
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
this.setState({
@ -91,13 +91,13 @@ class MemoShixun extends Component {
loadingMemos: true
})
axios.get(url,{
withCredentials: true,
// withCredentials: true,
})
.then((response) => {
if (response.data) {
const user = response.data.current_user;
user.tidding_count = response.data.tidding_count;
this.props.initCommonState(user)
// const user = response.data.current_user;
// user.tidding_count = response.data.tidding_count;
// this.props.initCommonState(user)
this.props.initForumState(response.data)
// const { hot_tags } = response.data;

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

Loading…
Cancel
Save