|
@@ -1,42 +1,138 @@
|
|
|
import React from 'react';
|
|
|
+import { Link } from 'react-router-dom';
|
|
|
import './index.less';
|
|
|
import Page from '@src/containers/Page';
|
|
|
import Assets from '@src/components/Assets';
|
|
|
+import { getMap, formatPercent, formatDate } from '@src/services/Tools';
|
|
|
import Footer from '../../../components/Footer';
|
|
|
+import { FaqModal, CommentModal, FinishModal, CourseNoteModal, AskCourseModal } from '../../../components/OtherModal';
|
|
|
import { Contact, AnswerCarousel, Comment } from '../../../components/Other';
|
|
|
import Tabs from '../../../components/Tabs';
|
|
|
+import { Icon as GIcon } from '../../../components/Icon';
|
|
|
import Button from '../../../components/Button';
|
|
|
+import IconButton from '../../../components/IconButton';
|
|
|
import UserTable from '../../../components/UserTable';
|
|
|
import ProgressText from '../../../components/ProgressText';
|
|
|
import { OpenText } from '../../../components/Open';
|
|
|
import Video from '../../../components/Video';
|
|
|
+import { Main } from '../../../stores/main';
|
|
|
+import { Course } from '../../../stores/course';
|
|
|
+import { User } from '../../../stores/user';
|
|
|
+import { Order } from '../../../stores/order';
|
|
|
+import { Question } from '../../../stores/question';
|
|
|
+import { My } from '../../../stores/my';
|
|
|
|
|
|
export default class extends Page {
|
|
|
initState() {
|
|
|
this.columns = [
|
|
|
{
|
|
|
- key: '1',
|
|
|
title: '学习内容',
|
|
|
+ key: 'title',
|
|
|
+ render: (text, record) => {
|
|
|
+ const { no } = this.state;
|
|
|
+ if (no === record.no) {
|
|
|
+ // 当前正在
|
|
|
+ }
|
|
|
+ return `课时 ${record.no}: ${text}`;
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
- key: '2',
|
|
|
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.times : 0;
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <div className="v-a-m d-i-b">
|
|
|
+ <ProgressText width={50} size="small" times={times} progress={progress} unit="次" />
|
|
|
+ </div>
|
|
|
+ {!text.report && (
|
|
|
+ <IconButton
|
|
|
+ className="m-l-2"
|
|
|
+ type="start"
|
|
|
+ tip="Start"
|
|
|
+ onClick={() => {
|
|
|
+ User.needLogin().then(() => {
|
|
|
+ Question.startLink('preview', text);
|
|
|
+ });
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ {text.report && !text.report.isFinish && (
|
|
|
+ <IconButton
|
|
|
+ className="m-l-2"
|
|
|
+ type="continue"
|
|
|
+ tip="Continue"
|
|
|
+ onClick={() => {
|
|
|
+ User.needLogin().then(() => {
|
|
|
+ Question.continueLink('preview', text);
|
|
|
+ });
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ {text.report && !!text.report.isFinish && (
|
|
|
+ <IconButton
|
|
|
+ className="m-l-2"
|
|
|
+ type="restart"
|
|
|
+ tip="Restart"
|
|
|
+ onClick={() => {
|
|
|
+ User.needLogin().then(() => {
|
|
|
+ Question.restart('preview', text);
|
|
|
+ });
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ {text.report && !!text.report.isFinish && (
|
|
|
+ <IconButton
|
|
|
+ className="m-l-5"
|
|
|
+ type="report"
|
|
|
+ tip="Report"
|
|
|
+ onClick={() => {
|
|
|
+ User.needLogin().then(() => {
|
|
|
+ Question.reportLink('preview', text);
|
|
|
+ });
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
- key: '3',
|
|
|
- title: '进展',
|
|
|
+ title: '进度',
|
|
|
+ key: 'progress',
|
|
|
+ render: (text, record) => {
|
|
|
+ const { paper = {} } = record;
|
|
|
+ return `${paper.paper && paper.paper.times > 0 ? `${paper.paper.times}次+` : ''}${
|
|
|
+ paper.report ? formatPercent(paper.report.userNumber, paper.report.questionNumber, false) : '0%'}`;
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
- key: '4',
|
|
|
title: '最近学习',
|
|
|
+ key: 'lastTime',
|
|
|
+ render: (text, record) => {
|
|
|
+ const { paper = {} } = record;
|
|
|
+ return paper.report && formatDate(paper.report.updateTime, 'YYYY-MM-DD HH:mm:ss');
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
- key: '5',
|
|
|
title: '笔记',
|
|
|
+ key: 'note',
|
|
|
+ render: (text, record) => {
|
|
|
+ return <GIcon name="note" active={record.note} />;
|
|
|
+ },
|
|
|
},
|
|
|
{
|
|
|
- key: '6',
|
|
|
title: '问答',
|
|
|
+ key: 'ask',
|
|
|
+ render: (text, record) => {
|
|
|
+ return (
|
|
|
+ <Link to={`/course/answer/${record.courseId}?tab=my&courseNoId=${record.id}`}>{`${record.answerNumber ||
|
|
|
+ 0}/${record.askNumber || 0}`}</Link>
|
|
|
+ );
|
|
|
+ },
|
|
|
},
|
|
|
];
|
|
|
return {
|
|
@@ -45,11 +141,97 @@ export default class extends Page {
|
|
|
key: '1',
|
|
|
add: false,
|
|
|
list: [{ key: '1' }, { key: '2' }, { key: '3' }],
|
|
|
- progress: 0,
|
|
|
- data: { title: '语法SC系统授课—课时10:逻辑语义解题专题讲解(1)' },
|
|
|
+ data: {},
|
|
|
+ position: 0,
|
|
|
};
|
|
|
}
|
|
|
|
|
|
+ init() {
|
|
|
+ Main.dataStruct().then(result => {
|
|
|
+ const dataStructSelect = result.map(row => {
|
|
|
+ return {
|
|
|
+ title: `${row.titleZh}${row.titleEn}`,
|
|
|
+ key: row.id,
|
|
|
+ };
|
|
|
+ });
|
|
|
+ const dataStructMap = getMap(dataStructSelect, 'key');
|
|
|
+ this.setState({ dataStructSelect, dataStructMap });
|
|
|
+ });
|
|
|
+ Main.getBase().then(result => {
|
|
|
+ this.setState({ base: result });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ formatRecord(row) {
|
|
|
+ row.paperMap = {};
|
|
|
+ if (row.papers) {
|
|
|
+ row.papers.forEach(paper => {
|
|
|
+ if (paper.courseNo) row.paperMap[paper.courseNo] = paper;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ row.progressMap = {};
|
|
|
+ if (row.progress) {
|
|
|
+ row.progress.forEach(progress => {
|
|
|
+ row.progressMap[progress.courseNoId] = progress;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ row.courseNoMap = {};
|
|
|
+ row.courseTime = 0;
|
|
|
+ if (row.courseNos) {
|
|
|
+ row.courseNos.forEach(no => {
|
|
|
+ row.courseNoMap[no.id] = no;
|
|
|
+ row.courseTime += no.time;
|
|
|
+ no.paper = row.paperMap[no.id];
|
|
|
+ no.progress = row.progressMap[no.id];
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (row.currentNo) {
|
|
|
+ row.currentCourseNo = row.courseNoMap[row.currentNo];
|
|
|
+ } else {
|
|
|
+ row.currentNo = 0;
|
|
|
+ }
|
|
|
+ return row;
|
|
|
+ }
|
|
|
+
|
|
|
+ initData() {
|
|
|
+ const { id } = this.params;
|
|
|
+ Course.detail(id).then(result => {
|
|
|
+ result = this.formatRecord(result);
|
|
|
+ this.setState({ data: result });
|
|
|
+ // 选择课时
|
|
|
+ if (this.state.search.no) {
|
|
|
+ this.onChangeItem(this.state.search.no);
|
|
|
+ } else {
|
|
|
+ this.onChangeItem(1);
|
|
|
+ }
|
|
|
+ this.refreshNote();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ refreshAsk(position) {
|
|
|
+ const { id } = this.params;
|
|
|
+ const { item } = this.state;
|
|
|
+ Course.listAsk(Object.assign({ page: 1, size: 1000, courseId: id, courseNoId: item.id, position })).then(result => {
|
|
|
+ this.setState({ asks: result.list });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ refreshNote() {
|
|
|
+ const { id } = this.params;
|
|
|
+ const { data } = this.state;
|
|
|
+ if (!data.have) return;
|
|
|
+ My.listCourseNote({ courseId: id, page: 1, size: data.courseNos.length })
|
|
|
+ .then((result) => {
|
|
|
+ this.noteMap = getMap(result.list, 'courseNoId');
|
|
|
+ data.courseNos.forEach((row) => {
|
|
|
+ const note = this.noteMap[row.id];
|
|
|
+ if (note) row.note = true;
|
|
|
+ });
|
|
|
+ this.setState({ data });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
onChangeRightTab(rightTab) {
|
|
|
this.setState({ rightTab });
|
|
|
}
|
|
@@ -59,16 +241,77 @@ export default class extends Page {
|
|
|
}
|
|
|
|
|
|
onChangeItem(key) {
|
|
|
- this.setState({ key });
|
|
|
+ key = Number(key);
|
|
|
+ this.changeQuery({ no: key });
|
|
|
+ this.setState({ no: key });
|
|
|
+ const { data, item } = this.state;
|
|
|
+ const index = key - 1;
|
|
|
+ const timelineSelect = [];
|
|
|
+ const current = data.courseNos[index];
|
|
|
+ if (current) {
|
|
|
+ const max = current.time;
|
|
|
+ let start = 0;
|
|
|
+ let end = start + 5;
|
|
|
+ while (start < max) {
|
|
|
+ timelineSelect.push({
|
|
|
+ title: `${start} - ${end}min`,
|
|
|
+ key: `${start}`,
|
|
|
+ });
|
|
|
+ start += 5;
|
|
|
+ end = Math.min(start + 5, max);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 切换播放,记录进度
|
|
|
+ if (item) {
|
|
|
+ this.updateProgress(item.id, this.lastSecond, item.time, true);
|
|
|
+ }
|
|
|
+ this.setState({ item: current, timelineSelect });
|
|
|
+ }
|
|
|
+
|
|
|
+ onTimeUpdate(second) {
|
|
|
+ const { position, item, data } = this.state;
|
|
|
+ if (!data.have) {
|
|
|
+ // 如果是试用,则按秒数增加
|
|
|
+ second += item.startTrail * 60;
|
|
|
+ }
|
|
|
+ const minute = second / 60;
|
|
|
+ const nowPosition = (minute / 5) * 5;
|
|
|
+ if (nowPosition !== position) {
|
|
|
+ this.refreshAsk(position);
|
|
|
+ this.setState({ position: nowPosition });
|
|
|
+ // 定时更新进度
|
|
|
+ this.updateProgress(item.id, second, item.time);
|
|
|
+ }
|
|
|
+ this.lastSecond = second;
|
|
|
+ }
|
|
|
+
|
|
|
+ playVideo() {
|
|
|
+ // 开始计时
|
|
|
+ this.lastTime = new Date();
|
|
|
+ }
|
|
|
+
|
|
|
+ pauseVideo() {
|
|
|
+ // 停止计时
|
|
|
+ const now = new Date();
|
|
|
+ this.time += (now.getTime() - this.lastTime.getTime()) / 1000;
|
|
|
+ this.lastTime = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ next() {
|
|
|
+ const { data, item } = this.state;
|
|
|
+ if (data.courseNos.length === item.no) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.onChangeItem(item.no + 1);
|
|
|
}
|
|
|
|
|
|
onVideoAction(key) {
|
|
|
- const { rightTab, showTab, showQuestion, showNote } = this.state;
|
|
|
+ const { rightTab, showTab, showAsk, showNote, item } = this.state;
|
|
|
switch (key) {
|
|
|
- case 'question':
|
|
|
- return this.setState({ showQuestion: !showQuestion });
|
|
|
+ case 'ask':
|
|
|
+ return this.setState({ showAsk: !showAsk });
|
|
|
case 'note':
|
|
|
- return this.setState({ showNote: !showNote });
|
|
|
+ return this.setState({ showNote: !showNote, note: this.noteMap ? this.noteMap[item.id] || {} : {} });
|
|
|
case 'answer':
|
|
|
return this.setState({ showTab: rightTab === '1' ? !showTab : true, rightTab: '1' });
|
|
|
case 'list':
|
|
@@ -78,42 +321,94 @@ export default class extends Page {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ updateProgress(courseNoId, currentTime, totalTime, record) {
|
|
|
+ if (!this.lastTime) return;
|
|
|
+ const { id } = this.params;
|
|
|
+ const now = new Date();
|
|
|
+ this.time += (now.getTime() - this.lastTime.getTime()) / 1000;
|
|
|
+ this.lastTime = now;
|
|
|
+ const progress = formatPercent(currentTime, totalTime);
|
|
|
+ if (record || this.time > 600) {
|
|
|
+ // 最长5分钟记录一次
|
|
|
+ Course.noProgress(id, courseNoId, progress, this.time, courseNoId);
|
|
|
+ this.time = 0;
|
|
|
+ } else {
|
|
|
+ Course.noProgress(id, courseNoId, progress, null, null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ buy() {
|
|
|
+ const { data } = this.props;
|
|
|
+ User.needLogin().then(() => {
|
|
|
+ Order.speedPay({ productType: 'course', productId: data.id }).then(result => {
|
|
|
+ User.needPay(result).then(() => {
|
|
|
+ this.refresh();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ add() {
|
|
|
+ const { data } = this.props;
|
|
|
+ User.needLogin().then(() => {
|
|
|
+ Order.addCheckout({ productType: 'course', productId: data.id }).then(() => {
|
|
|
+ this.setState({ add: true });
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ viewAsk(id) {
|
|
|
+ Course.askView(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ setVideo(video) {
|
|
|
+ this.video = video;
|
|
|
+ }
|
|
|
+
|
|
|
renderView() {
|
|
|
- const { base = {}, data = {}, add, progress, rightTab, showTab, showQuestion, showNote } = this.state;
|
|
|
+ const { base = {}, data = {}, item = {}, add, progress, rightTab, showTab, showAsk, showNote, dataStructMap = {}, showComment, comment = {}, showFaq, faq = {}, showFinish, note = {}, ask = {}, timelineSelect = [] } = this.state;
|
|
|
+ const { courseNos = [] } = data;
|
|
|
return (
|
|
|
<div>
|
|
|
<div className="top content t-8">
|
|
|
- 千行课堂 > 全部套餐 > {data.title} > <span className="t-1">课程详情</span>
|
|
|
+ 千行课堂 > 全部课程 > {data.parentStructId > 0 ? `${(dataStructMap[data.parentStructId] || {}).title} >` : ''}{' '}
|
|
|
+ {(dataStructMap[data.structId] || {}).title} > {data.title} > <span className="t-1">课程详情</span>
|
|
|
</div>
|
|
|
<div className="center content">
|
|
|
<div className="t-1 t-s-20">
|
|
|
{data.title}
|
|
|
<div className="action f-r">
|
|
|
- <Button className="m-r-1" radius size="lager" onClick={() => this.buy()}>
|
|
|
+ {!data.have && <Button className="m-r-1" radius size="lager" onClick={() => this.buy()}>
|
|
|
立即购买
|
|
|
- </Button>
|
|
|
- <Button theme="default" radius size="lager" disabled={data.add || add} onClick={() => this.add()}>
|
|
|
+ </Button>}
|
|
|
+ {!data.have && <Button theme="default" radius size="lager" disabled={data.add || add} onClick={() => this.add()}>
|
|
|
<Assets name="add" />
|
|
|
- </Button>
|
|
|
+ </Button>}
|
|
|
+ {data.have && <Button className="m-r-1" radius size="lager" onClick={() => linkTo('/my/course')}>
|
|
|
+ 我的课程
|
|
|
+ </Button>}
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div className="t-2 m-b-1">授课老师:李奕都</div>
|
|
|
+ <div className="t-2 m-b-1">授课老师:{data.teacher}</div>
|
|
|
<div className="detail">
|
|
|
<div className="left">
|
|
|
- <div hidden={progress === 0} className="left-top">
|
|
|
+ {data.have && <div hidden={(item.paper && item.paper.times > 0)} className="left-top">
|
|
|
<span className="d-i-b m-r-1">预习作业</span>
|
|
|
<span className="d-i-b m-r-2">
|
|
|
- <ProgressText width={480} size="small" progress={progress} />
|
|
|
+ <ProgressText width={480} size="small" progress={item.report ? formatPercent(item.report.userNumber, item.report.questionNumber) : 0} />
|
|
|
</span>
|
|
|
- <Button className="f-r" radius>
|
|
|
+ <Button className="f-r" radius onClick={() => (item.report ? Question.continueLink('preview', item) : Question.startLink('preview', item))}>
|
|
|
做题
|
|
|
</Button>
|
|
|
- </div>
|
|
|
+ </div>}
|
|
|
<div className="video-layout">
|
|
|
- <Video
|
|
|
- src="/01.mp4"
|
|
|
+ {item && <Video
|
|
|
+ key={item.id}
|
|
|
+ src={item.resource}
|
|
|
+ duration={10}
|
|
|
+ ref={ref => this.setVideo(ref)}
|
|
|
btnList={[
|
|
|
- { title: '提问', key: 'question', active: showQuestion },
|
|
|
+ { title: '提问', key: 'ask', show: data.have, active: showAsk, pause: true },
|
|
|
{
|
|
|
key: 'answer',
|
|
|
render(active) {
|
|
@@ -122,10 +417,14 @@ export default class extends Page {
|
|
|
full: true,
|
|
|
active: showTab && rightTab === '1',
|
|
|
},
|
|
|
- { title: '笔记', key: 'note', active: showNote },
|
|
|
+ { title: '笔记', key: 'note', show: data.have, active: showNote, pause: true },
|
|
|
{ title: '课表', key: 'list', full: true, active: showTab && rightTab === '2' },
|
|
|
]}
|
|
|
+ onPlay={() => this.playVideo()}
|
|
|
+ onPause={() => this.pauseVideo()}
|
|
|
+ onNext={() => this.next()}
|
|
|
onAction={key => this.onVideoAction(key)}
|
|
|
+ onTimeUpdate={time => this.onTimeUpdate(time)}
|
|
|
onFullChange={() => this.setState({ showTab: true, rightTab: '1' })}
|
|
|
>
|
|
|
<div hidden={!showTab} className="video-fixed tab-warpper">
|
|
@@ -139,7 +438,7 @@ export default class extends Page {
|
|
|
/>
|
|
|
<div className="tab-body">{this[`renderRightTab${rightTab}`]()}</div>
|
|
|
</div>
|
|
|
- </Video>
|
|
|
+ </Video>}
|
|
|
</div>
|
|
|
</div>
|
|
|
<div className={`right ${progress > 0 ? 'progress' : ''} tab-warpper`}>
|
|
@@ -154,27 +453,44 @@ export default class extends Page {
|
|
|
<div className="tab-body">{this[`renderRightTab${rightTab}`]()}</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <UserTable columns={this.columns} />
|
|
|
+ {data.have && <UserTable columns={this.columns} list={courseNos} />}
|
|
|
</div>
|
|
|
- <div className="bottom">
|
|
|
+ <div hidden={data.have} className="bottom">
|
|
|
<div className="content">{this.renderTab()}</div>
|
|
|
</div>
|
|
|
<Contact data={base.contact} />
|
|
|
<Footer />
|
|
|
- </div>
|
|
|
+ <AskCourseModal show={showAsk} defaultData={ask} course={data} courseNo={item} selectList={timelineSelect} onConfirm={() => this.setState({ showAsk: false })} onCancel={() => this.setState({ showAsk: false })} />
|
|
|
+ <CourseNoteModal show={showNote} defaultData={note} course={data} courseNos={courseNos} noteMap={this.noteMap} onConfirm={() => {
|
|
|
+ this.setState({ showNote: false });
|
|
|
+ this.refreshNote();
|
|
|
+ }} onCancel={() => this.setState({ showNote: false })} />
|
|
|
+ <CommentModal
|
|
|
+ show={showComment}
|
|
|
+ defaultData={comment}
|
|
|
+ onConfirm={() => this.setState({ showComment: false, showFinish: true })}
|
|
|
+ onCancel={() => this.setState({ showComment: false })}
|
|
|
+ onClose={() => this.setState({ showComment: false })}
|
|
|
+ />
|
|
|
+ <FaqModal show={showFaq} defaultData={faq} onCancel={() => this.setState({ showFaq: false })} onConfirm={() => this.setState({ showFaq: false, showFinish: true })} />
|
|
|
+ <FinishModal
|
|
|
+ show={showFinish}
|
|
|
+ onConfirm={() => this.setState({ showFinish: false })}
|
|
|
+ />,
|
|
|
+ </div >
|
|
|
);
|
|
|
}
|
|
|
|
|
|
renderRightTab1() {
|
|
|
- const { list = [] } = this.state;
|
|
|
+ const { asks = [], data = {}, position } = this.state;
|
|
|
return [
|
|
|
<div className="all-answer">
|
|
|
<span className="d-i-b b m-r-5" />
|
|
|
- <span className="d-i-b t-6">35:00 ~ 40:00</span>
|
|
|
- <span className="f-r d-i-b t-4 c-p">全部问答 ></span>
|
|
|
+ <span className="d-i-b t-6">{position}:00~{position + 5}:00</span>
|
|
|
+ <a className="f-r d-i-b t-4 c-p" href={`/course/answer/${data.id}`} target="_blank">全部问答 ></a>
|
|
|
</div>,
|
|
|
<div className="answer-layout">
|
|
|
- {list.map(item => {
|
|
|
+ {asks.map(item => {
|
|
|
return (
|
|
|
<div className="answer-item">
|
|
|
<div>
|
|
@@ -190,7 +506,7 @@ export default class extends Page {
|
|
|
)}
|
|
|
{item.answerStatus > 0 && (
|
|
|
<div className="desc">
|
|
|
- <OpenText>{item.answer}</OpenText>
|
|
|
+ <OpenText onOpen={() => this.viewAsk(item.id)}>{item.answer}</OpenText>
|
|
|
</div>
|
|
|
)}
|
|
|
</div>
|
|
@@ -201,14 +517,15 @@ export default class extends Page {
|
|
|
}
|
|
|
|
|
|
renderRightTab2() {
|
|
|
- const { list = [], key } = this.state;
|
|
|
+ const { data = {}, no } = this.state;
|
|
|
+ const { courseNos = [] } = data;
|
|
|
return (
|
|
|
<div className="item-layout">
|
|
|
- {list.map(item => {
|
|
|
+ {courseNos.map(item => {
|
|
|
return (
|
|
|
- <div className={`item ${item.key === key ? 'active' : ''}`} onClick={() => this.onChangeItem(item.key)}>
|
|
|
- <span className="t-1">课时1</span>
|
|
|
- <span className="t-2">解读句子结构</span>
|
|
|
+ <div className={`item ${item.no === no ? 'active' : ''}`} onClick={() => this.onChangeItem(item.no)}>
|
|
|
+ <span className="t-1">课时{item.no}</span>
|
|
|
+ <span className="t-2">{item.title}</span>
|
|
|
</div>
|
|
|
);
|
|
|
})}
|
|
@@ -242,49 +559,26 @@ export default class extends Page {
|
|
|
}
|
|
|
|
|
|
renderTab1() {
|
|
|
+ const { data = {} } = this.state;
|
|
|
return (
|
|
|
<div className="tab-layout">
|
|
|
<div className="tab-title">老师资历</div>
|
|
|
- <div className="tab-desc">
|
|
|
- 已经参加过GMAT基础班,对GMAT考试内容已经有全面认识,已经掌握了GMAT考试所需要的所有语言能力,希望学习具体的做题方法和应试技巧,提高实战做题能力的学员;
|
|
|
- 住宿管理, 让学生高效利用时间在最短的时间内攻破GMAT考试。
|
|
|
- 已经参加过GMAT基础班,对GMAT考试内容已经有全面认识,已经掌握了GMAT考试所需要的所有语言能力,希望学习具体的做题方法和应试技巧,提高实战做题能力的学员;
|
|
|
- 住宿管理, 让学生高效利用时间在最短的时间内攻破GMAT考试。
|
|
|
- </div>
|
|
|
+ <div className="tab-desc" dangerouslySetInnerHTML={{ __html: data.teacherContent }} />
|
|
|
<div className="tab-title">基本参数</div>
|
|
|
- <div className="tab-desc">
|
|
|
- 已经参加过GMAT基础班,对GMAT考试内容已经有全面认识,已经掌握了GMAT考试所需要的所有语言能力,希望学习具体的做题方法和应试技巧,提高实战做题能力的学员;
|
|
|
- 住宿管理, 让学生高效利用时间在最短的时间内攻破GMAT考试。
|
|
|
- 已经参加过GMAT基础班,对GMAT考试内容已经有全面认识,已经掌握了GMAT考试所需要的所有语言能力,希望学习具体的做题方法和应试技巧,提高实战做题能力的学员;
|
|
|
- 住宿管理, 让学生高效利用时间在最短的时间内攻破GMAT考试。
|
|
|
- </div>
|
|
|
+ <div className="tab-desc" dangerouslySetInnerHTML={{ __html: data.baseContent }} />
|
|
|
<div className="tab-title">授课重点</div>
|
|
|
- <div className="tab-desc">
|
|
|
- 已经参加过GMAT基础班,对GMAT考试内容已经有全面认识,已经掌握了GMAT考试所需要的所有语言能力,希望学习具体的做题方法和应试技巧,提高实战做题能力的学员;
|
|
|
- 住宿管理, 让学生高效利用时间在最短的时间内攻破GMAT考试。
|
|
|
- 已经参加过GMAT基础班,对GMAT考试内容已经有全面认识,已经掌握了GMAT考试所需要的所有语言能力,希望学习具体的做题方法和应试技巧,提高实战做题能力的学员;
|
|
|
- 住宿管理, 让学生高效利用时间在最短的时间内攻破GMAT考试。
|
|
|
- </div>
|
|
|
+ <div className="tab-desc" dangerouslySetInnerHTML={{ __html: data.pointContent }} />
|
|
|
<div className="tab-title">适合人群</div>
|
|
|
- <div className="tab-desc">
|
|
|
- 已经参加过GMAT基础班,对GMAT考试内容已经有全面认识,已经掌握了GMAT考试所需要的所有语言能力,希望学习具体的做题方法和应试技巧,提高实战做题能力的学员;
|
|
|
- 住宿管理, 让学生高效利用时间在最短的时间内攻破GMAT考试。
|
|
|
- 已经参加过GMAT基础班,对GMAT考试内容已经有全面认识,已经掌握了GMAT考试所需要的所有语言能力,希望学习具体的做题方法和应试技巧,提高实战做题能力的学员;
|
|
|
- 住宿管理, 让学生高效利用时间在最短的时间内攻破GMAT考试。
|
|
|
- </div>
|
|
|
+ <div className="tab-desc" dangerouslySetInnerHTML={{ __html: data.crowdContent }} />
|
|
|
</div>
|
|
|
);
|
|
|
}
|
|
|
|
|
|
renderTab2() {
|
|
|
+ const { data } = this.state;
|
|
|
return (
|
|
|
<div className="tab-layout">
|
|
|
- <div className="tab-desc">
|
|
|
- 已经参加过GMAT基础班,对GMAT考试内容已经有全面认识,已经掌握了GMAT考试所需要的所有语言能力,希望学习具体的做题方法和应试技巧,提高实战做题能力的学员;
|
|
|
- 住宿管理, 让学生高效利用时间在最短的时间内攻破GMAT考试。
|
|
|
- 已经参加过GMAT基础班,对GMAT考试内容已经有全面认识,已经掌握了GMAT考试所需要的所有语言能力,希望学习具体的做题方法和应试技巧,提高实战做题能力的学员;
|
|
|
- 住宿管理, 让学生高效利用时间在最短的时间内攻破GMAT考试。
|
|
|
- </div>
|
|
|
+ <div className="tab-desc" dangerouslySetInnerHTML={{ __html: data.syllabusContent }} />
|
|
|
</div>
|
|
|
);
|
|
|
}
|
|
@@ -306,47 +600,40 @@ export default class extends Page {
|
|
|
}
|
|
|
|
|
|
renderTab4() {
|
|
|
+ const { faqs, data = {}, showFaq, faq } = this.state;
|
|
|
return (
|
|
|
<div className="tab-layout">
|
|
|
<AnswerCarousel
|
|
|
hideBtn
|
|
|
- list={[
|
|
|
- { answer: '123123', content: '12312312' },
|
|
|
- { answer: '123123', content: '12312312' },
|
|
|
- { answer: '123123', content: '12312312' },
|
|
|
- { answer: '123123', content: '12312312' },
|
|
|
- ]}
|
|
|
+ list={faqs}
|
|
|
+ onFaq={() => this.setState({ showFaq: true, faq: { channel: 'course-video', position: data.id } })}
|
|
|
/>
|
|
|
+ <FaqModal show={showFaq} defaultData={faq} onCancel={() => this.setState({ showFaq: false })} onConfirm={() => this.setState({ showFaq: false })} />
|
|
|
</div>
|
|
|
);
|
|
|
}
|
|
|
|
|
|
renderTab5() {
|
|
|
+ const { data = {} } = this.state;
|
|
|
return (
|
|
|
<div className="tab-layout">
|
|
|
- <div className="tab-desc">
|
|
|
- 已经参加过GMAT基础班,对GMAT考试内容已经有全面认识,已经掌握了GMAT考试所需要的所有语言能力,希望学习具体的做题方法和应试技巧,提高实战做题能力的学员;
|
|
|
- 住宿管理, 让学生高效利用时间在最短的时间内攻破GMAT考试。
|
|
|
- 已经参加过GMAT基础班,对GMAT考试内容已经有全面认识,已经掌握了GMAT考试所需要的所有语言能力,希望学习具体的做题方法和应试技巧,提高实战做题能力的学员;
|
|
|
- 住宿管理, 让学生高效利用时间在最短的时间内攻破GMAT考试。
|
|
|
- </div>
|
|
|
+ <div className="tab-desc" dangerouslySetInnerHTML={{ __html: data.promoteContent }} />
|
|
|
</div>
|
|
|
);
|
|
|
}
|
|
|
|
|
|
renderTab6() {
|
|
|
+ const { data = {}, comments = [] } = this.state;
|
|
|
return (
|
|
|
<div className="tab-layout">
|
|
|
- <div className="m-b-1 t-r">
|
|
|
- <Button width={100} radius>
|
|
|
+ {data.have && <div className="m-b-1 t-r">
|
|
|
+ <Button width={100} radius onClick={() => User.needLogin().then(() => this.setState({ showComment: true, comment: { channel: 'course-video', position: data.id } }))}>
|
|
|
写评论
|
|
|
</Button>
|
|
|
- </div>
|
|
|
- <Comment />
|
|
|
- <Comment />
|
|
|
- <Comment />
|
|
|
- <Comment />
|
|
|
- <Comment />
|
|
|
+ </div>}
|
|
|
+ {(comments || []).map(item => {
|
|
|
+ return <Comment data={item} />;
|
|
|
+ })}
|
|
|
</div>
|
|
|
);
|
|
|
}
|