Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend
Deploy Frontend / deploy (push) Successful in 7m13s
Deploy Frontend / deploy (push) Successful in 7m13s
This commit is contained in:
@@ -659,7 +659,7 @@ GisOlLayer.prototype = {
|
||||
this.searchLayer = null;
|
||||
}
|
||||
},
|
||||
showSearchResultsFromGeoJSON: function (lyrTyNm, featureId) {
|
||||
showSearchResultsFromGeoJSON: function (lyrTyNm, featureId, options) {
|
||||
//레이어 타입 설정(point, line 등. 이걸 style에서 사용)
|
||||
const layerCode = GisApp.layerCode;
|
||||
const matched = Object.values(layerCode).find(obj => obj.lyrTyNm === lyrTyNm);
|
||||
@@ -674,10 +674,15 @@ GisOlLayer.prototype = {
|
||||
|
||||
// 1) 로드 완료시 extent 맞추기
|
||||
const onLoadEnd = () => {
|
||||
// 이전 검색 source의 지연 응답은 현재 선택을 변경하지 않는다.
|
||||
if (layer.getSource() !== source || this.searchLayer !== layer) return;
|
||||
if (Object.keys(source.nullGeometryFeatures_).length > 0) showBusinessUserMessage('해당 시설의 위치 정보가 없습니다.');
|
||||
|
||||
const feats = source.getFeatures();
|
||||
if (feats && feats.length > 0) {
|
||||
const extent = feats[0].getGeometry()?.getExtent();
|
||||
// 선택적 소비자만 성공 경계에서 초기화/취소를 결정한다.
|
||||
if (options?.beforeFocus && options.beforeFocus(extent) === false) return;
|
||||
const select = GisApp.Module.select;
|
||||
select.selectFeature(feats[0], false);
|
||||
} else {
|
||||
@@ -740,7 +745,7 @@ GisOlLayer.prototype = {
|
||||
* @param {string} lyrTyNm 레이어 타입명
|
||||
* @param {Array|string} featureIds 피처 ID 배열 또는 단일 ID
|
||||
*/
|
||||
showMultipleSearchResultsFromGeoJSON: function (lyrTyNm, featureIds) {
|
||||
showMultipleSearchResultsFromGeoJSON: function (lyrTyNm, featureIds, options) {
|
||||
|
||||
const layerCode = GisApp.layerCode;
|
||||
const matched = Object.values(layerCode).find(obj => obj.lyrTyNm === lyrTyNm);
|
||||
@@ -754,10 +759,13 @@ GisOlLayer.prototype = {
|
||||
const source = this.getMultiFeatureSourceFromGeoserver(lyrTyNm, featureIds);
|
||||
|
||||
const onLoadEnd = async () => {
|
||||
if (layer.getSource() !== source || this.searchLayer !== layer) return;
|
||||
const feats = source.getFeatures();
|
||||
if (feats && feats.length > 0) {
|
||||
const focusExtent = this.combineExtents(feats.map(f => f.getGeometry()?.getExtent()));
|
||||
if (options?.beforeFocus && options.beforeFocus(focusExtent) === false) return;
|
||||
const select = GisApp.Module.select;
|
||||
await select.resetSelectedFeature();
|
||||
select.resetSelectedFeature();
|
||||
for (const feature of feats) select.selectMultiFeature(feature, true);
|
||||
const geometries = feats.map(f => f.getGeometry());
|
||||
if (geometries.length > 0) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
import { SelectBox, type SelectDataType } from "../../../ui";
|
||||
import { Button } from "@common/components/ui";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
|
||||
import { showBusinessUserMessage } from "../../../lib/user-message";
|
||||
import GisApp from "../lib/gis.core";
|
||||
import {
|
||||
@@ -34,6 +34,10 @@ interface SearchBarProps {
|
||||
facilityLayerFilter?: FacilityLayerFilter;
|
||||
/** 관망도 전용 3개 셀렉트와 조회 버튼을 하나로 연결한 검색바 레이아웃이다. */
|
||||
integrated?: boolean;
|
||||
/** 지도 목록 선택이 성공했을 때만 증가하는 선택적 초기화 revision이다. */
|
||||
resetRevision?: number;
|
||||
/** 직접 검색조건 조작이 이전 비동기 지도 선택을 취소할 수 있게 알린다. */
|
||||
onSearchInteraction?: () => void;
|
||||
}
|
||||
|
||||
interface CenterSelectDataType extends SelectDataType {
|
||||
@@ -46,7 +50,13 @@ export const ProcSearchBar = ({
|
||||
sidoSearchZoom = 11,
|
||||
facilityLayerFilter,
|
||||
integrated = false,
|
||||
resetRevision,
|
||||
onSearchInteraction,
|
||||
}: SearchBarProps) => {
|
||||
/** 초기화·조건 변경 이전 시설 후보 응답이 현재 선택을 되살리지 못하게 한다. */
|
||||
const facilityRequestRef = useRef(0);
|
||||
/** 라벨 변경은 선택을 지우지 않고 새 revision에서만 초기화한다. */
|
||||
const appliedResetRevisionRef = useRef<number | undefined>(undefined);
|
||||
const [sidoValue, setSidoValue] = useState("0");
|
||||
const [sigunValue, setSigunValue] = useState("0");
|
||||
const [sidoData, setSidoData] = useState<CenterSelectDataType[]>([
|
||||
@@ -157,6 +167,7 @@ export const ProcSearchBar = ({
|
||||
sidoNm: string,
|
||||
currentFacilityType?: string,
|
||||
) => {
|
||||
const request = ++facilityRequestRef.current;
|
||||
const type = currentFacilityType ?? facilityType;
|
||||
if (!type || type === "0") return;
|
||||
|
||||
@@ -240,6 +251,7 @@ export const ProcSearchBar = ({
|
||||
}));
|
||||
}
|
||||
|
||||
if (request !== facilityRequestRef.current) return;
|
||||
const sorted = list
|
||||
.slice()
|
||||
.sort((a, b) => a.text.localeCompare(b.text, "ko"));
|
||||
@@ -248,6 +260,20 @@ export const ProcSearchBar = ({
|
||||
},
|
||||
[defaultFacilityData, facilityLayerFilter, facilityType],
|
||||
);
|
||||
/** 외부 이동은 검색값만 초기화하고 지도·레이어 및 원천 지역 목록은 유지한다. */
|
||||
useLayoutEffect(() => {
|
||||
if (resetRevision === undefined || appliedResetRevisionRef.current === resetRevision) return;
|
||||
appliedResetRevisionRef.current = resetRevision;
|
||||
facilityRequestRef.current += 1;
|
||||
setSidoValue("0");
|
||||
setSigunValue("0");
|
||||
setFacilityValue("0");
|
||||
setFilteredSigunData([{ text: "시군구", val: "0" }]);
|
||||
setFacilityData(defaultFacilityData());
|
||||
setPendingExternalFacilityName("");
|
||||
}, [resetRevision, defaultFacilityData]);
|
||||
|
||||
useEffect(() => () => { facilityRequestRef.current += 1; }, []);
|
||||
useEffect(() => {
|
||||
fetchSido();
|
||||
fetchSigungu();
|
||||
@@ -262,6 +288,7 @@ export const ProcSearchBar = ({
|
||||
return;
|
||||
}
|
||||
|
||||
facilityRequestRef.current += 1;
|
||||
setFacilityData(defaultFacilityData());
|
||||
setFacilityValue("0");
|
||||
}, [
|
||||
@@ -317,6 +344,8 @@ export const ProcSearchBar = ({
|
||||
|
||||
const onSelectValue = useCallback(
|
||||
(val: string, type: string) => {
|
||||
facilityRequestRef.current += 1;
|
||||
onSearchInteraction?.();
|
||||
if (type === "ctpvCd") {
|
||||
setSidoValue(val);
|
||||
initializeSigunData(val);
|
||||
@@ -368,10 +397,12 @@ export const ProcSearchBar = ({
|
||||
sidoData,
|
||||
sidoValue,
|
||||
facilityType,
|
||||
onSearchInteraction,
|
||||
],
|
||||
);
|
||||
|
||||
const handleSearch = useCallback(() => {
|
||||
onSearchInteraction?.();
|
||||
if (sidoValue === "0") {
|
||||
showBusinessUserMessage("시도를 선택해 주세요.");
|
||||
return;
|
||||
@@ -400,6 +431,7 @@ export const ProcSearchBar = ({
|
||||
filteredSigunData,
|
||||
sigunData,
|
||||
sidoSearchZoom,
|
||||
onSearchInteraction,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -79,6 +79,8 @@ export const moveMapToCenter = (
|
||||
gisMaps: RefObject<any>,
|
||||
centerCoord?: [number, number],
|
||||
zoom?: number,
|
||||
/** 유효한 중심을 확보한 뒤 소비자가 이동을 승인/취소하는 선택적 callback이다. */
|
||||
beforeMove?: (extent: number[]) => boolean,
|
||||
) => {
|
||||
if (!centerCoord) return;
|
||||
|
||||
@@ -99,6 +101,7 @@ export const moveMapToCenter = (
|
||||
}
|
||||
}
|
||||
|
||||
if (beforeMove && !beforeMove([center[0], center[1], center[0], center[1]])) return;
|
||||
view.animate({
|
||||
center,
|
||||
...(typeof zoom === "number" ? { zoom } : {}),
|
||||
|
||||
Reference in New Issue
Block a user