Merge branch 'dev' into dev-yj

This commit is contained in:
yjnoh 2024-12-04 14:58:14 +09:00
commit cf080c24cf
6 changed files with 257 additions and 241 deletions

View File

@ -9,7 +9,7 @@ import SingleDatePicker from '../common/datepicker/SingleDatePicker'
import EstimateFileUploader from './EstimateFileUploader' import EstimateFileUploader from './EstimateFileUploader'
import { useAxios } from '@/hooks/useAxios' import { useAxios } from '@/hooks/useAxios'
import { globalLocaleStore } from '@/store/localeAtom' import { globalLocaleStore } from '@/store/localeAtom'
import { isNotEmptyArray, isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils' import { isEmptyArray, isNotEmptyArray, isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { useCommonCode } from '@/hooks/common/useCommonCode' import { useCommonCode } from '@/hooks/common/useCommonCode'
import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController' import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController'
@ -61,7 +61,7 @@ export default function Estimate({ params }) {
const objectRecoil = useRecoilValue(floorPlanObjectState) const objectRecoil = useRecoilValue(floorPlanObjectState)
// //
const { estimateContextState, setEstimateContextState, addItem } = useEstimateController(params.pid) const { estimateContextState, setEstimateContextState, addItem, handleEstimateFileDownload } = useEstimateController(params.pid)
// List // List
const [specialNoteList, setSpecialNoteList] = useState([]) const [specialNoteList, setSpecialNoteList] = useState([])
@ -209,11 +209,12 @@ export default function Estimate({ params }) {
}, [files]) }, [files])
useEffect(() => { useEffect(() => {
if (originFiles.length > 0) { // console.log('USEEFFECT originFiles::::::::::', originFiles)
setEstimateContextState({ // if (originFiles.length > 0) {
originFiles: originFiles, // setEstimateContextState({
}) // originFiles: originFiles,
} // })
// }
}, [originFiles]) }, [originFiles])
// set // set
@ -232,10 +233,12 @@ export default function Estimate({ params }) {
file.delFlg = '0' file.delFlg = '0'
} }
}) })
setOriginFiles((prev) => { setOriginFiles((prev) => {
return [...prev] return [...prev]
}) })
setEstimateContextState({
originFiles: originFiles,
})
} }
// ( ?) // ( ?)
const deleteOriginFile = (no) => { const deleteOriginFile = (no) => {
@ -245,29 +248,13 @@ export default function Estimate({ params }) {
} }
}) })
// console.log('originFiles::', originFiles)
setOriginFiles((prev) => { setOriginFiles((prev) => {
return [...prev] return [...prev]
}) })
// setOriginFiles(originFiles) setEstimateContextState({
// const delParams = { originFiles: originFiles,
// userId: session.userId, })
// objectNo: objectNo,
// no: no,
// }
alert(getMessage('estimate.detail.alert.delFile')) alert(getMessage('estimate.detail.alert.delFile'))
// await promisePost({ url: 'api/file/fileDelete', data: delParams }).then((res) => {
// if (res.status === 204) {
// setOriginFiles(originFiles.filter((file) => file.objectNo === objectNo && file.no !== no))
// setEstimateContextState({
// fileList: originFiles.filter((file) => file.objectNo === objectNo && file.no !== no),
// originFiles: originFiles.filter((file) => file.objectNo === objectNo && file.no !== no),
// newFileList: originFiles.filter((file) => file.objectNo === objectNo && file.no !== no),
// })
// alert(getMessage('plan.message.delete'))
// }
// })
} }
// option && // option &&
@ -446,20 +433,6 @@ export default function Estimate({ params }) {
} }
} }
} }
// data.data2.map((item2) => {
// if (item2) {
// // console.log('::::', item2)
// if (item2.itemId === item.itemId) {
// updateList.push({
// ...item,
// openFlg: item2.unitPrice === '0.0' ? '1' : '0',
// salePrice: item2.unitPrice === null ? '0' : item2.unitPrice,
// saleTotPrice: (item.amount * item2.unitPrice).toString(),
// })
// checkYn = true
// }
// }
// })
if (!checkYn) { if (!checkYn) {
updateList.push({ ...item, salePrice: '0', saleTotPrice: '0' }) updateList.push({ ...item, salePrice: '0', saleTotPrice: '0' })
@ -624,14 +597,12 @@ export default function Estimate({ params }) {
updates.pkgMaterialFlg = res.pkgMaterialFlg updates.pkgMaterialFlg = res.pkgMaterialFlg
updates.pnowW = res.pnowW updates.pnowW = res.pnowW
updates.salePrice = res.salePrice updates.salePrice = res.salePrice
// updates.salePrice = ''
updates.specification = res.specification updates.specification = res.specification
updates.unit = res.unit updates.unit = res.unit
updates.specialNoteCd = res.spnAttrCds updates.specialNoteCd = res.spnAttrCds
updates.itemGroup = res.itemGroup updates.itemGroup = res.itemGroup
updates.delFlg = '0' // 0 updates.delFlg = '0' // 0
updates.saleTotPrice = (res.salePrice * estimateContextState.itemList[index].amount).toString() updates.saleTotPrice = (res.salePrice * estimateContextState.itemList[index].amount).toString()
// updates.saleTotPrice = ''
updates.amount = '' updates.amount = ''
updates.openFlg = res.openFlg updates.openFlg = res.openFlg
@ -1153,7 +1124,10 @@ export default function Estimate({ params }) {
return ( return (
<li className="file-item" key={uuidv4()}> <li className="file-item" key={uuidv4()}>
<div className="file-item-wrap"> <div className="file-item-wrap">
<span style={{ display: originFile.delFlg === '0' ? '' : 'none' }}> <span
style={{ display: originFile.delFlg === '0' ? '' : 'none' }}
onClick={() => handleEstimateFileDownload(originFile)}
>
{originFile.faileName} {originFile.faileName}
<button <button
type="button" type="button"
@ -1567,7 +1541,13 @@ export default function Estimate({ params }) {
</td> </td>
<td className="al-r"> <td className="al-r">
{convertNumberToPriceDecimal( {convertNumberToPriceDecimal(
item?.showSaleTotPrice === '0' ? null : item?.saleTotPrice === '0' ? null : item?.saleTotPrice?.replaceAll(',', ''), item?.showSaleTotPrice === '0'
? null
: item?.amount === ''
? null
: item?.saleTotPrice === '0'
? null
: item?.saleTotPrice?.replaceAll(',', ''),
)} )}
</td> </td>
</tr> </tr>

View File

@ -318,11 +318,11 @@ export default function CanvasMenu(props) {
<div className="ico-btn-from"> <div className="ico-btn-from">
<button className="btn-frame gray ico-flx" onClick={() => setEstimatePopupOpen(true)}> <button className="btn-frame gray ico-flx" onClick={() => setEstimatePopupOpen(true)}>
<span className="ico ico01"></span> <span className="ico ico01"></span>
<span>{getMessage('plan.menu.estimate.docDown')}</span> <span className="name">{getMessage('plan.menu.estimate.docDown')}</span>
</button> </button>
<button className="btn-frame gray ico-flx" onClick={handleEstimateSubmit}> <button className="btn-frame gray ico-flx" onClick={handleEstimateSubmit}>
<span className="ico ico02"></span> <span className="ico ico02"></span>
<span>{getMessage('plan.menu.estimate.save')}</span> <span className="name">{getMessage('plan.menu.estimate.save')}</span>
</button> </button>
<button <button
className="btn-frame gray ico-flx" className="btn-frame gray ico-flx"
@ -331,7 +331,7 @@ export default function CanvasMenu(props) {
}} }}
> >
<span className="ico ico03"></span> <span className="ico ico03"></span>
<span>{getMessage('plan.menu.estimate.reset')}</span> <span className="name">{getMessage('plan.menu.estimate.reset')}</span>
</button> </button>
{estimateRecoilState?.docNo !== null && (sessionState.storeId === 'T01' || sessionState.storeLvl === '1') && ( {estimateRecoilState?.docNo !== null && (sessionState.storeId === 'T01' || sessionState.storeLvl === '1') && (
@ -342,9 +342,13 @@ export default function CanvasMenu(props) {
}} }}
> >
<span className="ico ico04"></span> <span className="ico ico04"></span>
<span>{getMessage('plan.menu.estimate.copy')}</span> <span className="name">{getMessage('plan.menu.estimate.copy')}</span>
</button> </button>
)} )}
<button className="btn-frame gray ico-flx">
<span className="ico ico05"></span>
<span className="name">{getMessage('plan.menu.estimate.unLock')}</span>
</button>
</div> </div>
</> </>
)} )}

View File

@ -3,7 +3,7 @@ import { useContext, useEffect, useReducer, useState } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue } from 'recoil'
import { globalLocaleStore } from '@/store/localeAtom' import { globalLocaleStore } from '@/store/localeAtom'
import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom' import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom'
import { isObjectNotEmpty } from '@/util/common-utils' import { isObjectNotEmpty, isEmptyArray } from '@/util/common-utils'
import { SessionContext } from '@/app/SessionProvider' import { SessionContext } from '@/app/SessionProvider'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
@ -42,6 +42,12 @@ export const useEstimateController = (planNo) => {
} }
}, []) }, [])
useEffect(() => {
if (fileList.length > 0) {
realSave(fileList)
}
}, [fileList])
// 상세 조회 // 상세 조회
const fetchSetting = async (objectNo, planNo) => { const fetchSetting = async (objectNo, planNo) => {
try { try {
@ -53,6 +59,7 @@ export const useEstimateController = (planNo) => {
item.delFlg = '0' item.delFlg = '0'
}) })
} }
setEstimateContextState(res.data) setEstimateContextState(res.data)
} }
} }
@ -149,19 +156,16 @@ export const useEstimateController = (planNo) => {
return alert(getMessage('estimate.detail.save.requiredEstimateDate')) return alert(getMessage('estimate.detail.save.requiredEstimateDate'))
} }
//첨부파일을 첨부안했는데 //기존에 첨부된 파일이 있으면 파일첨부관련 통과
//아이템 fileUploadFlg가1(첨부파일 필수)이 1개라도 있는데 후일 자료 제출(fileFlg) 체크안했으면(0) alert 저장안돼
// console.log('새로추가첨부파일:::', estimateData.newFileList)
// console.log('기존첨부파일:::', estimateData.originFiles)
// return
if (estimateData?.originFiles?.length > 0) { if (estimateData?.originFiles?.length > 0) {
originFileFlg = true originFileFlg = true
} }
if (flag) { if (flag) {
if (!originFileFlg) { if (!originFileFlg) {
if (estimateData.newFileList?.length < 1) { //기존에 첨부된 파일이 없으면
// if (estimateData.newFileList?.length < 1) {
if (isEmptyArray(estimateData.newFileList)) {
//새로 첨부한 파일이 없으면
if (estimateData.itemList.length > 1) { if (estimateData.itemList.length > 1) {
estimateData.itemList.map((row) => { estimateData.itemList.map((row) => {
if (row.delFlg === '0') { if (row.delFlg === '0') {
@ -217,26 +221,7 @@ export const useEstimateController = (planNo) => {
} }
} }
}) })
}
if (flag && fileFlg && itemFlg) {
//1. 첨부파일 저장시작
const formData = new FormData()
if (estimateData?.newFileList?.length > 0) {
estimateData.newFileList.forEach((file) => {
formData.append('files', file)
})
formData.append('objectNo', estimateData.objectNo)
formData.append('planNo', estimateData.planNo)
formData.append('category', '10')
formData.append('userId', estimateData.userId)
await post({ url: '/api/file/fileUpload', data: formData }).then((res) => {
console.log('리턴::::::::::::', res)
})
}
//첨부파일저장끝
estimateData.itemList = estimateData.itemList.filter((item) => item.delFlg === '0' || !item.addFlg) estimateData.itemList = estimateData.itemList.filter((item) => item.delFlg === '0' || !item.addFlg)
let delCnt = 0 let delCnt = 0
@ -248,66 +233,103 @@ export const useEstimateController = (planNo) => {
if (delCnt === estimateData.itemList.length) { if (delCnt === estimateData.itemList.length) {
return alert(getMessage('estimate.detail.save.requiredItem')) return alert(getMessage('estimate.detail.save.requiredItem'))
} }
}
let option = [] if (flag && fileFlg && itemFlg) {
estimateData.itemList.forEach((item) => { //1. 첨부파일 저장시작
if (item.specialNoteCd) { const formData = new FormData()
let split2 = item.specialNoteCd.split('、') if (estimateData?.newFileList?.length > 0) {
option = option.concat(split2) // console.log('새로추가한 첨부파일있음:::', estimateData?.newFileList)
} estimateData.newFileList.forEach((file) => {
}) formData.append('files', file)
let estimateOptions = ''
let estimateOptionsArray
estimateData.specialNoteList.map((item) => {
if (item.pkgYn === '0') {
if (item.check) {
if (estimateOptions === '') {
estimateOptions = item.code
} else {
estimateOptions += '、' + item.code
}
}
} else {
if (item.check) {
let flg = '0'
for (let i = 0; i < estimateData.uniqueData.length; i++) {
if (item.code.indexOf(estimateData.uniqueData[i]) > -1) {
flg = '1'
}
if (flg === '1') {
estimateOptions += '、' + estimateData.uniqueData[i]
}
}
}
}
})
estimateOptionsArray = estimateOptions.split('、').sort()
estimateOptionsArray = Array.from(new Set(estimateOptionsArray))
estimateOptions = estimateOptionsArray.join('、')
estimateData.estimateOption = estimateOptions
// console.log('첨부파일::::::::', fileList)
// console.log('최종아이템:::', estimateData.itemList)
console.log('최종저장::', estimateData)
//2. 상세데이터 저장
// return
try {
await promisePost({ url: `${ESTIMATE_API_ENDPOINT}/save-estimate`, data: estimateData }).then((res) => {
if (res.status === 201) {
alert(getMessage('estimate.detail.save.alertMsg'))
//어디로 보낼지
fetchSetting(objectRecoil.floorPlanObjectNo, estimateData.planNo)
}
}) })
} catch (e) { formData.append('objectNo', estimateData.objectNo)
console.log('error::::::::::::', e.response.data.message) formData.append('planNo', estimateData.planNo)
formData.append('category', '10')
formData.append('userId', estimateData.userId)
await post({ url: '/api/file/fileUpload', data: formData }).then((res) => {
setFileList(res)
})
} else {
realSave()
} }
} }
} }
const realSave = async (fileList) => {
//첨부파일저장끝
let option = []
estimateData.itemList.forEach((item) => {
if (item.specialNoteCd) {
let split2 = item.specialNoteCd.split('、')
option = option.concat(split2)
}
})
let estimateOptions = ''
let estimateOptionsArray
estimateData.specialNoteList.map((item) => {
if (item.pkgYn === '0') {
if (item.check) {
if (estimateOptions === '') {
estimateOptions = item.code
} else {
estimateOptions += '、' + item.code
}
}
} else {
if (item.check) {
let flg = '0'
for (let i = 0; i < estimateData.uniqueData.length; i++) {
if (item.code.indexOf(estimateData.uniqueData[i]) > -1) {
flg = '1'
}
if (flg === '1') {
estimateOptions += '、' + estimateData.uniqueData[i]
}
}
}
}
})
estimateOptionsArray = estimateOptions.split('、').sort()
estimateOptionsArray = Array.from(new Set(estimateOptionsArray))
estimateOptions = estimateOptionsArray.join('、')
estimateData.estimateOption = estimateOptions
// console.log('최종아이템:::', estimateData.itemList)
if (fileList?.length > 0) {
estimateData.fileList = fileList
} else {
estimateData.fileList = []
}
if (estimateData.originFiles?.length > 0) {
estimateData.deleteFileList = estimateData.originFiles?.filter((item) => item.delFlg === '1')
} else {
estimateData.deleteFileList = []
}
console.log('최종저장::', estimateData)
//2. 상세데이터 저장
// return
try {
await promisePost({ url: `${ESTIMATE_API_ENDPOINT}/save-estimate`, data: estimateData }).then((res) => {
if (res.status === 201) {
estimateData.newFileList = []
estimateData.originFileList = []
alert(getMessage('estimate.detail.save.alertMsg'))
//어디로 보낼지
fetchSetting(objectRecoil.floorPlanObjectNo, estimateData.planNo)
}
})
} catch (e) {
console.log('error::::::::::::', e.response.data.message)
}
}
/** /**
* 견적서 복사버튼 * 견적서 복사버튼
* (견적서 번호(estimateData.docNo) 생성된 이후 버튼 활성화 ) * (견적서 번호(estimateData.docNo) 생성된 이후 버튼 활성화 )

View File

@ -958,120 +958,128 @@ export function useModuleBasicSetting() {
const calculateForApi = () => { const calculateForApi = () => {
// TODO : 현재는 남쪽기준. 동,서,북 분기처리 필요 // TODO : 현재는 남쪽기준. 동,서,북 분기처리 필요
const centerPoints = []
const modules = canvas.getObjects().filter((obj) => obj.name === 'module')
modules.forEach((module, index) => { const moduleSufaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
module.tempIndex = index const results = []
const { x, y } = module.getCenterPoint()
const { width, height } = module moduleSufaces.forEach((moduleSurface) => {
centerPoints.push({ x, y, width: Math.abs(width), height: Math.abs(height), index }) const centerPoints = []
const circle = new fabric.Circle({ const modules = moduleSurface.modules
radius: 5,
fill: 'red', modules.forEach((module, index) => {
name: 'redCircle', module.tempIndex = index
left: x - 5, const { x, y } = module.getCenterPoint()
top: y - 5, const { width, height } = module
index: index, centerPoints.push({ x, y, width: Math.abs(width), height: Math.abs(height), index })
selectable: false, const circle = new fabric.Circle({
radius: 5,
fill: 'red',
name: 'redCircle',
left: x - 5,
top: y - 5,
index: index,
selectable: false,
})
// canvas.add(circle)
})
//완전 노출 하면
let exposedBottom = 0
// 반 노출 하면
let exposedHalfBottom = 0
// 완전 노출 상면
let exposedTop = 0
//반 노출 상면
let exposedHalfTop = 0
// 완전 접면
let touchDimension = 0
//반접면
let halfTouchDimension = 0
// 노출하면 체크
centerPoints.forEach((centerPoint, index) => {
const { x, y, width, height } = centerPoint
// centerPoints중에 현재 centerPoint와 x값이 같고, y값이 y-height값과 같은 centerPoint가 있는지 확인
const bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y + height)) < 2)
if (bottomCell.length === 1) {
touchDimension++
return
}
const bottomLeftPoint = { x: x - width / 2, y: y + height }
const bottomRightPoint = { x: x + width / 2, y: y + height }
// 바로 아래에 셀이 없는 경우 물떼세 배치가 왼쪽 되어있는 셀을 찾는다.
const leftBottomCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < 2 && Math.abs(centerPoint.y - bottomLeftPoint.y) < 2,
).length
const rightBottomCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < 2 && Math.abs(centerPoint.y - bottomRightPoint.y) < 2,
).length
if (leftBottomCnt + rightBottomCnt === 2) {
touchDimension++
return
}
if (leftBottomCnt + rightBottomCnt === 1) {
halfTouchDimension++
exposedHalfBottom++
return
}
})
// 노출상면 체크
centerPoints.forEach((centerPoint, index) => {
const { x, y, width, height } = centerPoint
const topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2)
if (topCell.length === 1) {
return
}
const topLeftPoint = { x: x - width / 2, y: y - height }
const topRightPoint = { x: x + width / 2, y: y - height }
const leftTopCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2,
).length
const rightTopCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2,
).length
if (leftTopCnt + rightTopCnt === 1) {
exposedHalfTop++
return
}
if (leftTopCnt + rightTopCnt === 0) {
exposedTop++
return
}
})
// 완전 노출 하면 계산
/*const cells = canvas.getObjects().filter((obj) => polygon.id === obj.parentId)
const points = cells.map((cell) => {
return cell.getCenterPoint()
})*/
const groupPoints = groupCoordinates(centerPoints, modules[0])
console.log('groupPoints', groupPoints)
groupPoints.forEach((group) => {
// 각 그룹에서 y값이 큰 값을 찾는다.
// 그리고 그 y값과 같은 값을 가지는 centerPoint를 찾는다.
const maxY = group.reduce((acc, cur) => (acc.y > cur.y ? acc : cur)).y
const maxYCenterPoint = group.filter((centerPoint) => Math.abs(centerPoint.y - maxY) < 2)
exposedBottom += maxYCenterPoint.length
})
results.push({
exposedBottom,
exposedHalfBottom,
exposedTop,
exposedHalfTop,
touchDimension,
halfTouchDimension,
}) })
// canvas.add(circle)
}) })
//완전 노출 하면 return results
let exposedBottom = 0
// 반 노출 하면
let exposedHalfBottom = 0
// 완전 노출 상면
let exposedTop = 0
//반 노출 상면
let exposedHalfTop = 0
// 완전 접면
let touchDimension = 0
//반접면
let halfTouchDimension = 0
// 노출하면 체크
centerPoints.forEach((centerPoint, index) => {
const { x, y, width, height } = centerPoint
// centerPoints중에 현재 centerPoint와 x값이 같고, y값이 y-height값과 같은 centerPoint가 있는지 확인
const bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y + height)) < 2)
if (bottomCell.length === 1) {
touchDimension++
return
}
const bottomLeftPoint = { x: x - width / 2, y: y + height }
const bottomRightPoint = { x: x + width / 2, y: y + height }
// 바로 아래에 셀이 없는 경우 물떼세 배치가 왼쪽 되어있는 셀을 찾는다.
const leftBottomCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < 2 && Math.abs(centerPoint.y - bottomLeftPoint.y) < 2,
).length
const rightBottomCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < 2 && Math.abs(centerPoint.y - bottomRightPoint.y) < 2,
).length
if (leftBottomCnt + rightBottomCnt === 2) {
touchDimension++
return
}
if (leftBottomCnt + rightBottomCnt === 1) {
halfTouchDimension++
exposedHalfBottom++
return
}
})
// 노출상면 체크
centerPoints.forEach((centerPoint, index) => {
const { x, y, width, height } = centerPoint
const topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2)
if (topCell.length === 1) {
return
}
const topLeftPoint = { x: x - width / 2, y: y - height }
const topRightPoint = { x: x + width / 2, y: y - height }
const leftTopCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2,
).length
const rightTopCnt = centerPoints.filter(
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2,
).length
if (leftTopCnt + rightTopCnt === 1) {
exposedHalfTop++
return
}
if (leftTopCnt + rightTopCnt === 0) {
exposedTop++
return
}
})
// 완전 노출 하면 계산
/*const cells = canvas.getObjects().filter((obj) => polygon.id === obj.parentId)
const points = cells.map((cell) => {
return cell.getCenterPoint()
})*/
const groupPoints = groupCoordinates(centerPoints, modules[0])
console.log('groupPoints', groupPoints)
groupPoints.forEach((group) => {
// 각 그룹에서 y값이 큰 값을 찾는다.
// 그리고 그 y값과 같은 값을 가지는 centerPoint를 찾는다.
const maxY = group.reduce((acc, cur) => (acc.y > cur.y ? acc : cur)).y
const maxYCenterPoint = group.filter((centerPoint) => Math.abs(centerPoint.y - maxY) < 2)
exposedBottom += maxYCenterPoint.length
})
return {
exposedBottom,
exposedHalfBottom,
exposedTop,
exposedHalfTop,
touchDimension,
halfTouchDimension,
}
} }
// polygon 내부 cell들의 centerPoint 배열을 그룹화 해서 반환 // polygon 내부 cell들의 centerPoint 배열을 그룹화 해서 반환

View File

@ -164,6 +164,7 @@
"plan.menu.estimate.save": "保存", "plan.menu.estimate.save": "保存",
"plan.menu.estimate.reset": "初期化", "plan.menu.estimate.reset": "初期化",
"plan.menu.estimate.copy": "見積書のコピー", "plan.menu.estimate.copy": "見積書のコピー",
"plan.menu.estimate.unLock": "ロック解除",
"plan.menu.simulation": "発展シミュレーション", "plan.menu.simulation": "発展シミュレーション",
"plan.menu.simulation.excel": "Excel", "plan.menu.simulation.excel": "Excel",
"plan.menu.simulation.pdf": "PDF", "plan.menu.simulation.pdf": "PDF",

View File

@ -168,6 +168,7 @@
"plan.menu.estimate.save": "저장", "plan.menu.estimate.save": "저장",
"plan.menu.estimate.reset": "초기화", "plan.menu.estimate.reset": "초기화",
"plan.menu.estimate.copy": "견적서 복사", "plan.menu.estimate.copy": "견적서 복사",
"plan.menu.estimate.unLock": "잠금 해제",
"plan.menu.simulation": "발전 시뮬레이션", "plan.menu.simulation": "발전 시뮬레이션",
"plan.menu.simulation.excel": "Excel", "plan.menu.simulation.excel": "Excel",
"plan.menu.simulation.pdf": "PDF", "plan.menu.simulation.pdf": "PDF",