feat: Add CAD file conversion functionality to Playground component

This commit is contained in:
yoosangwook 2024-09-04 13:00:00 +09:00
parent b2b528fc07
commit 7a150be069
8 changed files with 136 additions and 15 deletions

View File

@ -1,10 +1,10 @@
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"
DATABASE_URL="sqlserver://mssql.devgrr.kr:1433;database=qcast;user=qcast;password=Qwertqaz12345;trustServerCertificate=true"
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"

View File

@ -6,4 +6,4 @@ DATABASE_URL=""
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"

View File

@ -1,7 +1,7 @@
'use client'
import { useState } from 'react'
import { Button, Table, TableBody, TableCell, TableColumn, TableHeader, TableRow } from '@nextui-org/react'
import { useRef, useState } from 'react'
import { Button } from '@nextui-org/react'
import ColorPicker from './common/color-picker/ColorPicker'
import { useAxios } from '@/hooks/useAxios'
@ -12,11 +12,16 @@ import { convertDwgToPng } from '@/lib/cadAction'
import QSelect from '@/components/ui/QSelect'
import styles from './playground.module.css'
import { useRecoilState } from 'recoil'
import { cadFileNameState, useCadFileState } from '@/store/canvasAtom'
export default function Playground() {
const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState)
const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState)
const fileRef = useRef(null)
const { get, post } = useAxios()
const { get, promisePost } = useAxios()
const testVar = process.env.NEXT_PUBLIC_TEST
const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL
const { getMessage } = useMessage()
const [color, setColor] = useState('#ff0000')
@ -36,8 +41,16 @@ export default function Playground() {
const formData = new FormData()
formData.append('file', fileRef.current.files[0])
const result = await post({ url: process.env.CONVERTER_API_URL, data: formData })
await convertDwgToPng(result.Files[0].FileName, result.Files[0].FileData)
await promisePost({ url: converterUrl, data: formData })
.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 = [

View File

@ -1,7 +1,7 @@
'use client'
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 { useMode } from '@/hooks/useMode'
import { Mode } from '@/common/common'
@ -9,6 +9,8 @@ import { Button } from '@nextui-org/react'
import RangeSlider from './ui/RangeSlider'
import { useRecoilState, useRecoilValue } from 'recoil'
import {
cadFileCompleteState,
cadFileNameState,
canvasSizeState,
compassState,
currentObjectState,
@ -17,6 +19,7 @@ import {
roofState,
sortedPolygonArray,
templateTypeState,
useCadFileState,
wallState,
} from '@/store/canvasAtom'
import { QLine } from '@/components/fabric/QLine'
@ -38,7 +41,18 @@ import { SurfaceShapeModal } from '@/components/ui/SurfaceShape'
export default function Roof2(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()
@ -84,6 +98,13 @@ export default function Roof2(props) {
canvas,
}
// cad
const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState)
const [cadFileName, setCadFileName] = useRecoilState(cadFileNameState)
const [cadFileComplete, setCadFileComplete] = useRecoilState(cadFileCompleteState)
let imgPath
useCadFile && (imgPath = `/cadImages/${cadFileName}`)
const {
mode,
setMode,
@ -130,6 +151,11 @@ export default function Roof2(props) {
return
}
changeMode(canvas, mode)
if (!cadFileComplete && useCadFile) {
// cad
useCadFile && handleCadImageLoad(imgPath, canvas)
}
}, [canvas, mode])
const makeLine = () => {
@ -757,6 +783,32 @@ export default function Roof2(props) {
<Button className="m-1 p-2" onClick={drawCellInTrestle}>
모듈 채우기
</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}>
canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`}
</Button>

View File

@ -45,6 +45,10 @@ export function useAxios() {
.catch(console.error)
}
const promisePost = async ({ url, data }) => {
return await getInstances(url).post(url, data)
}
const put = async ({ url, data }) => {
return await getInstances(url)
.put(url, data)
@ -66,5 +70,5 @@ export function useAxios() {
.catch(console.error)
}
return { get, post, put, patch, del }
return { get, post, promisePost, put, patch, del }
}

View File

@ -17,6 +17,7 @@ export function useCanvas(id) {
const [canvas, setCanvas] = useState()
const [isLocked, setIsLocked] = useState(false)
const [history, setHistory] = useState([])
const [backImg, setBackImg] = useState()
const [canvasSize] = useRecoilState(canvasSizeState)
const [fontSize] = useRecoilState(fontSizeState)
const { setCanvasForEvent, attachDefaultEventOnCanvas } = useCanvasEvent()
@ -444,6 +445,30 @@ export function useCanvas(id) {
// }, 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 {
canvas,
addShape,
@ -459,5 +484,9 @@ export function useCanvas(id) {
setCanvasBackgroundWithDots,
addCanvas,
removeMouseLines,
handleCadImageLoad,
handleCadImageInit,
backImg,
setBackImg,
}
}

View File

@ -1,13 +1,18 @@
'use server'
import fs from 'fs/promises'
const imageSavePath = 'public/cadImages'
const convertDwgToPng = async (fileName, data) => {
console.log('fileName', fileName)
const imagePath = 'public/cad-images'
try {
await fs.readdir(imagePath)
await fs.readdir(imageSavePath)
} 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 }

View File

@ -126,3 +126,21 @@ export const customSettingsState = atom({
default: {},
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,
})