feat: add more share config (#3120)
* feat: add more share config * add i18n en
This commit is contained in:
@@ -34,7 +34,7 @@ export type ChatProviderProps = OutLinkChatAuthProps & {
|
||||
|
||||
// not chat test params
|
||||
chatId?: string;
|
||||
chatType?: 'log' | 'chat';
|
||||
chatType?: 'log' | 'chat' | 'share' | 'team';
|
||||
};
|
||||
|
||||
type useChatStoreType = OutLinkChatAuthProps &
|
||||
|
||||
@@ -13,6 +13,9 @@ import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
||||
import { ChatSiteItemType } from '@fastgpt/global/core/chat/type';
|
||||
import { addStatisticalDataToHistoryItem } from '@/global/core/chat/utils';
|
||||
import { useSize } from 'ahooks';
|
||||
import { ChatContext } from '@/web/core/chat/context/chatContext';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
import { ChatBoxContext } from '../Provider';
|
||||
|
||||
const QuoteModal = dynamic(() => import('./QuoteModal'));
|
||||
const ContextModal = dynamic(() => import('./ContextModal'));
|
||||
@@ -37,6 +40,7 @@ const ResponseTags = ({
|
||||
totalRunningTime: runningTime = 0,
|
||||
historyPreviewLength = 0
|
||||
} = useMemo(() => addStatisticalDataToHistoryItem(historyItem), [historyItem]);
|
||||
|
||||
const [quoteModalData, setQuoteModalData] = useState<{
|
||||
rawSearch: SearchDataResponseItemType[];
|
||||
metadata?: {
|
||||
@@ -47,6 +51,13 @@ const ResponseTags = ({
|
||||
}>();
|
||||
const [quoteFolded, setQuoteFolded] = useState<boolean>(true);
|
||||
|
||||
const showCompleteQuote = useContextSelector(ChatContext, (v) => v.showCompleteQuote);
|
||||
const { chatType } = useContextSelector(ChatBoxContext, (v) => v);
|
||||
|
||||
const showAllTag = useMemo(() => {
|
||||
return chatType !== 'share' && chatType !== 'team';
|
||||
}, [chatType]);
|
||||
|
||||
const {
|
||||
isOpen: isOpenWholeModal,
|
||||
onOpen: onOpenWholeModal,
|
||||
@@ -77,10 +88,10 @@ const ResponseTags = ({
|
||||
sourceName: item.sourceName,
|
||||
sourceId: item.sourceId,
|
||||
icon: getSourceNameIcon({ sourceId: item.sourceId, sourceName: item.sourceName }),
|
||||
canReadQuote: showDetail || strIsLink(item.sourceId),
|
||||
canReadQuote: showCompleteQuote || strIsLink(item.sourceId),
|
||||
collectionId: item.collectionId
|
||||
}));
|
||||
}, [quoteList, showDetail]);
|
||||
}, [quoteList, showCompleteQuote]);
|
||||
|
||||
return !showTags ? null : (
|
||||
<>
|
||||
@@ -176,49 +187,51 @@ const ResponseTags = ({
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
{showDetail && (
|
||||
<Flex alignItems={'center'} mt={3} flexWrap={'wrap'} gap={2}>
|
||||
{quoteList.length > 0 && (
|
||||
<MyTooltip label={t('chat:view_citations')}>
|
||||
<MyTag
|
||||
colorSchema="blue"
|
||||
type="borderSolid"
|
||||
cursor={'pointer'}
|
||||
onClick={() => setQuoteModalData({ rawSearch: quoteList })}
|
||||
>
|
||||
{t('chat:citations', { num: quoteList.length })}
|
||||
</MyTag>
|
||||
</MyTooltip>
|
||||
)}
|
||||
{llmModuleAccount === 1 && (
|
||||
<>
|
||||
{historyPreviewLength > 0 && (
|
||||
<MyTooltip label={t('chat:click_contextual_preview')}>
|
||||
<MyTag
|
||||
colorSchema="green"
|
||||
cursor={'pointer'}
|
||||
type="borderSolid"
|
||||
onClick={onOpenContextModal}
|
||||
>
|
||||
{t('chat:contextual', { num: historyPreviewLength })}
|
||||
</MyTag>
|
||||
</MyTooltip>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{llmModuleAccount > 1 && (
|
||||
<MyTag type="borderSolid" colorSchema="blue">
|
||||
{t('chat:multiple_AI_conversations')}
|
||||
</MyTag>
|
||||
)}
|
||||
|
||||
{isPc && runningTime > 0 && (
|
||||
<MyTooltip label={t('chat:module_runtime_and')}>
|
||||
<MyTag colorSchema="purple" type="borderSolid" cursor={'default'}>
|
||||
{runningTime}s
|
||||
</MyTag>
|
||||
</MyTooltip>
|
||||
)}
|
||||
<Flex alignItems={'center'} mt={3} flexWrap={'wrap'} gap={2}>
|
||||
{quoteList.length > 0 && (
|
||||
<MyTooltip label={t('chat:view_citations')}>
|
||||
<MyTag
|
||||
colorSchema="blue"
|
||||
type="borderSolid"
|
||||
cursor={'pointer'}
|
||||
onClick={() => setQuoteModalData({ rawSearch: quoteList })}
|
||||
>
|
||||
{t('chat:citations', { num: quoteList.length })}
|
||||
</MyTag>
|
||||
</MyTooltip>
|
||||
)}
|
||||
{llmModuleAccount === 1 && showAllTag && (
|
||||
<>
|
||||
{historyPreviewLength > 0 && (
|
||||
<MyTooltip label={t('chat:click_contextual_preview')}>
|
||||
<MyTag
|
||||
colorSchema="green"
|
||||
cursor={'pointer'}
|
||||
type="borderSolid"
|
||||
onClick={onOpenContextModal}
|
||||
>
|
||||
{t('chat:contextual', { num: historyPreviewLength })}
|
||||
</MyTag>
|
||||
</MyTooltip>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{llmModuleAccount > 1 && showAllTag && (
|
||||
<MyTag type="borderSolid" colorSchema="blue">
|
||||
{t('chat:multiple_AI_conversations')}
|
||||
</MyTag>
|
||||
)}
|
||||
|
||||
{isPc && runningTime > 0 && (
|
||||
<MyTooltip label={t('chat:module_runtime_and')}>
|
||||
<MyTag colorSchema="purple" type="borderSolid" cursor={'default'}>
|
||||
{runningTime}s
|
||||
</MyTag>
|
||||
</MyTooltip>
|
||||
)}
|
||||
|
||||
{showAllTag && (
|
||||
<MyTooltip label={t('common:core.chat.response.Read complete response tips')}>
|
||||
<MyTag
|
||||
colorSchema="gray"
|
||||
@@ -229,18 +242,19 @@ const ResponseTags = ({
|
||||
{t('common:core.chat.response.Read complete response')}
|
||||
</MyTag>
|
||||
</MyTooltip>
|
||||
</Flex>
|
||||
)}
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
{!!quoteModalData && (
|
||||
<QuoteModal
|
||||
{...quoteModalData}
|
||||
showDetail={showDetail}
|
||||
showDetail={showCompleteQuote}
|
||||
onClose={() => setQuoteModalData(undefined)}
|
||||
/>
|
||||
)}
|
||||
{isOpenContextModal && <ContextModal dataId={dataId} onClose={onCloseContextModal} />}
|
||||
{isOpenWholeModal && (
|
||||
<WholeResponseModal dataId={dataId} showDetail={showDetail} onClose={onCloseWholeModal} />
|
||||
<WholeResponseModal dataId={dataId} showDetail={true} onClose={onCloseWholeModal} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -9,6 +9,8 @@ import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
|
||||
import dynamic from 'next/dynamic';
|
||||
import MyBox from '@fastgpt/web/components/common/MyBox';
|
||||
import { SearchScoreTypeEnum, SearchScoreTypeMap } from '@fastgpt/global/core/dataset/constants';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
import { ChatBoxContext } from '../chat/ChatContainer/ChatBox/Provider';
|
||||
|
||||
const InputDataModal = dynamic(() => import('@/pages/dataset/detail/components/InputDataModal'));
|
||||
|
||||
@@ -54,6 +56,12 @@ const QuoteItem = ({
|
||||
const { t } = useTranslation();
|
||||
const [editInputData, setEditInputData] = useState<{ dataId: string; collectionId: string }>();
|
||||
|
||||
const { chatType } = useContextSelector(ChatBoxContext, (v) => v);
|
||||
|
||||
const canEdit = useMemo(() => {
|
||||
return chatType !== 'share' && chatType !== 'team';
|
||||
}, [chatType]);
|
||||
|
||||
const score = useMemo(() => {
|
||||
if (!Array.isArray(quoteItem.score)) {
|
||||
return {
|
||||
@@ -224,7 +232,7 @@ const QuoteItem = ({
|
||||
canView={canViewSource}
|
||||
/>
|
||||
<Box flex={1} />
|
||||
{quoteItem.id && (
|
||||
{quoteItem.id && canEdit && (
|
||||
<MyTooltip label={t('common:core.dataset.data.Edit')}>
|
||||
<Box
|
||||
className="hover-data"
|
||||
@@ -252,7 +260,7 @@ const QuoteItem = ({
|
||||
</Box>
|
||||
</MyTooltip>
|
||||
)}
|
||||
{linkToDataset && (
|
||||
{linkToDataset && canEdit && (
|
||||
<Link
|
||||
as={NextLink}
|
||||
className="hover-data"
|
||||
|
||||
@@ -6,6 +6,8 @@ import { getCollectionSourceAndOpen } from '@/web/core/dataset/hooks/readCollect
|
||||
import { getSourceNameIcon } from '@fastgpt/global/core/dataset/utils';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { useI18n } from '@/web/context/I18n';
|
||||
import { ChatBoxContext } from '../chat/ChatContainer/ChatBox/Provider';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
|
||||
type Props = BoxProps & {
|
||||
sourceName?: string;
|
||||
@@ -23,11 +25,19 @@ const RawSourceBox = ({
|
||||
}: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const { fileT } = useI18n();
|
||||
const { shareId, outLinkUid, chatType } = useContextSelector(ChatBoxContext, (v) => v);
|
||||
|
||||
const canPreview = !!sourceId && canView;
|
||||
|
||||
const icon = useMemo(() => getSourceNameIcon({ sourceId, sourceName }), [sourceId, sourceName]);
|
||||
const read = getCollectionSourceAndOpen(collectionId);
|
||||
const read = getCollectionSourceAndOpen({
|
||||
collectionId,
|
||||
authProps: {
|
||||
shareId,
|
||||
outLinkUid
|
||||
},
|
||||
isShare: chatType === 'share'
|
||||
});
|
||||
|
||||
return (
|
||||
<MyTooltip
|
||||
|
||||
@@ -5,12 +5,15 @@ import { DatasetCollectionTypeEnum } from '@fastgpt/global/core/dataset/constant
|
||||
import { createFileToken } from '@fastgpt/service/support/permission/controller';
|
||||
import { BucketNameEnum, ReadFileBaseUrl } from '@fastgpt/global/common/file/constants';
|
||||
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { AuthOutLinkProps } from '@fastgpt/global/support/outLink/api';
|
||||
import { authOutLink } from '@/service/support/permission/auth/outLink';
|
||||
|
||||
export type readCollectionSourceQuery = {
|
||||
export type readCollectionSourceQuery = {};
|
||||
|
||||
export type readCollectionSourceBody = {
|
||||
collectionId: string;
|
||||
};
|
||||
|
||||
export type readCollectionSourceBody = {};
|
||||
isShare?: boolean;
|
||||
} & AuthOutLinkProps;
|
||||
|
||||
export type readCollectionSourceResponse = {
|
||||
type: 'url';
|
||||
@@ -20,11 +23,17 @@ export type readCollectionSourceResponse = {
|
||||
async function handler(
|
||||
req: ApiRequestProps<readCollectionSourceBody, readCollectionSourceQuery>
|
||||
): Promise<readCollectionSourceResponse> {
|
||||
const { isShare, outLinkUid, shareId } = req.body;
|
||||
|
||||
if (isShare) {
|
||||
await authOutLink({ shareId, outLinkUid });
|
||||
}
|
||||
|
||||
const { collection, teamId, tmbId } = await authDatasetCollection({
|
||||
req,
|
||||
authToken: true,
|
||||
authApiKey: true,
|
||||
collectionId: req.query.collectionId,
|
||||
collectionId: req.body.collectionId,
|
||||
per: ReadPermissionVal
|
||||
});
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ export type OutLinkUpdateResponse = {};
|
||||
async function handler(
|
||||
req: ApiRequestProps<OutLinkUpdateBody, OutLinkUpdateQuery>
|
||||
): Promise<OutLinkUpdateResponse> {
|
||||
const { _id, name, responseDetail, limit, app } = req.body;
|
||||
const { _id, name, responseDetail, limit, app, showCompleteQuote, showNodeStatus } = req.body;
|
||||
|
||||
if (!_id) {
|
||||
return Promise.reject(CommonErrEnum.missingParams);
|
||||
@@ -35,6 +35,8 @@ async function handler(
|
||||
await MongoOutLink.findByIdAndUpdate(_id, {
|
||||
name,
|
||||
responseDetail,
|
||||
showCompleteQuote,
|
||||
showNodeStatus,
|
||||
limit,
|
||||
app
|
||||
});
|
||||
|
||||
@@ -83,6 +83,8 @@ type AuthResponseType = {
|
||||
user: UserModelSchema;
|
||||
app: AppSchema;
|
||||
responseDetail?: boolean;
|
||||
showNodeStatus?: boolean;
|
||||
showCompleteQuote?: boolean;
|
||||
authType: `${AuthUserTypeEnum}`;
|
||||
apikey?: string;
|
||||
canWrite: boolean;
|
||||
@@ -160,7 +162,8 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
sourceName,
|
||||
apikey,
|
||||
canWrite,
|
||||
outLinkUserId = customUid
|
||||
outLinkUserId = customUid,
|
||||
showNodeStatus
|
||||
} = await (async () => {
|
||||
// share chat
|
||||
if (shareId && outLinkUid) {
|
||||
@@ -256,7 +259,8 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
res,
|
||||
detail,
|
||||
streamResponse: stream,
|
||||
id: chatId
|
||||
id: chatId,
|
||||
showNodeStatus
|
||||
});
|
||||
|
||||
/* start flow controller */
|
||||
@@ -461,7 +465,7 @@ const authShareChat = async ({
|
||||
shareId: string;
|
||||
chatId?: string;
|
||||
}): Promise<AuthResponseType> => {
|
||||
const { teamId, tmbId, user, appId, authType, responseDetail, uid, sourceName } =
|
||||
const { teamId, tmbId, user, appId, authType, responseDetail, showNodeStatus, uid, sourceName } =
|
||||
await authOutLinkChatStart(data);
|
||||
const app = await MongoApp.findById(appId).lean();
|
||||
|
||||
@@ -485,7 +489,8 @@ const authShareChat = async ({
|
||||
apikey: '',
|
||||
authType,
|
||||
canWrite: false,
|
||||
outLinkUserId: uid
|
||||
outLinkUserId: uid,
|
||||
showNodeStatus
|
||||
};
|
||||
};
|
||||
const authTeamSpaceChat = async ({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import {
|
||||
Flex,
|
||||
Box,
|
||||
@@ -184,6 +184,8 @@ const Share = ({ appId }: { appId: string; type: PublishChannelEnum }) => {
|
||||
_id: item._id,
|
||||
name: item.name,
|
||||
responseDetail: item.responseDetail,
|
||||
showCompleteQuote: item.showCompleteQuote,
|
||||
showNodeStatus: item.showNodeStatus,
|
||||
limit: item.limit
|
||||
})
|
||||
},
|
||||
@@ -272,11 +274,27 @@ function EditLinkModal({
|
||||
const {
|
||||
register,
|
||||
setValue,
|
||||
watch,
|
||||
handleSubmit: submitShareChat
|
||||
} = useForm({
|
||||
defaultValues: defaultData
|
||||
});
|
||||
|
||||
const responseDetail = watch('responseDetail');
|
||||
const showCompleteQuote = watch('showCompleteQuote');
|
||||
|
||||
useEffect(() => {
|
||||
if (!responseDetail) {
|
||||
setValue('showCompleteQuote', false);
|
||||
}
|
||||
}, [responseDetail, setValue]);
|
||||
|
||||
useEffect(() => {
|
||||
if (showCompleteQuote) {
|
||||
setValue('responseDetail', true);
|
||||
}
|
||||
}, [showCompleteQuote, setValue]);
|
||||
|
||||
const isEdit = useMemo(() => !!defaultData._id, [defaultData]);
|
||||
|
||||
const { mutate: onclickCreate, isLoading: creating } = useRequest({
|
||||
@@ -302,100 +320,130 @@ function EditLinkModal({
|
||||
isOpen={true}
|
||||
iconSrc="/imgs/modal/shareFill.svg"
|
||||
title={isEdit ? publishT('edit_link') : publishT('create_link')}
|
||||
w={'53.125rem'}
|
||||
>
|
||||
<ModalBody>
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel flex={'0 0 90px'}>{t('common:Name')}</FormLabel>
|
||||
<Input
|
||||
placeholder={publishT('link_name')}
|
||||
maxLength={20}
|
||||
{...register('name', {
|
||||
required: t('common:common.name_is_empty') || 'name_is_empty'
|
||||
})}
|
||||
/>
|
||||
</Flex>
|
||||
{feConfigs?.isPlus && (
|
||||
<>
|
||||
<ModalBody p={6}>
|
||||
<Flex flexDir={['column', 'row']}>
|
||||
<Box pr={[0, 6]} borderRight={['0px', '1px']} borderColor={['', 'myGray.150']}>
|
||||
<Box fontSize={'sm'} fontWeight={'500'} color={'myGray.600'}>
|
||||
{t('publish:basic_info')}
|
||||
</Box>
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<FormLabel flex={'0 0 90px'} alignItems={'center'}>
|
||||
{t('common:common.Expired Time')}
|
||||
</FormLabel>
|
||||
<FormLabel flex={'0 0 90px'}>{t('common:Name')}</FormLabel>
|
||||
<Input
|
||||
type="datetime-local"
|
||||
defaultValue={
|
||||
defaultData.limit?.expiredTime
|
||||
? dayjs(defaultData.limit?.expiredTime).format('YYYY-MM-DDTHH:mm')
|
||||
: ''
|
||||
}
|
||||
onChange={(e) => {
|
||||
setValue('limit.expiredTime', new Date(e.target.value));
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
||||
<FormLabel>QPM</FormLabel>
|
||||
<QuestionTip ml={1} label={publishT('qpm_tips' || '')}></QuestionTip>
|
||||
</Flex>
|
||||
<Input
|
||||
max={1000}
|
||||
{...register('limit.QPM', {
|
||||
min: 0,
|
||||
max: 1000,
|
||||
valueAsNumber: true,
|
||||
required: publishT('qpm_is_empty') || ''
|
||||
placeholder={publishT('link_name')}
|
||||
maxLength={20}
|
||||
{...register('name', {
|
||||
required: t('common:common.name_is_empty') || 'name_is_empty'
|
||||
})}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
||||
<FormLabel>{t('common:support.outlink.Max usage points')}</FormLabel>
|
||||
{feConfigs?.isPlus && (
|
||||
<>
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<FormLabel flex={'0 0 90px'} alignItems={'center'}>
|
||||
{t('common:common.Expired Time')}
|
||||
</FormLabel>
|
||||
<Input
|
||||
type="datetime-local"
|
||||
defaultValue={
|
||||
defaultData.limit?.expiredTime
|
||||
? dayjs(defaultData.limit?.expiredTime).format('YYYY-MM-DDTHH:mm')
|
||||
: ''
|
||||
}
|
||||
onChange={(e) => {
|
||||
setValue('limit.expiredTime', new Date(e.target.value));
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
||||
<FormLabel>QPM</FormLabel>
|
||||
<QuestionTip ml={1} label={publishT('qpm_tips' || '')}></QuestionTip>
|
||||
</Flex>
|
||||
<Input
|
||||
max={1000}
|
||||
{...register('limit.QPM', {
|
||||
min: 0,
|
||||
max: 1000,
|
||||
valueAsNumber: true,
|
||||
required: publishT('qpm_is_empty') || ''
|
||||
})}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
||||
<FormLabel>{t('common:support.outlink.Max usage points')}</FormLabel>
|
||||
<QuestionTip
|
||||
ml={1}
|
||||
label={t('common:support.outlink.Max usage points tip')}
|
||||
></QuestionTip>
|
||||
</Flex>
|
||||
<Input
|
||||
{...register('limit.maxUsagePoints', {
|
||||
min: -1,
|
||||
max: 10000000,
|
||||
valueAsNumber: true,
|
||||
required: true
|
||||
})}
|
||||
/>
|
||||
</Flex>
|
||||
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
||||
<FormLabel>{publishT('token_auth')}</FormLabel>
|
||||
<QuestionTip ml={1} label={publishT('token_auth_tips') || ''}></QuestionTip>
|
||||
</Flex>
|
||||
<Input
|
||||
placeholder={publishT('token_auth_tips') || ''}
|
||||
fontSize={'sm'}
|
||||
{...register('limit.hookUrl')}
|
||||
/>
|
||||
</Flex>
|
||||
<Link
|
||||
href={getDocPath('/docs/development/openapi/share')}
|
||||
target={'_blank'}
|
||||
fontSize={'xs'}
|
||||
color={'myGray.500'}
|
||||
>
|
||||
{publishT('token_auth_use_cases')}
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
<Box pl={[0, 6]} flexGrow={1} pt={[6, 0]}>
|
||||
<Box fontSize={'sm'} fontWeight={'500'} color={'myGray.600'}>
|
||||
{t('publish:config')}
|
||||
</Box>
|
||||
<Flex alignItems={'center'} mt={4} justify={'space-between'}>
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel>{t('publish:show_node')}</FormLabel>
|
||||
</Flex>
|
||||
<Switch {...register('showNodeStatus')} />
|
||||
</Flex>
|
||||
|
||||
<Flex alignItems={'center'} mt={4} justify={'space-between'}>
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel>{t('common:support.outlink.share.Response Quote')}</FormLabel>
|
||||
<QuestionTip
|
||||
ml={1}
|
||||
label={t('common:support.outlink.Max usage points tip')}
|
||||
label={t('common:support.outlink.share.Response Quote tips' || '')}
|
||||
></QuestionTip>
|
||||
</Flex>
|
||||
<Input
|
||||
{...register('limit.maxUsagePoints', {
|
||||
min: -1,
|
||||
max: 10000000,
|
||||
valueAsNumber: true,
|
||||
required: true
|
||||
})}
|
||||
/>
|
||||
<Switch {...register('responseDetail')} isChecked={responseDetail} />
|
||||
</Flex>
|
||||
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
||||
<FormLabel>{publishT('token_auth')}</FormLabel>
|
||||
<QuestionTip ml={1} label={publishT('token_auth_tips') || ''}></QuestionTip>
|
||||
<Flex alignItems={'center'} mt={4} justify={'space-between'}>
|
||||
<Flex alignItems={'center'}>
|
||||
<FormLabel>{t('common:support.outlink.share.show_complete_quote')}</FormLabel>
|
||||
<QuestionTip
|
||||
ml={1}
|
||||
label={t('common:support.outlink.share.show_complete_quote_tips' || '')}
|
||||
></QuestionTip>
|
||||
</Flex>
|
||||
<Input
|
||||
placeholder={publishT('token_auth_tips') || ''}
|
||||
fontSize={'sm'}
|
||||
{...register('limit.hookUrl')}
|
||||
/>
|
||||
<Switch {...register('showCompleteQuote')} isChecked={showCompleteQuote} />
|
||||
</Flex>
|
||||
<Link
|
||||
href={getDocPath('/docs/development/openapi/share')}
|
||||
target={'_blank'}
|
||||
fontSize={'xs'}
|
||||
color={'myGray.500'}
|
||||
>
|
||||
{publishT('token_auth_use_cases')}
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Flex alignItems={'center'} mt={4}>
|
||||
<Flex flex={'0 0 90px'} alignItems={'center'}>
|
||||
<FormLabel>{t('common:support.outlink.share.Response Quote')}</FormLabel>
|
||||
<QuestionTip
|
||||
ml={1}
|
||||
label={t('support.outlink.share.Response Quote tips' || '')}
|
||||
></QuestionTip>
|
||||
</Flex>
|
||||
<Switch {...register('responseDetail')} />
|
||||
</Box>
|
||||
</Flex>
|
||||
</ModalBody>
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ type Props = {
|
||||
shareId: string;
|
||||
authToken: string;
|
||||
customUid: string;
|
||||
showCompleteQuote: boolean;
|
||||
};
|
||||
|
||||
const OutLink = (
|
||||
@@ -364,6 +365,7 @@ const OutLink = (
|
||||
chatId={chatId}
|
||||
shareId={shareId}
|
||||
outLinkUid={outLinkUid}
|
||||
chatType="share"
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
@@ -375,13 +377,13 @@ const OutLink = (
|
||||
};
|
||||
|
||||
const Render = (props: Props) => {
|
||||
const { shareId, authToken, customUid } = props;
|
||||
const { shareId, authToken, customUid, showCompleteQuote } = props;
|
||||
const { localUId, loaded } = useShareChatStore();
|
||||
const [isLoaded, setIsLoaded] = useState(false);
|
||||
|
||||
const contextParams = useMemo(() => {
|
||||
return { shareId, outLinkUid: authToken || customUid || localUId };
|
||||
}, [authToken, customUid, localUId, shareId]);
|
||||
return { shareId, outLinkUid: authToken || localUId || customUid, showCompleteQuote };
|
||||
}, [authToken, customUid, localUId, shareId, showCompleteQuote]);
|
||||
|
||||
useMount(() => {
|
||||
setIsLoaded(true);
|
||||
@@ -415,7 +417,7 @@ export async function getServerSideProps(context: any) {
|
||||
{
|
||||
shareId
|
||||
},
|
||||
'appId'
|
||||
'appId showCompleteQuote'
|
||||
)
|
||||
.populate('appId', 'name avatar intro')
|
||||
.lean()) as OutLinkWithAppType;
|
||||
@@ -431,6 +433,7 @@ export async function getServerSideProps(context: any) {
|
||||
appName: app?.appId?.name ?? 'AI',
|
||||
appAvatar: app?.appId?.avatar ?? '',
|
||||
appIntro: app?.appId?.intro ?? 'AI',
|
||||
showCompleteQuote: app?.showCompleteQuote ?? false,
|
||||
shareId: shareId ?? '',
|
||||
authToken: authToken ?? '',
|
||||
customUid,
|
||||
|
||||
@@ -296,6 +296,7 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
|
||||
chatId={chatId}
|
||||
teamId={teamId}
|
||||
teamToken={teamToken}
|
||||
chatType="team"
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
@@ -10,6 +10,8 @@ import { formatTime2YMDHM } from '@fastgpt/global/common/string/time';
|
||||
import { DatasetCollectionTypeMap, TrainingTypeMap } from '@fastgpt/global/core/dataset/constants';
|
||||
import { getCollectionSourceAndOpen } from '@/web/core/dataset/hooks/readCollectionSource';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
import { ChatBoxContext } from '@/components/core/chat/ChatContainer/ChatBox/Provider';
|
||||
|
||||
const MetaDataCard = ({ datasetId }: { datasetId: string }) => {
|
||||
const { t } = useTranslation();
|
||||
@@ -18,7 +20,17 @@ const MetaDataCard = ({ datasetId }: { datasetId: string }) => {
|
||||
collectionId: string;
|
||||
datasetId: string;
|
||||
};
|
||||
const readSource = getCollectionSourceAndOpen(collectionId);
|
||||
|
||||
const { shareId, outLinkUid, chatType } = useContextSelector(ChatBoxContext, (v) => v);
|
||||
|
||||
const readSource = getCollectionSourceAndOpen({
|
||||
collectionId,
|
||||
authProps: {
|
||||
shareId,
|
||||
outLinkUid
|
||||
},
|
||||
isShare: chatType === 'share'
|
||||
});
|
||||
const { data: collection, loading: isLoading } = useRequest2(
|
||||
() => getDatasetCollectionById(collectionId),
|
||||
{
|
||||
|
||||
@@ -3,7 +3,8 @@ import type {
|
||||
AuthOutLinkChatProps,
|
||||
AuthOutLinkLimitProps,
|
||||
AuthOutLinkInitProps,
|
||||
AuthOutLinkResponse
|
||||
AuthOutLinkResponse,
|
||||
AuthOutLinkProps
|
||||
} from '@fastgpt/global/support/outLink/api.d';
|
||||
import { authOutLinkValid } from '@fastgpt/service/support/permission/publish/authLink';
|
||||
import { getUserChatInfoAndAuthTeamPoints } from '@/service/support/permission/auth/team';
|
||||
@@ -23,10 +24,7 @@ export function authOutLinkChatLimit(data: AuthOutLinkLimitProps): Promise<AuthO
|
||||
export const authOutLink = async ({
|
||||
shareId,
|
||||
outLinkUid
|
||||
}: {
|
||||
shareId?: string;
|
||||
outLinkUid?: string;
|
||||
}): Promise<{
|
||||
}: AuthOutLinkProps): Promise<{
|
||||
uid: string;
|
||||
appId: string;
|
||||
shareChat: OutLinkSchema;
|
||||
@@ -70,6 +68,7 @@ export async function authOutLinkChatStart({
|
||||
tmbId: shareChat.tmbId,
|
||||
authType: AuthUserTypeEnum.token,
|
||||
responseDetail: shareChat.responseDetail,
|
||||
showNodeStatus: shareChat.showNodeStatus,
|
||||
user,
|
||||
appId,
|
||||
uid
|
||||
|
||||
@@ -23,6 +23,8 @@ export const defaultApp: AppDetailType = {
|
||||
export const defaultOutLinkForm: OutLinkEditType = {
|
||||
name: '',
|
||||
responseDetail: false,
|
||||
showNodeStatus: false,
|
||||
showCompleteQuote: false,
|
||||
limit: {
|
||||
QPM: 100,
|
||||
maxUsagePoints: -1
|
||||
|
||||
@@ -16,7 +16,7 @@ import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||
import { useScrollPagination } from '@fastgpt/web/hooks/useScrollPagination';
|
||||
|
||||
type ChatContextValueType = {
|
||||
params: Record<string, string | number>;
|
||||
params: Record<string, string | number | boolean>;
|
||||
};
|
||||
type ChatContextType = {
|
||||
chatId: string;
|
||||
@@ -44,6 +44,7 @@ type ChatContextType = {
|
||||
isLoading: boolean;
|
||||
histories: ChatHistoryItemType[];
|
||||
onUpdateHistoryTitle: ({ chatId, newTitle }: { chatId: string; newTitle: string }) => void;
|
||||
showCompleteQuote: boolean;
|
||||
};
|
||||
|
||||
export const ChatContext = createContext<ChatContextType>({
|
||||
@@ -85,7 +86,8 @@ export const ChatContext = createContext<ChatContextType>({
|
||||
onChangeAppId: function (appId: string): void {
|
||||
throw new Error('Function not implemented.');
|
||||
},
|
||||
isLoading: false
|
||||
isLoading: false,
|
||||
showCompleteQuote: true
|
||||
});
|
||||
|
||||
const ChatContextProvider = ({
|
||||
@@ -94,6 +96,7 @@ const ChatContextProvider = ({
|
||||
}: ChatContextValueType & { children: ReactNode }) => {
|
||||
const router = useRouter();
|
||||
const { chatId = '' } = router.query as { chatId: string };
|
||||
const { showCompleteQuote }: { showCompleteQuote?: boolean } = params;
|
||||
|
||||
const forbidLoadChat = useRef(false);
|
||||
|
||||
@@ -225,7 +228,8 @@ const ChatContextProvider = ({
|
||||
ScrollData,
|
||||
loadHistories,
|
||||
histories,
|
||||
onUpdateHistoryTitle
|
||||
onUpdateHistoryTitle,
|
||||
showCompleteQuote: showCompleteQuote ?? true
|
||||
};
|
||||
return <ChatContext.Provider value={contextValue}>{children}</ChatContext.Provider>;
|
||||
};
|
||||
|
||||
@@ -56,6 +56,7 @@ import type { UpdateDatasetDataProps } from '@fastgpt/global/core/dataset/contro
|
||||
import type { DatasetFolderCreateBody } from '@/pages/api/core/dataset/folder/create';
|
||||
import type { PaginationProps, PaginationResponse } from '@fastgpt/web/common/fetch/type';
|
||||
import type { GetScrollCollectionsProps } from '@/pages/api/core/dataset/collection/scrollList';
|
||||
import { AuthOutLinkProps } from '@fastgpt/global/support/outLink/api';
|
||||
|
||||
/* ======================== dataset ======================= */
|
||||
export const getDatasets = (data: GetDatasetListBody) =>
|
||||
@@ -197,5 +198,6 @@ export const getPreviewChunks = (data: PostPreviewFilesChunksProps) =>
|
||||
POST<PreviewChunksResponse>('/core/dataset/file/getPreviewChunks', data);
|
||||
|
||||
/* ================== read source ======================== */
|
||||
export const getCollectionSource = (collectionId: string) =>
|
||||
GET<readCollectionSourceResponse>('/core/dataset/collection/read', { collectionId });
|
||||
export const getCollectionSource = (
|
||||
data: { collectionId: string; isShare?: boolean } & AuthOutLinkProps
|
||||
) => POST<readCollectionSourceResponse>('/core/dataset/collection/read', data);
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
import { authOutLink } from '@/service/support/permission/auth/outLink';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { getCollectionSource } from '@/web/core/dataset/api';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { AuthOutLinkProps } from '@fastgpt/global/support/outLink/api';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
export function getCollectionSourceAndOpen(collectionId: string) {
|
||||
export function getCollectionSourceAndOpen({
|
||||
collectionId,
|
||||
authProps,
|
||||
isShare
|
||||
}: {
|
||||
collectionId: string;
|
||||
authProps: AuthOutLinkProps;
|
||||
isShare?: boolean;
|
||||
}) {
|
||||
const { toast } = useToast();
|
||||
const { t } = useTranslation();
|
||||
const { setLoading } = useSystemStore();
|
||||
@@ -12,7 +22,8 @@ export function getCollectionSourceAndOpen(collectionId: string) {
|
||||
return async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const { value: url } = await getCollectionSource(collectionId);
|
||||
|
||||
const { value: url } = await getCollectionSource({ collectionId, isShare, ...authProps });
|
||||
|
||||
if (!url) {
|
||||
throw new Error('No file found');
|
||||
|
||||
Reference in New Issue
Block a user