mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 13:03:50 +00:00
feat: error track, app scroll
This commit is contained in:
@@ -37,7 +37,7 @@
|
||||
"chat": {
|
||||
"Admin Mark Content": "纠正后的回复",
|
||||
"Complete Response": "完整响应",
|
||||
"Confirm to clear history": "确认清空该应用的聊天记录?",
|
||||
"Confirm to clear history": "确认清空该应用的在线聊天记录?分享和 API 调用的记录不会被清空。",
|
||||
"Exit Chat": "退出聊天",
|
||||
"Feedback Close": "关闭反馈",
|
||||
"Feedback Failed": "提交反馈异常",
|
||||
|
@@ -439,13 +439,20 @@ const ChatBox = (
|
||||
border: theme.borders.base,
|
||||
mr: 3
|
||||
};
|
||||
const controlContainerStyle = {
|
||||
className: 'control',
|
||||
color: 'myGray.400',
|
||||
display: feedbackType === FeedbackTypeEnum.admin ? 'flex' : ['flex', 'none'],
|
||||
pl: 1,
|
||||
mt: 2
|
||||
};
|
||||
const controlContainerStyle = useCallback((status: ChatSiteItemType['status']) => {
|
||||
return {
|
||||
className: 'control',
|
||||
color: 'myGray.400',
|
||||
display:
|
||||
status === 'finish'
|
||||
? feedbackType === FeedbackTypeEnum.admin
|
||||
? 'flex'
|
||||
: ['flex', 'none']
|
||||
: 'none',
|
||||
pl: 1,
|
||||
mt: 2
|
||||
};
|
||||
}, []);
|
||||
const MessageCardStyle: BoxProps = {
|
||||
px: 4,
|
||||
py: 3,
|
||||
@@ -604,7 +611,11 @@ const ChatBox = (
|
||||
{item.obj === 'Human' && (
|
||||
<>
|
||||
<Flex w={'100%'} alignItems={'center'} justifyContent={'flex-end'}>
|
||||
<Flex {...controlContainerStyle} justifyContent={'flex-end'} mr={3}>
|
||||
<Flex
|
||||
{...controlContainerStyle(item.status)}
|
||||
justifyContent={'flex-end'}
|
||||
mr={3}
|
||||
>
|
||||
<MyTooltip label={'复制'}>
|
||||
<MyIcon
|
||||
{...controlIconStyle}
|
||||
@@ -652,7 +663,7 @@ const ChatBox = (
|
||||
<>
|
||||
<Flex w={'100%'} alignItems={'flex-end'}>
|
||||
<ChatAvatar src={appAvatar} type={'AI'} />
|
||||
<Flex {...controlContainerStyle} ml={3}>
|
||||
<Flex {...controlContainerStyle(item.status)} ml={3}>
|
||||
<MyTooltip label={'复制'}>
|
||||
<MyIcon
|
||||
{...controlIconStyle}
|
||||
|
@@ -13,6 +13,11 @@ export const fileImgs = [
|
||||
{ suffix: 'md', src: '/imgs/files/markdown.svg' }
|
||||
];
|
||||
|
||||
export enum TrackEventName {
|
||||
windowError = 'windowError',
|
||||
pageError = 'pageError'
|
||||
}
|
||||
|
||||
export const htmlTemplate = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
@@ -42,6 +42,7 @@ function App({ Component, pageProps }: AppProps) {
|
||||
const [googleClientVerKey, setGoogleVerKey] = useState<string>();
|
||||
|
||||
useEffect(() => {
|
||||
// get init data
|
||||
(async () => {
|
||||
const {
|
||||
feConfigs: { scripts, googleClientVerKey }
|
||||
@@ -49,6 +50,21 @@ function App({ Component, pageProps }: AppProps) {
|
||||
setScripts(scripts || []);
|
||||
setGoogleVerKey(googleClientVerKey);
|
||||
})();
|
||||
// add window error track
|
||||
window.onerror = function (msg, url) {
|
||||
window.umami?.track('windowError', {
|
||||
device: {
|
||||
userAgent: navigator.userAgent,
|
||||
platform: navigator.platform,
|
||||
appName: navigator.appName
|
||||
},
|
||||
msg,
|
||||
url
|
||||
});
|
||||
};
|
||||
return () => {
|
||||
window.onerror = null;
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
@@ -1,10 +1,19 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { serviceSideProps } from '@/utils/i18n';
|
||||
function Error() {
|
||||
const router = useRouter();
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
router.replace('/app/list');
|
||||
window.umami?.track('pageError', {
|
||||
userAgent: navigator.userAgent,
|
||||
platform: navigator.platform,
|
||||
appName: navigator.appName
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
setTimeout(() => {
|
||||
router.back();
|
||||
}, 2000);
|
||||
}, []);
|
||||
|
||||
@@ -16,4 +25,12 @@ function Error() {
|
||||
);
|
||||
}
|
||||
|
||||
export async function getServerSideProps(context: any) {
|
||||
console.log(context);
|
||||
|
||||
return {
|
||||
props: { ...(await serviceSideProps(context)) }
|
||||
};
|
||||
}
|
||||
|
||||
export default Error;
|
||||
|
@@ -2,6 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { connectToDatabase, Chat, ChatItem } from '@/service/mongo';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
import { ChatSourceEnum } from '@/constants/chat';
|
||||
|
||||
type Props = {
|
||||
chatId?: string;
|
||||
@@ -29,14 +30,19 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
]);
|
||||
}
|
||||
if (appId) {
|
||||
const chats = await Chat.find({
|
||||
appId,
|
||||
userId,
|
||||
source: ChatSourceEnum.online
|
||||
}).select('_id');
|
||||
const chatIds = chats.map((chat) => chat._id);
|
||||
|
||||
await Promise.all([
|
||||
Chat.deleteMany({
|
||||
appId,
|
||||
userId
|
||||
_id: { $in: chatIds }
|
||||
}),
|
||||
ChatItem.deleteMany({
|
||||
userId,
|
||||
appId
|
||||
chatId: { $in: chatIds }
|
||||
})
|
||||
]);
|
||||
}
|
||||
|
@@ -15,29 +15,31 @@ const SliderApps = ({ appId }: { appId: string }) => {
|
||||
useQuery(['loadModels'], () => loadMyApps(false));
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex
|
||||
alignItems={'center'}
|
||||
cursor={'pointer'}
|
||||
py={2}
|
||||
px={3}
|
||||
borderRadius={'md'}
|
||||
_hover={{ bg: 'myGray.200' }}
|
||||
onClick={() => router.push('/app/list')}
|
||||
>
|
||||
<IconButton
|
||||
mr={3}
|
||||
icon={<MyIcon name={'backFill'} w={'18px'} color={'myBlue.600'} />}
|
||||
bg={'white'}
|
||||
boxShadow={'1px 1px 9px rgba(0,0,0,0.15)'}
|
||||
h={'28px'}
|
||||
size={'sm'}
|
||||
borderRadius={'50%'}
|
||||
aria-label={''}
|
||||
/>
|
||||
{t('chat.Exit Chat')}
|
||||
</Flex>
|
||||
<Box mt={5}>
|
||||
<Flex flexDirection={'column'} h={'100%'}>
|
||||
<Box px={5} py={4}>
|
||||
<Flex
|
||||
alignItems={'center'}
|
||||
cursor={'pointer'}
|
||||
py={2}
|
||||
px={3}
|
||||
borderRadius={'md'}
|
||||
_hover={{ bg: 'myGray.200' }}
|
||||
onClick={() => router.push('/app/list')}
|
||||
>
|
||||
<IconButton
|
||||
mr={3}
|
||||
icon={<MyIcon name={'backFill'} w={'18px'} color={'myBlue.600'} />}
|
||||
bg={'white'}
|
||||
boxShadow={'1px 1px 9px rgba(0,0,0,0.15)'}
|
||||
h={'28px'}
|
||||
size={'sm'}
|
||||
borderRadius={'50%'}
|
||||
aria-label={''}
|
||||
/>
|
||||
{t('chat.Exit Chat')}
|
||||
</Flex>
|
||||
</Box>
|
||||
<Box flex={'1 0 0'} h={0} px={5} overflow={'overlay'}>
|
||||
{myApps.map((item) => (
|
||||
<Flex
|
||||
key={item._id}
|
||||
@@ -72,7 +74,7 @@ const SliderApps = ({ appId }: { appId: string }) => {
|
||||
</Flex>
|
||||
))}
|
||||
</Box>
|
||||
</>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
|
@@ -252,7 +252,7 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
|
||||
</Head>
|
||||
{/* pc show myself apps */}
|
||||
{isPc && (
|
||||
<Box p={5} borderRight={theme.borders.base} w={'220px'} flexShrink={0}>
|
||||
<Box borderRight={theme.borders.base} w={'220px'} flexShrink={0}>
|
||||
<SliderApps appId={appId} />
|
||||
</Box>
|
||||
)}
|
||||
|
4
client/src/types/index.d.ts
vendored
4
client/src/types/index.d.ts
vendored
@@ -4,6 +4,7 @@ import type { Pool } from 'pg';
|
||||
import type { Tiktoken } from '@dqbd/tiktoken';
|
||||
import type { Logger } from 'winston';
|
||||
import { ChatModelItemType, QAModelItemType, VectorModelItemType } from './model';
|
||||
import { TrackEventName } from '@/constants/common';
|
||||
|
||||
export type PagingData<T> = {
|
||||
pageNum: number;
|
||||
@@ -60,5 +61,8 @@ declare global {
|
||||
particlesJS: any;
|
||||
grecaptcha: any;
|
||||
QRCode: any;
|
||||
umami?: {
|
||||
track: (event: `${TrackEventName}`, data: any) => void;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user