一、需求
动态矩阵定价,是动态行、动态列组成的表单,每行的影厅类型,对不同影片版本进行价格设置,用户可选择给哪些厅哪些影片版本设置价格。
二、数据结构
三、组件开发
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;