= {
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 });
+}
|