|
|
@ -1,104 +1,273 @@
|
|
|
|
import { useState } from 'react'
|
|
|
|
import { useEffect, useState } from 'react'
|
|
|
|
import { Table, Form, Modal, Button, Radio, Input, InputNumber, Checkbox, DatePicker, Space } from 'antd'
|
|
|
|
import { Table, Form, Modal, Button, Radio, Input, Flex, Card, Select, Typography, InputNumber, Checkbox, DatePicker, Space } from 'antd'
|
|
|
|
import { useTranslation } from 'react-i18next'
|
|
|
|
import { useTranslation } from 'react-i18next'
|
|
|
|
import dayjs from 'dayjs'
|
|
|
|
import dayjs from 'dayjs'
|
|
|
|
import BatchImportPrice from './BatchImportPrice'
|
|
|
|
import { CloseOutlined, StarTwoTone, PlusOutlined } from '@ant-design/icons';
|
|
|
|
import { useDatePresets } from '@/hooks/useDatePresets'
|
|
|
|
import { useDatePresets } from '@/hooks/useDatePresets'
|
|
|
|
import useProductsStore from '@/stores/Products/Index'
|
|
|
|
import useProductsStore from '@/stores/Products/Index'
|
|
|
|
|
|
|
|
|
|
|
|
const { RangePicker } = DatePicker
|
|
|
|
const { RangePicker } = DatePicker
|
|
|
|
|
|
|
|
|
|
|
|
const ProductInfoQuotation = ({ editable, ...props }) => {
|
|
|
|
const PriceInput = (props) => {
|
|
|
|
|
|
|
|
const { id, value = {}, onChange } = props
|
|
|
|
const { t } = useTranslation()
|
|
|
|
const [numberStart, setNumberStart] = useState(0)
|
|
|
|
|
|
|
|
const [numberEnd, setNumberEnd] = useState(0)
|
|
|
|
const [isQuotationModalOpen, setQuotationModalOpen] = useState(false)
|
|
|
|
const [audultPrice, setAudultPrice] = useState(0)
|
|
|
|
const [quotationForm] = Form.useForm()
|
|
|
|
const [childrenPrice, setChildrenPrice] = useState(0)
|
|
|
|
|
|
|
|
const triggerChange = (changedValue) => {
|
|
|
|
const datePresets = useDatePresets()
|
|
|
|
onChange?.({
|
|
|
|
|
|
|
|
numberStart,
|
|
|
|
const [editingProduct] = useProductsStore((state) => [state.editingProduct])
|
|
|
|
numberEnd,
|
|
|
|
const [batchImportPriceVisible, setBatchImportPriceVisible] = useState(false)
|
|
|
|
audultPrice,
|
|
|
|
const [quotationTableVisible, setQuotationTableVisible] = useState(false)
|
|
|
|
childrenPrice,
|
|
|
|
const [quotation, setQuotation] = useState([])
|
|
|
|
...value,
|
|
|
|
const [batchImportData, setBatchImportData] = useState([])
|
|
|
|
...changedValue,
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const handleBatchImportData = (data) => {
|
|
|
|
|
|
|
|
setBatchImportData(data)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const onNumberStartChange = (e) => {
|
|
|
|
const handleBatchImportOK = () => {
|
|
|
|
const newNumber = parseInt(e.target.value || '0', 10)
|
|
|
|
const tempBatchImportData = batchImportData.map((item) => {
|
|
|
|
if (Number.isNaN(numberStart)) {
|
|
|
|
const { tag, validPeriod, ...rest } = item
|
|
|
|
return
|
|
|
|
return rest
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!('numberStart' in value)) {
|
|
|
|
|
|
|
|
setNumberStart(newNumber);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
triggerChange({
|
|
|
|
|
|
|
|
numberStart: newNumber,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
const newData = [...quotation, ...tempBatchImportData]
|
|
|
|
}
|
|
|
|
const sortedData = [...newData].sort((a, b) => {
|
|
|
|
const onNumberEndChange = (e) => {
|
|
|
|
if (a.group_size_min !== b.group_size_min) {
|
|
|
|
const newNumber = parseInt(e.target.value || '0', 10)
|
|
|
|
return a.group_size_min - b.group_size_min
|
|
|
|
if (Number.isNaN(numberEnd)) {
|
|
|
|
}
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
return a.group_size_max - b.group_size_max
|
|
|
|
if (!('numberEnd' in value)) {
|
|
|
|
|
|
|
|
setNumberEnd(newNumber)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
triggerChange({
|
|
|
|
|
|
|
|
numberEnd: newNumber,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
const onAudultPriceChange = (e) => {
|
|
|
|
|
|
|
|
const newNumber = parseInt(e.target.value || '0', 10)
|
|
|
|
|
|
|
|
if (Number.isNaN(audultPrice)) {
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!('audultPrice' in value)) {
|
|
|
|
|
|
|
|
setAudultPrice(newNumber)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
triggerChange({
|
|
|
|
|
|
|
|
audultPrice: newNumber,
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const onChildrenPriceChange = (e) => {
|
|
|
|
|
|
|
|
const newNumber = parseInt(e.target.value || '0', 10)
|
|
|
|
|
|
|
|
if (Number.isNaN(childrenPrice)) {
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!('childrenPrice' in value)) {
|
|
|
|
|
|
|
|
setChildrenPrice(newNumber)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
triggerChange({
|
|
|
|
|
|
|
|
childrenPrice: newNumber,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
|
|
<Space.Compact id={id}>
|
|
|
|
|
|
|
|
<Input
|
|
|
|
|
|
|
|
type='text'
|
|
|
|
|
|
|
|
value={value.numberStart || numberStart}
|
|
|
|
|
|
|
|
onChange={onNumberStartChange}
|
|
|
|
|
|
|
|
style={{
|
|
|
|
|
|
|
|
width: '20%',
|
|
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
<Input
|
|
|
|
|
|
|
|
type='text'
|
|
|
|
|
|
|
|
value={value.numberEnd || numberEnd}
|
|
|
|
|
|
|
|
onChange={onNumberEndChange}
|
|
|
|
|
|
|
|
style={{
|
|
|
|
|
|
|
|
width: '40%',
|
|
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
addonBefore='~'
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
<Input
|
|
|
|
|
|
|
|
type='text'
|
|
|
|
|
|
|
|
value={value.audultPrice || audultPrice}
|
|
|
|
|
|
|
|
onChange={onAudultPriceChange}
|
|
|
|
|
|
|
|
style={{
|
|
|
|
|
|
|
|
width: '70%',
|
|
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
addonBefore='成人价'
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
<Input
|
|
|
|
|
|
|
|
type='text'
|
|
|
|
|
|
|
|
value={value.childrenPrice || childrenPrice}
|
|
|
|
|
|
|
|
onChange={onChildrenPriceChange}
|
|
|
|
|
|
|
|
style={{
|
|
|
|
|
|
|
|
width: '70%',
|
|
|
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
addonBefore='儿童价'
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</Space.Compact>
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const batchSetupInitialValues = {
|
|
|
|
|
|
|
|
'defList': [
|
|
|
|
|
|
|
|
// 旺季
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
'useDate': [
|
|
|
|
|
|
|
|
dayjs().add(1, 'year').startOf('y'), dayjs().add(1, 'year').endOf('y')
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
'unitName': '每人',
|
|
|
|
|
|
|
|
'currency': 'CNY',
|
|
|
|
|
|
|
|
'weekend': [
|
|
|
|
|
|
|
|
'5',
|
|
|
|
|
|
|
|
'6'
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
'priceList': [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
'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': [
|
|
|
|
|
|
|
|
'5',
|
|
|
|
|
|
|
|
'6'
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
'priceList': [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
'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
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
setQuotation(sortedData)
|
|
|
|
const defaultPriceValue = {
|
|
|
|
setBatchImportPriceVisible(false)
|
|
|
|
'priceInput': {
|
|
|
|
|
|
|
|
'numberStart': 1,
|
|
|
|
|
|
|
|
'numberEnd': 2,
|
|
|
|
|
|
|
|
'audultPrice': 0,
|
|
|
|
|
|
|
|
'childrenPrice': 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const quotationTableVisibleOK = () => {
|
|
|
|
}
|
|
|
|
const tempQuotation = [...quotation]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const sortedData = [...tempQuotation].sort((a, b) => {
|
|
|
|
const defaultDefinitionValue = {
|
|
|
|
const aValidPeriod = dayjs(a.use_dates_end).diff(dayjs(a.use_dates_start))
|
|
|
|
'useDate': [
|
|
|
|
const bValidPeriod = dayjs(b.use_dates_end).diff(dayjs(b.use_dates_start))
|
|
|
|
dayjs().add(1, 'year').subtract(2, 'M').startOf('M'), dayjs().add(1, 'year').endOf('M')
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
'unitName': '每人',
|
|
|
|
|
|
|
|
'currency': 'CNY',
|
|
|
|
|
|
|
|
'weekend': [
|
|
|
|
|
|
|
|
'5',
|
|
|
|
|
|
|
|
'6'
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
'priceList': [
|
|
|
|
|
|
|
|
defaultPriceValue
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (aValidPeriod !== bValidPeriod) {
|
|
|
|
const ProductInfoQuotation = ({ editable, ...props }) => {
|
|
|
|
return aValidPeriod - bValidPeriod
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const aGroupSize = a.group_size_max - a.group_size_min
|
|
|
|
|
|
|
|
const bGroupSize = b.group_size_max - b.group_size_min
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return aGroupSize - bGroupSize
|
|
|
|
const { t } = useTranslation()
|
|
|
|
})
|
|
|
|
|
|
|
|
setQuotation(sortedData)
|
|
|
|
|
|
|
|
setQuotationTableVisible(false)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const quotationTableVisibleCancel = () => {
|
|
|
|
|
|
|
|
setQuotationTableVisible(false)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleDelete = (index) => {
|
|
|
|
const [isQuotationModalOpen, setQuotationModalOpen] = useState(false)
|
|
|
|
const newData = [...quotation]
|
|
|
|
const [isBatchSetupModalOpen, setBatchSetupModalOpen] = useState(false)
|
|
|
|
newData.splice(index, 1)
|
|
|
|
const [quotationForm] = Form.useForm()
|
|
|
|
const sortedData = [...newData].sort((a, b) => {
|
|
|
|
const [batchSetupForm] = Form.useForm()
|
|
|
|
const aValidPeriod = dayjs(a.use_dates_end).diff(dayjs(a.use_dates_start))
|
|
|
|
|
|
|
|
const bValidPeriod = dayjs(b.use_dates_end).diff(dayjs(b.use_dates_start))
|
|
|
|
|
|
|
|
if (aValidPeriod !== bValidPeriod) {
|
|
|
|
|
|
|
|
return aValidPeriod - bValidPeriod
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const aGroupSize = a.group_size_max - a.group_size_min
|
|
|
|
|
|
|
|
const bGroupSize = b.group_size_max - b.group_size_min
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return aGroupSize - bGroupSize
|
|
|
|
const datePresets = useDatePresets()
|
|
|
|
})
|
|
|
|
|
|
|
|
setQuotation(sortedData)
|
|
|
|
const [newEmptyQuotation, appendQuotationList, quotationList] =
|
|
|
|
}
|
|
|
|
useProductsStore((state) => [state.newEmptyQuotation, state.appendQuotationList, state.quotationList])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
|
|
console.info('quotationList: ', quotationList)
|
|
|
|
|
|
|
|
}, [quotationList])
|
|
|
|
|
|
|
|
|
|
|
|
const onQuotationSeleted = async (quotation) => {
|
|
|
|
const onQuotationSeleted = async (quotation) => {
|
|
|
|
// 转换为 RangePicker 赋值格式
|
|
|
|
// 把 start, end 转换为 RangePicker 数组格式
|
|
|
|
quotation.use_dates = [dayjs(quotation.use_dates_start), dayjs(quotation.use_dates_end)]
|
|
|
|
quotation.use_dates = [dayjs(quotation.use_dates_start), dayjs(quotation.use_dates_end)]
|
|
|
|
quotationForm.setFieldsValue(quotation)
|
|
|
|
quotationForm.setFieldsValue(quotation)
|
|
|
|
setQuotationModalOpen(true)
|
|
|
|
setQuotationModalOpen(true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const onNewQuotation = () => {
|
|
|
|
const onNewQuotation = () => {
|
|
|
|
// const emptyQuotation = newEmptyQuotation()
|
|
|
|
const emptyQuotation = newEmptyQuotation()
|
|
|
|
// quotationForm.setFieldsValue(emptyQuotation)
|
|
|
|
quotationForm.setFieldsValue(emptyQuotation)
|
|
|
|
// setQuotationModalOpen(true)
|
|
|
|
setQuotationModalOpen(true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const onQuotationFinish = (values) => {
|
|
|
|
const onQuotationFinish = (values) => {
|
|
|
|
console.info(values)
|
|
|
|
console.info(values)
|
|
|
|
|
|
|
|
setQuotationModalOpen(false)
|
|
|
|
// saveOrUpdateQuotation(values)
|
|
|
|
// saveOrUpdateQuotation(values)
|
|
|
|
// .then(() => {
|
|
|
|
// .then(() => {
|
|
|
|
// setQuotationModalOpen(false)
|
|
|
|
// setQuotationModalOpen(false)
|
|
|
@ -118,6 +287,35 @@ const ProductInfoQuotation = ({ editable, ...props }) => {
|
|
|
|
// form.resetFields()
|
|
|
|
// form.resetFields()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const onBatchSetupFinish = () => {
|
|
|
|
|
|
|
|
// console.info(batchSetupForm.getFieldsValue())
|
|
|
|
|
|
|
|
let previewList = []
|
|
|
|
|
|
|
|
const defList = batchSetupForm.getFieldsValue().defList
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
defList.forEach(definition => {
|
|
|
|
|
|
|
|
const previewPrice = definition?.priceList.map(price => {
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
id: 0,
|
|
|
|
|
|
|
|
adult_cost: price.priceInput.audultPrice,
|
|
|
|
|
|
|
|
child_cost: price.priceInput.childrenPrice,
|
|
|
|
|
|
|
|
group_size_min: price.priceInput.numberStart,
|
|
|
|
|
|
|
|
group_size_max: price.priceInput.numberEnd,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
currency: definition.currency,
|
|
|
|
|
|
|
|
unit: definition.unitName,
|
|
|
|
|
|
|
|
// 保持和 API 返回格式一致,日期要转换为字符串
|
|
|
|
|
|
|
|
use_dates_start: definition.useDate[0].format('YYYY-MM-DD'),
|
|
|
|
|
|
|
|
use_dates_end: definition.useDate[1].format('YYYY-MM-DD'),
|
|
|
|
|
|
|
|
weekdays: definition.weekend.join(','),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
previewList.push(...previewPrice)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
appendQuotationList(previewList)
|
|
|
|
|
|
|
|
setBatchSetupModalOpen(false)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const quotationColumns = [
|
|
|
|
const quotationColumns = [
|
|
|
|
{ title: t('products:adultPrice'), dataIndex: 'adult_cost', width: '4rem' },
|
|
|
|
{ title: t('products:adultPrice'), dataIndex: 'adult_cost', width: '4rem' },
|
|
|
|
{ title: t('products:childrenPrice'), dataIndex: 'child_cost', width: '4rem' },
|
|
|
|
{ title: t('products:childrenPrice'), dataIndex: 'child_cost', width: '4rem' },
|
|
|
@ -162,28 +360,110 @@ const ProductInfoQuotation = ({ editable, ...props }) => {
|
|
|
|
<>
|
|
|
|
<>
|
|
|
|
<h2>{t('products:EditComponents.Quotation')}</h2>
|
|
|
|
<h2>{t('products:EditComponents.Quotation')}</h2>
|
|
|
|
<Table
|
|
|
|
<Table
|
|
|
|
rowKey={'id'}
|
|
|
|
// rowKey={'id'}
|
|
|
|
bordered
|
|
|
|
bordered
|
|
|
|
dataSource={editingProduct.quotation}
|
|
|
|
dataSource={quotationList}
|
|
|
|
columns={quotationColumns}
|
|
|
|
columns={quotationColumns}
|
|
|
|
pagination={false}
|
|
|
|
pagination={false}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// editable &&
|
|
|
|
// editable &&
|
|
|
|
<Button onClick={() => setQuotationModalOpen(true)} type='primary' ghost style={{ marginTop: 16 }}>
|
|
|
|
<Button onClick={() => onNewQuotation()} type='primary' ghost style={{ marginTop: 16 }}>
|
|
|
|
{t('products:addQuotation')}
|
|
|
|
{t('products:addQuotation')}
|
|
|
|
</Button>
|
|
|
|
</Button>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// editable &&
|
|
|
|
// editable &&
|
|
|
|
<Button onClick={() => setBatchImportPriceVisible(true)} type='primary' ghost style={{ marginTop: 16, marginLeft: 16 }}>
|
|
|
|
<Button onClick={() => setBatchSetupModalOpen(true)} type='primary' ghost style={{ marginTop: 16, marginLeft: 16 }}>
|
|
|
|
批量添加
|
|
|
|
批量设置
|
|
|
|
</Button>
|
|
|
|
</Button>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
<Modal title='批量设置价格' open={batchImportPriceVisible} onOk={handleBatchImportOK} onCancel={() => setBatchImportPriceVisible(false)} width={'90%'}>
|
|
|
|
<Modal
|
|
|
|
<BatchImportPrice onBatchImportData={handleBatchImportData} />
|
|
|
|
centered
|
|
|
|
|
|
|
|
title='批量设置价格'
|
|
|
|
|
|
|
|
width={'640px'}
|
|
|
|
|
|
|
|
open={isBatchSetupModalOpen}
|
|
|
|
|
|
|
|
onOk={() => onBatchSetupFinish()}
|
|
|
|
|
|
|
|
onCancel={() => setBatchSetupModalOpen(false)}
|
|
|
|
|
|
|
|
destroyOnClose
|
|
|
|
|
|
|
|
forceRender
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<Form
|
|
|
|
|
|
|
|
labelCol={{ span: 3 }}
|
|
|
|
|
|
|
|
wrapperCol={{ span: 20 }}
|
|
|
|
|
|
|
|
form={batchSetupForm}
|
|
|
|
|
|
|
|
name='batchSetupForm'
|
|
|
|
|
|
|
|
autoComplete='off'
|
|
|
|
|
|
|
|
initialValues={batchSetupInitialValues}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<Form.List name='defList'>
|
|
|
|
|
|
|
|
{(fields, { add, remove }) => (
|
|
|
|
|
|
|
|
<Flex gap='middle' vertical>
|
|
|
|
|
|
|
|
{fields.map((field, index) => (
|
|
|
|
|
|
|
|
<Card
|
|
|
|
|
|
|
|
size='small'
|
|
|
|
|
|
|
|
title={index == 0 ? '旺季' : index == 1 ? '淡季' : '其他'}
|
|
|
|
|
|
|
|
key={field.key}
|
|
|
|
|
|
|
|
extra={index == 0 ? <StarTwoTone twoToneColor='#eb2f96' /> : <CloseOutlined onClick={() => {
|
|
|
|
|
|
|
|
remove(field.name)
|
|
|
|
|
|
|
|
}} />}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
<Form.Item label='币种' name={[field.name, 'currency']}>
|
|
|
|
|
|
|
|
<Select placeholder='选择币种'>
|
|
|
|
|
|
|
|
<Select.Option value='CNY'>CNY</Select.Option>
|
|
|
|
|
|
|
|
<Select.Option value='USD'>USD</Select.Option>
|
|
|
|
|
|
|
|
</Select>
|
|
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
<Form.Item label='类型' name={[field.name, 'unitName']}>
|
|
|
|
|
|
|
|
<Select placeholder='选择类型'>
|
|
|
|
|
|
|
|
<Select.Option value='每人'>每人</Select.Option>
|
|
|
|
|
|
|
|
<Select.Option value='每团'>每团</Select.Option>
|
|
|
|
|
|
|
|
</Select>
|
|
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
<Form.Item label='周末' name={[field.name, 'weekend']}>
|
|
|
|
|
|
|
|
<Checkbox.Group
|
|
|
|
|
|
|
|
options={['5', '6', '7']}
|
|
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
<Form.Item label='有效期' name={[field.name, 'useDate']}>
|
|
|
|
|
|
|
|
<RangePicker style={{ width: '100%' }} allowClear={true} inputReadOnly={true} presets={datePresets} placeholder={['From', 'Thru']} />
|
|
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
<Form.Item label='人等'>
|
|
|
|
|
|
|
|
<Form.List name={[field.name, 'priceList']}>
|
|
|
|
|
|
|
|
{(priceFieldList, priceOptList) => (
|
|
|
|
|
|
|
|
<Flex gap='middle' vertical>
|
|
|
|
|
|
|
|
{priceFieldList.map((priceField, index) => (
|
|
|
|
|
|
|
|
<Space key={priceField.key}>
|
|
|
|
|
|
|
|
<Form.Item noStyle name={[priceField.name, 'priceInput']}>
|
|
|
|
|
|
|
|
<PriceInput />
|
|
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
{index == 0 ? <StarTwoTone twoToneColor='#eb2f96' /> : <CloseOutlined onClick={() => priceOptList.remove(priceField.name)} />}
|
|
|
|
|
|
|
|
</Space>
|
|
|
|
|
|
|
|
))}
|
|
|
|
|
|
|
|
<Button type='dashed' icon={<PlusOutlined />} onClick={() => priceOptList.add(defaultPriceValue)} block>
|
|
|
|
|
|
|
|
新增人等
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
</Flex>
|
|
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
</Form.List>
|
|
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
|
|
))}
|
|
|
|
|
|
|
|
<Button type='dashed' icon={<PlusOutlined />} onClick={() => add(defaultDefinitionValue)} block>
|
|
|
|
|
|
|
|
新增设置
|
|
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
</Flex>
|
|
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
</Form.List>
|
|
|
|
|
|
|
|
<Form.Item noStyle shouldUpdate>
|
|
|
|
|
|
|
|
{() => (
|
|
|
|
|
|
|
|
<Typography className='hidden'>
|
|
|
|
|
|
|
|
<pre>{JSON.stringify(batchSetupForm.getFieldsValue(), null, 2)}</pre>
|
|
|
|
|
|
|
|
</Typography>
|
|
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
</Form>
|
|
|
|
</Modal>
|
|
|
|
</Modal>
|
|
|
|
|
|
|
|
|
|
|
|
<Modal
|
|
|
|
<Modal
|
|
|
@ -222,7 +502,7 @@ const ProductInfoQuotation = ({ editable, ...props }) => {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
]}
|
|
|
|
]}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<InputNumber style={{width: '100%'}} />
|
|
|
|
<InputNumber style={{ width: '100%' }} />
|
|
|
|
</Form.Item>
|
|
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
|
|
<Form.Item
|
|
|
|
label={t('products:childrenPrice')}
|
|
|
|
label={t('products:childrenPrice')}
|
|
|
@ -234,7 +514,7 @@ const ProductInfoQuotation = ({ editable, ...props }) => {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
]}
|
|
|
|
]}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<InputNumber style={{width: '100%'}} />
|
|
|
|
<InputNumber style={{ width: '100%' }} />
|
|
|
|
</Form.Item>
|
|
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
|
|
<Form.Item
|
|
|
|
label={t('products:currency')}
|
|
|
|
label={t('products:currency')}
|
|
|
@ -253,7 +533,7 @@ const ProductInfoQuotation = ({ editable, ...props }) => {
|
|
|
|
</Form.Item>
|
|
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
|
|
<Form.Item
|
|
|
|
label={t('products:Types')}
|
|
|
|
label={t('products:Types')}
|
|
|
|
name='unit_name'
|
|
|
|
name='unit_id'
|
|
|
|
rules={[
|
|
|
|
rules={[
|
|
|
|
{
|
|
|
|
{
|
|
|
|
required: true,
|
|
|
|
required: true,
|
|
|
@ -261,10 +541,10 @@ const ProductInfoQuotation = ({ editable, ...props }) => {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
]}
|
|
|
|
]}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<Radio.Group>
|
|
|
|
<Radio.Group>
|
|
|
|
<Radio value='0'>每人</Radio>
|
|
|
|
<Radio value='0'>每人</Radio>
|
|
|
|
<Radio value='1'>每团</Radio>
|
|
|
|
<Radio value='1'>每团</Radio>
|
|
|
|
</Radio.Group>
|
|
|
|
</Radio.Group>
|
|
|
|
</Form.Item>
|
|
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
|
|
<Form.Item
|
|
|
|
label={t('products:number')}
|
|
|
|
label={t('products:number')}
|
|
|
@ -276,7 +556,7 @@ const ProductInfoQuotation = ({ editable, ...props }) => {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
]}
|
|
|
|
]}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<InputNumber style={{width: '100%'}} />
|
|
|
|
<InputNumber style={{ width: '100%' }} />
|
|
|
|
</Form.Item>
|
|
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
|
|
<Form.Item
|
|
|
|
label={t('products:number')}
|
|
|
|
label={t('products:number')}
|
|
|
@ -288,7 +568,7 @@ const ProductInfoQuotation = ({ editable, ...props }) => {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
]}
|
|
|
|
]}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<InputNumber style={{width: '100%'}} />
|
|
|
|
<InputNumber style={{ width: '100%' }} />
|
|
|
|
</Form.Item>
|
|
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
|
|
<Form.Item
|
|
|
|
label={t('products:validityPeriod')}
|
|
|
|
label={t('products:validityPeriod')}
|
|
|
@ -300,7 +580,7 @@ const ProductInfoQuotation = ({ editable, ...props }) => {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
]}
|
|
|
|
]}
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<RangePicker presets={datePresets} style={{width: '100%'}} />
|
|
|
|
<RangePicker presets={datePresets} style={{ width: '100%' }} />
|
|
|
|
</Form.Item>
|
|
|
|
</Form.Item>
|
|
|
|
<Form.Item
|
|
|
|
<Form.Item
|
|
|
|
label={t('products:Weekdays')}
|
|
|
|
label={t('products:Weekdays')}
|
|
|
|