From c9234b264660f3be6a8e317f640f67af077c8baf Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Thu, 20 Feb 2025 16:48:21 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=93=8Cfix:=20sqlite3=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 + qcast3.database.sqlite | Bin 0 -> 16384 bytes src/hooks/common/useRefFiles.js | 31 +++++++++++-- src/hooks/surface/useSurfaceShapeBatch.js | 36 ++++++++++++++- src/lib/imageActions.js | 54 ++++++++++++++++++++++ 5 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 qcast3.database.sqlite create mode 100644 src/lib/imageActions.js diff --git a/package.json b/package.json index c2b9e6cf..a9b977ce 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,8 @@ "react-responsive-modal": "^6.4.2", "react-select": "^5.8.1", "recoil": "^0.7.7", + "sqlite": "^5.1.1", + "sqlite3": "^5.1.7", "sweetalert2": "^11.14.1", "sweetalert2-react-content": "^5.0.7", "swr": "^2.3.0", diff --git a/qcast3.database.sqlite b/qcast3.database.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..6e35d0d37fabdff88cd32274d68ffa283e682e54 GIT binary patch literal 16384 zcmeI(&u-H&7y$5O9WYJn#sO3bffRPy*xV+L9mm^+fhuv>0Y=B4Q)N4LSK6jsno8`* zcmiI58)qJg8&84Lb%=$-s02clKDSBZeD;?wzqE%)>B|>~-CTQSm<>ekh0blqb)Cna z=QvKyF3WaVvWq+0F8Y_P*mqs4IrZ#wb^V*ORLz|APt~m2zHSP{K>!3m00ck)1V8`; zKmY_lU?Bz08)^>@)7vZ$-(1~V^=#`V#ky$SG}j%SdFe3s(n-HR4Hp45Ovia9Y}_knX^(n8hZRFd znXM%|^LqNs6O(+{O;x4`I?Z>d!-n#mR(abVv(>@tui?p2%?f!Bxv$)7l zidmkQ>-Tx_c{zV|`}xw%+Rl#qwxH7E)4shsZIAWoM5n6Utz4lgjonJcK=0a_+xG7D z!4$kR%~?M8a)0Sc)^hYea$C^9&%KbpDkvHRKmY_l00ck)1V8`;KmY_l00cl_E`h2Y z?QVQ`>>C;gfB*=900@8p2!H?xfB*=900@A<0t?)8EBh<*j$1))`EiD|;{M-0^zUqZ zsXqJlwZNwfrGo$nfB*=900@8p2!H?xfWSW$I9|Ew+;u-Z3?stVPx5@U*JuQFOyWAm ztRApvkNCddn2h>Ek&GKOiZJ6zgnXkyLz7t@r@b6pH&-S$~lfH!d%9P*y0iAJU}GWTp49dM5k#tj-1!?R2wRybu3U4gfUeFgFPOy)Ly=HK { + const handleFileDelete = async () => { swalFire({ text: '삭제하시겠습니까?', type: 'confirm', - confirmFn: () => { + confirmFn: async () => { setRefImage(null) setCurrentCanvasPlan((prev) => ({ ...prev, bgImageName: null })) + await deleteBackGroundImage({ + objectId: currentCanvasPlan.id, + planNo: currentCanvasPlan.planNo, + }) }, }) } @@ -86,14 +91,18 @@ export function useRefFiles() { /** * 주소 삭제 */ - const handleAddressDelete = () => { + const handleAddressDelete = async () => { swalFire({ text: '삭제하시겠습니까?', type: 'confirm', - confirmFn: () => { + confirmFn: async () => { setMapPositionAddress('') setCurrentBgImage(null) setCurrentCanvasPlan((prev) => ({ ...prev, mapPositionAddress: null })) + await deleteBackGroundImage({ + objectId: currentCanvasPlan.id, + planNo: currentCanvasPlan.planNo, + }) }, }) } @@ -112,6 +121,12 @@ export function useRefFiles() { }) console.log('🚀 ~ handleMapImageDown ~ res:', res) setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`) + + await setBackGroundImage({ + objectId: currentCanvasPlan.id, + planNo: currentCanvasPlan.planNo, + imagePath: `${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`, + }) } /** @@ -145,6 +160,14 @@ export function useRefFiles() { console.log('🚀 ~ handleUploadImageRefFile ~ res:', res) setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`) setRefImage(file) + + const params = { + objectId: currentCanvasPlan.id, + planNo: currentCanvasPlan.planNo, + imagePath: `${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`, + } + console.log('🚀 ~ handleUploadImageRefFile ~ params:', params) + await setBackGroundImage(params) } /** diff --git a/src/hooks/surface/useSurfaceShapeBatch.js b/src/hooks/surface/useSurfaceShapeBatch.js index 5dea9058..a2625749 100644 --- a/src/hooks/surface/useSurfaceShapeBatch.js +++ b/src/hooks/surface/useSurfaceShapeBatch.js @@ -2,7 +2,7 @@ import { useEffect } from 'react' import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil' -import { canvasState, globalPitchState } from '@/store/canvasAtom' +import { canvasState, currentCanvasPlanState, globalPitchState } from '@/store/canvasAtom' import { MENU, POLYGON_TYPE } from '@/common/common' import { getIntersectionPoint } from '@/util/canvas-util' import { degreesToRadians } from '@turf/turf' @@ -19,6 +19,7 @@ import { QLine } from '@/components/fabric/QLine' import { useRoofFn } from '@/hooks/common/useRoofFn' import { outerLinePointsState } from '@/store/outerLineAtom' import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom' +import { getBackGroundImage } from '@/lib/imageActions' export function useSurfaceShapeBatch({ isHidden, setIsHidden }) { const { getMessage } = useMessage() @@ -36,6 +37,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) { // const { addCanvasMouseEventListener, initEvent } = useContext(EventContext) const { closePopup } = usePopup() const { setSurfaceShapePattern } = useRoofFn() + const currentCanvasPlan = useRecoilValue(currentCanvasPlanState) const applySurfaceShape = (surfaceRefs, selectedType, id) => { let length1, length2, length3, length4, length5 @@ -711,12 +713,42 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) { return points } - const deleteAllSurfacesAndObjects = () => { + const deleteAllSurfacesAndObjects = async () => { + const backgroundImage = await getBackGroundImage({ + objectId: currentCanvasPlan.id, + planNo: currentCanvasPlan.planNo, + }) + console.log('🚀 ~ deleteAllSurfacesAndObjects ~ backgroundImage:', backgroundImage) + swalFire({ text: getMessage('batch.canvas.delete.all'), type: 'confirm', confirmFn: () => { canvas.clear() + + fabric.Image.fromURL(`${backgroundImage.path}`, function (img) { + console.log('🚀 ~ img:', img) + img.set({ + left: 0, + top: 0, + width: img.width, + height: img.height, + name: 'backGroundImage', + selectable: false, + hasRotatingPoint: false, // 회전 핸들 활성화 + lockMovementX: false, + lockMovementY: false, + lockRotation: false, + lockScalingX: false, + lockScalingY: false, + }) + // image = img + canvas?.add(img) + canvas?.sendToBack(img) + canvas?.renderAll() + // setBackImg(img) + }) + resetOuterLinePoints() resetPlacementShapeDrawingPoints() swalFire({ text: getMessage('plan.message.delete') }) diff --git a/src/lib/imageActions.js b/src/lib/imageActions.js new file mode 100644 index 00000000..f3276d64 --- /dev/null +++ b/src/lib/imageActions.js @@ -0,0 +1,54 @@ +'use server' + +import sqlite3 from 'sqlite3' +import { open } from 'sqlite' + +export const setBackGroundImage = async ({ objectId, planNo, imagePath }) => { + let db = null + + if (!db) { + db = await open({ + filename: 'qcast3.database.sqlite', + driver: sqlite3.Database, + }) + } + + const fetchSql = `SELECT * FROM background_image WHERE object_id = '${objectId}' AND plan_no = '${planNo}'` + const result = await db.get(fetchSql) + if (result) { + const updateSql = `UPDATE background_image SET path = '${imagePath}' WHERE object_id = '${objectId}' AND plan_no = '${planNo}'` + await db.run(updateSql) + } else { + const insertSql = `INSERT INTO background_image (object_id, plan_no, path) VALUES ('${objectId}', '${planNo}', '${imagePath}')` + await db.run(insertSql) + } +} + +export const getBackGroundImage = async ({ objectId, planNo }) => { + let db = null + + if (!db) { + db = await open({ + filename: 'qcast3.database.sqlite', + driver: sqlite3.Database, + }) + } + + const sql = `SELECT * FROM background_image WHERE object_id = '${objectId}' AND plan_no = '${planNo}'` + const result = await db.get(sql) + return result +} + +export const deleteBackGroundImage = async ({ objectId, planNo }) => { + let db = null + + if (!db) { + db = await open({ + filename: 'qcast3.database.sqlite', + driver: sqlite3.Database, + }) + } + + const sql = `DELETE FROM background_image WHERE object_id = '${objectId}' AND plan_no = '${planNo}'` + await db.run(sql) +} From aead423eda30c7f2e9ecaee5aaa9ad6aaf1731f0 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Thu, 20 Feb 2025 17:36:29 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=EC=97=85=EB=A1=9C=EB=93=9C=20?= =?UTF-8?q?=EC=A7=84=ED=96=89=ED=95=98=EB=A9=B4=20=EA=B0=95=EC=A0=9C?= =?UTF-8?q?=EB=A1=9C=20=EC=84=A4=EC=A0=95=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- qcast3.database.sqlite | Bin 16384 -> 16384 bytes src/hooks/common/useRefFiles.js | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/qcast3.database.sqlite b/qcast3.database.sqlite index 6e35d0d37fabdff88cd32274d68ffa283e682e54..c0c43e6faa95884fffddcdf0dcf1413c2e23f368 100644 GIT binary patch delta 72 zcmZo@U~Fh$oFL68HBrWyQEFqte0@gVO$Mv@8F?rB+v#dprlgn~Tc(=orkST1>zY`k c8tEn(r6lSm8k(D$n6#>3 cn(A5_rW)xcTbNrWnVOiSCMOx|738G@0LqXPkN^Mx diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index 69d38954..52f8ef47 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -6,6 +6,7 @@ import { useAxios } from '../useAxios' import { currentCanvasPlanState } from '@/store/canvasAtom' import { useCanvas } from '@/hooks/useCanvas' import { deleteBackGroundImage, setBackGroundImage } from '@/lib/imageActions' +import { settingModalFirstOptionsState } from '@/store/settingAtom' /** * 배경 이미지 관리 @@ -20,6 +21,7 @@ export function useRefFiles() { const [currentBgImage, setCurrentBgImage] = useState(null) const queryRef = useRef(null) const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) + const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState) const { handleBackImageLoadToCanvas } = useCanvas() const { swalFire } = useSwal() const { get, post } = useAxios() @@ -116,6 +118,16 @@ export function useRefFiles() { return } + const newOption1 = settingModalFirstOptions.option1.map((option) => ({ + ...option, + selected: option.column === 'imageDisplay' ? true : option.selected, + })) + + setSettingModalFirstOptions((prev) => ({ + ...prev, + option1: newOption1, + })) + const res = await get({ url: `${process.env.NEXT_PUBLIC_HOST_URL}/map/convert?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20`, }) @@ -150,6 +162,16 @@ export function useRefFiles() { * @param {*} file */ const handleUploadImageRefFile = async (file) => { + const newOption1 = settingModalFirstOptions.option1.map((option) => ({ + ...option, + selected: option.column === 'imageDisplay' ? true : option.selected, + })) + + setSettingModalFirstOptions((prev) => ({ + ...prev, + option1: newOption1, + })) + const formData = new FormData() formData.append('file', file)