Merge branch 'dev' of https://git.hanasys.jp/qcast3/qcast-front into dev
This commit is contained in:
commit
44508faf04
@ -21,6 +21,8 @@ const defaultEstimateData = {
|
|||||||
fileList: [],
|
fileList: [],
|
||||||
fileFlg: '0', //후일 자료 제출 (체크 1 노체크 0)
|
fileFlg: '0', //후일 자료 제출 (체크 1 노체크 0)
|
||||||
priceCd: '',
|
priceCd: '',
|
||||||
|
pricingFlag: false, // 가격 처리 플래그 추가
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -507,6 +507,7 @@ export default function Estimate({}) {
|
|||||||
icon: 'warning',
|
icon: 'warning',
|
||||||
confirmFn: () => {
|
confirmFn: () => {
|
||||||
handlePricing(showPriceCd)
|
handlePricing(showPriceCd)
|
||||||
|
setEstimateContextState({ pricingFlag:true })
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1437,7 +1438,7 @@ export default function Estimate({}) {
|
|||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
//주문분류
|
//주문분류
|
||||||
setHandlePricingFlag(true)
|
setHandlePricingFlag(true)
|
||||||
setEstimateContextState({ estimateType: e.target.value })
|
setEstimateContextState({ estimateType: e.target.value, setEstimateContextState })
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="YJSS">{getMessage('estimate.detail.estimateType.yjss')}</label>
|
<label htmlFor="YJSS">{getMessage('estimate.detail.estimateType.yjss')}</label>
|
||||||
|
|||||||
@ -130,7 +130,7 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen, docDown
|
|||||||
<div className="common-table">
|
<div className="common-table">
|
||||||
<table>
|
<table>
|
||||||
<colgroup>
|
<colgroup>
|
||||||
<col style={{ width: '260px' }} />
|
<col style={{ width: '220px' }} />
|
||||||
<col />
|
<col />
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|||||||
@ -701,14 +701,14 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
inPolygonImproved(point) {
|
inPolygonImproved(point) {
|
||||||
const vertices = this.points
|
const vertices = this.points
|
||||||
let inside = false
|
let inside = false
|
||||||
const testX = point.x
|
const testX = Number(point.x.toFixed(this.toFixed))
|
||||||
const testY = point.y
|
const testY = Number(point.y.toFixed(this.toFixed))
|
||||||
|
|
||||||
for (let i = 0, j = vertices.length - 1; i < vertices.length; j = i++) {
|
for (let i = 0, j = vertices.length - 1; i < vertices.length; j = i++) {
|
||||||
const xi = vertices[i].x
|
const xi = Number(vertices[i].x.toFixed(this.toFixed))
|
||||||
const yi = vertices[i].y
|
const yi = Number(vertices[i].y.toFixed(this.toFixed))
|
||||||
const xj = vertices[j].x
|
const xj = Number(vertices[j].x.toFixed(this.toFixed))
|
||||||
const yj = vertices[j].y
|
const yj = Number(vertices[j].y.toFixed(this.toFixed))
|
||||||
|
|
||||||
// 점이 정점 위에 있는지 확인
|
// 점이 정점 위에 있는지 확인
|
||||||
if (Math.abs(xi - testX) < 0.01 && Math.abs(yi - testY) < 0.01) {
|
if (Math.abs(xi - testX) < 0.01 && Math.abs(yi - testY) < 0.01) {
|
||||||
@ -720,10 +720,16 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ray casting 알고리즘
|
// Ray casting 알고리즘 - 부동소수점 정밀도 개선
|
||||||
if (((yi > testY) !== (yj > testY)) &&
|
if (yi > testY !== yj > testY) {
|
||||||
(testX < (xj - xi) * (testY - yi) / (yj - yi) + xi)) {
|
const denominator = yj - yi
|
||||||
inside = !inside
|
if (Math.abs(denominator) > 1e-10) {
|
||||||
|
// 0으로 나누기 방지
|
||||||
|
const intersection = ((xj - xi) * (testY - yi)) / denominator + xi
|
||||||
|
if (testX < intersection) {
|
||||||
|
inside = !inside
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -739,7 +745,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
|
|
||||||
// 벡터의 외적을 계산하여 점이 선분 위에 있는지 확인
|
// 벡터의 외적을 계산하여 점이 선분 위에 있는지 확인
|
||||||
const crossProduct = Math.abs(dxPoint * dySegment - dyPoint * dxSegment)
|
const crossProduct = Math.abs(dxPoint * dySegment - dyPoint * dxSegment)
|
||||||
|
|
||||||
if (crossProduct > tolerance) {
|
if (crossProduct > tolerance) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -747,7 +753,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
// 점이 선분의 범위 내에 있는지 확인
|
// 점이 선분의 범위 내에 있는지 확인
|
||||||
const dotProduct = dxPoint * dxSegment + dyPoint * dySegment
|
const dotProduct = dxPoint * dxSegment + dyPoint * dySegment
|
||||||
const squaredLength = dxSegment * dxSegment + dySegment * dySegment
|
const squaredLength = dxSegment * dxSegment + dySegment * dySegment
|
||||||
|
|
||||||
return dotProduct >= 0 && dotProduct <= squaredLength
|
return dotProduct >= 0 && dotProduct <= squaredLength
|
||||||
},
|
},
|
||||||
setCoords: function () {
|
setCoords: function () {
|
||||||
@ -792,13 +798,15 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
// pathOffset을 고려한 최종 좌표 계산
|
// pathOffset을 고려한 최종 좌표 계산
|
||||||
const pathOffset = this.get('pathOffset')
|
const pathOffset = this.get('pathOffset')
|
||||||
const finalPoint = {
|
const finalPoint = {
|
||||||
x: transformedPoint.x + pathOffset.x,
|
x: Number((transformedPoint.x + pathOffset.x).toFixed(this.toFixed)),
|
||||||
y: transformedPoint.y + pathOffset.y,
|
y: Number((transformedPoint.y + pathOffset.y).toFixed(this.toFixed)),
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.name === POLYGON_TYPE.ROOF && this.isFixed) {
|
if (this.name === POLYGON_TYPE.ROOF && this.isFixed) {
|
||||||
const isInside = this.inPolygonImproved(finalPoint)
|
const isInside = this.inPolygonImproved(finalPoint)
|
||||||
this.set('selectable', isInside)
|
if (!this.selectable) {
|
||||||
|
this.set('selectable', isInside)
|
||||||
|
}
|
||||||
return isInside
|
return isInside
|
||||||
} else {
|
} else {
|
||||||
return this.inPolygonImproved(finalPoint)
|
return this.inPolygonImproved(finalPoint)
|
||||||
|
|||||||
@ -167,13 +167,34 @@ export const useEstimateController = (planNo, flag) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//견적서 저장
|
|
||||||
const handleEstimateSubmit = async () => {
|
const handleEstimateSubmit = async () => {
|
||||||
|
if(estimateContextState.pricingFlag) {
|
||||||
|
await handleEstimateSubmitCore();
|
||||||
|
}else {
|
||||||
|
swalFire({
|
||||||
|
text: getMessage('estimate.detail.save.pricingFlag'),
|
||||||
|
type: 'confirm',
|
||||||
|
icon: 'warning',
|
||||||
|
confirmFn: async () => {
|
||||||
|
await handleEstimateSubmitCore();
|
||||||
|
|
||||||
|
},
|
||||||
|
denyFn: () => false
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//견적서 저장
|
||||||
|
const handleEstimateSubmitCore = async () => {
|
||||||
//0. 필수체크
|
//0. 필수체크
|
||||||
let flag = true
|
let flag = true
|
||||||
let originFileFlg = false
|
let originFileFlg = false
|
||||||
let fileFlg = true
|
let fileFlg = true
|
||||||
let itemFlg = true
|
let itemFlg = true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (estimateData?.charger === null || estimateData?.charger?.trim().length === 0) {
|
if (estimateData?.charger === null || estimateData?.charger?.trim().length === 0) {
|
||||||
flag = false
|
flag = false
|
||||||
setIsGlobalLoading(false)
|
setIsGlobalLoading(false)
|
||||||
@ -355,6 +376,8 @@ export const useEstimateController = (planNo, flag) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const realSave = async (fileList) => {
|
const realSave = async (fileList) => {
|
||||||
|
|
||||||
|
setEstimateContextState({pricingFlag: false})
|
||||||
//첨부파일저장끝
|
//첨부파일저장끝
|
||||||
|
|
||||||
let option = []
|
let option = []
|
||||||
|
|||||||
@ -44,7 +44,7 @@ export function useImgLoader() {
|
|||||||
*/
|
*/
|
||||||
const handleCanvasToPng = async (type) => {
|
const handleCanvasToPng = async (type) => {
|
||||||
try {
|
try {
|
||||||
removeMouseLines()
|
toggleLineEtc(false)
|
||||||
|
|
||||||
canvas.getObjects('image').forEach((obj) => {
|
canvas.getObjects('image').forEach((obj) => {
|
||||||
if (obj.getSrc) {
|
if (obj.getSrc) {
|
||||||
@ -86,6 +86,8 @@ export function useImgLoader() {
|
|||||||
})
|
})
|
||||||
console.log('🚀 ~ handleCanvasToPng ~ result:', result)
|
console.log('🚀 ~ handleCanvasToPng ~ result:', result)
|
||||||
|
|
||||||
|
toggleLineEtc(true)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setIsGlobalLoading(false)
|
setIsGlobalLoading(false)
|
||||||
@ -94,13 +96,21 @@ export function useImgLoader() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 마우스 포인터의 가이드라인을 제거합니다.
|
* 마우스 포인터 그리드, 임의그리드, 흡착점 등 제거.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
const removeMouseLines = () => {
|
const toggleLineEtc = (visible = false) => {
|
||||||
if (canvas?._objects.length > 0) {
|
if (canvas?._objects.length > 0) {
|
||||||
const mouseLines = canvas?._objects.filter((obj) => obj.name === 'mouseLine')
|
const mouseLines = canvas?._objects.filter((obj) => obj.name === 'mouseLine')
|
||||||
mouseLines.forEach((item) => canvas?.remove(item))
|
mouseLines.forEach((item) => canvas?.remove(item))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const adsorptionPoints = canvas?._objects.filter((obj) => obj.name === 'adsorptionPoint')
|
||||||
|
const gridLines = canvas?._objects.filter((obj) => obj.name === 'lineGrid' || obj.name === 'tempGrid' || obj.name === 'dotGrid')
|
||||||
|
|
||||||
|
adsorptionPoints.forEach((item) => item.set({ visible: visible }))
|
||||||
|
gridLines.forEach((item) => item.set({ visible: visible }))
|
||||||
|
|
||||||
canvas?.renderAll()
|
canvas?.renderAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -32,7 +32,10 @@ export const useTrestle = () => {
|
|||||||
const apply = () => {
|
const apply = () => {
|
||||||
const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit)
|
const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit)
|
||||||
if (notAllocationModules.length > 0) {
|
if (notAllocationModules.length > 0) {
|
||||||
swalFire({ text: '回路番号が設定されていないモジュールがあります。 番号を設定しなおすか、 パネルを削除してください。', icon: 'error' })
|
swalFire({
|
||||||
|
text: '回路番号が設定されていないモジュールがあります。 番号を設定しなおすか、 パネルを削除してください。',
|
||||||
|
icon: 'error',
|
||||||
|
})
|
||||||
setIsGlobalLoading(false)
|
setIsGlobalLoading(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -807,15 +810,12 @@ export const useTrestle = () => {
|
|||||||
const getAzimuth = (parent) => {
|
const getAzimuth = (parent) => {
|
||||||
const { moduleCompass, surfaceCompass, direction } = parent
|
const { moduleCompass, surfaceCompass, direction } = parent
|
||||||
|
|
||||||
if(surfaceCompass) {
|
if (surfaceCompass) {
|
||||||
return -surfaceCompass
|
return -surfaceCompass
|
||||||
}
|
}
|
||||||
|
|
||||||
let resultAzimuth = moduleCompass
|
let resultAzimuth = moduleCompass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case 'south': {
|
case 'south': {
|
||||||
return resultAzimuth
|
return resultAzimuth
|
||||||
@ -1882,7 +1882,15 @@ export const useTrestle = () => {
|
|||||||
const { width, height } = { ...module }
|
const { width, height } = { ...module }
|
||||||
widthArr.push(width)
|
widthArr.push(width)
|
||||||
heightArr.push(height)
|
heightArr.push(height)
|
||||||
centerPoints.push({ x, y, width: Math.floor(width), height: Math.floor(height), index, moduleInfo: module.moduleInfo, module })
|
centerPoints.push({
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width: Math.floor(width),
|
||||||
|
height: Math.floor(height),
|
||||||
|
index,
|
||||||
|
moduleInfo: module.moduleInfo,
|
||||||
|
module,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
//widthArr 중복 제거 1이상 차이가 나지 않으면 같은 너비로 간주
|
//widthArr 중복 제거 1이상 차이가 나지 않으면 같은 너비로 간주
|
||||||
@ -2055,8 +2063,8 @@ export const useTrestle = () => {
|
|||||||
/**
|
/**
|
||||||
* 디버깅용
|
* 디버깅용
|
||||||
|
|
||||||
module.set('fill', originFill)
|
module.set('fill', originFill)
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
*/
|
*/
|
||||||
if (bottomCell) {
|
if (bottomCell) {
|
||||||
return
|
return
|
||||||
@ -2182,8 +2190,8 @@ export const useTrestle = () => {
|
|||||||
/**
|
/**
|
||||||
* 디버깅 용
|
* 디버깅 용
|
||||||
|
|
||||||
module.set('fill', originFill)
|
module.set('fill', originFill)
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (leftTopCnt + rightTopCnt === 2) {
|
if (leftTopCnt + rightTopCnt === 2) {
|
||||||
@ -3265,18 +3273,49 @@ export const useTrestle = () => {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function countMatchingCircuitNumbers(arrays) {
|
||||||
|
let cnt = 0
|
||||||
|
|
||||||
|
// 모든 고유한 circuitNumber 찾기
|
||||||
|
const allCircuitNumbers = new Set()
|
||||||
|
arrays.forEach((arr) => {
|
||||||
|
arr.forEach((item) => {
|
||||||
|
allCircuitNumbers.add(item.circuitNumber)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// 각 circuitNumber가 몇 개의 배열에 나타나는지 세기
|
||||||
|
allCircuitNumbers.forEach((circuitNum) => {
|
||||||
|
let arrayCount = 0
|
||||||
|
|
||||||
|
arrays.forEach((arr) => {
|
||||||
|
const hasCircuitNum = arr.some((item) => item.circuitNumber === circuitNum)
|
||||||
|
if (hasCircuitNum) {
|
||||||
|
arrayCount++
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 2개 이상의 배열에 나타나는 경우에만 카운트 (배열 개수 - 1)
|
||||||
|
if (arrayCount >= 2) {
|
||||||
|
cnt += arrayCount - 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return cnt
|
||||||
|
}
|
||||||
|
|
||||||
// 양단 케이블 구하는 공식
|
// 양단 케이블 구하는 공식
|
||||||
const getTotalConnectCableCnt = () => {
|
const getTotalConnectCableCnt = () => {
|
||||||
let cnt = 0
|
let cnt = 0
|
||||||
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)
|
||||||
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
|
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
|
||||||
|
|
||||||
surfaces.forEach((surface) => {
|
surfaces.forEach((surface) => {
|
||||||
const modules = surface.modules
|
const modules = surface.modules
|
||||||
const groups = groupByType(modules)
|
// 1. 현재 surface의 모듈들을 그룹화
|
||||||
groups.forEach((group) => {
|
const groupInSurface = groupPoints(modules, surface)
|
||||||
const result = groupPoints(group, surface)
|
|
||||||
cnt += result.length - 1
|
cnt += countMatchingCircuitNumbers(groupInSurface)
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const groupByCircuitAndSurfaceCnt = groupByCircuitAndSurface(modules)
|
const groupByCircuitAndSurfaceCnt = groupByCircuitAndSurface(modules)
|
||||||
|
|||||||
@ -1,18 +1,17 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { useEffect, useRef } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
import { BATCH_TYPE, INPUT_TYPE, POLYGON_TYPE } from '@/common/common'
|
import { BATCH_TYPE, INPUT_TYPE, POLYGON_TYPE } from '@/common/common'
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
import {
|
import {
|
||||||
|
getDegreeByChon,
|
||||||
|
getTrianglePoints,
|
||||||
pointsToTurfPolygon,
|
pointsToTurfPolygon,
|
||||||
polygonToTurfPolygon,
|
polygonToTurfPolygon,
|
||||||
rectToPolygon,
|
rectToPolygon,
|
||||||
triangleToPolygon,
|
|
||||||
getDegreeByChon,
|
|
||||||
toFixedWithoutRounding,
|
toFixedWithoutRounding,
|
||||||
getTrianglePoints,
|
|
||||||
} from '@/util/canvas-util'
|
} from '@/util/canvas-util'
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
import * as turf from '@turf/turf'
|
import * as turf from '@turf/turf'
|
||||||
@ -23,6 +22,7 @@ import { fontSelector } from '@/store/fontAtom'
|
|||||||
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
||||||
import { roofDisplaySelector } from '@/store/settingAtom'
|
import { roofDisplaySelector } from '@/store/settingAtom'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useMouse } from '@/hooks/useMouse'
|
||||||
|
|
||||||
export function useObjectBatch({ isHidden, setIsHidden }) {
|
export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
@ -35,6 +35,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
|||||||
const lengthTextFont = useRecoilValue(fontSelector('lengthText'))
|
const lengthTextFont = useRecoilValue(fontSelector('lengthText'))
|
||||||
const roofDisplay = useRecoilValue(roofDisplaySelector)
|
const roofDisplay = useRecoilValue(roofDisplaySelector)
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
const { getIntersectMousePoint } = useMouse()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
@ -59,7 +60,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
|||||||
console.log('event', e)
|
console.log('event', e)
|
||||||
|
|
||||||
if (e.target && e.target instanceof fabric.Group) {
|
if (e.target && e.target instanceof fabric.Group) {
|
||||||
const pointer = canvas.getPointer(e.e)
|
const pointer = getIntersectMousePoint(e)
|
||||||
const objects = e.target._objects
|
const objects = e.target._objects
|
||||||
|
|
||||||
// 클릭한 위치에 있는 객체 찾기
|
// 클릭한 위치에 있는 객체 찾기
|
||||||
@ -98,7 +99,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
|||||||
if (selectedType === INPUT_TYPE.FREE) {
|
if (selectedType === INPUT_TYPE.FREE) {
|
||||||
addCanvasMouseEventListener('mouse:down', (e) => {
|
addCanvasMouseEventListener('mouse:down', (e) => {
|
||||||
isDown = true
|
isDown = true
|
||||||
const pointer = canvas.getPointer(e.e)
|
const pointer = getIntersectMousePoint(e)
|
||||||
|
|
||||||
surfaceShapePolygons.forEach((surface) => {
|
surfaceShapePolygons.forEach((surface) => {
|
||||||
if (surface.inPolygon({ x: pointer.x, y: pointer.y })) {
|
if (surface.inPolygon({ x: pointer.x, y: pointer.y })) {
|
||||||
@ -140,7 +141,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
|||||||
if (!isDown) return
|
if (!isDown) return
|
||||||
|
|
||||||
if (selectedSurface) {
|
if (selectedSurface) {
|
||||||
const pointer = canvas.getPointer(e.e)
|
const pointer = getIntersectMousePoint(e)
|
||||||
const width = pointer.x - origX
|
const width = pointer.x - origX
|
||||||
const height = pointer.y - origY
|
const height = pointer.y - origY
|
||||||
|
|
||||||
@ -208,7 +209,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
|||||||
if (!isDown) return
|
if (!isDown) return
|
||||||
|
|
||||||
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === objTempName)) //움직일때 일단 지워가면서 움직임
|
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === objTempName)) //움직일때 일단 지워가면서 움직임
|
||||||
const pointer = canvas.getPointer(e.e)
|
const pointer = getIntersectMousePoint(e)
|
||||||
|
|
||||||
surfaceShapePolygons.forEach((surface) => {
|
surfaceShapePolygons.forEach((surface) => {
|
||||||
if (surface.inPolygon({ x: pointer.x, y: pointer.y })) {
|
if (surface.inPolygon({ x: pointer.x, y: pointer.y })) {
|
||||||
@ -220,8 +221,8 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
|||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
left: pointer.x - width / 2,
|
left: pointer.x,
|
||||||
top: pointer.y - height / 2,
|
top: pointer.y,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
lockMovementX: true,
|
lockMovementX: true,
|
||||||
lockMovementY: true,
|
lockMovementY: true,
|
||||||
@ -329,7 +330,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
|||||||
if (!isDown) return
|
if (!isDown) return
|
||||||
|
|
||||||
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === dormerTempName)) //움직일때 일단 지워가면서 움직임
|
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === dormerTempName)) //움직일때 일단 지워가면서 움직임
|
||||||
const pointer = canvas.getPointer(e.e)
|
const pointer = getIntersectMousePoint(e)
|
||||||
|
|
||||||
surfaceShapePolygons.forEach((surface) => {
|
surfaceShapePolygons.forEach((surface) => {
|
||||||
if (surface.inPolygon({ x: pointer.x, y: pointer.y })) {
|
if (surface.inPolygon({ x: pointer.x, y: pointer.y })) {
|
||||||
@ -679,7 +680,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
|||||||
if (!isDown) return
|
if (!isDown) return
|
||||||
|
|
||||||
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === dormerTempName)) //움직일때 일단 지워가면서 움직임
|
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === dormerTempName)) //움직일때 일단 지워가면서 움직임
|
||||||
const pointer = canvas.getPointer(e.e)
|
const pointer = getIntersectMousePoint(e)
|
||||||
|
|
||||||
surfaceShapePolygons.forEach((surface) => {
|
surfaceShapePolygons.forEach((surface) => {
|
||||||
if (surface.inPolygon({ x: pointer.x, y: pointer.y })) {
|
if (surface.inPolygon({ x: pointer.x, y: pointer.y })) {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { useSwal } from '@/hooks/useSwal'
|
|||||||
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
|
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
|
||||||
import Big from 'big.js'
|
import Big from 'big.js'
|
||||||
import { calcLinePlaneSize } from '@/util/qpolygon-utils'
|
import { calcLinePlaneSize } from '@/util/qpolygon-utils'
|
||||||
|
import { useMouse } from '@/hooks/useMouse'
|
||||||
|
|
||||||
//동선이동 형 올림 내림
|
//동선이동 형 올림 내림
|
||||||
export function useMovementSetting(id) {
|
export function useMovementSetting(id) {
|
||||||
@ -19,6 +20,7 @@ export function useMovementSetting(id) {
|
|||||||
const { initEvent, addCanvasMouseEventListener } = useEvent()
|
const { initEvent, addCanvasMouseEventListener } = useEvent()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const { getIntersectMousePoint } = useMouse()
|
||||||
const currentObject = useRecoilValue(currentObjectState)
|
const currentObject = useRecoilValue(currentObjectState)
|
||||||
const selectedObject = useRef(null)
|
const selectedObject = useRef(null)
|
||||||
const buttonType = [
|
const buttonType = [
|
||||||
@ -180,7 +182,7 @@ export function useMovementSetting(id) {
|
|||||||
FOLLOW_LINE_REF.current = followLine
|
FOLLOW_LINE_REF.current = followLine
|
||||||
|
|
||||||
canvas.on('mouse:move', (event) => {
|
canvas.on('mouse:move', (event) => {
|
||||||
const mousePos = canvas.getPointer(event.e)
|
const mousePos = getIntersectMousePoint(event)
|
||||||
if (followLine.x1 === followLine.x2) {
|
if (followLine.x1 === followLine.x2) {
|
||||||
followLine.left = mousePos.x - 2
|
followLine.left = mousePos.x - 2
|
||||||
} else {
|
} else {
|
||||||
@ -212,8 +214,8 @@ export function useMovementSetting(id) {
|
|||||||
if (!target) return
|
if (!target) return
|
||||||
|
|
||||||
const { top: targetTop, left: targetLeft } = target
|
const { top: targetTop, left: targetLeft } = target
|
||||||
const currentX = Big(canvas.getPointer(e.e).x).round(0, Big.roundUp)
|
const currentX = Big(getIntersectMousePoint(e).x).round(0, Big.roundUp)
|
||||||
const currentY = Big(canvas.getPointer(e.e).y).round(0, Big.roundUp)
|
const currentY = Big(getIntersectMousePoint(e).y).round(0, Big.roundUp)
|
||||||
let value = ''
|
let value = ''
|
||||||
if (target.y1 === target.y2) {
|
if (target.y1 === target.y2) {
|
||||||
value = Big(targetTop).minus(currentY).times(10)
|
value = Big(targetTop).minus(currentY).times(10)
|
||||||
@ -415,7 +417,12 @@ export function useMovementSetting(id) {
|
|||||||
startPoint: { x: currentLine.x1 + deltaX, y: currentLine.y1 + deltaY },
|
startPoint: { x: currentLine.x1 + deltaX, y: currentLine.y1 + deltaY },
|
||||||
endPoint: { x: currentLine.x2 + deltaX, y: currentLine.y2 + deltaY },
|
endPoint: { x: currentLine.x2 + deltaX, y: currentLine.y2 + deltaY },
|
||||||
})
|
})
|
||||||
const currentSize = calcLinePlaneSize({ x1: currentLine.x1, y1: currentLine.y1, x2: currentLine.x2, y2: currentLine.y2 })
|
const currentSize = calcLinePlaneSize({
|
||||||
|
x1: currentLine.x1,
|
||||||
|
y1: currentLine.y1,
|
||||||
|
x2: currentLine.x2,
|
||||||
|
y2: currentLine.y2,
|
||||||
|
})
|
||||||
currentLine.attributes.planeSize = currentSize
|
currentLine.attributes.planeSize = currentSize
|
||||||
currentLine.attributes.actualSize = currentSize
|
currentLine.attributes.actualSize = currentSize
|
||||||
|
|
||||||
|
|||||||
@ -241,7 +241,11 @@ export function useRoofShapeSetting(id) {
|
|||||||
outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||||
let isValid = outerLines.every((line) => line.attributes?.isFixed)
|
let isValid = outerLines.every((line) => line.attributes?.isFixed)
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
swalFire({ text: getMessage('modal.canvas.setting.roofline.properties.setting.not.setting'), type: 'alert', icon: 'warning' })
|
swalFire({
|
||||||
|
text: getMessage('modal.canvas.setting.roofline.properties.setting.not.setting'),
|
||||||
|
type: 'alert',
|
||||||
|
icon: 'warning',
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const pitch = outerLines.find((line) => line.attributes.type === LINE_TYPE.WALLLINE.SHED)?.attributes.pitch
|
const pitch = outerLines.find((line) => line.attributes.type === LINE_TYPE.WALLLINE.SHED)?.attributes.pitch
|
||||||
@ -497,7 +501,13 @@ export function useRoofShapeSetting(id) {
|
|||||||
canvas.remove(obj)
|
canvas.remove(obj)
|
||||||
})
|
})
|
||||||
|
|
||||||
const polygon = addPolygonByLines(outerLines, { name: POLYGON_TYPE.WALL, direction, originX: 'center', originY: 'center' })
|
const polygon = addPolygonByLines(outerLines, {
|
||||||
|
name: POLYGON_TYPE.WALL,
|
||||||
|
direction,
|
||||||
|
originX: 'center',
|
||||||
|
originY: 'center',
|
||||||
|
})
|
||||||
|
polygon.setViewLengthText(false)
|
||||||
polygon.lines = [...outerLines]
|
polygon.lines = [...outerLines]
|
||||||
|
|
||||||
addPitchTextsByOuterLines()
|
addPitchTextsByOuterLines()
|
||||||
|
|||||||
@ -16,6 +16,7 @@ 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 { MENU, POLYGON_TYPE } from '@/common/common'
|
import { MENU, POLYGON_TYPE } from '@/common/common'
|
||||||
|
import { useMouse } from '@/hooks/useMouse'
|
||||||
|
|
||||||
export function useEvent() {
|
export function useEvent() {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
@ -35,6 +36,8 @@ export function useEvent() {
|
|||||||
|
|
||||||
const textMode = useRecoilValue(textModeState)
|
const textMode = useRecoilValue(textModeState)
|
||||||
|
|
||||||
|
const { getIntersectMousePoint } = useMouse()
|
||||||
|
|
||||||
// 이벤트 초기화 위치 수정 -> useCanvasSetting에서 세팅값 불러오고 나서 초기화 함수 호출
|
// 이벤트 초기화 위치 수정 -> useCanvasSetting에서 세팅값 불러오고 나서 초기화 함수 호출
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
// initEvent()
|
// initEvent()
|
||||||
@ -89,6 +92,7 @@ export function useEvent() {
|
|||||||
const wheelEvent = (opt) => {
|
const wheelEvent = (opt) => {
|
||||||
const delta = opt.e.deltaY // 휠 이동 값 (양수면 축소, 음수면 확대)
|
const delta = opt.e.deltaY // 휠 이동 값 (양수면 축소, 음수면 확대)
|
||||||
let zoom = canvas.getZoom() // 현재 줌 값
|
let zoom = canvas.getZoom() // 현재 줌 값
|
||||||
|
// console.log('zoom', zoom, 'delta', delta)
|
||||||
|
|
||||||
zoom += delta > 0 ? -0.1 : 0.1
|
zoom += delta > 0 ? -0.1 : 0.1
|
||||||
|
|
||||||
@ -99,15 +103,14 @@ export function useEvent() {
|
|||||||
setCanvasZoom(Number((zoom * 100).toFixed(0)))
|
setCanvasZoom(Number((zoom * 100).toFixed(0)))
|
||||||
|
|
||||||
// 마우스 위치 기준으로 확대/축소
|
// 마우스 위치 기준으로 확대/축소
|
||||||
canvas.zoomToPoint(new fabric.Point(opt.e.offsetX, opt.e.offsetY), zoom)
|
canvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom)
|
||||||
canvas.calcOffset()
|
|
||||||
canvas.setViewportTransform(canvas.viewportTransform)
|
|
||||||
canvas.requestRenderAll()
|
|
||||||
|
|
||||||
canvas.getObjects().forEach((obj) => {
|
canvas.getObjects().forEach((obj) => {
|
||||||
obj.setCoords()
|
obj.setCoords()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
canvas.renderAll()
|
||||||
|
|
||||||
// 이벤트의 기본 동작 방지 (스크롤 방지)
|
// 이벤트의 기본 동작 방지 (스크롤 방지)
|
||||||
opt.e.preventDefault()
|
opt.e.preventDefault()
|
||||||
opt.e.stopPropagation()
|
opt.e.stopPropagation()
|
||||||
@ -129,7 +132,7 @@ export function useEvent() {
|
|||||||
const roofsPoints = roofs.map((roof) => roof.points).flat()
|
const roofsPoints = roofs.map((roof) => roof.points).flat()
|
||||||
roofAdsorptionPoints.current = [...roofsPoints]
|
roofAdsorptionPoints.current = [...roofsPoints]
|
||||||
|
|
||||||
const auxiliaryLines = canvas.getObjects().filter((obj) => obj.name === 'auxiliaryLine' && !obj.isFixed)
|
const auxiliaryLines = canvas.getObjects().filter((obj) => obj.name === 'auxiliaryLine')
|
||||||
const otherAdsorptionPoints = []
|
const otherAdsorptionPoints = []
|
||||||
|
|
||||||
auxiliaryLines.forEach((line1) => {
|
auxiliaryLines.forEach((line1) => {
|
||||||
@ -138,7 +141,17 @@ export function useEvent() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const intersectionPoint = calculateIntersection(line1, line2)
|
const intersectionPoint = calculateIntersection(line1, line2) // 보조선끼리 만나는 점
|
||||||
|
|
||||||
|
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') // 외벽선
|
||||||
|
|
||||||
|
outerLines.forEach((outerLine) => {
|
||||||
|
const outerIntersectionPoint = calculateIntersection(outerLine, line1) // 외벽선과 보조선의 교차점
|
||||||
|
if (outerIntersectionPoint) {
|
||||||
|
intersectionPoints.current.push(outerIntersectionPoint)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if (!intersectionPoint || intersectionPoints.current.some((point) => point.x === intersectionPoint.x && point.y === intersectionPoint.y)) {
|
if (!intersectionPoint || intersectionPoints.current.some((point) => point.x === intersectionPoint.x && point.y === intersectionPoint.y)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -147,6 +160,7 @@ export function useEvent() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
let innerLinePoints = []
|
let innerLinePoints = []
|
||||||
|
let outerLinePoints = []
|
||||||
canvas
|
canvas
|
||||||
.getObjects()
|
.getObjects()
|
||||||
.filter((obj) => obj.innerLines)
|
.filter((obj) => obj.innerLines)
|
||||||
@ -157,14 +171,68 @@ export function useEvent() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const adsorptionPoints = [
|
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||||
|
outerLines.forEach((line) => {
|
||||||
|
outerLinePoints.push({ x: line.x2, y: line.y2 })
|
||||||
|
outerLinePoints.push({ x: line.x1, y: line.y1 })
|
||||||
|
})
|
||||||
|
|
||||||
|
const allAuxiliaryLines = canvas.getObjects().filter((obj) => obj.name === 'auxiliaryLine')
|
||||||
|
|
||||||
|
allAuxiliaryLines.forEach((aux) => {
|
||||||
|
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
|
|
||||||
|
roofs.forEach((roof) => {
|
||||||
|
//지붕과 보조선이 만나는 지점
|
||||||
|
roof.lines.forEach((line) => {
|
||||||
|
const intersectionPoint = calculateIntersection(aux, line)
|
||||||
|
if (intersectionPoint) {
|
||||||
|
intersectionPoints.current.push(intersectionPoint)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
//innerLines와 보조선이 만나는 지점
|
||||||
|
roof.innerLines.forEach((line) => {
|
||||||
|
const intersectionPoint = calculateIntersection(aux, line)
|
||||||
|
if (intersectionPoint) {
|
||||||
|
intersectionPoints.current.push(intersectionPoint)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// outerLines와의 교점
|
||||||
|
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||||
|
outerLines.forEach((outerLine) => {
|
||||||
|
const intersectionPoint = calculateIntersection(aux, outerLine)
|
||||||
|
if (intersectionPoint) {
|
||||||
|
intersectionPoints.current.push(intersectionPoint)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
let adsorptionPoints = [
|
||||||
...getAdsorptionPoints(),
|
...getAdsorptionPoints(),
|
||||||
...roofAdsorptionPoints.current,
|
...roofAdsorptionPoints.current,
|
||||||
...otherAdsorptionPoints,
|
...otherAdsorptionPoints,
|
||||||
...intersectionPoints.current,
|
...intersectionPoints.current,
|
||||||
...innerLinePoints,
|
...innerLinePoints,
|
||||||
|
...outerLinePoints,
|
||||||
|
...allAuxiliaryLines.map((line) => {
|
||||||
|
return {
|
||||||
|
x: line.x1,
|
||||||
|
y: line.y1,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
...allAuxiliaryLines.map((line) => {
|
||||||
|
return {
|
||||||
|
x: line.x2,
|
||||||
|
y: line.y2,
|
||||||
|
}
|
||||||
|
}),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
adsorptionPoints = removeDuplicatePoints(adsorptionPoints)
|
||||||
|
|
||||||
if (dotLineGridSetting.LINE || canvas.getObjects().filter((obj) => ['lineGrid', 'tempGrid'].includes(obj.name)).length > 1) {
|
if (dotLineGridSetting.LINE || canvas.getObjects().filter((obj) => ['lineGrid', 'tempGrid'].includes(obj.name)).length > 1) {
|
||||||
const closestLine = getClosestLineGrid(pointer)
|
const closestLine = getClosestLineGrid(pointer)
|
||||||
|
|
||||||
@ -354,15 +422,10 @@ export function useEvent() {
|
|||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultKeyboardEvent = (e) => {
|
|
||||||
if (e.key === 'Escape') {
|
|
||||||
console.log('defaultKeyboardEvent')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const addCanvasMouseEventListener = (eventType, handler) => {
|
const addCanvasMouseEventListener = (eventType, handler) => {
|
||||||
canvas.off(eventType)
|
canvas.off(eventType)
|
||||||
canvas.on(eventType, handler)
|
canvas.on(eventType, handler)
|
||||||
|
canvas.on('mouse:move', defaultMouseMoveEvent) // default mouse:move 이벤트는 항상 등록
|
||||||
mouseEventListeners.current.push({ eventType, handler })
|
mouseEventListeners.current.push({ eventType, handler })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,6 +484,17 @@ export function useEvent() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const removeDuplicatePoints = (points) => {
|
||||||
|
const map = new Map()
|
||||||
|
points.forEach((point) => {
|
||||||
|
const key = `${point.x},${point.y}`
|
||||||
|
if (!map.has(key)) {
|
||||||
|
map.set(key, point)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return Array.from(map.values())
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
addDocumentEventListener,
|
addDocumentEventListener,
|
||||||
addCanvasMouseEventListener,
|
addCanvasMouseEventListener,
|
||||||
|
|||||||
@ -993,10 +993,10 @@
|
|||||||
"estimate.detail.docPopup.title": "見積書出力オプションの設定",
|
"estimate.detail.docPopup.title": "見積書出力オプションの設定",
|
||||||
"estimate.detail.docPopup.explane": "ダウンロードする文書オプションを選択し、[見積書出力]ボタンをクリックします。",
|
"estimate.detail.docPopup.explane": "ダウンロードする文書オプションを選択し、[見積書出力]ボタンをクリックします。",
|
||||||
"estimate.detail.docPopup.schUnitPriceFlg": "ダウンロードファイル",
|
"estimate.detail.docPopup.schUnitPriceFlg": "ダウンロードファイル",
|
||||||
"estimate.detail.docPopup.schUnitPriceFlg.excelFlg0": "仕切用Excel",
|
"estimate.detail.docPopup.schUnitPriceFlg.excelFlg0": "見積書Excel",
|
||||||
"estimate.detail.docPopup.schUnitPriceFlg.excelFlg1": "定価用Excel",
|
"estimate.detail.docPopup.schUnitPriceFlg.excelFlg1": "定価用Excel",
|
||||||
"estimate.detail.docPopup.schUnitPriceFlg.excelFlg2": "見積書",
|
"estimate.detail.docPopup.schUnitPriceFlg.excelFlg2": "旧見積書書式",
|
||||||
"estimate.detail.docPopup.schUnitPriceFlg.pdfFlg0": "仕切用PDF",
|
"estimate.detail.docPopup.schUnitPriceFlg.pdfFlg0": "見積書PDF",
|
||||||
"estimate.detail.docPopup.schUnitPriceFlg.pdfFlg1": "定価用PDF",
|
"estimate.detail.docPopup.schUnitPriceFlg.pdfFlg1": "定価用PDF",
|
||||||
"estimate.detail.docPopup.schDisplayFlg": "見積提出書の表示名",
|
"estimate.detail.docPopup.schDisplayFlg": "見積提出書の表示名",
|
||||||
"estimate.detail.docPopup.schDisplayFlg.schDisplayFlg0": "販売店名",
|
"estimate.detail.docPopup.schDisplayFlg.schDisplayFlg0": "販売店名",
|
||||||
@ -1034,6 +1034,7 @@
|
|||||||
"estimate.detail.save.requiredItemId": "製品を選択してください。",
|
"estimate.detail.save.requiredItemId": "製品を選択してください。",
|
||||||
"estimate.detail.save.requiredAmount": "数量は0より大きい値を入力してください。",
|
"estimate.detail.save.requiredAmount": "数量は0より大きい値を入力してください。",
|
||||||
"estimate.detail.save.requiredSalePrice": "単価は0より大きい値を入力してください。",
|
"estimate.detail.save.requiredSalePrice": "単価は0より大きい値を入力してください。",
|
||||||
|
"estimate.detail.save.pricingFlag": "設定した価格見積が作成されます。このまま進めてよろしいですか?",
|
||||||
"estimate.detail.reset.alertMsg": "初期化されました。",
|
"estimate.detail.reset.alertMsg": "初期化されました。",
|
||||||
"estimate.detail.reset.confirmMsg": "保存した見積情報が初期化され、最近保存された図面情報が反映されます。本当に初期化しますか?",
|
"estimate.detail.reset.confirmMsg": "保存した見積情報が初期化され、最近保存された図面情報が反映されます。本当に初期化しますか?",
|
||||||
"estimate.detail.lock.alertMsg": "見積もりを[ロック]すると変更できません。 <br />見積もりを修正するには、ロックを解除してください。",
|
"estimate.detail.lock.alertMsg": "見積もりを[ロック]すると変更できません。 <br />見積もりを修正するには、ロックを解除してください。",
|
||||||
|
|||||||
@ -1034,6 +1034,7 @@
|
|||||||
"estimate.detail.save.requiredItemId": "제품을 선택해주세요.",
|
"estimate.detail.save.requiredItemId": "제품을 선택해주세요.",
|
||||||
"estimate.detail.save.requiredAmount": "수량은 0보다 큰값을 입력해주세요.",
|
"estimate.detail.save.requiredAmount": "수량은 0보다 큰값을 입력해주세요.",
|
||||||
"estimate.detail.save.requiredSalePrice": "단가는 0보다 큰값을 입력해주세요.",
|
"estimate.detail.save.requiredSalePrice": "단가는 0보다 큰값을 입력해주세요.",
|
||||||
|
"estimate.detail.save.pricingFlag": "설정한 가격 견적이 작성됩니다. 이대로 진행해도 괜찮으시겠습니까?",
|
||||||
"estimate.detail.reset.alertMsg": "초기화 되었습니다.",
|
"estimate.detail.reset.alertMsg": "초기화 되었습니다.",
|
||||||
"estimate.detail.reset.confirmMsg": "수기 변경(저장)한 견적 정보가 초기화되고 최근 저장된 도면정보가 반영됩니다. 정말로 초기화하시겠습니까?",
|
"estimate.detail.reset.confirmMsg": "수기 변경(저장)한 견적 정보가 초기화되고 최근 저장된 도면정보가 반영됩니다. 정말로 초기화하시겠습니까?",
|
||||||
"estimate.detail.lock.alertMsg": "견적서를 [잠금]하면 수정할 수 없습니다. <br />견적서를 수정하려면 잠금해제를 하십시오.",
|
"estimate.detail.lock.alertMsg": "견적서를 [잠금]하면 수정할 수 없습니다. <br />견적서를 수정하려면 잠금해제를 하십시오.",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user