feat: Add CAD file conversion functionality to Playground component
This commit is contained in:
parent
b2b528fc07
commit
7a150be069
@ -1,10 +1,10 @@
|
|||||||
NEXT_PUBLIC_TEST="테스트변수입니다. development"
|
NEXT_PUBLIC_TEST="테스트변수입니다. development"
|
||||||
|
|
||||||
NEXT_PUBLIC_API_SERVER_PATH="http://1.248.227.176:38080"
|
NEXT_PUBLIC_API_SERVER_PATH="http://1.248.227.176:38080"
|
||||||
# NEXT_PUBLIC_API_SERVER_PATH="http://localhost:8080"
|
# NEXT_PUBLIC_API_SERVER_PATH="http://localhost:8080"
|
||||||
|
|
||||||
DATABASE_URL="sqlserver://mssql.devgrr.kr:1433;database=qcast;user=qcast;password=Qwertqaz12345;trustServerCertificate=true"
|
DATABASE_URL="sqlserver://mssql.devgrr.kr:1433;database=qcast;user=qcast;password=Qwertqaz12345;trustServerCertificate=true"
|
||||||
|
|
||||||
SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y="
|
SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y="
|
||||||
|
|
||||||
CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3"
|
NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3"
|
||||||
@ -6,4 +6,4 @@ DATABASE_URL=""
|
|||||||
|
|
||||||
SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y="
|
SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y="
|
||||||
|
|
||||||
CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3"
|
NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3"
|
||||||
@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useState } from 'react'
|
import { useRef, useState } from 'react'
|
||||||
import { Button, Table, TableBody, TableCell, TableColumn, TableHeader, TableRow } from '@nextui-org/react'
|
import { Button } from '@nextui-org/react'
|
||||||
import ColorPicker from './common/color-picker/ColorPicker'
|
import ColorPicker from './common/color-picker/ColorPicker'
|
||||||
|
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
@ -12,11 +12,16 @@ import { convertDwgToPng } from '@/lib/cadAction'
|
|||||||
import QSelect from '@/components/ui/QSelect'
|
import QSelect from '@/components/ui/QSelect'
|
||||||
|
|
||||||
import styles from './playground.module.css'
|
import styles from './playground.module.css'
|
||||||
|
import { useRecoilState } from 'recoil'
|
||||||
|
import { cadFileNameState, useCadFileState } from '@/store/canvasAtom'
|
||||||
|
|
||||||
export default function Playground() {
|
export default function Playground() {
|
||||||
|
const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState)
|
||||||
|
const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState)
|
||||||
const fileRef = useRef(null)
|
const fileRef = useRef(null)
|
||||||
const { get, post } = useAxios()
|
const { get, promisePost } = useAxios()
|
||||||
const testVar = process.env.NEXT_PUBLIC_TEST
|
const testVar = process.env.NEXT_PUBLIC_TEST
|
||||||
|
const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
const [color, setColor] = useState('#ff0000')
|
const [color, setColor] = useState('#ff0000')
|
||||||
@ -36,8 +41,16 @@ export default function Playground() {
|
|||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('file', fileRef.current.files[0])
|
formData.append('file', fileRef.current.files[0])
|
||||||
|
|
||||||
const result = await post({ url: process.env.CONVERTER_API_URL, data: formData })
|
await promisePost({ url: converterUrl, data: formData })
|
||||||
await convertDwgToPng(result.Files[0].FileName, result.Files[0].FileData)
|
.then((res) => {
|
||||||
|
console.log('response: ', res)
|
||||||
|
convertDwgToPng(res.data.Files[0].FileName, res.data.Files[0].FileData)
|
||||||
|
setUseCadFile(true)
|
||||||
|
setCadFileName(res.data.Files[0].FileName)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = [
|
const data = [
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useCanvas } from '@/hooks/useCanvas'
|
import { useCanvas } from '@/hooks/useCanvas'
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { useMode } from '@/hooks/useMode'
|
import { useMode } from '@/hooks/useMode'
|
||||||
import { Mode } from '@/common/common'
|
import { Mode } from '@/common/common'
|
||||||
@ -9,6 +9,8 @@ import { Button } from '@nextui-org/react'
|
|||||||
import RangeSlider from './ui/RangeSlider'
|
import RangeSlider from './ui/RangeSlider'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import {
|
import {
|
||||||
|
cadFileCompleteState,
|
||||||
|
cadFileNameState,
|
||||||
canvasSizeState,
|
canvasSizeState,
|
||||||
compassState,
|
compassState,
|
||||||
currentObjectState,
|
currentObjectState,
|
||||||
@ -17,6 +19,7 @@ import {
|
|||||||
roofState,
|
roofState,
|
||||||
sortedPolygonArray,
|
sortedPolygonArray,
|
||||||
templateTypeState,
|
templateTypeState,
|
||||||
|
useCadFileState,
|
||||||
wallState,
|
wallState,
|
||||||
} from '@/store/canvasAtom'
|
} from '@/store/canvasAtom'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
@ -38,7 +41,18 @@ import { SurfaceShapeModal } from '@/components/ui/SurfaceShape'
|
|||||||
|
|
||||||
export default function Roof2(props) {
|
export default function Roof2(props) {
|
||||||
const { name, userId, email, isLoggedIn } = props
|
const { name, userId, email, isLoggedIn } = props
|
||||||
const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage, addCanvas } = useCanvas('canvas')
|
const {
|
||||||
|
canvas,
|
||||||
|
handleRedo,
|
||||||
|
handleUndo,
|
||||||
|
setCanvasBackgroundWithDots,
|
||||||
|
saveImage,
|
||||||
|
addCanvas,
|
||||||
|
handleCadImageLoad,
|
||||||
|
handleCadImageInit,
|
||||||
|
backImg,
|
||||||
|
setBackImg,
|
||||||
|
} = useCanvas('canvas')
|
||||||
|
|
||||||
const { get } = useAxios()
|
const { get } = useAxios()
|
||||||
|
|
||||||
@ -84,6 +98,13 @@ export default function Roof2(props) {
|
|||||||
canvas,
|
canvas,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cad 파일 업로드
|
||||||
|
const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState)
|
||||||
|
const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState)
|
||||||
|
const [cadFileComplete, setCadFileComplete] = useRecoilState(cadFileCompleteState)
|
||||||
|
let imgPath
|
||||||
|
useCadFile && (imgPath = `/cadImages/${cadFileName}`)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
mode,
|
mode,
|
||||||
setMode,
|
setMode,
|
||||||
@ -130,6 +151,11 @@ export default function Roof2(props) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
changeMode(canvas, mode)
|
changeMode(canvas, mode)
|
||||||
|
|
||||||
|
if (!cadFileComplete && useCadFile) {
|
||||||
|
// cad 파일 로드
|
||||||
|
useCadFile && handleCadImageLoad(imgPath, canvas)
|
||||||
|
}
|
||||||
}, [canvas, mode])
|
}, [canvas, mode])
|
||||||
|
|
||||||
const makeLine = () => {
|
const makeLine = () => {
|
||||||
@ -757,6 +783,32 @@ export default function Roof2(props) {
|
|||||||
<Button className="m-1 p-2" onClick={drawCellInTrestle}>
|
<Button className="m-1 p-2" onClick={drawCellInTrestle}>
|
||||||
모듈 채우기
|
모듈 채우기
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
className="m-1 p-2"
|
||||||
|
onClick={() => {
|
||||||
|
setUseCadFile(false)
|
||||||
|
setCadFileName('')
|
||||||
|
handleCadImageInit()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
cad 파일 초기화
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
className="m-1 p-2"
|
||||||
|
onClick={() => {
|
||||||
|
backImg
|
||||||
|
.set({
|
||||||
|
selectable: false,
|
||||||
|
})
|
||||||
|
.sendToBack()
|
||||||
|
canvas.clear()
|
||||||
|
canvas.add(backImg)
|
||||||
|
canvas.renderAll()
|
||||||
|
setCadFileComplete(true)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
cad 파일 조정 완료
|
||||||
|
</Button>
|
||||||
<Button className="m-1 p-2" color={`${showControl ? 'primary' : 'default'}`} onClick={handleShowController}>
|
<Button className="m-1 p-2" color={`${showControl ? 'primary' : 'default'}`} onClick={handleShowController}>
|
||||||
canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`}
|
canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -45,6 +45,10 @@ export function useAxios() {
|
|||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const promisePost = async ({ url, data }) => {
|
||||||
|
return await getInstances(url).post(url, data)
|
||||||
|
}
|
||||||
|
|
||||||
const put = async ({ url, data }) => {
|
const put = async ({ url, data }) => {
|
||||||
return await getInstances(url)
|
return await getInstances(url)
|
||||||
.put(url, data)
|
.put(url, data)
|
||||||
@ -66,5 +70,5 @@ export function useAxios() {
|
|||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
return { get, post, put, patch, del }
|
return { get, post, promisePost, put, patch, del }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ export function useCanvas(id) {
|
|||||||
const [canvas, setCanvas] = useState()
|
const [canvas, setCanvas] = useState()
|
||||||
const [isLocked, setIsLocked] = useState(false)
|
const [isLocked, setIsLocked] = useState(false)
|
||||||
const [history, setHistory] = useState([])
|
const [history, setHistory] = useState([])
|
||||||
|
const [backImg, setBackImg] = useState()
|
||||||
const [canvasSize] = useRecoilState(canvasSizeState)
|
const [canvasSize] = useRecoilState(canvasSizeState)
|
||||||
const [fontSize] = useRecoilState(fontSizeState)
|
const [fontSize] = useRecoilState(fontSizeState)
|
||||||
const { setCanvasForEvent, attachDefaultEventOnCanvas } = useCanvasEvent()
|
const { setCanvasForEvent, attachDefaultEventOnCanvas } = useCanvasEvent()
|
||||||
@ -444,6 +445,30 @@ export function useCanvas(id) {
|
|||||||
// }, 1000)
|
// }, 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cad 파일 사용시 이미지 로딩 함수
|
||||||
|
*/
|
||||||
|
const handleCadImageLoad = (url) => {
|
||||||
|
console.log('image load url: ', url)
|
||||||
|
|
||||||
|
fabric.Image.fromURL(url, function (img) {
|
||||||
|
img.set({
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
width: 1500,
|
||||||
|
height: 1500,
|
||||||
|
selectable: true,
|
||||||
|
})
|
||||||
|
canvas.add(img)
|
||||||
|
canvas.renderAll()
|
||||||
|
setBackImg(img)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCadImageInit = () => {
|
||||||
|
canvas.clear()
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
canvas,
|
canvas,
|
||||||
addShape,
|
addShape,
|
||||||
@ -459,5 +484,9 @@ export function useCanvas(id) {
|
|||||||
setCanvasBackgroundWithDots,
|
setCanvasBackgroundWithDots,
|
||||||
addCanvas,
|
addCanvas,
|
||||||
removeMouseLines,
|
removeMouseLines,
|
||||||
|
handleCadImageLoad,
|
||||||
|
handleCadImageInit,
|
||||||
|
backImg,
|
||||||
|
setBackImg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,18 @@
|
|||||||
|
'use server'
|
||||||
|
|
||||||
|
import fs from 'fs/promises'
|
||||||
|
|
||||||
|
const imageSavePath = 'public/cadImages'
|
||||||
|
|
||||||
const convertDwgToPng = async (fileName, data) => {
|
const convertDwgToPng = async (fileName, data) => {
|
||||||
console.log('fileName', fileName)
|
console.log('fileName', fileName)
|
||||||
const imagePath = 'public/cad-images'
|
|
||||||
try {
|
try {
|
||||||
await fs.readdir(imagePath)
|
await fs.readdir(imageSavePath)
|
||||||
} catch {
|
} catch {
|
||||||
await fs.mkdir(imagePath)
|
await fs.mkdir(imageSavePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fs.writeFile(`${imagePath}/${fileName}`, data, 'base64')
|
return await fs.writeFile(`${imageSavePath}/${fileName}`, data, 'base64')
|
||||||
}
|
}
|
||||||
|
|
||||||
export { convertDwgToPng }
|
export { convertDwgToPng }
|
||||||
|
|||||||
@ -126,3 +126,21 @@ export const customSettingsState = atom({
|
|||||||
default: {},
|
default: {},
|
||||||
dangerouslyAllowMutability: true,
|
dangerouslyAllowMutability: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// cad 도면 파일 사용 여부
|
||||||
|
export const useCadFileState = atom({
|
||||||
|
key: 'useCadFile',
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
// cad 도면 파일 이름
|
||||||
|
export const cadFileNameState = atom({
|
||||||
|
key: 'cadFileName',
|
||||||
|
default: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
// cad 도면 파일 조정 완료
|
||||||
|
export const cadFileCompleteState = atom({
|
||||||
|
key: 'cadFileComplete',
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user