Merge branch 'dev' into dev-yj

This commit is contained in:
yjnoh 2025-02-04 19:39:15 +09:00
commit 1f2cb6af1d
9 changed files with 321 additions and 65 deletions

View File

@ -34,11 +34,11 @@ export default function ImgLoad() {
const handleModal = () => { const handleModal = () => {
setFloorPlanState({ ...floorPlanState, refFileModalOpen: false, toggleRotate: false }) setFloorPlanState({ ...floorPlanState, refFileModalOpen: false, toggleRotate: false })
setCurrentCanvasPlan({ // setCurrentCanvasPlan({
...currentCanvasPlan, // ...currentCanvasPlan,
bgImageName: refImage?.name ?? null, // bgImageName: refImage?.name ?? null,
mapPositionAddress, // mapPositionAddress,
}) // })
} }
useEffect(() => { useEffect(() => {

View File

@ -21,6 +21,7 @@ import { selectedModuleState } from '@/store/selectedModuleOptions'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import { stepUpListDataState } from '@/store/circuitTrestleAtom' import { stepUpListDataState } from '@/store/circuitTrestleAtom'
import { useEstimate } from '@/hooks/useEstimate'
const ALLOCATION_TYPE = { const ALLOCATION_TYPE = {
AUTO: 'auto', AUTO: 'auto',
@ -31,6 +32,7 @@ export default function CircuitTrestleSetting({ id }) {
const { closePopup } = usePopup() const { closePopup } = usePopup()
const { apply } = useTrestle() const { apply } = useTrestle()
const { swalFire } = useSwal() const { swalFire } = useSwal()
const { saveEstimate } = useEstimate()
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const [makers, setMakers] = useRecoilState(makersState) const [makers, setMakers] = useRecoilState(makersState)
@ -336,8 +338,10 @@ export default function CircuitTrestleSetting({ id }) {
}) })
const result = await apply() const result = await apply()
if (result) {
await saveEstimate(result)
}
removeNotAllocationModules() removeNotAllocationModules()
apply()
} }
const removeNotAllocationModules = () => { const removeNotAllocationModules = () => {

View File

@ -131,12 +131,16 @@ export function useRefFiles() {
// setCurrentCanvasPlan((prev) => ({ ...prev, bgImageName: currentCanvasPlan.id, mapPositionAddress: queryRef.current.value })) // setCurrentCanvasPlan((prev) => ({ ...prev, bgImageName: currentCanvasPlan.id, mapPositionAddress: queryRef.current.value }))
} }
/**
* 배경 이미지 로드를 위한 세팅
*/
useEffect(() => { useEffect(() => {
if (!currentBgImage) { if (!currentBgImage) {
return return
} }
console.log('🚀 ~ useEffect ~ currentBgImage:', currentBgImage) console.log('🚀 ~ useEffect ~ currentBgImage:', currentBgImage)
handleBackImageLoadToCanvas(`plan-images/${currentCanvasPlan.id}.png`) // handleBackImageLoadToCanvas(`plan-images/${currentCanvasPlan.id}.png`)
handleBackImageLoadToCanvas(currentBgImage)
setCurrentCanvasPlan((prev) => ({ ...prev, bgImageName: refImage?.name ?? null, mapPositionAddress: queryRef.current.value })) setCurrentCanvasPlan((prev) => ({ ...prev, bgImageName: refImage?.name ?? null, mapPositionAddress: queryRef.current.value }))
}, [currentBgImage]) }, [currentBgImage])
@ -147,15 +151,15 @@ export function useRefFiles() {
const handleUploadImageRefFile = async (file) => { const handleUploadImageRefFile = async (file) => {
const formData = new FormData() const formData = new FormData()
formData.append('file', file) formData.append('file', file)
formData.append('fileName', currentCanvasPlan.id) // formData.append('fileName', currentCanvasPlan.id)
// const res = await post({ url: `${process.env.NEXT_PUBLIC_API_SERVER_PATH}/api/image-upload`, data: formData }) // const res = await post({ url: `${process.env.NEXT_PUBLIC_API_SERVER_PATH}/api/image-upload`, data: formData })
const res = await post({ url: `http://localhost:3000/api/image-upload`, data: formData }) const res = await post({ url: `${process.env.NEXT_PUBLIC_HOST_URL}/image/upload`, data: formData })
console.log('🚀 ~ handleUploadImageRefFile ~ res:', res) console.log('🚀 ~ handleUploadImageRefFile ~ res:', res)
const image = await readImage(res.fileNm) // const image = await readImage(res.filePath)
console.log('🚀 ~ handleUploadImageRefFile ~ file:', image) // console.log('🚀 ~ handleUploadImageRefFile ~ file:', image)
setCurrentBgImage(image) setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`)
setRefImage(file) setRefImage(file)
} }

View File

@ -1,18 +1,16 @@
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { canvasState, currentAngleTypeSelector } 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'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import { useMasterController } from '@/hooks/common/useMasterController' import { useMasterController } from '@/hooks/common/useMasterController'
import { estimateParamAtom } from '@/store/estimateAtom'
// 회로 및 가대설정 // 회로 및 가대설정
export const useTrestle = () => { export const useTrestle = () => {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const moduleSelectionData = useRecoilValue(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터 const moduleSelectionData = useRecoilValue(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
const { getQuotationItem } = useMasterController() const { getQuotationItem } = useMasterController()
const [estimateParam, setEstimateParam] = useRecoilState(estimateParamAtom)
const currentAngleType = useRecoilValue(currentAngleTypeSelector) const currentAngleType = useRecoilValue(currentAngleTypeSelector)
const apply = () => { const apply = () => {
@ -41,6 +39,7 @@ export const useTrestle = () => {
return return
} }
const plvrYn = construction.plvrYn
let moduleRowsTotCnt = 0 let moduleRowsTotCnt = 0
let isEaveBar = construction.setupCover let isEaveBar = construction.setupCover
let isSnowGuard = construction.setupSnowCover let isSnowGuard = construction.setupSnowCover
@ -102,6 +101,14 @@ export const useTrestle = () => {
leftExposedHalfTopModules.length > 0 || leftExposedHalfTopModules.length > 0 ||
rightExposedHalfTopPoints.length > 0 rightExposedHalfTopPoints.length > 0
console.log('isChidory', isChidory)
if (plvrYn === 'N' && isChidory) {
alert('치조불가공법입니다.')
clear()
throw new Error('치조불가공법입니다.')
}
surface.set({ isChidory: isChidory }) surface.set({ isChidory: isChidory })
canvas canvas
@ -210,6 +217,10 @@ export const useTrestle = () => {
let findLeft = true let findLeft = true
let findRight = true let findRight = true
let leftFindModuleList = [module]
let rightFindModuleList = [module]
let centerFindModuleList = [module]
//우선 절반을 나눈 뒤 왼쪽부터 찾는다. //우선 절반을 나눈 뒤 왼쪽부터 찾는다.
while (hasNextModule) { while (hasNextModule) {
//바로 위에 있는지 확인한다. //바로 위에 있는지 확인한다.
@ -218,6 +229,7 @@ export const useTrestle = () => {
if (nextModule) { if (nextModule) {
// 바로 위 모듈을 찾는다. // 바로 위 모듈을 찾는다.
leftRows++ leftRows++
leftFindModuleList.push(nextModule)
x = nextModule.x x = nextModule.x
y = nextModule.y y = nextModule.y
} else { } else {
@ -233,6 +245,7 @@ export const useTrestle = () => {
if (nextModule) { if (nextModule) {
// 바로 위 모듈을 찾는다. // 바로 위 모듈을 찾는다.
leftRows++ leftRows++
leftFindModuleList.push(nextModule)
x = nextModule.x x = nextModule.x
y = nextModule.y y = nextModule.y
} else { } else {
@ -253,6 +266,7 @@ export const useTrestle = () => {
if (nextModule) { if (nextModule) {
// 바로 위 모듈을 찾는다. // 바로 위 모듈을 찾는다.
rightRows++ rightRows++
rightFindModuleList.push(nextModule)
x = nextModule.x x = nextModule.x
y = nextModule.y y = nextModule.y
} else { } else {
@ -268,6 +282,7 @@ export const useTrestle = () => {
if (nextModule) { if (nextModule) {
// 바로 위 모듈을 찾는다. // 바로 위 모듈을 찾는다.
rightRows++ rightRows++
rightFindModuleList.push(nextModule)
x = nextModule.x x = nextModule.x
y = nextModule.y y = nextModule.y
} else { } else {
@ -287,6 +302,7 @@ export const useTrestle = () => {
if (nextModule) { if (nextModule) {
// 바로 위 모듈을 찾는다. // 바로 위 모듈을 찾는다.
centerFindModuleList.push(nextModule)
centerRows++ centerRows++
x = nextModule.x x = nextModule.x
y = nextModule.y y = nextModule.y
@ -295,19 +311,77 @@ export const useTrestle = () => {
} }
} }
const leftModuleInfos = leftFindModuleList.map((module) => {
return {
moduleTpCd: module.moduleInfo.moduleTpCd,
}
})
const rightModuleInfos = rightFindModuleList.map((module) => {
return {
moduleTpCd: module.moduleInfo.moduleTpCd,
}
})
const centerModuleInfos = centerFindModuleList.map((module) => {
return {
moduleTpCd: module.moduleInfo.moduleTpCd,
}
})
const leftRowsInfo = moduleTransformData(leftModuleInfos)
const rightRowsInfo = moduleTransformData(rightModuleInfos)
const centerRowsInfo = moduleTransformData(centerModuleInfos)
// 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다. // 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다.
const leftRacks = rackInfos.find((rack) => { const leftRacks = rackInfos.find((rack) => {
return rack.value.moduleRows === leftRows if (leftRowsInfo.rowsInfo.length === 1) {
return (
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
return (
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
rack.value.moduleTpRows1 === leftRowsInfo.rowsInfo[0].count &&
rack.value.moduleTpRows2 === leftRowsInfo.rowsInfo[1].count
)
}
})?.value.racks })?.value.racks
// 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다. // 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다.
const rightRacks = rackInfos.find((rack) => { const rightRacks = rackInfos.find((rack) => {
return rack.value.moduleRows === rightRows if (rightRowsInfo.rowsInfo.length === 1) {
return (
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
return (
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
rack.value.moduleTpRows1 === rightRowsInfo.rowsInfo[0].count &&
rack.value.moduleTpRows2 === rightRowsInfo.rowsInfo[1].count
)
}
})?.value.racks })?.value.racks
// 해당 rack으로 그려준다. // 해당 rack으로 그려준다.
const centerRacks = rackInfos.find((rack) => { const centerRacks = rackInfos.find((rack) => {
return rack.value.moduleRows === centerRows if (centerRowsInfo.rowsInfo.length === 1) {
return (
rack.value.moduleTpCd === centerRowsInfo.moduleTotalTp &&
rack.value.moduleRows === centerRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
return (
rack.value.moduleTpCd === centerRowsInfo.moduleTotalTp &&
rack.value.moduleRows === centerRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
rack.value.moduleTpRows1 === centerRowsInfo.rowsInfo[0].count &&
rack.value.moduleTpRows2 === centerRowsInfo.rowsInfo[1].count
)
}
})?.value.racks })?.value.racks
mostRowsModule = Math.max(leftRows, rightRows, centerRows, mostRowsModule) mostRowsModule = Math.max(leftRows, rightRows, centerRows, mostRowsModule)
@ -336,6 +410,7 @@ export const useTrestle = () => {
let leftRows = 1 let leftRows = 1
let hasNextModule = true let hasNextModule = true
let findLeft = true let findLeft = true
let findModuleList = [module]
//우선 절반을 나눈 뒤 왼쪽부터 찾는다. //우선 절반을 나눈 뒤 왼쪽부터 찾는다.
while (hasNextModule) { while (hasNextModule) {
@ -345,6 +420,7 @@ export const useTrestle = () => {
if (nextModule) { if (nextModule) {
// 바로 위 모듈을 찾는다. // 바로 위 모듈을 찾는다.
leftRows++ leftRows++
findModuleList.push(nextModule)
x = nextModule.x x = nextModule.x
y = nextModule.y y = nextModule.y
} else { } else {
@ -371,6 +447,7 @@ export const useTrestle = () => {
if (nextModule) { if (nextModule) {
// 바로 위 모듈을 찾는다. // 바로 위 모듈을 찾는다.
leftRows++ leftRows++
findModuleList.push(nextModule)
x = nextModule.x x = nextModule.x
y = nextModule.y y = nextModule.y
} else { } else {
@ -379,10 +456,30 @@ export const useTrestle = () => {
} }
} }
const leftModuleInfos = findModuleList.map((module) => {
return {
moduleTpCd: module.moduleInfo.moduleTpCd,
}
})
const leftRowsInfo = moduleTransformData(leftModuleInfos)
// 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다. // 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다.
const leftRacks = rackInfos.find((rack) => { const leftRacks = rackInfos.find((rack) => {
return rack.value.moduleRows === leftRows if (leftRowsInfo.rowsInfo.length === 1) {
return (
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
return (
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
rack.value.moduleTpRows1 === leftRowsInfo.rowsInfo[0].count &&
rack.value.moduleTpRows2 === leftRowsInfo.rowsInfo[1].count
)
}
})?.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)
@ -400,6 +497,7 @@ export const useTrestle = () => {
let rightRows = 1 let rightRows = 1
let hasNextModule = true let hasNextModule = true
let findRight = true let findRight = true
let findModuleList = [module]
// 오른쪽 찾는다. // 오른쪽 찾는다.
while (hasNextModule) { while (hasNextModule) {
@ -409,6 +507,7 @@ export const useTrestle = () => {
if (nextModule) { if (nextModule) {
// 바로 위 모듈을 찾는다. // 바로 위 모듈을 찾는다.
rightRows++ rightRows++
findModuleList.push(nextModule)
x = nextModule.x x = nextModule.x
y = nextModule.y y = nextModule.y
} else { } else {
@ -424,6 +523,7 @@ export const useTrestle = () => {
if (nextModule) { if (nextModule) {
// 바로 위 모듈을 찾는다. // 바로 위 모듈을 찾는다.
rightRows++ rightRows++
findModuleList.push(nextModule)
x = nextModule.x x = nextModule.x
y = nextModule.y y = nextModule.y
} else { } else {
@ -432,11 +532,30 @@ export const useTrestle = () => {
} }
} }
const rightRowsInfos = findModuleList.map((module) => {
return {
moduleTpCd: module.moduleInfo.moduleTpCd,
}
})
const rightRowsInfo = moduleTransformData(rightRowsInfos)
// 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다. // 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다.
const rightRacks = rackInfos.find((rack) => { const rightRacks = rackInfos.find((rack) => {
return rack.value.moduleRows === rightRows if (rightRowsInfo.rowsInfo.length === 1) {
return (
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
return (
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
rack.value.moduleTpRows1 === rightRowsInfo.rowsInfo[0].count &&
rack.value.moduleTpRows2 === rightRowsInfo.rowsInfo[1].count
)
}
})?.value.racks })?.value.racks
mostRowsModule = Math.max(rightRows, mostRowsModule) mostRowsModule = Math.max(rightRows, mostRowsModule)
// 해당 rack으로 그려준다. // 해당 rack으로 그려준다.
if (rackYn === 'Y') { if (rackYn === 'Y') {
@ -462,10 +581,24 @@ export const useTrestle = () => {
return setEstimateData() return setEstimateData()
} catch (e) { } catch (e) {
return false return null
} }
} }
//module Rack 정보를 얻기위한 데이터 가공
function moduleTransformData(arr) {
let counts = {}
arr.forEach((item) => {
counts[item.moduleTpCd] = (counts[item.moduleTpCd] || 0) + 1
})
let moduleTotalTp = Object.keys(counts).join('')
let rowsInfo = Object.entries(counts).map(([moduleTpCd, count]) => ({ moduleTpCd, count }))
return { moduleTotalTp, rowsInfo }
}
// itemList 조회 후 estimateParam에 저장 // itemList 조회 후 estimateParam에 저장
const setEstimateData = async () => { 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)
@ -480,7 +613,7 @@ export const useTrestle = () => {
//견적서 itemList 조회 //견적서 itemList 조회
const res = await getQuotationItem(params) const res = await getQuotationItem(params)
if (!res.data) { if (!res.data) {
return false return null
} }
const itemList = res.data const itemList = res.data
//northArrangement 북면 설치 여부 //northArrangement 북면 설치 여부
@ -540,10 +673,10 @@ export const useTrestle = () => {
} }
}) })
setEstimateParam({ ...estimateParam, itemList, northArrangement, roofSurfaceList, circuitItemList }) const estimateParam = { itemList, northArrangement, roofSurfaceList, circuitItemList }
// 정상적으로 완료 되면 true 반환 // 정상적으로 완료 되면 true 반환
return true return estimateParam
} }
const getNorthArrangement = () => { const getNorthArrangement = () => {
@ -565,9 +698,11 @@ export const useTrestle = () => {
} }
const findNextModule = (currentPoint, centerPoints, direction) => { const findNextModule = (currentPoint, centerPoints, direction) => {
let { x, y, width, height, horizontal, vertical } = { ...currentPoint } let { x, y, horizontal, vertical } = { ...currentPoint }
width = width + horizontal let { widthArr, heightArr } = centerPoints[0]
height = height + vertical
let width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal
let height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length + vertical
let maxX = 2 + horizontal * 3 let maxX = 2 + horizontal * 3
let maxY = 2 + vertical * 3 let maxY = 2 + vertical * 3
@ -596,7 +731,11 @@ export const useTrestle = () => {
} }
const findNextLeftModule = (currentPoint, centerPoints, direction) => { const findNextLeftModule = (currentPoint, centerPoints, direction) => {
let { x, y, width, height, horizontal, vertical } = { ...currentPoint } let { x, y, horizontal, vertical } = { ...currentPoint }
let { widthArr, heightArr } = centerPoints[0]
let width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal
let height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length + vertical
let result let result
let topLeftPoint let topLeftPoint
@ -631,9 +770,11 @@ export const useTrestle = () => {
return result return result
} }
const findNextRightModule = (currentPoint, centerPoints, direction) => { const findNextRightModule = (currentPoint, centerPoints, direction) => {
let { x, y, width, height, horizontal, vertical } = { ...currentPoint } let { x, y, horizontal, vertical } = { ...currentPoint }
width = width + horizontal let { widthArr, heightArr } = centerPoints[0]
height = height + vertical
let width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal
let height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length + vertical
let result let result
let topRightPoint let topRightPoint
@ -665,6 +806,9 @@ export const useTrestle = () => {
} }
const drawRacks = (rackInfos, rackQty, rackIntvlPct, module, direction, l, rackYn) => { const drawRacks = (rackInfos, rackQty, rackIntvlPct, module, direction, l, rackYn) => {
if (!rackInfos) {
return
}
const { width, height, left, top, lastX, lastY, surfaceId } = module const { width, height, left, top, lastX, lastY, surfaceId } = module
const surface = canvas.getObjects().find((obj) => obj.id === surfaceId) const surface = canvas.getObjects().find((obj) => obj.id === surfaceId)
const roof = canvas.getObjects().find((obj) => obj.id === surface.parentId) const roof = canvas.getObjects().find((obj) => obj.id === surface.parentId)
@ -762,7 +906,7 @@ export const useTrestle = () => {
name: 'smartRack', name: 'smartRack',
stroke: 'red', stroke: 'red',
strokeWidth: 4, strokeWidth: 4,
selectable: false, selectable: true,
shadow: { shadow: {
color: 'black', // Outline color color: 'black', // Outline color
blur: 10, blur: 10,
@ -774,17 +918,18 @@ export const useTrestle = () => {
surfaceId: surface.id, surfaceId: surface.id,
supFitQty, supFitQty,
supFitIntvlPct, supFitIntvlPct,
rackLen, rackLen: rackLength,
rackRowsCd, rackRowsCd,
seq, seq,
smartRackId, smartRackId,
rackId: itemId, rackId: itemId,
direction: 'top', direction: 'top',
}) })
startPointY -= rackLength + 8
canvas.add(rack) canvas.add(rack)
canvas.renderAll() canvas.renderAll()
} else if (setRackTpCd === 'INTVL') { } else if (setRackTpCd === 'INTVL') {
startPointY -= rackLength + 8 startPointY -= rackLength
} }
}) })
} else { } else {
@ -844,13 +989,14 @@ export const useTrestle = () => {
surfaceId: surface.id, surfaceId: surface.id,
supFitQty, supFitQty,
supFitIntvlPct, supFitIntvlPct,
rackLen, rackLen: rackLength,
rackRowsCd, rackRowsCd,
seq, seq,
smartRackId, smartRackId,
rackId: itemId, rackId: itemId,
direction: 'left', direction: 'left',
}) })
startPointX -= rackLength + 8
canvas.add(rack) canvas.add(rack)
canvas.renderAll() canvas.renderAll()
} else if (setRackTpCd === 'INTVL') { } else if (setRackTpCd === 'INTVL') {
@ -873,7 +1019,7 @@ export const useTrestle = () => {
selectable: false, selectable: false,
supFitQty, supFitQty,
supFitIntvlPct, supFitIntvlPct,
rackLen, rackLen: rackLength,
rackYn, rackYn,
rackRowsCd, rackRowsCd,
rackId: itemId, rackId: itemId,
@ -913,17 +1059,18 @@ export const useTrestle = () => {
surfaceId: surface.id, surfaceId: surface.id,
supFitQty, supFitQty,
supFitIntvlPct, supFitIntvlPct,
rackLen, rackLen: rackLength,
rackRowsCd, rackRowsCd,
seq, seq,
smartRackId, smartRackId,
rackId: itemId, rackId: itemId,
direction: 'right', direction: 'right',
}) })
startPointX += rackLength + 8
canvas.add(rack) canvas.add(rack)
canvas.renderAll() canvas.renderAll()
} else if (setRackTpCd === 'INTVL') { } else if (setRackTpCd === 'INTVL') {
startPointX += rackLength + 8 startPointX += rackLength
} }
}) })
} else { } else {
@ -989,8 +1136,9 @@ export const useTrestle = () => {
}) })
canvas.add(rack) canvas.add(rack)
canvas.renderAll() canvas.renderAll()
} else if (setRackTpCd === 'INTVL') {
startPointY += rackLength + 8 startPointY += rackLength + 8
} else if (setRackTpCd === 'INTVL') {
startPointY += rackLength
} }
}) })
} else { } else {
@ -1043,17 +1191,16 @@ export const useTrestle = () => {
canvas.renderAll() canvas.renderAll()
racks.forEach((rack) => { racks.forEach((rack) => {
const { x1, y1, x2, y2, direction, supFitQty, supFitIntvlPct, rackLen } = rack const { x1, y1, x2, y2, direction, supFitQty, supFitIntvlPct, rackLen, name } = rack
const bracketLength = 10 const bracketLength = 10
if (direction === 'top') { if (direction === 'top') {
const result = getBracketPoints(supFitQty, supFitIntvlPct) const result = getBracketPoints(supFitQty, supFitIntvlPct)
result.forEach((percent) => { result.forEach((percent) => {
const bracket = new fabric.Rect({ const bracket = new fabric.Rect({
left: x2 - bracketLength / 3, left: x2 - bracketLength / 3,
top: y2 + (rackLen / 10) * percent, top: name === 'smartRack' ? y2 + rackLen * percent : y2 + (rackLen / 10) * percent,
fill: 'green', fill: 'green',
name: 'bracket', name: 'bracket',
parentId: rack.parentId, parentId: rack.parentId,
@ -1071,7 +1218,7 @@ export const useTrestle = () => {
result.forEach((percent) => { result.forEach((percent) => {
const bracket = new fabric.Rect({ const bracket = new fabric.Rect({
left: x2 + (rackLen / 10) * percent, left: name === 'smartRack' ? x2 + rackLen * percent : x2 + (rackLen / 10) * percent,
top: y2 - bracketLength / 3, top: y2 - bracketLength / 3,
fill: 'green', fill: 'green',
name: 'bracket', name: 'bracket',
@ -1090,7 +1237,7 @@ export const useTrestle = () => {
result.forEach((percent) => { result.forEach((percent) => {
const bracket = new fabric.Rect({ const bracket = new fabric.Rect({
left: x2 - (rackLen / 10) * percent, left: name === 'smartRack' ? x2 - rackLen * percent : x2 - (rackLen / 10) * percent,
top: y2 - bracketLength / 3, top: y2 - bracketLength / 3,
fill: 'green', fill: 'green',
parentId: rack.parentId, parentId: rack.parentId,
@ -1110,7 +1257,7 @@ export const useTrestle = () => {
result.forEach((percent) => { result.forEach((percent) => {
const bracket = new fabric.Rect({ const bracket = new fabric.Rect({
left: x2 - bracketLength / 3, left: x2 - bracketLength / 3,
top: y2 - (rackLen / 10) * percent, top: name === 'smartRack' ? y2 - rackLen * percent : y2 - (rackLen / 10) * percent,
fill: 'green', fill: 'green',
name: 'bracket', name: 'bracket',
parentId: rack.parentId, parentId: rack.parentId,
@ -1337,8 +1484,49 @@ export const useTrestle = () => {
return points.slice(0, 2) return points.slice(0, 2)
} }
const calculateForApi = (moduleSurface) => { const getCenterPoints = (moduleSurface) => {
const centerPoints = [] const centerPoints = []
let widthArr = []
let heightArr = []
const modules = moduleSurface.modules
modules.forEach((module, index) => {
module.tempIndex = index
const { x, y } = module.getCenterPoint()
const { width, height } = { ...module }
widthArr.push(width)
heightArr.push(height)
centerPoints.push({ x, y, width: Math.floor(width), height: Math.floor(height), index, moduleInfo: module.moduleInfo })
})
//widthArr 중복 제거 1이상 차이가 나지 않으면 같은 너비로 간주
widthArr = removeCloseValues(Array.from(new Set(widthArr)))
heightArr = removeCloseValues(Array.from(new Set(heightArr)))
centerPoints.forEach((centerPoint, index) => {
centerPoint.widthArr = [...widthArr]
centerPoint.heightArr = [...heightArr]
})
function removeCloseValues(arr, threshold = 1) {
arr.sort((a, b) => a - b) // 배열을 정렬
let result = []
for (let i = 0; i < arr.length; i++) {
if (i === 0 || Math.abs(arr[i] - arr[i - 1]) >= threshold) {
result.push(arr[i])
}
}
return result
}
return centerPoints
}
const calculateForApi = (moduleSurface) => {
const centerPoints = getCenterPoints(moduleSurface)
const direction = moduleSurface.direction const direction = moduleSurface.direction
const modules = moduleSurface.modules const modules = moduleSurface.modules
@ -1350,12 +1538,6 @@ export const useTrestle = () => {
const maxX = 2 + horizontal * 3 const maxX = 2 + horizontal * 3
const maxY = 2 + vertical * 3 const maxY = 2 + vertical * 3
modules.forEach((module, index) => {
module.tempIndex = index
const { x, y } = module.getCenterPoint()
const { width, height } = { ...module }
centerPoints.push({ x, y, width: Math.floor(width), height: Math.floor(height), index })
})
if (centerPoints.length === 0) return if (centerPoints.length === 0) return
@ -1382,7 +1564,7 @@ export const useTrestle = () => {
let rightExposedHalfTopPoints = [] let rightExposedHalfTopPoints = []
centerPoints.forEach((centerPoint, index) => { centerPoints.forEach((centerPoint, index) => {
let { x, y, width, height } = { ...centerPoint } let { x, y, width, height, widthArr, heightArr } = { ...centerPoint }
// centerPoints중에 현재 centerPoint와 x값이 같고, y값이 y-height값과 같은 centerPoint가 있는지 확인 // centerPoints중에 현재 centerPoint와 x값이 같고, y값이 y-height값과 같은 centerPoint가 있는지 확인
let bottomCell let bottomCell
let bottomLeftPoint let bottomLeftPoint
@ -1392,28 +1574,29 @@ export const useTrestle = () => {
switch (direction) { switch (direction) {
case 'south': case 'south':
width = width + horizontal //widthArr의 값을 전부 더한 후 widthArr의 길이로 나누어 평균값을 구한다.
height = height + vertical width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal
height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length + vertical
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y + height)) < maxY) bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y + height)) < maxY)
bottomLeftPoint = { x: x - width / 2, y: y + height } bottomLeftPoint = { x: x - width / 2, y: y + height }
bottomRightPoint = { x: x + width / 2, y: y + height } bottomRightPoint = { x: x + width / 2, y: y + height }
break break
case 'north': case 'north':
width = width + horizontal width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal
height = height + vertical height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length + vertical
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y - height)) < maxY) bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y - height)) < maxY)
bottomLeftPoint = { x: x + width / 2, y: y - height } bottomLeftPoint = { x: x + width / 2, y: y - height }
bottomRightPoint = { x: x - width / 2, y: y - height } bottomRightPoint = { x: x - width / 2, y: y - height }
break break
case 'east': case 'east':
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x + width)) < maxX && Math.abs(centerPoint.y - y) < maxY) bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x + width)) < maxX && Math.abs(centerPoint.y - y) < maxY)
width = width + horizontal width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal
bottomLeftPoint = { x: x + width, y: y + height / 2 } bottomLeftPoint = { x: x + width, y: y + height / 2 }
bottomRightPoint = { x: x + width, y: y - height / 2 } bottomRightPoint = { x: x + width, y: y - height / 2 }
break break
case 'west': case 'west':
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x - width)) < maxX && Math.abs(centerPoint.y - y) < maxY) bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x - width)) < maxX && Math.abs(centerPoint.y - y) < maxY)
width = width + horizontal width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal
bottomLeftPoint = { x: x - width, y: y - height / 2 } bottomLeftPoint = { x: x - width, y: y - height / 2 }
bottomRightPoint = { x: x - width, y: y + height / 2 } bottomRightPoint = { x: x - width, y: y + height / 2 }
break break
@ -1870,16 +2053,16 @@ export const useTrestle = () => {
const { direction, modules } = surface const { direction, modules } = surface
let { rackYn, cvrPlvrYn, moduleIntvlHor, moduleIntvlVer, rackQty, lessSupFitQty } = surface.trestleDetail let { rackYn, cvrPlvrYn, moduleIntvlHor, moduleIntvlVer, rackQty, lessSupFitQty } = surface.trestleDetail
const centerPoints = modules.map((module) => { const centerPoints = getCenterPoints(surface)
return module.getCenterPoint()
})
const horizontal = ['south', 'north'].includes(direction) ? moduleIntvlHor : moduleIntvlVer const horizontal = ['south', 'north'].includes(direction) ? moduleIntvlHor : moduleIntvlVer
const vertical = ['south', 'north'].includes(direction) ? moduleIntvlVer : moduleIntvlHor const vertical = ['south', 'north'].includes(direction) ? moduleIntvlVer : moduleIntvlHor
const maxX = 2 + horizontal * 3 const maxX = 2 + horizontal * 3
const maxY = 2 + vertical * 3 const maxY = 2 + vertical * 3
let { width, height } = { ...module } let { widthArr, heightArr } = centerPoints[0]
let width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length
let height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length
let { x, y } = { ...module.getCenterPoint() } let { x, y } = { ...module.getCenterPoint() }
let halfBottomLeftPoint let halfBottomLeftPoint

59
src/hooks/useEstimate.js Normal file
View File

@ -0,0 +1,59 @@
import { useContext } from 'react'
import { useRecoilValue } from 'recoil'
import { useAxios } from '@/hooks/useAxios'
import { useSwal } from '@/hooks/useSwal'
import { GlobalDataContext } from '@/app/GlobalDataProvider'
import { currentCanvasPlanState } from '@/store/canvasAtom'
import { loginUserStore } from '@/store/commonAtom'
export function useEstimate() {
const { managementStateLoaded } = useContext(GlobalDataContext)
const loginUserState = useRecoilValue(loginUserStore)
const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
const { swalFire } = useSwal()
const { promisePost } = useAxios()
/**
* 도면 견적서 저장
*/
const saveEstimate = async (estimateParam) => {
const userId = loginUserState.userId
const saleStoreId = managementStateLoaded.saleStoreId
const objectNo = currentCanvasPlan.objectNo
const planNo = currentCanvasPlan.planNo
const slope = estimateParam.roofSurfaceList[0].slope
const angle = estimateParam.roofSurfaceList[0].angle
const surfaceType = managementStateLoaded.surfaceType
const setupHeight = managementStateLoaded.installHeight
const standardWindSpeedId = managementStateLoaded.standardWindSpeedId
const snowfall = managementStateLoaded.verticalSnowCover
const drawingFlg = '1'
const saveEstimateData = {
...estimateParam,
userId: userId,
saleStoreId: saleStoreId,
objectNo: objectNo,
planNo: planNo,
slope: slope,
angle: angle,
surfaceType: surfaceType,
setupHeight: setupHeight,
standardWindSpeedId: standardWindSpeedId,
snowfall: snowfall,
drawingFlg: drawingFlg,
}
await promisePost({ url: '/api/estimate/save-estimate', data: saveEstimateData }).catch((error) => {
swalFire({ text: error.message, icon: 'error' })
})
}
return {
saveEstimate,
}
}

View File

@ -394,6 +394,7 @@ export function usePlan(params = {}) {
canvas, canvas,
plans, plans,
currentCanvasPlan, currentCanvasPlan,
setCurrentCanvasPlan,
selectedPlan, selectedPlan,
saveCanvas, saveCanvas,
handleCurrentPlan, handleCurrentPlan,

View File

@ -72,7 +72,8 @@ const writeImage = async (fileName, file) => {
} }
const readImage = async (fileName) => { const readImage = async (fileName) => {
const file = await fs.readFile(`${FILE_PATH}/${fileName}`) // const file = await fs.readFile(`${FILE_PATH}/${fileName}`)
const file = await fs.readFile(`${process.env.NEXT_PUBLIC_HOST_URL}${fileName}`)
// .then((res) => { // .then((res) => {
// console.log('readImage-then', res) // console.log('readImage-then', res)
// }) // })

View File

@ -877,6 +877,7 @@
"estimate.detail.roofCns": "屋根材・仕様施工", "estimate.detail.roofCns": "屋根材・仕様施工",
"estimate.detail.remarks": "備考", "estimate.detail.remarks": "備考",
"estimate.detail.fileFlg": "後日資料提出", "estimate.detail.fileFlg": "後日資料提出",
"estimate.detail.dragFileGuide": "(※北面設置の場合、ファイル添付が必須です.)",
"estimate.detail.header.fileList1": "ファイル添付", "estimate.detail.header.fileList1": "ファイル添付",
"estimate.detail.fileList.btn": "ファイル選択", "estimate.detail.fileList.btn": "ファイル選択",
"estimate.detail.fileList.extCheck": "画像ファイルのみ添付可能です。", "estimate.detail.fileList.extCheck": "画像ファイルのみ添付可能です。",
@ -942,6 +943,7 @@
"estimate.detail.save.alertMsg": "保存されました。見積書で製品を変更すると、図面や回路には反映されません。", "estimate.detail.save.alertMsg": "保存されました。見積書で製品を変更すると、図面や回路には反映されません。",
"estimate.detail.copy.alertMsg": "コピーされました。", "estimate.detail.copy.alertMsg": "コピーされました。",
"estimate.detail.save.requiredFileUpload": "ファイル添付が必須のアイテムがあります。ファイルを添付するか、後日添付をチェックしてください。", "estimate.detail.save.requiredFileUpload": "ファイル添付が必須のアイテムがあります。ファイルを添付するか、後日添付をチェックしてください。",
"estimate.detail.save.requiredNorthArrangementFileUpload": "北面にモジュールを配置した場合、北面配置許可書を必ず添付する必要があります.",
"estimate.detail.save.requiredItem": "製品は1つ以上登録する必要があります。", "estimate.detail.save.requiredItem": "製品は1つ以上登録する必要があります。",
"estimate.detail.save.requiredCharger": "担当者は必須です。", "estimate.detail.save.requiredCharger": "担当者は必須です。",
"estimate.detail.save.requiredObjectName": "案件名は必須です。", "estimate.detail.save.requiredObjectName": "案件名は必須です。",

View File

@ -877,6 +877,7 @@
"estimate.detail.roofCns": "지붕재・사양시공", "estimate.detail.roofCns": "지붕재・사양시공",
"estimate.detail.remarks": "비고", "estimate.detail.remarks": "비고",
"estimate.detail.fileFlg": "후일자료제출", "estimate.detail.fileFlg": "후일자료제출",
"estimate.detail.dragFileGuide": "(※ 북면설치인 경우, 파일 첨부가 필수입니다.)",
"estimate.detail.header.fileList1": "파일첨부", "estimate.detail.header.fileList1": "파일첨부",
"estimate.detail.fileList.btn": "파일선택", "estimate.detail.fileList.btn": "파일선택",
"estimate.detail.fileList.extCheck": "이미지 파일만 첨부 가능합니다.", "estimate.detail.fileList.extCheck": "이미지 파일만 첨부 가능합니다.",
@ -942,6 +943,7 @@
"estimate.detail.save.alertMsg": "저장되었습니다. 견적서에서 제품을 변경할 경우 도면 및 회로에 반영되지 않습니다.", "estimate.detail.save.alertMsg": "저장되었습니다. 견적서에서 제품을 변경할 경우 도면 및 회로에 반영되지 않습니다.",
"estimate.detail.copy.alertMsg": "복사되었습니다.", "estimate.detail.copy.alertMsg": "복사되었습니다.",
"estimate.detail.save.requiredFileUpload": "파일첨부가 필수인 아이템이 있습니다. 파일을 첨부하거나 후일첨부를 체크해주십시오.", "estimate.detail.save.requiredFileUpload": "파일첨부가 필수인 아이템이 있습니다. 파일을 첨부하거나 후일첨부를 체크해주십시오.",
"estimate.detail.save.requiredNorthArrangementFileUpload": "북면에 모듈을 배치한 경우, 북면배치허가서를 반드시 첨부해야 합니다.",
"estimate.detail.save.requiredItem": "제품은 1개이상 등록해야 됩니다.", "estimate.detail.save.requiredItem": "제품은 1개이상 등록해야 됩니다.",
"estimate.detail.save.requiredCharger": "담당자는 필수값 입니다.", "estimate.detail.save.requiredCharger": "담당자는 필수값 입니다.",
"estimate.detail.save.requiredObjectName": "안건명은 필수값 입니다.", "estimate.detail.save.requiredObjectName": "안건명은 필수값 입니다.",