page.js 17 KB

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