From a08df8a32e6126eca6b9cdce91fb6e1199e5f5ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Wed, 22 Jan 2025 15:11:52 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=EC=9E=90=EB=8F=99=20=ED=9A=8C=EB=A1=9C?= =?UTF-8?q?=ED=95=A0=EB=8B=B9=20=EA=B0=9C=EB=B0=9C=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../circuitTrestle/CircuitTrestleSetting.jsx | 84 +++++++- .../step/PowerConditionalSelect.jsx | 179 +++++++++--------- src/hooks/common/useMasterController.js | 3 +- src/store/circuitTrestleAtom.js | 10 +- 4 files changed, 166 insertions(+), 110 deletions(-) diff --git a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx index 2901f952..fc0be1f6 100644 --- a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx @@ -11,12 +11,13 @@ import { correntObjectNoState } from '@/store/settingAtom' import { useRecoilValue } from 'recoil' import { GlobalDataContext } from '@/app/GlobalDataProvider' import { useRecoilState } from 'recoil' -import { makersState, modelsState, modelState, pcsCheckState, selectedMakerState, seriesState } from '@/store/circuitTrestleAtom' +import { makersState, modelsState, modelState, pcsCheckState, selectedMakerState, selectedModelsState, seriesState } from '@/store/circuitTrestleAtom' import { POLYGON_TYPE } from '@/common/common' import { useSwal } from '@/hooks/useSwal' import { canvasState } from '@/store/canvasAtom' import { useTrestle } from '@/hooks/module/useTrestle' +import { selectedModuleState } from '@/store/selectedModuleOptions' const ALLOCATION_TYPE = { AUTO: 'auto', @@ -33,12 +34,15 @@ export default function CircuitTrestleSetting({ id }) { const [selectedMaker, setSelectedMaker] = useRecoilState(selectedMakerState) const [series, setSeries] = useRecoilState(seriesState) const [models, setModels] = useRecoilState(modelsState) + const [selectedModels, setSelectedModels] = useRecoilState(selectedModelsState) const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState) const [tabNum, setTabNum] = useState(1) const [allocationType, setAllocationType] = useState(ALLOCATION_TYPE.AUTO) const [circuitAllocationType, setCircuitAllocationType] = useState(1) - + const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext) + const selectedModules = useRecoilValue(selectedModuleState) + const { getPcsAutoRecommendList } = useMasterController() const powerConditionalSelectProps = { tabNum, setTabNum, @@ -50,6 +54,9 @@ export default function CircuitTrestleSetting({ id }) { setSeries, models, setModels, + selectedModels, + setSelectedModels, + managementState, } const passivityProps = { @@ -67,19 +74,78 @@ export default function CircuitTrestleSetting({ id }) { setCircuitAllocationType, } + useEffect(() => { + if (!managementState) { + setManagementState(managementStateLoaded) + } + }, []) + + const onAutoRecommend = () => { + if (series.filter((s) => s.selected).length === 0) { + swalFire({ + title: '시리즈를 선택해 주세요.', + type: 'alert', + }) + return + } + const roofSurfaceList = canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) + .map((obj) => { + return { + roofSurfaceId: obj.id, + roofSurface: canvas + .getObjects() + .filter((o) => o.id === obj.parentId)[0] + .directionText.replace(/[0-9]/g, ''), + roofSurfaceIncl: canvas.getObjects().filter((o) => o.id === obj.parentId)[0].roofMaterial.pitch, + moduleList: obj.modules.map((module) => { + return { + itemId: module.moduleInfo.itemId, + } + }), + } + }) + + const params = { + maxConnYn: pcsCheck.max ? 'Y' : 'N', + smpCirYn: pcsCheck.division ? 'Y' : 'N', + coldZoneYn: managementState?.coldRegionFlg === '1' ? 'Y' : 'N', + useModuleItemList: selectedModules.itemList.map((m) => { + return { + itemId: m.itemId, + mixMatlNo: m.mixMatlNo, + } + }), + roofSurfaceList: roofSurfaceList, + pcsItemList: models.map((model) => { + return { + itemId: model.itemId, + pcsMkrCd: model.pcsMkrCd, + pcsSerCd: model.pcsSerCd, + } + }), + } + getPcsAutoRecommendList(params).then((res) => { + if (res.data?.pcsItemList) { + setModels(res.data.pcsItemList) + setTabNum(2) + } else { + swalFire({ + title: '파워컨디셔너를 추가해 주세요.', + type: 'alert', + }) + } + }) + } + const onAutoAllocation = () => { let moduleStdQty = 0 let moduleMaxQty = 0 const selectedModels = models.filter((m) => m.selected) if (selectedModels.length === 0) { - moduleStdQty = models.reduce((acc, model) => { - return acc + parseInt(model.moduleStdQty) - }, 0) - - moduleMaxQty = models.reduce((acc, model) => { - return acc + parseInt(model.moduleMaxQty) - }, 0) + onAutoRecommend() } else { moduleStdQty = selectedModels.reduce((acc, model) => { return acc + parseInt(model.moduleStdQty) diff --git a/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx b/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx index bc67679d..bf362856 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx @@ -13,9 +13,23 @@ import { useRecoilValue } from 'recoil' import { v4 as uuidv4 } from 'uuid' export default function PowerConditionalSelect(props) { - let { tabNum, setTabNum, makers, setMakers, selectedMaker, setSelectedMaker, series, setSeries, models, setModels } = props + let { + tabNum, + setTabNum, + makers, + setMakers, + selectedMaker, + setSelectedMaker, + series, + setSeries, + models, + setModels, + selectedModels, + setSelectedModels, + managementState, + } = props const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState) - const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext) + const { getMessage } = useMessage() const [selectedRow, setSelectedRow] = useState(null) const globalLocale = useRecoilValue(globalLocaleStore) @@ -47,54 +61,49 @@ export default function PowerConditionalSelect(props) { ] useEffect(() => { - console.log('series', series) - console.log('models', models) if (makers.length === 0) { getPcsMakerList().then((res) => { setMakers(res.data) }) } - console.log('🚀 ~ useEffect ~ selectedModules:', selectedModules) - if (!managementState) { - setManagementState(managementStateLoaded) - } - // promiseGet({ url: `/api/object/${correntObjectNo}/detail` }).then((res) => { - // console.log('🚀 ~ useEffect ~ /api/object/${correntObjectNo}/detail:', res) - // // coldRegionFlg-한랭지사양, conType// 계약조건(잉여~,전량) - // }) - // return () => { - // console.log('🚀 ~ useEffect ~ PowerConditionalSelect unmount:', makers, selectedMaker) - // setMakerData({ makers, selectedMaker }) - // setSeries({ series: seriesList, selectedSeries }) - // setModels({ models, selectedModels }) - // } }, []) - useEffect(() => { - console.log('🚀 ~ PowerConditionalSelect ~ selectedMaker:', selectedMaker) - if (selectedMaker) { - setModels(null) - 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 - .filter((series) => series.selected) - .map((series) => { - return { pcsSerCd: series.pcsSerCd } + const checkValidation = () => { + const checkedSeries = series.filter((s) => s.selected) + if (checkedSeries.length === 0) { + swalFire({ + title: 'PCS 시리즈를 선택해 주세요.', + icon: 'warning', }) + return false + } else if (checkedSeries.length === 1) { + if (checkedSeries[0].pcsMkrMultiType === 'SINGLE-P' && checkedSeries[0].pcsSerParallelYn === 'Y') { + swalFire({ + title: '병설은 단독으로 안 됨', + icon: 'warning', + }) + } + return false + } + return true + } + + const onCheckSeries = (data) => { + const copySeries = series.map((s) => { + return { + ...s, + selected: s.pcsSerCd === data.pcsSerCd ? !s.selected : s.selected, + } + }) + setSeries(copySeries) + handleSetmodels(copySeries.filter((s) => s.selected)) + } + + const handleSetmodels = (series) => { + const pcsMkrCd = series[0]?.pcsMkrCd + const pcsSerList = series.map((series) => { + return { pcsSerCd: series.pcsSerCd } + }) const moduleItemList = selectedModules.itemList?.map((module) => { return { itemId: module.itemId, @@ -103,7 +112,6 @@ export default function PowerConditionalSelect(props) { }) getPcsModelList({ pcsMkrCd, pcsSerList, moduleItemList }).then((res) => { if (res?.result.code === 200 && res?.data) { - console.log('🚀 ~ useEffect ~ res:', res.data) setModels( res.data.map((model) => { return { @@ -111,21 +119,20 @@ export default function PowerConditionalSelect(props) { moduleStdQty: parseInt(model.moduleStdQty), moduleMaxQty: parseInt(model.moduleMaxQty), code: uuidv4(), - selected: false, } }), ) + return } - }) - }, [series]) - const onCheckSeries = (series) => { - setSeries((prev) => prev.map((s) => ({ ...s, selected: s.pcsSerCd === series.pcsSerCd ? !s.selected : s.selected }))) + setModels([]) + setSelectedModels([]) + }) } const onAddSelectedModel = () => { if (selectedRow === null) return - if (models.filter((m) => m.selected).length === 3) { + if (selectedModels.length === 3) { swalFire({ title: '최대 3개까지 선택할 수 있습니다.', icon: 'warning', @@ -133,41 +140,29 @@ export default function PowerConditionalSelect(props) { return } - setModels( - models.map((model) => { - if (model.code === selectedRow.code) { - return { - ...model, - selected: true, - } - } - return { - ...model, - } - }), - ) + setSelectedModels([...selectedModels, selectedRow]) setSelectedRow(null) } const onRemoveSelectedModel = (model) => { - // setSelectedModels(selectedModels.filter((m) => m.code !== model.code)) setModels(models.map((m) => ({ ...m, selected: m.code !== model.code ? m.selected : false }))) } - // useEffect(() => { - // console.log('🚀 ~ useEffect ~ selectedModels:', selectedModels) - // const selectedModelsIds = selectedModels.map((model) => model.code) + const onChangeMaker = (option) => { + if (option) { + setModels(null) + setSelectedMaker(option) + + getPcsMakerList(option).then((res) => { + setSeries( + res.data.map((series) => { + return { ...series, selected: false } + }), + ) + }) + } + } - // setModels( - // models.map((model) => { - // return { - // ...model, - // selected: selectedModelsIds.includes(model.code), - // } - // }), - // ) - // setModel({ ...model, selectedModels: selectedModels }) - // }, [selectedModels]) return ( <>
@@ -182,7 +177,7 @@ export default function PowerConditionalSelect(props) { sourceKey="pcsMkrCd" targetKey="pcsMkrCd" value={selectedMaker} - onChange={(option) => setSelectedMaker(option)} + onChange={(option) => onChangeMaker(option)} />
{managementState?.coldRegionFlg === '1' && ( @@ -194,7 +189,7 @@ export default function PowerConditionalSelect(props) {
{series?.map((series, index) => (
- onCheckSeries(series)} checked={series.selected} /> + onCheckSeries(series)} checked={series.selected} />
))} @@ -216,15 +211,13 @@ export default function PowerConditionalSelect(props) { - {models - ?.filter((model) => !model.selected) - .map((model, index) => ( - setSelectedRow(model)} className={model === selectedRow ? 'on' : ''}> - {modelHeader.map((header) => ( - {model[header.prop]} - ))} - - ))} + {models?.map((model, index) => ( + setSelectedRow(model)} className={model === selectedRow ? 'on' : ''}> + {modelHeader.map((header) => ( + {model[header.prop]} + ))} + + ))}
@@ -235,13 +228,11 @@ export default function PowerConditionalSelect(props) {
- {models - ?.filter((m) => m.selected) - ?.map((model) => ( - - {model.itemNm} - - ))} + {selectedModels?.map((model) => ( + + {model.itemNm} + + ))}
diff --git a/src/hooks/common/useMasterController.js b/src/hooks/common/useMasterController.js index 013c7870..b289baf4 100644 --- a/src/hooks/common/useMasterController.js +++ b/src/hooks/common/useMasterController.js @@ -162,8 +162,7 @@ export function useMasterController() { * @returns */ const getPcsAutoRecommendList = async (params = null) => { - const paramString = getQueryString(params) - return await post({ url: '/api/master/pcsAutoRecommendList', data: params }).then((res) => { + return await post({ url: '/api/v1/master/getPcsAutoRecommendList', data: params }).then((res) => { console.log('🚀🚀 ~ getPcsAutoRecommendList ~ res:', res) return res }) diff --git a/src/store/circuitTrestleAtom.js b/src/store/circuitTrestleAtom.js index 46f62676..ad77c778 100644 --- a/src/store/circuitTrestleAtom.js +++ b/src/store/circuitTrestleAtom.js @@ -17,16 +17,16 @@ export const seriesState = atom({ default: [], }) -export const selectedSeriesState = atom({ - key: 'selectedSeriesState', - default: null, -}) - export const modelsState = atom({ key: 'modelState', default: [], }) +export const selectedModelsState = atom({ + key: 'selectedModelsState', + default: [], +}) + export const pcsCheckState = atom({ key: 'divisionCircuitState', default: { division: true, max: false }, From edd660b2454bb3654c4cf0b009e3af181e242811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=8B=9D?= <43837214+Minsiki@users.noreply.github.com> Date: Thu, 23 Jan 2025 09:33:18 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=EC=9E=90=EB=8F=99=20=ED=9A=8C=EB=A1=9C?= =?UTF-8?q?=ED=95=A0=EB=8B=B9=20=EA=B0=9C=EB=B0=9C=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../circuitTrestle/CircuitTrestleSetting.jsx | 9 +- .../step/PowerConditionalSelect.jsx | 1 + .../step/type/PassivityCircuitAllocation.jsx | 159 +++++++++++++----- src/hooks/useCanvasEvent.js | 4 +- 4 files changed, 122 insertions(+), 51 deletions(-) diff --git a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx index fc0be1f6..fa4abd4c 100644 --- a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx @@ -62,8 +62,8 @@ export default function CircuitTrestleSetting({ id }) { const passivityProps = { tabNum, setTabNum, - models, - setModels, + selectedModels, + setSelectedModels, } const stepUpProps = { tabNum, @@ -170,16 +170,13 @@ export default function CircuitTrestleSetting({ id }) { } const onPassivityAllocation = () => { - console.log('🚀 ~ onPassivityAllocation ~ selectedModels:', models) - - if (models.filter((m) => m.selected).length === 0) { + if (selectedModels.length === 0) { swalFire({ title: '파워 컨디셔너를 추가해 주세요.', type: 'alert', }) return } else if (pcsCheck.max) { - const selectedModels = models.filter((m) => m.selected) const moduleStdQty = selectedModels.reduce((acc, model) => { return acc + parseInt(model.moduleStdQty) }, 0) diff --git a/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx b/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx index bf362856..fbaef41a 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx @@ -37,6 +37,7 @@ export default function PowerConditionalSelect(props) { const selectedModules = useRecoilValue(selectedModuleState) const { swalFire } = useSwal() const modelHeader = [ + { name: getMessage('시리즈'), width: '15%', prop: 'pcsSerNm', type: 'color-box' }, { name: getMessage('명칭'), width: '15%', prop: 'itemNm', type: 'color-box' }, { name: `${getMessage('modal.circuit.trestle.setting.power.conditional.select.rated.output')} (kW)`, diff --git a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx index a1c26c6b..62e54ec1 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx @@ -8,38 +8,68 @@ import { useContext, useEffect, useState } from 'react' import { useRecoilValue } from 'recoil' export default function PassivityCircuitAllocation(props) { - const { tabNum, setTabNum, models, setModels } = props + const { tabNum, setTabNum, selectedModels } = props const { getMessage } = useMessage() const canvas = useRecoilValue(canvasState) const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext) const selectedModules = useRecoilValue(selectedModuleState) const moduleStatistics = useRecoilValue(moduleStatisticsState) // const [totalWpout, setTotalWpout] = useState(0) - const [selectedPcs, setSelectedPcs] = useState(models.filter((model) => model.selected)[0]) + const [selectedPcs, setSelectedPcs] = useState(selectedModels[0]) const { header, rows: row } = moduleStatistics const [headers, setHeaders] = useState(header) const [rows, setRows] = useState(row) const [footer, setFooter] = useState(['합계']) + const [circuitNumber, setCircuitNumber] = useState(1) + const [targetModules, setTargetModules] = useState([]) + + useEffect(() => { + console.log('🚀 ~ PassivityCircuitAllocation ~ targetModules:', targetModules) + }, [targetModules]) + + const handleTargetModules = (obj) => { + if (!Array.isArray(targetModules)) { + setTargetModules([]) + return + } + + setTargetModules((prev) => { + if (prev.includes(obj.id)) { + obj.set({ strokeWidth: 0.3 }) + return prev.filter((o) => o !== obj.id) + } else { + obj.set({ strokeWidth: 2 }) + return [...prev, obj.id] + } + }) + + canvas.renderAll() + } useEffect(() => { setSurfaceInfo() if (!managementState) { setManagementState(managementStateLoaded) } + const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE) + + modules.forEach((obj) => { + obj.on('mousedown', (e) => handleTargetModules(obj)) + }) + + return () => { + canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE) + .forEach((obj) => { + obj.set({ strokeWidth: 0.3 }) + obj.off('mousedown') + }) + canvas.renderAll() + } }, []) - 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) setHeaders([header[0], { name: '회로', prop: 'circuit' }, ...header.slice(1)]) setRows( @@ -63,7 +93,6 @@ export default function PassivityCircuitAllocation(props) { totals[header[3]] += +row[header[3]] } }) - console.log(totals) setFooter([ ...['합계', ''], ...Object.keys(totals).map((key) => { @@ -113,6 +142,39 @@ export default function PassivityCircuitAllocation(props) { // rows: rows, // }) } + + const handleCircuitNumberFix = () => { + console.log('🚀 ~ handleCircuitNumberFix ~ circuitNumber:', circuitNumber) + canvas + .getObjects() + .filter((obj) => targetModules.includes(obj.id)) + .forEach((obj) => { + obj.set({ + circuit: circuitNumber, + }) + canvas.add( + new fabric.Text(`(${circuitNumber})`, { + left: obj.left + obj.width / 2, + top: obj.top + obj.height / 2, + fill: 'red', + fontSize: 20, + width: obj.width, + height: obj.height, + textAlign: 'center', + originX: 'center', + originY: 'center', + name: 'circuitNumber', + parentId: obj.id, + }), + ) + canvas.renderAll() + console.log(obj) + }) + setTargetModules([]) + setCircuitNumber(circuitNumber + 1) + canvas.renderAll() + } + return ( <>
@@ -126,22 +188,26 @@ export default function PassivityCircuitAllocation(props) { - {headers.map((header) => ( - + {headers.map((header, index) => ( + ))} {rows.map((row, index) => ( - {headers.map((header) => ( - + {headers.map((header, i) => ( + ))} ))} - {footer.map((footer) => ( - + {footer.map((footer, index) => ( + ))} @@ -157,27 +223,25 @@ export default function PassivityCircuitAllocation(props) {
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional')}
- {models - .filter((model) => model.selected) - .map((model, index) => ( -
- setSelectedPcs(model)} - /> - -
- ))} + {selectedModels.map((model, index) => ( +
+ setSelectedPcs(model)} + /> + +
+ ))} {/*
@@ -201,9 +265,18 @@ export default function PassivityCircuitAllocation(props) { {getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num')}
- + setCircuitNumber(e.target.value)} + />
- +
diff --git a/src/hooks/useCanvasEvent.js b/src/hooks/useCanvasEvent.js index 7ea3e03c..9076bbc8 100644 --- a/src/hooks/useCanvasEvent.js +++ b/src/hooks/useCanvasEvent.js @@ -198,7 +198,7 @@ export function useCanvasEvent() { if (selected?.length > 0) { selected.forEach((obj) => { - if (obj.type === 'QPolygon') { + if (obj.type === 'QPolygon' && obj.name !== 'module') { obj.set({ stroke: 'red' }) } }) @@ -235,7 +235,7 @@ export function useCanvasEvent() { if (selected?.length > 0) { selected.forEach((obj) => { - if (obj.type === 'QPolygon') { + if (obj.type === 'QPolygon' && obj.name !== 'module') { obj.set({ stroke: 'red' }) } })
{header.name}{header.name}
{row[header.prop]} + {row[header.prop]} +
{footer} + {footer} +