问答助手完成子组件反对填写反馈建议模态框确认按钮loading加载,增加confirmLoading状态,并改确认事件为异步,传递至父组件

问答助手解决Popconfirm气泡确认框不触发的问题,为Dify二次开发问答助手前端的Tooltip导致及Popconfirm需在Button按钮的上一级才可触发,将Dify的Tooltip更换成Ant Design的Tooltip,此气泡确认框的作用为取消赞成及取消反对时进行确认,而不是直接取消
This commit is contained in:
wenyongda 2025-07-23 17:28:10 +08:00
parent 36f93db93f
commit 26cd7f7e8f
5 changed files with 60 additions and 31 deletions

View File

@ -4,7 +4,8 @@ import { t } from 'i18next'
import { debounce } from 'lodash-es' import { debounce } from 'lodash-es'
import copy from 'copy-to-clipboard' import copy from 'copy-to-clipboard'
import s from './style.module.css' import s from './style.module.css'
import Tooltip from '@/app/components/base/tooltip' // import Tooltip from '@/app/components/base/tooltip'
import { Tooltip } from 'antd';
type ICopyBtnProps = { type ICopyBtnProps = {
value: string value: string
@ -31,8 +32,7 @@ const CopyBtn = ({
return ( return (
<div className={`${className}`}> <div className={`${className}`}>
<Tooltip <Tooltip
popupContent={(isCopied ? t('appApi.copied') : t('appApi.copy'))} title={(isCopied ? t('appApi.copied') : t('appApi.copy'))}
asChild={false}
> >
<div <div
onMouseLeave={onMouseLeave} onMouseLeave={onMouseLeave}

View File

@ -1,7 +1,8 @@
'use client' 'use client'
import { t } from 'i18next' import { t } from 'i18next'
import { Refresh } from '@/app/components/base/icons/src/vender/line/general' import { Refresh } from '@/app/components/base/icons/src/vender/line/general'
import Tooltip from '@/app/components/base/tooltip' // import Tooltip from '@/app/components/base/tooltip'
import { Tooltip } from 'antd';
type Props = { type Props = {
className?: string className?: string
@ -12,7 +13,7 @@ const RegenerateBtn = ({ className, onClick }: Props) => {
return ( return (
<div className={`${className}`}> <div className={`${className}`}>
<Tooltip <Tooltip
popupContent={t('appApi.regenerate') as string} title={t('appApi.regenerate') as string}
> >
<div <div
className={'box-border p-0.5 flex items-center justify-center rounded-md bg-white cursor-pointer'} className={'box-border p-0.5 flex items-center justify-center rounded-md bg-white cursor-pointer'}

View File

@ -6,7 +6,7 @@ const { TextArea } = Input;
interface FeedbackModalProps { interface FeedbackModalProps {
open: boolean; open: boolean;
onOk: (selectedOption: number | null, feedbackText: string) => void; onOk: (selectedOption: number | null, feedbackText: string) => Promise<void>;
onCancel: () => void; onCancel: () => void;
} }
@ -14,12 +14,20 @@ const FeedbackModal: React.FC<FeedbackModalProps> = ({ open, onOk, onCancel }) =
const [selectedOption, setSelectedOption] = useState<number | null>(null); const [selectedOption, setSelectedOption] = useState<number | null>(null);
const [feedbackText, setFeedbackText] = useState<string>(''); const [feedbackText, setFeedbackText] = useState<string>('');
const { t } = useTranslation() const { t } = useTranslation()
const handleOk = () => { const [confirmLoading, setConfirmLoading] = useState(false);
const handleOk = async () => {
if (!feedbackText) { if (!feedbackText) {
message.warning('请填写反馈建议'); message.warning('请填写反馈建议');
return; return;
} }
onOk(selectedOption, feedbackText); setConfirmLoading(true)
try {
await onOk(selectedOption, feedbackText);
} finally {
setConfirmLoading(false)
}
}; };
return ( return (
@ -30,6 +38,7 @@ const FeedbackModal: React.FC<FeedbackModalProps> = ({ open, onOk, onCancel }) =
onCancel={onCancel} onCancel={onCancel}
okText={`${t('common.operation.confirm')}`} okText={`${t('common.operation.confirm')}`}
cancelText={`${t('common.operation.cancel')}`} cancelText={`${t('common.operation.cancel')}`}
confirmLoading={confirmLoading}
> >
{/* <div> {/* <div>
<Checkbox <Checkbox

View File

@ -690,7 +690,6 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
} }
setIsFeedbackModalVisible(false) setIsFeedbackModalVisible(false)
}} }}
// feedbackText={}
/> />
), ),
}; };

View File

@ -3,6 +3,7 @@ import {
memo, memo,
useMemo, useMemo,
useState, useState,
useCallback
} from 'react' } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import type { ChatItem } from '../../types' import type { ChatItem } from '../../types'
@ -19,8 +20,9 @@ import {
ThumbsDown, ThumbsDown,
ThumbsUp, ThumbsUp,
} from '@/app/components/base/icons/src/vender/line/alertsAndFeedback' } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
import Tooltip from '@/app/components/base/tooltip' // import Tooltip from '@/app/components/base/tooltip'
import Log from '@/app/components/chat/log' import Log from '@/app/components/chat/log'
import { message, Popconfirm, Tooltip } from 'antd';
interface OperationProps { interface OperationProps {
item: ChatItem item: ChatItem
@ -80,6 +82,14 @@ const Operation: FC<OperationProps> = ({
} }
} }
const confirmCancelCallback = useCallback(async () => {
try {
await handleFeedback(null)
} finally {
message.success(localFeedback!.rating === 'like' ? `${t('appDebug.operation.cancelAgree')}成功` : `${t('appDebug.operation.cancelDisagree')}成功`)
}
}, [handleFeedback])
const operationWidth = useMemo(() => { const operationWidth = useMemo(() => {
let width = 0 let width = 0
if (!isOpeningStatement) if (!isOpeningStatement)
@ -171,7 +181,7 @@ const Operation: FC<OperationProps> = ({
{ {
config?.supportFeedback && !localFeedback?.rating && onFeedback && !isOpeningStatement && ( config?.supportFeedback && !localFeedback?.rating && onFeedback && !isOpeningStatement && (
<div className='hidden group-hover:flex shrink-0 items-center px-0.5 bg-white border-[0.5px] border-gray-100 shadow-md text-gray-500 rounded-lg'> <div className='hidden group-hover:flex shrink-0 items-center px-0.5 bg-white border-[0.5px] border-gray-100 shadow-md text-gray-500 rounded-lg'>
<Tooltip popupContent={t('appDebug.operation.agree')}> <Tooltip title={t('appDebug.operation.agree')}>
<div <div
className='flex items-center justify-center mr-0.5 w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer' className='flex items-center justify-center mr-0.5 w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer'
onClick={() => handleFeedback('like')} onClick={() => handleFeedback('like')}
@ -180,7 +190,7 @@ const Operation: FC<OperationProps> = ({
</div> </div>
</Tooltip> </Tooltip>
<Tooltip <Tooltip
popupContent={t('appDebug.operation.disagree')} title={t('appDebug.operation.disagree')}
> >
<div <div
className='flex items-center justify-center w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer' className='flex items-center justify-center w-6 h-6 rounded-md hover:bg-black/5 hover:text-gray-800 cursor-pointer'
@ -195,15 +205,23 @@ const Operation: FC<OperationProps> = ({
{ {
config?.supportFeedback && localFeedback?.rating && onFeedback && !isOpeningStatement && ( config?.supportFeedback && localFeedback?.rating && onFeedback && !isOpeningStatement && (
<Tooltip <Tooltip
popupContent={localFeedback.rating === 'like' ? t('appDebug.operation.cancelAgree') : t('appDebug.operation.cancelDisagree')} title={localFeedback.rating === 'like' ? t('appDebug.operation.cancelAgree') : t('appDebug.operation.cancelDisagree')}
> >
<div <Popconfirm
title={localFeedback.rating === 'like' ? t('appDebug.operation.cancelAgree') : t('appDebug.operation.cancelDisagree')}
description={localFeedback.rating === 'like' ? `是否${t('appDebug.operation.cancelAgree')}` : `是否${t('appDebug.operation.cancelDisagree')}`}
onConfirm={confirmCancelCallback}
okText={`${t('common.operation.confirm')}`}
cancelText={`${t('common.operation.cancel')}`}
>
<button
type="button"
className={` className={`
flex items-center justify-center w-7 h-7 rounded-[10px] border-[2px] border-white cursor-pointer flex items-center justify-center w-7 h-7 rounded-[10px] border-[2px] border-white cursor-pointer
${localFeedback.rating === 'like' && 'bg-blue-50 text-blue-600'} ${localFeedback.rating === 'like' && 'bg-blue-50 text-blue-600'}
${localFeedback.rating === 'dislike' && 'bg-red-100 text-red-600'} ${localFeedback.rating === 'dislike' && 'bg-red-100 text-red-600'}
`} `}
onClick={() => handleFeedback(null)} onClick={(e) => e.stopPropagation()}
> >
{ {
localFeedback.rating === 'like' && ( localFeedback.rating === 'like' && (
@ -215,7 +233,9 @@ const Operation: FC<OperationProps> = ({
<ThumbsDown className='w-4 h-4' /> <ThumbsDown className='w-4 h-4' />
) )
} }
</div> </button>
</Popconfirm>
</Tooltip> </Tooltip>
) )
} }