Feat: New search page components and features (#9344)

### What problem does this PR solve?

Feat: New search page components and features #3221

- Added search homepage, search settings, and ongoing search components
- Implemented features such as search app list, creating search apps,
and deleting search apps
- Optimized the multi-select component, adding disabled state and suffix
display
- Adjusted navigation hooks to support search page navigation

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
chanx
2025-08-11 10:34:22 +08:00
committed by GitHub
parent 597d88bf9a
commit 4c7b2ef46e
16 changed files with 1347 additions and 87 deletions

View File

@ -0,0 +1,209 @@
// src/pages/next-searches/hooks.ts
import searchService from '@/services/search-service';
import { useMutation, useQuery } from '@tanstack/react-query';
import { message } from 'antd';
import { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useParams } from 'umi';
interface CreateSearchProps {
name: string;
description?: string;
}
interface CreateSearchResponse {
id: string;
name: string;
description: string;
}
export const useCreateSearch = () => {
const { t } = useTranslation();
const {
data,
isLoading,
isError,
mutateAsync: createSearchMutation,
} = useMutation<CreateSearchResponse, Error, CreateSearchProps>({
mutationKey: ['createSearch'],
mutationFn: async (props) => {
const { data: response } = await searchService.createSearch(props);
if (response.code !== 0) {
throw new Error(response.message || 'Failed to create search');
}
return response.data;
},
onSuccess: () => {
message.success(t('message.created'));
},
onError: (error) => {
message.error(t('message.error', { error: error.message }));
},
});
const createSearch = useCallback(
(props: CreateSearchProps) => {
return createSearchMutation(props);
},
[createSearchMutation],
);
return { data, isLoading, isError, createSearch };
};
export interface SearchListParams {
keywords?: string;
parser_id?: string;
page?: number;
page_size?: number;
orderby?: string;
desc?: boolean;
owner_ids?: string;
}
export interface ISearchAppProps {
avatar: any;
create_time: number;
created_by: string;
description: string;
id: string;
name: string;
nickname: string;
status: string;
tenant_avatar: any;
tenant_id: string;
update_time: number;
}
interface SearchListResponse {
code: number;
data: {
search_apps: Array<ISearchAppProps>;
total: number;
};
message: string;
}
export const useFetchSearchList = (params?: SearchListParams) => {
const [searchParams, setSearchParams] = useState<SearchListParams>({
page: 1,
page_size: 10,
...params,
});
const { data, isLoading, isError } = useQuery<SearchListResponse, Error>({
queryKey: ['searchList', searchParams],
queryFn: async () => {
const { data: response } =
await searchService.getSearchList(searchParams);
if (response.code !== 0) {
throw new Error(response.message || 'Failed to fetch search list');
}
return response;
},
});
const setSearchListParams = (newParams: SearchListParams) => {
setSearchParams((prevParams) => ({
...prevParams,
...newParams,
}));
};
return { data, isLoading, isError, searchParams, setSearchListParams };
};
interface DeleteSearchProps {
search_id: string;
}
interface DeleteSearchResponse {
code: number;
data: boolean;
message: string;
}
export const useDeleteSearch = () => {
const { t } = useTranslation();
const {
data,
isLoading,
isError,
mutateAsync: deleteSearchMutation,
} = useMutation<DeleteSearchResponse, Error, DeleteSearchProps>({
mutationKey: ['deleteSearch'],
mutationFn: async (props) => {
const response = await searchService.deleteSearch(props);
if (response.code !== 0) {
throw new Error(response.message || 'Failed to delete search');
}
return response;
},
onSuccess: () => {
message.success(t('message.deleted'));
},
onError: (error) => {
message.error(t('message.error', { error: error.message }));
},
});
const deleteSearch = useCallback(
(props: DeleteSearchProps) => {
return deleteSearchMutation(props);
},
[deleteSearchMutation],
);
return { data, isLoading, isError, deleteSearch };
};
export interface ISearchAppDetailProps {
avatar: any;
created_by: string;
description: string;
id: string;
name: string;
search_config: {
cross_languages: string[];
doc_ids: string[];
highlight: boolean;
kb_ids: string[];
keyword: boolean;
query_mindmap: boolean;
related_search: boolean;
rerank_id: string;
similarity_threshold: number;
summary: boolean;
top_k: number;
use_kg: boolean;
vector_similarity_weight: number;
web_search: boolean;
};
tenant_id: string;
update_time: number;
}
interface SearchDetailResponse {
code: number;
data: ISearchAppDetailProps;
message: string;
}
export const useFetchSearchDetail = () => {
const { id } = useParams();
const { data, isLoading, isError } = useQuery<SearchDetailResponse, Error>({
queryKey: ['searchDetail', id],
queryFn: async () => {
const { data: response } = await searchService.getSearchDetail({
search_id: id,
});
if (response.code !== 0) {
throw new Error(response.message || 'Failed to fetch search detail');
}
return response;
},
});
return { data: data?.data, isLoading, isError };
};