page.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. import React from 'react';
  2. import { Link } from 'react-router-dom';
  3. import { Button, Modal, Checkbox, Row, Col, Switch, Icon } from 'antd';
  4. import './index.less';
  5. import Page from '@src/containers/Page';
  6. import Block from '@src/components/Block';
  7. import EditTableCell from '@src/components/EditTableCell';
  8. // import DragList from '@src/components/DragList';
  9. import FilterLayout from '@src/layouts/FilterLayout';
  10. import TreeLayout from '@src/layouts/TreeLayout';
  11. import ActionLayout from '@src/layouts/ActionLayout';
  12. import TableLayout from '@src/layouts/TableLayout';
  13. import { formatDate, getMap, formatTreeData } from '@src/services/Tools';
  14. import { asyncSMessage, asyncDelConfirm } from '@src/services/AsyncTools';
  15. // import { ArticleChannel } from '../../../../Constant';
  16. import { Ready } from '../../../stores/ready';
  17. // const ArticleChannelMap = getMap(ArticleChannel, 'value', 'label');
  18. export default class extends Page {
  19. init() {
  20. this.categoryTitleMap = {};
  21. this.categoryMap = {};
  22. this.categoryList = [];
  23. this.categoryTree = [];
  24. this.categoryColumns = [{
  25. dataIndex: 'parentId',
  26. title: '一级标题',
  27. render: (text, record) => {
  28. if (text) {
  29. return this.categoryMap[text];
  30. }
  31. return record.title;
  32. },
  33. }, {
  34. dataIndex: 'title',
  35. title: '二级标题',
  36. render: (text, record) => {
  37. if (record.parentId) {
  38. return record.title;
  39. }
  40. return '-';
  41. },
  42. }, {
  43. dataIndex: 'isData',
  44. title: '资料节点',
  45. render: (text, record) => {
  46. return record.parentId > 0 && <Checkbox onChange={(e) => {
  47. this.changeCategoryData(record.id, e.target.checked);
  48. }} checked={!!text} />;
  49. },
  50. }, {
  51. dataIndex: 'isOfficial',
  52. title: '官方资料',
  53. render: (text, record) => {
  54. return record.parentId > 0 && record.isData > 0 && <Checkbox onChange={(e) => {
  55. this.changeCategoryOfficial(record.id, e.target.checked);
  56. }} checked={!!text} />;
  57. },
  58. }];
  59. this.filterF = null;
  60. this.filterForm = [{
  61. key: 'parentCategoryId',
  62. type: 'select',
  63. allowClear: true,
  64. name: '一级标题',
  65. placeholder: '请选择',
  66. select: [],
  67. number: true,
  68. onChange: (value) => {
  69. this.filterF.setFieldsValue({ categoryId: null });
  70. this.changeSearch(this.filterForm, this, value);
  71. },
  72. }, {
  73. key: 'categoryId',
  74. type: 'select',
  75. allowClear: true,
  76. name: '二级标题',
  77. select: [],
  78. number: true,
  79. placeholder: '请选择',
  80. }];
  81. this.actionList = [{
  82. key: 'add',
  83. type: 'primary',
  84. name: '创建',
  85. render: (item) => {
  86. return <Link to='/ready/article/detail'><Button>{item.name}</Button></Link>;
  87. },
  88. }, {
  89. key: 'category',
  90. name: '目录',
  91. }];
  92. this.columns = [{
  93. title: '一级标题',
  94. dataIndex: 'parentCategoryId',
  95. render: (text) => {
  96. return this.categoryTitleMap[text];
  97. },
  98. }, {
  99. title: '二级标题',
  100. dataIndex: 'categoryId',
  101. render: (text) => {
  102. return this.categoryTitleMap[text];
  103. },
  104. }, {
  105. title: '文章标题',
  106. dataIndex: 'title',
  107. }, {
  108. title: '更新时间',
  109. dataIndex: 'updateTime',
  110. render: (text) => {
  111. return formatDate(text, 'YYYY-MM-DD HH:mm:ss');
  112. },
  113. }, {
  114. title: '操作',
  115. dataIndex: 'handler',
  116. render: (text, record) => {
  117. return <div className="table-button">
  118. {<Link to={`/ready/article/detail/${record.id}`}>编辑</Link>}
  119. {<a onClick={() => {
  120. this.deleteAction(record);
  121. }}>删除</a>}
  122. </div>;
  123. },
  124. }];
  125. this.refreshCategory();
  126. }
  127. refreshCategory() {
  128. Ready.allCategory().then(result => {
  129. this.categoryTitleMap = getMap(result, 'id', 'title');
  130. this.categoryMap = getMap(result, 'id');
  131. result = result.filter(row => {
  132. if (!row.parentId) return true;
  133. const parent = this.categoryMap[row.parentId];
  134. if (parent) return true;
  135. return false;
  136. });
  137. const copy = result.map(row => Object.assign({}, row)).map((row) => {
  138. const parent = this.categoryMap[row.parentId];
  139. row.value = row.id;
  140. row.title = <Row style={{ width: 400 }}>
  141. <Col span={12}><Icon type="delete" onClick={() => this.deleteCategory(row.id)} /><EditTableCell value={row.title} onChange={(value) => this.changeCategoryTitle(row.id, value)} /></Col>
  142. <Col span={2} />
  143. <Col span={5}>{row.parentId === 0 && <Switch checked={row.isData} checkedChildren='资料节点' unCheckedChildren='非资料' onChange={() => this.changeCategoryData(row.id, !row.isData)} />}{row.parentId === 0 && <Switch checked={row.isRoom} checkedChildren='考场节点' unCheckedChildren='非考场' onChange={() => this.changeCategoryRoom(row.id, !row.isRoom)} />}</Col>
  144. <Col span={5}>{row.parentId > 0 && parent && parent.isData > 0 && <Switch checked={row.isOfficial} checkedChildren='官方资料' unCheckedChildren='非官方资料' onChange={() => this.changeCategoryOfficial(row.id, !row.isOfficial)} />}</Col>
  145. </Row>;
  146. return row;
  147. });
  148. this.categoryTree = formatTreeData(copy, 'id', 'title', 'parentId');
  149. this.categoryList = result.map(row => {
  150. row.value = row.id;
  151. return row;
  152. });
  153. this.filterForm[0].select = this.categoryList.filter(row => row.parentId === 0);
  154. this.changeSearch(this.filterForm, this, this.state.search.parentCategoryId);
  155. this.initData();
  156. this.setState({ categoryList: this.categoryList, categoryTree: this.categoryTree });
  157. });
  158. }
  159. changeSearch(list, component, value) {
  160. if (value) {
  161. list[1].disabled = false;
  162. list[1].select = this.categoryList.filter(row => row.parentId === Number(value));
  163. } else {
  164. list[1].disabled = true;
  165. list[1].select = [];
  166. }
  167. component.setState({ load: false });
  168. }
  169. initData() {
  170. Ready.listArticle(this.state.search).then(result => {
  171. this.setTableData(result.list, result.total);
  172. });
  173. }
  174. deleteAction(row) {
  175. asyncDelConfirm('删除确认', '是否删除选中?', () => {
  176. const handler = Ready.delArticle({ id: row.id });
  177. return handler.then(() => {
  178. asyncSMessage('删除成功!');
  179. this.refresh();
  180. });
  181. });
  182. }
  183. changeCategoryTitle(id, title) {
  184. Ready.editCategory({ id, title })
  185. .then(() => { });
  186. }
  187. changeCategoryRoom(id, checked) {
  188. const category = this.categoryMap[id];
  189. if (category.isRoom) {
  190. if (checked) return;
  191. } else if (!checked) return;
  192. Ready.editCategory({ id, isRoom: checked ? 1 : 0, isData: 0 })
  193. .then(() => {
  194. this.refreshCategory();
  195. });
  196. }
  197. changeCategoryData(id, checked) {
  198. const category = this.categoryMap[id];
  199. if (category.isData) {
  200. if (checked) return;
  201. } else if (!checked) return;
  202. Ready.editCategory({ id, isData: checked ? 1 : 0, isRoom: 0 })
  203. .then(() => {
  204. this.refreshCategory();
  205. });
  206. }
  207. changeCategoryOfficial(id, checked) {
  208. Ready.editCategory({ id, isOfficial: checked ? 1 : 0 })
  209. .then(() => {
  210. this.refreshCategory();
  211. });
  212. }
  213. deleteCategory(id) {
  214. asyncDelConfirm('删除确认', '是否删除选中?', () => {
  215. const handler = Ready.deleteCategory({ id });
  216. return handler.then(() => {
  217. asyncSMessage('删除成功!');
  218. this.refreshCategory();
  219. });
  220. });
  221. }
  222. changeCategoryOrder(from, to) {
  223. if (from.id === to.id) return;
  224. if (from.parentId !== to.parentId) {
  225. asyncSMessage('只允许同层排序', 'warn');
  226. return;
  227. }
  228. let parent = [];
  229. if (to.parentId === 0) {
  230. parent = this.categoryTree;
  231. } else {
  232. parent = this.categoryMap[to.parentId].children;
  233. }
  234. let oldIndex = -1;
  235. let newIndex = -1;
  236. parent.forEach((row, i) => {
  237. if (row.id === from.id) oldIndex = i;
  238. if (row.id === to.id) newIndex = i;
  239. });
  240. const others = parent.map(row => row.id);
  241. const tmp = others.splice(oldIndex, 1);
  242. if (newIndex === parent.length) {
  243. others.push(tmp[0]);
  244. } else {
  245. others.splice(newIndex, 0, tmp[0]);
  246. }
  247. Ready.editCategory({ id: from.id, index: newIndex === parent.length ? parent.length : newIndex })
  248. .then(() => {
  249. this.refreshCategory();
  250. });
  251. }
  252. categoryAction() {
  253. this.open({});
  254. }
  255. renderView() {
  256. return <Block flex>
  257. <FilterLayout
  258. show
  259. ref={ref => {
  260. if (ref) this.filterF = ref;
  261. }}
  262. itemList={this.filterForm}
  263. data={this.state.search}
  264. onChange={data => {
  265. data.page = 1;
  266. this.search(data);
  267. }} />
  268. <ActionLayout
  269. itemList={this.actionList}
  270. selectedKeys={this.state.selectedKeys}
  271. onAction={key => this.onAction(key)}
  272. />
  273. <TableLayout
  274. columns={this.tableSort(this.columns)}
  275. list={this.state.list}
  276. pagination={this.state.page}
  277. loading={this.props.core.loading}
  278. onChange={(pagination, filters, sorter) => this.tableChange(pagination, filters, sorter)}
  279. onSelect={(keys, rows) => this.tableSelect(keys, rows)}
  280. selectedKeys={this.state.selectedKeys}
  281. />
  282. {this.state.detail && <Modal visible closable title='目录结构' footer={null} onCancel={() => {
  283. this.close(false, 'detail');
  284. }} onOk={() => {
  285. this.close(true, 'detail');
  286. }} className="article-category-modal">
  287. <TreeLayout
  288. autoExpandParent
  289. defaultExpandAll
  290. itemList={this.state.categoryTree}
  291. selectable={false}
  292. draggable
  293. // onDragStart={({ event, node }) => console.log('start', event, node.props)}
  294. // onDragOver={({ event, node }) => console.log('over', event, node.props)}
  295. // onDragLeave={({ event, node }) => console.log('leave', event, node.kepropsy)}
  296. // onDragEnd={({ event, node }) => console.log('end', event, node.props)}
  297. // onDragEnter={({ event, node, expandedKeys }) => console.log('enter', event, node.props, expandedKeys)}
  298. onDrop={({ event, node, dragNode, dragNodesKeys }) => {
  299. console.log('drop', event, node.props, dragNode.props, dragNodesKeys);
  300. this.changeCategoryOrder(dragNode.props, node.props);
  301. }
  302. }
  303. />
  304. {/* <TableLayout
  305. rowKey={'id'}
  306. columns={this.categoryColumns}
  307. list={this.state.categoryList}
  308. pagination={false}
  309. /> */}
  310. {/* <DragList
  311. loading={this.props.core.loading}
  312. dataSource={this.state.categoryTree || []}
  313. handle={'.icon'}
  314. onMove={(oldIndex, newIndex) => {
  315. this.orderQuestion(oldIndex, newIndex);
  316. }}
  317. renderItem={(item) => (
  318. <List.Item actions={[<Icon type='bars' className='icon' />]}>
  319. <Row style={{ width: '100%' }}>
  320. <Col span={11}>标题: {item.title}</Col>
  321. </Row>
  322. <Row style={{ width: '100%' }}>
  323. <DragList
  324. loading={false}
  325. dataSource={item.children}
  326. handle={`.icon${item.id}`}
  327. onMove={(oldIndex, newIndex) => {
  328. this.orderQuestion(oldIndex, newIndex);
  329. }}
  330. renderItem={(row) => (
  331. <List.Item actions={[<Icon type='bars' className={`.icon${item.id}`} />]}>
  332. <Row style={{ width: '100%' }}>
  333. <Col span={11}>标题: {row.title}</Col>
  334. <Col span={5}><Switch checked={row.isData} checkedChildren='资料节点' unCheckedChildren='基本节点' onChange={() => this.changeCategoryData(row.id, !row.isData)} /></Col>
  335. <Col span={5}>{row.isData > 0 && <Switch checked={row.isOfficial} checkedChildren='官方资料' unCheckedChildren='非官方资料' onChange={() => this.changeCategoryOfficial(row.id, !row.isOfficial)} />}</Col>
  336. </Row>
  337. </List.Item>
  338. )} />
  339. </Row>
  340. </List.Item>
  341. )} /> */}
  342. </Modal>}
  343. </Block>;
  344. }
  345. }