todo: 产品编辑页面: 组件

perf/export-docx
Lei OT 1 year ago
parent 26d354e0ea
commit 2a193f9955

@ -1068,9 +1068,9 @@ function Detail() {
<div> <div>
<Flex gap={10}> <Flex gap={10}>
{/* onNodeSelect={handleNodeSelect} */} {/* onNodeSelect={handleNodeSelect} */}
<ProductsTree className='basis-64 sticky top-16 overflow-y-auto shrink-0' style={{ height: 'calc(100vh - 182px)' }} /> <ProductsTree className='basis-64 sticky top-16 overflow-y-auto shrink-0' style={{ height: 'calc(100vh - 150px)' }} />
<Divider type={'vertical'} className='mx-1 h-auto' /> <Divider type={'vertical'} className='mx-1 h-auto' />
<div className=' flex-auto'> <div className=' flex-auto grow-0'>
<ProductInfo /> <ProductInfo />
{/* <Row> */} {/* <Row> */}
{/* <Col span={6} className=' relative'> */} {/* <Col span={6} className=' relative'> */}
@ -1165,8 +1165,8 @@ function Detail() {
{/* </Card> */} {/* </Card> */}
{/* <Card style={{ width: "80%" }}> */} {/* <Card style={{ width: "80%" }}> */}
<h2>{t('products:supplierQuotation')}</h2> {/* <h2>{t('products:supplierQuotation')}</h2> */}
<Form.Item name="quotation"> {/* <Form.Item name="quotation">
<Table rowKey={'tempKey'} <Table rowKey={'tempKey'}
bordered bordered
dataSource={quotation} dataSource={quotation}
@ -1175,7 +1175,7 @@ function Detail() {
// pagination={{ onChange: cancel }} // pagination={{ onChange: cancel }}
/> />
{ {
!isCanEditable && // !isCanEditable &&
<Button onClick={handleAdd} type="primary" style={{ marginTop: 16 }}> <Button onClick={handleAdd} type="primary" style={{ marginTop: 16 }}>
{t('products:addQuotation')} {t('products:addQuotation')}
</Button> </Button>
@ -1184,7 +1184,7 @@ function Detail() {
{ {
<Button onClick={handleBatchImport} type="primary" style={{ marginTop: 16, marginLeft: 16 }}>批量添加</Button> <Button onClick={handleBatchImport} type="primary" style={{ marginTop: 16, marginLeft: 16 }}>批量添加</Button>
} }
</Form.Item> </Form.Item> */}
{/* <Button type="primary" htmlType="submit" style={{ marginTop: 16, float: "right", marginRight: "20%" }}> {/* <Button type="primary" htmlType="submit" style={{ marginTop: 16, float: "right", marginRight: "20%" }}>
{t('Save')} {t('Save')}
@ -1227,7 +1227,7 @@ function Detail() {
</div> </div>
</Flex> </Flex>
<Modal {/* <Modal
title='批量设置价格' title='批量设置价格'
open={batchImportPriceVisible} open={batchImportPriceVisible}
onOk={handleBatchImportOK} onOk={handleBatchImportOK}
@ -1235,7 +1235,7 @@ function Detail() {
width={'90%'} width={'90%'}
> >
<BatchImportPrice onBatchImportData={handleBatchImportData} /> <BatchImportPrice onBatchImportData={handleBatchImportData} />
</Modal> </Modal> */}
<Modal <Modal
title="增加新产品" title="增加新产品"
@ -1262,7 +1262,7 @@ function Detail() {
onChange={(e) => setAddProductName(e.target.value)} onChange={(e) => setAddProductName(e.target.value)}
/> />
</Modal> </Modal>
{/*
<Modal <Modal
title="编辑供应商报价" title="编辑供应商报价"
visible={quotationTableVisible} visible={quotationTableVisible}
@ -1326,7 +1326,7 @@ function Detail() {
{day} {day}
</Button> </Button>
))} ))}
</Modal> </Modal> */}
</div>} </div>}
</SecondHeaderWrapper> </SecondHeaderWrapper>
); );

@ -141,7 +141,7 @@ const Header = ({ refresh, ...props }) => {
</RequireAuth> </RequireAuth>
<RequireAuth subject={PERM_PRODUCTS_OFFER_PUT}> <RequireAuth subject={PERM_PRODUCTS_OFFER_PUT}>
<Button size='small' type={'primary'} onClick={props.handleSubmitForAudit}> <Button size='small' type={'primary'} onClick={props.handleSubmitForAudit}>
提交审核 {t('Submit')}{t('Audit')}
</Button> </Button>
</RequireAuth> </RequireAuth>
</div> </div>

@ -16,6 +16,7 @@ import { HT_HOST } from '@/config';
import { useProductsTypesMapVal, useProductsTypesFieldsets } from '@/hooks/useProductsSets'; import { useProductsTypesMapVal, useProductsTypesFieldsets } from '@/hooks/useProductsSets';
import useProductsStore from '@/stores/Products/Index'; import useProductsStore from '@/stores/Products/Index';
import ProductInfoLgc from './ProductInfoLgc'; import ProductInfoLgc from './ProductInfoLgc';
import ProductInfoQuotation from './ProductInfoQuotation';
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
@ -23,8 +24,6 @@ const InfoForm = ({ formInstance, onSubmit, onReset, onValuesChange, editable, s
const { t } = useTranslation('products'); const { t } = useTranslation('products');
const [agencyProducts, editingProduct, setEditingProduct] = useProductsStore((state) => [state.agencyProducts, state.editingProduct, state.setEditingProduct]); const [agencyProducts, editingProduct, setEditingProduct] = useProductsStore((state) => [state.agencyProducts, state.editingProduct, state.setEditingProduct]);
const weekdays = useWeekdays(); const weekdays = useWeekdays();
// const [formValues, setFormValues] = useFormStore((state) => [state.formValues, state.setFormValues]);
// const [formValuesToSub, setFormValuesToSub] = useFormStore((state) => [state.formValuesToSub, state.setFormValuesToSub]);
const [form] = Form.useForm(); const [form] = Form.useForm();
const { sort, hides, fieldProps, fieldComProps } = { const { sort, hides, fieldProps, fieldComProps } = {
sort: '', sort: '',
@ -37,45 +36,12 @@ const InfoForm = ({ formInstance, onSubmit, onReset, onValuesChange, editable, s
const filedsets = useProductsTypesFieldsets(editingProduct?.info?.product_type_id); const filedsets = useProductsTypesFieldsets(editingProduct?.info?.product_type_id);
const shows = filedsets[0]; const shows = filedsets[0];
// console.log('filedsets', filedsets, shows); // console.log('filedsets', filedsets, shows);
const formValuesMapper = (values) => {
const destinationObject = {
'keyword': { key: 'keyword', transform: (value) => value || '' },
'referenceNo': { key: 'referenceNo', transform: (value) => value || '' },
'dates': [
{ key: 'startdate', transform: (arrVal) => (arrVal ? arrVal[0].format(DATE_FORMAT) : '') },
{ key: 'enddate', transform: (arrVal) => (arrVal ? arrVal[1].format(DATE_FORMAT) : '') },
{ key: 'starttime', transform: (arrVal) => (arrVal ? arrVal[0].format(DATE_FORMAT) : '') },
{ key: 'endtime', transform: (arrVal) => (arrVal ? arrVal[1].format(SMALL_DATETIME_FORMAT) : '') },
],
'invoiceStatus': { key: 'invoiceStatus', transform: (value) => value?.value || value?.key || '', default: '' },
'audit_state': { key: 'audit_state', transform: (value) => value?.value || value?.key || '', default: '' },
'agency': {
key: 'agency',
transform: (value) => {
return Array.isArray(value) ? value.map((ele) => ele.key).join(',') : value ? value.value : '';
},
},
'year': [{ key: 'year', transform: (arrVal) => (arrVal ? arrVal.format('YYYY') : '') }],
};
let dest = {};
const { dates, ...omittedValue } = values;
dest = { ...omittedValue, ...objectMapper(values, destinationObject) };
for (const key in dest) {
if (Object.prototype.hasOwnProperty.call(dest, key)) {
dest[key] = typeof dest[key] === 'string' ? (dest[key] || '').trim() : dest[key];
}
}
// omit empty
// Object.keys(dest).forEach((key) => (dest[key] == null || dest[key] === '' || dest[key].length === 0) && delete dest[key]);
return dest;
};
useEffect(() => { useEffect(() => {
// const dest = formValuesMapper(formValues); // const dest = formValuesMapper(formValues);
// setFormValuesToSub(dest);
form.resetFields(); form.resetFields();
form.setFieldsValue(editingProduct?.info); // form.setFieldsValue(editingProduct?.info);
form.setFieldValue('city', { value: editingProduct?.info?.city_id, label: editingProduct?.info?.city_name }); form.setFieldValue('city', { value: editingProduct?.info?.city_id, label: editingProduct?.info?.city_name });
form.setFieldValue('dept', { value: editingProduct?.info?.dept_id, label: editingProduct?.info?.dept_name });
// form.setFieldValue('open_weekdays', ['1', '2', '3', '4', '5', '6', '7']); // form.setFieldValue('open_weekdays', ['1', '2', '3', '4', '5', '6', '7']);
return () => {}; return () => {};
}, [editingProduct?.info?.id]); }, [editingProduct?.info?.id]);
@ -85,8 +51,6 @@ const InfoForm = ({ formInstance, onSubmit, onReset, onValuesChange, editable, s
const dest = formValuesMapper(values); const dest = formValuesMapper(values);
console.log('form value send to onSubmit:\n', dest); console.log('form value send to onSubmit:\n', dest);
const str = new URLSearchParams(dest).toString(); const str = new URLSearchParams(dest).toString();
// setFormValues(values);
// setFormValuesToSub(dest);
if (typeof onSubmit === 'function') { if (typeof onSubmit === 'function') {
onSubmit(null, dest, values, str); onSubmit(null, dest, values, str);
} }
@ -102,8 +66,6 @@ const InfoForm = ({ formInstance, onSubmit, onReset, onValuesChange, editable, s
}; };
const onIValuesChange = (changedValues, allValues) => { const onIValuesChange = (changedValues, allValues) => {
const dest = formValuesMapper(allValues); const dest = formValuesMapper(allValues);
// setFormValues(allValues);
// setFormValuesToSub(dest);
// console.log('form onValuesChange', Object.keys(changedValues), args); // console.log('form onValuesChange', Object.keys(changedValues), args);
if (typeof onValuesChange === 'function') { if (typeof onValuesChange === 'function') {
onValuesChange(dest); onValuesChange(dest);
@ -111,7 +73,7 @@ const InfoForm = ({ formInstance, onSubmit, onReset, onValuesChange, editable, s
}; };
return ( return (
<> <>
<Form form={form} disabled={!(editable || false)} name={formName || 'product_info'} onFinish={onFinish} onValuesChange={onIValuesChange}> <Form form={form} disabled={!(editable || false)} name={formName || 'product_info'} onFinish={onFinish} onValuesChange={onIValuesChange} initialValues={editingProduct?.info}>
<Row gutter={16}> <Row gutter={16}>
{getFields({ sort, initialValue: editingProduct?.info, hides, shows, fieldProps, fieldComProps, form, t, dataSets: { weekdays } })} {getFields({ sort, initialValue: editingProduct?.info, hides, shows, fieldProps, fieldComProps, form, t, dataSets: { weekdays } })}
{/* {showSubmit && ( {/* {showSubmit && (
@ -127,6 +89,7 @@ const InfoForm = ({ formInstance, onSubmit, onReset, onValuesChange, editable, s
{/* <Divider className='my-1' /> */} {/* <Divider className='my-1' /> */}
<ProductInfoLgc formInstance={form} /> <ProductInfoLgc formInstance={form} />
<ProductInfoQuotation formInstance={form} />
<Form.Item hidden name={'id'} label={'ID'}> <Form.Item hidden name={'id'} label={'ID'}>
<Input /> <Input />
@ -174,7 +137,7 @@ function getFields(props) {
item( item(
'code', 'code',
99, 99,
<Form.Item name='code' label={t('Code')} {...fieldProps.code} initialValue={at(props, 'initialValue.code')[0]}> <Form.Item name='code' label={t('Code')} {...fieldProps.code} _initialValue={at(props, 'initialValue.code')[0]}>
<Input allowClear {...fieldComProps.code} /> <Input allowClear {...fieldComProps.code} />
</Form.Item>, </Form.Item>,
fieldProps?.code?.col || 8 fieldProps?.code?.col || 8
@ -182,7 +145,7 @@ function getFields(props) {
item( item(
'city', // todo: 'city', // todo:
99, 99,
<Form.Item name='city' label={t('City')} {...fieldProps.city} initialValue={at(props, 'initialValue.city')[0]}> <Form.Item name='city' label={t('City')} {...fieldProps.city} _initialValue={at(props, 'initialValue.city')[0]}>
<CitySelector /> <CitySelector />
</Form.Item>, </Form.Item>,
fieldProps?.city?.col || 8 fieldProps?.city?.col || 8
@ -231,15 +194,6 @@ function getFields(props) {
</Form.Item>, </Form.Item>,
fieldProps?.recommends_rate?.col || 8 fieldProps?.recommends_rate?.col || 8
), ),
item(
'open_weekdays',
99,
<Form.Item name='open_weekdays' label={t('OpenWeekdays')} initialValue={['1', '2', '3', '4', '5', '6', '7']} {...fieldProps.open_weekdays}>
{/* 默认全部 */}
<Checkbox.Group options={dataSets.weekdays} />
</Form.Item>,
fieldProps?.open_weekdays?.col || 24
),
item( item(
'display_to_c', 'display_to_c',
99, 99,
@ -272,6 +226,15 @@ function getFields(props) {
</Form.Item>, </Form.Item>,
fieldProps?.display_to_c?.col || 8 fieldProps?.display_to_c?.col || 8
), ),
item(
'open_weekdays',
99,
<Form.Item name='open_weekdays' label={t('OpenWeekdays')} initialValue={['1', '2', '3', '4', '5', '6', '7']} {...fieldProps.open_weekdays}>
{/* 默认全部 */}
<Checkbox.Group options={dataSets.weekdays} />
</Form.Item>,
fieldProps?.open_weekdays?.col || 24
),
item( item(
'remarks', 'remarks',
99, 99,
@ -327,5 +290,38 @@ function getFields(props) {
} }
return children; return children;
} }
const formValuesMapper = (values) => {
const destinationObject = {
'keyword': { key: 'keyword', transform: (value) => value || '' },
'referenceNo': { key: 'referenceNo', transform: (value) => value || '' },
'dates': [
{ key: 'startdate', transform: (arrVal) => (arrVal ? arrVal[0].format(DATE_FORMAT) : '') },
{ key: 'enddate', transform: (arrVal) => (arrVal ? arrVal[1].format(DATE_FORMAT) : '') },
{ key: 'starttime', transform: (arrVal) => (arrVal ? arrVal[0].format(DATE_FORMAT) : '') },
{ key: 'endtime', transform: (arrVal) => (arrVal ? arrVal[1].format(SMALL_DATETIME_FORMAT) : '') },
],
'invoiceStatus': { key: 'invoiceStatus', transform: (value) => value?.value || value?.key || '', default: '' },
'audit_state': { key: 'audit_state', transform: (value) => value?.value || value?.key || '', default: '' },
'agency': {
key: 'agency',
transform: (value) => {
return Array.isArray(value) ? value.map((ele) => ele.key).join(',') : value ? value.value : '';
},
},
'year': [{ key: 'year', transform: (arrVal) => (arrVal ? arrVal.format('YYYY') : '') }],
};
let dest = {};
const { dates, ...omittedValue } = values;
dest = { ...omittedValue, ...objectMapper(values, destinationObject) };
for (const key in dest) {
if (Object.prototype.hasOwnProperty.call(dest, key)) {
dest[key] = typeof dest[key] === 'string' ? (dest[key] || '').trim() : dest[key];
}
}
// omit empty
// Object.keys(dest).forEach((key) => (dest[key] == null || dest[key] === '' || dest[key].length === 0) && delete dest[key]);
return dest;
};
export default InfoForm; export default InfoForm;

@ -143,7 +143,7 @@ const ProductInfoLgc = ({ formInstance, ...props }) => {
return ( return (
<> <>
<Form.List name={'lgc_details'}> <Form.List name={'lgc_details'}>
{(fields, { add, remove }) => <Tabs type='editable-card' size='small' onChange={onChange} activeKey={activeKey} onEdit={onEdit} items={items} />} {(fields, { add, remove }) => <Tabs type='editable-card' size='small' onChange={onChange} activeKey={activeKey} onEdit={onEdit} items={items} hideAdd={isEmpty(lgcOptions)} tabPosition='top' />}
</Form.List> </Form.List>
<Modal title='选择语言' open={newLgcModalVisible} onOk={handleOk} onCancel={() => setNewLgcModalVisible(false)}> <Modal title='选择语言' open={newLgcModalVisible} onOk={handleOk} onCancel={() => setNewLgcModalVisible(false)}>
<Select <Select

@ -0,0 +1,220 @@
import { createContext, useEffect, useState } from 'react';
import { Table, Form, Modal, Button, InputNumber, Select, DatePicker } from 'antd';
import { useTranslation } from 'react-i18next';
import dayjs from 'dayjs';
import BatchImportPrice from './BatchImportPrice';
import { useDatePresets } from '@/hooks/useDatePresets';
const { RangePicker } = DatePicker;
const ProductInfoQuotation = ({ formInstance, ...props }) => {
const { t } = useTranslation();
const presets = useDatePresets();
const [batchImportPriceVisible, setBatchImportPriceVisible] = useState(false);
const [quotationTableVisible, setQuotationTableVisible] = useState(false);
const [editIndex, setEditIndex] = useState(null);
const [quotation, setQuotation] = useState([]);
const [batchImportData, setBatchImportData] = useState([]);
const [weekdays, setWeekdays] = useState([]);
const [selectedDays, setSelectedDays] = useState([]);
const [currentQuotationRecord, setCurrentQuotationRecord] = useState({
use_dates_start: null,
use_dates_end: null,
});
const edit = (record, index) => {
setQuotationTableVisible(true);
setEditIndex(index);
setCurrentQuotationRecord(record);
};
const handleAdd = () => {
const newData = {
adult_cost: 0,
child_cost: 0,
currency: '',
group_size_min: 0,
group_size_max: 0,
id: '',
lastedit_changed: '',
use_dates_start: '',
use_dates_end: '',
weekdays: '',
tempKey: Math.random(),
};
setQuotation([...quotation, newData]);
const index = [...quotation, newData].length - 1;
edit(newData, index);
};
const handleBatchImportData = (data) => {
setBatchImportData(data);
};
const handleBatchImport = () => {
setBatchImportPriceVisible(true);
};
const handleBatchImportOK = () => {
const tempBatchImportData = batchImportData.map((item) => {
const { tag, validPeriod, ...rest } = item;
return rest;
});
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;
});
setQuotation(sortedData);
setBatchImportPriceVisible(false);
};
const quotationTableVisibleOK = () => {
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');
const tempQuotation = [...quotation];
tempQuotation[editIndex] = { ...currentQuotationRecord, weekdays: weekdays };
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 aGroupSize = a.group_size_max - a.group_size_min;
const bGroupSize = b.group_size_max - b.group_size_min;
return aGroupSize - bGroupSize;
});
setQuotation(sortedData);
setQuotationTableVisible(false);
};
const quotationTableVisibleCancel = () => {
setQuotationTableVisible(false);
};
const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
const handleDayClick = (dayIndex) => {
const dayOfWeek = (dayIndex % 7) + 1;
setSelectedDays((prevSelectedDays) => {
const updatedDays = prevSelectedDays.includes(dayOfWeek) ? prevSelectedDays.filter((d) => d !== dayOfWeek) : [...prevSelectedDays, dayOfWeek];
const weekdaysString = updatedDays.sort().join(',');
setWeekdays(weekdaysString);
return updatedDays;
});
};
const columns = [
{ title: t('products:adultPrice'), dataIndex: 'adult_cost', width: '10%', editable: true },
{ title: t('products:childrenPrice'), dataIndex: 'child_cost', width: '10%', editable: true },
{ title: t('products:currency'), dataIndex: 'currency', width: '10%', editable: true },
{
title: t('products:Types'),
dataIndex: 'unit',
width: '10%',
editable: true,
render: (text) => (text === '0' ? '每人' : text === '1' ? '每团' : text),
},
{
title: t('products:number'),
dataIndex: 'group_size',
width: '20%',
editable: true,
render: (_, record) => `${record.group_size_min}-${record.group_size_max}`,
},
{
title: t('products:validityPeriod'),
dataIndex: 'validityPeriod',
width: '20%',
editable: true,
render: (_, record) => `${record.use_dates_start}-${record.use_dates_end}`,
},
{ title: t('products:Weekdays'), dataIndex: 'weekdays', width: '10%' },
];
return (
<>
<h2>{t('products:EditComponents.Quotation')}</h2>
<Form.Item name='quotation'>
<Table
rowKey={'tempKey'}
bordered
dataSource={quotation}
columns={columns}
rowClassName='editable-row'
// pagination={{ onChange: cancel }}
/>
{
// !isCanEditable &&
<Button onClick={handleAdd} type='primary' ghost style={{ marginTop: 16 }}>
{t('products:addQuotation')}
</Button>
}
{
<Button onClick={handleBatchImport} type='primary' ghost style={{ marginTop: 16, marginLeft: 16 }}>
批量添加
</Button>
}
</Form.Item>
<Modal title='批量设置价格' open={batchImportPriceVisible} onOk={handleBatchImportOK} onCancel={() => setBatchImportPriceVisible(false)} width={'90%'}>
<BatchImportPrice onBatchImportData={handleBatchImportData} />
</Modal>
<Modal title='编辑供应商报价' open={quotationTableVisible} onOk={quotationTableVisibleOK} onCancel={quotationTableVisibleCancel}>
<h3>成人价</h3>
<InputNumber value={currentQuotationRecord.adult_cost} onChange={(e) => setCurrentQuotationRecord({ ...currentQuotationRecord, adult_cost: e })} />
<h3>儿童价</h3>
<InputNumber value={currentQuotationRecord.child_cost} onChange={(e) => setCurrentQuotationRecord({ ...currentQuotationRecord, child_cost: e })} />
<h3>币种</h3>
<Select style={{ width: '30%' }} value={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} onChange={(e) => setCurrentQuotationRecord({ ...currentQuotationRecord, unit: e })}>
<Select.Option value='0'>每人</Select.Option>
<Select.Option value='1'>每团</Select.Option>
</Select>
<h3>人等</h3>
<td style={{ display: 'flex', alignItems: 'center' }}>
<InputNumber
min={0}
value={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={(e) => setCurrentQuotationRecord({ ...currentQuotationRecord, group_size_max: e })}
style={{ width: '50%', marginLeft: '10px' }}
/>
</td>
<h3>有效期</h3>
<RangePicker
allowClear={true}
inputReadOnly={true}
presets={presets}
placeholder={['From', 'Thru']}
// value={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((index % 7) + 1) ? 'primary' : 'default'} onClick={() => handleDayClick(index)} style={{ margin: '5px' }}>
{day}
</Button>
))}
</Modal>
</>
);
};
export default ProductInfoQuotation;

@ -1,10 +1,10 @@
import { createContext, useEffect, useState } from 'react'; import { createContext, useEffect, useState } from 'react';
import { Tree, Input } from 'antd'; import { Tree, Input } from 'antd';
import { CaretDownOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import useProductsStore from '@/stores/Products/Index'; import useProductsStore from '@/stores/Products/Index';
import { useProductsTypes, useProductsAuditStatesMapVal } from '@/hooks/useProductsSets'; import { useProductsTypes, useProductsAuditStatesMapVal } from '@/hooks/useProductsSets';
const flattenTreeFun = (tree) => { const flattenTreeFun = (tree) => {
let flatList = []; let flatList = [];
const flatten = (nodes) => { const flatten = (nodes) => {
@ -57,7 +57,7 @@ const ProductsTree = ({ onNodeSelect, ...props }) => {
...ele, ...ele,
title: ele.label, title: ele.label,
key: ele.value, key: ele.value,
children: (agencyProducts[ele.value] || []).map(product => ({ children: (agencyProducts[ele.value] || []).map((product) => ({
title: product.info.title, title: product.info.title,
// key: `${ele.value}-${product.info.id}`, // key: `${ele.value}-${product.info.id}`,
key: product.info.id, key: product.info.id,
@ -68,18 +68,18 @@ const ProductsTree = ({ onNodeSelect, ...props }) => {
setRawTreeData(_show); setRawTreeData(_show);
setFlattenTreeData(flattenTreeFun(_show)); setFlattenTreeData(flattenTreeFun(_show));
setExpandedKeys(productsTypes.map(item => item.key)); // setExpandedKeys(productsTypes.map((item) => item.key)); //
// setActiveKey(isEmpty(_show) ? [] : [_show[0].key]); // setActiveKey(isEmpty(_show) ? [] : [_show[0].key]);
return () => {}; return () => {};
}, [productsTypes, agencyProducts]); }, [productsTypes, agencyProducts]);
const [searchValue, setSearchValue] = useState(''); const [searchValue, setSearchValue] = useState('');
const onSearch = ({target: {value}}) => { const onSearch = ({ target: { value } }) => {
// const { value } = e.target; // const { value } = e.target;
const newExpandedKeys = flattenTreeData const newExpandedKeys = flattenTreeData
.filter(item => item.title.includes(value)) .filter((item) => item.title.includes(value))
.map(item => getParentKey(item.key, rawTreeData)) .map((item) => getParentKey(item.key, rawTreeData))
.filter((item, i, self) => item && self.indexOf(item) === i); .filter((item, i, self) => item && self.indexOf(item) === i);
setExpandedKeys(newExpandedKeys); setExpandedKeys(newExpandedKeys);
setSearchValue(value); setSearchValue(value);
@ -92,18 +92,6 @@ const ProductsTree = ({ onNodeSelect, ...props }) => {
if (typeof onNodeSelect === 'function') { if (typeof onNodeSelect === 'function') {
onNodeSelect(_, { node }); onNodeSelect(_, { node });
} }
// setSelectedNodeid(node.key);
// const fatherKey = node.key.split('-')[0];
// setSelectedCategory(productProject[fatherKey]);
// setTags([languageLabel]);
// //
// if (selectedNodeid === node.key) return;
// setLanguageStatus(language);
// const matchedLanguage = HTLanguageSets.find(HTLanguage => HTLanguage.key === language.toString());
// const languageLabelRefresh = matchedLanguage.label;
// setLanguageLabel(languageLabelRefresh);
// setSelectedTag(languageLabelRefresh);
// setRemainderLanguage(HTLanguageSets.filter(item => item.key !== language.toString()));
}; };
const onExpand = (keys) => { const onExpand = (keys) => {
setExpandedKeys(keys); setExpandedKeys(keys);
@ -114,9 +102,7 @@ const ProductsTree = ({ onNodeSelect, ...props }) => {
const index = node.title.indexOf(searchValue); const index = node.title.indexOf(searchValue);
const beforeStr = node.title.substr(0, index); const beforeStr = node.title.substr(0, index);
const afterStr = node.title.substr(index + searchValue.length); const afterStr = node.title.substr(index + searchValue.length);
const highlighted = ( const highlighted = <span style={{ color: 'red' }}>{searchValue}</span>;
<span style={{ color: 'red' }}>{searchValue}</span>
);
return index > -1 ? ( return index > -1 ? (
<span> <span>
@ -132,7 +118,10 @@ const ProductsTree = ({ onNodeSelect, ...props }) => {
return ( return (
<div className={`${props.className} relative`} style={props.style}> <div className={`${props.className} relative`} style={props.style}>
<Input.Search placeholder='Search' onChange={onSearch} allowClear className='sticky top-1 z-20 mb-3' /> <Input.Search placeholder='Search' onChange={onSearch} allowClear className='sticky top-1 z-20 mb-3' />
<Tree blockNode <Tree
blockNode
showLine
switcherIcon={<CaretDownOutlined />}
onSelect={handleNodeSelect} onSelect={handleNodeSelect}
treeData={treeData} treeData={treeData}
expandedKeys={expandedKeys} expandedKeys={expandedKeys}

Loading…
Cancel
Save