'use client'; import React, { useEffect, useMemo, useState } from 'react' import Agent from './NodeType/Agent'; import Form from './NodeType/Form'; import Unsupport from './NodeType/Unsupport'; import * as R from 'ramda' import { curNodeAtom, curStepAtom, arrowStateAtom, cardInstantAtomFamily, cardInstantAtomsAtom, instantDataAtom, stepsNodesAtom, viewedStepAtom, asideInstantAtomsAtom, asideInstantAtomFamily } from '../store'; import { useAtom, useAtomValue, useSetAtom } from 'jotai'; import { exportFlowToDocx } from '../export'; import PreviewModal from './PreviewModal'; import { useReducerAtom } from 'jotai/utils'; import ClearAfterFlowConfirmModal from './ClearAfterFlowConfirmModal'; const NodeRender = () => { const [curStep, setCurStep] = useAtom(curStepAtom) const [viewedStep, dispatchViewedStep] = useReducerAtom(viewedStepAtom, (prev: number, step: number) => { return R.max(prev, step) }) const forceSetViewedStep = useSetAtom(viewedStepAtom) useEffect(() => { dispatchViewedStep(curStep) }, [curStep]) const [confirmClearAfterFlowModalOpen, setConfirmClearAfterFlowModalOpen] = useState(false) const node = useAtomValue(curNodeAtom) const arrowState = useAtomValue(arrowStateAtom) const Comp = useMemo(() => { return R.cond([ [R.propEq('form_card', 'type'), R.always(Form)], [R.propEq('UserTask', 'type'), R.always(Agent)], [R.T, R.always(Unsupport)], ])(node) }, [node, node?.id]) const nodeName = useMemo(() => { return R.cond([ [R.propEq('form_card', 'type'), R.always('表单填写')], [R.propEq('UserTask', 'type'), R.pathOr('Unknown Agent', ['properties', 'item', 'assistantName'])], [R.T, R.always('Unknown')], ])(node) }, [node, node?.id]) // 动态注册当前节点的Atom,并将其放进一个atom集合的atom,方便后续格式化所有节点实例 const cardInstantAtom = cardInstantAtomFamily(node) const [cardInstantAtoms, dispatchCardInstantAtoms] = useAtom(cardInstantAtomsAtom) useEffect(() => { if (node?.id) { dispatchCardInstantAtoms({ payload: { [node.id]: cardInstantAtom }, type: 'update' }) } }, [cardInstantAtom]) const stepsNodes = useAtomValue(stepsNodesAtom); const [asideInstantAtoms, dispatchAsideInstantAtoms] = useAtom(asideInstantAtomsAtom) const onNextStep = (confirmed?: 'clear' | 'not_clear') => { if (!confirmed) { if (curStep < viewedStep) { setConfirmClearAfterFlowModalOpen(true) } else { setCurStep(prev => prev + 1) } return } switch (confirmed) { case 'clear': // Clear node instant data after current node const nodesToClear = stepsNodes.slice(curStep + 1); const updatedCardInstantAtoms = R.pickBy( (_, key) => !nodesToClear.some(node => node.id === key), cardInstantAtoms ); dispatchCardInstantAtoms({ payload: updatedCardInstantAtoms, type: 'replace' }); const updatedAsideInstantAtoms = R.pickBy( (_, key) => !nodesToClear.some(node => node.id === key), asideInstantAtoms ) dispatchAsideInstantAtoms({ payload: updatedAsideInstantAtoms, type: 'replace' }) nodesToClear.forEach((node) => { console.log('removed: ', node.id) cardInstantAtomFamily.remove(node) asideInstantAtomFamily.remove(node) }) forceSetViewedStep(curStep); break; case 'not_clear': break; default: break; } setCurStep(prev => prev + 1) setConfirmClearAfterFlowModalOpen(false) } const onPrevStep = () => { setCurStep(prev => prev - 1) } const [isPreviewModalOpen, setPreviewModalOpen] = useState(false) const onPreview = () => { setPreviewModalOpen(true) } return (

{curStep + 1}: {nodeName}

{arrowState.prev && } {arrowState.next ? : }
setConfirmClearAfterFlowModalOpen(false)} onConfirm={onNextStep} /> setPreviewModalOpen(false)} />
) } export default React.memo(React.forwardRef(NodeRender))