Commit f520e296 by Liu

feat:问答后增加跳转逻辑

parent a5a5bf7e
...@@ -5,7 +5,6 @@ import { useLocalStorageState, useToggle } from 'ahooks' ...@@ -5,7 +5,6 @@ import { useLocalStorageState, useToggle } from 'ahooks'
import { LoginModal } from '../LoginModal' import { LoginModal } from '../LoginModal'
import type { RootState } from '@/store' import type { RootState } from '@/store'
import SendIcon from '@/assets/svg/send.svg?react' import SendIcon from '@/assets/svg/send.svg?react'
import dataIcon from '@/assets/data-icon.png'
import efficiencyIcon from '@/assets/efficiency-icon.png' import efficiencyIcon from '@/assets/efficiency-icon.png'
import { type WithAuthProps, withAuth } from '@/auth/withAuth' import { type WithAuthProps, withAuth } from '@/auth/withAuth'
import { useAppSelector } from '@/store/hook' import { useAppSelector } from '@/store/hook'
...@@ -143,12 +142,14 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth, ...@@ -143,12 +142,14 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
onPaste={handlePaste} onPaste={handlePaste}
suppressContentEditableWarning suppressContentEditableWarning
data-placeholder="输入您想问的问题吧~"
style={{ style={{
resize: 'none', resize: 'none',
maxHeight: '48px', maxHeight: '48px',
marginBottom: '40px', marginBottom: '40px',
}} }}
/> >
</div>
<Tooltip isOpen={Boolean(token) && showContentTips && !isAsking && !content} color="foreground" content="请输入您的问题📖" placement="top-end"> <Tooltip isOpen={Boolean(token) && showContentTips && !isAsking && !content} color="foreground" content="请输入您的问题📖" placement="top-end">
<Button className="ask-send" onPress={handleSubmit} radius="full" isDisabled={!content || isAsking} isIconOnly color="primary"> <Button className="ask-send" onPress={handleSubmit} radius="full" isDisabled={!content || isAsking} isIconOnly color="primary">
<SendIcon /> <SendIcon />
...@@ -177,20 +178,19 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth, ...@@ -177,20 +178,19 @@ const ChatEditorBase: React.FC<ChatEditorProps & WithAuthProps> = ({ checkAuth,
}} }}
className="dark:text-zinc-500 text-[14px] sm:text-[14px] font-normal text-[#3333334d] pl-4 sm:pl-12 text-left w-[calc(100%-2rem)] truncate" className="dark:text-zinc-500 text-[14px] sm:text-[14px] font-normal text-[#3333334d] pl-4 sm:pl-12 text-left w-[calc(100%-2rem)] truncate"
> >
{placeholders[currentPlaceholder]}
</motion.p> </motion.p>
)} )}
</AnimatePresence> </AnimatePresence>
</div> </div>
<div className="absolute left-4 bottom-2 flex items-center gap-3 pointer-events-auto"> <div className="absolute left-4 bottom-2 flex items-center gap-3 pointer-events-auto pl-[16px]">
<Button {/* <Button
className="w-[96px] h-[32px] px-3 rounded-full bg-white border border-[#E6E8EB] shadow-none text-[#111827] text-[12px]" className="w-[96px] h-[32px] px-3 rounded-full bg-white border border-[#E6E8EB] shadow-none text-[#111827] text-[12px]"
radius="full" radius="full"
variant="bordered" variant="bordered"
startContent={<img src={dataIcon} alt="数据助手" className="w-5 h-5" />} startContent={<img src={dataIcon} alt="数据助手" className="w-5 h-5" />}
> >
数据助手 数据助手
</Button> </Button> */}
<Button <Button
className="w-[96px] h-[32px] px-3 rounded-full bg-white border border-[#E6E8EB] shadow-none text-[#111827] text-[12px]" className="w-[96px] h-[32px] px-3 rounded-full bg-white border border-[#E6E8EB] shadow-none text-[#111827] text-[12px]"
radius="full" radius="full"
......
...@@ -42,6 +42,7 @@ export const ChatAnswerParser: React.FC<ChatAnswerParserProps> = ({ isLastAnswer ...@@ -42,6 +42,7 @@ export const ChatAnswerParser: React.FC<ChatAnswerParserProps> = ({ isLastAnswer
const [isTyping, setIsTyping] = useState(false) const [isTyping, setIsTyping] = useState(false)
const [hideOperate, setHideOperate] = useState(false) const [hideOperate, setHideOperate] = useState(false)
const [isImageAnswer, setIsImageAnswer] = useState(false) const [isImageAnswer, setIsImageAnswer] = useState(false)
const [hasProcessedCardList, setHasProcessedCardList] = useState(false) // 添加标记,避免重复处理cardList
function extractImageSources(htmlString: string): string[] { function extractImageSources(htmlString: string): string[] {
const imgRegex = /<img[^>]+src="([^">]+)"/gi const imgRegex = /<img[^>]+src="([^">]+)"/gi
...@@ -90,6 +91,28 @@ export const ChatAnswerParser: React.FC<ChatAnswerParserProps> = ({ isLastAnswer ...@@ -90,6 +91,28 @@ export const ChatAnswerParser: React.FC<ChatAnswerParserProps> = ({ isLastAnswer
onComplate() onComplate()
} }
const handleCardListUrls = () => {
// 如果已经处理过cardList,直接返回,避免重复警告
if (hasProcessedCardList) {
return
}
if (answer.cardList && answer.cardList.length > 0) {
const cardsWithUrl = answer.cardList[0].url || ''
// eslint-disable-next-line no-console
console.log('准备跳转的URL:', cardsWithUrl)
if (cardsWithUrl) {
window.open(cardsWithUrl, '_blank')
}
else {
console.warn('cardList中的URL为空')
}
}
else {
console.warn('cardList为空或不存在')
}
setHasProcessedCardList(true) // 标记已处理
}
useEffect(() => { useEffect(() => {
if (isStopTyping) { if (isStopTyping) {
return return
...@@ -124,6 +147,8 @@ export const ChatAnswerParser: React.FC<ChatAnswerParserProps> = ({ isLastAnswer ...@@ -124,6 +147,8 @@ export const ChatAnswerParser: React.FC<ChatAnswerParserProps> = ({ isLastAnswer
setIsTyping(false) setIsTyping(false)
onComplate() onComplate()
} }
// 流式输出结束时检查 cardList 中的 URL
handleCardListUrls()
} }
} }
}, [answer, currentIndex]) }, [answer, currentIndex])
......
...@@ -32,3 +32,11 @@ body { ...@@ -32,3 +32,11 @@ body {
color: var(--sdream-text-primary); color: var(--sdream-text-primary);
overflow: hidden; overflow: hidden;
} }
// contentEditable placeholder样式
[contenteditable]:empty:before {
content: attr(data-placeholder);
color: rgba(51,51,51,0.3);
pointer-events: none;
font-size: 15px;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment