Compare commits

..

18 Commits

Author SHA1 Message Date
89ae48d2fe [1475] 플랜복사(다중지붕 복사안됨 - 단일지붕) 2026-02-25 10:05:02 +09:00
4a4a86e6b9 Merge branch 'dev' of https://git.hanasys.jp/qcast3/qcast-front into feature/skeleton-dev
# Conflicts:
#	src/util/skeleton-utils.js
2026-02-25 09:04:34 +09:00
188e6ee2f2 [1475] 플랜복사(다중지붕 복사안됨 - 단일지붕) 2026-02-23 17:29:30 +09:00
d1045fa0df Merge branch 'dev' of https://git.hanasys.jp/qcast3/qcast-front into dev_ysCha 2026-02-23 16:48:41 +09:00
9ada34c020 [1480] 설정값 오류 (이전플랜저장 -> 현플랜저장) 2026-02-23 16:48:16 +09:00
4bf90e7dfb 이동시 spare 0.5 추가 2026-02-23 11:40:34 +09:00
4ce66733dd [1490]메뉴 표기 변경 요청 (실측값입력-> 배치면) 2026-02-23 10:40:37 +09:00
df4b2a889b rack정보 제대로 못가져오는 현상 수정 2026-02-20 11:41:19 +09:00
c2b4f5c7df 치수입력방식에 따른 페이지구분 2026-02-13 13:09:08 +09:00
14dc84502c [1386]T01 계정이 작성한 안건 중 해당 판매점 ID가 열람 가능한 것에 한합니다. 2026-02-13 08:26:25 +09:00
55e201db9c 메뉴를 찾아가지 못하는 오류 발생 2026-02-12 15:50:27 +09:00
cf84e51f24 [1455]처마커버 표시문제 2026-02-12 15:02:55 +09:00
4b635493fe 간격이 다를 때 스켈레톤이 문제 2026-02-12 14:22:41 +09:00
0f59fa2b36 지붕면 회전 시 길이 계산 수행하도록 수정 2026-02-11 15:26:46 +09:00
2cef7546ab Merge branch 'dev' of https://git.hanasys.jp/qcast3/qcast-front into dev 2026-02-11 15:24:04 +09:00
a92f335a83 지붕재 변경 시 길이 계산 강제 실행 2026-02-11 15:23:58 +09:00
b4baaa06dd 전화번호 0000-000-000 추가 2026-02-10 17:55:31 +09:00
256189fe40 배치면 초기 설정 후 길이 계산 오류 수정, 배치면 복사 시 길이 이상 수정 2026-02-10 11:44:34 +09:00
16 changed files with 290 additions and 163 deletions

View File

@ -33,6 +33,7 @@ import { compasDegAtom } from '@/store/orientationAtom'
import { hotkeyStore } from '@/store/hotkeyAtom' import { hotkeyStore } from '@/store/hotkeyAtom'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { outerLinePointsState } from '@/store/outerLineAtom' import { outerLinePointsState } from '@/store/outerLineAtom'
import { canvasSettingState } from '@/store/canvasAtom'
export default function CanvasFrame() { export default function CanvasFrame() {
const canvasRef = useRef(null) const canvasRef = useRef(null)
@ -59,6 +60,7 @@ export default function CanvasFrame() {
const { basicSetting, fetchBasicSettings } = useCanvasSetting() const { basicSetting, fetchBasicSettings } = useCanvasSetting()
const { selectedMenu, setSelectedMenu } = useCanvasMenu() const { selectedMenu, setSelectedMenu } = useCanvasMenu()
const { initEvent } = useEvent() const { initEvent } = useEvent()
const canvasSetting = useRecoilValue(canvasSettingState)
const loadCanvas = () => { const loadCanvas = () => {
if (!canvas) return if (!canvas) return
@ -82,7 +84,12 @@ export default function CanvasFrame() {
setSelectedMenu('module') setSelectedMenu('module')
}, 500) }, 500)
} else if (canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL).length > 0) { } else if (canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL).length > 0) {
setSelectedMenu('outline') // canvasSetting.roofSizeSet
if (canvasSetting?.roofSizeSet === '2') {
setSelectedMenu('surface') // surface
} else {
setSelectedMenu('outline') // outline
}
} else { } else {
setTimeout(() => { setTimeout(() => {
setSelectedMenu('surface') setSelectedMenu('surface')
@ -121,7 +128,11 @@ export default function CanvasFrame() {
if (currentCanvasPlan.planNo) { if (currentCanvasPlan.planNo) {
/* 약간의 지연을 줘서 roofMaterials가 로드될 시간을 확보 */ /* 약간의 지연을 줘서 roofMaterials가 로드될 시간을 확보 */
setTimeout(() => { setTimeout(() => {
// canvasSetting
// canvasSetting roofSizeSet API
if (!canvasSetting?.roofSizeSet) {
fetchBasicSettings(Number(currentCanvasPlan.planNo), null) fetchBasicSettings(Number(currentCanvasPlan.planNo), null)
}
}, 100) }, 100)
} }
}, [currentCanvasPlan, canvas]) }, [currentCanvasPlan, canvas])

View File

@ -426,7 +426,7 @@ export default function CanvasMenu(props) {
return ( return (
(['2', '3'].includes(canvasSetting?.roofSizeSet) && menu.type === 'outline') || (['2', '3'].includes(canvasSetting?.roofSizeSet) && menu.type === 'outline') ||
(selectedMenu === 'module' && ['placement', 'outline'].includes(menu.type)) || (selectedMenu === 'module' && ['placement', 'outline'].includes(menu.type)) ||
(isExistModule() && ['placement', 'outline'].some((num) => num === menu.type)) || (isExistModule() && canvasSetting?.roofSizeSet !== '1' && ['placement', 'outline'].some((num) => num === menu.type)) ||
(['estimate', 'simulation'].includes(selectedMenu) && ['placement', 'outline', 'surface'].includes(menu.type)) (['estimate', 'simulation'].includes(selectedMenu) && ['placement', 'outline', 'surface'].includes(menu.type))
) )
} }

View File

@ -41,7 +41,7 @@ export default function FloorPlan({ children }) {
promiseGet({ url: `/api/object/${objectNo}/detail` }).then((res) => { promiseGet({ url: `/api/object/${objectNo}/detail` }).then((res) => {
if (res.status === 200) { if (res.status === 200) {
const { data } = res const { data } = res
console.log(data) //console.log(data)
let surfaceTypeValue let surfaceTypeValue
if (res.data.surfaceType === 'Ⅲ・Ⅳ') { if (res.data.surfaceType === 'Ⅲ・Ⅳ') {

View File

@ -211,8 +211,8 @@ export default function ModuleTabContents({ tabIndex, addRoof, setAddedRoofs, ro
<input <input
type="checkbox" type="checkbox"
id={`ch01_${tabIndex}`} id={`ch01_${tabIndex}`}
disabled={cvrYn === 'N' ? true : false} disabled={cvrYn !== 'Y'}
checked={cvrYn === 'N' ? false : cvrChecked ?? true} checked={cvrYn === 'Y' && (cvrChecked ?? true)}
onChange={handleCvrChecked} onChange={handleCvrChecked}
/> />
<label htmlFor={`ch01_${tabIndex}`}>{getMessage('modal.module.basic.setting.module.eaves.bar.fitting')}</label> <label htmlFor={`ch01_${tabIndex}`}>{getMessage('modal.module.basic.setting.module.eaves.bar.fitting')}</label>

View File

@ -194,7 +194,7 @@ const Placement = forwardRef((props, refs) => {
type="checkbox" type="checkbox"
id={item.itemId} id={item.itemId}
name={item.itemId} name={item.itemId}
checked={selectedItems[item.itemId]} checked={selectedItems[item.itemId] || false}
onChange={(e) => handleSelectedItem(e, item.itemId)} onChange={(e) => handleSelectedItem(e, item.itemId)}
/> />
<label htmlFor={item.itemId}></label> <label htmlFor={item.itemId}></label>
@ -217,8 +217,7 @@ const Placement = forwardRef((props, refs) => {
type="text" type="text"
className="input-origin block" className="input-origin block"
name="row" name="row"
value={props.layoutSetup[index]?.row ?? 1} value={props.layoutSetup[index]?.row || 1}
//defaultValue={0}
onChange={(e) => handleLayoutSetup(e, item.itemId, index)} onChange={(e) => handleLayoutSetup(e, item.itemId, index)}
/> />
</div> </div>
@ -229,8 +228,7 @@ const Placement = forwardRef((props, refs) => {
type="text" type="text"
className="input-origin block" className="input-origin block"
name="col" name="col"
value={props.layoutSetup[index]?.col ?? 1} value={props.layoutSetup[index]?.col || 1}
//defaultValue={0}
onChange={(e) => handleLayoutSetup(e, item.itemId, index)} onChange={(e) => handleLayoutSetup(e, item.itemId, index)}
/> />
</div> </div>
@ -268,7 +266,7 @@ const Placement = forwardRef((props, refs) => {
type="radio" type="radio"
name="radio02" name="radio02"
id="ra03" id="ra03"
checked={moduleSetupOption.isChidori} checked={moduleSetupOption.isChidori === true}
disabled={isChidoriNotAble} disabled={isChidoriNotAble}
value={'true'} value={'true'}
onChange={(e) => handleChangeChidori(e)} onChange={(e) => handleChangeChidori(e)}
@ -280,7 +278,7 @@ const Placement = forwardRef((props, refs) => {
type="radio" type="radio"
name="radio02" name="radio02"
id="ra04" id="ra04"
checked={!moduleSetupOption.isChidori} checked={moduleSetupOption.isChidori === false}
value={'false'} value={'false'}
onChange={(e) => handleChangeChidori(e)} onChange={(e) => handleChangeChidori(e)}
/> />

View File

@ -63,6 +63,7 @@ export default function CircuitTrestleSetting({ id }) {
const originCanvasViewPortTransform = useRef([]) const originCanvasViewPortTransform = useRef([])
const [isFold, setIsFold] = useState(false) const [isFold, setIsFold] = useState(false)
const [showHiddenBasicSetting, setShowHiddenBasicSetting] = useState(true)
const { const {
makers, makers,
@ -108,6 +109,14 @@ export default function CircuitTrestleSetting({ id }) {
} }
}, []) }, [])
// /
useEffect(() => {
const timer = setTimeout(() => {
setShowHiddenBasicSetting(false)
}, 300)
return () => clearTimeout(timer)
}, [])
// rack reopen // rack reopen
useEffect(() => { useEffect(() => {
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE) const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
@ -998,6 +1007,12 @@ export default function CircuitTrestleSetting({ id }) {
} }
return ( return (
<>
{showHiddenBasicSetting && (
<div style={{ display: 'none' }}>
<BasicSetting id={`hidden-basic-${id}`} />
</div>
)}
<WithDraggable isShow={true} pos={{ x: 50, y: 230 }} className="l-2"> <WithDraggable isShow={true} pos={{ x: 50, y: 230 }} className="l-2">
<WithDraggable.Header <WithDraggable.Header
title={getMessage('modal.circuit.trestle.setting')} title={getMessage('modal.circuit.trestle.setting')}
@ -1056,5 +1071,6 @@ export default function CircuitTrestleSetting({ id }) {
)} )}
</WithDraggable.Body> </WithDraggable.Body>
</WithDraggable> </WithDraggable>
</>
) )
} }

View File

@ -8,7 +8,7 @@ import MaterialGuide from '@/components/floor-plan/modal/placementShape/Material
import WithDraggable from '@/components/common/draggable/WithDraggable' import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting' import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { addedRoofsState, roofDisplaySelector, roofMaterialsAtom } from '@/store/settingAtom' import { addedRoofsState, roofDisplaySelector, roofMaterialsAtom } from '@/store/settingAtom'
import { useCommonCode } from '@/hooks/common/useCommonCode' import { useCommonCode } from '@/hooks/common/useCommonCode'
import QSelectBox from '@/components/common/select/QSelectBox' import QSelectBox from '@/components/common/select/QSelectBox'
@ -16,11 +16,12 @@ import { globalLocaleStore } from '@/store/localeAtom'
import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util' import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util'
import { usePolygon } from '@/hooks/usePolygon' import { usePolygon } from '@/hooks/usePolygon'
import { canvasState } from '@/store/canvasAtom' import { canvasState, canvasSettingState, currentCanvasPlanState, currentMenuState } from '@/store/canvasAtom'
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
import { MENU, POLYGON_TYPE } from '@/common/common'
import { useRoofFn } from '@/hooks/common/useRoofFn' import { useRoofFn } from '@/hooks/common/useRoofFn'
import { usePlan } from '@/hooks/usePlan' import { usePlan } from '@/hooks/usePlan'
import { normalizeDecimal, normalizeDigits } from '@/util/input-utils' import { normalizeDecimal } from '@/util/input-utils'
import { logger } from '@/util/logger'
import { CalculatorInput } from '@/components/common/input/CalcInput' import { CalculatorInput } from '@/components/common/input/CalcInput'
/** /**
@ -41,14 +42,23 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
const { basicSetting, setBasicSettings, fetchBasicSettings, basicSettingSave } = useCanvasSetting() const { basicSetting, setBasicSettings, fetchBasicSettings, basicSettingSave } = useCanvasSetting()
const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState) const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState)
const { findCommonCode } = useCommonCode() const { findCommonCode } = useCommonCode()
const [raftCodes, setRaftCodes] = useState([]) /** 서까래 정보 */ const [raftCodes, setRaftCodes] = useState([])
const [currentRoof, setCurrentRoof] = useState(null) /** 현재 선택된 지붕재 정보 */ /** 서까래 정보 */
const { closePopup } = usePopup() /** usePopup에서 closePopup 함수 가져오기 */ const [currentRoof, setCurrentRoof] = useState(null)
/** 현재 선택된 지붕재 정보 */
const { closePopup } = usePopup()
/** usePopup에서 closePopup 함수 가져오기 */
const { drawDirectionArrow } = usePolygon() const { drawDirectionArrow } = usePolygon()
const { setSurfaceShapePattern } = useRoofFn() const { setSurfaceShapePattern } = useRoofFn()
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState)
const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
const roofDisplay = useRecoilValue(roofDisplaySelector) const roofDisplay = useRecoilValue(roofDisplaySelector)
const { setPolygonLinesActualSize } = usePolygon()
const { setSelectedMenu } = useCanvasMenu()
const setCurrentMenu = useSetRecoilState(currentMenuState)
const roofRef = { const roofRef = {
roofCd: useRef(null), roofCd: useRef(null),
width: useRef(null), width: useRef(null),
@ -114,6 +124,15 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
if (openPoint && openPoint === 'canvasMenus') fetchBasicSettings(planNo, openPoint) if (openPoint && openPoint === 'canvasMenus') fetchBasicSettings(planNo, openPoint)
}, []) }, [])
/**
* 현재 활성 플랜이 변경될 currentRoof.planNo 업데이트
*/
useEffect(() => {
if (currentCanvasPlan?.planNo && currentRoof) {
setCurrentRoof(prev => ({ ...prev, planNo: currentCanvasPlan.planNo }))
}
}, [currentCanvasPlan?.planNo])
/** /**
* 배치면초기설정 데이터 조회 화면 오픈 * 배치면초기설정 데이터 조회 화면 오픈
*/ */
@ -121,7 +140,12 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
if (addedRoofs.length > 0) { if (addedRoofs.length > 0) {
const raftCodeList = findCommonCode('203800') const raftCodeList = findCommonCode('203800')
setRaftCodes(raftCodeList) setRaftCodes(raftCodeList)
setCurrentRoof({ ...addedRoofs[0], planNo: planNo, roofSizeSet: String(basicSetting.roofSizeSet), roofAngleSet: basicSetting.roofAngleSet }) setCurrentRoof({
...addedRoofs[0],
planNo: currentCanvasPlan?.planNo || planNo,
roofSizeSet: String(basicSetting.roofSizeSet),
roofAngleSet: basicSetting.roofAngleSet,
})
} else { } else {
/** 데이터 설정 확인 후 데이터가 없으면 기본 데이터 설정 */ /** 데이터 설정 확인 후 데이터가 없으면 기본 데이터 설정 */
setCurrentRoof({ ...DEFAULT_ROOF_SETTINGS }) setCurrentRoof({ ...DEFAULT_ROOF_SETTINGS })
@ -154,10 +178,6 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
}) })
}, [currentRoof]) }, [currentRoof])
const handleRoofSizeSetChange = (value) => {
setCurrentRoof({ ...currentRoof, roofSizeSet: value })
}
const handleRoofAngleSetChange = (value) => { const handleRoofAngleSetChange = (value) => {
setCurrentRoof({ ...currentRoof, roofAngleSet: value }) setCurrentRoof({ ...currentRoof, roofAngleSet: value })
} }
@ -209,10 +229,9 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
* 배치면초기설정 저장 버튼 클릭 * 배치면초기설정 저장 버튼 클릭
*/ */
const handleSaveBtn = async () => { const handleSaveBtn = async () => {
const roofInfo = { const roofInfo = {
...currentRoof, ...currentRoof,
planNo: basicSetting.planNo, planNo: currentCanvasPlan?.planNo || basicSetting.planNo,
roofCd: roofRef.roofCd.current?.value, roofCd: roofRef.roofCd.current?.value,
width: roofRef.width.current?.value, width: roofRef.width.current?.value,
length: roofRef.length.current?.value, length: roofRef.length.current?.value,
@ -227,25 +246,22 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
newAddedRoofs[0] = { ...roofInfo } newAddedRoofs[0] = { ...roofInfo }
setAddedRoofs(newAddedRoofs) setAddedRoofs(newAddedRoofs)
logger.debug('save Info', { // currentRoof roofSizeSet canvasSetting
...basicSetting, setCanvasSetting({ ...canvasSetting, roofSizeSet: currentRoof?.roofSizeSet })
selectedRoofMaterial: {
...newAddedRoofs[0],
},
})
/** /**
* 배치면초기설정 저장 * 배치면초기설정 저장 (메뉴 변경/useEffect 트리거 없이)
*/ */
basicSettingSave({ basicSettingSave({
...basicSetting, ...basicSetting,
planNo: currentCanvasPlan?.planNo || basicSetting.planNo,
/** /**
* 선택된 지붕재 정보 * 선택된 지붕재 정보
*/ */
selectedRoofMaterial: { selectedRoofMaterial: {
...newAddedRoofs[0], ...newAddedRoofs[0],
}, },
}) }, { skipSideEffects: true })
const roofs = canvas.getObjects().filter((obj) => obj.roofMaterial?.index === 0) const roofs = canvas.getObjects().filter((obj) => obj.roofMaterial?.index === 0)
@ -254,7 +270,27 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
setSurfaceShapePattern(roof, roofDisplay.column, false, { ...roofInfo }) setSurfaceShapePattern(roof, roofDisplay.column, false, { ...roofInfo })
roof.roofMaterial = { ...roofInfo } roof.roofMaterial = { ...roofInfo }
drawDirectionArrow(roof) drawDirectionArrow(roof)
setPolygonLinesActualSize(roof, true)
}) })
canvas.renderAll()
/** 지붕면 존재 여부에 따라 메뉴 설정 */
const hasRoofs = canvas.getObjects().some((obj) => obj.name === POLYGON_TYPE.ROOF)
// roofSizeSet
if (currentRoof?.roofSizeSet === '2') {
setSelectedMenu('surface')
setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING)
} else if (currentRoof?.roofSizeSet === '1') {
setSelectedMenu('outline')
setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
} else if (hasRoofs) {
setSelectedMenu('surface')
setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING)
} else {
setSelectedMenu('outline')
setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
}
/* 저장 후 화면 닫기 */ /* 저장 후 화면 닫기 */
closePopup(id) closePopup(id)
@ -353,26 +389,26 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
value={index === 0 ? (currentRoof?.pitch ?? basicSetting?.inclBase ?? '0') : (currentRoof?.angle ?? '0')} value={index === 0 ? (currentRoof?.pitch ?? basicSetting?.inclBase ?? '0') : (currentRoof?.angle ?? '0')}
onChange={(value) => { onChange={(value) => {
if (index === 0) { if (index === 0) {
const pitch = value === '' ? '' : Number(value); const pitch = value === '' ? '' : Number(value)
const angle = pitch === '' ? '' : getDegreeByChon(pitch); const angle = pitch === '' ? '' : getDegreeByChon(pitch)
setCurrentRoof(prev => ({ setCurrentRoof((prev) => ({
...prev, ...prev,
pitch, pitch,
angle angle,
})); }))
} else { } else {
const angle = value === '' ? '' : Number(value); const angle = value === '' ? '' : Number(value)
const pitch = angle === '' ? '' : getChonByDegree(angle); const pitch = angle === '' ? '' : getChonByDegree(angle)
setCurrentRoof(prev => ({ setCurrentRoof((prev) => ({
...prev, ...prev,
pitch, pitch,
angle angle,
})); }))
} }
}} }}
options={{ options={{
allowNegative: false, allowNegative: false,
allowDecimal: true allowDecimal: true,
}} }}
/> />
</div> </div>
@ -440,7 +476,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
disabled={currentRoof?.roofSizeSet === '3'} disabled={currentRoof?.roofSizeSet === '3'}
options={{ options={{
allowNegative: false, allowNegative: false,
allowDecimal: false //(index !== 0), allowDecimal: false, //(index !== 0),
}} }}
/> />
</div> </div>
@ -475,7 +511,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
disabled={currentRoof?.roofSizeSet === '3'} disabled={currentRoof?.roofSizeSet === '3'}
options={{ options={{
allowNegative: false, allowNegative: false,
allowDecimal: false //(index !== 0), allowDecimal: false, //(index !== 0),
}} }}
/> />
</div> </div>
@ -522,20 +558,19 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
ref={roofRef.hajebichi} ref={roofRef.hajebichi}
value={currentRoof?.hajebichi ?? basicSetting?.roofPchBase ?? '0'} value={currentRoof?.hajebichi ?? basicSetting?.roofPchBase ?? '0'}
onChange={(value) => { onChange={(value) => {
const hajebichi = value === '' ? '' : Number(value); const hajebichi = value === '' ? '' : Number(value)
setCurrentRoof(prev => ({ setCurrentRoof((prev) => ({
...prev, ...prev,
hajebichi hajebichi,
})); }))
}} }}
readOnly={currentRoof?.roofPchAuth === 'R'} readOnly={currentRoof?.roofPchAuth === 'R'}
disabled={currentRoof?.roofSizeSet === '3'} disabled={currentRoof?.roofSizeSet === '3'}
options={{ options={{
allowNegative: false, allowNegative: false,
allowDecimal: false //(index !== 0), allowDecimal: false, //(index !== 0),
}} }}
/> />
</div> </div>
</div> </div>
)} )}

View File

@ -357,7 +357,11 @@ export default function StuffDetail() {
if (res?.data?.createSaleStoreId === 'T01') { if (res?.data?.createSaleStoreId === 'T01') {
if (session?.storeId !== 'T01') { if (session?.storeId !== 'T01') {
setShowButton('none') //T01 ID .
if(session?.storeId !== managementState?.saleStoreId){
return false
}
} }
} }
if (isObjectNotEmpty(res.data)) { if (isObjectNotEmpty(res.data)) {
@ -1658,8 +1662,12 @@ export default function StuffDetail() {
const getCellDoubleClicked = (params) => { const getCellDoubleClicked = (params) => {
if (managementState?.createSaleStoreId === 'T01') { if (managementState?.createSaleStoreId === 'T01') {
if (session?.storeId !== 'T01') { if (session?.storeId !== 'T01') {
//T01 ID .
if(session?.storeId !== managementState?.saleStoreId){
return false return false
} }
}
} }
if (params?.column?.colId !== 'estimateDate') { if (params?.column?.colId !== 'estimateDate') {

View File

@ -39,8 +39,12 @@ export default function StuffSubHeader({ type }) {
if (isObjectNotEmpty(managementState)) { if (isObjectNotEmpty(managementState)) {
if (managementState?.createSaleStoreId === 'T01') { if (managementState?.createSaleStoreId === 'T01') {
if (session?.storeId !== 'T01') { if (session?.storeId !== 'T01') {
//T01 ID .
if(session?.storeId !== managementState?.saleStoreId){
setButtonStyle('none') setButtonStyle('none')
} }
}
} }
} }
} }

View File

@ -633,9 +633,7 @@ export function useCommonUtils() {
// 원본 roof의 자식 오브젝트들 찾기 (개구, 그림자, 도머 등) // 원본 roof의 자식 오브젝트들 찾기 (개구, 그림자, 도머 등)
const childObjectTypes = [BATCH_TYPE.OPENING, BATCH_TYPE.SHADOW, BATCH_TYPE.TRIANGLE_DORMER, BATCH_TYPE.PENTAGON_DORMER] const childObjectTypes = [BATCH_TYPE.OPENING, BATCH_TYPE.SHADOW, BATCH_TYPE.TRIANGLE_DORMER, BATCH_TYPE.PENTAGON_DORMER]
const childObjects = canvas.getObjects().filter( const childObjects = canvas.getObjects().filter((o) => o.parentId === obj.id && childObjectTypes.includes(o.name))
(o) => o.parentId === obj.id && childObjectTypes.includes(o.name)
)
// 원본 roof 중심점 계산 // 원본 roof 중심점 계산
const originalPoints = obj.getCurrentPoints() const originalPoints = obj.getCurrentPoints()
@ -669,7 +667,9 @@ export function useCommonUtils() {
y: p.y + offsetY, y: p.y + offsetY,
})) }))
clonedObj = new QPolygon(newPoints, { clonedObj = new QPolygon(
newPoints,
{
fill: obj.fill || 'transparent', fill: obj.fill || 'transparent',
stroke: obj.stroke || 'black', stroke: obj.stroke || 'black',
strokeWidth: obj.strokeWidth || 1, strokeWidth: obj.strokeWidth || 1,
@ -685,8 +685,10 @@ export function useCommonUtils() {
originY: 'center', originY: 'center',
pitch: obj.pitch, pitch: obj.pitch,
surfaceId: obj.surfaceId, surfaceId: obj.surfaceId,
sort: false, // sort: false,
}, canvas) },
canvas,
)
canvas.add(clonedObj) canvas.add(clonedObj)

View File

@ -179,7 +179,7 @@ export function useRoofFn() {
polygon.set('fill', null) polygon.set('fill', null)
polygon.set('fill', pattern) polygon.set('fill', pattern)
polygon.roofMaterial = roofMaterial polygon.roofMaterial = roofMaterial
setPolygonLinesActualSize(polygon) setPolygonLinesActualSize(polygon, true)
changeCorridorDimensionText() changeCorridorDimensionText()
polygon.canvas?.renderAll() polygon.canvas?.renderAll()
} catch (e) { } catch (e) {

View File

@ -1059,7 +1059,7 @@ export function useModule() {
} }
const isOutsideSurface = (module, moduleSetupSurface) => { const isOutsideSurface = (module, moduleSetupSurface) => {
return !checkModuleDisjointSurface(polygonToTurfPolygon(module, true), polygonToTurfPolygon(moduleSetupSurface, true)) return !checkModuleDisjointSurface(polygonToTurfPolygon(module, true), polygonToTurfPolygon(moduleSetupSurface, true), 0.5)
} }
const getRowModules = (target) => { const getRowModules = (target) => {

View File

@ -440,6 +440,10 @@ export function useCanvasSetting(executeEffect = true) {
}) })
setAddedRoofs(addRoofs) setAddedRoofs(addRoofs)
if (openPoint !== 'basicSettingSave') {
// canvasSetting은 현재 값을 유지하고 basicSetting만 업데이트
// 새로고침 시 canvasSetting이 바뀌는 문제 방지
if (!canvasSetting?.roofSizeSet) {
setCanvasSetting({ setCanvasSetting({
...basicSetting, ...basicSetting,
roofMaterials: addRoofs[0], roofMaterials: addRoofs[0],
@ -450,6 +454,8 @@ export function useCanvasSetting(executeEffect = true) {
selectedRoofMaterial: addRoofs.find((roof) => roof.selected), selectedRoofMaterial: addRoofs.find((roof) => roof.selected),
}) })
} }
}
}
}) })
} catch (error) { } catch (error) {
console.error('Data fetching error:', error) console.error('Data fetching error:', error)
@ -474,7 +480,8 @@ export function useCanvasSetting(executeEffect = true) {
/** /**
* 기본설정(PlacementShapeSetting) 저장 * 기본설정(PlacementShapeSetting) 저장
*/ */
const basicSettingSave = async (params) => { const basicSettingSave = async (params, options = {}) => {
const { skipSideEffects = false } = options
try { try {
const patternData = { const patternData = {
objectNo: correntObjectNo, objectNo: correntObjectNo,
@ -527,6 +534,7 @@ export function useCanvasSetting(executeEffect = true) {
setBasicSettings({ ...params }) setBasicSettings({ ...params })
}) })
if (!skipSideEffects) {
/** CanvasSetting Recoil 설정 - roofSizeSet을 문자열로 변환 */ /** CanvasSetting Recoil 설정 - roofSizeSet을 문자열로 변환 */
setCanvasSetting({ setCanvasSetting({
...basicSetting, ...basicSetting,
@ -534,6 +542,9 @@ export function useCanvasSetting(executeEffect = true) {
}) })
/** 메뉴 설정 */ /** 메뉴 설정 */
//setMenuByRoofSize(params.roofSizeSet)
}
//메뉴를 찾아가지 못하는 오류 발생으로 변경
setMenuByRoofSize(params.roofSizeSet) setMenuByRoofSize(params.roofSizeSet)
/** 배치면초기설정 조회 */ /** 배치면초기설정 조회 */
@ -559,12 +570,28 @@ export function useCanvasSetting(executeEffect = true) {
*/ */
const basicSettingCopySave = async (params) => { const basicSettingCopySave = async (params) => {
try { try {
const patternData = { // roofsData가 단일 항목인 경우, 모든 추가된 지붕재(addedRoofs)를 사용하여 다중 항목으로 확장
objectNo: correntObjectNo, let roofMaterialsList = []
if (params.roofsData && params.roofsData.length === 1) {
// 단일 항목인 경우 addedRoofs의 모든 항목을 사용
if (addedRoofs && addedRoofs.length > 0) {
roofMaterialsList = addedRoofs.map((roof, index) => ({
planNo: Number(params.planNo), planNo: Number(params.planNo),
roofSizeSet: Number(params.roofSizeSet), roofApply: roof.selected || index === 0, // 첫 번째 또는 선택된 항목
roofAngleSet: params.roofAngleSet, roofSeq: index,
roofMaterialsAddList: params.roofsData.map((item) => ({ roofMatlCd: roof.roofMatlCd,
roofWidth: roof.width || roof.roofWidth,
roofHeight: roof.length || roof.roofHeight,
roofHajebichi: roof.hajebichi || 0,
roofGap: roof.raft || roof.roofGap,
roofLayout: roof.layout || 'P',
roofPitch: roof.pitch || 0,
roofAngle: roof.angle || 0,
}))
} else {
// addedRoofs가 비어있을 경우 원래 단일 항목 사용
roofMaterialsList = params.roofsData.map((item) => ({
planNo: Number(item.planNo), planNo: Number(item.planNo),
roofApply: item.roofApply, roofApply: item.roofApply,
roofSeq: item.roofSeq, roofSeq: item.roofSeq,
@ -576,7 +603,31 @@ export function useCanvasSetting(executeEffect = true) {
roofLayout: item.roofLayout, roofLayout: item.roofLayout,
roofPitch: item.roofPitch, roofPitch: item.roofPitch,
roofAngle: item.roofAngle, roofAngle: item.roofAngle,
})), }))
}
} else {
// 다중 항목인 경우 기존 방식 사용
roofMaterialsList = 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,
}))
}
const patternData = {
objectNo: correntObjectNo,
planNo: Number(params.planNo),
roofSizeSet: Number(params.roofSizeSet),
roofAngleSet: params.roofAngleSet,
roofMaterialsAddList: roofMaterialsList,
} }
await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }).then((res) => { await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }).then((res) => {

View File

@ -1573,13 +1573,13 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
currentObject.fire('modified') currentObject.fire('modified')
currentObject.fire('polygonMoved') currentObject.fire('polygonMoved')
// 화살표와 선 다시 그리기 // 화살표와 선 다시 그리기
setPolygonLinesActualSize(currentObject, true)
drawDirectionArrow(currentObject) drawDirectionArrow(currentObject)
setTimeout(() => { setTimeout(() => {
setPolygonLinesActualSize(currentObject)
changeSurfaceLineType(currentObject) changeSurfaceLineType(currentObject)
currentObject.dirty = true currentObject.dirty = true
currentObject.setCoords() currentObject.setCoords()
canvas.requestRenderAll() canvas.renderAll()
setCurrentObject(currentObject) setCurrentObject(currentObject)
}, 500) }, 500)
} }

View File

@ -76,7 +76,7 @@
"common.setting.rollback": "前に戻る", "common.setting.rollback": "前に戻る",
"modal.cover.outline.remove": "外壁の取り外し", "modal.cover.outline.remove": "外壁の取り外し",
"modal.cover.outline.select.move": "外壁選択の移動", "modal.cover.outline.select.move": "外壁選択の移動",
"plan.menu.placement.surface": "実測値入力", "plan.menu.placement.surface": "配置面",
"plan.menu.placement.surface.slope.setting": "傾斜設定", "plan.menu.placement.surface.slope.setting": "傾斜設定",
"plan.menu.placement.surface.drawing": "配置面の描画", "plan.menu.placement.surface.drawing": "配置面の描画",
"modal.placement.surface.drawing.straight.line": "直線", "modal.placement.surface.drawing.straight.line": "直線",

View File

@ -470,7 +470,9 @@ export const skeletonBuilder = (roofId, canvas, textMode) => {
//마루이동 //마루이동
if (moveFlowLine !== 0 || moveUpDown !== 0) { if (moveFlowLine !== 0 || moveUpDown !== 0) {
roofLineContactPoints = movingLineFromSkeleton(roofId, canvas) const movedPoints = movingLineFromSkeleton(roofId, canvas)
roofLineContactPoints = movedPoints
changRoofLinePoints = movedPoints
} }
// changRoofLinePoints 좌표를 roof.skeletonPoints에 저장 (원본 roof.points는 유지) // changRoofLinePoints 좌표를 roof.skeletonPoints에 저장 (원본 roof.points는 유지)