地区联动


关于地区联动

/**
*
* 接口会提供两个接口,一个查询州,另一个接口用州的item 的code 请求每个州下面国家、
*
* 省、市、的数据
*
* useRegion
* 
*/

import {useState, useEffect} from 'react';
import {getRegionOne, getRegionTwo} from '@/constants/actions';
import {regionSlice} from '@/store/region';
import store from '@/store/index';

const {saveRegion} = regionSlice.actions;

// 深度递归  生成子级以及子级可能存在的子集 item 类型
const deepChildren = (list: any) => {
    return list.map((item: any) => {
        let children: Region[] = [];
      
        // 若接口数据的 child 有子级, 先生成子级别,再执行下面的代码
        if (Array.isArray(item?.child) && item.child.length > 0) {
            children = deepChildren(item.child);
        }
        return {
            value: item.adminDivisionCd,
            label: item.adminDivisionCnNm,
            children,
        };
    });
};

export interface Region {
    value: string;
    label: string;
    children?: Region[];
}

const useRegion = () => {
    const [changePromise, setChangePromise] = useState<Region[]>([]);

    useEffect(() => {
        (async () => {
            const result = await getRegionOne();
           
           // map函数的回调,采用async修饰,返回一个 Promise[] 
            const newList = result.map(async (item: any) => {
                const copyItem = item;
                copyItem.value = item.adminDivisionCd;
                copyItem.label = item.adminDivisionCnNm;

                const res = await getRegionTwo({parentCd: item.value});
                copyItem.children = deepChildren(res);

                return {
                    value: copyItem.value,
                    label: copyItem.label,
                    children: copyItem.children,
                };
            });
                        
            // 使用 Promise.all 将 Promise 数组包装成一个 Promise对象
            // 将转化后变成正常数组的值存入 redux 、存入 useState
            Promise.all(newList).then(res => {
                console.warn('Promise.all(newList).then', res);
                setChangePromise(res);
                store.dispatch(
                    saveRegion({
                        region: res,
                    })
                );
            });
        })();
    }, []);

    // 暴露区域信息实例,可选, 可在需要的组件使用,
    // 但其实存入了 redux 更可能用不上
  
    return {
        region: changePromise,
    };
};

export default useRegion;
// 从省或市的 code 向上寻找 上级的code,并组成一条关系链, [州、国家、省、市]

// 将字符串转化为级联可用的 value
const reverseStr = (str: string, region?: any) => {
    const findArr: string[] = [];

    if (str.constructor === String) {
        const casterList = str // casterList 是一个二维数组
            .split(',')
            .map(item => {
                if (item[0]) {
                    return item.split('-');
                }
                return ['', ''];
            })
            .filter(ele => ele);
      
        // 递归查找
        // 取得省级或者是市级的code码,返回上级 省 --> 国家 --> 州 的数组 findArr : string[]
        // 只有国内需要追加前缀
     
        const deepFind = (list: any, findCode: string, curItem?: any) => {
            list.forEach((item: any) => {
                /**
                * 若找到了,将传入的对象,也就是当前对象的 上级对象的value取出放入数组里,
                * 
                * 同时再次开启查找,条件为当前找到的value
                */
                if (item.value === findCode) {
                    const addItem = curItem?.value || '';
                    findArr.unshift(addItem);
                    deepFind(region, addItem);
                }
                
                /**
                * 若没找到,将当前对象的 children 属性、查找的code、当前对象传入 deepFind 函数,
                *
                * 从children的每一项中查找
                */
              
                if (!(item.value === findCode)) {
                    deepFind(item.children, findCode, item);
                }
            });
        };

        const code = casterList[0][0];
        deepFind(region, code);
      
        // 将得到的关系链前缀追加到 初始数组中,确保 antd 联动的值能够正常回显
        // 只有省市code的关系链数组,缺少上级的国家和州code的关系链,
        // 是无法显示value所对应的label的,只会显示vlaue
      
        const newArr = casterList.map((item: string[]) => {
            return findArr.filter(ele => ele).concat(item);
        });

        return newArr;
    }
};

export default reverseStr;

文章作者: KarlFranz
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 reprint policy. If reproduced, please indicate source KarlFranz !
评论
  目录