Spaces:
Sleeping
Sleeping
| import { useEffect, useState, useRef } from 'react'; | |
| import styles from './index.module.less'; | |
| import classNames from 'classnames'; | |
| import CustomMarkdown from '../custom-markdown'; | |
| import IconFont from '../iconfont'; | |
| import PackIcon from '../../assets/pack-up.svg'; | |
| import PackDisableIcon from '../../assets/pack-up-disabled.svg'; | |
| import { Tooltip } from 'antd'; | |
| import QueryItem from './components/query-item'; | |
| import SearchItem from './components/search-item'; | |
| import Loading from '../loading'; | |
| import EmptyPlaceHolder from './components/empty-placeholder'; | |
| interface IProps { | |
| nodeInfo: any; | |
| stashInfo?: any; | |
| historyNode?: any; | |
| toggleRight: () => void; | |
| chatIsOver?: Boolean; | |
| } | |
| const ChatRight = ({ nodeInfo, historyNode = null, toggleRight, chatIsOver = false }: IProps) => { | |
| const [subQuestion, setSubQuestion] = useState(''); | |
| const [queries, setQuries] = useState<any>([]); | |
| const [searchList, setSearchList] = useState<any>([]); | |
| const [conclusionRef, setConclusionRef] = useState<any>(null); | |
| const [isLoading, setIsLoading] = useState(false); | |
| const [selectedIds, setSelectedIds] = useState([]); | |
| const [currentStep, setCurrentStep] = useState(0); | |
| const [conclusion, setConclusion] = useState(''); | |
| const [thinkingData, setThinking] = useState<any>(null); | |
| const [readingData, setReading] = useState<any>(null); | |
| const [isOutputing, setIsOutputing] = useState(false); | |
| // steps展开收起的信息 | |
| const [collapseInfo, setCollapseInfo] = useState<boolean[]>([true, true, true]); | |
| const [currentNode, setCurrentNode] = useState<any>(); | |
| // 展开收起 | |
| const toggleCard = (index: number) => { | |
| const arr = [...collapseInfo]; | |
| arr[index] = !arr[index]; | |
| setCollapseInfo(arr); | |
| }; | |
| // 高亮searchList | |
| const highLightSearchList = (ids: any) => { | |
| setCurrentStep(2); | |
| const highlightArr: any = [...searchList]; | |
| highlightArr.forEach((item: any) => { | |
| if (ids.includes(Number(item.id))) { | |
| item.highLight = true; | |
| } | |
| }); | |
| highlightArr.sort((item1: any, item2: any) => { | |
| if (item1.highLight === item2.highLight) { | |
| return 0; | |
| } | |
| // 如果item1是highlight,放在前面 | |
| if (item1.highLight) { | |
| return -1; | |
| } | |
| // 如果item2是highlight,放在后面 | |
| return 1; | |
| }); | |
| setSearchList(highlightArr); | |
| setCollapseInfo([false, false, true]); | |
| }; | |
| const handleReceiveHistory = () => { | |
| setCurrentNode(2); | |
| setCollapseInfo([false, false, true]); | |
| setIsLoading(false); | |
| setThinking(historyNode.thinkingData); | |
| setConclusion(historyNode.conclusion); | |
| setReading(historyNode.readingData); | |
| setQuries(historyNode.queries); | |
| setSearchList(historyNode.searchList); | |
| setConclusionRef(historyNode.conclusionRef); | |
| setSelectedIds(historyNode.selectedIds); | |
| setSubQuestion(historyNode.subQuestion); | |
| }; | |
| const resetStatus = () => { | |
| // 初始化组件状态 | |
| console.log('reset status-------'); | |
| setCurrentStep(0); | |
| setCollapseInfo([true, true, true]); | |
| setSelectedIds([]); | |
| setSearchList([]); | |
| setConclusionRef(null); | |
| setThinking(null); | |
| setReading(null); | |
| setConclusion(''); | |
| setSubQuestion(''); | |
| }; | |
| const hideRight = () => { | |
| if (isOutputing) return; | |
| toggleRight(); | |
| }; | |
| useEffect(() => { | |
| if (!historyNode) return; | |
| handleReceiveHistory(); | |
| }, [historyNode]); | |
| useEffect(() => { | |
| if (!selectedIds.length) return; | |
| highLightSearchList(selectedIds); | |
| }, [selectedIds]); | |
| useEffect(() => { | |
| if (historyNode) return; // 有历史记录,不处理 | |
| try { | |
| if (nodeInfo?.current_node !== currentNode) { | |
| setCurrentNode(nodeInfo?.current_node); | |
| resetStatus(); | |
| } | |
| setIsOutputing(nodeInfo?.outputing); | |
| if (!subQuestion && nodeInfo?.subQuestion) { | |
| setSubQuestion(nodeInfo.subQuestion); | |
| } | |
| if (nodeInfo?.thinkingData) { | |
| setThinking(nodeInfo.thinkingData); | |
| } | |
| if (nodeInfo?.readingData) { | |
| setReading(nodeInfo.readingData); | |
| } | |
| if (nodeInfo?.queries?.length) { | |
| setQuries(nodeInfo.queries); | |
| } | |
| if (nodeInfo?.searchList && !searchList?.length) { | |
| setSearchList(nodeInfo.searchList); | |
| setCurrentStep(1); | |
| setCollapseInfo([false, true, true]); | |
| } | |
| if (nodeInfo?.selectedIds && !selectedIds?.length) { | |
| setSelectedIds(nodeInfo.selectedIds); | |
| } | |
| if (nodeInfo?.conclusion) { | |
| setConclusion(nodeInfo.conclusion); | |
| } | |
| if (nodeInfo?.conclusionRef) { | |
| setConclusionRef(nodeInfo.conclusionRef); | |
| } | |
| } catch (err) { | |
| console.log('[chat right]--error from nodeinfo---', err); | |
| } | |
| }, [nodeInfo, currentStep]); | |
| return <div className={styles.rightContent} id="rightContent"> | |
| <div className={styles.toggleIcon} onClick={hideRight}> | |
| <img src={PackIcon} /> | |
| </div> | |
| { | |
| currentNode ? <> | |
| <div className={styles.titleNode}>{subQuestion}</div> | |
| <div className={classNames( | |
| styles.nodeInfo, | |
| isOutputing ? styles.forbidScroll : '' | |
| )}> | |
| {thinkingData && ( | |
| <div className={classNames(styles.steps)}> | |
| <div className={styles.title}> | |
| <i></i>思考 | |
| <div | |
| className={styles.open} | |
| onClick={() => { | |
| toggleCard(0); | |
| }} | |
| > | |
| <IconFont type={collapseInfo[0] ? 'icon-shouqi' : 'icon-xiangxiazhankai'} /> | |
| </div> | |
| </div> | |
| <div className={classNames(styles.con, !collapseInfo[0] ? styles.collapsed : '')}> | |
| <div> | |
| <CustomMarkdown source={thinkingData} /> | |
| </div> | |
| {queries.length > 0 && ( | |
| <div className={styles.query}> | |
| <div className={styles.subTitle}> | |
| <IconFont type="icon-SearchOutlined" /> | |
| 搜索关键词 | |
| </div> | |
| {queries.map((item: string, index: number) => ( | |
| <QueryItem key={`query-item-${item}`} item={item} /> | |
| ))} | |
| </div> | |
| )} | |
| {searchList.length > 0 && currentStep === 0 && ( | |
| <div className={styles.searchList}> | |
| <div className={styles.subTitle}> | |
| <IconFont type="icon-DocOutlined" /> | |
| 信息来源 | |
| </div> | |
| <div className={styles.scrollCon} style={searchList.length > 5 ? { height: '542px' } : {}}> | |
| <div className={styles.inner} style={searchList.length > 5 ? {} : {}}> | |
| {searchList.map((item: any) => ( | |
| <SearchItem item={item} key={`search-item-${item.url}`} /> | |
| ))} | |
| </div> | |
| </div> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| )} | |
| {currentStep > 0 && readingData && ( | |
| <div className={classNames(styles.steps)}> | |
| <div className={styles.title}> | |
| <i></i>信息来源 | |
| <div | |
| className={styles.open} | |
| onClick={() => { | |
| toggleCard(1); | |
| }} | |
| > | |
| <IconFont type={collapseInfo[1] ? 'icon-shouqi' : 'icon-xiangxiazhankai'} /> | |
| </div> | |
| </div> | |
| <div className={classNames(styles.con, !collapseInfo[1] ? styles.collapsed : '')}> | |
| <div className={styles.draft}> | |
| <CustomMarkdown source={readingData} /> | |
| </div> | |
| {searchList.length > 0 && ( | |
| <div className={styles.searchList}> | |
| <div className={styles.scrollCon} style={searchList.length > 5 ? { height: '542px' } : {}}> | |
| <div className={styles.inner} style={searchList.length > 5 ? {} : {}}> | |
| {searchList.map((item: any) => ( | |
| <SearchItem item={item} key={`search-item-${item.url}`} /> | |
| ))} | |
| </div> | |
| </div> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| )} | |
| { | |
| conclusion && ( | |
| <div className={classNames(styles.steps)}> | |
| <div className={styles.title}> | |
| <i></i>信息整合 | |
| <div | |
| className={styles.open} | |
| onClick={() => { | |
| toggleCard(2); | |
| }} | |
| > | |
| <IconFont type={collapseInfo[2] ? 'icon-shouqi' : 'icon-xiangxiazhankai'} /> | |
| </div> | |
| </div> | |
| <div | |
| id="nodeConclusionModule" | |
| className={classNames( | |
| styles.con, | |
| !collapseInfo[2] ? styles.collapsed : '', | |
| isOutputing ? styles.limitHeight : '' | |
| )} | |
| > | |
| <div id="conclusionInfo"> | |
| <CustomMarkdown source={conclusion} refList={chatIsOver ? conclusionRef : null} /> | |
| </div> | |
| </div> | |
| </div> | |
| )} | |
| {isLoading && <Loading />} | |
| </div></> : <EmptyPlaceHolder /> | |
| } | |
| </div> | |
| }; | |
| export default ChatRight; | |