Merge branch 'dev' of https://git.hanasys.jp/qcast3/qcast-front into dev
This commit is contained in:
commit
0430be1945
@ -1,8 +1,10 @@
|
|||||||
|
NEXT_PUBLIC_RUN_MODE="development"
|
||||||
|
|
||||||
NEXT_PUBLIC_API_SERVER_PATH="https://dev-api.hanasys.jp"
|
NEXT_PUBLIC_API_SERVER_PATH="https://dev-api.hanasys.jp"
|
||||||
|
|
||||||
NEXT_PUBLIC_HOST_URL="//1.248.227.176:4000"
|
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="https://dev.hanasys.jp"
|
||||||
|
|
||||||
SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y="
|
SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y="
|
||||||
|
|
||||||
@ -25,4 +27,6 @@ AWS_REGION="ap-northeast-1"
|
|||||||
AMPLIFY_BUCKET="files.hanasys.jp"
|
AMPLIFY_BUCKET="files.hanasys.jp"
|
||||||
AWS_ACCESS_KEY_ID="AKIA3K4QWLZHFZRJOM2E"
|
AWS_ACCESS_KEY_ID="AKIA3K4QWLZHFZRJOM2E"
|
||||||
AWS_SECRET_ACCESS_KEY="Cw87TjKwnTWRKgORGxYiFU6GUTgu25eUw4eLBNcA"
|
AWS_SECRET_ACCESS_KEY="Cw87TjKwnTWRKgORGxYiFU6GUTgu25eUw4eLBNcA"
|
||||||
NEXT_PUBLIC_AWS_S3_BASE_URL="//files.hanasys.jp"
|
NEXT_PUBLIC_AWS_S3_BASE_URL="//files.hanasys.jp"
|
||||||
|
|
||||||
|
S3_PROFILE="dev"
|
||||||
32
.env.local.dev
Normal file
32
.env.local.dev
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
NEXT_PUBLIC_RUN_MODE="local.dev"
|
||||||
|
|
||||||
|
NEXT_PUBLIC_API_SERVER_PATH="https://dev-api.hanasys.jp"
|
||||||
|
|
||||||
|
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"
|
||||||
|
# NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_yAS4QDalL9jgQ7vS"
|
||||||
|
NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_a0FLEK6M2oTpXInK"
|
||||||
|
|
||||||
|
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="NDzSvPUo4/ErpPOEs1eZAnoUBilc1FL7YaoHkqe4"
|
||||||
|
# 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="Cw87TjKwnTWRKgORGxYiFU6GUTgu25eUw4eLBNcA"
|
||||||
|
NEXT_PUBLIC_AWS_S3_BASE_URL="//files.hanasys.jp"
|
||||||
|
|
||||||
|
S3_PROFILE="dev"
|
||||||
32
.env.localhost
Normal file
32
.env.localhost
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
NEXT_PUBLIC_RUN_MODE="local"
|
||||||
|
|
||||||
|
NEXT_PUBLIC_API_SERVER_PATH="https://dev-api.hanasys.jp"
|
||||||
|
|
||||||
|
NEXT_PUBLIC_HOST_URL="//1.248.227.176:4000"
|
||||||
|
|
||||||
|
NEXT_PUBLIC_API_HOST_URL="http://localhost:3000"
|
||||||
|
|
||||||
|
SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y="
|
||||||
|
|
||||||
|
# NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3"
|
||||||
|
# NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_yAS4QDalL9jgQ7vS"
|
||||||
|
NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_a0FLEK6M2oTpXInK"
|
||||||
|
|
||||||
|
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="NDzSvPUo4/ErpPOEs1eZAnoUBilc1FL7YaoHkqe4"
|
||||||
|
# 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="Cw87TjKwnTWRKgORGxYiFU6GUTgu25eUw4eLBNcA"
|
||||||
|
NEXT_PUBLIC_AWS_S3_BASE_URL="//files.hanasys.jp"
|
||||||
|
|
||||||
|
S3_PROFILE="dev"
|
||||||
@ -1,8 +1,10 @@
|
|||||||
|
NEXT_PUBLIC_RUN_MODE="production"
|
||||||
|
|
||||||
NEXT_PUBLIC_API_SERVER_PATH="https://api.hanasys.jp/"
|
NEXT_PUBLIC_API_SERVER_PATH="https://api.hanasys.jp/"
|
||||||
|
|
||||||
NEXT_PUBLIC_HOST_URL="//1.248.227.176:4000"
|
NEXT_PUBLIC_HOST_URL="//1.248.227.176:4000"
|
||||||
|
|
||||||
NEXT_PUBLIC_API_HOST_URL="https://www.hanasys.jp/"
|
NEXT_PUBLIC_API_HOST_URL="https://www.hanasys.jp"
|
||||||
|
|
||||||
SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y="
|
SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y="
|
||||||
|
|
||||||
@ -15,8 +17,17 @@ 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_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"
|
NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-stg.q-cells.jp:8120/qm/login/autoLogin"
|
||||||
|
|
||||||
AWS_REGION="ap-northeast-2"
|
# AWS_REGION="ap-northeast-2"
|
||||||
AMPLIFY_BUCKET="interplug"
|
# AMPLIFY_BUCKET="interplug"
|
||||||
AWS_ACCESS_KEY_ID="AKIAVWMWJCUXFHEAZ4FR"
|
# AWS_ACCESS_KEY_ID="AKIAVWMWJCUXFHEAZ4FR"
|
||||||
AWS_SECRET_ACCESS_KEY="NDzSvPUo4/ErpPOEs1eZAnoUBilc1FL7YaoHkqe4"
|
# AWS_SECRET_ACCESS_KEY="NDzSvPUo4/ErpPOEs1eZAnoUBilc1FL7YaoHkqe4"
|
||||||
NEXT_PUBLIC_AWS_S3_BASE_URL="//files.hanasys.jp"
|
# NEXT_PUBLIC_AWS_S3_BASE_URL="//files.hanasys.jp"
|
||||||
|
|
||||||
|
# 실제 일본 서버
|
||||||
|
AWS_REGION="ap-northeast-1"
|
||||||
|
AMPLIFY_BUCKET="files.hanasys.jp"
|
||||||
|
AWS_ACCESS_KEY_ID="AKIA3K4QWLZHFZRJOM2E"
|
||||||
|
AWS_SECRET_ACCESS_KEY="Cw87TjKwnTWRKgORGxYiFU6GUTgu25eUw4eLBNcA"
|
||||||
|
NEXT_PUBLIC_AWS_S3_BASE_URL="//files.hanasys.jp"
|
||||||
|
|
||||||
|
S3_PROFILE="prd"
|
||||||
@ -6,7 +6,7 @@ module.exports = {
|
|||||||
instances: 1,
|
instances: 1,
|
||||||
exec_mode: 'fork',
|
exec_mode: 'fork',
|
||||||
env: {
|
env: {
|
||||||
NODE_ENV: 'development',
|
PORT: 5010,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
13
dev.local.ecosystem.config.js
Normal file
13
dev.local.ecosystem.config.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module.exports = {
|
||||||
|
apps: [
|
||||||
|
{
|
||||||
|
name: 'qcast-front-local-development',
|
||||||
|
script: 'node_modules/next/dist/bin/next',
|
||||||
|
instances: 1,
|
||||||
|
exec_mode: 'fork',
|
||||||
|
env: {
|
||||||
|
PORT: 5000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
15
package.json
15
package.json
@ -3,11 +3,14 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "env-cmd -f .env.localhost next dev",
|
||||||
"build": "next build",
|
"local:dev": "env-cmd -f .env.local.dev next dev",
|
||||||
"start:cluster1": "next start -p 5000",
|
"build": "env-cmd -f .env.production next build",
|
||||||
"start:cluster2": "next start -p 5001",
|
"build:dev": "env-cmd -f .env.development next build",
|
||||||
"start:dev": "next start -p 5010",
|
"build:local.dev": "env-cmd -f .env.local.dev next build",
|
||||||
|
"start:cluster1": "env-cmd -f .env.production next start -p 5000",
|
||||||
|
"start:cluster2": "env-cmd -f .env.production next start -p 5001",
|
||||||
|
"start:dev": "env-cmd -f .env.development next start -p 5010",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"serve": "node server.js"
|
"serve": "node server.js"
|
||||||
},
|
},
|
||||||
@ -18,10 +21,12 @@
|
|||||||
"big.js": "^6.2.2",
|
"big.js": "^6.2.2",
|
||||||
"chart.js": "^4.4.6",
|
"chart.js": "^4.4.6",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
|
"env-cmd": "^10.1.0",
|
||||||
"fabric": "^5.3.0",
|
"fabric": "^5.3.0",
|
||||||
"framer-motion": "^11.2.13",
|
"framer-motion": "^11.2.13",
|
||||||
"fs": "^0.0.1-security",
|
"fs": "^0.0.1-security",
|
||||||
"iron-session": "^8.0.2",
|
"iron-session": "^8.0.2",
|
||||||
|
"jimp": "^1.6.0",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"mathjs": "^13.0.2",
|
"mathjs": "^13.0.2",
|
||||||
"mssql": "^11.0.1",
|
"mssql": "^11.0.1",
|
||||||
|
|||||||
13
prd1.ecosystem.config.js
Normal file
13
prd1.ecosystem.config.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module.exports = {
|
||||||
|
apps: [
|
||||||
|
{
|
||||||
|
name: 'qcast-front-production-1',
|
||||||
|
script: 'node_modules/next/dist/bin/next',
|
||||||
|
instances: 1,
|
||||||
|
exec_mode: 'fork',
|
||||||
|
env: {
|
||||||
|
PORT: 5000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
13
prd2.ecosystem.config.js
Normal file
13
prd2.ecosystem.config.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module.exports = {
|
||||||
|
apps: [
|
||||||
|
{
|
||||||
|
name: 'qcast-front-production-2',
|
||||||
|
script: 'node_modules/next/dist/bin/next',
|
||||||
|
instances: 1,
|
||||||
|
exec_mode: 'fork',
|
||||||
|
env: {
|
||||||
|
PORT: 5001,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
BIN
public/static/images/canvas/roof_warning_correct.png
Normal file
BIN
public/static/images/canvas/roof_warning_correct.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
public/static/images/canvas/roof_warning_wrong.png
Normal file
BIN
public/static/images/canvas/roof_warning_wrong.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
@ -11,9 +11,10 @@ const s3 = new S3Client({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const uploadImage = async (file) => {
|
const uploadImage = async (file) => {
|
||||||
|
console.log('🚀 ~ uploadImage ~ file:', file)
|
||||||
const Body = Buffer.from(await file.arrayBuffer())
|
const Body = Buffer.from(await file.arrayBuffer())
|
||||||
const Key = `cads/${file.name}`
|
const Key = `cads/${file.name}`
|
||||||
const ContentType = file.ContentType
|
const ContentType = 'image/png'
|
||||||
|
|
||||||
await s3.send(
|
await s3.send(
|
||||||
new PutObjectCommand({
|
new PutObjectCommand({
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import { NextResponse } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
import { S3Client, PutObjectCommand, DeleteObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3'
|
import { DeleteObjectCommand, GetObjectCommand, PutObjectCommand, S3Client } from '@aws-sdk/client-s3'
|
||||||
import sharp from 'sharp'
|
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
import { Jimp } from 'jimp'
|
||||||
|
|
||||||
const Bucket = process.env.AMPLIFY_BUCKET
|
const Bucket = process.env.AMPLIFY_BUCKET
|
||||||
const s3 = new S3Client({
|
const s3 = new S3Client({
|
||||||
region: process.env.AWS_REGION,
|
region: process.env.AWS_REGION,
|
||||||
@ -23,8 +24,6 @@ const checkArea = (obj) => {
|
|||||||
|
|
||||||
const cropImage = async (Key, width, height, left, top) => {
|
const cropImage = async (Key, width, height, left, top) => {
|
||||||
try {
|
try {
|
||||||
const checkResult = checkArea({ width, height, left, top })
|
|
||||||
|
|
||||||
// Get the image from S3
|
// Get the image from S3
|
||||||
const { Body } = await s3.send(
|
const { Body } = await s3.send(
|
||||||
new GetObjectCommand({
|
new GetObjectCommand({
|
||||||
@ -33,28 +32,45 @@ const cropImage = async (Key, width, height, left, top) => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Convert stream to buffer
|
|
||||||
const chunks = []
|
const chunks = []
|
||||||
for await (const chunk of Body) {
|
for await (const chunk of Body) {
|
||||||
chunks.push(chunk)
|
chunks.push(chunk)
|
||||||
}
|
}
|
||||||
const imageBuffer = Buffer.concat(chunks)
|
const buffer = Buffer.concat(chunks)
|
||||||
|
|
||||||
let processedImage
|
const image = await Jimp.read(buffer)
|
||||||
if (!checkResult) {
|
|
||||||
processedImage = await sharp(imageBuffer).toBuffer()
|
image.autocrop({ tolerance: 0.0002, leaveBorder: 10 })
|
||||||
} else {
|
return await image.getBuffer('image/png')
|
||||||
processedImage = await sharp(imageBuffer)
|
|
||||||
.extract({
|
// Convert stream to buffer
|
||||||
width: parseInt(width),
|
// const chunks = []
|
||||||
height: parseInt(height),
|
// for await (const chunk of Body) {
|
||||||
left: parseInt(left),
|
// chunks.push(chunk)
|
||||||
top: parseInt(top),
|
// }
|
||||||
})
|
// const imageBuffer = Buffer.concat(chunks)
|
||||||
.png()
|
|
||||||
.toBuffer()
|
// const image = await Jimp.read(Body)
|
||||||
}
|
|
||||||
return processedImage
|
// if (!checkResult) {
|
||||||
|
// processedImage = await image.toBuffer()
|
||||||
|
// }
|
||||||
|
|
||||||
|
//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) {
|
} catch (error) {
|
||||||
console.error('Error processing image:', error)
|
console.error('Error processing image:', error)
|
||||||
throw error
|
throw error
|
||||||
@ -96,7 +112,7 @@ export async function POST(req) {
|
|||||||
/**
|
/**
|
||||||
* 크롭 이미지 이름을 결정한다.
|
* 크롭 이미지 이름을 결정한다.
|
||||||
*/
|
*/
|
||||||
const Key = `Drawing/${objectNo}_${planNo}_${type}.png`
|
const Key = `Drawing/${process.env.S3_PROFILE}/${objectNo}_${planNo}_${type}.png`
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 크롭이 완료된 이미지를 업로드한다.
|
* 크롭이 완료된 이미지를 업로드한다.
|
||||||
|
|||||||
59
src/app/api/image/estimate-image-copy/route.js
Normal file
59
src/app/api/image/estimate-image-copy/route.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { NextResponse } from 'next/server'
|
||||||
|
import { S3Client, CopyObjectCommand, 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,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export async function POST(req) {
|
||||||
|
const { objectNo, planNo, newObjectNo, newPlanNo } = await req.json()
|
||||||
|
|
||||||
|
const responseArray = []
|
||||||
|
|
||||||
|
//견적서1 번 이미지
|
||||||
|
const isExistImage1 = await s3.send(
|
||||||
|
new GetObjectCommand({
|
||||||
|
Bucket,
|
||||||
|
Key: `Drawing/${process.env.S3_PROFILE}/${objectNo}_${planNo}_1.png`,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
//견적서2 번 이미지
|
||||||
|
const isExistImage2 = await s3.send(
|
||||||
|
new GetObjectCommand({
|
||||||
|
Bucket,
|
||||||
|
Key: `Drawing/${process.env.S3_PROFILE}/${objectNo}_${planNo}_2.png`,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
//견적서1,2 번 이미지 둘다 있어야함
|
||||||
|
if (isExistImage1.$metadata.httpStatusCode === 200 && isExistImage2.$metadata.httpStatusCode === 200) {
|
||||||
|
//견적서1 번 이미지 복사
|
||||||
|
const copyCommand = new CopyObjectCommand({
|
||||||
|
Bucket,
|
||||||
|
CopySource: encodeURI(`${Bucket}/Drawing/${process.env.S3_PROFILE}/${objectNo}_${planNo}_1.png`),
|
||||||
|
Key: `Drawing/${process.env.S3_PROFILE}/${newObjectNo}_${newPlanNo}_1.png`,
|
||||||
|
})
|
||||||
|
|
||||||
|
const response = await s3.send(copyCommand)
|
||||||
|
|
||||||
|
const copyCommand2 = new CopyObjectCommand({
|
||||||
|
Bucket,
|
||||||
|
CopySource: encodeURI(`${Bucket}/Drawing/${process.env.S3_PROFILE}/${objectNo}_${planNo}_2.png`),
|
||||||
|
Key: `Drawing/${process.env.S3_PROFILE}/${newObjectNo}_${newPlanNo}_2.png`,
|
||||||
|
})
|
||||||
|
|
||||||
|
const response2 = await s3.send(copyCommand2)
|
||||||
|
|
||||||
|
responseArray.push(response, response2)
|
||||||
|
return NextResponse.json({ message: '견적서 이미지 복사 성공', responseArray }, { status: 200 })
|
||||||
|
} else {
|
||||||
|
return NextResponse.json({ message: '견적서 이미지 복사 실패(존재하지 않는 이미지)', responseArray }, { status: 400 })
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -45,8 +45,19 @@ const FloorPlanProvider = ({ children }) => {
|
|||||||
// const pathname = usePathname()
|
// const pathname = usePathname()
|
||||||
// const setCorrentObjectNo = useSetRecoilState(correntObjectNoState)
|
// const setCorrentObjectNo = useSetRecoilState(correntObjectNoState)
|
||||||
const searchParams = useSearchParams()
|
const searchParams = useSearchParams()
|
||||||
|
const path = usePathname()
|
||||||
const objectNo = searchParams.get('objectNo')
|
const objectNo = searchParams.get('objectNo')
|
||||||
const pid = searchParams.get('pid')
|
const pid = searchParams.get('pid')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setFloorPlanState((prev) => {
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
objectNo,
|
||||||
|
pid,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [path])
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// console.log('🚀 ~ useEffect ~ objectNo:')
|
// console.log('🚀 ~ useEffect ~ objectNo:')
|
||||||
// if (pathname === '/floor-plan') {
|
// if (pathname === '/floor-plan') {
|
||||||
|
|||||||
@ -210,6 +210,7 @@ export const SAVE_KEY = [
|
|||||||
'toFixed',
|
'toFixed',
|
||||||
'startPoint',
|
'startPoint',
|
||||||
'endPoint',
|
'endPoint',
|
||||||
|
'editable',
|
||||||
'isSortedPoints',
|
'isSortedPoints',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import { sessionStore } from '@/store/commonAtom'
|
|||||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||||
|
|
||||||
import BoardDetailModal from './community/modal/BoardDetailModal'
|
import BoardDetailModal from './community/modal/BoardDetailModal'
|
||||||
|
import Config from '@/config/config.export'
|
||||||
|
|
||||||
export default function MainPage() {
|
export default function MainPage() {
|
||||||
const [sessionState, setSessionState] = useRecoilState(sessionStore)
|
const [sessionState, setSessionState] = useRecoilState(sessionStore)
|
||||||
|
|||||||
@ -195,9 +195,7 @@ export default function Qna() {
|
|||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={4} className="al-c">
|
<td className="al-c no-data" colSpan={5}>{getMessage('common.message.no.data')}</td>
|
||||||
{getMessage('common.message.no.data')}
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@ -73,7 +73,7 @@ export default function QnaDetailModal({ qnaNo, setOpen, qnaType }) {
|
|||||||
<dt>{getMessage('qna.detail.sub.fileList')}</dt>
|
<dt>{getMessage('qna.detail.sub.fileList')}</dt>
|
||||||
{boardDetail.listFile.map((boardFile) => (
|
{boardDetail.listFile.map((boardFile) => (
|
||||||
<dd key={boardFile.encodeFileNo}>
|
<dd key={boardFile.encodeFileNo}>
|
||||||
<button type="button" className="down" onClick={() => handleFileDown(boardFile.fileNo, 'N')}>
|
<button type="button" className="down" onClick={() => handleFileDown(boardFile.fileNo, 'NO')}>
|
||||||
{boardFile.srcFileNm}
|
{boardFile.srcFileNm}
|
||||||
</button>
|
</button>
|
||||||
</dd>
|
</dd>
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import { QcastContext } from '@/app/QcastProvider'
|
|||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
import { e } from 'mathjs'
|
import { e } from 'mathjs'
|
||||||
|
import { set } from 'react-hook-form'
|
||||||
|
|
||||||
|
|
||||||
export default function QnaRegModal({ setOpen, setReload, searchValue, selectPageBlock }) {
|
export default function QnaRegModal({ setOpen, setReload, searchValue, selectPageBlock }) {
|
||||||
@ -24,9 +25,11 @@ export default function QnaRegModal({ setOpen, setReload, searchValue, selectPag
|
|||||||
const [qnaData, setQnaData] = useState([])
|
const [qnaData, setQnaData] = useState([])
|
||||||
const [closeMdFlg, setCloseMdFlg] = useState(true)
|
const [closeMdFlg, setCloseMdFlg] = useState(true)
|
||||||
const [closeSmFlg, setCloseSmFlg] = useState(true)
|
const [closeSmFlg, setCloseSmFlg] = useState(true)
|
||||||
|
const [hideSmFlg, setHideSmFlg] = useState(false)
|
||||||
const qnaTypeLgCodeRef = useRef(null)
|
const qnaTypeLgCodeRef = useRef(null)
|
||||||
const qnaTypeMdCodeRef = useRef(null)
|
const qnaTypeMdCodeRef = useRef(null)
|
||||||
const qnaTypeSmCodeRef = useRef(null)
|
const qnaTypeSmCodeRef = useRef(null)
|
||||||
|
const qstMail = useRef(null);
|
||||||
const regUserNmRef = useRef(null)
|
const regUserNmRef = useRef(null)
|
||||||
const regUserTelNoRef = useRef(null)
|
const regUserTelNoRef = useRef(null)
|
||||||
const titleRef = useRef(null)
|
const titleRef = useRef(null)
|
||||||
@ -65,11 +68,12 @@ let fileCheck = false;
|
|||||||
const initQnaReg = async () => {
|
const initQnaReg = async () => {
|
||||||
|
|
||||||
|
|
||||||
|
qstMail.current.value = ''
|
||||||
regUserNmRef.current.value = ''
|
regUserNmRef.current.value = ''
|
||||||
regUserTelNoRef.current.value = ''
|
regUserTelNoRef.current.value = ''
|
||||||
qnaTypeLgCodeRef.current.setValue();
|
qnaTypeLgCodeRef.current.setValue();
|
||||||
qnaTypeMdCodeRef.current.setValue();
|
qnaTypeMdCodeRef.current.setValue();
|
||||||
qnaTypeSmCodeRef.current.setValue();
|
qnaTypeSmCodeRef.current?.setValue();
|
||||||
titleRef.current.value = ''
|
titleRef.current.value = ''
|
||||||
contentsRef.current.value = ''
|
contentsRef.current.value = ''
|
||||||
|
|
||||||
@ -110,7 +114,7 @@ let fileCheck = false;
|
|||||||
setQnaData({ ...qnaData, qnaClsLrgCd:e.clCode})
|
setQnaData({ ...qnaData, qnaClsLrgCd:e.clCode})
|
||||||
setCloseMdFlg(false)
|
setCloseMdFlg(false)
|
||||||
qnaTypeMdCodeRef.current.setValue();
|
qnaTypeMdCodeRef.current.setValue();
|
||||||
qnaTypeSmCodeRef.current.setValue();
|
qnaTypeSmCodeRef.current?.setValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -129,10 +133,20 @@ let fileCheck = false;
|
|||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
setQnaTypeSmCodeList(codeList)
|
|
||||||
|
|
||||||
setQnaData({ ...qnaData, qnaClsMidCd: e.clCode })
|
setQnaData({ ...qnaData, qnaClsMidCd: e.clCode })
|
||||||
setCloseSmFlg(false)
|
setCloseSmFlg(false)
|
||||||
qnaTypeSmCodeRef.current.setValue();
|
setQnaTypeSmCodeList(codeList)
|
||||||
|
qnaTypeSmCodeRef.current?.setValue();
|
||||||
|
|
||||||
|
if(codeList.length > 0) {
|
||||||
|
setHideSmFlg(false)
|
||||||
|
}else{
|
||||||
|
setHideSmFlg(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +162,7 @@ let fileCheck = false;
|
|||||||
if(!fileCheck) return;
|
if(!fileCheck) return;
|
||||||
|
|
||||||
fileUploadProps.uploadFiles.forEach((file) => {
|
fileUploadProps.uploadFiles.forEach((file) => {
|
||||||
console.log("file::::::::",file)
|
//console.log("file::::::::",file)
|
||||||
formData.push(file)
|
formData.push(file)
|
||||||
|
|
||||||
})
|
})
|
||||||
@ -156,6 +170,16 @@ let fileCheck = false;
|
|||||||
fileCheck = false;
|
fileCheck = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isValidEmail = (email) => {
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
return emailRegex.test(email);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isEmpty = (value) => {
|
||||||
|
return value === null || value === undefined || value.trim() === "";
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const handleQnaSubmit = async () => {
|
const handleQnaSubmit = async () => {
|
||||||
//필수 체크
|
//필수 체크
|
||||||
|
|
||||||
@ -164,13 +188,22 @@ let fileCheck = false;
|
|||||||
|
|
||||||
let regUserNm = qnaData?.regUserNm??'';
|
let regUserNm = qnaData?.regUserNm??'';
|
||||||
|
|
||||||
if (regUserNm.trim().length === 0) {
|
if (!isValidEmail(qnaData.qstMail)) {
|
||||||
|
qstMail.current.focus();
|
||||||
|
swalFire({
|
||||||
|
title: getMessage('qna.reg.alert.require.qstMail'),
|
||||||
|
icon: 'warning',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
regUserNmRef.current.value = '';
|
|
||||||
|
if (isEmpty(regUserNm)) {
|
||||||
|
regUserNmRef.current.value = '';
|
||||||
regUserNmRef.current.focus()
|
regUserNmRef.current.focus()
|
||||||
swalFire({
|
swalFire({
|
||||||
text: getMessage('qna.reg.alert.require.regUserNm'),
|
title: getMessage('qna.reg.alert.require.regUserNm'),
|
||||||
type: 'alert',
|
icon: 'warning',
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -178,35 +211,35 @@ let fileCheck = false;
|
|||||||
let qnaClsLrgCd = qnaData?.qnaClsLrgCd??'';
|
let qnaClsLrgCd = qnaData?.qnaClsLrgCd??'';
|
||||||
let qnaClsMidCd = qnaData?.qnaClsMidCd??'';
|
let qnaClsMidCd = qnaData?.qnaClsMidCd??'';
|
||||||
|
|
||||||
if (qnaClsLrgCd.trim().length === 0 || qnaClsMidCd.trim().length === 0 ) {
|
if (isEmpty(qnaClsLrgCd) || isEmpty(qnaClsMidCd) ) {
|
||||||
(qnaClsLrgCd.trim().length === 0)?qnaTypeLgCodeRef.current.focus():qnaTypeMdCodeRef.current.focus()
|
(isEmpty(qnaClsLrgCd))?qnaTypeLgCodeRef.current.focus():qnaTypeMdCodeRef.current.focus()
|
||||||
swalFire({
|
swalFire({
|
||||||
text: getMessage('qna.reg.alert.select.type'),
|
title: getMessage('qna.reg.alert.select.type'),
|
||||||
type: 'alert',
|
icon: 'warning',
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
let title = qnaData?.title??'';
|
let title = qnaData?.title??'';
|
||||||
|
|
||||||
if (title.trim().length === 0) {
|
if (isEmpty(title)) {
|
||||||
titleRef.current.value = '';
|
titleRef.current.value = '';
|
||||||
titleRef.current.focus()
|
titleRef.current.focus()
|
||||||
swalFire({
|
swalFire({
|
||||||
text: getMessage('qna.reg.alert.require.title'),
|
title: getMessage('qna.reg.alert.require.title'),
|
||||||
type: 'alert',
|
icon: 'warning',
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
//console.log("5::::",qnaData)
|
//console.log("5::::",qnaData)
|
||||||
let contents = qnaData?.contents??'';
|
let contents = qnaData?.contents??'';
|
||||||
|
|
||||||
if (contents.trim().length === 0) {
|
if (isEmpty(contents)) {
|
||||||
contentsRef.current.value = '';
|
contentsRef.current.value = '';
|
||||||
contentsRef.current.focus()
|
contentsRef.current.focus()
|
||||||
swalFire({
|
swalFire({
|
||||||
text: getMessage('qna.reg.alert.require.contents'),
|
title: getMessage('qna.reg.alert.require.contents'),
|
||||||
type: 'alert',
|
icon: 'warning',
|
||||||
})
|
})
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -310,7 +343,13 @@ let fileCheck = false;
|
|||||||
<th>{getMessage('qna.list.header.regNm')}</th>
|
<th>{getMessage('qna.list.header.regNm')}</th>
|
||||||
<td><input type="text" className="input-light" value={sessionState?.userNm || ''} readOnly /></td>
|
<td><input type="text" className="input-light" value={sessionState?.userNm || ''} readOnly /></td>
|
||||||
<th>E-Mail<span className="red">*</span></th>
|
<th>E-Mail<span className="red">*</span></th>
|
||||||
<td ><input type="text" className="input-light" value={sessionState?.email || ''} readOnly /></td>
|
<td ><input type="text" className="input-light" required
|
||||||
|
ref={qstMail}
|
||||||
|
value={qnaData?.qstMail || ''}
|
||||||
|
onChange={(e) => setQnaData({...qnaData, qstMail: e.target.value })}
|
||||||
|
onBlur={(e) => setQnaData({ ...qnaData, qstMail: e.target.value })} />
|
||||||
|
</td>
|
||||||
|
|
||||||
<th>{getMessage('qna.reg.header.regDt')}</th>
|
<th>{getMessage('qna.reg.header.regDt')}</th>
|
||||||
<td>{dayjs(new Date()).format('YYYY-MM-DD')}</td>
|
<td>{dayjs(new Date()).format('YYYY-MM-DD')}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -366,6 +405,7 @@ let fileCheck = false;
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="select-wrap" >
|
<div className="select-wrap" >
|
||||||
|
{!hideSmFlg && (
|
||||||
<Select name="" ref={qnaTypeSmCodeRef}
|
<Select name="" ref={qnaTypeSmCodeRef}
|
||||||
options={qnaTypeSmCodeList}
|
options={qnaTypeSmCodeList}
|
||||||
placeholder="Select"
|
placeholder="Select"
|
||||||
@ -374,8 +414,8 @@ let fileCheck = false;
|
|||||||
getOptionValue={(x) => x.clCode}
|
getOptionValue={(x) => x.clCode}
|
||||||
isClearable={false}
|
isClearable={false}
|
||||||
isSearchable={false}
|
isSearchable={false}
|
||||||
isDisabled={closeSmFlg}
|
isDisabled={closeSmFlg}
|
||||||
/>
|
/>)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-wrap mt5">
|
<div className="input-wrap mt5">
|
||||||
@ -401,8 +441,8 @@ let fileCheck = false;
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className="footer-btn-wrap">
|
<div className="footer-btn-wrap">
|
||||||
{isBtnDisable === false && <button className="btn-origin grey mr5" onClick={handleQnaSubmit}>{getMessage("qna.reg.header.save")}</button>}
|
{isBtnDisable === false && <button className="btn-origin navy mr5" onClick={handleQnaSubmit}>{getMessage("qna.reg.header.save")}</button>}
|
||||||
<button className="btn-origin navy" onClick={() => {
|
<button className="btn-origin grey" onClick={() => {
|
||||||
setOpen(false)
|
setOpen(false)
|
||||||
}}>{getMessage("board.sub.btn.close")}</button>
|
}}>{getMessage("board.sub.btn.close")}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -154,7 +154,7 @@ export default function Estimate({}) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// console.log('🚀 ~ Estimate ~ selectedPlan:', selectedPlan)
|
// console.log('🚀 ~ Estimate ~ selectedPlan:', selectedPlan)
|
||||||
if (selectedPlan) initEstimate(selectedPlan.planNo)
|
if (selectedPlan) initEstimate(selectedPlan?.planNo?? currentPid)
|
||||||
}, [selectedPlan])
|
}, [selectedPlan])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -1281,7 +1281,7 @@ export default function Estimate({}) {
|
|||||||
<div className="estimate-box">
|
<div className="estimate-box">
|
||||||
<div className="estimate-tit">{getMessage('estimate.detail.objectNo')}</div>
|
<div className="estimate-tit">{getMessage('estimate.detail.objectNo')}</div>
|
||||||
<div className="estimate-name">
|
<div className="estimate-name">
|
||||||
{currentObjectNo} (Plan No: {planNo})
|
{currentObjectNo} (Plan No: {currentPid})
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="estimate-box">
|
<div className="estimate-box">
|
||||||
|
|||||||
@ -76,8 +76,12 @@ export default function CanvasFrame() {
|
|||||||
}
|
}
|
||||||
initEvent()
|
initEvent()
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
setSelectedMenu(null)
|
||||||
}
|
}
|
||||||
Object.keys(currentCanvasPlan).length > 0 && canvas && handleModuleSelectionTotal()
|
Object.keys(currentCanvasPlan).length > 0 && canvas && handleModuleSelectionTotal()
|
||||||
|
} else {
|
||||||
|
setSelectedMenu(null)
|
||||||
}
|
}
|
||||||
gridInit()
|
gridInit()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { useContext, useEffect, useState } from 'react'
|
|||||||
|
|
||||||
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
|
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
|
||||||
|
|
||||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil'
|
||||||
|
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
|
||||||
@ -50,6 +50,7 @@ import JA from '@/locales/ja.json'
|
|||||||
import { QcastContext } from '@/app/QcastProvider'
|
import { QcastContext } from '@/app/QcastProvider'
|
||||||
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
||||||
import { usePolygon } from '@/hooks/usePolygon'
|
import { usePolygon } from '@/hooks/usePolygon'
|
||||||
|
import { useTrestle } from '@/hooks/module/useTrestle'
|
||||||
export default function CanvasMenu(props) {
|
export default function CanvasMenu(props) {
|
||||||
const { selectedMenu, setSelectedMenu } = props
|
const { selectedMenu, setSelectedMenu } = props
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
@ -67,6 +68,7 @@ export default function CanvasMenu(props) {
|
|||||||
const globalLocale = useRecoilValue(globalLocaleStore)
|
const globalLocale = useRecoilValue(globalLocaleStore)
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const { handleZoomClear, handleZoom } = useCanvasEvent()
|
const { handleZoomClear, handleZoom } = useCanvasEvent()
|
||||||
|
const { setAllModuleSurfaceIsComplete, isAllComplete } = useTrestle()
|
||||||
const { handleMenu } = useMenu()
|
const { handleMenu } = useMenu()
|
||||||
// const urlParams = useSearchParams()
|
// const urlParams = useSearchParams()
|
||||||
const { handleEstimateSubmit, fetchSetting, estimateContextState, setEstimateContextState } = useEstimateController()
|
const { handleEstimateSubmit, fetchSetting, estimateContextState, setEstimateContextState } = useEstimateController()
|
||||||
@ -96,7 +98,7 @@ export default function CanvasMenu(props) {
|
|||||||
const [lockButtonStyle, setLockButtonStyle] = useState('') //잠금 버튼
|
const [lockButtonStyle, setLockButtonStyle] = useState('') //잠금 버튼
|
||||||
|
|
||||||
const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState) //견적서 화면용 물건번호리코일
|
const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState) //견적서 화면용 물건번호리코일
|
||||||
|
const resetCommonUtils = useResetRecoilState(commonUtilsState)
|
||||||
// 발전시뮬레이션 메뉴 이동
|
// 발전시뮬레이션 메뉴 이동
|
||||||
const { objectNo, pid } = floorPlanState
|
const { objectNo, pid } = floorPlanState
|
||||||
|
|
||||||
@ -164,6 +166,7 @@ export default function CanvasMenu(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onClickNav = async (menu) => {
|
const onClickNav = async (menu) => {
|
||||||
|
resetCommonUtils()
|
||||||
switch (menu.type) {
|
switch (menu.type) {
|
||||||
case 'drawing':
|
case 'drawing':
|
||||||
swalFire({
|
swalFire({
|
||||||
@ -194,6 +197,7 @@ export default function CanvasMenu(props) {
|
|||||||
confirmFn: () => {
|
confirmFn: () => {
|
||||||
//해당 메뉴 이동시 배치면 삭제
|
//해당 메뉴 이동시 배치면 삭제
|
||||||
|
|
||||||
|
setAllModuleSurfaceIsComplete(false)
|
||||||
const moduleSurfacesArray = canvas
|
const moduleSurfacesArray = canvas
|
||||||
.getObjects()
|
.getObjects()
|
||||||
.filter((obj) => [POLYGON_TYPE.MODULE_SETUP_SURFACE, POLYGON_TYPE.MODULE, POLYGON_TYPE.OBJECT_SURFACE].includes(obj.name))
|
.filter((obj) => [POLYGON_TYPE.MODULE_SETUP_SURFACE, POLYGON_TYPE.MODULE, POLYGON_TYPE.OBJECT_SURFACE].includes(obj.name))
|
||||||
@ -233,8 +237,12 @@ export default function CanvasMenu(props) {
|
|||||||
await reloadCanvasStatus(objectNo, pid)
|
await reloadCanvasStatus(objectNo, pid)
|
||||||
break
|
break
|
||||||
case 'estimate':
|
case 'estimate':
|
||||||
|
if (!isAllComplete()) {
|
||||||
|
swalFire({ text: getMessage('estimate.menu.move.valid1') })
|
||||||
|
return
|
||||||
|
}
|
||||||
setIsGlobalLoading(true)
|
setIsGlobalLoading(true)
|
||||||
promiseGet({ url: `/api/estimate/${objectNo}/${selectedPlan.planNo}/detail` }).then((res) => {
|
promiseGet({ url: `/api/estimate/${objectNo}/${selectedPlan?.planNo ?? pid}/detail` }).then((res) => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const estimateDetail = res.data
|
const estimateDetail = res.data
|
||||||
if (estimateDetail.estimateDate !== null) {
|
if (estimateDetail.estimateDate !== null) {
|
||||||
@ -242,7 +250,7 @@ export default function CanvasMenu(props) {
|
|||||||
setCurrentMenu(menu.title)
|
setCurrentMenu(menu.title)
|
||||||
setFloorPlanObjectNo({ floorPlanObjectNo: objectNo })
|
setFloorPlanObjectNo({ floorPlanObjectNo: objectNo })
|
||||||
setIsGlobalLoading(false)
|
setIsGlobalLoading(false)
|
||||||
router.push(`/floor-plan/estimate/5?pid=${selectedPlan.planNo}&objectNo=${objectNo}`)
|
router.push(`/floor-plan/estimate/5?pid=${selectedPlan?.planNo ?? pid}&objectNo=${objectNo}`)
|
||||||
if (pathname === '/floor-plan/estimate/5') {
|
if (pathname === '/floor-plan/estimate/5') {
|
||||||
setIsGlobalLoading(false)
|
setIsGlobalLoading(false)
|
||||||
}
|
}
|
||||||
@ -255,13 +263,13 @@ export default function CanvasMenu(props) {
|
|||||||
break
|
break
|
||||||
case 'simulation':
|
case 'simulation':
|
||||||
setIsGlobalLoading(true)
|
setIsGlobalLoading(true)
|
||||||
promiseGet({ url: `/api/estimate/${objectNo}/${selectedPlan.planNo}/detail` }).then((res) => {
|
promiseGet({ url: `/api/estimate/${objectNo}/${selectedPlan?.planNo ?? pid}/detail` }).then((res) => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const estimateDetail = res.data
|
const estimateDetail = res.data
|
||||||
if (estimateDetail.estimateDate !== null && estimateDetail.docNo) {
|
if (estimateDetail.estimateDate !== null && estimateDetail.docNo) {
|
||||||
setSelectedMenu(menu.type)
|
setSelectedMenu(menu.type)
|
||||||
setCurrentMenu(menu.title)
|
setCurrentMenu(menu.title)
|
||||||
router.push(`/floor-plan/simulator/6?pid=${selectedPlan.planNo}&objectNo=${objectNo}`)
|
router.push(`/floor-plan/simulator/6?pid=${selectedPlan?.planNo ?? pid}&objectNo=${objectNo}`)
|
||||||
if (pathname === '/floor-plan/simulator/6') {
|
if (pathname === '/floor-plan/simulator/6') {
|
||||||
setIsGlobalLoading(false)
|
setIsGlobalLoading(false)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,9 +5,10 @@ import { useEffect } from 'react'
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import useMenu from '@/hooks/common/useMenu'
|
import useMenu from '@/hooks/common/useMenu'
|
||||||
import { canvasState, currentMenuState } from '@/store/canvasAtom'
|
import { canvasState, currentMenuState } from '@/store/canvasAtom'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
|
||||||
import { subMenusState } from '@/store/menuAtom'
|
import { subMenusState } from '@/store/menuAtom'
|
||||||
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||||
|
import { commonUtilsState } from '@/store/commonUtilsAtom'
|
||||||
|
|
||||||
export default function MenuDepth01() {
|
export default function MenuDepth01() {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
@ -16,8 +17,10 @@ export default function MenuDepth01() {
|
|||||||
const { selectedMenu, setSelectedMenu } = useCanvasMenu()
|
const { selectedMenu, setSelectedMenu } = useCanvasMenu()
|
||||||
const [currentMenu, setCurrentMenu] = useRecoilState(currentMenuState)
|
const [currentMenu, setCurrentMenu] = useRecoilState(currentMenuState)
|
||||||
const subMenus = useRecoilValue(subMenusState)
|
const subMenus = useRecoilValue(subMenusState)
|
||||||
|
const resetCommonUtils = useResetRecoilState(commonUtilsState)
|
||||||
|
|
||||||
const onClickMenu = ({ id, menu }) => {
|
const onClickMenu = ({ id, menu }) => {
|
||||||
|
resetCommonUtils()
|
||||||
if (menu === currentMenu) {
|
if (menu === currentMenu) {
|
||||||
handleMenu(selectedMenu)
|
handleMenu(selectedMenu)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -12,10 +12,12 @@ import {
|
|||||||
import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil'
|
||||||
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
||||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||||
|
import Image from 'next/image'
|
||||||
|
|
||||||
const Placement = forwardRef((props, refs) => {
|
const Placement = forwardRef((props, refs) => {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const [useTab, setUseTab] = useState(true)
|
const [useTab, setUseTab] = useState(true)
|
||||||
|
const [guideType, setGuideType] = useState('batch')
|
||||||
|
|
||||||
const [isChidoriNotAble, setIsChidoriNotAble] = useState(false)
|
const [isChidoriNotAble, setIsChidoriNotAble] = useState(false)
|
||||||
|
|
||||||
@ -317,60 +319,91 @@ const Placement = forwardRef((props, refs) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="hide-check-guide">
|
<div className="hide-tab-wrap">
|
||||||
{getMessage('modal.module.basic.setting.module.placement.max.size.check')}
|
<div className="hide-check-guide">
|
||||||
<button className={`arr ${!useTab ? 'act' : ''}`} onClick={() => setUseTab(!useTab)}></button>
|
{getMessage('modal.module.basic.setting.module.placement.info')}
|
||||||
</div>
|
<button className={`arr ${useTab ? 'act' : ''}`} onClick={() => setUseTab(!useTab)}></button>
|
||||||
<div className={`module-table-box mt10 ${useTab ? 'hide' : ''}`}>
|
</div>
|
||||||
<div className="module-table-inner">
|
<div className={`hide-tab-contents ${!useTab ? 'hide' : ''}`}>
|
||||||
<div className="roof-module-table">
|
<div className="roof-content-tab-wrap">
|
||||||
<table className="">
|
<button className={`btn-frame block modal mr5 ${guideType === 'batch' ? 'act' : ''} `} onClick={() => setGuideType('batch')}>
|
||||||
<thead>
|
{getMessage('modal.module.basic.setting.module.placement.info.batch')}
|
||||||
<tr>
|
</button>
|
||||||
<th rowSpan={2} style={{ width: '22%' }}></th>
|
<button className={`btn-frame block modal mr5 ${guideType === 'module' ? 'act' : ''}`} onClick={() => setGuideType('module')}>
|
||||||
{selectedModules &&
|
{getMessage('modal.module.basic.setting.module.placement.info.module')}
|
||||||
selectedModules.itemList?.map((item) => (
|
</button>
|
||||||
// <th colSpan={colspan}>
|
|
||||||
<th>
|
|
||||||
<div className="color-wrap">
|
|
||||||
<span className="color-box" style={{ backgroundColor: item.color }}></span>
|
|
||||||
<span className="name">{item.itemNm}</span>
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
))}
|
|
||||||
{colspan > 1 && <th rowSpan={2}>{getMessage('modal.module.basic.setting.module.placement.max.rows.multiple')}</th>}
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
{selectedModules &&
|
|
||||||
selectedModules.itemList?.map((item) => (
|
|
||||||
<>
|
|
||||||
<th>{getMessage('modal.module.basic.setting.module.placement.max.row')}</th>
|
|
||||||
{/* {colspan > 1 && <th>{getMessage('modal.module.basic.setting.module.placement.max.rows.multiple')}</th>} */}
|
|
||||||
</>
|
|
||||||
))}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{moduleSelectionData.roofConstructions.map((item, index) => (
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<div className="color-wrap">
|
|
||||||
<span className="color-box" style={{ backgroundColor: roofOutlineColor(item.addRoof?.index) }}></span>
|
|
||||||
<span className="name">{item.addRoof?.roofMatlNmJp}</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
{moduleRowColArray[index]?.map((item, index2) => (
|
|
||||||
<>
|
|
||||||
<td className="al-c">{item.moduleMaxRows}</td>
|
|
||||||
{/* {colspan > 1 && <td className="al-c">{item.mixModuleMaxRows}</td>} */}
|
|
||||||
{colspan > 1 && index2 === moduleRowColArray[index].length - 1 && <td className="al-c">{item.maxRow}</td>}
|
|
||||||
</>
|
|
||||||
))}
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
|
{guideType === 'batch' && (
|
||||||
|
<div className={`roof-warning-wrap mt10`}>
|
||||||
|
<div className="guide">
|
||||||
|
{getMessage('modal.module.basic.setting.module.placement.info.batch.content1')}
|
||||||
|
<br />
|
||||||
|
{getMessage('modal.module.basic.setting.module.placement.info.batch.content2')}
|
||||||
|
</div>
|
||||||
|
<div className="roof-warning-img-wrap">
|
||||||
|
<div className="roof-warning-img">
|
||||||
|
<Image src={'/static/images/canvas/roof_warning_correct.png'} width={350} height={198} alt="" />
|
||||||
|
</div>
|
||||||
|
<div className="roof-warning-img">
|
||||||
|
<Image src={'/static/images/canvas/roof_warning_wrong.png'} width={350} height={198} alt="" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{guideType === 'module' && (
|
||||||
|
<div className={`module-table-box mt10 ${!useTab ? 'hide' : ''}`}>
|
||||||
|
<div className="module-table-inner">
|
||||||
|
<div className="roof-module-table">
|
||||||
|
<table className="">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th rowSpan={2} style={{ width: '22%' }}></th>
|
||||||
|
{selectedModules &&
|
||||||
|
selectedModules.itemList?.map((item) => (
|
||||||
|
// <th colSpan={colspan}>
|
||||||
|
<th>
|
||||||
|
<div className="color-wrap">
|
||||||
|
<span className="color-box" style={{ backgroundColor: item.color }}></span>
|
||||||
|
<span className="name">{item.itemNm}</span>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
))}
|
||||||
|
{colspan > 1 && <th rowSpan={2}>{getMessage('modal.module.basic.setting.module.placement.max.rows.multiple')}</th>}
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{selectedModules &&
|
||||||
|
selectedModules.itemList?.map((item) => (
|
||||||
|
<>
|
||||||
|
<th>{getMessage('modal.module.basic.setting.module.placement.max.row')}</th>
|
||||||
|
{/* {colspan > 1 && <th>{getMessage('modal.module.basic.setting.module.placement.max.rows.multiple')}</th>} */}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{moduleSelectionData.roofConstructions.map((item, index) => (
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div className="color-wrap">
|
||||||
|
<span className="color-box" style={{ backgroundColor: roofOutlineColor(item.addRoof?.index) }}></span>
|
||||||
|
<span className="name">{item.addRoof?.roofMatlNmJp}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
{moduleRowColArray[index]?.map((item, index2) => (
|
||||||
|
<>
|
||||||
|
<td className="al-c">{item.moduleMaxRows}</td>
|
||||||
|
{/* {colspan > 1 && <td className="al-c">{item.mixModuleMaxRows}</td>} */}
|
||||||
|
{colspan > 1 && index2 === moduleRowColArray[index].length - 1 && <td className="al-c">{item.maxRow}</td>}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -217,7 +217,7 @@ const Trestle = forwardRef((props, ref) => {
|
|||||||
stdWindSpeed: managementState?.standardWindSpeedId ?? '',
|
stdWindSpeed: managementState?.standardWindSpeedId ?? '',
|
||||||
stdSnowLd: managementState?.verticalSnowCover ?? '',
|
stdSnowLd: managementState?.verticalSnowCover ?? '',
|
||||||
inclCd: selectedRoof?.pitch ?? 0,
|
inclCd: selectedRoof?.pitch ?? 0,
|
||||||
roofPitch: Math.round(selectedRoof?.roofPchBase ?? 0),
|
roofPitch: Math.round(hajebichi ?? 0),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -236,9 +236,9 @@ const Trestle = forwardRef((props, ref) => {
|
|||||||
illuminationTp: managementState?.surfaceTypeValue ?? '',
|
illuminationTp: managementState?.surfaceTypeValue ?? '',
|
||||||
instHt: managementState?.installHeight ?? '',
|
instHt: managementState?.installHeight ?? '',
|
||||||
stdWindSpeed: managementState?.standardWindSpeedId ?? '',
|
stdWindSpeed: managementState?.standardWindSpeedId ?? '',
|
||||||
stdSnowLd: +managementState?.verticalSnowCover ?? '',
|
stdSnowLd: managementState?.verticalSnowCover ?? '',
|
||||||
inclCd: selectedRoof?.pitch ?? 0,
|
inclCd: selectedRoof?.pitch ?? 0,
|
||||||
roofPitch: Math.round(selectedRoof?.roofPchBase ?? 0),
|
roofPitch: Math.round(hajebichi ?? 0),
|
||||||
constTp: constructionList[index].constTp,
|
constTp: constructionList[index].constTp,
|
||||||
snowGdPossYn: constructionList[index].snowGdPossYn,
|
snowGdPossYn: constructionList[index].snowGdPossYn,
|
||||||
cvrYn: constructionList[index].cvrYn,
|
cvrYn: constructionList[index].cvrYn,
|
||||||
@ -304,6 +304,7 @@ const Trestle = forwardRef((props, ref) => {
|
|||||||
kerabaMargin,
|
kerabaMargin,
|
||||||
roofIndex: roof.index,
|
roofIndex: roof.index,
|
||||||
raft: selectedRaftBase?.clCode,
|
raft: selectedRaftBase?.clCode,
|
||||||
|
hajebichi: hajebichi,
|
||||||
trestle: {
|
trestle: {
|
||||||
length: lengthBase,
|
length: lengthBase,
|
||||||
hajebichi: hajebichi,
|
hajebichi: hajebichi,
|
||||||
|
|||||||
@ -13,10 +13,10 @@ import { useRecoilState } from 'recoil'
|
|||||||
import { makersState, modelsState, modelState, pcsCheckState, selectedMakerState, selectedModelsState, seriesState } from '@/store/circuitTrestleAtom'
|
import { makersState, modelsState, modelState, pcsCheckState, selectedMakerState, selectedModelsState, seriesState } from '@/store/circuitTrestleAtom'
|
||||||
import { POLYGON_TYPE } from '@/common/common'
|
import { POLYGON_TYPE } from '@/common/common'
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
import { canvasState, canvasZoomState } from '@/store/canvasAtom'
|
||||||
|
|
||||||
import { useTrestle } from '@/hooks/module/useTrestle'
|
import { useTrestle } from '@/hooks/module/useTrestle'
|
||||||
import { selectedModuleState } from '@/store/selectedModuleOptions'
|
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
|
||||||
import { useEstimate } from '@/hooks/useEstimate'
|
import { useEstimate } from '@/hooks/useEstimate'
|
||||||
@ -25,6 +25,8 @@ import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupSta
|
|||||||
import { useImgLoader } from '@/hooks/floorPlan/useImgLoader'
|
import { useImgLoader } from '@/hooks/floorPlan/useImgLoader'
|
||||||
import { usePlan } from '@/hooks/usePlan'
|
import { usePlan } from '@/hooks/usePlan'
|
||||||
import { QcastContext } from '@/app/QcastProvider'
|
import { QcastContext } from '@/app/QcastProvider'
|
||||||
|
import { fabric } from 'fabric'
|
||||||
|
import { fontSelector } from '@/store/fontAtom'
|
||||||
|
|
||||||
const ALLOCATION_TYPE = {
|
const ALLOCATION_TYPE = {
|
||||||
AUTO: 'auto',
|
AUTO: 'auto',
|
||||||
@ -37,13 +39,16 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
const { swalFire } = useSwal()
|
const { swalFire } = useSwal()
|
||||||
const { saveEstimate } = useEstimate()
|
const { saveEstimate } = useEstimate()
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
|
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
|
||||||
const [tabNum, setTabNum] = useState(1)
|
const [tabNum, setTabNum] = useState(1)
|
||||||
const [allocationType, setAllocationType] = useState(ALLOCATION_TYPE.AUTO)
|
const [allocationType, setAllocationType] = useState(ALLOCATION_TYPE.AUTO)
|
||||||
const [circuitAllocationType, setCircuitAllocationType] = useState(1)
|
const [circuitAllocationType, setCircuitAllocationType] = useState(1)
|
||||||
const { managementState, setManagementState } = useContext(GlobalDataContext)
|
const { managementState, setManagementState } = useContext(GlobalDataContext)
|
||||||
const selectedModules = useRecoilValue(selectedModuleState)
|
const selectedModules = useRecoilValue(selectedModuleState)
|
||||||
const { getPcsAutoRecommendList, getPcsVoltageChk, getPcsVoltageStepUpList, getPcsManualConfChk } = useMasterController()
|
const { getPcsAutoRecommendList, getPcsVoltageChk, getPcsVoltageStepUpList, getPcsManualConfChk } = useMasterController()
|
||||||
|
const flowText = useRecoilValue(fontSelector('flowText'))
|
||||||
|
const lengthText = useRecoilValue(fontSelector('lengthText'))
|
||||||
|
const circuitNumberText = useRecoilValue(fontSelector('circuitNumberText'))
|
||||||
|
|
||||||
// 회로할당(승합설정)에서 선택된 값들을 저장할 상태 추가
|
// 회로할당(승합설정)에서 선택된 값들을 저장할 상태 추가
|
||||||
const [selectedStepUpValues, setSelectedStepUpValues] = useState({})
|
const [selectedStepUpValues, setSelectedStepUpValues] = useState({})
|
||||||
@ -55,7 +60,7 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
const [seletedSubOption, setSeletedSubOption] = useState(null)
|
const [seletedSubOption, setSeletedSubOption] = useState(null)
|
||||||
const { setModuleStatisticsData } = useCircuitTrestle()
|
const { setModuleStatisticsData } = useCircuitTrestle()
|
||||||
const { handleCanvasToPng } = useImgLoader()
|
const { handleCanvasToPng } = useImgLoader()
|
||||||
|
const moduleSelectionData = useRecoilValue(moduleSelectionDataState)
|
||||||
const passivityCircuitAllocationRef = useRef()
|
const passivityCircuitAllocationRef = useRef()
|
||||||
const { setIsGlobalLoading } = useContext(QcastContext)
|
const { setIsGlobalLoading } = useContext(QcastContext)
|
||||||
|
|
||||||
@ -102,6 +107,29 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
// 캡쳐 전 처리
|
||||||
|
const beforeCapture = () => {
|
||||||
|
// setCanvasZoom(100)
|
||||||
|
const x = canvas.width / 2
|
||||||
|
const y = canvas.height / 2
|
||||||
|
canvas.zoomToPoint(new fabric.Point(x, y), 0.5)
|
||||||
|
changeFontSize('lengthText', '28')
|
||||||
|
changeFontSize('circuitNumber', '28')
|
||||||
|
changeFontSize('flowText', '28')
|
||||||
|
canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 캡쳐 후 처리
|
||||||
|
const afterCapture = () => {
|
||||||
|
setCanvasZoom(100)
|
||||||
|
canvas.set({ zoom: 1 })
|
||||||
|
canvas.viewportTransform = [1, 0, 0, 1, 0, 0]
|
||||||
|
changeFontSize('lengthText', lengthText.fontSize.value)
|
||||||
|
changeFontSize('circuitNumber', circuitNumberText.fontSize.value)
|
||||||
|
changeFontSize('flowText', flowText.fontSize.value)
|
||||||
|
canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
// 수동할당 시 모듈 삭제
|
// 수동할당 시 모듈 삭제
|
||||||
|
|
||||||
// 시리즈중 자동으로 추천 PCS 정보 조회
|
// 시리즈중 자동으로 추천 PCS 정보 조회
|
||||||
@ -154,6 +182,7 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
getPcsVoltageChk(pcsVoltageChkParams).then((res) => {
|
getPcsVoltageChk(pcsVoltageChkParams).then((res) => {
|
||||||
if (res.resultCode === 'S') {
|
if (res.resultCode === 'S') {
|
||||||
setTabNum(2)
|
setTabNum(2)
|
||||||
|
setAllModuleSurfaceIsComplete(false)
|
||||||
} else {
|
} else {
|
||||||
swalFire({
|
swalFire({
|
||||||
title: res.resultMsg,
|
title: res.resultMsg,
|
||||||
@ -187,6 +216,7 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
if (res?.result.resultCode === 'S' && res?.data) {
|
if (res?.result.resultCode === 'S' && res?.data) {
|
||||||
setTabNum(2)
|
setTabNum(2)
|
||||||
|
setAllModuleSurfaceIsComplete(false)
|
||||||
} else {
|
} else {
|
||||||
swalFire({ text: getMessage('common.message.send.error') })
|
swalFire({ text: getMessage('common.message.send.error') })
|
||||||
}
|
}
|
||||||
@ -286,6 +316,8 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
setSelectedModels(pcsItemList)
|
setSelectedModels(pcsItemList)
|
||||||
getPcsVoltageChk(pcsVoltageChkParams).then((res) => {
|
getPcsVoltageChk(pcsVoltageChkParams).then((res) => {
|
||||||
setAllocationType(ALLOCATION_TYPE.PASSIVITY)
|
setAllocationType(ALLOCATION_TYPE.PASSIVITY)
|
||||||
|
setAllModuleSurfaceIsComplete(false)
|
||||||
|
clearTrestle()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
swalFire({
|
swalFire({
|
||||||
@ -308,8 +340,15 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
|
|
||||||
const target = pcsCheck.max ? moduleMaxQty : moduleStdQty
|
const target = pcsCheck.max ? moduleMaxQty : moduleStdQty
|
||||||
const placementModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
|
const placementModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
|
||||||
|
let moduleAmount = placementModules.reduce((acc, module) => {
|
||||||
|
if (moduleSelectionData.module.itemList.length === 1 || module.moduleInfo.itemId === moduleSelectionData.module.itemList[0].itemId) {
|
||||||
|
return acc + 1
|
||||||
|
} else {
|
||||||
|
return acc + 0.66
|
||||||
|
}
|
||||||
|
}, 0)
|
||||||
|
|
||||||
if (placementModules.length > target) {
|
if (moduleAmount > target) {
|
||||||
swalFire({
|
swalFire({
|
||||||
title: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.validation.error01'),
|
title: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.validation.error01'),
|
||||||
type: 'alert',
|
type: 'alert',
|
||||||
@ -318,6 +357,7 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setAllocationType(ALLOCATION_TYPE.PASSIVITY)
|
setAllocationType(ALLOCATION_TYPE.PASSIVITY)
|
||||||
|
clearTrestle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,13 +387,11 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
.map((obj) => {
|
.map((obj) => {
|
||||||
obj.pcses = getStepUpListData()
|
obj.pcses = getStepUpListData()
|
||||||
})
|
})
|
||||||
|
beforeCapture()
|
||||||
setViewCircuitNumberTexts(false)
|
|
||||||
|
|
||||||
handleCanvasToPng(1)
|
handleCanvasToPng(1)
|
||||||
|
afterCapture()
|
||||||
|
|
||||||
//회로할당 저장 시 result=null인 경우에도 회로번호 텍스트 표시 유지 처리
|
//회로할당 저장 시 result=null인 경우에도 회로번호 텍스트 표시 유지 처리
|
||||||
setViewCircuitNumberTexts(true)
|
|
||||||
|
|
||||||
// 회로할당 저장 클릭 시
|
// 회로할당 저장 클릭 시
|
||||||
// 가대 및 지지금구 설치
|
// 가대 및 지지금구 설치
|
||||||
@ -368,7 +406,9 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
const result = await getEstimateData()
|
const result = await getEstimateData()
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
|
beforeCapture()
|
||||||
handleCanvasToPng(2)
|
handleCanvasToPng(2)
|
||||||
|
afterCapture()
|
||||||
// 견적서 저장
|
// 견적서 저장
|
||||||
await saveEstimate(result)
|
await saveEstimate(result)
|
||||||
} else {
|
} else {
|
||||||
@ -378,6 +418,16 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
// removeNotAllocationModules()
|
// removeNotAllocationModules()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const changeFontSize = (name, size) => {
|
||||||
|
const textObjs = canvas?.getObjects().filter((obj) => obj.name === name)
|
||||||
|
textObjs.forEach((obj) => {
|
||||||
|
obj.set({
|
||||||
|
fontSize: size,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
canvas.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
// 이전 버튼 클릭 시
|
// 이전 버튼 클릭 시
|
||||||
const onClickPrev = () => {
|
const onClickPrev = () => {
|
||||||
// setAllocationType(ALLOCATION_TYPE.AUTO)
|
// setAllocationType(ALLOCATION_TYPE.AUTO)
|
||||||
@ -654,6 +704,7 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
setTabNum(2)
|
setTabNum(2)
|
||||||
|
setAllModuleSurfaceIsComplete(false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -227,7 +227,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
|||||||
console.log('save Info', {
|
console.log('save Info', {
|
||||||
...basicSetting,
|
...basicSetting,
|
||||||
selectedRoofMaterial: {
|
selectedRoofMaterial: {
|
||||||
roofInfo,
|
...newAddedRoofs[0],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -240,7 +240,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
|||||||
* 선택된 지붕재 정보
|
* 선택된 지붕재 정보
|
||||||
*/
|
*/
|
||||||
selectedRoofMaterial: {
|
selectedRoofMaterial: {
|
||||||
roofInfo,
|
...newAddedRoofs[0],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -952,9 +952,18 @@ export default function StuffDetail() {
|
|||||||
|
|
||||||
//팝업에서 넘어온 우편정보
|
//팝업에서 넘어온 우편정보
|
||||||
const setZipInfo = (info) => {
|
const setZipInfo = (info) => {
|
||||||
setPrefValue(info.prefId)
|
|
||||||
form.setValue('prefId', info.prefId)
|
prefCodeList.map((row) => {
|
||||||
form.setValue('prefName', info.address1)
|
if (row.prefName == info.address1) {
|
||||||
|
setPrefValue(row.prefId)
|
||||||
|
form.setValue('prefId', row.prefId)
|
||||||
|
form.setValue('prefName', info.address1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
//setPrefValue(info.prefId)
|
||||||
|
// form.setValue('prefId', info.prefId)
|
||||||
|
// form.setValue('prefName', info.address1)
|
||||||
form.setValue('address', info.address2 + info.address3)
|
form.setValue('address', info.address2 + info.address3)
|
||||||
form.setValue('zipNo', info.zipNo)
|
form.setValue('zipNo', info.zipNo)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,19 +56,20 @@ export default function StuffSubHeader({ type }) {
|
|||||||
*/
|
*/
|
||||||
const moveFloorPlan = () => {
|
const moveFloorPlan = () => {
|
||||||
setFloorPlanObjectNo({ floorPlanObjectNo: objectNo })
|
setFloorPlanObjectNo({ floorPlanObjectNo: objectNo })
|
||||||
|
|
||||||
const param = {
|
const param = {
|
||||||
pid: managementState?.planList?.length === 0 ? '1' : managementState?.planList[0].planNo,
|
pid: managementState?.planList?.length > 0 ? managementState?.planList[0].planNo : '1',
|
||||||
objectNo: objectNo,
|
objectNo: objectNo,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (managementState?.planList?.length === 0) {
|
if (managementState?.planList?.length > 0) {
|
||||||
setSelectedMenu('surface')
|
|
||||||
} else {
|
|
||||||
if (managementState?.planList[0].estimateDate) {
|
if (managementState?.planList[0].estimateDate) {
|
||||||
setSelectedMenu('module')
|
setSelectedMenu('module')
|
||||||
} else {
|
} else {
|
||||||
setSelectedMenu('surface')
|
setSelectedMenu('surface')
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
setSelectedMenu('surface')
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = `/floor-plan?${queryStringFormatter(param)}`
|
const url = `/floor-plan?${queryStringFormatter(param)}`
|
||||||
|
|||||||
@ -114,7 +114,7 @@ export default function Simulator() {
|
|||||||
setHatsudenryouPeakcutAllSnow([])
|
setHatsudenryouPeakcutAllSnow([])
|
||||||
|
|
||||||
if (objectNo && pid && selectedPlan) {
|
if (objectNo && pid && selectedPlan) {
|
||||||
fetchObjectDetail(objectNo, selectedPlan.planNo)
|
fetchObjectDetail(objectNo, selectedPlan?.planNo??pid)
|
||||||
fetchSimulatorNotice()
|
fetchSimulatorNotice()
|
||||||
setPwrGnrSimType('D')
|
setPwrGnrSimType('D')
|
||||||
setPwrRecoil({ ...pwrRecoil, type: 'D' })
|
setPwrRecoil({ ...pwrRecoil, type: 'D' })
|
||||||
|
|||||||
11
src/config/config.common.js
Normal file
11
src/config/config.common.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// local, development, production 과 관계없이 동일한 값으로 반환되는 부분은 해당 함수의 return 되는 부분만 수정하면 됩니다. (달라져야 하는 값이 아닌, 같은 값에 대해서는 local, development, production 파일을 모두 수정할 필요가 없어지게 됩니다.)
|
||||||
|
export default function getConfigs(params) {
|
||||||
|
// local, development, production 마다 달라지는 값
|
||||||
|
const { baseUrl, mode } = params
|
||||||
|
|
||||||
|
// 공통으로 반환되는 구조
|
||||||
|
return {
|
||||||
|
baseUrl,
|
||||||
|
mode,
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/config/config.development.js
Normal file
13
src/config/config.development.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import getConfigs from './config.common'
|
||||||
|
|
||||||
|
// 환경마다 달라져야 할 변수, 값들을 정의합니다. (여기는 development 환경에 맞는 값을 지정합니다.)
|
||||||
|
const baseUrl = 'https://dev.hanssys.jp'
|
||||||
|
const mode = 'development'
|
||||||
|
|
||||||
|
// 환경마다 달라져야 할 값들을 getConfig 함수에 전달합니다.
|
||||||
|
const configDevelopment = getConfigs({
|
||||||
|
baseUrl,
|
||||||
|
mode,
|
||||||
|
})
|
||||||
|
|
||||||
|
export default configDevelopment
|
||||||
23
src/config/config.export.js
Normal file
23
src/config/config.export.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import configDevelopment from './config.development'
|
||||||
|
import configLocal from './config.local'
|
||||||
|
import configLocalDev from './config.local.dev'
|
||||||
|
import configProduction from './config.production'
|
||||||
|
|
||||||
|
// 클라이언트에서는 이 함수를 사용하여 config 값을 참조합니다.
|
||||||
|
const Config = () => {
|
||||||
|
console.log('🚀 ~ Config ~ process.env.NEXT_PUBLIC_RUN_MODE:', process.env.NEXT_PUBLIC_RUN_MODE)
|
||||||
|
switch (process.env.NEXT_PUBLIC_RUN_MODE) {
|
||||||
|
case 'local':
|
||||||
|
return configLocal
|
||||||
|
case 'local.dev':
|
||||||
|
return configLocalDev
|
||||||
|
case 'development':
|
||||||
|
return configDevelopment
|
||||||
|
case 'production':
|
||||||
|
return configProduction
|
||||||
|
default:
|
||||||
|
return configLocal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Config
|
||||||
13
src/config/config.local.dev.js
Normal file
13
src/config/config.local.dev.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import getConfigs from './config.common'
|
||||||
|
|
||||||
|
// 환경마다 달라져야 할 변수, 값들을 정의합니다. (여기는 local 환경에 맞는 값을 지정합니다.)
|
||||||
|
const baseUrl = 'http://1.248.227.176:5000'
|
||||||
|
const mode = 'local.dev'
|
||||||
|
|
||||||
|
// 환경마다 달라져야 할 값들을 getConfig 함수에 전달합니다.
|
||||||
|
const configLocalDev = getConfigs({
|
||||||
|
baseUrl,
|
||||||
|
mode,
|
||||||
|
})
|
||||||
|
|
||||||
|
export default configLocalDev
|
||||||
13
src/config/config.local.js
Normal file
13
src/config/config.local.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import getConfigs from './config.common'
|
||||||
|
|
||||||
|
// 환경마다 달라져야 할 변수, 값들을 정의합니다. (여기는 local 환경에 맞는 값을 지정합니다.)
|
||||||
|
const baseUrl = 'http://localhost:3000'
|
||||||
|
const mode = 'local'
|
||||||
|
|
||||||
|
// 환경마다 달라져야 할 값들을 getConfig 함수에 전달합니다.
|
||||||
|
const configLocal = getConfigs({
|
||||||
|
baseUrl,
|
||||||
|
mode,
|
||||||
|
})
|
||||||
|
|
||||||
|
export default configLocal
|
||||||
13
src/config/config.production.js
Normal file
13
src/config/config.production.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import getConfigs from './config.common'
|
||||||
|
|
||||||
|
// 환경마다 달라져야 할 변수, 값들을 정의합니다. (여기는 production 환경에 맞는 값을 지정합니다.)
|
||||||
|
const baseUrl = 'https://www.hanasys.jp'
|
||||||
|
const mode = 'production'
|
||||||
|
|
||||||
|
// 환경마다 달라져야 할 값들을 getConfig 함수에 전달합니다.
|
||||||
|
const configProduction = getConfigs({
|
||||||
|
baseUrl,
|
||||||
|
mode,
|
||||||
|
})
|
||||||
|
|
||||||
|
export default configProduction
|
||||||
@ -1,11 +1,11 @@
|
|||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
|
||||||
import { wordDisplaySelector } from '@/store/settingAtom'
|
import { wordDisplaySelector } from '@/store/settingAtom'
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
import { checkLineOrientation, getDistance } from '@/util/canvas-util'
|
import { checkLineOrientation, getDistance } from '@/util/canvas-util'
|
||||||
import { commonUtilsState, dimensionLineSettingsState } from '@/store/commonUtilsAtom'
|
import { commonUtilsState, dimensionLineSettingsState } from '@/store/commonUtilsAtom'
|
||||||
import { fontSelector } from '@/store/fontAtom'
|
import { fontSelector } from '@/store/fontAtom'
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
import { canvasState, currentMenuState } from '@/store/canvasAtom'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import Distance from '@/components/floor-plan/modal/distance/Distance'
|
import Distance from '@/components/floor-plan/modal/distance/Distance'
|
||||||
@ -16,57 +16,91 @@ import { BATCH_TYPE } from '@/common/common'
|
|||||||
export function useCommonUtils() {
|
export function useCommonUtils() {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const wordDisplay = useRecoilValue(wordDisplaySelector)
|
const wordDisplay = useRecoilValue(wordDisplaySelector)
|
||||||
const { addCanvasMouseEventListener, addDocumentEventListener, initEvent } = useEvent()
|
const { addCanvasMouseEventListener, addDocumentEventListener, initEvent, removeMouseEvent } = useEvent()
|
||||||
const dimensionSettings = useRecoilValue(dimensionLineSettingsState)
|
const dimensionSettings = useRecoilValue(dimensionLineSettingsState)
|
||||||
const dimensionLineTextFont = useRecoilValue(fontSelector('dimensionLineText'))
|
const dimensionLineTextFont = useRecoilValue(fontSelector('dimensionLineText'))
|
||||||
const lengthTextFont = useRecoilValue(fontSelector('lengthText'))
|
const lengthTextFont = useRecoilValue(fontSelector('lengthText'))
|
||||||
const commonTextFont = useRecoilValue(fontSelector('commonText'))
|
const commonTextFont = useRecoilValue(fontSelector('commonText'))
|
||||||
const [commonUtils, setCommonUtilsState] = useRecoilState(commonUtilsState)
|
const [commonUtils, setCommonUtilsState] = useRecoilState(commonUtilsState)
|
||||||
const { addPopup } = usePopup()
|
const { addPopup, closeAll, targetClose } = usePopup()
|
||||||
const { drawDirectionArrow, addLengthText } = usePolygon()
|
const { drawDirectionArrow, addLengthText } = usePolygon()
|
||||||
const { applyDormers } = useObjectBatch({})
|
const { applyDormers } = useObjectBatch({})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (commonUtils.text) {
|
commonTextMode()
|
||||||
commonTextMode()
|
if (commonUtils.dimension) {
|
||||||
} else if (commonUtils.dimension) {
|
|
||||||
commonDimensionMode()
|
commonDimensionMode()
|
||||||
} else if (commonUtils.distance) {
|
return
|
||||||
|
}
|
||||||
|
if (commonUtils.distance) {
|
||||||
commonDistanceMode()
|
commonDistanceMode()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}, [commonUtils, dimensionSettings, commonTextFont, dimensionLineTextFont])
|
}, [commonUtils, dimensionSettings, commonTextFont, dimensionLineTextFont])
|
||||||
|
|
||||||
const commonTextMode = () => {
|
const commonTextMode = () => {
|
||||||
let textbox
|
let textbox
|
||||||
|
|
||||||
if (commonUtils.text) {
|
if (commonUtils.text) {
|
||||||
commonTextKeyEvent()
|
targetClose('other')
|
||||||
addCanvasMouseEventListener('mouse:down', (event) => {
|
setTimeout(() => {
|
||||||
const pointer = canvas?.getPointer(event.e)
|
commonTextKeyEvent()
|
||||||
|
addCanvasMouseEventListener('mouse:down', (event) => {
|
||||||
|
const pointer = canvas?.getPointer(event.e)
|
||||||
|
|
||||||
textbox = new fabric.Textbox('', {
|
textbox = new fabric.Textbox('', {
|
||||||
left: pointer.x,
|
left: pointer.x,
|
||||||
top: pointer.y,
|
top: pointer.y,
|
||||||
width: 200,
|
width: 200,
|
||||||
editable: true,
|
editable: true,
|
||||||
name: 'commonText',
|
name: 'commonText',
|
||||||
visible: wordDisplay,
|
visible: wordDisplay,
|
||||||
fill: commonTextFont.fontColor.value,
|
fill: commonTextFont.fontColor.value,
|
||||||
fontFamily: commonTextFont.fontFamily.value,
|
fontFamily: commonTextFont.fontFamily.value,
|
||||||
fontSize: commonTextFont.fontSize.value,
|
fontSize: commonTextFont.fontSize.value,
|
||||||
fontStyle: commonTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
|
fontStyle: commonTextFont.fontWeight.value.toLowerCase().includes('italic') ? 'italic' : 'normal',
|
||||||
fontWeight: commonTextFont.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal',
|
fontWeight: commonTextFont.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal',
|
||||||
selectable: true,
|
selectable: true,
|
||||||
lockMovementX: true,
|
lockMovementX: true,
|
||||||
lockMovementY: true,
|
lockMovementY: true,
|
||||||
originX: 'center',
|
originX: 'center',
|
||||||
originY: 'center',
|
originY: 'center',
|
||||||
|
})
|
||||||
|
|
||||||
|
canvas?.add(textbox)
|
||||||
|
canvas.setActiveObject(textbox)
|
||||||
|
textbox.enterEditing()
|
||||||
|
textbox.selectAll()
|
||||||
})
|
})
|
||||||
|
}, 100)
|
||||||
|
} else {
|
||||||
|
removeMouseEvent('mouse:down')
|
||||||
|
const activeObject = canvas?.getActiveObject()
|
||||||
|
const commonTexts = canvas?.getObjects().filter((obj) => obj.name === 'commonText')
|
||||||
|
if (commonTexts) {
|
||||||
|
commonTexts.forEach((text) => {
|
||||||
|
if (text.text === '') {
|
||||||
|
canvas?.remove(text)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/*if (activeObject && activeObject.name === 'commonText') {
|
||||||
|
if (activeObject && activeObject.isEditing) {
|
||||||
|
if (activeObject.text === '') {
|
||||||
|
canvas?.remove(activeObject)
|
||||||
|
} else {
|
||||||
|
activeObject.exitEditing()
|
||||||
|
}
|
||||||
|
//정책 협의
|
||||||
|
const texts = canvas.getObjects().filter((obj) => obj.name === 'commonText')
|
||||||
|
texts.forEach((text) => {
|
||||||
|
text.set({ editable: false })
|
||||||
|
})
|
||||||
|
canvas.renderAll()
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
canvas?.add(textbox)
|
initEvent()
|
||||||
canvas.setActiveObject(textbox)
|
|
||||||
textbox.enterEditing()
|
|
||||||
textbox.selectAll()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -212,9 +212,14 @@ export function useMasterController() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getQuotationItem = async (params) => {
|
const getQuotationItem = async (params) => {
|
||||||
return await post({ url: '/api/v1/master/getQuotationItem', data: params }).then((res) => {
|
return await post({ url: '/api/v1/master/getQuotationItem', data: params })
|
||||||
return res
|
.then((res) => {
|
||||||
})
|
return res
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log('🚀 ~ getQuotationItem ~ error:', error)
|
||||||
|
setIsGlobalLoading(false)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { useCanvas } from '@/hooks/useCanvas'
|
|||||||
import { deleteBackGroundImage, setBackGroundImage } from '@/lib/imageActions'
|
import { deleteBackGroundImage, setBackGroundImage } from '@/lib/imageActions'
|
||||||
import { settingModalFirstOptionsState } from '@/store/settingAtom'
|
import { settingModalFirstOptionsState } from '@/store/settingAtom'
|
||||||
import { popSpinnerState } from '@/store/popupAtom'
|
import { popSpinnerState } from '@/store/popupAtom'
|
||||||
|
import Config from '@/config/config.export'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 배경 이미지 관리
|
* 배경 이미지 관리
|
||||||
@ -97,7 +98,7 @@ export function useRefFiles() {
|
|||||||
setPopSpinnerStore(true)
|
setPopSpinnerStore(true)
|
||||||
console.log('🚀 ~ handleFileDelete ~ handleFileDelete:', refImage)
|
console.log('🚀 ~ handleFileDelete ~ handleFileDelete:', refImage)
|
||||||
console.log('🚀 ~ handleFileDelete ~ currentCanvasPlan.bgImageName:', currentCanvasPlan.bgImageName)
|
console.log('🚀 ~ handleFileDelete ~ currentCanvasPlan.bgImageName:', currentCanvasPlan.bgImageName)
|
||||||
await del({ url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/upload?fileName=${currentCanvasPlan.bgImageName}` })
|
await del({ url: `${Config().baseUrl}/api/image/upload?fileName=${currentCanvasPlan.bgImageName}` })
|
||||||
setCurrentBgImage(null)
|
setCurrentBgImage(null)
|
||||||
await deleteBackGroundImage({
|
await deleteBackGroundImage({
|
||||||
objectId: currentCanvasPlan.id,
|
objectId: currentCanvasPlan.id,
|
||||||
@ -118,7 +119,7 @@ export function useRefFiles() {
|
|||||||
confirmFn: async () => {
|
confirmFn: async () => {
|
||||||
console.log('🚀 ~ handleAddressDelete ~ handleAddressDelete:', refImage)
|
console.log('🚀 ~ handleAddressDelete ~ handleAddressDelete:', refImage)
|
||||||
console.log('🚀 ~ handleAddressDelete ~ currentCanvasPlan.bgImageName:', currentCanvasPlan.bgImageName)
|
console.log('🚀 ~ handleAddressDelete ~ currentCanvasPlan.bgImageName:', currentCanvasPlan.bgImageName)
|
||||||
await del({ url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/map?fileName=${currentCanvasPlan.bgImageName}` })
|
await del({ url: `${Config().baseUrl}/api/image/map?fileName=${currentCanvasPlan.bgImageName}` })
|
||||||
setMapPositionAddress('')
|
setMapPositionAddress('')
|
||||||
setCurrentBgImage(null)
|
setCurrentBgImage(null)
|
||||||
await deleteBackGroundImage({
|
await deleteBackGroundImage({
|
||||||
@ -149,7 +150,7 @@ export function useRefFiles() {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
const res = await get({
|
const res = await get({
|
||||||
url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/map?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20`,
|
url: `${Config().baseUrl}/api/image/map?q=${queryRef.current.value}&fileNm=${currentCanvasPlan.id}&zoom=20`,
|
||||||
})
|
})
|
||||||
console.log('🚀 ~ handleMapImageDown ~ res:', res)
|
console.log('🚀 ~ handleMapImageDown ~ res:', res)
|
||||||
setCurrentBgImage(`${process.env.NEXT_PUBLIC_AWS_S3_BASE_URL}/${res.fileName}`)
|
setCurrentBgImage(`${process.env.NEXT_PUBLIC_AWS_S3_BASE_URL}/${res.fileName}`)
|
||||||
@ -208,7 +209,7 @@ export function useRefFiles() {
|
|||||||
formData.append('file', file)
|
formData.append('file', file)
|
||||||
|
|
||||||
const res = await post({
|
const res = await post({
|
||||||
url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/upload`,
|
url: `${Config().baseUrl}/api/image/upload`,
|
||||||
data: formData,
|
data: formData,
|
||||||
})
|
})
|
||||||
console.log('🚀 ~ handleUploadImageRefFile ~ res:', res)
|
console.log('🚀 ~ handleUploadImageRefFile ~ res:', res)
|
||||||
@ -238,14 +239,40 @@ export function useRefFiles() {
|
|||||||
const res = await post({ url: converterUrl, data: formData })
|
const res = await post({ url: converterUrl, data: formData })
|
||||||
console.log('🚀 ~ handleUploadConvertRefFile ~ res:', res)
|
console.log('🚀 ~ handleUploadConvertRefFile ~ res:', res)
|
||||||
|
|
||||||
|
// Convert Base64 to Blob
|
||||||
|
const base64Data = res.Files[0].FileData
|
||||||
|
const byteCharacters = atob(base64Data)
|
||||||
|
const byteArrays = []
|
||||||
|
|
||||||
|
for (let offset = 0; offset < byteCharacters.length; offset += 512) {
|
||||||
|
const slice = byteCharacters.slice(offset, offset + 512)
|
||||||
|
const byteNumbers = new Array(slice.length)
|
||||||
|
|
||||||
|
for (let i = 0; i < slice.length; i++) {
|
||||||
|
byteNumbers[i] = slice.charCodeAt(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
const byteArray = new Uint8Array(byteNumbers)
|
||||||
|
byteArrays.push(byteArray)
|
||||||
|
}
|
||||||
|
|
||||||
|
const blob = new Blob(byteArrays, { type: 'image/png' })
|
||||||
|
|
||||||
|
// Create File object from Blob
|
||||||
|
const convertImg = new File([blob], res.Files[0].FileName, { type: 'image/png' })
|
||||||
|
|
||||||
|
const newFormData = new FormData()
|
||||||
|
newFormData.append('file', convertImg)
|
||||||
|
|
||||||
/** 캐드 도면 파일 업로드 */
|
/** 캐드 도면 파일 업로드 */
|
||||||
const result = await post({
|
const result = await post({
|
||||||
url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/cad`,
|
url: `${Config().baseUrl}/api/image/cad`,
|
||||||
data: res,
|
data: newFormData,
|
||||||
})
|
})
|
||||||
console.log('🚀 ~ handleUploadConvertRefFile ~ result:', result)
|
console.log('🚀 ~ handleUploadConvertRefFile ~ result:', result)
|
||||||
|
|
||||||
setCurrentBgImage(`${process.env.NEXT_PUBLIC_AWS_S3_BASE_URL}/${res.fileName}`)
|
setCurrentBgImage(`${process.env.NEXT_PUBLIC_AWS_S3_BASE_URL}/${result.fileName}`)
|
||||||
|
// setCurrentBgImage(result.filePath)
|
||||||
setRefImage(file)
|
setRefImage(file)
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
|
|||||||
@ -13,6 +13,8 @@ import { useSwal } from '@/hooks/useSwal'
|
|||||||
// Constants
|
// Constants
|
||||||
const ESTIMATE_API_ENDPOINT = '/api/estimate' // API 엔드포인트 정의
|
const ESTIMATE_API_ENDPOINT = '/api/estimate' // API 엔드포인트 정의
|
||||||
|
|
||||||
|
import Config from '@/config/config.export'
|
||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
const updateItemInList = (itemList, dispOrder, updates) => {
|
const updateItemInList = (itemList, dispOrder, updates) => {
|
||||||
return itemList.map((item) => (item.dispOrder === dispOrder ? { ...item, ...updates } : item))
|
return itemList.map((item) => (item.dispOrder === dispOrder ? { ...item, ...updates } : item))
|
||||||
@ -464,11 +466,13 @@ export const useEstimateController = (planNo, flag) => {
|
|||||||
|
|
||||||
setIsGlobalLoading(true)
|
setIsGlobalLoading(true)
|
||||||
await promisePost({ url: '/api/estimate/save-estimate-copy', data: params })
|
await promisePost({ url: '/api/estimate/save-estimate-copy', data: params })
|
||||||
.then((res) => {
|
.then(async (res) => {
|
||||||
setIsGlobalLoading(false)
|
setIsGlobalLoading(false)
|
||||||
if (res.status === 201) {
|
if (res.status === 201) {
|
||||||
if (isObjectNotEmpty(res.data)) {
|
if (isObjectNotEmpty(res.data)) {
|
||||||
let newObjectNo = res.data.objectNo
|
let newObjectNo = res.data.objectNo
|
||||||
|
const copyImage = await handleEstimateImageCopy(params.objectNo, params.planNo, newObjectNo, '1')
|
||||||
|
|
||||||
swalFire({
|
swalFire({
|
||||||
text: getMessage('estimate.detail.estimateCopyPopup.copy.alertMessage'),
|
text: getMessage('estimate.detail.estimateCopyPopup.copy.alertMessage'),
|
||||||
type: 'alert',
|
type: 'alert',
|
||||||
@ -489,6 +493,27 @@ export const useEstimateController = (planNo, flag) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleEstimateImageCopy = async (objectNo, planNo, newObjectNo, newPlanNo) => {
|
||||||
|
await promisePost({ url: `${Config().baseUrl}/api/image/estimate-image-copy`, data: { objectNo, planNo, newObjectNo, newPlanNo } }).then(
|
||||||
|
(res) => {
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDeleteEstimate = async (canvasStatus) => {
|
||||||
|
try {
|
||||||
|
setIsGlobalLoading(true)
|
||||||
|
await promisePost({ url: `${ESTIMATE_API_ENDPOINT}/delete-estimate`, data: canvasStatus }).then((res) => {
|
||||||
|
if (res.status === 201) {
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
console.error('error::::::::::::', e.response.data.message)
|
||||||
|
}
|
||||||
|
setIsGlobalLoading(false)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 전각20자 (반각40자)
|
* 전각20자 (반각40자)
|
||||||
*/
|
*/
|
||||||
@ -509,5 +534,7 @@ export const useEstimateController = (planNo, flag) => {
|
|||||||
fetchSetting,
|
fetchSetting,
|
||||||
handleEstimateFileDownload,
|
handleEstimateFileDownload,
|
||||||
handleEstimateCopy,
|
handleEstimateCopy,
|
||||||
|
handleDeleteEstimate,
|
||||||
|
handleEstimateImageCopy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { usePlan } from '../usePlan'
|
|||||||
import { POLYGON_TYPE } from '@/common/common'
|
import { POLYGON_TYPE } from '@/common/common'
|
||||||
import { QcastContext } from '@/app/QcastProvider'
|
import { QcastContext } from '@/app/QcastProvider'
|
||||||
import { useContext } from 'react'
|
import { useContext } from 'react'
|
||||||
|
import Config from '@/config/config.export'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 이미지 로더 hook
|
* 이미지 로더 hook
|
||||||
@ -80,7 +81,7 @@ export function useImgLoader() {
|
|||||||
/** 이미지 크롭 요청 */
|
/** 이미지 크롭 요청 */
|
||||||
const result = await post({
|
const result = await post({
|
||||||
// url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/image/canvas`,
|
// url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/image/canvas`,
|
||||||
url: `${process.env.NEXT_PUBLIC_API_HOST_URL}/api/image/canvas`,
|
url: `${Config().baseUrl}/api/image/canvas`,
|
||||||
data: formData,
|
data: formData,
|
||||||
})
|
})
|
||||||
console.log('🚀 ~ handleCanvasToPng ~ result:', result)
|
console.log('🚀 ~ handleCanvasToPng ~ result:', result)
|
||||||
|
|||||||
@ -661,7 +661,7 @@ export function useModuleBasicSetting(tabNum) {
|
|||||||
|
|
||||||
//가운데 가운데
|
//가운데 가운데
|
||||||
if (Math.abs(smallCenterY - holdCellCenterY) < snapDistance) {
|
if (Math.abs(smallCenterY - holdCellCenterY) < snapDistance) {
|
||||||
tempModule.top = holdCellCenterY - toFixedWithoutRounding(width / 2, 2)
|
tempModule.top = holdCellCenterY - toFixedWithoutRounding(height / 2, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isChidori) {
|
if (isChidori) {
|
||||||
|
|||||||
@ -209,7 +209,7 @@ export function useModuleTrestle(props) {
|
|||||||
stdSnowLd: trestleState.stdSnowLd ?? '',
|
stdSnowLd: trestleState.stdSnowLd ?? '',
|
||||||
inclCd: trestleState.inclCd ?? '',
|
inclCd: trestleState.inclCd ?? '',
|
||||||
raftBaseCd: trestleState.raft ?? '',
|
raftBaseCd: trestleState.raft ?? '',
|
||||||
roofPitch: Math.round(trestleState.roofPitch) ?? '',
|
roofPitch: trestleState.hajebichi ? trestleState.hajebichi : (trestleState.roofPitch ?? ''),
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res?.data) setConstructionList(res.data)
|
if (res?.data) setConstructionList(res.data)
|
||||||
@ -236,7 +236,7 @@ export function useModuleTrestle(props) {
|
|||||||
inclCd: trestleState.inclCd ?? '',
|
inclCd: trestleState.inclCd ?? '',
|
||||||
constTp: trestleState.constTp ?? '',
|
constTp: trestleState.constTp ?? '',
|
||||||
mixMatlNo: trestleState.mixMatlNo ?? '',
|
mixMatlNo: trestleState.mixMatlNo ?? '',
|
||||||
roofPitch: trestleState.roofPitch ?? '',
|
roofPitch: trestleState.hajebichi ? trestleState.hajebichi : (trestleState.roofPitch ?? ''),
|
||||||
// workingWidth: trestleState.length ?? '',
|
// workingWidth: trestleState.length ?? '',
|
||||||
workingWidth: lengthBase ?? '',
|
workingWidth: lengthBase ?? '',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -53,6 +53,7 @@ export const useTrestle = () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
surfaces.forEach((surface) => {
|
surfaces.forEach((surface) => {
|
||||||
|
getSameLineModules(surface)
|
||||||
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
|
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
|
||||||
const roofMaterialIndex = parent.roofMaterial.index
|
const roofMaterialIndex = parent.roofMaterial.index
|
||||||
if (+roofSizeSet === 3) {
|
if (+roofSizeSet === 3) {
|
||||||
@ -67,6 +68,7 @@ export const useTrestle = () => {
|
|||||||
let moduleRowsTotCnt = 0
|
let moduleRowsTotCnt = 0
|
||||||
let isEaveBar = construction.setupCover
|
let isEaveBar = construction.setupCover
|
||||||
let isSnowGuard = construction.setupSnowCover
|
let isSnowGuard = construction.setupSnowCover
|
||||||
|
let cvrLmtRow = construction.cvrLmtRow
|
||||||
const direction = parent.direction
|
const direction = parent.direction
|
||||||
const rack = surface.trestleDetail.rack
|
const rack = surface.trestleDetail.rack
|
||||||
let { rackQty, rackIntvlPct, rackYn, cvrPlvrYn, lessSupFitIntvlPct, lessSupFitQty } = surface.trestleDetail
|
let { rackQty, rackIntvlPct, rackYn, cvrPlvrYn, lessSupFitIntvlPct, lessSupFitQty } = surface.trestleDetail
|
||||||
@ -149,6 +151,10 @@ export const useTrestle = () => {
|
|||||||
if (isEaveBar) {
|
if (isEaveBar) {
|
||||||
// 처마력바설치 true인 경우 설치
|
// 처마력바설치 true인 경우 설치
|
||||||
exposedBottomModules.forEach((module) => {
|
exposedBottomModules.forEach((module) => {
|
||||||
|
const level = module.level
|
||||||
|
if (level > cvrLmtRow) {
|
||||||
|
return
|
||||||
|
}
|
||||||
const bottomPoints = findTopTwoPoints([...module.getCurrentPoints()], direction)
|
const bottomPoints = findTopTwoPoints([...module.getCurrentPoints()], direction)
|
||||||
if (!bottomPoints) return
|
if (!bottomPoints) return
|
||||||
const eaveBar = new fabric.Line([bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y], {
|
const eaveBar = new fabric.Line([bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y], {
|
||||||
@ -167,6 +173,10 @@ export const useTrestle = () => {
|
|||||||
|
|
||||||
if (isChidory && cvrPlvrYn === 'Y') {
|
if (isChidory && cvrPlvrYn === 'Y') {
|
||||||
leftExposedHalfBottomModules.forEach((module) => {
|
leftExposedHalfBottomModules.forEach((module) => {
|
||||||
|
const level = module.level
|
||||||
|
if (level > cvrLmtRow) {
|
||||||
|
return
|
||||||
|
}
|
||||||
const bottomPoints = findTopTwoPoints([...module.getCurrentPoints()], direction)
|
const bottomPoints = findTopTwoPoints([...module.getCurrentPoints()], direction)
|
||||||
let barPoints = []
|
let barPoints = []
|
||||||
//설치해야할 반처마커버 포인트를 방향에 따라 설정
|
//설치해야할 반처마커버 포인트를 방향에 따라 설정
|
||||||
@ -197,6 +207,10 @@ export const useTrestle = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
rightExposedHalfBottomPoints.forEach((module) => {
|
rightExposedHalfBottomPoints.forEach((module) => {
|
||||||
|
const level = module.level
|
||||||
|
if (level > cvrLmtRow) {
|
||||||
|
return
|
||||||
|
}
|
||||||
const bottomPoints = findTopTwoPoints([...module.points], direction)
|
const bottomPoints = findTopTwoPoints([...module.points], direction)
|
||||||
let barPoints = []
|
let barPoints = []
|
||||||
//설치해야할 반처마커버 포인트를 방향에 따라 설정
|
//설치해야할 반처마커버 포인트를 방향에 따라 설정
|
||||||
@ -1059,7 +1073,8 @@ export const useTrestle = () => {
|
|||||||
|
|
||||||
const roof = canvas.getObjects().find((obj) => obj.id === surface.parentId)
|
const roof = canvas.getObjects().find((obj) => obj.id === surface.parentId)
|
||||||
const degree = getDegreeByChon(roof.roofMaterial.pitch)
|
const degree = getDegreeByChon(roof.roofMaterial.pitch)
|
||||||
|
rackIntvlPct = rackIntvlPct === 0 ? 1 : rackIntvlPct // 0인 경우 1로 변경
|
||||||
|
rackIntvlPct = 100 / rackIntvlPct // 퍼센트로 변경
|
||||||
const moduleLeft = lastX ?? left
|
const moduleLeft = lastX ?? left
|
||||||
const moduleTop = lastY ?? top
|
const moduleTop = lastY ?? top
|
||||||
|
|
||||||
@ -1573,7 +1588,9 @@ export const useTrestle = () => {
|
|||||||
drawBracketWithOutRack(module, rackIntvlPct, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
|
drawBracketWithOutRack(module, rackIntvlPct, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
|
||||||
if (rackQty === 3 && !findSamePointInBottom(exposedBottomModules, module)) {
|
if (rackQty === 3 && !findSamePointInBottom(exposedBottomModules, module)) {
|
||||||
// 해당 모듈과 같은 위치 맨 아래에 모듈이 없는 경우 하나 더 설치 필요
|
// 해당 모듈과 같은 위치 맨 아래에 모듈이 없는 경우 하나 더 설치 필요
|
||||||
drawBracketWithOutRack(module, rackIntvlPct / 3, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
|
if (module.level % 2 !== 0) {
|
||||||
|
drawBracketWithOutRack(module, rackIntvlPct / 3, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (rackQty === 4) {
|
if (rackQty === 4) {
|
||||||
drawBracketWithOutRack(module, rackIntvlPct / 3, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
|
drawBracketWithOutRack(module, rackIntvlPct / 3, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
|
||||||
@ -1581,10 +1598,13 @@ export const useTrestle = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
rightExposedHalfBottomPoints.forEach((module) => {
|
rightExposedHalfBottomPoints.forEach((module) => {
|
||||||
|
console.log('rightmodule.level', module.level)
|
||||||
drawBracketWithOutRack(module, rackIntvlPct, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
|
drawBracketWithOutRack(module, rackIntvlPct, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
|
||||||
if (rackQty === 3 && !findSamePointInBottom(exposedBottomModules, module, direction)) {
|
if (rackQty === 3 && !findSamePointInBottom(exposedBottomModules, module, direction)) {
|
||||||
// 해당 모듈과 같은 위치 맨 아래에 모듈이 없는 경우 하나 더 설치 필요
|
// 해당 모듈과 같은 위치 맨 아래에 모듈이 없는 경우 하나 더 설치 필요
|
||||||
drawBracketWithOutRack(module, rackIntvlPct / 3, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
|
if (module.level % 2 === 0) {
|
||||||
|
drawBracketWithOutRack(module, rackIntvlPct / 3, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (rackQty === 4) {
|
if (rackQty === 4) {
|
||||||
drawBracketWithOutRack(module, rackIntvlPct / 3, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
|
drawBracketWithOutRack(module, rackIntvlPct / 3, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
|
||||||
@ -1627,6 +1647,8 @@ export const useTrestle = () => {
|
|||||||
// 랙 없음의 지지금구를 그린다.
|
// 랙 없음의 지지금구를 그린다.
|
||||||
const drawBracketWithOutRack = (module, rackIntvlPct, count, l, direction, moduleIntvlHor, moduleIntvlVer) => {
|
const drawBracketWithOutRack = (module, rackIntvlPct, count, l, direction, moduleIntvlHor, moduleIntvlVer) => {
|
||||||
const { leftFindModuleList, rightFindModuleList, centerFindModuleList } = module
|
const { leftFindModuleList, rightFindModuleList, centerFindModuleList } = module
|
||||||
|
rackIntvlPct = rackIntvlPct === 0 ? 1 : rackIntvlPct // 0인 경우 1로 변경
|
||||||
|
rackIntvlPct = 100 / rackIntvlPct // 퍼센트로 변경
|
||||||
|
|
||||||
let { width, height, left, top } = module
|
let { width, height, left, top } = module
|
||||||
let startPointX
|
let startPointX
|
||||||
@ -1641,14 +1663,14 @@ export const useTrestle = () => {
|
|||||||
break
|
break
|
||||||
} else if (direction === 'east') {
|
} else if (direction === 'east') {
|
||||||
startPointX = left + width
|
startPointX = left + width
|
||||||
startPointY = top + height - height / rackIntvlPct
|
startPointY = top + height - height / rackIntvlPct - 10
|
||||||
break
|
break
|
||||||
} else if (direction === 'west') {
|
} else if (direction === 'west') {
|
||||||
startPointX = left
|
startPointX = left
|
||||||
startPointY = top + height / rackIntvlPct
|
startPointY = top + height / rackIntvlPct
|
||||||
break
|
break
|
||||||
} else if (direction === 'north') {
|
} else if (direction === 'north') {
|
||||||
startPointX = left + width - width / rackIntvlPct
|
startPointX = left + width - width / rackIntvlPct - 10
|
||||||
startPointY = top
|
startPointY = top
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -1657,7 +1679,7 @@ export const useTrestle = () => {
|
|||||||
case 'R': {
|
case 'R': {
|
||||||
// 오른쪽부분 시작 점
|
// 오른쪽부분 시작 점
|
||||||
if (direction === 'south') {
|
if (direction === 'south') {
|
||||||
startPointX = left + width - width / rackIntvlPct
|
startPointX = left + width - width / rackIntvlPct - 10
|
||||||
startPointY = top + height / 2 + height / 2
|
startPointY = top + height / 2 + height / 2
|
||||||
break
|
break
|
||||||
} else if (direction === 'east') {
|
} else if (direction === 'east') {
|
||||||
@ -1666,7 +1688,7 @@ export const useTrestle = () => {
|
|||||||
break
|
break
|
||||||
} else if (direction === 'west') {
|
} else if (direction === 'west') {
|
||||||
startPointX = left
|
startPointX = left
|
||||||
startPointY = top + height - height / rackIntvlPct
|
startPointY = top + height - height / rackIntvlPct - 10
|
||||||
break
|
break
|
||||||
} else if (direction === 'north') {
|
} else if (direction === 'north') {
|
||||||
startPointX = left + width / rackIntvlPct
|
startPointX = left + width / rackIntvlPct
|
||||||
@ -2543,23 +2565,15 @@ export const useTrestle = () => {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// 가장 왼쪽에 있는 모듈을 기준으로 같은 단에 있는 모듈들 파라미터 생성
|
const getSameLineModules = (surface) => {
|
||||||
const getMostLeftModules = (surface, exposedBottomModules) => {
|
|
||||||
const { direction, modules, isChidory } = surface
|
const { direction, modules, isChidory } = surface
|
||||||
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
|
|
||||||
const roofMaterialIndex = parent.roofMaterial.index
|
|
||||||
const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
|
|
||||||
let isEaveBar = construction.setupCover
|
|
||||||
let isSnowGuard = construction.setupSnowCover
|
|
||||||
let { rackYn, cvrPlvrYn, moduleIntvlHor, moduleIntvlVer, rackQty, lessSupFitQty } = surface.trestleDetail
|
|
||||||
|
|
||||||
if (rackYn === 'N') {
|
if (!modules || modules.length === 0) {
|
||||||
rackQty = lessSupFitQty
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 같은 단에 있는 모듈들의 리스트
|
// 같은 단에 있는 모듈들의 리스트
|
||||||
let sameLineModuleList = []
|
let sameLineModuleList = []
|
||||||
let result = []
|
|
||||||
|
|
||||||
if (direction === 'south') {
|
if (direction === 'south') {
|
||||||
// 모듈의 top으로 groupBy
|
// 모듈의 top으로 groupBy
|
||||||
@ -2610,9 +2624,34 @@ export const useTrestle = () => {
|
|||||||
sameLineModuleList = Object.values(groupedByLeft).sort((a, b) => a[0].left - b[0].left)
|
sameLineModuleList = Object.values(groupedByLeft).sort((a, b) => a[0].left - b[0].left)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sameLineModuleList.forEach((modules, index) => {
|
||||||
|
modules.forEach((module) => {
|
||||||
|
module.set({ level: index + 1 }) // 각 모듈에 level 속성 추가
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return sameLineModuleList
|
||||||
|
}
|
||||||
|
|
||||||
|
// 가장 왼쪽에 있는 모듈을 기준으로 같은 단에 있는 모듈들 파라미터 생성
|
||||||
|
const getMostLeftModules = (surface, exposedBottomModules) => {
|
||||||
|
const { direction, modules, isChidory } = surface
|
||||||
|
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
|
||||||
|
const roofMaterialIndex = parent.roofMaterial.index
|
||||||
|
const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
|
||||||
|
let isEaveBar = construction.setupCover
|
||||||
|
let isSnowGuard = construction.setupSnowCover
|
||||||
|
let cvrLmtRow = construction.cvrLmtRow
|
||||||
|
let { rackYn, cvrPlvrYn, moduleIntvlHor, moduleIntvlVer, rackQty, lessSupFitQty } = surface.trestleDetail
|
||||||
|
let result = []
|
||||||
|
if (rackYn === 'N') {
|
||||||
|
rackQty = lessSupFitQty
|
||||||
|
}
|
||||||
|
const sameLineModuleList = getSameLineModules(surface, exposedBottomModules)
|
||||||
|
|
||||||
sameLineModuleList.forEach((modules, index) => {
|
sameLineModuleList.forEach((modules, index) => {
|
||||||
const moduleRowResultData = {
|
const moduleRowResultData = {
|
||||||
seq: index,
|
seq: index + 1,
|
||||||
moduleItemId: modules[0].moduleInfo.itemId,
|
moduleItemId: modules[0].moduleInfo.itemId,
|
||||||
moduleTpCd: modules[0].moduleInfo.itemTp,
|
moduleTpCd: modules[0].moduleInfo.itemTp,
|
||||||
moduleCnt: modules.length,
|
moduleCnt: modules.length,
|
||||||
@ -2644,6 +2683,7 @@ export const useTrestle = () => {
|
|||||||
}
|
}
|
||||||
// 모듈 하면,최하면 등 구해야함
|
// 모듈 하면,최하면 등 구해야함
|
||||||
modules.forEach((module, index) => {
|
modules.forEach((module, index) => {
|
||||||
|
const level = module.level
|
||||||
// 해당 모듈 주변에 다른 모듈이 있는지 확인
|
// 해당 모듈 주변에 다른 모듈이 있는지 확인
|
||||||
let {
|
let {
|
||||||
bottomModule,
|
bottomModule,
|
||||||
@ -2657,6 +2697,7 @@ export const useTrestle = () => {
|
|||||||
bottomLeftModule,
|
bottomLeftModule,
|
||||||
bottomRightModule,
|
bottomRightModule,
|
||||||
} = findSideModule(module, surface)
|
} = findSideModule(module, surface)
|
||||||
|
|
||||||
if (bottomModule) {
|
if (bottomModule) {
|
||||||
moduleRowResultData.touchedSurfaceCnt++
|
moduleRowResultData.touchedSurfaceCnt++
|
||||||
if (rackYn === 'N') {
|
if (rackYn === 'N') {
|
||||||
@ -2700,10 +2741,12 @@ export const useTrestle = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cvrPlvrYn === 'Y') {
|
if (cvrPlvrYn === 'Y') {
|
||||||
moduleRowResultData.eavesHalfCnt++
|
if (level <= cvrLmtRow) {
|
||||||
if (bottomLeftModule || bottomRightModule || halfBottomLeftModule || halfBottomRightModule) {
|
moduleRowResultData.eavesHalfCnt++
|
||||||
//처마커버 한개 노출 추가
|
if (bottomLeftModule || bottomRightModule || halfBottomLeftModule || halfBottomRightModule) {
|
||||||
moduleRowResultData.exposedSideEavesCnt++
|
//처마커버 한개 노출 추가
|
||||||
|
moduleRowResultData.exposedSideEavesCnt++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2712,13 +2755,15 @@ export const useTrestle = () => {
|
|||||||
moduleRowResultData.exposedBottomBracketCnt += rackQty
|
moduleRowResultData.exposedBottomBracketCnt += rackQty
|
||||||
}
|
}
|
||||||
if (isEaveBar) {
|
if (isEaveBar) {
|
||||||
moduleRowResultData.eavesCnt++
|
if (level <= cvrLmtRow) {
|
||||||
if ((rightModule && !leftModule) || (!rightModule && leftModule)) {
|
moduleRowResultData.eavesCnt++
|
||||||
// 둘중 하나가 없는경우는 처마커버 노출 추가
|
if ((rightModule && !leftModule) || (!rightModule && leftModule)) {
|
||||||
moduleRowResultData.exposedSideEavesCnt++
|
// 둘중 하나가 없는경우는 처마커버 노출 추가
|
||||||
} else if (!rightModule && !leftModule) {
|
moduleRowResultData.exposedSideEavesCnt++
|
||||||
// 양쪽 둘다 없는경우는 처마커버 노출 2개 추가
|
} else if (!rightModule && !leftModule) {
|
||||||
moduleRowResultData.exposedSideEavesCnt += 2
|
// 양쪽 둘다 없는경우는 처마커버 노출 2개 추가
|
||||||
|
moduleRowResultData.exposedSideEavesCnt += 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3077,6 +3122,9 @@ export const useTrestle = () => {
|
|||||||
// 배치면 전체에 가대 설치 여부
|
// 배치면 전체에 가대 설치 여부
|
||||||
const isAllComplete = () => {
|
const isAllComplete = () => {
|
||||||
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
||||||
|
if (surfaces.length === 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return surfaces.every((surface) => surface.isComplete)
|
return surfaces.every((surface) => surface.isComplete)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -199,6 +199,9 @@ export function useCanvasSetting(executeEffect = true) {
|
|||||||
if (!executeEffect) {
|
if (!executeEffect) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (roofMaterials.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
const selectedRoofMaterial = roofMaterials[0]
|
const selectedRoofMaterial = roofMaterials[0]
|
||||||
|
|
||||||
if (addedRoofs.length === 0) {
|
if (addedRoofs.length === 0) {
|
||||||
@ -495,11 +498,26 @@ export function useCanvasSetting(executeEffect = true) {
|
|||||||
roofSeq: 0,
|
roofSeq: 0,
|
||||||
roofMatlCd:
|
roofMatlCd:
|
||||||
params.roofsData.roofMatlCd === null || params.roofsData.roofMatlCd === undefined ? 'ROOF_ID_WA_53A' : params.roofsData.roofMatlCd,
|
params.roofsData.roofMatlCd === null || params.roofsData.roofMatlCd === undefined ? 'ROOF_ID_WA_53A' : params.roofsData.roofMatlCd,
|
||||||
roofWidth: params.roofsData.roofWidth === null || params.roofsData.roofWidth === undefined ? 0 : params.roofsData.roofWidth,
|
roofWidth:
|
||||||
roofHeight: params.roofsData.roofHeight === null || params.roofsData.roofHeight === undefined ? 0 : params.roofsData.roofHeight,
|
params.selectedRoofMaterial.width === null || params.selectedRoofMaterial.width === undefined
|
||||||
|
? !params.selectedRoofMaterial.widBase
|
||||||
|
? 0
|
||||||
|
: Number(params.roofsData.widBase)
|
||||||
|
: Number(params.selectedRoofMaterial.width),
|
||||||
|
roofHeight:
|
||||||
|
params.selectedRoofMaterial.height === null || params.selectedRoofMaterial.height === undefined
|
||||||
|
? !params.selectedRoofMaterial.lenBase
|
||||||
|
? 0
|
||||||
|
: Number(params.selectedRoofMaterial.lenBase)
|
||||||
|
: Number(params.roofsData.roofHeight),
|
||||||
roofHajebichi:
|
roofHajebichi:
|
||||||
params.roofsData.roofHajebichi === null || params.roofsData.roofHajebichi === undefined ? 0 : params.roofsData.roofHajebichi,
|
params.selectedRoofMaterial.hajebichi === null || params.selectedRoofMaterial.hajebichi === undefined
|
||||||
roofGap: params.roofsData.roofGap === null || params.roofsData.roofGap === undefined ? 'HEI_455' : params.roofsData.roofGap,
|
? 0
|
||||||
|
: Number(params.selectedRoofMaterial.hajebichi),
|
||||||
|
roofGap:
|
||||||
|
params.selectedRoofMaterial.raft === null || params.selectedRoofMaterial.raft === undefined
|
||||||
|
? params.selectedRoofMaterial.raftBaseCd
|
||||||
|
: params.roofsData.raft,
|
||||||
roofLayout: params.roofsData.roofLayout === null || params.roofsData.roofLayout === undefined ? 'P' : params.roofsData.roofLayout,
|
roofLayout: params.roofsData.roofLayout === null || params.roofsData.roofLayout === undefined ? 'P' : params.roofsData.roofLayout,
|
||||||
roofPitch: params.roofsData.roofPitch === null || params.roofsData.roofPitch === undefined ? 0 : params.roofsData.roofPitch,
|
roofPitch: params.roofsData.roofPitch === null || params.roofsData.roofPitch === undefined ? 0 : params.roofsData.roofPitch,
|
||||||
roofAngle: params.roofsData.roofAngle === null || params.roofsData.roofAngle === undefined ? 0 : params.roofsData.roofAngle,
|
roofAngle: params.roofsData.roofAngle === null || params.roofsData.roofAngle === undefined ? 0 : params.roofsData.roofAngle,
|
||||||
|
|||||||
@ -212,7 +212,6 @@ export function useRoofAllocationSetting(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await post({ url: `/api/canvas-management/roof-allocation-settings`, data: patternData }).then((res) => {
|
await post({ url: `/api/canvas-management/roof-allocation-settings`, data: patternData }).then((res) => {
|
||||||
swalFire({ text: getMessage(res.returnMessage) })
|
|
||||||
setIsGlobalLoading(false)
|
setIsGlobalLoading(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -315,7 +314,8 @@ export function useRoofAllocationSetting(id) {
|
|||||||
setSurfaceShapePattern(currentObject, roofDisplay.column, false, selectedRoofMaterial, true)
|
setSurfaceShapePattern(currentObject, roofDisplay.column, false, selectedRoofMaterial, true)
|
||||||
drawDirectionArrow(currentObject)
|
drawDirectionArrow(currentObject)
|
||||||
modifyModuleSelectionData()
|
modifyModuleSelectionData()
|
||||||
closeAll()
|
// closeAll()
|
||||||
|
closePopup(id)
|
||||||
basicSettingSave()
|
basicSettingSave()
|
||||||
setModuleSelectionData({ ...moduleSelectionData, roofConstructions: newRoofList })
|
setModuleSelectionData({ ...moduleSelectionData, roofConstructions: newRoofList })
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,22 @@
|
|||||||
import { useRef } from 'react'
|
import { useEffect, useRef } from 'react'
|
||||||
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
||||||
import { canvasState, canvasZoomState, currentMenuState, textModeState } from '@/store/canvasAtom'
|
import { canvasState, canvasZoomState, currentMenuState, textModeState } from '@/store/canvasAtom'
|
||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
import { calculateDistance, calculateDistancePoint, calculateIntersection, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util'
|
import {
|
||||||
|
calculateDistance,
|
||||||
|
calculateDistancePoint,
|
||||||
|
calculateIntersection,
|
||||||
|
distanceBetweenPoints,
|
||||||
|
findClosestPoint,
|
||||||
|
getInterSectionLineNotOverCoordinate,
|
||||||
|
} from '@/util/canvas-util'
|
||||||
import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint'
|
import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint'
|
||||||
import { useDotLineGrid } from '@/hooks/useDotLineGrid'
|
import { useDotLineGrid } from '@/hooks/useDotLineGrid'
|
||||||
import { useTempGrid } from '@/hooks/useTempGrid'
|
import { useTempGrid } from '@/hooks/useTempGrid'
|
||||||
import { gridColorState } from '@/store/gridAtom'
|
import { gridColorState } from '@/store/gridAtom'
|
||||||
import { gridDisplaySelector } from '@/store/settingAtom'
|
import { gridDisplaySelector } from '@/store/settingAtom'
|
||||||
import { POLYGON_TYPE } from '@/common/common'
|
import { MENU, POLYGON_TYPE } from '@/common/common'
|
||||||
|
import useMenu from '@/hooks/common/useMenu'
|
||||||
|
|
||||||
export function useEvent() {
|
export function useEvent() {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
@ -18,6 +26,7 @@ export function useEvent() {
|
|||||||
const setCanvasZoom = useSetRecoilState(canvasZoomState)
|
const setCanvasZoom = useSetRecoilState(canvasZoomState)
|
||||||
const gridColor = useRecoilValue(gridColorState)
|
const gridColor = useRecoilValue(gridColorState)
|
||||||
const isGridDisplay = useRecoilValue(gridDisplaySelector)
|
const isGridDisplay = useRecoilValue(gridDisplaySelector)
|
||||||
|
const zoom = useRecoilValue(canvasZoomState)
|
||||||
|
|
||||||
const { adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, getAdsorptionPoints, adsorptionPointAddModeStateEvent } = useAdsorptionPoint()
|
const { adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, getAdsorptionPoints, adsorptionPointAddModeStateEvent } = useAdsorptionPoint()
|
||||||
const { dotLineGridSetting, interval, getClosestLineGrid } = useDotLineGrid()
|
const { dotLineGridSetting, interval, getClosestLineGrid } = useDotLineGrid()
|
||||||
@ -52,6 +61,13 @@ export function useEvent() {
|
|||||||
addDefaultEvent()
|
addDefaultEvent()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const whiteMenus = [MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH, MENU.BATCH_CANVAS.OBJECT_BATCH, MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING]
|
||||||
|
if (canvas && !whiteMenus.includes(currentMenu)) {
|
||||||
|
addCanvasMouseEventListener('mouse:move', defaultMouseMoveEvent)
|
||||||
|
}
|
||||||
|
}, [zoom])
|
||||||
|
|
||||||
const addDefaultEvent = () => {
|
const addDefaultEvent = () => {
|
||||||
//default Event 추가
|
//default Event 추가
|
||||||
addCanvasMouseEventListener('mouse:move', defaultMouseMoveEvent)
|
addCanvasMouseEventListener('mouse:move', defaultMouseMoveEvent)
|
||||||
@ -146,13 +162,14 @@ export function useEvent() {
|
|||||||
...innerLinePoints,
|
...innerLinePoints,
|
||||||
]
|
]
|
||||||
|
|
||||||
if (dotLineGridSetting.LINE || canvas.getObjects().filter((obj) => ['lineGrid', 'tempGrid'].includes(obj.name)).length > 0) {
|
if (dotLineGridSetting.LINE || canvas.getObjects().filter((obj) => ['lineGrid', 'tempGrid'].includes(obj.name)).length > 1) {
|
||||||
const closestLine = getClosestLineGrid(pointer)
|
const closestLine = getClosestLineGrid(pointer)
|
||||||
|
|
||||||
const horizonLines = canvas.getObjects().filter((obj) => ['lineGrid', 'tempGrid'].includes(obj.name) && obj.direction === 'horizontal')
|
const horizonLines = canvas.getObjects().filter((obj) => ['lineGrid', 'tempGrid'].includes(obj.name) && obj.direction === 'horizontal')
|
||||||
const verticalLines = canvas.getObjects().filter((obj) => ['lineGrid', 'tempGrid'].includes(obj.name) && obj.direction === 'vertical')
|
const verticalLines = canvas.getObjects().filter((obj) => ['lineGrid', 'tempGrid'].includes(obj.name) && obj.direction === 'vertical')
|
||||||
|
|
||||||
if (!horizonLines || !verticalLines) {
|
if (!horizonLines || !verticalLines) {
|
||||||
|
drawMouseLine(pointer)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,6 +193,7 @@ export function useEvent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!closestVerticalLine || !closestHorizontalLine) {
|
if (!closestVerticalLine || !closestHorizontalLine) {
|
||||||
|
drawMouseLine(pointer)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,9 +278,18 @@ export function useEvent() {
|
|||||||
arrivalPoint = guideIntersectionPoint
|
arrivalPoint = guideIntersectionPoint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
|
||||||
const horizontalLine = new fabric.Line([-4 * canvas.width, arrivalPoint.y, 4 * canvas.width, arrivalPoint.y], {
|
drawMouseLine(arrivalPoint)
|
||||||
|
|
||||||
|
// 캔버스를 다시 그립니다.
|
||||||
|
canvas?.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
const drawMouseLine = (pointer) => {
|
||||||
|
const horizontalLine = new fabric.Line([-2 * canvas.width, pointer.y, 2 * canvas.width, pointer.y], {
|
||||||
stroke: 'red',
|
stroke: 'red',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
selectable: false,
|
selectable: false,
|
||||||
@ -270,7 +297,7 @@ export function useEvent() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 세로선
|
// 세로선
|
||||||
const verticalLine = new fabric.Line([arrivalPoint.x, -4 * canvas.height, arrivalPoint.x, 4 * canvas.height], {
|
const verticalLine = new fabric.Line([pointer.x, -2 * canvas.height, pointer.x, 2 * canvas.height], {
|
||||||
stroke: 'red',
|
stroke: 'red',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
selectable: false,
|
selectable: false,
|
||||||
@ -279,9 +306,6 @@ export function useEvent() {
|
|||||||
|
|
||||||
// 선들을 캔버스에 추가합니다.
|
// 선들을 캔버스에 추가합니다.
|
||||||
canvas?.add(horizontalLine, verticalLine)
|
canvas?.add(horizontalLine, verticalLine)
|
||||||
|
|
||||||
// 캔버스를 다시 그립니다.
|
|
||||||
canvas?.renderAll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeMouseLine = () => {
|
const removeMouseLine = () => {
|
||||||
@ -298,7 +322,12 @@ export function useEvent() {
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
//임의 그리드 모드일 경우
|
//임의 그리드 모드일 경우
|
||||||
let pointer = { x: e.offsetX, y: e.offsetY }
|
let originPointer = { x: e.offsetX, y: e.offsetY }
|
||||||
|
const mouseLines = canvas.getObjects().filter((obj) => obj.name === 'mouseLine')
|
||||||
|
let pointer = getInterSectionLineNotOverCoordinate(mouseLines[0], mouseLines[1]) || {
|
||||||
|
x: Math.round(originPointer.x),
|
||||||
|
y: Math.round(originPointer.y),
|
||||||
|
}
|
||||||
|
|
||||||
const tempGrid = new fabric.Line([-1500, pointer.y, 2500, pointer.y], {
|
const tempGrid = new fabric.Line([-1500, pointer.y, 2500, pointer.y], {
|
||||||
stroke: gridColor,
|
stroke: gridColor,
|
||||||
@ -372,7 +401,7 @@ export function useEvent() {
|
|||||||
const removeMouseEvent = (type) => {
|
const removeMouseEvent = (type) => {
|
||||||
mouseEventListeners.current = mouseEventListeners.current.filter((event) => {
|
mouseEventListeners.current = mouseEventListeners.current.filter((event) => {
|
||||||
if (event.eventType === type) {
|
if (event.eventType === type) {
|
||||||
canvas.off(type, event.handler)
|
canvas?.off(type, event.handler)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|||||||
@ -159,5 +159,6 @@ export const useLine = () => {
|
|||||||
addPitchText,
|
addPitchText,
|
||||||
removePitchText,
|
removePitchText,
|
||||||
addPitchTextsByOuterLines,
|
addPitchTextsByOuterLines,
|
||||||
|
getLengthByLine,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,9 +3,17 @@
|
|||||||
import { useContext, useEffect, useState } from 'react'
|
import { useContext, useEffect, useState } from 'react'
|
||||||
import { usePathname, useRouter } from 'next/navigation'
|
import { usePathname, useRouter } from 'next/navigation'
|
||||||
|
|
||||||
import { useRecoilState, useResetRecoilState } from 'recoil'
|
import { useRecoilState, useResetRecoilState, useSetRecoilState } from 'recoil'
|
||||||
|
|
||||||
import { canvasState, currentCanvasPlanState, plansState, canvasSettingState, currentObjectState, moduleSetupSurfaceState } from '@/store/canvasAtom'
|
import {
|
||||||
|
canvasState,
|
||||||
|
currentCanvasPlanState,
|
||||||
|
plansState,
|
||||||
|
canvasSettingState,
|
||||||
|
currentObjectState,
|
||||||
|
moduleSetupSurfaceState,
|
||||||
|
currentMenuState,
|
||||||
|
} from '@/store/canvasAtom'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
@ -22,6 +30,7 @@ import { useCanvasPopupStatusController } from './common/useCanvasPopupStatusCon
|
|||||||
import { useCanvasMenu } from './common/useCanvasMenu'
|
import { useCanvasMenu } from './common/useCanvasMenu'
|
||||||
import { QcastContext } from '@/app/QcastProvider'
|
import { QcastContext } from '@/app/QcastProvider'
|
||||||
import { unescapeString } from '@/util/common-utils'
|
import { unescapeString } from '@/util/common-utils'
|
||||||
|
import { useTrestle } from '@/hooks/module/useTrestle'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 플랜 처리 훅
|
* 플랜 처리 훅
|
||||||
@ -33,7 +42,7 @@ export function usePlan(params = {}) {
|
|||||||
const { floorPlanState } = useContext(FloorPlanContext)
|
const { floorPlanState } = useContext(FloorPlanContext)
|
||||||
|
|
||||||
const [selectedPlan, setSelectedPlan] = useState(null)
|
const [selectedPlan, setSelectedPlan] = useState(null)
|
||||||
|
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
||||||
const [canvas, setCanvas] = useRecoilState(canvasState)
|
const [canvas, setCanvas] = useRecoilState(canvasState)
|
||||||
|
|
||||||
const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState)
|
const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState)
|
||||||
@ -46,7 +55,7 @@ export function usePlan(params = {}) {
|
|||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { get, post, promisePost, promisePut, promiseDel, promiseGet } = useAxios()
|
const { get, post, promisePost, promisePut, promiseDel, promiseGet } = useAxios()
|
||||||
|
|
||||||
const { setEstimateContextState } = useEstimateController()
|
const { setEstimateContextState, handleDeleteEstimate, handleEstimateImageCopy } = useEstimateController()
|
||||||
|
|
||||||
const resetOuterLinePoints = useResetRecoilState(outerLinePointsState)
|
const resetOuterLinePoints = useResetRecoilState(outerLinePointsState)
|
||||||
const resetPlacementShapeDrawingPoints = useResetRecoilState(placementShapeDrawingPointsState)
|
const resetPlacementShapeDrawingPoints = useResetRecoilState(placementShapeDrawingPointsState)
|
||||||
@ -70,6 +79,7 @@ export function usePlan(params = {}) {
|
|||||||
const resetCurrentObject = useResetRecoilState(currentObjectState)
|
const resetCurrentObject = useResetRecoilState(currentObjectState)
|
||||||
//선택된 모듈 배치면 초기화
|
//선택된 모듈 배치면 초기화
|
||||||
const resetModuleSetupSurface = useResetRecoilState(moduleSetupSurfaceState)
|
const resetModuleSetupSurface = useResetRecoilState(moduleSetupSurfaceState)
|
||||||
|
const { isAllComplete } = useTrestle()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 마우스 포인터의 가이드라인 제거
|
* 마우스 포인터의 가이드라인 제거
|
||||||
@ -164,7 +174,11 @@ export function usePlan(params = {}) {
|
|||||||
*/
|
*/
|
||||||
const saveCanvas = async (saveAlert = true) => {
|
const saveCanvas = async (saveAlert = true) => {
|
||||||
const canvasStatus = currentCanvasData('save')
|
const canvasStatus = currentCanvasData('save')
|
||||||
await putCanvasStatus(canvasStatus, saveAlert)
|
const result = await putCanvasStatus(canvasStatus, saveAlert)
|
||||||
|
//캔버스 저장 완료 후
|
||||||
|
if (result && !isAllComplete()) {
|
||||||
|
handleDeleteEstimate(currentCanvasPlan)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -293,6 +307,9 @@ export function usePlan(params = {}) {
|
|||||||
setModuleSelectionDataStore(copyData)
|
setModuleSelectionDataStore(copyData)
|
||||||
if (copyData.module) setSelectedModules(copyData.module)
|
if (copyData.module) setSelectedModules(copyData.module)
|
||||||
setSelectedMenu(currentSelectedMenu)
|
setSelectedMenu(currentSelectedMenu)
|
||||||
|
|
||||||
|
//이미지 복사
|
||||||
|
handleEstimateImageCopy(planData.objectNo, planData.planNo, planData.objectNo, newPlan.planNo)
|
||||||
} else {
|
} else {
|
||||||
setSelectedMenu('placement')
|
setSelectedMenu('placement')
|
||||||
}
|
}
|
||||||
@ -310,20 +327,25 @@ export function usePlan(params = {}) {
|
|||||||
* @param {boolean} saveAlert - 저장 완료 알림 표시 여부
|
* @param {boolean} saveAlert - 저장 완료 알림 표시 여부
|
||||||
*/
|
*/
|
||||||
const putCanvasStatus = async (canvasStatus, saveAlert = true) => {
|
const putCanvasStatus = async (canvasStatus, saveAlert = true) => {
|
||||||
|
let rtn = false
|
||||||
const planData = {
|
const planData = {
|
||||||
id: currentCanvasPlan.id,
|
id: currentCanvasPlan.id,
|
||||||
bgImageName: currentCanvasPlan?.bgImageName ?? null,
|
bgImageName: currentCanvasPlan?.bgImageName ?? null,
|
||||||
mapPositionAddress: currentCanvasPlan?.mapPositionAddress ?? null,
|
mapPositionAddress: currentCanvasPlan?.mapPositionAddress ?? null,
|
||||||
canvasStatus: canvasToDbFormat(canvasStatus),
|
canvasStatus: canvasToDbFormat(canvasStatus),
|
||||||
}
|
}
|
||||||
|
|
||||||
await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData })
|
await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData })
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setPlans((plans) => plans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)))
|
setPlans((plans) => plans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)))
|
||||||
if (saveAlert) swalFire({ text: getMessage('plan.message.save') })
|
if (saveAlert) swalFire({ text: getMessage('plan.message.save') })
|
||||||
|
rtn = true
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
swalFire({ text: error.message, icon: 'error' })
|
swalFire({ text: error.message, icon: 'error' })
|
||||||
|
setIsGlobalLoading(false)
|
||||||
})
|
})
|
||||||
|
return rtn
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -577,8 +599,10 @@ export function usePlan(params = {}) {
|
|||||||
* plan canvasStatus 초기화
|
* plan canvasStatus 초기화
|
||||||
*/
|
*/
|
||||||
const resetCanvasStatus = () => {
|
const resetCanvasStatus = () => {
|
||||||
setCurrentCanvasPlan((prev) => ({ ...prev, canvasStatus: null }))
|
setCurrentCanvasPlan((prev) => ({ ...prev, canvasStatus: null, objectNo: null, planNo: null, id: null }))
|
||||||
setPlans((plans) => plans.map((plan) => ({ ...plan, canvasStatus: null })))
|
setPlans((plans) => plans.map((plan) => ({ ...plan, canvasStatus: null })))
|
||||||
|
setCurrentMenu(null)
|
||||||
|
setSelectedMenu(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -592,8 +616,10 @@ export function usePlan(params = {}) {
|
|||||||
if (pathname === '/floor-plan/estimate/5' || pathname === '/floor-plan/simulator/6') {
|
if (pathname === '/floor-plan/estimate/5' || pathname === '/floor-plan/simulator/6') {
|
||||||
await getCanvasByObjectNo(objectNo, planNo).then((res) => {
|
await getCanvasByObjectNo(objectNo, planNo).then((res) => {
|
||||||
if (res.length > 0) {
|
if (res.length > 0) {
|
||||||
setCurrentCanvasPlan((prev) => ({ ...prev, canvasStatus: res.find((plan) => plan.planNo === planNo).canvasStatus }))
|
// setCurrentCanvasPlan((prev) => ({ ...prev, canvasStatus: res.find((plan) => plan.planNo === planNo).canvasStatus }))
|
||||||
setPlans((plans) => plans.map((plan) => ({ ...plan, canvasStatus: res.find((resPlan) => resPlan.planNo === plan.planNo).canvasStatus })))
|
// setPlans((plans) => plans.map((plan) => ({ ...plan, canvasStatus: res.find((resPlan) => resPlan.planNo === plan.planNo).canvasStatus })))
|
||||||
|
setCurrentCanvasPlan(res.find((plan) => plan.planNo === planNo))
|
||||||
|
setPlans(res)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import { flowDisplaySelector } from '@/store/settingAtom'
|
|||||||
import { fontSelector } from '@/store/fontAtom'
|
import { fontSelector } from '@/store/fontAtom'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
|
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
|
||||||
|
import { useLine } from '@/hooks/useLine'
|
||||||
|
|
||||||
export const usePolygon = () => {
|
export const usePolygon = () => {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
@ -24,6 +25,8 @@ export const usePolygon = () => {
|
|||||||
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
|
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
|
||||||
const pitchText = useRecoilValue(pitchTextSelector)
|
const pitchText = useRecoilValue(pitchTextSelector)
|
||||||
|
|
||||||
|
const { getLengthByLine } = useLine()
|
||||||
|
|
||||||
const addPolygon = (points, options, isAddCanvas = true) => {
|
const addPolygon = (points, options, isAddCanvas = true) => {
|
||||||
const polygon = new QPolygon(points, {
|
const polygon = new QPolygon(points, {
|
||||||
...options,
|
...options,
|
||||||
@ -1093,25 +1096,37 @@ export const usePolygon = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (startFlag && endFlag) {
|
if (startFlag && endFlag) {
|
||||||
if (!representLines.includes(line)) {
|
if (!representLines.includes(line) && line.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
|
||||||
representLines.push(line)
|
representLines.push(line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// blue로 생성된 것들은 대표라인이 될 수 없음.
|
|
||||||
// representLines = representLines.filter((line) => line.stroke !== 'blue')
|
|
||||||
// representLines중 가장 긴 line을 찾는다.
|
// representLines중 가장 긴 line을 찾는다.
|
||||||
representLines.forEach((line) => {
|
representLines.forEach((line) => {
|
||||||
if (!representLine) {
|
if (!representLine) {
|
||||||
representLine = line
|
representLine = line
|
||||||
} else {
|
} else {
|
||||||
if (representLine.length < line.length) {
|
if (getLengthByLine(representLine) < getLengthByLine(line)) {
|
||||||
representLine = line
|
representLine = line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const direction = polygon.direction ?? representLine?.direction
|
|
||||||
|
if (!representLine) {
|
||||||
|
representLines = representLines.filter((line) => line.stroke !== 'blue')
|
||||||
|
representLines.forEach((line) => {
|
||||||
|
if (!representLine) {
|
||||||
|
representLine = line
|
||||||
|
} else {
|
||||||
|
if (representLine.length < line.length) {
|
||||||
|
representLine = line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const direction = polygon.direction ?? representLine?.direction ?? ''
|
||||||
const polygonDirection = polygon.direction
|
const polygonDirection = polygon.direction
|
||||||
|
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
@ -1178,7 +1193,7 @@ export const usePolygon = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
canvas.add(roof)
|
canvas.add(roof)
|
||||||
// addLengthText(roof)
|
addLengthText(roof)
|
||||||
canvas.remove(polygon)
|
canvas.remove(polygon)
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState, useResetRecoilState } from 'recoil'
|
||||||
import { contextPopupState, popupState } from '@/store/popupAtom'
|
import { contextPopupState, popupState } from '@/store/popupAtom'
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
import { commonUtilsState } from '@/store/commonUtilsAtom'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 팝업 관리 훅
|
* 팝업 관리 훅
|
||||||
@ -128,11 +130,17 @@ export function usePopup() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const targetClose = (type) => {
|
||||||
|
popup[type] = []
|
||||||
|
setPopup({ ...popup, [type]: [] })
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
popup,
|
popup,
|
||||||
addPopup,
|
addPopup,
|
||||||
closePopup,
|
closePopup,
|
||||||
closePopups,
|
closePopups,
|
||||||
closeAll,
|
closeAll,
|
||||||
|
targetClose,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { canvasState, tempGridModeState } from '@/store/canvasAtom'
|
|||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { gridColorState } from '@/store/gridAtom'
|
import { gridColorState } from '@/store/gridAtom'
|
||||||
import { gridDisplaySelector } from '@/store/settingAtom'
|
import { gridDisplaySelector } from '@/store/settingAtom'
|
||||||
|
import { useMouse } from '@/hooks/useMouse'
|
||||||
|
|
||||||
const GRID_PADDING = 5
|
const GRID_PADDING = 5
|
||||||
export function useTempGrid() {
|
export function useTempGrid() {
|
||||||
@ -9,10 +10,10 @@ export function useTempGrid() {
|
|||||||
const gridColor = useRecoilValue(gridColorState)
|
const gridColor = useRecoilValue(gridColorState)
|
||||||
const isGridDisplay = useRecoilValue(gridDisplaySelector)
|
const isGridDisplay = useRecoilValue(gridDisplaySelector)
|
||||||
const [tempGridMode, setTempGridMode] = useRecoilState(tempGridModeState)
|
const [tempGridMode, setTempGridMode] = useRecoilState(tempGridModeState)
|
||||||
|
const { getIntersectMousePoint } = useMouse()
|
||||||
const tempGridModeStateLeftClickEvent = (e) => {
|
const tempGridModeStateLeftClickEvent = (e) => {
|
||||||
//임의 그리드 모드일 경우
|
//임의 그리드 모드일 경우
|
||||||
let pointer = canvas.getPointer(e.e)
|
let pointer = getIntersectMousePoint(e)
|
||||||
|
|
||||||
const tempGrid = new fabric.Line([pointer.x, -1500, pointer.x, 2500], {
|
const tempGrid = new fabric.Line([pointer.x, -1500, pointer.x, 2500], {
|
||||||
stroke: gridColor,
|
stroke: gridColor,
|
||||||
|
|||||||
@ -612,11 +612,12 @@
|
|||||||
"qna.reg.header.contents": "お問い合わせ内容",
|
"qna.reg.header.contents": "お問い合わせ内容",
|
||||||
"qna.reg.header.fileList": "ファイル添付",
|
"qna.reg.header.fileList": "ファイル添付",
|
||||||
"qna.reg.header.save": "保存",
|
"qna.reg.header.save": "保存",
|
||||||
|
"qna.reg.alert.require.qstMail": "無効なメール形式です。",
|
||||||
"qna.reg.alert.require.regUserNm": "名前を入力してください。",
|
"qna.reg.alert.require.regUserNm": "名前を入力してください。",
|
||||||
"qna.reg.alert.select.type": "お問い合わせ区分を選択してください。",
|
"qna.reg.alert.select.type": "お問い合わせ区分を選択してください。",
|
||||||
"qna.reg.alert.require.title": "タイトルを入力してください。",
|
"qna.reg.alert.require.title": "タイトルを入力してください。",
|
||||||
"qna.reg.alert.require.contents": "内容を入力してください。",
|
"qna.reg.alert.require.contents": "内容を入力してください。",
|
||||||
"qna.reg.confirm.save": "1:1お問い合わせを登録しますか? <br/>Hanwha Japan 担当者にお問い合わせメールが送信されます。",
|
"qna.reg.confirm.save": "お問い合わせを登録しますか? <br/>Hanwha Japan 担当者にお問い合わせメールが送信されます。",
|
||||||
"qna.reg.alert.save": "保存されました。",
|
"qna.reg.alert.save": "保存されました。",
|
||||||
"qna.reg.alert.saveFail": "保存に失敗しました。",
|
"qna.reg.alert.saveFail": "保存に失敗しました。",
|
||||||
"qna.list.header.regNm": "登録者",
|
"qna.list.header.regNm": "登録者",
|
||||||
@ -665,9 +666,9 @@
|
|||||||
"join.sub1.title": "販売代理店情報",
|
"join.sub1.title": "販売代理店情報",
|
||||||
"join.sub1.comment": "※登録される販売店の会社名を入力してください。 (2次店は「○○販売株式会社(2次店:××設備株式会社)」でご記入ください。)",
|
"join.sub1.comment": "※登録される販売店の会社名を入力してください。 (2次店は「○○販売株式会社(2次店:××設備株式会社)」でご記入ください。)",
|
||||||
"join.sub1.storeQcastNm": "販売代理店名",
|
"join.sub1.storeQcastNm": "販売代理店名",
|
||||||
"join.sub1.storeQcastNm_placeholder": "株式会社エネルギーギアソリューションアンサービス(2次点:山口周期販売有限会社)",
|
"join.sub1.storeQcastNm_placeholder": "ハンファジャパン株式会社",
|
||||||
"join.sub1.storeQcastNmKana": "販売代理店名フリガナ",
|
"join.sub1.storeQcastNmKana": "販売代理店名フリガナ",
|
||||||
"join.sub1.storeQcastNmKana_placeholder": "株式会社エネルギーギアソリューション",
|
"join.sub1.storeQcastNmKana_placeholder": "ハンファジャパンカブシキカイシャ",
|
||||||
"join.sub1.postCd": "郵便番号",
|
"join.sub1.postCd": "郵便番号",
|
||||||
"join.sub1.postCd_placeholder": "数字7桁",
|
"join.sub1.postCd_placeholder": "数字7桁",
|
||||||
"join.sub1.addr": "住所",
|
"join.sub1.addr": "住所",
|
||||||
@ -680,7 +681,7 @@
|
|||||||
"join.sub2.title": "担当者情報",
|
"join.sub2.title": "担当者情報",
|
||||||
"join.sub2.userNm": "担当者名",
|
"join.sub2.userNm": "担当者名",
|
||||||
"join.sub2.userNmKana": "担当者名ふりがな",
|
"join.sub2.userNmKana": "担当者名ふりがな",
|
||||||
"join.sub2.userId": "申請ID",
|
"join.sub2.userId": "ユーザーID",
|
||||||
"join.sub2.email": "メールアドレス",
|
"join.sub2.email": "メールアドレス",
|
||||||
"join.sub2.telNo": "電話番号",
|
"join.sub2.telNo": "電話番号",
|
||||||
"join.sub2.telNo_placeholder": "00 0000 0000",
|
"join.sub2.telNo_placeholder": "00 0000 0000",
|
||||||
@ -688,12 +689,12 @@
|
|||||||
"join.sub2.fax_placeholder": "00 0000 0000",
|
"join.sub2.fax_placeholder": "00 0000 0000",
|
||||||
"join.sub2.category": "部署名",
|
"join.sub2.category": "部署名",
|
||||||
"join.btn.login_page": "ログイン画面に移動",
|
"join.btn.login_page": "ログイン画面に移動",
|
||||||
"join.btn.approval_request": "ID承認要求",
|
"join.btn.approval_request": "ID申請",
|
||||||
"join.complete.title": "HANASYS設計ログインID発行申請完了",
|
"join.complete.title": "HANASYS設計ログインID発行申請完了",
|
||||||
"join.complete.contents": "※申請したIDが承認されると、担当者情報に入力したEメールアドレスにログイン関連案内メールが送信されます。",
|
"join.complete.contents": "※申請したIDが承認されると、担当者情報に入力したEメールアドレスにログイン関連案内メールが送信されます。",
|
||||||
"join.complete.email_comment": "担当者のメールアドレス",
|
"join.complete.email_comment": "担当者のメールアドレス",
|
||||||
"join.validation.check1": "{0}形式を確認してください。",
|
"join.validation.check1": "{0}形式を確認してください。",
|
||||||
"join.complete.save.confirm": "ハンファジャパンの担当者にID承認が要求された場合、これ以上情報を修正することはできません。申請しますか?",
|
"join.complete.save.confirm": "ID申請を完了後は申請情報の修正が出来ません。申請しますか?",
|
||||||
"stuff.gridHeader.lastEditDatetime": "更新日時",
|
"stuff.gridHeader.lastEditDatetime": "更新日時",
|
||||||
"stuff.gridHeader.objectNo": "物件番号",
|
"stuff.gridHeader.objectNo": "物件番号",
|
||||||
"stuff.gridHeader.planTotCnt": "プラン数",
|
"stuff.gridHeader.planTotCnt": "プラン数",
|
||||||
@ -955,7 +956,7 @@
|
|||||||
"estimate.detail.dragFileGuide": "(※北面設置の場合、ファイル添付が必須です。)",
|
"estimate.detail.dragFileGuide": "(※北面設置の場合、ファイル添付が必須です。)",
|
||||||
"estimate.detail.header.fileList1": "ファイル添付",
|
"estimate.detail.header.fileList1": "ファイル添付",
|
||||||
"estimate.detail.fileList.btn": "ファイル選択",
|
"estimate.detail.fileList.btn": "ファイル選択",
|
||||||
"estimate.detail.fileList.extCheck": "画像ファイルのみ添付可能です。",
|
"estimate.detail.fileList.extCheck": "画像、PDF、Excel ファイルのみ添付できます。",
|
||||||
"estimate.detail.header.fileList2": "添付ファイル一覧",
|
"estimate.detail.header.fileList2": "添付ファイル一覧",
|
||||||
"estimate.detail.fileList2.btn.return": "復元",
|
"estimate.detail.fileList2.btn.return": "復元",
|
||||||
"estimate.detail.header.specialEstimate": "見積特記事項",
|
"estimate.detail.header.specialEstimate": "見積特記事項",
|
||||||
@ -1077,6 +1078,7 @@
|
|||||||
"module.not.found": "インストールモジュールを選択してください。",
|
"module.not.found": "インストールモジュールを選択してください。",
|
||||||
"module.circuit.minimun.error": "回路番号は1以上の数値を入力してください。",
|
"module.circuit.minimun.error": "回路番号は1以上の数値を入力してください。",
|
||||||
"module.already.exist.error": "回路番号が同じで異なるパワーコンディショナのモジュールがあります。 別の回路番号を設定してください。",
|
"module.already.exist.error": "回路番号が同じで異なるパワーコンディショナのモジュールがあります。 別の回路番号を設定してください。",
|
||||||
|
"module.circuit.fix.not.same.roof.error": "異なる屋根面のモジュールが選択されています。 モジュールの選択をや直してください。",
|
||||||
"construction.length.difference": "屋根面工法をすべて選択してください。",
|
"construction.length.difference": "屋根面工法をすべて選択してください。",
|
||||||
"menu.validation.canvas.roof": "パネルを配置するには、屋根面を入力する必要があります。",
|
"menu.validation.canvas.roof": "パネルを配置するには、屋根面を入力する必要があります。",
|
||||||
"batch.object.outside.roof": "オブジェクトは屋根に設置する必要があります。",
|
"batch.object.outside.roof": "オブジェクトは屋根に設置する必要があります。",
|
||||||
@ -1103,6 +1105,11 @@
|
|||||||
"module.layout.setup.max.count": "モジュールの単体での最大段数は{0}、最大列数は{1}です。 (JA)",
|
"module.layout.setup.max.count": "モジュールの単体での最大段数は{0}、最大列数は{1}です。 (JA)",
|
||||||
"module.layout.setup.max.count.multiple": "モジュール{0}の単体での最大段数は{1}、最大列数は{2}です。 (JA)",
|
"module.layout.setup.max.count.multiple": "モジュール{0}の単体での最大段数は{1}、最大列数は{2}です。 (JA)",
|
||||||
"roofAllocation.not.found": "割り当てる屋根がありません。 (JA)",
|
"roofAllocation.not.found": "割り当てる屋根がありません。 (JA)",
|
||||||
|
"modal.module.basic.setting.module.placement.info": "モジュール配置案内",
|
||||||
|
"modal.module.basic.setting.module.placement.info.batch": "千鳥配置を手動で行う際の注意事項",
|
||||||
|
"modal.module.basic.setting.module.placement.info.batch.content1": "千鳥配置する時に図のような配置ができてしまいますが、正常な積算ができません。",
|
||||||
|
"modal.module.basic.setting.module.placement.info.batch.content2": "千鳥で配置する時は、千鳥配置を「する」にして、モジュールが吸着されるようにして下さい。",
|
||||||
|
"modal.module.basic.setting.module.placement.info.module": "屋根材別 単一・混合モジュールの最大段数",
|
||||||
"modal.module.basic.setting.module.placement.max.size.check": "屋根材別モジュールの単体の単体での最大段数、2種混合の段数を確認して下さい",
|
"modal.module.basic.setting.module.placement.max.size.check": "屋根材別モジュールの単体の単体での最大段数、2種混合の段数を確認して下さい",
|
||||||
"modal.module.basic.setting.module.placement.max.row": "単体で\rの最大段数",
|
"modal.module.basic.setting.module.placement.max.row": "単体で\rの最大段数",
|
||||||
"modal.module.basic.setting.module.placement.max.rows.multiple": "2種混合時\rの最大段数",
|
"modal.module.basic.setting.module.placement.max.rows.multiple": "2種混合時\rの最大段数",
|
||||||
|
|||||||
@ -612,6 +612,7 @@
|
|||||||
"qna.reg.header.contents": "문의정보",
|
"qna.reg.header.contents": "문의정보",
|
||||||
"qna.reg.header.fileList": "파일첨부",
|
"qna.reg.header.fileList": "파일첨부",
|
||||||
"qna.reg.header.save": "저장",
|
"qna.reg.header.save": "저장",
|
||||||
|
"qna.reg.alert.require.qstMail": "올바르지 않은 이메일 형식입니다.",
|
||||||
"qna.reg.alert.require.regUserNm": "이름을 입력하세요.",
|
"qna.reg.alert.require.regUserNm": "이름을 입력하세요.",
|
||||||
"qna.reg.alert.select.type": "문의구분을 선택하세요.",
|
"qna.reg.alert.select.type": "문의구분을 선택하세요.",
|
||||||
"qna.reg.alert.require.title": "제목을 입력하세요.",
|
"qna.reg.alert.require.title": "제목을 입력하세요.",
|
||||||
@ -665,9 +666,9 @@
|
|||||||
"join.sub1.title": "판매대리점 정보",
|
"join.sub1.title": "판매대리점 정보",
|
||||||
"join.sub1.comment": "※ 등록되는 리셀러의 회사 이름을 입력하십시오. (2차점은 「○○판매주식회사(2차점:××설비주식회사)」로 기입해 주세요.)",
|
"join.sub1.comment": "※ 등록되는 리셀러의 회사 이름을 입력하십시오. (2차점은 「○○판매주식회사(2차점:××설비주식회사)」로 기입해 주세요.)",
|
||||||
"join.sub1.storeQcastNm": "판매대리점명",
|
"join.sub1.storeQcastNm": "판매대리점명",
|
||||||
"join.sub1.storeQcastNm_placeholder": "주식회사 에너지 기어 솔루션 앤 서비스 (2차점: 야마구치 주기 판매 유한회사)",
|
"join.sub1.storeQcastNm_placeholder": "한화재팬 주식회사",
|
||||||
"join.sub1.storeQcastNmKana": "판매대리점명 후리가나",
|
"join.sub1.storeQcastNmKana": "판매대리점명 후리가나",
|
||||||
"join.sub1.storeQcastNmKana_placeholder": "주식회사 에너지 기어 솔루션",
|
"join.sub1.storeQcastNmKana_placeholder": "한화재팬 카부시키 카이샤",
|
||||||
"join.sub1.postCd": "우편번호",
|
"join.sub1.postCd": "우편번호",
|
||||||
"join.sub1.postCd_placeholder": "숫자 7자리",
|
"join.sub1.postCd_placeholder": "숫자 7자리",
|
||||||
"join.sub1.addr": "주소",
|
"join.sub1.addr": "주소",
|
||||||
@ -680,7 +681,7 @@
|
|||||||
"join.sub2.title": "담당자 정보",
|
"join.sub2.title": "담당자 정보",
|
||||||
"join.sub2.userNm": "담당자명",
|
"join.sub2.userNm": "담당자명",
|
||||||
"join.sub2.userNmKana": "담당자명 후리가나",
|
"join.sub2.userNmKana": "담당자명 후리가나",
|
||||||
"join.sub2.userId": "신청 ID",
|
"join.sub2.userId": "사용자 ID",
|
||||||
"join.sub2.email": "이메일 주소",
|
"join.sub2.email": "이메일 주소",
|
||||||
"join.sub2.telNo": "전화번호",
|
"join.sub2.telNo": "전화번호",
|
||||||
"join.sub2.telNo_placeholder": "00 0000 0000",
|
"join.sub2.telNo_placeholder": "00 0000 0000",
|
||||||
@ -1104,6 +1105,11 @@
|
|||||||
"module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다.",
|
"module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다.",
|
||||||
"module.layout.setup.max.count.multiple": "모듈 {0}번의 최대 단수는 {1}, 최대 열수는 {2} 입니다.",
|
"module.layout.setup.max.count.multiple": "모듈 {0}번의 최대 단수는 {1}, 최대 열수는 {2} 입니다.",
|
||||||
"roofAllocation.not.found": "할당할 지붕이 없습니다.",
|
"roofAllocation.not.found": "할당할 지붕이 없습니다.",
|
||||||
|
"modal.module.basic.setting.module.placement.info": "모듈 배치 안내",
|
||||||
|
"modal.module.basic.setting.module.placement.info.batch": "치도리 수동 배치 시 유의사항",
|
||||||
|
"modal.module.basic.setting.module.placement.info.batch.content1": "치조 배치할 때 그림과 같은 배치가 되어 버립니다만, 정상적인 적산을 할 수 없습니다.",
|
||||||
|
"modal.module.basic.setting.module.placement.info.batch.content2": "치조로 배치할 때는, 치조 배치를 「한다」로 하고, 모듈이 흡착되도록 해 주세요.",
|
||||||
|
"modal.module.basic.setting.module.placement.info.module": "지붕재별 단일·혼합 모듈 최대 단수",
|
||||||
"modal.module.basic.setting.module.placement.max.size.check": "지붕재별 모듈 단체의 최대 단수, 2종 혼합 단수를 확인하십시오.",
|
"modal.module.basic.setting.module.placement.max.size.check": "지붕재별 모듈 단체의 최대 단수, 2종 혼합 단수를 확인하십시오.",
|
||||||
"modal.module.basic.setting.module.placement.max.row": "최대 단수",
|
"modal.module.basic.setting.module.placement.max.row": "최대 단수",
|
||||||
"modal.module.basic.setting.module.placement.max.rows.multiple": "2종 혼합 최대단수",
|
"modal.module.basic.setting.module.placement.max.rows.multiple": "2종 혼합 최대단수",
|
||||||
|
|||||||
@ -37,11 +37,11 @@ export const subMenusState = atom({
|
|||||||
// 지붕덮개
|
// 지붕덮개
|
||||||
{ id: 0, name: 'plan.menu.roof.cover.outline.drawing', menu: MENU.ROOF_COVERING.EXTERIOR_WALL_LINE },
|
{ id: 0, name: 'plan.menu.roof.cover.outline.drawing', menu: MENU.ROOF_COVERING.EXTERIOR_WALL_LINE },
|
||||||
{ id: 1, name: 'plan.menu.roof.cover.roof.shape.setting', menu: MENU.ROOF_COVERING.ROOF_SHAPE_SETTINGS },
|
{ id: 1, name: 'plan.menu.roof.cover.roof.shape.setting', menu: MENU.ROOF_COVERING.ROOF_SHAPE_SETTINGS },
|
||||||
{
|
// {
|
||||||
id: 2,
|
// id: 2,
|
||||||
name: 'plan.menu.roof.cover.roof.shape.passivity.setting',
|
// name: 'plan.menu.roof.cover.roof.shape.passivity.setting',
|
||||||
menu: MENU.ROOF_COVERING.ROOF_SHAPE_PASSIVITY_SETTINGS,
|
// menu: MENU.ROOF_COVERING.ROOF_SHAPE_PASSIVITY_SETTINGS,
|
||||||
},
|
// },
|
||||||
{ id: 3, name: 'plan.menu.roof.cover.auxiliary.line.drawing', menu: MENU.ROOF_COVERING.HELP_LINE_DRAWING },
|
{ id: 3, name: 'plan.menu.roof.cover.auxiliary.line.drawing', menu: MENU.ROOF_COVERING.HELP_LINE_DRAWING },
|
||||||
{ id: 4, name: 'plan.menu.roof.cover.eaves.kerava.edit', menu: MENU.ROOF_COVERING.EAVES_KERAVA_EDIT },
|
{ id: 4, name: 'plan.menu.roof.cover.eaves.kerava.edit', menu: MENU.ROOF_COVERING.EAVES_KERAVA_EDIT },
|
||||||
{ id: 5, name: 'plan.menu.roof.cover.movement.shape.updown', menu: MENU.ROOF_COVERING.MOVEMENT_SHAPE_UPDOWN },
|
{ id: 5, name: 'plan.menu.roof.cover.movement.shape.updown', menu: MENU.ROOF_COVERING.MOVEMENT_SHAPE_UPDOWN },
|
||||||
|
|||||||
@ -2457,3 +2457,22 @@ $alert-color: #101010;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2025-05-30 지붕 모듈
|
||||||
|
.roof-warning-img-wrap{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roof-content-tab-wrap{
|
||||||
|
display: flex;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
.hide-tab-contents{
|
||||||
|
&.hide{
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -447,10 +447,11 @@
|
|||||||
border-top: none;
|
border-top: none;
|
||||||
.community_detail-file-wrap{
|
.community_detail-file-wrap{
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
.community_detail-inner{
|
.community_detail-inner{
|
||||||
max-height: 110px;
|
max-height: 110px;
|
||||||
margin-top: 24px;
|
margin-top: 0;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -461,12 +462,14 @@
|
|||||||
border: 1px solid #101010;
|
border: 1px solid #101010;
|
||||||
.community_detail-inner{
|
.community_detail-inner{
|
||||||
max-height: 110px;
|
max-height: 110px;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
.community_detail-file-wrap{
|
.community_detail-file-wrap{
|
||||||
border-top: 1px solid #D4DCE7;
|
border-top: 1px solid #D4DCE7;
|
||||||
padding: 16px 0 0 0;
|
padding: 16px 0 0 0;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
startscript-cluster1.js
Normal file
2
startscript-cluster1.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
var exec = require('child_process').exec
|
||||||
|
exec('yarn start:cluster1', { windowsHide: true })
|
||||||
2
startscript-cluster2.js
Normal file
2
startscript-cluster2.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
var exec = require('child_process').exec
|
||||||
|
exec('yarn start:cluster2', { windowsHide: true })
|
||||||
2
startscript-dev.js
Normal file
2
startscript-dev.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
var exec = require('child_process').exec
|
||||||
|
exec('yarn start:dev', { windowsHide: true })
|
||||||
@ -1,2 +1,2 @@
|
|||||||
var exec = require('child_process').exec
|
var exec = require('child_process').exec
|
||||||
exec('yarn dev -p 5000', { windowsHide: true })
|
exec('yarn local:dev -p 5000', { windowsHide: true })
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user