diff --git a/src/stores/Account.js b/src/stores/Account.js
index f11f545..195c46b 100644
--- a/src/stores/Account.js
+++ b/src/stores/Account.js
@@ -91,13 +91,11 @@ const useAccountStore = create((set, get) => ({
return postAccountPassword(formData)
},
- newEmptyRole: () => {
- return {
- role_id: null,
- role_name: '',
- role_ids: ''
- }
- },
+ newEmptyRole: () => ({
+ role_id: null,
+ role_name: '',
+ role_ids: ''
+ }),
newEmptyAccount: () => {
return {
diff --git a/src/stores/Products/Index.js b/src/stores/Products/Index.js
index 1b7c10b..ae7d0d7 100644
--- a/src/stores/Products/Index.js
+++ b/src/stores/Products/Index.js
@@ -1,6 +1,6 @@
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
-
+import dayjs from 'dayjs'
import { fetchJSON, postForm, postJSON } from '@/utils/request';
import { HT_HOST } from '@/config';
import { groupBy } from '@/utils/commons';
@@ -107,6 +107,7 @@ const initialState = {
activeAgency: {}, // 审核/编辑 页: 当前的供应商
agencyProducts: {}, // 审核/编辑 页: 供应商产品列表
editingProduct: {}, // 编辑页: 当前编辑的产品
+ quotationList: [], // 编辑页: 当前产品报价列表
editing: false,
};
export const useProductsStore = create(
@@ -120,11 +121,37 @@ export const useProductsStore = create(
setAgencyList: (agencyList) => set({ agencyList }),
setActiveAgency: (activeAgency) => set({ activeAgency }),
setAgencyProducts: (agencyProducts) => set({ agencyProducts }),
- setEditingProduct: (editingProduct) => set({ editingProduct }),
+ setEditingProduct: (product) => {
+ set(() => ({
+ editingProduct: product,
+ quotationList: product.quotation
+ }))
+ },
setEditing: (editing) => set({ editing }),
reset: () => set(initialState),
+ newEmptyQuotation: () => ({
+ id: null,
+ adult_cost: 0,
+ child_cost: 0,
+ currency: 'RMB',
+ unit_id: '0',
+ group_size_min: 1,
+ group_size_max: 10,
+ use_dates: [
+ dayjs().startOf('M'),
+ dayjs().endOf('M')
+ ],
+ weekdays: '5, 6'
+ }),
+
+ appendQuotationList: (newList) => {
+ set((state) => ({
+ quotationList: [...state.quotationList, ...newList]
+ }))
+ },
+
// side effects
searchAgency: async (param) => {
const { setLoading, setAgencyList } = get();
diff --git a/src/views/products/Detail/BatchImportPrice.jsx b/src/views/products/Detail/BatchImportPrice.jsx
index 535d811..935072b 100644
--- a/src/views/products/Detail/BatchImportPrice.jsx
+++ b/src/views/products/Detail/BatchImportPrice.jsx
@@ -56,6 +56,7 @@ const BatchImportPrice = ({ onBatchImportData }) => {
currency: definition.currency,
unit: definition.unitName,
+ // 保持和 API 返回格式一致,日期要转换为字符串
use_dates_start: definition.useDate[0],
use_dates_end: definition.useDate[1],
weekdays: definition.weekend.join(','),
@@ -315,27 +316,26 @@ const BatchImportPrice = ({ onBatchImportData }) => {
remove(field.name)
}} />}
>
-
-
-
-
-
-
+
+
+
+
+
{(priceFieldList, priceOptList) => (
diff --git a/src/views/products/Detail/ProductInfoQuotation.jsx b/src/views/products/Detail/ProductInfoQuotation.jsx
index 235310d..fa8438c 100644
--- a/src/views/products/Detail/ProductInfoQuotation.jsx
+++ b/src/views/products/Detail/ProductInfoQuotation.jsx
@@ -1,104 +1,273 @@
-import { useState } from 'react'
-import { Table, Form, Modal, Button, Radio, Input, InputNumber, Checkbox, DatePicker, Space } from 'antd'
+import { useEffect, useState } from 'react'
+import { Table, Form, Modal, Button, Radio, Input, Flex, Card, Select, Typography, InputNumber, Checkbox, DatePicker, Space } from 'antd'
import { useTranslation } from 'react-i18next'
import dayjs from 'dayjs'
-import BatchImportPrice from './BatchImportPrice'
+import { CloseOutlined, StarTwoTone, PlusOutlined } from '@ant-design/icons';
import { useDatePresets } from '@/hooks/useDatePresets'
import useProductsStore from '@/stores/Products/Index'
const { RangePicker } = DatePicker
-const ProductInfoQuotation = ({ editable, ...props }) => {
-
- const { t } = useTranslation()
-
- const [isQuotationModalOpen, setQuotationModalOpen] = useState(false)
- const [quotationForm] = Form.useForm()
-
- const datePresets = useDatePresets()
-
- const [editingProduct] = useProductsStore((state) => [state.editingProduct])
- const [batchImportPriceVisible, setBatchImportPriceVisible] = useState(false)
- const [quotationTableVisible, setQuotationTableVisible] = useState(false)
- const [quotation, setQuotation] = useState([])
- const [batchImportData, setBatchImportData] = useState([])
-
-
- const handleBatchImportData = (data) => {
- setBatchImportData(data)
+const PriceInput = (props) => {
+ const { id, value = {}, onChange } = props
+ const [numberStart, setNumberStart] = useState(0)
+ const [numberEnd, setNumberEnd] = useState(0)
+ const [audultPrice, setAudultPrice] = useState(0)
+ const [childrenPrice, setChildrenPrice] = useState(0)
+ const triggerChange = (changedValue) => {
+ onChange?.({
+ numberStart,
+ numberEnd,
+ audultPrice,
+ childrenPrice,
+ ...value,
+ ...changedValue,
+ })
}
-
- const handleBatchImportOK = () => {
- const tempBatchImportData = batchImportData.map((item) => {
- const { tag, validPeriod, ...rest } = item
- return rest
+ const onNumberStartChange = (e) => {
+ const newNumber = parseInt(e.target.value || '0', 10)
+ if (Number.isNaN(numberStart)) {
+ return
+ }
+ if (!('numberStart' in value)) {
+ setNumberStart(newNumber);
+ }
+ triggerChange({
+ numberStart: newNumber,
})
- const newData = [...quotation, ...tempBatchImportData]
- const sortedData = [...newData].sort((a, b) => {
- if (a.group_size_min !== b.group_size_min) {
- return a.group_size_min - b.group_size_min
- }
-
- return a.group_size_max - b.group_size_max
+ }
+ const onNumberEndChange = (e) => {
+ const newNumber = parseInt(e.target.value || '0', 10)
+ if (Number.isNaN(numberEnd)) {
+ return
+ }
+ 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 (
+
+
+
+
+
+
+ )
+}
+
+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)
- setBatchImportPriceVisible(false)
+const defaultPriceValue = {
+ 'priceInput': {
+ 'numberStart': 1,
+ 'numberEnd': 2,
+ 'audultPrice': 0,
+ 'childrenPrice': 0
}
- const quotationTableVisibleOK = () => {
- const tempQuotation = [...quotation]
+}
- const sortedData = [...tempQuotation].sort((a, b) => {
- 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))
+const defaultDefinitionValue = {
+ 'useDate': [
+ 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) {
- return aValidPeriod - bValidPeriod
- }
- const aGroupSize = a.group_size_max - a.group_size_min
- const bGroupSize = b.group_size_max - b.group_size_min
+const ProductInfoQuotation = ({ editable, ...props }) => {
- return aGroupSize - bGroupSize
- })
- setQuotation(sortedData)
- setQuotationTableVisible(false)
- }
- const quotationTableVisibleCancel = () => {
- setQuotationTableVisible(false)
- }
+ const { t } = useTranslation()
- const handleDelete = (index) => {
- const newData = [...quotation]
- newData.splice(index, 1)
- const sortedData = [...newData].sort((a, b) => {
- 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
+ const [isQuotationModalOpen, setQuotationModalOpen] = useState(false)
+ const [isBatchSetupModalOpen, setBatchSetupModalOpen] = useState(false)
+ const [quotationForm] = Form.useForm()
+ const [batchSetupForm] = Form.useForm()
- return aGroupSize - bGroupSize
- })
- setQuotation(sortedData)
- }
+ const datePresets = useDatePresets()
+
+ const [newEmptyQuotation, appendQuotationList, quotationList] =
+ useProductsStore((state) => [state.newEmptyQuotation, state.appendQuotationList, state.quotationList])
+
+ useEffect(() => {
+ console.info('quotationList: ', quotationList)
+ }, [quotationList])
const onQuotationSeleted = async (quotation) => {
- // 转换为 RangePicker 赋值格式
+ // 把 start, end 转换为 RangePicker 数组格式
quotation.use_dates = [dayjs(quotation.use_dates_start), dayjs(quotation.use_dates_end)]
quotationForm.setFieldsValue(quotation)
setQuotationModalOpen(true)
}
const onNewQuotation = () => {
- // const emptyQuotation = newEmptyQuotation()
- // quotationForm.setFieldsValue(emptyQuotation)
- // setQuotationModalOpen(true)
+ const emptyQuotation = newEmptyQuotation()
+ quotationForm.setFieldsValue(emptyQuotation)
+ setQuotationModalOpen(true)
}
const onQuotationFinish = (values) => {
console.info(values)
+ setQuotationModalOpen(false)
// saveOrUpdateQuotation(values)
// .then(() => {
// setQuotationModalOpen(false)
@@ -118,6 +287,35 @@ const ProductInfoQuotation = ({ editable, ...props }) => {
// 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 = [
{ title: t('products:adultPrice'), dataIndex: 'adult_cost', width: '4rem' },
{ title: t('products:childrenPrice'), dataIndex: 'child_cost', width: '4rem' },
@@ -162,28 +360,110 @@ const ProductInfoQuotation = ({ editable, ...props }) => {
<>
{t('products:EditComponents.Quotation')}
{
// editable &&
-
+
+
+ ))}
+ } onClick={() => add(defaultDefinitionValue)} block>
+ 新增设置
+
+
+ )}
+
+
+ {() => (
+
+ {JSON.stringify(batchSetupForm.getFieldsValue(), null, 2)}
+
+ )}
+
+
{
},
]}
>
-
+
{
},
]}
>
-
+
{
{
},
]}
>
-
- 每人
- 每团
-
+
+ 每人
+ 每团
+
{
},
]}
>
-
+
{
},
]}
>
-
+
{
},
]}
>
-
+