import React, { useEffect, useState } from 'react'; import { ScrollView, StyleProp, StyleSheet, TextStyle, TouchableOpacity, View, ViewStyle } from 'react-native'; import { ThemedText } from './ThemedText'; export type CascaderItem = { name: string; [key: string]: any; // 允许其他自定义属性 children?: CascaderItem[]; }; type CascaderProps = { data: CascaderItem[]; // 级联数据 value?: CascaderItem[]; // 选中的值 onChange?: (value: CascaderItem[]) => void; // 选中项变化时的回调 displayRender?: (selectedItems: CascaderItem[]) => React.ReactNode; // 自定义显示内容 style?: StyleProp; // 容器样式 itemStyle?: StyleProp; // 选项样式 activeItemStyle?: StyleProp; // 选中项样式 textStyle?: StyleProp; // 文字样式 activeTextStyle?: StyleProp; // 选中文字样式 columnWidth?: number; // 列宽 showDivider?: boolean; // 是否显示分割线 dividerColor?: string; // 分割线颜色 showArrow?: boolean; // 是否显示箭头 }; const CascaderComponent: React.FC = ({ data, value = [], onChange, displayRender, style, activeItemStyle, textStyle, activeTextStyle, columnWidth = 120, showDivider = true, dividerColor = '#e0e0e0', showArrow = false, }) => { const [selectedItems, setSelectedItems] = useState(value); const [allLevelsData, setAllLevelsData] = useState([]); // 初始化数据 useEffect(() => { setAllLevelsData([data]); }, [data]); // 处理选择 const handleSelect = (item: CascaderItem, level: number) => { const newSelectedItems = [...selectedItems.slice(0, level), item]; setSelectedItems(newSelectedItems); // 如果有子项,添加下一级数据 if (item.children?.length) { setAllLevelsData(prev => { const newLevels = [...prev.slice(0, level + 1)]; // 确保 children 存在且是数组 if (item.children && Array.isArray(item.children)) { newLevels.push(item.children); } return newLevels; }); } else { setAllLevelsData(prev => prev.slice(0, level + 1)); } // 触发onChange回调 onChange?.(newSelectedItems); }; // 渲染某一级选项 const renderLevel = (items: CascaderItem[], level: number) => { return ( {items.map((item, index) => { const isActive = selectedItems[level]?.name === item.name; return ( handleSelect(item, level)} > {item.name} {showArrow && item.children?.length ? ( ) : null} ); })} ); }; // 渲染所有级联列 const renderColumns = () => { const totalLevels = allLevelsData.length; return allLevelsData.map((items, level) => { // 计算每列的宽度 let width; if (totalLevels === 1) { width = '100%'; // 只有一级时占满全部宽度 } else if (totalLevels === 2) { width = level === 0 ? '40%' : '60%'; // 两级时第一级40%,第二级60% } else { // 三级或以上时,前两级各占30%,其余级别平分剩余40% if (level < 2) { width = '30%'; } else { const remainingLevels = totalLevels - 2; width = remainingLevels > 0 ? `${40 / remainingLevels}%` : '40%'; } } return ( {renderLevel(items, level)} ); }); }; // 自定义显示内容 const renderDisplay = () => { if (displayRender) { return displayRender(selectedItems); } return selectedItems.map(item => item.name).join(' / '); }; return ( {renderColumns()} {displayRender && ( {renderDisplay()} )} ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', height: 300, }, scrollContent: { flexGrow: 1, height: '100%', flexDirection: 'row', }, column: { height: '100%', maxHeight: '100%', flexShrink: 0, }, columnWithDivider: { borderRightWidth: 1, }, levelContainer: { height: '100%', maxHeight: '100%', }, item: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingVertical: 12, paddingHorizontal: 16, minWidth: '100%', overflow: 'hidden', }, text: { fontSize: 15, color: '#333', flexShrink: 0, // 禁止收缩 paddingRight: 4, }, itemContent: { flexDirection: 'row', alignItems: 'center', paddingRight: 16, // 确保有足够的右边距 }, activeItem: { backgroundColor: '#F6F6F6', }, activeText: { color: '#AC7E35', fontWeight: '500', }, arrow: { fontSize: 18, color: '#999', marginLeft: 8, }, displayContainer: { padding: 12, borderTopWidth: 1, borderTopColor: '#f0f0f0', }, }); export default CascaderComponent;