Commit 3fa6b366 by Xianquan Committed by GitHub

fix: translations (#7182)

* fix: translations

* chore: add more translateY

* fix: button bgc
parent 579f5270
...@@ -489,6 +489,7 @@ ...@@ -489,6 +489,7 @@
"type.hidden": "Hide app", "type.hidden": "Hide app",
"type_http_tool_set_intro": "Batch import API tool", "type_http_tool_set_intro": "Batch import API tool",
"type_mcp_intro": "Connect to MCP service", "type_mcp_intro": "Connect to MCP service",
"type_not_recognized": "Unable to recognize app type. Please check the imported JSON configuration.",
"type_plugin_description": "Output the specified results with one click.", "type_plugin_description": "Output the specified results with one click.",
"type_plugin_intro": "Commonly used to encapsulate workflow", "type_plugin_intro": "Commonly used to encapsulate workflow",
"type_simple_description": "The most basic conversation application, no complicated configuration is required, and it can be created and used quickly.", "type_simple_description": "The most basic conversation application, no complicated configuration is required, and it can be created and used quickly.",
......
...@@ -489,6 +489,7 @@ ...@@ -489,6 +489,7 @@
"type.hidden": "隐藏应用", "type.hidden": "隐藏应用",
"type_http_tool_set_intro": "批量导入 API 工具", "type_http_tool_set_intro": "批量导入 API 工具",
"type_mcp_intro": "连接 MCP 服务", "type_mcp_intro": "连接 MCP 服务",
"type_not_recognized": "无法识别应用类型,请检查导入的 JSON 配置",
"type_plugin_description": "一键输出指定结果。", "type_plugin_description": "一键输出指定结果。",
"type_plugin_intro": "常用于封装工作流", "type_plugin_intro": "常用于封装工作流",
"type_simple_description": "最基础的对话应用,无需复杂配置,快速创建和使用。", "type_simple_description": "最基础的对话应用,无需复杂配置,快速创建和使用。",
......
...@@ -476,6 +476,7 @@ ...@@ -476,6 +476,7 @@
"type.hidden": "隱藏應用", "type.hidden": "隱藏應用",
"type_http_tool_set_intro": "批量導入 API 工具", "type_http_tool_set_intro": "批量導入 API 工具",
"type_mcp_intro": "連接 MCP 服務", "type_mcp_intro": "連接 MCP 服務",
"type_not_recognized": "無法識別應用類型,請檢查匯入的 JSON 設定",
"type_plugin_description": "一鍵輸出指定結果。", "type_plugin_description": "一鍵輸出指定結果。",
"type_plugin_intro": "常用於封裝工作流", "type_plugin_intro": "常用於封裝工作流",
"type_simple_description": "最基礎的對話應用,無需複雜配置,快速創建和使用。", "type_simple_description": "最基礎的對話應用,無需複雜配置,快速創建和使用。",
......
...@@ -28,6 +28,8 @@ type AIChatBubbleActionsProps = { ...@@ -28,6 +28,8 @@ type AIChatBubbleActionsProps = {
responseData?: ChatHistoryItemResType[]; responseData?: ChatHistoryItemResType[];
}; };
const footerActionTransition = 'color 180ms ease, transform 180ms ease, filter 180ms ease';
const AIChatBubbleActions = ({ const AIChatBubbleActions = ({
chatControllerProps, chatControllerProps,
historyItem, historyItem,
...@@ -38,7 +40,11 @@ const AIChatBubbleActions = ({ ...@@ -38,7 +40,11 @@ const AIChatBubbleActions = ({
responseData responseData
}: AIChatBubbleActionsProps) => { }: AIChatBubbleActionsProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { onRetry, feedbackUserName } = chatControllerProps; const { onRetry, feedbackUserName, disableFooterHoverTranslate } = chatControllerProps;
const footerActionHoverStyle = {
color: 'primary.600',
...(!disableFooterHoverTranslate ? { transform: 'translateY(-1px)' } : {})
};
const { isPc } = useSystem(); const { isPc } = useSystem();
const chatType = useContextSelector(ChatBoxContext, (v) => v.chatType); const chatType = useContextSelector(ChatBoxContext, (v) => v.chatType);
const showRetry = chatType !== ChatTypeEnum.log && !!onRetry; const showRetry = chatType !== ChatTypeEnum.log && !!onRetry;
...@@ -85,7 +91,8 @@ const AIChatBubbleActions = ({ ...@@ -85,7 +91,8 @@ const AIChatBubbleActions = ({
p={'4px'} p={'4px'}
cursor={'pointer'} cursor={'pointer'}
color={'myGray.400'} color={'myGray.400'}
_hover={{ color: 'primary.600' }} transition={footerActionTransition}
_hover={footerActionHoverStyle}
onClick={onOpenWholeModal} onClick={onOpenWholeModal}
> >
<MyIcon name={'core/chat/terminal'} w={'16px'} /> <MyIcon name={'core/chat/terminal'} w={'16px'} />
...@@ -122,7 +129,8 @@ const AIChatBubbleActions = ({ ...@@ -122,7 +129,8 @@ const AIChatBubbleActions = ({
p={'4px'} p={'4px'}
cursor={'pointer'} cursor={'pointer'}
color={'myGray.400'} color={'myGray.400'}
_hover={{ color: 'primary.600' }} transition={footerActionTransition}
_hover={footerActionHoverStyle}
onClick={onRetry} onClick={onRetry}
/> />
</MyTooltip> </MyTooltip>
......
...@@ -320,7 +320,7 @@ const ChatController = ({ ...@@ -320,7 +320,7 @@ const ChatController = ({
h={'22px'} h={'22px'}
color={'primary.600'} color={'primary.600'}
borderRadius={'sm'} borderRadius={'sm'}
_hover={{ bg: 'primary.50' }} _hover={{ bg: 'rgba(17, 24, 36, 0.05)' }}
isLoading={isLoadingOnToggleFeedbackReadStatus} isLoading={isLoadingOnToggleFeedbackReadStatus}
onClick={requestOnToggleFeedbackReadStatus} onClick={requestOnToggleFeedbackReadStatus}
> >
......
...@@ -11,6 +11,66 @@ import { normalizeFormInputResultFile } from '../../../components/FormInputResul ...@@ -11,6 +11,66 @@ import { normalizeFormInputResultFile } from '../../../components/FormInputResul
import type { ChatSiteItemType } from '../type'; import type { ChatSiteItemType } from '../type';
/** /**
* 用户选择规划 Agent 选项后,前端会立即追加 Human/AI 占位消息。
* 这里把答案乐观写回对应的 agentPlanAskQuery,避免旧消息在失去 isLastChild 后丢失选中态。
*/
export const persistAgentPlanAskAnswerToHistories = ({
histories,
interactive,
answer
}: {
histories: ChatSiteItemType[];
interactive: WorkflowInteractiveResponseType;
answer: string;
}): ChatSiteItemType[] => {
const sourceInteractive = extractDeepestInteractive(interactive);
if (sourceInteractive.type !== 'agentPlanAskQuery') {
return histories;
}
const targetPlanId = sourceInteractive.planId;
let hasUpdated = false;
const nextHistories = histories.map((item) => {
if (item.obj !== ChatRoleEnum.AI) return item;
let itemUpdated = false;
const nextValues = item.value.map((val) => {
if (!('interactive' in val) || !val.interactive) return val;
const finalInteractive = extractDeepestInteractive(val.interactive);
if (finalInteractive.type !== 'agentPlanAskQuery') return val;
if (finalInteractive.params.answer) return val;
if (targetPlanId && finalInteractive.planId && finalInteractive.planId !== targetPlanId) {
return val;
}
itemUpdated = true;
hasUpdated = true;
return {
...val,
interactive: {
...finalInteractive,
params: {
...finalInteractive.params,
answer
}
}
};
});
if (!itemUpdated) return item;
return {
...item,
value: nextValues
};
});
return hasUpdated ? nextHistories : histories;
};
/**
* 恢复流收到 `flowNodeResponse` 且带 `formInputResult` 时,把节点结果写回已提交的表单交互节点。 * 恢复流收到 `flowNodeResponse` 且带 `formInputResult` 时,把节点结果写回已提交的表单交互节点。
* *
* 匹配目标交互节点(二者满足其一即可): * 匹配目标交互节点(二者满足其一即可):
...@@ -208,8 +268,24 @@ export const rewriteHistoriesByInteractiveResponse = ({ ...@@ -208,8 +268,24 @@ export const rewriteHistoriesByInteractiveResponse = ({
return histories.slice(0, -2); return histories.slice(0, -2);
})(); })();
const newHistories = formatHistories.map((item, i) => { const workingHistories =
if (i !== formatHistories.length - 1) return item; status === 'query'
? persistAgentPlanAskAnswerToHistories({
histories: formatHistories,
interactive,
answer: interactiveVal
})
: formatHistories;
const newHistories = workingHistories.map((item, i) => {
if (i !== workingHistories.length - 1) return item;
if (status === 'query') {
return {
...item,
status: ChatStatusEnum.loading
} as ChatSiteItemType;
}
const value = item.value.map((val, i) => { const value = item.value.map((val, i) => {
if (i !== item.value.length - 1) { if (i !== item.value.length - 1) {
......
...@@ -224,6 +224,31 @@ describe('rewriteHistoriesByInteractiveResponse', () => { ...@@ -224,6 +224,31 @@ describe('rewriteHistoriesByInteractiveResponse', () => {
status: ChatStatusEnum.loading status: ChatStatusEnum.loading
}); });
}); });
it('persists agentPlanAskQuery answer on the previous AI message for query responses', () => {
const interactive = {
...baseInteractive,
planId: 'plan-1',
type: 'agentPlanAskQuery',
params: {
content: 'Need more detail',
options: ['A', 'B', 'C']
}
} as WorkflowInteractiveResponseType;
const histories = [createAiRecord(interactive), createHumanRecord(), createAiPlaceholder()];
const result = rewriteHistoriesByInteractiveResponse({
histories,
interactive,
interactiveVal: 'B'
});
expect((result[0].value[0] as any).interactive.params.answer).toBe('B');
expect(result[2]).toEqual({
...histories[2],
status: ChatStatusEnum.loading
});
});
}); });
describe('resolveInteractiveResponseChatItemId', () => { describe('resolveInteractiveResponseChatItemId', () => {
......
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 sign in to comment