diff --git a/public/static/images/canvas/ico-flx05.svg b/public/static/images/canvas/ico-flx05.svg new file mode 100644 index 00000000..350aee07 --- /dev/null +++ b/public/static/images/canvas/ico-flx05.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/static/images/canvas/return-btn.svg b/public/static/images/canvas/return-btn.svg new file mode 100644 index 00000000..f33f417b --- /dev/null +++ b/public/static/images/canvas/return-btn.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/app/api/html2canvas/route.js b/src/app/api/html2canvas/route.js index ada6c54a..21f93c82 100644 --- a/src/app/api/html2canvas/route.js +++ b/src/app/api/html2canvas/route.js @@ -3,6 +3,7 @@ import fs from 'fs/promises' import { NextResponse } from 'next/server' +import { writeImage, writeImageBuffer } from '@/lib/fileAction' export async function GET(req) { const path = 'public/plan-map-images' @@ -15,14 +16,7 @@ export async function GET(req) { const response = await fetch(decodeUrl) const data = await response.arrayBuffer() const buffer = Buffer.from(data) - - try { - await fs.readdir(path) - } catch { - await fs.mkdir(path) - } finally { - await fs.writeFile(`${path}/${fileNm}.png`, buffer) - } + await writeImage(fileNm, buffer) return NextResponse.json({ fileNm: `${fileNm}.png` }) } diff --git a/src/app/api/image-upload/route.js b/src/app/api/image-upload/route.js index e817bd3b..92cf7da4 100644 --- a/src/app/api/image-upload/route.js +++ b/src/app/api/image-upload/route.js @@ -3,23 +3,25 @@ import fs from 'fs/promises' import { NextResponse } from 'next/server' +import { writeImage } from '@/lib/fileAction' export async function POST(req) { const path = 'public/plan-bg-images' const formData = await req.formData() const file = formData.get('file') + const fileName = formData.get('fileName') const arrayBuffer = await file.arrayBuffer() const buffer = Buffer.from(arrayBuffer) // const buffer = new Uint8Array(arrayBuffer) + await writeImage(fileName, buffer) + // try { + // await fs.readdir(path) + // } catch { + // await fs.mkdir(path) + // } finally { + // await fs.writeFile(`${path}/${fileName}`, buffer) + // } - try { - await fs.readdir(path) - } catch { - await fs.mkdir(path) - } finally { - await fs.writeFile(`${path}/${file.name}`, buffer) - } - - return NextResponse.json({ fileNm: `${file.name}` }) + return NextResponse.json({ fileNm: `${fileName}` }) } diff --git a/src/components/floor-plan/modal/ImgLoad.jsx b/src/components/floor-plan/modal/ImgLoad.jsx index c95d62a9..d5724972 100644 --- a/src/components/floor-plan/modal/ImgLoad.jsx +++ b/src/components/floor-plan/modal/ImgLoad.jsx @@ -22,18 +22,20 @@ export default function ImgLoad() { setMapPositionAddress, handleFileDelete, handleMapImageDown, + handleAddressDelete, } = useRefFiles() const { currentCanvasPlan } = usePlan() const { getMessage } = useMessage() const { floorPlanState, setFloorPlanState } = useContext(FloorPlanContext) const handleModal = () => { + console.log(floorPlanState) setFloorPlanState({ ...floorPlanState, refFileModalOpen: false }) } useEffect(() => { - console.log('๐Ÿš€ ~ ImgLoad ~ floorPlanState.refFileModalOpen:', floorPlanState.refFileModalOpen) - console.log('๐Ÿš€ ~ ImgLoad ~ currentCanvasPlan:', currentCanvasPlan) + // console.log('๐Ÿš€ ~ ImgLoad ~ floorPlanState.refFileModalOpen:', floorPlanState.refFileModalOpen) + // console.log('๐Ÿš€ ~ ImgLoad ~ currentCanvasPlan:', currentCanvasPlan) }, [floorPlanState.refFileModalOpen]) useEffect(() => { @@ -50,7 +52,7 @@ export default function ImgLoad() {
- ใ‚ตใ‚คใ‚บ่ชฟๆ•ดใจๅ›ž่ปข + {getMessage('modal.image.load.size.rotate')}
diff --git a/src/components/floor-plan/modal/grid/GridCopy.jsx b/src/components/floor-plan/modal/grid/GridCopy.jsx index 86f79df7..2f768406 100644 --- a/src/components/floor-plan/modal/grid/GridCopy.jsx +++ b/src/components/floor-plan/modal/grid/GridCopy.jsx @@ -17,8 +17,7 @@ export default function GridCopy(props) { const currentObject = useRecoilValue(currentObjectState) const { copy } = useGrid() const handleApply = () => { - // copy(currentObject, ) - copy(currentObject, ['โ†‘', 'โ†'].includes(arrow) ? Number(length) * -1 : Number(length)) + copy(currentObject, ['โ†‘', 'โ†'].includes(arrow) ? +length * -1 : +length) } return ( diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index 05f60afe..5997b399 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -5,7 +5,7 @@ import { v4 as uuidv4 } from 'uuid' import { useSwal } from '@/hooks/useSwal' import { useAxios } from '../useAxios' import { currentCanvasPlanState } from '@/store/canvasAtom' -import { convertDwgToPng, writeImageBuffer } from '@/lib/fileAction' +import { convertDwgToPng, removeImage, writeImageBuffer } from '@/lib/fileAction' export function useRefFiles() { const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL @@ -19,17 +19,51 @@ export function useRefFiles() { const { get, promisePut, promisePost } = useAxios() // const { currentCanvasPlan, setCurrentCanvasPlan } = usePlan() + useEffect(() => { + console.log('refImage', refImage) + }, [refImage]) + + useEffect(() => { + if (refFileMethod === '1') { + // ํŒŒ์ผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ + setMapPositionAddress('') + } else { + setRefImage(null) + } + }, [refFileMethod]) /** * ํŒŒ์ผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋ฒ„ํŠผ ์ปจํŠธ๋กค * @param {*} file */ const handleRefFile = (file) => { - setRefImage(file) + console.log('handleRefFile', file) + console.log('refImage', refImage) + if (file && ['image/png', 'image/jpg', 'image/jpeg', 'image/bmp', 'image/gif'].includes(file.type)) { + // setRefImage(file) + file.name.split('.').pop() === 'dwg' ? handleUploadConvertRefFile(file) : handleUploadImageRefFile(file) + } else { + swalFire({ + text: '์ด๋ฏธ์ง€๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.', + type: 'alert', + icon: 'error', + }) + } + if (refImage) { + swalFire({ + text: 'ํŒŒ์ผ์„ ๋ณ€๊ฒฝํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?', + type: 'confirm', + confirmFn: () => { + setRefImage(file) + file.name.split('.').pop() === 'dwg' ? handleUploadConvertRefFile(file) : handleUploadImageRefFile(file) + }, + }) + } + /** * ํŒŒ์ผ ํ™•์žฅ์ž๊ฐ€ dwg์ผ ๊ฒฝ์šฐ ๋ณ€ํ™˜ํ•˜์—ฌ ์ด๋ฏธ์ง€๋กœ ์ €์žฅ * ํŒŒ์ผ ํ™•์žฅ์ž๊ฐ€ ์ด๋ฏธ์ง€์ผ ๊ฒฝ์šฐ ์ด๋ฏธ์ง€ ์ €์žฅ */ - file.name.split('.').pop() === 'dwg' ? handleUploadConvertRefFile(file) : handleUploadImageRefFile(file) + // handleUploadRefFile(file) } @@ -37,15 +71,34 @@ export function useRefFiles() { * ํŒŒ์ผ ์‚ญ์ œ */ const handleFileDelete = () => { - setRefImage(null) - setCurrentCanvasPlan((prev) => ({ ...prev, bgFileName: null })) + swalFire({ + text: '์‚ญ์ œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?', + type: 'confirm', + confirmFn: () => { + setRefImage(null) + setCurrentCanvasPlan((prev) => ({ ...prev, bgFileName: null })) + removeImage(currentCanvasPlan.id).then((res) => { + console.log(res) + }) + }, + }) } /** * ์ฃผ์†Œ ์‚ญ์ œ */ const handleAddressDelete = () => { - setCurrentCanvasPlan((prev) => ({ ...prev, mapPositionAddress: null })) + swalFire({ + text: '์‚ญ์ œํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?', + type: 'confirm', + confirmFn: () => { + setMapPositionAddress('') + setCurrentCanvasPlan((prev) => ({ ...prev, mapPositionAddress: null })) + removeImage(currentCanvasPlan.id).then((res) => { + console.log(res) + }) + }, + }) } /** @@ -56,9 +109,10 @@ export function useRefFiles() { return } - const res = await get({ url: `http://localhost:3000/api/html2canvas?q=${queryRef.current.value}&fileNm=${uuidv4()}&zoom=20` }) - console.log('๐Ÿš€ ~ handleMapImageDown ~ res:', res) - setCurrentCanvasPlan((prev) => ({ ...prev, bgImageName: res.fileNm, mapPositionAddress: queryRef.current.value })) + const res = await get({ url: `http://localhost:3000/api/html2canvas?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20` }) + // console.log('๐Ÿš€ ~ handleMapImageDown ~ res:', res) + console.log('currentCanvasPlan', currentCanvasPlan) + setCurrentCanvasPlan((prev) => ({ ...prev, bgImageName: currentCanvasPlan.id, mapPositionAddress: queryRef.current.value })) } /** @@ -66,9 +120,10 @@ export function useRefFiles() { * @param {*} file */ const handleUploadImageRefFile = async (file) => { - console.log('๐Ÿš€ ~ handleUploadImageRefFile ~ file:', file) + // console.log('๐Ÿš€ ~ handleUploadImageRefFile ~ file:', file) const formData = new FormData() formData.append('file', file) + formData.append('fileName', currentCanvasPlan.id) const response = await fetch('http://localhost:3000/api/image-upload', { method: 'POST', @@ -76,7 +131,8 @@ export function useRefFiles() { }) const result = await response.json() - console.log('๐Ÿš€ ~ handleUploadImageRefFile ~ res:', result) + setRefImage(file) + // console.log('๐Ÿš€ ~ handleUploadImageRefFile ~ res:', result) // writeImageBuffer(file) } @@ -92,6 +148,7 @@ export function useRefFiles() { .then((res) => { convertDwgToPng(res.data.Files[0].FileName, res.data.Files[0].FileData) swalFire({ text: 'ํŒŒ์ผ ๋ณ€ํ™˜ ์„ฑ๊ณต' }) + setRefImage(res.data.Files[0].FileData) }) .catch((err) => { swalFire({ text: 'ํŒŒ์ผ ๋ณ€ํ™˜ ์‹คํŒจ', icon: 'error' }) @@ -110,7 +167,7 @@ export function useRefFiles() { * ํ˜„์žฌ ํ”Œ๋žœ์ด ๋ณ€๊ฒฝ๋˜๋ฉด ํ”Œ๋žœ ์ƒํƒœ ์ €์žฅ */ useEffect(() => { - console.log('๐Ÿš€ ~ useRefFiles ~ currentCanvasPlan:', currentCanvasPlan) + // console.log('๐Ÿš€ ~ useRefFiles ~ currentCanvasPlan:', currentCanvasPlan) // const handleCurrentPlan = async () => { // await promisePut({ url: '/api/canvas-management/canvas-statuses', data: currentCanvasPlan }).then((res) => { // console.log('๐Ÿš€ ~ awaitpromisePut ~ res:', res) diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index 6b1336a5..3f3ad1a0 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -6,6 +6,7 @@ import { useAxios } from '@/hooks/useAxios' import { useMessage } from '@/hooks/useMessage' import { useSwal } from '@/hooks/useSwal' import { SAVE_KEY } from '@/common/common' +import { readImage } from '@/lib/fileAction' export function usePlan() { const [planNum, setPlanNum] = useState(0) @@ -204,6 +205,7 @@ export function usePlan() { userId: userId, imageName: 'image_name', // api ํ•„์ˆ˜ํ•ญ๋ชฉ์ด์—ฌ์„œ ์ž„์‹œ๋กœ ๋„ฃ์Œ, ์ดํ›„ ์‚ญ์ œ ํ•„์š” objectNo: currentCanvasPlan.objectNo, + mapPositionAddress: currentCanvasPlan.mapPositionAddress, canvasStatus: canvasToDbFormat(canvasStatus), } await promisePost({ url: '/api/canvas-management/canvas-statuses', data: planData }) @@ -233,6 +235,7 @@ export function usePlan() { const putCanvasStatus = async (canvasStatus) => { const planData = { id: currentCanvasPlan.id, + mapPositionAddress: currentCanvasPlan.mapPositionAddress, canvasStatus: canvasToDbFormat(canvasStatus), } await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData }) @@ -285,6 +288,7 @@ export function usePlan() { updateCurrentPlan(newCurrentId) } } + const updateCurrentPlan = (newCurrentId) => { setPlans((plans) => plans.map((plan) => { @@ -295,8 +299,13 @@ export function usePlan() { useEffect(() => { setCurrentCanvasPlan(plans.find((plan) => plan.isCurrent) || null) setSelectedPlan(plans.find((plan) => plan.isCurrent)) + // setBgImage() }, [plans]) + const setBgImage = () => { + readImage(selectedPlan?.id) + } + /** * ์ƒˆ๋กœ์šด plan ์ƒ์„ฑ * ํ˜„์žฌ plan์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ๋ณต์ œ ์—ฌ๋ถ€๋ฅผ ํ™•์ธ diff --git a/src/lib/fileAction.js b/src/lib/fileAction.js index d09473a8..6f88758a 100644 --- a/src/lib/fileAction.js +++ b/src/lib/fileAction.js @@ -4,6 +4,7 @@ import fs from 'fs/promises' const CAD_FILE_PATH = 'public/cad-images' const IMAGE_FILE_PATH = 'public/plan-bg-images' +const FILE_PATH = 'public/plan-images' /** * ํŒŒ์ผ ๋ณ€ํ™˜ & ์ €์žฅ @@ -39,25 +40,54 @@ const writeImageBase64 = async (title, data) => { return fs.writeFile(`${IMAGE_FILE_PATH}/${title}.png`, data, 'base64') } -/** - * ์ด๋ฏธ์ง€ ์ €์žฅ - * Buffer ํ˜•์‹์œผ๋กœ ์ €์žฅ - * @param {*} title - * @param {*} data - * @returns - */ -const writeImageBuffer = async (file) => { - // ํ•ด๋‹น ๊ฒฝ๋กœ์— Directory ๊ฐ€ ์—†๋‹ค๋ฉด ์ƒ์„ฑ +// /** +// * ์ด๋ฏธ์ง€ ์ €์žฅ +// * Buffer ํ˜•์‹์œผ๋กœ ์ €์žฅ +// * @param {*} title +// * @param {*} data +// * @returns +// */ +// const writeImageBuffer = async (file) => { +// // ํ•ด๋‹น ๊ฒฝ๋กœ์— Directory ๊ฐ€ ์—†๋‹ค๋ฉด ์ƒ์„ฑ +// try { +// await fs.readdir(IMAGE_FILE_PATH) +// } catch { +// await fs.mkdir(IMAGE_FILE_PATH) +// } +// +// const arrayBuffer = await fileURLToPath.arrayBuffer() +// const buffer = new Uint8Array(arrayBuffer) +// +// return fs.writeFile(`${IMAGE_FILE_PATH}/${file.fileName}`, buffer) +// } + +const writeImage = async (fileName, file) => { try { - await fs.readdir(IMAGE_FILE_PATH) + await fs.readdir(FILE_PATH) } catch { - await fs.mkdir(IMAGE_FILE_PATH) + await fs.mkdir(FILE_PATH) } - const arrayBuffer = await fileURLToPath.arrayBuffer() - const buffer = new Uint8Array(arrayBuffer) - - return fs.writeFile(`${IMAGE_FILE_PATH}/${file.fileName}`, buffer) + return fs.writeFile(`${FILE_PATH}/${fileName}.png`, file) } -export { convertDwgToPng, writeImageBase64, writeImageBuffer } +const readImage = async (fileName) => { + await fs + .readFile(`${FILE_PATH}/${fileName}.png`) + .then((res) => { + console.log('readImage-then', res) + }) + .catch((e) => { + console.log('readImage-catch', e) + }) +} + +const removeImage = async (fileName) => { + try { + await fs.rm(`${FILE_PATH}/${fileName}.png`) + } catch (e) { + console.log(e) + } +} + +export { convertDwgToPng, writeImageBase64, writeImage, readImage, removeImage } diff --git a/src/locales/ja.json b/src/locales/ja.json index 7697cf69..d41ca44a 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -341,6 +341,7 @@ "modal.panel.column.insert.info": "ๆŒฟๅ…ฅใ™ใ‚‹ๆ–นๅ‘ใ‚’้ธๆŠžใ—ใฆใใ ใ•ใ„ใ€‚", "modal.panel.column.insert.type.left": "ๅทฆๆŒฟๅ…ฅ", "modal.panel.column.insert.type.right": "ๅณๆŒฟๅ…ฅ", + "modal.image.load.size.rotate": "ใ‚ตใ‚คใ‚บ่ชฟๆ•ดใจๅ›ž่ปข", "contextmenu.column.insert": "ๅˆ—ใฎๆŒฟๅ…ฅ", "contextmenu.row.move": "๋‹จ ์ด๋™(JA)", "contextmenu.row.copy": "๋‹จ ๋ณต์‚ฌ(JA)", @@ -483,9 +484,13 @@ "common.message.writeToConfirm": "ไฝœๆˆ่งฃ้™คใ‚’ๅฎŸ่กŒใ—ใพใ™ใ‹๏ผŸ", "common.message.password.init.success": "ใƒ‘ใ‚นใƒฏใƒผใƒ‰ [{0}] ใซๅˆๆœŸๅŒ–ใ•ใ‚Œใพใ—ใŸใ€‚", "common.message.no.edit.save": "ใ“ใฎๆ–‡ๆ›ธใฏๅค‰ๆ›ดใงใใพใ›ใ‚“ใ€‚", + "common.load": "ใƒ•ใ‚กใ‚คใƒซใฎ่ฟฝๅŠ ", "common.input.file": "ใƒ•ใ‚กใ‚คใƒซใ‚’่ชญใฟ่พผใ‚€", "common.input.file.load": "ใƒ•ใ‚กใ‚คใƒซใฎ่ฟฝๅŠ ", + "common.input.image.load": "์ด๋ฏธ์ง€ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ", + "common.input.address.load": "ใ‚ขใƒ‰ใƒฌใ‚นใ‚’่ชญใฟ่พผใ‚€", "common.require": "ๅฟ…้ ˆ", + "common.finish": "ๅฎŒไบ†", "common.ok": "็ขบ่ช", "commons.west": "็ซ‹ใค", "commons.east": "ใƒ‰ใƒณ", diff --git a/src/locales/ko.json b/src/locales/ko.json index 4b12d055..7287c914 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -348,6 +348,7 @@ "modal.panel.column.insert.info": "์‚ฝ์ž…ํ•  ๋ฐฉํ–ฅ์„ ์„ ํƒํ•ด์ฃผ์„ธ์š”.", "modal.panel.column.insert.type.left": "์™ผ์ชฝ ์‚ฝ์ž…", "modal.panel.column.insert.type.right": "์˜ค๋ฅธ์ชฝ ์‚ฝ์ž…", + "modal.image.load.size.rotate": "ํฌ๊ธฐ ์กฐ์ ˆ ๋ฐ ํšŒ์ „", "contextmenu.row.move": "๋‹จ ์ด๋™", "contextmenu.row.copy": "๋‹จ ๋ณต์‚ฌ", "contextmenu.row.remove": "๋‹จ ์‚ญ์ œ", @@ -492,9 +493,13 @@ "common.message.writeToConfirm": "์ž‘์„ฑ ํ•ด์ œ๋ฅผ ์‹คํ–‰ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?", "common.message.password.init.success": "๋น„๋ฐ€๋ฒˆํ˜ธ [{0}]๋กœ ์ดˆ๊ธฐํ™” ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.", "common.message.no.edit.save": "This document cannot be changed.", + "common.load": "๋ถˆ๋Ÿฌ์˜ค๊ธฐ", "common.input.file": "ํŒŒ์ผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ", "common.input.file.load": "๋ถˆ๋Ÿฌ์˜ค๊ธฐ", + "common.input.image.load": "์ด๋ฏธ์ง€ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ", + "common.input.address.load": "์ฃผ์†Œ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ", "common.require": "ํ•„์ˆ˜", + "common.finish": "์™„๋ฃŒ", "common.ok": "ํ™•์ธ", "commons.west": "์„œ", "commons.east": "๋™", diff --git a/src/styles/_contents.scss b/src/styles/_contents.scss index e72637e4..8d3b1408 100644 --- a/src/styles/_contents.scss +++ b/src/styles/_contents.scss @@ -139,6 +139,7 @@ &.ico02{background-image: url(../../public/static/images/canvas/ico-flx02.svg);} &.ico03{background-image: url(../../public/static/images/canvas/ico-flx03.svg);} &.ico04{background-image: url(../../public/static/images/canvas/ico-flx04.svg);} + &.ico05{background-image: url(../../public/static/images/canvas/ico-flx05.svg);} } .name{ font-size: 12px; @@ -827,6 +828,47 @@ &:last-child{ margin-bottom: 0; } + .file-item-wrap{ + display: flex; + align-items: center; + gap: 30px; + .return-wrap{ + display: flex; + align-items: center; + } + .return{ + padding: 0; + font-size: 13px; + color: #B0BCCD; + text-decoration: line-through; + } + .return-btn{ + flex: none; + position: relative; + top: 0; + left: 0; + transform: none; + display: flex; + align-items: center; + height: 24px; + padding: 0 9px; + margin-left: 10px; + background: none; + border: 1px solid #B0BCCD; + border-radius: 2px; + font-size: 12px; + color: #B0BCCD; + font-weight: 500; + .return-ico{ + display: block; + width: 14px; + height: 14px; + background: url(../../public/static/images/canvas/return-btn.svg)no-repeat center; + background-size: contain; + margin-right: 5px; + } + } + } } } } @@ -877,6 +919,16 @@ &.act{ background-color: #F7F9FA; } + .special-note-check-box{ + display: flex; + align-items: center; + .check-name{ + font-size: 13px; + color: #45576F; + cursor: pointer; + line-height: 1.3; + } + } } }