index.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <template>
  2. <view class="jnpf-location">
  3. <u-button class="jnpf-location-btn" @click="handleLocation" v-if="!detailed" size="mini">
  4. <u-icon class="jnpf-location-icon" name="map" />
  5. {{ innerValue.fullAddress ||errTitle ? $t('app.apply.location.relocation') : $t('app.apply.location.location') }}
  6. </u-button>
  7. <view class="location-card" v-if="innerValue.fullAddress">
  8. <view class="location-card-info" @click="getLocation">
  9. <image class="location-card-static-map" :src="staticMapUrl" v-if="enableLocationScope" />
  10. <view class="location-card-address">{{ innerValue.fullAddress }}</view>
  11. <u-icon name="close-circle-fill" v-if="!detailed && !disabled && clearable" @click="handleClear" />
  12. </view>
  13. </view>
  14. <view v-if="errTitle" class="errTitle">{{errTitle}}</view>
  15. </view>
  16. </template>
  17. <script>
  18. import {
  19. getAddress
  20. } from '@/api/common.js'
  21. const defaultValue = {
  22. lat: '',
  23. lng: '',
  24. name: '',
  25. fullAddress: '',
  26. };
  27. export default {
  28. name: 'jnpf-location',
  29. props: {
  30. modelValue: {
  31. type: String,
  32. default: ''
  33. },
  34. autoLocation: {
  35. type: Boolean,
  36. default: false
  37. },
  38. enableLocationScope: {
  39. type: Boolean,
  40. default: false
  41. },
  42. adjustmentScope: {
  43. type: Number,
  44. default: 500
  45. },
  46. enableDesktopLocation: {
  47. type: Boolean,
  48. default: false
  49. },
  50. locationScope: {
  51. type: Array,
  52. default: []
  53. },
  54. disabled: {
  55. type: Boolean,
  56. default: false
  57. },
  58. detailed: {
  59. type: Boolean,
  60. default: false
  61. },
  62. clearable: {
  63. type: Boolean,
  64. default: false
  65. },
  66. },
  67. data() {
  68. return {
  69. innerValue: '',
  70. errTitle: '',
  71. emitKey: ''
  72. }
  73. },
  74. watch: {
  75. modelValue: {
  76. handler(val) {
  77. this.innerValue = val ? JSON.parse(val) : defaultValue
  78. },
  79. immediate: true,
  80. },
  81. },
  82. computed: {
  83. staticMapUrl() {
  84. if (!this.enableLocationScope) return ' ';
  85. const location = this.innerValue.lng + ',' + this.innerValue.lat;
  86. const url =
  87. `${this.define.baseURL}/api/system/Location/staticmap?location=${location}&zoom=19&size=80*80&key=${this.define.aMapWebKey}`;
  88. return url;
  89. }
  90. },
  91. created() {
  92. this.errTitle = ''
  93. this.handleAutoLocation()
  94. this.handleListen()
  95. },
  96. methods: {
  97. handleListen() {
  98. this.emitKey = 'location' + this.jnpf.idGenerator()
  99. uni.$on(this.emitKey, data => {
  100. this.handleConfirm(data)
  101. })
  102. },
  103. handleLocation(val) {
  104. if (this.disabled || this.detailed) return
  105. const data = {
  106. adjustmentScope: this.adjustmentScope,
  107. enableLocationScope: this.enableLocationScope,
  108. enableDesktopLocation: this.enableDesktopLocation,
  109. locationScope: this.locationScope,
  110. emitKey: this.emitKey
  111. }
  112. uni.navigateTo({
  113. url: '/pages/apply/location/index?data=' + JSON.stringify(data)
  114. })
  115. },
  116. handleAutoLocation() {
  117. if (!this.autoLocation || this.innerValue.fullAddress || this.detailed) return;
  118. uni.getLocation({
  119. type: 'gcj02',
  120. isHighAccuracy: true,
  121. success: (e) => {
  122. const getAddressFun = () => {
  123. const query = {
  124. location: e.longitude + ',' + e.latitude,
  125. key: this.define.aMapWebKey
  126. }
  127. getAddress(query).then(res => {
  128. const data = res.data.regeocode.addressComponent;
  129. this.innerValue = {
  130. pName: data.province,
  131. cName: data.city,
  132. adName: data.district,
  133. address: data.streetNumber.street + data.streetNumber
  134. .number,
  135. name: res.data.regeocode.formatted_address,
  136. lng: e.longitude,
  137. lat: e.latitude,
  138. fullAddress: res.data.regeocode.formatted_address,
  139. };
  140. this.$emit('update:modelValue', JSON.stringify(this.innerValue));
  141. this.$emit('change', JSON.stringify(this.innerValue));
  142. }).catch(() => {
  143. this.handelError()
  144. })
  145. }
  146. if (this.enableDesktopLocation && this.locationScope.length) {
  147. let list = [];
  148. for (let i = 0; i < this.locationScope.length; i++) {
  149. const o = this.locationScope[i];
  150. const discount = this.jnpf.getDistance(o.lat, o.lng, e.latitude, e
  151. .longitude) || 0;
  152. list.push(discount > o.radius);
  153. }
  154. if (list.every(o => o === true)) return;
  155. getAddressFun()
  156. } else {
  157. getAddressFun()
  158. }
  159. },
  160. fail: (err) => {
  161. this.handelError()
  162. }
  163. });
  164. },
  165. handleConfirm(item) {
  166. this.innerValue = item ? JSON.parse(item) : defaultValue
  167. this.errTitle = ''
  168. this.onchange()
  169. },
  170. handelError() {
  171. this.errTitle = '定位失败,请检查网络畅通、定位开启后重试'
  172. },
  173. handleClear() {
  174. this.innerValue = defaultValue;
  175. this.$emit('update:modelValue', '');
  176. this.$emit('change', '');
  177. },
  178. onchange() {
  179. let innerValue = this.$u.deepClone(this.innerValue)
  180. this.$emit('update:modelValue', JSON.stringify(innerValue))
  181. this.$emit('change', JSON.stringify(innerValue))
  182. },
  183. openMap() {
  184. uni.openLocation({
  185. latitude: Number(this.innerValue.lat),
  186. longitude: Number(this.innerValue.lng),
  187. name: this.innerValue.name,
  188. address: this.innerValue.address,
  189. success: () => {},
  190. fail: function(error) {
  191. console.log(error)
  192. }
  193. });
  194. },
  195. getLocation() {
  196. if (this.detailed) return this.openMap()
  197. if (this.enableLocationScope) this.handleLocation()
  198. }
  199. }
  200. }
  201. </script>
  202. <style lang="scss">
  203. .jnpf-location {
  204. width: 100%;
  205. display: flex;
  206. flex-wrap: wrap;
  207. justify-content: flex-end;
  208. .jnpf-location-btn {
  209. margin: unset;
  210. .jnpf-location-icon {
  211. font-size: 28rpx;
  212. padding-right: 2px;
  213. }
  214. }
  215. .location-card {
  216. display: flex;
  217. align-items: center;
  218. margin-top: 16rpx;
  219. background: #f2f2f6;
  220. padding: 16rpx;
  221. border-radius: 16rpx;
  222. justify-content: space-between;
  223. .location-card-info {
  224. flex: 1;
  225. display: flex;
  226. align-items: center;
  227. .location-card-static-map {
  228. width: 96rpx;
  229. height: 96rpx;
  230. margin-right: 8rpx;
  231. flex-shrink: 0;
  232. }
  233. .location-card-address {
  234. line-height: 1.5;
  235. padding: 0 8rpx;
  236. word-break: normal;
  237. white-space: normal;
  238. }
  239. }
  240. .location-card-actions {
  241. color: rgb(135, 143, 149);
  242. cursor: pointer;
  243. flex-shrink: 0;
  244. }
  245. }
  246. .errTitle {
  247. color: $u-type-error
  248. }
  249. }
  250. </style>