page.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. import React from 'react';
  2. import { Form, Input, Button, Row, Col, InputNumber, Switch } from 'antd';
  3. import './index.less';
  4. import Editor from '@src/components/Editor';
  5. import Page from '@src/containers/Page';
  6. import Block from '@src/components/Block';
  7. import Select from '@src/components/Select';
  8. // import FileUpload from '@src/components/FileUpload';
  9. import { formatFormError, getMap } from '@src/services/Tools';
  10. import { asyncSMessage } from '@src/services/AsyncTools';
  11. import { Sentence } from '../../../stores/sentence';
  12. import config from './index';
  13. export default class extends Page {
  14. constructor(props) {
  15. super(props);
  16. this.preview = null;
  17. this.structMap = {};
  18. this.partList = [];
  19. this.pageLine = 100;
  20. const { id } = this.params;
  21. if (id) {
  22. config.title = '编辑长难句文章';
  23. } else {
  24. config.title = '添加长难句文章';
  25. }
  26. }
  27. init() {
  28. Sentence.getStruct().then(result => {
  29. return this.refreshStruct(result);
  30. });
  31. }
  32. refreshStruct(result) {
  33. result = result || {};
  34. result.chapters = result.chapters || [];
  35. const chapters = result.chapters.map((row, index) => { row.value = index + 1; return row; }).filter(row => !row.exercise);
  36. this.structMap = getMap(chapters, 'value');
  37. this.setState({ struct: result, chapters });
  38. }
  39. refreshPart(chapter) {
  40. const { form } = this.props;
  41. const { id } = this.params;
  42. Sentence.listArticle({ chapter }).then(result => {
  43. this.partList = result.list.map(row => row.part);
  44. if (id) {
  45. this.partList = this.partList.filter(row => row !== this.data.part);
  46. }
  47. form.validateFields(['part'], { force: true });
  48. });
  49. }
  50. initData() {
  51. const { id } = this.params;
  52. const { form } = this.props;
  53. let handler;
  54. if (id) {
  55. handler = Sentence.getArticle({ id }).then((result) => {
  56. this.refreshPart(result.chapter);
  57. return result;
  58. });
  59. } else {
  60. handler = Promise.resolve({ part: 1 });
  61. }
  62. handler
  63. .then(result => {
  64. this.data = result;
  65. this.content = result.content || '';
  66. form.setFieldsValue(result);
  67. });
  68. }
  69. computePages() {
  70. if (!this.preview) return 0;
  71. this.preview.style.display = 'block';
  72. const lines = this.preview.clientHeight / 20;
  73. this.preview.style.display = 'none';
  74. return Math.ceil(lines / this.pageLine);
  75. }
  76. submit() {
  77. const { form } = this.props;
  78. form.validateFields((err) => {
  79. if (!err) {
  80. const data = form.getFieldsValue();
  81. data.isTrail = data.isTrail ? 1 : 0;
  82. data.pages = this.computePages();
  83. let handler;
  84. if (!data.id) {
  85. handler = Sentence.editArticle(data);
  86. } else {
  87. handler = Sentence.addArticle(data);
  88. }
  89. handler.then(() => {
  90. asyncSMessage('保存成功');
  91. goBack();
  92. }).catch((e) => {
  93. if (e.result) form.setFields(formatFormError(data, e.result));
  94. });
  95. }
  96. });
  97. }
  98. changeContent(content) {
  99. this.content = content;
  100. if (this.preview) {
  101. this.preview.innerHTML = content;
  102. }
  103. }
  104. renderBase() {
  105. const { getFieldDecorator, getFieldValue } = this.props.form;
  106. return <Block>
  107. <Form>
  108. {getFieldDecorator('id')(<input hidden />)}
  109. <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='Chapter'>
  110. {getFieldDecorator('chapter', {
  111. rules: [
  112. { required: true, message: '请选择章节' },
  113. ],
  114. })(
  115. <Select select={this.state.chapters} placeholder='请选择章节' onChange={(v) => {
  116. this.refreshPart(v);
  117. }} />,
  118. )}
  119. </Form.Item>
  120. <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='Part'>
  121. {getFieldDecorator('part', {
  122. rules: [
  123. { required: true, message: '请输入Part' },
  124. {
  125. validator: (rule, value, callback) => {
  126. if (this.partList.indexOf(value) >= 0) callback('该part已被使用');
  127. else callback();
  128. },
  129. },
  130. ],
  131. })(
  132. <InputNumber min={1} precision={0} formatter={(v) => parseInt(v, 10) || 1} />,
  133. )}
  134. </Form.Item>
  135. <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='名称'>
  136. {getFieldDecorator('title', {
  137. rules: [
  138. { required: true, message: '请输入名称' },
  139. ],
  140. })(
  141. <Input placeholder='请输入名称' />,
  142. )}
  143. </Form.Item>
  144. <Form.Item labelCol={{ span: 5 }} wrapperCol={{ span: 16 }} label='开放试用'>
  145. <Row>
  146. <Col span={4}>
  147. {getFieldDecorator('isTrail', {
  148. valuePropName: 'checked',
  149. })(
  150. <Switch checkedChildren='on' unCheckedChildren='off' />,
  151. )}
  152. </Col>
  153. <Col span={3}>
  154. <Form.Item>
  155. {getFieldDecorator('trailStart')(
  156. <InputNumber disabled={!getFieldValue('isTrail')} min={1} precision={0} formatter={(v) => parseInt(v, 10) || 1} />,
  157. )}
  158. </Form.Item>
  159. </Col>
  160. <Col span={1}>至</Col>
  161. <Col span={3}>
  162. <Form.Item>
  163. {getFieldDecorator('trailEnd')(
  164. <InputNumber disabled={!getFieldValue('isTrail')} min={1} precision={0} formatter={(v) => parseInt(v, 10) || 1} />,
  165. )}
  166. </Form.Item>
  167. </Col>
  168. </Row>
  169. </Form.Item>
  170. </Form>
  171. </Block>;
  172. }
  173. renderContent() {
  174. const { getFieldDecorator } = this.props.form;
  175. return <Block flex>
  176. <Form>
  177. <Form.Item label='文章录入'>
  178. {getFieldDecorator('content', {
  179. })(
  180. <Editor placeholder='输入内容'
  181. onChange={(value) => {
  182. this.changeContent(value);
  183. }} />,
  184. )}
  185. </Form.Item>
  186. </Form>
  187. <div ref={(ref) => {
  188. if (ref) {
  189. this.preview = ref;
  190. this.preview.style.display = 'none';
  191. this.changeContent(this.content);
  192. }
  193. }} className='simulation' />
  194. </Block>;
  195. }
  196. renderView() {
  197. return <div flex>
  198. {this.renderBase()}
  199. {this.renderContent()}
  200. <Row type="flex" justify="center">
  201. <Col>
  202. <Button type="primary" onClick={() => {
  203. this.submit();
  204. }}>保存</Button>
  205. </Col>
  206. </Row>
  207. </div>;
  208. }
  209. }