完成批量设置价格界面

perf/export-docx
Jimmy Liow 1 year ago
parent f68370fa72
commit cae1a8774a

@ -1213,11 +1213,11 @@ function Detail() {
</Row> </Row>
<Modal <Modal
title="批量添加价格" title='批量设置价格'
visible={batchImportPriceVisible} open={batchImportPriceVisible}
onOk={handleBatchImportOK} onOk={handleBatchImportOK}
onCancel={() => setBatchImportPriceVisible(false)} onCancel={() => setBatchImportPriceVisible(false)}
width="80%" width={620}
> >
<BatchImportPrice onBatchImportData={handleBatchImportData} /> <BatchImportPrice onBatchImportData={handleBatchImportData} />
</Modal> </Modal>

@ -1,272 +1,15 @@
import { useEffect, useState } from 'react'; import { useState } from 'react';
import { Button, Card, Checkbox, Col, DatePicker, Typography, Form, Input, Row, Select, Space, Tag, Table, InputNumber } from 'antd'; import { Button, Card, Checkbox, Col, Flex, DatePicker, Typography, Form, Input, Row, Select, Space } from 'antd';
import dayjs from "dayjs";
import { CloseOutlined } from '@ant-design/icons'; import { CloseOutlined } from '@ant-design/icons';
import { useDatePresets } from '@/hooks/useDatePresets'; import { useDatePresets } from '@/hooks/useDatePresets';
const { Option } = Select; const { Option } = Select;
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
const BatchImportPrice = ({ onBatchImportData }) => { const BatchImportPrice = ({ onBatchImportData }) => {
const [form] = Form.useForm(); const [priceForm] = Form.useForm();
const [peopleForm] = Form.useForm();
const [tags, setTags] = useState([]);
const [minPeople, setMinPeople] = useState('');
const [maxPeople, setMaxPeople] = useState('');
const [checkedDays, setCheckedDays] = useState([]);
const [tableData, setTableData] = useState([]);
const [sendData, setSendData] = useState(null);
const presets = useDatePresets(); const presets = useDatePresets();
useEffect(() => {
peopleForm.setFieldValue({
"items": [
{
"weekend": [
"5",
"6",
"7"
],
"peopleList": [
{
"peoplePrice": "22",
"numberStart": "1",
"numberEnd": "2",
"audultPrice": "23",
"childrenPrice": "44"
},
{
"numberStart": "3",
"numberEnd": "5",
"audultPrice": "24",
"childrenPrice": "12"
}
]
}
]
})
})
const handleTagClose = (removedTag) => {
setTags(tags.filter(tag => tag !== removedTag));
};
const handleInputConfirm = () => {
if (minPeople && maxPeople) {
const tag = `${minPeople}-${maxPeople}`;
if (tags.indexOf(tag) === -1) {
setTags([...tags, tag]);
}
}
setMinPeople('');
setMaxPeople('');
};
const handleCheckboxChange = (checkedValues) => {
setCheckedDays(checkedValues);
};
const generateTableData = () => {
const values = form.getFieldsValue();
const weekdays = checkedDays.join(',');
let tempSendData = [];
console.log("values",values)
// items
values.items.forEach((item, index) => {
// validPeriods
let tempValidPeriods = []
item.validPeriods?.forEach((period) => {
console.log("period",period)
const validPeriod = period.validPeriod.map(date => date.format('YYYY-MM-DD')).join('~');
tempValidPeriods.push(validPeriod)
// tempSendData tag
});
const priceType = `批量设置价格 ${index + 1} ${item.currency}/${item.type}`
let tempData = []
const unit_name = item.type
const currency = item.currency
tags.forEach((tag) => {
tempValidPeriods.forEach(validPeriod => {
const group_size_min = tag.split('-')[0]
const group_size_max = tag.split('-')[1]
let unit_id = null
const use_dates_start = validPeriod.split('~')[0]
const use_dates_end = validPeriod.split('~')[1]
if (unit_name === "每人") {
unit_id = 0
} else {
unit_id = 1
}
tempData.push({ group_size_min, group_size_max, validPeriod, unit_id, unit_name, use_dates_start, use_dates_end, currency, weekdays, tag, priceType })
});
})
console.log("tempData", tempData)
tempSendData.push(...tempData)
});
//
setSendData([...tempSendData]); // 使 setSendData
const data = [];
values.items.forEach((item, index) => {
item.validPeriods?.forEach((period, idx) => {
const row = {
key: `${index}-${idx}`,
priceType: `批量设置价格 ${index + 1} ${item.currency}/${item.type}`,
validPeriod: period.validPeriod.map(date => date.format('YYYY-MM-DD')).join('~'),
currency: item.currency,
type: item.type,
};
tags.forEach((tag, tagIndex) => {
row[`adultPrice${tagIndex + 1}`] = 0; // Initialize with 0
row[`childrenPrice${tagIndex + 1}`] = 0; // Initialize with 0
});
data.push(row);
});
});
// setSendData([...tempSendData,data]);
setTableData(data);
// onBatchImportData(data); //
};
const handleTableChange = (age_type, value, tag, priceType) => {
if (age_type === 'adult_cost') {
console.log("sendData", sendData)
const updatedSendData = sendData.map((item) => {
console.log("item.priceType === priceType", item.priceType === priceType)
console.log("item.priceType", item.priceType)
console.log("priceType", priceType)
if (item.priceType === priceType && item.tag === tag) {
return {
...item,
adult_cost: value, // adult_cost
};
}
return item; //
});
// sendData
console.log("updatedSendData", updatedSendData)
onBatchImportData(updatedSendData);
setSendData(updatedSendData);
} else {
const updatedSendData = sendData.map((item) => {
if (item.priceType === priceType && item.tag === tag) {
return {
...item,
child_cost: value, // child_cost
};
}
return item; //
});
// sendData
onBatchImportData(updatedSendData);
setSendData(updatedSendData);
}
};
const generatePeopleColumns = () => {
const columns = [];
tags.forEach((tag, index) => {
columns.push({
title: tag,
children: [
{
title: '成人价',
dataIndex: `adultPrice${index + 1}`,
key: `adultPrice${index + 1}`,
render: (text, record, rowIndex) => {
const sameTagRecords = tableData.filter(item => item.priceType === record.priceType);
const firstTagIndex = tableData.findIndex(item => item.priceType === record.priceType && item.validPeriod === sameTagRecords[0].validPeriod);
if (rowIndex === firstTagIndex) {
return {
children: (
<InputNumber
formatter={value => `${value}`}
parser={value => value.replace(/[^\d]/g, '')}
onChange={(value) => handleTableChange('adult_cost', value, tag, record.priceType)}
/>
),
props: {
rowSpan: sameTagRecords.length,
},
};
} else {
return {
props: {
rowSpan: 0,
},
};
}
},
},
{
title: '儿童价',
dataIndex: `childrenPrice${index + 1}`,
key: `childrenPrice${index + 1}`,
render: (text, record, rowIndex) => {
const sameTagRecords = tableData.filter(item => item.priceType === record.priceType);
const firstTagIndex = tableData.findIndex(item => item.priceType === record.priceType && item.validPeriod === sameTagRecords[0].validPeriod);
if (rowIndex === firstTagIndex) {
return {
children: (
<InputNumber
formatter={value => `${value}`}
parser={value => value.replace(/[^\d]/g, '')}
onChange={(value) => handleTableChange('child_cost', value, tag, record.priceType)}
/>
),
props: {
rowSpan: sameTagRecords.length,
},
};
} else {
return {
props: {
rowSpan: 0,
},
};
}
},
}
]
});
});
return columns;
};
const columns = [
{
title: ' ',
dataIndex: 'priceType',
key: 'priceType',
width: "10%",
render: (text, record, index) => {
const obj = {
children: text,
props: {},
};
if (index > 0 && text === tableData[index - 1].priceType) {
obj.props.rowSpan = 0;
} else {
obj.props.rowSpan = tableData.filter(item => item.priceType === text).length;
}
return obj;
},
},
{
title: '有效期\\人等',
dataIndex: 'validPeriod',
key: 'validPeriod',
width: "15%"
},
...generatePeopleColumns(),
];
const PriceInput = (props) => { const PriceInput = (props) => {
const { id, value = {}, onChange } = props const { id, value = {}, onChange } = props
const [numberStart, setNumberStart] = useState(0) const [numberStart, setNumberStart] = useState(0)
@ -372,22 +115,65 @@ const BatchImportPrice = ({ onBatchImportData }) => {
) )
} }
return ( const priceInitialValues = {
<Row gutter={16}>
<Col span={10}>
<Form
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
form={peopleForm}
name="peopleForm"
autoComplete="off"
initialValues={{
"items": [ "items": [
//
{
"useDate": [
dayjs().add(1, 'year').startOf("y"), dayjs().add(1, 'year').endOf("y")
],
"unitName": "每人",
"currency": "CNY",
"weekend": [
"5",
"6"
],
"prieceList": [
{
"priceInput": {
"numberStart": 1,
"numberEnd": 2,
"audultPrice": 0,
"childrenPrice": 0
}
},
{
"priceInput": {
"numberStart": 3,
"numberEnd": 4,
"audultPrice": 0,
"childrenPrice": 0
}
},
{
"priceInput": {
"numberStart": 5,
"numberEnd": 6,
"audultPrice": 0,
"childrenPrice": 0
}
},
{ {
"priceInput": {
"numberStart": 7,
"numberEnd": 9,
"audultPrice": 0,
"childrenPrice": 0
}
}
]
},
//
{
"useDate": [
dayjs().add(1, 'year').subtract(2, "M").startOf("M"), dayjs().add(1, 'year').endOf("M")
],
"unitName": "每人",
"currency": "CNY",
"weekend": [ "weekend": [
"5", "5",
"6", "6"
"7"
], ],
"prieceList": [ "prieceList": [
@ -426,83 +212,32 @@ const BatchImportPrice = ({ onBatchImportData }) => {
] ]
} }
] ]
}} }
>
<Form.List name="items" >
{(fields, { add, remove }) => (
<div style={{ display: 'flex', rowGap: 16, flexDirection: 'column' }}>
{fields.map((field, index) => (
<Card
size="small"
title={`周末、人等`}
key={field.key}
>
<Form.Item label="周末" name={[field.name, 'weekend']}>
<Checkbox.Group
options={['5', '6', '7']}
onChange={handleCheckboxChange}
/>
</Form.Item>
<Form.Item label="价格">
<Form.List name={[field.name, 'prieceList']}>
{(priceFields, priceOpt) => (
<>
{priceFields.map((priceField) => (
<Space key={priceField.key}>
<Form.Item noStyle name={[priceField.name, 'priceInput']}>
<PriceInput />
</Form.Item>
<CloseOutlined onClick={() => priceOpt.remove(priceField.name)} />
</Space>
))}
<Button type="dashed" onClick={() => priceOpt.add()} block>
+ 新增人等
</Button>
</>
)}
</Form.List>
</Form.Item>
</Card>
))}
</div>
)}
</Form.List>
<Form.Item noStyle shouldUpdate>
{() => (
<Typography>
<pre>{JSON.stringify(peopleForm.getFieldsValue(), null, 2)}</pre>
</Typography>
)}
</Form.Item>
</Form>
</Col>
<Col span={14}> return (
<Row gutter={16} justify="center">
<Col span={24}>
<Form <Form
labelCol={{ span: 6 }} labelCol={{ span: 3 }}
wrapperCol={{ span: 18 }} wrapperCol={{ span: 20 }}
form={form} form={priceForm}
name="dynamic_form_complex" name="priceForm"
autoComplete="off" autoComplete="off"
initialValues={{ items: [{}] }} initialValues={priceInitialValues}
> >
<Form.List name="items"> <Form.List name="items">
{(fields, { add, remove }) => ( {(fields, { add, remove }) => (
<div style={{ display: 'flex', rowGap: 16, flexDirection: 'column' }}> <Flex gap="middle" vertical>
{fields.map((field, index) => ( {fields.map((field, index) => (
<Card <Card
size="small" size="small"
title={`批量设置价格 ${index + 1}`} title={index==0?'旺季':index==1?'淡季':'其他'}
key={field.key} key={field.key}
extra={<CloseOutlined onClick={() => remove(field.name)} />} extra={index==0?null:<CloseOutlined onClick={() => {
remove(field.name)
}} />}
> >
<Form.Item label="类型" name={[field.name, 'type']}> <Form.Item label="类型" name={[field.name, 'unitName']}>
<Select placeholder="选择类型"> <Select placeholder="选择类型">
<Option value="每人">每人</Option> <Option value="每人">每人</Option>
<Option value="每团">每团</Option> <Option value="每团">每团</Option>
@ -515,23 +250,30 @@ const BatchImportPrice = ({ onBatchImportData }) => {
<Option value="USD">USD</Option> <Option value="USD">USD</Option>
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item label="有效期" name={[field.name, 'useDate']}>
<Form.Item label="有效期"> <RangePicker style={{width: '100%'}} allowClear={true} inputReadOnly={true} presets={presets} placeholder={['From', 'Thru']} />
<Form.List name={[field.name, 'validPeriods']}> </Form.Item>
{(periodFields, periodOpt) => ( <Form.Item label="周末" name={[field.name, 'weekend']}>
<div style={{ display: 'flex', flexDirection: 'column', rowGap: 16 }}> <Checkbox.Group
{periodFields.map((periodField, idx) => ( options={['5', '6', '7']}
<Space key={periodField.key}> />
<Form.Item noStyle name={[periodField.name, 'validPeriod']}>
<RangePicker allowClear={true} inputReadOnly={true} presets={presets} placeholder={['From', 'Thru']}/>
</Form.Item> </Form.Item>
<CloseOutlined onClick={() => periodOpt.remove(periodField.name)} /> <Form.Item label="人等">
<Form.List name={[field.name, 'prieceList']}>
{(prieceFieldList, priceOptList) => (
<Flex gap="middle" vertical>
{prieceFieldList.map((priceField) => (
<Space key={priceField.key}>
<Form.Item noStyle name={[priceField.name, 'priceInput']}>
<PriceInput />
</Form.Item>
<CloseOutlined onClick={() => priceOptList.remove(priceField.name)} />
</Space> </Space>
))} ))}
<Button type="dashed" onClick={() => periodOpt.add()} block> <Button type="dashed" onClick={() => priceOptList.add()} block>
+ 新增有效期 + 新增人等
</Button> </Button>
</div> </Flex>
)} )}
</Form.List> </Form.List>
</Form.Item> </Form.Item>
@ -540,32 +282,17 @@ const BatchImportPrice = ({ onBatchImportData }) => {
<Button type="dashed" onClick={() => add()} block> <Button type="dashed" onClick={() => add()} block>
+ 新增价格设置 + 新增价格设置
</Button> </Button>
</div> </Flex>
)} )}
</Form.List> </Form.List>
<Form.Item noStyle shouldUpdate> <Form.Item noStyle shouldUpdate>
{() => ( {() => (
<Typography> <Typography className='hidden'>
<pre>{JSON.stringify(form.getFieldsValue(), null, 2)}</pre> <pre>{JSON.stringify(priceForm.getFieldsValue(), null, 2)}</pre>
</Typography> </Typography>
)} )}
</Form.Item> </Form.Item>
</Form> </Form>
<Button type="primary" onClick={generateTableData} style={{ marginTop: 20 }}>
生成表格
</Button>
{tableData.length > 0 && (
<div style={{ overflowX: 'auto' }}>
<Table
style={{ marginTop: 20 }}
columns={columns}
dataSource={tableData}
pagination={false}
/>
</div>
)}
</Col> </Col>
</Row> </Row>
); );

Loading…
Cancel
Save