diff --git a/public/locales/en/products.json b/public/locales/en/products.json index b468364..e5e841c 100644 --- a/public/locales/en/products.json +++ b/public/locales/en/products.json @@ -48,7 +48,7 @@ "OpenHours": "Open Hours", "Duration": "Duration", "KM": "KM", - "RecommendsRate": "RecommendsRate", + "RecommendsRate": "Recommends Rate", "OpenWeekdays": "Open Weekdays", "DisplayToC": "Display To C", "Dept": "Dept", @@ -116,20 +116,64 @@ "Weekdays": "Weekdays" }, + "sureSubmitAudit": "确认提交所有产品审核? 提交后,所有产品将进入待审核流程. ", "FormTooltip": { "Type": "Product Type", "Title": "Title", "Code": "Code", - "City": "City", + "City": "起始城市,举例:北京", "Dept": "Department", - "Duration": "Duration", - "RecommendsRate": "RecommendsRate", + "Duration": "", + "RecommendsRate": "Recommends Rate", "OpenHours": "Open Hours", "OpenWeekdays": "Open Weekdays", "DisplayToC": "Display Type", - "KM": "KM", + "KM": "往返", "Description": "Description", - "Remarks": "Memo" + "Remarks": "", + "NewTitle": { + "6": "", + "B": "A点-B点,举例:桂林-龙胜", + "J": "A点-B点时长车费,举例:张家界5晚6天车费", + "Q": "城市语种导游工资单位,举例:北京英文导游工资(元/天/团)", + "7": "官方景点名称,举例:陕西历史博物馆", + "R": "普通、豪华、特色餐标,举例:普通餐标", + "8": "举例:故宫导游门票", + "D": "城市A点-B点时间包含内容,举例:北京市区一日游车导" + }, + "----Todo: 下面一组待定": "#", + "6": { + "Title": "", + "#": "" + }, + "B": { + "Title": "A点-B点,举例:桂林-龙胜", + "#": "" + }, + "J": { + "Title": "A点-B点时长车费,举例:张家界5晚6天车费", + "#": "" + }, + "Q": { + "Title": "城市语种导游工资单位,举例:北京英文导游工资(元/天/团)", + "#": "" + }, + "7": { + "Title": "官方景点名称,举例:陕西历史博物馆", + "#": "" + }, + "R": { + "Title": "普通、豪华、特色餐标,举例:普通餐标", + "#": "" + }, + "8": { + "Title": "举例:故宫导游门票", + "#": "" + }, + "D": { + "Title": "城市A点-B点时间包含内容,举例:北京市区一日游车导", + "#": "" + } }, "LgcModal": { diff --git a/public/locales/zh/products.json b/public/locales/zh/products.json index 1778f9d..37cfb4f 100644 --- a/public/locales/zh/products.json +++ b/public/locales/zh/products.json @@ -104,20 +104,32 @@ "Weekdays": "周末", "Operation": "Operation" }, - "FormTooltop": { + + "sureSubmitAudit": "确认提交所有产品审核? 提交后,所有产品将进入待审核流程. ", + "FormTooltip": { "Type": "Product Type", "Title": "Title", "Code": "Code", - "City": "City", - "dept": "Department", - "Duration": "Duration", - "RecommendsRate": "RecommendsRate", + "City": "起始城市,举例:北京", + "Dept": "Department", + "Duration": "", + "RecommendsRate": "Recommends Rate", "OpenHours": "Open Hours", "OpenWeekdays": "Open Weekdays", "DisplayToC": "Display Type", - "KM": "KM", + "KM": "往返", "Description": "Description", - "Remarks": "Remarks" + "Remarks": "", + "NewTitle": { + "6": "", + "B": "A点-B点,举例:桂林-龙胜", + "J": "A点-B点时长车费,举例:张家界5晚6天车费", + "Q": "城市语种导游工资单位,举例:北京英文导游工资(元/天/团)", + "7": "官方景点名称,举例:陕西历史博物馆", + "R": "普通、豪华、特色餐标,举例:普通餐标", + "8": "举例:故宫导游门票", + "D": "城市A点-B点时间包含内容,举例:北京市区一日游车导" + } }, "LgcModal": { diff --git a/src/hooks/useProductsSets.js b/src/hooks/useProductsSets.js index b4e9abb..1900465 100644 --- a/src/hooks/useProductsSets.js +++ b/src/hooks/useProductsSets.js @@ -145,7 +145,7 @@ export const useNewProductRecord = () => { 'dept_id': 0, 'dept_name': '', 'display_to_c': 0, - 'km': 0, + 'km': undefined, 'city_id': 0, 'city_name': '', 'open_hours': '', diff --git a/src/views/App.jsx b/src/views/App.jsx index 4689721..fa8a61f 100644 --- a/src/views/App.jsx +++ b/src/views/App.jsx @@ -15,6 +15,8 @@ import useNoticeStore from '@/stores/Notice'; import useAuthStore from '@/stores/Auth'; import { useThemeContext } from '@/stores/ThemeContext'; import { usingStorage } from '@/hooks/usingStorage'; +import { useDefaultLgc } from '@/i18n/LanguageSwitcher'; +import { appendRequestParams } from '@/utils/request' import { PERM_ACCOUNT_MANAGEMENT, PERM_ROLE_NEW, PERM_OVERSEA, PERM_AIR_TICKET, PERM_PRODUCTS_MANAGEMENT } from '@/config'; @@ -63,9 +65,11 @@ function App() { defaultPath = splitPath[1] } + const { language } = useDefaultLgc(); const [antdLng, setAntdLng] = useState(enLocale); useEffect(() => { setAntdLng(i18n.language === 'en' ? enLocale : zhLocale); + appendRequestParams('lgc', language); }, [i18n.language]) return ( diff --git a/src/views/products/Detail.jsx b/src/views/products/Detail.jsx index 6f55b5c..5967b20 100644 --- a/src/views/products/Detail.jsx +++ b/src/views/products/Detail.jsx @@ -60,8 +60,6 @@ function Detail() { - - setAddProductVisible(false)} onCancel={() => setAddProductVisible(false)} /> > )} diff --git a/src/views/products/Detail/Header.jsx b/src/views/products/Detail/Header.jsx index 84d7bb0..93beec6 100644 --- a/src/views/products/Detail/Header.jsx +++ b/src/views/products/Detail/Header.jsx @@ -12,6 +12,7 @@ import { PERM_PRODUCTS_OFFER_AUDIT, PERM_PRODUCTS_OFFER_PUT } from '@/config'; import dayjs from 'dayjs'; import VendorSelector from '@/components/VendorSelector'; import AuditStateSelector from '@/components/AuditStateSelector'; +import NewProductModal from './NewProductModal'; const Header = ({ refresh, newActionable, ...props }) => { const location = useLocation(); @@ -174,17 +175,12 @@ const Header = ({ refresh, newActionable, ...props }) => { {/* 编辑 */} {isEditPage && ( - - - {t('New')} - {t('products:#')} - - + )} - {activeAgencyState === 0 && ( + {/* {activeAgencyState === 0 && ( */} <> - + {t('Submit')} {t('Audit')} @@ -192,7 +188,7 @@ const Header = ({ refresh, newActionable, ...props }) => { > - )} + {/* )} */} ); }; diff --git a/src/views/products/Detail/NewProductModal.jsx b/src/views/products/Detail/NewProductModal.jsx index 4903d4e..3319910 100644 --- a/src/views/products/Detail/NewProductModal.jsx +++ b/src/views/products/Detail/NewProductModal.jsx @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react'; -import { Form, Modal, Input } from 'antd'; +import { Form, Modal, Input, Button } from 'antd'; import { objectMapper } from '@/utils/commons'; import { useTranslation } from 'react-i18next'; @@ -7,7 +7,8 @@ import ProductsTypesSelector from '@/components/ProductsTypesSelector'; import useProductsStore from '@/stores/Products/Index'; import { useNewProductRecord, useProductsTypesMapVal } from '@/hooks/useProductsSets'; import { useDefaultLgc } from '@/i18n/LanguageSwitcher'; -import dayjs from 'dayjs' +import RequireAuth from '@/components/RequireAuth'; +import { PERM_PRODUCTS_OFFER_PUT } from '@/config'; export const NewProductsForm = ({ initialValues, onFormInstanceReady, ...props }) => { const { t } = useTranslation('products'); @@ -17,15 +18,21 @@ export const NewProductsForm = ({ initialValues, onFormInstanceReady, ...props } onFormInstanceReady(form); }, []); - const onValuesChange = (changeValues, allValues) => {}; + const [pickType, setPickType] = useState({ value: '6' }); + const onValuesChange = (changeValues, allValues) => { + if ('products_type' in changeValues) { + setPickType(changeValues.products_type); + } + }; return ( - - + + - - + + {/* ${pickType.value} */} + ); @@ -54,12 +61,13 @@ const formValuesMapper = (values) => { /** * */ -export const NewProductModal = ({ source, action = '#' | 'o', open, onSubmit, onCancel, initialValues }) => { +export const NewProductModal = ({ initialValues }) => { const { t } = useTranslation(); const [formInstance, setFormInstance] = useState(); const [setEditingProduct] = useProductsStore((state) => [state.setEditingProduct]); const [switchParams] = useProductsStore((state) => [state.switchParams]); + const [open, setOpen] = useState(false); const [copyLoading, setCopyLoading] = useState(false); const productsTypesMapVal = useProductsTypesMapVal(); const newProduct = useNewProductRecord(); @@ -71,26 +79,35 @@ export const NewProductModal = ({ source, action = '#' | 'o', open, onSubmit, on copyNewProduct.info.product_type_name = productsTypesMapVal[param.products_type.value].label; copyNewProduct.lgc_details[0].lgc = language; copyNewProduct.lgc_details[0].title = param.title; - copyNewProduct.quotation[0].use_dates_start = (`${switchParams.use_year}-01-01`); - copyNewProduct.quotation[0].use_dates_end = (`${switchParams.use_year}-12-31`); + copyNewProduct.quotation[0].use_dates_start = `${switchParams.use_year}-01-01`; + copyNewProduct.quotation[0].use_dates_end = `${switchParams.use_year}-12-31`; setEditingProduct(copyNewProduct); - if (typeof onSubmit === 'function') { - onSubmit(); - } + // if (typeof onSubmit === 'function') { + // onSubmit(); + // } + setOpen(false); return false; }; return ( <> + + setOpen(true)}> + {t('New')} + {t('products:#')} + + + { - onCancel(); + // onCancel(); + setOpen(false); formInstance?.resetFields(); }} destroyOnClose @@ -105,8 +122,6 @@ export const NewProductModal = ({ source, action = '#' | 'o', open, onSubmit, on } }}> { setFormInstance(instance); diff --git a/src/views/products/Detail/PriceCompactInput.jsx b/src/views/products/Detail/PriceCompactInput.jsx index c2b860e..2485b52 100644 --- a/src/views/products/Detail/PriceCompactInput.jsx +++ b/src/views/products/Detail/PriceCompactInput.jsx @@ -106,4 +106,8 @@ const PriceCompactInput = (props) => { ) } -export default PriceCompactInput \ No newline at end of file +<<<<<<< HEAD +export default PriceCompactInput +======= +export default PriceCompactInput +>>>>>>> acaf5a3de7b7197af62517e06d7fdbb7a4a48ace diff --git a/src/views/products/Detail/ProductInfo.jsx b/src/views/products/Detail/ProductInfo.jsx index 87f148e..95e759a 100644 --- a/src/views/products/Detail/ProductInfo.jsx +++ b/src/views/products/Detail/ProductInfo.jsx @@ -9,6 +9,7 @@ import { isEmpty, pick } from '@/utils/commons'; import ProductInfoForm from './ProductInfoForm'; import { usingStorage } from '@/hooks/usingStorage'; import Extras from './Extras'; +import NewProductModal from './NewProductModal'; const ProductInfo = ({ ...props }) => { const { t } = useTranslation(); @@ -22,18 +23,25 @@ const ProductInfo = ({ ...props }) => { const [activeAgency, editingProduct, setEditingProduct] = useProductsStore((state) => [state.activeAgency, state.editingProduct, state.setEditingProduct]); const [extrasVisible, setExtrasVisible] = useState(false); - const [editable, setEditable] = useState(false); + const [editablePerm, setEditablePerm] = useState(false); + const [infoEditable, setInfoEditable] = useState(false); + const [priceEditable, setPriceEditable] = useState(false); const topPerm = isPermitted(PERM_PRODUCTS_MANAGEMENT); // 高级权限 useEffect(() => { const hasHT = (editingProduct?.info?.htid || 0) > 0; // const hasAuditPer = isPermitted(PERM_PRODUCTS_OFFER_AUDIT); const hasEditPer = isPermitted(PERM_PRODUCTS_OFFER_PUT); - setEditable(topPerm || (!hasHT && hasEditPer)); + + setEditablePerm(topPerm || hasEditPer); // setEditable(topPerm || (hasAuditPer ? true : (!hasHT && hasEditPer))); // setEditable(true); // debug: 0 // console.log('editable', hasAuditPer, (notAudit && hasEditPer)); + setInfoEditable(topPerm || (!hasHT && hasEditPer)); + + const _priceEditable = [-1, 3].includes(activeAgency?.audit_state_id) || isEmpty(editingProduct?.info?.id); + setPriceEditable(topPerm || (_priceEditable && hasEditPer)); - const showExtras = topPerm && !isEmpty(editingProduct) && hasHT; + const showExtras = topPerm && hasHT; // !isEmpty(editingProduct) && setExtrasVisible(showExtras); return () => {}; }, [activeAgency, editingProduct]); @@ -42,18 +50,19 @@ const ProductInfo = ({ ...props }) => { values.travel_agency_id = activeAgency.travel_agency_id; const copyNewProduct = structuredClone(newProductRecord); const poster = { - 'audit_state': '-1', + ...(topPerm ? {} : { 'audit_state': -1 }), // 高级权限: 不变更状态值 // "create_date": dayjs().format('YYYY-MM-DD HH:mm:ss'), // "created_by": userId, 'travel_agency_id': activeAgency.travel_agency_id, // "travel_agency_name": "", // "lastedit_changed": "", }; - /** lgc_details */ const copyFields = pick(editingProduct.info, ['product_type_id']); // 'title', const readyToSubInfo = { ...copyNewProduct.info, ...editingProduct.info, ...values.info, ...copyFields, type: copyFields.product_type_id, ...poster }; + readyToSubInfo.dept = Number(readyToSubInfo.dept); // console.log('onSave', editingProduct.info, readyToSubInfo); - const prevLgcDetailsMapped = editingProduct.lgc_details.reduce((r, c) => ({ ...r, [c.lgc]: { ...c, description: c.descriptions } }), {}); // todo: description字段不一致 + /** lgc_details */ + const prevLgcDetailsMapped = editingProduct.lgc_details.reduce((r, c) => ({ ...r, [c.lgc]: { ...c, description: c.descriptions } }), {}); const mergedLgc = { ...prevLgcDetailsMapped, ...values.lgc_details_mapped }; // console.log(values); @@ -64,15 +73,15 @@ const ProductInfo = ({ ...props }) => { travel_agency_id: activeAgency.travel_agency_id, info: readyToSubInfo, lgc_details: Object.values(mergedLgc), - quotation: values.quotation, // || editingProduct.quotation, // 没改动, 就用原来的 - }).catch(ex => { + quotation: values.quotation.map((q) => ({ ...q, unit: Number(q.unit || q.unit_id), unit_id: Number(q.unit_id) })), // || editingProduct.quotation, // 没改动, 就用原来的 + }).catch((ex) => { setLoading(false); notification.error({ message: 'Notification', description: ex.message, placement: 'top', duration: 4, - }) + }); }); setLoading(false); success ? message.success(t('Success')) : message.error(t('Failed')); @@ -90,10 +99,18 @@ const ProductInfo = ({ ...props }) => { ]} /> - {t('products:EditComponents.info')} - - - {extrasVisible && } + {isEmpty(editingProduct) ? ( + + + + ) : ( + <> + {t('products:EditComponents.info')} + + + {extrasVisible && } + > + )} > ); }; diff --git a/src/views/products/Detail/ProductInfoForm.jsx b/src/views/products/Detail/ProductInfoForm.jsx index c0fefe6..f7dff06 100644 --- a/src/views/products/Detail/ProductInfoForm.jsx +++ b/src/views/products/Detail/ProductInfoForm.jsx @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { Form, Input, Row, Col, Select, Button, InputNumber, Checkbox } from 'antd'; +import { App, Form, Input, Row, Col, Select, Button, InputNumber, Checkbox } from 'antd'; import { objectMapper, isEmpty, isNotEmpty } from '@/utils/commons'; import { useTranslation } from 'react-i18next'; import { useWeekdays } from '@/hooks/useDatePresets'; @@ -11,7 +11,8 @@ import ProductInfoLgc from './ProductInfoLgc'; import ProductInfoQuotation from './ProductInfoQuotation'; import { useHTLanguageSetsMapVal } from '@/hooks/useHTLanguageSets'; -const InfoForm = ({ onSubmit, onReset, onValuesChange, editable: _editable, showSubmit, confirmText, formName, ...props }) => { +const InfoForm = ({ onSubmit, onReset, onValuesChange, editablePerm, infoEditable, priceEditable, showSubmit, confirmText, formName, ...props }) => { + const { notification } = App.useApp(); const { t } = useTranslation('products'); const HTLanguageSetsMapVal = useHTLanguageSetsMapVal(); const [loading, editingProduct] = useProductsStore((state) => [state.loading, state.editingProduct]); @@ -28,19 +29,24 @@ const InfoForm = ({ onSubmit, onReset, onValuesChange, editable: _editable, show const filedsets = useProductsTypesFieldsets(editingProduct?.info?.product_type_id); const shows = filedsets[0]; - const [editable, setEditable] = useState(true); + // const [editable, setEditable] = useState(true); + const [formEditable, setFormEditable] = useState(true); + const [showSave, setShowSave] = useState(true); useEffect(() => { form.resetFields(); - form.setFieldValue('city', { value: editingProduct?.info?.city_id, label: editingProduct?.info?.city_name }); + form.setFieldValue('city', editingProduct?.info?.city_id ? { value: editingProduct?.info?.city_id, label: editingProduct?.info?.city_name } : undefined); form.setFieldValue('dept', { value: editingProduct?.info?.dept_id, label: editingProduct?.info?.dept_name }); const lgc_details_mapped = (editingProduct?.lgc_details || []).reduce((r, c) => ({ ...r, [c.lgc]: c }), {}); form.setFieldValue('lgc_details_mapped', lgc_details_mapped); form.setFieldValue('quotation', editingProduct?.quotation); - const editable0 = isEmpty(editingProduct) ? false : _editable; // 空对象未操作 - setEditable(editable0); + setFormEditable(infoEditable || priceEditable); + + // const editable0 = isEmpty(editingProduct) ? false : editablePerm; // 空对象未操作 + setShowSave(infoEditable || priceEditable); + // setEditable(editable0); return () => {}; - }, [editingProduct?.info?.id, _editable]); + }, [editingProduct?.info?.id, editablePerm, infoEditable, priceEditable]); const onFinish = (values) => { console.log('Received values of form, origin form value: \n', values); @@ -53,6 +59,12 @@ const InfoForm = ({ onSubmit, onReset, onValuesChange, editable: _editable, show const onFinishFailed = ({ values, errorFields }) => { console.log('form validate failed', '\nform values:', values, '\nerrorFields', errorFields); + notification.warning({ + message: '数据未填写完整', + // description: '数据未填写完整', + placement: 'top', + duration: 4, + }) }; const handleReset = () => { @@ -77,16 +89,16 @@ const InfoForm = ({ onSubmit, onReset, onValuesChange, editable: _editable, show <> + onFinishFailed={onFinishFailed} scrollToFirstError > - {getFields({ sort, initialValue: editingProduct?.info, hides, shows, fieldProps, fieldComProps, form, t, dataSets: { weekdays }, editable })} + {getFields({ sort, initialValue: editingProduct?.info, hides, shows, fieldProps, fieldComProps, form, t, dataSets: { weekdays }, editable: infoEditable })} {/* {showSubmit && ( @@ -118,11 +130,11 @@ const InfoForm = ({ onSubmit, onReset, onValuesChange, editable: _editable, show }, }), ]}> - + - + @@ -131,7 +143,7 @@ const InfoForm = ({ onSubmit, onReset, onValuesChange, editable: _editable, show {/* */} - {editable && ( + {showSave && ( @@ -196,8 +208,8 @@ function getFields(props) { item( 'city', 99, - - + + , fieldProps?.city?.col || midCol ), @@ -212,7 +224,7 @@ function getFields(props) { item( 'duration', 99, - + {/* */} , @@ -221,8 +233,8 @@ function getFields(props) { item( 'km', 99, - - + + , fieldProps?.km?.col || midCol ), @@ -297,7 +309,7 @@ function getFields(props) { 'remarks', 99, - + , fieldProps?.remarks?.col || 24 ), diff --git a/src/views/products/Detail/ProductInfoLgc.jsx b/src/views/products/Detail/ProductInfoLgc.jsx index c530755..2b6a595 100644 --- a/src/views/products/Detail/ProductInfoLgc.jsx +++ b/src/views/products/Detail/ProductInfoLgc.jsx @@ -25,10 +25,11 @@ const ProductInfoLgc = ({ editable, formInstance, ...props }) => { forceRender: true, children: ( - + handleChange('title', e.target.value)} // disabled={ignoreEditable ? false : (!isEmpty(ele.title) || !editable)} // disabled={ignoreEditable ? false : !editable} @@ -86,8 +87,8 @@ const ProductInfoLgc = ({ editable, formInstance, ...props }) => { key: lgcItem.value, children: ( - - + + diff --git a/src/views/products/Detail/ProductInfoQuotation.jsx b/src/views/products/Detail/ProductInfoQuotation.jsx index 7832b89..1ef3d4f 100644 --- a/src/views/products/Detail/ProductInfoQuotation.jsx +++ b/src/views/products/Detail/ProductInfoQuotation.jsx @@ -229,10 +229,11 @@ const ProductInfoQuotation = ({ editable, ...props }) => { dataIndex: 'operation', width: '3%', render: (_, quotation) => { + const _rowEditable = [-1,3].includes(quotation.audit_state_id); return ( - onQuotationSeleted(quotation)}>{t('Edit')} - onDeleteQuotation(quotation.id)}>{t('Delete')} + onQuotationSeleted(quotation)}>{t('Edit')} + onDeleteQuotation(quotation.id)}>{t('Delete')} ) }, diff --git a/src/views/products/Detail/ProductsTree.jsx b/src/views/products/Detail/ProductsTree.jsx index d3aeae4..132356f 100644 --- a/src/views/products/Detail/ProductsTree.jsx +++ b/src/views/products/Detail/ProductsTree.jsx @@ -4,6 +4,7 @@ import { CaretDownOutlined } from '@ant-design/icons'; import { useTranslation } from 'react-i18next'; import useProductsStore from '@/stores/Products/Index'; import { useProductsTypes, useProductsAuditStatesMapVal } from '@/hooks/useProductsSets'; +import { groupBy, sortBy } from '@/utils/commons'; const flattenTreeFun = (tree) => { let flatList = []; @@ -52,6 +53,13 @@ const ProductsTree = ({ onNodeSelect, ...props }) => { // 只显示有产品的类型; // const title = text || r.lgc_details?.['2']?.title || r.lgc_details?.['1']?.title || ''; const hasDataTypes = Object.keys(agencyProducts); + // const cityData = groupBy(productsSortByHT, (row) => `${row.info.city_id}-${row.info.city_name}`); + const copyAgencyProducts = structuredClone(agencyProducts); + Object.keys(copyAgencyProducts).map((key) => { + const _cityProductsData = groupBy(copyAgencyProducts[key], (row) => `${row.info.city_name || '(空)'}`); + copyAgencyProducts[key] = _cityProductsData; + }); + // console.log(copyAgencyProducts); const _show = productsTypes .filter((kk) => hasDataTypes.includes(kk.value)) .map((ele) => ({ @@ -62,10 +70,20 @@ const ProductsTree = ({ onNodeSelect, ...props }) => { const lgc_map = product.lgc_details.reduce((rlgc, clgc) => ({...rlgc, [clgc.lgc]: clgc}), {}); return { title: product.info.title || lgc_map?.['2']?.title || lgc_map?.['1']?.title || '', + // title: `【${product.info.city_name}】` + (product.info.title || lgc_map?.['2']?.title || lgc_map?.['1']?.title || ''), // key: `${ele.value}-${product.info.id}`, key: product.info.id, _raw: product, + isLeaf: true, }}), + // 增加`城市`层级 + _children: Object.keys(copyAgencyProducts[ele.value] || []).map(city => { + return { + title: city, + key: `${ele.value}-${city}`, + children: copyAgencyProducts[ele.value][city], + }; + }), })); setTreeData(_show); setRawTreeData(_show); @@ -88,12 +106,17 @@ const ProductsTree = ({ onNodeSelect, ...props }) => { setSearchValue(value); setAutoExpandParent(true); }; - const handleNodeSelect = (_, { node }) => { + const handleNodeSelect = (selectedKeys, { node }) => { if (node._raw) { setEditingProduct(node._raw); + } else { + // 单击: 折叠/展开 + // const isExpand = expandedKeys.includes(selectedKeys[0]); + // const _keys = isExpand ? expandedKeys.filter(k => k !== node.key) : [].concat(expandedKeys, selectedKeys); + // setExpandedKeys(_keys); } if (typeof onNodeSelect === 'function') { - onNodeSelect(_, { node }); + onNodeSelect(selectedKeys, { node }); } }; const onExpand = (keys) => { @@ -123,7 +146,7 @@ const ProductsTree = ({ onNodeSelect, ...props }) => { } onSelect={handleNodeSelect}