feat: iframe embed

This commit is contained in:
archer
2023-07-28 17:44:07 +08:00
parent 5d0c8fa462
commit f764d81cdd
10 changed files with 152 additions and 134 deletions

View File

@@ -1,6 +1,6 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { connectToDatabase } from '@/service/mongo';
import { authUser, authApp, authShareChat } from '@/service/utils/auth';
import { authUser, authApp, authShareChat, AuthUserTypeEnum } from '@/service/utils/auth';
import { sseErrRes, jsonRes } from '@/service/response';
import { withNextCors } from '@/service/utils/tools';
import { ChatRoleEnum, ChatSourceEnum, sseResponseEventEnum } from '@/constants/chat';
@@ -25,7 +25,6 @@ import { pushTaskBill } from '@/service/events/pushBill';
import { BillSourceEnum } from '@/constants/user';
import { ChatHistoryItemResType } from '@/types/chat';
import { UserModelSchema } from '@/types/mongoSchema';
import { getAIChatApi } from '@/service/ai/openai';
export type MessageItemType = ChatCompletionRequestMessage & { _id?: string };
type FastGptWebChatProps = {
@@ -84,7 +83,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
if (!user) {
throw new Error('Account is error');
}
if (authType !== 'token') {
if (authType === AuthUserTypeEnum.apikey || shareId) {
user.openaiAccount = undefined;
}
@@ -208,7 +207,11 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
appName: app.name,
appId,
userId,
source: authType === 'apikey' ? BillSourceEnum.api : BillSourceEnum.fastgpt,
source: (() => {
if (authType === 'apikey') return BillSourceEnum.api;
if (shareId) return BillSourceEnum.shareLink;
return BillSourceEnum.fastgpt;
})(),
response: responseData,
shareId
});

View File

@@ -19,11 +19,10 @@ import {
} from '@chakra-ui/react';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import MyIcon from '@/components/Icon';
import { useToast } from '@/hooks/useToast';
import { useLoading } from '@/hooks/useLoading';
import { useQuery } from '@tanstack/react-query';
import { getShareChatList, delShareChatById, createShareChat } from '@/api/chat';
import { formatTimeToChatTime, useCopyData, getErrText } from '@/utils/tools';
import { formatTimeToChatTime, useCopyData } from '@/utils/tools';
import { useForm } from 'react-hook-form';
import { defaultShareChat } from '@/constants/model';
import type { ShareChatEditType } from '@/types/app';
@@ -67,8 +66,8 @@ const Share = ({ appId }: { appId: string }) => {
onSuccess(id) {
onCloseCreateShareChat();
refetchShareChatList();
const url = `对话地址为:${location.origin}/chat/share?shareId=${id}`;
copyData(url, '已复制分享地址');
const url = `${location.origin}/chat/share?shareId=${id}`;
copyData(url, '创建成功。已复制分享地址,可直接分享使用');
resetShareChat(defaultShareChat);
}
});
@@ -116,40 +115,53 @@ const Share = ({ appId }: { appId: string }) => {
<Td>{item.name}</Td>
<Td>{formatPrice(item.total)}</Td>
<Td>{item.lastTime ? formatTimeToChatTime(item.lastTime) : '未使用'}</Td>
<Td>
<Flex>
<MyTooltip label={'复制分享链接'}>
<MyIcon
mr={3}
name="copy"
w={'14px'}
cursor={'pointer'}
_hover={{ color: 'myBlue.600' }}
onClick={() => {
const url = `${location.origin}/chat/share?shareId=${item.shareId}`;
copyData(url, '已复制分享链接');
}}
/>
</MyTooltip>
<MyTooltip label={'删除链接'}>
<MyIcon
name="delete"
w={'14px'}
cursor={'pointer'}
_hover={{ color: 'red' }}
onClick={async () => {
setIsLoading(true);
try {
await delShareChatById(item._id);
refetchShareChatList();
} catch (error) {
console.log(error);
}
setIsLoading(false);
}}
/>
</MyTooltip>
</Flex>
<Td display={'flex'} alignItems={'center'}>
<MyTooltip label={'嵌入网页'}>
<MyIcon
mr={4}
name="apiLight"
w={'14px'}
cursor={'pointer'}
_hover={{ color: 'myBlue.600' }}
onClick={() => {
const url = `${location.origin}/chat/share?shareId=${item.shareId}`;
const src = `${location.origin}/js/iframe.js`;
const script = `<script src="${src}" id="fastgpt-iframe" data-src="${url}" data-color="#4e83fd"></script>`;
copyData(script, '已复制嵌入 Script可在应用 HTML 底部嵌入', 3000);
}}
/>
</MyTooltip>
<MyTooltip label={'复制分享链接'}>
<MyIcon
mr={4}
name="copy"
w={'14px'}
cursor={'pointer'}
_hover={{ color: 'myBlue.600' }}
onClick={() => {
const url = `${location.origin}/chat/share?shareId=${item.shareId}`;
copyData(url, '已复制分享链接,可直接分享使用');
}}
/>
</MyTooltip>
<MyTooltip label={'删除链接'}>
<MyIcon
name="delete"
w={'14px'}
cursor={'pointer'}
_hover={{ color: 'red' }}
onClick={async () => {
setIsLoading(true);
try {
await delShareChatById(item._id);
refetchShareChatList();
} catch (error) {
console.log(error);
}
setIsLoading(false);
}}
/>
</MyTooltip>
</Td>
</Tr>
))}

View File

@@ -1,4 +1,4 @@
import React, { useCallback } from 'react';
import React, { useCallback, useEffect } from 'react';
import {
Box,
Grid,

View File

@@ -8,7 +8,7 @@ import { useRouter } from 'next/router';
const ToolMenu = ({ history }: { history: ChatItemType[] }) => {
const { onExportChat } = useChatBox();
const router = useRouter();
const { appId } = router.query;
const { appId, shareId } = router.query;
const menuList = useMemo(
() => [
@@ -18,7 +18,8 @@ const ToolMenu = ({ history }: { history: ChatItemType[] }) => {
onClick: () => {
router.replace({
query: {
appId
appId,
shareId
}
});
}
@@ -35,7 +36,7 @@ const ToolMenu = ({ history }: { history: ChatItemType[] }) => {
},
{ icon: 'pdf', label: 'PDF导出', onClick: () => onExportChat({ type: 'pdf', history }) }
],
[appId, history, onExportChat, router]
[appId, history, onExportChat, router, shareId]
);
return history.length > 0 ? (
@@ -59,7 +60,9 @@ const ToolMenu = ({ history }: { history: ChatItemType[] }) => {
))}
</MenuList>
</Menu>
) : null;
) : (
<Box w={'28px'} h={'28px'} />
);
};
export default ToolMenu;