page.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. import React from 'react';
  2. import './index.less';
  3. import Page from '@src/containers/Page';
  4. import Block from '@src/components/Block';
  5. import FilterLayout from '@src/layouts/FilterLayout';
  6. import ActionLayout from '@src/layouts/ActionLayout';
  7. import TableLayout from '@src/layouts/TableLayout';
  8. import { formatDate, bindSearch, getMap } from '@src/services/Tools';
  9. import { asyncSMessage, asyncForm } from '@src/services/AsyncTools';
  10. import { CourseSource, CourseStatus, CourseVsType } from '../../../../Constant';
  11. import { Course } from '../../../stores/course';
  12. import { User } from '../../../stores/user';
  13. const CourseSourceMap = getMap(CourseSource, 'value', 'label');
  14. const CourseStatusMap = getMap(CourseStatus, 'value', 'label');
  15. const CourseVsTypeMap = getMap(CourseVsType, 'value', 'label');
  16. export default class extends Page {
  17. init() {
  18. this.onlineAction = [{
  19. key: 'info',
  20. name: '课程',
  21. render: () => {
  22. const { data } = this.state;
  23. return `${data.title}`;
  24. },
  25. }, {
  26. key: 'addOnlineStudent',
  27. name: '添加学员',
  28. }];
  29. this.onlineFilter = [{
  30. key: 'id',
  31. type: 'hidden',
  32. }, {
  33. key: 'timeId',
  34. type: 'select',
  35. allowClear: true,
  36. select: [],
  37. number: true,
  38. name: '时间段',
  39. }, {
  40. key: 'userId',
  41. type: 'select',
  42. name: '学员',
  43. allowClear: true,
  44. select: [],
  45. number: true,
  46. placeholder: '请输入',
  47. }];
  48. this.onlineList = [{
  49. key: 'timeId',
  50. type: 'select',
  51. select: [],
  52. name: '时间段',
  53. }, {
  54. key: 'userIds',
  55. type: 'multiple',
  56. name: '学员',
  57. allowClear: true,
  58. select: [],
  59. number: true,
  60. placeholder: '请输入',
  61. }];
  62. this.onlineColumns = [{
  63. title: '时间段',
  64. dataIndex: 'time',
  65. render: (text) => {
  66. return `${formatDate(text.startTime, 'YYYY-MM-DD')}~${formatDate(text.endTime, 'YYYY-MM-DD')}`;
  67. },
  68. }, {
  69. title: '学员id',
  70. dataIndex: 'userId',
  71. }, {
  72. title: '学员名称',
  73. dataIndex: 'user.nickname',
  74. }, {
  75. title: '手机号',
  76. dataIndex: 'user.mobile',
  77. }, {
  78. title: '操作',
  79. dataIndex: 'handler',
  80. render: (text, record) => {
  81. return <div className="table-button">
  82. {<a onClick={() => {
  83. this.deleteOnlineStudent(record);
  84. }}>删除</a>}
  85. </div>;
  86. },
  87. }];
  88. this.vsAction = [{
  89. key: 'info',
  90. name: '课程',
  91. render: () => {
  92. const { data } = this.state;
  93. return `${data.title}(${CourseVsTypeMap[data.vsType]})`;
  94. },
  95. }, {
  96. key: 'addVsStudent',
  97. name: '添加学员',
  98. }];
  99. this.vsAddList = [{
  100. key: 'id',
  101. type: 'hidden',
  102. }, {
  103. key: 'userId',
  104. type: 'select',
  105. name: '学员',
  106. select: [],
  107. number: true,
  108. placeholder: '请输入',
  109. }, {
  110. key: 'teacherId',
  111. type: 'select',
  112. select: [],
  113. name: '老师',
  114. }, {
  115. key: 'number',
  116. type: 'number',
  117. name: '课时数',
  118. }, {
  119. key: 'cctalkName',
  120. type: 'input',
  121. name: 'CCTalk名',
  122. }];
  123. this.vsChangeList = [{
  124. key: 'id',
  125. type: 'hidden',
  126. }, {
  127. key: 'teacherId',
  128. type: 'select',
  129. required: true,
  130. select: [],
  131. name: '老师',
  132. }, {
  133. key: 'cctalkName',
  134. type: 'input',
  135. name: 'CCTalk名',
  136. }, {
  137. key: 'number',
  138. type: 'hidden',
  139. name: '课时数',
  140. }];
  141. this.vsColumns = [{
  142. title: '学员id',
  143. dataIndex: 'user.id',
  144. }, {
  145. title: '学员名称',
  146. dataIndex: 'user.nickname',
  147. render: (text, record) => {
  148. return `${text}(${record.user.mobile})`;
  149. },
  150. }, {
  151. title: '课时数',
  152. dataIndex: 'number',
  153. }, {
  154. title: '有效期',
  155. dataIndex: 'time',
  156. render: (text, record) => {
  157. return record.isUsed ? `${formatDate(record.useStartTime, 'YYYY-MM-DD')}~${formatDate(record.useEndTime, 'YYYY-MM-DD')}` : '';
  158. },
  159. }, {
  160. title: '添加方式',
  161. dataIndex: 'source',
  162. render: (text) => {
  163. return CourseSourceMap[text] || text;
  164. },
  165. }, {
  166. title: '授课老师',
  167. dataIndex: 'teacher.realname',
  168. }, {
  169. title: '状态',
  170. dataIndex: 'status',
  171. render: (text, record) => {
  172. let status = 0;
  173. if (record.isUsed) {
  174. const end = new Date(record.useEndTime);
  175. status = 1;
  176. if (new Date().getTime() > end.getTime()) {
  177. status = 2;
  178. }
  179. }
  180. return CourseStatusMap[status] || status;
  181. },
  182. }, {
  183. title: 'CCTalk用户名',
  184. dataIndex: 'cctalkName',
  185. }, {
  186. title: '操作',
  187. dataIndex: 'handler',
  188. render: (text, record) => {
  189. return <div className="table-button">
  190. {<a onClick={() => {
  191. this.changeVs(record);
  192. }}>修改</a>}
  193. </div>;
  194. },
  195. }];
  196. }
  197. initData() {
  198. const { id } = this.params;
  199. let handler;
  200. if (id) {
  201. handler = Course.get({ id });
  202. }
  203. handler
  204. .then(result => {
  205. this.setState({ module: result.courseModule });
  206. this.setState({ data: result });
  207. this.refresh();
  208. });
  209. }
  210. refresh() {
  211. const { id } = this.params;
  212. const { module } = this.state;
  213. switch (module) {
  214. case 'video':
  215. break;
  216. case 'online':
  217. bindSearch(this.onlineFilter, 'timeId', this, (search) => {
  218. return Course.listTime(Object.assign({ courseId: id }, search));
  219. }, (row) => {
  220. return {
  221. title: `${formatDate(row.startTime, 'YYYY-MM-DD')}~${formatDate(row.endTime, 'YYYY-MM-DD')}`,
  222. value: row.id,
  223. };
  224. }, this.state.search.timeId ? Number(this.state.search.timeId) : null, null);
  225. bindSearch(this.onlineFilter, 'userId', this, (search) => {
  226. return User.list(search);
  227. }, (row) => {
  228. return {
  229. title: `${row.nickname}(${row.mobile})`,
  230. value: row.id,
  231. };
  232. }, null, null);
  233. bindSearch(this.onlineList, 'timeId', this, (search) => {
  234. return Course.listTime(Object.assign({ courseId: id }, search));
  235. }, (row) => {
  236. return {
  237. title: `${formatDate(row.startTime, 'YYYY-MM-DD')}~${formatDate(row.endTime, 'YYYY-MM-DD')}`,
  238. value: row.id,
  239. };
  240. }, null, null);
  241. bindSearch(this.onlineList, 'userIds', this, (search) => {
  242. return User.list(search);
  243. }, (row) => {
  244. return {
  245. title: `${row.nickname}(${row.mobile})`,
  246. value: row.id,
  247. };
  248. }, null, null);
  249. this.refreshOnline();
  250. break;
  251. case 'vs':
  252. this.refreshVs();
  253. break;
  254. default:
  255. }
  256. }
  257. refreshOnline() {
  258. const { id } = this.params;
  259. Course.listStudentOnline(Object.assign({ courseId: id }, this.state.search)).then(result => {
  260. this.setTableData(result.list, result.total);
  261. });
  262. }
  263. refreshVs() {
  264. const { id } = this.params;
  265. Course.listStudentVs(Object.assign({ courseId: id }, this.state.search)).then(result => {
  266. this.setTableData(result.list, result.total);
  267. });
  268. }
  269. addOnlineStudentAction() {
  270. const { id } = this.params;
  271. asyncForm('添加', this.onlineList, {}, data => {
  272. return Promise.all(data.userIds.map(userId => Course.addStudentOnline({ courseId: id, timeId: data.timeId, userId }))).then(() => {
  273. asyncSMessage('添加成功!');
  274. this.refresh();
  275. });
  276. }).catch(err => {
  277. console.log(err);
  278. });
  279. }
  280. deleteOnlineStudent(row) {
  281. Course.delStudentOnline({ id: row.id }).then(() => {
  282. asyncSMessage('删除成功!');
  283. this.refresh();
  284. });
  285. }
  286. addVsStudentAction() {
  287. const { id } = this.params;
  288. const { data } = this.state;
  289. this.vsAddList[3].type = data.vsType === 'novice' ? 'hidden' : 'number';
  290. asyncForm('添加', this.vsAddList, {}, info => {
  291. if (data.vsType === 'novice') {
  292. // 写死:新手每次1课时
  293. info.number = 1;
  294. }
  295. // ([info.useStartTime, info.useEndTime] = info.time);
  296. return Course.addStudentVs(Object.assign({ courseId: id }, info)).then(() => {
  297. asyncSMessage('添加成功!');
  298. this.refresh();
  299. });
  300. }).then(component => {
  301. bindSearch(this.vsAddList, 'userId', component, (search) => {
  302. return User.list(search);
  303. }, (row) => {
  304. return {
  305. title: `${row.nickname}(${row.mobile})`,
  306. value: row.id,
  307. };
  308. }, null, null);
  309. bindSearch(this.vsAddList, 'teacherId', component, (search) => {
  310. return Course.listTeacher(Object.assign({ courseId: id }, search));
  311. }, (row) => {
  312. return {
  313. title: row.realname,
  314. value: row.id,
  315. };
  316. }, null, null);
  317. });
  318. }
  319. changeVs(record) {
  320. const { id } = this.params;
  321. asyncForm('修改', this.vsChangeList, record, info => {
  322. // ([info.useStartTime, info.useEndTime] = info.time);
  323. return Course.editStudentVs(Object.assign({ courseId: id }, info)).then(() => {
  324. asyncSMessage('编辑成功!');
  325. this.refresh();
  326. });
  327. }).then(component => {
  328. bindSearch(this.vsChangeList, 'teacherId', component, (search) => {
  329. return Course.listTeacher(Object.assign({ courseId: id }, search));
  330. }, (row) => {
  331. return {
  332. title: row.realname,
  333. value: row.id,
  334. };
  335. }, record.teacherId, null);
  336. });
  337. }
  338. renderOnline() {
  339. return <Block flex>
  340. {<FilterLayout
  341. show
  342. itemList={this.onlineFilter}
  343. data={this.state.search}
  344. onChange={data => {
  345. data.page = 1;
  346. this.search(data);
  347. }} />}
  348. <ActionLayout
  349. itemList={this.onlineAction}
  350. selectedKeys={this.state.selectedKeys}
  351. onAction={key => this.onAction(key)}
  352. />
  353. <TableLayout
  354. columns={this.onlineColumns}
  355. list={this.state.list}
  356. pagination={this.state.page}
  357. loading={this.props.core.loading}
  358. onChange={(pagination, filters, sorter) => this.tableChange(pagination, filters, sorter)}
  359. onSelect={(keys, rows) => this.tableSelect(keys, rows)}
  360. selectedKeys={this.state.selectedKeys}
  361. />
  362. </Block>;
  363. }
  364. renderVs() {
  365. return <Block flex>
  366. {<ActionLayout
  367. itemList={this.vsAction}
  368. selectedKeys={this.state.selectedKeys}
  369. onAction={key => this.onAction(key)}
  370. />}
  371. <TableLayout
  372. columns={this.vsColumns}
  373. list={this.state.list}
  374. pagination={this.state.page}
  375. loading={this.props.core.loading}
  376. onChange={(pagination, filters, sorter) => this.tableChange(pagination, filters, sorter)}
  377. onSelect={(keys, rows) => this.tableSelect(keys, rows)}
  378. selectedKeys={this.state.selectedKeys}
  379. />
  380. </Block>;
  381. }
  382. renderView() {
  383. switch (this.state.module) {
  384. case 'online':
  385. return [this.renderOnline()];
  386. case 'vs':
  387. return [this.renderVs()];
  388. case 'video':
  389. return [];
  390. default:
  391. return <div />;
  392. }
  393. }
  394. }