diff --git a/frontend/src/pages/admin/AdminProductsPage.tsx b/frontend/src/pages/admin/AdminProductsPage.tsx
index eae6ce1..6fcf5b8 100644
--- a/frontend/src/pages/admin/AdminProductsPage.tsx
+++ b/frontend/src/pages/admin/AdminProductsPage.tsx
@@ -250,7 +250,8 @@ export default function AdminProductsPage() {
return {formatDuration(h)};
})()}
-
+
+
diff --git a/frontend/src/pages/admin/AnalyticsDashboard.tsx b/frontend/src/pages/admin/AnalyticsDashboard.tsx
index 989873a..08f8c39 100644
--- a/frontend/src/pages/admin/AnalyticsDashboard.tsx
+++ b/frontend/src/pages/admin/AnalyticsDashboard.tsx
@@ -2,8 +2,8 @@
* 个人能力图谱:X 轴 = 设备身份证,单机耗时对比,支持点击柱子下钻备注弹窗(含照片)。 */
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useSearchParams } from "react-router-dom";
-import { DatePicker, Tabs, Select, Button, Empty, Modal, Timeline, Image } from "antd";
-import { Users, GitBranch, RefreshCw, Loader2, AlertCircle } from "lucide-react";
+import { DatePicker, Tabs, Select, Button, Empty, Modal, Timeline, Image, Radio } from "antd";
+import { Users, GitBranch, RefreshCw, Loader2, AlertCircle, CalendarDays } from "lucide-react";
import dayjs, { type Dayjs } from "dayjs";
import type { EChartsCoreOption } from "echarts/core";
import "dayjs/locale/zh-cn";
@@ -88,6 +88,8 @@ export default function AnalyticsDashboard() {
const [capabilityLoading, setCapabilityLoading] = useState(false);
const [flow, setFlow] = useState(null);
const [flowLoading, setFlowLoading] = useState(false);
+ // 📅 设备生产总天数口径:自然天 / 工作日
+ const [totalDaysMode, setTotalDaysMode] = useState<"natural" | "workdays">("natural");
const [error, setError] = useState(null);
// ─── 弹窗下钻:设备备注(all=true 表示流转图点击,展示全部) ──
@@ -673,10 +675,57 @@ export default function AnalyticsDashboard() {
)}
+ {/* 📅 设备生产总天数(自然天 / 工作日切换) */}
+
+
+
+ 📅 设备生产总天数
+
+ setTotalDaysMode(e.target.value)}
+ size="small"
+ optionType="button"
+ buttonStyle="solid"
+ >
+ 自然天
+ 工作日
+
+
+ {flowLoading && !flow ? (
+
+
+
+ ) : !flow || flow.devices.length === 0 ? (
+
暂无设备数据,请选择筛选条件后查询
+ ) : (
+
+
+
设备数
+
{flow.devices.length} 台
+
+
+
{totalDaysMode === "natural" ? "平均生产总天数(自然天)" : "平均生产总天数(工作日)"}
+
+ {Math.round(flow.devices.reduce((s, d) => s + (totalDaysMode === "natural" ? d.total_days : d.total_workdays), 0) / flow.devices.length)}
+ 天
+
+
+
+
最长生产周期({totalDaysMode === "natural" ? "自然天" : "工作日"})
+
+ {Math.max(...flow.devices.map(d => totalDaysMode === "natural" ? d.total_days : d.total_workdays))}
+ 天
+
+
+
+ )}
+
+
{/* 主体:两个可视化区块 */}
setActiveTab(k as "capability" | "flow")}
items={[
{
key: "capability",
diff --git a/frontend/src/services/analyticsApi.ts b/frontend/src/services/analyticsApi.ts
index 3938eab..ff0a30b 100644
--- a/frontend/src/services/analyticsApi.ts
+++ b/frontend/src/services/analyticsApi.ts
@@ -41,6 +41,8 @@ export interface FlowDevice {
spec_model: string;
lead_time: number; // 设备生命周期总时长(小时)
started_at: string; // 设备最早介入时间(T0),MM-DD HH:mm
+ total_days: number; // 设备生产总天数(自然天)
+ total_workdays: number; // 设备生产总天数(工作日)
}
// 时间区间:deviceIndex, startOffset, endOffset, taskName, duration, isMain
diff --git a/frontend/src/types/admin.ts b/frontend/src/types/admin.ts
index b41028f..223a269 100644
--- a/frontend/src/types/admin.ts
+++ b/frontend/src/types/admin.ts
@@ -24,6 +24,8 @@ export interface ProductResponse {
latest_record_assignee_id: string | null;
latest_record_assignee_name: string | null;
active_duration_hours: number | null;
+ production_days: number;
+ production_days_workdays: number;
}
/** MOM 物料选项 */