diff --git a/docs/2025-02-13_Qcell_회의.txt b/docs/2025-02-13_Qcell_회의.txt new file mode 100644 index 00000000..3aa60619 --- /dev/null +++ b/docs/2025-02-13_Qcell_회의.txt @@ -0,0 +1,36 @@ +1. 회로할당 -> + 수동 할당시 와트수 소수점 노출 + +2. 모듈 -> + 멀티 모듈일시 모듈 순번에 따라 배치면 그리기 적용해야됨 + 멀티 모듈시 모듈 간격 붙여서 조정 + +3. contextMenu -> + 한번 클릭 후 contextMenu 호출 재호출시 화면에 안나옴 + +4. 수치 입력시 -> + 반각?전각? 입력 처리 필요???????????????? + +5. 지도 호출 -> + 최초 호출 후 삭제, 재호출 안됨 + +6. 도면 화면 -> + redo, undo 제거 + +7. 모든 배치면 -> + 배치면 외각선 굵기 조절 + +8. 패브릭 캔버스 -> + 줌, 확대 기능 선택 오류 수정 필요 + +9. 모듈선택 -> + 모듈 선택 페이지 단계 변경 예정정(현업 화면에 너무 크게 적용) + +10. 외벽선 삭제시 수치 삭제 처리 필요 + +11. 모듈 삭제 후 재 설치시 모듈이 겹친다고 오류남 + +12. 모듈 수동시 첫번째는 아무데나 놓을 수 있고 두번째 부터는 무조건 주변에 모듈이 있어야 한다는 조건이 있어야 한다고 함 + +13. 견적서 다운로드 이미지 정비율이 아님 + diff --git a/docs/2025-02-14_Qcell_회의.txt b/docs/2025-02-14_Qcell_회의.txt new file mode 100644 index 00000000..5add84f4 --- /dev/null +++ b/docs/2025-02-14_Qcell_회의.txt @@ -0,0 +1,10 @@ +1. 오픈 예정일정 -> 신상품 7월에 오픈 그와 같이 하는게 어떻냐? + +2. 웹 상에서 단축키 모드 추가 + +3. 형이동 동선이동 작업 해보겠다. + +4. 모듈 작업 확정 (좌하, 우상) + +5. 발전 시뮬레이션 qsp에 이관 작업(유지보수) + diff --git a/src/components/common/context-menu/QContextMenu.jsx b/src/components/common/context-menu/QContextMenu.jsx index 63160eda..955a3e4b 100644 --- a/src/components/common/context-menu/QContextMenu.jsx +++ b/src/components/common/context-menu/QContextMenu.jsx @@ -40,7 +40,7 @@ export default function QContextMenu(props) { if (!contextRef.current) return const handleContextMenu = (e) => { - // e.preventDefault() //기존 contextmenu 막고 + e.preventDefault() //기존 contextmenu 막고 if (tempGridMode) return const position = { x: window.innerWidth / 2 < e.pageX ? e.pageX - 240 : e.pageX, diff --git a/src/components/estimate/popup/EstimateCopyPop.jsx b/src/components/estimate/popup/EstimateCopyPop.jsx index 6ff2e540..3bc25c74 100644 --- a/src/components/estimate/popup/EstimateCopyPop.jsx +++ b/src/components/estimate/popup/EstimateCopyPop.jsx @@ -296,7 +296,7 @@ export default function EstimateCopyPop({ planNo, setEstimateCopyPopupOpen }) { type="button" className="btn-origin navy mr5" onClick={() => { - handleEstimateCopy(sendPlanNo, copyReceiveUser, saleStoreId, otherSaleStoreId) + handleEstimateCopy(sendPlanNo, copyReceiveUser, saleStoreId, otherSaleStoreId, setEstimateCopyPopupOpen) }} > {getMessage('estimate.detail.estimateCopyPopup.copyBtn')} diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index df43d7bb..1ed413cf 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -221,6 +221,7 @@ export default function CanvasMenu(props) { await reloadCanvasStatus(objectNo, pid) break case 5: + setIsGlobalLoading(true) promiseGet({ url: `/api/estimate/${objectNo}/${selectedPlan.planNo}/detail` }).then((res) => { if (res.status === 200) { const estimateDetail = res.data @@ -230,6 +231,9 @@ export default function CanvasMenu(props) { setFloorPlanObjectNo({ floorPlanObjectNo: objectNo }) setIsGlobalLoading(false) router.push(`/floor-plan/estimate/${menu.index}?pid=${selectedPlan.planNo}&objectNo=${objectNo}`) + if (pathname === '/floor-plan/estimate/5') { + setIsGlobalLoading(false) + } } else { setIsGlobalLoading(false) swalFire({ text: getMessage('estimate.menu.move.valid1') }) @@ -239,7 +243,6 @@ export default function CanvasMenu(props) { break case 6: setIsGlobalLoading(true) - //로딩바해제는 발전시뮬레이션 조회쪽에서(Simulator.jsx) setIsGlobalLoading(false) promiseGet({ url: `/api/estimate/${objectNo}/${selectedPlan.planNo}/detail` }).then((res) => { if (res.status === 200) { const estimateDetail = res.data @@ -247,7 +250,9 @@ export default function CanvasMenu(props) { setMenuNumber(menu.index) setCurrentMenu(menu.title) router.push(`/floor-plan/simulator/${menu.index}?pid=${selectedPlan.planNo}&objectNo=${objectNo}`) - setIsGlobalLoading(false) + if (pathname === '/floor-plan/simulator/6') { + setIsGlobalLoading(false) + } } else { setIsGlobalLoading(false) swalFire({ text: getMessage('simulator.menu.move.valid1') }) diff --git a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx index a7f26838..681a425d 100644 --- a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx @@ -1,5 +1,5 @@ import WithDraggable from '@/components/common/draggable/WithDraggable' -import { useState, useEffect, useContext } from 'react' +import { useState, useEffect, useContext, useRef } from 'react' import PowerConditionalSelect from '@/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect' import StepUp from '@/components/floor-plan/modal/circuitTrestle/step/StepUp' import { useMessage } from '@/hooks/useMessage' @@ -33,7 +33,7 @@ const ALLOCATION_TYPE = { export default function CircuitTrestleSetting({ id }) { const { getMessage } = useMessage() const { closePopup } = usePopup() - const { apply, setViewCircuitNumberTexts, getEstimateData } = useTrestle() + const { apply, setViewCircuitNumberTexts, getEstimateData, clear: clearTrestle } = useTrestle() const { swalFire } = useSwal() const { saveEstimate } = useEstimate() const canvas = useRecoilValue(canvasState) @@ -43,7 +43,7 @@ export default function CircuitTrestleSetting({ id }) { const [circuitAllocationType, setCircuitAllocationType] = useState(1) const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext) const selectedModules = useRecoilValue(selectedModuleState) - const { getPcsAutoRecommendList, getPcsVoltageChk, getPcsVoltageStepUpList } = useMasterController() + const { getPcsAutoRecommendList, getPcsVoltageChk, getPcsVoltageStepUpList, getPcsManualConfChk } = useMasterController() // 회로할당(승합설정)에서 선택된 값들을 저장할 상태 추가 const [selectedStepUpValues, setSelectedStepUpValues] = useState({}) @@ -53,10 +53,9 @@ export default function CircuitTrestleSetting({ id }) { const [stepUpListData, setStepUpListData] = useState([]) const [seletedOption, setSeletedOption] = useState(null) const { setModuleStatisticsData } = useCircuitTrestle() - const { handleCanvasToPng } = useImgLoader() const { saveCanvas } = usePlan() - + const passivityCircuitAllocationRef = useRef() const { setIsGlobalLoading } = useContext(QcastContext) const { @@ -385,6 +384,12 @@ export default function CircuitTrestleSetting({ id }) { obj.pcsItemId = null obj.circuitNumber = null }) + setSelectedModels( + JSON.parse(JSON.stringify(selectedModels)).map((model) => { + model.isUsed = false + return model + }), + ) if (allocationType === ALLOCATION_TYPE.PASSIVITY) { setAllocationType(ALLOCATION_TYPE.AUTO) @@ -392,6 +397,7 @@ export default function CircuitTrestleSetting({ id }) { } else { setTabNum(1) } + clearTrestle() canvas.renderAll() setModuleStatisticsData() @@ -479,16 +485,18 @@ export default function CircuitTrestleSetting({ id }) { } const handleStepUp = () => { - const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit) - if (notAllocationModules.length > 0) { - swalFire({ - title: getMessage('not.allocation.exist.module'), - type: 'alert', - }) - return - } else { - setTabNum(2) - } + handlePassivityAllocationCkeck() + // const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit) + // if (notAllocationModules.length > 0) { + // swalFire({ + // title: getMessage('not.allocation.exist.module'), + // type: 'alert', + // }) + // return + // } else { + // passivityCircuitAllocationRef.current.onApply() + // setTabNum(2) + // } } // 닫기 버튼 클릭 시 처리하는 함수 추가 @@ -510,6 +518,83 @@ export default function CircuitTrestleSetting({ id }) { closePopup(id) } + const handlePassivityAllocationCkeck = () => { + let pcsCount = {} + let result = {} + canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE) + .forEach((module) => { + const circuitNumber = module.circuitNumber.replace(/[()]/g, '') + pcsCount[circuitNumber] = (pcsCount[circuitNumber] || 0) + 1 + }) + for (const key in pcsCount) { + const firstPart = key.split('-')[0] // '-' 기준으로 첫 번째 부분을 추출 + const value = pcsCount[key] + + // 그룹이 없으면 초기화 + if (!result[firstPart]) { + result[firstPart] = { maxValue: value, count: 1 } + } else { + // 이미 그룹이 있으면 큰 값으로 갱신, count는 증가 + result[firstPart].maxValue = Math.max(result[firstPart].maxValue, value) + result[firstPart].count += 1 + } + } + const params = { + ...getOptYn(), + useModuleItemList: getUseModuleItemList(), + roofSurfaceList: getRoofSurfaceList(), + pcsItemList: selectedModels.map((model, index) => { + return { + pcsMkrCd: model.pcsMkrCd, + pcsSerCd: model.pcsSerCd, + itemId: model.itemId, + itemNm: model.itemNm, + goodsNo: model.goodsNo, + serQtyList: [ + { + serQty: result[index + 1].maxValue, + paralQty: result[index + 1].count, + rmdYn: 'Y', + usePossYn: 'Y', + roofSurfaceList: canvas + .getObjects() + .filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name && obj?.modules.length > 0) + .map((surface) => { + return { + roofSurfaceId: surface.id, + roofSurface: surface.direction, + roofSurfaceIncl: +canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].pitch, + moduleList: surface.modules.map((module) => { + return { + itemId: module.moduleInfo.itemId, + circuit: module.circuitNumber, + pcsItemId: module.pcsItemId, + } + }), + } + }), + }, + ], + } + }), + } + + getPcsManualConfChk(params).then((res) => { + if (res?.resultCode === 'E') { + swalFire({ + text: res.resultMsg, + type: 'alert', + icon: 'warning', + }) + return + } else { + setTabNum(2) + } + }) + } + return (
@@ -531,7 +616,9 @@ export default function CircuitTrestleSetting({ id }) {
{tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO && } - {tabNum === 1 && allocationType === ALLOCATION_TYPE.PASSIVITY && } + {tabNum === 1 && allocationType === ALLOCATION_TYPE.PASSIVITY && ( + + )} {tabNum === 2 && } {tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO && (
diff --git a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx index 36fdad35..a526f05a 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx @@ -15,6 +15,7 @@ import { useRecoilState, useRecoilValue } from 'recoil' export default function PassivityCircuitAllocation(props) { const { + setTabNum, selectedModels, setSelectedModels, getOptYn: getApiProps, @@ -88,14 +89,14 @@ export default function PassivityCircuitAllocation(props) { ] if (!circuitNumber || circuitNumber === 0) { swalFire({ - text: '회로번호를 1 이상입력해주세요.', + text: getMessage('module.circuit.minimun.error'), type: 'alert', icon: 'warning', }) return } else if (targetModules.length === 0) { swalFire({ - text: '모듈을 선택해주세요.', + text: getMessage('module.not.found'), type: 'alert', icon: 'warning', }) @@ -113,7 +114,7 @@ export default function PassivityCircuitAllocation(props) { }) if (result) { swalFire({ - text: '회로 번호가 같은 다른 파워 컨디셔너 모듈이 있습니다. 다른 회로 번호를 설정하십시오.', + text: getMessage('module.already.exist.error'), type: 'alert', icon: 'warning', }) @@ -185,7 +186,30 @@ export default function PassivityCircuitAllocation(props) { }), } }) + let pcsCount = {} + let result = {} + canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE) + .forEach((module) => { + if (module.circuitNumber) { + const circuitNumber = module.circuitNumber.replace(/[()]/g, '') + pcsCount[circuitNumber] = (pcsCount[circuitNumber] || 0) + 1 + } + }) + for (const key in pcsCount) { + const firstPart = key.split('-')[0] // '-' 기준으로 첫 번째 부분을 추출 + const value = pcsCount[key] + // 그룹이 없으면 초기화 + if (!result[firstPart]) { + result[firstPart] = { maxValue: value, count: 1 } + } else { + // 이미 그룹이 있으면 큰 값으로 갱신, count는 증가 + result[firstPart].maxValue = Math.max(result[firstPart].maxValue, value) + result[firstPart].count += 1 + } + } const usedPcses = pcsList.filter((model) => model.isUsed) const pcsItemList = usedPcses.map((model, index) => { return { @@ -196,8 +220,8 @@ export default function PassivityCircuitAllocation(props) { goodsNo: model.goodsNo, serQtyList: [ { - serQty: targetModules.length, - paralQty: uniqueCircuitNumbers.length, + serQty: result[index + 1].maxValue, + paralQty: result[index + 1].count, rmdYn: 'Y', usePossYn: 'Y', roofSurfaceList: roofSurfaceList, @@ -305,6 +329,173 @@ export default function PassivityCircuitAllocation(props) { }) } + const onApply = () => { + let uniqueCircuitNumbers = [ + ...new Set( + canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE && obj.circuitNumber) + .map((obj) => obj.circuitNumber), + ), + ] + if (!circuitNumber || circuitNumber === 0) { + swalFire({ + text: getMessage('module.circuit.minimun.error'), + type: 'alert', + icon: 'warning', + }) + return + } else if (targetModules.length === 0) { + swalFire({ + text: getMessage('module.not.found'), + type: 'alert', + icon: 'warning', + }) + return + } else if (selectedModels.length > 1) { + let result = false + + uniqueCircuitNumbers.forEach((number) => { + if ( + number.split('-')[1] === circuitNumber + ')' && + number.split('-')[0] !== '(' + (selectedModels.findIndex((model) => model.id === selectedPcs.id) + 1) + ) { + result = true + } + }) + if (result) { + swalFire({ + text: getMessage('module.already.exist.error'), + type: 'alert', + icon: 'warning', + }) + return + } + } + + let tempSelectedPcs = { ...selectedPcs } + canvas.discardActiveObject() + canvas + .getObjects() + .filter((obj) => targetModules.includes(obj.id)) + .forEach((obj) => { + if (obj.circuit) { + canvas.remove(obj.circuit) + } + const moduleCircuitText = new fabric.Text(getCircuitNumber(), { + left: obj.left + obj.width / 2, + top: obj.top + obj.height / 2, + fontFamily: circuitNumberText.fontFamily.value, + fontWeight: circuitNumberText.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal', + fontStyle: circuitNumberText.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal', + fontSize: circuitNumberText.fontSize.value, + fill: circuitNumberText.fontColor.value, + width: obj.width, + height: obj.height, + textAlign: 'center', + originX: 'center', + originY: 'center', + name: 'circuitNumber', + selectable: false, + parentId: obj.id, + circuitInfo: selectedPcs, + visible: isDisplayCircuitNumber, + }) + obj.set({ + strokeWidth: 0.3, + }) + obj.pcsItemId = selectedPcs.itemId + obj.pcsItemCode = selectedPcs.id + obj.circuit = moduleCircuitText + obj.circuitNumber = getCircuitNumber() + tempSelectedPcs.used = true + setSelectedPcs(tempSelectedPcs) + canvas.add(moduleCircuitText) + }) + + let pcsList = JSON.parse(JSON.stringify(selectedModels)).map((model) => { + if (model.id === selectedPcs.id) { + model.isUsed = true + } + return model + }) + + const roofSurfaceList = canvas + .getObjects() + .filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name && obj?.modules.length > 0) + .map((surface) => { + return { + roofSurfaceId: surface.id, + roofSurface: surface.direction, + roofSurfaceIncl: +canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].pitch, + moduleList: surface.modules.map((module) => { + return { + itemId: module.moduleInfo.itemId, + circuit: module.circuitNumber, + pcsItemId: module.pcsItemId, + } + }), + } + }) + const usedPcses = pcsList.filter((model) => model.isUsed) + const pcsItemList = usedPcses.map((model, index) => { + return { + pcsMkrCd: model.pcsMkrCd, + pcsSerCd: model.pcsSerCd, + itemId: model.itemId, + itemNm: model.itemNm, + goodsNo: model.goodsNo, + serQtyList: [ + { + serQty: targetModules.length, + paralQty: uniqueCircuitNumbers.length, + rmdYn: 'Y', + usePossYn: 'Y', + roofSurfaceList: roofSurfaceList, + }, + ], + } + }) + + const params = { + ...getApiProps(), + useModuleItemList: getSelectedModuleList(), + pcsItemList: pcsItemList, + } + + getPcsManualConfChk(params).then((res) => { + if (res?.resultCode === 'E') { + swalFire({ + text: res.resultMsg, + type: 'alert', + icon: 'warning', + confirmFn: () => { + const circuitNumbers = canvas.getObjects().filter((obj) => obj.name === 'circuitNumber' && targetModules.includes(obj.parentId)) + canvas.remove(...circuitNumbers) + canvas + .getObjects() + .filter((obj) => obj.name === 'module' && targetModules.includes(obj.id)) + .forEach((obj) => { + obj.pcsItemId = null + obj.circuit = null + obj.circuitNumber = null + }) + canvas.renderAll() + }, + }) + setSelectedPcs({ ...selectedPcs, used: false }) + setTargetModules([]) + return + } + + setSelectedModels(pcsList) + + setTargetModules([]) + setModuleStatisticsData() + setTabNum(2) + }) + } + return ( <>
diff --git a/src/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty.jsx b/src/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty.jsx index 00f00e80..cd20adf3 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty.jsx @@ -7,10 +7,14 @@ import { LINE_TYPE } from '@/common/common' import { useSwal } from '@/hooks/useSwal' export default function PlacementSurfaceLineProperty(props) { - const { id, pos = { x: 50, y: 230 }, roof } = props + const { id, pos = { x: 50, y: 230 }, roof, setIsHidden } = props const { closePopup } = usePopup() // const { handleSetEaves, handleSetGable, handleRollback, handleFix, closeModal } = usePropertiesSetting(id) - const { roofLinesInit, handleSetRidge, handleSetEaves, handleSetGable, handleRollback, handleFix } = useRoofLinePropertySetting(id, roof) + const { roofLinesInit, handleSetRidge, handleSetEaves, handleSetGable, handleRollback, handleFix } = useRoofLinePropertySetting({ + id, + roof, + setIsHidden, + }) const { getMessage } = useMessage() const { swalFire } = useSwal() @@ -29,6 +33,10 @@ export default function PlacementSurfaceLineProperty(props) { } closePopup(id) + + if (setIsHidden) { + setIsHidden(false) + } } return ( diff --git a/src/hooks/floorPlan/estimate/useEstimateController.js b/src/hooks/floorPlan/estimate/useEstimateController.js index 10d90416..4a3bf0c2 100644 --- a/src/hooks/floorPlan/estimate/useEstimateController.js +++ b/src/hooks/floorPlan/estimate/useEstimateController.js @@ -83,6 +83,10 @@ export const useEstimateController = (planNo, flag) => { res.data.pkgAsp = roundedNumber.toString() } setEstimateContextState(res.data) + } else { + swalFire({ text: getMessage('stuff.detail.header.notExistObjectNo'), type: 'alert', icon: 'error' }) + setIsLoading(true) + setIsGlobalLoading(false) } } }) @@ -90,8 +94,7 @@ export const useEstimateController = (planNo, flag) => { setIsGlobalLoading(false) } catch (error) { console.error('견적서 상세조회 Error: ', error) - - swalFire({ text: getMessage('estimate.menu.move.valid1') }) + swalFire({ text: getMessage('stuff.detail.header.notExistObjectNo'), type: 'alert', icon: 'error' }) setIsLoading(true) setIsGlobalLoading(false) } @@ -415,7 +418,7 @@ export const useEstimateController = (planNo, flag) => { * (견적서 번호(estimateData.docNo)가 생성된 이후 버튼 활성화 ) * T01관리자 계정 및 1차판매점에게만 제공 */ - const handleEstimateCopy = async (sendPlanNo, copyReceiveUser, saleStoreId, otherSaleStoreId) => { + const handleEstimateCopy = async (sendPlanNo, copyReceiveUser, saleStoreId, otherSaleStoreId, setEstimateCopyPopupOpen) => { //todo: 추후 YJSS가 다시 나타날 경우 아래 swalFire 제거 필요 if (estimateData.estimateType === 'YJSS') { return swalFire({ text: getMessage('estimate.detail.save.requiredEstimateType'), type: 'alert', icon: 'warning' }) @@ -455,6 +458,7 @@ export const useEstimateController = (planNo, flag) => { text: getMessage('estimate.detail.estimateCopyPopup.copy.alertMessage'), type: 'alert', confirmFn: () => { + setEstimateCopyPopupOpen(false) //팝업닫고 router.push(`/management/stuff/detail?objectNo=${newObjectNo.toString()}`, { scroll: false }) }, }) diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 74158c1f..3c27393b 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -448,7 +448,7 @@ export function useModuleBasicSetting(tabNum) { let tmpHeight = flowDirection === 'south' || flowDirection === 'north' ? moduleHeight : moduleWidth let { width, height } = - canvasSetting.roofSizeSet === '1' + canvasSetting.roofSizeSet == '1' ? calculateVisibleModuleHeight(tmpWidth, tmpHeight, getDegreeByChon(moduleSetupSurfaces[i].roofMaterial.pitch), flowDirection) : { width: tmpWidth, height: tmpHeight } @@ -568,14 +568,14 @@ export function useModuleBasicSetting(tabNum) { 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 - holdCellCenterY) < cellSnapDistance) { + tempModule.top = holdCellCenterY + } + //아랫쪽 -> 가운데 + if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) { + tempModule.top = holdCellCenterY - height + } }) } @@ -842,6 +842,7 @@ export function useModuleBasicSetting(tabNum) { return turf.booleanContains(turfModuleSetupSurface, squarePolygon) || turf.booleanWithin(squarePolygon, turfModuleSetupSurface) } + //흐름 방향이 남쪽(아래) const downFlowSetupModule = ( surfaceMaxLines, maxLengthLine, @@ -854,67 +855,133 @@ export function useModuleBasicSetting(tabNum) { ) => { let setupModule = [] - checkedModule.forEach((module, index) => { - const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) + const trestleDetailData = moduleSetupSurface.trestleDetail + const moduleMaxCols = trestleDetailData.moduleMaxCols // 모듈 최대 가로 설치 갯수 - const flowLines = getFlowLines(moduleSetupSurface, height) - //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 - // let startPoint = flowLines.bottom + let installedLastHeightCoord = 0 //마지막으로 설치된 모듈의 좌표 + let installedModuleHeightCount = 0 //마지막으로 설치된 모듈의 카운트 + let isChidoriLine = false + let flowLines - let startPoint = flowLines.bottom - const moduleArray = [] + 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 - console.log('flowLines', flowLines) + // 혼합모듈 포함 총 모듈 설치 높이 갯수 + const totalModuleMaxRows = tmpModuleData.moduleMaxRows - if (isCenter) { - //중앙배치일 경우에는 계산한다 - if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { - //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 - const halfModuleWidthLength = width / 2 - startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + //모듈의 넓이 높이를 가져옴 (복시도 촌수 적용) + //1번 깔았던 모듈 기준으로 잡야아함 + let { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) - if (flowLines.top.type === 'flat') { - //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 - const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 - const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 - startPoint = { ...startPoint, y1: startPoint.y1 - heightMargin } - } + if (moduleIndex === 0) { + flowLines = getFlowLines(moduleSetupSurface, height) + if (flowLines.bottom.type === 'curve') { + flowLines = getFlowLines(moduleSetupSurface, width) } } + + //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + // let startPoint = flowLines.bottom + const moduleArray = [] + // const moduleMaxRows = module + //밑에가 곡선이면 모듈의 넓이를 가지고 계산한다 + // if (isCenter) { + // //중앙배치일 경우에는 계산한다 + // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { + // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = width / 2 + // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + + // if (flowLines.top.type === 'flat') { + // //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + // const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 + // const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 + // startPoint = { ...startPoint, y1: startPoint.y1 - heightMargin } + // } + // } + // } //밑에가 평면이면 좌측으로 붙여서 배치 // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'curve') { // startPoint = flowLines.left // } - const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측 - const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 - const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 + // let leftEnd = new fabric.Circle({ left: surfaceMaxLines.left.x1 - 2.5, top: surfaceMaxLines.left.y1 - 2.5, radius: 5, fill: 'green' }) + // let rightEnd = new fabric.Circle({ left: surfaceMaxLines.right.x1 - 2.5, top: surfaceMaxLines.right.y1 - 2.5, radius: 5, fill: 'green' }) + // let topEnd = new fabric.Circle({ left: surfaceMaxLines.top.x1 - 2.5, top: surfaceMaxLines.top.y1 - 2.5, radius: 5, fill: 'green' }) - let totalLeftEndPoint = maxLeftEndPoint - startPoint.x1 - let totalTopEndPoint = maxTopEndPoint - startPoint.y1 - let totalWidth = Math.ceil(Math.abs(maxRightEndPoint - maxLeftEndPoint) / width) - let diffLeftEndPoint = Math.abs(totalLeftEndPoint / width) - let diffTopEndPoint = Math.abs(totalTopEndPoint / height) - let startColPoint = Math.abs(width * Math.ceil(diffLeftEndPoint) - startPoint.x1) - let tempMaxWidth = isMaxSetup ? width / 2 : width //최대배치인지 확인하려고 넣음 - if (isMaxSetup) totalWidth = totalWidth * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함 + // canvas?.add(leftEnd) + // canvas?.add(rightEnd) + // canvas?.add(topEnd) - for (let j = 0; j < diffTopEndPoint; j++) { - bottomMargin = j === 0 ? 0 : intvVer * j - for (let i = 0; i <= totalWidth; i++) { - leftMargin = i === 0 ? 0 : intvHor * i - chidoriLength = 0 + // canvas.renderAll() + + let calcAreaWidth = flowLines.right.x1 - flowLines.left.x1 //오른쪽 x에서 왼쪽 x를 뺀 가운데를 찾는 로직 + let calcModuleWidthCount = calcAreaWidth / (width + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcMaxModuleWidthCount = calcModuleWidthCount > moduleMaxCols ? moduleMaxCols : calcModuleWidthCount //최대 모듈 단수가 있기 때문에 최대 단수보다 카운트가 크면 최대 단수로 씀씀 + // let totalModuleWidthCount = isChidori ? Math.abs(calcMaxModuleWidthCount) : Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 + let totalModuleWidthCount = Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 + + // let calcAreaHeight = flowLines.bottom.y1 - flowLines.top.y1 + // let calcModuleHeightCount = calcAreaHeight / (height + intvVer) + + let calcStartPoint = flowLines.right.type === 'flat' ? (calcAreaWidth - totalModuleWidthCount * width) / 2 : 0 //반씩 나눠서 중앙에 맞춤 bottom 기준으로 양변이 직선일때만 가운데 정렬 + let startPointX = flowLines.left.x1 + calcStartPoint //시작점을 만든다 + + //근데 양변이 곡선이면 중앙에 맞추기 위해 아래와 위의 길이를 재서 모듈의 길이를 나눠서 들어갈수 있는 갯수가 동일하면 가운데로 정렬 시킨다 + if (flowLines.left.type === 'curve' && flowLines.right.type === 'curve') { + startPointX = flowLines.left.x1 + (calcAreaWidth - totalModuleWidthCount * width) / 2 + } + + let heightMargin = 0 + let widthMargin = 0 + let chidoriLength = 0 + + //첫번재 모듈 설치 후 두번째 모듈을 몇개까지 설치 할 수 있는지 계산 + if (moduleIndex > 0) { + moduleMaxRows = totalModuleMaxRows - installedModuleHeightCount //두번째 모듈일때 + isChidoriLine = installedModuleHeightCount % 2 != 0 ? true : false //첫번째에서 짝수에서 끝났으면 홀수는 치도리가 아님 짝수는 치도리 + } + + let isInstall = false + + for (let i = 0; i < moduleMaxRows; i++) { + let moduleY = flowLines.bottom.y1 - height * i - 0.1 //살짝 여유를 준다 + + //두번째 모듈 -> 혼합일 경우의 설치될 모듈 높이를 계산 + if (moduleIndex > 0) { + moduleY = installedLastHeightCoord - intvVer + } + + //전체 설치 간으 모듈이랑 같으면 반복을 멈춘다 + if (totalModuleMaxRows === installedModuleHeightCount) { + break + } + + //첫번째는 붙여서 두번째는 마진을 주고 설치 + heightMargin = i === 0 ? 0 : intvVer * i + + for (let j = 0; j < totalModuleWidthCount; j++) { + let moduleX = startPointX + width * j + 0.1 //5정도 마진을 준다 + widthMargin = j === 0 ? 0 : intvHor * j // 가로 마진값 + chidoriLength = 0 //치도리가 아니여도 기본값을 5정도 준다 if (isChidori && !isMaxSetup) { - chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor + chidoriLength = installedModuleHeightCount % 2 == 0 ? 0 : width / 2 - intvHor } - square = [ - [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], - [startColPoint + tempMaxWidth * i + width - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], - [startColPoint + tempMaxWidth * i + width - chidoriLength + leftMargin, startPoint.y1 - height * j - height - bottomMargin], - [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - height - bottomMargin], - [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], + //치도리 일때 는 짝수(1 기준) 일때만 치도리 라인으로 본다 + if (isChidori && isChidoriLine) { + chidoriLength = width / 2 - intvHor + } + + let square = [ + [moduleX + widthMargin + chidoriLength, moduleY - height - heightMargin], + [moduleX + widthMargin + chidoriLength, moduleY - heightMargin], + [moduleX + width + widthMargin + chidoriLength, moduleY - heightMargin], + [moduleX + width + widthMargin + chidoriLength, moduleY - height - heightMargin], + [moduleX + widthMargin + chidoriLength, moduleY - height - heightMargin], ] let squarePolygon = turf.polygon([square]) @@ -928,148 +995,114 @@ export function useModuleBasicSetting(tabNum) { let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) if (disjointFromTrestle && isDisjoint) { - if (index > 0) { - setupModule.forEach((item) => { - const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) - if (!isOverlap) { - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } - }) - } else { - //최초 한번은 그냥 그린다 - //겹치는지 확인해서 포함된 모듈만 그린다 - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } + //최초 한번은 그냥 그린다 + //겹치는지 확인해서 포함된 모듈만 그린다 + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + canvas.renderAll() + + // ++installedModuleHeightCount + + isInstall = true + //마지막에 설치된 모듈의 Y 좌표 + installedLastHeightCoord = moduleY - height - heightMargin + + // if (j === 0) { + // let startCircle = new fabric.Rect({ + // left: surfaceMaxLines.left.x1, + // top: installedLastHeightCoord, + // stroke: 'red', + // strokeWidth: 1, + // width: 5, + // height: 5, + // fill: 'red', + // originX: 'center', + // originY: 'center', + // }) + // canvas.add(startCircle) + // } } else { //디버깅용 - // tempModule.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) + // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) // canvas?.add(tempModule) // canvas.renderAll() } } + if (isInstall) { + ++installedModuleHeightCount + } } + // } + // else { + // //밑바닥이 직선이 아닐때 + // //모양이 이상할때 - setupModule.push(moduleArray) - }) - } + // let totalLeftEndPoint = maxLeftEndPoint - startPoint.x1 + // let totalTopEndPoint = maxTopEndPoint - startPoint.y1 + // let totalWidth = Math.ceil(Math.abs(maxRightEndPoint - maxLeftEndPoint) / width) + // let diffLeftEndPoint = Math.abs(totalLeftEndPoint / width) + // let diffTopEndPoint = Math.abs(totalTopEndPoint / height) + // let startColPoint = Math.abs(width * Math.ceil(diffLeftEndPoint) - startPoint.x1) + // let tempMaxWidth = isMaxSetup ? width / 2 : width //최대배치인지 확인하려고 넣음 + // if (isMaxSetup) totalWidth = totalWidth * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함 - const leftFlowSetupModule = ( - surfaceMaxLines, - maxLengthLine, - moduleSetupArray, - moduleSetupSurface, - containsBatchObjects, - isCenter = false, - intvHor, - intvVer, - ) => { - let setupModule = [] + // for (let j = 0; j < diffTopEndPoint; j++) { + // bottomMargin = j === 0 ? 0 : intvVer * j + // for (let i = 0; i <= totalWidth; i++) { + // leftMargin = i === 0 ? 0 : intvHor * i + // chidoriLength = 0 + // if (isChidori && !isMaxSetup) { + // chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor + // } - checkedModule.forEach((module, index) => { - const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) - let flowLines = getFlowLines(moduleSetupSurface, width) - //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 - let startPoint = flowLines.left - const moduleArray = [] + // square = [ + // [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], + // [startColPoint + tempMaxWidth * i + width - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], + // [startColPoint + tempMaxWidth * i + width - chidoriLength + leftMargin, startPoint.y1 - height * j - height - bottomMargin], + // [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - height - bottomMargin], + // [startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin], + // ] - // if (flowLines.left.type === 'flat') { - // const tempPoint = { ...flowLines.top } - // startPoint = { ...flowLines.top, x1: tempPoint.x2, x2: tempPoint.x1 } - // } else { - // flowLines = getFlowLines(moduleSetupSurface, height) - // const tempPoint = { ...flowLines.left } - // startPoint = { ...flowLines.left, x1: tempPoint.x1 + 5, x2: tempPoint.x2, y1: tempPoint.y1 - 5 } + // let squarePolygon = turf.polygon([square]) + // let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) + // let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) + + // moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module } + // let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) + + // let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true)) + // let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) + + // if (disjointFromTrestle && isDisjoint) { + // if (moduleIndex > 0) { + // setupModule.forEach((item) => { + // const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) + // if (!isOverlap) { + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // }) + // } else { + // //최초 한번은 그냥 그린다 + // //겹치는지 확인해서 포함된 모듈만 그린다 + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // } else { + // //디버깅용 + // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + // canvas?.add(tempModule) + // canvas.renderAll() + // } + // } + // } // } - //중앙배치일 경우에는 계산한다 - if (isCenter) { - if (flowLines.left.type === 'flat' && flowLines.bottom.type === 'flat' && flowLines.top.type === 'flat') { - //좌측 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - const halfWidthLength = Math.abs(startPoint.y1 + startPoint.y2) / 2 //밑에 길이에서 반을 가른다 - const halfModuleWidthLength = height / 2 - startPoint = { ...startPoint, y1: halfWidthLength - halfModuleWidthLength } - if (flowLines.right.type === 'flat') { - //우측까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 - const widthLength = Math.abs(flowLines.top.x1 - flowLines.top.x2) //옆에에 길이에서 반을 가른다 - const widthMargin = Math.abs(widthLength - width * Math.floor(widthLength / width)) / 2 - startPoint = { ...startPoint, x1: startPoint.x1 + widthMargin } - } - } - } - - const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 - const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 - const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 - - let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌 - let diffTopEndPoint = Math.abs(totalTopEndPoint / height) - let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height) - let totalWidth = Math.abs(startPoint.x1 - maxRightEndPoint) / width - let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint) - - let tempMaxHeight = isMaxSetup ? height / 2 : height //최대배치인지 확인하려고 넣음 - if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려 서 반씩 검사 - - for (let i = 0; i <= totalWidth; i++) { - bottomMargin = i === 0 ? 0 : intvHor * i - for (let j = 0; j < totalHeight; j++) { - leftMargin = j === 0 ? 0 : intvVer * j - chidoriLength = 0 - if (isChidori && !isMaxSetup) { - chidoriLength = i % 2 === 0 ? 0 : height / 2 - } - - square = [ - [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], - [startPoint.x1 + width * i + width + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], - [startPoint.x1 + width * i + width + bottomMargin, startRowPoint + tempMaxHeight * j + height + leftMargin - chidoriLength], - [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + height + leftMargin - chidoriLength], - [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], - ] - - let squarePolygon = turf.polygon([square]) - let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) - let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) - - // if (disjointFromTrestle && isDisjoint) { - moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module } - let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) - let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true)) - let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) - - if (disjointFromTrestle && isDisjoint) { - if (index > 0) { - setupModule.forEach((item) => { - const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) - if (!isOverlap) { - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } - }) - } else { - //최초 한번은 그냥 그린다 - //겹치는지 확인해서 포함된 모듈만 그린다 - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } - } else { - //디버깅용 - // tempModule.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) - // canvas?.add(tempModule) - // canvas.renderAll() - } - } - } setupModule.push(moduleArray) }) } @@ -1086,81 +1119,136 @@ export function useModuleBasicSetting(tabNum) { ) => { let setupModule = [] - checkedModule.forEach((module, index) => { + const trestleDetailData = moduleSetupSurface.trestleDetail + const moduleMaxCols = trestleDetailData.moduleMaxCols // 모듈 최대 가로 설치 갯수 + + let installedLastHeightCoord = 0 //마지막으로 설치된 모듈의 좌표 + let installedModuleHeightCount = 0 //마지막으로 설치된 모듈의 카운트 + let isChidoriLine = false + let flowLines + + 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 + // 혼합모듈 포함 총 모듈 설치 높이 갯수 + const totalModuleMaxRows = tmpModuleData.moduleMaxRows + const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) - const flowLines = getFlowLines(moduleSetupSurface, height) - let startPoint = flowLines.top - // if (flowLines.top.type === 'flat' && flowLines.right.type === 'curve') { - // startPoint = flowLines.right - // } - - const moduleArray = [] - - if (isCenter) { - //중앙배치일 경우에는 계산한다 - if (flowLines.top.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { - //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 - const halfModuleWidthLength = width / 2 - startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } - - if (flowLines.bottom.type === 'flat') { - //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 - const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 - const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 - startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength, y1: startPoint.y1 - heightMargin } - } + if (moduleIndex === 0) { + flowLines = getFlowLines(moduleSetupSurface, height) + if (flowLines.top.type === 'curve') { + flowLines = getFlowLines(moduleSetupSurface, width) } } - // else { - // //중앙배치가 아닐때도 흐름 방향 기준면으로 양면이 직선이면 가운데 배치 - // if (flowModuleLine.bottom.type === 'flat' && flowModuleLine.left.type === 'flat' && flowModuleLine.right.type === 'flat') { - // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 - // const halfModuleWidthLength = width / 2 - // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + + //흐름 방향이 북쪽(위) + + //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + // let startPoint = flowLines.bottom + const moduleArray = [] + // const moduleMaxRows = module + + // if (isCenter) { + // //중앙배치일 경우에는 계산한다 + // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { + // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = width / 2 + // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + + // if (flowLines.top.type === 'flat') { + // //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + // const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 + // const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 + // startPoint = { ...startPoint, y1: startPoint.y1 - heightMargin } + // } + // } // } + //밑에가 평면이면 좌측으로 붙여서 배치 + // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'curve') { + // startPoint = flowLines.left // } - const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측 - const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 - const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 + // let leftEnd = new fabric.Circle({ left: surfaceMaxLines.left.x1 - 2.5, top: surfaceMaxLines.left.y1 - 2.5, radius: 5, fill: 'green' }) + // let rightEnd = new fabric.Circle({ left: surfaceMaxLines.right.x1 - 2.5, top: surfaceMaxLines.right.y1 - 2.5, radius: 5, fill: 'green' }) + // let bottomEnd = new fabric.Circle({ left: surfaceMaxLines.bottom.x1 - 2.5, top: surfaceMaxLines.bottom.y1 - 2.5, radius: 5, fill: 'green' }) - let totalLeftEndPoint = maxLeftEndPoint - startPoint.x1 - let totalRightEndPoint = maxLeftEndPoint - maxRightEndPoint - let totalBottomEndPoint = maxBottomEndPoint - startPoint.y1 - let diffLeftEndPoint = Math.abs(totalLeftEndPoint / width) - let diffRightEndPoint = Math.ceil(Math.abs(totalRightEndPoint / width)) - let diffBottomEndPoint = Math.ceil(Math.abs(totalBottomEndPoint / height)) - let startColPoint = Math.abs(width * Math.ceil(diffLeftEndPoint) - startPoint.x1) - let tempMaxWidth = isMaxSetup ? width / 2 : width //최대배치인지 확인하려고 넣음 - if (isMaxSetup) diffRightEndPoint = diffRightEndPoint * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함 + // canvas?.add(leftEnd) + // canvas?.add(rightEnd) + // canvas?.add(bottomEnd) - startColPoint = Math.round(startColPoint - intvHor * diffRightEndPoint) + // canvas.renderAll() - for (let j = 0; j < diffBottomEndPoint; j++) { - bottomMargin = j === 0 ? 0 : intvVer * j - for (let i = 0; i < diffRightEndPoint; i++) { - leftMargin = i === 0 ? 0 : intvHor * i + let calcAreaWidth = flowLines.right.x1 - flowLines.left.x1 //오른쪽 x에서 왼쪽 x를 뺀 가운데를 찾는 로직 + let calcModuleWidthCount = calcAreaWidth / (width + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcMaxModuleWidthCount = calcModuleWidthCount > moduleMaxCols ? moduleMaxCols : calcModuleWidthCount //최대 모듈 단수가 있기 때문에 최대 단수보다 카운트가 크면 최대 단수로 씀씀 + // let totalModuleWidthCount = isChidori ? Math.abs(calcMaxModuleWidthCount) : Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 //??어쩔때는 붙고 어쩔때는 안붙고 멋대로??? + let totalModuleWidthCount = Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 + + let calcStartPoint = flowLines.left.type === 'flat' ? (calcAreaWidth - totalModuleWidthCount * width) / 2 : 0 //반씩 나눠서 중앙에 맞춤 bottom 기준으로 양변이 직선일때만 가운데 정렬 + let startPointX = flowLines.right.x1 - calcStartPoint //시작점을 만든다 + + //근데 양변이 곡선이면 중앙에 맞추기 위해 아래와 위의 길이를 재서 모듈의 길이를 나눠서 들어갈수 있는 갯수가 동일하면 가운데로 정렬 시킨다 + if (flowLines.left.type === 'curve' && flowLines.right.type === 'curve') { + // const calcTopWidth = Math.abs(flowLines.top.x1 - flowLines.top.x2) + // const calcTopModuleWidthCount = calcTopWidth / (width + intvHor) + + // if (Math.floor(calcMaxModuleWidthCount) === Math.floor(calcTopModuleWidthCount)) { + startPointX = flowLines.right.x1 - (calcAreaWidth - totalModuleWidthCount * width) / 2 + // } + } + + let heightMargin = 0 + let widthMargin = 0 + let chidoriLength = 0 + + if (moduleIndex > 0) { + moduleMaxRows = totalModuleMaxRows - installedModuleHeightCount //두번째 모듈일때 + isChidoriLine = installedModuleHeightCount % 2 != 0 ? true : false //첫번째에서 짝수에서 끝났으면 홀수는 치도리가 아님 짝수는 치도리 + } + + let isInstall = false + + for (let i = 0; i < moduleMaxRows; i++) { + let moduleY = flowLines.top.y1 + height * i //탑의 y점에서부터 아래로 그려 내려간다 + + if (moduleIndex > 0) { + moduleY = installedLastHeightCoord + intvVer + 1 + } + + //전체 설치 간으 모듈이랑 같으면 반복을 멈춘다 + if (totalModuleMaxRows === installedModuleHeightCount) { + break + } + + heightMargin = i === 0 ? 0 : intvVer * i //모듈간에 마진이 있어 마진값도 넣음 + for (let j = 0; j < totalModuleWidthCount; j++) { + //모듈 열수 만큼 반복 + let moduleX = startPointX - width * j - 1 //시작점에서 우 -> 좌로 그려 내려간다 + widthMargin = j === 0 ? 0 : intvHor * j chidoriLength = 0 if (isChidori && !isMaxSetup) { - chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor + chidoriLength = installedModuleHeightCount % 2 == 0 ? 0 : width / 2 - intvHor } - square = [ - [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], - [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin], - [startColPoint + tempMaxWidth * i + width + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin], - [startColPoint + tempMaxWidth * i + width + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], - [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], + if (isChidori && isChidoriLine) { + chidoriLength = width / 2 + intvHor + } + + let square = [ + [moduleX - widthMargin - chidoriLength, moduleY + heightMargin], + [moduleX - widthMargin - chidoriLength, moduleY + height + heightMargin], + [moduleX - width - widthMargin - chidoriLength, moduleY + height + heightMargin], + [moduleX - width - widthMargin - chidoriLength, moduleY + heightMargin], + [moduleX - widthMargin - chidoriLength, moduleY + heightMargin], ] let squarePolygon = turf.polygon([square]) let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) - // if (disjointFromTrestle && isDisjoint) { moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module } let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) @@ -1168,32 +1256,454 @@ export function useModuleBasicSetting(tabNum) { let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) if (disjointFromTrestle && isDisjoint) { - if (index > 0) { - setupModule.forEach((item) => { - const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) - if (!isOverlap) { - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } - }) - } else { - //최초 한번은 그냥 그린다 - //겹치는지 확인해서 포함된 모듈만 그린다 - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + canvas.renderAll() + + isInstall = true + + // if (j === 0) { + // let startCircle = new fabric.Rect({ + // left: surfaceMaxLines.left.x1, + // top: installedLastHeightCoord, + // stroke: 'red', + // strokeWidth: 1, + // width: 5, + // height: 5, + // fill: 'red', + // originX: 'center', + // originY: 'center', + // }) + // canvas.add(startCircle) + // } + + //마지막에 설치된 모듈의 Y 좌표 + installedLastHeightCoord = moduleY + height + heightMargin } else { //디버깅용 - // tempModule.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) + // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) // canvas?.add(tempModule) // canvas.renderAll() } } + if (isInstall) { + ++installedModuleHeightCount + } } + + // checkedModule.forEach((module, index) => { + // const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) + // const flowLines = getFlowLines(moduleSetupSurface, height) + // let startPoint = flowLines.top + + // // if (flowLines.top.type === 'flat' && flowLines.right.type === 'curve') { + // // startPoint = flowLines.right + // // } + + // const moduleArray = [] + + // if (isCenter) { + // //중앙배치일 경우에는 계산한다 + // if (flowLines.top.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { + // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = width / 2 + // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + + // if (flowLines.bottom.type === 'flat') { + // //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + // const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 + // const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 + // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength, y1: startPoint.y1 - heightMargin } + // } + // } + // } + // // else { + // // //중앙배치가 아닐때도 흐름 방향 기준면으로 양면이 직선이면 가운데 배치 + // // if (flowModuleLine.bottom.type === 'flat' && flowModuleLine.left.type === 'flat' && flowModuleLine.right.type === 'flat') { + // // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + // // const halfModuleWidthLength = width / 2 + // // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + // // } + // // } + + // const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측 + // const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 + // const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 + + // let totalLeftEndPoint = maxLeftEndPoint - startPoint.x1 + // let totalRightEndPoint = maxLeftEndPoint - maxRightEndPoint + // let totalBottomEndPoint = maxBottomEndPoint - startPoint.y1 + // let diffLeftEndPoint = Math.abs(totalLeftEndPoint / width) + // let diffRightEndPoint = Math.ceil(Math.abs(totalRightEndPoint / width)) + // let diffBottomEndPoint = Math.ceil(Math.abs(totalBottomEndPoint / height)) + // let startColPoint = Math.abs(width * Math.ceil(diffLeftEndPoint) - startPoint.x1) + // let tempMaxWidth = isMaxSetup ? width / 2 : width //최대배치인지 확인하려고 넣음 + // if (isMaxSetup) diffRightEndPoint = diffRightEndPoint * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함 + + // startColPoint = Math.round(startColPoint - intvHor * diffRightEndPoint) + + // for (let j = 0; j < diffBottomEndPoint; j++) { + // bottomMargin = j === 0 ? 0 : intvVer * j + // for (let i = 0; i < diffRightEndPoint; i++) { + // leftMargin = i === 0 ? 0 : intvHor * i + // chidoriLength = 0 + // if (isChidori && !isMaxSetup) { + // chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor + // } + + // square = [ + // [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], + // [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin], + // [startColPoint + tempMaxWidth * i + width + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin], + // [startColPoint + tempMaxWidth * i + width + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], + // [startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin], + // ] + + // let squarePolygon = turf.polygon([square]) + // let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) + // let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) + + // // if (disjointFromTrestle && isDisjoint) { + // moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module } + // let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) + + // let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true)) + // let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) + + // if (disjointFromTrestle && isDisjoint) { + // if (index > 0) { + // setupModule.forEach((item) => { + // const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) + // if (!isOverlap) { + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // }) + // } else { + // //최초 한번은 그냥 그린다 + // //겹치는지 확인해서 포함된 모듈만 그린다 + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // } else { + // //디버깅용 + // // tempModule.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) + // // canvas?.add(tempModule) + // // canvas.renderAll() + // } + // } + // } + setupModule.push(moduleArray) + }) + } + + //남, 북과 같은 로직으로 적용하려면 좌우는 열 -> 행 으로 그려야함 + //변수명은 bottom 기준으로 작성하여 동일한 방향으로 진행한다 + const leftFlowSetupModule = ( + surfaceMaxLines, + maxLengthLine, + moduleSetupArray, + moduleSetupSurface, + containsBatchObjects, + isCenter = false, + intvHor, + intvVer, + ) => { + let setupModule = [] + + const trestleDetailData = moduleSetupSurface.trestleDetail //가대 상세 데이터 + const moduleMaxCols = trestleDetailData.moduleMaxCols // 모듈 최대 가로 설치 갯수 + + let installedLastHeightCoord = 0 //마지막으로 설치된 모듈의 좌표 + let installedModuleHeightCount = 0 //마지막으로 설치된 모듈의 카운트 + let isChidoriLine = false + let flowLines + + 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 + + // 혼합모듈 포함 총 모듈 설치 높이 갯수 + const totalModuleMaxRows = tmpModuleData.moduleMaxRows + + //모듈의 넓이 높이를 가져옴 (복시도 촌수 적용) + //1번 깔았던 모듈 기준으로 잡야아함 + const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) + + if (moduleIndex === 0) { + flowLines = getFlowLines(moduleSetupSurface, width) + if (flowLines.left.type === 'curve') { + flowLines = getFlowLines(moduleSetupSurface, height) + } + } + + //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + // let startPoint = flowLines.bottom + const moduleArray = [] + // const moduleMaxRows = module + //밑에가 곡선이면 모듈의 넓이를 가지고 계산한다 + // if (isCenter) { + // //중앙배치일 경우에는 계산한다 + // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { + // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = width / 2 + // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } + + // if (flowLines.top.type === 'flat') { + // //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + // const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 + // const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 + // startPoint = { ...startPoint, y1: startPoint.y1 - heightMargin } + // } + // } + // } + //밑에가 평면이면 좌측으로 붙여서 배치 + // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'curve') { + // startPoint = flowLines.left + // } + + // let leftEnd = new fabric.Circle({ left: surfaceMaxLines.left.x1 - 2.5, top: surfaceMaxLines.left.y1 - 2.5, radius: 5, fill: 'green' }) + // let rightEnd = new fabric.Circle({ left: surfaceMaxLines.right.x1 - 2.5, top: surfaceMaxLines.right.y1 - 2.5, radius: 5, fill: 'green' }) + // let topEnd = new fabric.Circle({ left: surfaceMaxLines.top.x1 - 2.5, top: surfaceMaxLines.top.y1 - 2.5, radius: 5, fill: 'green' }) + + // canvas?.add(leftEnd) + // canvas?.add(rightEnd) + // canvas?.add(topEnd) + + // canvas.renderAll() + + let calcAreaWidth = flowLines.bottom.y1 - flowLines.top.y1 //아래에서 y에서 위를 y를 뺀 가운데를 찾는 로직 + let calcModuleWidthCount = calcAreaWidth / (height + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcMaxModuleWidthCount = calcModuleWidthCount > moduleMaxCols ? moduleMaxCols : calcModuleWidthCount //최대 모듈 단수가 있기 때문에 최대 단수보다 카운트가 크면 최대 단수로 씀씀 + // let totalModuleWidthCount = isChidori ? Math.abs(calcMaxModuleWidthCount) : Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 + let totalModuleWidthCount = Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 + + // let calcAreaHeight = flowLines.bottom.y1 - flowLines.top.y1 + // let calcModuleHeightCount = calcAreaHeight / (height + intvVer) + + let calcStartPoint = flowLines.bottom.type === 'flat' ? (calcAreaWidth - totalModuleWidthCount * height) / 2 : 0 //반씩 나눠서 중앙에 맞춤 left 높이 기준으로 양변이 직선일때만 가운데 정렬 + let startPointX = flowLines.top.y1 + calcStartPoint //시작점을 만든다 + + //근데 양변이 곡선이면 중앙에 맞추기 위해 아래와 위의 길이를 재서 모듈의 길이를 나눠서 들어갈수 있는 갯수가 동일하면 가운데로 정렬 시킨다 + if (flowLines.top.type === 'curve' && flowLines.bottom.type === 'curve') { + // const calcTopWidth = Math.abs(flowLines.right.y1 - flowLines.right.y2) + // const calcTopModuleWidthCount = calcTopWidth / (height + intvVer) + + // if (Math.floor(calcMaxModuleWidthCount) === Math.floor(calcTopModuleWidthCount)) { + startPointX = flowLines.top.y1 + (calcAreaWidth - totalModuleWidthCount * height) / 2 + // } + } + + let heightMargin = 0 + let widthMargin = 0 + let chidoriLength = 0 + + //첫번재 모듈 설치 후 두번째 모듈을 몇개까지 설치 할 수 있는지 계산 + if (moduleIndex > 0) { + moduleMaxRows = totalModuleMaxRows - installedModuleHeightCount //두번째 모듈일때 + isChidoriLine = installedModuleHeightCount % 2 != 0 ? true : false //첫번째에서 짝수에서 끝났으면 홀수는 치도리가 아님 짝수는 치도리 + } + + let isInstall = false + + for (let i = 0; i < moduleMaxRows; i++) { + let moduleY = flowLines.left.x1 + width * i + 1 //살짝 여유를 준다 + + //두번째 모듈 -> 혼합일 경우의 설치될 모듈 높이를 계산 + if (moduleIndex > 0) { + moduleY = installedLastHeightCoord + intvHor + } + + //전체 설치 간으 모듈이랑 같으면 반복을 멈춘다 + if (totalModuleMaxRows === installedModuleHeightCount) { + break + } + + //첫번째는 붙여서 두번째는 마진을 주고 설치 + heightMargin = i === 0 ? 0 : intvHor * i + + for (let j = 0; j < totalModuleWidthCount; j++) { + let moduleX = startPointX + height * j + 1 //5정도 마진을 준다 + widthMargin = j === 0 ? 0 : intvVer * j // 가로 마진값 + chidoriLength = 0 //치도리가 아니여도 기본값을 5정도 준다 + if (isChidori && !isMaxSetup) { + chidoriLength = installedModuleHeightCount % 2 == 0 ? 0 : height / 2 - intvVer + } + + //치도리 일때 는 짝수(1 기준) 일때만 치도리 라인으로 본다 + if (isChidori && isChidoriLine) { + chidoriLength = width / 2 - height + } + + let square = [ + [moduleY + heightMargin, moduleX + height + widthMargin + chidoriLength], + [moduleY + heightMargin, moduleX + widthMargin + chidoriLength], + [moduleY + width + heightMargin, moduleX + widthMargin + chidoriLength], + [moduleY + width + heightMargin, moduleX + height + widthMargin + chidoriLength], + [moduleY + heightMargin, moduleX + height + widthMargin + chidoriLength], + ] + + let squarePolygon = turf.polygon([square]) + let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) + let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) + + moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module } + let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) + + let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true)) + let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) + + if (disjointFromTrestle && isDisjoint) { + //최초 한번은 그냥 그린다 + //겹치는지 확인해서 포함된 모듈만 그린다 + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + canvas.renderAll() + + // ++installedModuleHeightCount + + isInstall = true + //마지막에 설치된 모듈의 Y 좌표 + + //디버깅용 + // if (j === 0) { + // let startCircle = new fabric.Rect({ + // left: surfaceMaxLines.left.x1, + // top: installedLastHeightCoord, + // stroke: 'red', + // strokeWidth: 1, + // width: 5, + // height: 5, + // fill: 'red', + // originX: 'center', + // originY: 'center', + // }) + // canvas.add(startCircle) + // } + } else { + //디버깅용 + // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) + // canvas?.add(tempModule) + // canvas.renderAll() + } + } + + installedLastHeightCoord = moduleY + width + widthMargin + + if (isInstall) { + ++installedModuleHeightCount + } + } + + // checkedModule.forEach((module, index) => { + // const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) + // let flowLines = getFlowLines(moduleSetupSurface, width) + // //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + // let startPoint = flowLines.left + // const moduleArray = [] + + // // if (flowLines.left.type === 'flat') { + // // const tempPoint = { ...flowLines.top } + // // startPoint = { ...flowLines.top, x1: tempPoint.x2, x2: tempPoint.x1 } + // // } else { + // // flowLines = getFlowLines(moduleSetupSurface, height) + // // const tempPoint = { ...flowLines.left } + // // startPoint = { ...flowLines.left, x1: tempPoint.x1 + 5, x2: tempPoint.x2, y1: tempPoint.y1 - 5 } + // // } + + // //중앙배치일 경우에는 계산한다 + // if (isCenter) { + // if (flowLines.left.type === 'flat' && flowLines.bottom.type === 'flat' && flowLines.top.type === 'flat') { + // //좌측 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.y1 + startPoint.y2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = height / 2 + // startPoint = { ...startPoint, y1: halfWidthLength - halfModuleWidthLength } + // if (flowLines.right.type === 'flat') { + // //우측까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + // const widthLength = Math.abs(flowLines.top.x1 - flowLines.top.x2) //옆에에 길이에서 반을 가른다 + // const widthMargin = Math.abs(widthLength - width * Math.floor(widthLength / width)) / 2 + // startPoint = { ...startPoint, x1: startPoint.x1 + widthMargin } + // } + // } + // } + + // const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 + // const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 + // const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 + + // let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌 + // let diffTopEndPoint = Math.abs(totalTopEndPoint / height) + // let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height) + // let totalWidth = Math.abs(startPoint.x1 - maxRightEndPoint) / width + // let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint) + + // let tempMaxHeight = isMaxSetup ? height / 2 : height //최대배치인지 확인하려고 넣음 + // if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려 서 반씩 검사 + + // for (let i = 0; i <= totalWidth; i++) { + // bottomMargin = i === 0 ? 0 : intvHor * i + // for (let j = 0; j < totalHeight; j++) { + // leftMargin = j === 0 ? 0 : intvVer * j + // chidoriLength = 0 + // if (isChidori && !isMaxSetup) { + // chidoriLength = i % 2 === 0 ? 0 : height / 2 + // } + + // square = [ + // [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + width + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + width + bottomMargin, startRowPoint + tempMaxHeight * j + height + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + height + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], + // ] + + // let squarePolygon = turf.polygon([square]) + // let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) + // let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) + + // // if (disjointFromTrestle && isDisjoint) { + // moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module } + // let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) + // let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true)) + // let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) + + // if (disjointFromTrestle && isDisjoint) { + // if (index > 0) { + // setupModule.forEach((item) => { + // const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) + // if (!isOverlap) { + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // }) + // } else { + // //최초 한번은 그냥 그린다 + // //겹치는지 확인해서 포함된 모듈만 그린다 + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // } else { + // //디버깅용 + // // tempModule.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) + // // canvas?.add(tempModule) + // // canvas.renderAll() + // } + // } + // } setupModule.push(moduleArray) }) } @@ -1210,108 +1720,291 @@ export function useModuleBasicSetting(tabNum) { ) => { let setupModule = [] - checkedModule.forEach((module, index) => { + const trestleDetailData = moduleSetupSurface.trestleDetail //가대 상세 데이터 + const moduleMaxCols = trestleDetailData.moduleMaxCols // 모듈 최대 가로 설치 갯수 + + let installedLastHeightCoord = 0 //마지막으로 설치된 모듈의 좌표 + let installedModuleHeightCount = 0 //마지막으로 설치된 모듈의 카운트 + let isChidoriLine = false + let flowLines + + 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 + + // 혼합모듈 포함 총 모듈 설치 높이 갯수 + const totalModuleMaxRows = tmpModuleData.moduleMaxRows + + //모듈의 넓이 높이를 가져옴 (복시도 촌수 적용) + //1번 깔았던 모듈 기준으로 잡야아함 const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) - let flowLines = getFlowLines(moduleSetupSurface, width) - let startPoint = flowLines.right - // if (flowLines.right.type === 'flat') { - // const tempPoint = { ...flowLines.bottom } - // startPoint = { ...flowLines.bottom, x1: tempPoint.x2, x2: tempPoint.x1 } - // } else { - // flowLines = getFlowLines(moduleSetupSurface, height) - // const tempPoint = { ...flowLines.right } - // startPoint = { ...flowLines.right, x1: tempPoint.x1 - 5, x2: tempPoint.x2, y1: tempPoint.y1 + 5 } - // } - - // console.log('startPoint', startPoint) - - const moduleArray = [] - - if (isCenter) { - if (flowLines.left.type === 'flat' && flowLines.bottom.type === 'flat' && flowLines.top.type === 'flat') { - //좌측 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 - const halfWidthLength = Math.abs(startPoint.y1 + startPoint.y2) / 2 //밑에 길이에서 반을 가른다 - const halfModuleWidthLength = height / 2 - startPoint = { ...startPoint, y1: halfWidthLength + halfModuleWidthLength } - - if (flowLines.right.type === 'flat') { - //우측까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 - const widthLength = Math.abs(flowLines.top.x1 - flowLines.top.x2) //옆에에 길이에서 반을 가른다 - const widthMargin = Math.abs(widthLength - width * Math.floor(widthLength / width)) / 2 - startPoint = { ...startPoint, x1: startPoint.x1 - widthMargin } - } + if (moduleIndex === 0) { + flowLines = getFlowLines(moduleSetupSurface, width) + if (flowLines.right.type === 'curve') { + flowLines = getFlowLines(moduleSetupSurface, height) } } - const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측 - const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 - const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 + //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + // let startPoint = flowLines.bottom + const moduleArray = [] + // const moduleMaxRows = module + //밑에가 곡선이면 모듈의 넓이를 가지고 계산한다 + // if (isCenter) { + // //중앙배치일 경우에는 계산한다 + // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'flat' && flowLines.right.type === 'flat') { + // //하단 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.x1 + startPoint.x2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = width / 2 + // startPoint = { ...startPoint, x1: halfWidthLength - halfModuleWidthLength } - let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌 - let diffTopEndPoint = Math.abs(totalTopEndPoint / height) - let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height) - let totalWidth = Math.abs(startPoint.x1 - maxLeftEndPoint) / width - let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint) - 4 // -3으로 위치살짝 보정1 + // if (flowLines.top.type === 'flat') { + // //상단까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + // const heightLength = Math.abs(flowLines.left.y1 - flowLines.left.y2) //옆에에 길이에서 반을 가른다 + // const heightMargin = Math.abs(heightLength - height * Math.floor(heightLength / height)) / 2 + // startPoint = { ...startPoint, y1: startPoint.y1 - heightMargin } + // } + // } + // } + //밑에가 평면이면 좌측으로 붙여서 배치 + // if (flowLines.bottom.type === 'flat' && flowLines.left.type === 'curve') { + // startPoint = flowLines.left + // } - let tempMaxHeight = isMaxSetup ? height / 2 : height //최대배치인지 확인하려고 넣음 - if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려서 반씩 검사 + // let leftEnd = new fabric.Circle({ left: surfaceMaxLines.left.x1 - 2.5, top: surfaceMaxLines.left.y1 - 2.5, radius: 5, fill: 'green' }) + // let bottomEnd = new fabric.Circle({ left: surfaceMaxLines.bottom.x1 - 2.5, top: surfaceMaxLines.bottom.y1 - 2.5, radius: 5, fill: 'green' }) + // let topEnd = new fabric.Circle({ left: surfaceMaxLines.top.x1 - 2.5, top: surfaceMaxLines.top.y1 - 2.5, radius: 5, fill: 'green' }) - for (let i = 0; i <= totalWidth; i++) { - bottomMargin = i === 0 ? 0 : -(intvHor * i) - for (let j = 0; j < totalHeight; j++) { - leftMargin = j === 0 ? 0 : intvVer * j + // canvas?.add(leftEnd) + // canvas?.add(bottomEnd) + // canvas?.add(topEnd) - chidoriLength = 0 + // canvas.renderAll() + + let calcAreaWidth = flowLines.bottom.y1 - flowLines.top.y1 //아래에서 y에서 위를 y를 뺀 가운데를 찾는 로직 + let calcModuleWidthCount = calcAreaWidth / (height + intvHor) //뺀 공간에서 모듈을 몇개를 넣을수 있는지 확인하는 로직 + let calcMaxModuleWidthCount = calcModuleWidthCount > moduleMaxCols ? moduleMaxCols : calcModuleWidthCount //최대 모듈 단수가 있기 때문에 최대 단수보다 카운트가 크면 최대 단수로 씀씀 + // let totalModuleWidthCount = isChidori ? Math.abs(calcMaxModuleWidthCount) : Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 + let totalModuleWidthCount = Math.floor(calcMaxModuleWidthCount) //치조배치일경우는 한개 더 넣는다 + + // let calcAreaHeight = flowLines.bottom.y1 - flowLines.top.y1 + // let calcModuleHeightCount = calcAreaHeight / (height + intvVer) + + let calcStartPoint = flowLines.top.type === 'flat' ? (calcAreaWidth - totalModuleWidthCount * height) / 2 : 0 //반씩 나눠서 중앙에 맞춤 left 높이 기준으로 양변이 직선일때만 가운데 정렬 + let startPointX = flowLines.bottom.y2 - calcStartPoint //시작점을 만든다 + + //근데 양변이 곡선이면 중앙에 맞추기 위해 아래와 위의 길이를 재서 모듈의 길이를 나눠서 들어갈수 있는 갯수가 동일하면 가운데로 정렬 시킨다 + if (flowLines.top.type === 'curve' && flowLines.bottom.type === 'curve') { + // const calcTopWidth = Math.abs(flowLines.right.y1 - flowLines.right.y2) + // const calcTopModuleWidthCount = calcTopWidth / (height + intvVer) + + // if (Math.floor(calcMaxModuleWidthCount) === Math.floor(calcTopModuleWidthCount)) { + startPointX = flowLines.bottom.y2 - (calcAreaWidth - totalModuleWidthCount * height) / 2 + // } + } + + let heightMargin = 0 + let widthMargin = 0 + let chidoriLength = 0 + + //첫번재 모듈 설치 후 두번째 모듈을 몇개까지 설치 할 수 있는지 계산 + if (moduleIndex > 0) { + moduleMaxRows = totalModuleMaxRows - installedModuleHeightCount //두번째 모듈일때 + isChidoriLine = installedModuleHeightCount % 2 != 0 ? true : false //첫번째에서 짝수에서 끝났으면 홀수는 치도리가 아님 짝수는 치도리 + } + + let isInstall = false + + for (let i = 0; i < moduleMaxRows; i++) { + let moduleY = flowLines.right.x1 - width * i - 1 //살짝 여유를 준다 + + //두번째 모듈 -> 혼합일 경우의 설치될 모듈 높이를 계산 + if (moduleIndex > 0) { + moduleY = installedLastHeightCoord - intvHor + } + + //전체 설치 간으 모듈이랑 같으면 반복을 멈춘다 + if (totalModuleMaxRows === installedModuleHeightCount) { + break + } + + //첫번째는 붙여서 두번째는 마진을 주고 설치 + heightMargin = i === 0 ? 0 : intvHor * i + + for (let j = 0; j < totalModuleWidthCount; j++) { + let moduleX = startPointX - height * j - 1 //5정도 마진을 준다 + widthMargin = j === 0 ? 0 : intvVer * j // 가로 마진값 + chidoriLength = 0 //치도리가 아니여도 기본값을 5정도 준다 if (isChidori && !isMaxSetup) { - chidoriLength = i % 2 === 0 ? 0 : height / 2 - intvHor + chidoriLength = installedModuleHeightCount % 2 == 0 ? 0 : height / 2 - intvVer } - square = [ - [startPoint.x1 - width * i + bottomMargin, startRowPoint - intvHor + tempMaxHeight * j + leftMargin + chidoriLength], - [startPoint.x1 - width * i - width + bottomMargin, startRowPoint - intvHor + tempMaxHeight * j + leftMargin + chidoriLength], - [startPoint.x1 - width * i - width + bottomMargin, startRowPoint - intvHor + tempMaxHeight * j + height + leftMargin + chidoriLength], - [startPoint.x1 - width * i + bottomMargin, startRowPoint - intvHor + tempMaxHeight * j + height + leftMargin + chidoriLength], - [startPoint.x1 - width * i + bottomMargin, startRowPoint - intvHor + tempMaxHeight * j + leftMargin + chidoriLength], + //치도리 일때 는 짝수(1 기준) 일때만 치도리 라인으로 본다 + if (isChidori && isChidoriLine) { + chidoriLength = width / 2 - height + } + + let square = [ + [moduleY - heightMargin, moduleX - height - widthMargin - chidoriLength], + [moduleY - heightMargin, moduleX - widthMargin - chidoriLength], + [moduleY - width - heightMargin, moduleX - widthMargin - chidoriLength], + [moduleY - width - heightMargin, moduleX - height - widthMargin - chidoriLength], + [moduleY - heightMargin, moduleX - height - widthMargin - chidoriLength], ] let squarePolygon = turf.polygon([square]) let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) - // if (disjointFromTrestle && isDisjoint) { moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module } let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) + let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true)) let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) if (disjointFromTrestle && isDisjoint) { - if (index > 0) { - setupModule.forEach((item) => { - const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) - if (!isOverlap) { - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } - }) - } else { - //최초 한번은 그냥 그린다 - //겹치는지 확인해서 포함된 모듈만 그린다 - canvas?.add(tempModule) - moduleSetupArray.push(tempModule) - moduleArray.push(tempModule) - canvas.renderAll() - } + //최초 한번은 그냥 그린다 + //겹치는지 확인해서 포함된 모듈만 그린다 + canvas?.add(tempModule) + moduleSetupArray.push(tempModule) + moduleArray.push(tempModule) + canvas.renderAll() + + // ++installedModuleHeightCount + + isInstall = true + //마지막에 설치된 모듈의 Y 좌표 + + // if (j === 0) { + // let startCircle = new fabric.Rect({ + // left: surfaceMaxLines.left.x1, + // top: installedLastHeightCoord, + // stroke: 'red', + // strokeWidth: 1, + // width: 5, + // height: 5, + // fill: 'red', + // originX: 'center', + // originY: 'center', + // }) + // canvas.add(startCircle) + // } } else { //디버깅용 - // tempModule.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) + // tempModule.set({ fill: 'transparent', stroke: 'red', strokeWidth: 1 }) // canvas?.add(tempModule) // canvas.renderAll() } } + + installedLastHeightCoord = moduleY + height + heightMargin + + if (isInstall) { + ++installedModuleHeightCount + } } + + // checkedModule.forEach((module, index) => { + // const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module) + // let flowLines = getFlowLines(moduleSetupSurface, width) + // //육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음 + // let startPoint = flowLines.left + // const moduleArray = [] + + // // if (flowLines.left.type === 'flat') { + // // const tempPoint = { ...flowLines.top } + // // startPoint = { ...flowLines.top, x1: tempPoint.x2, x2: tempPoint.x1 } + // // } else { + // // flowLines = getFlowLines(moduleSetupSurface, height) + // // const tempPoint = { ...flowLines.left } + // // startPoint = { ...flowLines.left, x1: tempPoint.x1 + 5, x2: tempPoint.x2, y1: tempPoint.y1 - 5 } + // // } + + // //중앙배치일 경우에는 계산한다 + // if (isCenter) { + // if (flowLines.left.type === 'flat' && flowLines.bottom.type === 'flat' && flowLines.top.type === 'flat') { + // //좌측 기준으로 양면이 직선이면 하단 방면으로 가운데로 배치 + // const halfWidthLength = Math.abs(startPoint.y1 + startPoint.y2) / 2 //밑에 길이에서 반을 가른다 + // const halfModuleWidthLength = height / 2 + // startPoint = { ...startPoint, y1: halfWidthLength - halfModuleWidthLength } + // if (flowLines.right.type === 'flat') { + // //우측까지 평면이면 직사각,정사각이라 가정하고 상자의 중심으로 계산 + // const widthLength = Math.abs(flowLines.top.x1 - flowLines.top.x2) //옆에에 길이에서 반을 가른다 + // const widthMargin = Math.abs(widthLength - width * Math.floor(widthLength / width)) / 2 + // startPoint = { ...startPoint, x1: startPoint.x1 + widthMargin } + // } + // } + // } + + // const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측 + // const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단 + // const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단 + + // let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌 + // let diffTopEndPoint = Math.abs(totalTopEndPoint / height) + // let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height) + // let totalWidth = Math.abs(startPoint.x1 - maxRightEndPoint) / width + // let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint) + + // let tempMaxHeight = isMaxSetup ? height / 2 : height //최대배치인지 확인하려고 넣음 + // if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려 서 반씩 검사 + + // for (let i = 0; i <= totalWidth; i++) { + // bottomMargin = i === 0 ? 0 : intvHor * i + // for (let j = 0; j < totalHeight; j++) { + // leftMargin = j === 0 ? 0 : intvVer * j + // chidoriLength = 0 + // if (isChidori && !isMaxSetup) { + // chidoriLength = i % 2 === 0 ? 0 : height / 2 + // } + + // square = [ + // [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + width + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + width + bottomMargin, startRowPoint + tempMaxHeight * j + height + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + height + leftMargin - chidoriLength], + // [startPoint.x1 + width * i + bottomMargin, startRowPoint + tempMaxHeight * j + leftMargin - chidoriLength], + // ] + + // let squarePolygon = turf.polygon([square]) + // let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) + // let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) + + // // if (disjointFromTrestle && isDisjoint) { + // moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module } + // let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) + // let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true)) + // let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects) + + // if (disjointFromTrestle && isDisjoint) { + // if (index > 0) { + // setupModule.forEach((item) => { + // const isOverlap = item.some((item2) => turf.booleanOverlap(squarePolygon, polygonToTurfPolygon(item2, true))) + // if (!isOverlap) { + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // }) + // } else { + // //최초 한번은 그냥 그린다 + // //겹치는지 확인해서 포함된 모듈만 그린다 + // canvas?.add(tempModule) + // moduleSetupArray.push(tempModule) + // moduleArray.push(tempModule) + // canvas.renderAll() + // } + // } else { + // //디버깅용 + // // tempModule.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 }) + // // canvas?.add(tempModule) + // // canvas.renderAll() + // } + // } + // } setupModule.push(moduleArray) }) } @@ -1516,6 +2209,7 @@ export function useModuleBasicSetting(tabNum) { const pointX2 = coords[2].x + ((coords[2].y - top) / (coords[2].y - coords[1].y)) * (coords[1].x - coords[2].x) const pointY2 = top + //디버깅 const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], { stroke: 'red', strokeWidth: 1, @@ -1524,8 +2218,8 @@ export function useModuleBasicSetting(tabNum) { // console.log(`index ${index} : finalLine`, pointX1, pointY1, pointX2, pointY2) - canvas?.add(finalLine) - canvas?.renderAll() + // canvas?.add(finalLine) + // canvas?.renderAll() let rtnObj //평평하면 @@ -1562,7 +2256,6 @@ export function useModuleBasicSetting(tabNum) { rtnObjArray.push(rtnObj) }) - return rtnObjArray } @@ -1642,13 +2335,14 @@ export function useModuleBasicSetting(tabNum) { const pointX2 = top const pointY2 = coords[2].y + ((coords[2].x - top) / (coords[2].x - coords[1].x)) * (coords[1].y - coords[2].y) + //디버깅용 const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], { stroke: 'red', strokeWidth: 1, selectable: true, }) - canvas?.add(finalLine) - canvas?.renderAll() + // canvas?.add(finalLine) + // canvas?.renderAll() let rtnObj //평평하면 @@ -1836,7 +2530,7 @@ export function useModuleBasicSetting(tabNum) { let tmpHeight = flowDirection === 'south' || flowDirection === 'north' ? moduleHeight : moduleWidth let { width, height } = - canvasSetting.roofSizeSet === '1' + canvasSetting.roofSizeSet == '1' ? calculateVisibleModuleHeight(tmpWidth, tmpHeight, getDegreeByChon(moduleSetupSurfaces[i].roofMaterial.pitch), flowDirection) : { width: tmpWidth, height: tmpHeight } @@ -2622,7 +3316,7 @@ export function useModuleBasicSetting(tabNum) { 10 } - return canvasSetting.roofSizeSet === '1' + return canvasSetting.roofSizeSet == '1' ? calculateVisibleModuleHeight(tmpWidth, tmpHeight, getDegreeByChon(moduleSetupSurface.roofMaterial.pitch), moduleSetupSurface.direction) : { width: tmpWidth, height: tmpHeight } } diff --git a/src/hooks/module/useTrestle.js b/src/hooks/module/useTrestle.js index 686643a7..3304d180 100644 --- a/src/hooks/module/useTrestle.js +++ b/src/hooks/module/useTrestle.js @@ -710,7 +710,7 @@ export const useTrestle = () => { slope, classType: currentAngleType === 'slope' ? '0' : '1', angle: getDegreeByChon(slope), - azimuth: surfaceCompass ?? moduleCompass ?? 0, + azimuth: getAzimuth(parent), moduleList, } }) @@ -726,6 +726,70 @@ export const useTrestle = () => { return { itemList, northArrangement, roofSurfaceList, circuitItemList } } + const getAzimuth = (parent) => { + const { moduleCompass, surfaceCompass, direction } = parent + + if (surfaceCompass) { + if (surfaceCompass > 180) { + return surfaceCompass - 360 + } + return surfaceCompass + } + + switch (direction) { + case 'south': { + if (moduleCompass < 0) { + return -1 * moduleCompass + } else if (moduleCompass === 0) { + return 0 + } else if (moduleCompass < 180) { + return -1 * moduleCompass + } else if (moduleCompass === 180) { + return 180 + } + } + case 'north': { + if (moduleCompass < 0) { + return -1 * (180 + moduleCompass) + } else if (moduleCompass === 0) { + return 180 + } else if (moduleCompass < 180) { + return 180 - moduleCompass + } else if (moduleCompass === 180) { + return 0 + } + } + case 'west': { + if (moduleCompass > -180 && moduleCompass < -90) { + return -180 - (90 + moduleCompass) + } else if (moduleCompass < 0) { + return 180 - (90 + moduleCompass) + } else if (moduleCompass === 0) { + return 90 + } else if (moduleCompass < 180) { + return 90 - moduleCompass + } else if (moduleCompass === 180) { + return -90 + } + } + case 'east': { + if (moduleCompass < 0) { + return -(90 + moduleCompass) + } else if (moduleCompass === 0) { + return -90 + } else if (moduleCompass < 90) { + return -180 + (90 - moduleCompass) + } else if (moduleCompass < 180) { + return 180 + (90 - moduleCompass) + } else if (moduleCompass === 180) { + return 90 + } + } + } + + return 0 + } + const getNorthArrangement = () => { const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) let northArrangement = '0' @@ -2086,7 +2150,7 @@ export const useTrestle = () => { moduleTpCd: module.itemTp, roofMatlCd: parent.roofMaterial.roofMatlCd, mixMatlNo: module.mixMatlNo, - raftBaseCd: addRoof.raft, + raftBaseCd: addRoof.raft ?? addRoof.raftBaseCd, inclCd: addRoof.pitch, roofPitch: !addRoof.roofPchBase ? addRoof.roofPchBase : Number(addRoof.roofPchBase), exposedLowerBottomTotCnt: result.exposedBottom, // 노출 최하면 갯수 diff --git a/src/hooks/option/useCanvasSetting.js b/src/hooks/option/useCanvasSetting.js index 179b2221..37161700 100644 --- a/src/hooks/option/useCanvasSetting.js +++ b/src/hooks/option/useCanvasSetting.js @@ -501,6 +501,67 @@ export function useCanvasSetting() { } } + /** + * 기본설정(PlacementShapeSetting) 복사 저장 + */ + const basicSettingCopySave = async (params) => { + try { + const patternData = { + objectNo: correntObjectNo, + planNo: Number(params.planNo), + roofSizeSet: Number(params.roofSizeSet), + roofAngleSet: params.roofAngleSet, + roofMaterialsAddList: params.roofsData.map((item) => ({ + planNo: Number(item.planNo), + roofApply: item.roofApply, + roofSeq: item.roofSeq, + roofMatlCd: item.roofMatlCd, + roofWidth: item.roofWidth, + roofHeight: item.roofHeight, + roofHajebichi: item.roofHajebichi, + roofGap: item.roofGap, + roofLayout: item.roofLayout, + roofPitch: item.roofPitch, + roofAngle: item.roofAngle, + })), + } + + await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }).then((res) => { + swalFire({ text: getMessage(res.returnMessage) }) + }) + + /* CanvasSetting Recoil 설정 - roofSizeSet을 문자열로 변환 */ + setCanvasSetting({ + ...basicSetting, + roofSizeSet: String(params.roofSizeSet), + }) + + /* 배치면초기설정 조회 */ + fetchBasicSettings(Number(params.planNo), null) + + /* 메뉴 설정 */ + if (['2', '3'].includes(params?.roofSizeSet)) { + setMenuNumber(3) + setType('surface') + setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING) + } else { + setMenuNumber(2) + setType('outline') + setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE) + } + + /* 모듈 선택 데이터 초기화 */ + resetModuleSelectionData() + moduleSelectedDataTrigger({ common: {}, module: {}, roofConstructions: [] }) + const isModuleExist = canvas.getObjects().some((obj) => obj.name === POLYGON_TYPE.MODULE) + if (!isModuleExist) { + resetSelectedModules() + } + } catch (error) { + swalFire({ text: error.message, icon: 'error' }) + } + } + /** * CanvasSetting 조회 및 초기화 */ @@ -878,7 +939,7 @@ export function useCanvasSetting() { optionName = ['rack', 'smartRack', 'bracket', 'eaveBar', 'halfEaveBar'] break case 'imageDisplay': - optionName = ['9'] + optionName = ['backGroundImage'] break case 'totalDisplay': /** @@ -915,6 +976,7 @@ export function useCanvasSetting() { setAdsorptionRange, fetchSettings, fetchBasicSettings, + basicSettingCopySave, frontSettings, globalFont, setGlobalFont, diff --git a/src/hooks/surface/useRoofLinePropertySetting.js b/src/hooks/surface/useRoofLinePropertySetting.js index ba5eedee..d6615ddf 100644 --- a/src/hooks/surface/useRoofLinePropertySetting.js +++ b/src/hooks/surface/useRoofLinePropertySetting.js @@ -15,7 +15,8 @@ const LINE_COLOR = { ACTIVE: '#EA10AC', } -export function useRoofLinePropertySetting(id, roof) { +export function useRoofLinePropertySetting(props) { + const { id, roof, setIsHidden } = props const canvas = useRecoilValue(canvasState) const currentObject = useRecoilValue(currentObjectState) const history = useRef([]) @@ -25,10 +26,20 @@ export function useRoofLinePropertySetting(id, roof) { useEffect(() => { if (currentObject && currentObject.name === 'roofLine') { + roof.lines.forEach((line) => { + const lineType = line.attributes?.type + if (!lineType) { + line.set({ + stroke: '#000000', + strokeWidth: 4, + }) + } + }) currentObject.set({ stroke: LINE_COLOR.ACTIVE, strokeWidth: 4, }) + canvas.renderAll() } }, [currentObject]) @@ -97,11 +108,8 @@ export function useRoofLinePropertySetting(id, roof) { } const lastLine = history.current.pop() - // delete lastLine.attributes - lastLine.attributes = { - ...lastLine.attributes, - type: null, - } + delete lastLine.attributes + lastLine.set({ stroke: LINE_COLOR.DEFAULT, strokeWidth: 4, @@ -132,6 +140,7 @@ export function useRoofLinePropertySetting(id, roof) { canvas.renderAll() closePopup(id) + if (setIsHidden) setIsHidden(false) } const nextLineFocus = (selectedLine) => { diff --git a/src/hooks/surface/useSurfaceShapeBatch.js b/src/hooks/surface/useSurfaceShapeBatch.js index a2625749..abb3688b 100644 --- a/src/hooks/surface/useSurfaceShapeBatch.js +++ b/src/hooks/surface/useSurfaceShapeBatch.js @@ -20,6 +20,8 @@ import { useRoofFn } from '@/hooks/common/useRoofFn' import { outerLinePointsState } from '@/store/outerLineAtom' import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom' import { getBackGroundImage } from '@/lib/imageActions' +import PlacementSurfaceLineProperty from '@/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty' +import { v4 as uuidv4 } from 'uuid' export function useSurfaceShapeBatch({ isHidden, setIsHidden }) { const { getMessage } = useMessage() @@ -35,7 +37,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) { const { swalFire } = useSwal() const { addCanvasMouseEventListener, initEvent } = useEvent() // const { addCanvasMouseEventListener, initEvent } = useContext(EventContext) - const { closePopup } = usePopup() + const { addPopup, closePopup } = usePopup() const { setSurfaceShapePattern } = useRoofFn() const currentCanvasPlan = useRecoilValue(currentCanvasPlanState) @@ -115,9 +117,13 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) { let imageRotate = 0 if (xInversion && !yInversion) { if (rotate % 180 === 0 || rotate < 0) { - imageRotate = Math.abs((rotate - 180) % 360) + imageRotate = Math.abs(rotate % 360) } else { - imageRotate = Math.abs((rotate + 180) % 4) + if (rotate < 0) { + imageRotate = Math.abs((rotate - 180) % 360) + } else { + imageRotate = Math.abs((rotate + 180) % 360) + } } } else if (xInversion && yInversion) { imageRotate = Math.abs((rotate + 360) % 360) @@ -134,7 +140,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) { } } } else { - imageRotate = (rotate + 360) % 360 + imageRotate = (rotate + 4) % 4 } obj.set({ angle: imageRotate }) obj.setCoords() //좌표 변경 적용 @@ -190,10 +196,12 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) { setSurfaceShapePattern(batchSurface, roofDisplay.column) drawDirectionArrow(batchSurface) - if (setIsHidden) setIsHidden(false) + // if (setIsHidden) setIsHidden(false) // closePopup(id) initEvent() + const popupId = uuidv4() + addPopup(popupId, 2, ) }) } else { if (setIsHidden) setIsHidden(false) diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js index 52be5c90..2afbe126 100644 --- a/src/hooks/useCanvas.js +++ b/src/hooks/useCanvas.js @@ -3,7 +3,7 @@ import { fabric } from 'fabric' import { actionHandler, anchorWrapper, polygonPositionHandler } from '@/util/canvas-util' -import { useRecoilState } from 'recoil' +import { useRecoilState, useRecoilValue } from 'recoil' import { canvasSizeState, canvasState, fontSizeState } from '@/store/canvasAtom' import { QLine } from '@/components/fabric/QLine' import { QPolygon } from '@/components/fabric/QPolygon' @@ -15,6 +15,7 @@ import { useAxios } from '@/hooks/useAxios' import { useFont } from '@/hooks/common/useFont' import { OBJECT_PROTOTYPE, POLYGON_TYPE, RELOAD_TYPE_PROTOTYPE, SAVE_KEY } from '@/common/common' import { usePlan } from './usePlan' +import { imageDisplaySelector } from '@/store/settingAtom' export function useCanvas(id) { const [canvas, setCanvas] = useRecoilState(canvasState) @@ -24,6 +25,7 @@ export function useCanvas(id) { const [canvasSize] = useRecoilState(canvasSizeState) const [fontSize] = useRecoilState(fontSizeState) const { setCanvasForEvent, attachDefaultEventOnCanvas } = useCanvasEvent() + const isImageDisplay = useRecoilValue(imageDisplaySelector) const {} = useFont() /** @@ -530,6 +532,7 @@ export function useCanvas(id) { lockRotation: false, lockScalingX: false, lockScalingY: false, + visible: isImageDisplay, }) // image = img canvas?.add(img) diff --git a/src/hooks/useCirCuitTrestle.js b/src/hooks/useCirCuitTrestle.js index aacc7e5d..8e73d59d 100644 --- a/src/hooks/useCirCuitTrestle.js +++ b/src/hooks/useCirCuitTrestle.js @@ -62,7 +62,6 @@ export function useCircuitTrestle() { // 사용된 모듈아이템 목록 const getUseModuleItemList = () => { - console.log('🚀 ~ getUseModuleItemList ~ selectedModules:', selectedModules) return selectedModules?.itemList?.map((m) => { return { itemId: m.itemId, diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index 01579ca7..10bc7e45 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -5,7 +5,7 @@ import { usePathname, useRouter } from 'next/navigation' import { useRecoilState, useResetRecoilState } from 'recoil' -import { canvasState, currentCanvasPlanState, plansState } from '@/store/canvasAtom' +import { canvasState, currentCanvasPlanState, plansState, canvasSettingState } from '@/store/canvasAtom' import { useAxios } from '@/hooks/useAxios' import { useMessage } from '@/hooks/useMessage' import { useSwal } from '@/hooks/useSwal' @@ -39,7 +39,8 @@ export function usePlan(params = {}) { const resetOuterLinePoints = useResetRecoilState(outerLinePointsState) const resetPlacementShapeDrawingPoints = useResetRecoilState(placementShapeDrawingPointsState) - const { fetchBasicSettings } = useCanvasSetting() + const { fetchBasicSettings, basicSettingCopySave } = useCanvasSetting() + const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) /** * 마우스 포인터의 가이드라인 제거 @@ -184,41 +185,55 @@ export function usePlan(params = {}) { objectNo: objectNo, copyFlg: '0', } - await promisePost({ url: '/api/object/add-plan', data: planData }) - .then((res) => { - let newPlan = { - id: res.data.canvasId, - objectNo: objectNo, - planNo: res.data.planNo, - userId: userId, - canvasStatus: '', - isCurrent: true, - bgImageName: null, - mapPositionAddress: null, - } + try { + const res = await promisePost({ url: '/api/object/add-plan', data: planData }) + let newPlan = { + id: res.data.canvasId, + objectNo: objectNo, + planNo: res.data.planNo, + userId: userId, + canvasStatus: '', + isCurrent: true, + bgImageName: null, + mapPositionAddress: null, + } - if (isInitPlan) { - /* 초기 플랜 생성인 경우 플랜 목록 초기화 */ - setCurrentCanvasPlan(newPlan) - setPlans([newPlan]) - } else { - if (isCopy) { - /* 복제 플랜 생성인 경우 현재 캔버스 데이터를 복제 */ - newPlan.canvasStatus = currentCanvasData() - newPlan.bgImageName = currentCanvasPlan?.bgImageName ?? null - newPlan.mapPositionAddress = currentCanvasPlan?.mapPositionAddress ?? null - } - setCurrentCanvasPlan(newPlan) - setPlans((plans) => [...plans.map((plan) => ({ ...plan, isCurrent: false })), newPlan]) - swalFire({ text: getMessage('plan.message.save') }) - } + if (isInitPlan) { + /* 초기 플랜 생성인 경우 플랜 목록 초기화 */ + setCurrentCanvasPlan(newPlan) + setPlans([newPlan]) /* 플랜 추가 시 배치면초기설정 정보 조회 */ fetchBasicSettings(newPlan.planNo, null) - }) - .catch((error) => { - swalFire({ text: error.response.data.message, icon: 'error' }) - }) + } else { + if (isCopy) { + /* 복제 플랜 생성인 경우 현재 캔버스 데이터를 복제 */ + newPlan.canvasStatus = currentCanvasData() + newPlan.bgImageName = currentCanvasPlan?.bgImageName ?? null + newPlan.mapPositionAddress = currentCanvasPlan?.mapPositionAddress ?? null + + /* 복제 시 배치면 초기설정 복사 */ + basicSettingCopySave({ + ...canvasSetting, + planNo: newPlan.planNo, + selectedRoofMaterial: { + ...canvasSetting.selectedRoofMaterial, + planNo: newPlan.planNo, + }, + roofsData: canvasSetting.roofsData.map((roof) => ({ + ...roof, + planNo: newPlan.planNo, + })), + }) + } + setCurrentCanvasPlan(newPlan) + setPlans((plans) => [...plans.map((plan) => ({ ...plan, isCurrent: false })), newPlan]) + + swalFire({ text: getMessage('plan.message.save') }) + } + } catch (error) { + swalFire({ text: error.response.data.message, icon: 'error' }) + } } /** @@ -275,7 +290,6 @@ export function usePlan(params = {}) { const objectNo = floorPlanState.objectNo //견적서 or 발전시뮬 - if (pathname !== '/floor-plan') { await promiseGet({ url: `/api/estimate/${objectNo}/${planNo}/detail` }) .then((res) => { @@ -304,9 +318,6 @@ export function usePlan(params = {}) { // 클릭한 플랜 탭으로 이동 setCurrentCanvasPlan(plans.find((plan) => plan.id === newCurrentId)) setPlans((plans) => plans.map((plan) => ({ ...plan, isCurrent: plan.id === newCurrentId }))) - - /* 플랜 이동 시 배치면초기설정 정보 조회 (견적서 메뉴 제외) */ - fetchBasicSettings(planNo, null) } else { swalFire({ text: getMessage('estimate.menu.move.valid1') }) } @@ -494,7 +505,13 @@ export function usePlan(params = {}) { * @param {string} planNo - 플랜번호 */ const deleteBasicSettings = async (objectNo, planNo) => { - await promiseDel({ url: `/api/canvas-management/canvas-basic-settings/delete-basic-settings/${objectNo}/${planNo}` }) + try { + await promiseDel({ url: `/api/canvas-management/canvas-basic-settings/delete-basic-settings/${objectNo}/${planNo}` }) + } catch (error) { + /* 오류를 무시하고 계속 진행 */ + console.log('Basic settings delete failed or not found:', error) + // swalFire({ text: error.message, icon: 'error' }) + } } return { diff --git a/src/locales/ja.json b/src/locales/ja.json index e78f57d7..677f9cab 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -663,9 +663,9 @@ "stuff.planReqPopup.title": "設計依頼のインポート", "stuff.temp.subTitle": "商品情報", "stuff.temp.subTitle2": "作図", - "stuff.detail.header.notExistObjectNo": "存在しないものです。", - "stuff.detail.header.successCopy": "物件番号がコピーされました。", - "stuff.detail.header.failCopy": "物件番号のコピーに失敗しました。", + "stuff.detail.header.notExistObjectNo": "存在しないもの番号です.", + "stuff.detail.header.successCopy": "物件番号がコピーされました.", + "stuff.detail.header.failCopy": "物件番号のコピーに失敗しました.", "stuff.detail.header.objectNo": "物件番号", "stuff.detail.header.specificationConfirmDate": "仕様確認日", "stuff.detail.header.lastEditDatetime": "更新日時", @@ -1013,6 +1013,8 @@ "module.place.select.one.module": "モジュールは1つだけ選択してください。", "batch.canvas.delete.all": "配置面の内容をすべて削除しますか?", "module.not.found": "インストールモジュールを選択してください。", + "module.circuit.minimun.error": "회로번호는 1 이상입력해주세요.(JA)", + "module.already.exist.error": "회로번호가 같은 다른 파워 컨디셔너 모듈이 있습니다. 다른 회로번호를 설정하십시오.(JA)", "construction.length.difference": "屋根面工法をすべて選択してください。", "menu.validation.canvas.roof": "パネルを配置するには、屋根面を入力する必要があります。", "batch.object.outside.roof": "オブジェクトは屋根に設置する必要があります。", diff --git a/src/locales/ko.json b/src/locales/ko.json index f898200a..67b4b301 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -663,7 +663,7 @@ "stuff.planReqPopup.title": "설계의뢰 불러오기", "stuff.temp.subTitle": "물건정보", "stuff.temp.subTitle2": "도면작성", - "stuff.detail.header.notExistObjectNo": "존재하지 않는 물건입니다.", + "stuff.detail.header.notExistObjectNo": "존재하지 않는 물건번호 입니다.", "stuff.detail.header.successCopy": "물건번호가 복사되었습니다.", "stuff.detail.header.failCopy": "물건번호 복사에 실패했습니다.", "stuff.detail.header.objectNo": "물건번호", @@ -1014,6 +1014,8 @@ "module.place.select.one.module": "모듈은 하나만 선택해주세요.", "batch.canvas.delete.all": "배치면 내용을 전부 삭제하시겠습니까?", "module.not.found": "모듈을 선택하세요.", + "module.circuit.minimun.error": "회로번호는 1 이상입력해주세요.", + "module.already.exist.error": "회로번호가 같은 다른 파워 컨디셔너 모듈이 있습니다. 다른 회로번호를 설정하십시오.", "construction.length.difference": "지붕면 공법을 전부 선택해주세요.", "menu.validation.canvas.roof": "패널을 배치하려면 지붕면을 입력해야 합니다.", "batch.object.outside.roof": "오브젝트는 지붕내에 설치해야 합니다.",