feat(next-search): Implements document preview functionality #3221 (#9465)

### What problem does this PR solve?

feat(next-search): Implements document preview functionality

- Adds a new document preview modal component
- Implements document preview page logic
- Adds document preview-related hooks
- Optimizes document preview rendering logic
### Type of change

- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
chanx
2025-08-14 12:11:53 +08:00
committed by GitHub
parent b55c3d07dc
commit b1baa91ff0
29 changed files with 1336 additions and 122 deletions

View File

@ -30,17 +30,24 @@ import { cn } from '@/lib/utils';
import { transformFile2Base64 } from '@/utils/file-util';
import { zodResolver } from '@hookform/resolvers/zod';
import { t } from 'i18next';
import { PanelRightClose, Pencil, Upload } from 'lucide-react';
import { Pencil, Upload, X } from 'lucide-react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { z } from 'zod';
import { LlmModelType, ModelVariableType } from '../dataset/dataset/constant';
import {
LlmModelType,
ModelVariableType,
settledModelVariableMap,
} from '../dataset/dataset/constant';
import {
ISearchAppDetailProps,
IUpdateSearchProps,
useUpdateSearch,
} from '../next-searches/hooks';
import { LlmSettingFieldItems } from './search-setting-aisummery-config';
import {
LlmSettingFieldItems,
LlmSettingSchema,
} from './search-setting-aisummery-config';
interface SearchSettingProps {
open: boolean;
@ -48,6 +55,15 @@ interface SearchSettingProps {
className?: string;
data: ISearchAppDetailProps;
}
interface ISubmitLlmSettingProps {
llm_id: string;
parameter: string;
temperature?: number;
top_p?: number;
frequency_penalty?: number;
presence_penalty?: number;
}
const SearchSettingFormSchema = z
.object({
search_id: z.string().optional(),
@ -64,14 +80,7 @@ const SearchSettingFormSchema = z
use_rerank: z.boolean(),
top_k: z.number(),
summary: z.boolean(),
llm_setting: z.object({
llm_id: z.string(),
parameter: z.string(),
temperature: z.number(),
top_p: z.union([z.string(), z.number()]),
frequency_penalty: z.number(),
presence_penalty: z.number(),
}),
llm_setting: z.object(LlmSettingSchema),
related_search: z.boolean(),
query_mindmap: z.boolean(),
}),
@ -133,10 +142,26 @@ const SearchSetting: React.FC<SearchSettingProps> = ({
llm_setting: {
llm_id: llm_setting?.llm_id || '',
parameter: llm_setting?.parameter || ModelVariableType.Improvise,
temperature: llm_setting?.temperature || 0.8,
top_p: llm_setting?.top_p || 0.9,
frequency_penalty: llm_setting?.frequency_penalty || 0.1,
presence_penalty: llm_setting?.presence_penalty || 0.1,
temperature:
llm_setting?.temperature ||
settledModelVariableMap[ModelVariableType.Improvise].temperature,
top_p:
llm_setting?.top_p ||
settledModelVariableMap[ModelVariableType.Improvise].top_p,
frequency_penalty:
llm_setting?.frequency_penalty ||
settledModelVariableMap[ModelVariableType.Improvise]
.frequency_penalty,
presence_penalty:
llm_setting?.presence_penalty ||
settledModelVariableMap[ModelVariableType.Improvise]
.presence_penalty,
temperatureEnabled: llm_setting?.temperature ? true : false,
topPEnabled: llm_setting?.top_p ? true : false,
presencePenaltyEnabled: llm_setting?.presence_penalty ? true : false,
frequencyPenaltyEnabled: llm_setting?.frequency_penalty
? true
: false,
},
chat_settingcross_languages: [],
highlight: false,
@ -193,7 +218,10 @@ const SearchSetting: React.FC<SearchSettingProps> = ({
setDatasetList(datasetListMap);
}, [datasetListOrigin, datasetSelectEmbdId]);
const handleDatasetSelectChange = (value, onChange) => {
const handleDatasetSelectChange = (
value: string[],
onChange: (value: string[]) => void,
) => {
console.log(value);
if (value.length) {
const data = datasetListOrigin?.find((item) => item.id === value[0]);
@ -224,18 +252,44 @@ const SearchSetting: React.FC<SearchSettingProps> = ({
name: 'search_config.summary',
});
const { updateSearch, isLoading: isUpdating } = useUpdateSearch();
const { updateSearch } = useUpdateSearch();
const { data: systemSetting } = useFetchTenantInfo();
const onSubmit = async (
formData: IUpdateSearchProps & { tenant_id: string },
) => {
try {
const { search_config, ...other_formdata } = formData;
const { llm_setting, ...other_config } = search_config;
const llmSetting = {
llm_id: llm_setting.llm_id,
parameter: llm_setting.parameter,
temperature: llm_setting.temperature,
top_p: llm_setting.top_p,
frequency_penalty: llm_setting.frequency_penalty,
presence_penalty: llm_setting.presence_penalty,
} as ISubmitLlmSettingProps;
if (!llm_setting.frequencyPenaltyEnabled) {
delete llmSetting.frequency_penalty;
}
if (!llm_setting.presencePenaltyEnabled) {
delete llmSetting.presence_penalty;
}
if (!llm_setting.temperatureEnabled) {
delete llmSetting.temperature;
}
if (!llm_setting.topPEnabled) {
delete llmSetting.top_p;
}
await updateSearch({
...formData,
...other_formdata,
search_config: {
...other_config,
llm_setting: { ...llmSetting },
},
tenant_id: systemSetting.tenant_id,
avatar: avatarBase64Str,
});
setOpen(false); // 关闭弹窗
setOpen(false);
} catch (error) {
console.error('Failed to update search:', error);
}
@ -256,10 +310,7 @@ const SearchSetting: React.FC<SearchSettingProps> = ({
<div className="flex justify-between items-center text-base mb-8">
<div className="text-text-primary">Search Settings</div>
<div onClick={() => setOpen(false)}>
<PanelRightClose
size={16}
className="text-text-primary cursor-pointer"
/>
<X size={16} className="text-text-primary cursor-pointer" />
</div>
</div>
<div
@ -271,7 +322,7 @@ const SearchSetting: React.FC<SearchSettingProps> = ({
onSubmit={formMethods.handleSubmit(
(data) => {
console.log('Form submitted with data:', data);
onSubmit(data as IUpdateSearchProps);
onSubmit(data as unknown as IUpdateSearchProps);
},
(errors) => {
console.log('Validation errors:', errors);
@ -462,26 +513,37 @@ const SearchSetting: React.FC<SearchSettingProps> = ({
</FormItem>
)}
/>
<FormField
control={formMethods.control}
name="search_config.top_k"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormItem>
<FormLabel>Top K</FormLabel>
<FormControl>
<div className="flex justify-between items-center">
<div
className={cn(
'flex items-center gap-4 justify-between',
className,
)}
>
<FormControl>
<SingleFormSlider
{...field}
max={100}
min={0}
step={1}
value={field.value as number}
onChange={(values) => field.onChange(values)}
></SingleFormSlider>
<Label className="w-10 h-6 bg-bg-card flex justify-center items-center rounded-lg ml-20">
{field.value}
</Label>
</div>
</FormControl>
</FormControl>
<FormControl>
<Input
type={'number'}
className="h-7 w-20 bg-bg-card"
max={100}
min={0}
step={1}
{...field}
></Input>
</FormControl>
</div>
<FormMessage />
</FormItem>
)}