feat(chunk): add chunk editing and image preview functionality

This commit is contained in:
2025-10-30 17:56:03 +08:00
parent b35fe51d60
commit 19b70a4abd
13 changed files with 448 additions and 147 deletions

View File

@@ -102,8 +102,8 @@ function OllamaDialog({
reset,
} = useForm<OllamaFormData>({
defaultValues: {
model_type: 'chat',
llm_name: '',
model_type: initialData?.model_type || 'chat',
llm_name: initialData?.llm_name || '',
api_base: initialData?.api_base,
api_key: initialData?.api_key,
max_tokens: initialData?.max_tokens,
@@ -146,8 +146,8 @@ function OllamaDialog({
useEffect(() => {
if (open) {
reset({
model_type: 'chat',
llm_name: '',
model_type: initialData?.model_type || 'chat',
llm_name: initialData?.llm_name || '',
api_base: initialData?.api_base,
api_key: initialData?.api_key,
max_tokens: initialData?.max_tokens,

View File

@@ -17,10 +17,10 @@ import {
import { useForm, Controller } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { LlmSvgIcon } from '@/components/AppSvgIcon';
import { IconMap, type LLMFactory } from '@/constants/llm';
import { type LLMFactory } from '@/constants/llm';
import type { ITenantInfo } from '@/interfaces/database/knowledge';
import type { LlmModelType } from '@/constants/knowledge';
import type { IMyLlmModel, IThirdOAIModel } from '@/interfaces/database/llm';
import type { IThirdOAIModel } from '@/interfaces/database/llm';
import { getFactoryIconName } from '@/utils/common';
interface AllModelOptionItem {
label: string;
@@ -75,11 +75,6 @@ function SystemModelDialog({
defaultValues: {}
});
// 获取工厂图标名称
const getFactoryIconName = (factoryName: LLMFactory) => {
return IconMap[factoryName] || 'default';
};
// all model options 包含了全部的 options
const llmOptions = useMemo(() => allModelOptions?.llmOptions || [], [allModelOptions]);
const embdOptions = useMemo(() => allModelOptions?.embeddingOptions || [], [allModelOptions]);

View File

@@ -6,6 +6,7 @@ import { IconMap, type LLMFactory } from "@/constants/llm";
import type { IFactory } from "@/interfaces/database/llm";
import { Box, Button, Card, CardContent, Chip, Typography } from "@mui/material";
import { useTranslation } from 'react-i18next';
import { getFactoryIconName } from '@/utils/common';
// 模型类型标签颜色映射
export const MODEL_TYPE_COLORS: Record<string, string> = {
@@ -30,11 +31,6 @@ const LLMFactoryCard: React.FC<ModelFactoryCardProps> = ({
}) => {
const { t } = useTranslation();
// 获取工厂图标名称
const getFactoryIconName = (factoryName: LLMFactory) => {
return IconMap[factoryName] || 'default';
};
return (
<Card sx={{
mb: 2,

View File

@@ -352,7 +352,6 @@ export const useModelDialogs = (onSuccess?: () => void) => {
// 根据工厂类型打开对应的对话框
const openFactoryDialog = useCallback((factoryName: string, data?: any, isEdit = false) => {
// 使用通用的 ConfigurationDialog 替代特定的 Dialog
configurationDialog.openConfigurationDialog(factoryName, data, isEdit);
}, [configurationDialog]);

View File

@@ -32,8 +32,16 @@ import { ModelDialogs } from './components/ModelDialogs';
import { useDialog } from '@/hooks/useDialog';
import logger from '@/utils/logger';
import { LLM_FACTORY_LIST, LocalLlmFactories, type LLMFactory } from '@/constants/llm';
import { LlmSvgIcon } from '@/components/AppSvgIcon';
import { getFactoryIconName } from '@/utils/common';
function MyLlmGridItem({ model, onDelete }: { model: ILlmItem, onDelete: (model: ILlmItem) => void }) {
interface MyLlmGridItemProps {
model: ILlmItem,
onDelete: (model: ILlmItem) => void,
onEditLlm?: (model: ILlmItem) => void,
}
function MyLlmGridItem({ model, onDelete, onEditLlm }: MyLlmGridItemProps) {
return (
<Grid size={{ xs: 6, sm: 4, md: 3 }} key={model.name}>
<Card variant="outlined" sx={{ p: 2 }}>
@@ -41,7 +49,21 @@ function MyLlmGridItem({ model, onDelete }: { model: ILlmItem, onDelete: (model:
<Typography variant="body2" fontWeight="bold">
{model.name}
</Typography>
<Box>
<Box sx={{
display: 'flex',
gap: 1,
}}>
{
onEditLlm && (
<IconButton
size="small"
color="primary"
onClick={() => onEditLlm(model)}
>
<EditIcon fontSize="small" />
</IconButton>
)
}
<IconButton
size="small"
color="error"
@@ -105,8 +127,8 @@ function ModelsPage() {
if (!fN) {
return false;
}
return LocalLlmFactories.includes(fN) ||
return LocalLlmFactories.includes(fN) ||
configurationFactories.includes(fN);
}
@@ -144,7 +166,7 @@ function ModelsPage() {
logger.debug('handleConfigureFactory', factory);
}, [modelDialogs]);
const handleEditLlmFactory = useCallback((factoryName: string) => {
const handleEditLlmFactory = useCallback((factoryName: string, llmmodel?: ILlmItem) => {
if (factoryName == null) {
return;
}
@@ -164,10 +186,17 @@ function ModelsPage() {
// local llm
modelDialogs.ollamaDialog.openDialog({
llm_factory: factoryN,
...llmmodel,
llm_name: llmmodel?.name || '',
model_type: llmmodel?.type || 'chat',
}, true);
} else if (configurationFactories.includes(factoryN)) {
// custom configuration llm
modelDialogs.configurationDialog.openConfigurationDialog(factoryN);
modelDialogs.configurationDialog.openConfigurationDialog(factoryN, {
...llmmodel,
llm_name: llmmodel?.name || '',
model_type: llmmodel?.type || 'chat',
});
} else {
// llm set api
modelDialogs.apiKeyDialog.openApiKeyDialog(factoryN, {}, true);
@@ -246,9 +275,9 @@ function ModelsPage() {
<AccordionDetails>
<Grid container spacing={2}>
{Object.entries(myLlm).map(([factoryName, group]) => (
<Grid size={12} key={factoryName}>
<Grid size={12} key={factoryName} >
<Card variant="outlined">
<CardContent>
<CardContent sx={{ padding: 2 }}>
<Box
sx={{
display: 'flex',
@@ -267,12 +296,15 @@ function ModelsPage() {
{collapsedFactories[factoryName] ? <ExpandLessIcon /> : <ExpandMoreIcon />}
</IconButton>
<Box>
{/* 模型工厂名称 */}
<Typography variant="h6" gutterBottom>
{factoryName}
</Typography>
<Box sx={{ display: 'flex', flexDirection: 'row', gap: 2, alignItems: 'center' }}>
{/* svg icon */}
<LlmSvgIcon name={getFactoryIconName(factoryName as LLMFactory)} sx={{ fontSize: 36 }} />
{/* 模型工厂名称 */}
<Typography variant="h6" gutterBottom>
{factoryName}
</Typography></Box>
{/* 模型标签 */}
<Box display="flex" gap={1} mb={2}>
<Box display="flex" gap={1} mt={2}>
{group.tags.split(',').map((tag) => (
<Chip
key={tag}
@@ -293,7 +325,7 @@ function ModelsPage() {
variant='contained' color='primary' startIcon={<EditIcon />}
onClick={() => handleEditLlmFactory(factoryName)}
>
{ showAddModel(factoryName) ? t('setting.addModel') : t('setting.edit')}
{showAddModel(factoryName) ? t('setting.addModel') : t('setting.edit')}
</Button>
<Button
variant='outlined' color='primary' startIcon={<DeleteIcon />}
@@ -311,6 +343,9 @@ function ModelsPage() {
<MyLlmGridItem
key={model.name}
model={model}
onEditLlm={showAddModel(factoryName) ? (llm) => {
handleEditLlmFactory(factoryName, llm);
} : undefined}
onDelete={() => handleDeleteModel(factoryName, model.name)}
/>
))}