mapSelectModal.vue 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. <template>
  2. <BasicModal
  3. v-bind="$attrs"
  4. @register="register"
  5. :title="t('layout.map.mapSelect')"
  6. @ok="handleSubmit"
  7. @cancel="handleCancel"
  8. :scaleControl="true"
  9. :width="828"
  10. :minHeight="500"
  11. @resize="handleRsize"
  12. destroyOnClose
  13. centered
  14. >
  15. <GoogleMap
  16. ref="mapRef"
  17. :api-key="googleKey"
  18. mapId="japan_4dkankan"
  19. :center="center"
  20. :map-type-control="false"
  21. :disable-default-ui="true"
  22. :language="lang"
  23. region="JP"
  24. :zoom="7"
  25. :minZoom="2"
  26. :scaleControl="true"
  27. :scaleControlOptions="{
  28. position: 22,
  29. }"
  30. map-type-id="roadmap"
  31. :mapTypeControlOptions="{
  32. style: 1,
  33. position: 3,
  34. }"
  35. style="width: 800px; height: 500px"
  36. @click="handleMapClick"
  37. v-loading="loadingRef"
  38. :loading-tip="t('common.loadingText')"
  39. >
  40. <CustomControl position="TOP_LEFT">
  41. <div class="p-20px">
  42. <a-input id="pac-input" allow-clear />
  43. </div>
  44. </CustomControl>
  45. <AdvancedMarker
  46. v-show="searchMarkerShow"
  47. ref="searchMarkerRef"
  48. :options="{
  49. position: searchMarker,
  50. title: searchMarkerTitle,
  51. }"
  52. />
  53. </GoogleMap>
  54. <div v-if="searchMarker.lng || searchMarker.lat">
  55. {{ t('layout.map.lat') }} {{ searchMarker.lat }}, {{ t('layout.map.lng') }}
  56. {{ searchMarker.lng }}</div
  57. >
  58. <template #centerFooter> </template>
  59. </BasicModal>
  60. </template>
  61. <script lang="ts">
  62. import { computed, defineComponent, onDeactivated, ref, unref, watch } from 'vue';
  63. import { BasicModal, useModalInner } from '/@/components/Modal';
  64. import { useI18n } from '/@/hooks/web/useI18n';
  65. import {
  66. GoogleMap,
  67. AdvancedMarker,
  68. // MarkerCluster,
  69. // // InfoWindow,
  70. CustomControl,
  71. } from 'vue3-google-map';
  72. import { useLocaleStore } from '/@/store/modules/locale';
  73. const { t } = useI18n();
  74. const localeStore = useLocaleStore();
  75. export default defineComponent({
  76. components: { BasicModal, GoogleMap, CustomControl, AdvancedMarker },
  77. props: {
  78. open: Boolean,
  79. currentLatLng: {
  80. type: Object as PropType<{
  81. lat: number;
  82. lng: number;
  83. }>,
  84. },
  85. },
  86. emits: ['register', 'success', 'update'],
  87. setup(props, { emit }) {
  88. // const { createMessage } = useMessage();
  89. // const sceneNum = ref('');
  90. const location = ref('');
  91. const loadingRef = ref(true);
  92. const center = { lat: 35.717, lng: 139.731 };
  93. const mapRef = ref();
  94. const searchMarker = ref({ lat: 0, lng: 0 });
  95. const searchMarkerShow = ref(false);
  96. const searchMarkerTitle = ref('');
  97. const searchMarkerRef = ref();
  98. const isCanClick = ref(false);
  99. const googleKey = computed(() => import.meta.env.VITE_GOOGLE_KEY);
  100. const lang = computed(() => localeStore.getLocale);
  101. const [register, { closeModal }] = useModalInner((_) => {
  102. console.warn('useModalInner-entry');
  103. // resetMapview();
  104. // data && onDataReceive(data);
  105. });
  106. watch(
  107. () => [mapRef.value?.ready, props.currentLatLng],
  108. ([ready, currentLatLng]) => {
  109. if (!ready) return;
  110. console.log('ready', ready, unref(currentLatLng));
  111. loadingRef.value = false;
  112. const map = mapRef.value.map;
  113. if (map) {
  114. const defaultBounds = {
  115. north: center.lat + 0.1,
  116. south: center.lat - 0.1,
  117. east: center.lng + 0.1,
  118. west: center.lng - 0.1,
  119. };
  120. const input = document.getElementById('pac-input') as HTMLInputElement;
  121. const options = {
  122. bounds: defaultBounds,
  123. componentRestrictions: { country: ['jp'] },
  124. fields: ['address_components', 'geometry', 'icon', 'name'],
  125. strictBounds: false,
  126. };
  127. setTimeout(() => {
  128. // @ts-ignore
  129. const autocomplete = new google.maps.places.Autocomplete(input, options);
  130. // debugger;
  131. isCanClick.value = true;
  132. console.log('map', map);
  133. autocomplete.bindTo('bounds', map);
  134. autocomplete.addListener('place_changed', () => {
  135. const place = autocomplete.getPlace();
  136. if (!place.geometry || !place.geometry.location) {
  137. // window.alert("No details available for input: '" + place.name + "'");
  138. return;
  139. }
  140. // If the place has a geometry, then present it on a map.
  141. if (place.geometry.viewport) {
  142. map.fitBounds(place.geometry.viewport);
  143. } else {
  144. map.setCenter(place.geometry.location);
  145. map.setZoom(17);
  146. }
  147. searchMarker.value.lat = place.geometry.location.lat();
  148. searchMarker.value.lng = place.geometry.location.lng();
  149. console.log('last-get', searchMarker.value);
  150. searchMarkerShow.value = true;
  151. if (unref(searchMarkerRef)) {
  152. searchMarkerRef.value.marker.position = searchMarker.value;
  153. }
  154. const input = document.getElementById('pac-input') as HTMLInputElement;
  155. searchMarkerTitle.value = input.value;
  156. });
  157. }, 600);
  158. }
  159. if (currentLatLng?.lat && currentLatLng?.lng) {
  160. // debugger;
  161. console.warn('entry');
  162. setTimeout(() => {
  163. searchMarker.value.lat = Number(currentLatLng.lat);
  164. searchMarker.value.lng = Number(currentLatLng.lng);
  165. console.log('last-get', searchMarker.value);
  166. searchMarkerShow.value = true;
  167. if (searchMarkerRef.value) {
  168. searchMarkerRef.value.marker.position = searchMarker.value;
  169. }
  170. map.setCenter(searchMarker.value);
  171. map.setZoom(17);
  172. }, 800);
  173. } else {
  174. resetMapview();
  175. }
  176. },
  177. {
  178. deep: true,
  179. },
  180. );
  181. // function onDataReceive(data) {
  182. // console.log('Data Received', data);
  183. // data &&
  184. // setFieldsValue({
  185. // ...data,
  186. // });
  187. // // sceneNum.value = data.num;
  188. // }
  189. const resetMapview = () => {
  190. if (unref(searchMarkerRef).marker) {
  191. console.warn('resetMapview');
  192. searchMarkerRef.value.marker.position = { lat: 0, lng: 0 };
  193. }
  194. searchMarkerShow.value = false;
  195. searchMarker.value = { lat: 0, lng: 0 };
  196. mapRef.value?.map?.setCenter(center);
  197. mapRef.value?.map?.setZoom(7);
  198. const input = document.getElementById('pac-input') as HTMLInputElement;
  199. if (input) {
  200. input.value = '';
  201. }
  202. };
  203. const handleMapClick = async (event) => {
  204. if (!isCanClick.value) {
  205. return;
  206. }
  207. const { lat, lng } = event.latLng;
  208. searchMarker.value.lat = lat();
  209. searchMarker.value.lng = lng();
  210. console.log('searchMarkerRef', searchMarkerRef.value.marker.position);
  211. searchMarkerRef.value.marker.position = searchMarker.value;
  212. searchMarkerTitle.value = '';
  213. };
  214. const handleSubmit = async () => {
  215. if (searchMarker.value.lat || searchMarker.value.lng) {
  216. emit('update', searchMarker.value);
  217. }
  218. resetMapview();
  219. setTimeout(closeModal, 200);
  220. };
  221. const handleCancel = async () => {
  222. resetMapview();
  223. };
  224. const handleRsize = () => {
  225. console.log('handleRsize');
  226. };
  227. onDeactivated(() => {
  228. console.warn('onDeactivated');
  229. });
  230. return {
  231. t,
  232. register,
  233. handleSubmit,
  234. closeModal,
  235. location,
  236. handleMapClick,
  237. loadingRef,
  238. lang,
  239. mapRef,
  240. center,
  241. searchMarker,
  242. handleCancel,
  243. handleRsize,
  244. googleKey,
  245. searchMarkerRef,
  246. searchMarkerShow,
  247. searchMarkerTitle,
  248. };
  249. },
  250. });
  251. </script>
  252. <style lang="less" scoped>
  253. .map-select {
  254. display: flex;
  255. flex-direction: row;
  256. gap: 0 20px;
  257. }
  258. </style>