| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- <template>
- <v-dialog v-model="props.isLatlngModal" persistent width="50rem">
- <div class="v-common-dialog-wrapper custom-dialog">
- <div class="modal-tit">
- <strong>지도로 검색</strong>
- <button class="btn-close" @click="$emit('closeModal')"></button>
- </div>
- <div class="v-common-dialog-content">
- <div class="map-area" id="map2"></div>
- <div class="map-address">
- <strong>주소 :</strong>
- <p class="color-blue2" v-if="!objSetLatlng.address">
- ※ 마우스로 위치를 지정하세요
- </p>
- <p style="" v-else>{{ objSetLatlng.address }}</p>
- </div>
- </div>
- <div class="btn-wrap">
- <v-btn class="custom-btn btn-white mini" @click="$emit('closeModal')">
- 취소
- </v-btn>
- <v-btn class="custom-btn btn-blue mini" @click="fnSaveLatlng"> 저장 </v-btn>
- </div>
- </div>
- </v-dialog>
- </template>
- <script setup>
- /***********************
- * import
- ************************/
- import { useI18n } from "vue-i18n";
- import useUtil from "@/composables/useUtil";
- import useValid from "@/composables/useValid";
- import useEnumCode from "@/composables/useEnumCode";
- /***********************
- * plugins inject
- ************************/
- const { $toast, $log, $dayjs, $eventBus } = useNuxtApp();
- // props
- const props = defineProps({
- isLatlngModal: Boolean,
- address: String,
- centerPosition: Object,
- });
- // 참조가능 데이터 설정
- defineExpose({
- fnInit,
- fnReset,
- });
- // 발신 이벤트 선언
- const emit = defineEmits(["closeModal", "setLatlng"]);
- const i18n = useI18n();
- /***********************
- * data & created
- ************************/
- const map = ref(null); // 카카오 맵 객체
- const marker = ref(null); // 카카오맵 마커(핀) 객체
- const geocoder = ref(null);
- // 주소위치설정값
- const objSetLatlng = ref({
- lat: "", // 위도
- lng: "", // 경도
- address: "", // 주소
- regionalCode: "", // 지역명 (코드로 변환필요)
- });
- const sidoCode = ref([]);
- watchEffect(() => {
- fnGetEnumCode(useLangStore().getLang);
- });
- /**
- * ENUM 업데이트
- * @param lang
- */
- function fnGetEnumCode(lang) {
- let objEnum = useEnumCode.getEnumCode(lang);
- // ...objEnum.sidoCode
- sidoCode.value = _cloneDeep(objEnum.sidoCode);
- }
- /***********************
- * Methods
- ************************/
- function fnInit() {
- if (!useUtil.isNull(props.address)) {
- objSetLatlng.value.address = _cloneDeep(props.address);
- }
- nextTick().then(() => {
- if (window.kakao && window.kakao.maps) {
- loadMap();
- } else {
- loadScript();
- }
- });
- }
- function fnReset() {
- objSetLatlng.value = {
- lat: "",
- lng: "",
- address: "",
- };
- }
- /**
- * kakao 스크립트 로드
- */
- function loadScript() {
- const script = document.createElement("script");
- script.async = true;
- script.onload = () => {
- window.kakao.maps.load(loadMap);
- };
- script.src = `//dapi.kakao.com/v2/maps/sdk.js?autoload=false&libraries=services,clusterer,drawing&appkey=${
- import.meta.env.VITE_APP_KAKAO_APP_KEY
- }`;
- document.head.appendChild(script);
- }
- /**
- * kakao 지도 로드
- */
- async function loadMap() {
- const mapContainer = document.getElementById("map2");
- let mapOption = {
- center: new kakao.maps.LatLng(props.centerPosition.lat, props.centerPosition.lng), // 지도의 중심좌표
- level: 3, // 지도의 확대 레벨
- };
- map.value = new kakao.maps.Map(mapContainer, mapOption);
- // 주소-좌표 변환 객체를 생성합니다
- geocoder.value = new kakao.maps.services.Geocoder();
- // 지도를 클릭한 위치에 표출할 마커입니다
- marker.value = new kakao.maps.Marker({
- // 지도 중심좌표에 마커를 생성합니다
- position: map.value.getCenter(),
- });
- // 지도에 마커를 표시합니다
- marker.value.setMap(map.value);
- let zoomControl = new kakao.maps.ZoomControl();
- // map.value.addControl(zoomControl, kakao.maps.ControlPosition.BOTTOMRIGHT)
- fnSetEventListener(); // 지도 이벤트 등록
- }
- /**
- * 지도 클릭 이벤트
- */
- function fnSetEventListener() {
- kakao.maps.event.addListener(map.value, "click", function (mouseEvent) {
- // 클릭한 위도, 경도 정보
- let latlng = mouseEvent.latLng;
- marker.value.setPosition(latlng);
- // 위/경도값으로 주소 조회
- fnSearchAddrDetail(latlng);
- // 위치값 설정
- objSetLatlng.value.lat = latlng.getLat();
- objSetLatlng.value.lng = latlng.getLng();
- });
- }
- /**
- * 위/경도 값으로 주소 구하기
- */
- function fnSearchAddrDetail(coords) {
- return new Promise((resolve, reject) => {
- fnSearchDetailAddrFromCoords(coords, function (result, status) {
- if (status === kakao.maps.services.Status.OK) {
- var detailAddr = !!result[0].road_address
- ? result[0].road_address.address_name
- : "";
- detailAddr += `(${result[0].address.address_name})`;
- objSetLatlng.value.address = detailAddr;
- objSetLatlng.value.regionalCode = fnGetRegionCode(
- result[0].address.region_1depth_name
- );
- resolve();
- } else {
- reject(status);
- }
- });
- });
- }
- function fnSearchDetailAddrFromCoords(coords, callback) {
- geocoder.value.coord2Address(coords.getLng(), coords.getLat(), callback);
- }
- // 지역코드 변환
- function fnGetRegionCode(regionName) {
- let regionCode = "";
- sidoCode.value.forEach((item) => {
- if (item.title.includes(regionName)) {
- regionCode = item.value;
- }
- });
- return regionCode;
- }
- /**
- * 저장
- */
- async function fnSaveLatlng() {
- if (useUtil.isNull(objSetLatlng.value.lat) || useUtil.isNull(objSetLatlng.value.lng)) {
- let latlng = new kakao.maps.LatLng(
- props.centerPosition.lat,
- props.centerPosition.lng
- );
- try {
- await fnSearchAddrDetail(latlng);
- objSetLatlng.value.lat = latlng.getLat();
- objSetLatlng.value.lng = latlng.getLng();
- } catch (error) {
- $log.debug("[주소위치설정 실패][error]", JSON.stringify(error));
- }
- }
- let params = {
- lat: objSetLatlng.value.lat.toFixed(8),
- lng: objSetLatlng.value.lng.toFixed(8),
- address: objSetLatlng.value.address,
- regionalCode: objSetLatlng.value.regionalCode,
- };
- emit("setLatlng", params);
- }
- </script>
|