You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
7.8 KiB
JavaScript
208 lines
7.8 KiB
JavaScript
import { createContext, useEffect, useState } from 'react';
|
|
import { useLocation } from 'react-router-dom';
|
|
import { Tree, Input, Divider } from 'antd';
|
|
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, isEmpty, sortBy } from '@/utils/commons';
|
|
import NewProductModal from './NewProductModal';
|
|
import ContractRemarksModal from './ContractRemarksModal'
|
|
|
|
const flattenTreeFun = (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 ProductsTree = ({ onNodeSelect, ...props }) => {
|
|
const { t } = useTranslation();
|
|
const location = useLocation();
|
|
const isEditPage = location.pathname.includes('edit');
|
|
const [agencyProducts, editingProduct, setEditingProduct] = useProductsStore((state) => [state.agencyProducts, state.editingProduct, state.setEditingProduct]);
|
|
const [activeAgency] = useProductsStore((state) => [state.activeAgency]);
|
|
const productsTypes = useProductsTypes();
|
|
|
|
const [treeData, setTreeData] = useState([]); // render data
|
|
const [rawTreeData, setRawTreeData] = useState([]);
|
|
const [flattenTreeData, setFlattenTreeData] = useState([]);
|
|
const [expandedKeys, setExpandedKeys] = useState([]);
|
|
const [selectedKeys, setSelectedKeys] = useState([]);
|
|
const [autoExpandParent, setAutoExpandParent] = useState(true);
|
|
|
|
useEffect(() => {
|
|
setExpandedKeys(productsTypes.map((item) => item.key)); // 全部展开
|
|
return () => {}
|
|
}, [productsTypes, activeAgency]);
|
|
|
|
useEffect(() => {
|
|
// 只显示有产品的类型;
|
|
// 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) => ({
|
|
...ele,
|
|
title: ele.label,
|
|
key: ele.value,
|
|
children: (agencyProducts[ele.value] || []).reduce((arr, product) => {
|
|
const lgc_map = product.lgc_details.reduce((rlgc, clgc) => ({ ...rlgc, [clgc.lgc]: clgc }), {});
|
|
const combindCityList = product.info.city_list.indexOf(city => city.id === product.info.city_id) !== -1 ? product.info.city_list : [...product.info.city_list, { id: product.info.city_id, name: product.info.city_name }];
|
|
const flatCityP = combindCityList.map(city => ({
|
|
title: `【${city.name}】` + (product.info.title || lgc_map?.['2']?.title || lgc_map?.['1']?.title || product.info.product_title || ''),
|
|
// key: `${ele.value}-${product.info.id}`,
|
|
key: `${product.info.id}-${city.id}`,
|
|
_raw: product,
|
|
isLeaf: true,
|
|
}));
|
|
return arr.concat(flatCityP);
|
|
}, []),
|
|
// 增加`城市`层级
|
|
// _children: Object.keys(copyAgencyProducts[ele.value] || []).map(city => {
|
|
// return {
|
|
// title: city,
|
|
// key: `${ele.value}-${city}`,
|
|
// children: copyAgencyProducts[ele.value][city],
|
|
// };
|
|
// }),
|
|
}));
|
|
setTreeData(_show);
|
|
setRawTreeData(_show);
|
|
setFlattenTreeData(flattenTreeFun(_show));
|
|
|
|
// setExpandedKeys(productsTypes.map((item) => item.key)); // 全部展开
|
|
|
|
// setActiveKey(isEmpty(_show) ? [] : [_show[0].key]);
|
|
return () => {};
|
|
}, [productsTypes, agencyProducts]);
|
|
|
|
useEffect(() => {
|
|
if (isEmpty(editingProduct)) {
|
|
return () => {};
|
|
}
|
|
const allKeysWithCity = [...editingProduct.info.city_list, { id: editingProduct.info.city_id, name: editingProduct.info.city_name }].map(
|
|
(city) => `${editingProduct.info.id}-${city.id}`
|
|
);
|
|
setSelectedKeys(allKeysWithCity);
|
|
|
|
return () => {};
|
|
}, [editingProduct?.info?.id]);
|
|
|
|
|
|
const [searchValue, setSearchValue] = useState('');
|
|
const onSearch = ({ target: { value } }) => {
|
|
// const { value } = e.target;
|
|
if (isEmpty(value)) {
|
|
setTreeData(rawTreeData);
|
|
setSearchValue(value);
|
|
return;
|
|
}
|
|
const newExpandedKeys = flattenTreeData
|
|
.filter((item) => item.title.includes(value))
|
|
.map((item) => getParentKey(item.key, rawTreeData))
|
|
.filter((item, i, self) => item && self.indexOf(item) === i);
|
|
setExpandedKeys(newExpandedKeys);
|
|
setSearchValue(value);
|
|
setAutoExpandParent(true);
|
|
const matchTree = rawTreeData.map(node1 => {
|
|
const _find = node1.children.filter(node2 => node2.title.includes(value));
|
|
return _find.length > 0 ? {...node1, children: _find} : null;
|
|
}).filter(node => node);
|
|
setTreeData(matchTree);
|
|
};
|
|
const handleNodeSelect = (selectedKeys, { node }) => {
|
|
if (node._raw) {
|
|
setEditingProduct(node._raw);
|
|
const allKeysWithCity = [...node._raw.info.city_list, { id: node._raw.info.city_id, name: node._raw.info.city_name }].map((city) => `${node._raw.info.id}-${city.id}`);
|
|
setSelectedKeys(allKeysWithCity);
|
|
} 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(selectedKeys, { node });
|
|
}
|
|
};
|
|
const onExpand = (keys) => {
|
|
setExpandedKeys(keys);
|
|
setAutoExpandParent(false);
|
|
};
|
|
|
|
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 = <span style={{ color: 'red' }}>{searchValue}</span>;
|
|
|
|
return index > -1 ? (
|
|
<span>
|
|
{beforeStr}
|
|
{highlighted}
|
|
{afterStr}
|
|
</span>
|
|
) : (
|
|
<span>{node.title}</span>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<div className={`${props.className} relative`} style={props.style}>
|
|
<Input.Search placeholder='Search' onChange={onSearch} allowClear className='sticky top-1 z-20 mb-3' />
|
|
{/* 编辑 */}
|
|
{isEditPage && (
|
|
<NewProductModal />
|
|
)}
|
|
<Divider type='vertical' />
|
|
<ContractRemarksModal />
|
|
<Tree
|
|
blockNode
|
|
showLine defaultExpandAll expandAction={'doubleClick'}
|
|
selectedKeys={selectedKeys} multiple
|
|
switcherIcon={<CaretDownOutlined />}
|
|
onSelect={handleNodeSelect}
|
|
treeData={treeData}
|
|
expandedKeys={expandedKeys}
|
|
autoExpandParent={autoExpandParent}
|
|
onExpand={onExpand}
|
|
titleRender={titleRender}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
export default ProductsTree;
|