page.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. import React, { Component } from 'react';
  2. import { Link } from 'react-router-dom';
  3. import './index.less';
  4. import { Icon } from 'antd';
  5. import FileUpload from '@src/components/FileUpload';
  6. import Page from '@src/containers/Page';
  7. import Assets from '@src/components/Assets';
  8. import UserLayout from '../../../layouts/User';
  9. import Button from '../../../components/Button';
  10. import ProgressText from '../../../components/ProgressText';
  11. import { Icon as GIcon } from '../../../components/Icon';
  12. import menu from '../index';
  13. import Tabs from '../../../components/Tabs';
  14. import UserTable from '../../../components/UserTable';
  15. import More from '../../../components/More';
  16. import Modal from '../../../components/Modal';
  17. import Date from '../../../components/Date';
  18. export default class extends Page {
  19. initState() {
  20. return {
  21. tab1: '1',
  22. tab2: '1',
  23. data: [
  24. {
  25. status: 'ing',
  26. history: [{}],
  27. list: [
  28. { status: 'ing', type: '1' },
  29. { status: 'not', type: '2' },
  30. { status: 'end', type: '3' },
  31. { status: 'not', type: '4' },
  32. { status: 'end', type: '5' },
  33. { status: 'not', type: '6' },
  34. { status: 'end', type: '7' },
  35. ],
  36. },
  37. {
  38. status: 'not',
  39. history: [{}],
  40. list: [
  41. { status: 'ing', type: '1' },
  42. { status: 'not', type: '2' },
  43. { status: 'end', type: '3' },
  44. { status: 'not', type: '4' },
  45. { status: 'end', type: '5' },
  46. { status: 'not', type: '6' },
  47. { status: 'end', type: '7' },
  48. ],
  49. },
  50. { status: 'end', history: [{}], list: [] },
  51. ],
  52. };
  53. }
  54. onAction() {}
  55. refresh(tab1, tab2) {
  56. this.setState({ tab1, tab2 });
  57. }
  58. renderView() {
  59. const { config } = this.props;
  60. return <UserLayout active={config.key} menu={menu} center={this.renderDetail()} />;
  61. }
  62. renderDetail() {
  63. const { tab1, tab2 } = this.state;
  64. return (
  65. <div className="detail-layout">
  66. <div className="tip">
  67. <div className="text">理清备考思路,避开常见误区,让学习的每一分钟发光发热!</div>
  68. <Link to="">去填写 ></Link>
  69. <Icon type="close-circle" theme="filled" />
  70. </div>
  71. <Tabs
  72. type="division"
  73. theme="theme"
  74. size="small"
  75. space={2.5}
  76. width={100}
  77. active={tab1}
  78. tabs={[{ key: '1', title: '在线课程' }, { key: '2', title: '1V1私教' }]}
  79. onChange={key => this.refresh(key, tab2)}
  80. />
  81. <Tabs
  82. type="tag"
  83. theme="white"
  84. size="small"
  85. space={5}
  86. width={54}
  87. active={tab2}
  88. tabs={[
  89. { key: '1', title: '全部' },
  90. { key: '2', title: '未开通' },
  91. { key: '3', title: '学习中' },
  92. { key: '4', title: '已结束' },
  93. ]}
  94. onChange={key => this.refresh(tab1, key)}
  95. />
  96. {this[`renderTab${tab1}`]()}
  97. <Modal show className="clock-modal" title="打卡表" width={460} onClose={() => {}}>
  98. <div>
  99. <div className="d-i-b w-3">
  100. <div className="t-2 t-s-14">听课频率</div>
  101. <div className="t-4 t-s-18">2天/课时</div>
  102. </div>
  103. <div className="d-i-b w-3">
  104. <div className="t-2 t-s-14">作业完成度</div>
  105. <div className="t-4 t-s-18">50%</div>
  106. </div>
  107. </div>
  108. <div className="b-b m-t-1 m-b-1" />
  109. <div className="m-b-1">
  110. <div className="tag d-i-b t-s-16">
  111. <i style={{ background: '#6865FD' }} />
  112. 听课
  113. </div>
  114. <div className="tag d-i-b t-s-16">
  115. <i style={{ background: '#4299FF' }} />
  116. 预习
  117. </div>
  118. <div className="tag d-i-b t-s-16">
  119. <i style={{ background: '#E7E7E7' }} />
  120. 停课
  121. </div>
  122. </div>
  123. <Date
  124. hideInput
  125. disabledDate={() => false}
  126. dateRender={current => {
  127. return (
  128. <div className="ant-calendar-date">
  129. {current.get('date')}
  130. <i className="s1" style={{ background: '#6865FD' }} />
  131. <i className="s2" style={{ background: '#4299FF' }} />
  132. </div>
  133. );
  134. }}
  135. checkRefresh={(date, refresh) => {
  136. console.log(date);
  137. setTimeout(() => {
  138. refresh();
  139. }, 2000);
  140. return true;
  141. }}
  142. />
  143. <div className="t-2 t-s-12">*听课频率≤2天/课时,作业完成度≥90%,课程有效期可延长7-10天。</div>
  144. </Modal>
  145. <Modal title="恢复学习" onConfirm={() => {}} onCancel={() => {}}>
  146. <div className="t-2 t-s-18">恢复学习后,本课程的停课功能将无法使用。是否恢复学习?</div>
  147. </Modal>
  148. <Modal title="上传笔记" width={630} confirmText="提交" onConfirm={() => {}} onCancel={() => {}}>
  149. <textarea
  150. className="b-c-1 w-10 p-10 m-b-1"
  151. rows={6}
  152. placeholder="请输入留言内容,也可将文件拖动到这里上传。"
  153. />
  154. <div className="t-2 t-s-16 m-b-1">
  155. 上传文件 <FileUpload type="file" title="选择文件" />
  156. <span className="t-3 t-s-14">支持 docx, xls, PDF, rar, zip, PNG, JPG 等类型的文件</span>
  157. </div>
  158. <div className="b-b m-t-2" />
  159. </Modal>
  160. </div>
  161. );
  162. }
  163. renderTab1() {
  164. const { data = [] } = this.state;
  165. return data.map(item => {
  166. return <Course data={item} />;
  167. });
  168. }
  169. renderTab2() {
  170. const { data = [] } = this.state;
  171. return data.map(item => {
  172. return <Education data={item} />;
  173. });
  174. }
  175. }
  176. class Course extends Component {
  177. constructor(props) {
  178. super(props);
  179. this.columns = [
  180. { title: '学习内容' },
  181. { title: '预习作业' },
  182. { title: '进度' },
  183. { title: '最近学习' },
  184. { title: '笔记' },
  185. { title: '问答' },
  186. ];
  187. this.state = { open: false };
  188. }
  189. render() {
  190. const { data = {} } = this.props;
  191. switch (data.status) {
  192. case 'ing':
  193. return this.renderIng();
  194. case 'not':
  195. return this.renderNot();
  196. case 'end':
  197. return this.renderEnd();
  198. default:
  199. return <div />;
  200. }
  201. }
  202. renderIng() {
  203. const { data } = this.props;
  204. const { history = [] } = data;
  205. return (
  206. <div className="course-item ing">
  207. <div className="title">
  208. <div className="tag">学习中</div>
  209. <div className="text">OG20整合刷题-语法SC</div>
  210. </div>
  211. <div className="continue">
  212. <Assets name="notice" />
  213. 继续学习:课时 13:解读句子属性
  214. </div>
  215. <div className="detail">
  216. <div className="left">
  217. <Assets name="sun_blue" />
  218. <div className="info">
  219. <div className="t1">授课老师</div>
  220. <div className="t2">李小小</div>
  221. <div className="t1">有效期</div>
  222. <div className="t2">88Day</div>
  223. </div>
  224. </div>
  225. <div className="right">
  226. <div className="item">
  227. <GIcon name="speed-block" noHover />
  228. <div className="text">
  229. <span>12</span>/20
  230. </div>
  231. </div>
  232. <div className="item">
  233. <GIcon name="question-block" active noHover />
  234. <div className="text">
  235. <span>12</span>/20
  236. </div>
  237. </div>
  238. <div className="item">
  239. <GIcon name="clockin-block" noHover />
  240. <div className="text">
  241. <span>12</span>/20
  242. </div>
  243. </div>
  244. <div className="item">
  245. <GIcon name="note-block" noHover />
  246. <div className="text">
  247. <span>12</span>/20
  248. </div>
  249. </div>
  250. </div>
  251. </div>
  252. <UserTable size="small" columns={this.columns} data={history} />
  253. </div>
  254. );
  255. }
  256. renderNot() {
  257. return (
  258. <div className="course-item not">
  259. <div className="title">
  260. <div className="tag">未开通</div>
  261. <div className="text">OG20整合刷题-语法SC</div>
  262. </div>
  263. <div className="detail">
  264. <div className="left">
  265. <Assets name="sun_blue" />
  266. <div className="info">
  267. <div className="t1">授课老师</div>
  268. <div className="t2">李小小</div>
  269. <div className="t1">有效期</div>
  270. <div className="t2">88Day</div>
  271. </div>
  272. </div>
  273. <div className="right t-c">
  274. <div className="text">请于 2020-06-26 前开通</div>
  275. <Button size="lager" radius>
  276. 立即开通
  277. </Button>
  278. </div>
  279. </div>
  280. </div>
  281. );
  282. }
  283. renderEnd() {
  284. return (
  285. <div className="course-item end">
  286. <div className="title">
  287. <div className="tag">已结束</div>
  288. <div className="text">OG20整合刷题-语法SC</div>
  289. </div>
  290. <div className="detail">
  291. <div className="left">
  292. <Assets name="sun_blue" />
  293. <div className="info">
  294. <div className="t1">授课老师</div>
  295. <div className="t2">李小小</div>
  296. <div className="t1">有效期</div>
  297. <div className="t2">88Day</div>
  298. </div>
  299. </div>
  300. <div className="right">
  301. <div className="item">
  302. <GIcon name="gift-block" active />
  303. <div className="text">赠送7天</div>
  304. </div>
  305. </div>
  306. </div>
  307. </div>
  308. );
  309. }
  310. }
  311. class Education extends Component {
  312. constructor(props) {
  313. super(props);
  314. this.columns = [
  315. { title: '学习内容' },
  316. { title: '预习作业' },
  317. { title: '授课时间' },
  318. { title: '课后笔记' },
  319. { title: '课后补充' },
  320. ];
  321. this.state = { open: true, tab: '1' };
  322. }
  323. render() {
  324. const { data = {} } = this.props;
  325. switch (data.status) {
  326. case 'ing':
  327. return this.renderIng();
  328. case 'not':
  329. return this.renderNot();
  330. case 'end':
  331. return this.renderEnd();
  332. default:
  333. return <div />;
  334. }
  335. }
  336. renderIng() {
  337. const { tab } = this.state;
  338. return (
  339. <div className="education-item ing">
  340. <div className="title">
  341. <div className="tag">学习中</div>
  342. <div className="text">OG20整合刷题-语法SC</div>
  343. <div className="right">
  344. <More menu={[{ label: '评价', key: '1' }, { label: '停课', key: '2' }]} />
  345. </div>
  346. </div>
  347. <div className="continue">
  348. <Assets name="notice" />
  349. 继续学习:课时 13:解读句子属性
  350. </div>
  351. <div className="detail">
  352. <div className="left">
  353. <Assets name="sun_blue" />
  354. <div className="info">
  355. <div className="t1">授课老师</div>
  356. <div className="t2">李小小</div>
  357. <div className="t1">有效期</div>
  358. <div className="t2">88Day</div>
  359. </div>
  360. </div>
  361. <div className="right">
  362. <div className="item">
  363. <GIcon name="speed-block" noHover />
  364. <div className="text">
  365. <span>12</span>/20
  366. </div>
  367. </div>
  368. <div className="item">
  369. <GIcon name="question-block" active noHover />
  370. <div className="text">
  371. <span>12</span>/20
  372. </div>
  373. </div>
  374. </div>
  375. </div>
  376. <Tabs
  377. className="t-l"
  378. type="line"
  379. theme="theme"
  380. size="small"
  381. width={80}
  382. active={tab}
  383. tabs={[{ key: '1', title: '在线课程' }, { key: '2', title: '1V1私教' }]}
  384. onChange={key => this.setState({ tab: key })}
  385. />
  386. <div className="class-hour">
  387. <div className="text">课时 5:解读句子属性</div>
  388. <div className="right">
  389. <GIcon name="prev" onClick={() => {}} />
  390. <span>上一课时</span>
  391. <span>下一课时</span>
  392. <GIcon name="next" onClick={() => {}} />
  393. </div>
  394. </div>
  395. {tab === '1' ? this.renderTimeLine() : this.renderTable()}
  396. </div>
  397. );
  398. }
  399. renderNot() {
  400. return (
  401. <div className="education-item not">
  402. <div className="title">
  403. <div className="tag">未开通</div>
  404. <div className="text">OG20整合刷题-语法SC</div>
  405. </div>
  406. <div className="detail">
  407. <div className="left">
  408. <Assets name="sun_blue" />
  409. <div className="info">
  410. <div className="t1">授课老师</div>
  411. <div className="t2">李小小</div>
  412. <div className="t1">有效期</div>
  413. <div className="t2">88Day</div>
  414. </div>
  415. </div>
  416. <div className="right">
  417. <div className="qr-code">
  418. <Assets name="qrcode" />
  419. <div className="i">
  420. <div className="t1">请尽快与老师预约上课时间</div>
  421. <div className="t2">请于 2019-07-25 前开通课程</div>
  422. </div>
  423. </div>
  424. </div>
  425. </div>
  426. {this.renderTimeLine()}
  427. </div>
  428. );
  429. }
  430. renderEnd() {
  431. const { open } = this.state;
  432. return (
  433. <div className="education-item end">
  434. <div className="title">
  435. <div className="tag">已结课</div>
  436. <div className="text">OG20整合刷题-语法SC</div>
  437. </div>
  438. <div className="detail">
  439. <div className="left">
  440. <Assets name="sun_blue" />
  441. <div className="info">
  442. <div className="t1">授课老师</div>
  443. <div className="t2">李小小</div>
  444. <div className="t1">有效期</div>
  445. <div className="t2">88Day</div>
  446. </div>
  447. </div>
  448. <div className="right">
  449. <div className="item">
  450. <GIcon name="speed-block" noHover />
  451. <div className="text">
  452. <span>12</span>/20
  453. </div>
  454. </div>
  455. <div className="item">
  456. <GIcon name="question-block" active noHover />
  457. <div className="text">
  458. <span>12</span>/20
  459. </div>
  460. </div>
  461. </div>
  462. <div className="open">
  463. <GIcon name={open ? 'up' : 'down'} onClick={() => this.setState({ open: !open })} />
  464. </div>
  465. </div>
  466. {open && this.renderTable()}
  467. </div>
  468. );
  469. }
  470. renderTimeLine() {
  471. const { data = {} } = this.props;
  472. const { list = [] } = data;
  473. return (
  474. <div className="time-line">
  475. {list.map(item => {
  476. return <TimeLineItem data={item} />;
  477. })}
  478. </div>
  479. );
  480. }
  481. renderTable() {
  482. const { data = {} } = this.props;
  483. const { history = [] } = data;
  484. return <UserTable size="small" columns={this.columns} data={history} />;
  485. }
  486. }
  487. class TimeLineItem extends Component {
  488. constructor(props) {
  489. super(props);
  490. this.titleMap = {
  491. 1: '预约时间',
  492. 2: '答疑文档',
  493. 3: '上课',
  494. 4: '课后笔记',
  495. 5: '课后补充',
  496. 6: '备考信息',
  497. 7: '完成作业',
  498. };
  499. this.iconMap = {
  500. 1: 'time-icon',
  501. 2: 'QA-icon',
  502. 3: 'class-icon',
  503. 4: 'note-icon',
  504. 5: 'supplement-icon',
  505. 6: 'information-icon',
  506. 7: 'homework-icon',
  507. };
  508. }
  509. onClick(key) {
  510. const { data = {}, onClick } = this.props;
  511. const { status } = data;
  512. if (status === 'not') return;
  513. if (onClick) onClick(key);
  514. }
  515. render() {
  516. const { data = {} } = this.props;
  517. const { status, type } = data;
  518. return (
  519. <div className={`time-line-item ${status}`}>
  520. <div className="icon-title">
  521. <GIcon name={this.iconMap[type]} active={status !== 'not'} noHover />
  522. <div className="title">{this.titleMap[type]}</div>
  523. </div>
  524. <div className="time-line-detail">{this.renderDetail()}</div>
  525. </div>
  526. );
  527. }
  528. renderDetail() {
  529. const { data = {} } = this.props;
  530. const { type, status } = data;
  531. switch (type) {
  532. case '1':
  533. return status === 'not' ? (
  534. <span>请尽快与老师预约上课时间,扫码加微信</span>
  535. ) : (
  536. <span>2019-07-24 09:00 ~ 10:00</span>
  537. );
  538. case '2':
  539. return <span className="link">点此上传</span>;
  540. case '3':
  541. return status === 'end' ? (
  542. <span>
  543. CCtalk 频道号 :1234567 <span className="link">CC talk使用手册</span>
  544. </span>
  545. ) : (
  546. <input placeholder="请输入CCtalk用户名查看授课频道" />
  547. );
  548. case '4':
  549. return <span className="link">点此上传</span>;
  550. case '5':
  551. return <span className="link">写留言</span>;
  552. case '6':
  553. return [
  554. <div>
  555. <span>基本情况梳理</span>
  556. <span>2019-08-20 更新</span>
  557. <span className="link">修改</span>
  558. </div>,
  559. <div>
  560. <span>备考细节梳理</span>
  561. <span className="link">填写</span>
  562. </div>,
  563. ];
  564. case '7':
  565. return <ProgressText progress={10} size="small" />;
  566. default:
  567. return <div />;
  568. }
  569. }
  570. }