Backup
This commit is contained in:
@@ -90,6 +90,13 @@ type TimelineSeg = {
|
||||
state: TimelineState;
|
||||
};
|
||||
|
||||
type ActiveStoppage = {
|
||||
state: "microstop" | "macrostop";
|
||||
startedAt: string;
|
||||
durationSec: number;
|
||||
theoreticalCycleTime: number;
|
||||
};
|
||||
|
||||
type UploadState = {
|
||||
status: "idle" | "parsing" | "uploading" | "success" | "error";
|
||||
message?: string;
|
||||
@@ -246,9 +253,12 @@ export default function MachineDetailClient() {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [cycles, setCycles] = useState<CycleRow[]>([]);
|
||||
const [thresholds, setThresholds] = useState<Thresholds | null>(null);
|
||||
const [activeStoppage, setActiveStoppage] = useState<ActiveStoppage | null>(null);
|
||||
const [open, setOpen] = useState<null | "events" | "deviation" | "impact">(null);
|
||||
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
||||
const [uploadState, setUploadState] = useState<UploadState>({ status: "idle" });
|
||||
const [nowMs, setNowMs] = useState(() => Date.now());
|
||||
|
||||
|
||||
const BUCKET = {
|
||||
normal: {
|
||||
@@ -308,6 +318,7 @@ export default function MachineDetailClient() {
|
||||
setEvents(json.events ?? []);
|
||||
setCycles(json.cycles ?? []);
|
||||
setThresholds(json.thresholds ?? null);
|
||||
setActiveStoppage(json.activeStoppage ?? null);
|
||||
setError(null);
|
||||
setLoading(false);
|
||||
} catch {
|
||||
@@ -325,6 +336,11 @@ export default function MachineDetailClient() {
|
||||
};
|
||||
}, [machineId, t]);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => setNowMs(Date.now()), 1000);
|
||||
return () => clearInterval(timer);
|
||||
}, []);
|
||||
|
||||
async function parseWorkOrdersFile(file: File) {
|
||||
const name = file.name.toLowerCase();
|
||||
if (name.endsWith(".csv")) {
|
||||
@@ -430,6 +446,20 @@ export default function MachineDetailClient() {
|
||||
return `${v}`;
|
||||
}
|
||||
|
||||
function formatDurationShort(totalSec?: number | null) {
|
||||
if (totalSec === null || totalSec === undefined || Number.isNaN(totalSec)) {
|
||||
return t("common.na");
|
||||
}
|
||||
const sec = Math.max(0, Math.floor(totalSec));
|
||||
const h = Math.floor(sec / 3600);
|
||||
const m = Math.floor((sec % 3600) / 60);
|
||||
const s = sec % 60;
|
||||
if (h > 0) return `${h}h ${m}m`;
|
||||
if (m > 0) return `${m}m ${s}s`;
|
||||
return `${s}s`;
|
||||
}
|
||||
|
||||
|
||||
function timeAgo(ts?: string) {
|
||||
if (!ts) return t("common.never");
|
||||
const diff = Math.floor((Date.now() - new Date(ts).getTime()) / 1000);
|
||||
@@ -815,6 +845,8 @@ export default function MachineDetailClient() {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
return { windowSec, segments: segs, start, end };
|
||||
}, [cycles, cycleTarget, thresholds]);
|
||||
|
||||
|
||||
@@ -312,6 +312,34 @@ const rawCycles = await prisma.machineCycle.findMany({
|
||||
sku: true,
|
||||
},
|
||||
});
|
||||
const latestCycle = rawCycles[0] ?? null;
|
||||
|
||||
let activeStoppage: {
|
||||
state: "microstop" | "macrostop";
|
||||
startedAt: string;
|
||||
durationSec: number;
|
||||
theoreticalCycleTime: number;
|
||||
} | null = null;
|
||||
|
||||
if (latestCycle?.ts && effectiveCycleTime && effectiveCycleTime > 0) {
|
||||
const elapsedSec = (Date.now() - latestCycle.ts.getTime()) / 1000;
|
||||
const microThresholdSec = effectiveCycleTime * microMultiplier;
|
||||
const macroThresholdSec = effectiveCycleTime * macroMultiplier;
|
||||
|
||||
if (elapsedSec >= microThresholdSec) {
|
||||
const isMacro = elapsedSec >= macroThresholdSec;
|
||||
const state = isMacro ? "macrostop" : "microstop";
|
||||
const thresholdSec = isMacro ? macroThresholdSec : microThresholdSec;
|
||||
const startedAtMs = latestCycle.ts.getTime() + thresholdSec * 1000;
|
||||
|
||||
activeStoppage = {
|
||||
state,
|
||||
startedAt: new Date(startedAtMs).toISOString(),
|
||||
durationSec: Math.max(0, Math.floor(elapsedSec - thresholdSec)),
|
||||
theoreticalCycleTime: effectiveCycleTime,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// chart-friendly: oldest -> newest + numeric timestamps
|
||||
const cycles = rawCycles
|
||||
@@ -340,14 +368,14 @@ const cycles = rawCycles
|
||||
latestHeartbeat: machine.heartbeats[0] ?? null,
|
||||
latestKpi: machine.kpiSnapshots[0] ?? null,
|
||||
effectiveCycleTime,
|
||||
|
||||
},
|
||||
thresholds: {
|
||||
stoppageMultiplier: microMultiplier,
|
||||
macroStoppageMultiplier: macroMultiplier,
|
||||
},
|
||||
activeStoppage,
|
||||
events,
|
||||
cycles
|
||||
cycles,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user