Files
bj_power/bj_power_dashboard/src/store/useStore.ts
T
SunYF a2afd2f6dc feat: 五项目业务实现并对接完成
- MES(B): 工单/BOM/备料/工序字典/PLC下发/拧紧/扫码报工/半成品/AGV/追溯逻辑,WMS与海康RCS客户端,看板Redis缓存API(概览/设备/进度/报警/趋势)+SSE
- WMS(C): JWT滑动续签、Excel导入、盘点、内部API、种子数据、独立Postgres配置
- WMS客户端(E): Go网关8891反向代理+内嵌Vue3十页
- 工位终端(D): SQLite本地缓存+模拟拧紧源+内嵌Vue3页面
- Dashboard(A): 看板数据改接MES内部缓存API,SSE实时刷新+vite代理
- 清理各项目球形磨遗留代码,新增部署手册.md
2026-08-27 19:50:57 +08:00

184 lines
6.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { create } from 'zustand';
import api, { mesApi } from '../api/client';
import type {
OverviewData, EquipmentItem, ProgressItem,
AlarmItem, TrendItem, SamplingOverview, SamplingTrendItem,
InspectionOverview, InspectionTrendItem,
DevStatus, CncDisplay, WasherPoint, CncHistoryPoint,
CncOeeItem, WasherOeeItem,
} from '../types';
// MES /api/internal/dashboard/overview 响应结构
interface MesOverviewReply {
activeOrderCount: number;
activeJobCount: number;
completedToday: number;
scrappedToday: number;
stationFaultCount: number;
}
/** MES 返回(camelCase,包在 Body.data 里)→ 看板 OverviewDatasnake_case */
function mapMesOverview(body: { data?: MesOverviewReply } | MesOverviewReply): OverviewData {
const d = (body as any)?.data ?? body;
return {
active_work_orders: d.activeOrderCount ?? 0,
completed_today: d.completedToday ?? 0,
yield_rate: d.completedToday + d.scrappedToday > 0
? Math.round((d.completedToday / (d.completedToday + d.scrappedToday)) * 1000) / 10
: 100,
equipment_util_rate: d.activeJobCount ?? 0,
active_alarms: d.stationFaultCount ?? 0,
};
}
async function fetchOverview(): Promise<OverviewData> {
try {
const r = await mesApi.get('/dashboard/overview');
return mapMesOverview(r.data);
} catch {
// 回退旧接口(保留兼容)
return api.get('/overview').then(r => r.data);
}
}
// MES 内部 API 优先,失败回退旧接口(本地兜底服务 :3001)
async function fromMes<T>(path: string, fallbackPath?: string): Promise<T | null> {
try {
const r = await mesApi.get(`/dashboard/${path}`);
return r.data as T;
} catch {
if (!fallbackPath) return null;
try {
const r = await api.get(fallbackPath);
return r.data as T;
} catch {
return null;
}
}
}
interface DashboardState {
// Page 1: Overview
overview: OverviewData | null;
equipment: EquipmentItem[];
progress: ProgressItem[];
alarms: AlarmItem[];
trends: TrendItem[];
samplingOverview: SamplingOverview | null;
samplingTrends: SamplingTrendItem[];
inspectionOverview: InspectionOverview | null;
inspectionTrends: InspectionTrendItem[];
loading: boolean;
// Page 2: Machine Monitor
devStatus: DevStatus[];
cncLatest: CncDisplay[];
washerLatest: WasherPoint[];
cncHistory: CncHistoryPoint[];
cncOee: CncOeeItem[];
washerOee: WasherOeeItem[];
monitorLoading: boolean;
fetchAll: () => Promise<void>;
refresh: () => Promise<void>;
fetchMonitor: () => Promise<void>;
refreshMonitor: () => Promise<void>;
}
export const useStore = create<DashboardState>((set) => ({
// Page 1 state
overview: null,
equipment: [],
progress: [],
alarms: [],
trends: [],
samplingOverview: null,
samplingTrends: [],
inspectionOverview: null,
inspectionTrends: [],
loading: false,
// Page 2 state
devStatus: [],
cncLatest: [],
washerLatest: [],
cncHistory: [],
cncOee: [],
washerOee: [],
monitorLoading: false,
fetchAll: async () => {
set({ loading: true });
try {
const [overview, equipment, progress, alarms, trends, cncLatest, samplingOverview, samplingTrends, inspectionOverview, inspectionTrends] =
await Promise.all([
fetchOverview(),
fromMes<EquipmentItem[]>('equipment', '/equipment-status').then(v => v ?? []),
fromMes<ProgressItem[]>('progress', '/production-progress').then(v => v ?? []),
fromMes<AlarmItem[]>('alarms', '/alarms').then(v => v ?? []),
fromMes<TrendItem[]>('trends', '/trends').then(v => v ?? []),
api.get('/cnc-latest').then(r => r.data).catch(() => []),
api.get('/sampling-overview').then(r => r.data).catch(() => null),
api.get('/sampling-trends').then(r => r.data).catch(() => []),
api.get('/inspection-overview').then(r => r.data).catch(() => null),
api.get('/inspection-trends').then(r => r.data).catch(() => []),
]);
set({ overview, equipment, progress, alarms, trends, cncLatest, samplingOverview, samplingTrends, inspectionOverview, inspectionTrends, loading: false });
} catch {
set({ loading: false });
}
},
refresh: async () => {
try {
const [overview, equipment, alarms, trends, cncLatest, samplingOverview, inspectionOverview] = await Promise.all([
fetchOverview(),
fromMes<EquipmentItem[]>('equipment', '/equipment-status'),
fromMes<AlarmItem[]>('alarms', '/alarms'),
fromMes<TrendItem[]>('trends', '/trends'),
api.get('/cnc-latest').then(r => r.data).catch(() => undefined),
api.get('/sampling-overview').then(r => r.data).catch(() => undefined),
api.get('/inspection-overview').then(r => r.data).catch(() => undefined),
]);
set((prev) => ({
overview,
...(equipment !== null ? { equipment } : {}),
...(alarms !== null ? { alarms } : {}),
...(trends !== null ? { trends } : {}),
...(cncLatest !== undefined ? { cncLatest } : {}),
...(samplingOverview !== undefined ? { samplingOverview } : {}),
...(inspectionOverview !== undefined ? { inspectionOverview } : {}),
}));
} catch { /* ignore */ }
},
fetchMonitor: async () => {
set({ monitorLoading: true });
try {
const [devStatus, cncLatest, washerLatest, cncOee, washerOee] = await Promise.all([
api.get('/device-status').then(r => r.data),
api.get('/cnc-latest').then(r => r.data),
api.get('/washer-latest').then(r => r.data),
api.get('/cnc-oee').then(r => r.data),
api.get('/washer-oee').then(r => r.data),
]);
set({ devStatus, cncLatest, washerLatest, cncOee, washerOee, monitorLoading: false });
} catch {
set({ monitorLoading: false });
}
},
refreshMonitor: async () => {
try {
const [devStatus, cncLatest, washerLatest, cncOee, washerOee] = await Promise.all([
api.get('/device-status').then(r => r.data),
api.get('/cnc-latest').then(r => r.data),
api.get('/washer-latest').then(r => r.data),
api.get('/cnc-oee').then(r => r.data),
api.get('/washer-oee').then(r => r.data),
]);
set({ devStatus, cncLatest, washerLatest, cncOee, washerOee });
} catch { /* ignore */ }
},
}));