|
|
@@ -0,0 +1,144 @@
|
|
|
+import { useQuery } from '@tanstack/react-query';
|
|
|
+import { areaClient, areaClientManager } from '../../../api/areaClient';
|
|
|
+import type { InferResponseType } from 'hono/client';
|
|
|
+
|
|
|
+// 正确的类型推断
|
|
|
+type AreaResponse = InferResponseType<typeof areaClient.index.$get, 200>['data'][0];
|
|
|
+
|
|
|
+interface UseAreasOptions {
|
|
|
+ enabled?: boolean;
|
|
|
+}
|
|
|
+
|
|
|
+export const useProvinces = (options?: UseAreasOptions) => {
|
|
|
+ return 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('获取省份列表失败');
|
|
|
+ const json = await res.json();
|
|
|
+ return json.data as AreaResponse[];
|
|
|
+ },
|
|
|
+ staleTime: 10 * 60 * 1000,
|
|
|
+ gcTime: 30 * 60 * 1000,
|
|
|
+ enabled: options?.enabled ?? true,
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+export const useCities = (provinceId?: number, options?: UseAreasOptions) => {
|
|
|
+ return useQuery({
|
|
|
+ queryKey: ['areas', 'cities', provinceId],
|
|
|
+ queryFn: async () => {
|
|
|
+ if (!provinceId) return [];
|
|
|
+
|
|
|
+ const res = await areaClientManager.get().index.$get({
|
|
|
+ query: {
|
|
|
+ page: 1,
|
|
|
+ pageSize: 100,
|
|
|
+ filters: JSON.stringify({
|
|
|
+ level: 2,
|
|
|
+ parentId: provinceId,
|
|
|
+ isDisabled: 0
|
|
|
+ }),
|
|
|
+ sortBy: 'id',
|
|
|
+ sortOrder: 'ASC'
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (res.status !== 200) throw new Error('获取城市列表失败');
|
|
|
+ const json = await res.json();
|
|
|
+ return json.data as AreaResponse[];
|
|
|
+ },
|
|
|
+ staleTime: 10 * 60 * 1000,
|
|
|
+ gcTime: 30 * 60 * 1000,
|
|
|
+ enabled: !!provinceId && (options?.enabled ?? true),
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+export const useDistricts = (cityId?: number, options?: UseAreasOptions) => {
|
|
|
+ return useQuery({
|
|
|
+ queryKey: ['areas', 'districts', cityId],
|
|
|
+ queryFn: async () => {
|
|
|
+ if (!cityId) return [];
|
|
|
+
|
|
|
+ const res = await areaClientManager.get().index.$get({
|
|
|
+ query: {
|
|
|
+ page: 1,
|
|
|
+ pageSize: 100,
|
|
|
+ filters: JSON.stringify({
|
|
|
+ level: 3,
|
|
|
+ parentId: cityId,
|
|
|
+ isDisabled: 0
|
|
|
+ }),
|
|
|
+ sortBy: 'id',
|
|
|
+ sortOrder: 'ASC'
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (res.status !== 200) throw new Error('获取区县列表失败');
|
|
|
+ const json = await res.json();
|
|
|
+ return json.data as AreaResponse[];
|
|
|
+ },
|
|
|
+ staleTime: 10 * 60 * 1000,
|
|
|
+ gcTime: 30 * 60 * 1000,
|
|
|
+ enabled: !!cityId && (options?.enabled ?? true),
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+export const useTowns = (districtId?: number, options?: UseAreasOptions) => {
|
|
|
+ return useQuery({
|
|
|
+ queryKey: ['areas', 'towns', districtId],
|
|
|
+ queryFn: async () => {
|
|
|
+ if (!districtId) return [];
|
|
|
+
|
|
|
+ const res = await areaClientManager.get().index.$get({
|
|
|
+ query: {
|
|
|
+ page: 1,
|
|
|
+ pageSize: 100,
|
|
|
+ filters: JSON.stringify({
|
|
|
+ level: 4,
|
|
|
+ parentId: districtId,
|
|
|
+ isDisabled: 0
|
|
|
+ }),
|
|
|
+ sortBy: 'id',
|
|
|
+ sortOrder: 'ASC'
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (res.status !== 200) throw new Error('获取街道列表失败');
|
|
|
+ const json = await res.json();
|
|
|
+ return json.data as AreaResponse[];
|
|
|
+ },
|
|
|
+ staleTime: 10 * 60 * 1000,
|
|
|
+ gcTime: 30 * 60 * 1000,
|
|
|
+ enabled: !!districtId && (options?.enabled ?? true),
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 组合Hook,方便一次性获取所有需要的地区数据
|
|
|
+export const useAreas = (provinceId?: number, cityId?: number, districtId?: number) => {
|
|
|
+ const provincesQuery = useProvinces();
|
|
|
+ const citiesQuery = useCities(provinceId);
|
|
|
+ const districtsQuery = useDistricts(cityId);
|
|
|
+ const townsQuery = useTowns(districtId);
|
|
|
+
|
|
|
+ return {
|
|
|
+ provinces: provincesQuery.data || [],
|
|
|
+ cities: citiesQuery.data || [],
|
|
|
+ districts: districtsQuery.data || [],
|
|
|
+ towns: townsQuery.data || [],
|
|
|
+ isLoadingProvinces: provincesQuery.isLoading,
|
|
|
+ isLoadingCities: citiesQuery.isLoading,
|
|
|
+ isLoadingDistricts: districtsQuery.isLoading,
|
|
|
+ isLoadingTowns: townsQuery.isLoading,
|
|
|
+ isError: provincesQuery.isError || citiesQuery.isError || districtsQuery.isError || townsQuery.isError,
|
|
|
+ error: provincesQuery.error || citiesQuery.error || districtsQuery.error || townsQuery.error,
|
|
|
+ };
|
|
|
+};
|