|
|
import React, { Fragment, useState, useMemo } from 'react'
|
|
|
import AttachmentItem from '../attachment-item'
|
|
|
import CommentItemReplay from '../commonent-item-replay'
|
|
|
|
|
|
import { useParams } from 'react-router-dom'
|
|
|
import TPMMDEditor from '../../../../tpm/challengesnew/TPMMDEditor'
|
|
|
import axios from 'axios'
|
|
|
|
|
|
import { markdownToHTML, WordsBtn, getUrl } from 'educoder'
|
|
|
import './index.css'
|
|
|
|
|
|
const ACCEPT = 3
|
|
|
const REFUSE = 4
|
|
|
export default ({ confirm, item, showNotification, replySuccess, isStudent, isAdmin, homework_status, is_author, commentIndex, onDelete }) => {
|
|
|
|
|
|
const [data, setData] = useState({
|
|
|
value: '',
|
|
|
isShow: false,
|
|
|
mode: 'reply'
|
|
|
})
|
|
|
const { studentWorkId, workId } = useParams()
|
|
|
const { value, isShow, mode } = data
|
|
|
|
|
|
function onCancelMyAppeal() {
|
|
|
confirm({
|
|
|
content: <div>
|
|
|
<p>撤销申诉后,无法再对本评阅记录进行申诉</p>
|
|
|
<p>是否确认撤销申诉</p>
|
|
|
</div>,
|
|
|
onOk: () => {
|
|
|
const url = `/student_works/${studentWorkId}/cancel_appeal.json`
|
|
|
axios.post(url, {
|
|
|
score_id: item.id
|
|
|
})
|
|
|
.then((response) => {
|
|
|
if (response.data.status == 0) {
|
|
|
showNotification('撤销成功')
|
|
|
replySuccess()
|
|
|
}
|
|
|
})
|
|
|
.catch(function (error) {
|
|
|
console.log(error)
|
|
|
})
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
|
|
|
function onDeleteReply(source) {
|
|
|
confirm({
|
|
|
content: `是否确认删除?`,
|
|
|
onOk: () => {
|
|
|
const url = `/commons/delete.json`
|
|
|
axios.delete(url, {
|
|
|
data: {
|
|
|
object_id: source.id,
|
|
|
object_type: 'journals_for_message'
|
|
|
}
|
|
|
})
|
|
|
.then((response) => {
|
|
|
if (response.data.status == 0) {
|
|
|
replySuccess()
|
|
|
setData({ ...data, isShow: false })
|
|
|
}
|
|
|
})
|
|
|
.catch(function (error) {
|
|
|
console.log(error)
|
|
|
})
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
function onDeleteHandler() {
|
|
|
onDelete(item)
|
|
|
}
|
|
|
|
|
|
function onSubmit() {
|
|
|
if (!value || !value.trim()) {
|
|
|
showNotification('内容不能为空')
|
|
|
return
|
|
|
}
|
|
|
let url = `/student_works/${studentWorkId}/appeal_anonymous_score.json`
|
|
|
if (mode === 'reply') {
|
|
|
url = `/student_works/${studentWorkId}/add_score_reply.json`
|
|
|
axios.post(url, {
|
|
|
score_id: item.id,
|
|
|
comment: value
|
|
|
}).then((result) => {
|
|
|
if (result.data.status == 0) {
|
|
|
replySuccess()
|
|
|
setData({ ...data, isShow: false })
|
|
|
}
|
|
|
}).catch((error) => {
|
|
|
console.log(error)
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function callback(type, source) {
|
|
|
if (type === 'refuse-appeal-score') {
|
|
|
onDealAppealScore(REFUSE, source)
|
|
|
}
|
|
|
if (type === 'accept-appeal-score') {
|
|
|
onDealAppealScore(ACCEPT, source)
|
|
|
}
|
|
|
if (type === 'cancel-my-appeal') {
|
|
|
onCancelMyAppeal()
|
|
|
}
|
|
|
if (type === 'del-replay-item') {
|
|
|
onDeleteReply(source)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function onDealAppealScore(mode, source) {
|
|
|
confirm({
|
|
|
content:
|
|
|
<div>
|
|
|
<div>{mode == ACCEPT ? '此匿评成绩将被废弃,评阅人的作品将被违规扣分' : '此匿评成绩将被认为合理'}</div>
|
|
|
<div>是否确认{mode == ACCEPT ? '接受申诉' : '拒绝申诉'}</div>
|
|
|
</div>
|
|
|
,
|
|
|
onOk: () => {
|
|
|
const url = `/student_works/${studentWorkId}/deal_appeal_score.json`
|
|
|
axios.post(url, {
|
|
|
score_id: source.score_id,
|
|
|
status: mode
|
|
|
})
|
|
|
.then((response) => {
|
|
|
if (response.data.status == 0) {
|
|
|
showNotification(`${mode == ACCEPT ? '接受申诉' : '拒绝申诉'}成功`)
|
|
|
replySuccess()
|
|
|
}
|
|
|
})
|
|
|
.catch(function (error) {
|
|
|
console.log(error);
|
|
|
});
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
const pre = getUrl()
|
|
|
const _origin = ''
|
|
|
|
|
|
function onChangeHandler(value) {
|
|
|
setData({ ...data, value })
|
|
|
}
|
|
|
|
|
|
function onReplayHandler() {
|
|
|
setData({ ...data, isShow: true, mode: 'reply' })
|
|
|
}
|
|
|
|
|
|
function onAppealHandler() {
|
|
|
setData({ ...data, isShow: true, mode: 'appeal' })
|
|
|
}
|
|
|
function onCancel() {
|
|
|
setData({ ...data, isShow: false })
|
|
|
}
|
|
|
const { id, image_url, user_login, username, comment_role, time, score, is_invalid, can_appeal, appeal_status, content, attachments, journals } = item
|
|
|
const isAnonymous = homework_status && homework_status.indexOf('匿评中') != -1
|
|
|
const isAppealing = homework_status && homework_status.indexOf('申诉中') != -1
|
|
|
|
|
|
const md = useMemo(() => {
|
|
|
return content ? markdownToHTML(content) : ''
|
|
|
}, [content, id])
|
|
|
|
|
|
return (
|
|
|
<div className="ccomment comment_item_cont df clearfix" key={id}>
|
|
|
<div className="J_Comment_Face fl">
|
|
|
<a href={image_url === '--' ? `${_origin}/users/${user_login}` : 'javascript:void(0)'} target="_blank">
|
|
|
<img alt="用户头像" height="50"
|
|
|
src={`${pre}/images/${image_url}`}
|
|
|
width="50" />
|
|
|
</a>
|
|
|
</div>
|
|
|
<div className="t_content fl">
|
|
|
<div className="J_Comment_Reply">
|
|
|
<div className="comment_orig_content" style={{ margin: "0px" }}>
|
|
|
<div className="J_Comment_Info clearfix mt3">
|
|
|
<div className="t_info fl">
|
|
|
<a href={user_login === "--" ? `${_origin}/users/${user_login}` : 'javascript:void(0)'} className="content-username hide fl"> {username}({comment_role})</a>
|
|
|
<span className="t_area fl">{time}</span>
|
|
|
{score !== null && <span className="score_area fl">{score}分</span>}
|
|
|
{is_invalid ? <span className="validate_area fr">失效</span> :
|
|
|
<Fragment>
|
|
|
<WordsBtn style="blue" className="fr" onClick={onReplayHandler}>回复</WordsBtn>
|
|
|
{(isAppealing || isAnonymous) && can_appeal && appeal_status == 0 &&
|
|
|
<WordsBtn style="blue" className="fr mr20" onClick={onAppealHandler}>申诉</WordsBtn>}
|
|
|
</Fragment>
|
|
|
}
|
|
|
{item.delete && isAdmin() && <WordsBtn style="blue" className="fr mr12" onClick={onDeleteHandler}>删除</WordsBtn>}
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
{!!md ? <div className="comment_content clearfix" id={`reply_content_${id}`}>
|
|
|
<div className="color-grey-3" id={`reply_content_${id}`}>
|
|
|
<div className={"markdown-body"} dangerouslySetInnerHTML={{ __html: md }}></div>
|
|
|
<div className="cl"></div>
|
|
|
</div>
|
|
|
</div> : <span className="color656565 mt2 color-grey-9 font-12 mr8" style={{ display: 'inline-block' }}>{"暂未写评语"}</span>}
|
|
|
{attachments && attachments.length > 0 ? <div className="mt6"> {attachments.map((attaItem, key) => <AttachmentItem {...attaItem} key={key} />)} </div> : null}
|
|
|
{journals && journals.length > 0 ?
|
|
|
<div className="childrenCommentsView" style={{ background: '#fff' }}>
|
|
|
{journals.map(journal => <CommentItemReplay key={journal.id} {...journal} callback={callback} isAdmin={isAdmin()} is_author={is_author} isStudent={isStudent()} />)}
|
|
|
</div> : null
|
|
|
}
|
|
|
<div>
|
|
|
{isShow &&
|
|
|
<Fragment>
|
|
|
<TPMMDEditor mdID={`${commentIndex}`} watch={false}
|
|
|
height={130} onChange={onChangeHandler}
|
|
|
placeholder={`请输入内容`} noStorage={true}
|
|
|
></TPMMDEditor>
|
|
|
<div className="fr">
|
|
|
<a className="task-btn task-btn-orange fr" style={{ height: '26px', lineHeight: '26px', width: '60px' }}
|
|
|
onClick={onSubmit}
|
|
|
>{mode === 'reply' ? '回复' : '申诉'}</a>
|
|
|
<a onClick={onCancel} className="defalutCancelbtn fr"
|
|
|
style={{ height: '26px', width: '60px', fontSize: '14px', lineHeight: '26px', marginRight: '10px' }}>取消</a>
|
|
|
</div>
|
|
|
</Fragment>
|
|
|
}
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div >
|
|
|
)
|
|
|
} |