mirror of
https://github.com/labring/FastGPT.git
synced 2025-08-02 20:58:12 +00:00
Optimize the project structure and introduce DDD design (#394)
This commit is contained in:
26
projects/app/src/web/support/api/openapi.ts
Normal file
26
projects/app/src/web/support/api/openapi.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { GET, POST, DELETE } from '@/web/common/api/request';
|
||||
import type { EditApiKeyProps, GetApiKeyProps } from '@/global/support/api/openapiReq.d';
|
||||
import type { OpenApiSchema } from '@/types/support/openapi';
|
||||
|
||||
/**
|
||||
* crete a api key
|
||||
*/
|
||||
export const createAOpenApiKey = (data: EditApiKeyProps) =>
|
||||
POST<string>('/support/openapi/postKey', data);
|
||||
|
||||
/**
|
||||
* update a api key
|
||||
*/
|
||||
export const putOpenApiKey = (data: EditApiKeyProps & { _id: string }) =>
|
||||
POST<string>('/support/openapi/putKey', data);
|
||||
|
||||
/**
|
||||
* get api keys
|
||||
*/
|
||||
export const getOpenApiKeys = (params?: GetApiKeyProps) =>
|
||||
GET<OpenApiSchema[]>('/support/openapi/getKeys', params);
|
||||
|
||||
/**
|
||||
* delete api by id
|
||||
*/
|
||||
export const delOpenApiById = (id: string) => DELETE(`/support/openapi/delKey?id=${id}`);
|
34
projects/app/src/web/support/api/outLink.ts
Normal file
34
projects/app/src/web/support/api/outLink.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { GET, POST, DELETE } from '@/web/common/api/request';
|
||||
import type { InitShareChatResponse } from '@/global/support/api/outLinkRes.d';
|
||||
import type { OutLinkEditType } from '@/types/support/outLink';
|
||||
import type { OutLinkSchema } from '@/types/support/outLink';
|
||||
|
||||
/**
|
||||
* 初始化分享聊天
|
||||
*/
|
||||
export const initShareChatInfo = (data: { shareId: string; authToken?: string }) =>
|
||||
GET<InitShareChatResponse>(`/support/outLink/init`, data);
|
||||
|
||||
/**
|
||||
* create a shareChat
|
||||
*/
|
||||
export const createShareChat = (
|
||||
data: OutLinkEditType & {
|
||||
appId: string;
|
||||
type: OutLinkSchema['type'];
|
||||
}
|
||||
) => POST<string>(`/support/outLink/create`, data);
|
||||
|
||||
export const putShareChat = (data: OutLinkEditType) =>
|
||||
POST<string>(`/support/outLink/update`, data);
|
||||
|
||||
/**
|
||||
* get shareChat
|
||||
*/
|
||||
export const getShareChatList = (appId: string) =>
|
||||
GET<OutLinkSchema[]>(`/support/outLink/list`, { appId });
|
||||
|
||||
/**
|
||||
* delete a shareChat
|
||||
*/
|
||||
export const delShareChatById = (id: string) => DELETE(`/support/outLink/delete?id=${id}`);
|
88
projects/app/src/web/support/api/user.ts
Normal file
88
projects/app/src/web/support/api/user.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { GET, POST, PUT } from '@/web/common/api/request';
|
||||
import { createHashPassword } from '@/utils/tools';
|
||||
import type { ResLogin, PromotionRecordType } from '@/global/support/api/userRes.d';
|
||||
import { UserAuthTypeEnum } from '@/constants/common';
|
||||
import { UserType, UserUpdateParams } from '@/types/user';
|
||||
import type { PagingData, RequestPaging } from '@/types';
|
||||
import { informSchema } from '@/types/mongoSchema';
|
||||
import { OAuthEnum } from '@/constants/user';
|
||||
|
||||
export const sendAuthCode = (data: {
|
||||
username: string;
|
||||
type: `${UserAuthTypeEnum}`;
|
||||
googleToken: string;
|
||||
}) => POST(`/plusApi/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/user/account/login/oauth', params);
|
||||
|
||||
export const postRegister = ({
|
||||
username,
|
||||
password,
|
||||
code,
|
||||
inviterId
|
||||
}: {
|
||||
username: string;
|
||||
code: string;
|
||||
password: string;
|
||||
inviterId?: string;
|
||||
}) =>
|
||||
POST<ResLogin>(`/plusApi/user/account/register/emailAndPhone`, {
|
||||
username,
|
||||
code,
|
||||
inviterId,
|
||||
password: createHashPassword(password)
|
||||
});
|
||||
|
||||
export const postFindPassword = ({
|
||||
username,
|
||||
code,
|
||||
password
|
||||
}: {
|
||||
username: string;
|
||||
code: string;
|
||||
password: string;
|
||||
}) =>
|
||||
POST<ResLogin>(`/plusApi/user/account/password/updateByCode`, {
|
||||
username,
|
||||
code,
|
||||
password: createHashPassword(password)
|
||||
});
|
||||
|
||||
export const updatePasswordByOld = ({ oldPsw, newPsw }: { oldPsw: string; newPsw: string }) =>
|
||||
POST('/user/account/updatePasswordByOld', {
|
||||
oldPsw: createHashPassword(oldPsw),
|
||||
newPsw: createHashPassword(newPsw)
|
||||
});
|
||||
|
||||
export const postLogin = ({ username, password }: { username: string; password: string }) =>
|
||||
POST<ResLogin>('/user/account/loginByPassword', {
|
||||
username,
|
||||
password: createHashPassword(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<informSchema>>(`/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);
|
81
projects/app/src/web/support/hooks/useSendCode.ts
Normal file
81
projects/app/src/web/support/hooks/useSendCode.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { useState, useMemo, useCallback } from 'react';
|
||||
import { sendAuthCode } from '@/web/support/api/user';
|
||||
import { UserAuthTypeEnum } from '@/constants/common';
|
||||
import { useToast } from '@/web/common/hooks/useToast';
|
||||
import { feConfigs } from '@/web/common/store/static';
|
||||
import { getErrText } from '@/utils/tools';
|
||||
|
||||
let timer: any;
|
||||
|
||||
export const useSendCode = () => {
|
||||
const { toast } = useToast();
|
||||
const [codeSending, setCodeSending] = useState(false);
|
||||
const [codeCountDown, setCodeCountDown] = useState(0);
|
||||
const sendCodeText = useMemo(() => {
|
||||
if (codeCountDown >= 10) {
|
||||
return `${codeCountDown}s后重新获取`;
|
||||
}
|
||||
if (codeCountDown > 0) {
|
||||
return `0${codeCountDown}s后重新获取`;
|
||||
}
|
||||
return '获取验证码';
|
||||
}, [codeCountDown]);
|
||||
|
||||
const sendCode = useCallback(
|
||||
async ({ username, type }: { username: string; type: `${UserAuthTypeEnum}` }) => {
|
||||
setCodeSending(true);
|
||||
try {
|
||||
await sendAuthCode({
|
||||
username,
|
||||
type,
|
||||
googleToken: await getClientToken(feConfigs.googleClientVerKey)
|
||||
});
|
||||
setCodeCountDown(60);
|
||||
timer = setInterval(() => {
|
||||
setCodeCountDown((val) => {
|
||||
if (val <= 0) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
return val - 1;
|
||||
});
|
||||
}, 1000);
|
||||
toast({
|
||||
title: '验证码已发送',
|
||||
status: 'success',
|
||||
position: 'top'
|
||||
});
|
||||
} catch (error: any) {
|
||||
toast({
|
||||
title: getErrText(error, '验证码发送异常'),
|
||||
status: 'error'
|
||||
});
|
||||
}
|
||||
setCodeSending(false);
|
||||
},
|
||||
[toast]
|
||||
);
|
||||
|
||||
return {
|
||||
codeSending,
|
||||
sendCode,
|
||||
sendCodeText,
|
||||
codeCountDown
|
||||
};
|
||||
};
|
||||
|
||||
export function getClientToken(googleClientVerKey?: string) {
|
||||
if (!googleClientVerKey || typeof window.grecaptcha === 'undefined' || !window.grecaptcha?.ready)
|
||||
return '';
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
window.grecaptcha.ready(async () => {
|
||||
try {
|
||||
const token = await window.grecaptcha.execute(googleClientVerKey, {
|
||||
action: 'submit'
|
||||
});
|
||||
resolve(token);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
109
projects/app/src/web/support/store/user.ts
Normal file
109
projects/app/src/web/support/store/user.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
import { create } from 'zustand';
|
||||
import { devtools, persist } from 'zustand/middleware';
|
||||
import { immer } from 'zustand/middleware/immer';
|
||||
import type { UserType, UserUpdateParams } from '@/types/user';
|
||||
import { getMyModels, getModelById, putAppById } from '@/web/core/api/app';
|
||||
import { formatPrice } from '@fastgpt/common/bill/index';
|
||||
import { getTokenLogin, putUserInfo } from '@/web/support/api/user';
|
||||
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>()(
|
||||
devtools(
|
||||
persist(
|
||||
immer((set, get) => ({
|
||||
userInfo: null,
|
||||
async initUserInfo() {
|
||||
const res = await getTokenLogin();
|
||||
get().setUserInfo(res);
|
||||
return res;
|
||||
},
|
||||
setUserInfo(user: UserType | null) {
|
||||
set((state) => {
|
||||
state.userInfo = user
|
||||
? {
|
||||
...user,
|
||||
balance: formatPrice(user.balance)
|
||||
}
|
||||
: null;
|
||||
});
|
||||
},
|
||||
async updateUserInfo(user: UserUpdateParams) {
|
||||
const oldInfo = (get().userInfo ? { ...get().userInfo } : null) as UserType | null;
|
||||
set((state) => {
|
||||
if (!state.userInfo) return;
|
||||
state.userInfo = {
|
||||
...state.userInfo,
|
||||
...user
|
||||
};
|
||||
});
|
||||
try {
|
||||
await putUserInfo(user);
|
||||
} catch (error) {
|
||||
set((state) => {
|
||||
state.userInfo = oldInfo;
|
||||
});
|
||||
return Promise.reject(error);
|
||||
}
|
||||
},
|
||||
myApps: [],
|
||||
myCollectionApps: [],
|
||||
async loadMyApps(init = true) {
|
||||
if (get().myApps.length > 0 && !init) return [];
|
||||
const res = await getMyModels();
|
||||
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: 'userStore',
|
||||
partialize: (state) => ({})
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
Reference in New Issue
Block a user