import React, { useState, useEffect } from 'react'; import { useQuery } from '@tanstack/react-query'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/client/components/ui/select'; import { FormItem, FormLabel, FormControl, FormMessage } from '@/client/components/ui/form'; import { cityClient } from '@/client/api'; interface CityCascadeSelectorProps { provinceValue?: number; cityValue?: number; districtValue?: number; townValue?: number; onProvinceChange?: (value: number) => void; onCityChange?: (value: number) => void; onDistrictChange?: (value: number) => void; onTownChange?: (value: number) => void; disabled?: boolean; showLabels?: boolean; } interface City { id: number; name: string; level: number; parentId: number; } export const CityCascadeSelector: React.FC = ({ provinceValue, cityValue, districtValue, townValue, onProvinceChange, onCityChange, onDistrictChange, onTownChange, disabled = false, showLabels = true, }) => { // 获取省份数据 (level=1) const { data: provinces } = useQuery({ queryKey: ['cities', 'provinces'], queryFn: async () => { const res = await cityClient.$get({ query: { page: 1, pageSize: 100, filters: JSON.stringify({ level: 1 }), }, }); if (res.status !== 200) throw new Error('获取省份数据失败'); const data = await res.json(); return data.data as City[]; }, }); // 获取城市数据 (level=2) const { data: cities } = useQuery({ queryKey: ['cities', 'cities', provinceValue], queryFn: async () => { if (!provinceValue) return []; const res = await cityClient.$get({ query: { page: 1, pageSize: 100, filters: JSON.stringify({ level: 2, parentId: provinceValue }), }, }); if (res.status !== 200) throw new Error('获取城市数据失败'); const data = await res.json(); return data.data as City[]; }, enabled: !!provinceValue, }); // 获取区县数据 (level=3) const { data: districts } = useQuery({ queryKey: ['cities', 'districts', cityValue], queryFn: async () => { if (!cityValue) return []; const res = await cityClient.$get({ query: { page: 1, pageSize: 100, filters: JSON.stringify({ level: 3, parentId: cityValue }), }, }); if (res.status !== 200) throw new Error('获取区县数据失败'); const data = await res.json(); return data.data as City[]; }, enabled: !!cityValue, }); // 获取街道数据 (level=4) const { data: towns } = useQuery({ queryKey: ['cities', 'towns', districtValue], queryFn: async () => { if (!districtValue) return []; const res = await cityClient.$get({ query: { page: 1, pageSize: 100, filters: JSON.stringify({ level: 4, parentId: districtValue }), }, }); if (res.status !== 200) throw new Error('获取街道数据失败'); const data = await res.json(); return data.data as City[]; }, enabled: !!districtValue, }); // 清除下级选择器 useEffect(() => { if (!provinceValue && cityValue !== undefined) { onCityChange?.(0); } }, [provinceValue, cityValue]); useEffect(() => { if (!cityValue && districtValue !== undefined) { onDistrictChange?.(0); } }, [cityValue, districtValue]); useEffect(() => { if (!districtValue && townValue !== undefined) { onTownChange?.(0); } }, [districtValue, townValue]); const renderSelect = ( label: string, value: number | undefined, onChange: ((value: number) => void) | undefined, options: City[] | undefined, placeholder: string ) => ( {showLabels && {label}} ); return (
{renderSelect( '省份', provinceValue, onProvinceChange, provinces, '选择省份' )} {renderSelect( '城市', cityValue, onCityChange, cities, provinceValue ? '选择城市' : '请先选择省份' )} {renderSelect( '区县', districtValue, onDistrictChange, districts, cityValue ? '选择区县' : '请先选择城市' )} {renderSelect( '街道', townValue, onTownChange, towns, districtValue ? '选择街道' : '请先选择区县' )}
); };