import { useContext, useEffect, useState } from 'react' import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil' import { adsorptionPointModeState, adsorptionRangeState, canvasSettingState, canvasState, currentMenuState, dotLineGridSettingState, planSizeSettingState, } from '@/store/canvasAtom' import { globalLocaleStore } from '@/store/localeAtom' import { useMessage } from '@/hooks/useMessage' import { useAxios } from '@/hooks/useAxios' import { useSwal } from '@/hooks/useSwal' import { addedRoofsState, basicSettingState, correntObjectNoState, corridorDimensionSelector, roofMaterialsAtom, selectedRoofMaterialSelector, settingModalFirstOptionsState, settingModalGridOptionsState, settingModalSecondOptionsState, } from '@/store/settingAtom' import { MENU, POLYGON_TYPE } from '@/common/common' import { globalFontAtom } from '@/store/fontAtom' import { dimensionLineSettingsState } from '@/store/commonUtilsAtom' import { gridColorState } from '@/store/gridAtom' import { useColor } from 'react-color-palette' import { useMasterController } from '@/hooks/common/useMasterController' import PlacementShapeSetting, { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting' import { useCanvasMenu } from '../common/useCanvasMenu' import { usePopup } from '../usePopup' import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider' import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions' import { useCommonCode } from '@/hooks/common/useCommonCode' import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController' import { v4 as uuidv4 } from 'uuid' import { useEvent } from '@/hooks/useEvent' import { logger } from '@/util/logger' import { useText } from '@/hooks/useText' import { usePolygon } from '@/hooks/usePolygon' const defaultDotLineGridSetting = { INTERVAL: { type: 2 /* 1: 가로,세로 간격 수동, 2: 비율 간격 */, ratioInterval: 910, verticalInterval: 910, horizontalInterval: 910, dimension: 1 /* 치수 */, }, DOT: false, LINE: false, } // hook 추가 시 executeEffect를 인자로 받고 false일 경우 useEffect를 실행하지 않는다. default true // 아래 hook에 추가 된 함수만 사용하고 싶을 경우 false로 인자 전달 export function useCanvasSetting(executeEffect = true) { const canvas = useRecoilValue(canvasState) /** canvas가 null이 아닐 때에만 getObjects 호출 */ const canvasObjects = canvas ? canvas.getObjects() : [] const [correntObjectNo, setCorrentObjectNo] = useRecoilState(correntObjectNoState) const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState) const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState) const resetSettingModalFirstOptions = useResetRecoilState(settingModalFirstOptionsState) const resetSettingModalSecondOptions = useResetRecoilState(settingModalSecondOptionsState) const [selectedFont, setSelectedFont] = useState() const [selectedFontWeight, setSelectedFontWeight] = useState() const [selectedFontSize, setSelectedFontSize] = useState() const [selectedFontColor, setSelectedFontColor] = useState() const [globalFont, setGlobalFont] = useRecoilState(globalFontAtom) const resetGlobalFont = useResetRecoilState(globalFontAtom) const [adsorptionPointMode, setAdsorptionPointMode] = useRecoilState(adsorptionPointModeState) const [adsorptionRange, setAdsorptionRange] = useRecoilState(adsorptionRangeState) const [planSizeSettingMode, setPlanSizeSettingMode] = useRecoilState(planSizeSettingState) const resetPlanSizeSettingMode = useResetRecoilState(planSizeSettingState) const [dimensionLineSettings, setDimensionLineSettings] = useRecoilState(dimensionLineSettingsState) const resetDimensionLineSettings = useResetRecoilState(dimensionLineSettingsState) const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState) const [dotLineGridSetting, setDotLineGridSettingState] = useRecoilState(dotLineGridSettingState) const resetDotLineGridSetting = useResetRecoilState(dotLineGridSettingState) const [currentSetting, setCurrentSetting] = useState( JSON.stringify(dotLineGridSetting) === JSON.stringify(defaultDotLineGridSetting) ? { ...defaultDotLineGridSetting } : { ...dotLineGridSetting }, ) const [gridColor, setGridColor] = useRecoilState(gridColorState) const [color, setColor] = useColor(gridColor ?? '#FF0000') const { selectedMenu, setSelectedMenu } = useCanvasMenu() const { initEvent } = useEvent() const [settingsData, setSettingsData] = useState({ ...settingModalFirstOptions, ...settingModalSecondOptions, ...globalFont, ...dotLineGridSetting, ...planSizeSettingMode, ...dimensionLineSettings, ...color, }) const [settingsDataSave, setSettingsDataSave] = useState() const { option1, option2, dimensionDisplay } = settingModalFirstOptions const { option4 } = settingModalSecondOptions const corridorDimension = useRecoilValue(corridorDimensionSelector) const globalLocaleState = useRecoilValue(globalLocaleStore) const { get, post } = useAxios(globalLocaleState) const { getMessage } = useMessage() const { swalFire } = useSwal() const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) const { getRoofMaterialList, getModuleTypeItemList } = useMasterController() const [roofMaterials, setRoofMaterials] = useRecoilState(roofMaterialsAtom) const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState) const setCurrentMenu = useSetRecoilState(currentMenuState) const resetModuleSelectionData = useResetRecoilState(moduleSelectionDataState) /* 다음으로 넘어가는 최종 데이터 */ const resetSelectedModules = useResetRecoilState(selectedModuleState) /* 선택된 모듈 */ const { trigger: orientationTrigger } = useCanvasPopupStatusController(1) const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2) const [raftCodes, setRaftCodes] = useState([]) /* 서까래 정보 */ const { findCommonCode } = useCommonCode() const [currentRoof, setCurrentRoof] = useState(null) /* 현재 선택된 지붕재 정보 */ const { addPopup } = usePopup() const [popupId, setPopupId] = useState(uuidv4()) const { changeCorridorDimensionText } = useText() const { setPolygonLinesActualSize } = usePolygon() const SelectOptions = [ { id: 1, name: getMessage('modal.canvas.setting.grid.dot.line.setting.line.origin'), value: 1 }, { id: 2, name: '1/2', value: 1 / 2 }, { id: 3, name: '1/4', value: 1 / 4 }, { id: 4, name: '1/10', value: 1 / 10 }, ] const selectedRoofMaterial = useRecoilValue(selectedRoofMaterialSelector) // 선택된 지붕재 정보 const { floorPlanState } = useContext(FloorPlanContext) // 플랜 상태 const { closePopup, closeAll } = usePopup() // 팝업 닫기 useEffect(() => { if (!executeEffect) { return } /** 초 1회만 실행하도록 처리 */ addRoofMaterials() }, [executeEffect]) /** * 지붕재 초기세팅 */ const addRoofMaterials = async () => { if (roofMaterials.length !== 0) { return roofMaterials } const { data } = await getRoofMaterialList() const roofLists = data.map((item, idx) => ({ ...item, id: item.roofMatlCd, name: item.roofMatlNm, selected: idx === 0, index: idx, nameJp: item.roofMatlNmJp, length: item.lenBase && parseInt(item.lenBase), width: item.widBase && parseInt(item.widBase), raft: item.raftBase && parseInt(item.raftBase), layout: ['ROOF_ID_SLATE', 'ROOF_ID_SINGLE'].includes(item.roofMatlCd) ? ROOF_MATERIAL_LAYOUT.STAIRS : ROOF_MATERIAL_LAYOUT.PARALLEL, hajebichi: item.roofPchBase && parseInt(item.roofPchBase), pitch: item.pitch ? parseInt(item.pitch) : 4, angle: item.angle ? parseInt(item.angle) : 21.8, })) setRoofMaterials(roofLists) return roofLists } useEffect(() => { if (!executeEffect) { return } if (addedRoofs.length > 0 && addedRoofs[0].planNo === basicSetting.planNo) { const raftCodeList = findCommonCode('203800') setRaftCodes(raftCodeList) setCurrentRoof({ ...addedRoofs[0], planNo: addedRoofs[0].planNo, roofSizeSet: String(basicSetting.roofSizeSet), roofAngleSet: basicSetting.roofAngleSet, }) } }, [addedRoofs]) /*useEffect(() => { if (!executeEffect) { return } if (roofMaterials.length === 0) { return } const selectedRoofMaterial = roofMaterials[0] if (addedRoofs.length === 0) { const newAddedRoofs = [] newAddedRoofs.push({ ...selectedRoofMaterial, selected: true, index: 0 }) setAddedRoofs(newAddedRoofs) } setBasicSettings({ ...basicSetting, selectedRoofMaterial: selectedRoofMaterial }) }, [roofMaterials])*/ useEffect(() => { if (!canvas) { return } if (!executeEffect) { return } const roofs = canvasObjects.filter((obj) => obj.name === POLYGON_TYPE.ROOF) if (roofs.length > 0) { roofs.forEach((roof) => { setPolygonLinesActualSize(roof) }) changeCorridorDimensionText() } }, [corridorDimension]) useEffect(() => { if (!executeEffect) { return } if (settingsDataSave !== undefined) onClickOption2() }, [settingsData]) const getFonts = (itemValue) => { if (!itemValue) return { id: 1, name: 'MS PGothic', value: 'MS PGothic' } const data = [ { id: 1, name: 'MS PGothic', value: 'MS PGothic' }, { id: 2, name: '@Yu Gothic', value: '@Yu Gothic' }, { id: 3, name: 'Yu Gothic', value: 'Yu Gothic' }, { id: 4, name: '@Yu Gothic UI', value: '@Yu Gothic UI' }, { id: 5, name: 'Yu Gothic UI', value: 'Yu Gothic UI' }, ].filter((font) => font.value === itemValue) if (data.length !== 0) { return data[0] } else { return { id: 1, name: 'MS PGothic', value: 'MS PGothic' } } } const getFontSizes = (itemValue) => { if (!itemValue) return { id: 16, name: 16, value: 16 } const data = [ ...Array.from({ length: 4 }).map((_, index) => { return { id: index + 8, name: index + 8, value: index + 8 } }), ...Array.from({ length: 9 }).map((_, index) => { return { id: (index + 6) * 2, name: (index + 6) * 2, value: (index + 6) * 2 } }), { id: 36, name: 36, value: 36 }, { id: 48, name: 48, value: 48 }, { id: 72, name: 72, value: 72 }, ].filter((fontSize) => fontSize.value === itemValue) if (data.length !== 0) { return data[0] } else { return { id: 16, name: 16, value: 16 } } } const getFontStyles = (itemValue) => { if (!itemValue) return { id: 'normal', name: getMessage('font.style.normal'), value: 'normal' } const data = [ { id: 'normal', name: getMessage('font.style.normal'), value: 'normal' }, { id: 'italic', name: getMessage('font.style.italic'), value: 'italic' }, { id: 'bold', name: getMessage('font.style.bold'), value: 'bold' }, { id: 'boldAndItalic', name: getMessage('font.style.bold.italic'), value: 'boldAndItalic' }, ].filter((fontStyle) => fontStyle.value === itemValue) if (data.length !== 0) { return data[0] } else { return { id: 'normal', name: getMessage('font.style.normal'), value: 'normal' } } } const getFontColors = (itemValue) => { if (!itemValue) return { id: 'black', name: getMessage('color.black'), value: 'black' } const data = [ { id: 'black', name: getMessage('color.black'), value: 'black' }, { id: 'red', name: getMessage('color.red'), value: 'red' }, { id: 'blue', name: getMessage('color.blue'), value: 'blue' }, { id: 'gray', name: getMessage('color.gray'), value: 'gray' }, { id: 'yellow', name: getMessage('color.yellow'), value: 'yellow' }, { id: 'green', name: getMessage('color.green'), value: 'green' }, { id: 'pink', name: getMessage('color.pink'), value: 'pink' }, { id: 'gold', name: getMessage('color.gold'), value: 'gold' }, { id: 'darkblue', name: getMessage('color.darkblue'), value: 'darkblue' }, ].filter((fontColor) => fontColor.value === itemValue) if (data.length !== 0) { return data[0] } else { return { id: 'black', name: getMessage('color.black'), value: 'black' } } } /** * 기본설정(PlacementShapeSetting) 조회 및 초기화 */ const fetchBasicSettings = async (planNo, openPoint) => { // 지붕재 데이터가 없으면 먼저 로드 let materials = roofMaterials if (!materials || materials.length === 0) { logger.log('Waiting for roofMaterials to be loaded...') materials = await addRoofMaterials() logger.log('roofMaterials loaded:', materials) } try { await get({ url: `/api/canvas-management/canvas-basic-settings/by-object/${correntObjectNo}/${planNo}`, }).then((res) => { let roofsRow = {} let roofsArray = {} if (res.length > 0) { roofsRow = res.map((item) => { return { planNo: item.planNo, roofSizeSet: String(item.roofSizeSet), roofAngleSet: item.roofAngleSet, } }) roofsArray = res.map((item) => { return { planNo: 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, } }) /* 데이터 존재 시 화면 닫기(메뉴/저장 클릭 시 제외) */ if (openPoint !== 'canvasMenus' && openPoint !== 'basicSettingSave') { //closePopup(popupId) closeAll() } } else { roofsRow = [ { planNo: planNo, roofSizeSet: '1', roofAngleSet: 'slope', }, ] roofsArray = [ { planNo: planNo, roofApply: true, roofSeq: 0, roofMatlCd: 'ROOF_ID_WA_53A', roofWidth: 265, roofHeight: 235, roofHajebichi: 0, roofGap: 'HEI_455', roofLayout: 'P', roofPitch: 4, roofAngle: 21.8, }, ] /** 메뉴에서 배치면 초기설정 클릭 시 실행하지 않음 */ if (openPoint === null) { /** 배치면 초기설정 미저장 상태이면 화면 열기 */ const placementInitialProps = { id: popupId, pos: { x: 50, y: 180, }, planNo: planNo, openPoint: 'useCanvasSetting', } addPopup(popupId, 1, ) } } /** 데이터 설정 */ const addRoofs = [] for (let i = 0; i < roofsArray.length; i++) { materials.map((material) => { if (material.roofMatlCd === roofsArray[i].roofMatlCd) { addRoofs.push({ ...material, selected: roofsArray[i].roofApply, index: i, width: roofsArray[i].roofWidth, length: roofsArray[i].roofHeight, hajebichi: roofsArray[i].roofHajebichi, raft: roofsArray[i].roofGap, layout: roofsArray[i].roofLayout, planNo: roofsRow[i].planNo, roofSizeSet: roofsRow[i].roofSizeSet, roofAngleSet: roofsRow[i].roofAngleSet, pitch: roofsArray[i].roofPitch, angle: roofsArray[i].roofAngle, }) } }) } if (addRoofs.length > 0) { setBasicSettings((prev) => { return { ...basicSetting, roofMaterials: addRoofs[0], planNo: roofsRow[0].planNo, roofSizeSet: roofsRow[0].roofSizeSet, roofAngleSet: roofsRow[0].roofAngleSet, roofsData: roofsArray, selectedRoofMaterial: addRoofs.find((roof) => roof.selected), } }) setAddedRoofs(addRoofs) 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 }) } /** * 저장/복사저장 시 지붕 크기에 따른 메뉴 설정 */ const setMenuByRoofSize = (roofSizeSet) => { if (['2', '3'].includes(String(roofSizeSet))) { setSelectedMenu('surface') setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING) } else { setSelectedMenu('outline') setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE) } } /** * 기본설정(PlacementShapeSetting) 저장 */ const basicSettingSave = async (params) => { try { const patternData = { objectNo: correntObjectNo, planNo: Number(params.planNo), roofSizeSet: Number(params.roofSizeSet), roofAngleSet: params.roofAngleSet, roofMaterialsAddList: [ { planNo: Number(params.planNo), roofApply: true, roofSeq: 0, roofMatlCd: params.roofsData.roofMatlCd === null || params.roofsData.roofMatlCd === undefined ? 'ROOF_ID_WA_53A' : params.roofsData.roofMatlCd, roofWidth: params.selectedRoofMaterial.width === null || params.selectedRoofMaterial.width === undefined ? !params.selectedRoofMaterial.widBase ? 0 : Number(params.roofsData.widBase) : Number(params.selectedRoofMaterial.width), roofHeight: params.selectedRoofMaterial.height === null || params.selectedRoofMaterial.height === undefined ? !params.selectedRoofMaterial.lenBase ? 0 : Number(params.selectedRoofMaterial.lenBase) : Number(params.roofsData.roofHeight), roofHajebichi: params.selectedRoofMaterial.hajebichi === null || params.selectedRoofMaterial.hajebichi === undefined ? 0 : Number(params.selectedRoofMaterial.hajebichi), roofGap: params.selectedRoofMaterial.raft === null || params.selectedRoofMaterial.raft === undefined ? params.selectedRoofMaterial.raftBaseCd : params.roofsData.roofGap, roofLayout: params.roofsData.roofLayout === null || params.roofsData.roofLayout === undefined ? 'P' : params.roofsData.roofLayout, roofPitch: params.roofsData.roofPitch === null || params.roofsData.roofPitch === undefined || params.roofsData.roofPitch === '' ? 0 : params.roofsData.roofPitch, roofAngle: params.roofsData.roofAngle === null || params.roofsData.roofAngle === undefined || params.roofsData.roofAngle === '' ? 0 : params.roofsData.roofAngle, }, ], } await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }).then((res) => { swalFire({ text: getMessage(res.returnMessage) }) /** BasicSettings Recoil 설정 */ setBasicSettings({ ...params }) }) /** CanvasSetting Recoil 설정 - roofSizeSet을 문자열로 변환 */ setCanvasSetting({ ...basicSetting, roofSizeSet: String(params.roofSizeSet), }) /** 메뉴 설정 */ setMenuByRoofSize(params.roofSizeSet) /** 배치면초기설정 조회 */ fetchBasicSettings(params.planNo, 'basicSettingSave') /** 모듈 선택 데이터 초기화 */ resetModuleSelectionData() //1번 초기화 orientationTrigger({ compasDeg: 0, common: {}, module: {} }) //2번 초기화 moduleSelectedDataTrigger({ roofConstructions: [] }) const isModuleExist = canvas.getObjects().some((obj) => obj.name === POLYGON_TYPE.MODULE) if (!isModuleExist) { resetSelectedModules() } } catch (error) { swalFire({ text: error.message, icon: 'error' }) } } /** * 기본설정(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), }) /** 메뉴 설정 */ setMenuByRoofSize(params.roofSizeSet) /** 배치면초기설정 조회 */ fetchBasicSettings(Number(params.planNo), 'basicSettingSave') /** 모듈 선택 데이터 초기화 */ 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 조회 및 초기화 */ const fetchSettings = async () => { try { initEvent() const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${correntObjectNo}` }) if (Object.keys(res).length > 0) { const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] })) const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] })) const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item })) const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] })) const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({ ...item })) /** 흡착점 ON/OFF */ setAdsorptionPointMode(res.adsorpPoint) /** 치수선 설정 */ setDimensionLineSettings({ ...dimensionLineSettings, pixel: res.originPixel, color: res.originColor }) /** 도면크기 설정 */ setPlanSizeSettingMode({ ...planSizeSettingMode, originHorizon: res.originHorizon, originVertical: res.originVertical, }) canvas.setWidth(res.originHorizon) canvas.setHeight(res.originVertical) canvas.renderAll() /** 데이터 설정 */ setSettingModalFirstOptions({ ...settingModalFirstOptions, option1: optionData1, option2: optionData2, dimensionDisplay: optionData5, }) setSettingModalSecondOptions({ ...settingModalSecondOptions, option3: optionData3, option4: optionData4, }) const fontPatternData = { commonText: { /** 문자 글꼴 조회 데이터 */ fontFamily: getFonts(res.wordFont), fontWeight: getFontStyles(res.wordFontStyle), fontSize: getFontSizes(res.wordFontSize), fontColor: getFontColors(res.wordFontColor), }, flowText: { /** 흐름방향 글꼴 조회 데이터 */ fontFamily: getFonts(res.flowFont), fontWeight: getFontStyles(res.flowFontStyle), fontSize: getFontSizes(res.flowFontSize), fontColor: getFontColors(res.flowFontColor), }, dimensionLineText: { /** 치수 글꼴 조회 데이터 */ fontFamily: getFonts(res.dimensioFont), fontWeight: getFontStyles(res.dimensioFontStyle), fontSize: getFontSizes(res.dimensioFontSize), fontColor: getFontColors(res.dimensioFontColor), }, circuitNumberText: { /** 회로번호 글꼴 조회 데이터 */ fontFamily: getFonts(res.circuitNumFont), fontWeight: getFontStyles(res.circuitNumFontStyle), fontSize: getFontSizes(res.circuitNumFontSize), fontColor: getFontColors(res.circuitNumFontColor), }, lengthText: { /** 치수선 글꼴 조회 데이터 */ fontFamily: getFonts(res.lengthFont), fontWeight: getFontStyles(res.lengthFontStyle), fontSize: getFontSizes(res.lengthFontSize), fontColor: getFontColors(res.lengthFontColor), }, } /** 조회된 글꼴 데이터 set */ setGlobalFont(fontPatternData) /** 점/선 그리드 */ const patternData = { INTERVAL: { type: res.gridType, horizontalInterval: res.gridHorizon * 10, verticalInterval: res.gridVertical * 10, ratioInterval: res.gridRatio * 10, dimension: res.gridDimen, }, DOT: res.dotGridDisplay, LINE: res.lineGridDisplay, } setDotLineGridSettingState(patternData) /** 그리드 색 설정 */ setGridColor(res.gridColor) } else { /** 조회된 글꼴 데이터가 없는 경우 (데이터 초기화) */ /** 흡착점 ON/OFF */ setAdsorptionPointMode(true) /** 치수선 설정 */ resetDimensionLineSettings() /** 도면크기 설정 */ resetPlanSizeSettingMode() /** 데이터 설정 */ resetSettingModalFirstOptions() resetSettingModalSecondOptions() /** 데이터 초기화 */ resetGlobalFont() /** 점/선 그리드 */ setDotLineGridSettingState({ ...defaultDotLineGridSetting }) /** 그리드 색 설정 */ setGridColor('#FF0000') } frontSettings() } catch (error) { console.error('Data fetching error:', error) } } /** * CanvasSetting 옵션 클릭 후 저장 */ const onClickOption2 = async () => { /** 서버에 전송할 데이터 */ const dataToSend = { firstOption1: option1.map((item) => ({ column: item.column, selected: item.selected, })), firstOption2: option2.map((item) => ({ column: item.column, selected: item.selected, })), firstOption3: dimensionDisplay.map((item) => ({ column: item.column, selected: item.selected, })), secondOption2: option4.map((item) => ({ column: item.column, selected: item.selected, range: item.range, })), } const patternData = { /** 견적서 번호 */ objectNo: correntObjectNo, /** 디스플레이 설정(다중) */ allocDisplay: dataToSend.firstOption1[0].selected, outlineDisplay: dataToSend.firstOption1[1].selected, gridDisplay: dataToSend.firstOption1[2].selected, lineDisplay: dataToSend.firstOption1[3].selected, wordDisplay: dataToSend.firstOption1[4].selected, circuitNumDisplay: dataToSend.firstOption1[5].selected, flowDisplay: dataToSend.firstOption1[6].selected, trestleDisplay: dataToSend.firstOption1[7].selected, imageDisplay: dataToSend.firstOption1[8].selected, totalDisplay: dataToSend.firstOption1[9].selected, /** 차수 표시(단 건) */ corridorDimension: dataToSend.firstOption3[0].selected, realDimension: dataToSend.firstOption3[1].selected, noneDimension: dataToSend.firstOption3[2].selected, /** 화면 표시(단 건) */ onlyBorder: dataToSend.firstOption2[0].selected, lineHatch: dataToSend.firstOption2[1].selected, allPainted: dataToSend.firstOption2[2].selected, /** 흡착범위 설정(단 건) */ adsorpRangeSmall: dataToSend.secondOption2[0].selected, adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected, adsorpRangeMedium: dataToSend.secondOption2[2].selected, adsorpRangeLarge: dataToSend.secondOption2[3].selected, /** 흡착점 ON/OFF */ adsorpPoint: adsorptionPointMode, //??: adsorptionRange, 사용여부 확인 필요 /** 문자 글꼴 설정 */ wordFont: globalFont.commonText.fontFamily?.value ?? 'MS PGothic', wordFontStyle: globalFont.commonText.fontWeight?.value ?? 'normal', wordFontSize: globalFont.commonText.fontSize?.value ?? 16, wordFontColor: globalFont.commonText.fontColor?.value ?? 'black', /** 흐름방향 글꼴 설정 */ flowFont: globalFont.flowText.fontFamily?.value ?? 'MS PGothic', flowFontStyle: globalFont.flowText.fontWeight?.value ?? 'normal', flowFontSize: globalFont.flowText.fontSize?.value ?? 16, flowFontColor: globalFont.flowText.fontColor?.value ?? 'black', /** 치수 글꼴 설정 */ dimensioFont: globalFont.dimensionLineText.fontFamily?.value ?? 'MS PGothic', dimensioFontStyle: globalFont.dimensionLineText.fontWeight?.value ?? 'normal', dimensioFontSize: globalFont.dimensionLineText.fontSize?.value ?? 16, dimensioFontColor: globalFont.dimensionLineText.fontColor?.value ?? 'black', /** 회로번호 글꼴 설정 */ circuitNumFont: globalFont.circuitNumberText.fontFamily?.value ?? 'MS PGothic', circuitNumFontStyle: globalFont.circuitNumberText.fontWeight?.value ?? 'normal', circuitNumFontSize: globalFont.circuitNumberText.fontSize?.value ?? 16, circuitNumFontColor: globalFont.circuitNumberText.fontColor?.value ?? 'black', /** 치수선 글꼴 설정 */ lengthFont: globalFont.lengthText.fontFamily?.value ?? 'MS PGothic', lengthFontStyle: globalFont.lengthText.fontWeight?.value ?? 'normal', lengthFontSize: globalFont.lengthText.fontSize?.value ?? 16, lengthFontColor: globalFont.lengthText.fontColor?.value ?? 'black', /** 치수선 설정 */ originPixel: dimensionLineSettings.pixel, originColor: dimensionLineSettings.color, /** 도면크기 설정 */ originHorizon: planSizeSettingMode.originHorizon, originVertical: planSizeSettingMode.originVertical, /** 점/선 그리드 */ dotGridDisplay: dotLineGridSetting.DOT, lineGridDisplay: dotLineGridSetting.LINE, gridType: dotLineGridSetting.INTERVAL.type, gridHorizon: dotLineGridSetting.INTERVAL.horizontalInterval / 10, gridVertical: dotLineGridSetting.INTERVAL.verticalInterval / 10, gridRatio: dotLineGridSetting.INTERVAL.ratioInterval / 10, gridDimen: dotLineGridSetting.INTERVAL.dimension, /** 그리드 색 설정 */ gridColor: gridColor, } logger.log('patternData ', patternData) /** * 저장 API 호출 */ await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }) .then((res) => { //swalFire({ text: getMessage(res.returnMessage) }) /** Canvas 디스플레이 설정 시 해당 옵션 적용 */ frontSettings() /** 저장 후 재조회 */ fetchSettings() }) .catch((error) => { //swalFire({ text: getMessage(res.returnMessage), icon: 'error' }) swalFire({ text: error.message, icon: 'error' }) }) //setAdsorptionRange(item.range) } /** * Canvas 디스플레이 설정 시 해당 옵션 적용 */ const frontSettings = async () => { const option1 = settingModalFirstOptions.option1 /** * 'allocDisplay' 할당 표시 * 'outlineDisplay' 외벽선 표시 'outerLine', POLYGON_TYPE.WALL * 'gridDisplay' 그리드 표시 'lindGrid', 'dotGrid' * 'lineDisplay' 지붕선 표시 'roof', POLYGON_TYPE.ROOF * 'wordDisplay' 문자 표시 * 'circuitNumDisplay' 회로번호 표시 * 'flowDisplay' 흐름방향 표시 'arrow', 'flowText' * 'trestleDisplay' 가대 표시 * 'imageDisplay' 이미지 표시 * 'totalDisplay' 집계표 표시 */ /** * 옵션명 optionName * 옵션상태 optionSelected */ let optionName let optionSelected for (let i = 0; i < option1.length; i++) { switch (option1[i].column) { case 'allocDisplay': optionName = [] break case 'outlineDisplay': optionName = ['outerLine', POLYGON_TYPE.WALL] break case 'gridDisplay': optionName = ['lindGrid', 'dotGrid', 'tempGrid'] break case 'lineDisplay': optionName = ['roof', POLYGON_TYPE.ROOF] break case 'wordDisplay': optionName = ['commonText'] break case 'circuitNumDisplay': optionName = ['circuitNumber'] break case 'flowDisplay': optionName = ['arrow', 'flowText'] break case 'trestleDisplay': optionName = ['rack', 'smartRack', 'bracket', 'eaveBar', 'halfEaveBar'] break case 'imageDisplay': optionName = ['backGroundImage'] break case 'totalDisplay': /** 작업할 필요 없음 */ optionName = [] break } /** 표시 선택 상태(true/false)*/ optionSelected = option1[i].selected canvasObjects .filter((obj) => optionName.includes(obj.name)) .forEach((obj) => { obj.set({ visible: optionSelected }) }) canvas?.renderAll() } } return { canvas, correntObjectNo, settingModalFirstOptions, setSettingModalFirstOptions, settingModalSecondOptions, setSettingModalSecondOptions, adsorptionPointMode, setAdsorptionPointMode, adsorptionRange, setAdsorptionRange, fetchSettings, fetchBasicSettings, basicSettingCopySave, frontSettings, globalFont, setGlobalFont, selectedFont, setSelectedFont, selectedFontWeight, setSelectedFontWeight, selectedFontSize, setSelectedFontSize, selectedFontColor, setSelectedFontColor, dimensionLineSettings, setDimensionLineSettings, planSizeSettingMode, setPlanSizeSettingMode, SelectOptions, currentSetting, setCurrentSetting, dotLineGridSettingState, setDotLineGridSettingState, resetDotLineGridSetting, setSettingModalGridOptions, gridColor, setGridColor, color, setColor, canvasSetting, setCanvasSetting, basicSetting, setBasicSettings, basicSettingSave, settingsData, setSettingsData, settingsDataSave, setSettingsDataSave, addedRoofs, setAddedRoofs, } }