This commit is contained in:
hyojun.choi 2025-01-21 17:15:24 +09:00
commit d82eccf229
12 changed files with 187 additions and 123 deletions

View File

@ -75,7 +75,11 @@ export default function QSelectBox({
useOnClickOutside(ref, handleClose)
return (
<div className={`sort-select ${openSelect ? 'active' : ''}`} ref={ref} onClick={disabled ? () => {} : () => setOpenSelect(!openSelect)}>
<div
className={`sort-select ${openSelect ? 'active' : ''} ${disabled ? 'disabled' : ''}`}
ref={ref}
onClick={disabled ? () => {} : () => setOpenSelect(!openSelect)}
>
<p>{selected}</p>
<ul className="select-item-wrap">
{options?.length > 0 &&

View File

@ -51,9 +51,18 @@ export default function CircuitTrestleSetting({ id }) {
models,
setModels,
}
const circuitProps = {
const passivityProps = {
tabNum,
setTabNum,
models,
setModels,
}
const stepUpProps = {
tabNum,
setTabNum,
models,
setModels,
circuitAllocationType,
setCircuitAllocationType,
}
@ -61,6 +70,7 @@ export default function CircuitTrestleSetting({ id }) {
const onAutoAllocation = () => {
let moduleStdQty = 0
let moduleMaxQty = 0
const selectedModels = models.filter((m) => m.selected)
if (selectedModels.length === 0) {
moduleStdQty = models.reduce((acc, model) => {
@ -144,8 +154,8 @@ export default function CircuitTrestleSetting({ id }) {
</div>
</div>
{tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO && <PowerConditionalSelect {...powerConditionalSelectProps} />}
{tabNum === 1 && allocationType === ALLOCATION_TYPE.PASSIVITY && <PassivityCircuitAllocation {...powerConditionalSelectProps} />}
{tabNum === 2 && <StepUp />}
{tabNum === 1 && allocationType === ALLOCATION_TYPE.PASSIVITY && <PassivityCircuitAllocation {...passivityProps} />}
{tabNum === 2 && <StepUp {...stepUpProps} />}
{tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO && (
<div className="grid-btn-wrap">
<button className="btn-frame modal mr5" onClick={() => onAutoAllocation()}>

View File

@ -6,6 +6,7 @@ import { useSwal } from '@/hooks/useSwal'
import { pcsCheckState } from '@/store/circuitTrestleAtom'
import { globalLocaleStore } from '@/store/localeAtom'
import { selectedModuleState } from '@/store/selectedModuleOptions'
import { isNullOrUndefined } from '@/util/common-utils'
import { useContext, useEffect, useState } from 'react'
import { useRecoilState } from 'recoil'
import { useRecoilValue } from 'recoil'
@ -46,6 +47,8 @@ export default function PowerConditionalSelect(props) {
]
useEffect(() => {
console.log('series', series)
console.log('models', models)
if (makers.length === 0) {
getPcsMakerList().then((res) => {
setMakers(res.data)
@ -71,17 +74,20 @@ export default function PowerConditionalSelect(props) {
console.log('🚀 ~ PowerConditionalSelect ~ selectedMaker:', selectedMaker)
if (selectedMaker) {
setModels(null)
getPcsMakerList(selectedMaker).then((res) => {
setSeries(
res.data.map((series) => {
return { ...series, selected: false }
}),
)
})
if (series.length === 0)
getPcsMakerList(selectedMaker).then((res) => {
setSeries(
res.data.map((series) => {
// return { ...series, selected: isNullOrUndefined(series.selected) ? false : series.selected }
return { ...series, selected: false }
}),
)
})
}
}, [selectedMaker])
useEffect(() => {
console.log('🚀 ~ useEffect ~ series:', series)
if (series.filter((s) => s.selected).length === 0) return
const pcsMkrCd = series.filter((s) => s.selected)[0]?.pcsMkrCd
const pcsSerList = series

View File

@ -10,13 +10,13 @@ import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupSta
import { canvasPopupStatusStore } from '@/store/canvasPopupStatusAtom'
import { useMasterController } from '@/hooks/common/useMasterController'
export default function StepUp({}) {
export default function StepUp(props) {
const { getMessage } = useMessage()
const [moduleTab, setModuleTab] = useState(1)
const [arrayLength, setArrayLength] = useState(3) //module-table-inner
const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState)
const model = useRecoilValue(modelState)
const { getPcsVoltageStepUpList } = useMasterController()
const { models } = props
const { getPcsVoltageStepUpList, getPcsAutoRecommendList } = useMasterController()
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
const canvas = useRecoilValue(canvasState)
const selectedModules = useRecoilValue(selectedModuleState)
@ -27,9 +27,11 @@ export default function StepUp({}) {
setManagementState(managementStateLoaded)
}
const useModuleItemList = model.selectedModels.map((model) => {
return { itemId: model.itemId, mixMatlNo: model.mixMatlNo }
})
const useModuleItemList = models
.filter((m) => m.selected)
.map((model) => {
return { itemId: model.itemId, mixMatlNo: model.mixMatlNo }
})
// [{ roofSurfaceId: '', roofSurface: '', roofSurfaceIncl: '', moduleList: [{ itemId: '' }] }],
const roofSurfaceList = canvas
.getObjects()
@ -48,13 +50,15 @@ export default function StepUp({}) {
}
})
// [{ itemId: '', pcsMkrCd: '', pcsSerCd: '' }],
const pscItemList = model.selectedModels.map((model) => {
return {
itemId: model.itemId,
pcsMkrCd: model.pcsMkrCd,
pcsSerCd: model.pcsSerCd,
}
})
const pscItemList = models
.filter((m) => m.selected)
.map((model) => {
return {
itemId: model.itemId,
pcsMkrCd: model.pcsMkrCd,
pcsSerCd: model.pcsSerCd,
}
})
const params = {
maxConnYn: pcsCheck.max,

View File

@ -2,31 +2,24 @@ import { GlobalDataContext } from '@/app/GlobalDataProvider'
import { POLYGON_TYPE } from '@/common/common'
import { useMessage } from '@/hooks/useMessage'
import { canvasState } from '@/store/canvasAtom'
import { modelState } from '@/store/circuitTrestleAtom'
import { moduleStatisticsState } from '@/store/circuitTrestleAtom'
import { selectedModuleState } from '@/store/selectedModuleOptions'
import { useContext, useEffect, useState } from 'react'
import { useRecoilValue } from 'recoil'
const DIRECTION = {
north: '北',
south: '南',
west: '西',
east: '東',
}
export default function PassivityCircuitAllocation() {
export default function PassivityCircuitAllocation(props) {
const { tabNum, setTabNum, models, setModels } = props
const { getMessage } = useMessage()
const canvas = useRecoilValue(canvasState)
const selectedModules = useRecoilValue(selectedModuleState)
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
const [moduleData, setModuleData] = useState({
header: [],
rows: [],
})
const model = useRecoilValue(modelState)
const [selectedModels, setSelectedModels] = useState(model.selectedModels)
const [selectedPcs, setSelectedPcs] = useState(selectedModels[0])
const [totalWpout, setTotalWpout] = useState(0)
const selectedModules = useRecoilValue(selectedModuleState)
const moduleStatistics = useRecoilValue(moduleStatisticsState)
// const [totalWpout, setTotalWpout] = useState(0)
const [selectedPcs, setSelectedPcs] = useState(models.filter((model) => model.selected)[0])
const { header, rows: row } = moduleStatistics
const [headers, setHeaders] = useState(header)
const [rows, setRows] = useState(row)
const [footer, setFooter] = useState(['합계'])
useEffect(() => {
setSurfaceInfo()
@ -35,48 +28,90 @@ export default function PassivityCircuitAllocation() {
}
}, [])
useEffect(() => {
console.log('🚀 ~ useEffect ~ headers:', headers)
}, [headers])
useEffect(() => {
console.log('🚀 ~ useEffect ~ rows:', rows)
}, [rows])
const setSurfaceInfo = () => {
console.log('🚀 ~ setSurfaceInfo ~ headers:', headers)
console.log('🚀 ~ setSurfaceInfo ~ rows:', rows)
// console.log('🚀 ~ setSurfaceInfo ~ surfaces:', surfaces)
const surfaces = canvas.getObjects().filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name)
let totalWpout = 0
const rows = surfaces.map((surface) => {
let wpOut = 0
let moduleInfo = {}
surface.modules.forEach((module) => {
wpOut += +module.moduleInfo.wpOut
if (!moduleInfo[module.moduleInfo.itemId]) moduleInfo[module.moduleInfo.itemId] = 0
moduleInfo[module.moduleInfo.itemId]++
})
totalWpout += wpOut
console.log('🚀 ~ moduleData.rows=surfaces.map ~ module:', module)
return {
roofShape: DIRECTION[surface.direction],
powerGeneration: wpOut.toLocaleString('ko-KR', { maximumFractionDigits: 4 }),
...moduleInfo,
setHeaders([header[0], { name: '회로', prop: 'circuit' }, ...header.slice(1)])
setRows(
rows.map((row) => {
return {
...row,
circuit: '',
}
}),
)
let totals = {}
rows.forEach((row) => {
if (header.length === 4) {
if (!totals[header[2].prop]) totals[header[2].prop] = 0
totals[header[2].prop] += +row[header[2].prop]
} else if (header.length === 5) {
if (!totals[header[2].prop]) totals[header[2].prop] = 0
totals[header[2].prop] += +row[header[2].prop]
if (!totals[header[3].prop]) totals[header[3].prop] = 0
totals[header[3]] += +row[header[3]]
}
})
console.log(totals)
setFooter([
...['합계', ''],
...Object.keys(totals).map((key) => {
return totals[key]
}),
Object.keys(totals).reduce((acc, key) => {
return acc + totals[key]
}, 0),
])
// let totalWpout = 0
// const rows = surfaces.map((surface) => {
// let wpOut = 0
// let moduleInfo = {}
// surface.modules.forEach((module) => {
// wpOut += +module.moduleInfo.wpOut
// if (!moduleInfo[module.moduleInfo.itemId]) moduleInfo[module.moduleInfo.itemId] = 0
// moduleInfo[module.moduleInfo.itemId]++
// })
// totalWpout += wpOut
// console.log('🚀 ~ moduleData.rows=surfaces.map ~ module:', module)
// return {
// roofShape: DIRECTION[surface.direction],
// powerGeneration: wpOut.toLocaleString('ko-KR', { maximumFractionDigits: 4 }),
// ...moduleInfo,
// }
// })
setTotalWpout(totalWpout)
// setTotalWpout(totalWpout)
// -> ->
// wpOut
console.log('🚀 ~ setSurfaceInfo ~ modules:', rows)
console.log('🚀 ~ setSurfaceInfo ~ surfaces:', surfaces)
setModuleData({
header: [
{ name: getMessage('modal.panel.batch.statistic.roof.shape'), prop: 'roofShape' },
{ name: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit'), prop: 'circuit' },
...selectedModules.itemList.map((module) => {
return {
name: module.itemNm,
prop: module.itemId,
}
}),
{
name: `${getMessage('modal.panel.batch.statistic.power.generation.amount')}(kW)`,
prop: 'powerGeneration',
},
],
rows: rows,
})
// setModuleData({
// header: [
// { name: getMessage('modal.panel.batch.statistic.roof.shape'), prop: 'roofShape' },
// { name: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit'), prop: 'circuit' },
// ...selectedModules.itemList.map((module) => {
// return {
// name: module.itemNm,
// prop: module.itemId,
// }
// }),
// {
// name: `${getMessage('modal.panel.batch.statistic.power.generation.amount')}(kW)`,
// prop: 'powerGeneration',
// },
// ],
// rows: rows,
// })
}
return (
<>
@ -87,32 +122,27 @@ export default function PassivityCircuitAllocation() {
<div className="bold-font mb10">{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity')}</div>
<div className="normal-font mb15">{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.info')}</div>
<div className="roof-module-table overflow-y">
{moduleData.header && (
{header && (
<table>
<thead>
<tr>
{moduleData.header.map((header) => (
<th key={header.prop}>{header.name}</th>
{headers.map((header) => (
<th key={'header' + header.prop}>{header.name}</th>
))}
</tr>
</thead>
<tbody>
{moduleData.rows.map((row, index) => (
<tr key={index} className="wrong">
{moduleData.header.map((header) => (
<td className="al-c" key={header.prop}>
{row[header.prop]}
</td>
{rows.map((row, index) => (
<tr key={'row' + index}>
{headers.map((header) => (
<td className="al-c">{row[header.prop]}</td>
))}
</tr>
))}
<tr className="wrong">
<td className="al-c">총합</td>
{Array.from({ length: moduleData.header.length - 3 }).map((_, index) => {
return <td key={index} className="al-c"></td>
})}
<td className="al-c">{totalWpout.toLocaleString('ko-KR', { maximumFractionDigits: 4 })}</td>
<td className="al-c">{totalWpout.toLocaleString('ko-KR', { maximumFractionDigits: 4 })}</td>
<tr>
{footer.map((footer) => (
<td className="al-c">{footer}</td>
))}
</tr>
</tbody>
</table>
@ -127,25 +157,27 @@ export default function PassivityCircuitAllocation() {
<div className="bold-font">{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional')}</div>
</div>
<div className="hexagonal-item">
{selectedModels.map((model, index) => (
<div className="d-check-radio pop mb10">
<input
type="radio"
name="radio01"
id={`ra0${index + 1}`}
checked={selectedPcs === model}
onChange={() => setSelectedPcs(model)}
/>
<label htmlFor="ra01">
{model.itemNm} (
{getMessage(
'modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.info',
managementState?.coldRegionFlg === '1' ? [model.serMinQty, model.serColdZoneMaxQty] : [model.serMinQty, model.serMaxQty],
)}
)
</label>
</div>
))}
{models
.filter((model) => model.selected)
.map((model, index) => (
<div className="d-check-radio pop mb10" key={'model' + index}>
<input
type="radio"
name="radio01"
id={`ra0${index + 1}`}
checked={selectedPcs === model}
onChange={() => setSelectedPcs(model)}
/>
<label htmlFor="ra01">
{model.itemNm} (
{getMessage(
'modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.info',
managementState?.coldRegionFlg === '1' ? [model.serMinQty, model.serColdZoneMaxQty] : [model.serMinQty, model.serMaxQty],
)}
)
</label>
</div>
))}
{/* <div className="d-check-radio pop mb10">
<input type="radio" name="radio01" id="ra01" />
<label htmlFor="ra01">HQJP-KA55-5 (標準回路2枚10)</label>

View File

@ -33,8 +33,9 @@ export default function PanelBatchStatistics() {
{rows.map((row, index) => (
<tr key={index}>
{header.map((item, i) => (
// <td>{item.prop === 'name' ? item.name : item.prop === 'powerGeneration' ? item.powerGeneration : item.amount}</td>
<td key={i}>{row[item.prop]}</td>
<td key={index}>
{typeof row[item.prop] === 'number' ? row[item.prop].toLocaleString('ko-KR', { maximumFractionDigits: 4 }) : row[item.prop]}
</td>
))}
</tr>
))}

View File

@ -2308,12 +2308,14 @@ export function useModuleBasicSetting() {
})
return {
...rowObject, // 총 발전량 = 발전량 * 모듈 개수
...surface,
name: canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].directionText, // 지붕면
// powerGeneration: wpOut.toLocaleString('ko-KR', { maximumFractionDigits: 4 }),
wpOut: wpOut,
}
})
console.log('🚀 ~ getModuleStatistics ~ rows:', rows)
console.log('🚀 ~ getModuleStatistics ~ moduleInfo:', moduleInfo)
const header = [
{ name: getMessage('modal.panel.batch.statistic.roof.shape'), prop: 'name' },
@ -2334,15 +2336,7 @@ export function useModuleBasicSetting() {
footer.push(footerData[key])
})
footer.push(totalWpout)
// const footer = [
// '합계',
// ...Object.keys(moduleInfo).map((key) => {
// return { name: moduleInfo[key].name, prop: moduleInfo[key] }
// }),
// totalWpout,
// ]
// const footer = []
console.log('@@@@@@@@@@', header, rows, footer)
console.log({ header: header, rows, footer: footer })
setModuleStatistics({ header: header, rows, footer: footer })
}

View File

@ -51,6 +51,7 @@ export function useModulePlace() {
useEffect(() => {
//지붕을 가져옴
console.log('🚀 ~ trestleDetailList.forEach ~ trestleDetailList:', trestleDetailList)
canvas
.getObjects()
.filter((roof) => roof.name === 'roof')

View File

@ -281,6 +281,12 @@
"modal.object.setting.direction.select": "方向の選択",
"modal.placement.surface.setting.info": "ⓘ ①の長さ入力後に対角線の長さを入力すると、②の長さを自動計算します。",
"modal.placement.surface.setting.diagonal.length": "斜めの長さ",
"modal.placement.surface.drawing.straight.line": "직선(JA)",
"modal.placement.surface.drawing.right.angle": "직각(JA)",
"modal.placement.surface.drawing.double.pitch": "이구배(JA)",
"modal.placement.surface.drawing.angle": "각도(JA)",
"modal.placement.surface.drawing.diagonal": "대각선(JA)",
"modal.placement.surface.drawing.fix": "배치면 확정(JA)",
"modal.color.picker.title": "色の設定",
"modal.color.picker.default.color": "基本色",
"modal.size.setting": "サイズ変更",

View File

@ -80,6 +80,7 @@
"modal.placement.surface.drawing.double.pitch": "이구배",
"modal.placement.surface.drawing.angle": "각도",
"modal.placement.surface.drawing.diagonal": "대각선",
"modal.placement.surface.drawing.fix": "배치면 확정",
"plan.menu.placement.surface.arrangement": "면형상 배치",
"plan.menu.placement.surface.object": "오브젝트 배치",
"plan.menu.placement.surface.all.remove": "배치면 전체 삭제",

View File

@ -42,4 +42,5 @@ export const moduleStatisticsState = atom({
rows: [],
footer: ['합계', '0'],
},
dangerouslyAllowMutability: true,
})

View File

@ -149,3 +149,7 @@ export const unescapeString = (str) => {
return str.replace(regex, (matched) => chars[matched] || matched)
}
}
export const isNullOrUndefined = (value) => {
return value === null || value === undefined
}