From 828ea12484efe76f9c495b0ba9f20bbcbbca7be9 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Wed, 8 Apr 2026 15:59:04 +0900 Subject: [PATCH] =?UTF-8?q?=ED=9A=8C=EB=A1=9C=20=ED=95=A0=EB=8B=B9=20?= =?UTF-8?q?=EC=A0=9C=EB=8C=80=EB=A1=9C=20=EC=95=88=EB=90=98=EB=8A=94=20?= =?UTF-8?q?=ED=98=84=EC=83=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modal/circuitTrestle/step/StepUp.jsx | 164 +++++++++--------- 1 file changed, 83 insertions(+), 81 deletions(-) diff --git a/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx b/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx index f8ae00ad..2fc0c38f 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx @@ -130,6 +130,7 @@ export default function StepUp(props) { if (selectedSerQty) { selectedSerQty.roofSurfaceList.forEach((roofSurface) => { const targetSurface = canvas.getObjects().filter((obj) => obj.id === roofSurface.roofSurfaceId)[0] + if (!targetSurface) return const moduleIds = targetSurface.modules.map((module) => module.id) /** 기존 모듈 텍스트 삭제 */ @@ -406,37 +407,94 @@ export default function StepUp(props) { /** * 행 선택 핸들러 함수 추가 */ + /** + * 주어진 stepUpListData 를 기준으로 캔버스의 모든 module circuit 텍스트를 다시 그린다. + * 모든 pcsItem 의 selected serQty 를 순회해 적용한다. + */ + const applyCircuitsToCanvas = (stepUpListSrc) => { + if (!stepUpListSrc?.[0]?.pcsItemList) return + + /** 모든 모듈 circuit 데이터 초기화 */ + canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE) + .forEach((module) => { + module.circuit = null + module.circuitNumber = null + module.pcsItemId = null + }) + + /** 기존 circuit 텍스트 객체 모두 제거 */ + canvas + .getObjects() + .filter((obj) => obj.name === 'circuitNumber') + .forEach((text) => canvas.remove(text)) + + stepUpListSrc[0].pcsItemList.forEach((pcsItem) => { + const sel = pcsItem.serQtyList?.find((sq) => sq.selected) + if (!sel) return + sel.roofSurfaceList.forEach((roofSurface) => { + const targetSurface = canvas.getObjects().filter((obj) => obj.id === roofSurface.roofSurfaceId)[0] + if (!targetSurface) return + + roofSurface.moduleList.forEach((module) => { + const targetModule = canvas.getObjects().find((obj) => obj.id === module.uniqueId) + if (targetModule && module.circuit !== '' && module.circuit !== null) { + const moduleCircuitText = new fabric.Text(module.circuit, { + left: targetModule.left + targetModule.width / 2, + top: targetModule.top + targetModule.height / 2, + fontFamily: circuitNumberText.fontFamily.value, + fontWeight: circuitNumberText.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal', + fontStyle: circuitNumberText.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal', + fontSize: circuitNumberText.fontSize.value, + fill: circuitNumberText.fontColor.value, + width: targetModule.width, + height: targetModule.height, + textAlign: 'center', + originX: 'center', + originY: 'center', + name: 'circuitNumber', + parentId: targetModule.id, + circuitInfo: module.pcsItemId, + visible: isDisplayCircuitNumber, + }) + targetModule.circuit = moduleCircuitText + targetModule.pcsItemId = module.pcsItemId + targetModule.circuitNumber = module.circuit + canvas.add(moduleCircuitText) + } + }) + }) + }) + + canvas.renderAll() + setModuleStatisticsData() + } + const handleRowClick = (mainIdx, subIdx, applyParalQty = null) => { /** 자동 승압 설정인 경우만 실행 */ if (allocationType !== 'auto') return let tempStepUpListData = [...stepUpListData] - let selectedData = {} tempStepUpListData[0].pcsItemList[mainIdx].serQtyList.forEach((item, index) => { - if (index === subIdx) { - selectedData = item - } item.selected = index === subIdx }) /** 선택된 행 정보 저장 */ setStepUpListData(tempStepUpListData) /** PCS 2개 이상 또는 첫번째 PCS 선택 시에만 실행 */ - if (tempStepUpListData[0].pcsItemList.length > 1 && mainIdx === 0) { + const needsRefetch = + tempStepUpListData[0].pcsItemList.length > 1 && mainIdx === 0 + + if (needsRefetch) { /** 파워컨디셔너 옵션 조회 요청 파라미터 */ const params = { ...props.getOptYn(), // 옵션 Y/N useModuleItemList: props.getUseModuleItemList(), // 사용된 모듈아이템 List roofSurfaceList: props.getRoofSurfaceList(), // 지붕면 목록 pcsItemList: props.getSelectedPcsItemList().map((pcsItem, index) => { - /** PCS 아이템 목록 - * tempStepUpListData에서 해당 PCS 아이템 찾기 - * uniqueIndex를 사용하여 매칭 - */ const matchingPcsItem = tempStepUpListData[0].pcsItemList.find((item) => item.uniqueIndex === `${pcsItem.itemId}_${index}`) - - /** 선택된 serQty 찾기 */ const selectedSerQty = matchingPcsItem?.serQtyList.find((serQty) => serQty.selected)?.serQty || 0 if (index === 0) { return { @@ -453,86 +511,30 @@ export default function StepUp(props) { } /** PCS가 1개 이고 2번째 또는 3번째 PCS serQty가 0인 경우는 추천 API 실행하지 않음 */ - if (params.pcsItemList.length !== 1 && (params.pcsItemList[1]?.applySerQty !== 0 || params.pcsItemList[2]?.applySerQty) !== 0) { - /** PCS 승압설정 정보 조회 */ + const skipApi = !(params.pcsItemList.length !== 1 && (params.pcsItemList[1]?.applySerQty !== 0 || params.pcsItemList[2]?.applySerQty) !== 0) + + if (!skipApi) { + /** + * PCS 승압설정 정보 조회. 캔버스 갱신은 응답을 받은 뒤에 수행해야 + * "한박자 늦게" 반영되는 stale state 문제가 발생하지 않는다. + */ getPcsVoltageStepUpList(params).then((res) => { if (res?.result.resultCode === 'S' && res?.data) { const dataArray = Array.isArray(res.data) ? res.data : [res.data] - const stepUpListData = formatStepUpListData(dataArray) - - /** PCS 승압설정 정보 SET */ - setStepUpListData(stepUpListData) - - /** PCS 옵션 조회 */ - // const formattedOptCodes = formatOptionCodes(res.data.optionList) - // setOptCodes(formattedOptCodes) - // setSeletedOption(formattedOptCodes[0]) + const newStepUpListData = formatStepUpListData(dataArray) + setStepUpListData(newStepUpListData) + applyCircuitsToCanvas(newStepUpListData) } else { swalFire({ text: getMessage('common.message.send.error') }) + applyCircuitsToCanvas(tempStepUpListData) } }) + return } } - /** 모듈 목록 삭제 */ - canvas - .getObjects() - .filter((obj) => obj.name === POLYGON_TYPE.MODULE) - .forEach((module) => { - module.circuit = null - module.circuitNumber = null - module.pcsItemId = null - }) - - /** 선택된 모듈 목록 추가 */ - selectedData.roofSurfaceList.forEach((roofSurface) => { - const targetSurface = canvas.getObjects().filter((obj) => obj.id === roofSurface.roofSurfaceId)[0] - const moduleIds = targetSurface.modules.map((module) => { - return module.id - }) - - /** 모듈 목록 삭제 */ - canvas - .getObjects() - .filter((obj) => moduleIds.includes(obj.parentId)) - .map((text) => { - canvas.remove(text) - }) - - /** 모듈 목록 추가 */ - canvas.renderAll() - - roofSurface.moduleList.forEach((module) => { - const targetModule = canvas.getObjects().find((obj) => obj.id === module.uniqueId) - if (targetModule && module.circuit !== '' && module.circuit !== null) { - const moduleCircuitText = new fabric.Text(module.circuit, { - left: targetModule.left + targetModule.width / 2, - top: targetModule.top + targetModule.height / 2, - fontFamily: circuitNumberText.fontFamily.value, - fontWeight: circuitNumberText.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal', - fontStyle: circuitNumberText.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal', - fontSize: circuitNumberText.fontSize.value, - fill: circuitNumberText.fontColor.value, - width: targetModule.width, - height: targetModule.height, - textAlign: 'center', - originX: 'center', - originY: 'center', - name: 'circuitNumber', - parentId: targetModule.id, - circuitInfo: module.pcsItemId, - visible: isDisplayCircuitNumber, - }) - targetModule.circuit = moduleCircuitText - targetModule.pcsItemId = module.pcsItemId - targetModule.circuitNumber = module.circuit - canvas.add(moduleCircuitText) - } - }) - }) - - canvas.renderAll() - setModuleStatisticsData() + /** API 재조회가 없는 경로: 현재 tempStepUpListData 로 즉시 캔버스 갱신 */ + applyCircuitsToCanvas(tempStepUpListData) } /**