Merge branch 'refs/heads/release/v0.2.8' into fix/features_028
This commit is contained in:
@@ -172,7 +172,7 @@ def _retrieve_for_knowledge(
|
|||||||
return results, chat_model, embedding_model
|
return results, chat_model, embedding_model
|
||||||
|
|
||||||
# Folder 类型:递归处理子知识库
|
# Folder 类型:递归处理子知识库
|
||||||
if db_knowledge.type == knowledge_model.KnowledgeType.Folder:
|
if db_knowledge.type == knowledge_model.KnowledgeType.FOLDER:
|
||||||
children = knowledge_repository.get_knowledges_by_parent_id(db=db, parent_id=db_knowledge.id)
|
children = knowledge_repository.get_knowledges_by_parent_id(db=db, parent_id=db_knowledge.id)
|
||||||
for child in children:
|
for child in children:
|
||||||
if not (child and child.chunk_num > 0 and child.status == 1):
|
if not (child and child.chunk_num > 0 and child.status == 1):
|
||||||
|
|||||||
@@ -636,30 +636,33 @@ class WorkflowService:
|
|||||||
final_messages = result.get("messages", [])[init_message_length:]
|
final_messages = result.get("messages", [])[init_message_length:]
|
||||||
human_message = ""
|
human_message = ""
|
||||||
assistant_message = ""
|
assistant_message = ""
|
||||||
|
human_meta = {
|
||||||
|
"files": []
|
||||||
|
}
|
||||||
for message in final_messages:
|
for message in final_messages:
|
||||||
if message["role"] == "user":
|
if message["role"] == "user":
|
||||||
if isinstance(message["content"], str):
|
if isinstance(message["content"], str):
|
||||||
human_message += message["content"]
|
human_message += message["content"]
|
||||||
elif isinstance(message["content"], list):
|
elif isinstance(message["content"], list):
|
||||||
for file in message["content"]:
|
for file in message["content"]:
|
||||||
if file.get("type") == FileType.IMAGE:
|
human_meta["files"].append({
|
||||||
human_message += f"})"
|
"type": file.get("type"),
|
||||||
else:
|
"url": file.get("url")
|
||||||
human_message += f"[{file.get('type')}]({file.get('url', '')})"
|
})
|
||||||
if message["role"] == "assistant":
|
if message["role"] == "assistant":
|
||||||
assistant_message = message["content"]
|
assistant_message = message["content"]
|
||||||
self.conversation_service.add_message(
|
self.conversation_service.add_message(
|
||||||
conversation_id=conversation_id_uuid,
|
conversation_id=conversation_id_uuid,
|
||||||
role="user",
|
role="user",
|
||||||
content=human_message,
|
content=human_message,
|
||||||
meta_data=None
|
meta_data=human_meta
|
||||||
)
|
)
|
||||||
self.conversation_service.add_message(
|
self.conversation_service.add_message(
|
||||||
message_id=message_id,
|
message_id=message_id,
|
||||||
conversation_id=conversation_id_uuid,
|
conversation_id=conversation_id_uuid,
|
||||||
role="assistant",
|
role="assistant",
|
||||||
content=assistant_message,
|
content=assistant_message,
|
||||||
meta_data={"usage": token_usage}
|
meta_data={"usage": token_usage, "audio_url": None}
|
||||||
)
|
)
|
||||||
self.update_execution_status(
|
self.update_execution_status(
|
||||||
execution.execution_id,
|
execution.execution_id,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-02 15:01:59
|
* @Date: 2026-02-02 15:01:59
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-17 15:35:34
|
* @Last Modified time: 2026-03-19 13:41:26
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,7 +42,8 @@ const ButtonCheckbox: FC<ButtonCheckboxProps> = ({
|
|||||||
icon,
|
icon,
|
||||||
checkedIcon,
|
checkedIcon,
|
||||||
children,
|
children,
|
||||||
cicle = false
|
cicle = false,
|
||||||
|
disabled,
|
||||||
}) => {
|
}) => {
|
||||||
// Listen to value changes and trigger side effects via onValueChange callback
|
// Listen to value changes and trigger side effects via onValueChange callback
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -70,6 +71,7 @@ const ButtonCheckbox: FC<ButtonCheckboxProps> = ({
|
|||||||
"rb:bg-[rgba(21,94,239,0.06)] rb:border-[rgba(21,94,239,0.25)] rb:hover:bg-[rgba(21,94,239,0.06)] rb:text-[#155EEF]": checked,
|
"rb:bg-[rgba(21,94,239,0.06)] rb:border-[rgba(21,94,239,0.25)] rb:hover:bg-[rgba(21,94,239,0.06)] rb:text-[#155EEF]": checked,
|
||||||
// Unchecked state: gray border and dark text
|
// Unchecked state: gray border and dark text
|
||||||
"rb:border-[#DFE4ED] rb:text-[#212332]": !checked,
|
"rb:border-[#DFE4ED] rb:text-[#212332]": !checked,
|
||||||
|
"rb:opacity-65 rb:cursor-not-allowed!": disabled
|
||||||
})}
|
})}
|
||||||
onClick={handleChange}
|
onClick={handleChange}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2025-12-10 16:46:17
|
* @Date: 2025-12-10 16:46:17
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-19 10:37:01
|
* @Last Modified time: 2026-03-19 13:38:20
|
||||||
*/
|
*/
|
||||||
import { type FC, useRef, useEffect, useState } from 'react'
|
import { type FC, useRef, useEffect, useState } from 'react'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
@@ -118,7 +118,7 @@ const ChatContent: FC<ChatContentProps> = ({
|
|||||||
{labelFormat(item)}
|
{labelFormat(item)}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{item.meta_data?.files && item.meta_data?.files.length > 0 && <Flex vertical align="end">
|
{item.meta_data?.files && item.meta_data?.files.length > 0 && <Flex gap={8} vertical align="end">
|
||||||
{item.meta_data?.files?.map((file) => {
|
{item.meta_data?.files?.map((file) => {
|
||||||
if (file.type.includes('image')) {
|
if (file.type.includes('image')) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2025-12-10 16:46:14
|
* @Date: 2025-12-10 16:46:14
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-06 13:36:20
|
* @Last Modified time: 2026-03-19 16:05:56
|
||||||
*/
|
*/
|
||||||
import { type FC, useEffect, useMemo } from 'react'
|
import { type FC, useEffect, useMemo } from 'react'
|
||||||
import { Flex, Input, Form } from 'antd'
|
import { Flex, Input, Form } from 'antd'
|
||||||
@@ -109,15 +109,20 @@ const ChatInput: FC<ChatInputProps> = ({
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div key={file.url || file.uid} className="rb:w-45 rb:text-[12px] rb:gap-2.5 rb:flex rb:items-center rb:group rb:relative rb:rounded-lg rb:bg-[#F0F3F8] rb:py-2 rb:px-2.5">
|
<div key={file.url || file.uid} className="rb:w-45 rb:text-[12px] rb:gap-2.5 rb:flex rb:items-center rb:group rb:relative rb:rounded-lg rb:bg-[#F0F3F8] rb:py-2 rb:px-2.5">
|
||||||
{(file.type.includes('doc') || file.type.includes('docx') || file.type.includes('word') || file.type.includes('wordprocessingml.document')) && <div
|
{file.type.includes('pdf')
|
||||||
className="rb:size-5 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/conversation/word_disabled.svg')] rb:hover:bg-[url('@/assets/images/conversation/word.svg')]"
|
? <div
|
||||||
></div>}
|
className="rb:size-5 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/conversation/pdf_disabled.svg')] rb:hover:bg-[url('@/assets/images/conversation/pdf.svg')]"
|
||||||
{(file.type.includes('pdf')) && <div
|
></div>
|
||||||
className="rb:size-5 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/conversation/pdf_disabled.svg')] rb:hover:bg-[url('@/assets/images/conversation/pdf.svg')]"
|
: (file.type.includes('excel') || file.type.includes('spreadsheetml.sheet') || file.type.includes('csv'))
|
||||||
></div>}
|
? <div
|
||||||
{(file.type.includes('excel') || file.type.includes('spreadsheetml.sheet') || file.type.includes('csv')) && <div
|
className="rb:size-5 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/conversation/excel_disabled.svg')] rb:hover:bg-[url('@/assets/images/conversation/excel.svg')]"
|
||||||
className="rb:size-5 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/conversation/excel_disabled.svg')] rb:hover:bg-[url('@/assets/images/conversation/excel.svg')]"
|
></div>
|
||||||
></div>}
|
: (file.type.includes('doc') || file.type.includes('docx') || file.type.includes('word') || file.type.includes('wordprocessingml.document'))
|
||||||
|
? <div
|
||||||
|
className="rb:size-5 rb:cursor-pointer rb:bg-cover rb:bg-[url('@/assets/images/conversation/word_disabled.svg')] rb:hover:bg-[url('@/assets/images/conversation/word.svg')]"
|
||||||
|
></div>
|
||||||
|
: null
|
||||||
|
}
|
||||||
<div className="rb:flex-1 rb:w-32.5">
|
<div className="rb:flex-1 rb:w-32.5">
|
||||||
<div className="rb:leading-4 rb:text-ellipsis rb:overflow-hidden rb:whitespace-nowrap">{file.name}</div>
|
<div className="rb:leading-4 rb:text-ellipsis rb:overflow-hidden rb:whitespace-nowrap">{file.name}</div>
|
||||||
<div className="rb:leading-3.5 rb:mt-0.5 rb:text-[#5B6167] rb:text-ellipsis rb:overflow-hidden rb:whitespace-nowrap">{file.type} · {file.size}</div>
|
<div className="rb:leading-3.5 rb:mt-0.5 rb:text-[#5B6167] rb:text-ellipsis rb:overflow-hidden rb:whitespace-nowrap">{file.type} · {file.size}</div>
|
||||||
|
|||||||
@@ -1564,6 +1564,7 @@ export const en = {
|
|||||||
summary: 'Summary',
|
summary: 'Summary',
|
||||||
core_entities: 'Core Entities',
|
core_entities: 'Core Entities',
|
||||||
communityDetailEmptyDesc: 'Click on a community in the chart on the left to view details',
|
communityDetailEmptyDesc: 'Click on a community in the chart on the left to view details',
|
||||||
|
communityLoadingTip: 'Generating community graph',
|
||||||
},
|
},
|
||||||
space: {
|
space: {
|
||||||
createSpace: 'Create Space',
|
createSpace: 'Create Space',
|
||||||
|
|||||||
@@ -1562,6 +1562,7 @@ export const zh = {
|
|||||||
summary: '摘要',
|
summary: '摘要',
|
||||||
core_entities: '核心实体',
|
core_entities: '核心实体',
|
||||||
communityDetailEmptyDesc: '点击左侧图表中的社区查看详情',
|
communityDetailEmptyDesc: '点击左侧图表中的社区查看详情',
|
||||||
|
communityLoadingTip: '社区图谱生成中',
|
||||||
},
|
},
|
||||||
space: {
|
space: {
|
||||||
createSpace: '创建空间',
|
createSpace: '创建空间',
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 16:27:52
|
* @Date: 2026-02-03 16:27:52
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-18 21:25:23
|
* @Last Modified time: 2026-03-19 17:13:54
|
||||||
*/
|
*/
|
||||||
import { type FC, useRef, useMemo, useCallback } from 'react';
|
import { type FC, useRef, useMemo, useCallback } from 'react';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
@@ -212,7 +212,7 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({
|
|||||||
className={styles.tabs}
|
className={styles.tabs}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{application?.type === 'workflow' && source !== 'sharing'
|
{application?.type === 'workflow' && source !== 'sharing' && activeTab === 'arrangement'
|
||||||
? <div className="rb:h-8 rb:flex rb:items-center rb:justify-end rb:gap-2.5">
|
? <div className="rb:h-8 rb:flex rb:items-center rb:justify-end rb:gap-2.5">
|
||||||
<FeaturesConfig source={application?.type} value={features as FeaturesConfigForm} refresh={handleSaveFeaturesConfig} />
|
<FeaturesConfig source={application?.type} value={features as FeaturesConfigForm} refresh={handleSaveFeaturesConfig} />
|
||||||
<Button onClick={clear}>{t('workflow.clear')}</Button>
|
<Button onClick={clear}>{t('workflow.clear')}</Button>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-03-05
|
* @Date: 2026-03-05
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-19 09:59:42
|
* @Last Modified time: 2026-03-19 15:18:20
|
||||||
*/
|
*/
|
||||||
import { forwardRef, useImperativeHandle, useState } from 'react';
|
import { forwardRef, useImperativeHandle, useState } from 'react';
|
||||||
import { Form, InputNumber, Flex, Switch, Row, Col, Radio } from 'antd';
|
import { Form, InputNumber, Flex, Switch, Row, Col, Radio } from 'antd';
|
||||||
@@ -27,22 +27,43 @@ const fileTypeOptions = [
|
|||||||
{
|
{
|
||||||
type: 'document',
|
type: 'document',
|
||||||
icon: <div className="rb:size-9 rb:bg-cover rb:bg-[url('@/assets/images/file/txt.svg')]"></div>,
|
icon: <div className="rb:size-9 rb:bg-cover rb:bg-[url('@/assets/images/file/txt.svg')]"></div>,
|
||||||
formats: 'TXT, PDF, DOC, DOCX, XLSX, CSV, JSON',
|
formats: [
|
||||||
|
"pdf",
|
||||||
|
"docx",
|
||||||
|
"doc",
|
||||||
|
"xlsx",
|
||||||
|
"xls",
|
||||||
|
"txt",
|
||||||
|
"csv",
|
||||||
|
"json",
|
||||||
|
"md",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'image',
|
type: 'image',
|
||||||
icon: <div className="rb:size-9 rb:bg-cover rb:bg-[url('@/assets/images/file/image.svg')]"></div>,
|
icon: <div className="rb:size-9 rb:bg-cover rb:bg-[url('@/assets/images/file/image.svg')]"></div>,
|
||||||
formats: 'JPG, JPEG, PNG, GIF, WEBP',
|
formats: [
|
||||||
|
"png",
|
||||||
|
"jpg",
|
||||||
|
"jpeg"
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'audio',
|
type: 'audio',
|
||||||
icon: <div className="rb:size-9 rb:bg-cover rb:bg-[url('@/assets/images/file/audio.svg')]"></div>,
|
icon: <div className="rb:size-9 rb:bg-cover rb:bg-[url('@/assets/images/file/audio.svg')]"></div>,
|
||||||
formats: 'MP3, M4A, WAV, OGG, FLAC',
|
formats: [
|
||||||
|
"mp3",
|
||||||
|
"wav",
|
||||||
|
"m4a",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'video',
|
type: 'video',
|
||||||
icon: <div className="rb:size-9 rb:bg-cover rb:bg-[url('@/assets/images/file/video.svg')]"></div>,
|
icon: <div className="rb:size-9 rb:bg-cover rb:bg-[url('@/assets/images/file/video.svg')]"></div>,
|
||||||
formats: 'MP4, MOV, AVI, WEBM',
|
formats: [
|
||||||
|
"mp4",
|
||||||
|
"mov",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -50,16 +71,38 @@ const defaultValues: FileUpload = {
|
|||||||
enabled: false,
|
enabled: false,
|
||||||
image_enabled: false,
|
image_enabled: false,
|
||||||
image_max_size_mb: 20,
|
image_max_size_mb: 20,
|
||||||
image_allowed_extensions: ['png', 'jpg', 'jpeg', 'gif', 'webp'],
|
image_allowed_extensions: [
|
||||||
|
"png",
|
||||||
|
"jpg",
|
||||||
|
"jpeg"
|
||||||
|
],
|
||||||
audio_enabled: false,
|
audio_enabled: false,
|
||||||
audio_max_size_mb: 50,
|
audio_max_size_mb: 50,
|
||||||
audio_allowed_extensions: ['mp3', 'wav', 'm4a', 'ogg', 'flac'],
|
audio_allowed_extensions: [
|
||||||
|
"mp3",
|
||||||
|
"wav",
|
||||||
|
"m4a",
|
||||||
|
"ogg",
|
||||||
|
"flac"
|
||||||
|
],
|
||||||
document_enabled: false,
|
document_enabled: false,
|
||||||
document_max_size_mb: 100,
|
document_max_size_mb: 100,
|
||||||
document_allowed_extensions: ['pdf', 'docx', 'xlsx', 'txt', 'csv', 'json'],
|
document_allowed_extensions: [
|
||||||
|
"pdf",
|
||||||
|
"docx",
|
||||||
|
"xlsx",
|
||||||
|
"txt",
|
||||||
|
"csv",
|
||||||
|
"json"
|
||||||
|
],
|
||||||
video_enabled: false,
|
video_enabled: false,
|
||||||
video_max_size_mb: 500,
|
video_max_size_mb: 100,
|
||||||
video_allowed_extensions: ['mp4', 'mov', 'avi', 'webm'],
|
video_allowed_extensions: [
|
||||||
|
"mp4",
|
||||||
|
"mov",
|
||||||
|
"avi",
|
||||||
|
"webm"
|
||||||
|
],
|
||||||
max_file_count: 5,
|
max_file_count: 5,
|
||||||
allowed_transfer_methods: 'both'
|
allowed_transfer_methods: 'both'
|
||||||
}
|
}
|
||||||
@@ -127,7 +170,7 @@ const FileUploadSettingModal = forwardRef<FileUploadSettingModalRef, FileUploadS
|
|||||||
|
|
||||||
<div className="rb:text-[12px] rb:text-[#5B6167] rb:mb-1">{t('application.maxCount')}</div>
|
<div className="rb:text-[12px] rb:text-[#5B6167] rb:mb-1">{t('application.maxCount')}</div>
|
||||||
<Form.Item label={t('application.maxCount')} name="max_file_count">
|
<Form.Item label={t('application.maxCount')} name="max_file_count">
|
||||||
<InputNumber min={1} max={100} precision={0} className="rb:w-full!" placeholder={t('common.pleaseEnter')} />
|
<InputNumber min={1} max={20} precision={0} className="rb:w-full!" placeholder={t('common.pleaseEnter')} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item label={t('application.supportedTypes')}>
|
<Form.Item label={t('application.supportedTypes')}>
|
||||||
@@ -149,7 +192,7 @@ const FileUploadSettingModal = forwardRef<FileUploadSettingModalRef, FileUploadS
|
|||||||
<Flex align="center" justify="space-between">
|
<Flex align="center" justify="space-between">
|
||||||
<Flex vertical>
|
<Flex vertical>
|
||||||
<div className="rb:font-medium">{t(`application.${option.type}`)}</div>
|
<div className="rb:font-medium">{t(`application.${option.type}`)}</div>
|
||||||
<div className="rb:text-[12px] rb:text-[#5B6167]">{option.formats}</div>
|
<div className="rb:text-[12px] rb:text-[#5B6167]">{option.formats.map(item => item.toUpperCase()).join(', ')}</div>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Form.Item name={enabledKey} valuePropName="checked" noStyle>
|
<Form.Item name={enabledKey} valuePropName="checked" noStyle>
|
||||||
<Switch />
|
<Switch />
|
||||||
@@ -161,7 +204,7 @@ const FileUploadSettingModal = forwardRef<FileUploadSettingModalRef, FileUploadS
|
|||||||
<Flex align="center" gap={12} className="rb:mt-3! rb:pt-3! rb:border-t rb:border-[#DFE4ED]">
|
<Flex align="center" gap={12} className="rb:mt-3! rb:pt-3! rb:border-t rb:border-[#DFE4ED]">
|
||||||
<div>{t('application.singleMaxSize')}: </div>
|
<div>{t('application.singleMaxSize')}: </div>
|
||||||
<Form.Item name={sizeKey} noStyle>
|
<Form.Item name={sizeKey} noStyle>
|
||||||
<InputNumber min={1} max={500} suffix="MB" className="rb:flex-1" />
|
<InputNumber min={1} max={100} suffix="MB" className="rb:flex-1" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name={`${option.type}_allowed_extensions`} hidden />
|
<Form.Item name={`${option.type}_allowed_extensions`} hidden />
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: ZhaoYing
|
* @Author: ZhaoYing
|
||||||
* @Date: 2026-02-03 16:58:03
|
* @Date: 2026-02-03 16:58:03
|
||||||
* @Last Modified by: ZhaoYing
|
* @Last Modified by: ZhaoYing
|
||||||
* @Last Modified time: 2026-03-18 20:54:00
|
* @Last Modified time: 2026-03-19 12:30:41
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Conversation Page
|
* Conversation Page
|
||||||
@@ -63,6 +63,7 @@ const Conversation: FC = () => {
|
|||||||
const [isHasMemory, setIsHasMemory] = useState(false)
|
const [isHasMemory, setIsHasMemory] = useState(false)
|
||||||
const [memory, setMemory] = useState(true)
|
const [memory, setMemory] = useState(true)
|
||||||
const [features, setFeatures] = useState<FeaturesConfigForm>({} as FeaturesConfigForm)
|
const [features, setFeatures] = useState<FeaturesConfigForm>({} as FeaturesConfigForm)
|
||||||
|
const [config, setConfig] = useState<Record<string, any>>({})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const shareToken = localStorage.getItem(`shareToken_${token}`)
|
const shareToken = localStorage.getItem(`shareToken_${token}`)
|
||||||
@@ -88,6 +89,7 @@ const Conversation: FC = () => {
|
|||||||
.then(res => {
|
.then(res => {
|
||||||
const response = res as { variables: Variable[]; features: FeaturesConfigForm; app_type: string; memory?: boolean; }
|
const response = res as { variables: Variable[]; features: FeaturesConfigForm; app_type: string; memory?: boolean; }
|
||||||
toolbarRef.current?.setVariables(response.variables || [])
|
toolbarRef.current?.setVariables(response.variables || [])
|
||||||
|
setConfig(response)
|
||||||
setFeatures(response.features)
|
setFeatures(response.features)
|
||||||
setIsHasMemory((response.app_type === 'workflow' && response.memory) || (response.app_type !== 'workflow'))
|
setIsHasMemory((response.app_type === 'workflow' && response.memory) || (response.app_type !== 'workflow'))
|
||||||
})
|
})
|
||||||
@@ -284,6 +286,7 @@ const Conversation: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleChangeMemory = (value: boolean) => {
|
const handleChangeMemory = (value: boolean) => {
|
||||||
|
if (config.app_type === 'workflow') return;
|
||||||
modal.confirm({
|
modal.confirm({
|
||||||
title: value ? t('memoryConversation.memoryTipTitle') : t('memoryConversation.memoryCancelTipTitle'),
|
title: value ? t('memoryConversation.memoryTipTitle') : t('memoryConversation.memoryCancelTipTitle'),
|
||||||
okText: t('common.confirm'),
|
okText: t('common.confirm'),
|
||||||
@@ -388,6 +391,7 @@ const Conversation: FC = () => {
|
|||||||
icon={MemoryFunctionIcon}
|
icon={MemoryFunctionIcon}
|
||||||
checkedIcon={MemoryFunctionCheckedIcon}
|
checkedIcon={MemoryFunctionCheckedIcon}
|
||||||
checked={memory}
|
checked={memory}
|
||||||
|
disabled={config.app_type === 'workflow'}
|
||||||
onChange={handleChangeMemory}
|
onChange={handleChangeMemory}
|
||||||
>
|
>
|
||||||
{t('memoryConversation.memory')}
|
{t('memoryConversation.memory')}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import React, { useState, type FC, useEffect } from 'react'
|
import React, { useState, type FC, useEffect } from 'react'
|
||||||
import { useParams } from 'react-router-dom'
|
import { useParams } from 'react-router-dom'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { Spin, Flex } from 'antd';
|
||||||
|
|
||||||
import type { CommunityD3Node, CommunityGraphData, RawCommunityGraphData, RawCommunityNode } from '@/components/D3Graph/types'
|
import type { CommunityD3Node, CommunityGraphData, RawCommunityGraphData, RawCommunityNode } from '@/components/D3Graph/types'
|
||||||
import { buildCommunityGraphData } from '@/components/D3Graph/utils'
|
import { buildCommunityGraphData } from '@/components/D3Graph/utils'
|
||||||
import CommunityGraph from '@/components/D3Graph/CommunityGraph'
|
import CommunityGraph from '@/components/D3Graph/CommunityGraph'
|
||||||
@@ -40,14 +42,17 @@ const NodeTooltip: FC<{ node: CommunityD3Node }> = ({ node }) => {
|
|||||||
|
|
||||||
const CommunityNetwork: FC<{ onSelectCommunity?: (node: RawCommunityNode) => void }> = ({ onSelectCommunity }) => {
|
const CommunityNetwork: FC<{ onSelectCommunity?: (node: RawCommunityNode) => void }> = ({ onSelectCommunity }) => {
|
||||||
const { id } = useParams()
|
const { id } = useParams()
|
||||||
|
const { t } = useTranslation()
|
||||||
const [graphData, setGraphData] = useState<CommunityGraphData | null>(null)
|
const [graphData, setGraphData] = useState<CommunityGraphData | null>(null)
|
||||||
const [empty, setEmpty] = useState(false)
|
const [empty, setEmpty] = useState(false)
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!id) return
|
if (!id) return
|
||||||
const controller = new AbortController()
|
const controller = new AbortController()
|
||||||
setEmpty(false)
|
setEmpty(false)
|
||||||
setGraphData(null)
|
setGraphData(null)
|
||||||
|
setLoading(true)
|
||||||
getMemoryCommunityGraph(id, { signal: controller.signal }).then(res => {
|
getMemoryCommunityGraph(id, { signal: controller.signal }).then(res => {
|
||||||
const raw = res as RawCommunityGraphData
|
const raw = res as RawCommunityGraphData
|
||||||
if (!raw.nodes?.length) { setEmpty(true); return }
|
if (!raw.nodes?.length) { setEmpty(true); return }
|
||||||
@@ -55,9 +60,18 @@ const CommunityNetwork: FC<{ onSelectCommunity?: (node: RawCommunityNode) => voi
|
|||||||
if (!built) { setEmpty(true); return }
|
if (!built) { setEmpty(true); return }
|
||||||
setGraphData(built)
|
setGraphData(built)
|
||||||
}).catch((e) => { if (e?.code !== 'ERR_CANCELED') setEmpty(true) })
|
}).catch((e) => { if (e?.code !== 'ERR_CANCELED') setEmpty(true) })
|
||||||
|
.finally(() => setLoading(false))
|
||||||
return () => controller.abort()
|
return () => controller.abort()
|
||||||
}, [id])
|
}, [id])
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return <Flex align="center" justify="center" className="rb:w-full rb:h-full">
|
||||||
|
<Spin tip={t('userMemory.communityLoadingTip')} size="large">
|
||||||
|
<div className="rb:w-64 rb:h-64" />
|
||||||
|
</Spin>
|
||||||
|
</Flex>
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommunityGraph
|
<CommunityGraph
|
||||||
data={graphData}
|
data={graphData}
|
||||||
|
|||||||
Reference in New Issue
Block a user