import React, { useState, useEffect } from 'react'; import { useQuery } from '@tanstack/react-query'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@d8d/shared-ui-components/components/ui/select'; import { FormControl, FormDescription, FormItem, FormLabel, FormMessage } from '@d8d/shared-ui-components/components/ui/form'; import { areaClient, areaClientManager } from '../api/areaClient'; import type { InferResponseType } from 'hono/client'; // 类型定义 type AreaResponse = InferResponseType['data'][0]; interface AreaSelectProps { value?: { provinceId?: number; cityId?: number; districtId?: number; }; onChange?: (value: { provinceId?: number; cityId?: number; districtId?: number; }) => void; disabled?: boolean; required?: boolean; className?: string; 'data-testid'?: string; } export const AreaSelect: React.FC = ({ value = {}, onChange, disabled = false, required = false, className, 'data-testid': testId }) => { const [selectedProvince, setSelectedProvince] = useState(value.provinceId); const [selectedCity, setSelectedCity] = useState(value.cityId); const [selectedDistrict, setSelectedDistrict] = useState(value.districtId); // 查询省份列表 const { data: provinces, isLoading: isLoadingProvinces } = useQuery({ queryKey: ['areas', 'provinces'], queryFn: async () => { const res = await areaClientManager.get().index.$get({ query: { page: 1, pageSize: 100, filters: JSON.stringify({ level: 1, isDisabled: 0 }), sortBy: 'id', sortOrder: 'ASC' } }); if (res.status !== 200) throw new Error('获取省份列表失败'); return await res.json(); }, staleTime: 10 * 60 * 1000, gcTime: 30 * 60 * 1000, }); // 查询城市列表 const { data: cities, isLoading: isLoadingCities } = useQuery({ queryKey: ['areas', 'cities', selectedProvince], queryFn: async () => { if (!selectedProvince) return { data: [] }; const res = await areaClientManager.get().index.$get({ query: { page: 1, pageSize: 100, filters: JSON.stringify({ level: 2, parentId: selectedProvince, isDisabled: 0 }), sortBy: 'id', sortOrder: 'ASC' } }); if (res.status !== 200) throw new Error('获取城市列表失败'); return await res.json(); }, staleTime: 10 * 60 * 1000, gcTime: 30 * 60 * 1000, enabled: !!selectedProvince, }); // 查询区县列表 const { data: districts, isLoading: isLoadingDistricts } = useQuery({ queryKey: ['areas', 'districts', selectedCity], queryFn: async () => { if (!selectedCity) return { data: [] }; const res = await areaClientManager.get().index.$get({ query: { page: 1, pageSize: 100, filters: JSON.stringify({ level: 3, parentId: selectedCity, isDisabled: 0 }), sortBy: 'id', sortOrder: 'ASC' } }); if (res.status !== 200) throw new Error('获取区县列表失败'); return await res.json(); }, staleTime: 10 * 60 * 1000, gcTime: 30 * 60 * 1000, enabled: !!selectedCity, }); // 处理省份选择 const handleProvinceChange = (provinceId: string) => { const id = provinceId && provinceId !== 'none' ? Number(provinceId) : undefined; setSelectedProvince(id); setSelectedCity(undefined); setSelectedDistrict(undefined); onChange?.({ provinceId: id, cityId: undefined, districtId: undefined }); }; // 处理城市选择 const handleCityChange = (cityId: string) => { const id = cityId && cityId !== 'none' ? Number(cityId) : undefined; setSelectedCity(id); setSelectedDistrict(undefined); onChange?.({ provinceId: selectedProvince, cityId: id, districtId: undefined }); }; // 处理区县选择 const handleDistrictChange = (districtId: string) => { const id = districtId && districtId !== 'none' ? Number(districtId) : undefined; setSelectedDistrict(id); onChange?.({ provinceId: selectedProvince, cityId: selectedCity, districtId: id }); }; // 同步外部值变化 useEffect(() => { setSelectedProvince(value.provinceId); setSelectedCity(value.cityId); setSelectedDistrict(value.districtId); }, [value.provinceId, value.cityId, value.districtId]); return (
{/* 省份选择 */}
省份{required && *} 选择所在省份
{/* 城市选择 */}
城市{required && selectedProvince && *} 选择所在城市
{/* 区县选择 */}
区县 选择所在区县
); };