Merge branch 'dev' into dev-yj

This commit is contained in:
yjnoh 2025-02-20 17:45:28 +09:00
commit 1679351fc1
9 changed files with 173 additions and 38 deletions

View File

@ -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",

BIN
qcast3.database.sqlite Normal file

Binary file not shown.

View File

@ -384,7 +384,12 @@ export default function CircuitTrestleSetting({ id }) {
obj.pcsItemId = null
obj.circuitNumber = null
})
setSelectedModels(JSON.parse(JSON.stringify(selectedModels)).map((model) => (model.isUsed = false)))
setSelectedModels(
JSON.parse(JSON.stringify(selectedModels)).map((model) => {
model.isUsed = false
return model
}),
)
if (allocationType === ALLOCATION_TYPE.PASSIVITY) {
setAllocationType(ALLOCATION_TYPE.AUTO)

View File

@ -364,7 +364,7 @@ export default function StepUp(props) {
// console.log('🚀 ~ handleRowClick ~ selectedData:', selectedData)
// PCS 2 PCS
if (stepUpListData[0].pcsItemList.length > 1 && mainIdx === 0) {
if (tempStepUpListData[0].pcsItemList.length > 1 && mainIdx === 0) {
//
const params = {
...props.getOptYn(), // Y/N
@ -442,29 +442,30 @@ export default function StepUp(props) {
roofSurface.moduleList.forEach((module) => {
const targetModule = canvas.getObjects().filter((obj) => obj.id === module.uniqueId)[0]
if (module.circuit === '') return
const moduleCircuitText = new fabric.Text(module.circuit, {
left: targetModule.left + targetModule.width / 2,
top: targetModule.top + targetModule.height / 2,
fontFamily: circuitNumberText.fontFamily.value,
fontWeight: circuitNumberText.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal',
fontStyle: circuitNumberText.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
fontSize: circuitNumberText.fontSize.value,
fill: circuitNumberText.fontColor.value,
width: targetModule.width,
height: targetModule.height,
textAlign: 'center',
originX: 'center',
originY: 'center',
name: 'circuitNumber',
parentId: targetModule.id,
circuitInfo: module.pcsItemId,
visible: isDisplayCircuitNumber,
})
targetModule.circuit = moduleCircuitText
targetModule.pcsItemId = module.pcsItemId
targetModule.circuitNumber = module.circuit
canvas.add(moduleCircuitText)
if (module.circuit !== '' && module.circuit) {
const moduleCircuitText = new fabric.Text(module.circuit, {
left: targetModule.left + targetModule.width / 2,
top: targetModule.top + targetModule.height / 2,
fontFamily: circuitNumberText.fontFamily.value,
fontWeight: circuitNumberText.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal',
fontStyle: circuitNumberText.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
fontSize: circuitNumberText.fontSize.value,
fill: circuitNumberText.fontColor.value,
width: targetModule.width,
height: targetModule.height,
textAlign: 'center',
originX: 'center',
originY: 'center',
name: 'circuitNumber',
parentId: targetModule.id,
circuitInfo: module.pcsItemId,
visible: isDisplayCircuitNumber,
})
targetModule.circuit = moduleCircuitText
targetModule.pcsItemId = module.pcsItemId
targetModule.circuitNumber = module.circuit
canvas.add(moduleCircuitText)
}
})
})

View File

@ -24,7 +24,6 @@ export const ROOF_MATERIAL_LAYOUT = {
export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, planNo, openPoint }) {
const [showSizeGuideModal, setShowSizeGuidModal] = useState(false)
const [showMaterialGuideModal, setShowMaterialGuidModal] = useState(false)
const { closePopup } = usePopup()
const { getMessage } = useMessage()
const roofMaterials = useRecoilValue(roofMaterialsAtom)
@ -221,9 +220,6 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
<div className={`modal-pop-wrap ll mount`}>
<div className="modal-head modal-handle">
<h1 className="title">{getMessage('plan.menu.placement.surface.initial.setting')}</h1>
<button className="modal-close" onClick={() => closePopup(id)}>
닫기
</button>
</div>
<div className="modal-body">
<div className="left-bar modal-handle"></div>

View File

@ -5,6 +5,8 @@ import { useSwal } from '@/hooks/useSwal'
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'
/**
* 배경 이미지 관리
@ -19,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()
@ -72,13 +75,17 @@ export function useRefFiles() {
/**
* 파일 삭제
*/
const handleFileDelete = () => {
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 +93,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,
})
},
})
}
@ -107,11 +118,27 @@ 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`,
})
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}`,
})
}
/**
@ -135,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)
@ -145,6 +182,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)
}
/**

View File

@ -710,7 +710,7 @@ export const useTrestle = () => {
slope,
classType: currentAngleType === 'slope' ? '0' : '1',
angle: getDegreeByChon(slope),
azimuth: getAzimuth(surface),
azimuth: getAzimuth(parent),
moduleList,
}
})
@ -726,8 +726,8 @@ export const useTrestle = () => {
return { itemList, northArrangement, roofSurfaceList, circuitItemList }
}
const getAzimuth = (surface) => {
const { moduleCompass, surfaceCompass, direction } = surface
const getAzimuth = (parent) => {
const { moduleCompass, surfaceCompass, direction } = parent
if (surfaceCompass) {
if (surfaceCompass > 180) {

View File

@ -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'
import PlacementSurfaceLineProperty from '@/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty'
import { v4 as uuidv4 } from 'uuid'
@ -38,6 +39,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
// const { addCanvasMouseEventListener, initEvent } = useContext(EventContext)
const { addPopup, closePopup } = usePopup()
const { setSurfaceShapePattern } = useRoofFn()
const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
const applySurfaceShape = (surfaceRefs, selectedType, id) => {
let length1, length2, length3, length4, length5
@ -719,12 +721,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') })

54
src/lib/imageActions.js Normal file
View File

@ -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)
}