chore(deploy): finalize 0309 SAE rollout updates

Sync deployment documentation to the final successful SAE state and clear pending deployment checklist items. Include backend/frontend/R hardening and diagnostics improvements required for stable production behavior.

Made-with: Cursor
This commit is contained in:
2026-03-09 22:27:11 +08:00
parent d30bf95815
commit 971e903acf
23 changed files with 810 additions and 180 deletions

View File

@@ -2,14 +2,21 @@
* 运营统计 API
*/
import { authRequest } from '@/framework/request';
import apiClient from '@/common/api/axios';
// ==================== 类型定义 ====================
export interface OverviewData {
dau: number;
mau: number;
dat: number;
exportCount: number;
apiTokenTotal: number;
topActiveUser: {
userId: string;
userName: string | null;
actionCount: number;
} | null;
moduleStats: Record<string, number>;
}
@@ -54,29 +61,29 @@ export interface UserOverview {
* 获取今日大盘数据
*/
export async function getOverview(): Promise<OverviewData> {
const res = await authRequest.get<{ success: boolean; data: OverviewData }>(
const res = await apiClient.get<{ success: boolean; data: OverviewData }>(
'/api/admin/stats/overview'
);
return res.data;
return res.data.data;
}
/**
* 获取实时流水账
*/
export async function getLiveFeed(limit = 100): Promise<ActivityLog[]> {
const res = await authRequest.get<{ success: boolean; data: ActivityLog[] }>(
const res = await apiClient.get<{ success: boolean; data: ActivityLog[] }>(
`/api/admin/stats/live-feed?limit=${limit}`
);
return res.data;
return res.data.data;
}
/**
* 获取用户360画像
*/
export async function getUserOverview(userId: string): Promise<UserOverview> {
const res = await authRequest.get<{ success: boolean; data: UserOverview }>(
const res = await apiClient.get<{ success: boolean; data: UserOverview }>(
`/api/admin/users/${userId}/overview`
);
return res.data;
return res.data.data;
}

View File

@@ -11,6 +11,8 @@ import {
UserOutlined,
BankOutlined,
ExportOutlined,
FireOutlined,
ApiOutlined,
MessageOutlined,
BookOutlined,
SearchOutlined,
@@ -23,7 +25,7 @@ import {
ReloadOutlined,
} from '@ant-design/icons';
import { getOverview, getLiveFeed } from '../api/statsApi';
import type { OverviewData, ActivityLog } from '../api/statsApi';
import type { ActivityLog } from '../api/statsApi';
// ==================== 模块图标映射 ====================
@@ -174,7 +176,7 @@ export default function StatsDashboardPage() {
{/* 核心指标卡片 */}
<Row gutter={[16, 16]} className="mb-6">
<Col xs={24} sm={8}>
<Col xs={24} sm={12} md={6}>
<Card className="shadow-sm hover:shadow-md transition-shadow">
<Statistic
title={<span className="text-gray-600"> (DAU)</span>}
@@ -185,7 +187,18 @@ export default function StatsDashboardPage() {
/>
</Card>
</Col>
<Col xs={24} sm={8}>
<Col xs={24} sm={12} md={6}>
<Card className="shadow-sm hover:shadow-md transition-shadow">
<Statistic
title={<span className="text-gray-600">30 (MAU)</span>}
value={overview?.mau ?? 0}
prefix={<UserOutlined className="text-indigo-500" />}
loading={overviewLoading}
valueStyle={{ color: '#4f46e5', fontWeight: 'bold' }}
/>
</Card>
</Col>
<Col xs={24} sm={12} md={6}>
<Card className="shadow-sm hover:shadow-md transition-shadow">
<Statistic
title={<span className="text-gray-600"> (DAT)</span>}
@@ -196,7 +209,7 @@ export default function StatsDashboardPage() {
/>
</Card>
</Col>
<Col xs={24} sm={8}>
<Col xs={24} sm={12} md={6}>
<Card className="shadow-sm hover:shadow-md transition-shadow">
<Statistic
title={<span className="text-gray-600"></span>}
@@ -209,6 +222,31 @@ export default function StatsDashboardPage() {
</Col>
</Row>
<Row gutter={[16, 16]} className="mb-6">
<Col xs={24} md={12}>
<Card className="shadow-sm hover:shadow-md transition-shadow">
<Statistic
title={<span className="text-gray-600"></span>}
value={overview?.topActiveUser?.userName || '暂无'}
prefix={<FireOutlined className="text-orange-500" />}
suffix={overview?.topActiveUser ? `${overview.topActiveUser.actionCount}` : ''}
loading={overviewLoading}
/>
</Card>
</Col>
<Col xs={24} md={12}>
<Card className="shadow-sm hover:shadow-md transition-shadow">
<Statistic
title={<span className="text-gray-600"> API Token </span>}
value={overview?.apiTokenTotal ?? 0}
prefix={<ApiOutlined className="text-cyan-500" />}
loading={overviewLoading}
valueStyle={{ color: '#0891b2', fontWeight: 'bold' }}
/>
</Card>
</Col>
</Row>
{/* 模块使用统计 */}
{overview?.moduleStats && Object.keys(overview.moduleStats).length > 0 && (
<Card