@@ -531,7 +611,9 @@ export default function CircuitTrestleSetting({ id }) {
{tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO &&
diff --git a/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx b/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx
index d8fa01e5..239487e9 100644
--- a/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx
+++ b/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx
@@ -322,7 +322,7 @@ export default function StepUp(props) {
moduleList: formatModuleList(rsf.moduleList),
roofSurface: rsf.roofSurface ? rsf.roofSurface : '',
roofSurfaceId: rsf.roofSurfaceId ? rsf.roofSurfaceId : '',
- roofSurfaceIncl: rsf.roofSurfaceIncl ? rsf.roofSurfaceIncl : '',
+ roofSurfaceIncl: rsf.roofSurfaceIncl ? +rsf.roofSurfaceIncl : '',
}))
}
// PCS MatModule 포맷
diff --git a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx
index 6ec3ba25..a526f05a 100644
--- a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx
+++ b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx
@@ -15,6 +15,7 @@ import { useRecoilState, useRecoilValue } from 'recoil'
export default function PassivityCircuitAllocation(props) {
const {
+ setTabNum,
selectedModels,
setSelectedModels,
getOptYn: getApiProps,
@@ -88,14 +89,14 @@ export default function PassivityCircuitAllocation(props) {
]
if (!circuitNumber || circuitNumber === 0) {
swalFire({
- text: '회로번호를 1 이상입력해주세요.',
+ text: getMessage('module.circuit.minimun.error'),
type: 'alert',
icon: 'warning',
})
return
} else if (targetModules.length === 0) {
swalFire({
- text: '모듈을 선택해주세요.',
+ text: getMessage('module.not.found'),
type: 'alert',
icon: 'warning',
})
@@ -113,7 +114,7 @@ export default function PassivityCircuitAllocation(props) {
})
if (result) {
swalFire({
- text: '회로 번호가 같은 다른 파워 컨디셔너 모듈이 있습니다. 다른 회로 번호를 설정하십시오.',
+ text: getMessage('module.already.exist.error'),
type: 'alert',
icon: 'warning',
})
@@ -175,7 +176,7 @@ export default function PassivityCircuitAllocation(props) {
return {
roofSurfaceId: surface.id,
roofSurface: surface.direction,
- roofSurfaceIncl: canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].pitch,
+ roofSurfaceIncl: +canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].pitch,
moduleList: surface.modules.map((module) => {
return {
itemId: module.moduleInfo.itemId,
@@ -185,7 +186,30 @@ export default function PassivityCircuitAllocation(props) {
}),
}
})
+ let pcsCount = {}
+ let result = {}
+ canvas
+ .getObjects()
+ .filter((obj) => obj.name === POLYGON_TYPE.MODULE)
+ .forEach((module) => {
+ if (module.circuitNumber) {
+ const circuitNumber = module.circuitNumber.replace(/[()]/g, '')
+ pcsCount[circuitNumber] = (pcsCount[circuitNumber] || 0) + 1
+ }
+ })
+ for (const key in pcsCount) {
+ const firstPart = key.split('-')[0] // '-' 기준으로 첫 번째 부분을 추출
+ const value = pcsCount[key]
+ // 그룹이 없으면 초기화
+ if (!result[firstPart]) {
+ result[firstPart] = { maxValue: value, count: 1 }
+ } else {
+ // 이미 그룹이 있으면 큰 값으로 갱신, count는 증가
+ result[firstPart].maxValue = Math.max(result[firstPart].maxValue, value)
+ result[firstPart].count += 1
+ }
+ }
const usedPcses = pcsList.filter((model) => model.isUsed)
const pcsItemList = usedPcses.map((model, index) => {
return {
@@ -196,8 +220,8 @@ export default function PassivityCircuitAllocation(props) {
goodsNo: model.goodsNo,
serQtyList: [
{
- serQty: targetModules.length,
- paralQty: uniqueCircuitNumbers.length,
+ serQty: result[index + 1].maxValue,
+ paralQty: result[index + 1].count,
rmdYn: 'Y',
usePossYn: 'Y',
roofSurfaceList: roofSurfaceList,
@@ -262,12 +286,13 @@ export default function PassivityCircuitAllocation(props) {
const circuitModules = canvas.getObjects().filter((obj) => obj.name === 'module' && obj.circuit?.circuitInfo?.id === selectedPcs.id)
const circuitNumbers = circuitModules.map((obj) => {
const circuitNumber = obj.circuitNumber.replace(/[()]/g, '').split('-')
- return parseInt(circuitNumber[circuitNumber.length - 1])
+ return parseInt(circuitNumber[0])
})
const minCircuitNumber = Math.min(...circuitNumbers)
canvas.remove(...circuitModules.map((module) => module.circuit))
circuitModules.forEach((obj) => {
obj.circuit = null
+ obj.circuitNumber = null
obj.pcsItemId = null
})
setCircuitNumber(minCircuitNumber)
@@ -293,15 +318,184 @@ export default function PassivityCircuitAllocation(props) {
canvas.remove(...circuitModules.map((module) => module.circuit))
circuitModules.forEach((obj) => {
obj.circuit = null
+ obj.circuitNumber = null
obj.pcsItemId = null
})
canvas.renderAll()
+ setCircuitNumber(1)
setTargetModules([])
setModuleStatisticsData()
},
})
}
+ const onApply = () => {
+ let uniqueCircuitNumbers = [
+ ...new Set(
+ canvas
+ .getObjects()
+ .filter((obj) => obj.name === POLYGON_TYPE.MODULE && obj.circuitNumber)
+ .map((obj) => obj.circuitNumber),
+ ),
+ ]
+ if (!circuitNumber || circuitNumber === 0) {
+ swalFire({
+ text: getMessage('module.circuit.minimun.error'),
+ type: 'alert',
+ icon: 'warning',
+ })
+ return
+ } else if (targetModules.length === 0) {
+ swalFire({
+ text: getMessage('module.not.found'),
+ type: 'alert',
+ icon: 'warning',
+ })
+ return
+ } else if (selectedModels.length > 1) {
+ let result = false
+
+ uniqueCircuitNumbers.forEach((number) => {
+ if (
+ number.split('-')[1] === circuitNumber + ')' &&
+ number.split('-')[0] !== '(' + (selectedModels.findIndex((model) => model.id === selectedPcs.id) + 1)
+ ) {
+ result = true
+ }
+ })
+ if (result) {
+ swalFire({
+ text: getMessage('module.already.exist.error'),
+ type: 'alert',
+ icon: 'warning',
+ })
+ return
+ }
+ }
+
+ let tempSelectedPcs = { ...selectedPcs }
+ canvas.discardActiveObject()
+ canvas
+ .getObjects()
+ .filter((obj) => targetModules.includes(obj.id))
+ .forEach((obj) => {
+ if (obj.circuit) {
+ canvas.remove(obj.circuit)
+ }
+ const moduleCircuitText = new fabric.Text(getCircuitNumber(), {
+ left: obj.left + obj.width / 2,
+ top: obj.top + obj.height / 2,
+ fontFamily: circuitNumberText.fontFamily.value,
+ fontWeight: circuitNumberText.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal',
+ fontStyle: circuitNumberText.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
+ fontSize: circuitNumberText.fontSize.value,
+ fill: circuitNumberText.fontColor.value,
+ width: obj.width,
+ height: obj.height,
+ textAlign: 'center',
+ originX: 'center',
+ originY: 'center',
+ name: 'circuitNumber',
+ selectable: false,
+ parentId: obj.id,
+ circuitInfo: selectedPcs,
+ visible: isDisplayCircuitNumber,
+ })
+ obj.set({
+ strokeWidth: 0.3,
+ })
+ obj.pcsItemId = selectedPcs.itemId
+ obj.pcsItemCode = selectedPcs.id
+ obj.circuit = moduleCircuitText
+ obj.circuitNumber = getCircuitNumber()
+ tempSelectedPcs.used = true
+ setSelectedPcs(tempSelectedPcs)
+ canvas.add(moduleCircuitText)
+ })
+
+ let pcsList = JSON.parse(JSON.stringify(selectedModels)).map((model) => {
+ if (model.id === selectedPcs.id) {
+ model.isUsed = true
+ }
+ return model
+ })
+
+ const roofSurfaceList = canvas
+ .getObjects()
+ .filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name && obj?.modules.length > 0)
+ .map((surface) => {
+ return {
+ roofSurfaceId: surface.id,
+ roofSurface: surface.direction,
+ roofSurfaceIncl: +canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].pitch,
+ moduleList: surface.modules.map((module) => {
+ return {
+ itemId: module.moduleInfo.itemId,
+ circuit: module.circuitNumber,
+ pcsItemId: module.pcsItemId,
+ }
+ }),
+ }
+ })
+ const usedPcses = pcsList.filter((model) => model.isUsed)
+ const pcsItemList = usedPcses.map((model, index) => {
+ return {
+ pcsMkrCd: model.pcsMkrCd,
+ pcsSerCd: model.pcsSerCd,
+ itemId: model.itemId,
+ itemNm: model.itemNm,
+ goodsNo: model.goodsNo,
+ serQtyList: [
+ {
+ serQty: targetModules.length,
+ paralQty: uniqueCircuitNumbers.length,
+ rmdYn: 'Y',
+ usePossYn: 'Y',
+ roofSurfaceList: roofSurfaceList,
+ },
+ ],
+ }
+ })
+
+ const params = {
+ ...getApiProps(),
+ useModuleItemList: getSelectedModuleList(),
+ pcsItemList: pcsItemList,
+ }
+
+ getPcsManualConfChk(params).then((res) => {
+ if (res?.resultCode === 'E') {
+ swalFire({
+ text: res.resultMsg,
+ type: 'alert',
+ icon: 'warning',
+ confirmFn: () => {
+ const circuitNumbers = canvas.getObjects().filter((obj) => obj.name === 'circuitNumber' && targetModules.includes(obj.parentId))
+ canvas.remove(...circuitNumbers)
+ canvas
+ .getObjects()
+ .filter((obj) => obj.name === 'module' && targetModules.includes(obj.id))
+ .forEach((obj) => {
+ obj.pcsItemId = null
+ obj.circuit = null
+ obj.circuitNumber = null
+ })
+ canvas.renderAll()
+ },
+ })
+ setSelectedPcs({ ...selectedPcs, used: false })
+ setTargetModules([])
+ return
+ }
+
+ setSelectedModels(pcsList)
+
+ setTargetModules([])
+ setModuleStatisticsData()
+ setTabNum(2)
+ })
+ }
+
return (
<>
diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx
index 9f8c54b2..140c9abd 100644
--- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx
+++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx
@@ -170,6 +170,10 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
}
const handleRoofLayoutChange = (value) => {
+ if (+currentRoof.roofSizeSet === 3) {
+ setCurrentRoof({ ...currentRoof, layout: ROOF_MATERIAL_LAYOUT.PARALLEL })
+ return
+ }
setCurrentRoof({ ...currentRoof, layout: value })
}
@@ -451,7 +455,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
setRotate((yInversion !== xInversion ? rotate - 1 : rotate + 1) % 4)}>
+ {/*
setRotate((rotate + 1) % 4)}> */}
{/*
setYInversion(!yInversion)}>
setXInversion(!xInversion)}> */}
handleInversion('y')}>
diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx
index 748de71c..a95f34d2 100644
--- a/src/components/management/StuffDetail.jsx
+++ b/src/components/management/StuffDetail.jsx
@@ -229,9 +229,8 @@ export default function StuffDetail() {
},
{
// 가대
- // field: 'supportMethodIdMulti',
- field: 'standTypeNo',
- headerName: getMessage('stuff.detail.planGridHeader.standTypeNo'),
+ field: 'supportMethodIdMulti',
+ headerName: getMessage('stuff.detail.planGridHeader.supportMethodIdMulti'),
wrapText: true,
autoHeight: true,
cellStyle: { alignItems: 'flex-start' /* 좌측정렬*/, cursor: 'pointer' },
@@ -291,15 +290,14 @@ export default function StuffDetail() {
buttonStyle = 'none'
buttonStyle2 = 'none'
} else {
- if (params?.data?.createSaleStoreId === 'T01') {
- if (session?.storeId !== 'T01') {
- buttonStyle = 'none'
- }
+ if (params?.data?.createSaleStoreId === 'T01' && session?.storeId !== 'T01') {
+ buttonStyle = 'none'
}
- if (params?.data?.tempFlg === '1') {
+ if (params?.data?.tempFlg === '1' || !params?.data?.docNo) {
buttonStyle2 = 'none'
}
}
+
return (
<>
diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx
index 58be659c..05c00a13 100644
--- a/src/components/management/StuffSearchCondition.jsx
+++ b/src/components/management/StuffSearchCondition.jsx
@@ -761,6 +761,15 @@ export default function StuffSearchCondition() {
setSchSelSaleStoreId('')
setOtherSaleStoreId('')
} else {
+ setObjectNo(stuffSearch.schObjectNo ? stuffSearch.schObjectNo : objectNo)
+ setSaleStoreName(stuffSearch.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName)
+ setDispCompanyName(stuffSearch.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName)
+ setObjectName(stuffSearch.schObjectName ? stuffSearch.schObjectName : objectName)
+ setReceiveUser(stuffSearch.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser)
+ setAddress(stuffSearch.schAddress ? stuffSearch.schAddress : address)
+ setDateType(stuffSearch.schDateType ? stuffSearch.schDateType : dateType)
+ setStartDate(stuffSearch?.schFromDt ? stuffSearch.schFromDt : dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'))
+ setEndDate(stuffSearch?.schToDt ? stuffSearch.schToDt : dayjs(new Date()).format('YYYY-MM-DD'))
setTempFlg(stuffSearch.schTempFlg ? stuffSearch.schTempFlg : tempFlg)
}
} else {
diff --git a/src/components/management/StuffSubHeader.jsx b/src/components/management/StuffSubHeader.jsx
index bb6f48b9..368926a2 100644
--- a/src/components/management/StuffSubHeader.jsx
+++ b/src/components/management/StuffSubHeader.jsx
@@ -8,7 +8,6 @@ import { useRouter, useSearchParams } from 'next/navigation'
import { useSetRecoilState } from 'recoil'
-import { QcastContext } from '@/app/QcastProvider'
import { useMessage } from '@/hooks/useMessage'
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
import { isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils'
@@ -24,8 +23,6 @@ export default function StuffSubHeader({ type }) {
const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState)
- const { isGlobalLoading } = useContext(QcastContext)
-
const { managementState } = useContext(GlobalDataContext)
const [buttonStyle, setButtonStyle] = useState('')
@@ -70,7 +67,7 @@ export default function StuffSubHeader({ type }) {
{type === 'list' && (
<>
-
+
{getMessage('header.menus.management')}
@@ -92,7 +89,7 @@ export default function StuffSubHeader({ type }) {
<>
-
-
+
{getMessage('stuff.temp.subTitle')}
@@ -116,7 +113,7 @@ export default function StuffSubHeader({ type }) {
<>
-
-
+
{getMessage('stuff.temp.subTitle')}
diff --git a/src/hooks/common/useCommonUtils.js b/src/hooks/common/useCommonUtils.js
index da5d558d..b7e944c5 100644
--- a/src/hooks/common/useCommonUtils.js
+++ b/src/hooks/common/useCommonUtils.js
@@ -591,8 +591,8 @@ export function useCommonUtils() {
//배치면일 경우
if (obj.name === 'roof') {
clonedObj.setCoords()
- clonedObj.set({ direction: obj.direction, directionText: obj.directionText, roofMaterial: obj.roofMaterial })
clonedObj.fire('polygonMoved')
+ clonedObj.set({ direction: obj.direction, directionText: obj.directionText, roofMaterial: obj.roofMaterial })
canvas.renderAll()
addLengthText(clonedObj) //수치 추가
drawDirectionArrow(clonedObj) //방향 화살표 추가
diff --git a/src/hooks/floorPlan/estimate/useEstimateController.js b/src/hooks/floorPlan/estimate/useEstimateController.js
index 10d90416..4a3bf0c2 100644
--- a/src/hooks/floorPlan/estimate/useEstimateController.js
+++ b/src/hooks/floorPlan/estimate/useEstimateController.js
@@ -83,6 +83,10 @@ export const useEstimateController = (planNo, flag) => {
res.data.pkgAsp = roundedNumber.toString()
}
setEstimateContextState(res.data)
+ } else {
+ swalFire({ text: getMessage('stuff.detail.header.notExistObjectNo'), type: 'alert', icon: 'error' })
+ setIsLoading(true)
+ setIsGlobalLoading(false)
}
}
})
@@ -90,8 +94,7 @@ export const useEstimateController = (planNo, flag) => {
setIsGlobalLoading(false)
} catch (error) {
console.error('견적서 상세조회 Error: ', error)
-
- swalFire({ text: getMessage('estimate.menu.move.valid1') })
+ swalFire({ text: getMessage('stuff.detail.header.notExistObjectNo'), type: 'alert', icon: 'error' })
setIsLoading(true)
setIsGlobalLoading(false)
}
@@ -415,7 +418,7 @@ export const useEstimateController = (planNo, flag) => {
* (견적서 번호(estimateData.docNo)가 생성된 이후 버튼 활성화 )
* T01관리자 계정 및 1차판매점에게만 제공
*/
- const handleEstimateCopy = async (sendPlanNo, copyReceiveUser, saleStoreId, otherSaleStoreId) => {
+ const handleEstimateCopy = async (sendPlanNo, copyReceiveUser, saleStoreId, otherSaleStoreId, setEstimateCopyPopupOpen) => {
//todo: 추후 YJSS가 다시 나타날 경우 아래 swalFire 제거 필요
if (estimateData.estimateType === 'YJSS') {
return swalFire({ text: getMessage('estimate.detail.save.requiredEstimateType'), type: 'alert', icon: 'warning' })
@@ -455,6 +458,7 @@ export const useEstimateController = (planNo, flag) => {
text: getMessage('estimate.detail.estimateCopyPopup.copy.alertMessage'),
type: 'alert',
confirmFn: () => {
+ setEstimateCopyPopupOpen(false) //팝업닫고
router.push(`/management/stuff/detail?objectNo=${newObjectNo.toString()}`, { scroll: false })
},
})
diff --git a/src/hooks/module/useModuleSelection.js b/src/hooks/module/useModuleSelection.js
index 26bac8e8..23c201b0 100644
--- a/src/hooks/module/useModuleSelection.js
+++ b/src/hooks/module/useModuleSelection.js
@@ -1,4 +1,4 @@
-import { useRecoilState, useRecoilValue } from 'recoil'
+import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
import { useContext, useEffect, useState } from 'react'
import { GlobalDataContext } from '@/app/GlobalDataProvider'
import { useMasterController } from '@/hooks/common/useMasterController'
@@ -7,6 +7,7 @@ import { selectedModuleState, moduleSelectionInitParamsState, moduleSelectionDat
import { isObjectNotEmpty } from '@/util/common-utils'
import { canvasState } from '@/store/canvasAtom'
import { POLYGON_TYPE } from '@/common/common'
+import { moduleStatisticsState } from '@/store/circuitTrestleAtom'
export function useModuleSelection(props) {
const canvas = useRecoilValue(canvasState)
@@ -25,6 +26,7 @@ export function useModuleSelection(props) {
const [moduleSelectionInitParams, setModuleSelectionInitParams] = useRecoilState(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등
const { getModuleTypeItemList } = useMasterController()
const { findCommonCode } = useCommonCode()
+ const resetStatisticsData = useResetRecoilState(moduleStatisticsState)
const bindInitData = () => {
setInstallHeight(managementState?.installHeight)
@@ -98,6 +100,7 @@ export function useModuleSelection(props) {
canvas.remove(moduleSurface)
})
canvas.renderAll()
+ resetStatisticsData()
}
}, [])
diff --git a/src/hooks/module/useTrestle.js b/src/hooks/module/useTrestle.js
index ebbfd7cf..17f58814 100644
--- a/src/hooks/module/useTrestle.js
+++ b/src/hooks/module/useTrestle.js
@@ -710,7 +710,7 @@ export const useTrestle = () => {
slope,
classType: currentAngleType === 'slope' ? '0' : '1',
angle: getDegreeByChon(slope),
- azimuth: surfaceCompass ?? moduleCompass ?? 0,
+ azimuth: getAzimuth(surface),
moduleList,
}
})
@@ -726,6 +726,70 @@ export const useTrestle = () => {
return { itemList, northArrangement, roofSurfaceList, circuitItemList }
}
+ const getAzimuth = (surface) => {
+ const { moduleCompass, surfaceCompass, direction } = surface
+
+ if (surfaceCompass) {
+ if (surfaceCompass > 180) {
+ return surfaceCompass - 360
+ }
+ return surfaceCompass
+ }
+
+ switch (direction) {
+ case 'south': {
+ if (moduleCompass < 0) {
+ return -1 * moduleCompass
+ } else if (moduleCompass === 0) {
+ return 0
+ } else if (moduleCompass < 180) {
+ return -1 * moduleCompass
+ } else if (moduleCompass === 180) {
+ return 180
+ }
+ }
+ case 'north': {
+ if (moduleCompass < 0) {
+ return -1 * (180 + moduleCompass)
+ } else if (moduleCompass === 0) {
+ return 180
+ } else if (moduleCompass < 180) {
+ return 180 - moduleCompass
+ } else if (moduleCompass === 180) {
+ return 0
+ }
+ }
+ case 'west': {
+ if (moduleCompass > -180 && moduleCompass < -90) {
+ return -180 - (90 + moduleCompass)
+ } else if (moduleCompass < 0) {
+ return 180 - (90 + moduleCompass)
+ } else if (moduleCompass === 0) {
+ return 90
+ } else if (moduleCompass < 180) {
+ return 90 - moduleCompass
+ } else if (moduleCompass === 180) {
+ return -90
+ }
+ }
+ case 'east': {
+ if (moduleCompass < 0) {
+ return -(90 + moduleCompass)
+ } else if (moduleCompass === 0) {
+ return -90
+ } else if (moduleCompass < 90) {
+ return -180 + (90 - moduleCompass)
+ } else if (moduleCompass < 180) {
+ return 180 + (90 - moduleCompass)
+ } else if (moduleCompass === 180) {
+ return 90
+ }
+ }
+ }
+
+ return 0
+ }
+
const getNorthArrangement = () => {
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
let northArrangement = '0'
@@ -2086,7 +2150,7 @@ export const useTrestle = () => {
moduleTpCd: module.itemTp,
roofMatlCd: parent.roofMaterial.roofMatlCd,
mixMatlNo: module.mixMatlNo,
- raftBaseCd: addRoof.raft,
+ raftBaseCd: addRoof.raft ?? addRoof.raftBaseCd,
inclCd: addRoof.pitch,
roofPitch: !addRoof.roofPchBase ? addRoof.roofPchBase : Number(addRoof.roofPchBase),
exposedLowerBottomTotCnt: result.exposedBottom, // 노출 최하면 갯수
@@ -2354,6 +2418,9 @@ export const useTrestle = () => {
if ((rightModule && !leftModule) || (!rightModule && leftModule)) {
// 둘중 하나가 없는경우는 처마커버 노출 추가
moduleRowResultData.exposedSideEavesCnt++
+ } else if (!rightModule && !leftModule) {
+ // 양쪽 둘다 없는경우는 처마커버 노출 2개 추가
+ moduleRowResultData.exposedSideEavesCnt += 2
}
}
}
diff --git a/src/hooks/option/useCanvasSetting.js b/src/hooks/option/useCanvasSetting.js
index 5df718ec..37161700 100644
--- a/src/hooks/option/useCanvasSetting.js
+++ b/src/hooks/option/useCanvasSetting.js
@@ -140,8 +140,6 @@ export function useCanvasSetting() {
const selectedRoofMaterial = useRecoilValue(selectedRoofMaterialSelector) // 선택된 지붕재 정보
const { floorPlanState } = useContext(FloorPlanContext) // 플랜 상태
const { closeAll } = usePopup() // 팝업 닫기
- // const previousObjectNoRef = useRef(null) // 최초 데이터 설정 확인
- // const previousRoofMaterialsRef = useRef(null) // 최초 데이터 설정 확인
useEffect(() => {
const tempFetchRoofMaterials = !fetchRoofMaterials
@@ -188,26 +186,6 @@ export function useCanvasSetting() {
setBasicSettings({ ...basicSetting, selectedRoofMaterial: selectedRoofMaterial })
}
- // useEffect(() => {
- // // 지붕재 select 정보가 존재해야 배치면초기설정 DB 정보 비교 후 지붕재 정보를 가져올 수 있음
- // if (
- // (!previousObjectNoRef.current && !correntObjectNo && previousObjectNoRef.current !== correntObjectNo) ||
- // (roofMaterials.length !== 0 && JSON.stringify(previousRoofMaterialsRef.current) !== JSON.stringify(roofMaterials))
- // ) {
- // // 1회만 실행
- // if (roofMaterials && previousRoofMaterialsYn === 'N') {
- // if (correntObjectNo) {
- // //fetchBasicSettings()
- // previousRoofMaterialsYn = 'Y'
- // }
- // }
-
- // // 이전 값을 업데이트
- // previousObjectNoRef.current = correntObjectNo
- // previousRoofMaterialsRef.current = roofMaterials
- // }
- // }, [roofMaterials, correntObjectNo])
-
/**
* 배치면 초기설정 화면이 열리지 않아도 데이터 set 하기 위해서 추가
*/
@@ -330,12 +308,6 @@ export function useCanvasSetting() {
* 기본설정(PlacementShapeSetting) 조회 및 초기화
*/
const fetchBasicSettings = async (planNo, openPoint) => {
- /* roofMaterials가 로드될 때까지 대기 */
- if (!roofMaterials || roofMaterials.length === 0) {
- console.log('Waiting for roofMaterials to load...')
- return
- }
-
try {
await get({
url: `/api/canvas-management/canvas-basic-settings/by-object/${correntObjectNo}/${planNo}`,
@@ -433,6 +405,7 @@ export function useCanvasSetting() {
if (addRoofs.length > 0) {
setAddedRoofs(addRoofs)
+
setBasicSettings({
...basicSetting,
roofMaterials: addRoofs[0],
@@ -442,13 +415,23 @@ export function useCanvasSetting() {
roofsData: roofsArray,
selectedRoofMaterial: addRoofs.find((roof) => roof.selected),
})
+
+ setCanvasSetting({
+ ...basicSetting,
+ roofMaterials: addRoofs[0],
+ planNo: roofsRow[0].planNo,
+ roofSizeSet: roofsRow[0].roofSizeSet,
+ roofAngleSet: roofsRow[0].roofAngleSet,
+ roofsData: roofsArray,
+ selectedRoofMaterial: addRoofs.find((roof) => roof.selected),
+ })
}
})
} catch (error) {
console.error('Data fetching error:', error)
}
- setCanvasSetting({ ...basicSetting })
+ // setCanvasSetting({ ...basicSetting })
}
/**
@@ -482,12 +465,15 @@ export function useCanvasSetting() {
await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }).then((res) => {
swalFire({ text: getMessage(res.returnMessage) })
- /* 배치면초기설정 조회 */
+ /* BasicSettings Recoil 설정 */
setBasicSettings({ ...params })
})
- /* CanvasSetting Recoil 설정 */
- setCanvasSetting({ ...basicSetting })
+ /* CanvasSetting Recoil 설정 - roofSizeSet을 문자열로 변환 */
+ setCanvasSetting({
+ ...basicSetting,
+ roofSizeSet: String(params.roofSizeSet),
+ })
/* 배치면초기설정 조회 */
fetchBasicSettings(params.planNo, null)
@@ -515,6 +501,67 @@ export function useCanvasSetting() {
}
}
+ /**
+ * 기본설정(PlacementShapeSetting) 복사 저장
+ */
+ const basicSettingCopySave = async (params) => {
+ try {
+ const patternData = {
+ objectNo: correntObjectNo,
+ planNo: Number(params.planNo),
+ roofSizeSet: Number(params.roofSizeSet),
+ roofAngleSet: params.roofAngleSet,
+ roofMaterialsAddList: params.roofsData.map((item) => ({
+ planNo: Number(item.planNo),
+ roofApply: item.roofApply,
+ roofSeq: item.roofSeq,
+ roofMatlCd: item.roofMatlCd,
+ roofWidth: item.roofWidth,
+ roofHeight: item.roofHeight,
+ roofHajebichi: item.roofHajebichi,
+ roofGap: item.roofGap,
+ roofLayout: item.roofLayout,
+ roofPitch: item.roofPitch,
+ roofAngle: item.roofAngle,
+ })),
+ }
+
+ await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }).then((res) => {
+ swalFire({ text: getMessage(res.returnMessage) })
+ })
+
+ /* CanvasSetting Recoil 설정 - roofSizeSet을 문자열로 변환 */
+ setCanvasSetting({
+ ...basicSetting,
+ roofSizeSet: String(params.roofSizeSet),
+ })
+
+ /* 배치면초기설정 조회 */
+ fetchBasicSettings(Number(params.planNo), null)
+
+ /* 메뉴 설정 */
+ if (['2', '3'].includes(params?.roofSizeSet)) {
+ setMenuNumber(3)
+ setType('surface')
+ setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING)
+ } else {
+ setMenuNumber(2)
+ setType('outline')
+ setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
+ }
+
+ /* 모듈 선택 데이터 초기화 */
+ resetModuleSelectionData()
+ moduleSelectedDataTrigger({ common: {}, module: {}, roofConstructions: [] })
+ const isModuleExist = canvas.getObjects().some((obj) => obj.name === POLYGON_TYPE.MODULE)
+ if (!isModuleExist) {
+ resetSelectedModules()
+ }
+ } catch (error) {
+ swalFire({ text: error.message, icon: 'error' })
+ }
+ }
+
/**
* CanvasSetting 조회 및 초기화
*/
@@ -892,7 +939,7 @@ export function useCanvasSetting() {
optionName = ['rack', 'smartRack', 'bracket', 'eaveBar', 'halfEaveBar']
break
case 'imageDisplay':
- optionName = ['9']
+ optionName = ['backGroundImage']
break
case 'totalDisplay':
/**
@@ -929,6 +976,7 @@ export function useCanvasSetting() {
setAdsorptionRange,
fetchSettings,
fetchBasicSettings,
+ basicSettingCopySave,
frontSettings,
globalFont,
setGlobalFont,
diff --git a/src/hooks/surface/usePlacementShapeDrawing.js b/src/hooks/surface/usePlacementShapeDrawing.js
index dee54673..c2b7ff98 100644
--- a/src/hooks/surface/usePlacementShapeDrawing.js
+++ b/src/hooks/surface/usePlacementShapeDrawing.js
@@ -34,6 +34,7 @@ import { usePopup } from '@/hooks/usePopup'
import { roofDisplaySelector } from '@/store/settingAtom'
import { useRoofFn } from '@/hooks/common/useRoofFn'
+import PlacementSurfaceLineProperty from '@/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty'
// 면형상 배치
export function usePlacementShapeDrawing(id) {
@@ -76,7 +77,7 @@ export function usePlacementShapeDrawing(id) {
const isFix = useRef(false)
- const { closePopup } = usePopup()
+ const { closePopup, addPopup } = usePopup()
const globalPitch = useRecoilValue(globalPitchState)
@@ -244,7 +245,8 @@ export function usePlacementShapeDrawing(id) {
setPoints([])
canvas?.renderAll()
- closePopup(id)
+
+ addPopup(id, 1, , false)
}
if (points.length < 3) {
diff --git a/src/hooks/surface/useRoofLinePropertySetting.js b/src/hooks/surface/useRoofLinePropertySetting.js
new file mode 100644
index 00000000..d6615ddf
--- /dev/null
+++ b/src/hooks/surface/useRoofLinePropertySetting.js
@@ -0,0 +1,169 @@
+import { LINE_TYPE } from '@/common/common'
+import { canvasState, currentObjectState } from '@/store/canvasAtom'
+import { useEffect, useRef } from 'react'
+import { useRecoilValue } from 'recoil'
+import { usePopup } from '../usePopup'
+import useSWR from 'swr'
+import { useSwal } from '../useSwal'
+import { useMessage } from '../useMessage'
+
+const LINE_COLOR = {
+ EAVES: '#45CD7D',
+ GABLE: '#3FBAE6',
+ RIDGE: '#9e9e9e',
+ DEFAULT: '#000000',
+ ACTIVE: '#EA10AC',
+}
+
+export function useRoofLinePropertySetting(props) {
+ const { id, roof, setIsHidden } = props
+ const canvas = useRecoilValue(canvasState)
+ const currentObject = useRecoilValue(currentObjectState)
+ const history = useRef([])
+ const { closePopup } = usePopup()
+ const { swalFire } = useSwal()
+ const { getMessage } = useMessage()
+
+ useEffect(() => {
+ if (currentObject && currentObject.name === 'roofLine') {
+ roof.lines.forEach((line) => {
+ const lineType = line.attributes?.type
+ if (!lineType) {
+ line.set({
+ stroke: '#000000',
+ strokeWidth: 4,
+ })
+ }
+ })
+ currentObject.set({
+ stroke: LINE_COLOR.ACTIVE,
+ strokeWidth: 4,
+ })
+ canvas.renderAll()
+ }
+ }, [currentObject])
+
+ const roofLinesInit = () => {
+ roof.lines.forEach((line) => {
+ canvas.add(line)
+ line.set({
+ stroke: LINE_COLOR.DEFAULT,
+ strokeWidth: 4,
+ visible: true,
+ name: 'roofLine',
+ })
+ line.bringToFront()
+ })
+ canvas.renderAll()
+ }
+
+ const handleSetEaves = () => {
+ if (!currentObject) return
+ currentObject.set({
+ attributes: {
+ ...currentObject.attributes,
+ type: LINE_TYPE.WALLLINE.EAVES,
+ },
+ stroke: LINE_COLOR.EAVES,
+ })
+
+ history.current.push(currentObject)
+ nextLineFocus(currentObject)
+ canvas.renderAll()
+ }
+
+ const handleSetGable = () => {
+ if (!currentObject) return
+ currentObject.set({
+ attributes: {
+ ...currentObject.attributes,
+ type: LINE_TYPE.WALLLINE.GABLE,
+ },
+ stroke: LINE_COLOR.GABLE,
+ })
+
+ history.current.push(currentObject)
+ nextLineFocus(currentObject)
+ canvas.renderAll()
+ }
+
+ const handleSetRidge = () => {
+ if (!currentObject) return
+ currentObject.set({
+ attributes: {
+ ...currentObject.attributes,
+ type: LINE_TYPE.SUBLINE.RIDGE,
+ },
+ stroke: LINE_COLOR.RIDGE,
+ })
+
+ history.current.push(currentObject)
+ nextLineFocus(currentObject)
+ canvas.renderAll()
+ }
+
+ const handleRollback = () => {
+ if (history.current.length === 0) {
+ return
+ }
+ const lastLine = history.current.pop()
+
+ delete lastLine.attributes
+
+ lastLine.set({
+ stroke: LINE_COLOR.DEFAULT,
+ strokeWidth: 4,
+ })
+
+ canvas.setActiveObject(lastLine)
+ canvas.renderAll()
+ }
+
+ const handleFix = () => {
+ // const roof = canvas.getObjects().find((obj) => currentObject.parentId === obj.id)
+ const notSettingLines = roof.lines.filter(
+ (line) =>
+ !line.attributes.type || ![LINE_TYPE.WALLLINE.EAVES, LINE_TYPE.WALLLINE.GABLE, LINE_TYPE.SUBLINE.RIDGE].includes(line.attributes.type),
+ )
+ if (notSettingLines.length > 0) {
+ swalFire({ text: getMessage('modal.canvas.setting.roofline.properties.setting.not.setting'), type: 'alert', icon: 'warning' })
+ return
+ }
+
+ roof.lines.forEach((line) => {
+ line.set({
+ stroke: LINE_COLOR.DEFAULT,
+ strokeWidth: 4,
+ visible: false,
+ })
+ })
+
+ canvas.renderAll()
+ closePopup(id)
+ if (setIsHidden) setIsHidden(false)
+ }
+
+ const nextLineFocus = (selectedLine) => {
+ // const roof = canvas.getObjects().find((obj) => currentObject.parentId === obj.id)
+ const lines = roof?.lines
+ if (!lines) return
+ const index = lines.findIndex((line) => line === selectedLine)
+
+ const nextLine = lines[index + 1] || lines[0]
+ if (!nextLine.attributes?.type) {
+ canvas.setActiveObject(nextLine)
+ } else {
+ //activeObject 해제
+ canvas.discardActiveObject()
+ }
+ }
+
+ return {
+ roofLinesInit,
+ handleSetEaves,
+ handleSetGable,
+ handleSetRidge,
+ handleRollback,
+ handleFix,
+ }
+}
diff --git a/src/hooks/surface/useSurfaceShapeBatch.js b/src/hooks/surface/useSurfaceShapeBatch.js
index 298ef982..dd0ae21f 100644
--- a/src/hooks/surface/useSurfaceShapeBatch.js
+++ b/src/hooks/surface/useSurfaceShapeBatch.js
@@ -19,6 +19,8 @@ import { QLine } from '@/components/fabric/QLine'
import { useRoofFn } from '@/hooks/common/useRoofFn'
import { outerLinePointsState } from '@/store/outerLineAtom'
import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom'
+import PlacementSurfaceLineProperty from '@/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty'
+import { v4 as uuidv4 } from 'uuid'
export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
const { getMessage } = useMessage()
@@ -34,7 +36,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
const { swalFire } = useSwal()
const { addCanvasMouseEventListener, initEvent } = useEvent()
// const { addCanvasMouseEventListener, initEvent } = useContext(EventContext)
- const { closePopup } = usePopup()
+ const { addPopup, closePopup } = usePopup()
const { setSurfaceShapePattern } = useRoofFn()
const applySurfaceShape = (surfaceRefs, selectedType, id) => {
@@ -101,15 +103,44 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
lockScalingX: true, // X 축 크기 조정 잠금
lockScalingY: true, // Y 축 크기 조정 잠금
name: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH_TEMP,
- flipX: xInversion !== yInversion ? yInversion : false,
- flipY: xInversion !== yInversion ? xInversion : false,
- angle: xInversion && yInversion ? Math.abs((rotate + 180) % 360) : Math.abs(rotate),
+ flipX: xInversion !== yInversion,
+ // angle: xInversion && yInversion ? Math.abs((rotate + 180) % 360) : Math.abs(rotate),
+ // angle: rotate,
originX: 'center',
originY: 'center',
pitch: globalPitch,
}
obj = new QPolygon(points, options)
+ let imageRotate = 0
+ if (xInversion && !yInversion) {
+ if (rotate % 180 === 0 || rotate < 0) {
+ imageRotate = Math.abs(rotate % 360)
+ } else {
+ if (rotate < 0) {
+ imageRotate = Math.abs((rotate - 180) % 360)
+ } else {
+ imageRotate = Math.abs((rotate + 180) % 360)
+ }
+ }
+ } else if (xInversion && yInversion) {
+ imageRotate = Math.abs((rotate + 360) % 360)
+ } else if (xInversion !== yInversion && rotate < 0) {
+ imageRotate = Math.abs(rotate)
+ } else if (!xInversion && yInversion) {
+ if (rotate % 180 === 0 || rotate < 0) {
+ imageRotate = Math.abs(rotate % 360)
+ } else {
+ if (rotate < 0) {
+ imageRotate = Math.abs((rotate - 180) % 360)
+ } else {
+ imageRotate = Math.abs((rotate + 180) % 360)
+ }
+ }
+ } else {
+ imageRotate = (rotate + 4) % 4
+ }
+ obj.set({ angle: imageRotate })
obj.setCoords() //좌표 변경 적용
canvas?.add(obj)
@@ -159,13 +190,16 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
direction: direction,
})
canvas?.add(batchSurface)
+ canvas.setActiveObject(batchSurface)
setSurfaceShapePattern(batchSurface, roofDisplay.column)
drawDirectionArrow(batchSurface)
- if (setIsHidden) setIsHidden(false)
+ // if (setIsHidden) setIsHidden(false)
// closePopup(id)
initEvent()
+ const popupId = uuidv4()
+ addPopup(popupId, 2, )
})
} else {
if (setIsHidden) setIsHidden(false)
diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js
index 52be5c90..2afbe126 100644
--- a/src/hooks/useCanvas.js
+++ b/src/hooks/useCanvas.js
@@ -3,7 +3,7 @@ import { fabric } from 'fabric'
import { actionHandler, anchorWrapper, polygonPositionHandler } from '@/util/canvas-util'
-import { useRecoilState } from 'recoil'
+import { useRecoilState, useRecoilValue } from 'recoil'
import { canvasSizeState, canvasState, fontSizeState } from '@/store/canvasAtom'
import { QLine } from '@/components/fabric/QLine'
import { QPolygon } from '@/components/fabric/QPolygon'
@@ -15,6 +15,7 @@ import { useAxios } from '@/hooks/useAxios'
import { useFont } from '@/hooks/common/useFont'
import { OBJECT_PROTOTYPE, POLYGON_TYPE, RELOAD_TYPE_PROTOTYPE, SAVE_KEY } from '@/common/common'
import { usePlan } from './usePlan'
+import { imageDisplaySelector } from '@/store/settingAtom'
export function useCanvas(id) {
const [canvas, setCanvas] = useRecoilState(canvasState)
@@ -24,6 +25,7 @@ export function useCanvas(id) {
const [canvasSize] = useRecoilState(canvasSizeState)
const [fontSize] = useRecoilState(fontSizeState)
const { setCanvasForEvent, attachDefaultEventOnCanvas } = useCanvasEvent()
+ const isImageDisplay = useRecoilValue(imageDisplaySelector)
const {} = useFont()
/**
@@ -530,6 +532,7 @@ export function useCanvas(id) {
lockRotation: false,
lockScalingX: false,
lockScalingY: false,
+ visible: isImageDisplay,
})
// image = img
canvas?.add(img)
diff --git a/src/hooks/useCirCuitTrestle.js b/src/hooks/useCirCuitTrestle.js
index 0d811dfd..8e73d59d 100644
--- a/src/hooks/useCirCuitTrestle.js
+++ b/src/hooks/useCirCuitTrestle.js
@@ -62,7 +62,6 @@ export function useCircuitTrestle() {
// 사용된 모듈아이템 목록
const getUseModuleItemList = () => {
- console.log('🚀 ~ getUseModuleItemList ~ selectedModules:', selectedModules)
return selectedModules?.itemList?.map((m) => {
return {
itemId: m.itemId,
@@ -83,7 +82,7 @@ export function useCircuitTrestle() {
.getObjects()
.filter((o) => o.id === obj.parentId)[0]
.directionText.replace(/[0-9]/g, ''),
- roofSurfaceIncl: canvas.getObjects().filter((o) => o.id === obj.parentId)[0].roofMaterial.pitch,
+ roofSurfaceIncl: +canvas.getObjects().filter((o) => o.id === obj.parentId)[0].roofMaterial.pitch,
moduleList: getModuleList(obj).map((module) => {
return {
itemId: module.moduleInfo.itemId,
diff --git a/src/hooks/useLine.js b/src/hooks/useLine.js
index e2667e80..b447d4f0 100644
--- a/src/hooks/useLine.js
+++ b/src/hooks/useLine.js
@@ -40,7 +40,7 @@ export const useLine = () => {
})
canvas
?.getObjects()
- .find((obj) => obj.parent === line)
+ .find((obj) => obj.parentId === line.id)
.set({
visible: false,
})
@@ -53,7 +53,7 @@ export const useLine = () => {
})
canvas
?.getObjects()
- .find((obj) => obj.parent === line)
+ .find((obj) => obj.parentId === line.id)
.set({
visible: true,
})
diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js
index 40b2b29e..10bc7e45 100644
--- a/src/hooks/usePlan.js
+++ b/src/hooks/usePlan.js
@@ -5,7 +5,7 @@ import { usePathname, useRouter } from 'next/navigation'
import { useRecoilState, useResetRecoilState } from 'recoil'
-import { canvasState, currentCanvasPlanState, plansState } from '@/store/canvasAtom'
+import { canvasState, currentCanvasPlanState, plansState, canvasSettingState } from '@/store/canvasAtom'
import { useAxios } from '@/hooks/useAxios'
import { useMessage } from '@/hooks/useMessage'
import { useSwal } from '@/hooks/useSwal'
@@ -39,7 +39,8 @@ export function usePlan(params = {}) {
const resetOuterLinePoints = useResetRecoilState(outerLinePointsState)
const resetPlacementShapeDrawingPoints = useResetRecoilState(placementShapeDrawingPointsState)
- const { fetchBasicSettings } = useCanvasSetting()
+ const { fetchBasicSettings, basicSettingCopySave } = useCanvasSetting()
+ const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState)
/**
* 마우스 포인터의 가이드라인 제거
@@ -184,41 +185,55 @@ export function usePlan(params = {}) {
objectNo: objectNo,
copyFlg: '0',
}
- await promisePost({ url: '/api/object/add-plan', data: planData })
- .then((res) => {
- let newPlan = {
- id: res.data.canvasId,
- objectNo: objectNo,
- planNo: res.data.planNo,
- userId: userId,
- canvasStatus: '',
- isCurrent: true,
- bgImageName: null,
- mapPositionAddress: null,
- }
+ try {
+ const res = await promisePost({ url: '/api/object/add-plan', data: planData })
+ let newPlan = {
+ id: res.data.canvasId,
+ objectNo: objectNo,
+ planNo: res.data.planNo,
+ userId: userId,
+ canvasStatus: '',
+ isCurrent: true,
+ bgImageName: null,
+ mapPositionAddress: null,
+ }
- if (isInitPlan) {
- /* 초기 플랜 생성인 경우 플랜 목록 초기화 */
- setCurrentCanvasPlan(newPlan)
- setPlans([newPlan])
- } else {
- if (isCopy) {
- /* 복제 플랜 생성인 경우 현재 캔버스 데이터를 복제 */
- newPlan.canvasStatus = currentCanvasData()
- newPlan.bgImageName = currentCanvasPlan?.bgImageName ?? null
- newPlan.mapPositionAddress = currentCanvasPlan?.mapPositionAddress ?? null
- }
- setCurrentCanvasPlan(newPlan)
- setPlans((plans) => [...plans.map((plan) => ({ ...plan, isCurrent: false })), newPlan])
- swalFire({ text: getMessage('plan.message.save') })
- }
+ if (isInitPlan) {
+ /* 초기 플랜 생성인 경우 플랜 목록 초기화 */
+ setCurrentCanvasPlan(newPlan)
+ setPlans([newPlan])
/* 플랜 추가 시 배치면초기설정 정보 조회 */
fetchBasicSettings(newPlan.planNo, null)
- })
- .catch((error) => {
- swalFire({ text: error.response.data.message, icon: 'error' })
- })
+ } else {
+ if (isCopy) {
+ /* 복제 플랜 생성인 경우 현재 캔버스 데이터를 복제 */
+ newPlan.canvasStatus = currentCanvasData()
+ newPlan.bgImageName = currentCanvasPlan?.bgImageName ?? null
+ newPlan.mapPositionAddress = currentCanvasPlan?.mapPositionAddress ?? null
+
+ /* 복제 시 배치면 초기설정 복사 */
+ basicSettingCopySave({
+ ...canvasSetting,
+ planNo: newPlan.planNo,
+ selectedRoofMaterial: {
+ ...canvasSetting.selectedRoofMaterial,
+ planNo: newPlan.planNo,
+ },
+ roofsData: canvasSetting.roofsData.map((roof) => ({
+ ...roof,
+ planNo: newPlan.planNo,
+ })),
+ })
+ }
+ setCurrentCanvasPlan(newPlan)
+ setPlans((plans) => [...plans.map((plan) => ({ ...plan, isCurrent: false })), newPlan])
+
+ swalFire({ text: getMessage('plan.message.save') })
+ }
+ } catch (error) {
+ swalFire({ text: error.response.data.message, icon: 'error' })
+ }
}
/**
@@ -275,7 +290,6 @@ export function usePlan(params = {}) {
const objectNo = floorPlanState.objectNo
//견적서 or 발전시뮬
-
if (pathname !== '/floor-plan') {
await promiseGet({ url: `/api/estimate/${objectNo}/${planNo}/detail` })
.then((res) => {
@@ -304,9 +318,6 @@ export function usePlan(params = {}) {
// 클릭한 플랜 탭으로 이동
setCurrentCanvasPlan(plans.find((plan) => plan.id === newCurrentId))
setPlans((plans) => plans.map((plan) => ({ ...plan, isCurrent: plan.id === newCurrentId })))
-
- /* 플랜 이동 시 배치면초기설정 정보 조회 (견적서 메뉴 제외) */
- fetchBasicSettings(planNo, null)
} else {
swalFire({ text: getMessage('estimate.menu.move.valid1') })
}
@@ -494,7 +505,13 @@ export function usePlan(params = {}) {
* @param {string} planNo - 플랜번호
*/
const deleteBasicSettings = async (objectNo, planNo) => {
- await promiseDel({ url: `/api/canvas-management/delete-basic-settings/${objectNo}/${planNo}` })
+ try {
+ await promiseDel({ url: `/api/canvas-management/canvas-basic-settings/delete-basic-settings/${objectNo}/${planNo}` })
+ } catch (error) {
+ /* 오류를 무시하고 계속 진행 */
+ console.log('Basic settings delete failed or not found:', error)
+ // swalFire({ text: error.message, icon: 'error' })
+ }
}
return {
diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js
index 99845d46..1dc3f231 100644
--- a/src/hooks/usePolygon.js
+++ b/src/hooks/usePolygon.js
@@ -7,7 +7,7 @@ import { isSamePoint, removeDuplicatePolygons } from '@/util/qpolygon-utils'
import { flowDisplaySelector } from '@/store/settingAtom'
import { fontSelector } from '@/store/fontAtom'
import { QLine } from '@/components/fabric/QLine'
-import { POLYGON_TYPE } from '@/common/common'
+import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
export const usePolygon = () => {
const canvas = useRecoilValue(canvasState)
@@ -909,6 +909,29 @@ export const usePolygon = () => {
const allLines = [...polygonLines, ...innerLines]
+ // 2025-02-19 대각선은 케라바, 직선은 용마루로 세팅
+ innerLines.forEach((innerLine) => {
+ const startPoint = innerLine.startPoint
+ const endPoint = innerLine.endPoint
+
+ // startPoint와 endPoint의 각도가 0,90,180,270이면 직선으로 판단
+ if (Math.abs(startPoint.x - endPoint.x) < 2 || Math.abs(startPoint.y - endPoint.y) < 2) {
+ if (!innerLine.attributes || !innerLine.attributes.type) {
+ innerLine.attributes = {
+ ...innerLine.attributes,
+ type: LINE_TYPE.SUBLINE.RIDGE,
+ }
+ }
+ } else {
+ if (!innerLine.attributes || !innerLine.attributes.type) {
+ innerLine.attributes = {
+ ...innerLine.attributes,
+ type: LINE_TYPE.SUBLINE.GABLE,
+ }
+ }
+ }
+ })
+
/**
* 왼쪽 상단을 startPoint로 전부 변경
*/
diff --git a/src/locales/ja.json b/src/locales/ja.json
index 9f06310e..677f9cab 100644
--- a/src/locales/ja.json
+++ b/src/locales/ja.json
@@ -269,6 +269,10 @@
"modal.canvas.setting.wallline.properties.setting.info": "※属性を変更する外壁線を選択し、軒で設定またはケラバで設定\nボタンをクリックして設定値を適用してください。\n",
"modal.canvas.setting.wallline.properties.setting.eaves": "軒で設定",
"modal.canvas.setting.wallline.properties.setting.edge": "ケラバに設定",
+ "modal.canvas.setting.wallline.properties.setting.ridge": "용마루로 설정(JA)",
+ "modal.canvas.setting.roofline.properties.setting": "지붕선 속성 설정(JA)",
+ "modal.canvas.setting.roofline.properties.setting.info": "※ 속성을 변경할 지붕선을 선택하고 처마로 설정 또는 케라바로 설정\n 버튼을 클릭하여 설정값을 적용하십시오.\n(JA)",
+ "modal.canvas.setting.roofline.properties.setting.not.setting": "설정하지 않은 라인이 존재합니다.(JA)",
"modal.eaves.gable.edit": "軒/ケラバ変更",
"modal.eaves.gable.edit.basic": "通常",
"modal.eaves.gable.edit.wall.merge.info": "河屋などの壁に面する屋根を作成します。",
@@ -659,9 +663,9 @@
"stuff.planReqPopup.title": "設計依頼のインポート",
"stuff.temp.subTitle": "商品情報",
"stuff.temp.subTitle2": "作図",
- "stuff.detail.header.notExistObjectNo": "存在しないものです。",
- "stuff.detail.header.successCopy": "物件番号がコピーされました。",
- "stuff.detail.header.failCopy": "物件番号のコピーに失敗しました。",
+ "stuff.detail.header.notExistObjectNo": "存在しないもの番号です.",
+ "stuff.detail.header.successCopy": "物件番号がコピーされました.",
+ "stuff.detail.header.failCopy": "物件番号のコピーに失敗しました.",
"stuff.detail.header.objectNo": "物件番号",
"stuff.detail.header.specificationConfirmDate": "仕様確認日",
"stuff.detail.header.lastEditDatetime": "更新日時",
@@ -783,7 +787,7 @@
"stuff.detail.planGridHeader.capacity": "システム容量",
"stuff.detail.planGridHeader.roofMaterialIdMulti": "屋根材",
"stuff.detail.planGridHeader.constructSpecificationMulti": "施工方法",
- "stuff.detail.planGridHeader.supprotMethodIdMulti": "架台",
+ "stuff.detail.planGridHeader.supportMethodIdMulti": "架台",
"stuff.detail.planGridHeader.pcTypeNo": "パワーコンディショナー",
"stuff.detail.planGridHeader.management": "管理",
"stuff.detail.planGrid.btn1": "見積書の照会",
@@ -1009,6 +1013,8 @@
"module.place.select.one.module": "モジュールは1つだけ選択してください。",
"batch.canvas.delete.all": "配置面の内容をすべて削除しますか?",
"module.not.found": "インストールモジュールを選択してください。",
+ "module.circuit.minimun.error": "회로번호는 1 이상입력해주세요.(JA)",
+ "module.already.exist.error": "회로번호가 같은 다른 파워 컨디셔너 모듈이 있습니다. 다른 회로번호를 설정하십시오.(JA)",
"construction.length.difference": "屋根面工法をすべて選択してください。",
"menu.validation.canvas.roof": "パネルを配置するには、屋根面を入力する必要があります。",
"batch.object.outside.roof": "オブジェクトは屋根に設置する必要があります。",
diff --git a/src/locales/ko.json b/src/locales/ko.json
index b43e6853..67b4b301 100644
--- a/src/locales/ko.json
+++ b/src/locales/ko.json
@@ -269,6 +269,10 @@
"modal.canvas.setting.wallline.properties.setting.info": "※ 속성을 변경할 외벽선을 선택하고 처마로 설정 또는 케라바로 설정\n 버튼을 클릭하여 설정값을 적용하십시오.\n",
"modal.canvas.setting.wallline.properties.setting.eaves": "처마로 설정",
"modal.canvas.setting.wallline.properties.setting.edge": "케라바로 설정",
+ "modal.canvas.setting.wallline.properties.setting.ridge": "용마루로 설정",
+ "modal.canvas.setting.roofline.properties.setting": "지붕선 속성 설정",
+ "modal.canvas.setting.roofline.properties.setting.info": "※ 속성을 변경할 지붕선을 선택하고 처마로 설정 또는 케라바로 설정\n 버튼을 클릭하여 설정값을 적용하십시오.\n",
+ "modal.canvas.setting.roofline.properties.setting.not.setting": "설정하지 않은 라인이 존재합니다.",
"modal.eaves.gable.edit": "처마/케라바 변경",
"modal.eaves.gable.edit.basic": "통상",
"modal.eaves.gable.edit.wall.merge.info": "하옥 등 벽에 접하는 지붕을 작성합니다.",
@@ -659,7 +663,7 @@
"stuff.planReqPopup.title": "설계의뢰 불러오기",
"stuff.temp.subTitle": "물건정보",
"stuff.temp.subTitle2": "도면작성",
- "stuff.detail.header.notExistObjectNo": "존재하지 않는 물건입니다.",
+ "stuff.detail.header.notExistObjectNo": "존재하지 않는 물건번호 입니다.",
"stuff.detail.header.successCopy": "물건번호가 복사되었습니다.",
"stuff.detail.header.failCopy": "물건번호 복사에 실패했습니다.",
"stuff.detail.header.objectNo": "물건번호",
@@ -783,7 +787,7 @@
"stuff.detail.planGridHeader.capacity": "시스템용량",
"stuff.detail.planGridHeader.roofMaterialIdMulti": "지붕재",
"stuff.detail.planGridHeader.constructSpecificationMulti": "시공방법",
- "stuff.detail.planGridHeader.supprotMethodIdMulti": "가대",
+ "stuff.detail.planGridHeader.supportMethodIdMulti": "가대",
"stuff.detail.planGridHeader.pcTypeNo": "파워컨디셔너",
"stuff.detail.planGridHeader.management": "관리",
"stuff.detail.planGrid.btn1": "견적서 조회",
@@ -1010,6 +1014,8 @@
"module.place.select.one.module": "모듈은 하나만 선택해주세요.",
"batch.canvas.delete.all": "배치면 내용을 전부 삭제하시겠습니까?",
"module.not.found": "모듈을 선택하세요.",
+ "module.circuit.minimun.error": "회로번호는 1 이상입력해주세요.",
+ "module.already.exist.error": "회로번호가 같은 다른 파워 컨디셔너 모듈이 있습니다. 다른 회로번호를 설정하십시오.",
"construction.length.difference": "지붕면 공법을 전부 선택해주세요.",
"menu.validation.canvas.roof": "패널을 배치하려면 지붕면을 입력해야 합니다.",
"batch.object.outside.roof": "오브젝트는 지붕내에 설치해야 합니다.",
diff --git a/src/styles/_modal.scss b/src/styles/_modal.scss
index b6e2d322..a19aba2e 100644
--- a/src/styles/_modal.scss
+++ b/src/styles/_modal.scss
@@ -769,6 +769,13 @@ $alert-color: #101010;
background-color: #365f6e;
}
}
+ &.gray{
+ background-color: #535353;
+ border: 1px solid #9e9e9e;
+ &:hover{
+ background-color: #6b6b6b;
+ }
+ }
}
}
}
diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js
index 0444c93d..557342b8 100644
--- a/src/util/qpolygon-utils.js
+++ b/src/util/qpolygon-utils.js
@@ -3525,7 +3525,14 @@ export const calcLinePlaneSize = (points) => {
* @returns number
*/
export const calcLineActualSize = (points, degree) => {
+ const { x1, y1, x2, y2 } = points
const planeSize = calcLinePlaneSize(points)
- const height = Big(Math.tan(Big(degree).times(Math.PI / 180))).times(planeSize)
+ let height = Big(Math.tan(Big(degree).times(Math.PI / 180))).times(planeSize)
+ /**
+ * 대각선일 경우 높이 계산 변경
+ */
+ if (x1 !== x2 && y1 !== y2) {
+ height = Big(Math.tan(Big(degree).times(Math.PI / 180))).times(Big(x1).minus(x2).times(10).round())
+ }
return Big(planeSize).pow(2).plus(height.pow(2)).sqrt().abs().round().toNumber()
}
diff --git a/startscript.js b/startscript.js
index 37f52696..350b2c06 100644
--- a/startscript.js
+++ b/startscript.js
@@ -1,2 +1,2 @@
var exec = require('child_process').exec
-exec('yarn start', { windowsHide: true })
+exec('yarn serve', { windowsHide: true })