feat(knowledge): enhance knowledge base management with improved interfaces and components

refactor(interfaces): add comprehensive documentation and type definitions
feat(components): implement empty state handling and team filtering in KnowledgeGridView
refactor(hooks): optimize knowledge list fetching with better parameter handling
style(interfaces): improve code readability with detailed comments
This commit is contained in:
2025-10-11 18:30:41 +08:00
parent 836ee763e3
commit d475a0e982
9 changed files with 463 additions and 82 deletions

View File

@@ -16,6 +16,7 @@ import {
MoreVert as MoreVertIcon, MoreVert as MoreVertIcon,
Folder as FolderIcon, Folder as FolderIcon,
ArrowForward as ArrowForwardIcon, ArrowForward as ArrowForwardIcon,
Add as AddIcon,
} from '@mui/icons-material'; } from '@mui/icons-material';
import type { IKnowledge } from '@/interfaces/database/knowledge'; import type { IKnowledge } from '@/interfaces/database/knowledge';
@@ -28,6 +29,10 @@ interface KnowledgeGridViewProps {
onDelete?: (kb: IKnowledge) => void; onDelete?: (kb: IKnowledge) => void;
onView?: (kb: IKnowledge) => void; onView?: (kb: IKnowledge) => void;
loading?: boolean; loading?: boolean;
// 新增属性用于控制空状态显示
searchTerm?: string;
teamFilter?: string;
onCreateKnowledge?: () => void;
} }
interface KnowledgeCardProps { interface KnowledgeCardProps {
@@ -209,6 +214,9 @@ const KnowledgeGridView: React.FC<KnowledgeGridViewProps> = ({
onDelete, onDelete,
onView, onView,
loading = false, loading = false,
searchTerm = '',
teamFilter = 'all',
onCreateKnowledge,
}) => { }) => {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const [selectedKB, setSelectedKB] = React.useState<IKnowledge | null>(null); const [selectedKB, setSelectedKB] = React.useState<IKnowledge | null>(null);
@@ -257,14 +265,26 @@ const KnowledgeGridView: React.FC<KnowledgeGridViewProps> = ({
if (knowledgeBases.length === 0) { if (knowledgeBases.length === 0) {
return ( return (
<Box sx={{ textAlign: 'center', py: 4 }}> <Box sx={{ textAlign: 'center', py: 8 }}>
<FolderIcon sx={{ fontSize: 64, color: 'text.secondary', mb: 2 }} /> <FolderIcon sx={{ fontSize: 64, color: 'text.secondary', mb: 2 }} />
<Typography variant="h6" color="text.secondary"> <Typography variant="h6" color="text.secondary" gutterBottom>
{searchTerm || teamFilter !== 'all' ? '没有找到匹配的知识库' : '暂无知识库'}
</Typography> </Typography>
<Typography variant="body2" color="text.secondary"> <Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
使 {searchTerm || teamFilter !== 'all'
? '尝试调整搜索条件或筛选器'
: '创建您的第一个知识库开始使用'
}
</Typography> </Typography>
{(!searchTerm && teamFilter === 'all' && onCreateKnowledge) && (
<Button
variant="contained"
startIcon={<AddIcon />}
onClick={onCreateKnowledge}
>
</Button>
)}
</Box> </Box>
); );
} }

View File

@@ -1,19 +1,7 @@
import { useState, useEffect, useCallback } from 'react'; import { useState, useEffect, useCallback } from 'react';
import knowledgeService from '@/services/knowledge_service'; import knowledgeService from '@/services/knowledge_service';
import type { IKnowledge } from '@/interfaces/database/knowledge'; import type { IKnowledge, IKnowledgeResult } from '@/interfaces/database/knowledge';
import type { IFetchKnowledgeListRequestParams } from '@/interfaces/request/knowledge';
// 知识库列表查询参数接口
export interface KnowledgeListParams {
keywords?: string;
page?: number;
page_size?: number;
}
// 知识库列表响应接口
export interface KnowledgeListResponse {
kbs: IKnowledge[];
total: number;
}
// 知识库列表Hook状态接口 // 知识库列表Hook状态接口
export interface UseKnowledgeListState { export interface UseKnowledgeListState {
@@ -28,7 +16,7 @@ export interface UseKnowledgeListState {
// 知识库列表Hook返回值接口 // 知识库列表Hook返回值接口
export interface UseKnowledgeListReturn extends UseKnowledgeListState { export interface UseKnowledgeListReturn extends UseKnowledgeListState {
fetchKnowledgeBases: (params?: KnowledgeListParams) => Promise<void>; fetchKnowledgeBases: (params?: IFetchKnowledgeListRequestParams) => Promise<void>;
setKeywords: (keywords: string) => void; setKeywords: (keywords: string) => void;
setCurrentPage: (page: number) => void; setCurrentPage: (page: number) => void;
setPageSize: (size: number) => void; setPageSize: (size: number) => void;
@@ -40,7 +28,7 @@ export interface UseKnowledgeListReturn extends UseKnowledgeListState {
* 支持关键词搜索、分页等功能 * 支持关键词搜索、分页等功能
*/ */
export const useKnowledgeList = ( export const useKnowledgeList = (
initialParams?: KnowledgeListParams initialParams?: IFetchKnowledgeListRequestParams
): UseKnowledgeListReturn => { ): UseKnowledgeListReturn => {
const [knowledgeBases, setKnowledgeBases] = useState<IKnowledge[]>([]); const [knowledgeBases, setKnowledgeBases] = useState<IKnowledge[]>([]);
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
@@ -53,7 +41,7 @@ export const useKnowledgeList = (
/** /**
* 获取知识库列表 * 获取知识库列表
*/ */
const fetchKnowledgeBases = useCallback(async (params?: KnowledgeListParams) => { const fetchKnowledgeBases = useCallback(async (params?: IFetchKnowledgeListRequestParams) => {
try { try {
setLoading(true); setLoading(true);
setError(null); setError(null);
@@ -67,8 +55,8 @@ export const useKnowledgeList = (
// 构建请求体 // 构建请求体
const requestBody: any = {}; const requestBody: any = {};
if (queryParams.keywords) { if (queryParams.keywords && queryParams.keywords.trim()) {
requestBody.keywords = queryParams.keywords; requestBody.keywords = queryParams.keywords.trim();
} }
// 构建查询参数 // 构建查询参数
@@ -79,6 +67,9 @@ export const useKnowledgeList = (
if (queryParams.page_size) { if (queryParams.page_size) {
requestParams.page_size = queryParams.page_size; requestParams.page_size = queryParams.page_size;
} }
if (queryParams.keywords) {
requestParams.keywords = queryParams.keywords;
}
const response = await knowledgeService.getKnowledgeList( const response = await knowledgeService.getKnowledgeList(
Object.keys(requestParams).length > 0 ? requestParams : undefined, Object.keys(requestParams).length > 0 ? requestParams : undefined,
@@ -87,7 +78,7 @@ export const useKnowledgeList = (
// 检查响应状态 // 检查响应状态
if (response.data.code === 0) { if (response.data.code === 0) {
const data = response.data.data as KnowledgeListResponse; const data = response.data.data as IKnowledgeResult;
setKnowledgeBases(data.kbs || []); setKnowledgeBases(data.kbs || []);
setTotal(data.total || 0); setTotal(data.total || 0);
} else { } else {
@@ -132,10 +123,10 @@ export const useKnowledgeList = (
setCurrentPage(1); setCurrentPage(1);
}, []); }, []);
// 初始化时获取数据 // 当关键词、页码或页面大小变化时重新获取数据
useEffect(() => { useEffect(() => {
fetchKnowledgeBases(); fetchKnowledgeBases();
}, [fetchKnowledgeBases]); }, [keywords, currentPage, pageSize]);
return { return {
knowledgeBases, knowledgeBases,

View File

@@ -1,17 +1,41 @@
/**
* 通用响应类型接口
* 定义API响应的标准格式
* @template T 响应数据的类型默认为any
*/
export interface ResponseType<T = any> { export interface ResponseType<T = any> {
/** 响应状态码 */
code: number; code: number;
/** 响应数据 */
data: T; data: T;
/** 响应消息 */
message: string; message: string;
/** HTTP状态码 */
status: number; status: number;
} }
/**
* GET请求响应类型接口
* 用于GET请求的响应数据结构
* @template T 响应数据的类型默认为any
*/
export interface ResponseGetType<T = any> { export interface ResponseGetType<T = any> {
/** 响应数据 */
data: T; data: T;
/** 加载状态,可选字段 */
loading?: boolean; loading?: boolean;
} }
/**
* POST请求响应类型接口
* 用于POST请求的响应数据结构支持扩展字段
* @template T 响应数据的类型默认为any
*/
export interface ResponsePostType<T = any> { export interface ResponsePostType<T = any> {
/** 响应数据 */
data: T; data: T;
/** 加载状态,可选字段 */
loading?: boolean; loading?: boolean;
/** 其他扩展字段,键为字符串,值为未知类型 */
[key: string]: unknown; [key: string]: unknown;
} }

View File

@@ -1,168 +1,355 @@
import type { RunningStatus } from '@/constants/knowledge'; import type { RunningStatus } from '@/constants/knowledge';
// knowledge base /**
* 知识库接口定义
* 包含知识库的基本信息、配置和状态
*/
export interface IKnowledge { export interface IKnowledge {
/** 知识库头像,可选字段 */
avatar?: any; avatar?: any;
/** 知识库中的文档块数量 */
chunk_num: number; chunk_num: number;
/** 创建日期(字符串格式) */
create_date: string; create_date: string;
/** 创建时间戳 */
create_time: number; create_time: number;
/** 创建者ID */
created_by: string; created_by: string;
/** 知识库描述 */
description: string; description: string;
/** 知识库中的文档数量 */
doc_num: number; doc_num: number;
/** 知识库语言 */
language: string; language: string;
/** 知识库唯一标识符 */
id: string; id: string;
/** 知识库名称 */
name: string; name: string;
/** 解析器配置 */
parser_config: ParserConfig; parser_config: ParserConfig;
/** 解析器ID */
parser_id: string; parser_id: string;
/** 管道ID */
pipeline_id: string; pipeline_id: string;
/** 管道名称 */
pipeline_name: string; pipeline_name: string;
/** 管道头像 */
pipeline_avatar: string; pipeline_avatar: string;
/** 权限设置 */
permission: string; permission: string;
/** 相似度阈值 */
similarity_threshold: number; similarity_threshold: number;
/** 知识库状态 */
status: string; status: string;
/** 租户ID */
tenant_id: string; tenant_id: string;
/** 令牌数量 */
token_num: number; token_num: number;
/** 更新日期(字符串格式) */
update_date: string; update_date: string;
/** 更新时间戳 */
update_time: number; update_time: number;
/** 向量相似度权重 */
vector_similarity_weight: number; vector_similarity_weight: number;
/** 嵌入模型ID */
embd_id: string; embd_id: string;
/** 昵称 */
nickname: string; nickname: string;
/** 操作权限级别 */
operator_permission: number; operator_permission: number;
/** 知识库大小(字节) */
size: number; size: number;
/** Raptor任务完成时间可选 */
raptor_task_finish_at?: string; raptor_task_finish_at?: string;
/** Raptor任务ID可选 */
raptor_task_id?: string; raptor_task_id?: string;
/** 思维导图任务完成时间,可选 */
mindmap_task_finish_at?: string; mindmap_task_finish_at?: string;
/** 思维导图任务ID可选 */
mindmap_task_id?: string; mindmap_task_id?: string;
} }
/**
* 知识库查询结果接口
* 包含知识库列表和总数
*/
export interface IKnowledgeResult { export interface IKnowledgeResult {
/** 知识库列表 */
kbs: IKnowledge[]; kbs: IKnowledge[];
/** 知识库总数 */
total: number; total: number;
} }
/**
* Raptor配置接口
* 用于配置是否启用Raptor功能
*/
export interface Raptor { export interface Raptor {
/** 是否使用Raptor */
use_raptor: boolean; use_raptor: boolean;
} }
/**
* 解析器配置接口
* 定义文档解析的各种参数和选项
*/
export interface ParserConfig { export interface ParserConfig {
/** 起始页码,可选 */
from_page?: number; from_page?: number;
/** 结束页码,可选 */
to_page?: number; to_page?: number;
/** 自动关键词数量,可选 */
auto_keywords?: number; auto_keywords?: number;
/** 自动问题数量,可选 */
auto_questions?: number; auto_questions?: number;
/** 每个文档块的令牌数量,可选 */
chunk_token_num?: number; chunk_token_num?: number;
/** 分隔符,可选 */
delimiter?: string; delimiter?: string;
/** 是否将HTML转换为Excel格式可选 */
html4excel?: boolean; html4excel?: boolean;
/** 是否启用布局识别,可选 */
layout_recognize?: boolean; layout_recognize?: boolean;
/** Raptor配置可选 */
raptor?: Raptor; raptor?: Raptor;
/** 标签知识库ID列表可选 */
tag_kb_ids?: string[]; tag_kb_ids?: string[];
/** 顶部标签数量,可选 */
topn_tags?: number; topn_tags?: number;
/** GraphRAG配置可选 */
graphrag?: { use_graphrag?: boolean }; graphrag?: { use_graphrag?: boolean };
} }
/**
* 知识库文件解析器配置接口
* 定义文件解析的具体参数
*/
export interface IKnowledgeFileParserConfig { export interface IKnowledgeFileParserConfig {
/** 每个文档块的令牌数量 */
chunk_token_num: number; chunk_token_num: number;
/** 是否启用布局识别 */
layout_recognize: boolean; layout_recognize: boolean;
/** 页面范围数组 */
pages: number[][]; pages: number[][];
/** 任务页面大小 */
task_page_size: number; task_page_size: number;
} }
/**
* 知识库文件接口
* 定义知识库中单个文件的信息和状态
*/
export interface IKnowledgeFile { export interface IKnowledgeFile {
/** 文件中的文档块数量 */
chunk_num: number; chunk_num: number;
/** 创建日期(字符串格式) */
create_date: string; create_date: string;
/** 创建时间戳 */
create_time: number; create_time: number;
/** 创建者ID */
created_by: string; created_by: string;
/** 文件唯一标识符 */
id: string; id: string;
/** 所属知识库ID */
kb_id: string; kb_id: string;
/** 文件存储位置 */
location: string; location: string;
/** 文件名称 */
name: string; name: string;
/** 解析器ID */
parser_id: string; parser_id: string;
/** 处理开始时间,可选 */
process_begin_at?: any; process_begin_at?: any;
/** 处理持续时间 */
process_duration: number; process_duration: number;
progress: number; // parsing process /** 解析进度百分比 */
progress_msg: string; // parsing log progress: number;
run: RunningStatus; // parsing status /** 解析进度消息 */
progress_msg: string;
/** 解析运行状态 */
run: RunningStatus;
/** 文件大小(字节) */
size: number; size: number;
/** 文件来源类型 */
source_type: string; source_type: string;
status: string; // enabled /** 文件状态(启用/禁用) */
thumbnail?: any; // base64 status: string;
/** 文件缩略图base64编码可选 */
thumbnail?: any;
/** 文件中的令牌数量 */
token_num: number; token_num: number;
/** 文件类型 */
type: string; type: string;
/** 更新日期(字符串格式) */
update_date: string; update_date: string;
/** 更新时间戳 */
update_time: number; update_time: number;
/** 解析器配置 */
parser_config: IKnowledgeFileParserConfig; parser_config: IKnowledgeFileParserConfig;
} }
/**
* 租户信息接口
* 定义租户的各种服务配置
*/
export interface ITenantInfo { export interface ITenantInfo {
/** 自动语音识别服务ID */
asr_id: string; asr_id: string;
/** 嵌入模型服务ID */
embd_id: string; embd_id: string;
/** 图像转文本服务ID */
img2txt_id: string; img2txt_id: string;
/** 大语言模型服务ID */
llm_id: string; llm_id: string;
/** 租户名称 */
name: string; name: string;
/** 解析器ID列表 */
parser_ids: string; parser_ids: string;
/** 租户角色 */
role: string; role: string;
/** 租户ID */
tenant_id: string; tenant_id: string;
/** 聊天服务ID */
chat_id: string; chat_id: string;
/** 语音转文本服务ID */
speech2text_id: string; speech2text_id: string;
/** 文本转语音服务ID */
tts_id: string; tts_id: string;
} }
/**
* 文档块接口
* 定义知识库中单个文档块的信息
*/
export interface IChunk { export interface IChunk {
available_int: number; // Whether to enable, 0: not enabled, 1: enabled /** 是否启用0未启用1启用 */
available_int: number;
/** 文档块唯一标识符 */
chunk_id: string; chunk_id: string;
/** 带权重的内容 */
content_with_weight: string; content_with_weight: string;
/** 所属文档ID */
doc_id: string; doc_id: string;
/** 所属文档名称 */
doc_name: string; doc_name: string;
/** 关联图像ID */
image_id: string; image_id: string;
/** 重要关键词列表,可选 */
important_kwd?: string[]; important_kwd?: string[];
question_kwd?: string[]; // keywords /** 问题关键词列表,可选 */
question_kwd?: string[];
/** 标签关键词列表,可选 */
tag_kwd?: string[]; tag_kwd?: string[];
/** 位置信息数组 */
positions: number[][]; positions: number[][];
/** 标签特征映射,可选 */
tag_feas?: Record<string, number>; tag_feas?: Record<string, number>;
} }
/**
* 测试文档块接口
* 用于知识库测试和检索的文档块信息
*/
export interface ITestingChunk { export interface ITestingChunk {
/** 文档块唯一标识符 */
chunk_id: string; chunk_id: string;
/** 内容的LTKS表示 */
content_ltks: string; content_ltks: string;
/** 带权重的内容 */
content_with_weight: string; content_with_weight: string;
/** 所属文档ID */
doc_id: string; doc_id: string;
/** 所属文档名称 */
doc_name: string; doc_name: string;
/** 图像ID旧字段 */
img_id: string; img_id: string;
/** 图像ID */
image_id: string; image_id: string;
/** 重要关键词列表 */
important_kwd: any[]; important_kwd: any[];
/** 所属知识库ID */
kb_id: string; kb_id: string;
/** 相似度分数 */
similarity: number; similarity: number;
/** 词汇相似度分数 */
term_similarity: number; term_similarity: number;
/** 向量表示 */
vector: number[]; vector: number[];
/** 向量相似度分数 */
vector_similarity: number; vector_similarity: number;
/** 高亮显示的内容 */
highlight: string; highlight: string;
/** 位置信息数组 */
positions: number[][]; positions: number[][];
/** 文档名称关键词 */
docnm_kwd: string; docnm_kwd: string;
/** 文档类型关键词 */
doc_type_kwd: string; doc_type_kwd: string;
} }
/**
* 测试文档接口
* 用于知识库测试的文档统计信息
*/
export interface ITestingDocument { export interface ITestingDocument {
/** 文档中的块数量 */
count: number; count: number;
/** 文档ID */
doc_id: string; doc_id: string;
/** 文档名称 */
doc_name: string; doc_name: string;
} }
/**
* 测试结果接口
* 知识库测试的完整结果
*/
export interface ITestingResult { export interface ITestingResult {
/** 匹配的文档块列表 */
chunks: ITestingChunk[]; chunks: ITestingChunk[];
/** 匹配的文档列表 */
documents: ITestingDocument[]; documents: ITestingDocument[];
/** 总匹配数量 */
total: number; total: number;
/** 标签统计,可选 */
labels?: Record<string, number>; labels?: Record<string, number>;
} }
/**
* 下一代测试结果接口
* 改进版本的知识库测试结果
*/
export interface INextTestingResult { export interface INextTestingResult {
/** 匹配的文档块列表 */
chunks: ITestingChunk[]; chunks: ITestingChunk[];
/** 文档聚合统计 */
doc_aggs: ITestingDocument[]; doc_aggs: ITestingDocument[];
/** 总匹配数量 */
total: number; total: number;
/** 标签统计,可选 */
labels?: Record<string, number>; labels?: Record<string, number>;
/** 是否已运行,可选 */
isRuned?: boolean; isRuned?: boolean;
} }
export type IRenameTag = { fromTag: string; toTag: string }; /**
* 重命名标签类型
* 用于标签重命名操作
*/
export type IRenameTag = {
/** 原标签名 */
fromTag: string;
/** 新标签名 */
toTag: string;
};
/**
* 知识图谱接口
* 定义知识库的图谱结构
*/
export interface IKnowledgeGraph { export interface IKnowledgeGraph {
/** 图谱数据结构 */
graph: Record<string, any>; graph: Record<string, any>;
/** 思维导图数据(已注释) */
// mind_map: TreeData; // mind_map: TreeData;
} }

View File

@@ -1,13 +1,31 @@
/**
* LLM工具集合类型
* 定义大语言模型可用工具的元数据数组
*/
export type ILLMTools = ILLMToolMetadata[]; export type ILLMTools = ILLMToolMetadata[];
/**
* LLM工具元数据接口
* 定义单个LLM工具的基本信息和参数
*/
export interface ILLMToolMetadata { export interface ILLMToolMetadata {
/** 工具名称(内部标识符) */
name: string; name: string;
/** 工具显示名称(用户界面显示) */
displayName: string; displayName: string;
/** 工具显示描述(用户界面显示的功能说明) */
displayDescription: string; displayDescription: string;
/** 工具参数映射,键为参数名,值为参数配置 */
parameters: Map<string, ILLMToolParameter>; parameters: Map<string, ILLMToolParameter>;
} }
/**
* LLM工具参数接口
* 定义工具参数的类型和描述信息
*/
export interface ILLMToolParameter { export interface ILLMToolParameter {
/** 参数类型string、number、boolean等 */
type: string; type: string;
/** 参数显示描述(用户界面显示的参数说明) */
displayDescription: string; displayDescription: string;
} }

View File

@@ -1,7 +1,17 @@
/**
* Langfuse配置接口
* 定义Langfuse服务的连接和认证配置
* Langfuse是一个用于LLM应用的可观测性平台
*/
export interface ILangfuseConfig { export interface ILangfuseConfig {
/** 密钥用于API认证 */
secret_key: string; secret_key: string;
/** 公钥,用于客户端认证 */
public_key: string; public_key: string;
/** 服务主机地址 */
host: string; host: string;
/** 项目ID */
project_id: string; project_id: string;
/** 项目名称 */
project_name: string; project_name: string;
} }

View File

@@ -1,96 +1,204 @@
/**
* 用户信息接口
* 定义用户的基本信息和配置
*/
export interface IUserInfo { export interface IUserInfo {
/** 访问令牌 */
access_token: string; access_token: string;
/** 用户头像,可选字段 */
avatar?: any; avatar?: any;
/** 颜色主题方案 */
color_schema: string; color_schema: string;
/** 创建日期(字符串格式) */
create_date: string; create_date: string;
/** 创建时间戳 */
create_time: number; create_time: number;
/** 用户邮箱 */
email: string; email: string;
/** 用户唯一标识符 */
id: string; id: string;
/** 是否激活状态 */
is_active: string; is_active: string;
/** 是否匿名用户 */
is_anonymous: string; is_anonymous: string;
/** 是否已认证 */
is_authenticated: string; is_authenticated: string;
/** 是否超级用户 */
is_superuser: boolean; is_superuser: boolean;
/** 用户语言设置 */
language: string; language: string;
/** 最后登录时间 */
last_login_time: string; last_login_time: string;
/** 登录渠道 */
login_channel: string; login_channel: string;
/** 用户昵称 */
nickname: string; nickname: string;
/** 用户密码 */
password: string; password: string;
/** 用户状态 */
status: string; status: string;
/** 时区设置 */
timezone: string; timezone: string;
/** 更新日期(字符串格式) */
update_date: string; update_date: string;
/** 更新时间戳 */
update_time: number; update_time: number;
} }
/**
* 任务执行器耗时统计类型
* 记录各个任务执行器的耗时数据
*/
export type TaskExecutorElapsed = Record<string, number[]>; export type TaskExecutorElapsed = Record<string, number[]>;
/**
* 任务执行器心跳项接口
* 定义任务执行器的运行状态信息
*/
export interface TaskExecutorHeartbeatItem { export interface TaskExecutorHeartbeatItem {
/** 启动时间 */
boot_at: string; boot_at: string;
/** 当前任务通常为null */
current: null; current: null;
/** 已完成任务数 */
done: number; done: number;
/** 失败任务数 */
failed: number; failed: number;
/** 延迟时间 */
lag: number; lag: number;
/** 执行器名称 */
name: string; name: string;
/** 当前时间 */
now: string; now: string;
/** 待处理任务数 */
pending: number; pending: number;
} }
/**
* 系统状态接口
* 定义系统各个组件的运行状态
*/
export interface ISystemStatus { export interface ISystemStatus {
/** Elasticsearch状态 */
es: Es; es: Es;
/** 存储系统状态 */
storage: Storage; storage: Storage;
/** 数据库状态 */
database: Database; database: Database;
/** Redis状态 */
redis: Redis; redis: Redis;
/** 任务执行器心跳信息 */
task_executor_heartbeat: Record<string, TaskExecutorHeartbeatItem[]>; task_executor_heartbeat: Record<string, TaskExecutorHeartbeatItem[]>;
} }
/**
* Redis状态接口
* 定义Redis服务的状态信息
*/
interface Redis { interface Redis {
/** 服务状态 */
status: string; status: string;
/** 响应耗时 */
elapsed: number; elapsed: number;
/** 错误信息 */
error: string; error: string;
/** 待处理任务数 */
pending: number; pending: number;
} }
/**
* 存储系统状态接口
* 定义存储服务的状态信息
*/
export interface Storage { export interface Storage {
/** 服务状态 */
status: string; status: string;
/** 响应耗时 */
elapsed: number; elapsed: number;
/** 错误信息 */
error: string; error: string;
} }
/**
* 数据库状态接口
* 定义数据库服务的状态信息
*/
export interface Database { export interface Database {
/** 服务状态 */
status: string; status: string;
/** 响应耗时 */
elapsed: number; elapsed: number;
/** 错误信息 */
error: string; error: string;
} }
/**
* Elasticsearch状态接口
* 定义Elasticsearch服务的状态信息
*/
interface Es { interface Es {
/** 服务状态 */
status: string; status: string;
/** 响应耗时 */
elapsed: number; elapsed: number;
/** 错误信息 */
error: string; error: string;
/** 节点数量 */
number_of_nodes: number; number_of_nodes: number;
/** 活跃分片数 */
active_shards: number; active_shards: number;
} }
/**
* 租户用户接口
* 定义租户下用户的信息
*/
export interface ITenantUser { export interface ITenantUser {
/** 用户ID */
id: string; id: string;
/** 用户头像 */
avatar: string; avatar: string;
/** 时间差(秒) */
delta_seconds: number; delta_seconds: number;
/** 用户邮箱 */
email: string; email: string;
/** 是否激活状态 */
is_active: string; is_active: string;
/** 是否匿名用户 */
is_anonymous: string; is_anonymous: string;
/** 是否已认证 */
is_authenticated: string; is_authenticated: string;
/** 是否超级用户 */
is_superuser: boolean; is_superuser: boolean;
/** 用户昵称 */
nickname: string; nickname: string;
/** 用户角色 */
role: string; role: string;
/** 用户状态 */
status: string; status: string;
/** 更新日期 */
update_date: string; update_date: string;
/** 关联的用户ID */
user_id: string; user_id: string;
} }
/**
* 租户接口
* 定义租户的基本信息
*/
export interface ITenant { export interface ITenant {
/** 租户头像 */
avatar: string; avatar: string;
/** 时间差(秒) */
delta_seconds: number; delta_seconds: number;
/** 租户邮箱 */
email: string; email: string;
/** 租户昵称 */
nickname: string; nickname: string;
/** 租户角色 */
role: string; role: string;
/** 租户ID */
tenant_id: string; tenant_id: string;
/** 更新日期 */
update_date: string; update_date: string;
} }

View File

@@ -1,4 +1,4 @@
import React, { useState, useCallback } from 'react'; import React, { useState, useCallback, useMemo } from 'react';
import { import {
Box, Box,
Typography, Typography,
@@ -20,6 +20,7 @@ import {
} from '@mui/icons-material'; } from '@mui/icons-material';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { useKnowledgeList } from '@/hooks/knowledge_hooks'; import { useKnowledgeList } from '@/hooks/knowledge_hooks';
import { useUserData } from '@/hooks/useUserData';
import KnowledgeGridView from '@/components/KnowledgeGridView'; import KnowledgeGridView from '@/components/KnowledgeGridView';
import type { IKnowledge } from '@/interfaces/database/knowledge'; import type { IKnowledge } from '@/interfaces/database/knowledge';
@@ -29,37 +30,43 @@ const KnowledgeBaseList: React.FC = () => {
// 搜索和筛选状态 // 搜索和筛选状态
const [searchTerm, setSearchTerm] = useState(''); const [searchTerm, setSearchTerm] = useState('');
const [teamFilter, setTeamFilter] = useState('all'); const [teamFilter, setTeamFilter] = useState('all');
const [currentPage, setCurrentPage] = useState(1);
const pageSize = 12; // 每页显示12个知识库 const pageSize = 12; // 每页显示12个知识库
// 获取用户数据(包含租户列表)
const { tenantList } = useUserData();
// 使用knowledge_hooks获取数据 // 使用knowledge_hooks获取数据
const { const {
knowledgeBases, knowledgeBases,
total,
loading, loading,
error, error,
currentPage,
setKeywords,
setCurrentPage,
refresh, refresh,
} = useKnowledgeList({ } = useKnowledgeList({
keywords: searchTerm, keywords: searchTerm,
page: currentPage, page: 1,
page_size: pageSize, page_size: pageSize,
}); });
// 处理搜索 // 处理搜索
const handleSearch = useCallback((value: string) => { const handleSearch = useCallback((value: string) => {
setSearchTerm(value); setSearchTerm(value);
setCurrentPage(1); // 搜索时重置到第一页 setKeywords(value);
}, []); }, [setKeywords]);
// 处理团队筛选 // 处理团队筛选
const handleTeamFilterChange = useCallback((value: string) => { const handleTeamFilterChange = useCallback((value: string) => {
setTeamFilter(value); setTeamFilter(value);
setCurrentPage(1); // 筛选时重置到第一页 setCurrentPage(1); // 筛选时重置到第一页
}, []); }, [setCurrentPage]);
// 处理分页变化 // 处理分页变化
const handlePageChange = useCallback((_: React.ChangeEvent<unknown>, page: number) => { const handlePageChange = useCallback((_: React.ChangeEvent<unknown>, page: number) => {
setCurrentPage(page); setCurrentPage(page);
}, []); }, [setCurrentPage]);
// 处理刷新 // 处理刷新
const handleRefresh = useCallback(() => { const handleRefresh = useCallback(() => {
@@ -88,22 +95,57 @@ const KnowledgeBaseList: React.FC = () => {
}, []); }, []);
// 根据团队筛选过滤知识库 // 根据团队筛选过滤知识库
const filteredKnowledgeBases = React.useMemo(() => { const filteredKnowledgeBases = useMemo(() => {
if (!knowledgeBases) return []; if (!knowledgeBases) return [];
if (teamFilter === 'all') { if (teamFilter === 'all') {
return knowledgeBases; return knowledgeBases;
} }
return knowledgeBases.filter(kb => { // 根据租户ID筛选
if (teamFilter === 'me') return kb.permission === 'me'; if (teamFilter !== 'all') {
if (teamFilter === 'team') return kb.permission === 'team'; return knowledgeBases.filter(kb => {
return true; // 如果选择的是特定租户ID则筛选该租户的知识库
}); if (teamFilter === 'me') {
}, [knowledgeBases, teamFilter]); // 假设'me'表示当前用户的知识库,这里可以根据实际业务逻辑调整
return kb.permission === 'me' || kb.tenant_id === tenantList?.[0].tenant_id;
}
// 如果是具体的租户ID
return kb.tenant_id === teamFilter;
});
}
return knowledgeBases;
}, [knowledgeBases, teamFilter, tenantList]);
// 计算总页数 // 计算总页数(基于筛选后的结果)
const totalPages = Math.ceil((knowledgeBases?.length || 0) / pageSize); const totalPages = Math.ceil(filteredKnowledgeBases.length / pageSize);
// 获取当前页的数据
const currentPageData = useMemo(() => {
const startIndex = (currentPage - 1) * pageSize;
const endIndex = startIndex + pageSize;
return filteredKnowledgeBases.slice(startIndex, endIndex);
}, [filteredKnowledgeBases, currentPage, pageSize]);
// 构建团队筛选选项
const teamFilterOptions = useMemo(() => {
const options = [
{ value: 'all', label: '全部' },
];
// 添加租户选项
if (tenantList && tenantList.length > 0) {
tenantList.forEach(tenant => {
options.push({
value: tenant.tenant_id,
label: tenant.nickname || tenant.tenant_id,
});
});
}
return options;
}, [tenantList]);
return ( return (
<Box sx={{ p: 3 }}> <Box sx={{ p: 3 }}>
@@ -145,9 +187,11 @@ const KnowledgeBaseList: React.FC = () => {
label="团队筛选" label="团队筛选"
onChange={(e) => handleTeamFilterChange(e.target.value)} onChange={(e) => handleTeamFilterChange(e.target.value)}
> >
<MenuItem value="all"></MenuItem> {teamFilterOptions.map(option => (
<MenuItem value="me"></MenuItem> <MenuItem key={option.value} value={option.value}>
<MenuItem value="team"></MenuItem> {option.label}
</MenuItem>
))}
</Select> </Select>
</FormControl> </FormControl>
@@ -181,11 +225,14 @@ const KnowledgeBaseList: React.FC = () => {
{!loading && ( {!loading && (
<> <>
<KnowledgeGridView <KnowledgeGridView
knowledgeBases={filteredKnowledgeBases} knowledgeBases={currentPageData}
onEdit={handleEditKnowledge} onEdit={handleEditKnowledge}
onDelete={handleDeleteKnowledge} onDelete={handleDeleteKnowledge}
onView={handleViewKnowledge} onView={handleViewKnowledge}
loading={loading} loading={loading}
searchTerm={searchTerm}
teamFilter={teamFilter}
onCreateKnowledge={handleCreateKnowledge}
/> />
{/* 分页组件 */} {/* 分页组件 */}
@@ -202,35 +249,11 @@ const KnowledgeBaseList: React.FC = () => {
showLastButton showLastButton
/> />
<Typography variant="body2" color="text.secondary" textAlign="center"> <Typography variant="body2" color="text.secondary" textAlign="center">
{knowledgeBases?.length || 0} {currentPage} {totalPages} {filteredKnowledgeBases.length} {currentPage} {totalPages}
</Typography> </Typography>
</Stack> </Stack>
</Box> </Box>
)} )}
{/* 空状态 */}
{!loading && filteredKnowledgeBases.length === 0 && !error && (
<Box sx={{ textAlign: 'center', py: 8 }}>
<Typography variant="h6" color="text.secondary" gutterBottom>
{searchTerm || teamFilter !== 'all' ? '没有找到匹配的知识库' : '暂无知识库'}
</Typography>
<Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
{searchTerm || teamFilter !== 'all'
? '尝试调整搜索条件或筛选器'
: '创建您的第一个知识库开始使用'
}
</Typography>
{(!searchTerm && teamFilter === 'all') && (
<Button
variant="contained"
startIcon={<AddIcon />}
onClick={handleCreateKnowledge}
>
</Button>
)}
</Box>
)}
</> </>
)} )}
</Box> </Box>

View File

@@ -23,7 +23,7 @@ const knowledgeService = {
params?: IFetchKnowledgeListRequestParams, params?: IFetchKnowledgeListRequestParams,
body?: IFetchKnowledgeListRequestBody body?: IFetchKnowledgeListRequestBody
) => { ) => {
return request.post(api.kb_list, { data: body || {}, params }); return request.post(api.kb_list, { data: body || {}}, { params });
}, },
// 创建知识库 // 创建知识库