From 3df466a7179858864d91465e7dbe5ba536862f85 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Wed, 12 Mar 2025 16:44:41 +0900 Subject: [PATCH 01/35] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EC=84=A4=EC=B9=98=20=EB=8D=B0=EB=AA=A8=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/basic/BasicSetting.jsx | 46 +- .../floor-plan/modal/basic/step/Placement.jsx | 32 ++ src/hooks/module/useModuleBasicSetting.js | 499 +++++++++++++++++- src/store/canvasAtom.js | 5 + 4 files changed, 571 insertions(+), 11 deletions(-) diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index 291ef086..f607d3cb 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -6,7 +6,7 @@ import PitchModule from '@/components/floor-plan/modal/basic/step/pitch/PitchMod import PitchPlacement from '@/components/floor-plan/modal/basic/step/pitch/PitchPlacement' import Placement from '@/components/floor-plan/modal/basic/step/Placement' import { useRecoilValue, useRecoilState } from 'recoil' -import { canvasSettingState, canvasState, isManualModuleSetupState } from '@/store/canvasAtom' +import { canvasSettingState, canvasState, isManualModuleLayoutSetupState, isManualModuleSetupState } from '@/store/canvasAtom' import { usePopup } from '@/hooks/usePopup' import { Orientation } from '@/components/floor-plan/modal/basic/step/Orientation' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' @@ -29,6 +29,8 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const orientationRef = useRef(null) const { initEvent } = useEvent() const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState) + const [isManualModuleLayoutSetup, setIsManualModuleLayoutSetup] = useRecoilState(isManualModuleLayoutSetupState) + const moduleSelectionData = useRecoilValue(moduleSelectionDataState) const addedRoofs = useRecoilValue(addedRoofsState) const loginUserState = useRecoilValue(loginUserStore) @@ -37,8 +39,16 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) const [isClosePopup, setIsClosePopup] = useState({ close: false, id: 0 }) + const [manualSetupMode, setManualSetupMode] = useState('manualSetup') + + const [layoutSetup, setLayoutSetup] = useState({ + col: 1, + row: 1, + }) + // const { initEvent } = useContext(EventContext) - const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup } = useModuleBasicSetting(tabNum) + const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup, manualModuleLayoutSetup } = + useModuleBasicSetting(tabNum) const { updateObjectDate } = useMasterController() const handleBtnNextStep = () => { if (tabNum === 1) { @@ -86,7 +96,10 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const placementRef = { isChidori: useRef('false'), setupLocation: useRef('eaves'), - isMaxSetup: useRef('false'), + layoutSetup: useRef({ + col: 1, + row: 1, + }), } const placementFlatRef = { @@ -94,9 +107,15 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { } const handleManualModuleSetup = () => { + setManualSetupMode(`manualSetup_${!isManualModuleSetup}`) setIsManualModuleSetup(!isManualModuleSetup) } + const handleManualModuleLayoutSetup = () => { + setManualSetupMode(`manualLayoutSetup_${!isManualModuleLayoutSetup}`) + setIsManualModuleLayoutSetup(!isManualModuleLayoutSetup) + } + const updateObjectDataApi = async (params) => { const res = await updateObjectDate(params) } @@ -125,14 +144,24 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { useEffect(() => { if (basicSetting.roofSizeSet !== '3') { - manualModuleSetup(placementRef) + if (manualSetupMode.indexOf('manualSetup') > -1) { + manualModuleSetup(placementRef) + } else if (manualSetupMode.indexOf('manualLayoutSetup') > -1) { + manualModuleLayoutSetup(placementRef) + } } else { manualFlatroofModuleSetup(placementFlatRef) } if (isClosePopup.close) { closePopup(isClosePopup.id) } - }, [isManualModuleSetup, isClosePopup]) + }, [manualSetupMode, isClosePopup]) + + useEffect(() => { + if (isManualModuleLayoutSetup) { + manualModuleLayoutSetup(placementRef) + } + }, [layoutSetup]) return ( @@ -156,7 +185,9 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { {tabNum === 1 && } {/*배치면 초기설정 - 입력방법: 복시도 입력 || 실측값 입력*/} {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 2 && } - {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 3 && } + {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 3 && ( + + )} {/*배치면 초기설정 - 입력방법: 육지붕*/} {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 2 && } @@ -184,6 +215,9 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { + diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx index d4b979c7..d2fca8b2 100644 --- a/src/components/floor-plan/modal/basic/step/Placement.jsx +++ b/src/components/floor-plan/modal/basic/step/Placement.jsx @@ -111,6 +111,11 @@ const Placement = forwardRef((props, refs) => { setSelectedItems({ ...selectedItems, [e.target.name]: e.target.checked }) } + const handleLayoutSetup = (e) => { + props.setLayoutSetup({ ...props.layoutSetup, [e.target.name]: Number(e.target.value) }) + refs.layoutSetup.current = { ...props.layoutSetup, [e.target.name]: Number(e.target.value) } + } + return ( <>
@@ -233,6 +238,33 @@ const Placement = forwardRef((props, refs) => {
+
+
레이아웃 입력
+
+
+
+ + {' '} + × + +
+
+
+
{/*
diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 44a0d02e..aa008fc8 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -1,7 +1,14 @@ import { useState } from 'react' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' -import { canvasSettingState, canvasState, checkedModuleState, currentObjectState, isManualModuleSetupState } from '@/store/canvasAtom' -import { rectToPolygon, polygonToTurfPolygon, calculateVisibleModuleHeight, getDegreeByChon } from '@/util/canvas-util' +import { + canvasSettingState, + canvasState, + checkedModuleState, + currentObjectState, + isManualModuleLayoutSetupState, + isManualModuleSetupState, +} from '@/store/canvasAtom' +import { rectToPolygon, polygonToTurfPolygon, calculateVisibleModuleHeight, getDegreeByChon, toFixedWithoutRounding } from '@/util/canvas-util' import { basicSettingState, roofDisplaySelector } from '@/store/settingAtom' import offsetPolygon, { calculateAngle, createLinesFromPolygon } from '@/util/qpolygon-utils' import { QPolygon } from '@/components/fabric/QPolygon' @@ -35,6 +42,7 @@ export function useModuleBasicSetting(tabNum) { const { setSurfaceShapePattern } = useRoofFn() const checkedModule = useRecoilValue(checkedModuleState) const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState) + const [isManualModuleLayoutSetup, setIsManualModuleLayoutSetup] = useRecoilState(isManualModuleLayoutSetupState) const setModuleStatistics = useSetRecoilState(moduleStatisticsState) const canvasSetting = useRecoilValue(canvasSettingState) @@ -417,13 +425,18 @@ export function useModuleBasicSetting(tabNum) { setSaleStoreNorthFlg(true) } } - }, [isManualModuleSetup]) + }, [isManualModuleSetup, isManualModuleLayoutSetup]) /** * trestle에서 영역을 가져와 mouse:move 이벤트로 해당 영역에 진입했을때 booleanPointInPolygon 로 진입여부를 확인 * 확인 후 셀을 이동시킴 */ const manualModuleSetup = (placementRef) => { + //레이아웃 수동설치 토글 + if (isManualModuleLayoutSetup) { + setIsManualModuleLayoutSetup(false) + } + const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 if (isManualModuleSetup) { @@ -730,7 +743,7 @@ export function useModuleBasicSetting(tabNum) { tempModule.setCoords() //좌표 재정렬 if (turf.booleanContains(turfPolygon, tempTurfModule) || turf.booleanWithin(tempTurfModule, turfPolygon)) { //마우스 클릭시 set으로 해당 위치에 셀을 넣음 - const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 + const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module, true))) //겹치는지 확인 if (!isOverlap) { canvas?.remove(tempModule) @@ -778,6 +791,480 @@ export function useModuleBasicSetting(tabNum) { } } + const manualModuleLayoutSetup = (placementRef) => { + if (isManualModuleSetup) { + setIsManualModuleSetup(false) + } + + const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 + + if (isManualModuleLayoutSetup) { + if (checkedModule.length === 0) { + swalFire({ text: getMessage('module.place.select.module') }) + setIsManualModuleLayoutSetup(!isManualModuleLayoutSetup) + return + } + + if (checkedModule.length > 1) { + swalFire({ text: getMessage('module.place.select.one.module') }) + setIsManualModuleLayoutSetup(!isManualModuleLayoutSetup) + return + } + + const batchObjects = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.OBJECT_SURFACE) //도머s 객체 + //수동모드 모듈 설치면 선택 잠금 + moduleSetupSurfaces.forEach((obj) => { + obj.set({ + selectable: false, + evented: false, + }) + }) + + //모듈 기본 옵션 + const moduleOptions = { + fill: checkedModule[0].color, + stroke: 'black', + strokeWidth: 0.3, + selectable: true, // 선택 가능하게 설정 + lockMovementX: true, // X 축 이동 잠금 + lockMovementY: true, // Y 축 이동 잠금 + lockRotation: true, // 회전 잠금 + lockScalingX: true, // X 축 크기 조정 잠금 + lockScalingY: true, // Y 축 크기 조정 잠금 + name: POLYGON_TYPE.MODULE, + } + + const objectsIncludeSurface = (turfModuleSetupSurface) => { + let containsBatchObjects = [] + containsBatchObjects = batchObjects.filter((batchObject) => { + let convertBatchObject = polygonToTurfPolygon(batchObject) + // 폴리곤 안에 도머 폴리곤이 포함되어있는지 확인해서 반환하는 로직 + return ( + turf.booleanContains(turfModuleSetupSurface, convertBatchObject) || + turf.booleanWithin(convertBatchObject, turfModuleSetupSurface) || + turf.booleanOverlap(turfModuleSetupSurface, convertBatchObject) + ) + }) + + return containsBatchObjects + } + + if (moduleSetupSurfaces.length !== 0) { + const col = placementRef.layoutSetup.current.col + const row = placementRef.layoutSetup.current.row + + let tempModule + let manualDrawModules = [] + let inside = false + let turfPolygon + let flowDirection + let trestlePolygon + let width, height, intvHor, intvVer + let containsBatchObjects + + addCanvasMouseEventListener('mouse:move', (e) => { + //마우스 이벤트 삭제 후 재추가 + const mousePoint = canvas.getPointer(e.e) + + for (let i = 0; i < moduleSetupSurfaces.length; i++) { + //배치면이 여러개 일때 옮겨가면서 동작해야함 + turfPolygon = polygonToTurfPolygon(moduleSetupSurfaces[i]) + trestlePolygon = moduleSetupSurfaces[i] + manualDrawModules = moduleSetupSurfaces[i].modules // 앞에서 자동으로 했을때 추가됨 + flowDirection = moduleSetupSurfaces[i].direction //도형의 방향 + + containsBatchObjects = objectsIncludeSurface(turfPolygon) //배치면에 오브젝트(도머, 개구등)이 있는지 확인하는 로직 + + const moduleWidth = Number(checkedModule[0].longAxis) / 10 + const moduleHeight = Number(checkedModule[0].shortAxis) / 10 + let tmpWidth = flowDirection === 'south' || flowDirection === 'north' ? moduleWidth : moduleHeight + let tmpHeight = flowDirection === 'south' || flowDirection === 'north' ? moduleHeight : moduleWidth + + width = + canvasSetting.roofSizeSet == '1' + ? calculateVisibleModuleHeight(tmpWidth, tmpHeight, getDegreeByChon(moduleSetupSurfaces[i].roofMaterial.pitch), flowDirection).width + : tmpWidth + height = + canvasSetting.roofSizeSet == '1' + ? calculateVisibleModuleHeight(tmpWidth, tmpHeight, getDegreeByChon(moduleSetupSurfaces[i].roofMaterial.pitch), flowDirection).height + : tmpHeight + + intvHor = + flowDirection === 'south' || flowDirection === 'north' + ? moduleSetupSurfaces[i].trestleDetail.moduleIntvlHor / 10 + : moduleSetupSurfaces[i].trestleDetail.moduleIntvlVer / 10 + intvVer = + flowDirection === 'south' || flowDirection === 'north' + ? moduleSetupSurfaces[i].trestleDetail.moduleIntvlVer / 10 + : moduleSetupSurfaces[i].trestleDetail.moduleIntvlHor / 10 + + let calcHalfWidth = (Number((width * col).toFixed(1)) + Number((intvHor * (col - 1)).toFixed(1))) / 2 + let calcHalfHeight = (Number((height * row).toFixed(1)) + Number((intvVer * (row - 1)).toFixed(1))) / 2 + + //아래래 + let points = [ + { + x: Number(mousePoint.x.toFixed(1)) - calcHalfWidth, + y: Number(mousePoint.y.toFixed(1)) - calcHalfHeight, + }, + { + x: Number(mousePoint.x.toFixed(1)) - calcHalfWidth, + y: Number(mousePoint.y.toFixed(1)) + calcHalfHeight, + }, + { + x: Number(mousePoint.x.toFixed(1)) + calcHalfWidth, + y: Number(mousePoint.y.toFixed(1)) + calcHalfHeight, + }, + { + x: Number(mousePoint.x.toFixed(1)) + calcHalfWidth, + y: Number(mousePoint.y.toFixed(1)) - calcHalfHeight, + }, + ] + + // const points = [ + // { + // x: Number(mousePoint.x.toFixed(1)) + Number((width / 2).toFixed(1)), + // y: Number(mousePoint.y.toFixed(1)) - Number((height / 2).toFixed(1)), + // }, + // { + // x: Number(mousePoint.x.toFixed(1)) + Number((width / 2).toFixed(1)), + // y: Number(mousePoint.y.toFixed(1)) + Number((height / 2).toFixed(1)), + // }, + // { + // x: Number(mousePoint.x.toFixed(1)) - Number((width / 2).toFixed(1)), + // y: Number(mousePoint.y.toFixed(1)) - Number((height / 2).toFixed(1)), + // }, + // { + // x: Number(mousePoint.x.toFixed(1)) - Number((width / 2).toFixed(1)), + // y: Number(mousePoint.y.toFixed(1)) + Number((height / 2).toFixed(1)), + // }, + // ] + + const turfPoints = coordToTurfPolygon(points) + + if (turf.booleanWithin(turfPoints, turfPolygon)) { + let isDrawing = false + + if (isDrawing) return + canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) //움직일때 일단 지워가면서 움직임 + + tempModule = new fabric.Rect({ + fill: 'rgba(224, 221, 222, 0.7)', + stroke: 'black', + strokeWidth: 1, + strokeDashArray: [10, 5], + // width: Number(width.toFixed(1)), //작은버전 + // height: Number(height.toFixed(1)), //작은버전 + // left: Number(mousePoint.x.toFixed(1) - Number((width / 2).toFixed(1))), //작은버전 + // top: Number(mousePoint.y.toFixed(1) - Number((height / 2).toFixed(1))), //작은버전 + width: Number((width * col).toFixed(1)) + Number((intvHor * (col - 1)).toFixed(1)), //큰버전 + height: Number((height * row).toFixed(1)) + Number((intvVer * (row - 1)).toFixed(1)), //큰버전 + left: Number(mousePoint.x.toFixed(1)) - calcHalfWidth.toFixed(1), //큰버전 + top: Number(mousePoint.y.toFixed(1)) - calcHalfHeight.toFixed(1), //큰버전 + selectable: false, + lockMovementX: true, + lockMovementY: true, + lockRotation: true, + lockScalingX: true, + lockScalingY: true, + name: 'tempModule', + parentId: moduleSetupSurfaces[i].parentId, + }) + + //북면이고 북면설치상점이 아니면 그냥 return + if (trestlePolygon.isNorth && !saleStoreNorthFlg) { + return + } else { + canvas?.add(tempModule) //움직여가면서 추가됨 + } + + /** + * 스냅기능 + */ + let snapDistance = flowDirection === 'south' || flowDirection === 'north' ? 70 : 40 + let trestleSnapDistance = 15 + + const trestleLeft = Number(moduleSetupSurfaces[i].left.toFixed(1)) - Number((moduleSetupSurfaces[i].width / 2).toFixed(1)) + const trestleTop = Number(moduleSetupSurfaces[i].top.toFixed(1)) - Number((moduleSetupSurfaces[i].height / 2).toFixed(1)) + const trestleRight = Number(moduleSetupSurfaces[i].left.toFixed(1)) + Number((moduleSetupSurfaces[i].width / 2).toFixed(1)) + const trestleBottom = Number(moduleSetupSurfaces[i].top.toFixed(1)) + Number((moduleSetupSurfaces[i].height / 2).toFixed(1)) + const bigCenterY = (trestleTop + trestleTop + moduleSetupSurfaces[i].height) / 2 + + // 이동하는 모듈의 경계 좌표 + const smallLeft = Number(tempModule.left.toFixed(1)) + const smallTop = Number(tempModule.top.toFixed(1)) + const smallRight = smallLeft + Number(tempModule.width.toFixed(1)) + const smallBottom = smallTop + Number(tempModule.height.toFixed(1)) + const smallCenterX = smallLeft + Number((tempModule.width / 2).toFixed(1)) + const smallCenterY = smallTop + Number((tempModule.height / 2).toFixed(1)) + + /** + * 미리 깔아놓은 셀이 있을때 셀에 흡착됨 + */ + // if (manualDrawModules) { + // manualDrawModules.forEach((cell) => { + // const holdCellLeft = cell.left + // const holdCellTop = cell.top + // const holdCellRight = holdCellLeft + Number(cell.width.toFixed(1)) + // const holdCellBottom = holdCellTop + Number(cell.height.toFixed(1)) + // const holdCellCenterX = holdCellLeft + Number((cell.width / 2).toFixed(1)) + // const holdCellCenterY = holdCellTop + Number((cell.height / 2).toFixed(1)) + + // //설치된 셀에 좌측에 스냅 + // if (Math.abs(smallRight - holdCellLeft) < snapDistance) { + // tempModule.left = holdCellLeft - width - intvHor + // } + + // //설치된 셀에 우측에 스냅 + // if (Math.abs(smallLeft - holdCellRight) < snapDistance) { + // tempModule.left = holdCellRight + intvHor + // } + + // //설치된 셀에 위쪽에 스냅 + // if (Math.abs(smallBottom - holdCellTop) < snapDistance) { + // tempModule.top = holdCellTop - height - intvVer + // } + + // //설치된 셀에 밑쪽에 스냅 + // if (Math.abs(smallTop - holdCellBottom) < snapDistance) { + // tempModule.top = holdCellBottom + intvVer + // } + // //가운데 -> 가운데 + // if (Math.abs(smallCenterX - holdCellCenterX) < snapDistance) { + // tempModule.left = holdCellCenterX - Number((width / 2).toFixed(1)) + // } + // //왼쪽 -> 가운데 + // if (Math.abs(smallLeft - holdCellCenterX) < snapDistance) { + // tempModule.left = holdCellCenterX + // } + // // 오른쪽 -> 가운데 + // if (Math.abs(smallRight - holdCellCenterX) < snapDistance) { + // tempModule.left = holdCellCenterX - width + // } + // //세로 가운데 -> 가운데 + // if (Math.abs(smallCenterY - holdCellCenterY) < snapDistance) { + // tempModule.top = holdCellCenterY - Number((height / 2).toFixed(1)) + // } + // // //위쪽 -> 가운데 + // // if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) { + // // tempModule.top = holdCellCenterY + // // } + // // //아랫쪽 -> 가운데 + // // if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) { + // // tempModule.top = holdCellCenterY - height + // // } + // }) + // } + + // 위쪽 변에 스냅 + if (Math.abs(smallTop - trestleTop) < trestleSnapDistance) { + tempModule.top = trestleTop + 1 + } + + // 아래쪽 변에 스냅 + if (Math.abs(smallBottom - trestleBottom) < trestleSnapDistance) { + tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height - 1 + } + + // 왼쪽변에 스냅 + if (Math.abs(smallLeft - trestleLeft) < trestleSnapDistance) { + tempModule.left = trestleLeft + 1 + } + //오른쪽 변에 스냅 + if (Math.abs(smallRight - trestleRight) < trestleSnapDistance) { + tempModule.left = trestleRight - tempModule.width - 1 + } + + if (flowDirection === 'south' || flowDirection === 'north') { + // 모듈왼쪽이 세로중앙선에 붙게 스냅 + // if (Math.abs(smallLeft - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { + // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 + // } + + // 모듈이 가운데가 세로중앙선에 붙게 스냅 + if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < trestleSnapDistance) { + tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width / 2 + } + + // 모듈오른쪽이 세로중앙선에 붙게 스냅 + // if (Math.abs(smallRight - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < trestleSnapDistance) { + // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width * tempModule.scaleX + // } + } else { + // 모듈이 가로중앙선에 스냅 + if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < trestleSnapDistance) { + tempModule.top = bigCenterY - tempModule.height / 2 + } + + // if (Math.abs(smallTop - (trestleTop + moduleSetupSurfaces[i].height / 2)) < trestleSnapDistance) { + // tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 + // } + // 모듈 밑면이 가로중앙선에 스냅 + // if (Math.abs(smallBottom - (trestleTop + moduleSetupSurfaces[i].height / 2)) < trestleSnapDistance) { + // tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - tempModule.height * tempModule.scaleY + // } + } + + tempModule.setCoords() + canvas?.renderAll() + inside = true + break + } else { + inside = false + } + } + + if (!inside) { + // tempModule.set({ fill: 'red' }) + canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) + canvas?.renderAll() + } + }) + + addCanvasMouseEventListener('mouse:up', (e) => { + let isIntersection = true + if (!inside) return + if (tempModule) { + let startX, startY + + console.log(tempModule) + + //그려진 가이드 라인의 포인트를 기준으로 시작점을 만든다 + if (flowDirection === 'south') { + startX = toFixedWithoutRounding(tempModule.left, 1) + startY = toFixedWithoutRounding(tempModule.top + tempModule.height, 1) + + for (let i = 0; i < placementRef.layoutSetup.current.row; i++) { + let tempY = startY - i * height + let tempHeightMargin = i === 0 ? 0 : i * intvVer + for (let j = 0; j < placementRef.layoutSetup.current.col; j++) { + let tempX = startX + j * width + let tempWidthMargin = j === 0 ? 0 : j * intvHor + + let rectPoints = [ + { x: tempX + tempWidthMargin, y: tempY - height - tempHeightMargin }, + { x: tempX + tempWidthMargin, y: tempY - tempHeightMargin }, + { x: tempX + width + tempWidthMargin, y: tempY - tempHeightMargin }, + { x: tempX + width + tempWidthMargin, y: tempY - height - tempHeightMargin }, + ] + // console.log('🚀 ~ addCanvasMouseEventListener ~ rectPoints:', rectPoints) + + tempModule.set({ points: rectPoints }) + const tempTurfModule = polygonToTurfPolygon(tempModule) + tempModule.setCoords() //좌표 재정렬 + + if (turf.booleanContains(turfPolygon, tempTurfModule) || turf.booleanWithin(tempTurfModule, turfPolygon)) { + //마우스 클릭시 set으로 해당 위치에 셀을 넣음 + const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 + if (!isOverlap) { + canvas?.remove(tempModule) + + //안겹치면 넣는다 + // tempModule.setCoords() + moduleOptions.surfaceId = trestlePolygon.id + + let manualModule = new QPolygon(tempModule.points, { + ...moduleOptions, + moduleInfo: checkedModule[0], + // left: toFixedWithoutRounding(tempX + tempWidthMargin, 1), + // top: toFixedWithoutRounding(tempY - height - tempHeightMargin, 1), + width: toFixedWithoutRounding(width, 1), + height: toFixedWithoutRounding(height, 1), + }) + + let isDisjoint = checkModuleDisjointObjects(tempTurfModule, containsBatchObjects) + + //오브젝트와 겹치지 않으면 넣는다 + if (isDisjoint) { + canvas?.add(manualModule) + manualDrawModules.push(manualModule) + setModuleStatisticsData() + } + // getModuleStatistics() + } else { + swalFire({ text: getMessage('module.place.overlab') }) + return + } + } + } + } + } else if (flowDirection === 'north') { + startX = tempModule.points[3].x + startY = tempModule.points[3].y + } else if (flowDirection === 'east') { + startX = tempModule.points[2].x + startY = tempModule.points[2].y + } else { + startX = tempModule.points[0].x + startY = tempModule.points[0].y + } + + //도머 객체를 가져옴 + // if (batchObjects) { + // batchObjects.forEach((object) => { + // let dormerTurfPolygon = polygonToTurfPolygon(object, true) + // const intersection = turf.intersect(turf.featureCollection([dormerTurfPolygon, tempTurfModule])) //겹치는지 확인 + // //겹치면 안됨 + // if (intersection) { + // swalFire({ text: getMessage('module.place.overobject') }) + // isIntersection = false + // } + // }) + // } + + // if (!isIntersection) return + + // tempModule.setCoords() //좌표 재정렬 + // if (turf.booleanContains(turfPolygon, tempTurfModule) || turf.booleanWithin(tempTurfModule, turfPolygon)) { + // //마우스 클릭시 set으로 해당 위치에 셀을 넣음 + // const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 + // if (!isOverlap) { + // canvas?.remove(tempModule) + + // //안겹치면 넣는다 + // // tempModule.setCoords() + // moduleOptions.surfaceId = trestlePolygon.id + + // // console.log('tempModule.points', tempModule.points) + + // let manualModule = new QPolygon(tempModule.points, { + // ...moduleOptions, + // moduleInfo: checkedModule[0], + // left: Number(tempModule.left.toFixed(1)), + // top: Number(tempModule.top.toFixed(1)), + // width: Number(tempModule.width.toFixed(1)), + // height: Number(tempModule.height.toFixed(1)), + // }) + // canvas?.add(manualModule) + // manualDrawModules.push(manualModule) + // setModuleStatisticsData() + // // getModuleStatistics() + // } else { + // swalFire({ text: getMessage('module.place.overlab') }) + // } + // } else { + // swalFire({ text: getMessage('module.place.out') }) + // } + } + }) + } + } else { + if (moduleSetupSurfaces) { + //수동모드 해제시 모듈 설치면 선택 잠금 + moduleSetupSurfaces.forEach((obj) => { + obj.set({ + selectable: true, + evented: true, + }) + }) + } + + removeMouseEvent('mouse:up') + removeMouseEvent('mouse:move') + canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) //움직일때 일단 지워가면서 움직임 + } + } + //자동 모듈 설치(그리드 방식) const autoModuleSetup = (placementRef) => { initEvent() //마우스 이벤트 초기화 @@ -789,7 +1276,8 @@ export function useModuleBasicSetting(tabNum) { const isChidori = placementRef.isChidori.current === 'true' ? true : false const setupLocation = placementRef.setupLocation.current - const isMaxSetup = placementRef.isMaxSetup.current === 'true' ? true : false + const isMaxSetup = false + // const isMaxSetup = placementRef.isMaxSetup.current === 'true' ? true : false const moduleSetupSurfaces = moduleSetupSurface //선택 설치면 const notSelectedTrestlePolygons = canvas @@ -2726,6 +3214,7 @@ export function useModuleBasicSetting(tabNum) { selectedModules, makeModuleInstArea, manualModuleSetup, + manualModuleLayoutSetup, autoModuleSetup, restoreModuleInstArea, manualFlatroofModuleSetup, diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js index 772e55be..3e795f22 100644 --- a/src/store/canvasAtom.js +++ b/src/store/canvasAtom.js @@ -384,3 +384,8 @@ export const isManualModuleSetupState = atom({ key: 'isManualModuleSetupState', default: false, }) + +export const isManualModuleLayoutSetupState = atom({ + key: 'isManualModuleLayoutSetupState', + default: false, +}) From ae2171c6331d28a48ab911e86280431024899836 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Fri, 14 Mar 2025 18:35:13 +0900 Subject: [PATCH 02/35] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EC=84=A4=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/basic/BasicSetting.jsx | 35 ++- .../floor-plan/modal/basic/step/Placement.jsx | 62 ++-- src/hooks/module/useModuleBasicSetting.js | 284 ++++++++++-------- 3 files changed, 214 insertions(+), 167 deletions(-) diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index ff56d212..e2a38de8 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -25,9 +25,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const { getMessage } = useMessage() const { closePopup } = usePopup() const [tabNum, setTabNum] = useState(1) - const canvasSetting = useRecoilValue(canvasSettingState) const orientationRef = useRef(null) - const { initEvent } = useEvent() const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState) const [isManualModuleLayoutSetup, setIsManualModuleLayoutSetup] = useRecoilState(isManualModuleLayoutSetupState) @@ -40,12 +38,9 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const [isClosePopup, setIsClosePopup] = useState({ close: false, id: 0 }) const [checkedModules, setCheckedModules] = useRecoilState(checkedModuleState) - const [manualSetupMode, setManualSetupMode] = useState('manualSetup') + const [manualSetupMode, setManualSetupMode] = useState('') - const [layoutSetup, setLayoutSetup] = useState({ - col: 1, - row: 1, - }) + const [layoutSetup, setLayoutSetup] = useState([{}]) // const { initEvent } = useContext(EventContext) const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup, manualModuleLayoutSetup } = @@ -98,12 +93,10 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const placementRef = { isChidori: useRef('false'), setupLocation: useRef('eaves'), - layoutSetup: useRef({ - col: 1, - row: 1, - }), } + const layoutSetupRef = useRef([]) + const placementFlatRef = { setupLocation: useRef('south'), } @@ -114,6 +107,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { } const handleManualModuleLayoutSetup = () => { + console.log('asdfasdkljfhaskjdhfakjsdhkfjh') setManualSetupMode(`manualLayoutSetup_${!isManualModuleLayoutSetup}`) setIsManualModuleLayoutSetup(!isManualModuleLayoutSetup) } @@ -140,16 +134,21 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { if (isManualModuleSetup) { setIsManualModuleSetup(false) } + if (isManualModuleLayoutSetup) { + setIsManualModuleLayoutSetup(false) + } } setIsClosePopup({ close: true, id: id }) } useEffect(() => { + console.log('asdfasdf', manualSetupMode) + if (basicSetting.roofSizeSet !== '3') { if (manualSetupMode.indexOf('manualSetup') > -1) { manualModuleSetup(placementRef) } else if (manualSetupMode.indexOf('manualLayoutSetup') > -1) { - manualModuleLayoutSetup(placementRef) + manualModuleLayoutSetup(layoutSetupRef) } } else { manualFlatroofModuleSetup(placementFlatRef) @@ -161,7 +160,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { useEffect(() => { if (isManualModuleLayoutSetup) { - manualModuleLayoutSetup(placementRef) + manualModuleLayoutSetup(layoutSetupRef) } }, [layoutSetup]) @@ -183,7 +182,15 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { {tabNum === 1 && } {/*배치면 초기설정 - 입력방법: 복시도 입력 || 실측값 입력*/} {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 2 && } - {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 3 && } + {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 3 && ( + + )} {/*배치면 초기설정 - 입력방법: 육지붕*/} {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 2 && } diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx index d2fca8b2..f2c3c83f 100644 --- a/src/components/floor-plan/modal/basic/step/Placement.jsx +++ b/src/components/floor-plan/modal/basic/step/Placement.jsx @@ -1,7 +1,7 @@ import { forwardRef, useEffect, useState } from 'react' import { useMessage } from '@/hooks/useMessage' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' -import { checkedModuleState, currentCanvasPlanState, isManualModuleSetupState } from '@/store/canvasAtom' +import { checkedModuleState, currentCanvasPlanState, isManualModuleLayoutSetupState, isManualModuleSetupState } from '@/store/canvasAtom' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions' import { isObjectNotEmpty } from '@/util/common-utils' @@ -23,7 +23,9 @@ const Placement = forwardRef((props, refs) => { const [isMultiModule, setIsMultiModule] = useState(false) - const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState) + //언마운트시 버튼 초기화 + const setIsManualModuleSetup = useSetRecoilState(isManualModuleSetupState) + const setIsManualModuleLayoutSetup = useSetRecoilState(isManualModuleLayoutSetupState) //모듈 배치면 생성 useEffect(() => { @@ -38,6 +40,7 @@ const Placement = forwardRef((props, refs) => { return () => { setIsManualModuleSetup(false) + setIsManualModuleLayoutSetup(false) } }, []) @@ -56,6 +59,8 @@ const Placement = forwardRef((props, refs) => { }) setSelectedItems(initCheckedModule) setSelectedModules(moduleSelectionData.module) + props.setLayoutSetup(moduleSelectionData.module.itemList.map((item) => ({ moduleId: item.itemId, col: 0, row: 0 }))) + props.layoutSetupRef.current = moduleSelectionData.module.itemList.map((item) => ({ moduleId: item.itemId, col: 0, row: 0 })) } //모듈 배치면 생성 @@ -111,9 +116,11 @@ const Placement = forwardRef((props, refs) => { setSelectedItems({ ...selectedItems, [e.target.name]: e.target.checked }) } - const handleLayoutSetup = (e) => { - props.setLayoutSetup({ ...props.layoutSetup, [e.target.name]: Number(e.target.value) }) - refs.layoutSetup.current = { ...props.layoutSetup, [e.target.name]: Number(e.target.value) } + const handleLayoutSetup = (e, itemId, index) => { + const newLayoutSetup = [...props.layoutSetup] + newLayoutSetup[index] = { ...newLayoutSetup[index], moduleId: itemId, [e.target.name]: Number(e.target.value) } + props.setLayoutSetup(newLayoutSetup) + props.layoutSetupRef.current[index] = { ...props.layoutSetupRef.current[index], moduleId: itemId, [e.target.name]: Number(e.target.value) } } return ( @@ -162,6 +169,24 @@ const Placement = forwardRef((props, refs) => {
{item.wpOut} + + handleLayoutSetup(e, item.itemId, index)} + />{' '} + × + handleLayoutSetup(e, item.itemId, index)} + /> ))} @@ -238,33 +263,6 @@ const Placement = forwardRef((props, refs) => {
-
-
레이아웃 입력
-
-
-
- - {' '} - × - -
-
-
-
{/*
diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 27dee861..44f7d21e 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -560,7 +560,7 @@ export function useModuleBasicSetting(tabNum) { /** * 스냅기능 */ - let snapDistance = flowDirection === 'south' || flowDirection === 'north' ? 70 : 40 + let snapDistance = flowDirection === 'south' || flowDirection === 'north' ? 10 : 10 let trestleSnapDistance = 15 let intvHor = @@ -817,7 +817,7 @@ export function useModuleBasicSetting(tabNum) { } } - const manualModuleLayoutSetup = (placementRef) => { + const manualModuleLayoutSetup = (layoutSetupRef) => { if (isManualModuleSetup) { setIsManualModuleSetup(false) } @@ -831,8 +831,12 @@ export function useModuleBasicSetting(tabNum) { return } - if (checkedModule.length > 1) { - swalFire({ text: getMessage('module.place.select.one.module') }) + const hasZeroLength = checkedModule.some((item) => + layoutSetupRef.current.some((layoutItem) => item.itemId === layoutItem.moduleId && (layoutItem.row === 0 || layoutItem.col === 0)), + ) + + if (hasZeroLength) { + swalFire({ text: getMessage('모듈의 열, 행을 입력해 주세요.') }) setIsManualModuleLayoutSetup(!isManualModuleLayoutSetup) return } @@ -876,8 +880,8 @@ export function useModuleBasicSetting(tabNum) { } if (moduleSetupSurfaces.length !== 0) { - const col = placementRef.layoutSetup.current.col - const row = placementRef.layoutSetup.current.row + // const col = layoutSetupRef.current[0].col + // const row = layoutSetupRef.current[0].row let tempModule let manualDrawModules = [] @@ -924,48 +928,48 @@ export function useModuleBasicSetting(tabNum) { ? moduleSetupSurfaces[i].trestleDetail.moduleIntvlVer / 10 : moduleSetupSurfaces[i].trestleDetail.moduleIntvlHor / 10 - let calcHalfWidth = (Number((width * col).toFixed(1)) + Number((intvHor * (col - 1)).toFixed(1))) / 2 - let calcHalfHeight = (Number((height * row).toFixed(1)) + Number((intvVer * (row - 1)).toFixed(1))) / 2 + // let calcHalfWidth = (Number((width * col).toFixed(1)) + Number((intvHor * (col - 1)).toFixed(1))) / 2 + // let calcHalfHeight = (Number((height * row).toFixed(1)) + Number((intvVer * (row - 1)).toFixed(1))) / 2 //아래래 - let points = [ - { - x: Number(mousePoint.x.toFixed(1)) - calcHalfWidth, - y: Number(mousePoint.y.toFixed(1)) - calcHalfHeight, - }, - { - x: Number(mousePoint.x.toFixed(1)) - calcHalfWidth, - y: Number(mousePoint.y.toFixed(1)) + calcHalfHeight, - }, - { - x: Number(mousePoint.x.toFixed(1)) + calcHalfWidth, - y: Number(mousePoint.y.toFixed(1)) + calcHalfHeight, - }, - { - x: Number(mousePoint.x.toFixed(1)) + calcHalfWidth, - y: Number(mousePoint.y.toFixed(1)) - calcHalfHeight, - }, - ] - - // const points = [ + // let points = [ // { - // x: Number(mousePoint.x.toFixed(1)) + Number((width / 2).toFixed(1)), - // y: Number(mousePoint.y.toFixed(1)) - Number((height / 2).toFixed(1)), + // x: Number(mousePoint.x.toFixed(1)) - calcHalfWidth, + // y: Number(mousePoint.y.toFixed(1)) - calcHalfHeight, // }, // { - // x: Number(mousePoint.x.toFixed(1)) + Number((width / 2).toFixed(1)), - // y: Number(mousePoint.y.toFixed(1)) + Number((height / 2).toFixed(1)), + // x: Number(mousePoint.x.toFixed(1)) - calcHalfWidth, + // y: Number(mousePoint.y.toFixed(1)) + calcHalfHeight, // }, // { - // x: Number(mousePoint.x.toFixed(1)) - Number((width / 2).toFixed(1)), - // y: Number(mousePoint.y.toFixed(1)) - Number((height / 2).toFixed(1)), + // x: Number(mousePoint.x.toFixed(1)) + calcHalfWidth, + // y: Number(mousePoint.y.toFixed(1)) + calcHalfHeight, // }, // { - // x: Number(mousePoint.x.toFixed(1)) - Number((width / 2).toFixed(1)), - // y: Number(mousePoint.y.toFixed(1)) + Number((height / 2).toFixed(1)), + // x: Number(mousePoint.x.toFixed(1)) + calcHalfWidth, + // y: Number(mousePoint.y.toFixed(1)) - calcHalfHeight, // }, // ] + const points = [ + { + x: Number(mousePoint.x.toFixed(1)) + Number((width / 2).toFixed(1)), + y: Number(mousePoint.y.toFixed(1)) - Number((height / 2).toFixed(1)), + }, + { + x: Number(mousePoint.x.toFixed(1)) + Number((width / 2).toFixed(1)), + y: Number(mousePoint.y.toFixed(1)) + Number((height / 2).toFixed(1)), + }, + { + x: Number(mousePoint.x.toFixed(1)) - Number((width / 2).toFixed(1)), + y: Number(mousePoint.y.toFixed(1)) - Number((height / 2).toFixed(1)), + }, + { + x: Number(mousePoint.x.toFixed(1)) - Number((width / 2).toFixed(1)), + y: Number(mousePoint.y.toFixed(1)) + Number((height / 2).toFixed(1)), + }, + ] + const turfPoints = coordToTurfPolygon(points) if (turf.booleanWithin(turfPoints, turfPolygon)) { @@ -979,14 +983,14 @@ export function useModuleBasicSetting(tabNum) { stroke: 'black', strokeWidth: 1, strokeDashArray: [10, 5], - // width: Number(width.toFixed(1)), //작은버전 - // height: Number(height.toFixed(1)), //작은버전 - // left: Number(mousePoint.x.toFixed(1) - Number((width / 2).toFixed(1))), //작은버전 - // top: Number(mousePoint.y.toFixed(1) - Number((height / 2).toFixed(1))), //작은버전 - width: Number((width * col).toFixed(1)) + Number((intvHor * (col - 1)).toFixed(1)), //큰버전 - height: Number((height * row).toFixed(1)) + Number((intvVer * (row - 1)).toFixed(1)), //큰버전 - left: Number(mousePoint.x.toFixed(1)) - calcHalfWidth.toFixed(1), //큰버전 - top: Number(mousePoint.y.toFixed(1)) - calcHalfHeight.toFixed(1), //큰버전 + width: Number(width.toFixed(1)), //작은버전 + height: Number(height.toFixed(1)), //작은버전 + left: Number(mousePoint.x.toFixed(1) - Number((width / 2).toFixed(1))), //작은버전 + top: Number(mousePoint.y.toFixed(1) - Number((height / 2).toFixed(1))), //작은버전 + // width: Number((width * col).toFixed(1)) + Number((intvHor * (col - 1)).toFixed(1)), //큰버전 + // height: Number((height * row).toFixed(1)) + Number((intvVer * (row - 1)).toFixed(1)), //큰버전 + // left: Number(mousePoint.x.toFixed(1)) - calcHalfWidth.toFixed(1), //큰버전 + // top: Number(mousePoint.y.toFixed(1)) - calcHalfHeight.toFixed(1), //큰버전 selectable: false, lockMovementX: true, lockMovementY: true, @@ -1027,60 +1031,60 @@ export function useModuleBasicSetting(tabNum) { /** * 미리 깔아놓은 셀이 있을때 셀에 흡착됨 */ - // if (manualDrawModules) { - // manualDrawModules.forEach((cell) => { - // const holdCellLeft = cell.left - // const holdCellTop = cell.top - // const holdCellRight = holdCellLeft + Number(cell.width.toFixed(1)) - // const holdCellBottom = holdCellTop + Number(cell.height.toFixed(1)) - // const holdCellCenterX = holdCellLeft + Number((cell.width / 2).toFixed(1)) - // const holdCellCenterY = holdCellTop + Number((cell.height / 2).toFixed(1)) + if (manualDrawModules) { + manualDrawModules.forEach((cell) => { + const holdCellLeft = cell.left + const holdCellTop = cell.top + const holdCellRight = holdCellLeft + Number(cell.width.toFixed(1)) + const holdCellBottom = holdCellTop + Number(cell.height.toFixed(1)) + const holdCellCenterX = holdCellLeft + Number((cell.width / 2).toFixed(1)) + const holdCellCenterY = holdCellTop + Number((cell.height / 2).toFixed(1)) - // //설치된 셀에 좌측에 스냅 - // if (Math.abs(smallRight - holdCellLeft) < snapDistance) { - // tempModule.left = holdCellLeft - width - intvHor - // } + //설치된 셀에 좌측에 스냅 + if (Math.abs(smallRight - holdCellLeft) < snapDistance) { + tempModule.left = holdCellLeft - width - intvHor + } - // //설치된 셀에 우측에 스냅 - // if (Math.abs(smallLeft - holdCellRight) < snapDistance) { - // tempModule.left = holdCellRight + intvHor - // } + //설치된 셀에 우측에 스냅 + if (Math.abs(smallLeft - holdCellRight) < snapDistance) { + tempModule.left = holdCellRight + intvHor + } - // //설치된 셀에 위쪽에 스냅 - // if (Math.abs(smallBottom - holdCellTop) < snapDistance) { - // tempModule.top = holdCellTop - height - intvVer - // } + //설치된 셀에 위쪽에 스냅 + if (Math.abs(smallBottom - holdCellTop) < snapDistance) { + tempModule.top = holdCellTop - height - intvVer + } - // //설치된 셀에 밑쪽에 스냅 - // if (Math.abs(smallTop - holdCellBottom) < snapDistance) { - // tempModule.top = holdCellBottom + intvVer - // } - // //가운데 -> 가운데 - // if (Math.abs(smallCenterX - holdCellCenterX) < snapDistance) { - // tempModule.left = holdCellCenterX - Number((width / 2).toFixed(1)) - // } - // //왼쪽 -> 가운데 - // if (Math.abs(smallLeft - holdCellCenterX) < snapDistance) { - // tempModule.left = holdCellCenterX - // } - // // 오른쪽 -> 가운데 - // if (Math.abs(smallRight - holdCellCenterX) < snapDistance) { - // tempModule.left = holdCellCenterX - width - // } - // //세로 가운데 -> 가운데 - // if (Math.abs(smallCenterY - holdCellCenterY) < snapDistance) { - // tempModule.top = holdCellCenterY - Number((height / 2).toFixed(1)) - // } - // // //위쪽 -> 가운데 - // // if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) { - // // tempModule.top = holdCellCenterY - // // } - // // //아랫쪽 -> 가운데 - // // if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) { - // // tempModule.top = holdCellCenterY - height - // // } - // }) - // } + //설치된 셀에 밑쪽에 스냅 + if (Math.abs(smallTop - holdCellBottom) < snapDistance) { + tempModule.top = holdCellBottom + intvVer + } + //가운데 -> 가운데 + if (Math.abs(smallCenterX - holdCellCenterX) < snapDistance) { + tempModule.left = holdCellCenterX - Number((width / 2).toFixed(1)) + } + //왼쪽 -> 가운데 + if (Math.abs(smallLeft - holdCellCenterX) < snapDistance) { + tempModule.left = holdCellCenterX + } + // 오른쪽 -> 가운데 + if (Math.abs(smallRight - holdCellCenterX) < snapDistance) { + tempModule.left = holdCellCenterX - width + } + //세로 가운데 -> 가운데 + if (Math.abs(smallCenterY - holdCellCenterY) < snapDistance) { + tempModule.top = holdCellCenterY - Number((height / 2).toFixed(1)) + } + // //위쪽 -> 가운데 + // if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) { + // tempModule.top = holdCellCenterY + // } + // //아랫쪽 -> 가운데 + // if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) { + // tempModule.top = holdCellCenterY - height + // } + }) + } // 위쪽 변에 스냅 if (Math.abs(smallTop - trestleTop) < trestleSnapDistance) { @@ -1152,37 +1156,66 @@ export function useModuleBasicSetting(tabNum) { if (!inside) return if (tempModule) { let startX, startY - - console.log(tempModule) + let installedLastHeightCoord = 0 //마지막으로 설치된 모듈의 좌표 //그려진 가이드 라인의 포인트를 기준으로 시작점을 만든다 if (flowDirection === 'south') { startX = toFixedWithoutRounding(tempModule.left, 1) startY = toFixedWithoutRounding(tempModule.top + tempModule.height, 1) - for (let i = 0; i < placementRef.layoutSetup.current.row; i++) { - let tempY = startY - i * height - let tempHeightMargin = i === 0 ? 0 : i * intvVer - for (let j = 0; j < placementRef.layoutSetup.current.col; j++) { - let tempX = startX + j * width - let tempWidthMargin = j === 0 ? 0 : j * intvHor + console.log('checkedModule', checkedModule) - let rectPoints = [ - { x: tempX + tempWidthMargin, y: tempY - height - tempHeightMargin }, - { x: tempX + tempWidthMargin, y: tempY - tempHeightMargin }, - { x: tempX + width + tempWidthMargin, y: tempY - tempHeightMargin }, - { x: tempX + width + tempWidthMargin, y: tempY - height - tempHeightMargin }, - ] - // console.log('🚀 ~ addCanvasMouseEventListener ~ rectPoints:', rectPoints) + checkedModule.forEach((module, index) => { + moduleOptions.fill = module.color + const moduleWidth = Number(module.longAxis) / 10 + const moduleHeight = Number(module.shortAxis) / 10 - tempModule.set({ points: rectPoints }) - const tempTurfModule = polygonToTurfPolygon(tempModule) - tempModule.setCoords() //좌표 재정렬 + let tmpWidth = flowDirection === 'south' || flowDirection === 'north' ? moduleWidth : moduleHeight + let tmpHeight = flowDirection === 'south' || flowDirection === 'north' ? moduleHeight : moduleWidth - if (turf.booleanContains(turfPolygon, tempTurfModule) || turf.booleanWithin(tempTurfModule, turfPolygon)) { - //마우스 클릭시 set으로 해당 위치에 셀을 넣음 - const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 - if (!isOverlap) { + width = + canvasSetting.roofSizeSet == '1' + ? calculateVisibleModuleHeight(tmpWidth, tmpHeight, getDegreeByChon(moduleSetupSurfaces[i].roofMaterial.pitch), flowDirection) + .width + : tmpWidth + height = + canvasSetting.roofSizeSet == '1' + ? calculateVisibleModuleHeight(tmpWidth, tmpHeight, getDegreeByChon(moduleSetupSurfaces[i].roofMaterial.pitch), flowDirection) + .height + : tmpHeight + + const col = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].col + const row = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].row + for (let i = 0; i < row; i++) { + let tempY = startY - i * height + + if (index > 0) { + //두번째 모듈일때 마지막 설치 지점 + tempY = index > 0 && i === 0 ? installedLastHeightCoord - intvVer : installedLastHeightCoord + } + + let tempHeightMargin = i === 0 ? 0 : i * intvVer + + for (let j = 0; j < col; j++) { + let tempX = startX + j * width + let tempWidthMargin = j === 0 ? 0 : j * intvHor + + let rectPoints = [ + { x: tempX + tempWidthMargin, y: tempY - height - tempHeightMargin }, + { x: tempX + tempWidthMargin, y: tempY - tempHeightMargin }, + { x: tempX + width + tempWidthMargin, y: tempY - tempHeightMargin }, + { x: tempX + width + tempWidthMargin, y: tempY - height - tempHeightMargin }, + ] + // console.log('🚀 ~ addCanvasMouseEventListener ~ rectPoints:', rectPoints) + + tempModule.set({ points: rectPoints }) + const tempTurfModule = polygonToTurfPolygon(tempModule) + tempModule.setCoords() //좌표 재정렬 + + if (turf.booleanContains(turfPolygon, tempTurfModule) || turf.booleanWithin(tempTurfModule, turfPolygon)) { + //마우스 클릭시 set으로 해당 위치에 셀을 넣음 + const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 + // if (!isOverlap) { canvas?.remove(tempModule) //안겹치면 넣는다 @@ -1191,7 +1224,7 @@ export function useModuleBasicSetting(tabNum) { let manualModule = new QPolygon(tempModule.points, { ...moduleOptions, - moduleInfo: checkedModule[0], + moduleInfo: module, // left: toFixedWithoutRounding(tempX + tempWidthMargin, 1), // top: toFixedWithoutRounding(tempY - height - tempHeightMargin, 1), width: toFixedWithoutRounding(width, 1), @@ -1205,15 +1238,24 @@ export function useModuleBasicSetting(tabNum) { canvas?.add(manualModule) manualDrawModules.push(manualModule) setModuleStatisticsData() + installedLastHeightCoord = tempY - height - tempHeightMargin + } else { + manualModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + canvas?.add(manualModule) + canvas.renderAll() } // getModuleStatistics() - } else { - swalFire({ text: getMessage('module.place.overlab') }) - return + // } else { + // swalFire({ text: getMessage('module.place.overlab') }) + // return + // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + // canvas?.add(tempModule) + // canvas.renderAll() + // } } } } - } + }) } else if (flowDirection === 'north') { startX = tempModule.points[3].x startY = tempModule.points[3].y From 9e66b3ef7d38e4367393dfb815dc44d07d661a1a Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 17 Mar 2025 11:33:44 +0900 Subject: [PATCH 03/35] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EC=84=A4=EC=B9=98=20=EB=8F=99=EC=84=9C=EB=82=A8=EB=B6=81=20?= =?UTF-8?q?=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/basic/BasicSetting.jsx | 73 ++-- .../floor-plan/modal/basic/step/Placement.jsx | 4 +- src/hooks/module/useModuleBasicSetting.js | 358 +++++++++++++++--- 3 files changed, 328 insertions(+), 107 deletions(-) diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index e2a38de8..33b0c65f 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -6,7 +6,7 @@ import PitchModule from '@/components/floor-plan/modal/basic/step/pitch/PitchMod import PitchPlacement from '@/components/floor-plan/modal/basic/step/pitch/PitchPlacement' import Placement from '@/components/floor-plan/modal/basic/step/Placement' import { useRecoilValue, useRecoilState } from 'recoil' -import { canvasSettingState, canvasState, isManualModuleLayoutSetupState, isManualModuleSetupState } from '@/store/canvasAtom' +import { canvasSettingState, canvasState, checkedModuleState, isManualModuleLayoutSetupState, isManualModuleSetupState } from '@/store/canvasAtom' import { usePopup } from '@/hooks/usePopup' import { Orientation } from '@/components/floor-plan/modal/basic/step/Orientation' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' @@ -107,7 +107,6 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { } const handleManualModuleLayoutSetup = () => { - console.log('asdfasdkljfhaskjdhfakjsdhkfjh') setManualSetupMode(`manualLayoutSetup_${!isManualModuleLayoutSetup}`) setIsManualModuleLayoutSetup(!isManualModuleLayoutSetup) } @@ -142,8 +141,6 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { } useEffect(() => { - console.log('asdfasdf', manualSetupMode) - if (basicSetting.roofSizeSet !== '3') { if (manualSetupMode.indexOf('manualSetup') > -1) { manualModuleSetup(placementRef) @@ -211,47 +208,33 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { )} -
- {tabNum !== 1 && ( - - )} - {/*{tabNum !== 3 && }*/} - {tabNum !== 3 && ( - - )} - - {tabNum === 3 && ( - <> - {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && ( - <> - - - - - )} - {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && ( - <> - - - - )} - - )} -
+ {tabNum === 3 && ( + <> + {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && ( + <> + + + + + )} + {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && ( + <> + + + + )} + + )}
diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx index f2c3c83f..582f291c 100644 --- a/src/components/floor-plan/modal/basic/step/Placement.jsx +++ b/src/components/floor-plan/modal/basic/step/Placement.jsx @@ -175,7 +175,7 @@ const Placement = forwardRef((props, refs) => { className="input-origin block mr10" name="col" value={props.layoutSetup[index]?.col ?? 1} - defaultValue={1} + defaultValue={0} onChange={(e) => handleLayoutSetup(e, item.itemId, index)} />{' '} × @@ -184,7 +184,7 @@ const Placement = forwardRef((props, refs) => { className="input-origin block" name="row" value={props.layoutSetup[index]?.row ?? 1} - defaultValue={1} + defaultValue={0} onChange={(e) => handleLayoutSetup(e, item.itemId, index)} /> diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 44f7d21e..c7b9ec38 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -1146,43 +1146,43 @@ export function useModuleBasicSetting(tabNum) { if (!inside) { // tempModule.set({ fill: 'red' }) - canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) - canvas?.renderAll() + // canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) + // canvas?.renderAll() } }) addCanvasMouseEventListener('mouse:up', (e) => { - let isIntersection = true if (!inside) return if (tempModule) { let startX, startY let installedLastHeightCoord = 0 //마지막으로 설치된 모듈의 좌표 - //그려진 가이드 라인의 포인트를 기준으로 시작점을 만든다 - if (flowDirection === 'south') { - startX = toFixedWithoutRounding(tempModule.left, 1) - startY = toFixedWithoutRounding(tempModule.top + tempModule.height, 1) + checkedModule.forEach((module, index) => { + //모듈 사이즈 + const moduleWidth = toFixedWithoutRounding(module.longAxis / 10, 1) + const moduleHeight = toFixedWithoutRounding(module.shortAxis / 10, 1) - console.log('checkedModule', checkedModule) + //흐름 방향에 따른 모듈 사이즈 + let tmpWidth = flowDirection === 'south' || flowDirection === 'north' ? moduleWidth : moduleHeight + let tmpHeight = flowDirection === 'south' || flowDirection === 'north' ? moduleHeight : moduleWidth + + //복시도, 실치수에 따른 모듈 높이 조정 + width = + canvasSetting.roofSizeSet == '1' + ? calculateVisibleModuleHeight(tmpWidth, tmpHeight, getDegreeByChon(trestlePolygon.roofMaterial.pitch), flowDirection).width + : tmpWidth + height = + canvasSetting.roofSizeSet == '1' + ? calculateVisibleModuleHeight(tmpWidth, tmpHeight, getDegreeByChon(trestlePolygon.roofMaterial.pitch), flowDirection).height + : tmpHeight + + //그려진 가이드 라인의 포인트를 기준으로 시작점을 만든다 + if (flowDirection === 'south') { + //남 + startX = toFixedWithoutRounding(tempModule.left, 1) + startY = toFixedWithoutRounding(tempModule.top + tempModule.height, 1) - checkedModule.forEach((module, index) => { moduleOptions.fill = module.color - const moduleWidth = Number(module.longAxis) / 10 - const moduleHeight = Number(module.shortAxis) / 10 - - let tmpWidth = flowDirection === 'south' || flowDirection === 'north' ? moduleWidth : moduleHeight - let tmpHeight = flowDirection === 'south' || flowDirection === 'north' ? moduleHeight : moduleWidth - - width = - canvasSetting.roofSizeSet == '1' - ? calculateVisibleModuleHeight(tmpWidth, tmpHeight, getDegreeByChon(moduleSetupSurfaces[i].roofMaterial.pitch), flowDirection) - .width - : tmpWidth - height = - canvasSetting.roofSizeSet == '1' - ? calculateVisibleModuleHeight(tmpWidth, tmpHeight, getDegreeByChon(moduleSetupSurfaces[i].roofMaterial.pitch), flowDirection) - .height - : tmpHeight const col = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].col const row = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].row @@ -1206,7 +1206,6 @@ export function useModuleBasicSetting(tabNum) { { x: tempX + width + tempWidthMargin, y: tempY - tempHeightMargin }, { x: tempX + width + tempWidthMargin, y: tempY - height - tempHeightMargin }, ] - // console.log('🚀 ~ addCanvasMouseEventListener ~ rectPoints:', rectPoints) tempModule.set({ points: rectPoints }) const tempTurfModule = polygonToTurfPolygon(tempModule) @@ -1215,34 +1214,39 @@ export function useModuleBasicSetting(tabNum) { if (turf.booleanContains(turfPolygon, tempTurfModule) || turf.booleanWithin(tempTurfModule, turfPolygon)) { //마우스 클릭시 set으로 해당 위치에 셀을 넣음 const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 - // if (!isOverlap) { - canvas?.remove(tempModule) + if (!isOverlap) { + canvas?.remove(tempModule) - //안겹치면 넣는다 - // tempModule.setCoords() - moduleOptions.surfaceId = trestlePolygon.id + //안겹치면 넣는다 + // tempModule.setCoords() + moduleOptions.surfaceId = trestlePolygon.id - let manualModule = new QPolygon(tempModule.points, { - ...moduleOptions, - moduleInfo: module, - // left: toFixedWithoutRounding(tempX + tempWidthMargin, 1), - // top: toFixedWithoutRounding(tempY - height - tempHeightMargin, 1), - width: toFixedWithoutRounding(width, 1), - height: toFixedWithoutRounding(height, 1), - }) + let manualModule = new QPolygon(tempModule.points, { + ...moduleOptions, + moduleInfo: module, + // left: toFixedWithoutRounding(tempX + tempWidthMargin, 1), + // top: toFixedWithoutRounding(tempY - height - tempHeightMargin, 1), + width: toFixedWithoutRounding(width, 1), + height: toFixedWithoutRounding(height, 1), + }) - let isDisjoint = checkModuleDisjointObjects(tempTurfModule, containsBatchObjects) + let isDisjoint = checkModuleDisjointObjects(tempTurfModule, containsBatchObjects) - //오브젝트와 겹치지 않으면 넣는다 - if (isDisjoint) { - canvas?.add(manualModule) - manualDrawModules.push(manualModule) - setModuleStatisticsData() - installedLastHeightCoord = tempY - height - tempHeightMargin + //오브젝트와 겹치지 않으면 넣는다 + if (isDisjoint) { + canvas?.add(manualModule) + manualDrawModules.push(manualModule) + setModuleStatisticsData() + installedLastHeightCoord = tempY - height - tempHeightMargin + } else { + //디버깅용 + // manualModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + // canvas?.add(manualModule) + // canvas.renderAll() + } } else { - manualModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) - canvas?.add(manualModule) - canvas.renderAll() + swalFire({ text: getMessage('module.place.overlab') }) + return } // getModuleStatistics() // } else { @@ -1255,18 +1259,252 @@ export function useModuleBasicSetting(tabNum) { } } } - }) - } else if (flowDirection === 'north') { - startX = tempModule.points[3].x - startY = tempModule.points[3].y - } else if (flowDirection === 'east') { - startX = tempModule.points[2].x - startY = tempModule.points[2].y - } else { - startX = tempModule.points[0].x - startY = tempModule.points[0].y - } + } else if (flowDirection === 'north') { + //북북 + startX = toFixedWithoutRounding(tempModule.left + tempModule.width, 1) + startY = toFixedWithoutRounding(tempModule.top, 1) + moduleOptions.fill = module.color + + const col = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].col + const row = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].row + for (let i = 0; i < row; i++) { + let tempY = startY + i * height + + if (index > 0) { + //두번째 모듈일때 마지막 설치 지점 + tempY = index > 0 && i === 0 ? installedLastHeightCoord + intvVer : installedLastHeightCoord + } + + let tempHeightMargin = i === 0 ? 0 : i * intvVer + + for (let j = 0; j < col; j++) { + let tempX = startX - j * width + let tempWidthMargin = j === 0 ? 0 : j * intvHor + + let rectPoints = [ + { x: tempX - tempWidthMargin, y: tempY + height + tempHeightMargin }, + { x: tempX - tempWidthMargin, y: tempY + tempHeightMargin }, + { x: tempX - width - tempWidthMargin, y: tempY + tempHeightMargin }, + { x: tempX - width - tempWidthMargin, y: tempY + height + tempHeightMargin }, + ] + + tempModule.set({ points: rectPoints }) + const tempTurfModule = polygonToTurfPolygon(tempModule) + tempModule.setCoords() //좌표 재정렬 + + if (turf.booleanContains(turfPolygon, tempTurfModule) || turf.booleanWithin(tempTurfModule, turfPolygon)) { + //마우스 클릭시 set으로 해당 위치에 셀을 넣음 + const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 + if (!isOverlap) { + canvas?.remove(tempModule) + + //안겹치면 넣는다 + // tempModule.setCoords() + moduleOptions.surfaceId = trestlePolygon.id + + let manualModule = new QPolygon(tempModule.points, { + ...moduleOptions, + moduleInfo: module, + // left: toFixedWithoutRounding(tempX + tempWidthMargin, 1), + // top: toFixedWithoutRounding(tempY - height - tempHeightMargin, 1), + width: toFixedWithoutRounding(width, 1), + height: toFixedWithoutRounding(height, 1), + }) + + let isDisjoint = checkModuleDisjointObjects(tempTurfModule, containsBatchObjects) + + //오브젝트와 겹치지 않으면 넣는다 + if (isDisjoint) { + canvas?.add(manualModule) + manualDrawModules.push(manualModule) + setModuleStatisticsData() + installedLastHeightCoord = tempY + height + tempHeightMargin + } else { + //디버깅용 + // manualModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + // canvas?.add(manualModule) + // canvas.renderAll() + } + } else { + swalFire({ text: getMessage('module.place.overlab') }) + return + } + // getModuleStatistics() + // } else { + // swalFire({ text: getMessage('module.place.overlab') }) + // return + // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + // canvas?.add(tempModule) + // canvas.renderAll() + // } + } + } + } + } else if (flowDirection === 'west') { + startX = toFixedWithoutRounding(tempModule.left, 1) + startY = toFixedWithoutRounding(tempModule.top, 1) + moduleOptions.fill = module.color + + const col = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].col + const row = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].row + + for (let i = 0; i < row; i++) { + //옆으로 올라가는거라 height가 아니고 width로 변경 + let tempX = startX + i * width + let tempWidthMargin = i === 0 ? 0 : i * intvHor + + if (index > 0) { + //두번째 모듈일때 마지막 설치 지점 //명칭은 그대로 쓴다 + tempX = index > 0 && i === 0 ? installedLastHeightCoord + intvHor : installedLastHeightCoord + } + + for (let j = 0; j < col; j++) { + let tempY = startY + j * height + let tempHeightMargin = j === 0 ? 0 : j * intvVer + + let rectPoints = [ + { x: tempX + tempWidthMargin, y: tempY + tempHeightMargin }, + { x: tempX + tempWidthMargin, y: tempY + height + tempHeightMargin }, + { x: tempX + width + tempWidthMargin, y: tempY + height + tempHeightMargin }, + { x: tempX + width + tempWidthMargin, y: tempY + tempHeightMargin }, + ] + + tempModule.set({ points: rectPoints }) + const tempTurfModule = polygonToTurfPolygon(tempModule) + tempModule.setCoords() //좌표 재정렬 + + if (turf.booleanContains(turfPolygon, tempTurfModule) || turf.booleanWithin(tempTurfModule, turfPolygon)) { + //마우스 클릭시 set으로 해당 위치에 셀을 넣음 + const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 + if (!isOverlap) { + canvas?.remove(tempModule) + + //안겹치면 넣는다 + // tempModule.setCoords() + moduleOptions.surfaceId = trestlePolygon.id + + let manualModule = new QPolygon(tempModule.points, { + ...moduleOptions, + moduleInfo: module, + // left: toFixedWithoutRounding(tempX + tempWidthMargin, 1), + // top: toFixedWithoutRounding(tempY - height - tempHeightMargin, 1), + width: toFixedWithoutRounding(width, 1), + height: toFixedWithoutRounding(height, 1), + }) + + let isDisjoint = checkModuleDisjointObjects(tempTurfModule, containsBatchObjects) + + //오브젝트와 겹치지 않으면 넣는다 + if (isDisjoint) { + canvas?.add(manualModule) + manualDrawModules.push(manualModule) + setModuleStatisticsData() + installedLastHeightCoord = tempX + width + tempWidthMargin + } else { + //디버깅용 + // manualModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + // canvas?.add(manualModule) + // canvas.renderAll() + } + } else { + swalFire({ text: getMessage('module.place.overlab') }) + return + } + // getModuleStatistics() + // } else { + // swalFire({ text: getMessage('module.place.overlab') }) + // return + // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + // canvas?.add(tempModule) + // canvas.renderAll() + // } + } + } + } + } else { + startX = toFixedWithoutRounding(tempModule.left + width, 1) + startY = toFixedWithoutRounding(tempModule.top + height, 1) + moduleOptions.fill = module.color + + const col = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].col + const row = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].row + + for (let i = 0; i < row; i++) { + //옆으로 올라가는거라 height가 아니고 width로 변경 + let tempX = startX - i * width + let tempWidthMargin = i === 0 ? 0 : i * intvHor + + if (index > 0) { + //두번째 모듈일때 마지막 설치 지점 //명칭은 그대로 쓴다 + tempX = index > 0 && i === 0 ? installedLastHeightCoord - intvHor : installedLastHeightCoord + } + + for (let j = 0; j < col; j++) { + let tempY = startY - j * height + let tempHeightMargin = j === 0 ? 0 : j * intvVer + + let rectPoints = [ + { x: tempX - tempWidthMargin, y: tempY - tempHeightMargin }, + { x: tempX - tempWidthMargin, y: tempY - height - tempHeightMargin }, + { x: tempX - width - tempWidthMargin, y: tempY - height - tempHeightMargin }, + { x: tempX - width - tempWidthMargin, y: tempY - tempHeightMargin }, + ] + + tempModule.set({ points: rectPoints }) + const tempTurfModule = polygonToTurfPolygon(tempModule) + tempModule.setCoords() //좌표 재정렬 + + if (turf.booleanContains(turfPolygon, tempTurfModule) || turf.booleanWithin(tempTurfModule, turfPolygon)) { + //마우스 클릭시 set으로 해당 위치에 셀을 넣음 + const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 + if (!isOverlap) { + canvas?.remove(tempModule) + + //안겹치면 넣는다 + // tempModule.setCoords() + moduleOptions.surfaceId = trestlePolygon.id + + let manualModule = new QPolygon(tempModule.points, { + ...moduleOptions, + moduleInfo: module, + // left: toFixedWithoutRounding(tempX + tempWidthMargin, 1), + // top: toFixedWithoutRounding(tempY - height - tempHeightMargin, 1), + width: toFixedWithoutRounding(width, 1), + height: toFixedWithoutRounding(height, 1), + }) + + let isDisjoint = checkModuleDisjointObjects(tempTurfModule, containsBatchObjects) + + //오브젝트와 겹치지 않으면 넣는다 + if (isDisjoint) { + canvas?.add(manualModule) + manualDrawModules.push(manualModule) + setModuleStatisticsData() + installedLastHeightCoord = tempX - width - tempWidthMargin + } else { + //디버깅용 + // manualModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + // canvas?.add(manualModule) + // canvas.renderAll() + } + } else { + swalFire({ text: getMessage('module.place.overlab') }) + return + } + // getModuleStatistics() + // } else { + // swalFire({ text: getMessage('module.place.overlab') }) + // return + // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + // canvas?.add(tempModule) + // canvas.renderAll() + // } + } + } + } + } + }) //도머 객체를 가져옴 // if (batchObjects) { // batchObjects.forEach((object) => { From 83b27582f7413ea5bd46316d9b887c92008dc342 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 17 Mar 2025 15:01:25 +0900 Subject: [PATCH 04/35] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useModuleBasicSetting.js | 161 ++++++++++++++-------- 1 file changed, 107 insertions(+), 54 deletions(-) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index c7b9ec38..5203a972 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -560,7 +560,8 @@ export function useModuleBasicSetting(tabNum) { /** * 스냅기능 */ - let snapDistance = flowDirection === 'south' || flowDirection === 'north' ? 10 : 10 + let snapDistance = flowDirection === 'south' || flowDirection === 'north' ? 50 : 50 + let sideSnapDistance = 15 let trestleSnapDistance = 15 let intvHor = @@ -600,51 +601,103 @@ export function useModuleBasicSetting(tabNum) { const holdCellCenterX = holdCellLeft + toFixedWithoutRounding(cell.width / 2, 2) const holdCellCenterY = holdCellTop + toFixedWithoutRounding(cell.height / 2, 2) + //흐름방향따라 달라야 한다. + if (flowDirection === 'south' || flowDirection === 'north') { + if (Math.abs(smallCenterX - holdCellCenterX) < snapDistance) { + tempModule.left = holdCellCenterX - toFixedWithoutRounding(width / 2, 2) + } + + //왼쪽 -> 가운데 + if (Math.abs(smallLeft - holdCellCenterX) < snapDistance) { + // console.log('holdCellCenterX', holdCellCenterX) + // console.log('smallLeft', smallLeft) + + // console.log('모듈 센터에 스냅') + tempModule.left = holdCellCenterX + intvHor / 2 + + // console.log('tempModule.left', tempModule.left) + } + // 오른쪽 -> 가운데 + if (Math.abs(smallRight - holdCellCenterX) < snapDistance) { + tempModule.left = holdCellCenterX - width - intvHor / 2 + } + + //설치된 셀에 좌측에 스냅 + if (Math.abs(smallRight - holdCellLeft) < snapDistance) { + // console.log('모듈 좌측 스냅') + tempModule.left = holdCellLeft - width - intvHor + } + + //설치된 셀에 우측에 스냅 + if (Math.abs(smallLeft - holdCellRight) < snapDistance) { + // console.log('모듈 우측 스냅') + tempModule.left = holdCellRight + intvHor + } + //설치된 셀에 위쪽에 스냅 + if (Math.abs(smallBottom - holdCellTop) < sideSnapDistance) { + tempModule.top = holdCellTop - height - intvVer + } + + //설치된 셀에 밑쪽에 스냅 + if (Math.abs(smallTop - holdCellBottom) < sideSnapDistance) { + tempModule.top = holdCellBottom + intvVer + } + + //설치된 셀에 윗쪽에 스냅 + if (Math.abs(smallTop - holdCellTop) < sideSnapDistance) { + tempModule.top = holdCellTop + } + } else { + //흐름방향 west, east + + //가운데 가운데 + if (Math.abs(smallCenterY - holdCellCenterY) < snapDistance) { + tempModule.top = holdCellCenterY - toFixedWithoutRounding(width / 2, 2) + } + + //위쪽 -> 가운데 + if (Math.abs(smallTop - holdCellCenterY) < snapDistance) { + // console.log('holdCellCenterX', holdCellCenterX) + // console.log('smallLeft', smallLeft) + + // console.log('모듈 센터에 스냅') + tempModule.top = holdCellCenterY + intvHor / 2 + + // console.log('tempModule.left', tempModule.left) + } + // 밑 -> 가운데 + if (Math.abs(smallBottom - holdCellCenterY) < snapDistance) { + tempModule.top = holdCellCenterY - height - intvHor / 2 + } + + //설치된 셀에 좌측에 스냅 + if (Math.abs(smallRight - holdCellLeft) < snapDistance) { + // console.log('모듈 좌측 스냅') + tempModule.left = holdCellLeft - width - intvHor + } + + //설치된 셀에 우측에 스냅 + if (Math.abs(smallLeft - holdCellRight) < snapDistance) { + // console.log('모듈 우측 스냅') + tempModule.left = holdCellRight + intvHor + } + //설치된 셀에 위쪽에 스냅 + if (Math.abs(smallBottom - holdCellTop) < sideSnapDistance) { + tempModule.top = holdCellTop - height - intvVer + } + + //설치된 셀에 밑쪽에 스냅 + if (Math.abs(smallTop - holdCellBottom) < sideSnapDistance) { + tempModule.top = holdCellBottom + intvVer + } + + //설치된 셀에 윗쪽에 스냅 + if (Math.abs(smallTop - holdCellTop) < sideSnapDistance) { + tempModule.top = holdCellTop + } + } + //가운데 -> 가운대 - if (Math.abs(smallCenterX - holdCellCenterX) < snapDistance) { - tempModule.left = holdCellCenterX - toFixedWithoutRounding(width / 2, 2) - } - - //왼쪽 -> 가운데 - if (Math.abs(smallLeft - holdCellCenterX) < snapDistance) { - // console.log('holdCellCenterX', holdCellCenterX) - // console.log('smallLeft', smallLeft) - - // console.log('모듈 센터에 스냅') - tempModule.left = holdCellCenterX + intvHor / 2 - - // console.log('tempModule.left', tempModule.left) - } - // 오른쪽 -> 가운데 - if (Math.abs(smallRight - holdCellCenterX) < snapDistance) { - tempModule.left = holdCellCenterX - width - intvHor / 2 - } - - //설치된 셀에 좌측에 스냅 - if (Math.abs(smallRight - holdCellLeft) < snapDistance) { - // console.log('모듈 좌측 스냅') - tempModule.left = holdCellLeft - width - intvHor - } - - //설치된 셀에 우측에 스냅 - if (Math.abs(smallLeft - holdCellRight) < snapDistance) { - // console.log('모듈 우측 스냅') - tempModule.left = holdCellRight + intvHor - } - //설치된 셀에 위쪽에 스냅 - if (Math.abs(smallBottom - holdCellTop) < 10) { - tempModule.top = holdCellTop - height - intvVer - } - - //설치된 셀에 밑쪽에 스냅 - if (Math.abs(smallTop - holdCellBottom) < 10) { - tempModule.top = holdCellBottom + intvVer - } - - //설치된 셀에 윗쪽에 스냅 - if (Math.abs(smallTop - holdCellTop) < 10) { - tempModule.top = holdCellTop - } //세로 가운데 -> 가운데 // if (Math.abs(smallCenterY - holdCellCenterY) < snapDistance) { @@ -653,14 +706,10 @@ export function useModuleBasicSetting(tabNum) { // //위쪽 -> 가운데 // if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) { // tempModule.top = holdCellCenterY - // } - // //아랫쪽 -> 가운데 - // if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) { - // tempModule.top = holdCellCenterY - height - // } }) } + //여기서부턴 배치면 설치 외곽선 라인 // 위쪽 변에 스냅 if (Math.abs(smallTop - trestleTop) < trestleSnapDistance) { tempModule.top = trestleTop + 1 @@ -962,11 +1011,11 @@ export function useModuleBasicSetting(tabNum) { }, { x: Number(mousePoint.x.toFixed(1)) - Number((width / 2).toFixed(1)), - y: Number(mousePoint.y.toFixed(1)) - Number((height / 2).toFixed(1)), + y: Number(mousePoint.y.toFixed(1)) + Number((height / 2).toFixed(1)), }, { x: Number(mousePoint.x.toFixed(1)) - Number((width / 2).toFixed(1)), - y: Number(mousePoint.y.toFixed(1)) + Number((height / 2).toFixed(1)), + y: Number(mousePoint.y.toFixed(1)) - Number((height / 2).toFixed(1)), }, ] @@ -1146,8 +1195,8 @@ export function useModuleBasicSetting(tabNum) { if (!inside) { // tempModule.set({ fill: 'red' }) - // canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) - // canvas?.renderAll() + canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) + canvas?.renderAll() } }) @@ -1235,6 +1284,7 @@ export function useModuleBasicSetting(tabNum) { //오브젝트와 겹치지 않으면 넣는다 if (isDisjoint) { canvas?.add(manualModule) + canvas?.renderAll() manualDrawModules.push(manualModule) setModuleStatisticsData() installedLastHeightCoord = tempY - height - tempHeightMargin @@ -1317,6 +1367,7 @@ export function useModuleBasicSetting(tabNum) { //오브젝트와 겹치지 않으면 넣는다 if (isDisjoint) { canvas?.add(manualModule) + canvas?.renderAll() manualDrawModules.push(manualModule) setModuleStatisticsData() installedLastHeightCoord = tempY + height + tempHeightMargin @@ -1398,6 +1449,7 @@ export function useModuleBasicSetting(tabNum) { //오브젝트와 겹치지 않으면 넣는다 if (isDisjoint) { canvas?.add(manualModule) + canvas?.renderAll() manualDrawModules.push(manualModule) setModuleStatisticsData() installedLastHeightCoord = tempX + width + tempWidthMargin @@ -1479,6 +1531,7 @@ export function useModuleBasicSetting(tabNum) { //오브젝트와 겹치지 않으면 넣는다 if (isDisjoint) { canvas?.add(manualModule) + canvas?.renderAll() manualDrawModules.push(manualModule) setModuleStatisticsData() installedLastHeightCoord = tempX - width - tempWidthMargin From 63db694efa3f105ca390e4acaddcc8e3a224c0dc Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 17 Mar 2025 18:36:39 +0900 Subject: [PATCH 05/35] =?UTF-8?q?=EB=8B=A8=EC=88=98=EC=A7=80=EC=A0=95?= =?UTF-8?q?=EB=B0=B0=EC=B9=98=20=EC=9E=91=EC=97=85=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/basic/BasicSetting.jsx | 13 ++- .../floor-plan/modal/basic/step/Placement.jsx | 35 +++++--- src/hooks/module/useModuleBasicSetting.js | 86 +++++++++++++------ src/locales/ja.json | 3 +- src/locales/ko.json | 3 +- src/store/canvasAtom.js | 10 +++ 6 files changed, 104 insertions(+), 46 deletions(-) diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index 33b0c65f..c76c9394 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -6,7 +6,14 @@ import PitchModule from '@/components/floor-plan/modal/basic/step/pitch/PitchMod import PitchPlacement from '@/components/floor-plan/modal/basic/step/pitch/PitchPlacement' import Placement from '@/components/floor-plan/modal/basic/step/Placement' import { useRecoilValue, useRecoilState } from 'recoil' -import { canvasSettingState, canvasState, checkedModuleState, isManualModuleLayoutSetupState, isManualModuleSetupState } from '@/store/canvasAtom' +import { + canvasSettingState, + canvasState, + checkedModuleState, + isManualModuleLayoutSetupState, + isManualModuleSetupState, + toggleManualSetupModeState, +} from '@/store/canvasAtom' import { usePopup } from '@/hooks/usePopup' import { Orientation } from '@/components/floor-plan/modal/basic/step/Orientation' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' @@ -38,7 +45,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const [isClosePopup, setIsClosePopup] = useState({ close: false, id: 0 }) const [checkedModules, setCheckedModules] = useRecoilState(checkedModuleState) - const [manualSetupMode, setManualSetupMode] = useState('') + const [manualSetupMode, setManualSetupMode] = useRecoilState(toggleManualSetupModeState) const [layoutSetup, setLayoutSetup] = useState([{}]) @@ -142,6 +149,8 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { useEffect(() => { if (basicSetting.roofSizeSet !== '3') { + console.log('ManualSetupMode', manualSetupMode) + if (manualSetupMode.indexOf('manualSetup') > -1) { manualModuleSetup(placementRef) } else if (manualSetupMode.indexOf('manualLayoutSetup') > -1) { diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx index 582f291c..8c105e00 100644 --- a/src/components/floor-plan/modal/basic/step/Placement.jsx +++ b/src/components/floor-plan/modal/basic/step/Placement.jsx @@ -1,14 +1,21 @@ import { forwardRef, useEffect, useState } from 'react' import { useMessage } from '@/hooks/useMessage' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' -import { checkedModuleState, currentCanvasPlanState, isManualModuleLayoutSetupState, isManualModuleSetupState } from '@/store/canvasAtom' +import { + checkedModuleState, + currentCanvasPlanState, + isManualModuleLayoutSetupState, + isManualModuleSetupState, + isModuleChidoriSetupState, + toggleManualSetupModeState, +} from '@/store/canvasAtom' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions' import { isObjectNotEmpty } from '@/util/common-utils' const Placement = forwardRef((props, refs) => { const { getMessage } = useMessage() - const [isChidori, setIsChidori] = useState(false) + const [isChidori, setIsChidori] = useRecoilState(isModuleChidoriSetupState) const [isChidoriNotAble, setIsChidoriNotAble] = useState(false) const [setupLocation, setSetupLocation] = useState('eaves') @@ -26,6 +33,7 @@ const Placement = forwardRef((props, refs) => { //언마운트시 버튼 초기화 const setIsManualModuleSetup = useSetRecoilState(isManualModuleSetupState) const setIsManualModuleLayoutSetup = useSetRecoilState(isManualModuleLayoutSetupState) + const setManualSetupMode = useSetRecoilState(toggleManualSetupModeState) //모듈 배치면 생성 useEffect(() => { @@ -41,6 +49,7 @@ const Placement = forwardRef((props, refs) => { return () => { setIsManualModuleSetup(false) setIsManualModuleLayoutSetup(false) + setManualSetupMode('') } }, []) @@ -60,7 +69,11 @@ const Placement = forwardRef((props, refs) => { setSelectedItems(initCheckedModule) setSelectedModules(moduleSelectionData.module) props.setLayoutSetup(moduleSelectionData.module.itemList.map((item) => ({ moduleId: item.itemId, col: 0, row: 0 }))) - props.layoutSetupRef.current = moduleSelectionData.module.itemList.map((item) => ({ moduleId: item.itemId, col: 0, row: 0 })) + props.layoutSetupRef.current = moduleSelectionData.module.itemList.map((item) => ({ + moduleId: item.itemId, + col: 0, + row: 0, + })) } //모듈 배치면 생성 @@ -101,16 +114,6 @@ const Placement = forwardRef((props, refs) => { refs.setupLocation.current = e.target.value } - const handleMaxSetup = (e) => { - if (e.target.checked) { - setIsMaxSetup('true') - refs.isMaxSetup.current = 'true' - } else { - setIsMaxSetup('false') - refs.isMaxSetup.current = 'false' - } - } - //체크된 모듈 아이디 추출 const handleSelectedItem = (e) => { setSelectedItems({ ...selectedItems, [e.target.name]: e.target.checked }) @@ -120,7 +123,11 @@ const Placement = forwardRef((props, refs) => { const newLayoutSetup = [...props.layoutSetup] newLayoutSetup[index] = { ...newLayoutSetup[index], moduleId: itemId, [e.target.name]: Number(e.target.value) } props.setLayoutSetup(newLayoutSetup) - props.layoutSetupRef.current[index] = { ...props.layoutSetupRef.current[index], moduleId: itemId, [e.target.name]: Number(e.target.value) } + props.layoutSetupRef.current[index] = { + ...props.layoutSetupRef.current[index], + moduleId: itemId, + [e.target.name]: Number(e.target.value), + } } return ( diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 5203a972..cc266caa 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -8,6 +8,8 @@ import { currentObjectState, isManualModuleLayoutSetupState, isManualModuleSetupState, + isModuleChidoriSetupState, + toggleManualSetupModeState, } from '@/store/canvasAtom' import { rectToPolygon, polygonToTurfPolygon, calculateVisibleModuleHeight, getDegreeByChon, toFixedWithoutRounding } from '@/util/canvas-util' @@ -59,6 +61,9 @@ export function useModuleBasicSetting(tabNum) { const [currentObject, setCurrentObject] = useRecoilState(currentObjectState) const { setModuleStatisticsData } = useCircuitTrestle() const { createRoofPolygon, createMarginPolygon, createPaddingPolygon } = useMode() + const isModuleChidoriSetup = useRecoilValue(isModuleChidoriSetupState) + + const setManualSetupMode = useSetRecoilState(toggleManualSetupModeState) useEffect(() => { // console.log('basicSetting', basicSetting) @@ -437,19 +442,22 @@ export function useModuleBasicSetting(tabNum) { //레이아웃 수동설치 토글 if (isManualModuleLayoutSetup) { setIsManualModuleLayoutSetup(false) + setManualSetupMode(`manualLayoutSetup_false`) } const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 if (isManualModuleSetup) { if (checkedModule.length === 0) { swalFire({ text: getMessage('module.place.select.module') }) - setIsManualModuleSetup(!isManualModuleSetup) + setIsManualModuleSetup(false) + setManualSetupMode(`manualSetup_false`) return } if (checkedModule.length > 1) { swalFire({ text: getMessage('module.place.select.one.module') }) - setIsManualModuleSetup(!isManualModuleSetup) + setIsManualModuleSetup(false) + setManualSetupMode(`manualSetup_false`) return } @@ -604,18 +612,13 @@ export function useModuleBasicSetting(tabNum) { //흐름방향따라 달라야 한다. if (flowDirection === 'south' || flowDirection === 'north') { if (Math.abs(smallCenterX - holdCellCenterX) < snapDistance) { + //움직이는 모듈 가운데 -> 설치 모듈 가운데 tempModule.left = holdCellCenterX - toFixedWithoutRounding(width / 2, 2) } - //왼쪽 -> 가운데 + //움직이는 모듈왼쪽 -> 가운데 if (Math.abs(smallLeft - holdCellCenterX) < snapDistance) { - // console.log('holdCellCenterX', holdCellCenterX) - // console.log('smallLeft', smallLeft) - - // console.log('모듈 센터에 스냅') tempModule.left = holdCellCenterX + intvHor / 2 - - // console.log('tempModule.left', tempModule.left) } // 오른쪽 -> 가운데 if (Math.abs(smallRight - holdCellCenterX) < snapDistance) { @@ -695,6 +698,10 @@ export function useModuleBasicSetting(tabNum) { if (Math.abs(smallTop - holdCellTop) < sideSnapDistance) { tempModule.top = holdCellTop } + + if (Math.abs(smallLeft - holdCellLeft) < snapDistance) { + tempModule.left = holdCellLeft + } } //가운데 -> 가운대 @@ -734,22 +741,19 @@ export function useModuleBasicSetting(tabNum) { // if (Math.abs(smallLeft - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 // } - // 모듈이 가운데가 세로중앙선에 붙게 스냅 - if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < trestleSnapDistance) { - tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width / 2 - } - + // if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < trestleSnapDistance) { + // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width / 2 + // } // 모듈오른쪽이 세로중앙선에 붙게 스냅 // if (Math.abs(smallRight - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < trestleSnapDistance) { // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width * tempModule.scaleX // } } else { // 모듈이 가로중앙선에 스냅 - if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < trestleSnapDistance) { - tempModule.top = bigCenterY - tempModule.height / 2 - } - + // if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < trestleSnapDistance) { + // tempModule.top = bigCenterY - tempModule.height / 2 + // } // if (Math.abs(smallTop - (trestleTop + moduleSetupSurfaces[i].height / 2)) < trestleSnapDistance) { // tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 // } @@ -869,6 +873,7 @@ export function useModuleBasicSetting(tabNum) { const manualModuleLayoutSetup = (layoutSetupRef) => { if (isManualModuleSetup) { setIsManualModuleSetup(false) + setManualSetupMode(`manualSetup_false`) } const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 @@ -876,7 +881,8 @@ export function useModuleBasicSetting(tabNum) { if (isManualModuleLayoutSetup) { if (checkedModule.length === 0) { swalFire({ text: getMessage('module.place.select.module') }) - setIsManualModuleLayoutSetup(!isManualModuleLayoutSetup) + setIsManualModuleLayoutSetup(false) + setManualSetupMode(`manualLayoutSetup_false`) return } @@ -885,8 +891,9 @@ export function useModuleBasicSetting(tabNum) { ) if (hasZeroLength) { - swalFire({ text: getMessage('모듈의 열, 행을 입력해 주세요.') }) - setIsManualModuleLayoutSetup(!isManualModuleLayoutSetup) + swalFire({ text: getMessage('module.layout.setup.has.zero.value') }) + setIsManualModuleLayoutSetup(false) + setManualSetupMode(`manualLayoutSetup_false`) return } @@ -1205,6 +1212,7 @@ export function useModuleBasicSetting(tabNum) { if (tempModule) { let startX, startY let installedLastHeightCoord = 0 //마지막으로 설치된 모듈의 좌표 + let installedHeightModuleCount = 0 checkedModule.forEach((module, index) => { //모듈 사이즈 @@ -1233,10 +1241,13 @@ export function useModuleBasicSetting(tabNum) { moduleOptions.fill = module.color - const col = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].col - const row = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].row + let col = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].col + let row = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].row + let tempCol = col + for (let i = 0; i < row; i++) { let tempY = startY - i * height + let isInstalled = false if (index > 0) { //두번째 모듈일때 마지막 설치 지점 @@ -1245,15 +1256,26 @@ export function useModuleBasicSetting(tabNum) { let tempHeightMargin = i === 0 ? 0 : i * intvVer - for (let j = 0; j < col; j++) { + //치도리 설치시 컬럼 조정 + if (isModuleChidoriSetup) { + //치도리면 짝수열은 안으로 넣기 + tempCol = installedHeightModuleCount % 2 === 0 ? col : col - 1 + } + + for (let j = 0; j < tempCol; j++) { + let chidoriMargin = 0 let tempX = startX + j * width let tempWidthMargin = j === 0 ? 0 : j * intvHor + if (isModuleChidoriSetup) { + chidoriMargin = installedHeightModuleCount % 2 === 0 ? 0 : width / 2 + intvHor + } + let rectPoints = [ - { x: tempX + tempWidthMargin, y: tempY - height - tempHeightMargin }, - { x: tempX + tempWidthMargin, y: tempY - tempHeightMargin }, - { x: tempX + width + tempWidthMargin, y: tempY - tempHeightMargin }, - { x: tempX + width + tempWidthMargin, y: tempY - height - tempHeightMargin }, + { x: tempX + tempWidthMargin + chidoriMargin, y: tempY - height - tempHeightMargin }, + { x: tempX + tempWidthMargin + chidoriMargin, y: tempY - tempHeightMargin }, + { x: tempX + width + tempWidthMargin + chidoriMargin, y: tempY - tempHeightMargin }, + { x: tempX + width + tempWidthMargin + chidoriMargin, y: tempY - height - tempHeightMargin }, ] tempModule.set({ points: rectPoints }) @@ -1288,6 +1310,10 @@ export function useModuleBasicSetting(tabNum) { manualDrawModules.push(manualModule) setModuleStatisticsData() installedLastHeightCoord = tempY - height - tempHeightMargin + + if (j === 0) { + isInstalled = true + } } else { //디버깅용 // manualModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) @@ -1308,6 +1334,10 @@ export function useModuleBasicSetting(tabNum) { // } } } + + if (isInstalled) { + ++installedHeightModuleCount + } } } else if (flowDirection === 'north') { //북북 diff --git a/src/locales/ja.json b/src/locales/ja.json index 0028a047..69b6b28f 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -1034,5 +1034,6 @@ "roof.exceed.count": "屋根材は4つまで選択可能です。", "outerLine.property.fix": "外壁線の属性設定 を完了しますか?", "outerLine.property.close": "外壁線の属性設定 を終了しますか?", - "want.to.complete.auxiliary.creation": "보補助線の作成を完了しますか?" + "want.to.complete.auxiliary.creation": "보補助線の作成を完了しますか?", + "module.layout.setup.has.zero.value": "モジュールの列、行を入力してください." } diff --git a/src/locales/ko.json b/src/locales/ko.json index 4c051305..79a47142 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -1034,5 +1034,6 @@ "roof.exceed.count": "지붕재는 4개까지 선택 가능합니다.", "outerLine.property.fix": "외벽선 속성 설정을 완료하시겠습니까?", "outerLine.property.close": "외벽선 속성 설정을 종료하시겠습니까?", - "want.to.complete.auxiliary.creation": "보조선 작성을 완료하시겠습니까?" + "want.to.complete.auxiliary.creation": "보조선 작성을 완료하시겠습니까?", + "module.layout.setup.has.zero.value": "모듈의 열, 행을 입력해 주세요." } diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js index b31b8bc3..dc9aeabd 100644 --- a/src/store/canvasAtom.js +++ b/src/store/canvasAtom.js @@ -389,3 +389,13 @@ export const isManualModuleLayoutSetupState = atom({ key: 'isManualModuleLayoutSetupState', default: false, }) + +export const isModuleChidoriSetupState = atom({ + key: 'isModuleChidoriSetupState', + default: false, +}) + +export const toggleManualSetupModeState = atom({ + key: 'toggleManualSetupModeState', + default: '', +}) From 8a5bd9f505bcc907f5ee61905b2acf13aad59002 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Tue, 18 Mar 2025 15:44:41 +0900 Subject: [PATCH 06/35] =?UTF-8?q?=EB=8B=A8=EC=88=98=EB=B0=B0=EC=B9=98=20?= =?UTF-8?q?=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/basic/BasicSetting.jsx | 30 +- .../floor-plan/modal/basic/step/Placement.jsx | 65 +- src/hooks/module/useModuleBasicSetting.js | 674 ++++++++++-------- src/store/canvasAtom.js | 9 +- 4 files changed, 409 insertions(+), 369 deletions(-) diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index c76c9394..a3f0f08e 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -97,13 +97,6 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { setTabNum(tabNum + 1) } - const placementRef = { - isChidori: useRef('false'), - setupLocation: useRef('eaves'), - } - - const layoutSetupRef = useRef([]) - const placementFlatRef = { setupLocation: useRef('south'), } @@ -149,16 +142,18 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { useEffect(() => { if (basicSetting.roofSizeSet !== '3') { - console.log('ManualSetupMode', manualSetupMode) - if (manualSetupMode.indexOf('manualSetup') > -1) { - manualModuleSetup(placementRef) + manualModuleSetup() } else if (manualSetupMode.indexOf('manualLayoutSetup') > -1) { - manualModuleLayoutSetup(layoutSetupRef) + manualModuleLayoutSetup(layoutSetup) + } else if (manualSetupMode.indexOf('off') > -1) { + manualModuleSetup() + manualModuleLayoutSetup(layoutSetup) } } else { manualFlatroofModuleSetup(placementFlatRef) } + if (isClosePopup.close) { closePopup(isClosePopup.id) } @@ -166,12 +161,13 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { useEffect(() => { if (isManualModuleLayoutSetup) { - manualModuleLayoutSetup(layoutSetupRef) + manualModuleLayoutSetup(layoutSetup) } }, [layoutSetup]) useEffect(() => { setIsManualModuleSetup(false) + setIsManualModuleLayoutSetup(false) }, [checkedModules]) return ( @@ -189,13 +185,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { {/*배치면 초기설정 - 입력방법: 복시도 입력 || 실측값 입력*/} {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 2 && } {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 3 && ( - + )} {/*배치면 초기설정 - 입력방법: 육지붕*/} @@ -227,7 +217,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { - diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx index 8c105e00..4afd507b 100644 --- a/src/components/floor-plan/modal/basic/step/Placement.jsx +++ b/src/components/floor-plan/modal/basic/step/Placement.jsx @@ -3,10 +3,9 @@ import { useMessage } from '@/hooks/useMessage' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' import { checkedModuleState, - currentCanvasPlanState, isManualModuleLayoutSetupState, isManualModuleSetupState, - isModuleChidoriSetupState, + moduleSetupOptionState, toggleManualSetupModeState, } from '@/store/canvasAtom' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' @@ -15,13 +14,10 @@ import { isObjectNotEmpty } from '@/util/common-utils' const Placement = forwardRef((props, refs) => { const { getMessage } = useMessage() - const [isChidori, setIsChidori] = useRecoilState(isModuleChidoriSetupState) + const [isChidoriNotAble, setIsChidoriNotAble] = useState(false) - const [setupLocation, setSetupLocation] = useState('eaves') - const [isMaxSetup, setIsMaxSetup] = useState('false') const [selectedItems, setSelectedItems] = useState({}) - const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) const setCheckedModules = useSetRecoilState(checkedModuleState) @@ -35,6 +31,8 @@ const Placement = forwardRef((props, refs) => { const setIsManualModuleLayoutSetup = useSetRecoilState(isManualModuleLayoutSetupState) const setManualSetupMode = useSetRecoilState(toggleManualSetupModeState) + const [moduleSetupOption, setModuleSetupOption] = useRecoilState(moduleSetupOptionState) //모듈 설치 옵션 + //모듈 배치면 생성 useEffect(() => { if (moduleSelectionData) { @@ -49,7 +47,7 @@ const Placement = forwardRef((props, refs) => { return () => { setIsManualModuleSetup(false) setIsManualModuleLayoutSetup(false) - setManualSetupMode('') + setManualSetupMode('off') } }, []) @@ -69,11 +67,6 @@ const Placement = forwardRef((props, refs) => { setSelectedItems(initCheckedModule) setSelectedModules(moduleSelectionData.module) props.setLayoutSetup(moduleSelectionData.module.itemList.map((item) => ({ moduleId: item.itemId, col: 0, row: 0 }))) - props.layoutSetupRef.current = moduleSelectionData.module.itemList.map((item) => ({ - moduleId: item.itemId, - col: 0, - row: 0, - })) } //모듈 배치면 생성 @@ -105,13 +98,21 @@ const Placement = forwardRef((props, refs) => { const handleChangeChidori = (e) => { const bool = e.target.value === 'true' ? true : false - setIsChidori(bool) - refs.isChidori.current = e.target.value + setModuleSetupOption({ ...moduleSetupOption, isChidori: bool }) + + //변경하면 수동 다 꺼짐 + setIsManualModuleSetup(false) + setIsManualModuleLayoutSetup(false) + setManualSetupMode('off') } const handleSetupLocation = (e) => { - setSetupLocation(e.target.value) - refs.setupLocation.current = e.target.value + setModuleSetupOption({ ...moduleSetupOption, setupLocation: e.target.value }) + + //변경하면 수동 다 꺼짐 + setIsManualModuleSetup(false) + setIsManualModuleLayoutSetup(false) + setManualSetupMode('off') } //체크된 모듈 아이디 추출 @@ -123,11 +124,6 @@ const Placement = forwardRef((props, refs) => { const newLayoutSetup = [...props.layoutSetup] newLayoutSetup[index] = { ...newLayoutSetup[index], moduleId: itemId, [e.target.name]: Number(e.target.value) } props.setLayoutSetup(newLayoutSetup) - props.layoutSetupRef.current[index] = { - ...props.layoutSetupRef.current[index], - moduleId: itemId, - [e.target.name]: Number(e.target.value), - } } return ( @@ -214,7 +210,7 @@ const Placement = forwardRef((props, refs) => { type="radio" name="radio01" id="ra01" - checked={isChidori} + checked={moduleSetupOption.isChidori} disabled={isChidoriNotAble} value={'true'} onChange={(e) => handleChangeChidori(e)} @@ -222,7 +218,14 @@ const Placement = forwardRef((props, refs) => {
- handleChangeChidori(e)} /> + handleChangeChidori(e)} + />
@@ -232,24 +235,12 @@ const Placement = forwardRef((props, refs) => {
{getMessage('modal.module.basic.setting.module.placement.arrangement.standard')}
-
- - -
@@ -260,7 +251,7 @@ const Placement = forwardRef((props, refs) => { type="radio" name="radio05" id="ra05" - checked={setupLocation === 'ridge'} + checked={moduleSetupOption.setupLocation === 'ridge'} value={'ridge'} onChange={handleSetupLocation} disabled={isMultiModule} diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index cc266caa..524cbd73 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -8,7 +8,7 @@ import { currentObjectState, isManualModuleLayoutSetupState, isManualModuleSetupState, - isModuleChidoriSetupState, + moduleSetupOptionState, toggleManualSetupModeState, } from '@/store/canvasAtom' @@ -33,6 +33,7 @@ import { v4 as uuidv4 } from 'uuid' import { isObjectNotEmpty } from '@/util/common-utils' import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle' import { useMode } from '@/hooks/useMode' +import { usePolygon } from '@/hooks/usePolygon' export function useModuleBasicSetting(tabNum) { const canvas = useRecoilValue(canvasState) @@ -61,7 +62,10 @@ export function useModuleBasicSetting(tabNum) { const [currentObject, setCurrentObject] = useRecoilState(currentObjectState) const { setModuleStatisticsData } = useCircuitTrestle() const { createRoofPolygon, createMarginPolygon, createPaddingPolygon } = useMode() - const isModuleChidoriSetup = useRecoilValue(isModuleChidoriSetupState) + + const { drawDirectionArrow } = usePolygon() + + const moduleSetupOption = useRecoilValue(moduleSetupOptionState) const setManualSetupMode = useSetRecoilState(toggleManualSetupModeState) @@ -440,13 +444,15 @@ export function useModuleBasicSetting(tabNum) { */ const manualModuleSetup = (placementRef) => { //레이아웃 수동설치 토글 - if (isManualModuleLayoutSetup) { - setIsManualModuleLayoutSetup(false) - setManualSetupMode(`manualLayoutSetup_false`) - } + const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 if (isManualModuleSetup) { + if (isManualModuleLayoutSetup) { + setIsManualModuleLayoutSetup(false) + // setManualSetupMode(`manualLayoutSetup_false`) + } + if (checkedModule.length === 0) { swalFire({ text: getMessage('module.place.select.module') }) setIsManualModuleSetup(false) @@ -871,14 +877,17 @@ export function useModuleBasicSetting(tabNum) { } const manualModuleLayoutSetup = (layoutSetupRef) => { - if (isManualModuleSetup) { - setIsManualModuleSetup(false) - setManualSetupMode(`manualSetup_false`) - } - const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 + const isChidori = moduleSetupOption.isChidori + const setupLocation = moduleSetupOption.setupLocation + if (isManualModuleLayoutSetup) { + if (isManualModuleSetup) { + setIsManualModuleSetup(false) + // setManualSetupMode(`manualSetup_false`) + } + if (checkedModule.length === 0) { swalFire({ text: getMessage('module.place.select.module') }) setIsManualModuleLayoutSetup(false) @@ -887,7 +896,7 @@ export function useModuleBasicSetting(tabNum) { } const hasZeroLength = checkedModule.some((item) => - layoutSetupRef.current.some((layoutItem) => item.itemId === layoutItem.moduleId && (layoutItem.row === 0 || layoutItem.col === 0)), + layoutSetupRef.some((layoutItem) => item.itemId === layoutItem.moduleId && (layoutItem.row === 0 || layoutItem.col === 0)), ) if (hasZeroLength) { @@ -1009,20 +1018,20 @@ export function useModuleBasicSetting(tabNum) { const points = [ { - x: Number(mousePoint.x.toFixed(1)) + Number((width / 2).toFixed(1)), - y: Number(mousePoint.y.toFixed(1)) - Number((height / 2).toFixed(1)), + x: toFixedWithoutRounding(mousePoint.x, 2) + toFixedWithoutRounding(width / 2, 2), + y: toFixedWithoutRounding(mousePoint.y, 2) - toFixedWithoutRounding(height / 2, 2), }, { - x: Number(mousePoint.x.toFixed(1)) + Number((width / 2).toFixed(1)), - y: Number(mousePoint.y.toFixed(1)) + Number((height / 2).toFixed(1)), + x: toFixedWithoutRounding(mousePoint.x, 2) + toFixedWithoutRounding(width / 2, 2), + y: toFixedWithoutRounding(mousePoint.y, 2) + toFixedWithoutRounding(height / 2, 2), }, { - x: Number(mousePoint.x.toFixed(1)) - Number((width / 2).toFixed(1)), - y: Number(mousePoint.y.toFixed(1)) + Number((height / 2).toFixed(1)), + x: toFixedWithoutRounding(mousePoint.x, 2) - toFixedWithoutRounding(width / 2, 2), + y: toFixedWithoutRounding(mousePoint.y, 2) - toFixedWithoutRounding(height / 2, 2), }, { - x: Number(mousePoint.x.toFixed(1)) - Number((width / 2).toFixed(1)), - y: Number(mousePoint.y.toFixed(1)) - Number((height / 2).toFixed(1)), + x: toFixedWithoutRounding(mousePoint.x, 2) - toFixedWithoutRounding(width / 2, 2), + y: toFixedWithoutRounding(mousePoint.y, 2) + toFixedWithoutRounding(height / 2, 2), }, ] @@ -1039,11 +1048,11 @@ export function useModuleBasicSetting(tabNum) { stroke: 'black', strokeWidth: 1, strokeDashArray: [10, 5], - width: Number(width.toFixed(1)), //작은버전 - height: Number(height.toFixed(1)), //작은버전 - left: Number(mousePoint.x.toFixed(1) - Number((width / 2).toFixed(1))), //작은버전 - top: Number(mousePoint.y.toFixed(1) - Number((height / 2).toFixed(1))), //작은버전 - // width: Number((width * col).toFixed(1)) + Number((intvHor * (col - 1)).toFixed(1)), //큰버전 + width: toFixedWithoutRounding(width, 2), //작은버전 + height: toFixedWithoutRounding(height, 2), //작은버전 + left: toFixedWithoutRounding(mousePoint.x, 2) - toFixedWithoutRounding(width / 2, 2), //작은버전 + top: toFixedWithoutRounding(mousePoint.y, 2) - toFixedWithoutRounding(height / 2, 2), //작은버전 + // // width: Number((width * col).toFixed(1)) + Number((intvHor * (col - 1)).toFixed(1)), //큰버전 // height: Number((height * row).toFixed(1)) + Number((intvVer * (row - 1)).toFixed(1)), //큰버전 // left: Number(mousePoint.x.toFixed(1)) - calcHalfWidth.toFixed(1), //큰버전 // top: Number(mousePoint.y.toFixed(1)) - calcHalfHeight.toFixed(1), //큰버전 @@ -1068,77 +1077,131 @@ export function useModuleBasicSetting(tabNum) { * 스냅기능 */ let snapDistance = flowDirection === 'south' || flowDirection === 'north' ? 70 : 40 + let sideSnapDistance = 15 let trestleSnapDistance = 15 - const trestleLeft = Number(moduleSetupSurfaces[i].left.toFixed(1)) - Number((moduleSetupSurfaces[i].width / 2).toFixed(1)) - const trestleTop = Number(moduleSetupSurfaces[i].top.toFixed(1)) - Number((moduleSetupSurfaces[i].height / 2).toFixed(1)) - const trestleRight = Number(moduleSetupSurfaces[i].left.toFixed(1)) + Number((moduleSetupSurfaces[i].width / 2).toFixed(1)) - const trestleBottom = Number(moduleSetupSurfaces[i].top.toFixed(1)) + Number((moduleSetupSurfaces[i].height / 2).toFixed(1)) + const trestleLeft = toFixedWithoutRounding(moduleSetupSurfaces[i].left, 2) - toFixedWithoutRounding(moduleSetupSurfaces[i].width / 2, 2) + const trestleTop = toFixedWithoutRounding(moduleSetupSurfaces[i].top, 2) - toFixedWithoutRounding(moduleSetupSurfaces[i].height / 2, 2) + const trestleRight = + toFixedWithoutRounding(moduleSetupSurfaces[i].left, 2) + toFixedWithoutRounding(moduleSetupSurfaces[i].width / 2, 2) + const trestleBottom = + toFixedWithoutRounding(moduleSetupSurfaces[i].top, 2) + toFixedWithoutRounding(moduleSetupSurfaces[i].height / 2, 2) const bigCenterY = (trestleTop + trestleTop + moduleSetupSurfaces[i].height) / 2 // 이동하는 모듈의 경계 좌표 - const smallLeft = Number(tempModule.left.toFixed(1)) - const smallTop = Number(tempModule.top.toFixed(1)) - const smallRight = smallLeft + Number(tempModule.width.toFixed(1)) - const smallBottom = smallTop + Number(tempModule.height.toFixed(1)) - const smallCenterX = smallLeft + Number((tempModule.width / 2).toFixed(1)) - const smallCenterY = smallTop + Number((tempModule.height / 2).toFixed(1)) + const smallLeft = toFixedWithoutRounding(tempModule.left, 2) + const smallTop = toFixedWithoutRounding(tempModule.top, 2) + const smallRight = smallLeft + toFixedWithoutRounding(tempModule.width, 2) + const smallBottom = smallTop + toFixedWithoutRounding(tempModule.height, 2) + const smallCenterX = smallLeft + toFixedWithoutRounding(tempModule.width / 2, 2) + const smallCenterY = smallTop + toFixedWithoutRounding(tempModule.height / 2, 2) /** * 미리 깔아놓은 셀이 있을때 셀에 흡착됨 */ if (manualDrawModules) { manualDrawModules.forEach((cell) => { - const holdCellLeft = cell.left - const holdCellTop = cell.top - const holdCellRight = holdCellLeft + Number(cell.width.toFixed(1)) - const holdCellBottom = holdCellTop + Number(cell.height.toFixed(1)) - const holdCellCenterX = holdCellLeft + Number((cell.width / 2).toFixed(1)) - const holdCellCenterY = holdCellTop + Number((cell.height / 2).toFixed(1)) + const holdCellLeft = toFixedWithoutRounding(cell.left, 2) + const holdCellTop = toFixedWithoutRounding(cell.top, 2) + const holdCellRight = holdCellLeft + toFixedWithoutRounding(cell.width, 2) + const holdCellBottom = holdCellTop + toFixedWithoutRounding(cell.height, 2) + const holdCellCenterX = holdCellLeft + toFixedWithoutRounding(cell.width / 2, 2) + const holdCellCenterY = holdCellTop + toFixedWithoutRounding(cell.height / 2, 2) - //설치된 셀에 좌측에 스냅 - if (Math.abs(smallRight - holdCellLeft) < snapDistance) { - tempModule.left = holdCellLeft - width - intvHor - } + //흐름방향따라 달라야 한다. + if (flowDirection === 'south' || flowDirection === 'north') { + if (Math.abs(smallCenterX - holdCellCenterX) < snapDistance) { + //움직이는 모듈 가운데 -> 설치 모듈 가운데 + tempModule.left = holdCellCenterX - toFixedWithoutRounding(width / 2, 2) + } - //설치된 셀에 우측에 스냅 - if (Math.abs(smallLeft - holdCellRight) < snapDistance) { - tempModule.left = holdCellRight + intvHor - } + //움직이는 모듈왼쪽 -> 가운데 + if (Math.abs(smallLeft - holdCellCenterX) < snapDistance) { + tempModule.left = holdCellCenterX + intvHor / 2 + } + // 오른쪽 -> 가운데 + if (Math.abs(smallRight - holdCellCenterX) < snapDistance) { + tempModule.left = holdCellCenterX - width - intvHor / 2 + } - //설치된 셀에 위쪽에 스냅 - if (Math.abs(smallBottom - holdCellTop) < snapDistance) { - tempModule.top = holdCellTop - height - intvVer - } + //설치된 셀에 좌측에 스냅 + if (Math.abs(smallRight - holdCellLeft) < snapDistance) { + // console.log('모듈 좌측 스냅') + tempModule.left = holdCellLeft - width - intvHor + } - //설치된 셀에 밑쪽에 스냅 - if (Math.abs(smallTop - holdCellBottom) < snapDistance) { - tempModule.top = holdCellBottom + intvVer + //설치된 셀에 우측에 스냅 + if (Math.abs(smallLeft - holdCellRight) < snapDistance) { + // console.log('모듈 우측 스냅') + tempModule.left = holdCellRight + intvHor + } + //설치된 셀에 위쪽에 스냅 + if (Math.abs(smallBottom - holdCellTop) < sideSnapDistance) { + tempModule.top = holdCellTop - height - intvVer + } + + //설치된 셀에 밑쪽에 스냅 + if (Math.abs(smallTop - holdCellBottom) < sideSnapDistance) { + tempModule.top = holdCellBottom + intvVer + } + + //설치된 셀에 윗쪽에 스냅 + if (Math.abs(smallTop - holdCellTop) < sideSnapDistance) { + tempModule.top = holdCellTop + } + } else { + //흐름방향 west, east + + //가운데 가운데 + if (Math.abs(smallCenterY - holdCellCenterY) < snapDistance) { + tempModule.top = holdCellCenterY - toFixedWithoutRounding(width / 2, 2) + } + + //위쪽 -> 가운데 + if (Math.abs(smallTop - holdCellCenterY) < snapDistance) { + // console.log('holdCellCenterX', holdCellCenterX) + // console.log('smallLeft', smallLeft) + + // console.log('모듈 센터에 스냅') + tempModule.top = holdCellCenterY + intvHor / 2 + + // console.log('tempModule.left', tempModule.left) + } + // 밑 -> 가운데 + if (Math.abs(smallBottom - holdCellCenterY) < snapDistance) { + tempModule.top = holdCellCenterY - height - intvHor / 2 + } + + //설치된 셀에 좌측에 스냅 + if (Math.abs(smallRight - holdCellLeft) < snapDistance) { + // console.log('모듈 좌측 스냅') + tempModule.left = holdCellLeft - width - intvHor + } + + //설치된 셀에 우측에 스냅 + if (Math.abs(smallLeft - holdCellRight) < snapDistance) { + // console.log('모듈 우측 스냅') + tempModule.left = holdCellRight + intvHor + } + //설치된 셀에 위쪽에 스냅 + if (Math.abs(smallBottom - holdCellTop) < sideSnapDistance) { + tempModule.top = holdCellTop - height - intvVer + } + + //설치된 셀에 밑쪽에 스냅 + if (Math.abs(smallTop - holdCellBottom) < sideSnapDistance) { + tempModule.top = holdCellBottom + intvVer + } + + //설치된 셀에 윗쪽에 스냅 + if (Math.abs(smallTop - holdCellTop) < sideSnapDistance) { + tempModule.top = holdCellTop + } + + if (Math.abs(smallLeft - holdCellLeft) < snapDistance) { + tempModule.left = holdCellLeft + } } - //가운데 -> 가운데 - if (Math.abs(smallCenterX - holdCellCenterX) < snapDistance) { - tempModule.left = holdCellCenterX - Number((width / 2).toFixed(1)) - } - //왼쪽 -> 가운데 - if (Math.abs(smallLeft - holdCellCenterX) < snapDistance) { - tempModule.left = holdCellCenterX - } - // 오른쪽 -> 가운데 - if (Math.abs(smallRight - holdCellCenterX) < snapDistance) { - tempModule.left = holdCellCenterX - width - } - //세로 가운데 -> 가운데 - if (Math.abs(smallCenterY - holdCellCenterY) < snapDistance) { - tempModule.top = holdCellCenterY - Number((height / 2).toFixed(1)) - } - // //위쪽 -> 가운데 - // if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) { - // tempModule.top = holdCellCenterY - // } - // //아랫쪽 -> 가운데 - // if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) { - // tempModule.top = holdCellCenterY - height - // } }) } @@ -1162,33 +1225,15 @@ export function useModuleBasicSetting(tabNum) { } if (flowDirection === 'south' || flowDirection === 'north') { - // 모듈왼쪽이 세로중앙선에 붙게 스냅 - // if (Math.abs(smallLeft - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { - // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - // } - // 모듈이 가운데가 세로중앙선에 붙게 스냅 if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < trestleSnapDistance) { tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width / 2 } - - // 모듈오른쪽이 세로중앙선에 붙게 스냅 - // if (Math.abs(smallRight - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < trestleSnapDistance) { - // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width * tempModule.scaleX - // } } else { // 모듈이 가로중앙선에 스냅 if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < trestleSnapDistance) { tempModule.top = bigCenterY - tempModule.height / 2 } - - // if (Math.abs(smallTop - (trestleTop + moduleSetupSurfaces[i].height / 2)) < trestleSnapDistance) { - // tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - // } - // 모듈 밑면이 가로중앙선에 스냅 - // if (Math.abs(smallBottom - (trestleTop + moduleSetupSurfaces[i].height / 2)) < trestleSnapDistance) { - // tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - tempModule.height * tempModule.scaleY - // } } tempModule.setCoords() @@ -1234,15 +1279,16 @@ export function useModuleBasicSetting(tabNum) { : tmpHeight //그려진 가이드 라인의 포인트를 기준으로 시작점을 만든다 - if (flowDirection === 'south') { + //남쪽에 처마방향이나 북쪽에 용마루면 + if ((flowDirection === 'south' && setupLocation === 'eaves') || (flowDirection === 'north' && setupLocation === 'ridge')) { //남 startX = toFixedWithoutRounding(tempModule.left, 1) startY = toFixedWithoutRounding(tempModule.top + tempModule.height, 1) moduleOptions.fill = module.color - let col = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].col - let row = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].row + let col = layoutSetupRef.filter((item) => item.moduleId === module.itemId)[0].col + let row = layoutSetupRef.filter((item) => item.moduleId === module.itemId)[0].row let tempCol = col for (let i = 0; i < row; i++) { @@ -1257,7 +1303,7 @@ export function useModuleBasicSetting(tabNum) { let tempHeightMargin = i === 0 ? 0 : i * intvVer //치도리 설치시 컬럼 조정 - if (isModuleChidoriSetup) { + if (isChidori) { //치도리면 짝수열은 안으로 넣기 tempCol = installedHeightModuleCount % 2 === 0 ? col : col - 1 } @@ -1267,7 +1313,7 @@ export function useModuleBasicSetting(tabNum) { let tempX = startX + j * width let tempWidthMargin = j === 0 ? 0 : j * intvHor - if (isModuleChidoriSetup) { + if (isChidori) { chidoriMargin = installedHeightModuleCount % 2 === 0 ? 0 : width / 2 + intvHor } @@ -1324,14 +1370,6 @@ export function useModuleBasicSetting(tabNum) { swalFire({ text: getMessage('module.place.overlab') }) return } - // getModuleStatistics() - // } else { - // swalFire({ text: getMessage('module.place.overlab') }) - // return - // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) - // canvas?.add(tempModule) - // canvas.renderAll() - // } } } @@ -1339,17 +1377,21 @@ export function useModuleBasicSetting(tabNum) { ++installedHeightModuleCount } } - } else if (flowDirection === 'north') { + //북쪽에 처마거나 남쪽에 용마루일경우 + } else if ((flowDirection === 'north' && setupLocation === 'eaves') || (flowDirection === 'south' && setupLocation === 'ridge')) { //북북 startX = toFixedWithoutRounding(tempModule.left + tempModule.width, 1) startY = toFixedWithoutRounding(tempModule.top, 1) moduleOptions.fill = module.color - const col = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].col - const row = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].row + const col = layoutSetupRef.filter((item) => item.moduleId === module.itemId)[0].col + const row = layoutSetupRef.filter((item) => item.moduleId === module.itemId)[0].row + let tempCol = col //치도리시 하나 빼려고 임시로 + for (let i = 0; i < row; i++) { let tempY = startY + i * height + let isInstalled = false if (index > 0) { //두번째 모듈일때 마지막 설치 지점 @@ -1358,15 +1400,24 @@ export function useModuleBasicSetting(tabNum) { let tempHeightMargin = i === 0 ? 0 : i * intvVer - for (let j = 0; j < col; j++) { + if (isChidori) { + tempCol = installedHeightModuleCount % 2 === 0 ? col : col - 1 + } + + for (let j = 0; j < tempCol; j++) { + let chidoriMargin = 0 let tempX = startX - j * width let tempWidthMargin = j === 0 ? 0 : j * intvHor + if (isChidori) { + chidoriMargin = installedHeightModuleCount % 2 === 0 ? 0 : width / 2 + intvHor + } + let rectPoints = [ - { x: tempX - tempWidthMargin, y: tempY + height + tempHeightMargin }, - { x: tempX - tempWidthMargin, y: tempY + tempHeightMargin }, - { x: tempX - width - tempWidthMargin, y: tempY + tempHeightMargin }, - { x: tempX - width - tempWidthMargin, y: tempY + height + tempHeightMargin }, + { x: tempX - tempWidthMargin - chidoriMargin, y: tempY + height + tempHeightMargin }, + { x: tempX - tempWidthMargin - chidoriMargin, y: tempY + tempHeightMargin }, + { x: tempX - width - tempWidthMargin - chidoriMargin, y: tempY + tempHeightMargin }, + { x: tempX - width - tempWidthMargin - chidoriMargin, y: tempY + height + tempHeightMargin }, ] tempModule.set({ points: rectPoints }) @@ -1386,8 +1437,6 @@ export function useModuleBasicSetting(tabNum) { let manualModule = new QPolygon(tempModule.points, { ...moduleOptions, moduleInfo: module, - // left: toFixedWithoutRounding(tempX + tempWidthMargin, 1), - // top: toFixedWithoutRounding(tempY - height - tempHeightMargin, 1), width: toFixedWithoutRounding(width, 1), height: toFixedWithoutRounding(height, 1), }) @@ -1401,6 +1450,10 @@ export function useModuleBasicSetting(tabNum) { manualDrawModules.push(manualModule) setModuleStatisticsData() installedLastHeightCoord = tempY + height + tempHeightMargin + + if (j === 0) { + isInstalled = true + } } else { //디버깅용 // manualModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) @@ -1411,44 +1464,52 @@ export function useModuleBasicSetting(tabNum) { swalFire({ text: getMessage('module.place.overlab') }) return } - // getModuleStatistics() - // } else { - // swalFire({ text: getMessage('module.place.overlab') }) - // return - // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) - // canvas?.add(tempModule) - // canvas.renderAll() - // } } } + if (isInstalled) { + ++installedHeightModuleCount + } } - } else if (flowDirection === 'west') { + //서쪽에 처마 또는 동쪽의 용마루일경우 + } else if ((flowDirection === 'west' && setupLocation === 'eaves') || (flowDirection === 'east' && setupLocation === 'ridge')) { startX = toFixedWithoutRounding(tempModule.left, 1) startY = toFixedWithoutRounding(tempModule.top, 1) moduleOptions.fill = module.color - const col = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].col - const row = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].row + const col = layoutSetupRef.filter((item) => item.moduleId === module.itemId)[0].col + const row = layoutSetupRef.filter((item) => item.moduleId === module.itemId)[0].row + let tempCol = col //치도리시 하나 빼려고 임시로 for (let i = 0; i < row; i++) { //옆으로 올라가는거라 height가 아니고 width로 변경 let tempX = startX + i * width let tempWidthMargin = i === 0 ? 0 : i * intvHor + let isInstalled = false if (index > 0) { //두번째 모듈일때 마지막 설치 지점 //명칭은 그대로 쓴다 tempX = index > 0 && i === 0 ? installedLastHeightCoord + intvHor : installedLastHeightCoord } - for (let j = 0; j < col; j++) { + if (isChidori) { + tempCol = installedHeightModuleCount % 2 === 0 ? col : col - 1 + } + + for (let j = 0; j < tempCol; j++) { let tempY = startY + j * height let tempHeightMargin = j === 0 ? 0 : j * intvVer + let chidoriMargin = 0 + + if (isChidori) { + chidoriMargin = installedHeightModuleCount % 2 === 0 ? 0 : height / 2 + intvVer + } + let rectPoints = [ - { x: tempX + tempWidthMargin, y: tempY + tempHeightMargin }, - { x: tempX + tempWidthMargin, y: tempY + height + tempHeightMargin }, - { x: tempX + width + tempWidthMargin, y: tempY + height + tempHeightMargin }, - { x: tempX + width + tempWidthMargin, y: tempY + tempHeightMargin }, + { x: tempX + tempWidthMargin, y: tempY + tempHeightMargin + chidoriMargin }, + { x: tempX + tempWidthMargin, y: tempY + height + tempHeightMargin + chidoriMargin }, + { x: tempX + width + tempWidthMargin, y: tempY + height + tempHeightMargin + chidoriMargin }, + { x: tempX + width + tempWidthMargin, y: tempY + tempHeightMargin + chidoriMargin }, ] tempModule.set({ points: rectPoints }) @@ -1468,8 +1529,6 @@ export function useModuleBasicSetting(tabNum) { let manualModule = new QPolygon(tempModule.points, { ...moduleOptions, moduleInfo: module, - // left: toFixedWithoutRounding(tempX + tempWidthMargin, 1), - // top: toFixedWithoutRounding(tempY - height - tempHeightMargin, 1), width: toFixedWithoutRounding(width, 1), height: toFixedWithoutRounding(height, 1), }) @@ -1483,6 +1542,10 @@ export function useModuleBasicSetting(tabNum) { manualDrawModules.push(manualModule) setModuleStatisticsData() installedLastHeightCoord = tempX + width + tempWidthMargin + + if (j === 0) { + isInstalled = true + } } else { //디버깅용 // manualModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) @@ -1493,44 +1556,51 @@ export function useModuleBasicSetting(tabNum) { swalFire({ text: getMessage('module.place.overlab') }) return } - // getModuleStatistics() - // } else { - // swalFire({ text: getMessage('module.place.overlab') }) - // return - // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) - // canvas?.add(tempModule) - // canvas.renderAll() - // } } } + if (isInstalled) { + ++installedHeightModuleCount + } } - } else { + //동쪽의 처마 또는 서쪽의 용마루일경우 + } else if ((flowDirection === 'east' && setupLocation === 'eaves') || (flowDirection === 'west' && setupLocation === 'ridge')) { startX = toFixedWithoutRounding(tempModule.left + width, 1) startY = toFixedWithoutRounding(tempModule.top + height, 1) moduleOptions.fill = module.color - const col = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].col - const row = layoutSetupRef.current.filter((item) => item.moduleId === module.itemId)[0].row + const col = layoutSetupRef.filter((item) => item.moduleId === module.itemId)[0].col + const row = layoutSetupRef.filter((item) => item.moduleId === module.itemId)[0].row + let tempCol = col //치도리시 하나 빼려고 임시로 for (let i = 0; i < row; i++) { //옆으로 올라가는거라 height가 아니고 width로 변경 let tempX = startX - i * width let tempWidthMargin = i === 0 ? 0 : i * intvHor + let isInstalled = false if (index > 0) { //두번째 모듈일때 마지막 설치 지점 //명칭은 그대로 쓴다 tempX = index > 0 && i === 0 ? installedLastHeightCoord - intvHor : installedLastHeightCoord } - for (let j = 0; j < col; j++) { + if (isChidori) { + tempCol = installedHeightModuleCount % 2 === 0 ? col : col - 1 + } + + for (let j = 0; j < tempCol; j++) { + let chidoriMargin = 0 let tempY = startY - j * height let tempHeightMargin = j === 0 ? 0 : j * intvVer + if (isChidori) { + chidoriMargin = installedHeightModuleCount % 2 === 0 ? 0 : height / 2 + intvVer + } + let rectPoints = [ - { x: tempX - tempWidthMargin, y: tempY - tempHeightMargin }, - { x: tempX - tempWidthMargin, y: tempY - height - tempHeightMargin }, - { x: tempX - width - tempWidthMargin, y: tempY - height - tempHeightMargin }, - { x: tempX - width - tempWidthMargin, y: tempY - tempHeightMargin }, + { x: tempX - tempWidthMargin, y: tempY - tempHeightMargin - chidoriMargin }, + { x: tempX - tempWidthMargin, y: tempY - height - tempHeightMargin - chidoriMargin }, + { x: tempX - width - tempWidthMargin, y: tempY - height - tempHeightMargin - chidoriMargin }, + { x: tempX - width - tempWidthMargin, y: tempY - tempHeightMargin - chidoriMargin }, ] tempModule.set({ points: rectPoints }) @@ -1550,8 +1620,6 @@ export function useModuleBasicSetting(tabNum) { let manualModule = new QPolygon(tempModule.points, { ...moduleOptions, moduleInfo: module, - // left: toFixedWithoutRounding(tempX + tempWidthMargin, 1), - // top: toFixedWithoutRounding(tempY - height - tempHeightMargin, 1), width: toFixedWithoutRounding(width, 1), height: toFixedWithoutRounding(height, 1), }) @@ -1565,6 +1633,10 @@ export function useModuleBasicSetting(tabNum) { manualDrawModules.push(manualModule) setModuleStatisticsData() installedLastHeightCoord = tempX - width - tempWidthMargin + + if (j === 0) { + isInstalled = true + } } else { //디버깅용 // manualModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) @@ -1575,65 +1647,14 @@ export function useModuleBasicSetting(tabNum) { swalFire({ text: getMessage('module.place.overlab') }) return } - // getModuleStatistics() - // } else { - // swalFire({ text: getMessage('module.place.overlab') }) - // return - // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) - // canvas?.add(tempModule) - // canvas.renderAll() - // } } } + if (isInstalled) { + ++installedHeightModuleCount + } } } }) - //도머 객체를 가져옴 - // if (batchObjects) { - // batchObjects.forEach((object) => { - // let dormerTurfPolygon = polygonToTurfPolygon(object, true) - // const intersection = turf.intersect(turf.featureCollection([dormerTurfPolygon, tempTurfModule])) //겹치는지 확인 - // //겹치면 안됨 - // if (intersection) { - // swalFire({ text: getMessage('module.place.overobject') }) - // isIntersection = false - // } - // }) - // } - - // if (!isIntersection) return - - // tempModule.setCoords() //좌표 재정렬 - // if (turf.booleanContains(turfPolygon, tempTurfModule) || turf.booleanWithin(tempTurfModule, turfPolygon)) { - // //마우스 클릭시 set으로 해당 위치에 셀을 넣음 - // const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 - // if (!isOverlap) { - // canvas?.remove(tempModule) - - // //안겹치면 넣는다 - // // tempModule.setCoords() - // moduleOptions.surfaceId = trestlePolygon.id - - // // console.log('tempModule.points', tempModule.points) - - // let manualModule = new QPolygon(tempModule.points, { - // ...moduleOptions, - // moduleInfo: checkedModule[0], - // left: Number(tempModule.left.toFixed(1)), - // top: Number(tempModule.top.toFixed(1)), - // width: Number(tempModule.width.toFixed(1)), - // height: Number(tempModule.height.toFixed(1)), - // }) - // canvas?.add(manualModule) - // manualDrawModules.push(manualModule) - // setModuleStatisticsData() - // // getModuleStatistics() - // } else { - // swalFire({ text: getMessage('module.place.overlab') }) - // } - // } else { - // swalFire({ text: getMessage('module.place.out') }) - // } } }) } @@ -1663,8 +1684,8 @@ export function useModuleBasicSetting(tabNum) { return } - const isChidori = placementRef.isChidori.current === 'true' ? true : false - const setupLocation = placementRef.setupLocation.current + const isChidori = moduleSetupOption.isChidori + const setupLocation = moduleSetupOption.setupLocation const isMaxSetup = false // const isMaxSetup = placementRef.isMaxSetup.current === 'true' ? true : false @@ -2784,7 +2805,7 @@ export function useModuleBasicSetting(tabNum) { ) //도머s 객체 let moduleOptions = { - fill: '#BFFD9F', + fill: checkedModule[0].color, stroke: 'black', strokeWidth: 0.3, selectable: true, // 선택 가능하게 설정 @@ -2817,14 +2838,15 @@ export function useModuleBasicSetting(tabNum) { const angle = calculateAngle(points1, points2) //변별로 선택으로 되어있을때 모듈면을 회전시키기 - const targetdSurface = moduleSetupSurfaces.filter((surface) => surface.surfaceId === obj.surfaceId)[0] - targetdSurface.angle = -angle + const targetSurface = moduleSetupSurfaces.filter((surface) => surface.surfaceId === obj.surfaceId)[0] + targetSurface.angle = -angle //변별로 선택되어있는 지붕도 회전시키기 - const targetRoof = canvas.getObjects().filter((roof) => roof.name === POLYGON_TYPE.ROOF && roof.id === targetdSurface.parentId)[0] + const targetRoof = canvas.getObjects().filter((roof) => roof.name === POLYGON_TYPE.ROOF && roof.id === targetSurface.parentId)[0] targetRoof.angle = -angle targetRoof.fire('modified') - targetdSurface.fire('modified') + targetSurface.fire('modified') + drawDirectionArrow(targetRoof) } canvas.remove(obj) }) @@ -2833,6 +2855,10 @@ export function useModuleBasicSetting(tabNum) { const targetRoof = canvas.getObjects().filter((roof) => roof.name === POLYGON_TYPE.ROOF && roof.id === surface.parentId)[0] if (targetRoof) targetRoof.angle = -compasDeg surface.angle = -compasDeg + + targetRoof.fire('modified') + surface.fire('modified') + drawDirectionArrow(targetRoof) }) } canvas.renderAll() @@ -2896,131 +2922,158 @@ export function useModuleBasicSetting(tabNum) { /** * 스냅기능 */ - let snapDistance = 10 - let cellSnapDistance = 50 + let snapDistance = flowDirection === 'south' || flowDirection === 'north' ? 70 : 40 + let sideSnapDistance = 15 + let trestleSnapDistance = 15 - let intvHor = flowDirection === 'south' || flowDirection === 'north' ? 1 : 3 - let intvVer = flowDirection === 'south' || flowDirection === 'north' ? 3 : 1 + let intvVer = flowDirection === 'south' || flowDirection === 'north' ? 10 : 30 + let intvHor = flowDirection === 'south' || flowDirection === 'north' ? 30 : 10 - const trestleLeft = moduleSetupSurfaces[i].left - const trestleTop = moduleSetupSurfaces[i].top - const trestleRight = trestleLeft + moduleSetupSurfaces[i].width * moduleSetupSurfaces[i].scaleX - const trestleBottom = trestleTop + moduleSetupSurfaces[i].height * moduleSetupSurfaces[i].scaleY + const trestleLeft = toFixedWithoutRounding(moduleSetupSurfaces[i].left, 2) - toFixedWithoutRounding(moduleSetupSurfaces[i].width / 2, 2) + const trestleTop = toFixedWithoutRounding(moduleSetupSurfaces[i].top, 2) - toFixedWithoutRounding(moduleSetupSurfaces[i].height / 2, 2) + const trestleRight = + toFixedWithoutRounding(moduleSetupSurfaces[i].left, 2) + toFixedWithoutRounding(moduleSetupSurfaces[i].width / 2, 2) + const trestleBottom = + toFixedWithoutRounding(moduleSetupSurfaces[i].top, 2) + toFixedWithoutRounding(moduleSetupSurfaces[i].height / 2, 2) const bigCenterY = (trestleTop + trestleTop + moduleSetupSurfaces[i].height) / 2 - // 작은 폴리곤의 경계 좌표 계산 - const smallLeft = tempModule.left - const smallTop = tempModule.top - const smallRight = smallLeft + tempModule.width * tempModule.scaleX - const smallBottom = smallTop + tempModule.height * tempModule.scaleY - const smallCenterX = smallLeft + (tempModule.width * tempModule.scaleX) / 2 - const smallCenterY = smallTop + (tempModule.height * tempModule.scaleX) / 2 + // 이동하는 모듈의 경계 좌표 + const smallLeft = toFixedWithoutRounding(tempModule.left, 2) + const smallTop = toFixedWithoutRounding(tempModule.top, 2) + const smallRight = smallLeft + toFixedWithoutRounding(tempModule.width, 2) + const smallBottom = smallTop + toFixedWithoutRounding(tempModule.height, 2) + const smallCenterX = smallLeft + toFixedWithoutRounding(tempModule.width / 2, 2) + const smallCenterY = smallTop + toFixedWithoutRounding(tempModule.height / 2, 2) /** * 미리 깔아놓은 셀이 있을때 셀에 흡착됨 */ if (manualDrawModules) { manualDrawModules.forEach((cell) => { - const holdCellLeft = cell.left - const holdCellTop = cell.top - const holdCellRight = holdCellLeft + cell.width * cell.scaleX - const holdCellBottom = holdCellTop + cell.height * cell.scaleY - const holdCellCenterX = holdCellLeft + (cell.width * cell.scaleX) / 2 - const holdCellCenterY = holdCellTop + (cell.height * cell.scaleY) / 2 + const holdCellLeft = toFixedWithoutRounding(cell.left, 2) + const holdCellTop = toFixedWithoutRounding(cell.top, 2) + const holdCellRight = holdCellLeft + toFixedWithoutRounding(cell.width, 2) + const holdCellBottom = holdCellTop + toFixedWithoutRounding(cell.height, 2) + const holdCellCenterX = holdCellLeft + toFixedWithoutRounding(cell.width / 2, 2) + const holdCellCenterY = holdCellTop + toFixedWithoutRounding(cell.height / 2, 2) - //설치된 셀에 좌측에 스냅 - if (Math.abs(smallRight - holdCellLeft) < snapDistance) { - tempModule.left = holdCellLeft - width - intvHor - } + //흐름방향따라 달라야 한다. + if (flowDirection === 'south' || flowDirection === 'north') { + if (Math.abs(smallCenterX - holdCellCenterX) < snapDistance) { + //움직이는 모듈 가운데 -> 설치 모듈 가운데 + tempModule.left = holdCellCenterX - toFixedWithoutRounding(width / 2, 2) + } - //설치된 셀에 우측에 스냅 - if (Math.abs(smallLeft - holdCellRight) < snapDistance) { - tempModule.left = holdCellRight + intvHor - } + //설치된 셀에 좌측에 스냅 + if (Math.abs(smallRight - holdCellLeft) < snapDistance) { + // console.log('모듈 좌측 스냅') + tempModule.left = holdCellLeft - width - intvHor + } - //설치된 셀에 위쪽에 스냅 - if (Math.abs(smallBottom - holdCellTop) < snapDistance) { - tempModule.top = holdCellTop - height - intvVer - } + //설치된 셀에 우측에 스냅 + if (Math.abs(smallLeft - holdCellRight) < snapDistance) { + // console.log('모듈 우측 스냅') + tempModule.left = holdCellRight + intvHor + } + //설치된 셀에 위쪽에 스냅 + if (Math.abs(smallBottom - holdCellTop) < sideSnapDistance) { + tempModule.top = holdCellTop - height - intvVer + } - //설치된 셀에 밑쪽에 스냅 - if (Math.abs(smallTop - holdCellBottom) < snapDistance) { - tempModule.top = holdCellBottom + intvVer + //설치된 셀에 밑쪽에 스냅 + if (Math.abs(smallTop - holdCellBottom) < sideSnapDistance) { + tempModule.top = holdCellBottom + intvVer + } + + //설치된 셀에 윗쪽에 스냅 + if (Math.abs(smallTop - holdCellTop) < sideSnapDistance) { + tempModule.top = holdCellTop + } + } else { + //흐름방향 west, east + + //가운데 가운데 + if (Math.abs(smallCenterY - holdCellCenterY) < snapDistance) { + tempModule.top = holdCellCenterY - toFixedWithoutRounding(width / 2, 2) + } + + //위쪽 -> 가운데 + if (Math.abs(smallTop - holdCellCenterY) < snapDistance) { + // console.log('holdCellCenterX', holdCellCenterX) + // console.log('smallLeft', smallLeft) + + // console.log('모듈 센터에 스냅') + tempModule.top = holdCellCenterY + intvHor / 2 + + // console.log('tempModule.left', tempModule.left) + } + // 밑 -> 가운데 + if (Math.abs(smallBottom - holdCellCenterY) < snapDistance) { + tempModule.top = holdCellCenterY - height - intvHor / 2 + } + + //설치된 셀에 좌측에 스냅 + if (Math.abs(smallRight - holdCellLeft) < snapDistance) { + // console.log('모듈 좌측 스냅') + tempModule.left = holdCellLeft - width - intvHor + } + + //설치된 셀에 우측에 스냅 + if (Math.abs(smallLeft - holdCellRight) < snapDistance) { + // console.log('모듈 우측 스냅') + tempModule.left = holdCellRight + intvHor + } + //설치된 셀에 위쪽에 스냅 + if (Math.abs(smallBottom - holdCellTop) < sideSnapDistance) { + tempModule.top = holdCellTop - height - intvVer + } + + //설치된 셀에 밑쪽에 스냅 + if (Math.abs(smallTop - holdCellBottom) < sideSnapDistance) { + tempModule.top = holdCellBottom + intvVer + } + + //설치된 셀에 윗쪽에 스냅 + if (Math.abs(smallTop - holdCellTop) < sideSnapDistance) { + tempModule.top = holdCellTop + } + + if (Math.abs(smallLeft - holdCellLeft) < snapDistance) { + tempModule.left = holdCellLeft + } } - //가운데 -> 가운데 - if (Math.abs(smallCenterX - holdCellCenterX) < cellSnapDistance) { - tempModule.left = holdCellCenterX - width / 2 - } - //왼쪽 -> 가운데 - if (Math.abs(smallLeft - holdCellCenterX) < cellSnapDistance) { - tempModule.left = holdCellCenterX - } - // 오른쪽 -> 가운데 - if (Math.abs(smallRight - holdCellCenterX) < cellSnapDistance) { - tempModule.left = holdCellCenterX - width - } - //세로 가운데 -> 가운데 - if (Math.abs(smallCenterY - holdCellCenterY) < cellSnapDistance) { - tempModule.top = holdCellCenterY - height / 2 - } - // //위쪽 -> 가운데 - // if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) { - // tempModule.top = holdCellCenterY - // } - // //아랫쪽 -> 가운데 - // if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) { - // tempModule.top = holdCellCenterY - height - // } }) } // 위쪽 변에 스냅 - if (Math.abs(smallTop - trestleTop) < snapDistance) { - tempModule.top = trestleTop + if (Math.abs(smallTop - trestleTop) < trestleSnapDistance) { + tempModule.top = trestleTop + 1 } // 아래쪽 변에 스냅 - if (Math.abs(smallTop + tempModule.height * tempModule.scaleY - (trestleTop + moduleSetupSurfaces[i].height)) < snapDistance) { - tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height * tempModule.scaleY + if (Math.abs(smallBottom - trestleBottom) < trestleSnapDistance) { + tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height - 1 } // 왼쪽변에 스냅 - if (Math.abs(smallLeft - trestleLeft) < snapDistance) { - tempModule.left = trestleLeft + if (Math.abs(smallLeft - trestleLeft) < trestleSnapDistance) { + tempModule.left = trestleLeft + 1 } //오른쪽 변에 스냅 - if (Math.abs(smallRight - trestleRight) < snapDistance) { - tempModule.left = trestleRight - tempModule.width * tempModule.scaleX + if (Math.abs(smallRight - trestleRight) < trestleSnapDistance) { + tempModule.left = trestleRight - tempModule.width - 1 } if (flowDirection === 'south' || flowDirection === 'north') { - // 모듈왼쪽이 세로중앙선에 붙게 스냅 - if (Math.abs(smallLeft - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { - tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - } - // 모듈이 가운데가 세로중앙선에 붙게 스냅 - if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { - tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - (tempModule.width * tempModule.scaleX) / 2 - } - - // 모듈오른쪽이 세로중앙선에 붙게 스냅 - if (Math.abs(smallRight - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { - tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width * tempModule.scaleX + if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < trestleSnapDistance) { + tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width / 2 } } else { // 모듈이 가로중앙선에 스냅 - if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < snapDistance) { + if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < trestleSnapDistance) { tempModule.top = bigCenterY - tempModule.height / 2 } - - if (Math.abs(smallTop - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) { - tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - } - // 모듈 밑면이 가로중앙선에 스냅 - if (Math.abs(smallBottom - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) { - tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - tempModule.height * tempModule.scaleY - } } tempModule.setCoords() @@ -3185,6 +3238,7 @@ export function useModuleBasicSetting(tabNum) { targetRoof.setCoords() targetSurface.setCoords() moduleSetupSurfaces.push(targetSurface) + drawDirectionArrow(targetSurface) } canvas.remove(obj) }) @@ -3193,6 +3247,10 @@ export function useModuleBasicSetting(tabNum) { const targetRoof = canvas.getObjects().filter((roof) => roof.name === POLYGON_TYPE.ROOF && roof.id === surface.parentId)[0] if (targetRoof) targetRoof.angle = -compasDeg surface.angle = -compasDeg + + targetRoof.fire('modified') + surface.fire('modified') + drawDirectionArrow(surface) }) } canvas.renderAll() @@ -3275,8 +3333,6 @@ export function useModuleBasicSetting(tabNum) { return turf.booleanContains(turfModuleSetupSurface, squarePolygon) || turf.booleanWithin(squarePolygon, turfModuleSetupSurface) } - let moduleGroup = [] - const flatRoofDownFlowSetupModule = ( surfaceMaxLines, maxLengthLine, diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js index dc9aeabd..0679938f 100644 --- a/src/store/canvasAtom.js +++ b/src/store/canvasAtom.js @@ -390,9 +390,12 @@ export const isManualModuleLayoutSetupState = atom({ default: false, }) -export const isModuleChidoriSetupState = atom({ - key: 'isModuleChidoriSetupState', - default: false, +export const moduleSetupOptionState = atom({ + key: 'moduleSetupOptionState', + default: { + isChidori: false, //치조 안함 + setupLocation: 'eaves', //처마 + }, }) export const toggleManualSetupModeState = atom({ From 9bb72bfa3acc9fdbea8f92179d433846abbecf82 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Wed, 19 Mar 2025 13:38:35 +0900 Subject: [PATCH 07/35] =?UTF-8?q?=EA=B7=B8=EB=A6=BC=EC=9E=90=20=EC=A0=9C?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useModuleBasicSetting.js | 25 ++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 5fa14745..688a457f 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -206,13 +206,7 @@ export function useModuleBasicSetting(tabNum) { //도머등 오브젝트 객체가 있으면 아웃라인 낸다 const batchObjects = canvas ?.getObjects() - .filter( - (obj) => - obj.name === BATCH_TYPE.OPENING || - obj.name === BATCH_TYPE.SHADOW || - obj.name === BATCH_TYPE.TRIANGLE_DORMER || - obj.name === BATCH_TYPE.PENTAGON_DORMER, - ) //도머s 객체 + .filter((obj) => obj.name === BATCH_TYPE.OPENING || obj.name === BATCH_TYPE.TRIANGLE_DORMER || obj.name === BATCH_TYPE.PENTAGON_DORMER) //그림자 제외 나머지 오브젝트들 //도머도 외곽을 따야한다 const batchObjectOptions = { @@ -850,6 +844,13 @@ export function useModuleBasicSetting(tabNum) { canvas?.add(manualModule) manualDrawModules.push(manualModule) setModuleStatisticsData() + + //그림자는 무조건 가장 앞으로 + const shadowObj = canvas?.getObjects().find((obj) => obj.name === BATCH_TYPE.SHADOW) + if (shadowObj) { + shadowObj.bringToFront() + } + // getModuleStatistics() } else { swalFire({ text: getMessage('module.place.overlab') }) @@ -1656,6 +1657,10 @@ export function useModuleBasicSetting(tabNum) { } } }) + const shadowObj = canvas?.getObjects().find((obj) => obj.name === BATCH_TYPE.SHADOW) + if (shadowObj) { + shadowObj.bringToFront() + } } }) } @@ -2462,6 +2467,12 @@ export function useModuleBasicSetting(tabNum) { // moduleSetupArray: setupedModules, // }) // setModuleIsSetup(moduleArray) + + //그림자는 무조건 가장 앞으로 + const shadowObj = canvas?.getObjects().find((obj) => obj.name === BATCH_TYPE.SHADOW) + if (shadowObj) { + shadowObj.bringToFront() + } }) // calculateForApi() } From c34a7fc54dcaed46e38b7d8cb58da554f64114e7 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Wed, 19 Mar 2025 17:49:17 +0900 Subject: [PATCH 08/35] =?UTF-8?q?=EC=88=98=EB=8F=99=EC=8B=9C=20=EC=B9=98?= =?UTF-8?q?=EC=A1=B0=20=EC=97=AC=EB=B6=80=EC=97=90=20=EB=94=B0=EB=9D=BC=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EA=B0=80=EC=9A=B4=EB=8D=B0=20=ED=9D=A1?= =?UTF-8?q?=EC=B0=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/object/ObjectSetting.jsx | 2 +- src/hooks/module/useModuleBasicSetting.js | 89 +++++++++---------- 2 files changed, 42 insertions(+), 49 deletions(-) diff --git a/src/components/floor-plan/modal/object/ObjectSetting.jsx b/src/components/floor-plan/modal/object/ObjectSetting.jsx index 1bbddfe6..b893bf75 100644 --- a/src/components/floor-plan/modal/object/ObjectSetting.jsx +++ b/src/components/floor-plan/modal/object/ObjectSetting.jsx @@ -100,7 +100,7 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) { ] return ( - + closePopup(id)} />
diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 688a457f..c49764c6 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -64,9 +64,7 @@ export function useModuleBasicSetting(tabNum) { const { createRoofPolygon, createMarginPolygon, createPaddingPolygon } = useMode() const { drawDirectionArrow } = usePolygon() - const moduleSetupOption = useRecoilValue(moduleSetupOptionState) - const setManualSetupMode = useSetRecoilState(toggleManualSetupModeState) useEffect(() => { @@ -440,6 +438,7 @@ export function useModuleBasicSetting(tabNum) { //레이아웃 수동설치 토글 const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 + const isChidori = moduleSetupOption.isChidori if (isManualModuleSetup) { if (isManualModuleLayoutSetup) { @@ -617,15 +616,16 @@ export function useModuleBasicSetting(tabNum) { tempModule.left = holdCellCenterX - toFixedWithoutRounding(width / 2, 2) } - //움직이는 모듈왼쪽 -> 가운데 - if (Math.abs(smallLeft - holdCellCenterX) < snapDistance) { - tempModule.left = holdCellCenterX + intvHor / 2 + if (isChidori) { + //움직이는 모듈왼쪽 -> 가운데 + if (Math.abs(smallLeft - holdCellCenterX) < snapDistance) { + tempModule.left = holdCellCenterX + intvHor / 2 + } + // 오른쪽 -> 가운데 + if (Math.abs(smallRight - holdCellCenterX) < snapDistance) { + tempModule.left = holdCellCenterX - width - intvHor / 2 + } } - // 오른쪽 -> 가운데 - if (Math.abs(smallRight - holdCellCenterX) < snapDistance) { - tempModule.left = holdCellCenterX - width - intvHor / 2 - } - //설치된 셀에 좌측에 스냅 if (Math.abs(smallRight - holdCellLeft) < snapDistance) { // console.log('모듈 좌측 스냅') @@ -659,21 +659,16 @@ export function useModuleBasicSetting(tabNum) { tempModule.top = holdCellCenterY - toFixedWithoutRounding(width / 2, 2) } - //위쪽 -> 가운데 - if (Math.abs(smallTop - holdCellCenterY) < snapDistance) { - // console.log('holdCellCenterX', holdCellCenterX) - // console.log('smallLeft', smallLeft) - - // console.log('모듈 센터에 스냅') - tempModule.top = holdCellCenterY + intvHor / 2 - - // console.log('tempModule.left', tempModule.left) + if (isChidori) { + //위쪽 -> 가운데 + if (Math.abs(smallTop - holdCellCenterY) < snapDistance) { + tempModule.top = holdCellCenterY + intvHor / 2 + } + // 밑 -> 가운데 + if (Math.abs(smallBottom - holdCellCenterY) < snapDistance) { + tempModule.top = holdCellCenterY - height - intvHor / 2 + } } - // 밑 -> 가운데 - if (Math.abs(smallBottom - holdCellCenterY) < snapDistance) { - tempModule.top = holdCellCenterY - height - intvHor / 2 - } - //설치된 셀에 좌측에 스냅 if (Math.abs(smallRight - holdCellLeft) < snapDistance) { // console.log('모듈 좌측 스냅') @@ -881,8 +876,9 @@ export function useModuleBasicSetting(tabNum) { const manualModuleLayoutSetup = (layoutSetupRef) => { const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 - const isChidori = moduleSetupOption.isChidori - const setupLocation = moduleSetupOption.setupLocation + const isChidori = moduleSetupOption.isChidori //치도리 여부 + const setupLocation = moduleSetupOption.setupLocation //모듈 설치 위치 처마, 용마루 + const isMultiModule = checkedModule.length > 1 //멀티 모듈인지 아닌지 여부 if (isManualModuleLayoutSetup) { if (isManualModuleSetup) { @@ -1117,15 +1113,16 @@ export function useModuleBasicSetting(tabNum) { tempModule.left = holdCellCenterX - toFixedWithoutRounding(width / 2, 2) } - //움직이는 모듈왼쪽 -> 가운데 - if (Math.abs(smallLeft - holdCellCenterX) < snapDistance) { - tempModule.left = holdCellCenterX + intvHor / 2 + if (isChidori) { + //움직이는 모듈왼쪽 -> 가운데 + if (Math.abs(smallLeft - holdCellCenterX) < snapDistance) { + tempModule.left = holdCellCenterX + intvHor / 2 + } + // 오른쪽 -> 가운데 + if (Math.abs(smallRight - holdCellCenterX) < snapDistance) { + tempModule.left = holdCellCenterX - width - intvHor / 2 + } } - // 오른쪽 -> 가운데 - if (Math.abs(smallRight - holdCellCenterX) < snapDistance) { - tempModule.left = holdCellCenterX - width - intvHor / 2 - } - //설치된 셀에 좌측에 스냅 if (Math.abs(smallRight - holdCellLeft) < snapDistance) { // console.log('모듈 좌측 스냅') @@ -1159,21 +1156,16 @@ export function useModuleBasicSetting(tabNum) { tempModule.top = holdCellCenterY - toFixedWithoutRounding(width / 2, 2) } - //위쪽 -> 가운데 - if (Math.abs(smallTop - holdCellCenterY) < snapDistance) { - // console.log('holdCellCenterX', holdCellCenterX) - // console.log('smallLeft', smallLeft) - - // console.log('모듈 센터에 스냅') - tempModule.top = holdCellCenterY + intvHor / 2 - - // console.log('tempModule.left', tempModule.left) + if (isChidori) { + //위쪽 -> 가운데 + if (Math.abs(smallTop - holdCellCenterY) < snapDistance) { + tempModule.top = holdCellCenterY + intvHor / 2 + } + // 밑 -> 가운데 + if (Math.abs(smallBottom - holdCellCenterY) < snapDistance) { + tempModule.top = holdCellCenterY - height - intvHor / 2 + } } - // 밑 -> 가운데 - if (Math.abs(smallBottom - holdCellCenterY) < snapDistance) { - tempModule.top = holdCellCenterY - height - intvHor / 2 - } - //설치된 셀에 좌측에 스냅 if (Math.abs(smallRight - holdCellLeft) < snapDistance) { // console.log('모듈 좌측 스냅') @@ -1256,6 +1248,7 @@ export function useModuleBasicSetting(tabNum) { addCanvasMouseEventListener('mouse:up', (e) => { if (!inside) return + if (tempModule) { let startX, startY let installedLastHeightCoord = 0 //마지막으로 설치된 모듈의 좌표 From c704207d2f04dba2ae3bcc3347efe665ef059ec9 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 24 Mar 2025 09:35:21 +0900 Subject: [PATCH 09/35] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83?= =?UTF-8?q?=EC=84=A4=EC=B9=98=20validation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useModuleBasicSetting.js | 28 +++++++++++++++++++++++ src/locales/ja.json | 3 ++- src/locales/ko.json | 3 ++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index c49764c6..29a1237c 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -1249,6 +1249,34 @@ export function useModuleBasicSetting(tabNum) { addCanvasMouseEventListener('mouse:up', (e) => { if (!inside) return + //입력받은 값의 합 + let sumRowCount = layoutSetupRef.reduce((acc, cur) => acc + cur.row, 0) + let sumColCount = layoutSetupRef.reduce((acc, cur) => acc + cur.col, 0) + let maxRow = 0 + let maxCol = trestlePolygon.trestleDetail.moduleMaxCols + + if (checkedModule.length > 1) { + //모듈이 여러개일때 + maxRow = trestlePolygon.trestleDetail.moduleMaxRows + + if (sumRowCount > maxRow || sumColCount > maxCol) { + swalFire({ text: getMessage('module.layout.setup.max.count', [maxRow, maxCol]) }) + return + } + } else { + //모듈이 하나일때는 module에 list를 조회 + const checkModuleId = checkedModule[0].itemId + const targetModuleRows = trestlePolygon.trestleDetail.module.find((item) => item.itemId === checkModuleId).modulemaxRows + const refOption = layoutSetupRef.find((item) => item.moduleId === checkModuleId) + + sumRowCount = refOption.row + + if (sumRowCount > targetModuleRows || sumColCount > maxCol) { + swalFire({ text: getMessage('module.layout.setup.max.count', [targetModuleRows, maxCol]) }) + return + } + } + if (tempModule) { let startX, startY let installedLastHeightCoord = 0 //마지막으로 설치된 모듈의 좌표 diff --git a/src/locales/ja.json b/src/locales/ja.json index 1ae3eadb..618f26c4 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -1041,5 +1041,6 @@ "modal.placement.initial.setting.plan.drawing.only.number": "(※数字は[半角]入力のみ可能です。)", "wall.line.not.found": "外壁がありません", "roof.line.not.found": "屋根形状がありません", - "roof.material.can.not.delete": "割り当てられた配置面があります。" + "roof.material.can.not.delete": "割り当てられた配置面があります。", + "module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다. (JA)" } diff --git a/src/locales/ko.json b/src/locales/ko.json index cea4d87e..4e2a5589 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -1041,5 +1041,6 @@ "modal.placement.initial.setting.plan.drawing.only.number": "(※ 숫자는 [반각]입력만 가능합니다.)", "wall.line.not.found": "외벽선이 없습니다.", "roof.line.not.found": "지붕형상이 없습니다.", - "roof.material.can.not.delete": "할당된 배치면이 있습니다." + "roof.material.can.not.delete": "할당된 배치면이 있습니다.", + "module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다." } From 943fd16e4bda5c316cd231df71e371f86557f84e Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 24 Mar 2025 10:23:35 +0900 Subject: [PATCH 10/35] =?UTF-8?q?=ED=81=B4=EB=A6=AD=EC=8B=9C=20=EB=B0=B0?= =?UTF-8?q?=EC=B9=98=EB=A9=B4=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20validation?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/basic/BasicSetting.jsx | 1 + src/hooks/module/useModuleBasicSetting.js | 32 +++++++------------ 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index a3f0f08e..7edbb05e 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -168,6 +168,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { useEffect(() => { setIsManualModuleSetup(false) setIsManualModuleLayoutSetup(false) + setManualSetupMode(`off`) }, [checkedModules]) return ( diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 29a1237c..3d0b35df 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -1250,31 +1250,21 @@ export function useModuleBasicSetting(tabNum) { if (!inside) return //입력받은 값의 합 - let sumRowCount = layoutSetupRef.reduce((acc, cur) => acc + cur.row, 0) + let sumColCount = layoutSetupRef.reduce((acc, cur) => acc + cur.col, 0) - let maxRow = 0 - let maxCol = trestlePolygon.trestleDetail.moduleMaxCols - if (checkedModule.length > 1) { - //모듈이 여러개일때 - maxRow = trestlePolygon.trestleDetail.moduleMaxRows + const isMultipleModules = checkedModule.length > 1 + const maxRow = isMultipleModules + ? trestlePolygon.trestleDetail.moduleMaxRows + : trestlePolygon.trestleDetail.module.find((item) => item.moduleTpCd === checkedModule[0].moduleTpCd).moduleMaxRows - if (sumRowCount > maxRow || sumColCount > maxCol) { - swalFire({ text: getMessage('module.layout.setup.max.count', [maxRow, maxCol]) }) - return - } - } else { - //모듈이 하나일때는 module에 list를 조회 - const checkModuleId = checkedModule[0].itemId - const targetModuleRows = trestlePolygon.trestleDetail.module.find((item) => item.itemId === checkModuleId).modulemaxRows - const refOption = layoutSetupRef.find((item) => item.moduleId === checkModuleId) + const sumRowCount = isMultipleModules + ? layoutSetupRef.reduce((acc, cur) => acc + cur.row, 0) + : layoutSetupRef.find((item) => item.moduleId === checkedModule[0].itemId).row - sumRowCount = refOption.row - - if (sumRowCount > targetModuleRows || sumColCount > maxCol) { - swalFire({ text: getMessage('module.layout.setup.max.count', [targetModuleRows, maxCol]) }) - return - } + if (sumRowCount > maxRow || sumColCount > trestlePolygon.trestleDetail.moduleMaxCols) { + swalFire({ text: getMessage('module.layout.setup.max.count', [maxRow, trestlePolygon.trestleDetail.moduleMaxCols]) }) + return } if (tempModule) { From dc8f033e9f99c4e36a80f768dafd96803ef10750 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 24 Mar 2025 10:49:56 +0900 Subject: [PATCH 11/35] =?UTF-8?q?validation=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useModuleBasicSetting.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 3d0b35df..abfb19ca 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -1250,20 +1250,19 @@ export function useModuleBasicSetting(tabNum) { if (!inside) return //입력받은 값의 합 - - let sumColCount = layoutSetupRef.reduce((acc, cur) => acc + cur.col, 0) - - const isMultipleModules = checkedModule.length > 1 + const isMultipleModules = checkedModule.length > 1 //모듈이 여러개면 + const maxCol = trestlePolygon.trestleDetail.moduleMaxCols //최대 열수 -> 얘는 멀티랑 관계없음 const maxRow = isMultipleModules ? trestlePolygon.trestleDetail.moduleMaxRows - : trestlePolygon.trestleDetail.module.find((item) => item.moduleTpCd === checkedModule[0].moduleTpCd).moduleMaxRows + : trestlePolygon.trestleDetail.module.find((item) => item.moduleTpCd === checkedModule[0].moduleTpCd).moduleMaxRows //멀티모듈이면 밖에 maxRows로 판단 아니면 module->itemmList를 가지고 판단 + const sumColCount = layoutSetupRef.reduce((acc, cur) => acc + cur.col, 0) //입력한 행의 합 const sumRowCount = isMultipleModules ? layoutSetupRef.reduce((acc, cur) => acc + cur.row, 0) - : layoutSetupRef.find((item) => item.moduleId === checkedModule[0].itemId).row + : layoutSetupRef.find((item) => item.moduleId === checkedModule[0].itemId).row //멀티모듈이면 전체 합, 체크된 한개의 열 - if (sumRowCount > maxRow || sumColCount > trestlePolygon.trestleDetail.moduleMaxCols) { - swalFire({ text: getMessage('module.layout.setup.max.count', [maxRow, trestlePolygon.trestleDetail.moduleMaxCols]) }) + if (sumRowCount > maxRow || sumColCount > maxCol) { + swalFire({ text: getMessage('module.layout.setup.max.count', [maxRow, maxCol]) }) return } From 0ec917b09f5a34df52b9ddd40a6469189359da79 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 24 Mar 2025 14:07:14 +0900 Subject: [PATCH 12/35] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=96=B4=20=ED=8C=9D?= =?UTF-8?q?=EC=97=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useModuleBasicSetting.js | 47 ++++++++++++----------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index abfb19ca..bb0b42c6 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -878,7 +878,6 @@ export function useModuleBasicSetting(tabNum) { const isChidori = moduleSetupOption.isChidori //치도리 여부 const setupLocation = moduleSetupOption.setupLocation //모듈 설치 위치 처마, 용마루 - const isMultiModule = checkedModule.length > 1 //멀티 모듈인지 아닌지 여부 if (isManualModuleLayoutSetup) { if (isManualModuleSetup) { @@ -943,8 +942,8 @@ export function useModuleBasicSetting(tabNum) { } if (moduleSetupSurfaces.length !== 0) { - // const col = layoutSetupRef.current[0].col - // const row = layoutSetupRef.current[0].row + // const col = layoutSetupRef.reduce((acc, cur) => acc + cur.col, 0) + // const row = layoutSetupRef.reduce((acc, cur) => acc + cur.row, 0) let tempModule let manualDrawModules = [] @@ -991,9 +990,30 @@ export function useModuleBasicSetting(tabNum) { ? moduleSetupSurfaces[i].trestleDetail.moduleIntvlVer / 10 : moduleSetupSurfaces[i].trestleDetail.moduleIntvlHor / 10 + //큰버전용 계산 // let calcHalfWidth = (Number((width * col).toFixed(1)) + Number((intvHor * (col - 1)).toFixed(1))) / 2 // let calcHalfHeight = (Number((height * row).toFixed(1)) + Number((intvVer * (row - 1)).toFixed(1))) / 2 + //작은버전용 + const points = [ + { + x: toFixedWithoutRounding(mousePoint.x, 2) + toFixedWithoutRounding(width / 2, 2), + y: toFixedWithoutRounding(mousePoint.y, 2) - toFixedWithoutRounding(height / 2, 2), + }, + { + x: toFixedWithoutRounding(mousePoint.x, 2) + toFixedWithoutRounding(width / 2, 2), + y: toFixedWithoutRounding(mousePoint.y, 2) + toFixedWithoutRounding(height / 2, 2), + }, + { + x: toFixedWithoutRounding(mousePoint.x, 2) - toFixedWithoutRounding(width / 2, 2), + y: toFixedWithoutRounding(mousePoint.y, 2) - toFixedWithoutRounding(height / 2, 2), + }, + { + x: toFixedWithoutRounding(mousePoint.x, 2) - toFixedWithoutRounding(width / 2, 2), + y: toFixedWithoutRounding(mousePoint.y, 2) + toFixedWithoutRounding(height / 2, 2), + }, + ] + //아래래 // let points = [ // { @@ -1014,25 +1034,6 @@ export function useModuleBasicSetting(tabNum) { // }, // ] - const points = [ - { - x: toFixedWithoutRounding(mousePoint.x, 2) + toFixedWithoutRounding(width / 2, 2), - y: toFixedWithoutRounding(mousePoint.y, 2) - toFixedWithoutRounding(height / 2, 2), - }, - { - x: toFixedWithoutRounding(mousePoint.x, 2) + toFixedWithoutRounding(width / 2, 2), - y: toFixedWithoutRounding(mousePoint.y, 2) + toFixedWithoutRounding(height / 2, 2), - }, - { - x: toFixedWithoutRounding(mousePoint.x, 2) - toFixedWithoutRounding(width / 2, 2), - y: toFixedWithoutRounding(mousePoint.y, 2) - toFixedWithoutRounding(height / 2, 2), - }, - { - x: toFixedWithoutRounding(mousePoint.x, 2) - toFixedWithoutRounding(width / 2, 2), - y: toFixedWithoutRounding(mousePoint.y, 2) + toFixedWithoutRounding(height / 2, 2), - }, - ] - const turfPoints = coordToTurfPolygon(points) if (turf.booleanWithin(turfPoints, turfPolygon)) { @@ -1050,7 +1051,7 @@ export function useModuleBasicSetting(tabNum) { height: toFixedWithoutRounding(height, 2), //작은버전 left: toFixedWithoutRounding(mousePoint.x, 2) - toFixedWithoutRounding(width / 2, 2), //작은버전 top: toFixedWithoutRounding(mousePoint.y, 2) - toFixedWithoutRounding(height / 2, 2), //작은버전 - // // width: Number((width * col).toFixed(1)) + Number((intvHor * (col - 1)).toFixed(1)), //큰버전 + // width: Number((width * col).toFixed(1)) + Number((intvHor * (col - 1)).toFixed(1)), //큰버전 // height: Number((height * row).toFixed(1)) + Number((intvVer * (row - 1)).toFixed(1)), //큰버전 // left: Number(mousePoint.x.toFixed(1)) - calcHalfWidth.toFixed(1), //큰버전 // top: Number(mousePoint.y.toFixed(1)) - calcHalfHeight.toFixed(1), //큰버전 From c631c6344efd5f4e5628afa202ad68c73b19efcd Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 24 Mar 2025 17:07:19 +0900 Subject: [PATCH 13/35] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EC=84=A4=EC=B9=98=20=EC=9E=91=EC=97=85=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useModuleBasicSetting.js | 35 ++--------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index bb0b42c6..1da528a2 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -1251,6 +1251,7 @@ export function useModuleBasicSetting(tabNum) { if (!inside) return //입력받은 값의 합 + //지붕재+공법에 따라 최대 모듈 갯수가 달라지므로 클릭시점에 validate 체크해야함 const isMultipleModules = checkedModule.length > 1 //모듈이 여러개면 const maxCol = trestlePolygon.trestleDetail.moduleMaxCols //최대 열수 -> 얘는 멀티랑 관계없음 const maxRow = isMultipleModules @@ -1759,8 +1760,6 @@ export function useModuleBasicSetting(tabNum) { name: 'module', } - let leftMargin, bottomMargin, square, chidoriLength - //선택된 지붕안에 오브젝트(도머, 개구등)이 있는지 확인하는 로직 포함되면 배열 반환 const objectsIncludeSurface = (turfModuleSetupSurface) => { let containsBatchObjects = [] @@ -1777,36 +1776,6 @@ export function useModuleBasicSetting(tabNum) { return containsBatchObjects } - // /** - // * 도머나 개구가 모듈에 걸치는지 확인하는 로직 - // * @param {*} squarePolygon - // * @param {*} containsBatchObjects - // * @returns - // */ - // const checkModuleDisjointObjects = (squarePolygon, containsBatchObjects) => { - // let isDisjoint = false - // - // if (containsBatchObjects.length > 0) { - // let convertBatchObject - // //도머가 있으면 적용되는 로직 - // isDisjoint = containsBatchObjects.every((batchObject) => { - // if (batchObject.type === 'group') { - // convertBatchObject = batchObjectGroupToTurfPolygon(batchObject) - // } else { - // convertBatchObject = polygonToTurfPolygon(batchObject) - // } - // /** - // * 도머가 여러개일수있으므로 겹치는게 있다면... - // * 안겹치는지 확인하는 로직이라 안겹치면 true를 반환 - // */ - // return turf.booleanDisjoint(squarePolygon, convertBatchObject) - // }) - // } else { - // isDisjoint = true - // } - // return isDisjoint - // } - /** * 배치면 안에 있는지 확인 * @param {*} squarePolygon @@ -1841,7 +1810,7 @@ export function useModuleBasicSetting(tabNum) { checkedModule.forEach((module, moduleIndex) => { const tmpModuleData = trestleDetailData.module.filter((moduleObj) => module.moduleTpCd === moduleObj.moduleTpCd)[0] //혼합모듈일때는 mixModuleMaxRows 값이 0 이상임 - let moduleMaxRows = tmpModuleData.mixModuleMaxRows === 0 ? tmpModuleData.moduleMaxRows : tmpModuleData.mixModuleMaxRows + // let moduleMaxRows = tmpModuleData.mixModuleMaxRows === 0 ? tmpModuleData.moduleMaxRows : tmpModuleData.mixModuleMaxRows //모듈의 넓이 높이를 가져옴 (복시도 촌수 적용) //1번 깔았던 모듈 기준으로 잡야아함 From 5597f8ad70dbbaeeffc8a16c216df6a04fb83159 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Tue, 25 Mar 2025 15:48:18 +0900 Subject: [PATCH 14/35] =?UTF-8?q?=EC=A7=80=EB=B6=95=EB=9D=BC=EC=9D=B8=20?= =?UTF-8?q?=EC=83=89=EC=B9=A0=ED=95=98=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useModuleBasicSetting.js | 30 ++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 1da528a2..277ec492 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -81,6 +81,14 @@ export function useModuleBasicSetting(tabNum) { removeMouseEvent('mouse:up') removeMouseEvent('mouse:move') canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) //움직일때 일단 지워가면서 움직임 + canvas.getObjects().forEach((obj) => { + if (obj.name === POLYGON_TYPE.ROOF) { + obj.set({ + stroke: 'black', + strokeWidth: 3, + }) + } + }) } }, []) @@ -147,11 +155,10 @@ export function useModuleBasicSetting(tabNum) { //가대 상세 데이터 들어오면 실행 useEffect(() => { if (trestleDetailList.length > 0) { - console.log('trestleDetailList', trestleDetailList) //지붕을 가져옴 canvas .getObjects() - .filter((roof) => roof.name === 'roof') + .filter((roof) => roof.name === POLYGON_TYPE.ROOF) .forEach((roof) => { if (!roof.roofMaterial) return const roofIndex = roof.roofMaterial.index //지붕의 지붕재의 순번 @@ -159,7 +166,12 @@ export function useModuleBasicSetting(tabNum) { if (detail.data !== null) { if (Number(detail.data.roofIndex) === roofIndex) { //roof에 상세 데이터 추가 - roof.set({ trestleDetail: detail.data }) + + roof.set({ + trestleDetail: detail.data, + stroke: roofOutlineColor(roofIndex), + strokeWidth: 7, + }) roof.lines.forEach((line) => { line.attributes = { ...line.attributes, @@ -176,6 +188,18 @@ export function useModuleBasicSetting(tabNum) { } }, [trestleDetailList]) + const roofOutlineColor = (roofIndex) => { + if (roofIndex === 1) { + return 'rgb(86,170,255)' + } else if (roofIndex === 2) { + return 'rgb(125, 252, 173)' + } else if (roofIndex === 3) { + return 'rgb(238, 109, 255)' + } else { + return 'rgb(252, 148, 106)' + } + } + const getOffset = (data, type) => { switch (type) { case LINE_TYPE.WALLLINE.EAVES: From 63d8ae092c5e43d7083b60805441c3c6d327d4c5 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Thu, 27 Mar 2025 14:11:23 +0900 Subject: [PATCH 15/35] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EC=84=A4=EC=B9=98=20validate=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useModuleBasicSetting.js | 30 ++++++++++++++++++++--- src/locales/ja.json | 3 ++- src/locales/ko.json | 3 ++- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 277ec492..646c743f 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -81,7 +81,7 @@ export function useModuleBasicSetting(tabNum) { removeMouseEvent('mouse:up') removeMouseEvent('mouse:move') canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) //움직일때 일단 지워가면서 움직임 - canvas.getObjects().forEach((obj) => { + canvas?.getObjects().forEach((obj) => { if (obj.name === POLYGON_TYPE.ROOF) { obj.set({ stroke: 'black', @@ -1282,13 +1282,35 @@ export function useModuleBasicSetting(tabNum) { ? trestlePolygon.trestleDetail.moduleMaxRows : trestlePolygon.trestleDetail.module.find((item) => item.moduleTpCd === checkedModule[0].moduleTpCd).moduleMaxRows //멀티모듈이면 밖에 maxRows로 판단 아니면 module->itemmList를 가지고 판단 - const sumColCount = layoutSetupRef.reduce((acc, cur) => acc + cur.col, 0) //입력한 행의 합 + //단수 합단수 const sumRowCount = isMultipleModules ? layoutSetupRef.reduce((acc, cur) => acc + cur.row, 0) : layoutSetupRef.find((item) => item.moduleId === checkedModule[0].itemId).row //멀티모듈이면 전체 합, 체크된 한개의 열 - if (sumRowCount > maxRow || sumColCount > maxCol) { - swalFire({ text: getMessage('module.layout.setup.max.count', [maxRow, maxCol]) }) + // + const sumColCount = layoutSetupRef.filter((item) => item.col).some((item) => item.col > maxCol) + + if (sumRowCount > maxRow || sumColCount) { + swalFire({ text: getMessage('module.layout.setup.max.count', [maxRow, maxCol]), icon: 'warning' }) + return + } + + let alertMessage = '' + let isPassed = true + if (isMultipleModules) { + layoutSetupRef.forEach((item, index) => { + const moduleInfo = trestlePolygon.trestleDetail.module[index] + if (item.row > moduleInfo.mixModuleMaxRows) { + alertMessage = getMessage('module.layout.setup.max.count.multiple', [index + 1, moduleInfo.mixModuleMaxRows, maxCol]) + isPassed = false + } + }) + } + + console.log(alertMessage) + + if (!isPassed) { + swalFire({ text: alertMessage, icon: 'warning' }) return } diff --git a/src/locales/ja.json b/src/locales/ja.json index 9ca0466a..c8d080de 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -1043,5 +1043,6 @@ "roof.line.not.found": "屋根形状がありません", "roof.material.can.not.delete": "割り当てられた配置面があります。", "module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다. (JA)", - "chidory.can.not.install": "千鳥配置できない工法です。" + "chidory.can.not.install": "千鳥配置できない工法です。", + "module.layout.setup.max.count.multiple": "모듈 {0}번의 최대 단수는 {1}, 최대 열수는 {2} 입니다. (JA)" } diff --git a/src/locales/ko.json b/src/locales/ko.json index f61ea784..6cd3cfb6 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -1043,5 +1043,6 @@ "roof.line.not.found": "지붕형상이 없습니다.", "roof.material.can.not.delete": "할당된 배치면이 있습니다.", "module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다.", - "chidory.can.not.install": "치조 불가 공법입니다." + "chidory.can.not.install": "치조 불가 공법입니다.", + "module.layout.setup.max.count.multiple": "모듈 {0}번의 최대 단수는 {1}, 최대 열수는 {2} 입니다." } From 2bb1b71a0bad709fdd2f4fdf871d501f84b19874 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Fri, 28 Mar 2025 09:40:19 +0900 Subject: [PATCH 16/35] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EC=84=A4=EC=B9=98=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useModuleBasicSetting.js | 84 ++++++----------------- 1 file changed, 21 insertions(+), 63 deletions(-) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 646c743f..a196d798 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -275,7 +275,6 @@ export function useModuleBasicSetting(tabNum) { setSurfaceShapePattern(roof, roofDisplay.column, true, roof.roofMaterial) //패턴 변경 // let offsetPoints = createPaddingPolygon(createRoofPolygon(roof.points), roof.lines).vertices //안쪽 offset let offsetPoints = null - console.log(roof, roof.getCurrentPoints()) const polygon = createRoofPolygon(roof.getCurrentPoints()) const originPolygon = new QPolygon(roof.getCurrentPoints(), { fontSize: 0 }) @@ -400,7 +399,7 @@ export function useModuleBasicSetting(tabNum) { canvas?.renderAll() selectedModuleInstSurfaceArray.push(setupSurface) - setCurrentObject({ name: 'moduleSetupSurface', arrayData: [...selectedModuleInstSurfaceArray] }) + setCurrentObject({ name: POLYGON_TYPE.MODULE_SETUP_SURFACE, arrayData: [...selectedModuleInstSurfaceArray] }) } else { //선택후 재선택하면 선택안됨으로 변경 setupSurface.set({ @@ -415,7 +414,7 @@ export function useModuleBasicSetting(tabNum) { const removeIndex = setupSurface.parentId const removeArrayIndex = selectedModuleInstSurfaceArray.findIndex((obj) => obj.parentId === removeIndex) selectedModuleInstSurfaceArray.splice(removeArrayIndex, 1) - setCurrentObject({ name: 'moduleSetupSurface', arrayData: [...selectedModuleInstSurfaceArray] }) + setCurrentObject({ name: POLYGON_TYPE.MODULE_SETUP_SURFACE, arrayData: [...selectedModuleInstSurfaceArray] }) } canvas?.renderAll() @@ -1295,22 +1294,19 @@ export function useModuleBasicSetting(tabNum) { return } - let alertMessage = '' - let isPassed = true - if (isMultipleModules) { - layoutSetupRef.forEach((item, index) => { - const moduleInfo = trestlePolygon.trestleDetail.module[index] - if (item.row > moduleInfo.mixModuleMaxRows) { - alertMessage = getMessage('module.layout.setup.max.count.multiple', [index + 1, moduleInfo.mixModuleMaxRows, maxCol]) - isPassed = false - } + // 혼합일때 모듈 개별의 row를 체크함 + const isPassedObject = + isMultipleModules && layoutSetupRef.find((item, index) => item.row > trestlePolygon.trestleDetail.module[index].mixModuleMaxRows) + + if (isPassedObject) { + swalFire({ + text: getMessage('module.layout.setup.max.count.multiple', [ + layoutSetupRef.indexOf(isPassedObject) + 1, + trestlePolygon.trestleDetail.module[layoutSetupRef.indexOf(isPassedObject)].mixModuleMaxRows, + maxCol, + ]), + icon: 'warning', }) - } - - console.log(alertMessage) - - if (!isPassed) { - swalFire({ text: alertMessage, icon: 'warning' }) return } @@ -1340,6 +1336,7 @@ export function useModuleBasicSetting(tabNum) { //그려진 가이드 라인의 포인트를 기준으로 시작점을 만든다 //남쪽에 처마방향이나 북쪽에 용마루면 + //tempModule에 좌,하 좌표를 기준으로 우측으로 위로 그림 if ((flowDirection === 'south' && setupLocation === 'eaves') || (flowDirection === 'north' && setupLocation === 'ridge')) { //남 startX = toFixedWithoutRounding(tempModule.left, 1) @@ -1438,6 +1435,7 @@ export function useModuleBasicSetting(tabNum) { } } //북쪽에 처마거나 남쪽에 용마루일경우 + //tempModule에 우,상 좌표를 기준으로 좌측으로 아래로 그림 } else if ((flowDirection === 'north' && setupLocation === 'eaves') || (flowDirection === 'south' && setupLocation === 'ridge')) { //북북 startX = toFixedWithoutRounding(tempModule.left + tempModule.width, 1) @@ -1531,6 +1529,7 @@ export function useModuleBasicSetting(tabNum) { } } //서쪽에 처마 또는 동쪽의 용마루일경우 + //tempModule에 좌,상 좌표를 기준으로 아래로 좌측으로 그림 } else if ((flowDirection === 'west' && setupLocation === 'eaves') || (flowDirection === 'east' && setupLocation === 'ridge')) { startX = toFixedWithoutRounding(tempModule.left, 1) startY = toFixedWithoutRounding(tempModule.top, 1) @@ -1623,6 +1622,7 @@ export function useModuleBasicSetting(tabNum) { } } //동쪽의 처마 또는 서쪽의 용마루일경우 + //tempModule에 우,하 좌표를 기준으로 위로 우측으로 그림 } else if ((flowDirection === 'east' && setupLocation === 'eaves') || (flowDirection === 'west' && setupLocation === 'ridge')) { startX = toFixedWithoutRounding(tempModule.left + width, 1) startY = toFixedWithoutRounding(tempModule.top + height, 1) @@ -1715,6 +1715,7 @@ export function useModuleBasicSetting(tabNum) { } } }) + //그림자가 있다면 무조건 그림자를 가장 앞으로 올림 const shadowObj = canvas?.getObjects().find((obj) => obj.name === BATCH_TYPE.SHADOW) if (shadowObj) { shadowObj.bringToFront() @@ -1751,7 +1752,6 @@ export function useModuleBasicSetting(tabNum) { const isChidori = moduleSetupOption.isChidori const setupLocation = moduleSetupOption.setupLocation const isMaxSetup = false - // const isMaxSetup = placementRef.isMaxSetup.current === 'true' ? true : false const moduleSetupSurfaces = moduleSetupSurface //선택 설치면 const notSelectedTrestlePolygons = canvas @@ -1767,24 +1767,11 @@ export function useModuleBasicSetting(tabNum) { //어짜피 자동으로 누르면 선택안된데도 다 날아간다 canvas.getObjects().forEach((obj) => { - if (obj.name === 'module') { + if (obj.name === POLYGON_TYPE.MODULE) { canvas.remove(obj) } }) - // if (moduleIsSetup.length > 0) { - // swalFire({ text: 'alert 아이콘 테스트입니다.', icon: 'error' }) - // } - - // moduleSetupSurfaces.forEach((obj) => { - // if (obj.modules) { - // obj.modules.forEach((module) => { - // canvas?.remove(module) - // }) - // obj.modules = [] - // } - // }) - notSelectedTrestlePolygons.forEach((obj) => { if (obj.modules) { obj.modules.forEach((module) => { @@ -1803,7 +1790,7 @@ export function useModuleBasicSetting(tabNum) { lockRotation: true, // 회전 잠금 lockScalingX: true, // X 축 크기 조정 잠금 lockScalingY: true, // Y 축 크기 조정 잠금 - name: 'module', + name: POLYGON_TYPE.MODULE, } //선택된 지붕안에 오브젝트(도머, 개구등)이 있는지 확인하는 로직 포함되면 배열 반환 @@ -2437,37 +2424,8 @@ export function useModuleBasicSetting(tabNum) { if (moduleSetupSurface.direction === 'north') { downFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, false, intvHor, intvVer) } - } else if (setupLocation === 'center') { - //중가면 - if (moduleSetupSurface.direction === 'south') { - downFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true, intvHor, intvVer) - } - if (moduleSetupSurface.direction === 'west') { - leftFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true, intvHor, intvVer) - } - if (moduleSetupSurface.direction === 'east') { - rightFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true, intvHor, intvVer) - } - if (moduleSetupSurface.direction === 'north') { - topFlowSetupModule(surfaceMaxLines, maxLengthLine, moduleSetupArray, moduleSetupSurface, containsBatchObjects, true, intvHor, intvVer) - } } - // const setupedModules = moduleSetupArray.filter((module, index) => { - // let disjointFromTrestle = checkModuleDisjointSurface(module.turfPoints, turfModuleSetupSurface) - // let isDisjoint = checkModuleDisjointObjects(module.turfPoints, containsBatchObjects) - - // if (!(disjointFromTrestle && isDisjoint)) { - // canvas?.remove(module) - // // module.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) - // return false - // } else { - // return module - // } - // }) - - // canvas?.renderAll() - //나간애들 제외하고 설치된 애들로 겹친애들 삭제 하기 moduleSetupArray.forEach((module, index) => { if (isMaxSetup && index > 0) { From 482b6b54777142e39c4d753ca06b9acdf81b0d57 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 31 Mar 2025 10:20:45 +0900 Subject: [PATCH 17/35] =?UTF-8?q?=EC=88=98=EB=8F=99=20=EC=84=A4=EC=B9=98?= =?UTF-8?q?=20=ED=98=BC=ED=95=A9=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=20=EC=84=A4?= =?UTF-8?q?=EC=B9=98=20=EC=97=AC=EB=B6=80=20=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useModuleBasicSetting.js | 15 +++++++++++++-- src/locales/ja.json | 3 ++- src/locales/ko.json | 3 ++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index a196d798..8065df04 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -457,9 +457,8 @@ export function useModuleBasicSetting(tabNum) { * trestle에서 영역을 가져와 mouse:move 이벤트로 해당 영역에 진입했을때 booleanPointInPolygon 로 진입여부를 확인 * 확인 후 셀을 이동시킴 */ - const manualModuleSetup = (placementRef) => { + const manualModuleSetup = () => { //레이아웃 수동설치 토글 - const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴 const isChidori = moduleSetupOption.isChidori @@ -800,6 +799,18 @@ export function useModuleBasicSetting(tabNum) { addCanvasMouseEventListener('mouse:up', (e) => { let isIntersection = true + + // 혼합 설치 불가능한 모듈인지 확인 Y는 Y끼리 N은 N끼리만 설치 가능 + if (trestlePolygon.modules.length > 0) { + //이미 설치된 모듈중에 한개만 가져옴 + const mixAsgYn = trestlePolygon.modules[0].moduleInfo.mixAsgYn + //현재 체크된 모듈기준으로 혼합가능인지 확인 Y === Y, N === N 일때만 설치 가능 + if (checkedModule[0].mixAsgYn !== mixAsgYn) { + swalFire({ text: getMessage('module.place.mix.asg.yn.error') }) + return + } + } + if (!inside) return if (tempModule) { const rectPoints = [ diff --git a/src/locales/ja.json b/src/locales/ja.json index c8d080de..718aeb8e 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -1044,5 +1044,6 @@ "roof.material.can.not.delete": "割り当てられた配置面があります。", "module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다. (JA)", "chidory.can.not.install": "千鳥配置できない工法です。", - "module.layout.setup.max.count.multiple": "모듈 {0}번의 최대 단수는 {1}, 최대 열수는 {2} 입니다. (JA)" + "module.layout.setup.max.count.multiple": "모듈 {0}번의 최대 단수는 {1}, 최대 열수는 {2} 입니다. (JA)", + "module.place.mix.asg.yn.error": "혼합 설치가 불가능합니다. (JA)" } diff --git a/src/locales/ko.json b/src/locales/ko.json index 6cd3cfb6..9ff2ecec 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -1044,5 +1044,6 @@ "roof.material.can.not.delete": "할당된 배치면이 있습니다.", "module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다.", "chidory.can.not.install": "치조 불가 공법입니다.", - "module.layout.setup.max.count.multiple": "모듈 {0}번의 최대 단수는 {1}, 최대 열수는 {2} 입니다." + "module.layout.setup.max.count.multiple": "모듈 {0}번의 최대 단수는 {1}, 최대 열수는 {2} 입니다.", + "module.place.mix.asg.yn.error": "혼합 설치가 불가능합니다." } From 826739fb0ea539a86f39fe8c9db3fda199c97c8a Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 31 Mar 2025 10:44:56 +0900 Subject: [PATCH 18/35] =?UTF-8?q?=ED=98=BC=ED=95=A9=20=EA=B0=80=EB=8A=A5?= =?UTF-8?q?=20=EC=97=AC=EB=B6=80=20=ED=99=95=EC=9D=B8=20validate=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useModuleBasicSetting.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 8065df04..d9b573c5 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -1760,6 +1760,16 @@ export function useModuleBasicSetting(tabNum) { return } + //혼합 가능 모듈과 혼합 불가능 모듈을 선택했을때 카운트를 해서 확인 + const mixAsgY = checkedModule.filter((obj) => obj.mixAsgYn === 'Y') + const mixAsgN = checkedModule.filter((obj) => obj.mixAsgYn === 'N') + + //Y인 모듈과 N인 모듈이 둘다 존재하면 설치 불가 + if (mixAsgY.length > 0 && mixAsgN.length > 0) { + swalFire({ text: getMessage('module.place.mix.asg.yn.error') }) + return + } + const isChidori = moduleSetupOption.isChidori const setupLocation = moduleSetupOption.setupLocation const isMaxSetup = false From 7d37deb048c1b88047b3786a943359dd7a2c46ca Mon Sep 17 00:00:00 2001 From: yjnoh Date: Tue, 1 Apr 2025 15:31:12 +0900 Subject: [PATCH 19/35] =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EC=84=A4=EC=B9=98?= =?UTF-8?q?=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/basic/BasicSetting.jsx | 2 +- .../floor-plan/modal/basic/step/Placement.jsx | 295 +++++++++++------- src/hooks/module/useModuleBasicSetting.js | 15 +- src/locales/ja.json | 11 +- src/locales/ko.json | 7 +- 5 files changed, 210 insertions(+), 120 deletions(-) diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index 7edbb05e..ae99c73b 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -172,7 +172,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { }, [checkedModules]) return ( - + handleClosePopup(id)} />
diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx index ab1782bf..16c06ab2 100644 --- a/src/components/floor-plan/modal/basic/step/Placement.jsx +++ b/src/components/floor-plan/modal/basic/step/Placement.jsx @@ -8,12 +8,13 @@ import { moduleSetupOptionState, toggleManualSetupModeState, } from '@/store/canvasAtom' -import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' +import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil' import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions' import { isObjectNotEmpty } from '@/util/common-utils' const Placement = forwardRef((props, refs) => { const { getMessage } = useMessage() + const [useTab, setUseTab] = useState(true) const [isChidoriNotAble, setIsChidoriNotAble] = useState(false) @@ -22,7 +23,7 @@ const Placement = forwardRef((props, refs) => { const setCheckedModules = useSetRecoilState(checkedModuleState) const moduleSelectionData = useRecoilValue(moduleSelectionDataState) - const { makeModuleInitArea } = useModuleBasicSetting(3) + const { makeModuleInitArea, roofOutlineColor } = useModuleBasicSetting(3) const [isMultiModule, setIsMultiModule] = useState(false) @@ -32,6 +33,9 @@ const Placement = forwardRef((props, refs) => { const setManualSetupMode = useSetRecoilState(toggleManualSetupModeState) const [moduleSetupOption, setModuleSetupOption] = useRecoilState(moduleSetupOptionState) //모듈 설치 옵션 + const resetModuleSetupOption = useResetRecoilState(moduleSetupOptionState) + + const [colspan, setColspan] = useState(1) //모듈 배치면 생성 useEffect(() => { @@ -44,17 +48,24 @@ const Placement = forwardRef((props, refs) => { makeModuleInitArea(moduleSelectionData) } + if (moduleSelectionData.module.itemList.length > 1) { + setColspan(2) + } + return () => { - refs.isChidori.current = 'false' - refs.setupLocation.current = 'eaves' + // refs.isChidori.current = 'false' + // refs.setupLocation.current = 'eaves' setIsManualModuleSetup(false) setIsManualModuleLayoutSetup(false) setManualSetupMode('off') + resetModuleSetupOption() } }, []) //최초 지입시 체크 useEffect(() => { + console.log('moduleSelectionData', moduleSelectionData) + if (isObjectNotEmpty(moduleSelectionData)) { //두번째 선택한 데이터가를 기반으로 세번째 선택을 체크한다 if (moduleSelectionData.roofConstructions.length > 0 && moduleSelectionData.module.itemList.length > 0) { @@ -93,7 +104,9 @@ const Placement = forwardRef((props, refs) => { header: [ { type: 'check', name: '', prop: 'check', width: 70 }, { type: 'color-box', name: getMessage('module'), prop: 'module' }, - { type: 'text', name: `${getMessage('output')} (W)`, prop: 'output', width: 70 }, + { type: 'text', name: getMessage('modal.module.basic.setting.module.placement.mix.asg.yn'), prop: 'mixAsgYn', width: 50 }, + { type: 'text', name: `単数`, prop: 'rows', width: 60 }, + { type: 'text', name: `熱水`, prop: 'cols', width: 60 }, ], rows: [], } @@ -130,26 +143,24 @@ const Placement = forwardRef((props, refs) => { return ( <> -
+
- - {moduleData.header.map((data) => ( - - ))} - + {moduleData.header.map((data) => ( + + ))} {selectedModules.itemList && @@ -173,106 +184,174 @@ const Placement = forwardRef((props, refs) => { {item.itemNm} - - - handleLayoutSetup(e, item.itemId, index)} - />{' '} - × - handleLayoutSetup(e, item.itemId, index)} - /> + + + ))} + + + + + + +
- {data.type === 'check' ? ( -
- - -
- ) : ( - data.name - )} -
+ {data.type === 'check' ? ( +
+ + +
+ ) : ( + data.name + )} +
{item.wpOut} +
+ {item.mixAsgYn} +
+
+
+ handleLayoutSetup(e, item.itemId, index)} + /> +
+
+
+ handleLayoutSetup(e, item.itemId, index)} + /> +
+
-
+
-
{getMessage('modal.module.basic.setting.module.placement.select.fitting.type')}
-
-
-
{getMessage('modal.module.basic.setting.module.placement.waterfowl.arrangement')}
-
-
-
- handleChangeChidori(e)} - /> - -
-
- handleChangeChidori(e)} - /> - -
-
-
-
-
-
{getMessage('modal.module.basic.setting.module.placement.arrangement.standard')}
-
-
-
- - -
-
- - -
-
-
-
-
-
- {/*
- - -
*/} +
+ + + + + + + + + + + + + +
{getMessage('modal.module.basic.setting.module.placement.waterfowl.arrangement')}{getMessage('modal.module.basic.setting.module.placement.arrangement.standard')}
+
+
+ handleChangeChidori(e)} + /> + +
+
+ handleChangeChidori(e)} + /> + +
+
+
+
+
+ + +
+
+ + +
+
+
+
+ {getMessage('modal.module.basic.setting.module.placement.max.size.check')} + +
+
+
+
+ + + + + {selectedModules && + selectedModules.itemList.map((item) => ( + + ))} + + + {selectedModules.itemList.map((item) => ( + <> + + {colspan > 1 && } + + ))} + + + + {moduleSelectionData.roofConstructions.map((item) => ( + + + {selectedModules.itemList.map((item) => ( + <> + + {colspan > 1 && } + + ))} + + ))} + +
+
+ + {item.itemNm} +
+
{getMessage('modal.module.basic.setting.module.placement.max.row')}{getMessage('modal.module.basic.setting.module.placement.max.rows.multiple')}
+
+ + {item.addRoof.roofMatlNmJp} +
+
75
+
+
+
) }) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 2e490a85..417fdeea 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -114,7 +114,7 @@ export function useModuleBasicSetting(tabNum) { //육지붕 일경우에는 바로 배치면 설치LL canvas .getObjects() - .filter((roof) => roof.name === 'roof') + .filter((roof) => roof.name === POLYGON_TYPE.ROOF) .forEach((roof) => { makeModuleInstArea(roof, null) }) @@ -172,13 +172,13 @@ export function useModuleBasicSetting(tabNum) { const roofOutlineColor = (roofIndex) => { if (roofIndex === 1) { - return 'rgb(86,170,255)' + return '#FFC000' } else if (roofIndex === 2) { - return 'rgb(125, 252, 173)' + return '#7030A0' } else if (roofIndex === 3) { - return 'rgb(238, 109, 255)' + return '#385723' } else { - return 'rgb(252, 148, 106)' + return '#FFFF00' } } @@ -775,7 +775,7 @@ export function useModuleBasicSetting(tabNum) { const mixAsgYn = trestlePolygon.modules[0].moduleInfo.mixAsgYn //현재 체크된 모듈기준으로 혼합가능인지 확인 Y === Y, N === N 일때만 설치 가능 if (checkedModule[0].mixAsgYn !== mixAsgYn) { - swalFire({ text: getMessage('module.place.mix.asg.yn.error') }) + swalFire({ text: getMessage('modal.module.basic.setting.module.placement.mix.asg.yn.error') }) return } } @@ -1732,7 +1732,7 @@ export function useModuleBasicSetting(tabNum) { //Y인 모듈과 N인 모듈이 둘다 존재하면 설치 불가 if (mixAsgY.length > 0 && mixAsgN.length > 0) { - swalFire({ text: getMessage('module.place.mix.asg.yn.error') }) + swalFire({ text: getMessage('modal.module.basic.setting.module.placement.mix.asg.yn.error') }) return } @@ -3575,5 +3575,6 @@ export function useModuleBasicSetting(tabNum) { autoFlatroofModuleSetup, checkModuleDisjointObjects, makeModuleInitArea, + roofOutlineColor, } } diff --git a/src/locales/ja.json b/src/locales/ja.json index b8195843..32bc6743 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -116,8 +116,8 @@ "modal.module.basic.setting.module.placement.do.not": "しない", "modal.module.basic.setting.module.placement.arrangement.standard": "配置基準", "modal.module.basic.setting.module.placement.arrangement.standard.center": "中央", - "modal.module.basic.setting.module.placement.arrangement.standard.eaves": "軒", - "modal.module.basic.setting.module.placement.arrangement.standard.ridge": "棟", + "modal.module.basic.setting.module.placement.arrangement.standard.eaves": "軒側", + "modal.module.basic.setting.module.placement.arrangement.standard.ridge": "棟側", "modal.module.basic.setting.module.placement.maximum": "最大配置", "modal.module.basic.setting.pitch.module.placement.standard.setting": "配置基準設定", "modal.module.basic.setting.pitch.module.placement.standard.setting.south": "南向き設置", @@ -1045,5 +1045,10 @@ "chidory.can.not.install": "千鳥配置できない工法です。", "module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다. (JA)", "module.layout.setup.max.count.multiple": "모듈 {0}번의 최대 단수는 {1}, 최대 열수는 {2} 입니다. (JA)", - "roofAllocation.not.found": "할당할 지붕이 없습니다. (JA)" + "roofAllocation.not.found": "할당할 지붕이 없습니다. (JA)", + "modal.module.basic.setting.module.placement.max.size.check": "지붕재별 모듈의 최대 단수. 혼합 최대 단수를 확인하십시오. (JA)", + "modal.module.basic.setting.module.placement.max.row": "최대 단수 (JA)", + "modal.module.basic.setting.module.placement.max.rows.multiple": "혼합 단수 (JA)", + "modal.module.basic.setting.module.placement.mix.asg.yn.error": "혼합 설치 불가능한 모듈입니다. (JA)", + "modal.module.basic.setting.module.placement.mix.asg.yn": "ミックス. (JA)" } diff --git a/src/locales/ko.json b/src/locales/ko.json index 6ea42c9f..d5dcbb07 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -1045,5 +1045,10 @@ "chidory.can.not.install": "치조 불가 공법입니다.", "module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다.", "module.layout.setup.max.count.multiple": "모듈 {0}번의 최대 단수는 {1}, 최대 열수는 {2} 입니다.", - "roofAllocation.not.found": "할당할 지붕이 없습니다." + "roofAllocation.not.found": "할당할 지붕이 없습니다.", + "modal.module.basic.setting.module.placement.max.size.check": "지붕재별 모듈의 최대 단수. 혼합 최대 단수를 확인하십시오.", + "modal.module.basic.setting.module.placement.max.row": "최대 단수", + "modal.module.basic.setting.module.placement.max.rows.multiple": "혼합 단수", + "modal.module.basic.setting.module.placement.mix.asg.yn.error": "혼합 설치 불가능한 모듈입니다.", + "modal.module.basic.setting.module.placement.mix.asg.yn": "혼합" } From 87ef010ae63b0ee8f99023bdb7f30fc255927782 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Tue, 1 Apr 2025 15:40:20 +0900 Subject: [PATCH 20/35] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EB=AC=B8=EA=B5=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/modal/basic/BasicSetting.jsx | 2 +- src/locales/ja.json | 1 + src/locales/ko.json | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index ae99c73b..90ef755c 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -216,7 +216,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { {getMessage('modal.module.basic.setting.passivity.placement')}
diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 417fdeea..bb966f4e 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -892,8 +892,11 @@ export function useModuleBasicSetting(tabNum) { return } + //숫자 0이 하나라도 있으면 설치 불가 const hasZeroLength = checkedModule.some((item) => - layoutSetupRef.some((layoutItem) => item.itemId === layoutItem.moduleId && (layoutItem.row === 0 || layoutItem.col === 0)), + layoutSetupRef.some( + (layoutItem) => layoutItem.checked && item.itemId === layoutItem.moduleId && (layoutItem.row === 0 || layoutItem.col === 0), + ), ) if (hasZeroLength) { @@ -903,6 +906,16 @@ export function useModuleBasicSetting(tabNum) { return } + //혼합 가능 모듈과 혼합 불가능 모듈을 선택했을때 카운트를 해서 확인 + const mixAsgY = checkedModule.filter((obj) => obj.mixAsgYn === 'Y') + const mixAsgN = checkedModule.filter((obj) => obj.mixAsgYn === 'N') + + //Y인 모듈과 N인 모듈이 둘다 존재하면 설치 불가 + if (mixAsgY.length > 0 && mixAsgN.length > 0) { + swalFire({ text: getMessage('modal.module.basic.setting.module.placement.mix.asg.yn.error') }) + return + } + const batchObjects = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.OBJECT_SURFACE) //도머s 객체 //수동모드 모듈 설치면 선택 잠금 moduleSetupSurfaces.forEach((obj) => { @@ -1260,7 +1273,7 @@ export function useModuleBasicSetting(tabNum) { //단수 합단수 const sumRowCount = isMultipleModules - ? layoutSetupRef.reduce((acc, cur) => acc + cur.row, 0) + ? layoutSetupRef.filter((item) => item.checked).reduce((acc, cur) => acc + cur.row, 0) : layoutSetupRef.find((item) => item.moduleId === checkedModule[0].itemId).row //멀티모듈이면 전체 합, 체크된 한개의 열 // @@ -1273,7 +1286,8 @@ export function useModuleBasicSetting(tabNum) { // 혼합일때 모듈 개별의 row를 체크함 const isPassedObject = - isMultipleModules && layoutSetupRef.find((item, index) => item.row > trestlePolygon.trestleDetail.module[index].mixModuleMaxRows) + isMultipleModules && + layoutSetupRef.find((item, index) => item.checked && item.row > trestlePolygon.trestleDetail.module[index].mixModuleMaxRows) if (isPassedObject) { swalFire({ diff --git a/src/locales/ja.json b/src/locales/ja.json index 96dc0dde..509e0d62 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -130,7 +130,6 @@ "modal.module.basic.setting.pitch.module.column.margin": "左右間隔", "modal.module.basic.setting.prev": "前に戻る", "modal.module.basic.setting.passivity.placement": "手動配置", - "modal.module.basic.setting.layoutpassivity.placement": "layout配置", "modal.module.basic.setting.auto.placement": "設定値に自動配置", "plan.menu.module.circuit.setting.circuit.trestle.setting": "回路設定", "modal.circuit.trestle.setting": "回路設定", @@ -1051,5 +1050,6 @@ "modal.module.basic.setting.module.placement.max.row": "최대 단수 (JA)", "modal.module.basic.setting.module.placement.max.rows.multiple": "혼합 단수 (JA)", "modal.module.basic.setting.module.placement.mix.asg.yn.error": "혼합 설치 불가능한 모듈입니다. (JA)", - "modal.module.basic.setting.module.placement.mix.asg.yn": "ミックス. (JA)" + "modal.module.basic.setting.module.placement.mix.asg.yn": "ミックス. (JA)", + "modal.module.basic.setting.layoutpassivity.placement": "layout配置 (JA)" } diff --git a/src/locales/ko.json b/src/locales/ko.json index 4df83b2b..127da1bc 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -130,7 +130,6 @@ "modal.module.basic.setting.pitch.module.column.margin": "좌우간격", "modal.module.basic.setting.prev": "이전", "modal.module.basic.setting.passivity.placement": "수동 배치", - "modal.module.basic.setting.layoutpassivity.placement": "레이아웃 배치", "modal.module.basic.setting.auto.placement": "설정값으로 자동 배치", "plan.menu.module.circuit.setting.circuit.trestle.setting": "회로설정", "modal.circuit.trestle.setting": "회로설정", @@ -1051,5 +1050,6 @@ "modal.module.basic.setting.module.placement.max.row": "최대 단수", "modal.module.basic.setting.module.placement.max.rows.multiple": "혼합 단수", "modal.module.basic.setting.module.placement.mix.asg.yn.error": "혼합 설치 불가능한 모듈입니다.", - "modal.module.basic.setting.module.placement.mix.asg.yn": "혼합" + "modal.module.basic.setting.module.placement.mix.asg.yn": "혼합", + "modal.module.basic.setting.layoutpassivity.placement": "레이아웃 배치" } From 964d9bdcc74b794a5a4626149d52d75442599395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Wed, 2 Apr 2025 13:56:03 +0900 Subject: [PATCH 22/35] =?UTF-8?q?basicsetting=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/basic/BasicSetting.jsx | 224 ++++++-- .../modal/basic/step/Orientation.jsx | 441 ++++++++++++--- .../floor-plan/modal/basic/step/Trestle.jsx | 532 ++++++++++++++++++ .../common/useCanvasPopupStatusController.js | 32 +- src/hooks/module/useModuleSelection.js | 21 +- 5 files changed, 1113 insertions(+), 137 deletions(-) create mode 100644 src/components/floor-plan/modal/basic/step/Trestle.jsx diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index f312d5ea..1f19f950 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -20,6 +20,10 @@ import { useMasterController } from '@/hooks/common/useMasterController' import { loginUserStore } from '@/store/commonAtom' import { currentCanvasPlanState } from '@/store/canvasAtom' import { POLYGON_TYPE } from '@/common/common' +import { useModuleSelection } from '@/hooks/module/useModuleSelection' +import { useOrientation } from '@/hooks/module/useOrientation' +import Trestle from './step/Trestle' +import { roofsState } from '@/store/roofAtom' export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const { getMessage } = useMessage() @@ -27,24 +31,118 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const [tabNum, setTabNum] = useState(1) const canvasSetting = useRecoilValue(canvasSettingState) const orientationRef = useRef(null) + const trestleRef = useRef(null) const { initEvent } = useEvent() const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState) - const moduleSelectionData = useRecoilValue(moduleSelectionDataState) - const addedRoofs = useRecoilValue(addedRoofsState) + const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState) + const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState) const loginUserState = useRecoilValue(loginUserStore) const currentCanvasPlan = useRecoilValue(currentCanvasPlanState) const canvas = useRecoilValue(canvasState) const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) const [isClosePopup, setIsClosePopup] = useState({ close: false, id: 0 }) const [checkedModules, setCheckedModules] = useRecoilState(checkedModuleState) - + const [roofs, setRoofs] = useState(null) + const { + moduleSelectionInitParams, + selectedModules, + roughnessCodes, + windSpeedCodes, + managementState, + setManagementState, + moduleList, + setSelectedModules, + selectedSurfaceType, + setSelectedSurfaceType, + installHeight, + setInstallHeight, + standardWindSpeed, + setStandardWindSpeed, + verticalSnowCover, + setVerticalSnowCover, + handleChangeModule, + handleChangeSurfaceType, + handleChangeWindSpeed, + handleChangeInstallHeight, + handleChangeVerticalSnowCover, + } = useModuleSelection({ addedRoofs }) + const { nextStep, compasDeg, setCompasDeg } = useOrientation() + const { trigger: orientationTrigger } = useCanvasPopupStatusController(1) + const { trigger: trestleTrigger } = useCanvasPopupStatusController(2) + const { trigger: placementTrigger } = useCanvasPopupStatusController(3) + const roofsStore = useRecoilValue(roofsState) // const { initEvent } = useContext(EventContext) const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup } = useModuleBasicSetting(tabNum) const { updateObjectDate } = useMasterController() + useEffect(() => { + if (managementState) console.log('managementState', managementState) + }, [managementState]) + + useEffect(() => { + if (roofsStore && addedRoofs) { + console.log('🚀 ~ useEffect ~ roofsStore, addedRoofs:', roofsStore, addedRoofs) + setRoofs( + addedRoofs.map((roof, index) => { + return { + ...roof, + ...roofsStore[index].addRoof, + } + }), + ) + + setModuleSelectionData({ + ...moduleSelectionData, + roofConstructions: roofsStore.map((roof) => { + return { + addRoof: { + ...roof.addRoof, + }, + construction: { + ...roof.construction, + }, + trestle: { + ...roof.trestle, + }, + } + }), + }) + } + }, [roofsStore, addedRoofs]) + + useEffect(() => { + let hasModules = canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) + .some((obj) => obj.modules?.length > 0) + + if (hasModules) { + orientationRef.current.handleNextStep() + setTabNum(3) + } + }, []) + + useEffect(() => { + if (basicSetting.roofSizeSet !== '3') { + manualModuleSetup(placementRef) + } else { + manualFlatroofModuleSetup(placementFlatRef) + } + if (isClosePopup.close) { + closePopup(isClosePopup.id) + } + }, [isManualModuleSetup, isClosePopup]) + + useEffect(() => { + setIsManualModuleSetup(false) + }, [checkedModules]) + const handleBtnNextStep = () => { if (tabNum === 1) { + console.log('moduleSelectionData', moduleSelectionData) orientationRef.current.handleNextStep() + setAddedRoofs(roofs) + return } else if (tabNum === 2) { if (basicSetting.roofSizeSet !== '3') { if (!isObjectNotEmpty(moduleSelectionData.module)) { @@ -55,22 +153,22 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { return } - if (addedRoofs.length !== moduleSelectionData.roofConstructions.length) { + // if (addedRoofs.length !== moduleSelectionData.roofConstructions.length) { + // Swal.fire({ + // title: getMessage('construction.length.difference'), + // icon: 'warning', + // }) + // return + // } + + if (!trestleRef.current.isComplete()) { Swal.fire({ - title: getMessage('construction.length.difference'), + title: getMessage('아직 멀었따'), icon: 'warning', }) return } //물건정보 갱신일 수정 - updateObjectDataApi({ - objectNo: currentCanvasPlan.objectNo, //오브젝트_no - standardWindSpeedId: moduleSelectionData.common.stdWindSpeed, //기준풍속코드 - verticalSnowCover: moduleSelectionData.common.stdSnowLd, //적설량 - surfaceType: moduleSelectionData.common.illuminationTpNm, //면조도구분 - installHeight: moduleSelectionData.common.instHt, //설치높이 - userId: loginUserState.userId, //작성자아아디 - }) } else { if (!isObjectNotEmpty(moduleSelectionData.module)) { Swal.fire({ @@ -103,18 +201,6 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const res = await updateObjectDate(params) } - useEffect(() => { - let hasModules = canvas - .getObjects() - .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) - .some((obj) => obj.modules?.length > 0) - - if (hasModules) { - orientationRef.current.handleNextStep() - setTabNum(3) - } - }, []) - //팝업 닫기 버튼 이벤트 const handleClosePopup = (id) => { if (tabNum == 3) { @@ -125,44 +211,86 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { setIsClosePopup({ close: true, id: id }) } - useEffect(() => { - if (basicSetting.roofSizeSet !== '3') { - manualModuleSetup(placementRef) - } else { - manualFlatroofModuleSetup(placementFlatRef) - } - if (isClosePopup.close) { - closePopup(isClosePopup.id) - } - }, [isManualModuleSetup, isClosePopup]) - - useEffect(() => { - setIsManualModuleSetup(false) - }, [checkedModules]) + const orientationProps = { + roofs, + setRoofs, + tabNum, + setTabNum, + compasDeg, // 방위각 + setCompasDeg, + moduleSelectionInitParams, + selectedModules, + moduleSelectionData, + setModuleSelectionData, + roughnessCodes, // 면조도 목록 + windSpeedCodes, // 기준풍속 목록 + managementState, + setManagementState, + moduleList, // 모듈 리스트 + setSelectedModules, + selectedSurfaceType, + setSelectedSurfaceType, + installHeight, // 설치높이 + setInstallHeight, + standardWindSpeed, // 기준풍속 + setStandardWindSpeed, + verticalSnowCover, // 적설량 + setVerticalSnowCover, + currentCanvasPlan, + loginUserState, + handleChangeModule, + handleChangeSurfaceType, + handleChangeWindSpeed, + handleChangeInstallHeight, + handleChangeVerticalSnowCover, + orientationTrigger, + nextStep, + updateObjectDataApi, + } + const trestleProps = { + roofs, + setRoofs, + setTabNum, + moduleSelectionData, + setModuleSelectionData, + trestleTrigger, + } + const placementProps = {} return ( - + handleClosePopup(id)} />
{getMessage('modal.module.basic.setting.orientation.setting')}
-
{getMessage('modal.module.basic.setting.module.setting')}
- -
{getMessage('modal.module.basic.setting.module.placement')}
+ {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && ( + <> +
{getMessage('modal.module.basic.setting.module.setting')}
+ +
{getMessage('modal.module.basic.setting.module.placement')}
+ + )} + {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && ( + <> +
{getMessage('modal.module.basic.setting.module.placement')}
+ + )}
- {tabNum === 1 && } + {tabNum === 1 && } {/*배치면 초기설정 - 입력방법: 복시도 입력 || 실측값 입력*/} - {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 2 && } + {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 2 && } {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 3 && } {/*배치면 초기설정 - 입력방법: 육지붕*/} - {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 2 && } - {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 3 && ( + {/* {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 3 && } */} + {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 2 && ( )}
+ {/* {tabNum === 1 && } */} + {tabNum !== 1 && ( @@ -189,6 +318,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { )} {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && ( <> + diff --git a/src/components/floor-plan/modal/basic/step/Orientation.jsx b/src/components/floor-plan/modal/basic/step/Orientation.jsx index 4e279f04..59ff4f37 100644 --- a/src/components/floor-plan/modal/basic/step/Orientation.jsx +++ b/src/components/floor-plan/modal/basic/step/Orientation.jsx @@ -1,35 +1,153 @@ -import { forwardRef, useContext, useEffect, useImperativeHandle, useState } from 'react' +import { forwardRef, use, useContext, useEffect, useImperativeHandle, useState } from 'react' import { useMessage } from '@/hooks/useMessage' import { useOrientation } from '@/hooks/module/useOrientation' import { getDegreeInOrientation } from '@/util/canvas-util' import { numberCheck } from '@/util/common-utils' import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController' +import { addedRoofsState, basicSettingState } from '@/store/settingAtom' +import { useRecoilState, useRecoilValue } from 'recoil' +import QSelectBox from '@/components/common/select/QSelectBox' +import { moduleSelectionDataState } from '@/store/selectedModuleOptions' -export const Orientation = forwardRef(({ tabNum }, ref) => { +export const Orientation = forwardRef((props, ref) => { const { getMessage } = useMessage() - - const { trigger: canvasPopupStatusTrigger } = useCanvasPopupStatusController(1) - - const { nextStep, compasDeg, setCompasDeg } = useOrientation() - const [hasAnglePassivity, setHasAnglePassivity] = useState(false) + const basicSetting = useRecoilValue(basicSettingState) + const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState) //지붕재 선택 + const [roofTab, setRoofTab] = useState(0) //지붕재 탭 + const { + roofs, + setRoofs, + tabNum, + setTabNum, + compasDeg, + setCompasDeg, + moduleSelectionInitParams, + selectedModules, + roughnessCodes, + windSpeedCodes, + managementState, + setManagementState, + moduleList, + moduleSelectionData, + setModuleSelectionData, + setSelectedModules, + selectedSurfaceType, + setSelectedSurfaceType, + installHeight, + setInstallHeight, + standardWindSpeed, + setStandardWindSpeed, + verticalSnowCover, + setVerticalSnowCover, + orientationTrigger, + nextStep, + currentCanvasPlan, + loginUserState, + updateObjectDataApi, + } = props + const [inputCompasDeg, setInputCompasDeg] = useState(compasDeg ?? 0) + const [inputInstallHeight, setInputInstallHeight] = useState('0') + const [inputVerticalSnowCover, setInputVerticalSnowCover] = useState('0') + const [inputRoughness, setInputRoughness] = useState(selectedSurfaceType) + const [inputStandardWindSpeed, setInputStandardWindSpeed] = useState(standardWindSpeed) + const moduleData = { + header: [ + { name: getMessage('module'), width: 150, prop: 'module', type: 'color-box' }, + { + name: `${getMessage('height')} (mm)`, + prop: 'height', + }, + { name: `${getMessage('width')} (mm)`, prop: 'width' }, + { name: `${getMessage('output')} (W)`, prop: 'output' }, + ], + } + + useEffect(() => { + if (selectedSurfaceType) { + console.log(roughnessCodes, selectedSurfaceType) + setInputRoughness(roughnessCodes.find((code) => code.clCode === moduleSelectionData.common.illuminationTp)) + } + }, [selectedSurfaceType]) + + useEffect(() => { + if (standardWindSpeed) setInputStandardWindSpeed(windSpeedCodes.find((code) => code.clCode === moduleSelectionData.common.stdWindSpeed)) + }, [standardWindSpeed]) + + useEffect(() => { + if (managementState?.installHeight && managementState?.installHeight) { + console.log('🚀 ~ useEffect ~ managementState:', managementState) + setSelectedSurfaceType(roughnessCodes.find((code) => code.clCode === managementState?.surfaceTypeValue)) + setInputInstallHeight(managementState?.installHeight) + setStandardWindSpeed(windSpeedCodes.find((code) => code.clCode === managementState?.standardWindSpeedId)) + setInputVerticalSnowCover(managementState?.verticalSnowCover) + } + }, [managementState]) + + useEffect(() => { + if (moduleSelectionData) { + console.log('moduleSelectionData', moduleSelectionData) + } + }, [moduleSelectionData]) useImperativeHandle(ref, () => ({ handleNextStep, })) const handleNextStep = () => { - nextStep() - canvasPopupStatusTrigger(compasDeg) + if (isComplete()) { + const common = { + illuminationTp: inputRoughness.clCode, + illuminationTpNm: inputRoughness.clCodeNm, + instHt: inputInstallHeight, + stdWindSpeed: inputStandardWindSpeed.clCode, + stdSnowLd: inputVerticalSnowCover, + saleStoreNorthFlg: managementState?.saleStoreNorthFlg, + moduleTpCd: selectedModules.itemTp, + moduleItemId: selectedModules.itemId, + } + setCompasDeg(inputCompasDeg) + setInstallHeight(inputInstallHeight) + setVerticalSnowCover(inputVerticalSnowCover) + setSelectedSurfaceType(inputRoughness) + setStandardWindSpeed(inputStandardWindSpeed) + nextStep() + setManagementState({ + ...managementState, + installHeight: inputInstallHeight, + verticalSnowCover: inputVerticalSnowCover, + standardWindSpeedId: inputStandardWindSpeed.clCode, + surfaceType: inputRoughness.clCodeNm, + surfaceTypeValue: inputRoughness.clCode, + }) + setModuleSelectionData({ + ...moduleSelectionData, + module: { + ...selectedModules, + }, + }) + orientationTrigger({ + compasDeg: inputCompasDeg, + common: common, + module: { + ...selectedModules, + }, + }) + updateObjectDataApi({ + objectNo: currentCanvasPlan.objectNo, //오브젝트_no + standardWindSpeedId: inputStandardWindSpeed.clCode, //기준풍속코드 + verticalSnowCover: inputVerticalSnowCover, //적설량 + surfaceType: inputRoughness.clCodeNm, //면조도구분 + installHeight: inputInstallHeight, //설치높이 + userId: loginUserState.userId, //작성자아아디 + }) + setTabNum(2) + } } - useEffect(() => { - checkDegree(compasDeg) - }, [compasDeg]) - const checkDegree = (e) => { if (e === '-0' || e === '-') { - setCompasDeg('-') + setInputCompasDeg('-') return } if (e === '0-') { @@ -45,71 +163,256 @@ export const Orientation = forwardRef(({ tabNum }, ref) => { } } + const isComplete = () => { + if (basicSetting && basicSetting.roofSizeSet !== '3') { + if (inputInstallHeight <= 0) { + return false + } + + if (+inputVerticalSnowCover <= 0) { + return false + } + + if (!inputStandardWindSpeed) return false + if (!inputRoughness) return false + } + + return true + } + + const handleChangeModule = (e) => { + const newRoofs = addedRoofs.map((roof) => { + return { + ...roof, + lengthBase: null, + raftBaseCd: null, + trestleMkrCd: null, + constMthdCd: null, + constTp: null, + roofBaseCd: null, + ridgeMargin: null, + kerabaMargin: null, + eavesMargin: null, + roofPchBase: null, + cvrYn: 'N', + snowGdPossYn: 'N', + cvrChecked: false, + snowGdChecked: false, + } + }) + setRoofs(newRoofs) + setSelectedModules(e) + } + return ( <>
-
{getMessage('modal.module.basic.setting.orientation.setting.info')}
-
-
-
- {Array.from({ length: 180 / 15 }).map((dot, index) => ( -
= 172 && index === 0 && compasDeg <= 180) || (compasDeg === -180 && index === 0) ? 'act' : ''}`} - onClick={() => { - if (index === 0) { - setCompasDeg(180) - return - } - setCompasDeg(-1 * (-15 * index + 180)) - }} - > - {index === 0 && 180°} - {index === 6 && -90°} +
+
+
{getMessage('modal.module.basic.setting.orientation.setting.info')}
+
+
+
+ {Array.from({ length: 180 / 15 }).map((dot, index) => ( +
= 172 && index === 0 && inputCompasDeg <= 180) || (inputCompasDeg === -180 && index === 0) ? 'act' : ''}`} + onClick={() => { + if (index === 0) { + setInputCompasDeg(180) + return + } + setInputCompasDeg(-1 * (-15 * index + 180)) + }} + > + {index === 0 && 180°} + {index === 6 && -90°} +
+ ))} + {Array.from({ length: 180 / 15 }).map((dot, index) => ( +
setInputCompasDeg(15 * index)} + > + {index === 0 && } + {index === 6 && 90°} +
+ ))} +
+
+
- ))} - {Array.from({ length: 180 / 15 }).map((dot, index) => ( -
setCompasDeg(15 * index)} - > - {index === 0 && } - {index === 6 && 90°} +
+
+
+
+
+ setHasAnglePassivity(!hasAnglePassivity)} /> +
- ))} -
-
+
+ checkDegree(e.target.value)} + /> +
+ ° + ( -180 〜 180 )
-
-
-
- setHasAnglePassivity(!hasAnglePassivity)} /> - -
-
-
- checkDegree(e.target.value) - // setCompasDeg( - - // e.target.value === '-' || (e.target.value !== '' && parseInt(e.target.value) <= 180 && parseInt(e.target.value) >= -180) - // ? e.target.value - // : 0, - // ) - } - /> +
+
+
+ {getMessage('modal.module.basic.setting.module.setting')} +
+ {moduleList && ( + handleChangeModule(e)} + /> + )} +
+
+
+ + + + {moduleData.header.map((header) => { + return ( + + ) + })} + + + + {Array.from({ length: 2 }).map((_, index) => { + return selectedModules && selectedModules?.itemList && selectedModules?.itemList?.length >= index + 1 ? ( + + + + + + + ) : ( + + + + + + + ) + })} + +
+ {header.name} +
+
+ + {selectedModules.itemList[index].itemNm} +
+
{Number(selectedModules.itemList[index].shortAxis).toFixed(0)}{Number(selectedModules.itemList[index].longAxis).toFixed(0)}{Number(selectedModules.itemList[index].wpOut).toFixed(0)}
+
+
+
+ {basicSetting && basicSetting.roofSizeSet === '3' && ( +
+ {getMessage('modal.module.basic.setting.module.placement.area')} +
+ setInputInstallHeight(e.target.value)} + /> +
+ m +
+ )}
- ° + + {basicSetting && basicSetting.roofSizeSet !== '3' && ( +
+
+
+ {getMessage('modal.module.basic.setting.module.surface.type')} +
+ {roughnessCodes.length > 0 && managementState && ( + { + console.log('🚀 ~ handleChangeModule ~ inputRoughness:', e) + setInputRoughness(e) + }} + /> + )} +
+
+
+ {getMessage('modal.module.basic.setting.module.fitting.height')} +
+ setInputInstallHeight(e.target.value)} + /> +
+ m +
+
+ {getMessage('modal.module.basic.setting.module.standard.wind.speed')} +
+ {windSpeedCodes.length > 0 && managementState && ( + { + console.log('🚀 ~ handleChangeModule ~ inputStandardWindSpeed:', e) + setInputStandardWindSpeed(e) + }} + /> + )} +
+
+
+ {getMessage('modal.module.basic.setting.module.standard.snowfall.amount')} +
+ setInputVerticalSnowCover(e.target.value)} + /> +
+ cm +
+
+
+ )}
diff --git a/src/components/floor-plan/modal/basic/step/Trestle.jsx b/src/components/floor-plan/modal/basic/step/Trestle.jsx new file mode 100644 index 00000000..a6c62750 --- /dev/null +++ b/src/components/floor-plan/modal/basic/step/Trestle.jsx @@ -0,0 +1,532 @@ +import { GlobalDataContext } from '@/app/GlobalDataProvider' +import QSelectBox from '@/components/common/select/QSelectBox' +import { useModuleTrestle } from '@/hooks/module/useModuleTrestle' +import { useMessage } from '@/hooks/useMessage' +import { currentAngleTypeSelector, pitchTextSelector } from '@/store/canvasAtom' +import { roofsState } from '@/store/roofAtom' +import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions' +import { isObjectNotEmpty } from '@/util/common-utils' +import { forwardRef, useContext, useEffect, useImperativeHandle, useState } from 'react' +import { useRecoilState, useRecoilValue } from 'recoil' + +const Trestle = forwardRef((props, ref) => { + const { setTabNum, trestleTrigger, roofs, setRoofs, moduleSelectionData, setModuleSelectionData } = props + const { getMessage } = useMessage() + // const [selectedTrestle, setSelectedTrestle] = useState() + const currentAngleType = useRecoilValue(currentAngleTypeSelector) + const pitchText = useRecoilValue(pitchTextSelector) + const [selectedRoof, setSelectedRoof] = useState() + const { + trestleState, + dispatch, + raftBaseList, + trestleList, + constMthdList, + roofBaseList, + constructionList, + eavesMargin, + ridgeMargin, + kerabaMargin, + setEavesMargin, + setRidgeMargin, + setKerabaMargin, + cvrYn, + cvrChecked, + snowGdPossYn, + snowGdChecked, + setCvrYn, + setCvrChecked, + setSnowGdPossYn, + setSnowGdChecked, + } = useModuleTrestle({ + selectedRoof, + }) + const selectedModules = useRecoilValue(selectedModuleState) //선택된 모듈 + // const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState) + const [lengthBase, setLengthBase] = useState(0) + const [hajebichi, setHajebichi] = useState(0) + const [selectedRaftBase, setSelectedRaftBase] = useState(null) + const [selectedTrestle, setSelectedTrestle] = useState(null) + const [selectedConstMthd, setSelectedConstMthd] = useState(null) + const [selectedConstruction, setSelectedConstruction] = useState(null) + const [selectedRoofBase, setSelectedRoofBase] = useState(null) + const { managementState } = useContext(GlobalDataContext) + + useEffect(() => { + if (roofs && !selectedRoof) { + setSelectedRoof(roofs[0]) + } + }, [roofs]) + + useEffect(() => { + if (selectedRoof) { + dispatch({ type: 'SET_INITIALIZE', roof: { ...selectedRoof, moduleTpCd: selectedModules.itemTp } }) + } + }, [selectedRoof]) + + useEffect(() => { + if (raftBaseList.length > 0) setSelectedRaftBase(raftBaseList.find((raft) => raft.clCode === trestleState?.raftBaseCd) ?? null) + }, [raftBaseList]) + + useEffect(() => { + if (trestleList.length > 0) setSelectedTrestle(trestleList.find((trestle) => trestle.trestleMkrCd === trestleState?.trestleMkrCd) ?? null) + }, [trestleList]) + + useEffect(() => { + if (roofBaseList.length > 0) setSelectedRoofBase(roofBaseList.find((roofBase) => roofBase.roofBaseCd === trestleState?.roofBaseCd) ?? null) + }, [roofBaseList]) + + useEffect(() => { + if (constMthdList.length > 0) setSelectedConstMthd(constMthdList.find((constMthd) => constMthd.constMthdCd === trestleState?.constMthdCd) ?? null) + }, [constMthdList]) + + useEffect(() => { + if (constructionList.length > 0) { + setSelectedConstruction(constructionList.find((construction) => construction.constTp === trestleState?.constTp) ?? null) + } + }, [constructionList]) + + const getConstructionState = (index) => { + if (constructionList && constructionList.length > 0) { + if (constructionList[index].constPossYn === 'Y') { + if (trestleState && trestleState.constTp === constructionList[index].constTp) { + return 'blue' + } + return 'white' + } + return 'no-click' + } + return 'no-click' + } + + const onChangeRaftBase = (e) => { + setSelectedRaftBase(e) + dispatch({ + type: 'SET_RAFT_BASE', + roof: { + moduleTpCd: selectedModules.itemTp ?? '', + roofMatlCd: selectedRoof?.roofMatlCd ?? '', + raftBaseCd: e.clCode, + }, + }) + } + + const onChangeTrestleMaker = (e) => { + setSelectedTrestle(e) + dispatch({ + type: 'SET_TRESTLE_MAKER', + roof: { + moduleTpCd: selectedModules.itemTp ?? '', + roofMatlCd: selectedRoof?.roofMatlCd ?? '', + raftBaseCd: trestleState.raftBaseCd ?? '', + trestleMkrCd: e.trestleMkrCd, + }, + }) + } + + const onChangeConstMthd = (e) => { + setSelectedConstMthd(e) + dispatch({ + type: 'SET_CONST_MTHD', + roof: { + moduleTpCd: selectedModules.itemTp ?? '', + roofMatlCd: selectedRoof?.roofMatlCd ?? '', + raftBaseCd: trestleState.raftBaseCd ?? '', + trestleMkrCd: trestleState.trestleMkrCd, + constMthdCd: e.constMthdCd, + }, + }) + } + + const onChangeRoofBase = (e) => { + setSelectedRoofBase(e) + dispatch({ + type: 'SET_ROOF_BASE', + roof: { + moduleTpCd: selectedModules.itemTp ?? '', + roofMatlCd: selectedRoof?.roofMatlCd ?? '', + raftBaseCd: trestleState.raftBaseCd ?? '', + trestleMkrCd: trestleState.trestleMkrCd, + constMthdCd: trestleState.constMthdCd, + roofBaseCd: e.roofBaseCd, + illuminationTp: managementState?.surfaceTypeValue ?? '', + instHt: managementState?.installHeight ?? '', + stdWindSpeed: managementState?.standardWindSpeedId ?? '', + stdSnowLd: managementState?.verticalSnowCover ?? '', + inclCd: selectedRoof?.pitch ?? 0, + roofPitch: Math.round(selectedRoof?.roofPchBase ?? 0), + }, + }) + } + const handleChangeRoofMaterial = (index) => { + const newAddedRoofs = roofs.map((roof, i) => { + if (i === selectedRoof.index) { + return { + ...selectedRoof, + ...trestleState, + eavesMargin, + ridgeMargin, + kerabaMargin, + cvrYn, + snowGdPossYn, + cvrChecked, + snowGdChecked, + } + } + return { ...roof } + }) + setRoofs(newAddedRoofs) + setSelectedRoof(newAddedRoofs[index]) + } + + const handleConstruction = (index) => { + if (constructionList[index]?.constPossYn === 'Y') { + dispatch({ + type: 'SET_CONSTRUCTION', + roof: { + moduleTpCd: selectedModules.itemTp ?? '', + roofMatlCd: selectedRoof?.roofMatlCd ?? '', + raftBaseCd: trestleState.raftBaseCd ?? '', + trestleMkrCd: trestleState.trestleMkrCd, + constMthdCd: trestleState.constMthdCd, + roofBaseCd: trestleState.roofBaseCd, + illuminationTp: managementState?.surfaceTypeValue ?? '', + instHt: managementState?.installHeight ?? '', + stdWindSpeed: managementState?.standardWindSpeedId ?? '', + stdSnowLd: +managementState?.verticalSnowCover ?? '', + inclCd: selectedRoof?.pitch.toString() ?? 0, + roofPitch: Math.round(selectedRoof?.roofPchBase ?? 0), + constTp: constructionList[index].constTp, + mixMatlNo: selectedModules.mixMatlNo, + workingWidth: selectedRoof?.length.toString() ?? '', + // snowGdPossYn: constructionList[index].snowGdPossYn, + // cvrYn: constructionList[index].cvrYn, + }, + }) + + setCvrYn(constructionList[index].cvrYn) + setSnowGdPossYn(constructionList[index].snowGdPossYn) + setCvrChecked(false) + setSnowGdChecked(false) + } + } + + const isComplete = () => { + const newAddedRoofs = roofs.map((roof, i) => { + if (i === selectedRoof?.index) { + return { + ...selectedRoof, + ...trestleState, + eavesMargin, + ridgeMargin, + kerabaMargin, + cvrYn, + snowGdPossYn, + cvrChecked, + snowGdChecked, + } + } + return { ...roof } + }) + + let result = true + newAddedRoofs.forEach((roof) => { + if (roof.eavesMargin && roof.ridgeMargin && roof.kerabaMargin) { + return true + } + + if (!roof.trestleMkrCd) result = false + if (!roof.constMthdCd) result = false + if (!roof.roofBaseCd) result = false + if (!roof.constTp) result = false + + if (selectedRoof.lenAuth === 'C') { + if (!trestleState?.lengthBase) result = false + } + if (['C', 'R'].includes(selectedRoof.raftAuth)) { + if (!roof.raftBaseCd) result = false + } + + if (['C', 'R'].includes(selectedRoof.roofPchAuth)) { + if (!roof.roofPchBase) result = false + } + }) + + console.log('newAddedRoofs', newAddedRoofs) + + if (result) { + setRoofs(newAddedRoofs) + setModuleSelectionData({ + ...moduleSelectionData, + roofConstruction: { + ...newAddedRoofs, + }, + }) + trestleTrigger({ + roofConstruction: newAddedRoofs.map((roof) => { + return { + roofIndex: roof.index, + addRoof: { + ...roof, + }, + trestle: { + ...selectedTrestle, + raftBaseCd: roof.raftBaseCd, + }, + construction: { + ...constructionList.find((construction) => trestleState.constTp === construction.constTp), + roofIndex: roof.index, + setupCover: roof.cvrYn === 'Y', + setupSnowCover: roof.snowGdYn === 'Y', + selectedIndex: roof.index, + }, + } + }), + }) + } + + return result + } + + useImperativeHandle(ref, () => ({ + isComplete, + })) + + return ( +
+
+
+ {roofs && + roofs.map((roof, index) => ( + + ))} +
+
+
+
+
+ {selectedRoof && selectedRoof.lenAuth === 'C' && ( + <> +
+
L
+
+
+ setLengthBase(e.target.value)} + disabled={selectedRoof.lenAuth === 'R'} + /> +
+
+
+ + )} + {selectedRoof && ['C', 'R'].includes(selectedRoof.raftAuth) && ( + <> +
+
{getMessage('modal.module.basic.setting.module.rafter.margin')}
+
+
+ {raftBaseList.length > 0 && ( + onChangeRaftBase(e)} + /> + )} +
+
+
+ + )} + {selectedRoof && ['C', 'R'].includes(selectedRoof.roofPchAuth) && ( + <> +
+
{getMessage('modal.module.basic.setting.module.hajebichi')}
+
+
+ handleHajebichiAndLength(e, 'hajebichi')} + value={hajebichi} + /> +
+
+
+ + )} +
+
{getMessage('modal.module.basic.setting.module.trestle.maker')}
+
+
+ {trestleList && ( + onChangeTrestleMaker(e)} + /> + )} +
+
+
+
+
{getMessage('modal.module.basic.setting.module.construction.method')}
+
+
+ {constMthdList && ( + onChangeConstMthd(e)} + /> + )} +
+
+
+
+
{getMessage('modal.module.basic.setting.module.under.roof')}
+
+
+ {roofBaseList && ( + onChangeRoofBase(e)} + /> + )} +
+
+
+
+
+
+
+ + + + + +
+
+
+ dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, cvrChecked: !trestleState.cvrChecked } })} + onChange={() => setCvrChecked(!cvrChecked)} + /> + +
+
+ dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, snowGdChecked: !trestleState.snowGdChecked } })} + onChange={() => setSnowGdChecked(!snowGdChecked)} + /> + +
+
+
+
+ +
+
{getMessage('modal.module.basic.setting.module.placement.area')}
+
+ {getMessage('modal.module.basic.setting.module.placement.area.eaves')} +
+ dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, eavesMargin: e.target.value } })} + onChange={(e) => setEavesMargin(e.target.value)} + /> +
+ mm +
+
+ {getMessage('modal.module.basic.setting.module.placement.area.ridge')} +
+ dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, ridgeMargin: e.target.value } })} + onChange={(e) => setRidgeMargin(e.target.value)} + /> +
+ mm +
+
+ {getMessage('modal.module.basic.setting.module.placement.area.keraba')} +
+ dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, kerabaMargin: e.target.value } })} + onChange={(e) => setKerabaMargin(e.target.value)} + /> +
+ mm +
+
+
+
+
+
+
+
+ {getMessage('modal.module.basic.setting.module.setting.info1')} +
+ {getMessage('modal.module.basic.setting.module.setting.info2')} +
+
+
+
+
+ ) +}) + +export default Trestle diff --git a/src/hooks/common/useCanvasPopupStatusController.js b/src/hooks/common/useCanvasPopupStatusController.js index a31bd0ed..4a6ed6dd 100644 --- a/src/hooks/common/useCanvasPopupStatusController.js +++ b/src/hooks/common/useCanvasPopupStatusController.js @@ -1,6 +1,6 @@ 'use client' -import { useRecoilState, useRecoilValue } from 'recoil' +import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import useSWRMutation from 'swr/mutation' import { useAxios } from '../useAxios' import { unescapeString } from '@/util/common-utils' @@ -10,6 +10,8 @@ import { canvasState, currentCanvasPlanState } from '@/store/canvasAtom' import { POLYGON_TYPE } from '@/common/common' import { useCircuitTrestle } from '../useCirCuitTrestle' import { useEffect } from 'react' +import { addedRoofsState } from '@/store/settingAtom' +import { roofsState } from '@/store/roofAtom' /** * 캔버스 팝업 상태 관리 @@ -19,13 +21,14 @@ import { useEffect } from 'react' export function useCanvasPopupStatusController(param = 1) { const popupType = parseInt(param) - const [compasDeg, setCompasDeg] = useRecoilState(compasDegAtom) - const [moduleSelectionDataStore, setModuleSelectionDataStore] = useRecoilState(moduleSelectionDataState) - const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) + const setCompasDeg = useSetRecoilState(compasDegAtom) + const setModuleSelectionDataStore = useSetRecoilState(moduleSelectionDataState) + const setSelectedModules = useSetRecoilState(selectedModuleState) const { get, promiseGet, getFetcher, postFetcher } = useAxios() const canvas = useRecoilValue(canvasState) const currentCanvasPlan = useRecoilValue(currentCanvasPlanState) - + const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState) + const [roofs, setRoofs] = useRecoilState(roofsState) /** * 팝업 상태 조회 * @param {number} popupTypeParam @@ -53,19 +56,27 @@ export function useCanvasPopupStatusController(param = 1) { const handleModuleSelectionTotal = async () => { for (let i = 1; i < 3; i++) { const result = await getModuleSelection(i) - console.log('🚀 ~ handleModuleSelectionTotal ~ result:', result) if (!result.objectNo) return if (i === 1) { - setCompasDeg(result.popupStatus) + if (result.popupStatus && unescapeString(result.popupStatus)) { + const data = JSON.parse(unescapeString(result.popupStatus)) + + if (data?.compasDeg) setCompasDeg(data.compasDeg) + if (data?.module) setSelectedModules(data.module) + setModuleSelectionDataStore(data) + } } else if (i === 2) { const data = JSON.parse(unescapeString(result.popupStatus)) - setModuleSelectionDataStore(data) const roofSurfaceList = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE) roofSurfaceList.forEach((surface) => { surface.modules = modules.filter((module) => module.surfaceId === surface.id) }) - if (data.module) setSelectedModules(data.module) + if (data.roofConstruction) { + setRoofs(data.roofConstruction) + // setManagementState({ ...managementState, roofs: data.roofConstruction.map((roof) => roof.construction.managementState) }) + } + // if (data?.module) setManagementState(data.common.managementState) } } } @@ -80,7 +91,8 @@ export function useCanvasPopupStatusController(param = 1) { objectNo: currentCanvasPlan.objectNo, planNo: parseInt(currentCanvasPlan.planNo), popupType: popupType.toString(), - popupStatus: popupType === 1 ? arg : JSON.stringify(arg).replace(/"/g, '\"'), + // popupStatus: popupType === 1 ? arg : JSON.stringify(arg).replace(/"/g, '\"'), + popupStatus: JSON.stringify(arg).replace(/"/g, '\"'), } postFetcher(`/api/v1/canvas-popup-status`, params) }, diff --git a/src/hooks/module/useModuleSelection.js b/src/hooks/module/useModuleSelection.js index 8fa274a4..1373ea05 100644 --- a/src/hooks/module/useModuleSelection.js +++ b/src/hooks/module/useModuleSelection.js @@ -19,9 +19,9 @@ export function useModuleSelection(props) { const [moduleList, setModuleList] = useState([{}]) //모듈 목록 const [selectedSurfaceType, setSelectedSurfaceType] = useState({}) //선택된 면조도 - const [installHeight, setInstallHeight] = useState() //설치 높이 - const [standardWindSpeed, setStandardWindSpeed] = useState({}) //기준풍속 - const [verticalSnowCover, setVerticalSnowCover] = useState() //수직적설량 + const [installHeight, setInstallHeight] = useState(managementState?.installHeight) //설치 높이 + const [standardWindSpeed, setStandardWindSpeed] = useState() //기준풍속 + const [verticalSnowCover, setVerticalSnowCover] = useState(managementState?.verticalSnowCover) //수직적설량 const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) //선택된 모듈 const [moduleSelectionInitParams, setModuleSelectionInitParams] = useRecoilState(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등 @@ -32,6 +32,7 @@ export function useModuleSelection(props) { const { restoreModuleInstArea } = useModuleBasicSetting() const bindInitData = () => { + console.log('bindInitData', managementState) setInstallHeight(managementState?.installHeight) setStandardWindSpeed(managementState?.standardWindSpeedId) setVerticalSnowCover(managementState?.verticalSnowCover) @@ -184,14 +185,6 @@ export function useModuleSelection(props) { }) } - useEffect(() => { - // console.log('installHeight', installHeight) - }, [installHeight]) - - useEffect(() => { - // console.log('verticalSnowCover', verticalSnowCover) - }, [verticalSnowCover]) - //TODO: 설치높이, 기준적설량 debounce 적용해서 추가해야됨 // useEffect(() => { @@ -226,11 +219,17 @@ export function useModuleSelection(props) { roughnessCodes, windSpeedCodes, managementState, + setManagementState, moduleList, + setSelectedModules, selectedSurfaceType, + setSelectedSurfaceType, installHeight, + setInstallHeight, standardWindSpeed, + setStandardWindSpeed, verticalSnowCover, + setVerticalSnowCover, handleChangeModule, handleChangeSurfaceType, handleChangeWindSpeed, From fe10ecf476bde27831d927ba42a04e585513ecad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Wed, 2 Apr 2025 14:22:15 +0900 Subject: [PATCH 23/35] PlacementShapeSetting merge --- .../modal/placementShape/PlacementShapeSetting.jsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 364526fb..9cef4f03 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -19,6 +19,7 @@ import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util' import { usePolygon } from '@/hooks/usePolygon' import { canvasState } from '@/store/canvasAtom' import { useRoofFn } from '@/hooks/common/useRoofFn' +import { usePlan } from '@/hooks/usePlan' /** * 지붕 레이아웃 @@ -53,7 +54,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla rafter: useRef(null), hajebichi: useRef(null), } - + const { saveCanvas } = usePlan() /** * 치수 입력방법(복시도입력/실측값입력/육지붕) */ @@ -260,8 +261,6 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla -
-
From d165267ec1b3b6d0fee5d4909becb0cef62c86af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Wed, 2 Apr 2025 14:47:09 +0900 Subject: [PATCH 24/35] =?UTF-8?q?=F0=9F=9A=A8chore:=20Sync=20Sass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/styles/_grid-detail.scss | 4 ++++ src/styles/_reset.scss | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/styles/_grid-detail.scss b/src/styles/_grid-detail.scss index b0c88984..5f27bd18 100644 --- a/src/styles/_grid-detail.scss +++ b/src/styles/_grid-detail.scss @@ -24,6 +24,10 @@ .ag-header-cell{ font-size: 13px; color: #fff; + border-right: 1px solid #738596; + &:last-child{ + border: none; + } } .ag-header-cell-label{ justify-content: center; diff --git a/src/styles/_reset.scss b/src/styles/_reset.scss index fab3eb04..ac0d2f73 100644 --- a/src/styles/_reset.scss +++ b/src/styles/_reset.scss @@ -383,7 +383,7 @@ button{ } } &::-webkit-scrollbar { - width: 2px; + width: 5px; background-color: transparent; } From 2dbbd3a9570242ad06e7bb11db2f4b6c742ed0d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Wed, 2 Apr 2025 14:47:21 +0900 Subject: [PATCH 25/35] =?UTF-8?q?roofAtom=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/store/roofAtom.js | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/store/roofAtom.js diff --git a/src/store/roofAtom.js b/src/store/roofAtom.js new file mode 100644 index 00000000..36f35b6c --- /dev/null +++ b/src/store/roofAtom.js @@ -0,0 +1,7 @@ +import { atom } from 'recoil' + +export const roofsState = atom({ + key: 'roofs', + default: null, + dangerouslyAllowMutability: true, +}) From ba06fde9cce184ddaf5ded280628cf40f4333234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Wed, 2 Apr 2025 14:50:20 +0900 Subject: [PATCH 26/35] =?UTF-8?q?useModuleTrestle=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useModuleTrestle.js | 237 +++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 src/hooks/module/useModuleTrestle.js diff --git a/src/hooks/module/useModuleTrestle.js b/src/hooks/module/useModuleTrestle.js new file mode 100644 index 00000000..d0838b34 --- /dev/null +++ b/src/hooks/module/useModuleTrestle.js @@ -0,0 +1,237 @@ +import { use, useContext, useEffect, useReducer, useState } from 'react' +import { useCommonCode } from '../common/useCommonCode' +import { useMasterController } from '../common/useMasterController' +import { selectedModuleState } from '@/store/selectedModuleOptions' +import { useRecoilValue } from 'recoil' +import { GlobalDataContext } from '@/app/GlobalDataProvider' + +const RAFT_BASE_CODE = '203800' + +const trestleReducer = (state, action) => { + console.log('🚀 ~ trestleReducer ~ state:', state) + console.log('🚀 ~ trestleReducer ~ action:', action) + switch (action.type) { + case 'SET_RAFT_BASE': + case 'SET_TRESTLE_MAKER': + case 'SET_CONST_MTHD': + case 'SET_ROOF_BASE': + case 'SET_CONSTRUCTION': + case 'SET_TRESTLE_DETAIL': + return { + ...action.roof, + } + case 'SET_INITIALIZE': + console.log('SET_INITIALIZE') + return { + moduleTpCd: action.roof.moduleTpCd ?? '', + roofMatlCd: action.roof.roofMatlCd ?? '', + raftBaseCd: action.roof.raftBaseCd ?? null, + trestleMkrCd: action.roof.trestleMkrCd ?? null, + constMthdCd: action.roof.constMthdCd ?? null, + constTp: action.roof.constTp ?? null, + roofBaseCd: action.roof.roofBaseCd ?? null, + workingWidth: action.roof.workingWidth ?? 0, + lengthBase: action.roof.length ?? 0, + illuminationTp: action.roof.illuminationTp ?? null, + instHt: action.roof.instHt ?? null, + stdWindSpeed: action.roof.stdWindSpeed ?? null, + stdSnowLd: action.roof.stdSnowLd ?? null, + inclCd: action.roof.inclCd ?? null, + roofPitch: action.roof.roofPchBase ?? 0, + eavesMargin: action.roof.eavesMargin ?? null, + ridgeMargin: action.roof.ridgeMargin ?? null, + kerabaMargin: action.roof.kerabaMargin ?? null, + } + default: + return state + } +} + +export function useModuleTrestle(props) { + const { selectedRoof } = props + const { findCommonCode } = useCommonCode() + const [raftBaseList, setRaftBaseList] = useState([]) + const [trestleList, setTrestleList] = useState([]) + const [constMthdList, setConstMthdList] = useState([]) + const [roofBaseList, setRoofBaseList] = useState([]) + const [constructionList, setConstructionList] = useState([]) + const { getTrestleList, getConstructionList, getTrestleDetailList } = useMasterController() + const [cvrYn, setCvrYn] = useState('N') + const [cvrChecked, setCvrChecked] = useState(false) + const [snowGdPossYn, setSnowGdPossYn] = useState('N') + const [snowGdChecked, setSnowGdChecked] = useState(false) + const [eavesMargin, setEavesMargin] = useState(0) + const [ridgeMargin, setRidgeMargin] = useState(0) + const [kerabaMargin, setKerabaMargin] = useState(0) + const [trestleState, dispatch] = useReducer(trestleReducer, null) + + useEffect(() => { + const raftCodeList = findCommonCode(RAFT_BASE_CODE) + + setRaftBaseList(raftCodeList) + setTrestleList([]) + setConstMthdList([]) + setRoofBaseList([]) + setConstructionList([]) + setEavesMargin(selectedRoof?.eavesMargin ?? 0) + setRidgeMargin(selectedRoof?.ridgeMargin ?? 0) + setKerabaMargin(selectedRoof?.kerabaMargin ?? 0) + setCvrYn(selectedRoof?.cvrYn ?? 'N') + setCvrChecked(selectedRoof?.cvrChecked ?? false) + setSnowGdPossYn(selectedRoof?.snowGdPossYn ?? 'N') + setSnowGdChecked(selectedRoof?.snowGdChecked ?? false) + }, [selectedRoof]) + + useEffect(() => { + if (trestleState) { + console.log('🚀 ~ useEffect ~ trestleState:', trestleState) + handleSetTrestleList() + if (!trestleState.trestleMkrCd) { + setConstMthdList([]) + setRoofBaseList([]) + setConstructionList([]) + return + } + + handleSetConstMthdList() + if (!trestleState.constMthdCd) { + setRoofBaseList([]) + setConstructionList([]) + return + } + + handleSetRoofBaseList() + if (!trestleState.roofBaseCd) { + setConstructionList([]) + return + } + + handleSetConstructionList() + if (!trestleState.constTp) { + return + } + + if (!trestleState.eavesMargin) { + handleSetTrestleDetailData() + } + } + }, [trestleState]) + + const handleSetTrestleList = () => { + getTrestleList({ + moduleTpCd: trestleState.moduleTpCd ?? '', + roofMatlCd: trestleState.roofMatlCd ?? '', + raftBaseCd: trestleState.raftBaseCd ?? '', + }).then((res) => { + if (res?.data) setTrestleList(res.data) + }) + } + + const handleSetConstMthdList = () => { + getTrestleList({ + moduleTpCd: trestleState.moduleTpCd ?? '', + roofMatlCd: trestleState.roofMatlCd ?? '', + raftBaseCd: trestleState.raftBaseCd ?? '', + trestleMkrCd: trestleState.trestleMkrCd ?? '', + }).then((res) => { + if (res?.data) setConstMthdList(res.data) + }) + } + + const handleSetRoofBaseList = () => { + getTrestleList({ + moduleTpCd: trestleState.moduleTpCd ?? '', + roofMatlCd: trestleState.roofMatlCd ?? '', + raftBaseCd: trestleState.raftBaseCd ?? '', + trestleMkrCd: trestleState.trestleMkrCd ?? '', + constMthdCd: trestleState.constMthdCd ?? '', + }).then((res) => { + if (res?.data) setRoofBaseList(res.data) + }) + } + + const handleSetConstructionList = () => { + getConstructionList({ + moduleTpCd: trestleState.moduleTpCd ?? '', + roofMatlCd: trestleState.roofMatlCd ?? '', + trestleMkrCd: trestleState.trestleMkrCd ?? '', + constMthdCd: trestleState.constMthdCd ?? '', + roofBaseCd: trestleState.roofBaseCd ?? '', + illuminationTp: trestleState.illuminationTp ?? '', + instHt: trestleState.instHt ?? '', + stdWindSpeed: trestleState.stdWindSpeed ?? '', + stdSnowLd: trestleState.stdSnowLd ?? '', + inclCd: trestleState.inclCd ?? '', + raftBaseCd: trestleState.raftBaseCd ?? '', + roofPitch: trestleState.roofPitch ?? '', + }).then((res) => { + if (res?.data) setConstructionList(res.data) + }) + } + + const handleSetTrestleDetailData = () => { + getTrestleDetailList([ + { + moduleTpCd: trestleState.moduleTpCd ?? '', + roofMatlCd: trestleState.roofMatlCd ?? '', + trestleMkrCd: trestleState.trestleMkrCd ?? '', + constMthdCd: trestleState.constMthdCd ?? '', + roofBaseCd: trestleState.roofBaseCd ?? '', + illuminationTp: trestleState.illuminationTp ?? '', + instHt: trestleState.instHt ?? '', + stdWindSpeed: trestleState.stdWindSpeed ?? '', + stdSnowLd: trestleState.stdSnowLd ?? '', + inclCd: trestleState.inclCd ?? '', + constTp: trestleState.constTp ?? '', + mixMatlNo: trestleState.mixMatlNo ?? '', + roofPitch: trestleState.roofPitch ?? '', + workingWidth: trestleState.workingWidth ?? '', + }, + ]).then((res) => { + if (res.length > 0) { + if (!res[0].data) return + setEavesMargin(res[0].data.eaveIntvl) + setRidgeMargin(res[0].data.ridgeIntvl) + setKerabaMargin(res[0].data.kerabaIntvl) + // dispatch({ + // type: 'SET_TRESTLE_DETAIL', + // roof: { + // ...trestleState, + // eavesMargin: res[0].data.eaveIntvl, + // ridgeMargin: res[0].data.ridgeIntvl, + // kerabaMargin: res[0].data.kerabaIntvl, + // }, + // }) + } + }) + } + + return { + trestleState, + dispatch, + raftBaseList, + trestleList, + constMthdList, + roofBaseList, + constructionList, + handleSetTrestleList, + handleSetConstMthdList, + handleSetRoofBaseList, + handleSetConstructionList, + handleSetTrestleDetailData, + eavesMargin, + ridgeMargin, + kerabaMargin, + setEavesMargin, + setRidgeMargin, + setKerabaMargin, + cvrYn, + cvrChecked, + snowGdPossYn, + snowGdChecked, + setCvrYn, + setCvrChecked, + setSnowGdPossYn, + setSnowGdChecked, + } +} From d8e43b0d8191ccd9c6b66b8ce3d77ff613df663c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Wed, 2 Apr 2025 15:19:00 +0900 Subject: [PATCH 27/35] =?UTF-8?q?BasicSetting=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/basic/BasicSetting.jsx | 2 +- .../floor-plan/modal/basic/step/Trestle.jsx | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index 1f19f950..240d1514 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -42,7 +42,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) const [isClosePopup, setIsClosePopup] = useState({ close: false, id: 0 }) const [checkedModules, setCheckedModules] = useRecoilState(checkedModuleState) - const [roofs, setRoofs] = useState(null) + const [roofs, setRoofs] = useState(addedRoofs) const { moduleSelectionInitParams, selectedModules, diff --git a/src/components/floor-plan/modal/basic/step/Trestle.jsx b/src/components/floor-plan/modal/basic/step/Trestle.jsx index a6c62750..dd5a7529 100644 --- a/src/components/floor-plan/modal/basic/step/Trestle.jsx +++ b/src/components/floor-plan/modal/basic/step/Trestle.jsx @@ -258,9 +258,19 @@ const Trestle = forwardRef((props, ref) => { setRoofs(newAddedRoofs) setModuleSelectionData({ ...moduleSelectionData, - roofConstruction: { - ...newAddedRoofs, - }, + roofConstructions: newAddedRoofs.map((roof) => { + return { + addRoof: { + ...roof.addRoof, + }, + trestle: { + ...roof.trestle, + }, + construction: { + ...roof.construction, + }, + } + }), }) trestleTrigger({ roofConstruction: newAddedRoofs.map((roof) => { From 82632b962e93eaaae4731c1cebbc1e90fc7b3516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Wed, 2 Apr 2025 16:55:23 +0900 Subject: [PATCH 28/35] =?UTF-8?q?Trestle=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/basic/step/Trestle.jsx | 11 ++++++++++- src/hooks/module/useModuleTrestle.js | 7 +++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/components/floor-plan/modal/basic/step/Trestle.jsx b/src/components/floor-plan/modal/basic/step/Trestle.jsx index dd5a7529..e3d093a7 100644 --- a/src/components/floor-plan/modal/basic/step/Trestle.jsx +++ b/src/components/floor-plan/modal/basic/step/Trestle.jsx @@ -18,6 +18,7 @@ const Trestle = forwardRef((props, ref) => { const [selectedRoof, setSelectedRoof] = useState() const { trestleState, + trestleDetail, dispatch, raftBaseList, trestleList, @@ -171,6 +172,7 @@ const Trestle = forwardRef((props, ref) => { snowGdPossYn, cvrChecked, snowGdChecked, + trestleDetail, } } return { ...roof } @@ -224,6 +226,7 @@ const Trestle = forwardRef((props, ref) => { snowGdPossYn, cvrChecked, snowGdChecked, + trestleDetail, } } return { ...roof } @@ -258,16 +261,22 @@ const Trestle = forwardRef((props, ref) => { setRoofs(newAddedRoofs) setModuleSelectionData({ ...moduleSelectionData, - roofConstructions: newAddedRoofs.map((roof) => { + roofConstructions: newAddedRoofs.map((roof, index) => { return { addRoof: { ...roof.addRoof, + ...moduleSelectionData.roofConstructions[index].addRoof, }, trestle: { ...roof.trestle, + ...moduleSelectionData.roofConstructions[index].trestle, }, construction: { ...roof.construction, + ...moduleSelectionData.roofConstructions[index].construction, + }, + trestleDetail: { + ...roof.trestleDetail, }, } }), diff --git a/src/hooks/module/useModuleTrestle.js b/src/hooks/module/useModuleTrestle.js index d0838b34..178054ef 100644 --- a/src/hooks/module/useModuleTrestle.js +++ b/src/hooks/module/useModuleTrestle.js @@ -64,6 +64,7 @@ export function useModuleTrestle(props) { const [ridgeMargin, setRidgeMargin] = useState(0) const [kerabaMargin, setKerabaMargin] = useState(0) const [trestleState, dispatch] = useReducer(trestleReducer, null) + const [trestleDetail, setTrestleDetail] = useState(null) useEffect(() => { const raftCodeList = findCommonCode(RAFT_BASE_CODE) @@ -90,6 +91,7 @@ export function useModuleTrestle(props) { setConstMthdList([]) setRoofBaseList([]) setConstructionList([]) + setTrestleDetail(null) return } @@ -97,17 +99,20 @@ export function useModuleTrestle(props) { if (!trestleState.constMthdCd) { setRoofBaseList([]) setConstructionList([]) + setTrestleDetail(null) return } handleSetRoofBaseList() if (!trestleState.roofBaseCd) { setConstructionList([]) + setTrestleDetail(null) return } handleSetConstructionList() if (!trestleState.constTp) { + setTrestleDetail(null) return } @@ -193,6 +198,7 @@ export function useModuleTrestle(props) { setEavesMargin(res[0].data.eaveIntvl) setRidgeMargin(res[0].data.ridgeIntvl) setKerabaMargin(res[0].data.kerabaIntvl) + setTrestleDetail(res[0].data) // dispatch({ // type: 'SET_TRESTLE_DETAIL', // roof: { @@ -208,6 +214,7 @@ export function useModuleTrestle(props) { return { trestleState, + trestleDetail, dispatch, raftBaseList, trestleList, From 2e60e848c8933deb820029cdd7561b21c936b691 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Wed, 2 Apr 2025 17:01:37 +0900 Subject: [PATCH 29/35] =?UTF-8?q?basicsetting=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/basic/BasicSetting.jsx | 22 +++++++++---------- .../floor-plan/modal/basic/step/Trestle.jsx | 5 ++++- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index 9ae90e71..57264d89 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -1,8 +1,6 @@ import { useMessage } from '@/hooks/useMessage' import WithDraggable from '@/components/common/draggable/WithDraggable' import { useContext, useEffect, useRef, useState } from 'react' -import Module from '@/components/floor-plan/modal/basic/step/Module' -import PitchModule from '@/components/floor-plan/modal/basic/step/pitch/PitchModule' import PitchPlacement from '@/components/floor-plan/modal/basic/step/pitch/PitchPlacement' import Placement from '@/components/floor-plan/modal/basic/step/Placement' import { useRecoilValue, useRecoilState } from 'recoil' @@ -37,9 +35,9 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const { closePopup } = usePopup() const [tabNum, setTabNum] = useState(1) const orientationRef = useRef(null) + const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState) + const [isManualModuleLayoutSetup, setIsManualModuleLayoutSetup] = useRecoilState(isManualModuleLayoutSetupState) const trestleRef = useRef(null) - const { initEvent } = useEvent() - const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState) const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState) const loginUserState = useRecoilValue(loginUserStore) @@ -49,6 +47,9 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const [isClosePopup, setIsClosePopup] = useState({ close: false, id: 0 }) const [checkedModules, setCheckedModules] = useRecoilState(checkedModuleState) const [roofs, setRoofs] = useState(addedRoofs) + const [manualSetupMode, setManualSetupMode] = useRecoilState(toggleManualSetupModeState) + const [layoutSetup, setLayoutSetup] = useState([{}]) + const { moduleSelectionInitParams, selectedModules, @@ -132,7 +133,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { useEffect(() => { if (basicSetting.roofSizeSet !== '3') { - manualModuleSetup(placementRef) + manualModuleSetup() } else { manualFlatroofModuleSetup(placementFlatRef) } @@ -171,7 +172,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { if (!trestleRef.current.isComplete()) { Swal.fire({ - title: getMessage('아직 멀었따'), + title: getMessage('construction.length.difference'), icon: 'warning', }) return @@ -300,7 +301,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { }, [checkedModules]) return ( - + handleClosePopup(id)} />
@@ -350,13 +351,12 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { <> {basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && ( <> - + - diff --git a/src/components/floor-plan/modal/basic/step/Trestle.jsx b/src/components/floor-plan/modal/basic/step/Trestle.jsx index dd5a7529..89724109 100644 --- a/src/components/floor-plan/modal/basic/step/Trestle.jsx +++ b/src/components/floor-plan/modal/basic/step/Trestle.jsx @@ -258,16 +258,19 @@ const Trestle = forwardRef((props, ref) => { setRoofs(newAddedRoofs) setModuleSelectionData({ ...moduleSelectionData, - roofConstructions: newAddedRoofs.map((roof) => { + roofConstructions: newAddedRoofs.map((roof, index) => { return { addRoof: { ...roof.addRoof, + ...moduleSelectionData.roofConstructions[index].addRoof, }, trestle: { ...roof.trestle, + ...moduleSelectionData.roofConstructions[index].trestle, }, construction: { ...roof.construction, + ...moduleSelectionData.roofConstructions[index].construction, }, } }), From 001143954ec510375943affd4e1b5901c7c8de27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Thu, 3 Apr 2025 10:22:14 +0900 Subject: [PATCH 30/35] =?UTF-8?q?QSelectbox=20value=20=EC=97=86=EC=9D=84?= =?UTF-8?q?=EB=95=8C=20title=20=EB=B6=80=EB=B6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/select/QSelectBox.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/common/select/QSelectBox.jsx b/src/components/common/select/QSelectBox.jsx index a027cb55..3e797071 100644 --- a/src/components/common/select/QSelectBox.jsx +++ b/src/components/common/select/QSelectBox.jsx @@ -39,7 +39,7 @@ export default function QSelectBox({ if (showKey !== '' && !value) { //value가 없으면 showKey가 있으면 우선 보여준다 // return options[0][showKey] - return title + return title !== '' ? title : getMessage('selectbox.title') } else if (showKey !== '' && value) { //value가 있으면 sourceKey와 targetKey를 비교하여 보여준다 From 6c6e5845ef0341b4125f19d16837ddcddaefbd86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Thu, 3 Apr 2025 10:22:48 +0900 Subject: [PATCH 31/35] =?UTF-8?q?=EC=A0=81=EC=84=A4=EB=9F=89,=20=ED=92=8D?= =?UTF-8?q?=EC=86=8D=20=EB=93=B1=20=EC=88=98=EC=A0=95=ED=96=88=EC=9D=84?= =?UTF-8?q?=EB=95=8C=20=EC=84=A4=EC=A0=95=ED=95=9C=20roof=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modal/basic/step/Orientation.jsx | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/src/components/floor-plan/modal/basic/step/Orientation.jsx b/src/components/floor-plan/modal/basic/step/Orientation.jsx index 59ff4f37..6dcadde8 100644 --- a/src/components/floor-plan/modal/basic/step/Orientation.jsx +++ b/src/components/floor-plan/modal/basic/step/Orientation.jsx @@ -66,12 +66,12 @@ export const Orientation = forwardRef((props, ref) => { useEffect(() => { if (selectedSurfaceType) { console.log(roughnessCodes, selectedSurfaceType) - setInputRoughness(roughnessCodes.find((code) => code.clCode === moduleSelectionData.common.illuminationTp)) + setInputRoughness(roughnessCodes.find((code) => code.clCode === managementState?.surfaceTypeValue)) } }, [selectedSurfaceType]) useEffect(() => { - if (standardWindSpeed) setInputStandardWindSpeed(windSpeedCodes.find((code) => code.clCode === moduleSelectionData.common.stdWindSpeed)) + if (standardWindSpeed) setInputStandardWindSpeed(windSpeedCodes.find((code) => code.clCode === managementState?.standardWindSpeedId)) }, [standardWindSpeed]) useEffect(() => { @@ -181,11 +181,35 @@ export const Orientation = forwardRef((props, ref) => { } const handleChangeModule = (e) => { + resetRoofs() + setSelectedModules(e) + } + + const handleChangeRoughness = (e) => { + resetRoofs() + setInputRoughness(e) + } + + const handleChangeInstallHeight = (e) => { + resetRoofs() + setInputInstallHeight(e) + } + + const handleChangeStandardWindSpeed = (e) => { + resetRoofs() + setInputStandardWindSpeed(e) + } + + const handleChangeVerticalSnowCover = (e) => { + resetRoofs() + setInputVerticalSnowCover(e) + } + + const resetRoofs = () => { const newRoofs = addedRoofs.map((roof) => { return { ...roof, lengthBase: null, - raftBaseCd: null, trestleMkrCd: null, constMthdCd: null, constTp: null, @@ -201,7 +225,6 @@ export const Orientation = forwardRef((props, ref) => { } }) setRoofs(newRoofs) - setSelectedModules(e) } return ( @@ -359,10 +382,7 @@ export const Orientation = forwardRef((props, ref) => { targetKey={'clCode'} sourceKey={'clCode'} showKey={'clCodeNm'} - onChange={(e) => { - console.log('🚀 ~ handleChangeModule ~ inputRoughness:', e) - setInputRoughness(e) - }} + onChange={(e) => handleChangeRoughness(e)} /> )}
@@ -374,7 +394,7 @@ export const Orientation = forwardRef((props, ref) => { type="text" className="input-origin block" value={inputInstallHeight} - onChange={(e) => setInputInstallHeight(e.target.value)} + onChange={(e) => handleChangeInstallHeight(e.target.value)} /> m @@ -390,10 +410,7 @@ export const Orientation = forwardRef((props, ref) => { targetKey={'clCode'} sourceKey={'clCode'} showKey={'clCodeNm'} - onChange={(e) => { - console.log('🚀 ~ handleChangeModule ~ inputStandardWindSpeed:', e) - setInputStandardWindSpeed(e) - }} + onChange={(e) => handleChangeStandardWindSpeed(e)} /> )} @@ -405,7 +422,7 @@ export const Orientation = forwardRef((props, ref) => { type="text" className="input-origin block" value={inputVerticalSnowCover} - onChange={(e) => setInputVerticalSnowCover(e.target.value)} + onChange={(e) => handleChangeVerticalSnowCover(e.target.value)} /> cm From 7d7692968912e5aeaba348383587fd7a55b46634 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Thu, 3 Apr 2025 11:23:37 +0900 Subject: [PATCH 32/35] =?UTF-8?q?=EA=B3=A0=EB=8F=84=ED=99=94=20=EC=9E=91?= =?UTF-8?q?=EC=97=85=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EC=84=A4=EC=B9=98=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../floor-plan/modal/basic/BasicSetting.jsx | 2 +- .../modal/basic/step/Orientation.jsx | 2 +- .../floor-plan/modal/basic/step/Placement.jsx | 16 +++++--- .../floor-plan/modal/basic/step/Trestle.jsx | 11 ++++-- src/hooks/module/useModuleBasicSetting.js | 39 +++++++++++++------ src/store/canvasAtom.js | 6 +++ 6 files changed, 55 insertions(+), 21 deletions(-) diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index 57264d89..3e22c508 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -95,7 +95,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { addedRoofs.map((roof, index) => { return { ...roof, - ...roofsStore[index].addRoof, + ...roofsStore[index]?.addRoof, } }), ) diff --git a/src/components/floor-plan/modal/basic/step/Orientation.jsx b/src/components/floor-plan/modal/basic/step/Orientation.jsx index 6dcadde8..2ce0d536 100644 --- a/src/components/floor-plan/modal/basic/step/Orientation.jsx +++ b/src/components/floor-plan/modal/basic/step/Orientation.jsx @@ -321,7 +321,7 @@ export const Orientation = forwardRef((props, ref) => {
- {Array.from({ length: 2 }).map((_, index) => { + {Array.from({ length: 3 }).map((_, index) => { return selectedModules && selectedModules?.itemList && selectedModules?.itemList?.length >= index + 1 ? ( - {moduleSelectionData.roofConstructions.map((item) => ( + {moduleSelectionData.roofConstructions.map((item, index) => ( - {selectedModules.itemList.map((item) => ( + {moduleRowColArray[index]?.map((item) => ( <> - - {colspan > 1 && } + + {colspan > 1 && } ))} diff --git a/src/components/floor-plan/modal/basic/step/Trestle.jsx b/src/components/floor-plan/modal/basic/step/Trestle.jsx index a7bb39d9..529b2fcb 100644 --- a/src/components/floor-plan/modal/basic/step/Trestle.jsx +++ b/src/components/floor-plan/modal/basic/step/Trestle.jsx @@ -1,5 +1,6 @@ import { GlobalDataContext } from '@/app/GlobalDataProvider' import QSelectBox from '@/components/common/select/QSelectBox' +import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' import { useModuleTrestle } from '@/hooks/module/useModuleTrestle' import { useMessage } from '@/hooks/useMessage' import { currentAngleTypeSelector, pitchTextSelector } from '@/store/canvasAtom' @@ -52,11 +53,15 @@ const Trestle = forwardRef((props, ref) => { const [selectedConstruction, setSelectedConstruction] = useState(null) const [selectedRoofBase, setSelectedRoofBase] = useState(null) const { managementState } = useContext(GlobalDataContext) + const { restoreModuleInstArea } = useModuleBasicSetting() useEffect(() => { if (roofs && !selectedRoof) { setSelectedRoof(roofs[0]) } + + //모듈 설치 영역 복구 + restoreModuleInstArea() }, [roofs]) useEffect(() => { @@ -263,16 +268,16 @@ const Trestle = forwardRef((props, ref) => { roofConstructions: newAddedRoofs.map((roof, index) => { return { addRoof: { + ...moduleSelectionData.roofConstructions[index]?.addRoof, ...roof.addRoof, - ...moduleSelectionData.roofConstructions[index].addRoof, }, trestle: { ...roof.trestle, - ...moduleSelectionData.roofConstructions[index].trestle, + ...moduleSelectionData.roofConstructions[index]?.trestle, }, construction: { ...roof.construction, - ...moduleSelectionData.roofConstructions[index].construction, + ...moduleSelectionData.roofConstructions[index]?.construction, }, trestleDetail: { ...roof.trestleDetail, diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index bb966f4e..6e8d5fce 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -10,6 +10,7 @@ import { isManualModuleSetupState, moduleSetupOptionState, toggleManualSetupModeState, + moduleRowColArrayState, } from '@/store/canvasAtom' import { rectToPolygon, polygonToTurfPolygon, calculateVisibleModuleHeight, getDegreeByChon, toFixedWithoutRounding } from '@/util/canvas-util' @@ -61,6 +62,7 @@ export function useModuleBasicSetting(tabNum) { const { drawDirectionArrow } = usePolygon() const moduleSetupOption = useRecoilValue(moduleSetupOptionState) const setManualSetupMode = useSetRecoilState(toggleManualSetupModeState) + const [moduleRowColArray, setModuleRowColArray] = useRecoilState(moduleRowColArrayState) useEffect(() => { return () => { @@ -81,6 +83,8 @@ export function useModuleBasicSetting(tabNum) { //모듈 선택에서 선택된 값들 넘어옴 const makeModuleInitArea = () => { + console.log('moduleSelectionData', moduleSelectionData) + if (isObjectNotEmpty(moduleSelectionData) && tabNum === 3) { if (canvasSetting.roofSizeSet !== '3') { const common = moduleSelectionData.common @@ -90,11 +94,11 @@ export function useModuleBasicSetting(tabNum) { const listParams = roofConstructions.map((item) => { return { ...common, - roofMatlCd: item.trestle.roofMatlCd, - trestleMkrCd: item.trestle.trestleMkrCd, - constMthdCd: item.trestle.constMthdCd, - roofBaseCd: item.trestle.roofBaseCd, - constTp: item.construction.constTp, + roofMatlCd: item.addRoof.roofMatlCd, + trestleMkrCd: item.addRoof.trestleMkrCd, + constMthdCd: item.addRoof.constMthdCd, + roofBaseCd: item.addRoof.roofBaseCd, + constTp: item.addRoof.constTp, mixMatlNo: selectedModules.mixMatlNo, roofPitch: item.addRoof.hajebichi ? item.addRoof.hajebichi : 0, inclCd: String(item.addRoof.pitch), @@ -140,6 +144,7 @@ export function useModuleBasicSetting(tabNum) { //가대 상세 데이터 들어오면 실행 useEffect(() => { if (trestleDetailList.length > 0) { + let rowColArray = [] //지붕을 가져옴 canvas .getObjects() @@ -147,26 +152,38 @@ export function useModuleBasicSetting(tabNum) { .forEach((roof) => { if (!roof.roofMaterial) return const roofIndex = roof.roofMaterial.index //지붕의 지붕재의 순번 + + console.log('moduleSelectionData', moduleSelectionData) + trestleDetailList.forEach((detail) => { if (detail.data !== null) { + const moduleRowArray = [] if (Number(detail.data.roofIndex) === roofIndex) { //roof에 상세 데이터 추가 - roof.set({ trestleDetail: detail.data, stroke: roofOutlineColor(roofIndex), strokeWidth: 7, }) + + const offsetObjects = moduleSelectionData.roofConstructions.find((item) => item.addRoof.index === roofIndex) + + console.log('offsetObjects', offsetObjects) + roof.lines.forEach((line) => { - line.attributes = { ...line.attributes, offset: getOffset(detail.data, line.attributes.type) } + line.attributes = { ...line.attributes, offset: getOffset(offsetObjects.addRoof, line.attributes.type) } }) //배치면 설치 영역 makeModuleInstArea(roof, detail.data) - //surface에 상세 데이터 추가 } + detail.data.module.forEach((module) => { + moduleRowArray.push({ moduleMaxRows: module.moduleMaxRows, mixModuleMaxRows: module.mixModuleMaxRows }) + }) + rowColArray.push(moduleRowArray) } }) }) + setModuleRowColArray(rowColArray) } }, [trestleDetailList]) @@ -185,12 +202,12 @@ export function useModuleBasicSetting(tabNum) { const getOffset = (data, type) => { switch (type) { case LINE_TYPE.WALLLINE.EAVES: - return data.eaveIntvl / 10 + return data.eavesMargin / 10 case LINE_TYPE.WALLLINE.GABLE: - return data.kerabaIntvl / 10 + return data.kerabaMargin / 10 case LINE_TYPE.SUBLINE.RIDGE: case LINE_TYPE.WALLLINE.SHED: - return data.ridgeIntvl / 10 + return data.ridgeMargin / 10 default: return 200 / 10 } diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js index 0679938f..c8bb1ad0 100644 --- a/src/store/canvasAtom.js +++ b/src/store/canvasAtom.js @@ -402,3 +402,9 @@ export const toggleManualSetupModeState = atom({ key: 'toggleManualSetupModeState', default: '', }) + +export const moduleRowColArrayState = atom({ + key: 'moduleRowColArrayState', + default: [], + dangerouslyAllowMutability: true, +}) From f32e77214127ce3bfdcb79a4ee6c16905bd25d2b Mon Sep 17 00:00:00 2001 From: yjnoh Date: Thu, 3 Apr 2025 13:36:46 +0900 Subject: [PATCH 33/35] =?UTF-8?q?=EB=AA=A8=EB=93=88=20=ED=91=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useModuleBasicSetting.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 6e8d5fce..6aea3d59 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -153,11 +153,8 @@ export function useModuleBasicSetting(tabNum) { if (!roof.roofMaterial) return const roofIndex = roof.roofMaterial.index //지붕의 지붕재의 순번 - console.log('moduleSelectionData', moduleSelectionData) - trestleDetailList.forEach((detail) => { if (detail.data !== null) { - const moduleRowArray = [] if (Number(detail.data.roofIndex) === roofIndex) { //roof에 상세 데이터 추가 roof.set({ @@ -168,21 +165,23 @@ export function useModuleBasicSetting(tabNum) { const offsetObjects = moduleSelectionData.roofConstructions.find((item) => item.addRoof.index === roofIndex) - console.log('offsetObjects', offsetObjects) - roof.lines.forEach((line) => { line.attributes = { ...line.attributes, offset: getOffset(offsetObjects.addRoof, line.attributes.type) } }) //배치면 설치 영역 makeModuleInstArea(roof, detail.data) } - detail.data.module.forEach((module) => { - moduleRowArray.push({ moduleMaxRows: module.moduleMaxRows, mixModuleMaxRows: module.mixModuleMaxRows }) - }) - rowColArray.push(moduleRowArray) } }) }) + + trestleDetailList.forEach((detail) => { + const moduleRowArray = [] + detail.data.module.forEach((module) => { + moduleRowArray.push({ moduleMaxRows: module.moduleMaxRows, mixModuleMaxRows: module.mixModuleMaxRows }) + }) + rowColArray.push(moduleRowArray) + }) setModuleRowColArray(rowColArray) } }, [trestleDetailList]) From aa2685e5585527cea09f3fa4a6dd6d65587908e1 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Thu, 3 Apr 2025 14:33:54 +0900 Subject: [PATCH 34/35] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83?= =?UTF-8?q?=EC=84=A4=EC=B9=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useModuleBasicSetting.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 6aea3d59..7b2bc999 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -1277,6 +1277,16 @@ export function useModuleBasicSetting(tabNum) { }) addCanvasMouseEventListener('mouse:up', (e) => { + if (trestlePolygon.modules.length > 0) { + //이미 설치된 모듈중에 한개만 가져옴 + const mixAsgYn = trestlePolygon.modules[0].moduleInfo.mixAsgYn + //현재 체크된 모듈기준으로 혼합가능인지 확인 Y === Y, N === N 일때만 설치 가능 + if (checkedModule[0].mixAsgYn !== mixAsgYn) { + swalFire({ text: getMessage('modal.module.basic.setting.module.placement.mix.asg.yn.error') }) + return + } + } + if (!inside) return //입력받은 값의 합 From 3f40725647cf742e28e26a9c4cef811bbd6eb95c Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Thu, 3 Apr 2025 16:28:58 +0900 Subject: [PATCH 35/35] =?UTF-8?q?3=EC=A4=91=20=EB=A9=80=ED=8B=B0=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EB=8C=80=EC=9D=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/module/useTrestle.js | 96 ++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 5 deletions(-) diff --git a/src/hooks/module/useTrestle.js b/src/hooks/module/useTrestle.js index a584876c..963c4cf7 100644 --- a/src/hooks/module/useTrestle.js +++ b/src/hooks/module/useTrestle.js @@ -370,7 +370,20 @@ export const useTrestle = () => { rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp && rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) ) - } else { + } else if (leftRowsInfo.rowsInfo.length >= 2) { + //C1C2C3인 경우 + if (rack.value.moduleTpCd.length === 6) { + // 변환 C1C2만 있는경우 C3 0개로 추가해준다. + let newLeftRowsInfo = normalizeModules(rack.value.moduleTpCd, leftRowsInfo) + + return ( + rack.value.moduleTpCd === newLeftRowsInfo.moduleTotalTp && + rack.value.moduleRows === newLeftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) && + Number(rack.value.moduleTpRows1) === newLeftRowsInfo.rowsInfo[0].count && + Number(rack.value.moduleTpRows2) === newLeftRowsInfo.rowsInfo[1].count && + Number(rack.value.moduleTpRows3) === newLeftRowsInfo.rowsInfo[2].count + ) + } return ( rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp && rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) && @@ -387,7 +400,19 @@ export const useTrestle = () => { rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp && rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) ) - } else { + } else if (rightRowsInfo.rowsInfo.length === 2) { + if (rack.value.moduleTpCd.length === 6) { + // 변환 C1C2만 있는경우 C3 0개로 추가해준다. + let newRightRowsInfo = normalizeModules(rack.value.moduleTpCd, rightRowsInfo) + + return ( + rack.value.moduleTpCd === newRightRowsInfo.moduleTotalTp && + rack.value.moduleRows === newRightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) && + Number(rack.value.moduleTpRows1) === newRightRowsInfo.rowsInfo[0].count && + Number(rack.value.moduleTpRows2) === newRightRowsInfo.rowsInfo[1].count && + Number(rack.value.moduleTpRows3) === newRightRowsInfo.rowsInfo[2].count + ) + } return ( rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp && rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) && @@ -404,7 +429,19 @@ export const useTrestle = () => { rack.value.moduleTpCd === centerRowsInfo.moduleTotalTp && rack.value.moduleRows === centerRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) ) - } else { + } else if (centerRowsInfo.rowsInfo.length === 2) { + if (rack.value.moduleTpCd.length === 6) { + // 변환 C1C2만 있는경우 C3 0개로 추가해준다. + let newCenterRowsInfo = normalizeModules(rack.value.moduleTpCd, centerRowsInfo) + + return ( + rack.value.moduleTpCd === newCenterRowsInfo.moduleTotalTp && + rack.value.moduleRows === newCenterRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) && + Number(rack.value.moduleTpRows1) === newCenterRowsInfo.rowsInfo[0].count && + Number(rack.value.moduleTpRows2) === newCenterRowsInfo.rowsInfo[1].count && + Number(rack.value.moduleTpRows3) === newCenterRowsInfo.rowsInfo[2].count + ) + } return ( rack.value.moduleTpCd === centerRowsInfo.moduleTotalTp && rack.value.moduleRows === centerRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) && @@ -499,7 +536,19 @@ export const useTrestle = () => { rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp && rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) ) - } else { + } else if (leftRowsInfo.rowsInfo.length === 2) { + if (rack.value.moduleTpCd.length === 6) { + // 변환 C1C2만 있는경우 C3 0개로 추가해준다. + let newLeftRowsInfo = normalizeModules(rack.value.moduleTpCd, leftRowsInfo) + + return ( + rack.value.moduleTpCd === newLeftRowsInfo.moduleTotalTp && + rack.value.moduleRows === newLeftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) && + Number(rack.value.moduleTpRows1) === newLeftRowsInfo.rowsInfo[0].count && + Number(rack.value.moduleTpRows2) === newLeftRowsInfo.rowsInfo[1].count && + Number(rack.value.moduleTpRows3) === newLeftRowsInfo.rowsInfo[2].count + ) + } return ( rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp && rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) && @@ -575,7 +624,19 @@ export const useTrestle = () => { rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp && rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) ) - } else { + } else if (rightRowsInfo.rowsInfo.length === 2) { + if (rack.value.moduleTpCd.length === 6) { + // 변환 C1C2만 있는경우 C3 0개로 추가해준다. + let newRightRowsInfo = normalizeModules(rack.value.moduleTpCd, rightRowsInfo) + + return ( + rack.value.moduleTpCd === newRightRowsInfo.moduleTotalTp && + rack.value.moduleRows === newRightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) && + Number(rack.value.moduleTpRows1) === newRightRowsInfo.rowsInfo[0].count && + Number(rack.value.moduleTpRows2) === newRightRowsInfo.rowsInfo[1].count && + Number(rack.value.moduleTpRows3) === newRightRowsInfo.rowsInfo[2].count + ) + } return ( rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp && rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) && @@ -635,6 +696,31 @@ export const useTrestle = () => { return { moduleTotalTp, rowsInfo } } + function normalizeModules(rackTpCd, data) { + // rackTpCd를 숫자를 기준으로 자른다. + const allModules = rackTpCd.match(/[A-Za-z]+\d+/g) || [] // 모든 모듈 유형 + + // 현재 존재하는 모듈 유형을 추출 + const existingModules = data.rowsInfo.map((row) => row.moduleTpCd) + + const result = { ...data, rowsInfo: [...data.rowsInfo] } + + // 없는 모듈을 추가 (count: 0) + allModules.forEach((module) => { + if (!existingModules.includes(module)) { + result.rowsInfo.push({ moduleTpCd: module, count: 0 }) + } + }) + + // rowsInfo를 C1, C2, C3 순서로 정렬 + result.rowsInfo.sort((a, b) => allModules.indexOf(a.moduleTpCd) - allModules.indexOf(b.moduleTpCd)) + + // moduleTotalTp를 C1C2C3로 설정 + result.moduleTotalTp = allModules.join('') + + return result + } + // itemList 조회 후 estimateParam에 저장 const getEstimateData = async () => { const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx index b7ba409e..726d3c24 100644 --- a/src/components/floor-plan/modal/basic/step/Placement.jsx +++ b/src/components/floor-plan/modal/basic/step/Placement.jsx @@ -5,6 +5,7 @@ import { checkedModuleState, isManualModuleLayoutSetupState, isManualModuleSetupState, + moduleRowColArrayState, moduleSetupOptionState, toggleManualSetupModeState, } from '@/store/canvasAtom' @@ -36,6 +37,7 @@ const Placement = forwardRef((props, refs) => { const resetModuleSetupOption = useResetRecoilState(moduleSetupOptionState) const [colspan, setColspan] = useState(1) + const [moduleRowColArray, setModuleRowColArray] = useRecoilState(moduleRowColArrayState) //모듈 배치면 생성 useEffect(() => { @@ -62,6 +64,10 @@ const Placement = forwardRef((props, refs) => { } }, []) + useEffect(() => { + console.log('moduleRowColArray', moduleRowColArray) + }, [moduleRowColArray]) + //최초 지입시 체크 useEffect(() => { if (isObjectNotEmpty(moduleSelectionData)) { @@ -342,18 +348,18 @@ const Placement = forwardRef((props, refs) => {
- + {item.addRoof.roofMatlNmJp}
75{item.moduleMaxRows}{item.mixModuleMaxRows}