733 lines
21 KiB
TypeScript
733 lines
21 KiB
TypeScript
import { create } from "zustand";
|
||
import dayjs from "dayjs";
|
||
import {
|
||
getGamesList,
|
||
getGamesIntegrateList,
|
||
getSearchHistory,
|
||
clearHistory,
|
||
searchSuggestion,
|
||
getGamesCount,
|
||
getCities,
|
||
getCityQrCode,
|
||
getDistricts,
|
||
} from "../services/listApi";
|
||
import {
|
||
ListActions,
|
||
IFilterOptions,
|
||
ListState,
|
||
IPayload,
|
||
} from "../../types/list/types";
|
||
|
||
function translateCityData(dataTree) {
|
||
return dataTree.map((item) => {
|
||
const { children, ...rest } = item;
|
||
// 只保留两级:国家和省份,去掉第三级(区域)
|
||
const processedChildren = children?.length > 0
|
||
? children.map(child => ({
|
||
...child,
|
||
text: child.name,
|
||
label: child.name,
|
||
value: child.name,
|
||
children: null, // 去掉第三级
|
||
}))
|
||
: null;
|
||
|
||
return {
|
||
...rest,
|
||
text: rest.name,
|
||
label: rest.name,
|
||
value: rest.name,
|
||
children: processedChildren,
|
||
};
|
||
});
|
||
}
|
||
|
||
|
||
// 完整的 Store 类型
|
||
type TennisStore = ListState & ListActions;
|
||
|
||
const defaultDateRange: [string, string] = [dayjs().format('YYYY-MM-DD'), dayjs().add(1, 'M').format('YYYY-MM-DD')]
|
||
|
||
const defaultFilterOptions: IFilterOptions = {
|
||
dateRange: defaultDateRange, // 日期区间
|
||
timeSlot: [], // 时间段(多选,默认为空数组)
|
||
ntrp: [1, 5], // NTRP 水平区间
|
||
venueType: [], // 场地类型(多选,默认为空数组)
|
||
playType: [], // 玩法(多选,默认为空数组)
|
||
};
|
||
|
||
// const defaultDistance = "all"; // 默认距离
|
||
const defaultDistanceQuickFilter = {
|
||
distanceFilter: "",
|
||
order: "0",
|
||
district: "", // 新增:行政区筛选
|
||
};
|
||
|
||
const defaultPageOption = {
|
||
page: 1,
|
||
pageSize: 20,
|
||
};
|
||
|
||
// 页面状态默认值
|
||
const pageStateDefaultValue = {
|
||
// 列表数据
|
||
data: [],
|
||
// 推荐列表
|
||
recommendList: [],
|
||
// 是否展示综合筛选弹窗
|
||
isShowFilterPopup: false,
|
||
// 综合筛选项
|
||
filterOptions: defaultFilterOptions,
|
||
// 距离筛选和快捷筛选
|
||
distanceQuickFilter: defaultDistanceQuickFilter,
|
||
// 综合筛选 选择的筛选数量
|
||
filterCount: 0,
|
||
// 分页
|
||
pageOption: defaultPageOption,
|
||
// 球局数量
|
||
gamesNum: 0,
|
||
// 是否还有更多数据
|
||
isHasMoreData: true,
|
||
// 是否展示无数据
|
||
isShowNoData: false,
|
||
}
|
||
|
||
// 列表页状态
|
||
const listPageStateDefaultValue = {
|
||
...pageStateDefaultValue,
|
||
// 列表页是否显示搜索框自定义导航
|
||
isShowInputCustomerNavBar: false,
|
||
}
|
||
|
||
// 搜索页状态
|
||
const searchPageStateDefaultValue = {
|
||
...pageStateDefaultValue,
|
||
// 搜索结果数据
|
||
data: [],
|
||
// 联想词
|
||
suggestionList: [],
|
||
// 是否显示联想词
|
||
isShowSuggestion: false,
|
||
// 搜索历史数据
|
||
searchHistory: [],
|
||
// 搜索历史数据默认 Top 15
|
||
searchHistoryParams: {
|
||
page: 1,
|
||
pageSize: 15,
|
||
},
|
||
}
|
||
|
||
// const now = new Date();
|
||
|
||
// 公共属性
|
||
const commonStateDefaultValue = {
|
||
// 是否是搜索结果页
|
||
isSearchResult: false,
|
||
// 是否加载中
|
||
loading: false,
|
||
// 错误信息
|
||
error: null,
|
||
// 位置
|
||
location: {
|
||
latitude: 0,
|
||
longitude: 0,
|
||
},
|
||
// 搜索的value
|
||
searchValue: "",
|
||
// 日期区间
|
||
// dateRange: [now, new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000)],
|
||
|
||
// 距离筛选数据
|
||
distanceData: [
|
||
{ id: 0, label: "全城", value: "" },
|
||
{ id: 1, label: "3km", value: "3" },
|
||
{ id: 2, label: "5km", value: "5" },
|
||
{ id: 3, label: "10km", value: "10" },
|
||
],
|
||
// 快捷筛选数据
|
||
quickFilterData: [
|
||
{ label: "智能排序", value: "0" },
|
||
{ label: "距离更近", value: "distance" },
|
||
{ label: "时间更近", value: "time" },
|
||
],
|
||
|
||
// 气泡日期范围
|
||
dateRangeOptions: [
|
||
{ id: 1, label: "本周末", value: "1" },
|
||
{ id: 2, label: "一周内", value: "2" },
|
||
{ id: 3, label: "一月内", value: "3" },
|
||
],
|
||
// 时间气泡数据
|
||
timeBubbleData: [
|
||
{ id: 1, label: "晨间 6:00-10:00", value: "6:00-10:00" },
|
||
{ id: 2, label: "上午 10:00-12:00", value: "10:00-12:00" },
|
||
{ id: 3, label: "中午 12:00-14:00", value: "12:00-14:00" },
|
||
{ id: 4, label: "下午 14:00-18:00", value: "14:00-18:00" },
|
||
{ id: 5, label: "晚上 18:00-22:00", value: "18:00-22:00" },
|
||
{ id: 6, label: "夜间 22:00-24:00", value: "22:00-24:00" },
|
||
],
|
||
cities: [],
|
||
cityQrCode: [],
|
||
area: ['', ''] as [string, string], // 改为两级:国家、省份
|
||
districts: [], // 新增:行政区列表
|
||
}
|
||
|
||
// 创建 store
|
||
export const useListStore = create<TennisStore>()((set, get) => ({
|
||
currentPage: "",
|
||
// 列表页
|
||
listPageState: listPageStateDefaultValue,
|
||
// 搜索及搜索结果页
|
||
searchPageState: searchPageStateDefaultValue,
|
||
|
||
...commonStateDefaultValue,
|
||
gamesNum: 0,
|
||
|
||
// 组装搜索数据
|
||
// 注意:始终使用 state.area,不接收 overrideArea 参数,确保参数一致性
|
||
getSearchParams: () => {
|
||
const state = get();
|
||
const currentPageState = state.isSearchResult ? state.searchPageState : state.listPageState;
|
||
const filterOptions = currentPageState?.filterOptions || {};
|
||
// 全城和快捷筛选
|
||
const distanceQuickFilter = currentPageState?.distanceQuickFilter || {};
|
||
const { distanceFilter, order, district } = distanceQuickFilter || {};
|
||
|
||
// 始终使用 state.area,确保所有接口使用一致的城市参数
|
||
const areaProvince = state.area?.at(1) || "";
|
||
const last_location_province = areaProvince;
|
||
|
||
// city 参数逻辑:
|
||
// 1. 如果选择了行政区(district 有值),使用行政区的名称(label)
|
||
// 2. 如果是"全城"(distanceFilter 为空),不传 city
|
||
let city: string | undefined = undefined;
|
||
if (district) {
|
||
// 从 districts 数组中查找对应的行政区名称
|
||
const selectedDistrict = state.districts.find(item => item.value === district);
|
||
if (selectedDistrict) {
|
||
city = selectedDistrict.label; // 传递行政区名称,如"静安"
|
||
}
|
||
}
|
||
// 如果是"全城"(distanceFilter 为空),city 保持 undefined,不会被传递
|
||
|
||
// 使用 filterOptions 中的 dateRange
|
||
const dateRange: [string, string] = filterOptions?.dateRange || defaultDateRange;
|
||
|
||
// 构建 searchOption
|
||
// 注意:province 必须从 state.area 获取,不能依赖 filterOptions 中可能存在的旧值
|
||
const searchOption: any = {
|
||
...filterOptions,
|
||
title: state.searchValue,
|
||
ntrpMin: filterOptions?.ntrp?.[0],
|
||
ntrpMax: filterOptions?.ntrp?.[1],
|
||
dateRange: dateRange, // 确保始终是两个值的数组
|
||
distanceFilter: distanceFilter,
|
||
// 显式设置 province,确保始终使用 state.area 中的最新值
|
||
province: last_location_province, // 始终使用 state.area 中的 province,确保城市参数一致
|
||
};
|
||
|
||
// 只在有值时添加 city 参数
|
||
if (city) {
|
||
searchOption.city = city;
|
||
}
|
||
|
||
const params = {
|
||
pageOption: currentPageState?.pageOption,
|
||
seachOption: searchOption,
|
||
order: order,
|
||
lat: state?.location?.latitude,
|
||
lng: state?.location?.longitude,
|
||
};
|
||
return params;
|
||
},
|
||
|
||
// 设置列表结果
|
||
setListData: (payload: IPayload & { isAppend?: boolean }) => {
|
||
const state = get();
|
||
const { error, data, loading, count, isAppend = false } = payload;
|
||
const isHasMoreData = count > 0;
|
||
|
||
const currentPageState = state.isSearchResult ? state.searchPageState : state.listPageState;
|
||
const currentData = currentPageState?.data || [];
|
||
const newData = isAppend ? [...currentData, ...(data || [])] : (data || []);
|
||
state.updateCurrentPageState({
|
||
data: newData,
|
||
isHasMoreData,
|
||
isShowNoData: newData?.length === 0,
|
||
});
|
||
|
||
set({
|
||
error,
|
||
loading,
|
||
});
|
||
},
|
||
|
||
// 获取列表数据(常规搜索)
|
||
fetchMatches: async (params, isFirstLoad = false, isAppend = false) => {
|
||
if (get().loading) {
|
||
return;
|
||
}
|
||
set({ loading: true, error: null });
|
||
const { getSearchParams, setListData } = get();
|
||
|
||
try {
|
||
const searchParams = getSearchParams() || {};
|
||
const reqParams = {
|
||
...(searchParams || {}),
|
||
...params,
|
||
};
|
||
|
||
// 获取当前页面的距离筛选
|
||
const state = get();
|
||
const currentPageState = state.isSearchResult ? state.searchPageState : state.listPageState;
|
||
const distanceQuickFilter = currentPageState?.distanceQuickFilter || {};
|
||
|
||
// 是否选择了智能排序
|
||
const isIntegrate = distanceQuickFilter?.order === "0";
|
||
let fetchFn = getGamesList;
|
||
|
||
if (isIntegrate) {
|
||
reqParams.order = "";
|
||
fetchFn = getGamesIntegrateList;
|
||
|
||
// 第一次进入页面时传入 isRefresh 参数
|
||
if (isFirstLoad) {
|
||
reqParams.seachOption.isRefresh = true;
|
||
}
|
||
}
|
||
|
||
const resData = (await fetchFn(reqParams)) || {};
|
||
const { data = {}, code } = resData;
|
||
if (code !== 0) {
|
||
setListData({
|
||
error: "-1",
|
||
data: [],
|
||
loading: false,
|
||
count: 0,
|
||
isAppend,
|
||
});
|
||
return Promise.reject(new Error('获取数据失败'));
|
||
}
|
||
const { count, rows } = data;
|
||
setListData({
|
||
error: '',
|
||
data: rows || [],
|
||
loading: false,
|
||
count,
|
||
isAppend,
|
||
});
|
||
return Promise.resolve();
|
||
} catch (error) {
|
||
setListData({
|
||
error: "",
|
||
data: [],
|
||
loading: false,
|
||
count: 0,
|
||
isAppend,
|
||
});
|
||
return Promise.reject(error);
|
||
}
|
||
},
|
||
|
||
// 获取列表数据
|
||
getMatchesData: async () => {
|
||
const { fetchMatches } = get();
|
||
return await fetchMatches({}, true); // 第一次进入页面,传入 isFirstLoad = true
|
||
},
|
||
|
||
// 同时更新两个列表接口(常规列表和智能排序列表)
|
||
// 注意:不再接收 overrideArea 参数,始终使用 state.area
|
||
refreshBothLists: async () => {
|
||
const state = get();
|
||
const { getSearchParams, setListData } = state;
|
||
const { getGamesList, getGamesIntegrateList } = await import("../services/listApi");
|
||
|
||
try {
|
||
const searchParams = getSearchParams() || {};
|
||
|
||
// 调用常规列表接口
|
||
const listParams = {
|
||
...searchParams,
|
||
order: searchParams.order || "distance",
|
||
};
|
||
const listRes = await getGamesList(listParams);
|
||
|
||
// 调用智能排序列表接口
|
||
const integrateParams = {
|
||
...searchParams,
|
||
order: "",
|
||
seachOption: {
|
||
...searchParams.seachOption,
|
||
isRefresh: true,
|
||
},
|
||
};
|
||
const integrateRes = await getGamesIntegrateList(integrateParams);
|
||
|
||
// 根据当前排序方式更新对应的数据
|
||
const currentPageState = state.isSearchResult ? state.searchPageState : state.listPageState;
|
||
const distanceQuickFilter = currentPageState?.distanceQuickFilter || {};
|
||
const isIntegrate = distanceQuickFilter?.order === "0";
|
||
|
||
if (listRes?.code === 0 && listRes?.data) {
|
||
const { count, rows } = listRes.data;
|
||
if (!isIntegrate) {
|
||
// 如果当前是常规排序,更新常规列表数据
|
||
setListData({
|
||
error: '',
|
||
data: rows || [],
|
||
loading: false,
|
||
count,
|
||
isAppend: false,
|
||
});
|
||
}
|
||
}
|
||
|
||
if (integrateRes?.code === 0 && integrateRes?.data) {
|
||
const { count, rows, recommendList } = integrateRes.data;
|
||
if (isIntegrate) {
|
||
// 如果当前是智能排序,更新智能排序列表数据
|
||
setListData({
|
||
error: '',
|
||
data: rows || [],
|
||
loading: false,
|
||
count,
|
||
isAppend: false,
|
||
});
|
||
}
|
||
// 无论当前排序方式如何,都更新推荐列表
|
||
state.updateCurrentPageState({
|
||
recommendList: recommendList || [],
|
||
});
|
||
}
|
||
|
||
return Promise.resolve();
|
||
} catch (error) {
|
||
console.error("更新列表数据失败:", error);
|
||
return Promise.reject(error);
|
||
}
|
||
},
|
||
|
||
// 获取球局数量
|
||
// 注意:必须和 games/integrate_list 使用相同的参数构建逻辑,确保数据一致性
|
||
// 不再接收 overrideArea 参数,始终使用 state.area
|
||
fetchGetGamesCount: async () => {
|
||
const state = get();
|
||
const { getSearchParams } = state;
|
||
const searchParams = getSearchParams() || {};
|
||
|
||
// 使用和 games/integrate_list 相同的参数构建逻辑
|
||
const params = {
|
||
...searchParams,
|
||
order: "", // 和 integrate_list 保持一致
|
||
seachOption: {
|
||
...searchParams.seachOption,
|
||
isRefresh: true, // 和 integrate_list 保持一致
|
||
},
|
||
};
|
||
|
||
console.log("fetchGetGamesCount 参数:", { area: state.area, params: JSON.stringify(params) });
|
||
const resData = (await getGamesCount(params)) || {};
|
||
const gamesNum = resData?.data?.count || 0;
|
||
console.log("fetchGetGamesCount 结果:", gamesNum);
|
||
set({ gamesNum });
|
||
},
|
||
|
||
// 获取历史搜索数据
|
||
getSearchHistory: async () => {
|
||
try {
|
||
const state = get();
|
||
const params = state.searchPageState?.searchHistoryParams || {};
|
||
const resData = (await getSearchHistory(params)) || {};
|
||
const searchHistory = resData?.data?.records || [];
|
||
set({
|
||
searchPageState: {
|
||
...state.searchPageState,
|
||
searchHistory,
|
||
},
|
||
});
|
||
} catch (error) { }
|
||
},
|
||
|
||
// 清空历史记录
|
||
clearHistory: async () => {
|
||
try {
|
||
const state = get();
|
||
const params = {};
|
||
const resData = (await clearHistory(params)) || {};
|
||
if (resData?.code === 0) {
|
||
set({
|
||
searchPageState: {
|
||
...state.searchPageState,
|
||
searchHistory: [],
|
||
},
|
||
});
|
||
}
|
||
} catch (error) { }
|
||
},
|
||
|
||
// 获取联想
|
||
searchSuggestion: async (val: string) => {
|
||
try {
|
||
const state = get();
|
||
const resData = (await searchSuggestion({ keyword: val, limit: 10 })) || {};
|
||
const recommendations = resData?.data?.recommendations || [];
|
||
const total = resData?.data?.total;
|
||
set({
|
||
searchPageState: {
|
||
...state.searchPageState,
|
||
suggestionList: recommendations,
|
||
isShowSuggestion: total > 0,
|
||
},
|
||
});
|
||
} catch (error) {
|
||
const state = get();
|
||
set({
|
||
searchPageState: {
|
||
...state.searchPageState,
|
||
suggestionList: [],
|
||
isShowSuggestion: true,
|
||
},
|
||
});
|
||
}
|
||
},
|
||
|
||
// 清除错误信息
|
||
clearError: () => {
|
||
set({ error: null });
|
||
},
|
||
|
||
getCurrentPageState: () => {
|
||
const state = get();
|
||
return {
|
||
currentPageState: state.isSearchResult ? state.searchPageState : state.listPageState,
|
||
currentPageKey: state.isSearchResult ? "searchPageState" : "listPageState",
|
||
};
|
||
},
|
||
|
||
// 更新当前页面状态
|
||
updateCurrentPageState: (payload: Record<string, any>) => {
|
||
const state = get();
|
||
const { currentPageState, currentPageKey } = state.getCurrentPageState();
|
||
set({
|
||
[currentPageKey]: { ...currentPageState, ...payload }
|
||
});
|
||
},
|
||
|
||
// 更新综合筛选项
|
||
updateFilterOptions: (payload: Record<string, any>) => {
|
||
const state = get();
|
||
const { currentPageState } = state.getCurrentPageState();
|
||
const filterOptions = { ...currentPageState?.filterOptions, ...payload };
|
||
|
||
// 计算筛选数量:排除 dateRange、ntrp 默认值,以及空数组和空字符串
|
||
const filterCount = Object.entries(filterOptions).filter(([key, value]) => {
|
||
if (key === 'dateRange') return false; // 日期区间不算筛选
|
||
if (key === 'ntrp') {
|
||
// NTRP 只有不是默认值 [1, 5] 时才算筛选
|
||
const ntrp = value as [number, number];
|
||
return ntrp && (ntrp[0] !== 1 || ntrp[1] !== 5);
|
||
}
|
||
// 数组为空数组或字符串为空字符串时不算筛选
|
||
if (Array.isArray(value)) return value.length > 0;
|
||
if (typeof value === 'string') return value !== '';
|
||
return Boolean(value);
|
||
}).length;
|
||
|
||
// 先更新状态
|
||
state.updateCurrentPageState({
|
||
filterOptions,
|
||
filterCount,
|
||
pageOption: defaultPageOption,
|
||
});
|
||
|
||
// 使用 Promise.resolve 确保状态更新后再调用接口
|
||
// 先调用列表接口,然后在列表接口完成后调用数量接口
|
||
Promise.resolve().then(async () => {
|
||
const freshState = get(); // 重新获取最新状态
|
||
// 先调用列表接口
|
||
await freshState.getMatchesData();
|
||
// 列表接口完成后,再调用数量接口
|
||
await freshState.fetchGetGamesCount();
|
||
});
|
||
},
|
||
|
||
// 更新距离和快捷筛选
|
||
updateDistanceQuickFilter: (payload: Record<string, any>) => {
|
||
const state = get();
|
||
const { currentPageState } = state.getCurrentPageState();
|
||
const { distanceQuickFilter } = currentPageState || {};
|
||
const newDistanceQuickFilter = { ...distanceQuickFilter, ...payload };
|
||
|
||
// 先更新状态
|
||
state.updateCurrentPageState({
|
||
distanceQuickFilter: newDistanceQuickFilter,
|
||
pageOption: defaultPageOption,
|
||
});
|
||
|
||
// 使用 Promise.resolve 确保状态更新后再调用接口
|
||
// 先调用列表接口,然后在列表接口完成后调用数量接口
|
||
Promise.resolve().then(async () => {
|
||
const freshState = get(); // 重新获取最新状态
|
||
// 先调用列表接口
|
||
await freshState.getMatchesData();
|
||
// 列表接口完成后,再调用数量接口
|
||
await freshState.fetchGetGamesCount();
|
||
});
|
||
},
|
||
|
||
// 清空综合筛选选项
|
||
clearFilterOptions: async () => {
|
||
const state = get();
|
||
const { getMatchesData, fetchGetGamesCount } = state;
|
||
|
||
state.updateCurrentPageState({
|
||
filterOptions: defaultFilterOptions,
|
||
filterCount: 0,
|
||
pageOption: defaultPageOption,
|
||
});
|
||
// 先调用列表接口
|
||
await getMatchesData();
|
||
// 列表接口完成后,再调用数量接口
|
||
await fetchGetGamesCount();
|
||
},
|
||
|
||
// 加载更多数据
|
||
loadMoreMatches: async () => {
|
||
const state = get();
|
||
const currentPageState = state.isSearchResult ? state.searchPageState : state.listPageState;
|
||
const { pageOption, isHasMoreData } = currentPageState || {};
|
||
|
||
if (!isHasMoreData) {
|
||
return Promise.resolve();
|
||
}
|
||
|
||
const newPageOption = {
|
||
page: (pageOption?.page || 1) + 1,
|
||
pageSize: 20,
|
||
};
|
||
|
||
state.updateCurrentPageState({
|
||
pageOption: newPageOption,
|
||
});
|
||
|
||
// 加载更多时追加数据到现有数组
|
||
return await state.fetchMatches({}, false, true);
|
||
},
|
||
|
||
// 初始化搜索条件 重新搜索
|
||
initialFilterSearch: async (isSearchData = false) => {
|
||
const state = get();
|
||
const { getMatchesData, fetchGetGamesCount } = state;
|
||
|
||
if (state.isSearchResult) {
|
||
set({
|
||
searchPageState: {
|
||
...searchPageStateDefaultValue
|
||
},
|
||
// loading: true,
|
||
});
|
||
} else {
|
||
set({
|
||
listPageState: {
|
||
...listPageStateDefaultValue
|
||
},
|
||
// loading: true,
|
||
});
|
||
}
|
||
if (!isSearchData) {
|
||
return;
|
||
}
|
||
// 先调用列表接口
|
||
await getMatchesData();
|
||
// 列表接口完成后,再调用数量接口
|
||
await fetchGetGamesCount();
|
||
},
|
||
|
||
// 更新store数据
|
||
updateState: (payload: Record<string, any>) => {
|
||
set({
|
||
...(payload || {}),
|
||
});
|
||
},
|
||
|
||
// 更新列表页状态中的特定字段
|
||
updateListPageState: (payload: Record<string, any>) => {
|
||
console.log("===更新列表页状态:", payload);
|
||
const state = get();
|
||
set({
|
||
listPageState: {
|
||
...state.listPageState,
|
||
...payload,
|
||
},
|
||
});
|
||
},
|
||
|
||
// 更新搜索页状态中的特定字段
|
||
updateSearchPageState: (payload: Record<string, any>) => {
|
||
const state = get();
|
||
set({
|
||
searchPageState: {
|
||
...state.searchPageState,
|
||
...payload,
|
||
},
|
||
});
|
||
console.log("===更新搜索页状态:", state);
|
||
},
|
||
|
||
async getCities() {
|
||
const res = await getCities();
|
||
const state = get();
|
||
set({
|
||
...state,
|
||
cities: translateCityData(res.data),
|
||
})
|
||
},
|
||
|
||
async getCityQrCode() {
|
||
const res = await getCityQrCode();
|
||
const state = get();
|
||
set({
|
||
...state,
|
||
cityQrCode: res.data,
|
||
})
|
||
},
|
||
|
||
// 新增:获取行政区列表
|
||
async getDistricts() {
|
||
try {
|
||
const state = get();
|
||
// 从 area 中获取省份,area 格式: ["中国", 省份, 城市]
|
||
const country = "中国";
|
||
const province = state.area?.at(1) || "上海"; // area[1] 是省份
|
||
|
||
const res = await getDistricts({
|
||
country,
|
||
state: province
|
||
});
|
||
|
||
if (res.code === 0 && res.data) {
|
||
const districts = res.data.map((item) => ({
|
||
label: item.cn_city,
|
||
value: item.id.toString(),
|
||
id: item.id,
|
||
}));
|
||
set({ districts });
|
||
return districts;
|
||
}
|
||
return [];
|
||
} catch (error) {
|
||
console.error("获取行政区列表失败:", error);
|
||
return [];
|
||
}
|
||
},
|
||
|
||
updateArea(payload: [string, string]) {
|
||
set({
|
||
area: payload,
|
||
})
|
||
},
|
||
}));
|
||
|
||
// 导出便捷的 hooks
|
||
export const useListState = () => useListStore((state) => state);
|