|
|
|
@ -2,19 +2,15 @@ import React, { useState, useEffect, useRef, useMemo } from 'react';
|
|
|
|
|
import { Button, Card, Col, Row, Breadcrumb, Table, Popconfirm, Form, Input, InputNumber, Tag, Modal, Select, Tree, FloatButton, DatePicker } from 'antd';
|
|
|
|
|
import { Link } from 'react-router-dom';
|
|
|
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
|
import AddValidityWithWeekend from '@/views/products/Detail/addValidityWithWeekend';
|
|
|
|
|
import { getAgencyProductsAction } from '@/stores/Products/Index';
|
|
|
|
|
import { useProductsTypes } from '@/hooks/useProductsSets';
|
|
|
|
|
import Extras from './Detail/Extras';
|
|
|
|
|
import { groupBy } from '@/utils/commons';
|
|
|
|
|
import { useParams } from 'react-router-dom';
|
|
|
|
|
import useProductsStore from '@/stores/Products/Index';
|
|
|
|
|
import { useHTLanguageSets } from '@/hooks/useHTLanguageSets';
|
|
|
|
|
import { useDefaultLgc } from '@/i18n/LanguageSwitcher';
|
|
|
|
|
import BatchImportPrice from './Detail/BatchImportPrice1';
|
|
|
|
|
import BatchImportPrice from './Detail/BatchImportPrice';
|
|
|
|
|
import dayjs from 'dayjs';
|
|
|
|
|
import { PlusCircleFilled } from '@ant-design/icons';
|
|
|
|
|
import { info } from 'autoprefixer';
|
|
|
|
|
import { DeptSelector } from '@/components/DeptSelector';
|
|
|
|
|
import { useDatePresets } from '@/hooks/useDatePresets';
|
|
|
|
|
|
|
|
|
@ -27,7 +23,6 @@ function Detail() {
|
|
|
|
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
|
|
|
|
const [selectedTag, setSelectedTag] = useState(null);
|
|
|
|
|
const [saveData, setSaveData] = useState(null);
|
|
|
|
|
const [datePickerVisible, setDatePickerVisible] = useState(false);
|
|
|
|
|
const [batchImportPriceVisible, setBatchImportPriceVisible] = useState(false);
|
|
|
|
|
const [quotationTableVisible, setQuotationTableVisible] = useState(false)
|
|
|
|
|
const [currentid, setCurrentid] = useState(null);
|
|
|
|
@ -61,7 +56,22 @@ function Detail() {
|
|
|
|
|
const [dataFetched, setDataFetched] = useState(false); // 添加一个标志位
|
|
|
|
|
const [selectedNodeKey, setSelectedNodeKey] = useState(null);
|
|
|
|
|
const [selectedDays, setSelectedDays] = useState([]);
|
|
|
|
|
const [currentQuotationRecord, setCurrentQuotationRecord] = useState(null);
|
|
|
|
|
const [weekdays,setWeekdays] = useState([]);
|
|
|
|
|
const [currentQuotationRecord, setCurrentQuotationRecord] = useState({
|
|
|
|
|
use_dates_start: null,
|
|
|
|
|
use_dates_end: null
|
|
|
|
|
});
|
|
|
|
|
const formatDate = (date) => (date ? dayjs(date) : null);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const startDate = currentQuotationRecord.use_dates_start && dayjs(currentQuotationRecord.use_dates_start).isValid()
|
|
|
|
|
? formatDate(currentQuotationRecord.use_dates_start)
|
|
|
|
|
: null;
|
|
|
|
|
const endDate = currentQuotationRecord.use_dates_end && dayjs(currentQuotationRecord.use_dates_end).isValid()
|
|
|
|
|
? formatDate(currentQuotationRecord.use_dates_end)
|
|
|
|
|
: null;
|
|
|
|
|
|
|
|
|
|
const [editIndex, setEditIndex] = useState(null);
|
|
|
|
|
const presets = useDatePresets();
|
|
|
|
|
const handleBatchImportData = (data) => {
|
|
|
|
|
setBatchImportData(data);
|
|
|
|
@ -158,11 +168,13 @@ function Detail() {
|
|
|
|
|
}))
|
|
|
|
|
}));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const tempExpandedKeys = productsTypes.map(item => item.key)
|
|
|
|
|
console.log("tempExpandedKeys", tempExpandedKeys)
|
|
|
|
|
const treeData = generateTreeData(productsTypes, agencyProducts);
|
|
|
|
|
console.log("treeData", treeData)
|
|
|
|
|
setDataFetched(true); // 设置标志位为 true,表示数据已获取
|
|
|
|
|
setTreeData(treeData);
|
|
|
|
|
setExpandedKeys(tempExpandedKeys)
|
|
|
|
|
setProductsData(agencyProducts);
|
|
|
|
|
setDefaultData(treeData);
|
|
|
|
|
setDataList(flattenTreeData(treeData));
|
|
|
|
@ -173,6 +185,7 @@ function Detail() {
|
|
|
|
|
fetchData();
|
|
|
|
|
}, [agencyProducts, dataFetched]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const flattenTreeData = (tree) => {
|
|
|
|
|
let flatList = [];
|
|
|
|
|
const flatten = (nodes) => {
|
|
|
|
@ -224,6 +237,7 @@ function Detail() {
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const onChange = (e) => {
|
|
|
|
|
const { value } = e.target;
|
|
|
|
|
const newExpandedKeys = dataList
|
|
|
|
@ -243,64 +257,33 @@ function Detail() {
|
|
|
|
|
|
|
|
|
|
const isEditing = (record) => record.id === editingid;
|
|
|
|
|
|
|
|
|
|
const edit = (record) => {
|
|
|
|
|
// setQuotationTableVisible(true);
|
|
|
|
|
// setCurrentQuotationRecord(record);
|
|
|
|
|
console.log("record", record)
|
|
|
|
|
form.setFieldsValue({ ...record });
|
|
|
|
|
setEditingid(record.id);
|
|
|
|
|
const edit = (record, index) => {
|
|
|
|
|
setQuotationTableVisible(true);
|
|
|
|
|
setEditIndex(index);
|
|
|
|
|
// record.use_dates_start = dayjs(record.use_dates_start);
|
|
|
|
|
// record.use_dates_end = dayjs(record.use_dates_end);
|
|
|
|
|
setCurrentQuotationRecord(record);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const cancel = () => {
|
|
|
|
|
setEditingid('');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleSave = async (id) => {
|
|
|
|
|
try {
|
|
|
|
|
const { info, ...restRow } = await form.validateFields();
|
|
|
|
|
const newData = [...quotation];
|
|
|
|
|
const index = newData.findIndex((item) => id === item.id);
|
|
|
|
|
if (index > -1) {
|
|
|
|
|
const item = newData[index];
|
|
|
|
|
newData.splice(index, 1, { ...item, ...restRow });
|
|
|
|
|
delete newData[index].quotation
|
|
|
|
|
delete newData[index].extras
|
|
|
|
|
console.log("newData", newData)
|
|
|
|
|
|
|
|
|
|
//按人等范围排序
|
|
|
|
|
const sortedData = [...newData].sort((a, b) => {
|
|
|
|
|
// 首先按照 group_size_min 升序排序
|
|
|
|
|
if (a.group_size_min !== b.group_size_min) {
|
|
|
|
|
return a.group_size_min - b.group_size_min;
|
|
|
|
|
}
|
|
|
|
|
// 如果 group_size_min 相同,则按照 group_size_max 升序排序
|
|
|
|
|
return a.group_size_max - b.group_size_max;
|
|
|
|
|
});
|
|
|
|
|
setQuotation(sortedData);
|
|
|
|
|
setEditingid('');
|
|
|
|
|
} else {
|
|
|
|
|
newData.push(restRow);
|
|
|
|
|
setQuotation(newData);
|
|
|
|
|
setEditingid('');
|
|
|
|
|
}
|
|
|
|
|
} catch (errInfo) {
|
|
|
|
|
console.log('Validate Failed:', errInfo);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleDelete = (id) => {
|
|
|
|
|
const newData = [...quotation];
|
|
|
|
|
const index = newData.findIndex((item) => id === item.id);
|
|
|
|
|
newData.splice(index, 1);
|
|
|
|
|
|
|
|
|
|
//按人等范围排序
|
|
|
|
|
const sortedData = [...newData].sort((a, b) => {
|
|
|
|
|
// 首先按照 group_size_min 升序排序
|
|
|
|
|
if (a.group_size_min !== b.group_size_min) {
|
|
|
|
|
return a.group_size_min - b.group_size_min;
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
// 如果 group_size_min 相同,则按照 group_size_max 升序排序
|
|
|
|
|
return a.group_size_max - b.group_size_max;
|
|
|
|
|
const aGroupSize = a.group_size_max - a.group_size_min;
|
|
|
|
|
const bGroupSize = b.group_size_max - b.group_size_min;
|
|
|
|
|
|
|
|
|
|
return aGroupSize - bGroupSize;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
setQuotation(sortedData);
|
|
|
|
@ -308,7 +291,6 @@ function Detail() {
|
|
|
|
|
|
|
|
|
|
const handleAdd = () => {
|
|
|
|
|
const newData = {
|
|
|
|
|
// id: `${quotation.length + 1}`,
|
|
|
|
|
value: '',
|
|
|
|
|
currency: '',
|
|
|
|
|
unit_name: '',
|
|
|
|
@ -331,164 +313,60 @@ function Detail() {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const quotationTableVisibleOK = () => {
|
|
|
|
|
setQuotationTableVisible(false);
|
|
|
|
|
}
|
|
|
|
|
const quotationTableVisibleCancel = () => {
|
|
|
|
|
setQuotationTableVisible(false);
|
|
|
|
|
currentQuotationRecord.use_dates_start = dayjs(currentQuotationRecord.use_dates_start).format('YYYY-MM-DD')
|
|
|
|
|
currentQuotationRecord.use_dates_end = dayjs(currentQuotationRecord.use_dates_end).format('YYYY-MM-DD')
|
|
|
|
|
console.log("currentQuotationRecord", currentQuotationRecord);
|
|
|
|
|
console.log("qqqqq", quotation)
|
|
|
|
|
const tempQuotation = [...quotation];
|
|
|
|
|
tempQuotation[editIndex] = { ...currentQuotationRecord,weekdays:weekdays };
|
|
|
|
|
console.log("tempQuotation", tempQuotation)
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
|
|
if (aValidPeriod !== bValidPeriod) {
|
|
|
|
|
return aValidPeriod - bValidPeriod;
|
|
|
|
|
}
|
|
|
|
|
const handleDateChange = ({ dateRange, selectedDays }) => {
|
|
|
|
|
|
|
|
|
|
console.log("dateRange", dateRange)
|
|
|
|
|
console.log("selectedDays", selectedDays)
|
|
|
|
|
const aGroupSize = a.group_size_max - a.group_size_min;
|
|
|
|
|
const bGroupSize = b.group_size_max - b.group_size_min;
|
|
|
|
|
|
|
|
|
|
return aGroupSize - bGroupSize;
|
|
|
|
|
});
|
|
|
|
|
console.log("sortedData",sortedData)
|
|
|
|
|
|
|
|
|
|
// 计算周末
|
|
|
|
|
const weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
|
|
|
|
|
let weekDayCount = selectedDays.map(day => weekdays.indexOf(day) + 1).sort().join(',');
|
|
|
|
|
if (!weekDayCount || weekDayCount.length === 0) {
|
|
|
|
|
weekDayCount = "全年";
|
|
|
|
|
setQuotation(sortedData);
|
|
|
|
|
setQuotationTableVisible(false);
|
|
|
|
|
}
|
|
|
|
|
const newData = [...quotation];
|
|
|
|
|
const index = newData.findIndex((item) => currentid === item.id);
|
|
|
|
|
if (index > -1) {
|
|
|
|
|
newData[index].weekdays = weekDayCount;
|
|
|
|
|
setQuotation(newData);
|
|
|
|
|
const quotationTableVisibleCancel = () => {
|
|
|
|
|
setQuotationTableVisible(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setSelectedDateData({ dateRange, selectedDays })
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleDateOk = () => {
|
|
|
|
|
let { dateRange } = selectedDateData;
|
|
|
|
|
console.log("handleDateOk_dateRange", dateRange)
|
|
|
|
|
const use_dates_start = dateRange[0];
|
|
|
|
|
const use_dates_end = dateRange[1];
|
|
|
|
|
if (currentid !== null) {
|
|
|
|
|
const newData = [...quotation];
|
|
|
|
|
const index = newData.findIndex((item) => currentid === item.id);
|
|
|
|
|
if (index > -1) {
|
|
|
|
|
newData[index].use_dates_start = use_dates_start;
|
|
|
|
|
newData[index].use_dates_end = use_dates_end;
|
|
|
|
|
console.log("newData", newData)
|
|
|
|
|
setQuotation(newData);
|
|
|
|
|
setCurrentid(null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
setSelectedDateData({ dateRange: null, selectedDays: [] })
|
|
|
|
|
setDatePickerVisible(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleBatchImportOK = () => {
|
|
|
|
|
console.log("quotation", quotation)
|
|
|
|
|
console.log('Batch Import Data:', batchImportData);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建一个新的数据副本,删除 tag 和 validPeriod 属性
|
|
|
|
|
|
|
|
|
|
const tempBatchImportData = batchImportData.map(item => {
|
|
|
|
|
const { tag, validPeriod, ...rest } = item;
|
|
|
|
|
return rest; // 返回剩余的属性
|
|
|
|
|
return rest;
|
|
|
|
|
});
|
|
|
|
|
// 将剩余的属性添加到 quotation 中
|
|
|
|
|
const newData = [...quotation, ...tempBatchImportData];
|
|
|
|
|
|
|
|
|
|
//按人等范围排序
|
|
|
|
|
const sortedData = [...newData].sort((a, b) => {
|
|
|
|
|
// 首先按照 group_size_min 升序排序
|
|
|
|
|
if (a.group_size_min !== b.group_size_min) {
|
|
|
|
|
return a.group_size_min - b.group_size_min;
|
|
|
|
|
}
|
|
|
|
|
// 如果 group_size_min 相同,则按照 group_size_max 升序排序
|
|
|
|
|
|
|
|
|
|
return a.group_size_max - b.group_size_max;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 更新状态来更新页面
|
|
|
|
|
|
|
|
|
|
setQuotation(sortedData);
|
|
|
|
|
setBatchImportPriceVisible(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const EditableCell = ({ editing, dataIndex, title, inputType, record, children, handleDateSelect, ...restProps }) => {
|
|
|
|
|
let inputNode = inputType === 'number' ? <InputNumber /> : <Input />;
|
|
|
|
|
if (dataIndex === 'validityPeriod' && editing) {
|
|
|
|
|
return (
|
|
|
|
|
<td {...restProps}>
|
|
|
|
|
{children}
|
|
|
|
|
<Button onClick={() => handleDateSelect(record.id)}>选择日期</Button>
|
|
|
|
|
</td>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dataIndex === 'unit_name' && editing) {
|
|
|
|
|
inputNode = (
|
|
|
|
|
<Select>
|
|
|
|
|
<Select.Option value="每人">每人</Select.Option>
|
|
|
|
|
<Select.Option value="每团">每团</Select.Option>
|
|
|
|
|
</Select>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dataIndex === 'currency' && editing) {
|
|
|
|
|
inputNode = (
|
|
|
|
|
<Select>
|
|
|
|
|
<Select.Option value="CNY">CNY</Select.Option>
|
|
|
|
|
<Select.Option value="USD">USD</Select.Option>
|
|
|
|
|
</Select>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dataIndex === 'group_size' && editing) {
|
|
|
|
|
return (
|
|
|
|
|
<td {...restProps} style={{ height: 115, display: 'flex', alignItems: 'center' }}>
|
|
|
|
|
<InputNumber
|
|
|
|
|
min={0}
|
|
|
|
|
value={record.group_size_min}
|
|
|
|
|
onChange={(value) => handleInputGroupSize('group_size_min', record.id, 'group_size', value)}
|
|
|
|
|
style={{ width: '50%', marginRight: '10px' }}
|
|
|
|
|
/>
|
|
|
|
|
<span>-</span>
|
|
|
|
|
<InputNumber
|
|
|
|
|
min={0}
|
|
|
|
|
value={record.group_size_max}
|
|
|
|
|
onChange={(value) => handleInputGroupSize('group_size_max', record.id, 'group_size', value)}
|
|
|
|
|
style={{ width: '50%', marginLeft: '10px' }}
|
|
|
|
|
/>
|
|
|
|
|
</td>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<td {...restProps}>
|
|
|
|
|
{editing ? (
|
|
|
|
|
<Form.Item
|
|
|
|
|
name={dataIndex}
|
|
|
|
|
style={{ margin: 0 }}
|
|
|
|
|
rules={[{ required: true, message: `Please Input ${title}!` }]}
|
|
|
|
|
>
|
|
|
|
|
{inputNode}
|
|
|
|
|
</Form.Item>
|
|
|
|
|
) : (
|
|
|
|
|
children
|
|
|
|
|
)}
|
|
|
|
|
</td>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleInputGroupSize = (name, id, dataIndex, value) => {
|
|
|
|
|
|
|
|
|
|
const newData = [...quotation];
|
|
|
|
|
const index = newData.findIndex((item) => id === item.id);
|
|
|
|
|
if (index > -1) {
|
|
|
|
|
const item = newData[index];
|
|
|
|
|
newData[index] = { ...item, }
|
|
|
|
|
if (name === 'group_size_min') {
|
|
|
|
|
newData[index] = { ...item, group_size_min: value };
|
|
|
|
|
} else {
|
|
|
|
|
newData[index] = { ...item, group_size_max: value };
|
|
|
|
|
}
|
|
|
|
|
setQuotation(newData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const columns = [
|
|
|
|
|
{ title: t('products:adultPrice'), dataIndex: 'adult_cost', width: '10%', editable: true },
|
|
|
|
@ -516,43 +394,37 @@ function Detail() {
|
|
|
|
|
{
|
|
|
|
|
title: t('products:operation'),
|
|
|
|
|
dataIndex: 'operation',
|
|
|
|
|
render: (_, record) => {
|
|
|
|
|
const editable = isEditing(record);
|
|
|
|
|
return editable ? (
|
|
|
|
|
<span>
|
|
|
|
|
<Button type="link" onClick={() => handleSave(record.id)}>{t('Save')}</Button>
|
|
|
|
|
<Button type="link" onClick={cancel}>{t('Cancel')}</Button>
|
|
|
|
|
</span>
|
|
|
|
|
) : (
|
|
|
|
|
render: (_, record, index) => {
|
|
|
|
|
return (
|
|
|
|
|
<span>
|
|
|
|
|
<a disabled={editingid !== ''} onClick={() => edit(record)} style={{ marginRight: 8 }}>{t('Edit')}</a>
|
|
|
|
|
<a onClick={() => edit(record, index)} style={{ marginRight: 8 }}>{t('Edit')}</a>
|
|
|
|
|
<Popconfirm title={t('sureDelete')} onConfirm={() => handleDelete(record.id)}>
|
|
|
|
|
<a>{t('Delete')}</a>
|
|
|
|
|
</Popconfirm>
|
|
|
|
|
</span>
|
|
|
|
|
);
|
|
|
|
|
)
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const mergedColumns = columns.map((col) => {
|
|
|
|
|
if (!col.editable) {
|
|
|
|
|
return col;
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
...col,
|
|
|
|
|
onCell: (record) => ({
|
|
|
|
|
record,
|
|
|
|
|
inputType: col.dataIndex === 'age' ? 'number' : 'text',
|
|
|
|
|
dataIndex: col.dataIndex,
|
|
|
|
|
title: col.title,
|
|
|
|
|
editing: isEditing(record),
|
|
|
|
|
handleDateSelect: handleDateSelect,
|
|
|
|
|
}),
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
// const mergedColumns = columns.map((col) => {
|
|
|
|
|
// if (!col.editable) {
|
|
|
|
|
// return col;
|
|
|
|
|
// }
|
|
|
|
|
// return {
|
|
|
|
|
// ...col,
|
|
|
|
|
// onCell: (record) => ({
|
|
|
|
|
// record,
|
|
|
|
|
// inputType: col.dataIndex === 'age' ? 'number' : 'text',
|
|
|
|
|
// dataIndex: col.dataIndex,
|
|
|
|
|
// title: col.title,
|
|
|
|
|
// editing: isEditing(record),
|
|
|
|
|
// handleDateSelect: handleDateSelect,
|
|
|
|
|
// }),
|
|
|
|
|
// };
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
const handleTagClick = (tag) => {
|
|
|
|
|
setSelectedTag(tag);
|
|
|
|
@ -618,11 +490,17 @@ function Detail() {
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleDayClick = (day) => {
|
|
|
|
|
const handleDayClick = (dayIndex) => {
|
|
|
|
|
const dayOfWeek = (dayIndex % 7) + 1;
|
|
|
|
|
|
|
|
|
|
setSelectedDays((prevSelectedDays) => {
|
|
|
|
|
const updatedDays = prevSelectedDays.includes(day)
|
|
|
|
|
? prevSelectedDays.filter((d) => d !== day)
|
|
|
|
|
: [...prevSelectedDays, day];
|
|
|
|
|
const updatedDays = prevSelectedDays.includes(dayOfWeek)
|
|
|
|
|
? prevSelectedDays.filter((d) => d !== dayOfWeek)
|
|
|
|
|
: [...prevSelectedDays, dayOfWeek];
|
|
|
|
|
console.log("updatedDays",updatedDays);
|
|
|
|
|
const weekdaysString = updatedDays.sort().join(',');
|
|
|
|
|
console.log("weekdaysString",weekdaysString)
|
|
|
|
|
setWeekdays(weekdaysString)
|
|
|
|
|
return updatedDays;
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
@ -631,6 +509,7 @@ function Detail() {
|
|
|
|
|
const handleNodeSelect = (_, { node }) => {
|
|
|
|
|
if (!node._raw.info.id) {
|
|
|
|
|
console.log("nodeNoID", node)
|
|
|
|
|
setQuotation([])
|
|
|
|
|
const infoData = node._raw.info
|
|
|
|
|
const newLgcDetails = node._raw.lgc_details
|
|
|
|
|
const fatherKey = node.key.split('-')[0];
|
|
|
|
@ -715,9 +594,26 @@ function Detail() {
|
|
|
|
|
setInfoDataForId(infoData.id)
|
|
|
|
|
}
|
|
|
|
|
setLgc_details(newLgcDetails);
|
|
|
|
|
setQuotation(initialQuotationData);
|
|
|
|
|
|
|
|
|
|
// 使用 setTimeout 确保 lgc_details 已经更新
|
|
|
|
|
|
|
|
|
|
const sortedData = [...initialQuotationData].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;
|
|
|
|
|
|
|
|
|
|
return aGroupSize - bGroupSize;
|
|
|
|
|
});
|
|
|
|
|
setQuotation(sortedData);
|
|
|
|
|
|
|
|
|
|
if (node._raw.info.id) {
|
|
|
|
|
form.setFieldsValue({
|
|
|
|
|
info: {
|
|
|
|
@ -870,12 +766,12 @@ function Detail() {
|
|
|
|
|
<div>
|
|
|
|
|
<Row>
|
|
|
|
|
<Col span={6} className=' relative'>
|
|
|
|
|
<Card className='w-[inherit] fixed overflow-y-auto max-h-[80vh]'>
|
|
|
|
|
<Card className='w-[inherit] fixed overflow-y-auto max-h-[80%] max-w-[22%] overflow-x-auto'>
|
|
|
|
|
<Row>
|
|
|
|
|
<Search style={{ marginBottom: 8 }} placeholder="Search" onChange={onChange} />
|
|
|
|
|
</Row>
|
|
|
|
|
|
|
|
|
|
<Tree
|
|
|
|
|
style={{ overflowX: 'auto' }}
|
|
|
|
|
onSelect={handleNodeSelect}
|
|
|
|
|
treeData={treeData}
|
|
|
|
|
expandedKeys={expandedKeys}
|
|
|
|
@ -980,10 +876,9 @@ function Detail() {
|
|
|
|
|
<h2>{t('products:supplierQuotation')}</h2>
|
|
|
|
|
<Form.Item name="quotation">
|
|
|
|
|
<Table rowKey={'id'}
|
|
|
|
|
components={{ body: { cell: EditableCell } }}
|
|
|
|
|
bordered
|
|
|
|
|
dataSource={quotation}
|
|
|
|
|
columns={mergedColumns}
|
|
|
|
|
columns={columns}
|
|
|
|
|
rowClassName="editable-row"
|
|
|
|
|
pagination={{ onChange: cancel }}
|
|
|
|
|
/>
|
|
|
|
@ -1010,18 +905,6 @@ function Detail() {
|
|
|
|
|
</Col>
|
|
|
|
|
</Row>
|
|
|
|
|
|
|
|
|
|
{datePickerVisible && (
|
|
|
|
|
<Modal
|
|
|
|
|
title="选择日期"
|
|
|
|
|
visible={datePickerVisible}
|
|
|
|
|
onOk={handleDateOk}
|
|
|
|
|
onCancel={() => setDatePickerVisible(false)}
|
|
|
|
|
>
|
|
|
|
|
<AddValidityWithWeekend onDateChange={handleDateChange} />
|
|
|
|
|
</Modal>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
batchImportPriceVisible && (
|
|
|
|
|
<Modal
|
|
|
|
@ -1066,7 +949,7 @@ function Detail() {
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{/* {
|
|
|
|
|
{
|
|
|
|
|
quotationTableVisible && (
|
|
|
|
|
<Modal
|
|
|
|
|
title="编辑供应商报价"
|
|
|
|
@ -1075,16 +958,16 @@ function Detail() {
|
|
|
|
|
onCancel={quotationTableVisibleCancel}
|
|
|
|
|
>
|
|
|
|
|
<h3>成人价</h3>
|
|
|
|
|
<Input value={currentQuotationRecord.adult_cost} />
|
|
|
|
|
<InputNumber defaultValue={currentQuotationRecord.adult_cost} onChange={(e) => setCurrentQuotationRecord({ ...currentQuotationRecord, adult_cost: e })} />
|
|
|
|
|
<h3>儿童价</h3>
|
|
|
|
|
<Input value={currentQuotationRecord.children} />
|
|
|
|
|
<InputNumber defaultValue={currentQuotationRecord.child_cost} onChange={(e) => setCurrentQuotationRecord({ ...currentQuotationRecord, child_cost: e })} />
|
|
|
|
|
<h3>币种</h3>
|
|
|
|
|
<Select style={{ width: "30%" }} value={currentQuotationRecord.currency}>
|
|
|
|
|
<Select.Option value="CNY">CNY</Select.Option>
|
|
|
|
|
<Select style={{ width: "30%" }} defaultValue={currentQuotationRecord.currency} onChange={(e) => setCurrentQuotationRecord({ ...currentQuotationRecord, currency: e })}>
|
|
|
|
|
<Select.Option value="RMB">RMB</Select.Option>
|
|
|
|
|
<Select.Option value="USD">USD</Select.Option>
|
|
|
|
|
</Select >
|
|
|
|
|
<h3>类型</h3>
|
|
|
|
|
<Select style={{ width: "30%" }} value={currentQuotationRecord.unit_name}>
|
|
|
|
|
<Select style={{ width: "30%" }} defaultValue={currentQuotationRecord.unit_name} onChange={(e) => setCurrentQuotationRecord({ ...currentQuotationRecord, unit_name: e })}>
|
|
|
|
|
<Select.Option value="每人">每人</Select.Option>
|
|
|
|
|
<Select.Option value="每团">每团</Select.Option>
|
|
|
|
|
</Select>
|
|
|
|
@ -1093,26 +976,39 @@ function Detail() {
|
|
|
|
|
<td style={{ display: 'flex', alignItems: 'center' }}>
|
|
|
|
|
<InputNumber
|
|
|
|
|
min={0}
|
|
|
|
|
value={currentQuotationRecord.group_size_min}
|
|
|
|
|
// onChange={(value) => handleInputGroupSize('group_size_min', currentQuotationRecord.id, 'group_size', value)}
|
|
|
|
|
defaultValue={currentQuotationRecord.group_size_min}
|
|
|
|
|
onChange={(e) => setCurrentQuotationRecord({ ...currentQuotationRecord, group_size_min: e })}
|
|
|
|
|
style={{ width: '50%', marginRight: '10px' }}
|
|
|
|
|
/>
|
|
|
|
|
<span>-</span>
|
|
|
|
|
<InputNumber
|
|
|
|
|
min={0}
|
|
|
|
|
value={currentQuotationRecord.group_size_max}
|
|
|
|
|
// onChange={(value) => handleInputGroupSize('group_size_max', currentQuotationRecord.id, 'group_size', value)}
|
|
|
|
|
defaultValue={currentQuotationRecord.group_size_max}
|
|
|
|
|
onChange={(e) => setCurrentQuotationRecord({ ...currentQuotationRecord, group_size_max: e })}
|
|
|
|
|
style={{ width: '50%', marginLeft: '10px' }}
|
|
|
|
|
/>
|
|
|
|
|
</td>
|
|
|
|
|
<h4>有效期</h4>
|
|
|
|
|
<RangePicker allowClear={true} inputReadOnly={true} presets={presets} placeholder={['From', 'Thru']} value={[dayjs(currentQuotationRecord.use_dates_start).format('YYYY-MM-DD'),dayjs(currentQuotationRecord.use_dates_end).format('YYYY-MM-DD')]}/>
|
|
|
|
|
<h4>周末</h4>
|
|
|
|
|
<h3>有效期</h3>
|
|
|
|
|
<RangePicker
|
|
|
|
|
allowClear={true}
|
|
|
|
|
inputReadOnly={true}
|
|
|
|
|
presets={presets}
|
|
|
|
|
placeholder={['From', 'Thru']}
|
|
|
|
|
defaultValue={startDate && endDate ? [startDate, endDate] : null}
|
|
|
|
|
onChange={(dates) => {
|
|
|
|
|
setCurrentQuotationRecord({
|
|
|
|
|
...currentQuotationRecord,
|
|
|
|
|
use_dates_start: dates[0],
|
|
|
|
|
use_dates_end: dates[1]
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
<h3>周末</h3>
|
|
|
|
|
{days.map((day, index) => (
|
|
|
|
|
<Button
|
|
|
|
|
key={index}
|
|
|
|
|
type={selectedDays.includes(day) ? 'primary' : 'default'}
|
|
|
|
|
onClick={() => handleDayClick(day)}
|
|
|
|
|
type={selectedDays.includes((index % 7) + 1) ? 'primary' : 'default'}
|
|
|
|
|
onClick={() => handleDayClick(index)}
|
|
|
|
|
style={{ margin: '5px' }}
|
|
|
|
|
>
|
|
|
|
|
{day}
|
|
|
|
@ -1122,7 +1018,7 @@ function Detail() {
|
|
|
|
|
</Modal>
|
|
|
|
|
|
|
|
|
|
)
|
|
|
|
|
} */}
|
|
|
|
|
}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|