mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-28 09:03:53 +00:00
perf: Dataset new ui (#2555)
* perf: dataset detail ui * fix: collection tag modal * perf: data card support markdown * fix :ts
This commit is contained in:
@@ -5,9 +5,14 @@ import { Box, Image, ImageProps } from '@chakra-ui/react';
|
|||||||
import { useSystem } from '../../../hooks/useSystem';
|
import { useSystem } from '../../../hooks/useSystem';
|
||||||
import Loading from '../MyLoading';
|
import Loading from '../MyLoading';
|
||||||
|
|
||||||
const MyPhotoView = (props: ImageProps) => {
|
const MyPhotoView = ({
|
||||||
|
forbidImgPreview,
|
||||||
|
...props
|
||||||
|
}: ImageProps & { forbidImgPreview?: boolean }) => {
|
||||||
const { isPc } = useSystem();
|
const { isPc } = useSystem();
|
||||||
return (
|
return forbidImgPreview ? (
|
||||||
|
<Image {...props} />
|
||||||
|
) : (
|
||||||
<PhotoProvider
|
<PhotoProvider
|
||||||
maskOpacity={0.6}
|
maskOpacity={0.6}
|
||||||
bannerVisible={!isPc}
|
bannerVisible={!isPc}
|
||||||
|
@@ -19,8 +19,8 @@ import {
|
|||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import type { ButtonProps, MenuItemProps } from '@chakra-ui/react';
|
import type { ButtonProps, MenuItemProps } from '@chakra-ui/react';
|
||||||
import { ChevronDownIcon } from '@chakra-ui/icons';
|
import { ChevronDownIcon } from '@chakra-ui/icons';
|
||||||
import { useLoading } from '../../../hooks/useLoading';
|
|
||||||
import MyIcon from '../Icon';
|
import MyIcon from '../Icon';
|
||||||
|
import { useRequest2 } from '../../../hooks/useRequest';
|
||||||
|
|
||||||
export type SelectProps<T = any> = ButtonProps & {
|
export type SelectProps<T = any> = ButtonProps & {
|
||||||
value?: T;
|
value?: T;
|
||||||
@@ -32,7 +32,7 @@ export type SelectProps<T = any> = ButtonProps & {
|
|||||||
value: T;
|
value: T;
|
||||||
}[];
|
}[];
|
||||||
isLoading?: boolean;
|
isLoading?: boolean;
|
||||||
onchange?: (val: T) => void;
|
onchange?: (val: T) => any | Promise<any>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const MySelect = <T = any,>(
|
const MySelect = <T = any,>(
|
||||||
@@ -82,6 +82,10 @@ const MySelect = <T = any,>(
|
|||||||
}
|
}
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
|
const { runAsync: onChange, loading } = useRequest2((val: T) => onchange?.(val));
|
||||||
|
|
||||||
|
const isSelecting = loading || isLoading;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
css={css({
|
css={css({
|
||||||
@@ -92,7 +96,7 @@ const MySelect = <T = any,>(
|
|||||||
>
|
>
|
||||||
<Menu
|
<Menu
|
||||||
autoSelect={false}
|
autoSelect={false}
|
||||||
isOpen={isOpen}
|
isOpen={isOpen && !isSelecting}
|
||||||
onOpen={onOpen}
|
onOpen={onOpen}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
strategy={'fixed'}
|
strategy={'fixed'}
|
||||||
@@ -118,7 +122,7 @@ const MySelect = <T = any,>(
|
|||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<Flex alignItems={'center'}>
|
<Flex alignItems={'center'}>
|
||||||
{isLoading && <MyIcon mr={2} name={'common/loading'} w={'16px'} />}
|
{isSelecting && <MyIcon mr={2} name={'common/loading'} w={'16px'} />}
|
||||||
{selectItem?.alias || selectItem?.label || placeholder}
|
{selectItem?.alias || selectItem?.label || placeholder}
|
||||||
</Flex>
|
</Flex>
|
||||||
</MenuButton>
|
</MenuButton>
|
||||||
@@ -160,8 +164,8 @@ const MySelect = <T = any,>(
|
|||||||
color: 'myGray.900'
|
color: 'myGray.900'
|
||||||
})}
|
})}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (onchange && value !== item.value) {
|
if (onChange && value !== item.value) {
|
||||||
onchange(item.value);
|
onChange(item.value);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
whiteSpace={'pre-wrap'}
|
whiteSpace={'pre-wrap'}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { Box, Flex, Grid, Image } from '@chakra-ui/react';
|
import { Box, Flex, Grid } from '@chakra-ui/react';
|
||||||
import type { FlexProps, GridProps } from '@chakra-ui/react';
|
import type { FlexProps, GridProps } from '@chakra-ui/react';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import Avatar from '../Avatar';
|
import Avatar from '../Avatar';
|
||||||
@@ -9,7 +9,7 @@ type Props<ValueType = string> = Omit<GridProps, 'onChange'> & {
|
|||||||
value: ValueType;
|
value: ValueType;
|
||||||
size?: 'sm' | 'md' | 'lg';
|
size?: 'sm' | 'md' | 'lg';
|
||||||
inlineStyles?: FlexProps;
|
inlineStyles?: FlexProps;
|
||||||
activatedColor?: string;
|
activeColor?: string;
|
||||||
onChange: (value: ValueType) => void;
|
onChange: (value: ValueType) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ const LightRowTabs = <ValueType = string,>({
|
|||||||
list,
|
list,
|
||||||
size = 'md',
|
size = 'md',
|
||||||
value,
|
value,
|
||||||
activatedColor = 'primary.600',
|
activeColor = 'primary.600',
|
||||||
onChange,
|
onChange,
|
||||||
inlineStyles,
|
inlineStyles,
|
||||||
...props
|
...props
|
||||||
@@ -68,10 +68,10 @@ const LightRowTabs = <ValueType = string,>({
|
|||||||
whiteSpace={'nowrap'}
|
whiteSpace={'nowrap'}
|
||||||
{...(value === item.value
|
{...(value === item.value
|
||||||
? {
|
? {
|
||||||
color: activatedColor,
|
color: activeColor,
|
||||||
cursor: 'default',
|
cursor: 'default',
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
borderBottomColor: activatedColor
|
borderBottomColor: activeColor
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
cursor: 'pointer'
|
cursor: 'pointer'
|
||||||
|
@@ -3,7 +3,7 @@ import { Box, ImageProps, Skeleton } from '@chakra-ui/react';
|
|||||||
import MyPhotoView from '@fastgpt/web/components/common/Image/PhotoView';
|
import MyPhotoView from '@fastgpt/web/components/common/Image/PhotoView';
|
||||||
import { useBoolean } from 'ahooks';
|
import { useBoolean } from 'ahooks';
|
||||||
|
|
||||||
const MdImage = ({ src, ...props }: { src?: string } & ImageProps) => {
|
const MdImage = ({ src, ...props }: { src?: string; forbidImgPreview?: boolean } & ImageProps) => {
|
||||||
const [isLoaded, { setTrue }] = useBoolean(false);
|
const [isLoaded, { setTrue }] = useBoolean(false);
|
||||||
|
|
||||||
const [renderSrc, setRenderSrc] = useState(src);
|
const [renderSrc, setRenderSrc] = useState(src);
|
||||||
@@ -11,7 +11,6 @@ const MdImage = ({ src, ...props }: { src?: string } & ImageProps) => {
|
|||||||
if (src?.includes('base64') && !src.startsWith('data:image')) {
|
if (src?.includes('base64') && !src.startsWith('data:image')) {
|
||||||
return <Box>Invalid base64 image</Box>;
|
return <Box>Invalid base64 image</Box>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Skeleton isLoaded={isLoaded}>
|
<Skeleton isLoaded={isLoaded}>
|
||||||
<MyPhotoView
|
<MyPhotoView
|
||||||
|
@@ -28,20 +28,22 @@ const QuestionGuide = dynamic(() => import('./chat/QuestionGuide'), { ssr: false
|
|||||||
|
|
||||||
const Markdown = ({
|
const Markdown = ({
|
||||||
source = '',
|
source = '',
|
||||||
showAnimation = false
|
showAnimation = false,
|
||||||
|
forbidImgPreview = false
|
||||||
}: {
|
}: {
|
||||||
source?: string;
|
source?: string;
|
||||||
showAnimation?: boolean;
|
showAnimation?: boolean;
|
||||||
|
forbidImgPreview?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const components = useMemo<any>(
|
const components = useMemo<any>(
|
||||||
() => ({
|
() => ({
|
||||||
img: Image,
|
img: (props: any) => <Image {...props} forbidImgPreview={forbidImgPreview} />,
|
||||||
pre: RewritePre,
|
pre: RewritePre,
|
||||||
p: (pProps: any) => <p {...pProps} dir="auto" />,
|
p: (pProps: any) => <p {...pProps} dir="auto" />,
|
||||||
code: Code,
|
code: Code,
|
||||||
a: A
|
a: A
|
||||||
}),
|
}),
|
||||||
[]
|
[forbidImgPreview]
|
||||||
);
|
);
|
||||||
|
|
||||||
const formatSource = useMemo(() => {
|
const formatSource = useMemo(() => {
|
||||||
@@ -74,7 +76,7 @@ const Markdown = ({
|
|||||||
export default React.memo(Markdown);
|
export default React.memo(Markdown);
|
||||||
|
|
||||||
/* Custom dom */
|
/* Custom dom */
|
||||||
const Code = React.memo(function Code(e: any) {
|
function Code(e: any) {
|
||||||
const { className, codeBlock, children } = e;
|
const { className, codeBlock, children } = e;
|
||||||
const match = /language-(\w+)/.exec(className || '');
|
const match = /language-(\w+)/.exec(className || '');
|
||||||
const codeType = match?.[1];
|
const codeType = match?.[1];
|
||||||
@@ -103,11 +105,13 @@ const Code = React.memo(function Code(e: any) {
|
|||||||
}, [codeType, className, codeBlock, match, children, strChildren]);
|
}, [codeType, className, codeBlock, match, children, strChildren]);
|
||||||
|
|
||||||
return Component;
|
return Component;
|
||||||
});
|
}
|
||||||
const Image = React.memo(function Image({ src }: { src?: string }) {
|
|
||||||
return <MdImage src={src} />;
|
function Image({ src, forbidImgPreview }: { forbidImgPreview: boolean; src?: string }) {
|
||||||
});
|
return <MdImage forbidImgPreview={forbidImgPreview} src={src} />;
|
||||||
const A = React.memo(function A({ children, ...props }: any) {
|
}
|
||||||
|
|
||||||
|
function A({ children, ...props }: any) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
// empty href link
|
// empty href link
|
||||||
@@ -152,7 +156,7 @@ const A = React.memo(function A({ children, ...props }: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return <Link {...props}>{children}</Link>;
|
return <Link {...props}>{children}</Link>;
|
||||||
});
|
}
|
||||||
|
|
||||||
function RewritePre({ children }: any) {
|
function RewritePre({ children }: any) {
|
||||||
const modifiedChildren = React.Children.map(children, (child) => {
|
const modifiedChildren = React.Children.map(children, (child) => {
|
||||||
|
@@ -61,7 +61,7 @@ const AIModelSelector = ({ list, onchange, disableTip, ...props }: Props) => {
|
|||||||
router.push(AI_POINT_USAGE_CARD_ROUTE);
|
router.push(AI_POINT_USAGE_CARD_ROUTE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
onchange?.(e);
|
return onchange?.(e);
|
||||||
},
|
},
|
||||||
[onchange, router]
|
[onchange, router]
|
||||||
);
|
);
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Box, BoxProps, ButtonProps } from '@chakra-ui/react';
|
import { Box, BoxProps } from '@chakra-ui/react';
|
||||||
import MySelect from '@fastgpt/web/components/common/MySelect';
|
import MySelect from '@fastgpt/web/components/common/MySelect';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { PermissionValueType } from '@fastgpt/global/support/permission/type';
|
import type { PermissionValueType } from '@fastgpt/global/support/permission/type';
|
||||||
@@ -20,7 +20,6 @@ type Props = Omit<BoxProps, 'onChange'> & {
|
|||||||
writePer?: PermissionValueType;
|
writePer?: PermissionValueType;
|
||||||
onChange: (v: PermissionValueType) => Promise<any> | any;
|
onChange: (v: PermissionValueType) => Promise<any> | any;
|
||||||
isInheritPermission?: boolean;
|
isInheritPermission?: boolean;
|
||||||
isDisabled?: boolean;
|
|
||||||
hasParent?: boolean;
|
hasParent?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,15 +41,12 @@ const DefaultPermissionList = ({
|
|||||||
{ label: t('user:permission.team_write'), value: writePer }
|
{ label: t('user:permission.team_write'), value: writePer }
|
||||||
];
|
];
|
||||||
|
|
||||||
const { runAsync: onRequestChange, loading } = useRequest2((v: PermissionValueType) =>
|
const { runAsync: onRequestChange } = useRequest2((v: PermissionValueType) => onChange(v));
|
||||||
onChange(v)
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box {...styles}>
|
<Box {...styles}>
|
||||||
<MySelect
|
<MySelect
|
||||||
isLoading={loading}
|
|
||||||
list={defaultPermissionSelectList}
|
list={defaultPermissionSelectList}
|
||||||
value={per}
|
value={per}
|
||||||
onchange={(per) => {
|
onchange={(per) => {
|
||||||
|
@@ -1,5 +1,14 @@
|
|||||||
import React, { useCallback, useRef } from 'react';
|
import React, { useCallback, useRef } from 'react';
|
||||||
import { Box, Flex, MenuButton, Button, Link, useTheme, useDisclosure } from '@chakra-ui/react';
|
import {
|
||||||
|
Box,
|
||||||
|
Flex,
|
||||||
|
MenuButton,
|
||||||
|
Button,
|
||||||
|
Link,
|
||||||
|
useTheme,
|
||||||
|
useDisclosure,
|
||||||
|
HStack
|
||||||
|
} from '@chakra-ui/react';
|
||||||
import {
|
import {
|
||||||
getDatasetCollectionPathById,
|
getDatasetCollectionPathById,
|
||||||
postDatasetCollection,
|
postDatasetCollection,
|
||||||
@@ -114,55 +123,55 @@ const Header = ({}: {}) => {
|
|||||||
const isWebSite = datasetDetail?.type === DatasetTypeEnum.websiteDataset;
|
const isWebSite = datasetDetail?.type === DatasetTypeEnum.websiteDataset;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex px={[2, 6]} alignItems={'flex-start'} h={'35px'}>
|
<Box display={['block', 'flex']} alignItems={'center'} gap={2}>
|
||||||
<Box flex={1} fontWeight={'500'} color={'myGray.900'} h={'100%'}>
|
<HStack flex={1}>
|
||||||
<ParentPath
|
<Box flex={1} fontWeight={'500'} color={'myGray.900'}>
|
||||||
paths={paths.map((path, i) => ({
|
<ParentPath
|
||||||
parentId: path.parentId,
|
paths={paths.map((path, i) => ({
|
||||||
parentName: i === paths.length - 1 ? `${path.parentName}` : path.parentName
|
parentId: path.parentId,
|
||||||
}))}
|
parentName: i === paths.length - 1 ? `${path.parentName}` : path.parentName
|
||||||
FirstPathDom={
|
}))}
|
||||||
<Flex
|
FirstPathDom={
|
||||||
flexDir={'column'}
|
<Flex
|
||||||
justify={'center'}
|
flexDir={'column'}
|
||||||
h={'100%'}
|
justify={'center'}
|
||||||
fontSize={isWebSite ? 'sm' : 'md'}
|
h={'100%'}
|
||||||
fontWeight={'500'}
|
fontSize={isWebSite ? 'sm' : 'md'}
|
||||||
color={'myGray.600'}
|
fontWeight={'500'}
|
||||||
>
|
color={'myGray.600'}
|
||||||
<Flex align={'center'}>
|
>
|
||||||
{!isWebSite && <MyIcon name="common/list" mr={2} w={'20px'} color={'black'} />}
|
<Flex align={'center'}>
|
||||||
{t(DatasetTypeMap[datasetDetail?.type]?.collectionLabel as any)}({total})
|
{!isWebSite && <MyIcon name="common/list" mr={2} w={'20px'} color={'black'} />}
|
||||||
</Flex>
|
{t(DatasetTypeMap[datasetDetail?.type]?.collectionLabel as any)}({total})
|
||||||
{datasetDetail?.websiteConfig?.url && (
|
|
||||||
<Flex fontSize={'mini'}>
|
|
||||||
{t('common:core.dataset.website.Base Url')}:
|
|
||||||
<Link
|
|
||||||
href={datasetDetail.websiteConfig.url}
|
|
||||||
target="_blank"
|
|
||||||
mr={2}
|
|
||||||
color={'blue.700'}
|
|
||||||
>
|
|
||||||
{datasetDetail.websiteConfig.url}
|
|
||||||
</Link>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
{datasetDetail?.websiteConfig?.url && (
|
||||||
</Flex>
|
<Flex fontSize={'mini'}>
|
||||||
}
|
{t('common:core.dataset.website.Base Url')}:
|
||||||
onClick={(e) => {
|
<Link
|
||||||
router.replace({
|
href={datasetDetail.websiteConfig.url}
|
||||||
query: {
|
target="_blank"
|
||||||
...router.query,
|
mr={2}
|
||||||
parentId: e
|
color={'blue.700'}
|
||||||
}
|
>
|
||||||
});
|
{datasetDetail.websiteConfig.url}
|
||||||
}}
|
</Link>
|
||||||
/>
|
</Flex>
|
||||||
</Box>
|
)}
|
||||||
|
</Flex>
|
||||||
|
}
|
||||||
|
onClick={(e) => {
|
||||||
|
router.replace({
|
||||||
|
query: {
|
||||||
|
...router.query,
|
||||||
|
parentId: e
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
{/* search input */}
|
{/* search input */}
|
||||||
{isPc && (
|
{isPc && (
|
||||||
<Flex alignItems={'center'} mr={4}>
|
|
||||||
<MyInput
|
<MyInput
|
||||||
w={['100%', '250px']}
|
w={['100%', '250px']}
|
||||||
size={'sm'}
|
size={'sm'}
|
||||||
@@ -192,14 +201,15 @@ const Header = ({}: {}) => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
)}
|
||||||
)}
|
|
||||||
|
{/* Tag */}
|
||||||
|
{datasetDetail.permission.hasWritePer && feConfigs?.isPlus && <HeaderTagPopOver />}
|
||||||
|
</HStack>
|
||||||
|
|
||||||
{/* diff collection button */}
|
{/* diff collection button */}
|
||||||
{datasetDetail.permission.hasWritePer && (
|
{datasetDetail.permission.hasWritePer && (
|
||||||
<Flex gap={3}>
|
<Box textAlign={'end'} mt={[3, 0]}>
|
||||||
{feConfigs?.isPlus && <HeaderTagPopOver />}
|
|
||||||
|
|
||||||
{datasetDetail?.type === DatasetTypeEnum.dataset && (
|
{datasetDetail?.type === DatasetTypeEnum.dataset && (
|
||||||
<MyMenu
|
<MyMenu
|
||||||
offset={[0, 5]}
|
offset={[0, 5]}
|
||||||
@@ -396,7 +406,7 @@ const Header = ({}: {}) => {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* modal */}
|
{/* modal */}
|
||||||
@@ -427,7 +437,7 @@ const Header = ({}: {}) => {
|
|||||||
)}
|
)}
|
||||||
<EditCreateVirtualFileModal iconSrc={'modal/manualDataset'} closeBtnText={''} />
|
<EditCreateVirtualFileModal iconSrc={'modal/manualDataset'} closeBtnText={''} />
|
||||||
{isOpenFileSourceSelector && <FileSourceSelector onClose={onCloseFileSourceSelector} />}
|
{isOpenFileSourceSelector && <FileSourceSelector onClose={onCloseFileSourceSelector} />}
|
||||||
</Flex>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -29,7 +29,7 @@ const TagManageModal = ({ onClose }: { onClose: () => void }) => {
|
|||||||
const datasetDetail = useContextSelector(DatasetPageContext, (v) => v.datasetDetail);
|
const datasetDetail = useContextSelector(DatasetPageContext, (v) => v.datasetDetail);
|
||||||
const loadDatasetTags = useContextSelector(DatasetPageContext, (v) => v.loadDatasetTags);
|
const loadDatasetTags = useContextSelector(DatasetPageContext, (v) => v.loadDatasetTags);
|
||||||
const loadAllDatasetTags = useContextSelector(DatasetPageContext, (v) => v.loadAllDatasetTags);
|
const loadAllDatasetTags = useContextSelector(DatasetPageContext, (v) => v.loadAllDatasetTags);
|
||||||
const { getData, collections } = useContextSelector(CollectionPageContext, (v) => v);
|
const { getData, pageNum, collections } = useContextSelector(CollectionPageContext, (v) => v);
|
||||||
|
|
||||||
const tagInputRef = useRef<HTMLInputElement>(null);
|
const tagInputRef = useRef<HTMLInputElement>(null);
|
||||||
const editInputRef = useRef<HTMLInputElement>(null);
|
const editInputRef = useRef<HTMLInputElement>(null);
|
||||||
@@ -73,42 +73,43 @@ const TagManageModal = ({ onClose }: { onClose: () => void }) => {
|
|||||||
errorToast: t('common:common.Create Failed')
|
errorToast: t('common:common.Create Failed')
|
||||||
});
|
});
|
||||||
|
|
||||||
const { mutate: onDeleteCollectionTag, isLoading: isDeleteCollectionTagLoading } = useRequest({
|
const { runAsync: onDeleteCollectionTag, loading: isDeleteCollectionTagLoading } = useRequest2(
|
||||||
mutationFn: async (tag: string) => {
|
(tag: string) => {
|
||||||
const id = await delDatasetCollectionTag({
|
return delDatasetCollectionTag({
|
||||||
datasetId: datasetDetail._id,
|
datasetId: datasetDetail._id,
|
||||||
id: tag
|
id: tag
|
||||||
});
|
});
|
||||||
return id;
|
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
onSuccess() {
|
||||||
|
fetchData(1);
|
||||||
|
loadDatasetTags({ id: datasetDetail._id, searchKey: '' });
|
||||||
|
loadAllDatasetTags({ id: datasetDetail._id });
|
||||||
|
},
|
||||||
|
successToast: t('common:common.Delete Success'),
|
||||||
|
errorToast: t('common:common.Delete Failed')
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
onSuccess() {
|
const { runAsync: onUpdateCollectionTag, loading: isUpdateCollectionTagLoading } = useRequest2(
|
||||||
fetchData(1);
|
async (tag: DatasetTagType) => {
|
||||||
loadDatasetTags({ id: datasetDetail._id, searchKey: '' });
|
return updateDatasetCollectionTag({
|
||||||
loadAllDatasetTags({ id: datasetDetail._id });
|
|
||||||
},
|
|
||||||
successToast: t('common:common.Delete Success'),
|
|
||||||
errorToast: t('common:common.Delete Failed')
|
|
||||||
});
|
|
||||||
|
|
||||||
const { mutate: onUpdateCollectionTag, isLoading: isUpdateCollectionTagLoading } = useRequest({
|
|
||||||
mutationFn: async (tag: DatasetTagType) => {
|
|
||||||
const id = await updateDatasetCollectionTag({
|
|
||||||
datasetId: datasetDetail._id,
|
datasetId: datasetDetail._id,
|
||||||
tagId: tag._id,
|
tagId: tag._id,
|
||||||
tag: tag.tag
|
tag: tag.tag
|
||||||
});
|
});
|
||||||
return id;
|
|
||||||
},
|
},
|
||||||
onSuccess() {
|
{
|
||||||
fetchData(1);
|
onSuccess() {
|
||||||
loadDatasetTags({ id: datasetDetail._id, searchKey: '' });
|
fetchData(1);
|
||||||
loadAllDatasetTags({ id: datasetDetail._id });
|
loadDatasetTags({ id: datasetDetail._id, searchKey: '' });
|
||||||
|
loadAllDatasetTags({ id: datasetDetail._id });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
const { mutate: onSaveCollectionTag, isLoading: isSaveCollectionTagLoading } = useRequest({
|
const { runAsync: onSaveCollectionTag, loading: isSaveCollectionTagLoading } = useRequest2(
|
||||||
mutationFn: async ({
|
async ({
|
||||||
tag,
|
tag,
|
||||||
originCollectionIds,
|
originCollectionIds,
|
||||||
collectionIds
|
collectionIds
|
||||||
@@ -117,22 +118,21 @@ const TagManageModal = ({ onClose }: { onClose: () => void }) => {
|
|||||||
originCollectionIds: string[];
|
originCollectionIds: string[];
|
||||||
collectionIds: string[];
|
collectionIds: string[];
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
return postAddTagsToCollections({
|
||||||
await postAddTagsToCollections({
|
tag,
|
||||||
tag,
|
originCollectionIds,
|
||||||
originCollectionIds,
|
collectionIds,
|
||||||
collectionIds,
|
datasetId: datasetDetail._id
|
||||||
datasetId: datasetDetail._id
|
});
|
||||||
});
|
|
||||||
} catch (error) {}
|
|
||||||
},
|
},
|
||||||
|
{
|
||||||
onSuccess() {
|
onFinally() {
|
||||||
getData(1);
|
getData(pageNum);
|
||||||
},
|
},
|
||||||
successToast: t('common:common.Save Success'),
|
successToast: t('common:common.Save Success'),
|
||||||
errorToast: t('common:common.Save Failed')
|
errorToast: t('common:common.Save Failed')
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
list,
|
list,
|
||||||
@@ -379,11 +379,9 @@ const AddTagToCollections = ({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const datasetDetail = useContextSelector(DatasetPageContext, (v) => v.datasetDetail);
|
const datasetDetail = useContextSelector(DatasetPageContext, (v) => v.datasetDetail);
|
||||||
const [selectedCollections, setSelectedCollections] = useState<string[]>([]);
|
const [selectedCollections, setSelectedCollections] = useState<string[]>(
|
||||||
|
currentAddTag.collections
|
||||||
useEffect(() => {
|
);
|
||||||
setSelectedCollections(currentAddTag.collections);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const [searchText, setSearchText] = useState('');
|
const [searchText, setSearchText] = useState('');
|
||||||
|
|
||||||
|
@@ -21,7 +21,7 @@ import { useQuery } from '@tanstack/react-query';
|
|||||||
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||||
import { useRequest, useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import MyMenu from '@fastgpt/web/components/common/MyMenu';
|
import MyMenu from '@fastgpt/web/components/common/MyMenu';
|
||||||
import { useEditTitle } from '@/web/common/hooks/useEditTitle';
|
import { useEditTitle } from '@/web/common/hooks/useEditTitle';
|
||||||
@@ -119,23 +119,22 @@ const CollectionCard = () => {
|
|||||||
successToast: t('common:common.Update Success')
|
successToast: t('common:common.Update Success')
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const { mutate: onDelCollection, isLoading: isDeleting } = useRequest({
|
const { runAsync: onDelCollection, loading: isDeleting } = useRequest2(
|
||||||
mutationFn: (collectionId: string) => {
|
(collectionId: string) => {
|
||||||
return delDatasetCollectionById({
|
return delDatasetCollectionById({
|
||||||
id: collectionId
|
id: collectionId
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onSuccess() {
|
{
|
||||||
getData(pageNum);
|
onSuccess() {
|
||||||
},
|
getData(pageNum);
|
||||||
successToast: t('common:common.Delete Success'),
|
},
|
||||||
errorToast: t('common:common.Delete Failed')
|
successToast: t('common:common.Delete Success'),
|
||||||
});
|
errorToast: t('common:common.Delete Failed')
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const { mutate: onclickStartSync, isLoading: isSyncing } = useRequest({
|
const { runAsync: onclickStartSync, loading: isSyncing } = useRequest2(postLinkCollectionSync, {
|
||||||
mutationFn: (collectionId: string) => {
|
|
||||||
return postLinkCollectionSync(collectionId);
|
|
||||||
},
|
|
||||||
onSuccess(res: DatasetCollectionSyncResultEnum) {
|
onSuccess(res: DatasetCollectionSyncResultEnum) {
|
||||||
getData(pageNum);
|
getData(pageNum);
|
||||||
toast({
|
toast({
|
||||||
@@ -186,12 +185,12 @@ const CollectionCard = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<MyBox isLoading={isLoading} h={'100%'} py={[2, 4]}>
|
<MyBox isLoading={isLoading} h={'100%'} py={[2, 4]}>
|
||||||
<Flex ref={BoxRef} flexDirection={'column'} py={[1, 0]} h={'100%'}>
|
<Flex ref={BoxRef} flexDirection={'column'} py={[1, 0]} h={'100%'} px={[2, 6]}>
|
||||||
{/* header */}
|
{/* header */}
|
||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
{/* collection table */}
|
{/* collection table */}
|
||||||
<TableContainer px={[2, 6]} mt={[0, 3]} overflowY={'auto'} fontSize={'sm'}>
|
<TableContainer mt={3} overflowY={'auto'} fontSize={'sm'}>
|
||||||
<Table variant={'simple'} draggable={false}>
|
<Table variant={'simple'} draggable={false}>
|
||||||
<Thead draggable={false}>
|
<Thead draggable={false}>
|
||||||
<Tr>
|
<Tr>
|
||||||
@@ -237,7 +236,7 @@ const CollectionCard = () => {
|
|||||||
>
|
>
|
||||||
<Td minW={'150px'} maxW={['200px', '300px']} draggable py={2}>
|
<Td minW={'150px'} maxW={['200px', '300px']} draggable py={2}>
|
||||||
<Flex alignItems={'center'}>
|
<Flex alignItems={'center'}>
|
||||||
<MyIcon name={collection.icon as any} w={'18px'} mr={2} />
|
<MyIcon name={collection.icon as any} w={'1.25rem'} mr={2} />
|
||||||
<MyTooltip
|
<MyTooltip
|
||||||
label={t('common:common.folder.Drag Tip')}
|
label={t('common:common.folder.Drag Tip')}
|
||||||
shouldWrapChildren={false}
|
shouldWrapChildren={false}
|
||||||
@@ -287,8 +286,8 @@ const CollectionCard = () => {
|
|||||||
offset={[-70, 5]}
|
offset={[-70, 5]}
|
||||||
Button={
|
Button={
|
||||||
<MenuButton
|
<MenuButton
|
||||||
w={'22px'}
|
w={'1.5rem'}
|
||||||
h={'22px'}
|
h={'1.5rem'}
|
||||||
borderRadius={'md'}
|
borderRadius={'md'}
|
||||||
_hover={{
|
_hover={{
|
||||||
color: 'primary.500',
|
color: 'primary.500',
|
||||||
@@ -300,8 +299,8 @@ const CollectionCard = () => {
|
|||||||
<MyIcon
|
<MyIcon
|
||||||
className="icon"
|
className="icon"
|
||||||
name={'more'}
|
name={'more'}
|
||||||
h={'16px'}
|
h={'1rem'}
|
||||||
w={'16px'}
|
w={'1rem'}
|
||||||
px={1}
|
px={1}
|
||||||
py={1}
|
py={1}
|
||||||
borderRadius={'md'}
|
borderRadius={'md'}
|
||||||
@@ -317,7 +316,11 @@ const CollectionCard = () => {
|
|||||||
{
|
{
|
||||||
label: (
|
label: (
|
||||||
<Flex alignItems={'center'}>
|
<Flex alignItems={'center'}>
|
||||||
<MyIcon name={'common/refreshLight'} w={'14px'} mr={2} />
|
<MyIcon
|
||||||
|
name={'common/refreshLight'}
|
||||||
|
w={'0.9rem'}
|
||||||
|
mr={2}
|
||||||
|
/>
|
||||||
{t('common:core.dataset.collection.Sync')}
|
{t('common:core.dataset.collection.Sync')}
|
||||||
</Flex>
|
</Flex>
|
||||||
),
|
),
|
||||||
@@ -331,7 +334,7 @@ const CollectionCard = () => {
|
|||||||
{
|
{
|
||||||
label: (
|
label: (
|
||||||
<Flex alignItems={'center'}>
|
<Flex alignItems={'center'}>
|
||||||
<MyIcon name={'common/file/move'} w={'14px'} mr={2} />
|
<MyIcon name={'common/file/move'} w={'0.9rem'} mr={2} />
|
||||||
{t('common:Move')}
|
{t('common:Move')}
|
||||||
</Flex>
|
</Flex>
|
||||||
),
|
),
|
||||||
@@ -341,7 +344,7 @@ const CollectionCard = () => {
|
|||||||
{
|
{
|
||||||
label: (
|
label: (
|
||||||
<Flex alignItems={'center'}>
|
<Flex alignItems={'center'}>
|
||||||
<MyIcon name={'edit'} w={'14px'} mr={2} />
|
<MyIcon name={'edit'} w={'0.9rem'} mr={2} />
|
||||||
{t('common:Rename')}
|
{t('common:Rename')}
|
||||||
</Flex>
|
</Flex>
|
||||||
),
|
),
|
||||||
@@ -365,7 +368,7 @@ const CollectionCard = () => {
|
|||||||
<MyIcon
|
<MyIcon
|
||||||
mr={1}
|
mr={1}
|
||||||
name={'delete'}
|
name={'delete'}
|
||||||
w={'14px'}
|
w={'0.9rem'}
|
||||||
_hover={{ color: 'red.600' }}
|
_hover={{ color: 'red.600' }}
|
||||||
/>
|
/>
|
||||||
<Box>{t('common:common.Delete')}</Box>
|
<Box>{t('common:common.Delete')}</Box>
|
||||||
|
@@ -47,7 +47,7 @@ import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
|||||||
import TagsPopOver from './CollectionCard/TagsPopOver';
|
import TagsPopOver from './CollectionCard/TagsPopOver';
|
||||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||||
import MyDivider from '@fastgpt/web/components/common/MyDivider';
|
import MyDivider from '@fastgpt/web/components/common/MyDivider';
|
||||||
import index from '../../../index';
|
import Markdown from '@/components/Markdown';
|
||||||
|
|
||||||
const DataCard = () => {
|
const DataCard = () => {
|
||||||
const BoxRef = useRef<HTMLDivElement>(null);
|
const BoxRef = useRef<HTMLDivElement>(null);
|
||||||
@@ -232,6 +232,7 @@ const DataCard = () => {
|
|||||||
setEditDataId(item._id);
|
setEditDataId(item._id);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{/* Data tag */}
|
||||||
<Flex
|
<Flex
|
||||||
position={'absolute'}
|
position={'absolute'}
|
||||||
zIndex={1}
|
zIndex={1}
|
||||||
@@ -259,118 +260,82 @@ const DataCard = () => {
|
|||||||
ID:{item._id}
|
ID:{item._id}
|
||||||
</Box>
|
</Box>
|
||||||
</MyTag>
|
</MyTag>
|
||||||
|
|
||||||
{/* {item.forbid ? (
|
|
||||||
<MyTag colorSchema="gray" bg={'transparent'} px={1} showDot>
|
|
||||||
{datasetT('Disabled')}
|
|
||||||
</MyTag>
|
|
||||||
) : (
|
|
||||||
<MyTag colorSchema="green" bg={'transparent'} px={1} showDot>
|
|
||||||
{datasetT('Enabled')}
|
|
||||||
</MyTag>
|
|
||||||
)}
|
|
||||||
<HStack
|
|
||||||
borderLeftWidth={'1.5px'}
|
|
||||||
className="forbid-switch"
|
|
||||||
display={['flex', 'none']}
|
|
||||||
borderLeftColor={'myGray.200'}
|
|
||||||
pl={1}
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
}}
|
|
||||||
h={'12px'}
|
|
||||||
>
|
|
||||||
<Switch
|
|
||||||
size={'sm'}
|
|
||||||
isChecked={!item.forbid}
|
|
||||||
onChange={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
onUpdate({
|
|
||||||
dataId: item._id,
|
|
||||||
forbid: !e.target.checked
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</HStack> */}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
<Box
|
|
||||||
maxH={'135px'}
|
|
||||||
minH={'90px'}
|
|
||||||
overflow={'hidden'}
|
|
||||||
wordBreak={'break-all'}
|
|
||||||
pt={1}
|
|
||||||
pb={3}
|
|
||||||
fontSize={'sm'}
|
|
||||||
>
|
|
||||||
<Box color={'black'} mb={1}>
|
|
||||||
{item.q}
|
|
||||||
</Box>
|
|
||||||
<Box color={'myGray.700'}>{item.a}</Box>
|
|
||||||
|
|
||||||
{/* Mask */}
|
{/* Data content */}
|
||||||
|
<Box wordBreak={'break-all'} fontSize={'sm'}>
|
||||||
|
<Markdown source={item.q} forbidImgPreview />
|
||||||
|
{!!item.a && (
|
||||||
|
<>
|
||||||
|
<MyDivider />
|
||||||
|
<Markdown source={item.a} forbidImgPreview />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Mask */}
|
||||||
|
<Flex
|
||||||
|
className="footer"
|
||||||
|
position={'absolute'}
|
||||||
|
bottom={2}
|
||||||
|
right={2}
|
||||||
|
overflow={'hidden'}
|
||||||
|
alignItems={'flex-end'}
|
||||||
|
visibility={'hidden'}
|
||||||
|
fontSize={'mini'}
|
||||||
|
>
|
||||||
<Flex
|
<Flex
|
||||||
className="footer"
|
alignItems={'center'}
|
||||||
position={'absolute'}
|
bg={'white'}
|
||||||
bottom={2}
|
color={'myGray.600'}
|
||||||
right={2}
|
borderRadius={'sm'}
|
||||||
overflow={'hidden'}
|
border={'1px'}
|
||||||
alignItems={'flex-end'}
|
borderColor={'myGray.200'}
|
||||||
visibility={'hidden'}
|
h={'24px'}
|
||||||
|
px={2}
|
||||||
fontSize={'mini'}
|
fontSize={'mini'}
|
||||||
|
boxShadow={'1'}
|
||||||
|
py={1}
|
||||||
|
mr={2}
|
||||||
>
|
>
|
||||||
<Flex
|
<MyIcon
|
||||||
alignItems={'center'}
|
|
||||||
bg={'white'}
|
bg={'white'}
|
||||||
color={'myGray.600'}
|
color={'myGray.600'}
|
||||||
borderRadius={'sm'}
|
borderRadius={'sm'}
|
||||||
border={'1px'}
|
border={'1px'}
|
||||||
borderColor={'myGray.200'}
|
borderColor={'myGray.200'}
|
||||||
h={'24px'}
|
name="common/text/t"
|
||||||
px={2}
|
w={'14px'}
|
||||||
fontSize={'mini'}
|
mr={1}
|
||||||
boxShadow={'1'}
|
/>
|
||||||
py={1}
|
{item.q.length + (item.a?.length || 0)}
|
||||||
mr={2}
|
|
||||||
>
|
|
||||||
<MyIcon
|
|
||||||
bg={'white'}
|
|
||||||
color={'myGray.600'}
|
|
||||||
borderRadius={'sm'}
|
|
||||||
border={'1px'}
|
|
||||||
borderColor={'myGray.200'}
|
|
||||||
name="common/text/t"
|
|
||||||
w={'14px'}
|
|
||||||
mr={1}
|
|
||||||
/>
|
|
||||||
{item.q.length + (item.a?.length || 0)}
|
|
||||||
</Flex>
|
|
||||||
{canWrite && (
|
|
||||||
<IconButton
|
|
||||||
display={'flex'}
|
|
||||||
p={1}
|
|
||||||
boxShadow={'1'}
|
|
||||||
icon={<MyIcon name={'common/trash'} w={'14px'} color={'myGray.600'} />}
|
|
||||||
variant={'whiteDanger'}
|
|
||||||
size={'xsSquare'}
|
|
||||||
aria-label={'delete'}
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
openConfirm(async () => {
|
|
||||||
try {
|
|
||||||
await delOneDatasetDataById(item._id);
|
|
||||||
getData(pageNum);
|
|
||||||
} catch (error) {
|
|
||||||
toast({
|
|
||||||
title: getErrText(error),
|
|
||||||
status: 'error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
{canWrite && (
|
||||||
|
<IconButton
|
||||||
|
display={'flex'}
|
||||||
|
p={1}
|
||||||
|
boxShadow={'1'}
|
||||||
|
icon={<MyIcon name={'common/trash'} w={'14px'} />}
|
||||||
|
variant={'whiteDanger'}
|
||||||
|
size={'xsSquare'}
|
||||||
|
aria-label={'delete'}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
openConfirm(async () => {
|
||||||
|
try {
|
||||||
|
await delOneDatasetDataById(item._id);
|
||||||
|
getData(pageNum);
|
||||||
|
} catch (error) {
|
||||||
|
toast({
|
||||||
|
title: getErrText(error),
|
||||||
|
status: 'error'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
))}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { Box, Flex, Button, IconButton, Input, Textarea, HStack } from '@chakra-ui/react';
|
import { Box, Flex, Input } from '@chakra-ui/react';
|
||||||
import { DeleteIcon } from '@chakra-ui/icons';
|
|
||||||
import { delDatasetById } from '@/web/core/dataset/api';
|
import { delDatasetById } from '@/web/core/dataset/api';
|
||||||
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
|
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
|
||||||
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
||||||
@@ -9,7 +8,6 @@ import { useForm } from 'react-hook-form';
|
|||||||
import { compressImgFileAndUpload } from '@/web/common/file/controller';
|
import { compressImgFileAndUpload } from '@/web/common/file/controller';
|
||||||
import type { DatasetItemType } from '@fastgpt/global/core/dataset/type.d';
|
import type { DatasetItemType } from '@fastgpt/global/core/dataset/type.d';
|
||||||
import Avatar from '@fastgpt/web/components/common/Avatar';
|
import Avatar from '@fastgpt/web/components/common/Avatar';
|
||||||
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
|
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||||
import { useRequest, useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
import { useRequest, useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||||
@@ -56,7 +54,6 @@ const Info = ({ datasetId }: { datasetId: string }) => {
|
|||||||
defaultValues: datasetDetail
|
defaultValues: datasetDetail
|
||||||
});
|
});
|
||||||
|
|
||||||
const avatar = watch('avatar');
|
|
||||||
const vectorModel = watch('vectorModel');
|
const vectorModel = watch('vectorModel');
|
||||||
const agentModel = watch('agentModel');
|
const agentModel = watch('agentModel');
|
||||||
const defaultPermission = watch('defaultPermission');
|
const defaultPermission = watch('defaultPermission');
|
||||||
@@ -77,8 +74,20 @@ const Info = ({ datasetId }: { datasetId: string }) => {
|
|||||||
multiple: false
|
multiple: false
|
||||||
});
|
});
|
||||||
|
|
||||||
const { mutate: onSave, isLoading: isSaving } = useRequest({
|
/* 点击删除 */
|
||||||
mutationFn: (data: DatasetItemType) => {
|
const { mutate: onclickDelete, isLoading: isDeleting } = useRequest({
|
||||||
|
mutationFn: () => {
|
||||||
|
return delDatasetById(datasetId);
|
||||||
|
},
|
||||||
|
onSuccess() {
|
||||||
|
router.replace(`/dataset/list`);
|
||||||
|
},
|
||||||
|
successToast: t('common:common.Delete Success'),
|
||||||
|
errorToast: t('common:common.Delete Failed')
|
||||||
|
});
|
||||||
|
|
||||||
|
const { runAsync: onSave, loading: isSaving } = useRequest2(
|
||||||
|
(data: DatasetItemType) => {
|
||||||
return updateDataset({
|
return updateDataset({
|
||||||
id: datasetId,
|
id: datasetId,
|
||||||
agentModel: data.agentModel,
|
agentModel: data.agentModel,
|
||||||
@@ -86,12 +95,14 @@ const Info = ({ datasetId }: { datasetId: string }) => {
|
|||||||
defaultPermission: data.defaultPermission
|
defaultPermission: data.defaultPermission
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
successToast: t('common:common.Update Success'),
|
{
|
||||||
errorToast: t('common:common.Update Failed')
|
successToast: t('common:common.Update Success'),
|
||||||
});
|
errorToast: t('common:common.Update Failed')
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const { mutate: onSelectFile, isLoading: isSelecting } = useRequest({
|
const { runAsync: onSelectFile, loading: isSelecting } = useRequest2(
|
||||||
mutationFn: (e: File[]) => {
|
(e: File[]) => {
|
||||||
const file = e[0];
|
const file = e[0];
|
||||||
if (!file) return Promise.resolve(null);
|
if (!file) return Promise.resolve(null);
|
||||||
return compressImgFileAndUpload({
|
return compressImgFileAndUpload({
|
||||||
@@ -101,37 +112,41 @@ const Info = ({ datasetId }: { datasetId: string }) => {
|
|||||||
maxH: 300
|
maxH: 300
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onSuccess(src: string | null) {
|
{
|
||||||
if (src) {
|
onSuccess(src: string | null) {
|
||||||
setValue('avatar', src);
|
if (src) {
|
||||||
}
|
setValue('avatar', src);
|
||||||
},
|
}
|
||||||
errorToast: t('common:common.avatar.Select Failed')
|
},
|
||||||
});
|
errorToast: t('common:common.avatar.Select Failed')
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const { mutate: onRebuilding, isLoading: isRebuilding } = useRequest({
|
const { runAsync: onRebuilding, loading: isRebuilding } = useRequest2(
|
||||||
mutationFn: (vectorModel: VectorModelItemType) => {
|
(vectorModel: VectorModelItemType) => {
|
||||||
return postRebuildEmbedding({
|
return postRebuildEmbedding({
|
||||||
datasetId,
|
datasetId,
|
||||||
vectorModel: vectorModel.model
|
vectorModel: vectorModel.model
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onSuccess() {
|
{
|
||||||
refetchDatasetTraining();
|
onSuccess() {
|
||||||
loadDatasetDetail(datasetId);
|
refetchDatasetTraining();
|
||||||
},
|
loadDatasetDetail(datasetId);
|
||||||
successToast: t('dataset:rebuild_embedding_start_tip'),
|
},
|
||||||
errorToast: t('common:common.Update Failed')
|
successToast: t('dataset:rebuild_embedding_start_tip'),
|
||||||
});
|
errorToast: t('common:common.Update Failed')
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const { runAsync: onEditBaseInfo } = useRequest2((data) => updateDataset(data), {
|
const { runAsync: onEditBaseInfo } = useRequest2(updateDataset, {
|
||||||
manual: true,
|
onSuccess() {
|
||||||
|
setEditedDataset(undefined);
|
||||||
|
},
|
||||||
successToast: t('common:common.Update Success'),
|
successToast: t('common:common.Update Success'),
|
||||||
errorToast: t('common:common.Update Failed')
|
errorToast: t('common:common.Update Failed')
|
||||||
});
|
});
|
||||||
|
|
||||||
const totalLoading = isSelecting || isSaving || isRebuilding;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box w={'100%'} h={'100%'} p={6}>
|
<Box w={'100%'} h={'100%'} p={6}>
|
||||||
<Box>
|
<Box>
|
||||||
@@ -225,7 +240,7 @@ const Info = ({ datasetId }: { datasetId: string }) => {
|
|||||||
if (!vectorModel) return;
|
if (!vectorModel) return;
|
||||||
return onOpenConfirmRebuild(() => {
|
return onOpenConfirmRebuild(() => {
|
||||||
setValue('vectorModel', vectorModel);
|
setValue('vectorModel', vectorModel);
|
||||||
onRebuilding(vectorModel);
|
return onRebuilding(vectorModel);
|
||||||
})();
|
})();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -260,7 +275,6 @@ const Info = ({ datasetId }: { datasetId: string }) => {
|
|||||||
setValue('agentModel', agentModel);
|
setValue('agentModel', agentModel);
|
||||||
return handleSubmit((data) => onSave({ ...data, agentModel: agentModel }))();
|
return handleSubmit((data) => onSave({ ...data, agentModel: agentModel }))();
|
||||||
}}
|
}}
|
||||||
isDisabled={totalLoading}
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -311,7 +325,6 @@ const Info = ({ datasetId }: { datasetId: string }) => {
|
|||||||
fontSize={'mini'}
|
fontSize={'mini'}
|
||||||
per={defaultPermission}
|
per={defaultPermission}
|
||||||
defaultPer={DatasetDefaultPermissionVal}
|
defaultPer={DatasetDefaultPermissionVal}
|
||||||
isDisabled={totalLoading}
|
|
||||||
onChange={(v) => {
|
onChange={(v) => {
|
||||||
setValue('defaultPermission', v);
|
setValue('defaultPermission', v);
|
||||||
return handleSubmit((data) => onSave({ ...data, defaultPermission: v }))();
|
return handleSubmit((data) => onSave({ ...data, defaultPermission: v }))();
|
||||||
@@ -349,18 +362,15 @@ const Info = ({ datasetId }: { datasetId: string }) => {
|
|||||||
<EditResourceModal
|
<EditResourceModal
|
||||||
{...editedDataset}
|
{...editedDataset}
|
||||||
title={t('common:dataset.Edit Info')}
|
title={t('common:dataset.Edit Info')}
|
||||||
onClose={() => {
|
onClose={() => setEditedDataset(undefined)}
|
||||||
setEditedDataset(undefined);
|
onEdit={(data) =>
|
||||||
}}
|
onEditBaseInfo({
|
||||||
onEdit={async (data) => {
|
|
||||||
await onEditBaseInfo({
|
|
||||||
id: editedDataset.id,
|
id: editedDataset.id,
|
||||||
name: data.name,
|
name: data.name,
|
||||||
intro: data.intro,
|
intro: data.intro,
|
||||||
avatar: data.avatar
|
avatar: data.avatar
|
||||||
});
|
})
|
||||||
setEditedDataset(undefined);
|
}
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
@@ -115,7 +115,7 @@ const NavBar = ({ currentTab }: { currentTab: TabEnum }) => {
|
|||||||
w={'100%'}
|
w={'100%'}
|
||||||
list={tabList}
|
list={tabList}
|
||||||
value={currentTab}
|
value={currentTab}
|
||||||
activatedColor="blue.700"
|
activeColor="primary.700"
|
||||||
onChange={setCurrentTab}
|
onChange={setCurrentTab}
|
||||||
inlineStyles={{
|
inlineStyles={{
|
||||||
fontSize: '1rem',
|
fontSize: '1rem',
|
||||||
@@ -193,7 +193,7 @@ const NavBar = ({ currentTab }: { currentTab: TabEnum }) => {
|
|||||||
</MyPopover>
|
</MyPopover>
|
||||||
</Flex>
|
</Flex>
|
||||||
) : (
|
) : (
|
||||||
<Box mb={3}>
|
<Box mb={2}>
|
||||||
<LightRowTabs<TabEnum>
|
<LightRowTabs<TabEnum>
|
||||||
m={'auto'}
|
m={'auto'}
|
||||||
w={'full'}
|
w={'full'}
|
||||||
|
@@ -4,7 +4,7 @@ import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
|||||||
import { useSearchTestStore, SearchTestStoreItemType } from '@/web/core/dataset/store/searchTest';
|
import { useSearchTestStore, SearchTestStoreItemType } from '@/web/core/dataset/store/searchTest';
|
||||||
import { postSearchText } from '@/web/core/dataset/api';
|
import { postSearchText } from '@/web/core/dataset/api';
|
||||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||||
import { useRequest } from '@fastgpt/web/hooks/useRequest';
|
import { useRequest, useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||||
import { formatTimeToChatTime } from '@fastgpt/global/common/string/time';
|
import { formatTimeToChatTime } from '@fastgpt/global/common/string/time';
|
||||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||||
@@ -48,7 +48,6 @@ type FormType = {
|
|||||||
|
|
||||||
const Test = ({ datasetId }: { datasetId: string }) => {
|
const Test = ({ datasetId }: { datasetId: string }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const theme = useTheme();
|
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { llmModelList } = useSystemStore();
|
const { llmModelList } = useSystemStore();
|
||||||
const datasetDetail = useContextSelector(DatasetPageContext, (v) => v.datasetDetail);
|
const datasetDetail = useContextSelector(DatasetPageContext, (v) => v.datasetDetail);
|
||||||
@@ -86,40 +85,42 @@ const Test = ({ datasetId }: { datasetId: string }) => {
|
|||||||
onClose: onCloseSelectMode
|
onClose: onCloseSelectMode
|
||||||
} = useDisclosure();
|
} = useDisclosure();
|
||||||
|
|
||||||
const { mutate: onTextTest, isLoading: textTestIsLoading } = useRequest({
|
const { runAsync: onTextTest, loading: textTestIsLoading } = useRequest2(
|
||||||
mutationFn: ({ inputText, searchParams }: FormType) =>
|
({ inputText, searchParams }: FormType) =>
|
||||||
postSearchText({ datasetId, text: inputText.trim(), ...searchParams }),
|
postSearchText({ datasetId, text: inputText.trim(), ...searchParams }),
|
||||||
onSuccess(res: SearchTestResponse) {
|
{
|
||||||
if (!res || res.list.length === 0) {
|
onSuccess(res: SearchTestResponse) {
|
||||||
return toast({
|
if (!res || res.list.length === 0) {
|
||||||
status: 'warning',
|
return toast({
|
||||||
title: t('common:dataset.test.noResult')
|
status: 'warning',
|
||||||
|
title: t('common:dataset.test.noResult')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const testItem: SearchTestStoreItemType = {
|
||||||
|
id: nanoid(),
|
||||||
|
datasetId,
|
||||||
|
text: getValues('inputText').trim(),
|
||||||
|
time: new Date(),
|
||||||
|
results: res.list,
|
||||||
|
duration: res.duration,
|
||||||
|
searchMode: res.searchMode,
|
||||||
|
usingReRank: res.usingReRank,
|
||||||
|
limit: res.limit,
|
||||||
|
similarity: res.similarity,
|
||||||
|
queryExtensionModel: res.queryExtensionModel
|
||||||
|
};
|
||||||
|
pushDatasetTestItem(testItem);
|
||||||
|
setDatasetTestItem(testItem);
|
||||||
|
},
|
||||||
|
onError(err) {
|
||||||
|
toast({
|
||||||
|
title: getErrText(err),
|
||||||
|
status: 'error'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const testItem: SearchTestStoreItemType = {
|
|
||||||
id: nanoid(),
|
|
||||||
datasetId,
|
|
||||||
text: getValues('inputText').trim(),
|
|
||||||
time: new Date(),
|
|
||||||
results: res.list,
|
|
||||||
duration: res.duration,
|
|
||||||
searchMode: res.searchMode,
|
|
||||||
usingReRank: res.usingReRank,
|
|
||||||
limit: res.limit,
|
|
||||||
similarity: res.similarity,
|
|
||||||
queryExtensionModel: res.queryExtensionModel
|
|
||||||
};
|
|
||||||
pushDatasetTestItem(testItem);
|
|
||||||
setDatasetTestItem(testItem);
|
|
||||||
},
|
|
||||||
onError(err) {
|
|
||||||
toast({
|
|
||||||
title: getErrText(err),
|
|
||||||
status: 'error'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
const onSelectFile = async (files: File[]) => {
|
const onSelectFile = async (files: File[]) => {
|
||||||
const file = files[0];
|
const file = files[0];
|
||||||
@@ -329,6 +330,7 @@ const TestHistories = React.memo(function TestHistories({
|
|||||||
() => datasetTestList.filter((item) => item.datasetId === datasetId),
|
() => datasetTestList.filter((item) => item.datasetId === datasetId),
|
||||||
[datasetId, datasetTestList]
|
[datasetId, datasetTestList]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Flex alignItems={'center'} color={'myGray.900'}>
|
<Flex alignItems={'center'} color={'myGray.900'}>
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { Box, Flex } from '@chakra-ui/react';
|
import { Box, Flex, FlexProps } from '@chakra-ui/react';
|
||||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
|
||||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import PageContainer from '@/components/PageContainer';
|
import PageContainer from '@/components/PageContainer';
|
||||||
@@ -36,6 +35,13 @@ export enum TabEnum {
|
|||||||
}
|
}
|
||||||
type Props = { datasetId: string; currentTab: TabEnum };
|
type Props = { datasetId: string; currentTab: TabEnum };
|
||||||
|
|
||||||
|
const sliderStyles: FlexProps = {
|
||||||
|
bg: 'white',
|
||||||
|
borderRadius: 'md',
|
||||||
|
overflowY: 'scroll',
|
||||||
|
boxShadow: 2
|
||||||
|
};
|
||||||
|
|
||||||
const Detail = ({ datasetId, currentTab }: Props) => {
|
const Detail = ({ datasetId, currentTab }: Props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
@@ -64,20 +70,10 @@ const Detail = ({ datasetId, currentTab }: Props) => {
|
|||||||
<NextHead title={datasetDetail?.name} icon={datasetDetail?.avatar} />
|
<NextHead title={datasetDetail?.name} icon={datasetDetail?.avatar} />
|
||||||
|
|
||||||
{isPc ? (
|
{isPc ? (
|
||||||
<Flex h={'100%'} w={'100%'}>
|
<Flex h={'100%'} py={3} pl={1} pr={3} gap={2}>
|
||||||
<Flex
|
<Flex flex={1} w={0} bg={'white'} flexDir={'column'} boxShadow={'2'} borderRadius={'md'}>
|
||||||
flexGrow={1}
|
|
||||||
flex={81}
|
|
||||||
bg={'white'}
|
|
||||||
w={'100%'}
|
|
||||||
flexDir={'column'}
|
|
||||||
my={3}
|
|
||||||
mr={2}
|
|
||||||
boxShadow={'2'}
|
|
||||||
borderRadius={'md'}
|
|
||||||
>
|
|
||||||
{currentTab !== TabEnum.import && <NavBar currentTab={currentTab} />}
|
{currentTab !== TabEnum.import && <NavBar currentTab={currentTab} />}
|
||||||
<Box flex={'1 0 0'} w={'100%'} overflow={'auto'}>
|
<Box flex={'1'} overflow={'auto'}>
|
||||||
{currentTab === TabEnum.collectionCard && (
|
{currentTab === TabEnum.collectionCard && (
|
||||||
<CollectionPageContextProvider>
|
<CollectionPageContextProvider>
|
||||||
<CollectionCard />
|
<CollectionCard />
|
||||||
@@ -88,27 +84,24 @@ const Detail = ({ datasetId, currentTab }: Props) => {
|
|||||||
{currentTab === TabEnum.import && <Import />}
|
{currentTab === TabEnum.import && <Import />}
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
{currentTab !== TabEnum.import && (
|
|
||||||
<Flex
|
{/* Slider */}
|
||||||
bg={'white'}
|
<>
|
||||||
borderRadius={'md'}
|
{currentTab === TabEnum.dataCard && (
|
||||||
overflowY={'scroll'}
|
<Flex {...sliderStyles} flex={'0 0 20rem'}>
|
||||||
boxShadow={'2'}
|
|
||||||
my={3}
|
|
||||||
mr={3}
|
|
||||||
flex={19}
|
|
||||||
>
|
|
||||||
{currentTab === TabEnum.dataCard ? (
|
|
||||||
<MetaDataCard datasetId={datasetId} />
|
<MetaDataCard datasetId={datasetId} />
|
||||||
) : (
|
</Flex>
|
||||||
|
)}
|
||||||
|
{[TabEnum.collectionCard, TabEnum.test].includes(currentTab) && (
|
||||||
|
<Flex {...sliderStyles} flex={'0 0 17rem'}>
|
||||||
<Info datasetId={datasetId} />
|
<Info datasetId={datasetId} />
|
||||||
)}
|
</Flex>
|
||||||
</Flex>
|
)}
|
||||||
)}
|
</>
|
||||||
</Flex>
|
</Flex>
|
||||||
) : (
|
) : (
|
||||||
<PageContainer insertProps={{ bg: 'white' }}>
|
<PageContainer insertProps={{ bg: 'white' }}>
|
||||||
<MyBox display={'flex'} flexDirection={['column', 'row']} h={'100%'} pt={[4, 0]}>
|
<MyBox display={'flex'} flexDirection={'column'} h={'100%'} pt={1}>
|
||||||
<NavBar currentTab={currentTab} />
|
<NavBar currentTab={currentTab} />
|
||||||
|
|
||||||
{!!datasetDetail._id && (
|
{!!datasetDetail._id && (
|
||||||
|
@@ -120,7 +120,7 @@ export const putDatasetCollectionById = (data: UpdateDatasetCollectionParams) =>
|
|||||||
export const delDatasetCollectionById = (params: { id: string }) =>
|
export const delDatasetCollectionById = (params: { id: string }) =>
|
||||||
DELETE(`/core/dataset/collection/delete`, params);
|
DELETE(`/core/dataset/collection/delete`, params);
|
||||||
export const postLinkCollectionSync = (collectionId: string) =>
|
export const postLinkCollectionSync = (collectionId: string) =>
|
||||||
POST<`${DatasetCollectionSyncResultEnum}`>(`/core/dataset/collection/sync/link`, {
|
POST<DatasetCollectionSyncResultEnum>(`/core/dataset/collection/sync/link`, {
|
||||||
collectionId
|
collectionId
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user