Merge branch 'dev' into feature/yj-layoutSetup
# Conflicts: # src/locales/ja.json
This commit is contained in:
commit
9285caf422
@ -2,7 +2,7 @@ module.exports = {
|
|||||||
apps: [
|
apps: [
|
||||||
{
|
{
|
||||||
name: 'qcast-front-production',
|
name: 'qcast-front-production',
|
||||||
script: 'npm run start',
|
script: 'npm run start:dev',
|
||||||
instance: 2,
|
instance: 2,
|
||||||
exec_mode: 'cluster',
|
exec_mode: 'cluster',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -6,29 +6,19 @@ import { contextMenuListState, contextMenuState } from '@/store/contextMenu'
|
|||||||
import { useTempGrid } from '@/hooks/useTempGrid'
|
import { useTempGrid } from '@/hooks/useTempGrid'
|
||||||
import { useContextMenu } from '@/hooks/useContextMenu'
|
import { useContextMenu } from '@/hooks/useContextMenu'
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
import { canvasState, currentObjectState } from '@/store/canvasAtom'
|
||||||
|
|
||||||
export default function QContextMenu(props) {
|
export default function QContextMenu(props) {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const { contextRef, canvasProps } = props
|
const { contextRef, canvasProps } = props
|
||||||
const [contextMenu, setContextMenu] = useRecoilState(contextMenuState)
|
const [contextMenu, setContextMenu] = useRecoilState(contextMenuState)
|
||||||
const contextMenuList = useRecoilValue(contextMenuListState)
|
const contextMenuList = useRecoilValue(contextMenuListState)
|
||||||
const activeObject = canvasProps?.getActiveObject() //액티브된 객체를 가져옴
|
const currentObject = useRecoilValue(currentObjectState)
|
||||||
const { tempGridMode, setTempGridMode } = useTempGrid()
|
const { tempGridMode, setTempGridMode } = useTempGrid()
|
||||||
const { handleKeyup } = useContextMenu()
|
const { handleKeyup } = useContextMenu()
|
||||||
const { addDocumentEventListener, removeDocumentEvent } = useEvent()
|
const { addDocumentEventListener, removeDocumentEvent } = useEvent()
|
||||||
// const { addDocumentEventListener, removeDocumentEvent } = useContext(EventContext)
|
// const { addDocumentEventListener, removeDocumentEvent } = useContext(EventContext)
|
||||||
|
|
||||||
let contextType = ''
|
|
||||||
|
|
||||||
if (activeObject) {
|
|
||||||
if (activeObject.initOptions && activeObject.initOptions.name) {
|
|
||||||
//이건 바뀔 가능성이 있음
|
|
||||||
if (activeObject.initOptions?.name?.indexOf('guide') > -1) {
|
|
||||||
contextType = 'surface' //면형상
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const getYPosition = (e) => {
|
const getYPosition = (e) => {
|
||||||
const contextLength = contextMenuList.reduce((acc, cur, index) => {
|
const contextLength = contextMenuList.reduce((acc, cur, index) => {
|
||||||
return acc + cur.length
|
return acc + cur.length
|
||||||
@ -36,11 +26,13 @@ export default function QContextMenu(props) {
|
|||||||
return e?.clientY - (contextLength * 25 + contextMenuList.length * 2 * 17)
|
return e?.clientY - (contextLength * 25 + contextMenuList.length * 2 * 17)
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
const handleContextMenu = (e) => {
|
||||||
if (!contextRef.current) return
|
// e.preventDefault() //기존 contextmenu 막고
|
||||||
|
|
||||||
|
if (currentObject) {
|
||||||
|
const isArray = currentObject.hasOwnProperty('arrayData')
|
||||||
|
if (isArray && currentObject.arrayData.length === 0) return
|
||||||
|
|
||||||
const handleContextMenu = (e) => {
|
|
||||||
e.preventDefault() //기존 contextmenu 막고
|
|
||||||
if (tempGridMode) return
|
if (tempGridMode) return
|
||||||
const position = {
|
const position = {
|
||||||
x: window.innerWidth / 2 < e.pageX ? e.pageX - 240 : e.pageX,
|
x: window.innerWidth / 2 < e.pageX ? e.pageX - 240 : e.pageX,
|
||||||
@ -48,21 +40,24 @@ export default function QContextMenu(props) {
|
|||||||
}
|
}
|
||||||
setContextMenu({ visible: true, ...position, currentMousePos: canvasProps.getPointer(e) })
|
setContextMenu({ visible: true, ...position, currentMousePos: canvasProps.getPointer(e) })
|
||||||
addDocumentEventListener('keyup', document, handleKeyup)
|
addDocumentEventListener('keyup', document, handleKeyup)
|
||||||
canvasProps?.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) //한번 노출 후 이벤트 삭제
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleClick = (e) => {
|
const handleClick = (e) => {
|
||||||
// e.preventDefault()
|
// e.preventDefault()
|
||||||
|
setContextMenu({ ...contextMenu, visible: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleOutsideClick = (e) => {
|
||||||
|
// e.preventDefault()
|
||||||
|
if (contextMenu.visible) {
|
||||||
setContextMenu({ ...contextMenu, visible: false })
|
setContextMenu({ ...contextMenu, visible: false })
|
||||||
|
removeDocumentEvent('keyup')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleOutsideClick = (e) => {
|
useEffect(() => {
|
||||||
// e.preventDefault()
|
if (!contextRef.current) return
|
||||||
if (contextMenu.visible) {
|
|
||||||
setContextMenu({ ...contextMenu, visible: false })
|
|
||||||
removeDocumentEvent('keyup')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
canvasProps?.upperCanvasEl.addEventListener('contextmenu', handleContextMenu)
|
canvasProps?.upperCanvasEl.addEventListener('contextmenu', handleContextMenu)
|
||||||
document.addEventListener('click', handleClick)
|
document.addEventListener('click', handleClick)
|
||||||
@ -72,43 +67,9 @@ export default function QContextMenu(props) {
|
|||||||
removeDocumentEvent('keyup')
|
removeDocumentEvent('keyup')
|
||||||
document.removeEventListener('click', handleClick)
|
document.removeEventListener('click', handleClick)
|
||||||
document.removeEventListener('click', handleOutsideClick)
|
document.removeEventListener('click', handleOutsideClick)
|
||||||
|
canvasProps?.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) //한번 노출 후 이벤트 삭제
|
||||||
}
|
}
|
||||||
}, [contextRef, contextMenuList])
|
}, [contextRef, contextMenuList, currentObject])
|
||||||
|
|
||||||
const handleObjectMove = () => {
|
|
||||||
activeObject.set({
|
|
||||||
lockMovementX: false, // X 축 이동 잠금
|
|
||||||
lockMovementY: false, // Y 축 이동 잠금
|
|
||||||
})
|
|
||||||
|
|
||||||
canvasProps?.on('object:modified', function (e) {
|
|
||||||
activeObject.set({
|
|
||||||
lockMovementX: true, // X 축 이동 잠금
|
|
||||||
lockMovementY: true, // Y 축 이동 잠금
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleObjectDelete = () => {
|
|
||||||
if (confirm('삭제하실거?')) {
|
|
||||||
canvasProps.remove(activeObject)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleObjectCopy = () => {
|
|
||||||
activeObject.clone((cloned) => {
|
|
||||||
cloned.set({
|
|
||||||
left: activeObject.left + activeObject.width + 20,
|
|
||||||
initOptions: { ...activeObject.initOptions },
|
|
||||||
lockMovementX: true, // X 축 이동 잠금
|
|
||||||
lockMovementY: true, // Y 축 이동 잠금
|
|
||||||
lockRotation: true, // 회전 잠금
|
|
||||||
lockScalingX: true, // X 축 크기 조정 잠금
|
|
||||||
lockScalingY: true, // Y 축 크기 조정 잠금
|
|
||||||
})
|
|
||||||
canvasProps?.add(cloned)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@ -387,6 +387,8 @@ export default function Estimate({}) {
|
|||||||
if (isNotEmptyArray(res?.data)) {
|
if (isNotEmptyArray(res?.data)) {
|
||||||
setStorePriceList(res.data)
|
setStorePriceList(res.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setItemChangeYn(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (estimateContextState.estimateType === 'YJSS') {
|
if (estimateContextState.estimateType === 'YJSS') {
|
||||||
@ -416,8 +418,6 @@ export default function Estimate({}) {
|
|||||||
handlePricing('UNIT_PRICE')
|
handlePricing('UNIT_PRICE')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setItemChangeYn(true)
|
|
||||||
}
|
}
|
||||||
}, [estimateContextState?.estimateType])
|
}, [estimateContextState?.estimateType])
|
||||||
|
|
||||||
|
|||||||
@ -119,10 +119,12 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
this.addLengthText()
|
this.addLengthText()
|
||||||
|
|
||||||
this.on('moving', () => {
|
this.on('moving', () => {
|
||||||
|
this.initLines()
|
||||||
this.addLengthText()
|
this.addLengthText()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.on('modified', (e) => {
|
this.on('modified', (e) => {
|
||||||
|
this.initLines()
|
||||||
this.addLengthText()
|
this.addLengthText()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -183,8 +185,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
|
|
||||||
this.lines = []
|
this.lines = []
|
||||||
|
|
||||||
this.points.forEach((point, i) => {
|
this.getCurrentPoints().forEach((point, i) => {
|
||||||
const nextPoint = this.points[(i + 1) % this.points.length]
|
const nextPoint = this.getCurrentPoints()[(i + 1) % this.points.length]
|
||||||
const line = new QLine([point.x, point.y, nextPoint.x, nextPoint.y], {
|
const line = new QLine([point.x, point.y, nextPoint.x, nextPoint.y], {
|
||||||
stroke: this.stroke,
|
stroke: this.stroke,
|
||||||
strokeWidth: this.strokeWidth,
|
strokeWidth: this.strokeWidth,
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
|
|||||||
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
import { compasDegAtom } from '@/store/orientationAtom'
|
import { compasDegAtom } from '@/store/orientationAtom'
|
||||||
|
import { hotkeyStore } from '@/store/hotkeyAtom'
|
||||||
|
|
||||||
export default function CanvasFrame() {
|
export default function CanvasFrame() {
|
||||||
const canvasRef = useRef(null)
|
const canvasRef = useRef(null)
|
||||||
@ -110,6 +111,38 @@ export default function CanvasFrame() {
|
|||||||
resetPcsCheckState()
|
resetPcsCheckState()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 캔버스가 있을 경우 핫키 이벤트 처리
|
||||||
|
* hotkeyStore에 핫키 이벤트 리스너 추가
|
||||||
|
*
|
||||||
|
* const hotkeys = [
|
||||||
|
{ key: 'c', fn: () => asdf() },
|
||||||
|
{ key: 'v', fn: () => qwer() },
|
||||||
|
]
|
||||||
|
setHotkeyStore(hotkeys)
|
||||||
|
*/
|
||||||
|
const hotkeyState = useRecoilValue(hotkeyStore)
|
||||||
|
const hotkeyHandlerRef = useRef(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
hotkeyHandlerRef.current = (e) => {
|
||||||
|
hotkeyState.forEach((hotkey) => {
|
||||||
|
if (e.key === hotkey.key) {
|
||||||
|
hotkey.fn()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('keyup', hotkeyHandlerRef.current)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (hotkeyHandlerRef.current) {
|
||||||
|
document.removeEventListener('keyup', hotkeyHandlerRef.current)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [hotkeyState])
|
||||||
|
/** 핫키 이벤트 처리 끝 */
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="canvas-frame">
|
<div className="canvas-frame">
|
||||||
<canvas ref={canvasRef} id="canvas" style={{ position: 'relative' }}></canvas>
|
<canvas ref={canvasRef} id="canvas" style={{ position: 'relative' }}></canvas>
|
||||||
|
|||||||
@ -634,7 +634,7 @@ export default function CanvasMenu(props) {
|
|||||||
onClick={() => setEstimatePopupOpen(true)}
|
onClick={() => setEstimatePopupOpen(true)}
|
||||||
>
|
>
|
||||||
<span className="ico ico01"></span>
|
<span className="ico ico01"></span>
|
||||||
<span className="name">{getMessage('plan.menu.estimate.docDown')}</span>
|
<span className="name">{getMessage('plan.menu.estimate.docDownload')}</span>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" style={{ display: saveButtonStyle }} className="btn-frame gray ico-flx" onClick={handleEstimateSubmit}>
|
<button type="button" style={{ display: saveButtonStyle }} className="btn-frame gray ico-flx" onClick={handleEstimateSubmit}>
|
||||||
<span className="ico ico02"></span>
|
<span className="ico ico02"></span>
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { useMessage } from '@/hooks/useMessage'
|
|||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
import { usePolygon } from '@/hooks/usePolygon'
|
import { usePolygon } from '@/hooks/usePolygon'
|
||||||
|
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
|
||||||
|
|
||||||
const FLOW_DIRECTION_TYPE = {
|
const FLOW_DIRECTION_TYPE = {
|
||||||
EIGHT_AZIMUTH: 'eightAzimuth',
|
EIGHT_AZIMUTH: 'eightAzimuth',
|
||||||
@ -19,6 +20,8 @@ export default function FlowDirectionSetting(props) {
|
|||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
|
const { changeSurfaceLineType } = useSurfaceShapeBatch({})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
canvas?.discardActiveObject()
|
canvas?.discardActiveObject()
|
||||||
@ -53,6 +56,7 @@ export default function FlowDirectionSetting(props) {
|
|||||||
})
|
})
|
||||||
drawDirectionArrow(roof)
|
drawDirectionArrow(roof)
|
||||||
canvas?.renderAll()
|
canvas?.renderAll()
|
||||||
|
changeSurfaceLineType(roof)
|
||||||
closePopup(id)
|
closePopup(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -462,24 +462,30 @@ export const useEstimateController = (planNo, flag) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setIsGlobalLoading(true)
|
setIsGlobalLoading(true)
|
||||||
await promisePost({ url: '/api/estimate/save-estimate-copy', data: params }).then((res) => {
|
await promisePost({ url: '/api/estimate/save-estimate-copy', data: params })
|
||||||
setIsGlobalLoading(false)
|
.then((res) => {
|
||||||
if (res.status === 201) {
|
|
||||||
if (isObjectNotEmpty(res.data)) {
|
|
||||||
let newObjectNo = res.data.objectNo
|
|
||||||
swalFire({
|
|
||||||
text: getMessage('estimate.detail.estimateCopyPopup.copy.alertMessage'),
|
|
||||||
type: 'alert',
|
|
||||||
confirmFn: () => {
|
|
||||||
setEstimateCopyPopupOpen(false) //팝업닫고
|
|
||||||
router.push(`/management/stuff/detail?objectNo=${newObjectNo.toString()}`, { scroll: false })
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setIsGlobalLoading(false)
|
setIsGlobalLoading(false)
|
||||||
}
|
if (res.status === 201) {
|
||||||
})
|
if (isObjectNotEmpty(res.data)) {
|
||||||
|
let newObjectNo = res.data.objectNo
|
||||||
|
swalFire({
|
||||||
|
text: getMessage('estimate.detail.estimateCopyPopup.copy.alertMessage'),
|
||||||
|
type: 'alert',
|
||||||
|
confirmFn: () => {
|
||||||
|
setEstimateCopyPopupOpen(false) //팝업닫고
|
||||||
|
router.push(`/management/stuff/detail?objectNo=${newObjectNo.toString()}`, { scroll: false })
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setIsGlobalLoading(false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.error('캔버스 복사 중 오류 발생')
|
||||||
|
swalFire({ text: getMessage('estimate.detail.estimateCopyPopup.copy.alertMessageError'), type: 'alert', icon: 'error' })
|
||||||
|
setIsGlobalLoading(false)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkLength = (value) => {
|
const checkLength = (value) => {
|
||||||
|
|||||||
@ -1,35 +0,0 @@
|
|||||||
import { useEffect, useState } from 'react'
|
|
||||||
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
|
||||||
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
|
||||||
import { useMasterController } from '@/hooks/common/useMasterController'
|
|
||||||
import { canvasSettingState, canvasState, currentCanvasPlanState, moduleSetupSurfaceState } from '@/store/canvasAtom'
|
|
||||||
import { POLYGON_TYPE, BATCH_TYPE } from '@/common/common'
|
|
||||||
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
|
||||||
import { roofDisplaySelector } from '@/store/settingAtom'
|
|
||||||
import offsetPolygon from '@/util/qpolygon-utils'
|
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
|
||||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
|
||||||
|
|
||||||
export function useModulePlace() {
|
|
||||||
const canvas = useRecoilValue(canvasState)
|
|
||||||
const moduleSelectionData = useRecoilValue(moduleSelectionDataState)
|
|
||||||
const [trestleDetailParams, setTrestleDetailParams] = useState([])
|
|
||||||
const [trestleDetailList, setTrestleDetailList] = useState([])
|
|
||||||
const selectedModules = useRecoilValue(selectedModuleState)
|
|
||||||
const { getTrestleDetailList } = useMasterController()
|
|
||||||
const canvasSetting = useRecoilValue(canvasSettingState)
|
|
||||||
const { setSurfaceShapePattern } = useRoofFn()
|
|
||||||
const roofDisplay = useRecoilValue(roofDisplaySelector)
|
|
||||||
const { addTargetMouseEventListener } = useEvent()
|
|
||||||
const setModuleSetupSurface = useSetRecoilState(moduleSetupSurfaceState)
|
|
||||||
const [saleStoreNorthFlg, setSaleStoreNorthFlg] = useState(false)
|
|
||||||
const { swalFire } = useSwal()
|
|
||||||
const { getMessage } = useMessage()
|
|
||||||
|
|
||||||
return {
|
|
||||||
selectedModules,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -261,6 +261,15 @@ export function useRoofAllocationSetting(id) {
|
|||||||
* 지붕재 삭제
|
* 지붕재 삭제
|
||||||
*/
|
*/
|
||||||
const onDeleteRoofMaterial = (idx) => {
|
const onDeleteRoofMaterial = (idx) => {
|
||||||
|
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
|
|
||||||
|
for (let i = 0; i < roofs.length; i++) {
|
||||||
|
if (roofs[i].roofMaterial.index === idx) {
|
||||||
|
swalFire({ type: 'alert', icon: 'error', text: getMessage('roof.material.can.not.delete') })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const isSelected = currentRoofList[idx].selected
|
const isSelected = currentRoofList[idx].selected
|
||||||
const newRoofList = JSON.parse(JSON.stringify(currentRoofList)).filter((_, index) => index !== idx)
|
const newRoofList = JSON.parse(JSON.stringify(currentRoofList)).filter((_, index) => index !== idx)
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
@ -300,6 +309,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
setRoofList(newRoofList)
|
setRoofList(newRoofList)
|
||||||
|
setRoofMaterials(newRoofList)
|
||||||
const selectedRoofMaterial = newRoofList.find((roof) => roof.selected)
|
const selectedRoofMaterial = newRoofList.find((roof) => roof.selected)
|
||||||
setSurfaceShapePattern(currentObject, roofDisplay.column, false, selectedRoofMaterial, true)
|
setSurfaceShapePattern(currentObject, roofDisplay.column, false, selectedRoofMaterial, true)
|
||||||
drawDirectionArrow(currentObject)
|
drawDirectionArrow(currentObject)
|
||||||
@ -308,6 +318,21 @@ export function useRoofAllocationSetting(id) {
|
|||||||
basicSettingSave()
|
basicSettingSave()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 기존 세팅된 지붕에 지붕재 내용을 바뀐 내용으로 수정
|
||||||
|
* @param newRoofMaterials
|
||||||
|
*/
|
||||||
|
const setRoofMaterials = (newRoofMaterials) => {
|
||||||
|
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
|
newRoofMaterials.forEach((roofMaterial) => {
|
||||||
|
const index = roofMaterial.index
|
||||||
|
const tempRoofs = roofs.filter((roof) => roof.roofMaterial?.index === index)
|
||||||
|
tempRoofs.forEach((roof) => {
|
||||||
|
setSurfaceShapePattern(roof, roofDisplay.column, false, roofMaterial)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 지붕면 할당
|
* 지붕면 할당
|
||||||
*/
|
*/
|
||||||
@ -411,6 +436,8 @@ export function useRoofAllocationSetting(id) {
|
|||||||
drawDirectionArrow(roof)
|
drawDirectionArrow(roof)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
setRoofMaterials(newRoofList)
|
||||||
|
|
||||||
/** 외곽선 삭제 */
|
/** 외곽선 삭제 */
|
||||||
const removeTargets = canvas.getObjects().filter((obj) => obj.name === 'outerLinePoint' || obj.name === 'outerLine')
|
const removeTargets = canvas.getObjects().filter((obj) => obj.name === 'outerLinePoint' || obj.name === 'outerLine')
|
||||||
removeTargets.forEach((obj) => {
|
removeTargets.forEach((obj) => {
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import {
|
|||||||
import { usePolygon } from '@/hooks/usePolygon'
|
import { usePolygon } from '@/hooks/usePolygon'
|
||||||
import { POLYGON_TYPE } from '@/common/common'
|
import { POLYGON_TYPE } from '@/common/common'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useSurfaceShapeBatch } from './useSurfaceShapeBatch'
|
||||||
|
|
||||||
import { roofDisplaySelector } from '@/store/settingAtom'
|
import { roofDisplaySelector } from '@/store/settingAtom'
|
||||||
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
||||||
@ -50,6 +51,8 @@ export function usePlacementShapeDrawing(id) {
|
|||||||
const { addPolygonByLines, drawDirectionArrow } = usePolygon()
|
const { addPolygonByLines, drawDirectionArrow } = usePolygon()
|
||||||
const { tempGridMode } = useTempGrid()
|
const { tempGridMode } = useTempGrid()
|
||||||
const { setSurfaceShapePattern } = useRoofFn()
|
const { setSurfaceShapePattern } = useRoofFn()
|
||||||
|
const { changeSurfaceLineType } = useSurfaceShapeBatch({})
|
||||||
|
|
||||||
const canvasSetting = useRecoilValue(canvasSettingState)
|
const canvasSetting = useRecoilValue(canvasSettingState)
|
||||||
const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
|
const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
|
||||||
const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState)
|
const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState)
|
||||||
@ -253,11 +256,14 @@ export function usePlacementShapeDrawing(id) {
|
|||||||
setPoints([])
|
setPoints([])
|
||||||
canvas?.renderAll()
|
canvas?.renderAll()
|
||||||
|
|
||||||
if (+canvasSetting?.roofSizeSet === 3) {
|
// if (+canvasSetting?.roofSizeSet === 3) {
|
||||||
closePopup(id)
|
// closePopup(id)
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
addPopup(id, 1, <PlacementSurfaceLineProperty id={id} roof={roof} />, false)
|
// addPopup(id, 1, <PlacementSurfaceLineProperty id={id} roof={roof} />, false)
|
||||||
|
|
||||||
|
changeSurfaceLineType(roof)
|
||||||
|
closePopup(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (points.length < 3) {
|
if (points.length < 3) {
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
|
||||||
import { canvasSettingState, canvasState, currentCanvasPlanState, globalPitchState } from '@/store/canvasAtom'
|
import { canvasSettingState, canvasState, currentCanvasPlanState, globalPitchState } from '@/store/canvasAtom'
|
||||||
import { MENU, POLYGON_TYPE } from '@/common/common'
|
import { MENU, POLYGON_TYPE, LINE_TYPE } from '@/common/common'
|
||||||
import { getIntersectionPoint, toFixedWithoutRounding } from '@/util/canvas-util'
|
import { getIntersectionPoint, toFixedWithoutRounding } from '@/util/canvas-util'
|
||||||
import { degreesToRadians } from '@turf/turf'
|
import { degreesToRadians } from '@turf/turf'
|
||||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||||
@ -111,7 +111,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
lockScalingX: true, // X 축 크기 조정 잠금
|
lockScalingX: true, // X 축 크기 조정 잠금
|
||||||
lockScalingY: true, // Y 축 크기 조정 잠금
|
lockScalingY: true, // Y 축 크기 조정 잠금
|
||||||
name: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH_TEMP,
|
name: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH_TEMP,
|
||||||
flipX: xInversion !== yInversion,
|
// flipX: xInversion !== yInversion,
|
||||||
// angle: xInversion && yInversion ? Math.abs((rotate + 180) % 360) : Math.abs(rotate),
|
// angle: xInversion && yInversion ? Math.abs((rotate + 180) % 360) : Math.abs(rotate),
|
||||||
// angle: rotate,
|
// angle: rotate,
|
||||||
originX: 'center',
|
originX: 'center',
|
||||||
@ -120,6 +120,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
obj = new QPolygon(points, options)
|
obj = new QPolygon(points, options)
|
||||||
|
|
||||||
let imageRotate = 0
|
let imageRotate = 0
|
||||||
if (xInversion && !yInversion) {
|
if (xInversion && !yInversion) {
|
||||||
if (rotate % 180 === 0 || rotate < 0) {
|
if (rotate % 180 === 0 || rotate < 0) {
|
||||||
@ -148,7 +149,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
} else {
|
} else {
|
||||||
imageRotate = (rotate + 360) % 360
|
imageRotate = (rotate + 360) % 360
|
||||||
}
|
}
|
||||||
obj.set({ angle: imageRotate })
|
obj.set({ angle: imageRotate, flipX: xInversion !== yInversion })
|
||||||
obj.setCoords() //좌표 변경 적용
|
obj.setCoords() //좌표 변경 적용
|
||||||
|
|
||||||
canvas?.add(obj)
|
canvas?.add(obj)
|
||||||
@ -201,13 +202,15 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
setSurfaceShapePattern(batchSurface, roofDisplay.column)
|
setSurfaceShapePattern(batchSurface, roofDisplay.column)
|
||||||
drawDirectionArrow(batchSurface)
|
drawDirectionArrow(batchSurface)
|
||||||
|
|
||||||
// if (setIsHidden) setIsHidden(false)
|
|
||||||
|
|
||||||
// closePopup(id)
|
// closePopup(id)
|
||||||
initEvent()
|
initEvent()
|
||||||
if (+canvasSetting?.roofSizeSet === 3) return
|
// if (+canvasSetting?.roofSizeSet === 3) return
|
||||||
const popupId = uuidv4()
|
// const popupId = uuidv4()
|
||||||
addPopup(popupId, 2, <PlacementSurfaceLineProperty roof={batchSurface} id={popupId} setIsHidden={setIsHidden} />)
|
// addPopup(popupId, 2, <PlacementSurfaceLineProperty roof={batchSurface} id={popupId} setIsHidden={setIsHidden} />)
|
||||||
|
|
||||||
|
changeSurfaceLineType(batchSurface)
|
||||||
|
|
||||||
|
if (setIsHidden) setIsHidden(false)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
if (setIsHidden) setIsHidden(false)
|
if (setIsHidden) setIsHidden(false)
|
||||||
@ -1066,45 +1069,101 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
canvas?.renderAll()
|
canvas?.renderAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateFlippedPoints = (polygon) => {
|
/**
|
||||||
if (!(polygon instanceof fabric.Polygon)) {
|
* 면형상 작도시 라인 속성 넣는 로직
|
||||||
console.error('The object is not a Polygon.')
|
* 폴리곤으로 보면 직선방향에 따라 아래쪽인지 윗쪽인지 판단이 가능하다고 생각하여
|
||||||
return
|
* south -> 밑면은 무조건 right direction이라 가정하고 작업함 좌우반전시 반대로 그려지는 경우도 생기지만 그럴땐 흐름방향에 따라 최대값(최소값)을 찾아
|
||||||
}
|
* 해당 하는 흐름에 맞게 변경함
|
||||||
|
* @param { } polygon
|
||||||
|
*/
|
||||||
|
|
||||||
const { flipX, flipY, width, height, points, left, top, scaleX, scaleY } = polygon
|
const changeSurfaceLineType = (polygon) => {
|
||||||
|
polygon.lines.forEach((line) => {
|
||||||
// 현재 points의 사본 가져오기
|
line.attributes.type = LINE_TYPE.WALLLINE.GABLE
|
||||||
const newPoints = points.map((point) => {
|
|
||||||
let x = point.x
|
|
||||||
let y = point.y
|
|
||||||
|
|
||||||
// flipX 적용
|
|
||||||
if (flipX) {
|
|
||||||
x = width - x
|
|
||||||
}
|
|
||||||
|
|
||||||
// flipY 적용
|
|
||||||
if (flipY) {
|
|
||||||
y = height - y
|
|
||||||
}
|
|
||||||
|
|
||||||
// 스케일 및 전역 좌표 고려
|
|
||||||
x = (x - width / 2) * scaleX + width / 2
|
|
||||||
y = (y - height / 2) * scaleY + height / 2
|
|
||||||
|
|
||||||
return { x, y }
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// flipX, flipY를 초기화
|
const directionConfig = {
|
||||||
polygon.flipX = false
|
south: { evaesDirection: 'right', ridgeDirection: 'left', coord1: 'y1', coord2: 'y2' },
|
||||||
polygon.flipY = false
|
north: { evaesDirection: 'left', ridgeDirection: 'right', coord1: 'y1', coord2: 'y2' },
|
||||||
|
east: { evaesDirection: 'top', ridgeDirection: 'bottom', coord1: 'x1', coord2: 'x2' },
|
||||||
|
west: { evaesDirection: 'bottom', ridgeDirection: 'top', coord1: 'x1', coord2: 'x2' },
|
||||||
|
}
|
||||||
|
|
||||||
// points 업데이트
|
const { evaesDirection, ridgeDirection, coord1, coord2 } = directionConfig[polygon.direction] || directionConfig.west
|
||||||
polygon.set({ points: newPoints })
|
|
||||||
polygon.setCoords()
|
|
||||||
|
|
||||||
return polygon
|
polygon.lines.forEach((line) => {
|
||||||
|
if (line[coord1] === line[coord2]) {
|
||||||
|
if (line.direction === evaesDirection) {
|
||||||
|
line.attributes.type = LINE_TYPE.WALLLINE.EAVES
|
||||||
|
line.stroke = 'rgb(47, 0, 255)'
|
||||||
|
} else if (line.direction === ridgeDirection) {
|
||||||
|
line.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||||
|
line.stroke = 'rgb(44, 255, 2)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 진짜 처마 라인인지 확인하는 로직 -> 특정 모양에 따라 처마가 없는 경우가 있는데 위에 로직으로는
|
||||||
|
* 용마루도 처마로 만들어서 재보정
|
||||||
|
*/
|
||||||
|
//직선 찾는 로직
|
||||||
|
const maxLine = polygon.lines.filter((line) => line[coord1] === line[coord2])
|
||||||
|
|
||||||
|
if (maxLine.length > 0) {
|
||||||
|
const maxLineSorted = maxLine.reduce((a, b) => {
|
||||||
|
return (polygon.direction === 'south' || polygon.direction === 'east' ? b : a)[coord1] >
|
||||||
|
(polygon.direction === 'south' || polygon.direction === 'east' ? a : b)[coord1]
|
||||||
|
? b
|
||||||
|
: a
|
||||||
|
})
|
||||||
|
|
||||||
|
if (
|
||||||
|
(polygon.direction === 'south' && maxLineSorted.direction === 'left') ||
|
||||||
|
(polygon.direction === 'north' && maxLineSorted.direction === 'right') ||
|
||||||
|
(polygon.direction === 'east' && maxLineSorted.direction === 'bottom') ||
|
||||||
|
(polygon.direction === 'west' && maxLineSorted.direction === 'top')
|
||||||
|
) {
|
||||||
|
polygon.lines.forEach((line) => {
|
||||||
|
if (line.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
|
||||||
|
line.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||||
|
} else if (line.attributes.type === LINE_TYPE.SUBLINE.RIDGE) {
|
||||||
|
line.attributes.type = LINE_TYPE.WALLLINE.EAVES
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxLine.length === 1) {
|
||||||
|
const maxLineCoord = polygon.lines.reduce((a, b) => {
|
||||||
|
return (polygon.direction === 'south' || polygon.direction === 'east' ? b : a)[coord1] >
|
||||||
|
(polygon.direction === 'south' || polygon.direction === 'east' ? a : b)[coord1]
|
||||||
|
? b
|
||||||
|
: a
|
||||||
|
})
|
||||||
|
|
||||||
|
const isRealEavesLine = polygon.lines.find((line) => line.attributes.type === LINE_TYPE.WALLLINE.EAVES)
|
||||||
|
if (isRealEavesLine) {
|
||||||
|
if (polygon.direction === 'south' || polygon.direction === 'north') {
|
||||||
|
const targetCoord =
|
||||||
|
polygon.direction === 'south' ? Math.max(maxLineCoord.y1, maxLineCoord.y2) : Math.min(maxLineCoord.y1, maxLineCoord.y2)
|
||||||
|
const realLineCoord =
|
||||||
|
polygon.direction === 'south' ? Math.max(isRealEavesLine.y1, isRealEavesLine.y2) : Math.min(isRealEavesLine.y1, isRealEavesLine.y2)
|
||||||
|
|
||||||
|
if (targetCoord !== realLineCoord) {
|
||||||
|
isRealEavesLine.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||||
|
}
|
||||||
|
} else if (polygon.direction === 'east' || polygon.direction === 'west') {
|
||||||
|
const targetCoord = polygon.direction === 'east' ? Math.max(maxLineCoord.x1, maxLineCoord.x2) : Math.min(maxLineCoord.x1, maxLineCoord.x2)
|
||||||
|
const realLineCoord =
|
||||||
|
polygon.direction === 'east' ? Math.max(isRealEavesLine.x1, isRealEavesLine.x2) : Math.min(isRealEavesLine.x1, isRealEavesLine.x2)
|
||||||
|
|
||||||
|
if (targetCoord !== realLineCoord) {
|
||||||
|
isRealEavesLine.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -1115,5 +1174,6 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
changeSurfaceLinePropertyEvent,
|
changeSurfaceLinePropertyEvent,
|
||||||
changeSurfaceLineProperty,
|
changeSurfaceLineProperty,
|
||||||
changeSurfaceLinePropertyReset,
|
changeSurfaceLinePropertyReset,
|
||||||
|
changeSurfaceLineType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -81,9 +81,9 @@ export function useContextMenu() {
|
|||||||
switch (selectedMenu) {
|
switch (selectedMenu) {
|
||||||
case 'outline':
|
case 'outline':
|
||||||
break
|
break
|
||||||
default:
|
// default:
|
||||||
setContextMenu([])
|
// setContextMenu([])
|
||||||
break
|
// break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -178,7 +178,7 @@
|
|||||||
"modal.roof.alloc.select.parallel": "筋配置",
|
"modal.roof.alloc.select.parallel": "筋配置",
|
||||||
"modal.roof.alloc.select.stairs": "千鳥配置",
|
"modal.roof.alloc.select.stairs": "千鳥配置",
|
||||||
"modal.roof.alloc.apply": "選択した屋根材として割り当て",
|
"modal.roof.alloc.apply": "選択した屋根材として割り当て",
|
||||||
"plan.menu.estimate.docDown": "各種資料ダウンロード",
|
"plan.menu.estimate.docDownload": "見積書出力",
|
||||||
"plan.menu.estimate.save": "保存",
|
"plan.menu.estimate.save": "保存",
|
||||||
"plan.menu.estimate.reset": "初期化",
|
"plan.menu.estimate.reset": "初期化",
|
||||||
"plan.menu.estimate.copy": "見積書のコピー",
|
"plan.menu.estimate.copy": "見積書のコピー",
|
||||||
@ -887,7 +887,7 @@
|
|||||||
"estimate.detail.drawingEstimateCreateDate": "登録日",
|
"estimate.detail.drawingEstimateCreateDate": "登録日",
|
||||||
"estimate.detail.lastEditDatetime": "変更日時",
|
"estimate.detail.lastEditDatetime": "変更日時",
|
||||||
"estimate.detail.saleStoreId": "一次販売店名",
|
"estimate.detail.saleStoreId": "一次販売店名",
|
||||||
"estimate.detail.estimateDate": "見積日",
|
"estimate.detail.estimateDate": "見積作成日",
|
||||||
"estimate.detail.otherSaleStoreId": "二次販売店名",
|
"estimate.detail.otherSaleStoreId": "二次販売店名",
|
||||||
"estimate.detail.noOtherSaleStoreId": "二次店なし",
|
"estimate.detail.noOtherSaleStoreId": "二次店なし",
|
||||||
"estimate.detail.receiveUser": "担当者",
|
"estimate.detail.receiveUser": "担当者",
|
||||||
@ -958,6 +958,7 @@
|
|||||||
"estimate.detail.estimateCopyPopup.close": "閉じる",
|
"estimate.detail.estimateCopyPopup.close": "閉じる",
|
||||||
"estimate.detail.estimateCopyPopup.copyBtn": "見積コピー",
|
"estimate.detail.estimateCopyPopup.copyBtn": "見積コピー",
|
||||||
"estimate.detail.estimateCopyPopup.copy.alertMessage": "見積書がコピーされました。コピーした見積情報に移動します。",
|
"estimate.detail.estimateCopyPopup.copy.alertMessage": "見積書がコピーされました。コピーした見積情報に移動します。",
|
||||||
|
"estimate.detail.estimateCopyPopup.copy.alertMessageError": "キャンバスのコピー中にエラーが発生しました.",
|
||||||
"estimate.detail.productFeaturesPopup.title": "製品特異事項",
|
"estimate.detail.productFeaturesPopup.title": "製品特異事項",
|
||||||
"estimate.detail.productFeaturesPopup.close": "閉じる",
|
"estimate.detail.productFeaturesPopup.close": "閉じる",
|
||||||
"estimate.detail.productFeaturesPopup.requiredStoreId": "一次販売店は必須です。",
|
"estimate.detail.productFeaturesPopup.requiredStoreId": "一次販売店は必須です。",
|
||||||
@ -1035,9 +1036,10 @@
|
|||||||
"roof.exceed.count": "屋根材は4つまで選択可能です。",
|
"roof.exceed.count": "屋根材は4つまで選択可能です。",
|
||||||
"outerLine.property.fix": "外壁線の属性設定 を完了しますか?",
|
"outerLine.property.fix": "外壁線の属性設定 を完了しますか?",
|
||||||
"outerLine.property.close": "外壁線の属性設定 を終了しますか?",
|
"outerLine.property.close": "外壁線の属性設定 を終了しますか?",
|
||||||
"want.to.complete.auxiliary.creation": "보補助線の作成を完了しますか?",
|
"want.to.complete.auxiliary.creation": "補助線の作成を完了しますか?",
|
||||||
"module.layout.setup.has.zero.value": "モジュールの列、行を入力してください.",
|
"module.layout.setup.has.zero.value": "モジュールの列、行を入力してください.",
|
||||||
"modal.placement.initial.setting.plan.drawing.only.number": "(※数字は[半角]入力のみ可能です。)",
|
"modal.placement.initial.setting.plan.drawing.only.number": "(※数字は[半角]入力のみ可能です。)",
|
||||||
"wall.line.not.found": "外壁がありません",
|
"wall.line.not.found": "外壁がありません",
|
||||||
"roof.line.not.found": "屋根形状がありません"
|
"roof.line.not.found": "屋根形状がありません",
|
||||||
|
"roof.material.can.not.delete": "割り当てられた配置面があります。"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -178,7 +178,7 @@
|
|||||||
"modal.roof.alloc.select.parallel": "병렬식",
|
"modal.roof.alloc.select.parallel": "병렬식",
|
||||||
"modal.roof.alloc.select.stairs": "계단식",
|
"modal.roof.alloc.select.stairs": "계단식",
|
||||||
"modal.roof.alloc.apply": "선택한 지붕재로 할당",
|
"modal.roof.alloc.apply": "선택한 지붕재로 할당",
|
||||||
"plan.menu.estimate.docDown": "문서 다운로드",
|
"plan.menu.estimate.docDownload": "문서 다운로드",
|
||||||
"plan.menu.estimate.save": "저장",
|
"plan.menu.estimate.save": "저장",
|
||||||
"plan.menu.estimate.reset": "초기화",
|
"plan.menu.estimate.reset": "초기화",
|
||||||
"plan.menu.estimate.copy": "견적서 복사",
|
"plan.menu.estimate.copy": "견적서 복사",
|
||||||
@ -887,7 +887,7 @@
|
|||||||
"estimate.detail.drawingEstimateCreateDate": "등록일",
|
"estimate.detail.drawingEstimateCreateDate": "등록일",
|
||||||
"estimate.detail.lastEditDatetime": "변경일시",
|
"estimate.detail.lastEditDatetime": "변경일시",
|
||||||
"estimate.detail.saleStoreId": "1차 판매점명",
|
"estimate.detail.saleStoreId": "1차 판매점명",
|
||||||
"estimate.detail.estimateDate": "견적일",
|
"estimate.detail.estimateDate": "견적작성일",
|
||||||
"estimate.detail.otherSaleStoreId": "2차 판매점명",
|
"estimate.detail.otherSaleStoreId": "2차 판매점명",
|
||||||
"estimate.detail.noOtherSaleStoreId": "2차점 없음",
|
"estimate.detail.noOtherSaleStoreId": "2차점 없음",
|
||||||
"estimate.detail.receiveUser": "담당자",
|
"estimate.detail.receiveUser": "담당자",
|
||||||
@ -958,6 +958,7 @@
|
|||||||
"estimate.detail.estimateCopyPopup.close": "닫기",
|
"estimate.detail.estimateCopyPopup.close": "닫기",
|
||||||
"estimate.detail.estimateCopyPopup.copyBtn": "견적복사",
|
"estimate.detail.estimateCopyPopup.copyBtn": "견적복사",
|
||||||
"estimate.detail.estimateCopyPopup.copy.alertMessage": "견적서가 복사되었습니다. 복사된 물건정보로 이동합니다.",
|
"estimate.detail.estimateCopyPopup.copy.alertMessage": "견적서가 복사되었습니다. 복사된 물건정보로 이동합니다.",
|
||||||
|
"estimate.detail.estimateCopyPopup.copy.alertMessageError": "캔버스 복사 중 오류 발생.",
|
||||||
"estimate.detail.productFeaturesPopup.title": "제품특이사항",
|
"estimate.detail.productFeaturesPopup.title": "제품특이사항",
|
||||||
"estimate.detail.productFeaturesPopup.close": "닫기",
|
"estimate.detail.productFeaturesPopup.close": "닫기",
|
||||||
"estimate.detail.productFeaturesPopup.requiredStoreId": "1차 판매점은 필수값 입니다.",
|
"estimate.detail.productFeaturesPopup.requiredStoreId": "1차 판매점은 필수값 입니다.",
|
||||||
@ -1039,5 +1040,6 @@
|
|||||||
"module.layout.setup.has.zero.value": "모듈의 열, 행을 입력해 주세요.",
|
"module.layout.setup.has.zero.value": "모듈의 열, 행을 입력해 주세요.",
|
||||||
"modal.placement.initial.setting.plan.drawing.only.number": "(※ 숫자는 [반각]입력만 가능합니다.)",
|
"modal.placement.initial.setting.plan.drawing.only.number": "(※ 숫자는 [반각]입력만 가능합니다.)",
|
||||||
"wall.line.not.found": "외벽선이 없습니다.",
|
"wall.line.not.found": "외벽선이 없습니다.",
|
||||||
"roof.line.not.found": "지붕형상이 없습니다."
|
"roof.line.not.found": "지붕형상이 없습니다.",
|
||||||
|
"roof.material.can.not.delete": "할당된 배치면이 있습니다."
|
||||||
}
|
}
|
||||||
|
|||||||
6
src/store/hotkeyAtom.js
Normal file
6
src/store/hotkeyAtom.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { atom } from 'recoil'
|
||||||
|
|
||||||
|
export const hotkeyStore = atom({
|
||||||
|
key: 'hotkeyState',
|
||||||
|
default: [],
|
||||||
|
})
|
||||||
@ -348,15 +348,15 @@ export const calculateIntersection = (line1, line2) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Determine the min and max for line1 and line2 for both x and y
|
// Determine the min and max for line1 and line2 for both x and y
|
||||||
const line1MinX = Math.min(line1.x1, line1.x2)
|
const line1MinX = Math.min(line1.x1, line1.x2) - 5
|
||||||
const line1MaxX = Math.max(line1.x1, line1.x2)
|
const line1MaxX = Math.max(line1.x1, line1.x2) + 5
|
||||||
const line2MinX = Math.min(line2.x1, line2.x2)
|
const line2MinX = Math.min(line2.x1, line2.x2) - 5
|
||||||
const line2MaxX = Math.max(line2.x1, line2.x2)
|
const line2MaxX = Math.max(line2.x1, line2.x2) + 5
|
||||||
|
|
||||||
const line1MinY = Math.min(line1.y1, line1.y2)
|
const line1MinY = Math.min(line1.y1, line1.y2) - 5
|
||||||
const line1MaxY = Math.max(line1.y1, line1.y2)
|
const line1MaxY = Math.max(line1.y1, line1.y2) + 5
|
||||||
const line2MinY = Math.min(line2.y1, line2.y2)
|
const line2MinY = Math.min(line2.y1, line2.y2) - 5
|
||||||
const line2MaxY = Math.max(line2.y1, line2.y2)
|
const line2MaxY = Math.max(line2.y1, line2.y2) + 5
|
||||||
|
|
||||||
// Check if the intersection X and Y are within the range of both lines
|
// Check if the intersection X and Y are within the range of both lines
|
||||||
if (
|
if (
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user