Skip to content

Commit

Permalink
feat: 区块新增城市联级选择器
Browse files Browse the repository at this point in the history
  • Loading branch information
syb01094648 committed Sep 26, 2023
1 parent 2f782e2 commit 329c967
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 0 deletions.
32 changes: 32 additions & 0 deletions docs/blocks/administrative-select.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
toc: false
order: 3
nav:
title: 区块
path: /blocks
order: 4
---

## 城市联级选择器

### 介绍

用于快速查找省市县位置并迅速定位到指定位置

### 代码演示

#### 默认示例

<code src="./administrative-select/demos/default.tsx" compact></code>

### API

| 参数 | 说明 | 类型 | 默认值 |
| -------------- | ---------------- | ---------------------------------- | ------ |
| value | 指定选中项 | `string[]|number[]` | `--` |
| onChange | 选择完成后的回调 | `(value, selectedOptions) => void` | `--` |
| enableBoundary | 是否显示边界 | `boolean` | `true` |
| autoFit | 是否平移 | `boolean` | `true` |
| boundaryLayer | 边界 layer 属性 | `Omit<LineLayerProps, 'source'>` | `--` |

其他参数可以参照 [Ant Design 5.0 Cascader](https://ant-design.antgroup.com/components/cascader-cn#api)
27 changes: 27 additions & 0 deletions docs/blocks/administrative-select/demos/default.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { LarkMapProps } from '@antv/larkmap';
import { LarkMap } from '@antv/larkmap';
import React, { useState } from 'react';
import { AdministrativeSelect } from '..';

const config: LarkMapProps = {
mapType: 'Gaode',
mapOptions: {
style: 'light',
center: [120.210792, 30.246026],
zoom: 9,
},
};

export default () => {
const [value, setValue] = useState<string[]>([]);
return (
<LarkMap {...config} style={{ height: '300px' }}>
<AdministrativeSelect
onChange={(e: string[]) => {
setValue(e);
}}
value={value}
/>
</LarkMap>
);
};
133 changes: 133 additions & 0 deletions docs/blocks/administrative-select/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import type { LineLayerProps } from '@antv/larkmap';
import { CustomControl, LineLayer, useScene } from '@antv/larkmap';
import type { Feature, MultiLineString} from '@turf/turf';
import { featureCollection, multiLineString } from '@turf/turf';
import { Cascader, message } from 'antd';
import React, { useEffect, useState } from 'react';
import type { AdministrativeSelectProps } from './type';

const defaultLayerOptions: Omit<LineLayerProps, 'source'> = {
shape: 'line',
color: '#ff0000',
size: 2,
style: {
opacity: 0.8,
},
};

export const AdministrativeSelect: React.FC<AdministrativeSelectProps> = ({
placeholder,
expandTrigger,
allowClear,
changeOnSelect,
style,
enableBoundary,
autoFit,
boundaryLayer,
value,
onChange,
...props
}) => {
const [districtFeature, setDistrictFeature] = useState<Feature<MultiLineString> | null>(null);
const scene = useScene();
const [options, setOptions] = useState();

const getCascadeData = (list: any) => {
list.sort((a: { adcode: number }, b: { adcode: number }) => {
return +a.adcode - +b.adcode;
});
if (list.length) {
return list.map((item: any) => {
const { name, districts, adcode } = item;
return {
adcode,
value: adcode,
label: name,
children: getCascadeData(districts),
};
});
} else {
return [];
}
};

useEffect(() => {
fetch(
'https://restapi.amap.com/v3/config/district?key=98d10f05a2da96697313a2ce35ebf1a2&keywords=中华人民共和国&subdistrict=3&extensions=base',
)
.then((res) => res.json())
.then((res) => {
setOptions(getCascadeData(res.districts[0].districts));
});
}, []);

useEffect(() => {
if (value) {
const name = value[value.length - 1];
fetch(
`https://restapi.amap.com/v3/config/district?keywords=${name}&subdistrict=0&key=98d10f05a2da96697313a2ce35ebf1a2&extensions=all`,
)
.then((res) => res.json())
.then((res) => {
if (res.status === '1' && res.districts?.length && scene) {
const [lng, lat] = (res.districts[0].center as string).split(',').map((item) => +item);
if (autoFit) {
scene.setZoomAndCenter(9, [lng, lat]);
}
const positions: number[][][] = [];

res.districts.forEach((district: any) => {
(district.polyline as string).split('|').forEach((chunk) => {
positions.push(chunk.split(';').map((item) => item.split(',').map((num) => +num)));
});
});
setDistrictFeature(multiLineString(positions));
}
})
.catch(() => {
message.error('围栏数据请求失败');
});
}
}, [value]);
return (
<>
<CustomControl position="lefttop">
<Cascader
options={options}
value={value}
onChange={(e: any, option: any) => {
onChange?.(e, option);
if (!value) {
setDistrictFeature(null);
}
}}
allowClear={allowClear}
placeholder={placeholder}
changeOnSelect={changeOnSelect}
style={style}
expandTrigger={expandTrigger}
{...props}
/>
</CustomControl>
{enableBoundary && (
<LineLayer
source={{
data: featureCollection(districtFeature ? [districtFeature] : []),
}}
{...boundaryLayer}
/>
)}
</>
);
};

AdministrativeSelect.defaultProps = {
placeholder: '可选择省/市/县',
expandTrigger: 'hover',
allowClear: true,
changeOnSelect: true,
style: { width: 250 },
enableBoundary: true,
autoFit: true,
boundaryLayer: defaultLayerOptions,
};
19 changes: 19 additions & 0 deletions docs/blocks/administrative-select/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { LineLayerProps } from '@antv/larkmap';
import type { CascaderProps } from 'antd';

export interface AdministrativeSelectProps extends Omit<CascaderProps, 'value' | 'options' | 'onChange'> {
value: string[];
onChange?: (value: string[], selectedOptions: any) => void;
/**
* 是否显示边界
*/
enableBoundary?: boolean;
/**
* 是否平移
*/
autoFit?: boolean;
/**
* layer属性
*/
boundaryLayer?: Omit<LineLayerProps, 'source'>;
}

0 comments on commit 329c967

Please sign in to comment.