From d8341385a4828212ff212744950e96a4dea6ce5e Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Fri, 21 Mar 2025 16:44:01 +0900 Subject: [PATCH 01/33] =?UTF-8?q?chore:=20=ED=99=98=EA=B2=BD=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 8 +++++++- .env.production | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.env.development b/.env.development index cfc50e71..bd024a3b 100644 --- a/.env.development +++ b/.env.development @@ -8,4 +8,10 @@ SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y=" NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_yAS4QDalL9jgQ7vS" NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="http://q-order-stg.q-cells.jp:8120/eos/login/autoLogin" -NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-stg.q-cells.jp:8120/qm/login/autoLogin" \ No newline at end of file +NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-stg.q-cells.jp:8120/qm/login/autoLogin" + +AWS_REGION="ap-northeast-2" +AMPLIFY_BUCKET="interplug" +AWS_ACCESS_KEY_ID="AKIAVWMWJCUXFHEAZ4FR" +AWS_SECRET_ACCESS_KEY="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" +AWS_S3_BASE_URL="https://interplug.s3.ap-northeast-2.amazonaws.com" diff --git a/.env.production b/.env.production index 09bb27d3..28c4dd86 100644 --- a/.env.production +++ b/.env.production @@ -10,4 +10,10 @@ NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secr # NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="https://q-order.q-cells.jp/eos/login/autoLogin" # NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="https://q-musubi.q-cells.jp/qm/login/autoLogin" NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="http://q-order-stg.q-cells.jp:8120/eos/login/autoLogin" -NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-stg.q-cells.jp:8120/qm/login/autoLogin" \ No newline at end of file +NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-stg.q-cells.jp:8120/qm/login/autoLogin" + +AWS_REGION="ap-northeast-2" +AMPLIFY_BUCKET="interplug" +AWS_ACCESS_KEY_ID="AKIAVWMWJCUXFHEAZ4FR" +AWS_SECRET_ACCESS_KEY="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" +AWS_S3_BASE_URL="https://interplug.s3.ap-northeast-2.amazonaws.com" \ No newline at end of file From 20cef812ae305d12b88e0b42cec36be401e5ea4b Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Fri, 21 Mar 2025 16:47:14 +0900 Subject: [PATCH 02/33] =?UTF-8?q?chore:=20=EB=B8=8C=EB=9D=BC=EC=9A=B0?= =?UTF-8?q?=EC=A0=80=EC=9A=A9=20=ED=99=98=EA=B2=BD=EB=B3=80=EC=88=98=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 2 +- .env.production | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.development b/.env.development index bd024a3b..4f613c70 100644 --- a/.env.development +++ b/.env.development @@ -14,4 +14,4 @@ AWS_REGION="ap-northeast-2" AMPLIFY_BUCKET="interplug" AWS_ACCESS_KEY_ID="AKIAVWMWJCUXFHEAZ4FR" AWS_SECRET_ACCESS_KEY="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" -AWS_S3_BASE_URL="https://interplug.s3.ap-northeast-2.amazonaws.com" +NEXT_PUBLIC_AWS_S3_BASE_URL="https://interplug.s3.ap-northeast-2.amazonaws.com" diff --git a/.env.production b/.env.production index 28c4dd86..f0951f7a 100644 --- a/.env.production +++ b/.env.production @@ -16,4 +16,4 @@ AWS_REGION="ap-northeast-2" AMPLIFY_BUCKET="interplug" AWS_ACCESS_KEY_ID="AKIAVWMWJCUXFHEAZ4FR" AWS_SECRET_ACCESS_KEY="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" -AWS_S3_BASE_URL="https://interplug.s3.ap-northeast-2.amazonaws.com" \ No newline at end of file +NEXT_PUBLIC_AWS_S3_BASE_URL="https://interplug.s3.ap-northeast-2.amazonaws.com" \ No newline at end of file From a7b90621542218c6deb00210741e1ff56c45d880 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Mon, 24 Mar 2025 13:58:29 +0900 Subject: [PATCH 03/33] =?UTF-8?q?feat:=20s3=20=EC=97=85=EB=A1=9C=EB=93=9C?= =?UTF-8?q?=20=EA=B8=B0=EB=B3=B8=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + qcast3.database.sqlite | Bin 16384 -> 16384 bytes src/app/api/image/upload/route.js | 70 ++++++++++++++++++++ src/components/floor-plan/modal/ImgLoad.jsx | 2 +- src/hooks/common/useRefFiles.js | 17 +++-- 5 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 src/app/api/image/upload/route.js diff --git a/package.json b/package.json index 1f31b9d3..230e1b81 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "serve": "node server.js" }, "dependencies": { + "@aws-sdk/client-s3": "^3.772.0", "ag-grid-react": "^32.0.2", "axios": "^1.7.8", "big.js": "^6.2.2", diff --git a/qcast3.database.sqlite b/qcast3.database.sqlite index c0c43e6faa95884fffddcdf0dcf1413c2e23f368..66ac677f482169e439cd063c21efbc753f2a27c9 100644 GIT binary patch delta 122 zcmZo@U~Fh$oFL68J5k1&QFdd(e0^>{UIri#U|`^1y_w5kA%AEv9~*-xW23Bzp}7H9 zMoCFQv6a4lW?o5ZQ9({=x?ZudUSff6UVc$YMrvYliLQ}eVs2tpeqLgEv0ie1u6}7j YPJUvFer{!PVUBK2etN!MRzYey0Qtuyp8x;= delta 81 zcmZo@U~Fh$oFL68HBrWyQEFqte0^?SUIri#U|`^1xtYsgA^&85J6#RSloWGg%T!a{ jH1jlLT@#B`Bi$sUltkS`LvvGe( { + const Body = Buffer.from(await file.arrayBuffer()) + const Key = `upload/${file.name}` + const ContentType = file.ContentType + + await s3.send( + new PutObjectCommand({ + Bucket, + Key, + Body, + ContentType, + }), + ) + + return { + filePath: `https://${process.env.AMPLIFY_BUCKET}.s3.${process.env.AWS_REGION}.amazonaws.com/${Key}`, + fileName: Key, + } +} + +export async function POST(req) { + try { + const formData = await req.formData() + const file = formData.get('file') + + const result = await uploadImage(file) + result.message = '이미지 업로드 성공' + + return NextResponse.json(result) + } catch (error) { + console.error(error) + return NextResponse.json({ error: 'Failed to upload image' }, { status: 500 }) + } +} + +export async function DELETE(req) { + try { + const searchParams = req.nextUrl.searchParams + const Key = `upload/${searchParams.get('fileName')}` + console.log('🚀 ~ DELETE ~ Key:', Key) + + if (!Key) { + return NextResponse.json({ error: 'fileName parameter is required' }, { status: 400 }) + } + + await s3.send( + new DeleteObjectCommand({ + Bucket, + Key, + }), + ) + + return NextResponse.json({ message: '이미지 삭제 성공' }, { status: 200 }) + } catch (error) { + console.error('S3 Delete Error:', error) + return NextResponse.json({ error: 'Failed to delete image' }, { status: 500 }) + } +} diff --git a/src/components/floor-plan/modal/ImgLoad.jsx b/src/components/floor-plan/modal/ImgLoad.jsx index dda395a9..f0a86938 100644 --- a/src/components/floor-plan/modal/ImgLoad.jsx +++ b/src/components/floor-plan/modal/ImgLoad.jsx @@ -120,7 +120,7 @@ export default function ImgLoad() { value={refImage ? (refImage?.name ?? '') : (currentCanvasPlan?.bgImageName ?? '')} readOnly /> - {refImage && } + {currentCanvasPlan?.bgImageName && } diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index b21cc954..1642daa9 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -28,7 +28,7 @@ export function useRefFiles() { const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState) const { handleBackImageLoadToCanvas } = useCanvas() const { swalFire } = useSwal() - const { get, post } = useAxios() + const { get, post, del } = useAxios() useEffect(() => { if (refFileMethod === '1') { @@ -84,6 +84,9 @@ export function useRefFiles() { text: '삭제하시겠습니까?', type: 'confirm', confirmFn: async () => { + console.log('🚀 ~ handleFileDelete ~ handleFileDelete:', refImage) + console.log('🚀 ~ handleFileDelete ~ currentCanvasPlan.bgImageName:', currentCanvasPlan.bgImageName) + await del({ url: `http://localhost:3000/api/image/upload?fileName=${currentCanvasPlan.bgImageName}` }) setRefImage(null) setCurrentCanvasPlan((prev) => ({ ...prev, bgImageName: null })) await deleteBackGroundImage({ @@ -179,18 +182,24 @@ export function useRefFiles() { const formData = new FormData() formData.append('file', file) + // const res = await post({ + // url: `${process.env.NEXT_PUBLIC_HOST_URL}/image/upload`, + // data: formData, + // }) const res = await post({ - url: `${process.env.NEXT_PUBLIC_HOST_URL}/image/upload`, + url: `http://localhost:3000/api/image/upload`, data: formData, }) console.log('🚀 ~ handleUploadImageRefFile ~ res:', res) - setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`) + // setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`) + setCurrentBgImage(`${res.filePath}`) setRefImage(file) const params = { objectId: currentCanvasPlan.id, planNo: currentCanvasPlan.planNo, - imagePath: `${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`, + // imagePath: `${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`, + imagePath: `${res.filePath}`, } console.log('🚀 ~ handleUploadImageRefFile ~ params:', params) await setBackGroundImage(params) From 2492b45a66159ad7392ff04a86c91ae9c5dcc5b9 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Mon, 24 Mar 2025 17:08:31 +0900 Subject: [PATCH 04/33] =?UTF-8?q?feat:=20=EA=B5=AC=EA=B8=80=20=EB=A7=B5=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=84=ED=8A=B8=20=EA=B8=B0=EB=8A=A5=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 --- src/app/api/image/map/route.js | 68 +++++++++++++++++++++++++++++++++ src/hooks/common/useRefFiles.js | 14 +++++-- 2 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 src/app/api/image/map/route.js diff --git a/src/app/api/image/map/route.js b/src/app/api/image/map/route.js new file mode 100644 index 00000000..3bcfb35a --- /dev/null +++ b/src/app/api/image/map/route.js @@ -0,0 +1,68 @@ +import { NextResponse } from 'next/server' + +export async function GET(req) { + try { + const searchParams = req.nextUrl.searchParams + const q = searchParams.get('q') + const fileNm = searchParams.get('fileNm') + const zoom = searchParams.get('zoom') + + /** 구글 맵을 이미지로 변경하기 위한 API */ + const API_KEY = 'AIzaSyDO7nVR1N_D2tKy60hgGFavpLaXkHpiHpc' + const targetUrl = `https://maps.googleapis.com/maps/api/staticmap?center=${q}&zoom=${zoom}&maptype=satellite&size=640x640&scale=1&key=${API_KEY}` + const decodeUrl = decodeURIComponent(targetUrl) + + /** 구글 맵을 이미지로 변경하기 위한 API 호출 */ + const response = await fetch(decodeUrl) + const data = await response.arrayBuffer() + // const buffer = Buffer.from(data) + + /** 변경된 이미지를 S3에 업로드 */ + const Body = Buffer.from(data) + const Key = `map/${file.name}` + const ContentType = 'image/png' + + await s3.send( + new PutObjectCommand({ + Bucket, + Key, + Body, + ContentType, + }), + ) + + const result = { + filePath: `https://${process.env.AMPLIFY_BUCKET}.s3.${process.env.AWS_REGION}.amazonaws.com/${Key}`, + fileName: Key, + } + + return NextResponse.json(result) + } catch (error) { + console.error(error) + return NextResponse.json({ error: 'Failed to upload image' }, { status: 500 }) + } +} + +export async function DELETE(req) { + try { + const searchParams = req.nextUrl.searchParams + const Key = `map/${searchParams.get('fileName')}` + console.log('🚀 ~ DELETE ~ Key:', Key) + + if (!Key) { + return NextResponse.json({ error: 'fileName parameter is required' }, { status: 400 }) + } + + await s3.send( + new DeleteObjectCommand({ + Bucket, + Key, + }), + ) + + return NextResponse.json({ message: '이미지 삭제 성공' }, { status: 200 }) + } catch (error) { + console.error('S3 Delete Error:', error) + return NextResponse.json({ error: 'Failed to delete image' }, { status: 500 }) + } +} diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index 1642daa9..254c4b12 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -105,6 +105,9 @@ export function useRefFiles() { text: '삭제하시겠습니까?', type: 'confirm', confirmFn: async () => { + console.log('🚀 ~ handleAddressDelete ~ handleAddressDelete:', refImage) + console.log('🚀 ~ handleAddressDelete ~ currentCanvasPlan.bgImageName:', currentCanvasPlan.bgImageName) + await del({ url: `http://localhost:3000/api/image/map?fileName=${currentCanvasPlan.bgImageName}` }) setMapPositionAddress('') setCurrentBgImage(null) setCurrentCanvasPlan((prev) => ({ ...prev, mapPositionAddress: null })) @@ -135,16 +138,21 @@ export function useRefFiles() { option1: newOption1, })) + // const res = await get({ + // url: `${process.env.NEXT_PUBLIC_HOST_URL}/map/convert?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20`, + // }) const res = await get({ - url: `${process.env.NEXT_PUBLIC_HOST_URL}/map/convert?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20`, + url: `http://localhost:3000/api/map/upload?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20`, }) console.log('🚀 ~ handleMapImageDown ~ res:', res) - setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`) + // setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`) + setCurrentBgImage(`${res.filePath}`) await setBackGroundImage({ objectId: currentCanvasPlan.id, planNo: currentCanvasPlan.planNo, - imagePath: `${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`, + // imagePath: `${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`, + imagePath: `${res.filePath}`, }) } From 9a9fa522f9e158d06c18a5bee97c3e749d4f0afe Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Mon, 24 Mar 2025 17:54:32 +0900 Subject: [PATCH 05/33] =?UTF-8?q?feat:=20=EA=B5=AC=EA=B8=80=20=EB=A7=B5=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=84=ED=8A=B8=20=EA=B8=B0=EB=8A=A5=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- qcast3.database.sqlite | Bin 16384 -> 16384 bytes src/app/api/image/map/route.js | 14 ++++++++++++-- src/hooks/common/useRefFiles.js | 29 +++++++++++++++++++---------- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/qcast3.database.sqlite b/qcast3.database.sqlite index 66ac677f482169e439cd063c21efbc753f2a27c9..e6022fd79a14effb51bb9a253191dd42b5f6ec9e 100644 GIT binary patch delta 59 zcmZo@U~Fh$oFL7pHc`fzQEg+we0^?VUIqpRM*bZP{5v*t8LZ>ya1&-@5M^v+p1j%K PoHIAEpjh9;(A)q3y!Q^F delta 63 zcmZo@U~Fh$oFL68J5k1&QFdd(e0^>{UIri#U|`^1y_w5k9slH`_C{i*1v&YNDf+pU R#f3S#Ir-`NdRYaj=>Q$c63zes diff --git a/src/app/api/image/map/route.js b/src/app/api/image/map/route.js index 3bcfb35a..0cc76c02 100644 --- a/src/app/api/image/map/route.js +++ b/src/app/api/image/map/route.js @@ -1,4 +1,14 @@ import { NextResponse } from 'next/server' +import { S3Client, PutObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3' + +const Bucket = process.env.AMPLIFY_BUCKET +const s3 = new S3Client({ + region: process.env.AWS_REGION, + credentials: { + accessKeyId: process.env.AWS_ACCESS_KEY_ID, + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, + }, +}) export async function GET(req) { try { @@ -19,7 +29,7 @@ export async function GET(req) { /** 변경된 이미지를 S3에 업로드 */ const Body = Buffer.from(data) - const Key = `map/${file.name}` + const Key = `maps/${fileNm}` const ContentType = 'image/png' await s3.send( @@ -46,7 +56,7 @@ export async function GET(req) { export async function DELETE(req) { try { const searchParams = req.nextUrl.searchParams - const Key = `map/${searchParams.get('fileName')}` + const Key = `maps/${searchParams.get('fileName')}` console.log('🚀 ~ DELETE ~ Key:', Key) if (!Key) { diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index 254c4b12..3e726364 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -142,7 +142,7 @@ export function useRefFiles() { // url: `${process.env.NEXT_PUBLIC_HOST_URL}/map/convert?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20`, // }) const res = await get({ - url: `http://localhost:3000/api/map/upload?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20`, + url: `http://localhost:3000/api/image/map?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20`, }) console.log('🚀 ~ handleMapImageDown ~ res:', res) // setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`) @@ -160,16 +160,25 @@ export function useRefFiles() { * 배경 이미지 로드를 위한 세팅 */ useEffect(() => { - if (!currentBgImage) { - return - } + // if (!currentBgImage) { + // return + // } console.log('🚀 ~ useEffect ~ currentBgImage:', currentBgImage) - handleBackImageLoadToCanvas(currentBgImage) - setCurrentCanvasPlan((prev) => ({ - ...prev, - bgImageName: refImage?.name ?? null, - mapPositionAddress: queryRef.current.value, - })) + if (currentBgImage) { + handleBackImageLoadToCanvas(currentBgImage) + setCurrentCanvasPlan((prev) => ({ + ...prev, + // bgImageName: refImage?.name ?? null, + bgImageName: currentBgImage.split('/').pop(), + mapPositionAddress: queryRef.current.value, + })) + } else { + setCurrentCanvasPlan((prev) => ({ + ...prev, + bgImageName: null, + mapPositionAddress: null, + })) + } }, [currentBgImage]) /** From 11edbe19883e7034f58673dabc38def0179fd1a2 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Mon, 24 Mar 2025 19:01:09 +0900 Subject: [PATCH 06/33] =?UTF-8?q?feat:=20cad=ED=8C=8C=EC=9D=BC=20=EC=BB=A8?= =?UTF-8?q?=EB=B2=84=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/api/image/cad/route.js | 70 +++++++++++++++++++++++++++++++++ src/hooks/common/useRefFiles.js | 37 ++++++++++++++--- 2 files changed, 101 insertions(+), 6 deletions(-) create mode 100644 src/app/api/image/cad/route.js diff --git a/src/app/api/image/cad/route.js b/src/app/api/image/cad/route.js new file mode 100644 index 00000000..510feff2 --- /dev/null +++ b/src/app/api/image/cad/route.js @@ -0,0 +1,70 @@ +import { NextResponse } from 'next/server' +import { S3Client, PutObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3' + +const Bucket = process.env.AMPLIFY_BUCKET +const s3 = new S3Client({ + region: process.env.AWS_REGION, + credentials: { + accessKeyId: process.env.AWS_ACCESS_KEY_ID, + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, + }, +}) + +const uploadImage = async (file) => { + const Body = Buffer.from(await file.arrayBuffer()) + const Key = `cads/${file.name}` + const ContentType = file.ContentType + + await s3.send( + new PutObjectCommand({ + Bucket, + Key, + Body, + ContentType, + }), + ) + + return { + filePath: `https://${process.env.AMPLIFY_BUCKET}.s3.${process.env.AWS_REGION}.amazonaws.com/${Key}`, + fileName: Key, + } +} + +export async function POST(req) { + try { + const formData = await req.formData() + const file = formData.get('file') + + const result = await uploadImage(file) + result.message = '이미지 업로드 성공' + + return NextResponse.json(result) + } catch (error) { + console.error(error) + return NextResponse.json({ error: 'Failed to upload image' }, { status: 500 }) + } +} + +export async function DELETE(req) { + try { + const searchParams = req.nextUrl.searchParams + const Key = `cads/${searchParams.get('fileName')}` + console.log('🚀 ~ DELETE ~ Key:', Key) + + if (!Key) { + return NextResponse.json({ error: 'fileName parameter is required' }, { status: 400 }) + } + + await s3.send( + new DeleteObjectCommand({ + Bucket, + Key, + }), + ) + + return NextResponse.json({ message: '이미지 삭제 성공' }, { status: 200 }) + } catch (error) { + console.error('S3 Delete Error:', error) + return NextResponse.json({ error: 'Failed to delete image' }, { status: 500 }) + } +} diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index 3e726364..097d42ae 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -87,8 +87,9 @@ export function useRefFiles() { console.log('🚀 ~ handleFileDelete ~ handleFileDelete:', refImage) console.log('🚀 ~ handleFileDelete ~ currentCanvasPlan.bgImageName:', currentCanvasPlan.bgImageName) await del({ url: `http://localhost:3000/api/image/upload?fileName=${currentCanvasPlan.bgImageName}` }) - setRefImage(null) - setCurrentCanvasPlan((prev) => ({ ...prev, bgImageName: null })) + // setRefImage(null) + setCurrentBgImage(null) + // setCurrentCanvasPlan((prev) => ({ ...prev, bgImageName: null })) await deleteBackGroundImage({ objectId: currentCanvasPlan.id, planNo: currentCanvasPlan.planNo, @@ -110,7 +111,7 @@ export function useRefFiles() { await del({ url: `http://localhost:3000/api/image/map?fileName=${currentCanvasPlan.bgImageName}` }) setMapPositionAddress('') setCurrentBgImage(null) - setCurrentCanvasPlan((prev) => ({ ...prev, mapPositionAddress: null })) + // setCurrentCanvasPlan((prev) => ({ ...prev, mapPositionAddress: null })) await deleteBackGroundImage({ objectId: currentCanvasPlan.id, planNo: currentCanvasPlan.planNo, @@ -173,6 +174,7 @@ export function useRefFiles() { mapPositionAddress: queryRef.current.value, })) } else { + setRefImage(null) setCurrentCanvasPlan((prev) => ({ ...prev, bgImageName: null, @@ -230,15 +232,38 @@ export function useRefFiles() { const formData = new FormData() formData.append('file', file) + /** 캐드 도면 파일 변환 */ const res = await post({ url: converterUrl, data: formData }) console.log('🚀 ~ handleUploadConvertRefFile ~ res:', res) + + /** 캐드 도면 파일 업로드 */ const result = await post({ - url: `${process.env.NEXT_PUBLIC_HOST_URL}/cad/convert`, + url: `http://localhost:3000/api/image/cad`, data: res, }) console.log('🚀 ~ handleUploadConvertRefFile ~ result:', result) - setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${result.filePath}`) - setRefImage(res.Files[0].FileData) + + setCurrentBgImage(`${result.filePath}`) + setRefImage(file) + + const params = { + objectId: currentCanvasPlan.id, + planNo: currentCanvasPlan.planNo, + // imagePath: `${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`, + imagePath: `${result.filePath}`, + } + console.log('🚀 ~ handleUploadImageRefFile ~ params:', params) + await setBackGroundImage(params) + + // const res = await post({ url: converterUrl, data: formData }) + // console.log('🚀 ~ handleUploadConvertRefFile ~ res:', res) + // const result = await post({ + // url: `${process.env.NEXT_PUBLIC_HOST_URL}/cad/convert`, + // data: res, + // }) + // console.log('🚀 ~ handleUploadConvertRefFile ~ result:', result) + // setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${result.filePath}`) + // setRefImage(res.Files[0].FileData) } /** From 97389f714162a0872e8a7a9d9d3ed3a5d9735f20 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Tue, 25 Mar 2025 11:01:40 +0900 Subject: [PATCH 07/33] =?UTF-8?q?feat:=20=EC=BA=94=EB=B2=84=EC=8A=A4=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20S3=EB=A1=9C=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/api/image/canvas/route.js | 120 ++++++++++++++++++++++++++++ src/app/api/image/upload/route.js | 8 +- src/hooks/floorPlan/useImgLoader.js | 3 +- 3 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 src/app/api/image/canvas/route.js diff --git a/src/app/api/image/canvas/route.js b/src/app/api/image/canvas/route.js new file mode 100644 index 00000000..f2e6df86 --- /dev/null +++ b/src/app/api/image/canvas/route.js @@ -0,0 +1,120 @@ +import { NextResponse } from 'next/server' +import { S3Client, PutObjectCommand, DeleteObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3' +import sharp from 'sharp' +import { v4 as uuidv4 } from 'uuid' +const Bucket = process.env.AMPLIFY_BUCKET +const s3 = new S3Client({ + region: process.env.AWS_REGION, + credentials: { + accessKeyId: process.env.AWS_ACCESS_KEY_ID, + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, + }, +}) + +const checkArea = (obj) => { + const { width, height, left, top } = obj + + if (left < 0 || top < 0 || width > 1600 || height > 1000) { + return false + } + + return true +} + +const cropImage = async (Key, width, height, left, top) => { + try { + const checkResult = checkArea({ width, height, left, top }) + + // Get the image from S3 + const { Body } = await s3.send( + new GetObjectCommand({ + Bucket, + Key, + }), + ) + + // Convert stream to buffer + const chunks = [] + for await (const chunk of Body) { + chunks.push(chunk) + } + const imageBuffer = Buffer.concat(chunks) + + let processedImage + if (!checkResult) { + processedImage = await sharp(imageBuffer).toBuffer() + } else { + processedImage = await sharp(imageBuffer) + .extract({ + width: parseInt(width), + height: parseInt(height), + left: parseInt(left), + top: parseInt(top), + }) + .png() + .toBuffer() + } + return processedImage + } catch (error) { + console.error('Error processing image:', error) + throw error + } +} + +export async function POST(req) { + try { + const formData = await req.formData() + const file = formData.get('file') + const objectNo = formData.get('objectNo') + const planNo = formData.get('planNo') + const type = formData.get('type') + const width = formData.get('width') + const height = formData.get('height') + const left = formData.get('left') + const top = formData.get('top') + + const OriginalKey = `Drawing/${uuidv4()}` + + // Upload original image + await s3.send( + new PutObjectCommand({ + Bucket, + Key: OriginalKey, + Body: Buffer.from(await file.arrayBuffer()), + ContentType: 'image/png', + }), + ) + + // Process the image + const bufferImage = await cropImage(OriginalKey, width, height, left, top) + + const Key = `Drawing/${objectNo}_${planNo}_${type}` + + // Upload processed image + await s3.send( + new PutObjectCommand({ + Bucket, + Key, + Body: bufferImage, + ContentType: 'image/png', + }), + ) + + await s3.send( + new DeleteObjectCommand({ + Bucket, + Key: OriginalKey, + }), + ) + + const result = { + filePath: `https://${process.env.AMPLIFY_BUCKET}.s3.${process.env.AWS_REGION}.amazonaws.com/${Key}`, + fileName: Key, + } + + return NextResponse.json(result) + } catch (error) { + console.error('Error in POST:', error) + return NextResponse.json({ error: 'Failed to process and upload image' }, { status: 500 }) + } +} diff --git a/src/app/api/image/upload/route.js b/src/app/api/image/upload/route.js index 99daa259..4d875257 100644 --- a/src/app/api/image/upload/route.js +++ b/src/app/api/image/upload/route.js @@ -48,13 +48,15 @@ export async function POST(req) { export async function DELETE(req) { try { const searchParams = req.nextUrl.searchParams - const Key = `upload/${searchParams.get('fileName')}` - console.log('🚀 ~ DELETE ~ Key:', Key) + const fileName = searchParams.get('fileName') - if (!Key) { + if (!fileName) { return NextResponse.json({ error: 'fileName parameter is required' }, { status: 400 }) } + const Key = `upload/${fileName}` + console.log('🚀 ~ DELETE ~ Key:', Key) + await s3.send( new DeleteObjectCommand({ Bucket, diff --git a/src/hooks/floorPlan/useImgLoader.js b/src/hooks/floorPlan/useImgLoader.js index e51a4a2b..2a5a09ab 100644 --- a/src/hooks/floorPlan/useImgLoader.js +++ b/src/hooks/floorPlan/useImgLoader.js @@ -79,7 +79,8 @@ export function useImgLoader() { /** 이미지 크롭 요청 */ const result = await post({ - url: `${process.env.NEXT_PUBLIC_HOST_URL}/image/canvas`, + // url: `${process.env.NEXT_PUBLIC_HOST_URL}/image/canvas`, + url: `http://localhost:3000/api/image/canvas`, data: formData, }) console.log('🚀 ~ handleCanvasToPng ~ result:', result) From 553a259c1fc4f09e14bc4ab0569898f225d91b32 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Tue, 25 Mar 2025 11:02:08 +0900 Subject: [PATCH 08/33] =?UTF-8?q?chore:=20=EB=8F=84=EB=A9=B4=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=ED=81=AC=EB=A1=AD=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20sharp=20lib=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 230e1b81..4c3b230b 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "react-responsive-modal": "^6.4.2", "react-select": "^5.8.1", "recoil": "^0.7.7", + "sharp": "^0.33.5", "sqlite": "^5.1.1", "sqlite3": "^5.1.7", "sweetalert2": "^11.14.1", From 8d645d08dca2ba91b6aa71dcc542804acfdc84ff Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Tue, 25 Mar 2025 13:33:36 +0900 Subject: [PATCH 09/33] =?UTF-8?q?refactor:=20API=20Router=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=9D=BC=EB=B6=80=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 패턴에 어긋나는 응답 포맷 수정 - 주석 작성 --- src/app/api/image/cad/route.js | 1 - src/app/api/image/canvas/route.js | 19 ++++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/app/api/image/cad/route.js b/src/app/api/image/cad/route.js index 510feff2..b7d64a50 100644 --- a/src/app/api/image/cad/route.js +++ b/src/app/api/image/cad/route.js @@ -36,7 +36,6 @@ export async function POST(req) { const file = formData.get('file') const result = await uploadImage(file) - result.message = '이미지 업로드 성공' return NextResponse.json(result) } catch (error) { diff --git a/src/app/api/image/canvas/route.js b/src/app/api/image/canvas/route.js index f2e6df86..6a15e9bf 100644 --- a/src/app/api/image/canvas/route.js +++ b/src/app/api/image/canvas/route.js @@ -75,7 +75,10 @@ export async function POST(req) { const OriginalKey = `Drawing/${uuidv4()}` - // Upload original image + /** + * 원본 이미지를 우선 저장한다. + * 이미지 이름이 겹지는 현상을 방지하기 위해 uuid 를 사용한다. + */ await s3.send( new PutObjectCommand({ Bucket, @@ -85,12 +88,19 @@ export async function POST(req) { }), ) - // Process the image + /** + * 저장된 원본 이미지를 기준으로 크롭여부를 결정하여 크롭 이미지를 저장한다. + */ const bufferImage = await cropImage(OriginalKey, width, height, left, top) + /** + * 크롭 이미지 이름을 결정한다. + */ const Key = `Drawing/${objectNo}_${planNo}_${type}` - // Upload processed image + /** + * 크롭이 완료된 이미지를 업로드한다. + */ await s3.send( new PutObjectCommand({ Bucket, @@ -100,6 +110,9 @@ export async function POST(req) { }), ) + /** + * 크롭이미지 저장이 완료되면 원본 이미지를 삭제한다. + */ await s3.send( new DeleteObjectCommand({ Bucket, From c7de33b8b9021a794c1d7129e2931d7c76dc72cc Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Tue, 25 Mar 2025 14:20:28 +0900 Subject: [PATCH 10/33] =?UTF-8?q?fix:=20popup=20spinner=20=EB=8F=99?= =?UTF-8?q?=EC=9E=91=20=EC=B6=94=EA=B0=80?= 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 | 8 +++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/qcast3.database.sqlite b/qcast3.database.sqlite index e6022fd79a14effb51bb9a253191dd42b5f6ec9e..166f2da26bfaf6d977a400c5ef8dd5a21ef49896 100644 GIT binary patch delta 82 zcmZo@U~Fh$oFL7pHBrWyQEOwue0^R~UIqpRM*bZP{5$wlHuD%n@bd(TvN4EqHp-fq mm|0FfYHuV~T9A{Un4+IsSzMT-o0FfOua{Mjnm&1ly$1kpWEZml delta 102 zcmZo@U~Fh$oFL7pHc`fzQEg+we0^SFUIqpRM*bZP{5yC(HuD%n@K27nlQmB^w=_vL zH8IjnPDx79HAyoz)lEt>veZpUGdD6yGBZd_O197|$O{YQ4d!EG5M^wXH8C_d;F`R{ G-U9$hz8XaU diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index 097d42ae..3be7fff2 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from 'react' -import { useRecoilState } from 'recoil' +import { useRecoilState, useSetRecoilState } from 'recoil' import { useSwal } from '@/hooks/useSwal' import { useAxios } from '../useAxios' @@ -7,6 +7,7 @@ import { currentCanvasPlanState } from '@/store/canvasAtom' import { useCanvas } from '@/hooks/useCanvas' import { deleteBackGroundImage, setBackGroundImage } from '@/lib/imageActions' import { settingModalFirstOptionsState } from '@/store/settingAtom' +import { popSpinnerState } from '@/store/popupAtom' /** * 배경 이미지 관리 @@ -29,6 +30,7 @@ export function useRefFiles() { const { handleBackImageLoadToCanvas } = useCanvas() const { swalFire } = useSwal() const { get, post, del } = useAxios() + const setPopSpinnerStore = useSetRecoilState(popSpinnerState) useEffect(() => { if (refFileMethod === '1') { @@ -84,6 +86,7 @@ export function useRefFiles() { text: '삭제하시겠습니까?', type: 'confirm', confirmFn: async () => { + setPopSpinnerStore(true) console.log('🚀 ~ handleFileDelete ~ handleFileDelete:', refImage) console.log('🚀 ~ handleFileDelete ~ currentCanvasPlan.bgImageName:', currentCanvasPlan.bgImageName) await del({ url: `http://localhost:3000/api/image/upload?fileName=${currentCanvasPlan.bgImageName}` }) @@ -94,6 +97,7 @@ export function useRefFiles() { objectId: currentCanvasPlan.id, planNo: currentCanvasPlan.planNo, }) + setPopSpinnerStore(false) }, }) } @@ -188,6 +192,7 @@ export function useRefFiles() { * @param {*} file */ const handleUploadImageRefFile = async (file) => { + setPopSpinnerStore(true) const newOption1 = settingModalFirstOptions.option1.map((option) => ({ ...option, selected: option.column === 'imageDisplay' ? true : option.selected, @@ -222,6 +227,7 @@ export function useRefFiles() { } console.log('🚀 ~ handleUploadImageRefFile ~ params:', params) await setBackGroundImage(params) + setPopSpinnerStore(false) } /** From c6b96bec23a054ed5dcff169a5c14719f54d7ccc Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 23 Apr 2025 10:03:25 +0900 Subject: [PATCH 11/33] chore: update environment variables to use protocol-relative URLs for host --- .env.development | 2 +- .env.production | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.development b/.env.development index 4f613c70..ceac1712 100644 --- a/.env.development +++ b/.env.development @@ -1,6 +1,6 @@ NEXT_PUBLIC_API_SERVER_PATH="http://1.248.227.176:38080" -NEXT_PUBLIC_HOST_URL="http://1.248.227.176:4000" +NEXT_PUBLIC_HOST_URL="//1.248.227.176:4000" SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y=" diff --git a/.env.production b/.env.production index f0951f7a..767c3e4b 100644 --- a/.env.production +++ b/.env.production @@ -1,6 +1,6 @@ NEXT_PUBLIC_API_SERVER_PATH="https://api.hanasys.jp/" -NEXT_PUBLIC_HOST_URL="http://1.248.227.176:4000" +NEXT_PUBLIC_HOST_URL="//1.248.227.176:4000" SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y=" From ef75ad0ef8a080d58e086de2d4f98204a254bd63 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Thu, 8 May 2025 13:29:13 +0900 Subject: [PATCH 12/33] chore: update environment variables for Japanese server configuration --- .env.development | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/.env.development b/.env.development index ceac1712..6488b496 100644 --- a/.env.development +++ b/.env.development @@ -10,8 +10,16 @@ NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secr NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="http://q-order-stg.q-cells.jp:8120/eos/login/autoLogin" NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-stg.q-cells.jp:8120/qm/login/autoLogin" -AWS_REGION="ap-northeast-2" -AMPLIFY_BUCKET="interplug" -AWS_ACCESS_KEY_ID="AKIAVWMWJCUXFHEAZ4FR" -AWS_SECRET_ACCESS_KEY="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" -NEXT_PUBLIC_AWS_S3_BASE_URL="https://interplug.s3.ap-northeast-2.amazonaws.com" +# 테스트용 +# AWS_REGION="ap-northeast-2" +# AMPLIFY_BUCKET="interplug" +# AWS_ACCESS_KEY_ID="AKIAVWMWJCUXFHEAZ4FR" +# AWS_SECRET_ACCESS_KEY="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" +# NEXT_PUBLIC_AWS_S3_BASE_URL="https://interplug.s3.ap-northeast-2.amazonaws.com" + +# 실제 일본 서버 +AWS_REGION="ap-northeast-1" +AMPLIFY_BUCKET="files.hanasys.jp" +AWS_ACCESS_KEY_ID="AKIA3K4QWLZHFZRJOM2E" +AWS_SECRET_ACCESS_KEY="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" +NEXT_PUBLIC_AWS_S3_BASE_URL="http://files.hanasys.jp.s3-website-ap-northeast-1.amazonaws.com" \ No newline at end of file From 1d4100a579abf9d94dbe39bcd55403b216b17f28 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Tue, 13 May 2025 15:13:59 +0900 Subject: [PATCH 13/33] chore: nextjs version update --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4c3b230b..bbddf9ad 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "js-cookie": "^3.0.5", "mathjs": "^13.0.2", "mssql": "^11.0.1", - "next": "14.2.21", + "next": "14.2.28", "next-international": "^1.2.4", "react": "^18", "react-chartjs-2": "^5.2.0", From ad2aa50d83c8e6264da01dbe20ad5c3fcd668bb4 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Tue, 13 May 2025 15:24:57 +0900 Subject: [PATCH 14/33] =?UTF-8?q?feat:=20=EC=BA=94=EB=B2=84=EC=8A=A4=20s3?= =?UTF-8?q?=20=EC=A0=80=EC=9E=A5=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=B0=8F?= =?UTF-8?q?=20=ED=99=95=EC=9E=A5=EC=9E=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/api/image/canvas/route.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/api/image/canvas/route.js b/src/app/api/image/canvas/route.js index 6a15e9bf..0a4d0be2 100644 --- a/src/app/api/image/canvas/route.js +++ b/src/app/api/image/canvas/route.js @@ -96,7 +96,7 @@ export async function POST(req) { /** * 크롭 이미지 이름을 결정한다. */ - const Key = `Drawing/${objectNo}_${planNo}_${type}` + const Key = `Drawing/${objectNo}_${planNo}_${type}.png` /** * 크롭이 완료된 이미지를 업로드한다. From 3fefb4b22fd0cafea823737b671794a91feb6610 Mon Sep 17 00:00:00 2001 From: nalpari Date: Tue, 13 May 2025 16:33:37 +0900 Subject: [PATCH 15/33] feat: update environment variables and API endpoint in useImgLoader hook --- .env.development | 2 ++ .env.production | 2 ++ src/hooks/floorPlan/useImgLoader.js | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.env.development b/.env.development index 6488b496..1ca922e7 100644 --- a/.env.development +++ b/.env.development @@ -2,6 +2,8 @@ NEXT_PUBLIC_API_SERVER_PATH="http://1.248.227.176:38080" NEXT_PUBLIC_HOST_URL="//1.248.227.176:4000" +NEXT_PUBLIC_API_HOST_URL="http://1.248.227.176:5000" + SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y=" # NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3" diff --git a/.env.production b/.env.production index 767c3e4b..3842b041 100644 --- a/.env.production +++ b/.env.production @@ -2,6 +2,8 @@ NEXT_PUBLIC_API_SERVER_PATH="https://api.hanasys.jp/" NEXT_PUBLIC_HOST_URL="//1.248.227.176:4000" +NEXT_PUBLIC_API_HOST_URL="https://www.hanasys.jp/" + SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y=" # NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3" diff --git a/src/hooks/floorPlan/useImgLoader.js b/src/hooks/floorPlan/useImgLoader.js index 2a5a09ab..ca5fef79 100644 --- a/src/hooks/floorPlan/useImgLoader.js +++ b/src/hooks/floorPlan/useImgLoader.js @@ -79,8 +79,8 @@ export function useImgLoader() { /** 이미지 크롭 요청 */ const result = await post({ - // url: `${process.env.NEXT_PUBLIC_HOST_URL}/image/canvas`, - url: `http://localhost:3000/api/image/canvas`, + // url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/image/canvas`, + url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/canvas`, data: formData, }) console.log('🚀 ~ handleCanvasToPng ~ result:', result) From 2f5f49c69cc6a37c7e7d1c19c0177eef76b361e1 Mon Sep 17 00:00:00 2001 From: yjnoh Date: Wed, 14 May 2025 09:59:46 +0900 Subject: [PATCH 16/33] =?UTF-8?q?canvas=20=EC=8B=9C=EC=9E=91=EC=8B=9C=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/common/useCanvasPopupStatusController.js | 5 +++-- src/hooks/surface/useSurfaceShapeBatch.js | 4 ---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/hooks/common/useCanvasPopupStatusController.js b/src/hooks/common/useCanvasPopupStatusController.js index b6499099..e7bd8457 100644 --- a/src/hooks/common/useCanvasPopupStatusController.js +++ b/src/hooks/common/useCanvasPopupStatusController.js @@ -37,6 +37,7 @@ export function useCanvasPopupStatusController(param = 1) { * @returns */ const getModuleSelection = async (popupTypeParam) => { + if (!currentCanvasPlan.objectNo || !currentCanvasPlan.planNo) return const result = await promiseGet({ url: `/api/v1/canvas-popup-status?objectNo=${currentCanvasPlan.objectNo}&planNo=${currentCanvasPlan.planNo}&popupType=${popupTypeParam}`, }) @@ -48,7 +49,7 @@ export function useCanvasPopupStatusController(param = 1) { return null }) - return result.data + return result?.data } /** @@ -59,7 +60,7 @@ export function useCanvasPopupStatusController(param = 1) { let resultData = {} for (let i = 1; i < 3; i++) { const result = await getModuleSelection(i) - if (!result.objectNo) return + if (!result?.objectNo) return if (i === 1) { if (result.popupStatus && unescapeString(result.popupStatus)) { const data = JSON.parse(unescapeString(result.popupStatus)) diff --git a/src/hooks/surface/useSurfaceShapeBatch.js b/src/hooks/surface/useSurfaceShapeBatch.js index 16f68668..863de4bf 100644 --- a/src/hooks/surface/useSurfaceShapeBatch.js +++ b/src/hooks/surface/useSurfaceShapeBatch.js @@ -72,16 +72,12 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) { length5 = surfaceRefs.length5.current.value } - console.log(' before length : ', length1, length2, length3, length4, length5) - length1 = parseFloat(length1 === undefined ? 0 : Number(length1 / 10).toFixed(1)) length2 = parseFloat(length2 === undefined ? 0 : Number(length2 / 10).toFixed(1)) length3 = parseFloat(length3 === undefined ? 0 : Number(length3 / 10).toFixed(1)) length4 = parseFloat(length4 === undefined ? 0 : Number(length4 / 10).toFixed(1)) length5 = parseFloat(length5 === undefined ? 0 : Number(length5 / 10).toFixed(1)) - console.log(' after length : ', length1, length2, length3, length4, length5) - let isDrawing = true let obj = null let points = [] From 5e359bb0baea127475d2de9c0db388c16aadb6ea Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 14 May 2025 10:54:16 +0900 Subject: [PATCH 17/33] fix: update API host URL and S3 base URL in environment files; refactor useRefFiles hook to utilize environment variables for API endpoints --- .env.development | 4 ++-- .env.production | 2 +- qcast3.database.sqlite | Bin 16384 -> 16384 bytes src/hooks/common/useRefFiles.js | 16 +++++++++------- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.env.development b/.env.development index 1ca922e7..e6e38032 100644 --- a/.env.development +++ b/.env.development @@ -2,7 +2,7 @@ NEXT_PUBLIC_API_SERVER_PATH="http://1.248.227.176:38080" NEXT_PUBLIC_HOST_URL="//1.248.227.176:4000" -NEXT_PUBLIC_API_HOST_URL="http://1.248.227.176:5000" +NEXT_PUBLIC_API_HOST_URL="http://1.248.227.176:3000" SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y=" @@ -24,4 +24,4 @@ AWS_REGION="ap-northeast-1" AMPLIFY_BUCKET="files.hanasys.jp" AWS_ACCESS_KEY_ID="AKIA3K4QWLZHFZRJOM2E" AWS_SECRET_ACCESS_KEY="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" -NEXT_PUBLIC_AWS_S3_BASE_URL="http://files.hanasys.jp.s3-website-ap-northeast-1.amazonaws.com" \ No newline at end of file +NEXT_PUBLIC_AWS_S3_BASE_URL="//files.hanasys.jp" \ No newline at end of file diff --git a/.env.production b/.env.production index 3842b041..b2d50cdd 100644 --- a/.env.production +++ b/.env.production @@ -18,4 +18,4 @@ AWS_REGION="ap-northeast-2" AMPLIFY_BUCKET="interplug" AWS_ACCESS_KEY_ID="AKIAVWMWJCUXFHEAZ4FR" AWS_SECRET_ACCESS_KEY="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" -NEXT_PUBLIC_AWS_S3_BASE_URL="https://interplug.s3.ap-northeast-2.amazonaws.com" \ No newline at end of file +NEXT_PUBLIC_AWS_S3_BASE_URL="//files.hanasys.jp" \ No newline at end of file diff --git a/qcast3.database.sqlite b/qcast3.database.sqlite index 166f2da26bfaf6d977a400c5ef8dd5a21ef49896..6a7a809a38f22f297032357b29759527ebbd7c22 100644 GIT binary patch delta 170 zcmZo@U~Fh$oFL6;K2gS*(R^dVe0^SNUIqpRM*bZP{5$yLHuD&`^4F(|u`!5pHaeTe zh_f+7NP{_=riP{#86_nJ#a8f<)OEL^&H}O-#%zCm*#p5-lyr$xlqt&#f#j%+bxsPtVuODoCBY-QE)b D->Vyv diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index 3be7fff2..94f7a8df 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -89,7 +89,7 @@ export function useRefFiles() { setPopSpinnerStore(true) console.log('🚀 ~ handleFileDelete ~ handleFileDelete:', refImage) console.log('🚀 ~ handleFileDelete ~ currentCanvasPlan.bgImageName:', currentCanvasPlan.bgImageName) - await del({ url: `http://localhost:3000/api/image/upload?fileName=${currentCanvasPlan.bgImageName}` }) + await del({ url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/upload?fileName=${currentCanvasPlan.bgImageName}` }) // setRefImage(null) setCurrentBgImage(null) // setCurrentCanvasPlan((prev) => ({ ...prev, bgImageName: null })) @@ -112,7 +112,7 @@ export function useRefFiles() { confirmFn: async () => { console.log('🚀 ~ handleAddressDelete ~ handleAddressDelete:', refImage) console.log('🚀 ~ handleAddressDelete ~ currentCanvasPlan.bgImageName:', currentCanvasPlan.bgImageName) - await del({ url: `http://localhost:3000/api/image/map?fileName=${currentCanvasPlan.bgImageName}` }) + await del({ url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/map?fileName=${currentCanvasPlan.bgImageName}` }) setMapPositionAddress('') setCurrentBgImage(null) // setCurrentCanvasPlan((prev) => ({ ...prev, mapPositionAddress: null })) @@ -147,7 +147,7 @@ export function useRefFiles() { // url: `${process.env.NEXT_PUBLIC_HOST_URL}/map/convert?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20`, // }) const res = await get({ - url: `http://localhost:3000/api/image/map?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20`, + url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/map?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20`, }) console.log('🚀 ~ handleMapImageDown ~ res:', res) // setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`) @@ -211,12 +211,13 @@ export function useRefFiles() { // data: formData, // }) const res = await post({ - url: `http://localhost:3000/api/image/upload`, + url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/upload`, data: formData, }) console.log('🚀 ~ handleUploadImageRefFile ~ res:', res) // setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`) - setCurrentBgImage(`${res.filePath}`) + // setCurrentBgImage(`${res.filePath}`) + setCurrentBgImage(`${process.env.NEXT_PUBLIC_AWS_S3_BASE_URL}/${res.fileName}`) setRefImage(file) const params = { @@ -244,12 +245,13 @@ export function useRefFiles() { /** 캐드 도면 파일 업로드 */ const result = await post({ - url: `http://localhost:3000/api/image/cad`, + url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/cad`, data: res, }) console.log('🚀 ~ handleUploadConvertRefFile ~ result:', result) - setCurrentBgImage(`${result.filePath}`) + // setCurrentBgImage(`${result.filePath}`) + setCurrentBgImage(`${process.env.NEXT_PUBLIC_AWS_S3_BASE_URL}/${res.fileName}`) setRefImage(file) const params = { From ad12f9b8172c52551e39fe454c206b460922c0fb Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 14 May 2025 10:59:15 +0900 Subject: [PATCH 18/33] fix: update API host URL in development environment file --- .env.development | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.development b/.env.development index e6e38032..d3e1ba88 100644 --- a/.env.development +++ b/.env.development @@ -2,7 +2,7 @@ NEXT_PUBLIC_API_SERVER_PATH="http://1.248.227.176:38080" NEXT_PUBLIC_HOST_URL="//1.248.227.176:4000" -NEXT_PUBLIC_API_HOST_URL="http://1.248.227.176:3000" +NEXT_PUBLIC_API_HOST_URL="http://1.248.227.176:5000" SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y=" From e26673b78a31500dc1b5252c75c39177750fa448 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 14 May 2025 11:03:43 +0900 Subject: [PATCH 19/33] fix: update background image URL in useRefFiles hook to utilize AWS S3 base URL --- src/hooks/common/useRefFiles.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index 94f7a8df..7d2cc0fa 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -151,7 +151,8 @@ export function useRefFiles() { }) console.log('🚀 ~ handleMapImageDown ~ res:', res) // setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`) - setCurrentBgImage(`${res.filePath}`) + // setCurrentBgImage(`${res.filePath}`) + setCurrentBgImage(`${process.env.NEXT_PUBLIC_AWS_S3_BASE_URL}/${res.fileName}`) await setBackGroundImage({ objectId: currentCanvasPlan.id, From 4bff451dc4167e05800a32de658bce6d918eaa1d Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 14 May 2025 11:22:50 +0900 Subject: [PATCH 20/33] refactor: enhance useRefFiles hook with additional comments and improve file handling logic for background images --- src/hooks/common/useRefFiles.js | 39 ++++++++++----------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/src/hooks/common/useRefFiles.js b/src/hooks/common/useRefFiles.js index 7d2cc0fa..d13e7213 100644 --- a/src/hooks/common/useRefFiles.js +++ b/src/hooks/common/useRefFiles.js @@ -16,6 +16,9 @@ import { popSpinnerState } from '@/store/popupAtom' * 이미지 -> 캔버스 배경에 이미지 로드 * 주소 -> 구글 맵에서 주소 검색 후 이미지로 다운로드 받아서 캔버스 배경에 이미지 로드 * .dwg -> api를 통해서 .png로 변환 후 캔버스 배경에 이미지 로드 + * + * setCurrentBgImage 에 이미지를 세팅하면 도면에 배경으로 로딩된다. + * 다만 S3 Response에 aws 고유 주소가 나오는데 여기서는 cloudfront 사용을 위해서 NEXT_PUBLIC_AWS_S3_BASE_URL 도메인을 사용한다. * @returns {object} */ export function useRefFiles() { @@ -41,6 +44,7 @@ export function useRefFiles() { }, [refFileMethod]) /** + * 최초 input type="file" 에 대한 이벤트 * 파일 불러오기 버튼 컨트롤 * @param {*} file */ @@ -61,6 +65,10 @@ export function useRefFiles() { } } + /** + * 허용하는 파일인지 체크한다 + * @param {File} file + */ const refFileSetting = (file) => { console.log('🚀 ~ refFileSetting ~ file:', file) if (file.name.split('.').pop() === 'dwg') { @@ -79,7 +87,7 @@ export function useRefFiles() { } /** - * 파일 삭제 + * 이미지 파일 삭제 */ const handleFileDelete = async () => { swalFire({ @@ -90,9 +98,7 @@ export function useRefFiles() { console.log('🚀 ~ handleFileDelete ~ handleFileDelete:', refImage) console.log('🚀 ~ handleFileDelete ~ currentCanvasPlan.bgImageName:', currentCanvasPlan.bgImageName) await del({ url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/upload?fileName=${currentCanvasPlan.bgImageName}` }) - // setRefImage(null) setCurrentBgImage(null) - // setCurrentCanvasPlan((prev) => ({ ...prev, bgImageName: null })) await deleteBackGroundImage({ objectId: currentCanvasPlan.id, planNo: currentCanvasPlan.planNo, @@ -103,7 +109,7 @@ export function useRefFiles() { } /** - * 주소 삭제 + * 주소 맵 이미지 삭제 */ const handleAddressDelete = async () => { swalFire({ @@ -115,7 +121,6 @@ export function useRefFiles() { await del({ url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/map?fileName=${currentCanvasPlan.bgImageName}` }) setMapPositionAddress('') setCurrentBgImage(null) - // setCurrentCanvasPlan((prev) => ({ ...prev, mapPositionAddress: null })) await deleteBackGroundImage({ objectId: currentCanvasPlan.id, planNo: currentCanvasPlan.planNo, @@ -125,7 +130,7 @@ export function useRefFiles() { } /** - * 주소로 구글 맵 이미지 다운로드 + * 주소로 구글 맵 이미지 다운로드하여 캔버스 배경으로 로드 */ const handleMapImageDown = async () => { console.log('🚀 ~ handleMapImageDown ~ handleMapImageDown:') @@ -143,15 +148,10 @@ export function useRefFiles() { option1: newOption1, })) - // const res = await get({ - // url: `${process.env.NEXT_PUBLIC_HOST_URL}/map/convert?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20`, - // }) const res = await get({ url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/map?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20`, }) console.log('🚀 ~ handleMapImageDown ~ res:', res) - // setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`) - // setCurrentBgImage(`${res.filePath}`) setCurrentBgImage(`${process.env.NEXT_PUBLIC_AWS_S3_BASE_URL}/${res.fileName}`) await setBackGroundImage({ @@ -207,17 +207,11 @@ export function useRefFiles() { const formData = new FormData() formData.append('file', file) - // const res = await post({ - // url: `${process.env.NEXT_PUBLIC_HOST_URL}/image/upload`, - // data: formData, - // }) const res = await post({ url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/upload`, data: formData, }) console.log('🚀 ~ handleUploadImageRefFile ~ res:', res) - // setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${res.filePath}`) - // setCurrentBgImage(`${res.filePath}`) setCurrentBgImage(`${process.env.NEXT_PUBLIC_AWS_S3_BASE_URL}/${res.fileName}`) setRefImage(file) @@ -251,7 +245,6 @@ export function useRefFiles() { }) console.log('🚀 ~ handleUploadConvertRefFile ~ result:', result) - // setCurrentBgImage(`${result.filePath}`) setCurrentBgImage(`${process.env.NEXT_PUBLIC_AWS_S3_BASE_URL}/${res.fileName}`) setRefImage(file) @@ -263,16 +256,6 @@ export function useRefFiles() { } console.log('🚀 ~ handleUploadImageRefFile ~ params:', params) await setBackGroundImage(params) - - // const res = await post({ url: converterUrl, data: formData }) - // console.log('🚀 ~ handleUploadConvertRefFile ~ res:', res) - // const result = await post({ - // url: `${process.env.NEXT_PUBLIC_HOST_URL}/cad/convert`, - // data: res, - // }) - // console.log('🚀 ~ handleUploadConvertRefFile ~ result:', result) - // setCurrentBgImage(`${process.env.NEXT_PUBLIC_HOST_URL}${result.filePath}`) - // setRefImage(res.Files[0].FileData) } /** From 8a49f7169b396bd52bc12a30950a826bf2397a71 Mon Sep 17 00:00:00 2001 From: ysCha Date: Wed, 14 May 2025 14:00:29 +0900 Subject: [PATCH 21/33] =?UTF-8?q?[948]=20-=20=EA=B2=AC=EC=A0=81=EC=84=9C?= =?UTF-8?q?=20=EC=96=91=EB=8B=A8=EC=BC=80=EC=9D=B4=EB=B8=94=20selectbox=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EC=BC=80=EC=9D=B4=EB=B8=94=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=20=EA=B0=80=EB=8A=A5.=20=EB=8B=A8=EC=96=B4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/estimate/Estimate.jsx | 75 +++++++++++++++++++++++----- src/locales/ja.json | 2 + src/locales/ko.json | 2 + 3 files changed, 66 insertions(+), 13 deletions(-) diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index 8ce54402..7237e056 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -60,7 +60,7 @@ export default function Estimate({}) { const [cableItemList, setCableItemList] = useState([]) //케이블 리스트 const [cableItem, setCableItem] = useState('') //케이블 선택값 - + const [cableDbItem, setCableDbItem] = useState('') //케이블 선택값 const [startDate, setStartDate] = useState(new Date()) const singleDatePickerProps = { startDate, @@ -98,7 +98,7 @@ export default function Estimate({}) { } const initEstimate = (currPid = currentPid) => { - console.log('🚀 ~ initEstimate ~ currPid:', currPid) + // console.log('🚀 ~ initEstimate ~ currPid:', currPid) closeAll() setObjectNo(objectRecoil.floorPlanObjectNo) @@ -117,6 +117,7 @@ export default function Estimate({}) { item.value = item.clRefChr1 item.label = item.clRefChr2 }) + // console.log(code2) setCableItemList(code2) } @@ -152,7 +153,7 @@ export default function Estimate({}) { } useEffect(() => { - console.log('🚀 ~ Estimate ~ selectedPlan:', selectedPlan) + // console.log('🚀 ~ Estimate ~ selectedPlan:', selectedPlan) if (selectedPlan) initEstimate(selectedPlan.planNo) }, [selectedPlan]) @@ -739,6 +740,18 @@ export default function Estimate({}) { setCableItem(value) } + /* 케이블 select 변경시 */ + const onChangeDisplayDoubleCableItem = (value, itemList) => { + itemList.map((item, index) => { + if (item.dispCableFlg === '1' && item.itemTpCd === 'M12') { + if (value !== '') { + onChangeDisplayItem(value, item.dispOrder, index, true) + } + } + }) + setCableDbItem(value) + } + // 아이템 자동완성 검색시 아이템 추가/변경시 const onChangeDisplayItem = (itemId, dispOrder, index, flag) => { const param = { @@ -1088,15 +1101,20 @@ export default function Estimate({}) { item.showSaleTotPrice = '0' } - if (item.dispCableFlg === '1' && item.itemTpCd !== 'M12') { + if (item.dispCableFlg === '1' ) { dispCableFlgCnt++ - setCableItem(item.itemId) + if(item.itemTpCd === 'M12') { + setCableDbItem(item.itemId) + }else{ + setCableItem(item.itemId) + } } } }) if (dispCableFlgCnt === 0) { setCableItem('100038') + setCableDbItem('100037') } let pkgAsp = estimateContextState.pkgAsp ? Number(estimateContextState.pkgAsp.replaceAll(',', '')) : 0 @@ -1159,14 +1177,20 @@ export default function Estimate({}) { dispCableFlgCnt++ } - if (item.dispCableFlg === '1' && item.itemTpCd !== 'M12') { - setCableItem(item.itemId) + if (item.dispCableFlg === '1'){ + + if(item.itemTpCd === 'M12') { + setCableDbItem(item.itemId) + }else{ + setCableItem(item.itemId) + } } } }) if (dispCableFlgCnt === 0) { setCableItem('100038') + setCableDbItem('100037') } totals.vatPrice = totals.supplyPrice * 0.1 @@ -1227,6 +1251,7 @@ export default function Estimate({}) { if (dispCableFlgCnt === 0) { setCableItem('100038') + setCableDbItem('100037') } } }, [estimateContextState?.itemList, cableItemList]) @@ -1831,6 +1856,7 @@ export default function Estimate({}) {
+
{getMessage('estimate.detail.header.singleCable')}
+
+
+
+
{getMessage('estimate.detail.header.doubleCable')}
+
+
@@ -1927,7 +1976,7 @@ export default function Estimate({}) { onChangeSelect(item.dispOrder)} checked={!!selection.has(item.dispOrder)} /> diff --git a/src/locales/ja.json b/src/locales/ja.json index 35f0b757..c59d0a16 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -944,6 +944,8 @@ "estimate.detail.sepcialEstimateProductInfo.pkgPrice": "PKG金額", "estimate.detail.header.showPrice": "価格表示", "estimate.detail.header.unitPrice": "定価", + "estimate.detail.header.singleCable": "片端ケーブル長さ", + "estimate.detail.header.doubleCable": "両端ケーブル長さ", "estimate.detail.showPrice.pricingBtn": "Pricing", "estimate.detail.showPrice.pricingBtn.noItemId": "Pricingが欠落しているアイテムがあります。 Pricingを進めてください。", "estimate.detail.showPrice.pricingBtn.confirm": "価格登録初期化されますがよろしいですか?", diff --git a/src/locales/ko.json b/src/locales/ko.json index daf9ad60..3374c1b9 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -945,6 +945,8 @@ "estimate.detail.sepcialEstimateProductInfo.pkgPrice": "PKG 금액", "estimate.detail.header.showPrice": "가격표시", "estimate.detail.header.unitPrice": "정가", + "estimate.detail.header.singleCable": "편당케이블 길이", + "estimate.detail.header.doubleCable": "양단케이블 길이", "estimate.detail.showPrice.pricingBtn": "Pricing", "estimate.detail.showPrice.pricingBtn.noItemId": "Pricing이 누락된 아이템이 있습니다. 제품 선택 후 Pricing을 진행해주세요.", "estimate.detail.showPrice.pricingBtn.confirm": "가격등록을 초기화 하시겠습니까?", From 5b322d0143a0aa0d800e7de76eeb6417b2b3e986 Mon Sep 17 00:00:00 2001 From: ysCha Date: Wed, 14 May 2025 14:06:45 +0900 Subject: [PATCH 22/33] feature/ysCha (#37) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [948] - 견적서 양단케이블 selectbox 추가 케이블 체크 가능. 단어 추가 --- src/components/estimate/Estimate.jsx | 75 +++++++++++++++++++++++----- src/locales/ja.json | 2 + src/locales/ko.json | 2 + 3 files changed, 66 insertions(+), 13 deletions(-) diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index 8ce54402..7237e056 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -60,7 +60,7 @@ export default function Estimate({}) { const [cableItemList, setCableItemList] = useState([]) //케이블 리스트 const [cableItem, setCableItem] = useState('') //케이블 선택값 - + const [cableDbItem, setCableDbItem] = useState('') //케이블 선택값 const [startDate, setStartDate] = useState(new Date()) const singleDatePickerProps = { startDate, @@ -98,7 +98,7 @@ export default function Estimate({}) { } const initEstimate = (currPid = currentPid) => { - console.log('🚀 ~ initEstimate ~ currPid:', currPid) + // console.log('🚀 ~ initEstimate ~ currPid:', currPid) closeAll() setObjectNo(objectRecoil.floorPlanObjectNo) @@ -117,6 +117,7 @@ export default function Estimate({}) { item.value = item.clRefChr1 item.label = item.clRefChr2 }) + // console.log(code2) setCableItemList(code2) } @@ -152,7 +153,7 @@ export default function Estimate({}) { } useEffect(() => { - console.log('🚀 ~ Estimate ~ selectedPlan:', selectedPlan) + // console.log('🚀 ~ Estimate ~ selectedPlan:', selectedPlan) if (selectedPlan) initEstimate(selectedPlan.planNo) }, [selectedPlan]) @@ -739,6 +740,18 @@ export default function Estimate({}) { setCableItem(value) } + /* 케이블 select 변경시 */ + const onChangeDisplayDoubleCableItem = (value, itemList) => { + itemList.map((item, index) => { + if (item.dispCableFlg === '1' && item.itemTpCd === 'M12') { + if (value !== '') { + onChangeDisplayItem(value, item.dispOrder, index, true) + } + } + }) + setCableDbItem(value) + } + // 아이템 자동완성 검색시 아이템 추가/변경시 const onChangeDisplayItem = (itemId, dispOrder, index, flag) => { const param = { @@ -1088,15 +1101,20 @@ export default function Estimate({}) { item.showSaleTotPrice = '0' } - if (item.dispCableFlg === '1' && item.itemTpCd !== 'M12') { + if (item.dispCableFlg === '1' ) { dispCableFlgCnt++ - setCableItem(item.itemId) + if(item.itemTpCd === 'M12') { + setCableDbItem(item.itemId) + }else{ + setCableItem(item.itemId) + } } } }) if (dispCableFlgCnt === 0) { setCableItem('100038') + setCableDbItem('100037') } let pkgAsp = estimateContextState.pkgAsp ? Number(estimateContextState.pkgAsp.replaceAll(',', '')) : 0 @@ -1159,14 +1177,20 @@ export default function Estimate({}) { dispCableFlgCnt++ } - if (item.dispCableFlg === '1' && item.itemTpCd !== 'M12') { - setCableItem(item.itemId) + if (item.dispCableFlg === '1'){ + + if(item.itemTpCd === 'M12') { + setCableDbItem(item.itemId) + }else{ + setCableItem(item.itemId) + } } } }) if (dispCableFlgCnt === 0) { setCableItem('100038') + setCableDbItem('100037') } totals.vatPrice = totals.supplyPrice * 0.1 @@ -1227,6 +1251,7 @@ export default function Estimate({}) { if (dispCableFlgCnt === 0) { setCableItem('100038') + setCableDbItem('100037') } } }, [estimateContextState?.itemList, cableItemList]) @@ -1831,6 +1856,7 @@ export default function Estimate({}) {
+
{getMessage('estimate.detail.header.singleCable')}
+
+
+
+
{getMessage('estimate.detail.header.doubleCable')}
+
+
@@ -1927,7 +1976,7 @@ export default function Estimate({}) { onChangeSelect(item.dispOrder)} checked={!!selection.has(item.dispOrder)} /> diff --git a/src/locales/ja.json b/src/locales/ja.json index 35f0b757..c59d0a16 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -944,6 +944,8 @@ "estimate.detail.sepcialEstimateProductInfo.pkgPrice": "PKG金額", "estimate.detail.header.showPrice": "価格表示", "estimate.detail.header.unitPrice": "定価", + "estimate.detail.header.singleCable": "片端ケーブル長さ", + "estimate.detail.header.doubleCable": "両端ケーブル長さ", "estimate.detail.showPrice.pricingBtn": "Pricing", "estimate.detail.showPrice.pricingBtn.noItemId": "Pricingが欠落しているアイテムがあります。 Pricingを進めてください。", "estimate.detail.showPrice.pricingBtn.confirm": "価格登録初期化されますがよろしいですか?", diff --git a/src/locales/ko.json b/src/locales/ko.json index daf9ad60..3374c1b9 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -945,6 +945,8 @@ "estimate.detail.sepcialEstimateProductInfo.pkgPrice": "PKG 금액", "estimate.detail.header.showPrice": "가격표시", "estimate.detail.header.unitPrice": "정가", + "estimate.detail.header.singleCable": "편당케이블 길이", + "estimate.detail.header.doubleCable": "양단케이블 길이", "estimate.detail.showPrice.pricingBtn": "Pricing", "estimate.detail.showPrice.pricingBtn.noItemId": "Pricing이 누락된 아이템이 있습니다. 제품 선택 후 Pricing을 진행해주세요.", "estimate.detail.showPrice.pricingBtn.confirm": "가격등록을 초기화 하시겠습니까?", From 80bf9263fdd5f2ae85eee3a86163ba0399bac9ea Mon Sep 17 00:00:00 2001 From: ysCha Date: Wed, 14 May 2025 15:16:28 +0900 Subject: [PATCH 23/33] =?UTF-8?q?=3F=3F=20=3D>=20=3F=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/locales/ja.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/locales/ja.json b/src/locales/ja.json index c59d0a16..57953508 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -346,9 +346,9 @@ "modal.actual.size.setting.not.exist.size": "実際の寸法の長さを入力してください", "modal.actual.size.setting.plane.size.length": "廊下寸法の長さ", "modal.actual.size.setting.actual.size.length": "実寸長", - "plan.message.confirm.save": "プラン保存しますか??", - "plan.message.confirm.copy": "プランコピーしますか??", - "plan.message.confirm.delete": "プラン削除しますか??", + "plan.message.confirm.save": "プラン保存しますか?", + "plan.message.confirm.copy": "プランコピーしますか?", + "plan.message.confirm.delete": "プラン削除しますか?", "plan.message.save": "保存されました。", "plan.message.delete": "削除されました。", "plan.message.leave": "物件状況(リスト)に移動しますか? [はい]を選択した場合は保存して移動します。", From 9609cad8f55fe5da7911ecaa74373337b30f4eda Mon Sep 17 00:00:00 2001 From: ysCha Date: Wed, 14 May 2025 15:18:50 +0900 Subject: [PATCH 24/33] =?UTF-8?q?=3F=3F=20=3D>=20=3F=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-on: https://git.hanasys.jp/qcast3/qcast-front/pulls/38 --- src/locales/ja.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/locales/ja.json b/src/locales/ja.json index c59d0a16..57953508 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -346,9 +346,9 @@ "modal.actual.size.setting.not.exist.size": "実際の寸法の長さを入力してください", "modal.actual.size.setting.plane.size.length": "廊下寸法の長さ", "modal.actual.size.setting.actual.size.length": "実寸長", - "plan.message.confirm.save": "プラン保存しますか??", - "plan.message.confirm.copy": "プランコピーしますか??", - "plan.message.confirm.delete": "プラン削除しますか??", + "plan.message.confirm.save": "プラン保存しますか?", + "plan.message.confirm.copy": "プランコピーしますか?", + "plan.message.confirm.delete": "プラン削除しますか?", "plan.message.save": "保存されました。", "plan.message.delete": "削除されました。", "plan.message.leave": "物件状況(リスト)に移動しますか? [はい]を選択した場合は保存して移動します。", From e6da798e4300a6e9c3b4f1d351de4243e89efa2c Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Thu, 15 May 2025 14:13:06 +0900 Subject: [PATCH 25/33] fix: update API server path in development environment to use secure HTTPS URL --- .env.development | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.development b/.env.development index d3e1ba88..f35f6208 100644 --- a/.env.development +++ b/.env.development @@ -1,4 +1,4 @@ -NEXT_PUBLIC_API_SERVER_PATH="http://1.248.227.176:38080" +NEXT_PUBLIC_API_SERVER_PATH="https://dev-api.hanasys.jp" NEXT_PUBLIC_HOST_URL="//1.248.227.176:4000" From b5b2ac21047272197b507772393426038c4a8b1e Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 16 May 2025 10:09:22 +0900 Subject: [PATCH 26/33] =?UTF-8?q?=EB=B3=B4=EC=A1=B0=EC=84=A0=20,=20?= =?UTF-8?q?=EC=A7=80=EB=B6=95=EC=84=A0=20=EB=A7=8C=EB=82=98=EB=8A=94=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=20=EC=A7=80=EB=B6=95=EC=84=A0=EB=B6=80?= =?UTF-8?q?=ED=84=B0=20=EC=9E=91=EC=97=85=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/roofcover/useAuxiliaryDrawing.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hooks/roofcover/useAuxiliaryDrawing.js b/src/hooks/roofcover/useAuxiliaryDrawing.js index 78d0b883..c854ae77 100644 --- a/src/hooks/roofcover/useAuxiliaryDrawing.js +++ b/src/hooks/roofcover/useAuxiliaryDrawing.js @@ -704,6 +704,7 @@ export function useAuxiliaryDrawing(id, isUseEffect = true) { removeLine(line1) } intersectionPoints.current.push(interSectionPointsWithRoofLines[0]) + return } } From 59a55e4c881cc87d7f3d2d0ae8abd0aa16a62e95 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 16 May 2025 10:31:23 +0900 Subject: [PATCH 27/33] =?UTF-8?q?961=20:=20=EC=99=B8=EB=B2=BD=EC=84=A0=20?= =?UTF-8?q?=EA=B7=B8=EB=A6=AC=EA=B8=B0=20=EB=B0=8F=20=EB=B0=B0=EC=B9=98?= =?UTF-8?q?=EB=A9=B4=20=EA=B7=B8=EB=A6=AC=EA=B8=B0=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=B4=EC=84=9C=E3=80=80=E5=A4=96=E5=A3=81=E7=B7=9A=E3=82=92?= =?UTF-8?q?=E6=8F=8F=E3=81=8F=E3=83=BB=E9=85=8D=E7=BD=AE=E9=9D=A2=E3=81=AE?= =?UTF-8?q?=E6=8F=8F=E7=94=BB=E3=81=AB=E3=81=A4=E3=81=84=E3=81=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. "외벽선 그리기", "배치면 그리기"에서 선을 그을때 우클릭으로 "undo" 할 수 있도록 해주세요. 2. 마찬가지로 "외벽선 그리기", "배치면 그리기"로 지붕면을 확정할 때 Enter Key로 지붕면을 확정할 수 있도록 해주시기 바랍니다. --- src/hooks/roofcover/useOuterLineWall.js | 7 +++++++ src/hooks/surface/usePlacementShapeDrawing.js | 19 ++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/hooks/roofcover/useOuterLineWall.js b/src/hooks/roofcover/useOuterLineWall.js index 18a07cf8..9ca76ea5 100644 --- a/src/hooks/roofcover/useOuterLineWall.js +++ b/src/hooks/roofcover/useOuterLineWall.js @@ -96,6 +96,10 @@ export function useOuterLineWall(id, propertiesId) { } addCanvasMouseEventListener('mouse:down', mouseDown) + addDocumentEventListener('contextmenu', document, (e) => { + handleRollback() + }) + clear() return () => { initEvent() @@ -690,6 +694,9 @@ export function useOuterLineWall(id, propertiesId) { if (points.length === 0) { return } + if (e.key === 'Enter') { + handleFix() + } // 포커스가 length1에 있지 않으면 length1에 포커스를 줌 const activeElem = document.activeElement if (activeElem !== length1Ref.current) { diff --git a/src/hooks/surface/usePlacementShapeDrawing.js b/src/hooks/surface/usePlacementShapeDrawing.js index d53faa39..be23cd7c 100644 --- a/src/hooks/surface/usePlacementShapeDrawing.js +++ b/src/hooks/surface/usePlacementShapeDrawing.js @@ -92,6 +92,9 @@ export function usePlacementShapeDrawing(id) { } addCanvasMouseEventListener('mouse:down', mouseDown) + addDocumentEventListener('contextmenu', document, (e) => { + handleRollback() + }) clear() }, [verticalHorizontalMode, points, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, interval, tempGridMode]) @@ -175,7 +178,7 @@ export function usePlacementShapeDrawing(id) { } } -/* + /* mouseMove */ const roofs = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) @@ -184,7 +187,7 @@ mouseMove const { getAdsorptionPoints } = useAdsorptionPoint() const mouseMove = (e) => { - removeMouseLine(); + removeMouseLine() const pointer = canvas.getPointer(e.e) const roofsPoints = roofs.map((roof) => roof.points).flat() roofAdsorptionPoints.current = [...roofsPoints] @@ -246,7 +249,6 @@ mouseMove }) canvas?.add(horizontalLine, verticalLine) canvas?.renderAll() - } useEffect(() => { @@ -768,6 +770,7 @@ mouseMove if (points.length === 0) { return } + enterCheck(e) // 포커스가 length1에 있지 않으면 length1에 포커스를 줌 const activeElem = document.activeElement @@ -833,6 +836,7 @@ mouseMove if (points.length === 0) { return } + enterCheck(e) const key = e.key const activeElem = document.activeElement @@ -866,6 +870,7 @@ mouseMove if (points.length === 0) { return } + enterCheck(e) const key = e.key switch (key) { case 'Down': // IE/Edge에서 사용되는 값 @@ -891,6 +896,7 @@ mouseMove if (points.length === 0) { return } + enterCheck(e) const key = e.key switch (key) { case 'Enter': { @@ -915,6 +921,7 @@ mouseMove if (points.length === 0) { return } + enterCheck(e) const key = e.key switch (key) { @@ -979,6 +986,12 @@ mouseMove isFix.current = true } + const enterCheck = (e) => { + if (e.key === 'Enter') { + handleFix() + } + } + return { points, setPoints, From 46f9385163be4096114cf7892bfe10c14c3068d8 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 16 May 2025 10:37:30 +0900 Subject: [PATCH 28/33] =?UTF-8?q?enterCheck=20=EC=A0=84=EB=B6=80=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/roofcover/useOuterLineWall.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/hooks/roofcover/useOuterLineWall.js b/src/hooks/roofcover/useOuterLineWall.js index 9ca76ea5..302a4c9a 100644 --- a/src/hooks/roofcover/useOuterLineWall.js +++ b/src/hooks/roofcover/useOuterLineWall.js @@ -694,9 +694,7 @@ export function useOuterLineWall(id, propertiesId) { if (points.length === 0) { return } - if (e.key === 'Enter') { - handleFix() - } + enterCheck(e) // 포커스가 length1에 있지 않으면 length1에 포커스를 줌 const activeElem = document.activeElement if (activeElem !== length1Ref.current) { @@ -761,6 +759,7 @@ export function useOuterLineWall(id, propertiesId) { if (points.length === 0) { return } + enterCheck(e) const key = e.key const activeElem = document.activeElement @@ -794,6 +793,7 @@ export function useOuterLineWall(id, propertiesId) { if (points.length === 0) { return } + enterCheck(e) const key = e.key switch (key) { case 'Down': // IE/Edge에서 사용되는 값 @@ -819,6 +819,7 @@ export function useOuterLineWall(id, propertiesId) { if (points.length === 0) { return } + enterCheck(e) const key = e.key switch (key) { case 'Enter': { @@ -843,7 +844,7 @@ export function useOuterLineWall(id, propertiesId) { if (points.length === 0) { return } - + enterCheck(e) const key = e.key switch (key) { case 'Down': // IE/Edge에서 사용되는 값 @@ -909,6 +910,12 @@ export function useOuterLineWall(id, propertiesId) { isFix.current = true } + const enterCheck = (e) => { + if (e.key === 'Enter') { + handleFix() + } + } + return { points, setPoints, From 79e33880acdeab9ca990da531516eef4e5d7e7fb Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 16 May 2025 14:39:11 +0900 Subject: [PATCH 29/33] =?UTF-8?q?direction=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=8B=9C=20default=EA=B0=92=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/usePolygon.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js index 577274ad..91562948 100644 --- a/src/hooks/usePolygon.js +++ b/src/hooks/usePolygon.js @@ -1127,6 +1127,9 @@ export const usePolygon = () => { case 'left': defense = 'north' break + default: + defense = 'south' + break } pitch = polygon.lines[index]?.attributes?.pitch ?? 0 From 97d20321ed0ed9df6719e98e56ec0d0e4ad40f9b Mon Sep 17 00:00:00 2001 From: yjnoh Date: Mon, 19 May 2025 10:29:49 +0900 Subject: [PATCH 30/33] =?UTF-8?q?[1049]=20:=20[=E6=96=87=E5=AD=97=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [작업내용] : 번역 작업 진행 --- src/locales/ja.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/locales/ja.json b/src/locales/ja.json index 57953508..6eef1edc 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -125,9 +125,9 @@ "modal.module.basic.settting.module.error6": "垂木の間隔を入力してください。\n(屋根材: {0})", "modal.module.basic.settting.module.error7": "下在ビーチを入力してください。\n(屋根材: {0})", "modal.module.basic.settting.module.error8": "モジュール配置領域の値を入力してください。\n(屋根材: {0})", - "modal.module.basic.settting.module.error9": "軒側の値は{0} mm以上でなければなりません。\n(屋根材: {1})", - "modal.module.basic.settting.module.error10": "吊下側の値は{0} mm以上でなければなりません。\n(屋根材: {1})", - "modal.module.basic.settting.module.error11": "ケラバ側の値は{0} mm以上でなければなりません。\n(屋根材: {1})", + "modal.module.basic.settting.module.error9": "軒側の配置領域の値を{0} mm以上に変更してください。\n(屋根材: {1})", + "modal.module.basic.settting.module.error10": "棟側の配置領域の値を{0} mm上に変更してください。\n(屋根材: {1})", + "modal.module.basic.settting.module.error11": "ケラバ側の配置領域の値を{0} mm上に変更してください。\n(屋根材: {1})", "modal.module.basic.settting.module.error12": "施工方法を選択してください。\n(屋根材: {0})", "modal.module.basic.setting.module.placement": "モジュールの配置", "modal.module.basic.setting.module.placement.select.fitting.type": "設置形態を選択してください。", @@ -786,7 +786,7 @@ "stuff.search.schObjectNo": "物件番号", "stuff.search.schSaleStoreName": "販売代理店名", "stuff.search.schAddress": "商品アドレス", - "stuff.search.schObjectName": "商品名", + "stuff.search.schObjectName": "物件名", "stuff.search.schDispCompanyName": "見積先", "stuff.search.schSelSaleStoreId": "販売代理店選択", "stuff.search.schReceiveUser": "担当者", From 98f87553e6f8dd598b55fb750e006390be51bb52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Mon, 19 May 2025 10:30:15 +0900 Subject: [PATCH 31/33] =?UTF-8?q?[1049]=20:=20[=E3=80=90HANASYS=20DESIGN?= =?UTF-8?q?=E3=80=91=E6=96=87=E5=AD=97=E4=BF=AE=E6=AD=A3]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [작업내용] : 일본어 번역 수정 --- src/locales/ja.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/locales/ja.json b/src/locales/ja.json index e866e95e..b4b66991 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -125,9 +125,9 @@ "modal.module.basic.settting.module.error6": "垂木の間隔を入力してください。\n(屋根材: {0})", "modal.module.basic.settting.module.error7": "下在ビーチを入力してください。\n(屋根材: {0})", "modal.module.basic.settting.module.error8": "モジュール配置領域の値を入力してください。\n(屋根材: {0})", - "modal.module.basic.settting.module.error9": "軒側の値は{0} mm以上でなければなりません。\n(屋根材: {1})", - "modal.module.basic.settting.module.error10": "吊下側の値は{0} mm以上でなければなりません。\n(屋根材: {1})", - "modal.module.basic.settting.module.error11": "ケラバ側の値は{0} mm以上でなければなりません。\n(屋根材: {1})", + "modal.module.basic.settting.module.error9": "軒側の配置領域の値を{0} mm以上に変更してください。\n(屋根材: {1})", + "modal.module.basic.settting.module.error10": "棟側の配置領域の値を{0} mm以上に変更してください。\n(屋根材: {1})", + "modal.module.basic.settting.module.error11": "ケラバ側の配置領域の値を{0} mm以上に変更してください。\n(屋根材: {1})", "modal.module.basic.settting.module.error12": "施工方法を選択してください。\n(屋根材: {0})", "modal.module.basic.setting.module.placement": "モジュールの配置", "modal.module.basic.setting.module.placement.select.fitting.type": "設置形態を選択してください。", @@ -785,7 +785,7 @@ "stuff.search.schObjectNo": "物件番号", "stuff.search.schSaleStoreName": "販売代理店名", "stuff.search.schAddress": "商品アドレス", - "stuff.search.schObjectName": "商品名", + "stuff.search.schObjectName": "物件名", "stuff.search.schDispCompanyName": "見積先", "stuff.search.schSelSaleStoreId": "販売代理店選択", "stuff.search.schReceiveUser": "担当者", From e482538dec5b1a18f92bd31fff9b19317a222224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Mon, 19 May 2025 13:50:39 +0900 Subject: [PATCH 32/33] =?UTF-8?q?[995]=20:=20[=E3=80=90HANASYS=20DESIGN?= =?UTF-8?q?=E3=80=91=E5=9B=9E=E8=B7=AF=E7=B5=84=E3=81=AB=E3=81=A4=E3=81=84?= =?UTF-8?q?=E3=81=A6]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [작업내용] : 수동 회로 할당 시 동일면/경사인 지붕면 일 경우 불가하게 수정 및 관련 다국어 메시지 추가 --- .../step/type/PassivityCircuitAllocation.jsx | 20 +++++++++++++++++++ src/locales/ja.json | 1 + src/locales/ko.json | 1 + 3 files changed, 22 insertions(+) diff --git a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx index 4a4d72a2..281ae5a8 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx @@ -86,6 +86,26 @@ export default function PassivityCircuitAllocation(props) { .map((obj) => obj.circuitNumber), ), ] + + const surfaceList = targetModules.map((module) => { + return canvas.getObjects().filter((obj) => obj.id === canvas.getObjects().filter((obj) => obj.id === module)[0].surfaceId)[0] + }) + + if (surfaceList.length > 1) { + let surfaceType = {} + + surfaceList.forEach((surface) => { + surfaceType[`${surface.direction}-${surface.roofMaterial.pitch}`] = surface + }) + if (Object.keys(surfaceType).length > 1) { + swalFire({ + text: getMessage('module.circuit.fix.not.same.roof.error'), + type: 'alert', + icon: 'warning', + }) + return + } + } if (!circuitNumber || circuitNumber === 0) { swalFire({ text: getMessage('module.circuit.minimun.error'), diff --git a/src/locales/ja.json b/src/locales/ja.json index e4804401..4e0114ab 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -1050,6 +1050,7 @@ "batch.canvas.delete.all": "配置面の内容をすべて削除しますか?", "module.not.found": "インストールモジュールを選択してください。", "module.circuit.minimun.error": "回路番号は1以上の数値を入力してください。", + "module.circuit.fix.not.same.roof.error": "異なる屋根面のモジュールが選択されています。 モジュールの選択をや直してください。", "module.already.exist.error": "回路番号が同じで異なるパワーコンディショナのモジュールがあります。 別の回路番号を設定してください。", "construction.length.difference": "屋根面工法をすべて選択してください。", "menu.validation.canvas.roof": "パネルを配置するには、屋根面を入力する必要があります。", diff --git a/src/locales/ko.json b/src/locales/ko.json index 3374c1b9..e7ab9711 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -1052,6 +1052,7 @@ "module.not.found": "모듈을 선택하세요.", "module.circuit.minimun.error": "회로번호는 1 이상입력해주세요.", "module.already.exist.error": "회로번호가 같은 다른 파워 컨디셔너 모듈이 있습니다. 다른 회로번호를 설정하십시오.", + "module.circuit.fix.not.same.roof.error": "다른 지붕면의 모듈이 선택되어 있습니다. 모듈 선택을 다시 하세요.", "construction.length.difference": "지붕면 공법을 모두 선택하십시오.", "menu.validation.canvas.roof": "패널을 배치하려면 지붕면을 입력해야 합니다.", "batch.object.outside.roof": "오브젝트는 지붕내에 설치해야 합니다.", From 70a4c85149ea14457613cb02213a0cf1eafc97a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Mon, 19 May 2025 13:57:34 +0900 Subject: [PATCH 33/33] =?UTF-8?q?[1049]=20:=20[=E3=80=90HANASYS=20DESIGN?= =?UTF-8?q?=E3=80=91=E6=96=87=E5=AD=97=E4=BF=AE=E6=AD=A3]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [작업내용] : 다국어 수정 --- src/locales/ja.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/locales/ja.json b/src/locales/ja.json index 3fe4da71..7593b6b6 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -786,7 +786,7 @@ "stuff.search.schObjectNo": "物件番号", "stuff.search.schSaleStoreName": "販売代理店名", "stuff.search.schAddress": "商品アドレス", - "stuff.search.schObjectName": "商品名", + "stuff.search.schObjectName": "物件名", "stuff.search.schDispCompanyName": "見積先", "stuff.search.schSelSaleStoreId": "販売代理店選択", "stuff.search.schReceiveUser": "担当者", @@ -1050,7 +1050,6 @@ "batch.canvas.delete.all": "配置面の内容をすべて削除しますか?", "module.not.found": "インストールモジュールを選択してください。", "module.circuit.minimun.error": "回路番号は1以上の数値を入力してください。", - "module.circuit.fix.not.same.roof.error": "異なる屋根面のモジュールが選択されています。 モジュールの選択をや直してください。", "module.already.exist.error": "回路番号が同じで異なるパワーコンディショナのモジュールがあります。 別の回路番号を設定してください。", "construction.length.difference": "屋根面工法をすべて選択してください。", "menu.validation.canvas.roof": "パネルを配置するには、屋根面を入力する必要があります。",