index.tsx 7.0 KB
import React, { useState, useEffect } from 'react';
import { Input, Space, Select, Divider, Cascader } from 'antd';
import AMapLoader from '@amap/amap-jsapi-loader';
import './index.less';
import areaData from '@/utils/areaData';
import { getAreaData, getAreaNamesByCodes } from '@/utils/format';
import $ from 'jquery';
// 获取平铺的地区数据
const areaDatas = getAreaData(areaData);

declare global {
  interface Window {
    _AMapSecurityConfig: any;
    AMapUI: any;
    AMap: any;
  }
}

const { Search } = Input;

window._AMapSecurityConfig = {
  securityJsCode: 'f4e73616d1028a16dad9556a0d493571',
};

const MapRender: React.FC = (props: any) => {
  const [map, setMap] = useState<any>(null);
  const [marker, setMarker] = useState<any>(null);
  const [infoWindow, setInfoWindow] = useState<any>(null);
  const [mapVisble, setMapVisble] = useState<boolean>(true);
  const { poiPicker, setPoiPicker, open, setSelectCode, addressName } = props;
  const initMap = async () => {
    const AMap = await AMapLoader.load({
      key: '6b7ba7695c5c2c76d10610a3be45a0f1', // 申请好的Web端开发者Key,首次调用 load 时必填
      version: '1.4.15', // 指定要加载的 JS API 的版本,缺省时默认为 1.4.15
      plugins: ['AMap.Scale'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
      AMapUI: {
        version: '1.0',
      },
    });

    if (AMap) {
      if (!map) {
        const tempMap = new AMap.Map(addressName + 'map');

        setMap(tempMap);
        tempMap.addControl(new AMap.Scale());
      }

      if (!marker) {
        setMarker(new AMap.Marker());
      }
      if (!infoWindow) {
        setInfoWindow(
          new AMap.InfoWindow({
            offset: new AMap.Pixel(0, -20),
          }),
        );
      }
    }
    window.AMapUI.setDomLibrary($);
    if (window.AMapUI) {
      window.AMapUI.loadUI(['misc/PoiPicker', 'misc/PositionPicker'], function (PoiPicker: any) {
        if (!poiPicker) {
          const tempPoiPicker = new PoiPicker({
            //city:'北京',
            input: addressName + 'search',
          });
          setPoiPicker(tempPoiPicker);
        }
      });
    }
  };

  const initWindowMap = async () => {
    if (!map) {
      const tempMap = new window.AMap.Map(addressName + 'map', {
        zoom: 10,
      });
      setMap(tempMap);
    }
    if (!marker) {
      // @ts-ignore
      setMarker(new window.AMap.Marker());
    }
    if (!infoWindow) {
      setInfoWindow(
        new window.AMap.InfoWindow({
          offset: new window.AMap.Pixel(0, -20),
        }),
      );
    }
    if (window.AMapUI) {
      window.AMapUI.loadUI(['misc/PoiPicker', 'misc/PositionPicker'], function (PoiPicker: any) {
        if (!poiPicker) {
          const tempPoiPicker = new PoiPicker({
            //city:'北京',
            input: addressName + 'search',
          });
          setPoiPicker(tempPoiPicker);
        }
      });
    }
  };

  useEffect(() => {
    const search = document.getElementById(addressName + 'search');
    search?.focus();
  }, [document.getElementById(addressName + 'search')]);

  useEffect(() => {
    if (document.getElementById(addressName + 'map')) {
      if (window.AMap) {
        initWindowMap();
      } else {
        initMap();
      }
    } else {
      setMapVisble(!mapVisble);
    }
    if (poiPicker) {
      //初始化poiPicker
      poiPicker.on('poiPicked', function (poiResult: any) {
        const { onChange, setOpen } = props;
        const poi = poiResult.item;
        const { adcode }: { adcode: string } = poi;
        let provideCode = adcode.substring(0, 2) + '0000';
        let cityCode = adcode.substring(0, 4) + '00';
        let areaCode = adcode;
        map.clearMap();
        marker.setMap(map);
        infoWindow.setMap(map);

        marker.setPosition(poi.location);
        infoWindow.setPosition(poi.location);

        // 根据code获取省市区名称
        const info = getAreaNamesByCodes([provideCode, cityCode, areaCode], areaDatas);
        // infoWindow.setContent(
        //   'POI信息: <pre>' + JSON.stringify(info, null, 2) + '</pre>',
        // );
        // infoWindow.open(map, marker.getPosition());
        map.setCenter(marker.getPosition());

        const { location = {}, address = '' } = poi;
        const { lng, lat } = location;
        const [provide, city, district] = info;

        if (onChange) {
          // 给表单组件赋值
          onChange({
            address,
            province_code: provideCode,
            city_code: cityCode,
            district_code: areaCode,
            provide,
            city,
            district,
            lng: lng + '',
            ltg: lat + '',
          });
        }
        setSelectCode([provideCode, cityCode, areaCode]);
        setOpen(false);
      });
    }
  }, [open, poiPicker, mapVisble]);

  return <div className="map" id={addressName + 'map'}></div>;
};

const MapSelect = (props: any) => {
  const { value = {}, addressName = '', cascaderStyle = {}, selectStyle = {} } = props;
  const [poiPicker, setPoiPicker] = useState<any>(null);
  const [open, setOpen] = useState(false);
  const [searchValue, setSearchValue] = useState('');
  const [selectCode, setSelectCode] = useState<any>([]);
  const { province_code, city_code, district_code } = value;

  useEffect(() => {
    if (province_code && city_code && district_code) {
      setSelectCode([province_code, city_code, district_code]);
    }
  }, [district_code]);

  useEffect(() => {
    setSearchValue(value?.address);
  }, [value?.address]);

  return (
    <Space.Compact style={{ width: '100%' }}>
      <Cascader
        options={areaData}
        style={cascaderStyle}
        value={selectCode}
        placeholder="省/市/区"
        disabled
      />
      <Select
        open={open}
        value={value?.address}
        dropdownMatchSelectWidth={false}
        style={selectStyle}
        placeholder="请输入关键字选取地点"
        onDropdownVisibleChange={(isopen) => {
          if (isopen) {
            setOpen(true);
            return;
          }
          setOpen(false);
        }}
        dropdownRender={() => (
          <div style={{ overflow: 'auto' }}>
            <Search
              id={addressName + 'search'}
              placeholder="请输入关键字选取地点"
              value={searchValue}
              onPressEnter={(e: any) => {
                if (poiPicker && e.target.value) {
                  poiPicker.searchByKeyword(e.target.value);
                }
                setSearchValue(e.target.value);
              }}
              onChange={(e) => {
                setSearchValue(e.target.value);
              }}
              // onSearch={(value) => {}}
            />
            <Divider style={{ margin: '8px 0' }} />
            <MapRender
              {...props}
              open={open}
              setOpen={setOpen}
              poiPicker={poiPicker}
              setPoiPicker={setPoiPicker}
              setSelectCode={setSelectCode}
            />
          </div>
        )}
      />
    </Space.Compact>
  );
};

export default MapSelect;