|
@@ -0,0 +1,489 @@
|
|
|
+import React, { Component } from 'react';
|
|
|
+import pathToRegexp from 'path-to-regexp';
|
|
|
+import { connect } from 'dva';
|
|
|
+import { routerRedux } from 'dva/router';
|
|
|
+import { Form, Modal, Card, Button, Input, Switch, Row, Col, Carousel, Select } from 'antd';
|
|
|
+import { renderStatus, statusToBool, boolToStatus, genAbsolutePicUrl } from '../../../utils/utils';
|
|
|
+import AXDragSortTable from '../../../components/AXDragSortTable';
|
|
|
+import Selector from '../../../components/AXTableSelector/Selector';
|
|
|
+import FooterToolbar from '../../../components/FooterToolbar';
|
|
|
+import styles from './SupportCreate.less';
|
|
|
+
|
|
|
+const fieldLabels = {
|
|
|
+ code: '配套编号',
|
|
|
+ title: '配套标题',
|
|
|
+ subTitle: '配套副标题',
|
|
|
+ name: '配套全称',
|
|
|
+ merchant: '内容提供商',
|
|
|
+ digest: '配套概要',
|
|
|
+ detail: '配套详情',
|
|
|
+ coverUrl: '配套封面图',
|
|
|
+ imgList: '配套滚动图册',
|
|
|
+ status: '配套状态',
|
|
|
+};
|
|
|
+const formItemLayout = {
|
|
|
+ labelCol: {
|
|
|
+ xs: { span: 24 },
|
|
|
+ sm: { span: 3 },
|
|
|
+ },
|
|
|
+ wrapperCol: {
|
|
|
+ xs: { span: 24 },
|
|
|
+ sm: { span: 14 },
|
|
|
+ md: { span: 12 },
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+@connect(({ loading, product, resource, merchant }) => ({
|
|
|
+ product,
|
|
|
+ resource,
|
|
|
+ merchant,
|
|
|
+ pLoading: loading.models.product,
|
|
|
+ rLoading: loading.models.resource,
|
|
|
+ submitting: loading.models.product,
|
|
|
+}))
|
|
|
+@Form.create()
|
|
|
+export default class SupportCreatePage extends Component {
|
|
|
+ state = {
|
|
|
+ coverSelectorDestroy: true,
|
|
|
+ carouselSelectorDestroy: true,
|
|
|
+ supportSelectorDestroy: true,
|
|
|
+ };
|
|
|
+ componentWillMount() {
|
|
|
+ const match = pathToRegexp('/product/support/create').exec(this.props.location.pathname);
|
|
|
+ if (match) {
|
|
|
+ this.cleanPageState();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ componentDidMount() {
|
|
|
+ const matchId = this.isEdit();
|
|
|
+ if (matchId) {
|
|
|
+ this.props.dispatch({
|
|
|
+ type: 'product/fetchProductItem',
|
|
|
+ payload: { pid: matchId },
|
|
|
+ });
|
|
|
+ }
|
|
|
+ this.props.dispatch({
|
|
|
+ type: 'merchant/fetchMerchantList',
|
|
|
+ payload: { pageSize: 1000 }, // TODO 以后商户多了需要改写交互样式
|
|
|
+ });
|
|
|
+ }
|
|
|
+ isEdit = () => {
|
|
|
+ const { location } = this.props;
|
|
|
+ const match = pathToRegexp('/product/support/edit/:id').exec(location.pathname);
|
|
|
+ if (match) {
|
|
|
+ return match[1];
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ };
|
|
|
+ cleanPageState = () => {
|
|
|
+ this.props.dispatch({
|
|
|
+ type: 'product/cleanItemState',
|
|
|
+ payload: {},
|
|
|
+ });
|
|
|
+ };
|
|
|
+ selectorDataFetcher = (name, params) => {
|
|
|
+ switch (name) {
|
|
|
+ case 'cover':
|
|
|
+ this.props.dispatch({
|
|
|
+ type: 'resource/fetchImageList',
|
|
|
+ payload: params,
|
|
|
+ });
|
|
|
+ break;
|
|
|
+ case 'carousel':
|
|
|
+ this.props.dispatch({
|
|
|
+ type: 'resource/fetchImageList',
|
|
|
+ payload: params,
|
|
|
+ });
|
|
|
+ break;
|
|
|
+ case 'support':
|
|
|
+ this.props.dispatch({
|
|
|
+ type: 'product/fetchSupportList',
|
|
|
+ payload: params,
|
|
|
+ });
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ currentItemFormatter = (name, rows) => {
|
|
|
+ let payload;
|
|
|
+ switch (name) {
|
|
|
+ case 'cover':
|
|
|
+ payload = { coverUrl: rows[0].path };
|
|
|
+ break;
|
|
|
+ case 'carousel':
|
|
|
+ payload = { imgList: rows.map(row => row.path) };
|
|
|
+ break;
|
|
|
+ case 'support':
|
|
|
+ payload = { supportList: rows };
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return payload;
|
|
|
+ };
|
|
|
+ handleSelectorModalShow = (name) => {
|
|
|
+ this.setState({
|
|
|
+ [`${name}SelectorDestroy`]: false,
|
|
|
+ });
|
|
|
+ this.selectorDataFetcher(name);
|
|
|
+ };
|
|
|
+ handleSelectorChange = (name, params) => {
|
|
|
+ this.selectorDataFetcher(name, params);
|
|
|
+ };
|
|
|
+ handleSelectorFinish = (name, rows) => {
|
|
|
+ this.setState({
|
|
|
+ [`${name}SelectorDestroy`]: true,
|
|
|
+ });
|
|
|
+ const payload = this.currentItemFormatter(name, rows);
|
|
|
+ this.props.dispatch({
|
|
|
+ payload,
|
|
|
+ type: 'product/fixCurrentItem',
|
|
|
+ });
|
|
|
+ };
|
|
|
+ handleDragSortTableChange = (name, rows) => {
|
|
|
+ const payload = this.currentItemFormatter(name, rows);
|
|
|
+ this.props.dispatch({
|
|
|
+ payload,
|
|
|
+ type: 'product/fixCurrentItem',
|
|
|
+ });
|
|
|
+ };
|
|
|
+ handleSelectorCancel = (name) => {
|
|
|
+ this.setState({
|
|
|
+ [`${name}SelectorDestroy`]: true,
|
|
|
+ });
|
|
|
+ };
|
|
|
+ handlePageBack = () => {
|
|
|
+ this.props.dispatch(routerRedux.push({
|
|
|
+ pathname: '/product/support/list',
|
|
|
+ state: this.props.location.state,
|
|
|
+ }));
|
|
|
+ };
|
|
|
+ handlePageSubmit = (e) => {
|
|
|
+ e.preventDefault();
|
|
|
+ this.props.form.validateFieldsAndScroll((err, values) => {
|
|
|
+ if (!err) {
|
|
|
+ // 从表单提取基础信息字段
|
|
|
+ const { status, title, subTitle, name, ...rest } = values;
|
|
|
+ const newName = `${title}_${subTitle}`;
|
|
|
+ const newVals = { title, subTitle, name: newName, status: boolToStatus(status), ...rest };
|
|
|
+
|
|
|
+ // 从props中提取coverUrl、imgList、supportList字段
|
|
|
+ const { product } = this.props;
|
|
|
+ const { currentItem } = product;
|
|
|
+ const { imgList, supportList, coverUrl } = currentItem;
|
|
|
+
|
|
|
+ // 防止supportList为空
|
|
|
+ let supportIdList;
|
|
|
+ if (supportList && supportList.length) {
|
|
|
+ supportIdList = supportList.map(item => item.id);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新或者创建操作
|
|
|
+ const matchId = this.isEdit();
|
|
|
+ if (matchId) {
|
|
|
+ const params = {
|
|
|
+ imgList,
|
|
|
+ coverUrl,
|
|
|
+ supportList: supportIdList,
|
|
|
+ id: matchId,
|
|
|
+ ...newVals,
|
|
|
+ };
|
|
|
+ this.props.dispatch({
|
|
|
+ type: 'product/updateSupportItem',
|
|
|
+ payload: params,
|
|
|
+ states: this.props.location.state,
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ const params = {
|
|
|
+ imgList,
|
|
|
+ coverUrl,
|
|
|
+ supportList: supportIdList,
|
|
|
+ ...newVals,
|
|
|
+ };
|
|
|
+ this.props.dispatch({
|
|
|
+ type: 'product/createSupportItem',
|
|
|
+ payload: params,
|
|
|
+ states: this.props.location.state,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ render() {
|
|
|
+ const {
|
|
|
+ form, submitting, rLoading, pLoading, product, resource, merchant,
|
|
|
+ } = this.props;
|
|
|
+ const {
|
|
|
+ supportSelectorDestroy, coverSelectorDestroy, carouselSelectorDestroy,
|
|
|
+ } = this.state;
|
|
|
+ const {
|
|
|
+ currentItem,
|
|
|
+ } = product;
|
|
|
+ const {
|
|
|
+ code, title, subTitle, name, digest, detail, status, coverUrl, cpId,
|
|
|
+ imgList = [], supportList = [],
|
|
|
+ } = currentItem;
|
|
|
+ const {
|
|
|
+ getFieldDecorator,
|
|
|
+ } = form;
|
|
|
+
|
|
|
+ const supportColumns = [{
|
|
|
+ title: '配套编号',
|
|
|
+ dataIndex: 'code',
|
|
|
+ key: 1,
|
|
|
+ width: '20%',
|
|
|
+ render: (text, record) => (
|
|
|
+ <a
|
|
|
+ className="a-link"
|
|
|
+ target="_blank"
|
|
|
+ rel="noopener noreferrer"
|
|
|
+ href={`/product/support/edit/${record.id}`}
|
|
|
+ >
|
|
|
+ {text}
|
|
|
+ </a>
|
|
|
+ ),
|
|
|
+ }, {
|
|
|
+ title: '配套名称',
|
|
|
+ dataIndex: 'name',
|
|
|
+ key: 2,
|
|
|
+ width: '30%',
|
|
|
+ render: (text, record) => (
|
|
|
+ <a
|
|
|
+ className="a-link"
|
|
|
+ target="_blank"
|
|
|
+ rel="noopener noreferrer"
|
|
|
+ href={`/product/support/edit/${record.id}`}
|
|
|
+ >
|
|
|
+ {text}
|
|
|
+ </a>
|
|
|
+ ),
|
|
|
+ }, {
|
|
|
+ title: '配套状态',
|
|
|
+ dataIndex: 'status',
|
|
|
+ key: 3,
|
|
|
+ render: text => renderStatus(text),
|
|
|
+ }];
|
|
|
+
|
|
|
+ const getMerchants = () => {
|
|
|
+ const { list } = merchant;
|
|
|
+ return list.map(item => ({
|
|
|
+ text: item.name,
|
|
|
+ key: item.id,
|
|
|
+ }));
|
|
|
+ };
|
|
|
+
|
|
|
+ const getResourceModal = (isCover) => {
|
|
|
+ return (
|
|
|
+ <Modal
|
|
|
+ width={isCover ? 900 : 1100}
|
|
|
+ footer={null}
|
|
|
+ visible
|
|
|
+ title="图片资源"
|
|
|
+ maskClosable={false}
|
|
|
+ onCancel={() => this.handleSelectorCancel(isCover ? 'cover' : 'carousel')}
|
|
|
+ >
|
|
|
+ <Selector
|
|
|
+ loading={rLoading}
|
|
|
+ list={resource.list}
|
|
|
+ pageNo={resource.pageNo}
|
|
|
+ pageSize={resource.pageSize}
|
|
|
+ totalSize={resource.totalSize}
|
|
|
+ multiple={!isCover}
|
|
|
+ selectorName={isCover ? 'PictureSingle' : 'Picture'}
|
|
|
+ onCancel={() => this.handleSelectorCancel(isCover ? 'cover' : 'carousel')}
|
|
|
+ onChange={data => this.handleSelectorChange(isCover ? 'cover' : 'carousel', data)}
|
|
|
+ onFinish={rows => this.handleSelectorFinish(isCover ? 'cover' : 'carousel', rows)}
|
|
|
+ />
|
|
|
+ </Modal>
|
|
|
+ );
|
|
|
+ };
|
|
|
+ const getSupportModal = () => {
|
|
|
+ return (
|
|
|
+ <Modal
|
|
|
+ width={1100}
|
|
|
+ footer={null}
|
|
|
+ visible
|
|
|
+ title="配套资源"
|
|
|
+ maskClosable={false}
|
|
|
+ onCancel={() => this.handleSelectorCancel('support')}
|
|
|
+ >
|
|
|
+ <Selector
|
|
|
+ multiple
|
|
|
+ loading={pLoading}
|
|
|
+ selectorName="Support"
|
|
|
+ list={product.list}
|
|
|
+ pageNo={product.pageNo}
|
|
|
+ pageSize={product.pageSize}
|
|
|
+ totalSize={product.totalSize}
|
|
|
+ onCancel={() => this.handleSelectorCancel('support')}
|
|
|
+ onChange={data => this.handleSelectorChange('support', data)}
|
|
|
+ onFinish={rows => this.handleSelectorFinish('support', rows)}
|
|
|
+ />
|
|
|
+ </Modal>
|
|
|
+ );
|
|
|
+ };
|
|
|
+
|
|
|
+ const renderSupportCardName = () => {
|
|
|
+ return (
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ onClick={() => this.handleSelectorModalShow('support')}
|
|
|
+ >相关配套
|
|
|
+ </Button>
|
|
|
+ );
|
|
|
+ };
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ {/* 基础信息Card */}
|
|
|
+ <Card title="基础信息" style={{ marginBottom: 16 }}>
|
|
|
+ <Form>
|
|
|
+ <Form.Item hasFeedback label={fieldLabels.code} {...formItemLayout}>
|
|
|
+ {getFieldDecorator('code', {
|
|
|
+ rules: [
|
|
|
+ {
|
|
|
+ required: true, message: '请填写配套编号',
|
|
|
+ }, {
|
|
|
+ pattern: /^[a-zA-Z0-9|-]+$/g, message: '编号包含非法字符',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ initialValue: code,
|
|
|
+ })(
|
|
|
+ <Input placeholder="请输入" />
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
+ {this.isEdit() && (
|
|
|
+ <Form.Item label={fieldLabels.name} {...formItemLayout}>
|
|
|
+ {getFieldDecorator('name', {
|
|
|
+ initialValue: name,
|
|
|
+ })(
|
|
|
+ <Input disabled />
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
+ )}
|
|
|
+ <Form.Item hasFeedback label={fieldLabels.title} {...formItemLayout}>
|
|
|
+ {getFieldDecorator('title', {
|
|
|
+ rules: [{ required: true, message: '请填写配套标题' }],
|
|
|
+ initialValue: title,
|
|
|
+ })(
|
|
|
+ <Input placeholder="请输入" />
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item hasFeedback label={fieldLabels.subTitle} {...formItemLayout}>
|
|
|
+ {getFieldDecorator('subTitle', {
|
|
|
+ rules: [{ required: true, message: '请填写配套副标题' }],
|
|
|
+ initialValue: subTitle,
|
|
|
+ })(
|
|
|
+ <Input placeholder="请输入" />
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item hasFeedback label={fieldLabels.merchant} {...formItemLayout}>
|
|
|
+ {getFieldDecorator('cpId', {
|
|
|
+ rules: [{ required: true, message: '请选择供应商' }],
|
|
|
+ initialValue: cpId,
|
|
|
+ })(
|
|
|
+ <Select placeholder="请选择">
|
|
|
+ {
|
|
|
+ getMerchants().map(item => (
|
|
|
+ <Select.Option key={item.key} value={item.key}>
|
|
|
+ {item.text}
|
|
|
+ </Select.Option>
|
|
|
+ ))
|
|
|
+ }
|
|
|
+ </Select>
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item label={fieldLabels.digest} {...formItemLayout}>
|
|
|
+ {getFieldDecorator('digest', {
|
|
|
+ initialValue: digest,
|
|
|
+ })(
|
|
|
+ <Input.TextArea rows={4} placeholder="请输入" />
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item label={fieldLabels.detail} {...formItemLayout}>
|
|
|
+ {getFieldDecorator('detail', {
|
|
|
+ initialValue: detail,
|
|
|
+ })(
|
|
|
+ <Input.TextArea rows={6} placeholder="请输入" />
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item label={fieldLabels.status} {...formItemLayout}>
|
|
|
+ {getFieldDecorator('status', {
|
|
|
+ valuePropName: 'checked',
|
|
|
+ initialValue: statusToBool(status),
|
|
|
+ })(
|
|
|
+ <Switch
|
|
|
+ checkedChildren="正常"
|
|
|
+ unCheckedChildren="删除"
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
+ </Form>
|
|
|
+ </Card>
|
|
|
+ <Row gutter={16} style={{ marginBottom: 16 }}>
|
|
|
+ <Col span={12}>
|
|
|
+ <Card
|
|
|
+ title={
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ onClick={() => this.handleSelectorModalShow('cover')}
|
|
|
+ >配套封面
|
|
|
+ </Button>
|
|
|
+ }
|
|
|
+ className={styles.picCard}
|
|
|
+ >
|
|
|
+ {coverUrl && <img src={coverUrl && genAbsolutePicUrl(coverUrl)} alt="" />}
|
|
|
+ {!coverSelectorDestroy && getResourceModal(true)}
|
|
|
+ </Card>
|
|
|
+ </Col>
|
|
|
+ <Col span={12}>
|
|
|
+ <Card
|
|
|
+ title={
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ onClick={() => this.handleSelectorModalShow('carousel')}
|
|
|
+ >详情图册
|
|
|
+ </Button>
|
|
|
+ }
|
|
|
+ className={styles.carouselCard}
|
|
|
+ >
|
|
|
+ <Carousel autoplay>
|
|
|
+ {
|
|
|
+ imgList.map(
|
|
|
+ path => (
|
|
|
+ <img key={path} src={genAbsolutePicUrl(path)} alt="" />
|
|
|
+ )
|
|
|
+ )
|
|
|
+ }
|
|
|
+ </Carousel>
|
|
|
+ {!carouselSelectorDestroy && getResourceModal(false)}
|
|
|
+ </Card>
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
+ {/* 相关周边配套选择Card */}
|
|
|
+ <Card title={renderSupportCardName()} style={{ marginBottom: 70 }}>
|
|
|
+ <AXDragSortTable
|
|
|
+ columns={supportColumns}
|
|
|
+ data={supportList}
|
|
|
+ onChange={rows => this.handleDragSortTableChange('support', rows)}
|
|
|
+ />
|
|
|
+ {!supportSelectorDestroy && getSupportModal()}
|
|
|
+ </Card>
|
|
|
+ <FooterToolbar style={{ width: '100%' }}>
|
|
|
+ <Button
|
|
|
+ onClick={this.handlePageBack}
|
|
|
+ style={{ marginRight: 10 }}
|
|
|
+ >取消
|
|
|
+ </Button>
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ loading={submitting}
|
|
|
+ onClick={this.handlePageSubmit}
|
|
|
+ >提交
|
|
|
+ </Button>
|
|
|
+ </FooterToolbar>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|