Commit 2e3fd9b0 authored by XieZhiXiong's avatar XieZhiXiong

feat: 抽离 区域选择 AreaSelect 组件

parent 35ac7554
/*
* @Description: 省市区选择组件子项
*/
import React, { useState, useEffect } from 'react';
import { Select } from 'antd';
import { getManageAreaByPcode } from '@/services/ManageV2Api';
export type AreaSelectValueType = {
/**
* 名称
*/
name?: string,
/**
* 编码
*/
code: string,
}
export type OptionType = {
label: string,
value: string,
}
interface AreaSelectItemProps {
/**
* 父级code,null 表示第一层级,也就是省
*/
pcode: string | null,
/**
* 值,code数组
*/
value?: AreaSelectValueType,
/**
* 选择触发改变
*/
onChange?: (value: AreaSelectValueType) => void,
/**
* 自定义外部 className
*/
customClassName?: string,
}
const AreaSelectItem: React.FC<AreaSelectItemProps> = (props) => {
const { pcode, value, onChange, customClassName } = props;
const [innerValue, setInnerValue] = useState<string | undefined>(undefined);
const [options, setOptions] = useState<OptionType[]>([]);
const [loading, setLoading] = useState<boolean>(false);
const getAreaByPcode = (code?: string) => getManageAreaByPcode({
pcode: code,
});
const initProvinceOptions = async () => {
if (pcode === undefined) {
setOptions([]);
return;
}
setLoading(true);
const res = await getAreaByPcode(pcode);
if (res.code === 1000) {
setOptions(res.data.map((item) => ({ label: item.name, value: item.code })));
}
setLoading(false);
};
useEffect(() => {
initProvinceOptions();
}, [pcode]);
useEffect(() => {
if ('value' in props) {
setInnerValue(value?.code);
}
}, [value]);
const triggerChange = (value: AreaSelectValueType) => {
if (onChange) {
onChange(value);
}
};
const handleSelectChange = (value: string) => {
if (!('value' in props)) {
setInnerValue(value);
}
triggerChange(value ? {
name: options.find((curOptions) => curOptions.value === value)?.label || '',
code: value,
} : undefined);
};
return (
<Select
className={customClassName}
options={options}
value={innerValue}
onChange={handleSelectChange}
loading={loading}
allowClear
/>
);
};
export default AreaSelectItem;
\ No newline at end of file
.area-select {
&-item {
width: 100%;
}
}
\ No newline at end of file
/*
* @Description: 省市区选择组件
*/
import React, { useState, useEffect } from 'react';
import { Row, Col } from 'antd';
import themeConfig from '@/../config/lingxi.theme.config';
import AreaSelectItem, { AreaSelectValueType } from './AreaSelectItem';
import styles from './index.less';
interface AreaSelectProps {
/**
* 值,code数组
*/
value?: AreaSelectValueType[],
/**
* 选择触发改变
*/
onChange?: (value: AreaSelectValueType[]) => void,
}
const MAX = 4; // 到街道
const AreaSelect: React.FC<AreaSelectProps> = (props) => {
const {
value,
onChange,
} = props;
const [innerValues, setInnerValues] = useState<AreaSelectValueType[]>([]);
useEffect(() => {
if ('value' in props && value.length) {
setInnerValues(value);
}
}, [value]);
const triggerChange = (value: AreaSelectValueType[]) => {
if (onChange) {
onChange(value);
}
};
const handleSelectChange = (value: AreaSelectValueType, index: number) => {
let newInnerValues = [...innerValues];
newInnerValues[index] = value;
// 如果是清空操作,则把当前层级之后的 选项 及 值 也清空
if (!value) {
let i = index + 1;
while (i < newInnerValues.length) {
newInnerValues[i] = undefined;
i++;
}
newInnerValues = newInnerValues.filter(Boolean);
triggerChange([]);
}
if (!('value' in props)) {
setInnerValues(newInnerValues);
}
// 全部选择了才触发 onChange
if (newInnerValues.length === MAX) {
triggerChange(newInnerValues);
}
};
return (
<div className={styles['area-select']}>
<Row gutter={parseInt(themeConfig['@padding-sm'])}>
<Col span={6}>
<AreaSelectItem
pcode={null}
customClassName={styles['area-select-item']}
value={innerValues[0]}
onChange={(value) => handleSelectChange(value, 0)}
/>
</Col>
<Col span={6}>
<AreaSelectItem
pcode={innerValues[0]?.code}
customClassName={styles['area-select-item']}
value={innerValues[1]}
onChange={(value) => handleSelectChange(value, 1)}
/>
</Col>
<Col span={6}>
<AreaSelectItem
pcode={innerValues[1]?.code}
customClassName={styles['area-select-item']}
value={innerValues[2]}
onChange={(value) => handleSelectChange(value, 2)}
/>
</Col>
<Col span={6}>
<AreaSelectItem
pcode={innerValues[2]?.code}
customClassName={styles['area-select-item']}
value={innerValues[3]}
onChange={(value) => handleSelectChange(value, 3)}
/>
</Col>
</Row>
</div>
);
};
export default AreaSelect;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment