feat(logging): add loglevel package and implement logger utility

refactor(document): update document list filtering and API request handling
This commit is contained in:
2025-10-20 14:57:43 +08:00
parent 266b10a23b
commit 85eb3ab3da
7 changed files with 140 additions and 70 deletions

View File

@@ -17,8 +17,8 @@ export interface UseDocumentListState {
// 文档列表Hook返回值接口
export interface UseDocumentListReturn extends UseDocumentListState {
fetchDocuments: (params?: IFetchKnowledgeListRequestParams) => Promise<void>;
fetchDocumentsFilter: () => Promise<IDocumentInfoFilter | undefined>;
fetchDocuments: (params?: IFetchKnowledgeListRequestParams, body?: IFetchDocumentListRequestBody) => Promise<void>;
fetchDocumentsFilter: () => Promise<{ filter?: IDocumentInfoFilter, total?: number } | undefined>;
setKeywords: (keywords: string) => void;
setCurrentPage: (page: number) => void;
setPageSize: (size: number) => void;
@@ -44,7 +44,9 @@ export const useDocumentList = (
/**
* 获取文档列表
*/
const fetchDocuments = useCallback(async (params?: IFetchKnowledgeListRequestParams) => {
const fetchDocuments = useCallback(async (
params?: IFetchKnowledgeListRequestParams,
body?: IFetchDocumentListRequestBody) => {
if (!kbId) return;
try {
@@ -61,6 +63,13 @@ export const useDocumentList = (
// 构建请求体
const requestBody: IFetchDocumentListRequestBody = {};
if (body?.suffix) {
requestBody.suffix = body.suffix;
}
if (body?.run_status) {
requestBody.run_status = body.run_status;
}
// 构建查询参数
const requestParams: IFetchKnowledgeListRequestParams = {
kb_id: kbId,
@@ -108,7 +117,7 @@ export const useDocumentList = (
kb_id: kbId,
});
if (response.data.code === 0) {
const data: IDocumentInfoFilter = response.data.data;
const data: { filter?: IDocumentInfoFilter, total?: number } = response.data.data;
return data;
} else {
throw new Error(response.data.message || '获取文档过滤器失败');
@@ -189,7 +198,7 @@ export const useDocumentOperations = () => {
const formData = new FormData();
formData.append('kb_id', kbId);
files.forEach((file) => {
formData.append('file', file);
});
@@ -221,7 +230,7 @@ export const useDocumentOperations = () => {
const formData = new FormData();
formData.append('kb_id', kbId);
files.forEach((file) => {
formData.append('file', file);
});

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef } from 'react';
import React, { useState, useEffect, useRef, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import {
Box,
@@ -54,6 +54,7 @@ import type { IDocumentInfoFilter } from '@/interfaces/database/document';
import { RUNNING_STATUS_KEYS, type RunningStatus } from '@/constants/knowledge';
import { LanguageAbbreviation } from '@/locales';
import dayjs from 'dayjs';
import logger from '@/utils/logger';
interface DocumentListComponentProps {
@@ -75,7 +76,11 @@ interface DocumentListComponentProps {
onPageSizeChange: (pageSize: number) => void;
// 筛选器相关props
documentFilter?: IDocumentInfoFilter;
onFetchFilter?: () => Promise<IDocumentInfoFilter | undefined>;
// filter 变化时触发
onSelectedFilterChange?: (filter: {
run_status: Array<string>,
suffix: Array<string>,
}) => void;
// 新增操作功能props
onRename: (fileId: string, newName: string) => void;
onChangeStatus: (fileIds: string[], status: string) => void;
@@ -183,7 +188,7 @@ const DocumentListComponent: React.FC<DocumentListComponentProps> = ({
onPageChange,
onPageSizeChange,
documentFilter,
onFetchFilter,
onSelectedFilterChange,
onRename,
onChangeStatus,
onCancelRun,
@@ -199,7 +204,6 @@ const DocumentListComponent: React.FC<DocumentListComponentProps> = ({
const [selectedFileId, setSelectedFileId] = useState<string>('');
const [selectedFile, setSelectedFile] = useState<IKnowledgeFile | undefined>(undefined);
const [filter, setFilter] = useState<IDocumentInfoFilter | undefined>(documentFilter);
const [selectedRunStatus, setSelectedRunStatus] = useState<string[]>([]);
const [selectedSuffix, setSelectedSuffix] = useState<string[]>([]);
const [renameDialogOpen, setRenameDialogOpen] = useState(false);
@@ -213,21 +217,16 @@ const DocumentListComponent: React.FC<DocumentListComponentProps> = ({
return currentLanguage === LanguageAbbreviation.Zh ? zhCN : enUS;
};
// 获取筛选器数据
useEffect(() => {
const fetchFilter = async () => {
try {
const filterData = await onFetchFilter?.();
setFilter(filterData);
} catch (error) {
console.error('Failed to fetch document filter:', error);
}
const handleFilterSubmit = useCallback(() => {
const filter = {
run_status: selectedRunStatus,
suffix: selectedSuffix,
};
if (!filter) {
fetchFilter();
if (onSelectedFilterChange) {
onSelectedFilterChange(filter);
}
}, [onFetchFilter, filter]);
}, [selectedRunStatus, selectedSuffix])
const handleMenuClick = (event: React.MouseEvent<HTMLElement>, file: IKnowledgeFile) => {
event.stopPropagation();
@@ -334,10 +333,10 @@ const DocumentListComponent: React.FC<DocumentListComponentProps> = ({
minWidth: 200,
cellClassName: 'grid-center-cell',
renderCell: (params) => (
<Box
<Box
sx={{
display: 'flex',
alignItems: 'center',
display: 'flex',
alignItems: 'center',
gap: 1,
cursor: 'pointer',
":hover": { color: 'primary.main', fontWeight: 'bold' }
@@ -470,7 +469,7 @@ const DocumentListComponent: React.FC<DocumentListComponentProps> = ({
return (
<Box>
{/* 筛选器 */}
{filter && (
{documentFilter && (
<Paper sx={{ p: 2, mb: 2 }}>
<Typography variant="h6" sx={{ mb: 2 }}></Typography>
<Stack direction="row" spacing={2} alignItems="center">
@@ -490,7 +489,7 @@ const DocumentListComponent: React.FC<DocumentListComponentProps> = ({
</Box>
)}
>
{Object.entries(filter.run_status).map(([status, count]) => (
{Object.entries(documentFilter.run_status).map(([status, count]) => (
<MenuItem key={status} value={status}>
{getRunStatusLabel(status)} ({count})
</MenuItem>
@@ -514,20 +513,33 @@ const DocumentListComponent: React.FC<DocumentListComponentProps> = ({
</Box>
)}
>
{Object.entries(filter.suffix).map(([suffix, count]) => (
{Object.entries(documentFilter.suffix).map(([suffix, count]) => (
<MenuItem key={suffix} value={suffix}>
{suffix.toUpperCase()} ({count})
</MenuItem>
))}
</Select>
</FormControl>
<Button variant="outlined" onClick={() => {
setSelectedRunStatus([]);
setSelectedSuffix([]);
{/* clear filter */}
<Button variant="outlined" onClick={async () => {
await new Promise(resolve => {
setSelectedRunStatus([]);
setSelectedSuffix([]);
setTimeout(resolve, 200);
});
handleFilterSubmit();
}}>
</Button>
{/* submit filter */}
<Button variant="contained" onClick={async () => {
await new Promise(resolve => {
setTimeout(resolve, 200);
});
handleFilterSubmit();
}}>
</Button>
</Stack>
</Paper>
)}

View File

@@ -33,11 +33,12 @@ import KnowledgeGraphView from './components/KnowledgeGraphView';
import { useDocumentList, useDocumentOperations } from '@/hooks/document-hooks';
import { RUNNING_STATUS_KEYS } from '@/constants/knowledge';
import { useKnowledgeDetail } from '@/hooks/knowledge-hooks';
import logger from '@/utils/logger';
function KnowledgeBaseDetail() {
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
// 状态管理
const [error, setError] = useState<string | null>(null);
const [searchKeyword, setSearchKeyword] = useState('');
@@ -47,17 +48,27 @@ function KnowledgeBaseDetail() {
});
const [uploadDialogOpen, setUploadDialogOpen] = useState(false);
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [processDetailsDialogOpen, setProcessDetailsDialogOpen] = useState(false);
const [selectedFileDetails, setSelectedFileDetails] = useState<IKnowledgeFile | null>(null);
// 标签页状态
const [currentTab, setCurrentTab] = useState(0);
// 轮询相关状态
const pollingIntervalRef = useRef<any>(null);
const [isPolling, setIsPolling] = useState(false);
// documents filter
const [documentsFilter, setDocumentsFilter] = useState<IDocumentInfoFilter | undefined>(undefined);
const {
knowledge: knowledgeBase,
refresh: fetchKnowledgeDetail,
loading, showKnowledgeGraph,
knowledgeGraph
} = useKnowledgeDetail(id || '');
// 使用新的document hooks
const {
documents: files,
@@ -70,6 +81,8 @@ function KnowledgeBaseDetail() {
setKeywords,
setCurrentPage,
setPageSize,
fetchDocuments,
fetchDocumentsFilter,
} = useDocumentList(id || '');
const {
@@ -79,17 +92,19 @@ function KnowledgeBaseDetail() {
renameDocument,
changeDocumentStatus,
cancelRunDocuments,
loading: operationLoading,
error: operationError,
} = useDocumentOperations();
const { knowledge: knowledgeBase, refresh: fetchKnowledgeDetail, loading, showKnowledgeGraph, knowledgeGraph } = useKnowledgeDetail(id || '');
console.log('showKnowledgeGraph:', showKnowledgeGraph, knowledgeGraph);
const refreshDetailData = async () => {
await fetchKnowledgeDetail();
await refreshFiles();
};
// 删除文件
const handleDeleteFiles = async () => {
try {
try {
await deleteDocuments(Array.from(rowSelectionModel.ids) as string[]);
setDeleteDialogOpen(false);
setRowSelectionModel({
@@ -176,7 +191,7 @@ function KnowledgeBaseDetail() {
if (pollingIntervalRef.current) {
clearInterval(pollingIntervalRef.current);
}
setIsPolling(true);
pollingIntervalRef.current = setInterval(() => {
refreshFiles();
@@ -215,7 +230,20 @@ function KnowledgeBaseDetail() {
// 初始化数据
useEffect(() => {
fetchKnowledgeDetail();
fetchDocumentsFilter().then(filterData => {
if (filterData?.filter) {
// setKeywords(filter.keywords || '');
logger.debug('filter:', filterData.filter);
const filter = filterData.filter || {};
const showFilter = Object.keys(filter.run_status || {}).length > 0 || Object.keys(filter.suffix || {}).length > 0;
if (showFilter) {
setDocumentsFilter({
run_status: filterData.filter?.run_status || {},
suffix: filterData.filter?.suffix || {},
});
}
}
});
}, [id]);
// 搜索文件
@@ -230,7 +258,7 @@ function KnowledgeBaseDetail() {
// 合并错误状态
const combinedError = error || filesError || operationError;
if (loading) {
if (loading || !knowledgeBase) {
return (
<Box sx={{ p: 3 }}>
<LinearProgress />
@@ -247,22 +275,10 @@ function KnowledgeBaseDetail() {
);
}
if (!knowledgeBase) {
return (
<Box sx={{ p: 3 }}>
<Alert severity="warning"></Alert>
</Box>
);
}
function fetchDocumentsFilter(): Promise<IDocumentInfoFilter | undefined> {
throw new Error('Function not implemented.');
}
return (
<Box sx={{ p: 3 }}>
{/* 面包屑导航 */}
<KnowledgeBreadcrumbs
<KnowledgeBreadcrumbs
kbItems={[
{
label: '知识库',
@@ -281,15 +297,15 @@ function KnowledgeBaseDetail() {
{/* 标签页组件 - 仅在showKnowledgeGraph为true时显示 */}
{showKnowledgeGraph ? (
<Box sx={{ mt: 3 }}>
<Tabs
value={currentTab}
<Tabs
value={currentTab}
onChange={(event, newValue) => setCurrentTab(newValue)}
sx={{ borderBottom: 1, borderColor: 'divider' }}
>
<Tab label="Documents" />
<Tab label="Graph" />
</Tabs>
{/* Document List 标签页内容 */}
{currentTab === 0 && (
<Box sx={{ mt: 2 }}>
@@ -300,7 +316,6 @@ function KnowledgeBaseDetail() {
onSearchChange={setSearchKeyword}
onReparse={(fileIds) => handleReparse(fileIds)}
onDelete={(fileIds) => {
console.log('删除文件:', fileIds);
setRowSelectionModel({
type: 'include',
ids: new Set(fileIds)
@@ -314,12 +329,15 @@ function KnowledgeBaseDetail() {
}}
rowSelectionModel={rowSelectionModel}
onRowSelectionModelChange={(newModel) => {
console.log('新的选择模型:', newModel);
setRowSelectionModel(newModel);
}}
total={total}
page={currentPage}
pageSize={pageSize}
documentFilter={documentsFilter}
onSelectedFilterChange={(filterBody) => {
fetchDocuments({}, filterBody);
}}
onPageChange={setCurrentPage}
onPageSizeChange={setPageSize}
onRename={handleRename}
@@ -330,7 +348,7 @@ function KnowledgeBaseDetail() {
/>
</Box>
)}
{/* Graph 标签页内容 */}
{currentTab === 1 && (
<Box sx={{ mt: 2 }}>
@@ -367,6 +385,10 @@ function KnowledgeBaseDetail() {
total={total}
page={currentPage}
pageSize={pageSize}
documentFilter={documentsFilter}
onSelectedFilterChange={(filterBody) => {
fetchDocuments({}, filterBody);
}}
onPageChange={setCurrentPage}
onPageSizeChange={setPageSize}
onRename={handleRename}
@@ -477,14 +499,14 @@ function KnowledgeBaseDetail() {
</Typography>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
<Chip
label={`${100*(selectedFileDetails.progress || 0)}%`}
color="primary"
size="small"
<Chip
label={`${100 * (selectedFileDetails.progress || 0)}%`}
color="primary"
size="small"
/>
<LinearProgress
variant="determinate"
value={100*(selectedFileDetails.progress || 0)}
<LinearProgress
variant="determinate"
value={100 * (selectedFileDetails.progress || 0)}
sx={{ flexGrow: 1, height: 8, borderRadius: 4 }}
/>
</Box>

View File

@@ -68,7 +68,7 @@ const knowledgeService = {
params?: IFetchKnowledgeListRequestParams,
body?: IFetchDocumentListRequestBody
) => {
return request.post(api.get_document_list, { data: body || {} }, { params });
return request.post(api.get_document_list, body || {}, { params });
},
// 创建文档

17
src/utils/logger.ts Normal file
View File

@@ -0,0 +1,17 @@
import log from 'loglevel';
// 根据环境设置日志级别
if (import.meta.env.DEV) {
log.setLevel('debug');
} else {
log.setLevel('warn');
}
const logger = {
debug: log.debug.bind(log),
info: log.info.bind(log),
warn: log.warn.bind(log),
error: log.error.bind(log),
}
export default logger;