diff --git a/frontend/src/pages/admin/Achievement.tsx b/frontend/src/pages/admin/Achievement.tsx index 4d8751a..afb6d98 100644 --- a/frontend/src/pages/admin/Achievement.tsx +++ b/frontend/src/pages/admin/Achievement.tsx @@ -11,6 +11,7 @@ import React, { useState, useEffect, useCallback } from 'react'; import { adminAPI } from '@/api'; +import { formatBjTime } from '@/utils/datetime'; @@ -1012,7 +1013,7 @@ const Achievement: React.FC = () => {
- 完成时间: {new Date(ach.completed_at).toLocaleString('zh-CN')} + 完成时间: {formatBjTime(ach.completed_at)}
diff --git a/frontend/src/pages/admin/Apps.tsx b/frontend/src/pages/admin/Apps.tsx index 8b0ec40..7ad8920 100644 --- a/frontend/src/pages/admin/Apps.tsx +++ b/frontend/src/pages/admin/Apps.tsx @@ -1,6 +1,7 @@ import { useState, useEffect, useCallback } from 'react'; import { adminAPI } from '@/api'; import './Apps.css'; +import { formatBjTime } from '@/utils/datetime'; interface AIApp { id: string; @@ -779,9 +780,9 @@ function AppDetailDrawer({ app, analytics, onClose, onAction }: { {/* Timestamps */}
-
创建时间: {app.created_at ? new Date(app.created_at).toLocaleString('zh-CN') : '-'}
-
更新时间: {app.updated_at ? new Date(app.updated_at).toLocaleString('zh-CN') : '-'}
- {app.published_at &&
发布时间: {new Date(app.published_at).toLocaleString('zh-CN')}
} +
创建时间: {app.created_at ? formatBjTime(app.created_at) : '-'}
+
更新时间: {app.updated_at ? formatBjTime(app.updated_at) : '-'}
+ {app.published_at &&
发布时间: {formatBjTime(app.published_at)}
}
diff --git a/frontend/src/pages/admin/Automation.tsx b/frontend/src/pages/admin/Automation.tsx index 29a7b9c..8eaf84f 100644 --- a/frontend/src/pages/admin/Automation.tsx +++ b/frontend/src/pages/admin/Automation.tsx @@ -1,5 +1,6 @@ import React, { useState, useEffect } from 'react'; import { adminAPI } from '@/api'; +import { formatBjTime } from '@/utils/datetime'; interface AutomationTask { id: string; @@ -270,7 +271,7 @@ const Automation: React.FC = () => { // Format time const formatTime = (ts: string) => { if (!ts) return '-'; - try { return new Date(ts).toLocaleString('zh-CN'); } + try { return formatBjTime(ts); } catch { return ts; } }; diff --git a/frontend/src/pages/admin/Dashboard.tsx b/frontend/src/pages/admin/Dashboard.tsx index b805550..3f1fb98 100644 --- a/frontend/src/pages/admin/Dashboard.tsx +++ b/frontend/src/pages/admin/Dashboard.tsx @@ -1,6 +1,7 @@ import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { adminAPI } from '@/api'; +import { formatBjTime } from '@/utils/datetime'; const SVGIcon: React.FC<{ children: React.ReactNode; size?: number }> = ({ children, size = 20 }) => ( @@ -226,12 +227,7 @@ const Dashboard: React.FC = () => { fetchData(); }, []); - const formatDate = (d: string) => { - if (!d) return '-'; - const dt = new Date(d); - if (isNaN(dt.getTime())) return d.slice(0, 19) || '-'; - return dt.toLocaleDateString('zh-CN', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); - }; + const formatDate = (d: string | null) => formatBjTime(d); const formatTokens = (n: number): string => { if (n >= 100000000) return (n / 100000000).toFixed(2) + '亿'; @@ -336,7 +332,7 @@ const Dashboard: React.FC = () => { ))}
- 服务器时间: {stats.server_time ? new Date(stats.server_time).toLocaleString('zh-CN') : '-'} + 服务器时间: {stats.server_time ? formatBjTime(stats.server_time) : '-'}
diff --git a/frontend/src/pages/admin/Developer.tsx b/frontend/src/pages/admin/Developer.tsx index 412b0a1..7ee1531 100644 --- a/frontend/src/pages/admin/Developer.tsx +++ b/frontend/src/pages/admin/Developer.tsx @@ -1,5 +1,6 @@ import { useState, useEffect, useCallback } from 'react'; import './Developer.css'; +import { formatBjTime } from '@/utils/datetime'; const API_BASE = '/app/api'; @@ -216,7 +217,7 @@ export default function AdminDeveloper() { const fmtTime = (t: string | null) => { if (!t) return '-'; - try { return new Date(t).toLocaleString('zh-CN'); } catch { return t; } + try { return formatBjTime(t); } catch { return t; } }; const statusBadge = (status: string) => { diff --git a/frontend/src/pages/admin/DeveloperTools.tsx b/frontend/src/pages/admin/DeveloperTools.tsx index e1e1a1e..f1fdb2d 100644 --- a/frontend/src/pages/admin/DeveloperTools.tsx +++ b/frontend/src/pages/admin/DeveloperTools.tsx @@ -1,5 +1,6 @@ import { useState, useEffect, useCallback } from 'react'; import './Developer.css'; +import { formatBjTime } from '@/utils/datetime'; const API_BASE = '/app/api'; @@ -169,7 +170,7 @@ export default function AdminDeveloperTools() { const fmtTime = (t: string | null) => { if (!t) return '-'; - try { return new Date(t).toLocaleString('zh-CN'); } catch { return t; } + try { return formatBjTime(t); } catch { return t; } }; const statusBadge = (status: string) => { diff --git a/frontend/src/pages/admin/ImBots.tsx b/frontend/src/pages/admin/ImBots.tsx index 03b7451..3a8b293 100644 --- a/frontend/src/pages/admin/ImBots.tsx +++ b/frontend/src/pages/admin/ImBots.tsx @@ -3,6 +3,7 @@ import React, { useState, useEffect, useCallback } from 'react'; import { adminAPI, } from '@/api'; +import { formatBjTime } from '@/utils/datetime'; // Platform icons (simple SVG representations) const platformIcons: Record = { @@ -329,7 +330,7 @@ const ImBots: React.FC = () => { // Format time const formatTime = (time: string) => { if (!time) return '-'; - return new Date(time).toLocaleString('zh-CN'); + return formatBjTime(time); }; const tabs: { key: Tab; label: string; icon: string }[] = [ diff --git a/frontend/src/pages/admin/Mcp.tsx b/frontend/src/pages/admin/Mcp.tsx index 44a0df4..d79bba8 100644 --- a/frontend/src/pages/admin/Mcp.tsx +++ b/frontend/src/pages/admin/Mcp.tsx @@ -1,5 +1,6 @@ import React, { useState, useEffect, useCallback } from 'react'; import { adminAPI } from '@/api'; +import { formatBjTime } from '@/utils/datetime'; const styles: Record = { container: { padding: 24, backgroundColor: '#f5f7fa', minHeight: '100vh' }, @@ -277,7 +278,7 @@ export default function AdminMcp() { {getTransportBadge(s.transport_type)} {getStatusBadge(s.status)} {s.tools_count || '-'} - {s.last_connected_at ? new Date(s.last_connected_at).toLocaleString() : '从未'} + {s.last_connected_at ? formatBjTime(s.last_connected_at) : '从未'} {s.is_enabled ? '是' : '否'} diff --git a/frontend/src/pages/admin/PrivacySettings.tsx b/frontend/src/pages/admin/PrivacySettings.tsx index c7a39b8..fb04d45 100644 --- a/frontend/src/pages/admin/PrivacySettings.tsx +++ b/frontend/src/pages/admin/PrivacySettings.tsx @@ -3,6 +3,7 @@ import React, { useState, useEffect, useCallback } from 'react'; import { adminAPI } from '@/api'; +import { formatBjTime } from '@/utils/datetime'; @@ -464,7 +465,7 @@ export default function PrivacySettings() { - const formatDate = (d: string | null) => d ? new Date(d).toLocaleString('zh-CN') : '-'; + const formatDate = (d: string | null) => d ? formatBjTime(d) : '-'; diff --git a/frontend/src/pages/admin/Users.tsx b/frontend/src/pages/admin/Users.tsx index 34431ce..36e508f 100644 --- a/frontend/src/pages/admin/Users.tsx +++ b/frontend/src/pages/admin/Users.tsx @@ -3,6 +3,7 @@ import { adminAPI } from '@/api'; import { mockUsers, mockMembershipPlans } from '@/mock/data'; import type { User, RegisterSettings } from '@/types'; import './Users.css'; +import { formatBjTime } from '@/utils/datetime'; // ===== SVG Icons ===== const IconSearch = () => ( @@ -141,7 +142,7 @@ const UserDetailModal: React.FC = ({ user, onClose }) => {
注册时间 - {new Date(user.createdAt).toLocaleString('zh-CN')} + {formatBjTime(user.createdAt)}
diff --git a/frontend/src/pages/front/EvolutionDashboard.tsx b/frontend/src/pages/front/EvolutionDashboard.tsx index a930820..cca89b7 100644 --- a/frontend/src/pages/front/EvolutionDashboard.tsx +++ b/frontend/src/pages/front/EvolutionDashboard.tsx @@ -4,6 +4,7 @@ import type { EvolutionSkill, EvolutionEvent, EvolutionProfile, SkillTreeData, S import html2canvas from 'html2canvas'; import jsPDF from 'jspdf'; import './EvolutionDashboard.css'; +import { formatBjTime } from '@/utils/datetime'; // ==================== SVG Icons ==================== const Icon: React.FC<{ children: React.ReactNode; size?: number; className?: string }> = ({ children, size = 16, className }) => ( @@ -486,7 +487,7 @@ const TimelinePanel: React.FC<{

{event.description}

- {new Date(event.created_at).toLocaleString()} + {formatBjTime(event.created_at)}
diff --git a/frontend/src/utils/datetime.ts b/frontend/src/utils/datetime.ts new file mode 100644 index 0000000..3c53d40 --- /dev/null +++ b/frontend/src/utils/datetime.ts @@ -0,0 +1,9 @@ +// 后端按北京时间存储(无时区标记),此处显式按 Asia/Shanghai 渲染, +// 避免浏览器本地时区导致时间显示错乱。 +export function formatBjTime(t?: string | null): string { + if (!t) return '-'; + const iso = /[Z+]/.test(t) ? t : t + '+08:00'; + const d = new Date(iso); + if (isNaN(d.getTime())) return t; + return d.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai', hour12: false }); +}