mirror of
https://github.com/labring/FastGPT.git
synced 2025-12-26 04:32:50 +00:00
fix: export log dateend
This commit is contained in:
parent
c7fb948300
commit
4efd805961
|
|
@ -57,6 +57,7 @@ curl --location --request POST 'https://{{host}}/api/admin/initv4144' \
|
|||
10. 发布渠道文档链接定位错误。
|
||||
11. Checkbox 在禁用状态时,hover 样式错误。
|
||||
12. 模型头像缺失情况下,默认 huggingface.svg 图标显示错误。
|
||||
13. 日志导出时,结束时间会多出一天。
|
||||
|
||||
## 插件
|
||||
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@
|
|||
"document/content/docs/upgrading/4-14/4141.mdx": "2025-11-19T10:15:27+08:00",
|
||||
"document/content/docs/upgrading/4-14/4142.mdx": "2025-11-18T19:27:14+08:00",
|
||||
"document/content/docs/upgrading/4-14/4143.mdx": "2025-11-26T20:52:05+08:00",
|
||||
"document/content/docs/upgrading/4-14/4144.mdx": "2025-12-10T11:41:15+08:00",
|
||||
"document/content/docs/upgrading/4-14/4144.mdx": "2025-12-09T23:33:32+08:00",
|
||||
"document/content/docs/upgrading/4-8/40.mdx": "2025-08-02T19:38:37+08:00",
|
||||
"document/content/docs/upgrading/4-8/41.mdx": "2025-08-02T19:38:37+08:00",
|
||||
"document/content/docs/upgrading/4-8/42.mdx": "2025-08-02T19:38:37+08:00",
|
||||
|
|
@ -201,4 +201,4 @@
|
|||
"document/content/docs/use-cases/external-integration/openapi.mdx": "2025-09-29T11:34:11+08:00",
|
||||
"document/content/docs/use-cases/external-integration/wecom.mdx": "2025-12-09T23:33:32+08:00",
|
||||
"document/content/docs/use-cases/index.mdx": "2025-07-24T14:23:04+08:00"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,3 +16,10 @@ export const parseI18nString = (str: I18nStringType | string = '', lang = 'en')
|
|||
// 最后回退到英文
|
||||
return str['en'] || '';
|
||||
};
|
||||
|
||||
export const formatI18nLocationToZhEn = (locale: localeType = 'zh-CN'): 'zh' | 'en' => {
|
||||
if (locale.toLocaleLowerCase().startsWith('zh')) {
|
||||
return 'zh';
|
||||
}
|
||||
return 'en';
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@ import fs from 'node:fs';
|
|||
import type { ReaderModel } from '@maxmind/geoip2-node';
|
||||
import { Reader } from '@maxmind/geoip2-node';
|
||||
import { cleanupIntervalMs, dbPath, privateOrOtherLocationName } from './constants';
|
||||
import type { I18nName, LocationName } from './type';
|
||||
import type { LocationName } from './type';
|
||||
import { extractLocationData } from './utils';
|
||||
import type { NextApiRequest } from 'next';
|
||||
import { getClientIp } from 'request-ip';
|
||||
import { addLog } from '../system/log';
|
||||
import type { localeType } from '@fastgpt/global/common/i18n/type';
|
||||
import { formatI18nLocationToZhEn } from '@fastgpt/global/common/i18n/utils';
|
||||
|
||||
let reader: ReaderModel | null = null;
|
||||
|
||||
|
|
@ -25,21 +27,23 @@ export function getGeoReader() {
|
|||
return reader;
|
||||
}
|
||||
|
||||
export function getLocationFromIp(ip?: string, locale: keyof I18nName = 'zh') {
|
||||
export function getLocationFromIp(ip?: string, locale: localeType = 'zh-CN') {
|
||||
const formatedLocale = formatI18nLocationToZhEn(locale);
|
||||
|
||||
if (!ip) {
|
||||
return privateOrOtherLocationName.country?.[locale];
|
||||
return privateOrOtherLocationName.country?.[formatedLocale];
|
||||
}
|
||||
const reader = getGeoReader();
|
||||
|
||||
let locationName = locationIpMap.get(ip);
|
||||
if (locationName) {
|
||||
return [
|
||||
locationName.country?.[locale],
|
||||
locationName.province?.[locale],
|
||||
locationName.city?.[locale]
|
||||
locationName.country?.[formatedLocale],
|
||||
locationName.province?.[formatedLocale],
|
||||
locationName.city?.[formatedLocale]
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(locale === 'zh' ? ',' : ',');
|
||||
.join(formatedLocale === 'zh' ? ',' : ',');
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -62,15 +66,15 @@ export function getLocationFromIp(ip?: string, locale: keyof I18nName = 'zh') {
|
|||
locationIpMap.set(ip, locationName);
|
||||
|
||||
return [
|
||||
locationName.country?.[locale],
|
||||
locationName.province?.[locale],
|
||||
locationName.city?.[locale]
|
||||
locationName.country?.[formatedLocale],
|
||||
locationName.province?.[formatedLocale],
|
||||
locationName.city?.[formatedLocale]
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(locale === 'zh' ? ',' : ', ');
|
||||
.join(formatedLocale === 'zh' ? ',' : ', ');
|
||||
} catch (error) {
|
||||
locationIpMap.set(ip, privateOrOtherLocationName);
|
||||
return privateOrOtherLocationName.country?.[locale];
|
||||
return privateOrOtherLocationName.country?.[formatedLocale];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@
|
|||
"expand_tool_create": "Expand MCP/Http create",
|
||||
"export_config_successful": "Configuration copied, some sensitive information automatically filtered. Please check for any remaining sensitive data.",
|
||||
"export_configs": "Export",
|
||||
"export_log_filename": "{{name}} chat logs.csv",
|
||||
"fastgpt_marketplace": "FastGPT plug-in market",
|
||||
"feedback_count": "User Feedback",
|
||||
"file_quote_link": "Files",
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@
|
|||
"expand_tool_create": "展开MCP、Http创建",
|
||||
"export_config_successful": "已复制配置,自动过滤部分敏感信息,请注意检查是否仍有敏感数据",
|
||||
"export_configs": "导出配置",
|
||||
"export_log_filename": "{{name}} 对话日志.csv",
|
||||
"fastgpt_marketplace": "FastGPT 插件市场",
|
||||
"feedback_count": "用户反馈",
|
||||
"file_quote_link": "文件链接",
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@
|
|||
"expand_tool_create": "展開 MCP、Http 創建",
|
||||
"export_config_successful": "已複製設定,自動過濾部分敏感資訊,請注意檢查是否仍有敏感資料",
|
||||
"export_configs": "匯出設定",
|
||||
"export_log_filename": "{{name}} 對話日誌.csv",
|
||||
"fastgpt_marketplace": "FastGPT 插件市場",
|
||||
"feedback_count": "使用者回饋",
|
||||
"file_quote_link": "檔案連結",
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ export type GetAppChatLogsProps = {
|
|||
sources?: ChatSourceEnum[];
|
||||
tmbIds?: string[];
|
||||
chatSearch?: string;
|
||||
locale?: keyof I18nName;
|
||||
};
|
||||
|
||||
export type GetAppChatLogsParams = PaginationProps<GetAppChatLogsProps>;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import MultipleSelect, {
|
|||
import React, { useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import DateRangePicker from '@fastgpt/web/components/common/DateRangePicker';
|
||||
import { addDays } from 'date-fns';
|
||||
import { useScrollPagination } from '@fastgpt/web/hooks/useScrollPagination';
|
||||
import { getTeamMembers } from '@/web/support/user/team/api';
|
||||
import Avatar from '@fastgpt/web/components/common/Avatar';
|
||||
|
|
@ -50,7 +49,8 @@ import dynamic from 'next/dynamic';
|
|||
import type { HeaderControlProps } from './LogChart';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import MyBox from '@fastgpt/web/components/common/MyBox';
|
||||
import type { I18nName } from '@fastgpt/service/common/geo/type';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
import { AppContext } from '../context';
|
||||
|
||||
const DetailLogsModal = dynamic(() => import('./DetailLogsModal'));
|
||||
|
||||
|
|
@ -65,10 +65,11 @@ const LogTable = ({
|
|||
showSourceSelector = true,
|
||||
px = [4, 8]
|
||||
}: HeaderControlProps) => {
|
||||
const { t, i18n } = useTranslation();
|
||||
const { t } = useTranslation();
|
||||
const { feConfigs } = useSystemStore();
|
||||
|
||||
const [detailLogsId, setDetailLogsId] = useState<string>();
|
||||
const appName = useContextSelector(AppContext, (v) => v.appDetail.name);
|
||||
|
||||
// source
|
||||
const sourceList = useMemo(
|
||||
|
|
@ -147,15 +148,14 @@ const LogTable = ({
|
|||
const headerTitle = enabledKeys.map((k) => t(AppLogKeysEnumMap[k])).join(',');
|
||||
await downloadFetch({
|
||||
url: '/api/core/app/exportChatLogs',
|
||||
filename: 'chat_logs.csv',
|
||||
filename: t('app:export_log_filename', { name: appName }),
|
||||
body: {
|
||||
appId,
|
||||
dateStart: dayjs(dateRange.from || new Date()).format(),
|
||||
dateEnd: dayjs(addDays(dateRange.to || new Date(), 1)).format(),
|
||||
dateEnd: dayjs(dateRange.to || new Date()).format(),
|
||||
sources: isSelectAllSource ? undefined : chatSources,
|
||||
tmbIds: isSelectAllTmb ? undefined : selectTmbIds,
|
||||
chatSearch,
|
||||
locale: i18n.language === 'zh-CN' ? 'zh' : 'en',
|
||||
title: `${headerTitle},${t('app:logs_keys_chatDetails')}`,
|
||||
logKeys: enabledKeys,
|
||||
sourcesMap: Object.fromEntries(
|
||||
|
|
@ -180,8 +180,7 @@ const LogTable = ({
|
|||
dateEnd: dateRange.to!,
|
||||
sources: isSelectAllSource ? undefined : chatSources,
|
||||
tmbIds: isSelectAllTmb ? undefined : selectTmbIds,
|
||||
chatSearch,
|
||||
locale: (i18n.language === 'zh-CN' ? 'zh' : 'en') as keyof I18nName
|
||||
chatSearch
|
||||
}),
|
||||
[
|
||||
appId,
|
||||
|
|
@ -191,8 +190,7 @@ const LogTable = ({
|
|||
isSelectAllSource,
|
||||
selectTmbIds,
|
||||
isSelectAllTmb,
|
||||
chatSearch,
|
||||
i18n.language
|
||||
chatSearch
|
||||
]
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import { getAppLatestVersion } from '@fastgpt/service/core/app/version/controlle
|
|||
import { VariableInputEnum } from '@fastgpt/global/core/workflow/constants';
|
||||
import { getTimezoneCodeFromStr } from '@fastgpt/global/common/time/timezone';
|
||||
import { getLocationFromIp } from '@fastgpt/service/common/geo';
|
||||
import type { I18nName } from '@fastgpt/service/common/geo/type';
|
||||
import { getLocale } from '@fastgpt/service/common/middle/i18n';
|
||||
|
||||
const formatJsonString = (data: any) => {
|
||||
if (data == null) return '';
|
||||
|
|
@ -40,7 +40,6 @@ export type ExportChatLogsBody = GetAppChatLogsProps & {
|
|||
title: string;
|
||||
sourcesMap: Record<string, { label: string }>;
|
||||
logKeys: AppLogKeysEnum[];
|
||||
locale?: keyof I18nName;
|
||||
};
|
||||
|
||||
async function handler(req: ApiRequestProps<ExportChatLogsBody, {}>, res: NextApiResponse) {
|
||||
|
|
@ -51,7 +50,6 @@ async function handler(req: ApiRequestProps<ExportChatLogsBody, {}>, res: NextAp
|
|||
sources,
|
||||
tmbIds,
|
||||
chatSearch,
|
||||
locale = 'en',
|
||||
title,
|
||||
sourcesMap,
|
||||
logKeys = []
|
||||
|
|
@ -61,6 +59,7 @@ async function handler(req: ApiRequestProps<ExportChatLogsBody, {}>, res: NextAp
|
|||
throw new Error('缺少参数');
|
||||
}
|
||||
|
||||
const locale = getLocale(req);
|
||||
const timezoneCode = getTimezoneCodeFromStr(dateStart);
|
||||
|
||||
const { teamId, tmbId, app } = await authApp({
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import type { NextApiResponse } from 'next';
|
||||
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
|
||||
import { type AppLogsListItemType } from '@/types/app';
|
||||
import { Types } from '@fastgpt/service/common/mongo';
|
||||
import { addDays } from 'date-fns';
|
||||
import type { GetAppChatLogsParams } from '@/global/core/api/appReq.d';
|
||||
import { authApp } from '@fastgpt/service/support/permission/app/auth';
|
||||
import {
|
||||
|
|
@ -19,12 +18,13 @@ import { getLocationFromIp } from '@fastgpt/service/common/geo';
|
|||
import { AppReadChatLogPerVal } from '@fastgpt/global/support/permission/app/constant';
|
||||
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
|
||||
import type { ApiRequestProps } from '@fastgpt/service/type/next';
|
||||
import { getLocale } from '@fastgpt/service/common/middle/i18n';
|
||||
|
||||
async function handler(
|
||||
req: ApiRequestProps<GetAppChatLogsParams>,
|
||||
_res: NextApiResponse
|
||||
): Promise<PaginationResponse<AppLogsListItemType>> {
|
||||
const { appId, dateStart, dateEnd, sources, tmbIds, chatSearch, locale = 'en' } = req.body;
|
||||
const { appId, dateStart, dateEnd, sources, tmbIds, chatSearch } = req.body;
|
||||
|
||||
const { pageSize = 20, offset } = parsePaginationRequest(req);
|
||||
|
||||
|
|
@ -294,7 +294,7 @@ async function handler(
|
|||
|
||||
const listWithRegion = list.map((item) => {
|
||||
const ip = item.region;
|
||||
const region = getLocationFromIp(ip, locale);
|
||||
const region = getLocationFromIp(ip, getLocale(req));
|
||||
|
||||
return {
|
||||
...item,
|
||||
|
|
|
|||
Loading…
Reference in New Issue