diff --git a/web/src/i18n/locales/en.ts b/web/src/i18n/locales/en.ts index a9ce993..e470658 100644 --- a/web/src/i18n/locales/en.ts +++ b/web/src/i18n/locales/en.ts @@ -527,9 +527,11 @@ export const en = { 'Level': 'Level', 'Source': 'Source', 'Message': 'Message', + 'User ID': 'User ID', 'Search source': 'Search source', 'Clear': 'Clear', 'Log Details': 'Log Details', + 'Raw Log': 'Raw Log', // Backup 'Export started, check your downloads.': 'Export started, check your downloads.', diff --git a/web/src/i18n/locales/zh.ts b/web/src/i18n/locales/zh.ts index e3995b9..d6bf9fc 100644 --- a/web/src/i18n/locales/zh.ts +++ b/web/src/i18n/locales/zh.ts @@ -531,9 +531,11 @@ export const zh = { 'Level': '级别', 'Source': '来源', 'Message': '消息', + 'User ID': '用户 ID', 'Search source': '搜索来源', 'Clear': '清理', 'Log Details': '日志详情', + 'Raw Log': '原始日志', // Backup 'Export started, check your downloads.': '导出已开始,请检查您的下载。', diff --git a/web/src/pages/LogsPage.tsx b/web/src/pages/LogsPage.tsx index cd079f4..faf2ee3 100644 --- a/web/src/pages/LogsPage.tsx +++ b/web/src/pages/LogsPage.tsx @@ -1,5 +1,5 @@ import { memo, useState, useEffect, useCallback } from 'react'; -import { Table, message, Tag, Input, Select, Button, Space, Modal, DatePicker } from 'antd'; +import { Table, message, Tag, Input, Select, Button, Space, Modal, DatePicker, Descriptions, Divider, Typography } from 'antd'; import PageCard from '../components/PageCard'; import { logsApi, type LogItem, type PaginatedLogs } from '../api/logs'; import { useI18n } from '../i18n'; @@ -8,6 +8,7 @@ import { format, formatISO } from 'date-fns'; const { RangePicker } = DatePicker; const LOG_LEVELS = ['API', 'INFO', 'WARNING', 'ERROR']; +const LEVEL_COLOR_MAP: Record = { API: 'blue', INFO: 'green', WARNING: 'orange', ERROR: 'red' }; const LogsPage = memo(function LogsPage() { const [loading, setLoading] = useState(false); @@ -74,7 +75,7 @@ const LogsPage = memo(function LogsPage() { dataIndex: 'level', width: 100, render: (level: string) => { - const color = { API: 'blue', INFO: 'green', WARNING: 'orange', ERROR: 'red' }[level] || 'default'; + const color = LEVEL_COLOR_MAP[level] || 'default'; return {level}; }, }, @@ -93,9 +94,10 @@ const LogsPage = memo(function LogsPage() { + { setFilters(f => ({ ...f, @@ -109,6 +111,7 @@ const LogsPage = memo(function LogsPage() { style={{ width: 120 }} placeholder={t('Level')} allowClear + size="small" value={filters.level || undefined} onChange={level => setFilters(f => ({ ...f, level: level || '', page: 1 }))} options={LOG_LEVELS.map(l => ({ value: l, label: l }))} @@ -116,6 +119,7 @@ const LogsPage = memo(function LogsPage() { setFilters(f => ({ ...f, source, page: 1 }))} allowClear /> @@ -145,9 +149,32 @@ const LogsPage = memo(function LogsPage() { width={800} > {selectedLog && ( -
-            {JSON.stringify(selectedLog.details, null, 2)}
-          
+ + + + {format(new Date(selectedLog.timestamp), 'yyyy-MM-dd HH:mm:ss')} + + + {selectedLog.level} + + + {selectedLog.source} + + + {selectedLog.message} + + + {selectedLog.user_id ?? '-'} + + + + + {t('Raw Log')} + +
+              {JSON.stringify(selectedLog, null, 2)}
+            
+
)}