page.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import React from 'react';
  2. import './index.less';
  3. import { Drawer, Tabs, ListView } from 'antd-mobile';
  4. import Page from '@src/containers/Page';
  5. import Assets from '@src/components/Assets';
  6. import { formatTreeData, getMap } from '@src/services/Tools';
  7. import ListData from '@src/services/ListData';
  8. import { CourseBlock, CoursePackageBlock } from '../../../components/Block';
  9. import { SpecialRadioGroup } from '../../../components/Radio';
  10. import Button from '../../../components/Button';
  11. import Checkbox from '../../../components/CheckBox';
  12. import { Course } from '../../../stores/course';
  13. import { Main } from '../../../stores/main';
  14. export default class extends Page {
  15. initState() {
  16. return {
  17. listMap: {},
  18. };
  19. }
  20. init() {
  21. Main.dataStruct().then((list) => {
  22. list = list.map(row => {
  23. row.title = `${row.titleZh} ${row.titleEn}`;
  24. row.label = row.title;
  25. row.key = row.id;
  26. return row;
  27. });
  28. const structMap = getMap(list, 'id');
  29. const videoTree = formatTreeData(list, 'id', 'title', 'parentId');
  30. const packageTree = formatTreeData(list.filter(row => row.level === 1), 'id', 'title', 'parentId');
  31. this.setState({ videoTree, packageTree, structMap });
  32. });
  33. const { search } = this.state;
  34. if (!search.order) search.order = 'saleNumber';
  35. this.setState({ search, tab: 'video' });
  36. }
  37. initData() {
  38. return this.initListKeys(['video', 'package'])
  39. .then(() => {
  40. return this.getList('video', 1);
  41. });
  42. }
  43. initListKeys(keys) {
  44. const { listMap } = this.state;
  45. keys.forEach((key) => {
  46. listMap[key] = new ListData();
  47. });
  48. this.setState({ listMap });
  49. return Promise.resolve();
  50. }
  51. getList(key, page) {
  52. this.setState({ tab: key });
  53. let handler;
  54. switch (key) {
  55. case 'video':
  56. handler = Course.listVideo(Object.assign({ page }, this.state.search));
  57. break;
  58. case 'package':
  59. handler = Course.listPackage(Object.assign({ page }, this.state.search))
  60. .then(result => {
  61. const { structMap } = this.state;
  62. result.list = result.list.map(row => {
  63. row.tag = (structMap[row.structId] || {}).title;
  64. return row;
  65. });
  66. return result;
  67. });
  68. break;
  69. default:
  70. return;
  71. }
  72. handler.then((result) => {
  73. const { listMap } = this.state;
  74. if (page === 1) { // todo 是否重新读取第一页为刷新所有数据
  75. listMap[key] = new ListData();
  76. }
  77. listMap[key].get(page, result, this.state.search.size);
  78. this.setState({ listMap, tab: key });
  79. });
  80. }
  81. changeStruct(value) {
  82. const { search = {} } = this.state;
  83. search.structId = value;
  84. this.setState({ search });
  85. }
  86. renderView() {
  87. const { filter } = this.state;
  88. return (
  89. <Drawer
  90. style={{ minHeight: document.documentElement.clientHeight }}
  91. position="right"
  92. open={filter}
  93. sidebar={this.renderFilter()}
  94. onOpenChange={isOpen => this.setState({ filter: isOpen })}
  95. >
  96. <div className="top">
  97. <Tabs onChange={(value) => {
  98. this.changeStruct(null);
  99. this.getList(value.key, 1);
  100. }} tabs={[{ title: '单次', key: 'video' }, { title: '套餐', key: 'package' }]} />
  101. <div className="right" onClick={() => this.setState({ filter: true })}>
  102. 筛选
  103. <Assets name="screen" />
  104. </div>
  105. </div>
  106. {this.renderList()}
  107. </Drawer>
  108. );
  109. }
  110. renderRow(rowData) {
  111. const { tab } = this.state;
  112. switch (tab) {
  113. case 'video':
  114. return <CourseBlock data={rowData} />;
  115. case 'package':
  116. return <CoursePackageBlock data={rowData} />;
  117. default:
  118. return <div />;
  119. }
  120. }
  121. renderList() {
  122. const { listMap, tab } = this.state;
  123. const data = listMap[tab];
  124. if (!data) return <div />;
  125. const { dataSource = {}, bottom, loading, finish, maxSectionId = 1, total } = data;
  126. if (total === 0) return this.renderEmpty();
  127. return <ListView
  128. className="list"
  129. ref={el => { this.lv = el; }}
  130. dataSource={dataSource}
  131. renderFooter={() => (<div style={{ padding: 30, textAlign: 'center' }}>
  132. {loading ? '加载中...' : (bottom ? '没有更多了' : '')}
  133. </div>)}
  134. renderRow={(rowData, sectionID, rowID) => this.renderRow(rowData, sectionID, rowID)}
  135. style={{
  136. height: this.state.height,
  137. overflow: 'auto',
  138. }}
  139. pageSize={this.state.search.size}
  140. scrollRenderAheadDistance={500}
  141. onEndReached={() => {
  142. if (loading) return;
  143. if (bottom) {
  144. if (!finish) {
  145. data.finish = true;
  146. // this.setState({ time: new Date() })
  147. }
  148. return;
  149. }
  150. this.getList(tab, maxSectionId + 1);
  151. }}
  152. onEndReachedThreshold={10}
  153. />;
  154. }
  155. renderEmpty() {
  156. return <div />;
  157. }
  158. renderFilter() {
  159. const { search, videoTree = [], packageTree = [], tab } = this.state;
  160. return (
  161. <div className="filter">
  162. <div className="body">
  163. <div className="sub">
  164. <div className="title">筛选学科</div>
  165. {(tab === 'package' ? packageTree : videoTree).map((row) => {
  166. return <div className="item">
  167. <div className={row.children.length > 0 ? 'label' : 'label left'}>{row.title}</div>
  168. {row.children.length > 0 && <div className="value">
  169. <SpecialRadioGroup
  170. list={row.children}
  171. value={search.structId}
  172. onChange={(value) => {
  173. this.changeStruct(value);
  174. }}
  175. />
  176. </div>}
  177. {row.children.length === 0 && <div className="value right">
  178. <Checkbox checked={search.structId === row.id} onClick={() => {
  179. this.changeStruct(row.id);
  180. }} />
  181. </div>}
  182. </div>;
  183. })}
  184. </div>
  185. </div>
  186. <div className="footer">
  187. <Button radius width={90} onClick={() => {
  188. this.getList(tab, 1);
  189. }}>
  190. 确定
  191. </Button>
  192. </div>
  193. </div>
  194. );
  195. }
  196. }