109 lines
4.8 KiB
JavaScript
109 lines
4.8 KiB
JavaScript
import React, { useState, useRef, useEffect } from "react";
|
||
import { Row, Col, Input, List, Empty, Spin, } from 'antd';
|
||
import { SearchOutlined, CheckCircleFilled } from '@ant-design/icons';
|
||
import OpenLayer from '../openlayer';
|
||
import Styles from './web.module.less';
|
||
import { useFeatures } from '../../../platforms/web';
|
||
export default function Locate(props) {
|
||
const [mode, setMode] = useState('dragMap');
|
||
const [searchValue, setSearchValue] = useState('');
|
||
const [searchLoading, setSearchLoading] = useState(false);
|
||
const [pois, setPois] = useState();
|
||
const [currentPoi, setCurrentPoi] = useState();
|
||
const searchRef = useRef();
|
||
// 这里不能用useFeatures,因为无法引用lib里面的provider,引用src注入是不行的
|
||
const featureGeo = useFeatures().geo;
|
||
const searchFn = () => {
|
||
if (searchValue?.length > 1) {
|
||
setSearchLoading(true);
|
||
featureGeo.searchPoi(searchValue, props.areaId, undefined, 0, 10).then((result) => {
|
||
setSearchLoading(false);
|
||
setPois(result.map((ele, idx) => ({
|
||
...ele,
|
||
id: idx,
|
||
coordinate: [ele.longitude, ele.latitude],
|
||
})));
|
||
// setCurrentPoi(pois[0]);
|
||
}, (error) => {
|
||
console.warn(error);
|
||
setPois(undefined);
|
||
setSearchLoading(false);
|
||
});
|
||
}
|
||
else {
|
||
setPois(undefined);
|
||
}
|
||
};
|
||
let handle;
|
||
useEffect(() => {
|
||
handle = setTimeout(searchFn, 1000);
|
||
}, [searchValue]);
|
||
const center = currentPoi?.coordinate || props.coordinate;
|
||
const Locate = (<List className={Styles["location-list"]} header={<Input ref={searchRef} placeholder="请输入完整名称(如“浙江大学”)而非简称(如“浙大”)" value={searchValue} allowClear onChange={(e) => {
|
||
clearTimeout(handle);
|
||
setSearchValue(e.target.value);
|
||
}} prefix={<SearchOutlined />} onFocus={() => {
|
||
setMode('searchPoi');
|
||
}} onBlur={() => {
|
||
}}/>}>
|
||
{mode === 'searchPoi' && (<React.Fragment>
|
||
{searchLoading ? (<div className={Styles['location-list-meta']}>
|
||
<Spin delay={0} spinning size="default"/>
|
||
</div>) : (pois?.length
|
||
? pois.map((poi, index) => {
|
||
return (<div key={poi.id} onClick={() => {
|
||
setCurrentPoi(poi);
|
||
props.onLocated({
|
||
poiName: poi.poiName,
|
||
coordinate: poi.coordinate,
|
||
areaId: poi.areaId,
|
||
});
|
||
}}>
|
||
<List.Item actions={[
|
||
<div style={{
|
||
width: 24,
|
||
}}>
|
||
{currentPoi?.id ===
|
||
poi.id && (<CheckCircleFilled className={Styles['location-list-checked']}/>)}
|
||
</div>,
|
||
]}>
|
||
<List.Item.Meta title={poi.poiName}/>
|
||
</List.Item>
|
||
</div>);
|
||
})
|
||
: (<div className={Styles['location-list-meta']}>
|
||
<Empty description={`没有${searchValue}相关的地名搜索结果`} image={Empty.PRESENTED_IMAGE_SIMPLE}/>
|
||
</div>))}
|
||
</React.Fragment>)}
|
||
</List>);
|
||
const Map2 = props.Map || OpenLayer;
|
||
if (window.innerWidth > 480) {
|
||
return (<Row gutter={[16, 16]} style={{
|
||
width: '100%',
|
||
minHeight: 600,
|
||
maxHeight: '100%',
|
||
}}>
|
||
<Col xs={24} sm={14}>
|
||
<Map2 style={{ height: '100%' }} id="location-map" center={center} markers={center ? [center] : undefined}/>
|
||
</Col>
|
||
<Col xs={24} sm={10}>
|
||
{Locate}
|
||
</Col>
|
||
</Row>);
|
||
}
|
||
return (<Col style={{
|
||
width: '100%',
|
||
height: '100%',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
alignItems: 'stretch',
|
||
}}>
|
||
<Row>
|
||
<Map2 style={{ height: 400, width: '100%' }} id="location-map" center={center} markers={center ? [center] : undefined}/>
|
||
</Row>
|
||
<Row style={{ flex: 1, marginLeft: 5, marginRight: 5 }}>
|
||
{Locate}
|
||
</Row>
|
||
</Col>);
|
||
}
|