Merge branch 'dev' of https://git.jetbrains.space/nalpari/q-cast-iii/qcast-front into dev
This commit is contained in:
commit
82bc00e2aa
@ -212,7 +212,7 @@ export default function CanvasMenu(props) {
|
|||||||
}, [canvasSetting])
|
}, [canvasSetting])
|
||||||
|
|
||||||
const checkMenuState = (menu) => {
|
const checkMenuState = (menu) => {
|
||||||
return ([2, 3].some((num) => num === canvasSetting?.roofSizeSet) && menu.index === 2) || (menuNumber === 4 && menu.index === 2)
|
return (['2', '3'].includes(canvasSetting?.roofSizeSet) && menu.index === 2) || (menuNumber === 4 && menu.index === 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 발전시물레이션 Excel/PDF 다운
|
// 발전시물레이션 Excel/PDF 다운
|
||||||
@ -283,7 +283,7 @@ export default function CanvasMenu(props) {
|
|||||||
key={`canvas-menu-${menu.index}`}
|
key={`canvas-menu-${menu.index}`}
|
||||||
className={`canvas-menu-item ${menuNumber === menu.index ? 'active' : ''}`}
|
className={`canvas-menu-item ${menuNumber === menu.index ? 'active' : ''}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if ([2, 3].some((num) => num === canvasSetting?.roofSizeSet) && menu.index === 2) return
|
if (['2', '3'].includes(canvasSetting?.roofSizeSet) && menu.index === 2) return
|
||||||
if (menuNumber === 4 && menu.index === 2) return
|
if (menuNumber === 4 && menu.index === 2) return
|
||||||
onClickNav(menu)
|
onClickNav(menu)
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -29,6 +29,8 @@ export default function DotLineGrid(props) {
|
|||||||
const { SelectOptions, currentSetting, setCurrentSetting, dotLineGridSettingState, setSettingModalGridOptions, setDotLineGridSettingState } =
|
const { SelectOptions, currentSetting, setCurrentSetting, dotLineGridSettingState, setSettingModalGridOptions, setDotLineGridSettingState } =
|
||||||
useCanvasSetting()
|
useCanvasSetting()
|
||||||
|
|
||||||
|
const [copyCurrentSetting, setCopyCurrentSetting] = useState({ ...currentSetting })
|
||||||
|
|
||||||
// 데이터를 최초 한 번만 조회
|
// 데이터를 최초 한 번만 조회
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('DotLineGrid useEffect 실행')
|
console.log('DotLineGrid useEffect 실행')
|
||||||
@ -57,7 +59,7 @@ export default function DotLineGrid(props) {
|
|||||||
|
|
||||||
const handleCheckBoxChange = (e) => {
|
const handleCheckBoxChange = (e) => {
|
||||||
const { value, checked } = e.target
|
const { value, checked } = e.target
|
||||||
setCurrentSetting((prev) => {
|
setCopyCurrentSetting((prev) => {
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
[value]: checked,
|
[value]: checked,
|
||||||
@ -66,23 +68,23 @@ export default function DotLineGrid(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
if (!currentSetting.DOT && !currentSetting.LINE) {
|
/*if (!currentSetting.DOT && !currentSetting.LINE) {
|
||||||
swalFire({ text: '배치할 그리드를 설정해주세요.' })
|
swalFire({ text: '배치할 그리드를 설정해주세요.' })
|
||||||
return
|
return
|
||||||
}
|
}*/
|
||||||
|
|
||||||
setDotLineGridSettingState((prev) => {
|
setDotLineGridSettingState((prev) => {
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
INTERVAL: {
|
INTERVAL: {
|
||||||
type: currentSetting.INTERVAL.type,
|
type: copyCurrentSetting.INTERVAL.type,
|
||||||
horizontalInterval: currentSetting.INTERVAL.horizontalInterval,
|
horizontalInterval: copyCurrentSetting.INTERVAL.horizontalInterval,
|
||||||
verticalInterval: currentSetting.INTERVAL.verticalInterval,
|
verticalInterval: copyCurrentSetting.INTERVAL.verticalInterval,
|
||||||
ratioInterval: currentSetting.INTERVAL.ratioInterval,
|
ratioInterval: copyCurrentSetting.INTERVAL.ratioInterval,
|
||||||
dimension: currentSetting.INTERVAL.dimension,
|
dimension: copyCurrentSetting.INTERVAL.dimension,
|
||||||
},
|
},
|
||||||
DOT: currentSetting.DOT,
|
DOT: copyCurrentSetting.DOT,
|
||||||
LINE: currentSetting.LINE,
|
LINE: copyCurrentSetting.LINE,
|
||||||
}
|
}
|
||||||
//setDotLineGridSettingState({ ...currentSetting })
|
//setDotLineGridSettingState({ ...currentSetting })
|
||||||
})
|
})
|
||||||
@ -90,16 +92,18 @@ export default function DotLineGrid(props) {
|
|||||||
setSettingsData({
|
setSettingsData({
|
||||||
...settingsData,
|
...settingsData,
|
||||||
INTERVAL: {
|
INTERVAL: {
|
||||||
type: currentSetting.INTERVAL.type,
|
type: copyCurrentSetting.INTERVAL.type,
|
||||||
horizontalInterval: currentSetting.INTERVAL.horizontalInterval,
|
horizontalInterval: copyCurrentSetting.INTERVAL.horizontalInterval,
|
||||||
verticalInterval: currentSetting.INTERVAL.verticalInterval,
|
verticalInterval: copyCurrentSetting.INTERVAL.verticalInterval,
|
||||||
ratioInterval: currentSetting.INTERVAL.ratioInterval,
|
ratioInterval: copyCurrentSetting.INTERVAL.ratioInterval,
|
||||||
dimension: currentSetting.INTERVAL.dimension,
|
dimension: copyCurrentSetting.INTERVAL.dimension,
|
||||||
},
|
},
|
||||||
DOT: currentSetting.DOT,
|
DOT: copyCurrentSetting.DOT,
|
||||||
LINE: currentSetting.LINE,
|
LINE: copyCurrentSetting.LINE,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
setCurrentSetting({ ...copyCurrentSetting })
|
||||||
|
|
||||||
setIsShow(false)
|
setIsShow(false)
|
||||||
closePopup(id, isConfig)
|
closePopup(id, isConfig)
|
||||||
}
|
}
|
||||||
@ -107,7 +111,7 @@ export default function DotLineGrid(props) {
|
|||||||
const handleRadioChange = (e) => {
|
const handleRadioChange = (e) => {
|
||||||
const { value, name, checked, selected } = e.target
|
const { value, name, checked, selected } = e.target
|
||||||
|
|
||||||
setCurrentSetting((prev) => {
|
setCopyCurrentSetting((prev) => {
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
INTERVAL: {
|
INTERVAL: {
|
||||||
@ -120,7 +124,7 @@ export default function DotLineGrid(props) {
|
|||||||
|
|
||||||
const changeInput = (value, e) => {
|
const changeInput = (value, e) => {
|
||||||
const { name } = e.target
|
const { name } = e.target
|
||||||
setCurrentSetting((prev) => {
|
setCopyCurrentSetting((prev) => {
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
INTERVAL: {
|
INTERVAL: {
|
||||||
@ -133,7 +137,7 @@ export default function DotLineGrid(props) {
|
|||||||
|
|
||||||
const changeDimension = (result) => {
|
const changeDimension = (result) => {
|
||||||
const { value } = result
|
const { value } = result
|
||||||
setCurrentSetting((prev) => {
|
setCopyCurrentSetting((prev) => {
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
INTERVAL: {
|
INTERVAL: {
|
||||||
@ -146,7 +150,7 @@ export default function DotLineGrid(props) {
|
|||||||
|
|
||||||
// 초기화
|
// 초기화
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
canvas
|
/*canvas
|
||||||
?.getObjects()
|
?.getObjects()
|
||||||
.filter((obj) => obj.name === 'lineGrid')
|
.filter((obj) => obj.name === 'lineGrid')
|
||||||
.forEach((obj) => canvas?.remove(obj))
|
.forEach((obj) => canvas?.remove(obj))
|
||||||
@ -154,9 +158,9 @@ export default function DotLineGrid(props) {
|
|||||||
?.getObjects()
|
?.getObjects()
|
||||||
.filter((obj) => obj.name === 'dotGrid')
|
.filter((obj) => obj.name === 'dotGrid')
|
||||||
.forEach((obj) => canvas?.remove(obj))
|
.forEach((obj) => canvas?.remove(obj))
|
||||||
|
*/
|
||||||
// resetDotLineGridSetting()
|
// resetDotLineGridSetting()
|
||||||
setCurrentSetting({
|
setCopyCurrentSetting({
|
||||||
INTERVAL: {
|
INTERVAL: {
|
||||||
type: 2, // 1: 가로,세로 간격 수동, 2: 비율 간격
|
type: 2, // 1: 가로,세로 간격 수동, 2: 비율 간격
|
||||||
ratioInterval: 910,
|
ratioInterval: 910,
|
||||||
@ -188,11 +192,11 @@ export default function DotLineGrid(props) {
|
|||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
<div className="grid-check-form">
|
<div className="grid-check-form">
|
||||||
<div className="d-check-box pop">
|
<div className="d-check-box pop">
|
||||||
<input type="checkbox" id="ch01" value={TYPE.DOT} onChange={handleCheckBoxChange} checked={currentSetting.DOT} />
|
<input type="checkbox" id="ch01" value={TYPE.DOT} onChange={handleCheckBoxChange} checked={copyCurrentSetting.DOT} />
|
||||||
<label htmlFor="ch01">{getMessage('modal.canvas.setting.grid.dot.line.setting.dot.display')}</label>
|
<label htmlFor="ch01">{getMessage('modal.canvas.setting.grid.dot.line.setting.dot.display')}</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="d-check-box pop">
|
<div className="d-check-box pop">
|
||||||
<input type="checkbox" id="ch02" value={TYPE.LINE} onChange={handleCheckBoxChange} checked={currentSetting.LINE} />
|
<input type="checkbox" id="ch02" value={TYPE.LINE} onChange={handleCheckBoxChange} checked={copyCurrentSetting.LINE} />
|
||||||
<label htmlFor="ch02">{getMessage('modal.canvas.setting.grid.dot.line.setting.line.display')}</label>
|
<label htmlFor="ch02">{getMessage('modal.canvas.setting.grid.dot.line.setting.line.display')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -205,8 +209,8 @@ export default function DotLineGrid(props) {
|
|||||||
id="ra01"
|
id="ra01"
|
||||||
value={1}
|
value={1}
|
||||||
onChange={handleRadioChange}
|
onChange={handleRadioChange}
|
||||||
checked={(currentSetting.DOT || currentSetting.LINE) && currentSetting.INTERVAL.type === 1}
|
checked={(copyCurrentSetting.DOT || copyCurrentSetting.LINE) && copyCurrentSetting.INTERVAL.type === 1}
|
||||||
readOnly={!currentSetting.DOT && !currentSetting.LINE}
|
readOnly={!copyCurrentSetting.DOT && !copyCurrentSetting.LINE}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="ra01"></label>
|
<label htmlFor="ra01"></label>
|
||||||
</div>
|
</div>
|
||||||
@ -217,7 +221,7 @@ export default function DotLineGrid(props) {
|
|||||||
type="text"
|
type="text"
|
||||||
className="input-origin"
|
className="input-origin"
|
||||||
name={`horizontalInterval`}
|
name={`horizontalInterval`}
|
||||||
value={currentSetting.INTERVAL.horizontalInterval}
|
value={copyCurrentSetting.INTERVAL.horizontalInterval}
|
||||||
onChange={(e) => onlyNumberInputChange(e, changeInput)}
|
onChange={(e) => onlyNumberInputChange(e, changeInput)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -230,7 +234,7 @@ export default function DotLineGrid(props) {
|
|||||||
type="text"
|
type="text"
|
||||||
className="input-origin"
|
className="input-origin"
|
||||||
name={`verticalInterval`}
|
name={`verticalInterval`}
|
||||||
value={currentSetting.INTERVAL.verticalInterval}
|
value={copyCurrentSetting.INTERVAL.verticalInterval}
|
||||||
onChange={(e) => onlyNumberInputChange(e, changeInput)}
|
onChange={(e) => onlyNumberInputChange(e, changeInput)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -245,8 +249,8 @@ export default function DotLineGrid(props) {
|
|||||||
id="ra02"
|
id="ra02"
|
||||||
value={2}
|
value={2}
|
||||||
onChange={handleRadioChange}
|
onChange={handleRadioChange}
|
||||||
checked={(currentSetting.DOT || currentSetting.LINE) && currentSetting.INTERVAL.type === 2}
|
checked={(copyCurrentSetting.DOT || copyCurrentSetting.LINE) && copyCurrentSetting.INTERVAL.type === 2}
|
||||||
readOnly={!currentSetting.DOT && !currentSetting.LINE}
|
readOnly={!copyCurrentSetting.DOT && !copyCurrentSetting.LINE}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="ra02"></label>
|
<label htmlFor="ra02"></label>
|
||||||
</div>
|
</div>
|
||||||
@ -257,14 +261,21 @@ export default function DotLineGrid(props) {
|
|||||||
type="text"
|
type="text"
|
||||||
className="input-origin"
|
className="input-origin"
|
||||||
name={`ratioInterval`}
|
name={`ratioInterval`}
|
||||||
value={currentSetting.INTERVAL.ratioInterval}
|
value={copyCurrentSetting.INTERVAL.ratioInterval}
|
||||||
onChange={(e) => onlyNumberInputChange(e, changeInput)}
|
onChange={(e) => onlyNumberInputChange(e, changeInput)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span>mm</span>
|
<span>mm</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-select">
|
<div className="grid-select">
|
||||||
<QSelectBox options={SelectOptions} onChange={changeDimension} value={selectOption} />
|
<QSelectBox
|
||||||
|
options={SelectOptions}
|
||||||
|
onChange={changeDimension}
|
||||||
|
value={selectOption}
|
||||||
|
showKey={'name'}
|
||||||
|
targetKey={'id'}
|
||||||
|
sourceKey={'id'}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -14,7 +14,9 @@ import { useModule } from '@/hooks/module/useModule'
|
|||||||
|
|
||||||
export const PANEL_EDIT_TYPE = {
|
export const PANEL_EDIT_TYPE = {
|
||||||
MOVE: 'move',
|
MOVE: 'move',
|
||||||
|
MOVE_ALL: 'moveAll',
|
||||||
COPY: 'copy',
|
COPY: 'copy',
|
||||||
|
COPY_ALL: 'copyAll',
|
||||||
COLUMN_MOVE: 'columnMove',
|
COLUMN_MOVE: 'columnMove',
|
||||||
COLUMN_COPY: 'columnCopy',
|
COLUMN_COPY: 'columnCopy',
|
||||||
ROW_MOVE: 'rowMove',
|
ROW_MOVE: 'rowMove',
|
||||||
@ -29,7 +31,7 @@ export default function PanelEdit(props) {
|
|||||||
const [direction, setDirection] = useState('up')
|
const [direction, setDirection] = useState('up')
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const { moduleMove, moduleCopy, moduleMultiMove, moduleMultiCopy } = useModule()
|
const { moduleMove, moduleCopy, moduleMultiMove, moduleMultiCopy, moduleMoveAll, moduleCopyAll } = useModule()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
@ -44,9 +46,15 @@ export default function PanelEdit(props) {
|
|||||||
case PANEL_EDIT_TYPE.MOVE:
|
case PANEL_EDIT_TYPE.MOVE:
|
||||||
moduleMove(length, direction)
|
moduleMove(length, direction)
|
||||||
break
|
break
|
||||||
|
case PANEL_EDIT_TYPE.MOVE_ALL:
|
||||||
|
moduleMoveAll(length, direction)
|
||||||
|
break
|
||||||
case PANEL_EDIT_TYPE.COPY:
|
case PANEL_EDIT_TYPE.COPY:
|
||||||
moduleCopy(length, direction)
|
moduleCopy(length, direction)
|
||||||
break
|
break
|
||||||
|
case PANEL_EDIT_TYPE.COPY_ALL:
|
||||||
|
moduleCopyAll(length, direction)
|
||||||
|
break
|
||||||
case PANEL_EDIT_TYPE.COLUMN_MOVE:
|
case PANEL_EDIT_TYPE.COLUMN_MOVE:
|
||||||
moduleMultiMove('column', length, direction)
|
moduleMultiMove('column', length, direction)
|
||||||
break
|
break
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
import { useState } from 'react'
|
|
||||||
import FlowLine from '@/components/floor-plan/modal/movement/type/FlowLine'
|
import FlowLine from '@/components/floor-plan/modal/movement/type/FlowLine'
|
||||||
import Updown from '@/components/floor-plan/modal/movement/type/Updown'
|
import Updown from '@/components/floor-plan/modal/movement/type/Updown'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
|
||||||
import { useMovementSetting } from '@/hooks/roofcover/useMovementSetting'
|
import { useMovementSetting } from '@/hooks/roofcover/useMovementSetting'
|
||||||
|
|
||||||
export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) {
|
export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
import { currentObjectState } from '@/store/canvasAtom'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
|
||||||
const FLOW_LINE_TYPE = {
|
const FLOW_LINE_TYPE = {
|
||||||
DOWN_LEFT: 'downLeft',
|
DOWN_LEFT: 'downLeft',
|
||||||
@ -9,7 +11,18 @@ const FLOW_LINE_TYPE = {
|
|||||||
export default function FlowLine({ FLOW_LINE_REF }) {
|
export default function FlowLine({ FLOW_LINE_REF }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const [type, setType] = useState(FLOW_LINE_TYPE.DOWN_LEFT)
|
const [type, setType] = useState(FLOW_LINE_TYPE.DOWN_LEFT)
|
||||||
|
const [filledInput, setFilledInput] = useState('')
|
||||||
|
const currentObject = useRecoilValue(currentObjectState)
|
||||||
|
const handleFocus = () => {
|
||||||
|
if (currentObject === null) {
|
||||||
|
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = ''
|
||||||
|
FLOW_LINE_REF.FILLED_INPUT_REF.current.blur()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleInput = (e) => {
|
||||||
|
const value = e.target.value.replace(/^0+/, '')
|
||||||
|
setFilledInput(value.replace(/[^0-9]/g, ''))
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="outline-wrap">
|
<div className="outline-wrap">
|
||||||
@ -57,7 +70,14 @@ export default function FlowLine({ FLOW_LINE_REF }) {
|
|||||||
<div className="eaves-keraba-td">
|
<div className="eaves-keraba-td">
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||||
<input type="text" className="input-origin block" ref={FLOW_LINE_REF.FILLED_INPUT_REF} />
|
<input
|
||||||
|
type="text"
|
||||||
|
className="input-origin block"
|
||||||
|
ref={FLOW_LINE_REF.FILLED_INPUT_REF}
|
||||||
|
value={filledInput}
|
||||||
|
onFocus={handleFocus}
|
||||||
|
onChange={handleInput}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">mm</span>
|
<span className="thin">mm</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -28,7 +28,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
|||||||
const roofMaterials = useRecoilValue(roofMaterialsAtom)
|
const roofMaterials = useRecoilValue(roofMaterialsAtom)
|
||||||
|
|
||||||
const globalLocale = useRecoilValue(globalLocaleStore)
|
const globalLocale = useRecoilValue(globalLocaleStore)
|
||||||
const { basicSetting, setBasicSettings, fetchBasicSettings, basicSettingSave, addedRoofs, setAddedRoofs } = useCanvasSetting()
|
const { basicSetting, setBasicSettings, basicSettingSave, addedRoofs, setAddedRoofs } = useCanvasSetting()
|
||||||
const { findCommonCode } = useCommonCode()
|
const { findCommonCode } = useCommonCode()
|
||||||
const [raftCodes, setRaftCodes] = useState([]) // 서까래 정보
|
const [raftCodes, setRaftCodes] = useState([]) // 서까래 정보
|
||||||
const [currentRoof, setCurrentRoof] = useState(addedRoofs[0]) // 현재 선택된 지붕재 정보
|
const [currentRoof, setCurrentRoof] = useState(addedRoofs[0]) // 현재 선택된 지붕재 정보
|
||||||
@ -43,7 +43,6 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
|||||||
|
|
||||||
// 데이터를 최초 한 번만 조회
|
// 데이터를 최초 한 번만 조회
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
//fetchBasicSettings()
|
|
||||||
const raftCodeList = findCommonCode('203800')
|
const raftCodeList = findCommonCode('203800')
|
||||||
setRaftCodes(raftCodeList)
|
setRaftCodes(raftCodeList)
|
||||||
}, [])
|
}, [])
|
||||||
|
|||||||
@ -73,119 +73,121 @@ export default function RoofAllocationSetting(props) {
|
|||||||
{getMessage('modal.common.add')}
|
{getMessage('modal.common.add')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-option-wrap">
|
<div className="grid-option-overflow">
|
||||||
{currentRoofList.map((roof, index) => {
|
<div className="grid-option-wrap">
|
||||||
return (
|
{currentRoofList.map((roof, index) => {
|
||||||
<div className="grid-option-box" key={index}>
|
return (
|
||||||
<div className="d-check-radio pop no-text">
|
<div className="grid-option-box" key={index}>
|
||||||
<input type="radio" name="radio01" checked={roof.selected && 'checked'} readOnly={true} />
|
<div className="d-check-radio pop no-text">
|
||||||
<label
|
<input type="radio" name="radio01" checked={roof.selected && 'checked'} readOnly={true} />
|
||||||
htmlFor="ra01"
|
<label
|
||||||
onClick={(e) => {
|
htmlFor="ra01"
|
||||||
handleDefaultRoofMaterial(index)
|
onClick={(e) => {
|
||||||
}}
|
handleDefaultRoofMaterial(index)
|
||||||
></label>
|
}}
|
||||||
</div>
|
></label>
|
||||||
<div className="grid-option-block-form">
|
|
||||||
<div className="block-box">
|
|
||||||
<div className="flex-ment">
|
|
||||||
<div className="grid-select" style={{ width: '248px' }}>
|
|
||||||
<QSelectBox
|
|
||||||
options={roofMaterials}
|
|
||||||
value={roof}
|
|
||||||
showKey={'roofMatlNm'}
|
|
||||||
sourceKey={'roofMatlCd'}
|
|
||||||
targetKey={'roofMatlCd'}
|
|
||||||
onChange={(e) => handleChangeRoofMaterial(e, index)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{index === 0 && <span className="dec">{getMessage('modal.roof.alloc.default.roof.material')}</span>}
|
|
||||||
{index !== 0 && <button className="delete" onClick={() => onDeleteRoofMaterial(index)}></button>}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{(roof.widAuth || roof.lenAuth) && (
|
<div className="grid-option-block-form">
|
||||||
<div className="block-box">
|
<div className="block-box">
|
||||||
{roof.widAuth && (
|
<div className="flex-ment">
|
||||||
<div className="flex-ment">
|
<div className="grid-select" style={{ width: '248px' }}>
|
||||||
<span>W</span>
|
<QSelectBox
|
||||||
<div className="input-grid" style={{ width: '100px' }}>
|
options={roofMaterials}
|
||||||
<input type="text" className="input-origin block" defaultValue={roof.width} readOnly={roof.widAuth === 'R'} />
|
value={roof}
|
||||||
</div>
|
showKey={'roofMatlNm'}
|
||||||
|
sourceKey={'roofMatlCd'}
|
||||||
|
targetKey={'roofMatlCd'}
|
||||||
|
onChange={(e) => handleChangeRoofMaterial(e, index)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
{index === 0 && <span className="dec">{getMessage('modal.roof.alloc.default.roof.material')}</span>}
|
||||||
{roof.lenAuth && (
|
{index !== 0 && <button className="delete" onClick={() => onDeleteRoofMaterial(index)}></button>}
|
||||||
<div className="flex-ment">
|
</div>
|
||||||
<span>L</span>
|
|
||||||
<div className="input-grid" style={{ width: '100px' }}>
|
|
||||||
<input type="text" className="input-origin block" defaultValue={roof.length} readOnly={roof.lenAuth === 'R'} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
{(roof.widAuth || roof.lenAuth) && (
|
||||||
{(roof.raftAuth || roof.roofPchAuth) && (
|
<div className="block-box">
|
||||||
<div className="block-box">
|
{roof.widAuth && (
|
||||||
{roof.raftAuth && (
|
|
||||||
<div className="block-box">
|
|
||||||
<div className="flex-ment">
|
<div className="flex-ment">
|
||||||
<span>{getMessage('modal.placement.initial.setting.rafter')}</span>
|
<span>W</span>
|
||||||
{raftCodes.length > 0 && (
|
<div className="input-grid" style={{ width: '100px' }}>
|
||||||
<div className="grid-select" style={{ width: '160px' }}>
|
<input type="text" className="input-origin block" defaultValue={roof.width} readOnly={roof.widAuth === 'R'} />
|
||||||
<QSelectBox
|
|
||||||
options={raftCodes}
|
|
||||||
value={roof}
|
|
||||||
showKey={'clCodeNm'}
|
|
||||||
sourceKey={'clCode'}
|
|
||||||
targetKey={roof.raft ? 'raft' : 'raftBaseCd'}
|
|
||||||
onChange={(e) => handleChangeRaft(e, index)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{roof.roofPchAuth && (
|
|
||||||
<div className="block-box">
|
|
||||||
<div className="flex-ment">
|
|
||||||
<span>{getMessage('hajebichi')}</span>
|
|
||||||
<div className="input-grid" style={{ width: '84px' }}>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="input-origin block"
|
|
||||||
value={parseInt(roof.hajebichi)}
|
|
||||||
readOnly={roof.roofPchAuth === 'R'}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
{roof.lenAuth && (
|
||||||
</div>
|
<div className="flex-ment">
|
||||||
)}
|
<span>L</span>
|
||||||
<div className="block-box">
|
<div className="input-grid" style={{ width: '100px' }}>
|
||||||
<div className="icon-btn-wrap">
|
<input type="text" className="input-origin block" defaultValue={roof.length} readOnly={roof.lenAuth === 'R'} />
|
||||||
<button
|
</div>
|
||||||
className={roof.layout === ROOF_MATERIAL_LAYOUT.PARALLEL ? 'act' : ''}
|
</div>
|
||||||
onClick={() => {
|
)}
|
||||||
handleChangeLayout(ROOF_MATERIAL_LAYOUT.PARALLEL, index)
|
</div>
|
||||||
}}
|
)}
|
||||||
>
|
{(roof.raftAuth || roof.roofPchAuth) && (
|
||||||
{getMessage('modal.roof.alloc.select.parallel')}
|
<div className="block-box">
|
||||||
<i className="allocation01"></i>
|
{roof.raftAuth && (
|
||||||
</button>
|
<div className="block-box">
|
||||||
<button
|
<div className="flex-ment">
|
||||||
className={roof.layout === ROOF_MATERIAL_LAYOUT.STAIRS ? 'act' : ''}
|
<span>{getMessage('modal.placement.initial.setting.rafter')}</span>
|
||||||
onClick={() => {
|
{raftCodes.length > 0 && (
|
||||||
handleChangeLayout(ROOF_MATERIAL_LAYOUT.STAIRS, index)
|
<div className="grid-select" style={{ width: '160px' }}>
|
||||||
}}
|
<QSelectBox
|
||||||
>
|
options={raftCodes}
|
||||||
{getMessage('modal.roof.alloc.select.stairs')} <i className="allocation02"></i>
|
value={roof}
|
||||||
</button>
|
showKey={'clCodeNm'}
|
||||||
|
sourceKey={'clCode'}
|
||||||
|
targetKey={roof.raft ? 'raft' : 'raftBaseCd'}
|
||||||
|
onChange={(e) => handleChangeRaft(e, index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{roof.roofPchAuth && (
|
||||||
|
<div className="block-box">
|
||||||
|
<div className="flex-ment">
|
||||||
|
<span>{getMessage('hajebichi')}</span>
|
||||||
|
<div className="input-grid" style={{ width: '84px' }}>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="input-origin block"
|
||||||
|
value={parseInt(roof.hajebichi)}
|
||||||
|
readOnly={roof.roofPchAuth === 'R'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="block-box">
|
||||||
|
<div className="icon-btn-wrap">
|
||||||
|
<button
|
||||||
|
className={roof.layout === ROOF_MATERIAL_LAYOUT.PARALLEL ? 'act' : ''}
|
||||||
|
onClick={() => {
|
||||||
|
handleChangeLayout(ROOF_MATERIAL_LAYOUT.PARALLEL, index)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{getMessage('modal.roof.alloc.select.parallel')}
|
||||||
|
<i className="allocation01"></i>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={roof.layout === ROOF_MATERIAL_LAYOUT.STAIRS ? 'act' : ''}
|
||||||
|
onClick={() => {
|
||||||
|
handleChangeLayout(ROOF_MATERIAL_LAYOUT.STAIRS, index)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{getMessage('modal.roof.alloc.select.stairs')} <i className="allocation02"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
)
|
})}
|
||||||
})}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act" onClick={handleSave}>
|
<button className="btn-frame modal act" onClick={handleSave}>
|
||||||
|
|||||||
@ -7,15 +7,6 @@ export default function Gable({ offsetRef, pitchRef, pitchText }) {
|
|||||||
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
|
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="outline-form mb10">
|
|
||||||
<span className="mr10" style={{ width: '63px' }}>
|
|
||||||
{getMessage('slope')}
|
|
||||||
</span>
|
|
||||||
<div className="input-grid mr5">
|
|
||||||
<input type="text" className="input-origin block" defaultValue={currentAngleType === ANGLE_TYPE.SLOPE ? 4 : 21.8} ref={pitchRef} />
|
|
||||||
</div>
|
|
||||||
<span className="thin">{pitchText}</span>
|
|
||||||
</div>
|
|
||||||
<div className="outline-form mb10">
|
<div className="outline-form mb10">
|
||||||
<span className="mr10" style={{ width: '63px' }}>
|
<span className="mr10" style={{ width: '63px' }}>
|
||||||
{getMessage('gable.offset')}
|
{getMessage('gable.offset')}
|
||||||
|
|||||||
@ -1,12 +1,10 @@
|
|||||||
import React, { useState } from 'react'
|
import React from 'react'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useForm } from 'react-hook-form'
|
import { useForm } from 'react-hook-form'
|
||||||
import { sessionStore } from '@/store/commonAtom'
|
import { sessionStore } from '@/store/commonAtom'
|
||||||
import { useRecoilValue, useRecoilState } from 'recoil'
|
import { useRecoilValue, useRecoilState } from 'recoil'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
import { useRouter } from 'next/navigation'
|
|
||||||
import { setSession } from '@/lib/authActions'
|
|
||||||
import { logout } from '@/lib/authActions'
|
import { logout } from '@/lib/authActions'
|
||||||
export default function ChangePasswordPop(props) {
|
export default function ChangePasswordPop(props) {
|
||||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||||
@ -14,7 +12,6 @@ export default function ChangePasswordPop(props) {
|
|||||||
const { patch } = useAxios(globalLocaleState)
|
const { patch } = useAxios(globalLocaleState)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const [sessionState, setSessionState] = useRecoilState(sessionStore)
|
const [sessionState, setSessionState] = useRecoilState(sessionStore)
|
||||||
const router = useRouter()
|
|
||||||
const formInitValue = {
|
const formInitValue = {
|
||||||
password1: '',
|
password1: '',
|
||||||
password2: '',
|
password2: '',
|
||||||
@ -56,6 +53,16 @@ export default function ChangePasswordPop(props) {
|
|||||||
const _password1 = form.watch('password1')
|
const _password1 = form.watch('password1')
|
||||||
const _password2 = form.watch('password2')
|
const _password2 = form.watch('password2')
|
||||||
|
|
||||||
|
//비밀번호 미입력시
|
||||||
|
if (_password1.trim() === '') {
|
||||||
|
alert(getMessage('main.popup.login.validate3'))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (_password2.trim() === '') {
|
||||||
|
alert(getMessage('main.popup.login.validate3'))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
if (_password1 !== _password2) {
|
if (_password1 !== _password2) {
|
||||||
alert(getMessage('main.popup.login.validate1'))
|
alert(getMessage('main.popup.login.validate1'))
|
||||||
return false
|
return false
|
||||||
@ -78,10 +85,6 @@ export default function ChangePasswordPop(props) {
|
|||||||
if (res?.result?.resultCode === 'S') {
|
if (res?.result?.resultCode === 'S') {
|
||||||
alert(getMessage('main.popup.login.success'))
|
alert(getMessage('main.popup.login.success'))
|
||||||
logout()
|
logout()
|
||||||
//로그인 화면으로 이동해서 다시 로그인해야되서 setSessionState필요없음
|
|
||||||
// setSessionState({ ...sessionState, pwdInitYn: 'Y' })
|
|
||||||
//props.setChagePasswordPopOpen(false)
|
|
||||||
//router.push('/login')
|
|
||||||
} else {
|
} else {
|
||||||
alert(res?.result?.resultMsg)
|
alert(res?.result?.resultMsg)
|
||||||
}
|
}
|
||||||
@ -110,10 +113,7 @@ export default function ChangePasswordPop(props) {
|
|||||||
<div className="table-item">
|
<div className="table-item">
|
||||||
<div className="table-item-th">
|
<div className="table-item-th">
|
||||||
<div className="change-password-tit">
|
<div className="change-password-tit">
|
||||||
<div className="tit-b">
|
<div className="tit-b">{getMessage('main.popup.login.newPassword1')}</div>
|
||||||
{getMessage('main.popup.login.newPassword1')}
|
|
||||||
<span className="important">*</span>
|
|
||||||
</div>
|
|
||||||
<div className="tit-s">{getMessage('main.popup.login.placeholder')}</div>
|
<div className="tit-s">{getMessage('main.popup.login.placeholder')}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -133,10 +133,7 @@ export default function ChangePasswordPop(props) {
|
|||||||
<div className="table-item">
|
<div className="table-item">
|
||||||
<div className="table-item-th">
|
<div className="table-item-th">
|
||||||
<div className="change-password-tit">
|
<div className="change-password-tit">
|
||||||
<div className="tit-b">
|
<div className="tit-b">{getMessage('main.popup.login.newPassword2')}</div>
|
||||||
{getMessage('main.popup.login.newPassword2')}
|
|
||||||
<span className="important">*</span>
|
|
||||||
</div>
|
|
||||||
<div className="tit-s">{getMessage('main.popup.login.placeholder')}</div>
|
<div className="tit-s">{getMessage('main.popup.login.placeholder')}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -169,7 +166,6 @@ export default function ChangePasswordPop(props) {
|
|||||||
className="btn-origin grey"
|
className="btn-origin grey"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
logout()
|
logout()
|
||||||
// router.push('/login')
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{getMessage('main.popup.login.btn2')}
|
{getMessage('main.popup.login.btn2')}
|
||||||
|
|||||||
@ -11,11 +11,13 @@ import { useRouter } from 'next/navigation'
|
|||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
import { queryStringFormatter } from '@/util/common-utils'
|
import { queryStringFormatter } from '@/util/common-utils'
|
||||||
import MainSkeleton from '../ui/MainSkeleton'
|
import MainSkeleton from '../ui/MainSkeleton'
|
||||||
import { SessionContext } from '@/app/SessionProvider'
|
|
||||||
import { useMainContentsController } from '@/hooks/main/useMainContentsController'
|
import { useMainContentsController } from '@/hooks/main/useMainContentsController'
|
||||||
import { QcastContext } from '@/app/QcastProvider'
|
import { QcastContext } from '@/app/QcastProvider'
|
||||||
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
|
|
||||||
export default function MainContents() {
|
export default function MainContents() {
|
||||||
|
const { swalFire } = useSwal()
|
||||||
|
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||||
@ -85,7 +87,6 @@ export default function MainContents() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('qcastState:::', qcastState?.businessCharger)
|
|
||||||
return (
|
return (
|
||||||
<div className="main-product-list-wrap">
|
<div className="main-product-list-wrap">
|
||||||
<div className="main-product-list">
|
<div className="main-product-list">
|
||||||
@ -116,67 +117,60 @@ export default function MainContents() {
|
|||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<div className="recently-no-data">
|
||||||
// <MainSkeleton count={6} />
|
<h3>{getMessage('main.content.objectList.noData1')}</h3>
|
||||||
|
<p>{getMessage('main.content.objectList.noData2')}</p>
|
||||||
|
<button type="button" className="btn-origin navy" onClick={() => router.push('/management/stuff/tempReg')}>
|
||||||
|
+ {getMessage('stuff.search.btn.register')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</ProductItem>
|
</ProductItem>
|
||||||
<ProductItem num={2} name={getMessage('main.content.notice')}>
|
<ProductItem num={2} name={getMessage('main.content.notice')}>
|
||||||
<div className="notice-box">
|
{recentNoticeList.length > 0 ? (
|
||||||
{recentNoticeList.length > 0 ? (
|
<div className="notice-box">
|
||||||
<>
|
<div className="notice-day pre">{dayjs(recentNoticeList[0]?.regDt).format('YYYY.MM.DD')}</div>
|
||||||
<div className="notice-day pre">{dayjs(recentNoticeList[0]?.regDt).format('YYYY.MM.DD')}</div>
|
<div className="notice-title">{recentNoticeList[0]?.title}</div>
|
||||||
<div className="notice-title">{recentNoticeList[0]?.title}</div>
|
<div
|
||||||
<div
|
className="notice-contents"
|
||||||
className="notice-contents"
|
dangerouslySetInnerHTML={{ __html: recentNoticeList[0]?.contents ? recentNoticeList[0].contents.replaceAll('\n', '<br/>') : '' }}
|
||||||
dangerouslySetInnerHTML={{ __html: recentNoticeList[0]?.contents ? recentNoticeList[0].contents.replaceAll('\n', '<br/>') : '' }}
|
></div>
|
||||||
></div>
|
</div>
|
||||||
</>
|
) : (
|
||||||
) : (
|
<div className="recently-no-data">
|
||||||
<MainSkeleton count={5} />
|
<h3>{getMessage('main.content.noBusiness')}</h3>
|
||||||
)}
|
</div>
|
||||||
</div>
|
)}
|
||||||
</ProductItem>
|
</ProductItem>
|
||||||
</div>
|
</div>
|
||||||
<div className="main-product-list">
|
<div className="main-product-list">
|
||||||
<ProductItem num={3} name={getMessage('main.faq')}>
|
<ProductItem num={3} name={getMessage('main.faq')}>
|
||||||
<ul className="faq-list">
|
{recentFaqList.length > 0 ? (
|
||||||
{recentFaqList.length > 0 ? (
|
<ul className="faq-list">
|
||||||
<>
|
{recentFaqList.map((row) => {
|
||||||
{recentFaqList.map((row) => {
|
return (
|
||||||
return (
|
<li key={row.rowNumber} className="faq-item">
|
||||||
<li key={row.rowNumber} className="faq-item">
|
<div className="faq-item-inner">
|
||||||
<div className="faq-item-inner">
|
<div className="faq-num pre">FAQ {row.totCnt - row.rowNumber}</div>
|
||||||
<div className="faq-num pre">FAQ {row.rowNumber}</div>
|
<div className="faq-title pre">{row.title}</div>
|
||||||
<div className="faq-title pre">{row.title}</div>
|
<div className="faq-day pre">{dayjs(row.regDt).format('YYYY.MM.DD')}</div>
|
||||||
<div className="faq-day pre">{dayjs(row.regDt).format('YYYY.MM.DD')}</div>
|
</div>
|
||||||
</div>
|
</li>
|
||||||
</li>
|
)
|
||||||
)
|
})}
|
||||||
})}
|
</ul>
|
||||||
</>
|
) : (
|
||||||
) : (
|
<div className="recently-no-data">
|
||||||
<MainSkeleton count={2} />
|
<h3>{getMessage('main.content.noBusiness')}</h3>
|
||||||
)}
|
</div>
|
||||||
</ul>
|
)}
|
||||||
</ProductItem>
|
</ProductItem>
|
||||||
<ProductItem num={4} name={'Data Download'}>
|
<ProductItem num={4} name={'Data Download'}>
|
||||||
<div className="data-download-wrap">
|
<div className="data-download-wrap">
|
||||||
<button
|
<button className="data-down" type="button" onClick={() => swalFire({ text: getMessage('main.content.alert.noFile'), type: 'alert' })}>
|
||||||
className="data-down"
|
|
||||||
type="button"
|
|
||||||
onClick={() => {
|
|
||||||
return alert(getMessage('main.content.alert.noFile'))
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span>{getMessage('main.content.download1')}</span>
|
<span>{getMessage('main.content.download1')}</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button className="data-down" type="button" onClick={() => swalFire({ text: getMessage('main.content.alert.noFile'), type: 'alert' })}>
|
||||||
className="data-down"
|
|
||||||
type="button"
|
|
||||||
onClick={() => {
|
|
||||||
return alert(getMessage('main.content.alert.noFile'))
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span>{getMessage('main.content.download2')}</span>
|
<span>{getMessage('main.content.download2')}</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -30,7 +30,7 @@ export default function Stuff() {
|
|||||||
const [pageNo, setPageNo] = useState(1) //현재 페이지 번호
|
const [pageNo, setPageNo] = useState(1) //현재 페이지 번호
|
||||||
const [pageSize, setPageSize] = useState(100) //페이지 당 게시물 수
|
const [pageSize, setPageSize] = useState(100) //페이지 당 게시물 수
|
||||||
const [totalCount, setTotalCount] = useState(0) //총 갯수
|
const [totalCount, setTotalCount] = useState(0) //총 갯수
|
||||||
const [defaultSortType, setDefaultSortType] = useState('R')
|
const [defaultSortType, setDefaultSortType] = useState('U')
|
||||||
|
|
||||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||||
const { get } = useAxios(globalLocaleState)
|
const { get } = useAxios(globalLocaleState)
|
||||||
@ -207,6 +207,7 @@ export default function Stuff() {
|
|||||||
schReceiveUser: stuffSearchParams?.schReceiveUser,
|
schReceiveUser: stuffSearchParams?.schReceiveUser,
|
||||||
schDispCompanyName: stuffSearchParams?.schDispCompanyName,
|
schDispCompanyName: stuffSearchParams?.schDispCompanyName,
|
||||||
schDateType: stuffSearchParams.schDateType,
|
schDateType: stuffSearchParams.schDateType,
|
||||||
|
schTempFlg: stuffSearchParams.schTempFlg, //임시저장 물건
|
||||||
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
|
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
|
||||||
schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
|
schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
|
||||||
startRow: (stuffSearch.pageNo - 1) * stuffSearchParams.pageSize + 1,
|
startRow: (stuffSearch.pageNo - 1) * stuffSearchParams.pageSize + 1,
|
||||||
@ -249,12 +250,13 @@ export default function Stuff() {
|
|||||||
schReceiveUser: '',
|
schReceiveUser: '',
|
||||||
schDispCompanyName: '',
|
schDispCompanyName: '',
|
||||||
schDateType: 'U',
|
schDateType: 'U',
|
||||||
|
schTempFlg: '',
|
||||||
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
|
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
|
||||||
schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
|
schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
|
||||||
startRow: (pageNo - 1) * pageSize + 1,
|
startRow: (pageNo - 1) * pageSize + 1,
|
||||||
endRow: pageNo * pageSize,
|
endRow: pageNo * pageSize,
|
||||||
schSelSaleStoreId: stuffSearchParams?.schOtherSelSaleStoreId ? stuffSearchParams.schOtherSelSaleStoreId : stuffSearchParams.schSelSaleStoreId,
|
schSelSaleStoreId: stuffSearchParams?.schOtherSelSaleStoreId ? stuffSearchParams.schOtherSelSaleStoreId : stuffSearchParams.schSelSaleStoreId,
|
||||||
schSortType: 'R',
|
schSortType: 'U',
|
||||||
code: 'E',
|
code: 'E',
|
||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
pageSize: 100,
|
pageSize: 100,
|
||||||
@ -322,13 +324,14 @@ export default function Stuff() {
|
|||||||
schReceiveUser: '',
|
schReceiveUser: '',
|
||||||
schDispCompanyName: '',
|
schDispCompanyName: '',
|
||||||
schDateType: 'U',
|
schDateType: 'U',
|
||||||
|
schTempFlg: '',
|
||||||
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
|
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
|
||||||
schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
|
schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
|
||||||
startRow: 1,
|
startRow: 1,
|
||||||
endRow: 100,
|
endRow: 100,
|
||||||
schSelSaleStoreId: '',
|
schSelSaleStoreId: '',
|
||||||
schOtherSelSaleStoreId: '',
|
schOtherSelSaleStoreId: '',
|
||||||
schSortType: 'R',
|
schSortType: 'U',
|
||||||
code: 'S',
|
code: 'S',
|
||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
pageSize: 100,
|
pageSize: 100,
|
||||||
@ -438,8 +441,8 @@ export default function Stuff() {
|
|||||||
<div className="left-unit-box">
|
<div className="left-unit-box">
|
||||||
<div className="select-box mr5" style={{ width: '110px' }}>
|
<div className="select-box mr5" style={{ width: '110px' }}>
|
||||||
<select className="select-light black" onChange={onChangeSortType} value={stuffSearch.schSortType}>
|
<select className="select-light black" onChange={onChangeSortType} value={stuffSearch.schSortType}>
|
||||||
<option value="R">{getMessage('stuff.search.grid.schSortTypeR')}</option>
|
|
||||||
<option value="U">{getMessage('stuff.search.grid.schSortTypeU')}</option>
|
<option value="U">{getMessage('stuff.search.grid.schSortTypeU')}</option>
|
||||||
|
<option value="R">{getMessage('stuff.search.grid.schSortTypeR')}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="select-box" style={{ width: '80px' }}>
|
<div className="select-box" style={{ width: '80px' }}>
|
||||||
|
|||||||
@ -53,7 +53,7 @@ export default function StuffDetail() {
|
|||||||
const formInitValue = {
|
const formInitValue = {
|
||||||
// 물건번호 T...(임시) R...(진짜)
|
// 물건번호 T...(임시) R...(진짜)
|
||||||
planReqNo: '', //설계의뢰No
|
planReqNo: '', //설계의뢰No
|
||||||
receiveUser: '', //담당자
|
receiveUser: session?.userNm, //담당자 로그인사용자명 디폴트
|
||||||
objectStatusId: '0', //물건구분(신축:0 기축 : 1)
|
objectStatusId: '0', //물건구분(신축:0 기축 : 1)
|
||||||
objectName: '', //물건명
|
objectName: '', //물건명
|
||||||
objectNameOmit: '', //경칭선택
|
objectNameOmit: '', //경칭선택
|
||||||
@ -1745,7 +1745,7 @@ export default function StuffDetail() {
|
|||||||
onChange={onSelectionChange2}
|
onChange={onSelectionChange2}
|
||||||
getOptionLabel={(x) => x.saleStoreName}
|
getOptionLabel={(x) => x.saleStoreName}
|
||||||
getOptionValue={(x) => x.saleStoreId}
|
getOptionValue={(x) => x.saleStoreId}
|
||||||
isDisabled={otherSaleStoreList.length > 1 ? false : true}
|
isDisabled={otherSaleStoreList != null && otherSaleStoreList.length > 0 ? false : true}
|
||||||
isClearable={true}
|
isClearable={true}
|
||||||
value={otherSaleStoreList.filter(function (option) {
|
value={otherSaleStoreList.filter(function (option) {
|
||||||
return option.saleStoreId === otherSelOptions
|
return option.saleStoreId === otherSelOptions
|
||||||
|
|||||||
@ -60,6 +60,7 @@ export default function StuffSearchCondition() {
|
|||||||
const [schSelSaleStoreId, setSchSelSaleStoreId] = useState('') //판매대리점 선택
|
const [schSelSaleStoreId, setSchSelSaleStoreId] = useState('') //판매대리점 선택
|
||||||
const [receiveUser, setReceiveUser] = useState('') //담당자
|
const [receiveUser, setReceiveUser] = useState('') //담당자
|
||||||
const [dateType, setDateType] = useState('U') //갱신일(U)/등록일(R)
|
const [dateType, setDateType] = useState('U') //갱신일(U)/등록일(R)
|
||||||
|
const [tempFlg, setTempFlg] = useState('') //임시저장여부
|
||||||
|
|
||||||
const [schSelSaleStoreList, setSchSelSaleStoreList] = useState([]) //판매대리점 자동완성 SELECT 전체
|
const [schSelSaleStoreList, setSchSelSaleStoreList] = useState([]) //판매대리점 자동완성 SELECT 전체
|
||||||
const [favoriteStoreList, setFavoriteStoreList] = useState([]) //즐겨찾기한 판매점목록
|
const [favoriteStoreList, setFavoriteStoreList] = useState([]) //즐겨찾기한 판매점목록
|
||||||
@ -95,12 +96,13 @@ export default function StuffSearchCondition() {
|
|||||||
schOtherSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? stuffSearch.schOtherSelSaleStoreId : '',
|
schOtherSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? stuffSearch.schOtherSelSaleStoreId : '',
|
||||||
schReceiveUser: receiveUser ? receiveUser.trim() : '',
|
schReceiveUser: receiveUser ? receiveUser.trim() : '',
|
||||||
schDateType: dateType,
|
schDateType: dateType,
|
||||||
|
schTempFlg: tempFlg, //임시저장물건
|
||||||
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
||||||
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
||||||
code: 'E',
|
code: 'E',
|
||||||
startRow: 1,
|
startRow: 1,
|
||||||
endRow: 1 * stuffSearch?.pageSize,
|
endRow: 1 * stuffSearch?.pageSize,
|
||||||
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'R',
|
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'U',
|
||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
pageSize: stuffSearch?.pageSize,
|
pageSize: stuffSearch?.pageSize,
|
||||||
})
|
})
|
||||||
@ -115,12 +117,13 @@ export default function StuffSearchCondition() {
|
|||||||
schOtherSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? stuffSearch.schOtherSelSaleStoreId : '',
|
schOtherSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? stuffSearch.schOtherSelSaleStoreId : '',
|
||||||
schReceiveUser: receiveUser ? receiveUser.trim() : '',
|
schReceiveUser: receiveUser ? receiveUser.trim() : '',
|
||||||
schDateType: dateType,
|
schDateType: dateType,
|
||||||
|
schTempFlg: tempFlg, //임시저장물건
|
||||||
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
||||||
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
||||||
code: 'E',
|
code: 'E',
|
||||||
startRow: stuffSearch?.startRow ? stuffSearch.startRow : 1,
|
startRow: stuffSearch?.startRow ? stuffSearch.startRow : 1,
|
||||||
endRow: stuffSearch?.endRow ? stuffSearch.endRow : 100,
|
endRow: stuffSearch?.endRow ? stuffSearch.endRow : 100,
|
||||||
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'R',
|
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'U',
|
||||||
pageNo: stuffSearch?.pageNo,
|
pageNo: stuffSearch?.pageNo,
|
||||||
pageSize: stuffSearch?.pageSize,
|
pageSize: stuffSearch?.pageSize,
|
||||||
})
|
})
|
||||||
@ -136,12 +139,13 @@ export default function StuffSearchCondition() {
|
|||||||
schOtherSelSaleStoreId: otherSaleStoreId,
|
schOtherSelSaleStoreId: otherSaleStoreId,
|
||||||
schReceiveUser: receiveUser.trim(),
|
schReceiveUser: receiveUser.trim(),
|
||||||
schDateType: dateType,
|
schDateType: dateType,
|
||||||
|
schTempFlg: tempFlg, //임시저장물건
|
||||||
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
||||||
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
||||||
code: 'E',
|
code: 'E',
|
||||||
startRow: 1,
|
startRow: 1,
|
||||||
endRow: 100,
|
endRow: 100,
|
||||||
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'R',
|
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'U',
|
||||||
})
|
})
|
||||||
} else if (stuffSearch.code === 'E') {
|
} else if (stuffSearch.code === 'E') {
|
||||||
if (session.storeId !== 'T01' && session.storeLvl === '1') {
|
if (session.storeId !== 'T01' && session.storeLvl === '1') {
|
||||||
@ -155,12 +159,13 @@ export default function StuffSearchCondition() {
|
|||||||
schOtherSelSaleStoreId: otherSaleStoreId,
|
schOtherSelSaleStoreId: otherSaleStoreId,
|
||||||
schReceiveUser: stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser.trim() : receiveUser.trim(),
|
schReceiveUser: stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser.trim() : receiveUser.trim(),
|
||||||
schDateType: dateType,
|
schDateType: dateType,
|
||||||
|
schTempFlg: tempFlg, //임시저장물건
|
||||||
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
||||||
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
||||||
code: 'E',
|
code: 'E',
|
||||||
startRow: stuffSearch?.startRow ? stuffSearch.startRow : 1,
|
startRow: stuffSearch?.startRow ? stuffSearch.startRow : 1,
|
||||||
endRow: stuffSearch?.endRow ? stuffSearch.endRow : 100,
|
endRow: stuffSearch?.endRow ? stuffSearch.endRow : 100,
|
||||||
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'R',
|
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'U',
|
||||||
pageNo: stuffSearch?.pageNo,
|
pageNo: stuffSearch?.pageNo,
|
||||||
pageSize: stuffSearch?.pageSize,
|
pageSize: stuffSearch?.pageSize,
|
||||||
})
|
})
|
||||||
@ -176,12 +181,13 @@ export default function StuffSearchCondition() {
|
|||||||
schOtherSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? stuffSearch.schOtherSelSaleStoreId : '',
|
schOtherSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? stuffSearch.schOtherSelSaleStoreId : '',
|
||||||
schReceiveUser: receiveUser ? receiveUser.trim() : '',
|
schReceiveUser: receiveUser ? receiveUser.trim() : '',
|
||||||
schDateType: dateType,
|
schDateType: dateType,
|
||||||
|
schTempFlg: tempFlg, //임시저장물건
|
||||||
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
||||||
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
||||||
code: 'E',
|
code: 'E',
|
||||||
startRow: 1,
|
startRow: 1,
|
||||||
endRow: 1 * stuffSearch?.pageSize,
|
endRow: 1 * stuffSearch?.pageSize,
|
||||||
schSortType: 'R',
|
schSortType: 'U',
|
||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
pageSize: stuffSearch?.pageSize,
|
pageSize: stuffSearch?.pageSize,
|
||||||
})
|
})
|
||||||
@ -196,12 +202,13 @@ export default function StuffSearchCondition() {
|
|||||||
schOtherSelSaleStoreId: otherSaleStoreId,
|
schOtherSelSaleStoreId: otherSaleStoreId,
|
||||||
schReceiveUser: stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser.trim() : receiveUser.trim(),
|
schReceiveUser: stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser.trim() : receiveUser.trim(),
|
||||||
schDateType: dateType,
|
schDateType: dateType,
|
||||||
|
schTempFlg: tempFlg, //임시저장물건
|
||||||
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
||||||
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
||||||
code: 'E',
|
code: 'E',
|
||||||
startRow: stuffSearch?.startRow ? stuffSearch.startRow : 1,
|
startRow: stuffSearch?.startRow ? stuffSearch.startRow : 1,
|
||||||
endRow: stuffSearch?.endRow ? stuffSearch.endRow : 100,
|
endRow: stuffSearch?.endRow ? stuffSearch.endRow : 100,
|
||||||
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'R',
|
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'U',
|
||||||
pageNo: stuffSearch?.pageNo,
|
pageNo: stuffSearch?.pageNo,
|
||||||
pageSize: stuffSearch?.pageSize,
|
pageSize: stuffSearch?.pageSize,
|
||||||
})
|
})
|
||||||
@ -217,12 +224,13 @@ export default function StuffSearchCondition() {
|
|||||||
schOtherSelSaleStoreId: otherSaleStoreId,
|
schOtherSelSaleStoreId: otherSaleStoreId,
|
||||||
schReceiveUser: stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser.trim() : receiveUser.trim(),
|
schReceiveUser: stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser.trim() : receiveUser.trim(),
|
||||||
schDateType: dateType,
|
schDateType: dateType,
|
||||||
|
schTempFlg: tempFlg, //임시저장물건
|
||||||
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
||||||
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
||||||
code: 'E',
|
code: 'E',
|
||||||
startRow: stuffSearch?.startRow ? stuffSearch.startRow : 1,
|
startRow: stuffSearch?.startRow ? stuffSearch.startRow : 1,
|
||||||
endRow: stuffSearch?.endRow ? stuffSearch.endRow : 100,
|
endRow: stuffSearch?.endRow ? stuffSearch.endRow : 100,
|
||||||
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'R',
|
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'U',
|
||||||
pageNo: stuffSearch?.pageNo,
|
pageNo: stuffSearch?.pageNo,
|
||||||
pageSize: stuffSearch?.pageSize,
|
pageSize: stuffSearch?.pageSize,
|
||||||
})
|
})
|
||||||
@ -238,12 +246,13 @@ export default function StuffSearchCondition() {
|
|||||||
schOtherSelSaleStoreId: otherSaleStoreId,
|
schOtherSelSaleStoreId: otherSaleStoreId,
|
||||||
schReceiveUser: receiveUser.trim(),
|
schReceiveUser: receiveUser.trim(),
|
||||||
schDateType: dateType,
|
schDateType: dateType,
|
||||||
|
schTempFlg: tempFlg, //임시저장물건
|
||||||
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
schFromDt: startDate ? dayjs(startDate).format('YYYY-MM-DD') : '',
|
||||||
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
schToDt: endDate ? dayjs(endDate).format('YYYY-MM-DD') : '',
|
||||||
code: 'E',
|
code: 'E',
|
||||||
startRow: stuffSearch?.startRow ? stuffSearch.startRow : 1,
|
startRow: stuffSearch?.startRow ? stuffSearch.startRow : 1,
|
||||||
endRow: stuffSearch?.endRow ? stuffSearch.endRow : 100,
|
endRow: stuffSearch?.endRow ? stuffSearch.endRow : 100,
|
||||||
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'R',
|
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'U',
|
||||||
pageNo: stuffSearch?.pageNo,
|
pageNo: stuffSearch?.pageNo,
|
||||||
pageSize: stuffSearch?.pageSize,
|
pageSize: stuffSearch?.pageSize,
|
||||||
})
|
})
|
||||||
@ -261,6 +270,7 @@ export default function StuffSearchCondition() {
|
|||||||
dispCompanyNameRef.current.value = ''
|
dispCompanyNameRef.current.value = ''
|
||||||
receiveUserRef.current.value = ''
|
receiveUserRef.current.value = ''
|
||||||
stuffSearch.schDateType = 'U'
|
stuffSearch.schDateType = 'U'
|
||||||
|
stuffSearch.schTempFlg = ''
|
||||||
setObjectNo('')
|
setObjectNo('')
|
||||||
setAddress('')
|
setAddress('')
|
||||||
setobjectName('')
|
setobjectName('')
|
||||||
@ -268,6 +278,7 @@ export default function StuffSearchCondition() {
|
|||||||
setReceiveUser('')
|
setReceiveUser('')
|
||||||
setDispCompanyName('')
|
setDispCompanyName('')
|
||||||
setDateType('U')
|
setDateType('U')
|
||||||
|
setTempFlg('')
|
||||||
setStartDate(dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'))
|
setStartDate(dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'))
|
||||||
setEndDate(dayjs(new Date()).format('YYYY-MM-DD'))
|
setEndDate(dayjs(new Date()).format('YYYY-MM-DD'))
|
||||||
if (session?.storeId === 'T01') {
|
if (session?.storeId === 'T01') {
|
||||||
@ -285,12 +296,12 @@ export default function StuffSearchCondition() {
|
|||||||
schSelSaleStoreId: '',
|
schSelSaleStoreId: '',
|
||||||
schOtherSelSaleStoreId: '',
|
schOtherSelSaleStoreId: '',
|
||||||
schDateType: 'U',
|
schDateType: 'U',
|
||||||
|
schTempFlg: '',
|
||||||
startRow: 1,
|
startRow: 1,
|
||||||
endRow: 100,
|
endRow: 100,
|
||||||
schSortType: 'R',
|
schSortType: 'U',
|
||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
pageSize: 100,
|
pageSize: 100,
|
||||||
// code: 'S',
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
if (otherSaleStoreList.length > 1) {
|
if (otherSaleStoreList.length > 1) {
|
||||||
@ -303,10 +314,11 @@ export default function StuffSearchCondition() {
|
|||||||
stuffSearch.schReceiveUser = ''
|
stuffSearch.schReceiveUser = ''
|
||||||
stuffSearch.schDispCompanyName = ''
|
stuffSearch.schDispCompanyName = ''
|
||||||
stuffSearch.schDateType = 'U'
|
stuffSearch.schDateType = 'U'
|
||||||
|
stuffSearch.schTempFlg = ''
|
||||||
|
|
||||||
stuffSearch.startRow = 1
|
stuffSearch.startRow = 1
|
||||||
stuffSearch.endRow = 100
|
stuffSearch.endRow = 100
|
||||||
stuffSearch.schSortType = 'R'
|
stuffSearch.schSortType = 'U'
|
||||||
stuffSearch.pageNo = 1
|
stuffSearch.pageNo = 1
|
||||||
stuffSearch.pageSize = 100
|
stuffSearch.pageSize = 100
|
||||||
} else {
|
} else {
|
||||||
@ -317,10 +329,11 @@ export default function StuffSearchCondition() {
|
|||||||
stuffSearch.schReceiveUser = ''
|
stuffSearch.schReceiveUser = ''
|
||||||
stuffSearch.schDispCompanyName = ''
|
stuffSearch.schDispCompanyName = ''
|
||||||
stuffSearch.schDateType = 'U'
|
stuffSearch.schDateType = 'U'
|
||||||
|
stuffSearch.schTempFlg = ''
|
||||||
|
|
||||||
stuffSearch.startRow = 1
|
stuffSearch.startRow = 1
|
||||||
stuffSearch.endRow = 100
|
stuffSearch.endRow = 100
|
||||||
stuffSearch.schSortType = 'R'
|
stuffSearch.schSortType = 'U'
|
||||||
stuffSearch.pageNo = 1
|
stuffSearch.pageNo = 1
|
||||||
stuffSearch.pageSize = 100
|
stuffSearch.pageSize = 100
|
||||||
}
|
}
|
||||||
@ -543,13 +556,14 @@ export default function StuffSearchCondition() {
|
|||||||
stuffSearch.schReceiveUser = ''
|
stuffSearch.schReceiveUser = ''
|
||||||
stuffSearch.schDispCompanyName = ''
|
stuffSearch.schDispCompanyName = ''
|
||||||
stuffSearch.schDateType = 'U'
|
stuffSearch.schDateType = 'U'
|
||||||
|
stuffSearch.schTempFlg = ''
|
||||||
stuffSearch.schFromDt = dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD')
|
stuffSearch.schFromDt = dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD')
|
||||||
stuffSearch.schToDt = dayjs(new Date()).format('YYYY-MM-DD')
|
stuffSearch.schToDt = dayjs(new Date()).format('YYYY-MM-DD')
|
||||||
stuffSearch.startRow = 1
|
stuffSearch.startRow = 1
|
||||||
stuffSearch.endRow = 100
|
stuffSearch.endRow = 100
|
||||||
stuffSearch.schSelSaleStoreId = ''
|
stuffSearch.schSelSaleStoreId = ''
|
||||||
stuffSearch.schOtherSelSaleStoreId = ''
|
stuffSearch.schOtherSelSaleStoreId = ''
|
||||||
stuffSearch.schSortType = 'R'
|
stuffSearch.schSortType = 'U'
|
||||||
stuffSearch.pageNo = 1
|
stuffSearch.pageNo = 1
|
||||||
stuffSearch.pageSize = 100
|
stuffSearch.pageSize = 100
|
||||||
|
|
||||||
@ -575,13 +589,14 @@ export default function StuffSearchCondition() {
|
|||||||
stuffSearch.schReceiveUser = ''
|
stuffSearch.schReceiveUser = ''
|
||||||
stuffSearch.schDispCompanyName = ''
|
stuffSearch.schDispCompanyName = ''
|
||||||
stuffSearch.schDateType = 'U'
|
stuffSearch.schDateType = 'U'
|
||||||
|
stuffSearch.schTempFlg = ''
|
||||||
stuffSearch.schFromDt = dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD')
|
stuffSearch.schFromDt = dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD')
|
||||||
stuffSearch.schToDt = dayjs(new Date()).format('YYYY-MM-DD')
|
stuffSearch.schToDt = dayjs(new Date()).format('YYYY-MM-DD')
|
||||||
stuffSearch.startRow = 1
|
stuffSearch.startRow = 1
|
||||||
stuffSearch.endRow = 100
|
stuffSearch.endRow = 100
|
||||||
stuffSearch.schSelSaleStoreId = ''
|
stuffSearch.schSelSaleStoreId = ''
|
||||||
stuffSearch.schOtherSelSaleStoreId = ''
|
stuffSearch.schOtherSelSaleStoreId = ''
|
||||||
stuffSearch.schSortType = 'R'
|
stuffSearch.schSortType = 'U'
|
||||||
stuffSearch.pageNo = 1
|
stuffSearch.pageNo = 1
|
||||||
stuffSearch.pageSize = 100
|
stuffSearch.pageSize = 100
|
||||||
setSchSelSaleStoreId('')
|
setSchSelSaleStoreId('')
|
||||||
@ -597,6 +612,17 @@ export default function StuffSearchCondition() {
|
|||||||
setDispCompanyName(stuffSearch.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName)
|
setDispCompanyName(stuffSearch.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName)
|
||||||
setReceiveUser(stuffSearch.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser)
|
setReceiveUser(stuffSearch.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser)
|
||||||
setDateType(stuffSearch.schDateType ? stuffSearch.schDateType : dateType)
|
setDateType(stuffSearch.schDateType ? stuffSearch.schDateType : dateType)
|
||||||
|
setTempFlg(stuffSearch.schTempFlg ? stuffSearch.schTempFlg : tempFlg)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stuffSearch.schDateType === 'R') {
|
||||||
|
setDateType('R')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stuffSearch.schTempFlg === '0') {
|
||||||
|
setTempFlg('0')
|
||||||
|
} else if (stuffSearch.schTempFlg === '1') {
|
||||||
|
setTempFlg('1')
|
||||||
}
|
}
|
||||||
}, [stuffSearch])
|
}, [stuffSearch])
|
||||||
|
|
||||||
@ -648,8 +674,8 @@ export default function StuffSearchCondition() {
|
|||||||
<col />
|
<col />
|
||||||
<col style={{ width: '160px' }} />
|
<col style={{ width: '160px' }} />
|
||||||
<col />
|
<col />
|
||||||
<col style={{ width: '160px' }} />
|
{/* <col style={{ width: '160px' }} />
|
||||||
<col />
|
<col /> */}
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
@ -685,22 +711,7 @@ export default function StuffSearchCondition() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<th>{getMessage('stuff.search.schAddress')}</th>
|
|
||||||
<td>
|
|
||||||
<div className="input-wrap">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
ref={addressRef}
|
|
||||||
className="input-light"
|
|
||||||
defaultValue={stuffSearch?.schAddress ? stuffSearch.schAddress : address}
|
|
||||||
onChange={() => {
|
|
||||||
stuffSearch.schAddress = addressRef.current.value
|
|
||||||
setAddress(addressRef.current.value)
|
|
||||||
}}
|
|
||||||
onKeyUp={handleByOnKeyUp}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<th>{getMessage('stuff.search.schDispCompanyName')}</th>
|
<th>{getMessage('stuff.search.schDispCompanyName')}</th>
|
||||||
<td>
|
<td>
|
||||||
<div className="input-wrap">
|
<div className="input-wrap">
|
||||||
@ -751,8 +762,127 @@ export default function StuffSearchCondition() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<th>{getMessage('stuff.search.schSelSaleStoreId')}</th>
|
<th>{getMessage('stuff.search.schAddress')}</th>
|
||||||
|
<td>
|
||||||
|
<div className="input-wrap">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
ref={addressRef}
|
||||||
|
className="input-light"
|
||||||
|
defaultValue={stuffSearch?.schAddress ? stuffSearch.schAddress : address}
|
||||||
|
onChange={() => {
|
||||||
|
stuffSearch.schAddress = addressRef.current.value
|
||||||
|
setAddress(addressRef.current.value)
|
||||||
|
}}
|
||||||
|
onKeyUp={handleByOnKeyUp}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{getMessage('stuff.search.period')}</th>
|
||||||
<td colSpan={3}>
|
<td colSpan={3}>
|
||||||
|
<div className="form-flex-wrap">
|
||||||
|
<div className="radio-wrap mr10">
|
||||||
|
<div className="d-check-radio light mr10">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="radio_ptype"
|
||||||
|
id="radio_u"
|
||||||
|
// checked={stuffSearch.schDateType === 'U' ? true : false}
|
||||||
|
checked={dateType === 'U' ? true : false}
|
||||||
|
value={'U'}
|
||||||
|
onChange={(e) => {
|
||||||
|
setDateType(e.target.value)
|
||||||
|
stuffSearch.schDateType = e.target.value
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label htmlFor="radio_u">{getMessage('stuff.search.schDateTypeU')}</label>
|
||||||
|
</div>
|
||||||
|
<div className="d-check-radio light">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="radio_ptype"
|
||||||
|
id="radio_r"
|
||||||
|
// checked={stuffSearch.schDateType === 'R' ? true : false}
|
||||||
|
checked={dateType === 'R' ? true : false}
|
||||||
|
value={'R'}
|
||||||
|
onChange={(e) => {
|
||||||
|
setDateType(e.target.value)
|
||||||
|
stuffSearch.schDateType = e.target.value
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label htmlFor="radio_r">{getMessage('stuff.search.schDateTypeR')}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="date-picker-wrap">
|
||||||
|
<div className="date-picker" style={{ flex: 1 }}>
|
||||||
|
<SingleDatePicker {...rangeDatePickerProps1} />
|
||||||
|
</div>
|
||||||
|
<span> ~ </span>
|
||||||
|
<div className="date-picker" style={{ flex: 1 }}>
|
||||||
|
<SingleDatePicker {...rangeDatePickerProps2} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<th>{getMessage('stuff.search.schTempFlgT')}</th>
|
||||||
|
<td>
|
||||||
|
<div className="form-flex-wrap">
|
||||||
|
<div className="radio-wrap mr10">
|
||||||
|
<div className="d-check-radio light mr10">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="schTempFlg"
|
||||||
|
id="schTempFlg"
|
||||||
|
checked={stuffSearch.schTempFlg === '' ? true : false}
|
||||||
|
value={''}
|
||||||
|
onChange={(e) => {
|
||||||
|
// let tempFlg = e.target.value
|
||||||
|
// setTempFlg(tempFlg)
|
||||||
|
// console.log('포함을 눌렀어:::::11:::::::', e.target.value)
|
||||||
|
// console.log('포함을 눌렀어::::22::::::::', tempFlg)
|
||||||
|
setTempFlg(e.target.value)
|
||||||
|
stuffSearch.schTempFlg = e.target.value
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label htmlFor="schTempFlg">{getMessage('stuff.search.schTempFlg')}</label>
|
||||||
|
</div>
|
||||||
|
<div className="d-check-radio light mr10">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="schTempFlg"
|
||||||
|
id="schTempFlg0"
|
||||||
|
checked={stuffSearch.schTempFlg === '0' ? true : false}
|
||||||
|
value={'0'}
|
||||||
|
onChange={(e) => {
|
||||||
|
setTempFlg(e.target.value)
|
||||||
|
stuffSearch.schTempFlg = e.target.value
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label htmlFor="schTempFlg0">{getMessage('stuff.search.schTempFlg0')}</label>
|
||||||
|
</div>
|
||||||
|
<div className="d-check-radio light">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="schTempFlg"
|
||||||
|
id="schTempFlg1"
|
||||||
|
checked={stuffSearch.schTempFlg === '1' ? true : false}
|
||||||
|
value={'1'}
|
||||||
|
onChange={(e) => {
|
||||||
|
setTempFlg(e.target.value)
|
||||||
|
stuffSearch.schTempFlg = e.target.value
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label htmlFor="schTempFlg1">{getMessage('stuff.search.schTempFlg1')}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{getMessage('stuff.search.schSelSaleStoreId')}</th>
|
||||||
|
<td colSpan={5}>
|
||||||
<div className="form-flex-wrap">
|
<div className="form-flex-wrap">
|
||||||
<div className="select-wrap mr5" style={{ flex: 1 }}>
|
<div className="select-wrap mr5" style={{ flex: 1 }}>
|
||||||
{session?.storeId === 'T01' && (
|
{session?.storeId === 'T01' && (
|
||||||
@ -876,52 +1006,6 @@ export default function StuffSearchCondition() {
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<th>{getMessage('stuff.search.period')}</th>
|
|
||||||
<td colSpan={7}>
|
|
||||||
<div className="form-flex-wrap">
|
|
||||||
<div className="radio-wrap mr10">
|
|
||||||
<div className="d-check-radio light mr10">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="radio_ptype"
|
|
||||||
id="radio_u"
|
|
||||||
defaultChecked={stuffSearch.schDateType === 'U' ? true : false}
|
|
||||||
value={'U'}
|
|
||||||
onChange={(e) => {
|
|
||||||
setDateType(e.target.value)
|
|
||||||
stuffSearch.schDateType = e.target.value
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<label htmlFor="radio_u">{getMessage('stuff.search.schDateTypeU')}</label>
|
|
||||||
</div>
|
|
||||||
<div className="d-check-radio light">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="radio_ptype"
|
|
||||||
id="radio_r"
|
|
||||||
defaultChecked={stuffSearch.schDateType === 'R' ? true : false}
|
|
||||||
value={'R'}
|
|
||||||
onChange={(e) => {
|
|
||||||
setDateType(e.target.value)
|
|
||||||
stuffSearch.schDateType = e.target.value
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<label htmlFor="radio_r">{getMessage('stuff.search.schDateTypeR')}</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="date-picker-wrap">
|
|
||||||
<div className="date-picker" style={{ flex: 1 }}>
|
|
||||||
<SingleDatePicker {...rangeDatePickerProps1} />
|
|
||||||
</div>
|
|
||||||
<span> ~ </span>
|
|
||||||
<div className="date-picker" style={{ flex: 1 }}>
|
|
||||||
<SingleDatePicker {...rangeDatePickerProps2} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -26,7 +26,8 @@ export const MODULE_INSERT_TYPE = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const MODULE_ALIGN_TYPE = {
|
export const MODULE_ALIGN_TYPE = {
|
||||||
TOP: 'top',
|
VERTICAL: 'vertical',
|
||||||
|
HORIZONTAL: 'horizontal',
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useModule() {
|
export function useModule() {
|
||||||
@ -83,6 +84,162 @@ export function useModule() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const moduleMultiMove = (type, length, direction) => {
|
||||||
|
if (canvas.getActiveObjects().length === 0) return
|
||||||
|
if (canvas.getActiveObjects().length > 1) {
|
||||||
|
swalFire({
|
||||||
|
title: '여러 개의 모듈을 선택할 수 없습니다.',
|
||||||
|
icon: 'error',
|
||||||
|
type: 'alert',
|
||||||
|
})
|
||||||
|
canvas.discardActiveObject()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const activeModule = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
|
||||||
|
const modules = type === 'row' ? getRowModules(activeModule) : getColumnModules(activeModule)
|
||||||
|
const otherModules = getOtherModules(modules)
|
||||||
|
const objects = getObjects()
|
||||||
|
const moduleSetupSurface = canvas
|
||||||
|
.getObjects()
|
||||||
|
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.id === activeModule.surfaceId)[0]
|
||||||
|
let isWarning = false
|
||||||
|
|
||||||
|
modules.forEach((module) => {
|
||||||
|
const { top, left } = getPosotion(module, direction, length, false)
|
||||||
|
module.originPos = {
|
||||||
|
top: module.top,
|
||||||
|
left: module.left,
|
||||||
|
fill: module.fill,
|
||||||
|
}
|
||||||
|
|
||||||
|
module.set({ top, left })
|
||||||
|
module.setCoords()
|
||||||
|
canvas.renderAll()
|
||||||
|
|
||||||
|
if (otherModules.length > 0) {
|
||||||
|
if (isOverlapOtherModules(module, otherModules) || isOverlapObjects(module, objects) || isOutsideSurface(module, moduleSetupSurface)) {
|
||||||
|
isWarning = true
|
||||||
|
module.set({ fill: 'red' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
canvas.renderAll()
|
||||||
|
if (isWarning) {
|
||||||
|
swalFire({
|
||||||
|
title: getMessage('can.not.move.module'),
|
||||||
|
icon: 'error',
|
||||||
|
type: 'alert',
|
||||||
|
confirmFn: () => {
|
||||||
|
modules.forEach((module) => {
|
||||||
|
module.set({ top: module.originPos.top, left: module.originPos.left, fill: module.originPos.fill })
|
||||||
|
module.setCoords()
|
||||||
|
})
|
||||||
|
canvas.renderAll()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const moduleMoveAll = (length, direction) => {
|
||||||
|
const moduleSetupSurface = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
|
||||||
|
const modules = canvas.getObjects().filter((obj) => obj.surfaceId === moduleSetupSurface.id && obj.name === POLYGON_TYPE.MODULE)
|
||||||
|
const objects = getObjects()
|
||||||
|
|
||||||
|
let isWarning = false
|
||||||
|
|
||||||
|
modules.forEach((module) => {
|
||||||
|
const { top, left } = getPosotion(module, direction, length, false)
|
||||||
|
module.originPos = {
|
||||||
|
top: module.top,
|
||||||
|
left: module.left,
|
||||||
|
fill: module.fill,
|
||||||
|
}
|
||||||
|
|
||||||
|
module.set({ top, left })
|
||||||
|
module.setCoords()
|
||||||
|
canvas.renderAll()
|
||||||
|
|
||||||
|
if (isOverlapObjects(module, objects) || isOutsideSurface(module, moduleSetupSurface)) {
|
||||||
|
isWarning = true
|
||||||
|
module.set({ fill: 'red' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
canvas.renderAll()
|
||||||
|
if (isWarning) {
|
||||||
|
swalFire({
|
||||||
|
title: getMessage('can.not.move.module'),
|
||||||
|
icon: 'error',
|
||||||
|
type: 'alert',
|
||||||
|
confirmFn: () => {
|
||||||
|
modules.forEach((module) => {
|
||||||
|
module.set({ top: module.originPos.top, left: module.originPos.left, fill: module.originPos.fill })
|
||||||
|
module.setCoords()
|
||||||
|
})
|
||||||
|
canvas.renderAll()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const moduleCopyAll = (length, direction) => {
|
||||||
|
const moduleSetupSurface = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
|
||||||
|
const modules = canvas.getObjects().filter((obj) => obj.surfaceId === moduleSetupSurface.id && obj.name === POLYGON_TYPE.MODULE)
|
||||||
|
const objects = getObjects()
|
||||||
|
const copyModules = []
|
||||||
|
let copyModule = null
|
||||||
|
let isWarning = false
|
||||||
|
let moduleLength = 0
|
||||||
|
if (['up', 'down'].includes(direction)) {
|
||||||
|
modules.sort((a, b) => a.top - b.top)
|
||||||
|
moduleLength = Number(modules[modules.length - 1].top) + Number(modules[modules.length - 1].height) - Number(modules[0].top)
|
||||||
|
} else if (['left', 'right'].includes(direction)) {
|
||||||
|
modules.sort((a, b) => a.left - b.left)
|
||||||
|
moduleLength = Number(modules[modules.length - 1].left) + Number(modules[modules.length - 1].width) - Number(modules[0].left)
|
||||||
|
}
|
||||||
|
|
||||||
|
modules.forEach((module) => {
|
||||||
|
const { top, left } = getPosotion(module, direction, Number(length) + Number(moduleLength), false)
|
||||||
|
module.clone((obj) => {
|
||||||
|
obj.set({
|
||||||
|
parentId: module.parentId,
|
||||||
|
initOptions: module.initOptions,
|
||||||
|
direction: module.direction,
|
||||||
|
arrow: module.arrow,
|
||||||
|
name: module.name,
|
||||||
|
type: module.type,
|
||||||
|
length: module.length,
|
||||||
|
points: module.points,
|
||||||
|
surfaceId: module.surfaceId,
|
||||||
|
left,
|
||||||
|
top,
|
||||||
|
id: uuidv4(),
|
||||||
|
})
|
||||||
|
copyModule = obj
|
||||||
|
canvas.add(obj)
|
||||||
|
copyModules.push(obj)
|
||||||
|
obj.setCoords()
|
||||||
|
})
|
||||||
|
if (isOverlapObjects(copyModule, objects) || isOutsideSurface(copyModule, moduleSetupSurface)) {
|
||||||
|
isWarning = true
|
||||||
|
copyModule.set({ fill: 'red' })
|
||||||
|
}
|
||||||
|
canvas.renderAll()
|
||||||
|
})
|
||||||
|
|
||||||
|
if (isWarning) {
|
||||||
|
swalFire({
|
||||||
|
title: getMessage('can.not.copy.module'),
|
||||||
|
icon: 'error',
|
||||||
|
type: 'alert',
|
||||||
|
confirmFn: () => {
|
||||||
|
canvas.remove(...copyModules)
|
||||||
|
canvas.renderAll()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const moduleCopy = (length, direction) => {
|
const moduleCopy = (length, direction) => {
|
||||||
if (canvas.getActiveObjects().length === 0) return
|
if (canvas.getActiveObjects().length === 0) return
|
||||||
@ -144,63 +301,6 @@ export function useModule() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const moduleMultiMove = (type, length, direction) => {
|
|
||||||
if (canvas.getActiveObjects().length === 0) return
|
|
||||||
if (canvas.getActiveObjects().length > 1) {
|
|
||||||
swalFire({
|
|
||||||
title: '여러 개의 모듈을 선택할 수 없습니다.',
|
|
||||||
icon: 'error',
|
|
||||||
type: 'alert',
|
|
||||||
})
|
|
||||||
canvas.discardActiveObject()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const activeModule = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
|
|
||||||
const modules = type === 'row' ? getRowModules(activeModule) : getColumnModules(activeModule)
|
|
||||||
const otherModules = getOtherModules(modules)
|
|
||||||
const objects = getObjects()
|
|
||||||
const moduleSetupSurface = canvas
|
|
||||||
.getObjects()
|
|
||||||
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.id === activeModule.surfaceId)[0]
|
|
||||||
let isWarning = false
|
|
||||||
|
|
||||||
modules.forEach((module) => {
|
|
||||||
const { top, left } = getPosotion(module, direction, length, false)
|
|
||||||
module.originPos = {
|
|
||||||
top: module.top,
|
|
||||||
left: module.left,
|
|
||||||
fill: module.fill,
|
|
||||||
}
|
|
||||||
|
|
||||||
module.set({ top, left })
|
|
||||||
module.setCoords()
|
|
||||||
canvas.renderAll()
|
|
||||||
|
|
||||||
if (otherModules.length > 0) {
|
|
||||||
if (isOverlapOtherModules(module, otherModules) || isOverlapObjects(module, objects) || isOutsideSurface(module, moduleSetupSurface)) {
|
|
||||||
isWarning = true
|
|
||||||
module.set({ fill: 'red' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
canvas.renderAll()
|
|
||||||
if (isWarning) {
|
|
||||||
swalFire({
|
|
||||||
title: getMessage('can.not.move.module'),
|
|
||||||
icon: 'error',
|
|
||||||
type: 'alert',
|
|
||||||
confirmFn: () => {
|
|
||||||
modules.forEach((module) => {
|
|
||||||
module.set({ top: module.originPos.top, left: module.originPos.left, fill: module.originPos.fill })
|
|
||||||
module.setCoords()
|
|
||||||
})
|
|
||||||
canvas.renderAll()
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const moduleMultiCopy = (type, length, direction) => {
|
const moduleMultiCopy = (type, length, direction) => {
|
||||||
if (canvas.getActiveObjects().length === 0) return
|
if (canvas.getActiveObjects().length === 0) return
|
||||||
if (canvas.getActiveObjects().length > 1) {
|
if (canvas.getActiveObjects().length > 1) {
|
||||||
@ -694,7 +794,68 @@ export function useModule() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const alignModule = (type) => {}
|
const alignModule = (type) => {
|
||||||
|
const moduleSetupSurface = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
|
||||||
|
const modules = canvas.getObjects().filter((obj) => obj.surfaceId === moduleSetupSurface.id && obj.name === POLYGON_TYPE.MODULE)
|
||||||
|
const objects = getObjects()
|
||||||
|
let [top, bottom, left, right] = [0, 0, 0, 0]
|
||||||
|
|
||||||
|
top = Math.min(...modules.map((module) => module.top))
|
||||||
|
bottom = Math.max(...modules.map((module) => module.top + module.height))
|
||||||
|
left = Math.min(...modules.map((module) => module.left))
|
||||||
|
right = Math.max(...modules.map((module) => module.left + module.width))
|
||||||
|
const moduleSurfacePos = {
|
||||||
|
top: Math.min(...moduleSetupSurface.points.map((point) => point.y)),
|
||||||
|
left: Math.min(...moduleSetupSurface.points.map((point) => point.x)),
|
||||||
|
}
|
||||||
|
const [height, width] = [bottom - top, right - left]
|
||||||
|
const verticalCenterLength = moduleSurfacePos.top + moduleSetupSurface.height / 2 - (top + height / 2)
|
||||||
|
const horizontalCenterLength = moduleSurfacePos.left + moduleSetupSurface.width / 2 - (left + width / 2)
|
||||||
|
let isWarning = false
|
||||||
|
|
||||||
|
canvas.discardActiveObject()
|
||||||
|
modules.forEach((module) => {
|
||||||
|
module.originPos = {
|
||||||
|
left: module.left,
|
||||||
|
top: module.top,
|
||||||
|
fill: module.fill,
|
||||||
|
}
|
||||||
|
if (type === MODULE_ALIGN_TYPE.VERTICAL) {
|
||||||
|
module.set({ top: module.top + verticalCenterLength })
|
||||||
|
} else if (type === MODULE_ALIGN_TYPE.HORIZONTAL) {
|
||||||
|
module.set({ left: module.left + horizontalCenterLength })
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.renderAll()
|
||||||
|
module.setCoords()
|
||||||
|
if (isOverlapObjects(module, objects) || isOutsideSurface(module, moduleSetupSurface)) {
|
||||||
|
isWarning = true
|
||||||
|
module.set({ fill: 'red' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
canvas.renderAll()
|
||||||
|
if (isWarning) {
|
||||||
|
swalFire({
|
||||||
|
title: getMessage('can.not.align.module'),
|
||||||
|
icon: 'error',
|
||||||
|
type: 'alert',
|
||||||
|
confirmFn: () => {
|
||||||
|
modules.forEach((module) => {
|
||||||
|
module.set({ top: module.originPos.top, left: module.originPos.left, fill: module.originPos.fill })
|
||||||
|
module.setCoords()
|
||||||
|
})
|
||||||
|
canvas.renderAll()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const modulesRemove = () => {
|
||||||
|
const activeModule = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
|
||||||
|
const modules = canvas.getObjects().filter((obj) => obj.surfaceId === activeModule.surfaceId && obj.name === POLYGON_TYPE.MODULE)
|
||||||
|
canvas.remove(...modules)
|
||||||
|
canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
const isOverlapOtherModules = (module, otherModules) => {
|
const isOverlapOtherModules = (module, otherModules) => {
|
||||||
return otherModules.some(
|
return otherModules.some(
|
||||||
@ -765,11 +926,15 @@ export function useModule() {
|
|||||||
return {
|
return {
|
||||||
moduleMove,
|
moduleMove,
|
||||||
moduleMultiMove,
|
moduleMultiMove,
|
||||||
|
moduleMoveAll,
|
||||||
moduleCopy,
|
moduleCopy,
|
||||||
moduleMultiCopy,
|
moduleMultiCopy,
|
||||||
|
moduleCopyAll,
|
||||||
moduleColumnRemove,
|
moduleColumnRemove,
|
||||||
moduleRowRemove,
|
moduleRowRemove,
|
||||||
moduleColumnInsert,
|
moduleColumnInsert,
|
||||||
muduleRowInsert,
|
muduleRowInsert,
|
||||||
|
modulesRemove,
|
||||||
|
alignModule,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -272,7 +272,7 @@ export function useCanvasSetting() {
|
|||||||
// 기본설정(PlacementShapeSetting) 조회 및 초기화
|
// 기본설정(PlacementShapeSetting) 조회 및 초기화
|
||||||
const fetchBasicSettings = async () => {
|
const fetchBasicSettings = async () => {
|
||||||
try {
|
try {
|
||||||
await get({ url: `/api/canvas-management/canvas-basic-settings/by-object/${correntObjectNo}` }).then((res) => {
|
await get({ url: `/api/canvas-management/canvas-basic-settings/by-object/0/${correntObjectNo}` }).then((res) => {
|
||||||
|
|
||||||
let roofsRow = {}
|
let roofsRow = {}
|
||||||
let roofsArray = {}
|
let roofsArray = {}
|
||||||
@ -762,7 +762,6 @@ export function useCanvasSetting() {
|
|||||||
setCanvasSetting,
|
setCanvasSetting,
|
||||||
basicSetting,
|
basicSetting,
|
||||||
setBasicSettings,
|
setBasicSettings,
|
||||||
fetchBasicSettings,
|
|
||||||
basicSettingSave,
|
basicSettingSave,
|
||||||
settingsData,
|
settingsData,
|
||||||
setSettingsData,
|
setSettingsData,
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import { useMessage } from '@/hooks/useMessage'
|
|||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
|
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
|
||||||
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
|
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||||
import { getDegreeByChon } from '@/util/canvas-util'
|
import { getDegreeByChon } from '@/util/canvas-util'
|
||||||
|
|
||||||
//동선이동 형 올림 내림
|
//동선이동 형 올림 내림
|
||||||
@ -26,6 +28,7 @@ export function useMovementSetting(id) {
|
|||||||
]
|
]
|
||||||
const [type, setType] = useState(TYPE.FLOW_LINE)
|
const [type, setType] = useState(TYPE.FLOW_LINE)
|
||||||
const typeRef = useRef(type)
|
const typeRef = useRef(type)
|
||||||
|
const { swalFire } = useSwal()
|
||||||
|
|
||||||
const FLOW_LINE_REF = {
|
const FLOW_LINE_REF = {
|
||||||
POINTER_INPUT_REF: useRef(null),
|
POINTER_INPUT_REF: useRef(null),
|
||||||
@ -69,6 +72,7 @@ export function useMovementSetting(id) {
|
|||||||
roof.innerLines.forEach((line) => {
|
roof.innerLines.forEach((line) => {
|
||||||
if (line.name === LINE_TYPE.SUBLINE.RIDGE) {
|
if (line.name === LINE_TYPE.SUBLINE.RIDGE) {
|
||||||
line.bringToFront()
|
line.bringToFront()
|
||||||
|
line.set({ visible: true })
|
||||||
line.set({ selectable: true })
|
line.set({ selectable: true })
|
||||||
line.set({ strokeWidth: 4 })
|
line.set({ strokeWidth: 4 })
|
||||||
line.set({ stroke: '#1083E3' })
|
line.set({ stroke: '#1083E3' })
|
||||||
@ -89,7 +93,6 @@ export function useMovementSetting(id) {
|
|||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
addCanvasMouseEventListener('mouse:move', mouseMoveEvent)
|
addCanvasMouseEventListener('mouse:move', mouseMoveEvent)
|
||||||
addCanvasMouseEventListener('mouse:down', mouseDownEvent)
|
addCanvasMouseEventListener('mouse:down', mouseDownEvent)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
initEvent()
|
initEvent()
|
||||||
|
|
||||||
@ -178,6 +181,36 @@ export function useMovementSetting(id) {
|
|||||||
updownMoveEvent(e)
|
updownMoveEvent(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function edgesIntersection(edgeA, edgeB) {
|
||||||
|
const den =
|
||||||
|
(edgeB.vertex2.y - edgeB.vertex1.y) * (edgeA.vertex2.x - edgeA.vertex1.x) -
|
||||||
|
(edgeB.vertex2.x - edgeB.vertex1.x) * (edgeA.vertex2.y - edgeA.vertex1.y)
|
||||||
|
|
||||||
|
if (den === 0) {
|
||||||
|
return null // lines are parallel or coincident
|
||||||
|
}
|
||||||
|
|
||||||
|
const ua =
|
||||||
|
((edgeB.vertex2.x - edgeB.vertex1.x) * (edgeA.vertex1.y - edgeB.vertex1.y) -
|
||||||
|
(edgeB.vertex2.y - edgeB.vertex1.y) * (edgeA.vertex1.x - edgeB.vertex1.x)) /
|
||||||
|
den
|
||||||
|
|
||||||
|
const ub =
|
||||||
|
((edgeA.vertex2.x - edgeA.vertex1.x) * (edgeA.vertex1.y - edgeB.vertex1.y) -
|
||||||
|
(edgeA.vertex2.y - edgeA.vertex1.y) * (edgeA.vertex1.x - edgeB.vertex1.x)) /
|
||||||
|
den
|
||||||
|
|
||||||
|
// Edges are not intersecting but the lines defined by them are
|
||||||
|
const isIntersectionOutside = ua < 0 || ub < 0 || ua > 1 || ub > 1
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: edgeA.vertex1.x + ua * (edgeA.vertex2.x - edgeA.vertex1.x),
|
||||||
|
y: edgeA.vertex1.y + ua * (edgeA.vertex2.y - edgeA.vertex1.y),
|
||||||
|
isIntersectionOutside,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//동선 이동 마우스 클릭 이벤트
|
//동선 이동 마우스 클릭 이벤트
|
||||||
const saveFlowLine = (e) => {
|
const saveFlowLine = (e) => {
|
||||||
const target = selectedObject.current
|
const target = selectedObject.current
|
||||||
@ -187,22 +220,23 @@ export function useMovementSetting(id) {
|
|||||||
|
|
||||||
let newPoint = []
|
let newPoint = []
|
||||||
if (Math.sign(target.x1 - target.x2) !== 0) {
|
if (Math.sign(target.x1 - target.x2) !== 0) {
|
||||||
|
const sign = FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked ? 1 : -1
|
||||||
newPoint = [
|
newPoint = [
|
||||||
target.x1,
|
target.x1,
|
||||||
target.y1 - Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
|
target.y1 - sign * Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
|
||||||
target.x2,
|
target.x2,
|
||||||
target.y2 - Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
|
target.y2 - sign * Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
|
||||||
]
|
]
|
||||||
} else {
|
} else {
|
||||||
|
const sign = FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked ? -1 : 1
|
||||||
newPoint = [
|
newPoint = [
|
||||||
target.x1 + Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
|
target.x1 - sign * Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
|
||||||
target.y1,
|
target.y1,
|
||||||
target.x2 + Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
|
target.x2 - sign * Number(FLOW_LINE_REF.FILLED_INPUT_REF.current.value / 10),
|
||||||
target.y2,
|
target.y2,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
newPoint = newPoint.map((point) => Math.round(point * 10) / 10)
|
||||||
clearRef()
|
|
||||||
const cloned = new fabric.Line(newPoint, {})
|
const cloned = new fabric.Line(newPoint, {})
|
||||||
let currentObject = selectedObject.current
|
let currentObject = selectedObject.current
|
||||||
const currentX1 = currentObject.x1,
|
const currentX1 = currentObject.x1,
|
||||||
@ -210,39 +244,94 @@ export function useMovementSetting(id) {
|
|||||||
currentX2 = currentObject.x2,
|
currentX2 = currentObject.x2,
|
||||||
currentY2 = currentObject.y2
|
currentY2 = currentObject.y2
|
||||||
|
|
||||||
|
const currentMidX = (currentX1 + currentX2) / 2
|
||||||
|
const currentMidY = (currentY1 + currentY2) / 2
|
||||||
|
const clonedMidX = (cloned.x1 + cloned.x2) / 2
|
||||||
|
const clonedMidY = (cloned.y1 + cloned.y2) / 2
|
||||||
|
|
||||||
const roof = canvas.getObjects().find((obj) => obj.id === currentObject.attributes.roofId)
|
const roof = canvas.getObjects().find((obj) => obj.id === currentObject.attributes.roofId)
|
||||||
if (roof.separatePolygon.length > 0) {
|
let isOutside = false
|
||||||
const separatePolygon = roof.separatePolygon
|
roof.lines.forEach((line) => {
|
||||||
separatePolygon
|
const intersection = edgesIntersection(
|
||||||
.filter((polygon) =>
|
{ vertex1: { x: currentMidX, y: currentMidY }, vertex2: { x: clonedMidX, y: clonedMidY } },
|
||||||
polygon.points.some((point) => (point.x === currentX1 && point.y === currentY1) || (point.x === currentX2 && point.y === currentY2)),
|
{ vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } },
|
||||||
)
|
)
|
||||||
.forEach((polygon) => {
|
if (intersection && !intersection.isIntersectionOutside) {
|
||||||
const newPoints = polygon.points.map((point) => {
|
isOutside = true
|
||||||
if (point.x === currentX1 && point.y === currentY1) {
|
}
|
||||||
return { x: newPoint[0], y: newPoint[1] }
|
})
|
||||||
} else if (point.x === currentX2 && point.y === currentY2) {
|
if (isOutside) {
|
||||||
return { x: newPoint[2], y: newPoint[3] }
|
swalFire({ text: getMessage('modal.movement.flow.line.move.alert'), icon: 'error' })
|
||||||
} else {
|
return
|
||||||
return point
|
}
|
||||||
}
|
currentObject.set({ x1: cloned.x1, y1: cloned.y1, x2: cloned.x2, y2: cloned.y2 })
|
||||||
})
|
currentObject.setCoords()
|
||||||
polygon.set({ points: newPoints })
|
const otherRidges = roof.innerLines.filter((line) => line.name === LINE_TYPE.SUBLINE.RIDGE && line.id !== currentObject.id)
|
||||||
polygon.setCoords()
|
const overlapRidges = otherRidges.filter((line) => {
|
||||||
polygon.addLengthText()
|
if (currentObject.x1 === currentObject.x2 && line.x1 === line.x2 && 0 < Math.abs(currentObject.x1 - line.x1) < 1) {
|
||||||
polygon.initLines()
|
if (
|
||||||
const slope = (line) => (line.x2 - line.x1 === 0 ? Infinity : (line.y2 - line.y1) / (line.x2 - line.x1))
|
currentObject.y1 <= line.y1 <= currentObject.y2 ||
|
||||||
const currentDegree = polygon.attributes.pitch > 0 ? getDegreeByChon(polygon.attributes.pitch) : polygon.attributes.degree
|
currentObject.y1 >= line.y1 >= currentObject.y2 ||
|
||||||
polygon.lines.forEach((line) => {
|
currentObject.y1 <= line.y2 <= currentObject.y2 ||
|
||||||
line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x2 - line.x1, 2) + Math.pow(line.y2 - line.y1, 2)) * 10)
|
currentObject.y1 >= line.y2 >= currentObject.y2
|
||||||
if (currentDegree > 0 && slope(line) !== slope(currentObject)) {
|
) {
|
||||||
const height = Math.tan(currentDegree * (Math.PI / 180)) * line.attributes.planeSize
|
return true
|
||||||
line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.attributes.planeSize, 2) + Math.pow(height, 2)))
|
}
|
||||||
} else {
|
}
|
||||||
line.attributes.actualSize = line.attributes.planeSize
|
if (currentObject.y1 === currentObject.y2 && line.y1 === line.y2 && 0 < Math.abs(currentObject.y1 - line.y1) < 1) {
|
||||||
}
|
if (
|
||||||
})
|
currentObject.x1 <= line.x1 <= currentObject.x2 ||
|
||||||
|
currentObject.x1 >= line.x1 >= currentObject.x2 ||
|
||||||
|
currentObject.x1 <= line.x2 <= currentObject.x2 ||
|
||||||
|
currentObject.x1 >= line.x2 >= currentObject.x2
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (overlapRidges.length > 0) {
|
||||||
|
const minX = Math.min(...overlapRidges.flatMap((line) => [line.x1, line.x2]), currentObject.x1, currentObject.x2)
|
||||||
|
const maxX = Math.max(...overlapRidges.flatMap((line) => [line.x1, line.x2]), currentObject.x1, currentObject.x2)
|
||||||
|
const minY = Math.min(...overlapRidges.flatMap((line) => [line.y1, line.y2]), currentObject.y1, currentObject.y2)
|
||||||
|
const maxY = Math.max(...overlapRidges.flatMap((line) => [line.y1, line.y2]), currentObject.y1, currentObject.y2)
|
||||||
|
const newRidge = new fabric.Line([minX, minY, maxX, maxY], {
|
||||||
|
name: LINE_TYPE.SUBLINE.RIDGE,
|
||||||
|
selectable: true,
|
||||||
|
stroke: '#1083E3',
|
||||||
|
strokeWidth: 4,
|
||||||
|
attributes: { roofId: roof.id, currentRoof: currentObject.attributes.currentRoof },
|
||||||
|
})
|
||||||
|
|
||||||
|
overlapRidges.forEach((line) =>
|
||||||
|
line.attributes.currentRoof.forEach((id) => {
|
||||||
|
if (!newRidge.attributes.currentRoof.includes(id)) {
|
||||||
|
newRidge.attributes.currentRoof.push(id)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
canvas.add(newRidge)
|
||||||
|
newRidge.bringToFront()
|
||||||
|
roof.innerLines.push(newRidge)
|
||||||
|
|
||||||
|
canvas.remove(currentObject)
|
||||||
|
roof.innerLines.forEach((innerLine, index) => {
|
||||||
|
if (innerLine.id === currentObject.id) {
|
||||||
|
roof.innerLines.splice(index, 1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
overlapRidges.forEach((line) => {
|
||||||
|
canvas.remove(line)
|
||||||
|
roof.innerLines.forEach((innerLine, index) => {
|
||||||
|
if (innerLine.id === line.id) {
|
||||||
|
roof.innerLines.splice(index, 1)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roof.separatePolygon.length > 0) {
|
||||||
|
redrawSeparatePolygon(roof)
|
||||||
} else {
|
} else {
|
||||||
roof.innerLines
|
roof.innerLines
|
||||||
.filter((line) => currentObject !== line)
|
.filter((line) => currentObject !== line)
|
||||||
@ -277,6 +366,390 @@ export function useMovementSetting(id) {
|
|||||||
|
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
canvas.discardActiveObject()
|
canvas.discardActiveObject()
|
||||||
|
|
||||||
|
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const redrawSeparatePolygon = (roof) => {
|
||||||
|
roof.separatePolygon.forEach((polygon) => canvas.remove(polygon))
|
||||||
|
roof.separatePolygon = []
|
||||||
|
const roofLines = roof.lines
|
||||||
|
const wallLines = roof.wall.lines
|
||||||
|
const eaves = []
|
||||||
|
roofLines.forEach((currentRoof, index) => {
|
||||||
|
if (currentRoof.attributes?.type === LINE_TYPE.WALLLINE.EAVES) {
|
||||||
|
eaves.push({ index: index, roof: currentRoof, length: currentRoof.attributes.planeSize })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const ridges = roof.innerLines.filter((line) => line.name === LINE_TYPE.SUBLINE.RIDGE)
|
||||||
|
eaves.sort((a, b) => a.length - b.length)
|
||||||
|
|
||||||
|
const ridgeCount = eaves.length - 1
|
||||||
|
console.log('ridgeCount', ridgeCount, 'ridges', ridges.length)
|
||||||
|
|
||||||
|
const duplicatedEaves = []
|
||||||
|
ridges.forEach((ridge) => {
|
||||||
|
const positiveLines = []
|
||||||
|
const negativeLines = []
|
||||||
|
ridge.attributes.currentRoof.forEach((id) => {
|
||||||
|
console.log('id : ', id)
|
||||||
|
const eave = roofLines.find((obj) => obj.id === id)
|
||||||
|
console.log('roof : ', eave)
|
||||||
|
if (ridge.x1 === ridge.x2) {
|
||||||
|
if (eave.y1 < eave.y2) {
|
||||||
|
positiveLines.push(eave)
|
||||||
|
} else {
|
||||||
|
negativeLines.push(eave)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (eave.x1 < eave.x2) {
|
||||||
|
positiveLines.push(eave)
|
||||||
|
} else {
|
||||||
|
negativeLines.push(eave)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (positiveLines.length > 1) {
|
||||||
|
duplicatedEaves.push(positiveLines)
|
||||||
|
}
|
||||||
|
if (negativeLines.length > 1) {
|
||||||
|
duplicatedEaves.push(negativeLines)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
console.log('duplicatedEaves', duplicatedEaves)
|
||||||
|
|
||||||
|
duplicatedEaves.forEach((duplicatedEave) => {
|
||||||
|
duplicatedEave.forEach((eave) => {
|
||||||
|
const index = eaves.findIndex((item) => item.roof.id === eave.id)
|
||||||
|
eaves.splice(index, 1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// if (ridgeCount === ridges.length) {
|
||||||
|
eaves.forEach((eave, i) => {
|
||||||
|
const index = eave.index,
|
||||||
|
currentRoof = eave.roof
|
||||||
|
const currentWall = wallLines[index]
|
||||||
|
const currentRidges = ridges.filter((ridge) => ridge.attributes.currentRoof.includes(eave.roof.id))
|
||||||
|
let points = []
|
||||||
|
const signX = Math.sign(currentRoof.x1 - currentRoof.x2)
|
||||||
|
let currentX1 = currentRoof.x1,
|
||||||
|
currentY1 = currentRoof.y1,
|
||||||
|
currentX2 = currentRoof.x2,
|
||||||
|
currentY2 = currentRoof.y2
|
||||||
|
let changeX1 = [Math.min(currentRoof.x1, currentRoof.x2), Math.min(currentRoof.x1, currentRoof.x2)],
|
||||||
|
changeY1 = [Math.min(currentRoof.y1, currentRoof.y2), Math.min(currentRoof.y1, currentRoof.y2)],
|
||||||
|
changeX2 = [Math.max(currentRoof.x2, currentRoof.x1), Math.max(currentRoof.x2, currentRoof.x1)],
|
||||||
|
changeY2 = [Math.max(currentRoof.y2, currentRoof.y1), Math.max(currentRoof.y2, currentRoof.y1)]
|
||||||
|
|
||||||
|
if (signX === 0) {
|
||||||
|
currentY1 = Math.min(currentRoof.y1, currentRoof.y2, currentWall.y1, currentWall.y2)
|
||||||
|
changeY1[1] = currentY1
|
||||||
|
currentY2 = Math.max(currentRoof.y1, currentRoof.y2, currentWall.y1, currentWall.y2)
|
||||||
|
changeY2[1] = currentY2
|
||||||
|
} else {
|
||||||
|
currentX1 = Math.min(currentRoof.x1, currentRoof.x2, currentWall.x1, currentWall.x2)
|
||||||
|
changeX1[1] = currentX1
|
||||||
|
currentX2 = Math.max(currentRoof.x1, currentRoof.x2, currentWall.x1, currentWall.x2)
|
||||||
|
changeX2[1] = currentX2
|
||||||
|
}
|
||||||
|
points.push({ x: currentX1, y: currentY1 }, { x: currentX2, y: currentY2 })
|
||||||
|
|
||||||
|
currentRidges.forEach((ridge) => {
|
||||||
|
let ridgeX1 = ridge.x1,
|
||||||
|
ridgeY1 = ridge.y1,
|
||||||
|
ridgeX2 = ridge.x2,
|
||||||
|
ridgeY2 = ridge.y2
|
||||||
|
if (signX === 0) {
|
||||||
|
ridgeY1 = Math.min(ridge.y1, ridge.y2)
|
||||||
|
ridgeY2 = Math.max(ridge.y1, ridge.y2)
|
||||||
|
} else {
|
||||||
|
ridgeX1 = Math.min(ridge.x1, ridge.x2)
|
||||||
|
ridgeX2 = Math.max(ridge.x1, ridge.x2)
|
||||||
|
}
|
||||||
|
points.push({ x: ridgeX1, y: ridgeY1 }, { x: ridgeX2, y: ridgeY2 })
|
||||||
|
})
|
||||||
|
|
||||||
|
points.forEach((point) => {
|
||||||
|
if (point.x === changeX1[0] && changeX1[0] !== changeX1[1]) {
|
||||||
|
point.x = changeX1[1]
|
||||||
|
}
|
||||||
|
if (point.x === changeX2[0] && changeX2[0] !== changeX2[1]) {
|
||||||
|
point.x = changeX2[1]
|
||||||
|
}
|
||||||
|
if (point.y === changeY1[0] && changeY1[0] !== changeY1[1]) {
|
||||||
|
point.y = changeY1[1]
|
||||||
|
}
|
||||||
|
if (point.y === changeY2[0] && changeY2[0] !== changeY2[1]) {
|
||||||
|
point.y = changeY2[1]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
//중복된 point 제거
|
||||||
|
points = points.filter((point, index, self) => index === self.findIndex((p) => p.x === point.x && p.y === point.y))
|
||||||
|
//point 정렬 (가장 좌측, 최상단의 점을 기준으로 삼는다.)
|
||||||
|
const startPoint = points
|
||||||
|
.filter((point) => point.x === Math.min(...points.map((point) => point.x)))
|
||||||
|
.reduce((prev, current) => {
|
||||||
|
return prev.y < current.y ? prev : current
|
||||||
|
})
|
||||||
|
|
||||||
|
const sortedPoints = []
|
||||||
|
sortedPoints.push(startPoint)
|
||||||
|
|
||||||
|
points.forEach((p, index) => {
|
||||||
|
if (index === 0) {
|
||||||
|
//시작점 다음 점 찾기, y좌표가 startPoint.y 보다 큰 점 중 x좌표가 가까운 점
|
||||||
|
const underStartPoint = points.filter((point) => point.y > startPoint.y)
|
||||||
|
const nextPoint = underStartPoint
|
||||||
|
.filter((point) => point.x === startPoint.x)
|
||||||
|
.reduce((prev, current) => {
|
||||||
|
if (prev === undefined) {
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
return Math.abs(prev.y - startPoint.y) < Math.abs(current.y - startPoint.y) ? prev : current
|
||||||
|
}, undefined)
|
||||||
|
if (nextPoint) {
|
||||||
|
sortedPoints.push(nextPoint)
|
||||||
|
} else {
|
||||||
|
const nextPoint = underStartPoint.reduce((prev, current) => {
|
||||||
|
const prevHypos = Math.sqrt(Math.abs(Math.pow(prev.x - startPoint.x, 2)) + Math.abs(Math.pow(prev.y - startPoint.y, 2)))
|
||||||
|
const currentHypos = Math.sqrt(Math.abs(Math.pow(current.x - startPoint.x, 2)) + Math.abs(Math.pow(current.y - startPoint.y, 2)))
|
||||||
|
return prevHypos < currentHypos ? prev : current
|
||||||
|
}, undefined)
|
||||||
|
sortedPoints.push(nextPoint)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const lastPoint = sortedPoints[sortedPoints.length - 1]
|
||||||
|
console.log('lastPoint', lastPoint)
|
||||||
|
const prevPoint = sortedPoints[sortedPoints.length - 2]
|
||||||
|
const otherPoints = points.filter((point) => sortedPoints.includes(point) === false)
|
||||||
|
const nextPoint = otherPoints.reduce((prev, current) => {
|
||||||
|
if (prev === undefined) {
|
||||||
|
const height = Math.abs(Math.sqrt(Math.abs(Math.pow(prevPoint.x - lastPoint.x, 2)) + Math.abs(Math.pow(prevPoint.y - lastPoint.y, 2))))
|
||||||
|
const adjacent = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - lastPoint.x, 2)) + Math.abs(Math.pow(current.y - lastPoint.y, 2))))
|
||||||
|
const hypotenuse = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - prevPoint.x, 2)) + Math.abs(Math.pow(current.y - prevPoint.y, 2))))
|
||||||
|
|
||||||
|
const angle = Math.round(
|
||||||
|
Math.acos((Math.pow(adjacent, 2) + Math.pow(height, 2) - Math.pow(hypotenuse, 2)) / (2 * adjacent * height)) * (180 / Math.PI),
|
||||||
|
)
|
||||||
|
if (angle === 90) {
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return prev
|
||||||
|
}
|
||||||
|
}, undefined)
|
||||||
|
if (nextPoint) {
|
||||||
|
sortedPoints.push(nextPoint)
|
||||||
|
} else {
|
||||||
|
const nextPoint = otherPoints.reduce((prev, current) => {
|
||||||
|
if (prev !== undefined) {
|
||||||
|
const height = Math.abs(
|
||||||
|
Math.sqrt(Math.abs(Math.pow(prevPoint.x - lastPoint.x, 2)) + Math.abs(Math.pow(prevPoint.y - lastPoint.y, 2))),
|
||||||
|
)
|
||||||
|
const adjacentC = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - lastPoint.x, 2)) + Math.abs(Math.pow(current.y - lastPoint.y, 2))))
|
||||||
|
const hypotenuseC = Math.abs(
|
||||||
|
Math.sqrt(Math.abs(Math.pow(current.x - prevPoint.x, 2)) + Math.abs(Math.pow(current.y - prevPoint.y, 2))),
|
||||||
|
)
|
||||||
|
const angleC = Math.round(
|
||||||
|
Math.acos((Math.pow(adjacentC, 2) + Math.pow(height, 2) - Math.pow(hypotenuseC, 2)) / (2 * adjacentC * height)) * (180 / Math.PI),
|
||||||
|
)
|
||||||
|
const adjacentP = Math.abs(Math.sqrt(Math.abs(Math.pow(prev.x - lastPoint.x, 2)) + Math.abs(Math.pow(prev.y - lastPoint.y, 2))))
|
||||||
|
const hypotenuseP = Math.abs(Math.sqrt(Math.abs(Math.pow(prev.x - prevPoint.x, 2)) + Math.abs(Math.pow(prev.y - prevPoint.y, 2))))
|
||||||
|
const angleP = Math.round(
|
||||||
|
Math.acos((Math.pow(adjacentP, 2) + Math.pow(height, 2) - Math.pow(hypotenuseP, 2)) / (2 * adjacentP * height)) * (180 / Math.PI),
|
||||||
|
)
|
||||||
|
if (Math.abs(90 - angleC) < Math.abs(90 - angleP)) {
|
||||||
|
return current
|
||||||
|
} else {
|
||||||
|
return prev
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
}, undefined)
|
||||||
|
if (nextPoint) {
|
||||||
|
sortedPoints.push(nextPoint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (sortedPoints.length > 0) {
|
||||||
|
const roofPolygon = new QPolygon(sortedPoints, {
|
||||||
|
fill: 'transparent',
|
||||||
|
stroke: '#000000',
|
||||||
|
strokeWidth: 1,
|
||||||
|
selectable: false,
|
||||||
|
fontSize: roof.fontSize,
|
||||||
|
name: 'roofPolygon',
|
||||||
|
attributes: {
|
||||||
|
roofId: roof.id,
|
||||||
|
currentRoof: currentRoof.id,
|
||||||
|
pitch: currentRoof.attributes.pitch,
|
||||||
|
degree: currentRoof.attributes.degree,
|
||||||
|
direction: currentRoof.direction,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree
|
||||||
|
//지붕 각도에 따른 실측치 조정
|
||||||
|
roofPolygon.lines.forEach((line) => {
|
||||||
|
line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x2 - line.x1, 2) + Math.pow(line.y2 - line.y1, 2)) * 10)
|
||||||
|
const slope = (line) => (line.x2 - line.x1 === 0 ? Infinity : (line.y2 - line.y1) / (line.x2 - line.x1))
|
||||||
|
|
||||||
|
if (currentDegree > 0 && slope(line) !== slope(currentRoof)) {
|
||||||
|
const height = Math.tan(currentDegree * (Math.PI / 180)) * line.attributes.planeSize
|
||||||
|
line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.attributes.planeSize, 2) + Math.pow(height, 2)))
|
||||||
|
} else {
|
||||||
|
line.attributes.actualSize = line.attributes.planeSize
|
||||||
|
}
|
||||||
|
})
|
||||||
|
roof.separatePolygon.push(roofPolygon)
|
||||||
|
canvas.add(roofPolygon)
|
||||||
|
canvas.renderAll()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
duplicatedEaves.forEach((duplicatedEave) => {
|
||||||
|
const currentRoof = duplicatedEave[0]
|
||||||
|
let points = []
|
||||||
|
duplicatedEave.forEach((eave) => {
|
||||||
|
points.push({ x: eave.x1, y: eave.y1 }, { x: eave.x2, y: eave.y2 })
|
||||||
|
const currentRidges = ridges.filter((ridge) => ridge.attributes.currentRoof.includes(eave.id))
|
||||||
|
currentRidges.forEach((ridge) => {
|
||||||
|
points.push({ x: ridge.x1, y: ridge.y1 }, { x: ridge.x2, y: ridge.y2 })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
console.log('points', points)
|
||||||
|
points = points.filter((point, index, self) => index === self.findIndex((p) => p.x === point.x && p.y === point.y))
|
||||||
|
//point 정렬 (가장 좌측, 최상단의 점을 기준으로 삼는다.)
|
||||||
|
|
||||||
|
const startPoint = points
|
||||||
|
.filter((point) => point.x === Math.min(...points.map((point) => point.x)))
|
||||||
|
.reduce((prev, current) => {
|
||||||
|
return prev.y < current.y ? prev : current
|
||||||
|
})
|
||||||
|
|
||||||
|
const sortedPoints = []
|
||||||
|
sortedPoints.push(startPoint)
|
||||||
|
|
||||||
|
points.forEach((p, index) => {
|
||||||
|
if (index === 0) {
|
||||||
|
//시작점 다음 점 찾기, y좌표가 startPoint.y 보다 큰 점 중 x좌표가 가까운 점
|
||||||
|
const underStartPoint = points.filter((point) => point.y > startPoint.y)
|
||||||
|
const nextPoint = underStartPoint
|
||||||
|
.filter((point) => point.x === startPoint.x)
|
||||||
|
.reduce((prev, current) => {
|
||||||
|
if (prev === undefined) {
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
return Math.abs(prev.y - startPoint.y) < Math.abs(current.y - startPoint.y) ? prev : current
|
||||||
|
}, undefined)
|
||||||
|
if (nextPoint) {
|
||||||
|
sortedPoints.push(nextPoint)
|
||||||
|
} else {
|
||||||
|
const nextPoint = underStartPoint.reduce((prev, current) => {
|
||||||
|
const prevHypos = Math.sqrt(Math.abs(Math.pow(prev.x - startPoint.x, 2)) + Math.abs(Math.pow(prev.y - startPoint.y, 2)))
|
||||||
|
const currentHypos = Math.sqrt(Math.abs(Math.pow(current.x - startPoint.x, 2)) + Math.abs(Math.pow(current.y - startPoint.y, 2)))
|
||||||
|
return prevHypos < currentHypos ? prev : current
|
||||||
|
}, undefined)
|
||||||
|
sortedPoints.push(nextPoint)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const lastPoint = sortedPoints[sortedPoints.length - 1]
|
||||||
|
console.log('lastPoint', lastPoint)
|
||||||
|
const prevPoint = sortedPoints[sortedPoints.length - 2]
|
||||||
|
const otherPoints = points.filter((point) => sortedPoints.includes(point) === false)
|
||||||
|
const nextPoint = otherPoints.reduce((prev, current) => {
|
||||||
|
if (prev === undefined) {
|
||||||
|
const height = Math.abs(Math.sqrt(Math.abs(Math.pow(prevPoint.x - lastPoint.x, 2)) + Math.abs(Math.pow(prevPoint.y - lastPoint.y, 2))))
|
||||||
|
const adjacent = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - lastPoint.x, 2)) + Math.abs(Math.pow(current.y - lastPoint.y, 2))))
|
||||||
|
const hypotenuse = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - prevPoint.x, 2)) + Math.abs(Math.pow(current.y - prevPoint.y, 2))))
|
||||||
|
|
||||||
|
const angle = Math.round(
|
||||||
|
Math.acos((Math.pow(adjacent, 2) + Math.pow(height, 2) - Math.pow(hypotenuse, 2)) / (2 * adjacent * height)) * (180 / Math.PI),
|
||||||
|
)
|
||||||
|
if (angle === 90) {
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return prev
|
||||||
|
}
|
||||||
|
}, undefined)
|
||||||
|
if (nextPoint) {
|
||||||
|
sortedPoints.push(nextPoint)
|
||||||
|
} else {
|
||||||
|
const nextPoint = otherPoints.reduce((prev, current) => {
|
||||||
|
if (prev !== undefined) {
|
||||||
|
const height = Math.abs(
|
||||||
|
Math.sqrt(Math.abs(Math.pow(prevPoint.x - lastPoint.x, 2)) + Math.abs(Math.pow(prevPoint.y - lastPoint.y, 2))),
|
||||||
|
)
|
||||||
|
const adjacentC = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - lastPoint.x, 2)) + Math.abs(Math.pow(current.y - lastPoint.y, 2))))
|
||||||
|
const hypotenuseC = Math.abs(
|
||||||
|
Math.sqrt(Math.abs(Math.pow(current.x - prevPoint.x, 2)) + Math.abs(Math.pow(current.y - prevPoint.y, 2))),
|
||||||
|
)
|
||||||
|
const angleC = Math.round(
|
||||||
|
Math.acos((Math.pow(adjacentC, 2) + Math.pow(height, 2) - Math.pow(hypotenuseC, 2)) / (2 * adjacentC * height)) * (180 / Math.PI),
|
||||||
|
)
|
||||||
|
const adjacentP = Math.abs(Math.sqrt(Math.abs(Math.pow(prev.x - lastPoint.x, 2)) + Math.abs(Math.pow(prev.y - lastPoint.y, 2))))
|
||||||
|
const hypotenuseP = Math.abs(Math.sqrt(Math.abs(Math.pow(prev.x - prevPoint.x, 2)) + Math.abs(Math.pow(prev.y - prevPoint.y, 2))))
|
||||||
|
const angleP = Math.round(
|
||||||
|
Math.acos((Math.pow(adjacentP, 2) + Math.pow(height, 2) - Math.pow(hypotenuseP, 2)) / (2 * adjacentP * height)) * (180 / Math.PI),
|
||||||
|
)
|
||||||
|
if (Math.abs(90 - angleC) < Math.abs(90 - angleP)) {
|
||||||
|
return current
|
||||||
|
} else {
|
||||||
|
return prev
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
}, undefined)
|
||||||
|
if (nextPoint) {
|
||||||
|
sortedPoints.push(nextPoint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (sortedPoints.length > 0) {
|
||||||
|
const roofPolygon = new QPolygon(sortedPoints, {
|
||||||
|
fill: 'transparent',
|
||||||
|
stroke: '#000000',
|
||||||
|
strokeWidth: 1,
|
||||||
|
selectable: false,
|
||||||
|
fontSize: roof.fontSize,
|
||||||
|
name: 'roofPolygon',
|
||||||
|
attributes: {
|
||||||
|
roofId: roof.id,
|
||||||
|
currentRoof: currentRoof.id,
|
||||||
|
pitch: currentRoof.attributes.pitch,
|
||||||
|
degree: currentRoof.attributes.degree,
|
||||||
|
direction: currentRoof.direction,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree
|
||||||
|
//지붕 각도에 따른 실측치 조정
|
||||||
|
roofPolygon.lines.forEach((line) => {
|
||||||
|
line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x2 - line.x1, 2) + Math.pow(line.y2 - line.y1, 2)) * 10)
|
||||||
|
const slope = (line) => (line.x2 - line.x1 === 0 ? Infinity : (line.y2 - line.y1) / (line.x2 - line.x1))
|
||||||
|
|
||||||
|
if (currentDegree > 0 && slope(line) !== slope(currentRoof)) {
|
||||||
|
const height = Math.tan(currentDegree * (Math.PI / 180)) * line.attributes.planeSize
|
||||||
|
line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.attributes.planeSize, 2) + Math.pow(height, 2)))
|
||||||
|
} else {
|
||||||
|
line.attributes.actualSize = line.attributes.planeSize
|
||||||
|
}
|
||||||
|
})
|
||||||
|
roof.separatePolygon.push(roofPolygon)
|
||||||
|
canvas.add(roofPolygon)
|
||||||
|
canvas.renderAll()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
console.log('roof.separatePolygon : ', roof.separatePolygon)
|
||||||
|
|
||||||
|
ridges.forEach((ridge) => ridge.bringToFront())
|
||||||
|
console.log('ridges : ', ridges)
|
||||||
}
|
}
|
||||||
|
|
||||||
//형 올림내림 마우스 클릭 이벤트
|
//형 올림내림 마우스 클릭 이벤트
|
||||||
@ -295,18 +768,18 @@ export function useMovementSetting(id) {
|
|||||||
if (Math.sign(target.x1 - target.x2) !== 0) {
|
if (Math.sign(target.x1 - target.x2) !== 0) {
|
||||||
if (targetTop > currentY) {
|
if (targetTop > currentY) {
|
||||||
FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked = true
|
FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked = true
|
||||||
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.round(targetTop - currentY)) / 10000).toFixed(5) * 100000)
|
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.abs(Math.round(targetTop - currentY))) / 10000).toFixed(5) * 100000)
|
||||||
} else {
|
} else {
|
||||||
FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked = true
|
FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked = true
|
||||||
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.round(targetTop - currentY)) / 10000).toFixed(5) * 100000)
|
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.abs(Math.round(targetTop - currentY))) / 10000).toFixed(5) * 100000)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (targetLeft > currentX) {
|
if (targetLeft < currentX) {
|
||||||
FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked = true
|
FLOW_LINE_REF.UP_RIGHT_RADIO_REF.current.checked = true
|
||||||
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.round(currentX - targetLeft)) / 10000).toFixed(5) * 100000)
|
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.abs(Math.round(currentX - targetLeft))) / 10000).toFixed(5) * 100000)
|
||||||
} else {
|
} else {
|
||||||
FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked = true
|
FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked = true
|
||||||
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.round(currentX - targetLeft)) / 10000).toFixed(5) * 100000)
|
FLOW_LINE_REF.FILLED_INPUT_REF.current.value = Math.floor((Number(Math.abs(Math.round(currentX - targetLeft))) / 10000).toFixed(5) * 100000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -258,8 +258,6 @@ export function useRoofAllocationSetting(id) {
|
|||||||
return roof
|
return roof
|
||||||
})
|
})
|
||||||
|
|
||||||
newRoofList[selectedIndex].selected = true
|
|
||||||
|
|
||||||
setCurrentRoofList(newRoofList)
|
setCurrentRoofList(newRoofList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
||||||
import { canvasState, currentMenuState, currentObjectState } from '@/store/canvasAtom'
|
import { canvasState, currentMenuState, currentObjectState } from '@/store/canvasAtom'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { MENU } from '@/common/common'
|
import { MENU, POLYGON_TYPE } from '@/common/common'
|
||||||
import AuxiliarySize from '@/components/floor-plan/modal/auxiliary/AuxiliarySize'
|
import AuxiliarySize from '@/components/floor-plan/modal/auxiliary/AuxiliarySize'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
@ -40,6 +40,7 @@ import { useCanvasSetting } from './option/useCanvasSetting'
|
|||||||
import { useGrid } from './common/useGrid'
|
import { useGrid } from './common/useGrid'
|
||||||
import { useAdsorptionPoint } from './useAdsorptionPoint'
|
import { useAdsorptionPoint } from './useAdsorptionPoint'
|
||||||
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
||||||
|
import { MODULE_ALIGN_TYPE, useModule } from './module/useModule'
|
||||||
|
|
||||||
export function useContextMenu() {
|
export function useContextMenu() {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
@ -66,6 +67,7 @@ export function useContextMenu() {
|
|||||||
const commonTextFont = useRecoilValue(fontSelector('commonText'))
|
const commonTextFont = useRecoilValue(fontSelector('commonText'))
|
||||||
const { settingsData, setSettingsDataSave } = useCanvasSetting()
|
const { settingsData, setSettingsDataSave } = useCanvasSetting()
|
||||||
const { swalFire } = useSwal()
|
const { swalFire } = useSwal()
|
||||||
|
const { alignModule } = useModule()
|
||||||
const { removeRoofMaterial, removeAllRoofMaterial } = useRoofFn()
|
const { removeRoofMaterial, removeAllRoofMaterial } = useRoofFn()
|
||||||
|
|
||||||
const currentMenuSetting = () => {
|
const currentMenuSetting = () => {
|
||||||
@ -691,36 +693,38 @@ export function useContextMenu() {
|
|||||||
])
|
])
|
||||||
break
|
break
|
||||||
case 'moduleSetupSurface':
|
case 'moduleSetupSurface':
|
||||||
case 'dimensionLineText':
|
case 'roof':
|
||||||
setContextMenu([
|
setContextMenu([
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
id: 'moduleVerticalCenterAlign',
|
id: 'moduleVerticalCenterAlign',
|
||||||
name: getMessage('contextmenu.module.vertical.align'),
|
name: getMessage('contextmenu.module.vertical.align'),
|
||||||
|
fn: () => alignModule(MODULE_ALIGN_TYPE.VERTICAL),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'moduleHorizonCenterAlign',
|
id: 'moduleHorizonCenterAlign',
|
||||||
name: getMessage('contextmenu.module.horizon.align'),
|
name: getMessage('contextmenu.module.horizon.align'),
|
||||||
},
|
fn: () => alignModule(MODULE_ALIGN_TYPE.HORIZONTAL),
|
||||||
{
|
|
||||||
id: 'moduleLeftAlign',
|
|
||||||
name: getMessage('contextmenu.module.left.align'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'moduleRightAlign',
|
|
||||||
name: getMessage('contextmenu.module.right.align'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'moduleUpAlign',
|
|
||||||
name: getMessage('contextmenu.module.up.align'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'moduleDownAlign',
|
|
||||||
name: getMessage('contextmenu.module.down.align'),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'moduleRemove',
|
id: 'moduleRemove',
|
||||||
name: getMessage('contextmenu.module.remove'),
|
name: getMessage('contextmenu.module.remove'),
|
||||||
|
fn: () => {
|
||||||
|
const moduleSetupSurface = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
|
||||||
|
const modules = canvas.getObjects().filter((obj) => obj.surfaceId === moduleSetupSurface.id && obj.name === POLYGON_TYPE.MODULE)
|
||||||
|
canvas.remove(...modules)
|
||||||
|
canvas.renderAll()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'moduleMove',
|
||||||
|
name: getMessage('contextmenu.module.move'),
|
||||||
|
component: <PanelEdit id={popupId} type={PANEL_EDIT_TYPE.MOVE_ALL} />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'moduleCopy',
|
||||||
|
name: getMessage('contextmenu.module.copy'),
|
||||||
|
component: <PanelEdit id={popupId} type={PANEL_EDIT_TYPE.COPY_ALL} />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'moduleCircuitNumberEdit',
|
id: 'moduleCircuitNumberEdit',
|
||||||
|
|||||||
@ -1719,6 +1719,25 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const drawRoofPolygon = (wall) => {
|
const drawRoofPolygon = (wall) => {
|
||||||
|
const startLine = wall.lines
|
||||||
|
.filter((line) => line.x1 === Math.min(...wall.lines.map((line) => line.x1)))
|
||||||
|
.reduce((prev, current) => {
|
||||||
|
return prev.y1 < current.y1 ? prev : current
|
||||||
|
})
|
||||||
|
|
||||||
|
const beforeLine = [],
|
||||||
|
afterLine = []
|
||||||
|
let startIndex = wall.lines.findIndex((line) => line === startLine)
|
||||||
|
wall.lines.forEach((line, index) => {
|
||||||
|
if (index < startIndex) {
|
||||||
|
beforeLine.push(line)
|
||||||
|
} else {
|
||||||
|
afterLine.push(line)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
wall.lines = afterLine.concat(beforeLine)
|
||||||
|
|
||||||
const polygon = createRoofPolygon(wall.points)
|
const polygon = createRoofPolygon(wall.points)
|
||||||
const originPolygon = new QPolygon(wall.points, { fontSize: 0 })
|
const originPolygon = new QPolygon(wall.points, { fontSize: 0 })
|
||||||
originPolygon.setViewLengthText(false)
|
originPolygon.setViewLengthText(false)
|
||||||
|
|||||||
@ -44,6 +44,7 @@
|
|||||||
"plan.menu.roof.cover.eaves.kerava.edit": "처마·케라바 변경",
|
"plan.menu.roof.cover.eaves.kerava.edit": "처마·케라바 변경",
|
||||||
"plan.menu.roof.cover.movement.shape.updown": "동선이동·형올림내림(JA)",
|
"plan.menu.roof.cover.movement.shape.updown": "동선이동·형올림내림(JA)",
|
||||||
"modal.movement.flow.line.move": "銅線の移動軒",
|
"modal.movement.flow.line.move": "銅線の移動軒",
|
||||||
|
"modal.movement.flow.line.move.alert": "이동 할 수 없습니다.(JA)",
|
||||||
"modal.movement.flow.line.updown": "型上げ・降り",
|
"modal.movement.flow.line.updown": "型上げ・降り",
|
||||||
"modal.movement.flow.line.updown.info": "を選択して幅を指定してください桁の異なる辺。",
|
"modal.movement.flow.line.updown.info": "を選択して幅を指定してください桁の異なる辺。",
|
||||||
"modal.movement.flow.line.updown.up": "桁を上げる",
|
"modal.movement.flow.line.updown.up": "桁を上げる",
|
||||||
@ -631,7 +632,7 @@
|
|||||||
"stuff.detail.header.successCopy": "商品番号がコピーされました。",
|
"stuff.detail.header.successCopy": "商品番号がコピーされました。",
|
||||||
"stuff.detail.header.failCopy": "存在しないものです。",
|
"stuff.detail.header.failCopy": "存在しないものです。",
|
||||||
"stuff.detail.header.objectNo": "商品番号のコピーに失敗しました。",
|
"stuff.detail.header.objectNo": "商品番号のコピーに失敗しました。",
|
||||||
"stuff.detail.header.specificationConfirmDate": "仕様拡張日",
|
"stuff.detail.header.specificationConfirmDate": "仕様確認日",
|
||||||
"stuff.detail.header.lastEditDatetime": "更新日時",
|
"stuff.detail.header.lastEditDatetime": "更新日時",
|
||||||
"stuff.detail.header.createDatetime": "登録日",
|
"stuff.detail.header.createDatetime": "登録日",
|
||||||
"stuff.detail.required": "必須入力項目",
|
"stuff.detail.required": "必須入力項目",
|
||||||
@ -723,11 +724,15 @@
|
|||||||
"stuff.search.period": "期間検索",
|
"stuff.search.period": "期間検索",
|
||||||
"stuff.search.schDateTypeU": "更新日",
|
"stuff.search.schDateTypeU": "更新日",
|
||||||
"stuff.search.schDateTypeR": "登録日",
|
"stuff.search.schDateTypeR": "登録日",
|
||||||
|
"stuff.search.schTempFlgT": "一時保存物",
|
||||||
|
"stuff.search.schTempFlg": "含む",
|
||||||
|
"stuff.search.schTempFlg0": "除外",
|
||||||
|
"stuff.search.schTempFlg1": "一時的なものだけを見る",
|
||||||
"stuff.search.grid.title": "商品リスト",
|
"stuff.search.grid.title": "商品リスト",
|
||||||
"stuff.search.grid.all": "全体",
|
"stuff.search.grid.all": "全体",
|
||||||
"stuff.search.grid.selected": "選択",
|
"stuff.search.grid.selected": "選択",
|
||||||
"stuff.search.grid.schSortTypeR": "最近の登録日",
|
"stuff.search.grid.schSortTypeR": "最近の登録日",
|
||||||
"stuff.search.grid.schSortTypeU": "最近の更新日",
|
"stuff.search.grid.schSortTypeU": "最近修正日",
|
||||||
"stuff.windSelectPopup.title": "風速選択",
|
"stuff.windSelectPopup.title": "風速選択",
|
||||||
"stuff.windSelectPopup.table.selected": "選択",
|
"stuff.windSelectPopup.table.selected": "選択",
|
||||||
"stuff.windSelectPopup.table.windspeed": "風速",
|
"stuff.windSelectPopup.table.windspeed": "風速",
|
||||||
@ -801,6 +806,8 @@
|
|||||||
"main.storeName": "販売店名",
|
"main.storeName": "販売店名",
|
||||||
"main.objectNo": "物件番号",
|
"main.objectNo": "物件番号",
|
||||||
"main.faq": "FAQ",
|
"main.faq": "FAQ",
|
||||||
|
"main.content.objectList.noData1": "登録された商品情報はありません.",
|
||||||
|
"main.content.objectList.noData2": "下のボタンをクリックして商品情報を登録してください.",
|
||||||
"main.content.objectList": "最近の更新物件一覧",
|
"main.content.objectList": "最近の更新物件一覧",
|
||||||
"main.content.notice": "お知らせ",
|
"main.content.notice": "お知らせ",
|
||||||
"main.content.download1": "操作マニュアル",
|
"main.content.download1": "操作マニュアル",
|
||||||
@ -817,6 +824,7 @@
|
|||||||
"main.popup.login.btn2": "変更しない",
|
"main.popup.login.btn2": "変更しない",
|
||||||
"main.popup.login.validate1": "入力したパスワードが異なります。",
|
"main.popup.login.validate1": "入力したパスワードが異なります。",
|
||||||
"main.popup.login.validate2": "半角10文字以内で入力してください。",
|
"main.popup.login.validate2": "半角10文字以内で入力してください。",
|
||||||
|
"main.popup.login.validate3": "비밀번호를 입력해주세요.",
|
||||||
"main.popup.login.success": "パスワードが変更されました。",
|
"main.popup.login.success": "パスワードが変更されました。",
|
||||||
"common.canvas.validate.size": "寸法を入力してください.",
|
"common.canvas.validate.size": "寸法を入力してください.",
|
||||||
"surface.shape.validate.size.1to2": "①길이는 ②보다 큰 값을 넣어주세요.",
|
"surface.shape.validate.size.1to2": "①길이는 ②보다 큰 값을 넣어주세요.",
|
||||||
@ -941,5 +949,6 @@
|
|||||||
"can.not.move.module": "모듈을 이동할 수 없습니다.(JA)",
|
"can.not.move.module": "모듈을 이동할 수 없습니다.(JA)",
|
||||||
"can.not.copy.module": "모듈을 복사할 수 없습니다.(JA)",
|
"can.not.copy.module": "모듈을 복사할 수 없습니다.(JA)",
|
||||||
"can.not.remove.module": "모듈을 삭제할 수 없습니다.(JA)",
|
"can.not.remove.module": "모듈을 삭제할 수 없습니다.(JA)",
|
||||||
"can.not.insert.module": "모듈을 삽입할 수 없습니다.(JA)"
|
"can.not.insert.module": "모듈을 삽입할 수 없습니다.(JA)",
|
||||||
|
"can.not.align.module": "모듈을 정렬할 수 없습니다.(JA)"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,6 +44,7 @@
|
|||||||
"plan.menu.roof.cover.eaves.kerava.edit": "처마·케라바 변경",
|
"plan.menu.roof.cover.eaves.kerava.edit": "처마·케라바 변경",
|
||||||
"plan.menu.roof.cover.movement.shape.updown": "동선이동·형올림내림",
|
"plan.menu.roof.cover.movement.shape.updown": "동선이동·형올림내림",
|
||||||
"modal.movement.flow.line.move": "동선 이동",
|
"modal.movement.flow.line.move": "동선 이동",
|
||||||
|
"modal.movement.flow.line.move.alert": "이동 할 수 없습니다.",
|
||||||
"modal.movement.flow.line.updown": "형 올림·내림",
|
"modal.movement.flow.line.updown": "형 올림·내림",
|
||||||
"modal.movement.flow.line.updown.info": "자릿수가 다른 변을 선택하고 폭을 지정하십시오.",
|
"modal.movement.flow.line.updown.info": "자릿수가 다른 변을 선택하고 폭을 지정하십시오.",
|
||||||
"modal.movement.flow.line.updown.up": "자릿수를 올리다",
|
"modal.movement.flow.line.updown.up": "자릿수를 올리다",
|
||||||
@ -641,7 +642,7 @@
|
|||||||
"stuff.detail.header.successCopy": "물건번호가 복사되었습니다.",
|
"stuff.detail.header.successCopy": "물건번호가 복사되었습니다.",
|
||||||
"stuff.detail.header.failCopy": "물건번호 복사에 실패했습니다.",
|
"stuff.detail.header.failCopy": "물건번호 복사에 실패했습니다.",
|
||||||
"stuff.detail.header.objectNo": "물건번호",
|
"stuff.detail.header.objectNo": "물건번호",
|
||||||
"stuff.detail.header.specificationConfirmDate": "사양확장일",
|
"stuff.detail.header.specificationConfirmDate": "사양확정일",
|
||||||
"stuff.detail.header.lastEditDatetime": "갱신일시",
|
"stuff.detail.header.lastEditDatetime": "갱신일시",
|
||||||
"stuff.detail.header.createDatetime": "등록일",
|
"stuff.detail.header.createDatetime": "등록일",
|
||||||
"stuff.detail.required": "필수 입력항목",
|
"stuff.detail.required": "필수 입력항목",
|
||||||
@ -733,11 +734,15 @@
|
|||||||
"stuff.search.period": "기간검색",
|
"stuff.search.period": "기간검색",
|
||||||
"stuff.search.schDateTypeU": "갱신일",
|
"stuff.search.schDateTypeU": "갱신일",
|
||||||
"stuff.search.schDateTypeR": "등록일",
|
"stuff.search.schDateTypeR": "등록일",
|
||||||
|
"stuff.search.schTempFlgT": "임시저장 물건",
|
||||||
|
"stuff.search.schTempFlg": "포함",
|
||||||
|
"stuff.search.schTempFlg0": "제외",
|
||||||
|
"stuff.search.schTempFlg1": "임시물건만 조회",
|
||||||
"stuff.search.grid.title": "물건목록",
|
"stuff.search.grid.title": "물건목록",
|
||||||
"stuff.search.grid.all": "전체",
|
"stuff.search.grid.all": "전체",
|
||||||
"stuff.search.grid.selected": "선택",
|
"stuff.search.grid.selected": "선택",
|
||||||
"stuff.search.grid.schSortTypeR": "최근 등록일",
|
"stuff.search.grid.schSortTypeR": "최근 등록일",
|
||||||
"stuff.search.grid.schSortTypeU": "최근 갱신일",
|
"stuff.search.grid.schSortTypeU": "최근 수정일",
|
||||||
"stuff.windSelectPopup.title": "풍속선택",
|
"stuff.windSelectPopup.title": "풍속선택",
|
||||||
"stuff.windSelectPopup.table.selected": "선택",
|
"stuff.windSelectPopup.table.selected": "선택",
|
||||||
"stuff.windSelectPopup.table.windspeed": "풍속",
|
"stuff.windSelectPopup.table.windspeed": "풍속",
|
||||||
@ -811,6 +816,8 @@
|
|||||||
"main.storeName": "판매점명",
|
"main.storeName": "판매점명",
|
||||||
"main.objectNo": "물건번호",
|
"main.objectNo": "물건번호",
|
||||||
"main.faq": "FAQ",
|
"main.faq": "FAQ",
|
||||||
|
"main.content.objectList.noData1": "등록된 물건정보가 없습니다.",
|
||||||
|
"main.content.objectList.noData2": "아래 버튼을 클릭하여 물건정보를 등록하십시오.",
|
||||||
"main.content.objectList": "최근 갱신 물건목록",
|
"main.content.objectList": "최근 갱신 물건목록",
|
||||||
"main.content.notice": "공지사항",
|
"main.content.notice": "공지사항",
|
||||||
"main.content.download1": "조작메뉴얼",
|
"main.content.download1": "조작메뉴얼",
|
||||||
@ -827,6 +834,7 @@
|
|||||||
"main.popup.login.btn2": "변경안함",
|
"main.popup.login.btn2": "변경안함",
|
||||||
"main.popup.login.validate1": "입력한 패스워드가 다릅니다.",
|
"main.popup.login.validate1": "입력한 패스워드가 다릅니다.",
|
||||||
"main.popup.login.validate2": "반각 10자 이내로 입력해주세요.",
|
"main.popup.login.validate2": "반각 10자 이내로 입력해주세요.",
|
||||||
|
"main.popup.login.validate3": "비밀번호를 입력해주세요.",
|
||||||
"main.popup.login.success": "비밀번호가 변경되었습니다.",
|
"main.popup.login.success": "비밀번호가 변경되었습니다.",
|
||||||
"common.canvas.validate.size": "사이즈를 입력해 주세요.",
|
"common.canvas.validate.size": "사이즈를 입력해 주세요.",
|
||||||
"surface.shape.validate.size.1to2": "①길이는 ②보다 큰 값을 넣어주세요.",
|
"surface.shape.validate.size.1to2": "①길이는 ②보다 큰 값을 넣어주세요.",
|
||||||
@ -951,5 +959,6 @@
|
|||||||
"can.not.move.module": "모듈을 이동할 수 없습니다.",
|
"can.not.move.module": "모듈을 이동할 수 없습니다.",
|
||||||
"can.not.copy.module": "모듈을 복사할 수 없습니다.",
|
"can.not.copy.module": "모듈을 복사할 수 없습니다.",
|
||||||
"can.not.remove.module": "모듈을 삭제할 수 없습니다.",
|
"can.not.remove.module": "모듈을 삭제할 수 없습니다.",
|
||||||
"can.not.insert.module": "모듈을 삽입할 수 없습니다."
|
"can.not.insert.module": "모듈을 삽입할 수 없습니다.",
|
||||||
|
"can.not.align.module": "모듈을 정렬할 수 없습니다."
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,9 +17,10 @@ export const stuffSearchState = atom({
|
|||||||
schOtherSelSaleStoreId: '', //1차 이외 판매대리점 선택
|
schOtherSelSaleStoreId: '', //1차 이외 판매대리점 선택
|
||||||
startRow: 1,
|
startRow: 1,
|
||||||
endRow: 100,
|
endRow: 100,
|
||||||
schSortType: 'R', //정렬조건 (R:최근등록일 U:최근수정일)
|
schSortType: 'U', //정렬조건 (R:최근등록일 U:최근수정일)
|
||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
pageSize: 100,
|
pageSize: 100,
|
||||||
|
schTempFlg: '', //임시저장여부
|
||||||
},
|
},
|
||||||
dangerouslyAllowMutability: true,
|
dangerouslyAllowMutability: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -207,6 +207,7 @@ header{
|
|||||||
.select-box{
|
.select-box{
|
||||||
min-width: 165px;
|
min-width: 165px;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
|
height: 30px;
|
||||||
>div{
|
>div{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -155,6 +155,7 @@
|
|||||||
.product-item-content{
|
.product-item-content{
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
height: 100%;
|
||||||
.recently-list{
|
.recently-list{
|
||||||
.recently-item{
|
.recently-item{
|
||||||
border: 1px solid #F2F2F2;
|
border: 1px solid #F2F2F2;
|
||||||
@ -208,6 +209,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.recently-no-data{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
h3{
|
||||||
|
font-size: 16px;
|
||||||
|
color: #101010;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
p{
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
font-weight: 400;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
.notice-box{
|
.notice-box{
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|||||||
@ -317,7 +317,7 @@ export const drawGabledRoof = (roofId, canvas) => {
|
|||||||
// 처마라인의 기본속성 입력
|
// 처마라인의 기본속성 입력
|
||||||
const eaves = []
|
const eaves = []
|
||||||
roofLines.forEach((currentRoof, index) => {
|
roofLines.forEach((currentRoof, index) => {
|
||||||
if (currentRoof.attributes !== undefined && currentRoof.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
|
if (currentRoof.attributes?.type === LINE_TYPE.WALLLINE.EAVES) {
|
||||||
eaves.push({ index: index, roof: currentRoof, length: currentRoof.attributes.planeSize })
|
eaves.push({ index: index, roof: currentRoof, length: currentRoof.attributes.planeSize })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -325,291 +325,147 @@ export const drawGabledRoof = (roofId, canvas) => {
|
|||||||
const ridges = []
|
const ridges = []
|
||||||
eaves.sort((a, b) => a.length - b.length)
|
eaves.sort((a, b) => a.length - b.length)
|
||||||
|
|
||||||
eaves.forEach((eave) => {
|
eaves.forEach((eave, i) => {
|
||||||
if (ridges.length < ridgeCount) {
|
|
||||||
const index = eave.index,
|
|
||||||
currentRoof = eave.roof
|
|
||||||
const currentWall = wallLines[index]
|
|
||||||
|
|
||||||
//현재 지붕의 중심 좌표
|
|
||||||
const midX = Math.round(((currentRoof.x1 + currentRoof.x2) / 2) * 10) / 10
|
|
||||||
const midY = Math.round(((currentRoof.y1 + currentRoof.y2) / 2) * 10) / 10
|
|
||||||
const deltaX = currentWall.x2 - currentWall.x1
|
|
||||||
const deltaY = currentWall.y2 - currentWall.y1
|
|
||||||
const length = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
|
|
||||||
// currentWall 과 직각인 기울기 계산
|
|
||||||
const perpendicularDeltaX = deltaY / length
|
|
||||||
const perpendicularDeltaY = -deltaX / length
|
|
||||||
// midX와 midY를 기준으로 직각 기울기를 사용하여 midWallX와 midWallY 계산
|
|
||||||
const midWallX = midX + perpendicularDeltaX * length
|
|
||||||
const midWallY = midY + perpendicularDeltaY * length
|
|
||||||
|
|
||||||
const signX = Math.sign(midX - midWallX)
|
|
||||||
const signY = Math.sign(midY - midWallY)
|
|
||||||
const checkX = Math.round((midX - signX * checkLength) * 10) / 10
|
|
||||||
const checkY = Math.round((midY - signY * checkLength) * 10) / 10
|
|
||||||
|
|
||||||
const intersectLines = []
|
|
||||||
// 현재 지붕의 맞은편 지붕을 찾는다.
|
|
||||||
roofLines
|
|
||||||
.filter((line) => line !== currentRoof)
|
|
||||||
.forEach((line) => {
|
|
||||||
const intersect = edgesIntersection(
|
|
||||||
{ vertex1: { x: midX, y: midY }, vertex2: { x: checkX, y: checkY } },
|
|
||||||
{ vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } },
|
|
||||||
)
|
|
||||||
if (intersect && !intersect.isIntersectionOutside) {
|
|
||||||
intersectLines.push({ x: intersect.x, y: intersect.y, line: line })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 가장 가까운 지붕을 찾는다.
|
|
||||||
const intersect = intersectLines.reduce((prev, current) => {
|
|
||||||
if (prev !== undefined) {
|
|
||||||
const prevDistance = Math.sqrt(Math.pow(prev.x - midX, 2) + Math.pow(prev.y - midY, 2))
|
|
||||||
const currentDistance = Math.sqrt(Math.pow(current.x - midX, 2) + Math.pow(current.y - midY, 2))
|
|
||||||
return prevDistance >= currentDistance ? current : prev
|
|
||||||
} else {
|
|
||||||
return current
|
|
||||||
}
|
|
||||||
}, undefined)
|
|
||||||
|
|
||||||
const linesCenterX = Math.round(((midX + intersect.x) / 2) * 10) / 10
|
|
||||||
const linesCenterY = Math.round(((midY + intersect.y) / 2) * 10) / 10
|
|
||||||
|
|
||||||
let addLength = currentRoof.attributes.planeSize / 2 / 10
|
|
||||||
|
|
||||||
let centerLineX1 = Math.sign(currentRoof.x1 - currentRoof.x2) * addLength + linesCenterX
|
|
||||||
let centerLineY1 = Math.sign(currentRoof.y1 - currentRoof.y2) * addLength + linesCenterY
|
|
||||||
let centerLineX2 = Math.sign(currentRoof.x2 - currentRoof.x1) * addLength + linesCenterX
|
|
||||||
let centerLineY2 = Math.sign(currentRoof.y2 - currentRoof.y1) * addLength + linesCenterY
|
|
||||||
|
|
||||||
const point1Intersect = []
|
|
||||||
const point2Intersect = []
|
|
||||||
roofLines.forEach((line) => {
|
|
||||||
const point1 = edgesIntersection(
|
|
||||||
{ vertex1: { x: linesCenterX, y: linesCenterY }, vertex2: { x: centerLineX1, y: centerLineY1 } },
|
|
||||||
{ vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } },
|
|
||||||
)
|
|
||||||
if (point1 && !point1.isIntersectionOutside) {
|
|
||||||
point1Intersect.push({ x: point1.x, y: point1.y })
|
|
||||||
}
|
|
||||||
const point2 = edgesIntersection(
|
|
||||||
{ vertex1: { x: linesCenterX, y: linesCenterY }, vertex2: { x: centerLineX2, y: centerLineY2 } },
|
|
||||||
{ vertex1: { x: line.x1, y: line.y1 }, vertex2: { x: line.x2, y: line.y2 } },
|
|
||||||
)
|
|
||||||
if (point2 && !point2.isIntersectionOutside) {
|
|
||||||
point2Intersect.push({ x: point2.x, y: point2.y })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
point1Intersect.reduce((prev, current) => {
|
|
||||||
if (prev !== undefined) {
|
|
||||||
const prevDistance = Math.sqrt(Math.pow(prev.x - linesCenterX, 2) + Math.pow(prev.y - linesCenterY, 2))
|
|
||||||
const currentDistance = Math.sqrt(Math.pow(current.x - linesCenterX, 2) + Math.pow(current.y - linesCenterY, 2))
|
|
||||||
return prevDistance >= currentDistance ? current : prev
|
|
||||||
} else {
|
|
||||||
return current
|
|
||||||
}
|
|
||||||
}, undefined)
|
|
||||||
point2Intersect.reduce((prev, current) => {
|
|
||||||
if (prev !== undefined) {
|
|
||||||
const prevDistance = Math.sqrt(Math.pow(prev.x - linesCenterX, 2) + Math.pow(prev.y - linesCenterY, 2))
|
|
||||||
const currentDistance = Math.sqrt(Math.pow(current.x - linesCenterX, 2) + Math.pow(current.y - linesCenterY, 2))
|
|
||||||
return prevDistance >= currentDistance ? current : prev
|
|
||||||
} else {
|
|
||||||
return current
|
|
||||||
}
|
|
||||||
}, undefined)
|
|
||||||
|
|
||||||
if (point1Intersect.length > 0) {
|
|
||||||
centerLineX1 = point1Intersect[0].x
|
|
||||||
centerLineY1 = point1Intersect[0].y
|
|
||||||
}
|
|
||||||
if (point2Intersect.length > 0) {
|
|
||||||
centerLineX2 = point2Intersect[0].x
|
|
||||||
centerLineY2 = point2Intersect[0].y
|
|
||||||
}
|
|
||||||
|
|
||||||
const ridge = new QLine([centerLineX1, centerLineY1, centerLineX2, centerLineY2], {
|
|
||||||
fontSize: roof.fontSize,
|
|
||||||
stroke: '#1083E3',
|
|
||||||
strokeWidth: 2,
|
|
||||||
name: LINE_TYPE.SUBLINE.RIDGE,
|
|
||||||
attributes: { roofId: roof.id, currentRoof: currentRoof.id },
|
|
||||||
})
|
|
||||||
canvas.add(ridge)
|
|
||||||
canvas.renderAll()
|
|
||||||
ridges.push(ridge)
|
|
||||||
roof.innerLines.push(ridge)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
eaves.forEach((eave) => {
|
|
||||||
const index = eave.index,
|
const index = eave.index,
|
||||||
currentRoof = eave.roof
|
currentRoof = eave.roof
|
||||||
const currentWall = wallLines[index]
|
const currentWall = wallLines[index]
|
||||||
const prevRoof = index === 0 ? roofLines[wallLines.length - 1] : roofLines[index - 1]
|
|
||||||
const nextRoof = index === roofLines.length - 1 ? roofLines[0] : index === roofLines.length ? roofLines[1] : roofLines[index + 1]
|
|
||||||
|
|
||||||
const midX = Math.round(((currentRoof.x1 + currentRoof.x2) / 2) * 10) / 10
|
const oppositeLine = roofLines
|
||||||
const midY = Math.round(((currentRoof.y1 + currentRoof.y2) / 2) * 10) / 10
|
.filter((line) => line !== currentRoof) // 현재 벽라인을 제외한 나머지 벽라인
|
||||||
const deltaX = currentWall.x2 - currentWall.x1
|
.filter((line) => {
|
||||||
const deltaY = currentWall.y2 - currentWall.y1
|
if (currentRoof.x1 === currentRoof.x2) {
|
||||||
const length = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
|
const vector = Math.sign(currentRoof.y1 - currentRoof.y2)
|
||||||
// currentWall 과 직각인 기울기 계산
|
const vector2 = Math.sign(currentRoof.x1 - currentWall.x1)
|
||||||
const perpendicularDeltaX = deltaY / length
|
return line.x1 === line.x2 && Math.sign(line.y1 - line.y2) === -vector && Math.sign(currentRoof.x1 - line.x1) === vector2
|
||||||
const perpendicularDeltaY = -deltaX / length
|
}
|
||||||
// midX와 midY를 기준으로 직각 기울기를 사용하여 midWallX와 midWallY 계산
|
if (currentRoof.y1 === currentRoof.y2) {
|
||||||
const midWallX = midX + perpendicularDeltaX * length
|
const vector = Math.sign(currentRoof.x1 - currentRoof.x2)
|
||||||
const midWallY = midY + perpendicularDeltaY * length
|
const vector2 = Math.sign(currentRoof.y1 - currentWall.y1)
|
||||||
const signX = Math.sign(midX - midWallX)
|
return line.y1 === line.y2 && Math.sign(line.x1 - line.x2) === -vector && Math.sign(currentRoof.y1 - line.y1) === vector2
|
||||||
const signY = Math.sign(midY - midWallY)
|
}
|
||||||
|
}) // 현재 벽라인과 직교하는 벽라인
|
||||||
|
|
||||||
|
console.log('oppositeLine', oppositeLine)
|
||||||
|
|
||||||
|
// 현재 벽라인과 직교하는 벽라인 사이에 마루를 그린다.
|
||||||
|
oppositeLine.forEach((line) => {
|
||||||
|
let points // 마루의 시작점과 끝점
|
||||||
|
if (currentRoof.x1 === currentRoof.x2) {
|
||||||
|
const currentRoofYRange = [Math.min(currentRoof.y1, currentRoof.y2), Math.max(currentRoof.y1, currentRoof.y2)]
|
||||||
|
const lineYRange = [Math.min(line.y1, line.y2), Math.max(line.y1, line.y2)]
|
||||||
|
const overlapYRange = [Math.max(currentRoofYRange[0], lineYRange[0]), Math.min(currentRoofYRange[1], lineYRange[1])]
|
||||||
|
if (overlapYRange[1] - overlapYRange[0] > 0) {
|
||||||
|
const centerX = Math.round(((currentRoof.x1 + line.x1) / 2) * 10) / 10
|
||||||
|
points = [centerX, overlapYRange[0], centerX, overlapYRange[1]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentRoof.y1 === currentRoof.y2) {
|
||||||
|
const currentRoofXRange = [Math.min(currentRoof.x1, currentRoof.x2), Math.max(currentRoof.x1, currentRoof.x2)]
|
||||||
|
const lineXRange = [Math.min(line.x1, line.x2), Math.max(line.x1, line.x2)]
|
||||||
|
const overlapXRange = [Math.max(currentRoofXRange[0], lineXRange[0]), Math.min(currentRoofXRange[1], lineXRange[1])]
|
||||||
|
if (overlapXRange[1] - overlapXRange[0] > 0) {
|
||||||
|
const centerY = Math.round(((currentRoof.y1 + line.y1) / 2) * 10) / 10
|
||||||
|
points = [overlapXRange[0], centerY, overlapXRange[1], centerY]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 마루를 그린다.
|
||||||
|
if (points) {
|
||||||
|
const ridge = new QLine(points, {
|
||||||
|
fontSize: roof.fontSize,
|
||||||
|
stroke: '#1083E3',
|
||||||
|
strokeWidth: 1,
|
||||||
|
name: LINE_TYPE.SUBLINE.RIDGE,
|
||||||
|
attributes: { roofId: roof.id, currentRoof: [currentRoof.id] },
|
||||||
|
visible: false,
|
||||||
|
})
|
||||||
|
const duplicateRidge = ridges.find(
|
||||||
|
(ridge) => ridge.x1 === points[0] && ridge.y1 === points[1] && ridge.x2 === points[2] && ridge.y2 === points[3],
|
||||||
|
)
|
||||||
|
// 중복된 마루는 제외한다.
|
||||||
|
if (duplicateRidge) {
|
||||||
|
duplicateRidge.attributes.currentRoof.push(currentRoof.id)
|
||||||
|
} else {
|
||||||
|
canvas.add(ridge)
|
||||||
|
canvas.renderAll()
|
||||||
|
ridges.push(ridge)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// 처마마다 지붕 polygon 을 그린다.
|
||||||
|
eaves.forEach((eave, i) => {
|
||||||
|
const index = eave.index,
|
||||||
|
currentRoof = eave.roof
|
||||||
|
const currentWall = wallLines[index]
|
||||||
|
const currentRidges = ridges.filter((ridge) => ridge.attributes.currentRoof.includes(eave.roof.id))
|
||||||
let points = []
|
let points = []
|
||||||
const intersectRidge = []
|
const signX = Math.sign(currentRoof.x1 - currentRoof.x2)
|
||||||
// 현재 roof 가 wall 보다 작을때 이전, 다음 지붕의 offset 만큼 포인트를 조정한다.
|
let currentX1 = currentRoof.x1,
|
||||||
if (currentRoof.attributes.planeSize > currentWall.attributes.planeSize) {
|
currentY1 = currentRoof.y1,
|
||||||
points.push({ x: currentRoof.x1, y: currentRoof.y1 }, { x: currentRoof.x2, y: currentRoof.y2 })
|
currentX2 = currentRoof.x2,
|
||||||
} else if (currentRoof.attributes.planeSize === currentWall.attributes.planeSize) {
|
currentY2 = currentRoof.y2
|
||||||
const deltaX = currentRoof.x2 - currentRoof.x1
|
let changeX1 = [Math.min(currentRoof.x1, currentRoof.x2), Math.min(currentRoof.x1, currentRoof.x2)],
|
||||||
const deltaY = currentRoof.y2 - currentRoof.y1
|
changeY1 = [Math.min(currentRoof.y1, currentRoof.y2), Math.min(currentRoof.y1, currentRoof.y2)],
|
||||||
let x1 = currentRoof.x1,
|
changeX2 = [Math.max(currentRoof.x2, currentRoof.x1), Math.max(currentRoof.x2, currentRoof.x1)],
|
||||||
y1 = currentRoof.y1,
|
changeY2 = [Math.max(currentRoof.y2, currentRoof.y1), Math.max(currentRoof.y2, currentRoof.y1)]
|
||||||
x2 = currentRoof.x2,
|
|
||||||
y2 = currentRoof.y2
|
|
||||||
|
|
||||||
if (deltaX !== 0) {
|
if (signX === 0) {
|
||||||
const minX = Math.min(currentRoof.x1, currentRoof.x2, currentWall.x1, currentWall.x2)
|
currentY1 = Math.min(currentRoof.y1, currentRoof.y2, currentWall.y1, currentWall.y2)
|
||||||
const maxX = Math.max(currentRoof.x1, currentRoof.x2, currentWall.x1, currentWall.x2)
|
changeY1[1] = currentY1
|
||||||
if (x1 > x2) {
|
currentY2 = Math.max(currentRoof.y1, currentRoof.y2, currentWall.y1, currentWall.y2)
|
||||||
x1 = maxX
|
changeY2[1] = currentY2
|
||||||
x2 = minX
|
|
||||||
} else {
|
|
||||||
x1 = minX
|
|
||||||
x2 = maxX
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (deltaY !== 0) {
|
|
||||||
const minY = Math.min(currentRoof.y1, currentRoof.y2, currentWall.y1, currentWall.y2)
|
|
||||||
const maxY = Math.max(currentRoof.y1, currentRoof.y2, currentWall.y1, currentWall.y2)
|
|
||||||
if (y1 > y2) {
|
|
||||||
y1 = maxY
|
|
||||||
y2 = minY
|
|
||||||
} else {
|
|
||||||
y1 = minY
|
|
||||||
y2 = maxY
|
|
||||||
}
|
|
||||||
}
|
|
||||||
points.push({ x: x1, y: y1 }, { x: x2, y: y2 })
|
|
||||||
} else {
|
} else {
|
||||||
const deltaX = currentRoof.x2 - currentRoof.x1
|
currentX1 = Math.min(currentRoof.x1, currentRoof.x2, currentWall.x1, currentWall.x2)
|
||||||
const deltaY = currentRoof.y2 - currentRoof.y1
|
changeX1[1] = currentX1
|
||||||
points.push(
|
currentX2 = Math.max(currentRoof.x1, currentRoof.x2, currentWall.x1, currentWall.x2)
|
||||||
{ x: currentRoof.x1 - Math.sign(deltaX) * prevRoof.attributes.offset, y: currentRoof.y1 - Math.sign(deltaY) * prevRoof.attributes.offset },
|
changeX2[1] = currentX2
|
||||||
{ x: currentRoof.x2 + Math.sign(deltaX) * nextRoof.attributes.offset, y: currentRoof.y2 + Math.sign(deltaY) * nextRoof.attributes.offset },
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
ridges.forEach((ridge) => {
|
points.push({ x: currentX1, y: currentY1 }, { x: currentX2, y: currentY2 })
|
||||||
const ridgeMidX = (ridge.x1 + ridge.x2) / 2
|
|
||||||
const ridgeMidY = (ridge.y1 + ridge.y2) / 2
|
|
||||||
if (midX === ridgeMidX || midY === ridgeMidY) {
|
|
||||||
const intersection = edgesIntersection(
|
|
||||||
{ vertex1: { x: midX, y: midY }, vertex2: { x: ridgeMidX, y: ridgeMidY } },
|
|
||||||
{ vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } },
|
|
||||||
)
|
|
||||||
if (intersection && !intersection.isIntersectionOutside) {
|
|
||||||
intersectRidge.push({ line: ridge })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Math.sign(midX - ridgeMidX) === signX || Math.sign(midY - ridgeMidY) === signY) {
|
|
||||||
const prevIntersect = edgesIntersection(
|
|
||||||
{ vertex1: { x: prevRoof.x1, y: prevRoof.y1 }, vertex2: { x: prevRoof.x2, y: prevRoof.y2 } },
|
|
||||||
{ vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } },
|
|
||||||
)
|
|
||||||
const nextIntersect = edgesIntersection(
|
|
||||||
{ vertex1: { x: nextRoof.x1, y: nextRoof.y1 }, vertex2: { x: nextRoof.x2, y: nextRoof.y2 } },
|
|
||||||
{ vertex1: { x: ridge.x1, y: ridge.y1 }, vertex2: { x: ridge.x2, y: ridge.y2 } },
|
|
||||||
)
|
|
||||||
if (prevIntersect && !prevIntersect.isIntersectionOutside) {
|
|
||||||
intersectRidge.push({ line: ridge })
|
|
||||||
}
|
|
||||||
if (nextIntersect && !nextIntersect.isIntersectionOutside) {
|
|
||||||
intersectRidge.push({ line: ridge })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
intersectRidge.forEach((intersect) => {
|
currentRidges.forEach((ridge) => {
|
||||||
const line = intersect.line
|
let ridgeX1 = ridge.x1,
|
||||||
if (currentRoof.attributes.planeSize > currentWall.attributes.planeSize) {
|
ridgeY1 = ridge.y1,
|
||||||
points.push({ x: line.x1, y: line.y1 }, { x: line.x2, y: line.y2 })
|
ridgeX2 = ridge.x2,
|
||||||
} else if (currentRoof.attributes.planeSize === currentWall.attributes.planeSize) {
|
ridgeY2 = ridge.y2
|
||||||
const deltaX = currentRoof.x2 - currentRoof.x1
|
if (signX === 0) {
|
||||||
const deltaY = currentRoof.y2 - currentRoof.y1
|
ridgeY1 = Math.min(ridge.y1, ridge.y2)
|
||||||
let x1 = line.x1,
|
ridgeY2 = Math.max(ridge.y1, ridge.y2)
|
||||||
y1 = line.y1,
|
|
||||||
x2 = line.x2,
|
|
||||||
y2 = line.y2
|
|
||||||
if (deltaX !== 0) {
|
|
||||||
const minX = Math.min(currentWall.x1, currentWall.x2, currentRoof.x1, currentRoof.x2, line.x1, line.x2)
|
|
||||||
const maxX = Math.max(currentWall.x1, currentWall.x2, currentRoof.x1, currentRoof.x2, line.x1, line.x2)
|
|
||||||
if (x1 > x2) {
|
|
||||||
x1 = maxX
|
|
||||||
x2 = minX
|
|
||||||
} else {
|
|
||||||
x1 = minX
|
|
||||||
x2 = maxX
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (deltaY !== 0) {
|
|
||||||
const minY = Math.min(currentWall.y1, currentWall.y2, currentRoof.y1, currentRoof.y2, line.y1, line.y2)
|
|
||||||
const maxY = Math.max(currentWall.y1, currentWall.y2, currentRoof.y1, currentRoof.y2, line.y1, line.y2)
|
|
||||||
if (y1 > y2) {
|
|
||||||
y1 = maxY
|
|
||||||
y2 = minY
|
|
||||||
} else {
|
|
||||||
y1 = minY
|
|
||||||
y2 = maxY
|
|
||||||
}
|
|
||||||
}
|
|
||||||
points.push({ x: x1, y: y1 }, { x: x2, y: y2 })
|
|
||||||
} else {
|
} else {
|
||||||
let lineX1 = line.x1,
|
ridgeX1 = Math.min(ridge.x1, ridge.x2)
|
||||||
lineY1 = line.y1,
|
ridgeX2 = Math.max(ridge.x1, ridge.x2)
|
||||||
lineX2 = line.x2,
|
|
||||||
lineY2 = line.y2
|
|
||||||
const prevCheck1 = Math.sqrt(Math.pow(Math.round(lineX1 - currentRoof.x1), 2) + Math.pow(Math.round(lineY1 - currentRoof.y1), 2))
|
|
||||||
const prevCheck2 = Math.sqrt(Math.pow(Math.round(lineX2 - currentRoof.x1), 2) + Math.pow(Math.round(lineY2 - currentRoof.y1), 2))
|
|
||||||
const deltaX = currentRoof.x2 - currentRoof.x1
|
|
||||||
const deltaY = currentRoof.y2 - currentRoof.y1
|
|
||||||
if (prevCheck1 < prevCheck2) {
|
|
||||||
lineX1 = lineX1 - Math.sign(deltaX) * prevRoof.attributes.offset
|
|
||||||
lineY1 = lineY1 - Math.sign(deltaY) * prevRoof.attributes.offset
|
|
||||||
lineX2 = lineX2 + Math.sign(deltaX) * nextRoof.attributes.offset
|
|
||||||
lineY2 = lineY2 + Math.sign(deltaY) * nextRoof.attributes.offset
|
|
||||||
} else {
|
|
||||||
lineX1 = lineX1 + Math.sign(deltaX) * prevRoof.attributes.offset
|
|
||||||
lineY1 = lineY1 + Math.sign(deltaY) * prevRoof.attributes.offset
|
|
||||||
lineX2 = lineX2 - Math.sign(deltaX) * nextRoof.attributes.offset
|
|
||||||
lineY2 = lineY2 - Math.sign(deltaY) * nextRoof.attributes.offset
|
|
||||||
}
|
|
||||||
points.push({ x: lineX1, y: lineY1 }, { x: lineX2, y: lineY2 })
|
|
||||||
}
|
}
|
||||||
|
points.push({ x: ridgeX1, y: ridgeY1 }, { x: ridgeX2, y: ridgeY2 })
|
||||||
// canvas.remove(ridge)
|
|
||||||
// canvas.renderAll()
|
|
||||||
})
|
})
|
||||||
points = points.filter((point, index, self) => index === self.findIndex((p) => p.x === point.x && p.y === point.y))
|
|
||||||
|
|
||||||
|
points.forEach((point) => {
|
||||||
|
if (point.x === changeX1[0] && changeX1[0] !== changeX1[1]) {
|
||||||
|
point.x = changeX1[1]
|
||||||
|
}
|
||||||
|
if (point.x === changeX2[0] && changeX2[0] !== changeX2[1]) {
|
||||||
|
point.x = changeX2[1]
|
||||||
|
}
|
||||||
|
if (point.y === changeY1[0] && changeY1[0] !== changeY1[1]) {
|
||||||
|
point.y = changeY1[1]
|
||||||
|
}
|
||||||
|
if (point.y === changeY2[0] && changeY2[0] !== changeY2[1]) {
|
||||||
|
point.y = changeY2[1]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
//중복된 point 제거
|
||||||
|
points = points.filter((point, index, self) => index === self.findIndex((p) => p.x === point.x && p.y === point.y))
|
||||||
|
//point 정렬 (가장 좌측, 최상단의 점을 기준으로 삼는다.)
|
||||||
const startPoint = points
|
const startPoint = points
|
||||||
.filter((point) => point.x === Math.min(...points.map((point) => point.x)))
|
.filter((point) => point.x === Math.min(...points.map((point) => point.x)))
|
||||||
.reduce((prev, current) => {
|
.reduce((prev, current) => {
|
||||||
return prev.y < current.y ? prev : current
|
return prev.y < current.y ? prev : current
|
||||||
})
|
})
|
||||||
const sortedPoints = [startPoint]
|
|
||||||
|
const sortedPoints = []
|
||||||
|
sortedPoints.push(startPoint)
|
||||||
|
|
||||||
points.forEach((p, index) => {
|
points.forEach((p, index) => {
|
||||||
const lastPoint = sortedPoints[sortedPoints.length - 1]
|
|
||||||
console.log('lastPoint', lastPoint)
|
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
|
//시작점 다음 점 찾기, y좌표가 startPoint.y 보다 큰 점 중 x좌표가 가까운 점
|
||||||
const underStartPoint = points.filter((point) => point.y > startPoint.y)
|
const underStartPoint = points.filter((point) => point.y > startPoint.y)
|
||||||
const nextPoint = underStartPoint
|
const nextPoint = underStartPoint
|
||||||
.filter((point) => point.x === startPoint.x)
|
.filter((point) => point.x === startPoint.x)
|
||||||
@ -630,6 +486,8 @@ export const drawGabledRoof = (roofId, canvas) => {
|
|||||||
sortedPoints.push(nextPoint)
|
sortedPoints.push(nextPoint)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
const lastPoint = sortedPoints[sortedPoints.length - 1]
|
||||||
|
console.log('lastPoint', lastPoint)
|
||||||
const prevPoint = sortedPoints[sortedPoints.length - 2]
|
const prevPoint = sortedPoints[sortedPoints.length - 2]
|
||||||
const otherPoints = points.filter((point) => sortedPoints.includes(point) === false)
|
const otherPoints = points.filter((point) => sortedPoints.includes(point) === false)
|
||||||
const nextPoint = otherPoints.reduce((prev, current) => {
|
const nextPoint = otherPoints.reduce((prev, current) => {
|
||||||
@ -656,18 +514,14 @@ export const drawGabledRoof = (roofId, canvas) => {
|
|||||||
const height = Math.abs(Math.sqrt(Math.abs(Math.pow(prevPoint.x - lastPoint.x, 2)) + Math.abs(Math.pow(prevPoint.y - lastPoint.y, 2))))
|
const height = Math.abs(Math.sqrt(Math.abs(Math.pow(prevPoint.x - lastPoint.x, 2)) + Math.abs(Math.pow(prevPoint.y - lastPoint.y, 2))))
|
||||||
const adjacentC = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - lastPoint.x, 2)) + Math.abs(Math.pow(current.y - lastPoint.y, 2))))
|
const adjacentC = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - lastPoint.x, 2)) + Math.abs(Math.pow(current.y - lastPoint.y, 2))))
|
||||||
const hypotenuseC = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - prevPoint.x, 2)) + Math.abs(Math.pow(current.y - prevPoint.y, 2))))
|
const hypotenuseC = Math.abs(Math.sqrt(Math.abs(Math.pow(current.x - prevPoint.x, 2)) + Math.abs(Math.pow(current.y - prevPoint.y, 2))))
|
||||||
|
|
||||||
const angleC = Math.round(
|
const angleC = Math.round(
|
||||||
Math.acos((Math.pow(adjacentC, 2) + Math.pow(height, 2) - Math.pow(hypotenuseC, 2)) / (2 * adjacentC * height)) * (180 / Math.PI),
|
Math.acos((Math.pow(adjacentC, 2) + Math.pow(height, 2) - Math.pow(hypotenuseC, 2)) / (2 * adjacentC * height)) * (180 / Math.PI),
|
||||||
)
|
)
|
||||||
|
|
||||||
const adjacentP = Math.abs(Math.sqrt(Math.abs(Math.pow(prev.x - lastPoint.x, 2)) + Math.abs(Math.pow(prev.y - lastPoint.y, 2))))
|
const adjacentP = Math.abs(Math.sqrt(Math.abs(Math.pow(prev.x - lastPoint.x, 2)) + Math.abs(Math.pow(prev.y - lastPoint.y, 2))))
|
||||||
const hypotenuseP = Math.abs(Math.sqrt(Math.abs(Math.pow(prev.x - prevPoint.x, 2)) + Math.abs(Math.pow(prev.y - prevPoint.y, 2))))
|
const hypotenuseP = Math.abs(Math.sqrt(Math.abs(Math.pow(prev.x - prevPoint.x, 2)) + Math.abs(Math.pow(prev.y - prevPoint.y, 2))))
|
||||||
|
|
||||||
const angleP = Math.round(
|
const angleP = Math.round(
|
||||||
Math.acos((Math.pow(adjacentP, 2) + Math.pow(height, 2) - Math.pow(hypotenuseP, 2)) / (2 * adjacentP * height)) * (180 / Math.PI),
|
Math.acos((Math.pow(adjacentP, 2) + Math.pow(height, 2) - Math.pow(hypotenuseP, 2)) / (2 * adjacentP * height)) * (180 / Math.PI),
|
||||||
)
|
)
|
||||||
|
|
||||||
if (Math.abs(90 - angleC) < Math.abs(90 - angleP)) {
|
if (Math.abs(90 - angleC) < Math.abs(90 - angleP)) {
|
||||||
return current
|
return current
|
||||||
} else {
|
} else {
|
||||||
@ -683,10 +537,11 @@ export const drawGabledRoof = (roofId, canvas) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (sortedPoints.length > 0) {
|
if (sortedPoints.length > 0) {
|
||||||
const roofPolygon = new QPolygon(sortedPoints, {
|
const roofPolygon = new QPolygon(sortedPoints, {
|
||||||
fill: 'transparent',
|
fill: 'transparent',
|
||||||
stroke: 'blue',
|
stroke: '#1083E3',
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
selectable: false,
|
selectable: false,
|
||||||
fontSize: roof.fontSize,
|
fontSize: roof.fontSize,
|
||||||
@ -717,6 +572,10 @@ export const drawGabledRoof = (roofId, canvas) => {
|
|||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (ridges.length > 0) {
|
||||||
|
ridges.forEach((ridge) => roof.innerLines.push(ridge))
|
||||||
|
}
|
||||||
//기준선 제거
|
//기준선 제거
|
||||||
// ridges.forEach((ridge) => canvas.remove(ridge))
|
// ridges.forEach((ridge) => canvas.remove(ridge))
|
||||||
}
|
}
|
||||||
@ -1049,7 +908,7 @@ const isInnerLine = (prevLine, currentLine, nextLine, line) => {
|
|||||||
* @param line2
|
* @param line2
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
const segmentsOverlap = (line1, line2) => {
|
export const segmentsOverlap = (line1, line2) => {
|
||||||
if (line1.y1 === line1.y2 && line2.y1 === line2.y2 && line1.y1 === line2.y1) {
|
if (line1.y1 === line1.y2 && line2.y1 === line2.y2 && line1.y1 === line2.y1) {
|
||||||
if ((line1.x1 <= line2.x1 && line1.x2 >= line2.x1) || (line1.x1 <= line2.x2 && line1.x2 >= line2.x2)) {
|
if ((line1.x1 <= line2.x1 && line1.x2 >= line2.x1) || (line1.x1 <= line2.x2 && line1.x2 >= line2.x2)) {
|
||||||
return true
|
return true
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user