增加批量添加报价界面

feature/price_manager
黄文强@HWQ-PC 1 year ago
parent e3727db78f
commit 11b5a80986

@ -0,0 +1,243 @@
import React, { useState } from 'react';
import { Table, Input, Button, DatePicker, Row, Col, Tag, Select } from 'antd';
const { RangePicker } = DatePicker;
const { Option } = Select;
const BatchImportPrice = () => {
const [startDate, setStartDate] = useState(null);
const [endDate, setEndDate] = useState(null);
const [startPeople, setStartPeople] = useState(1);
const [endPeople, setEndPeople] = useState(5);
const [dateRanges, setDateRanges] = useState([]);
const [peopleRanges, setPeopleRanges] = useState([]);
const [tableData, setTableData] = useState([]);
const [currency, setCurrency] = useState('RMB'); // RMB
const [type, setType] = useState('每人'); //
const handleGenerateTable = () => {
if (dateRanges.length === 0 || peopleRanges.length === 0) return;
const newData = dateRanges.flatMap(dateRange => {
const { startDate, endDate } = dateRange;
const dates = generateDateRange(startDate, endDate);
const row = { dateRange: `${startDate.format('YYYY-MM-DD')} ~ ${endDate.format('YYYY-MM-DD')}` };
peopleRanges.forEach(peopleRangeString => {
const [start, end] = peopleRangeString.split('-').map(Number);
generatePeopleRange(start, end).forEach(person => {
row[`${person}_adultPrice`] = '';
row[`${person}_childPrice`] = '';
});
});
dates.forEach(date => {
row[date] = '';
});
return row;
});
setTableData(newData);
};
const generateDateRange = (start, end) => {
const dates = [];
let currentDate = start.clone();
while (currentDate <= end) {
dates.push(currentDate.format('YYYY-MM-DD'));
currentDate = currentDate.add(1, 'day');
}
return dates;
};
const generatePeopleRange = (start, end) => {
const range = [];
for (let i = start; i <= end; i++) {
range.push(`人等${i}`);
}
return range;
};
const handleCellChange = (value, dateRange, peopleRange, type) => {
const newData = [...tableData];
const rowIndex = newData.findIndex(row => row.dateRange === dateRange);
newData[rowIndex][`${peopleRange}_${type}`] = value;
setTableData(newData);
};
const handleAddDateRange = () => {
if (startDate && endDate) {
const newDateRange = { startDate, endDate };
//
const isDateRangeExist = dateRanges.some(range => (
range.startDate.isSame(startDate, 'day') && range.endDate.isSame(endDate, 'day')
));
if (!isDateRangeExist) {
setDateRanges([...dateRanges, newDateRange]);
}
}
};
const handleAddPeopleRange = () => {
if (startPeople <= endPeople) {
const newPeopleRange = `${startPeople}-${endPeople}`;
//
const isPeopleRangeExist = peopleRanges.includes(newPeopleRange);
if (!isPeopleRangeExist) {
setPeopleRanges([...peopleRanges, newPeopleRange]);
}
}
};
const handleRemoveTag = (index, type) => {
if (type === 'date') {
setDateRanges(dateRanges.filter((_, i) => i !== index));
} else {
const removedPeopleRange = peopleRanges[index];
setPeopleRanges(peopleRanges.filter(range => range !== removedPeopleRange));
}
setTableData([]);
};
const [adultPrice, setAdultPrice] = useState('');
const [childPrice, setChildPrice] = useState('');
const handleAdultPriceChange = (value, dateRange) => {
const newData = [...tableData];
const rowIndex = newData.findIndex(row => row.dateRange === dateRange);
newData[rowIndex]['成人价'] = value;
setTableData(newData);
};
const handleChildPriceChange = (value, dateRange) => {
const newData = [...tableData];
const rowIndex = newData.findIndex(row => row.dateRange === dateRange);
newData[rowIndex]['儿童价'] = value;
setTableData(newData);
};
const columns = [
{
title: '日期\\人等',
dataIndex: 'dateRange',
key: 'dateRange',
},
...peopleRanges.flatMap(peopleRange => ([
{
title: peopleRange,
dataIndex: `${peopleRange}_price`,
key: `${peopleRange}_price`,
render: (text, record) => (
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Input
value={record[`${peopleRange}_adultPrice`]}
onChange={(e) => handleCellChange(e.target.value, record.dateRange, peopleRange, 'adultPrice')}
placeholder="成人价"
style={{ width: '45%' }}
suffix={`${currency}/${type}`}
/>
<Input
value={record[`${peopleRange}_childPrice`]}
onChange={(e) => handleCellChange(e.target.value, record.dateRange, peopleRange, 'childPrice')}
placeholder="儿童价"
style={{ width: '45%' }}
suffix={`${currency}/${type}`}
/>
</div>
),
}
])),
];
return (
<>
<Row>
<Col span={4}>
<Select value={currency} onChange={value => setCurrency(value)} style={{ width: '100%', marginTop: 10 }}>
<Option value="RMB">RMB</Option>
<Option value="MY">MY</Option>
</Select>
</Col>
<Col span={4}>
<Select value={type} onChange={value => setType(value)} style={{ width: '100%', marginTop: 10 }}>
<Option value="每人">每人</Option>
<Option value="美团">美团</Option>
</Select>
</Col>
</Row>
<Row gutter={16}>
<Col span={8}>
<RangePicker
onChange={(dates) => {
if (dates && dates.length === 2) {
setStartDate(dates[0]);
setEndDate(dates[1]);
} else {
setStartDate(null);
setEndDate(null);
}
}}
/>
</Col>
<Button onClick={handleAddDateRange} type="primary">记录有效期</Button>
</Row>
<Row gutter={16}>
<Col span={8}>
<Input.Group compact style={{ marginTop: 10 }}>
<Input
style={{ width: 100, textAlign: 'center' }}
placeholder="Start"
value={startPeople}
onChange={(e) => setStartPeople(parseInt(e.target.value, 10))}
/>
<Input
style={{ width: 30, borderLeft: 0, pointerEvents: 'none', backgroundColor: '#fff' }}
placeholder="~"
disabled
/>
<Input
style={{ width: 100, textAlign: 'center', borderLeft: 0 }}
placeholder="End"
value={endPeople}
onChange={(e) => setEndPeople(parseInt(e.target.value, 10))}
/>
</Input.Group>
</Col>
<Button onClick={handleAddPeopleRange} type="primary" style={{ marginTop: 10 }}>记录人等</Button>
</Row>
<Button onClick={handleGenerateTable} type="primary" style={{ marginTop: 10 }}>生成表格</Button>
<Row gutter={16} style={{ marginTop: '16px' }}>
<Col span={24}>
{dateRanges.map((dateRange, index) => (
<Tag key={index} closable onClose={() => handleRemoveTag(index, 'date')}>
{`${dateRange.startDate.format('YYYY-MM-DD')} ~ ${dateRange.endDate.format('YYYY-MM-DD')}`}
</Tag>
))}
{peopleRanges.map((peopleRange, index) => (
<Tag key={index} closable onClose={() => handleRemoveTag(index, 'people')}>
{peopleRange}
</Tag>
))}
</Col>
</Row>
<Table
columns={columns}
dataSource={tableData}
bordered
pagination={false}
style={{ marginTop: '16px' }}
/>
</>
);
};
export default BatchImportPrice;

@ -10,6 +10,7 @@ import { groupBy } from '@/utils/commons';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { useHTLanguageSets } from '@/hooks/useHTLanguageSets'; import { useHTLanguageSets } from '@/hooks/useHTLanguageSets';
import { useDefaultLgc } from '@/i18n/LanguageSwitcher'; import { useDefaultLgc } from '@/i18n/LanguageSwitcher';
import BatchImportPrice from '@/components/BatchImportPrice';
function Detail() { function Detail() {
const { t } = useTranslation(); const { t } = useTranslation();
const [form] = Form.useForm(); const [form] = Form.useForm();
@ -19,12 +20,13 @@ function Detail() {
const [selectedTag, setSelectedTag] = useState(null); const [selectedTag, setSelectedTag] = useState(null);
const [saveData, setSaveData] = useState(null); const [saveData, setSaveData] = useState(null);
const [datePickerVisible, setDatePickerVisible] = useState(false); const [datePickerVisible, setDatePickerVisible] = useState(false);
const [batchImportPriceVisible, setBatchImportPriceVisible] = useState(false);
const [currentid, setCurrentid] = useState(null); const [currentid, setCurrentid] = useState(null);
const [languageStatus, setLanguageStatus] = useState(null); const [languageStatus, setLanguageStatus] = useState(null);
const [selectedNodeid, setSelectedNodeid] = useState(null); const [selectedNodeid, setSelectedNodeid] = useState(null);
const [remainderLanguage, setRemainderLanguage] = useState([]) const [remainderLanguage, setRemainderLanguage] = useState([])
const [selectedDateData, setSelectedDateData] = useState({ dateRange: null, selectedDays: [] }); const [selectedDateData, setSelectedDateData] = useState({ dateRange: null, selectedDays: [] });
const [treeData1, setTreeData1] = useState([]); const [treeData, setTreeData] = useState([]);
const productsTypes = useProductsTypes(); const productsTypes = useProductsTypes();
const [productsData, setProductsData] = useState(null); const [productsData, setProductsData] = useState(null);
const [quotation, setQuotation] = useState(null); const [quotation, setQuotation] = useState(null);
@ -99,6 +101,7 @@ function Detail() {
const languageLabel = matchedLanguage.label const languageLabel = matchedLanguage.label
// setTags([languageLabel]) // setTags([languageLabel])
setLanguageLabel(languageLabel) setLanguageLabel(languageLabel)
setSelectedTag(languageLabel)
setRemainderLanguage(HTLanguageSets.filter(item => item.key !== language.toString())) setRemainderLanguage(HTLanguageSets.filter(item => item.key !== language.toString()))
}, []); }, []);
@ -124,8 +127,7 @@ function Detail() {
}; };
const treeData = generateTreeData(productsTypes, groupedProducts); const treeData = generateTreeData(productsTypes, groupedProducts);
console.log("treeData", treeData) setTreeData(treeData);
setTreeData1(treeData);
setProductsData(groupedProducts); setProductsData(groupedProducts);
setDefaultData(treeData); setDefaultData(treeData);
setDataList(flattenTreeData(treeData)); setDataList(flattenTreeData(treeData));
@ -202,17 +204,6 @@ function Detail() {
setAutoExpandParent(false); setAutoExpandParent(false);
}; };
// const productProject = [
// { code: "code", name: t('products:Code') },
// { code: "city_name", name: t('products:City') },
// { code: "remarks", name: t('products:Remarks') },
// { code: "open_hours", name: t('products:tourTime') },
// { code: "recommends_rate", name: t('products:recommendationRate') }
// ];
const isEditing = (record) => record.id === editingid; const isEditing = (record) => record.id === editingid;
const edit = (record) => { const edit = (record) => {
@ -268,6 +259,10 @@ function Detail() {
setQuotation([...quotation, newData]); setQuotation([...quotation, newData]);
}; };
const handleBatchImport = () => {
setBatchImportPriceVisible(true);
}
const handleDateSelect = (id) => { const handleDateSelect = (id) => {
setCurrentid(id); setCurrentid(id);
setDatePickerVisible(true); setDatePickerVisible(true);
@ -309,6 +304,11 @@ function Detail() {
setDatePickerVisible(false); setDatePickerVisible(false);
} }
const handleBatchImportOK = () => {
setBatchImportPriceVisible(false);
}
const EditableCell = ({ editing, dataIndex, title, inputType, record, children, handleDateSelect, ...restProps }) => { const EditableCell = ({ editing, dataIndex, title, inputType, record, children, handleDateSelect, ...restProps }) => {
let inputNode = inputType === 'number' ? <InputNumber /> : <Input />; let inputNode = inputType === 'number' ? <InputNumber /> : <Input />;
if (dataIndex === 'validityPeriod' && editing) { if (dataIndex === 'validityPeriod' && editing) {
@ -473,10 +473,15 @@ function Detail() {
const showModal = () => setIsModalVisible(true); const showModal = () => setIsModalVisible(true);
const handleOk = () => { const handleOk = () => {
if (!selectedTag) return;
if (!remainderLanguage.some(item => item.label === selectedTag)) return;
if (remainderLanguage.includes(selectedTag)) return;
let tempRemainderLanguage = remainderLanguage.filter((item)=>{
return item.label !== selectedTag;
})
setRemainderLanguage(tempRemainderLanguage)
setTags([...tags, selectedTag]) setTags([...tags, selectedTag])
setSelectedTag(null);
console.log("handleOkvalue")
setIsModalVisible(false); setIsModalVisible(false);
} }
@ -508,8 +513,9 @@ function Detail() {
// //
if (selectedNodeid === node.key) return; if (selectedNodeid === node.key) return;
const fatherKey = node.key.split('-')[0]; const fatherKey = node.key.split('-')[0];
console.log("fatherKey", fatherKey)
setSelectedCategory(productProject[fatherKey]) setSelectedCategory(productProject[fatherKey])
console.log("remainderLanguage",remainderLanguage)
let initialQuotationData = null; let initialQuotationData = null;
let infoData = null; let infoData = null;
let lgcDetailsData = null; let lgcDetailsData = null;
@ -558,30 +564,15 @@ function Detail() {
}); });
}; };
const onSave = (values) => { const onSave = (values) => {
const tempData = values; const tempData = values;
tempData['quotation'] = quotation; tempData['quotation'] = quotation;
tempData['extras'] = bindingData; // tempData['extras'] = bindingData;
// tempData['lgc_details'] = languageStatus; // tempData['lgc_details'] = languageStatus;
setSaveData(tempData); setSaveData(tempData);
console.log("保存的数据", tempData) console.log("保存的数据", tempData)
}; };
//Effect
return ( return (
<div> <div>
<Row> <Row>
@ -590,7 +581,7 @@ function Detail() {
<Search style={{ marginBottom: 8 }} placeholder="Search" onChange={onChange} /> <Search style={{ marginBottom: 8 }} placeholder="Search" onChange={onChange} />
<Tree <Tree
onSelect={handleNodeSelect} onSelect={handleNodeSelect}
treeData={treeData1} treeData={treeData}
expandedKeys={expandedKeys} expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent} autoExpandParent={autoExpandParent}
onExpand={onExpand} onExpand={onExpand}
@ -624,7 +615,7 @@ function Detail() {
</Form.Item> </Form.Item>
</Col> </Col>
))} ))}
</Row>duration </Row>
<Card title={ <Card title={
<div> <div>
@ -648,7 +639,8 @@ function Detail() {
placeholder="选择语言" placeholder="选择语言"
optionFilterProp="children" optionFilterProp="children"
onChange={handleTagChange} onChange={handleTagChange}
> value={remainderLanguage.some((item) => item.label === selectedTag) ? selectedTag : undefined}
>
{ {
remainderLanguage.map((value, label) => ( remainderLanguage.map((value, label) => (
@ -689,6 +681,8 @@ function Detail() {
<Button onClick={handleAdd} type="primary" style={{ marginBottom: 16 }}> <Button onClick={handleAdd} type="primary" style={{ marginBottom: 16 }}>
{t('products:addQuotation')} {t('products:addQuotation')}
</Button> </Button>
<Button onClick={handleBatchImport} type="primary" style={{ marginBottom: 16 }}>批量添加</Button>
</Form.Item> </Form.Item>
</Card> </Card>
@ -717,6 +711,20 @@ function Detail() {
<Date onDateChange={handleDateChange} /> <Date onDateChange={handleDateChange} />
</Modal> </Modal>
)} )}
{
batchImportPriceVisible && (
<Modal
title="批量添加价格"
visible={batchImportPriceVisible}
onOk={handleBatchImportOK}
onCancel={() => setBatchImportPriceVisible(false)}
width="80%"
>
<BatchImportPrice/>
</Modal>
)
}
</div> </div>
); );
} }

Loading…
Cancel
Save