瀏覽代碼

【u审批】新增带地图搜索功能组件

samhoo 4 年之前
父節點
當前提交
7cb1f8f5ca

+ 1 - 0
uas-office-web/wxuasapproval/package.json

@@ -13,6 +13,7 @@
     "moment": "^2.22.2",
     "react": "^16.12.0",
     "react-app-rewire-less": "^2.1.3",
+    "react-bmap": "^1.0.130",
     "react-dom": "^16.12.0",
     "react-file-viewer": "^1.2.1",
     "react-infinite-scroller": "^1.2.4",

+ 1 - 1
uas-office-web/wxuasapproval/public/index.html

@@ -48,7 +48,7 @@
 <noscript>
     You need to enable JavaScript to run this app.
 </noscript>
-
+<script type="text/javascript" src="https://api.map.baidu.com/api?v=3.0&ak=T1GtvYvfay3OYbSauKyRSYZCGE31mnXv"></script>
 <div id="root" style="width: 100%;height: 100%;"></div>
 <!--
   This HTML file is a template.

+ 90 - 1
uas-office-web/wxuasapproval/src/components/approvalAdd/FormInput.jsx

@@ -16,8 +16,11 @@ import {
   Toast,
 } from 'antd-mobile'
 import { isObjEmpty, isObjNull } from '../../utils/common'
+import MapSearch from '../map/MapSearch'
 import moment from 'moment'
 
+const prompt = Modal.prompt
+
 export default class FormInput extends Component {
 
   constructor () {
@@ -66,13 +69,17 @@ export default class FormInput extends Component {
         valueItem =
           this.getHtmlcom(billModel)
         break
+      case 'SM':
+        valueItem =
+          this.getSearchMap(billModel, modalOpen)
+        break
       default:
         valueItem =
           this.getTextCom(billModel)
         break
     }
     return (
-      (type === 'DT' || type === 'D' || type === 'T') ? <div>
+      (type === 'DT' || type === 'D' || type === 'T' || type === 'SM') ? <div>
           {valueItem}
         </div> :
         (type === 'MS') ? (this.renderTwoLines(
@@ -147,6 +154,52 @@ export default class FormInput extends Component {
     </div>
   }
 
+  /**
+   * 加载带搜索的地图类型
+   * @param {*} billModel 
+   * @param {*} modalOpen 
+   * @returns 
+   */
+  
+   getSearchMap (billModel, modalOpen) {
+    return <div className='form-common-layout'
+                style={{ minHeight: '32px' }}>
+      <div className='form-input-caption'>{billModel.caption}</div>
+      <div className={billModel.allowBlank == 'F'
+        ? 'form-input-fill'
+        : 'visibleHidden'}>*
+      </div>
+      {
+        <InputItem className='form-input-value' clear
+        placeholder={'请选择'}
+        editable={false}
+        onClick={() => {
+          this.setState({
+            modalOpen: true,
+          })
+        }}
+        value={billModel.getValue()}
+        />
+      }
+      <Modal visible={modalOpen}
+             animationType={'slide-up'}
+             onClose={() => {
+               this.setState({
+                 modalOpen: false,
+               })
+             }}
+             title={billModel.caption}
+             popup
+      >
+        <div className='map-modal-root'>
+            <MapSearch
+              onLocationSelect={this.onMapSelect}/>
+        </div>
+      </Modal>
+    </div>
+            
+  }
+
   /**
    * 文本输入类型
    * @param billModel
@@ -279,6 +332,41 @@ export default class FormInput extends Component {
     }
   }
 
+
+  onMapSelect = (location) => {
+    const { billModel } = this.state
+    this.setState({
+      modalOpen: false,
+    })
+
+    prompt('拜访单位', '请完善单位名称', [
+      {
+        text: '跳过此步', onPress: value => {
+          billModel.value = location.title;
+          this.setState({
+            billModel,
+          }, () => {
+            this.props.onTextChange &&
+            this.props.onTextChange(this.props.groupIndex, this.props.childIndex,
+              location.title)
+          })
+        },
+      },
+      {
+        text: '确定', onPress: value => {
+          billModel.value = value;
+          this.setState({
+            billModel,
+          }, () => {
+            this.props.onTextChange &&
+            this.props.onTextChange(this.props.groupIndex, this.props.childIndex,
+              value)
+          })
+        },
+      },
+    ], 'default', location.title)
+  }
+
   onModalSelect = index => {
     const { modalList } = this.state
     console.log(modalList)
@@ -323,6 +411,7 @@ export default class FormInput extends Component {
       case 'MF':
       case 'SF':
       case 'DF':
+      case 'SM':
         // return false
         return true
     }

+ 10 - 0
uas-office-web/wxuasapproval/src/components/approvalAdd/formCommon.css

@@ -174,3 +174,13 @@
     padding: 4px;
     color: gray;
 }
+
+.map-modal-root {
+    height: 70vh;
+    overflow: auto;
+    align-items: normal;
+}
+
+.map-modal-root::-webkit-scrollbar {
+  display: none;
+}

+ 138 - 0
uas-office-web/wxuasapproval/src/components/map/MapSearch.jsx

@@ -0,0 +1,138 @@
+/**
+ * Created by Hujs on 2021/7/9
+ * Desc: 地图-带搜索功能
+ */
+
+ import React, { Component } from 'react'
+ import {
+   Map,
+   Marker,
+   NavigationControl,
+   ScaleControl,
+   OverviewMapControl,
+ } from 'react-bmap'
+ import './map.css'
+ import { SearchBar } from 'antd-mobile'
+ import { getLocalPosition } from '../../utils/map.util'
+ 
+ export default class MapSearch extends Component {
+ 
+   constructor () {
+     super()
+ 
+     this.state = {
+       center: { lng: 113.887564, lat: 22.554923 },//初始化地址为海纳百川大厦B座
+       searchList: [],
+     }
+   }
+ 
+   componentDidMount () {
+     this.searchBar.focus()
+     const { BMap } = window
+     let that = this
+     this.localSearch = new BMap.LocalSearch(this.map,
+       {
+         renderOptions: {
+           map: this.map,
+         },
+         onSearchComplete: (results) => {
+           if (results) {
+             that.setState({
+               searchList: results.Br,
+             })
+           } else {
+             that.setState({
+               searchList: [],
+             })
+           }
+         },
+       })
+     this.localSearch.disableFirstResultSelection()
+ 
+     getLocalPosition(this.map)
+   }
+ 
+   componentWillUnmount () {
+ 
+   }
+ 
+   render () {
+     const {
+       center,
+       searchList,
+     } = this.state
+ 
+     const searchItems = []
+     if (searchList) {
+       searchList.forEach((item, index) => {
+         searchItems.push(
+            <div
+                key={index}
+                className='map-search-item'
+                onClick={this.onItemClick.bind(this, index)}>
+                <div className='map-search-item-name'>{item.title}</div>
+                <div className='map-search-item-address'>{item.address}</div>
+            </div>,
+         )
+       })
+     }
+     return (
+       <div
+         className='map-search-root'>
+         <SearchBar
+           ref={el => this.searchBar = el}
+           onChange={this.onSearchChange}
+           placeholder={'搜索'}/>
+         <Map
+           ref={ref => {
+             if (ref) {
+               this.map = ref.map
+             }
+           }}
+           style={{ height: '240px' }}
+           center={center}
+           enableScrollWheelZoom
+           enableDragging
+           enableRotate
+           enableScrollWheelZoom
+           zoom="17"
+         >
+           <Marker position={center}/>
+           <NavigationControl/>
+           <ScaleControl/>
+           <OverviewMapControl/>
+         </Map>
+         <div
+           className='map-search-result-list'>
+           {searchItems}
+         </div>
+       </div>
+     )
+   }
+ 
+   /**
+    * 地图搜索
+    * @param value
+    */
+   onSearchChange = value => {
+     if (value) {
+       if (this.localSearch) {
+         this.localSearch.search(value)
+       }
+     } else {
+       this.localSearch.search('')
+       getLocalPosition(this.map)
+     }
+   }
+ 
+   /**
+    * 搜索结果 选择事件回调
+    * @param index
+    */
+   onItemClick = index => {
+     const { searchList } = this.state
+     const { onLocationSelect } = this.props
+     onLocationSelect && onLocationSelect(searchList[index])
+   }
+ }
+ 

+ 51 - 0
uas-office-web/wxuasapproval/src/components/map/map.css

@@ -0,0 +1,51 @@
+.map-box {
+    padding: 10px 15px 24px 15px;
+    background: #fff;
+    margin-bottom: 10px;
+}
+.map-box .map-content {
+    width: 100%;
+    height: 30vh;
+}
+
+  
+.map-search-root {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    flex-direction: column;
+}
+.map-search-root  .map-search-result-list {
+    width: 100%;
+    flex: 1;
+    overflow-y: scroll;
+}
+  
+.map-search-root  .map-search-result-list::-webkit-scrollbar {
+    display: none;
+}
+  
+.map-search-root .map-search-result-list .map-search-item {
+    padding: 8px;
+    border-bottom: 1px solid #ddd;
+    text-align: left;
+}
+.map-search-root .map-search-result-list .map-search-item .map-search-item-name {
+    font-size: 14px;
+    color: #333333;
+    font-weight: bold;
+}
+  
+.map-search-root .map-search-result-list .map-search-item .map-search-item-address {
+    font-size: 12px;
+    margin-top: 6px;
+    color: #666666;
+}
+      
+  
+    
+  
+  
+  
+  
+  

+ 20 - 0
uas-office-web/wxuasapproval/src/utils/map.util.js

@@ -0,0 +1,20 @@
+/**
+ * 获取当前定位,并在地图上标识
+ * @param map
+ */
+export function getLocalPosition(map) {
+    const { BMap } = window
+    const geolocation = new BMap.Geolocation()
+    geolocation.enableSDKLocation()
+    geolocation.getCurrentPosition(function (r) {
+        if (r && r.point) {
+            window.localPoint = r.point
+            if (map) {
+                const mk = new BMap.Marker(r.point)
+                map.addOverlay(mk)
+                map.panTo(r.point)
+                map.setZoom(17)
+            }
+        }
+    })
+}

+ 34 - 1
uas-office-web/wxuasapproval/yarn.lock

@@ -2644,6 +2644,13 @@ babel-plugin-dynamic-import-node@^2.3.3:
   dependencies:
     object.assign "^4.1.0"
 
+babel-plugin-external-helpers@^6.22.0:
+  version "6.22.0"
+  resolved "https://registry.npm.taobao.org/babel-plugin-external-helpers/download/babel-plugin-external-helpers-6.22.0.tgz#2285f48b02bd5dede85175caf8c62e86adccefa1"
+  integrity sha1-IoX0iwK9Xe3oUXXK+MYuhq3M76E=
+  dependencies:
+    babel-runtime "^6.22.0"
+
 babel-plugin-import@^1.10.0:
   version "1.13.1"
   resolved "https://registry.npm.taobao.org/babel-plugin-import/download/babel-plugin-import-1.13.1.tgz#f6cf1acb76c5ce366bae2663ad12bd894316d8db"
@@ -2730,7 +2737,7 @@ babel-preset-react-app@^9.1.1:
     babel-plugin-macros "2.8.0"
     babel-plugin-transform-react-remove-prop-types "0.4.24"
 
-babel-runtime@6.x, babel-runtime@^6.23.0, babel-runtime@^6.26.0:
+babel-runtime@6.x, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0:
   version "6.26.0"
   resolved "https://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
   integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
@@ -7909,6 +7916,11 @@ kind-of@^6.0.0, kind-of@^6.0.2:
   resolved "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
   integrity sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=
 
+kits-js@^0.0.7:
+  version "0.0.7"
+  resolved "https://registry.npm.taobao.org/kits-js/download/kits-js-0.0.7.tgz#4ffb15729ecf4e69994e2591f3ec344496fc470c"
+  integrity sha1-T/sVcp7PTmmZTiWR8+w0RJb8Rww=
+
 kleur@^3.0.3:
   version "3.0.3"
   resolved "https://registry.npm.taobao.org/kleur/download/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
@@ -8473,6 +8485,18 @@ map-visit@^1.0.0:
   dependencies:
     object-visit "^1.0.0"
 
+mapv@^2.0.56:
+  version "2.0.62"
+  resolved "https://registry.npm.taobao.org/mapv/download/mapv-2.0.62.tgz#02489df3814b278839e0d73431ef807e647ca693"
+  integrity sha1-Akid84FLJ4g54Nc0Me+AfmR8ppM=
+  dependencies:
+    babel-plugin-external-helpers "^6.22.0"
+
+mapvgl@^1.0.0-beta.117:
+  version "1.0.0-beta.128"
+  resolved "https://registry.nlark.com/mapvgl/download/mapvgl-1.0.0-beta.128.tgz#b7656f6570f285f9a833c045969cb8ee87dcdec0"
+  integrity sha1-t2VvZXDyhfmoM8BFlpy47ofc3sA=
+
 md5.js@^1.3.4:
   version "1.3.5"
   resolved "https://registry.npm.taobao.org/md5.js/download/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
@@ -11486,6 +11510,15 @@ react-app-rewired@^2.1.5:
   dependencies:
     semver "^5.6.0"
 
+react-bmap@^1.0.130:
+  version "1.0.130"
+  resolved "https://registry.nlark.com/react-bmap/download/react-bmap-1.0.130.tgz#a0abcd345154c3f701bf1613a6a5e95f5207ca45"
+  integrity sha1-oKvNNFFUw/cBvxYTpqXpX1IHykU=
+  dependencies:
+    kits-js "^0.0.7"
+    mapv "^2.0.56"
+    mapvgl "^1.0.0-beta.117"
+
 react-data-grid@^5.0.5:
   version "5.0.5"
   resolved "https://registry.npm.taobao.org/react-data-grid/download/react-data-grid-5.0.5.tgz#529f5acd4750ae0461e9da66f9f30d6f597eed76"