index.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. import React, { PureComponent } from 'react';
  2. import { routerRedux } from 'dva/router';
  3. import PropTypes from 'prop-types';
  4. import queryString from 'query-string';
  5. import { connect } from 'dva';
  6. import { Spin, Popover, Badge, Table, Radio, Card, Form, Input, Icon, Button, Select } from 'antd';
  7. import PageHeaderLayout from '../../../layouts/PageHeaderLayout';
  8. import SupportSelectSortModal from './support';
  9. import ResourceSelectModal from './resource';
  10. import { Codes, ossHost } from '../../../utils/config';
  11. const FormItem = Form.Item;
  12. const Option = Select.Option;
  13. const { TextArea } = Input;
  14. @Form.create()
  15. @connect(state => ({
  16. merchant: state.merchant,
  17. resource: state.resource,
  18. support: state.support,
  19. supportDetail: state.supportDetail,
  20. }))
  21. export default class SupportDetail extends PureComponent {
  22. static propTypes = {
  23. supportDetail: PropTypes.object,
  24. };
  25. state = { curClickedBtn: null };
  26. componentDidMount() {
  27. const { dispatch } = this.props;
  28. dispatch({
  29. type: 'merchant/query',
  30. payload: {
  31. pageSize: 1000,
  32. pageNo: 1,
  33. domain: Codes.CODE_CP,
  34. }
  35. })
  36. }
  37. // 展示选择模态框 - 加载第一页数据
  38. handleModalShow = (btnName) => {
  39. this.setState({
  40. curClickedBtn: btnName,
  41. }, () => {
  42. const { dispatch } = this.props;
  43. if (btnName == 'supportBtn') {
  44. dispatch({ type: 'supportDetail/showSupportModal' });
  45. dispatch({
  46. type: 'support/query',
  47. payload: {
  48. pageNo: 1,
  49. pageSize: 10,
  50. }
  51. });
  52. } else if (btnName == 'imgBtn' || btnName == 'cvImgBtn') {
  53. dispatch({ type: 'supportDetail/showResourceModal' });
  54. dispatch({
  55. type: 'resource/query',
  56. payload: {
  57. pageNo: 1,
  58. pageSize: 10,
  59. type: Codes.CODE_IMAGE,
  60. }
  61. });
  62. }
  63. })
  64. }
  65. // 取消/关闭 - 隐藏选择模态框
  66. handleModalCancel = () => {
  67. const { curClickedBtn } = this.state;
  68. const { dispatch } = this.props;
  69. if (curClickedBtn == 'supportBtn') {
  70. dispatch({ type: 'supportDetail/hideSupportModal' });
  71. }
  72. if (curClickedBtn == 'imgBtn' || curClickedBtn == 'cvImgBtn') {
  73. dispatch({ type: 'supportDetail/hideResourceModal' });
  74. }
  75. }
  76. // 提交 - 保存选择和排序完的数据到model中
  77. handleModalOk = (data) => {
  78. const { curClickedBtn } = this.state;
  79. const { dispatch } = this.props;
  80. if (curClickedBtn == 'supportBtn') {
  81. dispatch({
  82. type: 'supportDetail/saveSupportList',
  83. payload: { supportList: data }
  84. });
  85. } else if (curClickedBtn == 'imgBtn') {
  86. dispatch({
  87. type: 'supportDetail/saveImgList',
  88. payload: { imgList: data.map(item => item.path) },
  89. });
  90. } else if (curClickedBtn == 'cvImgBtn') {
  91. dispatch({
  92. type: 'supportDetail/saveCoverImg',
  93. payload: { coverUrl: data.path },
  94. });
  95. }
  96. }
  97. // 搜索
  98. handleModalSearch = (data) => {
  99. const { curClickedBtn } = this.state;
  100. const { dispatch } = this.props;
  101. const newData = { ...data };
  102. if (newData.keyword) {
  103. newData[newData.field] = newData.keyword;
  104. }
  105. delete newData.field;
  106. delete newData.keyword;
  107. if (curClickedBtn == 'supportBtn') {
  108. dispatch({
  109. type: `support/query`,
  110. payload: { ...newData, pageNo: 1, pageSize: 10, status: Codes.CODE_NORMAL },
  111. });
  112. } else if (curClickedBtn == 'imgBtn' || curClickedBtn == 'cvImgBtn') {
  113. dispatch({
  114. type: `resource/query`,
  115. payload: { ...newData, pageNo: 1, pageSize: 10, status: Codes.CODE_NORMAL, type: Codes.CODE_IMAGE },
  116. });
  117. }
  118. }
  119. // 翻页 - 资源列表
  120. handleModalTableChange = (pagination, filterArgs, filters) => {
  121. const { curClickedBtn } = this.state;
  122. const { dispatch } = this.props;
  123. const newFilters = { ...filters };
  124. if (newFilters.keyword) {
  125. newFilters[newFilters.field] = newFilters.keyword;
  126. delete newFilters.field;
  127. delete newFilters.keyword;
  128. } else {
  129. delete newFilters.field;
  130. delete newFilters.keyword;
  131. }
  132. const getValue = obj => Object.keys(obj).map(key => obj[key]).join(',');
  133. const tableFilters = Object.keys(filterArgs).reduce((obj, key) => {
  134. const newObj = { ...obj };
  135. newObj[key] = getValue(filterArgs[key]);
  136. return newObj;
  137. }, {});
  138. const data = { ...newFilters, ...tableFilters, pageNo: pagination.current, pageSize: pagination.pageSize };
  139. Object.keys(data).map(key => data[key] ? null : delete data[key]);
  140. if (curClickedBtn == 'supportBtn') {
  141. dispatch({ type: `support/query`, payload: { ...data, status: Codes.CODE_NORMAL } });
  142. } else if (curClickedBtn == 'imgBtn' || curClickedBtn == 'cvImgBtn') {
  143. dispatch({ type: `resource/query`, payload: { ...data, status: Codes.CODE_NORMAL, type: Codes.CODE_IMAGE } });
  144. }
  145. }
  146. handlePageSubmit = (e) => {
  147. e.preventDefault()
  148. const {
  149. dispatch,
  150. form: {
  151. validateFields,
  152. getFieldsValue,
  153. resetFields
  154. },
  155. supportDetail: {
  156. operType,
  157. currentItem,
  158. filters,
  159. }
  160. } = this.props;
  161. validateFields((errors) => {
  162. if (errors) { return; }
  163. // 过滤掉gmtCreated, gmtModified, status三个字段
  164. const { supportList, imgList, gmtCreated, gmtModified, ...rest } = currentItem;
  165. let newImgList;
  166. let newSupportList;
  167. if (Array.isArray(imgList) && imgList.length) {
  168. newImgList = imgList;
  169. } else {
  170. newImgList = [];
  171. }
  172. // 如果supportList是个list且内容不为空
  173. if (Array.isArray(supportList) && supportList.length) {
  174. newSupportList = supportList.map(item => item.id);
  175. } else {
  176. newSupportList = [];
  177. }
  178. // 最终提交的数据
  179. const data = {
  180. ...rest,
  181. ...getFieldsValue(),
  182. imgList: newImgList,
  183. supportList: newSupportList,
  184. };
  185. // 其他参数
  186. if (operType == 'create') {
  187. data.type = Codes.CODE_SUPPORT;
  188. data.status = Codes.CODE_NORMAL;
  189. }
  190. dispatch({
  191. type: `supportDetail/${operType}`,
  192. payload: data,
  193. callback: () => {
  194. dispatch(
  195. routerRedux.push({
  196. pathname: '/product/support',
  197. search: queryString.stringify(filters),
  198. })
  199. );
  200. resetFields();
  201. }
  202. })
  203. });
  204. }
  205. handlePageCancel = () => {
  206. const { dispatch, supportDetail: { filters } } = this.props;
  207. dispatch({ type: 'supportDetail/initState' });
  208. dispatch(
  209. routerRedux.push({
  210. pathname: '/product/support',
  211. search: queryString.stringify(filters),
  212. })
  213. );
  214. }
  215. render() {
  216. const {
  217. merchant,
  218. resource,
  219. support,
  220. supportDetail,
  221. form: {
  222. getFieldDecorator
  223. },
  224. } = this.props;
  225. const {
  226. itemLoading,
  227. currentItem,
  228. filters,
  229. supportModalVisible,
  230. resourceModalVisible
  231. } = supportDetail;
  232. const {
  233. cpId,
  234. name,
  235. code,
  236. digest,
  237. detail,
  238. coverUrl,
  239. imgList,
  240. supportList,
  241. } = currentItem;
  242. const { curClickedBtn } = this.state;
  243. // 待选表格去掉分页的跳转及变换页码
  244. if (resource && resource.pagination) {
  245. delete resource.pagination.showQuickJumper;
  246. delete resource.pagination.showSizeChanger;
  247. }
  248. const supportTableColumns = [{
  249. title: '配套编号',
  250. dataIndex: 'code',
  251. key: 'code',
  252. },{
  253. title: '配套名称',
  254. dataIndex: 'name',
  255. key: 'name',
  256. }];
  257. const imgTableColumns = [{
  258. title: '位置',
  259. dataIndex: 'sort',
  260. key: 'sort',
  261. render: (text, record, index) => index + 1,
  262. },{
  263. title: '缩略图',
  264. dataIndex: 'path',
  265. key: 'path',
  266. render: (text, record) => (
  267. <Popover
  268. content={<img alt="" src={`${ossHost}/${text}`} width={350} />}
  269. title={record.name}
  270. >
  271. <img alt="" src={`${ossHost}/${text}`} width={70} />
  272. </Popover>
  273. ),
  274. // },{
  275. // title: '图片编号',
  276. // dataIndex: 'code',
  277. // key: 'code',
  278. // },{
  279. // title: '图片名称',
  280. // dataIndex: 'name',
  281. // key: 'name',
  282. }];
  283. const formItemLayout = {
  284. labelCol: {
  285. span: 7,
  286. },
  287. wrapperCol: {
  288. span: 12,
  289. },
  290. };
  291. const submitFormLayout = {
  292. wrapperCol: {
  293. xs: { span: 24, offset: 0 },
  294. sm: { span: 10, offset: 7 },
  295. },
  296. };
  297. return (
  298. <PageHeaderLayout>
  299. <Spin spinning={itemLoading}>
  300. <Card title="配套信息">
  301. <Form layout="horizontal" onSubmit={this.handlePageSubmit}>
  302. <FormItem label="配套编号:" hasFeedback {...formItemLayout}>
  303. {getFieldDecorator('code', {
  304. rules: [{ required: true, type: 'string', message: "编号为必填项!" }],
  305. initialValue: code,
  306. })(<Input />)}
  307. </FormItem>
  308. <FormItem label="配套名称:" hasFeedback {...formItemLayout}>
  309. {getFieldDecorator('name', {
  310. rules: [{ required: true, type: 'string', message: "名称为必填项!" }],
  311. initialValue: name,
  312. })(<Input />)}
  313. </FormItem>
  314. <FormItem label="配套概要:" hasFeedback {...formItemLayout}>
  315. {getFieldDecorator('digest', {
  316. initialValue: digest,
  317. })(<TextArea />)}
  318. </FormItem>
  319. <FormItem label="配套详情:" hasFeedback {...formItemLayout}>
  320. {getFieldDecorator('detail', {
  321. initialValue: detail,
  322. })(<TextArea />)}
  323. </FormItem>
  324. <FormItem label="所属供应商:" {...formItemLayout}>
  325. {getFieldDecorator('cpId', {
  326. initialValue: cpId,
  327. })(
  328. <Select placeholder="请选择">{merchant.list.map(item => <Option value={item.id} key={item.id}>{item.name}</Option>)}</Select>
  329. )}
  330. </FormItem>
  331. <FormItem label="封面图片" {...formItemLayout}>
  332. <Button onClick={() => this.handleModalShow('cvImgBtn')} type="primary" icon="select" size="small">选择</Button>
  333. {!coverUrl? null :
  334. <Card
  335. hoverable
  336. bordered
  337. cover={<img alt="" src={coverUrl.startsWith('http') ? coverUrl : `${ossHost}/${coverUrl}`} />}
  338. style={{ width: 240, marginTop: 20 }}
  339. >
  340. </Card>}
  341. </FormItem>
  342. <FormItem label="图片列表" {...formItemLayout}>
  343. <Button onClick={() => this.handleModalShow('imgBtn')} type="primary" size="small" icon="edit">编辑</Button>
  344. </FormItem>
  345. <FormItem wrapperCol={{ offset: 7, span: 12 }}>
  346. <Table
  347. locale={{
  348. emptyText: <span style={{ color: "#C6D0D6" }}>&nbsp;&nbsp;<Icon type="frown-o"/>
  349. 该配套下不包含任何图片,请选择!</span>
  350. }}
  351. dataSource={(imgList || []).map((item,index) => ({ id: index, path: item }))}
  352. columns={imgTableColumns}
  353. rowKey={record => record.id}
  354. bordered
  355. pagination={false}
  356. />
  357. </FormItem>
  358. <FormItem label="相关配套" {...formItemLayout}>
  359. <Button onClick={() => this.handleModalShow('supportBtn')} type="primary" size="small" icon="edit">编辑</Button>
  360. </FormItem>
  361. <FormItem wrapperCol={{ offset: 7, span: 12 }}>
  362. <Table
  363. locale={{
  364. emptyText: <span style={{ color: "#C6D0D6" }}>&nbsp;&nbsp;<Icon type="frown-o"/>
  365. 暂无与该配套相关的配套,请选择!</span>
  366. }}
  367. dataSource={supportList || []}
  368. columns={supportTableColumns}
  369. rowKey={record => record.id}
  370. bordered
  371. pagination={false}
  372. />
  373. </FormItem>
  374. <FormItem {...submitFormLayout} style={{ marginTop: 32 }}>
  375. <Button onClick={this.handlePageCancel}>取消</Button>
  376. <Button type="primary" style={{ marginLeft: 35 }} htmlType="submit">提交</Button>
  377. </FormItem>
  378. </Form>
  379. {/*周边的模态选择框*/}
  380. <SupportSelectSortModal
  381. rowKeyName="id"
  382. modalVisible={supportModalVisible}
  383. style={{ top: 20 }}
  384. width={600}
  385. onCancel={this.handleModalCancel}
  386. onOk={this.handleModalOk}
  387. onSearch={this.handleModalSearch}
  388. selTableData={supportList || []}
  389. fsTableDataSource={support.list || []}
  390. fsTableLoading={support.listLoading}
  391. fsTablePagination={support.pagination}
  392. fsTableOnChange={this.handleModalTableChange}
  393. />
  394. {/*图片资源的模态选择框*/}
  395. <ResourceSelectModal
  396. mode={curClickedBtn == 'imgBtn' ? 'multiple' : 'single'}
  397. rowKeyName="id"
  398. modalVisible={resourceModalVisible}
  399. style={{ top: 20 }}
  400. width={600}
  401. onOk={this.handleModalOk}
  402. onCancel={this.handleModalCancel}
  403. onSearch={this.handleModalSearch}
  404. selTableData={[]}
  405. fsTableDataSource={resource.list || []}
  406. fsTableLoading={resource.listLoading}
  407. fsTablePagination={resource.pagination}
  408. fsTableOnChange={this.handleModalTableChange}
  409. />
  410. </Card>
  411. </Spin>
  412. </PageHeaderLayout>
  413. );
  414. }
  415. }