123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593 |
- import React, { Component } from 'react';
- import { Link } from 'react-router-dom';
- import './index.less';
- import { Icon, Dropdown } from 'antd';
- 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 UserLayout from '../../../layouts/User';
- import Button from '../../../components/Button';
- import ProgressText from '../../../components/ProgressText';
- import IconButton from '../../../components/IconButton';
- import { Icon as GIcon } from '../../../components/Icon';
- import menu from '../index';
- import Tabs from '../../../components/Tabs';
- import UserTable from '../../../components/UserTable';
- import More from '../../../components/More';
- import Modal from '../../../components/Modal';
- import DatePlane from '../../../components/Date';
- import Note from '../../../components/Note';
- import { My } from '../../../stores/my';
- import { Order } from '../../../stores/order';
- import { Common } from '../../../stores/common';
- export default class extends Page {
- initState() {
- return {
- tab: 'online',
- status: 'all',
- };
- }
- formatRecord(row) {
- if (row.useEndTime) {
- if (row.isSuspend && !row.restoreTime) {
- row.status = 'suspend';
- } else if (new Date(row.useEndTime).getTime() < new Date().getTime()) {
- row.status = 'end';
- } else {
- row.status = 'ing';
- }
- } else {
- row.status = 'not';
- }
- row.paperMap = {};
- row.appointmentPaperMap = {};
- if (row.papers) {
- row.papers.forEach(paper => {
- if (paper.courseNo) row.paperMap[paper.courseNo] = paper;
- if (paper.appointment) row.appointmentPaperMap[paper.appointment] = 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;
- }
- // 如果已经最新预约结束,则添加一个空记录作为最新预约
- if (row.appointments) {
- row.appointments.forEach(r => {
- r.paper = row.appointmentPaperMap[r.id];
- r.noteList = (row.comments || []).filter(c => c.type === 'note' && c.appointmentId === r.id);
- r.supplyList = (row.comments || []).filter(c => c.type === 'supply' && c.appointmentId === r.id);
- });
- // 是否是最后一课时,是否过预约时间
- 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([{}]);
- }
- }
- }
- row.days = new Date(row.userEndTime);
- return row;
- }
- initData() {
- const data = Object.assign(this.state, this.state.search);
- data.filterMap = this.state.search;
- if (data.order) {
- data.sortMap = { [data.order]: data.direction };
- }
- this.setState(data);
- let isUsed = null;
- let isEnd = null;
- switch (data.status) {
- case 'learning':
- isUsed = true;
- isEnd = false;
- break;
- case 'end':
- isUsed = true;
- isEnd = true;
- break;
- case 'nouse':
- isUsed = false;
- isEnd = false;
- break;
- case 'all':
- default:
- }
- My.listCourse(Object.assign({ courseModule: data.tab }, this.state.search, { isUsed, isEnd })).then(result => {
- result.list = result.list.map(row => {
- return this.formatRecord(row);
- });
- this.setState({ list: result.list, total: result.total, page: data.page });
- });
- }
- onAction() { }
- onTabChange(tab) {
- const data = { tab };
- this.refreshQuery(data);
- }
- onStatusChange(status) {
- this.search({ status });
- }
- openTime(record) {
- if (record.courseTimeMap) {
- this.setState({ data: record, showTime: true });
- return;
- }
- My.timeCourse(record.id).then(result => {
- const courseMap = {};
- const previewMap = {};
- const stopMap = {};
- result.forEach(row => {
- const date = formatDate(row.day, 'YYYY-MM-DD');
- if (row.type === 'stop') {
- stopMap[date] = true;
- } else if (row.type === 'preview') {
- previewMap[date] = true;
- } else if (row.type === 'course') {
- courseMap[date] = true;
- }
- });
- record.courseTimeMap = courseMap;
- record.previewTimeMap = previewMap;
- record.stopTimeMap = stopMap;
- this.setState({ data: record, showTime: true });
- });
- }
- refreshDetail(recordId) {
- My.detailCourse(recordId).then(result => {
- let { list } = this.state;
- list = list.map(row => {
- if (row.id === recordId) return this.formatRecord(result);
- return row;
- });
- this.setState({ list });
- });
- }
- suspend() {
- const { suspend } = this.state;
- My.suspendCourse(suspend.id)
- .then(() => {
- asyncSMessage('停课成功');
- this.setState({ showSuspend: false });
- this.refreshDetail(suspend.id);
- })
- .catch(err => {
- asyncSMessage(err.message, 'error');
- });
- }
- restore() {
- const { restore } = this.state;
- My.restoreCourse(restore.id)
- .then(() => {
- asyncSMessage('恢复成功');
- this.setState({ showRestore: false });
- this.refreshDetail(restore.id);
- })
- .catch(err => {
- asyncSMessage(err.message, 'error');
- });
- }
- submitAppointmentComment(data, type) {
- data.type = type;
- if (data.id) {
- My.editAppointmentComment(data).then(() => {
- this.refreshDetail(data.recordId);
- });
- } else {
- My.addAppointmentComment(data).then(() => {
- this.refreshDetail(data.recordId);
- });
- }
- }
- deleteAppointmentComment(row) {
- My.delAppointmentComment(row.id).then(() => {
- this.refreshDetail(row.recordId);
- });
- }
- submitQuestionFile(data) {
- My.uploadAppointmentQuestion(data).then(() => {
- this.refreshDetail(data.recordId);
- });
- }
- setCCTalkName(recordId, cctalkname) {
- My.setCCTalkName(recordId, cctalkname).then(() => {
- this.refreshDetail(recordId);
- });
- }
- submitComment() {
- const { comment } = this.state;
- My.addComment(comment.channel, comment.position, comment.content).then(() => {
- this.setState({ showComment: false, showFinish: true, comment: {} });
- });
- }
- open(recordId) {
- Order.useRecord(recordId).then(() => {
- asyncSMessage('开通成功');
- this.refreshDetail(recordId);
- });
- }
- closeCommentTips(recordId) {
- My.courseCommentTips(recordId);
- }
- uploadNote(file) {
- const { note = {} } = this.state;
- Common.uploadImage(file).then(result => {
- note.file = result.url;
- note.name = file.name;
- this.setState({ note });
- });
- }
- uploadSupply(file) {
- const { supply = {} } = this.state;
- Common.uploadImage(file).then(result => {
- supply.file = result.url;
- supply.name = file.name;
- this.setState({ supply });
- });
- }
- renderView() {
- const { config } = this.props;
- return <UserLayout active={config.key} menu={menu} center={this.renderDetail()} />;
- }
- renderDetail() {
- const {
- tab,
- status,
- showTips,
- showTime,
- showSuspend,
- showRestore,
- showUploadNote,
- showUploadSupply,
- showSupply,
- showNote,
- showComment,
- showFinish,
- comment = {},
- data = {},
- note = {},
- supply = {},
- appointment = {},
- } = this.state;
- return (
- <div className="detail-layout">
- <div hidden={!showTips} className="tip">
- <div className="text">理清备考思路,避开常见误区,让学习的每一分钟发光发热!</div>
- <a href="" target="_blank">
- 去填写 >
- </a>
- <Icon type="close-circle" theme="filled" onClick={() => this.setState({ showTips: false })} />
- </div>
- <Tabs
- type="division"
- theme="theme"
- size="small"
- space={2.5}
- width={100}
- active={tab}
- tabs={[{ key: 'online', title: '在线课程' }, { key: 'vs', title: '1V1私教' }]}
- onChange={key => this.onTabChange(key)}
- />
- <Tabs
- type="tag"
- theme="white"
- size="small"
- space={5}
- width={54}
- active={status}
- tabs={[
- { key: 'all', title: '全部' },
- { key: 'nouse', title: '未开通' },
- { key: 'learning', title: '学习中' },
- { key: 'end', title: '已结束' },
- ]}
- onChange={key => this.onStatusChange(key)}
- />
- {this[`renderTab${tab}`]()}
- <Modal show={showTime} className="clock-modal" title="打卡表" width={460} onClose={() => this.setState({ showTime: false })}>
- <div>
- <div className="d-i-b w-3">
- <div className="t-2 t-s-14">听课频率</div>
- <div className="t-4 t-s-18">{data.currentNo ? data.totalDays / data.currentNo : 0}天/课时</div>
- </div>
- <div className="d-i-b w-3">
- <div className="t-2 t-s-14">作业完成度</div>
- <div className="t-4 t-s-18">{data.previewProgress || 0}%</div>
- </div>
- </div>
- <div className="b-b m-t-1 m-b-1" />
- <div className="m-b-1">
- <div className="tag d-i-b t-s-16">
- <i style={{ background: '#6865FD' }} />
- 听课
- </div>
- <div className="tag d-i-b t-s-16">
- <i style={{ background: '#4299FF' }} />
- 预习
- </div>
- <div className="tag d-i-b t-s-16">
- <i style={{ background: '#E7E7E7' }} />
- 停课
- </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 className="t-2 t-s-12">*听课频率≤2天/课时,作业完成度≥90%,课程有效期可延长7-10天。</div>
- </Modal>
- <Modal
- show={showComment}
- title="评价"
- onConfirm={() => comment.content && this.submitComment()}
- onCancel={() => this.setState({ showComment: false, comment: {} })}
- >
- <textarea
- value={comment.content}
- className="b-c-1 w-10 p-10"
- rows={6}
- placeholder="您的看法对我们来说很重要!"
- onChange={e => {
- comment.content = e.target.value;
- this.setState({ comment });
- }}
- />
- <div className="b-b m-t-2" />
- </Modal>
- <Modal
- show={showFinish}
- title="提交成功"
- confirmText="好的,知道了"
- btnAlign="center"
- onConfirm={() => this.setState({ showFinish: false })}
- >
- <div className="t-2 t-s-18">
- <Icon type="check" className="t-5 m-r-5" />
- 您的每一次反馈都是千行进步的动力。
- </div>
- </Modal>
- <Modal
- show={showSuspend}
- title="申请停课"
- width={630}
- confirmText="立即停课"
- onConfirm={() => this.suspend()}
- onCancel={() => this.setState({ showSuspend: false })}
- >
- <div className="t-2 t-s-18">最长停课周期为1个月,到期后系统自动恢复至“学习中”状态。</div>
- <div className="t-2 t-s-18">每门课程只有一次申请机会,是否需要停课?</div>
- <div style={{ bottom: 20, left: 0 }} className="p-a t-3 t-s-14">
- *停课不影响听课频率的计算;
- </div>
- <div style={{ bottom: 0, left: 0 }} className="p-a t-3 t-s-14">
- {' '}
- 停课期间可随时恢复学习。
- </div>
- </Modal>
- <Modal
- show={showRestore}
- title="恢复学习"
- width={630}
- confirmText="立即恢复"
- onConfirm={() => this.restore()}
- onCancel={() => this.setState({ showRestore: false })}
- >
- <div className="t-2 t-s-18">恢复学习后,本课程的停课功能将无法使用。是否恢复学习?</div>
- </Modal>
- <Modal
- show={showUploadNote}
- title="上传笔记"
- width={630}
- confirmText="提交"
- onConfirm={() => this.submitAppointmentComment(note, 'note')}
- onCancel={() => this.setState({ showUploadNote: false, note: {} })}
- >
- <textarea
- className="b-c-1 w-10 p-10 m-b-1"
- rows={6}
- value={note.content}
- placeholder="请输入留言内容。"
- onChange={e => {
- note.content = e.target.value;
- this.setState({ note });
- }}
- />
- <div className={`t-c drag-upload ${this.state.draging ? 'draging' : ''}`}>
- <Button theme="file">上传文件</Button>
- <span className="m-l-1 t-3 t-s-14">{note.file ? `上传文件:${note.name} 成功` : '支持 docx, xls, PDF, rar, zip, PNG, JPG 等类型的文件'}</span>
- <div className="fixed">
- <span className="f-w-b t-s-18">放开文件立刻上传</span>
- </div>
- <FileUpload
- type="none"
- onDragEnter={() => this.setState({ draging: true })}
- onDragLeave={() => this.setState({ draging: false })}
- onUpload={({ file }) => Common.upload(file).then(result => {
- note.file = result.url;
- note.name = file.name;
- this.setState({ note });
- })}
- />
- </div>
- <div className="b-b m-t-2" />
- </Modal>
- <Modal
- show={showNote}
- title="课后笔记"
- width={500}
- height={500}
- onClose={() => this.setState({ showNote: false })}
- >
- {appointment.noteList &&
- appointment.noteList.map(row => {
- return <Note user={this.props.user} teacher={data.teacher} data={row} />;
- })}
- </Modal>
- <Modal
- show={showSupply}
- title="课后留言"
- width={500}
- height={500}
- onClose={() => this.setState({ showSupply: false })}
- >
- {appointment.supplyList &&
- appointment.supplyList.map(row => {
- return <Note user={this.props.user} teacher={data.teacher} data={row} />;
- })}
- </Modal>
- <Modal
- show={showUploadSupply}
- title="上传留言"
- width={630}
- confirmText="提交"
- onConfirm={() => this.submitAppointmentComment(supply, 'supply')}
- onCancel={() => this.setState({ showUploadSupply: false, supply: {} })}
- >
- <textarea
- className="b-c-1 w-10 p-10 m-b-1"
- rows={6}
- value={supply.content}
- placeholder="请输入留言内容。"
- onChange={e => {
- supply.content = e.target.value;
- this.setState({ supply });
- }}
- />
- <div className={`t-c drag-upload ${this.state.draging ? 'draging' : ''}`}>
- <Button theme="file">上传文件</Button>
- <span className="m-l-1 t-3 t-s-14">{supply.file ? `上传文件:${supply.name} 成功` : '支持 docx, xls, PDF, rar, zip, PNG, JPG 等类型的文件'}</span>
- <div className="fixed">
- <span className="f-w-b t-s-18">放开文件立刻上传</span>
- </div>
- <FileUpload
- type="none"
- onDragEnter={() => this.setState({ draging: true })}
- onDragLeave={() => this.setState({ draging: false })}
- onUpload={({ file }) => Common.upload(file).then(result => {
- supply.file = result.url;
- supply.name = file.name;
- this.setState({ supply });
- })}
- />
- </div>
- <div className="b-b m-t-2" />
- </Modal>
- </div>
- );
- }
- renderTabonline() {
- const { list = [] } = this.state;
- return list.map(item => {
- return (
- <CourseOnline
- data={item}
- user={this.props.user}
- refreshDetail={recordId => {
- this.refreshDetail(recordId);
- }}
- onRestore={() => {
- this.setState({ showRestore: true, restore: item });
- }}
- onSuspend={() => {
- this.setState({ showSuspend: true, suspend: item });
- }}
- onTime={() => {
- this.openTime(item);
- }}
- onComment={() => {
- this.setState({ showComment: true, comment: { channel: 'course-video', position: item.course.id } });
- }}
- closeCommentTips={() => this.closeCommentTips(item.id)}
- />
- );
- });
- }
- renderTabvs() {
- const { list = [] } = this.state;
- return list.map(item => {
- return <CourseVs data={item} user={this.props.user} refreshDetail={(recordId) => {
- this.refreshDetail(recordId);
- }} onRestore={() => {
- this.setState({ showRestore: true, restore: item });
- }} onSuspend={() => {
- this.setState({ showSuspend: true, suspend: item });
- }} onComment={() => {
- this.setState({ showComment: true, comment: { channel: 'course-vs', position: item.course.id } });
- }} closeCommentTips={() => this.closeCommentTips(item.id)}
- onUploadNote={(appointment, row) => this.setState({ showUploadNote: true, appointment, data: item, note: row || {} })}
- onUploadSupply={(appointment, row) => this.setState({ showUploadSupply: true, appointment, data: item, supply: row || {} })}
- onDeleteNote={(appointment, row) => this.deleteAppointmentComment(row)}
- onDeleteSupply={(appointment, row) => this.deleteAppointmentComment(row)}
- onNote={(appointment) => this.setState({ showNote: true, appointment, data: item })}
- onSupply={(appointment) => this.setState({ showSupply: true, appointment, data: item })}
- onUploadQuestion={(appointment, file, name) => this.submitQuestionFile({ id: appointment.id, recordId: appointment.recordId, questionFile: file, questionFileName: name })}
- setCCTalkName={(appointment, cctalkName) => this.setCCTalkName(appointment.recordId, cctalkName)} />;
- });
- }
- }
- class CourseOnline extends Component {
- constructor(props) {
- super(props);
- this.columns = [
- {
- title: '学习内容',
- key: 'title',
- render: (text, record) => {
- return `课时 ${record.no}: ${text}`;
- },
- },
- {
- title: '预习作业',
- key: 'paper',
- 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%'
- }`;
- },
- },
- {
- title: '进度',
- key: 'progress',
- render: (text, record) => {
- return record.progress ? (
- <div>
- <div className="v-a-m d-i-b">
- <ProgressText width={50} size="small" times={1} progress={20} unit="次" />
- </div>
- <IconButton className="m-l-2" type="start" />
- <IconButton className="m-l-5" type="report" />
- </div>
- ) : (
- '-'
- );
- },
- },
- {
- title: '最近学习',
- key: 'lastTime',
- render: (text, record) => {
- const { paper = {} } = record;
- return paper.report && formatDate(paper.report.updateTime, 'YYYY-MM-DD HH:mm:ss');
- },
- },
- {
- title: '笔记',
- key: 'note',
- render: () => {
- return <GIcon name="note" active />;
- },
- },
- {
- title: '问答',
- key: 'ask',
- render: (text, record) => {
- return (
- <Link to={`/course/ask/${record.courseId}?no=${record.id}`}>{`${record.answerNumber ||
- 0}/${record.askNumber || 0}`}</Link>
- );
- },
- },
- ];
- this.state = { open: false };
- }
- render() {
- const { data = {} } = this.props;
- switch (data.status) {
- case 'ing':
- return this.renderIng();
- case 'not':
- return this.renderNot();
- case 'end':
- return this.renderEnd();
- case 'suspend':
- return this.renderSuspend();
- default:
- return <div />;
- }
- }
- renderIng() {
- const { data, onTime, onComment, onSuspend } = this.props;
- const { open } = this.state;
- return (
- <div className="course-item ing">
- <div className="title">
- <div className="tag">学习中</div>
- <div className="text">{data.course.title}</div>
- <div className="right">
- <More
- menu={[{ label: '评价', key: 'comment' }, { label: '停课', key: 'suspend' }]}
- onClick={value => {
- const { key } = value;
- if (key === 'comment') {
- onComment();
- } else if (key === 'suspend') {
- onSuspend();
- }
- }}
- />
- </div>
- </div>
- {data.currentCourseNo && (
- <div
- className="continue"
- onClick={() => {
- linkTo(`/course/detail/${data.course.id}`);
- }}
- >
- <Assets name="notice" />
- 继续学习:课时 {data.currentNo}:{data.currentCourseNo.title}
- </div>
- )}
- <div className="detail">
- <div className="left">
- <Assets name="sun_blue" src={data.course.cover} />
- <div className="info">
- <div className="t1">授课老师</div>
- <div className="t2">{data.course.teacher}</div>
- <div className="t1">有效期</div>
- <div className="t2">{data.useExpireDays}Days</div>
- </div>
- </div>
- <div className="right">
- <div className="item">
- <GIcon name="speed-block" active noHover />
- <div className="text">
- <span>{data.currentNo}</span>/{data.courseNos.length}
- </div>
- </div>
- <div className="item">
- <GIcon name="question-block" active noHover />
- <div className="text">
- <span>{data.answerNumber}</span>/{data.askNumber}
- </div>
- </div>
- <div className="item" onClick={() => onTime()}>
- <GIcon name="clockin-block" active noHover />
- <div className="text">
- <span>{formatSeconds(data.totalTime)}</span> {data.previewProgress || 0}%
- </div>
- </div>
- <div className="item">
- <GIcon name="note-block" active noHover />
- <div className="text">{data.noteNumber}</div>
- </div>
- </div>
- <div className="open">
- <GIcon name={open ? 'up' : 'down'} onClick={() => this.setState({ open: !open })} />
- </div>
- </div>
- {open && this.renderTable()}
- </div>
- );
- }
- renderNot() {
- const { data } = this.props;
- return (
- <div className="course-item not">
- <div className="title">
- <div className="tag">未开通</div>
- <div className="text">{data.course.title}</div>
- </div>
- <div className="detail">
- <div className="left">
- <Assets name="sun_blue" src={data.course.cover} />
- <div className="info">
- <div className="t1">授课老师</div>
- <div className="t2">{data.course.teacher}</div>
- <div>
- <div className="d-i-b m-r-2">
- <div className="t-2">课时</div>
- <div className="t-1 t-s-16">{data.courseNos.length}</div>
- </div>
- <div className="d-i-b">
- <div className="t-2">总时长</div>
- <div className="t-1 t-s-16">{formatSeconds(data.courseTime)}</div>
- </div>
- </div>
- </div>
- </div>
- <div className="right t-c">
- <div className="text">请于 {formatDate(data.endTime, 'YYYY-MM-DD')} 前开通</div>
- <Button
- size="lager"
- radius
- onClick={() => {
- this.open(data.id);
- }}
- >
- 立即开通
- </Button>
- </div>
- </div>
- </div>
- );
- }
- renderEnd() {
- const { data, onTime, onComment } = this.props;
- const { open } = this.state;
- return (
- <div className="course-item end">
- <div className="title">
- <div className="tag">已结束</div>
- <div className="text">{data.course.title}</div>
- <div className="right">
- <More
- menu={[{ label: '评价', key: 'comment' }]}
- onClick={value => {
- const { key } = value;
- if (key === 'comment') {
- onComment();
- }
- }}
- />
- </div>
- </div>
- <div className="detail">
- <div className="left">
- <Assets name="sun_blue" src={data.course.cover} />
- <div className="info">
- <div className="t1">授课老师</div>
- <div className="t2">{data.course.teacher}</div>
- <div className="t1">有效期</div>
- <div className="t-s-12">{formatDate(data.useStartTime, 'YYYY-MM-DD')}<br />至{formatDate(data.useEndTime, 'YYYY-MM-DD')}</div>
- </div>
- </div>
- <div className="right">
- <div className="item">
- <GIcon name="question-block" active noHover />
- <div className="text">
- <span>{data.answerNumber}</span>/{data.askNumber}
- </div>
- </div>
- <div className="item" onClick={() => onTime()}>
- <GIcon name="clockin-block" active noHover />
- <div className="text">
- <span>{formatSeconds(data.totalTime)}</span> {data.previewProgress || 0}%
- </div>
- </div>
- <div className="item">
- <GIcon name="note-block" active noHover />
- <div className="text">{data.noteNumber}</div>
- </div>
- {data.courseAward > 0 && (
- <div className="item">
- <GIcon name="gift-block" active />
- <div className="text">赠送{data.courseAward}天</div>
- </div>
- )}
- </div>
- <div className="open">
- <GIcon name={open ? 'up' : 'down'} onClick={() => this.setState({ open: !open })} />
- </div>
- </div>
- {open && this.renderTable()}
- </div>
- );
- }
- renderSuspend() {
- const { data, onTime, onRestore, onComment } = this.props;
- const { open } = this.state;
- return (
- <div className="course-item end">
- <div className="title">
- <div className="tag">已停课</div>
- <div className="text">
- {data.course.title}
- <Button size="small" radius onClick={() => onRestore()}>
- 恢复上课
- </Button>
- </div>
- <div className="t-s-12">
- <span className="t-3">申请时间:</span>
- <span className="t-2 m-r-1">{formatDate(data.suspendTime, 'YYYY-MM-DD HH:mm:ss')}</span>
- <span className="t-3">已停课:</span>
- <span>{parseInt((new Date().getTime() - new Date(data.suspendTime).getTime()) / 86400000, 10)}Days/30</span>
- </div>
- <div className="right">
- <More
- menu={[{ label: '评价', key: 'comment' }]}
- onClick={value => {
- const { key } = value;
- if (key === 'comment') {
- onComment();
- }
- }}
- />
- </div>
- </div>
- <div className="detail">
- <div className="left">
- <Assets name="sun_blue" src={data.course.cover} />
- <div className="info">
- <div className="t1">授课老师</div>
- <div className="t2">{data.course.teacher}</div>
- <div className="t1">有效期</div>
- <div className="t2">{data.useExpireDays}Days</div>
- </div>
- </div>
- <div className="right">
- <div className="item">
- <GIcon name="speed-block" noHover />
- <div className="text">
- <span>{data.currentNo}</span>/{data.courseNos.length}
- </div>
- </div>
- <div className="item">
- <GIcon name="question-block" active noHover />
- <div className="text">
- <span>{data.answerNumber}</span>/{data.askNumber}
- </div>
- </div>
- <div className="item" onClick={() => onTime()}>
- <GIcon name="clockin-block" active noHover />
- <div className="text">
- <span>{formatSeconds(data.totalTime)}</span> {data.previewProgress || 0}%
- </div>
- </div>
- <div className="item">
- <GIcon name="note-block" active noHover />
- <div className="text">{data.noteNumber}</div>
- </div>
- </div>
- <div className="open">
- <GIcon name={open ? 'up' : 'down'} onClick={() => this.setState({ open: !open })} />
- </div>
- </div>
- {open && this.renderTable()}
- </div>
- );
- }
- renderTable() {
- const { data = {} } = this.props;
- const { courseNos = [] } = data;
- return <UserTable size="small" columns={this.columns} data={courseNos} />;
- }
- }
- const titleMap = {
- 1: '预约时间',
- 2: '答疑文档',
- 3: '上课',
- 4: '课后笔记',
- 5: '课后补充',
- 6: '备考信息',
- 7: '完成作业',
- };
- const iconMap = {
- 1: 'time-icon',
- 2: 'QA-icon',
- 3: 'class-icon',
- 4: 'note-icon',
- 5: 'supplement-icon',
- 6: 'information-icon',
- 7: 'homework-icon',
- };
- const statusMap = {
- 1: appointment => {
- if (!appointment.id) return 'end';
- return '';
- },
- 2: appointment => {
- if (!appointment.questionFile) return 'not';
- return '';
- },
- 3: (appointment, data) => {
- if (!data.cctalkName) return 'not';
- // if (new Date(appointment.endTime).getTime() > new Date()) return 'not';
- return '';
- },
- 4: (appointment) => {
- if (!appointment.noteList || appointment.noteList.length === 0) return 'not';
- return '';
- },
- 5: (appointment) => {
- if (!appointment.supplyList || appointment.supplyList.length === 0) return 'not';
- return '';
- },
- 6: () => {
- return '';
- },
- 7: (appointment) => {
- const { paper = {} } = appointment;
- if (!paper.report || formatPercent(paper.report.userNumber, paper.report.questionNumber) < 100) return 'not';
- return '';
- },
- };
- class CourseVs extends Component {
- constructor(props) {
- super(props);
- this.columns = {
- system: [
- { title: '学习内容', key: 'title' },
- {
- title: '预习作业',
- key: 'paper',
- render: (text, record) => {
- return record.progress ? (
- <div>
- <div className="v-a-m d-i-b">
- <ProgressText width={50} size="small" times={1} progress={20} unit="次" />
- </div>
- <IconButton className="m-l-2" type="start" />
- <IconButton className="m-l-5" type="report" />
- </div>
- ) : (
- '-'
- );
- },
- },
- {
- title: '授课时间',
- key: 'time',
- render: (text, record) => {
- return `${formatDate(record.startTime, 'YYYY-MM-DD HH:mm:ss')} ~ ${formatDate(record.endTime, 'HH:mm:ss')}`;
- },
- },
- {
- title: '课后笔记',
- key: 'note',
- render: (text, record) => {
- return <a onClick={() => this.props.onNote(record)}>查看</a>;
- },
- },
- {
- title: '课后补充',
- key: 'supply',
- render: (text, record) => {
- return <a onClick={() => this.props.onSupply(record)}>查看</a>;
- },
- },
- ],
- answer: [
- { title: '学习内容', key: 'title' },
- {
- title: '答疑文档',
- key: 'questionFile',
- render: (text, record) => {
- return (
- <a href={text} target="_blank">
- {record.questionFileName}
- </a>
- );
- },
- },
- {
- title: '授课时间',
- key: 'time',
- render: (text, record) => {
- return `${formatDate(record.startTime, 'YYYY-MM-DD HH:mm:ss')} ~ ${formatDate(record.endTime, 'HH:mm:ss')}`;
- },
- },
- {
- title: '课后补充',
- key: 'supply',
- render: (text, record) => {
- return <a onClick={() => this.props.onSupply(record)}>查看</a>;
- },
- },
- ],
- };
- this.listMap = {
- novice: [1, 3],
- coach: [1, 6, 3],
- system: [1, 7, 3, 4],
- answer: [1, 2, 3],
- };
- const index = props.data.appointments.length - 1;
- this.state = {
- open: false,
- tab: 'ing',
- index,
- list: this.listMap[this.props.data.course.vsType],
- showTips:
- props.data.commentTips === 0 &&
- (props.data.appointments.length === parseInt(props.data.number / 2, 10) ||
- props.data.appointments.length === props.data.number),
- };
- }
- closeCommentTips() {
- My.courseCommentTips(this.props.data.id).then(() => {
- this.setState({ showTips: false });
- });
- }
- render() {
- const { data = {} } = this.props;
- switch (data.status) {
- case 'ing':
- return this.renderIng();
- case 'not':
- return this.renderNot();
- case 'end':
- return this.renderEnd();
- case 'suspend':
- return this.renderSuspend();
- default:
- return <div />;
- }
- }
- renderIng() {
- const { data, onComment, closeCommentTips } = this.props;
- const { tab, showTips, open } = this.state;
- return (
- <div className="education-item ing">
- <div className="title">
- <div className="tag">学习中</div>
- <div className="text">
- {data.course.title}
- {data.vsNo > 0 ? `V${data.vsNo}` : ''}
- {data.number > 0 ? `(${data.number}课时)` : ''}
- </div>
- <div className="right">
- <More
- menu={[{ label: '评价', key: 'comment' }, { label: '停课', key: 'suspend' }]}
- onClick={value => {
- const { key } = value;
- if (key === 'comment') {
- onComment();
- }
- }}
- />
- </div>
- </div>
- {showTips && <div className="continue">
- <Icon className='close m-r-5 t-3' type="close-circle" theme="filled" onClick={() => closeCommentTips()} />
- 课程已过半,可以来写写评价啦<a onClick={() => onComment()}>去写评价 ></a>
- </div>}
- <div className="detail">
- <div className="left">
- <Assets name="sun_blue" src={data.course.cover} />
- <div className="info">
- <div className="t1">授课老师</div>
- <div className="t2">{data.teacher.realname}</div>
- <div className="t1">有效期</div>
- <div className="t2">{data.useExpireDays}Days</div>
- </div>
- </div>
- <div className="right">
- <div className="item">
- <GIcon name="speed-block" active noHover />
- <div className="text">
- <span>{data.appointments.length}</span>/{data.number}
- </div>
- </div>
- <div className="item">
- <GIcon name="time-block" active noHover />
- <div className="text">
- <span>{data.appointments.length > 0 ? data.totalDays / data.appointments.length : 0}</span>/课时
- </div>
- </div>
- </div>
- <div className="open">
- <GIcon name={open ? 'up' : 'down'} onClick={() => this.setState({ open: !open })} />
- </div>
- </div>
- {open && (data.course.vsType === 'system' || data.course.vsType === 'answer') && <Tabs
- className="t-l"
- type="line"
- theme="theme"
- size="small"
- width={80}
- active={tab}
- tabs={[{ key: 'ing', title: '授课中' }, { key: 'end', title: '已结课' }]}
- onChange={key => this.setState({ tab: key })}
- />}
- {open && (tab === 'ing' ? this.renderTimeLine() : this.renderTable())}
- </div>
- );
- }
- renderNot() {
- const { data } = this.props;
- return (
- <div className="education-item not">
- <div className="title">
- <div className="tag">未开通</div>
- <div className="text">
- {data.course.title}
- {data.vsNo > 0 ? `V${data.vsNo}` : ''}
- {data.number > 0 ? `(${data.number}课时)` : ''}
- </div>
- </div>
- <div className="detail">
- <div className="left">
- <Assets name="sun_blue" src={data.course.cover} />
- <div className="info">
- <div className="t1">授课老师</div>
- <div className="t2">{data.teacher.realname}</div>
- <div>
- <div className="d-i-b m-r-2">
- <div className="t-2">课时</div>
- <div className="t-1 t-s-16">{data.number}</div>
- </div>
- <div className="d-i-b">
- <div className="t-2">总时长</div>
- <div className="t-1 t-s-16">{data.number}Hours</div>
- </div>
- </div>
- </div>
- </div>
- <div className="right">
- <div className="qr-code">
- <Assets name="qrcode" src={data.teacher.qr} />
- <div className="i">
- <div className="t1">请尽快与老师预约上课时间</div>
- <div className="t2">请于 {formatDate(data.endTime, 'YYYY-MM-DD')} 前开通课程</div>
- </div>
- </div>
- </div>
- </div>
- {/* {this.renderTimeLine()} */}
- </div>
- );
- }
- renderEnd() {
- const { data, onComment, closeCommentTips } = this.props;
- const { open, tab, showTips } = this.state;
- return (
- <div className="education-item end">
- <div className="title">
- <div className="tag">已结课</div>
- <div className="text">
- {data.course.title}
- {data.vsNo > 0 ? `V${data.vsNo}` : ''}
- {data.number > 0 ? `(${data.number}课时)` : ''}
- </div>
- <div className="right">
- <More
- menu={[{ label: '评价', key: 'comment' }]}
- onClick={value => {
- const { key } = value;
- if (key === 'comment') {
- onComment();
- }
- }}
- />
- </div>
- </div>
- {showTips && <div className="continue">
- <Icon className='close m-r-5 t-3' type="close-circle" theme="filled" onClick={() => closeCommentTips()} />
- 课程已结束,可以来写写评价啦<a onClick={() => onComment()}>去写评价 ></a>
- </div>}
- <div className="detail">
- <div className="left">
- <Assets name="sun_blue" src={data.course.cover} />
- <div className="info">
- <div className="t1">授课老师</div>
- <div className="t2">{data.teacher.realname}</div>
- <div className="t1">有效期</div>
- <div className="t2">{data.useExpireDays}Days</div>
- </div>
- </div>
- <div className="right">
- <div className="item">
- <GIcon name="speed-block" active noHover />
- <div className="text">
- <span>{data.appointments.length}</span>/{data.number}
- </div>
- </div>
- <div className="item">
- <GIcon name="time-block" active noHover />
- <div className="text">
- <span>{data.appointments.length > 0 ? data.totalDays / data.appointments.length : 0}</span>/课时
- </div>
- </div>
- </div>
- <div className="open">
- <GIcon name={open ? 'up' : 'down'} onClick={() => this.setState({ open: !open })} />
- </div>
- </div>
- {open && (data.course.vsType === 'system' || data.course.vsType === 'answer') && <Tabs
- className="t-l"
- type="line"
- theme="theme"
- size="small"
- width={80}
- active={tab}
- tabs={[{ key: 'ing', title: '授课中' }, { key: 'end', title: '已结课' }]}
- onChange={key => this.setState({ tab: key })}
- />}
- {open && (tab === 'ing' ? this.renderTimeLine() : this.renderTable())}
- </div>
- );
- }
- renderSuspend() {
- const { data, onRestore, onComment } = this.props;
- return (
- <div className="education-item end">
- <div className="title">
- <div className="tag">已停课</div>
- <div className="text">
- {data.course.title}
- {data.vsNo > 0 ? `V${data.vsNo}` : ''}
- {data.number > 0 ? `(${data.number}课时)` : ''}
- <Button size="small" onClick={() => onRestore()}>
- 恢复上课
- </Button>
- </div>
- <div className="t-s-12">
- <span className="t-3">申请时间:</span>
- <span className="t-2 m-r-1">{formatDate(data.suspendTime, 'YYYY-MM-DD HH:mm:ss')}</span>
- <span className="t-3">已停课:</span>
- <span>{parseInt((new Date().getTime() - new Date(data.suspendTime).getTime()) / 86400000, 10)}Days/30</span>
- </div>
- <div className="right">
- <More
- menu={[{ label: '评价', key: 'comment' }]}
- onClick={value => {
- const { key } = value;
- if (key === 'comment') {
- onComment();
- }
- }}
- />
- </div>
- </div>
- <div className="detail">
- <div className="left">
- <Assets name="sun_blue" src={data.course.cover} />
- <div className="info">
- <div className="t1">授课老师</div>
- <div className="t2">{data.teacher.realname}</div>
- <div className="t1">有效期</div>
- <div className="t2">{data.useExpireDays}Days</div>
- </div>
- </div>
- <div className="right">
- <div className="item">
- <GIcon name="speed-block" active noHover />
- <div className="text">
- <span>{data.appointments.length}</span>/{data.number}
- </div>
- </div>
- <div className="item">
- <GIcon name="time-block" active noHover />
- <div className="text">
- <span>{data.appointments.length > 0 ? data.totalDays / data.appointments.length : 0}</span>/课时
- </div>
- </div>
- </div>
- </div>
- </div>
- );
- }
- renderTimeLine() {
- const { data = {}, onUploadNote, onUploadSupply, onUploadQuestion, setCCTalkName } = this.props;
- const { list = [], index } = this.state;
- const appointment = data.appointments[index] || {};
- let status = '';
- return [
- <div className="class-hour">
- {data.number > 1 && <div className="text">课时 {appointment.no}:{appointment.title}</div>}
- {data.number > 1 && <div className="right">
- <GIcon name="prev" onClick={() => this.setState({ index: index === 0 ? index : index - 1 })} />
- <span>上一课时</span>
- <span>下一课时</span>
- <GIcon name="next" onClick={() => this.setState({ index: index >= data.appointments.length - 1 ? index : index + 1 })} />
- </div>}
- </div>,
- <div className="time-line">
- {list.map(item => {
- if (status === '') {
- // 上一阶段完成
- status = statusMap[item](appointment, data);
- } else {
- // 上一阶段未完成
- status = 'end';
- }
- return <TimeLineItem type={`${item}`} user={this.props.user} appointment={appointment} data={data} status={status} onUploadNote={onUploadNote} onUploadSupply={onUploadSupply} onUploadQuestion={onUploadQuestion} setCCTalkName={setCCTalkName} />;
- })}
- </div>,
- ];
- }
- renderTable() {
- const { data = {} } = this.props;
- const { appointments = [] } = data;
- return <UserTable size="small" columns={this.columns[data.course.vsType]} data={appointments.filter(row => row.id)} />;
- }
- }
- class TimeLineItem extends Component {
- constructor(props) {
- super(props);
- this.state = {};
- }
- onClick(key) {
- const { onClick } = this.props;
- const { status } = this.props;
- if (status === 'not') return;
- if (onClick) onClick(key);
- }
- render() {
- const { type } = this.props;
- const { status } = this.props;
- return (
- <div className={`time-line-item ${status}`}>
- <div className="icon-title">
- <GIcon name={iconMap[type]} active={!status} noHover />
- <div className="title">{titleMap[type]}</div>
- </div>
- <div className="time-line-detail">{this.renderDetail()}</div>
- </div>
- );
- }
- renderDetail() {
- const {
- data = {},
- appointment = {},
- type,
- onUploadNote,
- onUploadSupply,
- onDeleteNote,
- onDeleteSupply,
- onUploadQuestion,
- setCCTalkName,
- } = this.props;
- const { status } = this.props;
- const { paper } = appointment;
- switch (type) {
- case '1':
- switch (status) {
- case 'end':
- case 'not':
- return (
- <span>
- 请尽快与老师预约上课时间,老师微信:{data.teacher.wechat}扫码加微信{' '}
- <Dropdown overlay={<Assets name="qrcode" src={data.teacher.qr} />}>
- <span>
- <Assets className="m-l-1" name="erweima" />
- </span>
- </Dropdown>
- </span>
- );
- default:
- return (
- <span>
- {formatDate(appointment.startTime, 'YYYY-MM-DD HH:mm:ss')} ~{' '}
- {formatDate(appointment.endTime, 'HH:mm:ss')}
- </span>
- );
- }
- case '2':
- switch (status) {
- case 'end':
- return <span className="link">点此上传</span>;
- case 'not':
- return <FileUpload onUpload={(file) => {
- return Common.upload({ file }).then((result => onUploadQuestion(appointment, result.url, file.name)));
- }}><span className="link">点此上传</span></FileUpload>;
- default:
- return (
- <a href={appointment.questionFile} target="_blank">
- {appointment.questionFileName || '文件'}
- </a>
- );
- }
- case '3':
- switch (status) {
- case 'end':
- return data.cctalkName ? <span>
- CCtalk 频道号 :{appointment.cctalkChannel} <a className="link" href="" target="_black">CC talk使用手册</a>
- </span> : <div><input style={{ width: 200 }} className='b-c-1 p-l-1 p-r-1 t-s-12 m-r-1' placeholder="请输入CCtalk用户名查看授课频道" onChange={(e) => {
- this.setState({ cctalkName: e.target.value });
- }} /><Button size="small" radius disabled>提交</Button></div>;
- case 'not':
- return data.cctalkName ? <span>
- CCtalk 频道号 :{appointment.cctalkChannel} <a className="link" href="" target="_black">CC talk使用手册</a>
- </span> : <div><input style={{ width: 200 }} className='b-c-1 p-l-1 p-r-1 t-s-12 m-r-1' placeholder="请输入CCtalk用户名查看授课频道" onChange={(e) => {
- this.setState({ cctalkName: e.target.value });
- }} /><Button size="small" radius onClick={() => {
- if (this.state.cctalkName) setCCTalkName(appointment, this.state.cctalkName);
- }} >提交</Button></div>;
- default:
- return (
- <span>
- CCtalk 频道号 :{appointment.cctalkChannel}{' '}
- <a className="link" href="" target="_black">
- CC talk使用手册
- </a>
- </span>
- );
- }
- case '4':
- switch (status) {
- case 'end':
- return <span className="link">点此上传</span>;
- case 'not':
- return <span className="link" onClick={() => onUploadNote(appointment, { appointmentId: appointment.id, recordId: appointment.recordId })}>点此上传</span>;
- default:
- return (
- <div>
- <div>
- <span className="link" onClick={() => onUploadNote(appointment, { appointmentId: appointment.id, recordId: appointment.recordId })}>点此上传</span>
- </div>
- <div className="note-list">
- {appointment.noteList.map(row => {
- console.log(row);
- return <Note user={this.props.user} teacher={data.teacher} data={row} reply={!row.userId} actionList={row.userId ? [{ key: 'edit', label: '编辑' }, { key: 'delete', label: '删除' }] : null} onAction={(key) => {
- switch (key) {
- case 'edit':
- onUploadNote(appointment, row);
- break;
- case 'delete':
- onDeleteNote(appointment, row);
- break;
- case 'reply':
- onUploadNote(appointment, { parentId: row.id, appointmentId: appointment.id, recordId: appointment.recordId });
- break;
- default:
- }
- }} />;
- })}
- </div>
- </div>
- );
- }
- case '5':
- switch (status) {
- case 'end':
- return <span className="link">写留言</span>;
- case 'not':
- return <span className="link" onClick={() => onUploadSupply(appointment, { appointmentId: appointment.id, recordId: appointment.recordId })}>写留言</span>;
- default:
- return (
- <div>
- <div>
- <span className="link" onClick={() => onUploadSupply(appointment, { appointmentId: appointment.id, recordId: appointment.recordId })}>写留言</span>
- </div>
- <div className="note-list">
- {appointment.supplyList.map(row => {
- return <Note user={this.props.user} teacher={data.teacher} data={row} reply={!row.userId} actionList={row.userId ? [{ key: 'edit', label: '编辑' }, { key: 'delete', label: '删除' }] : null} onAction={(key) => {
- switch (key) {
- case 'edit':
- onUploadSupply(appointment, row);
- break;
- case 'delete':
- onDeleteSupply(appointment, row);
- break;
- case 'reply':
- onUploadSupply(appointment, { parentId: row.id, appointmentId: appointment.id, recordId: appointment.recordId });
- break;
- default:
- }
- }} />;
- })}
- </div>
- </div>
- );
- }
- case '6':
- return [
- <div>
- <span>基本情况</span>
- <a href={status !== 'end' ? '' : ''} className="link">
- 填写
- </a>
- </div>,
- <div>
- <span>备考细节</span>
- <a href={status !== 'end' ? '' : ''} className="link">
- 填写
- </a>
- </div>,
- ];
- case '7':
- return (
- <ProgressText
- progress={paper ? formatPercent(paper.report.userNumber, paper.report.questionNumber) : 0}
- size="small"
- />
- );
- default:
- return <div />;
- }
- }
- }
|