组件化开发复杂表单-动态矩阵定价

一、需求

动态矩阵定价,是动态行、动态列组成的表单,每行的影厅类型,对不同影片版本进行价格设置,用户可选择给哪些厅哪些影片版本设置价格。

二、数据结构

三、组件开发

ItemCombination.js:

import React, { PureComponent, Fragment } from 'react';
import { connect } from 'dva';
import moment from 'moment';
import { Form, Tag, Row, Col, Input, InputNumber, Button, Select, Card, Modal, DatePicker, TimePicker, Radio, Checkbox, Icon, message, Tooltip, Tabs, Table } from 'antd';

import CheckboxAll from '@/components/CheckboxAll/CheckboxAll';
import RowItemSetPrice from './RowItemSetPrice';
import RowItemIfBreak from './RowItemIfBreak';
import styles from '../subitemHigherForm.less';

const FormItem = Form.Item;
const RadioGroup = Radio.Group;
const { Option } = Select;
const dispatchType = 'marketingActivitySubitemHigherForm/setArrFieldData';

// 影厅类型和影片版本组合设置
@Form.create()
export default class extends PureComponent {
    constructor(props) {
        super(props);
        this.state = {

        };
    }

    onChange = (type, value) => {
        // console.log(type, value)
        const {
            dispatch,
            itemParams,
        } = this.props;
        dispatch({
            type: dispatchType,
            payload: {
                [type]: value,
                id: itemParams.id
            },
        });
    }

    // 表头
    renderColumns = () => {
        const {
            dispatch,
            itemParams,
        } = this.props;
        const propsRowItem = {
            itemId: itemParams.id,
            priceTable: itemParams.priceTable,
            dispatch,
            dispatchType,
        }
        // test 
        // {
        //     title: '2D',
        //     dataIndex: '2D',
        //     key: '2D',
        //     render: (value, row, index) => {
        //         console.log(value, row, index)
        //         return (<RowItemSetPrice
        //             {...propsRowItem}
        //             dataIndex={"2D"}
        //             renderRow={value}
        //             renderIndex={index}
        //         />);
        //     },
        // },
        return (!itemParams.selectedVersion.length && !itemParams.priceTable.length) ? [] : [
            {
                title: '影厅类型',
                dataIndex: 'name',
                key: "name",
                width: 160,
                align: "center",
                fixed: 'left',
            },
            ...itemParams.selectedVersion.map(item => {
                return {
                    title: item,
                    dataIndex: item,
                    key: item,
                    render: (value, row, index) => {
                        return (<RowItemSetPrice
                            {...propsRowItem}
                            dataIndex={item}
                            renderRow={value}
                            renderIndex={index}
                        />);
                    }
                }
            }),
            {
                title: '允许结算价突破最低发行价',
                dataIndex: 'ifBreak',
                key: 'ifBreak',
                width: 360,
                align: "center",
                render: (value, row, index) => {
                    return (<RowItemIfBreak
                        {...propsRowItem}
                        renderValue={value}
                        renderIndex={index}
                    />);
                },
                fixed: 'right',
            },
        ]
    };

    render() {
        const {
            form: { getFieldDecorator, setFieldsValue },
            dispatch,
            radioHigherSelected,
            list,
            itemParams,
            baseSubWeekOptions,
            baseSubFilmVersionOptions,
            baseSubHallsTypeOptions,
        } = this.props;

        const propsWeekCheckboxAll = {
            name: "selectedWeek",
            optionsAll: baseSubWeekOptions,
            initialValue: itemParams.selectedWeek,
            itemId: itemParams.id,
            dispatch,
            dispatchType,
        };
        const propsVersionCheckboxAll = {
            name: "selectedVersion",
            optionsAll: baseSubFilmVersionOptions.map(item => ({ code: item.k, name: item.v })),
            initialValue: itemParams.selectedVersion,
            itemId: itemParams.id,
            linkage: "colAddDel",
            dispatch,
            dispatchType,
        };

        const propsHallTypeCheckboxAll = {
            name: "selectedHallType",
            optionsAll: baseSubHallsTypeOptions.map(item => ({ code: item.k, name: item.v })),
            initialValue: itemParams.selectedHallType,
            itemId: itemParams.id,
            linkage: "rowAddDel",
            dispatch,
            dispatchType,
        };

        return (
            <Fragment>
                <FormItem label="星期" className={styles.weekBox}>
                    {getFieldDecorator('selectedWeek', {
                        initialValue: itemParams.selectedWeek,
                        rules: [
                            { required: true, message: '' },
                        ],
                    })(<CheckboxAll {...propsWeekCheckboxAll} />)}
                </FormItem>
                <FormItem label="场次时段" required>
                    <Row className={styles.timeRow} type="flex" justify="start">
                        <FormItem>
                            {getFieldDecorator("showtimeStart", {
                                initialValue: itemParams.showtimeStart ? moment(itemParams.showtimeStart, 'HH:mm') : null,
                                rules: [{ required: true, message: '开始时间为必填项' }],
                            })(
                                <TimePicker
                                    format="HH:mm"
                                    onChange={(time, timeString) => this.onChange("showtimeStart", timeString)}
                                    name="showtimeStart"
                                    defaultOpenValue={moment(`${new Date().getHours()}:00`, 'HH:mm')}
                                />
                            )}
                        </FormItem>

                        <span style={{ paddingLeft: 10, paddingRight: 10, lineHeight: '35px' }}>~</span>

                        <FormItem>
                            {getFieldDecorator("showtimeEnd", {
                                initialValue: itemParams.showtimeEnd ? moment(itemParams.showtimeEnd, 'HH:mm') : null,
                                rules: [{ required: true, message: '结束时间为必填项' }],
                            })(
                                <TimePicker
                                    format="HH:mm"
                                    onChange={(time, timeString) => this.onChange("showtimeEnd", timeString)}
                                    name="showtimeEnd"
                                    defaultOpenValue={moment(`${new Date().getHours()}:00`, 'HH:mm')}
                                />
                            )}
                        </FormItem>
                    </Row>
                </FormItem>

                <div style={{ border: "1px solid #0000ff29" }}>
                    <FormItem label="影片版本">
                        {getFieldDecorator('selectedVersion', {
                            initialValue: itemParams.selectedVersion,
                            rules: [
                                { required: true, message: '' },
                            ],
                        })(<CheckboxAll {...propsVersionCheckboxAll} />)}
                    </FormItem>
                    <FormItem label="影厅类型" style={{ borderBottom: "1px solid #0000ff29" }}>
                        {getFieldDecorator('selectedHallType', {
                            initialValue: itemParams.selectedHallType,
                            rules: [
                                { required: true, message: '' },
                            ],
                        })(<CheckboxAll {...propsHallTypeCheckboxAll} />)}
                    </FormItem>

                    <Table
                        className={styles.itemCombinationTable}
                        rowKey="code"
                        columns={this.renderColumns()}
                        scroll={{ x: 420 * itemParams.selectedVersion.length + 550 }}
                        tableLayout="fixed"
                        dataSource={itemParams.priceTable}
                        pagination={false}
                        bordered={true}
                    />
                </div>

            </Fragment>
        );
    }
}


RowItemSetPrice.js:

import React, { PureComponent, Fragment } from 'react';
import PropTypes from 'prop-types';
import { Select, InputNumber } from 'antd';
import styles from '../index.less';

const { Option } = Select;

class RowItemSetPrice extends PureComponent {
    constructor(props) {
        super(props);
        const { } = props;
        this.state = {

        };
    }

    onChange = (type, value) => {
        const {
            dispatch,
            dispatchType,
            renderIndex,
            itemId,
            priceTable,
            dataIndex, // ItemCombination用
        } = this.props;
        if (dataIndex) {
            dispatch({
                type: dispatchType,
                payload: {
                    priceTable: priceTable.map((item, index) =>
                        index == renderIndex ? {
                            ...item,
                            [dataIndex]: {
                                ...item[dataIndex],
                                [type]: value
                            }
                        } : item
                    ),
                    id: itemId
                },
            });
        } else {
            dispatch({
                type: dispatchType,
                payload: {
                    priceTable: priceTable.map((item, index) =>
                        index == renderIndex ? { ...item, [type]: value } : item
                    ),
                    id: itemId
                },
            });
        }

    }

    render() {
        const {
            renderRow
        } = this.props;
        // console.log(renderRow);
        return (
            <div style={{ textAlign: "center", minWidth: 400 }}>
                <Select
                    showSearch
                    optionFilterProp="children"
                    onChange={(value) => this.onChange("type", value)}
                    value={renderRow.type || "1"}
                    style={{ width: 120, marginRight: 20 }}
                >
                    <Option value={"1"}>指定价格</Option>
                    <Option value={"2"}>基准价</Option>
                    <Option value={"3"}>最低发行价</Option>
                </Select>
                <Select
                    showSearch
                    optionFilterProp="children"
                    onChange={(value) => this.onChange("discountType", value)}
                    value={renderRow.discountType || "3"}
                    style={{ width: 100, marginRight: 20, visibility: renderRow.type == "1" ? "hidden" : "visible" }}
                >
                    <Option value={"3"}> 不变 </Option>
                    <Option value={"2"}> 立减 </Option>
                    <Option value={"1"}> 打折 </Option>
                    <Option value={"4"}> 增加 </Option>
                </Select>
                <span style={{ visibility: ((renderRow.type == "2" || renderRow.type == "3") && renderRow.discountType == "3") ? "hidden" : "visible" }}>
                    <InputNumber
                        min={0.01}
                        value={renderRow.value}
                        onChange={value => this.onChange("value", value)}
                    />
                    <span>{renderRow.discountType == "1" ? ' 折' : ' 元'}</span>
                </span>

            </div>
        );
    }
}

RowItemSetPrice.propTypes = {
    renderRow: PropTypes.object,
    renderIndex: PropTypes.number, // 行号,0、1
    itemId: PropTypes.number,
    priceTable: PropTypes.array,
    dispatch: PropTypes.func,
    dispatchType: PropTypes.string,
    disabled: PropTypes.bool,
    dataIndex: PropTypes.string, // ItemCombination用,"2D"、"3D"
};

export default RowItemSetPrice;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值