Merge branch 'dev' into feature/qcast-229

This commit is contained in:
basssy 2025-02-04 15:11:53 +09:00
commit 0624fb466b
19 changed files with 791 additions and 608 deletions

View File

@ -1,6 +1,7 @@
'use client' 'use client'
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import { useOnClickOutside } from 'usehooks-ts' import { useOnClickOutside } from 'usehooks-ts'
import { useMessage } from '@/hooks/useMessage'
/** /**
* *
@ -26,13 +27,15 @@ export default function QSelectBox({
showKey = '', showKey = '',
params = {}, params = {},
}) { }) {
const { getMessage } = useMessage()
/** /**
* 초기 상태 처리 * 초기 상태 처리
* useState 초기 값으로 사용해야 해서 useState 보다 위에 작성 * useState 초기 값으로 사용해야 해서 useState 보다 위에 작성
* @returns {string} 초기 상태 * @returns {string} 초기 상태
*/ */
const handleInitState = () => { const handleInitState = () => {
if (options.length === 0) return title !== '' ? title : '선택하세요.' if (options.length === 0) return title !== '' ? title : getMessage('selectbox.title')
if (showKey !== '' && !value) { if (showKey !== '' && !value) {
//value showKey //value showKey
// return options[0][showKey] // return options[0][showKey]
@ -44,13 +47,13 @@ export default function QSelectBox({
return option[sourceKey] === value[targetKey] return option[sourceKey] === value[targetKey]
}) })
if (!option) { if (!option) {
return title !== '' ? title : '선택하세요.' return title !== '' ? title : getMessage('selectbox.title')
} else { } else {
return option[showKey] return option[showKey]
} }
} else { } else {
// . // .
return title !== '' ? title : '선택하세요.' return title !== '' ? title : getMessage('selectbox.title')
} }
} }

View File

@ -25,26 +25,29 @@ import { useCommonUtils } from '@/hooks/common/useCommonUtils'
import useMenu from '@/hooks/common/useMenu' import useMenu from '@/hooks/common/useMenu'
import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController' import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController'
import { useAxios } from '@/hooks/useAxios' import { useAxios } from '@/hooks/useAxios'
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
import { canvasSettingState, canvasState, canvasZoomState, currentMenuState, verticalHorizontalModeState } from '@/store/canvasAtom' import { canvasSettingState, canvasState, canvasZoomState, currentMenuState, verticalHorizontalModeState } from '@/store/canvasAtom'
import { sessionStore } from '@/store/commonAtom' import { sessionStore } from '@/store/commonAtom'
import { outerLinePointsState } from '@/store/outerLineAtom' import { outerLinePointsState } from '@/store/outerLineAtom'
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
import { addedRoofsState, basicSettingState, selectedRoofMaterialSelector, settingModalFirstOptionsState } from '@/store/settingAtom' import {
addedRoofsState,
basicSettingState,
corridorDimensionSelector,
selectedRoofMaterialSelector,
settingModalFirstOptionsState,
} from '@/store/settingAtom'
import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom' import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom'
import { commonUtilsState } from '@/store/commonUtilsAtom' import { commonUtilsState } from '@/store/commonUtilsAtom'
import { menusState, menuTypeState } from '@/store/menuAtom' import { menusState, menuTypeState } from '@/store/menuAtom'
import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom' import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom'
import { pwrGnrSimTypeState } from '@/store/simulatorAtom' import { pwrGnrSimTypeState } from '@/store/simulatorAtom'
import { isObjectNotEmpty } from '@/util/common-utils' import { isObjectNotEmpty } from '@/util/common-utils'
import { POLYGON_TYPE } from '@/common/common'
import KO from '@/locales/ko.json' import KO from '@/locales/ko.json'
import JA from '@/locales/ja.json' import JA from '@/locales/ja.json'
import { MENU, POLYGON_TYPE } from '@/common/common'
import { QcastContext } from '@/app/QcastProvider' import { QcastContext } from '@/app/QcastProvider'
export default function CanvasMenu(props) { export default function CanvasMenu(props) {
const { menuNumber, setMenuNumber } = props const { menuNumber, setMenuNumber } = props
const pathname = usePathname() const pathname = usePathname()
@ -238,6 +241,16 @@ export default function CanvasMenu(props) {
if (menuNumber === 1) { if (menuNumber === 1) {
onClickPlacementInitialMenu() onClickPlacementInitialMenu()
} }
if (menuNumber === 3) {
const moduleSurfacesArray = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
if (moduleSurfacesArray.length > 0) {
moduleSurfacesArray.forEach((moduleSurface) => {
moduleSurface.modules = []
canvas.remove(moduleSurface)
})
canvas.renderAll()
}
}
}, [menuNumber, type]) }, [menuNumber, type])
// (btn08) // (btn08)
@ -508,8 +521,12 @@ export default function CanvasMenu(props) {
<div className="select-box"> <div className="select-box">
{ {
<QSelectBox <QSelectBox
showKey={'roofMatlNm'} //options={addedRoofs}
options={addedRoofs} options={addedRoofs.map((roof) => {
return { ...roof, name: globalLocale === 'ko' ? roof.roofMatlNm : roof.roofMatlNmJp }
})}
//showKey={'roofMatlNm'}
showKey={'name'}
value={selectedRoofMaterial} value={selectedRoofMaterial}
onChange={changeSelectedRoofMaterial} onChange={changeSelectedRoofMaterial}
sourceKey={'index'} sourceKey={'index'}

View File

@ -34,7 +34,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
const currentCanvasPlan = useRecoilValue(currentCanvasPlanState) const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
// const { initEvent } = useContext(EventContext) // const { initEvent } = useContext(EventContext)
const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup } = useModuleBasicSetting() const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup } = useModuleBasicSetting(1)
const { updateObjectDate } = useMasterController() const { updateObjectDate } = useMasterController()
const handleBtnNextStep = () => { const handleBtnNextStep = () => {
if (tabNum === 1) { if (tabNum === 1) {

View File

@ -120,7 +120,7 @@ export default function ModuleTabContents({ tabIndex, addRoof, setAddedRoofs, ro
value={selectedTrestle} value={selectedTrestle}
sourceKey={'trestleMkrCd'} sourceKey={'trestleMkrCd'}
targetKey={'trestleMkrCd'} targetKey={'trestleMkrCd'}
showKey={'trestleMkrCdNm'} showKey={'trestleMkrCdJp'}
onChange={handleChangeTrestle} onChange={handleChangeTrestle}
/> />
)} )}
@ -138,7 +138,7 @@ export default function ModuleTabContents({ tabIndex, addRoof, setAddedRoofs, ro
value={selectedConstMthd} value={selectedConstMthd}
sourceKey={'constMthdCd'} sourceKey={'constMthdCd'}
targetKey={'constMthdCd'} targetKey={'constMthdCd'}
showKey={'constMthdCdNm'} showKey={'constMthdCdJp'}
onChange={handleChangeConstMthd} onChange={handleChangeConstMthd}
/> />
)} )}
@ -156,7 +156,7 @@ export default function ModuleTabContents({ tabIndex, addRoof, setAddedRoofs, ro
value={selectedRoofBase} value={selectedRoofBase}
sourceKey={'roofBaseCd'} sourceKey={'roofBaseCd'}
targetKey={'roofBaseCd'} targetKey={'roofBaseCd'}
showKey={'roofBaseCdNm'} showKey={'roofBaseCdJp'}
onChange={handleChangeRoofBase} onChange={handleChangeRoofBase}
/> />
)} )}

View File

@ -4,20 +4,17 @@ import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
import { checkedModuleState, currentCanvasPlanState } from '@/store/canvasAtom' import { checkedModuleState, currentCanvasPlanState } from '@/store/canvasAtom'
import { useRecoilValue, useSetRecoilState } from 'recoil' import { useRecoilValue, useSetRecoilState } from 'recoil'
import { moduleSelectionDataState } from '@/store/selectedModuleOptions' import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
import { useModulePlace } from '@/hooks/module/useModulePlace'
const Placement = forwardRef((props, refs) => { const Placement = forwardRef((props, refs) => {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const [isChidori, setIsChidori] = useState(false) const [isChidori, setIsChidori] = useState(false)
const [isChidoriNotAble, setIsChidoriNotAble] = useState(false) const [isChidoriNotAble, setIsChidoriNotAble] = useState(false)
const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
const [setupLocation, setSetupLocation] = useState('center') const [setupLocation, setSetupLocation] = useState('center')
const [isMaxSetup, setIsMaxSetup] = useState('false') const [isMaxSetup, setIsMaxSetup] = useState('false')
const [selectedItems, setSelectedItems] = useState({}) const [selectedItems, setSelectedItems] = useState({})
const { makeModuleInstArea } = useModuleBasicSetting() const { selectedModules } = useModuleBasicSetting(3)
const { selectedModules } = useModulePlace()
const setCheckedModules = useSetRecoilState(checkedModuleState) const setCheckedModules = useSetRecoilState(checkedModuleState)
const moduleSelectionData = useRecoilValue(moduleSelectionDataState) const moduleSelectionData = useRecoilValue(moduleSelectionDataState)

View File

@ -356,7 +356,7 @@ export default function CircuitTrestleSetting({ id }) {
} }
// () // ()
const onApply = () => { const onApply = async () => {
canvas canvas
.getObjects() .getObjects()
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
@ -364,8 +364,7 @@ export default function CircuitTrestleSetting({ id }) {
obj.pcses = getStepUpListData() obj.pcses = getStepUpListData()
}) })
console.log(canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)) const result = await apply()
apply()
} }
const onClickPrev = () => { const onClickPrev = () => {

View File

@ -258,7 +258,11 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
<div className="grid-select no-flx" style={{ width: '171px' }}> <div className="grid-select no-flx" style={{ width: '171px' }}>
<QSelectBox <QSelectBox
title={ title={
currentRoof?.roofSizeSet === '3' ? getMessage('modal.placement.initial.setting.size.none.pitch') : currentRoof?.roofMatlNm currentRoof?.roofSizeSet === '3'
? getMessage('modal.placement.initial.setting.size.none.pitch')
: globalLocale === 'ko'
? currentRoof?.roofMatlNm
: currentRoof?.roofMatlNmJp
} }
//ref={roofRef.roofCd} //ref={roofRef.roofCd}
options={roofMaterials.map((roof) => { options={roofMaterials.map((roof) => {

View File

@ -21,7 +21,7 @@ export function useCommonUtils() {
const commonTextFont = useRecoilValue(fontSelector('commonText')) const commonTextFont = useRecoilValue(fontSelector('commonText'))
const [commonUtils, setCommonUtilsState] = useRecoilState(commonUtilsState) const [commonUtils, setCommonUtilsState] = useRecoilState(commonUtilsState)
const { addPopup } = usePopup() const { addPopup } = usePopup()
const { drawDirectionArrow } = usePolygon() const { drawDirectionArrow, addLengthText } = usePolygon()
useEffect(() => { useEffect(() => {
// initEvent() // initEvent()
@ -610,17 +610,17 @@ export function useCommonUtils() {
//객체가 그룹일 경우에는 그룹 아이디를 따로 넣어준다 //객체가 그룹일 경우에는 그룹 아이디를 따로 넣어준다
if (clonedObj.type === 'group') clonedObj.set({ groupId: uuidv4() }) if (clonedObj.type === 'group') clonedObj.set({ groupId: uuidv4() })
initEvent()
//배치면일 경우 //배치면일 경우
if (obj.name === 'roof') { if (obj.name === 'roof') {
clonedObj.setCoords() clonedObj.setCoords()
clonedObj.fire('polygonMoved') clonedObj.fire('polygonMoved')
clonedObj.set({ direction: obj.direction, directionText: obj.directionText }) clonedObj.set({ direction: obj.direction, directionText: obj.directionText })
clonedObj.addLengthText()
canvas.renderAll() canvas.renderAll()
drawDirectionArrow(clonedObj) addLengthText(clonedObj) //수치 추가
drawDirectionArrow(clonedObj) //방향 화살표 추가
} }
initEvent()
}) })
} }
} }

View File

@ -229,9 +229,7 @@ export function useMasterController() {
* @returns * @returns
*/ */
const updateObjectDate = async (params = null) => { const updateObjectDate = async (params = null) => {
return await put({ url: '/api/object/update-object-date', data: params }).then((res) => { return await put({ url: '/api/object/update-object-date', data: params })
console.log('updateObjectDate', res)
})
} }
return { return {

View File

@ -1,5 +1,6 @@
import { useState } from 'react'
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { canvasSettingState, canvasState, checkedModuleState, isManualModuleSetupState, selectedModuleState } from '@/store/canvasAtom' import { canvasSettingState, canvasState, checkedModuleState, isManualModuleSetupState } from '@/store/canvasAtom'
import { rectToPolygon, polygonToTurfPolygon, calculateVisibleModuleHeight, getDegreeByChon } from '@/util/canvas-util' import { rectToPolygon, polygonToTurfPolygon, calculateVisibleModuleHeight, getDegreeByChon } from '@/util/canvas-util'
import { basicSettingState, roofDisplaySelector } from '@/store/settingAtom' import { basicSettingState, roofDisplaySelector } from '@/store/settingAtom'
import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils' import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils'
@ -15,14 +16,17 @@ import { useRoofFn } from '@/hooks/common/useRoofFn'
import { useEffect } from 'react' import { useEffect } from 'react'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { moduleStatisticsState } from '@/store/circuitTrestleAtom' import { moduleStatisticsState } from '@/store/circuitTrestleAtom'
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
import { useMasterController } from '@/hooks/common/useMasterController'
import { v4 as uuidv4 } from 'uuid'
export function useModuleBasicSetting() { export function useModuleBasicSetting(tabNum) {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const { getMessage } = useMessage() const { getMessage } = useMessage()
const roofDisplay = useRecoilValue(roofDisplaySelector) const roofDisplay = useRecoilValue(roofDisplaySelector)
const [moduleSetupSurface, setModuleSetupSurface] = useRecoilState(moduleSetupSurfaceState) const [moduleSetupSurface, setModuleSetupSurface] = useRecoilState(moduleSetupSurfaceState)
const [moduleIsSetup, setModuleIsSetup] = useRecoilState(moduleIsSetupState) const [moduleIsSetup, setModuleIsSetup] = useRecoilState(moduleIsSetupState)
const { addCanvasMouseEventListener, initEvent, removeMouseEvent } = useEvent() const { addCanvasMouseEventListener, initEvent, removeMouseEvent, addTargetMouseEventListener } = useEvent()
const { swalFire } = useSwal() const { swalFire } = useSwal()
const compasDeg = useRecoilValue(compasDegAtom) const compasDeg = useRecoilValue(compasDegAtom)
@ -34,6 +38,13 @@ export function useModuleBasicSetting() {
const canvasSetting = useRecoilValue(canvasSettingState) const canvasSetting = useRecoilValue(canvasSettingState)
const moduleSelectionData = useRecoilValue(moduleSelectionDataState)
const [trestleDetailParams, setTrestleDetailParams] = useState([])
const [trestleDetailList, setTrestleDetailList] = useState([])
const selectedModules = useRecoilValue(selectedModuleState)
const { getTrestleDetailList } = useMasterController()
const [saleStoreNorthFlg, setSaleStoreNorthFlg] = useState(false)
useEffect(() => { useEffect(() => {
// console.log('basicSetting', basicSetting) // console.log('basicSetting', basicSetting)
if (canvas) { if (canvas) {
@ -47,6 +58,247 @@ export function useModuleBasicSetting() {
// const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useContext(EventContext) // const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useContext(EventContext)
//모듈 선택에서 선택된 값들 넘어옴
useEffect(() => {
if (moduleSelectionData && tabNum === 3) {
const common = moduleSelectionData.common
const roofConstructions = moduleSelectionData.roofConstructions
const listParams = roofConstructions.map((item) => {
return {
...common,
moduleTpCd: selectedModules.itemTp,
roofMatlCd: item.trestle.roofMatlCd,
trestleMkrCd: item.trestle.trestleMkrCd,
constMthdCd: item.trestle.constMthdCd,
roofBaseCd: item.trestle.roofBaseCd,
constTp: item.construction.constTp,
mixMatlNo: selectedModules.mixMatlNo,
roofPitch: item.addRoof.hajebichi ? item.addRoof.hajebichi : 0,
inclCd: String(item.addRoof.pitch),
roofIndex: item.addRoof.index,
workingWidth: item.addRoof.lenBase,
}
})
setTrestleDetailParams(listParams)
//북면 설치 가능 판매점
if (moduleSelectionData.common.saleStoreNorthFlg === '1') {
setSaleStoreNorthFlg(true)
}
}
}, [moduleSelectionData])
//가대 상세 데이터 조회
const getTrestleDetailListData = async () => {
const trestleDetailList = await getTrestleDetailList(trestleDetailParams)
if (trestleDetailList.length > 0) {
setTrestleDetailList(trestleDetailList)
}
}
//가대 상세 데이터 파라메터 담기면 실행
useEffect(() => {
if (trestleDetailParams.length > 0) {
getTrestleDetailListData(trestleDetailParams)
}
}, [trestleDetailParams])
//가대 상세 데이터 들어오면 실행
useEffect(() => {
if (trestleDetailList.length > 0) {
//지붕을 가져옴
canvas
.getObjects()
.filter((roof) => roof.name === 'roof')
.forEach((roof) => {
const roofIndex = roof.roofMaterial.index //지붕의 지붕재의 순번
trestleDetailList.forEach((detail) => {
if (detail.data !== null) {
if (Number(detail.data.roofIndex) === roofIndex) {
//roof에 상세 데이터 추가
roof.set({ trestleDetail: detail.data })
//배치면 설치 영역
makeModuleInstArea(roof, detail.data)
//surface에 상세 데이터 추가
} else {
console.log('가대 데이터가 없네요...')
}
}
})
})
}
}, [trestleDetailList])
//가대 상세 데이터 기준으로 모듈 설치 배치면 생성
const makeModuleInstArea = (roof, trestleDetail) => {
//지붕 객체 반환
if (!roof) {
return
}
//도머등 오브젝트 객체가 있으면 아웃라인 낸다
const batchObjects = canvas
?.getObjects()
.filter(
(obj) =>
obj.name === BATCH_TYPE.OPENING ||
obj.name === BATCH_TYPE.SHADOW ||
obj.name === BATCH_TYPE.TRIANGLE_DORMER ||
obj.name === BATCH_TYPE.PENTAGON_DORMER,
) //도머s 객체
//도머도 외곽을 따야한다
const batchObjectOptions = {
stroke: 'red',
fill: 'transparent',
strokeDashArray: [10, 4],
strokeWidth: 1,
lockMovementX: true,
lockMovementY: true,
lockRotation: true,
lockScalingX: true,
lockScalingY: true,
selectable: true,
name: POLYGON_TYPE.OBJECT_SURFACE,
originX: 'center',
originY: 'center',
}
//도머등 오브젝트 객체가 있으면 아웃라인 낸다
batchObjects.forEach((obj) => {
//도머일때
if (obj.name === BATCH_TYPE.TRIANGLE_DORMER || obj.name === BATCH_TYPE.PENTAGON_DORMER) {
const groupPoints = obj.groupPoints
const offsetObjects = offsetPolygon(groupPoints, 10)
const dormerOffset = new QPolygon(offsetObjects, batchObjectOptions)
dormerOffset.setViewLengthText(false)
canvas.add(dormerOffset) //모듈설치면 만들기
} else {
//개구, 그림자일때
const points = obj.points
const offsetObjects = offsetPolygon(points, 10)
const offset = new QPolygon(offsetObjects, batchObjectOptions)
offset.setViewLengthText(false)
canvas.add(offset) //모듈설치면 만들기
}
})
const isExistSurface = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.parentId === roof.id)
if (isExistSurface) {
return
}
let offsetLength = canvasSetting.roofSizeSet === 3 ? -90 : (trestleDetail.eaveIntvl / 10) * -1
setSurfaceShapePattern(roof, roofDisplay.column, true) //패턴 변경
const offsetPoints = offsetPolygon(roof.points, offsetLength) //안쪽 offset
//모듈설치영역?? 생성
const surfaceId = uuidv4()
let isNorth = false
//북면이 있지만
if (roof.directionText && roof.directionText.indexOf('北') > -1) {
//북쪽일때 해당 서북서, 동북동은 제외한다고 한다
if (!(roof.directionText.indexOf('西北西') > -1 || roof.directionText.indexOf('東北東') > -1)) {
isNorth = true
}
}
//모듈설치면 생성
let setupSurface = new QPolygon(offsetPoints, {
stroke: 'red',
fill: 'rgba(255,255,255,0.1)',
strokeDashArray: [10, 4],
strokeWidth: 1,
lockMovementX: true,
lockMovementY: true,
lockRotation: true,
lockScalingX: true,
lockScalingY: true,
selectable: true,
parentId: roof.id, //가대 폴리곤의 임시 인덱스를 넣어줌
name: POLYGON_TYPE.MODULE_SETUP_SURFACE,
flowDirection: roof.direction,
direction: roof.direction,
flipX: roof.flipX,
flipY: roof.flipY,
surfaceId: surfaceId,
originX: 'center',
originY: 'center',
modules: [],
roofMaterial: roof.roofMaterial,
trestleDetail: trestleDetail,
isNorth: isNorth,
perPixelTargetFind: true,
// angle: -compasDeg,
})
setupSurface.setViewLengthText(false)
canvas.add(setupSurface) //모듈설치면 만들기
//지붕면 선택 금지
roof.set({
selectable: false, //선택 금지
evented: false, //클릭 이벤트도 금지
})
canvas.renderAll()
//모듈설치면 클릭이벤트
addTargetMouseEventListener('mousedown', setupSurface, function () {
toggleSelection(setupSurface)
})
}
let selectedModuleInstSurfaceArray = []
//설치 범위 지정 클릭 이벤트
const toggleSelection = (setupSurface) => {
const isExist = selectedModuleInstSurfaceArray.some((obj) => obj.parentId === setupSurface.parentId)
//최초 선택일때
if (!isExist) {
//설치면이 북면이고 북면설치 허용점이 아니면
if (setupSurface.isNorth && !saleStoreNorthFlg) {
swalFire({ text: getMessage('module.not.batch.north'), icon: 'warning' })
return
}
//기본 선택이랑 스트로크 굵기가 같으면 선택 안됨으로 봄
setupSurface.set({
...setupSurface,
strokeWidth: 3,
strokeDashArray: [0],
fill: 'rgba(255,255,255,0.1)',
})
canvas.discardActiveObject() // 객체의 활성 상태 해제
//중복으로 들어가는걸 방지하기 위한 코드
canvas?.renderAll()
selectedModuleInstSurfaceArray.push(setupSurface)
} else {
//선택후 재선택하면 선택안됨으로 변경
setupSurface.set({
...setupSurface,
fill: 'rgba(255,255,255,0.1)',
strokeDashArray: [10, 4],
strokeWidth: 1,
})
canvas.discardActiveObject() // 객체의 활성 상태 해제
//폴리곤에 커스텀 인덱스를 가지고 해당 배열 인덱스를 찾아 삭제함
const removeIndex = setupSurface.parentId
const removeArrayIndex = selectedModuleInstSurfaceArray.findIndex((obj) => obj.parentId === removeIndex)
selectedModuleInstSurfaceArray.splice(removeArrayIndex, 1)
}
canvas?.renderAll()
setModuleSetupSurface([...selectedModuleInstSurfaceArray])
}
//모듈,회로에서 다른메뉴 -> 배치면으로 갈 경수 초기화 //모듈,회로에서 다른메뉴 -> 배치면으로 갈 경수 초기화
const restoreModuleInstArea = () => { const restoreModuleInstArea = () => {
//설치면 삭제 //설치면 삭제
@ -76,6 +328,7 @@ export function useModuleBasicSetting() {
*/ */
const manualModuleSetup = () => { const manualModuleSetup = () => {
// console.log('isManualModuleSetup', isManualModuleSetup) // console.log('isManualModuleSetup', isManualModuleSetup)
const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴
if (isManualModuleSetup) { if (isManualModuleSetup) {
if (checkedModule.length === 0) { if (checkedModule.length === 0) {
@ -90,8 +343,14 @@ export function useModuleBasicSetting() {
return return
} }
const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴
const batchObjects = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.OBJECT_SURFACE) //도머s 객체 const batchObjects = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.OBJECT_SURFACE) //도머s 객체
//수동모드 모듈 설치면 선택 잠금
moduleSetupSurfaces.forEach((obj) => {
obj.set({
selectable: false,
evented: false,
})
})
const moduleOptions = { const moduleOptions = {
fill: checkedModule[0].color, fill: checkedModule[0].color,
@ -168,7 +427,12 @@ export function useModuleBasicSetting() {
parentId: moduleSetupSurfaces[i].parentId, parentId: moduleSetupSurfaces[i].parentId,
}) })
canvas?.add(tempModule) //움직여가면서 추가됨 //북면이고 북면설치상점이 아니면 그냥 return
if (trestlePolygon.isNorth && !saleStoreNorthFlg) {
return
} else {
canvas?.add(tempModule) //움직여가면서 추가됨
}
/** /**
* 스냅기능 * 스냅기능
@ -361,6 +625,7 @@ export function useModuleBasicSetting() {
const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인
if (!isOverlap) { if (!isOverlap) {
canvas?.remove(tempModule) canvas?.remove(tempModule)
//안겹치면 넣는다 //안겹치면 넣는다
// tempModule.setCoords() // tempModule.setCoords()
moduleOptions.surfaceId = trestlePolygon.id moduleOptions.surfaceId = trestlePolygon.id
@ -379,6 +644,14 @@ export function useModuleBasicSetting() {
}) })
} }
} else { } else {
//수동모드 해제시 모듈 설치면 선택 잠금
moduleSetupSurfaces.forEach((obj) => {
obj.set({
selectable: true,
evented: true,
})
})
removeMouseEvent('mouse:up') removeMouseEvent('mouse:up')
removeMouseEvent('mouse:move') removeMouseEvent('mouse:move')
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) //움직일때 일단 지워가면서 움직임 canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) //움직일때 일단 지워가면서 움직임
@ -2209,6 +2482,7 @@ export function useModuleBasicSetting() {
} }
return { return {
selectedModules,
manualModuleSetup, manualModuleSetup,
autoModuleSetup, autoModuleSetup,
restoreModuleInstArea, restoreModuleInstArea,

View File

@ -10,6 +10,8 @@ import offsetPolygon from '@/util/qpolygon-utils'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import { QPolygon } from '@/components/fabric/QPolygon' import { QPolygon } from '@/components/fabric/QPolygon'
import { useEvent } from '@/hooks/useEvent' import { useEvent } from '@/hooks/useEvent'
import { useSwal } from '@/hooks/useSwal'
import { useMessage } from '@/hooks/useMessage'
export function useModulePlace() { export function useModulePlace() {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
@ -23,211 +25,9 @@ export function useModulePlace() {
const roofDisplay = useRecoilValue(roofDisplaySelector) const roofDisplay = useRecoilValue(roofDisplaySelector)
const { addTargetMouseEventListener } = useEvent() const { addTargetMouseEventListener } = useEvent()
const setModuleSetupSurface = useSetRecoilState(moduleSetupSurfaceState) const setModuleSetupSurface = useSetRecoilState(moduleSetupSurfaceState)
const [saleStoreNorthFlg, setSaleStoreNorthFlg] = useState(false)
useEffect(() => { const { swalFire } = useSwal()
if (moduleSelectionData) { const { getMessage } = useMessage()
const common = moduleSelectionData.common
const roofConstructions = moduleSelectionData.roofConstructions
const listParams = roofConstructions.map((item) => {
return {
...common,
moduleTpCd: selectedModules.itemTp,
roofMatlCd: item.trestle.roofMatlCd,
trestleMkrCd: item.trestle.trestleMkrCd,
constMthdCd: item.trestle.constMthdCd,
roofBaseCd: item.trestle.roofBaseCd,
constTp: item.construction.constTp,
mixMatlNo: selectedModules.mixMatlNo,
roofPitch: item.addRoof.hajebichi ? item.addRoof.hajebichi : 0,
inclCd: String(item.addRoof.pitch),
roofIndex: item.addRoof.index,
workingWidth: item.addRoof.lenBase,
}
})
setTrestleDetailParams(listParams)
}
}, [moduleSelectionData])
const getTrestleDetailListData = async () => {
const trestleDetailList = await getTrestleDetailList(trestleDetailParams)
if (trestleDetailList.length > 0) {
setTrestleDetailList(trestleDetailList)
}
}
useEffect(() => {
if (trestleDetailParams.length > 0) {
getTrestleDetailListData(trestleDetailParams)
}
}, [trestleDetailParams])
useEffect(() => {
if (trestleDetailList.length > 0) {
//지붕을 가져옴
canvas
.getObjects()
.filter((roof) => roof.name === 'roof')
.forEach((roof) => {
const roofIndex = roof.roofMaterial.index //지붕의 지붕재의 순번
trestleDetailList.forEach((detail) => {
if (detail.data !== null) {
if (Number(detail.data.roofIndex) === roofIndex) {
//roof에 상세 데이터 추가
roof.set({ trestleDetail: detail.data })
//배치면 설치 영역
makeModuleInstArea(roof, detail.data)
//surface에 상세 데이터 추가
} else {
console.log('가대 데이터가 없네요...')
}
}
})
})
}
}, [trestleDetailList])
const makeModuleInstArea = (roof, trestleDetail) => {
//지붕 객체 반환
if (!roof) {
return
}
const batchObjects = canvas
?.getObjects()
.filter(
(obj) =>
obj.name === BATCH_TYPE.OPENING ||
obj.name === BATCH_TYPE.SHADOW ||
obj.name === BATCH_TYPE.TRIANGLE_DORMER ||
obj.name === BATCH_TYPE.PENTAGON_DORMER,
) //도머s 객체
//도머도 외곽을 따야한다
const batchObjectOptions = {
stroke: 'red',
fill: 'transparent',
strokeDashArray: [10, 4],
strokeWidth: 1,
lockMovementX: true,
lockMovementY: true,
lockRotation: true,
lockScalingX: true,
lockScalingY: true,
selectable: true,
name: POLYGON_TYPE.OBJECT_SURFACE,
originX: 'center',
originY: 'center',
}
batchObjects.forEach((obj) => {
if (obj.name === BATCH_TYPE.TRIANGLE_DORMER || obj.name === BATCH_TYPE.PENTAGON_DORMER) {
const groupPoints = obj.groupPoints
const offsetObjects = offsetPolygon(groupPoints, 10)
const dormerOffset = new QPolygon(offsetObjects, batchObjectOptions)
dormerOffset.setViewLengthText(false)
canvas.add(dormerOffset) //모듈설치면 만들기
} else {
const points = obj.points
const offsetObjects = offsetPolygon(points, 10)
const offset = new QPolygon(offsetObjects, batchObjectOptions)
offset.setViewLengthText(false)
canvas.add(offset) //모듈설치면 만들기
}
})
const isExistSurface = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.parentId === roof.id)
if (isExistSurface) {
return
}
let offsetLength = canvasSetting.roofSizeSet === 3 ? -90 : (trestleDetail.eaveIntvl / 10) * -1
setSurfaceShapePattern(roof, roofDisplay.column, true) //패턴 변경
const offsetPoints = offsetPolygon(roof.points, offsetLength) //안쪽 offset
//모듈설치영역?? 생성
const surfaceId = uuidv4()
let setupSurface = new QPolygon(offsetPoints, {
stroke: 'red',
fill: 'transparent',
strokeDashArray: [10, 4],
strokeWidth: 1,
lockMovementX: true,
lockMovementY: true,
lockRotation: true,
lockScalingX: true,
lockScalingY: true,
selectable: true,
parentId: roof.id, //가대 폴리곤의 임시 인덱스를 넣어줌
name: POLYGON_TYPE.MODULE_SETUP_SURFACE,
flowDirection: roof.direction,
direction: roof.direction,
flipX: roof.flipX,
flipY: roof.flipY,
surfaceId: surfaceId,
originX: 'center',
originY: 'center',
modules: [],
roofMaterial: roof.roofMaterial,
trestleDetail: trestleDetail,
// angle: -compasDeg,
})
setupSurface.setViewLengthText(false)
canvas.add(setupSurface) //모듈설치면 만들기
//지붕면 선택 금지
roof.set({
selectable: false,
})
//모듈설치면 클릭이벤트
addTargetMouseEventListener('mousedown', setupSurface, function () {
toggleSelection(setupSurface)
})
}
let selectedModuleInstSurfaceArray = []
//설치 범위 지정 클릭 이벤트
const toggleSelection = (setupSurface) => {
const isExist = selectedModuleInstSurfaceArray.some((obj) => obj.parentId === setupSurface.parentId)
//최초 선택일때
if (!isExist) {
//기본 선택이랑 스트로크 굵기가 같으면 선택 안됨으로 봄
setupSurface.set({
...setupSurface,
strokeWidth: 3,
strokeDashArray: [0],
fill: 'transparent',
})
canvas.discardActiveObject() // 객체의 활성 상태 해제
//중복으로 들어가는걸 방지하기 위한 코드
canvas?.renderAll()
selectedModuleInstSurfaceArray.push(setupSurface)
} else {
//선택후 재선택하면 선택안됨으로 변경
setupSurface.set({
...setupSurface,
fill: 'transparent',
strokeDashArray: [10, 4],
strokeWidth: 1,
})
canvas.discardActiveObject() // 객체의 활성 상태 해제
//폴리곤에 커스텀 인덱스를 가지고 해당 배열 인덱스를 찾아 삭제함
const removeIndex = setupSurface.parentId
const removeArrayIndex = selectedModuleInstSurfaceArray.findIndex((obj) => obj.parentId === removeIndex)
selectedModuleInstSurfaceArray.splice(removeArrayIndex, 1)
}
canvas?.renderAll()
setModuleSetupSurface([...selectedModuleInstSurfaceArray])
}
return { return {
selectedModules, selectedModules,

View File

@ -5,8 +5,11 @@ import { useMasterController } from '@/hooks/common/useMasterController'
import { useCommonCode } from '@/hooks/common/useCommonCode' import { useCommonCode } from '@/hooks/common/useCommonCode'
import { selectedModuleState, moduleSelectionInitParamsState, moduleSelectionDataState } from '@/store/selectedModuleOptions' import { selectedModuleState, moduleSelectionInitParamsState, moduleSelectionDataState } from '@/store/selectedModuleOptions'
import { isObjectNotEmpty } from '@/util/common-utils' import { isObjectNotEmpty } from '@/util/common-utils'
import { canvasState } from '@/store/canvasAtom'
import { POLYGON_TYPE } from '@/common/common'
export function useModuleSelection(props) { export function useModuleSelection(props) {
const canvas = useRecoilValue(canvasState)
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext) const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
const [roughnessCodes, setRoughnessCodes] = useState([]) //면조도 목록 const [roughnessCodes, setRoughnessCodes] = useState([]) //면조도 목록
@ -41,6 +44,7 @@ export function useModuleSelection(props) {
instHt: managementState?.installHeight, //설치높이 instHt: managementState?.installHeight, //설치높이
stdWindSpeed: managementState?.standardWindSpeedId, //기준풍속 stdWindSpeed: managementState?.standardWindSpeedId, //기준풍속
stdSnowLd: managementState?.verticalSnowCover, //기준적설량 stdSnowLd: managementState?.verticalSnowCover, //기준적설량
saleStoreNorthFlg: managementState?.saleStoreNorthFlg, //북쪽 설치 여부
} }
if (selectedModules) { if (selectedModules) {
@ -62,6 +66,7 @@ export function useModuleSelection(props) {
// 202000 풍속 // 202000 풍속
const windCodeList = findCommonCode('202000') const windCodeList = findCommonCode('202000')
windCodeList.forEach((obj) => { windCodeList.forEach((obj) => {
obj.name = obj.clCodeNm obj.name = obj.clCodeNm
obj.id = obj.clCode obj.id = obj.clCode
@ -83,6 +88,16 @@ export function useModuleSelection(props) {
} }
getModuleData(roofsIds) getModuleData(roofsIds)
//메뉴 이동시 배치면 삭제
const moduleSurfacesArray = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
if (moduleSurfacesArray.length > 0) {
moduleSurfacesArray.forEach((moduleSurface) => {
moduleSurface.module = []
canvas.remove(moduleSurface)
})
canvas.renderAll()
}
}, []) }, [])
const getModuleData = async (roofsIds) => { const getModuleData = async (roofsIds) => {

View File

@ -299,6 +299,7 @@ export function useModuleTabContents({ tabIndex, addRoof, setAddedRoofs, roofTab
//거대메이커, 공법, 지붕밑바탕 api 조회 //거대메이커, 공법, 지붕밑바탕 api 조회
const getModuleOptionsListData = async (params, type) => { const getModuleOptionsListData = async (params, type) => {
const optionsList = await getTrestleList(params) const optionsList = await getTrestleList(params)
console.log('optionsList', optionsList)
if (optionsList.data.length > 0) { if (optionsList.data.length > 0) {
if (type === 'trestle') { if (type === 'trestle') {

View File

@ -1,5 +1,5 @@
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom' import { canvasState, currentAngleTypeSelector } from '@/store/canvasAtom'
import { POLYGON_TYPE } from '@/common/common' import { POLYGON_TYPE } from '@/common/common'
import { moduleSelectionDataState } from '@/store/selectedModuleOptions' import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
import { getDegreeByChon, getTrestleLength } from '@/util/canvas-util' import { getDegreeByChon, getTrestleLength } from '@/util/canvas-util'
@ -13,220 +13,207 @@ export const useTrestle = () => {
const moduleSelectionData = useRecoilValue(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터 const moduleSelectionData = useRecoilValue(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
const { getQuotationItem } = useMasterController() const { getQuotationItem } = useMasterController()
const [estimateParam, setEstimateParam] = useRecoilState(estimateParamAtom) const [estimateParam, setEstimateParam] = useRecoilState(estimateParamAtom)
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
const apply = () => { const apply = () => {
//처마력바가 체크되어 있는 경우 exposedBottomPoints를 이용해 처마력바 그려줘야함. try {
// exposedBottomPoints는 노출 최하면 들의 centerPoint 배열. //처마력바가 체크되어 있는 경우 exposedBottomPoints를 이용해 처마력바 그려줘야함.
// exposedBottomPoints는 노출 최하면 들의 centerPoint 배열.
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
// 기존 eaveBar를 삭제 // 기존 eaveBar를 삭제
canvas.getObjects().forEach((obj) => { canvas.getObjects().forEach((obj) => {
if (obj.name === 'eaveBar' || obj.name === 'rack' || obj.name === 'halfEaveBar' || obj.name === 'smartRack') { if (obj.name === 'eaveBar' || obj.name === 'rack' || obj.name === 'halfEaveBar' || obj.name === 'smartRack') {
canvas.remove(obj)
}
})
canvas.getObjects().forEach((obj) => {
if (obj.name === 'bracket') {
canvas.remove(obj)
}
})
surfaces.forEach((surface) => {
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
const roofMaterialIndex = parent.roofMaterial.index
const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
if (!construction) {
alert('앞에서 셋팅 안됨')
return
}
let moduleRowsTotCnt = 0
let isEaveBar = construction.setupCover
let isSnowGuard = construction.setupSnowCover
const direction = parent.direction
const rack = surface.trestleDetail.rack
let { rackQty, rackIntvlPct, rackYn, cvrPlvrYn } = surface.trestleDetail
if (!rack) {
//25/01/16 기준 랙이 없는 경우는 그냥 안그려준다.
return
}
const rackInfos = Object.keys(rack).map((key) => {
return { key, value: rack[key] }
})
const result = calculateForApi(surface)
if (!result) {
return
}
const centerPoints = result.centerPoints
const exposedBottomModules = [] // 아래 두면이 모두 노출 되어있는 경우
const leftExposedHalfBottomModules = [] // 왼쪽 면만 노출되어있는 경우
const rightExposedHalfBottomPoints = [] // 오른쪽 면만 노출되어 있는 경우
const leftExposedHalfTopModules = [] // 왼쪽 면만 노출되어 있는 경우
const rightExposedHalfTopPoints = [] // 오른쪽 면만 노출되어 있는 경우
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
modules.forEach((module) => {
const { x, y } = module.getCenterPoint()
const isExposedBottom = result.exposedBottomPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
const isLeftExposedHalfBottom = result.leftExposedHalfBottomPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
const isRightExposedHalfBottom = result.rightExposedHalfBottomPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
const isRightExposedHalfTop = result.rightExposedHalfTopPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
const isLeftExposedHalfTop = result.leftExposedHalfTopPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
if (isExposedBottom) {
exposedBottomModules.push(module)
}
if (isLeftExposedHalfBottom) {
leftExposedHalfBottomModules.push(module)
}
if (isRightExposedHalfBottom) {
rightExposedHalfBottomPoints.push(module)
}
if (isRightExposedHalfTop) {
leftExposedHalfTopModules.push(module)
}
if (isLeftExposedHalfTop) {
rightExposedHalfTopPoints.push(module)
}
})
// 4개중 한개라도 있는 경우 치조배치로 간주한다.
const isChidory =
leftExposedHalfBottomModules.length > 0 ||
rightExposedHalfBottomPoints.length > 0 ||
leftExposedHalfTopModules.length > 0 ||
rightExposedHalfTopPoints.length > 0
surface.set({ isChidory: isChidory })
canvas
.getObjects()
.filter((obj) => ['eaveBar', 'halfEaveBar'].includes(obj.name) && obj.parentId === surface.id)
.forEach((obj) => {
canvas.remove(obj) canvas.remove(obj)
}
})
canvas.getObjects().forEach((obj) => {
if (obj.name === 'bracket') {
canvas.remove(obj)
}
})
surfaces.forEach((surface) => {
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
const roofMaterialIndex = parent.roofMaterial.index
const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
if (!construction) {
alert('앞에서 셋팅 안됨')
return
}
let moduleRowsTotCnt = 0
let isEaveBar = construction.setupCover
let isSnowGuard = construction.setupSnowCover
const direction = parent.direction
const rack = surface.trestleDetail.rack
let { rackQty, rackIntvlPct, rackYn, cvrPlvrYn } = surface.trestleDetail
if (!rack) {
//25/01/16 기준 랙이 없는 경우는 그냥 안그려준다.
return
}
const rackInfos = Object.keys(rack).map((key) => {
return { key, value: rack[key] }
}) })
if (isEaveBar) { const result = calculateForApi(surface)
// 처마력바설치 true인 경우 설치
exposedBottomModules.forEach((module) => { if (!result) {
//TODO : 방향별로 처마력바 설치해야함 return
const bottomPoints = findTopTwoPoints([...module.points], direction) }
if (!bottomPoints) return const centerPoints = result.centerPoints
const eaveBar = new fabric.Line([bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y], {
parent: surface, const exposedBottomModules = [] // 아래 두면이 모두 노출 되어있는 경우
name: 'eaveBar', const leftExposedHalfBottomModules = [] // 왼쪽 면만 노출되어있는 경우
stroke: 'blue', const rightExposedHalfBottomPoints = [] // 오른쪽 면만 노출되어 있는 경우
strokeWidth: 4, const leftExposedHalfTopModules = [] // 왼쪽 면만 노출되어 있는 경우
selectable: false, const rightExposedHalfTopPoints = [] // 오른쪽 면만 노출되어 있는 경우
surfaceId: surface.id, const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
parentId: module.id,
modules.forEach((module) => {
const { x, y } = module.getCenterPoint()
const isExposedBottom = result.exposedBottomPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
const isLeftExposedHalfBottom = result.leftExposedHalfBottomPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
const isRightExposedHalfBottom = result.rightExposedHalfBottomPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
const isRightExposedHalfTop = result.rightExposedHalfTopPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
const isLeftExposedHalfTop = result.leftExposedHalfTopPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
if (isExposedBottom) {
exposedBottomModules.push(module)
}
if (isLeftExposedHalfBottom) {
leftExposedHalfBottomModules.push(module)
}
if (isRightExposedHalfBottom) {
rightExposedHalfBottomPoints.push(module)
}
if (isRightExposedHalfTop) {
leftExposedHalfTopModules.push(module)
}
if (isLeftExposedHalfTop) {
rightExposedHalfTopPoints.push(module)
}
})
// 4개중 한개라도 있는 경우 치조배치로 간주한다.
const isChidory =
leftExposedHalfBottomModules.length > 0 ||
rightExposedHalfBottomPoints.length > 0 ||
leftExposedHalfTopModules.length > 0 ||
rightExposedHalfTopPoints.length > 0
surface.set({ isChidory: isChidory })
canvas
.getObjects()
.filter((obj) => ['eaveBar', 'halfEaveBar'].includes(obj.name) && obj.parentId === surface.id)
.forEach((obj) => {
canvas.remove(obj)
}) })
canvas.add(eaveBar)
canvas.renderAll()
})
if (isChidory && cvrPlvrYn === 'Y') { if (isEaveBar) {
leftExposedHalfBottomModules.forEach((module) => { // 처마력바설치 true인 경우 설치
exposedBottomModules.forEach((module) => {
//TODO : 방향별로 처마력바 설치해야함
const bottomPoints = findTopTwoPoints([...module.points], direction) const bottomPoints = findTopTwoPoints([...module.points], direction)
let barPoints = []
//설치해야할 반처마커버 포인트를 방향에 따라 설정
if (direction === 'south') {
barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x - module.width / 2, bottomPoints[1].y]
} else if (direction === 'north') {
barPoints = [bottomPoints[0].x + module.width / 2, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y]
} else if (direction === 'east') {
barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[0].y - module.height / 2]
} else if (direction === 'west') {
barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y - module.height / 2]
}
if (!bottomPoints) return if (!bottomPoints) return
const halfEaveBar = new fabric.Line(barPoints, { const eaveBar = new fabric.Line([bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y], {
parent: surface, parent: surface,
name: 'halfEaveBar', name: 'eaveBar',
stroke: 'blue', stroke: 'blue',
strokeWidth: 4, strokeWidth: 4,
selectable: false, selectable: false,
surfaceId: surface.id, surfaceId: surface.id,
parentId: module.id, parentId: module.id,
}) })
canvas.add(halfEaveBar) canvas.add(eaveBar)
canvas.renderAll() canvas.renderAll()
}) })
rightExposedHalfBottomPoints.forEach((module) => { if (isChidory && cvrPlvrYn === 'Y') {
const bottomPoints = findTopTwoPoints([...module.points], direction) leftExposedHalfBottomModules.forEach((module) => {
let barPoints = [] const bottomPoints = findTopTwoPoints([...module.points], direction)
//설치해야할 반처마커버 포인트를 방향에 따라 설정 let barPoints = []
//설치해야할 반처마커버 포인트를 방향에 따라 설정
if (direction === 'south') { if (direction === 'south') {
barPoints = [bottomPoints[0].x + module.width / 2, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y] barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x - module.width / 2, bottomPoints[1].y]
} else if (direction === 'north') { } else if (direction === 'north') {
barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[0].x + module.width / 2, bottomPoints[1].y] barPoints = [bottomPoints[0].x + module.width / 2, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y]
} else if (direction === 'east') { } else if (direction === 'east') {
barPoints = [bottomPoints[0].x, bottomPoints[1].y + module.height / 2, bottomPoints[1].x, bottomPoints[1].y] barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[0].y - module.height / 2]
} else if (direction === 'west') { } else if (direction === 'west') {
barPoints = [bottomPoints[0].x, bottomPoints[1].y - module.height / 2, bottomPoints[1].x, bottomPoints[1].y] barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y - module.height / 2]
} }
if (!bottomPoints) return if (!bottomPoints) return
const halfEaveBar = new fabric.Line(barPoints, { const halfEaveBar = new fabric.Line(barPoints, {
parent: surface, parent: surface,
name: 'halfEaveBar', name: 'halfEaveBar',
stroke: 'blue', stroke: 'blue',
strokeWidth: 4, strokeWidth: 4,
selectable: false, selectable: false,
parentId: module.id, surfaceId: surface.id,
parentId: module.id,
})
canvas.add(halfEaveBar)
canvas.renderAll()
}) })
canvas.add(halfEaveBar)
canvas.renderAll() rightExposedHalfBottomPoints.forEach((module) => {
}) const bottomPoints = findTopTwoPoints([...module.points], direction)
let barPoints = []
//설치해야할 반처마커버 포인트를 방향에 따라 설정
if (direction === 'south') {
barPoints = [bottomPoints[0].x + module.width / 2, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y]
} else if (direction === 'north') {
barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[0].x + module.width / 2, bottomPoints[1].y]
} else if (direction === 'east') {
barPoints = [bottomPoints[0].x, bottomPoints[1].y + module.height / 2, bottomPoints[1].x, bottomPoints[1].y]
} else if (direction === 'west') {
barPoints = [bottomPoints[0].x, bottomPoints[1].y - module.height / 2, bottomPoints[1].x, bottomPoints[1].y]
}
if (!bottomPoints) return
const halfEaveBar = new fabric.Line(barPoints, {
parent: surface,
name: 'halfEaveBar',
stroke: 'blue',
strokeWidth: 4,
selectable: false,
parentId: module.id,
})
canvas.add(halfEaveBar)
canvas.renderAll()
})
}
} }
} const horizontal = ['south', 'north'].includes(direction) ? surface.trestleDetail.moduleIntvlHor : surface.trestleDetail.moduleIntvlVer
const horizontal = ['south', 'north'].includes(direction) ? surface.trestleDetail.moduleIntvlHor : surface.trestleDetail.moduleIntvlVer
const vertical = ['south', 'north'].includes(direction) ? surface.trestleDetail.moduleIntvlVer : surface.trestleDetail.moduleIntvlHor const vertical = ['south', 'north'].includes(direction) ? surface.trestleDetail.moduleIntvlVer : surface.trestleDetail.moduleIntvlHor
let mostRowsModule = 0 // 모듈 최대 단 수 let mostRowsModule = 0 // 모듈 최대 단 수
// 가대 설치를 위한 가장 아래 모듈로부터 위로 몇단인지 계산 // 가대 설치를 위한 가장 아래 모듈로부터 위로 몇단인지 계산
// 오른쪽,왼쪽 둘 다 아래에 아무것도 없는, 처마 커버를 필요로 하는 모듈 // 오른쪽,왼쪽 둘 다 아래에 아무것도 없는, 처마 커버를 필요로 하는 모듈
exposedBottomModules.forEach((module) => { exposedBottomModules.forEach((module) => {
let { width, height } = { ...module } let { width, height } = { ...module }
width = Math.floor(width) width = Math.floor(width)
height = Math.floor(height) height = Math.floor(height)
let { x: startX, y: startY } = { ...module.getCenterPoint() } let { x: startX, y: startY } = { ...module.getCenterPoint() }
let { x, y } = { ...module.getCenterPoint() } let { x, y } = { ...module.getCenterPoint() }
let leftRows = 1 let leftRows = 1
let rightRows = 1 let rightRows = 1
let centerRows = 1 let centerRows = 1
let hasNextModule = true let hasNextModule = true
let findLeft = true let findLeft = true
let findRight = true let findRight = true
//우선 절반을 나눈 뒤 왼쪽부터 찾는다. //우선 절반을 나눈 뒤 왼쪽부터 찾는다.
while (hasNextModule) { while (hasNextModule) {
//바로 위에 있는지 확인한다. //바로 위에 있는지 확인한다.
let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction) let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) {
// 바로 위 모듈을 찾는다.
leftRows++
x = nextModule.x
y = nextModule.y
} else {
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findLeft) {
nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findLeft = false
} else {
nextModule = findNextRightModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findLeft = true
}
if (nextModule) { if (nextModule) {
// 바로 위 모듈을 찾는다. // 바로 위 모듈을 찾는다.
@ -234,126 +221,126 @@ export const useTrestle = () => {
x = nextModule.x x = nextModule.x
y = nextModule.y y = nextModule.y
} else { } else {
hasNextModule = false // 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findLeft) {
nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findLeft = false
} else {
nextModule = findNextRightModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findLeft = true
}
if (nextModule) {
// 바로 위 모듈을 찾는다.
leftRows++
x = nextModule.x
y = nextModule.y
} else {
hasNextModule = false
}
} }
} }
}
hasNextModule = true hasNextModule = true
x = startX x = startX
y = startY y = startY
// 오른쪽 찾는다. // 오른쪽 찾는다.
while (hasNextModule) { while (hasNextModule) {
//바로 위에 있는지 확인한다. //바로 위에 있는지 확인한다.
let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction) let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) {
// 바로 위 모듈을 찾는다.
rightRows++
x = nextModule.x
y = nextModule.y
} else {
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findRight) {
nextModule = findNextRightModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = false
} else {
nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = true
}
if (nextModule) { if (nextModule) {
// 바로 위 모듈을 찾는다. // 바로 위 모듈을 찾는다.
rightRows++ rightRows++
x = nextModule.x x = nextModule.x
y = nextModule.y y = nextModule.y
} else {
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findRight) {
nextModule = findNextRightModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = false
} else {
nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = true
}
if (nextModule) {
// 바로 위 모듈을 찾는다.
rightRows++
x = nextModule.x
y = nextModule.y
} else {
hasNextModule = false
}
}
}
hasNextModule = true
x = startX
y = startY
// 센터 찾는다.
while (hasNextModule) {
//바로 위에 있는지 확인한다.
let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) {
// 바로 위 모듈을 찾는다.
centerRows++
x = nextModule.x
y = nextModule.y
} else { } else {
hasNextModule = false hasNextModule = false
} }
} }
}
hasNextModule = true // 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다.
x = startX const leftRacks = rackInfos.find((rack) => {
y = startY return rack.value.moduleRows === leftRows
})?.value.racks
// 센터 찾는다. // 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다.
while (hasNextModule) { const rightRacks = rackInfos.find((rack) => {
//바로 위에 있는지 확인한다. return rack.value.moduleRows === rightRows
let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction) })?.value.racks
// 해당 rack으로 그려준다.
if (nextModule) { const centerRacks = rackInfos.find((rack) => {
// 바로 위 모듈을 찾는다. return rack.value.moduleRows === centerRows
centerRows++ })?.value.racks
x = nextModule.x
y = nextModule.y
} else {
hasNextModule = false
}
}
// 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다. mostRowsModule = Math.max(leftRows, rightRows, centerRows, mostRowsModule)
const leftRacks = rackInfos.find((rack) => {
return rack.value.moduleRows === leftRows
})?.value.racks
// 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다. if (rackYn === 'Y') {
const rightRacks = rackInfos.find((rack) => { drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L', rackYn)
return rack.value.moduleRows === rightRows drawRacks(rightRacks, rackQty, rackIntvlPct, module, direction, 'R', rackYn)
})?.value.racks
// 해당 rack으로 그려준다.
const centerRacks = rackInfos.find((rack) => { if (rackQty === 3) {
return rack.value.moduleRows === centerRows //rack 갯수가 3개인 경우는 중간렉도 추가해줘야함
})?.value.racks drawRacks(centerRacks, rackQty, rackIntvlPct, module, direction, 'C', rackYn)
} else if (rackQty === 4) {
mostRowsModule = Math.max(leftRows, rightRows, centerRows, mostRowsModule) drawRacks(leftRacks, rackQty, rackIntvlPct / 3, module, direction, 'L', rackYn)
drawRacks(rightRacks, rackQty, rackIntvlPct / 3, module, direction, 'R', rackYn)
if (rackYn === 'Y') {
drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L', rackYn)
drawRacks(rightRacks, rackQty, rackIntvlPct, module, direction, 'R', rackYn)
if (rackQty === 3) {
//rack 갯수가 3개인 경우는 중간렉도 추가해줘야함
drawRacks(centerRacks, rackQty, rackIntvlPct, module, direction, 'C', rackYn)
} else if (rackQty === 4) {
drawRacks(leftRacks, rackQty, rackIntvlPct / 3, module, direction, 'L', rackYn)
drawRacks(rightRacks, rackQty, rackIntvlPct / 3, module, direction, 'R', rackYn)
}
}
module.set({ leftRows, rightRows, centerRows })
})
// 왼쪽아래에 모듈이 없는 모듈들
leftExposedHalfBottomModules.forEach((module) => {
const { width, height } = module
let { x: startX, y: startY } = { ...module.getCenterPoint() }
let { x, y } = { ...module.getCenterPoint() }
//TODO : 방향별로 가대 설치해야함
let leftRows = 1
let hasNextModule = true
let findLeft = true
//우선 절반을 나눈 뒤 왼쪽부터 찾는다.
while (hasNextModule) {
//바로 위에 있는지 확인한다.
let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) {
// 바로 위 모듈을 찾는다.
leftRows++
x = nextModule.x
y = nextModule.y
} else {
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findLeft) {
nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findLeft = false
} else {
nextModule = nextModule = findNextRightModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findLeft = true
} }
}
module.set({ leftRows, rightRows, centerRows })
})
// 왼쪽아래에 모듈이 없는 모듈들
leftExposedHalfBottomModules.forEach((module) => {
const { width, height } = module
let { x: startX, y: startY } = { ...module.getCenterPoint() }
let { x, y } = { ...module.getCenterPoint() }
//TODO : 방향별로 가대 설치해야함
let leftRows = 1
let hasNextModule = true
let findLeft = true
//우선 절반을 나눈 뒤 왼쪽부터 찾는다.
while (hasNextModule) {
//바로 위에 있는지 확인한다.
let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) { if (nextModule) {
// 바로 위 모듈을 찾는다. // 바로 위 모듈을 찾는다.
@ -361,52 +348,63 @@ export const useTrestle = () => {
x = nextModule.x x = nextModule.x
y = nextModule.y y = nextModule.y
} else { } else {
hasNextModule = false // 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findLeft) {
nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findLeft = false
} else {
nextModule = nextModule = findNextRightModule(
{
x,
y,
width,
height,
horizontal,
vertical,
},
centerPoints,
direction,
)
findLeft = true
}
if (nextModule) {
// 바로 위 모듈을 찾는다.
leftRows++
x = nextModule.x
y = nextModule.y
} else {
hasNextModule = false
}
} }
} }
}
// 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다. // 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다.
const leftRacks = rackInfos.find((rack) => { const leftRacks = rackInfos.find((rack) => {
return rack.value.moduleRows === leftRows return rack.value.moduleRows === leftRows
})?.value.racks })?.value.racks
mostRowsModule = Math.max(leftRows, mostRowsModule) mostRowsModule = Math.max(leftRows, mostRowsModule)
if (rackYn === 'Y') { if (rackYn === 'Y') {
drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L', rackYn) drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L', rackYn)
} }
module.set({ leftRows }) module.set({ leftRows })
}) })
// 오른쪽 아래에 모듈이 없는 모듈들 // 오른쪽 아래에 모듈이 없는 모듈들
rightExposedHalfBottomPoints.forEach((module) => { rightExposedHalfBottomPoints.forEach((module) => {
const { width, height } = module const { width, height } = module
let { x: startX, y: startY } = { ...module.getCenterPoint() } let { x: startX, y: startY } = { ...module.getCenterPoint() }
let { x, y } = { ...module.getCenterPoint() } let { x, y } = { ...module.getCenterPoint() }
//TODO : 방향별로 가대 설치해야함 //TODO : 방향별로 가대 설치해야함
let rightRows = 1 let rightRows = 1
let hasNextModule = true let hasNextModule = true
let findRight = true let findRight = true
// 오른쪽 찾는다. // 오른쪽 찾는다.
while (hasNextModule) { while (hasNextModule) {
//바로 위에 있는지 확인한다. //바로 위에 있는지 확인한다.
let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction) let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) {
// 바로 위 모듈을 찾는다.
rightRows++
x = nextModule.x
y = nextModule.y
} else {
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findRight) {
nextModule = findNextRightModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = false
} else {
nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = true
}
if (nextModule) { if (nextModule) {
// 바로 위 모듈을 찾는다. // 바로 위 모듈을 찾는다.
@ -414,43 +412,62 @@ export const useTrestle = () => {
x = nextModule.x x = nextModule.x
y = nextModule.y y = nextModule.y
} else { } else {
hasNextModule = false // 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findRight) {
nextModule = findNextRightModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = false
} else {
nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = true
}
if (nextModule) {
// 바로 위 모듈을 찾는다.
rightRows++
x = nextModule.x
y = nextModule.y
} else {
hasNextModule = false
}
} }
} }
// 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다.
const rightRacks = rackInfos.find((rack) => {
return rack.value.moduleRows === rightRows
})?.value.racks
mostRowsModule = Math.max(rightRows, mostRowsModule)
// 해당 rack으로 그려준다.
if (rackYn === 'Y') {
drawRacks(rightRacks, rackQty, rackIntvlPct, module, direction, 'R', rackYn)
}
module.set({ rightRows })
})
surface.set({ moduleRowsTotCnt: mostRowsModule })
if (rackYn === 'N') {
// rack이 없을경우
installBracketWithOutRack(surface, exposedBottomModules, leftExposedHalfBottomModules, rightExposedHalfBottomPoints, isChidory)
} else if (rackYn === 'Y') {
installBracket(surface)
} }
// 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다. const quotationParam = getTrestleParams(surface)
const rightRacks = rackInfos.find((rack) => {
return rack.value.moduleRows === rightRows
})?.value.racks
mostRowsModule = Math.max(rightRows, mostRowsModule) surface.set({ quotationParam })
// 해당 rack으로 그려준다.
if (rackYn === 'Y') {
drawRacks(rightRacks, rackQty, rackIntvlPct, module, direction, 'R', rackYn)
}
module.set({ rightRows })
}) })
surface.set({ moduleRowsTotCnt: mostRowsModule }) return setEstimateData()
} catch (e) {
if (rackYn === 'N') { return false
// rack이 없을경우 }
installBracketWithOutRack(surface, exposedBottomModules, leftExposedHalfBottomModules, rightExposedHalfBottomPoints, isChidory)
} else if (rackYn === 'Y') {
installBracket(surface)
}
const quotationParam = getTrestleParams(surface)
surface.set({ quotationParam })
})
setQuoationItem()
} }
// itemList 조회 후 estimateParam에 저장 // itemList 조회 후 estimateParam에 저장
const setQuoationItem = () => { const setEstimateData = async () => {
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
//surfaces.pcses들을 배열로 묶는다 //surfaces.pcses들을 배열로 묶는다
const pcses = surfaces[0].pcses const pcses = surfaces[0].pcses
@ -461,16 +478,72 @@ export const useTrestle = () => {
}) })
const params = { trestles: surfaces.map((surface) => surface.quotationParam), pcses } const params = { trestles: surfaces.map((surface) => surface.quotationParam), pcses }
//견적서 itemList 조회 //견적서 itemList 조회
getQuotationItem(params).then((res) => { const res = await getQuotationItem(params)
if (!res.data) { if (!res.data) {
return return false
} }
const itemList = res.data const itemList = res.data
//northArrangement 북면 설치 여부 //northArrangement 북면 설치 여부
const northArrangement = getNorthArrangement() const northArrangement = getNorthArrangement()
// circuitItemList의 경우는 moduleList에서 circuitId만 groupBy한다.
let circuitItemList = []
setEstimateParam({ ...estimateParam, itemList, northArrangement }) // roofSurfaceList 생성
const roofSurfaceList = surfaces.map((surface) => {
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
const { directionText, roofMaterial, pitch: slope, moduleCompass, surfaceCompass } = parent
const roofMaterialIndex = parent.roofMaterial.index
const { nameJp: roofMaterialIdMulti } = roofMaterial
const moduleSelection = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex)
const { constTp: constructSpecification, constTpJp: constructSpecificationMulti } = moduleSelection.construction
const {
trestleMkrCd,
constMthdCd: supportMethodId,
roofBaseCd,
trestleMkrCdJp: supportMeaker,
constMthdCdJp: supportMethodIdMulti,
} = moduleSelection.trestle
const modules = surface.modules
const moduleList = modules.map((module) => {
circuitItemList.push(module.pcsItemId)
return {
itemId: module.moduleInfo.itemId,
circuit: module.circuitNumber,
pcItemId: module.pcsItemId,
}
})
return {
roofSurfaceId: surface.id,
roofSurface: directionText.replace(/[^0-9]/g, ''),
roofMaterialId: roofMaterial.roofMatlCd,
supportMethodId,
constructSpecification,
constructSpecificationMulti,
roofMaterialIdMulti,
supportMethodIdMulti,
supportMeaker,
slope,
classType: currentAngleType === 'slope' ? '0' : '1',
angle: getDegreeByChon(slope),
azimuth: surfaceCompass ?? moduleCompass ?? 0,
moduleList,
}
}) })
// circuitItemList 중복제거
circuitItemList = circuitItemList.filter((item, index) => circuitItemList.indexOf(item) === index)
circuitItemList = circuitItemList.map((circuitId) => {
return {
itemId: circuitId,
}
})
setEstimateParam({ ...estimateParam, itemList, northArrangement, roofSurfaceList, circuitItemList })
// 정상적으로 완료 되면 true 반환
return true
} }
const getNorthArrangement = () => { const getNorthArrangement = () => {

View File

@ -273,7 +273,8 @@ export function useRoofAllocationSetting(id) {
setRoofList(newRoofList) setRoofList(newRoofList)
const selectedRoofMaterial = newRoofList.find((roof) => roof.selected) const selectedRoofMaterial = newRoofList.find((roof) => roof.selected)
setSurfaceShapePattern(currentObject, roofDisplay.column, false, selectedRoofMaterial) setSurfaceShapePattern(currentObject, roofDisplay.column, false, selectedRoofMaterial, true)
drawDirectionArrow(currentObject)
modifyModuleSelectionData() modifyModuleSelectionData()
closeAll() closeAll()
} }

View File

@ -129,7 +129,7 @@ export function usePlan(params = {}) {
* objectNo에 해당하는 canvas 목록을 조회 * objectNo에 해당하는 canvas 목록을 조회
*/ */
const getCanvasByObjectNo = async (userId, objectNo, planNo) => { const getCanvasByObjectNo = async (userId, objectNo, planNo) => {
return await get({ url: `/api/canvas-management/canvas-statuses/by-object/${objectNo}/${userId}` }).then((res) => return await get({ url: `/api/canvas-management/canvas-statuses/by-object/${objectNo}` }).then((res) =>
res.map((item) => ({ res.map((item) => ({
id: item.id, id: item.id,
objectNo: item.objectNo, objectNo: item.objectNo,

View File

@ -515,9 +515,9 @@
"common.finish": "完了", "common.finish": "完了",
"common.ok": "確認", "common.ok": "確認",
"common.cancel": "キャンセル", "common.cancel": "キャンセル",
"commons.west": "立つ", "commons.west": "西",
"commons.east": "ドン", "commons.east": "",
"commons.south": "M", "commons.south": "",
"commons.north": "北", "commons.north": "北",
"commons.none": "選択しない", "commons.none": "選択しない",
"common.type": "分類", "common.type": "分類",

View File

@ -997,5 +997,6 @@
"construction.length.difference": "지붕면 공법을 전부 선택해주세요.", "construction.length.difference": "지붕면 공법을 전부 선택해주세요.",
"menu.validation.canvas.roof": "패널을 배치하려면 지붕면을 입력해야 합니다.", "menu.validation.canvas.roof": "패널을 배치하려면 지붕면을 입력해야 합니다.",
"batch.object.outside.roof": "오브젝트는 지붕내에 설치해야 합니다.", "batch.object.outside.roof": "오브젝트는 지붕내에 설치해야 합니다.",
"batch.object.notinstall.cross": "오브젝트는 겹쳐서 설치 할 수 없습니다." "batch.object.notinstall.cross": "오브젝트는 겹쳐서 설치 할 수 없습니다.",
"module.not.batch.north": "북쪽에는 모듈을 배치할 수 없습니다."
} }

View File

@ -14,7 +14,7 @@ export const estimateParamAtom = atom({
standardWindSpeedId: '', standardWindSpeedId: '',
snowfall: '', snowfall: '',
northArrangement: '', northArrangement: '',
drawingFlg: '', drawingFlg: '1',
userId: '', userId: '',
roofSurfaceList: [], roofSurfaceList: [],
circuitItemList: [], circuitItemList: [],