fix(web): ai prompt editor update

This commit is contained in:
zhaoying
2026-01-07 17:34:45 +08:00
parent 7a1131d8af
commit 72c27273e4
6 changed files with 98 additions and 27 deletions

View File

@@ -1144,6 +1144,8 @@ export const en = {
merge: 'Complete Aggregation', merge: 'Complete Aggregation',
vote: 'Key Information Extraction', vote: 'Key Information Extraction',
priority: 'Structured Integration', priority: 'Structured Integration',
addTool: 'Add Tool',
tool: 'Tool',
}, },
userMemory: { userMemory: {
userMemory: 'User Memory', userMemory: 'User Memory',
@@ -1201,6 +1203,7 @@ export const en = {
IMPLICIT_MEMORY: 'Implicit Memory', IMPLICIT_MEMORY: 'Implicit Memory',
EMOTIONAL_MEMORY: 'Emotional Memory', EMOTIONAL_MEMORY: 'Emotional Memory',
EPISODIC_MEMORY: 'Episodic Memory', EPISODIC_MEMORY: 'Episodic Memory',
FORGETTING_MANAGEMENT: 'Forgetting Management',
endUserProfile: 'Core Profile', endUserProfile: 'Core Profile',
editEndUserProfile: 'Edit', editEndUserProfile: 'Edit',
@@ -1833,6 +1836,7 @@ Memory Bear: After the rebellion, regional warlordism intensified for several re
status_code: 'Status Code', status_code: 'Status Code',
max_attempts: 'Max Retry Attempts', max_attempts: 'Max Retry Attempts',
retry_interval: 'Retry Interval', retry_interval: 'Retry Interval',
errorBranch: 'Error Branch',
}, },
'jinja-render': { 'jinja-render': {
template: 'Code', template: 'Code',

View File

@@ -633,6 +633,8 @@ export const zh = {
merge: '完整汇总', merge: '完整汇总',
vote: '关键信息提取', vote: '关键信息提取',
priority: '结构化整合', priority: '结构化整合',
addTool: '添加工具',
tool: '工具',
}, },
// 角色管理相关翻译 // 角色管理相关翻译
role: { role: {
@@ -1280,6 +1282,7 @@ export const zh = {
IMPLICIT_MEMORY: '隐性记忆', IMPLICIT_MEMORY: '隐性记忆',
EMOTIONAL_MEMORY: '情绪记忆', EMOTIONAL_MEMORY: '情绪记忆',
EPISODIC_MEMORY: '情景记忆', EPISODIC_MEMORY: '情景记忆',
FORGETTING_MANAGEMENT: '遗忘',
endUserProfile: '核心档案', endUserProfile: '核心档案',
editEndUserProfile: '编辑', editEndUserProfile: '编辑',
@@ -1933,6 +1936,7 @@ export const zh = {
status_code: '状态码', status_code: '状态码',
max_attempts: '最大重试次数', max_attempts: '最大重试次数',
retry_interval: '重试间隔', retry_interval: '重试间隔',
errorBranch: '异常分支',
}, },
'jinja-render': { 'jinja-render': {
template: '代码', template: '代码',
@@ -2246,5 +2250,12 @@ export const zh = {
orderPayInfo: '支付信息', orderPayInfo: '支付信息',
create_time: '创建时间', create_time: '创建时间',
}, },
forgetDetail: {
title: '遗忘管理系统帮助AI智能管理记忆生命周期通过自动识别低价值记忆、设置遗忘策略和执行定期清理优化记忆库存储空间提升检索效率。',
overviewTitle: '核心指标概览',
totalMemory: '记忆总量',
MemoryHealth: '记忆健康度',
riskOfForgetting: '遗忘风险',
}
}, },
} }

View File

@@ -19,7 +19,6 @@ import type {
MemoryConfig, MemoryConfig,
AiPromptModalRef, AiPromptModalRef,
Source, Source,
ToolModalRef,
ToolOption ToolOption
} from './types' } from './types'
import type { Model } from '@/views/ModelManagement/types' import type { Model } from '@/views/ModelManagement/types'
@@ -33,7 +32,6 @@ import { memoryConfigListUrl } from '@/api/memory'
import CustomSelect from '@/components/CustomSelect' import CustomSelect from '@/components/CustomSelect'
import aiPrompt from '@/assets/images/application/aiPrompt.png' import aiPrompt from '@/assets/images/application/aiPrompt.png'
import AiPromptModal from './components/AiPromptModal' import AiPromptModal from './components/AiPromptModal'
import ToolModal from './components/ToolModal'
import ToolList from './components/ToolList' import ToolList from './components/ToolList'
const DescWrapper: FC<{desc: string, className?: string}> = ({desc, className}) => { const DescWrapper: FC<{desc: string, className?: string}> = ({desc, className}) => {
@@ -115,6 +113,7 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
const [variableList, setVariableList] = useState<Variable[]>([]) const [variableList, setVariableList] = useState<Variable[]>([])
const [isSave, setIsSave] = useState(false) const [isSave, setIsSave] = useState(false)
const initialized = useRef(false) const initialized = useRef(false)
const [toolList, setToolList] = useState<ToolOption[]>([])
// 初始化完成标记 // 初始化完成标记
useEffect(() => { useEffect(() => {
@@ -143,6 +142,11 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
if (isSave) return if (isSave) return
setIsSave(true) setIsSave(true)
}, [values]) }, [values])
useEffect(() => {
if (!initialized.current) return
if (isSave) return
setIsSave(true)
}, [toolList])
useEffect(() => { useEffect(() => {
getModels() getModels()
@@ -294,7 +298,11 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
...(item.config || {}) ...(item.config || {})
})) }))
} as KnowledgeConfig : null, } as KnowledgeConfig : null,
tools: toolList tools: toolList.map(vo => ({
tool_id: vo.tool_id,
operation: vo.operation,
enabled: vo.enabled
}))
} }
console.log('params', rest, params) console.log('params', rest, params)
@@ -347,18 +355,6 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
form.setFieldValue('system_prompt', value) form.setFieldValue('system_prompt', value)
} }
const toolModalRef = useRef<ToolModalRef>(null)
const [toolList, setToolList] = useState<ToolOption[]>([])
const handleAddTool = () => {
toolModalRef.current?.handleOpen()
}
const updateTools = (tool: ToolOption) => {
const tools = [...toolList, tool]
setToolList(tools)
form.setFieldValue('tools', tools)
}
console.log('toolList', toolList)
return ( return (
<> <>
{loading && <Spin fullscreen></Spin>} {loading && <Spin fullscreen></Spin>}
@@ -469,10 +465,6 @@ const Agent = forwardRef<AgentRef>((_props, ref) => {
defaultModel={defaultModel} defaultModel={defaultModel}
refresh={updatePrompt} refresh={updatePrompt}
/> />
<ToolModal
ref={toolModalRef}
refresh={updateTools}
/>
</> </>
); );
}); });

View File

@@ -90,11 +90,19 @@ const AiPromptModal = forwardRef<AiPromptModalRef, AiPromptModalProps>(({
switch (item.event) { switch (item.event) {
case 'start': case 'start':
currentPromptValueRef.current = '' currentPromptValueRef.current = ''
if (editorRef.current?.clear) {
editorRef.current.clear();
}
break; break;
case 'message': case 'message':
if (content) { if (content) {
currentPromptValueRef.current += content; currentPromptValueRef.current += content;
form.setFieldsValue({ current_prompt: currentPromptValueRef.current }) if (editorRef.current?.appendText) {
editorRef.current.appendText(content);
editorRef.current.scrollToBottom();
} else {
form.setFieldsValue({ current_prompt: currentPromptValueRef.current })
}
} }
if (desc) { if (desc) {
setChatList(prev => { setChatList(prev => {
@@ -107,6 +115,8 @@ const AiPromptModal = forwardRef<AiPromptModalRef, AiPromptModalProps>(({
break; break;
case 'end': case 'end':
setLoading(false) setLoading(false)
// 流结束时同步表单值
form.setFieldsValue({ current_prompt: currentPromptValueRef.current })
break break
} }
}) })

View File

@@ -4,7 +4,7 @@ import { LexicalComposer } from '@lexical/react/LexicalComposer';
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'; import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
import { ContentEditable } from '@lexical/react/LexicalContentEditable'; import { ContentEditable } from '@lexical/react/LexicalContentEditable';
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary'; import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';
import { $getSelection } from 'lexical'; import { $getSelection, $getRoot, $createParagraphNode, $createTextNode, $isParagraphNode, $isTextNode } from 'lexical';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'; import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import InitialValuePlugin from './plugin/InitialValuePlugin' import InitialValuePlugin from './plugin/InitialValuePlugin'
import LineBreakPlugin from './plugin/LineBreakPlugin'; import LineBreakPlugin from './plugin/LineBreakPlugin';
@@ -12,6 +12,9 @@ import InsertTextPlugin from './plugin/InsertTextPlugin';
export interface EditorRef { export interface EditorRef {
insertText: (text: string) => void; insertText: (text: string) => void;
appendText: (text: string) => void;
clear: () => void;
scrollToBottom: () => void;
} }
interface LexicalEditorProps { interface LexicalEditorProps {
@@ -46,6 +49,41 @@ const EditorContent = forwardRef<EditorRef, LexicalEditorProps>(({
selection.insertText(text); selection.insertText(text);
} }
}); });
},
appendText: (text: string) => {
editor.update(() => {
const root = $getRoot();
const lastChild = root.getLastChild();
if (lastChild && $isParagraphNode(lastChild)) {
const lastTextNode = lastChild.getLastChild();
if (lastTextNode && $isTextNode(lastTextNode)) {
const currentText = lastTextNode.getTextContent();
lastTextNode.setTextContent(currentText + text);
} else {
const textNode = $createTextNode(text);
lastChild.append(textNode);
}
} else {
const paragraph = $createParagraphNode();
const textNode = $createTextNode(text);
paragraph.append(textNode);
root.append(paragraph);
}
});
},
clear: () => {
editor.update(() => {
const root = $getRoot();
root.clear();
const paragraph = $createParagraphNode();
root.append(paragraph);
});
},
scrollToBottom: () => {
const editorElement = editor.getRootElement();
if (editorElement) {
editorElement.scrollTop = editorElement.scrollHeight;
}
} }
}), [editor]); }), [editor]);

View File

@@ -1,21 +1,37 @@
import { type FC, useEffect } from 'react'; import { type FC, useEffect, useRef } from 'react';
import { $getRoot, $createParagraphNode, $createTextNode } from 'lexical'; import { $getRoot, $createParagraphNode, $createTextNode } from 'lexical';
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'; import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
// 设置初始值的插件 // 设置初始值的插件
const InitialValuePlugin: FC<{ value?: string }> = ({ value }) => { const InitialValuePlugin: FC<{ value?: string }> = ({ value }) => {
const [editor] = useLexicalComposerContext(); const [editor] = useLexicalComposerContext();
const lastValueRef = useRef<string | undefined>(undefined);
useEffect(() => { useEffect(() => {
if (value) { // 只有当value真正发生变化时才更新
if (lastValueRef.current !== value) {
editor.update(() => { editor.update(() => {
const root = $getRoot(); const root = $getRoot();
const currentText = root.getTextContent();
// 如果当前内容和新值相同,则不更新
if (currentText === (value || '')) {
return;
}
root.clear(); root.clear();
const paragraph = $createParagraphNode(); if (value) {
const textNode = $createTextNode(value); const paragraph = $createParagraphNode();
paragraph.append(textNode); const textNode = $createTextNode(value);
root.append(paragraph); paragraph.append(textNode);
root.append(paragraph);
} else {
// 当value为undefined或空时创建一个空段落
const paragraph = $createParagraphNode();
root.append(paragraph);
}
}); });
lastValueRef.current = value;
} }
}, [editor, value]); }, [editor, value]);