page.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  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. this.vsColumns = [{
  138. title: '学员id',
  139. dataIndex: 'user.id',
  140. }, {
  141. title: '学员名称',
  142. dataIndex: 'user.nickname',
  143. render: (text, record) => {
  144. return `${text}(${record.user.mobile})`;
  145. },
  146. }, {
  147. title: '课时数',
  148. dataIndex: 'number',
  149. }, {
  150. title: '有效期',
  151. dataIndex: 'time',
  152. render: (text, record) => {
  153. return record.isUsed ? `${formatDate(record.useStartTime, 'YYYY-MM-DD')}~${formatDate(record.useEndTime, 'YYYY-MM-DD')}` : '';
  154. },
  155. }, {
  156. title: '添加方式',
  157. dataIndex: 'source',
  158. render: (text) => {
  159. return CourseSourceMap[text] || text;
  160. },
  161. }, {
  162. title: '授课老师',
  163. dataIndex: 'teacher.realname',
  164. }, {
  165. title: '状态',
  166. dataIndex: 'status',
  167. render: (text, record) => {
  168. let status = 0;
  169. if (record.isUsed) {
  170. const end = new Date(record.useEndTime);
  171. status = 1;
  172. if (new Date().getTime() > end.getTime()) {
  173. status = 2;
  174. }
  175. }
  176. return CourseStatusMap[status] || status;
  177. },
  178. }, {
  179. title: 'CCTalk用户名',
  180. dataIndex: 'cctalkName',
  181. }, {
  182. title: '操作',
  183. dataIndex: 'handler',
  184. render: (text, record) => {
  185. return <div className="table-button">
  186. {<a onClick={() => {
  187. this.changeVs(record);
  188. }}>修改</a>}
  189. </div>;
  190. },
  191. }];
  192. }
  193. initData() {
  194. const { id } = this.params;
  195. let handler;
  196. if (id) {
  197. handler = Course.get({ id });
  198. }
  199. handler
  200. .then(result => {
  201. this.setState({ module: result.courseModule });
  202. this.setState({ data: result });
  203. this.refresh();
  204. });
  205. }
  206. refresh() {
  207. const { id } = this.params;
  208. const { module } = this.state;
  209. switch (module) {
  210. case 'video':
  211. break;
  212. case 'online':
  213. bindSearch(this.onlineFilter, 'timeId', this, (search) => {
  214. return Course.listTime(Object.assign({ courseId: id }, search));
  215. }, (row) => {
  216. return {
  217. title: `${formatDate(row.startTime, 'YYYY-MM-DD')}~${formatDate(row.endTime, 'YYYY-MM-DD')}`,
  218. value: row.id,
  219. };
  220. }, this.state.search.timeId ? Number(this.state.search.timeId) : null, null);
  221. bindSearch(this.onlineFilter, 'userId', this, (search) => {
  222. return User.list(search);
  223. }, (row) => {
  224. return {
  225. title: `${row.nickname}(${row.mobile})`,
  226. value: row.id,
  227. };
  228. }, null, null);
  229. bindSearch(this.onlineList, 'timeId', this, (search) => {
  230. return Course.listTime(Object.assign({ courseId: id }, search));
  231. }, (row) => {
  232. return {
  233. title: `${formatDate(row.startTime, 'YYYY-MM-DD')}~${formatDate(row.endTime, 'YYYY-MM-DD')}`,
  234. value: row.id,
  235. };
  236. }, null, null);
  237. bindSearch(this.onlineList, 'userIds', this, (search) => {
  238. return User.list(search);
  239. }, (row) => {
  240. return {
  241. title: `${row.nickname}(${row.mobile})`,
  242. value: row.id,
  243. };
  244. }, null, null);
  245. this.refreshOnline();
  246. break;
  247. case 'vs':
  248. this.refreshVs();
  249. break;
  250. default:
  251. }
  252. }
  253. refreshOnline() {
  254. const { id } = this.params;
  255. Course.listStudentOnline(Object.assign({ courseId: id }, this.state.search)).then(result => {
  256. this.setTableData(result.list, result.total);
  257. });
  258. }
  259. refreshVs() {
  260. const { id } = this.params;
  261. Course.listStudentVs(Object.assign({ courseId: id }, this.state.search)).then(result => {
  262. this.setTableData(result.list, result.total);
  263. });
  264. }
  265. addOnlineStudentAction() {
  266. const { id } = this.params;
  267. asyncForm('添加', this.onlineList, {}, data => {
  268. return Promise.all(data.userIds.map(userId => Course.addStudentOnline({ courseId: id, timeId: data.timeId, userId }))).then(() => {
  269. asyncSMessage('添加成功!');
  270. this.refresh();
  271. });
  272. }).catch(err => {
  273. console.log(err);
  274. });
  275. }
  276. deleteOnlineStudent(row) {
  277. Course.delStudentOnline({ id: row.id }).then(() => {
  278. asyncSMessage('删除成功!');
  279. this.refresh();
  280. });
  281. }
  282. addVsStudentAction() {
  283. const { id } = this.params;
  284. const { data } = this.state;
  285. this.vsAddList[3].type = data.vsType === 'novice' ? 'hidden' : 'number';
  286. asyncForm('添加', this.vsAddList, {}, info => {
  287. if (data.vsType === 'novice') {
  288. // 写死:新手每次1课时
  289. info.number = 1;
  290. }
  291. // ([info.useStartTime, info.useEndTime] = info.time);
  292. return Course.addStudentVs(Object.assign({ courseId: id }, info)).then(() => {
  293. asyncSMessage('添加成功!');
  294. this.refresh();
  295. });
  296. }).then(component => {
  297. bindSearch(this.vsAddList, 'userId', component, (search) => {
  298. return User.list(search);
  299. }, (row) => {
  300. return {
  301. title: `${row.nickname}(${row.mobile})`,
  302. value: row.id,
  303. };
  304. }, null, null);
  305. bindSearch(this.vsAddList, 'teacherId', component, (search) => {
  306. return Course.listTeacher(Object.assign({ courseId: id }, search));
  307. }, (row) => {
  308. return {
  309. title: row.realname,
  310. value: row.id,
  311. };
  312. }, null, null);
  313. });
  314. }
  315. changeVs(record) {
  316. const { id } = this.params;
  317. asyncForm('修改', this.vsChangeList, record, info => {
  318. // ([info.useStartTime, info.useEndTime] = info.time);
  319. return Course.editStudentVs(Object.assign({ courseId: id }, info)).then(() => {
  320. asyncSMessage('编辑成功!');
  321. this.refresh();
  322. });
  323. }).then(component => {
  324. bindSearch(this.vsChangeList, 'teacherId', component, (search) => {
  325. return Course.listTeacher(Object.assign({ courseId: id }, search));
  326. }, (row) => {
  327. return {
  328. title: row.realname,
  329. value: row.id,
  330. };
  331. }, record.teacherId, null);
  332. });
  333. }
  334. renderOnline() {
  335. return <Block flex>
  336. {<FilterLayout
  337. show
  338. itemList={this.onlineFilter}
  339. data={this.state.search}
  340. onChange={data => {
  341. data.page = 1;
  342. this.search(data);
  343. }} />}
  344. <ActionLayout
  345. itemList={this.onlineAction}
  346. selectedKeys={this.state.selectedKeys}
  347. onAction={key => this.onAction(key)}
  348. />
  349. <TableLayout
  350. columns={this.onlineColumns}
  351. list={this.state.list}
  352. pagination={this.state.page}
  353. loading={this.props.core.loading}
  354. onChange={(pagination, filters, sorter) => this.tableChange(pagination, filters, sorter)}
  355. onSelect={(keys, rows) => this.tableSelect(keys, rows)}
  356. selectedKeys={this.state.selectedKeys}
  357. />
  358. </Block>;
  359. }
  360. renderVs() {
  361. return <Block flex>
  362. {<ActionLayout
  363. itemList={this.vsAction}
  364. selectedKeys={this.state.selectedKeys}
  365. onAction={key => this.onAction(key)}
  366. />}
  367. <TableLayout
  368. columns={this.vsColumns}
  369. list={this.state.list}
  370. pagination={this.state.page}
  371. loading={this.props.core.loading}
  372. onChange={(pagination, filters, sorter) => this.tableChange(pagination, filters, sorter)}
  373. onSelect={(keys, rows) => this.tableSelect(keys, rows)}
  374. selectedKeys={this.state.selectedKeys}
  375. />
  376. </Block>;
  377. }
  378. renderView() {
  379. switch (this.state.module) {
  380. case 'online':
  381. return [this.renderOnline()];
  382. case 'vs':
  383. return [this.renderVs()];
  384. case 'video':
  385. return [];
  386. default:
  387. return <div />;
  388. }
  389. }
  390. }