fix: favorite apps ui and permission; fix favorite settings' table row (#5553)

* fix: fix favorite apps ui and permission; fix favorite settings' table row

* fix: tag overflow

* chore: remove default value
This commit is contained in:
伍闲犬
2025-09-01 11:32:37 +08:00
committed by GitHub
parent 42e249f30f
commit 6e8bf8c804
7 changed files with 79 additions and 55 deletions

View File

@@ -29,10 +29,15 @@ import ChatSliderMobileDrawer from '@/pageComponents/chat/slider/ChatSliderMobil
import { useSystem } from '@fastgpt/web/hooks/useSystem'; import { useSystem } from '@fastgpt/web/hooks/useSystem';
import { ChatContext } from '@/web/core/chat/context/chatContext'; import { ChatContext } from '@/web/core/chat/context/chatContext';
import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { getWebReqUrl } from '@fastgpt/web/common/system/utils';
import { useUserStore } from '@/web/support/user/useUserStore';
const ChatFavouriteApp = () => { const ChatFavouriteApp = () => {
const { isPc } = useSystem(); const { isPc } = useSystem();
const { t } = useTranslation(); const { t } = useTranslation();
const { feConfigs } = useSystemStore();
const { userInfo } = useUserStore();
const onOpenSlider = useContextSelector(ChatContext, (v) => v.onOpenSlider); const onOpenSlider = useContextSelector(ChatContext, (v) => v.onOpenSlider);
@@ -91,24 +96,26 @@ const ChatFavouriteApp = () => {
if (!tag) return null; if (!tag) return null;
return ( return (
<Box <Flex
key={id} key={id}
fontSize="xs" fontSize="xs"
borderRadius={8} borderRadius="sm"
bg="myGray.100" bg="myGray.100"
px="1.5" px="1.5"
py="0.5" py="0.5"
cursor="text" cursor="text"
minW="40px"
justifyContent="center"
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >
{tag.name} {tag.name}
</Box> </Flex>
); );
}; };
return ( return (
<MyBox isLoading={isSearching} display="flex" flexDirection={'column'} h={'100%'}> <MyBox isLoading={isSearching} display="flex" flexDirection={'column'} h={'100%'}>
<NextHead title={homeTabTitle || 'FastGPT'} icon="/icon/logo.svg" /> <NextHead title={homeTabTitle} icon={getWebReqUrl(feConfigs?.favicon)} />
{!isPc && ( {!isPc && (
<Flex <Flex
@@ -206,30 +213,31 @@ const ChatFavouriteApp = () => {
<GridItem key={app.appId} cursor="pointer"> <GridItem key={app.appId} cursor="pointer">
<Flex <Flex
flexDirection={'column'} flexDirection={'column'}
justifyContent="space-between" justifyContent="flex-start"
gap={2} gap={2}
p={4} p={4}
borderRadius={8} borderRadius={8}
border="sm" border="sm"
borderColor="myGray.200" borderColor="myGray.200"
boxShadow="sm" boxShadow="sm"
minH="140px" bg="white"
h="160px"
transition="all 0.1s ease-in-out" transition="all 0.1s ease-in-out"
_hover={{ _hover={{
borderColor: 'primary.300' borderColor: 'primary.300'
}} }}
onClick={() => handlePaneChange(ChatSidebarPaneEnum.RECENTLY_USED_APPS, app.appId)} onClick={() => handlePaneChange(ChatSidebarPaneEnum.RECENTLY_USED_APPS, app.appId)}
> >
<Box> <Flex fontSize="16px" fontWeight="500" alignItems="center" gap={2}>
<Flex fontSize="16px" fontWeight="500" alignItems="center" gap={2}> <Avatar src={app.avatar} borderRadius={8} />
<Avatar src={app.avatar} borderRadius={8} /> <Flex>{app.name}</Flex>
<Flex>{app.name}</Flex> </Flex>
</Flex>
<Box fontSize="sm">{app.intro}</Box> <Box fontSize="xs" color="myGray.500" minH="0" noOfLines={2} overflow="hidden">
{app.intro || t('common:no_intro')}
</Box> </Box>
<Flex gap="2" flexWrap="wrap"> <Flex gap="2" flexWrap="wrap" mt="auto">
{app.favouriteTags.slice(0, 3).map((id) => ( {app.favouriteTags.slice(0, 3).map((id) => (
<TagBox key={id} id={id} /> <TagBox key={id} id={id} />
))} ))}
@@ -276,19 +284,21 @@ const ChatFavouriteApp = () => {
<Flex flexDir="column" flex="1" justifyContent="center" alignItems="center" gap={4}> <Flex flexDir="column" flex="1" justifyContent="center" alignItems="center" gap={4}>
<EmptyTip p="0" text={t('chat:setting.favourite.category.no_data')} /> <EmptyTip p="0" text={t('chat:setting.favourite.category.no_data')} />
<Button {userInfo?.permission.hasManagePer && (
variant="primary" <Button
leftIcon={<MyIcon name="common/settingLight" w="16px" />} variant="primary"
onClick={() => leftIcon={<MyIcon name="common/settingLight" w="16px" />}
handlePaneChange( onClick={() =>
ChatSidebarPaneEnum.SETTING, handlePaneChange(
undefined, ChatSidebarPaneEnum.SETTING,
ChatSettingTabOptionEnum.FAVOURITE_APPS undefined,
) ChatSettingTabOptionEnum.FAVOURITE_APPS
} )
> }
{t('chat:setting.favourite.goto_add')} >
</Button> {t('chat:setting.favourite.goto_add')}
</Button>
)}
</Flex> </Flex>
)} )}
</MyBox> </MyBox>

View File

@@ -129,9 +129,9 @@ const EditableTagItem = React.memo(function EditableTagItem({
}} }}
/> />
) : ( ) : (
<Box px="1.5" py="0.5" bg="myGray.200" rounded="xs"> <Flex px="1.5" py="0.5" bg="myGray.200" rounded="xs" minW="40px" justifyContent="center">
{tag.name} {tag.name}
</Box> </Flex>
)} )}
<Box userSelect="none">({appCount ?? 0})</Box> <Box userSelect="none">({appCount ?? 0})</Box>
</Flex> </Flex>
@@ -286,9 +286,9 @@ const SaveTagForAppSubPanel = ({
/> />
<Flex alignItems="center" gap="1"> <Flex alignItems="center" gap="1">
<Box bg="myGray.100" rounded="sm" p="1" minW="30px" textAlign="center"> <Flex bg="myGray.100" rounded="sm" p="1" minW="30px" justifyContent="center">
{tag.name} {tag.name}
</Box> </Flex>
<Box>({checkedAppIds.length})</Box> <Box>({checkedAppIds.length})</Box>
</Flex> </Flex>
</Flex> </Flex>

View File

@@ -148,18 +148,22 @@ const FavouriteAppSetting = ({ Header }: Props) => {
if (!tag) return null; if (!tag) return null;
return ( return (
<Box <Flex
maxW="full"
key={id} key={id}
fontSize="xs" fontSize="xs"
borderRadius={8} borderRadius="sm"
bg="myGray.100" bg="myGray.100"
px="1.5" px="1.5"
py="0.5" py="0.5"
noOfLines={1}
cursor="text" cursor="text"
minW="40px"
justifyContent="center"
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >
{tag.name} {tag.name}
</Box> </Flex>
); );
}; };
@@ -264,23 +268,23 @@ const FavouriteAppSetting = ({ Header }: Props) => {
</Td> </Td>
{/* name */} {/* name */}
<Td> <Td w="0">
<HStack spacing={2} maxW="520px"> <HStack spacing={2} w="200px">
<Avatar src={row.avatar} borderRadius={'sm'} w="20px" /> <Avatar src={row.avatar} borderRadius={'sm'} w="20px" />
<Flex className="textEllipsis">{row.name || ''}</Flex> <Flex className="textEllipsis">{row.name || ''}</Flex>
</HStack> </HStack>
</Td> </Td>
{/* intro */} {/* intro */}
<Td maxW="520px"> <Td w="0">
<Flex className="textEllipsis" color={'myGray.600'}> <Box noOfLines={1} color={'myGray.600'} w="500px">
{row.intro || ''} {row.intro || ''}
</Flex> </Box>
</Td> </Td>
{/* tags */} {/* tags */}
<Td> <Td w="0">
<Wrap> <Wrap w="200px">
{row.favouriteTags.slice(0, 3).map((id) => ( {row.favouriteTags.slice(0, 3).map((id) => (
<TagBox key={id} id={id} /> <TagBox key={id} id={id} />
))} ))}
@@ -293,11 +297,13 @@ const FavouriteAppSetting = ({ Header }: Props) => {
Trigger={ Trigger={
<Box <Box
fontSize="xs" fontSize="xs"
borderRadius={8} borderRadius="sm"
bg="myGray.100" bg="myGray.100"
px="1.5" px="1.5"
py="0.5" py="0.5"
cursor="pointer" cursor="pointer"
minW="40px"
textAlign="center"
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >
+{row.favouriteTags.length - 3} +{row.favouriteTags.length - 3}
@@ -323,7 +329,7 @@ const FavouriteAppSetting = ({ Header }: Props) => {
</Td> </Td>
{/* action */} {/* action */}
<Td p="0" textAlign="center"> <Td p="0" w="0" textAlign="center">
<PopoverConfirm <PopoverConfirm
type="delete" type="delete"
content={t('chat:setting.favourite.delete_app_confirm')} content={t('chat:setting.favourite.delete_app_confirm')}
@@ -340,13 +346,17 @@ const FavouriteAppSetting = ({ Header }: Props) => {
}); });
}} }}
Trigger={ Trigger={
<IconButton <Box w="158px">
size="sm" <IconButton
aria-label="delete" size="sm"
variant="grayGhost" aria-label="delete"
color="myGray.500" variant="grayGhost"
icon={<MyIcon name="common/trash" w="20px" color="myGray.400" />} color="myGray.500"
/> icon={
<MyIcon name="common/trash" w="20px" color="myGray.400" />
}
/>
</Box>
} }
/> />
</Td> </Td>

View File

@@ -16,6 +16,7 @@ import { useMount } from 'ahooks';
import { useSystemStore } from '@/web/common/system/useSystemStore'; import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { useUserStore } from '@/web/support/user/useUserStore'; import { useUserStore } from '@/web/support/user/useUserStore';
import { getWebReqUrl } from '@fastgpt/web/common/system/utils';
const HomepageSetting = dynamic(() => import('@/pageComponents/chat/ChatSetting/HomepageSetting')); const HomepageSetting = dynamic(() => import('@/pageComponents/chat/ChatSetting/HomepageSetting'));
const LogDetails = dynamic(() => import('@/pageComponents/chat/ChatSetting/LogDetails')); const LogDetails = dynamic(() => import('@/pageComponents/chat/ChatSetting/LogDetails'));
@@ -69,7 +70,7 @@ const ChatSetting = () => {
return ( return (
<> <>
<NextHead title={chatSettings?.homeTabTitle || 'FastGPT'} icon="/icon/logo.svg" /> <NextHead title={chatSettings?.homeTabTitle} icon={getWebReqUrl(feConfigs?.favicon)} />
<Flex flexDir="column" h="100%"> <Flex flexDir="column" h="100%">
{!isPc && ( {!isPc && (

View File

@@ -15,11 +15,14 @@ import { ChatContext } from '@/web/core/chat/context/chatContext';
import NextHead from '@/components/common/NextHead'; import NextHead from '@/components/common/NextHead';
import { ChatSettingContext } from '@/web/core/chat/context/chatSettingContext'; import { ChatSettingContext } from '@/web/core/chat/context/chatSettingContext';
import ChatSliderMobileDrawer from '@/pageComponents/chat/slider/ChatSliderMobileDrawer'; import ChatSliderMobileDrawer from '@/pageComponents/chat/slider/ChatSliderMobileDrawer';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { getWebReqUrl } from '@fastgpt/web/common/system/utils';
const MyApps = () => { const MyApps = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const router = useRouter(); const router = useRouter();
const { isPc } = useSystem(); const { isPc } = useSystem();
const { feConfigs } = useSystemStore();
const { paths, myApps, isFetchingApps, setSearchKey } = useContextSelector( const { paths, myApps, isFetchingApps, setSearchKey } = useContextSelector(
AppListContext, AppListContext,
@@ -51,7 +54,7 @@ const MyApps = () => {
return ( return (
<Flex flexDirection={'column'} h={'100%'}> <Flex flexDirection={'column'} h={'100%'}>
<NextHead title={chatSettings?.homeTabTitle || 'FastGPT'} icon="/icon/logo.svg" /> <NextHead title={chatSettings?.homeTabTitle} icon={getWebReqUrl(feConfigs?.favicon)} />
{!isPc && ( {!isPc && (
<Flex <Flex

View File

@@ -48,6 +48,7 @@ import { ChatSidebarPaneEnum } from '../constants';
import ChatHistorySidebar from '@/pageComponents/chat/slider/ChatSliderSidebar'; import ChatHistorySidebar from '@/pageComponents/chat/slider/ChatSliderSidebar';
import ChatSliderMobileDrawer from '@/pageComponents/chat/slider/ChatSliderMobileDrawer'; import ChatSliderMobileDrawer from '@/pageComponents/chat/slider/ChatSliderMobileDrawer';
import type { QuickAppType } from '@fastgpt/global/core/chat/setting/type'; import type { QuickAppType } from '@fastgpt/global/core/chat/setting/type';
import { getWebReqUrl } from '@fastgpt/web/common/system/utils';
type Props = { type Props = {
myApps: AppListItemType[]; myApps: AppListItemType[];
@@ -66,8 +67,7 @@ const defaultWhisperConfig: AppWhisperConfigType = {
}; };
const HomeChatWindow = ({ myApps }: Props) => { const HomeChatWindow = ({ myApps }: Props) => {
const { t, i18n } = useTranslation(); const { t } = useTranslation();
const language = i18n.language;
const { isPc } = useSystem(); const { isPc } = useSystem();
const { userInfo } = useUserStore(); const { userInfo } = useUserStore();
@@ -398,7 +398,7 @@ const HomeChatWindow = ({ myApps }: Props) => {
return ( return (
<Flex h={'100%'} flexDirection={['column', 'row']}> <Flex h={'100%'} flexDirection={['column', 'row']}>
{/* set window title and icon */} {/* set window title and icon */}
<NextHead title={chatSettings?.homeTabTitle || 'FastGPT'} icon="/icon/logo.svg" /> <NextHead title={chatSettings?.homeTabTitle} icon={getWebReqUrl(feConfigs?.favicon)} />
{/* show history slider */} {/* show history slider */}
{isPc ? ( {isPc ? (

View File

@@ -109,7 +109,7 @@ const Render = (props: { appId: string; isStandalone?: string }) => {
if (!isInitedUser) { if (!isInitedUser) {
return ( return (
<PageContainer isLoading flex={'1'} p={4}> <PageContainer isLoading flex={'1'} p={4}>
<NextHead title={feConfigs?.systemTitle}></NextHead> <NextHead title={feConfigs?.systemTitle} icon={feConfigs?.favicon} />
</PageContainer> </PageContainer>
); );
} }