diff --git a/src/components/date.jsx b/src/components/date.jsx index fec0402..ecc674f 100644 --- a/src/components/date.jsx +++ b/src/components/date.jsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { DatePicker, Button } from 'antd'; -const DateComponent = ({ onDateChange }) => { +const Date = ({ onDateChange }) => { const dateFormat = 'YYYY/MM/DD'; const { RangePicker } = DatePicker; const [dateRange, setDateRange] = useState(null); @@ -48,4 +48,4 @@ const DateComponent = ({ onDateChange }) => { ); }; -export default DateComponent; +export default Date; diff --git a/src/views/products/Detail.jsx b/src/views/products/Detail.jsx index 8f35b06..74bac6a 100644 --- a/src/views/products/Detail.jsx +++ b/src/views/products/Detail.jsx @@ -1,8 +1,8 @@ -import React, { useState, useEffect, useRef,useMemo } from 'react'; +import React, { useState, useEffect, useRef, useMemo } from 'react'; import { Button, Card, Col, Row, Breadcrumb, Table, Popconfirm, Form, Input, InputNumber, Tag, Modal, Select, Tree } from 'antd'; import { Link } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; -import DateComponent from '@/components/date'; +import Date from '@/components/date'; import { searchAgencyAction, getAgencyProductsAction } from '@/stores/Products/Index'; import { useProductsTypes } from '@/hooks/useProductsSets'; import Extras from './Detail/Extras'; @@ -10,7 +10,7 @@ import { groupBy } from '@/utils/commons'; import { useParams } from 'react-router-dom'; import { useHTLanguageSets } from '@/hooks/useHTLanguageSets'; import { useDefaultLgc } from '@/i18n/LanguageSwitcher'; -function Index() { +function Detail() { const { t } = useTranslation(); const [form] = Form.useForm(); const [editingid, setEditingid] = useState(''); @@ -28,11 +28,70 @@ function Index() { const productsTypes = useProductsTypes(); const [productsData, setProductsData] = useState(null); const [quotation, setQuotation] = useState(null); - const [lgc_details,setLgc_details] = useState(null); - const [languageLabel,setLanguageLabel] = useState(null); + const [lgc_details, setLgc_details] = useState(null); + const [languageLabel, setLanguageLabel] = useState(null); const { travel_agency_id } = useParams(); - const {language} = useDefaultLgc(); + const { language } = useDefaultLgc(); const HTLanguageSets = useHTLanguageSets(); + const { Search } = Input; + + + const [expandedKeys, setExpandedKeys] = useState([]); + const [searchValue, setSearchValue] = useState(''); + const [autoExpandParent, setAutoExpandParent] = useState(true); + const [dataList, setDataList] = useState([]); + const [defaultData, setDefaultData] = useState([]); + + + const productProject = { + "6": [], + "B": [ + { code: "code", name: t('products:Code') }, + { code: "city_name", name: t('products:City') }, + { code: "km", name: t('products:KM') }, + { code: "remarks", name: t('products:Remarks') } + ], + "J": [ + { code: "code", name: t('products:Code') }, + { code: "city_name", name: t('products:City') }, + { code: "recommends_rate", name: t('products:recommendationRate') }, + { code: "duration", name: t('products:Duration') }, + { code: "dept_name", name: t('products:Dept') }, + { code: "display_to_c", name: t('products:DisplayToC') }, + { code: "remarks", name: t('products:Remarks') }, + ], + "Q": [ + { code: "code", name: t('products:Code') }, + { code: "city_name", name: t('products:City') }, + { code: "recommends_rate", name: t('products:recommendationRate') }, + { code: "duration", name: t('products:Duration') }, + { code: "dept_name", name: t('products:Dept') }, + { code: "display_to_c", name: t('products:DisplayToC') }, + { code: "remarks", name: t('products:Remarks') }, + ], + "D": [ + { code: "code", name: t('products:Code') }, + { code: "city_name", name: t('products:City') }, + { code: "recommends_rate", name: t('products:recommendationRate') }, + { code: "duration", name: t('products:Duration') }, + { code: "dept_name", name: t('products:Dept') }, + { code: "display_to_c", name: t('products:DisplayToC') }, + { code: "remarks", name: t('products:Remarks') }, + ], + "7": [ + { code: "code", name: t('products:Code') }, + { code: "city_name", name: t('products:City') }, + { code: "recommends_rate", name: t('products:recommendationRate') }, + { code: "duration", name: t('products:Duration') }, + { code: "open_weekdays", name: t('products:OpenWeekdays') }, + { code: "remarks", name: t('products:Remarks') }, + ], + "R": [ + { code: "code", name: t('products:Code') }, + { code: "city_name", name: t('products:City') }, + ] + } + const [selectedCategory, setSelectedCategory] = useState(productProject.B); useEffect(() => { setLanguageStatus(language); @@ -43,43 +102,116 @@ function Index() { setRemainderLanguage(HTLanguageSets.filter(item => item.key !== language.toString())) }, []); - - - const fetchData = async () => { - const a = { travel_agency_id }; - const res = await getAgencyProductsAction(a); - const groupedProducts = groupBy(res.products, (row) => row.info.product_type_id); - - const generateTreeData = (productsTypes, productsData) => { - return productsTypes.map(type => ({ - title: type.label, - key: type.value, - selectable: false, - children: (productsData[type.value] || []).map(product => ({ - title: product.info.title, - key: `${type.value}-${product.info.id}`, - })) - })); - }; - const treeData = generateTreeData(productsTypes, groupedProducts); - setProductsData(groupedProducts); - setTreeData1(treeData); - }; - + useEffect(() => { + const fetchData = async () => { + const a = { travel_agency_id }; + const res = await getAgencyProductsAction(a); + const groupedProducts = groupBy(res.products, (row) => row.info.product_type_id); + + const generateTreeData = (productsTypes, productsData) => { + return productsTypes.map(type => ({ + title: type.label, + key: type.value, + selectable: false, + children: (productsData[type.value] || []).map(product => ({ + title: product.info.title, + key: `${type.value}-${product.info.id}`, + })) + })); + }; + + const treeData = generateTreeData(productsTypes, groupedProducts); + console.log("treeData", treeData) + setTreeData1(treeData); + setProductsData(groupedProducts); + setDefaultData(treeData); + setDataList(flattenTreeData(treeData)); + }; + fetchData(); }, [productsTypes]); + const flattenTreeData = (tree) => { + let flatList = []; + const flatten = (nodes) => { + nodes.forEach((node) => { + flatList.push({ title: node.title, key: node.key }); + if (node.children) { + flatten(node.children); + } + }); + }; + flatten(tree); + return flatList; + }; + + const getParentKey = (key, tree) => { + let parentKey; + for (let i = 0; i < tree.length; i++) { + const node = tree[i]; + if (node.children) { + if (node.children.some((item) => item.key === key)) { + parentKey = node.key; + } else { + const pKey = getParentKey(key, node.children); + if (pKey) { + parentKey = pKey; + } + } + } + } + return parentKey; + }; + + const titleRender = (node) => { + const index = node.title.indexOf(searchValue); + const beforeStr = node.title.substr(0, index); + const afterStr = node.title.substr(index + searchValue.length); + const highlighted = ( + {searchValue} + ); + + return index > -1 ? ( + + {beforeStr} + {highlighted} + {afterStr} + + ) : ( + {node.title} + ); + }; + + const onChange = (e) => { + const { value } = e.target; + const newExpandedKeys = dataList + .filter(item => item.title.includes(value)) + .map(item => getParentKey(item.key, defaultData)) + .filter((item, i, self) => item && self.indexOf(item) === i); + console.log("newExpandedKeys", newExpandedKeys) + setExpandedKeys(newExpandedKeys); + setSearchValue(value); + setAutoExpandParent(true); + }; + + const onExpand = (keys) => { + setExpandedKeys(keys); + 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 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; @@ -330,8 +462,8 @@ function Index() { const key = matchedLanguage ? matchedLanguage.key : null; form.setFieldsValue({ lgc_details: { - title: lgc_details[key] ? lgc_details[key].title : '', - descriptions: lgc_details[key] ? lgc_details[key].descriptions : '' + title: lgc_details[key] ? lgc_details[key].title : '', + descriptions: lgc_details[key] ? lgc_details[key].descriptions : '' } }); setLanguageStatus(key) @@ -342,7 +474,7 @@ function Index() { const handleOk = () => { - setTags([...tags,selectedTag]) + setTags([...tags, selectedTag]) console.log("handleOkvalue") setIsModalVisible(false); @@ -352,46 +484,32 @@ function Index() { const handleTagChange = (value) => { - console.log("handleTagChange",value) + console.log("handleTagChange", value) setSelectedTag(value); - console.log("setSelectedTag",selectedTag) - // setLanguageStatus() - - - // if (!tags.includes(value)) { - // setTags([...tags, value]); - // setLanguageStatus([...languageStatus, { [value]: { title: "", descriptions: "" } }]); - // } - // setSelectedTag(value); - // setIsModalVisible(false); + console.log("setSelectedTag", selectedTag) }; const handleChange = (field, value) => { - console.log("languageStatus",languageStatus) - console.log("...lgc_details[languageStatus]",{...lgc_details[languageStatus]}) - // 更新整个 lgc_details 对象 - const updatedLgcDetails = { - ...lgc_details, - [languageStatus]:{...lgc_details[languageStatus],[field]: value,lgc:languageStatus} - }; - setLgc_details(updatedLgcDetails) - console.log("AAAAAAAAAAAAAA", lgc_details); - - }; + console.log("languageStatus", languageStatus) + console.log("...lgc_details[languageStatus]", { ...lgc_details[languageStatus] }) + // 更新整个 lgc_details 对象 + const updatedLgcDetails = { + ...lgc_details, + [languageStatus]: { ...lgc_details[languageStatus], [field]: value, lgc: languageStatus } + }; + setLgc_details(updatedLgcDetails) + console.log("AAAAAAAAAAAAAA", lgc_details); - const findLanguageDetails = (tag) => { - const lang = languageStatus.find(lang => lang[tag]); - return lang ? lang[tag] : { title: "", descriptions: "" }; }; - //树组件方法 const handleNodeSelect = (_, { node }) => { setTags([languageLabel]) // 如果点击的是同一个节点,不做任何操作 if (selectedNodeid === node.key) return; - const fatherKey = node.key.split('-')[0]; + console.log("fatherKey", fatherKey) + setSelectedCategory(productProject[fatherKey]) let initialQuotationData = null; let infoData = null; let lgcDetailsData = null; @@ -403,38 +521,43 @@ function Index() { return true; } }); - + + console.log("infoData", infoData) + // 累积 lgc_details 数据 let newLgcDetails = {}; lgcDetailsData.forEach(element => { newLgcDetails[element.lgc] = element; }); - + // 一次性更新 lgc_details setLgc_details(newLgcDetails); - + setQuotation(initialQuotationData); - - console.log("descriptions",lgc_details) + + console.log("descriptions", lgc_details) // 使用 setTimeout 确保 lgc_details 已经更新 - form.setFieldsValue({ - info: { - title: infoData.title, - code: infoData.code, - product_type_name: infoData.product_type_name, - city_name: infoData.city_name, - remarks: infoData.remarks, - open_weekdays: infoData.open_weekdays, - recommends_rate: infoData.recommends_rate, - unit_name: infoData.unit_name - }, - lgc_details: { - title: newLgcDetails[language]?.title || '', - descriptions: newLgcDetails[language]?.descriptions || '' - } - }); + form.setFieldsValue({ + info: { + title: infoData.title, + code: infoData.code, + product_type_name: infoData.product_type_name, + city_name: infoData.city_name, + remarks: infoData.remarks, + open_weekdays: infoData.open_weekdays, + recommends_rate: infoData.recommends_rate, + duration: infoData.duration, + dept: infoData.dept, + km: infoData.km, + dept_name: infoData.dept_name + }, + lgc_details: { + title: newLgcDetails[language]?.title || '', + descriptions: newLgcDetails[language]?.descriptions || '' + } + }); }; - + @@ -450,182 +573,28 @@ function Index() { }; - //绑定产品 - const initBindingData = [ - { id: '1', title: '英文导游', value: "100", age_type: '每人' }, - { id: '2', title: '中文导游', value: "200", age_type: '每团' }, - { id: '3', title: '可陪餐费', value: "400", age_type: '每人' }, - ] - const [bindingData, setBindingData] = useState(initBindingData); - const isEditingBinding = (record) => record.id === editingidBinding; - const [editingidBinding, setEditingidBinding] = useState(''); - - const editBinding = (record) => { - form.setFieldsValue({ ...record }); - setEditingidBinding(record.id); - }; - const cancelBinding = () => { - setEditingidBinding(''); - }; - const EditableCellBinding = ({ - editing, - dataIndex, - title, - inputType, - record, - index, - children, - ...restProps - }) => { - let inputNode = inputType === 'number' ? : ; - - if (dataIndex === 'unit_name' && editing) { - inputNode = ( - - ); - } - return ( - - {editing ? ( - - {inputNode} - - ) : ( - children - )} - - ); - }; - const bindingColums = [ - { title: t('products:Name'), dataIndex: 'title', width: '25%', editable: true }, - { title: t('products:price'), dataIndex: 'value', width: '25%', editable: true }, - { title: t('products:Types'), dataIndex: 'age_type', width: '25%', editable: true }, - { - title: t('products:operation'), - dataIndex: 'operation', - render: (_, record) => { - const editable = isEditingBinding(record); - return editable ? ( - - handleSaveBinding(record.id)} style={{ marginRight: 8 }}>{t('products:save')} - {t('products:cancel')} - - ) : ( - - editBinding(record)} style={{ marginRight: 8 }}>{t('products:edit')} - handleDeleteBinding(record.id)}> - {t('products:delete')} - - - ); - }, - }, - ].map(col => { - if (!col.editable) { - return col; - } - return { - ...col, - onCell: record => ({ - record, - inputType: col.dataIndex === 'value' ? 'number' : 'text', - dataIndex: col.dataIndex, - title: col.title, - editing: isEditingBinding(record), - }), - }; - }); - - - const handleAddBinding = () => { - const newData = { - id: `${bindingData.length + 1}`, - title: '', - value: '', - age_type: '', - }; - setBindingData([...bindingData, newData]); - setEditingidBinding(''); // 添加这一行 - }; - const handleSaveBinding = async (id) => { - try { - const row = await form.validateFields(); - const newData = [...bindingData]; - const { value, title, age_type } = row - const index = newData.findIndex((item) => id === item.id); - if (index > -1) { - const item = newData[index]; - newData.splice(index, 1, { ...item, value, title, age_type }); + //Effect - setBindingData(newData); - setEditingidBinding(''); - } else { - newData.push(row); - setBindingData(newData); - setEditingidBinding(''); - } - } catch (errInfo) { - console.log('Validate Failed:', errInfo); - } - }; - const handleDeleteBinding = (id) => { - const newData = [...bindingData]; - const index = newData.findIndex((item) => id === item.id); - newData.splice(index, 1); - setBindingData(newData); - }; - const componentsBinding = { - body: { - cell: EditableCellBinding, - }, - }; - const treeData = [ - { - title: '综费', - // id: 'zf', - selectable: false, - children: [{ title: '北京怡然假日', id: 'bjyrjr' }] - }, - { - title: '车费', - // id: 'cf', - selectable: false, - children: [ - { title: '北京', id: 'bj' }, - { title: '天津', id: 'tj' }, - { title: '北京-天津', id: 'bj-tj-3-5' } - ] - } - ] - - //Effect - useEffect(() => { - if (saveData) { - - } - }, [saveData]); return (
- + + @@ -644,14 +613,18 @@ function Index() { >

{t('products:productProject')}

- {productProject.map((item, index) => ( + {selectedCategory.map((item, index) => ( - + {item.code === "duration" ? ( + + ) : ( + + )} ))} - +
duration @@ -676,13 +649,13 @@ function Index() { optionFilterProp="children" onChange={handleTagChange} > - + { - remainderLanguage.map((value, label) => ( - - {value.label} - - )) + remainderLanguage.map((value, label) => ( + + {value.label} + + )) } @@ -690,13 +663,13 @@ function Index() { handleChange('title', e.target.value)} + onChange={(e) => handleChange('title', e.target.value)} /> handleChange('descriptions', e.target.value)} + onChange={(e) => handleChange('descriptions', e.target.value)} /> @@ -720,20 +693,6 @@ function Index() { - {/*

{t('products:bindingProducts')}

- - - - */} @@ -755,12 +714,12 @@ function Index() { onOk={handleDateOk} onCancel={() => setDatePickerVisible(false)} > - + )} ); } -export default Index; +export default Detail;