mirror of
https://github.com/labring/FastGPT.git
synced 2025-08-01 20:27:45 +00:00
v4.6 -1 (#459)
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { sseResponseEventEnum, TaskResponseKeyEnum } from '@/constants/chat';
|
||||
import { TaskResponseKeyEnum } from '@fastgpt/global/core/chat/constants';
|
||||
import { sseResponseEventEnum } from '@fastgpt/service/common/response/constant';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { parseStreamChunk, SSEParseData } from '@/utils/sse';
|
||||
import type { ChatHistoryItemResType } from '@/types/chat';
|
||||
import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/api.d';
|
||||
import { StartChatFnProps } from '@/components/ChatBox';
|
||||
import { getToken } from '@/web/support/user/auth';
|
||||
|
||||
|
@@ -1,34 +0,0 @@
|
||||
import { GET, POST } from '@/web/common/api/request';
|
||||
import type { CreateTrainingBillType } from '@fastgpt/global/common/bill/types/billReq.d';
|
||||
import type { PaySchema } from '@fastgpt/global/support/wallet/type.d';
|
||||
import type { PagingData, RequestPaging } from '@/types';
|
||||
import { UserBillType } from '@/types/user';
|
||||
import { delay } from '@/utils/tools';
|
||||
|
||||
export const getUserBills = (data: RequestPaging) =>
|
||||
POST<PagingData<UserBillType>>(`/user/getBill`, data);
|
||||
|
||||
export const postCreateTrainingBill = (data: CreateTrainingBillType) =>
|
||||
POST<string>(`/common/bill/createTrainingBill`, data);
|
||||
|
||||
export const getPayOrders = () => GET<PaySchema[]>(`/user/getPayOrders`);
|
||||
|
||||
export const getPayCode = (amount: number) =>
|
||||
GET<{
|
||||
codeUrl: string;
|
||||
payId: string;
|
||||
}>(`/plusApi/support/user/pay/getPayCode`, { amount });
|
||||
|
||||
export const checkPayResult = (payId: string) =>
|
||||
GET<number>(`/plusApi/support/user/pay/checkPayResult`, { payId }).then(() => {
|
||||
async function startQueue() {
|
||||
try {
|
||||
await GET('/user/account/paySuccess');
|
||||
} catch (error) {
|
||||
await delay(1000);
|
||||
startQueue();
|
||||
}
|
||||
}
|
||||
startQueue();
|
||||
return 'success';
|
||||
});
|
17
projects/app/src/web/common/file/api.ts
Normal file
17
projects/app/src/web/common/file/api.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { GET, POST, PUT, DELETE } from '@/web/common/api/request';
|
||||
import { AxiosProgressEvent } from 'axios';
|
||||
|
||||
export const postUploadImg = (base64Img: string) =>
|
||||
POST<string>('/common/file/uploadImage', { base64Img });
|
||||
|
||||
export const postUploadFiles = (
|
||||
data: FormData,
|
||||
onUploadProgress: (progressEvent: AxiosProgressEvent) => void
|
||||
) =>
|
||||
POST<string[]>('/common/file/upload', data, {
|
||||
timeout: 60000,
|
||||
onUploadProgress,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data; charset=utf-8'
|
||||
}
|
||||
});
|
104
projects/app/src/web/common/file/controller.ts
Normal file
104
projects/app/src/web/common/file/controller.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import { postUploadImg, postUploadFiles } from '@/web/common/file/api';
|
||||
import { BucketNameEnum } from '@fastgpt/global/common/file/constants';
|
||||
|
||||
/**
|
||||
* upload file to mongo gridfs
|
||||
*/
|
||||
export const uploadFiles = ({
|
||||
files,
|
||||
bucketName,
|
||||
metadata = {},
|
||||
percentListen
|
||||
}: {
|
||||
files: File[];
|
||||
bucketName: `${BucketNameEnum}`;
|
||||
metadata?: Record<string, any>;
|
||||
percentListen?: (percent: number) => void;
|
||||
}) => {
|
||||
const form = new FormData();
|
||||
form.append('metadata', JSON.stringify(metadata));
|
||||
form.append('bucketName', bucketName);
|
||||
files.forEach((file) => {
|
||||
form.append('file', file, encodeURIComponent(file.name));
|
||||
});
|
||||
return postUploadFiles(form, (e) => {
|
||||
if (!e.total) return;
|
||||
|
||||
const percent = Math.round((e.loaded / e.total) * 100);
|
||||
percentListen && percentListen(percent);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* compress image. response base64
|
||||
* @param maxSize The max size of the compressed image
|
||||
*/
|
||||
export const compressImgAndUpload = ({
|
||||
file,
|
||||
maxW = 200,
|
||||
maxH = 200,
|
||||
maxSize = 1024 * 100
|
||||
}: {
|
||||
file: File;
|
||||
maxW?: number;
|
||||
maxH?: number;
|
||||
maxSize?: number;
|
||||
}) =>
|
||||
new Promise<string>((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = async () => {
|
||||
const img = new Image();
|
||||
// @ts-ignore
|
||||
img.src = reader.result;
|
||||
img.onload = async () => {
|
||||
let width = img.width;
|
||||
let height = img.height;
|
||||
|
||||
if (width > height) {
|
||||
if (width > maxW) {
|
||||
height *= maxW / width;
|
||||
width = maxW;
|
||||
}
|
||||
} else {
|
||||
if (height > maxH) {
|
||||
width *= maxH / height;
|
||||
height = maxH;
|
||||
}
|
||||
}
|
||||
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
if (!ctx) {
|
||||
return reject('压缩图片异常');
|
||||
}
|
||||
|
||||
ctx.drawImage(img, 0, 0, width, height);
|
||||
const compressedDataUrl = canvas.toDataURL(file.type, 0.8);
|
||||
// 移除 canvas 元素
|
||||
canvas.remove();
|
||||
|
||||
if (compressedDataUrl.length > maxSize) {
|
||||
return reject('图片太大了');
|
||||
}
|
||||
|
||||
const src = await (async () => {
|
||||
try {
|
||||
const src = await postUploadImg(compressedDataUrl);
|
||||
return src;
|
||||
} catch (error) {
|
||||
return compressedDataUrl;
|
||||
}
|
||||
})();
|
||||
|
||||
resolve(src);
|
||||
};
|
||||
};
|
||||
reader.onerror = (err) => {
|
||||
console.log(err);
|
||||
reject('压缩图片异常');
|
||||
};
|
||||
});
|
@@ -1,27 +1,6 @@
|
||||
import mammoth from 'mammoth';
|
||||
import Papa from 'papaparse';
|
||||
import { postUploadImg, postUploadFiles, getFileViewUrl } from '@/web/common/system/api';
|
||||
|
||||
/**
|
||||
* upload file to mongo gridfs
|
||||
*/
|
||||
export const uploadFiles = (
|
||||
files: File[],
|
||||
metadata: Record<string, any> = {},
|
||||
percentListen?: (percent: number) => void
|
||||
) => {
|
||||
const form = new FormData();
|
||||
form.append('metadata', JSON.stringify(metadata));
|
||||
files.forEach((file) => {
|
||||
form.append('file', file, encodeURIComponent(file.name));
|
||||
});
|
||||
return postUploadFiles(form, (e) => {
|
||||
if (!e.total) return;
|
||||
|
||||
const percent = Math.round((e.loaded / e.total) * 100);
|
||||
percentListen && percentListen(percent);
|
||||
});
|
||||
};
|
||||
import { postUploadImg } from '@/web/common/file/api';
|
||||
|
||||
/**
|
||||
* 读取 txt 文件内容
|
||||
@@ -147,7 +126,7 @@ export const readCsvContent = async (file: File) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* file download
|
||||
* file download by text
|
||||
*/
|
||||
export const fileDownload = ({
|
||||
text,
|
||||
@@ -169,15 +148,9 @@ export const fileDownload = ({
|
||||
// 添加链接到页面并触发下载
|
||||
document.body.appendChild(downloadLink);
|
||||
downloadLink.click();
|
||||
document.body.removeChild(downloadLink);
|
||||
document.body?.removeChild(downloadLink);
|
||||
};
|
||||
|
||||
export async function getFileAndOpen(fileId: string) {
|
||||
const url = await getFileViewUrl(fileId);
|
||||
const asPath = `${location.origin}${url}`;
|
||||
window.open(asPath, '_blank');
|
||||
}
|
||||
|
||||
export const fileToBase64 = (file: File) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
@@ -186,77 +159,3 @@ export const fileToBase64 = (file: File) => {
|
||||
reader.onerror = (error) => reject(error);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* compress image. response base64
|
||||
* @param maxSize The max size of the compressed image
|
||||
*/
|
||||
export const compressImg = ({
|
||||
file,
|
||||
maxW = 200,
|
||||
maxH = 200,
|
||||
maxSize = 1024 * 100
|
||||
}: {
|
||||
file: File;
|
||||
maxW?: number;
|
||||
maxH?: number;
|
||||
maxSize?: number;
|
||||
}) =>
|
||||
new Promise<string>((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = async () => {
|
||||
const img = new Image();
|
||||
// @ts-ignore
|
||||
img.src = reader.result;
|
||||
img.onload = async () => {
|
||||
let width = img.width;
|
||||
let height = img.height;
|
||||
|
||||
if (width > height) {
|
||||
if (width > maxW) {
|
||||
height *= maxW / width;
|
||||
width = maxW;
|
||||
}
|
||||
} else {
|
||||
if (height > maxH) {
|
||||
width *= maxH / height;
|
||||
height = maxH;
|
||||
}
|
||||
}
|
||||
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
if (!ctx) {
|
||||
return reject('压缩图片异常');
|
||||
}
|
||||
|
||||
ctx.drawImage(img, 0, 0, width, height);
|
||||
const compressedDataUrl = canvas.toDataURL(file.type, 0.8);
|
||||
// 移除 canvas 元素
|
||||
canvas.remove();
|
||||
|
||||
if (compressedDataUrl.length > maxSize) {
|
||||
return reject('图片太大了');
|
||||
}
|
||||
|
||||
const src = await (async () => {
|
||||
try {
|
||||
const src = await postUploadImg(compressedDataUrl);
|
||||
return src;
|
||||
} catch (error) {
|
||||
return compressedDataUrl;
|
||||
}
|
||||
})();
|
||||
|
||||
resolve(src);
|
||||
};
|
||||
};
|
||||
reader.onerror = (err) => {
|
||||
console.log(err);
|
||||
reject('压缩图片异常');
|
||||
};
|
||||
});
|
||||
|
@@ -11,13 +11,14 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
export const useConfirm = (props: {
|
||||
export const useConfirm = (props?: {
|
||||
title?: string | null;
|
||||
content?: string | null;
|
||||
bg?: string;
|
||||
showCancel?: boolean;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { title = t('Warning'), content, bg } = props;
|
||||
const { title = t('Warning'), content, bg, showCancel = true } = props || {};
|
||||
const [customContent, setCustomContent] = useState(content);
|
||||
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
@@ -52,18 +53,23 @@ export const useConfirm = (props: {
|
||||
{title}
|
||||
</AlertDialogHeader>
|
||||
|
||||
<AlertDialogBody>{customContent}</AlertDialogBody>
|
||||
<AlertDialogBody whiteSpace={'pre-wrap'} py={0}>
|
||||
{customContent}
|
||||
</AlertDialogBody>
|
||||
|
||||
<AlertDialogFooter>
|
||||
<Button
|
||||
variant={'base'}
|
||||
onClick={() => {
|
||||
onClose();
|
||||
typeof cancelCb.current === 'function' && cancelCb.current();
|
||||
}}
|
||||
>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
{showCancel && (
|
||||
<Button
|
||||
variant={'base'}
|
||||
onClick={() => {
|
||||
onClose();
|
||||
typeof cancelCb.current === 'function' && cancelCb.current();
|
||||
}}
|
||||
>
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Button
|
||||
{...(bg && { bg: `${bg} !important` })}
|
||||
ml={4}
|
||||
|
@@ -26,7 +26,7 @@ export const useCopyData = () => {
|
||||
document.body.appendChild(textarea);
|
||||
textarea.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(textarea);
|
||||
document.body?.removeChild(textarea);
|
||||
}
|
||||
|
||||
toast({
|
||||
|
@@ -1,15 +0,0 @@
|
||||
import { POST } from '@fastgpt/service/common/api/plusRequest';
|
||||
|
||||
export const postTextCensor = (data: { text: string }) =>
|
||||
POST<{ code?: number; message: string }>('/common/censor/text_baidu', data)
|
||||
.then((res) => {
|
||||
if (res?.code === 5000) {
|
||||
return Promise.reject(res);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err?.code === 5000) {
|
||||
return Promise.reject(err.message);
|
||||
}
|
||||
return Promise.resolve('');
|
||||
});
|
@@ -1,22 +1,4 @@
|
||||
import { GET, POST, PUT, DELETE } from '@/web/common/api/request';
|
||||
import type { InitDateResponse } from '@/global/common/api/systemRes';
|
||||
import { AxiosProgressEvent } from 'axios';
|
||||
|
||||
export const getSystemInitData = () => GET<InitDateResponse>('/system/getInitData');
|
||||
|
||||
export const postUploadImg = (base64Img: string) =>
|
||||
POST<string>('/system/file/uploadImage', { base64Img });
|
||||
|
||||
export const postUploadFiles = (
|
||||
data: FormData,
|
||||
onUploadProgress: (progressEvent: AxiosProgressEvent) => void
|
||||
) =>
|
||||
POST<string[]>('/system/file/upload', data, {
|
||||
timeout: 60000,
|
||||
onUploadProgress,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data; charset=utf-8'
|
||||
}
|
||||
});
|
||||
|
||||
export const getFileViewUrl = (fileId: string) => GET<string>('/system/file/readUrl', { fileId });
|
||||
|
@@ -9,7 +9,7 @@ import {
|
||||
defaultExtractModels,
|
||||
defaultQGModels,
|
||||
defaultVectorModels
|
||||
} from '@/constants/model';
|
||||
} from '@fastgpt/global/core/ai/model';
|
||||
|
||||
export let feConfigs: FeConfigsType = {};
|
||||
export let priceMd = '';
|
||||
|
@@ -2,7 +2,7 @@ import { create } from 'zustand';
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import axios from 'axios';
|
||||
import { OAuthEnum } from '@/constants/user';
|
||||
import { OAuthEnum } from '@fastgpt/global/support/user/constant';
|
||||
|
||||
type LoginStoreType = { provider: `${OAuthEnum}`; lastRoute: string; state: string };
|
||||
|
||||
|
@@ -1,73 +1,85 @@
|
||||
import { useState, useCallback, useEffect, useMemo } from 'react';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { getChatItemSpeech } from '@/web/core/chat/api';
|
||||
import { AppTTSConfigType } from '@/types/app';
|
||||
import { TTSTypeEnum } from '@/constants/app';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
export const useAudioPlay = (props?: { ttsUrl?: string }) => {
|
||||
const { ttsUrl } = props || {};
|
||||
export const useAudioPlay = (props?: { ttsConfig?: AppTTSConfigType }) => {
|
||||
const { t } = useTranslation();
|
||||
const { ttsConfig } = props || {};
|
||||
const { toast } = useToast();
|
||||
const [audio, setAudio] = useState<HTMLAudioElement>();
|
||||
const [audioLoading, setAudioLoading] = useState(false);
|
||||
const [audioPlaying, setAudioPlaying] = useState(false);
|
||||
|
||||
// Check whether the voice is supported
|
||||
const hasAudio = useMemo(() => {
|
||||
if (ttsUrl) return true;
|
||||
if (ttsConfig?.type === TTSTypeEnum.none) return false;
|
||||
const voices = window.speechSynthesis?.getVoices?.() || []; // 获取语言包
|
||||
const voice = voices.find((item) => {
|
||||
return item.lang === 'zh-CN';
|
||||
});
|
||||
return !!voice;
|
||||
}, [ttsUrl]);
|
||||
}, [ttsConfig]);
|
||||
|
||||
const playAudio = useCallback(
|
||||
async (text: string) => {
|
||||
text = text.replace(/\\n/g, '\n');
|
||||
try {
|
||||
if (audio && ttsUrl) {
|
||||
setAudioLoading(true);
|
||||
const response = await fetch(ttsUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
text
|
||||
})
|
||||
}).then((res) => res.blob());
|
||||
const playAudio = async ({
|
||||
text,
|
||||
chatItemId,
|
||||
buffer
|
||||
}: {
|
||||
text: string;
|
||||
chatItemId?: string;
|
||||
buffer?: Buffer;
|
||||
}) => {
|
||||
text = text.replace(/\\n/g, '\n');
|
||||
try {
|
||||
// tts play
|
||||
if (audio && ttsConfig && ttsConfig?.type === TTSTypeEnum.model) {
|
||||
setAudioLoading(true);
|
||||
const { data } = buffer
|
||||
? { data: buffer }
|
||||
: await getChatItemSpeech({ chatItemId, ttsConfig, input: text });
|
||||
|
||||
const audioUrl = URL.createObjectURL(response);
|
||||
audio.src = audioUrl;
|
||||
audio.play();
|
||||
} else {
|
||||
// window speech
|
||||
window.speechSynthesis?.cancel();
|
||||
const msg = new SpeechSynthesisUtterance(text);
|
||||
const voices = window.speechSynthesis?.getVoices?.() || []; // 获取语言包
|
||||
const voice = voices.find((item) => {
|
||||
return item.lang === 'zh-CN';
|
||||
});
|
||||
if (voice) {
|
||||
msg.onstart = () => {
|
||||
setAudioPlaying(true);
|
||||
};
|
||||
msg.onend = () => {
|
||||
setAudioPlaying(false);
|
||||
msg.onstart = null;
|
||||
msg.onend = null;
|
||||
};
|
||||
msg.voice = voice;
|
||||
window.speechSynthesis?.speak(msg);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
toast({
|
||||
status: 'error',
|
||||
title: getErrText(error, '语音播报异常')
|
||||
const arrayBuffer = new Uint8Array(data).buffer;
|
||||
|
||||
const audioUrl = URL.createObjectURL(new Blob([arrayBuffer], { type: 'audio/mp3' }));
|
||||
|
||||
audio.src = audioUrl;
|
||||
audio.play();
|
||||
setAudioLoading(false);
|
||||
|
||||
return data;
|
||||
} else {
|
||||
// window speech
|
||||
window.speechSynthesis?.cancel();
|
||||
const msg = new SpeechSynthesisUtterance(text);
|
||||
const voices = window.speechSynthesis?.getVoices?.() || []; // 获取语言包
|
||||
const voice = voices.find((item) => {
|
||||
return item.lang === 'zh-CN';
|
||||
});
|
||||
if (voice) {
|
||||
msg.onstart = () => {
|
||||
setAudioPlaying(true);
|
||||
};
|
||||
msg.onend = () => {
|
||||
setAudioPlaying(false);
|
||||
msg.onstart = null;
|
||||
msg.onend = null;
|
||||
};
|
||||
msg.voice = voice;
|
||||
window.speechSynthesis?.speak(msg);
|
||||
}
|
||||
}
|
||||
setAudioLoading(false);
|
||||
},
|
||||
[audio, toast, ttsUrl]
|
||||
);
|
||||
} catch (error) {
|
||||
toast({
|
||||
status: 'error',
|
||||
title: getErrText(error, t('core.chat.Audio Speech Error'))
|
||||
});
|
||||
}
|
||||
setAudioLoading(false);
|
||||
};
|
||||
|
||||
const cancelAudio = useCallback(() => {
|
||||
if (audio) {
|
||||
@@ -78,14 +90,12 @@ export const useAudioPlay = (props?: { ttsUrl?: string }) => {
|
||||
setAudioPlaying(false);
|
||||
}, [audio]);
|
||||
|
||||
// listen ttsUrl update
|
||||
useEffect(() => {
|
||||
if (ttsUrl) {
|
||||
setAudio(new Audio());
|
||||
} else {
|
||||
setAudio(undefined);
|
||||
}
|
||||
}, [ttsUrl]);
|
||||
setAudio(new Audio());
|
||||
}, []);
|
||||
|
||||
// listen audio status
|
||||
useEffect(() => {
|
||||
if (audio) {
|
||||
audio.onplay = () => {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { GET, POST, PUT, DELETE } from '@/web/common/api/request';
|
||||
import type { CreateQuestionGuideParams } from '@/global/core/api/aiReq.d';
|
||||
import type { CreateQuestionGuideParams } from '@/global/core/ai/api.d';
|
||||
|
||||
export const postQuestionGuide = (data: CreateQuestionGuideParams, cancelToken: AbortController) =>
|
||||
POST<string[]>('/core/ai/agent/createQuestionGuide', data, { cancelToken });
|
||||
|
@@ -1,57 +1,56 @@
|
||||
import { GET, POST, DELETE, PUT } from '@/web/common/api/request';
|
||||
import type { AppSchema } from '@/types/mongoSchema';
|
||||
import type { AppListItemType, AppUpdateParams } from '@/types/app';
|
||||
import type { AppDetailType, AppListItemType } from '@fastgpt/global/core/app/type.d';
|
||||
import { RequestPaging } from '@/types/index';
|
||||
import { addDays } from 'date-fns';
|
||||
import type { GetAppChatLogsParams } from '@/global/core/api/appReq.d';
|
||||
import type { CreateAppParams } from '@/types/app';
|
||||
import type { CreateAppParams, AppUpdateParams } from '@fastgpt/global/core/app/api.d';
|
||||
|
||||
/**
|
||||
* 获取模型列表
|
||||
*/
|
||||
export const getMyApps = () => GET<AppListItemType[]>('/app/myApps');
|
||||
export const getMyApps = () => GET<AppListItemType[]>('/core/app/list');
|
||||
|
||||
/**
|
||||
* 创建一个模型
|
||||
*/
|
||||
export const postCreateApp = (data: CreateAppParams) => POST<string>('/app/create', data);
|
||||
export const postCreateApp = (data: CreateAppParams) => POST<string>('/core/app/create', data);
|
||||
|
||||
/**
|
||||
* 根据 ID 删除模型
|
||||
*/
|
||||
export const delModelById = (id: string) => DELETE(`/app/del?appId=${id}`);
|
||||
export const delModelById = (id: string) => DELETE(`/core/app/del?appId=${id}`);
|
||||
|
||||
/**
|
||||
* 根据 ID 获取模型
|
||||
*/
|
||||
export const getModelById = (id: string) => GET<AppSchema>(`/app/detail?appId=${id}`);
|
||||
export const getModelById = (id: string) => GET<AppDetailType>(`/core/app/detail?appId=${id}`);
|
||||
|
||||
/**
|
||||
* 根据 ID 更新模型
|
||||
*/
|
||||
export const putAppById = (id: string, data: AppUpdateParams) =>
|
||||
PUT(`/app/update?appId=${id}`, data);
|
||||
PUT(`/core/app/update?appId=${id}`, data);
|
||||
|
||||
/* 共享市场 */
|
||||
/**
|
||||
* 获取共享市场模型
|
||||
*/
|
||||
export const getShareModelList = (data: { searchText?: string } & RequestPaging) =>
|
||||
POST(`/app/share/getModels`, data);
|
||||
POST(`/core/app/share/getModels`, data);
|
||||
|
||||
/**
|
||||
* 收藏/取消收藏模型
|
||||
*/
|
||||
export const triggerModelCollection = (appId: string) =>
|
||||
POST<number>(`/app/share/collection?appId=${appId}`);
|
||||
POST<number>(`/core/app/share/collection?appId=${appId}`);
|
||||
|
||||
// ====================== data
|
||||
export const getAppTotalUsage = (data: { appId: string }) =>
|
||||
POST<{ date: String; total: number }[]>(`/app/data/totalUsage`, {
|
||||
POST<{ date: String; total: number }[]>(`/core/app/data/totalUsage`, {
|
||||
...data,
|
||||
start: addDays(new Date(), -13),
|
||||
end: addDays(new Date(), 1)
|
||||
}).then((res) => (res.length === 0 ? [{ date: new Date(), total: 0 }] : res));
|
||||
|
||||
// =================== chat logs
|
||||
export const getAppChatLogs = (data: GetAppChatLogsParams) => POST(`/app/getChatLogs`, data);
|
||||
export const getAppChatLogs = (data: GetAppChatLogsParams) => POST(`/core/app/getChatLogs`, data);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { VariableItemType } from '@/types/app';
|
||||
import type { AppTTSConfigType, VariableItemType } from '@/types/app';
|
||||
import { chatModelList } from '@/web/common/system/staticData';
|
||||
import type { ModuleItemType } from '@fastgpt/global/core/module/type';
|
||||
import {
|
||||
@@ -15,7 +15,7 @@ import { getGuideModule, splitGuideModule } from '@/global/core/app/modules/util
|
||||
|
||||
export type EditFormType = {
|
||||
chatModel: AIChatProps;
|
||||
kb: {
|
||||
dataset: {
|
||||
list: SelectedDatasetType;
|
||||
searchSimilarity: number;
|
||||
searchLimit: number;
|
||||
@@ -28,6 +28,7 @@ export type EditFormType = {
|
||||
};
|
||||
variables: VariableItemType[];
|
||||
questionGuide: boolean;
|
||||
tts: AppTTSConfigType;
|
||||
};
|
||||
export const getDefaultAppForm = (): EditFormType => {
|
||||
const defaultChatModel = chatModelList[0];
|
||||
@@ -40,11 +41,11 @@ export const getDefaultAppForm = (): EditFormType => {
|
||||
[SystemInputEnum.isResponseAnswerText]: true,
|
||||
quotePrompt: '',
|
||||
quoteTemplate: '',
|
||||
maxToken: defaultChatModel ? defaultChatModel.maxToken / 2 : 4000,
|
||||
maxToken: defaultChatModel ? defaultChatModel.maxResponse / 2 : 4000,
|
||||
frequency: 0.5,
|
||||
presence: -0.5
|
||||
},
|
||||
kb: {
|
||||
dataset: {
|
||||
list: [],
|
||||
searchSimilarity: 0.4,
|
||||
searchLimit: 5,
|
||||
@@ -56,7 +57,10 @@ export const getDefaultAppForm = (): EditFormType => {
|
||||
}
|
||||
},
|
||||
variables: [],
|
||||
questionGuide: false
|
||||
questionGuide: false,
|
||||
tts: {
|
||||
type: 'web'
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -118,17 +122,17 @@ export const appModules2Form = (modules: ModuleItemType[]) => {
|
||||
});
|
||||
} else if (module.flowType === FlowNodeTypeEnum.datasetSearchNode) {
|
||||
updateVal({
|
||||
formKey: 'kb.list',
|
||||
formKey: 'dataset.list',
|
||||
inputs: module.inputs,
|
||||
key: 'datasets'
|
||||
});
|
||||
updateVal({
|
||||
formKey: 'kb.searchSimilarity',
|
||||
formKey: 'dataset.searchSimilarity',
|
||||
inputs: module.inputs,
|
||||
key: 'similarity'
|
||||
});
|
||||
updateVal({
|
||||
formKey: 'kb.searchLimit',
|
||||
formKey: 'dataset.searchLimit',
|
||||
inputs: module.inputs,
|
||||
key: 'limit'
|
||||
});
|
||||
@@ -137,12 +141,12 @@ export const appModules2Form = (modules: ModuleItemType[]) => {
|
||||
const emptyOutput = emptyOutputs[0];
|
||||
if (emptyOutput) {
|
||||
const target = modules.find((item) => item.moduleId === emptyOutput.moduleId);
|
||||
defaultAppForm.kb.searchEmptyText =
|
||||
defaultAppForm.dataset.searchEmptyText =
|
||||
target?.inputs?.find((item) => item.key === FlowNodeSpecialInputKeyEnum.answerText)
|
||||
?.value || '';
|
||||
}
|
||||
} else if (module.flowType === FlowNodeTypeEnum.userGuide) {
|
||||
const { welcomeText, variableModules, questionGuide } = splitGuideModule(
|
||||
const { welcomeText, variableModules, questionGuide, ttsConfig } = splitGuideModule(
|
||||
getGuideModule(modules)
|
||||
);
|
||||
if (welcomeText) {
|
||||
@@ -153,6 +157,7 @@ export const appModules2Form = (modules: ModuleItemType[]) => {
|
||||
|
||||
defaultAppForm.variables = variableModules;
|
||||
defaultAppForm.questionGuide = !!questionGuide;
|
||||
defaultAppForm.tts = ttsConfig;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -213,13 +218,13 @@ const chatModelInput = (formData: EditFormType): FlowNodeInputItemType[] => [
|
||||
key: 'switch',
|
||||
type: 'target',
|
||||
label: '触发器',
|
||||
connected: formData.kb.list.length > 0 && !!formData.kb.searchEmptyText
|
||||
connected: formData.dataset.list.length > 0 && !!formData.dataset.searchEmptyText
|
||||
},
|
||||
{
|
||||
key: 'quoteQA',
|
||||
type: 'target',
|
||||
label: '引用内容',
|
||||
connected: formData.kb.list.length > 0
|
||||
connected: formData.dataset.list.length > 0
|
||||
},
|
||||
{
|
||||
key: 'history',
|
||||
@@ -256,6 +261,12 @@ const userGuideTemplate = (formData: EditFormType): ModuleItemType[] => [
|
||||
type: FlowNodeInputTypeEnum.hidden,
|
||||
label: '问题引导',
|
||||
value: formData.questionGuide
|
||||
},
|
||||
{
|
||||
key: SystemInputEnum.tts,
|
||||
type: FlowNodeInputTypeEnum.hidden,
|
||||
label: '语音播报',
|
||||
value: formData.tts
|
||||
}
|
||||
],
|
||||
outputs: [],
|
||||
@@ -434,21 +445,21 @@ const kbTemplate = (formData: EditFormType): ModuleItemType[] => [
|
||||
inputs: [
|
||||
{
|
||||
key: 'datasets',
|
||||
value: formData.kb.list,
|
||||
value: formData.dataset.list,
|
||||
type: FlowNodeInputTypeEnum.custom,
|
||||
label: '关联的知识库',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'similarity',
|
||||
value: formData.kb.searchSimilarity,
|
||||
value: formData.dataset.searchSimilarity,
|
||||
type: FlowNodeInputTypeEnum.slider,
|
||||
label: '相似度',
|
||||
connected: true
|
||||
},
|
||||
{
|
||||
key: 'limit',
|
||||
value: formData.kb.searchLimit,
|
||||
value: formData.dataset.searchLimit,
|
||||
type: FlowNodeInputTypeEnum.slider,
|
||||
label: '单次搜索上限',
|
||||
connected: true
|
||||
@@ -469,7 +480,7 @@ const kbTemplate = (formData: EditFormType): ModuleItemType[] => [
|
||||
outputs: [
|
||||
{
|
||||
key: 'isEmpty',
|
||||
targets: formData.kb.searchEmptyText
|
||||
targets: formData.dataset.searchEmptyText
|
||||
? [
|
||||
{
|
||||
moduleId: 'emptyText',
|
||||
@@ -480,7 +491,7 @@ const kbTemplate = (formData: EditFormType): ModuleItemType[] => [
|
||||
},
|
||||
{
|
||||
key: 'unEmpty',
|
||||
targets: formData.kb.searchEmptyText
|
||||
targets: formData.dataset.searchEmptyText
|
||||
? [
|
||||
{
|
||||
moduleId: 'chatModule',
|
||||
@@ -505,7 +516,7 @@ const kbTemplate = (formData: EditFormType): ModuleItemType[] => [
|
||||
},
|
||||
moduleId: 'datasetSearch'
|
||||
},
|
||||
...(formData.kb.searchEmptyText
|
||||
...(formData.dataset.searchEmptyText
|
||||
? [
|
||||
{
|
||||
name: '指定回复',
|
||||
@@ -519,7 +530,7 @@ const kbTemplate = (formData: EditFormType): ModuleItemType[] => [
|
||||
},
|
||||
{
|
||||
key: FlowNodeSpecialInputKeyEnum.answerText,
|
||||
value: formData.kb.searchEmptyText,
|
||||
value: formData.dataset.searchEmptyText,
|
||||
type: FlowNodeInputTypeEnum.textarea,
|
||||
valueType: FlowNodeValTypeEnum.string,
|
||||
label: '回复的内容',
|
||||
@@ -568,7 +579,7 @@ const kbTemplate = (formData: EditFormType): ModuleItemType[] => [
|
||||
export const appForm2Modules = (formData: EditFormType) => {
|
||||
const modules = [
|
||||
...userGuideTemplate(formData),
|
||||
...(formData.kb.list.length > 0 ? kbTemplate(formData) : simpleChatTemplate(formData))
|
||||
...(formData.dataset.list.length > 0 ? kbTemplate(formData) : simpleChatTemplate(formData))
|
||||
];
|
||||
|
||||
return modules as ModuleItemType[];
|
||||
|
65
projects/app/src/web/core/app/store/useAppStore.ts
Normal file
65
projects/app/src/web/core/app/store/useAppStore.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { create } from 'zustand';
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import { getMyApps, getModelById, putAppById } from '@/web/core/app/api';
|
||||
import { defaultApp } from '@/constants/app';
|
||||
import type { AppUpdateParams } from '@fastgpt/global/core/app/api.d';
|
||||
import { AppDetailType, AppListItemType } from '@fastgpt/global/core/app/type.d';
|
||||
|
||||
type State = {
|
||||
myApps: AppListItemType[];
|
||||
loadMyApps: (init?: boolean) => Promise<AppListItemType[]>;
|
||||
appDetail: AppDetailType;
|
||||
loadAppDetail: (id: string, init?: boolean) => Promise<AppDetailType>;
|
||||
updateAppDetail(appId: string, data: AppUpdateParams): Promise<void>;
|
||||
clearAppModules(): void;
|
||||
};
|
||||
|
||||
export const useAppStore = create<State>()(
|
||||
devtools(
|
||||
persist(
|
||||
immer((set, get) => ({
|
||||
myApps: [],
|
||||
async loadMyApps(init = true) {
|
||||
if (get().myApps.length > 0 && !init) return [];
|
||||
const res = await getMyApps();
|
||||
set((state) => {
|
||||
state.myApps = res;
|
||||
});
|
||||
return res;
|
||||
},
|
||||
appDetail: defaultApp,
|
||||
async loadAppDetail(id: string, init = false) {
|
||||
if (id === get().appDetail._id && !init) return get().appDetail;
|
||||
|
||||
const res = await getModelById(id);
|
||||
set((state) => {
|
||||
state.appDetail = res;
|
||||
});
|
||||
return res;
|
||||
},
|
||||
async updateAppDetail(appId: string, data: AppUpdateParams) {
|
||||
await putAppById(appId, data);
|
||||
set((state) => {
|
||||
state.appDetail = {
|
||||
...state.appDetail,
|
||||
...data
|
||||
};
|
||||
});
|
||||
},
|
||||
clearAppModules() {
|
||||
set((state) => {
|
||||
state.appDetail = {
|
||||
...state.appDetail,
|
||||
modules: []
|
||||
};
|
||||
});
|
||||
}
|
||||
})),
|
||||
{
|
||||
name: 'appStore',
|
||||
partialize: (state) => ({})
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
@@ -1,45 +1,49 @@
|
||||
import { GET, POST, DELETE, PUT } from '@/web/common/api/request';
|
||||
import type { ChatHistoryItemType } from '@/types/chat';
|
||||
import type { InitChatResponse } from '@/global/core/api/chatRes.d';
|
||||
import type { ChatHistoryItemType } from '@fastgpt/global/core/chat/type.d';
|
||||
import type { InitChatResponse } from '@fastgpt/global/core/chat/api.d';
|
||||
import type { RequestPaging } from '@/types';
|
||||
import type { Props as UpdateHistoryProps } from '@/pages/api/chat/history/updateChatHistory';
|
||||
import type { AdminUpdateFeedbackParams } from '@/global/core/api/chatReq.d';
|
||||
import { UpdateHistoryProps } from '@fastgpt/global/core/chat/api.d';
|
||||
import type { AdminUpdateFeedbackParams } from '@fastgpt/global/core/chat/api.d';
|
||||
import { GetChatSpeechProps } from '@/global/core/chat/api.d';
|
||||
|
||||
/**
|
||||
* 获取初始化聊天内容
|
||||
*/
|
||||
export const getInitChatSiteInfo = (data: { appId: string; chatId?: string }) =>
|
||||
GET<InitChatResponse>(`/chat/init`, data);
|
||||
GET<InitChatResponse>(`/core/chat/init`, data);
|
||||
|
||||
/**
|
||||
* 获取历史记录
|
||||
*/
|
||||
export const getChatHistory = (data: RequestPaging & { appId?: string }) =>
|
||||
POST<ChatHistoryItemType[]>('/chat/history/getHistory', data);
|
||||
export const getChatHistory = (data: RequestPaging & { appId: string }) =>
|
||||
POST<ChatHistoryItemType[]>('/core/chat/list', data);
|
||||
|
||||
/**
|
||||
* 删除一条历史记录
|
||||
*/
|
||||
export const delChatHistoryById = (chatId: string) => DELETE(`/chat/removeHistory`, { chatId });
|
||||
export const delChatHistoryById = (chatId: string) => DELETE(`/core/chat/delete`, { chatId });
|
||||
/**
|
||||
* clear all history by appid
|
||||
*/
|
||||
export const clearChatHistoryByAppId = (appId: string) => DELETE(`/chat/removeHistory`, { appId });
|
||||
export const clearChatHistoryByAppId = (appId: string) => DELETE(`/core/chat/delete`, { appId });
|
||||
|
||||
/**
|
||||
* 删除一句对话
|
||||
*/
|
||||
export const delChatRecordById = (data: { chatId: string; contentId: string }) =>
|
||||
DELETE(`/chat/delChatRecordByContentId`, data);
|
||||
DELETE(`/core/chat/item/delete`, data);
|
||||
|
||||
/**
|
||||
* 修改历史记录: 标题/置顶
|
||||
*/
|
||||
export const putChatHistory = (data: UpdateHistoryProps) =>
|
||||
PUT('/chat/history/updateChatHistory', data);
|
||||
export const putChatHistory = (data: UpdateHistoryProps) => PUT('/core/chat/update', data);
|
||||
|
||||
export const userUpdateChatFeedback = (data: { chatItemId: string; userFeedback?: string }) =>
|
||||
POST('/chat/feedback/userUpdate', data);
|
||||
POST('/core/chat/feedback/userUpdate', data);
|
||||
|
||||
export const adminUpdateChatFeedback = (data: AdminUpdateFeedbackParams) =>
|
||||
POST('/chat/feedback/adminUpdate', data);
|
||||
POST('/core/chat/feedback/adminUpdate', data);
|
||||
|
||||
/* ------------- function ------------- */
|
||||
export const getChatItemSpeech = (data: GetChatSpeechProps) =>
|
||||
POST<{ data: Buffer }>('/core/chat/item/getSpeech', data);
|
||||
|
@@ -1,14 +1,13 @@
|
||||
import { create } from 'zustand';
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
|
||||
import { ChatHistoryItemType } from '@/types/chat';
|
||||
import type { InitChatResponse } from '@/global/core/api/chatRes.d';
|
||||
import type { ChatHistoryItemType } from '@fastgpt/global/core/chat/type.d';
|
||||
import type { InitChatResponse } from '@fastgpt/global/core/chat/api';
|
||||
import { delChatHistoryById, getChatHistory, clearChatHistoryByAppId } from '@/web/core/chat/api';
|
||||
|
||||
type State = {
|
||||
history: ChatHistoryItemType[];
|
||||
loadHistory: (data: { appId?: string }) => Promise<null>;
|
||||
loadHistory: (data: { appId: string }) => Promise<null>;
|
||||
delHistory(history: string): Promise<void>;
|
||||
clearHistory(appId: string): Promise<void>;
|
||||
updateHistory: (history: ChatHistoryItemType) => void;
|
||||
|
@@ -1,9 +1,12 @@
|
||||
import { create } from 'zustand';
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
|
||||
import type { ChatSiteItemType, ShareChatHistoryItemType, ShareChatType } from '@/types/chat';
|
||||
import { HUMAN_ICON } from '@/constants/chat';
|
||||
import type {
|
||||
ShareChatHistoryItemType,
|
||||
ShareChatType
|
||||
} from '@fastgpt/global/support/outLink/api.d';
|
||||
import type { ChatSiteItemType } from '@fastgpt/global/core/chat/type.d';
|
||||
import { HUMAN_ICON } from '@fastgpt/global/core/chat/constants';
|
||||
|
||||
type State = {
|
||||
shareChatData: ShareChatType;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { GET, POST, PUT, DELETE } from '@/web/common/api/request';
|
||||
import type { DatasetItemType, DatasetsItemType, DatasetPathItemType } from '@/types/core/dataset';
|
||||
import type { DatasetItemType, DatasetPathItemType } from '@/types/core/dataset';
|
||||
import type {
|
||||
DatasetUpdateParams,
|
||||
CreateDatasetParams,
|
||||
@@ -12,27 +12,26 @@ import type {
|
||||
SetOneDatasetDataProps
|
||||
} from '@/global/core/api/datasetReq.d';
|
||||
import type { PushDataResponse } from '@/global/core/api/datasetRes.d';
|
||||
import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
|
||||
import type {
|
||||
DatasetCollectionItemType,
|
||||
SearchDataResponseItemType
|
||||
} from '@fastgpt/global/core/dataset/type';
|
||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constant';
|
||||
import type { GSFileInfoType } from '@/types/common/file';
|
||||
import { getToken } from '@/web/support/user/auth';
|
||||
import download from 'downloadjs';
|
||||
import type {
|
||||
DatasetCollectionSchemaType,
|
||||
DatasetDataItemType
|
||||
} from '@fastgpt/global/core/dataset/type';
|
||||
import type { DatasetDataItemType } from '@fastgpt/global/core/dataset/type';
|
||||
import { ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type';
|
||||
import { DatasetCollectionsListItemType } from '@/global/core/dataset/response';
|
||||
import { PagingData } from '@/types';
|
||||
|
||||
/* ======================== dataset ======================= */
|
||||
export const getDatasets = (data: { parentId?: string; type?: `${DatasetTypeEnum}` }) =>
|
||||
GET<DatasetsItemType[]>(`/core/dataset/list`, data);
|
||||
GET<DatasetItemType[]>(`/core/dataset/list`, data);
|
||||
|
||||
/**
|
||||
* get type=dataset list
|
||||
*/
|
||||
export const getAllDataset = () => GET<DatasetsItemType[]>(`/core/dataset/allDataset`);
|
||||
export const getAllDataset = () => GET<DatasetItemType[]>(`/core/dataset/allDataset`);
|
||||
|
||||
export const getDatasetPaths = (parentId?: string) =>
|
||||
GET<DatasetPathItemType[]>('/core/dataset/paths', { parentId });
|
||||
@@ -56,7 +55,7 @@ export const getDatasetCollections = (data: GetDatasetCollectionsProps) =>
|
||||
export const getDatasetCollectionPathById = (parentId: string) =>
|
||||
GET<ParentTreePathItemType[]>(`/core/dataset/collection/paths`, { parentId });
|
||||
export const getDatasetCollectionById = (id: string) =>
|
||||
GET<DatasetCollectionSchemaType>(`/core/dataset/collection/detail`, { id });
|
||||
GET<DatasetCollectionItemType>(`/core/dataset/collection/detail`, { id });
|
||||
export const postDatasetCollection = (data: CreateDatasetCollectionParams) =>
|
||||
POST<string>(`/core/dataset/collection/create`, data);
|
||||
export const putDatasetCollectionById = (data: UpdateDatasetCollectionParams) =>
|
||||
@@ -119,7 +118,5 @@ export const delOneDatasetDataById = (dataId: string) =>
|
||||
DELETE(`/core/dataset/data/delDataById?dataId=${dataId}`);
|
||||
|
||||
/* ================== file ======================== */
|
||||
export const getFileInfoById = (fileId: string) =>
|
||||
GET<GSFileInfoType>(`/core/dataset/file/detail`, { fileId });
|
||||
export const delDatasetEmptyFiles = (datasetId: string) =>
|
||||
DELETE(`/core/dataset/file/delEmptyFiles`, { datasetId });
|
||||
export const getFileViewUrl = (fileId: string) =>
|
||||
GET<string>('/core/dataset/file/getPreviewUrl', { fileId });
|
||||
|
@@ -1,17 +1,17 @@
|
||||
import { create } from 'zustand';
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import type { DatasetItemType, DatasetsItemType } from '@/types/core/dataset';
|
||||
import type { DatasetItemType } from '@/types/core/dataset';
|
||||
import { getAllDataset, getDatasets, getDatasetById, putDatasetById } from '@/web/core/dataset/api';
|
||||
import { defaultKbDetail } from '@/constants/dataset';
|
||||
import { defaultDatasetDetail } from '@/constants/dataset';
|
||||
import type { DatasetUpdateParams } from '@/global/core/api/datasetReq.d';
|
||||
|
||||
type State = {
|
||||
allDatasets: DatasetsItemType[];
|
||||
loadAllDatasets: () => Promise<DatasetsItemType[]>;
|
||||
myDatasets: DatasetsItemType[];
|
||||
allDatasets: DatasetItemType[];
|
||||
loadAllDatasets: () => Promise<DatasetItemType[]>;
|
||||
myDatasets: DatasetItemType[];
|
||||
loadDatasets: (parentId?: string) => Promise<any>;
|
||||
setDatasets(val: DatasetsItemType[]): void;
|
||||
setDatasets(val: DatasetItemType[]): void;
|
||||
datasetDetail: DatasetItemType;
|
||||
loadDatasetDetail: (id: string, init?: boolean) => Promise<DatasetItemType>;
|
||||
updateDataset: (data: DatasetUpdateParams) => Promise<any>;
|
||||
@@ -42,7 +42,7 @@ export const useDatasetStore = create<State>()(
|
||||
state.myDatasets = val;
|
||||
});
|
||||
},
|
||||
datasetDetail: defaultKbDetail,
|
||||
datasetDetail: defaultDatasetDetail,
|
||||
async loadDatasetDetail(id: string, init = false) {
|
||||
if (!id || (id === get().datasetDetail._id && !init)) return get().datasetDetail;
|
||||
|
||||
@@ -69,7 +69,7 @@ export const useDatasetStore = create<State>()(
|
||||
? {
|
||||
...item,
|
||||
...data,
|
||||
tags: data.tags?.split(' ') || []
|
||||
tags: data.tags || ''
|
||||
}
|
||||
: item
|
||||
);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { postChunks2Dataset } from '@/web/core/dataset/api';
|
||||
import { getFileViewUrl, postChunks2Dataset } from '@/web/core/dataset/api';
|
||||
import { TrainingModeEnum } from '@fastgpt/global/core/dataset/constant';
|
||||
import { DatasetChunkItemType } from '@fastgpt/global/core/dataset/type';
|
||||
import { delay } from '@/utils/tools';
|
||||
@@ -49,3 +49,9 @@ export async function chunksUpload({
|
||||
|
||||
return { insertLen: successInsert };
|
||||
}
|
||||
|
||||
export async function getFileAndOpen(fileId: string) {
|
||||
const url = await getFileViewUrl(fileId);
|
||||
const asPath = `${location.origin}${url}`;
|
||||
window.open(asPath, '_blank');
|
||||
}
|
||||
|
@@ -186,8 +186,7 @@ const Select = selectMultiStyle({
|
||||
variants: {
|
||||
outline: selectPart({
|
||||
field: {
|
||||
borderColor: 'myGray.100',
|
||||
|
||||
borderColor: 'myGray.200',
|
||||
_focusWithin: {
|
||||
boxShadow: '0px 0px 4px #A8DBFF',
|
||||
borderColor: 'myBlue.600'
|
||||
@@ -207,6 +206,7 @@ export const theme = extendTheme({
|
||||
fontWeight: 400,
|
||||
height: '100%',
|
||||
overflow: 'hidden'
|
||||
// lineHeight: 'unset'
|
||||
},
|
||||
a: {
|
||||
color: 'myBlue.700'
|
||||
|
14
projects/app/src/web/support/activity/promotion/api.ts
Normal file
14
projects/app/src/web/support/activity/promotion/api.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { GET, POST, PUT } from '@/web/common/api/request';
|
||||
import type { PromotionRecordType } from '@/global/support/api/userRes.d';
|
||||
import type { RequestPaging } from '@/types';
|
||||
|
||||
/* get promotion init data */
|
||||
export const getPromotionInitData = () =>
|
||||
GET<{
|
||||
invitedAmount: number;
|
||||
earningsAmount: number;
|
||||
}>('/plusApi/support/activity/promotion/getPromotionData');
|
||||
|
||||
/* promotion records */
|
||||
export const getPromotionRecords = (data: RequestPaging) =>
|
||||
POST<PromotionRecordType>(`/plusApi/support/activity/promotion/getPromotions`, data);
|
@@ -1,26 +1,26 @@
|
||||
import { GET, POST, DELETE } from '@/web/common/api/request';
|
||||
import type { EditApiKeyProps, GetApiKeyProps } from '@/global/support/api/openapiReq.d';
|
||||
import { GET, POST, DELETE, PUT } from '@/web/common/api/request';
|
||||
import type { EditApiKeyProps, GetApiKeyProps } from '@/global/support/openapi/api.d';
|
||||
import type { OpenApiSchema } from '@fastgpt/global/support/openapi/type';
|
||||
|
||||
/**
|
||||
* crete a api key
|
||||
*/
|
||||
export const createAOpenApiKey = (data: EditApiKeyProps) =>
|
||||
POST<string>('/support/openapi/postKey', data);
|
||||
POST<string>('/support/openapi/create', data);
|
||||
|
||||
/**
|
||||
* update a api key
|
||||
*/
|
||||
export const putOpenApiKey = (data: EditApiKeyProps & { _id: string }) =>
|
||||
POST<string>('/support/openapi/putKey', data);
|
||||
PUT<string>('/support/openapi/update', data);
|
||||
|
||||
/**
|
||||
* get api keys
|
||||
*/
|
||||
export const getOpenApiKeys = (params?: GetApiKeyProps) =>
|
||||
GET<OpenApiSchema[]>('/support/openapi/getKeys', params);
|
||||
GET<OpenApiSchema[]>('/support/openapi/list', params);
|
||||
|
||||
/**
|
||||
* delete api by id
|
||||
*/
|
||||
export const delOpenApiById = (id: string) => DELETE(`/support/openapi/delKey?id=${id}`);
|
||||
export const delOpenApiById = (id: string) => DELETE(`/support/openapi/delete`, { id });
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { GET, POST, DELETE } from '@/web/common/api/request';
|
||||
import type { InitShareChatResponse } from '@/global/support/api/outLinkRes.d';
|
||||
import type { InitShareChatResponse } from '@fastgpt/global/support/outLink/api.d';
|
||||
import type { OutLinkEditType, OutLinkSchema } from '@fastgpt/global/support/outLink/type.d';
|
||||
|
||||
/**
|
||||
|
@@ -1,11 +1,10 @@
|
||||
import { GET, POST, PUT } from '@/web/common/api/request';
|
||||
import { hashStr } from '@fastgpt/global/common/string/tools';
|
||||
import type { ResLogin, PromotionRecordType } from '@/global/support/api/userRes.d';
|
||||
import type { ResLogin } from '@/global/support/api/userRes.d';
|
||||
import { UserAuthTypeEnum } from '@/constants/common';
|
||||
import { UserType, UserUpdateParams } from '@/types/user';
|
||||
import type { PagingData, RequestPaging } from '@/types';
|
||||
import type { UserInformSchema } from '@fastgpt/global/support/user/type';
|
||||
import { OAuthEnum } from '@/constants/user';
|
||||
import { UserUpdateParams } from '@/types/user';
|
||||
import { UserType } from '@fastgpt/global/support/user/type.d';
|
||||
import type { OauthLoginProps, PostLoginProps } from '@fastgpt/global/support/user/api.d';
|
||||
|
||||
export const sendAuthCode = (data: {
|
||||
username: string;
|
||||
@@ -14,12 +13,8 @@ export const sendAuthCode = (data: {
|
||||
}) => POST(`/plusApi/support/user/inform/sendAuthCode`, data);
|
||||
|
||||
export const getTokenLogin = () => GET<UserType>('/user/account/tokenLogin');
|
||||
export const oauthLogin = (params: {
|
||||
type: `${OAuthEnum}`;
|
||||
code: string;
|
||||
callbackUrl: string;
|
||||
inviterId?: string;
|
||||
}) => POST<ResLogin>('/plusApi/support/user/account/login/oauth', params);
|
||||
export const oauthLogin = (params: OauthLoginProps) =>
|
||||
POST<ResLogin>('/plusApi/support/user/account/login/oauth', params);
|
||||
|
||||
export const postRegister = ({
|
||||
username,
|
||||
@@ -60,29 +55,12 @@ export const updatePasswordByOld = ({ oldPsw, newPsw }: { oldPsw: string; newPsw
|
||||
newPsw: hashStr(newPsw)
|
||||
});
|
||||
|
||||
export const postLogin = ({ username, password }: { username: string; password: string }) =>
|
||||
export const postLogin = ({ password, ...props }: PostLoginProps) =>
|
||||
POST<ResLogin>('/user/account/loginByPassword', {
|
||||
username,
|
||||
...props,
|
||||
password: hashStr(password)
|
||||
});
|
||||
|
||||
export const loginOut = () => GET('/user/account/loginout');
|
||||
|
||||
export const putUserInfo = (data: UserUpdateParams) => PUT('/user/account/update', data);
|
||||
|
||||
export const getInforms = (data: RequestPaging) =>
|
||||
POST<PagingData<UserInformSchema>>(`/user/inform/list`, data);
|
||||
|
||||
export const getUnreadCount = () => GET<number>(`/user/inform/countUnread`);
|
||||
export const readInform = (id: string) => GET(`/user/inform/read`, { id });
|
||||
|
||||
/* get promotion init data */
|
||||
export const getPromotionInitData = () =>
|
||||
GET<{
|
||||
invitedAmount: number;
|
||||
earningsAmount: number;
|
||||
}>('/user/promotion/getPromotionData');
|
||||
|
||||
/* promotion records */
|
||||
export const getPromotionRecords = (data: RequestPaging) =>
|
||||
POST<PromotionRecordType>(`/user/promotion/getPromotions`, data);
|
||||
|
@@ -11,8 +11,10 @@ export const clearToken = () => {
|
||||
};
|
||||
|
||||
export const setToken = (token: string) => {
|
||||
if (typeof window === 'undefined') return '';
|
||||
localStorage.setItem(tokenKey, token);
|
||||
};
|
||||
export const getToken = () => {
|
||||
if (typeof window === 'undefined') return '';
|
||||
return localStorage.getItem(tokenKey) || '';
|
||||
};
|
||||
|
9
projects/app/src/web/support/user/inform/api.ts
Normal file
9
projects/app/src/web/support/user/inform/api.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { GET, POST, PUT } from '@/web/common/api/request';
|
||||
import type { PagingData, RequestPaging } from '@/types';
|
||||
import type { UserInformSchema } from '@fastgpt/global/support/user/inform/type';
|
||||
|
||||
export const getInforms = (data: RequestPaging) =>
|
||||
POST<PagingData<UserInformSchema>>(`/plusApi/support/user/inform/list`, data);
|
||||
|
||||
export const getUnreadCount = () => GET<number>(`/plusApi/support/user/inform/countUnread`);
|
||||
export const readInform = (id: string) => GET(`/plusApi/support/user/inform/read`, { id });
|
40
projects/app/src/web/support/user/team/api.ts
Normal file
40
projects/app/src/web/support/user/team/api.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { GET, POST, PUT, DELETE } from '@/web/common/api/request';
|
||||
import {
|
||||
CreateTeamProps,
|
||||
DelMemberProps,
|
||||
InviteMemberProps,
|
||||
InviteMemberResponse,
|
||||
UpdateInviteProps,
|
||||
UpdateTeamMemberProps,
|
||||
UpdateTeamProps
|
||||
} from '@fastgpt/global/support/user/team/controller.d';
|
||||
import {
|
||||
TeamItemType,
|
||||
TeamMemberItemType,
|
||||
TeamMemberSchema
|
||||
} from '@fastgpt/global/support/user/team/type.d';
|
||||
|
||||
/* --------------- team ---------------- */
|
||||
export const getTeamList = (status: `${TeamMemberSchema['status']}`) =>
|
||||
GET<TeamItemType[]>(`/plusApi/support/user/team/list`, { status });
|
||||
export const postCreateTeam = (data: CreateTeamProps) =>
|
||||
POST<string>(`/plusApi/support/user/team/create`, data);
|
||||
export const putUpdateTeam = (data: UpdateTeamProps) =>
|
||||
PUT(`/plusApi/support/user/team/update`, data);
|
||||
export const deleteTeam = (id: number) => DELETE(`/plusApi/support/user/team/delete`, { id });
|
||||
export const putSwitchTeam = (teamId: string) =>
|
||||
PUT<string>(`/plusApi/support/user/team/switch`, { teamId });
|
||||
|
||||
/* --------------- team member ---------------- */
|
||||
export const getTeamMembers = (teamId: string) =>
|
||||
GET<TeamMemberItemType[]>(`/plusApi/support/user/team/member/list`, { teamId });
|
||||
export const postInviteTeamMember = (data: InviteMemberProps) =>
|
||||
POST<InviteMemberResponse>(`/plusApi/support/user/team/member/invite`, data);
|
||||
export const putUpdateMember = (data: UpdateTeamMemberProps) =>
|
||||
PUT(`/plusApi/support/user/team/member/update`, data);
|
||||
export const delRemoveMember = (props: DelMemberProps) =>
|
||||
DELETE(`/plusApi/support/user/team/member/delete`, props);
|
||||
export const updateInviteResult = (data: UpdateInviteProps) =>
|
||||
PUT('/plusApi/support/user/team/member/updateInvite', data);
|
||||
export const delLeaveTeam = (teamId: string) =>
|
||||
DELETE('/plusApi/support/user/team/member/leave', { teamId });
|
@@ -1,27 +1,16 @@
|
||||
import { create } from 'zustand';
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import type { UserType, UserUpdateParams } from '@/types/user';
|
||||
import { getMyApps, getModelById, putAppById } from '@/web/core/app/api';
|
||||
import { formatPrice } from '@fastgpt/global/common/bill/tools';
|
||||
import type { UserUpdateParams } from '@/types/user';
|
||||
import type { UserType } from '@fastgpt/global/support/user/type.d';
|
||||
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
|
||||
import { getTokenLogin, putUserInfo } from '@/web/support/user/api';
|
||||
import { defaultApp } from '@/constants/model';
|
||||
import { AppListItemType, AppUpdateParams } from '@/types/app';
|
||||
|
||||
import type { AppSchema } from '@/types/mongoSchema';
|
||||
|
||||
type State = {
|
||||
userInfo: UserType | null;
|
||||
initUserInfo: () => Promise<UserType>;
|
||||
setUserInfo: (user: UserType | null) => void;
|
||||
updateUserInfo: (user: UserUpdateParams) => Promise<void>;
|
||||
myApps: AppListItemType[];
|
||||
myCollectionApps: AppListItemType[];
|
||||
loadMyApps: (init?: boolean) => Promise<AppListItemType[]>;
|
||||
appDetail: AppSchema;
|
||||
loadAppDetail: (id: string, init?: boolean) => Promise<AppSchema>;
|
||||
updateAppDetail(appId: string, data: AppUpdateParams): Promise<void>;
|
||||
clearAppModules(): void;
|
||||
};
|
||||
|
||||
export const useUserStore = create<State>()(
|
||||
@@ -32,6 +21,7 @@ export const useUserStore = create<State>()(
|
||||
async initUserInfo() {
|
||||
const res = await getTokenLogin();
|
||||
get().setUserInfo(res);
|
||||
|
||||
return res;
|
||||
},
|
||||
setUserInfo(user: UserType | null) {
|
||||
@@ -61,43 +51,6 @@ export const useUserStore = create<State>()(
|
||||
});
|
||||
return Promise.reject(error);
|
||||
}
|
||||
},
|
||||
myApps: [],
|
||||
myCollectionApps: [],
|
||||
async loadMyApps(init = true) {
|
||||
if (get().myApps.length > 0 && !init) return [];
|
||||
const res = await getMyApps();
|
||||
set((state) => {
|
||||
state.myApps = res;
|
||||
});
|
||||
return res;
|
||||
},
|
||||
appDetail: defaultApp,
|
||||
async loadAppDetail(id: string, init = false) {
|
||||
if (id === get().appDetail._id && !init) return get().appDetail;
|
||||
|
||||
const res = await getModelById(id);
|
||||
set((state) => {
|
||||
state.appDetail = res;
|
||||
});
|
||||
return res;
|
||||
},
|
||||
async updateAppDetail(appId: string, data: AppUpdateParams) {
|
||||
await putAppById(appId, data);
|
||||
set((state) => {
|
||||
state.appDetail = {
|
||||
...state.appDetail,
|
||||
...data
|
||||
};
|
||||
});
|
||||
},
|
||||
clearAppModules() {
|
||||
set((state) => {
|
||||
state.appDetail = {
|
||||
...state.appDetail,
|
||||
modules: []
|
||||
};
|
||||
});
|
||||
}
|
||||
})),
|
||||
{
|
||||
|
10
projects/app/src/web/support/wallet/bill/api.ts
Normal file
10
projects/app/src/web/support/wallet/bill/api.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { GET, POST } from '@/web/common/api/request';
|
||||
import { CreateTrainingBillProps } from '@fastgpt/global/support/wallet/bill/api.d';
|
||||
import type { PagingData, RequestPaging } from '@/types';
|
||||
import type { BillItemType } from '@fastgpt/global/support/wallet/bill/type';
|
||||
|
||||
export const getUserBills = (data: RequestPaging) =>
|
||||
POST<PagingData<BillItemType>>(`/plusApi/support/wallet/bill/getBill`, data);
|
||||
|
||||
export const postCreateTrainingBill = (data: CreateTrainingBillProps) =>
|
||||
POST<string>(`/support/wallet/bill/createTrainingBill`, data);
|
25
projects/app/src/web/support/wallet/pay/api.ts
Normal file
25
projects/app/src/web/support/wallet/pay/api.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { GET } from '@/web/common/api/request';
|
||||
import type { PaySchema } from '@fastgpt/global/support/wallet/pay/type.d';
|
||||
import { delay } from '@/utils/tools';
|
||||
|
||||
export const getPayOrders = () => GET<PaySchema[]>(`/plusApi/support/wallet/pay/getPayOrders`);
|
||||
|
||||
export const getPayCode = (amount: number) =>
|
||||
GET<{
|
||||
codeUrl: string;
|
||||
payId: string;
|
||||
}>(`/plusApi/support/wallet/pay/getPayCode`, { amount });
|
||||
|
||||
export const checkPayResult = (payId: string) =>
|
||||
GET<number>(`/plusApi/support/wallet/pay/checkPayResult`, { payId }).then(() => {
|
||||
async function startQueue() {
|
||||
try {
|
||||
await GET('/common/system/unlockTask');
|
||||
} catch (error) {
|
||||
await delay(1000);
|
||||
startQueue();
|
||||
}
|
||||
}
|
||||
startQueue();
|
||||
return 'success';
|
||||
});
|
Reference in New Issue
Block a user