index.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. <template>
  2. <view class="map-box">
  3. <search ref="searchRef" :mapConfig="mapConfig" @handleSearch="handleSearch" v-show="showMap" />
  4. <tiandituMap ref="tiandituMapRefs" @handleSearch="$refs.searchRef.onSearchFocus()" @clickMap="handleClickMap"
  5. @moveMap="moveMapSearch" @onLoadTianDiTu="initMaps" @onSelect="selectPoint" :apiKey="apiKey"
  6. @handleMapSite="handleMapSite" @centre-text-callback="e => centreText = e" :siteListArr='siteListArr'
  7. :searchDot="searchDot" @openHint="$refs.HintContentRef.open()" @openFeedback="goPages('feedback')" />
  8. <Touchbox ref="TouchboxRef" :maxHeight="0.8" v-show="showMap && siteListArr && siteListArr.length > 0"
  9. :zIndex="1001" @currentHeight="e => TouchHeight = e">
  10. <template #touchSlot>
  11. <!-- <view class="centre-box" v-if="SearchText">
  12. <text class="text">为您展示</text>
  13. <text class="text-val one-row">{{SearchText}}</text>
  14. <text class="text">相关的大厅</text>
  15. </view> -->
  16. <view class="centre-box" v-if="SearchText || centreText">
  17. <svg t="1734080022350" class="position-icon" viewBox="0 0 1024 1024" version="1.1"
  18. xmlns="http://www.w3.org/2000/svg" p-id="4287" xmlns:xlink="http://www.w3.org/1999/xlink">
  19. <path d="M512 512m-80 0a80 80 0 1 0 160 0 80 80 0 1 0-160 0Z" p-id="4288"></path>
  20. <path
  21. d="M960 480h-33.632C910.752 276.16 747.84 113.248 544 97.632V64a32 32 0 1 0-64 0v33.632C276.16 113.248 113.248 276.16 97.632 480H64a32 32 0 0 0 0 64h33.632C113.248 747.84 276.16 910.752 480 926.368V960a32 32 0 1 0 64 0v-33.632C747.84 910.752 910.752 747.84 926.368 544H960a32 32 0 1 0 0-64zM544 862.368V800a32 32 0 1 0-64 0v62.368C311.424 847.104 176.896 712.576 161.632 544H224a32 32 0 1 0 0-64H161.632C176.896 311.424 311.424 176.896 480 161.632V224a32 32 0 0 0 64 0V161.632c168.576 15.296 303.104 149.792 318.368 318.368H800a32 32 0 1 0 0 64h62.368c-15.264 168.576-149.792 303.104-318.368 318.368z"
  22. p-id="4289"></path>
  23. </svg>
  24. <text class="text">为您展示</text>
  25. <text class="text-val one-row">{{SearchText || centreText}}</text>
  26. <text class="text">{{ SearchText ? '相关的大厅' : '附近的大厅'}}</text>
  27. </view>
  28. </template>
  29. <template #contentSlot>
  30. <!-- <scroll-view :style="{'height': getScrollHeight(TouchHeight , centreText)}" scroll-y="true" -->
  31. <scroll-view :style="{'height': TouchHeight + 'px'}" scroll-y="true" :show-scrollbar="false">
  32. <template v-for="(item , index) in siteListArr">
  33. <siteListModel :index="index" :info="item" @checkSiteDetails="handleMapSite" />
  34. </template>
  35. </scroll-view>
  36. </template>
  37. </Touchbox>
  38. <siteDetails ref="siteDetailsRef" />
  39. <!-- 提示 -->
  40. <HintContent ref="HintContentRef" :mapConfig="mapConfig" />
  41. </view>
  42. </template>
  43. <script>
  44. import search from "./model/search.vue"
  45. import siteListModel from "./model/siteList.vue";
  46. import tools from '@/components/tiandituMap/tools.js'
  47. import {
  48. getMapCenterPoint_Api,
  49. getMapList_Api,
  50. getMapConfig_Api,
  51. getVisituvpv_Api
  52. } from "@/api/map.js"
  53. import siteDetails from "./model/siteDetails.vue"
  54. import $config from "@/config/index.js"
  55. import {
  56. EventBus
  57. } from "@/utils/vueBus.js"
  58. import {
  59. getLocation
  60. } from "@/utils/tool.js"
  61. import serviceCenter from "./model/service-center.vue"
  62. import HintContent from "./model/hint.vue"
  63. import {
  64. getUUID
  65. } from "@/utils/tool.js";
  66. export default {
  67. name: 'tdtmap',
  68. components: {
  69. search,
  70. siteListModel,
  71. serviceCenter,
  72. siteDetails,
  73. HintContent,
  74. },
  75. data() {
  76. return {
  77. //是否通过搜索查询点位
  78. searchDot: false,
  79. // 是否显示地图
  80. showMap: false,
  81. SearchText: '',
  82. longitude: '114.28944',
  83. latitude: '30.66195',
  84. apiKey: $config.tianKey,
  85. winWidth: 0,
  86. winHeight: 0,
  87. winTop: 0,
  88. datalist: [],
  89. startY: 0,
  90. selectItem: {},
  91. iStatusBarHeight: 0,
  92. siteListArr: [],
  93. TouchHeight: 0,
  94. centreText: null,
  95. centreTextHeight: uni.upx2px(80),
  96. searchContent: null,
  97. mapConfig: {},
  98. }
  99. },
  100. created() {
  101. // getLocation();
  102. // this.getMapCenterPoint()
  103. },
  104. mounted() {
  105. this.getMapConfig()
  106. const userLabel = getUUID();
  107. const refererStr = document.referrer;
  108. getVisituvpv_Api({
  109. userLabel,
  110. refererStr,
  111. })
  112. // setTimeout(() => {
  113. // console.log("this.$refs.SelectMapNavigationRef = " , this.$refs.SelectMapNavigationRef)
  114. // this.$refs.SelectMapNavigationRef.open()
  115. // }, 3000)
  116. this.disableScroll();
  117. this.open(this.longitude, this.latitude);
  118. },
  119. beforeDestroy() {
  120. try {
  121. document.removeEventListener('touchmove');
  122. document.body.removeEventListener('mousewheel');
  123. document.body.removeEventListener('DOMMouseScroll');
  124. document.removeEventListener('onmousewheel', function() {
  125. window.event.returnValue = false;
  126. });
  127. } catch (error) {
  128. //TODO handle the exception
  129. }
  130. },
  131. watch: {
  132. },
  133. methods: {
  134. async getMapConfig() {
  135. const res = await getMapConfig_Api()
  136. console.log('地图配置',res)
  137. this.mapConfig = res || {}
  138. },
  139. async initMaps() {
  140. console.warn('--------天地图加载完成--------');
  141. this.$emit('onLoad')
  142. try {
  143. uni.showLoading()
  144. const { longitude, latitude } = await getLocation();
  145. // console.log("longitude, latitude = " , longitude, latitude)
  146. if(longitude && latitude){
  147. this.longitude = longitude;
  148. this.latitude = latitude;
  149. this.movePT({longitude , latitude} , true)
  150. uni.hideLoading()
  151. this.handleSearch()
  152. }else{
  153. throw new Error()
  154. }
  155. // this.longitude = '114.25497';
  156. // this.latitude = '30.62832';
  157. // this.movePT({longitude:this.longitude , latitude:this.latitude} , true)
  158. // uni.hideLoading()
  159. // this.handleSearch()
  160. } catch (error) {
  161. uni.hideLoading()
  162. this.getMapCenterPoint()
  163. } finally{
  164. this.showMap = true;
  165. }
  166. },
  167. /**
  168. * 移动到中心点
  169. * PT 点位
  170. * refresh 移动之后是否刷新获取数据
  171. */
  172. movePT(PT , refresh = false){
  173. this.$refs.tiandituMapRefs.SelectedDot({longitude:this.longitude , latitude:this.latitude} , !refresh)
  174. },
  175. // 获取地图中心点
  176. getMapCenterPoint() {
  177. uni.showLoading()
  178. getMapCenterPoint_Api().then(res => {
  179. const {
  180. longitude,
  181. latitude,
  182. mapTypeIcon
  183. } = res || {};
  184. this.longitude = longitude;
  185. this.latitude = latitude;
  186. this.movePT({longitude , latitude} , true)
  187. this.handleSearch()
  188. }).catch(err => {
  189. this.open(null, null)
  190. }).finally(() => {
  191. uni.hideLoading()
  192. })
  193. },
  194. open(lon, lat, mapTypeIcon) {
  195. if (lon && lat) {
  196. this.$nextTick(() => {
  197. this.$refs.tiandituMapRefs.initCharts(lon, lat, mapTypeIcon)
  198. })
  199. } else {
  200. uni.showModal({
  201. title: '提示',
  202. content: '地图中心点获取错误,请联系管理员!',
  203. success: res => {
  204. // console.log("showModal == ", res)
  205. if (res.confirm) {}
  206. }
  207. })
  208. }
  209. },
  210. handleSearch(val = {}) {
  211. this.showMap = true;
  212. const parms = {
  213. ...val,
  214. longitude: this.longitude,
  215. latitude: this.latitude,
  216. radius: 5000
  217. };
  218. // 记录搜索框中的内容
  219. this.SearchText = parms.locationName;
  220. // 判断是否通过收索
  221. this.searchDot = parms.search
  222. // 如果存在收索条件,则去掉 范围 和 中心点
  223. if (parms.locationName || parms.mapTypeId || parms.areaCode) {
  224. delete parms.radius
  225. // delete parms.latitude
  226. // delete parms.longitude
  227. }
  228. delete parms.search;
  229. this.searchContent = parms
  230. getMapList_Api(parms).then(res => {
  231. if (!res || res.length === 0) {
  232. uni.showToast({
  233. title: "当前区域无办理点位",
  234. icon: 'none'
  235. })
  236. }
  237. this.siteListArr = res || [];
  238. // this.$store.dispatch('map/updateDotInfo')
  239. // this.$store.dispatch('updateDotInfo')
  240. }).catch(err => {
  241. this.siteListArr = [];
  242. }).finally(() => {
  243. clearTimeout(this.SearchTimeout)
  244. this.SearchTimeout = null;
  245. })
  246. },
  247. getScrollHeight(TouchHeight, centreText) {
  248. const h = centreText ? this.centreTextHeight : 0
  249. return TouchHeight - h - 15 + 'px'
  250. },
  251. disableScroll() {
  252. if (typeof window.addEventListener === 'function') {
  253. document.addEventListener('touchmove', function(e) {
  254. e.preventDefault();
  255. }, {
  256. passive: false
  257. });
  258. document.body.addEventListener('mousewheel', function(e) {
  259. e.preventDefault();
  260. });
  261. document.body.addEventListener('DOMMouseScroll', function(e) {
  262. e.preventDefault();
  263. });
  264. } else {
  265. document.attachEvent('onmousewheel', function() {
  266. window.event.returnValue = false;
  267. });
  268. }
  269. },
  270. // 点击地图
  271. handleClickMap() {
  272. if (this.$refs.TouchboxRef) {
  273. this.$refs.TouchboxRef.concealList()
  274. }
  275. },
  276. // 点击地图标注点位
  277. handleMapSite(parmas = {}) {
  278. // const { Lng, Lat } = parmas;
  279. const Lng = parmas.Lng || parmas.longitude;
  280. const Lat = parmas.Lat || parmas.latitude;
  281. // const item = (this.siteListArr || []).find(el => el.longitude == Lng && el.latitude == Lat);
  282. // this.checkSiteDetails(item)
  283. const item = (this.siteListArr || []).find(el => el.longitude == Lng && el.latitude == Lat);
  284. if (item) {
  285. this.checkSiteDetails(item);
  286. this.$refs.tiandituMapRefs.Trenderjs.handleSiteList(this.siteListArr)
  287. }
  288. },
  289. // 查看点位详情
  290. checkSiteDetails(info) {
  291. if (info) {
  292. this.$refs.tiandituMapRefs.Trenderjs.SelectedDot(info, true)
  293. this.handleClickMap();
  294. this.$refs.siteDetailsRef.openDetails(info)
  295. }
  296. },
  297. moveMapSearch(parms) {
  298. console.log('moveMapSearch = ' ,1 )
  299. const {
  300. Lng,
  301. Lat
  302. } = parms;
  303. this.longitude = Lng;
  304. this.latitude = Lat;
  305. if(this.$refs.searchRef){
  306. this.$refs.searchRef.onSearchFocus()
  307. }else{
  308. this.handleSearch()
  309. }
  310. //
  311. // console.log("moveMapSearch", Lng, Lat)
  312. },
  313. // //普通搜索
  314. // handleSearch(val = {}) {
  315. // const parms = {
  316. // ...val,
  317. // longitude: this.longitude,
  318. // latitude: this.latitude,
  319. // radius: 5000
  320. // };
  321. // getMapList_Api(parms).then(res => {
  322. // if (!res || res.length === 0) {
  323. // uni.showToast({
  324. // title: "当前区域无办理点位",
  325. // icon: 'none'
  326. // })
  327. // }
  328. // this.siteListArr = res || [];
  329. // }).catch(err => {
  330. // this.siteListArr = [];
  331. // })
  332. // },
  333. close() {
  334. this.visible = false
  335. },
  336. onConfirm() {
  337. if (Object.keys(this.selectItem).length) {
  338. this.visible = false
  339. this.$emit('onSelect', this.selectItem)
  340. } else {
  341. tools.createMessage('请选择位置')
  342. }
  343. },
  344. upDateLonLat(lon, lat) {
  345. if (lon && lat) {
  346. this.$refs.tiandituMapRefs.upDataCharts(lon, lat)
  347. } else {
  348. console.error('请传入lon, lat')
  349. }
  350. },
  351. tianidtuSearch(value) {
  352. if (value.city) {
  353. this.cityInfoSearch(value)
  354. } else {
  355. this.infoSearch(value)
  356. }
  357. },
  358. async infoSearch(value) { // 地理编码查询
  359. let params = {
  360. ds: {
  361. "keyWord": value.keyword,
  362. },
  363. tk: this.apiKey,
  364. }
  365. let resData = await tools.createRequest('https://api.tianditu.gov.cn/geocoder', params, true)
  366. if (resData.status === '0') {
  367. const location = resData.location
  368. const formateOne = tools.formatterAdressLocation(resData, 3)
  369. this.datalist = [formateOne]
  370. this.selectItem = datalist
  371. this.$refs.tiandituMapRefs.upDataCharts(location.lon, location.lat)
  372. }
  373. },
  374. async cityInfoSearch(value) { // 地名搜索2.0
  375. let params = {
  376. postStr: {
  377. "keyWord": value.keyword,
  378. "queryType": 12,
  379. "start": 0,
  380. "count": 10,
  381. "specify": value.city.value
  382. },
  383. type: 'query',
  384. tk: this.apiKey,
  385. }
  386. let resData = await tools.createRequest('https://api.tianditu.gov.cn/v2/search', params, true)
  387. if (resData.status.infocode === 1000) {
  388. const {
  389. pois: aPoints,
  390. count
  391. } = resData
  392. if (count === '0' || !aPoints || !aPoints.length) {
  393. return tools.createMessage('没有找到该地址')
  394. }
  395. const {
  396. pois,
  397. keyWord,
  398. lonlat
  399. } = aPoints[0]
  400. const formateData = aPoints.map((item) => tools.formatterAdressLocation(item, 2))
  401. this.datalist = formateData
  402. this.selectItem = formateData[0]
  403. const [lon, lat] = lonlat.split(',')
  404. this.$refs.tiandituMapRefs.upDataCharts(lon, lat)
  405. } else {
  406. tools.createMessage('数据异常', 1000, false, 'error')
  407. }
  408. },
  409. selectListItem(item) {
  410. this.$refs.tiandituMapRefs.upDataCharts(item.location.lon, item.location.lat)
  411. },
  412. selectPoint(e) {
  413. this.domMinHeight = '0vh'
  414. this.datalist = [e]
  415. this.selectItem = e
  416. },
  417. // start(e) {
  418. // const clientY = e.changedTouches[0].clientY
  419. // this.startY = clientY
  420. // },
  421. // end(e) {
  422. // const transformY = e.changedTouches[0].clientY - this.startY;
  423. // switch (true) {
  424. // case transformY > 50:
  425. // console.log('下划')
  426. // this.domMaxHeight = '20vh'
  427. // this.domMinHeight = '0vh'
  428. // break;
  429. // case transformY < -50:
  430. // console.log('上划')
  431. // this.domMaxHeight = '50vh'
  432. // this.domMinHeight = '50vh'
  433. // break;
  434. // default:
  435. // break;
  436. // }
  437. // },
  438. selectCard(item) {
  439. this.domMaxHeight = '20vh'
  440. this.domMinHeight = '0vh'
  441. this.selectItem = item
  442. this.selectListItem(item)
  443. },
  444. setTouchHeight(val) {
  445. // console.log('setScrollHeight = ', val)
  446. // 实时返回的滑动组件高度
  447. this.TouchHeight = val;
  448. },
  449. setScrollMaxHeight(val) {
  450. //最大高度
  451. this.scrollMaxHeight = val;
  452. },
  453. // 页面跳转
  454. goPages() {
  455. // 'feedback'
  456. uni.navigateTo({
  457. url: "/pages/feedback/feedback"
  458. })
  459. }
  460. }
  461. }
  462. </script>
  463. <style lang="scss" scope>
  464. .map-box {
  465. width: 100vw;
  466. height: 100vh;
  467. /* position: fixed;
  468. left: 0;
  469. top:0;
  470. right: 0;
  471. bottom: 0; */
  472. }
  473. .mask {
  474. /* overflow: hidden; */
  475. position: fixed;
  476. left: 0;
  477. background-color: #FFFFFF;
  478. z-index: 399;
  479. }
  480. /* footer */
  481. .list-boxd {
  482. position: absolute;
  483. bottom: 0;
  484. left: 0;
  485. z-index: 401;
  486. right: 0;
  487. border-radius: 14px 14px 0 0;
  488. background: #FFFFFF;
  489. transition: all 1s;
  490. }
  491. .list-header {
  492. height: 20px;
  493. position: relative;
  494. border-bottom: 1px solid #f3f4f6;
  495. cursor: pointer;
  496. }
  497. .list-header::after {
  498. position: absolute;
  499. left: 50%;
  500. top: 50%;
  501. transform: translate(-50%, -50%);
  502. content: '';
  503. height: 6px;
  504. width: 60px;
  505. border-top: 1px solid #e8e8e8;
  506. border-bottom: 1px solid #e8e8e8;
  507. }
  508. .list-content {
  509. max-height: 50vh;
  510. overflow-y: scroll;
  511. }
  512. .card {
  513. min-height: 44px;
  514. padding: 12px;
  515. position: relative;
  516. display: flex;
  517. justify-content: space-between;
  518. align-items: center;
  519. }
  520. .card-left {
  521. display: flex;
  522. flex-direction: column;
  523. justify-content: center;
  524. }
  525. .card-right {
  526. padding-right: 10px;
  527. }
  528. .arrow {
  529. border-top: 2px solid #666666;
  530. border-right: 2px solid #666666;
  531. width: 10px;
  532. height: 10px;
  533. transform: rotate(45deg);
  534. }
  535. .card:active {
  536. background-color: #f3f4f6;
  537. }
  538. .card::after {
  539. position: absolute;
  540. content: '';
  541. bottom: 0;
  542. height: 1px;
  543. background-color: #e8e8e8;
  544. width: 90%;
  545. }
  546. .card:last-child::after {
  547. height: 0;
  548. background-color: #FFFFFF;
  549. }
  550. .card-title {
  551. font-size: 18px;
  552. }
  553. .card-text {
  554. color: #e8e8e8;
  555. font-size: 13px;
  556. }
  557. .centre-box {
  558. max-width: 100%;
  559. height: 77rpx;
  560. padding: 0 30rpx;
  561. display: inline-flex;
  562. align-items: center;
  563. .position-icon {
  564. flex-shrink: 0;
  565. width: 36rpx;
  566. margin-right: 10rpx;
  567. path {
  568. fill: #929292;
  569. }
  570. }
  571. text {
  572. flex-shrink: 0;
  573. font-size: 26rpx;
  574. color: #666666;
  575. font-weight: 700;
  576. }
  577. .text-val {
  578. flex: 1;
  579. flex-shrink: 0;
  580. color: #0090FF;
  581. padding: 0 5rpx;
  582. // display: flex;
  583. // align-items: center;
  584. // .text {
  585. // flex-shrink: 0;
  586. // flex: 1;
  587. // color: #329BF9;
  588. // padding: 0 5rpx;
  589. // }
  590. // font-size: 24rpx;
  591. // color: #329BF9;
  592. // padding: 0 5rpx;
  593. // // .one-row{
  594. // // width: auto;
  595. // // flex: 1;
  596. // // }
  597. }
  598. }
  599. </style>