perf: logs, auth root as super admin, etc (#2615)
* chore: usePagination hook type * feat: chat log show outlinkuid or tmb avatar and name * fix: ts error for pagination * feat: auth root
This commit is contained in:
parent
91ec895fd2
commit
a1ae08f62b
@ -38,11 +38,13 @@ export const authPluginByTmbId = async ({
|
|||||||
export const authAppByTmbId = async ({
|
export const authAppByTmbId = async ({
|
||||||
tmbId,
|
tmbId,
|
||||||
appId,
|
appId,
|
||||||
per
|
per,
|
||||||
|
isRoot
|
||||||
}: {
|
}: {
|
||||||
tmbId: string;
|
tmbId: string;
|
||||||
appId: string;
|
appId: string;
|
||||||
per: PermissionValueType;
|
per: PermissionValueType;
|
||||||
|
isRoot?: boolean;
|
||||||
}): Promise<{
|
}): Promise<{
|
||||||
app: AppDetailType;
|
app: AppDetailType;
|
||||||
}> => {
|
}> => {
|
||||||
@ -55,6 +57,14 @@ export const authAppByTmbId = async ({
|
|||||||
return Promise.reject(AppErrEnum.unExist);
|
return Promise.reject(AppErrEnum.unExist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isRoot) {
|
||||||
|
return {
|
||||||
|
...app,
|
||||||
|
defaultPermission: app.defaultPermission,
|
||||||
|
permission: new AppPermission({ isOwner: true })
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (String(app.teamId) !== teamId) {
|
if (String(app.teamId) !== teamId) {
|
||||||
return Promise.reject(AppErrEnum.unAuthApp);
|
return Promise.reject(AppErrEnum.unAuthApp);
|
||||||
}
|
}
|
||||||
@ -136,7 +146,8 @@ export const authApp = async ({
|
|||||||
const { app } = await authAppByTmbId({
|
const { app } = await authAppByTmbId({
|
||||||
tmbId,
|
tmbId,
|
||||||
appId,
|
appId,
|
||||||
per
|
per,
|
||||||
|
isRoot: result.isRoot
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -78,13 +78,18 @@ export const delResourcePermission = ({
|
|||||||
|
|
||||||
/* 下面代码等迁移 */
|
/* 下面代码等迁移 */
|
||||||
/* create token */
|
/* create token */
|
||||||
export function createJWT(user: { _id?: string; team?: { teamId?: string; tmbId: string } }) {
|
export function createJWT(user: {
|
||||||
|
_id?: string;
|
||||||
|
team?: { teamId?: string; tmbId: string };
|
||||||
|
isRoot?: boolean;
|
||||||
|
}) {
|
||||||
const key = process.env.TOKEN_KEY as string;
|
const key = process.env.TOKEN_KEY as string;
|
||||||
const token = jwt.sign(
|
const token = jwt.sign(
|
||||||
{
|
{
|
||||||
userId: String(user._id),
|
userId: String(user._id),
|
||||||
teamId: String(user.team?.teamId),
|
teamId: String(user.team?.teamId),
|
||||||
tmbId: String(user.team?.tmbId),
|
tmbId: String(user.team?.tmbId),
|
||||||
|
isRoot: user.isRoot,
|
||||||
exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 7
|
exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 7
|
||||||
},
|
},
|
||||||
key
|
key
|
||||||
@ -98,6 +103,7 @@ export function authJWT(token: string) {
|
|||||||
userId: string;
|
userId: string;
|
||||||
teamId: string;
|
teamId: string;
|
||||||
tmbId: string;
|
tmbId: string;
|
||||||
|
isRoot: boolean;
|
||||||
}>((resolve, reject) => {
|
}>((resolve, reject) => {
|
||||||
const key = process.env.TOKEN_KEY as string;
|
const key = process.env.TOKEN_KEY as string;
|
||||||
|
|
||||||
@ -110,7 +116,8 @@ export function authJWT(token: string) {
|
|||||||
resolve({
|
resolve({
|
||||||
userId: decoded.userId,
|
userId: decoded.userId,
|
||||||
teamId: decoded.teamId || '',
|
teamId: decoded.teamId || '',
|
||||||
tmbId: decoded.tmbId
|
tmbId: decoded.tmbId,
|
||||||
|
isRoot: decoded.isRoot
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -183,7 +190,7 @@ export async function parseHeaderCert({
|
|||||||
|
|
||||||
const { cookie, token, rootkey, authorization } = (req.headers || {}) as ReqHeaderAuthType;
|
const { cookie, token, rootkey, authorization } = (req.headers || {}) as ReqHeaderAuthType;
|
||||||
|
|
||||||
const { uid, teamId, tmbId, appId, openApiKey, authType } = await (async () => {
|
const { uid, teamId, tmbId, appId, openApiKey, authType, isRoot } = await (async () => {
|
||||||
if (authApiKey && authorization) {
|
if (authApiKey && authorization) {
|
||||||
// apikey from authorization
|
// apikey from authorization
|
||||||
const authResponse = await parseAuthorization(authorization);
|
const authResponse = await parseAuthorization(authorization);
|
||||||
@ -205,7 +212,8 @@ export async function parseHeaderCert({
|
|||||||
tmbId: res.tmbId,
|
tmbId: res.tmbId,
|
||||||
appId: '',
|
appId: '',
|
||||||
openApiKey: '',
|
openApiKey: '',
|
||||||
authType: AuthUserTypeEnum.token
|
authType: AuthUserTypeEnum.token,
|
||||||
|
isRoot: res.isRoot
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (authRoot && rootkey) {
|
if (authRoot && rootkey) {
|
||||||
@ -217,7 +225,8 @@ export async function parseHeaderCert({
|
|||||||
tmbId: '',
|
tmbId: '',
|
||||||
appId: '',
|
appId: '',
|
||||||
openApiKey: '',
|
openApiKey: '',
|
||||||
authType: AuthUserTypeEnum.root
|
authType: AuthUserTypeEnum.root,
|
||||||
|
isRoot: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +243,8 @@ export async function parseHeaderCert({
|
|||||||
tmbId: String(tmbId),
|
tmbId: String(tmbId),
|
||||||
appId,
|
appId,
|
||||||
authType,
|
authType,
|
||||||
apikey: openApiKey
|
apikey: openApiKey,
|
||||||
|
isRoot: !!isRoot
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,11 +24,13 @@ import { ParentIdType } from '@fastgpt/global/common/parentFolder/type';
|
|||||||
export const authDatasetByTmbId = async ({
|
export const authDatasetByTmbId = async ({
|
||||||
tmbId,
|
tmbId,
|
||||||
datasetId,
|
datasetId,
|
||||||
per
|
per,
|
||||||
|
isRoot = false
|
||||||
}: {
|
}: {
|
||||||
tmbId: string;
|
tmbId: string;
|
||||||
datasetId: string;
|
datasetId: string;
|
||||||
per: PermissionValueType;
|
per: PermissionValueType;
|
||||||
|
isRoot?: boolean;
|
||||||
}): Promise<{
|
}): Promise<{
|
||||||
dataset: DatasetSchemaType & {
|
dataset: DatasetSchemaType & {
|
||||||
permission: DatasetPermission;
|
permission: DatasetPermission;
|
||||||
@ -44,6 +46,15 @@ export const authDatasetByTmbId = async ({
|
|||||||
return Promise.reject(DatasetErrEnum.unExist);
|
return Promise.reject(DatasetErrEnum.unExist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isRoot) {
|
||||||
|
return {
|
||||||
|
...dataset,
|
||||||
|
permission: new DatasetPermission({
|
||||||
|
isOwner: true
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (String(dataset.teamId) !== teamId) {
|
if (String(dataset.teamId) !== teamId) {
|
||||||
return Promise.reject(DatasetErrEnum.unAuthDataset);
|
return Promise.reject(DatasetErrEnum.unAuthDataset);
|
||||||
}
|
}
|
||||||
@ -131,7 +142,8 @@ export const authDataset = async ({
|
|||||||
const { dataset } = await authDatasetByTmbId({
|
const { dataset } = await authDatasetByTmbId({
|
||||||
tmbId,
|
tmbId,
|
||||||
datasetId,
|
datasetId,
|
||||||
per
|
per,
|
||||||
|
isRoot: result.isRoot
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -144,15 +156,17 @@ export const authDataset = async ({
|
|||||||
export async function authDatasetCollection({
|
export async function authDatasetCollection({
|
||||||
collectionId,
|
collectionId,
|
||||||
per = NullPermission,
|
per = NullPermission,
|
||||||
|
isRoot = false,
|
||||||
...props
|
...props
|
||||||
}: AuthModeType & {
|
}: AuthModeType & {
|
||||||
collectionId: string;
|
collectionId: string;
|
||||||
|
isRoot?: boolean;
|
||||||
}): Promise<
|
}): Promise<
|
||||||
AuthResponseType<DatasetPermission> & {
|
AuthResponseType<DatasetPermission> & {
|
||||||
collection: CollectionWithDatasetType;
|
collection: CollectionWithDatasetType;
|
||||||
}
|
}
|
||||||
> {
|
> {
|
||||||
const { teamId, tmbId } = await parseHeaderCert(props);
|
const { teamId, tmbId, isRoot: isRootFromHeader } = await parseHeaderCert(props);
|
||||||
const collection = await getCollectionWithDataset(collectionId);
|
const collection = await getCollectionWithDataset(collectionId);
|
||||||
|
|
||||||
if (!collection) {
|
if (!collection) {
|
||||||
@ -162,7 +176,8 @@ export async function authDatasetCollection({
|
|||||||
const { dataset } = await authDatasetByTmbId({
|
const { dataset } = await authDatasetByTmbId({
|
||||||
tmbId,
|
tmbId,
|
||||||
datasetId: collection.datasetId._id,
|
datasetId: collection.datasetId._id,
|
||||||
per
|
per,
|
||||||
|
isRoot: isRootFromHeader || isRoot
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -184,7 +199,7 @@ export async function authDatasetFile({
|
|||||||
file: DatasetFileSchema;
|
file: DatasetFileSchema;
|
||||||
}
|
}
|
||||||
> {
|
> {
|
||||||
const { teamId, tmbId } = await parseHeaderCert(props);
|
const { teamId, tmbId, isRoot } = await parseHeaderCert(props);
|
||||||
|
|
||||||
const [file, collection] = await Promise.all([
|
const [file, collection] = await Promise.all([
|
||||||
getFileById({ bucketName: BucketNameEnum.dataset, fileId }),
|
getFileById({ bucketName: BucketNameEnum.dataset, fileId }),
|
||||||
@ -206,7 +221,8 @@ export async function authDatasetFile({
|
|||||||
const { permission } = await authDatasetCollection({
|
const { permission } = await authDatasetCollection({
|
||||||
...props,
|
...props,
|
||||||
collectionId: collection._id,
|
collectionId: collection._id,
|
||||||
per
|
per,
|
||||||
|
isRoot
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { getTmbInfoByTmbId } from '../../user/team/controller';
|
|||||||
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
|
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
|
||||||
import { AuthModeType, AuthResponseType } from '../type';
|
import { AuthModeType, AuthResponseType } from '../type';
|
||||||
import { NullPermission } from '@fastgpt/global/support/permission/constant';
|
import { NullPermission } from '@fastgpt/global/support/permission/constant';
|
||||||
|
import { TeamPermission } from '@fastgpt/global/support/permission/user/controller';
|
||||||
|
|
||||||
/* auth user role */
|
/* auth user role */
|
||||||
export async function authUserPer(props: AuthModeType): Promise<
|
export async function authUserPer(props: AuthModeType): Promise<
|
||||||
@ -14,6 +15,15 @@ export async function authUserPer(props: AuthModeType): Promise<
|
|||||||
const result = await parseHeaderCert(props);
|
const result = await parseHeaderCert(props);
|
||||||
const tmb = await getTmbInfoByTmbId({ tmbId: result.tmbId });
|
const tmb = await getTmbInfoByTmbId({ tmbId: result.tmbId });
|
||||||
|
|
||||||
|
if (result.isRoot) {
|
||||||
|
return {
|
||||||
|
...result,
|
||||||
|
permission: new TeamPermission({
|
||||||
|
isOwner: true
|
||||||
|
}),
|
||||||
|
tmb
|
||||||
|
};
|
||||||
|
}
|
||||||
if (!tmb.permission.checkPer(props.per ?? NullPermission)) {
|
if (!tmb.permission.checkPer(props.per ?? NullPermission)) {
|
||||||
return Promise.reject(TeamErrEnum.unAuthTeam);
|
return Promise.reject(TeamErrEnum.unAuthTeam);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ type PagingData<T> = {
|
|||||||
total?: number;
|
total?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function usePagination<T = any>({
|
export function usePagination<ResT = any>({
|
||||||
api,
|
api,
|
||||||
pageSize = 10,
|
pageSize = 10,
|
||||||
params = {},
|
params = {},
|
||||||
@ -25,7 +25,7 @@ export function usePagination<T = any>({
|
|||||||
onChange,
|
onChange,
|
||||||
elementRef
|
elementRef
|
||||||
}: {
|
}: {
|
||||||
api: (data: any) => any;
|
api: (data: any) => Promise<PagingData<ResT>>;
|
||||||
pageSize?: number;
|
pageSize?: number;
|
||||||
params?: Record<string, any>;
|
params?: Record<string, any>;
|
||||||
defaultRequest?: boolean;
|
defaultRequest?: boolean;
|
||||||
@ -41,7 +41,7 @@ export function usePagination<T = any>({
|
|||||||
const [total, setTotal] = useState(0);
|
const [total, setTotal] = useState(0);
|
||||||
const totalRef = useRef(total);
|
const totalRef = useRef(total);
|
||||||
totalRef.current = total;
|
totalRef.current = total;
|
||||||
const [data, setData] = useState<T[]>([]);
|
const [data, setData] = useState<ResT[]>([]);
|
||||||
const dataLengthRef = useRef(data.length);
|
const dataLengthRef = useRef(data.length);
|
||||||
dataLengthRef.current = data.length;
|
dataLengthRef.current = data.length;
|
||||||
const maxPage = useMemo(() => Math.ceil(total / pageSize) || 1, [pageSize, total]);
|
const maxPage = useMemo(() => Math.ceil(total / pageSize) || 1, [pageSize, total]);
|
||||||
@ -49,7 +49,7 @@ export function usePagination<T = any>({
|
|||||||
const { mutate, isLoading } = useMutation({
|
const { mutate, isLoading } = useMutation({
|
||||||
mutationFn: async (num: number = pageNum) => {
|
mutationFn: async (num: number = pageNum) => {
|
||||||
try {
|
try {
|
||||||
const res: PagingData<T> = await api({
|
const res: PagingData<ResT> = await api({
|
||||||
pageNum: num,
|
pageNum: num,
|
||||||
pageSize,
|
pageSize,
|
||||||
...params
|
...params
|
||||||
@ -107,7 +107,7 @@ export function usePagination<T = any>({
|
|||||||
onKeyDown={(e) => {
|
onKeyDown={(e) => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const val = +e.target.value;
|
const val = +e.target.value;
|
||||||
if (val && e.keyCode === 13) {
|
if (val && e.key === 'Enter') {
|
||||||
if (val === pageNum) return;
|
if (val === pageNum) return;
|
||||||
if (val >= maxPage) {
|
if (val >= maxPage) {
|
||||||
mutate(maxPage);
|
mutate(maxPage);
|
||||||
|
|||||||
@ -72,6 +72,7 @@
|
|||||||
"logs_empty": "还没有日志噢~",
|
"logs_empty": "还没有日志噢~",
|
||||||
"logs_message_total": "消息总数",
|
"logs_message_total": "消息总数",
|
||||||
"logs_title": "标题",
|
"logs_title": "标题",
|
||||||
|
"logs_chat_user": "使用者",
|
||||||
"mark_count": "标注答案数量",
|
"mark_count": "标注答案数量",
|
||||||
"module": {
|
"module": {
|
||||||
"Confirm Sync": "将会更新至最新的模板配置,不存在模板中的字段将会被删除(包括所有自定义字段),建议您先复制一份节点,再更新原来节点的版本。",
|
"Confirm Sync": "将会更新至最新的模板配置,不存在模板中的字段将会被删除(包括所有自定义字段),建议您先复制一份节点,再更新原来节点的版本。",
|
||||||
|
|||||||
@ -20,7 +20,6 @@ import { getPromotionInitData, getPromotionRecords } from '@/web/support/activit
|
|||||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||||
|
|
||||||
import { useCopyData } from '@/web/common/hooks/useCopyData';
|
import { useCopyData } from '@/web/common/hooks/useCopyData';
|
||||||
import type { PromotionRecordType } from '@/global/support/api/userRes.d';
|
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { usePagination } from '@fastgpt/web/hooks/usePagination';
|
import { usePagination } from '@fastgpt/web/hooks/usePagination';
|
||||||
import { useLoading } from '@fastgpt/web/hooks/useLoading';
|
import { useLoading } from '@fastgpt/web/hooks/useLoading';
|
||||||
@ -40,7 +39,7 @@ const Promotion = () => {
|
|||||||
total,
|
total,
|
||||||
pageSize,
|
pageSize,
|
||||||
Pagination
|
Pagination
|
||||||
} = usePagination<PromotionRecordType>({
|
} = usePagination({
|
||||||
api: getPromotionRecords,
|
api: getPromotionRecords,
|
||||||
pageSize: 20
|
pageSize: 20
|
||||||
});
|
});
|
||||||
|
|||||||
@ -62,7 +62,7 @@ const BillTable = () => {
|
|||||||
Pagination,
|
Pagination,
|
||||||
getData,
|
getData,
|
||||||
total
|
total
|
||||||
} = usePagination<BillSchemaType>({
|
} = usePagination({
|
||||||
api: getBills,
|
api: getBills,
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
params: {
|
params: {
|
||||||
|
|||||||
@ -31,7 +31,7 @@ const InvoiceTable = () => {
|
|||||||
Pagination,
|
Pagination,
|
||||||
getData,
|
getData,
|
||||||
total
|
total
|
||||||
} = usePagination<InvoiceSchemaType>({
|
} = usePagination({
|
||||||
api: getInvoiceRecords,
|
api: getInvoiceRecords,
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
defaultRequest: false
|
defaultRequest: false
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import { readFromSecondary } from '@fastgpt/service/common/mongo/utils';
|
|||||||
|
|
||||||
async function handler(
|
async function handler(
|
||||||
req: NextApiRequest,
|
req: NextApiRequest,
|
||||||
res: NextApiResponse
|
_res: NextApiResponse
|
||||||
): Promise<PagingData<AppLogsListItemType>> {
|
): Promise<PagingData<AppLogsListItemType>> {
|
||||||
const {
|
const {
|
||||||
pageNum = 1,
|
pageNum = 1,
|
||||||
@ -131,7 +131,9 @@ async function handler(
|
|||||||
userGoodFeedbackCount: 1,
|
userGoodFeedbackCount: 1,
|
||||||
userBadFeedbackCount: 1,
|
userBadFeedbackCount: 1,
|
||||||
customFeedbacksCount: 1,
|
customFeedbacksCount: 1,
|
||||||
markCount: 1
|
markCount: 1,
|
||||||
|
outLinkUid: 1,
|
||||||
|
tmbId: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import { connectToDatabase } from '@/service/mongo';
|
|||||||
import { getUserDetail } from '@fastgpt/service/support/user/controller';
|
import { getUserDetail } from '@fastgpt/service/support/user/controller';
|
||||||
import type { PostLoginProps } from '@fastgpt/global/support/user/api.d';
|
import type { PostLoginProps } from '@fastgpt/global/support/user/api.d';
|
||||||
import { UserStatusEnum } from '@fastgpt/global/support/user/constant';
|
import { UserStatusEnum } from '@fastgpt/global/support/user/constant';
|
||||||
import { checkTeamAiPointsAndLock } from '@/service/events/utils';
|
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
try {
|
try {
|
||||||
@ -50,7 +49,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
lastLoginTmbId: userDetail.team.tmbId
|
lastLoginTmbId: userDetail.team.tmbId
|
||||||
});
|
});
|
||||||
|
|
||||||
const token = createJWT(userDetail);
|
const token = createJWT({
|
||||||
|
...userDetail,
|
||||||
|
isRoot: username === 'root'
|
||||||
|
});
|
||||||
|
|
||||||
setCookie(res, token);
|
setCookie(res, token);
|
||||||
|
|
||||||
jsonRes(res, {
|
jsonRes(res, {
|
||||||
|
|||||||
@ -13,13 +13,12 @@ import {
|
|||||||
ModalBody,
|
ModalBody,
|
||||||
HStack
|
HStack
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
|
import Avatar from '@fastgpt/web/components/common/Avatar';
|
||||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
import { getAppChatLogs } from '@/web/core/app/api';
|
import { getAppChatLogs } from '@/web/core/app/api';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { ChatSourceMap } from '@fastgpt/global/core/chat/constants';
|
import { ChatSourceMap } from '@fastgpt/global/core/chat/constants';
|
||||||
import { AppLogsListItemType } from '@/types/app';
|
|
||||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
|
||||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||||
import { addDays } from 'date-fns';
|
import { addDays } from 'date-fns';
|
||||||
import { usePagination } from '@fastgpt/web/hooks/usePagination';
|
import { usePagination } from '@fastgpt/web/hooks/usePagination';
|
||||||
@ -32,6 +31,8 @@ import { cardStyles } from '../constants';
|
|||||||
|
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
||||||
|
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||||
|
import Tag from '@fastgpt/web/components/common/Tag';
|
||||||
const DetailLogsModal = dynamic(() => import('./DetailLogsModal'));
|
const DetailLogsModal = dynamic(() => import('./DetailLogsModal'));
|
||||||
|
|
||||||
const Logs = () => {
|
const Logs = () => {
|
||||||
@ -40,6 +41,7 @@ const Logs = () => {
|
|||||||
const { isPc } = useSystem();
|
const { isPc } = useSystem();
|
||||||
|
|
||||||
const appId = useContextSelector(AppContext, (v) => v.appId);
|
const appId = useContextSelector(AppContext, (v) => v.appId);
|
||||||
|
const { teamMembers } = useUserStore();
|
||||||
|
|
||||||
const [dateRange, setDateRange] = useState<DateRangeType>({
|
const [dateRange, setDateRange] = useState<DateRangeType>({
|
||||||
from: addDays(new Date(), -7),
|
from: addDays(new Date(), -7),
|
||||||
@ -58,7 +60,7 @@ const Logs = () => {
|
|||||||
Pagination,
|
Pagination,
|
||||||
getData,
|
getData,
|
||||||
pageNum
|
pageNum
|
||||||
} = usePagination<AppLogsListItemType>({
|
} = usePagination({
|
||||||
api: getAppChatLogs,
|
api: getAppChatLogs,
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
params: {
|
params: {
|
||||||
@ -107,11 +109,12 @@ const Logs = () => {
|
|||||||
<Thead>
|
<Thead>
|
||||||
<Tr>
|
<Tr>
|
||||||
<Th>{t('common:core.app.logs.Source And Time')}</Th>
|
<Th>{t('common:core.app.logs.Source And Time')}</Th>
|
||||||
<Th>{appT('logs_title')}</Th>
|
<Th>{t('app:logs_chat_user')}</Th>
|
||||||
<Th>{appT('logs_message_total')}</Th>
|
<Th>{t('app:logs_title')}</Th>
|
||||||
<Th>{appT('feedback_count')}</Th>
|
<Th>{t('app:logs_message_total')}</Th>
|
||||||
|
<Th>{t('app:feedback_count')}</Th>
|
||||||
<Th>{t('common:core.app.feedback.Custom feedback')}</Th>
|
<Th>{t('common:core.app.feedback.Custom feedback')}</Th>
|
||||||
<Th>{appT('mark_count')}</Th>
|
<Th>{t('app:mark_count')}</Th>
|
||||||
</Tr>
|
</Tr>
|
||||||
</Thead>
|
</Thead>
|
||||||
<Tbody fontSize={'xs'}>
|
<Tbody fontSize={'xs'}>
|
||||||
@ -127,6 +130,23 @@ const Logs = () => {
|
|||||||
<Box>{t(ChatSourceMap[item.source]?.name || ('UnKnow' as any))}</Box>
|
<Box>{t(ChatSourceMap[item.source]?.name || ('UnKnow' as any))}</Box>
|
||||||
<Box color={'myGray.500'}>{dayjs(item.time).format('YYYY/MM/DD HH:mm')}</Box>
|
<Box color={'myGray.500'}>{dayjs(item.time).format('YYYY/MM/DD HH:mm')}</Box>
|
||||||
</Td>
|
</Td>
|
||||||
|
<Td>
|
||||||
|
<Box>
|
||||||
|
{item.source === 'share' ? (
|
||||||
|
item.outLinkUid
|
||||||
|
) : (
|
||||||
|
<Tag key={item._id} type={'fill'} colorSchema="white">
|
||||||
|
<Avatar
|
||||||
|
src={teamMembers.find((v) => v.tmbId === item.tmbId)?.avatar}
|
||||||
|
w="1.25rem"
|
||||||
|
/>
|
||||||
|
<Box fontSize={'sm'} ml={1}>
|
||||||
|
{teamMembers.find((v) => v.tmbId === item.tmbId)?.memberName}
|
||||||
|
</Box>
|
||||||
|
</Tag>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Td>
|
||||||
<Td className="textEllipsis" maxW={'250px'}>
|
<Td className="textEllipsis" maxW={'250px'}>
|
||||||
{item.title}
|
{item.title}
|
||||||
</Td>
|
</Td>
|
||||||
|
|||||||
@ -1,22 +1,11 @@
|
|||||||
import React, { useState, useRef, useMemo, useCallback } from 'react';
|
import React, { useState, useRef, useMemo } from 'react';
|
||||||
import {
|
import { Box, Card, IconButton, Flex, Button, useTheme } from '@chakra-ui/react';
|
||||||
Box,
|
|
||||||
Card,
|
|
||||||
IconButton,
|
|
||||||
Flex,
|
|
||||||
Grid,
|
|
||||||
Button,
|
|
||||||
useTheme,
|
|
||||||
useDisclosure,
|
|
||||||
HStack
|
|
||||||
} from '@chakra-ui/react';
|
|
||||||
import {
|
import {
|
||||||
getDatasetDataList,
|
getDatasetDataList,
|
||||||
delOneDatasetDataById,
|
delOneDatasetDataById,
|
||||||
getDatasetCollectionById,
|
getDatasetCollectionById,
|
||||||
putDatasetDataById
|
putDatasetDataById
|
||||||
} from '@/web/core/dataset/api';
|
} from '@/web/core/dataset/api';
|
||||||
import { DeleteIcon } from '@chakra-ui/icons';
|
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||||
@ -27,16 +16,8 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
|
|||||||
import MyInput from '@/components/MyInput';
|
import MyInput from '@/components/MyInput';
|
||||||
import InputDataModal from '../components/InputDataModal';
|
import InputDataModal from '../components/InputDataModal';
|
||||||
import RawSourceBox from '@/components/core/dataset/RawSourceBox';
|
import RawSourceBox from '@/components/core/dataset/RawSourceBox';
|
||||||
import type { DatasetDataListItemType } from '@/global/core/dataset/type.d';
|
|
||||||
import { TabEnum } from '..';
|
|
||||||
import { DatasetCollectionTypeMap, TrainingTypeMap } from '@fastgpt/global/core/dataset/constants';
|
|
||||||
import { formatTime2YMDHM } from '@fastgpt/global/common/string/time';
|
|
||||||
import { formatFileSize } from '@fastgpt/global/common/file/tools';
|
|
||||||
import { getCollectionSourceAndOpen } from '@/web/core/dataset/hooks/readCollectionSource';
|
|
||||||
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
|
|
||||||
import { usePagination } from '@fastgpt/web/hooks/usePagination';
|
import { usePagination } from '@fastgpt/web/hooks/usePagination';
|
||||||
import { getCollectionSourceData } from '@fastgpt/global/core/dataset/collection/utils';
|
import { getCollectionSourceData } from '@fastgpt/global/core/dataset/collection/utils';
|
||||||
import { useI18n } from '@/web/context/I18n';
|
|
||||||
import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
|
import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
|
||||||
import { DatasetPageContext } from '@/web/core/dataset/context/datasetPageContext';
|
import { DatasetPageContext } from '@/web/core/dataset/context/datasetPageContext';
|
||||||
import { useContextSelector } from 'use-context-selector';
|
import { useContextSelector } from 'use-context-selector';
|
||||||
@ -78,7 +59,7 @@ const DataCard = () => {
|
|||||||
pageNum,
|
pageNum,
|
||||||
pageSize,
|
pageSize,
|
||||||
isLoading: isRequesting
|
isLoading: isRequesting
|
||||||
} = usePagination<DatasetDataListItemType>({
|
} = usePagination({
|
||||||
api: getDatasetDataList,
|
api: getDatasetDataList,
|
||||||
pageSize: 24,
|
pageSize: 24,
|
||||||
defaultRequest: false,
|
defaultRequest: false,
|
||||||
@ -125,7 +106,7 @@ const DataCard = () => {
|
|||||||
|
|
||||||
const canWrite = useMemo(() => datasetDetail.permission.hasWritePer, [datasetDetail]);
|
const canWrite = useMemo(() => datasetDetail.permission.hasWritePer, [datasetDetail]);
|
||||||
|
|
||||||
const { run: onUpdate, loading } = useRequest2(putDatasetDataById, {
|
const { loading } = useRequest2(putDatasetDataById, {
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
getData(pageNum);
|
getData(pageNum);
|
||||||
}
|
}
|
||||||
|
|||||||
2
projects/app/src/types/app.d.ts
vendored
2
projects/app/src/types/app.d.ts
vendored
@ -43,4 +43,6 @@ export type AppLogsListItemType = {
|
|||||||
userBadFeedbackCount: number;
|
userBadFeedbackCount: number;
|
||||||
customFeedbacksCount: number;
|
customFeedbacksCount: number;
|
||||||
markCount: number;
|
markCount: number;
|
||||||
|
outLinkUid?: string;
|
||||||
|
tmbId: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import type { GetAppChatLogsParams } from '@/global/core/api/appReq.d';
|
|||||||
import { AppUpdateParams, AppChangeOwnerBody } from '@/global/core/app/api';
|
import { AppUpdateParams, AppChangeOwnerBody } from '@/global/core/app/api';
|
||||||
import type { CreateAppBody } from '@/pages/api/core/app/create';
|
import type { CreateAppBody } from '@/pages/api/core/app/create';
|
||||||
import type { ListAppBody } from '@/pages/api/core/app/list';
|
import type { ListAppBody } from '@/pages/api/core/app/list';
|
||||||
|
import { AppLogsListItemType } from '@/types/app';
|
||||||
|
import { PagingData } from '@/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取模型列表
|
* 获取模型列表
|
||||||
@ -36,7 +38,8 @@ export const putAppById = (id: string, data: AppUpdateParams) =>
|
|||||||
PUT(`/core/app/update?appId=${id}`, data);
|
PUT(`/core/app/update?appId=${id}`, data);
|
||||||
|
|
||||||
// =================== chat logs
|
// =================== chat logs
|
||||||
export const getAppChatLogs = (data: GetAppChatLogsParams) => POST(`/core/app/getChatLogs`, data);
|
export const getAppChatLogs = (data: GetAppChatLogsParams) =>
|
||||||
|
POST<PagingData<AppLogsListItemType>>(`/core/app/getChatLogs`, data);
|
||||||
|
|
||||||
export const resumeInheritPer = (appId: string) =>
|
export const resumeInheritPer = (appId: string) =>
|
||||||
GET(`/core/app/resumeInheritPermission`, { appId });
|
GET(`/core/app/resumeInheritPermission`, { appId });
|
||||||
|
|||||||
@ -34,7 +34,10 @@ import type { CreateDatasetParams, InsertOneDatasetDataProps } from '@/global/co
|
|||||||
import type { DatasetCollectionItemType } from '@fastgpt/global/core/dataset/type';
|
import type { DatasetCollectionItemType } from '@fastgpt/global/core/dataset/type';
|
||||||
import { DatasetCollectionSyncResultEnum } from '@fastgpt/global/core/dataset/constants';
|
import { DatasetCollectionSyncResultEnum } from '@fastgpt/global/core/dataset/constants';
|
||||||
import type { DatasetDataItemType } from '@fastgpt/global/core/dataset/type';
|
import type { DatasetDataItemType } from '@fastgpt/global/core/dataset/type';
|
||||||
import type { DatasetCollectionsListItemType } from '@/global/core/dataset/type.d';
|
import type {
|
||||||
|
DatasetCollectionsListItemType,
|
||||||
|
DatasetDataListItemType
|
||||||
|
} from '@/global/core/dataset/type.d';
|
||||||
import { PagingData } from '@/types';
|
import { PagingData } from '@/types';
|
||||||
import type { getDatasetTrainingQueueResponse } from '@/pages/api/core/dataset/training/getDatasetTrainingQueue';
|
import type { getDatasetTrainingQueueResponse } from '@/pages/api/core/dataset/training/getDatasetTrainingQueue';
|
||||||
import type { rebuildEmbeddingBody } from '@/pages/api/core/dataset/training/rebuildEmbedding';
|
import type { rebuildEmbeddingBody } from '@/pages/api/core/dataset/training/rebuildEmbedding';
|
||||||
@ -153,7 +156,7 @@ export const getScrollCollectionList = (data: GetScrollCollectionsProps) =>
|
|||||||
/* =============================== data ==================================== */
|
/* =============================== data ==================================== */
|
||||||
/* get dataset list */
|
/* get dataset list */
|
||||||
export const getDatasetDataList = (data: GetDatasetDataListProps) =>
|
export const getDatasetDataList = (data: GetDatasetDataListProps) =>
|
||||||
POST(`/core/dataset/data/list`, data);
|
POST<PagingData<DatasetDataListItemType>>(`/core/dataset/data/list`, data);
|
||||||
|
|
||||||
export const getDatasetDataItemById = (id: string) =>
|
export const getDatasetDataItemById = (id: string) =>
|
||||||
GET<DatasetDataItemType>(`/core/dataset/data/detail`, { id });
|
GET<DatasetDataItemType>(`/core/dataset/data/detail`, { id });
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { GET, POST, PUT } from '@/web/common/api/request';
|
import { GET, POST, PUT } from '@/web/common/api/request';
|
||||||
import type { PromotionRecordType } from '@/global/support/api/userRes.d';
|
import type { PromotionRecordType } from '@/global/support/api/userRes.d';
|
||||||
import type { RequestPaging } from '@/types';
|
import { PagingData, type RequestPaging } from '@/types';
|
||||||
|
|
||||||
/* get promotion init data */
|
/* get promotion init data */
|
||||||
export const getPromotionInitData = () =>
|
export const getPromotionInitData = () =>
|
||||||
@ -11,4 +11,4 @@ export const getPromotionInitData = () =>
|
|||||||
|
|
||||||
/* promotion records */
|
/* promotion records */
|
||||||
export const getPromotionRecords = (data: RequestPaging) =>
|
export const getPromotionRecords = (data: RequestPaging) =>
|
||||||
POST<PromotionRecordType>(`/proApi/support/activity/promotion/getPromotions`, data);
|
POST<PagingData<PromotionRecordType>>(`/proApi/support/activity/promotion/getPromotions`, data);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { RequestPaging } from '@/types';
|
import { PagingData, RequestPaging } from '@/types';
|
||||||
import { GET, POST } from '@/web/common/api/request';
|
import { GET, POST } from '@/web/common/api/request';
|
||||||
import { CreateBillProps, CreateBillResponse } from '@fastgpt/global/support/wallet/bill/api';
|
import { CreateBillProps, CreateBillResponse } from '@fastgpt/global/support/wallet/bill/api';
|
||||||
import { BillTypeEnum } from '@fastgpt/global/support/wallet/bill/constants';
|
import { BillTypeEnum } from '@fastgpt/global/support/wallet/bill/constants';
|
||||||
@ -8,7 +8,7 @@ export const getBills = (
|
|||||||
data: RequestPaging & {
|
data: RequestPaging & {
|
||||||
type?: BillTypeEnum;
|
type?: BillTypeEnum;
|
||||||
}
|
}
|
||||||
) => POST<BillSchemaType[]>(`/proApi/support/wallet/bill/list`, data);
|
) => POST<PagingData<BillSchemaType>>(`/proApi/support/wallet/bill/list`, data);
|
||||||
|
|
||||||
export const getWxPayQRCode = (data: CreateBillProps) =>
|
export const getWxPayQRCode = (data: CreateBillProps) =>
|
||||||
POST<CreateBillResponse>(`/proApi/support/wallet/bill/create`, data);
|
POST<CreateBillResponse>(`/proApi/support/wallet/bill/create`, data);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { RequestPaging } from '@/types';
|
import { PagingData, RequestPaging } from '@/types';
|
||||||
import { GET, POST } from '@/web/common/api/request';
|
import { GET, POST } from '@/web/common/api/request';
|
||||||
import { BillTypeEnum } from '@fastgpt/global/support/wallet/bill/constants';
|
import { BillTypeEnum } from '@fastgpt/global/support/wallet/bill/constants';
|
||||||
import { InvoiceType } from '@fastgpt/global/support/wallet/bill/type';
|
import { InvoiceType } from '@fastgpt/global/support/wallet/bill/type';
|
||||||
@ -17,4 +17,4 @@ export const submitInvoice = (data: InvoiceType) =>
|
|||||||
POST(`/proApi/support/wallet/bill/invoice/submit`, data);
|
POST(`/proApi/support/wallet/bill/invoice/submit`, data);
|
||||||
|
|
||||||
export const getInvoiceRecords = (data: RequestPaging) =>
|
export const getInvoiceRecords = (data: RequestPaging) =>
|
||||||
POST<InvoiceSchemaType[]>(`/proApi/support/wallet/bill/invoice/records`, data);
|
POST<PagingData<InvoiceSchemaType>>(`/proApi/support/wallet/bill/invoice/records`, data);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user