mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-06-04 11:24:00 +08:00
### What problem does this PR solve? Embed the chat window into other websites through iframe #345 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
962c66714e
commit
cda7b607cb
@ -2,7 +2,11 @@ import Markdown from 'react-markdown';
|
||||
import SyntaxHighlighter from 'react-syntax-highlighter';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
|
||||
const SharedMarkdown = ({ content }: { content: string }) => {
|
||||
const HightLightMarkdown = ({
|
||||
children,
|
||||
}: {
|
||||
children: string | null | undefined;
|
||||
}) => {
|
||||
return (
|
||||
<Markdown
|
||||
remarkPlugins={[remarkGfm]}
|
||||
@ -24,9 +28,9 @@ const SharedMarkdown = ({ content }: { content: string }) => {
|
||||
} as any
|
||||
}
|
||||
>
|
||||
{content}
|
||||
{children}
|
||||
</Markdown>
|
||||
);
|
||||
};
|
||||
|
||||
export default SharedMarkdown;
|
||||
export default HightLightMarkdown;
|
@ -4,7 +4,7 @@ import {
|
||||
IStats,
|
||||
IToken,
|
||||
} from '@/interfaces/database/chat';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { useDispatch, useSelector } from 'umi';
|
||||
|
||||
export const useFetchDialogList = () => {
|
||||
@ -299,27 +299,4 @@ export const useCompleteSharedConversation = () => {
|
||||
return completeSharedConversation;
|
||||
};
|
||||
|
||||
export const useCreatePublicUrlToken = (dialogId: string, visible: boolean) => {
|
||||
const [token, setToken] = useState();
|
||||
const createToken = useCreateToken(dialogId);
|
||||
const { protocol, host } = window.location;
|
||||
|
||||
const urlWithToken = `${protocol}//${host}/chat/share?shared_id=${token}`;
|
||||
|
||||
const createUrlToken = useCallback(async () => {
|
||||
if (visible) {
|
||||
const data = await createToken();
|
||||
const urlToken = data.data?.token;
|
||||
if (urlToken) {
|
||||
setToken(urlToken);
|
||||
}
|
||||
}
|
||||
}, [createToken, visible]);
|
||||
|
||||
useEffect(() => {
|
||||
createUrlToken();
|
||||
}, [createUrlToken]);
|
||||
|
||||
return { token, createUrlToken, urlWithToken };
|
||||
};
|
||||
//#endregion
|
||||
|
@ -33,3 +33,12 @@
|
||||
.pointerCursor() {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.clearCardBody() {
|
||||
:global {
|
||||
.ant-card-body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ export default {
|
||||
'This sets the maximum length of the model’s output, measured in the number of tokens (words or pieces of words).',
|
||||
quote: 'Show Quote',
|
||||
quoteTip: 'Should the source of the original text be displayed?',
|
||||
overview: 'Overview',
|
||||
overview: 'API',
|
||||
pv: 'Number of messages',
|
||||
uv: 'Active user number',
|
||||
speed: 'Token output speed',
|
||||
@ -367,6 +367,14 @@ export default {
|
||||
createNewKey: 'Create new key',
|
||||
created: 'Created',
|
||||
action: 'Action',
|
||||
embedModalTitle: 'Embed into website',
|
||||
comingSoon: 'Coming Soon',
|
||||
fullScreenTitle: 'Full Embed',
|
||||
fullScreenDescription:
|
||||
'Embed the following iframe into your website at the desired location',
|
||||
partialTitle: 'Partial Embed',
|
||||
extensionTitle: 'Chrome Extension',
|
||||
tokenError: 'Please create API Token first!',
|
||||
},
|
||||
setting: {
|
||||
profile: 'Profile',
|
||||
|
@ -321,7 +321,7 @@ export default {
|
||||
'這設置了模型輸出的最大長度,以標記(單詞或單詞片段)的數量來衡量。',
|
||||
quote: '顯示引文',
|
||||
quoteTip: '是否應該顯示原文出處?',
|
||||
overview: '概覽',
|
||||
overview: 'API',
|
||||
pv: '消息數',
|
||||
uv: '活躍用戶數',
|
||||
speed: 'Token 輸出速度',
|
||||
@ -339,6 +339,13 @@ export default {
|
||||
createNewKey: '創建新密鑰',
|
||||
created: '創建於',
|
||||
action: '操作',
|
||||
embedModalTitle: '嵌入網站',
|
||||
comingSoon: '即將推出',
|
||||
fullScreenTitle: '全屏嵌入',
|
||||
fullScreenDescription: '將以下iframe嵌入您的網站處於所需位置',
|
||||
partialTitle: '部分嵌入',
|
||||
extensionTitle: 'Chrome 插件',
|
||||
tokenError: '請先創建 Api Token!',
|
||||
},
|
||||
setting: {
|
||||
profile: '概述',
|
||||
|
@ -338,7 +338,7 @@ export default {
|
||||
'这设置了模型输出的最大长度,以标记(单词或单词片段)的数量来衡量。',
|
||||
quote: '显示引文',
|
||||
quoteTip: '是否应该显示原文出处?',
|
||||
overview: '概览',
|
||||
overview: 'API',
|
||||
pv: '消息数',
|
||||
uv: '活跃用户数',
|
||||
speed: 'Token 输出速度',
|
||||
@ -356,6 +356,13 @@ export default {
|
||||
createNewKey: '创建新密钥',
|
||||
created: '创建于',
|
||||
action: '操作',
|
||||
embedModalTitle: '嵌入网站',
|
||||
comingSoon: '即将推出',
|
||||
fullScreenTitle: '全屏嵌入',
|
||||
fullScreenDescription: '将以下iframe嵌入您的网站处于所需位置',
|
||||
partialTitle: '部分嵌入',
|
||||
extensionTitle: 'Chrome 插件',
|
||||
tokenError: '请先创建 Api Token!',
|
||||
},
|
||||
setting: {
|
||||
profile: '概要',
|
||||
|
@ -1,17 +1,19 @@
|
||||
import CopyToClipboard from '@/components/copy-to-clipboard';
|
||||
import LineChart from '@/components/line-chart';
|
||||
import { useCreatePublicUrlToken } from '@/hooks/chatHooks';
|
||||
import { useSetModalState, useTranslate } from '@/hooks/commonHooks';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { IDialog, IStats } from '@/interfaces/database/chat';
|
||||
import { ReloadOutlined } from '@ant-design/icons';
|
||||
import { Button, Card, DatePicker, Flex, Modal, Space, Typography } from 'antd';
|
||||
import { RangePickerProps } from 'antd/es/date-picker';
|
||||
import dayjs from 'dayjs';
|
||||
import camelCase from 'lodash/camelCase';
|
||||
import { Link } from 'umi';
|
||||
import ChatApiKeyModal from '../chat-api-key-modal';
|
||||
import { useFetchStatsOnMount, useSelectChartStatsList } from '../hooks';
|
||||
import EmbedModal from '../embed-modal';
|
||||
import {
|
||||
useFetchStatsOnMount,
|
||||
usePreviewChat,
|
||||
useSelectChartStatsList,
|
||||
useShowEmbedModal,
|
||||
} from '../hooks';
|
||||
import styles from './index.less';
|
||||
|
||||
const { Paragraph } = Typography;
|
||||
@ -24,16 +26,18 @@ const ChatOverviewModal = ({
|
||||
}: IModalProps<any> & { dialog: IDialog }) => {
|
||||
const { t } = useTranslate('chat');
|
||||
const chartList = useSelectChartStatsList();
|
||||
const { urlWithToken, createUrlToken, token } = useCreatePublicUrlToken(
|
||||
dialog.id,
|
||||
visible,
|
||||
);
|
||||
|
||||
const {
|
||||
visible: apiKeyVisible,
|
||||
hideModal: hideApiKeyModal,
|
||||
showModal: showApiKeyModal,
|
||||
} = useSetModalState();
|
||||
const {
|
||||
embedVisible,
|
||||
hideEmbedModal,
|
||||
showEmbedModal,
|
||||
embedToken,
|
||||
errorContextHolder,
|
||||
} = useShowEmbedModal(dialog.id);
|
||||
|
||||
const { pickerValue, setPickerValue } = useFetchStatsOnMount(visible);
|
||||
|
||||
@ -41,6 +45,8 @@ const ChatOverviewModal = ({
|
||||
return current && current > dayjs().endOf('day');
|
||||
};
|
||||
|
||||
const { handlePreview, contextHolder } = usePreviewChat(dialog.id);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
@ -50,36 +56,41 @@ const ChatOverviewModal = ({
|
||||
width={'100vw'}
|
||||
>
|
||||
<Flex vertical gap={'middle'}>
|
||||
<Card title={dialog.name}>
|
||||
<Flex gap={8} vertical>
|
||||
{t('publicUrl')}
|
||||
<Flex className={styles.linkText} gap={10}>
|
||||
<span>{urlWithToken}</span>
|
||||
<CopyToClipboard text={urlWithToken}></CopyToClipboard>
|
||||
<ReloadOutlined onClick={createUrlToken} />
|
||||
</Flex>
|
||||
<Space size={'middle'}>
|
||||
<Button>
|
||||
<Link to={`/chat/share?shared_id=${token}`} target="_blank">
|
||||
{t('preview')}
|
||||
</Link>
|
||||
</Button>
|
||||
<Button>{t('embedded')}</Button>
|
||||
</Space>
|
||||
</Flex>
|
||||
</Card>
|
||||
<Card title={t('backendServiceApi')}>
|
||||
<Flex gap={8} vertical>
|
||||
{t('serviceApiEndpoint')}
|
||||
<Paragraph copyable className={styles.linkText}>
|
||||
This is a copyable text.
|
||||
https://demo.ragflow.io/v1/api/
|
||||
</Paragraph>
|
||||
</Flex>
|
||||
<Space size={'middle'}>
|
||||
<Button onClick={showApiKeyModal}>{t('apiKey')}</Button>
|
||||
<Button>{t('apiReference')}</Button>
|
||||
<a
|
||||
href={
|
||||
'https://github.com/infiniflow/ragflow/blob/main/docs/conversation_api.md'
|
||||
}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<Button>{t('apiReference')}</Button>
|
||||
</a>
|
||||
</Space>
|
||||
</Card>
|
||||
<Card title={dialog.name}>
|
||||
<Flex gap={8} vertical>
|
||||
{t('publicUrl')}
|
||||
{/* <Flex className={styles.linkText} gap={10}>
|
||||
<span>{urlWithToken}</span>
|
||||
<CopyToClipboard text={urlWithToken}></CopyToClipboard>
|
||||
<ReloadOutlined onClick={createUrlToken} />
|
||||
</Flex> */}
|
||||
<Space size={'middle'}>
|
||||
<Button onClick={handlePreview}>{t('preview')}</Button>
|
||||
<Button onClick={showEmbedModal}>{t('embedded')}</Button>
|
||||
</Space>
|
||||
</Flex>
|
||||
</Card>
|
||||
|
||||
<Space>
|
||||
<b>{t('dateRange')}</b>
|
||||
<RangePicker
|
||||
@ -103,6 +114,13 @@ const ChatOverviewModal = ({
|
||||
hideModal={hideApiKeyModal}
|
||||
dialogId={dialog.id}
|
||||
></ChatApiKeyModal>
|
||||
<EmbedModal
|
||||
token={embedToken}
|
||||
visible={embedVisible}
|
||||
hideModal={hideEmbedModal}
|
||||
></EmbedModal>
|
||||
{contextHolder}
|
||||
{errorContextHolder}
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
|
8
web/src/pages/chat/embed-modal/index.less
Normal file
8
web/src/pages/chat/embed-modal/index.less
Normal file
@ -0,0 +1,8 @@
|
||||
.codeCard {
|
||||
.clearCardBody();
|
||||
}
|
||||
|
||||
.codeText {
|
||||
padding: 10px;
|
||||
background-color: #e8e8ea;
|
||||
}
|
70
web/src/pages/chat/embed-modal/index.tsx
Normal file
70
web/src/pages/chat/embed-modal/index.tsx
Normal file
@ -0,0 +1,70 @@
|
||||
import CopyToClipboard from '@/components/copy-to-clipboard';
|
||||
import HightLightMarkdown from '@/components/highlight-markdown';
|
||||
import { useTranslate } from '@/hooks/commonHooks';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { Card, Modal, Tabs, TabsProps } from 'antd';
|
||||
import styles from './index.less';
|
||||
|
||||
const EmbedModal = ({
|
||||
visible,
|
||||
hideModal,
|
||||
token = '',
|
||||
}: IModalProps<any> & { token: string }) => {
|
||||
const { t } = useTranslate('chat');
|
||||
|
||||
const text = `
|
||||
~~~ html
|
||||
<iframe
|
||||
src="https://demo.ragflow.io/chat/share?shared_id=${token}"
|
||||
style="width: 100%; height: 100%; min-height: 600px"
|
||||
frameborder="0"
|
||||
>
|
||||
</iframe>
|
||||
~~~
|
||||
`;
|
||||
|
||||
const items: TabsProps['items'] = [
|
||||
{
|
||||
key: '1',
|
||||
label: t('fullScreenTitle'),
|
||||
children: (
|
||||
<Card
|
||||
title={t('fullScreenDescription')}
|
||||
extra={<CopyToClipboard text={text}></CopyToClipboard>}
|
||||
className={styles.codeCard}
|
||||
>
|
||||
<HightLightMarkdown>{text}</HightLightMarkdown>
|
||||
</Card>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: t('partialTitle'),
|
||||
children: t('comingSoon'),
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
label: t('extensionTitle'),
|
||||
children: t('comingSoon'),
|
||||
},
|
||||
];
|
||||
|
||||
const onChange = (key: string) => {
|
||||
console.log(key);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={t('embedModalTitle')}
|
||||
open={visible}
|
||||
style={{ top: 300 }}
|
||||
width={'50vw'}
|
||||
onOk={hideModal}
|
||||
onCancel={hideModal}
|
||||
>
|
||||
<Tabs defaultActiveKey="1" items={items} onChange={onChange} />
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default EmbedModal;
|
@ -14,15 +14,21 @@ import {
|
||||
useRemoveToken,
|
||||
useSelectConversationList,
|
||||
useSelectDialogList,
|
||||
useSelectStats,
|
||||
useSelectTokenList,
|
||||
useSetDialog,
|
||||
useUpdateConversation,
|
||||
} from '@/hooks/chatHooks';
|
||||
import { useSetModalState, useShowDeleteConfirm } from '@/hooks/commonHooks';
|
||||
import {
|
||||
useSetModalState,
|
||||
useShowDeleteConfirm,
|
||||
useTranslate,
|
||||
} from '@/hooks/commonHooks';
|
||||
import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks';
|
||||
import { IConversation, IDialog, IStats } from '@/interfaces/database/chat';
|
||||
import { IChunk } from '@/interfaces/database/knowledge';
|
||||
import { getFileExtension } from '@/utils';
|
||||
import { message } from 'antd';
|
||||
import dayjs, { Dayjs } from 'dayjs';
|
||||
import omit from 'lodash/omit';
|
||||
import {
|
||||
@ -777,35 +783,35 @@ type ChartStatsType = {
|
||||
};
|
||||
|
||||
export const useSelectChartStatsList = (): ChartStatsType => {
|
||||
// const stats: IStats = useSelectStats();
|
||||
const stats = {
|
||||
pv: [
|
||||
['2024-06-01', 1],
|
||||
['2024-07-24', 3],
|
||||
['2024-09-01', 10],
|
||||
],
|
||||
uv: [
|
||||
['2024-02-01', 0],
|
||||
['2024-03-01', 99],
|
||||
['2024-05-01', 3],
|
||||
],
|
||||
speed: [
|
||||
['2024-09-01', 2],
|
||||
['2024-09-01', 3],
|
||||
],
|
||||
tokens: [
|
||||
['2024-09-01', 1],
|
||||
['2024-09-01', 3],
|
||||
],
|
||||
round: [
|
||||
['2024-09-01', 0],
|
||||
['2024-09-01', 3],
|
||||
],
|
||||
thumb_up: [
|
||||
['2024-09-01', 3],
|
||||
['2024-09-01', 9],
|
||||
],
|
||||
};
|
||||
const stats: IStats = useSelectStats();
|
||||
// const stats = {
|
||||
// pv: [
|
||||
// ['2024-06-01', 1],
|
||||
// ['2024-07-24', 3],
|
||||
// ['2024-09-01', 10],
|
||||
// ],
|
||||
// uv: [
|
||||
// ['2024-02-01', 0],
|
||||
// ['2024-03-01', 99],
|
||||
// ['2024-05-01', 3],
|
||||
// ],
|
||||
// speed: [
|
||||
// ['2024-09-01', 2],
|
||||
// ['2024-09-01', 3],
|
||||
// ],
|
||||
// tokens: [
|
||||
// ['2024-09-01', 1],
|
||||
// ['2024-09-01', 3],
|
||||
// ],
|
||||
// round: [
|
||||
// ['2024-09-01', 0],
|
||||
// ['2024-09-01', 3],
|
||||
// ],
|
||||
// thumb_up: [
|
||||
// ['2024-09-01', 3],
|
||||
// ['2024-09-01', 9],
|
||||
// ],
|
||||
// };
|
||||
|
||||
return Object.keys(stats).reduce((pre, cur) => {
|
||||
const item = stats[cur as keyof IStats];
|
||||
@ -819,4 +825,93 @@ export const useSelectChartStatsList = (): ChartStatsType => {
|
||||
}, {} as ChartStatsType);
|
||||
};
|
||||
|
||||
export const useShowTokenEmptyError = () => {
|
||||
const [messageApi, contextHolder] = message.useMessage();
|
||||
const { t } = useTranslate('chat');
|
||||
|
||||
const showTokenEmptyError = useCallback(() => {
|
||||
messageApi.error(t('tokenError'));
|
||||
}, [messageApi, t]);
|
||||
return { showTokenEmptyError, contextHolder };
|
||||
};
|
||||
|
||||
const getUrlWithToken = (token: string) => {
|
||||
const { protocol, host } = window.location;
|
||||
return `${protocol}//${host}/chat/share?shared_id=${token}`;
|
||||
};
|
||||
|
||||
const useFetchTokenListBeforeOtherStep = (dialogId: string) => {
|
||||
const { showTokenEmptyError, contextHolder } = useShowTokenEmptyError();
|
||||
|
||||
const listToken = useListToken();
|
||||
const tokenList = useSelectTokenList();
|
||||
|
||||
const token =
|
||||
Array.isArray(tokenList) && tokenList.length > 0 ? tokenList[0].token : '';
|
||||
|
||||
const handleOperate = useCallback(async () => {
|
||||
const data = await listToken(dialogId);
|
||||
const list = data.data;
|
||||
if (data.retcode === 0 && Array.isArray(list) && list.length > 0) {
|
||||
return list[0]?.token;
|
||||
} else {
|
||||
showTokenEmptyError();
|
||||
return false;
|
||||
}
|
||||
}, [dialogId, listToken, showTokenEmptyError]);
|
||||
|
||||
return {
|
||||
token,
|
||||
contextHolder,
|
||||
handleOperate,
|
||||
};
|
||||
};
|
||||
|
||||
export const useShowEmbedModal = (dialogId: string) => {
|
||||
const {
|
||||
visible: embedVisible,
|
||||
hideModal: hideEmbedModal,
|
||||
showModal: showEmbedModal,
|
||||
} = useSetModalState();
|
||||
|
||||
const { handleOperate, token, contextHolder } =
|
||||
useFetchTokenListBeforeOtherStep(dialogId);
|
||||
|
||||
const handleShowEmbedModal = useCallback(async () => {
|
||||
const succeed = await handleOperate();
|
||||
if (succeed) {
|
||||
showEmbedModal();
|
||||
}
|
||||
}, [handleOperate, showEmbedModal]);
|
||||
|
||||
return {
|
||||
showEmbedModal: handleShowEmbedModal,
|
||||
hideEmbedModal,
|
||||
embedVisible,
|
||||
embedToken: token,
|
||||
errorContextHolder: contextHolder,
|
||||
};
|
||||
};
|
||||
|
||||
export const usePreviewChat = (dialogId: string) => {
|
||||
const { handleOperate, contextHolder } =
|
||||
useFetchTokenListBeforeOtherStep(dialogId);
|
||||
|
||||
const open = useCallback((t: string) => {
|
||||
window.open(getUrlWithToken(t), '_blank');
|
||||
}, []);
|
||||
|
||||
const handlePreview = useCallback(async () => {
|
||||
const token = await handleOperate();
|
||||
if (token) {
|
||||
open(token);
|
||||
}
|
||||
}, [handleOperate, open]);
|
||||
|
||||
return {
|
||||
handlePreview,
|
||||
contextHolder,
|
||||
};
|
||||
};
|
||||
|
||||
//#endregion
|
||||
|
@ -1,6 +1,11 @@
|
||||
import { ReactComponent as ChatAppCube } from '@/assets/svg/chat-app-cube.svg';
|
||||
import RenameModal from '@/components/rename-modal';
|
||||
import { DeleteOutlined, EditOutlined, FormOutlined } from '@ant-design/icons';
|
||||
import {
|
||||
CloudOutlined,
|
||||
DeleteOutlined,
|
||||
EditOutlined,
|
||||
FormOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
@ -185,16 +190,16 @@ const Chat = () => {
|
||||
),
|
||||
},
|
||||
{ type: 'divider' },
|
||||
// {
|
||||
// key: '3',
|
||||
// onClick: handleShowOverviewModal(dialog),
|
||||
// label: (
|
||||
// <Space>
|
||||
// <ProfileOutlined />
|
||||
// {t('overview')}
|
||||
// </Space>
|
||||
// ),
|
||||
// },
|
||||
{
|
||||
key: '3',
|
||||
onClick: handleShowOverviewModal(dialog),
|
||||
label: (
|
||||
<Space>
|
||||
<CloudOutlined />
|
||||
{t('overview')}
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return appItems;
|
||||
|
@ -202,7 +202,7 @@ const model: DvaModel<ChatModelState> = {
|
||||
payload: data.data,
|
||||
});
|
||||
}
|
||||
return data.retcode;
|
||||
return data;
|
||||
},
|
||||
*removeToken({ payload }, { call, put }) {
|
||||
const { data } = yield call(
|
||||
|
@ -6,10 +6,10 @@ import { Avatar, Button, Flex, Input, Skeleton, Spin } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { useSelectConversationLoading } from '../hooks';
|
||||
|
||||
import HightLightMarkdown from '@/components/highlight-markdown';
|
||||
import React, { ChangeEventHandler, forwardRef } from 'react';
|
||||
import { IClientConversation } from '../interface';
|
||||
import styles from './index.less';
|
||||
import SharedMarkdown from './shared-markdown';
|
||||
|
||||
const MessageItem = ({ item }: { item: Message }) => {
|
||||
const isAssistant = item.role === MessageType.Assistant;
|
||||
@ -46,7 +46,7 @@ const MessageItem = ({ item }: { item: Message }) => {
|
||||
<b>{isAssistant ? '' : 'You'}</b>
|
||||
<div className={styles.messageText}>
|
||||
{item.content !== '' ? (
|
||||
<SharedMarkdown content={item.content}></SharedMarkdown>
|
||||
<HightLightMarkdown>{item.content}</HightLightMarkdown>
|
||||
) : (
|
||||
<Skeleton active className={styles.messageEmpty} />
|
||||
)}
|
||||
|
@ -98,8 +98,8 @@ request.interceptors.request.use((url: string, options: any) => {
|
||||
url,
|
||||
options: {
|
||||
...options,
|
||||
// data,
|
||||
// params,
|
||||
data,
|
||||
params,
|
||||
headers: {
|
||||
...(options.skipToken ? undefined : { [Authorization]: authorization }),
|
||||
...options.headers,
|
||||
|
Loading…
x
Reference in New Issue
Block a user