|
@@ -6,7 +6,7 @@ import FileUpload from '@src/components/FileUpload';
|
|
|
import Page from '@src/containers/Page';
|
|
|
import Assets from '@src/components/Assets';
|
|
|
import { asyncSMessage } from '@src/services/AsyncTools';
|
|
|
-import { formatDate, formatSeconds, formatPercent } from '@src/services/Tools';
|
|
|
+import { formatDate, formatSeconds, formatPercent, getMap } from '@src/services/Tools';
|
|
|
import UserLayout from '../../../layouts/User';
|
|
|
import Button from '../../../components/Button';
|
|
|
import ProgressText from '../../../components/ProgressText';
|
|
@@ -19,7 +19,7 @@ import More from '../../../components/More';
|
|
|
import Modal from '../../../components/Modal';
|
|
|
import DatePlane from '../../../components/Date';
|
|
|
import Note from '../../../components/Note';
|
|
|
-import { FinishModal, CommentModal } from '../../../components/OtherModal';
|
|
|
+import { FinishModal, CommentModal, CourseNoteModal } from '../../../components/OtherModal';
|
|
|
import { My } from '../../../stores/my';
|
|
|
import { User } from '../../../stores/user';
|
|
|
import { Question } from '../../../stores/question';
|
|
@@ -86,11 +86,12 @@ export default class extends Page {
|
|
|
// 是否是最后一课时,是否过预约时间
|
|
|
const last = row.appointments.length - 1;
|
|
|
const appointment = row.appointments[last];
|
|
|
-
|
|
|
- if (new Date(appointment.endTime).getTime() < new Date().getTime()) {
|
|
|
- // row.status = 'end';
|
|
|
- if (row.number !== row.appointments.length) {
|
|
|
- row.appointments.push([{}]);
|
|
|
+ if (appointment) {
|
|
|
+ if (new Date(appointment.endTime).getTime() < new Date().getTime()) {
|
|
|
+ // row.status = 'end';
|
|
|
+ if (row.number !== row.appointments.length) {
|
|
|
+ row.appointments.push([{}]);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -180,6 +181,22 @@ export default class extends Page {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ refreshNote(recordId) {
|
|
|
+ let { list } = this.state;
|
|
|
+ const [record] = list.filter(row => row.id === recordId);
|
|
|
+ if (!record) return Promise.reject(new Error('记录错误'));
|
|
|
+ return My.listCourseNote({ courseId: record.productId, page: 1, size: record.courseNos.length })
|
|
|
+ .then((result) => {
|
|
|
+ list = list.map(row => {
|
|
|
+ if (row.id === recordId) {
|
|
|
+ row.noteMap = getMap(result.list, 'courseNoId');
|
|
|
+ }
|
|
|
+ return row;
|
|
|
+ });
|
|
|
+ this.setState({ list });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
suspend() {
|
|
|
const { suspend } = this.state;
|
|
|
My.suspendCourse(suspend.id)
|
|
@@ -240,6 +257,8 @@ export default class extends Page {
|
|
|
open(recordId) {
|
|
|
Order.useRecord(recordId).then(() => {
|
|
|
this.refreshDetail(recordId);
|
|
|
+ }).catch((err) => {
|
|
|
+ asyncSMessage(err.message, 'error');
|
|
|
});
|
|
|
}
|
|
|
|
|
@@ -282,6 +301,7 @@ export default class extends Page {
|
|
|
showUploadSupply,
|
|
|
showSupply,
|
|
|
showNote,
|
|
|
+ showCourseNote,
|
|
|
showComment,
|
|
|
showFinish,
|
|
|
comment = {},
|
|
@@ -357,31 +377,32 @@ export default class extends Page {
|
|
|
停课
|
|
|
</div>
|
|
|
</div>
|
|
|
- <DatePlane
|
|
|
- hideInput
|
|
|
- show={showTime}
|
|
|
- onChange={() => { }}
|
|
|
- disabledDate={current => {
|
|
|
- const date = current.format('YYYY-MM-DD');
|
|
|
- return data.stopTimeMap[date];
|
|
|
- }}
|
|
|
- dateRender={current => {
|
|
|
- const date = current.format('YYYY-MM-DD');
|
|
|
- return (
|
|
|
- <div className="ant-calendar-date">
|
|
|
- {current.get('date')}
|
|
|
- {data.courseTimeMap[date] && <i className="s1" style={{ background: '#6865FD' }} />}
|
|
|
- {data.previewTimeMap[date] && <i className="s2" style={{ background: '#4299FF' }} />}
|
|
|
- </div>
|
|
|
- );
|
|
|
- }}
|
|
|
- checkRefresh={(date, refresh) => {
|
|
|
- setTimeout(() => {
|
|
|
- refresh();
|
|
|
- }, 2000);
|
|
|
- return true;
|
|
|
- }}
|
|
|
- />
|
|
|
+ <div style={{ position: 'relative' }}>
|
|
|
+ <DatePlane
|
|
|
+ hideInput
|
|
|
+ show={showTime}
|
|
|
+ onChange={() => { }}
|
|
|
+ disabledDate={current => {
|
|
|
+ const date = current.format('YYYY-MM-DD');
|
|
|
+ return data.stopTimeMap[date];
|
|
|
+ }}
|
|
|
+ dateRender={current => {
|
|
|
+ const date = current.format('YYYY-MM-DD');
|
|
|
+ return (
|
|
|
+ <div className="ant-calendar-date">
|
|
|
+ {current.get('date')}
|
|
|
+ {data.courseTimeMap[date] && <i className="s1" style={{ background: '#6865FD' }} />}
|
|
|
+ {data.previewTimeMap[date] && <i className="s2" style={{ background: '#4299FF' }} />}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }}
|
|
|
+ checkRefresh={(date, refresh) => {
|
|
|
+ setTimeout(() => {
|
|
|
+ refresh();
|
|
|
+ }, 2000);
|
|
|
+ return true;
|
|
|
+ }}
|
|
|
+ /></div>
|
|
|
<div className="t-2 t-s-12">*听课频率≤2天/课时,作业完成度≥90%,课程有效期可延长7-10天。</div>
|
|
|
</Modal>
|
|
|
<Modal
|
|
@@ -530,6 +551,10 @@ export default class extends Page {
|
|
|
show={showFinish}
|
|
|
onConfirm={() => this.setState({ showFinish: false })}
|
|
|
/>
|
|
|
+ <CourseNoteModal getContainer={() => document.body} show={showCourseNote} defaultData={note} course={data.course} courseNos={data.courseNos} noteMap={data.noteMap} onConfirm={() => {
|
|
|
+ this.setState({ showCourseNote: false });
|
|
|
+ this.refreshNote();
|
|
|
+ }} onCancel={() => this.setState({ showCourseNote: false })} />
|
|
|
</div>
|
|
|
);
|
|
|
}
|
|
@@ -556,6 +581,15 @@ export default class extends Page {
|
|
|
onComment={() => {
|
|
|
this.setState({ showComment: true, comment: { channel: 'course-video', position: item.course.id } });
|
|
|
}}
|
|
|
+ onNote={(courseNo) => {
|
|
|
+ let handler = Promise.resolve();
|
|
|
+ if (!item.noteMap) {
|
|
|
+ handler = this.refreshNote(item.id);
|
|
|
+ }
|
|
|
+ handler.then(() => {
|
|
|
+ this.setState({ showCourseNote: true, note: item.noteMap[courseNo.id], data: item });
|
|
|
+ });
|
|
|
+ }}
|
|
|
closeCommentTips={() => this.closeCommentTips(item.id)}
|
|
|
/>
|
|
|
);
|
|
@@ -615,65 +649,65 @@ class CourseOnline extends Component {
|
|
|
title: '学习内容',
|
|
|
key: 'title',
|
|
|
render: (text, record) => {
|
|
|
- return `课时 ${record.no}: ${text}`;
|
|
|
+ return <a href={`/course/detail/${record.courseId}?no=${record.no}`} target="_blank">课时 {record.no}: {text}</a>;
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
title: '预习作业',
|
|
|
key: 'paper',
|
|
|
- render: text => {
|
|
|
- text = text || {};
|
|
|
- const progress = text.report ? formatPercent(text.report.userNumber, text.report.questionNumber) : 0;
|
|
|
- const times = text.paper ? text.paper.resetTimes : 0;
|
|
|
+ render: (text, record) => {
|
|
|
+ const { paper = {} } = record;
|
|
|
+ const progress = paper.report ? formatPercent(paper.report.userNumber, paper.report.questionNumber) : 0;
|
|
|
+ const times = paper.paper ? paper.paper.resetTimes : 0;
|
|
|
return (
|
|
|
<div>
|
|
|
<div className="v-a-m d-i-b">
|
|
|
<ProgressText width={50} size="small" times={times} progress={progress} unit="次" />
|
|
|
</div>
|
|
|
- {!text.report && (
|
|
|
+ {!paper.report && (
|
|
|
<IconButton
|
|
|
className="m-l-2"
|
|
|
type="start"
|
|
|
tip="Start"
|
|
|
onClick={() => {
|
|
|
User.needLogin().then(() => {
|
|
|
- Question.startLink('preview', text);
|
|
|
+ Question.startLink('preview', paper);
|
|
|
});
|
|
|
}}
|
|
|
/>
|
|
|
)}
|
|
|
- {text.report && !text.report.isFinish && (
|
|
|
+ {paper.report && !paper.report.isFinish && (
|
|
|
<IconButton
|
|
|
className="m-l-2"
|
|
|
type="continue"
|
|
|
tip="Continue"
|
|
|
onClick={() => {
|
|
|
User.needLogin().then(() => {
|
|
|
- Question.continueLink('preview', text);
|
|
|
+ Question.continueLink('preview', paper);
|
|
|
});
|
|
|
}}
|
|
|
/>
|
|
|
)}
|
|
|
- {text.report && (
|
|
|
+ {paper.report && (
|
|
|
<IconButton
|
|
|
className="m-l-2"
|
|
|
type="restart"
|
|
|
tip="Restart"
|
|
|
onClick={() => {
|
|
|
User.needLogin().then(() => {
|
|
|
- Question.restart('preview', text);
|
|
|
+ Question.restart('preview', paper);
|
|
|
});
|
|
|
}}
|
|
|
/>
|
|
|
)}
|
|
|
- {text.report && !!text.report.isFinish && (
|
|
|
+ {paper.report && !!paper.report.isFinish && (
|
|
|
<IconButton
|
|
|
className="m-l-5"
|
|
|
type="report"
|
|
|
tip="Report"
|
|
|
onClick={() => {
|
|
|
User.needLogin().then(() => {
|
|
|
- Question.reportLink('preview', text);
|
|
|
+ Question.reportLink('preview', paper);
|
|
|
});
|
|
|
}}
|
|
|
/>
|
|
@@ -685,30 +719,35 @@ class CourseOnline extends Component {
|
|
|
{
|
|
|
title: '进度',
|
|
|
key: 'progress',
|
|
|
+ width: 70,
|
|
|
render: (text, record) => {
|
|
|
- const { paper = {} } = record;
|
|
|
- return `${paper.paper && paper.paper.finishTimes > 0 ? `${paper.paper.finishTimes}次+` : ''}${
|
|
|
- paper.report ? formatPercent(paper.report.userNumber, paper.report.questionNumber, false) : '0%'}`;
|
|
|
+ const { progress } = record;
|
|
|
+ return progress ? `${progress.progress}%` : '0%';
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
title: '最近学习',
|
|
|
key: 'lastTime',
|
|
|
- render: (text, record) => {
|
|
|
- const { paper = {} } = record;
|
|
|
- return paper.report && formatDate(paper.report.updateTime, 'YYYY-MM-DD HH:mm:ss');
|
|
|
+ width: 105,
|
|
|
+ render: (text, rr) => {
|
|
|
+ const { record } = rr;
|
|
|
+ return record && formatDate(record.createTime, 'YYYY-MM-DD HH:mm:ss');
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
title: '笔记',
|
|
|
key: 'note',
|
|
|
+ width: 70,
|
|
|
render: (text, record) => {
|
|
|
- return <GIcon name="note" active={record.note} />;
|
|
|
+ return <GIcon name="note" active={record.note} onClick={() => {
|
|
|
+ this.onNote(record);
|
|
|
+ }} />;
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
title: '问答',
|
|
|
key: 'ask',
|
|
|
+ width: 70,
|
|
|
render: (text, record) => {
|
|
|
return (
|
|
|
<Link to={`/course/answer/${record.courseId}?tab=my&courseNoId=${record.id}`}>{`${record.answerNumber ||
|
|
@@ -720,6 +759,19 @@ class CourseOnline extends Component {
|
|
|
this.state = { open: props.data.status === 'ing' };
|
|
|
}
|
|
|
|
|
|
+ open(recordId) {
|
|
|
+ Order.useRecord(recordId).then(() => {
|
|
|
+ this.props.refreshDetail(recordId);
|
|
|
+ }).catch((err) => {
|
|
|
+ asyncSMessage(err.message, 'error');
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ onNote(record) {
|
|
|
+ const { onNote } = this.props;
|
|
|
+ onNote(record);
|
|
|
+ }
|
|
|
+
|
|
|
render() {
|
|
|
const { data = {} } = this.props;
|
|
|
switch (data.status) {
|
|
@@ -780,13 +832,17 @@ class CourseOnline extends Component {
|
|
|
</div>
|
|
|
</div>
|
|
|
<div className="right">
|
|
|
- <div className="item">
|
|
|
+ <div className="item" onClick={() => {
|
|
|
+ openLink(`/course/detail/${data.course.id}?no=${data.currentNo}`);
|
|
|
+ }}>
|
|
|
<GIcon name="speed-block" active noHover />
|
|
|
<div className="text">
|
|
|
- <span>{data.currentNo}</span>/{data.courseNos.length}
|
|
|
+ <span>{data.currentNo}</span>/{(data.courseNos || []).length}
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div className="item">
|
|
|
+ <div className="item" onClick={() => {
|
|
|
+ openLink(`/course/answer/${data.course.id}`);
|
|
|
+ }}>
|
|
|
<GIcon name="question-block" active noHover />
|
|
|
<div className="text">
|
|
|
<span>{data.answerNumber}</span>/{data.askNumber}
|
|
@@ -798,7 +854,9 @@ class CourseOnline extends Component {
|
|
|
<span>{formatSeconds(data.totalTime)}</span> {data.previewProgress || 0}%
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div className="item">
|
|
|
+ <div className="item" onClick={() => {
|
|
|
+ openLink(`/course/note/${data.course.id}`);
|
|
|
+ }}>
|
|
|
<GIcon name="note-block" active noHover />
|
|
|
<div className="text">{data.noteNumber}</div>
|
|
|
</div>
|
|
@@ -967,7 +1025,7 @@ class CourseOnline extends Component {
|
|
|
<div className="item">
|
|
|
<GIcon name="speed-block" noHover />
|
|
|
<div className="text">
|
|
|
- <span>{data.currentNo}</span>/{data.courseNos.length}
|
|
|
+ <span>{data.currentNo}</span>/{(data.courseNos || []).length}
|
|
|
</div>
|
|
|
</div>
|
|
|
<div className="item">
|
|
@@ -999,7 +1057,7 @@ class CourseOnline extends Component {
|
|
|
renderTable() {
|
|
|
const { data = {} } = this.props;
|
|
|
const { courseNos = [] } = data;
|
|
|
- return <UserTable size="small" columns={this.columns} data={courseNos} />;
|
|
|
+ return <UserTable size="small" columns={this.columns} data={courseNos || []} />;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1192,6 +1250,12 @@ class CourseVs extends Component {
|
|
|
system: [1, 7, 3, 4],
|
|
|
answer: [1, 2, 3],
|
|
|
};
|
|
|
+ if (!props.data.appointments) {
|
|
|
+ props.data.appointments = [];
|
|
|
+ }
|
|
|
+ if (!props.data.teacher) {
|
|
|
+ props.data.teacher = {};
|
|
|
+ }
|
|
|
const index = props.data.appointments.length - 1;
|
|
|
this.state = {
|
|
|
open: props.data.status === 'ing',
|