Compare commits

...

13 Commits

8 changed files with 265 additions and 33 deletions

View File

@ -35,4 +35,4 @@ The easiest way to deploy your Next.js app is to use the [Vercel Platform](https
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
test
deploy test

View File

@ -24,7 +24,7 @@
"js-cookie": "^3.0.5",
"mathjs": "^13.0.2",
"mssql": "^11.0.1",
"next": "14.2.25",
"next": "14.2.26",
"next-international": "^1.2.4",
"react": "^18",
"react-chartjs-2": "^5.2.0",

View File

@ -1,5 +1,6 @@
import { GlobalDataContext } from '@/app/GlobalDataProvider'
import QSelectBox from '@/components/common/select/QSelectBox'
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
import { useModuleTrestle } from '@/hooks/module/useModuleTrestle'
import { useMessage } from '@/hooks/useMessage'
import { currentAngleTypeSelector, pitchTextSelector } from '@/store/canvasAtom'
@ -45,18 +46,22 @@ const Trestle = forwardRef((props, ref) => {
const selectedModules = useRecoilValue(selectedModuleState) //
// const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState)
const [lengthBase, setLengthBase] = useState(0)
const [hajebichi, setHajebichi] = useState(trestleState?.roofPitch ?? 0)
const [hajebichi, setHajebichi] = useState(0)
const [selectedRaftBase, setSelectedRaftBase] = useState(null)
const [selectedTrestle, setSelectedTrestle] = useState(null)
const [selectedConstMthd, setSelectedConstMthd] = useState(null)
const [selectedConstruction, setSelectedConstruction] = useState(null)
const [selectedRoofBase, setSelectedRoofBase] = useState(null)
const { managementState } = useContext(GlobalDataContext)
const { restoreModuleInstArea } = useModuleBasicSetting()
useEffect(() => {
if (roofs && !selectedRoof) {
setSelectedRoof(roofs[0])
}
//
restoreModuleInstArea()
}, [roofs])
useEffect(() => {
@ -196,12 +201,10 @@ const Trestle = forwardRef((props, ref) => {
stdWindSpeed: managementState?.standardWindSpeedId ?? '',
stdSnowLd: +managementState?.verticalSnowCover ?? '',
inclCd: selectedRoof?.pitch.toString() ?? 0,
// roofPitch: Math.round(selectedRoof?.roofPchBase ?? 0),
roofPitch: hajebichi ?? 0,
roofPitch: Math.round(selectedRoof?.roofPchBase ?? 0),
constTp: constructionList[index].constTp,
mixMatlNo: selectedModules.mixMatlNo,
// workingWidth: selectedRoof?.length.toString() ?? '',
workingWidth: lengthBase ?? '',
workingWidth: selectedRoof?.length.toString() ?? '',
// snowGdPossYn: constructionList[index].snowGdPossYn,
// cvrYn: constructionList[index].cvrYn,
},
@ -256,6 +259,8 @@ const Trestle = forwardRef((props, ref) => {
}
})
console.log('newAddedRoofs', newAddedRoofs)
if (result) {
setRoofs(newAddedRoofs)
setModuleSelectionData({
@ -272,8 +277,8 @@ const Trestle = forwardRef((props, ref) => {
...roof.trestle,
},
construction: {
...moduleSelectionData.roofConstructions[index]?.construction,
...roof.construction,
...moduleSelectionData.roofConstructions[index]?.construction,
},
trestleDetail: {
...roof.trestleDetail,
@ -339,7 +344,7 @@ const Trestle = forwardRef((props, ref) => {
<input
type="text"
className="input-origin block"
value={lengthBase}
value={trestleState?.lengthBase}
onChange={(e) => setLengthBase(e.target.value)}
disabled={selectedRoof.lenAuth === 'R'}
/>
@ -380,7 +385,7 @@ const Trestle = forwardRef((props, ref) => {
type="text"
className="input-origin block"
disabled={selectedRoof.roofPchAuth === 'R'}
onChange={(e) => setHajebichi(e.target.value)}
onChange={(e) => handleHajebichiAndLength(e, 'hajebichi')}
value={hajebichi}
/>
</div>

View File

@ -94,17 +94,9 @@ export function useModuleBasicSetting(tabNum) {
const listParams = roofConstructions.map((item) => {
return {
...common,
roofMatlCd: item.addRoof.roofMatlCd,
trestleMkrCd: item.addRoof.trestleMkrCd,
constMthdCd: item.addRoof.constMthdCd,
roofBaseCd: item.addRoof.roofBaseCd,
constTp: item.addRoof.constTp,
mixMatlNo: selectedModules.mixMatlNo,
...item.addRoof,
roofPitch: item.addRoof.hajebichi ? item.addRoof.hajebichi : 0,
inclCd: String(item.addRoof.pitch),
roofIndex: item.addRoof.index,
workingWidth: item.addRoof.lenBase,
raftBaseCd: item.trestle.raftBaseCd,
}
})
setTrestleDetailParams(listParams)
@ -177,9 +169,11 @@ export function useModuleBasicSetting(tabNum) {
trestleDetailList.forEach((detail) => {
const moduleRowArray = []
detail.data.module.forEach((module) => {
moduleRowArray.push({ moduleMaxRows: module.moduleMaxRows, mixModuleMaxRows: module.mixModuleMaxRows })
})
if (detail.data !== null && detail.data.module.length > 0) {
detail.data.module.forEach((module) => {
moduleRowArray.push({ moduleMaxRows: module.moduleMaxRows, mixModuleMaxRows: module.mixModuleMaxRows })
})
}
rowColArray.push(moduleRowArray)
})
setModuleRowColArray(rowColArray)
@ -1277,6 +1271,16 @@ export function useModuleBasicSetting(tabNum) {
})
addCanvasMouseEventListener('mouse:up', (e) => {
if (trestlePolygon.modules.length > 0) {
//이미 설치된 모듈중에 한개만 가져옴
const mixAsgYn = trestlePolygon.modules[0].moduleInfo.mixAsgYn
//현재 체크된 모듈기준으로 혼합가능인지 확인 Y === Y, N === N 일때만 설치 가능
if (checkedModule[0].mixAsgYn !== mixAsgYn) {
swalFire({ text: getMessage('modal.module.basic.setting.module.placement.mix.asg.yn.error') })
return
}
}
if (!inside) return
//입력받은 값의 합

View File

@ -370,7 +370,20 @@ export const useTrestle = () => {
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
} else if (leftRowsInfo.rowsInfo.length >= 2) {
//C1C2C3인 경우
if (rack.value.moduleTpCd.length === 6) {
// 변환 C1C2만 있는경우 C3 0개로 추가해준다.
let newLeftRowsInfo = normalizeModules(rack.value.moduleTpCd, leftRowsInfo)
return (
rack.value.moduleTpCd === newLeftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === newLeftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
Number(rack.value.moduleTpRows1) === newLeftRowsInfo.rowsInfo[0].count &&
Number(rack.value.moduleTpRows2) === newLeftRowsInfo.rowsInfo[1].count &&
Number(rack.value.moduleTpRows3) === newLeftRowsInfo.rowsInfo[2].count
)
}
return (
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
@ -387,7 +400,19 @@ export const useTrestle = () => {
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
} else if (rightRowsInfo.rowsInfo.length === 2) {
if (rack.value.moduleTpCd.length === 6) {
// 변환 C1C2만 있는경우 C3 0개로 추가해준다.
let newRightRowsInfo = normalizeModules(rack.value.moduleTpCd, rightRowsInfo)
return (
rack.value.moduleTpCd === newRightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === newRightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
Number(rack.value.moduleTpRows1) === newRightRowsInfo.rowsInfo[0].count &&
Number(rack.value.moduleTpRows2) === newRightRowsInfo.rowsInfo[1].count &&
Number(rack.value.moduleTpRows3) === newRightRowsInfo.rowsInfo[2].count
)
}
return (
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
@ -404,7 +429,19 @@ export const useTrestle = () => {
rack.value.moduleTpCd === centerRowsInfo.moduleTotalTp &&
rack.value.moduleRows === centerRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
} else if (centerRowsInfo.rowsInfo.length === 2) {
if (rack.value.moduleTpCd.length === 6) {
// 변환 C1C2만 있는경우 C3 0개로 추가해준다.
let newCenterRowsInfo = normalizeModules(rack.value.moduleTpCd, centerRowsInfo)
return (
rack.value.moduleTpCd === newCenterRowsInfo.moduleTotalTp &&
rack.value.moduleRows === newCenterRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
Number(rack.value.moduleTpRows1) === newCenterRowsInfo.rowsInfo[0].count &&
Number(rack.value.moduleTpRows2) === newCenterRowsInfo.rowsInfo[1].count &&
Number(rack.value.moduleTpRows3) === newCenterRowsInfo.rowsInfo[2].count
)
}
return (
rack.value.moduleTpCd === centerRowsInfo.moduleTotalTp &&
rack.value.moduleRows === centerRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
@ -499,7 +536,19 @@ export const useTrestle = () => {
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
} else if (leftRowsInfo.rowsInfo.length === 2) {
if (rack.value.moduleTpCd.length === 6) {
// 변환 C1C2만 있는경우 C3 0개로 추가해준다.
let newLeftRowsInfo = normalizeModules(rack.value.moduleTpCd, leftRowsInfo)
return (
rack.value.moduleTpCd === newLeftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === newLeftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
Number(rack.value.moduleTpRows1) === newLeftRowsInfo.rowsInfo[0].count &&
Number(rack.value.moduleTpRows2) === newLeftRowsInfo.rowsInfo[1].count &&
Number(rack.value.moduleTpRows3) === newLeftRowsInfo.rowsInfo[2].count
)
}
return (
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
@ -575,7 +624,19 @@ export const useTrestle = () => {
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
} else if (rightRowsInfo.rowsInfo.length === 2) {
if (rack.value.moduleTpCd.length === 6) {
// 변환 C1C2만 있는경우 C3 0개로 추가해준다.
let newRightRowsInfo = normalizeModules(rack.value.moduleTpCd, rightRowsInfo)
return (
rack.value.moduleTpCd === newRightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === newRightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
Number(rack.value.moduleTpRows1) === newRightRowsInfo.rowsInfo[0].count &&
Number(rack.value.moduleTpRows2) === newRightRowsInfo.rowsInfo[1].count &&
Number(rack.value.moduleTpRows3) === newRightRowsInfo.rowsInfo[2].count
)
}
return (
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
@ -635,6 +696,31 @@ export const useTrestle = () => {
return { moduleTotalTp, rowsInfo }
}
function normalizeModules(rackTpCd, data) {
// rackTpCd를 숫자를 기준으로 자른다.
const allModules = rackTpCd.match(/[A-Za-z]+\d+/g) || [] // 모든 모듈 유형
// 현재 존재하는 모듈 유형을 추출
const existingModules = data.rowsInfo.map((row) => row.moduleTpCd)
const result = { ...data, rowsInfo: [...data.rowsInfo] }
// 없는 모듈을 추가 (count: 0)
allModules.forEach((module) => {
if (!existingModules.includes(module)) {
result.rowsInfo.push({ moduleTpCd: module, count: 0 })
}
})
// rowsInfo를 C1, C2, C3 순서로 정렬
result.rowsInfo.sort((a, b) => allModules.indexOf(a.moduleTpCd) - allModules.indexOf(b.moduleTpCd))
// moduleTotalTp를 C1C2C3로 설정
result.moduleTotalTp = allModules.join('')
return result
}
// itemList 조회 후 estimateParam에 저장
const getEstimateData = async () => {
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
@ -2131,12 +2217,13 @@ export const useTrestle = () => {
const visited = new Set()
const width = Math.floor(moduleExample.width)
const height = Math.floor(moduleExample.height)
const horizonPadding = 0 // 가로 패딩
const verticalPadding = 0 // 세로 패딩
const horizonPadding = 3 // 가로 패딩
const verticalPadding = 7 // 세로 패딩
function isAdjacent(p1, p2) {
const dx = Math.abs(p1.x - p2.x)
const dy = Math.abs(p1.y - p2.y)
return (
(Math.abs(width + horizonPadding - dx) < 2 && dy < 2) ||
(dx < 2 && Math.abs(dy - height + verticalPadding)) < 2 ||
@ -2168,6 +2255,128 @@ export const useTrestle = () => {
return groups
}
function areConnected(m1, m2, surface) {
/*const m1Fill = m1.fill
const m2Fill = m2.fill
m1.set({ fill: 'red' })
m2.set({ fill: 'blue' })
canvas.renderAll()*/
let sizes = []
const { width: currentWidth, height: currentHeight, moduleInfo: currentModuleInfo } = m1
const { width: neighborWidth, height: neighborHeight, moduleInfo: neighborModuleInfo } = m2
const { moduleTpCd: currentModuleTpCd } = currentModuleInfo
const { moduleTpCd: neighborModuleTpCd } = neighborModuleInfo
const { x: m1X, y: m1Y } = m1.getCenterPoint()
const { x: m2X, y: m2Y } = m2.getCenterPoint()
sizes.push({ width: currentWidth, height: currentHeight })
if (currentModuleTpCd !== neighborModuleTpCd) {
sizes.push({ width: neighborWidth, height: neighborHeight })
}
/*m1.set({ fill: m1Fill })
m2.set({ fill: m2Fill })
canvas.renderAll()*/
return sizes.some(({ width, height }) => {
let maxX
let maxY
let halfMaxX
let halfMaxY
const { direction, trestleDetail } = surface
const { moduleIntvlHor, moduleIntvlVer } = trestleDetail
if (direction === 'south' || direction === 'north') {
maxX = width + moduleIntvlHor / 10
maxY = height + moduleIntvlVer / 10
halfMaxX = moduleIntvlHor / 10
halfMaxY = moduleIntvlVer / 10
if (currentModuleTpCd !== neighborModuleTpCd) {
maxX = currentWidth / 2 + neighborWidth / 2 + moduleIntvlHor / 10
maxY = currentHeight / 2 + neighborHeight / 2 + moduleIntvlVer / 10
}
// console.log(maxX, maxY, halfMaxX, halfMaxY)
if (Math.abs(m1X - m2X) < 1) {
return Math.abs(Math.abs(m1Y - m2Y) - maxY) < 1
} else if (Math.abs(m1Y - m2Y) < 1) {
return Math.abs(Math.abs(m1X - m2X) - maxX) < 1
}
return (
(Math.abs(m1X - m2X) <= maxX && Math.abs(m1Y - m2Y) <= maxY) ||
(Math.abs(Math.abs(m1X - m2X) - maxX / 2) <= halfMaxX && Math.abs(Math.abs(m1Y - m2Y) - maxY) <= halfMaxY) ||
(Math.abs(Math.abs(m1X - m2X) - maxX) <= halfMaxX && Math.abs(Math.abs(m1Y - m2Y) - maxY / 2) <= halfMaxY)
)
} else if (direction === 'east' || direction === 'west') {
maxX = height + moduleIntvlHor / 10
maxY = width + moduleIntvlVer / 10
halfMaxX = moduleIntvlVer / 10
halfMaxY = moduleIntvlHor / 10
if (currentModuleTpCd !== neighborModuleTpCd) {
maxX = currentHeight / 2 + neighborHeight / 2 + moduleIntvlVer / 10
maxY = currentWidth / 2 + neighborWidth / 2 + moduleIntvlHor / 10
}
if (Math.abs(m1X - m2X) < 1) {
return Math.abs(Math.abs(m1Y - m2Y) - maxX) < 1
} else if (Math.abs(m1Y - m2Y) < 1) {
return Math.abs(Math.abs(m1X - m2X) - maxY) < 1
}
return (
(Math.abs(m1X - m2X) <= maxY && Math.abs(m1Y - m2Y) <= maxX) ||
(Math.abs(Math.abs(m1X - m2X) - maxY / 2) <= halfMaxY && Math.abs(Math.abs(m1Y - m2Y) - maxX) <= halfMaxX) ||
(Math.abs(Math.abs(m1X - m2X) - maxY) <= halfMaxY && Math.abs(Math.abs(m1Y - m2Y) - maxX / 2) <= halfMaxX)
)
}
})
}
// 25-04-02 추가
// 그룹화
function groupPoints(modules, surface) {
const groups = []
const visited = new Set()
for (const point of modules) {
const { x: pointX, y: pointY } = point.getCenterPoint()
const key = `${pointX},${pointY}`
if (visited.has(key)) continue
const queue = [point]
const group = []
while (queue.length > 0) {
const current = queue.shift()
const { x: currentX, y: currentY } = current.getCenterPoint()
const currentKey = `${currentX},${currentY}`
if (visited.has(currentKey)) continue
visited.add(currentKey)
group.push(current)
for (const neighbor of modules) {
const { x: neighborX, y: neighborY } = neighbor.getCenterPoint()
const neighborKey = `${neighborX},${neighborY}`
if (!visited.has(neighborKey) && areConnected(current, neighbor, surface)) {
queue.push(neighbor)
}
}
}
groups.push(group)
}
return groups
}
// 각도에 따른 길이 반환
function getTrestleLength(length, degree) {
if (roofSizeSet !== 1) {
@ -2865,5 +3074,15 @@ export const useTrestle = () => {
return surfaces.every((surface) => surface.isComplete)
}
return { apply, getTrestleParams, clear, setViewCircuitNumberTexts, getEstimateData, setAllModuleSurfaceIsComplete, isAllComplete }
return {
apply,
getTrestleParams,
clear,
setViewCircuitNumberTexts,
getEstimateData,
setAllModuleSurfaceIsComplete,
isAllComplete,
groupCoordinates,
groupPoints,
}
}

View File

@ -123,6 +123,7 @@ export function useCanvasSetting(executeEffect = true) {
const resetModuleSelectionData = useResetRecoilState(moduleSelectionDataState) /* 다음으로 넘어가는 최종 데이터 */
const resetSelectedModules = useResetRecoilState(selectedModuleState) /* 선택된 모듈 */
const { trigger: orientationTrigger } = useCanvasPopupStatusController(1)
const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2)
const [raftCodes, setRaftCodes] = useState([]) /* 서까래 정보 */
@ -526,7 +527,10 @@ export function useCanvasSetting(executeEffect = true) {
/** 모듈 선택 데이터 초기화 */
resetModuleSelectionData()
moduleSelectedDataTrigger({ common: {}, module: {}, roofConstructions: [] })
//1번 초기화
orientationTrigger({ compasDeg: 0, common: {}, module: {} })
//2번 초기화
moduleSelectedDataTrigger({ roofConstructions: [] })
const isModuleExist = canvas.getObjects().some((obj) => obj.name === POLYGON_TYPE.MODULE)
if (!isModuleExist) {
resetSelectedModules()

View File

@ -552,7 +552,7 @@ export function useRoofAllocationSetting(id) {
const modifyModuleSelectionData = () => {
if (moduleSelectionData.roofConstructions.length > 0) {
setModuleSelectionData({ ...moduleSelectionData, roofConstructions: [] })
moduleSelectedDataTrigger({ ...moduleSelectionData, roofConstructions: [] })
moduleSelectedDataTrigger({ roofConstructions: [] })
}
}

View File

@ -137,7 +137,7 @@
"modal.module.basic.setting.pitch.module.row.margin": "上下間隔",
"modal.module.basic.setting.pitch.module.column.amount": "列数",
"modal.module.basic.setting.pitch.module.column.margin": "左右間隔",
"modal.module.basic.setting.prev": "移転",
"modal.module.basic.setting.prev": "前に戻る",
"modal.module.basic.setting.row.batch": "単数指定配置",
"modal.module.basic.setting.passivity.placement": "手動配置",
"modal.module.basic.setting.auto.placement": "自動配置",