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